From: Marco Pesenti Gritti Date: Tue, 7 Jun 2005 09:20:35 +0000 (+0000) Subject: Add an async renderer interface (method + callback) which is useful for X-Git-Tag: EVINCE_0_3_3~269 X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=commitdiff_plain;h=421d3d8b0f2f2432ec02f57677da2964d339f2d8;p=evince.git Add an async renderer interface (method + callback) which is useful for 2005-06-07 Marco Pesenti Gritti * backend/Makefile.am: * backend/ev-async-renderer.c: (ev_async_renderer_get_type), (ev_async_renderer_class_init), (ev_async_renderer_render_pixbuf): * backend/ev-async-renderer.h: Add an async renderer interface (method + callback) which is useful for backends like ps. * backend/ev-job-queue.c: (remove_job_from_async_queue), (add_job_to_async_queue), (job_finished_cb), (handle_job), (ev_job_queue_run_next), (ev_job_queue_init), (find_queue), (ev_job_queue_add_job), (move_job_async), (move_job), (ev_job_queue_update_job), (ev_job_queue_remove_job): Add queues for async renderer, these are executed on the main thread. * backend/ev-jobs.c: (ev_job_render_new), (render_finished_cb), (ev_job_render_run): * backend/ev-jobs.h: If the backend support async renderer interface use it. * ps/ps-document.c: (ps_document_init), (push_pixbuf), (setup_pixmap), (ps_document_get_type), (ps_async_renderer_render_pixbuf), (ps_document_document_iface_init), (ps_async_renderer_iface_init): Implement async renderer interface. --- diff --git a/ChangeLog b/ChangeLog index 5612ca13..ca81c662 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,35 @@ +2005-06-07 Marco Pesenti Gritti + + * backend/Makefile.am: + * backend/ev-async-renderer.c: (ev_async_renderer_get_type), + (ev_async_renderer_class_init), (ev_async_renderer_render_pixbuf): + * backend/ev-async-renderer.h: + + Add an async renderer interface (method + callback) which + is useful for backends like ps. + + * backend/ev-job-queue.c: (remove_job_from_async_queue), + (add_job_to_async_queue), (job_finished_cb), (handle_job), + (ev_job_queue_run_next), (ev_job_queue_init), (find_queue), + (ev_job_queue_add_job), (move_job_async), (move_job), + (ev_job_queue_update_job), (ev_job_queue_remove_job): + + Add queues for async renderer, these are executed on the + main thread. + + * backend/ev-jobs.c: (ev_job_render_new), (render_finished_cb), + (ev_job_render_run): + * backend/ev-jobs.h: + + If the backend support async renderer interface use it. + + * ps/ps-document.c: (ps_document_init), (push_pixbuf), + (setup_pixmap), (ps_document_get_type), + (ps_async_renderer_render_pixbuf), + (ps_document_document_iface_init), (ps_async_renderer_iface_init): + + Implement async renderer interface. + 2005-06-07 Nickolay V. Shmyrev <> * shell/ev-sidebar-links.c: (ev_sidebar_links_dispose): diff --git a/backend/Makefile.am b/backend/Makefile.am index 744c932d..322cc7d5 100644 --- a/backend/Makefile.am +++ b/backend/Makefile.am @@ -10,6 +10,8 @@ INCLUDES= \ noinst_LTLIBRARIES = libevbackend.la libevbackend_la_SOURCES= \ + ev-async-renderer.c \ + ev-async-renderer.h \ ev-backend-marshal.c \ ev-link.c \ ev-link.h \ diff --git a/backend/ev-async-renderer.c b/backend/ev-async-renderer.c new file mode 100644 index 00000000..45ca7e4f --- /dev/null +++ b/backend/ev-async-renderer.c @@ -0,0 +1,81 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-indent-level: 8 -*- */ +/* + * Copyright (C) 2004 Marco Pesenti Gritti + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "config.h" + +#include "ev-async-renderer.h" + +static void ev_async_renderer_class_init (gpointer g_class); + +enum +{ + RENDER_FINISHED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +GType +ev_async_renderer_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) + { + static const GTypeInfo our_info = + { + sizeof (EvAsyncRendererIface), + NULL, + NULL, + (GClassInitFunc)ev_async_renderer_class_init + }; + + type = g_type_register_static (G_TYPE_INTERFACE, + "EvAsyncRenderer", + &our_info, (GTypeFlags)0); + } + + return type; +} + +static void +ev_async_renderer_class_init (gpointer g_class) +{ + signals[RENDER_FINISHED] = + g_signal_new ("render_finished", + EV_TYPE_ASYNC_RENDERER, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EvAsyncRendererIface, render_finished), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, + GDK_TYPE_PIXBUF); +} + +void +ev_async_renderer_render_pixbuf (EvAsyncRenderer *async_renderer, + int page, + double scale) +{ + EvAsyncRendererIface *iface = EV_ASYNC_RENDERER_GET_IFACE (async_renderer); + + iface->render_pixbuf (async_renderer, page, scale); +} diff --git a/backend/ev-async-renderer.h b/backend/ev-async-renderer.h new file mode 100644 index 00000000..044ee629 --- /dev/null +++ b/backend/ev-async-renderer.h @@ -0,0 +1,59 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-indent-level: 8 -*- */ +/* + * Copyright (C) 2000-2003 Marco Pesenti Gritti + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef EV_ASYNC_RENDERER_H +#define EV_ASYNC_RENDERER_H + +#include +#include +#include + +G_BEGIN_DECLS + +#define EV_TYPE_ASYNC_RENDERER (ev_async_renderer_get_type ()) +#define EV_ASYNC_RENDERER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EV_TYPE_ASYNC_RENDERER, EvAsyncRenderer)) +#define EV_ASYNC_RENDERER_IFACE(k) (G_TYPE_CHECK_CLASS_CAST((k), EV_TYPE_ASYNC_RENDERER, EvAsyncRendererIface)) +#define EV_IS_ASYNC_RENDERER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EV_TYPE_ASYNC_RENDERER)) +#define EV_IS_ASYNC_RENDERER_IFACE(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EV_TYPE_ASYNC_RENDERER)) +#define EV_ASYNC_RENDERER_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), EV_TYPE_ASYNC_RENDERER, EvAsyncRendererIface)) + +typedef struct _EvAsyncRenderer EvAsyncRenderer; +typedef struct _EvAsyncRendererIface EvAsyncRendererIface; + +struct _EvAsyncRendererIface +{ + GTypeInterface base_iface; + + void (* render_finished) (EvAsyncRenderer *renderer, + GdkPixbuf *pixbuf); + + void (* render_pixbuf) (EvAsyncRenderer *renderer, + int page, + double scale); +}; + +GType ev_async_renderer_get_type (void); +void ev_async_renderer_render_pixbuf (EvAsyncRenderer *renderer, + int page, + double scale); + +G_END_DECLS + +#endif diff --git a/backend/ev-job-queue.c b/backend/ev-job-queue.c index 72470eef..1b3e4962 100644 --- a/backend/ev-job-queue.c +++ b/backend/ev-job-queue.c @@ -13,6 +13,14 @@ static GQueue *render_queue_low = NULL; static GQueue *thumbnail_queue_high = NULL; static GQueue *thumbnail_queue_low = NULL; +/* Queues used for backends supporting EvAsyncRender interface, + they are executed on the main thread */ +static GQueue *async_render_queue_high = NULL; +static GQueue *async_render_queue_low = NULL; +static gboolean async_rendering = FALSE; + +static void ev_job_queue_run_next (void); + static gboolean remove_job_from_queue_locked (GQueue *queue, EvJob *job) { @@ -28,6 +36,19 @@ remove_job_from_queue_locked (GQueue *queue, EvJob *job) return FALSE; } +static gboolean +remove_job_from_async_queue (GQueue *queue, EvJob *job) +{ + return remove_job_from_queue_locked (queue, job); +} + +static void +add_job_to_async_queue (GQueue *queue, EvJob *job) +{ + g_object_ref (job); + g_queue_push_tail (queue, job); +} + static void add_job_to_queue_locked (GQueue *queue, EvJob *job) @@ -37,7 +58,6 @@ add_job_to_queue_locked (GQueue *queue, g_cond_broadcast (render_cond); } - static gboolean notify_finished (GObject *job) { @@ -46,12 +66,29 @@ notify_finished (GObject *job) return FALSE; } +static void +job_finished_cb (EvJob *job) +{ + g_object_unref (job); + async_rendering = FALSE; + ev_job_queue_run_next (); +} static void handle_job (EvJob *job) { g_object_ref (G_OBJECT (job)); + if (EV_JOB (job)->async) { + async_rendering = TRUE; + if (EV_IS_JOB_RENDER (job)) { + g_signal_connect (job, "finished", + G_CALLBACK (job_finished_cb), NULL); + } else { + g_assert_not_reached (); + } + } + if (EV_IS_JOB_THUMBNAIL (job)) ev_job_thumbnail_run (EV_JOB_THUMBNAIL (job)); else if (EV_IS_JOB_LINKS (job)) @@ -59,11 +96,13 @@ handle_job (EvJob *job) else if (EV_IS_JOB_RENDER (job)) ev_job_render_run (EV_JOB_RENDER (job)); - /* We let the idle own a ref, as we (the queue) are done with the job. */ - g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, - (GSourceFunc) notify_finished, - job, - g_object_unref); + if (!EV_JOB (job)->async) { + /* We let the idle own a ref, as we (the queue) are done with the job. */ + g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, + (GSourceFunc) notify_finished, + job, + g_object_unref); + } } static EvJob * @@ -129,6 +168,24 @@ ev_render_thread (gpointer data) } +static void +ev_job_queue_run_next (void) +{ + EvJob *job; + + job = (EvJob *) g_queue_pop_head (async_render_queue_high); + + if (job == NULL) { + job = (EvJob *) g_queue_pop_head (async_render_queue_low); + } + + /* Now that we have our job, we handle it */ + if (job) { + handle_job (job); + g_object_unref (G_OBJECT (job)); + } +} + /* Public Functions */ void ev_job_queue_init (void) @@ -141,6 +198,8 @@ ev_job_queue_init (void) links_queue = g_queue_new (); render_queue_high = g_queue_new (); render_queue_low = g_queue_new (); + async_render_queue_high = g_queue_new (); + async_render_queue_low = g_queue_new (); thumbnail_queue_high = g_queue_new (); thumbnail_queue_low = g_queue_new (); @@ -152,19 +211,28 @@ static GQueue * find_queue (EvJob *job, EvJobPriority priority) { - if (EV_IS_JOB_RENDER (job)) { - if (priority == EV_JOB_PRIORITY_HIGH) - return render_queue_high; - else - return render_queue_low; - } else if (EV_IS_JOB_THUMBNAIL (job)) { - if (priority == EV_JOB_PRIORITY_HIGH) - return thumbnail_queue_high; - else - return thumbnail_queue_low; - } else if (EV_IS_JOB_LINKS (job)) { - /* the priority doesn't effect links */ - return links_queue; + if (EV_JOB (job)->async) { + if (EV_IS_JOB_RENDER (job)) { + if (priority == EV_JOB_PRIORITY_HIGH) + return async_render_queue_high; + else + return async_render_queue_low; + } + } else { + if (EV_IS_JOB_RENDER (job)) { + if (priority == EV_JOB_PRIORITY_HIGH) + return render_queue_high; + else + return render_queue_low; + } else if (EV_IS_JOB_THUMBNAIL (job)) { + if (priority == EV_JOB_PRIORITY_HIGH) + return thumbnail_queue_high; + else + return thumbnail_queue_low; + } else if (EV_IS_JOB_LINKS (job)) { + /* the priority doesn't effect links */ + return links_queue; + } } g_assert_not_reached (); @@ -181,9 +249,52 @@ ev_job_queue_add_job (EvJob *job, queue = find_queue (job, priority); + if (!EV_JOB (job)->async) { + g_mutex_lock (ev_queue_mutex); + add_job_to_queue_locked (queue, job); + g_mutex_unlock (ev_queue_mutex); + } else { + add_job_to_async_queue (queue, job); + if (!async_rendering) { + ev_job_queue_run_next (); + } + } +} + +static gboolean +move_job_async (EvJob *job, GQueue *old_queue, GQueue *new_queue) +{ + gboolean retval = FALSE; + + g_object_ref (job); + + if (remove_job_from_queue_locked (old_queue, job)) { + add_job_to_async_queue (new_queue, job); + retval = TRUE; + } + + g_object_unref (job); + + return retval; +} + +static gboolean +move_job (EvJob *job, GQueue *old_queue, GQueue *new_queue) +{ + gboolean retval = FALSE; + g_mutex_lock (ev_queue_mutex); - add_job_to_queue_locked (queue, job); + g_object_ref (job); + + if (remove_job_from_queue_locked (old_queue, job)) { + add_job_to_queue_locked (new_queue, job); + retval = TRUE; + } + + g_object_unref (job); g_mutex_unlock (ev_queue_mutex); + + return retval; } gboolean @@ -194,38 +305,39 @@ ev_job_queue_update_job (EvJob *job, g_return_val_if_fail (EV_IS_JOB (job), FALSE); - g_mutex_lock (ev_queue_mutex); - g_object_ref (job); - - if (EV_IS_JOB_THUMBNAIL (job)) { - if (new_priority == EV_JOB_PRIORITY_LOW) { - if (remove_job_from_queue_locked (thumbnail_queue_high, job)) { - add_job_to_queue_locked (thumbnail_queue_low, job); - retval = TRUE; - } - } else if (new_priority == EV_JOB_PRIORITY_HIGH) { - if (remove_job_from_queue_locked (thumbnail_queue_low, job)) { - add_job_to_queue_locked (thumbnail_queue_high, job); - retval = TRUE; + if (EV_JOB (job)->async) { + if (EV_IS_JOB_RENDER (job)) { + if (new_priority == EV_JOB_PRIORITY_LOW) { + retval = move_job_async (job, async_render_queue_high, + async_render_queue_low); + } else if (new_priority == EV_JOB_PRIORITY_HIGH) { + retval = move_job_async (job, async_render_queue_low, + async_render_queue_high); } + } else { + g_assert_not_reached (); } - } else if (EV_IS_JOB_RENDER (job)) { - if (new_priority == EV_JOB_PRIORITY_LOW) { - if (remove_job_from_queue_locked (render_queue_high, job)) { - add_job_to_queue_locked (render_queue_low, job); - retval = TRUE; + } else { + if (EV_IS_JOB_THUMBNAIL (job)) { + if (new_priority == EV_JOB_PRIORITY_LOW) { + retval = move_job (job, thumbnail_queue_high, + thumbnail_queue_low); + } else if (new_priority == EV_JOB_PRIORITY_HIGH) { + retval = move_job (job, thumbnail_queue_low, + thumbnail_queue_high); } - } else if (new_priority == EV_JOB_PRIORITY_HIGH) { - if (remove_job_from_queue_locked (render_queue_low, job)) { - add_job_to_queue_locked (render_queue_high, job); - retval = TRUE; + } else if (EV_IS_JOB_RENDER (job)) { + if (new_priority == EV_JOB_PRIORITY_LOW) { + retval = move_job (job, render_queue_high, + render_queue_low); + } else if (new_priority == EV_JOB_PRIORITY_HIGH) { + retval = move_job (job, render_queue_low, + render_queue_high); } + } else { + g_assert_not_reached (); } - } else { - /* We don't have a priority queue for any of the other jobs */ - } - g_object_unref (job); - g_mutex_unlock (ev_queue_mutex); + } return retval; } @@ -237,22 +349,31 @@ ev_job_queue_remove_job (EvJob *job) g_return_val_if_fail (EV_IS_JOB (job), FALSE); - g_mutex_lock (ev_queue_mutex); - - if (EV_IS_JOB_THUMBNAIL (job)) { - retval = remove_job_from_queue_locked (thumbnail_queue_high, job); - retval = retval || remove_job_from_queue_locked (thumbnail_queue_low, job); - } else if (EV_IS_JOB_RENDER (job)) { - retval = remove_job_from_queue_locked (render_queue_high, job); - retval = retval || remove_job_from_queue_locked (render_queue_low, job); - } else if (EV_IS_JOB_LINKS (job)) { - retval = remove_job_from_queue_locked (links_queue, job); + if (EV_JOB (job)->async) { + if (EV_IS_JOB_RENDER (job)) { + retval = remove_job_from_async_queue (async_render_queue_high, job); + retval = retval || remove_job_from_async_queue (async_render_queue_low, job); + } else { + g_assert_not_reached (); + } } else { - g_assert_not_reached (); + g_mutex_lock (ev_queue_mutex); + + if (EV_IS_JOB_THUMBNAIL (job)) { + retval = remove_job_from_queue_locked (thumbnail_queue_high, job); + retval = retval || remove_job_from_queue_locked (thumbnail_queue_low, job); + } else if (EV_IS_JOB_RENDER (job)) { + retval = remove_job_from_queue_locked (render_queue_high, job); + retval = retval || remove_job_from_queue_locked (render_queue_low, job); + } else if (EV_IS_JOB_LINKS (job)) { + retval = remove_job_from_queue_locked (links_queue, job); + } else { + g_assert_not_reached (); + } + + g_mutex_unlock (ev_queue_mutex); } - g_mutex_unlock (ev_queue_mutex); - return retval; } diff --git a/backend/ev-jobs.c b/backend/ev-jobs.c index c4556c95..73b0614a 100644 --- a/backend/ev-jobs.c +++ b/backend/ev-jobs.c @@ -2,6 +2,7 @@ #include "ev-job-queue.h" #include "ev-document-thumbnails.h" #include "ev-document-links.h" +#include "ev-async-renderer.h" static void ev_job_init (EvJob *job); static void ev_job_class_init (EvJobClass *class); @@ -196,9 +197,24 @@ ev_job_render_new (EvDocument *document, job->target_height = height; job->include_links = include_links; + if (EV_IS_ASYNC_RENDERER (document)) { + EV_JOB (job)->async = TRUE; + } + return EV_JOB (job); } +static void +render_finished_cb (EvDocument *document, GdkPixbuf *pixbuf, EvJobRender *job) +{ + g_signal_handlers_disconnect_by_func (EV_JOB (job)->document, + render_finished_cb, job); + + EV_JOB (job)->finished = TRUE; + job->pixbuf = g_object_ref (pixbuf); + ev_job_finished (EV_JOB (job)); +} + void ev_job_render_run (EvJobRender *job) { @@ -206,12 +222,21 @@ ev_job_render_run (EvJobRender *job) ev_document_doc_mutex_lock (); - job->pixbuf = ev_document_render_pixbuf (EV_JOB (job)->document, - job->page, - job->scale); - if (job->include_links) - job->link_mapping = ev_document_get_links (EV_JOB (job)->document, job->page); - EV_JOB (job)->finished = TRUE; + if (EV_JOB (job)->async) { + EvAsyncRenderer *renderer = EV_ASYNC_RENDERER (EV_JOB (job)->document); + ev_async_renderer_render_pixbuf (renderer, job->page, job->scale); + g_signal_connect (EV_JOB (job)->document, "render_finished", + G_CALLBACK (render_finished_cb), job); + } else { + job->pixbuf = ev_document_render_pixbuf (EV_JOB (job)->document, + job->page, + job->scale); + if (job->include_links) + job->link_mapping = ev_document_get_links (EV_JOB (job)->document, job->page); + + EV_JOB (job)->finished = TRUE; + } + ev_document_doc_mutex_unlock (); } diff --git a/backend/ev-jobs.h b/backend/ev-jobs.h index 1b64e01d..c89aa1e5 100644 --- a/backend/ev-jobs.h +++ b/backend/ev-jobs.h @@ -67,6 +67,7 @@ struct _EvJob GObject parent; EvDocument *document; gboolean finished; + gboolean async; }; struct _EvJobClass diff --git a/ps/ps-document.c b/ps/ps-document.c index 3de53e3a..8d64daf9 100644 --- a/ps/ps-document.c +++ b/ps/ps-document.c @@ -47,6 +47,7 @@ #include "ev-debug.h" #include "gsdefaults.h" #include "ev-ps-exporter.h" +#include "ev-async-renderer.h" #ifdef HAVE_LOCALE_H # include @@ -64,10 +65,6 @@ PS_DOCUMENT(gs)->gs_filename_unc : \ PS_DOCUMENT(gs)->gs_filename) -GCond* pixbuf_cond = NULL; -GMutex* pixbuf_mutex = NULL; -GdkPixbuf *current_pixbuf = NULL; - /* structure to describe section of file to send to ghostscript */ struct record_list { FILE *fp; @@ -97,6 +94,7 @@ static void stop_interpreter(PSDocument * gs); static gint start_interpreter(PSDocument * gs); static void ps_document_document_iface_init (EvDocumentIface *iface); static void ps_document_ps_exporter_iface_init (EvPSExporterIface *iface); +static void ps_async_renderer_iface_init (EvAsyncRendererIface *iface); static gboolean ps_document_widget_event (GtkWidget *widget, GdkEvent *event, gpointer data); static GObjectClass *parent_class = NULL; @@ -140,9 +138,6 @@ ps_document_init (PSDocument *gs) gs->ps_export_pagelist = NULL; gs->ps_export_filename = NULL; - - pixbuf_cond = g_cond_new (); - pixbuf_mutex = g_mutex_new (); } static void @@ -216,11 +211,8 @@ push_pixbuf (PSDocument *gs) pixbuf = gdk_pixbuf_get_from_drawable (NULL, gs->bpixmap, cmap, 0, 0, 0, 0, width, height); - g_mutex_lock (pixbuf_mutex); - current_pixbuf = pixbuf; - g_cond_signal (pixbuf_cond); - g_mutex_unlock (pixbuf_mutex); - + g_signal_emit_by_name (gs, "render_finished", pixbuf); + g_object_unref (pixbuf); } static void @@ -314,8 +306,8 @@ setup_pixmap (PSDocument *gs, int page, double scale) int pixmap_width, pixmap_height; ev_document_get_page_size (EV_DOCUMENT (gs), page, &width, &height); - pixmap_width = floor (width * scale); - pixmap_height = floor (height * scale); + pixmap_width = width * scale + 0.5; + pixmap_height = height * scale + 0.5; if(gs->bpixmap) { int w, h; @@ -984,6 +976,13 @@ ps_document_get_type(void) NULL }; + static const GInterfaceInfo async_renderer_info = + { + (GInterfaceInitFunc) ps_async_renderer_iface_init, + NULL, + NULL + }; + gs_type = g_type_register_static(G_TYPE_OBJECT, "PSDocument", &gs_info, 0); @@ -993,6 +992,9 @@ ps_document_get_type(void) g_type_add_interface_static (gs_type, EV_TYPE_PS_EXPORTER, &ps_exporter_info); + g_type_add_interface_static (gs_type, + EV_TYPE_ASYNC_RENDERER, + &async_renderer_info); } return gs_type; @@ -1316,27 +1318,15 @@ render_pixbuf_idle (PSRenderJob *job) return FALSE; } -static GdkPixbuf * -ps_document_render_pixbuf (EvDocument *document, int page, double scale) +static void +ps_async_renderer_render_pixbuf (EvAsyncRenderer *renderer, int page, double scale) { - GdkPixbuf *pixbuf; PSRenderJob job; job.page = page; job.scale = scale; - job.document = PS_DOCUMENT (document); - g_idle_add ((GSourceFunc)render_pixbuf_idle, &job); - - g_mutex_lock (pixbuf_mutex); - while (!current_pixbuf) - g_cond_wait (pixbuf_cond, pixbuf_mutex); - pixbuf = current_pixbuf; - current_pixbuf = NULL; - g_mutex_unlock (pixbuf_mutex); - - LOG ("Pixbuf rendered %p\n", pixbuf); - - return pixbuf; + job.document = PS_DOCUMENT (renderer); + render_pixbuf_idle (&job); } static EvDocumentInfo * @@ -1362,10 +1352,15 @@ ps_document_document_iface_init (EvDocumentIface *iface) iface->can_get_text = ps_document_can_get_text; iface->get_n_pages = ps_document_get_n_pages; iface->get_page_size = ps_document_get_page_size; - iface->render_pixbuf = ps_document_render_pixbuf; iface->get_info = ps_document_get_info; } +static void +ps_async_renderer_iface_init (EvAsyncRendererIface *iface) +{ + iface->render_pixbuf = ps_async_renderer_render_pixbuf; +} + static void ps_document_ps_export_begin (EvPSExporter *exporter, const char *filename, int first_page, int last_page)