Bug 339318 - Allow page rendering to (optionally) happen in a thread

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.

svn path=/trunk/; revision=21913
This commit is contained in:
Marek Kasik
2008-12-19 16:42:05 +00:00
committed by Marek Kašík
parent 1b62d9ebda
commit 8ff5d4ffc4
6 changed files with 264 additions and 136 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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);
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,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,30 +2152,24 @@ 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;
data = (PrintPagesData*)user_data;
priv = data->op->priv;
if (priv->status == GTK_PRINT_STATUS_PREPARING)
{
if (!data->initialized)
{
data->initialized = TRUE;
@ -2125,7 +2191,7 @@ print_pages_idle (gpointer user_data)
data->collated_copies = priv->manual_num_copies;
}
goto out;
return;
}
if (g_signal_has_handler_pending (data->op, signals[PAGINATE], 0, FALSE))
@ -2134,7 +2200,7 @@ print_pages_idle (gpointer user_data)
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 +2211,7 @@ print_pages_idle (gpointer user_data)
{
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 +2238,12 @@ print_pages_idle (gpointer user_data)
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 +2263,23 @@ print_pages_idle (gpointer user_data)
_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 +2323,7 @@ print_pages_idle (gpointer user_data)
}
update_progress (data);
}
return !done;
}

View File

@ -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,