changeset 20622:caa5dabc7913

Let the freetype renderer return a list of parsed substrings (bug #31468) * txt-eng-ft.h (ft_render::ft_string): new class based on ft_font, that stores substrings position and font data. * txt-eng-ft.h (ft_render::text_to_strlist): new method that calls text_to_pixels and returns a list of parsed ft_string objects. * txt-eng-ft.h (ft_render::strlist): new private attribute. A list of ft_string objects. * txt-eng-ft.h (ft_render::line_xoffset): new private attribute. * txt-eng-ft.h (ft_render::line_xoffset): new private attribute. * txt-eng-ft.h (ft_render::text_to_pixels): add a boolean argument "handle_rotation" that defaults to true. * txt-eng-ft.c (ft_render::text_to_pixels): don't rotate the bounding box when handle_rotation if false * txt-eng-ft.c (ft_render::render): clear strlist before rendering * txt-eng-ft.c (ft_render::visit (text_element_string)): feed strlist with a new ft_string for each substring * txt-eng-ft.c (ft_render::visit (text_element_symbol& e)): feed strlist with a substring containing the symbol code * txt-eng-ft.c (ft_render::push_new_line): store line_xoffset
author Pantxo Diribarne <pantxo.diribarne@gmail.com>
date Mon, 12 Oct 2015 22:14:25 +0200
parents b92f8e148936
children 2be59ab36110
files libinterp/corefcn/txt-eng-ft.cc libinterp/corefcn/txt-eng-ft.h
diffstat 2 files changed, 141 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/txt-eng-ft.cc	Wed Oct 14 10:35:53 2015 -0700
+++ b/libinterp/corefcn/txt-eng-ft.cc	Mon Oct 12 22:14:25 2015 +0200
@@ -366,7 +366,7 @@
         line_bbox.pop_front ();
         Matrix new_bbox = line_bbox.front ();
 
-        xoffset = compute_line_xoffset (new_bbox);
+        xoffset = line_xoffset = compute_line_xoffset (new_bbox);
         line_yoffset += (old_bbox(1) - (new_bbox(1) + new_bbox(3)));
         yoffset = 0;
       }
@@ -637,10 +637,14 @@
       std::string str = e.string_value ();
       size_t n = str.length ();
       size_t curr = 0;
+      size_t idx = 0;
       mbstate_t ps;
       memset (&ps, 0, sizeof (ps));  // Initialize state to 0.
       wchar_t wc;
 
+      ft_string fs (str, font.get_angle (), font.get_weight (), 
+                    font.get_name (), font.get_size (), xoffset, yoffset);
+
       while (n > 0)
         {
           size_t r = gnulib::mbrtowc (&wc, str.data () + curr, n, &ps);
@@ -652,10 +656,32 @@
               n -= r;
               curr += r;
 
+              if (wc == L'\n')
+                {
+                  // Finish previous string in srtlist before processing 
+                  // the newline character
+                  fs.set_y (line_yoffset + yoffset);
+                  fs.set_color (color);
+                  std::string s = str.substr (idx, curr - idx - 1);
+                  if (! s.empty ())
+                    {
+                      fs.set_string (s);
+                      strlist.push_back (fs);
+                    }
+                }
+
               glyph_index = process_character (wc, previous);
 
               if (wc == L'\n')
-                previous = 0;
+                {
+                  previous = 0;
+                  // Start a new string in strlist
+                  idx = curr;
+                  fs = ft_string (str.substr (idx), font.get_angle (), 
+                                  font.get_weight (), font.get_name (), 
+                                  font.get_size (), line_xoffset, yoffset);
+                  
+                }
               else
                 previous = glyph_index;
             }
@@ -668,6 +694,12 @@
               break;
             }
         }
+      if (! fs.get_string ().empty ())
+        {
+          fs.set_y (line_yoffset + yoffset);
+          fs.set_color (color);
+          strlist.push_back (fs);
+        }
     }
 }
 
@@ -805,11 +837,24 @@
 ft_render::visit (text_element_symbol& e)
 {
   uint32_t code = e.get_symbol_code ();
+ 
+  ft_string fs (std::string ("-"), font.get_angle (), font.get_weight (), 
+                font.get_name (), font.get_size (), xoffset, yoffset);
 
   if (code != text_element_symbol::invalid_code && font.is_valid ())
-    process_character (code);
+    {
+      process_character (code);
+      fs.set_code (code);
+    }
   else if (font.is_valid ())
     ::warning ("ignoring unknown symbol: %d", e.get_symbol ());
+
+  if (fs.get_code ())
+    {
+      fs.set_y (line_yoffset + yoffset);
+      fs.set_color (color);
+      strlist.push_back (fs);
+   }
 }
 
 void
@@ -857,6 +902,9 @@
   box = bbox;
 
   set_mode (MODE_RENDER);
+  // Clear the list of parsed strings
+  strlist.clear ();
+
   if (pixels.numel () > 0)
     {
       elt->accept (*this);
@@ -976,7 +1024,8 @@
 ft_render::text_to_pixels (const std::string& txt,
                            uint8NDArray& pixels_, Matrix& box,
                            int _halign, int valign, double rotation,
-                           const caseless_str& interpreter)
+                           const caseless_str& interpreter, 
+                           bool handle_rotation)
 {
   int rot_mode = rotation_to_mode (rotation);
 
@@ -1007,23 +1056,24 @@
     case 4: box(1) = -box(3)-box(1); break;
     }
 
-  switch (rot_mode)
-    {
-    case ROTATION_90:
-      std::swap (box(0), box(1));
-      std::swap (box(2), box(3));
-      box(0) = -box(0)-box(2);
-      break;
-    case ROTATION_180:
-      box(0) = -box(0)-box(2);
-      box(1) = -box(1)-box(3);
-      break;
-    case ROTATION_270:
-      std::swap (box(0), box(1));
-      std::swap (box(2), box(3));
-      box(1) = -box(1)-box(3);
-      break;
-    }
+  if (handle_rotation)
+    switch (rot_mode)
+      {
+      case ROTATION_90:
+        std::swap (box(0), box(1));
+        std::swap (box(2), box(3));
+        box(0) = -box(0)-box(2);
+        break;
+      case ROTATION_180:
+        box(0) = -box(0)-box(2);
+        box(1) = -box(1)-box(3);
+        break;
+      case ROTATION_270:
+        std::swap (box(0), box(1));
+        std::swap (box(2), box(3));
+        box(1) = -box(1)-box(3);
+        break;
+      }
 }
 
 ft_render::ft_font::ft_font (const ft_font& ft)
--- a/libinterp/corefcn/txt-eng-ft.h	Wed Oct 14 10:35:53 2015 -0700
+++ b/libinterp/corefcn/txt-eng-ft.h	Mon Oct 12 22:14:25 2015 +0200
@@ -55,6 +55,7 @@
   };
 
 public:
+  
   ft_render (void);
 
   ~ft_render (void);
@@ -102,7 +103,8 @@
   void text_to_pixels (const std::string& txt,
                        uint8NDArray& pixels_, Matrix& bbox,
                        int halign, int valign, double rotation,
-                       const caseless_str& interpreter = "tex");
+                       const caseless_str& interpreter = "tex",
+                       bool handle_rotation = true);
 
 private:
   int rotation_to_mode (double rotation) const;
@@ -165,6 +167,66 @@
 
   FT_UInt process_character (FT_ULong code, FT_UInt previous = 0);
 
+public:
+  // A class to store informations on substrings after parsing. 
+  class ft_string : public ft_font
+  {
+  public:
+    ft_string (const std::string s, const std::string fontang,
+              const std::string fontwgt, const std::string nm,
+              const double fontsz, const double x0, const double y0)
+      : ft_font (nm, fontwgt, fontang, fontsz),
+        string(s), x(x0), y(y0), z(0.0), code(0),
+        color(Matrix (1,3,0.0)){ }
+  
+    void set_string (const std::string str) { string = str; }
+
+    std::string get_string (void) const { return string; }
+
+    void set_x (const double x0) { x = x0; }
+
+    double get_x (void) const { return x; }
+
+    void set_y (const double y0) { y = y0; }
+
+    double get_y (void) const { return y; }
+
+    void set_z (const double z0) { z = z0; }
+
+    double get_z (void) const { return z; }
+
+    void set_code (const uint32_t c) { code = c; }
+
+    uint32_t get_code (void) const { return code; }
+
+    void set_color (const uint8NDArray c) 
+    { 
+      color(0) = static_cast<double> (c(0)) / 255; 
+      color(1) = static_cast<double> (c(1)) / 255;
+      color(2) = static_cast<double> (c(2)) / 255;
+    }
+
+    Matrix get_color (void) const { return color; }
+  
+  private:
+    std::string  string;
+    double x, y, z;
+    uint32_t code;
+    Matrix color;
+  };
+
+ void text_to_strlist (const std::string& txt,
+                        std::list<ft_string>& lst, Matrix& box,
+                        int ha, int va, double rot,
+                        const caseless_str& interp = "tex")  
+  {
+    uint8NDArray pixels_;
+    // First run text_to_pixels which will also build the string list 
+    text_to_pixels (txt, pixels_, box, ha, va, rot, interp, false);
+    
+    lst = strlist;
+  }
+
 private:
   // The current font used by the renderer.
   ft_font font;
@@ -203,6 +265,13 @@
 
   // The base color of the rendered text.
   uint8NDArray color;
+
+  // A list of parsed strings to be used for printing.
+  std::list<ft_string> strlist;
+
+  // The X offset of the baseline for the current line.
+  int line_xoffset;
+
 };
 
 #endif // HAVE_FREETYPE