]> www.fi.muni.cz Git - evince.git/commitdiff
Implement search based on poppler_page_find_text(). Currently a bit crude
authorKristian Høgsberg <krh@redhat.com>
Fri, 1 Apr 2005 07:24:36 +0000 (07:24 +0000)
committerKristian Høgsberg <krh@src.gnome.org>
Fri, 1 Apr 2005 07:24:36 +0000 (07:24 +0000)
2005-04-01  Kristian Høgsberg  <krh@redhat.com>

        * pdf/ev-poppler.cc: Implement search based on
        poppler_page_find_text().  Currently a bit crude since we remember
        all matches from all pages.  Also, we grab the big document lock
        when we search since searching changes the underlying stream and
        thus conflicts with the rendering thread.

        * shell/ev-view.c: (draw_rubberband), (highlight_find_results),
        (jump_to_find_page), (ev_view_set_document), (ev_view_find_next),
        (ev_view_find_previous): Fix some page indexes to be 0 based,
        offset rubber band by view offset,

ChangeLog
pdf/ev-poppler.cc
shell/ev-view.c

index c0372c6b998d92a78ae94696bcd320d449db9a49..37a0cc4643664da55d94e5cece93f52d5b4cc94c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2005-04-01  Kristian Høgsberg  <krh@redhat.com>
+
+       * pdf/ev-poppler.cc: Implement search based on
+       poppler_page_find_text().  Currently a bit crude since we remember
+       all matches from all pages.  Also, we grab the big document lock
+       when we search since searching changes the underlying stream and
+       thus conflicts with the rendering thread.
+       
+       * shell/ev-view.c: (draw_rubberband), (highlight_find_results),
+       (jump_to_find_page), (ev_view_set_document), (ev_view_find_next),
+       (ev_view_find_previous): Fix some page indexes to be 0 based,
+       offset rubber band by view offset,
+
 Fri Apr 01 09:21:12 2005  Pablo Saratxaga  <pablo@mandrakesoft.com>
 
        * configure.ac: Added Walloon (wa) to ALL_LINGUAS.
index 97c882f35084c97399015ed5540d163dcf8efc68..e1ce95a41c0e5d10e99299b656907071cd65cc7c 100644 (file)
@@ -17,6 +17,8 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
+#include <math.h>
+#include <string.h>
 #include <gtk/gtk.h>
 #include <poppler.h>
 #include <poppler-document.h>
@@ -37,6 +39,15 @@ enum {
 };
 
 
+typedef struct {
+       PdfDocument *document;
+       char *text;
+       GList **pages;
+       guint idle;
+       int start_page;
+       int search_page;
+} PdfDocumentSearch;
+
 struct _PdfDocumentClass
 {
        GObjectClass parent_class;
@@ -50,12 +61,15 @@ struct _PdfDocument
        PopplerPage *page;
        double scale;
        gchar *password;
+
+       PdfDocumentSearch *search;
 };
 
 static void pdf_document_document_iface_init            (EvDocumentIface           *iface);
 static void pdf_document_security_iface_init            (EvDocumentSecurityIface   *iface);
 static void pdf_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface);
 static void pdf_document_document_links_iface_init      (EvDocumentLinksIface      *iface);
+static void pdf_document_find_iface_init                (EvDocumentFindIface       *iface);
 static void pdf_document_thumbnails_get_dimensions      (EvDocumentThumbnails      *document_thumbnails,
                                                         gint                       page,
                                                         gint                       size,
@@ -74,11 +88,11 @@ G_DEFINE_TYPE_WITH_CODE (PdfDocument, pdf_document, G_TYPE_OBJECT,
                                                        pdf_document_document_thumbnails_iface_init);
                                 G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_LINKS,
                                                        pdf_document_document_links_iface_init);
+                                G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_FIND,
+                                                       pdf_document_find_iface_init);
 #if 0
                                 G_IMPLEMENT_INTERFACE (EV_TYPE_PS_EXPORTER,
                                                        pdf_document_ps_exporter_iface_init);
-                                G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_FIND,
-                                                       pdf_document_find_iface_init);
 #endif
                         });
 
@@ -606,6 +620,221 @@ pdf_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface)
        iface->get_dimensions = pdf_document_thumbnails_get_dimensions;
 }
 
+
+static gboolean
+pdf_document_search_idle_callback (void *data)
+{
+        PdfDocumentSearch *search = (PdfDocumentSearch*) data;
+        PdfDocument *pdf_document = search->document;
+        int n_pages, changed_page;
+       GList *matches;
+       PopplerPage *page;
+
+       page = poppler_document_get_page (search->document->document,
+                                         search->search_page);
+
+       g_mutex_lock (EV_DOC_MUTEX);
+       matches = poppler_page_find_text (page, search->text);
+       g_mutex_unlock (EV_DOC_MUTEX);
+
+       search->pages[search->search_page] = matches;
+        n_pages = pdf_document_get_n_pages (EV_DOCUMENT (search->document));
+
+       changed_page = search->start_page;
+
+        search->search_page += 1;
+        if (search->search_page == n_pages) {
+                /* wrap around */
+                search->search_page = 0;
+        }
+
+        if (search->search_page != search->start_page) {
+               ev_document_find_changed (EV_DOCUMENT_FIND (pdf_document),
+                                         changed_page);
+               return TRUE;
+       }
+
+        /* We're done. */
+        search->idle = 0; /* will return FALSE to remove */
+        return FALSE;
+}
+
+
+static PdfDocumentSearch *
+pdf_document_search_new (PdfDocument *pdf_document, const char *text)
+{
+       PdfDocumentSearch *search;
+       int n_pages;
+       int i;
+
+       n_pages = pdf_document_get_n_pages (EV_DOCUMENT (pdf_document));
+
+        search = g_new0 (PdfDocumentSearch, 1);
+
+       search->text = g_strdup (text);
+        search->pages = g_new0 (GList *, n_pages);
+       for (i = 0; i < n_pages; i++) {
+               search->pages[i] = NULL;
+       }
+
+        search->document = pdf_document;
+
+        /* We add at low priority so the progress bar repaints */
+        search->idle = g_idle_add_full (G_PRIORITY_LOW,
+                                        pdf_document_search_idle_callback,
+                                        search,
+                                        NULL);
+
+        search->start_page = pdf_document_get_page (EV_DOCUMENT (pdf_document));
+        search->search_page = search->start_page;
+
+       return search;
+}
+
+static void
+pdf_document_search_free (PdfDocumentSearch   *search)
+{
+        PdfDocument *pdf_document = search->document;
+       int n_pages;
+       int i;
+
+        if (search->idle != 0)
+                g_source_remove (search->idle);
+
+       n_pages = pdf_document_get_n_pages (EV_DOCUMENT (pdf_document));
+       for (i = 0; i < n_pages; i++) {
+               g_list_foreach (search->pages[i], (GFunc) g_free, NULL);
+               g_list_free (search->pages[i]);
+       }
+       
+        g_free (search->text);
+}
+
+static void
+pdf_document_find_begin (EvDocumentFind   *document,
+                         const char       *search_string,
+                         gboolean          case_sensitive)
+{
+        PdfDocument *pdf_document = PDF_DOCUMENT (document);
+
+        /* FIXME handle case_sensitive (right now XPDF
+         * code is always case insensitive for ASCII
+         * and case sensitive for all other languaages)
+         */
+
+       if (pdf_document->search &&
+           strcmp (search_string, pdf_document->search->text) == 0)
+                return;
+
+        if (pdf_document->search)
+                pdf_document_search_free (pdf_document->search);
+
+        pdf_document->search = pdf_document_search_new (pdf_document,
+                                                       search_string);
+}
+
+int
+pdf_document_find_get_n_results (EvDocumentFind *document_find)
+{
+       PdfDocumentSearch *search = PDF_DOCUMENT (document_find)->search;
+       int current_page;
+
+       current_page = pdf_document_get_page (EV_DOCUMENT (document_find));
+
+       if (search) {
+               return g_list_length (search->pages[current_page]);
+       } else {
+               return 0;
+       }
+}
+
+gboolean
+pdf_document_find_get_result (EvDocumentFind *document_find,
+                             int             n_result,
+                             GdkRectangle   *rectangle)
+{
+       PdfDocument *pdf_document = PDF_DOCUMENT (document_find);
+       PdfDocumentSearch *search = pdf_document->search;
+       PopplerRectangle *r;
+       int current_page;
+       double scale;
+
+       if (search == NULL)
+               return FALSE;
+
+       current_page = pdf_document_get_page (EV_DOCUMENT (pdf_document));
+       r = (PopplerRectangle *) g_list_nth_data (search->pages[current_page],
+                                                 n_result);
+       if (r == NULL)
+               return FALSE;
+
+       scale = pdf_document->scale;
+       rectangle->x = (gint) floor (r->x1 * scale);
+       rectangle->y = (gint) floor (r->y1 * scale);
+       rectangle->width = (gint) ceil (r->x2 * scale) - rectangle->x;
+       rectangle->height = (gint) ceil (r->y2 * scale) - rectangle->y;
+       
+       return TRUE;
+}
+
+int
+pdf_document_find_page_has_results (EvDocumentFind *document_find,
+                                   int             page)
+{
+       PdfDocumentSearch *search = PDF_DOCUMENT (document_find)->search;
+
+       g_return_val_if_fail (search != NULL, FALSE);
+
+       return search->pages[page] != NULL;
+}
+
+double
+pdf_document_find_get_progress (EvDocumentFind *document_find)
+{
+       PdfDocumentSearch *search;
+       int n_pages, pages_done;
+
+       search = PDF_DOCUMENT (document_find)->search;
+
+       if (search == NULL) {
+               return 0;
+       }
+
+       n_pages = pdf_document_get_n_pages (EV_DOCUMENT (document_find));
+       if (search->search_page > search->start_page) {
+               pages_done = search->search_page - search->start_page + 1;
+       } else if (search->search_page == search->start_page) {
+               pages_done = n_pages;
+       } else {
+               pages_done = n_pages - search->start_page + search->search_page;
+       }
+
+       return pages_done / (double) n_pages;
+}
+
+static void
+pdf_document_find_cancel (EvDocumentFind *document)
+{
+        PdfDocument *pdf_document = PDF_DOCUMENT (document);
+
+       if (pdf_document->search) {
+               pdf_document_search_free (pdf_document->search);
+               pdf_document->search = NULL;
+       }
+}
+
+static void
+pdf_document_find_iface_init (EvDocumentFindIface *iface)
+{
+        iface->begin = pdf_document_find_begin;
+       iface->get_n_results = pdf_document_find_get_n_results;
+       iface->get_result = pdf_document_find_get_result;
+       iface->page_has_results = pdf_document_find_page_has_results;
+       iface->get_progress = pdf_document_find_get_progress;
+        iface->cancel = pdf_document_find_cancel;
+}
+
+
 PdfDocument *
 pdf_document_new (void)
 {
index 80958817a904dd9f49b1f4f7752a22e786f2f18e..eaf8804651178a02b3f97857b95b16a45c328ca7 100644 (file)
@@ -431,6 +431,9 @@ draw_rubberband (GtkWidget *widget, GdkWindow *window,
        GdkPixbuf *pixbuf;
        GdkColor *fill_color_gdk;
        guint fill_color;
+       int x_offset, y_offset;
+
+       ev_view_get_offsets (EV_VIEW (widget), &x_offset, &y_offset); 
 
        fill_color_gdk = gdk_color_copy (&GTK_WIDGET (widget)->style->base[GTK_STATE_SELECTED]);
        fill_color = ev_gdk_color_to_rgb (fill_color_gdk) << 8 | alpha;
@@ -441,7 +444,7 @@ draw_rubberband (GtkWidget *widget, GdkWindow *window,
 
        gdk_draw_pixbuf (window, NULL, pixbuf,
                         0, 0,
-                        rect->x,rect->y,
+                        rect->x + x_offset, rect->y + y_offset,
                         rect->width, rect->height,
                         GDK_RGB_DITHER_NONE,
                         0, 0);
@@ -451,7 +454,7 @@ draw_rubberband (GtkWidget *widget, GdkWindow *window,
        gc = gdk_gc_new (window);
        gdk_gc_set_rgb_fg_color (gc, fill_color_gdk);
        gdk_draw_rectangle (window, gc, FALSE,
-                           rect->x, rect->y,
+                           rect->x + x_offset, rect->y + y_offset,
                            rect->width - 1,
                            rect->height - 1);
        g_object_unref (gc);
@@ -469,11 +472,9 @@ highlight_find_results (EvView *view)
 
        find = EV_DOCUMENT_FIND (view->document);
 
-#if 0
        g_mutex_lock (EV_DOC_MUTEX);
        results = ev_document_find_get_n_results (find);
        g_mutex_unlock (EV_DOC_MUTEX);
-#endif
        
        for (i = 0; i < results; i++) {
                GdkRectangle rectangle;
@@ -1239,16 +1240,16 @@ jump_to_find_page (EvView *view)
 
        n_pages = ev_page_cache_get_n_pages (view->page_cache);
 
-       for (i = 0; i <= n_pages; i++) {
+       for (i = 0; i < n_pages; i++) {
                int has_results;
                int page;
 
                page = i + view->find_page;
-               if (page > n_pages) {
+               if (page >= n_pages) {
                        page = page - n_pages;
                }
 
-               g_mutex_lock (EV_DOC_MUTEX);
+               //              g_mutex_lock (EV_DOC_MUTEX);
                has_results = ev_document_find_page_has_results
                                (EV_DOCUMENT_FIND (view->document), page);
                if (has_results == -1) {
@@ -1357,7 +1358,7 @@ ev_view_set_document (EvView     *view,
                 }
 
                view->document = document;
-               view->find_page = 1;
+               view->find_page = 0;
                view->find_result = 0;
 
                if (view->document) {
@@ -1539,8 +1540,8 @@ ev_view_find_next (EvView *view)
                view->find_result = 0;
                view->find_page++;
 
-               if (view->find_page > n_pages) {
-                       view->find_page = 1;
+               if (view->find_page >= n_pages) {
+                       view->find_page = 0;
                }
 
                jump_to_find_page (view);
@@ -1571,8 +1572,8 @@ ev_view_find_previous (EvView *view)
                view->find_result = 0;
                view->find_page--;
 
-               if (view->find_page < 1) {
-                       view->find_page = n_pages;
+               if (view->find_page < 0) {
+                       view->find_page = n_pages - 1;
                }
 
                jump_to_find_page (view);