diff libinterp/corefcn/txt-eng-ft.cc @ 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 25caa0deaabb
children 5b7643257978
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)