diff options
author | Carlos Garcia Campos <carlosgc@gnome.org> | 2008-03-12 22:06:53 +0100 |
---|---|---|
committer | Carlos Garcia Campos <carlosgc@gnome.org> | 2008-03-12 22:06:53 +0100 |
commit | f5065016b168e4896e2fe774cd22bbd900849b52 (patch) | |
tree | 96f8713b70255ba1d705556d8f593dcd952f5749 | |
parent | 46d4fab82332e71d0b68c0a8deeac78f2201ed14 (diff) |
Make GDK dependency option for glib bindings
Fixes bug #13719.
-rw-r--r-- | configure.ac | 45 | ||||
-rw-r--r-- | glib/Makefile.am | 7 | ||||
-rw-r--r-- | glib/demo/page.c | 88 | ||||
-rw-r--r-- | glib/demo/render.c | 4 | ||||
-rw-r--r-- | glib/poppler-action.h | 1 | ||||
-rw-r--r-- | glib/poppler-annot.cc | 26 | ||||
-rw-r--r-- | glib/poppler-annot.h | 2 | ||||
-rw-r--r-- | glib/poppler-document.h | 2 | ||||
-rw-r--r-- | glib/poppler-features.h.in | 1 | ||||
-rw-r--r-- | glib/poppler-page.cc | 661 | ||||
-rw-r--r-- | glib/poppler-page.h | 76 | ||||
-rw-r--r-- | glib/poppler.h | 2 | ||||
-rw-r--r-- | glib/test-poppler-glib.cc | 2 |
13 files changed, 593 insertions, 324 deletions
diff --git a/configure.ac b/configure.ac index b871c921..7ce607f5 100644 --- a/configure.ac +++ b/configure.ac @@ -194,15 +194,16 @@ fi AC_SUBST(CAIRO_FEATURE) AC_SUBST(CAIRO_REQ) +GLIB_REQUIRED=2.6 AC_ARG_ENABLE(poppler-glib, AC_HELP_STRING([--disable-poppler-glib], [Don't compile poppler glib wrapper.]), enable_poppler_glib=$enableval, enable_poppler_glib="try") if test x$enable_poppler_glib = xyes; then - PKG_CHECK_MODULES(POPPLER_GLIB, gdk-2.0 >= 2.4.0 glib-2.0 >= 2.6) + PKG_CHECK_MODULES(POPPLER_GLIB, glib-2.0 >= $GLIB_REQUIRED gobject-2.0 >= $GLIB_REQUIRED) elif test x$enable_poppler_glib = xtry; then - PKG_CHECK_MODULES(POPPLER_GLIB, gdk-2.0 >= 2.4.0 glib-2.0 >= 2.6, + PKG_CHECK_MODULES(POPPLER_GLIB, glib-2.0 >= $GLIB_REQUIRED gobject-2.0 >= $GLIB_REQUIRED, [enable_poppler_glib="yes"], [enable_poppler_glib="no"]) fi @@ -213,6 +214,45 @@ AM_CONDITIONAL(BUILD_POPPLER_GLIB, test x$enable_poppler_glib = xyes) GTK_DOC_CHECK([1.0]) +dnl +dnl GDK +dnl +AC_ARG_ENABLE(gdk, + AC_HELP_STRING([--disable-gdk], + [Compile without gdk.]), + enable_gdk=$enableval, + enable_gdk="try") + +if test x$enable_poppler_glib = xyes; then + if test x$enable_gdk = xyes; then + PKG_CHECK_MODULES(GDK, gdk-2.0) + elif test x$enable_gdk = xtry; then + if test x$enable_splash_output = xyes; then + PKG_CHECK_MODULES(GDK, gdk-2.0) + enable_gdk=yes + elif test x$enable_cairo_output = xyes; then + PKG_CHECK_MODULES(GDK, gdk-2.0, + [enable_gdk="yes"], + [enable_gdk="no"]) + fi + elif test x$enable_splash_output = xyes; then + PKG_CHECK_MODULES(GDK, gdk-2.0) + AC_MSG_WARN("GDK is required by the glib wrapper when splash output device is + enabled. If you want to comppile popler without GDK use --disable-splash-output too") + enable_gdk=yes + fi + if test x$enable_gdk = xyes; then + AC_DEFINE(POPPLER_WITH_GDK,[1], [Have GDK]) + GDK_FEATURE="#define POPPLER_WITH_GDK 1" + else + GDK_FEATURE="" + fi +fi +AM_CONDITIONAL(BUILD_WITH_GDK, test x$enable_gdk = xyes) +AC_SUBST(GDK_CFLAGS) +AC_SUBST(GDK_LIBS) +AC_SUBST(GDK_FEATURE) + AC_ARG_ENABLE(poppler-qt, AC_HELP_STRING([--disable-poppler-qt], [Don't compile poppler qt wrapper.]), @@ -355,6 +395,7 @@ echo " abiword output: $enable_abiword_output" echo " qt wrapper: $enable_poppler_qt" echo " qt4 wrapper: $enable_poppler_qt4" echo " glib wrapper: $enable_poppler_glib" +echo " use GDK: $enable_gdk" echo " use gtk-doc: $enable_gtk_doc" echo " use libjpeg: $enable_libjpeg" echo " use zlib: $enable_zlib" diff --git a/glib/Makefile.am b/glib/Makefile.am index f4df44d9..e84e40b8 100644 --- a/glib/Makefile.am +++ b/glib/Makefile.am @@ -16,6 +16,7 @@ INCLUDES = \ -I$(top_srcdir)/poppler \ $(cairo_includes) \ $(POPPLER_GLIB_CFLAGS) \ + $(GDK_CFLAGS) \ $(FREETYPE_CFLAGS) \ $(FONTCONFIG_CFLAGS) \ $(cairo_includes) @@ -88,12 +89,14 @@ libpoppler_glib_la_SOURCES = \ libpoppler_glib_la_LIBADD = \ $(top_builddir)/poppler/libpoppler.la \ $(POPPLER_GLIB_LIBS) \ + $(GDK_LIBS) \ $(FREETYPE_LIBS) \ $(FONTCONFIG_LIBS) \ $(cairo_libs) -libpoppler_glib_la_LDFLAGS = -version-info 2:0:0 +libpoppler_glib_la_LDFLAGS = -version-info 3:0:0 +if BUILD_WITH_GDK noinst_PROGRAMS = test-poppler-glib test_poppler_glib_SOURCES = \ @@ -103,8 +106,10 @@ test_poppler_glib_LDADD = \ $(top_builddir)/poppler/libpoppler.la \ libpoppler-glib.la \ $(POPPLER_GLIB_LIBS) \ + $(GDK_LIBS) \ $(FREETYPE_LIBS) \ $(cairo_libs) +endif BUILT_SOURCES = \ poppler-enums.c \ diff --git a/glib/demo/page.c b/glib/demo/page.c index 10445fd1..c029b273 100644 --- a/glib/demo/page.c +++ b/glib/demo/page.c @@ -16,6 +16,8 @@ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ +#include "config.h" + #include <gtk/gtk.h> #include "page.h" @@ -48,11 +50,86 @@ pgd_page_free (PgdPageDemo *demo) g_free (demo); } +#ifndef POPPLER_WITH_GDK +static void +image_set_from_surface (GtkImage *gtkimage, + cairo_surface_t *surface) +{ + GdkPixbuf *pixbuf; + cairo_surface_t *image; + cairo_t *cr; + gboolean has_alpha; + gint width, height; + cairo_format_t surface_format; + gint pixbuf_n_channels; + gint pixbuf_rowstride; + guchar *pixbuf_pixels; + gint x, y; + + width = cairo_image_surface_get_width (surface); + height = cairo_image_surface_get_height (surface); + + surface_format = cairo_image_surface_get_format (surface); + has_alpha = (surface_format == CAIRO_FORMAT_ARGB32); + + pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, + TRUE, 8, + width, height); + pixbuf_n_channels = gdk_pixbuf_get_n_channels (pixbuf); + pixbuf_rowstride = gdk_pixbuf_get_rowstride (pixbuf); + pixbuf_pixels = gdk_pixbuf_get_pixels (pixbuf); + + image = cairo_image_surface_create_for_data (pixbuf_pixels, + surface_format, + width, height, + pixbuf_rowstride); + cr = cairo_create (image); + cairo_set_source_surface (cr, surface, 0, 0); + + if (has_alpha) + cairo_mask_surface (cr, surface, 0, 0); + else + cairo_paint (cr); + + cairo_destroy (cr); + cairo_surface_destroy (image); + + for (y = 0; y < height; y++) { + guchar *p = pixbuf_pixels + y * pixbuf_rowstride; + + for (x = 0; x < width; x++) { + guchar tmp; + +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + tmp = p[0]; + p[0] = p[2]; + p[2] = tmp; + p[3] = (has_alpha) ? p[3] : 0xff; +#else + tmp = p[0]; + p[0] = (has_alpha) ? p[3] : 0xff; + p[3] = p[2]; + p[2] = p[1]; + p[1] = tmp; +#endif + p += pixbuf_n_channels; + } + } + + gtk_image_set_from_pixbuf (gtkimage, pixbuf); + g_object_unref (pixbuf); +} +#endif /* !POPPLER_WITH_GDK */ + static void pgd_page_set_page (PgdPageDemo *demo, PopplerPage *page) { +#ifdef POPPLER_WITH_GDK GdkPixbuf *thumbnail; +#else + cairo_surface_t *thumbnail; +#endif gchar *str; str = page ? g_strdup_printf ("%d", poppler_page_get_index (page)) : NULL; @@ -82,7 +159,11 @@ pgd_page_set_page (PgdPageDemo *demo, gtk_label_set_text (GTK_LABEL (demo->duration), str); g_free (str); +#ifdef POPPLER_WITH_GDK + thumbnail = page ? poppler_page_get_thumbnail_pixbuf (page) : NULL; +#else thumbnail = page ? poppler_page_get_thumbnail (page) : NULL; +#endif if (thumbnail) { gint width, height; @@ -90,9 +171,14 @@ pgd_page_set_page (PgdPageDemo *demo, str = g_strdup_printf ("%d x %d", width, height); gtk_label_set_text (GTK_LABEL (demo->thumbnail_size), str); g_free (str); - + +#ifdef POPPLER_WITH_GDK gtk_image_set_from_pixbuf (GTK_IMAGE (demo->thumbnail), thumbnail); g_object_unref (thumbnail); +#else + image_set_from_surface (GTK_IMAGE (demo->thumbnail), thumbnail); + cairo_surface_destroy (thumbnail); +#endif } else { str = g_strdup ("<i>No thumbnail found</i>"); gtk_label_set_markup (GTK_LABEL (demo->thumbnail_size), str); diff --git a/glib/demo/render.c b/glib/demo/render.c index 55447481..15305130 100644 --- a/glib/demo/render.c +++ b/glib/demo/render.c @@ -205,6 +205,7 @@ pgd_render_start (GtkButton *button, cairo_destroy (cr); } else if (demo->mode == PGD_RENDER_PIXBUF) { #endif +#ifdef POPPLER_WITH_GDK timer = g_timer_new (); demo->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, width, height); @@ -217,6 +218,7 @@ pgd_render_start (GtkButton *button, demo->rotate, demo->pixbuf); g_timer_stop (timer); +#endif /* POPPLER_WITH_GDK */ #if defined (HAVE_CAIRO) } else { g_assert_not_reached (); @@ -391,7 +393,9 @@ pgd_render_properties_selector_create (PgdRenderDemo *demo) #if defined (HAVE_CAIRO) gtk_combo_box_append_text (GTK_COMBO_BOX (mode_selector), "cairo"); #endif +#ifdef POPPLER_WITH_GDK gtk_combo_box_append_text (GTK_COMBO_BOX (mode_selector), "pixbuf"); +#endif gtk_combo_box_set_active (GTK_COMBO_BOX (mode_selector), 0); g_signal_connect (G_OBJECT (mode_selector), "changed", G_CALLBACK (pgd_render_mode_selector_changed), diff --git a/glib/poppler-action.h b/glib/poppler-action.h index 45e92b15..87f216c1 100644 --- a/glib/poppler-action.h +++ b/glib/poppler-action.h @@ -20,7 +20,6 @@ #define __POPPLER_ACTION_H__ #include <glib-object.h> -#include <gdk-pixbuf/gdk-pixbuf.h> #include "poppler.h" G_BEGIN_DECLS diff --git a/glib/poppler-annot.cc b/glib/poppler-annot.cc index 8d7ab490..da900a32 100644 --- a/glib/poppler-annot.cc +++ b/glib/poppler-annot.cc @@ -316,10 +316,10 @@ poppler_annot_get_flags (PopplerAnnot *poppler_annot) * * Retrieves the color of @poppler_annot. * - * Return value: a new allocated #GdkColor with the color values of + * Return value: a new allocated #PopplerColor with the color values of * @poppler_annot. It must be freed with g_free() when done. **/ -GdkColor * +PopplerColor * poppler_annot_get_color (PopplerAnnot *poppler_annot) { AnnotColor *color; @@ -327,23 +327,23 @@ poppler_annot_get_color (PopplerAnnot *poppler_annot) g_return_val_if_fail (POPPLER_IS_ANNOT (poppler_annot), NULL); if ((color = poppler_annot->annot->getColor ())) { - GdkColor *gdk_color; + PopplerColor *poppler_color; double *values = color->getValues (); switch (color->getSpace ()) { case AnnotColor::colorGray: - gdk_color = g_new0 (GdkColor, 1); - gdk_color->red = (guint16) values[0]; - gdk_color->green = (guint16) values[0]; - gdk_color->blue = (guint16) values[0]; - return gdk_color; + poppler_color = g_new (PopplerColor, 1); + poppler_color->red = (guint16) values[0]; + poppler_color->green = (guint16) values[0]; + poppler_color->blue = (guint16) values[0]; + return poppler_color; case AnnotColor::colorRGB: - gdk_color = g_new0 (GdkColor, 1); - gdk_color->red = (guint16) values[0]; - gdk_color->green = (guint16) values[1]; - gdk_color->blue = (guint16) values[2]; - return gdk_color; + poppler_color = g_new (PopplerColor, 1); + poppler_color->red = (guint16) values[0]; + poppler_color->green = (guint16) values[1]; + poppler_color->blue = (guint16) values[2]; + return poppler_color; case AnnotColor::colorTransparent: case AnnotColor::colorCMYK: default: diff --git a/glib/poppler-annot.h b/glib/poppler-annot.h index 006255e7..706e3e16 100644 --- a/glib/poppler-annot.h +++ b/glib/poppler-annot.h @@ -147,7 +147,7 @@ gchar *poppler_annot_get_contents ( gchar *poppler_annot_get_name (PopplerAnnot *poppler_annot); gchar *poppler_annot_get_modified (PopplerAnnot *poppler_annot); PopplerAnnotFlag poppler_annot_get_flags (PopplerAnnot *poppler_annot); -GdkColor *poppler_annot_get_color (PopplerAnnot *poppler_annot); +PopplerColor *poppler_annot_get_color (PopplerAnnot *poppler_annot); /* PopplerAnnotMarkup */ GType poppler_annot_markup_get_type (void) G_GNUC_CONST; diff --git a/glib/poppler-document.h b/glib/poppler-document.h index 1ff140e3..45854258 100644 --- a/glib/poppler-document.h +++ b/glib/poppler-document.h @@ -20,8 +20,6 @@ #define __POPPLER_DOCUMENT_H__ #include <glib-object.h> -#include <gdk-pixbuf/gdk-pixbuf.h> - #include "poppler.h" G_BEGIN_DECLS diff --git a/glib/poppler-features.h.in b/glib/poppler-features.h.in index 76ff4237..7b72569c 100644 --- a/glib/poppler-features.h.in +++ b/glib/poppler-features.h.in @@ -20,5 +20,6 @@ #define __POPPLER_FEATURES_H__ @CAIRO_FEATURE@ +@GDK_FEATURE@ #endif /* __POPPLER_FEATURES_H__ */ diff --git a/glib/poppler-page.cc b/glib/poppler-page.cc index 0f39133b..5cbc5a89 100644 --- a/glib/poppler-page.cc +++ b/glib/poppler-page.cc @@ -234,8 +234,34 @@ poppler_page_get_transition (PopplerPage *page) return transition; } +static TextOutputDev * +poppler_page_get_text_output_dev (PopplerPage *page) +{ + if (page->text_dev == NULL) { + page->text_dev = new TextOutputDev (NULL, gTrue, gFalse, gFalse); + + if (page->gfx) + delete page->gfx; + page->gfx = page->page->createGfx(page->text_dev, + 72.0, 72.0, 0, + gFalse, /* useMediaBox */ + gTrue, /* Crop */ + -1, -1, -1, -1, + gFalse, /* printing */ + page->document->doc->getCatalog (), + NULL, NULL, NULL, NULL); + + page->page->display(page->gfx); + + page->text_dev->endPage(); + } + + return page->text_dev; +} + #if defined (HAVE_CAIRO) +#ifdef POPPLER_WITH_GDK typedef struct { unsigned char *cairo_data; cairo_surface_t *surface; @@ -342,6 +368,17 @@ poppler_page_copy_to_pixbuf (PopplerPage *page, gfree (output_dev_data->cairo_data); } +static void +poppler_page_set_selection_alpha (PopplerPage *page, + double scale, + GdkPixbuf *pixbuf, + PopplerSelectionStyle style, + PopplerRectangle *selection) +{ + /* Cairo doesn't need this, since cairo generates an alpha channel. */ +} +#endif /* POPPLER_WITH_GDK */ + #elif defined (HAVE_SPLASH) typedef struct { @@ -406,7 +443,60 @@ poppler_page_copy_to_pixbuf(PopplerPage *page, delete [] pixel; } -#endif +static void +poppler_page_set_selection_alpha (PopplerPage *page, + double scale, + GdkPixbuf *pixbuf, + PopplerSelectionStyle style, + PopplerRectangle *selection) +{ + GList *region, *l; + gint x, y, width, height; + int pixbuf_rowstride, pixbuf_n_channels; + guchar *pixbuf_data, *dst; + + pixbuf_data = gdk_pixbuf_get_pixels (pixbuf); + pixbuf_rowstride = gdk_pixbuf_get_rowstride (pixbuf); + pixbuf_n_channels = gdk_pixbuf_get_n_channels (pixbuf); + width = gdk_pixbuf_get_width (pixbuf); + height = gdk_pixbuf_get_height (pixbuf); + + if (pixbuf_n_channels != 4) + return; + + for (y = 0; y < height; y++) { + dst = pixbuf_data + y * pixbuf_rowstride; + for (x = 0; x < width; x++) { + dst[3] = 0x00; + dst += pixbuf_n_channels; + } + } + + region = poppler_page_get_selection_region (page, scale, style, selection); + + for (l = region; l; l = g_list_next (l)) { + PopplerRectangle *rectangle = (PopplerRectangle *)l->data; + GdkRectangle rect; + + rect.x = (gint)rectangle->x1; + rect.y = (gint)rectangle->y1; + rect.width = (gint) (rectangle->x2 - rectangle->x1); + rect.height = (gint) (rectangle->y2 - rectangle->y1); + + for (y = 0; y < rect.height; y++) { + dst = pixbuf_data + (rect.y + y) * pixbuf_rowstride + + rect.x * pixbuf_n_channels; + for (x = 0; x < rect.width; x++) { + dst[3] = 0xff; + dst += pixbuf_n_channels; + } + } + } + + poppler_page_selection_region_free (region); +} + +#endif /* HAVE_SPLASH */ static GBool poppler_print_annot_cb (Annot *annot, void *user_data) @@ -480,8 +570,165 @@ poppler_page_render_for_printing (PopplerPage *page, _poppler_page_render (page, cairo, gTrue); } +static cairo_surface_t * +create_surface_from_thumbnail_data (guchar *data, + gint width, + gint height, + gint rowstride) +{ + guchar *cairo_pixels; + cairo_surface_t *surface; + static cairo_user_data_key_t key; + int j; + + cairo_pixels = (guchar *)g_malloc (4 * width * height); + surface = cairo_image_surface_create_for_data ((unsigned char *)cairo_pixels, + CAIRO_FORMAT_RGB24, + width, height, 4 * width); + cairo_surface_set_user_data (surface, &key, + cairo_pixels, (cairo_destroy_func_t)g_free); + + for (j = height; j; j--) { + guchar *p = data; + guchar *q = cairo_pixels; + guchar *end = p + 3 * width; + + while (p < end) { +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + q[0] = p[2]; + q[1] = p[1]; + q[2] = p[0]; +#else + q[1] = p[0]; + q[2] = p[1]; + q[3] = p[2]; +#endif + p += 3; + q += 4; + } + + data += rowstride; + cairo_pixels += 4 * width; + } + + return surface; +} + + +/** + * poppler_page_get_thumbnail: + * @page: the #PopperPage to get the thumbnail for + * + * Get the embedded thumbnail for the specified page. If the document + * doesn't have an embedded thumbnail for the page, this function + * returns %NULL. + * + * Return value: the tumbnail as a cairo_surface_t or %NULL if the document + * doesn't have a thumbnail for this page. + **/ +cairo_surface_t * +poppler_page_get_thumbnail (PopplerPage *page) +{ + unsigned char *data; + int width, height, rowstride; + cairo_surface_t *surface; + + g_return_val_if_fail (POPPLER_IS_PAGE (page), FALSE); + + if (!page->page->loadThumb (&data, &width, &height, &rowstride)) + return NULL; + + surface = create_surface_from_thumbnail_data (data, width, height, rowstride); + gfree (data); + + return surface; +} + +/** + * poppler_page_render_selection: + * @page: the #PopplerPage for which to render selection + * @cairo: cairo context to render to + * @selection: start and end point of selection as a rectangle + * @old_selection: previous selection + * @style: a #PopplerSelectionStyle + * @glyph_color: color to use for drawing glyphs + * @background_color: color to use for the selection background + * + * Render the selection specified by @selection for @page to + * the given cairo context. The selection will be rendered, using + * @glyph_color for the glyphs and @background_color for the selection + * background. + * + * If non-NULL, @old_selection specifies the selection that is already + * rendered to @cairo, in which case this function will (some day) + * only render the changed part of the selection. + **/ +void +poppler_page_render_selection (PopplerPage *page, + cairo_t *cairo, + PopplerRectangle *selection, + PopplerRectangle *old_selection, + PopplerSelectionStyle style, + PopplerColor *glyph_color, + PopplerColor *background_color) +{ + TextOutputDev *text_dev; + CairoOutputDev *output_dev; + SelectionStyle selection_style = selectionStyleGlyph; + PDFRectangle pdf_selection(selection->x1, selection->y1, + selection->x2, selection->y2); + + GfxColor gfx_background_color = { + { + background_color->red, + background_color->green, + background_color->blue + } + }; + GfxColor gfx_glyph_color = { + { + glyph_color->red, + glyph_color->green, + glyph_color->blue + } + }; + + switch (style) + { + case POPPLER_SELECTION_GLYPH: + selection_style = selectionStyleGlyph; + break; + case POPPLER_SELECTION_WORD: + selection_style = selectionStyleWord; + break; + case POPPLER_SELECTION_LINE: + selection_style = selectionStyleLine; + break; + } + + text_dev = poppler_page_get_text_output_dev (page); + output_dev = page->document->output_dev; + output_dev->setCairo (cairo); + + text_dev->drawSelection (output_dev, 1.0, 0, + &pdf_selection, selection_style, + &gfx_glyph_color, &gfx_background_color); + + output_dev->setCairo (NULL); + + /* We'll need a function to destroy page->text_dev and page->gfx + * when the application wants to get rid of them. + * + * Two improvements: 1) make GfxFont refcounted and let TextPage and + * friends hold a reference to the GfxFonts they need so we can free + * up Gfx early. 2) use a TextPage directly when rendering the page + * so we don't have to use TextOutputDev and render a second + * time. */ +} + #endif /* HAVE_CAIRO */ +#ifdef POPPLER_WITH_GDK static void _poppler_page_render_to_pixbuf (PopplerPage *page, int src_x, int src_y, @@ -582,246 +829,32 @@ poppler_page_render_to_pixbuf_for_printing (PopplerPage *page, pixbuf); } -static TextOutputDev * -poppler_page_get_text_output_dev (PopplerPage *page) -{ - if (page->text_dev == NULL) { - page->text_dev = new TextOutputDev (NULL, gTrue, gFalse, gFalse); - - if (page->gfx) - delete page->gfx; - page->gfx = page->page->createGfx(page->text_dev, - 72.0, 72.0, 0, - gFalse, /* useMediaBox */ - gTrue, /* Crop */ - -1, -1, -1, -1, - gFalse, /* printing */ - page->document->doc->getCatalog (), - NULL, NULL, NULL, NULL); - - page->page->display(page->gfx); - - page->text_dev->endPage(); - } - - return page->text_dev; -} - /** - * poppler_page_get_selection_region: - * @page: a #PopplerPage - * @scale: scale specified as pixels per point - * @style: a #PopplerSelectionStyle - * @selection: start and end point of selection as a rectangle + * poppler_page_get_thumbnail_pixbuf: + * @page: the #PopperPage to get the thumbnail for * - * Returns a region containing the area that would be rendered by - * poppler_page_render_selection() or - * poppler_page_render_selection_to_pixbuf(). The returned - * region must be freed with gdk_region_destroy(). + * Get the embedded thumbnail for the specified page. If the document + * doesn't have an embedded thumbnail for the page, this function + * returns %NULL. * - * Return value: a newly allocated #GdkRegion - **/ -GdkRegion * -poppler_page_get_selection_region (PopplerPage *page, - gdouble scale, - PopplerSelectionStyle style, - PopplerRectangle *selection) -{ - TextOutputDev *text_dev; - PDFRectangle poppler_selection; - SelectionStyle selection_style = selectionStyleGlyph; - GooList *list; - GdkRectangle rect; - GdkRegion *region; - int i; - - poppler_selection.x1 = selection->x1; - poppler_selection.y1 = selection->y1; - poppler_selection.x2 = selection->x2; - poppler_selection.y2 = selection->y2; - - switch (style) - { - case POPPLER_SELECTION_GLYPH: - selection_style = selectionStyleGlyph; - break; - case POPPLER_SELECTION_WORD: - selection_style = selectionStyleWord; - break; - case POPPLER_SELECTION_LINE: - selection_style = selectionStyleLine; - break; - } - - text_dev = poppler_page_get_text_output_dev (page); - list = text_dev->getSelectionRegion(&poppler_selection, - selection_style, scale); - - region = gdk_region_new(); - - for (i = 0; i < list->getLength(); i++) { - PDFRectangle *selection_rect = (PDFRectangle *) list->get(i); - rect.x = (gint) selection_rect->x1; - rect.y = (gint) selection_rect->y1; - rect.width = (gint) (selection_rect->x2 - selection_rect->x1); - rect.height = (gint) (selection_rect->y2 - selection_rect->y1); - gdk_region_union_with_rect (region, &rect); - delete selection_rect; - } - - delete list; - - return region; -} - -#if defined (HAVE_CAIRO) - -static void -poppler_page_set_selection_alpha (PopplerPage *page, - double scale, - GdkPixbuf *pixbuf, - PopplerSelectionStyle style, - PopplerRectangle *selection) -{ - /* Cairo doesn't need this, since cairo generates an alpha channel. */ -} - -#elif defined (HAVE_SPLASH) - -static void -poppler_page_set_selection_alpha (PopplerPage *page, - double scale, - GdkPixbuf *pixbuf, - PopplerSelectionStyle style, - PopplerRectangle *selection) -{ - GdkRegion *region; - gint n_rectangles, i, x, y, width, height; - GdkRectangle *rectangles; - int pixbuf_rowstride, pixbuf_n_channels; - guchar *pixbuf_data, *dst; - - pixbuf_data = gdk_pixbuf_get_pixels (pixbuf); - pixbuf_rowstride = gdk_pixbuf_get_rowstride (pixbuf); - pixbuf_n_channels = gdk_pixbuf_get_n_channels (pixbuf); - width = gdk_pixbuf_get_width (pixbuf); - height = gdk_pixbuf_get_height (pixbuf); - - if (pixbuf_n_channels != 4) - return; - - for (y = 0; y < height; y++) { - dst = pixbuf_data + y * pixbuf_rowstride; - for (x = 0; x < width; x++) { - dst[3] = 0x00; - dst += pixbuf_n_channels; - } - } - - region = poppler_page_get_selection_region (page, scale, style, selection); - - gdk_region_get_rectangles (region, &rectangles, &n_rectangles); - for (i = 0; i < n_rectangles; i++) { - for (y = 0; y < rectangles[i].height; y++) { - dst = pixbuf_data + (rectangles[i].y + y) * pixbuf_rowstride + - rectangles[i].x * pixbuf_n_channels; - for (x = 0; x < rectangles[i].width; x++) { - dst[3] = 0xff; - dst += pixbuf_n_channels; - } - } - } - - g_free (rectangles); - - gdk_region_destroy (region); -} - -#endif - -#if defined (HAVE_CAIRO) -/** - * poppler_page_render_selection: - * @page: the #PopplerPage for which to render selection - * @cairo: cairo context to render to - * @selection: start and end point of selection as a rectangle - * @old_selection: previous selection - * @style: a #PopplerSelectionStyle - * @glyph_color: color to use for drawing glyphs - * @background_color: color to use for the selection background - * - * Render the selection specified by @selection for @page to - * the given cairo context. The selection will be rendered, using - * @glyph_color for the glyphs and @background_color for the selection - * background. - * - * If non-NULL, @old_selection specifies the selection that is already - * rendered to @cairo, in which case this function will (some day) - * only render the changed part of the selection. + * Return value: the tumbnail as a #GdkPixbuf or %NULL if the document + * doesn't have a thumbnail for this page. **/ -void -poppler_page_render_selection (PopplerPage *page, - cairo_t *cairo, - PopplerRectangle *selection, - PopplerRectangle *old_selection, - PopplerSelectionStyle style, - GdkColor *glyph_color, - GdkColor *background_color) +GdkPixbuf * +poppler_page_get_thumbnail_pixbuf (PopplerPage *page) { - TextOutputDev *text_dev; - CairoOutputDev *output_dev; - SelectionStyle selection_style = selectionStyleGlyph; - PDFRectangle pdf_selection(selection->x1, selection->y1, - selection->x2, selection->y2); - - GfxColor gfx_background_color = { - { - background_color->red, - background_color->green, - background_color->blue - } - }; - GfxColor gfx_glyph_color = { - { - glyph_color->red, - glyph_color->green, - glyph_color->blue - } - }; - - switch (style) - { - case POPPLER_SELECTION_GLYPH: - selection_style = selectionStyleGlyph; - break; - case POPPLER_SELECTION_WORD: - selection_style = selectionStyleWord; - break; - case POPPLER_SELECTION_LINE: - selection_style = selectionStyleLine; - break; - } - - text_dev = poppler_page_get_text_output_dev (page); - output_dev = page->document->output_dev; - output_dev->setCairo (cairo); + unsigned char *data; + int width, height, rowstride; - text_dev->drawSelection (output_dev, 1.0, 0, - &pdf_selection, selection_style, - &gfx_glyph_color, &gfx_background_color); + g_return_val_if_fail (POPPLER_IS_PAGE (page), FALSE); - output_dev->setCairo (NULL); + if (!page->page->loadThumb (&data, &width, &height, &rowstride)) + return NULL; - /* We'll need a function to destroy page->text_dev and page->gfx - * when the application wants to get rid of them. - * - * Two improvements: 1) make GfxFont refcounted and let TextPage and - * friends hold a reference to the GfxFonts they need so we can free - * up Gfx early. 2) use a TextPage directly when rendering the page - * so we don't have to use TextOutputDev and render a second - * time. */ + return gdk_pixbuf_new_from_data (data, GDK_COLORSPACE_RGB, + FALSE, 8, width, height, rowstride, + (GdkPixbufDestroyNotify)gfree, NULL); } -#endif /** * poppler_page_render_selection_to_pixbuf: @@ -913,39 +946,7 @@ poppler_page_render_selection_to_pixbuf (PopplerPage *page, * time. */ } - -static void -destroy_thumb_data (guchar *pixels, gpointer data) -{ - gfree (pixels); -} - -/** - * poppler_page_get_thumbnail: - * @page: the #PopperPage to get the thumbnail for - * - * Get the embedded thumbnail for the specified page. If the document - * doesn't have an embedded thumbnail for the page, this function - * returns %NULL. - * - * Return value: the tumbnail as a #GdkPixbuf or %NULL if the document - * doesn't have a thumbnail for this page. - **/ -GdkPixbuf * -poppler_page_get_thumbnail (PopplerPage *page) -{ - unsigned char *data; - int width, height, rowstride; - - g_return_val_if_fail (POPPLER_IS_PAGE (page), FALSE); - - if (!page->page->loadThumb (&data, &width, &height, &rowstride)) - return NULL; - - return gdk_pixbuf_new_from_data (data, GDK_COLORSPACE_RGB, - FALSE, 8, width, height, rowstride, - destroy_thumb_data, NULL); -} +#endif /* POPPLER_WITH_GDK */ /** * poppler_page_get_thumbnail_size: @@ -994,6 +995,87 @@ poppler_page_get_thumbnail_size (PopplerPage *page, } /** + * poppler_page_get_selection_region: + * @page: a #PopplerPage + * @scale: scale specified as pixels per point + * @style: a #PopplerSelectionStyle + * @selection: start and end point of selection as a rectangle + * + * Returns a region containing the area that would be rendered by + * poppler_page_render_selection() or + * poppler_page_render_selection_to_pixbuf() as a #GList of + * #PopplerRectangle. The returned list must be freed with + * poppler_page_selection_region_free(). + * + * Return value: a #GList of #PopplerRectangle + **/ +GList * +poppler_page_get_selection_region (PopplerPage *page, + gdouble scale, + PopplerSelectionStyle style, + PopplerRectangle *selection) +{ + TextOutputDev *text_dev; + PDFRectangle poppler_selection; + SelectionStyle selection_style = selectionStyleGlyph; + GooList *list; + GList *region = NULL; + int i; + + poppler_selection.x1 = selection->x1; + poppler_selection.y1 = selection->y1; + poppler_selection.x2 = selection->x2; + poppler_selection.y2 = selection->y2; + + switch (style) + { + case POPPLER_SELECTION_GLYPH: + selection_style = selectionStyleGlyph; + break; + case POPPLER_SELECTION_WORD: + selection_style = selectionStyleWord; + break; + case POPPLER_SELECTION_LINE: + selection_style = selectionStyleLine; + break; + } + + text_dev = poppler_page_get_text_output_dev (page); + list = text_dev->getSelectionRegion(&poppler_selection, + selection_style, scale); + + for (i = 0; i < list->getLength(); i++) { + PDFRectangle *selection_rect = (PDFRectangle *) list->get(i); + PopplerRectangle *rect; + + rect = poppler_rectangle_new (); + + rect->x1 = selection_rect->x1; + rect->y1 = selection_rect->y1; + rect->x2 = selection_rect->x2; + rect->y2 = selection_rect->y2; + + region = g_list_prepend (region, rect); + + delete selection_rect; + } + + delete list; + + return g_list_reverse (region); +} + +void +poppler_page_selection_region_free (GList *region) +{ + if (!region) + return; + + g_list_foreach (region, (GFunc)poppler_rectangle_free, NULL); + g_list_free (region); +} + +/** * poppler_page_get_text: * @page: a #PopplerPage * @style: a #PopplerSelectionStyle @@ -1624,7 +1706,7 @@ poppler_rectangle_get_type (void) { static GType our_type = 0; - if (our_type == 0) + if (G_UNLIKELY (our_type == 0)) our_type = g_boxed_type_register_static ("PopplerRectangle", (GBoxedCopyFunc) poppler_rectangle_copy, (GBoxedFreeFunc) poppler_rectangle_free); @@ -1645,7 +1727,7 @@ poppler_rectangle_copy (PopplerRectangle *rectangle) g_return_val_if_fail (rectangle != NULL, NULL); - new_rectangle = g_new0 (PopplerRectangle, 1); + new_rectangle = g_new (PopplerRectangle, 1); *new_rectangle = *rectangle; return new_rectangle; @@ -1657,13 +1739,50 @@ poppler_rectangle_free (PopplerRectangle *rectangle) g_free (rectangle); } +/* PopplerColor type */ +GType +poppler_color_get_type (void) +{ + static GType our_type = 0; + + if (G_UNLIKELY (our_type == 0)) + our_type = g_boxed_type_register_static ("PopplerColor", + (GBoxedCopyFunc) poppler_color_copy, + (GBoxedFreeFunc) poppler_color_free); + + return our_type; +} + +PopplerColor * +poppler_color_new (void) +{ + return (PopplerColor *) g_new0 (PopplerColor, 1); +} + +PopplerColor * +poppler_color_copy (PopplerColor *color) +{ + PopplerColor *new_color; + + new_color = g_new (PopplerColor, 1); + *new_color = *color; + + return new_color; +} + +void +poppler_color_free (PopplerColor *color) +{ + g_free (color); +} + /* PopplerLinkMapping type */ GType poppler_link_mapping_get_type (void) { static GType our_type = 0; - if (our_type == 0) + if (G_UNLIKELY (our_type == 0)) our_type = g_boxed_type_register_static ("PopplerLinkMapping", (GBoxedCopyFunc) poppler_link_mapping_copy, (GBoxedFreeFunc) poppler_link_mapping_free); @@ -1706,7 +1825,7 @@ poppler_image_mapping_get_type (void) { static GType our_type = 0; - if (our_type == 0) + if (G_UNLIKELY (our_type == 0)) our_type = g_boxed_type_register_static ("PopplerImageMapping", (GBoxedCopyFunc) poppler_image_mapping_copy, (GBoxedFreeFunc) poppler_image_mapping_free); @@ -1743,7 +1862,7 @@ GType poppler_page_transition_get_type (void) { static GType our_type = 0; - if (our_type == 0) + if (G_UNLIKELY (our_type == 0)) our_type = g_boxed_type_register_static("PopplerPageTransition", (GBoxedCopyFunc) poppler_page_transition_copy, (GBoxedFreeFunc) poppler_page_transition_free); @@ -1778,7 +1897,7 @@ GType poppler_form_field_mapping_get_type (void) { static GType our_type = 0; - if (our_type == 0) + if (G_UNLIKELY (our_type == 0)) our_type = g_boxed_type_register_static("PopplerFormFieldMapping", (GBoxedCopyFunc) poppler_form_field_mapping_copy, (GBoxedFreeFunc) poppler_form_field_mapping_free); diff --git a/glib/poppler-page.h b/glib/poppler-page.h index 5304d0b5..0cd57413 100644 --- a/glib/poppler-page.h +++ b/glib/poppler-page.h @@ -20,25 +20,29 @@ #define __POPPLER_PAGE_H__ #include <glib-object.h> + +#include "poppler.h" + +#ifdef POPPLER_WITH_GDK #include <gdk/gdkregion.h> #include <gdk/gdkcolor.h> #include <gdk-pixbuf/gdk-pixbuf.h> +#endif #ifdef POPPLER_HAS_CAIRO #include <cairo.h> #endif -#include "poppler.h" - G_BEGIN_DECLS - #define POPPLER_TYPE_PAGE (poppler_page_get_type ()) #define POPPLER_PAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), POPPLER_TYPE_PAGE, PopplerPage)) #define POPPLER_IS_PAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), POPPLER_TYPE_PAGE)) GType poppler_page_get_type (void) G_GNUC_CONST; + +#ifdef POPPLER_WITH_GDK void poppler_page_render_to_pixbuf (PopplerPage *page, int src_x, int src_y, @@ -55,13 +59,33 @@ void poppler_page_render_to_pixbuf_for_printing (PopplerPage *pa double scale, int rotation, GdkPixbuf *pixbuf); +GdkPixbuf *poppler_page_get_thumbnail_pixbuf (PopplerPage *page); +void poppler_page_render_selection_to_pixbuf ( + PopplerPage *page, + gdouble scale, + int rotation, + GdkPixbuf *pixbuf, + PopplerRectangle *selection, + PopplerRectangle *old_selection, + PopplerSelectionStyle style, + GdkColor *glyph_color, + GdkColor *background_color); +#endif /* POPPLER_WITH_GDK */ #ifdef POPPLER_HAS_CAIRO void poppler_page_render (PopplerPage *page, cairo_t *cairo); void poppler_page_render_for_printing (PopplerPage *page, cairo_t *cairo); -#endif +cairo_surface_t *poppler_page_get_thumbnail (PopplerPage *page); +void poppler_page_render_selection (PopplerPage *page, + cairo_t *cairo, + PopplerRectangle *selection, + PopplerRectangle *old_selection, + PopplerSelectionStyle style, + PopplerColor *glyph_color, + PopplerColor *background_color); +#endif /* POPPLER_HAS_CAIRO */ void poppler_page_get_size (PopplerPage *page, double *width, @@ -69,7 +93,6 @@ void poppler_page_get_size (PopplerPage *pa int poppler_page_get_index (PopplerPage *page); double poppler_page_get_duration (PopplerPage *page); PopplerPageTransition *poppler_page_get_transition (PopplerPage *page); -GdkPixbuf *poppler_page_get_thumbnail (PopplerPage *page); gboolean poppler_page_get_thumbnail_size (PopplerPage *page, int *width, int *height); @@ -80,6 +103,11 @@ void poppler_page_render_to_ps (PopplerPage *pa char *poppler_page_get_text (PopplerPage *page, PopplerSelectionStyle style, PopplerRectangle *rect); +GList *poppler_page_get_selection_region (PopplerPage *page, + gdouble scale, + PopplerSelectionStyle style, + PopplerRectangle *selection); +void poppler_page_selection_region_free(GList *region); GList *poppler_page_get_link_mapping (PopplerPage *page); void poppler_page_free_link_mapping (GList *list); GList *poppler_page_get_image_mapping (PopplerPage *page); @@ -87,35 +115,11 @@ void poppler_page_free_image_mapping (GList *li #ifdef POPPLER_HAS_CAIRO cairo_surface_t *poppler_page_get_image (PopplerPage *page, gint image_id); -#endif +#endif /* POPPLER_HAS_CAIRO */ GList *poppler_page_get_form_field_mapping (PopplerPage *page); void poppler_page_free_form_field_mapping (GList *list); GList *poppler_page_get_annot_mapping (PopplerPage *page); void poppler_page_free_annot_mapping (GList *list); -GdkRegion *poppler_page_get_selection_region (PopplerPage *page, - gdouble scale, - PopplerSelectionStyle style, - PopplerRectangle *selection); -#ifdef POPPLER_HAS_CAIRO -void poppler_page_render_selection (PopplerPage *page, - cairo_t *cairo, - PopplerRectangle *selection, - PopplerRectangle *old_selection, - PopplerSelectionStyle style, - GdkColor *glyph_color, - GdkColor *background_color); -#endif -void poppler_page_render_selection_to_pixbuf ( - PopplerPage *page, - gdouble scale, - int rotation, - GdkPixbuf *pixbuf, - PopplerRectangle *selection, - PopplerRectangle *old_selection, - PopplerSelectionStyle style, - GdkColor *glyph_color, - GdkColor *background_color); - void poppler_page_get_crop_box (PopplerPage *page, PopplerRectangle *rect); @@ -135,7 +139,19 @@ PopplerRectangle *poppler_rectangle_new (void); PopplerRectangle *poppler_rectangle_copy (PopplerRectangle *rectangle); void poppler_rectangle_free (PopplerRectangle *rectangle); +/* A color in RGB */ +#define POPPLER_TYPE_COLOR (poppler_color_get_type ()) +struct _PopplerColor +{ + guint16 red; + guint16 green; + guint16 blue; +}; +GType poppler_color_get_type (void) G_GNUC_CONST; +PopplerColor *poppler_color_new (void); +PopplerColor *poppler_color_copy (PopplerColor *color); +void poppler_color_free (PopplerColor *color); /* 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 07ef09ae..5f3eaa8c 100644 --- a/glib/poppler.h +++ b/glib/poppler.h @@ -20,7 +20,6 @@ #define __POPPLER_GLIB_H__ #include <glib-object.h> -#include <gdk-pixbuf/gdk-pixbuf.h> G_BEGIN_DECLS @@ -81,6 +80,7 @@ typedef struct _PopplerDocument PopplerDocument; typedef struct _PopplerIndexIter PopplerIndexIter; typedef struct _PopplerFontsIter PopplerFontsIter; typedef struct _PopplerRectangle PopplerRectangle; +typedef struct _PopplerColor PopplerColor; typedef struct _PopplerLinkMapping PopplerLinkMapping; typedef struct _PopplerPageTransition PopplerPageTransition; typedef struct _PopplerImageMapping PopplerImageMapping; diff --git a/glib/test-poppler-glib.cc b/glib/test-poppler-glib.cc index 2c3ededf..1b2f89b7 100644 --- a/glib/test-poppler-glib.cc +++ b/glib/test-poppler-glib.cc @@ -381,7 +381,7 @@ int main (int argc, char *argv[]) printf ("\tpage transition:no transition effect for page\n"); } - thumb = poppler_page_get_thumbnail (page); + thumb = poppler_page_get_thumbnail_pixbuf (page); if (thumb != NULL) { gdk_pixbuf_save (thumb, "thumb.png", "png", &error, NULL); if (error != NULL) |