[vte/wip/sixels: 70/111] image: Scale images to current cell size




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

    image: Scale images to current cell size
    
    If the cell size changed since an image was received, scale the image
    on paint to cover the cell extent correctly. We do this by storing the
    image's native cell size on creation and comparing it to the current
    cell size as passed in to paint().

 src/image.cc  | 22 +++++++++++++++++++---
 src/image.hh  | 20 +++++++++++---------
 src/ring.cc   | 10 +++-------
 src/ring.hh   |  5 ++++-
 src/vteseq.cc |  2 +-
 5 files changed, 38 insertions(+), 21 deletions(-)
---
diff --git a/src/image.cc b/src/image.cc
index b7e13552..242fc6e3 100644
--- a/src/image.cc
+++ b/src/image.cc
@@ -31,13 +31,29 @@ namespace image {
 void
 Image::paint(cairo_t *cr, int offset_x, int offset_y, int cell_width, int cell_height) const noexcept
 {
-        /* FIXME-hpj: Scale the image if cell width/height is different */
+        double scale_x = 1.0, scale_y = 1.0;
+        double real_offset_x, real_offset_y;
+
+        real_offset_x = offset_x;
+        real_offset_y = offset_y;
+
+        if (cell_width != m_cell_width || cell_height != m_cell_height) {
+                scale_x = cell_width / (double) m_cell_width;
+                scale_y = cell_height / (double) m_cell_height;
+
+                real_offset_x /= scale_x;
+                real_offset_y /= scale_y;
+        }
 
         cairo_save(cr);
         cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
-        cairo_rectangle(cr, offset_x, offset_y, m_width_pixels, m_height_pixels);
+
+        if (!(_vte_double_equal (scale_x, 1.0) && _vte_double_equal (scale_y, 1.0)))
+                cairo_scale (cr, scale_x, scale_y);
+
+        cairo_rectangle(cr, real_offset_x, real_offset_y, m_width_pixels, m_height_pixels);
         cairo_clip(cr);
-        cairo_set_source_surface(cr, m_surface.get(), offset_x, offset_y);
+        cairo_set_source_surface(cr, m_surface.get(), real_offset_x, real_offset_y);
         cairo_paint(cr);
         cairo_restore(cr);
 }
diff --git a/src/image.hh b/src/image.hh
index 9ffb83dd..02914985 100644
--- a/src/image.hh
+++ b/src/image.hh
@@ -37,35 +37,37 @@ private:
         int m_width_pixels;
         int m_height_pixels;
 
-        // Image geometry in cell units
+        // Top left corner offset in cell units
         int m_left_cells;
         int m_top_cells;
-        int m_width_cells;
-        int m_height_cells;
+
+        // Cell dimensions in pixels at time of image creation
+        int m_cell_width;
+        int m_cell_height;
 
 public:
         Image(vte::cairo::Surface&& surface,
               int priority,
               int width_pixels, int height_pixels,
               int col, int row,
-              int width_cells, int height_cells) noexcept
+              int cell_width, int cell_height) noexcept
                 : m_surface{std::move(surface)},
                   m_priority{priority},
                   m_width_pixels{width_pixels},
                   m_height_pixels{height_pixels},
                   m_left_cells{col},
                   m_top_cells{row},
-                  m_width_cells{width_cells},
-                  m_height_cells{height_cells}
+                  m_cell_width{cell_width},
+                  m_cell_height{cell_height}
         {
         }
 
         inline constexpr auto get_priority() const noexcept { return m_priority; }
         inline constexpr auto get_left() const noexcept { return m_left_cells; }
         inline constexpr auto get_top() const noexcept { return m_top_cells; }
-        inline constexpr auto get_bottom() const noexcept { return m_top_cells + m_height_cells - 1; }
-        inline constexpr auto get_width() const noexcept { return m_width_cells; }
-        inline constexpr auto get_height() const noexcept { return m_height_cells; }
+        inline constexpr auto get_width() const noexcept { return (m_width_pixels + m_cell_width - 1) / 
m_cell_width; }
+        inline constexpr auto get_height() const noexcept { return (m_height_pixels + m_cell_height - 1) / 
m_cell_height; }
+        inline constexpr auto get_bottom() const noexcept { return m_top_cells + get_height() - 1; }
         inline auto resource_size() const noexcept {
                 if (cairo_image_surface_get_stride(m_surface.get()) != 0)
                         return cairo_image_surface_get_stride(m_surface.get()) * m_height_pixels;
diff --git a/src/ring.cc b/src/ring.cc
index 1b9bae90..70534db2 100644
--- a/src/ring.cc
+++ b/src/ring.cc
@@ -1582,21 +1582,17 @@ Ring::write_contents(GOutputStream* stream,
  * Append an image into the internal image list.
  */
 void
-Ring::append_image (cairo_surface_t *surface, gint pixelwidth, gint pixelheight, glong left, glong top, 
glong width, glong height)
+Ring::append_image (cairo_surface_t *surface, gint pixelwidth, gint pixelheight, glong left, glong top, 
glong cell_width, glong cell_height)
 {
        using namespace vte::image;
        Image *image;
-       gulong char_width, char_height;
 
        image = new (std::nothrow) Image (vte::cairo::Surface(surface),
                                           m_next_image_priority++,
                                           pixelwidth, pixelheight,
                                           left, top,
-                                          width, height);
-       g_assert_true (image != NULL);
-
-       char_width = pixelwidth / width;
-       char_height = pixelwidth / height;
+                                          cell_width, cell_height);
+       g_assert (image != NULL);
 
        /*
         * Now register new image to the m_image_map container.
diff --git a/src/ring.hh b/src/ring.hh
index 5974f9a6..ff384f3b 100644
--- a/src/ring.hh
+++ b/src/ring.hh
@@ -91,7 +91,10 @@ public:
         VteRowData* insert(row_t position, guint8 bidi_flags);
         VteRowData* append(guint8 bidi_flags);
         void remove(row_t position);
-        void append_image (cairo_surface_t *surface, gint pixelwidth, gint pixelheight, glong left, glong 
top, glong width, glong height);
+        void append_image (cairo_surface_t *surface,
+                           gint pixelwidth, gint pixelheight,
+                           glong left, glong top,
+                           glong cell_width, glong cell_height);
         void drop_scrollback(row_t position);
         void set_visible_rows(row_t rows);
         void rewrap(column_t columns,
diff --git a/src/vteseq.cc b/src/vteseq.cc
index 010e0646..f59fd26a 100644
--- a/src/vteseq.cc
+++ b/src/vteseq.cc
@@ -3140,7 +3140,7 @@ Terminal::seq_load_sixel(char const* dcs)
        free (pixels);
 
        /* create image object */
-       m_screen->row_data->append_image (surface, pixelwidth, pixelheight, left, top, width, height);
+       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) {


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