[Commits] [SCM] claws branch, master, updated. 3.17.3-118-gce18d1c

ticho at claws-mail.org ticho at claws-mail.org
Tue Mar 5 08:46:06 CET 2019


The branch, master has been updated
       via  ce18d1ccbcde0bac5e01f4b3c2a07740226bfeb1 (commit)
       via  eb8f9e5bdffb7503513758e339d3215f1d690485 (commit)
      from  d43c0116bfdc8c3a511e5b638c2bd1908cfa9833 (commit)

Summary of changes:
 src/plugins/litehtml_viewer/Makefile.am            |    1 +
 src/plugins/litehtml_viewer/container_linux.cpp    |  116 +---------
 src/plugins/litehtml_viewer/container_linux.h      |   10 +-
 .../litehtml_viewer/container_linux_images.cpp     |  238 ++++++++++++++++++++
 src/plugins/litehtml_viewer/lh_widget.cpp          |   56 +----
 src/plugins/litehtml_viewer/lh_widget.h            |    3 +-
 6 files changed, 257 insertions(+), 167 deletions(-)
 create mode 100644 src/plugins/litehtml_viewer/container_linux_images.cpp


- Log -----------------------------------------------------------------
commit ce18d1ccbcde0bac5e01f4b3c2a07740226bfeb1
Author: Andrej Kacian <ticho at claws-mail.org>
Date:   Tue Mar 5 08:40:32 2019 +0100

    Make Litehtml image loading non-blocking using threads

diff --git a/src/plugins/litehtml_viewer/Makefile.am b/src/plugins/litehtml_viewer/Makefile.am
index 81ce766..a1dcd91 100644
--- a/src/plugins/litehtml_viewer/Makefile.am
+++ b/src/plugins/litehtml_viewer/Makefile.am
@@ -40,6 +40,7 @@ litehtml_viewer_la_CFLAGS = -std=c99
 
 litehtml_viewer_la_SOURCES = \
 	container_linux.cpp \
+	container_linux_images.cpp \
 	plugin.c \
 	lh_prefs.c \
 	lh_viewer.c \
diff --git a/src/plugins/litehtml_viewer/container_linux.cpp b/src/plugins/litehtml_viewer/container_linux.cpp
index e64d413..923ce76 100644
--- a/src/plugins/litehtml_viewer/container_linux.cpp
+++ b/src/plugins/litehtml_viewer/container_linux.cpp
@@ -106,65 +106,6 @@ void container_linux::draw_list_marker( litehtml::uint_ptr hdc, const litehtml::
 	}
 }
 
-void container_linux::load_image( const litehtml::tchar_t* src, const litehtml::tchar_t* baseurl, bool redraw_on_ready )
-{
-	litehtml::tstring url;
-	make_url(src, baseurl, url);
-	bool found = false;
-
-	for (auto ii = m_images.cbegin(); ii != m_images.cend(); ++ii) {
-		const image *i = &(*ii);
-
-		if (!strcmp(i->first.c_str(), url.c_str())) {
-			found = true;
-			break;
-		}
-	}
-
-	if(!found)
-	{
-		try
-		{
-			GdkPixbuf *img = get_image(url.c_str(), true);
-			if(img)
-			{
-				m_images.push_back(std::make_pair(url, img));
-			}
-		} catch(...)
-		{
-			int iii=0;
-			iii++;
-		}
-	}
-}
-
-void container_linux::get_image_size( const litehtml::tchar_t* src, const litehtml::tchar_t* baseurl, litehtml::size& sz )
-{
-	litehtml::tstring url;
-	make_url(src, baseurl, url);
-	bool found = false;
-	const image *img = NULL;
-
-	for (auto ii = m_images.cbegin(); ii != m_images.cend(); ++ii) {
-		const image *i = &(*ii);
-		if (i->first == url) {
-			img = i;
-			found = true;
-			break;
-		}
-	}
-
-	if(img != NULL)
-	{
-		sz.width	= gdk_pixbuf_get_width(img->second);
-		sz.height	= gdk_pixbuf_get_height(img->second);
-	} else
-	{
-		sz.width	= 0;
-		sz.height	= 0;
-	}
-}
-
 void container_linux::draw_background( litehtml::uint_ptr hdc, const litehtml::background_paint& bg )
 {
 	cairo_t* cr = (cairo_t*) hdc;
@@ -654,64 +595,6 @@ void container_linux::fill_ellipse( cairo_t* cr, int x, int y, int width, int he
 	cairo_restore(cr);
 }
 
-void container_linux::clear_images()
-{
-	lock_images_cache();
-
-	for(auto i = m_images.begin(); i != m_images.end(); ++i) {
-		image *img = &(*i);
-
-		if (img->second) {
-			g_object_unref(img->second);
-		}
-	}
-
-	m_images.clear();
-
-	unlock_images_cache();
-}
-
-gint container_linux::clear_images(gint desired_size)
-{
-	gint size = 0;
-	gint num = 0;
-
-	lock_images_cache();
-
-	/* First, tally up size of all the stored GdkPixbufs and
-	 * deallocate those which make the total size be above
-	 * the desired_size limit. We will remove their list
-	 * elements later. */
-	for (auto i = m_images.rbegin(); i != m_images.rend(); ++i) {
-		image *img = &(*i);
-		gint cursize;
-
-		if (img->second == NULL)
-			continue;
-
-		cursize = gdk_pixbuf_get_byte_length(img->second);
-
-		if (size + cursize > desired_size) {
-			g_object_unref(img->second);
-			img->second = NULL;
-			num++;
-		} else {
-			size += cursize;
-		}
-	}
-
-	/* Remove elements whose GdkPixbuf pointers point to NULL. */
-	m_images.remove_if([&](image _img) -> bool {
-			if (_img.second == NULL)
-				return true;
-			return false;
-			});
-
-	unlock_images_cache();
-
-	return num;
-}
-
 std::shared_ptr<litehtml::element>	container_linux::create_element(const litehtml::tchar_t *tag_name,
 																	  const litehtml::string_map &attributes,
 																	  const std::shared_ptr<litehtml::document> &doc)
diff --git a/src/plugins/litehtml_viewer/container_linux.h b/src/plugins/litehtml_viewer/container_linux.h
index 0b5f006..627bda6 100644
--- a/src/plugins/litehtml_viewer/container_linux.h
+++ b/src/plugins/litehtml_viewer/container_linux.h
@@ -87,7 +87,6 @@ public:
 	virtual void						del_clip() override;
 
 	virtual void						make_url( const litehtml::tchar_t* url, const litehtml::tchar_t* basepath, litehtml::tstring& out );
-	virtual GdkPixbuf	*get_image(const litehtml::tchar_t* url, bool redraw_on_ready) = 0;
 
 	void								clear_images();
 
@@ -95,6 +94,9 @@ public:
 	 * starting from oldest stored. */
 	gint								clear_images(gint desired_size);
 
+	void								add_image_to_cache(const gchar *url, GdkPixbuf *image);
+	virtual void				redraw(gboolean force_render) = 0;
+
 protected:
 	virtual void						draw_ellipse(cairo_t* cr, int x, int y, int width, int height, const litehtml::web_color& color, int line_width);
 	virtual void						fill_ellipse(cairo_t* cr, int x, int y, int width, int height, const litehtml::web_color& color);
diff --git a/src/plugins/litehtml_viewer/container_linux_images.cpp b/src/plugins/litehtml_viewer/container_linux_images.cpp
new file mode 100644
index 0000000..eeefd40
--- /dev/null
+++ b/src/plugins/litehtml_viewer/container_linux_images.cpp
@@ -0,0 +1,238 @@
+/*
+ * Claws Mail -- A GTK+ based, lightweight, and fast e-mail client
+ * Copyright(C) 2019 the Claws Mail Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write tothe Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#include "claws-features.h"
+#endif
+
+#include "common/utils.h"
+
+#include "container_linux.h"
+#include "http.h"
+#include "lh_prefs.h"
+
+static GdkPixbuf *lh_get_image(const litehtml::tchar_t* url)
+{
+	GError *error = NULL;
+	GdkPixbuf *pixbuf = NULL;
+	http* http_loader = NULL;
+
+	if (!lh_prefs_get()->enable_remote_content) {
+		debug_print("blocking download of image from '%s'\n", url);
+		return NULL;
+	}
+
+	debug_print("allowing download of image from '%s'\n", url);
+
+	http_loader = new http();
+	GInputStream *image = http_loader->load_url(url, &error);
+
+	if (error || !image) {
+		if (error) {
+			g_warning("lh_get_image: Could not create pixbuf %s",
+					error->message);
+			g_clear_error(&error);
+		}
+		goto theend;
+	}
+
+	pixbuf = gdk_pixbuf_new_from_stream(image, NULL, &error);
+	if (error) {
+		g_warning("lh_get_image: Could not create pixbuf %s",
+				error->message);
+		pixbuf = NULL;
+		g_clear_error(&error);
+	}
+
+theend:
+	if (http_loader) {
+		delete http_loader;
+	}
+
+	return pixbuf;
+}
+
+struct FetchCtx {
+	container_linux *container;
+	gchar *url;
+};
+
+static void get_image_threaded(GTask *task, gpointer source, gpointer task_data, GCancellable *cancellable)
+{
+	struct FetchCtx *ctx = (struct FetchCtx *)task_data;
+	GdkPixbuf *pixbuf = lh_get_image(ctx->url);
+
+	g_task_return_pointer(task, pixbuf, NULL);
+}
+
+static void get_image_callback(GObject *source, GAsyncResult *res, gpointer user_data)
+{
+	GdkPixbuf *pixbuf;
+	struct FetchCtx *ctx = (struct FetchCtx *)user_data;
+
+	pixbuf = GDK_PIXBUF(g_task_propagate_pointer(G_TASK(res), NULL));
+
+	if (pixbuf != NULL) {
+		ctx->container->add_image_to_cache(ctx->url, pixbuf);
+		ctx->container->redraw(true);
+	}
+
+	g_free(ctx->url);
+	g_free(ctx);
+}
+
+void container_linux::load_image( const litehtml::tchar_t* src, const litehtml::tchar_t* baseurl, bool redraw_on_ready )
+{
+	litehtml::tstring url;
+	make_url(src, baseurl, url);
+	bool found = false;
+
+	lock_images_cache();
+
+	for (auto ii = m_images.cbegin(); ii != m_images.cend(); ++ii) {
+		const image *i = &(*ii);
+
+		if (!strcmp(i->first.c_str(), url.c_str())) {
+			found = true;
+			break;
+		}
+	}
+
+	unlock_images_cache();
+
+	if(!found) {
+		struct FetchCtx *ctx = g_new(struct FetchCtx, 1);
+		ctx->url = g_strdup(url.c_str());
+		ctx->container = this;
+
+		GTask *task = g_task_new(this, NULL, get_image_callback, ctx);
+		g_task_set_task_data(task, ctx, NULL);
+		g_task_run_in_thread(task, get_image_threaded);
+	} else {
+		debug_print("found image in cache: '%s'\n", url.c_str());
+	}
+}
+
+void container_linux::get_image_size( const litehtml::tchar_t* src, const litehtml::tchar_t* baseurl, litehtml::size& sz )
+{
+	litehtml::tstring url;
+	make_url(src, baseurl, url);
+	bool found = false;
+	const image *img = NULL;
+
+	lock_images_cache();
+
+	for (auto ii = m_images.cbegin(); ii != m_images.cend(); ++ii) {
+		const image *i = &(*ii);
+		if (i->first == url) {
+			img = i;
+			found = true;
+			break;
+		}
+	}
+
+	if(img != NULL)
+	{
+		sz.width	= gdk_pixbuf_get_width(img->second);
+		sz.height	= gdk_pixbuf_get_height(img->second);
+	} else
+	{
+		sz.width	= 0;
+		sz.height	= 0;
+	}
+
+	unlock_images_cache();
+}
+
+void container_linux::add_image_to_cache(const gchar *url, GdkPixbuf *image)
+{
+	g_return_if_fail(url != NULL);
+	g_return_if_fail(image != NULL);
+
+	debug_print("adding image to cache: '%s'\n", url);
+	lock_images_cache();
+	m_images.push_back(std::make_pair(url, image));
+	unlock_images_cache();
+}
+void container_linux::lock_images_cache(void)
+{
+	g_rec_mutex_lock(&m_images_lock);
+}
+
+void container_linux::unlock_images_cache(void)
+{
+	g_rec_mutex_unlock(&m_images_lock);
+}
+
+void container_linux::clear_images()
+{
+	lock_images_cache();
+
+	for(auto i = m_images.begin(); i != m_images.end(); ++i) {
+		image *img = &(*i);
+
+		if (img->second) {
+			g_object_unref(img->second);
+		}
+	}
+
+	m_images.clear();
+
+	unlock_images_cache();
+}
+
+gint container_linux::clear_images(gint desired_size)
+{
+	gint size = 0;
+	gint num = 0;
+
+	lock_images_cache();
+
+	/* First, tally up size of all the stored GdkPixbufs and
+	 * deallocate those which make the total size be above
+	 * the desired_size limit. We will remove their list
+	 * elements later. */
+	for (auto i = m_images.rbegin(); i != m_images.rend(); ++i) {
+		image *img = &(*i);
+		gint cursize;
+
+		if (img->second == NULL)
+			continue;
+
+		cursize = gdk_pixbuf_get_byte_length(img->second);
+
+		if (size + cursize > desired_size) {
+			g_object_unref(img->second);
+			img->second = NULL;
+			num++;
+		} else {
+			size += cursize;
+		}
+	}
+
+	/* Remove elements whose GdkPixbuf pointers point to NULL. */
+	m_images.remove_if([&](image _img) -> bool {
+			if (_img.second == NULL)
+				return true;
+			return false;
+			});
+
+	unlock_images_cache();
+
+	return num;
+}
diff --git a/src/plugins/litehtml_viewer/lh_widget.cpp b/src/plugins/litehtml_viewer/lh_widget.cpp
index eb3ec2e..759b46e 100644
--- a/src/plugins/litehtml_viewer/lh_widget.cpp
+++ b/src/plugins/litehtml_viewer/lh_widget.cpp
@@ -36,7 +36,6 @@
 #include "lh_prefs.h"
 #include "lh_widget.h"
 #include "lh_widget_wrapped.h"
-#include "http.h"
 
 extern "C" {
 const gchar *prefs_common_get_uri_cmd(void);
@@ -167,53 +166,6 @@ void lh_widget::get_client_rect(litehtml::position& client) const
 //			client.width, client.height);
 }
 
-GdkPixbuf *lh_widget::get_image(const litehtml::tchar_t* url, bool redraw_on_ready)
-{
-	GError *error = NULL;
-	GdkPixbuf *pixbuf = NULL;
-	http* http_loader = NULL;
-
-	if (!lh_prefs_get()->enable_remote_content) {
-		debug_print("blocking download of image from '%s'\n", url);
-		return NULL;
-	}
-
-	debug_print("Loading... %s\n", url);
-	gchar *msg = g_strdup_printf("Loading %s ...", url);
-        lh_widget_statusbar_push(msg);
-	g_free(msg);
-	
-	http_loader = new http();
-	GInputStream *image = http_loader->load_url(url, &error);
-    
-	if (error || !image) {
-	    if (error) {
-		g_warning("lh_widget::get_image: Could not create pixbuf %s", error->message);
-		g_clear_error(&error);
-	    }
-	    goto statusbar_pop;
-	}
-
-	pixbuf = gdk_pixbuf_new_from_stream(image, NULL, &error);
-	if (error) {
-	    g_warning("lh_widget::get_image: Could not create pixbuf %s", error->message);
-	    pixbuf = NULL;
-	    g_clear_error(&error);
-	}
-
-/*	if (redraw_on_ready) {
-		redraw();
-	}*/
-
-statusbar_pop:
-	lh_widget_statusbar_pop();
-	if (http_loader) {
-		delete http_loader;
-	}
-	
-	return pixbuf;
-}
-
 void lh_widget::open_html(const gchar *contents)
 {
 	gint num = clear_images(lh_prefs_get()->image_cache_size * 1024 * 1000);
@@ -234,7 +186,7 @@ void lh_widget::open_html(const gchar *contents)
 		adj = gtk_scrolled_window_get_vadjustment(
 				GTK_SCROLLED_WINDOW(m_scrolled_window));
 		gtk_adjustment_set_value(adj, 0.0);
-		redraw();
+		redraw(false);
 	}
 	lh_widget_statusbar_pop();
 }
@@ -261,7 +213,7 @@ void lh_widget::draw(cairo_t *cr)
 	m_html->draw((litehtml::uint_ptr)cr, 0, 0, &pos);
 }
 
-void lh_widget::redraw()
+void lh_widget::redraw(gboolean force_render)
 {
 	GtkAllocation rect;
 	gint width;
@@ -279,7 +231,7 @@ void lh_widget::redraw()
 	m_height = gdk_window_get_height(gdkwin);
 
 	/* If the available width has changed, rerender the HTML content. */
-	if (m_rendered_width != width) {
+	if (m_rendered_width != width || force_render) {
 		debug_print("lh_widget::redraw: width changed: %d != %d\n",
 				m_rendered_width, width);
 
@@ -459,7 +411,7 @@ static gboolean expose_event_cb(GtkWidget *widget, GdkEvent *event,
 		gpointer user_data)
 {
 	lh_widget *w = (lh_widget *)user_data;
-	w->redraw();
+	w->redraw(false);
 	return FALSE;
 }
 
diff --git a/src/plugins/litehtml_viewer/lh_widget.h b/src/plugins/litehtml_viewer/lh_widget.h
index 5ca1d38..204d612 100644
--- a/src/plugins/litehtml_viewer/lh_widget.h
+++ b/src/plugins/litehtml_viewer/lh_widget.h
@@ -44,7 +44,6 @@ class lh_widget : public container_linux
 		void import_css(litehtml::tstring& text, const litehtml::tstring& url, litehtml::tstring& baseurl);
 		void get_client_rect(litehtml::position& client) const;
 		inline const litehtml::tchar_t *get_default_font_name() const { return m_font_name; };
-		GdkPixbuf *get_image(const litehtml::tchar_t* url, bool redraw_on_ready);
 
 		inline int get_default_font_size() const { return m_font_size; };
 		litehtml::uint_ptr create_font(const litehtml::tchar_t* faceName, int size, int weight, litehtml::font_style italic, unsigned int decoration, litehtml::font_metrics* fm);
@@ -53,7 +52,7 @@ class lh_widget : public container_linux
 		void draw_text(litehtml::uint_ptr hdc, const litehtml::tchar_t* text, litehtml::uint_ptr hFont, litehtml::web_color color, const litehtml::position& pos);
 
 		void draw(cairo_t *cr);
-		void redraw();
+		void redraw(gboolean force_render);
 		void open_html(const gchar *contents);
 		void clear();
 		void update_cursor();

commit eb8f9e5bdffb7503513758e339d3215f1d690485
Author: Andrej Kacian <ticho at claws-mail.org>
Date:   Tue Mar 5 08:40:20 2019 +0100

    Add a mutex lock for Litehtml plugin image cache

diff --git a/src/plugins/litehtml_viewer/container_linux.cpp b/src/plugins/litehtml_viewer/container_linux.cpp
index 9a11757..e64d413 100644
--- a/src/plugins/litehtml_viewer/container_linux.cpp
+++ b/src/plugins/litehtml_viewer/container_linux.cpp
@@ -35,6 +35,7 @@ container_linux::container_linux(void)
 {
 	m_temp_surface	= cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 2, 2);
 	m_temp_cr		= cairo_create(m_temp_surface);
+	g_rec_mutex_init(&m_images_lock);
 }
 
 container_linux::~container_linux(void)
@@ -42,6 +43,7 @@ container_linux::~container_linux(void)
 	clear_images();
 	cairo_surface_destroy(m_temp_surface);
 	cairo_destroy(m_temp_cr);
+	g_rec_mutex_clear(&m_images_lock);
 }
 
 int container_linux::pt_to_px( int pt )
@@ -184,7 +186,7 @@ void container_linux::draw_background( litehtml::uint_ptr hdc, const litehtml::b
 	litehtml::tstring url;
 	make_url(bg.image.c_str(), bg.baseurl.c_str(), url);
 
-	//lock_images_cache();
+	lock_images_cache();
 	bool found = false;
 	const image *img_i = NULL;
 
@@ -245,7 +247,8 @@ void container_linux::draw_background( litehtml::uint_ptr hdc, const litehtml::b
 		cairo_surface_destroy(img);
 
 	}
-//	unlock_images_cache();
+
+	unlock_images_cache();
 	cairo_restore(cr);
 }
 
@@ -653,6 +656,8 @@ void container_linux::fill_ellipse( cairo_t* cr, int x, int y, int width, int he
 
 void container_linux::clear_images()
 {
+	lock_images_cache();
+
 	for(auto i = m_images.begin(); i != m_images.end(); ++i) {
 		image *img = &(*i);
 
@@ -662,6 +667,8 @@ void container_linux::clear_images()
 	}
 
 	m_images.clear();
+
+	unlock_images_cache();
 }
 
 gint container_linux::clear_images(gint desired_size)
@@ -669,6 +676,8 @@ gint container_linux::clear_images(gint desired_size)
 	gint size = 0;
 	gint num = 0;
 
+	lock_images_cache();
+
 	/* First, tally up size of all the stored GdkPixbufs and
 	 * deallocate those which make the total size be above
 	 * the desired_size limit. We will remove their list
@@ -698,6 +707,8 @@ gint container_linux::clear_images(gint desired_size)
 			return false;
 			});
 
+	unlock_images_cache();
+
 	return num;
 }
 
diff --git a/src/plugins/litehtml_viewer/container_linux.h b/src/plugins/litehtml_viewer/container_linux.h
index a68502d..0b5f006 100644
--- a/src/plugins/litehtml_viewer/container_linux.h
+++ b/src/plugins/litehtml_viewer/container_linux.h
@@ -61,7 +61,9 @@ protected:
 	cairo_surface_t*			m_temp_surface;
 	cairo_t*					m_temp_cr;
 	images_map					m_images;
-    cairo_clip_box::vector		m_clips;
+	GRecMutex					m_images_lock;
+	cairo_clip_box::vector				m_clips;
+
 public:
 	container_linux(void);
 	virtual ~container_linux(void);
@@ -104,4 +106,6 @@ private:
 	void								add_path_arc(cairo_t* cr, double x, double y, double rx, double ry, double a1, double a2, bool neg);
 	void								draw_pixbuf(cairo_t* cr, const GdkPixbuf *bmp, int x, int y, int cx, int cy);
 	cairo_surface_t*					surface_from_pixbuf(const GdkPixbuf *bmp);
+	void lock_images_cache(void);
+	void unlock_images_cache(void);
 };

-----------------------------------------------------------------------


hooks/post-receive
-- 
Claws Mail


More information about the Commits mailing list