From 33a3e862d4dd6a87775cf084c0c0d4fd2f64a81b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Poo-Caama=C3=B1o?= Date: Tue, 29 Oct 2013 00:07:09 -0700 Subject: [PATCH] glib-demo: Add support for PopplerTextAnnotMarkup * The subtypes are: Highlihght, Squiggly, StrikeOut and Underline. * Use ScrolledWindow for annotation properties to make room to show the Quadrilaterals of TextMarkup annotations. * Two implementations to add quadrilatelars: from cairo rectangles and from a list of rectangles. --- glib/demo/annots.c | 258 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 205 insertions(+), 53 deletions(-) diff --git a/glib/demo/annots.c b/glib/demo/annots.c index 10c1c8b..11aca29 100644 --- a/glib/demo/annots.c +++ b/glib/demo/annots.c @@ -38,6 +38,23 @@ enum { SELECTED_N_COLUMNS }; +typedef struct +{ + const guint type; + const gchar *label; +} Annotations; + +static Annotations supported_annots[] = { + { POPPLER_ANNOT_TEXT, "Text" }, + { POPPLER_ANNOT_LINE, "Line" }, + { POPPLER_ANNOT_SQUARE, "Square" }, + { POPPLER_ANNOT_CIRCLE, "Circle" }, + { POPPLER_ANNOT_HIGHLIGHT, "Highlight" }, + { POPPLER_ANNOT_UNDERLINE, "Underline" }, + { POPPLER_ANNOT_SQUIGGLY, "Squiggly" }, + { POPPLER_ANNOT_STRIKE_OUT, "Strike Out" }, +}; + typedef enum { MODE_NORMAL, /* Regular use as pointer in the page */ MODE_ADD, /* To add simple annotations */ @@ -365,6 +382,10 @@ pgd_annots_start_add_annot (GtkWidget *button, case POPPLER_ANNOT_LINE: case POPPLER_ANNOT_SQUARE: case POPPLER_ANNOT_CIRCLE: + case POPPLER_ANNOT_HIGHLIGHT: + case POPPLER_ANNOT_UNDERLINE: + case POPPLER_ANNOT_SQUIGGLY: + case POPPLER_ANNOT_STRIKE_OUT: demo->mode = MODE_DRAWING; pgd_annots_update_cursor (demo, GDK_TCROSS); break; @@ -495,6 +516,40 @@ pgd_annot_view_set_annot_line (PgdAnnotsDemo *demo, } static void +pgd_annot_view_set_annot_text_markup (GtkWidget *table, + PopplerAnnotTextMarkup *annot, + gint *row) +{ + gchar *text = NULL; + gchar *prev_text; + GList *list, *quads_list; + PopplerAnnotQuadrilateral *quad; + gint i; + + quads_list = poppler_annot_text_markup_get_quadrilaterals (annot); + + prev_text = g_strdup (""); + for (list = quads_list, i = 0; list; list = list->next, ++i) { + quad = (PopplerAnnotQuadrilateral *) list->data; + + text = g_strdup_printf ("%s%2d:(%.1f,%.1f) (%.1f,%.1f)\n" + " (%.1f,%.1f) (%.1f,%.1f)\n", + prev_text, i+1, + quad->x1, quad->y1, quad->x2, quad->y2, + quad->x3, quad->y3, quad->x4, quad->y4); + g_free (prev_text); + prev_text = text; + } + + text = g_strchomp (text); + pgd_table_add_property (GTK_GRID (table), "Quadrilaterals:", text, row); + + poppler_annot_text_markup_free_quadrilaterals (quads_list); + g_free (text); +} + + +static void pgd_annot_view_set_annot_free_text (GtkWidget *table, PopplerAnnotFreeText *annot, gint *row) @@ -669,6 +724,12 @@ pgd_annot_view_set_annot (PgdAnnotsDemo *demo, case POPPLER_ANNOT_LINE: pgd_annot_view_set_annot_line (demo, table, annot, &row); break; + case POPPLER_ANNOT_HIGHLIGHT: + case POPPLER_ANNOT_UNDERLINE: + case POPPLER_ANNOT_SQUIGGLY: + case POPPLER_ANNOT_STRIKE_OUT: + pgd_annot_view_set_annot_text_markup (table, POPPLER_ANNOT_TEXT_MARKUP (annot), &row); + break; case POPPLER_ANNOT_FREE_TEXT: pgd_annot_view_set_annot_free_text (table, POPPLER_ANNOT_FREE_TEXT (annot), &row); break; @@ -886,6 +947,18 @@ pgd_annots_add_annotation (PgdAnnotsDemo *demo) case POPPLER_ANNOT_CIRCLE: annot = poppler_annot_geometry_new_circle (demo->doc, &rect); break; + case POPPLER_ANNOT_HIGHLIGHT: + annot = poppler_annot_text_markup_new_highlight (demo->doc, &rect); + break; + case POPPLER_ANNOT_UNDERLINE: + annot = poppler_annot_text_markup_new_underline (demo->doc, &rect); + break; + case POPPLER_ANNOT_SQUIGGLY: + annot = poppler_annot_text_markup_new_squiggly (demo->doc, &rect); + break; + case POPPLER_ANNOT_STRIKE_OUT: + annot = poppler_annot_text_markup_new_strikeout (demo->doc, &rect); + break; default: g_printerr ("Annotation not implemented: %d\n", demo->annot_type); return; @@ -904,6 +977,86 @@ pgd_annots_add_annotation (PgdAnnotsDemo *demo) gtk_tree_path_free (path); } +static void +pgd_annots_update_selected_text (PgdAnnotsDemo *demo) +{ + GList *quads_list = NULL; + PopplerRectangle doc_area; + gdouble width, height; + gboolean cairo = FALSE; + PopplerAnnotQuadrilateral *quad; + + poppler_page_get_size (demo->page, &width, &height); + + doc_area.x1 = demo->start.x; + doc_area.y1 = demo->start.y; + doc_area.x2 = demo->stop.x; + doc_area.y2 = demo->stop.y; + + if (!cairo) { + GList *list, *region; + PopplerRectangle *rect; + + region = poppler_page_get_selection_region (demo->page, 1.0, + POPPLER_SELECTION_GLYPH, + &doc_area); + + for (list = region; list; list = list->next) { + rect = (PopplerRectangle *) list->data; + + quad = poppler_annot_quadrilateral_new (); + quad->x1 = rect->x1; + quad->y1 = height - rect->y1; + quad->x2 = rect->x2; + quad->y2 = height - rect->y1; + quad->x3 = rect->x1; + quad->y3 = height - rect->y2; + quad->x4 = rect->x2; + quad->y4 = height - rect->y2; + + quads_list = g_list_prepend (quads_list, quad); + } + quads_list = g_list_reverse (quads_list); + + poppler_page_selection_region_free (region); + } else { + cairo_region_t *cr_region; + PopplerRectangle rect; + cairo_rectangle_int_t cr_rect; + + cr_region = poppler_page_get_selected_region (demo->page, 1.0, + POPPLER_SELECTION_GLYPH, + &doc_area); + + for (int i=0; i < cairo_region_num_rectangles (cr_region); i++) { + cairo_region_get_rectangle (cr_region, i, &cr_rect); + + rect.x1 = cr_rect.x; + rect.y1 = cr_rect.y; + rect.x2 = cr_rect.x + cr_rect.width; + rect.y2 = cr_rect.y + cr_rect.height; + + quad = poppler_annot_quadrilateral_new (); + quad->x1 = rect.x1; + quad->y1 = height - rect.y1; + quad->x2 = rect.x2; + quad->y2 = height - rect.y1; + quad->x3 = rect.x1; + quad->y3 = height - rect.y2; + quad->x4 = rect.x2; + quad->y4 = height - rect.y2; + + quads_list = g_list_prepend (quads_list, quad); + } + quads_list = g_list_reverse (quads_list); + + cairo_region_destroy (cr_region); + } + + poppler_annot_text_markup_set_quadrilaterals (POPPLER_ANNOT_TEXT_MARKUP (demo->active_annot), quads_list); + poppler_annot_text_markup_free_quadrilaterals (quads_list); +} + /* Render area */ static cairo_surface_t * pgd_annots_render_page (PgdAnnotsDemo *demo) @@ -1013,6 +1166,7 @@ pgd_annots_drawing_area_button_press (GtkWidget *area, break; case MODE_DRAWING: pgd_annots_add_annotation (demo); + break; default: break; } @@ -1025,44 +1179,49 @@ pgd_annots_drawing_area_motion_notify (GtkWidget *area, GdkEventMotion *event, PgdAnnotsDemo *demo) { + PopplerRectangle rect; + gdouble width, height; + if (!demo->page || demo->mode == MODE_NORMAL || demo->mode == MODE_ADD) return FALSE; - if (demo->start.x != -1) { - demo->stop.x = event->x; - demo->stop.y = event->y; + if (demo->start.x == -1) + return TRUE; - if (demo->mode == MODE_DRAWING) { - PopplerRectangle rect; - gdouble width, height; + demo->stop.x = event->x; + demo->stop.y = event->y; - poppler_page_get_size (demo->page, &width, &height); + if (demo->mode == MODE_DRAWING) { + poppler_page_get_size (demo->page, &width, &height); - /* Keep the drawing within the page */ - demo->stop.x = MAX (demo->stop.x, 0); - demo->stop.y = MAX (demo->stop.y, 0); - demo->stop.x = MIN (demo->stop.x, width); - demo->stop.y = MIN (demo->stop.y, height); + /* Keep the drawing within the page */ + demo->stop.x = MAX (demo->stop.x, 0); + demo->stop.y = MAX (demo->stop.y, 0); + demo->stop.x = MIN (demo->stop.x, width); + demo->stop.y = MIN (demo->stop.y, height); - rect.x1 = demo->start.x; - rect.y1 = height - demo->start.y; - rect.x2 = demo->stop.x; - rect.y2 = height - demo->stop.y; + rect.x1 = demo->start.x; + rect.y1 = height - demo->start.y; + rect.x2 = demo->stop.x; + rect.y2 = height - demo->stop.y; - poppler_annot_set_rectangle (demo->active_annot, rect); - - if (demo->annot_type == POPPLER_ANNOT_LINE) { - poppler_annot_line_set_vertices (POPPLER_ANNOT_LINE (demo->active_annot), - rect.x1, rect.y1, - rect.x2, rect.y2); - } - - pgd_annot_view_set_annot (demo, demo->active_annot); - if (demo->annotations_idle == 0) { - demo->annotations_idle = - g_idle_add ((GSourceFunc)pgd_annots_viewer_redraw, - demo); - } + poppler_annot_set_rectangle (demo->active_annot, rect); + + if (demo->annot_type == POPPLER_ANNOT_LINE) { + poppler_annot_line_set_vertices (POPPLER_ANNOT_LINE (demo->active_annot), + rect.x1, rect.y1, + rect.x2, rect.y2); + } + + if (POPPLER_IS_ANNOT_TEXT_MARKUP (demo->active_annot)) { + pgd_annots_update_selected_text (demo); + } + + pgd_annot_view_set_annot (demo, demo->active_annot); + if (demo->annotations_idle == 0) { + demo->annotations_idle = + g_idle_add ((GSourceFunc)pgd_annots_viewer_redraw, + demo); } } @@ -1164,29 +1323,14 @@ pgd_annots_create_widget (PopplerDocument *document) model = gtk_list_store_new(SELECTED_N_COLUMNS, G_TYPE_INT, G_TYPE_STRING); - gtk_list_store_append (model, &iter); - gtk_list_store_set (model, &iter, - SELECTED_TYPE_COLUMN, POPPLER_ANNOT_TEXT, - SELECTED_LABEL_COLUMN, "Text", - -1); - - gtk_list_store_append (model, &iter); - gtk_list_store_set (model, &iter, - SELECTED_TYPE_COLUMN, POPPLER_ANNOT_LINE, - SELECTED_LABEL_COLUMN, "Line", - -1); - gtk_list_store_append (model, &iter); - gtk_list_store_set (model, &iter, - SELECTED_TYPE_COLUMN, POPPLER_ANNOT_SQUARE, - SELECTED_LABEL_COLUMN, "Square", - -1); - - gtk_list_store_append (model, &iter); - gtk_list_store_set (model, &iter, - SELECTED_TYPE_COLUMN, POPPLER_ANNOT_CIRCLE, - SELECTED_LABEL_COLUMN, "Circle", - -1); + for (gint i = 0; i < G_N_ELEMENTS (supported_annots); i++) { + gtk_list_store_append (model, &iter); + gtk_list_store_set (model, &iter, + SELECTED_TYPE_COLUMN, supported_annots[i].type, + SELECTED_LABEL_COLUMN, supported_annots[i].label, + -1); + } demo->type_selector = gtk_combo_box_new_with_model (GTK_TREE_MODEL (model)); g_object_unref (model); @@ -1300,8 +1444,16 @@ pgd_annots_create_widget (PopplerDocument *document) gtk_widget_show (swindow); /* Annotation Properties */ - gtk_box_pack_start (GTK_BOX (vbox2), demo->annot_view, FALSE, FALSE, 6); + swindow = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + gtk_container_add (GTK_CONTAINER (swindow), demo->annot_view); gtk_widget_show (demo->annot_view); + gtk_widget_show (swindow); + + gtk_box_pack_start (GTK_BOX (vbox2), swindow, TRUE, TRUE, 6); + gtk_widget_show (swindow); gtk_paned_add1 (GTK_PANED (hpaned), vbox2); gtk_widget_show (vbox2); -- 1.7.9.5