[libgxps] tools: Add small library to be used by tools
- From: Carlos Garcia Campos <carlosgc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgxps] tools: Add small library to be used by tools
- Date: Sun, 30 Oct 2011 14:02:43 +0000 (UTC)
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]