Commit e68b6f3f authored by Albert Astals Cid's avatar Albert Astals Cid

2006-11-15 Albert Astals Cid <aacid@kde.org>

        * qt4/src/poppler-link.cc:
        * qt4/src/poppler-page.cc:
        * qt4/src/poppler-qt4.h:
        * qt4/src/poppler-document.cc:
        * qt4/src/poppler-private.h: Generalize the way we render the pages:
        merge all the Page::renderTo* functions in only one that renders on
        a QImage, taking into account the currently chosen backend.
        It is possible to switch rendering backend using the Document.
        Patch by Pino Toscano.

        * qt4/tests/stress-poppler-qt4.cpp:
        * qt4/tests/test-password-qt4.cpp:
        * qt4/tests/test-poppler-qt4.cpp: Adapt the tests to the changes in
        the rendering API of Page. Patch by Pino Toscano.
parent 37088dd3
2006-11-15 Albert Astals Cid <aacid@kde.org>
* qt4/src/poppler-link.cc:
* qt4/src/poppler-page.cc:
* qt4/src/poppler-qt4.h:
* qt4/src/poppler-document.cc:
* qt4/src/poppler-private.h: Generalize the way we render the pages:
merge all the Page::renderTo* functions in only one that renders on
a QImage, taking into account the currently chosen backend.
It is possible to switch rendering backend using the Document.
Patch by Pino Toscano.
* qt4/tests/stress-poppler-qt4.cpp:
* qt4/tests/test-password-qt4.cpp:
* qt4/tests/test-poppler-qt4.cpp: Adapt the tests to the changes in
the rendering API of Page. Patch by Pino Toscano.
2006-11-13 Albert Astals Cid <aacid@kde.org>
* poppler/ArthurOutputDev.cc: Small fix to get colors right
......
......@@ -417,6 +417,20 @@ namespace Poppler {
return m_doc->paperColor;
}
void Document::setRenderBackend( Document::RenderBackend backend )
{
// no need to delete the outputdev as for the moment we always create a splash one
// as the arthur one does not allow "precaching" due to it's signature
// delete m_doc->m_outputDev;
// m_doc->m_outputDev = NULL;
m_doc->m_backend = backend;
}
Document::RenderBackend Document::renderBackend() const
{
return m_doc->m_backend;
}
QDateTime convertDate( char *dateString )
{
int year;
......
......@@ -64,7 +64,7 @@ namespace Poppler {
int leftAux, topAux, rightAux, bottomAux;
SplashOutputDev *sod = data.doc->getSplashOutputDev();
OutputDev *sod = data.doc->getOutputDev();
sod->cvtUserToDev( left, top, &leftAux, &topAux );
sod->cvtUserToDev( right, bottom, &rightAux, &bottomAux );
......
......@@ -21,7 +21,7 @@
#include <QtCore/QFile>
#include <QtCore/QMap>
#include <QtGui/QImage>
#include <QtGui/QPixmap>
#include <QtGui/QPainter>
#include <GlobalParams.h>
#include <PDFDoc.h>
#include <Catalog.h>
......@@ -161,75 +161,81 @@ Page::~Page()
delete m_page;
}
QImage Page::splashRenderToImage(double xres, double yres, int x, int y, int w, int h, bool doLinks, Rotation rotate) const
QImage Page::renderToImage(double xres, double yres, int x, int y, int w, int h, bool doLinks, Rotation rotate) const
{
SplashOutputDev *output_dev = m_page->parentDoc->m_doc->getSplashOutputDev();
int rotation = (int)rotate * 90;
m_page->parentDoc->m_doc->doc.displayPageSlice(output_dev, m_page->index + 1, xres, yres,
rotation, false, true, doLinks, x, y, w, h);
SplashBitmap *bitmap = output_dev->getBitmap ();
int bw = bitmap->getWidth();
int bh = bitmap->getHeight();
SplashColorPtr dataPtr = output_dev->getBitmap()->getDataPtr();
if (QSysInfo::BigEndian == QSysInfo::ByteOrder)
QImage img;
switch(m_page->parentDoc->m_doc->m_backend)
{
uchar c;
int count = bw * bh * 4;
for (int k = 0; k < count; k += 4)
case Poppler::Document::SplashBackend:
{
c = dataPtr[k];
dataPtr[k] = dataPtr[k+3];
dataPtr[k+3] = c;
SplashOutputDev *splash_output = static_cast<SplashOutputDev *>(m_page->parentDoc->m_doc->getOutputDev());
c = dataPtr[k+1];
dataPtr[k+1] = dataPtr[k+2];
dataPtr[k+2] = c;
}
}
// construct a qimage SHARING the raw bitmap data in memory
QImage img( dataPtr, bw, bh, QImage::Format_ARGB32 );
img = img.copy();
// unload underlying xpdf bitmap
output_dev->startPage( 0, NULL );
m_page->parentDoc->m_doc->doc.displayPageSlice(splash_output, m_page->index + 1, xres, yres,
rotation, false, true, doLinks, x, y, w, h);
return img;
}
SplashBitmap *bitmap = splash_output->getBitmap();
int bw = bitmap->getWidth();
int bh = bitmap->getHeight();
QPixmap *Page::splashRenderToPixmap(double xres, double yres, int x, int y, int w, int h, bool doLinks, Rotation rotate) const
{
QImage img = splashRenderToImage(xres, yres, x, y, w, h, doLinks, rotate);
SplashColorPtr dataPtr = splash_output->getBitmap()->getDataPtr();
// Turn the QImage into a QPixmap
QPixmap* out = new QPixmap(QPixmap::fromImage(img));
if (QSysInfo::BigEndian == QSysInfo::ByteOrder)
{
uchar c;
int count = bw * bh * 4;
for (int k = 0; k < count; k += 4)
{
c = dataPtr[k];
dataPtr[k] = dataPtr[k+3];
dataPtr[k+3] = c;
return out;
}
c = dataPtr[k+1];
dataPtr[k+1] = dataPtr[k+2];
dataPtr[k+2] = c;
}
}
void Page::renderToPixmap(QPixmap *pixmap, double xres, double yres) const
{
QPainter* painter = new QPainter(pixmap);
painter->setRenderHint(QPainter::Antialiasing);
ArthurOutputDev output_dev(painter);
output_dev.startDoc(m_page->parentDoc->m_doc->doc.getXRef ());
m_page->parentDoc->m_doc->doc.displayPageSlice(&output_dev,
// construct a qimage SHARING the raw bitmap data in memory
QImage tmpimg( dataPtr, bw, bh, QImage::Format_ARGB32 );
img = tmpimg.copy();
// unload underlying xpdf bitmap
splash_output->startPage( 0, NULL );
break;
}
case Poppler::Document::ArthurBackend:
{
QSize size = pageSize();
QImage tmpimg(w == -1 ? size.width() : w, h == -1 ? size.height() : h, QImage::Format_ARGB32);
QPainter painter(&tmpimg);
painter.setRenderHint(QPainter::Antialiasing);
painter.save();
painter.translate(x == -1 ? 0 : -x, y == -1 ? 0 : -y);
if (w == -1 && h == -1)
painter.scale((double)w/(double)size.width(), (double)h/(double)size.height());
ArthurOutputDev arthur_output(&painter);
arthur_output.startDoc(m_page->parentDoc->m_doc->doc.getXRef());
m_page->parentDoc->m_doc->doc.displayPageSlice(&arthur_output,
m_page->index + 1,
xres,
yres,
0,
rotation,
false,
true,
false,
-1,
-1,
-1,
-1);
painter->end();
doLinks,
x,
y,
w,
h);
painter.restore();
painter.end();
img = tmpimg;
break;
}
}
return img;
}
QString Page::text(const QRectF &r) const
......@@ -412,7 +418,7 @@ QSizeF Page::pageSizeF() const
QSize Page::pageSize() const
{
return QSize( (int)pageSizeF().width(), (int)pageSizeF().height() );
return pageSizeF().toSize();
}
Page::Orientation Page::orientation() const
......@@ -454,8 +460,9 @@ QList<Link*> Page::links() const
xpdfLink->getRect( &left, &top, &right, &bottom );
QRectF linkArea;
m_page->parentDoc->m_doc->m_splashOutputDev->cvtUserToDev( left, top, &leftAux, &topAux );
m_page->parentDoc->m_doc->m_splashOutputDev->cvtUserToDev( right, bottom, &rightAux, &bottomAux );
OutputDev *output_dev = m_page->parentDoc->m_doc->getOutputDev();
output_dev->cvtUserToDev( left, top, &leftAux, &topAux );
output_dev->cvtUserToDev( right, bottom, &rightAux, &bottomAux );
linkArea.setLeft(leftAux);
linkArea.setTop(topAux);
linkArea.setRight(rightAux);
......
......@@ -66,7 +66,8 @@ namespace Poppler {
class DocumentData {
public:
DocumentData(GooString *filePath, GooString *ownerPassword, GooString *userPassword) :
doc(filePath, ownerPassword, userPassword), m_fontInfoScanner(0), m_splashOutputDev(0)
doc(filePath, ownerPassword, userPassword), m_fontInfoScanner(0),
m_backend(Document::SplashBackend), m_outputDev(0)
{
paperColor = Qt::white;
// It might be more appropriate to delete these in PDFDoc
......@@ -80,25 +81,35 @@ namespace Poppler {
~DocumentData()
{
qDeleteAll(m_embeddedFiles);
delete m_splashOutputDev;
delete m_outputDev;
delete m_fontInfoScanner;
count --;
if ( count == 0 ) delete globalParams;
}
SplashOutputDev *getSplashOutputDev()
OutputDev *getOutputDev()
{
if (!m_splashOutputDev)
if (!m_outputDev)
{
switch (m_backend)
{
case Document::ArthurBackend:
// create a splash backend even in case of the Arthur Backend
case Document::SplashBackend:
{
SplashColor bgColor;
bgColor[0] = paperColor.red();
bgColor[1] = paperColor.green();
bgColor[2] = paperColor.blue();
m_splashOutputDev = new SplashOutputDev(splashModeRGB8Qt, 4, gFalse, bgColor);
m_splashOutputDev->startDoc(doc.getXRef());
SplashOutputDev * splashOutputDev = new SplashOutputDev(splashModeRGB8Qt, 4, gFalse, bgColor);
splashOutputDev->startDoc(doc.getXRef());
m_outputDev = splashOutputDev;
break;
}
}
}
return m_splashOutputDev;
return m_outputDev;
}
void addTocChildren( QDomDocument * docSyn, QDomNode * parent, GooList * items )
......@@ -161,8 +172,8 @@ namespace Poppler {
if (color != paperColor)
{
paperColor = color;
delete m_splashOutputDev;
m_splashOutputDev = NULL;
delete m_outputDev;
m_outputDev = NULL;
}
}
......@@ -183,7 +194,8 @@ namespace Poppler {
class PDFDoc doc;
bool locked;
FontInfoScanner *m_fontInfoScanner;
SplashOutputDev *m_splashOutputDev;
Document::RenderBackend m_backend;
OutputDev *m_outputDev;
QList<EmbeddedFile*> m_embeddedFiles;
QColor paperColor;
static int count;
......
......@@ -234,18 +234,14 @@ namespace Poppler {
};
/**
Render the page to a QImage using the Splash renderer
This method can be used to render the page to a QPixmap. It
uses the "Splash" rendering engine. This method is reasonably
well-tested and has produced good output so far.
Render the page to a QImage using the specified renderer
If x=y=w=h=-1, the method will automatically compute the
size of the pixmap from the horizontal and vertical
resolutions specified in xres and yres. Otherwise, the
method renders only a part of the page, specified by the
parameters (x, y, w, h) in pixel coordinates. The QPixmap
returned then has size (w, h), independent of the page
parameters (x, y, w, h) in pixel coordinates. The returned
QImage then has size (w, h), independent of the page
size.
\param x specifies the left x-coordinate of the box, in
......@@ -274,54 +270,7 @@ namespace Poppler {
\returns a QImage of the page, or a null image on failure.
*/
QImage splashRenderToImage(double xres=72.0, double yres=72.0, int x=-1, int y=-1, int w=-1, int h=-1, bool doLinks = false, Rotation rotate = Rotate0) const;
/**
Render the page to a QPixmap using the Splash renderer
This member function is provided for convenience. It behaves essentially like the above function.
It is used as follows.
@code
Poppler::Page* pdfPage;
// Generate a QPixmap of the rendered page
QPixmap* pixmap = pdfPage->splashRenderToPixmap(0, 0, 0, 0, xres, yres );
if (pixmap == 0) {
... error message ...
return;
}
... use pixmap ...
delete pixmap;
@endcode
*/
QPixmap *splashRenderToPixmap(double xres=72.0, double yres=72.0, int x=-1, int y=-1, int w=-1, int h=-1, bool doLinks = false, Rotation rotate = Rotate0) const;
/**
Render the page to a pixmap using the Arthur (Qt4) renderer
\param q pointer to a QPixmap that is already set to the
intended size.
\param xres horizontal resolution of the graphics device,
in dots per inch
\param yres vertical resolution of the graphics device, in
dots per inch
You are meant to create the pixmap before passing it to
this routine, using something like:
\code
QPixmap* myPixmap = new QPixmap(page->pageSize());
page->renderToPixmap(myPixmap);
\endcode
\warning This is a work in progress. Results are unlikely to be of
high quality.
*/
void renderToPixmap(QPixmap *q, double xres=72.0, double yres=72.0) const;
QImage renderToImage(double xres=72.0, double yres=72.0, int x=-1, int y=-1, int w=-1, int h=-1, bool doLinks = false, Rotation rotate = Rotate0) const;
/**
Returns the text that is inside a specified rectangle
......@@ -460,6 +409,14 @@ delete pixmap;
TwoPageRight, ///< Display the pages two at a time, with odd-numbered pages on the right
};
/**
The render backends available
*/
enum RenderBackend {
SplashBackend, ///< Splash backend
ArthurBackend, ///< Arthur (Qt4) backend
};
/**
Load the document from a file on disk
......@@ -712,6 +669,14 @@ delete pixmap;
void setPaperColor(const QColor &color);
QColor paperColor() const;
/**
Sets the backend used to render the pages.
The default backend is @ref SplashBackend
*/
void setRenderBackend( RenderBackend backend );
RenderBackend renderBackend() const;
~Document();
private:
......
......@@ -53,8 +53,7 @@ int main( int argc, char **argv )
for( int index = 0; index < doc->numPages(); ++index ) {
Poppler::Page *page = doc->page( index );
QPixmap *pixmap = new QPixmap(page->pageSize());
page->renderToPixmap(pixmap);
QImage image = page->renderToImage();
page->pageSize();
page->orientation();
delete page;
......
......@@ -17,7 +17,7 @@ protected:
private:
void display();
int m_currentPage;
QPixmap *pixmap;
QImage image;
Poppler::Document *doc;
};
......@@ -34,8 +34,7 @@ void PDFDisplay::display()
Poppler::Page *page = doc->page(m_currentPage);
if (page) {
qDebug() << "Displaying page: " << m_currentPage;
pixmap = new QPixmap(page->pageSize());
page->renderToPixmap(pixmap);
image = page->renderToImage();
update();
delete page;
}
......@@ -47,16 +46,15 @@ void PDFDisplay::display()
PDFDisplay::~PDFDisplay()
{
delete doc;
delete pixmap;
}
void PDFDisplay::paintEvent( QPaintEvent *e )
{
QPainter paint( this ); // paint widget
if (pixmap) {
paint.drawPixmap(0, 0, *pixmap);
if (!image.isNull()) {
paint.drawImage(0, 0, image);
} else {
qWarning() << "no pixmap";
qWarning() << "null image";
}
}
......
......@@ -17,7 +17,7 @@ protected:
private:
void display();
int m_currentPage;
QPixmap *pixmap;
QImage image;
Poppler::Document *doc;
bool useArthur;
};
......@@ -25,7 +25,6 @@ private:
PDFDisplay::PDFDisplay( Poppler::Document *d, bool arthur )
{
doc = d;
pixmap = 0;
m_currentPage = 0;
useArthur = arthur;
display();
......@@ -39,15 +38,14 @@ void PDFDisplay::display()
if (useArthur)
{
qDebug() << "Displaying page using Arthur backend: " << m_currentPage;
pixmap = new QPixmap(page->pageSize());
page->renderToPixmap(pixmap, 72.0, 72.0);
doc->setRenderBackend(Poppler::Document::ArthurBackend);
}
else
{
qDebug() << "Displaying page using Splash backend: " << m_currentPage;
delete pixmap;
pixmap = page->splashRenderToPixmap();
doc->setRenderBackend(Poppler::Document::SplashBackend);
}
image = page->renderToImage();
update();
delete page;
}
......@@ -59,16 +57,15 @@ void PDFDisplay::display()
PDFDisplay::~PDFDisplay()
{
delete doc;
delete pixmap;
}
void PDFDisplay::paintEvent( QPaintEvent *e )
{
QPainter paint( this ); // paint widget
if (pixmap) {
paint.drawPixmap(0, 0, *pixmap);
if (!image.isNull()) {
paint.drawImage(0, 0, image);
} else {
qWarning() << "no pixmap";
qWarning() << "null image";
}
}
......
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