*
* 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.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <config.h>
#include "ev-document-security.h"
#include "ev-document-find.h"
#include "ev-document-layers.h"
+#include "ev-document-print.h"
+#include "ev-document-annotations.h"
+#include "ev-document-attachments.h"
+#include "ev-document-text.h"
#include "ev-debug.h"
#include <errno.h>
#include <glib/gstdio.h>
-#include <glib/gi18n.h>
+#include <glib/gi18n-lib.h>
#include <unistd.h>
static void ev_job_init (EvJob *job);
static void ev_job_links_class_init (EvJobLinksClass *class);
static void ev_job_attachments_init (EvJobAttachments *job);
static void ev_job_attachments_class_init (EvJobAttachmentsClass *class);
+static void ev_job_annots_init (EvJobAnnots *job);
+static void ev_job_annots_class_init (EvJobAnnotsClass *class);
static void ev_job_render_init (EvJobRender *job);
static void ev_job_render_class_init (EvJobRenderClass *class);
+static void ev_job_page_data_init (EvJobPageData *job);
+static void ev_job_page_data_class_init (EvJobPageDataClass *class);
static void ev_job_thumbnail_init (EvJobThumbnail *job);
static void ev_job_thumbnail_class_init (EvJobThumbnailClass *class);
static void ev_job_load_init (EvJobLoad *job);
static void ev_job_layers_class_init (EvJobLayersClass *class);
static void ev_job_export_init (EvJobExport *job);
static void ev_job_export_class_init (EvJobExportClass *class);
+static void ev_job_print_init (EvJobPrint *job);
+static void ev_job_print_class_init (EvJobPrintClass *class);
enum {
CANCELLED,
LAST_SIGNAL
};
-enum {
- PAGE_READY,
- RENDER_LAST_SIGNAL
-};
-
enum {
FONTS_UPDATED,
FONTS_LAST_SIGNAL
};
static guint job_signals[LAST_SIGNAL] = { 0 };
-static guint job_render_signals[RENDER_LAST_SIGNAL] = { 0 };
static guint job_fonts_signals[FONTS_LAST_SIGNAL] = { 0 };
static guint job_find_signals[FIND_LAST_SIGNAL] = { 0 };
G_DEFINE_ABSTRACT_TYPE (EvJob, ev_job, G_TYPE_OBJECT)
G_DEFINE_TYPE (EvJobLinks, ev_job_links, EV_TYPE_JOB)
G_DEFINE_TYPE (EvJobAttachments, ev_job_attachments, EV_TYPE_JOB)
+G_DEFINE_TYPE (EvJobAnnots, ev_job_annots, EV_TYPE_JOB)
G_DEFINE_TYPE (EvJobRender, ev_job_render, EV_TYPE_JOB)
+G_DEFINE_TYPE (EvJobPageData, ev_job_page_data, EV_TYPE_JOB)
G_DEFINE_TYPE (EvJobThumbnail, ev_job_thumbnail, EV_TYPE_JOB)
G_DEFINE_TYPE (EvJobFonts, ev_job_fonts, EV_TYPE_JOB)
G_DEFINE_TYPE (EvJobLoad, ev_job_load, EV_TYPE_JOB)
G_DEFINE_TYPE (EvJobFind, ev_job_find, EV_TYPE_JOB)
G_DEFINE_TYPE (EvJobLayers, ev_job_layers, EV_TYPE_JOB)
G_DEFINE_TYPE (EvJobExport, ev_job_export, EV_TYPE_JOB)
+G_DEFINE_TYPE (EvJobPrint, ev_job_print, EV_TYPE_JOB)
/* EvJob */
static void
ev_debug_message (DEBUG_JOBS, NULL);
ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
-
+
ev_document_doc_mutex_lock ();
- job_attachments->attachments = ev_document_get_attachments (job->document);
+ job_attachments->attachments =
+ ev_document_attachments_get_attachments (EV_DOCUMENT_ATTACHMENTS (job->document));
ev_document_doc_mutex_unlock ();
-
+
ev_job_succeeded (job);
-
+
return FALSE;
}
return job;
}
+/* EvJobAnnots */
+static void
+ev_job_annots_init (EvJobAnnots *job)
+{
+ EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
+}
+
+static void
+ev_job_annots_dispose (GObject *object)
+{
+ EvJobAnnots *job;
+
+ ev_debug_message (DEBUG_JOBS, NULL);
+
+ job = EV_JOB_ANNOTS (object);
+
+ if (job->annots) {
+ g_list_foreach (job->annots, (GFunc)ev_mapping_list_unref, NULL);
+ g_list_free (job->annots);
+ job->annots = NULL;
+ }
+
+ G_OBJECT_CLASS (ev_job_annots_parent_class)->dispose (object);
+}
+
+static gboolean
+ev_job_annots_run (EvJob *job)
+{
+ EvJobAnnots *job_annots = EV_JOB_ANNOTS (job);
+ gint i;
+
+ ev_debug_message (DEBUG_JOBS, NULL);
+ ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
+
+ ev_document_doc_mutex_lock ();
+ for (i = 0; i < ev_document_get_n_pages (job->document); i++) {
+ EvMappingList *mapping_list;
+ EvPage *page;
+
+ page = ev_document_get_page (job->document, i);
+ mapping_list = ev_document_annotations_get_annotations (EV_DOCUMENT_ANNOTATIONS (job->document),
+ page);
+ g_object_unref (page);
+
+ if (mapping_list)
+ job_annots->annots = g_list_prepend (job_annots->annots, mapping_list);
+ }
+ ev_document_doc_mutex_unlock ();
+
+ job_annots->annots = g_list_reverse (job_annots->annots);
+
+ ev_job_succeeded (job);
+
+ return FALSE;
+}
+
+static void
+ev_job_annots_class_init (EvJobAnnotsClass *class)
+{
+ GObjectClass *oclass = G_OBJECT_CLASS (class);
+ EvJobClass *job_class = EV_JOB_CLASS (class);
+
+ oclass->dispose = ev_job_annots_dispose;
+ job_class->run = ev_job_annots_run;
+}
+
+EvJob *
+ev_job_annots_new (EvDocument *document)
+{
+ EvJob *job;
+
+ ev_debug_message (DEBUG_JOBS, NULL);
+
+ job = g_object_new (EV_TYPE_JOB_ANNOTS, NULL);
+ job->document = g_object_ref (document);
+
+ return job;
+}
+
/* EvJobRender */
static void
ev_job_render_init (EvJobRender *job)
job = EV_JOB_RENDER (object);
- if (job->ev_page) {
- ev_debug_message (DEBUG_JOBS, "page: %d (%p)", job->ev_page->index, job);
- g_object_unref (job->ev_page);
- job->ev_page = NULL;
- }
-
+ ev_debug_message (DEBUG_JOBS, "page: %d (%p)", job->page, job);
+
if (job->surface) {
cairo_surface_destroy (job->surface);
job->surface = NULL;
}
if (job->selection_region) {
- gdk_region_destroy (job->selection_region);
+ cairo_region_destroy (job->selection_region);
job->selection_region = NULL;
}
(* G_OBJECT_CLASS (ev_job_render_parent_class)->dispose) (object);
}
-static gboolean
-notify_page_ready (EvJobRender *job)
-{
- ev_debug_message (DEBUG_JOBS, "%d (%p)", job->ev_page->index, job);
- ev_profiler_stop (EV_PROFILE_JOBS, "Rendering page %d", job->ev_page->index);
-
- if (EV_JOB (job)->cancelled) {
- ev_debug_message (DEBUG_JOBS, "%s (%p) job was cancelled, do not emit page_ready", EV_GET_TYPE_NAME (job), job);
- } else {
- g_signal_emit (job, job_render_signals[PAGE_READY], 0);
- }
-
- return FALSE;
-}
-
-static void
-ev_job_render_page_ready (EvJobRender *job)
-{
- ev_debug_message (DEBUG_JOBS, "%d (%p)", job->ev_page->index, job);
-
- job->page_ready = TRUE;
- g_idle_add_full (G_PRIORITY_HIGH_IDLE,
- (GSourceFunc)notify_page_ready,
- g_object_ref (job),
- (GDestroyNotify)g_object_unref);
-}
-
static gboolean
ev_job_render_run (EvJob *job)
{
EvJobRender *job_render = EV_JOB_RENDER (job);
+ EvPage *ev_page;
EvRenderContext *rc;
ev_debug_message (DEBUG_JOBS, "page: %d (%p)", job_render->page, job);
ev_document_fc_mutex_lock ();
- job_render->ev_page = ev_document_get_page (job->document, job_render->page);
- rc = ev_render_context_new (job_render->ev_page, job_render->rotation, job_render->scale);
-
+ ev_page = ev_document_get_page (job->document, job_render->page);
+ rc = ev_render_context_new (ev_page, job_render->rotation, job_render->scale);
+ g_object_unref (ev_page);
+
job_render->surface = ev_document_render (job->document, rc);
/* If job was cancelled during the page rendering,
* we return now, so that the thread is finished ASAP
return FALSE;
}
-
- if ((job_render->flags & EV_RENDER_INCLUDE_SELECTION) && EV_IS_SELECTION (job->document)) {
+
+ if (job_render->include_selection && EV_IS_SELECTION (job->document)) {
ev_selection_render_selection (EV_SELECTION (job->document),
rc,
&(job_render->selection),
&(job_render->selection_points));
}
- ev_job_render_page_ready (job_render);
-
- ev_document_fc_mutex_unlock ();
-
- if ((job_render->flags & EV_RENDER_INCLUDE_TEXT) && EV_IS_SELECTION (job->document))
- job_render->text_mapping =
- ev_selection_get_selection_map (EV_SELECTION (job->document), rc);
- if ((job_render->flags & EV_RENDER_INCLUDE_LINKS) && EV_IS_DOCUMENT_LINKS (job->document))
- job_render->link_mapping =
- ev_document_links_get_links (EV_DOCUMENT_LINKS (job->document), job_render->page);
- if ((job_render->flags & EV_RENDER_INCLUDE_FORMS) && EV_IS_DOCUMENT_FORMS (job->document))
- job_render->form_field_mapping =
- ev_document_forms_get_form_fields (EV_DOCUMENT_FORMS (job->document),
- job_render->ev_page);
- if ((job_render->flags & EV_RENDER_INCLUDE_IMAGES) && EV_IS_DOCUMENT_IMAGES (job->document))
- job_render->image_mapping =
- ev_document_images_get_image_mapping (EV_DOCUMENT_IMAGES (job->document),
- job_render->page);
g_object_unref (rc);
+
+ ev_document_fc_mutex_unlock ();
ev_document_doc_mutex_unlock ();
ev_job_succeeded (job);
GObjectClass *oclass = G_OBJECT_CLASS (class);
EvJobClass *job_class = EV_JOB_CLASS (class);
- job_render_signals [PAGE_READY] =
- g_signal_new ("page-ready",
- EV_TYPE_JOB_RENDER,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (EvJobRenderClass, page_ready),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
oclass->dispose = ev_job_render_dispose;
job_class->run = ev_job_render_run;
}
ev_job_render_new (EvDocument *document,
gint page,
gint rotation,
- gdouble scale,
+ gdouble scale,
gint width,
- gint height,
- EvRenderFlags flags)
+ gint height)
{
EvJobRender *job;
job->scale = scale;
job->target_width = width;
job->target_height = height;
- job->flags = flags;
return EV_JOB (job);
}
GdkColor *text,
GdkColor *base)
{
- job->flags |= EV_RENDER_INCLUDE_SELECTION;
-
+ job->include_selection = TRUE;
+
job->selection_points = *selection_points;
job->selection_style = selection_style;
job->text = *text;
job->base = *base;
}
+/* EvJobPageData */
+static void
+ev_job_page_data_init (EvJobPageData *job)
+{
+ EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
+}
+
+static gboolean
+ev_job_page_data_run (EvJob *job)
+{
+ EvJobPageData *job_pd = EV_JOB_PAGE_DATA (job);
+ EvPage *ev_page;
+
+ ev_debug_message (DEBUG_JOBS, "page: %d (%p)", job_pd->page, job);
+ ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
+
+ ev_document_doc_mutex_lock ();
+ ev_page = ev_document_get_page (job->document, job_pd->page);
+
+ if ((job_pd->flags & EV_PAGE_DATA_INCLUDE_TEXT_MAPPING) && EV_IS_DOCUMENT_TEXT (job->document))
+ job_pd->text_mapping =
+ ev_document_text_get_text_mapping (EV_DOCUMENT_TEXT (job->document), ev_page);
+ if ((job_pd->flags & EV_PAGE_DATA_INCLUDE_TEXT) && EV_IS_DOCUMENT_TEXT (job->document))
+ job_pd->text =
+ ev_document_text_get_text (EV_DOCUMENT_TEXT (job->document), ev_page);
+ if ((job_pd->flags & EV_PAGE_DATA_INCLUDE_TEXT_LAYOUT) && EV_IS_DOCUMENT_TEXT (job->document))
+ ev_document_text_get_text_layout (EV_DOCUMENT_TEXT (job->document),
+ ev_page,
+ &(job_pd->text_layout),
+ &(job_pd->text_layout_length));
+ if ((job_pd->flags & EV_PAGE_DATA_INCLUDE_LINKS) && EV_IS_DOCUMENT_LINKS (job->document))
+ job_pd->link_mapping =
+ ev_document_links_get_links (EV_DOCUMENT_LINKS (job->document), ev_page);
+ if ((job_pd->flags & EV_PAGE_DATA_INCLUDE_FORMS) && EV_IS_DOCUMENT_FORMS (job->document))
+ job_pd->form_field_mapping =
+ ev_document_forms_get_form_fields (EV_DOCUMENT_FORMS (job->document),
+ ev_page);
+ if ((job_pd->flags & EV_PAGE_DATA_INCLUDE_IMAGES) && EV_IS_DOCUMENT_IMAGES (job->document))
+ job_pd->image_mapping =
+ ev_document_images_get_image_mapping (EV_DOCUMENT_IMAGES (job->document),
+ ev_page);
+ if ((job_pd->flags & EV_PAGE_DATA_INCLUDE_ANNOTS) && EV_IS_DOCUMENT_ANNOTATIONS (job->document))
+ job_pd->annot_mapping =
+ ev_document_annotations_get_annotations (EV_DOCUMENT_ANNOTATIONS (job->document),
+ ev_page);
+ g_object_unref (ev_page);
+ ev_document_doc_mutex_unlock ();
+
+ ev_job_succeeded (job);
+
+ return FALSE;
+}
+
+static void
+ev_job_page_data_class_init (EvJobPageDataClass *class)
+{
+ EvJobClass *job_class = EV_JOB_CLASS (class);
+
+ job_class->run = ev_job_page_data_run;
+}
+
+EvJob *
+ev_job_page_data_new (EvDocument *document,
+ gint page,
+ EvJobPageDataFlags flags)
+{
+ EvJobPageData *job;
+
+ ev_debug_message (DEBUG_JOBS, "%d", page);
+
+ job = g_object_new (EV_TYPE_JOB_PAGE_DATA, NULL);
+
+ EV_JOB (job)->document = g_object_ref (document);
+ job->page = page;
+ job->flags = flags;
+
+ return EV_JOB (job);
+}
+
/* EvJobThumbnail */
static void
ev_job_thumbnail_init (EvJobThumbnail *job)
because, e.g., a password is required - if so, just reload rather than
creating a new instance */
if (job->document) {
+ const gchar *uncompressed_uri;
+
if (job_load->password) {
ev_document_security_set_password (EV_DOCUMENT_SECURITY (job->document),
job_load->password);
job->failed = FALSE;
job->finished = FALSE;
g_clear_error (&job->error);
-
+
+ uncompressed_uri = g_object_get_data (G_OBJECT (job->document),
+ "uri-uncompressed");
ev_document_load (job->document,
- job_load->uri,
+ uncompressed_uri ? uncompressed_uri : job_load->uri,
&error);
} else {
job->document = ev_document_factory_get_document (job_load->uri,
{
EvJobSave *job_save = EV_JOB_SAVE (job);
gint fd;
- gchar *filename;
- gchar *tmp_filename;
+ gchar *tmp_filename = NULL;
gchar *local_uri;
GError *error = NULL;
ev_debug_message (DEBUG_JOBS, "uri: %s, document_uri: %s", job_save->uri, job_save->document_uri);
ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
-
- filename = ev_tmp_filename ("saveacopy");
- tmp_filename = g_strdup_printf ("%s.XXXXXX", filename);
- g_free (filename);
-
- fd = g_mkstemp (tmp_filename);
- if (fd == -1) {
- gchar *display_name;
- gint save_errno = errno;
- display_name = g_filename_display_name (tmp_filename);
- ev_job_failed (job,
- G_FILE_ERROR,
- g_file_error_from_errno (save_errno),
- _("Failed to create file ā%sā: %s"),
- display_name, g_strerror (save_errno));
- g_free (display_name);
- g_free (tmp_filename);
+ fd = ev_mkstemp ("saveacopy.XXXXXX", &tmp_filename, &error);
+ if (fd == -1) {
+ ev_job_failed_from_error (job, error);
+ g_error_free (error);
return FALSE;
}
ev_document_doc_mutex_lock ();
/* Save document to temp filename */
- local_uri = g_filename_to_uri (tmp_filename, NULL, NULL);
- ev_document_save (job->document, local_uri, &error);
+ local_uri = g_filename_to_uri (tmp_filename, NULL, &error);
+ if (local_uri != NULL) {
+ ev_document_save (job->document, local_uri, &error);
+ }
+
close (fd);
ev_document_doc_mutex_unlock ();
uri_comp = ev_file_compress (local_uri, ctype, &error);
g_free (local_uri);
- ev_tmp_filename_unlink (tmp_filename);
+ g_unlink (tmp_filename);
if (!uri_comp || error) {
local_uri = NULL;
}
g_free (tmp_filename);
-
+
if (error) {
g_free (local_uri);
ev_job_failed_from_error (job, error);
gint i;
for (i = 0; i < job->n_pages; i++) {
- g_list_foreach (job->pages[i], (GFunc)g_free, NULL);
+ g_list_foreach (job->pages[i], (GFunc)ev_rectangle_free, NULL);
g_list_free (job->pages[i]);
}
{
job->page = page;
}
+
+/* EvJobPrint */
+static void
+ev_job_print_init (EvJobPrint *job)
+{
+ EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
+ job->page = -1;
+}
+
+static void
+ev_job_print_dispose (GObject *object)
+{
+ EvJobPrint *job;
+
+ ev_debug_message (DEBUG_JOBS, NULL);
+
+ job = EV_JOB_PRINT (object);
+
+ if (job->cr) {
+ cairo_destroy (job->cr);
+ job->cr = NULL;
+ }
+
+ (* G_OBJECT_CLASS (ev_job_print_parent_class)->dispose) (object);
+}
+
+static gboolean
+ev_job_print_run (EvJob *job)
+{
+ EvJobPrint *job_print = EV_JOB_PRINT (job);
+ EvPage *ev_page;
+ cairo_status_t cr_status;
+
+ g_assert (job_print->page != -1);
+ g_assert (job_print->cr != NULL);
+
+ ev_debug_message (DEBUG_JOBS, NULL);
+ ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
+
+ job->failed = FALSE;
+ job->finished = FALSE;
+ g_clear_error (&job->error);
+
+ ev_document_doc_mutex_lock ();
+
+ ev_page = ev_document_get_page (job->document, job_print->page);
+ ev_document_print_print_page (EV_DOCUMENT_PRINT (job->document),
+ ev_page, job_print->cr);
+ g_object_unref (ev_page);
+
+ ev_document_doc_mutex_unlock ();
+
+ cr_status = cairo_status (job_print->cr);
+ if (cr_status == CAIRO_STATUS_SUCCESS) {
+ ev_job_succeeded (job);
+ } else {
+ ev_job_failed (job,
+ GTK_PRINT_ERROR,
+ GTK_PRINT_ERROR_GENERAL,
+ _("Failed to print page %d: %s"),
+ job_print->page,
+ cairo_status_to_string (cr_status));
+ }
+
+ return FALSE;
+}
+
+static void
+ev_job_print_class_init (EvJobPrintClass *class)
+{
+ GObjectClass *oclass = G_OBJECT_CLASS (class);
+ EvJobClass *job_class = EV_JOB_CLASS (class);
+
+ oclass->dispose = ev_job_print_dispose;
+ job_class->run = ev_job_print_run;
+}
+
+EvJob *
+ev_job_print_new (EvDocument *document)
+{
+ EvJob *job;
+
+ ev_debug_message (DEBUG_JOBS, NULL);
+
+ job = g_object_new (EV_TYPE_JOB_PRINT, NULL);
+ job->document = g_object_ref (document);
+
+ return job;
+}
+
+void
+ev_job_print_set_page (EvJobPrint *job,
+ gint page)
+{
+ job->page = page;
+}
+
+void
+ev_job_print_set_cairo (EvJobPrint *job,
+ cairo_t *cr)
+{
+ if (job->cr == cr)
+ return;
+
+ if (job->cr)
+ cairo_destroy (job->cr);
+ job->cr = cr ? cairo_reference (cr) : NULL;
+}