[poppler] configure.ac glib/demo glib/Makefile.am glib/poppler-action.h glib/poppler-annot.cc glib/poppler-annot.h glib/poppler-document.h glib/poppler-features.h.in glib/poppler.h glib/poppler-page.cc glib/poppler-page.h glib/test-poppler-glib.cc
Carlos Garcia Campos
carlosgc at kemper.freedesktop.org
Wed Mar 12 14:14:07 PDT 2008
configure.ac | 45 ++-
glib/Makefile.am | 7
glib/demo/page.c | 88 +++++
glib/demo/render.c | 4
glib/poppler-action.h | 1
glib/poppler-annot.cc | 26 -
glib/poppler-annot.h | 2
glib/poppler-document.h | 2
glib/poppler-features.h.in | 1
glib/poppler-page.cc | 661 ++++++++++++++++++++++++++-------------------
glib/poppler-page.h | 76 +++--
glib/poppler.h | 2
glib/test-poppler-glib.cc | 2
13 files changed, 593 insertions(+), 324 deletions(-)
New commits:
commit f5065016b168e4896e2fe774cd22bbd900849b52
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date: Wed Mar 12 22:06:53 2008 +0100
Make GDK dependency option for glib bindings
Fixes bug #13719.
diff --git a/configure.ac b/configure.ac
index b871c92..7ce607f 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 f4df44d..e84e40b 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 10445fd..c029b27 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 5544748..1530513 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 45e92b1..87f216c 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 8d7ab49..da900a3 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 006255e..706e3e1 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 1ff140e..4585425 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 76ff423..7b72569 100644
--- a/glib/poppler-features.h.in
+++ b/glib/poppler-features.h.in
@@ -20,5 +20,6 @@
#define __POPPLER_FEATURES_H__
@CAIRO_FEATURE@
+ at GDK_FEATURE@
#endif /* __POPPLER_FEATURES_H__ */
diff --git a/glib/poppler-page.cc b/glib/poppler-page.cc
index 0f39133..5cbc5a8 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 5304d0b..0cd5741 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 07ef09a..5f3eaa8 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 2c3eded..1b2f89b 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)
More information about the poppler
mailing list