# HG changeset patch # User Pantxo Diribarne # Date 1444680865 -7200 # Node ID caa5dabc7913795248a321a91b6dafb154d9e522 # Parent b92f8e148936ed488849508555101b2ef8de29d3 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 diff -r b92f8e148936 -r caa5dabc7913 libinterp/corefcn/txt-eng-ft.cc --- 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) diff -r b92f8e148936 -r caa5dabc7913 libinterp/corefcn/txt-eng-ft.h --- 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 (c(0)) / 255; + color(1) = static_cast (c(1)) / 255; + color(2) = static_cast (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& 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 strlist; + + // The X offset of the baseline for the current line. + int line_xoffset; + }; #endif // HAVE_FREETYPE