From 39e73f95f6d3826c3104cfe5df1975340f711127 Mon Sep 17 00:00:00 2001 From: Pino Toscano Date: Wed, 28 Jun 2006 17:52:00 +0000 Subject: [PATCH] Read correctly the DjVu area maps (aka links) referring to local pages. svn path=/trunk/playground/graphics/okular/; revision=555915 --- generators/djvu/generator_djvu.cpp | 47 ++++++++++++- generators/djvu/kdjvu.cpp | 105 +++++++++++++++++++++++++++++ generators/djvu/kdjvu.h | 60 +++++++++++++++++ 3 files changed, 211 insertions(+), 1 deletion(-) diff --git a/generators/djvu/generator_djvu.cpp b/generators/djvu/generator_djvu.cpp index 41e52c68b..68637a2c9 100644 --- a/generators/djvu/generator_djvu.cpp +++ b/generators/djvu/generator_djvu.cpp @@ -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 @@ -141,10 +143,53 @@ void DjVuGenerator::setOrientation( QVector & 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 links = m_djvu->linksForPage( page ); + if ( links.count() > 0 ) + { + QLinkedList rects; + QList::ConstIterator it = links.constBegin(); + QList::ConstIterator itEnd = links.constEnd(); + for ( ; it != itEnd; ++it ) + { + ObjectRect *newlink = 0; + switch ( (*it)->type() ) + { + case KDjVu::Link::PageLink: + { + KDjVu::PageLink* l = static_cast( (*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 ); } diff --git a/generators/djvu/kdjvu.cpp b/generators/djvu/kdjvu.cpp index 6034a0ee8..eab6b1ca8 100644 --- a/generators/djvu/kdjvu.cpp +++ b/generators/djvu/kdjvu.cpp @@ -9,6 +9,7 @@ #include "kdjvu.h" +#include #include #include #include @@ -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::linksForPage( int pageNum ) const +{ + if ( ( pageNum < 0 ) || ( pageNum >= d->m_pages.count() ) ) + return QList(); + + 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(); + + QList 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::pages() const { return d->m_pages; diff --git a/generators/djvu/kdjvu.h b/generators/djvu/kdjvu.h index 2f0f2410c..0dc7f3d3a 100644 --- a/generators/djvu/kdjvu.h +++ b/generators/djvu/kdjvu.h @@ -13,6 +13,7 @@ #include #include #include +#include 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 linksForPage( int pageNum ) const; + // pixmap handling /** * Check if the pixmap for the specified \p page with the specified