X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=blobdiff_plain;ds=inline;f=libdocument%2Fev-document.c;h=78fb8a08f2de918ee52789a67f56492bde42523b;hb=b03015826c22cb2c28a0d0507963c23b9c9ddcb3;hp=5c63b25f9d86bd7f2d84b0bbd1ff796c449d6cab;hpb=8c149ccd2a3cced2cd0a676ad6f7b8d33fd98404;p=evince.git diff --git a/libdocument/ev-document.c b/libdocument/ev-document.c index 5c63b25f..78fb8a08 100644 --- a/libdocument/ev-document.c +++ b/libdocument/ev-document.c @@ -15,7 +15,7 @@ * * 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. * */ @@ -25,6 +25,8 @@ #include #include "ev-document.h" +#include "ev-document-misc.h" +#include "synctex_parser.h" #define EV_DOCUMENT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EV_TYPE_DOCUMENT, EvDocumentPrivate)) @@ -36,6 +38,8 @@ typedef struct _EvPageSize struct _EvDocumentPrivate { + gchar *uri; + gint n_pages; gboolean uniform; @@ -44,21 +48,26 @@ struct _EvDocumentPrivate gdouble max_width; gdouble max_height; + gdouble min_width; + gdouble min_height; gint max_label; gchar **page_labels; EvPageSize *page_sizes; EvDocumentInfo *info; + + synctex_scanner_t synctex_scanner; }; -static gint _ev_document_get_n_pages (EvDocument *document); -static void _ev_document_get_page_size (EvDocument *document, - EvPage *page, - double *width, - double *height); -static gchar *_ev_document_get_page_label (EvDocument *document, - EvPage *page); -static EvDocumentInfo *_ev_document_get_info (EvDocument *document); +static gint _ev_document_get_n_pages (EvDocument *document); +static void _ev_document_get_page_size (EvDocument *document, + EvPage *page, + double *width, + double *height); +static gchar *_ev_document_get_page_label (EvDocument *document, + EvPage *page); +static EvDocumentInfo *_ev_document_get_info (EvDocument *document); +static gboolean _ev_document_support_synctex (EvDocument *document); GMutex *ev_doc_mutex = NULL; GMutex *ev_fc_mutex = NULL; @@ -93,6 +102,11 @@ ev_document_finalize (GObject *object) { EvDocument *document = EV_DOCUMENT (object); + if (document->priv->uri) { + g_free (document->priv->uri); + document->priv->uri = NULL; + } + if (document->priv->page_sizes) { g_free (document->priv->page_sizes); document->priv->page_sizes = NULL; @@ -113,6 +127,11 @@ ev_document_finalize (GObject *object) document->priv->info = NULL; } + if (document->priv->synctex_scanner) { + synctex_scanner_free (document->priv->synctex_scanner); + document->priv->synctex_scanner = NULL; + } + G_OBJECT_CLASS (ev_document_parent_class)->finalize (object); } @@ -134,6 +153,7 @@ ev_document_class_init (EvDocumentClass *klass) klass->get_page = ev_document_impl_get_page; klass->get_info = ev_document_impl_get_info; + klass->get_backend_info = NULL; g_object_class->finalize = ev_document_finalize; } @@ -239,8 +259,8 @@ ev_document_load (EvDocument *document, /* Cache some info about the document to avoid * going to the backends since it requires locks */ + priv->uri = g_strdup (uri); priv->n_pages = _ev_document_get_n_pages (document); - priv->info = _ev_document_get_info (document); for (i = 0; i < priv->n_pages; i++) { EvPage *page = ev_document_get_page (document, i); @@ -254,6 +274,10 @@ ev_document_load (EvDocument *document, if (i == 0) { priv->uniform_width = page_width; priv->uniform_height = page_height; + priv->max_width = priv->uniform_width; + priv->max_height = priv->uniform_height; + priv->min_width = priv->uniform_width; + priv->min_height = priv->uniform_height; } else if (priv->uniform && (priv->uniform_width != page_width || priv->uniform_height != page_height)) { @@ -277,25 +301,21 @@ ev_document_load (EvDocument *document, if (page_width > priv->max_width) priv->max_width = page_width; + if (page_width < priv->min_width) + priv->min_width = page_width; if (page_height > priv->max_height) priv->max_height = page_height; + if (page_height < priv->min_height) + priv->min_height = page_height; } page_label = _ev_document_get_page_label (document, page); if (page_label) { - if (priv->page_labels) { - priv->page_labels[i] = page_label; - } else { - gchar *numeric_label; - - numeric_label = g_strdup_printf ("%d", i + 1); - if (strcmp (numeric_label, page_label) != 0) { - priv->page_labels = g_new0 (gchar *, priv->n_pages); - priv->page_labels[i] = page_label; - } - g_free (numeric_label); - } + if (!priv->page_labels) + priv->page_labels = g_new0 (gchar *, priv->n_pages); + + priv->page_labels[i] = page_label; priv->max_label = MAX (priv->max_label, g_utf8_strlen (page_label, 256)); } @@ -303,9 +323,16 @@ ev_document_load (EvDocument *document, g_object_unref (page); } - if (priv->uniform) { - priv->max_width = priv->uniform_width; - priv->max_height = priv->uniform_height; + priv->info = _ev_document_get_info (document); + if (_ev_document_support_synctex (document)) { + gchar *filename; + + filename = g_filename_from_uri (uri, NULL, NULL); + if (filename != NULL) { + priv->synctex_scanner = + synctex_scanner_new_with_output_file (filename, NULL, 1); + g_free (filename); + } } } @@ -341,6 +368,120 @@ ev_document_get_page (EvDocument *document, return klass->get_page (document, index); } +static gboolean +_ev_document_support_synctex (EvDocument *document) +{ + EvDocumentClass *klass = EV_DOCUMENT_GET_CLASS (document); + + return klass->support_synctex ? klass->support_synctex (document) : FALSE; +} + +gboolean +ev_document_has_synctex (EvDocument *document) +{ + g_return_val_if_fail (EV_IS_DOCUMENT (document), FALSE); + + return document->priv->synctex_scanner != NULL; +} + +/** + * ev_document_synctex_backward_search: + * @document: + * @page: the target page + * @x: + * @y: + * + * Peforms a Synctex backward search to obtain the TeX input file, line and + * (possibly) column corresponding to the position (@x,@y) (in 72dpi + * coordinates) in the @page of @document. + * + * Returns: A pointer to the EvSourceLink structure that holds the result. @NULL if synctex + * is not enabled for the document or no result is found. + * The EvSourceLink pointer should be freed with g_free after it is used. + */ +EvSourceLink * +ev_document_synctex_backward_search (EvDocument *document, + gint page_index, + gfloat x, + gfloat y) +{ + EvSourceLink *result = NULL; + synctex_scanner_t scanner; + + g_return_val_if_fail (EV_IS_DOCUMENT (document), NULL); + + scanner = document->priv->synctex_scanner; + if (!scanner) + return NULL; + + if (synctex_edit_query (scanner, page_index + 1, x, y) > 0) { + synctex_node_t node; + + /* We assume that a backward search returns either zero or one result_node */ + node = synctex_next_result (scanner); + if (node != NULL) { + const gchar *filename; + + filename = synctex_scanner_get_name (scanner, synctex_node_tag (node)); + + if (filename) { + result = g_new (EvSourceLink, 1); + result->filename = filename; + result->line = synctex_node_line (node); + result->col = synctex_node_column (node); + } + } + } + + return result; +} + +/** + * ev_document_synctex_forward_search: + * @document: + * @source_link: + * + * Peforms a Synctex forward search to obtain the area in the document + * corresponding to the position @line and @column number in the source Tex file + * + * Returns: An EvMapping with the page number and area corresponfing to + * the given line in the source file. It must be free with g_free when done + */ +EvMapping * +ev_document_synctex_forward_search (EvDocument *document, + EvSourceLink *link) +{ + EvMapping *result = NULL; + synctex_scanner_t scanner; + + g_return_val_if_fail (EV_IS_DOCUMENT (document), NULL); + + scanner = document->priv->synctex_scanner; + if (!scanner) + return NULL; + + if (synctex_display_query (scanner, link->filename, link->line, link->col) > 0) { + synctex_node_t node; + gint page; + + if ((node = synctex_next_result (scanner))) { + result = g_new (EvMapping, 1); + + page = synctex_node_page (node) - 1; + result->data = GINT_TO_POINTER (page); + + result->area.x1 = synctex_node_box_visible_h (node); + result->area.y1 = synctex_node_box_visible_v (node) - + synctex_node_box_visible_height (node); + result->area.x2 = synctex_node_box_visible_width (node) + result->area.x1; + result->area.y2 = synctex_node_box_visible_depth (node) + + synctex_node_box_visible_height (node) + result->area.y1; + } + } + + return result; +} + static gint _ev_document_get_n_pages (EvDocument *document) { @@ -425,6 +566,18 @@ ev_document_get_info (EvDocument *document) return document->priv->info; } +gboolean +ev_document_get_backend_info (EvDocument *document, EvDocumentBackendInfo *info) +{ + g_return_val_if_fail (EV_IS_DOCUMENT (document), FALSE); + + EvDocumentClass *klass = EV_DOCUMENT_GET_CLASS (document); + if (klass->get_backend_info == NULL) + return FALSE; + + return klass->get_backend_info (document, info); +} + cairo_surface_t * ev_document_render (EvDocument *document, EvRenderContext *rc) @@ -434,6 +587,40 @@ ev_document_render (EvDocument *document, return klass->render (document, rc); } +static GdkPixbuf * +_ev_document_get_thumbnail (EvDocument *document, + EvRenderContext *rc) +{ + cairo_surface_t *surface; + GdkPixbuf *pixbuf; + + surface = ev_document_render (document, rc); + pixbuf = ev_document_misc_pixbuf_from_surface (surface); + cairo_surface_destroy (surface); + + return pixbuf; +} + +GdkPixbuf * +ev_document_get_thumbnail (EvDocument *document, + EvRenderContext *rc) +{ + EvDocumentClass *klass = EV_DOCUMENT_GET_CLASS (document); + + if (klass->get_thumbnail) + return klass->get_thumbnail (document, rc); + + return _ev_document_get_thumbnail (document, rc); +} + +const gchar * +ev_document_get_uri (EvDocument *document) +{ + g_return_val_if_fail (EV_IS_DOCUMENT (document), NULL); + + return document->priv->uri; +} + const gchar * ev_document_get_title (EvDocument *document) { @@ -464,6 +651,19 @@ ev_document_get_max_page_size (EvDocument *document, *height = document->priv->max_height; } +void +ev_document_get_min_page_size (EvDocument *document, + gdouble *width, + gdouble *height) +{ + g_return_if_fail (EV_IS_DOCUMENT (document)); + + if (width) + *width = document->priv->min_width; + if (height) + *height = document->priv->min_height; +} + gboolean ev_document_check_dimensions (EvDocument *document) { @@ -565,6 +765,8 @@ ev_document_info_copy (EvDocumentInfo *info) copy->ui_hints = info->ui_hints; copy->permissions = info->permissions; copy->n_pages = info->n_pages; + copy->license = ev_document_license_copy (info->license); + copy->fields_mask = info->fields_mask; return copy; @@ -585,10 +787,71 @@ ev_document_info_free (EvDocumentInfo *info) g_free (info->producer); g_free (info->linearized); g_free (info->security); - + ev_document_license_free (info->license); + g_free (info); } +/* EvDocumentLicense */ +EV_DEFINE_BOXED_TYPE (EvDocumentLicense, ev_document_license, ev_document_license_copy, ev_document_license_free) + +EvDocumentLicense * +ev_document_license_new (void) +{ + return g_new0 (EvDocumentLicense, 1); +} + +EvDocumentLicense * +ev_document_license_copy (EvDocumentLicense *license) +{ + EvDocumentLicense *new_license; + + if (!license) + return NULL; + + new_license = ev_document_license_new (); + + if (license->text) + new_license->text = g_strdup (license->text); + if (license->uri) + new_license->uri = g_strdup (license->uri); + if (license->web_statement) + new_license->web_statement = g_strdup (license->web_statement); + + return new_license; +} + +void +ev_document_license_free (EvDocumentLicense *license) +{ + if (!license) + return; + + g_free (license->text); + g_free (license->uri); + g_free (license->web_statement); + + g_free (license); +} + +const gchar * +ev_document_license_get_text (EvDocumentLicense *license) +{ + return license->text; +} + +const gchar * +ev_document_license_get_uri (EvDocumentLicense *license) +{ + return license->uri; +} + +const gchar * +ev_document_license_get_web_statement (EvDocumentLicense *license) +{ + return license->web_statement; +} + /* EvRectangle */ EV_DEFINE_BOXED_TYPE (EvRectangle, ev_rectangle, ev_rectangle_copy, ev_rectangle_free)