changeset 26858:0adb232f93b9

Implement axes and text "fontsmoothing" property (bug #55833). * NEWS: Announce new property. * base-text-renderer.h (base_text_renderer::set_anti_aliasing): New pure virtual method * ft-text-renderer.[h,cc] (text_renderer::m_antialias): New bool data member. (ft_text_renderer::set_anti_aliasing): Implement base_text_renderer::set_anti_aliasing. (is_opaque): New function to determine if a pixel is opaque. (ft_text_renderer::process_charater): Render glyph monochrome or antialiased depending on m_antialias. * text-renderer.[h,cc] (text_renderer::set_anti_aliasing): New method. * graphics.in.h (axes::properties::fontsmoothing): Add "u" and corresponding updater. (text::properties::fontsmoothing,text::properties::update_fontsmoothing): New property and corresponding updater. * grpahics.cc (text::properties::update_font): Update the text_renderer anti-aliasing. * grpahics.cc (opengl_renderer::set_font): Update the text-renderer anti-aliasing. * genpropdoc: Document "fontsmoothnig" property.
author Pantxo Diribarne <pantxo.diribarne@gmail.com>
date Tue, 05 Mar 2019 13:51:16 +0100
parents 65c036b78040
children 7c9a681c4474
files NEWS doc/interpreter/genpropdoc.m libinterp/corefcn/base-text-renderer.h libinterp/corefcn/ft-text-renderer.cc libinterp/corefcn/gl-render.cc libinterp/corefcn/graphics.cc libinterp/corefcn/graphics.in.h libinterp/corefcn/text-renderer.cc libinterp/corefcn/text-renderer.h
diffstat 9 files changed, 60 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Wed Mar 06 09:51:21 2019 -0800
+++ b/NEWS	Tue Mar 05 13:51:16 2019 +0100
@@ -14,6 +14,11 @@
   (for example, the Y-axis of an axes object with `"ycolor" = "none"`)
   without hiding the entire primitive `"visibility" = "off"`.
 
+- A new property `"FontSmoothing"` has been added to text and axes
+  objects that controls whether anti-aliasing is used during the
+  rendering of characters.  The default is "on" which produces smooth,
+  more visually appealing text. 
+
 - The appearance of patterned lines `"LineStyle" = ":"|"--"|"-."` has
   been improved for small widths (`"LineWidth"` less than 1.5 pixels)
   which is a common scenario.
--- a/doc/interpreter/genpropdoc.m	Wed Mar 06 09:51:21 2019 -0800
+++ b/doc/interpreter/genpropdoc.m	Tue Mar 05 13:51:16 2019 +0100
@@ -696,12 +696,12 @@
         s.doc = doc_fontsize;
         s.valid = "scalar";
 
+      case "fontsmoothing"
+        s.doc = "Control whether any text associated with __objname__ is anti-aliased.";
+
       case "fontunits"
         s.doc = doc_fontunits;
 
-      case "fontsmoothing"
-        s.doc = doc_unused;
-
       case "fontweight"
         s.doc = doc_fontweight;
 
@@ -1082,6 +1082,9 @@
         s.doc = doc_fontname;
         s.valid = valid_string;
 
+      case "fontsmoothing"
+        s.doc = "Control whether anti-aliasing is used when rendering text.";
+
       case "fontsize"
         s.doc = doc_fontsize;
         s.valid = "scalar";
--- a/libinterp/corefcn/base-text-renderer.h	Wed Mar 06 09:51:21 2019 -0800
+++ b/libinterp/corefcn/base-text-renderer.h	Tue Mar 05 13:51:16 2019 +0100
@@ -52,6 +52,9 @@
 
     virtual ~base_text_renderer (void) = default;
 
+    virtual void
+    set_anti_aliasing (bool val) = 0;
+
     virtual Matrix
     get_extent (text_element *elt, double rotation) = 0;
 
--- a/libinterp/corefcn/ft-text-renderer.cc	Wed Mar 06 09:51:21 2019 -0800
+++ b/libinterp/corefcn/ft-text-renderer.cc	Tue Mar 05 13:51:16 2019 +0100
@@ -369,7 +369,7 @@
         xoffset (0), line_yoffset (0), yoffset (0), mode (MODE_BBOX),
         color (dim_vector (1, 3), 0), m_do_strlist (false), m_strlist (),
         line_xoffset (0), m_ymin (0), m_ymax (0), m_deltax (0),
-        m_max_fontsize (0)
+        m_max_fontsize (0), m_antialias (true)
     { }
 
     // No copying!
@@ -413,6 +413,8 @@
     Matrix get_extent (const std::string& txt, double rotation,
                        const caseless_str& interpreter);
 
+    void set_anti_aliasing (bool val) { m_antialias = val; };
+
     void set_font (const std::string& name, const std::string& weight,
                    const std::string& angle, double size);
 
@@ -537,6 +539,9 @@
 
     // Used for computing the distance between lines.
     double m_max_fontsize;
+    
+    // Anti-aliasing.
+    bool m_antialias;
 
   };
 
@@ -703,7 +708,17 @@
         break;
       }
   }
-
+  bool is_opaque (const FT_GlyphSlot &glyph, const int x, const int y)
+  {
+    // Borrowed from https://stackoverflow.com/questions/14800827/
+    //    indexing-pixels-in-a-monochrome-freetype-glyph-buffer
+    int pitch = std::abs (glyph->bitmap.pitch);
+    unsigned char *row = &glyph->bitmap.buffer[pitch * y];
+    char cvalue = row[x >> 3];
+    
+    return ((cvalue & (128 >> (x & 7))) != 0);
+  }
+  
   FT_UInt
   ft_text_renderer::process_character (FT_ULong code, FT_UInt previous)
   {
@@ -745,7 +760,9 @@
             switch (mode)
               {
               case MODE_RENDER:
-                if (FT_Render_Glyph (face->glyph, FT_RENDER_MODE_NORMAL))
+                if (FT_Render_Glyph (face->glyph, (m_antialias
+                                                   ? FT_RENDER_MODE_NORMAL
+                                                   : FT_RENDER_MODE_MONO)))
                   {
                     glyph_index = 0;
                     warn_glyph_render (code);
@@ -777,7 +794,11 @@
                     for (int r = 0; static_cast<unsigned int> (r) < bitmap.rows; r++)
                       for (int c = 0; static_cast<unsigned int> (c) < bitmap.width; c++)
                         {
-                          unsigned char pix = bitmap.buffer[r*bitmap.width+c];
+                          unsigned char pix
+                            = (m_antialias
+                               ? bitmap.buffer[r*bitmap.width+c]
+                               : (is_opaque (face->glyph, c, r) ? 255 : 0));
+                          
                           if (x0+c < 0 || x0+c >= pixels.dim2 ()
                               || y0-r < 0 || y0-r >= pixels.dim3 ())
                             {
--- a/libinterp/corefcn/gl-render.cc	Wed Mar 06 09:51:21 2019 -0800
+++ b/libinterp/corefcn/gl-render.cc	Tue Mar 05 13:51:16 2019 +0100
@@ -4008,6 +4008,8 @@
   void
   opengl_renderer::set_font (const base_properties& props)
   {
+    bool do_anti_alias = props.get ("fontsmoothing").string_value () == "on";
+    txt_renderer.set_anti_aliasing (do_anti_alias);
     txt_renderer.set_font (props.get ("fontname").string_value (),
                            props.get ("fontweight").string_value (),
                            props.get ("fontangle").string_value (),
--- a/libinterp/corefcn/graphics.cc	Wed Mar 06 09:51:21 2019 -0800
+++ b/libinterp/corefcn/graphics.cc	Tue Mar 05 13:51:16 2019 +0100
@@ -9182,6 +9182,8 @@
                          get ("fontangle").string_value (),
                          get ("__fontsize_points__").double_value () * dpr);
 
+  txt_renderer.set_anti_aliasing (is_fontsmoothing ());
+
   Matrix c = get_color_rgb ();
   if (! c.isempty ())
     txt_renderer.set_color (c);
@@ -9474,7 +9476,7 @@
 
   // check coplanarity for 3D-faces with more than 3 corners
   int fcmax = idx.rows ();
-  if (fcmax > 3 && vert.columns () > 2 && 
+  if (fcmax > 3 && vert.columns () > 2 &&
       ! (facecolor_is ("none") && edgecolor_is ("none")))
     {
       for (octave_idx_type jj = 0; jj < idx.columns (); jj++)
--- a/libinterp/corefcn/graphics.in.h	Wed Mar 06 09:51:21 2019 -0800
+++ b/libinterp/corefcn/graphics.in.h	Tue Mar 05 13:51:16 2019 +0100
@@ -3630,8 +3630,8 @@
       radio_property fontangle u , "{normal}|italic"
       string_property fontname u , OCTAVE_DEFAULT_FONTNAME
       double_property fontsize u , 10
+      bool_property fontsmoothing u , "on"
       radio_property fontunits SU , "{points}|inches|centimeters|normalized|pixels"
-      bool_property fontsmoothing , "on"
       radio_property fontweight u , "{normal}|bold"
       double_property gridalpha m , 0.15
       radio_property gridalphamode , "{auto}|manual"
@@ -3968,6 +3968,10 @@
       update_font ("fontsize");
       sync_positions ();
     }
+    void update_fontsmoothing (void)
+    {
+      update_font ("fontsmoothing");
+    }
     void update_fontangle (void)
     {
       update_font ("fontangle");
@@ -4347,6 +4351,7 @@
       radio_property fontangle u , "{normal}|italic|oblique"
       string_property fontname u , OCTAVE_DEFAULT_FONTNAME
       double_property fontsize u , 10
+      bool_property fontsmoothing u , "on"
       radio_property fontunits SU , "inches|centimeters|normalized|{points}|pixels"
       radio_property fontweight u , "{normal}|bold"
       radio_property horizontalalignment mu , "{left}|center|right"
@@ -4435,6 +4440,7 @@
     void update_rotation (void) { update_text_extent (); }
     void update_fontname (void) { update_font (); update_text_extent (); }
     void update_fontsize (void) { update_font (); update_text_extent (); }
+    void update_fontsmoothing (void) { update_font (); update_text_extent (); }
 
     void update_color (void)
     {
--- a/libinterp/corefcn/text-renderer.cc	Wed Mar 06 09:51:21 2019 -0800
+++ b/libinterp/corefcn/text-renderer.cc	Tue Mar 05 13:51:16 2019 +0100
@@ -87,6 +87,13 @@
   }
 
   void
+  text_renderer::set_anti_aliasing (bool val)
+  {
+    if (ok ())
+      rep->set_anti_aliasing (val);
+  }
+
+  void
   text_renderer::set_font (const std::string& name, const std::string& weight,
                            const std::string& angle, double size)
   {
--- a/libinterp/corefcn/text-renderer.h	Wed Mar 06 09:51:21 2019 -0800
+++ b/libinterp/corefcn/text-renderer.h	Tue Mar 05 13:51:16 2019 +0100
@@ -62,6 +62,8 @@
     Matrix get_extent (const std::string& txt, double rotation = 0.0,
                        const caseless_str& interpreter = "tex");
 
+    void set_anti_aliasing (bool val);
+    
     void set_font (const std::string& name, const std::string& weight,
                    const std::string& angle, double size);