From 43fb45a957de24157d740e4dbec6c58753ee219b Mon Sep 17 00:00:00 2001 From: Arkadiy Illarionov Date: Sat, 24 Feb 2024 14:36:01 +0300 Subject: [PATCH] Convert ImageLoaderBackend to interface and backends to implementations Add parameters to ImageLoaderBackend methods. Remove unused members from backend implementations. Rename ImageLoaderBackend loader_new to init. Move callbacks aliases to ImageLoaderBackend and rename SizeCb to SizePreparedCb. --- src/image-load-collection.cc | 87 ++++++---------- src/image-load-collection.h | 4 +- src/image-load-cr3.cc | 25 +++-- src/image-load-cr3.h | 4 +- src/image-load-dds.cc | 83 ++++++---------- src/image-load-dds.h | 4 +- src/image-load-djvu.cc | 104 +++++++------------ src/image-load-djvu.h | 4 +- src/image-load-external.cc | 86 ++++++---------- src/image-load-external.h | 4 +- src/image-load-ffmpegthumbnailer.cc | 128 ++++++++++-------------- src/image-load-ffmpegthumbnailer.h | 4 +- src/image-load-gdk.cc | 63 +++++++----- src/image-load-gdk.h | 4 +- src/image-load-heif.cc | 111 ++++++++------------- src/image-load-heif.h | 4 +- src/image-load-j2k.cc | 83 ++++++---------- src/image-load-j2k.h | 4 +- src/image-load-jpeg.cc | 135 +++++++++---------------- src/image-load-jpeg.h | 35 ++++++- src/image-load-jpegxl.cc | 89 ++++++----------- src/image-load-jpegxl.h | 4 +- src/image-load-pdf.cc | 105 +++++++------------- src/image-load-pdf.h | 4 +- src/image-load-psd.cc | 87 ++++++---------- src/image-load-psd.h | 4 +- src/image-load-svgz.cc | 63 +++++++----- src/image-load-svgz.h | 4 +- src/image-load-tiff.cc | 149 ++++++++++++---------------- src/image-load-tiff.h | 4 +- src/image-load-webp.cc | 94 ++++++------------ src/image-load-webp.h | 4 +- src/image-load-zxscr.cc | 85 ++++++---------- src/image-load-zxscr.h | 4 +- src/image-load.cc | 134 ++++++++++++------------- src/image-load.h | 49 ++++----- 36 files changed, 776 insertions(+), 1083 deletions(-) diff --git a/src/image-load-collection.cc b/src/image-load-collection.cc index 6aaa2691..dbd8a02b 100644 --- a/src/image-load-collection.cc +++ b/src/image-load-collection.cc @@ -38,21 +38,27 @@ namespace { -struct ImageLoaderCOLLECTION { - ImageLoaderBackendCbAreaUpdated area_updated_cb; - ImageLoaderBackendCbSize size_cb; - ImageLoaderBackendCbAreaPrepared area_prepared_cb; +struct ImageLoaderCOLLECTION : public ImageLoaderBackend +{ +public: + ~ImageLoaderCOLLECTION() override; + + void init(AreaUpdatedCb area_updated_cb, SizePreparedCb size_prepared_cb, AreaPreparedCb area_prepared_cb, gpointer data) override; + gboolean write(const guchar *buf, gsize &chunk_size, gsize count, GError **error) override; + GdkPixbuf *get_pixbuf() override; + gchar *get_format_name() override; + gchar **get_format_mime_types() override; + +private: + AreaUpdatedCb area_updated_cb; gpointer data; + GdkPixbuf *pixbuf; - guint requested_width; - guint requested_height; - gboolean abort; }; -gboolean image_loader_collection_write(gpointer loader, const guchar *, gsize &chunk_size, gsize count, GError **) +gboolean ImageLoaderCOLLECTION::write(const guchar *, gsize &chunk_size, gsize count, GError **) { - auto ld = static_cast(loader); - auto il = static_cast(ld->data); + auto il = static_cast(data); #define LINE_LENGTH 1000 @@ -103,10 +109,10 @@ gboolean image_loader_collection_write(gpointer loader, const guchar *, gsize &c cmd_line = g_strdup_printf("montage %s -geometry %dx%d+1+1 %s >/dev/null 2>&1", file_names->str, options->thumbnails.max_width, options->thumbnails.max_height, randname); runcmd(cmd_line); - ld->pixbuf = gdk_pixbuf_new_from_file(randname, nullptr); - if (ld->pixbuf) + pixbuf = gdk_pixbuf_new_from_file(randname, nullptr); + if (pixbuf) { - ld->area_updated_cb(loader, 0, 0, gdk_pixbuf_get_width(ld->pixbuf), gdk_pixbuf_get_height(ld->pixbuf), ld->data); + area_updated_cb(nullptr, 0, 0, gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf), data); } unlink(randname); @@ -123,71 +129,38 @@ gboolean image_loader_collection_write(gpointer loader, const guchar *, gsize &c return ret; } -gpointer image_loader_collection_new(ImageLoaderBackendCbAreaUpdated area_updated_cb, ImageLoaderBackendCbSize size_cb, ImageLoaderBackendCbAreaPrepared area_prepared_cb, gpointer data) -{ - auto loader = g_new0(ImageLoaderCOLLECTION, 1); - loader->area_updated_cb = area_updated_cb; - loader->size_cb = size_cb; - loader->area_prepared_cb = area_prepared_cb; - loader->data = data; - return loader; -} - -void image_loader_collection_set_size(gpointer loader, int width, int height) +void ImageLoaderCOLLECTION::init(AreaUpdatedCb area_updated_cb, SizePreparedCb, AreaPreparedCb, gpointer data) { - auto ld = static_cast(loader); - ld->requested_width = width; - ld->requested_height = height; + this->area_updated_cb = area_updated_cb; + this->data = data; } -GdkPixbuf* image_loader_collection_get_pixbuf(gpointer loader) +GdkPixbuf *ImageLoaderCOLLECTION::get_pixbuf() { - auto ld = static_cast(loader); - return ld->pixbuf; + return pixbuf; } -gchar* image_loader_collection_get_format_name(gpointer) +gchar *ImageLoaderCOLLECTION::get_format_name() { return g_strdup("collection"); } -gchar** image_loader_collection_get_format_mime_types(gpointer) +gchar **ImageLoaderCOLLECTION::get_format_mime_types() { static const gchar *mime[] = {"image/png", nullptr}; return g_strdupv(const_cast(mime)); } -gboolean image_loader_collection_close(gpointer, GError **) -{ - return TRUE; -} - -void image_loader_collection_abort(gpointer loader) -{ - auto ld = static_cast(loader); - ld->abort = TRUE; -} - -void image_loader_collection_free(gpointer loader) +ImageLoaderCOLLECTION::~ImageLoaderCOLLECTION() { - auto ld = static_cast(loader); - if (ld->pixbuf) g_object_unref(ld->pixbuf); - g_free(ld); + if (pixbuf) g_object_unref(pixbuf); } } // namespace -void image_loader_backend_set_collection(ImageLoaderBackend *funcs) +std::unique_ptr get_image_loader_backend_collection() { - funcs->loader_new = image_loader_collection_new; - funcs->set_size = image_loader_collection_set_size; - funcs->write = image_loader_collection_write; - funcs->get_pixbuf = image_loader_collection_get_pixbuf; - funcs->close = image_loader_collection_close; - funcs->abort = image_loader_collection_abort; - funcs->free = image_loader_collection_free; - funcs->get_format_name = image_loader_collection_get_format_name; - funcs->get_format_mime_types = image_loader_collection_get_format_mime_types; + return std::make_unique(); } /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff --git a/src/image-load-collection.h b/src/image-load-collection.h index 38867747..281cc91b 100644 --- a/src/image-load-collection.h +++ b/src/image-load-collection.h @@ -21,9 +21,11 @@ #ifndef IMAGE_LOAD_COLLECTION_H #define IMAGE_LOAD_COLLECTION_H +#include + struct ImageLoaderBackend; -void image_loader_backend_set_collection(ImageLoaderBackend *funcs); +std::unique_ptr get_image_loader_backend_collection(); #endif /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff --git a/src/image-load-cr3.cc b/src/image-load-cr3.cc index 7cbdcde8..ba91fdd8 100644 --- a/src/image-load-cr3.cc +++ b/src/image-load-cr3.cc @@ -36,7 +36,15 @@ namespace { -gboolean image_loader_cr3_write(gpointer loader, const guchar *buf, gsize &chunk_size, gsize count, GError **error) +struct ImageLoaderCr3 : public ImageLoaderJpeg +{ +public: + gboolean write(const guchar *buf, gsize &chunk_size, gsize count, GError **error) override; + gchar *get_format_name() override; + gchar **get_format_mime_types() override; +}; + +gboolean ImageLoaderCr3::write(const guchar *buf, gsize &chunk_size, gsize count, GError **error) { /** @FIXME Just start search at where full size jpeg should be, * then search through the file looking for a jpeg end-marker @@ -78,7 +86,7 @@ gboolean image_loader_cr3_write(gpointer loader, const guchar *buf, gsize &chunk return FALSE; } - gboolean ret = image_loader_jpeg_write(loader, buf + n + 12, chunk_size, i, error);; + gboolean ret = ImageLoaderJpeg::write(buf + n + 12, chunk_size, i, error); if (ret) { chunk_size = count; @@ -86,12 +94,12 @@ gboolean image_loader_cr3_write(gpointer loader, const guchar *buf, gsize &chunk return ret; } -gchar* image_loader_cr3_get_format_name(gpointer) +gchar *ImageLoaderCr3::get_format_name() { return g_strdup("cr3"); } -gchar** image_loader_cr3_get_format_mime_types(gpointer) +gchar **ImageLoaderCr3::get_format_mime_types() { static const gchar *mime[] = {"image/x-canon-cr3", nullptr}; return g_strdupv(const_cast(mime)); @@ -99,14 +107,9 @@ gchar** image_loader_cr3_get_format_mime_types(gpointer) } // namespace -void image_loader_backend_set_cr3(ImageLoaderBackend *funcs) +std::unique_ptr get_image_loader_backend_cr3() { - image_loader_backend_set_jpeg(funcs); - - funcs->write = image_loader_cr3_write; - - funcs->get_format_name = image_loader_cr3_get_format_name; - funcs->get_format_mime_types = image_loader_cr3_get_format_mime_types; + return std::make_unique(); } #endif // HAVE_JPEG && !HAVE_RAW diff --git a/src/image-load-cr3.h b/src/image-load-cr3.h index a866fc5c..99d79a2d 100644 --- a/src/image-load-cr3.h +++ b/src/image-load-cr3.h @@ -24,9 +24,11 @@ #include #if HAVE_JPEG && !HAVE_RAW +#include + struct ImageLoaderBackend; -void image_loader_backend_set_cr3(ImageLoaderBackend *funcs); +std::unique_ptr get_image_loader_backend_cr3(); #endif #endif // IMAGE_LOAD_CR3_H diff --git a/src/image-load-dds.cc b/src/image-load-dds.cc index af8b8583..9247b952 100644 --- a/src/image-load-dds.cc +++ b/src/image-load-dds.cc @@ -37,15 +37,22 @@ namespace { -struct ImageLoaderDDS { - ImageLoaderBackendCbAreaUpdated area_updated_cb; - ImageLoaderBackendCbSize size_cb; - ImageLoaderBackendCbAreaPrepared area_prepared_cb; +struct ImageLoaderDDS : public ImageLoaderBackend +{ +public: + ~ImageLoaderDDS() override; + + void init(AreaUpdatedCb area_updated_cb, SizePreparedCb size_prepared_cb, AreaPreparedCb area_prepared_cb, gpointer data) override; + gboolean write(const guchar *buf, gsize &chunk_size, gsize count, GError **error) override; + GdkPixbuf *get_pixbuf() override; + gchar *get_format_name() override; + gchar **get_format_mime_types() override; + +private: + AreaUpdatedCb area_updated_cb; gpointer data; + GdkPixbuf *pixbuf; - guint requested_width; - guint requested_height; - gboolean abort; }; void free_buffer(guchar *pixels, gpointer) @@ -537,9 +544,8 @@ guchar *ddsReadX8R8G8B8(uint width, uint height, const unsigned char *buffer) { return reinterpret_cast(pixels); } -gboolean image_loader_dds_write (gpointer loader, const guchar *buf, gsize &chunk_size, gsize count, GError **) +gboolean ImageLoaderDDS::write(const guchar *buf, gsize &chunk_size, gsize count, GError **) { - auto ld = static_cast(loader); uint width = ddsGetWidth(buf); uint height = ddsGetHeight(buf); uint type = ddsGetType(buf); @@ -564,78 +570,45 @@ gboolean image_loader_dds_write (gpointer loader, const guchar *buf, gsize &chun case A8R8G8B8: pixels = ddsReadA8R8G8B8(width, height, buf); break; case X8R8G8B8: pixels = ddsReadX8R8G8B8(width, height, buf); break; } - ld->pixbuf = gdk_pixbuf_new_from_data (pixels, GDK_COLORSPACE_RGB, TRUE, 8, width, height, rowstride, free_buffer, nullptr); - ld->area_updated_cb(loader, 0, 0, width, height, ld->data); + pixbuf = gdk_pixbuf_new_from_data (pixels, GDK_COLORSPACE_RGB, TRUE, 8, width, height, rowstride, free_buffer, nullptr); + area_updated_cb(nullptr, 0, 0, width, height, data); chunk_size = count; return TRUE; } } -gpointer image_loader_dds_new(ImageLoaderBackendCbAreaUpdated area_updated_cb, ImageLoaderBackendCbSize size_cb, ImageLoaderBackendCbAreaPrepared area_prepared_cb, gpointer data) -{ - auto loader = g_new0(ImageLoaderDDS, 1); - loader->area_updated_cb = area_updated_cb; - loader->size_cb = size_cb; - loader->area_prepared_cb = area_prepared_cb; - loader->data = data; - return loader; -} - -void image_loader_dds_set_size(gpointer loader, int width, int height) +void ImageLoaderDDS::init(AreaUpdatedCb area_updated_cb, SizePreparedCb, AreaPreparedCb, gpointer data) { - auto ld = static_cast(loader); - ld->requested_width = width; - ld->requested_height = height; + this->area_updated_cb = area_updated_cb; + this->data = data; } -GdkPixbuf* image_loader_dds_get_pixbuf(gpointer loader) +GdkPixbuf *ImageLoaderDDS::get_pixbuf() { - auto ld = static_cast(loader); - return ld->pixbuf; + return pixbuf; } -gchar* image_loader_dds_get_format_name(gpointer) +gchar *ImageLoaderDDS::get_format_name() { return g_strdup("dds"); } -gchar** image_loader_dds_get_format_mime_types(gpointer) +gchar **ImageLoaderDDS::get_format_mime_types() { static const gchar *mime[] = {"image/vnd-ms.dds", nullptr}; return g_strdupv(const_cast(mime)); } -gboolean image_loader_dds_close(gpointer, GError **) -{ - return TRUE; -} - -void image_loader_dds_abort(gpointer loader) -{ - auto ld = static_cast(loader); - ld->abort = TRUE; -} - -void image_loader_dds_free(gpointer loader) +ImageLoaderDDS::~ImageLoaderDDS() { - auto ld = static_cast(loader); - if (ld->pixbuf) g_object_unref(ld->pixbuf); - g_free(ld); + if (pixbuf) g_object_unref(pixbuf); } } // namespace -void image_loader_backend_set_dds(ImageLoaderBackend *funcs) +std::unique_ptr get_image_loader_backend_dds() { - funcs->loader_new = image_loader_dds_new; - funcs->set_size = image_loader_dds_set_size; - funcs->write = image_loader_dds_write; - funcs->get_pixbuf = image_loader_dds_get_pixbuf; - funcs->close = image_loader_dds_close; - funcs->abort = image_loader_dds_abort; - funcs->free = image_loader_dds_free; - funcs->get_format_name = image_loader_dds_get_format_name; - funcs->get_format_mime_types = image_loader_dds_get_format_mime_types; + return std::make_unique(); } /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff --git a/src/image-load-dds.h b/src/image-load-dds.h index 6081e515..d8d7f89e 100644 --- a/src/image-load-dds.h +++ b/src/image-load-dds.h @@ -21,9 +21,11 @@ #ifndef IMAGE_LOAD_DDS_H #define IMAGE_LOAD_DDS_H +#include + struct ImageLoaderBackend; -void image_loader_backend_set_dds(ImageLoaderBackend *funcs); +std::unique_ptr get_image_loader_backend_dds(); #endif diff --git a/src/image-load-djvu.cc b/src/image-load-djvu.cc index 36c9b432..99eb7617 100644 --- a/src/image-load-djvu.cc +++ b/src/image-load-djvu.cc @@ -35,15 +35,24 @@ namespace { -struct ImageLoaderDJVU { - ImageLoaderBackendCbAreaUpdated area_updated_cb; - ImageLoaderBackendCbSize size_cb; - ImageLoaderBackendCbAreaPrepared area_prepared_cb; +struct ImageLoaderDJVU : public ImageLoaderBackend +{ +public: + ~ImageLoaderDJVU() override; + + void init(AreaUpdatedCb area_updated_cb, SizePreparedCb size_prepared_cb, AreaPreparedCb area_prepared_cb, gpointer data) override; + gboolean write(const guchar *buf, gsize &chunk_size, gsize count, GError **error) override; + GdkPixbuf *get_pixbuf() override; + gchar *get_format_name() override; + gchar **get_format_mime_types() override; + void set_page_num(gint page_num) override; + gint get_page_total() override; + +private: + AreaUpdatedCb area_updated_cb; gpointer data; + GdkPixbuf *pixbuf; - guint requested_width; - guint requested_height; - gboolean abort; gint page_num; gint page_total; }; @@ -53,9 +62,8 @@ void free_buffer(guchar *pixels, gpointer) g_free (pixels); } -gboolean image_loader_djvu_write(gpointer loader, const guchar *buf, gsize &chunk_size, gsize count, GError **) +gboolean ImageLoaderDJVU::write(const guchar *buf, gsize &chunk_size, gsize count, GError **) { - auto ld = static_cast(loader); ddjvu_context_t *ctx; ddjvu_document_t *doc; ddjvu_page_t *page; @@ -76,9 +84,9 @@ gboolean image_loader_djvu_write(gpointer loader, const guchar *buf, gsize &chun ddjvu_stream_write(doc, 0, reinterpret_cast(buf), count ); while (!ddjvu_document_decoding_done(doc)); - ld->page_total = ddjvu_document_get_pagenum(doc); + page_total = ddjvu_document_get_pagenum(doc); - page = ddjvu_page_create_by_pageno(doc, ld->page_num); + page = ddjvu_page_create_by_pageno(doc, page_num); while (!ddjvu_page_decoding_done(page)); fmt = ddjvu_format_create(DDJVU_FORMAT_RGB24, 0, nullptr); @@ -107,10 +115,9 @@ gboolean image_loader_djvu_write(gpointer loader, const guchar *buf, gsize &chun tmp2 = gdk_pixbuf_flip(tmp1, TRUE); g_object_unref(tmp1); - ld->pixbuf = gdk_pixbuf_rotate_simple(tmp2,GDK_PIXBUF_ROTATE_UPSIDEDOWN); - - ld->area_updated_cb(loader, 0, 0, width, height, ld->data); + pixbuf = gdk_pixbuf_rotate_simple(tmp2, GDK_PIXBUF_ROTATE_UPSIDEDOWN); + area_updated_cb(nullptr, 0, 0, width, height, data); cairo_surface_destroy(surface); ddjvu_page_release(page); @@ -121,87 +128,48 @@ gboolean image_loader_djvu_write(gpointer loader, const guchar *buf, gsize &chun return TRUE; } -gpointer image_loader_djvu_new(ImageLoaderBackendCbAreaUpdated area_updated_cb, ImageLoaderBackendCbSize size_cb, ImageLoaderBackendCbAreaPrepared area_prepared_cb, gpointer data) -{ - auto loader = g_new0(ImageLoaderDJVU, 1); - loader->area_updated_cb = area_updated_cb; - loader->size_cb = size_cb; - loader->area_prepared_cb = area_prepared_cb; - loader->data = data; - return loader; -} - -void image_loader_djvu_set_size(gpointer loader, int width, int height) +void ImageLoaderDJVU::init(AreaUpdatedCb area_updated_cb, SizePreparedCb, AreaPreparedCb, gpointer data) { - auto ld = static_cast(loader); - ld->requested_width = width; - ld->requested_height = height; + this->area_updated_cb = area_updated_cb; + this->data = data; } -GdkPixbuf* image_loader_djvu_get_pixbuf(gpointer loader) +GdkPixbuf *ImageLoaderDJVU::get_pixbuf() { - auto ld = static_cast(loader); - return ld->pixbuf; + return pixbuf; } -gchar* image_loader_djvu_get_format_name(gpointer) +gchar *ImageLoaderDJVU::get_format_name() { return g_strdup("djvu"); } -gchar** image_loader_djvu_get_format_mime_types(gpointer) +gchar **ImageLoaderDJVU::get_format_mime_types() { static const gchar *mime[] = {"image/vnd.djvu", nullptr}; return g_strdupv(const_cast(mime)); } -void image_loader_djvu_set_page_num(gpointer loader, gint page_num) +void ImageLoaderDJVU::set_page_num(gint page_num) { - auto ld = static_cast(loader); - - ld->page_num = page_num; -} - -gint image_loader_djvu_get_page_total(gpointer loader) -{ - auto ld = static_cast(loader); - - return ld->page_total; -} - -gboolean image_loader_djvu_close(gpointer, GError **) -{ - return TRUE; + this->page_num = page_num; } -void image_loader_djvu_abort(gpointer loader) +gint ImageLoaderDJVU::get_page_total() { - auto ld = static_cast(loader); - ld->abort = TRUE; + return page_total; } -void image_loader_djvu_free(gpointer loader) +ImageLoaderDJVU::~ImageLoaderDJVU() { - auto ld = static_cast(loader); - if (ld->pixbuf) g_object_unref(ld->pixbuf); - g_free(ld); + if (pixbuf) g_object_unref(pixbuf); } } // namespace -void image_loader_backend_set_djvu(ImageLoaderBackend *funcs) +std::unique_ptr get_image_loader_backend_djvu() { - funcs->loader_new = image_loader_djvu_new; - funcs->set_size = image_loader_djvu_set_size; - funcs->write = image_loader_djvu_write; - funcs->get_pixbuf = image_loader_djvu_get_pixbuf; - funcs->close = image_loader_djvu_close; - funcs->abort = image_loader_djvu_abort; - funcs->free = image_loader_djvu_free; - funcs->get_format_name = image_loader_djvu_get_format_name; - funcs->get_format_mime_types = image_loader_djvu_get_format_mime_types; - funcs->set_page_num = image_loader_djvu_set_page_num; - funcs->get_page_total = image_loader_djvu_get_page_total; + return std::make_unique(); } #endif diff --git a/src/image-load-djvu.h b/src/image-load-djvu.h index 0f125d43..ead0a783 100644 --- a/src/image-load-djvu.h +++ b/src/image-load-djvu.h @@ -24,9 +24,11 @@ #include #if HAVE_DJVU +#include + struct ImageLoaderBackend; -void image_loader_backend_set_djvu(ImageLoaderBackend *funcs); +std::unique_ptr get_image_loader_backend_djvu(); #endif #endif diff --git a/src/image-load-external.cc b/src/image-load-external.cc index 3f285ce7..83b50807 100644 --- a/src/image-load-external.cc +++ b/src/image-load-external.cc @@ -33,21 +33,27 @@ namespace { -struct ImageLoaderExternal { - ImageLoaderBackendCbAreaUpdated area_updated_cb; - ImageLoaderBackendCbSize size_cb; - ImageLoaderBackendCbAreaPrepared area_prepared_cb; +struct ImageLoaderExternal : public ImageLoaderBackend +{ +public: + ~ImageLoaderExternal() override; + + void init(AreaUpdatedCb area_updated_cb, SizePreparedCb size_prepared_cb, AreaPreparedCb area_prepared_cb, gpointer data) override; + gboolean write(const guchar *buf, gsize &chunk_size, gsize count, GError **error) override; + GdkPixbuf *get_pixbuf() override; + gchar *get_format_name() override; + gchar **get_format_mime_types() override; + +private: + AreaUpdatedCb area_updated_cb; gpointer data; + GdkPixbuf *pixbuf; - guint requested_width; - guint requested_height; - gboolean abort; }; -gboolean image_loader_external_write(gpointer loader, const guchar *, gsize &chunk_size, gsize count, GError **) +gboolean ImageLoaderExternal::write(const guchar *, gsize &chunk_size, gsize count, GError **) { - auto ld = static_cast(loader); - auto il = static_cast(ld->data); + auto il = static_cast(data); gchar *cmd_line; gchar *randname; gchar *tilde_filename; @@ -61,9 +67,9 @@ gboolean image_loader_external_write(gpointer loader, const guchar *, gsize &chu runcmd(cmd_line); - ld->pixbuf = gdk_pixbuf_new_from_file(randname, nullptr); + pixbuf = gdk_pixbuf_new_from_file(randname, nullptr); - ld->area_updated_cb(loader, 0, 0, gdk_pixbuf_get_width(ld->pixbuf), gdk_pixbuf_get_height(ld->pixbuf), ld->data); + area_updated_cb(nullptr, 0, 0, gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf), data); g_free(cmd_line); unlink_file(randname); @@ -74,72 +80,38 @@ gboolean image_loader_external_write(gpointer loader, const guchar *, gsize &chu return TRUE; } -gpointer image_loader_external_new(ImageLoaderBackendCbAreaUpdated area_updated_cb, ImageLoaderBackendCbSize size_cb, ImageLoaderBackendCbAreaPrepared area_prepared_cb, gpointer data) +void ImageLoaderExternal::init(AreaUpdatedCb area_updated_cb, SizePreparedCb, AreaPreparedCb, gpointer data) { - auto loader = g_new0(ImageLoaderExternal, 1); - loader->area_updated_cb = area_updated_cb; - loader->size_cb = size_cb; - loader->area_prepared_cb = area_prepared_cb; - loader->data = data; - return loader; + this->area_updated_cb = area_updated_cb; + this->data = data; } -void image_loader_external_set_size(gpointer loader, int width, int height) +GdkPixbuf *ImageLoaderExternal::get_pixbuf() { - auto ld = static_cast(loader); - ld->requested_width = width; - ld->requested_height = height; + return pixbuf; } -GdkPixbuf* image_loader_external_get_pixbuf(gpointer loader) -{ - auto ld = static_cast(loader); - return ld->pixbuf; -} - -gchar* image_loader_external_get_format_name(gpointer) +gchar *ImageLoaderExternal::get_format_name() { return g_strdup("external"); } -gchar** image_loader_external_get_format_mime_types(gpointer) +gchar **ImageLoaderExternal::get_format_mime_types() { static const gchar *mime[] = {"application/octet-stream", nullptr}; return g_strdupv(const_cast(mime)); } -gboolean image_loader_external_close(gpointer, GError **) +ImageLoaderExternal::~ImageLoaderExternal() { - return TRUE; -} - -void image_loader_external_abort(gpointer loader) -{ - auto ld = static_cast(loader); - ld->abort = TRUE; -} - -void image_loader_external_free(gpointer loader) -{ - auto ld = static_cast(loader); - if (ld->pixbuf) g_object_unref(ld->pixbuf); - g_free(ld); + if (pixbuf) g_object_unref(pixbuf); } } // namespace -void image_loader_backend_set_external(ImageLoaderBackend *funcs) +std::unique_ptr get_image_loader_backend_external() { - funcs->loader_new = image_loader_external_new; - funcs->set_size = image_loader_external_set_size; - funcs->write = image_loader_external_write; - funcs->get_pixbuf = image_loader_external_get_pixbuf; - funcs->close = image_loader_external_close; - funcs->abort = image_loader_external_abort; - funcs->free = image_loader_external_free; - funcs->get_format_name = image_loader_external_get_format_name; - funcs->get_format_mime_types = image_loader_external_get_format_mime_types; + return std::make_unique(); } - /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff --git a/src/image-load-external.h b/src/image-load-external.h index d674fc3c..6e39fa06 100644 --- a/src/image-load-external.h +++ b/src/image-load-external.h @@ -21,9 +21,11 @@ #ifndef IMAGE_LOAD_EXTERNAL_H #define IMAGE_LOAD_EXTERNAL_H +#include + struct ImageLoaderBackend; -void image_loader_backend_set_external(ImageLoaderBackend *funcs); +std::unique_ptr get_image_loader_backend_external(); #endif /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff --git a/src/image-load-ffmpegthumbnailer.cc b/src/image-load-ffmpegthumbnailer.cc index 29ffaa4b..a1334dd3 100644 --- a/src/image-load-ffmpegthumbnailer.cc +++ b/src/image-load-ffmpegthumbnailer.cc @@ -39,19 +39,29 @@ namespace { -struct ImageLoaderFT { - ImageLoaderBackendCbAreaUpdated area_updated_cb; - ImageLoaderBackendCbSize size_cb; - ImageLoaderBackendCbAreaPrepared area_prepared_cb; +struct ImageLoaderFT : public ImageLoaderBackend +{ +public: + ~ImageLoaderFT() override; + + void init(AreaUpdatedCb area_updated_cb, SizePreparedCb size_prepared_cb, AreaPreparedCb area_prepared_cb, gpointer data) override; + void set_size(int width, int height) override; + gboolean write(const guchar *buf, gsize &chunk_size, gsize count, GError **error) override; + GdkPixbuf *get_pixbuf() override; + gchar *get_format_name() override; + gchar **get_format_mime_types() override; + +private: + AreaUpdatedCb area_updated_cb; + SizePreparedCb size_prepared_cb; + AreaPreparedCb area_prepared_cb; + gpointer data; video_thumbnailer *vt; - gpointer data; - GdkPixbuf *pixbuf; guint requested_width; guint requested_height; - }; #if HAVE_FFMPEGTHUMBNAILER_RGB @@ -71,73 +81,67 @@ void image_loader_ft_destroy_image_data(guchar *, gpointer data) video_thumbnailer_destroy_image_data (image); } -gchar* image_loader_ft_get_format_name(gpointer) +gchar *ImageLoaderFT::get_format_name() { return g_strdup("ffmpeg"); } -gchar** image_loader_ft_get_format_mime_types(gpointer) +gchar **ImageLoaderFT::get_format_mime_types() { static const gchar *mime[] = {"video/mp4", nullptr}; return g_strdupv(const_cast(mime)); } -gpointer image_loader_ft_new(ImageLoaderBackendCbAreaUpdated area_updated_cb, ImageLoaderBackendCbSize size_cb, ImageLoaderBackendCbAreaPrepared area_prepared_cb, gpointer data) +void ImageLoaderFT::init(AreaUpdatedCb area_updated_cb, SizePreparedCb size_prepared_cb, AreaPreparedCb area_prepared_cb, gpointer data) { - auto loader = g_new0(ImageLoaderFT, 1); - - loader->area_updated_cb = area_updated_cb; - loader->size_cb = size_cb; - loader->area_prepared_cb = area_prepared_cb; - loader->data = data; - - loader->vt = video_thumbnailer_create(); - loader->vt->overlay_film_strip = 1; - loader->vt->maintain_aspect_ratio = 1; + this->area_updated_cb = area_updated_cb; + this->size_prepared_cb = size_prepared_cb; + this->area_prepared_cb = area_prepared_cb; + this->data = data; + + vt = video_thumbnailer_create(); + vt->overlay_film_strip = 1; + vt->maintain_aspect_ratio = 1; #if HAVE_FFMPEGTHUMBNAILER_RGB - video_thumbnailer_set_log_callback(loader->vt, image_loader_ft_log_cb); + video_thumbnailer_set_log_callback(vt, image_loader_ft_log_cb); #endif - - return loader; } -void image_loader_ft_set_size(gpointer loader, int width, int height) +void ImageLoaderFT::set_size(int width, int height) { - auto lft = static_cast(loader); - lft->requested_width = width; - lft->requested_height = height; + requested_width = width; + requested_height = height; DEBUG_1("TG: setting size, w=%d, h=%d", width, height); } -gboolean image_loader_ft_write (gpointer loader, const guchar *, gsize &chunk_size, gsize count, GError **) +gboolean ImageLoaderFT::write(const guchar *, gsize &chunk_size, gsize count, GError **) { - auto lft = static_cast(loader); - auto il = static_cast(lft->data); + auto il = static_cast(data); image_data *image = video_thumbnailer_create_image_data(); #if HAVE_FFMPEGTHUMBNAILER_WH - video_thumbnailer_set_size(lft->vt, lft->requested_width, lft->requested_height); + video_thumbnailer_set_size(vt, requested_width, requested_height); #else - lft->vt->thumbnail_size = MAX(lft->requested_width,lft->requested_height); + vt->thumbnail_size = MAX(requested_width, requested_height); #endif #if HAVE_FFMPEGTHUMBNAILER_METADATA - lft->vt->prefer_embedded_metadata = options->thumbnails.use_ft_metadata ? 1 : 0; + vt->prefer_embedded_metadata = options->thumbnails.use_ft_metadata ? 1 : 0; #endif #if HAVE_FFMPEGTHUMBNAILER_RGB - lft->vt->thumbnail_image_type = Rgb; + vt->thumbnail_image_type = Rgb; #else - lft->vt->thumbnail_image_type = Png; + vt->thumbnail_image_type = Png; #endif - video_thumbnailer_generate_thumbnail_to_buffer (lft->vt, il->fd->path, image); + video_thumbnailer_generate_thumbnail_to_buffer (vt, il->fd->path, image); #if HAVE_FFMPEGTHUMBNAILER_RGB - lft->pixbuf = gdk_pixbuf_new_from_data (image->image_data_ptr, GDK_COLORSPACE_RGB, FALSE, 8, image->image_data_width, image->image_data_height, image->image_data_width*3, image_loader_ft_destroy_image_data, image); - lft->size_cb(loader, image->image_data_width, image->image_data_height, lft->data); - lft->area_updated_cb(loader, 0, 0, image->image_data_width, image->image_data_height, lft->data); + pixbuf = gdk_pixbuf_new_from_data (image->image_data_ptr, GDK_COLORSPACE_RGB, FALSE, 8, image->image_data_width, image->image_data_height, image->image_data_width*3, image_loader_ft_destroy_image_data, image); + size_prepared_cb(nullptr, image->image_data_width, image->image_data_height, data); + area_updated_cb(nullptr, 0, 0, image->image_data_width, image->image_data_height, data); #else GInputStream *image_stream; image_stream = g_memory_input_stream_new_from_data (image->image_data_ptr, image->image_data_size, nullptr); @@ -149,13 +153,13 @@ gboolean image_loader_ft_write (gpointer loader, const guchar *, gsize &chunk_si return FALSE; } - lft->pixbuf = gdk_pixbuf_new_from_stream (image_stream, nullptr, nullptr); - lft->size_cb(loader, gdk_pixbuf_get_width(lft->pixbuf), gdk_pixbuf_get_height(lft->pixbuf), lft->data); + pixbuf = gdk_pixbuf_new_from_stream (image_stream, nullptr, nullptr); + size_prepared_cb(nullptr, gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf), data); g_object_unref (image_stream); video_thumbnailer_destroy_image_data (image); #endif - if (!lft->pixbuf) + if (!pixbuf) { DEBUG_1("FFmpegthumbnailer: no frame generated for %s", il->fd->path); return FALSE; @@ -164,52 +168,30 @@ gboolean image_loader_ft_write (gpointer loader, const guchar *, gsize &chunk_si /** See comment in image_loader_area_prepared_cb * Geeqie uses area_prepared signal to fill pixbuf with background color. * We can't do it here as pixbuf already contains the data - * lft->area_prepared_cb(loader, lft->data); + * area_prepared_cb(data); */ - lft->area_updated_cb(loader, 0, 0, gdk_pixbuf_get_width(lft->pixbuf), gdk_pixbuf_get_height(lft->pixbuf), lft->data); + area_updated_cb(nullptr, 0, 0, gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf), data); chunk_size = count; return TRUE; } -GdkPixbuf* image_loader_ft_get_pixbuf(gpointer loader) +GdkPixbuf *ImageLoaderFT::get_pixbuf() { - auto lft = static_cast(loader); - return lft->pixbuf; + return pixbuf; } -void image_loader_ft_abort(gpointer) +ImageLoaderFT::~ImageLoaderFT() { -} - -gboolean image_loader_ft_close(gpointer, GError **) -{ - return TRUE; -} - -void image_loader_ft_free(gpointer loader) -{ - auto lft = static_cast(loader); - if (lft->pixbuf) g_object_unref(lft->pixbuf); - video_thumbnailer_destroy (lft->vt); - - g_free(lft); + if (pixbuf) g_object_unref(pixbuf); + video_thumbnailer_destroy (vt); } } // namespace -void image_loader_backend_set_ft(ImageLoaderBackend *funcs) +std::unique_ptr get_image_loader_backend_ft() { - funcs->loader_new = image_loader_ft_new; - funcs->set_size = image_loader_ft_set_size; - funcs->write = image_loader_ft_write; - funcs->get_pixbuf = image_loader_ft_get_pixbuf; - funcs->close = image_loader_ft_close; - funcs->abort = image_loader_ft_abort; - funcs->free = image_loader_ft_free; - - funcs->get_format_name = image_loader_ft_get_format_name; - funcs->get_format_mime_types = image_loader_ft_get_format_mime_types; + return std::make_unique(); } #endif diff --git a/src/image-load-ffmpegthumbnailer.h b/src/image-load-ffmpegthumbnailer.h index 43251af0..56ebe38b 100644 --- a/src/image-load-ffmpegthumbnailer.h +++ b/src/image-load-ffmpegthumbnailer.h @@ -25,9 +25,11 @@ #include #if HAVE_FFMPEGTHUMBNAILER +#include + struct ImageLoaderBackend; -void image_loader_backend_set_ft(ImageLoaderBackend *funcs); +std::unique_ptr get_image_loader_backend_ft(); #endif #endif diff --git a/src/image-load-gdk.cc b/src/image-load-gdk.cc index b2773499..888a0222 100644 --- a/src/image-load-gdk.cc +++ b/src/image-load-gdk.cc @@ -31,11 +31,28 @@ namespace { -gchar* image_loader_gdk_get_format_name(gpointer loader) +struct ImageLoaderGdk : public ImageLoaderBackend +{ +public: + ~ImageLoaderGdk() override; + + void init(AreaUpdatedCb area_updated_cb, SizePreparedCb size_prepared_cb, AreaPreparedCb area_prepared_cb, gpointer data) override; + void set_size(int width, int height) override; + gboolean write(const guchar *buf, gsize &chunk_size, gsize count, GError **error) override; + GdkPixbuf *get_pixbuf() override; + gboolean close(GError **error) override; + gchar *get_format_name() override; + gchar **get_format_mime_types() override; + +private: + GdkPixbufLoader *loader; +}; + +gchar *ImageLoaderGdk::get_format_name() { GdkPixbufFormat *format; - format = gdk_pixbuf_loader_get_format(GDK_PIXBUF_LOADER(loader)); + format = gdk_pixbuf_loader_get_format(loader); if (format) { return gdk_pixbuf_format_get_name(format); @@ -44,15 +61,14 @@ gchar* image_loader_gdk_get_format_name(gpointer loader) return nullptr; } -gchar** image_loader_gdk_get_format_mime_types(gpointer loader) +gchar **ImageLoaderGdk::get_format_mime_types() { - return gdk_pixbuf_format_get_mime_types(gdk_pixbuf_loader_get_format(GDK_PIXBUF_LOADER(loader))); + return gdk_pixbuf_format_get_mime_types(gdk_pixbuf_loader_get_format(loader)); } -gpointer image_loader_gdk_new(ImageLoaderBackendCbAreaUpdated area_updated_cb, ImageLoaderBackendCbSize size_cb, ImageLoaderBackendCbAreaPrepared area_prepared_cb, gpointer data) +void ImageLoaderGdk::init(AreaUpdatedCb area_updated_cb, SizePreparedCb size_prepared_cb, AreaPreparedCb area_prepared_cb, gpointer data) { auto il = static_cast(data); - GdkPixbufLoader *loader; /** @FIXME gdk-pixbuf-loader does not recognize .xbm files unless * the mime type is given. There should be a general case */ @@ -66,39 +82,40 @@ gpointer image_loader_gdk_new(ImageLoaderBackendCbAreaUpdated area_updated_cb, I } g_signal_connect(G_OBJECT(loader), "area_updated", G_CALLBACK(area_updated_cb), data); - g_signal_connect(G_OBJECT(loader), "size_prepared", G_CALLBACK(size_cb), data); + g_signal_connect(G_OBJECT(loader), "size_prepared", G_CALLBACK(size_prepared_cb), data); g_signal_connect(G_OBJECT(loader), "area_prepared", G_CALLBACK(area_prepared_cb), data); - return loader; } -gboolean image_loader_gdk_write(gpointer loader, const guchar *buf, gsize &chunk_size, gsize, GError **error) +void ImageLoaderGdk::set_size(int width, int height) +{ + gdk_pixbuf_loader_set_size(loader, width, height); +} + +gboolean ImageLoaderGdk::write(const guchar *buf, gsize &chunk_size, gsize, GError **error) +{ + return gdk_pixbuf_loader_write(loader, buf, chunk_size, error); +} + +GdkPixbuf *ImageLoaderGdk::get_pixbuf() { - return gdk_pixbuf_loader_write(GDK_PIXBUF_LOADER(loader), buf, chunk_size, error); + return gdk_pixbuf_loader_get_pixbuf(loader); } -void image_loader_gdk_abort(gpointer) +gboolean ImageLoaderGdk::close(GError **error) { + return gdk_pixbuf_loader_close(loader, error); } -void image_loader_gdk_free(gpointer loader) +ImageLoaderGdk::~ImageLoaderGdk() { g_object_unref(G_OBJECT(loader)); } } // namespace -void image_loader_backend_set_default(ImageLoaderBackend *funcs) +std::unique_ptr get_image_loader_backend_default() { - funcs->loader_new = image_loader_gdk_new; - funcs->set_size = reinterpret_cast(gdk_pixbuf_loader_set_size); - funcs->write = image_loader_gdk_write; - funcs->get_pixbuf = reinterpret_cast(gdk_pixbuf_loader_get_pixbuf); - funcs->close = reinterpret_cast(gdk_pixbuf_loader_close); - funcs->abort = image_loader_gdk_abort; - funcs->free = image_loader_gdk_free; - - funcs->get_format_name = image_loader_gdk_get_format_name; - funcs->get_format_mime_types = image_loader_gdk_get_format_mime_types; + return std::make_unique(); } /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff --git a/src/image-load-gdk.h b/src/image-load-gdk.h index f7d9563c..e63f04a7 100644 --- a/src/image-load-gdk.h +++ b/src/image-load-gdk.h @@ -22,9 +22,11 @@ #ifndef IMAGE_LOAD_GDK_H #define IMAGE_LOAD_GDK_H +#include + struct ImageLoaderBackend; -void image_loader_backend_set_default(ImageLoaderBackend *funcs); +std::unique_ptr get_image_loader_backend_default(); #endif diff --git a/src/image-load-heif.cc b/src/image-load-heif.cc index e013e154..6c57a7a2 100644 --- a/src/image-load-heif.cc +++ b/src/image-load-heif.cc @@ -36,15 +36,24 @@ namespace { -struct ImageLoaderHEIF { - ImageLoaderBackendCbAreaUpdated area_updated_cb; - ImageLoaderBackendCbSize size_cb; - ImageLoaderBackendCbAreaPrepared area_prepared_cb; +struct ImageLoaderHEIF : public ImageLoaderBackend +{ +public: + ~ImageLoaderHEIF() override; + + void init(AreaUpdatedCb area_updated_cb, SizePreparedCb size_prepared_cb, AreaPreparedCb area_prepared_cb, gpointer data) override; + gboolean write(const guchar *buf, gsize &chunk_size, gsize count, GError **error) override; + GdkPixbuf *get_pixbuf() override; + gchar *get_format_name() override; + gchar **get_format_mime_types() override; + void set_page_num(gint page_num) override; + gint get_page_total() override; + +private: + AreaUpdatedCb area_updated_cb; gpointer data; + GdkPixbuf *pixbuf; - guint requested_width; - guint requested_height; - gboolean abort; gint page_num; gint page_total; }; @@ -54,19 +63,17 @@ void free_buffer(guchar *, gpointer data) heif_image_release(static_cast(data)); } -gboolean image_loader_heif_write(gpointer loader, const guchar *buf, gsize &chunk_size, gsize count, GError **) +gboolean ImageLoaderHEIF::write(const guchar *buf, gsize &chunk_size, gsize count, GError **) { - auto ld = static_cast(loader); struct heif_context* ctx; struct heif_image* img; struct heif_error error_code; struct heif_image_handle* handle; - guint8* data; + guint8* pixels; gint width; gint height; gint stride; gboolean alpha; - gint page_total; ctx = heif_context_alloc(); @@ -79,17 +86,16 @@ gboolean image_loader_heif_write(gpointer loader, const guchar *buf, gsize &chun } page_total = heif_context_get_number_of_top_level_images(ctx); - ld->page_total = page_total; std::vector IDs(page_total); /* get list of all (top level) image IDs */ heif_context_get_list_of_top_level_image_IDs(ctx, IDs.data(), page_total); - error_code = heif_context_get_image_handle(ctx, IDs[ld->page_num], &handle); + error_code = heif_context_get_image_handle(ctx, IDs[page_num], &handle); if (error_code.code) { - log_printf("warning: heif reader error: %s\n", error_code.message); + log_printf("warning: heif reader error: %s\n", error_code.message); heif_context_free(ctx); return FALSE; } @@ -103,16 +109,16 @@ gboolean image_loader_heif_write(gpointer loader, const guchar *buf, gsize &chun return FALSE; } - data = heif_image_get_plane(img, heif_channel_interleaved, &stride); + pixels = heif_image_get_plane(img, heif_channel_interleaved, &stride); height = heif_image_get_height(img,heif_channel_interleaved); width = heif_image_get_width(img,heif_channel_interleaved); alpha = heif_image_handle_has_alpha_channel(handle); heif_image_handle_release(handle); - ld->pixbuf = gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB, alpha, 8, width, height, stride, free_buffer, img); + pixbuf = gdk_pixbuf_new_from_data(pixels, GDK_COLORSPACE_RGB, alpha, 8, width, height, stride, free_buffer, img); - ld->area_updated_cb(loader, 0, 0, width, height, ld->data); + area_updated_cb(nullptr, 0, 0, width, height, data); heif_context_free(ctx); @@ -120,88 +126,49 @@ gboolean image_loader_heif_write(gpointer loader, const guchar *buf, gsize &chun return TRUE; } -gpointer image_loader_heif_new(ImageLoaderBackendCbAreaUpdated area_updated_cb, ImageLoaderBackendCbSize size_cb, ImageLoaderBackendCbAreaPrepared area_prepared_cb, gpointer data) +void ImageLoaderHEIF::init(AreaUpdatedCb area_updated_cb, SizePreparedCb, AreaPreparedCb, gpointer data) { - auto loader = g_new0(ImageLoaderHEIF, 1); - loader->area_updated_cb = area_updated_cb; - loader->size_cb = size_cb; - loader->area_prepared_cb = area_prepared_cb; - loader->data = data; - loader->page_num = 0; - return loader; + this->area_updated_cb = area_updated_cb; + this->data = data; + page_num = 0; } -void image_loader_heif_set_size(gpointer loader, int width, int height) +GdkPixbuf *ImageLoaderHEIF::get_pixbuf() { - auto ld = static_cast(loader); - ld->requested_width = width; - ld->requested_height = height; + return pixbuf; } -GdkPixbuf* image_loader_heif_get_pixbuf(gpointer loader) -{ - auto ld = static_cast(loader); - return ld->pixbuf; -} - -gchar* image_loader_heif_get_format_name(gpointer) +gchar *ImageLoaderHEIF::get_format_name() { return g_strdup("heif"); } -gchar** image_loader_heif_get_format_mime_types(gpointer) +gchar **ImageLoaderHEIF::get_format_mime_types() { static const gchar *mime[] = {"image/heic", nullptr}; return g_strdupv(const_cast(mime)); } -void image_loader_heif_set_page_num(gpointer loader, gint page_num) -{ - auto ld = static_cast(loader); - - ld->page_num = page_num; -} - -gint image_loader_heif_get_page_total(gpointer loader) -{ - auto ld = static_cast(loader); - - return ld->page_total; -} - -gboolean image_loader_heif_close(gpointer, GError **) +void ImageLoaderHEIF::set_page_num(gint page_num) { - return TRUE; + this->page_num = page_num; } -void image_loader_heif_abort(gpointer loader) +gint ImageLoaderHEIF::get_page_total() { - auto ld = static_cast(loader); - ld->abort = TRUE; + return page_total; } -void image_loader_heif_free(gpointer loader) +ImageLoaderHEIF::~ImageLoaderHEIF() { - auto ld = static_cast(loader); - if (ld->pixbuf) g_object_unref(ld->pixbuf); - g_free(ld); + if (pixbuf) g_object_unref(pixbuf); } } // namespace -void image_loader_backend_set_heif(ImageLoaderBackend *funcs) +std::unique_ptr get_image_loader_backend_heif() { - funcs->loader_new = image_loader_heif_new; - funcs->set_size = image_loader_heif_set_size; - funcs->write = image_loader_heif_write; - funcs->get_pixbuf = image_loader_heif_get_pixbuf; - funcs->close = image_loader_heif_close; - funcs->abort = image_loader_heif_abort; - funcs->free = image_loader_heif_free; - funcs->get_format_name = image_loader_heif_get_format_name; - funcs->get_format_mime_types = image_loader_heif_get_format_mime_types; - funcs->set_page_num = image_loader_heif_set_page_num; - funcs->get_page_total = image_loader_heif_get_page_total; + return std::make_unique(); } #endif diff --git a/src/image-load-heif.h b/src/image-load-heif.h index e1e56ba1..514b4c5a 100644 --- a/src/image-load-heif.h +++ b/src/image-load-heif.h @@ -24,9 +24,11 @@ #include #if HAVE_HEIF +#include + struct ImageLoaderBackend; -void image_loader_backend_set_heif(ImageLoaderBackend *funcs); +std::unique_ptr get_image_loader_backend_heif(); #endif #endif diff --git a/src/image-load-j2k.cc b/src/image-load-j2k.cc index 84aa03b6..dd19af92 100644 --- a/src/image-load-j2k.cc +++ b/src/image-load-j2k.cc @@ -40,15 +40,22 @@ namespace { -struct ImageLoaderJ2K { - ImageLoaderBackendCbAreaUpdated area_updated_cb; - ImageLoaderBackendCbSize size_cb; - ImageLoaderBackendCbAreaPrepared area_prepared_cb; +struct ImageLoaderJ2K : public ImageLoaderBackend +{ +public: + ~ImageLoaderJ2K() override; + + void init(AreaUpdatedCb area_updated_cb, SizePreparedCb size_prepared_cb, AreaPreparedCb area_prepared_cb, gpointer data) override; + gboolean write(const guchar *buf, gsize &chunk_size, gsize count, GError **error) override; + GdkPixbuf *get_pixbuf() override; + gchar *get_format_name() override; + gchar **get_format_mime_types() override; + +private: + AreaUpdatedCb area_updated_cb; gpointer data; + GdkPixbuf *pixbuf; - guint requested_width; - guint requested_height; - gboolean abort; }; void free_buffer(guchar *pixels, gpointer) @@ -183,9 +190,8 @@ opj_stream_t* OPJ_CALLCONV opj_stream_create_buffer_stream (opj_buffer_info_t* p return ps; } -gboolean image_loader_j2k_write(gpointer loader, const guchar *buf, gsize &chunk_size, gsize count, GError **) +gboolean ImageLoaderJ2K::write(const guchar *buf, gsize &chunk_size, gsize count, GError **) { - auto ld = static_cast(loader); opj_stream_t *stream; opj_codec_t *codec; opj_dparameters_t parameters; @@ -282,9 +288,9 @@ gboolean image_loader_j2k_write(gpointer loader, const guchar *buf, gsize &chunk } } - ld->pixbuf = gdk_pixbuf_new_from_data(pixels, GDK_COLORSPACE_RGB, FALSE , 8, width, height, width * bytes_per_pixel, free_buffer, nullptr); + pixbuf = gdk_pixbuf_new_from_data(pixels, GDK_COLORSPACE_RGB, FALSE , 8, width, height, width * bytes_per_pixel, free_buffer, nullptr); - ld->area_updated_cb(loader, 0, 0, width, height, ld->data); + area_updated_cb(nullptr, 0, 0, width, height, data); g_free(decode_buffer); g_free(buf_copy); @@ -299,71 +305,38 @@ gboolean image_loader_j2k_write(gpointer loader, const guchar *buf, gsize &chunk return TRUE; } -gpointer image_loader_j2k_new(ImageLoaderBackendCbAreaUpdated area_updated_cb, ImageLoaderBackendCbSize size_cb, ImageLoaderBackendCbAreaPrepared area_prepared_cb, gpointer data) -{ - auto loader = g_new0(ImageLoaderJ2K, 1); - loader->area_updated_cb = area_updated_cb; - loader->size_cb = size_cb; - loader->area_prepared_cb = area_prepared_cb; - loader->data = data; - return loader; -} - -void image_loader_j2k_set_size(gpointer loader, int width, int height) +void ImageLoaderJ2K::init(AreaUpdatedCb area_updated_cb, SizePreparedCb, AreaPreparedCb, gpointer data) { - auto ld = static_cast(loader); - ld->requested_width = width; - ld->requested_height = height; + this->area_updated_cb = area_updated_cb; + this->data = data; } -GdkPixbuf* image_loader_j2k_get_pixbuf(gpointer loader) +GdkPixbuf *ImageLoaderJ2K::get_pixbuf() { - auto ld = static_cast(loader); - return ld->pixbuf; + return pixbuf; } -gchar* image_loader_j2k_get_format_name(gpointer) +gchar *ImageLoaderJ2K::get_format_name() { return g_strdup("j2k"); } -gchar** image_loader_j2k_get_format_mime_types(gpointer) +gchar **ImageLoaderJ2K::get_format_mime_types() { static const gchar *mime[] = {"image/jp2", nullptr}; return g_strdupv(const_cast(mime)); } -gboolean image_loader_j2k_close(gpointer, GError **) -{ - return TRUE; -} - -void image_loader_j2k_abort(gpointer loader) -{ - auto ld = static_cast(loader); - ld->abort = TRUE; -} - -void image_loader_j2k_free(gpointer loader) +ImageLoaderJ2K::~ImageLoaderJ2K() { - auto ld = static_cast(loader); - if (ld->pixbuf) g_object_unref(ld->pixbuf); - g_free(ld); + if (pixbuf) g_object_unref(pixbuf); } } // namespace -void image_loader_backend_set_j2k(ImageLoaderBackend *funcs) +std::unique_ptr get_image_loader_backend_j2k() { - funcs->loader_new = image_loader_j2k_new; - funcs->set_size = image_loader_j2k_set_size; - funcs->write = image_loader_j2k_write; - funcs->get_pixbuf = image_loader_j2k_get_pixbuf; - funcs->close = image_loader_j2k_close; - funcs->abort = image_loader_j2k_abort; - funcs->free = image_loader_j2k_free; - funcs->get_format_name = image_loader_j2k_get_format_name; - funcs->get_format_mime_types = image_loader_j2k_get_format_mime_types; + return std::make_unique(); } #endif diff --git a/src/image-load-j2k.h b/src/image-load-j2k.h index 454eaa2e..f0416b37 100644 --- a/src/image-load-j2k.h +++ b/src/image-load-j2k.h @@ -24,9 +24,11 @@ #include #if HAVE_J2K +#include + struct ImageLoaderBackend; -void image_loader_backend_set_j2k(ImageLoaderBackend *funcs); +std::unique_ptr get_image_loader_backend_j2k(); #endif #endif diff --git a/src/image-load-jpeg.cc b/src/image-load-jpeg.cc index 07f471fc..8573bc22 100644 --- a/src/image-load-jpeg.cc +++ b/src/image-load-jpeg.cc @@ -48,27 +48,11 @@ #include "jpeg-parser.h" #include "typedefs.h" -struct ImageLoaderJpeg { - ImageLoaderBackendCbAreaUpdated area_updated_cb; - ImageLoaderBackendCbSize size_cb; - ImageLoaderBackendCbAreaPrepared area_prepared_cb; - - gpointer data; - - GdkPixbuf *pixbuf; - guint requested_width; - guint requested_height; - - gboolean abort; - gboolean stereo; - -}; - /* error handler data */ struct error_handler_data { struct jpeg_error_mgr pub; sigjmp_buf setjmp_buffer; - GError **error; + GError **error; }; /* explode gray image data from jpeg library into rgb components in pixbuf */ @@ -146,15 +130,12 @@ convert_cmyk_to_rgb (struct jpeg_decompress_struct *cinfo, } -static gpointer image_loader_jpeg_new(ImageLoaderBackendCbAreaUpdated area_updated_cb, ImageLoaderBackendCbSize size_cb, ImageLoaderBackendCbAreaPrepared area_prepared_cb, gpointer data) +void ImageLoaderJpeg::init(AreaUpdatedCb area_updated_cb, SizePreparedCb size_prepared_cb, AreaPreparedCb area_prepared_cb, gpointer data) { - auto loader = g_new0(ImageLoaderJpeg, 1); - - loader->area_updated_cb = area_updated_cb; - loader->size_cb = size_cb; - loader->area_prepared_cb = area_prepared_cb; - loader->data = data; - return loader; + this->area_updated_cb = area_updated_cb; + this->size_prepared_cb = size_prepared_cb; + this->area_prepared_cb = area_prepared_cb; + this->data = data; } static void @@ -270,9 +251,8 @@ static void set_mem_src (j_decompress_ptr cinfo, void* buffer, long nbytes) } -gboolean image_loader_jpeg_write(gpointer loader, const guchar *buf, gsize &chunk_size, gsize count, GError **error) +gboolean ImageLoaderJpeg::write(const guchar *buf, gsize &chunk_size, gsize count, GError **error) { - auto lj = static_cast(loader); struct jpeg_decompress_struct cinfo; struct jpeg_decompress_struct cinfo2; guchar *dptr; @@ -283,7 +263,7 @@ gboolean image_loader_jpeg_write(gpointer loader, const guchar *buf, gsize &chun struct error_handler_data jerr; - lj->stereo = FALSE; + stereo = FALSE; MPOData *mpo = jpeg_get_mpo_data(buf, count); if (mpo && mpo->num_images > 1) @@ -311,7 +291,7 @@ gboolean image_loader_jpeg_write(gpointer loader, const guchar *buf, gsize &chun if (idx1 >= 0 && idx2 >= 0) { - lj->stereo = TRUE; + stereo = TRUE; stereo_buf2 = const_cast(buf) + mpo->images[idx2].offset; stereo_length = mpo->images[idx2].length; buf = const_cast(buf) + mpo->images[idx1].offset; @@ -322,7 +302,7 @@ gboolean image_loader_jpeg_write(gpointer loader, const guchar *buf, gsize &chun /* setup error handler */ cinfo.err = jpeg_std_error (&jerr.pub); - if (lj->stereo) cinfo2.err = jpeg_std_error (&jerr.pub); + if (stereo) cinfo2.err = jpeg_std_error (&jerr.pub); jerr.pub.error_exit = fatal_error_handler; jerr.pub.output_message = output_message_handler; @@ -335,7 +315,7 @@ gboolean image_loader_jpeg_write(gpointer loader, const guchar *buf, gsize &chun * We need to clean up the JPEG object, close the input file, and return. */ jpeg_destroy_decompress(&cinfo); - if (lj->stereo) jpeg_destroy_decompress(&cinfo2); + if (stereo) jpeg_destroy_decompress(&cinfo2); return FALSE; } @@ -346,7 +326,7 @@ gboolean image_loader_jpeg_write(gpointer loader, const guchar *buf, gsize &chun jpeg_read_header(&cinfo, TRUE); - if (lj->stereo) + if (stereo) { jpeg_create_decompress(&cinfo2); set_mem_src(&cinfo2, stereo_buf2, stereo_length); @@ -357,26 +337,25 @@ gboolean image_loader_jpeg_write(gpointer loader, const guchar *buf, gsize &chun { DEBUG_1("stereo data with different size"); jpeg_destroy_decompress(&cinfo2); - lj->stereo = FALSE; + stereo = FALSE; } } - - lj->requested_width = lj->stereo ? cinfo.image_width * 2: cinfo.image_width; - lj->requested_height = cinfo.image_height; - lj->size_cb(loader, lj->requested_width, lj->requested_height, lj->data); + requested_width = stereo ? cinfo.image_width * 2: cinfo.image_width; + requested_height = cinfo.image_height; + size_prepared_cb(nullptr, requested_width, requested_height, data); cinfo.scale_num = 1; for (cinfo.scale_denom = 2; cinfo.scale_denom <= 8; cinfo.scale_denom *= 2) { jpeg_calc_output_dimensions(&cinfo); - if (cinfo.output_width < (lj->stereo ? lj->requested_width / 2 : lj->requested_width) || cinfo.output_height < lj->requested_height) { + if (cinfo.output_width < (stereo ? requested_width / 2 : requested_width) || cinfo.output_height < requested_height) { cinfo.scale_denom /= 2; break; } } jpeg_calc_output_dimensions(&cinfo); - if (lj->stereo) + if (stereo) { cinfo2.scale_num = cinfo.scale_num; cinfo2.scale_denom = cinfo.scale_denom; @@ -388,7 +367,7 @@ gboolean image_loader_jpeg_write(gpointer loader, const guchar *buf, gsize &chun jpeg_start_decompress(&cinfo); - if (lj->stereo) + if (stereo) { if (cinfo.output_width != cinfo2.output_width || cinfo.output_height != cinfo2.output_height || @@ -396,45 +375,45 @@ gboolean image_loader_jpeg_write(gpointer loader, const guchar *buf, gsize &chun { DEBUG_1("stereo data with different output size"); jpeg_destroy_decompress(&cinfo2); - lj->stereo = FALSE; + stereo = FALSE; } } - lj->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, + pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, cinfo.out_color_components == 4 ? TRUE : FALSE, - 8, lj->stereo ? cinfo.output_width * 2: cinfo.output_width, cinfo.output_height); + 8, stereo ? cinfo.output_width * 2: cinfo.output_width, cinfo.output_height); - if (!lj->pixbuf) + if (!pixbuf) { jpeg_destroy_decompress (&cinfo); - if (lj->stereo) jpeg_destroy_decompress (&cinfo2); + if (stereo) jpeg_destroy_decompress (&cinfo2); return FALSE; } - if (lj->stereo) g_object_set_data(G_OBJECT(lj->pixbuf), "stereo_data", GINT_TO_POINTER(STEREO_PIXBUF_CROSS)); - lj->area_prepared_cb(loader, lj->data); + if (stereo) g_object_set_data(G_OBJECT(pixbuf), "stereo_data", GINT_TO_POINTER(STEREO_PIXBUF_CROSS)); + area_prepared_cb(nullptr, data); - rowstride = gdk_pixbuf_get_rowstride(lj->pixbuf); - dptr = gdk_pixbuf_get_pixels(lj->pixbuf); - dptr2 = gdk_pixbuf_get_pixels(lj->pixbuf) + ((cinfo.out_color_components == 4) ? 4 * cinfo.output_width : 3 * cinfo.output_width); + rowstride = gdk_pixbuf_get_rowstride(pixbuf); + dptr = gdk_pixbuf_get_pixels(pixbuf); + dptr2 = gdk_pixbuf_get_pixels(pixbuf) + ((cinfo.out_color_components == 4) ? 4 * cinfo.output_width : 3 * cinfo.output_width); - while (cinfo.output_scanline < cinfo.output_height && !lj->abort) + while (cinfo.output_scanline < cinfo.output_height && !aborted) { guint scanline = cinfo.output_scanline; image_loader_jpeg_read_scanline(&cinfo, &dptr, rowstride); - lj->area_updated_cb(loader, 0, scanline, cinfo.output_width, cinfo.rec_outbuf_height, lj->data); - if (lj->stereo) + area_updated_cb(nullptr, 0, scanline, cinfo.output_width, cinfo.rec_outbuf_height, data); + if (stereo) { guint scanline = cinfo2.output_scanline; image_loader_jpeg_read_scanline(&cinfo2, &dptr2, rowstride); - lj->area_updated_cb(loader, cinfo.output_width, scanline, cinfo2.output_width, cinfo2.rec_outbuf_height, lj->data); + area_updated_cb(nullptr, cinfo.output_width, scanline, cinfo2.output_width, cinfo2.rec_outbuf_height, data); } } jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); - if (lj->stereo) + if (stereo) { jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); @@ -444,63 +423,43 @@ gboolean image_loader_jpeg_write(gpointer loader, const guchar *buf, gsize &chun return TRUE; } -static void image_loader_jpeg_set_size(gpointer loader, int width, int height) +void ImageLoaderJpeg::set_size(int width, int height) { - auto lj = static_cast(loader); - lj->requested_width = width; - lj->requested_height = height; + requested_width = width; + requested_height = height; } -static GdkPixbuf* image_loader_jpeg_get_pixbuf(gpointer loader) +GdkPixbuf *ImageLoaderJpeg::get_pixbuf() { - auto lj = static_cast(loader); - return lj->pixbuf; + return pixbuf; } -static gchar* image_loader_jpeg_get_format_name(gpointer) +gchar *ImageLoaderJpeg::get_format_name() { return g_strdup("jpeg"); } -static gchar** image_loader_jpeg_get_format_mime_types(gpointer) +gchar **ImageLoaderJpeg::get_format_mime_types() { static const gchar *mime[] = {"image/jpeg", nullptr}; return g_strdupv(const_cast(mime)); } -static gboolean image_loader_jpeg_close(gpointer, GError **) -{ - return TRUE; -} - -static void image_loader_jpeg_abort(gpointer loader) +void ImageLoaderJpeg::abort() { - auto lj = static_cast(loader); - lj->abort = TRUE; + aborted = TRUE; } -static void image_loader_jpeg_free(gpointer loader) +ImageLoaderJpeg::~ImageLoaderJpeg() { - auto lj = static_cast(loader); - if (lj->pixbuf) g_object_unref(lj->pixbuf); - g_free(lj); + if (pixbuf) g_object_unref(pixbuf); } -void image_loader_backend_set_jpeg(ImageLoaderBackend *funcs) +std::unique_ptr get_image_loader_backend_jpeg() { - funcs->loader_new = image_loader_jpeg_new; - funcs->set_size = image_loader_jpeg_set_size; - funcs->write = image_loader_jpeg_write; - funcs->get_pixbuf = image_loader_jpeg_get_pixbuf; - funcs->close = image_loader_jpeg_close; - funcs->abort = image_loader_jpeg_abort; - funcs->free = image_loader_jpeg_free; - - funcs->get_format_name = image_loader_jpeg_get_format_name; - funcs->get_format_mime_types = image_loader_jpeg_get_format_mime_types; + return std::make_unique(); } - #endif /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff --git a/src/image-load-jpeg.h b/src/image-load-jpeg.h index e60790da..8bb5091c 100644 --- a/src/image-load-jpeg.h +++ b/src/image-load-jpeg.h @@ -25,13 +25,42 @@ #include #if HAVE_JPEG +#include + +#include #include -struct ImageLoaderBackend; +#include "image-load.h" + +struct ImageLoaderJpeg : public ImageLoaderBackend +{ +public: + ~ImageLoaderJpeg() override; + + void init(AreaUpdatedCb area_updated_cb, SizePreparedCb size_prepared_cb, AreaPreparedCb area_prepared_cb, gpointer data) override; + void set_size(int width, int height) override; + gboolean write(const guchar *buf, gsize &chunk_size, gsize count, GError **error) override; + GdkPixbuf *get_pixbuf() override; + void abort() override; + gchar *get_format_name() override; + gchar **get_format_mime_types() override; + +private: + AreaUpdatedCb area_updated_cb; + SizePreparedCb size_prepared_cb; + AreaPreparedCb area_prepared_cb; + + gpointer data; + + GdkPixbuf *pixbuf; + guint requested_width; + guint requested_height; -gboolean image_loader_jpeg_write(gpointer loader, const guchar *buf, gsize &chunk_size, gsize count, GError **error); + gboolean aborted; + gboolean stereo; +}; -void image_loader_backend_set_jpeg(ImageLoaderBackend *funcs); +std::unique_ptr get_image_loader_backend_jpeg(); #endif #endif diff --git a/src/image-load-jpegxl.cc b/src/image-load-jpegxl.cc index 36ef7036..8d4ed3b0 100644 --- a/src/image-load-jpegxl.cc +++ b/src/image-load-jpegxl.cc @@ -73,15 +73,22 @@ namespace { -struct ImageLoaderJPEGXL { - ImageLoaderBackendCbAreaUpdated area_updated_cb; - ImageLoaderBackendCbSize size_cb; - ImageLoaderBackendCbAreaPrepared area_prepared_cb; +struct ImageLoaderJPEGXL : public ImageLoaderBackend +{ +public: + ~ImageLoaderJPEGXL() override; + + void init(AreaUpdatedCb area_updated_cb, SizePreparedCb size_prepared_cb, AreaPreparedCb area_prepared_cb, gpointer data) override; + gboolean write(const guchar *buf, gsize &chunk_size, gsize count, GError **error) override; + GdkPixbuf *get_pixbuf() override; + gchar *get_format_name() override; + gchar **get_format_mime_types() override; + +private: + AreaUpdatedCb area_updated_cb; gpointer data; + GdkPixbuf *pixbuf; - guint requested_width; - guint requested_height; - gboolean abort; }; void free_buffer(guchar *pixels, gpointer) @@ -172,22 +179,21 @@ uint8_t *JxlMemoryToPixels(const uint8_t *next_in, size_t size, size_t &xsize, s return nullptr; } -gboolean image_loader_jpegxl_write(gpointer loader, const guchar *buf, gsize &chunk_size, gsize count, GError **) +gboolean ImageLoaderJPEGXL::write(const guchar *buf, gsize &chunk_size, gsize count, GError **) { - auto ld = static_cast(loader); gboolean ret = FALSE; size_t xsize; size_t ysize; size_t stride; - uint8_t *decoded = nullptr; + uint8_t *pixels = nullptr; - decoded = JxlMemoryToPixels(buf, count, xsize, ysize, stride); + pixels = JxlMemoryToPixels(buf, count, xsize, ysize, stride); - if (decoded) + if (pixels) { - ld->pixbuf = gdk_pixbuf_new_from_data(decoded, GDK_COLORSPACE_RGB, TRUE, 8, xsize, ysize, stride, free_buffer, nullptr); + pixbuf = gdk_pixbuf_new_from_data(pixels, GDK_COLORSPACE_RGB, TRUE, 8, xsize, ysize, stride, free_buffer, nullptr); - ld->area_updated_cb(loader, 0, 0, xsize, ysize, ld->data); + area_updated_cb(nullptr, 0, 0, xsize, ysize, data); chunk_size = count; ret = TRUE; @@ -196,71 +202,38 @@ gboolean image_loader_jpegxl_write(gpointer loader, const guchar *buf, gsize &ch return ret; } -gpointer image_loader_jpegxl_new(ImageLoaderBackendCbAreaUpdated area_updated_cb, ImageLoaderBackendCbSize size_cb, ImageLoaderBackendCbAreaPrepared area_prepared_cb, gpointer data) -{ - auto loader = g_new0(ImageLoaderJPEGXL, 1); - loader->area_updated_cb = area_updated_cb; - loader->size_cb = size_cb; - loader->area_prepared_cb = area_prepared_cb; - loader->data = data; - return loader; -} - -void image_loader_jpegxl_set_size(gpointer loader, int width, int height) +void ImageLoaderJPEGXL::init(AreaUpdatedCb area_updated_cb, SizePreparedCb, AreaPreparedCb, gpointer data) { - auto ld = static_cast(loader); - ld->requested_width = width; - ld->requested_height = height; + this->area_updated_cb = area_updated_cb; + this->data = data; } -GdkPixbuf* image_loader_jpegxl_get_pixbuf(gpointer loader) +GdkPixbuf *ImageLoaderJPEGXL::get_pixbuf() { - auto ld = static_cast(loader); - return ld->pixbuf; + return pixbuf; } -gchar* image_loader_jpegxl_get_format_name(gpointer) +gchar *ImageLoaderJPEGXL::get_format_name() { return g_strdup("jxl"); } -gchar** image_loader_jpegxl_get_format_mime_types(gpointer) +gchar **ImageLoaderJPEGXL::get_format_mime_types() { static const gchar *mime[] = {"image/jxl", nullptr}; return g_strdupv(const_cast(mime)); } -gboolean image_loader_jpegxl_close(gpointer, GError **) -{ - return TRUE; -} - -void image_loader_jpegxl_abort(gpointer loader) -{ - auto ld = static_cast(loader); - ld->abort = TRUE; -} - -void image_loader_jpegxl_free(gpointer loader) +ImageLoaderJPEGXL::~ImageLoaderJPEGXL() { - auto ld = static_cast(loader); - if (ld->pixbuf) g_object_unref(ld->pixbuf); - g_free(ld); + if (pixbuf) g_object_unref(pixbuf); } } // namespace -void image_loader_backend_set_jpegxl(ImageLoaderBackend *funcs) +std::unique_ptr get_image_loader_backend_jpegxl() { - funcs->loader_new = image_loader_jpegxl_new; - funcs->set_size = image_loader_jpegxl_set_size; - funcs->write = image_loader_jpegxl_write; - funcs->get_pixbuf = image_loader_jpegxl_get_pixbuf; - funcs->close = image_loader_jpegxl_close; - funcs->abort = image_loader_jpegxl_abort; - funcs->free = image_loader_jpegxl_free; - funcs->get_format_name = image_loader_jpegxl_get_format_name; - funcs->get_format_mime_types = image_loader_jpegxl_get_format_mime_types; + return std::make_unique(); } #endif diff --git a/src/image-load-jpegxl.h b/src/image-load-jpegxl.h index b406f5fd..071725d4 100644 --- a/src/image-load-jpegxl.h +++ b/src/image-load-jpegxl.h @@ -24,9 +24,11 @@ #include #if HAVE_JPEGXL +#include + struct ImageLoaderBackend; -void image_loader_backend_set_jpegxl(ImageLoaderBackend *funcs); +std::unique_ptr get_image_loader_backend_jpegxl(); #endif #endif diff --git a/src/image-load-pdf.cc b/src/image-load-pdf.cc index 6dd3cc12..263a368a 100644 --- a/src/image-load-pdf.cc +++ b/src/image-load-pdf.cc @@ -36,22 +36,30 @@ namespace { -struct ImageLoaderPDF { - ImageLoaderBackendCbAreaUpdated area_updated_cb; - ImageLoaderBackendCbSize size_cb; - ImageLoaderBackendCbAreaPrepared area_prepared_cb; +struct ImageLoaderPDF : public ImageLoaderBackend +{ +public: + ~ImageLoaderPDF() override; + + void init(AreaUpdatedCb area_updated_cb, SizePreparedCb size_prepared_cb, AreaPreparedCb area_prepared_cb, gpointer data) override; + gboolean write(const guchar *buf, gsize &chunk_size, gsize count, GError **error) override; + GdkPixbuf *get_pixbuf() override; + gchar *get_format_name() override; + gchar **get_format_mime_types() override; + void set_page_num(gint page_num) override; + gint get_page_total() override; + +private: + AreaUpdatedCb area_updated_cb; gpointer data; + GdkPixbuf *pixbuf; - guint requested_width; - guint requested_height; - gboolean abort; gint page_num; gint page_total; }; -gboolean image_loader_pdf_write(gpointer loader, const guchar *buf, gsize &chunk_size, gsize count, GError **) +gboolean ImageLoaderPDF::write(const guchar *buf, gsize &chunk_size, gsize count, GError **) { - auto ld = static_cast(loader); GError *poppler_error = nullptr; PopplerPage *page; PopplerDocument *document; @@ -79,10 +87,10 @@ gboolean image_loader_pdf_write(gpointer loader, const guchar *buf, gsize &chunk page_total = poppler_document_get_n_pages(document); if (page_total > 0) { - ld->page_total = page_total; + this->page_total = page_total; } - page = poppler_document_get_page(document, ld->page_num); + page = poppler_document_get_page(document, page_num); poppler_page_get_size(page, &width, &height); surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); @@ -93,8 +101,8 @@ gboolean image_loader_pdf_write(gpointer loader, const guchar *buf, gsize &chunk cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); cairo_paint(cr); - ld->pixbuf = gdk_pixbuf_get_from_surface(surface, 0, 0, width, height); - ld->area_updated_cb(loader, 0, 0, width, height, ld->data); + pixbuf = gdk_pixbuf_get_from_surface(surface, 0, 0, width, height); + area_updated_cb(nullptr, 0, 0, width, height, data); cairo_destroy (cr); cairo_surface_destroy(surface); @@ -111,88 +119,49 @@ gboolean image_loader_pdf_write(gpointer loader, const guchar *buf, gsize &chunk return ret; } -gpointer image_loader_pdf_new(ImageLoaderBackendCbAreaUpdated area_updated_cb, ImageLoaderBackendCbSize size_cb, ImageLoaderBackendCbAreaPrepared area_prepared_cb, gpointer data) +void ImageLoaderPDF::init(AreaUpdatedCb area_updated_cb, SizePreparedCb, AreaPreparedCb, gpointer data) { - auto loader = g_new0(ImageLoaderPDF, 1); - loader->area_updated_cb = area_updated_cb; - loader->size_cb = size_cb; - loader->area_prepared_cb = area_prepared_cb; - loader->data = data; - loader->page_num = 0; - return loader; + this->area_updated_cb = area_updated_cb; + this->data = data; + page_num = 0; } -void image_loader_pdf_set_size(gpointer loader, int width, int height) +GdkPixbuf *ImageLoaderPDF::get_pixbuf() { - auto ld = static_cast(loader); - ld->requested_width = width; - ld->requested_height = height; + return pixbuf; } -GdkPixbuf* image_loader_pdf_get_pixbuf(gpointer loader) -{ - auto ld = static_cast(loader); - return ld->pixbuf; -} - -gchar* image_loader_pdf_get_format_name(gpointer) +gchar *ImageLoaderPDF::get_format_name() { return g_strdup("pdf"); } -gchar** image_loader_pdf_get_format_mime_types(gpointer) +gchar **ImageLoaderPDF::get_format_mime_types() { static const gchar *mime[] = {"application/pdf", nullptr}; return g_strdupv(const_cast(mime)); } -void image_loader_pdf_set_page_num(gpointer loader, gint page_num) -{ - auto ld = static_cast(loader); - - ld->page_num = page_num; -} - -gint image_loader_pdf_get_page_total(gpointer loader) -{ - auto ld = static_cast(loader); - - return ld->page_total; -} - -gboolean image_loader_pdf_close(gpointer, GError **) +void ImageLoaderPDF::set_page_num(gint page_num) { - return TRUE; + this->page_num = page_num; } -void image_loader_pdf_abort(gpointer loader) +gint ImageLoaderPDF::get_page_total() { - auto ld = static_cast(loader); - ld->abort = TRUE; + return page_total; } -void image_loader_pdf_free(gpointer loader) +ImageLoaderPDF::~ImageLoaderPDF() { - auto ld = static_cast(loader); - if (ld->pixbuf) g_object_unref(ld->pixbuf); - g_free(ld); + if (pixbuf) g_object_unref(pixbuf); } } // namespace -void image_loader_backend_set_pdf(ImageLoaderBackend *funcs) +std::unique_ptr get_image_loader_backend_pdf() { - funcs->loader_new = image_loader_pdf_new; - funcs->set_size = image_loader_pdf_set_size; - funcs->write = image_loader_pdf_write; - funcs->get_pixbuf = image_loader_pdf_get_pixbuf; - funcs->close = image_loader_pdf_close; - funcs->abort = image_loader_pdf_abort; - funcs->free = image_loader_pdf_free; - funcs->get_format_name = image_loader_pdf_get_format_name; - funcs->get_format_mime_types = image_loader_pdf_get_format_mime_types; - funcs->set_page_num = image_loader_pdf_set_page_num; - funcs->get_page_total = image_loader_pdf_get_page_total; + return std::make_unique(); } #endif diff --git a/src/image-load-pdf.h b/src/image-load-pdf.h index 86f11fac..052e5b27 100644 --- a/src/image-load-pdf.h +++ b/src/image-load-pdf.h @@ -24,9 +24,11 @@ #include #if HAVE_PDF +#include + struct ImageLoaderBackend; -void image_loader_backend_set_pdf(ImageLoaderBackend *funcs); +std::unique_ptr get_image_loader_backend_pdf(); #endif #endif diff --git a/src/image-load-psd.cc b/src/image-load-psd.cc index 8ced9daf..8b27383b 100644 --- a/src/image-load-psd.cc +++ b/src/image-load-psd.cc @@ -62,15 +62,22 @@ namespace { -struct ImageLoaderPSD { - ImageLoaderBackendCbAreaUpdated area_updated_cb; - ImageLoaderBackendCbSize size_cb; - ImageLoaderBackendCbAreaPrepared area_prepared_cb; +struct ImageLoaderPSD : public ImageLoaderBackend +{ +public: + ~ImageLoaderPSD() override; + + void init(AreaUpdatedCb area_updated_cb, SizePreparedCb size_prepared_cb, AreaPreparedCb area_prepared_cb, gpointer data) override; + gboolean write(const guchar *buf, gsize &chunk_size, gsize count, GError **error) override; + GdkPixbuf *get_pixbuf() override; + gchar *get_format_name() override; + gchar **get_format_mime_types() override; + +private: + AreaUpdatedCb area_updated_cb; gpointer data; + GdkPixbuf *pixbuf; - guint requested_width; - guint requested_height; - gboolean abort; }; struct PsdHeader @@ -123,8 +130,8 @@ struct PsdContext { PsdReadState state; - GdkPixbuf* pixbuf; - gpointer user_data; + GdkPixbuf* pixbuf; + gpointer user_data; guchar* buffer; guint bytes_read; @@ -299,9 +306,8 @@ void free_context(PsdContext *ctx) g_free(ctx); } -gboolean image_loader_psd_write(gpointer loader, const guchar *buf, gsize &chunk_size, gsize count, GError **) +gboolean ImageLoaderPSD::write(const guchar *buf, gsize &chunk_size, gsize count, GError **) { - auto ld = static_cast(loader); auto ctx = g_new0(PsdContext, 1); guint i; guint32 j; @@ -529,8 +535,8 @@ gboolean image_loader_psd_write(gpointer loader, const guchar *buf, gsize &chunk } } ctx->finalized = TRUE; - ld->pixbuf = ctx->pixbuf; - ld->area_updated_cb(loader, 0, 0, ctx->width, ctx->height, ld->data); + pixbuf = ctx->pixbuf; + area_updated_cb(nullptr, 0, 0, ctx->width, ctx->height, data); free_context(ctx); chunk_size = count; @@ -543,70 +549,37 @@ gboolean image_loader_psd_write(gpointer loader, const guchar *buf, gsize &chunk /* ------- Geeqie ------------ */ -gpointer image_loader_psd_new(ImageLoaderBackendCbAreaUpdated area_updated_cb, ImageLoaderBackendCbSize size_cb, ImageLoaderBackendCbAreaPrepared area_prepared_cb, gpointer data) -{ - auto loader = g_new0(ImageLoaderPSD, 1); - loader->area_updated_cb = area_updated_cb; - loader->size_cb = size_cb; - loader->area_prepared_cb = area_prepared_cb; - loader->data = data; - return loader; -} - -void image_loader_psd_set_size(gpointer loader, int width, int height) +void ImageLoaderPSD::init(AreaUpdatedCb area_updated_cb, SizePreparedCb, AreaPreparedCb, gpointer data) { - auto ld = static_cast(loader); - ld->requested_width = width; - ld->requested_height = height; + this->area_updated_cb = area_updated_cb; + this->data = data; } -GdkPixbuf* image_loader_psd_get_pixbuf(gpointer loader) +GdkPixbuf *ImageLoaderPSD::get_pixbuf() { - auto ld = static_cast(loader); - return ld->pixbuf; + return pixbuf; } -gchar* image_loader_psd_get_format_name(gpointer) +gchar *ImageLoaderPSD::get_format_name() { return g_strdup("psd"); } -gchar** image_loader_psd_get_format_mime_types(gpointer) +gchar **ImageLoaderPSD::get_format_mime_types() { static const gchar *mime[] = {"application/psd", nullptr}; return g_strdupv(const_cast(mime)); } -gboolean image_loader_psd_close(gpointer, GError **) -{ - return TRUE; -} - -void image_loader_psd_abort(gpointer loader) -{ - auto ld = static_cast(loader); - ld->abort = TRUE; -} - -void image_loader_psd_free(gpointer loader) +ImageLoaderPSD::~ImageLoaderPSD() { - auto ld = static_cast(loader); - if (ld->pixbuf) g_object_unref(ld->pixbuf); - g_free(ld); + if (pixbuf) g_object_unref(pixbuf); } } // namespace -void image_loader_backend_set_psd(ImageLoaderBackend *funcs) +std::unique_ptr get_image_loader_backend_psd() { - funcs->loader_new = image_loader_psd_new; - funcs->set_size = image_loader_psd_set_size; - funcs->write = image_loader_psd_write; - funcs->get_pixbuf = image_loader_psd_get_pixbuf; - funcs->close = image_loader_psd_close; - funcs->abort = image_loader_psd_abort; - funcs->free = image_loader_psd_free; - funcs->get_format_name = image_loader_psd_get_format_name; - funcs->get_format_mime_types = image_loader_psd_get_format_mime_types; + return std::make_unique(); } /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff --git a/src/image-load-psd.h b/src/image-load-psd.h index 5f6cd6cd..3760f6c8 100644 --- a/src/image-load-psd.h +++ b/src/image-load-psd.h @@ -21,9 +21,11 @@ #ifndef IMAGE_LOAD_PSD_H #define IMAGE_LOAD_PSD_H +#include + struct ImageLoaderBackend; -void image_loader_backend_set_psd(ImageLoaderBackend *funcs); +std::unique_ptr get_image_loader_backend_psd(); #endif /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff --git a/src/image-load-svgz.cc b/src/image-load-svgz.cc index a94af709..df134601 100644 --- a/src/image-load-svgz.cc +++ b/src/image-load-svgz.cc @@ -29,63 +29,80 @@ namespace { -gchar* image_loader_svgz_get_format_name(gpointer) +struct ImageLoaderSvgz : public ImageLoaderBackend +{ +public: + ~ImageLoaderSvgz() override; + + void init(AreaUpdatedCb area_updated_cb, SizePreparedCb size_prepared_cb, AreaPreparedCb area_prepared_cb, gpointer data) override; + void set_size(int width, int height) override; + gboolean write(const guchar *buf, gsize &chunk_size, gsize count, GError **error) override; + GdkPixbuf *get_pixbuf() override; + gboolean close(GError **error) override; + gchar *get_format_name() override; + gchar **get_format_mime_types() override; + +private: + GdkPixbufLoader *loader; +}; + +gchar *ImageLoaderSvgz::get_format_name() { return g_strdup("svg"); - } -gchar** image_loader_svgz_get_format_mime_types(gpointer) +gchar **ImageLoaderSvgz::get_format_mime_types() { static const gchar *mime[] = {"image/svg", nullptr}; return g_strdupv(const_cast(mime)); } -gpointer image_loader_svgz_new(ImageLoaderBackendCbAreaUpdated area_updated_cb, ImageLoaderBackendCbSize size_cb, ImageLoaderBackendCbAreaPrepared area_prepared_cb, gpointer data) +void ImageLoaderSvgz::init(AreaUpdatedCb area_updated_cb, SizePreparedCb size_prepared_cb, AreaPreparedCb area_prepared_cb, gpointer data) { GError *error = nullptr; - GdkPixbufLoader *loader = gdk_pixbuf_loader_new_with_mime_type("image/svg", &error); + loader = gdk_pixbuf_loader_new_with_mime_type("image/svg", &error); if (error) { g_error_free(error); - return nullptr; + return; } g_signal_connect(G_OBJECT(loader), "area_updated", G_CALLBACK(area_updated_cb), data); - g_signal_connect(G_OBJECT(loader), "size_prepared", G_CALLBACK(size_cb), data); + g_signal_connect(G_OBJECT(loader), "size_prepared", G_CALLBACK(size_prepared_cb), data); g_signal_connect(G_OBJECT(loader), "area_prepared", G_CALLBACK(area_prepared_cb), data); - return loader; } -gboolean image_loader_svgz_write(gpointer loader, const guchar *buf, gsize &chunk_size, gsize, GError **error) +void ImageLoaderSvgz::set_size(int width, int height) +{ + gdk_pixbuf_loader_set_size(loader, width, height); +} + +gboolean ImageLoaderSvgz::write(const guchar *buf, gsize &chunk_size, gsize, GError **error) +{ + return gdk_pixbuf_loader_write(loader, buf, chunk_size, error); +} + +GdkPixbuf *ImageLoaderSvgz::get_pixbuf() { - return gdk_pixbuf_loader_write(GDK_PIXBUF_LOADER(loader), buf, chunk_size, error); + return gdk_pixbuf_loader_get_pixbuf(loader); } -void image_loader_svgz_abort(gpointer) +gboolean ImageLoaderSvgz::close(GError **error) { + return gdk_pixbuf_loader_close(loader, error); } -void image_loader_svgz_free(gpointer loader) +ImageLoaderSvgz::~ImageLoaderSvgz() { g_object_unref(G_OBJECT(loader)); } } // namespace -void image_loader_backend_set_svgz(ImageLoaderBackend *funcs) +std::unique_ptr get_image_loader_backend_svgz() { - funcs->loader_new = image_loader_svgz_new; - funcs->set_size = reinterpret_cast(gdk_pixbuf_loader_set_size); - funcs->write = image_loader_svgz_write; - funcs->get_pixbuf = reinterpret_cast(gdk_pixbuf_loader_get_pixbuf); - funcs->close = reinterpret_cast(gdk_pixbuf_loader_close); - funcs->abort = image_loader_svgz_abort; - funcs->free = image_loader_svgz_free; - - funcs->get_format_name = image_loader_svgz_get_format_name; - funcs->get_format_mime_types = image_loader_svgz_get_format_mime_types; + return std::make_unique(); } /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff --git a/src/image-load-svgz.h b/src/image-load-svgz.h index 3bcc1ede..c994257c 100644 --- a/src/image-load-svgz.h +++ b/src/image-load-svgz.h @@ -21,9 +21,11 @@ #ifndef IMAGE_LOAD_SVGZ_H #define IMAGE_LOAD_SVGZ_H +#include + struct ImageLoaderBackend; -void image_loader_backend_set_svgz(ImageLoaderBackend *funcs); +std::unique_ptr get_image_loader_backend_svgz(); #endif diff --git a/src/image-load-tiff.cc b/src/image-load-tiff.cc index 1b5ef7bc..263f01a0 100644 --- a/src/image-load-tiff.cc +++ b/src/image-load-tiff.cc @@ -47,24 +47,42 @@ namespace { -struct ImageLoaderTiff { - ImageLoaderBackendCbAreaUpdated area_updated_cb; - ImageLoaderBackendCbSize size_cb; - ImageLoaderBackendCbAreaPrepared area_prepared_cb; - +struct ImageLoaderTiff : public ImageLoaderBackend +{ +public: + ~ImageLoaderTiff() override; + + void init(AreaUpdatedCb area_updated_cb, SizePreparedCb size_prepared_cb, AreaPreparedCb area_prepared_cb, gpointer data) override; + void set_size(int width, int height) override; + gboolean write(const guchar *buf, gsize &chunk_size, gsize count, GError **error) override; + GdkPixbuf *get_pixbuf() override; + void abort() override; + gchar *get_format_name() override; + gchar **get_format_mime_types() override; + void set_page_num(gint page_num) override; + gint get_page_total() override; + +private: + AreaUpdatedCb area_updated_cb; + SizePreparedCb size_prepared_cb; + AreaPreparedCb area_prepared_cb; gpointer data; GdkPixbuf *pixbuf; guint requested_width; guint requested_height; - gboolean abort; + gboolean aborted; + + gint page_num; + gint page_total; +}; +struct GqTiffContext +{ const guchar *buffer; toff_t used; toff_t pos; - gint page_num; - gint page_total; }; void free_buffer (guchar *pixels, gpointer) @@ -74,7 +92,7 @@ void free_buffer (guchar *pixels, gpointer) tsize_t tiff_load_read (thandle_t handle, tdata_t buf, tsize_t size) { - auto context = static_cast(handle); + auto context = static_cast(handle); if (context->pos + size > context->used) return 0; @@ -91,7 +109,7 @@ tsize_t tiff_load_write (thandle_t, tdata_t, tsize_t) toff_t tiff_load_seek (thandle_t handle, toff_t offset, int whence) { - auto context = static_cast(handle); + auto context = static_cast(handle); switch (whence) { @@ -124,13 +142,13 @@ int tiff_load_close (thandle_t) toff_t tiff_load_size (thandle_t handle) { - auto context = static_cast(handle); + auto context = static_cast(handle); return context->used; } int tiff_load_map_file (thandle_t handle, tdata_t *buf, toff_t *size) { - auto context = static_cast(handle); + auto context = static_cast(handle); *buf = const_cast(context->buffer); *size = context->used; @@ -142,10 +160,8 @@ void tiff_load_unmap_file (thandle_t, tdata_t, toff_t) { } -gboolean image_loader_tiff_write (gpointer loader, const guchar *buf, gsize &chunk_size, gsize count, GError **) +gboolean ImageLoaderTiff::write(const guchar *buf, gsize &chunk_size, gsize count, GError **) { - auto lt = static_cast(loader); - TIFF *tiff; guchar *pixels = nullptr; gint width; @@ -155,13 +171,10 @@ gboolean image_loader_tiff_write (gpointer loader, const guchar *buf, gsize &chu guint32 rowsperstrip; gint dircount = 0; - lt->buffer = buf; - lt->used = count; - lt->pos = 0; - TIFFSetWarningHandler(nullptr); - tiff = TIFFClientOpen ( "libtiff-geeqie", "r", lt, + GqTiffContext context{buf, count, 0}; + tiff = TIFFClientOpen ( "libtiff-geeqie", "r", &context, tiff_load_read, tiff_load_write, tiff_load_seek, tiff_load_close, tiff_load_size, @@ -176,9 +189,9 @@ gboolean image_loader_tiff_write (gpointer loader, const guchar *buf, gsize &chu dircount++; } while (TIFFReadDirectory(tiff)); - lt->page_total = dircount; + page_total = dircount; - if (!TIFFSetDirectory(tiff, lt->page_num)) + if (!TIFFSetDirectory(tiff, page_num)) { DEBUG_1("Failed to open TIFF image"); TIFFClose(tiff); @@ -222,9 +235,9 @@ gboolean image_loader_tiff_write (gpointer loader, const guchar *buf, gsize &chu return FALSE; } - lt->requested_width = width; - lt->requested_height = height; - lt->size_cb(loader, lt->requested_width, lt->requested_height, lt->data); + requested_width = width; + requested_height = height; + size_prepared_cb(nullptr, requested_width, requested_height, data); pixels = static_cast(g_try_malloc (bytes)); @@ -235,10 +248,10 @@ gboolean image_loader_tiff_write (gpointer loader, const guchar *buf, gsize &chu return FALSE; } - lt->pixbuf = gdk_pixbuf_new_from_data (pixels, GDK_COLORSPACE_RGB, TRUE, 8, + pixbuf = gdk_pixbuf_new_from_data (pixels, GDK_COLORSPACE_RGB, TRUE, 8, width, height, rowstride, free_buffer, nullptr); - if (!lt->pixbuf) + if (!pixbuf) { g_free (pixels); DEBUG_1("Insufficient memory to open TIFF file"); @@ -246,7 +259,7 @@ gboolean image_loader_tiff_write (gpointer loader, const guchar *buf, gsize &chu return FALSE; } - lt->area_prepared_cb(loader, lt->data); + area_prepared_cb(nullptr, data); if (TIFFGetField(tiff, TIFFTAG_ROWSPERSTRIP, &rowsperstrip)) { @@ -260,7 +273,7 @@ gboolean image_loader_tiff_write (gpointer loader, const guchar *buf, gsize &chu int rows_to_write; int i_row; - if (lt->abort) { + if (aborted) { break; } @@ -293,7 +306,7 @@ gboolean image_loader_tiff_write (gpointer loader, const guchar *buf, gsize &chu memcpy(top_line, bottom_line, line_bytes); memcpy(bottom_line, wrk_line, line_bytes); } - lt->area_updated_cb(loader, 0, row, width, rows_to_write, lt->data); + area_updated_cb(nullptr, 0, row, width, rows_to_write, data); } g_free(wrk_line); } @@ -327,7 +340,7 @@ gboolean image_loader_tiff_write (gpointer loader, const guchar *buf, gsize &chu } #endif - lt->area_updated_cb(loader, 0, 0, width, height, lt->data); + area_updated_cb(nullptr, 0, 0, width, height, data); } TIFFClose(tiff); @@ -336,91 +349,61 @@ gboolean image_loader_tiff_write (gpointer loader, const guchar *buf, gsize &chu } -gpointer image_loader_tiff_new(ImageLoaderBackendCbAreaUpdated area_updated_cb, ImageLoaderBackendCbSize size_cb, ImageLoaderBackendCbAreaPrepared area_prepared_cb, gpointer data) +void ImageLoaderTiff::init(AreaUpdatedCb area_updated_cb, SizePreparedCb size_prepared_cb, AreaPreparedCb area_prepared_cb, gpointer data) { - auto loader = g_new0(ImageLoaderTiff, 1); - - loader->area_updated_cb = area_updated_cb; - loader->size_cb = size_cb; - loader->area_prepared_cb = area_prepared_cb; - loader->data = data; - return loader; + this->area_updated_cb = area_updated_cb; + this->size_prepared_cb = size_prepared_cb; + this->area_prepared_cb = area_prepared_cb; + this->data = data; } - -void image_loader_tiff_set_size(gpointer loader, int width, int height) +void ImageLoaderTiff::set_size(int width, int height) { - auto lt = static_cast(loader); - lt->requested_width = width; - lt->requested_height = height; + requested_width = width; + requested_height = height; } -GdkPixbuf* image_loader_tiff_get_pixbuf(gpointer loader) +GdkPixbuf *ImageLoaderTiff::get_pixbuf() { - auto lt = static_cast(loader); - return lt->pixbuf; + return pixbuf; } -gchar* image_loader_tiff_get_format_name(gpointer) +gchar *ImageLoaderTiff::get_format_name() { return g_strdup("tiff"); } -gchar** image_loader_tiff_get_format_mime_types(gpointer) +gchar **ImageLoaderTiff::get_format_mime_types() { static const gchar *mime[] = {"image/tiff", nullptr}; return g_strdupv(const_cast(mime)); } -gboolean image_loader_tiff_close(gpointer, GError **) +void ImageLoaderTiff::abort() { - return TRUE; + aborted = TRUE; } -void image_loader_tiff_abort(gpointer loader) +ImageLoaderTiff::~ImageLoaderTiff() { - auto lt = static_cast(loader); - lt->abort = TRUE; + if (pixbuf) g_object_unref(pixbuf); } -void image_loader_tiff_free(gpointer loader) +void ImageLoaderTiff::set_page_num(gint page_num) { - auto lt = static_cast(loader); - if (lt->pixbuf) g_object_unref(lt->pixbuf); - g_free(lt); + this->page_num = page_num; } -void image_loader_tiff_set_page_num(gpointer loader, gint page_num) +gint ImageLoaderTiff::get_page_total() { - auto lt = static_cast(loader); - - lt->page_num = page_num; -} - -gint image_loader_tiff_get_page_total(gpointer loader) -{ - auto lt = static_cast(loader); - - return lt->page_total; + return page_total; } } // namespace -void image_loader_backend_set_tiff(ImageLoaderBackend *funcs) +std::unique_ptr get_image_loader_backend_tiff() { - funcs->loader_new = image_loader_tiff_new; - funcs->set_size = image_loader_tiff_set_size; - funcs->write = image_loader_tiff_write; - funcs->get_pixbuf = image_loader_tiff_get_pixbuf; - funcs->close = image_loader_tiff_close; - funcs->abort = image_loader_tiff_abort; - funcs->free = image_loader_tiff_free; - - funcs->get_format_name = image_loader_tiff_get_format_name; - funcs->get_format_mime_types = image_loader_tiff_get_format_mime_types; - - funcs->set_page_num = image_loader_tiff_set_page_num; - funcs->get_page_total = image_loader_tiff_get_page_total; + return std::make_unique(); } #endif diff --git a/src/image-load-tiff.h b/src/image-load-tiff.h index a2d8b08e..2185e77d 100644 --- a/src/image-load-tiff.h +++ b/src/image-load-tiff.h @@ -25,9 +25,11 @@ #include #if HAVE_TIFF +#include + struct ImageLoaderBackend; -void image_loader_backend_set_tiff(ImageLoaderBackend *funcs); +std::unique_ptr get_image_loader_backend_tiff(); #endif #endif diff --git a/src/image-load-webp.cc b/src/image-load-webp.cc index 780964cc..24a52d50 100644 --- a/src/image-load-webp.cc +++ b/src/image-load-webp.cc @@ -34,16 +34,22 @@ namespace { -using ImageLoaderWEBP = struct _ImageLoaderWEBP; -struct _ImageLoaderWEBP { - ImageLoaderBackendCbAreaUpdated area_updated_cb; - ImageLoaderBackendCbSize size_cb; - ImageLoaderBackendCbAreaPrepared area_prepared_cb; +struct ImageLoaderWEBP : public ImageLoaderBackend +{ +public: + ~ImageLoaderWEBP() override; + + void init(AreaUpdatedCb area_updated_cb, SizePreparedCb size_prepared_cb, AreaPreparedCb area_prepared_cb, gpointer data) override; + gboolean write(const guchar *buf, gsize &chunk_size, gsize count, GError **error) override; + GdkPixbuf *get_pixbuf() override; + gchar *get_format_name() override; + gchar **get_format_mime_types() override; + +private: + AreaUpdatedCb area_updated_cb; gpointer data; + GdkPixbuf *pixbuf; - guint requested_width; - guint requested_height; - gboolean abort; }; void free_buffer(guchar *pixels, gpointer) @@ -51,10 +57,9 @@ void free_buffer(guchar *pixels, gpointer) g_free(pixels); } -gboolean image_loader_webp_write(gpointer loader, const guchar *buf, gsize &chunk_size, gsize count, GError **) +gboolean ImageLoaderWEBP::write(const guchar *buf, gsize &chunk_size, gsize count, GError **) { - auto *ld = (ImageLoaderWEBP *) loader; - guint8* data; + guint8* pixels; gint width; gint height; gboolean res_info; @@ -77,88 +82,55 @@ gboolean image_loader_webp_write(gpointer loader, const guchar *buf, gsize &chun if (features.has_alpha) { - data = WebPDecodeRGBA(buf, count, &width, &height); + pixels = WebPDecodeRGBA(buf, count, &width, &height); } else { - data = WebPDecodeRGB(buf, count, &width, &height); + pixels = WebPDecodeRGB(buf, count, &width, &height); } - ld->pixbuf = gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB, features.has_alpha, 8, width, height, width * (features.has_alpha ? 4 : 3), free_buffer, nullptr); + pixbuf = gdk_pixbuf_new_from_data(pixels, GDK_COLORSPACE_RGB, features.has_alpha, 8, width, height, width * (features.has_alpha ? 4 : 3), free_buffer, nullptr); - ld->area_updated_cb(loader, 0, 0, width, height, ld->data); + area_updated_cb(nullptr, 0, 0, width, height, data); chunk_size = count; return TRUE; } -gpointer image_loader_webp_new(ImageLoaderBackendCbAreaUpdated area_updated_cb, ImageLoaderBackendCbSize size_cb, ImageLoaderBackendCbAreaPrepared area_prepared_cb, gpointer data) -{ - auto *loader = g_new0(ImageLoaderWEBP, 1); - loader->area_updated_cb = area_updated_cb; - loader->size_cb = size_cb; - loader->area_prepared_cb = area_prepared_cb; - loader->data = data; - - return (gpointer) loader; -} - -void image_loader_webp_set_size(gpointer loader, int width, int height) +void ImageLoaderWEBP::init(AreaUpdatedCb area_updated_cb, SizePreparedCb, AreaPreparedCb, gpointer data) { - auto *ld = (ImageLoaderWEBP *) loader; - ld->requested_width = width; - ld->requested_height = height; + this->area_updated_cb = area_updated_cb; + this->data = data; } -GdkPixbuf* image_loader_webp_get_pixbuf(gpointer loader) +GdkPixbuf *ImageLoaderWEBP::get_pixbuf() { - auto *ld = (ImageLoaderWEBP *) loader; - return ld->pixbuf; + return pixbuf; } -gchar* image_loader_webp_get_format_name(gpointer) +gchar *ImageLoaderWEBP::get_format_name() { return g_strdup("webp"); } -gchar** image_loader_webp_get_format_mime_types(gpointer) +gchar **ImageLoaderWEBP::get_format_mime_types() { static const gchar *mime[] = {"image/webp", nullptr}; return g_strdupv(const_cast(mime)); } -gboolean image_loader_webp_close(gpointer, GError **) +ImageLoaderWEBP::~ImageLoaderWEBP() { - return TRUE; -} - -void image_loader_webp_abort(gpointer loader) -{ - auto *ld = (ImageLoaderWEBP *) loader; - ld->abort = TRUE; -} - -void image_loader_webp_free(gpointer loader) -{ - auto *ld = (ImageLoaderWEBP *) loader; - if (ld->pixbuf) g_object_unref(ld->pixbuf); - g_free(ld); + if (pixbuf) g_object_unref(pixbuf); } } // namespace -void image_loader_backend_set_webp(ImageLoaderBackend *funcs) + +std::unique_ptr get_image_loader_backend_webp() { -DEBUG_0(" " ); - funcs->loader_new = image_loader_webp_new; - funcs->set_size = image_loader_webp_set_size; - funcs->write = image_loader_webp_write; - funcs->get_pixbuf = image_loader_webp_get_pixbuf; - funcs->close = image_loader_webp_close; - funcs->abort = image_loader_webp_abort; - funcs->free = image_loader_webp_free; - funcs->get_format_name = image_loader_webp_get_format_name; - funcs->get_format_mime_types = image_loader_webp_get_format_mime_types; + DEBUG_0(" " ); + return std::make_unique(); } #endif diff --git a/src/image-load-webp.h b/src/image-load-webp.h index 19b5e0fb..abc37d13 100644 --- a/src/image-load-webp.h +++ b/src/image-load-webp.h @@ -24,9 +24,11 @@ #include #if HAVE_WEBP +#include + struct ImageLoaderBackend; -void image_loader_backend_set_webp(ImageLoaderBackend *funcs); +std::unique_ptr get_image_loader_backend_webp(); #endif #endif diff --git a/src/image-load-zxscr.cc b/src/image-load-zxscr.cc index 96b707aa..680861c5 100644 --- a/src/image-load-zxscr.cc +++ b/src/image-load-zxscr.cc @@ -30,15 +30,22 @@ namespace { -struct ImageLoaderZXSCR { - ImageLoaderBackendCbAreaUpdated area_updated_cb; - ImageLoaderBackendCbSize size_cb; - ImageLoaderBackendCbAreaPrepared area_prepared_cb; +struct ImageLoaderZXSCR : public ImageLoaderBackend +{ +public: + ~ImageLoaderZXSCR() override; + + void init(AreaUpdatedCb area_updated_cb, SizePreparedCb size_prepared_cb, AreaPreparedCb area_prepared_cb, gpointer data) override; + gboolean write(const guchar *buf, gsize &chunk_size, gsize count, GError **error) override; + GdkPixbuf *get_pixbuf() override; + gchar *get_format_name() override; + gchar **get_format_mime_types() override; + +private: + AreaUpdatedCb area_updated_cb; gpointer data; + GdkPixbuf *pixbuf; - guint requested_width; - guint requested_height; - gboolean abort; }; constexpr guchar palette[2][8][3] = { @@ -68,9 +75,8 @@ void free_buffer(guchar *pixels, gpointer) g_free(pixels); } -gboolean image_loader_zxscr_write(gpointer loader, const guchar *buf, gsize &chunk_size, gsize count, GError **) +gboolean ImageLoaderZXSCR::write(const guchar *buf, gsize &chunk_size, gsize count, GError **) { - auto ld = static_cast(loader); guint8 *pixels; gint width; gint height; @@ -102,9 +108,9 @@ gboolean image_loader_zxscr_write(gpointer loader, const guchar *buf, gsize &chu return FALSE; } - ld->pixbuf = gdk_pixbuf_new_from_data(pixels, GDK_COLORSPACE_RGB, FALSE, 8, width, height, width * 3, free_buffer, nullptr); + pixbuf = gdk_pixbuf_new_from_data(pixels, GDK_COLORSPACE_RGB, FALSE, 8, width, height, width * 3, free_buffer, nullptr); - if (!ld->pixbuf) + if (!pixbuf) { g_free(pixels); DEBUG_1("Insufficient memory to open ZXSCR file"); @@ -153,76 +159,43 @@ gboolean image_loader_zxscr_write(gpointer loader, const guchar *buf, gsize &chu } } - ld->area_updated_cb(loader, 0, 0, width, height, ld->data); + area_updated_cb(nullptr, 0, 0, width, height, data); chunk_size = count; return TRUE; } -gpointer image_loader_zxscr_new(ImageLoaderBackendCbAreaUpdated area_updated_cb, ImageLoaderBackendCbSize size_cb, ImageLoaderBackendCbAreaPrepared area_prepared_cb, gpointer data) -{ - auto loader = g_new0(ImageLoaderZXSCR, 1); - loader->area_updated_cb = area_updated_cb; - loader->size_cb = size_cb; - loader->area_prepared_cb = area_prepared_cb; - loader->data = data; - return loader; -} - -void image_loader_zxscr_set_size(gpointer loader, int width, int height) +void ImageLoaderZXSCR::init(AreaUpdatedCb area_updated_cb, SizePreparedCb, AreaPreparedCb, gpointer data) { - auto ld = static_cast(loader); - ld->requested_width = width; - ld->requested_height = height; + this->area_updated_cb = area_updated_cb; + this->data = data; } -GdkPixbuf *image_loader_zxscr_get_pixbuf(gpointer loader) +GdkPixbuf *ImageLoaderZXSCR::get_pixbuf() { - auto ld = static_cast(loader); - return ld->pixbuf; + return pixbuf; } -gchar *image_loader_zxscr_get_format_name(gpointer) +gchar *ImageLoaderZXSCR::get_format_name() { return g_strdup("zxscr"); } -gchar **image_loader_zxscr_get_format_mime_types(gpointer) +gchar **ImageLoaderZXSCR::get_format_mime_types() { static const gchar *mime[] = {"application/octet-stream", nullptr}; return g_strdupv(const_cast(mime)); } -gboolean image_loader_zxscr_close(gpointer, GError **) -{ - return TRUE; -} - -void image_loader_zxscr_abort(gpointer loader) -{ - auto ld = static_cast(loader); - ld->abort = TRUE; -} - -void image_loader_zxscr_free(gpointer loader) +ImageLoaderZXSCR::~ImageLoaderZXSCR() { - auto ld = static_cast(loader); - if (ld->pixbuf) g_object_unref(ld->pixbuf); - g_free(ld); + if (pixbuf) g_object_unref(pixbuf); } } // namespace -void image_loader_backend_set_zxscr(ImageLoaderBackend *funcs) +std::unique_ptr get_image_loader_backend_zxscr() { - funcs->loader_new = image_loader_zxscr_new; - funcs->set_size = image_loader_zxscr_set_size; - funcs->write = image_loader_zxscr_write; - funcs->get_pixbuf = image_loader_zxscr_get_pixbuf; - funcs->close = image_loader_zxscr_close; - funcs->abort = image_loader_zxscr_abort; - funcs->free = image_loader_zxscr_free; - funcs->get_format_name = image_loader_zxscr_get_format_name; - funcs->get_format_mime_types = image_loader_zxscr_get_format_mime_types; + return std::make_unique(); } /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff --git a/src/image-load-zxscr.h b/src/image-load-zxscr.h index 0b1e81e1..95d3a55f 100644 --- a/src/image-load-zxscr.h +++ b/src/image-load-zxscr.h @@ -21,9 +21,11 @@ #ifndef IMAGE_LOAD_ZXSCR_H #define IMAGE_LOAD_ZXSCR_H +#include + struct ImageLoaderBackend; -void image_loader_backend_set_zxscr(ImageLoaderBackend *funcs); +std::unique_ptr get_image_loader_backend_zxscr(); #endif /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff --git a/src/image-load.cc b/src/image-load.cc index 3d969fda..d5d21ec1 100644 --- a/src/image-load.cc +++ b/src/image-load.cc @@ -132,7 +132,7 @@ static void image_loader_init(GTypeInstance *instance, gpointer) il->idle_id = 0; il->idle_priority = G_PRIORITY_DEFAULT_IDLE; il->done = FALSE; - il->loader = nullptr; + il->backend.reset(nullptr); il->bytes_read = 0; il->bytes_total = 0; @@ -475,13 +475,13 @@ static void image_loader_sync_pixbuf(ImageLoader *il) g_mutex_lock(il->data_mutex); - if (!il->loader) + if (!il->backend) { g_mutex_unlock(il->data_mutex); return; } - pb = il->backend.get_pixbuf(il->loader); + pb = il->backend->get_pixbuf(); if (pb == il->pixbuf) { @@ -523,12 +523,12 @@ static void image_loader_area_updated_cb(gpointer, else image_loader_emit_area_ready(il, x, y, w, h); - if (il->stopping) il->backend.abort(il->loader); + if (il->stopping) il->backend->abort(); g_mutex_unlock(il->data_mutex); } -static void image_loader_area_prepared_cb(gpointer loader, gpointer data) +static void image_loader_area_prepared_cb(gpointer, gpointer data) { auto il = static_cast(data); GdkPixbuf *pb; @@ -540,7 +540,7 @@ static void image_loader_area_prepared_cb(gpointer loader, gpointer data) https://bugzilla.gnome.org/show_bug.cgi?id=547669 https://bugzilla.gnome.org/show_bug.cgi?id=589334 */ - gchar *format = il->backend.get_format_name(loader); + gchar *format = il->backend->get_format_name(); if (strcmp(format, "svg") == 0 || strcmp(format, "xpm") == 0) { @@ -550,7 +550,7 @@ static void image_loader_area_prepared_cb(gpointer loader, gpointer data) g_free(format); - pb = il->backend.get_pixbuf(loader); + pb = il->backend->get_pixbuf(); h = gdk_pixbuf_get_height(pb); rs = gdk_pixbuf_get_rowstride(pb); @@ -560,7 +560,7 @@ static void image_loader_area_prepared_cb(gpointer loader, gpointer data) } -static void image_loader_size_cb(gpointer loader, +static void image_loader_size_cb(gpointer, gint width, gint height, gpointer data) { auto il = static_cast(data); @@ -583,7 +583,7 @@ static void image_loader_size_cb(gpointer loader, if (il->fd->format_class == FORMAT_CLASS_VIDEO) scale = TRUE; #endif - mime_types = il->backend.get_format_mime_types(loader); + mime_types = il->backend->get_format_mime_types(); n = 0; while (mime_types[n] && !scale) { @@ -620,7 +620,7 @@ static void image_loader_size_cb(gpointer loader, il->actual_width = nw; il->actual_height = nh; - il->backend.set_size(loader, nw, nh); + il->backend->set_size(nw, nh); il->shrunk = TRUE; } @@ -632,13 +632,12 @@ static void image_loader_stop_loader(ImageLoader *il) { if (!il) return; - if (il->loader) + if (il->backend) { /* some loaders do not have a pixbuf till close, order is important here */ - il->backend.close(il->loader, il->error ? nullptr : &il->error); /* we are interested in the first error only */ + il->backend->close(il->error ? nullptr : &il->error); /* we are interested in the first error only */ image_loader_sync_pixbuf(il); - il->backend.free(il->loader); - il->loader = nullptr; + il->backend.reset(nullptr); } g_mutex_lock(il->data_mutex); il->done = TRUE; @@ -672,7 +671,7 @@ static void image_loader_setup_loader(ImageLoader *il) if (external_preview == 0) { DEBUG_1("Using custom external loader"); - image_loader_backend_set_external(&il->backend); + il->backend = get_image_loader_backend_external(); } else { @@ -680,7 +679,7 @@ static void image_loader_setup_loader(ImageLoader *il) if (il->fd->format_class == FORMAT_CLASS_VIDEO) { DEBUG_1("Using custom ffmpegthumbnailer loader"); - image_loader_backend_set_ft(&il->backend); + il->backend = get_image_loader_backend_ft(); } else #endif @@ -689,20 +688,20 @@ static void image_loader_setup_loader(ImageLoader *il) (memcmp(il->mapped_file + 0, "%PDF", 4) == 0)) { DEBUG_1("Using custom pdf loader"); - image_loader_backend_set_pdf(&il->backend); + il->backend = get_image_loader_backend_pdf(); } else #endif #if HAVE_HEIF if (il->bytes_total >= 12 && - ((memcmp(il->mapped_file + 4, "ftypheic", 8) == 0) || - (memcmp(il->mapped_file + 4, "ftypheix", 8) == 0) || - (memcmp(il->mapped_file + 4, "ftypmsf1", 8) == 0) || - (memcmp(il->mapped_file + 4, "ftypmif1", 8) == 0) || - (memcmp(il->mapped_file + 4, "ftypavif", 8) == 0))) + ((memcmp(il->mapped_file + 4, "ftypheic", 8) == 0) || + (memcmp(il->mapped_file + 4, "ftypheix", 8) == 0) || + (memcmp(il->mapped_file + 4, "ftypmsf1", 8) == 0) || + (memcmp(il->mapped_file + 4, "ftypmif1", 8) == 0) || + (memcmp(il->mapped_file + 4, "ftypavif", 8) == 0))) { DEBUG_1("Using custom heif loader"); - image_loader_backend_set_heif(&il->backend); + il->backend = get_image_loader_backend_heif(); } else #endif @@ -712,7 +711,7 @@ static void image_loader_setup_loader(ImageLoader *il) (memcmp(il->mapped_file + 8, "WEBP", 4) == 0)) { DEBUG_1("Using custom webp loader"); - image_loader_backend_set_webp(&il->backend); + il->backend = get_image_loader_backend_webp(); } else #endif @@ -722,7 +721,7 @@ static void image_loader_setup_loader(ImageLoader *il) (memcmp(il->mapped_file + 12, "DJV", 3) == 0)) { DEBUG_1("Using custom djvu loader"); - image_loader_backend_set_djvu(&il->backend); + il->backend = get_image_loader_backend_djvu(); } else #endif @@ -730,16 +729,16 @@ static void image_loader_setup_loader(ImageLoader *il) if (il->bytes_total >= 2 && il->mapped_file[0] == 0xff && il->mapped_file[1] == 0xd8) { DEBUG_1("Using custom jpeg loader"); - image_loader_backend_set_jpeg(&il->backend); + il->backend = get_image_loader_backend_jpeg(); } #if !HAVE_RAW else if (il->bytes_total >= 11 && - (memcmp(il->mapped_file + 4, "ftypcrx", 7) == 0) && - (memcmp(il->mapped_file + 64, "CanonCR3", 8) == 0)) + (memcmp(il->mapped_file + 4, "ftypcrx", 7) == 0) && + (memcmp(il->mapped_file + 64, "CanonCR3", 8) == 0)) { DEBUG_1("Using custom cr3 loader"); - image_loader_backend_set_cr3(&il->backend); + il->backend = get_image_loader_backend_cr3(); } #endif else @@ -752,21 +751,21 @@ static void image_loader_setup_loader(ImageLoader *il) memcmp(il->mapped_file, "II*\0", 4) == 0)) { DEBUG_1("Using custom tiff loader"); - image_loader_backend_set_tiff(&il->backend); + il->backend = get_image_loader_backend_tiff(); } else #endif if (il->bytes_total >= 3 && il->mapped_file[0] == 0x44 && il->mapped_file[1] == 0x44 && il->mapped_file[2] == 0x53) { DEBUG_1("Using dds loader"); - image_loader_backend_set_dds(&il->backend); + il->backend = get_image_loader_backend_dds(); } else if (il->bytes_total >= 6 && (memcmp(il->mapped_file, "8BPS\0\x01", 6) == 0)) { DEBUG_1("Using custom psd loader"); - image_loader_backend_set_psd(&il->backend); + il->backend = get_image_loader_backend_psd(); } else #if HAVE_J2K @@ -774,23 +773,18 @@ static void image_loader_setup_loader(ImageLoader *il) (memcmp(il->mapped_file, "\0\0\0\x0CjP\x20\x20\x0D\x0A\x87\x0A", 12) == 0)) { DEBUG_1("Using custom j2k loader"); - image_loader_backend_set_j2k(&il->backend); + il->backend = get_image_loader_backend_j2k(); } else #endif #if HAVE_JPEGXL - if (il->bytes_total >= 12 && - (memcmp(il->mapped_file, "\0\0\0\x0C\x4A\x58\x4C\x20\x0D\x0A\x87\x0A", 12) == 0)) - { - DEBUG_1("Using custom jpeg xl loader"); - image_loader_backend_set_jpegxl(&il->backend); - } - else - if (il->bytes_total >= 2 && - (memcmp(il->mapped_file, "\xFF\x0A", 2) == 0)) + if ((il->bytes_total >= 12 && + (memcmp(il->mapped_file, "\0\0\0\x0C\x4A\x58\x4C\x20\x0D\x0A\x87\x0A", 12) == 0)) || + (il->bytes_total >= 2 && + (memcmp(il->mapped_file, "\xFF\x0A", 2) == 0))) { DEBUG_1("Using custom jpeg xl loader"); - image_loader_backend_set_jpegxl(&il->backend); + il->backend = get_image_loader_backend_jpegxl(); } else #endif @@ -798,63 +792,63 @@ static void image_loader_setup_loader(ImageLoader *il) (file_extension_match(il->fd->path, ".scr"))) { DEBUG_1("Using custom zxscr loader"); - image_loader_backend_set_zxscr(&il->backend); + il->backend = get_image_loader_backend_zxscr(); } else if (il->fd->format_class == FORMAT_CLASS_COLLECTION) { DEBUG_1("Using custom collection loader"); - image_loader_backend_set_collection(&il->backend); + il->backend = get_image_loader_backend_collection(); } else if (g_strcmp0(strrchr(il->fd->path, '.'), ".svgz") == 0) { DEBUG_1("Using custom svgz loader"); - image_loader_backend_set_svgz(&il->backend); + il->backend = get_image_loader_backend_svgz(); } else - image_loader_backend_set_default(&il->backend); + il->backend = get_image_loader_backend_default(); } - il->loader = static_cast(il->backend.loader_new(image_loader_area_updated_cb, image_loader_size_cb, image_loader_area_prepared_cb, il)); + il->backend->init(image_loader_area_updated_cb, image_loader_size_cb, image_loader_area_prepared_cb, il); #if HAVE_TIFF - format = il->backend.get_format_name(il->loader); + format = il->backend->get_format_name(); if (g_strcmp0(format, "tiff") == 0) { - il->backend.set_page_num(il->loader, il->fd->page_num); + il->backend->set_page_num(il->fd->page_num); } g_free(format); #endif #if HAVE_PDF - format = il->backend.get_format_name(il->loader); + format = il->backend->get_format_name(); if (g_strcmp0(format, "pdf") == 0) { - il->backend.set_page_num(il->loader, il->fd->page_num); + il->backend->set_page_num(il->fd->page_num); } g_free(format); #endif #if HAVE_HEIF - format = il->backend.get_format_name(il->loader); + format = il->backend->get_format_name(); if (g_strcmp0(format, "heif") == 0) { - il->backend.set_page_num(il->loader, il->fd->page_num); + il->backend->set_page_num(il->fd->page_num); } g_free(format); #endif #if HAVE_DJVU - format = il->backend.get_format_name(il->loader); + format = il->backend->get_format_name(); if (g_strcmp0(format, "djvu") == 0) { - il->backend.set_page_num(il->loader, il->fd->page_num); + il->backend->set_page_num(il->fd->page_num); } g_free(format); #endif - il->fd->format_name = il->backend.get_format_name(il->loader); + il->fd->format_name = il->backend->get_format_name(); g_mutex_unlock(il->data_mutex); } @@ -899,7 +893,7 @@ static gboolean image_loader_continue(ImageLoader *il) gsize b = MIN(il->read_buffer_size, il->bytes_total - il->bytes_read); - if (!il->backend.write(il->loader, il->mapped_file + il->bytes_read, b, il->bytes_total, &il->error)) + if (!il->backend->write(il->mapped_file + il->bytes_read, b, il->bytes_total, &il->error)) { image_loader_error(il); return G_SOURCE_REMOVE; @@ -933,44 +927,44 @@ static gboolean image_loader_begin(ImageLoader *il) image_loader_setup_loader(il); g_assert(il->bytes_read == 0); - if (!il->backend.write(il->loader, il->mapped_file, b, il->bytes_total, &il->error)) + if (!il->backend->write(il->mapped_file, b, il->bytes_total, &il->error)) { image_loader_stop_loader(il); return FALSE; } #if HAVE_PDF - format = il->backend.get_format_name(il->loader); + format = il->backend->get_format_name(); if (g_strcmp0(format, "pdf") == 0) { - gint i = il->backend.get_page_total(il->loader); + gint i = il->backend->get_page_total(); file_data_set_page_total(il->fd, i); } g_free(format); #endif #if HAVE_HEIF - format = il->backend.get_format_name(il->loader); + format = il->backend->get_format_name(); if (g_strcmp0(format, "heif") == 0) { - gint i = il->backend.get_page_total(il->loader); + gint i = il->backend->get_page_total(); file_data_set_page_total(il->fd, i); } g_free(format); #endif #if HAVE_DJVU - format = il->backend.get_format_name(il->loader); + format = il->backend->get_format_name(); if (g_strcmp0(format, "djvu") == 0) { - gint i = il->backend.get_page_total(il->loader); + gint i = il->backend->get_page_total(); file_data_set_page_total(il->fd, i); } g_free(format); #endif #if HAVE_TIFF - format = il->backend.get_format_name(il->loader); + format = il->backend->get_format_name(); if (g_strcmp0(format, "tiff") == 0) { - gint i = il->backend.get_page_total(il->loader); + gint i = il->backend->get_page_total(); file_data_set_page_total(il->fd, i); } g_free(format); @@ -979,7 +973,7 @@ static gboolean image_loader_begin(ImageLoader *il) il->bytes_read += b; /* read until size is known */ - while (il->loader && !il->backend.get_pixbuf(il->loader) && b > 0 && !image_loader_get_stopping(il)) + while (il->backend && !il->backend->get_pixbuf() && b > 0 && !image_loader_get_stopping(il)) { if (il->bytes_total < il->bytes_read) { @@ -988,7 +982,7 @@ static gboolean image_loader_begin(ImageLoader *il) } b = MIN(il->read_buffer_size, il->bytes_total - il->bytes_read); - if (b > 0 && !il->backend.write(il->loader, il->mapped_file + il->bytes_read, b, il->bytes_total, &il->error)) + if (b > 0 && !il->backend->write(il->mapped_file + il->bytes_read, b, il->bytes_total, &il->error)) { image_loader_stop_loader(il); return FALSE; @@ -1026,7 +1020,7 @@ static gboolean image_loader_setup_source(ImageLoader *il) struct stat st; gchar *pathl; - if (!il || il->loader || il->mapped_file) return FALSE; + if (!il || il->backend || il->mapped_file) return FALSE; il->mapped_file = nullptr; diff --git a/src/image-load.h b/src/image-load.h index d77bf472..34541618 100644 --- a/src/image-load.h +++ b/src/image-load.h @@ -22,6 +22,8 @@ #ifndef IMAGE_LOAD_H #define IMAGE_LOAD_H +#include + #include #include #include @@ -30,35 +32,25 @@ struct FileData; #define TYPE_IMAGE_LOADER (image_loader_get_type()) -using ImageLoaderBackendCbAreaPrepared = void (*)(gpointer, gpointer); -using ImageLoaderBackendCbSize = void (*)(gpointer, gint, gint, gpointer); -using ImageLoaderBackendCbAreaUpdated = void (*)(gpointer, guint, guint, guint, guint, gpointer); - -using ImageLoaderBackendFuncLoaderNew = gpointer (*)(ImageLoaderBackendCbAreaUpdated, ImageLoaderBackendCbSize, ImageLoaderBackendCbAreaPrepared, gpointer); -using ImageLoaderBackendFuncSetSize = void (*)(gpointer, int, int); -using ImageLoaderBackendFuncWrite = gboolean (*)(gpointer, const guchar *, gsize &, gsize, GError **); -using ImageLoaderBackendFuncGetPixbuf = GdkPixbuf *(*)(gpointer); -using ImageLoaderBackendFuncClose = gboolean (*)(gpointer, GError **); -using ImageLoaderBackendFuncAbort = void (*)(gpointer); -using ImageLoaderBackendFuncFree = void (*)(gpointer); -using ImageLoaderBackendFuncGetFormatName = gchar *(*)(gpointer); -using ImageLoaderBackendFuncGetFormatMimeTypes = gchar **(*)(gpointer); -using ImageLoaderBackendFuncSetPageNum = void (*)(gpointer, gint); -using ImageLoaderBackendFuncGetPageTotal = gint (*)(gpointer); - struct ImageLoaderBackend { - ImageLoaderBackendFuncLoaderNew loader_new; - ImageLoaderBackendFuncSetSize set_size; - ImageLoaderBackendFuncWrite write; - ImageLoaderBackendFuncGetPixbuf get_pixbuf; - ImageLoaderBackendFuncClose close; - ImageLoaderBackendFuncAbort abort; - ImageLoaderBackendFuncFree free; - ImageLoaderBackendFuncGetFormatName get_format_name; - ImageLoaderBackendFuncGetFormatMimeTypes get_format_mime_types; - ImageLoaderBackendFuncSetPageNum set_page_num; - ImageLoaderBackendFuncGetPageTotal get_page_total; +public: + virtual ~ImageLoaderBackend() = default; + + using AreaUpdatedCb = void (*)(gpointer, guint, guint, guint, guint, gpointer); + using SizePreparedCb = void (*)(gpointer, gint, gint, gpointer); + using AreaPreparedCb = void (*)(gpointer, gpointer); + + virtual void init(AreaUpdatedCb area_updated_cb, SizePreparedCb size_prepared_cb, AreaPreparedCb area_prepared_cb, gpointer data) = 0; + virtual void set_size(int /*width*/, int /*height*/) {}; + virtual gboolean write(const guchar *buf, gsize &chunk_size, gsize count, GError **error) = 0; + virtual GdkPixbuf *get_pixbuf() = 0; + virtual gboolean close(GError **/*error*/) { return TRUE; }; + virtual void abort() {}; + virtual gchar *get_format_name() = 0; + virtual gchar **get_format_mime_types() = 0; + virtual void set_page_num(gint /*page_num*/) {}; + virtual gint get_page_total() { return 0; }; }; enum ImageLoaderPreview { @@ -94,9 +86,8 @@ struct ImageLoader guint idle_id; /**< event source id */ gint idle_priority; - gpointer *loader; GError *error; - ImageLoaderBackend backend; + std::unique_ptr backend; guint idle_done_id; /**< event source id */ GList *area_param_list; -- 2.20.1