[vte/wip/sixels: 28/82] image: Remove freeze/thaw and merging code, improve conformance



commit fc7ca3dfcf7f7a425064085fec96b1d1aa99420c
Author: Hans Petter Jansson <hpj cl no>
Date:   Wed Jun 3 21:28:01 2020 +0200

    image: Remove freeze/thaw and merging code, improve conformance

 src/image.cc | 234 ++---------------------------------------------------------
 src/image.hh |  64 ++++++++--------
 src/ring.cc  |  71 +-----------------
 src/vte.cc   |  75 +------------------
 4 files changed, 44 insertions(+), 400 deletions(-)
---
diff --git a/src/image.cc b/src/image.cc
index 08cf7354..18ebc7d4 100644
--- a/src/image.cc
+++ b/src/image.cc
@@ -27,252 +27,30 @@ namespace vte {
 
 namespace image {
 
-Image::Image(cairo_surface_t *surface,
-             int pixelwidth, int pixelheight,
-             int col, int row,
-             int w, int h,
-             _VteStream *stream)
-{
-        m_pixelwidth = pixelwidth;
-        m_pixelheight = pixelheight;
-        m_left = col;
-        m_top = row;
-        m_width = w;
-        m_height = h;
-        m_surface = surface;
-        m_stream = stream;
-
-        g_object_ref(m_stream);
-}
-
-Image::~Image()
-{
-        if(m_surface)
-                cairo_surface_destroy(m_surface);
-        g_object_unref(m_stream);
-}
-
-long
-Image::get_left() const
-{
-        return (long)m_left;
-}
-
-long
-Image::get_top() const
-{
-        return (long)m_top;
-}
-
-long
-Image::get_bottom() const
-{
-        return (long)(m_top + m_height - 1);
-}
-
-unsigned long
-Image::get_stream_position() const
-{
-        return m_position;
-}
-
-/* Indicate whether the image is serialized to the stream */
-bool
-Image::is_frozen() const
-{
-        return (m_surface == NULL);
-}
-
 /* Test whether this image contains given image */
 bool
-Image::contains(const Image *other) const
-{
-        assert(other != nullptr);
-
-        return other->m_left >= m_left &&
-               other->m_top >= m_top &&
-               other->m_left + other->m_width <= m_left + m_width &&
-               other->m_top + other->m_height <= m_top + m_height;
-}
-
-size_t
-Image::resource_size() const
-{
-        size_t result_size;
-
-        if (is_frozen()) {
-                /* If frozen, return the size sent to VteBoa. */
-                result_size = m_nwrite;
-        } else {
-                /* If not frozen, return the pixel buffer size
-                 * width * height * 4. */
-                result_size = m_pixelwidth * m_pixelheight * 4;
-        }
-
-        return result_size;
-}
-
-/* Deserialize the cairo image from the temporary file */
-bool
-Image::thaw()
-{
-        if (m_surface)
-                return true;
-        if (m_position < _vte_stream_tail(m_stream))
-                return false;
-
-        m_nread = 0;
-        m_surface = cairo_image_surface_create_from_png_stream((cairo_read_func_t)read_callback, this);
-        if (!m_surface)
-                return false;
-
-        return true;
-}
-
-/* Serialize the image to save RAM */
-void
-Image::freeze()
-{
-        cairo_status_t status;
-        double x_scale, y_scale;
-
-        if (!m_surface)
-                return;
-
-        m_position = _vte_stream_head(m_stream);
-        m_nwrite = 0;
-
-        cairo_surface_get_device_scale(m_surface, &x_scale, &y_scale);
-        if (!_vte_double_equal(x_scale, 1.0) || !_vte_double_equal(y_scale, 1.0)) {
-                /* If device scale exceeds 1.0, the PNG image created by
-                 * cairo_surface_write_to_png_stream() may be large. We need to convert
-                 * m_surface into a new surface with neutral scale. */
-                cairo_surface_t *image_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 
m_pixelwidth, m_pixelheight);
-                cairo_t *cr = cairo_create(image_surface);
-                paint(cr, 0, 0);
-                cairo_destroy(cr);
-                cairo_surface_destroy(m_surface);
-                m_surface = image_surface;
-        }
-        status = cairo_surface_write_to_png_stream(m_surface, (cairo_write_func_t)write_callback, this);
-        if (status == CAIRO_STATUS_SUCCESS) {
-                cairo_surface_destroy(m_surface);
-                m_surface = NULL;
-        }
-}
-
-/* Merge another image into this image */
-bool
-Image::subsume(Image *other, unsigned long cell_width, unsigned long cell_height)
+Image::contains(const Image &other) const
 {
-        cairo_t *cr;
-
-        assert(other != nullptr);
-
-        unsigned long offsetx = (other->m_left - m_left) * cell_width;
-        unsigned long offsety = (other->m_top - m_top) * cell_height;
-
-        if (is_frozen())
-                if (!thaw())
-                        return false;
-
-        if (other->is_frozen())
-                if (!other->thaw())
-                        return false;
-
-        cr = cairo_create(m_surface);
-        cairo_rectangle(cr, offsetx, offsety, m_pixelwidth, m_pixelheight);
-        cairo_clip(cr);
-        cairo_set_source_surface(cr, other->m_surface, offsetx, offsety);
-        cairo_paint(cr);
-        cairo_destroy(cr);
-
-        return true;
-}
-
-bool
-Image::unite(Image *other, unsigned long cell_width, unsigned long cell_height)
-{
-        if (is_frozen())
-                if (!thaw())
-                        return false;
-
-        int new_left = std::min(m_left, other->m_left);
-        int new_top = std::min(m_top, other->m_top);
-        int new_width = std::max(m_left + m_width, other->m_left + other->m_width) - new_left;
-        int new_height = std::max(m_top + m_height, other->m_top + other->m_width) - new_top;
-        int pixelwidth = new_width * cell_width;
-        int pixelheight = new_height * cell_height;
-        int offsetx = (m_left - new_left) * cell_width;
-        int offsety = (m_top - new_top) * cell_height;
-
-        cairo_surface_t *new_surface = cairo_surface_create_similar(other->m_surface, 
CAIRO_CONTENT_COLOR_ALPHA, m_pixelwidth, m_pixelheight);
-        cairo_t *cr = cairo_create(new_surface);
-        cairo_rectangle(cr, offsetx, offsety, m_pixelwidth, m_pixelheight);
-        cairo_clip(cr);
-        cairo_set_source_surface(cr, m_surface, offsetx, offsety);
-        cairo_paint(cr);
-        cairo_destroy(cr);
-
-        cairo_surface_destroy(m_surface);
-
-        m_left = new_left;
-        m_top = new_top;
-        m_width = new_width;
-        m_height = new_height;
-        m_pixelwidth = pixelwidth;
-        m_pixelheight = pixelheight;
-        m_surface = new_surface;
-
-        return subsume(other, cell_width, cell_height);
+        return other.m_left >= m_left &&
+               other.m_top >= m_top &&
+               other.m_left + other.m_width <= m_left + m_width &&
+               other.m_top + other.m_height <= m_top + m_height;
 }
 
 /* Paint the image with provided cairo context */
 bool
 Image::paint(cairo_t *cr, int offsetx, int offsety)
 {
-        if (is_frozen())
-                if (!thaw())
-                        return false;
-
         cairo_save(cr);
         cairo_rectangle(cr, offsetx, offsety, m_pixelwidth, m_pixelheight);
         cairo_clip(cr);
-        cairo_set_source_surface(cr, m_surface, offsetx, offsety);
+        cairo_set_source_surface(cr, m_surface.get(), offsetx, offsety);
         cairo_paint(cr);
         cairo_restore(cr);
 
         return true;
 }
 
-/* Callback routines for stream I/O */
-
-cairo_status_t
-Image::read_callback(void *closure, char *data, unsigned int length)
-{
-        Image *image = (Image *)closure;
-
-        assert(image != nullptr);
-
-        _vte_stream_read(image->m_stream, image->m_position + image->m_nread, data, length);
-        image->m_nread += length;
-
-        return CAIRO_STATUS_SUCCESS;
-}
-
-cairo_status_t
-Image::write_callback(void *closure, const char *data, unsigned int length)
-{
-        Image *image = (Image *)closure;
-
-        assert(image != nullptr);
-
-        _vte_stream_append(image->m_stream, data, length);
-        image->m_nwrite += length;
-
-        return CAIRO_STATUS_SUCCESS;
-}
-
 } // namespace image
 
 } // namespace vte
diff --git a/src/image.hh b/src/image.hh
index f7f835e3..fe6f334e 100644
--- a/src/image.hh
+++ b/src/image.hh
@@ -19,7 +19,7 @@
 #pragma once
 
 #include <pango/pangocairo.h>
-#include "vtestream.h"
+#include "cairo-glue.hh"
 
 namespace vte {
 
@@ -27,38 +27,40 @@ namespace image {
 
 struct Image {
 private:
-        int m_pixelwidth;           /* Image width in pixels */
-        int m_pixelheight;          /* Image height in pixels */
-        int m_left;                 /* Left position in cell units */
-        int m_top;                  /* Top position in cell units */
-        int m_width;                /* Width in cell units */
-        int m_height;               /* Height in cell units */
-        VteStream *m_stream;        /* For serialization */
-        unsigned long m_position;   /* Indicates the position at the stream if it's serialized */
-        size_t m_nread;             /* Private use: for read callback */
-        size_t m_nwrite;            /* Private use: for write callback */
-        cairo_surface_t *m_surface; /* Internal cairo image */
-public:
-        explicit Image(cairo_surface_t *surface, int pixelwidth, int pixelheight,
-                       int col, int row, int w, int h, _VteStream *stream);
-        ~Image();
-        long get_left() const;
-        long get_top() const;
-        long get_bottom() const;
-        unsigned long get_stream_position() const;
-        bool is_frozen() const;
-        bool contains(const Image *rhs) const;
-        size_t resource_size() const;
-        void freeze();
-        bool thaw();
-        bool subsume(Image *rhs, gulong cell_width, gulong cell_height);
-        bool unite(Image *rhs, gulong cell_width, gulong cell_height);
-        bool paint(cairo_t *cr, gint offsetx, gint offsety);
+        // Device-friendly Cairo surface
+        vte::cairo::Surface m_surface{};
+
+        // Image dimensions in pixels
+        int m_pixelwidth;
+        int m_pixelheight;
 
-        /* Callbacks */
+        // Image geometry in cell units
+        int m_left;
+        int m_top;
+        int m_width;
+        int m_height;
 
-        static cairo_status_t read_callback(void *closure, char *data, unsigned int length);
-        static cairo_status_t write_callback(void *closure, const char *data, unsigned int length);
+public:
+        Image(vte::cairo::Surface&& surface, int width_pixels, int height_pixels,
+              int col, int row, int width_cells, int height_cells) noexcept
+                : m_surface{std::move(surface)},
+                  m_pixelwidth{width_pixels},
+                  m_pixelheight{height_pixels},
+                  m_left{col},
+                  m_top{row},
+                  m_width{width_cells},
+                  m_height{height_cells}
+        {
+        }
+
+        constexpr auto const get_left() const noexcept { return m_left; }
+        constexpr auto const get_top() const noexcept { return m_top; }
+        constexpr auto const get_bottom() const noexcept { return m_top + m_height - 1; }
+        auto const resource_size() const noexcept {
+                return cairo_image_surface_get_stride(m_surface.get()) * m_pixelheight;
+        }
+        bool contains(const Image &other) const;
+        bool paint(cairo_t *cr, gint offsetx, gint offsety);
 };
 
 } // namespace image
diff --git a/src/ring.cc b/src/ring.cc
index da194607..28d7524a 100644
--- a/src/ring.cc
+++ b/src/ring.cc
@@ -75,7 +75,6 @@ Ring::Ring(row_t max_rows,
                m_attr_stream = _vte_file_stream_new ();
                m_text_stream = _vte_file_stream_new ();
                m_row_stream = _vte_file_stream_new ();
-               m_image_stream = _vte_file_stream_new ();
        } else {
                m_attr_stream = m_text_stream = m_row_stream = nullptr;
        }
@@ -114,7 +113,6 @@ Ring::~Ring()
                g_object_unref (m_attr_stream);
                g_object_unref (m_text_stream);
                g_object_unref (m_row_stream);
-               g_object_unref (m_image_stream);
        }
 
        g_string_free (m_utf8_buffer, TRUE);
@@ -1527,7 +1525,7 @@ Ring::append_image (cairo_surface_t *surface, gint pixelwidth, gint pixelheight,
        Image *image;
        gulong char_width, char_height;
 
-       image = new (std::nothrow) Image (surface, pixelwidth, pixelheight, left, top, width, height, 
m_image_stream);
+       image = new (std::nothrow) Image (vte::cairo::Surface(surface), pixelwidth, pixelheight, left, top, 
width, height);
        g_assert_true (image != NULL);
 
        char_width = pixelwidth / width;
@@ -1538,7 +1536,7 @@ Ring::append_image (cairo_surface_t *surface, gint pixelwidth, gint pixelheight,
                Image *current = it->second;
 
                /* Combine two images if one's area contains another's area */
-               if (image->contains (current)) {
+               if (image->contains (*current)) {
                        /*
                         * Replace current image with new image
                         *
@@ -1549,71 +1547,12 @@ Ring::append_image (cairo_surface_t *surface, gint pixelwidth, gint pixelheight,
                         *  | :.........:  |
                         *  +--------------+
                         */
-                       if (current->is_frozen())
-                               m_image_offscreen_resource_counter -= current->resource_size ();
-                       else
-                               m_image_onscreen_resource_counter -= current->resource_size ();
+                        m_image_onscreen_resource_counter -= current->resource_size ();
 
                         /* We must advance the iterator before erasure */
                        m_image_map->erase (it++);
                        delete current;
                         continue;
-               } else if (current->contains (image)) {
-                       /*
-                        * Copy new image to current image's sub-area.
-                        *
-                        *  +--------------+
-                        *  | +-----+      |
-                        *  | | new |      |
-                        *  | +-----+      |
-                        *  |    current   |
-                        *  +--------------+
-                        */
-                       if (current->is_frozen()) {
-                               m_image_offscreen_resource_counter -= current->resource_size ();
-                               current->thaw ();
-                       } else {
-                               m_image_onscreen_resource_counter -= current->resource_size ();
-                       }
-                       current->subsume (image, char_width, char_height);
-                       m_image_onscreen_resource_counter += current->resource_size ();
-                       delete image;
-                       goto end;
-               }
-
-               if ((current->get_bottom () - image->get_bottom ()) * (current->get_top () - image->get_top 
()) <= 0) {
-                        /*
-                        * Unite two images if one's [top, bottom] includes another's [top, bottom].
-                        * This operation ensures bottom-position-based order is same to top-position-based 
order.
-                        *
-                        *              +------+
-                        *  +---------+ |      |
-                        *  | current | | new  |
-                        *  |         | |      |
-                        *  +---------+ |      |
-                        *              +------+
-                        *  or
-                        *
-                        *  +---------+
-                        *  | current | +------+
-                        *  |         | | new  |
-                        *  |         | +------+
-                        *  +---------+
-                        *          |
-                        *          v
-                        *  +------------------+
-                        *  | new (united)     |
-                        *  |                  |
-                        *  +------------------+
-                        */
-                       image->unite (image, char_width, char_height);
-                       m_image_map->erase (current->get_bottom ());
-                       if (current->is_frozen())
-                               m_image_offscreen_resource_counter -= current->resource_size ();
-                       else
-                               m_image_onscreen_resource_counter -= current->resource_size ();
-                       delete current;
-                       goto end;
                }
 
                 it++;
@@ -1644,8 +1583,4 @@ Ring::shrink_image_stream ()
                return;
 
        first_image = m_image_map->begin()->second;
-
-       if (first_image->is_frozen ())
-               if (first_image->get_stream_position () > _vte_stream_tail (m_image_stream))
-                       _vte_stream_advance_tail (m_image_stream, first_image->get_stream_position ());
 }
diff --git a/src/vte.cc b/src/vte.cc
index 6c5c91ad..ba88f739 100644
--- a/src/vte.cc
+++ b/src/vte.cc
@@ -4249,10 +4249,7 @@ Terminal::maybe_remove_images ()
                        break;
 
                /* otherwise, delete it */
-               if (image->is_frozen ())
-                       ring->m_image_offscreen_resource_counter -= image->resource_size ();
-               else
-                       ring->m_image_onscreen_resource_counter -= image->resource_size ();
+                ring->m_image_onscreen_resource_counter -= image->resource_size ();
                image_map->erase (image->get_bottom ());
                delete image;
                _vte_debug_print (VTE_DEBUG_IMAGE,
@@ -4274,10 +4271,7 @@ Terminal::maybe_remove_images ()
 
                        /* remove */
                        image_map->erase (image->get_bottom ());
-                       if (image->is_frozen ())
-                               ring->m_image_offscreen_resource_counter -= image->resource_size ();
-                       else
-                               ring->m_image_onscreen_resource_counter -= image->resource_size ();
+                        ring->m_image_onscreen_resource_counter -= image->resource_size ();
                        _vte_debug_print (VTE_DEBUG_IMAGE,
                                          "deleted, offscreen: %zu\n",
                                          ring->m_image_offscreen_resource_counter);
@@ -4294,56 +4288,6 @@ Terminal::maybe_remove_images ()
                ring->shrink_image_stream ();
 }
 
-void
-Terminal::freeze_hidden_images_before_view_area (double start_pos, double end_pos)
-{
-       VteRing *ring = m_screen->row_data;
-       auto image_map = ring->m_image_map;
-       /* for images before view area */
-       vte::grid::row_t top_of_view = (vte::grid::row_t)start_pos;
-       typedef std::remove_pointer<decltype(ring->m_image_map)>::type map_t;
-
-       /* iterate from new to old */
-       for (auto it = map_t::reverse_iterator (image_map->lower_bound (top_of_view)); it != image_map->rend 
(); ++it) {
-               vte::image::Image *image = it->second;
-               if (image->get_bottom () + 1 < end_pos)
-                       break;
-               if (! image->is_frozen ()) {
-                       ring->m_image_onscreen_resource_counter -= image->resource_size ();
-                       image->freeze ();
-                       ring->m_image_offscreen_resource_counter += image->resource_size ();
-                       _vte_debug_print (VTE_DEBUG_IMAGE,
-                                         "frozen, onscreen: %zu, offscreen: %zu\n",
-                                         ring->m_image_onscreen_resource_counter,
-                                         ring->m_image_offscreen_resource_counter);
-               }
-       }
-}
-
-void
-Terminal::freeze_hidden_images_after_view_area (double start_pos, double end_pos)
-{
-       VteRing *ring = m_screen->row_data;
-       auto image_map = ring->m_image_map;
-       vte::grid::row_t bottom_of_view = (vte::grid::row_t)(start_pos + m_row_count);
-
-       /* for images after view area */
-       for (auto it = image_map->lower_bound (bottom_of_view); it != image_map->end (); ++it) {
-               vte::image::Image *image = it->second;
-               if (image->get_top () < end_pos + m_row_count)
-                       break;
-               if (image->get_top () > bottom_of_view && ! image->is_frozen ()) {
-                       ring->m_image_onscreen_resource_counter -= image->resource_size ();
-                       image->freeze ();
-                       ring->m_image_offscreen_resource_counter += image->resource_size ();
-                       _vte_debug_print (VTE_DEBUG_IMAGE,
-                                         "frozen, onscreen: %zu, offscreen: %zu\n",
-                                         ring->m_image_onscreen_resource_counter,
-                                         ring->m_image_offscreen_resource_counter);
-               }
-       }
-}
-
 void
 Terminal::send(vte::parser::u8SequenceBuilder const& builder,
                          bool c1,
@@ -7768,12 +7712,6 @@ Terminal::vadjustment_value_changed()
                _vte_debug_print(VTE_DEBUG_ADJ,
                            "Scrolling by %f\n", dy);
 
-                if (dy > 0.0) {
-                       freeze_hidden_images_before_view_area (adj, adj - dy);
-                } else {
-                       freeze_hidden_images_after_view_area (adj, adj - dy);
-                }
-
                 invalidate_all();
                 match_contents_clear();
                emit_text_scrolled(dy);
@@ -9378,15 +9316,6 @@ Terminal::widget_draw(cairo_t *cr)
                        vte::image::Image *image = it->second;
                        if (image->get_top () > bottom_row)
                                break;
-                       if (image->is_frozen ()) {
-                               ring->m_image_offscreen_resource_counter -= image->resource_size ();
-                               image->thaw ();
-                               ring->m_image_onscreen_resource_counter += image->resource_size ();
-                               _vte_debug_print (VTE_DEBUG_IMAGE,
-                                                 "thawn, onscreen: %zu, offscreen: %zu\n",
-                                                 ring->m_image_onscreen_resource_counter,
-                                                 ring->m_image_offscreen_resource_counter);
-                       }
                        /* Display images */
                        int x = m_padding.left + image->get_left () * m_cell_width;
                        int y = m_padding.top + (image->get_top () - m_screen->scroll_delta) * m_cell_height;


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