]> Pileus Git - ~andy/gtk/blobdiff - modules/printbackends/file/gtkprintbackendfile.c
Add SVG support to GtkPrintBackendFile
[~andy/gtk] / modules / printbackends / file / gtkprintbackendfile.c
index 43b96f457c481c79095f9fffd7ca06769ec47ca0..bc58751e0112138c85152df3303f9893c3ac19f5 100644 (file)
@@ -32,6 +32,7 @@
 #include <cairo.h>
 #include <cairo-pdf.h>
 #include <cairo-ps.h>
+#include <cairo-svg.h>
 
 #include <glib/gi18n-lib.h>
 
@@ -64,13 +65,15 @@ typedef enum
 {
   FORMAT_PDF,
   FORMAT_PS,
+  FORMAT_SVG,
   N_FORMATS
 } OutputFormat;
 
 static const gchar* formats[N_FORMATS] =
 {
   "pdf",
-  "ps"
+  "ps",
+  "svg"
 };
 
 static GObjectClass *backend_parent_class;
@@ -228,7 +231,19 @@ output_file_from_settings (GtkPrintSettings *settings,
           OutputFormat format;
 
           format = format_from_settings (settings);
-          extension = format == FORMAT_PS ? "ps" : "pdf";
+          switch (format)
+            {
+              default:
+              case FORMAT_PDF:
+                extension = "pdf";
+                break;
+              case FORMAT_PS:
+                extension = "ps";
+                break;
+              case FORMAT_SVG:
+                extension = "svg";
+                break;
+            }
         }
  
       /* default filename used for print-to-file */ 
@@ -238,11 +253,13 @@ output_file_from_settings (GtkPrintSettings *settings,
 
       if (locale_name != NULL)
         {
-          path = g_build_filename (g_get_current_dir (), locale_name, NULL);
+         gchar *current_dir = g_get_current_dir ();
+          path = g_build_filename (current_dir, locale_name, NULL);
           g_free (locale_name);
 
           uri = g_filename_to_uri (path, NULL, NULL);
           g_free (path);
+         g_free (current_dir);
        }
     }
 
@@ -296,16 +313,34 @@ file_printer_create_cairo_surface (GtkPrinter       *printer,
 {
   cairo_surface_t *surface;
   OutputFormat format;
+  const cairo_svg_version_t *versions;
+  int num_versions = 0;
 
   format = format_from_settings (settings);
 
-  if (format == FORMAT_PS)
-    surface = cairo_ps_surface_create_for_stream (_cairo_write, cache_io, width, height);
-  else
-    surface = cairo_pdf_surface_create_for_stream (_cairo_write, cache_io, width, height);
+  switch (format)
+    {
+      default:
+      case FORMAT_PDF:
+        surface = cairo_pdf_surface_create_for_stream (_cairo_write, cache_io, width, height);
+        break;
+      case FORMAT_PS:
+        surface = cairo_ps_surface_create_for_stream (_cairo_write, cache_io, width, height);
+        break;
+      case FORMAT_SVG:
+        surface = cairo_svg_surface_create_for_stream (_cairo_write, cache_io, width, height);
+        cairo_svg_get_versions (&versions, &num_versions);
+        if (num_versions > 0)
+          cairo_svg_surface_restrict_to_version (surface, versions[num_versions - 1]);
+        break;
+    }
+
+  if (gtk_print_settings_get_printer_lpi (settings) == 0.0)
+    gtk_print_settings_set_printer_lpi (settings, 150.0);
 
-  /* TODO: DPI from settings object? */
-  cairo_surface_set_fallback_resolution (surface, 300, 300);
+  cairo_surface_set_fallback_resolution (surface,
+                                         2.0 * gtk_print_settings_get_printer_lpi (settings),
+                                         2.0 * gtk_print_settings_get_printer_lpi (settings));
 
   return surface;
 }
@@ -314,7 +349,7 @@ typedef struct {
   GtkPrintBackend *backend;
   GtkPrintJobCompleteFunc callback;
   GtkPrintJob *job;
-  GIOChannel *target_io;
+  GFileOutputStream *target_io_stream;
   gpointer user_data;
   GDestroyNotify dnotify;
 } _PrintStreamData;
@@ -328,8 +363,8 @@ file_print_cb (GtkPrintBackendFile *print_backend,
 
   GDK_THREADS_ENTER ();
 
-  if (ps->target_io != NULL)
-    g_io_channel_unref (ps->target_io);
+  if (ps->target_io_stream != NULL)
+    g_output_stream_close (G_OUTPUT_STREAM (ps->target_io_stream), NULL, NULL);
 
   if (ps->callback)
     ps->callback (ps->job, ps->user_data, error);
@@ -372,11 +407,12 @@ file_write (GIOChannel   *source,
     {
       gsize bytes_written;
 
-      g_io_channel_write_chars (ps->target_io, 
-                                buf, 
-                               bytes_read, 
-                               &bytes_written, 
-                               &error);
+      g_output_stream_write_all (G_OUTPUT_STREAM (ps->target_io_stream),
+                                 buf,
+                                 bytes_read,
+                                 &bytes_written,
+                                 NULL,
+                                 &error);
     }
 
   if (error != NULL || read_status == G_IO_STATUS_EOF)
@@ -412,7 +448,8 @@ gtk_print_backend_file_print_stream (GtkPrintBackend        *print_backend,
   GtkPrinter *printer;
   _PrintStreamData *ps;
   GtkPrintSettings *settings;
-  gchar *uri, *filename;
+  gchar *uri;
+  GFile *file = NULL;
 
   printer = gtk_print_job_get_printer (job);
   settings = gtk_print_job_get_settings (job);
@@ -426,18 +463,15 @@ gtk_print_backend_file_print_stream (GtkPrintBackend        *print_backend,
 
   internal_error = NULL;
   uri = output_file_from_settings (settings, NULL);
-  filename = g_filename_from_uri (uri, NULL, &internal_error);
-  g_free (uri);
 
-  if (filename == NULL)
+  if (uri == NULL)
     goto error;
 
-  ps->target_io = g_io_channel_new_file (filename, "w", &internal_error);
-
-  g_free (filename);
+  file = g_file_new_for_uri (uri);
+  ps->target_io_stream = g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &internal_error);
 
-  if (internal_error == NULL)
-    g_io_channel_set_encoding (ps->target_io, NULL, &internal_error);
+  g_object_unref (file);
+  g_free (uri);
 
 error:
   if (internal_error != NULL)
@@ -538,7 +572,7 @@ file_printer_get_options (GtkPrinter           *printer,
   GtkPrinterOption *option;
   const gchar *n_up[] = {"1", "2", "4", "6", "9", "16" };
   const gchar *pages_per_sheet = NULL;
-  const gchar *format_names[N_FORMATS] = { N_("PDF"), N_("Postscript") };
+  const gchar *format_names[N_FORMATS] = { N_("PDF"), N_("Postscript"), N_("SVG") };
   const gchar *supported_formats[N_FORMATS];
   gchar *display_format_names[N_FORMATS];
   gint n_formats = 0;
@@ -586,7 +620,20 @@ file_printer_get_options (GtkPrinter           *printer,
     }
   else
     {
-      current_format = format == FORMAT_PS ? FORMAT_PS : FORMAT_PDF;
+      switch (format)
+        {
+          default:
+          case FORMAT_PDF:
+            current_format = FORMAT_PDF;
+            break;
+          case FORMAT_PS:
+            current_format = FORMAT_PS;
+            break;
+          case FORMAT_SVG:
+            current_format = FORMAT_SVG;            
+            break;
+        }
+
       for (n_formats = 0; n_formats < N_FORMATS; ++n_formats)
         {
          supported_formats[n_formats] = formats[n_formats];
@@ -642,6 +689,10 @@ file_printer_get_settings_from_options (GtkPrinter          *printer,
   option = gtk_printer_option_set_lookup (options, "gtk-n-up");
   if (option)
     gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_NUMBER_UP, option->value);
+
+  option = gtk_printer_option_set_lookup (options, "gtk-n-up-layout");
+  if (option)
+    gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_NUMBER_UP_LAYOUT, option->value);
 }
 
 static void
@@ -664,6 +715,8 @@ file_printer_prepare_for_print (GtkPrinter       *printer,
   print_job->collate = gtk_print_settings_get_collate (settings);
   print_job->reverse = gtk_print_settings_get_reverse (settings);
   print_job->num_copies = gtk_print_settings_get_n_copies (settings);
+  print_job->number_up = gtk_print_settings_get_number_up (settings);
+  print_job->number_up_layout = gtk_print_settings_get_number_up_layout (settings);
 
   scale = gtk_print_settings_get_scale (settings);
   if (scale != 100.0)