📄 kdjvu.cpp
字号:
/*************************************************************************** * Copyright (C) 2006 by Pino Toscano <toscano.pino@tiscali.it> * * * * 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. * ***************************************************************************/#include "kdjvu.h"#include <qbytearray.h>#include <qdom.h>#include <qfile.h>#include <qlist.h>#include <qmap.h>#include <qpainter.h>#include <qstring.h>#include <kdebug.h>#include <klocale.h>#include <libdjvu/ddjvuapi.h>#include <libdjvu/miniexp.h>kdbgstream &operator<<( kdbgstream & s, const ddjvu_rect_t &r ){ s << "[" << r.x << "," << r.y << " - " << r.w << "x" << r.h << "]"; return s;}static void which_ddjvu_message( const ddjvu_message_t *msg ){#ifdef KDJVU_DEBUG kDebug() << "which_djvu_message(...): " << msg->m_any.tag << endl; switch( msg->m_any.tag ) { case DDJVU_ERROR: kDebug() << "ERROR: file " << msg->m_error.filename << ", line " << msg->m_error.lineno << endl; kDebug() << "ERROR: function '" << msg->m_error.function << "'" << endl; kDebug() << "ERROR: '" << msg->m_error.message << "'" << endl; break; case DDJVU_INFO: kDebug() << "INFO: '" << msg->m_info.message << "'" << endl; break; case DDJVU_CHUNK: kDebug() << "CHUNK: '" << QByteArray( msg->m_chunk.chunkid ) << "'" << endl; break; default: ; }#else Q_UNUSED( msg );#endif}/** * Explore the message queue until there are message left in it. */static void handle_ddjvu_messages( ddjvu_context_t *ctx, int wait ){ const ddjvu_message_t *msg; if ( wait ) ddjvu_message_wait( ctx ); while ( ( msg = ddjvu_message_peek( ctx ) ) ) { which_ddjvu_message( msg ); ddjvu_message_pop( ctx ); }}/** * Explore the message queue until the message \p mid is found. */static void wait_for_ddjvu_message( ddjvu_context_t *ctx, ddjvu_message_tag_t mid ){ ddjvu_message_wait( ctx ); const ddjvu_message_t *msg; while ( ( msg = ddjvu_message_peek( ctx ) ) && msg && ( msg->m_any.tag != mid ) ) { which_ddjvu_message( msg ); ddjvu_message_pop( ctx ); }}/** * Convert a clockwise coefficient \p r for a rotation to a counter-clockwise * and vice versa. */static int flipRotation( int r ){ return ( 4 - r ) % 4;}// PixmapCacheItemclass PixmapCacheItem{ public: PixmapCacheItem( int p, int w, int h, int r, const QPixmap& px ) : page( p ), width( w ), height( h ), rotation( r ), pix( px ) { } int page; int width; int height; int rotation; QPixmap pix;};// KdjVu::PageKDjVu::Page::Page(){}KDjVu::Page::~Page(){}int KDjVu::Page::width() const{ return m_width;}int KDjVu::Page::height() const{ return m_height;}int KDjVu::Page::dpi() const{ return m_dpi;}int KDjVu::Page::orientation() const{ return m_orientation;}// KDjVu::LinkKDjVu::Link::~Link(){}KDjVu::Link::LinkArea KDjVu::Link::areaType() const{ return m_area;}QPoint KDjVu::Link::point() const{ return m_point;}QSize KDjVu::Link::size() const{ return m_size;}QPolygon KDjVu::Link::polygon() const{ return m_poly;}// KDjVu::PageLinkKDjVu::PageLink::PageLink(){}int KDjVu::PageLink::type() const{ return KDjVu::Link::PageLink;}QString KDjVu::PageLink::page() const{ return m_page;}// KDjVu::UrlLinkKDjVu::UrlLink::UrlLink(){}int KDjVu::UrlLink::type() const{ return KDjVu::Link::UrlLink;}QString KDjVu::UrlLink::url() const{ return m_url;}class KDjVu::Private{ public: Private() : m_djvu_cxt( 0 ), m_djvu_document( 0 ), m_format( 0 ), m_docBookmarks( 0 ) { } QPixmap generatePixmapTile( ddjvu_page_t *djvupage, int& res, int width, int row, int xdelta, int height, int col, int ydelta ); void readBookmarks(); void fillBookmarksRecurse( QDomDocument& maindoc, QDomNode& curnode, miniexp_t exp, int offset = -1 ); ddjvu_context_t *m_djvu_cxt; ddjvu_document_t *m_djvu_document; ddjvu_format_t *m_format; QVector<KDjVu::Page*> m_pages; QVector<ddjvu_page_t *> m_pages_cache; QList<PixmapCacheItem*> mPixCache; QMap<QString, QString> m_metaData; QDomDocument * m_docBookmarks;};QPixmap KDjVu::Private::generatePixmapTile( ddjvu_page_t *djvupage, int& res, int width, int row, int xdelta, int height, int col, int ydelta ){ ddjvu_rect_t renderrect; renderrect.x = row * xdelta; renderrect.y = col * ydelta; int realwidth = qMin( width - renderrect.x, xdelta ); int realheight = qMin( height - renderrect.y, ydelta ); renderrect.w = realwidth; renderrect.h = realheight;#ifdef KDJVU_DEBUG kDebug() << "renderrect: " << renderrect << endl;#endif ddjvu_rect_t pagerect; pagerect.x = 0; pagerect.y = 0; pagerect.w = width; pagerect.h = height;#ifdef KDJVU_DEBUG kDebug() << "pagerect: " << pagerect << endl;#endif handle_ddjvu_messages( m_djvu_cxt, false ); char* imagebuffer = new char[ realwidth * realheight * 4 + 1 ]; res = ddjvu_page_render( djvupage, DDJVU_RENDER_COLOR, &pagerect, &renderrect, m_format, realwidth * 4, imagebuffer );#ifdef KDJVU_DEBUG kDebug() << "rendering result: " << res << endl;#endif handle_ddjvu_messages( m_djvu_cxt, false ); QPixmap pix; if ( res ) { QImage img( (uchar*)imagebuffer, realwidth, realheight, QImage::Format_RGB32 ); pix = QPixmap::fromImage( img ); } delete [] imagebuffer; return pix;}void KDjVu::Private::readBookmarks(){ if ( !m_djvu_document ) return; miniexp_t outline; while ( ( outline = ddjvu_document_get_outline( m_djvu_document ) ) == miniexp_dummy ) handle_ddjvu_messages( m_djvu_cxt, true ); if ( miniexp_listp( outline ) && ( miniexp_length( outline ) > 0 ) && miniexp_symbolp( miniexp_nth( 0, outline ) ) && ( QString::fromUtf8( miniexp_to_name( miniexp_nth( 0, outline ) ) ) == QLatin1String( "bookmarks" ) ) ) { m_docBookmarks = new QDomDocument( "KDjVuBookmarks" ); fillBookmarksRecurse( *m_docBookmarks, *m_docBookmarks, outline, 1 ); }}void KDjVu::Private::fillBookmarksRecurse( QDomDocument& maindoc, QDomNode& curnode, miniexp_t exp, int offset ){ if ( !miniexp_listp( exp ) ) return; int l = miniexp_length( exp ); for ( int i = qMax( offset, 0 ); i < l; ++i ) { miniexp_t cur = miniexp_nth( i, exp ); if ( miniexp_consp( cur ) && ( miniexp_length( cur ) > 0 ) && miniexp_stringp( miniexp_nth( 0, cur ) ) && miniexp_stringp( miniexp_nth( 1, cur ) ) ) { QString title = QString::fromUtf8( miniexp_to_str( miniexp_nth( 0, cur ) ) ); QString dest = QString::fromUtf8( miniexp_to_str( miniexp_nth( 1, cur ) ) ); QDomElement el; if ( dest.isEmpty() || ( ( dest.at( 0 ) == QLatin1Char( '#' ) ) && ( dest.remove( 0, 1 ) != title ) ) ) { el = maindoc.createElement( "item" ); el.setAttribute( "title", title ); el.setAttribute( "destination", dest ); curnode.appendChild( el ); } if ( !el.isNull() && ( miniexp_length( cur ) > 2 ) ) { fillBookmarksRecurse( maindoc, el, cur, 2 ); } } }}KDjVu::KDjVu() : QObject(), d( new Private ){ // creating the djvu context d->m_djvu_cxt = ddjvu_context_create( "KDjVu" ); // creating the rendering format unsigned int* mask = new unsigned int[3]; mask[0] = 0x00ff0000; mask[1] = 0x0000ff00; mask[2] = 0x000000ff; d->m_format = ddjvu_format_create( DDJVU_FORMAT_RGBMASK32, 3, mask ); ddjvu_format_set_row_order( d->m_format, 1 ); ddjvu_format_set_y_direction( d->m_format, 1 );}KDjVu::~KDjVu(){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -