Index: backend/Makefile.am =================================================================== RCS file: /cvs/gnome/evince/backend/Makefile.am,v retrieving revision 1.27 diff -u -8 -p -r1.27 Makefile.am --- backend/Makefile.am 2 May 2006 19:02:45 -0000 1.27 +++ backend/Makefile.am 7 Jun 2006 20:04:48 -0000 @@ -36,16 +36,18 @@ libevbackend_la_SOURCES= \ ev-document-fonts.h \ ev-document-links.c \ ev-document-links.h \ ev-document-security.c \ ev-document-security.h \ ev-document-find.c \ ev-document-find.h \ ev-document-info.h \ + ev-form-field-mapping.h \ + ev-form-field-mapping.c \ ev-ps-exporter.c \ ev-ps-exporter.h \ ev-render-context.h \ ev-render-context.c \ ev-selection.h \ ev-selection.c \ ev-document-misc.h \ ev-document-misc.c Index: backend/ev-document.c =================================================================== RCS file: /cvs/gnome/evince/backend/ev-document.c,v retrieving revision 1.35 diff -u -8 -p -r1.35 ev-document.c --- backend/ev-document.c 2 May 2006 19:02:45 -0000 1.35 +++ backend/ev-document.c 7 Jun 2006 20:04:48 -0000 @@ -254,8 +254,35 @@ ev_rect_cmp (EvRectangle *a, if (a == NULL || b == NULL) return 1; return ! ((ABS (a->x1 - b->x1) < EPSILON) && (ABS (a->y1 - b->y1) < EPSILON) && (ABS (a->x2 - b->x2) < EPSILON) && (ABS (a->y2 - b->y2) < EPSILON)); } + +GList* +ev_document_get_form_field_mappings (EvDocument *document, + int page) +{ + EvDocumentIface *iface = EV_DOCUMENT_GET_IFACE (document); + GList *retval; + + LOG ("ev_document_get_form_fields"); + if (iface->get_form_field_mappings == NULL) + return NULL; + retval = iface->get_form_field_mappings (document, page); + return retval; +} + +gboolean +ev_document_get_crop_box (EvDocument *document, + int page, + EvRectangle *rect) +{ + EvDocumentIface *iface = EV_DOCUMENT_GET_IFACE (document); + LOG("ev_document_get_crop_box"); + if (iface->get_crop_box == NULL) + return FALSE; + iface->get_crop_box(document, page, rect); + return TRUE; +} Index: backend/ev-document.h =================================================================== RCS file: /cvs/gnome/evince/backend/ev-document.h,v retrieving revision 1.34 diff -u -8 -p -r1.34 ev-document.h --- backend/ev-document.h 2 May 2006 19:02:45 -0000 1.34 +++ backend/ev-document.h 7 Jun 2006 20:04:50 -0000 @@ -22,16 +22,17 @@ #ifndef EV_DOCUMENT_H #define EV_DOCUMENT_H #include #include #include #include "ev-link.h" +#include "ev-form-field-mapping.h" #include "ev-document-info.h" #include "ev-render-context.h" G_BEGIN_DECLS #define EV_TYPE_DOCUMENT (ev_document_get_type ()) #define EV_DOCUMENT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EV_TYPE_DOCUMENT, EvDocument)) #define EV_DOCUMENT_IFACE(k) (G_TYPE_CHECK_CLASS_CAST((k), EV_TYPE_DOCUMENT, EvDocumentIface)) @@ -83,21 +84,26 @@ struct _EvDocumentIface double *width, double *height); char * (* get_page_label) (EvDocument *document, int page); gboolean (* can_get_text) (EvDocument *document); char * (* get_text) (EvDocument *document, int page, EvRectangle *rect); + GList * (* get_form_field_mappings) (EvDocument *document, + int page); gboolean (* has_attachments) (EvDocument *document); GList * (* get_attachments) (EvDocument *document); GdkPixbuf * (* render_pixbuf) (EvDocument *document, EvRenderContext *rc); EvDocumentInfo * (* get_info) (EvDocument *document); + void (* get_crop_box) (EvDocument *document, + int page, + EvRectangle *rect); }; GType ev_document_get_type (void); GQuark ev_document_error_quark (void); GMutex *ev_document_get_doc_mutex (void); void ev_document_doc_mutex_lock (void); void ev_document_doc_mutex_unlock (void); @@ -121,13 +127,21 @@ char *ev_document_get_text EvRectangle *rect); gboolean ev_document_has_attachments (EvDocument *document); GList *ev_document_get_attachments (EvDocument *document); GdkPixbuf *ev_document_render_pixbuf (EvDocument *document, EvRenderContext *rc); gint ev_rect_cmp (EvRectangle *a, EvRectangle *b); + +GList *ev_document_get_form_field_mappings (EvDocument *document, + int page); + +gboolean ev_document_get_crop_box (EvDocument *document, + int page, + EvRectangle *rect); + G_END_DECLS #endif Index: backend/ev-form-field-mapping.c =================================================================== RCS file: backend/ev-form-field-mapping.c diff -N backend/ev-form-field-mapping.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ backend/ev-form-field-mapping.c 7 Jun 2006 20:04:50 -0000 @@ -0,0 +1,59 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-indent-level: 8 -*- */ +/* this file is part of evince, a gnome document viewer + * + * Copyright (C) 2005 Red Hat, Inc. + * Copyright (C) 2006 Julien Rebetez + * + * Evince 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 of the License, or + * (at your option) any later version. + * + * Evince 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "ev-form-field-mapping.h" + +void +ev_form_field_mapping_list_free (GList *form_field_mapping_list) +{ + if (form_field_mapping_list == NULL) + return; + + g_list_foreach (form_field_mapping_list, (GFunc) (g_free), NULL); + g_list_free (form_field_mapping_list); +} + + +EvFormFieldMapping * +ev_form_field_mapping_find (GList *form_field_mapping_list, + gdouble x, + gdouble y) +{ + GList *list; + + for (list = form_field_mapping_list; list; list = list->next) { + EvFormFieldMapping *mapping = list->data; + + if ((x >= mapping->x1) && + (y >= mapping->y1) && + (x <= mapping->x2) && + (y <= mapping->y2)) { + return mapping; + } + } + return NULL; +} + + Index: backend/ev-form-field-mapping.h =================================================================== RCS file: backend/ev-form-field-mapping.h diff -N backend/ev-form-field-mapping.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ backend/ev-form-field-mapping.h 7 Jun 2006 20:04:50 -0000 @@ -0,0 +1,52 @@ +/* this file is part of evince, a gnome document viewer + * + * Copyright (C) 2005 Red Hat, Inc. + * Copyright (C) 2006 Julien Rebetez + * + * Evince 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 of the License, or + * (at your option) any later version. + * + * Evince 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_FORM_FIELD_MAPPING_H +#define EV_FORM_FIELD_MAPPING_H + +#include + +/*MUST be in the same order as poppler/glib/poppler.h PopplerFormFieldType !*/ +typedef enum +{ + EV_FORM_FIELD_TYPE_BUTTON, + EV_FORM_FIELD_TYPE_TEXT, + EV_FORM_FIELD_TYPE_CHOICE, + EV_FORM_FIELD_TYPE_SIGNATURE +} EvFormFieldType; + +/* Form Mapping Stuff */ +typedef struct _EvFormFieldMapping EvFormFieldMapping; +struct _EvFormFieldMapping +{ + EvFormFieldType type; + gdouble x1; + gdouble y1; + gdouble x2; + gdouble y2; +}; + +void ev_form_field_mapping_list_free (GList *form_field_mapping); +EvFormFieldMapping *ev_form_field_mapping_find (GList *form_field_mapping, + gdouble x, + gdouble y); + +#endif /* !EV_FORM_H */ + Index: pdf/ev-poppler.cc =================================================================== RCS file: /cvs/gnome/evince/pdf/ev-poppler.cc,v retrieving revision 1.69 diff -u -8 -p -r1.69 ev-poppler.cc --- pdf/ev-poppler.cc 9 May 2006 18:00:47 -0000 1.69 +++ pdf/ev-poppler.cc 7 Jun 2006 20:04:51 -0000 @@ -79,16 +79,21 @@ static void pdf_document_thumbnails_get_ gint *width, gint *height); static int pdf_document_get_n_pages (EvDocument *document); static EvLinkDest *ev_link_dest_from_dest (PopplerDest *dest); static EvLink *ev_link_from_action (PopplerAction *action); static void pdf_document_search_free (PdfDocumentSearch *search); +static void pdf_document_get_crop_box (EvDocument *document, int page, EvRectangle *rect); +static GList *pdf_document_get_form_field_mappings (EvDocument *document, int page); + + + G_DEFINE_TYPE_WITH_CODE (PdfDocument, pdf_document, G_TYPE_OBJECT, { G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT, pdf_document_document_iface_init); G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_SECURITY, pdf_document_security_iface_init); G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_THUMBNAILS, @@ -627,16 +632,18 @@ pdf_document_document_iface_init (EvDocu iface->load = pdf_document_load; iface->get_n_pages = pdf_document_get_n_pages; iface->get_page_size = pdf_document_get_page_size; iface->get_page_label = pdf_document_get_page_label; iface->has_attachments = pdf_document_has_attachments; iface->get_attachments = pdf_document_get_attachments; iface->render_pixbuf = pdf_document_render_pixbuf; iface->get_text = pdf_document_get_text; + iface->get_form_field_mappings = pdf_document_get_form_field_mappings; + iface->get_crop_box = pdf_document_get_crop_box; iface->can_get_text = pdf_document_can_get_text; iface->get_info = pdf_document_get_info; }; static void pdf_document_security_iface_init (EvDocumentSecurityIface *iface) { iface->has_document_security = pdf_document_has_document_security; @@ -1496,8 +1503,71 @@ pdf_selection_iface_init (EvSelectionIfa iface->get_selection_map = pdf_selection_get_selection_map; } PdfDocument * pdf_document_new (void) { return PDF_DOCUMENT (g_object_new (PDF_TYPE_DOCUMENT, NULL)); } + + +static GList * +pdf_document_get_form_field_mappings (EvDocument *document, + int page) +{ + PdfDocument *pdf_document; + PopplerPage *poppler_page; + GList *retval = NULL; + GList *fields; + GList *list; + double height; + + pdf_document = PDF_DOCUMENT (document); + poppler_page = poppler_document_get_page (pdf_document->document, + page); + fields = poppler_page_get_form_fields (poppler_page); + poppler_page_get_size (poppler_page, NULL, &height); + + for (list = fields; list; list = list->next) { + PopplerFormField *field; + EvFormFieldMapping *field_mapping; + double rect[4]; + + field = (PopplerFormField *)list->data; + /* Invert y for X-style coordinates */ + rect[0] = field->area.x1; rect[1] = height - field->area.y2; + rect[2] = field->area.x2; rect[3] = height - field->area.y1; + + field_mapping = g_new (EvFormFieldMapping, 1); + field_mapping->type = (EvFormFieldType)field->type; + field_mapping->x1 = rect[0]; + field_mapping->x2 = rect[2]; + field_mapping->y1 = rect[1]; + field_mapping->y2 = rect[3]; + + retval = g_list_prepend(retval, field_mapping); + } + poppler_page_free_form_fields(fields); + g_object_unref (poppler_page); + + return g_list_reverse(retval); +} + +static void +pdf_document_get_crop_box (EvDocument *document, + int page, + EvRectangle *rect) +{ + PdfDocument *pdf_document; + PopplerPage *poppler_page; + PopplerRectangle poppler_rect; + + pdf_document = PDF_DOCUMENT (document); + poppler_page = poppler_document_get_page (pdf_document->document, page); + poppler_page_get_crop_box (poppler_page, &poppler_rect); + rect->x1 = poppler_rect.x1; + rect->x2 = poppler_rect.x2; + rect->y1 = poppler_rect.y1; + rect->y2 = poppler_rect.y2; +} + + Index: shell/ev-jobs.c =================================================================== RCS file: /cvs/gnome/evince/shell/ev-jobs.c,v retrieving revision 1.17 diff -u -8 -p -r1.17 ev-jobs.c --- shell/ev-jobs.c 29 May 2006 15:35:29 -0000 1.17 +++ shell/ev-jobs.c 7 Jun 2006 20:04:52 -0000 @@ -208,16 +208,17 @@ ev_job_links_run (EvJobLinks *job) EvJob * ev_job_render_new (EvDocument *document, EvRenderContext *rc, gint width, gint height, EvRectangle *selection_points, GdkColor *text, GdkColor *base, + gboolean include_form, gboolean include_links, gboolean include_text, gboolean include_selection) { EvJobRender *job; g_return_val_if_fail (EV_IS_RENDER_CONTEXT (rc), NULL); if (include_selection) @@ -226,16 +227,17 @@ ev_job_render_new (EvDocument *docu job = g_object_new (EV_TYPE_JOB_RENDER, NULL); EV_JOB (job)->document = g_object_ref (document); job->rc = g_object_ref (rc); job->target_width = width; job->target_height = height; job->text = *text; job->base = *base; + job->include_form = include_form; job->include_links = include_links; job->include_text = include_text; job->include_selection = include_selection; if (include_selection) job->selection_points = *selection_points; if (EV_IS_ASYNC_RENDERER (document)) { @@ -266,16 +268,18 @@ ev_job_render_run (EvJobRender *job) if (EV_JOB (job)->async) { EvAsyncRenderer *renderer = EV_ASYNC_RENDERER (EV_JOB (job)->document); ev_async_renderer_render_pixbuf (renderer, job->rc->page, job->rc->scale, job->rc->rotation); 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->rc); + if (job->include_form) + job->form_field_mappings = ev_document_get_form_field_mappings(EV_JOB(job)->document, job->rc->page); if (job->include_links && EV_IS_DOCUMENT_LINKS (EV_JOB (job)->document)) job->link_mapping = ev_document_links_get_links (EV_DOCUMENT_LINKS (EV_JOB (job)->document), job->rc->page); if (job->include_text && EV_IS_SELECTION (EV_JOB (job)->document)) job->text_mapping = ev_selection_get_selection_map (EV_SELECTION (EV_JOB (job)->document), job->rc); Index: shell/ev-jobs.h =================================================================== RCS file: /cvs/gnome/evince/shell/ev-jobs.h,v retrieving revision 1.12 diff -u -8 -p -r1.12 ev-jobs.h --- shell/ev-jobs.h 29 May 2006 15:35:29 -0000 1.12 +++ shell/ev-jobs.h 7 Jun 2006 20:04:53 -0000 @@ -111,23 +111,25 @@ struct _EvJobRender EvRenderContext *rc; gint target_width; gint target_height; GdkPixbuf *pixbuf; GList *link_mapping; GdkRegion *text_mapping; + GList *form_field_mappings; GdkPixbuf *selection; GdkRegion *selection_region; EvRectangle selection_points; GdkColor base; GdkColor text; + gint include_form : 1; gint include_links : 1; gint include_text : 1; gint include_selection : 1; }; struct _EvJobRenderClass { EvJobClass parent_class; @@ -186,16 +188,17 @@ void ev_job_links_run GType ev_job_render_get_type (void); EvJob *ev_job_render_new (EvDocument *document, EvRenderContext *rc, gint width, gint height, EvRectangle *selection_points, GdkColor *text, GdkColor *base, + gboolean include_form, gboolean include_links, gboolean include_text, gboolean include_selection); void ev_job_render_run (EvJobRender *thumbnail); /* EvJobThumbnail */ GType ev_job_thumbnail_get_type (void); EvJob *ev_job_thumbnail_new (EvDocument *document, Index: shell/ev-pixbuf-cache.c =================================================================== RCS file: /cvs/gnome/evince/shell/ev-pixbuf-cache.c,v retrieving revision 1.22 diff -u -8 -p -r1.22 ev-pixbuf-cache.c --- shell/ev-pixbuf-cache.c 7 Jan 2006 13:18:28 -0000 1.22 +++ shell/ev-pixbuf-cache.c 7 Jun 2006 20:04:55 -0000 @@ -7,16 +7,17 @@ typedef struct _CacheJobInfo { EvJob *job; EvRenderContext *rc; /* Data we get from rendering */ GdkPixbuf *pixbuf; GList *link_mapping; GdkRegion *text_mapping; + GList *form_field_mappings; /* Selection data. * Selection_points are the coordinates encapsulated in selection. * target_points is the target selection size. */ EvRectangle selection_points; EvRectangle target_points; gboolean points_set; @@ -143,16 +144,20 @@ dispose_cache_job_info (CacheJobInfo *jo ev_job_queue_remove_job (job_info->job); g_object_unref (G_OBJECT (job_info->job)); job_info->job = NULL; } if (job_info->pixbuf) { g_object_unref (G_OBJECT (job_info->pixbuf)); job_info->pixbuf = NULL; } + if (job_info->form_field_mappings) { + ev_form_field_mapping_list_free (job_info->form_field_mappings); + job_info->form_field_mappings = NULL; + } if (job_info->link_mapping) { ev_link_mapping_free (job_info->link_mapping); job_info->link_mapping = NULL; } if (job_info->text_mapping) { gdk_region_destroy (job_info->text_mapping); job_info->text_mapping = NULL; } @@ -304,16 +309,17 @@ move_one_job (CacheJobInfo *job_info, page_offset = page - start_page; g_assert (page_offset >= 0 && page_offset <= ((end_page - start_page) + 1)); new_priority = EV_JOB_PRIORITY_HIGH; target_page = new_job_list + page_offset; } *target_page = *job_info; + job_info->form_field_mappings = NULL; job_info->job = NULL; job_info->pixbuf = NULL; job_info->link_mapping = NULL; if (new_priority != priority && target_page->job) { ev_job_queue_update_job (target_page->job, new_priority); } } @@ -405,17 +411,19 @@ copy_job_to_job_info (EvJobRender *job dispose_cache_job_info (job_info, pixbuf_cache); job_info->pixbuf = pixbuf; job_info->rc = rc; if (job_render->link_mapping) job_info->link_mapping = job_render->link_mapping; if (job_render->text_mapping) - job_info->text_mapping = job_render->text_mapping; + job_info->text_mapping = job_render->text_mapping; + if (job_render->form_field_mappings) + job_info->form_field_mappings = job_render->form_field_mappings; if (job_render->include_selection) { pixbuf = g_object_ref (job_render->selection); job_info->selection_points = job_render->selection_points; job_info->selection_region = gdk_region_copy (job_render->selection_region); job_info->selection = pixbuf; g_assert (job_info->selection_points.x1 >= 0); } @@ -492,16 +500,17 @@ static void add_job_if_needed (EvPixbufCache *pixbuf_cache, CacheJobInfo *job_info, EvPageCache *page_cache, gint page, gint rotation, gfloat scale, EvJobPriority priority) { + gboolean include_form = FALSE; gboolean include_links = FALSE; gboolean include_text = FALSE; gboolean include_selection = FALSE; int width, height; GdkColor *text, *base; if (job_info->job) return; @@ -519,16 +528,20 @@ add_job_if_needed (EvPixbufCache *pixbuf job_info->rc = ev_render_context_new (rotation, page, scale); } else { ev_render_context_set_rotation (job_info->rc, rotation); ev_render_context_set_page (job_info->rc, page); ev_render_context_set_scale (job_info->rc, scale); } /* Figure out what else we need for this job */ + /* if we don't set include_form to TRUE, sometimes the render job's form_field_mapping is NULL + although the page has some fields + if (job_info->form_field_mappings == NULL)*/ + include_form = TRUE; if (job_info->link_mapping == NULL) include_links = TRUE; if (job_info->text_mapping == NULL) include_text = TRUE; if (new_selection_pixbuf_needed (pixbuf_cache, job_info, page, scale)) { include_selection = TRUE; } @@ -536,16 +549,17 @@ add_job_if_needed (EvPixbufCache *pixbuf get_selection_colors (pixbuf_cache->view, &text, &base); job_info->job = ev_job_render_new (pixbuf_cache->document, job_info->rc, width, height, &(job_info->target_points), text, base, + include_form, include_links, include_text, include_selection); ev_job_queue_add_job (job_info->job, priority); g_signal_connect (job_info->job, "finished", G_CALLBACK (job_finished_cb), pixbuf_cache); } @@ -1016,9 +1030,27 @@ ev_pixbuf_cache_get_selection_list (EvPi retval = g_list_append (retval, selection); } page ++; } return retval; } + +GList * +ev_pixbuf_cache_get_form_field_mapping (EvPixbufCache *pixbuf_cache, + gint page) +{ + CacheJobInfo *job_info; + + job_info = find_job_cache (pixbuf_cache, page); + if(job_info == NULL) + return NULL; + + if(job_info->job && + EV_JOB(job_info->job)->finished) { + copy_job_to_job_info (EV_JOB_RENDER(job_info->job), job_info, pixbuf_cache); + } + return job_info->form_field_mappings; +} + Index: shell/ev-pixbuf-cache.h =================================================================== RCS file: /cvs/gnome/evince/shell/ev-pixbuf-cache.h,v retrieving revision 1.9 diff -u -8 -p -r1.9 ev-pixbuf-cache.h --- shell/ev-pixbuf-cache.h 6 Aug 2005 05:13:20 -0000 1.9 +++ shell/ev-pixbuf-cache.h 7 Jun 2006 20:04:55 -0000 @@ -58,16 +58,19 @@ void ev_pixbuf_cache_set_page_ gfloat scale, GList *selection_list); GdkPixbuf *ev_pixbuf_cache_get_pixbuf (EvPixbufCache *pixbuf_cache, gint page); GList *ev_pixbuf_cache_get_link_mapping (EvPixbufCache *pixbuf_cache, gint page); GdkRegion *ev_pixbuf_cache_get_text_mapping (EvPixbufCache *pixbuf_cache, gint page); +GList *ev_pixbuf_cache_get_form_field_mapping (EvPixbufCache *pixbuf_cache, + gint page); + void ev_pixbuf_cache_clear (EvPixbufCache *pixbuf_cache); void ev_pixbuf_cache_style_changed (EvPixbufCache *pixbuf_cache); /* Selection */ GdkPixbuf *ev_pixbuf_cache_get_selection_pixbuf (EvPixbufCache *pixbuf_cache, gint page, gfloat scale, GdkRegion **region);