Commit 712dd1e8 authored by Enrico Ros's avatar Enrico Ros

Reworked the page class. Added in-place (only a non-threaded quick test,

but will change soon!) thumbnail generator. Previews are shown and rescaled
smoothly. Some optimizations and fixes (over my buggy code :-P). kpdf rocks

svn path=/branches/kpdf_experiments/kdegraphics/kpdf/; revision=345508
parent 69bb375c
......@@ -75,6 +75,7 @@ void QOutputDev::endPage()
bw = getBitmap()->getWidth();
dataPtr = getBitmap()->getDataPtr();
m_image = QImage((uchar*)dataPtr.rgb8, bw, bh, 32, 0, 0, QImage::IgnoreEndian);
m_image.setAlphaBuffer( false );
}
void QOutputDev::updateFont(GfxState *state)
......
......@@ -14,6 +14,7 @@
// local includes
#include "PDFDoc.h"
#include "QOutputDev.h"
//#include "TextOutputDev.h"
#include "kpdf_error.h"
......@@ -71,8 +72,8 @@ bool KPDFDocument::openFile( const QString & docFile )
GString *filename = new GString( QFile::encodeName( docFile ) );
delete d->pdfdoc;
d->pdfdoc = new PDFDoc( filename, 0, 0 );
deletePages();
d->pdfdoc = new PDFDoc( filename, 0, 0 );
if ( !d->pdfdoc->isOk() || d->pdfdoc->getNumPages() < 1 )
{
......@@ -89,7 +90,7 @@ bool KPDFDocument::openFile( const QString & docFile )
uint pageCount = d->pdfdoc->getNumPages();
d->pages.resize( pageCount );
for ( uint i = 0; i < pageCount ; i++ )
d->pages[i] = new KPDFPage( i, d->pdfdoc->getPageWidth(i+1), d->pdfdoc->getPageHeight(i+1) );
d->pages[i] = new KPDFPage( i, d->pdfdoc->getPageWidth(i+1), d->pdfdoc->getPageHeight(i+1), d->pdfdoc->getPageRotate(i+1) );
//filter = NONE; TODO
sendFilteredPageList();
......@@ -237,11 +238,52 @@ void KPDFDocument::slotChangeZoom( float /*offset*/ )
{
}
void KPDFDocument::addObserver( KPDFDocumentObserver * pObserver )
{
d->observers.push_back( pObserver );
}
void KPDFDocument::requestPixmap( uint /*page*/, int /*width*/, int /*height*/ )
{
//think at this.. Syncronous or Asyncronous that's the problem! (shakespeare)
}
void KPDFDocument::requestThumbnail( uint page, int width, int height )
{
// TODO FIXME BEGIN :: TEMP CODE. ONLY A TEST. quick in-place thumbnail gen
KPDFPage * kp = d->pages[page];
if ( !kp )
return;
if ( !kp->hasThumbnail( width, height ) && d->pdfdoc && kp->width() > 0 && kp->height() > 0 )
{
// make thumbnail pixmap
SplashColor paperColor;
paperColor.rgb8 = splashMakeRGB8( 0xff, 0xff, 0xff );
QOutputDev odev( paperColor );
odev.startDoc( d->pdfdoc->getXRef() );
double fakeDpiX = width * 72.0 / kp->width(),
fakeDpiY = height * 72.0 / kp->height();
d->docLock.lock();
d->pdfdoc->displayPage( &odev, page + 1, fakeDpiX, fakeDpiY, 0, true, false );
d->docLock.unlock();
// It can happen (but with zero+ probability :-) that the output
// image doesn't have the right size. In that case scale it.
if ( odev.getImage().size() != QSize( width, height ) )
{
QImage scaled( odev.getImage().smoothScale( width, height ) );
kp->setThumbnail( scaled );
}
else
kp->setThumbnail( odev.getImage() );
foreachObserver( notifyThumbnailChanged( page ) );
}
// TODO FIXME END :: TEMP CODE. ONLY A TEST.
}
void KPDFDocument::sendFilteredPageList()
{
// make up a value list of the pages [1,2,3..]
......
......@@ -50,9 +50,6 @@ public:
KPDFDocument();
~KPDFDocument();
// observers related methods
void addObserver( KPDFDocumentObserver * pObserver );
// document handling
bool openFile( const QString & docFile );
void close();
......@@ -64,9 +61,10 @@ public:
bool atEnd() const;
const KPDFPage * page( uint page ) const;
//FIXME TEMP, REMOVE THIS!!!!! (for experiments only..)
void makeThumbnail( uint page, int width, int height ) const {};
void makePixmap( uint page ) const {};
// observers related methods
void addObserver( KPDFDocumentObserver * pObserver );
void requestPixmap( uint page, int width, int height );
void requestThumbnail( uint page, int width, int height );
public slots:
// document commands via slots
......
......@@ -84,15 +84,15 @@ Part::Part(QWidget *parentWidget, const char *widgetName,
connect( document, SIGNAL( pageChanged() ), this, SLOT( updateActions() ) );
// build widgets
QSplitter *split = new QSplitter(parentWidget, widgetName);
QSplitter *split = new QSplitter( parentWidget, widgetName );
split->setOpaqueResize( true );
m_thumbnailList = new ThumbnailList(split, document);
m_thumbnailList = new ThumbnailList( split, document );
m_thumbnailList->setMaximumWidth( 125 );
m_thumbnailList->setMinimumWidth( 50 );
document->addObserver( m_thumbnailList );
m_pageWidget = new KPDF::PageWidget(split, document);
m_pageWidget = new KPDF::PageWidget( split, document );
connect( m_pageWidget, SIGNAL( urlDropped( const KURL& ) ), SLOT( openURL( const KURL & )));
//connect(m _pageWidget, SIGNAL( rightClick() ), this, SIGNAL( rightClick() ));
document->addObserver( m_pageWidget );
......
......@@ -17,9 +17,11 @@
#include "TextOutputDev.h"
#include "page.h"
class PageOverlay { /*fake temp class*/ };
#include <qimage.h>
KPDFPage::KPDFPage( uint page, float w, float h )
: m_number( page ), m_width( w ), m_height( h ), m_zoom( 1 ),
KPDFPage::KPDFPage( uint page, float w, float h, int r )
: m_number( page ), m_width( w ), m_height( h ), m_rotate( r ),
m_pixmap( 0 ), m_thumbnail( 0 ), m_text( 0 ), m_overlay( 0 )
{
/* m_thumbnail = new QPixmap( "/a.png", "PNG" );
......@@ -38,22 +40,17 @@ KPDFPage::~KPDFPage()
delete m_overlay;
}
/** DRAWING **/
void KPDFPage::drawPixmap( QPainter * p, const QRect & limits ) const // MUTEXED
{
//threadLock.lock();
//BEGIN drawing functions
void KPDFPage::drawPixmap( QPainter * p, const QRect & limits, int /*width*/, int /*height*/ ) const
{// ###
if ( m_pixmap )
p->drawPixmap( limits.topLeft(), *m_pixmap, limits );
else
p->fillRect( limits, Qt::blue );
//threadLock.unlock();
}
void KPDFPage::drawThumbnail( QPainter * p, const QRect & limits, int width, int height ) const // OK
{
//threadLock.lock();
if ( m_thumbnail )
{
if ( m_thumbnail->width() == width && m_thumbnail->height() == height )
......@@ -66,68 +63,54 @@ void KPDFPage::drawThumbnail( QPainter * p, const QRect & limits, int width, int
}
else
p->fillRect( limits, QApplication::palette().active().base() );
//threadLock.unlock();
}
//END drawing functions
/** FIND **/
bool KPDFPage::hasText( QString & text )
{
//FIXME
return text.isNull();
}
/*
const QRect & KPDFPage::textPosition()
//BEGIN contents set methods
bool KPDFPage::hasPixmap( int width, int height ) const
{
//FIXME
return QRect();
return m_pixmap ? ( m_pixmap->width() == width && m_pixmap->height() == height ) : false;
}
*/
/** SLOTS **/
void KPDFPage::slotSetZoom( float /*scale*/ )
bool KPDFPage::hasThumbnail( int width, int height ) const
{
return m_thumbnail ? ( m_thumbnail->width() == width && m_thumbnail->height() == height ) : false;
}
void KPDFPage::slotSetContents( QPixmap * pix ) // MUTEXED
void KPDFPage::setPixmap( const QImage & image )
{
if ( !pix )
return;
threadLock.lock();
delete m_pixmap;
m_pixmap = new QPixmap( pix->width() + 6, pix->height() + 6 );
bitBlt( m_pixmap, 1,1, pix, 0,0, pix->width(),pix->height() );
QPainter paint( m_pixmap );
paint.drawRect( 0,0, pix->width()+1, pix->height()+1 );
paint.end();
//update page size (in pixels)
m_size = m_pixmap->size();
threadLock.unlock();
m_pixmap = new QPixmap( image );
}
void KPDFPage::slotSetThumbnail( QPixmap * thumb ) // MUTEXED
{
if ( !thumb )
return;
threadLock.lock();
void KPDFPage::setPixmapOverlay( /*someClass*/ )
{ //TODO this
}
void KPDFPage::setThumbnail( const QImage & image )
{
delete m_thumbnail;
m_thumbnail = new QPixmap( *thumb );
threadLock.unlock();
m_thumbnail = new QPixmap( image );
}
void KPDFPage::slotSetOverlay() // MUTEXED
void KPDFPage::setTextPage( TextOutputDev * textPage )
{
threadLock.lock();
//TODO this
threadLock.unlock();
delete m_text;
m_text = 0;
if ( m_text )
m_text = textPage;
}
//END contents set methods
//BEGIN [FIND]
/*bool KPDFPage::hasText( QString & text )
{ //TODO this
return text.isNull();
}
const QRect & KPDFPage::textPosition()
{ //TODO this
return QRect();
}*/
//END [FIND]
#include "page.moc"
......@@ -10,16 +10,14 @@
#ifndef _KPDF_PAGE_H_
#define _KPDF_PAGE_H_
#include <qobject.h>
#include <qsize.h>
#include <qmutex.h>
class QPixmap;
class QString;
class QRect;
class QPainter;
class QImage;
//class QString;
//class QRect;
class TextOutputDev;
class PageOverlay{ /*fake temp*/ };
class PageOverlay;
/**
* @short Collector for all the data belonging to a page.
......@@ -33,46 +31,37 @@ class PageOverlay{ /*fake temp*/ };
* class is destroyed.
*/
class KPDFPage : public QObject
class KPDFPage
{
Q_OBJECT
public:
KPDFPage( uint number, float width, float height );
KPDFPage( uint number, float width, float height, int rotation );
~KPDFPage();
// page properties
// query properties (const read-only methods)
uint number() const { return m_number; }
float width() const { return m_width; }
float height() const { return m_height; }
float ratio() const { return m_height / m_width; }
// rendering
void drawPixmap( QPainter * p, const QRect & rect ) const;
float rotation() const { return m_rotate; }
bool hasPixmap( int width, int height ) const;
bool hasThumbnail( int width, int height ) const;
void drawPixmap( QPainter * p, const QRect & rect, int width, int height ) const;
void drawThumbnail( QPainter * p, const QRect & rect, int width, int height ) const;
float currentZoom() const { return m_zoom; }
const QSize & currentSize() const { return m_size; }
// find related methods
bool hasText( QString & text );
//const QRect & textPosition();
// page contents setup
void setPixmap( const QImage & image );
void setPixmapOverlay( /*..DOMdescription..*/ );
void setThumbnail( const QImage & image );
void setTextPage( TextOutputDev * );
signals:
void changed( KPDFPage * thisPage );
private slots:
void slotSetZoom( float scale );
void slotSetContents( QPixmap * );
void slotSetThumbnail( QPixmap * );
void slotSetOverlay( /*..DOMdescription..*/ );
// FIND command
//bool hasText( QString & text );
//const QRect & textPosition();
private:
QMutex threadLock;
uint m_number;
float m_width, m_height;
float m_zoom;
QSize m_size;
int m_rotate;
QPixmap * m_pixmap;
QPixmap * m_thumbnail;
TextOutputDev * m_text;
......
......@@ -78,7 +78,7 @@ void ThumbnailList::pageSetup( const QValueList<int> & pages )
void ThumbnailList::pageSetCurrent( int pageNumber, float /*position*/ )
{
// deselect previous page
// deselect previous thumbnail
if ( m_selected )
m_selected->setSelected( false );
m_selected = 0;
......@@ -119,31 +119,35 @@ void ThumbnailList::keyPressEvent( QKeyEvent * keyEvent )
{
if ( thumbnails.count() < 1 )
return keyEvent->ignore();
int nextPage = -1;
if ( keyEvent->key() == Key_Up )
{
if ( !m_selected )
m_document->slotSetCurrentPage( 0 );
nextPage = 0;
else if ( vectorIndex > 0 )
m_document->slotSetCurrentPage( thumbnails[ vectorIndex - 1 ]->pageNumber() );
else
return keyEvent->ignore();
nextPage = thumbnails[ vectorIndex - 1 ]->pageNumber();
}
else if ( keyEvent->key() == Key_Down )
{
if ( !m_selected )
m_document->slotSetCurrentPage( 0 );
nextPage = 0;
else if ( vectorIndex < (int)thumbnails.count() - 1 )
m_document->slotSetCurrentPage( thumbnails[ vectorIndex + 1 ]->pageNumber() );
else
return keyEvent->ignore();
nextPage = thumbnails[ vectorIndex + 1 ]->pageNumber();
}
else if ( keyEvent->key() == Key_Home )
m_document->slotSetCurrentPage( thumbnails[ 0 ]->pageNumber() );
nextPage = thumbnails[ 0 ]->pageNumber();
else if ( keyEvent->key() == Key_End )
m_document->slotSetCurrentPage( thumbnails[ thumbnails.count() - 1 ]->pageNumber() );
else
nextPage = thumbnails[ thumbnails.count() - 1 ]->pageNumber();
if ( nextPage == -1 )
return keyEvent->ignore();
keyEvent->accept();
if ( m_selected )
m_selected->setSelected( false );
m_selected = 0;
m_document->slotSetCurrentPage( nextPage );
}
void ThumbnailList::contentsMousePressEvent( QMouseEvent * e )
......@@ -171,6 +175,9 @@ void ThumbnailList::viewportResizeEvent(QResizeEvent *e)
// right place and recalculate the contents area
if ( e->size().width() != e->oldSize().width() )
{
// runs the timer avoiding a thumbnail regeneration by 'contentsMoving'
requestThumbnails( 2000 );
// resize and reposition items
int totalHeight = 0,
newWidth = e->size().width();
......@@ -190,7 +197,7 @@ void ThumbnailList::viewportResizeEvent(QResizeEvent *e)
if ( m_selected )
ensureVisible( 0, childY( m_selected ) + m_selected->height()/2, 0, visibleHeight()/2 );
}
else if ( e->size().height() > e->oldSize().height() )
else if ( e->size().height() <= e->oldSize().height() )
return;
// update thumbnails since width has changed or height has increased
requestThumbnails( 500 );
......@@ -217,7 +224,7 @@ void ThumbnailList::slotRequestThumbnails( int /*newContentsX*/, int newContents
if ( top > vHeight )
break;
else if ( top + t->height() > 0 )
m_document->makeThumbnail( t->pageNumber(), t->width(), t->height() );
m_document->requestThumbnail( t->pageNumber(), t->previewWidth(), t->previewHeight() );
}
}
//END internal SLOTS
......
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