[libgxps] Add generic converter to printing formats



commit b917110b5159d6f8ec484fba8d2e058d80af3418
Author: Carlos Garcia Campos <carlosgc gnome org>
Date:   Sat Oct 29 19:39:49 2011 +0200

    Add generic converter to printing formats
    
    Abstract class to handle options common to printing formats like PDF or
    PostScript.

 tools/Makefile.am            |    4 +-
 tools/gxps-print-converter.c |  278 ++++++++++++++++++++++++++++++++++++++++++
 tools/gxps-print-converter.h |   66 ++++++++++
 3 files changed, 347 insertions(+), 1 deletions(-)
---
diff --git a/tools/Makefile.am b/tools/Makefile.am
index c4c93dc..fa4dab5 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -6,7 +6,9 @@ libgxpstools_la_SOURCES = \
 	gxps-image-converter.c	\
 	gxps-image-converter.h	\
 	gxps-image-writer.c	\
-	gxps-image-writer.h
+	gxps-image-writer.h	\
+	gxps-print-converter.c	\
+	gxps-print-converter.h
 
 libgxpstools_la_CPPFLAGS = \
 	-I$(top_srcdir)		\
diff --git a/tools/gxps-print-converter.c b/tools/gxps-print-converter.c
new file mode 100644
index 0000000..38b18d7
--- /dev/null
+++ b/tools/gxps-print-converter.c
@@ -0,0 +1,278 @@
+/* GXPSPrintConverter
+ *
+ * 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-print-converter.h"
+#include <string.h>
+
+G_DEFINE_ABSTRACT_TYPE (GXPSPrintConverter, gxps_print_converter, GXPS_TYPE_CONVERTER)
+
+static guint paper_width = 0;
+static guint paper_height = 0;
+static gboolean expand = FALSE;
+static gboolean no_shrink = FALSE;
+static gboolean no_center = FALSE;
+
+static const GOptionEntry options[] =
+{
+        { "paper-width", '\0', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_INT, &paper_width, "paper width, in points", "WIDTH" },
+        { "paper-height", '\0', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_INT, &paper_height, "paper height, in points", "HEIGHT" },
+        { "expand", '\0', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &expand, "expand pages smaller than the paper size", NULL },
+        { "no-shrink", '\0', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &no_shrink, "don't shrink pages larger than the paper size", NULL },
+        { "no-center", '\0', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &no_center, "don't center pages smaller than the paper size", NULL },
+        { NULL }
+};
+
+static gboolean
+gxps_print_converter_init_with_args (GXPSConverter *converter,
+                                     gint          *argc,
+                                     gchar       ***argv,
+                                     GList        **option_groups)
+{
+        GXPSPrintConverter *print_converter = GXPS_PRINT_CONVERTER (converter);
+        GOptionContext     *context;
+        GOptionGroup       *option_group;
+        GError             *error = NULL;
+
+        option_group = g_option_group_new ("printing", "Printing Options", "Show Printing Options", NULL, NULL);
+        g_option_group_add_entries (option_group, options);
+
+        *option_groups = g_list_prepend (*option_groups, option_group);
+
+        if (GXPS_CONVERTER_CLASS (gxps_print_converter_parent_class)->init_with_args) {
+                if (!GXPS_CONVERTER_CLASS (gxps_print_converter_parent_class)->init_with_args (converter, argc, argv, option_groups))
+                        return FALSE;
+        }
+
+        context = g_option_context_new (NULL);
+        g_option_context_set_ignore_unknown_options (context, TRUE);
+        g_option_context_set_help_enabled (context, FALSE);
+        g_option_context_add_main_entries (context, options, NULL);
+        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;
+        }
+        g_option_context_free (context);
+
+        print_converter->paper_width = paper_width;
+        print_converter->paper_height = paper_height;
+
+        print_converter->flags = GXPS_PRINT_CONVERTER_SHRINK | GXPS_PRINT_CONVERTER_CENTER;
+        if (expand)
+                print_converter->flags |= GXPS_PRINT_CONVERTER_EXPAND;
+        if (no_shrink)
+                print_converter->flags &= ~GXPS_PRINT_CONVERTER_SHRINK;
+        if (no_center)
+                print_converter->flags &= ~GXPS_PRINT_CONVERTER_CENTER;
+
+        return TRUE;
+}
+
+
+static void
+gxps_converter_print_converter_begin_document (GXPSConverter *converter,
+                                               const gchar   *output_filename,
+                                               GXPSPage      *first_page)
+{
+        GXPSPrintConverter *print_converter = GXPS_PRINT_CONVERTER (converter);
+        gchar              *basename;
+        gchar              *basename_lower;
+        const gchar        *ext;
+
+        if (output_filename) {
+                print_converter->filename = g_strdup (output_filename);
+                return;
+        }
+
+        basename = g_path_get_basename (converter->input_filename);
+        basename_lower = g_ascii_strdown (basename, -1);
+        ext = g_strrstr (basename_lower, ".xps");
+        g_free (basename_lower);
+
+        if (ext) {
+                gchar *name;
+
+                name = g_strndup (basename, strlen (basename) - strlen (ext));
+                print_converter->filename = g_strdup_printf ("%s.%s", name,
+                                                             gxps_converter_get_extension (converter));
+                g_free (name);
+        } else {
+                print_converter->filename = g_strdup_printf ("%s.%s", basename,
+                                                             gxps_converter_get_extension (converter));
+        }
+
+        g_free (basename);
+}
+
+static void
+gxps_converter_print_get_fit_to_page_transform (GXPSPrintConverter *print_converter,
+                                                gdouble             page_width,
+                                                gdouble             page_height,
+                                                gdouble             paper_width,
+                                                gdouble             paper_height,
+                                                cairo_matrix_t     *matrix)
+{
+        gdouble x_scale, y_scale;
+        gdouble scale;
+
+        x_scale = paper_width / page_width;
+        y_scale = paper_height / page_height;
+        scale = (x_scale < y_scale) ? x_scale : y_scale;
+
+        cairo_matrix_init_identity (matrix);
+        if (scale > 1.0) {
+                /* Page is smaller than paper */
+                if (print_converter->flags & GXPS_PRINT_CONVERTER_EXPAND) {
+                        cairo_matrix_scale (matrix, scale, scale);
+                } else if (print_converter->flags & GXPS_PRINT_CONVERTER_CENTER) {
+                        cairo_matrix_translate (matrix,
+                                                (paper_width - page_width) / 2,
+                                                (paper_height - page_height) / 2);
+                } else {
+                        if (!print_converter->upside_down_coords) {
+                                /* Move to PostScript origin */
+                                cairo_matrix_translate (matrix, 0, (paper_height - page_height));
+                        }
+                }
+        } else if (scale < 1.0) {
+                /* Page is larger than paper */
+                if (print_converter->flags & GXPS_PRINT_CONVERTER_SHRINK)
+                        cairo_matrix_scale (matrix, scale, scale);
+        }
+}
+
+static cairo_t *
+gxps_converter_print_converter_begin_page (GXPSConverter *converter,
+                                           GXPSPage      *page,
+                                           guint          n_page)
+{
+        GXPSPrintConverter *print_converter = GXPS_PRINT_CONVERTER (converter);
+        guint               page_width, page_height;
+        gdouble             cropped_width, cropped_height;
+        gdouble             output_width, output_height;
+        cairo_matrix_t      matrix;
+        cairo_t            *cr;
+
+        g_return_val_if_fail (converter->surface != NULL, NULL);
+
+        cairo_surface_set_fallback_resolution (converter->surface,
+                                               converter->x_resolution,
+                                               converter->y_resolution);
+        cr = cairo_create (converter->surface);
+        cairo_translate (cr, -converter->crop.x, -converter->crop.y);
+
+        gxps_page_get_size (page, &page_width, &page_height);
+        gxps_converter_get_crop_size (converter,
+                                      (gdouble)page_width, (gdouble)page_height,
+                                      &cropped_width, &cropped_height);
+        _gxps_converter_print_get_output_size (print_converter, page,
+                                               &output_width, &output_height);
+        gxps_converter_print_get_fit_to_page_transform (print_converter,
+                                                        cropped_width, cropped_height,
+                                                        output_width, output_height,
+                                                        &matrix);
+        cairo_transform (cr, &matrix);
+        cairo_rectangle (cr, converter->crop.x, converter->crop.y, cropped_width, cropped_height);
+        cairo_clip (cr);
+
+        return cr;
+}
+
+static void
+gxps_converter_print_converter_end_page (GXPSConverter *converter)
+{
+        g_return_if_fail (converter->surface != NULL);
+
+        cairo_surface_show_page (converter->surface);
+}
+
+static void
+gxps_converter_print_converter_end_document (GXPSConverter *converter)
+{
+        GXPSPrintConverter *print_converter = GXPS_PRINT_CONVERTER (converter);
+        cairo_status_t      status;
+
+        cairo_surface_finish (converter->surface);
+        status = cairo_surface_status (converter->surface);
+        if (status)
+                g_printerr ("Cairo error: %s\n", cairo_status_to_string (status));
+        cairo_surface_destroy (converter->surface);
+        converter->surface = NULL;
+
+        g_free (print_converter->filename);
+        print_converter->filename = NULL;
+}
+
+static void
+gxps_print_converter_finalize (GObject *object)
+{
+        GXPSPrintConverter *print_converter = GXPS_PRINT_CONVERTER (object);
+
+        if (print_converter->filename) {
+                g_free (print_converter->filename);
+                print_converter->filename = NULL;
+        }
+
+        G_OBJECT_CLASS (gxps_print_converter_parent_class)->finalize (object);
+}
+
+static void
+gxps_print_converter_init (GXPSPrintConverter *converter)
+{
+}
+
+static void
+gxps_print_converter_class_init (GXPSPrintConverterClass *klass)
+{
+        GObjectClass       *object_class = G_OBJECT_CLASS (klass);
+        GXPSConverterClass *converter_class = GXPS_CONVERTER_CLASS (klass);
+
+        object_class->finalize = gxps_print_converter_finalize;
+
+        converter_class->init_with_args = gxps_print_converter_init_with_args;
+        converter_class->begin_document = gxps_converter_print_converter_begin_document;
+        converter_class->begin_page = gxps_converter_print_converter_begin_page;
+        converter_class->end_page = gxps_converter_print_converter_end_page;
+        converter_class->end_document = gxps_converter_print_converter_end_document;
+}
+
+void
+_gxps_converter_print_get_output_size (GXPSPrintConverter *converter,
+                                       GXPSPage           *page,
+                                       gdouble            *output_width,
+                                       gdouble            *output_height)
+{
+        guint page_width, page_height;
+
+        gxps_page_get_size (page, &page_width, &page_height);
+
+        if (output_width) {
+                *output_width = converter->paper_width == 0 ?
+                        (gdouble)page_width : (gdouble)converter->paper_width;
+        }
+
+        if (output_height) {
+                *output_height = converter->paper_height == 0 ?
+                        (gdouble)page_height : (gdouble)converter->paper_height;
+        }
+}
diff --git a/tools/gxps-print-converter.h b/tools/gxps-print-converter.h
new file mode 100644
index 0000000..dac9c59
--- /dev/null
+++ b/tools/gxps-print-converter.h
@@ -0,0 +1,66 @@
+/* GXPSPrintConverter
+ *
+ * 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_PRINT_CONVERTER_H__
+#define __GXPS_PRINT_CONVERTER_H__
+
+#include "gxps-converter.h"
+
+G_BEGIN_DECLS
+
+#define GXPS_TYPE_PRINT_CONVERTER           (gxps_print_converter_get_type ())
+#define GXPS_PRINT_CONVERTER(obj)           (G_TYPE_CHECK_INSTANCE_CAST (obj, GXPS_TYPE_PRINT_CONVERTER, GXPSPrintConverter))
+#define GXPS_PRINT_CONVERTER_CLASS(cls)     (G_TYPE_CHECK_CLASS_CAST (cls, GXPS_TYPE_PRINT_CONVERTER, GXPSPrintConverterClass))
+#define GXPS_IS_PRINT_CONVERTER(obj)        (G_TYPE_CHECK_INSTANCE_TYPE (obj, GXPS_TYPE_PRINT_CONVERTER))
+#define GXPS_IS_PRINT_CONVERTER_CLASS(obj)  (G_TYPE_CHECK_CLASS_TYPE (obj, GXPS_TYPE_PRINT_CONVERTER))
+#define GXPS_PRINT_CONVERTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GXPS_TYPE_PRINT_CONVERTER, GXPSPrintConverterClass))
+
+typedef enum {
+        GXPS_PRINT_CONVERTER_EXPAND = 1 << 0,
+        GXPS_PRINT_CONVERTER_SHRINK = 1 << 1,
+        GXPS_PRINT_CONVERTER_CENTER = 1 << 2
+} GXPSPrintConverterFlags;
+
+typedef struct _GXPSPrintConverter        GXPSPrintConverter;
+typedef struct _GXPSPrintConverterClass   GXPSPrintConverterClass;
+
+struct _GXPSPrintConverter {
+	GXPSConverter parent;
+
+        gchar                  *filename;
+        guint                   paper_width;
+        guint                   paper_height;
+        GXPSPrintConverterFlags flags;
+        guint                   upside_down_coords : 1;
+};
+
+struct _GXPSPrintConverterClass {
+	GXPSConverterClass parent_class;
+};
+
+GType gxps_print_converter_get_type        (void);
+
+void _gxps_converter_print_get_output_size (GXPSPrintConverter *converter,
+                                            GXPSPage           *page,
+                                            gdouble            *output_width,
+                                            gdouble            *output_height);
+
+G_END_DECLS
+
+#endif /* __GXPS_PRINT_CONVERTER_H__ */



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