📄 kdjvu.cpp.svn-base
字号:
closeFile(); ddjvu_format_release( d->m_format ); ddjvu_context_release( d->m_djvu_cxt ); delete d;}bool KDjVu::openFile( const QString & fileName ){ // first, close the old file if ( d->m_djvu_document ) closeFile(); // load the document... d->m_djvu_document = ddjvu_document_create_by_filename( d->m_djvu_cxt, QFile::encodeName( fileName ), true ); if ( !d->m_djvu_document ) return false; // ...and wait for its loading wait_for_ddjvu_message( d->m_djvu_cxt, DDJVU_DOCINFO ); kDebug() << "# of pages: " << ddjvu_document_get_pagenum( d->m_djvu_document ) << endl; int numofpages = ddjvu_document_get_pagenum( d->m_djvu_document ); d->m_pages.clear(); d->m_pages.resize( numofpages ); d->m_pages_cache.clear(); d->m_pages_cache.resize( numofpages ); // get the document type QString doctype; switch ( ddjvu_document_get_type( d->m_djvu_document ) ) { case DDJVU_DOCTYPE_UNKNOWN: doctype = i18nc( "Type of DjVu document", "Unknown" ); break; case DDJVU_DOCTYPE_SINGLEPAGE: doctype = i18nc( "Type of DjVu document", "Single Page" ); break; case DDJVU_DOCTYPE_BUNDLED: doctype = i18nc( "Type of DjVu document", "Bundled" ); break; case DDJVU_DOCTYPE_INDIRECT: doctype = i18nc( "Type of DjVu document", "Indirect" ); break; case DDJVU_DOCTYPE_OLD_BUNDLED: doctype = i18nc( "Type of DjVu document", "Bundled (old)" ); break; case DDJVU_DOCTYPE_OLD_INDEXED: doctype = i18nc( "Type of DjVu document", "Indexed (old)" ); break; } if ( !doctype.isEmpty() ) d->m_metaData[ "documentType" ] = doctype; // get the number of components d->m_metaData[ "componentFile" ] = QString::number( ddjvu_document_get_filenum( d->m_djvu_document ) ); // read the pages for ( int i = 0; i < numofpages; ++i ) { // wait for the new page to be loaded ddjvu_page_t *newpage = ddjvu_page_create_by_pageno( d->m_djvu_document, i ); ddjvu_status_t sts; while ( ( sts = ddjvu_page_decoding_status( newpage ) ) < DDJVU_JOB_OK ) handle_ddjvu_messages( d->m_djvu_cxt, true ); if ( sts >= DDJVU_JOB_FAILED ) { kDebug() << "\t>>> page " << i << " failed: " << sts << endl; break; } d->m_pages_cache[i] = newpage; KDjVu::Page *p = new KDjVu::Page(); p->m_width = ddjvu_page_get_width( newpage ); p->m_height = ddjvu_page_get_height( newpage ); p->m_dpi = ddjvu_page_get_resolution( newpage ); p->m_orientation = flipRotation( ddjvu_page_get_initial_rotation( newpage ) ); d->m_pages[i] = p; } return true;}void KDjVu::closeFile(){ // deleting the old TOC delete d->m_docBookmarks; d->m_docBookmarks = 0; // deleting the pages qDeleteAll( d->m_pages ); // releasing the djvu pages QVector<ddjvu_page_t *>::Iterator it = d->m_pages_cache.begin(), itEnd = d->m_pages_cache.end(); for ( ; it != itEnd; ++it ) ddjvu_page_release( *it ); d->m_pages_cache.clear(); // clearing the pixmap cache qDeleteAll( d->mPixCache ); // clearing the old metadata d->m_metaData.clear(); // releasing the old document if ( d->m_djvu_document ) ddjvu_document_release( d->m_djvu_document ); d->m_djvu_document = 0;}QString KDjVu::getMetaData( const QString & key ) const{ return d->m_metaData.contains( key ) ? d->m_metaData[ key ] : QString();}const QDomDocument * KDjVu::documentBookmarks() const{ if ( !d->m_docBookmarks ) d->readBookmarks(); 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 ) ) ) { QString target = QString::fromUtf8( miniexp_to_str( miniexp_nth( 1, cur ) ) ); if ( target.isEmpty() || ( ( target.length() > 0 ) && target.at(0) == QLatin1Char( '#' ) ) ) { KDjVu::PageLink* plink = new KDjVu::PageLink(); plink->m_page = target; link = plink; } else { KDjVu::UrlLink* ulink = new KDjVu::UrlLink(); ulink->m_url = target; link = ulink; } } else { // TODO: external hyperlink } if ( link ) { link->m_area = KDjVu::Link::UnknownArea; 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 ) || ( qstrncmp( miniexp_to_name( miniexp_nth( 0, area ) ), "oval", 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 ) ) ); if ( qstrncmp( miniexp_to_name( miniexp_nth( 0, area ) ), "rect", 4 ) == 0 ) { link->m_area = KDjVu::Link::RectArea; } else { link->m_area = KDjVu::Link::EllipseArea; } } else if ( ( arealength > 0 ) && ( arealength % 2 == 1 ) && miniexp_symbolp( miniexp_nth( 0, area ) ) && ( qstrncmp( miniexp_to_name( miniexp_nth( 0, area ) ), "poly", 4 ) == 0 ) ) { link->m_area = KDjVu::Link::PolygonArea; QPolygon poly; for ( int j = 1; j < arealength; j += 2 ) { poly << QPoint( miniexp_to_int( miniexp_nth( j, area ) ), miniexp_to_int( miniexp_nth( j + 1, area ) ) ); } link->m_poly = poly; } // TODO: other link shapes if ( link->m_area != KDjVu::Link::UnknownArea ) ret.append( link ); } } return ret;}const QVector<KDjVu::Page*> &KDjVu::pages() const{ return d->m_pages;}QPixmap KDjVu::pixmap( int page, int width, int height, int rotation ){ bool found = false; QList<PixmapCacheItem*>::Iterator it = d->mPixCache.begin(), itEnd = d->mPixCache.end(); for ( ; ( it != itEnd ) && !found; ++it ) { PixmapCacheItem* cur = *it; if ( ( cur->page == page ) && ( cur->width == width ) && ( cur->height == height ) && ( cur->rotation == rotation ) ) found = true; } if ( !found ) return QPixmap(); // taking the element and pushing to the top of the list --it; PixmapCacheItem* cur2 = *it; d->mPixCache.erase( it ); d->mPixCache.push_front( cur2 ); return cur2->pix;}void KDjVu::requestPixmap( int page, int width, int height, int rotation ){ QPixmap tmp = pixmap( page, width, height, rotation ); if ( !tmp.isNull() ) { emit pixmapGenerated( page, tmp ); return; } if ( !d->m_pages_cache.at( page ) ) { ddjvu_page_t *newpage = ddjvu_page_create_by_pageno( d->m_djvu_document, page ); // wait for the new page to be loaded ddjvu_status_t sts; while ( ( sts = ddjvu_page_decoding_status( newpage ) ) < DDJVU_JOB_OK ) handle_ddjvu_messages( d->m_djvu_cxt, true ); d->m_pages_cache[page] = newpage; } ddjvu_page_t *djvupage = d->m_pages_cache[page]; if ( ddjvu_page_get_rotation( djvupage ) != flipRotation( rotation ) ) {// TODO: test documents with initial rotation != 0// ddjvu_page_set_rotation( djvupage, m_pages.at( page )->orientation() ); ddjvu_page_set_rotation( djvupage, (ddjvu_page_rotation_t)flipRotation( rotation ) ); } static const int xdelta = 1500; static const int ydelta = 1500; int xparts = width / xdelta + 1; int yparts = height / ydelta + 1; QPixmap newpix( width, height ); int res = 10000; if ( ( xparts == 1 ) && ( yparts == 1 ) ) { // only one part -- render at once with no need to auxiliary pixmap newpix = d->generatePixmapTile( djvupage, res, width, 0, xdelta, height, 0, ydelta ); } else { // more than one part -- need to render piece-by-piece and to compose // the results QPainter p; p.begin( &newpix ); int parts = xparts * yparts; for ( int i = 0; i < parts; ++i ) { int row = i % xparts; int col = i / xparts; int tmpres = 0; QPixmap tempp = d->generatePixmapTile( djvupage, tmpres, width, row, xdelta, height, col, ydelta ); if ( tmpres ) { p.drawPixmap( row * xdelta, col * ydelta, tempp ); } res = qMin( tmpres, res ); } p.end(); } QPixmap pix; if ( res ) { pix = newpix; // delete all the cached pixmaps for the current page with a size that // differs no more than 35% of the new pixmap size int pixsize = pix.width() * pix.height(); if ( pixsize > 0 ) { for( int i = 0; i < d->mPixCache.count(); ) { PixmapCacheItem* cur = d->mPixCache.at(i); if ( ( cur->page == page ) && ( cur->rotation == rotation ) && ( abs( cur->pix.width() * cur->pix.height() - pixsize ) < pixsize * 0.35 ) ) { d->mPixCache.removeAt( i ); delete cur; } else ++i; } } // the pixmap cache has too many elements, remove the last if ( d->mPixCache.size() >= 10 ) { delete d->mPixCache.last(); d->mPixCache.removeLast(); } PixmapCacheItem* pch = new PixmapCacheItem( page, width, height, rotation, pix ); d->mPixCache.push_front( pch ); } emit pixmapGenerated( page, pix );}#include "kdjvu.moc"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -