diff options
-rw-r--r-- | ChangeLog | 23 | ||||
-rw-r--r-- | docs/reference/gtk/gtk-sections.txt | 2 | ||||
-rw-r--r-- | gtk/gtk.symbols | 2 | ||||
-rw-r--r-- | gtk/gtkprintoperation-private.h | 10 | ||||
-rw-r--r-- | gtk/gtkprintoperation.c | 357 | ||||
-rw-r--r-- | gtk/gtkprintoperation.h | 2 |
6 files changed, 262 insertions, 134 deletions
@@ -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, |