Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@redhat.com>2005-04-01 07:24:36 (GMT)
committer Kristian Høgsberg <krh@src.gnome.org>2005-04-01 07:24:36 (GMT)
commit40189c94ae17f6c54a8e28d37755f5d596a4cd4f (patch)
tree3862821942792f5b6b9dc40cfe26ce2fb690ce9e
parentc3c50adc936b117b89587d13be0ddc76f77dcb18 (diff)
Implement search based on poppler_page_find_text(). Currently a bit crude
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,
-rw-r--r--ChangeLog13
-rw-r--r--pdf/ev-poppler.cc233
-rw-r--r--shell/ev-view.c25
3 files changed, 257 insertions, 14 deletions
diff --git a/ChangeLog b/ChangeLog
index c0372c6..37a0cc4 100644
--- 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.
diff --git a/pdf/ev-poppler.cc b/pdf/ev-poppler.cc
index 97c882f..e1ce95a 100644
--- a/pdf/ev-poppler.cc
+++ b/pdf/ev-poppler.cc
@@ -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)
{
diff --git a/shell/ev-view.c b/shell/ev-view.c
index 8095881..eaf8804 100644
--- a/shell/ev-view.c
+++ b/shell/ev-view.c
@@ -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);