update copyright year
[claws.git] / src / plugins / litehtml_viewer / container_linux_images.cpp
index 5c6f7f6864f19968722f4d9cb2b1f2ed3256feba..4998a2adbc2c67ea34cc1974245e5b2f297bed4c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Claws Mail -- A GTK+ based, lightweight, and fast e-mail client
+ * 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
 
 #include "common/utils.h"
 
-#include "container_linux.h"
+#include "container_linux_images.h"
 #include "http.h"
-#include "lh_prefs.h"
 
-static GdkPixbuf *lh_get_image(const litehtml::tchar_t* url)
+static GdkPixbuf *lh_get_image(const char *url)
 {
        GError *error = NULL;
        GdkPixbuf *pixbuf = NULL;
-       http* http_loader = NULL;
 
-       http_loader = new http();
+       http* 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_warning("lh_get_image: Could not load URL for '%s': %s",
+                               url, error->message);
+                       g_clear_error(&error);
+               }
+       } else {
+               pixbuf = gdk_pixbuf_new_from_stream(image, NULL, &error);
+               if (error) {
+                       g_warning("lh_get_image: Could not create pixbuf for '%s': %s",
+                               url, error->message);
+                       pixbuf = NULL;
                        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;
-       }
+       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)
+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);
@@ -73,113 +62,51 @@ static void get_image_threaded(GTask *task, gpointer source, gpointer task_data,
        g_task_return_pointer(task, pixbuf, NULL);
 }
 
-static void get_image_callback(GObject *source, GAsyncResult *res, gpointer user_data)
+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);
-       }
+       ctx->container->update_image_cache(ctx->url, pixbuf);
+       ctx->container->rerender();
 
        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 )
+void container_linux::update_image_cache(const gchar *url, GdkPixbuf *image)
 {
-       litehtml::tstring url;
-       make_url(src, baseurl, url);
-       bool found = false;
+       g_return_if_fail(url != NULL);
 
+       debug_print("updating image cache: %p '%s'\n", image, url);
        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;
-               }
+       auto i = m_images.find(url);
+       if(i == m_images.end()) {
+               g_warning("image '%s' was not found in pixbuf cache", url);
+               unlock_images_cache();
+               return;
        }
 
-       unlock_images_cache();
-
-       if (!found) {
-               struct FetchCtx *ctx = g_new(struct FetchCtx, 1);
-
-               /* Attached images can be loaded into cache right here. */
-               if (!strncmp(src, "cid:", 4)) {
-                       GdkPixbuf *pixbuf = get_local_image(src);
-
-                       if (pixbuf != NULL)
-                               add_image_to_cache(src, pixbuf);
-
-                       return;
-               }
-
-               if (!lh_prefs_get()->enable_remote_content) {
-                       debug_print("blocking download of image from '%s'\n", src);
-                       return;
-               }
-
-               debug_print("allowing download of image from '%s'\n", src);
-
-               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());
+       if(i->second.first != NULL && i->second.first != image) {
+               g_warning("pixbuf pointer for image '%s' changed", url);
+               g_object_unref(i->second.first);
        }
-}
 
-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;
+       if(image == NULL) {
+               /* A null pixbuf pointer presumably means the download failed,
+                * so remove the cache entry to allow for future retries. */
+               debug_print("warning - new pixbuf for '%s' is null\n", url);
+               m_images.erase(i);
+               unlock_images_cache();
+               return;
        }
 
+       i->second.first = image;
        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);
@@ -189,73 +116,3 @@ 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, remove all local images - the ones with "cid:"
-        * URL. We will remove their list elements later. */
-       for (auto i = m_images.rbegin(); i != m_images.rend(); ++i) {
-               image *img = &(*i);
-
-               if (!strncmp(img->first.c_str(), "cid:", 4)) {
-                       g_object_unref(img->second);
-                       img->second = NULL;
-                       num++;
-               }
-       }
-
-       /* Now 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;
-}