You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdegraphics/kfile-plugins/pdf/poppler-qt/poppler-page.cc

363 lines
10 KiB

/* poppler-page.cc: qt interface to poppler
* Copyright (C) 2005, Net Integration Technologies, Inc.
* Copyright (C) 2005-2006, Albert Astals Cid <aacid@kde.org>
* Copyright (C) 2005, Tobias Koening <tokoe@kde.org>
* Copyright (C) 2005, Stefan Kebekus <stefan.kebekus@math.uni-koeln.de>
* Copyright (C) 2006, Wilfried Huss <Wilfried.Huss@gmx.at>
* Copyright (C) 2006, Jerry Epplin <jepplin@globalvelocity.com>
* Copyright (C) 2007, 2010, Pino Toscano <pino@kde.org>
*
* 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <poppler-qt.h>
#include <qfile.h>
#include <qimage.h>
#include <config.h>
#include <GlobalParams.h>
#include <PDFDoc.h>
#include <Catalog.h>
#include <ErrorCodes.h>
#include <TextOutputDev.h>
#include <Link.h>
#if defined(HAVE_SPLASH)
#include <SplashOutputDev.h>
#include <splash/SplashBitmap.h>
#endif
#include "poppler-private.h"
#include "poppler-page-transition-private.h"
namespace Poppler {
class PageData {
public:
const Document *doc;
int index;
PageTransition *transition;
};
Page::Page(const Document *doc, int index) {
data = new PageData();
data->index = index;
data->doc = doc;
data->transition = 0;
}
Page::~Page()
{
delete data->transition;
delete data;
}
void Page::renderToPixmap(QPixmap **q, int x, int y, int w, int h, bool doLinks) const
{
renderToPixmap(q, x, y, w, h, 72.0, 72.0, doLinks);
}
void Page::renderToPixmap(QPixmap **q, int x, int y, int w, int h, double xres, double yres, bool doLinks) const
{
QImage img = renderToImage(xres, yres, doLinks);
*q = new QPixmap( img );
}
QImage Page::renderToImage(double xres, double yres, bool doLinks) const
{
#if defined(HAVE_SPLASH)
SplashOutputDev *output_dev;
SplashBitmap *bitmap;
SplashColorPtr color_ptr;
output_dev = data->doc->data->getOutputDev();
data->doc->data->doc.displayPageSlice(output_dev, data->index + 1, xres, yres,
0, false, true, false, -1, -1, -1, -1);
bitmap = output_dev->getBitmap ();
color_ptr = bitmap->getDataPtr ();
int bw = output_dev->getBitmap()->getWidth();
int bh = output_dev->getBitmap()->getHeight();
SplashColorPtr dataPtr = output_dev->getBitmap()->getDataPtr();
if (QImage::BigEndian == QImage::systemByteOrder())
{
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;
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, 32, 0, 0, QImage::IgnoreEndian );
img = img.copy();
// unload underlying xpdf bitmap
output_dev->startPage( 0, NULL );
return img;
#else
(void)xres;
(void)xres;
(void)doLinks;
return QImage();
#endif
}
QString Page::getText(const Rectangle &r) const
{
TextOutputDev *output_dev;
GooString *s;
PDFRectangle *rect;
QString result;
::Page *p;
output_dev = new TextOutputDev(0, gFalse, gFalse, gFalse);
data->doc->data->doc.displayPageSlice(output_dev, data->index + 1, 72, 72,
0, false, false, false, -1, -1, -1, -1);
p = data->doc->data->doc.getCatalog()->getPage(data->index + 1);
if (r.isNull())
{
rect = p->getCropBox();
s = output_dev->getText(rect->x1, rect->y1, rect->x2, rect->y2);
}
else
{
double height, y1, y2;
height = p->getCropHeight();
y1 = height - r.m_y2;
y2 = height - r.m_y1;
s = output_dev->getText(r.m_x1, y1, r.m_x2, y2);
}
result = QString::fromUtf8(s->getCString());
delete output_dev;
delete s;
return result;
}
QValueList<TextBox*> Page::textList() const
{
TextOutputDev *output_dev;
QValueList<TextBox*> output_list;
output_dev = new TextOutputDev(0, gFalse, gFalse, gFalse);
data->doc->data->doc.displayPageSlice(output_dev, data->index + 1, 72, 72,
0, false, false, false, -1, -1, -1, -1);
TextWordList *word_list = output_dev->makeWordList();
if (!word_list) {
delete output_dev;
return output_list;
}
for (int i = 0; i < word_list->getLength(); i++) {
TextWord *word = word_list->get(i);
GooString *word_str = word->getText();
QString string = QString::fromUtf8(word_str->getCString());
delete word_str;
double xMin, yMin, xMax, yMax;
word->getBBox(&xMin, &yMin, &xMax, &yMax);
TextBox* text_box = new TextBox(string, Rectangle(xMin, yMin, xMax, yMax));
output_list.append(text_box);
}
delete word_list;
delete output_dev;
return output_list;
}
PageTransition *Page::getTransition() const
{
if (!data->transition)
{
Object o;
PageTransitionParams params;
params.dictObj = data->doc->data->doc.getCatalog()->getPage(data->index + 1)->getTrans(&o);
data->transition = new PageTransition(params);
o.free();
}
return data->transition;
}
QSize Page::pageSize() const
{
::Page *p;
p = data->doc->data->doc.getCatalog()->getPage(data->index + 1);
if ( ( Page::Landscape == orientation() ) || (Page::Seascape == orientation() ) ) {
return QSize( (int)p->getCropHeight(), (int)p->getCropWidth() );
} else {
return QSize( (int)p->getCropWidth(), (int)p->getCropHeight() );
}
}
Page::Orientation Page::orientation() const
{
::Page *p = data->doc->data->doc.getCatalog()->getPage(data->index + 1);
int rotation = p->getRotate();
switch (rotation) {
case 90:
return Page::Landscape;
break;
case 180:
return Page::UpsideDown;
break;
case 270:
return Page::Seascape;
break;
default:
return Page::Portrait;
}
}
QValueList<Link*> Page::links() const
{
QValueList<Link*> popplerLinks;
#if defined(HAVE_SPLASH)
Links *xpdfLinks = data->doc->data->doc.getLinks(data->index + 1);
for (int i = 0; i < xpdfLinks->getNumLinks(); ++i)
{
::Link *xpdfLink = xpdfLinks->getLink(i);
double left, top, right, bottom;
int leftAux, topAux, rightAux, bottomAux;
xpdfLink->getRect( &left, &top, &right, &bottom );
QRect linkArea;
data->doc->data->m_outputDev->cvtUserToDev( left, top, &leftAux, &topAux );
data->doc->data->m_outputDev->cvtUserToDev( right, bottom, &rightAux, &bottomAux );
linkArea.setLeft(leftAux);
linkArea.setTop(topAux);
linkArea.setRight(rightAux);
linkArea.setBottom(bottomAux);
if (!xpdfLink->isOk()) continue;
Link *popplerLink = NULL;
::LinkAction *a = xpdfLink->getAction();
if ( a )
{
switch ( a->getKind() )
{
case actionGoTo:
{
LinkGoTo * g = (LinkGoTo *) a;
// create link: no ext file, namedDest, object pointer
popplerLink = new LinkGoto( linkArea, QString::null, LinkDestination( LinkDestinationData(g->getDest(), g->getNamedDest(), data->doc->data ) ) );
}
break;
case actionGoToR:
{
LinkGoToR * g = (LinkGoToR *) a;
// copy link file
const QString fileName = UnicodeParsedString( g->getFileName() );
// ceate link: fileName, namedDest, object pointer
popplerLink = new LinkGoto( linkArea, fileName, LinkDestination( LinkDestinationData(g->getDest(), g->getNamedDest(), data->doc->data ) ) );
}
break;
case actionLaunch:
{
LinkLaunch * e = (LinkLaunch *)a;
GooString * p = e->getParams();
popplerLink = new LinkExecute( linkArea, e->getFileName()->getCString(), p ? p->getCString() : 0 );
}
break;
case actionNamed:
{
const char * name = ((LinkNamed *)a)->getName()->getCString();
if ( !strcmp( name, "NextPage" ) )
popplerLink = new LinkAction( linkArea, LinkAction::PageNext );
else if ( !strcmp( name, "PrevPage" ) )
popplerLink = new LinkAction( linkArea, LinkAction::PagePrev );
else if ( !strcmp( name, "FirstPage" ) )
popplerLink = new LinkAction( linkArea, LinkAction::PageFirst );
else if ( !strcmp( name, "LastPage" ) )
popplerLink = new LinkAction( linkArea, LinkAction::PageLast );
else if ( !strcmp( name, "GoBack" ) )
popplerLink = new LinkAction( linkArea, LinkAction::HistoryBack );
else if ( !strcmp( name, "GoForward" ) )
popplerLink = new LinkAction( linkArea, LinkAction::HistoryForward );
else if ( !strcmp( name, "Quit" ) )
popplerLink = new LinkAction( linkArea, LinkAction::Quit );
else if ( !strcmp( name, "GoToPage" ) )
popplerLink = new LinkAction( linkArea, LinkAction::GoToPage );
else if ( !strcmp( name, "Find" ) )
popplerLink = new LinkAction( linkArea, LinkAction::Find );
else if ( !strcmp( name, "FullScreen" ) )
popplerLink = new LinkAction( linkArea, LinkAction::Presentation );
else if ( !strcmp( name, "Close" ) )
{
// acroread closes the document always, doesnt care whether
// its presentation mode or not
// popplerLink = new LinkAction( linkArea, LinkAction::EndPresentation );
popplerLink = new LinkAction( linkArea, LinkAction::Close );
}
else
{
// TODO
}
}
break;
case actionURI:
{
popplerLink = new LinkBrowse( linkArea, ((LinkURI *)a)->getURI()->getCString() );
}
break;
case actionMovie:
case actionSound:
case actionRendition:
case actionJavaScript:
case actionOCGState:
break;
case actionUnknown:
break;
}
}
if (popplerLink)
{
popplerLinks.append(popplerLink);
}
}
delete xpdfLinks;
#endif
return popplerLinks;
}
}