Commit d839a0bd authored by Kristian Høgsberg's avatar Kristian Høgsberg

2006-04-11 Kristian Høgsberg <krh@redhat.com>

	* configure.ac:
	* poppler-glib.pc.in:
	* glib/Makefile.am:
	* glib/poppler-page.cc:
	* glib/poppler-page.h:
	* glib/poppler.h:
	* poppler/CairoOutputDev.cc:
	* poppler/CairoOutputDev.h:
	* glib/poppler-features.h.in:
	Make the CairoOutputDev render to a cairo_t instead of a
	cairo_surface_t and expose that functionality in the glib wrapper
	(poppler_page_render).

	* test/Makefile.am:
	* test/gtk-cairo-test.cc:
	Update gtk-cairo-test to use this new interface and add a spin
	button for changing page (#5951).

	* utils/Makefile.am (EXTRA_DIST): Fix warning where this was
	assigned twice.
parent b198c980
2006-04-11 Kristian Høgsberg <krh@redhat.com>
* configure.ac:
* poppler-glib.pc.in:
* glib/Makefile.am:
* glib/poppler-page.cc:
* glib/poppler-page.h:
* glib/poppler.h:
* poppler/CairoOutputDev.cc:
* poppler/CairoOutputDev.h:
* glib/poppler-features.h.in:
Make the CairoOutputDev render to a cairo_t instead of a
cairo_surface_t and expose that functionality in the glib wrapper
(poppler_page_render).
* test/Makefile.am:
* test/gtk-cairo-test.cc:
Update gtk-cairo-test to use this new interface and add a spin
button for changing page (#5951).
* utils/Makefile.am (EXTRA_DIST): Fix warning where this was
assigned twice.
2006-04-10 Jeff Muizelaar <jeff@infidigm.net>
* poppler/CairoOutputDev.cc: take originX and originY into account in
......
......@@ -182,7 +182,14 @@ AM_CONDITIONAL(BUILD_CAIRO_OUTPUT, test x$enable_cairo_output = xyes)
AH_TEMPLATE([HAVE_CAIRO], [Use cairo for rendering.])
if test x$enable_cairo_output = xyes; then
AC_DEFINE(HAVE_CAIRO)
CAIRO_FEATURE="#define POPPLER_HAS_CAIRO 1"
CAIRO_REQ="cairo"
else
CAIRO_FEATURE="#undef POPPLER_HAS_CAIRO"
CAIRO_REQ=""
fi
AC_SUBST(CAIRO_FEATURE)
AC_SUBST(CAIRO_REQ)
AC_ARG_ENABLE(poppler-glib,
AC_HELP_STRING([--disable-poppler-glib],
......@@ -306,6 +313,7 @@ splash/Makefile
poppler/Makefile
utils/Makefile
glib/Makefile
glib/poppler-features.h
glib/reference/Makefile
test/Makefile
qt/Makefile
......
......@@ -66,7 +66,8 @@ poppler_glib_includedir = $(includedir)/poppler/glib
poppler_glib_include_HEADERS = \
$(poppler_glib_public_headers) \
poppler-enums.h
poppler-enums.h \
poppler-features.h
lib_LTLIBRARIES = libpoppler-glib.la
libpoppler_glib_la_SOURCES = \
......@@ -98,9 +99,10 @@ test_poppler_glib_LDADD = \
$(FREETYPE_LIBS) \
$(cairo_libs)
BUILT_SOURCES = \
poppler-enums.c \
poppler-enums.h
BUILT_SOURCES = \
poppler-enums.c \
poppler-enums.h \
poppler-features.h
CLEANFILES = $(BUILT_SOURCES) $(stamp_files)
DISTCLEANFILES = $(BUILT_SOURCES) $(stamp_files)
......
/* poppler-features.h: glib interface to poppler
* Copyright (C) 2006, Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __POPPLER_FEATURES_H__
#define __POPPLER_FEATURES_H__
@CAIRO_FEATURE@
#endif /* __POPPLER_FEATURES_H__ */
......@@ -127,6 +127,7 @@ poppler_page_get_index (PopplerPage *page)
typedef struct {
unsigned char *cairo_data;
cairo_surface_t *surface;
cairo_t *cairo;
} OutputDevData;
static void
......@@ -138,19 +139,13 @@ poppler_page_prepare_output_dev (PopplerPage *page,
{
CairoOutputDev *output_dev;
cairo_surface_t *surface;
double width, height;
int cairo_width, cairo_height, cairo_rowstride;
int rotate;
unsigned char *cairo_data;
rotate = (rotation + page->page->getRotate()) % 360;
if (rotate == 90 || rotate == 270) {
cairo_width = MAX ((int)(page->page->getCropHeight() * scale + 0.5), 1);
cairo_height = MAX ((int)(page->page->getCropWidth() * scale + 0.5), 1);
} else {
cairo_width = MAX ((int)(page->page->getCropWidth() * scale + 0.5), 1);
cairo_height = MAX ((int)(page->page->getCropHeight() * scale + 0.5), 1);
}
poppler_page_get_size (page, &width, &height);
cairo_width = (int) ceil(width * scale);
cairo_height = (int) ceil(height * scale);
output_dev = page->document->output_dev;
cairo_rowstride = cairo_width * 4;
......@@ -167,7 +162,8 @@ poppler_page_prepare_output_dev (PopplerPage *page,
output_dev_data->cairo_data = cairo_data;
output_dev_data->surface = surface;
output_dev->setSurface (surface);
output_dev_data->cairo = cairo_create (surface);
output_dev->setCairo (output_dev_data->cairo);
}
static void
......@@ -194,7 +190,6 @@ poppler_page_copy_to_pixbuf (PopplerPage *page,
cairo_width = gdk_pixbuf_get_width (pixbuf);
if (cairo_height > gdk_pixbuf_get_height (pixbuf))
cairo_height = gdk_pixbuf_get_height (pixbuf);
for (y = 0; y < cairo_height; y++)
{
src = (unsigned int *) (cairo_data + y * cairo_rowstride);
......@@ -211,8 +206,9 @@ poppler_page_copy_to_pixbuf (PopplerPage *page,
}
}
page->document->output_dev->setSurface (NULL);
page->document->output_dev->setCairo (NULL);
cairo_surface_destroy (output_dev_data->surface);
cairo_destroy (output_dev_data->cairo);
gfree (output_dev_data->cairo_data);
}
......@@ -282,13 +278,44 @@ poppler_page_copy_to_pixbuf(PopplerPage *page,
#endif
#if defined (HAVE_CAIRO)
/**
* poppler_page_render:
* @page: the page to render from
* @cairo: cairo context to render to
*
* Render the page to the given cairo context.
**/
void
poppler_page_render (PopplerPage *page,
cairo_t *cairo)
{
CairoOutputDev *output_dev;
g_return_if_fail (POPPLER_IS_PAGE (page));
output_dev = page->document->output_dev;
output_dev->setCairo (cairo);
page->page->displaySlice(output_dev,
72.0, 72.0, 0,
gFalse, /* useMediaBox */
gTrue, /* Crop */
0, 0,
(int) ceil (page->page->getCropWidth ()),
(int) ceil (page->page->getCropHeight ()),
NULL, /* links */
page->document->doc->getCatalog ());
output_dev->setCairo (NULL);
}
#endif
/**
* poppler_page_render_to_pixbuf:
* poppler_page_render:
* @page: the page to render from
* @src_x: x coordinate of upper left corner
* @src_y: y coordinate of upper left corner
* @src_width: width of rectangle to render
* @src_height: height of rectangle to render
* @scale: scale specified as pixels per point
* @rotation: rotate the document by the specified degree
* @pixbuf: pixbuf to render into
......
......@@ -24,6 +24,10 @@
#include <gdk/gdkcolor.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#ifdef POPPLER_HAS_CAIRO
#include <cairo.h>
#endif
#include "poppler.h"
G_BEGIN_DECLS
......@@ -43,6 +47,12 @@ void poppler_page_render_to_pixbuf (PopplerPage *page,
double scale,
int rotation,
GdkPixbuf *pixbuf);
#ifdef POPPLER_HAS_CAIRO
void poppler_page_render (PopplerPage *page,
cairo_t *cairo);
#endif
void poppler_page_get_size (PopplerPage *page,
double *width,
double *height);
......
......@@ -65,6 +65,7 @@ const char * poppler_get_version (void);
G_END_DECLS
#include "poppler-features.h"
#include "poppler-document.h"
#include "poppler-page.h"
#include "poppler-action.h"
......
......@@ -6,7 +6,7 @@ includedir=@includedir@
Name: poppler-glib
Description: GLib wrapper for poppler
Version: @VERSION@
Requires: poppler = @VERSION@ gobject-2.0 gdk-pixbuf-2.0
Requires: poppler = @VERSION@ gobject-2.0 gdk-pixbuf-2.0 @CAIRO_REQ@
Libs: -L${libdir} -lpoppler-glib
Cflags: -I${includedir}/poppler/glib
......@@ -52,12 +52,12 @@ CairoOutputDev::CairoOutputDev() {
FT_Init_FreeType(&ft_lib);
fontEngine = NULL;
glyphs = NULL;
surface = NULL;
fill_pattern = NULL;
stroke_pattern = NULL;
stroke_opacity = 1.0;
fill_opacity = 1.0;
textClipPath = NULL;
cairo = NULL;
}
CairoOutputDev::~CairoOutputDev() {
......@@ -65,16 +65,19 @@ CairoOutputDev::~CairoOutputDev() {
delete fontEngine;
}
FT_Done_FreeType(ft_lib);
cairo_surface_destroy (surface);
cairo_destroy (cairo);
cairo_pattern_destroy (stroke_pattern);
cairo_pattern_destroy (fill_pattern);
}
void CairoOutputDev::setSurface(cairo_surface_t *surface)
void CairoOutputDev::setCairo(cairo_t *cairo)
{
cairo_surface_destroy (this->surface);
cairo_surface_reference (surface);
this->surface = surface;
if (this->cairo != NULL)
cairo_destroy (this->cairo);
if (cairo != NULL)
this->cairo = cairo_reference (cairo);
else
this->cairo = NULL;
}
void CairoOutputDev::startDoc(XRef *xrefA) {
......@@ -85,14 +88,6 @@ void CairoOutputDev::startDoc(XRef *xrefA) {
fontEngine = new CairoFontEngine(ft_lib);
}
void CairoOutputDev::startPage(int pageNum, GfxState *state) {
cairo = cairo_create (surface);
}
void CairoOutputDev::endPage() {
cairo_destroy (cairo);
}
void CairoOutputDev::drawLink(Link *link, Catalog *catalog) {
}
......
......@@ -57,10 +57,10 @@ public:
//----- initialization and control
// Start a page.
virtual void startPage(int pageNum, GfxState *state);
virtual void startPage(int pageNum, GfxState *state) { }
// End a page.
virtual void endPage();
virtual void endPage() { }
//----- link borders
virtual void drawLink(Link *link, Catalog *catalog);
......@@ -136,7 +136,7 @@ public:
GBool isReverseVideo() { return gFalse; }
void setSurface (cairo_surface_t *surface);
void setCairo (cairo_t *cr);
protected:
void doPath(GfxState *state, GfxPath *path);
......
......@@ -30,6 +30,8 @@ endif
INCLUDES = \
-I$(top_srcdir) \
-I$(top_srcdir)/poppler \
-I$(top_srcdir)/glib \
-I$(top_builddir)/glib \
$(cairo_includes) \
$(GTK_TEST_CFLAGS)
......@@ -47,7 +49,7 @@ gtk_cairo_test_SOURCES = \
gtk_cairo_test_LDADD = \
$(top_builddir)/poppler/libpoppler.la \
$(top_builddir)/poppler/libpoppler-cairo.la \
$(top_builddir)/glib/libpoppler-glib.la \
$(CAIRO_LIBS) \
$(GTK_TEST_LIBS)
......
......@@ -13,136 +13,23 @@
#pragma implementation
#endif
#include <goo/gmem.h>
#include <splash/SplashTypes.h>
#include <splash/SplashBitmap.h>
#include "Object.h"
#include "GfxState.h"
#include <math.h>
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include "CairoOutputDev.h"
#include <cairo-xlib.h>
#include <X11/Xutil.h>
#include "PDFDoc.h"
#include "GlobalParams.h"
#include "ErrorCodes.h"
#include <gtk/gtk.h>
class GDKCairoOutputDev: public CairoOutputDev {
public:
GDKCairoOutputDev(GdkDrawable *drawable,
void (*redrawCbkA)(void *data),
void *redrawCbkDataA);
virtual ~GDKCairoOutputDev();
// Start a page.
virtual void startPage(int pageNum, GfxState *state);
//----- special access
// Clear out the document (used when displaying an empty window).
void clear();
// Copy the rectangle (srcX, srcY, width, height) to (destX, destY)
// in destDC.
void redraw(int srcX, int srcY,
GdkDrawable *drawable,
int destX, int destY,
int width, int height);
int getPixmapWidth (void) { return pixmapWidth; }
int getPixmapHeight (void) { return pixmapHeight; }
private:
int incrementalUpdate;
void (*redrawCbk)(void *data);
void *redrawCbkData;
int pixmapWidth, pixmapHeight;
GdkPixmap *pixmap, *drawable;
};
GDKCairoOutputDev::GDKCairoOutputDev(GdkDrawable *drawableA,
void (*redrawCbkA)(void *data),
void *redrawCbkDataA):
CairoOutputDev()
{
drawable = drawableA;
redrawCbk = redrawCbkA;
redrawCbkData = redrawCbkDataA;
pixmap = NULL;
}
GDKCairoOutputDev::~GDKCairoOutputDev() {
}
void
GDKCairoOutputDev::startPage(int pageNum, GfxState *state) {
Display *display;
Drawable xid;
GdkGC *gc;
GdkColor white;
cairo_surface_t *surface;
int w, h;
w = state ? (int)(state->getPageWidth() + 0.5) : 1;
h = state ? (int)(state->getPageHeight() + 0.5) : 1;
if (!pixmap || pixmapWidth != w || h != pixmapHeight != h) {
if (pixmap)
g_object_unref (G_OBJECT (pixmap));
pixmap = gdk_pixmap_new (drawable, w, h, -1);
pixmapWidth = w;
pixmapHeight = h;
gc = gdk_gc_new (pixmap);
white.red = 0xffff;
white.green = 0xffff;
white.blue = 0xffff;
gdk_gc_set_rgb_fg_color (gc, &white);
gdk_draw_rectangle (pixmap, gc, TRUE, 0, 0, w, h);
g_object_unref (G_OBJECT (gc));
}
if (pixmap) {
display = gdk_x11_drawable_get_xdisplay (pixmap);
xid = gdk_x11_drawable_get_xid (pixmap);
surface = cairo_xlib_surface_create(display, xid,
DefaultVisual(display, DefaultScreen(display)),
w, h);
setSurface(surface);
cairo_surface_destroy (surface);
}
CairoOutputDev::startPage(pageNum, state);
}
void GDKCairoOutputDev::redraw(int srcX, int srcY,
GdkDrawable *drawable,
int destX, int destY,
int width, int height) {
GdkGC *gc;
gc = gdk_gc_new (drawable);
gdk_draw_drawable (drawable, gc,
pixmap, srcX, srcY,
destX, destY, width, height);
g_object_unref (gc);
}
#include <poppler.h>
typedef struct
{
GtkWidget *window;
GtkWidget *sw;
GtkWidget *drawing_area;
GDKCairoOutputDev *out;
PDFDoc *doc;
PopplerPage *page;
PopplerDocument *document;
cairo_surface_t *surface;
int *window_count;
} View;
static void
......@@ -153,109 +40,117 @@ drawing_area_expose (GtkWidget *drawing_area,
View *v = (View*) data;
GdkRectangle document;
GdkRectangle draw;
cairo_t *cr;
gdk_window_clear (drawing_area->window);
document.x = 0;
document.y = 0;
document.width = v->out->getPixmapWidth();
document.height = v->out->getPixmapHeight();
cr = gdk_cairo_create (drawing_area->window);
if (gdk_rectangle_intersect (&document, &event->area, &draw))
{
v->out->redraw (draw.x, draw.y,
drawing_area->window,
draw.x, draw.y,
draw.width, draw.height);
}
cairo_set_source_surface (cr, v->surface, 0, 0);
cairo_paint (cr);
cairo_destroy (cr);
}
static int
view_load (View *v,
const char *filename)
static void
view_set_page (View *v, int page)
{
PDFDoc *newDoc;
int err;
GooString *filename_g;
int w, h;
filename_g = new GooString (filename);
// open the PDF file
newDoc = new PDFDoc(filename_g, 0, 0);
delete filename_g;
if (!newDoc->isOk())
{
err = newDoc->getErrorCode();
delete newDoc;
return err;
}
if (v->doc)
delete v->doc;
v->doc = newDoc;
v->out->startDoc(v->doc->getXRef());
v->doc->displayPage (v->out, 1, 72, 72, 0, gFalse, gTrue, gTrue);
w = v->out->getPixmapWidth();
h = v->out->getPixmapHeight();
double width, height;
cairo_t *cr;
v->page = poppler_document_get_page (v->document, page);
poppler_page_get_size (v->page, &width, &height);
w = (int) ceil(width);
h = (int) ceil(height);
cairo_surface_destroy (v->surface);
v->surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, w, h);
cr = cairo_create (v->surface);
poppler_page_render (v->page, cr);
cairo_destroy (cr);
gtk_widget_set_size_request (v->drawing_area, w, h);
return errNone;
gtk_widget_queue_draw (v->drawing_area);
}
static void
view_show (View *v)
redraw_callback (void *data)
{
gtk_widget_show (v->window);
View *v = (View*) data;
gtk_widget_queue_draw (v->drawing_area);
}
static void
redraw_callback (void *data)
page_changed_callback (GtkSpinButton *button, View *v)
{
View *v = (View*) data;
int page;
gtk_widget_queue_draw (v->drawing_area);
page = gtk_spin_button_get_value_as_int (button);
view_set_page (v, page);
}
static void
destroy_window_callback (GtkWindow *window, View *v)
{
if (--(*v->window_count) == 0)
gtk_main_quit();
}
static View*
view_new (void)
view_new (const char *filename, int *window_count)
{
View *v;
GtkWidget *window;
GtkWidget *drawing_area;
GtkWidget *sw;
GtkWidget *vbox, *hbox;
GtkWidget *spin_button;
int n_pages;
v = g_new0 (View, 1);
v->document = poppler_document_new_from_file (filename, NULL, NULL);
if (v->document == NULL)
return NULL;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
vbox = gtk_vbox_new(FALSE, 5);
gtk_container_add (GTK_CONTAINER (window), vbox);
drawing_area = gtk_drawing_area_new ();
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_container_add (GTK_CONTAINER (window), sw);
gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (sw), drawing_area);
gtk_box_pack_end (GTK_BOX (vbox), sw, TRUE, TRUE, 0);
gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (sw),
drawing_area);
gtk_widget_show_all (sw);
gtk_widget_realize (window);
n_pages = poppler_document_get_n_pages (v->document);
spin_button = gtk_spin_button_new_with_range (0, n_pages - 1, 1);
g_signal_connect (G_OBJECT (spin_button), "value-changed",
G_CALLBACK (page_changed_callback), v);
hbox = gtk_hbox_new (FALSE, 5);
gtk_box_pack_end (GTK_BOX (hbox), spin_button, FALSE, TRUE, 0);
v = g_new0 (View, 1);
gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
gtk_widget_show_all (window);
gtk_widget_realize (window);
v->window = window;
v->drawing_area = drawing_area;
v->sw = sw;
v->out = new GDKCairoOutputDev (window->window, redraw_callback, (void*) v);
v->doc = 0;
v->window_count = window_count;
g_signal_connect (drawing_area,
"expose_event",
G_CALLBACK (drawing_area_expose),
(void*) v);
g_signal_connect (window,
"destroy",
G_CALLBACK (destroy_window_callback),
(void*) v);
return v;
}
......@@ -263,39 +158,30 @@ int
main (int argc, char *argv [])
{
View *v;
int i;
int i, window_count;
gtk_init (&argc, &argv);
globalParams = new GlobalParams("/etc/xpdfrc");
if (argc == 1)
{
fprintf (stderr, "usage: %s PDF-FILES...\n", argv[0]);
return -1;
}
i = 1;
while (i < argc)
{
int err;
v = view_new ();
err = view_load (v, argv[i]);
if (err != errNone)
g_printerr ("Error loading document!\n");
window_count = 0;
for (i = 1; i < argc; i++) {
v = view_new (argv[i], &window_count);
if (v == NULL) {
g_printerr ("Error loading %s\n", argv[i]);
continue;
}
view_show (v);
++i;
}
gtk_main ();
view_set_page (v, 0);
window_count++;
}
delete globalParams;
if (window_count > 0)
gtk_main ();
return 0;
}
......@@ -29,8 +29,6 @@ bin_PROGRAMS = \
pdftohtml \
$(pdftoppm_binary)
EXTRA_DIST = pdf2xml.dtd
dist_man1_MANS = \
pdffonts.1 \
pdfimages.1 \
......@@ -75,6 +73,6 @@ pdftohtml_SOURCES = \
$(common)
# Yay, automake! It should be able to figure out that it has to dist
# this file, but nooo. So we just add it here.
# pdftoppm.1, but nooo. So we just add it here.
EXTRA_DIST = pdftoppm.1
EXTRA_DIST = pdf2xml.dtd pdftoppm.1
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment