[vte/wip/sixels: 78/111] terminal: Pass const uint32_t string to sixel parser without conversion




commit f7562ecb5facb1f27177b1348cc333c2d03e32c7
Author: Hans Petter Jansson <hpj cl no>
Date:   Sat Aug 8 20:42:49 2020 +0200

    terminal: Pass const uint32_t string to sixel parser without conversion
    
    This saves converting back to UTF-8 and also a (bogus) strlen() on
    large amounts of data.
    
    Also remove unnecessary delegation to seq_load_sixel() and clean up
    comments a little.

 src/vteinternal.hh |   1 -
 src/vteseq.cc      | 172 +++++++++++++++++++++++++++--------------------------
 2 files changed, 87 insertions(+), 86 deletions(-)
---
diff --git a/src/vteinternal.hh b/src/vteinternal.hh
index e865e870..97596173 100644
--- a/src/vteinternal.hh
+++ b/src/vteinternal.hh
@@ -1596,7 +1596,6 @@ public:
                                    vte::grid::row_t end_row,
                                    vte::grid::column_t end_col);
 
-        void seq_load_sixel(char const* p);
         void subscribe_accessible_events();
         void select_text(vte::grid::column_t start_col,
                          vte::grid::row_t start_row,
diff --git a/src/vteseq.cc b/src/vteseq.cc
index f59fd26a..c31f7d64 100644
--- a/src/vteseq.cc
+++ b/src/vteseq.cc
@@ -3078,86 +3078,6 @@ Terminal::DECIC(vte::parser::Sequence const& seq)
          */
 }
 
-void
-Terminal::seq_load_sixel(char const* dcs)
-{
-       unsigned char *pixels = NULL;
-       auto fg = get_color(VTE_DEFAULT_FG);
-       auto bg = get_color(VTE_DEFAULT_BG);
-       int nfg = (fg->red >> 8) | ((fg->green >> 8) << 8) | ((fg->blue >> 8) << 16);
-       int nbg = (bg->red >> 8) | ((bg->green >> 8) << 8) | ((bg->blue >> 8) << 16);
-       glong left, top, width, height;
-       glong pixelwidth, pixelheight;
-       glong i;
-       cairo_surface_t *image_surface, *surface;
-       cairo_t *cr;
-
-       /* Parse images */
-       if (sixel_parser_init(&m_sixel_state, nfg, nbg, m_sixel_use_private_register) < 0) {
-               sixel_parser_deinit(&m_sixel_state);
-               return;
-       }
-       if (sixel_parser_parse(&m_sixel_state, (unsigned char *)dcs, strlen(dcs)) < 0) {
-               sixel_parser_deinit(&m_sixel_state);
-               return;
-       }
-       pixels = (unsigned char *)g_malloc(m_sixel_state.image.width * m_sixel_state.image.height * 4);
-       if (! pixels) {
-               sixel_parser_deinit(&m_sixel_state);
-               return;
-       }
-       if (sixel_parser_finalize(&m_sixel_state, pixels) < 0) {
-               sixel_parser_deinit(&m_sixel_state);
-               return;
-       }
-       sixel_parser_deinit(&m_sixel_state);
-
-       if (m_sixel_display_mode)
-               home_cursor();
-
-       /* Append new image to VteRing */
-       left = m_screen->cursor.col;
-       top = m_screen->cursor.row;
-       width = (m_sixel_state.image.width + m_cell_width - 1) / m_cell_width;
-       height = (m_sixel_state.image.height + m_cell_height - 1) / m_cell_height;
-       pixelwidth = m_sixel_state.image.width;
-       pixelheight = m_sixel_state.image.height;
-
-       /* create image surface (in-memory, device-independant) */
-       image_surface = cairo_image_surface_create_for_data (pixels, CAIRO_FORMAT_ARGB32, pixelwidth, 
pixelheight, pixelwidth * 4);
-       g_assert (image_surface);
-
-       /* create device-dependant surface compatible with m_widget */
-       surface = gdk_window_create_similar_surface (gtk_widget_get_window (m_widget), 
CAIRO_CONTENT_COLOR_ALPHA, pixelwidth, pixelheight);
-       g_assert (surface);
-
-       /* copy image surface to a device-compatible surface */
-       cr = cairo_create (surface);
-       cairo_set_source_surface (cr, image_surface, 0, 0);
-       cairo_paint (cr);
-       cairo_destroy (cr);
-       cairo_surface_destroy (image_surface);
-       free (pixels);
-
-       /* create image object */
-       m_screen->row_data->append_image (surface, pixelwidth, pixelheight, left, top, m_cell_width, 
m_cell_height);
-
-       /* Erase characters on the image */
-       for (i = 0; i < height; ++i) {
-               erase_characters(width, true);
-               if (i == height - 1) {
-                       if (m_sixel_scrolls_right)
-                               move_cursor_forward(width);
-                       else
-                               cursor_down(true);
-               } else {
-                       cursor_down(true);
-               }
-       }
-       if (m_sixel_display_mode)
-               home_cursor();
-}
-
 void
 Terminal::DECINVM(vte::parser::Sequence const& seq)
 {
@@ -4431,15 +4351,97 @@ Terminal::DECSIXEL(vte::parser::Sequence const& seq)
          *
          * References: VT330
          */
+
         if (!m_sixel_enabled)
                 return;
 
-        auto buf = seq.string_utf8();
-        char *dcs = (char *) buf.c_str();
-        if (!dcs)
-                return;
+       unsigned char *pixels = NULL;
+       auto fg = get_color(VTE_DEFAULT_FG);
+       auto bg = get_color(VTE_DEFAULT_BG);
+       int nfg = (fg->red >> 8) | ((fg->green >> 8) << 8) | ((fg->blue >> 8) << 16);
+       int nbg = (bg->red >> 8) | ((bg->green >> 8) << 8) | ((bg->blue >> 8) << 16);
+       glong left, top, width, height;
+       glong pixelwidth, pixelheight;
+       glong i;
+       cairo_surface_t *image_surface, *surface;
+       cairo_t *cr;
+
+        /* This is unfortunate, but it avoids copying or measuring potentially
+         * megabytes of data */
+        const vte_seq_string_t *arg_str = &((*((vte::parser::Sequence &) seq).seq_ptr())->arg_str);
 
-        seq_load_sixel(dcs);
+       /* Parse image */
+
+       if (sixel_parser_init(&m_sixel_state, nfg, nbg, m_sixel_use_private_register) < 0) {
+               sixel_parser_deinit(&m_sixel_state);
+               return;
+       }
+       if (sixel_parser_feed(&m_sixel_state, arg_str->buf, arg_str->len) < 0) {
+               sixel_parser_deinit(&m_sixel_state);
+               return;
+       }
+       pixels = (unsigned char *)g_malloc(m_sixel_state.image.width * m_sixel_state.image.height * 4);
+       if (!pixels) {
+               sixel_parser_deinit(&m_sixel_state);
+               return;
+       }
+       if (sixel_parser_finalize(&m_sixel_state, pixels) < 0) {
+               sixel_parser_deinit(&m_sixel_state);
+               return;
+       }
+       sixel_parser_deinit(&m_sixel_state);
+
+       if (m_sixel_display_mode)
+               home_cursor();
+
+       /* Calculate geometry */
+
+       left = m_screen->cursor.col;
+       top = m_screen->cursor.row;
+       width = (m_sixel_state.image.width + m_cell_width - 1) / m_cell_width;
+       height = (m_sixel_state.image.height + m_cell_height - 1) / m_cell_height;
+       pixelwidth = m_sixel_state.image.width;
+       pixelheight = m_sixel_state.image.height;
+
+       /* Convert to device-compatible surface for m_widget */
+
+       image_surface = cairo_image_surface_create_for_data (pixels, CAIRO_FORMAT_ARGB32, pixelwidth, 
pixelheight, pixelwidth * 4);
+
+        /* FIXME-hpj: Handle out-of-memory gracefully */
+       g_assert (image_surface);
+
+       surface = gdk_window_create_similar_surface (gtk_widget_get_window (m_widget), 
CAIRO_CONTENT_COLOR_ALPHA, pixelwidth, pixelheight);
+
+        /* FIXME-hpj: Handle out-of-memory gracefully */
+       g_assert (surface);
+
+       cr = cairo_create (surface);
+       cairo_set_source_surface (cr, image_surface, 0, 0);
+       cairo_paint (cr);
+       cairo_destroy (cr);
+       cairo_surface_destroy (image_surface);
+       free (pixels);
+
+       /* Append image to Ring */
+
+       m_screen->row_data->append_image (surface, pixelwidth, pixelheight, left, top, m_cell_width, 
m_cell_height);
+
+       /* Erase characters under the image */
+
+       for (i = 0; i < height; ++i) {
+               erase_characters(width, true);
+               if (i == height - 1) {
+                       if (m_sixel_scrolls_right)
+                               move_cursor_forward(width);
+                       else
+                               cursor_down(true);
+               } else {
+                       cursor_down(true);
+               }
+       }
+
+       if (m_sixel_display_mode)
+               home_cursor();
 }
 
 void


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]