Index: gtk/gtk.symbols
===================================================================
--- gtk/gtk.symbols	(revision 21912)
+++ gtk/gtk.symbols	(working copy)
@@ -2909,6 +2909,8 @@
 gtk_print_operation_get_status_string
 gtk_print_operation_is_finished
 gtk_print_operation_cancel
+gtk_print_operation_page_drawing_finished
+gtk_print_operation_defer_drawing
 #endif
 #endif
 
Index: gtk/gtkprintoperation-private.h
===================================================================
--- gtk/gtkprintoperation-private.h	(revision 21912)
+++ gtk/gtkprintoperation-private.h	(working copy)
@@ -25,6 +25,14 @@
 
 G_BEGIN_DECLS
 
+/* Page drawing states */
+typedef enum
+{
+  GTK_PAGE_DRAWING_STATE_READY,
+  GTK_PAGE_DRAWING_STATE_DRAWING,
+  GTK_PAGE_DRAWING_STATE_DEFERRED_DRAWING
+} GtkPageDrawingState;
+
 struct _GtkPrintOperationPrivate
 {
   GtkPrintOperationAction action;
@@ -45,6 +53,8 @@
   guint allow_async        : 1;
   guint is_sync            : 1;
 
+  GtkPageDrawingState      page_drawing_state;
+
   guint print_pages_idle_id;
   guint show_progress_timeout_id;
 
Index: gtk/gtkprintoperation.c
===================================================================
--- gtk/gtkprintoperation.c	(revision 21912)
+++ gtk/gtkprintoperation.c	(working copy)
@@ -160,6 +160,8 @@
   priv->track_print_status = FALSE;
   priv->is_sync = FALSE;
 
+  priv->page_drawing_state = GTK_PAGE_DRAWING_STATE_READY;
+
   priv->rloop = NULL;
   priv->unit = GTK_UNIT_PIXEL;
 
@@ -417,19 +419,31 @@
   GtkPrintOperation *op;
   gboolean retval = TRUE;
   cairo_t *cr;
+  GtkPrintOperationPrivate *priv; 
 
   pop = (PreviewOp *) data;
   op = GTK_PRINT_OPERATION (pop->preview);
+  priv = op->priv;
 
-  gtk_print_operation_preview_render_page (pop->preview, pop->page_nr);
   
+  if (priv->page_drawing_state == GTK_PAGE_DRAWING_STATE_READY)
+    {
+      /* TODO: print out sheets not pages and follow ranges */
+      if (pop->page_nr >= op->priv->nr_of_pages)
+        retval = FALSE;
+
+      if (pop->page_nr > 0)
+        {
   cr = gtk_print_context_get_cairo_context (pop->print_context);
   _gtk_print_operation_platform_backend_preview_end_page (op, pop->surface, cr);
+        }
   
-  /* TODO: print out sheets not pages and follow ranges */
+      if (retval)
+        {
+          gtk_print_operation_preview_render_page (pop->preview, pop->page_nr);
   pop->page_nr++;
-  if (op->priv->nr_of_pages <= pop->page_nr)
-    retval = FALSE;
+        }
+    }
 
   return retval;
 }
@@ -2046,6 +2060,62 @@
     }
  }
 
+/**
+ * gtk_print_operation_defer_drawing:
+ * @op: a #GtkPrintOperation
+ * 
+ * Sets up the #GtkPrintOperation to wait for calling of
+ * gtk_print_operation_page_drawing_finished from application. It can
+ * be used for drawing page in another thread.
+ *
+ * This function must be called in the callback of "draw-page" signal.
+ *
+ * Since: 2.16
+ **/
+void
+gtk_print_operation_defer_drawing (GtkPrintOperation *op)
+{
+  GtkPrintOperationPrivate *priv = op->priv;
+
+  priv->page_drawing_state = GTK_PAGE_DRAWING_STATE_DEFERRED_DRAWING;
+}
+
+/**
+ * gtk_print_operation_page_drawing_finished:
+ * @op: a #GtkPrintOperation
+ * 
+ * Signalize that drawing of particular page is complete.
+ *
+ * It is called after completion of page drawing (e.g. drawing in another
+ * thread).
+ * If gtk_print_operation_defer_drawing was called before, then this function
+ * has to be called by application. In another case it is called by the library
+ * itself.
+ *
+ * Since: 2.16
+ **/
+void
+gtk_print_operation_page_drawing_finished (GtkPrintOperation *op)
+{
+  GtkPrintOperationPrivate *priv = op->priv;
+  GtkPageSetup *page_setup;
+  GtkPrintContext *print_context;
+  cairo_t *cr;
+  
+  print_context = priv->print_context;
+  page_setup = gtk_print_context_get_page_setup (print_context);
+
+  cr = gtk_print_context_get_cairo_context (print_context);
+
+  priv->end_page (op, print_context);
+  
+  cairo_restore (cr);
+
+  g_object_unref (page_setup);
+
+  priv->page_drawing_state = GTK_PAGE_DRAWING_STATE_READY;
+}
+
 static void
 common_render_page (GtkPrintOperation *op,
 		    gint               page_nr)
@@ -2080,30 +2150,24 @@
   if (!priv->use_full_page)
     _gtk_print_context_translate_into_margin (print_context);
   
+  priv->page_drawing_state = GTK_PAGE_DRAWING_STATE_DRAWING;
+
   g_signal_emit (op, signals[DRAW_PAGE], 0, 
 		 print_context, page_nr);
 
-  priv->end_page (op, print_context);
-  
-  cairo_restore (cr);
-
-  g_object_unref (page_setup);
+  if (priv->page_drawing_state == GTK_PAGE_DRAWING_STATE_DRAWING)
+    gtk_print_operation_page_drawing_finished (op);
 }
 
-static gboolean
-print_pages_idle (gpointer user_data)
+void
+prepare_data (PrintPagesData *data)
 {
-  PrintPagesData *data; 
   GtkPrintOperationPrivate *priv; 
   GtkPageSetup *page_setup;
-  gboolean done = FALSE;
   gint i;
 
-  data = (PrintPagesData*)user_data;
   priv = data->op->priv;
 
-  if (priv->status == GTK_PRINT_STATUS_PREPARING)
-    {
       if (!data->initialized)
 	{
 	  data->initialized = TRUE;
@@ -2125,7 +2189,7 @@
 	      data->collated_copies = priv->manual_num_copies;
 	    }
 
-	  goto out;
+      return;
 	}
       
       if (g_signal_has_handler_pending (data->op, signals[PAGINATE], 0, FALSE))
@@ -2134,7 +2198,7 @@
 
 	  g_signal_emit (data->op, signals[PAGINATE], 0, priv->print_context, &paginated);
 	  if (!paginated)
-	    goto out;
+        return;
 	}
 
       /* Initialize parts of PrintPagesData that depend on nr_of_pages
@@ -2145,7 +2209,7 @@
             {
               g_warning ("no pages to print");
               priv->cancelled = TRUE;
-              goto out;
+          return;
 	  }
 	  data->ranges = priv->page_ranges;
 	  data->num_ranges = priv->num_page_ranges;
@@ -2172,6 +2236,12 @@
       
       clamp_page_ranges (data);
 
+  if (data->num_ranges < 1) 
+    {
+      priv->cancelled = TRUE;
+      return;
+    }
+
       if (priv->manual_reverse)
 	{
 	  data->range = data->num_ranges - 1;
@@ -2191,7 +2261,23 @@
       _gtk_print_operation_set_status (data->op, 
 				       GTK_PRINT_STATUS_GENERATING_DATA, 
 				       NULL);
+}
 
+static gboolean
+print_pages_idle (gpointer user_data)
+{
+  PrintPagesData *data; 
+  GtkPrintOperationPrivate *priv; 
+  gboolean done = FALSE;
+
+  data = (PrintPagesData*)user_data;
+  priv = data->op->priv;
+
+  if (priv->page_drawing_state == GTK_PAGE_DRAWING_STATE_READY)
+    {
+      if (priv->status == GTK_PRINT_STATUS_PREPARING)
+        {
+          prepare_data (data);
       goto out;
     }
 
@@ -2235,6 +2321,7 @@
     }
 
   update_progress (data);
+    }
 
   return !done;
 }
Index: gtk/gtkprintoperation.h
===================================================================
--- gtk/gtkprintoperation.h	(revision 21912)
+++ gtk/gtkprintoperation.h	(working copy)
@@ -172,6 +172,8 @@
 G_CONST_RETURN gchar *  gtk_print_operation_get_status_string      (GtkPrintOperation  *op);
 gboolean                gtk_print_operation_is_finished            (GtkPrintOperation  *op);
 void                    gtk_print_operation_cancel                 (GtkPrintOperation  *op);
+void                    gtk_print_operation_page_drawing_finished  (GtkPrintOperation  *op);
+void                    gtk_print_operation_defer_drawing          (GtkPrintOperation  *op);
 
 GtkPageSetup           *gtk_print_run_page_setup_dialog            (GtkWindow          *parent,
 								    GtkPageSetup       *page_setup,
Index: docs/reference/gtk/gtk-sections.txt
===================================================================
--- docs/reference/gtk/gtk-sections.txt	(revision 21912)
+++ docs/reference/gtk/gtk-sections.txt	(working copy)
@@ -6454,6 +6454,8 @@
 gtk_print_operation_set_custom_tab_label
 gtk_print_operation_run
 gtk_print_operation_cancel
+gtk_print_operation_page_drawing_finished
+gtk_print_operation_defer_drawing
 gtk_print_operation_get_status
 gtk_print_operation_get_status_string
 gtk_print_operation_is_finished
