[vte/wip/sixels: 28/82] image: Remove freeze/thaw and merging code, improve conformance
- From: Hans Petter Jansson <hansp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vte/wip/sixels: 28/82] image: Remove freeze/thaw and merging code, improve conformance
- Date: Fri, 26 Jun 2020 00:45:27 +0000 (UTC)
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]