Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:hiberis:mingw:win64
mingw64-evince
0004-comics-Optionally-use-libgsf-for-reading-c...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0004-comics-Optionally-use-libgsf-for-reading-comics.patch of Package mingw64-evince
From 3c4935d7a8afae526b68e299df799d7dd659b77c Mon Sep 17 00:00:00 2001 From: Hib Eris <hib@hiberis.nl> Date: Tue, 30 Aug 2011 21:39:08 +0200 Subject: [PATCH 04/12] comics: (Optionally) use libgsf for reading comics --- backend/comics/Makefile.am | 4 +- backend/comics/comics-document.c | 394 ++++++++++++++++++++++++++++++++++---- configure.ac | 14 ++ 3 files changed, 373 insertions(+), 39 deletions(-) diff --git a/backend/comics/Makefile.am b/backend/comics/Makefile.am index 5a36f1d..a6a0244 100644 --- a/backend/comics/Makefile.am +++ b/backend/comics/Makefile.am @@ -3,7 +3,7 @@ INCLUDES = \ -I$(top_srcdir)/libdocument \ -DGNOMELOCALEDIR=\"$(datadir)/locale\" \ -DEVINCE_COMPILATION \ - $(BACKEND_CFLAGS) \ + $(COMICS_CFLAGS) \ $(LIB_CFLAGS) \ $(WARN_CFLAGS) \ $(DISABLE_DEPRECATED) @@ -17,7 +17,7 @@ libcomicsdocument_la_SOURCES = \ libcomicsdocument_la_LDFLAGS = $(BACKEND_LIBTOOL_FLAGS) libcomicsdocument_la_LIBADD = \ $(top_builddir)/libdocument/libevdocument3.la \ - $(BACKEND_LIBS) \ + $(COMICS_LIBS) \ $(LIB_LIBS) backend_in_files = comicsdocument.evince-backend.in diff --git a/backend/comics/comics-document.c b/backend/comics/comics-document.c index 1aa36d4..63d9693 100644 --- a/backend/comics/comics-document.c +++ b/backend/comics/comics-document.c @@ -30,6 +30,14 @@ #include <glib/gstdio.h> #include <gio/gio.h> +#if WITH_LIBGSF +#include <gsf/gsf.h> +#include <gsf/gsf-input-gio.h> +#include <gsf/gsf-infile.h> +#include <gsf/gsf-infile-zip.h> +#include <gsf/gsf-infile-tar.h> +#endif + #ifdef G_OS_WIN32 # define WIFEXITED(x) ((x) != 3) # define WEXITSTATUS(x) (x) @@ -53,6 +61,15 @@ typedef enum { + TYPE_INVALID, + TYPE_ZIP, + TYPE_TAR, + TYPE_P7ZIP, + TYPE_RAR +} ComicBookType; + +typedef enum +{ RARLABS, GNAUNRAR, UNZIP, @@ -71,8 +88,10 @@ struct _ComicsDocument { EvDocument parent_instance; + ComicBookType type; gchar *archive, *dir; GPtrArray *page_names; + GPtrArray *pages; gchar *selected_command, *alternative_command; gchar *extract_command, *list_command, *decompress_tmp; gboolean regex_arg; @@ -132,6 +151,54 @@ static void render_pixbuf_size_prepared_cb (GdkPixbufLoader *loader, static char** extract_argv (EvDocument *document, gint page); +static ComicBookType +comics_document_get_comics_type (const char *uri, + GError **error) +{ + ComicBookType type; + + gchar *mime_type; + GError *err; + + mime_type = ev_file_get_mime_type (uri, FALSE, &err); + if (!mime_type) { + if (err) { + g_propagate_error (error, err); + } else { + g_set_error_literal (error, + EV_DOCUMENT_ERROR, + EV_DOCUMENT_ERROR_INVALID, + _("Unknown MIME Type")); + } + return TYPE_INVALID; + } + + /* FIXME, use proper cbr/cbz mime types once they're + * included in shared-mime-info */ + if (!strcmp (mime_type, "application/x-cbz") || + !strcmp (mime_type, "application/zip")) { + type = TYPE_ZIP; + } else if (!strcmp (mime_type, "application/x-cbt") || + !strcmp (mime_type, "application/x-tar")) { + type = TYPE_TAR; + } else if (!strcmp (mime_type, "application/x-cb7") || + !strcmp (mime_type, "application/x-7z-compressed")) { + type = TYPE_P7ZIP; + } else if (!strcmp (mime_type, "application/x-cbr") || + !strcmp (mime_type, "application/x-rar")) { + type = TYPE_RAR; + } else { + g_set_error (error, + EV_DOCUMENT_ERROR, + EV_DOCUMENT_ERROR_INVALID, + _("Not a comic book MIME type: %s"), + mime_type); + type = TYPE_INVALID; + } + + g_free (mime_type); + return type; +} EV_BACKEND_REGISTER (ComicsDocument, comics_document) @@ -300,20 +367,18 @@ comics_generate_command_lines (ComicsDocument *comics_document, /* This function chooses an external command for decompressing a comic * book based on its mime tipe. */ static gboolean -comics_check_decompress_command (gchar *mime_type, - ComicsDocument *comics_document, - GError **error) +comics_check_decompress_command (ComicsDocument *comics_document, + ComicBookType type, + GError **error) { gboolean success; gchar *std_out, *std_err; gint retval; GError *err = NULL; - /* FIXME, use proper cbr/cbz mime types once they're - * included in shared-mime-info */ - - if (!strcmp (mime_type, "application/x-cbr") || - !strcmp (mime_type, "application/x-rar")) { + switch (type) { + + case TYPE_RAR: /* The RARLAB provides a no-charge proprietary (freeware) * decompress-only client for Linux called unrar. Another * option is a GPLv2-licensed command-line tool developed by @@ -361,9 +426,9 @@ comics_check_decompress_command (gchar *mime_type, comics_document->command_usage = GNAUNRAR; return TRUE; } + break; - } else if (!strcmp (mime_type, "application/x-cbz") || - !strcmp (mime_type, "application/zip")) { + case TYPE_ZIP: /* InfoZIP's unzip program */ comics_document->selected_command = g_find_program_in_path ("unzip"); @@ -387,9 +452,9 @@ comics_check_decompress_command (gchar *mime_type, comics_document->command_usage = P7ZIP; return TRUE; } + break; - } else if (!strcmp (mime_type, "application/x-cb7") || - !strcmp (mime_type, "application/x-7z-compressed")) { + case TYPE_P7ZIP: /* 7zr, 7za and 7z are the commands from the p7zip project able * to decompress .7z files */ comics_document->selected_command = @@ -410,8 +475,9 @@ comics_check_decompress_command (gchar *mime_type, comics_document->command_usage = P7ZIP; return TRUE; } - } else if (!strcmp (mime_type, "application/x-cbt") || - !strcmp (mime_type, "application/x-tar")) { + break; + + case TYPE_TAR: /* tar utility (Tape ARchive) */ comics_document->selected_command = g_find_program_in_path ("tar"); @@ -419,14 +485,13 @@ comics_check_decompress_command (gchar *mime_type, comics_document->command_usage = TAR; return TRUE; } - } else { - g_set_error (error, - EV_DOCUMENT_ERROR, - EV_DOCUMENT_ERROR_INVALID, - _("Not a comic book MIME type: %s"), - mime_type); - return FALSE; + break; + + default: + g_warning (_("Invalid comic book type")); + break; } + g_set_error_literal (error, EV_DOCUMENT_ERROR, EV_DOCUMENT_ERROR_INVALID, @@ -442,39 +507,119 @@ sort_page_names (gconstpointer a, return strcmp (* (const char **) a, * (const char **) b); } +#if WITH_LIBGSF +static void +get_pages_gsf (GsfInput *source, + GSList *supported_extensions, + GPtrArray **pages) +{ + GsfInfile *infile = GSF_IS_INFILE (source) ? GSF_INFILE (source) : NULL; + GsfInput *child; + int i, n; + + n = infile ? gsf_infile_num_children (infile): 0; + if (n > 0) { + GPtrArray *page_names = g_ptr_array_sized_new (n); + for (i = 0; i < n; i++) { + child = gsf_infile_child_by_index (infile, i); + g_ptr_array_add (page_names, + g_strdup (gsf_input_name (child))); + g_object_unref (child); + } + g_ptr_array_sort (page_names, sort_page_names); + + for (i = 0; i < page_names->len; i++) { + child = gsf_infile_child_by_name (infile, + (char const*) page_names->pdata[i]); + get_pages_gsf (child, supported_extensions, pages); + g_object_unref (child); + } + g_ptr_array_foreach (page_names, (GFunc) g_free, NULL); + g_ptr_array_free (page_names, TRUE); + } else { + gchar *suffix = g_strrstr (gsf_input_name (source), "."); + if (suffix) { + suffix = g_ascii_strdown (suffix + 1, -1); + if (g_slist_find_custom (supported_extensions, suffix, + (GCompareFunc) strcmp) != NULL) { + g_object_ref (source); + g_ptr_array_add (*pages, source); + } + g_free (suffix); + } + } +} + static gboolean -comics_document_load (EvDocument *document, +comics_document_load_gsf (EvDocument *document, + const char *uri, + GError **error) +{ + ComicsDocument *comics_document = COMICS_DOCUMENT (document); + GsfInput *source; + GsfInfile *infile; + GSList *supported_extensions; + + source = gsf_input_gio_new_for_uri (uri, error); + if (!source) + return FALSE; + + switch (comics_document->type) { + case TYPE_ZIP: + infile = gsf_infile_zip_new (source, error); + break; + case TYPE_TAR: + infile = gsf_infile_tar_new (source, error); + break; + default: + g_warning (_("Invalid comic book type")); + g_set_error_literal (error, + EV_DOCUMENT_ERROR, + EV_DOCUMENT_ERROR_INVALID, + _("Can't find an appropriate command to " + "decompress this type of comic book")); + g_object_unref (source); + return FALSE; + } + g_object_unref (source); + if (!infile) + return FALSE; + + comics_document->pages = g_ptr_array_sized_new (64); + + supported_extensions = get_supported_image_extensions (); + get_pages_gsf (GSF_INPUT (infile), supported_extensions, &(comics_document->pages)); + g_slist_foreach (supported_extensions, (GFunc) g_free, NULL); + g_slist_free (supported_extensions); + g_object_unref (infile); + + return TRUE; +} +#endif + +static gboolean +comics_document_load_external (EvDocument *document, const char *uri, GError **error) { ComicsDocument *comics_document = COMICS_DOCUMENT (document); GSList *supported_extensions; gchar *std_out; - gchar *mime_type; gchar **cb_files, *cb_file; gboolean success; int i, retval; - GError *err = NULL; comics_document->archive = g_filename_from_uri (uri, NULL, error); if (!comics_document->archive) return FALSE; - mime_type = ev_file_get_mime_type (uri, FALSE, &err); - if (mime_type == NULL) - return FALSE; - - if (!comics_check_decompress_command (mime_type, comics_document, - error)) { - g_free (mime_type); + if (!comics_check_decompress_command (comics_document, + comics_document->type, error)) { return FALSE; } else if (!comics_generate_command_lines (comics_document, error)) { - g_free (mime_type); return FALSE; } - g_free (mime_type); - /* Get list of files in archive */ success = g_spawn_command_line_sync (comics_document->list_command, &std_out, NULL, &retval, error); @@ -548,6 +693,31 @@ comics_document_load (EvDocument *document, return TRUE; } +static gboolean +comics_document_load (EvDocument *document, + const char *uri, + GError **error) +{ + ComicsDocument *comics_document = COMICS_DOCUMENT (document); + + comics_document->type = comics_document_get_comics_type (uri, error); + if (comics_document->type == TYPE_INVALID) + return FALSE; + +#if WITH_LIBGSF + switch (comics_document->type) { + + case TYPE_ZIP: + case TYPE_TAR: + return comics_document_load_gsf (document, uri, error); + break; + default: + ; + } +#endif + + return comics_document_load_external (document, uri, error); +} static gboolean comics_document_save (EvDocument *document, @@ -564,14 +734,68 @@ comics_document_get_n_pages (EvDocument *document) { ComicsDocument *comics_document = COMICS_DOCUMENT (document); +#if WITH_LIBGSF + if (comics_document->pages != NULL) + return comics_document->pages->len; +#endif if (comics_document->page_names == NULL) return 0; return comics_document->page_names->len; } +#if WITH_LIBGSF static void -comics_document_get_page_size (EvDocument *document, +comics_document_get_page_size_gsf (EvDocument *document, + EvPage *page, + double *width, + double *height) +{ + ComicsDocument *comics_document = COMICS_DOCUMENT (document); + GdkPixbufLoader *loader; + guint8 const *data; + gsf_off_t len; + GdkPixbuf *pixbuf; + gboolean got_size = FALSE; + + loader = gdk_pixbuf_loader_new (); + g_signal_connect (loader, "area-prepared", + G_CALLBACK (get_page_size_area_prepared_cb), + &got_size); + + GsfInput *input = GSF_INPUT ( + g_ptr_array_index(comics_document->pages, page->index)); + + gsf_input_seek(input, 0, G_SEEK_SET); + while ((len = gsf_input_remaining (input)) > 0) { + + if (len > 1024) + len = 1024; + + if ((data = gsf_input_read (input, len, NULL))) { + gdk_pixbuf_loader_write (loader, data, len, NULL); + } + + if ((!data) || got_size) { + gdk_pixbuf_loader_close (loader, NULL); + break; + } + } + + if (gdk_pixbuf_loader_get_pixbuf (loader)) { + pixbuf = gdk_pixbuf_loader_get_pixbuf (loader); + if (width) + *width = gdk_pixbuf_get_width (pixbuf); + if (height) + *height = gdk_pixbuf_get_height (pixbuf); + } + + g_object_unref (loader); +} +#endif + +static void +comics_document_get_page_size_external (EvDocument *document, EvPage *page, double *width, double *height) @@ -640,6 +864,27 @@ comics_document_get_page_size (EvDocument *document, } static void +comics_document_get_page_size (EvDocument *document, + EvPage *page, + double *width, + double *height) +{ + ComicsDocument *comics_document = COMICS_DOCUMENT (document); + switch (comics_document->type) { +#if WITH_LIBGSF + case TYPE_ZIP: + case TYPE_TAR: + comics_document_get_page_size_gsf (document, + page, width, height); + break; +#endif + default: + comics_document_get_page_size_external (document, + page, width, height); + } +} + +static void get_page_size_area_prepared_cb (GdkPixbufLoader *loader, gpointer data) { @@ -647,9 +892,54 @@ get_page_size_area_prepared_cb (GdkPixbufLoader *loader, *got_size = TRUE; } +#if WITH_LIBGSF static GdkPixbuf * -comics_document_render_pixbuf (EvDocument *document, - EvRenderContext *rc) +comics_document_render_pixbuf_gsf (EvDocument *document, + EvRenderContext *rc) +{ + ComicsDocument *comics_document = COMICS_DOCUMENT (document); + GdkPixbufLoader *loader; + GdkPixbuf *rotated_pixbuf; + guint8 const *data; + gsf_off_t len; + + loader = gdk_pixbuf_loader_new (); + g_signal_connect (loader, "size-prepared", + G_CALLBACK (render_pixbuf_size_prepared_cb), + &rc->scale); + + GsfInput *input = GSF_INPUT ( + g_ptr_array_index(comics_document->pages, rc->page->index)); + + gsf_input_seek(input, 0, G_SEEK_SET); + while ((len = gsf_input_remaining (input)) > 0) { + + if (len > 1024) + len = 1024; + + if ((data = gsf_input_read (input, len, NULL))) { + gdk_pixbuf_loader_write (loader, data, len, NULL); + } + + if (!data) { + g_warning (_("Failed to read data")); + break; + } + } + gdk_pixbuf_loader_close (loader, NULL); + + rotated_pixbuf = gdk_pixbuf_rotate_simple ( + gdk_pixbuf_loader_get_pixbuf (loader), + 360 - rc->rotation); + g_object_unref (loader); + + return rotated_pixbuf; +} +#endif + +static GdkPixbuf * +comics_document_render_pixbuf_external (EvDocument *document, + EvRenderContext *rc) { GdkPixbufLoader *loader; GdkPixbuf *rotated_pixbuf, *tmp_pixbuf; @@ -718,6 +1008,23 @@ comics_document_render_pixbuf (EvDocument *document, return rotated_pixbuf; } +static GdkPixbuf * +comics_document_render_pixbuf (EvDocument *document, + EvRenderContext *rc) +{ + ComicsDocument *comics_document = COMICS_DOCUMENT (document); + switch (comics_document->type) { +#if WITH_LIBGSF + case TYPE_ZIP: + case TYPE_TAR: + return comics_document_render_pixbuf_gsf (document, rc); + break; +#endif + default: + return comics_document_render_pixbuf_external (document, rc); + } +} + static cairo_surface_t * comics_document_render (EvDocument *document, EvRenderContext *rc) @@ -789,6 +1096,13 @@ comics_document_finalize (GObject *object) g_free (comics_document->dir); } +#if WITH_LIBGSF + if (comics_document->pages) { + g_ptr_array_foreach (comics_document->pages, (GFunc) g_object_unref, NULL); + g_ptr_array_free (comics_document->pages, TRUE); + } +#endif + if (comics_document->page_names) { g_ptr_array_foreach (comics_document->page_names, (GFunc) g_free, NULL); g_ptr_array_free (comics_document->page_names, TRUE); @@ -822,8 +1136,14 @@ static void comics_document_init (ComicsDocument *comics_document) { comics_document->archive = NULL; + comics_document->dir = NULL; comics_document->page_names = NULL; + comics_document->pages = NULL; + comics_document->selected_command = NULL; + comics_document->alternative_command = NULL; comics_document->extract_command = NULL; + comics_document->list_command = NULL; + comics_document->decompress_tmp = NULL; } /* Returns a list of file extensions supported by gdk-pixbuf */ diff --git a/configure.ac b/configure.ac index 58386f9..4dfd6ed 100644 --- a/configure.ac +++ b/configure.ac @@ -635,6 +635,20 @@ AC_ARG_ENABLE(comics, if test "x$enable_comics" = "xyes"; then AC_DEFINE([ENABLE_COMICS], [1], [Enable support for comics.]) + COMICS_PKGS="gtk+-3.0 >= $GTK_REQUIRED" + AC_ARG_WITH(libgsf, + [AS_HELP_STRING([--with-libgsf], + [Use libgsf for comics support])], + [], + [case "$with_platform" in + win32) with_libgsf=yes ;; + *) with_libgsf=no ;; + esac]) + if test "x$with_libgsf" = "xyes"; then + AC_DEFINE([WITH_LIBGSF], [1], [Use libgsf for comics support.]) + COMICS_PKGS="$COMICS_PKGS libgsf-1" + fi + PKG_CHECK_MODULES(COMICS, [$COMICS_PKGS]) fi AM_CONDITIONAL(ENABLE_COMICS, test x$enable_comics = xyes) -- 1.7.5.4
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor