X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=blobdiff_plain;f=libdocument%2Fev-document.c;h=78fb8a08f2de918ee52789a67f56492bde42523b;hb=424cafeb778a0d3efeff09016858340070f04cb1;hp=163f2e266caa8c17d982ecd025d658c573e444d7;hpb=95395e6b0e5e174a43931605043dba668232d331;p=evince.git diff --git a/libdocument/ev-document.c b/libdocument/ev-document.c index 163f2e26..78fb8a08 100644 --- a/libdocument/ev-document.c +++ b/libdocument/ev-document.c @@ -1,5 +1,6 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-indent-level: 8 -*- */ /* + * Copyright (C) 2009 Carlos Garcia Campos * Copyright (C) 2004 Marco Pesenti Gritti * * This program is free software; you can redistribute it and/or modify @@ -14,44 +15,64 @@ * * 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 +#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)) + +typedef struct _EvPageSize +{ + gdouble width; + gdouble height; +} EvPageSize; + +struct _EvDocumentPrivate +{ + gchar *uri; + + gint n_pages; -static void ev_document_class_init (gpointer g_class); + gboolean uniform; + gdouble uniform_width; + gdouble uniform_height; + 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 gboolean _ev_document_support_synctex (EvDocument *document); GMutex *ev_doc_mutex = NULL; GMutex *ev_fc_mutex = NULL; -GType -ev_document_get_type (void) -{ - static GType type = 0; - - if (G_UNLIKELY (type == 0)) - { - const GTypeInfo our_info = - { - sizeof (EvDocumentIface), - NULL, - NULL, - (GClassInitFunc)ev_document_class_init - }; - - type = g_type_register_static (G_TYPE_INTERFACE, - "EvDocument", - &our_info, (GTypeFlags)0); - - g_type_interface_add_prerequisite (type, G_TYPE_OBJECT); - } - - return type; -} +G_DEFINE_ABSTRACT_TYPE (EvDocument, ev_document, G_TYPE_OBJECT) GQuark ev_document_error_quark (void) @@ -63,9 +84,78 @@ ev_document_error_quark (void) return q; } +static EvPage * +ev_document_impl_get_page (EvDocument *document, + gint index) +{ + return ev_page_new (index); +} + +static EvDocumentInfo * +ev_document_impl_get_info (EvDocument *document) +{ + return g_new0 (EvDocumentInfo, 1); +} + +static void +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; + } + + if (document->priv->page_labels) { + gint i; + + for (i = 0; i < document->priv->n_pages; i++) { + g_free (document->priv->page_labels[i]); + } + g_free (document->priv->page_labels); + document->priv->page_labels = NULL; + } + + if (document->priv->info) { + ev_document_info_free (document->priv->info); + 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); +} + static void -ev_document_class_init (gpointer g_class) +ev_document_init (EvDocument *document) { + document->priv = EV_DOCUMENT_GET_PRIVATE (document); + + /* Assume all pages are the same size until proven otherwise */ + document->priv->uniform = TRUE; +} + +static void +ev_document_class_init (EvDocumentClass *klass) +{ + GObjectClass *g_object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (g_object_class, sizeof (EvDocumentPrivate)); + + 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; } GMutex * @@ -122,125 +212,529 @@ ev_document_fc_mutex_trylock (void) return g_mutex_trylock (ev_document_get_fc_mutex ()); } +/** + * ev_document_load: + * @document: a #EvDocument + * @uri: the document's URI + * @error: a #GError location to store an error, or %NULL + * + * Loads @document from @uri. + * + * On failure, %FALSE is returned and @error is filled in. + * If the document is encrypted, EV_DEFINE_ERROR_ENCRYPTED is returned. + * If the backend cannot load the specific document, EV_DOCUMENT_ERROR_INVALID + * is returned. Other errors are possible too, depending on the backend + * used to load the document and the URI, e.g. #GIOError, #GFileError, and + * #GConvertError. + * + * Returns: %TRUE on success, or %FALSE on failure. + */ gboolean ev_document_load (EvDocument *document, const char *uri, GError **error) { - EvDocumentIface *iface = EV_DOCUMENT_GET_IFACE (document); + EvDocumentClass *klass = EV_DOCUMENT_GET_CLASS (document); gboolean retval; - - retval = iface->load (document, uri, error); + GError *err = NULL; + + retval = klass->load (document, uri, &err); + if (!retval) { + if (err) { + g_propagate_error (error, err); + } else { + g_warning ("%s::EvDocument::load returned FALSE but did not fill in @error; fix the backend!\n", + G_OBJECT_TYPE_NAME (document)); + + /* So upper layers don't crash */ + g_set_error_literal (error, + EV_DOCUMENT_ERROR, + EV_DOCUMENT_ERROR_INVALID, + "Internal error in backend"); + } + } else { + gint i; + EvDocumentPrivate *priv = document->priv; + + /* 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); + + for (i = 0; i < priv->n_pages; i++) { + EvPage *page = ev_document_get_page (document, i); + gdouble page_width = 0; + gdouble page_height = 0; + EvPageSize *page_size; + gchar *page_label; + + _ev_document_get_page_size (document, page, &page_width, &page_height); + + 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)) { + /* It's a different page size. Backfill the array. */ + int j; + + priv->page_sizes = g_new0 (EvPageSize, priv->n_pages); + + for (j = 0; j < i; j++) { + page_size = &(priv->page_sizes[j]); + page_size->width = priv->uniform_width; + page_size->height = priv->uniform_height; + } + priv->uniform = FALSE; + } + if (!priv->uniform) { + page_size = &(priv->page_sizes[i]); + + page_size->width = page_width; + page_size->height = page_height; + + 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 = 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)); + } + + g_object_unref (page); + } + + 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); + } + } + } return retval; } +/** + * ev_document_save: + * @document: + * @uri: the target URI + * @error: a #GError location to store an error, or %NULL + * + * Saves @document to @uri. + * + * Returns: %TRUE on success, or %FALSE on error with @error filled in + */ gboolean ev_document_save (EvDocument *document, const char *uri, GError **error) { - EvDocumentIface *iface = EV_DOCUMENT_GET_IFACE (document); - gboolean retval; + EvDocumentClass *klass = EV_DOCUMENT_GET_CLASS (document); - retval = iface->save (document, uri, error); + return klass->save (document, uri, error); +} - return retval; +EvPage * +ev_document_get_page (EvDocument *document, + gint index) +{ + EvDocumentClass *klass = EV_DOCUMENT_GET_CLASS (document); + + return klass->get_page (document, index); } -int -ev_document_get_n_pages (EvDocument *document) +static gboolean +_ev_document_support_synctex (EvDocument *document) { - EvDocumentIface *iface = EV_DOCUMENT_GET_IFACE (document); - gint retval; + EvDocumentClass *klass = EV_DOCUMENT_GET_CLASS (document); - retval = iface->get_n_pages (document); + return klass->support_synctex ? klass->support_synctex (document) : FALSE; +} - return retval; +gboolean +ev_document_has_synctex (EvDocument *document) +{ + g_return_val_if_fail (EV_IS_DOCUMENT (document), FALSE); + + return document->priv->synctex_scanner != NULL; } -EvPage * -ev_document_get_page (EvDocument *document, - gint index) +/** + * 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) { - EvDocumentIface *iface = EV_DOCUMENT_GET_IFACE (document); - EvPage *retval; + 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; +} - if (iface->get_page) - retval = iface->get_page (document, index); - else - retval = ev_page_new (index); +/** + * 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; - return retval; + 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) +{ + EvDocumentClass *klass = EV_DOCUMENT_GET_CLASS (document); + + return klass->get_n_pages (document); +} + +gint +ev_document_get_n_pages (EvDocument *document) +{ + g_return_val_if_fail (EV_IS_DOCUMENT (document), 0); + + return document->priv->n_pages; +} + +static void +_ev_document_get_page_size (EvDocument *document, + EvPage *page, + double *width, + double *height) +{ + EvDocumentClass *klass = EV_DOCUMENT_GET_CLASS (document); + + klass->get_page_size (document, page, width, height); } void ev_document_get_page_size (EvDocument *document, - EvPage *page, + gint page_index, double *width, double *height) { - EvDocumentIface *iface = EV_DOCUMENT_GET_IFACE (document); + g_return_if_fail (EV_IS_DOCUMENT (document)); + g_return_if_fail (page_index >= 0 || page_index < document->priv->n_pages); + + if (width) + *width = document->priv->uniform ? + document->priv->uniform_width : + document->priv->page_sizes[page_index].width; + if (height) + *height = document->priv->uniform ? + document->priv->uniform_height : + document->priv->page_sizes[page_index].height; +} - iface->get_page_size (document, page, width, height); +static gchar * +_ev_document_get_page_label (EvDocument *document, + EvPage *page) +{ + EvDocumentClass *klass = EV_DOCUMENT_GET_CLASS (document); + + return klass->get_page_label ? + klass->get_page_label (document, page) : NULL; } -char * +gchar * ev_document_get_page_label (EvDocument *document, - EvPage *page) + gint page_index) { - EvDocumentIface *iface = EV_DOCUMENT_GET_IFACE (document); + g_return_val_if_fail (EV_IS_DOCUMENT (document), NULL); + g_return_val_if_fail (page_index >= 0 || page_index < document->priv->n_pages, NULL); - if (iface->get_page_label == NULL) - return NULL; + return (document->priv->page_labels && document->priv->page_labels[page_index]) ? + g_strdup (document->priv->page_labels[page_index]) : + g_strdup_printf ("%d", page_index + 1); +} + +static EvDocumentInfo * +_ev_document_get_info (EvDocument *document) +{ + EvDocumentClass *klass = EV_DOCUMENT_GET_CLASS (document); - return iface->get_page_label (document, page); + return klass->get_info (document); } EvDocumentInfo * ev_document_get_info (EvDocument *document) { - EvDocumentIface *iface = EV_DOCUMENT_GET_IFACE (document); + g_return_val_if_fail (EV_IS_DOCUMENT (document), NULL); - return iface->get_info (document); + return document->priv->info; } gboolean -ev_document_has_attachments (EvDocument *document) +ev_document_get_backend_info (EvDocument *document, EvDocumentBackendInfo *info) { - EvDocumentIface *iface = EV_DOCUMENT_GET_IFACE (document); + g_return_val_if_fail (EV_IS_DOCUMENT (document), FALSE); - if (iface->has_attachments == NULL) + EvDocumentClass *klass = EV_DOCUMENT_GET_CLASS (document); + if (klass->get_backend_info == NULL) return FALSE; - - return iface->has_attachments (document); + + return klass->get_backend_info (document, info); } -GList * -ev_document_get_attachments (EvDocument *document) +cairo_surface_t * +ev_document_render (EvDocument *document, + EvRenderContext *rc) { - EvDocumentIface *iface = EV_DOCUMENT_GET_IFACE (document); - GList *retval; + EvDocumentClass *klass = EV_DOCUMENT_GET_CLASS (document); - if (iface->get_attachments == NULL) - return NULL; - retval = iface->get_attachments (document); + return klass->render (document, rc); +} - return retval; +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; } -cairo_surface_t * -ev_document_render (EvDocument *document, - EvRenderContext *rc) +GdkPixbuf * +ev_document_get_thumbnail (EvDocument *document, + EvRenderContext *rc) { - EvDocumentIface *iface = EV_DOCUMENT_GET_IFACE (document); - cairo_surface_t *retval; + EvDocumentClass *klass = EV_DOCUMENT_GET_CLASS (document); - g_assert (iface->render); + if (klass->get_thumbnail) + return klass->get_thumbnail (document, rc); - retval = iface->render (document, rc); + return _ev_document_get_thumbnail (document, rc); +} - return retval; +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) +{ + g_return_val_if_fail (EV_IS_DOCUMENT (document), NULL); + + return (document->priv->info->fields_mask & EV_DOCUMENT_INFO_TITLE) ? + document->priv->info->title : NULL; +} + +gboolean +ev_document_is_page_size_uniform (EvDocument *document) +{ + g_return_val_if_fail (EV_IS_DOCUMENT (document), TRUE); + + return document->priv->uniform; +} + +void +ev_document_get_max_page_size (EvDocument *document, + gdouble *width, + gdouble *height) +{ + g_return_if_fail (EV_IS_DOCUMENT (document)); + + if (width) + *width = document->priv->max_width; + if (height) + *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) +{ + g_return_val_if_fail (EV_IS_DOCUMENT (document), FALSE); + + return (document->priv->max_width > 0 && document->priv->max_height > 0); +} + +gint +ev_document_get_max_label_len (EvDocument *document) +{ + g_return_val_if_fail (EV_IS_DOCUMENT (document), -1); + + return document->priv->max_label; +} + +gboolean +ev_document_has_text_page_labels (EvDocument *document) +{ + g_return_val_if_fail (EV_IS_DOCUMENT (document), FALSE); + + return document->priv->page_labels != NULL; +} + +gboolean +ev_document_find_page_by_label (EvDocument *document, + const gchar *page_label, + gint *page_index) +{ + gint i, page; + glong value; + gchar *endptr = NULL; + EvDocumentPrivate *priv = document->priv; + + g_return_val_if_fail (EV_IS_DOCUMENT (document), FALSE); + g_return_val_if_fail (page_label != NULL, FALSE); + g_return_val_if_fail (page_index != NULL, FALSE); + + /* First, look for a literal label match */ + for (i = 0; priv->page_labels && i < priv->n_pages; i ++) { + if (priv->page_labels[i] != NULL && + ! strcmp (page_label, priv->page_labels[i])) { + *page_index = i; + return TRUE; + } + } + + /* Second, look for a match with case insensitively */ + for (i = 0; priv->page_labels && i < priv->n_pages; i++) { + if (priv->page_labels[i] != NULL && + ! strcasecmp (page_label, priv->page_labels[i])) { + *page_index = i; + return TRUE; + } + } + + /* Next, parse the label, and see if the number fits */ + value = strtol (page_label, &endptr, 10); + if (endptr[0] == '\0') { + /* Page number is an integer */ + page = MIN (G_MAXINT, value); + + /* convert from a page label to a page offset */ + page --; + if (page >= 0 && page < priv->n_pages) { + *page_index = page; + return TRUE; + } + } + + return FALSE; } /* EvDocumentInfo */ @@ -254,15 +748,15 @@ ev_document_info_copy (EvDocumentInfo *info) g_return_val_if_fail (info != NULL, NULL); copy = g_new0 (EvDocumentInfo, 1); - copy->title = info->title ? g_strdup (info->title) : NULL; - copy->format = info->format ? g_strdup (info->format) : NULL; - copy->author = info->author ? g_strdup (info->author) : NULL; - copy->subject = info->subject ? g_strdup (info->subject) : NULL; - copy->keywords = info->keywords ? g_strdup (info->keywords) : NULL; - copy->security = info->security ? g_strdup (info->security) : NULL; - copy->creator = info->creator ? g_strdup (info->creator) : NULL; - copy->producer = info->producer ? g_strdup (info->producer) : NULL; - copy->linearized = info->linearized ? g_strdup (info->linearized) : NULL; + copy->title = g_strdup (info->title); + copy->format = g_strdup (info->format); + copy->author = g_strdup (info->author); + copy->subject = g_strdup (info->subject); + copy->keywords = g_strdup (info->keywords); + copy->security = g_strdup (info->security); + copy->creator = g_strdup (info->creator); + copy->producer = g_strdup (info->producer); + copy->linearized = g_strdup (info->linearized); copy->creation_date = info->creation_date; copy->modified_date = info->modified_date; @@ -271,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; @@ -291,10 +787,98 @@ 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) + +EvRectangle * +ev_rectangle_new (void) +{ + return g_new0 (EvRectangle, 1); +} + +EvRectangle * +ev_rectangle_copy (EvRectangle *rectangle) +{ + EvRectangle *new_rectangle; + + g_return_val_if_fail (rectangle != NULL, NULL); + + new_rectangle = g_new (EvRectangle, 1); + *new_rectangle = *rectangle; + + return new_rectangle; +} + +void +ev_rectangle_free (EvRectangle *rectangle) +{ + g_free (rectangle); +} /* Compares two rects. returns 0 if they're equal */ #define EPSILON 0.0000001 @@ -313,6 +897,3 @@ ev_rect_cmp (EvRectangle *a, (ABS (a->x2 - b->x2) < EPSILON) && (ABS (a->y2 - b->y2) < EPSILON)); } - - -