[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