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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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) { _______________________________________________ poppler mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/poppler
