Read correctly the DjVu area maps (aka links) referring to local pages.

svn path=/trunk/playground/graphics/okular/; revision=555915
This commit is contained in:
Pino Toscano 2006-06-28 17:52:00 +00:00
parent 0b5aae86ab
commit 39e73f95f6
3 changed files with 211 additions and 1 deletions

View file

@ -9,7 +9,9 @@
#include "generator_djvu.h"
#include "kdjvu.h"
#include "core/area.h"
#include "core/document.h"
#include "core/link.h"
#include "core/page.h"
#include <qdom.h>
@ -141,10 +143,53 @@ void DjVuGenerator::setOrientation( QVector<KPDFPage*> & pagesVector, int orient
loadPages( pagesVector, orientation );
}
void DjVuGenerator::djvuPixmapGenerated( int /*page*/, const QPixmap & pix )
void DjVuGenerator::djvuPixmapGenerated( int page, const QPixmap & pix )
{
m_request->page->setPixmap( m_request->id, new QPixmap( pix ) );
QList<KDjVu::Link*> links = m_djvu->linksForPage( page );
if ( links.count() > 0 )
{
QLinkedList<ObjectRect *> rects;
QList<KDjVu::Link*>::ConstIterator it = links.constBegin();
QList<KDjVu::Link*>::ConstIterator itEnd = links.constEnd();
for ( ; it != itEnd; ++it )
{
ObjectRect *newlink = 0;
switch ( (*it)->type() )
{
case KDjVu::Link::PageLink:
{
KDjVu::PageLink* l = static_cast<KDjVu::PageLink*>( (*it) );
bool ok = true;
QString target = l->page();
if ( target.at(0) == QLatin1Char( '#' ) )
target.remove( 0, 1 );
int tmppage = target.toInt( &ok );
if ( ok )
{
DocumentViewport vp;
vp.pageNumber = ( target.at(0) == QLatin1Char( '+' ) || target.at(0) == QLatin1Char( '-' ) ) ? page + tmppage : tmppage - 1;
KPDFLinkGoto* go = new KPDFLinkGoto( QString::null, vp );
const KDjVu::Page* p = m_djvu->pages().at( vp.pageNumber );
QRect r( QPoint( l->point().x(), p->height() - l->point().y() - l->size().height() ), l->size() );
newlink = new ObjectRect( NormalizedRect( r, p->width(), p->height() ), ObjectRect::Link, go );
}
break;
}
case KDjVu::Link::UrlLink:
// TODO
break;
}
if ( newlink )
rects.append( newlink );
// delete the links as soon as we process them
delete (*it);
}
if ( rects.count() > 0 )
m_request->page->setObjectRects( rects );
}
ready = true;
signalRequestDone( m_request );
}

View file

@ -9,6 +9,7 @@
#include "kdjvu.h"
#include <qbytearray.h>
#include <qdom.h>
#include <qfile.h>
#include <qlist.h>
@ -133,6 +134,57 @@ int KDjVu::Page::orientation() const
return m_orientation;
}
// KDjVu::Link
KDjVu::Link::~Link()
{
}
QPoint KDjVu::Link::point() const
{
return m_point;
}
QSize KDjVu::Link::size() const
{
return m_size;
}
// KDjVu::PageLink
KDjVu::PageLink::PageLink()
{
}
int KDjVu::PageLink::type() const
{
return KDjVu::Link::PageLink;
}
QString KDjVu::PageLink::page() const
{
return m_page;
}
// KDjVu::UrlLink
KDjVu::UrlLink::UrlLink()
{
}
int KDjVu::UrlLink::type() const
{
return KDjVu::Link::UrlLink;
}
QUrl KDjVu::UrlLink::url() const
{
return m_url;
}
class KDjVu::Private
{
public:
@ -379,6 +431,59 @@ const QDomDocument * KDjVu::documentBookmarks() const
return d->m_docBookmarks;
}
QList<KDjVu::Link*> KDjVu::linksForPage( int pageNum ) const
{
if ( ( pageNum < 0 ) || ( pageNum >= d->m_pages.count() ) )
return QList<KDjVu::Link*>();
miniexp_t annots;
while ( ( annots = ddjvu_document_get_pageanno( d->m_djvu_document, pageNum ) ) == miniexp_dummy )
handle_ddjvu_messages( d->m_djvu_cxt, true );
if ( !miniexp_listp( annots ) )
return QList<KDjVu::Link*>();
QList<KDjVu::Link*> ret;
int l = miniexp_length( annots );
for ( int i = 0; i < l; ++i )
{
miniexp_t cur = miniexp_nth( i, annots );
int num = miniexp_length( cur );
if ( ( num <= 0 ) || !miniexp_symbolp( miniexp_nth( 0, cur ) ) ||
( qstrncmp( miniexp_to_name( miniexp_nth( 0, cur ) ), "maparea", 7 ) != 0 ) )
continue;
QString target;
KDjVu::Link* link = 0;
if ( miniexp_stringp( miniexp_nth( 1, cur ) ) )
{
KDjVu::PageLink* plink = new KDjVu::PageLink();
plink->m_page = QString::fromUtf8( miniexp_to_str( miniexp_nth( 1, cur ) ) );
link = plink;
}
else
{
// TODO: external hyperlink
}
if ( link )
{
miniexp_t area = miniexp_nth( 3, cur );
int arealength = miniexp_length( area );
if ( ( arealength == 5 ) && miniexp_symbolp( miniexp_nth( 0, area ) ) &&
( qstrncmp( miniexp_to_name( miniexp_nth( 0, area ) ), "rect", 4 ) == 0 ) )
{
link->m_point = QPoint( miniexp_to_int( miniexp_nth( 1, area ) ), miniexp_to_int( miniexp_nth( 2, area ) ) );
link->m_size = QSize( miniexp_to_int( miniexp_nth( 3, area ) ), miniexp_to_int( miniexp_nth( 4, area ) ) );
}
// TODO: other link shapes
ret.append( link );
}
}
return ret;
}
const QVector<KDjVu::Page*> &KDjVu::pages() const
{
return d->m_pages;

View file

@ -13,6 +13,7 @@
#include <qobject.h>
#include <qpixmap.h>
#include <qvector.h>
#include <qurl.h>
class QDomDocument;
@ -50,6 +51,60 @@ class KDjVu : public QObject
int m_orientation;
};
/**
* The base implementation for a DjVu link.
*/
class Link
{
friend class KDjVu;
public:
virtual ~Link();
enum LinkType { PageLink, UrlLink };
virtual int type() const = 0;
QPoint point() const;
QSize size() const;
private:
QPoint m_point;
QSize m_size;
};
/**
* A link to reach a page of a DjVu document.
*/
class PageLink : public Link
{
friend class KDjVu;
public:
virtual int type() const;
QString page() const;
private:
PageLink();
QString m_page;
};
/**
* A DjVu link to open an external Url.
*/
class UrlLink : public Link
{
friend class KDjVu;
public:
virtual int type() const;
QUrl url() const;
private:
UrlLink();
QUrl m_url;
};
/**
* Opens the file \p fileName, closing the old one if necessary.
*/
@ -85,6 +140,11 @@ class KDjVu : public QObject
*/
const QDomDocument * documentBookmarks() const;
/**
* Return the links for the page \p pageNum
*/
QList<KDjVu::Link*> linksForPage( int pageNum ) const;
// pixmap handling
/**
* Check if the pixmap for the specified \p page with the specified