[libgxps] tools: Add small library to be used by tools



commit 8f861f1bd70af7c0a66e00e79688c7b7aa388364
Author: Carlos Garcia Campos <carlosgc gnome org>
Date:   Sat Oct 29 11:48:17 2011 +0200

    tools: Add small library to be used by tools
    
    At the moment it's just a GXPSConverter abstract class with default
    implementation.

 Makefile.am            |    2 +-
 configure.ac           |    1 +
 tools/Makefile.am      |   17 +++
 tools/gxps-converter.c |  338 ++++++++++++++++++++++++++++++++++++++++++++++++
 tools/gxps-converter.h |   91 +++++++++++++
 5 files changed, 448 insertions(+), 1 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index feefc89..6c0d1aa 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = libgxps
+SUBDIRS = libgxps tools
 
 if ENABLE_TEST
 SUBDIRS += test
diff --git a/configure.ac b/configure.ac
index 77864dd..c3e73d6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -182,6 +182,7 @@ Makefile
 libgxps.pc
 libgxps/Makefile
 libgxps/gxps-version.h
+tools/Makefile
 test/Makefile
 docs/Makefile
 docs/reference/Makefile
diff --git a/tools/Makefile.am b/tools/Makefile.am
new file mode 100644
index 0000000..cf7582a
--- /dev/null
+++ b/tools/Makefile.am
@@ -0,0 +1,17 @@
+noinst_LTLIBRARIES = libgxpstools.la
+
+libgxpstools_la_SOURCES = \
+	gxps-converter.c	\
+	gxps-converter.h
+
+libgxpstools_la_CPPFLAGS = \
+	-I$(top_srcdir)		\
+	$(AM_CPPFLAGS)
+
+libgxpstools_la_CFLAGS = \
+	$(GXPS_CFLAGS)		\
+	$(WARN_CFLAGS)		\
+	$(AM_CFLAGS)
+
+libgxpstools_la_LIBADD = \
+	$(top_builddir)/libgxps/libgxps.la
diff --git a/tools/gxps-converter.c b/tools/gxps-converter.c
new file mode 100644
index 0000000..33de173
--- /dev/null
+++ b/tools/gxps-converter.c
@@ -0,0 +1,338 @@
+/* GXPSConverter
+ *
+ * Copyright (C) 2011  Carlos Garcia Campos <carlosgc gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <config.h>
+
+#include "gxps-converter.h"
+#include <gio/gio.h>
+#include <math.h>
+
+G_DEFINE_ABSTRACT_TYPE (GXPSConverter, gxps_converter, G_TYPE_OBJECT)
+
+static guint document = 0;
+static guint first_page = 0;
+static guint last_page = 0;
+static gboolean only_odd = FALSE;
+static gboolean only_even = FALSE;
+static gdouble resolution = 0.0;
+static gdouble x_resolution = 150.0;
+static gdouble y_resolution = 150.0;
+static guint crop_x = 0.0;
+static guint crop_y = 0.0;
+static guint crop_width = 0.0;
+static guint crop_height = 0.0;
+static const char **file_arguments = NULL;
+
+static const GOptionEntry options[] =
+{
+        { "document", 'd', 0, G_OPTION_ARG_INT, &document, "the XPS document to convert", "DOCUMENT" },
+        { "first", 'f', 0, G_OPTION_ARG_INT, &first_page, "first page to convert", "PAGE" },
+        { "last", 'l', 0, G_OPTION_ARG_INT, &last_page, "last page to convert", "PAGE" },
+        { "odd", 'o', 0, G_OPTION_ARG_NONE, &only_odd, "convert only odd pages", NULL },
+        { "even", 'e', 0, G_OPTION_ARG_NONE, &only_even, "convert only even pages", NULL },
+        { "resolution", 'r', 0, G_OPTION_ARG_DOUBLE, &resolution, "resolution in PPI [default: 150]", "RESOLUTION" },
+        { "rx", '\0', 0, G_OPTION_ARG_DOUBLE, &x_resolution, "X resolution in PPI [default: 150]", "X RESOLUTION" },
+        { "ry", '\0', 0, G_OPTION_ARG_DOUBLE, &y_resolution, "Y resolution in PPI [default: 150]", "Y RESOLUTION" },
+        { "crop-x", 'x', 0, G_OPTION_ARG_INT, &crop_x, "X coordinate of the crop area top left corner", "X" },
+        { "crop-y", 'y', 0, G_OPTION_ARG_INT, &crop_y, "Y coordinate of the crop area top left corner", "Y" },
+        { "crop-width", 'w', 0, G_OPTION_ARG_INT, &crop_width, "width of crop area in pixels", "WIDTH" },
+        { "crop-height", 'h', 0, G_OPTION_ARG_INT, &crop_height, "height of crop area in pixels", "HEIGHT" },
+        { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &file_arguments, NULL, "FILE [OUTPUT FILE]" },
+        { NULL }
+};
+
+static gboolean
+gxps_converter_real_init_with_args (GXPSConverter *converter,
+                                    gint          *argc,
+                                    gchar       ***argv,
+                                    GList        **option_groups)
+{
+        GOptionContext *context;
+        GFile          *file;
+        GXPSFile       *xps;
+        guint           n_pages;
+        GList          *group;
+        GError         *error = NULL;
+
+        context = g_option_context_new (NULL);
+        g_option_context_set_help_enabled (context, TRUE);
+        g_option_context_add_main_entries (context, options, NULL);
+
+        for (group = g_list_reverse (*option_groups); group; group = g_list_next (group))
+                g_option_context_add_group (context, (GOptionGroup *)group->data);
+
+        if (!g_option_context_parse (context, argc, argv, &error)) {
+                g_printerr ("Error parsing arguments: %s\n", error->message);
+                g_error_free (error);
+                g_option_context_free (context);
+
+                return FALSE;
+        }
+
+        if (!file_arguments) {
+                gchar *help_text = g_option_context_get_help (context, TRUE, NULL);
+
+                g_print ("%s", help_text);
+                g_free (help_text);
+
+                g_option_context_free (context);
+
+                return FALSE;
+        }
+        g_option_context_free (context);
+
+        file = g_file_new_for_commandline_arg (file_arguments[0]);
+        xps = gxps_file_new (file, &error);
+        g_object_unref (file);
+        if (!xps) {
+                g_printerr ("Error creating XPS file: %s\n", error->message);
+                g_error_free (error);
+
+                return FALSE;
+        }
+
+        document = CLAMP (document, 1, gxps_file_get_n_documents (xps));
+        converter->document = gxps_file_get_document (xps, document - 1, &error);
+        g_object_unref (xps);
+        if (!converter->document) {
+                g_printerr ("Error getting document %d: %s\n", document, error->message);
+                g_error_free (error);
+
+                return FALSE;
+        }
+
+        n_pages = gxps_document_get_n_pages (converter->document);
+        converter->first_page = MAX (first_page, 1);
+        converter->last_page = last_page < 1 ? n_pages : MIN(last_page, n_pages);
+        converter->only_odd = only_odd;
+        converter->only_even = only_even;
+        if (resolution != 0.0 && (x_resolution == 150.0 || y_resolution == 150.0)) {
+                converter->x_resolution = resolution;
+                converter->y_resolution = resolution;
+        } else {
+                converter->x_resolution = x_resolution;
+                converter->y_resolution = y_resolution;
+        }
+        converter->crop.x = crop_x;
+        converter->crop.y = crop_y;
+        converter->crop.width = crop_width;
+        converter->crop.height = crop_height;
+
+        return TRUE;
+}
+
+static void
+gxps_converter_begin_document (GXPSConverter *converter,
+                               const gchar   *output_filename,
+                               GXPSPage      *first_page)
+{
+        GXPSConverterClass *converter_class;
+
+        g_return_if_fail (GXPS_IS_CONVERTER (converter));
+        g_return_if_fail (GXPS_IS_PAGE (first_page));
+
+        converter_class = GXPS_CONVERTER_GET_CLASS (converter);
+        if (converter_class->begin_document)
+                converter_class->begin_document (converter, output_filename, first_page);
+}
+
+static cairo_t *
+gxps_converter_begin_page (GXPSConverter *converter,
+                           GXPSPage      *page,
+                           guint          n_page)
+{
+        g_return_val_if_fail (GXPS_IS_CONVERTER (converter), NULL);
+        g_return_val_if_fail (GXPS_IS_PAGE (page), NULL);
+
+        return GXPS_CONVERTER_GET_CLASS (converter)->begin_page (converter, page, n_page);
+}
+
+static void
+gxps_converter_end_page (GXPSConverter *converter)
+{
+        GXPSConverterClass *converter_class;
+
+        g_return_if_fail (GXPS_IS_CONVERTER (converter));
+
+        converter_class = GXPS_CONVERTER_GET_CLASS (converter);
+        if (converter_class->end_page)
+                converter_class->end_page (converter);
+}
+
+static void
+gxps_converter_end_document (GXPSConverter *converter)
+{
+        GXPSConverterClass *converter_class;
+
+        g_return_if_fail (GXPS_IS_CONVERTER (converter));
+
+        converter_class = GXPS_CONVERTER_GET_CLASS (converter);
+        if (converter_class->end_document)
+                converter_class->end_document (converter);
+}
+
+static void
+gxps_converter_finalize (GObject *object)
+{
+        GXPSConverter *converter = GXPS_CONVERTER (object);
+
+        if (converter->document) {
+                g_object_unref (converter->document);
+                converter->document = NULL;
+        }
+
+        if (converter->surface) {
+                g_object_unref (converter->surface);
+                converter->surface = NULL;
+        }
+
+        G_OBJECT_CLASS (gxps_converter_parent_class)->finalize (object);
+}
+
+static void
+gxps_converter_init (GXPSConverter *converter)
+{
+}
+
+static void
+gxps_converter_class_init (GXPSConverterClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        klass->init_with_args = gxps_converter_real_init_with_args;
+
+        object_class->finalize = gxps_converter_finalize;
+}
+
+gboolean
+gxps_converter_init_with_args (GXPSConverter *converter,
+                               gint          *argc,
+                               gchar       ***argv)
+{
+        GList   *option_groups = NULL;
+        gboolean retval;
+
+        g_return_val_if_fail (GXPS_IS_CONVERTER (converter), FALSE);
+
+        retval = GXPS_CONVERTER_GET_CLASS (converter)->init_with_args (converter, argc, argv, &option_groups);
+        /* Groups are owned by the option context */
+        g_list_free (option_groups);
+
+        return retval;
+}
+
+const gchar *
+gxps_converter_get_extension (GXPSConverter *converter)
+{
+        g_return_val_if_fail (GXPS_IS_CONVERTER (converter), NULL);
+
+        return GXPS_CONVERTER_GET_CLASS (converter)->get_extension (converter);
+}
+
+void
+gxps_converter_get_crop_size (GXPSConverter *converter,
+                              gdouble        page_width,
+                              gdouble        page_height,
+                              gdouble       *output_width,
+                              gdouble       *output_height)
+{
+        guint width, height;
+
+        g_return_if_fail (GXPS_IS_CONVERTER (converter));
+
+        width = converter->crop.width == 0 ? (int)ceil (page_width) : converter->crop.width;
+        height = converter->crop.height == 0 ? (int)ceil (page_height) : converter->crop.height;
+
+        if (output_width) {
+                *output_width = (converter->crop.x + width > page_width ?
+                                 (int)ceil (page_width - converter->crop.x) : width);
+        }
+        if (output_height) {
+                *output_height = (converter->crop.y + height > page_height ?
+                                  (int)ceil (page_height - converter->crop.y) : height);
+        }
+}
+
+void
+gxps_converter_run (GXPSConverter *converter)
+{
+        guint i;
+        guint first_page;
+
+        g_return_if_fail (GXPS_IS_CONVERTER (converter));
+
+        first_page = converter->first_page;
+        /* Make sure first_page is always used so that
+         * gxps_converter_begin_document() is called
+         */
+        if ((converter->only_even && first_page % 2 == 0) ||
+            (converter->only_odd && first_page % 2 == 1))
+                first_page++;
+
+        for (i = first_page; i <= converter->last_page; i++) {
+                GXPSPage *page;
+                cairo_t  *cr;
+                GError   *error;
+
+                if (converter->only_even && i % 2 == 0)
+                        continue;
+                if (converter->only_odd && i % 2 == 1)
+                        continue;
+
+                error = NULL;
+                page = gxps_document_get_page (converter->document, i - 1, &error);
+                if (!page) {
+                        g_printerr ("Error getting page %d: %s\n", i, error->message);
+                        g_error_free (error);
+
+                        continue;
+                }
+
+                if (i == first_page) {
+                        gchar *output_filename = NULL;
+
+                        if (file_arguments[1]) {
+                                GFile *file;
+
+                                file = g_file_new_for_commandline_arg (file_arguments[1]);
+                                output_filename = g_file_get_path (file);
+                                g_object_unref (file);
+                        }
+
+                        gxps_converter_begin_document (converter, output_filename, page);
+                        g_free (output_filename);
+                }
+
+                cr = gxps_converter_begin_page (converter, page, i);
+
+                error = NULL;
+                gxps_page_render (page, cr, &error);
+                if (error) {
+                        g_printerr ("Error rendering page %d: %s\n", i, error->message);
+                        g_error_free (error);
+                }
+                cairo_destroy (cr);
+
+                gxps_converter_end_page (converter);
+
+                g_object_unref (page);
+        }
+
+        gxps_converter_end_document (converter);
+}
diff --git a/tools/gxps-converter.h b/tools/gxps-converter.h
new file mode 100644
index 0000000..e07d1cf
--- /dev/null
+++ b/tools/gxps-converter.h
@@ -0,0 +1,91 @@
+/* GXPSConverter
+ *
+ * Copyright (C) 2011  Carlos Garcia Campos <carlosgc gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __GXPS_CONVERTER_H__
+#define __GXPS_CONVERTER_H__
+
+#include <glib-object.h>
+#include <libgxps/gxps.h>
+
+G_BEGIN_DECLS
+
+#define GXPS_TYPE_CONVERTER           (gxps_converter_get_type ())
+#define GXPS_CONVERTER(obj)           (G_TYPE_CHECK_INSTANCE_CAST (obj, GXPS_TYPE_CONVERTER, GXPSConverter))
+#define GXPS_CONVERTER_CLASS(cls)     (G_TYPE_CHECK_CLASS_CAST (cls, GXPS_TYPE_CONVERTER, GXPSConverterClass))
+#define GXPS_IS_CONVERTER(obj)        (G_TYPE_CHECK_INSTANCE_TYPE (obj, GXPS_TYPE_CONVERTER))
+#define GXPS_IS_CONVERTER_CLASS(obj)  (G_TYPE_CHECK_CLASS_TYPE (obj, GXPS_TYPE_CONVERTER))
+#define GXPS_CONVERTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GXPS_TYPE_CONVERTER, GXPSConverterClass))
+
+typedef struct _GXPSConverter        GXPSConverter;
+typedef struct _GXPSConverterClass   GXPSConverterClass;
+
+struct _GXPSConverter {
+	GObject parent;
+
+        GXPSDocument    *document;
+        cairo_surface_t *surface;
+
+        guint                 first_page;
+        guint                 last_page;
+        gdouble               x_resolution;
+        gdouble               y_resolution;
+        cairo_rectangle_int_t crop;
+        guint                 only_odd  : 1;
+        guint                 only_even : 1;
+};
+
+struct _GXPSConverterClass {
+	GObjectClass parent_class;
+
+        gboolean     (* init_with_args)  (GXPSConverter *converter,
+                                          gint          *argc,
+                                          gchar       ***argv,
+                                          GList        **option_groups);
+
+        void         (* begin_document)  (GXPSConverter *converter,
+                                          const gchar   *output_filename,
+                                          GXPSPage      *first_page);
+        cairo_t     *(* begin_page)      (GXPSConverter *converter,
+                                          GXPSPage      *page,
+                                          guint          n_page);
+        void         (* end_page)        (GXPSConverter *converter);
+        void         (* end_document)    (GXPSConverter *converter);
+
+        const gchar *(* get_extension)   (GXPSConverter *converter);
+};
+
+GType        gxps_converter_get_type        (void);
+
+gboolean     gxps_converter_init_with_args  (GXPSConverter *converter,
+                                             gint          *argc,
+                                             gchar       ***argv);
+
+const gchar *gxps_converter_get_extension   (GXPSConverter *converter);
+
+void         gxps_converter_get_crop_size   (GXPSConverter *converter,
+                                             gdouble        page_width,
+                                             gdouble        page_height,
+                                             gdouble       *output_width,
+                                             gdouble       *output_height);
+
+void         gxps_converter_run             (GXPSConverter *converter);
+
+G_END_DECLS
+
+#endif /* __GXPS_CONVERTER_H__ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]