Index: gtk/gtk.symbols
===================================================================
--- gtk/gtk.symbols	(revision 21770)
+++ gtk/gtk.symbols	(working copy)
@@ -2901,6 +2901,7 @@
 gtk_print_operation_get_status_string
 gtk_print_operation_is_finished
 gtk_print_operation_cancel
+gtk_print_operation_page_drawing_finished
 #endif
 #endif
 
Index: gtk/gtkprintoperation-private.h
===================================================================
--- gtk/gtkprintoperation-private.h	(revision 21770)
+++ gtk/gtkprintoperation-private.h	(working copy)
@@ -44,6 +44,8 @@
   guint cancelled          : 1;
   guint allow_async        : 1;
   guint is_sync            : 1;
+  guint allow_threads      : 1;
+  guint is_drawing_page    : 1;
 
   guint print_pages_idle_id;
   guint show_progress_timeout_id;
Index: gtk/gtkprintoperation.c
===================================================================
--- gtk/gtkprintoperation.c	(revision 21770)
+++ gtk/gtkprintoperation.c	(working copy)
@@ -67,7 +67,8 @@
   PROP_EXPORT_FILENAME,
   PROP_STATUS,
   PROP_STATUS_STRING,
-  PROP_CUSTOM_TAB_LABEL
+  PROP_CUSTOM_TAB_LABEL,
+  PROP_ALLOW_THREADS
 };
 
 static guint signals[LAST_SIGNAL] = { 0 };
@@ -159,6 +160,8 @@
   priv->export_filename = NULL;
   priv->track_print_status = FALSE;
   priv->is_sync = FALSE;
+  priv->allow_threads = FALSE;
+  priv->is_drawing_page = FALSE;
 
   priv->rloop = NULL;
   priv->unit = GTK_UNIT_PIXEL;
@@ -311,6 +314,9 @@
     case PROP_CUSTOM_TAB_LABEL:
       gtk_print_operation_set_custom_tab_label (op, g_value_get_string (value));
       break;
+    case PROP_ALLOW_THREADS:
+      gtk_print_operation_set_allow_threads (op, g_value_get_boolean (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -370,6 +376,9 @@
     case PROP_CUSTOM_TAB_LABEL:
       g_value_set_string (value, priv->custom_tab_label);
       break;
+    case PROP_ALLOW_THREADS:
+      g_value_set_boolean (value, priv->allow_threads);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1152,6 +1161,23 @@
 							P_("Label for the tab containing custom widgets."),
 							NULL,
 							GTK_PARAM_READWRITE));
+  /**
+   * GtkPrintOperation:allow-threads:
+   *
+   * Determines whether the print operation may draw pages in another thread or not.
+   *
+   * The gtk_print_operation_page_drawing_finished () has to be called from the other thread
+   * after the page drawing is finished.
+   *
+   * Since: 2.16
+   */
+  g_object_class_install_property (gobject_class,
+				   PROP_ALLOW_THREADS,
+				   g_param_spec_boolean ("allow-threads",
+							 P_("Allow Threads"),
+							 P_("TRUE if page drawing use threads."),
+							 FALSE,
+							 GTK_PARAM_READWRITE));
 
 }
 
@@ -2046,6 +2072,88 @@
     }
  }
 
+/**
+ * gtk_print_operation_set_allow_threads:
+ * @op: a #GtkPrintOperation
+ * @use_thread: %TRUE to allow page drawing in another thread
+ *
+ * Async operation is allowed with drawing in thread automatically.
+ *
+ * The gtk_print_operation_page_drawing_finished () has to be called from the other thread
+ * after the page drawing is finished.
+ *
+ * Since: 2.16
+ */
+void
+gtk_print_operation_set_allow_threads (GtkPrintOperation  *op,
+				       gboolean            allow_threads)
+{
+  GtkPrintOperationPrivate *priv;
+
+  g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
+
+  priv = op->priv;
+
+  allow_threads = allow_threads != FALSE;
+
+  if (priv->allow_threads != allow_threads)
+    {
+      priv->allow_threads = allow_threads;
+
+      g_object_notify (G_OBJECT (op), "allow-threads");
+    }
+
+  if (allow_threads)
+    gtk_print_operation_set_allow_async (op, TRUE);
+}
+
+/**
+ * gtk_print_operation_get_allow_threads:
+ * @op: a #GtkPrintOperation
+ *
+ * Returns: whether drawing in another thread is allowed
+ *
+ * Since: 2.16
+ */
+gboolean
+gtk_print_operation_get_allow_threads (GtkPrintOperation  *op)
+{
+  g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), FALSE);
+
+  return op->priv->allow_threads;
+}
+
+/**
+ * gtk_print_operation_page_drawing_finished:
+ * @op: a #GtkPrintOperation
+ * 
+ * Finish drawing of page.
+ *
+ * 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);
+
+  if (gtk_print_operation_get_allow_threads (op))
+    priv->is_drawing_page = FALSE;
+}
+
 static void
 common_render_page (GtkPrintOperation *op,
 		    gint               page_nr)
@@ -2083,159 +2191,178 @@
   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 (!gtk_print_operation_get_allow_threads (op))
+    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;
+  GtkPrintOperationPrivate *priv;
+  GtkPageSetup             *page_setup;
+  gint                      i;
 
-  data = (PrintPagesData*)user_data;
   priv = data->op->priv;
 
-  if (priv->status == GTK_PRINT_STATUS_PREPARING)
+  if (!data->initialized)
     {
-      if (!data->initialized)
-	{
-	  data->initialized = TRUE;
-	  page_setup = create_page_setup (data->op);
-	  _gtk_print_context_set_page_setup (priv->print_context, 
-					     page_setup);
-	  g_object_unref (page_setup);
-      
-	  g_signal_emit (data->op, signals[BEGIN_PRINT], 0, priv->print_context);
-      
-	  if (priv->manual_collation)
-	    {
-	      data->uncollated_copies = priv->manual_num_copies;
-	      data->collated_copies = 1;
-	    }
-	  else
-	    {
-	      data->uncollated_copies = 1;
-	      data->collated_copies = priv->manual_num_copies;
-	    }
+      data->initialized = TRUE;
+      page_setup = create_page_setup (data->op);
+      _gtk_print_context_set_page_setup (priv->print_context, 
+                                 page_setup);
+      g_object_unref (page_setup);
 
-	  goto out;
-	}
-      
-      if (g_signal_has_handler_pending (data->op, signals[PAGINATE], 0, FALSE))
-	{
-	  gboolean paginated = FALSE;
+      g_signal_emit (data->op, signals[BEGIN_PRINT], 0, priv->print_context);
 
-	  g_signal_emit (data->op, signals[PAGINATE], 0, priv->print_context, &paginated);
-	  if (!paginated)
-	    goto out;
-	}
-
-      /* Initialize parts of PrintPagesData that depend on nr_of_pages
-       */
-      if (priv->print_pages == GTK_PRINT_PAGES_RANGES)
-	{
-          if (priv->page_ranges == NULL) 
-            {
-              g_warning ("no pages to print");
-              priv->cancelled = TRUE;
-              goto out;
-	  }
-	  data->ranges = priv->page_ranges;
-	  data->num_ranges = priv->num_page_ranges;
-          for (i = 0; i < data->num_ranges; i++)
-            if (data->ranges[i].end == -1 || 
-                data->ranges[i].end >= priv->nr_of_pages)
-              data->ranges[i].end = priv->nr_of_pages - 1;
-	}
-      else if (priv->print_pages == GTK_PRINT_PAGES_CURRENT &&
-	       priv->current_page != -1)
-	{
-	  data->ranges = &data->one_range;
-	  data->num_ranges = 1;
-	  data->ranges[0].start = priv->current_page;
-	  data->ranges[0].end = priv->current_page;
-	}
+      if (priv->manual_collation)
+        {
+          data->uncollated_copies = priv->manual_num_copies;
+          data->collated_copies = 1;
+        }
       else
-	{
-	  data->ranges = &data->one_range;
-	  data->num_ranges = 1;
-	  data->ranges[0].start = 0;
-	  data->ranges[0].end = priv->nr_of_pages - 1;
-	}
-      
-      clamp_page_ranges (data);
+        {
+          data->uncollated_copies = 1;
+          data->collated_copies = priv->manual_num_copies;
+        }
 
-      if (priv->manual_reverse)
-	{
-	  data->range = data->num_ranges - 1;
-	  data->inc = -1;      
-	}
-      else
-	{
-	  data->range = 0;
-	  data->inc = 1;      
-	}
-      find_range (data);
-     
-      /* go back one page, since we preincrement below */
-      data->page = data->start - data->inc;
-      data->collated = data->collated_copies - 1;
+      return;
+    }
 
-      _gtk_print_operation_set_status (data->op, 
-				       GTK_PRINT_STATUS_GENERATING_DATA, 
-				       NULL);
+  if (g_signal_has_handler_pending (data->op, signals[PAGINATE], 0, FALSE))
+    {
+      gboolean paginated = FALSE;
 
-      goto out;
+      g_signal_emit (data->op, signals[PAGINATE], 0, priv->print_context, &paginated);
+      if (!paginated)
+        return;
     }
 
-  data->total++;
-  data->collated++;
-  if (data->collated == data->collated_copies)
+  /* Initialize parts of PrintPagesData that depend on nr_of_pages
+   */
+  if (priv->print_pages == GTK_PRINT_PAGES_RANGES)
     {
-      data->collated = 0;
-      if (!increment_page_sequence (data))
-	{
-	  done = TRUE;
-
-	  goto out;
-	}
+      if (priv->page_ranges == NULL) 
+        {
+          g_warning ("no pages to print");
+          priv->cancelled = TRUE;
+          return;
+        }
+      data->ranges = priv->page_ranges;
+      data->num_ranges = priv->num_page_ranges;
+      for (i = 0; i < data->num_ranges; i++)
+        if (data->ranges[i].end == -1 || 
+            data->ranges[i].end >= priv->nr_of_pages)
+          data->ranges[i].end = priv->nr_of_pages - 1;
     }
- 
-  if (data->is_preview && !priv->cancelled)
+  else if (priv->print_pages == GTK_PRINT_PAGES_CURRENT &&
+   priv->current_page != -1)
     {
-      done = TRUE;
-
-      g_signal_emit_by_name (data->op, "ready", priv->print_context);
-      goto out;
+      data->ranges = &data->one_range;
+      data->num_ranges = 1;
+      data->ranges[0].start = priv->current_page;
+      data->ranges[0].end = priv->current_page;
     }
+  else
+    {
+      data->ranges = &data->one_range;
+      data->num_ranges = 1;
+      data->ranges[0].start = 0;
+      data->ranges[0].end = priv->nr_of_pages - 1;
+    }
 
-  common_render_page (data->op, data->page);
+  clamp_page_ranges (data);
 
- out:
+  if (data->num_ranges < 1) 
+    {
+      priv->cancelled = TRUE;
+      return;
+    }
 
-  if (priv->cancelled)
+  if (priv->manual_reverse)
     {
-      _gtk_print_operation_set_status (data->op, GTK_PRINT_STATUS_FINISHED_ABORTED, NULL);
-      
-      data->is_preview = FALSE;
-      done = TRUE;
+      data->range = data->num_ranges - 1;
+      data->inc = -1;      
     }
+  else
+    {
+      data->range = 0;
+      data->inc = 1;      
+    }
+  find_range (data);
 
-  if (done && !data->is_preview)
+  /* go back one page, since we preincrement below */
+  data->page = data->start - data->inc;
+  data->collated = data->collated_copies - 1;
+
+  _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 (!(gtk_print_operation_get_allow_threads (data->op) && (priv->is_drawing_page)))
     {
-      g_signal_emit (data->op, signals[END_PRINT], 0, priv->print_context);
-      priv->end_run (data->op, priv->is_sync, priv->cancelled);
+      if (priv->status == GTK_PRINT_STATUS_PREPARING)
+        {
+          prepare_data (data);
+          goto out;
+        }
+
+      data->total++;
+      data->collated++;
+      if (data->collated == data->collated_copies)
+        {
+          data->collated = 0;
+          if (!increment_page_sequence (data))
+            {
+              done = TRUE;
+
+              goto out;
+            }
+        }
+
+      if (data->is_preview && !priv->cancelled)
+        {
+          done = TRUE;
+
+          g_signal_emit_by_name (data->op, "ready", priv->print_context);
+          goto out;
+        }
+
+      if (gtk_print_operation_get_allow_threads (data->op))
+        priv->is_drawing_page = TRUE;
+
+      common_render_page (data->op, data->page);
+
+ out:
+
+      if (priv->cancelled)
+        {
+          _gtk_print_operation_set_status (data->op, GTK_PRINT_STATUS_FINISHED_ABORTED, NULL);
+
+          data->is_preview = FALSE;
+          done = TRUE;
+        }
+
+      if (done && !data->is_preview)
+        {
+          g_signal_emit (data->op, signals[END_PRINT], 0, priv->print_context);
+          priv->end_run (data->op, priv->is_sync, priv->cancelled);
+        }
+
+      update_progress (data);
     }
 
-  update_progress (data);
-
   return !done;
 }
   
Index: gtk/gtkprintoperation.h
===================================================================
--- gtk/gtkprintoperation.h	(revision 21770)
+++ gtk/gtkprintoperation.h	(working copy)
@@ -172,6 +172,10 @@
 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_set_allow_threads      (GtkPrintOperation  *op,
+								    gboolean           allow_threads);
+gboolean                gtk_print_operation_get_allow_threads      (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 21770)
+++ docs/reference/gtk/gtk-sections.txt	(working copy)
@@ -6451,6 +6451,7 @@
 gtk_print_operation_set_custom_tab_label
 gtk_print_operation_run
 gtk_print_operation_cancel
+gtk_print_operation_page_drawing_finished
 gtk_print_operation_get_status
 gtk_print_operation_get_status_string
 gtk_print_operation_is_finished
