Commit 61e9bc76 authored by Kristian Høgsberg's avatar Kristian Høgsberg

2005-06-27 Kristian Høgsberg <krh@redhat.com>

        * poppler/CairoOutputDev.cc:
        * poppler/CairoOutputDev.h: Change CairoOutputDev to render to a
        given surface and let the user create that surface.

        * glib/poppler-document.cc:
        * glib/poppler-page.cc:
        * glib/poppler-private.h: Create the cairo image surface here
        instead and pass it to the CairoOutputDev for rendering.

        * poppler/CairoOutputDevImage.cc:
        * poppler/CairoOutputDevImage.h:
        * poppler/CairoOutputDevX.cc:
        * poppler/CairoOutputDevX.h:
        * poppler/Makefile.am: Remove specialized cairo output devices.
parent 8079dce3
2005-06-27 Kristian Høgsberg <krh@redhat.com>
* poppler/CairoOutputDev.cc:
* poppler/CairoOutputDev.h: Change CairoOutputDev to render to a
given surface and let the user create that surface.
* glib/poppler-document.cc:
* glib/poppler-page.cc:
* glib/poppler-private.h: Create the cairo image surface here
instead and pass it to the CairoOutputDev for rendering.
* poppler/CairoOutputDevImage.cc:
* poppler/CairoOutputDevImage.h:
* poppler/CairoOutputDevX.cc:
* poppler/CairoOutputDevX.h:
* poppler/Makefile.am: Remove specialized cairo output devices.
2005-06-26 Kristian Høgsberg <krh@redhat.com> 2005-06-26 Kristian Høgsberg <krh@redhat.com>
* poppler/CairoOutputDev.cc: * poppler/CairoOutputDev.cc:
......
...@@ -114,7 +114,7 @@ poppler_document_new_from_file (const char *uri, ...@@ -114,7 +114,7 @@ poppler_document_new_from_file (const char *uri,
document->doc = newDoc; document->doc = newDoc;
#if defined (HAVE_CAIRO) #if defined (HAVE_CAIRO)
document->output_dev = new CairoOutputDevImage (); document->output_dev = new CairoOutputDev ();
#elif defined (HAVE_SPLASH) #elif defined (HAVE_SPLASH)
SplashColor white; SplashColor white;
white.rgb8 = splashMakeRGB8 (0xff, 0xff, 0xff); white.rgb8 = splashMakeRGB8 (0xff, 0xff, 0xff);
......
...@@ -165,14 +165,26 @@ cairo_render_to_pixbuf (PopplerPage *page, ...@@ -165,14 +165,26 @@ cairo_render_to_pixbuf (PopplerPage *page,
GdkPixbuf *pixbuf, GdkPixbuf *pixbuf,
int dest_x, int dest_y) int dest_x, int dest_y)
{ {
CairoOutputDevImage *output_dev; CairoOutputDev *output_dev;
int cairo_width, cairo_height, cairo_rowstride; int cairo_width, cairo_height, cairo_rowstride;
int pixbuf_rowstride, pixbuf_n_channels; int pixbuf_rowstride, pixbuf_n_channels;
guchar *pixbuf_data, *cairo_data, *dst; guchar *pixbuf_data, *cairo_data, *dst;
cairo_surface_t *surface;
int x, y; int x, y;
output_dev = page->document->output_dev; output_dev = page->document->output_dev;
cairo_width = MAX ((int)(page->page->getWidth() * scale + 0.5), 1);
cairo_height = MAX ((int)(page->page->getHeight() * scale + 0.5), 1);
cairo_rowstride = cairo_width * 4;
cairo_data = (guchar *) gmalloc (cairo_height * cairo_rowstride);
memset (cairo_data, 0xff, cairo_height * cairo_rowstride);
surface = cairo_image_surface_create_for_data(cairo_data,
CAIRO_FORMAT_ARGB32,
cairo_width, cairo_height,
cairo_rowstride);
output_dev->setSurface (surface);
page->page->displaySlice(output_dev, 72.0 * scale, 72.0 * scale, page->page->displaySlice(output_dev, 72.0 * scale, 72.0 * scale,
poppler_page_get_rotate (page), poppler_page_get_rotate (page),
gTrue, /* Crop */ gTrue, /* Crop */
...@@ -181,9 +193,6 @@ cairo_render_to_pixbuf (PopplerPage *page, ...@@ -181,9 +193,6 @@ cairo_render_to_pixbuf (PopplerPage *page,
NULL, /* links */ NULL, /* links */
page->document->doc->getCatalog ()); page->document->doc->getCatalog ());
output_dev->getBitmap (&cairo_data,
&cairo_width, &cairo_height, &cairo_rowstride);
pixbuf_data = gdk_pixbuf_get_pixels (pixbuf); pixbuf_data = gdk_pixbuf_get_pixels (pixbuf);
pixbuf_rowstride = gdk_pixbuf_get_rowstride (pixbuf); pixbuf_rowstride = gdk_pixbuf_get_rowstride (pixbuf);
pixbuf_n_channels = gdk_pixbuf_get_n_channels (pixbuf); pixbuf_n_channels = gdk_pixbuf_get_n_channels (pixbuf);
...@@ -209,6 +218,10 @@ cairo_render_to_pixbuf (PopplerPage *page, ...@@ -209,6 +218,10 @@ cairo_render_to_pixbuf (PopplerPage *page,
src++; src++;
} }
} }
output_dev->setSurface (NULL);
cairo_surface_destroy (surface);
gfree (cairo_data);
} }
#elif defined (HAVE_SPLASH) #elif defined (HAVE_SPLASH)
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
#include <FontInfo.h> #include <FontInfo.h>
#if defined (HAVE_CAIRO) #if defined (HAVE_CAIRO)
#include <CairoOutputDevImage.h> #include <CairoOutputDev.h>
#elif defined (HAVE_SPLASH) #elif defined (HAVE_SPLASH)
#include <SplashOutputDev.h> #include <SplashOutputDev.h>
#endif #endif
...@@ -19,7 +19,7 @@ struct _PopplerDocument ...@@ -19,7 +19,7 @@ struct _PopplerDocument
PDFDoc *doc; PDFDoc *doc;
#if defined (HAVE_CAIRO) #if defined (HAVE_CAIRO)
CairoOutputDevImage *output_dev; CairoOutputDev *output_dev;
#elif defined (HAVE_SPLASH) #elif defined (HAVE_SPLASH)
SplashOutputDev *output_dev; SplashOutputDev *output_dev;
#endif #endif
......
...@@ -48,20 +48,27 @@ ...@@ -48,20 +48,27 @@
// CairoOutputDev // CairoOutputDev
//------------------------------------------------------------------------ //------------------------------------------------------------------------
CairoOutputDev::CairoOutputDev(void) { CairoOutputDev::CairoOutputDev() {
xref = NULL; xref = NULL;
FT_Init_FreeType(&ft_lib); FT_Init_FreeType(&ft_lib);
fontEngine = NULL; fontEngine = NULL;
surface = NULL;
} }
CairoOutputDev::~CairoOutputDev() { CairoOutputDev::~CairoOutputDev() {
if (fontEngine) { if (fontEngine) {
delete fontEngine; delete fontEngine;
} }
cairo_destroy (cairo);
FT_Done_FreeType(ft_lib); FT_Done_FreeType(ft_lib);
cairo_surface_destroy (surface);
}
void CairoOutputDev::setSurface(cairo_surface_t *surface)
{
cairo_surface_destroy (this->surface);
cairo_surface_reference (surface);
this->surface = surface;
} }
void CairoOutputDev::startDoc(XRef *xrefA) { void CairoOutputDev::startDoc(XRef *xrefA) {
...@@ -73,20 +80,11 @@ void CairoOutputDev::startDoc(XRef *xrefA) { ...@@ -73,20 +80,11 @@ void CairoOutputDev::startDoc(XRef *xrefA) {
} }
void CairoOutputDev::startPage(int pageNum, GfxState *state) { void CairoOutputDev::startPage(int pageNum, GfxState *state) {
cairo_destroy (cairo); cairo = cairo_create (surface);
createCairo (state);
cairo_reset_clip (cairo);
cairo_set_source_rgb (cairo, 0, 0, 0);
cairo_set_operator (cairo, CAIRO_OPERATOR_OVER);
cairo_set_line_cap (cairo, CAIRO_LINE_CAP_BUTT);
cairo_set_line_join (cairo, CAIRO_LINE_JOIN_MITER);
cairo_set_dash (cairo, NULL, 0, 0.0);
cairo_set_miter_limit (cairo, 10);
// cairo_set_tolerance (cairo, 1);
} }
void CairoOutputDev::endPage() { void CairoOutputDev::endPage() {
cairo_destroy (cairo);
} }
void CairoOutputDev::drawLink(Link *link, Catalog *catalog) { void CairoOutputDev::drawLink(Link *link, Catalog *catalog) {
......
...@@ -36,7 +36,7 @@ class CairoOutputDev: public OutputDev { ...@@ -36,7 +36,7 @@ class CairoOutputDev: public OutputDev {
public: public:
// Constructor. // Constructor.
CairoOutputDev(void); CairoOutputDev();
// Destructor. // Destructor.
virtual ~CairoOutputDev(); virtual ~CairoOutputDev();
...@@ -130,8 +130,9 @@ public: ...@@ -130,8 +130,9 @@ public:
GBool isReverseVideo() { return gFalse; } GBool isReverseVideo() { return gFalse; }
void setSurface (cairo_surface_t *surface);
protected: protected:
virtual void createCairo(GfxState *state) = 0;
void doPath(GfxState *state, GfxPath *path, GBool snapToGrid); void doPath(GfxState *state, GfxPath *path, GBool snapToGrid);
GfxRGB fill_color; GfxRGB fill_color;
...@@ -144,10 +145,9 @@ protected: ...@@ -144,10 +145,9 @@ protected:
FT_Library ft_lib; FT_Library ft_lib;
CairoFontEngine *fontEngine; CairoFontEngine *fontEngine;
unsigned char *pixels;
int pixels_w, pixels_h;
cairo_t *cairo; cairo_t *cairo;
GBool needFontUpdate; // set when the font needs to be updated GBool needFontUpdate; // set when the font needs to be updated
cairo_surface_t *surface;
cairo_glyph_t *glyphs; cairo_glyph_t *glyphs;
int glyphCount; int glyphCount;
}; };
......
//========================================================================
//
// CairoOutputDevImage.cc
//
// Copyright 2003 Glyph & Cog, LLC
// Copyright 2004 Red Hat, Inc
//
//========================================================================
#include <config.h>
#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
#include <string.h>
#include <math.h>
#include <cairo.h>
#include "goo/gfile.h"
#include "GlobalParams.h"
#include "Error.h"
#include "Object.h"
#include <fofi/FoFiTrueType.h>
#include "CairoOutputDevImage.h"
//------------------------------------------------------------------------
// CairoOutputDevImage
//------------------------------------------------------------------------
CairoOutputDevImage::CairoOutputDevImage(void) {
pixels = NULL;
createCairo (NULL);
}
CairoOutputDevImage::~CairoOutputDevImage() {
gfree (pixels);
}
void
CairoOutputDevImage::createCairo(GfxState *state) {
int w, h;
cairo_surface_t* surface;
w = state ? (int)(state->getPageWidth() + 0.5) : 1;
h = state ? (int)(state->getPageHeight() + 0.5) : 1;
if (!pixels || w != pixels_w || h != pixels_h) {
if (pixels) {
gfree(pixels);
}
pixels_w = w;
pixels_h = h;
pixels = (unsigned char *)gmalloc (pixels_w * pixels_h * 4);
}
memset (pixels, 0xff, pixels_w * pixels_h * 4);
surface = cairo_image_surface_create_for_data(pixels, CAIRO_FORMAT_ARGB32,
pixels_w, pixels_h,
pixels_w*4);
cairo = cairo_create (surface);
cairo_surface_destroy (surface);
}
void CairoOutputDevImage::getBitmap(unsigned char **data,
int *width, int *height,
int *rowstride) {
int w, h;
unsigned char *src;
unsigned int *dest;
*data = pixels;
*width = pixels_w;
*height = pixels_h;
*rowstride = 4 * pixels_w;
}
//========================================================================
//
// CairoOutputDevImage.h
//
// Copyright 2003 Glyph & Cog, LLC
// Copyright 2004 Red Hat, INC
//
//========================================================================
#ifndef CAIROOUTPUTDEVIMAGE_H
#define CAIROOUTPUTDEVIMAGE_H
#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
#include "splash/SplashTypes.h"
#include "CairoOutputDev.h"
#include "GfxState.h"
//------------------------------------------------------------------------
// CairoOutputDevImage
//------------------------------------------------------------------------
class CairoOutputDevImage: public CairoOutputDev {
public:
// Constructor.
CairoOutputDevImage(void);
// Destructor.
virtual ~CairoOutputDevImage();
virtual void createCairo(GfxState *state);
void getBitmap(unsigned char **data,
int *width, int *height, int *rowstride);
private:
unsigned char *pixels;
int pixels_w, pixels_h;
};
#endif
//========================================================================
//
// CairoOutputDevX.cc
//
// Copyright 2003 Glyph & Cog, LLC
// Copyright 2004 Red Hat, Inc
//
//========================================================================
#include <config.h>
#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
#include <string.h>
#include <math.h>
#include <cairo.h>
#include <cairo/cairo-xlib.h>
#include <X11/Xutil.h>
#include "goo/gfile.h"
#include "GlobalParams.h"
#include "Error.h"
#include "Object.h"
#include <fofi/FoFiTrueType.h>
#include <splash/SplashBitmap.h>
#include "TextOutputDev.h"
#include "CairoOutputDevX.h"
//------------------------------------------------------------------------
// CairoOutputDevX
//------------------------------------------------------------------------
CairoOutputDevX::CairoOutputDevX(Display *displayA, int screenNumA,
Visual *visualA, Colormap colormapA,
GBool reverseVideoA, SplashColor paperColorA,
GBool installCmapA, int rgbCubeSizeA,
GBool incrementalUpdateA,
void (*redrawCbkA)(void *data),
void *redrawCbkDataA) {
XVisualInfo visualTempl;
XVisualInfo *visualList;
int nVisuals;
pixmap = 0;
pixmap_w = 1;
pixmap_h = 1;
incrementalUpdate = incrementalUpdateA;
redrawCbk = redrawCbkA;
redrawCbkData = redrawCbkDataA;
//----- set up the X color stuff
display = displayA;
screenNum = screenNumA;
visual = visualA;
// check for TrueColor visual
//~ this should scan the list, not just look at the first one
visualTempl.visualid = XVisualIDFromVisual(visual);
visualList = XGetVisualInfo(display, VisualIDMask,
&visualTempl, &nVisuals);
if (nVisuals < 1) {
// this shouldn't happen
XFree((XPointer)visualList);
visualList = XGetVisualInfo(display, VisualNoMask, &visualTempl,
&nVisuals);
}
depth = visualList->depth;
XFree((XPointer)visualList);
text = new TextPage(gFalse);
createCairo (NULL);
}
CairoOutputDevX::~CairoOutputDevX() {
delete text;
}
void
CairoOutputDevX::createCairo(GfxState *state) {
int w, h;
XGCValues gcv;
GC gc;
cairo_surface_t *surface;
w = state ? (int)(state->getPageWidth() + 0.5) : 1;
h = state ? (int)(state->getPageHeight() + 0.5) : 1;
if (!pixmap || w != pixmap_w || h != pixmap_h) {
if (pixmap) {
XFreePixmap(display, pixmap);
}
pixmap_w = w;
pixmap_h = h;
Window window =
XCreateSimpleWindow(display, RootWindow (display, screenNum), 0, 0, 1, 1, 0,
WhitePixel(display, screenNum), WhitePixel(display, screenNum));
pixmap = XCreatePixmap(display, window, w, h,
depth);
XDestroyWindow (display, window);
}
gcv.foreground = WhitePixel(display, screenNum);
gc = XCreateGC(display, pixmap, GCForeground, &gcv);
XFillRectangle(display, pixmap, gc, 0, 0, w, h);
surface = cairo_xlib_surface_create(display, pixmap,
DefaultVisual(display, DefaultScreen(display)),
w, h);
cairo = cairo_create (surface);
cairo_surface_destroy (surface);
XFreeGC(display, gc);
}
void CairoOutputDevX::drawChar(GfxState *state, double x, double y,
double dx, double dy,
double originX, double originY,
CharCode code, Unicode *u, int uLen) {
text->addChar(state, x, y, dx, dy, code, u, uLen);
CairoOutputDev::drawChar(state, x, y, dx, dy, originX, originY,
code, u, uLen);
}
GBool CairoOutputDevX::beginType3Char(GfxState *state, double x, double y,
double dx, double dy,
CharCode code, Unicode *u, int uLen) {
text->addChar(state, x, y, dx, dy, code, u, uLen);
return CairoOutputDev::beginType3Char(state, x, y, dx, dy, code, u, uLen);
}
int CairoOutputDevX::getBitmapWidth() {
return pixmap_w;
};
int CairoOutputDevX::getBitmapHeight() {
return pixmap_h;
};
void CairoOutputDevX::clear() {
startDoc(NULL);
startPage(0, NULL);
}
void CairoOutputDevX::startPage(int pageNum, GfxState *state) {
CairoOutputDev::startPage(pageNum, state);
text->startPage(state);
}
void CairoOutputDevX::updateFont(GfxState *state) {
CairoOutputDev::updateFont(state);
text->updateFont(state);
}
void CairoOutputDevX::endPage() {
CairoOutputDev::endPage();
if (!incrementalUpdate) {
(*redrawCbk)(redrawCbkData);
}
text->coalesce(gTrue);
}
void CairoOutputDevX::dump() {
if (incrementalUpdate) {
(*redrawCbk)(redrawCbkData);
}
}
void CairoOutputDevX::redraw(int srcX, int srcY,
Drawable destDrawable, GC destGC,
int destX, int destY,
int width, int height) {
XCopyArea(display, pixmap, destDrawable, destGC,
srcX, srcY, width, height,
destX, destY);
}
#define xoutRound(x) ((int)((x) + 0.5))
GBool CairoOutputDevX::findText(Unicode *s, int len,
GBool startAtTop, GBool stopAtBottom,
GBool startAtLast, GBool stopAtLast,
int *xMin, int *yMin,
int *xMax, int *yMax) {
double xMin1, yMin1, xMax1, yMax1;
xMin1 = (double)*xMin;
yMin1 = (double)*yMin;
xMax1 = (double)*xMax;
yMax1 = (double)*yMax;
if (text->findText(s, len, startAtTop, stopAtBottom,
startAtLast, stopAtLast,
&xMin1, &yMin1, &xMax1, &yMax1)) {
*xMin = xoutRound(xMin1);
*xMax = xoutRound(xMax1);
*yMin = xoutRound(yMin1);
*yMax = xoutRound(yMax1);
return gTrue;
}
return gFalse;
}
GooString *CairoOutputDevX::getText(int xMin, int yMin, int xMax, int yMax) {
return text->getText((double)xMin, (double)yMin,
(double)xMax, (double)yMax);
}
void CairoOutputDevX::xorRectangle(int x0, int y0, int x1, int y1,
SplashPattern *pattern) {
return;
}
//========================================================================
//
// CairoOutputDevX.h
//
// Copyright 2003 Glyph & Cog, LLC
// Copyright 2004 Red Hat, INC
//
//========================================================================
#ifndef CAIROOUTPUTDEVX_H
#define CAIROOUTPUTDEVX_H
#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
#include <X11/Xlib.h>
#include "CairoOutputDev.h"
#include "GfxState.h"
#include "splash/SplashTypes.h"
class SplashPattern;
//------------------------------------------------------------------------
// CairoOutputDevX
//------------------------------------------------------------------------
class CairoOutputDevX: public CairoOutputDev {
public:
// Constructor.
CairoOutputDevX(Display *displayA, int screenNumA,
Visual *visualA, Colormap colormapA,
GBool reverseVideoA, SplashColor paperColorA,
GBool installCmapA, int rgbCubeSizeA,
GBool incrementalUpdateA,
void (*redrawCbkA)(void *data),
void *redrawCbkDataA);
// Destructor.
virtual ~CairoOutputDevX();
// End a page.
virtual void endPage();
// Dump page contents to display.
virtual void dump();
//----- special access
int getBitmapWidth();
int getBitmapHeight();
// 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,
Drawable destDrawable, GC destGC,
int destX, int destY,
int width, int height);
virtual void drawChar(GfxState *state, double x, double y,
double dx, double dy,
double originX, double originY,
CharCode code, Unicode *u, int uLen);
virtual GBool beginType3Char(GfxState *state, double x, double y,
double dx, double dy,
CharCode code, Unicode *u, int uLen);
virtual void startPage(int pageNum, GfxState *state);
virtual void updateFont(GfxState *state);
// Find a string. If <startAtTop> is true, starts looking at the
// top of the page; else if <startAtLast> is true, starts looking
// immediately after the last find result; else starts looking at
// <xMin>,<yMin>. If <stopAtBottom> is true, stops looking at the
// bottom of the page; else if <stopAtLast> is true, stops looking
// just before the last find result; else stops looking at
// <xMax>,<yMax>.
GBool findText(Unicode *s, int len,
GBool startAtTop, GBool stopAtBottom,
GBool startAtLast, GBool stopAtLast,
int *xMin, int *yMin,
int *xMax, int *yMax);
// Get the text which is inside the specified rectangle.
GooString *getText(int xMin, int yMin, int xMax, int yMax);
// XOR a rectangular region in the bitmap with <pattern>. <pattern>
// is passed to Splash::setFillPattern, so it should not be used
// after calling this function.
void xorRectangle(int x0, int y0, int x1, int y1, SplashPattern *pattern);
private:
virtual void createCairo(GfxState *state);