[poppler] 4 commits - glib/demo glib/poppler.h glib/poppler-page.cc glib/poppler-page.h glib/reference poppler/TextOutputDev.cc
Carlos Garcia Campos
carlosgc at kemper.freedesktop.org
Sat Jun 2 08:42:57 PDT 2012
glib/demo/find.c | 314 +++++++++++++++++++++++++++++++-----
glib/poppler-page.cc | 52 ++++-
glib/poppler-page.h | 3
glib/poppler.h | 18 ++
glib/reference/poppler-sections.txt | 2
poppler/TextOutputDev.cc | 144 ++++++++--------
6 files changed, 414 insertions(+), 119 deletions(-)
New commits:
commit 0df0aa439eed1d9838a80942e00af08e9acabb8d
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date: Sat Jun 2 17:33:23 2012 +0200
glib-demo: Add find options to find demo
diff --git a/glib/demo/find.c b/glib/demo/find.c
index 0ba3454..664c597 100644
--- a/glib/demo/find.c
+++ b/glib/demo/find.c
@@ -39,6 +39,7 @@ typedef struct {
GtkWidget *entry;
GtkWidget *progress;
+ PopplerFindFlags options;
gint n_pages;
gint page_index;
@@ -103,7 +104,7 @@ pgd_find_find_text (PgdFindDemo *demo)
model = gtk_tree_view_get_model (GTK_TREE_VIEW (demo->treeview));
timer = g_timer_new ();
- matches = poppler_page_find_text (page, gtk_entry_get_text (GTK_ENTRY (demo->entry)));
+ matches = poppler_page_find_text_with_options (page, gtk_entry_get_text (GTK_ENTRY (demo->entry)), demo->options);
g_timer_stop (timer);
if (matches) {
GtkTreeIter iter;
@@ -335,6 +336,36 @@ pgd_find_selection_changed (GtkTreeSelection *treeselection,
}
}
+static void
+pgd_find_case_sensitive_toggled (GtkToggleButton *togglebutton,
+ PgdFindDemo *demo)
+{
+ if (gtk_toggle_button_get_active (togglebutton))
+ demo->options |= POPPLER_FIND_CASE_SENSITIVE;
+ else
+ demo->options &= ~POPPLER_FIND_CASE_SENSITIVE;
+}
+
+static void
+pgd_find_backwards_toggled (GtkToggleButton *togglebutton,
+ PgdFindDemo *demo)
+{
+ if (gtk_toggle_button_get_active (togglebutton))
+ demo->options |= POPPLER_FIND_BACKWARDS;
+ else
+ demo->options &= ~POPPLER_FIND_BACKWARDS;
+}
+
+static void
+pgd_find_whole_words_toggled (GtkToggleButton *togglebutton,
+ PgdFindDemo *demo)
+{
+ if (gtk_toggle_button_get_active (togglebutton))
+ demo->options |= POPPLER_FIND_WHOLE_WORDS_ONLY;
+ else
+ demo->options &= ~POPPLER_FIND_WHOLE_WORDS_ONLY;
+}
+
GtkWidget *
pgd_find_create_widget (PopplerDocument *document)
{
@@ -342,6 +373,7 @@ pgd_find_create_widget (PopplerDocument *document)
GtkWidget *vbox, *hbox;
GtkWidget *button;
GtkWidget *swindow;
+ GtkWidget *checkbutton;
GtkTreeModel *model;
GtkWidget *treeview;
GtkCellRenderer *renderer;
@@ -354,6 +386,7 @@ pgd_find_create_widget (PopplerDocument *document)
demo->n_pages = poppler_document_get_n_pages (document);
demo->selected_page = -1;
+ demo->options = POPPLER_FIND_DEFAULT;
hpaned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
gtk_paned_set_position (GTK_PANED (hpaned), 300);
@@ -386,6 +419,32 @@ pgd_find_create_widget (PopplerDocument *document)
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 6);
gtk_widget_show (hbox);
+ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+
+ checkbutton = gtk_check_button_new_with_label ("Case sensitive");
+ g_signal_connect (checkbutton, "toggled",
+ G_CALLBACK (pgd_find_case_sensitive_toggled),
+ demo);
+ gtk_box_pack_start (GTK_BOX (hbox), checkbutton, FALSE, FALSE, 0);
+ gtk_widget_show (checkbutton);
+
+ checkbutton = gtk_check_button_new_with_label ("Backwards");
+ g_signal_connect (checkbutton, "toggled",
+ G_CALLBACK (pgd_find_backwards_toggled),
+ demo);
+ gtk_box_pack_start (GTK_BOX (hbox), checkbutton, FALSE, FALSE, 0);
+ gtk_widget_show (checkbutton);
+
+ checkbutton = gtk_check_button_new_with_label ("Whole words only");
+ g_signal_connect (checkbutton, "toggled",
+ G_CALLBACK (pgd_find_whole_words_toggled),
+ demo);
+ gtk_box_pack_start (GTK_BOX (hbox), checkbutton, FALSE, FALSE, 0);
+ gtk_widget_show (checkbutton);
+
+ gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+ gtk_widget_show (hbox);
+
swindow = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
commit 52b3ede4bfd1e2288a0efca34da5d6239d3563e9
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date: Sat Jun 2 16:25:06 2012 +0200
glib-demo: Show search matches in a document view
diff --git a/glib/demo/find.c b/glib/demo/find.c
index 0fdce85..0ba3454 100644
--- a/glib/demo/find.c
+++ b/glib/demo/find.c
@@ -26,20 +26,27 @@ enum {
Y2_COLUMN,
VISIBLE_COLUMN,
+ PAGE_COLUMN,
+ PAGE_RECT,
N_COLUMNS
};
typedef struct {
PopplerDocument *doc;
- GtkTreeModel *model;
+ GtkWidget *treeview;
+ GtkWidget *darea;
GtkWidget *entry;
GtkWidget *progress;
gint n_pages;
gint page_index;
-
+
guint idle_id;
+
+ cairo_surface_t *surface;
+ gint selected_page;
+ GdkRectangle selected_match;
} PgdFindDemo;
static void
@@ -58,10 +65,10 @@ pgd_find_free (PgdFindDemo *demo)
demo->doc = NULL;
}
- if (demo->model) {
- g_object_unref (demo->model);
- demo->model = NULL;
- }
+ if (demo->surface) {
+ cairo_surface_destroy (demo->surface);
+ demo->surface = NULL;
+ }
g_free (demo);
}
@@ -83,9 +90,10 @@ pgd_find_update_progress (PgdFindDemo *demo,
static gboolean
pgd_find_find_text (PgdFindDemo *demo)
{
- PopplerPage *page;
- GList *matches;
- GTimer *timer;
+ PopplerPage *page;
+ GList *matches;
+ GTimer *timer;
+ GtkTreeModel *model;
page = poppler_document_get_page (demo->doc, demo->page_index);
if (!page) {
@@ -93,6 +101,7 @@ pgd_find_find_text (PgdFindDemo *demo)
return demo->page_index < demo->n_pages;
}
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (demo->treeview));
timer = g_timer_new ();
matches = poppler_page_find_text (page, gtk_entry_get_text (GTK_ENTRY (demo->entry)));
g_timer_stop (timer);
@@ -100,45 +109,58 @@ pgd_find_find_text (PgdFindDemo *demo)
GtkTreeIter iter;
gchar *str;
GList *l;
+ gdouble height;
gint n_match = 0;
str = g_strdup_printf ("%d matches found on page %d in %.4f seconds",
g_list_length (matches), demo->page_index + 1,
g_timer_elapsed (timer, NULL));
- gtk_tree_store_append (GTK_TREE_STORE (demo->model), &iter, NULL);
- gtk_tree_store_set (GTK_TREE_STORE (demo->model), &iter,
+ gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &iter,
TITLE_COLUMN, str,
VISIBLE_COLUMN, FALSE,
+ PAGE_COLUMN, demo->page_index,
-1);
g_free (str);
-
+
+ poppler_page_get_size (page, NULL, &height);
+
for (l = matches; l && l->data; l = g_list_next (l)) {
PopplerRectangle *rect = (PopplerRectangle *)l->data;
GtkTreeIter iter_child;
gchar *x1, *y1, *x2, *y2;
+ gdouble tmp;
str = g_strdup_printf ("Match %d", ++n_match);
x1 = g_strdup_printf ("%.2f", rect->x1);
y1 = g_strdup_printf ("%.2f", rect->y1);
x2 = g_strdup_printf ("%.2f", rect->x2);
y2 = g_strdup_printf ("%.2f", rect->y2);
-
- gtk_tree_store_append (GTK_TREE_STORE (demo->model), &iter_child, &iter);
- gtk_tree_store_set (GTK_TREE_STORE (demo->model), &iter_child,
+
+ tmp = rect->y1;
+ rect->y1 = height - rect->y2;
+ rect->y2 = height - tmp;
+
+ gtk_tree_store_append (GTK_TREE_STORE (model), &iter_child, &iter);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &iter_child,
TITLE_COLUMN, str,
X1_COLUMN, x1,
Y1_COLUMN, y1,
X2_COLUMN, x2,
Y2_COLUMN, y2,
VISIBLE_COLUMN, TRUE,
+ PAGE_COLUMN, demo->page_index,
+ PAGE_RECT, rect,
-1);
g_free (str);
g_free (x1);
g_free (y1);
g_free (x2);
g_free (y2);
- poppler_rectangle_free (rect);
+ g_object_weak_ref (G_OBJECT (model),
+ (GWeakNotify)poppler_rectangle_free,
+ rect);
}
g_list_free (matches);
}
@@ -152,11 +174,115 @@ pgd_find_find_text (PgdFindDemo *demo)
return demo->page_index < demo->n_pages;
}
+static cairo_surface_t *
+pgd_find_render_page (PgdFindDemo *demo)
+{
+ cairo_t *cr;
+ PopplerPage *page;
+ gdouble width, height;
+ cairo_surface_t *surface = NULL;
+
+ page = poppler_document_get_page (demo->doc, demo->selected_page);
+ if (!page)
+ return NULL;
+
+ poppler_page_get_size (page, &width, &height);
+ gtk_widget_set_size_request (demo->darea, width, height);
+
+ surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
+ width, height);
+ cr = cairo_create (surface);
+
+ cairo_save (cr);
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ cairo_rectangle (cr, 0, 0, width, height);
+ cairo_fill (cr);
+ cairo_restore (cr);
+
+ cairo_save (cr);
+ poppler_page_render (page, cr);
+ cairo_restore (cr);
+
+ cairo_destroy (cr);
+ g_object_unref (page);
+
+ return surface;
+}
+
+static gboolean
+pgd_find_viewer_drawing_area_draw (GtkWidget *area,
+ cairo_t *cr,
+ PgdFindDemo *demo)
+{
+ if (demo->selected_page == -1)
+ return FALSE;
+
+ if (!demo->surface) {
+ demo->surface = pgd_find_render_page (demo);
+ if (!demo->surface)
+ return FALSE;
+ }
+
+ cairo_set_source_surface (cr, demo->surface, 0, 0);
+ cairo_paint (cr);
+
+ if (demo->selected_match.width > 0 && demo->selected_match.height > 0) {
+ cairo_set_source_rgb (cr, 1., 1., 0.);
+ cairo_set_operator (cr, CAIRO_OPERATOR_MULTIPLY);
+ gdk_cairo_rectangle (cr, &demo->selected_match);
+ cairo_fill (cr);
+ }
+
+ return TRUE;
+}
+
+static gboolean
+pgd_find_viewer_redraw (PgdFindDemo *demo)
+{
+ cairo_surface_destroy (demo->surface);
+ demo->surface = NULL;
+
+ gtk_widget_queue_draw (demo->darea);
+
+ return FALSE;
+}
+
+static void
+pgd_find_viewer_queue_redraw (PgdFindDemo *demo)
+{
+ g_idle_add ((GSourceFunc)pgd_find_viewer_redraw, demo);
+}
+
+static GtkTreeModel *
+pgd_find_create_model ()
+{
+ return GTK_TREE_MODEL (gtk_tree_store_new (N_COLUMNS,
+ G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_BOOLEAN, G_TYPE_UINT,
+ G_TYPE_POINTER));
+}
+
static void
pgd_find_button_clicked (GtkButton *button,
PgdFindDemo *demo)
{
- gtk_tree_store_clear (GTK_TREE_STORE (demo->model));
+ GtkTreeModel *model;
+
+ /* Delete the model and create a new one instead of
+ * just clearing it to make sure rectangle are free.
+ * This is a workaround because GtkTreeModel doesn't
+ * support boxed types and we have to store rectangles
+ * as pointers that are freed when the model is deleted.
+ */
+ model = pgd_find_create_model ();
+ gtk_tree_view_set_model (GTK_TREE_VIEW (demo->treeview), model);
+ g_object_unref (model);
+
+ demo->selected_page = -1;
+ pgd_find_viewer_queue_redraw (demo);
+
demo->page_index = 0;
pgd_find_update_progress (demo, demo->page_index);
if (demo->idle_id > 0)
@@ -174,21 +300,63 @@ pgd_find_button_sensitivity_cb (GtkWidget *button,
gtk_widget_set_sensitive (button, text != NULL && text[0] != '\0');
}
+static void
+pgd_find_selection_changed (GtkTreeSelection *treeselection,
+ PgdFindDemo *demo)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ if (gtk_tree_selection_get_selected (treeselection, &model, &iter)) {
+ guint page_index;
+ PopplerRectangle *rect;
+
+ gtk_tree_model_get (model, &iter,
+ PAGE_COLUMN, &page_index,
+ PAGE_RECT, &rect,
+ -1);
+
+ if (rect) {
+ demo->selected_match.x = rect->x1;
+ demo->selected_match.y = rect->y1;
+ demo->selected_match.width = rect->x2 - rect->x1;
+ demo->selected_match.height = rect->y2 - rect->y1;
+ } else {
+ demo->selected_match.width = 0;
+ demo->selected_match.height = 0;
+ }
+
+ if (page_index != demo->selected_page) {
+ demo->selected_page = page_index;
+ pgd_find_viewer_queue_redraw (demo);
+ } else {
+ gtk_widget_queue_draw (demo->darea);
+ }
+ }
+}
+
GtkWidget *
pgd_find_create_widget (PopplerDocument *document)
{
- PgdFindDemo *demo;
- GtkWidget *vbox, *hbox;
- GtkWidget *button;
- GtkWidget *swindow;
- GtkWidget *treeview;
- GtkCellRenderer *renderer;
+ PgdFindDemo *demo;
+ GtkWidget *vbox, *hbox;
+ GtkWidget *button;
+ GtkWidget *swindow;
+ GtkTreeModel *model;
+ GtkWidget *treeview;
+ GtkCellRenderer *renderer;
+ GtkWidget *hpaned;
+ GtkTreeSelection *selection;
demo = g_new0 (PgdFindDemo, 1);
demo->doc = g_object_ref (document);
demo->n_pages = poppler_document_get_n_pages (document);
+ demo->selected_page = -1;
+
+ hpaned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
+ gtk_paned_set_position (GTK_PANED (hpaned), 300);
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
@@ -222,17 +390,17 @@ pgd_find_create_widget (PopplerDocument *document)
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
- demo->model = GTK_TREE_MODEL (
- gtk_tree_store_new (N_COLUMNS,
- G_TYPE_STRING,
- G_TYPE_STRING, G_TYPE_STRING,
- G_TYPE_STRING, G_TYPE_STRING,
- G_TYPE_BOOLEAN));
- treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (demo->model));
+ model = pgd_find_create_model ();
+ treeview = gtk_tree_view_new_with_model (model);
+ g_object_unref (model);
+ demo->treeview = treeview;
gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (treeview), TRUE);
- gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)),
- GTK_SELECTION_NONE);
-
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+ g_signal_connect (selection, "changed",
+ G_CALLBACK (pgd_find_selection_changed),
+ demo);
+
renderer = gtk_cell_renderer_text_new ();
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview),
TITLE_COLUMN, "Matches",
@@ -271,8 +439,23 @@ pgd_find_create_widget (PopplerDocument *document)
gtk_container_add (GTK_CONTAINER (swindow), treeview);
gtk_widget_show (treeview);
- gtk_box_pack_start (GTK_BOX (vbox), swindow, TRUE, TRUE, 0);
- gtk_widget_show (swindow);
+ gtk_paned_add1 (GTK_PANED (hpaned), swindow);
+ gtk_widget_show (swindow);
+
+ demo->darea = gtk_drawing_area_new ();
+ g_signal_connect (demo->darea, "draw",
+ G_CALLBACK (pgd_find_viewer_drawing_area_draw),
+ demo);
+
+ swindow = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (swindow), demo->darea);
+ gtk_widget_show (demo->darea);
+
+ gtk_paned_add2 (GTK_PANED (hpaned), swindow);
+ gtk_widget_show (swindow);
+
+ gtk_box_pack_start (GTK_BOX (vbox), hpaned, TRUE, TRUE, 0);
+ gtk_widget_show (hpaned);
g_object_weak_ref (G_OBJECT (vbox),
(GWeakNotify)pgd_find_free,
commit ed0c761c2190a3c1959a60ae9b7961f58a43c939
Author: Thomas Schenker <mail.thomas.schenker at googlemail.com>
Date: Sat Jun 2 11:54:21 2012 +0200
glib: Add poppler_page_find_text_with_options
To be able to search text with options like case sensitive, search
backwards and whole words only.
https://bugs.freedesktop.org/show_bug.cgi?id=2951
diff --git a/glib/poppler-page.cc b/glib/poppler-page.cc
index 90f9a62..8113e9c 100644
--- a/glib/poppler-page.cc
+++ b/glib/poppler-page.cc
@@ -850,18 +850,23 @@ poppler_page_get_text (PopplerPage *page)
}
/**
- * poppler_page_find_text:
+ * poppler_page_find_text_with_options:
* @page: a #PopplerPage
* @text: the text to search for (UTF-8 encoded)
- *
- * A #GList of rectangles for each occurance of the text on the page.
+ * @options: find options
+ *
+ * Finds @text in @page with the given #PopplerFindFlags options and
+ * returns a #GList of rectangles for each occurance of the text on the page.
* The coordinates are in PDF points.
- *
+ *
* Return value: (element-type PopplerRectangle) (transfer full): a #GList of #PopplerRectangle,
+ *
+ * Since: 0.22
**/
GList *
-poppler_page_find_text (PopplerPage *page,
- const char *text)
+poppler_page_find_text_with_options (PopplerPage *page,
+ const char *text,
+ PopplerFindFlags options)
{
PopplerRectangle *match;
GList *matches;
@@ -870,6 +875,7 @@ poppler_page_find_text (PopplerPage *page,
glong ucs4_len;
double height;
TextPage *text_dev;
+ gboolean backwards;
g_return_val_if_fail (POPPLER_IS_PAGE (page), NULL);
g_return_val_if_fail (text != NULL, NULL);
@@ -878,17 +884,19 @@ poppler_page_find_text (PopplerPage *page,
ucs4 = g_utf8_to_ucs4_fast (text, -1, &ucs4_len);
poppler_page_get_size (page, NULL, &height);
-
+
+ backwards = options & POPPLER_FIND_BACKWARDS;
matches = NULL;
xMin = 0;
- yMin = 0;
+ yMin = backwards ? height : 0;
while (text_dev->findText (ucs4, ucs4_len,
- gFalse, gTrue, // startAtTop, stopAtBottom
- gFalse, gFalse, // startAtLast, stopAtLast
- gFalse, gFalse, // caseSensitive, backwards
- gFalse, // wholeWord
- &xMin, &yMin, &xMax, &yMax))
+ gFalse, gTrue, // startAtTop, stopAtBottom
+ gTrue, gFalse, // startAtLast, stopAtLast
+ options & POPPLER_FIND_CASE_SENSITIVE,
+ backwards,
+ options & POPPLER_FIND_WHOLE_WORDS_ONLY,
+ &xMin, &yMin, &xMax, &yMax))
{
match = poppler_rectangle_new ();
match->x1 = xMin;
@@ -903,6 +911,24 @@ poppler_page_find_text (PopplerPage *page,
return g_list_reverse (matches);
}
+/**
+ * poppler_page_find_text:
+ * @page: a #PopplerPage
+ * @text: the text to search for (UTF-8 encoded)
+ *
+ * Finds @text in @page with the default options (%POPPLER_FIND_DEFAULT) and
+ * returns a #GList of rectangles for each occurance of the text on the page.
+ * The coordinates are in PDF points.
+ *
+ * Return value: (element-type PopplerRectangle) (transfer full): a #GList of #PopplerRectangle,
+ **/
+GList *
+poppler_page_find_text (PopplerPage *page,
+ const char *text)
+{
+ return poppler_page_find_text_with_options (page, text, POPPLER_FIND_DEFAULT);
+}
+
static CairoImageOutputDev *
poppler_page_get_image_output_dev (PopplerPage *page,
GBool (*imgDrawDeviceCbk)(int img_id, void *data),
diff --git a/glib/poppler-page.h b/glib/poppler-page.h
index 6064ac5..c081b8c 100644
--- a/glib/poppler-page.h
+++ b/glib/poppler-page.h
@@ -60,6 +60,9 @@ PopplerPageTransition *poppler_page_get_transition (PopplerPage *pa
gboolean poppler_page_get_thumbnail_size (PopplerPage *page,
int *width,
int *height);
+GList *poppler_page_find_text_with_options (PopplerPage *page,
+ const char *text,
+ PopplerFindFlags options);
GList *poppler_page_find_text (PopplerPage *page,
const char *text);
void poppler_page_render_to_ps (PopplerPage *page,
diff --git a/glib/poppler.h b/glib/poppler.h
index 6c2eefd..2d190f3 100644
--- a/glib/poppler.h
+++ b/glib/poppler.h
@@ -153,6 +153,24 @@ typedef enum /*< flags >*/
POPPLER_PRINT_ALL = POPPLER_PRINT_MARKUP_ANNOTS
} PopplerPrintFlags;
+/**
+ * PopplerFindFlags:
+ * @POPPLER_FIND_CASE_SENSITIVE: do case sensitive search
+ * @POPPLER_FIND_BACKWARDS: search backwards
+ * @POPPLER_FIND_WHOLE_WORDS_ONLY: search only whole words
+ *
+ * Flags using while searching text in a page
+ *
+ * Since: 0.22
+ */
+typedef enum /*< flags >*/
+{
+ POPPLER_FIND_DEFAULT = 0,
+ POPPLER_FIND_CASE_SENSITIVE = 1 << 0,
+ POPPLER_FIND_BACKWARDS = 1 << 1,
+ POPPLER_FIND_WHOLE_WORDS_ONLY = 1 << 2
+} PopplerFindFlags;
+
typedef struct _PopplerDocument PopplerDocument;
typedef struct _PopplerIndexIter PopplerIndexIter;
typedef struct _PopplerFontsIter PopplerFontsIter;
diff --git a/glib/reference/poppler-sections.txt b/glib/reference/poppler-sections.txt
index 76abf4c..6fb14bc 100644
--- a/glib/reference/poppler-sections.txt
+++ b/glib/reference/poppler-sections.txt
@@ -33,6 +33,7 @@ poppler_page_get_selection_region
poppler_page_selection_region_free
poppler_page_get_selected_text
poppler_page_find_text
+poppler_page_find_text_with_options
poppler_page_get_text
poppler_page_get_text_layout
poppler_page_get_text_attributes
@@ -338,6 +339,7 @@ PopplerOrientation
PopplerBackend
PopplerColor
PopplerPrintFlags
+PopplerFindFlags
poppler_get_backend
poppler_get_version
poppler_date_parse
commit 126b55c9a44ccb0dba55e758843e9ee4aa43ee2b
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date: Sat Jun 2 17:19:30 2012 +0200
Implement whole words only option to search text
It seems we missed it in the xpdf303 merge.
diff --git a/poppler/TextOutputDev.cc b/poppler/TextOutputDev.cc
index e8d993b..9af7532 100644
--- a/poppler/TextOutputDev.cc
+++ b/poppler/TextOutputDev.cc
@@ -3653,76 +3653,80 @@ GBool TextPage::findText(Unicode *s, int len,
j = backward ? m - len : 0;
p = txt + j;
while (backward ? j >= 0 : j <= m - len) {
+ if (!wholeWord ||
+ ((j == 0 || !unicodeTypeAlphaNum(txt[j - 1])) &&
+ (j + len == m || !unicodeTypeAlphaNum(txt[j + len])))) {
+
+ // compare the strings
+ for (k = 0; k < len; ++k) {
+ if (p[k] != s2[k]) {
+ break;
+ }
+ }
- // compare the strings
- for (k = 0; k < len; ++k) {
- if (p[k] != s2[k]) {
- break;
- }
- }
-
- // found it
- if (k == len) {
- // where s2 matches a subsequence of a compatibility equivalence
- // decomposition, highlight the entire glyph, since we don't know
- // the internal layout of subglyph components
- int normStart = line->normalized_idx[j];
- int normAfterEnd = line->normalized_idx[j + len - 1] + 1;
- switch (line->rot) {
- case 0:
- xMin1 = line->edge[normStart];
- xMax1 = line->edge[normAfterEnd];
- yMin1 = line->yMin;
- yMax1 = line->yMax;
- break;
- case 1:
- xMin1 = line->xMin;
- xMax1 = line->xMax;
- yMin1 = line->edge[normStart];
- yMax1 = line->edge[normAfterEnd];
- break;
- case 2:
- xMin1 = line->edge[normAfterEnd];
- xMax1 = line->edge[normStart];
- yMin1 = line->yMin;
- yMax1 = line->yMax;
- break;
- case 3:
- xMin1 = line->xMin;
- xMax1 = line->xMax;
- yMin1 = line->edge[normAfterEnd];
- yMax1 = line->edge[normStart];
- break;
- }
- if (backward) {
- if ((startAtTop ||
- yMin1 < yStart || (yMin1 == yStart && xMin1 < xStart)) &&
- (stopAtBottom ||
- yMin1 > yStop || (yMin1 == yStop && xMin1 > xStop))) {
- if (!found ||
- yMin1 > yMin0 || (yMin1 == yMin0 && xMin1 > xMin0)) {
- xMin0 = xMin1;
- xMax0 = xMax1;
- yMin0 = yMin1;
- yMax0 = yMax1;
- found = gTrue;
- }
- }
- } else {
- if ((startAtTop ||
- yMin1 > yStart || (yMin1 == yStart && xMin1 > xStart)) &&
- (stopAtBottom ||
- yMin1 < yStop || (yMin1 == yStop && xMin1 < xStop))) {
- if (!found ||
- yMin1 < yMin0 || (yMin1 == yMin0 && xMin1 < xMin0)) {
- xMin0 = xMin1;
- xMax0 = xMax1;
- yMin0 = yMin1;
- yMax0 = yMax1;
- found = gTrue;
- }
- }
- }
+ // found it
+ if (k == len) {
+ // where s2 matches a subsequence of a compatibility equivalence
+ // decomposition, highlight the entire glyph, since we don't know
+ // the internal layout of subglyph components
+ int normStart = line->normalized_idx[j];
+ int normAfterEnd = line->normalized_idx[j + len - 1] + 1;
+ switch (line->rot) {
+ case 0:
+ xMin1 = line->edge[normStart];
+ xMax1 = line->edge[normAfterEnd];
+ yMin1 = line->yMin;
+ yMax1 = line->yMax;
+ break;
+ case 1:
+ xMin1 = line->xMin;
+ xMax1 = line->xMax;
+ yMin1 = line->edge[normStart];
+ yMax1 = line->edge[normAfterEnd];
+ break;
+ case 2:
+ xMin1 = line->edge[normAfterEnd];
+ xMax1 = line->edge[normStart];
+ yMin1 = line->yMin;
+ yMax1 = line->yMax;
+ break;
+ case 3:
+ xMin1 = line->xMin;
+ xMax1 = line->xMax;
+ yMin1 = line->edge[normAfterEnd];
+ yMax1 = line->edge[normStart];
+ break;
+ }
+ if (backward) {
+ if ((startAtTop ||
+ yMin1 < yStart || (yMin1 == yStart && xMin1 < xStart)) &&
+ (stopAtBottom ||
+ yMin1 > yStop || (yMin1 == yStop && xMin1 > xStop))) {
+ if (!found ||
+ yMin1 > yMin0 || (yMin1 == yMin0 && xMin1 > xMin0)) {
+ xMin0 = xMin1;
+ xMax0 = xMax1;
+ yMin0 = yMin1;
+ yMax0 = yMax1;
+ found = gTrue;
+ }
+ }
+ } else {
+ if ((startAtTop ||
+ yMin1 > yStart || (yMin1 == yStart && xMin1 > xStart)) &&
+ (stopAtBottom ||
+ yMin1 < yStop || (yMin1 == yStop && xMin1 < xStop))) {
+ if (!found ||
+ yMin1 < yMin0 || (yMin1 == yMin0 && xMin1 < xMin0)) {
+ xMin0 = xMin1;
+ xMax0 = xMax1;
+ yMin0 = yMin1;
+ yMax0 = yMax1;
+ found = gTrue;
+ }
+ }
+ }
+ }
}
if (backward) {
--j;
@@ -3733,7 +3737,7 @@ GBool TextPage::findText(Unicode *s, int len,
}
}
}
- }
+ }
gfree(s2);
if (!caseSensitive) {
More information about the poppler
mailing list