diff options
Diffstat (limited to 'src/book.c')
-rw-r--r-- | src/book.c | 2925 |
1 files changed, 2168 insertions, 757 deletions
@@ -1,7 +1,10 @@ +/* book.c generated by valac 0.13.1, the Vala compiler + * generated from book.vala, do not modify */ + /* - * Copyright (C) 2009 Canonical Ltd. + * Copyright (C) 2009-2011 Canonical Ltd. * Author: Robert Ancell <robert.ancell@canonical.com> - * + * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later @@ -9,870 +12,2278 @@ * license. */ -#include <stdio.h> +#include <glib.h> +#include <glib-object.h> +#include <stdlib.h> #include <string.h> +#include <gio/gio.h> +#include <cairo.h> +#include <gdk-pixbuf/gdk-pixdata.h> +#include <float.h> #include <math.h> +#include <gdk/gdk.h> +#include <cairo-ps.h> #include <zlib.h> #include <jpeglib.h> -#include <gdk/gdk.h> -#include <gdk-pixbuf/gdk-pixbuf.h> -#include <cairo/cairo-pdf.h> -#include <cairo/cairo-ps.h> +#include <config.h> +#include <gobject/gvaluecollector.h> + + +#define TYPE_BOOK (book_get_type ()) +#define BOOK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_BOOK, Book)) +#define BOOK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_BOOK, BookClass)) +#define IS_BOOK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_BOOK)) +#define IS_BOOK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_BOOK)) +#define BOOK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_BOOK, BookClass)) + +typedef struct _Book Book; +typedef struct _BookClass BookClass; +typedef struct _BookPrivate BookPrivate; + +#define TYPE_PAGE (page_get_type ()) +#define PAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PAGE, Page)) +#define PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PAGE, PageClass)) +#define IS_PAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PAGE)) +#define IS_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PAGE)) +#define PAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PAGE, PageClass)) + +typedef struct _Page Page; +typedef struct _PageClass PageClass; +#define __g_list_free__page_unref0_0(var) ((var == NULL) ? NULL : (var = (_g_list_free__page_unref0_ (var), NULL))) + +#define TYPE_SCAN_DIRECTION (scan_direction_get_type ()) +#define _page_unref0(var) ((var == NULL) ? NULL : (var = (page_unref (var), NULL))) +#define _g_free0(var) (var = (g_free (var), NULL)) +#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL))) +#define _cairo_destroy0(var) ((var == NULL) ? NULL : (var = (cairo_destroy (var), NULL))) + +#define TYPE_PS_WRITER (ps_writer_get_type ()) +#define PS_WRITER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PS_WRITER, PsWriter)) +#define PS_WRITER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PS_WRITER, PsWriterClass)) +#define IS_PS_WRITER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PS_WRITER)) +#define IS_PS_WRITER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PS_WRITER)) +#define PS_WRITER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PS_WRITER, PsWriterClass)) + +typedef struct _PsWriter PsWriter; +typedef struct _PsWriterClass PsWriterClass; +typedef struct _PsWriterPrivate PsWriterPrivate; +#define _cairo_surface_destroy0(var) ((var == NULL) ? NULL : (var = (cairo_surface_destroy (var), NULL))) +#define _ps_writer_unref0(var) ((var == NULL) ? NULL : (var = (ps_writer_unref (var), NULL))) + +#define TYPE_PDF_WRITER (pdf_writer_get_type ()) +#define PDF_WRITER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PDF_WRITER, PDFWriter)) +#define PDF_WRITER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PDF_WRITER, PDFWriterClass)) +#define IS_PDF_WRITER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PDF_WRITER)) +#define IS_PDF_WRITER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PDF_WRITER)) +#define PDF_WRITER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PDF_WRITER, PDFWriterClass)) + +typedef struct _PDFWriter PDFWriter; +typedef struct _PDFWriterClass PDFWriterClass; +typedef struct _PDFWriterPrivate PDFWriterPrivate; +#define _pdf_writer_unref0(var) ((var == NULL) ? NULL : (var = (pdf_writer_unref (var), NULL))) +typedef struct _ParamSpecBook ParamSpecBook; +#define _g_list_free0(var) ((var == NULL) ? NULL : (var = (g_list_free (var), NULL))) +#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL))) +typedef struct _ParamSpecPDFWriter ParamSpecPDFWriter; +typedef struct _ParamSpecPsWriter ParamSpecPsWriter; + +struct _Book { + GTypeInstance parent_instance; + volatile int ref_count; + BookPrivate * priv; +}; + +struct _BookClass { + GTypeClass parent_class; + void (*finalize) (Book *self); +}; + +struct _BookPrivate { + GList* pages; + gboolean needs_saving; +}; + +typedef enum { + SCAN_DIRECTION_TOP_TO_BOTTOM, + SCAN_DIRECTION_LEFT_TO_RIGHT, + SCAN_DIRECTION_BOTTOM_TO_TOP, + SCAN_DIRECTION_RIGHT_TO_LEFT +} ScanDirection; + +struct _PsWriter { + GTypeInstance parent_instance; + volatile int ref_count; + PsWriterPrivate * priv; + cairo_surface_t* surface; + GFileOutputStream* stream; +}; -#include "book.h" +struct _PsWriterClass { + GTypeClass parent_class; + void (*finalize) (PsWriter *self); +}; -enum { - PROP_0, - PROP_NEEDS_SAVING +struct _PDFWriter { + GTypeInstance parent_instance; + volatile int ref_count; + PDFWriterPrivate * priv; + gsize offset; + GList* object_offsets; }; -enum { - PAGE_ADDED, - PAGE_REMOVED, - REORDERED, - CLEARED, - LAST_SIGNAL +struct _PDFWriterClass { + GTypeClass parent_class; + void (*finalize) (PDFWriter *self); }; -static guint signals[LAST_SIGNAL] = { 0, }; -struct BookPrivate -{ - GList *pages; - - gboolean needs_saving; +struct _ParamSpecBook { + GParamSpec parent_instance; }; -G_DEFINE_TYPE (Book, book, G_TYPE_OBJECT); +struct _PDFWriterPrivate { + GFileOutputStream* stream; +}; + +struct _ParamSpecPDFWriter { + GParamSpec parent_instance; +}; + +struct _ParamSpecPsWriter { + GParamSpec parent_instance; +}; + + +static gpointer book_parent_class = NULL; +static gpointer pdf_writer_parent_class = NULL; +static gpointer ps_writer_parent_class = NULL; + +gpointer book_ref (gpointer instance); +void book_unref (gpointer instance); +GParamSpec* param_spec_book (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_book (GValue* value, gpointer v_object); +void value_take_book (GValue* value, gpointer v_object); +gpointer value_get_book (const GValue* value); +GType book_get_type (void) G_GNUC_CONST; +gpointer page_ref (gpointer instance); +void page_unref (gpointer instance); +GParamSpec* param_spec_page (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_page (GValue* value, gpointer v_object); +void value_take_page (GValue* value, gpointer v_object); +gpointer value_get_page (const GValue* value); +GType page_get_type (void) G_GNUC_CONST; +#define BOOK_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_BOOK, BookPrivate)) +enum { + BOOK_DUMMY_PROPERTY +}; +static void _page_unref0_ (gpointer var); +static void _g_list_free__page_unref0_ (GList* self); +Book* book_new (void); +Book* book_construct (GType object_type); +void book_clear (Book* self); +static void book_page_changed_cb (Book* self, Page* page); +void book_set_needs_saving (Book* self, gboolean needs_saving); +GType scan_direction_get_type (void) G_GNUC_CONST; +Page* book_append_page (Book* self, gint width, gint height, gint dpi, ScanDirection scan_direction); +Page* page_new (gint width, gint height, gint dpi, ScanDirection scan_direction); +Page* page_construct (GType object_type, gint width, gint height, gint dpi, ScanDirection scan_direction); +static void _book_page_changed_cb_page_pixels_changed (Page* _sender, gpointer self); +static void _book_page_changed_cb_page_crop_changed (Page* _sender, gpointer self); +void book_move_page (Book* self, Page* page, guint location); +void book_delete_page (Book* self, Page* page); +guint book_get_n_pages (Book* self); +Page* book_get_page (Book* self, gint page_number); +guint book_get_page_index (Book* self, Page* page); +static GFile* book_make_indexed_file (Book* self, const gchar* uri, gint i); +static void book_save_multi_file (Book* self, const gchar* type, GFile* file, GError** error); +void page_save (Page* self, const gchar* type, GFile* file, GError** error); +static void book_save_ps_pdf_surface (Book* self, cairo_surface_t* surface, GdkPixbuf* image, gdouble dpi); +static void book_save_ps (Book* self, GFile* file, GError** error); +PsWriter* ps_writer_new (GFileOutputStream* stream); +PsWriter* ps_writer_construct (GType object_type, GFileOutputStream* stream); +gpointer ps_writer_ref (gpointer instance); +void ps_writer_unref (gpointer instance); +GParamSpec* param_spec_ps_writer (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_ps_writer (GValue* value, gpointer v_object); +void value_take_ps_writer (GValue* value, gpointer v_object); +gpointer value_get_ps_writer (const GValue* value); +GType ps_writer_get_type (void) G_GNUC_CONST; +GdkPixbuf* page_get_image (Page* self, gboolean apply_crop); +gint page_get_dpi (Page* self); +static guint8* book_compress_zlib (Book* self, guint8* data, int data_length1, int* result_length1); +static void book_jpeg_init_cb (struct jpeg_compress_struct* info); +static gboolean book_jpeg_empty_cb (struct jpeg_compress_struct* info); +static void book_jpeg_term_cb (struct jpeg_compress_struct* info); +static guint8* book_compress_jpeg (Book* self, GdkPixbuf* image, gsize* n_written, int* result_length1); +static void _book_jpeg_init_cb_jpeg_initdestinationfunc (struct jpeg_compress_struct* cinfo); +static gboolean _book_jpeg_empty_cb_jpeg_emptyoutputbufferfunc (struct jpeg_compress_struct* cinfo); +static void _book_jpeg_term_cb_jpeg_termdestinationfunc (struct jpeg_compress_struct* cinfo); +static void book_save_pdf (Book* self, GFile* file, GError** error); +PDFWriter* pdf_writer_new (GFileOutputStream* stream); +PDFWriter* pdf_writer_construct (GType object_type, GFileOutputStream* stream); +gpointer pdf_writer_ref (gpointer instance); +void pdf_writer_unref (gpointer instance); +GParamSpec* param_spec_pdf_writer (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_pdf_writer (GValue* value, gpointer v_object); +void value_take_pdf_writer (GValue* value, gpointer v_object); +gpointer value_get_pdf_writer (const GValue* value); +GType pdf_writer_get_type (void) G_GNUC_CONST; +void pdf_writer_write_string (PDFWriter* self, const gchar* text); +guint pdf_writer_start_object (PDFWriter* self); +gboolean page_is_color (Page* self); +gint page_get_depth (Page* self); +static guint8* _vala_array_dup1 (guint8* self, int length); +static guint8* _vala_array_dup2 (guint8* self, int length); +void pdf_writer_write (PDFWriter* self, guint8* data, int data_length1); +void book_save (Book* self, const gchar* type, GFile* file, GError** error); +gboolean book_get_needs_saving (Book* self); +static void g_cclosure_user_marshal_VOID__PAGE (GClosure * closure, GValue * return_value, guint n_param_values, const GValue * param_values, gpointer invocation_hint, gpointer marshal_data); +static void book_finalize (Book* obj); +#define PDF_WRITER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_PDF_WRITER, PDFWriterPrivate)) +enum { + PDF_WRITER_DUMMY_PROPERTY +}; +static void pdf_writer_finalize (PDFWriter* obj); +enum { + PS_WRITER_DUMMY_PROPERTY +}; +static cairo_status_t ps_writer_write_cairo_data (PsWriter* self, guint8* data, int data_length1); +static cairo_status_t _ps_writer_write_cairo_data_cairo_write_func_t (gpointer self, guchar* data, int data_length1); +static void ps_writer_finalize (PsWriter* obj); + + +static void _page_unref0_ (gpointer var) { + (var == NULL) ? NULL : (var = (page_unref (var), NULL)); +} + + +static void _g_list_free__page_unref0_ (GList* self) { + g_list_foreach (self, (GFunc) _page_unref0_, NULL); + g_list_free (self); +} + + +Book* book_construct (GType object_type) { + Book* self = NULL; + self = (Book*) g_type_create_instance (object_type); + return self; +} + + +Book* book_new (void) { + return book_construct (TYPE_BOOK); +} + + +void book_clear (Book* self) { + g_return_if_fail (self != NULL); + __g_list_free__page_unref0_0 (self->priv->pages); + self->priv->pages = NULL; + g_signal_emit_by_name (self, "cleared"); +} + + +static void book_page_changed_cb (Book* self, Page* page) { + g_return_if_fail (self != NULL); + g_return_if_fail (page != NULL); + book_set_needs_saving (self, TRUE); +} + + +static void _book_page_changed_cb_page_pixels_changed (Page* _sender, gpointer self) { + book_page_changed_cb (self, _sender); +} + + +static void _book_page_changed_cb_page_crop_changed (Page* _sender, gpointer self) { + book_page_changed_cb (self, _sender); +} + + +static gpointer _page_ref0 (gpointer self) { + return self ? page_ref (self) : NULL; +} + + +Page* book_append_page (Book* self, gint width, gint height, gint dpi, ScanDirection scan_direction) { + Page* result = NULL; + Page* _tmp0_ = NULL; + Page* page; + Page* _tmp1_; + g_return_val_if_fail (self != NULL, NULL); + _tmp0_ = page_new (width, height, dpi, scan_direction); + page = _tmp0_; + g_signal_connect (page, "pixels-changed", (GCallback) _book_page_changed_cb_page_pixels_changed, self); + g_signal_connect (page, "crop-changed", (GCallback) _book_page_changed_cb_page_crop_changed, self); + _tmp1_ = _page_ref0 (page); + self->priv->pages = g_list_append (self->priv->pages, _tmp1_); + g_signal_emit_by_name (self, "page-added", page); + book_set_needs_saving (self, TRUE); + result = page; + return result; +} + + +void book_move_page (Book* self, Page* page, guint location) { + Page* _tmp0_; + g_return_if_fail (self != NULL); + g_return_if_fail (page != NULL); + self->priv->pages = g_list_remove (self->priv->pages, page); + _tmp0_ = _page_ref0 (page); + self->priv->pages = g_list_insert (self->priv->pages, _tmp0_, (gint) location); + g_signal_emit_by_name (self, "reordered"); + book_set_needs_saving (self, TRUE); +} + + +void book_delete_page (Book* self, Page* page) { + guint _tmp0_; + guint _tmp1_; + g_return_if_fail (self != NULL); + g_return_if_fail (page != NULL); + g_signal_parse_name ("pixels-changed", TYPE_PAGE, &_tmp0_, NULL, FALSE); + g_signal_handlers_disconnect_matched (page, G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, _tmp0_, 0, NULL, (GCallback) _book_page_changed_cb_page_pixels_changed, self); + g_signal_parse_name ("crop-changed", TYPE_PAGE, &_tmp1_, NULL, FALSE); + g_signal_handlers_disconnect_matched (page, G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, _tmp1_, 0, NULL, (GCallback) _book_page_changed_cb_page_crop_changed, self); + g_signal_emit_by_name (self, "page-removed", page); + self->priv->pages = g_list_remove (self->priv->pages, page); + book_set_needs_saving (self, TRUE); +} + + +guint book_get_n_pages (Book* self) { + guint result = 0U; + guint _tmp0_; + g_return_val_if_fail (self != NULL, 0U); + _tmp0_ = g_list_length (self->priv->pages); + result = _tmp0_; + return result; +} + + +Page* book_get_page (Book* self, gint page_number) { + Page* result = NULL; + gconstpointer _tmp1_ = NULL; + Page* _tmp2_; + g_return_val_if_fail (self != NULL, NULL); + if (page_number < 0) { + guint _tmp0_; + _tmp0_ = g_list_length (self->priv->pages); + page_number = ((gint) _tmp0_) + page_number; + } + _tmp1_ = g_list_nth_data (self->priv->pages, (guint) page_number); + _tmp2_ = _page_ref0 ((Page*) _tmp1_); + result = _tmp2_; + return result; +} + + +guint book_get_page_index (Book* self, Page* page) { + guint result = 0U; + gint _tmp0_; + g_return_val_if_fail (self != NULL, 0U); + g_return_val_if_fail (page != NULL, 0U); + _tmp0_ = g_list_index (self->priv->pages, page); + result = (guint) _tmp0_; + return result; +} + + +static gint string_last_index_of_char (const gchar* self, gunichar c, gint start_index) { + gint result = 0; + gchar* _tmp0_ = NULL; + gchar* _result_; + g_return_val_if_fail (self != NULL, 0); + _tmp0_ = g_utf8_strrchr (((gchar*) self) + start_index, (gssize) (-1), c); + _result_ = _tmp0_; + if (_result_ != NULL) { + result = (gint) (_result_ - ((gchar*) self)); + return result; + } else { + result = -1; + return result; + } +} + + +static gchar* string_slice (const gchar* self, glong start, glong end) { + gchar* result = NULL; + gint _tmp0_; + glong string_length; + gboolean _tmp1_ = FALSE; + gboolean _tmp2_ = FALSE; + gchar* _tmp3_ = NULL; + g_return_val_if_fail (self != NULL, NULL); + _tmp0_ = strlen (self); + string_length = (glong) _tmp0_; + if (start < ((glong) 0)) { + start = string_length + start; + } + if (end < ((glong) 0)) { + end = string_length + end; + } + if (start >= ((glong) 0)) { + _tmp1_ = start <= string_length; + } else { + _tmp1_ = FALSE; + } + g_return_val_if_fail (_tmp1_, NULL); + if (end >= ((glong) 0)) { + _tmp2_ = end <= string_length; + } else { + _tmp2_ = FALSE; + } + g_return_val_if_fail (_tmp2_, NULL); + g_return_val_if_fail (start <= end, NULL); + _tmp3_ = g_strndup (((gchar*) self) + start, (gsize) (end - start)); + result = _tmp3_; + return result; +} + + +static GFile* book_make_indexed_file (Book* self, const gchar* uri, gint i) { + GFile* result = NULL; + gchar* _tmp1_ = NULL; + gchar* basename; + gchar* _tmp2_; + gchar* prefix; + gchar* _tmp3_; + gchar* suffix; + gint _tmp4_; + gint extension_index; + gchar* _tmp10_ = NULL; + gchar* _tmp11_; + GFile* _tmp12_ = NULL; + GFile* _tmp13_; + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (uri != NULL, NULL); + if (i == 0) { + GFile* _tmp0_ = NULL; + _tmp0_ = g_file_new_for_uri (uri); + result = _tmp0_; + return result; + } + _tmp1_ = g_path_get_basename (uri); + basename = _tmp1_; + _tmp2_ = g_strdup (uri); + prefix = _tmp2_; + _tmp3_ = g_strdup (""); + suffix = _tmp3_; + _tmp4_ = string_last_index_of_char (basename, (gunichar) '.', 0); + extension_index = _tmp4_; + if (extension_index >= 0) { + gint _tmp5_; + gchar* _tmp6_ = NULL; + gint _tmp7_; + gint _tmp8_; + gchar* _tmp9_ = NULL; + _tmp5_ = strlen (basename); + _tmp6_ = string_slice (basename, (glong) extension_index, (glong) _tmp5_); + _g_free0 (suffix); + suffix = _tmp6_; + _tmp7_ = strlen (uri); + _tmp8_ = strlen (suffix); + _tmp9_ = string_slice (uri, (glong) 0, (glong) (_tmp7_ - _tmp8_)); + _g_free0 (prefix); + prefix = _tmp9_; + } + _tmp10_ = g_strdup_printf ("%s-%d%s", prefix, i, suffix); + _tmp11_ = _tmp10_; + _tmp12_ = g_file_new_for_uri (_tmp11_); + _tmp13_ = _tmp12_; + _g_free0 (_tmp11_); + result = _tmp13_; + _g_free0 (suffix); + _g_free0 (prefix); + _g_free0 (basename); + return result; +} + + +static void book_save_multi_file (Book* self, const gchar* type, GFile* file, GError** error) { + gint i; + GError * _inner_error_ = NULL; + g_return_if_fail (self != NULL); + g_return_if_fail (type != NULL); + g_return_if_fail (file != NULL); + i = 0; + { + GList* page_collection = NULL; + GList* page_it = NULL; + page_collection = self->priv->pages; + for (page_it = page_collection; page_it != NULL; page_it = page_it->next) { + Page* _tmp0_; + Page* page = NULL; + _tmp0_ = _page_ref0 ((Page*) page_it->data); + page = _tmp0_; + { + gchar* _tmp1_ = NULL; + gchar* _tmp2_; + GFile* _tmp3_ = NULL; + GFile* _tmp4_; + _tmp1_ = g_file_get_uri (file); + _tmp2_ = _tmp1_; + _tmp3_ = book_make_indexed_file (self, _tmp2_, i); + _tmp4_ = _tmp3_; + page_save (page, type, _tmp4_, &_inner_error_); + _g_object_unref0 (_tmp4_); + _g_free0 (_tmp2_); + if (_inner_error_ != NULL) { + g_propagate_error (error, _inner_error_); + _page_unref0 (page); + return; + } + i++; + _page_unref0 (page); + } + } + } +} + + +static void book_save_ps_pdf_surface (Book* self, cairo_surface_t* surface, GdkPixbuf* image, gdouble dpi) { + cairo_t* _tmp0_ = NULL; + cairo_t* context; + cairo_pattern_t* _tmp1_ = NULL; + g_return_if_fail (self != NULL); + g_return_if_fail (surface != NULL); + g_return_if_fail (image != NULL); + _tmp0_ = cairo_create (surface); + context = _tmp0_; + cairo_scale (context, 72.0 / dpi, 72.0 / dpi); + gdk_cairo_set_source_pixbuf (context, image, (gdouble) 0, (gdouble) 0); + _tmp1_ = cairo_get_source (context); + cairo_pattern_set_filter (_tmp1_, CAIRO_FILTER_BEST); + cairo_paint (context); + _cairo_destroy0 (context); +} + + +static gpointer _cairo_surface_reference0 (gpointer self) { + return self ? cairo_surface_reference (self) : NULL; +} + + +static void book_save_ps (Book* self, GFile* file, GError** error) { + GFileOutputStream* _tmp0_ = NULL; + GFileOutputStream* stream; + PsWriter* _tmp1_ = NULL; + PsWriter* writer; + cairo_surface_t* _tmp2_; + cairo_surface_t* surface; + GError * _inner_error_ = NULL; + g_return_if_fail (self != NULL); + g_return_if_fail (file != NULL); + _tmp0_ = g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &_inner_error_); + stream = _tmp0_; + if (_inner_error_ != NULL) { + g_propagate_error (error, _inner_error_); + return; + } + _tmp1_ = ps_writer_new (stream); + writer = _tmp1_; + _tmp2_ = _cairo_surface_reference0 (writer->surface); + surface = _tmp2_; + { + GList* page_collection = NULL; + GList* page_it = NULL; + page_collection = self->priv->pages; + for (page_it = page_collection; page_it != NULL; page_it = page_it->next) { + Page* _tmp3_; + Page* page = NULL; + _tmp3_ = _page_ref0 ((Page*) page_it->data); + page = _tmp3_; + { + GdkPixbuf* _tmp4_ = NULL; + GdkPixbuf* image; + gint _tmp5_; + gint _tmp6_; + gdouble width; + gint _tmp7_; + gint _tmp8_; + gdouble height; + gint _tmp9_; + _tmp4_ = page_get_image (page, TRUE); + image = _tmp4_; + _tmp5_ = gdk_pixbuf_get_width (image); + _tmp6_ = page_get_dpi (page); + width = (_tmp5_ * 72.0) / _tmp6_; + _tmp7_ = gdk_pixbuf_get_height (image); + _tmp8_ = page_get_dpi (page); + height = (_tmp7_ * 72.0) / _tmp8_; + cairo_ps_surface_set_size (surface, width, height); + _tmp9_ = page_get_dpi (page); + book_save_ps_pdf_surface (self, surface, image, (gdouble) _tmp9_); + cairo_surface_show_page (surface); + _g_object_unref0 (image); + _page_unref0 (page); + } + } + } + _cairo_surface_destroy0 (surface); + _ps_writer_unref0 (writer); + _g_object_unref0 (stream); +} + + +static guint8* book_compress_zlib (Book* self, guint8* data, int data_length1, int* result_length1) { + guint8* result = NULL; + z_stream stream = {0}; + guint8* _tmp0_ = NULL; + guint8* out_data; + gint out_data_length1; + gint _out_data_size_; + guint n_written; + gint _tmp3_; + guint8* _tmp4_; + g_return_val_if_fail (self != NULL, NULL); + deflateInit (&stream, (gint) Z_BEST_COMPRESSION); + _tmp0_ = g_new0 (guint8, data_length1); + out_data = _tmp0_; + out_data_length1 = data_length1; + _out_data_size_ = out_data_length1; + stream.next_in = data; + stream.avail_in = data_length1; + stream.next_out = out_data; + stream.avail_out = out_data_length1; + while (TRUE) { + gint _tmp1_; + if (!(stream.avail_in > ((guint) 0))) { + break; + } + _tmp1_ = deflate (&stream, (gint) Z_FINISH); + if (_tmp1_ == ((gint) Z_STREAM_ERROR)) { + break; + } + } + if (stream.avail_in > ((guint) 0)) { + guint8* _tmp2_; + _tmp2_ = NULL; + if (result_length1) { + *result_length1 = 0; + } + result = _tmp2_; + out_data = (g_free (out_data), NULL); + deflateEnd (&stream); + return result; + } + n_written = data_length1 - stream.avail_out; + _tmp3_ = (gint) n_written; + out_data = g_renew (guint8, out_data, (gint) n_written); + (_tmp3_ > out_data_length1) ? memset (out_data + out_data_length1, 0, sizeof (guint8) * (_tmp3_ - out_data_length1)) : NULL; + out_data_length1 = _tmp3_; + _out_data_size_ = _tmp3_; + _tmp4_ = out_data; + if (result_length1) { + *result_length1 = out_data_length1; + } + result = _tmp4_; + deflateEnd (&stream); + return result; +} + + +static void book_jpeg_init_cb (struct jpeg_compress_struct* info) { +} + + +static gboolean book_jpeg_empty_cb (struct jpeg_compress_struct* info) { + gboolean result = FALSE; + result = TRUE; + return result; +} + + +static void book_jpeg_term_cb (struct jpeg_compress_struct* info) { +} + + +static void _book_jpeg_init_cb_jpeg_initdestinationfunc (struct jpeg_compress_struct* cinfo) { + book_jpeg_init_cb (cinfo); +} + + +static gboolean _book_jpeg_empty_cb_jpeg_emptyoutputbufferfunc (struct jpeg_compress_struct* cinfo) { + gboolean result; + result = book_jpeg_empty_cb (cinfo); + return result; +} + + +static void _book_jpeg_term_cb_jpeg_termdestinationfunc (struct jpeg_compress_struct* cinfo) { + book_jpeg_term_cb (cinfo); +} + + +static guint8* book_compress_jpeg (Book* self, GdkPixbuf* image, gsize* n_written, int* result_length1) { + gsize _n_written = 0UL; + guint8* result = NULL; + struct jpeg_compress_struct info = {0}; + struct jpeg_error_mgr jerr = {0}; + struct jpeg_destination_mgr dest_mgr = {0}; + struct jpeg_error_mgr* _tmp0_ = NULL; + gint _tmp1_; + gint _tmp2_; + gint max_length; + guint8* _tmp3_ = NULL; + guint8* data; + gint data_length1; + gint _data_size_; + guint8* _tmp4_ = NULL; + guint8* pixels; + gint pixels_length1; + gint _pixels_size_; + guint8* _tmp7_; + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (image != NULL, NULL); + memset (&info, 0, sizeof (struct jpeg_compress_struct)); + memset (&jerr, 0, sizeof (struct jpeg_error_mgr)); + memset (&dest_mgr, 0, sizeof (struct jpeg_destination_mgr)); + _tmp0_ = jpeg_std_error (&jerr); + info.err = _tmp0_; + jpeg_create_compress (&info); + _tmp1_ = gdk_pixbuf_get_width (image); + info.image_width = _tmp1_; + _tmp2_ = gdk_pixbuf_get_height (image); + info.image_height = _tmp2_; + info.input_components = 3; + info.in_color_space = JCS_RGB; + jpeg_set_defaults (&info); + max_length = (info.image_width * info.image_height) * info.input_components; + _tmp3_ = g_new0 (guint8, max_length); + data = _tmp3_; + data_length1 = max_length; + _data_size_ = data_length1; + dest_mgr.next_output_byte = data; + dest_mgr.free_in_buffer = max_length; + dest_mgr.init_destination = _book_jpeg_init_cb_jpeg_initdestinationfunc; + dest_mgr.empty_output_buffer = _book_jpeg_empty_cb_jpeg_emptyoutputbufferfunc; + dest_mgr.term_destination = _book_jpeg_term_cb_jpeg_termdestinationfunc; + info.dest = &dest_mgr; + jpeg_start_compress (&info, TRUE); + _tmp4_ = gdk_pixbuf_get_pixels (image); + pixels = _tmp4_; + pixels_length1 = -1; + _pixels_size_ = pixels_length1; + { + gint r; + r = 0; + { + gboolean _tmp5_; + _tmp5_ = TRUE; + while (TRUE) { + guint8* row[1] = {0}; + gint _tmp6_; + if (!_tmp5_) { + r++; + } + _tmp5_ = FALSE; + if (!(r < info.image_height)) { + break; + } + _tmp6_ = gdk_pixbuf_get_rowstride (image); + row[0] = ((guint8*) pixels) + (r * _tmp6_); + jpeg_write_scanlines (&info, row, 1); + } + } + } + jpeg_finish_compress (&info); + _n_written = (gsize) (max_length - dest_mgr.free_in_buffer); + _tmp7_ = data; + if (result_length1) { + *result_length1 = data_length1; + } + result = _tmp7_; + jpeg_destroy_compress (&info); + if (n_written) { + *n_written = _n_written; + } + return result; +} + + +static guint8* _vala_array_dup1 (guint8* self, int length) { + return g_memdup (self, length * sizeof (guint8)); +} + + +static guint8* _vala_array_dup2 (guint8* self, int length) { + return g_memdup (self, length * sizeof (guint8)); +} + + +static void book_save_pdf (Book* self, GFile* file, GError** error) { + GFileOutputStream* _tmp0_ = NULL; + GFileOutputStream* stream; + PDFWriter* _tmp1_ = NULL; + PDFWriter* writer; + guint _tmp2_; + guint catalog_number; + gchar* _tmp3_ = NULL; + gchar* _tmp4_; + gchar* _tmp5_ = NULL; + gchar* _tmp6_; + guint _tmp7_; + guint pages_number; + gchar* _tmp8_ = NULL; + gchar* _tmp9_; + guint _tmp14_; + gchar* _tmp15_ = NULL; + gchar* _tmp16_; + guint _tmp100_; + guint info_number; + gchar* _tmp101_ = NULL; + gchar* _tmp102_; + gchar* _tmp103_ = NULL; + gchar* _tmp104_; + gsize xref_offset; + guint _tmp105_; + gchar* _tmp106_ = NULL; + gchar* _tmp107_; + guint _tmp110_; + gchar* _tmp111_ = NULL; + gchar* _tmp112_; + gchar* _tmp113_ = NULL; + gchar* _tmp114_; + gchar* _tmp115_ = NULL; + gchar* _tmp116_; + gchar* _tmp117_ = NULL; + gchar* _tmp118_; + GError * _inner_error_ = NULL; + g_return_if_fail (self != NULL); + g_return_if_fail (file != NULL); + _tmp0_ = g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &_inner_error_); + stream = _tmp0_; + if (_inner_error_ != NULL) { + g_propagate_error (error, _inner_error_); + return; + } + _tmp1_ = pdf_writer_new (stream); + writer = _tmp1_; + pdf_writer_write_string (writer, "%%PDF-1.3\n"); + pdf_writer_write_string (writer, "%%\xe2\xe3\xcf\xd3\n"); + _tmp2_ = pdf_writer_start_object (writer); + catalog_number = _tmp2_; + _tmp3_ = g_strdup_printf ("%u 0 obj\n", catalog_number); + _tmp4_ = _tmp3_; + pdf_writer_write_string (writer, _tmp4_); + _g_free0 (_tmp4_); + pdf_writer_write_string (writer, "<<\n"); + pdf_writer_write_string (writer, "/Type /Catalog\n"); + _tmp5_ = g_strdup_printf ("/Pages %u 0 R\n", catalog_number + 1); + _tmp6_ = _tmp5_; + pdf_writer_write_string (writer, _tmp6_); + _g_free0 (_tmp6_); + pdf_writer_write_string (writer, ">>\n"); + pdf_writer_write_string (writer, "endobj\n"); + pdf_writer_write_string (writer, "\n"); + _tmp7_ = pdf_writer_start_object (writer); + pages_number = _tmp7_; + _tmp8_ = g_strdup_printf ("%u 0 obj\n", pages_number); + _tmp9_ = _tmp8_; + pdf_writer_write_string (writer, _tmp9_); + _g_free0 (_tmp9_); + pdf_writer_write_string (writer, "<<\n"); + pdf_writer_write_string (writer, "/Type /Pages\n"); + pdf_writer_write_string (writer, "/Kids ["); + { + gint i; + i = 0; + { + gboolean _tmp10_; + _tmp10_ = TRUE; + while (TRUE) { + guint _tmp11_; + gchar* _tmp12_ = NULL; + gchar* _tmp13_; + if (!_tmp10_) { + i++; + } + _tmp10_ = FALSE; + _tmp11_ = book_get_n_pages (self); + if (!(((guint) i) < _tmp11_)) { + break; + } + _tmp12_ = g_strdup_printf (" %u 0 R", (pages_number + 1) + (i * 3)); + _tmp13_ = _tmp12_; + pdf_writer_write_string (writer, _tmp13_); + _g_free0 (_tmp13_); + } + } + } + pdf_writer_write_string (writer, " ]\n"); + _tmp14_ = book_get_n_pages (self); + _tmp15_ = g_strdup_printf ("/Count %u\n", _tmp14_); + _tmp16_ = _tmp15_; + pdf_writer_write_string (writer, _tmp16_); + _g_free0 (_tmp16_); + pdf_writer_write_string (writer, ">>\n"); + pdf_writer_write_string (writer, "endobj\n"); + { + gint i; + i = 0; + { + gboolean _tmp17_; + _tmp17_ = TRUE; + while (TRUE) { + guint _tmp18_; + Page* _tmp19_ = NULL; + Page* page; + GdkPixbuf* _tmp20_ = NULL; + GdkPixbuf* image; + gint _tmp21_; + gint width; + gint _tmp22_; + gint height; + guint8* _tmp23_ = NULL; + guint8* pixels; + gint pixels_length1; + gint _pixels_size_; + gint _tmp24_; + gdouble page_width; + gint _tmp25_; + gdouble page_height; + gint depth; + gchar* _tmp26_; + gchar* color_space; + gchar* filter; + gchar* _tmp27_ = NULL; + gchar* width_buffer; + gint width_buffer_length1; + gint _width_buffer_size_; + gchar* _tmp28_ = NULL; + gchar* height_buffer; + gint height_buffer_length1; + gint _height_buffer_size_; + guint8* data = NULL; + gint data_length1 = 0; + gint _data_size_ = 0; + gboolean _tmp29_; + gint _tmp52_; + guint8* _tmp53_ = NULL; + guint8* compressed_data; + gint compressed_data_length1; + gint _compressed_data_size_; + guint _tmp63_; + guint number; + gchar* _tmp64_ = NULL; + gchar* _tmp65_; + gchar* _tmp66_ = NULL; + gchar* _tmp67_; + gchar* _tmp68_ = NULL; + gchar* _tmp69_; + const gchar* _tmp70_ = NULL; + const gchar* _tmp71_ = NULL; + gchar* _tmp72_ = NULL; + gchar* _tmp73_; + gchar* _tmp74_ = NULL; + gchar* _tmp75_; + guint _tmp76_; + gchar* _tmp77_ = NULL; + gchar* _tmp78_; + gchar* _tmp79_ = NULL; + gchar* _tmp80_; + gchar* _tmp81_ = NULL; + gchar* _tmp82_; + gchar* _tmp83_ = NULL; + gchar* _tmp84_; + gchar* _tmp85_ = NULL; + gchar* _tmp86_; + gchar* _tmp87_ = NULL; + gchar* _tmp88_; + const gchar* _tmp91_ = NULL; + const gchar* _tmp92_ = NULL; + gchar* _tmp93_ = NULL; + gchar* command; + guint _tmp94_; + gchar* _tmp95_ = NULL; + gchar* _tmp96_; + gint _tmp97_; + gchar* _tmp98_ = NULL; + gchar* _tmp99_; + if (!_tmp17_) { + i++; + } + _tmp17_ = FALSE; + _tmp18_ = book_get_n_pages (self); + if (!(((guint) i) < _tmp18_)) { + break; + } + _tmp19_ = book_get_page (self, i); + page = _tmp19_; + _tmp20_ = page_get_image (page, TRUE); + image = _tmp20_; + _tmp21_ = gdk_pixbuf_get_width (image); + width = _tmp21_; + _tmp22_ = gdk_pixbuf_get_height (image); + height = _tmp22_; + _tmp23_ = gdk_pixbuf_get_pixels (image); + pixels = _tmp23_; + pixels_length1 = -1; + _pixels_size_ = pixels_length1; + _tmp24_ = page_get_dpi (page); + page_width = (width * 72.0) / _tmp24_; + _tmp25_ = page_get_dpi (page); + page_height = (height * 72.0) / _tmp25_; + depth = 8; + _tmp26_ = g_strdup ("DeviceRGB"); + color_space = _tmp26_; + filter = NULL; + _tmp27_ = g_new0 (gchar, G_ASCII_DTOSTR_BUF_SIZE); + width_buffer = _tmp27_; + width_buffer_length1 = G_ASCII_DTOSTR_BUF_SIZE; + _width_buffer_size_ = width_buffer_length1; + _tmp28_ = g_new0 (gchar, G_ASCII_DTOSTR_BUF_SIZE); + height_buffer = _tmp28_; + height_buffer_length1 = G_ASCII_DTOSTR_BUF_SIZE; + _height_buffer_size_ = height_buffer_length1; + _tmp29_ = page_is_color (page); + if (_tmp29_) { + gchar* _tmp30_; + gint data_length; + guint8* _tmp31_ = NULL; + depth = 8; + _tmp30_ = g_strdup ("DeviceRGB"); + _g_free0 (color_space); + color_space = _tmp30_; + data_length = ((height * width) * 3) + 1; + _tmp31_ = g_new0 (guint8, data_length); + data = (g_free (data), NULL); + data = _tmp31_; + data_length1 = data_length; + _data_size_ = data_length1; + { + gint row; + row = 0; + { + gboolean _tmp32_; + _tmp32_ = TRUE; + while (TRUE) { + gint _tmp33_; + gint in_offset; + gint out_offset; + if (!_tmp32_) { + row++; + } + _tmp32_ = FALSE; + if (!(row < height)) { + break; + } + _tmp33_ = gdk_pixbuf_get_rowstride (image); + in_offset = row * _tmp33_; + out_offset = (row * width) * 3; + { + gint x; + x = 0; + { + gboolean _tmp34_; + _tmp34_ = TRUE; + while (TRUE) { + gint in_o; + gint out_o; + if (!_tmp34_) { + x++; + } + _tmp34_ = FALSE; + if (!(x < width)) { + break; + } + in_o = in_offset + (x * 3); + out_o = out_offset + (x * 3); + data[out_o] = pixels[in_o]; + data[out_o + 1] = pixels[in_o + 1]; + data[out_o + 2] = pixels[in_o + 2]; + } + } + } + } + } + } + } else { + gint _tmp35_; + _tmp35_ = page_get_depth (page); + if (_tmp35_ == 2) { + gint shift_count; + gchar* _tmp36_; + gint data_length; + guint8* _tmp37_ = NULL; + gint offset; + shift_count = 6; + depth = 2; + _tmp36_ = g_strdup ("DeviceGray"); + _g_free0 (color_space); + color_space = _tmp36_; + data_length = height * (((width * 2) + 7) / 8); + _tmp37_ = g_new0 (guint8, data_length); + data = (g_free (data), NULL); + data = _tmp37_; + data_length1 = data_length; + _data_size_ = data_length1; + offset = 0; + data[offset] = (guint8) 0; + { + gint row; + row = 0; + { + gboolean _tmp38_; + _tmp38_ = TRUE; + while (TRUE) { + gint _tmp39_; + gint in_offset; + if (!_tmp38_) { + row++; + } + _tmp38_ = FALSE; + if (!(row < height)) { + break; + } + if (shift_count != 6) { + offset++; + data[offset] = (guint8) 0; + shift_count = 6; + } + _tmp39_ = gdk_pixbuf_get_rowstride (image); + in_offset = row * _tmp39_; + { + gint x; + x = 0; + { + gboolean _tmp40_; + _tmp40_ = TRUE; + while (TRUE) { + guint8 p; + if (!_tmp40_) { + x++; + } + _tmp40_ = FALSE; + if (!(x < width)) { + break; + } + p = pixels[in_offset + (x * 3)]; + if (((gint) p) >= 192) { + data[offset] |= (guint8) (3 << shift_count); + } else { + if (((gint) p) >= 128) { + data[offset] |= (guint8) (2 << shift_count); + } else { + if (((gint) p) >= 64) { + data[offset] |= (guint8) (1 << shift_count); + } + } + } + if (shift_count == 0) { + offset++; + data[offset] = (guint8) 0; + shift_count = 6; + } else { + shift_count = shift_count - 2; + } + } + } + } + } + } + } + } else { + gint _tmp41_; + _tmp41_ = page_get_depth (page); + if (_tmp41_ == 1) { + gint mask; + gchar* _tmp42_; + gint data_length; + guint8* _tmp43_ = NULL; + gint offset; + mask = 0x80; + depth = 1; + _tmp42_ = g_strdup ("DeviceGray"); + _g_free0 (color_space); + color_space = _tmp42_; + data_length = height * ((width + 7) / 8); + _tmp43_ = g_new0 (guint8, data_length); + data = (g_free (data), NULL); + data = _tmp43_; + data_length1 = data_length; + _data_size_ = data_length1; + offset = 0; + data[offset] = (guint8) 0; + { + gint row; + row = 0; + { + gboolean _tmp44_; + _tmp44_ = TRUE; + while (TRUE) { + gint _tmp45_; + gint in_offset; + if (!_tmp44_) { + row++; + } + _tmp44_ = FALSE; + if (!(row < height)) { + break; + } + if (mask != 0x80) { + offset++; + data[offset] = (guint8) 0; + mask = 0x80; + } + _tmp45_ = gdk_pixbuf_get_rowstride (image); + in_offset = row * _tmp45_; + { + gint x; + x = 0; + { + gboolean _tmp46_; + _tmp46_ = TRUE; + while (TRUE) { + if (!_tmp46_) { + x++; + } + _tmp46_ = FALSE; + if (!(x < width)) { + break; + } + if (((gint) pixels[in_offset + (x * 3)]) != 0) { + data[offset] |= (guint8) mask; + } + mask = mask >> 1; + if (mask == 0) { + offset++; + data[offset] = (guint8) 0; + mask = 0x80; + } + } + } + } + } + } + } + } else { + gchar* _tmp47_; + gint data_length; + guint8* _tmp48_ = NULL; + depth = 8; + _tmp47_ = g_strdup ("DeviceGray"); + _g_free0 (color_space); + color_space = _tmp47_; + data_length = (height * width) + 1; + _tmp48_ = g_new0 (guint8, data_length); + data = (g_free (data), NULL); + data = _tmp48_; + data_length1 = data_length; + _data_size_ = data_length1; + { + gint row; + row = 0; + { + gboolean _tmp49_; + _tmp49_ = TRUE; + while (TRUE) { + gint _tmp50_; + gint in_offset; + gint out_offset; + if (!_tmp49_) { + row++; + } + _tmp49_ = FALSE; + if (!(row < height)) { + break; + } + _tmp50_ = gdk_pixbuf_get_rowstride (image); + in_offset = row * _tmp50_; + out_offset = row * width; + { + gint x; + x = 0; + { + gboolean _tmp51_; + _tmp51_ = TRUE; + while (TRUE) { + if (!_tmp51_) { + x++; + } + _tmp51_ = FALSE; + if (!(x < width)) { + break; + } + data[out_offset + x] = pixels[in_offset + (x * 3)]; + } + } + } + } + } + } + } + } + } + _tmp53_ = book_compress_zlib (self, data, data_length1, &_tmp52_); + compressed_data = _tmp53_; + compressed_data_length1 = _tmp52_; + _compressed_data_size_ = compressed_data_length1; + if (compressed_data != NULL) { + if (depth > 1) { + gsize jpeg_length = 0UL; + gsize _tmp54_; + gint _tmp55_; + guint8* _tmp56_ = NULL; + guint8* jpeg_data; + gint jpeg_data_length1; + gint _jpeg_data_size_; + _tmp56_ = book_compress_jpeg (self, image, &_tmp54_, &_tmp55_); + jpeg_length = _tmp54_; + jpeg_data = _tmp56_; + jpeg_data_length1 = _tmp55_; + _jpeg_data_size_ = jpeg_data_length1; + if (jpeg_length < ((gsize) compressed_data_length1)) { + gchar* _tmp57_; + guint8* _tmp58_; + guint8* _tmp59_; + _tmp57_ = g_strdup ("DCTDecode"); + _g_free0 (filter); + filter = _tmp57_; + _tmp59_ = (_tmp58_ = jpeg_data, (_tmp58_ == NULL) ? ((gpointer) _tmp58_) : _vala_array_dup1 (_tmp58_, jpeg_data_length1)); + data = (g_free (data), NULL); + data = _tmp59_; + data_length1 = jpeg_data_length1; + _data_size_ = data_length1; + } + jpeg_data = (g_free (jpeg_data), NULL); + } + if (filter == NULL) { + gchar* _tmp60_; + guint8* _tmp61_; + guint8* _tmp62_; + _tmp60_ = g_strdup ("FlateDecode"); + _g_free0 (filter); + filter = _tmp60_; + _tmp62_ = (_tmp61_ = compressed_data, (_tmp61_ == NULL) ? ((gpointer) _tmp61_) : _vala_array_dup2 (_tmp61_, compressed_data_length1)); + data = (g_free (data), NULL); + data = _tmp62_; + data_length1 = compressed_data_length1; + _data_size_ = data_length1; + } + } + pdf_writer_write_string (writer, "\n"); + _tmp63_ = pdf_writer_start_object (writer); + number = _tmp63_; + _tmp64_ = g_strdup_printf ("%u 0 obj\n", number); + _tmp65_ = _tmp64_; + pdf_writer_write_string (writer, _tmp65_); + _g_free0 (_tmp65_); + pdf_writer_write_string (writer, "<<\n"); + pdf_writer_write_string (writer, "/Type /Page\n"); + _tmp66_ = g_strdup_printf ("/Parent %u 0 R\n", pages_number); + _tmp67_ = _tmp66_; + pdf_writer_write_string (writer, _tmp67_); + _g_free0 (_tmp67_); + _tmp68_ = g_strdup_printf ("/Resources << /XObject << /Im%d %u 0 R >> >>\n", i, number + 1); + _tmp69_ = _tmp68_; + pdf_writer_write_string (writer, _tmp69_); + _g_free0 (_tmp69_); + _tmp70_ = g_ascii_formatd (width_buffer, width_buffer_length1, "%.2f", page_width); + _tmp71_ = g_ascii_formatd (height_buffer, height_buffer_length1, "%.2f", page_height); + _tmp72_ = g_strdup_printf ("/MediaBox [ 0 0 %s %s ]\n", _tmp70_, _tmp71_); + _tmp73_ = _tmp72_; + pdf_writer_write_string (writer, _tmp73_); + _g_free0 (_tmp73_); + _tmp74_ = g_strdup_printf ("/Contents %u 0 R\n", number + 2); + _tmp75_ = _tmp74_; + pdf_writer_write_string (writer, _tmp75_); + _g_free0 (_tmp75_); + pdf_writer_write_string (writer, ">>\n"); + pdf_writer_write_string (writer, "endobj\n"); + pdf_writer_write_string (writer, "\n"); + _tmp76_ = pdf_writer_start_object (writer); + number = _tmp76_; + _tmp77_ = g_strdup_printf ("%u 0 obj\n", number); + _tmp78_ = _tmp77_; + pdf_writer_write_string (writer, _tmp78_); + _g_free0 (_tmp78_); + pdf_writer_write_string (writer, "<<\n"); + pdf_writer_write_string (writer, "/Type /XObject\n"); + pdf_writer_write_string (writer, "/Subtype /Image\n"); + _tmp79_ = g_strdup_printf ("/Width %d\n", width); + _tmp80_ = _tmp79_; + pdf_writer_write_string (writer, _tmp80_); + _g_free0 (_tmp80_); + _tmp81_ = g_strdup_printf ("/Height %d\n", height); + _tmp82_ = _tmp81_; + pdf_writer_write_string (writer, _tmp82_); + _g_free0 (_tmp82_); + _tmp83_ = g_strdup_printf ("/ColorSpace /%s\n", color_space); + _tmp84_ = _tmp83_; + pdf_writer_write_string (writer, _tmp84_); + _g_free0 (_tmp84_); + _tmp85_ = g_strdup_printf ("/BitsPerComponent %d\n", depth); + _tmp86_ = _tmp85_; + pdf_writer_write_string (writer, _tmp86_); + _g_free0 (_tmp86_); + _tmp87_ = g_strdup_printf ("/Length %d\n", data_length1); + _tmp88_ = _tmp87_; + pdf_writer_write_string (writer, _tmp88_); + _g_free0 (_tmp88_); + if (filter != NULL) { + gchar* _tmp89_ = NULL; + gchar* _tmp90_; + _tmp89_ = g_strdup_printf ("/Filter /%s\n", filter); + _tmp90_ = _tmp89_; + pdf_writer_write_string (writer, _tmp90_); + _g_free0 (_tmp90_); + } + pdf_writer_write_string (writer, ">>\n"); + pdf_writer_write_string (writer, "stream\n"); + pdf_writer_write (writer, data, data_length1); + pdf_writer_write_string (writer, "\n"); + pdf_writer_write_string (writer, "endstream\n"); + pdf_writer_write_string (writer, "endobj\n"); + _tmp91_ = g_ascii_formatd (width_buffer, width_buffer_length1, "%f", page_width); + _tmp92_ = g_ascii_formatd (height_buffer, height_buffer_length1, "%f", page_height); + _tmp93_ = g_strdup_printf ("q\n%s 0 0 %s 0 0 cm\n/Im%d Do\nQ", _tmp91_, _tmp92_, i); + command = _tmp93_; + pdf_writer_write_string (writer, "\n"); + _tmp94_ = pdf_writer_start_object (writer); + number = _tmp94_; + _tmp95_ = g_strdup_printf ("%u 0 obj\n", number); + _tmp96_ = _tmp95_; + pdf_writer_write_string (writer, _tmp96_); + _g_free0 (_tmp96_); + pdf_writer_write_string (writer, "<<\n"); + _tmp97_ = strlen (command); + _tmp98_ = g_strdup_printf ("/Length %d\n", _tmp97_ + 1); + _tmp99_ = _tmp98_; + pdf_writer_write_string (writer, _tmp99_); + _g_free0 (_tmp99_); + pdf_writer_write_string (writer, ">>\n"); + pdf_writer_write_string (writer, "stream\n"); + pdf_writer_write_string (writer, command); + pdf_writer_write_string (writer, "\n"); + pdf_writer_write_string (writer, "endstream\n"); + pdf_writer_write_string (writer, "endobj\n"); + _g_free0 (command); + compressed_data = (g_free (compressed_data), NULL); + data = (g_free (data), NULL); + height_buffer = (g_free (height_buffer), NULL); + width_buffer = (g_free (width_buffer), NULL); + _g_free0 (filter); + _g_free0 (color_space); + _g_object_unref0 (image); + _page_unref0 (page); + } + } + } + pdf_writer_write_string (writer, "\n"); + _tmp100_ = pdf_writer_start_object (writer); + info_number = _tmp100_; + _tmp101_ = g_strdup_printf ("%u 0 obj\n", info_number); + _tmp102_ = _tmp101_; + pdf_writer_write_string (writer, _tmp102_); + _g_free0 (_tmp102_); + pdf_writer_write_string (writer, "<<\n"); + _tmp103_ = g_strdup_printf ("/Creator (Simple Scan %s)\n", VERSION); + _tmp104_ = _tmp103_; + pdf_writer_write_string (writer, _tmp104_); + _g_free0 (_tmp104_); + pdf_writer_write_string (writer, ">>\n"); + pdf_writer_write_string (writer, "endobj\n"); + xref_offset = writer->offset; + pdf_writer_write_string (writer, "xref\n"); + _tmp105_ = g_list_length (writer->object_offsets); + _tmp106_ = g_strdup_printf ("1 %zu\n", (gsize) _tmp105_); + _tmp107_ = _tmp106_; + pdf_writer_write_string (writer, _tmp107_); + _g_free0 (_tmp107_); + { + GList* offset_collection = NULL; + GList* offset_it = NULL; + offset_collection = writer->object_offsets; + for (offset_it = offset_collection; offset_it != NULL; offset_it = offset_it->next) { + guint offset = 0U; + offset = GPOINTER_TO_UINT (offset_it->data); + { + gchar* _tmp108_ = NULL; + gchar* _tmp109_; + _tmp108_ = g_strdup_printf ("%010zu 0000 n\n", (gsize) offset); + _tmp109_ = _tmp108_; + pdf_writer_write_string (writer, _tmp109_); + _g_free0 (_tmp109_); + } + } + } + pdf_writer_write_string (writer, "trailer\n"); + pdf_writer_write_string (writer, "<<\n"); + _tmp110_ = g_list_length (writer->object_offsets); + _tmp111_ = g_strdup_printf ("/Size %zu\n", (gsize) _tmp110_); + _tmp112_ = _tmp111_; + pdf_writer_write_string (writer, _tmp112_); + _g_free0 (_tmp112_); + _tmp113_ = g_strdup_printf ("/Info %u 0 R\n", info_number); + _tmp114_ = _tmp113_; + pdf_writer_write_string (writer, _tmp114_); + _g_free0 (_tmp114_); + _tmp115_ = g_strdup_printf ("/Root %u 0 R\n", catalog_number); + _tmp116_ = _tmp115_; + pdf_writer_write_string (writer, _tmp116_); + _g_free0 (_tmp116_); + pdf_writer_write_string (writer, ">>\n"); + pdf_writer_write_string (writer, "startxref\n"); + _tmp117_ = g_strdup_printf ("%zu\n", xref_offset); + _tmp118_ = _tmp117_; + pdf_writer_write_string (writer, _tmp118_); + _g_free0 (_tmp118_); + pdf_writer_write_string (writer, "%%%%EOF\n"); + _pdf_writer_unref0 (writer); + _g_object_unref0 (stream); +} + + +void book_save (Book* self, const gchar* type, GFile* file, GError** error) { + gint _tmp0_; + GError * _inner_error_ = NULL; + g_return_if_fail (self != NULL); + g_return_if_fail (type != NULL); + g_return_if_fail (file != NULL); + _tmp0_ = g_strcmp0 (type, "jpeg"); + if (_tmp0_ == 0) { + book_save_multi_file (self, "jpeg", file, &_inner_error_); + if (_inner_error_ != NULL) { + g_propagate_error (error, _inner_error_); + return; + } + } else { + gint _tmp1_; + _tmp1_ = g_strcmp0 (type, "png"); + if (_tmp1_ == 0) { + book_save_multi_file (self, "png", file, &_inner_error_); + if (_inner_error_ != NULL) { + g_propagate_error (error, _inner_error_); + return; + } + } else { + gint _tmp2_; + _tmp2_ = g_strcmp0 (type, "tiff"); + if (_tmp2_ == 0) { + book_save_multi_file (self, "tiff", file, &_inner_error_); + if (_inner_error_ != NULL) { + g_propagate_error (error, _inner_error_); + return; + } + } else { + gint _tmp3_; + _tmp3_ = g_strcmp0 (type, "ps"); + if (_tmp3_ == 0) { + book_save_ps (self, file, &_inner_error_); + if (_inner_error_ != NULL) { + g_propagate_error (error, _inner_error_); + return; + } + } else { + gint _tmp4_; + _tmp4_ = g_strcmp0 (type, "pdf"); + if (_tmp4_ == 0) { + book_save_pdf (self, file, &_inner_error_); + if (_inner_error_ != NULL) { + g_propagate_error (error, _inner_error_); + return; + } + } + } + } + } + } +} + + +void book_set_needs_saving (Book* self, gboolean needs_saving) { + gboolean needed_saving; + g_return_if_fail (self != NULL); + needed_saving = self->priv->needs_saving; + self->priv->needs_saving = needs_saving; + if (needed_saving != needs_saving) { + g_signal_emit_by_name (self, "needs-saving-changed"); + } +} + + +gboolean book_get_needs_saving (Book* self) { + gboolean result = FALSE; + g_return_val_if_fail (self != NULL, FALSE); + result = self->priv->needs_saving; + return result; +} + + +static void g_cclosure_user_marshal_VOID__PAGE (GClosure * closure, GValue * return_value, guint n_param_values, const GValue * param_values, gpointer invocation_hint, gpointer marshal_data) { + typedef void (*GMarshalFunc_VOID__PAGE) (gpointer data1, gpointer arg_1, gpointer data2); + register GMarshalFunc_VOID__PAGE callback; + register GCClosure * cc; + register gpointer data1; + register gpointer data2; + cc = (GCClosure *) closure; + g_return_if_fail (n_param_values == 2); + if (G_CCLOSURE_SWAP_DATA (closure)) { + data1 = closure->data; + data2 = param_values->data[0].v_pointer; + } else { + data1 = param_values->data[0].v_pointer; + data2 = closure->data; + } + callback = (GMarshalFunc_VOID__PAGE) (marshal_data ? marshal_data : cc->callback); + callback (data1, value_get_page (param_values + 1), data2); +} + + +static void value_book_init (GValue* value) { + value->data[0].v_pointer = NULL; +} + + +static void value_book_free_value (GValue* value) { + if (value->data[0].v_pointer) { + book_unref (value->data[0].v_pointer); + } +} + + +static void value_book_copy_value (const GValue* src_value, GValue* dest_value) { + if (src_value->data[0].v_pointer) { + dest_value->data[0].v_pointer = book_ref (src_value->data[0].v_pointer); + } else { + dest_value->data[0].v_pointer = NULL; + } +} + + +static gpointer value_book_peek_pointer (const GValue* value) { + return value->data[0].v_pointer; +} + + +static gchar* value_book_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + if (collect_values[0].v_pointer) { + Book* object; + object = collect_values[0].v_pointer; + if (object->parent_instance.g_class == NULL) { + return g_strconcat ("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) { + return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } + value->data[0].v_pointer = book_ref (object); + } else { + value->data[0].v_pointer = NULL; + } + return NULL; +} + + +static gchar* value_book_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + Book** object_p; + object_p = collect_values[0].v_pointer; + if (!object_p) { + return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value)); + } + if (!value->data[0].v_pointer) { + *object_p = NULL; + } else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) { + *object_p = value->data[0].v_pointer; + } else { + *object_p = book_ref (value->data[0].v_pointer); + } + return NULL; +} + + +GParamSpec* param_spec_book (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) { + ParamSpecBook* spec; + g_return_val_if_fail (g_type_is_a (object_type, TYPE_BOOK), NULL); + spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags); + G_PARAM_SPEC (spec)->value_type = object_type; + return G_PARAM_SPEC (spec); +} + + +gpointer value_get_book (const GValue* value) { + g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_BOOK), NULL); + return value->data[0].v_pointer; +} + + +void value_set_book (GValue* value, gpointer v_object) { + Book* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_BOOK)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_BOOK)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + book_ref (value->data[0].v_pointer); + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + book_unref (old); + } +} -Book * -book_new () -{ - return g_object_new (BOOK_TYPE, NULL); +void value_take_book (GValue* value, gpointer v_object) { + Book* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_BOOK)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_BOOK)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + book_unref (old); + } } -void -book_clear (Book *book) -{ - GList *iter; - for (iter = book->priv->pages; iter; iter = iter->next) { - Page *page = iter->data; - g_object_unref (page); - } - g_list_free (book->priv->pages); - book->priv->pages = NULL; - g_signal_emit (book, signals[CLEARED], 0); +static void book_class_init (BookClass * klass) { + book_parent_class = g_type_class_peek_parent (klass); + BOOK_CLASS (klass)->finalize = book_finalize; + g_type_class_add_private (klass, sizeof (BookPrivate)); + g_signal_new ("page_added", TYPE_BOOK, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_user_marshal_VOID__PAGE, G_TYPE_NONE, 1, TYPE_PAGE); + g_signal_new ("page_removed", TYPE_BOOK, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_user_marshal_VOID__PAGE, G_TYPE_NONE, 1, TYPE_PAGE); + g_signal_new ("reordered", TYPE_BOOK, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + g_signal_new ("cleared", TYPE_BOOK, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + g_signal_new ("needs_saving_changed", TYPE_BOOK, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } -static void -page_changed_cb (Page *page, Book *book) -{ - book_set_needs_saving (book, TRUE); +static void book_instance_init (Book * self) { + self->priv = BOOK_GET_PRIVATE (self); + self->ref_count = 1; } -Page * -book_append_page (Book *book, gint width, gint height, gint dpi, ScanDirection scan_direction) -{ - Page *page; +static void book_finalize (Book* obj) { + Book * self; + self = BOOK (obj); + __g_list_free__page_unref0_0 (self->priv->pages); +} - page = page_new (width, height, dpi, scan_direction); - g_signal_connect (page, "pixels-changed", G_CALLBACK (page_changed_cb), book); - g_signal_connect (page, "crop-changed", G_CALLBACK (page_changed_cb), book); - book->priv->pages = g_list_append (book->priv->pages, page); +GType book_get_type (void) { + static volatile gsize book_type_id__volatile = 0; + if (g_once_init_enter (&book_type_id__volatile)) { + static const GTypeValueTable g_define_type_value_table = { value_book_init, value_book_free_value, value_book_copy_value, value_book_peek_pointer, "p", value_book_collect_value, "p", value_book_lcopy_value }; + static const GTypeInfo g_define_type_info = { sizeof (BookClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) book_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (Book), 0, (GInstanceInitFunc) book_instance_init, &g_define_type_value_table }; + static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) }; + GType book_type_id; + book_type_id = g_type_register_fundamental (g_type_fundamental_next (), "Book", &g_define_type_info, &g_define_type_fundamental_info, 0); + g_once_init_leave (&book_type_id__volatile, book_type_id); + } + return book_type_id__volatile; +} - g_signal_emit (book, signals[PAGE_ADDED], 0, page); - - book_set_needs_saving (book, TRUE); - return page; +gpointer book_ref (gpointer instance) { + Book* self; + self = instance; + g_atomic_int_inc (&self->ref_count); + return instance; } -void -book_move_page (Book *book, Page *page, gint location) -{ - book->priv->pages = g_list_remove (book->priv->pages, page); - book->priv->pages = g_list_insert (book->priv->pages, page, location); +void book_unref (gpointer instance) { + Book* self; + self = instance; + if (g_atomic_int_dec_and_test (&self->ref_count)) { + BOOK_GET_CLASS (self)->finalize (self); + g_type_free_instance ((GTypeInstance *) self); + } +} - g_signal_emit (book, signals[REORDERED], 0, page); - book_set_needs_saving (book, TRUE); +static gpointer _g_object_ref0 (gpointer self) { + return self ? g_object_ref (self) : NULL; } -void -book_delete_page (Book *book, Page *page) -{ - g_signal_handlers_disconnect_by_func (page, page_changed_cb, book); +PDFWriter* pdf_writer_construct (GType object_type, GFileOutputStream* stream) { + PDFWriter* self = NULL; + GFileOutputStream* _tmp0_; + g_return_val_if_fail (stream != NULL, NULL); + self = (PDFWriter*) g_type_create_instance (object_type); + _tmp0_ = _g_object_ref0 (stream); + _g_object_unref0 (self->priv->stream); + self->priv->stream = _tmp0_; + return self; +} - g_signal_emit (book, signals[PAGE_REMOVED], 0, page); - book->priv->pages = g_list_remove (book->priv->pages, page); - g_object_unref (page); +PDFWriter* pdf_writer_new (GFileOutputStream* stream) { + return pdf_writer_construct (TYPE_PDF_WRITER, stream); +} + - book_set_needs_saving (book, TRUE); +void pdf_writer_write (PDFWriter* self, guint8* data, int data_length1) { + GError * _inner_error_ = NULL; + g_return_if_fail (self != NULL); + { + g_output_stream_write_all ((GOutputStream*) self->priv->stream, data, (gsize) data_length1, NULL, NULL, &_inner_error_); + if (_inner_error_ != NULL) { + goto __catch0_g_error; + } + } + goto __finally0; + __catch0_g_error: + { + GError* e = NULL; + e = _inner_error_; + _inner_error_ = NULL; + g_warning ("book.vala:529: Error writing PDF: %s", e->message); + _g_error_free0 (e); + } + __finally0: + if (_inner_error_ != NULL) { + g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); + g_clear_error (&_inner_error_); + return; + } + self->offset = self->offset + data_length1; } -gint -book_get_n_pages (Book *book) -{ - return g_list_length (book->priv->pages); +static gchar* string_to_utf8 (const gchar* self, int* result_length1) { + gchar* result = NULL; + gint _tmp0_; + gchar* _tmp1_ = NULL; + gchar* _result_; + gint _result__length1; + gint __result__size_; + gint _tmp2_; + gchar* _tmp3_; + g_return_val_if_fail (self != NULL, NULL); + _tmp0_ = strlen (self); + _tmp1_ = g_new0 (gchar, _tmp0_ + 1); + _result_ = _tmp1_; + _result__length1 = _tmp0_ + 1; + __result__size_ = _result__length1; + _result__length1--; + _tmp2_ = strlen (self); + memcpy (_result_, self, (gsize) _tmp2_); + _tmp3_ = _result_; + if (result_length1) { + *result_length1 = _result__length1; + } + result = _tmp3_; + return result; } -Page * -book_get_page (Book *book, gint page_number) -{ - if (page_number < 0) - page_number = g_list_length (book->priv->pages) + page_number; - return g_list_nth_data (book->priv->pages, page_number); +void pdf_writer_write_string (PDFWriter* self, const gchar* text) { + gint _tmp0_; + gchar* _tmp1_ = NULL; + guint8* _tmp2_; + gint _tmp2__length1; + g_return_if_fail (self != NULL); + g_return_if_fail (text != NULL); + _tmp1_ = string_to_utf8 (text, &_tmp0_); + _tmp2_ = (guint8*) _tmp1_; + _tmp2__length1 = _tmp0_; + pdf_writer_write (self, _tmp2_, _tmp0_); + _tmp2_ = (g_free (_tmp2_), NULL); } -gint -book_get_page_index (Book *book, Page *page) -{ - return g_list_index (book->priv->pages, page); +guint pdf_writer_start_object (PDFWriter* self) { + guint result = 0U; + guint _tmp0_; + g_return_val_if_fail (self != NULL, 0U); + self->object_offsets = g_list_append (self->object_offsets, GUINT_TO_POINTER ((guint) self->offset)); + _tmp0_ = g_list_length (self->object_offsets); + result = _tmp0_; + return result; } -static GFile * -make_indexed_file (const gchar *uri, gint i) -{ - gchar *basename, *suffix, *indexed_uri; - GFile *file; +static void value_pdf_writer_init (GValue* value) { + value->data[0].v_pointer = NULL; +} + - if (i == 0) - return g_file_new_for_uri (uri); +static void value_pdf_writer_free_value (GValue* value) { + if (value->data[0].v_pointer) { + pdf_writer_unref (value->data[0].v_pointer); + } +} - basename = g_path_get_basename (uri); - suffix = g_strrstr (basename, "."); - if (suffix) - indexed_uri = g_strdup_printf ("%.*s-%d%s", (int) (strlen (uri) - strlen (suffix)), uri, i, suffix); - else - indexed_uri = g_strdup_printf ("%s-%d", uri, i); - g_free (basename); +static void value_pdf_writer_copy_value (const GValue* src_value, GValue* dest_value) { + if (src_value->data[0].v_pointer) { + dest_value->data[0].v_pointer = pdf_writer_ref (src_value->data[0].v_pointer); + } else { + dest_value->data[0].v_pointer = NULL; + } +} - file = g_file_new_for_uri (indexed_uri); - g_free (indexed_uri); - return file; +static gpointer value_pdf_writer_peek_pointer (const GValue* value) { + return value->data[0].v_pointer; } -static gboolean -book_save_multi_file (Book *book, const gchar *type, GFile *file, GError **error) -{ - GList *iter; - gboolean result = TRUE; - gint i; - gchar *uri; +static gchar* value_pdf_writer_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + if (collect_values[0].v_pointer) { + PDFWriter* object; + object = collect_values[0].v_pointer; + if (object->parent_instance.g_class == NULL) { + return g_strconcat ("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) { + return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } + value->data[0].v_pointer = pdf_writer_ref (object); + } else { + value->data[0].v_pointer = NULL; + } + return NULL; +} - uri = g_file_get_uri (file); - for (iter = book->priv->pages, i = 0; iter && result; iter = iter->next, i++) { - Page *page = iter->data; - GFile *file; - file = make_indexed_file (uri, i); - result = page_save (page, type, file, error); - g_object_unref (file); - } - g_free (uri); - - return result; +static gchar* value_pdf_writer_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + PDFWriter** object_p; + object_p = collect_values[0].v_pointer; + if (!object_p) { + return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value)); + } + if (!value->data[0].v_pointer) { + *object_p = NULL; + } else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) { + *object_p = value->data[0].v_pointer; + } else { + *object_p = pdf_writer_ref (value->data[0].v_pointer); + } + return NULL; } -static void -save_ps_pdf_surface (cairo_surface_t *surface, GdkPixbuf *image, gdouble dpi) -{ - cairo_t *context; - - context = cairo_create (surface); +GParamSpec* param_spec_pdf_writer (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) { + ParamSpecPDFWriter* spec; + g_return_val_if_fail (g_type_is_a (object_type, TYPE_PDF_WRITER), NULL); + spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags); + G_PARAM_SPEC (spec)->value_type = object_type; + return G_PARAM_SPEC (spec); +} - cairo_scale (context, 72.0 / dpi, 72.0 / dpi); - gdk_cairo_set_source_pixbuf (context, image, 0, 0); - cairo_pattern_set_filter (cairo_get_source (context), CAIRO_FILTER_BEST); - cairo_paint (context); - cairo_destroy (context); +gpointer value_get_pdf_writer (const GValue* value) { + g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PDF_WRITER), NULL); + return value->data[0].v_pointer; } -static cairo_status_t -write_cairo_data (GFileOutputStream *stream, unsigned char *data, unsigned int length) -{ - gboolean result; - GError *error = NULL; +void value_set_pdf_writer (GValue* value, gpointer v_object) { + PDFWriter* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PDF_WRITER)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_PDF_WRITER)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + pdf_writer_ref (value->data[0].v_pointer); + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + pdf_writer_unref (old); + } +} - result = g_output_stream_write_all (G_OUTPUT_STREAM (stream), data, length, NULL, NULL, &error); - - if (error) { - g_warning ("Error writing data: %s", error->message); - g_error_free (error); - } - return result ? CAIRO_STATUS_SUCCESS : CAIRO_STATUS_WRITE_ERROR; +void value_take_pdf_writer (GValue* value, gpointer v_object) { + PDFWriter* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PDF_WRITER)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_PDF_WRITER)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + pdf_writer_unref (old); + } } -static gboolean -book_save_ps (Book *book, GFile *file, GError **error) -{ - GFileOutputStream *stream; - GList *iter; - cairo_surface_t *surface; +static void pdf_writer_class_init (PDFWriterClass * klass) { + pdf_writer_parent_class = g_type_class_peek_parent (klass); + PDF_WRITER_CLASS (klass)->finalize = pdf_writer_finalize; + g_type_class_add_private (klass, sizeof (PDFWriterPrivate)); +} - stream = g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, error); - if (!stream) - return FALSE; - surface = cairo_ps_surface_create_for_stream ((cairo_write_func_t) write_cairo_data, - stream, 0, 0); +static void pdf_writer_instance_init (PDFWriter * self) { + self->priv = PDF_WRITER_GET_PRIVATE (self); + self->offset = (gsize) 0; + self->ref_count = 1; +} - for (iter = book->priv->pages; iter; iter = iter->next) { - Page *page = iter->data; - double width, height; - GdkPixbuf *image; - image = page_get_image (page, TRUE); +static void pdf_writer_finalize (PDFWriter* obj) { + PDFWriter * self; + self = PDF_WRITER (obj); + _g_list_free0 (self->object_offsets); + _g_object_unref0 (self->priv->stream); +} - width = gdk_pixbuf_get_width (image) * 72.0 / page_get_dpi (page); - height = gdk_pixbuf_get_height (image) * 72.0 / page_get_dpi (page); - cairo_ps_surface_set_size (surface, width, height); - save_ps_pdf_surface (surface, image, page_get_dpi (page)); - cairo_surface_show_page (surface); - - g_object_unref (image); - } - cairo_surface_destroy (surface); +GType pdf_writer_get_type (void) { + static volatile gsize pdf_writer_type_id__volatile = 0; + if (g_once_init_enter (&pdf_writer_type_id__volatile)) { + static const GTypeValueTable g_define_type_value_table = { value_pdf_writer_init, value_pdf_writer_free_value, value_pdf_writer_copy_value, value_pdf_writer_peek_pointer, "p", value_pdf_writer_collect_value, "p", value_pdf_writer_lcopy_value }; + static const GTypeInfo g_define_type_info = { sizeof (PDFWriterClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) pdf_writer_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (PDFWriter), 0, (GInstanceInitFunc) pdf_writer_instance_init, &g_define_type_value_table }; + static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) }; + GType pdf_writer_type_id; + pdf_writer_type_id = g_type_register_fundamental (g_type_fundamental_next (), "PDFWriter", &g_define_type_info, &g_define_type_fundamental_info, 0); + g_once_init_leave (&pdf_writer_type_id__volatile, pdf_writer_type_id); + } + return pdf_writer_type_id__volatile; +} - g_object_unref (stream); - return TRUE; +gpointer pdf_writer_ref (gpointer instance) { + PDFWriter* self; + self = instance; + g_atomic_int_inc (&self->ref_count); + return instance; } -typedef struct -{ - int offset; - int n_objects; - GList *object_offsets; - GFileOutputStream *stream; -} PDFWriter; +void pdf_writer_unref (gpointer instance) { + PDFWriter* self; + self = instance; + if (g_atomic_int_dec_and_test (&self->ref_count)) { + PDF_WRITER_GET_CLASS (self)->finalize (self); + g_type_free_instance ((GTypeInstance *) self); + } +} -static PDFWriter * -pdf_writer_new (GFileOutputStream *stream) -{ - PDFWriter *writer; - writer = g_malloc0 (sizeof (PDFWriter)); - writer->stream = g_object_ref (stream); - return writer; +static cairo_status_t _ps_writer_write_cairo_data_cairo_write_func_t (gpointer self, guchar* data, int data_length1) { + cairo_status_t result; + result = ps_writer_write_cairo_data (self, data, data_length1); + return result; } -static void -pdf_writer_free (PDFWriter *writer) -{ - g_object_unref (writer->stream); - g_list_free (writer->object_offsets); - g_free (writer); +PsWriter* ps_writer_construct (GType object_type, GFileOutputStream* stream) { + PsWriter* self = NULL; + GFileOutputStream* _tmp0_; + cairo_surface_t* _tmp1_ = NULL; + g_return_val_if_fail (stream != NULL, NULL); + self = (PsWriter*) g_type_create_instance (object_type); + _tmp0_ = _g_object_ref0 (stream); + _g_object_unref0 (self->stream); + self->stream = _tmp0_; + _tmp1_ = cairo_ps_surface_create_for_stream (_ps_writer_write_cairo_data_cairo_write_func_t, self, (gdouble) 0, (gdouble) 0); + _cairo_surface_destroy0 (self->surface); + self->surface = _tmp1_; + return self; } -static void -pdf_write (PDFWriter *writer, const unsigned char *data, size_t length) -{ - g_output_stream_write_all (G_OUTPUT_STREAM (writer->stream), data, length, NULL, NULL, NULL); - writer->offset += length; +PsWriter* ps_writer_new (GFileOutputStream* stream) { + return ps_writer_construct (TYPE_PS_WRITER, stream); } -static void -pdf_printf (PDFWriter *writer, const char *format, ...) -{ - va_list args; - gchar *string; +static cairo_status_t ps_writer_write_cairo_data (PsWriter* self, guint8* data, int data_length1) { + cairo_status_t result = 0; + GError * _inner_error_ = NULL; + g_return_val_if_fail (self != NULL, 0); + { + g_output_stream_write_all ((GOutputStream*) self->stream, data, (gsize) data_length1, NULL, NULL, &_inner_error_); + if (_inner_error_ != NULL) { + goto __catch1_g_error; + } + } + goto __finally1; + __catch1_g_error: + { + GError* e = NULL; + e = _inner_error_; + _inner_error_ = NULL; + g_warning ("book.vala:565: Error writing data: %s", e->message); + result = CAIRO_STATUS_WRITE_ERROR; + _g_error_free0 (e); + return result; + } + __finally1: + if (_inner_error_ != NULL) { + g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); + g_clear_error (&_inner_error_); + return 0; + } + result = CAIRO_STATUS_SUCCESS; + return result; +} - va_start (args, format); - string = g_strdup_vprintf (format, args); - va_end (args); - pdf_write (writer, (unsigned char *)string, strlen (string)); - g_free (string); +static void value_ps_writer_init (GValue* value) { + value->data[0].v_pointer = NULL; } -static int -pdf_start_object (PDFWriter *writer) -{ - writer->n_objects++; - writer->object_offsets = g_list_append (writer->object_offsets, GINT_TO_POINTER (writer->offset)); - return writer->n_objects; +static void value_ps_writer_free_value (GValue* value) { + if (value->data[0].v_pointer) { + ps_writer_unref (value->data[0].v_pointer); + } } -static guchar * -compress_zlib (guchar *data, size_t length, size_t *n_written) -{ - z_stream stream; - guchar *out_data; +static void value_ps_writer_copy_value (const GValue* src_value, GValue* dest_value) { + if (src_value->data[0].v_pointer) { + dest_value->data[0].v_pointer = ps_writer_ref (src_value->data[0].v_pointer); + } else { + dest_value->data[0].v_pointer = NULL; + } +} - out_data = g_malloc (sizeof (guchar) * length); - stream.zalloc = Z_NULL; - stream.zfree = Z_NULL; - stream.opaque = Z_NULL; - if (deflateInit (&stream, Z_BEST_COMPRESSION) != Z_OK) - return NULL; +static gpointer value_ps_writer_peek_pointer (const GValue* value) { + return value->data[0].v_pointer; +} - stream.next_in = data; - stream.avail_in = length; - stream.next_out = out_data; - stream.avail_out = length; - while (stream.avail_in > 0) { - if (deflate (&stream, Z_FINISH) == Z_STREAM_ERROR) - break; - } - deflateEnd (&stream); +static gchar* value_ps_writer_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + if (collect_values[0].v_pointer) { + PsWriter* object; + object = collect_values[0].v_pointer; + if (object->parent_instance.g_class == NULL) { + return g_strconcat ("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) { + return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } + value->data[0].v_pointer = ps_writer_ref (object); + } else { + value->data[0].v_pointer = NULL; + } + return NULL; +} + - if (stream.avail_in > 0) { - g_free (out_data); - return NULL; - } +static gchar* value_ps_writer_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { + PsWriter** object_p; + object_p = collect_values[0].v_pointer; + if (!object_p) { + return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value)); + } + if (!value->data[0].v_pointer) { + *object_p = NULL; + } else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) { + *object_p = value->data[0].v_pointer; + } else { + *object_p = ps_writer_ref (value->data[0].v_pointer); + } + return NULL; +} - *n_written = length - stream.avail_out; - return out_data; +GParamSpec* param_spec_ps_writer (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) { + ParamSpecPsWriter* spec; + g_return_val_if_fail (g_type_is_a (object_type, TYPE_PS_WRITER), NULL); + spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags); + G_PARAM_SPEC (spec)->value_type = object_type; + return G_PARAM_SPEC (spec); } - - -static void jpeg_init_cb (struct jpeg_compress_struct *info) {} -static boolean jpeg_empty_cb (struct jpeg_compress_struct *info) { return TRUE; } -static void jpeg_term_cb (struct jpeg_compress_struct *info) {} - -static guchar * -compress_jpeg (GdkPixbuf *image, size_t *n_written) -{ - struct jpeg_compress_struct info; - struct jpeg_error_mgr jerr; - struct jpeg_destination_mgr dest_mgr; - int r; - guchar *pixels; - guchar *data; - size_t max_length; - - info.err = jpeg_std_error (&jerr); - jpeg_create_compress (&info); - - pixels = gdk_pixbuf_get_pixels (image); - info.image_width = gdk_pixbuf_get_width (image); - info.image_height = gdk_pixbuf_get_height (image); - info.input_components = 3; - info.in_color_space = JCS_RGB; /* TODO: JCS_GRAYSCALE? */ - jpeg_set_defaults (&info); - - max_length = info.image_width * info.image_height * info.input_components; - data = g_malloc (sizeof (guchar) * max_length); - dest_mgr.next_output_byte = data; - dest_mgr.free_in_buffer = max_length; - dest_mgr.init_destination = jpeg_init_cb; - dest_mgr.empty_output_buffer = jpeg_empty_cb; - dest_mgr.term_destination = jpeg_term_cb; - info.dest = &dest_mgr; - - jpeg_start_compress (&info, TRUE); - for (r = 0; r < info.image_height; r++) { - JSAMPROW row[1]; - row[0] = pixels + r * gdk_pixbuf_get_rowstride (image); - jpeg_write_scanlines (&info, row, 1); - } - jpeg_finish_compress (&info); - *n_written = max_length - dest_mgr.free_in_buffer; - - jpeg_destroy_compress (&info); - - return data; -} - - -static gboolean -book_save_pdf (Book *book, GFile *file, GError **error) -{ - GFileOutputStream *stream; - PDFWriter *writer; - int catalog_number, pages_number, info_number; - int xref_offset; - int i; - - stream = g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, error); - if (!stream) - return FALSE; - - writer = pdf_writer_new (stream); - g_object_unref (stream); - - /* Header */ - pdf_printf (writer, "%%PDF-1.3\n"); - - /* Comment with binary as recommended so file is treated as binary */ - pdf_printf (writer, "%%\xe2\xe3\xcf\xd3\n"); - - /* Catalog */ - catalog_number = pdf_start_object (writer); - pdf_printf (writer, "%d 0 obj\n", catalog_number); - pdf_printf (writer, "<<\n"); - pdf_printf (writer, "/Type /Catalog\n"); - //FIXMEpdf_printf (writer, "/Metadata %d 0 R\n", catalog_number + 1); - pdf_printf (writer, "/Pages %d 0 R\n", catalog_number + 1); //+2 - pdf_printf (writer, ">>\n"); - pdf_printf (writer, "endobj\n"); - - /* Metadata */ - /* FIXME pdf_printf (writer, "\n"); - number = pdf_start_object (writer); - pdf_printf (writer, "%d 0 obj\n", number); - pdf_printf (writer, "<<\n"); - pdf_printf (writer, "/Type /Metadata\n"); - pdf_printf (writer, "/Subtype /XML\n"); - pdf_printf (writer, "/Length %d\n", ...); - pdf_printf (writer, ">>\n"); - pdf_printf (writer, "stream\n"); - // ... - pdf_printf (writer, "\n"); - pdf_printf (writer, "endstream\n"); - pdf_printf (writer, "endobj\n");*/ - - /* Pages */ - pdf_printf (writer, "\n"); - pages_number = pdf_start_object (writer); - pdf_printf (writer, "%d 0 obj\n", pages_number); - pdf_printf (writer, "<<\n"); - pdf_printf (writer, "/Type /Pages\n"); - pdf_printf (writer, "/Kids ["); - for (i = 0; i < book_get_n_pages (book); i++) { - pdf_printf (writer, " %d 0 R", pages_number + 1 + (i*3)); - } - pdf_printf (writer, " ]\n"); - pdf_printf (writer, "/Count %d\n", book_get_n_pages (book)); - pdf_printf (writer, ">>\n"); - pdf_printf (writer, "endobj\n"); - - for (i = 0; i < book_get_n_pages (book); i++) { - int number, width, height, depth; - size_t data_length, compressed_length; - Page *page; - GdkPixbuf *image; - guchar *pixels, *data, *compressed_data; - gchar *command, width_buffer[G_ASCII_DTOSTR_BUF_SIZE], height_buffer[G_ASCII_DTOSTR_BUF_SIZE]; - const gchar *color_space, *filter = NULL; - float page_width, page_height; - - page = book_get_page (book, i); - image = page_get_image (page, TRUE); - width = gdk_pixbuf_get_width (image); - height = gdk_pixbuf_get_height (image); - pixels = gdk_pixbuf_get_pixels (image); - page_width = width * 72. / page_get_dpi (page); - page_height = height * 72. / page_get_dpi (page); - - if (page_is_color (page)) { - int row; - - depth = 8; - color_space = "DeviceRGB"; - data_length = height * width * 3 + 1; - data = g_malloc (sizeof (guchar) * data_length); - for (row = 0; row < height; row++) { - int x; - guchar *in_line, *out_line; - - in_line = pixels + row * gdk_pixbuf_get_rowstride (image); - out_line = data + row * width * 3; - for (x = 0; x < width; x++) { - guchar *in_p = in_line + x*3; - guchar *out_p = out_line + x*3; - - out_p[0] = in_p[0]; - out_p[1] = in_p[1]; - out_p[2] = in_p[2]; - } - } - } - else if (page_get_depth (page) == 2) { - int row, shift_count = 6; - guchar *write_ptr; - - depth = 2; - color_space = "DeviceGray"; - data_length = height * ((width * 2 + 7) / 8); - data = g_malloc (sizeof (guchar) * data_length); - write_ptr = data; - write_ptr[0] = 0; - for (row = 0; row < height; row++) { - int x; - guchar *in_line; - - /* Pad to the next line */ - if (shift_count != 6) { - write_ptr++; - write_ptr[0] = 0; - shift_count = 6; - } - - in_line = pixels + row * gdk_pixbuf_get_rowstride (image); - for (x = 0; x < width; x++) { - guchar *in_p = in_line + x*3; - if (in_p[0] >= 192) - write_ptr[0] |= 3 << shift_count; - else if (in_p[0] >= 128) - write_ptr[0] |= 2 << shift_count; - else if (in_p[0] >= 64) - write_ptr[0] |= 1 << shift_count; - if (shift_count == 0) { - write_ptr++; - write_ptr[0] = 0; - shift_count = 6; - } - else - shift_count -= 2; - } - } - } - else if (page_get_depth (page) == 1) { - int row, mask = 0x80; - guchar *write_ptr; - - depth = 1; - color_space = "DeviceGray"; - data_length = height * ((width + 7) / 8); - data = g_malloc (sizeof (guchar) * data_length); - write_ptr = data; - write_ptr[0] = 0; - for (row = 0; row < height; row++) { - int x; - guchar *in_line; - - /* Pad to the next line */ - if (mask != 0x80) { - write_ptr++; - write_ptr[0] = 0; - mask = 0x80; - } - - in_line = pixels + row * gdk_pixbuf_get_rowstride (image); - for (x = 0; x < width; x++) { - guchar *in_p = in_line + x*3; - if (in_p[0] != 0) - write_ptr[0] |= mask; - mask >>= 1; - if (mask == 0) { - write_ptr++; - write_ptr[0] = 0; - mask = 0x80; - } - } - } - } - else { - int row; - - depth = 8; - color_space = "DeviceGray"; - data_length = height * width + 1; - data = g_malloc (sizeof (guchar) * data_length); - for (row = 0; row < height; row++) { - int x; - guchar *in_line, *out_line; - - in_line = pixels + row * gdk_pixbuf_get_rowstride (image); - out_line = data + row * width; - for (x = 0; x < width; x++) { - guchar *in_p = in_line + x*3; - guchar *out_p = out_line + x; - - out_p[0] = in_p[0]; - } - } - } - - /* Compress data */ - compressed_data = compress_zlib (data, data_length, &compressed_length); - if (compressed_data) { - /* Try if JPEG compression is better */ - if (depth > 1) { - guchar *jpeg_data; - size_t jpeg_length; - - jpeg_data = compress_jpeg (image, &jpeg_length); - if (jpeg_length < compressed_length) { - filter = "DCTDecode"; - g_free (data); - g_free (compressed_data); - data = jpeg_data; - data_length = jpeg_length; - } - } - - if (!filter) { - filter = "FlateDecode"; - g_free (data); - data = compressed_data; - data_length = compressed_length; - } - } - - /* Page */ - pdf_printf (writer, "\n"); - number = pdf_start_object (writer); - pdf_printf (writer, "%d 0 obj\n", number); - pdf_printf (writer, "<<\n"); - pdf_printf (writer, "/Type /Page\n"); - pdf_printf (writer, "/Parent %d 0 R\n", pages_number); - pdf_printf (writer, "/Resources << /XObject << /Im%d %d 0 R >> >>\n", i, number+1); - pdf_printf (writer, "/MediaBox [ 0 0 %s %s ]\n", - g_ascii_formatd (width_buffer, sizeof (width_buffer), "%.2f", page_width), - g_ascii_formatd (height_buffer, sizeof (height_buffer), "%.2f", page_height)); - pdf_printf (writer, "/Contents %d 0 R\n", number+2); - pdf_printf (writer, ">>\n"); - pdf_printf (writer, "endobj\n"); - - /* Page image */ - pdf_printf (writer, "\n"); - number = pdf_start_object (writer); - pdf_printf (writer, "%d 0 obj\n", number); - pdf_printf (writer, "<<\n"); - pdf_printf (writer, "/Type /XObject\n"); - pdf_printf (writer, "/Subtype /Image\n"); - pdf_printf (writer, "/Width %d\n", width); - pdf_printf (writer, "/Height %d\n", height); - pdf_printf (writer, "/ColorSpace /%s\n", color_space); - pdf_printf (writer, "/BitsPerComponent %d\n", depth); - pdf_printf (writer, "/Length %d\n", data_length); - if (filter) - pdf_printf (writer, "/Filter /%s\n", filter); - pdf_printf (writer, ">>\n"); - pdf_printf (writer, "stream\n"); - pdf_write (writer, data, data_length); - g_free (data); - pdf_printf (writer, "\n"); - pdf_printf (writer, "endstream\n"); - pdf_printf (writer, "endobj\n"); - - /* Page contents */ - command = g_strdup_printf ("q\n" - "%s 0 0 %s 0 0 cm\n" - "/Im%d Do\n" - "Q", - g_ascii_formatd (width_buffer, sizeof (width_buffer), "%f", page_width), - g_ascii_formatd (height_buffer, sizeof (height_buffer), "%f", page_height), - i); - pdf_printf (writer, "\n"); - number = pdf_start_object (writer); - pdf_printf (writer, "%d 0 obj\n", number); - pdf_printf (writer, "<<\n"); - pdf_printf (writer, "/Length %d\n", strlen (command) + 1); - pdf_printf (writer, ">>\n"); - pdf_printf (writer, "stream\n"); - pdf_write (writer, (unsigned char *)command, strlen (command)); - pdf_printf (writer, "\n"); - pdf_printf (writer, "endstream\n"); - pdf_printf (writer, "endobj\n"); - g_free (command); - - g_object_unref (image); - } - - /* Info */ - pdf_printf (writer, "\n"); - info_number = pdf_start_object (writer); - pdf_printf (writer, "%d 0 obj\n", info_number); - pdf_printf (writer, "<<\n"); - pdf_printf (writer, "/Creator (Simple Scan " VERSION ")\n"); - pdf_printf (writer, ">>\n"); - pdf_printf (writer, "endobj\n"); - - /* Cross-reference table */ - xref_offset = writer->offset; - pdf_printf (writer, "xref\n"); - pdf_printf (writer, "1 %d\n", writer->n_objects); - GList *link; - for (link = writer->object_offsets; link != NULL; link = link->next) { - int offset = GPOINTER_TO_INT (link->data); - pdf_printf (writer, "%010d 0000 n\n", offset); - } - - /* Trailer */ - pdf_printf (writer, "trailer\n"); - pdf_printf (writer, "<<\n"); - pdf_printf (writer, "/Size %d\n", writer->n_objects); - pdf_printf (writer, "/Info %d 0 R\n", info_number); - pdf_printf (writer, "/Root %d 0 R\n", catalog_number); - //FIXME: pdf_printf (writer, "/ID [<...> <...>]\n"); - pdf_printf (writer, ">>\n"); - pdf_printf (writer, "startxref\n"); - pdf_printf (writer, "%d\n", xref_offset); - pdf_printf (writer, "%%%%EOF\n"); - - pdf_writer_free (writer); - - return TRUE; -} - - -gboolean -book_save (Book *book, const gchar *type, GFile *file, GError **error) -{ - gboolean result = FALSE; - - if (strcmp (type, "jpeg") == 0) - result = book_save_multi_file (book, "jpeg", file, error); - else if (strcmp (type, "png") == 0) - result = book_save_multi_file (book, "png", file, error); - else if (strcmp (type, "tiff") == 0) - result = book_save_multi_file (book, "tiff", file, error); - else if (strcmp (type, "ps") == 0) - result = book_save_ps (book, file, error); - else if (strcmp (type, "pdf") == 0) - result = book_save_pdf (book, file, error); - - return result; -} - - -void -book_set_needs_saving (Book *book, gboolean needs_saving) -{ - gboolean needed_saving = book->priv->needs_saving; - book->priv->needs_saving = needs_saving; - if (needed_saving != needs_saving) - g_object_notify (G_OBJECT (book), "needs-saving"); -} - - -gboolean -book_get_needs_saving (Book *book) -{ - return book->priv->needs_saving; -} - - -static void -book_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - Book *self; - - self = BOOK (object); - - switch (prop_id) { - case PROP_NEEDS_SAVING: - book_set_needs_saving (self, g_value_get_boolean (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - - -static void -book_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - Book *self; - - self = BOOK (object); - - switch (prop_id) { - case PROP_NEEDS_SAVING: - g_value_set_boolean (value, book_get_needs_saving (self)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - - -static void -book_finalize (GObject *object) -{ - Book *book = BOOK (object); - book_clear (book); - G_OBJECT_CLASS (book_parent_class)->finalize (object); -} - - -static void -book_class_init (BookClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->get_property = book_get_property; - object_class->set_property = book_set_property; - object_class->finalize = book_finalize; - - g_object_class_install_property (object_class, - PROP_NEEDS_SAVING, - g_param_spec_boolean ("needs-saving", - "needs-saving", - "TRUE if this book needs saving", - FALSE, - G_PARAM_READWRITE)); - - signals[PAGE_ADDED] = - g_signal_new ("page-added", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (BookClass, page_added), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, page_get_type ()); - signals[PAGE_REMOVED] = - g_signal_new ("page-removed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (BookClass, page_removed), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, page_get_type ()); - signals[REORDERED] = - g_signal_new ("reordered", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (BookClass, reordered), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - signals[CLEARED] = - g_signal_new ("cleared", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (BookClass, cleared), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - g_type_class_add_private (klass, sizeof (BookPrivate)); -} - - -static void -book_init (Book *book) -{ - book->priv = G_TYPE_INSTANCE_GET_PRIVATE (book, BOOK_TYPE, BookPrivate); + + +gpointer value_get_ps_writer (const GValue* value) { + g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PS_WRITER), NULL); + return value->data[0].v_pointer; } + + +void value_set_ps_writer (GValue* value, gpointer v_object) { + PsWriter* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PS_WRITER)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_PS_WRITER)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + ps_writer_ref (value->data[0].v_pointer); + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + ps_writer_unref (old); + } +} + + +void value_take_ps_writer (GValue* value, gpointer v_object) { + PsWriter* old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PS_WRITER)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_PS_WRITER)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + ps_writer_unref (old); + } +} + + +static void ps_writer_class_init (PsWriterClass * klass) { + ps_writer_parent_class = g_type_class_peek_parent (klass); + PS_WRITER_CLASS (klass)->finalize = ps_writer_finalize; +} + + +static void ps_writer_instance_init (PsWriter * self) { + self->ref_count = 1; +} + + +static void ps_writer_finalize (PsWriter* obj) { + PsWriter * self; + self = PS_WRITER (obj); + _cairo_surface_destroy0 (self->surface); + _g_object_unref0 (self->stream); +} + + +GType ps_writer_get_type (void) { + static volatile gsize ps_writer_type_id__volatile = 0; + if (g_once_init_enter (&ps_writer_type_id__volatile)) { + static const GTypeValueTable g_define_type_value_table = { value_ps_writer_init, value_ps_writer_free_value, value_ps_writer_copy_value, value_ps_writer_peek_pointer, "p", value_ps_writer_collect_value, "p", value_ps_writer_lcopy_value }; + static const GTypeInfo g_define_type_info = { sizeof (PsWriterClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) ps_writer_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (PsWriter), 0, (GInstanceInitFunc) ps_writer_instance_init, &g_define_type_value_table }; + static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) }; + GType ps_writer_type_id; + ps_writer_type_id = g_type_register_fundamental (g_type_fundamental_next (), "PsWriter", &g_define_type_info, &g_define_type_fundamental_info, 0); + g_once_init_leave (&ps_writer_type_id__volatile, ps_writer_type_id); + } + return ps_writer_type_id__volatile; +} + + +gpointer ps_writer_ref (gpointer instance) { + PsWriter* self; + self = instance; + g_atomic_int_inc (&self->ref_count); + return instance; +} + + +void ps_writer_unref (gpointer instance) { + PsWriter* self; + self = instance; + if (g_atomic_int_dec_and_test (&self->ref_count)) { + PS_WRITER_GET_CLASS (self)->finalize (self); + g_type_free_instance ((GTypeInstance *) self); + } +} + + + |