Commit 33848a3e authored by Albert Astals Cid's avatar Albert Astals Cid

The big poppler commit, we now don't use poppler but poppler-qt4 frontend, and that is GOOD

You need poppler from cvs as of today, i'll change the check to a bigger version number once a new poppler gets released
There are still some problems i think but i'm commiting to see if someone wants to help ;-)
Includes some EBN fixes by Christian Mueller

svn path=/branches/work/kde4/playground/graphics/okular/; revision=540404
parent f8de9e78
......@@ -58,14 +58,15 @@ class AnnotationUtils
struct OKULAR_EXPORT Annotation
{
// enum definitions
// WARNING!!! Get that in sync with poppler enums!
enum SubType { AText = 1, ALine = 2, AGeom = 3, AHighlight = 4, AStamp = 5,
AInk = 6, A_BASE = 0 };
enum Flag { Hidden = 1, FixedSize = 2, FixedRotation = 4, DenyPrint = 8,
DenyWrite = 16, DenyDelete = 32, ToggleHidingOnMouse = 64, External = 128 };
enum LineStyle { Solid, Dashed, Beveled, Inset, Underline };
enum LineEffect { NoEffect, Cloudy };
enum RevScope { Reply, Group, Delete };
enum RevType { None, Marked, Unmarked, Accepted, Rejected, Cancelled, Completed };
enum LineStyle { Solid = 1, Dashed = 2, Beveled = 4, Inset = 8, Underline = 16 };
enum LineEffect { NoEffect = 1, Cloudy = 2};
enum RevScope { Reply = 1, Group = 2, Delete = 4 };
enum RevType { None = 1, Marked = 2, Unmarked = 4, Accepted = 8, Rejected = 16, Cancelled = 32, Completed = 64 };
/** properties: contents related */
QString author; // ''
......
......@@ -137,7 +137,7 @@ bool KPDFDocument::openDocument( const QString & docFile, const KUrl& url, const
QFile fileReadTest( docFile );
if ( !fileReadTest.open( IO_ReadOnly ) )
{
d->docFileName = QString::null;
d->docFileName.clear();
return false;
}
// determine the related "xml document-info" filename
......@@ -1526,7 +1526,7 @@ QString KPDFDocument::giveAbsolutePath( const QString & fileName )
bool KPDFDocument::openRelativeFile( const QString & fileName )
{
QString absFileName = giveAbsolutePath( fileName );
if ( absFileName.isNull() )
if ( absFileName.isEmpty() )
return false;
kDebug() << "openDocument: '" << absFileName << "'" << endl;
......@@ -1538,7 +1538,7 @@ bool KPDFDocument::openRelativeFile( const QString & fileName )
void KPDFDocument::saveDocumentInfo() const
{
if ( d->docFileName.isNull() )
if ( d->docFileName.isEmpty() )
return;
QFile infoFile( d->xmlFileName );
......
......@@ -56,7 +56,7 @@ class OKULAR_EXPORT KPDFLinkGoto : public KPDFLink
};
/** Execute: filename and parameters to execute **/
class KPDFLinkExecute : public KPDFLink
class OKULAR_EXPORT KPDFLinkExecute : public KPDFLink
{
public:
// query for filename / parameters
......@@ -90,12 +90,23 @@ class OKULAR_EXPORT KPDFLinkBrowse : public KPDFLink
};
/** Action: contains an action to perform on document / kpdf **/
class KPDFLinkAction : public KPDFLink
class OKULAR_EXPORT KPDFLinkAction : public KPDFLink
{
public:
// define types of actions
enum ActionType { PageFirst, PagePrev, PageNext, PageLast, HistoryBack, HistoryForward,
Quit, Presentation, EndPresentation, Find, GoToPage, Close };
// WARNING KEEP IN SYNC WITH POPPLER
enum ActionType { PageFirst = 1,
PagePrev = 2,
PageNext = 3,
PageLast = 4,
HistoryBack = 5,
HistoryForward = 6,
Quit = 7,
Presentation = 8,
EndPresentation = 9,
Find = 10,
GoToPage = 11,
Close = 12 };
// query for action type
ActionType actionType() const { return m_type; }
......
......@@ -38,7 +38,7 @@ class KPDFPage;
* @short Base class for objects being notified when something changes.
*
* Inherit this class and call KPDFDocument->addObserver( yourClass ) to get
* notified of asyncronous events (new pixmap generated, or changed, etc..).
* notified of asynchronous events (new pixmap generated, or changed, etc..).
*/
class DocumentObserver
{
......
......@@ -458,14 +458,14 @@ bool CHMFile::ParseHhcAndFillTree (const QString& file, QDomDocument *tree, bool
qFatal ("CHMFile::ParseAndFillTopicsTree: bad <param> tag '%s': no name=\n", tag.toAscii().constData());
// offset+5 skips 'name='
offset = findStringInQuotes (tag, offset + name_pattern.length(), pname, TRUE, FALSE);
offset = findStringInQuotes (tag, offset + name_pattern.length(), pname, true, false);
pname = pname.toLower();
if ( (offset = tag.indexOf (value_pattern, offset, Qt::CaseInsensitive)) == -1 )
qFatal ("CHMFile::ParseAndFillTopicsTree: bad <param> tag '%s': no value=\n", tag.toAscii().constData());
// offset+6 skips 'value='
findStringInQuotes (tag, offset + value_pattern.length(), pvalue, FALSE, TRUE);
findStringInQuotes (tag, offset + value_pattern.length(), pvalue, false, true);
// qDebug ("<param>: name '%s', value '%s'", pname.toAscii().constData(), pvalue.toAscii().constData());
......@@ -634,14 +634,14 @@ bool CHMFile::ParseHhcAndFillTree (const QString& file, K3ListView *tree, bool a
qFatal ("CHMFile::ParseAndFillTopicsTree: bad <param> tag '%s': no name=\n", tag.toAscii().constData());
// offset+5 skips 'name='
offset = findStringInQuotes (tag, offset + name_pattern.length(), pname, TRUE, FALSE);
offset = findStringInQuotes (tag, offset + name_pattern.length(), pname, true, false);
pname = pname.toLower();
if ( (offset = tag.indexOf (value_pattern, offset, Qt::CaseInsensitive)) == -1 )
qFatal ("CHMFile::ParseAndFillTopicsTree: bad <param> tag '%s': no value=\n", tag.toAscii().constData());
// offset+6 skips 'value='
findStringInQuotes (tag, offset + value_pattern.length(), pvalue, FALSE, TRUE);
findStringInQuotes (tag, offset + value_pattern.length(), pvalue, false, true);
//qDebug ("<param>: name '%s', value '%s'", pname.toAscii().constData(), pvalue.toAscii().constData());
......@@ -1544,18 +1544,18 @@ bool CHMFile::ParseChmIndexFile ( const QString& file, bool asIndex, KCHMParsedI
QString name_pattern = "name=", value_pattern = "value=";
QString pname, pvalue;
if ( (offset = tag.find (name_pattern, 0, FALSE)) == -1 )
if ( (offset = tag.find (name_pattern, 0, false)) == -1 )
qFatal ("CHMFile::ParseAndFillTopicsTree: bad <param> tag '%s': no name=\n", tag.toAscii().constData());
// offset+5 skips 'name='
offset = findStringInQuotes (tag, offset + name_pattern.length(), pname, TRUE, FALSE);
offset = findStringInQuotes (tag, offset + name_pattern.length(), pname, true, false);
pname = pname.toLower();
if ( (offset = tag.find (value_pattern, offset, FALSE)) == -1 )
if ( (offset = tag.find (value_pattern, offset, false)) == -1 )
qFatal ("CHMFile::ParseAndFillTopicsTree: bad <param> tag '%s': no value=\n", tag.toAscii().constData());
// offset+6 skips 'value='
findStringInQuotes (tag, offset + value_pattern.length(), pvalue, FALSE, TRUE);
findStringInQuotes (tag, offset + value_pattern.length(), pvalue, false, true);
//qDebug ("<param>: name '%s', value '%s'", pname.toAscii().constData(), pvalue.toAscii().constData());
......
......@@ -381,7 +381,7 @@ private:
//! Map to decode HTML entitles like &acute; based on current encoding
QMap<QString, QString> m_entityDecodeMap;
//! TRUE if /#TOPICS, /#STRINGS, /#URLTBL and /#URLSTR are resolved, and the members below are valid
//! true if /#TOPICS, /#STRINGS, /#URLTBL and /#URLSTR are resolved, and the members below are valid
bool m_lookupTablesValid;
//! pointer to /#TOPICS
......@@ -397,7 +397,7 @@ private:
chmUnitInfo m_chmURLSTR;
//! Indicates whether the built-in search is available. This is true only when m_lookupTablesValid
//! is TRUE, and m_chmFIftiMain is resolved.
//! is true, and m_chmFIftiMain is resolved.
bool m_searchAvailable;
//! pointer to /$FIftiMain
......
......@@ -7,7 +7,7 @@ include_directories(
########### next target ###############
set(okularGenerator_poppler_PART_SRCS generator_pdf.cpp gp_outputdev.cpp pagetransition.cpp )
set(okularGenerator_poppler_PART_SRCS generator_pdf.cpp )
kde4_automoc(${okularGenerator_poppler_PART_SRCS})
......@@ -24,24 +24,3 @@ install_targets(${PLUGIN_INSTALL_DIR} okularGenerator_poppler )
install_files( ${SERVICES_INSTALL_DIR} FILES libokularGenerator_poppler.desktop )
#original Makefile.am contents follow:
#kde_module_LTLIBRARIES = \
# libokularGenerator_poppler.la
#
#INCLUDES = -I$(srcdir)/../.. -I../.. $(POPPLER_CFLAGS) $(all_includes)
#
#libokularGenerator_poppler_la_LIBADD = ../../core/liboKularcore.la ../../conf/liboKularconf.la \
# $(POPPLER_LIBS) $(LIB_KDEPRINT) $(LIB_KDEUI) -lm
#libokularGenerator_poppler_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN)
#libokularGenerator_poppler_la_SOURCES = generator_pdf.cpp gp_outputdev.cpp pagetransition.cpp
#
#KDE_OPTIONS = nofinal
#
#METASOURCES = AUTO
#
#kde_services_DATA = libokularGenerator_poppler.desktop
#
#generator_pdf.lo: ../../conf/settings.h
This diff is collapsed.
......@@ -11,7 +11,10 @@
#ifndef _KPDF_GENERATOR_PDF_H_
#define _KPDF_GENERATOR_PDF_H_
#include <qevent.h>
#define UNSTABLE_POPPLER_QT4
#include <poppler-qt4.h>
#include <qmutex.h>
#include <qcolor.h>
#include <qstring.h>
......@@ -21,16 +24,7 @@
#include "core/link.h"
#include "core/textpage.h"
class PDFDoc;
class GooList;
class TextPage;
class LinkDest;
class Page;
class Dict;
class Ref;
class ObjectRect;
class KPDFOutputDev;
class PDFPixmapGeneratorThread;
/**
......@@ -44,7 +38,7 @@ class PDFPixmapGeneratorThread;
* For generating page contents we tell PDFDoc to render a page and grab
* contents from out OutputDevs when rendering finishes.
*
* Background asyncronous contents providing is done via a QThread inherited
* Background asynchronous contents providing is done via a QThread inherited
* class defined at the bottom of the file.
*/
class PDFGenerator : public Generator
......@@ -57,12 +51,12 @@ class PDFGenerator : public Generator
// [INHERITED] load a document and fill up the pagesVector
bool loadDocument( const QString & fileName, QVector<KPDFPage*> & pagesVector );
void loadPages(QVector<KPDFPage*> &pagesVector, int rotation=-1, bool clear=false);
// [INHERITED] document informations
// [INHERITED] document information
const DocumentInfo * generateDocumentInfo();
const DocumentSynopsis * generateDocumentSynopsis();
const DocumentFonts * generateDocumentFonts();
// [INHERITED] document informations
// [INHERITED] document information
bool isAllowed( int permissions );
// [INHERITED] perform actions on document / pages
......@@ -80,8 +74,9 @@ class PDFGenerator : public Generator
bool prefersInternalSearching() { return false; };
RegularAreaRect * findText (const QString & text, SearchDir dir,
const bool strictCase, const RegularAreaRect * lastRect,
KPDFPage * page );
const bool strictCase, const RegularAreaRect * lastRect,
KPDFPage * page );
// TODO does this really need to be a pointer?
QString * getText( const RegularAreaRect * area, KPDFPage * page );
void setOrientation(QVector<KPDFPage*> & pagesVector, int orientation);
......@@ -99,36 +94,28 @@ class PDFGenerator : public Generator
void warning(QString & string, int duration);
void notice(QString & string, int duration);
private slots:
// (async related) receive data from the generator thread
void threadFinished();
private:
// friend class to access private document related variables
friend class PDFPixmapGeneratorThread;
void fillViewportFromLink( DocumentViewport &viewport, LinkDest *destination );
// access document informations
QString getDocumentInfo( const QString & data ) const;
QString getDocumentDate( const QString & data ) const;
// create the document synopsis hieracy
void addSynopsisChildren( QDomNode * parent, GooList * items );
// add fonts (in resDict) to the private 'docFonts' class
void addFonts( Dict * resDict, Ref ** fonts, int &fontsLen, int &fontsSize );
void addSynopsisChildren( QDomNode * parentSource, QDomNode * parentDestination );
// fetch annotations from the pdf file and add they to the page
void addAnnotations( Page * xpdfPage, KPDFPage * page );
void addAnnotations( Poppler::Page * popplerPage, KPDFPage * page );
// fetch the transition information and add it to the page
void addTransition( Page * xpdfPage, KPDFPage * page );
void addTransition( Poppler::Page * popplerPage, KPDFPage * page );
static KPDFTextPage * abstractTextPage(TextPage *tp, double height, double width, int rot);
TextPage * fastTextPage (KPDFPage * page);
// (async related) receive data from the generator thread
void customEvent( QEvent * );
// xpdf dependant stuff
static KPDFTextPage * abstractTextPage(const QList<Poppler::TextBox*> &text, double height, double width, int rot);
// poppler dependant stuff
QMutex docLock;
PDFDoc * pdfdoc;
KPDFOutputDev * kpdfOutputDev;
QColor paperColor;
Poppler::Document *pdfdoc;
// asyncronous generation related stuff
// asynchronous generation related stuff
PDFPixmapGeneratorThread * generatorThread;
// misc variables for document info and synopsis caching
......@@ -140,9 +127,6 @@ class PDFGenerator : public Generator
DocumentSynopsis docSyn;
bool docFontsDirty;
DocumentFonts docFonts;
// static instances counter
static unsigned int m_count;
};
......@@ -161,9 +145,11 @@ class PDFPixmapGeneratorThread : public QThread
// end generation
void endGeneration();
PixmapRequest *request() const;
// methods for getting contents from the GUI thread
QImage * takeImage() const;
TextPage * takeTextPage() const;
QList<Poppler::TextBox*> takeText();
QLinkedList< ObjectRect * > takeObjectRects() const;
private:
......
/***************************************************************************
* Copyright (C) 2003-2004 by Christophe Devriese *
* <Christophe.Devriese@student.kuleuven.ac.be> *
* Copyright (C) 2003 by Andy Goossens <andygoossens@telenet.be> *
* Copyright (C) 2003 by Scott Wheeler <wheeler@kde.org> *
* Copyright (C) 2003 by Ingo Kl�ker <kloecker@kde.org> *
* Copyright (C) 2003 by Will Andrews <will@csociety.org> *
* Copyright (C) 2004 by Dominique Devriese <devriese@kde.org> *
* Copyright (C) 2004 by Waldo Bastian <bastian@kde.org> *
* Copyright (C) 2004 by Albert Astals Cid <tsdgeos@terra.es> *
* *
* 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 of the License, or *
* (at your option) any later version. *
***************************************************************************/
#ifdef __GNUC__
#pragma implementation
#endif
#include <kdebug.h>
#include <qpixmap.h>
#include <qimage.h>
#include "gp_outputdev.h"
#include "generator_pdf.h"
#include "core/document.h" // for DocumentViewport
#include "core/page.h"
#include "core/link.h"
#include "Link.h"
#include "GfxState.h"
#include "TextOutputDev.h"
#include "splash/SplashBitmap.h"
//NOTE: XPDF/Splash *implementation dependant* code is marked with '###'
/** KPDFOutputDev implementation **/
KPDFOutputDev::KPDFOutputDev( SplashColor paperColor )
: SplashOutputDev( splashModeRGB8, 4, false, paperColor ),
m_doc( 0 ), m_pixmap( 0 ), m_image( 0 )
{
}
KPDFOutputDev::~KPDFOutputDev()
{
clear();
}
void KPDFOutputDev::initDevice( PDFDoc * pdfDoc )
{
m_doc = pdfDoc;
startDoc( pdfDoc->getXRef() );
}
void KPDFOutputDev::setParams( int width, int height, bool genL, bool genI, bool safe )
{
clear();
m_pixmapWidth = width;
m_pixmapHeight = height;
m_qtThreadSafety = safe;
m_generateLinks = genL;
m_generateImages = genI;
}
QPixmap * KPDFOutputDev::takePixmap()
{
QPixmap * pix = m_pixmap;
m_pixmap = 0;
return pix;
}
QImage * KPDFOutputDev::takeImage()
{
QImage * img = m_image;
m_image = 0;
return img;
}
QLinkedList< ObjectRect * > KPDFOutputDev::takeObjectRects()
{
if ( m_rects.isEmpty() )
return m_rects;
QLinkedList< ObjectRect * > rectsCopy( m_rects );
m_rects.clear();
return rectsCopy;
}
//BEGIN - OutputDev hooked calls
void KPDFOutputDev::endPage()
{
SplashOutputDev::endPage();
int bh = getBitmap()->getHeight(),
bw = getBitmap()->getWidth();
// TODO The below loop can be avoided if using the code that is commented here and
// we change splashModeRGB8 to splashModeARGB8 the problem is that then bug101800.pdf
// does not work
/* SplashColorPtr dataPtr = getBitmap()->getDataPtr();
// construct a qimage SHARING the raw bitmap data in memory
QImage * img = new QImage( dataPtr, bw, bh, 32, 0, 0, QImage::IgnoreEndian );*/
QImage * img = new QImage( bw, bh, 32 );
SplashColorPtr pixel = new Guchar[4];
for (int i = 0; i < bw; i++)
{
for (int j = 0; j < bh; j++)
{
getBitmap()->getPixel(i, j, pixel);
img->setPixel( i, j, qRgb( pixel[0], pixel[1], pixel[2] ) );
}
}
delete [] pixel;
// use the QImage or convert it immediately to QPixmap for better
// handling and memory unloading
if ( m_qtThreadSafety )
{
delete m_image;
// it may happen (in fact it doesn't) that we need a rescaling
if ( bw != m_pixmapWidth && bh != m_pixmapHeight )
m_image = new QImage( img->scaled( m_pixmapWidth, m_pixmapHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ) );
else
// dereference image from the xpdf memory
m_image = new QImage( img->copy() );
}
else
{
delete m_pixmap;
// it may happen (in fact it doesn't) that we need a rescaling
if ( bw != m_pixmapWidth || bh != m_pixmapHeight )
m_pixmap = new QPixmap( img->scaled( m_pixmapWidth, m_pixmapHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ) );
else
m_pixmap = new QPixmap( *img );
}
// destroy the shared descriptor and (###) unload underlying xpdf bitmap
delete img;
SplashOutputDev::startPage( 0, NULL );
}
void KPDFOutputDev::drawLink( Link * link, Catalog * catalog )
{
if ( !link->isOk() )
return;
if ( m_generateLinks )
{
// create the link descriptor
KPDFLink * l = generateLink( link->getAction() );
if ( l )
{
// create the page rect representing the link
double x1, y1, x2, y2;
link->getRect( &x1, &y1, &x2, &y2 );
int left, top, right, bottom;
cvtUserToDev( x1, y1, &left, &top );
cvtUserToDev( x2, y2, &right, &bottom );
double nl = (double)left / (double)m_pixmapWidth,
nt = (double)top / (double)m_pixmapHeight,
nr = (double)right / (double)m_pixmapWidth,
nb = (double)bottom / (double)m_pixmapHeight;
// create the rect using normalized coords and attach the KPDFLink to it
ObjectRect * rect = new ObjectRect( nl, nt, nr, nb, ObjectRect::Link, l );
// add the ObjectRect to the vector container
m_rects.push_front( rect );
}
}
SplashOutputDev::drawLink( link, catalog );
}
void KPDFOutputDev::drawImage( GfxState *state, Object *ref, Stream *str,
int _width, int _height, GfxImageColorMap *colorMap, int *maskColors, GBool inlineImg )
{
if ( m_generateImages )
{
// find out image rect from the Coord Transform Matrix
double * ctm = state->getCTM();
int left = (int)ctm[4],
top = (int)ctm[5],
width = (int)ctm[0],
height = (int)ctm[3];
// normalize width
if ( width < 0 )
{
width = -width;
left -= width;
}
// normalize height
if ( height < 0 )
{
height = -height;
top -= height;
}
if ( width > 10 && height > 10 )
{
// build a descriptor for the image rect
double nl = (double)left / (double)m_pixmapWidth,
nt = (double)top / (double)m_pixmapHeight,
nr = (double)(left + width) / (double)m_pixmapWidth,
nb = (double)(top + height) / (double)m_pixmapHeight;
// create the rect using normalized coords and set it of KPDFImage type
ObjectRect * rect = new ObjectRect( nl, nt, nr, nb, ObjectRect::Image, 0 );
// add the ObjectRect to the vector container
m_rects.push_back( rect );
}
}
SplashOutputDev::drawImage( state, ref, str, _width, _height, colorMap, maskColors, inlineImg );
}
//END - OutputDev hooked calls
//BEGIN - private helpers
void KPDFOutputDev::clear()
{
// delete rects
if ( m_rects.count() )
{
QLinkedList< ObjectRect * >::iterator it = m_rects.begin(), end = m_rects.end();
for ( ; it != end; ++it )
delete *it;
m_rects.clear();
}
// delete pixmap
if ( m_pixmap )
{
delete m_pixmap;
m_pixmap = 0;
}
// delete image
if ( m_image )
{
delete m_image;
m_image = 0;
}
}
KPDFLink * KPDFOutputDev::generateLink( LinkAction * a )
// note: this function is called when processing a page, when the MUTEX is already LOCKED
{
KPDFLink * link = NULL;
if ( a ) switch ( a->getKind() )
{
case actionGoTo:
{
LinkGoTo * g = (LinkGoTo *) a;
// create link: no ext file, namedDest, object pointer
link = new KPDFLinkGoto( QString::null, decodeViewport( g->getNamedDest(), g->getDest() ) );
}
break;
case actionGoToR:
{
LinkGoToR * g = (LinkGoToR *) a;
// copy link file
const char * fileName = g->getFileName()->getCString();
// ceate link: fileName, namedDest, object pointer
link = new KPDFLinkGoto( (QString)fileName, decodeViewport( g->getNamedDest(), g->getDest() ) );
}
break;
case actionLaunch:
{
LinkLaunch * e = (LinkLaunch *)a;
GooString * p = e->getParams();
link = new KPDFLinkExecute( e->getFileName()->getCString(), p ? p->getCString() : 0 );
}
break;
case actionNamed: