summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog23
-rw-r--r--docs/reference/gtk/gtk-sections.txt2
-rw-r--r--gtk/gtk.symbols2
-rw-r--r--gtk/gtkprintoperation-private.h10
-rw-r--r--gtk/gtkprintoperation.c357
-rw-r--r--gtk/gtkprintoperation.h2
6 files changed, 262 insertions, 134 deletions
diff --git a/ChangeLog b/ChangeLog
index c1299be435..4ddd519501 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+2008-12-19 Marek Kasik <mkasik@redhat.com>
+
+ Bug 339318 - Allow page rendering to (optionally) happen in a thread
+
+ * gtk/gtk.symbols: API change
+ * doc/reference/gtk/gtk-sections.txt: API change
+ * gtk/gtkprintoperation-private.h
+ * gtk/gtkprintoperation.h
+ * gtk/gtkprintoperation.c: Adds 2 new functions
+ gtk_print_operation_set_defer_drawing()
+ - Sets up the GtkPrintOperation to wait for calling of
+ gtk_print_operation_draw_page_finish() from application. It can
+ be used for drawing page in another thread.
+ This function must be called in the callback of "draw-page"
+ signal.
+ gtk_print_operation_draw_page_finish()
+ - 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_set_defer_drawing() was called before,
+ then this function has to be called by application. In another
+ case it is called by the library itself.
+
2008-12-15 Matthias Clasen <mclasen@redhat.com>
* gtk/gtkprintunixdialog.c: Don't export emit_ok_response
diff --git a/docs/reference/gtk/gtk-sections.txt b/docs/reference/gtk/gtk-sections.txt
index 1ec1925d09..b49a731ea1 100644
--- a/docs/reference/gtk/gtk-sections.txt
+++ b/docs/reference/gtk/gtk-sections.txt
@@ -6454,6 +6454,8 @@ gtk_print_operation_set_track_print_status
gtk_print_operation_set_custom_tab_label
gtk_print_operation_run
gtk_print_operation_cancel
+gtk_print_operation_draw_page_finish
+gtk_print_operation_set_defer_drawing
gtk_print_operation_get_status
gtk_print_operation_get_status_string
gtk_print_operation_is_finished
diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols
index 39f32f35e7..2b4f07fc47 100644
--- a/gtk/gtk.symbols
+++ b/gtk/gtk.symbols
@@ -2909,6 +2909,8 @@ gtk_print_operation_get_status
gtk_print_operation_get_status_string
gtk_print_operation_is_finished
gtk_print_operation_cancel
+gtk_print_operation_draw_page_finish
+gtk_print_operation_set_defer_drawing
#endif
#endif
diff --git a/gtk/gtkprintoperation-private.h b/gtk/gtkprintoperation-private.h
index 3595314b4d..0e5f606c80 100644
--- a/gtk/gtkprintoperation-private.h
+++ b/gtk/gtkprintoperation-private.h
@@ -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 @@ struct _GtkPrintOperationPrivate
guint allow_async : 1;
guint is_sync : 1;
+ GtkPageDrawingState page_drawing_state;
+
guint print_pages_idle_id;
guint show_progress_timeout_id;
diff --git a/gtk/gtkprintoperation.c b/gtk/gtkprintoperation.c
index 0362d58f31..403902403e 100644
--- a/gtk/gtkprintoperation.c
+++ b/gtk/gtkprintoperation.c
@@ -160,6 +160,8 @@ gtk_print_operation_init (GtkPrintOperation *operation)
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 @@ preview_print_idle (gpointer data)
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);
-
- 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 */
- pop->page_nr++;
- if (op->priv->nr_of_pages <= pop->page_nr)
- retval = FALSE;
+
+ 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);
+ }
+
+ if (retval)
+ {
+ gtk_print_operation_preview_render_page (pop->preview, pop->page_nr);
+ pop->page_nr++;
+ }
+ }
return retval;
}
@@ -2046,6 +2060,64 @@ update_progress (PrintPagesData *data)
}
}
+/**
+ * gtk_print_operation_set_defer_drawing:
+ * @op: a #GtkPrintOperation
+ *
+ * Sets up the #GtkPrintOperation to wait for calling of
+ * gtk_print_operation_draw_page_finish() 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_set_defer_drawing (GtkPrintOperation *op)
+{
+ GtkPrintOperationPrivate *priv = op->priv;
+
+ g_return_if_fail (priv->page_drawing_state == GTK_PAGE_DRAWING_STATE_DRAWING);
+
+ priv->page_drawing_state = GTK_PAGE_DRAWING_STATE_DEFERRED_DRAWING;
+}
+
+/**
+ * gtk_print_operation_draw_page_finish:
+ * @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_set_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_draw_page_finish (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,161 +2152,178 @@ common_render_page (GtkPrintOperation *op,
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_draw_page_finish (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;
- }
-
- goto out;
- }
-
- if (g_signal_has_handler_pending (data->op, signals[PAGINATE], 0, FALSE))
- {
- gboolean paginated = FALSE;
+ 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[PAGINATE], 0, priv->print_context, &paginated);
- if (!paginated)
- goto out;
- }
+ g_signal_emit (data->op, signals[BEGIN_PRINT], 0, priv->print_context);
- /* 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);
-
- out:
+ clamp_page_ranges (data);
- if (priv->cancelled)
+ if (data->num_ranges < 1)
{
- _gtk_print_operation_set_status (data->op, GTK_PRINT_STATUS_FINISHED_ABORTED, NULL);
-
- data->is_preview = FALSE;
- done = TRUE;
+ priv->cancelled = TRUE;
+ return;
}
- if (done && !data->is_preview)
+ if (priv->manual_reverse)
+ {
+ data->range = data->num_ranges - 1;
+ data->inc = -1;
+ }
+ else
{
- g_signal_emit (data->op, signals[END_PRINT], 0, priv->print_context);
- priv->end_run (data->op, priv->is_sync, priv->cancelled);
+ 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;
+
+ _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;
+ }
+
+ 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;
+ }
+
+ common_render_page (data->op, data->page);
- update_progress (data);
+ 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);
+ }
return !done;
}
diff --git a/gtk/gtkprintoperation.h b/gtk/gtkprintoperation.h
index 38c12d0318..a3f0410943 100644
--- a/gtk/gtkprintoperation.h
+++ b/gtk/gtkprintoperation.h
@@ -172,6 +172,8 @@ GtkPrintStatus gtk_print_operation_get_status (GtkPrintOper
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_draw_page_finish (GtkPrintOperation *op);
+void gtk_print_operation_set_defer_drawing (GtkPrintOperation *op);
GtkPageSetup *gtk_print_run_page_setup_dialog (GtkWindow *parent,
GtkPageSetup *page_setup,