diff --git a/core/document.cpp b/core/document.cpp index 53b08cf6a..aad045fce 100644 --- a/core/document.cpp +++ b/core/document.cpp @@ -891,6 +891,8 @@ void DocumentPrivate::sendGeneratorRequest() const NormalizedRect visibleRect = ( r ? r->normalizedRect() : NormalizedRect() ); const QRect requestRect = !visibleRect.isNull() ? visibleRect.geometry( r->width(), r->height() ) : QRect( 0, 0, r->width(), r->height() ); + TilesManager *tilesManager = r->page()->tilesManager( r->id() ); + if (!r) m_pixmapRequestsStack.pop_back(); @@ -900,7 +902,42 @@ void DocumentPrivate::sendGeneratorRequest() m_pixmapRequestsStack.pop_back(); delete r; } - else if ( (long)requestRect.width() * (long)requestRect.height() > 20000000L ) + else if ( !tilesManager && r->id() == PAGEVIEW_ID && (long)r->width() * (long)r->height() > 8000000L ) + { + // if the image is too big. start using tiles + kWarning(OkularDebug).nospace() << "Running out of memory on page " << r->pageNumber() + << " (" << r->width() << "x" << r->height() << " px);"; + kWarning(OkularDebug) << "start using tiles."; + + // fill the tiles manager with the last rendered pixmap + const QPixmap *pixmap = r->page()->_o_nearestPixmap( r->id(), r->width(), r->height() ); + if ( pixmap ) + { + tilesManager = new TilesManager( pixmap->width(), pixmap->height() ); + tilesManager->setPixmap( pixmap, NormalizedRect( 0, 0, 1, 1 ) ); + tilesManager->setWidth( r->width() ); + tilesManager->setHeight( r->height() ); + } + else + { + // create new tiles manager + tilesManager = new TilesManager( r->width(), r->height() ); + } + r->page()->setTilesManager( r->id(), tilesManager ); + + request = r; + } + else if ( tilesManager && (long)r->width() * (long)r->height() < 6000000L ) + { + kWarning(OkularDebug).nospace() << "Stop using tiles on page " << r->pageNumber() + << " (" << r->width() << "x" << r->height() << " px);"; + + // page is too small. stop using tiles. + r->setNormalizedRect( NormalizedRect() ); + + request = r; + } + else if ( tilesManager && (long)requestRect.width() * (long)requestRect.height() > 20000000L ) { m_pixmapRequestsStack.pop_back(); if ( !m_warnedOutOfMemory ) @@ -932,7 +969,8 @@ void DocumentPrivate::sendGeneratorRequest() // submit the request to the generator if ( m_generator->canGeneratePixmap() ) { - kDebug(OkularDebug).nospace() << "sending request id=" << request->id() << " " <width() << "x" << request->height() << "@" << request->pageNumber() << " async == " << request->asynchronous(); + QRect requestRect = request->normalizedRect().isNull() ? QRect(0, 0, request->width(), request->height() ) : request->normalizedRect().geometry( request->width(), request->height() ); + kDebug(OkularDebug).nospace() << "sending request id=" << request->id() << " " <pageNumber() << " async == " << request->asynchronous(); m_pixmapRequestsStack.removeAll ( request ); if ( (int)m_rotation % 2 ) diff --git a/core/page.cpp b/core/page.cpp index 4b718d8ec..ee67e711a 100644 --- a/core/page.cpp +++ b/core/page.cpp @@ -205,15 +205,9 @@ void Page::setBoundingBox( const NormalizedRect& bbox ) bool Page::hasPixmap( int id, int width, int height, const NormalizedRect &rect ) const { - if ( id == PAGEVIEW_ID ) + TilesManager *tm = tilesManager( id ); + if ( tm ) { - TilesManager *tm = tilesManager( id ); - if ( !tm ) - { - tm = new TilesManager( width, height ); - d->m_tilesManagers.insert( id, tm ); - } - if ( width != tm->width() || height != tm->height() ) { tm->setWidth( width ); @@ -492,6 +486,7 @@ void Page::setPixmap( int id, QPixmap *pixmap, const NormalizedRect &rect ) if ( tm ) { tm->setPixmap( pixmap, rect ); + delete pixmap; return; } @@ -962,14 +957,14 @@ TilesManager *Page::tilesManager( int id ) const return tilesManager; } -void Page::deleteTilesManagers() +void Page::setTilesManager( int id, TilesManager *tm ) { - QMap< int, TilesManager* >::iterator itTilesManager = d->m_tilesManagers.begin(); - while ( itTilesManager != d->m_tilesManagers.end() ) + QMap< int, TilesManager* >::const_iterator itTilesManager = d->m_tilesManagers.constFind( id ); + if ( itTilesManager != d->m_tilesManagers.constEnd() ) { - delete (*itTilesManager); - itTilesManager++; + if ( *itTilesManager ) + delete *itTilesManager; } - d->m_tilesManagers.clear(); + d->m_tilesManagers.insert( id, tm ); } diff --git a/core/page.h b/core/page.h index aaad9d836..2c4fff378 100644 --- a/core/page.h +++ b/core/page.h @@ -364,9 +364,9 @@ class OKULAR_EXPORT Page TilesManager *tilesManager( int id ) const; /** - * Deletes all tiles managers + * Sets a tiles manager for the given @p id */ - void deleteTilesManagers(); + void setTilesManager( int id, TilesManager *tm ); private: PagePrivate* const d; diff --git a/core/tilesmanager.cpp b/core/tilesmanager.cpp index 136287687..d572ae910 100644 --- a/core/tilesmanager.cpp +++ b/core/tilesmanager.cpp @@ -29,7 +29,7 @@ TilesManager::~TilesManager() { for ( int i = 0; i < 16; ++i ) { - if ( m_tiles[ i ] ) + if ( m_tiles[ i ].pixmap ) delete m_tiles[ i ].pixmap; } } @@ -60,7 +60,7 @@ void TilesManager::setHeight( int height ) } } -void TilesManager::setPixmap( QPixmap *pixmap, const NormalizedRect &rect ) +void TilesManager::setPixmap( const QPixmap *pixmap, const NormalizedRect &rect ) { const double dim = 0.25; int left = qCeil( rect.left/dim ); @@ -84,8 +84,6 @@ void TilesManager::setPixmap( QPixmap *pixmap, const NormalizedRect &rect ) m_tiles[ index ].dirty = false; } } - - delete pixmap; } bool TilesManager::hasPixmap( const NormalizedRect &rect ) diff --git a/core/tilesmanager.h b/core/tilesmanager.h index e65dbeda8..ca14664f4 100644 --- a/core/tilesmanager.h +++ b/core/tilesmanager.h @@ -34,7 +34,7 @@ class OKULAR_EXPORT TilesManager TilesManager( int width, int height ); virtual ~TilesManager(); - void setPixmap( QPixmap *pixmap, const NormalizedRect &rect ); + void setPixmap( const QPixmap *pixmap, const NormalizedRect &rect ); bool hasPixmap( const NormalizedRect &rect ); QList tilesAt( const NormalizedRect &rect ) const; diff --git a/ui/pageview.cpp b/ui/pageview.cpp index a9e624baa..4d52ab01c 100644 --- a/ui/pageview.cpp +++ b/ui/pageview.cpp @@ -3126,21 +3126,25 @@ void PageView::drawDocumentOnPainter( const QRect & contentsRect, QPainter * p ) } } - QVector< Okular::VisiblePageRect * >::const_iterator vIt = d->document->visiblePageRects().constBegin(), vEnd = d->document->visiblePageRects().constEnd(); Okular::NormalizedRect crop; - for ( ; vIt != vEnd; ++vIt ) + + if ( item->page()->tilesManager( PAGEVIEW_ID ) ) { - Okular::VisiblePageRect *vItem = *vIt; - if ( vItem->pageNumber == item->pageNumber() ) + QVector< Okular::VisiblePageRect * >::const_iterator vIt = d->document->visiblePageRects().constBegin(), vEnd = d->document->visiblePageRects().constEnd(); + for ( ; vIt != vEnd; ++vIt ) { - crop = item->crop() & vItem->rect; - if ( crop.isNull() ) - crop = item->crop(); - - break; + Okular::VisiblePageRect *vItem = *vIt; + if ( vItem->pageNumber == item->pageNumber() ) + { + crop = item->crop() & vItem->rect; + break; + } } } + if ( crop.isNull() ) + crop = item->crop(); + // draw the page using the PagePainter with all flags active if ( contentsRect.intersects( itemGeometry ) ) { @@ -3984,19 +3988,29 @@ void PageView::slotRequestVisiblePixmaps( int newValue ) #ifdef PAGEVIEW_DEBUG kWarning() << "rerequesting visible pixmaps for page" << i->pageNumber() << "!"; #endif - QList tiles = i->page()->tilesManager( PAGEVIEW_ID )->tilesAt( vItem->rect ); - QList::const_iterator tIt = tiles.constBegin(), tEnd = tiles.constEnd(); - while ( tIt != tEnd ) + Okular::TilesManager *tilesManager = i->page()->tilesManager( PAGEVIEW_ID ); + if ( tilesManager ) { - Okular::Tile tile = *tIt; - if ( !tile.isValid() ) + QList tiles = i->page()->tilesManager( PAGEVIEW_ID )->tilesAt( vItem->rect ); + QList::const_iterator tIt = tiles.constBegin(), tEnd = tiles.constEnd(); + while ( tIt != tEnd ) { - Okular::PixmapRequest * p = new Okular::PixmapRequest( - PAGEVIEW_ID, i->pageNumber(), i->uncroppedWidth(), i->uncroppedHeight(), PAGEVIEW_PRIO, true ); - p->setNormalizedRect( tile.rect ); - requestedPixmaps.push_back( p ); + Okular::Tile tile = *tIt; + if ( !tile.isValid() ) + { + Okular::PixmapRequest * p = new Okular::PixmapRequest( + PAGEVIEW_ID, i->pageNumber(), i->uncroppedWidth(), i->uncroppedHeight(), PAGEVIEW_PRIO, true ); + p->setNormalizedRect( tile.rect ); + requestedPixmaps.push_back( p ); + } + tIt++; } - tIt++; + } + else + { + Okular::PixmapRequest * p = new Okular::PixmapRequest( + PAGEVIEW_ID, i->pageNumber(), i->uncroppedWidth(), i->uncroppedHeight(), PAGEVIEW_PRIO, true ); + requestedPixmaps.push_back( p ); } }