glib/demo/annots.c | 22 --- glib/demo/text.c | 103 +++++++++++++++++- glib/demo/utils.c | 27 ++++ glib/demo/utils.h | 1 glib/poppler-page.cc | 202 ++++++++++++++++++++++++++++++++++++ glib/poppler-page.h | 33 +++++ glib/poppler.h | 1 glib/reference/poppler-sections.txt | 7 + poppler/TextOutputDev.cc | 4 poppler/TextOutputDev.h | 1 10 files changed, 374 insertions(+), 27 deletions(-)
New commits: commit eb740dac838d2a1e32899327ca6d25c3dca641df Author: Carlos Garcia Campos <[email protected]> Date: Mon Aug 22 13:41:56 2011 +0200 glib-demo: Add text attributes information to text demo diff --git a/glib/demo/text.c b/glib/demo/text.c index 54d140b..3a7b2cd 100644 --- a/glib/demo/text.c +++ b/glib/demo/text.c @@ -19,6 +19,7 @@ #include <string.h> #include "text.h" +#include "utils.h" enum { TEXT_X1_COLUMN, @@ -38,6 +39,13 @@ typedef struct { GtkWidget *treeview; GtkListStore *model; + /* Text attributes */ + GList *text_attrs; + GtkWidget *font_name; + GtkWidget *font_size; + GtkWidget *is_underlined; + GtkWidget *text_color; + gint page; } PgdTextDemo; @@ -57,6 +65,11 @@ pgd_text_free (PgdTextDemo *demo) demo->buffer = NULL; } + if (demo->text_attrs) { + poppler_page_free_text_attributes (demo->text_attrs); + demo->text_attrs = NULL; + } + if (demo->model) { g_object_unref (demo->model); demo->model = NULL; @@ -81,6 +94,9 @@ pgd_text_get_text (GtkWidget *button, return; gtk_list_store_clear (demo->model); + if (demo->text_attrs) + poppler_page_free_text_attributes (demo->text_attrs); + demo->text_attrs = NULL; timer = g_timer_new (); text = poppler_page_get_text (page); @@ -88,7 +104,7 @@ pgd_text_get_text (GtkWidget *button, if (text) { gchar *str; - gdouble text_elapsed; + gdouble text_elapsed, layout_elapsed; text_elapsed = g_timer_elapsed (timer, NULL); @@ -96,8 +112,14 @@ pgd_text_get_text (GtkWidget *button, poppler_page_get_text_layout (page, &recs, &n_recs); g_timer_stop (timer); - str = g_strdup_printf ("<i>got text in %.4f seconds, text layout in %.4f seconds</i>", - text_elapsed, g_timer_elapsed (timer, NULL)); + layout_elapsed = g_timer_elapsed (timer, NULL); + + g_timer_start (timer); + demo->text_attrs = poppler_page_get_text_attributes (page); + g_timer_stop (timer); + + str = g_strdup_printf ("<i>got text in %.4f seconds, text layout in %.4f seconds, text attrs in %.4f seconds</i>", + text_elapsed, layout_elapsed, g_timer_elapsed (timer, NULL)); gtk_label_set_markup (GTK_LABEL (demo->timer_label), str); g_free (str); } else { @@ -146,6 +168,34 @@ pgd_text_get_text (GtkWidget *button, } static void +pgd_text_set_text_attrs_for_offset (PgdTextDemo *demo, + gint offset) +{ + GList *l; + + for (l = demo->text_attrs; l; l = g_list_next (l)) { + PopplerTextAttributes *attrs = (PopplerTextAttributes *)l->data; + + if (offset >= attrs->start_index && offset <= attrs->end_index) { + gchar *str; + GdkPixbuf *pixbuf; + + gtk_label_set_text (GTK_LABEL (demo->font_name), attrs->font_name); + + str = g_strdup_printf ("%.2f", attrs->font_size); + gtk_label_set_text (GTK_LABEL (demo->font_size), str); + g_free (str); + + gtk_label_set_text (GTK_LABEL (demo->is_underlined), attrs->is_underlined ? "Yes" : "No"); + + pixbuf = pgd_pixbuf_new_for_color (&(attrs->color)); + gtk_image_set_from_pixbuf (GTK_IMAGE (demo->text_color), pixbuf); + g_object_unref (pixbuf); + } + } +} + +static void pgd_text_selection_changed (GtkTreeSelection *treeselection, PgdTextDemo *demo) { @@ -164,6 +214,8 @@ pgd_text_selection_changed (GtkTreeSelection *treeselection, end_iter = begin_iter; gtk_text_iter_forward_char (&end_iter); gtk_text_buffer_select_range (demo->buffer, &begin_iter, &end_iter); + + pgd_text_set_text_attrs_for_offset (demo, GPOINTER_TO_INT (offset)); } } @@ -232,15 +284,18 @@ pgd_text_create_widget (PopplerDocument *document) { PgdTextDemo *demo; GtkWidget *label; - GtkWidget *vbox; + GtkWidget *vbox, *vbox2; + GtkWidget *textinfo; GtkWidget *hbox, *page_selector; GtkWidget *button; GtkWidget *swindow, *textview, *treeview; GtkTreeSelection *selection; + GtkWidget *frame, *alignment, *table; GtkWidget *hpaned; GtkCellRenderer *renderer; gchar *str; gint n_pages; + gint row = 0; demo = g_new0 (PgdTextDemo, 1); @@ -249,6 +304,8 @@ pgd_text_create_widget (PopplerDocument *document) n_pages = poppler_document_get_n_pages (document); vbox = gtk_vbox_new (FALSE, 12); + vbox2 = gtk_vbox_new (FALSE, 12); + textinfo = gtk_label_new ("TextInfo"); hbox = gtk_hbox_new (FALSE, 6); @@ -341,8 +398,42 @@ pgd_text_create_widget (PopplerDocument *document) gtk_container_add (GTK_CONTAINER (swindow), treeview); gtk_widget_show (treeview); - gtk_paned_add1 (GTK_PANED (hpaned), swindow); - gtk_widget_show (swindow); + gtk_container_add (GTK_CONTAINER (vbox2), swindow); + gtk_widget_show (swindow); + + /* Text attributes */ + frame = gtk_frame_new (NULL); + gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE); + label = gtk_label_new (NULL); + gtk_label_set_markup (GTK_LABEL (label), "<b>Text Attributes</b>"); + gtk_frame_set_label_widget (GTK_FRAME (frame), label); + gtk_widget_show (label); + + alignment = gtk_alignment_new (0.5, 0.5, 1, 1); + gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 5, 5, 12, 5); + gtk_container_add (GTK_CONTAINER (frame), alignment); + gtk_widget_show (alignment); + + table = gtk_table_new (4, 2, FALSE); + gtk_table_set_col_spacings (GTK_TABLE (table), 6); + gtk_table_set_row_spacings (GTK_TABLE (table), 6); + + demo->font_name = gtk_label_new (NULL); + pgd_table_add_property_with_custom_widget (GTK_TABLE (table), "<b>Font Name:</b>", demo->font_name, &row); + demo->font_size = gtk_label_new (NULL); + pgd_table_add_property_with_custom_widget (GTK_TABLE (table), "<b>Font Size:</b>", demo->font_size, &row); + demo->is_underlined = gtk_label_new (NULL); + pgd_table_add_property_with_custom_widget (GTK_TABLE (table), "<b>Underlined:</b>", demo->is_underlined, &row); + demo->text_color = gtk_image_new (); + pgd_table_add_property_with_custom_widget (GTK_TABLE (table), "<b>Color:</b>", demo->text_color, &row); + + gtk_container_add (GTK_CONTAINER (alignment), table); + gtk_widget_show (table); + + gtk_box_pack_start (GTK_BOX (vbox2), frame, FALSE, FALSE, 12); + gtk_widget_show (frame); + gtk_paned_add1 (GTK_PANED (hpaned), vbox2); + gtk_widget_show (vbox2); swindow = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow), commit cda4aefaa136ae07778de3b1593808a5aaa2db5b Author: Carlos Garcia Campos <[email protected]> Date: Mon Aug 22 13:40:49 2011 +0200 glib-demo: Add pgd_pixbuf_new_for_color() to utils To get a pixbuf for a given poppler color. diff --git a/glib/demo/annots.c b/glib/demo/annots.c index 856fbef..9d99c34 100644 --- a/glib/demo/annots.c +++ b/glib/demo/annots.c @@ -154,27 +154,7 @@ get_annot_color (PopplerAnnot *poppler_annot) PopplerColor *poppler_color; if ((poppler_color = poppler_annot_get_color (poppler_annot))) { - GdkPixbuf *pixbuf; - gint rowstride, num, x; - guchar *pixels; - - pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, - FALSE, 8, - 64, 16); - - rowstride = gdk_pixbuf_get_rowstride (pixbuf); - pixels = gdk_pixbuf_get_pixels (pixbuf); - - num = gdk_pixbuf_get_width (pixbuf) * - gdk_pixbuf_get_height (pixbuf); - - for (x = 0; x < num; x++) { - pixels[0] = poppler_color->red; - pixels[1] = poppler_color->green; - pixels[2] = poppler_color->blue; - pixels += 3; - } - + GdkPixbuf *pixbuf = pgd_pixbuf_new_for_color (poppler_color); g_free (poppler_color); return pixbuf; diff --git a/glib/demo/utils.c b/glib/demo/utils.c index 1e59e10..625596c 100644 --- a/glib/demo/utils.c +++ b/glib/demo/utils.c @@ -583,3 +583,30 @@ pgd_movie_view_set_movie (GtkWidget *movie_view, gtk_container_add (GTK_CONTAINER (alignment), table); gtk_widget_show (table); } + +GdkPixbuf * +pgd_pixbuf_new_for_color (PopplerColor *poppler_color) +{ + GdkPixbuf *pixbuf; + gint num, x; + guchar *pixels; + + if (!poppler_color) + return NULL; + + pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, + FALSE, 8, + 64, 16); + + pixels = gdk_pixbuf_get_pixels (pixbuf); + num = gdk_pixbuf_get_width (pixbuf) * gdk_pixbuf_get_height (pixbuf); + + for (x = 0; x < num; x++) { + pixels[0] = poppler_color->red; + pixels[1] = poppler_color->green; + pixels[2] = poppler_color->blue; + pixels += 3; + } + + return pixbuf; +} diff --git a/glib/demo/utils.h b/glib/demo/utils.h index aafcf83..452f3fa 100644 --- a/glib/demo/utils.h +++ b/glib/demo/utils.h @@ -44,6 +44,7 @@ gchar *pgd_format_date (time_t utime); GtkWidget *pgd_movie_view_new (void); void pgd_movie_view_set_movie (GtkWidget *movie_view, PopplerMovie *movie); +GdkPixbuf *pgd_pixbuf_new_for_color (PopplerColor *poppler_color); G_END_DECLS commit 2a11b2963a548186654722a393db1e19d57828f1 Author: danigm <[email protected]> Date: Mon Aug 22 12:51:50 2011 +0200 glib: Add poppler_page_get_text_attributes() It returns a list of text attributes that apply to a range of text as returned by poppler_page_get_text(). Text attributes are represented by a PopplerTextAttributes struct that contains font name, font size, whether text is undrlined and foreground color for a range of text. Fixes bug #33269. diff --git a/glib/poppler-page.cc b/glib/poppler-page.cc index d1f1bcf..9850d44 100644 --- a/glib/poppler-page.cc +++ b/glib/poppler-page.cc @@ -1479,6 +1479,107 @@ poppler_rectangle_free (PopplerRectangle *rectangle) g_slice_free (PopplerRectangle, rectangle); } +/* PopplerTextAttributes type */ + +POPPLER_DEFINE_BOXED_TYPE (PopplerTextAttributes, poppler_text_attributes, + poppler_text_attributes_copy, + poppler_text_attributes_free) + +/** + * poppler_text_attributes_new: + * + * Creates a new #PopplerTextAttributes + * + * Returns: a new #PopplerTextAttributes, use poppler_text_attributes_free() to free it + * + * Since: 0.18 + */ +PopplerTextAttributes * +poppler_text_attributes_new (void) +{ + return (PopplerTextAttributes *) g_slice_new0 (PopplerTextAttributes); +} + +static gchar * +get_font_name_from_word (TextWord *word) +{ + GooString *font_name = word->getFontName(); + const gchar *name; + gboolean subset; + gint i; + + if (!font_name || font_name->getLength () == 0) + return g_strdup ("Default"); + + // check for a font subset name: capital letters followed by a '+' sign + for (i = 0; i < font_name->getLength (); ++i) { + if (font_name->getChar (i) < 'A' || font_name->getChar (i) > 'Z') { + break; + } + } + subset = i > 0 && i < font_name->getLength () && font_name->getChar (i) == '+'; + name = font_name->getCString (); + if (subset) + name += i + 1; + + return g_strdup (name); +} + +/* + * Allocates a new PopplerTextAttributes with word attributes + */ +static PopplerTextAttributes * +poppler_text_attributes_new_from_word (TextWord *word) +{ + PopplerTextAttributes *attrs = poppler_text_attributes_new (); + gdouble r, g, b; + + attrs->font_name = get_font_name_from_word (word); + attrs->font_size = word->getFontSize(); + attrs->is_underlined = word->isUnderlined(); + word->getColor (&r, &g, &b); + attrs->color.red = (int) (r * 65535. + 0.5); + attrs->color.green = (int)(g * 65535. + 0.5); + attrs->color.blue = (int)(b * 65535. + 0.5); + + return attrs; +} + +/** + * poppler_text_attributes_copy: + * @text_attrs: a #PopplerTextAttributes to copy + * + * Creates a copy of @text_attrs + * + * Returns: a new allocated copy of @text_attrs + * + * Since: 0.18 + */ +PopplerTextAttributes * +poppler_text_attributes_copy (PopplerTextAttributes *text_attrs) +{ + PopplerTextAttributes *attrs; + + attrs = g_slice_dup (PopplerTextAttributes, text_attrs); + attrs->font_name = g_strdup (text_attrs->font_name); + return attrs; +} + +/** + * poppler_text_attributes_free: + * @text_attrs: a #PopplerTextAttributes + * + * Frees the given #PopplerTextAttributes + * + * Since: 0.18 + */ +void +poppler_text_attributes_free (PopplerTextAttributes *text_attrs) +{ + g_free (text_attrs->font_name); + g_slice_free (PopplerTextAttributes, text_attrs); +} + /* PopplerColor type */ POPPLER_DEFINE_BOXED_TYPE (PopplerColor, poppler_color, poppler_color_copy, poppler_color_free) @@ -1904,3 +2005,104 @@ poppler_page_get_text_layout (PopplerPage *page, return TRUE; } + +/** + * poppler_page_free_text_attributes; + * @list: A list of #PopplerTextAttributes<!-- -->s + * + * Frees a list of #PopplerTextAttributes<!-- -->s allocated by + * poppler_page_get_text_attributes(). + * + * Since: 0.18 + **/ +void +poppler_page_free_text_attributes (GList *list) +{ + if (G_UNLIKELY (list == NULL)) + return; + + g_list_foreach (list, (GFunc)poppler_text_attributes_free, NULL); + g_list_free (list); +} + +static gboolean +word_text_attributes_equal (TextWord *a, TextWord *b) +{ + double ar, ag, ab, br, bg, bb; + + if (!a->getFontInfo()->matches (b->getFontInfo())) + return FALSE; + + if (a->getFontSize() != b->getFontSize()) + return FALSE; + + if (a->isUnderlined() != b->isUnderlined()) + return FALSE; + + a->getColor(&ar, &ag, &ab); + b->getColor(&br, &bg, &bb); + return (ar == br && ag == bg && ab == bb); +} + +/** + * poppler_page_get_text_attributes: + * @page: A #PopplerPage + * + * Obtains the attributes of the text as a GList of #PopplerTextAttributes. + * This list must be freed with poppler_page_free_text_attributes() when done. + * + * Each list element is a #PopplerTextAttributes struct where start_index and + * end_index indicates the range of text (as returned by poppler_page_get_text()) + * to which text attributes apply. + * + * Return value: (element-type PopplerTextAttributes) (transfer full): A #GList of #PopplerTextAttributes + * + * Since: 0.18 + **/ +GList * +poppler_page_get_text_attributes (PopplerPage *page) +{ + TextPage *text; + TextWordList *wordlist; + PopplerTextAttributes *attrs = NULL; + PopplerTextAttributes *previous = NULL; + gint i, offset = 0; + GList *attributes = NULL; + + g_return_val_if_fail (POPPLER_IS_PAGE (page), NULL); + + text = poppler_page_get_text_page (page); + wordlist = text->makeWordList (gFalse); + + if (wordlist->getLength () <= 0) + { + delete wordlist; + return NULL; + } + + // Calculating each word attributes + for (i = 0; i < wordlist->getLength (); i++) + { + TextWord *word = wordlist->get (i); + + // each char of the word has the same attributes + if (i > 0 && word_text_attributes_equal (word, wordlist->get (i - 1))) { + attrs = previous; + } else { + attrs = poppler_text_attributes_new_from_word (word); + attrs->start_index = offset; + if (previous) + previous->end_index--; + previous = attrs; + attributes = g_list_prepend (attributes, attrs); + } + offset += word->getLength () + 1; + attrs->end_index = offset; + } + if (attrs) + attrs->end_index--; + + delete wordlist; + + return g_list_reverse(attributes); +} diff --git a/glib/poppler-page.h b/glib/poppler-page.h index 03e22ec..c151cdc 100644 --- a/glib/poppler-page.h +++ b/glib/poppler-page.h @@ -94,6 +94,8 @@ void poppler_page_get_crop_box (PopplerPage *page, gboolean poppler_page_get_text_layout (PopplerPage *page, PopplerRectangle **rectangles, guint *n_rectangles); +GList *poppler_page_get_text_attributes (PopplerPage *page); +void poppler_page_free_text_attributes (GList *list); /* A rectangle on a page, with coordinates in PDF points. */ #define POPPLER_TYPE_RECTANGLE (poppler_rectangle_get_type ()) @@ -144,6 +146,37 @@ PopplerColor *poppler_color_new (void); PopplerColor *poppler_color_copy (PopplerColor *color); void poppler_color_free (PopplerColor *color); +/* Text attributes. */ +#define POPPLER_TYPE_TEXT_ATTRIBUTES (poppler_text_attributes_get_type ()) +/** + * PopplerTextAttributes: + * @font_name: font name + * @font_size: font size + * @is_underlined: if text is underlined + * @color: a #PopplerColor, the foreground color + * @start_index: start position this text attributes apply + * @end_index: end position this text text attributes apply + * + * A #PopplerTextInfo is used to describe text attriutes of a reange of text + * + * Since: 0.18 + */ +struct _PopplerTextAttributes +{ + gchar *font_name; + gdouble font_size; + gboolean is_underlined; + PopplerColor color; + + gint start_index; + gint end_index; +}; + +GType poppler_text_attributes_get_type (void) G_GNUC_CONST; +PopplerTextAttributes *poppler_text_attributes_new (void); +PopplerTextAttributes *poppler_text_attributes_copy (PopplerTextAttributes *text_attrs); +void poppler_text_attributes_free (PopplerTextAttributes *text_attrs); + /* Mapping between areas on the current page and PopplerActions */ #define POPPLER_TYPE_LINK_MAPPING (poppler_link_mapping_get_type ()) diff --git a/glib/poppler.h b/glib/poppler.h index 008f5d8..f139bb1 100644 --- a/glib/poppler.h +++ b/glib/poppler.h @@ -158,6 +158,7 @@ typedef struct _PopplerIndexIter PopplerIndexIter; typedef struct _PopplerFontsIter PopplerFontsIter; typedef struct _PopplerLayersIter PopplerLayersIter; typedef struct _PopplerRectangle PopplerRectangle; +typedef struct _PopplerTextAttributes PopplerTextAttributes; typedef struct _PopplerColor PopplerColor; typedef struct _PopplerLinkMapping PopplerLinkMapping; typedef struct _PopplerPageTransition PopplerPageTransition; diff --git a/glib/reference/poppler-sections.txt b/glib/reference/poppler-sections.txt index 9495052..51bbbb5 100644 --- a/glib/reference/poppler-sections.txt +++ b/glib/reference/poppler-sections.txt @@ -14,6 +14,7 @@ PopplerPageTransitionType PopplerPageTransitionAlignment PopplerPageTransitionDirection PopplerSelectionStyle +PopplerTextAttributes poppler_page_get_index poppler_page_get_label poppler_page_get_size @@ -38,6 +39,8 @@ poppler_page_get_selected_text poppler_page_find_text poppler_page_get_text poppler_page_get_text_layout +poppler_page_get_text_attributes +poppler_page_free_text_attributes poppler_page_get_link_mapping poppler_page_free_link_mapping poppler_page_get_image_mapping @@ -66,6 +69,9 @@ poppler_form_field_mapping_free poppler_annot_mapping_new poppler_annot_mapping_copy poppler_annot_mapping_free +poppler_text_attributes_new +poppler_text_attributes_copy +poppler_text_attributes_free <SUBSECTION Standard> POPPLER_PAGE @@ -93,6 +99,7 @@ poppler_page_transition_alignment_get_type poppler_page_transition_direction_get_type poppler_page_transition_type_get_type poppler_selection_style_get_type +poppler_text_attributes_get_type </SECTION> <SECTION> commit 15f99157cf3900bf20cf619e204ae53085af497d Author: Carlos Garcia Campos <[email protected]> Date: Mon Aug 22 12:43:12 2011 +0200 textoutputdev: Add TextFontInfo::matches() It checks whether two TextFontInfo objects contain the same font. diff --git a/poppler/TextOutputDev.cc b/poppler/TextOutputDev.cc index 6c89510..3d7ba6d 100644 --- a/poppler/TextOutputDev.cc +++ b/poppler/TextOutputDev.cc @@ -226,6 +226,10 @@ GBool TextFontInfo::matches(GfxState *state) { return state->getFont() == gfxFont; } +GBool TextFontInfo::matches(TextFontInfo *fontInfo) { + return gfxFont == fontInfo->gfxFont; +} + //------------------------------------------------------------------------ // TextWord //------------------------------------------------------------------------ diff --git a/poppler/TextOutputDev.h b/poppler/TextOutputDev.h index d647340..63f3670 100644 --- a/poppler/TextOutputDev.h +++ b/poppler/TextOutputDev.h @@ -78,6 +78,7 @@ public: ~TextFontInfo(); GBool matches(GfxState *state); + GBool matches(TextFontInfo *fontInfo); #if TEXTOUT_WORD_LIST // Get the font name (which may be NULL). _______________________________________________ poppler mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/poppler
