mirror of
https://bitbucket.org/smil3y/kde-extraapps.git
synced 2025-02-24 02:42:52 +00:00
okular: remove unused tiles feature
it was supposed to be optimization for extreme zoom-out levels Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
parent
8f8e8671b4
commit
306b8bc92e
17 changed files with 116 additions and 1469 deletions
|
@ -99,7 +99,6 @@ set(okularcore_SRCS
|
|||
core/textdocumentgenerator.cpp
|
||||
core/textdocumentsettings.cpp
|
||||
core/textpage.cpp
|
||||
core/tilesmanager.cpp
|
||||
core/utils.cpp
|
||||
core/view.cpp
|
||||
core/chooseenginewidget.ui
|
||||
|
@ -124,7 +123,6 @@ install(
|
|||
core/textdocumentgenerator.h
|
||||
core/textdocumentsettings.h
|
||||
core/textpage.h
|
||||
core/tile.h
|
||||
core/utils.h
|
||||
core/version.h
|
||||
core/observer.h
|
||||
|
|
|
@ -491,3 +491,53 @@ bool SourceRefObjectRect::contains( double x, double y, double xScale, double yS
|
|||
{
|
||||
return distanceSqr( x, y, xScale, yScale ) < ( pow( 7.0 / xScale, 2 ) + pow( 7.0 / yScale, 2 ) );
|
||||
}
|
||||
|
||||
NormalizedRect NormalizedRect::toRotatedRect( const NormalizedRect &rect, Rotation rotation )
|
||||
{
|
||||
if ( rotation == Rotation0 )
|
||||
return rect;
|
||||
|
||||
NormalizedRect newRect;
|
||||
switch ( rotation )
|
||||
{
|
||||
case Rotation90:
|
||||
newRect = NormalizedRect( 1 - rect.bottom, rect.left, 1 - rect.top, rect.right );
|
||||
break;
|
||||
case Rotation180:
|
||||
newRect = NormalizedRect( 1 - rect.right, 1 - rect.bottom, 1 - rect.left, 1 - rect.top );
|
||||
break;
|
||||
case Rotation270:
|
||||
newRect = NormalizedRect( rect.top, 1 - rect.right, rect.bottom, 1 - rect.left );
|
||||
break;
|
||||
default:
|
||||
newRect = rect;
|
||||
break;
|
||||
}
|
||||
|
||||
return newRect;
|
||||
}
|
||||
|
||||
NormalizedRect NormalizedRect::fromRotatedRect( const NormalizedRect &rect, Rotation rotation )
|
||||
{
|
||||
if ( rotation == Rotation0 )
|
||||
return rect;
|
||||
|
||||
NormalizedRect newRect;
|
||||
switch ( rotation )
|
||||
{
|
||||
case Rotation90:
|
||||
newRect = NormalizedRect( rect.top, 1 - rect.right, rect.bottom, 1 - rect.left );
|
||||
break;
|
||||
case Rotation180:
|
||||
newRect = NormalizedRect( 1 - rect.right, 1 - rect.bottom, 1 - rect.left, 1 - rect.top );
|
||||
break;
|
||||
case Rotation270:
|
||||
newRect = NormalizedRect( 1 - rect.bottom, rect.left, 1 - rect.top, rect.right );
|
||||
break;
|
||||
default:
|
||||
newRect = rect;
|
||||
break;
|
||||
}
|
||||
|
||||
return newRect;
|
||||
}
|
||||
|
|
|
@ -299,6 +299,16 @@ class OKULAR_EXPORT NormalizedRect
|
|||
return pow( distX * xScale, 2 ) + pow( distY * yScale, 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a rotated NormalizedRect given a @p rotation
|
||||
*/
|
||||
static NormalizedRect toRotatedRect( const NormalizedRect &rect, Rotation rotation );
|
||||
|
||||
/**
|
||||
* Returns a non rotated version of @p rect, which is rotated by @p rotation
|
||||
*/
|
||||
static NormalizedRect fromRotatedRect( const NormalizedRect &rect, Rotation rotation );
|
||||
|
||||
/**
|
||||
* The normalized left coordinate.
|
||||
*/
|
||||
|
|
|
@ -76,8 +76,6 @@
|
|||
#include "sourcereference.h"
|
||||
#include "sourcereference_p.h"
|
||||
#include "texteditors_p.h"
|
||||
#include "tile.h"
|
||||
#include "tilesmanager_p.h"
|
||||
#include "utils_p.h"
|
||||
#include "view.h"
|
||||
#include "view_p.h"
|
||||
|
@ -373,8 +371,6 @@ void DocumentPrivate::cleanupPixmapMemory( qulonglong memoryToFree )
|
|||
delete p;
|
||||
}
|
||||
|
||||
// If we're still on low memory, try to free individual tiles
|
||||
|
||||
// Store pages that weren't completely removed
|
||||
|
||||
QList< AllocatedPixmap * > pixmapsToKeep;
|
||||
|
@ -388,30 +384,7 @@ void DocumentPrivate::cleanupPixmapMemory( qulonglong memoryToFree )
|
|||
continue;
|
||||
|
||||
clean_hits++;
|
||||
|
||||
TilesManager *tilesManager = m_pagesVector.at( p->page )->d->tilesManager( observer );
|
||||
if ( tilesManager && tilesManager->totalMemory() > 0 )
|
||||
{
|
||||
qulonglong memoryDiff = p->memory;
|
||||
NormalizedRect visibleRect;
|
||||
if ( visibleRects.contains( p->page ) )
|
||||
visibleRect = visibleRects[ p->page ]->rect;
|
||||
|
||||
// Free non visible tiles
|
||||
tilesManager->cleanupPixmapMemory( memoryToFree, visibleRect, currentViewportPage );
|
||||
|
||||
p->memory = tilesManager->totalMemory();
|
||||
memoryDiff -= p->memory;
|
||||
memoryToFree = (memoryDiff < memoryToFree) ? (memoryToFree - memoryDiff) : 0;
|
||||
m_allocatedPixmapsTotalMemory -= memoryDiff;
|
||||
|
||||
if ( p->memory > 0 )
|
||||
pixmapsToKeep.append( p );
|
||||
else
|
||||
delete p;
|
||||
}
|
||||
else
|
||||
pixmapsToKeep.append( p );
|
||||
pixmapsToKeep.append( p );
|
||||
}
|
||||
|
||||
if (clean_hits == 0) break;
|
||||
|
@ -1301,8 +1274,7 @@ void DocumentPrivate::sendGeneratorPixmapRequest()
|
|||
continue;
|
||||
}
|
||||
|
||||
QRect requestRect = r->isTile() ? r->normalizedRect().geometry( r->width(), r->height() ) : QRect( 0, 0, r->width(), r->height() );
|
||||
TilesManager *tilesManager = r->d->tilesManager();
|
||||
QRect requestRect = QRect( 0, 0, r->width(), r->height() );
|
||||
|
||||
// If it's a preload but the generator is not threaded no point in trying to preload
|
||||
if ( r->preload() && !m_generator->hasFeature( Generator::Threaded ) )
|
||||
|
@ -1323,80 +1295,6 @@ void DocumentPrivate::sendGeneratorPixmapRequest()
|
|||
//kDebug() << "Ignoring request that doesn't fit in cache";
|
||||
delete r;
|
||||
}
|
||||
// Ignore requests for pixmaps that are already being generated
|
||||
else if ( tilesManager && tilesManager->isRequesting( r->normalizedRect(), r->width(), r->height() ) )
|
||||
{
|
||||
m_pixmapRequestsStack.pop_back();
|
||||
delete r;
|
||||
}
|
||||
// If the requested area is above 8000000 pixels, switch on the tile manager
|
||||
else if ( !tilesManager && m_generator->hasFeature( Generator::TiledRendering ) && (long)r->width() * (long)r->height() > 8000000L )
|
||||
{
|
||||
// if the image is too big. start using tiles
|
||||
kDebug(OkularDebug).nospace() << "Start using tiles on page " << r->pageNumber()
|
||||
<< " (" << r->width() << "x" << r->height() << " px);";
|
||||
|
||||
// fill the tiles manager with the last rendered pixmap
|
||||
const QPixmap *pixmap = r->page()->_o_nearestPixmap( r->observer(), r->width(), r->height() );
|
||||
if ( pixmap )
|
||||
{
|
||||
tilesManager = new TilesManager( r->pageNumber(), pixmap->width(), pixmap->height(), r->page()->rotation() );
|
||||
tilesManager->setPixmap( pixmap, NormalizedRect( 0, 0, 1, 1 ) );
|
||||
tilesManager->setSize( r->width(), r->height() );
|
||||
}
|
||||
else
|
||||
{
|
||||
// create new tiles manager
|
||||
tilesManager = new TilesManager( r->pageNumber(), r->width(), r->height(), r->page()->rotation() );
|
||||
}
|
||||
tilesManager->setRequest( r->normalizedRect(), r->width(), r->height() );
|
||||
r->page()->deletePixmap( r->observer() );
|
||||
r->page()->d->setTilesManager( r->observer(), tilesManager );
|
||||
r->setTile( true );
|
||||
|
||||
// Change normalizedRect to the smallest rect that contains all
|
||||
// visible tiles.
|
||||
if ( !r->normalizedRect().isNull() )
|
||||
{
|
||||
NormalizedRect tilesRect;
|
||||
const QList<Tile> tiles = tilesManager->tilesAt( r->normalizedRect(), TilesManager::TerminalTile );
|
||||
QList<Tile>::const_iterator tIt = tiles.constBegin(), tEnd = tiles.constEnd();
|
||||
while ( tIt != tEnd )
|
||||
{
|
||||
Tile tile = *tIt;
|
||||
if ( tilesRect.isNull() )
|
||||
tilesRect = tile.rect();
|
||||
else
|
||||
tilesRect |= tile.rect();
|
||||
|
||||
++tIt;
|
||||
}
|
||||
|
||||
r->setNormalizedRect( tilesRect );
|
||||
request = r;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Discard request if normalizedRect is null. This happens in
|
||||
// preload requests issued by PageView if the requested page is
|
||||
// not visible and the user has just switched from a non-tiled
|
||||
// zoom level to a tiled one
|
||||
m_pixmapRequestsStack.pop_back();
|
||||
delete r;
|
||||
}
|
||||
}
|
||||
// If the requested area is below 6000000 pixels, switch off the tile manager
|
||||
else if ( tilesManager && (long)r->width() * (long)r->height() < 6000000L )
|
||||
{
|
||||
kDebug(OkularDebug).nospace() << "Stop using tiles on page " << r->pageNumber()
|
||||
<< " (" << r->width() << "x" << r->height() << " px);";
|
||||
|
||||
// page is too small. stop using tiles.
|
||||
r->page()->deletePixmap( r->observer() );
|
||||
r->setTile( false );
|
||||
|
||||
request = r;
|
||||
}
|
||||
else if ( (long)requestRect.width() * (long)requestRect.height() > 20000000L )
|
||||
{
|
||||
m_pixmapRequestsStack.pop_back();
|
||||
|
@ -1423,12 +1321,7 @@ void DocumentPrivate::sendGeneratorPixmapRequest()
|
|||
}
|
||||
|
||||
// [MEM] preventive memory freeing
|
||||
qulonglong pixmapBytes = 0;
|
||||
TilesManager * tm = request->d->tilesManager();
|
||||
if ( tm )
|
||||
pixmapBytes = tm->totalMemory();
|
||||
else
|
||||
pixmapBytes = 4 * request->width() * request->height();
|
||||
qulonglong pixmapBytes = 4 * request->width() * request->height();
|
||||
|
||||
if ( pixmapBytes > (1024 * 1024) )
|
||||
cleanupPixmapMemory( memoryToFree /* previously calculated value */ );
|
||||
|
@ -1436,19 +1329,15 @@ void DocumentPrivate::sendGeneratorPixmapRequest()
|
|||
// submit the request to the generator
|
||||
if ( m_generator->canGeneratePixmap() )
|
||||
{
|
||||
QRect requestRect = !request->isTile() ? QRect(0, 0, request->width(), request->height() ) : request->normalizedRect().geometry( request->width(), request->height() );
|
||||
kDebug(OkularDebug).nospace() << "sending request observer=" << request->observer() << " " <<requestRect.width() << "x" << requestRect.height() << "@" << request->pageNumber() << " async == " << request->asynchronous() << " isTile == " << request->isTile();
|
||||
QRect requestRect = QRect(0, 0, request->width(), request->height() );
|
||||
kDebug(OkularDebug).nospace() << "sending request observer=" << request->observer() << " " <<requestRect.width() << "x" << requestRect.height() << "@" << request->pageNumber() << " async == " << request->asynchronous();
|
||||
m_pixmapRequestsStack.removeAll ( request );
|
||||
|
||||
if ( tm )
|
||||
tm->setRequest( request->normalizedRect(), request->width(), request->height() );
|
||||
|
||||
if ( (int)m_rotation % 2 )
|
||||
request->d->swap();
|
||||
|
||||
if ( m_rotation != Rotation0 && !request->normalizedRect().isNull() )
|
||||
request->setNormalizedRect( TilesManager::fromRotatedRect(
|
||||
request->normalizedRect(), m_rotation ) );
|
||||
request->setNormalizedRect( NormalizedRect::fromRotatedRect(request->normalizedRect(), m_rotation ) );
|
||||
|
||||
// we always have to unlock _before_ the generatePixmap() because
|
||||
// a sync generation would end with requestDone() -> deadlock, and
|
||||
|
@ -1553,43 +1442,6 @@ void DocumentPrivate::refreshPixmaps( int pageNumber )
|
|||
requestedPixmaps.push_back( p );
|
||||
}
|
||||
|
||||
foreach (DocumentObserver *observer, m_observers)
|
||||
{
|
||||
TilesManager *tilesManager = page->d->tilesManager( observer );
|
||||
if ( tilesManager )
|
||||
{
|
||||
tilesManager->markDirty();
|
||||
|
||||
PixmapRequest * p = new PixmapRequest( observer, pageNumber, tilesManager->width(), tilesManager->height(), 1, PixmapRequest::Asynchronous );
|
||||
|
||||
NormalizedRect tilesRect;
|
||||
|
||||
// Get the visible page rect
|
||||
NormalizedRect visibleRect;
|
||||
QVector< Okular::VisiblePageRect * >::const_iterator vIt = m_pageRects.constBegin(), vEnd = m_pageRects.constEnd();
|
||||
for ( ; vIt != vEnd; ++vIt )
|
||||
{
|
||||
if ( (*vIt)->pageNumber == pageNumber )
|
||||
{
|
||||
visibleRect = (*vIt)->rect;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !visibleRect.isNull() )
|
||||
{
|
||||
p->setNormalizedRect( visibleRect );
|
||||
p->setTile( true );
|
||||
p->d->mForce = true;
|
||||
requestedPixmaps.push_back( p );
|
||||
}
|
||||
else
|
||||
{
|
||||
delete p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !requestedPixmaps.isEmpty() )
|
||||
m_parent->requestPixmaps( requestedPixmaps, Okular::Document::NoOption );
|
||||
}
|
||||
|
@ -2688,11 +2540,6 @@ bool Document::supportsPageSizes() const
|
|||
return d->m_generator ? d->m_generator->hasFeature( Generator::PageSizes ) : false;
|
||||
}
|
||||
|
||||
bool Document::supportsTiles() const
|
||||
{
|
||||
return d->m_generator ? d->m_generator->hasFeature( Generator::TiledRendering ) : false;
|
||||
}
|
||||
|
||||
PageSize::List Document::pageSizes() const
|
||||
{
|
||||
if ( d->m_generator )
|
||||
|
@ -2850,30 +2697,6 @@ void Document::requestPixmaps( const QList< PixmapRequest * > & requests, Pixmap
|
|||
|
||||
request->d->mPage = d->m_pagesVector.value( request->pageNumber() );
|
||||
|
||||
if ( request->isTile() )
|
||||
{
|
||||
// Change the current request rect so that only invalid tiles are
|
||||
// requested. Also make sure the rect is tile-aligned.
|
||||
NormalizedRect tilesRect;
|
||||
const QList<Tile> tiles = request->d->tilesManager()->tilesAt( request->normalizedRect(), TilesManager::TerminalTile );
|
||||
QList<Tile>::const_iterator tIt = tiles.constBegin(), tEnd = tiles.constEnd();
|
||||
while ( tIt != tEnd )
|
||||
{
|
||||
const Tile &tile = *tIt;
|
||||
if ( !tile.isValid() )
|
||||
{
|
||||
if ( tilesRect.isNull() )
|
||||
tilesRect = tile.rect();
|
||||
else
|
||||
tilesRect |= tile.rect();
|
||||
}
|
||||
|
||||
tIt++;
|
||||
}
|
||||
|
||||
request->setNormalizedRect( tilesRect );
|
||||
}
|
||||
|
||||
if ( !request->asynchronous() )
|
||||
request->d->mPriority = 0;
|
||||
|
||||
|
@ -4301,12 +4124,7 @@ void DocumentPrivate::requestDone( PixmapRequest * req )
|
|||
if ( m_observers.contains(observer) )
|
||||
{
|
||||
// [MEM] 1.2 append memory allocation descriptor to the FIFO
|
||||
qulonglong memoryBytes = 0;
|
||||
const TilesManager *tm = req->d->tilesManager();
|
||||
if ( tm )
|
||||
memoryBytes = tm->totalMemory();
|
||||
else
|
||||
memoryBytes = 4 * req->width() * req->height();
|
||||
qulonglong memoryBytes = 4 * req->width() * req->height();
|
||||
|
||||
AllocatedPixmap * memoryPage = new AllocatedPixmap( req->observer(), req->pageNumber(), memoryBytes );
|
||||
m_allocatedPixmaps.append( memoryPage );
|
||||
|
|
|
@ -229,13 +229,6 @@ class OKULAR_EXPORT Document : public QObject
|
|||
*/
|
||||
bool supportsPageSizes() const;
|
||||
|
||||
/**
|
||||
* Returns whether the current document supports tiles
|
||||
*
|
||||
* @since 0.16 (KDE 4.10)
|
||||
*/
|
||||
bool supportsTiles() const;
|
||||
|
||||
/**
|
||||
* Returns the list of supported page sizes or an empty list if this
|
||||
* feature is not available.
|
||||
|
|
|
@ -236,7 +236,7 @@ void Generator::generatePixmap( PixmapRequest *request )
|
|||
Q_D( Generator );
|
||||
d->mPixmapReady = false;
|
||||
|
||||
const bool calcBoundingBox = !request->isTile() && !request->page()->isBoundingBoxKnown();
|
||||
const bool calcBoundingBox = !request->page()->isBoundingBoxKnown();
|
||||
|
||||
if ( request->asynchronous() && hasFeature( Threaded ) )
|
||||
{
|
||||
|
@ -467,7 +467,6 @@ PixmapRequest::PixmapRequest( DocumentObserver *observer, int pageNumber, int wi
|
|||
d->mPriority = priority;
|
||||
d->mFeatures = features;
|
||||
d->mForce = false;
|
||||
d->mTile = false;
|
||||
d->mNormalizedRect = NormalizedRect();
|
||||
}
|
||||
|
||||
|
@ -516,16 +515,6 @@ Page* PixmapRequest::page() const
|
|||
return d->mPage;
|
||||
}
|
||||
|
||||
void PixmapRequest::setTile( bool tile )
|
||||
{
|
||||
d->mTile = tile;
|
||||
}
|
||||
|
||||
bool PixmapRequest::isTile() const
|
||||
{
|
||||
return d->mTile;
|
||||
}
|
||||
|
||||
void PixmapRequest::setNormalizedRect( const NormalizedRect &rect )
|
||||
{
|
||||
if ( d->mNormalizedRect == rect )
|
||||
|
@ -539,11 +528,6 @@ const NormalizedRect& PixmapRequest::normalizedRect() const
|
|||
return d->mNormalizedRect;
|
||||
}
|
||||
|
||||
Okular::TilesManager* PixmapRequestPrivate::tilesManager() const
|
||||
{
|
||||
return mPage->d->tilesManager(mObserver);
|
||||
}
|
||||
|
||||
void PixmapRequestPrivate::swap()
|
||||
{
|
||||
qSwap( mWidth, mHeight );
|
||||
|
|
|
@ -202,8 +202,7 @@ class OKULAR_EXPORT Generator : public QObject
|
|||
ReadRawData, ///< Whether the Generator can read a document directly from its raw data.
|
||||
FontInfo, ///< Whether the Generator can provide information about the fonts used in the document
|
||||
PageSizes, ///< Whether the Generator can change the size of the document pages.
|
||||
PrintNative, ///< Whether the Generator supports native cross-platform printing (QPainter-based).
|
||||
TiledRendering ///< Whether the Generator can render tiles @since 0.16 (KDE 4.10)
|
||||
PrintNative ///< Whether the Generator supports native cross-platform printing (QPainter-based).
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -637,22 +636,6 @@ class OKULAR_EXPORT PixmapRequest
|
|||
*/
|
||||
Page *page() const;
|
||||
|
||||
/**
|
||||
* Sets whether the generator should render only the given normalized
|
||||
* rect or the entire page
|
||||
*
|
||||
* @since 0.16 (KDE 4.10)
|
||||
*/
|
||||
void setTile( bool tile );
|
||||
|
||||
/**
|
||||
* Returns whether the generator should render just the region given by
|
||||
* normalizedRect() or the entire page.
|
||||
*
|
||||
* @since 0.16 (KDE 4.10)
|
||||
*/
|
||||
bool isTile() const;
|
||||
|
||||
/**
|
||||
* Sets the region of the page to request.
|
||||
*
|
||||
|
|
|
@ -30,7 +30,6 @@ class PixmapGenerationThread;
|
|||
class PixmapRequest;
|
||||
class TextPage;
|
||||
class TextPageGenerationThread;
|
||||
class TilesManager;
|
||||
|
||||
class GeneratorPrivate
|
||||
{
|
||||
|
@ -73,7 +72,6 @@ class PixmapRequestPrivate
|
|||
{
|
||||
public:
|
||||
void swap();
|
||||
TilesManager *tilesManager() const;
|
||||
|
||||
DocumentObserver *mObserver;
|
||||
int mPageNumber;
|
||||
|
@ -81,8 +79,7 @@ class PixmapRequestPrivate
|
|||
int mHeight;
|
||||
int mPriority;
|
||||
int mFeatures;
|
||||
bool mForce : 1;
|
||||
bool mTile : 1;
|
||||
bool mForce;
|
||||
Page *mPage;
|
||||
NormalizedRect mNormalizedRect;
|
||||
};
|
||||
|
|
|
@ -37,8 +37,6 @@
|
|||
#include "rotationjob_p.h"
|
||||
#include "textpage.h"
|
||||
#include "textpage_p.h"
|
||||
#include "tile.h"
|
||||
#include "tilesmanager_p.h"
|
||||
#include "utils_p.h"
|
||||
|
||||
#include <limits>
|
||||
|
@ -92,15 +90,6 @@ PagePrivate::~PagePrivate()
|
|||
|
||||
void PagePrivate::imageRotationDone( RotationJob * job )
|
||||
{
|
||||
TilesManager *tm = tilesManager( job->observer() );
|
||||
if ( tm )
|
||||
{
|
||||
QPixmap *pixmap = new QPixmap( QPixmap::fromImage( job->image() ) );
|
||||
tm->setPixmap( pixmap, job->rect() );
|
||||
delete pixmap;
|
||||
return;
|
||||
}
|
||||
|
||||
QMap< DocumentObserver*, PixmapObject >::iterator it = m_pixmaps.find( job->observer() );
|
||||
if ( it != m_pixmaps.end() )
|
||||
{
|
||||
|
@ -201,18 +190,6 @@ void Page::setBoundingBox( const NormalizedRect& bbox )
|
|||
|
||||
bool Page::hasPixmap( DocumentObserver *observer, int width, int height, const NormalizedRect &rect ) const
|
||||
{
|
||||
TilesManager *tm = d->tilesManager( observer );
|
||||
if ( tm )
|
||||
{
|
||||
if ( width != tm->width() || height != tm->height() )
|
||||
{
|
||||
tm->setSize( width, height );
|
||||
return false;
|
||||
}
|
||||
|
||||
return tm->hasPixmap( rect );
|
||||
}
|
||||
|
||||
QMap< DocumentObserver*, PagePrivate::PixmapObject >::const_iterator it = d->m_pixmaps.constFind( observer );
|
||||
if ( it == d->m_pixmaps.constEnd() )
|
||||
return false;
|
||||
|
@ -376,18 +353,6 @@ void PagePrivate::rotateAt( Rotation orientation )
|
|||
m_doc->m_pageController->addRotationJob(job);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotate tiles manager
|
||||
*/
|
||||
QMapIterator<const DocumentObserver *, TilesManager *> i(m_tilesManagers);
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
|
||||
TilesManager *tm = i.value();
|
||||
if ( tm )
|
||||
tm->setRotation( m_rotation );
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotate the object rects on the page.
|
||||
*/
|
||||
|
@ -507,14 +472,6 @@ QList< FormField * > Page::formFields() const
|
|||
void Page::setPixmap( DocumentObserver *observer, QPixmap *pixmap, const NormalizedRect &rect )
|
||||
{
|
||||
if ( d->m_rotation == Rotation0 ) {
|
||||
TilesManager *tm = d->tilesManager( observer );
|
||||
if ( tm )
|
||||
{
|
||||
tm->setPixmap( pixmap, rect );
|
||||
delete pixmap;
|
||||
return;
|
||||
}
|
||||
|
||||
QMap< DocumentObserver*, PagePrivate::PixmapObject >::iterator it = d->m_pixmaps.find( observer );
|
||||
if ( it != d->m_pixmaps.end() )
|
||||
{
|
||||
|
@ -529,7 +486,7 @@ void Page::setPixmap( DocumentObserver *observer, QPixmap *pixmap, const Normali
|
|||
} else {
|
||||
RotationJob *job = new RotationJob( pixmap->toImage(), Rotation0, d->m_rotation, observer );
|
||||
job->setPage( d );
|
||||
job->setRect( TilesManager::toRotatedRect( rect, d->m_rotation ) );
|
||||
job->setRect( NormalizedRect::toRotatedRect( rect, d->m_rotation ) );
|
||||
d->m_doc->m_pageController->addRotationJob(job);
|
||||
|
||||
delete pixmap;
|
||||
|
@ -711,17 +668,8 @@ void Page::setFormFields( const QList< FormField * >& fields )
|
|||
|
||||
void Page::deletePixmap( DocumentObserver *observer )
|
||||
{
|
||||
TilesManager *tm = d->tilesManager( observer );
|
||||
if ( tm )
|
||||
{
|
||||
delete tm;
|
||||
d->m_tilesManagers.remove(observer);
|
||||
}
|
||||
else
|
||||
{
|
||||
PagePrivate::PixmapObject object = d->m_pixmaps.take( observer );
|
||||
delete object.m_pixmap;
|
||||
}
|
||||
PagePrivate::PixmapObject object = d->m_pixmaps.take( observer );
|
||||
delete object.m_pixmap;
|
||||
}
|
||||
|
||||
void Page::deletePixmaps()
|
||||
|
@ -733,9 +681,6 @@ void Page::deletePixmaps()
|
|||
}
|
||||
|
||||
d->m_pixmaps.clear();
|
||||
|
||||
qDeleteAll(d->m_tilesManagers);
|
||||
d->m_tilesManagers.clear();
|
||||
}
|
||||
|
||||
void Page::deleteRects()
|
||||
|
@ -989,30 +934,3 @@ const QPixmap * Page::_o_nearestPixmap( DocumentObserver *observer, int w, int h
|
|||
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
bool Page::hasTilesManager( const DocumentObserver *observer ) const
|
||||
{
|
||||
return d->tilesManager( observer ) != 0;
|
||||
}
|
||||
|
||||
QList<Tile> Page::tilesAt( const DocumentObserver *observer, const NormalizedRect &rect ) const
|
||||
{
|
||||
TilesManager *tm = d->m_tilesManagers.value( observer );
|
||||
if ( tm )
|
||||
return tm->tilesAt( rect, TilesManager::PixmapTile );
|
||||
else
|
||||
return QList<Tile>();
|
||||
}
|
||||
|
||||
TilesManager *PagePrivate::tilesManager( const DocumentObserver *observer ) const
|
||||
{
|
||||
return m_tilesManagers.value( observer );
|
||||
}
|
||||
|
||||
void PagePrivate::setTilesManager( const DocumentObserver *observer, TilesManager *tm )
|
||||
{
|
||||
TilesManager *old = m_tilesManagers.value( observer );
|
||||
delete old;
|
||||
|
||||
m_tilesManagers.insert(observer, tm);
|
||||
}
|
||||
|
|
|
@ -32,7 +32,6 @@ class PagePrivate;
|
|||
class PageTransition;
|
||||
class SourceReference;
|
||||
class TextSelection;
|
||||
class Tile;
|
||||
|
||||
/**
|
||||
* @short Collector for all the data belonging to a page.
|
||||
|
@ -368,23 +367,6 @@ class OKULAR_EXPORT Page
|
|||
*/
|
||||
void deleteAnnotations();
|
||||
|
||||
/**
|
||||
* Returns whether pixmaps for the tiled observer are handled by a
|
||||
* tile manager.
|
||||
*
|
||||
* @since 0.19 (KDE 4.13)
|
||||
*/
|
||||
bool hasTilesManager( const DocumentObserver *observer ) const;
|
||||
|
||||
/**
|
||||
* Returns a list of all tiles intersecting with @p rect.
|
||||
*
|
||||
* The list contains only tiles with a pixmap
|
||||
*
|
||||
* @since 0.19 (KDE 4.13)
|
||||
*/
|
||||
QList<Tile> tilesAt( const DocumentObserver *observer, const NormalizedRect &rect ) const;
|
||||
|
||||
private:
|
||||
PagePrivate* const d;
|
||||
/// @cond PRIVATE
|
||||
|
|
|
@ -37,7 +37,6 @@ class PageSize;
|
|||
class PageTransition;
|
||||
class RotationJob;
|
||||
class TextPage;
|
||||
class TilesManager;
|
||||
|
||||
enum PageItem
|
||||
{
|
||||
|
@ -104,16 +103,6 @@ class PagePrivate
|
|||
*/
|
||||
void deleteTextSelections();
|
||||
|
||||
/**
|
||||
* Get the tiles manager for the tiled @observer
|
||||
*/
|
||||
TilesManager *tilesManager( const DocumentObserver *observer ) const;
|
||||
|
||||
/**
|
||||
* Set the tiles manager for the tiled @observer
|
||||
*/
|
||||
void setTilesManager( const DocumentObserver *observer, TilesManager *tm );
|
||||
|
||||
class PixmapObject
|
||||
{
|
||||
public:
|
||||
|
@ -121,7 +110,6 @@ class PagePrivate
|
|||
Rotation m_rotation;
|
||||
};
|
||||
QMap< DocumentObserver*, PixmapObject > m_pixmaps;
|
||||
QMap< const DocumentObserver*, TilesManager *> m_tilesManagers;
|
||||
|
||||
Page *m_page;
|
||||
int m_number;
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2012 by Fabio D'Urso <fabiodurso@hotmail.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. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef _OKULAR_TILE_H_
|
||||
#define _OKULAR_TILE_H_
|
||||
|
||||
#include "area.h"
|
||||
|
||||
#include <QPixmap>
|
||||
|
||||
namespace Okular {
|
||||
|
||||
/**
|
||||
* This class represents a rectangular portion of a page.
|
||||
*
|
||||
* It doesn't take ownership of pixmap
|
||||
*
|
||||
* @since 0.16 (KDE 4.10)
|
||||
*/
|
||||
class OKULAR_EXPORT Tile
|
||||
{
|
||||
public:
|
||||
Tile( const NormalizedRect &rect, QPixmap *pixmap, bool isValid );
|
||||
Tile( const Tile &t );
|
||||
~Tile();
|
||||
|
||||
/**
|
||||
* Location of the tile
|
||||
*/
|
||||
NormalizedRect rect() const;
|
||||
|
||||
/**
|
||||
* Pixmap (may also be NULL)
|
||||
*/
|
||||
QPixmap * pixmap() const;
|
||||
|
||||
/**
|
||||
* True if the pixmap is available and updated
|
||||
*/
|
||||
bool isValid() const;
|
||||
|
||||
Tile& operator=( const Tile &other );
|
||||
|
||||
private:
|
||||
class Private;
|
||||
Private * d;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // _OKULAR_TILE_H_
|
|
@ -1,709 +0,0 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2012 by Mailson Menezes <mailson@gmail.com> *
|
||||
* 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 "tilesmanager_p.h"
|
||||
|
||||
#include <QPixmap>
|
||||
#include <QtCore/qmath.h>
|
||||
#include <QList>
|
||||
#include <QPainter>
|
||||
|
||||
#include "tile.h"
|
||||
|
||||
#define TILES_MAXSIZE 2000000
|
||||
|
||||
using namespace Okular;
|
||||
|
||||
static bool rankedTilesLessThan( TileNode *t1, TileNode *t2 )
|
||||
{
|
||||
// Order tiles by its dirty state and then by distance from the viewport.
|
||||
if ( t1->dirty == t2->dirty )
|
||||
return t1->distance < t2->distance;
|
||||
|
||||
return !t1->dirty;
|
||||
}
|
||||
|
||||
class TilesManager::Private
|
||||
{
|
||||
public:
|
||||
Private();
|
||||
|
||||
bool hasPixmap( const NormalizedRect &rect, const TileNode &tile ) const;
|
||||
void tilesAt( const NormalizedRect &rect, TileNode &tile, QList<Tile> &result, TileLeaf tileLeaf );
|
||||
void setPixmap( const QPixmap *pixmap, const NormalizedRect &rect, TileNode &tile );
|
||||
|
||||
/**
|
||||
* Mark @p tile and all its children as dirty
|
||||
*/
|
||||
static void markDirty( TileNode &tile );
|
||||
|
||||
/**
|
||||
* Deletes all tiles, recursively
|
||||
*/
|
||||
void deleteTiles( const TileNode &tile );
|
||||
|
||||
void markParentDirty( const TileNode &tile );
|
||||
void rankTiles( TileNode &tile, QList<TileNode*> &rankedTiles, const NormalizedRect &visibleRect, int visiblePageNumber );
|
||||
/**
|
||||
* Since the tile can be large enough to occupy a significant amount of
|
||||
* space, they may be split in more tiles. This operation is performed
|
||||
* when the tiles of a certain region is requested and they are bigger
|
||||
* than an arbitrary value. Only tiles intersecting the desired region
|
||||
* are split. There's no need to do this for the entire page.
|
||||
*/
|
||||
void split( TileNode &tile, const NormalizedRect &rect );
|
||||
|
||||
/**
|
||||
* Checks whether the tile's size is bigger than an arbitrary value and
|
||||
* performs the split operation returning true.
|
||||
* Otherwise it just returns false, without performing any operation.
|
||||
*/
|
||||
bool splitBigTiles( TileNode &tile, const NormalizedRect &rect );
|
||||
|
||||
// The page is split in a 4x4 grid of tiles
|
||||
TileNode tiles[16];
|
||||
int width;
|
||||
int height;
|
||||
int pageNumber;
|
||||
qulonglong totalPixels;
|
||||
Rotation rotation;
|
||||
NormalizedRect visibleRect;
|
||||
NormalizedRect requestRect;
|
||||
int requestWidth;
|
||||
int requestHeight;
|
||||
};
|
||||
|
||||
TilesManager::Private::Private()
|
||||
: width( 0 )
|
||||
, height( 0 )
|
||||
, pageNumber( 0 )
|
||||
, totalPixels( 0 )
|
||||
, rotation( Rotation0 )
|
||||
, requestRect( NormalizedRect() )
|
||||
, requestWidth( 0 )
|
||||
, requestHeight( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
TilesManager::TilesManager( int pageNumber, int width, int height, Rotation rotation )
|
||||
: d( new Private )
|
||||
{
|
||||
d->pageNumber = pageNumber;
|
||||
d->width = width;
|
||||
d->height = height;
|
||||
d->rotation = rotation;
|
||||
|
||||
// The page is split in a 4x4 grid of tiles
|
||||
const double dim = 0.25;
|
||||
for ( int i = 0; i < 16; ++i )
|
||||
{
|
||||
int x = i % 4;
|
||||
int y = i / 4;
|
||||
d->tiles[ i ].rect = NormalizedRect( x*dim, y*dim, x*dim+dim, y*dim+dim );
|
||||
}
|
||||
}
|
||||
|
||||
TilesManager::~TilesManager()
|
||||
{
|
||||
for ( int i = 0; i < 16; ++i )
|
||||
d->deleteTiles( d->tiles[ i ] );
|
||||
|
||||
delete d;
|
||||
}
|
||||
|
||||
void TilesManager::Private::deleteTiles( const TileNode &tile )
|
||||
{
|
||||
if ( tile.pixmap )
|
||||
{
|
||||
totalPixels -= tile.pixmap->width()*tile.pixmap->height();
|
||||
delete tile.pixmap;
|
||||
}
|
||||
|
||||
if ( tile.nTiles > 0 )
|
||||
{
|
||||
for ( int i = 0; i < tile.nTiles; ++i )
|
||||
deleteTiles( tile.tiles[ i ] );
|
||||
|
||||
delete [] tile.tiles;
|
||||
}
|
||||
}
|
||||
|
||||
void TilesManager::setSize( int width, int height )
|
||||
{
|
||||
if ( width == d->width && height == d->height )
|
||||
return;
|
||||
|
||||
d->width = width;
|
||||
d->height = height;
|
||||
|
||||
markDirty();
|
||||
}
|
||||
|
||||
int TilesManager::width() const
|
||||
{
|
||||
return d->width;
|
||||
}
|
||||
|
||||
int TilesManager::height() const
|
||||
{
|
||||
return d->height;
|
||||
}
|
||||
|
||||
void TilesManager::setRotation( Rotation rotation )
|
||||
{
|
||||
if ( rotation == d->rotation )
|
||||
return;
|
||||
|
||||
d->rotation = rotation;
|
||||
}
|
||||
|
||||
Rotation TilesManager::rotation() const
|
||||
{
|
||||
return d->rotation;
|
||||
}
|
||||
|
||||
void TilesManager::markDirty()
|
||||
{
|
||||
for ( int i = 0; i < 16; ++i )
|
||||
{
|
||||
TilesManager::Private::markDirty( d->tiles[ i ] );
|
||||
}
|
||||
}
|
||||
|
||||
void TilesManager::Private::markDirty( TileNode &tile )
|
||||
{
|
||||
tile.dirty = true;
|
||||
|
||||
for ( int i = 0; i < tile.nTiles; ++i )
|
||||
{
|
||||
markDirty( tile.tiles[ i ] );
|
||||
}
|
||||
}
|
||||
|
||||
void TilesManager::setPixmap( const QPixmap *pixmap, const NormalizedRect &rect )
|
||||
{
|
||||
NormalizedRect rotatedRect = TilesManager::fromRotatedRect( rect, d->rotation );
|
||||
if ( !d->requestRect.isNull() )
|
||||
{
|
||||
if ( !(d->requestRect == rect) )
|
||||
return;
|
||||
|
||||
// Check whether the pixmap has the same absolute size of the expected
|
||||
// request.
|
||||
// If the document is rotated, rotate requestRect back to the original
|
||||
// rotation before comparing to pixmap's size. This is to avoid
|
||||
// conversion issues. The pixmap request was made using an unrotated
|
||||
// rect.
|
||||
QSize pixmapSize = pixmap->size();
|
||||
int w = width();
|
||||
int h = height();
|
||||
if ( d->rotation % 2 )
|
||||
{
|
||||
qSwap(w, h);
|
||||
pixmapSize.transpose();
|
||||
}
|
||||
|
||||
if ( rotatedRect.geometry( w, h ).size() != pixmapSize )
|
||||
return;
|
||||
|
||||
d->requestRect = NormalizedRect();
|
||||
}
|
||||
|
||||
for ( int i = 0; i < 16; ++i )
|
||||
{
|
||||
d->setPixmap( pixmap, rotatedRect, d->tiles[ i ] );
|
||||
}
|
||||
}
|
||||
|
||||
void TilesManager::Private::setPixmap( const QPixmap *pixmap, const NormalizedRect &rect, TileNode &tile )
|
||||
{
|
||||
QRect pixmapRect = TilesManager::toRotatedRect( rect, rotation ).geometry( width, height );
|
||||
|
||||
// Exclude tiles outside the viewport
|
||||
if ( !tile.rect.intersects( rect ) )
|
||||
return;
|
||||
|
||||
// if the tile is not entirely within the viewport (the tile intersects an
|
||||
// edged of the viewport), attempt to set the pixmap in the children tiles
|
||||
if ( !((tile.rect & rect) == tile.rect) )
|
||||
{
|
||||
// paint children tiles
|
||||
if ( tile.nTiles > 0 )
|
||||
{
|
||||
for ( int i = 0; i < tile.nTiles; ++i )
|
||||
setPixmap( pixmap, rect, tile.tiles[ i ] );
|
||||
|
||||
delete tile.pixmap;
|
||||
tile.pixmap = 0;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// the tile lies entirely within the viewport
|
||||
if ( tile.nTiles == 0 )
|
||||
{
|
||||
tile.dirty = false;
|
||||
|
||||
// check whether the tile size is big and split it if necessary
|
||||
if ( !splitBigTiles( tile, rect ) )
|
||||
{
|
||||
if ( tile.pixmap )
|
||||
{
|
||||
totalPixels -= tile.pixmap->width()*tile.pixmap->height();
|
||||
delete tile.pixmap;
|
||||
}
|
||||
NormalizedRect rotatedRect = TilesManager::toRotatedRect( tile.rect, rotation );
|
||||
tile.pixmap = new QPixmap( pixmap->copy( rotatedRect.geometry( width, height ).translated( -pixmapRect.topLeft() ) ) );
|
||||
tile.rotation = rotation;
|
||||
totalPixels += tile.pixmap->width()*tile.pixmap->height();
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( tile.pixmap )
|
||||
{
|
||||
totalPixels -= tile.pixmap->width()*tile.pixmap->height();
|
||||
delete tile.pixmap;
|
||||
tile.pixmap = 0;
|
||||
}
|
||||
|
||||
for ( int i = 0; i < tile.nTiles; ++i )
|
||||
setPixmap( pixmap, rect, tile.tiles[ i ] );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QRect tileRect = tile.rect.geometry( width, height );
|
||||
// sets the pixmap of the children tiles. if the tile's size is too
|
||||
// small, discards the children tiles and use the current one
|
||||
if ( tileRect.width()*tileRect.height() >= TILES_MAXSIZE )
|
||||
{
|
||||
tile.dirty = false;
|
||||
if ( tile.pixmap )
|
||||
{
|
||||
totalPixels -= tile.pixmap->width()*tile.pixmap->height();
|
||||
delete tile.pixmap;
|
||||
tile.pixmap = 0;
|
||||
}
|
||||
|
||||
for ( int i = 0; i < tile.nTiles; ++i )
|
||||
setPixmap( pixmap, rect, tile.tiles[ i ] );
|
||||
}
|
||||
else
|
||||
{
|
||||
// remove children tiles
|
||||
for ( int i = 0; i < tile.nTiles; ++i )
|
||||
{
|
||||
deleteTiles( tile.tiles[ i ] );
|
||||
tile.tiles[ i ].pixmap = 0;
|
||||
}
|
||||
|
||||
delete [] tile.tiles;
|
||||
tile.tiles = 0;
|
||||
tile.nTiles = 0;
|
||||
|
||||
// paint tile
|
||||
if ( tile.pixmap )
|
||||
{
|
||||
totalPixels -= tile.pixmap->width()*tile.pixmap->height();
|
||||
delete tile.pixmap;
|
||||
}
|
||||
NormalizedRect rotatedRect = TilesManager::toRotatedRect( tile.rect, rotation );
|
||||
tile.pixmap = new QPixmap( pixmap->copy( rotatedRect.geometry( width, height ).translated( -pixmapRect.topLeft() ) ) );
|
||||
tile.rotation = rotation;
|
||||
totalPixels += tile.pixmap->width()*tile.pixmap->height();
|
||||
tile.dirty = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool TilesManager::hasPixmap( const NormalizedRect &rect )
|
||||
{
|
||||
NormalizedRect rotatedRect = fromRotatedRect( rect, d->rotation );
|
||||
for ( int i = 0; i < 16; ++i )
|
||||
{
|
||||
if ( !d->hasPixmap( rotatedRect, d->tiles[ i ] ) )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TilesManager::Private::hasPixmap( const NormalizedRect &rect, const TileNode &tile ) const
|
||||
{
|
||||
if ( !tile.rect.intersects( rect ) )
|
||||
return true;
|
||||
|
||||
if ( tile.nTiles == 0 )
|
||||
return tile.isValid();
|
||||
|
||||
// all children tiles are clean. doesn't need to go deeper
|
||||
if ( !tile.dirty )
|
||||
return true;
|
||||
|
||||
for ( int i = 0; i < tile.nTiles; ++i )
|
||||
{
|
||||
if ( !hasPixmap( rect, tile.tiles[ i ] ) )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QList<Tile> TilesManager::tilesAt( const NormalizedRect &rect, TileLeaf tileLeaf )
|
||||
{
|
||||
QList<Tile> result;
|
||||
|
||||
NormalizedRect rotatedRect = fromRotatedRect( rect, d->rotation );
|
||||
for ( int i = 0; i < 16; ++i )
|
||||
{
|
||||
d->tilesAt( rotatedRect, d->tiles[ i ], result, tileLeaf );
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void TilesManager::Private::tilesAt( const NormalizedRect &rect, TileNode &tile, QList<Tile> &result, TileLeaf tileLeaf )
|
||||
{
|
||||
if ( !tile.rect.intersects( rect ) )
|
||||
return;
|
||||
|
||||
// split big tiles before the requests are made, otherwise we would end up
|
||||
// requesting huge areas unnecessarily
|
||||
splitBigTiles( tile, rect );
|
||||
|
||||
if ( ( tileLeaf == TerminalTile && tile.nTiles == 0 ) || ( tileLeaf == PixmapTile && tile.pixmap ) )
|
||||
{
|
||||
NormalizedRect rotatedRect;
|
||||
if ( rotation != Rotation0 )
|
||||
rotatedRect = TilesManager::toRotatedRect( tile.rect, rotation );
|
||||
else
|
||||
rotatedRect = tile.rect;
|
||||
|
||||
if ( tile.pixmap && tileLeaf == PixmapTile && tile.rotation != rotation )
|
||||
{
|
||||
// Lazy tiles rotation
|
||||
int angleToRotate = (rotation - tile.rotation)*90;
|
||||
int xOffset = 0, yOffset = 0;
|
||||
int w = 0, h = 0;
|
||||
switch( angleToRotate )
|
||||
{
|
||||
case 0:
|
||||
xOffset = 0;
|
||||
yOffset = 0;
|
||||
w = tile.pixmap->width();
|
||||
h = tile.pixmap->height();
|
||||
break;
|
||||
case 90:
|
||||
case -270:
|
||||
xOffset = 0;
|
||||
yOffset = -tile.pixmap->height();
|
||||
w = tile.pixmap->height();
|
||||
h = tile.pixmap->width();
|
||||
break;
|
||||
case 180:
|
||||
case -180:
|
||||
xOffset = -tile.pixmap->width();
|
||||
yOffset = -tile.pixmap->height();
|
||||
w = tile.pixmap->width();
|
||||
h = tile.pixmap->height();
|
||||
break;
|
||||
case 270:
|
||||
case -90:
|
||||
xOffset = -tile.pixmap->width();
|
||||
yOffset = 0;
|
||||
w = tile.pixmap->height();
|
||||
h = tile.pixmap->width();
|
||||
break;
|
||||
}
|
||||
QPixmap *rotatedPixmap = new QPixmap( w, h );
|
||||
QPainter p( rotatedPixmap );
|
||||
p.rotate( angleToRotate );
|
||||
p.translate( xOffset, yOffset );
|
||||
p.drawPixmap( 0, 0, *tile.pixmap );
|
||||
p.end();
|
||||
|
||||
delete tile.pixmap;
|
||||
tile.pixmap = rotatedPixmap;
|
||||
tile.rotation = rotation;
|
||||
}
|
||||
result.append( Tile( rotatedRect, tile.pixmap, tile.isValid() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( int i = 0; i < tile.nTiles; ++i )
|
||||
tilesAt( rect, tile.tiles[ i ], result, tileLeaf );
|
||||
}
|
||||
}
|
||||
|
||||
qulonglong TilesManager::totalMemory() const
|
||||
{
|
||||
return 4*d->totalPixels;
|
||||
}
|
||||
|
||||
void TilesManager::cleanupPixmapMemory( qulonglong numberOfBytes, const NormalizedRect &visibleRect, int visiblePageNumber )
|
||||
{
|
||||
QList<TileNode*> rankedTiles;
|
||||
for ( int i = 0; i < 16; ++i )
|
||||
{
|
||||
d->rankTiles( d->tiles[ i ], rankedTiles, visibleRect, visiblePageNumber );
|
||||
}
|
||||
qSort( rankedTiles.begin(), rankedTiles.end(), rankedTilesLessThan );
|
||||
|
||||
while ( numberOfBytes > 0 && !rankedTiles.isEmpty() )
|
||||
{
|
||||
TileNode *tile = rankedTiles.takeLast();
|
||||
if ( !tile->pixmap )
|
||||
continue;
|
||||
|
||||
// do not evict visible pixmaps
|
||||
if ( tile->rect.intersects( visibleRect ) )
|
||||
continue;
|
||||
|
||||
qulonglong pixels = tile->pixmap->width()*tile->pixmap->height();
|
||||
d->totalPixels -= pixels;
|
||||
if ( numberOfBytes < 4*pixels )
|
||||
numberOfBytes = 0;
|
||||
else
|
||||
numberOfBytes -= 4*pixels;
|
||||
|
||||
delete tile->pixmap;
|
||||
tile->pixmap = 0;
|
||||
|
||||
d->markParentDirty( *tile );
|
||||
}
|
||||
}
|
||||
|
||||
void TilesManager::Private::markParentDirty( const TileNode &tile )
|
||||
{
|
||||
if ( !tile.parent )
|
||||
return;
|
||||
|
||||
if ( !tile.parent->dirty )
|
||||
{
|
||||
tile.parent->dirty = true;
|
||||
markParentDirty( *tile.parent );
|
||||
}
|
||||
}
|
||||
|
||||
void TilesManager::Private::rankTiles( TileNode &tile, QList<TileNode*> &rankedTiles, const NormalizedRect &visibleRect, int visiblePageNumber )
|
||||
{
|
||||
// If the page is visible, visibleRect is not null.
|
||||
// Otherwise we use the number of one of the visible pages to calculate the
|
||||
// distance.
|
||||
// Note that the current page may be visible and yet its pageNumber is
|
||||
// different from visiblePageNumber. Since we only use this value on hidden
|
||||
// pages, any visible page number will fit.
|
||||
if ( visibleRect.isNull() && visiblePageNumber < 0 )
|
||||
return;
|
||||
|
||||
if ( tile.pixmap )
|
||||
{
|
||||
// Update distance
|
||||
if ( !visibleRect.isNull() )
|
||||
{
|
||||
NormalizedPoint viewportCenter = visibleRect.center();
|
||||
NormalizedPoint tileCenter = tile.rect.center();
|
||||
// Manhattan distance. It's a good and fast approximation.
|
||||
tile.distance = qAbs(viewportCenter.x - tileCenter.x) + qAbs(viewportCenter.y - tileCenter.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
// For non visible pages only the vertical distance is used
|
||||
if ( pageNumber < visiblePageNumber )
|
||||
tile.distance = 1 - tile.rect.bottom;
|
||||
else
|
||||
tile.distance = tile.rect.top;
|
||||
}
|
||||
rankedTiles.append( &tile );
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( int i = 0; i < tile.nTiles; ++i )
|
||||
{
|
||||
rankTiles( tile.tiles[ i ], rankedTiles, visibleRect, visiblePageNumber );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool TilesManager::isRequesting( const NormalizedRect &rect, int pageWidth, int pageHeight ) const
|
||||
{
|
||||
return rect == d->requestRect && pageWidth == d->requestWidth && pageHeight == d->requestHeight;
|
||||
}
|
||||
|
||||
void TilesManager::setRequest( const NormalizedRect &rect, int pageWidth, int pageHeight )
|
||||
{
|
||||
d->requestRect = rect;
|
||||
d->requestWidth = pageWidth;
|
||||
d->requestHeight = pageHeight;
|
||||
}
|
||||
|
||||
bool TilesManager::Private::splitBigTiles( TileNode &tile, const NormalizedRect &rect )
|
||||
{
|
||||
QRect tileRect = tile.rect.geometry( width, height );
|
||||
if ( tileRect.width()*tileRect.height() < TILES_MAXSIZE )
|
||||
return false;
|
||||
|
||||
split( tile, rect );
|
||||
return true;
|
||||
}
|
||||
|
||||
void TilesManager::Private::split( TileNode &tile, const NormalizedRect &rect )
|
||||
{
|
||||
if ( tile.nTiles != 0 )
|
||||
return;
|
||||
|
||||
if ( rect.isNull() || !tile.rect.intersects( rect ) )
|
||||
return;
|
||||
|
||||
tile.nTiles = 4;
|
||||
tile.tiles = new TileNode[4];
|
||||
double hCenter = (tile.rect.left + tile.rect.right)/2;
|
||||
double vCenter = (tile.rect.top + tile.rect.bottom)/2;
|
||||
|
||||
tile.tiles[0].rect = NormalizedRect( tile.rect.left, tile.rect.top, hCenter, vCenter );
|
||||
tile.tiles[1].rect = NormalizedRect( hCenter, tile.rect.top, tile.rect.right, vCenter );
|
||||
tile.tiles[2].rect = NormalizedRect( tile.rect.left, vCenter, hCenter, tile.rect.bottom );
|
||||
tile.tiles[3].rect = NormalizedRect( hCenter, vCenter, tile.rect.right, tile.rect.bottom );
|
||||
|
||||
for ( int i = 0; i < tile.nTiles; ++i )
|
||||
{
|
||||
tile.tiles[ i ].parent = &tile;
|
||||
splitBigTiles( tile.tiles[ i ], rect );
|
||||
}
|
||||
}
|
||||
|
||||
NormalizedRect TilesManager::fromRotatedRect( const NormalizedRect &rect, Rotation rotation )
|
||||
{
|
||||
if ( rotation == Rotation0 )
|
||||
return rect;
|
||||
|
||||
NormalizedRect newRect;
|
||||
switch ( rotation )
|
||||
{
|
||||
case Rotation90:
|
||||
newRect = NormalizedRect( rect.top, 1 - rect.right, rect.bottom, 1 - rect.left );
|
||||
break;
|
||||
case Rotation180:
|
||||
newRect = NormalizedRect( 1 - rect.right, 1 - rect.bottom, 1 - rect.left, 1 - rect.top );
|
||||
break;
|
||||
case Rotation270:
|
||||
newRect = NormalizedRect( 1 - rect.bottom, rect.left, 1 - rect.top, rect.right );
|
||||
break;
|
||||
default:
|
||||
newRect = rect;
|
||||
break;
|
||||
}
|
||||
|
||||
return newRect;
|
||||
}
|
||||
|
||||
NormalizedRect TilesManager::toRotatedRect( const NormalizedRect &rect, Rotation rotation )
|
||||
{
|
||||
if ( rotation == Rotation0 )
|
||||
return rect;
|
||||
|
||||
NormalizedRect newRect;
|
||||
switch ( rotation )
|
||||
{
|
||||
case Rotation90:
|
||||
newRect = NormalizedRect( 1 - rect.bottom, rect.left, 1 - rect.top, rect.right );
|
||||
break;
|
||||
case Rotation180:
|
||||
newRect = NormalizedRect( 1 - rect.right, 1 - rect.bottom, 1 - rect.left, 1 - rect.top );
|
||||
break;
|
||||
case Rotation270:
|
||||
newRect = NormalizedRect( rect.top, 1 - rect.right, rect.bottom, 1 - rect.left );
|
||||
break;
|
||||
default:
|
||||
newRect = rect;
|
||||
break;
|
||||
}
|
||||
|
||||
return newRect;
|
||||
}
|
||||
|
||||
TileNode::TileNode()
|
||||
: pixmap( 0 )
|
||||
, rotation( Rotation0 )
|
||||
, dirty ( true )
|
||||
, distance( -1 )
|
||||
, tiles( 0 )
|
||||
, nTiles( 0 )
|
||||
, parent( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
bool TileNode::isValid() const
|
||||
{
|
||||
return pixmap && !dirty;
|
||||
}
|
||||
|
||||
class Tile::Private
|
||||
{
|
||||
public:
|
||||
Private();
|
||||
|
||||
NormalizedRect rect;
|
||||
QPixmap *pixmap;
|
||||
bool isValid;
|
||||
};
|
||||
|
||||
Tile::Private::Private()
|
||||
: pixmap( 0 )
|
||||
, isValid( false )
|
||||
{
|
||||
}
|
||||
|
||||
Tile::Tile( const NormalizedRect &rect, QPixmap *pixmap, bool isValid )
|
||||
: d( new Tile::Private )
|
||||
{
|
||||
d->rect = rect;
|
||||
d->pixmap = pixmap;
|
||||
d->isValid = isValid;
|
||||
}
|
||||
|
||||
Tile::Tile( const Tile &t )
|
||||
: d( new Tile::Private )
|
||||
{
|
||||
d->rect = t.d->rect;
|
||||
d->pixmap = t.d->pixmap;
|
||||
d->isValid = t.d->isValid;
|
||||
}
|
||||
|
||||
Tile& Tile::operator=( const Tile &other )
|
||||
{
|
||||
if ( this == &other )
|
||||
return *this;
|
||||
|
||||
d->rect = other.d->rect;
|
||||
d->pixmap = other.d->pixmap;
|
||||
d->isValid = other.d->isValid;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Tile::~Tile()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
NormalizedRect Tile::rect() const
|
||||
{
|
||||
return d->rect;
|
||||
}
|
||||
|
||||
QPixmap * Tile::pixmap() const
|
||||
{
|
||||
return d->pixmap;
|
||||
}
|
||||
|
||||
bool Tile::isValid() const
|
||||
{
|
||||
return d->isValid;
|
||||
}
|
|
@ -1,207 +0,0 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2012 by Mailson Menezes <mailson@gmail.com> *
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef _OKULAR_TILES_MANAGER_P_H_
|
||||
#define _OKULAR_TILES_MANAGER_P_H_
|
||||
|
||||
#include "okular_export.h"
|
||||
#include "area.h"
|
||||
|
||||
#include <QPixmap>
|
||||
|
||||
namespace Okular {
|
||||
|
||||
class Tile;
|
||||
|
||||
/**
|
||||
* Node in the quadtree structure used by the tiles manager to store tiles.
|
||||
*
|
||||
* Except for the first level, the tiles manager stores tiles in a quadtree
|
||||
* structure.
|
||||
* Each node stores the pixmap of a tile and its location on the page.
|
||||
* There's a limit on the size of the pixmaps (TILES_MAXSIZE, defined in
|
||||
* tilesmanager.cpp), and tiles that are bigger than that value are split into
|
||||
* four children tiles, which are stored as children of the original tile.
|
||||
* If children tiles are still too big, they are recursively split again.
|
||||
* If the zoom level changes and a big tile goes below the limit, it is merged
|
||||
* back into a leaf tile.
|
||||
*/
|
||||
class TileNode
|
||||
{
|
||||
public:
|
||||
TileNode();
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
/**
|
||||
* Location on the page in normalized coords
|
||||
*/
|
||||
NormalizedRect rect;
|
||||
|
||||
/**
|
||||
* Associated pixmap or NULL if not present
|
||||
*
|
||||
* For each node, it is guaranteed that there's no more than one pixmap
|
||||
* along the path from the root to the node itself.
|
||||
* In fact, it is very frequent that a leaf node has no pixmap and one
|
||||
* of its ancestors has. Such a situation shows, for example, when the
|
||||
* parent tile still has a dirty tile from a previous lower zoom level.
|
||||
*/
|
||||
QPixmap *pixmap;
|
||||
|
||||
/**
|
||||
* Rotation of this individual tile.
|
||||
*
|
||||
* A rotation to the page does not immediately rotates the pixmaps in
|
||||
* cache. This operation happens when pixmaps are going to be used.
|
||||
*/
|
||||
Rotation rotation;
|
||||
|
||||
/**
|
||||
* Whether the tile needs to be repainted (after a zoom or rotation)
|
||||
* If a tile doesn't have a pixmap but all its children are updated
|
||||
* (dirty = false), the parent tile is also considered updated.
|
||||
*/
|
||||
bool dirty;
|
||||
|
||||
/**
|
||||
* Distance between the tile and the viewport.
|
||||
* This is used by the evicting algorithm.
|
||||
*/
|
||||
double distance;
|
||||
|
||||
/**
|
||||
* Children tiles
|
||||
* When a tile is split into multiple tiles, they're added as children.
|
||||
* nTiles can be either 0 (in leaf tiles) or 4 (in split tiles).
|
||||
*/
|
||||
TileNode *tiles;
|
||||
int nTiles;
|
||||
TileNode *parent;
|
||||
};
|
||||
|
||||
/**
|
||||
* @short Tiles management
|
||||
*
|
||||
* This class has direct access to all tiles and handles how they should be
|
||||
* stored, deleted and retrieved. Each tiles manager only handles one page.
|
||||
*
|
||||
* The tiles manager is a tree of tiles. At first the page is divided in a 4x4
|
||||
* grid of 16 tiles. Then each of these tiles can be recursively split in 4
|
||||
* subtiles so that we keep the size of each pixmap inside a safe interval.
|
||||
*/
|
||||
class TilesManager
|
||||
{
|
||||
public:
|
||||
enum TileLeaf
|
||||
{
|
||||
TerminalTile, ///< Return tiles without children
|
||||
PixmapTile ///< Return only tiles with pixmap
|
||||
};
|
||||
|
||||
TilesManager( int pageNumber, int width, int height, Rotation rotation = Rotation0 );
|
||||
~TilesManager();
|
||||
|
||||
/**
|
||||
* Sets the pixmap of the tiles covered by @p rect (which represents
|
||||
* the location of @p pixmap on the page).
|
||||
* @p pixmap may cover an area which contains multiple tiles. So each
|
||||
* tile we get a cropped part of the @p pixmap.
|
||||
*
|
||||
* Also it checks the dimensions of the given parameters against the
|
||||
* current request as to avoid setting pixmaps of late requests.
|
||||
*/
|
||||
void setPixmap( const QPixmap *pixmap, const NormalizedRect &rect );
|
||||
|
||||
/**
|
||||
* Checks whether all tiles intersecting with @p rect are available.
|
||||
* Returns false if at least one tile needs to be repainted (the tile
|
||||
* is dirty).
|
||||
*/
|
||||
bool hasPixmap( const NormalizedRect &rect );
|
||||
|
||||
/**
|
||||
* Returns a list of all tiles intersecting with @p rect.
|
||||
*
|
||||
* As to avoid requests of big areas, each traversed tile is checked
|
||||
* for its size and split if necessary.
|
||||
*
|
||||
* @param tileLeaf Indicate the type of tile to return
|
||||
*/
|
||||
QList<Tile> tilesAt( const NormalizedRect &rect, TileLeaf tileLeaf );
|
||||
|
||||
/**
|
||||
* The total memory consumed by the tiles manager
|
||||
*/
|
||||
qulonglong totalMemory() const;
|
||||
|
||||
/**
|
||||
* Removes at least @p numberOfBytes bytes worth of tiles (least ranked
|
||||
* tiles are removed first).
|
||||
* Set @p visibleRect to the visible region of the page. Set a
|
||||
* @p visiblePageNumber if the current page is not visible.
|
||||
* Visible tiles are not discarded.
|
||||
*/
|
||||
void cleanupPixmapMemory( qulonglong numberOfBytes, const NormalizedRect &visibleRect, int visiblePageNumber );
|
||||
|
||||
/**
|
||||
* Checks whether a given region has already been requested
|
||||
*/
|
||||
bool isRequesting( const NormalizedRect &rect, int pageWidth, int pageHeight ) const;
|
||||
|
||||
/**
|
||||
* Sets a region to be requested so the tiles manager knows which
|
||||
* pixmaps to expect and discard those not useful anymore (late pixmaps)
|
||||
*/
|
||||
void setRequest( const NormalizedRect &rect, int pageWidth, int pageHeight );
|
||||
|
||||
/**
|
||||
* Inform the new size of the page and mark all tiles to repaint
|
||||
*/
|
||||
void setSize( int width, int height );
|
||||
|
||||
/**
|
||||
* Gets the width of the page in tiles manager
|
||||
*/
|
||||
int width() const;
|
||||
|
||||
/**
|
||||
* Gets the height of the page in tiles manager
|
||||
*/
|
||||
int height() const;
|
||||
|
||||
/**
|
||||
* Inform the new rotation of the page
|
||||
*/
|
||||
void setRotation( Rotation rotation );
|
||||
Rotation rotation() const;
|
||||
|
||||
/**
|
||||
* Mark all tiles as dirty
|
||||
*/
|
||||
void markDirty();
|
||||
|
||||
/**
|
||||
* Returns a rotated NormalizedRect given a @p rotation
|
||||
*/
|
||||
static NormalizedRect toRotatedRect( const NormalizedRect &rect, Rotation rotation );
|
||||
|
||||
/**
|
||||
* Returns a non rotated version of @p rect, which is rotated by @p rotation
|
||||
*/
|
||||
static NormalizedRect fromRotatedRect( const NormalizedRect &rect, Rotation rotation );
|
||||
|
||||
private:
|
||||
class Private;
|
||||
Private * const d;
|
||||
friend class Private;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // _OKULAR_TILES_MANAGER_P_H_
|
|
@ -128,10 +128,6 @@ void MagnifierView::requestPixmap()
|
|||
|
||||
Okular::PixmapRequest *p = new Okular::PixmapRequest( this, m_current, full_width, full_height, PAGEVIEW_PRIO, Okular::PixmapRequest::Asynchronous );
|
||||
|
||||
if ( m_page->hasTilesManager( this ) ) {
|
||||
p->setTile( true );
|
||||
}
|
||||
|
||||
// request a little bit bigger rectangle then currently viewed, but not the full scale page
|
||||
const double rect_width = (nrect.right - nrect.left) * 0.5,
|
||||
rect_height = (nrect.bottom - nrect.top) * 0.5;
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#include "guiutils.h"
|
||||
#include "settings.h"
|
||||
#include "core/observer.h"
|
||||
#include "core/tile.h"
|
||||
#include "settings_core.h"
|
||||
#include "core/document_p.h"
|
||||
|
||||
|
@ -89,33 +88,27 @@ void PagePainter::paintCroppedPageOnPainter( QPainter * destPainter, const Okula
|
|||
}
|
||||
destPainter->fillRect( limits, backgroundColor );
|
||||
|
||||
const bool hasTilesManager = page->hasTilesManager( observer );
|
||||
const QPixmap *pixmap = 0;
|
||||
/** 1 - RETRIEVE THE 'PAGE+ID' PIXMAP OR A SIMILAR 'PAGE' ONE **/
|
||||
const QPixmap *pixmap = page->_o_nearestPixmap( observer, scaledWidth, scaledHeight );
|
||||
|
||||
if ( !hasTilesManager )
|
||||
/** 1B - IF NO PIXMAP, DRAW EMPTY PAGE **/
|
||||
double pixmapRescaleRatio = pixmap ? scaledWidth / (double)pixmap->width() : -1;
|
||||
long pixmapPixels = pixmap ? (long)pixmap->width() * (long)pixmap->height() : 0;
|
||||
if ( !pixmap || pixmapRescaleRatio > 20.0 || pixmapRescaleRatio < 0.25 ||
|
||||
(scaledWidth != pixmap->width() && pixmapPixels > 6000000L) )
|
||||
{
|
||||
/** 1 - RETRIEVE THE 'PAGE+ID' PIXMAP OR A SIMILAR 'PAGE' ONE **/
|
||||
pixmap = page->_o_nearestPixmap( observer, scaledWidth, scaledHeight );
|
||||
|
||||
/** 1B - IF NO PIXMAP, DRAW EMPTY PAGE **/
|
||||
double pixmapRescaleRatio = pixmap ? scaledWidth / (double)pixmap->width() : -1;
|
||||
long pixmapPixels = pixmap ? (long)pixmap->width() * (long)pixmap->height() : 0;
|
||||
if ( !pixmap || pixmapRescaleRatio > 20.0 || pixmapRescaleRatio < 0.25 ||
|
||||
(scaledWidth != pixmap->width() && pixmapPixels > 6000000L) )
|
||||
// draw something on the blank page: the okular icon or a cross (as a fallback)
|
||||
if ( !busyPixmap->isNull() )
|
||||
{
|
||||
// draw something on the blank page: the okular icon or a cross (as a fallback)
|
||||
if ( !busyPixmap->isNull() )
|
||||
{
|
||||
destPainter->drawPixmap( QPoint( 10, 10 ), *busyPixmap );
|
||||
}
|
||||
else
|
||||
{
|
||||
destPainter->setPen( Qt::gray );
|
||||
destPainter->drawLine( 0, 0, croppedWidth-1, croppedHeight-1 );
|
||||
destPainter->drawLine( 0, croppedHeight-1, croppedWidth-1, 0 );
|
||||
}
|
||||
return;
|
||||
destPainter->drawPixmap( QPoint( 10, 10 ), *busyPixmap );
|
||||
}
|
||||
else
|
||||
{
|
||||
destPainter->setPen( Qt::gray );
|
||||
destPainter->drawLine( 0, 0, croppedWidth-1, croppedHeight-1 );
|
||||
destPainter->drawLine( 0, croppedHeight-1, croppedWidth-1, 0 );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** 2 - FIND OUT WHAT TO PAINT (Flags + Configuration + Presence) **/
|
||||
|
@ -243,41 +236,17 @@ void PagePainter::paintCroppedPageOnPainter( QPainter * destPainter, const Okula
|
|||
/** 4A -- REGULAR FLOW. PAINT PIXMAP NORMAL OR RESCALED USING GIVEN QPAINTER **/
|
||||
if ( !useBackBuffer )
|
||||
{
|
||||
if ( hasTilesManager )
|
||||
{
|
||||
const Okular::NormalizedRect normalizedLimits( limitsInPixmap, scaledWidth, scaledHeight );
|
||||
const QList<Okular::Tile> tiles = page->tilesAt( observer, normalizedLimits );
|
||||
QList<Okular::Tile>::const_iterator tIt = tiles.constBegin(), tEnd = tiles.constEnd();
|
||||
while ( tIt != tEnd )
|
||||
{
|
||||
const Okular::Tile &tile = *tIt;
|
||||
QRect tileRect = tile.rect().geometry( scaledWidth, scaledHeight ).translated( -scaledCrop.topLeft() );
|
||||
QRect limitsInTile = limits & tileRect;
|
||||
if ( !limitsInTile.isEmpty() )
|
||||
{
|
||||
if ( tile.pixmap()->width() == tileRect.width() && tile.pixmap()->height() == tileRect.height() )
|
||||
destPainter->drawPixmap( limitsInTile.topLeft(), *(tile.pixmap()),
|
||||
limitsInTile.translated( -tileRect.topLeft() ) );
|
||||
else
|
||||
destPainter->drawPixmap( tileRect, *(tile.pixmap()) );
|
||||
}
|
||||
tIt++;
|
||||
}
|
||||
}
|
||||
// 4A.1. if size is ok, draw the page pixmap using painter
|
||||
if ( pixmap->width() == scaledWidth && pixmap->height() == scaledHeight )
|
||||
destPainter->drawPixmap( limits.topLeft(), *pixmap, limitsInPixmap );
|
||||
|
||||
// else draw a scaled portion of the magnified pixmap
|
||||
else
|
||||
{
|
||||
// 4A.1. if size is ok, draw the page pixmap using painter
|
||||
if ( pixmap->width() == scaledWidth && pixmap->height() == scaledHeight )
|
||||
destPainter->drawPixmap( limits.topLeft(), *pixmap, limitsInPixmap );
|
||||
|
||||
// else draw a scaled portion of the magnified pixmap
|
||||
else
|
||||
{
|
||||
QImage destImage;
|
||||
scalePixmapOnImage( destImage, pixmap, scaledWidth, scaledHeight, limitsInPixmap );
|
||||
destPainter->drawImage( limits.left(), limits.top(), destImage, 0, 0,
|
||||
limits.width(),limits.height() );
|
||||
}
|
||||
QImage destImage;
|
||||
scalePixmapOnImage( destImage, pixmap, scaledWidth, scaledHeight, limitsInPixmap );
|
||||
destPainter->drawImage( limits.left(), limits.top(), destImage, 0, 0,
|
||||
limits.width(),limits.height() );
|
||||
}
|
||||
|
||||
// 4A.2. active painter is the one passed to this method
|
||||
|
@ -295,50 +264,11 @@ void PagePainter::paintCroppedPageOnPainter( QPainter * destPainter, const Okula
|
|||
else
|
||||
has_alpha = true;
|
||||
|
||||
if ( hasTilesManager )
|
||||
{
|
||||
backImage = QImage( limits.width(), limits.height(), QImage::Format_ARGB32_Premultiplied );
|
||||
backImage.fill( paperColor.rgb() );
|
||||
QPainter p( &backImage );
|
||||
const Okular::NormalizedRect normalizedLimits( limitsInPixmap, scaledWidth, scaledHeight );
|
||||
const QList<Okular::Tile> tiles = page->tilesAt( observer, normalizedLimits );
|
||||
QList<Okular::Tile>::const_iterator tIt = tiles.constBegin(), tEnd = tiles.constEnd();
|
||||
while ( tIt != tEnd )
|
||||
{
|
||||
const Okular::Tile &tile = *tIt;
|
||||
QRect tileRect = tile.rect().geometry( scaledWidth, scaledHeight ).translated( -scaledCrop.topLeft() );
|
||||
QRect limitsInTile = limits & tileRect;
|
||||
if ( !limitsInTile.isEmpty() )
|
||||
{
|
||||
if ( !tile.pixmap()->hasAlpha() )
|
||||
has_alpha = false;
|
||||
|
||||
if ( tile.pixmap()->width() == tileRect.width() && tile.pixmap()->height() == tileRect.height() )
|
||||
{
|
||||
p.drawPixmap( limitsInTile.translated( -limits.topLeft() ).topLeft(), *(tile.pixmap()),
|
||||
limitsInTile.translated( -tileRect.topLeft() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
double xScale = tile.pixmap()->width() / (double)tileRect.width();
|
||||
double yScale = tile.pixmap()->height() / (double)tileRect.height();
|
||||
QTransform transform( xScale, 0, 0, yScale, 0, 0 );
|
||||
p.drawPixmap( limitsInTile.translated( -limits.topLeft() ), *(tile.pixmap()),
|
||||
transform.mapRect( limitsInTile ).translated( -transform.mapRect( tileRect ).topLeft() ) );
|
||||
}
|
||||
}
|
||||
++tIt;
|
||||
}
|
||||
p.end();
|
||||
}
|
||||
// 4B.1. draw the page pixmap: normal or scaled
|
||||
if ( pixmap->width() == scaledWidth && pixmap->height() == scaledHeight )
|
||||
cropPixmapOnImage( backImage, pixmap, limitsInPixmap );
|
||||
else
|
||||
{
|
||||
// 4B.1. draw the page pixmap: normal or scaled
|
||||
if ( pixmap->width() == scaledWidth && pixmap->height() == scaledHeight )
|
||||
cropPixmapOnImage( backImage, pixmap, limitsInPixmap );
|
||||
else
|
||||
scalePixmapOnImage( backImage, pixmap, scaledWidth, scaledHeight, limitsInPixmap );
|
||||
}
|
||||
scalePixmapOnImage( backImage, pixmap, scaledWidth, scaledHeight, limitsInPixmap );
|
||||
|
||||
// 4B.2. modify pixmap following accessibility settings
|
||||
if ( bufferAccessibility )
|
||||
|
|
|
@ -80,7 +80,6 @@
|
|||
#include "core/movie.h"
|
||||
#include "core/audioplayer.h"
|
||||
#include "core/sourcereference.h"
|
||||
#include "core/tile.h"
|
||||
#include "settings.h"
|
||||
#include "settings_core.h"
|
||||
#include "magnifierview.h"
|
||||
|
@ -1059,8 +1058,11 @@ void PageView::updateActionState( bool haspages, bool documentChanged, bool hasf
|
|||
d->aSpeakDoc->setEnabled( enablettsactions );
|
||||
d->aSpeakPage->setEnabled( enablettsactions );
|
||||
}
|
||||
if (d->aMouseMagnifier)
|
||||
d->aMouseMagnifier->setEnabled(d->document->supportsTiles());
|
||||
if (d->aMouseMagnifier) {
|
||||
// FIXME: works only for some zoom-levels
|
||||
d->aMouseMagnifier->setVisible(false);
|
||||
d->aMouseMagnifier->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
bool PageView::areSourceLocationsShownGraphically() const
|
||||
|
@ -1813,7 +1815,7 @@ void PageView::mouseMoveEvent( QMouseEvent * e )
|
|||
deltaY = mouseContainer.height() - absDeltaY;
|
||||
}
|
||||
|
||||
const float upperZoomLimit = d->document->supportsTiles() ? 15.99 : 3.99;
|
||||
const float upperZoomLimit = 3.99;
|
||||
if ( mouseY <= mouseContainer.top() + 4 &&
|
||||
d->zoomFactor < upperZoomLimit )
|
||||
{
|
||||
|
@ -2421,7 +2423,7 @@ void PageView::mouseReleaseEvent( QMouseEvent * e )
|
|||
double nX = (double)(selRect.left() + selRect.right()) / (2.0 * (double)contentAreaWidth());
|
||||
double nY = (double)(selRect.top() + selRect.bottom()) / (2.0 * (double)contentAreaHeight());
|
||||
|
||||
const float upperZoomLimit = d->document->supportsTiles() ? 16.0 : 4.0;
|
||||
const float upperZoomLimit = 4.0;
|
||||
if ( d->zoomFactor <= upperZoomLimit || zoom <= 1.0 )
|
||||
{
|
||||
d->zoomFactor *= zoom;
|
||||
|
@ -3637,7 +3639,7 @@ void PageView::updateZoom( ZoomMode newZoomMode )
|
|||
d->zoomFactor = -1;
|
||||
break;
|
||||
}
|
||||
const float upperZoomLimit = d->document->supportsTiles() ? 16.0 : 4.0;
|
||||
const float upperZoomLimit = 4.0;
|
||||
if ( newFactor > upperZoomLimit )
|
||||
newFactor = upperZoomLimit;
|
||||
if ( newFactor < 0.1 )
|
||||
|
@ -3689,8 +3691,6 @@ void PageView::updateZoomText()
|
|||
int idx = 0, selIdx = 3;
|
||||
bool inserted = false; //use: "d->zoomMode != ZoomFixed" to hide Fit/* zoom ratio
|
||||
int zoomValueCount = 11;
|
||||
if ( d->document->supportsTiles() )
|
||||
zoomValueCount = 13;
|
||||
while ( idx < zoomValueCount || !inserted )
|
||||
{
|
||||
float value = idx < zoomValueCount ? kZoomValues[ idx ] : newFactor;
|
||||
|
@ -4208,21 +4208,9 @@ static void slotRequestPreloadPixmap( Okular::DocumentObserver * observer, const
|
|||
{
|
||||
Okular::PixmapRequest::PixmapRequestFeatures requestFeatures = Okular::PixmapRequest::Preload;
|
||||
requestFeatures |= Okular::PixmapRequest::Asynchronous;
|
||||
const bool pageHasTilesManager = i->page()->hasTilesManager( observer );
|
||||
if ( pageHasTilesManager && !preRenderRegion.isNull() )
|
||||
{
|
||||
Okular::PixmapRequest * p = new Okular::PixmapRequest( observer, i->pageNumber(), i->uncroppedWidth(), i->uncroppedHeight(), PAGEVIEW_PRELOAD_PRIO, requestFeatures );
|
||||
requestedPixmaps->push_back( p );
|
||||
|
||||
p->setNormalizedRect( preRenderRegion );
|
||||
p->setTile( true );
|
||||
}
|
||||
else if ( !pageHasTilesManager )
|
||||
{
|
||||
Okular::PixmapRequest * p = new Okular::PixmapRequest( observer, i->pageNumber(), i->uncroppedWidth(), i->uncroppedHeight(), PAGEVIEW_PRELOAD_PRIO, requestFeatures );
|
||||
requestedPixmaps->push_back( p );
|
||||
p->setNormalizedRect( preRenderRegion );
|
||||
}
|
||||
Okular::PixmapRequest * p = new Okular::PixmapRequest( observer, i->pageNumber(), i->uncroppedWidth(), i->uncroppedHeight(), PAGEVIEW_PRELOAD_PRIO, requestFeatures );
|
||||
requestedPixmaps->push_back( p );
|
||||
p->setNormalizedRect( preRenderRegion );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4300,18 +4288,8 @@ void PageView::slotRequestVisiblePixmaps( int newValue )
|
|||
kWarning() << "checking for text for page" << i->pageNumber() << "=" << i->page()->hasTextPage();
|
||||
#endif
|
||||
|
||||
Okular::NormalizedRect expandedVisibleRect = vItem->rect;
|
||||
if ( i->page()->hasTilesManager( this ) && Okular::Settings::memoryLevel() != Okular::Settings::EnumMemoryLevel::Low )
|
||||
{
|
||||
double rectMargin = pixelsToExpand/(double)i->uncroppedHeight();
|
||||
expandedVisibleRect.left = qMax( 0.0, vItem->rect.left - rectMargin );
|
||||
expandedVisibleRect.top = qMax( 0.0, vItem->rect.top - rectMargin );
|
||||
expandedVisibleRect.right = qMin( 1.0, vItem->rect.right + rectMargin );
|
||||
expandedVisibleRect.bottom = qMin( 1.0, vItem->rect.bottom + rectMargin );
|
||||
}
|
||||
|
||||
// if the item has not the right pixmap, add a request for it
|
||||
if ( !i->page()->hasPixmap( this, i->uncroppedWidth(), i->uncroppedHeight(), expandedVisibleRect ) )
|
||||
if ( !i->page()->hasPixmap( this, i->uncroppedWidth(), i->uncroppedHeight(), vItem->rect ) )
|
||||
{
|
||||
#ifdef PAGEVIEW_DEBUG
|
||||
kWarning() << "rerequesting visible pixmaps for page" << i->pageNumber() << "!";
|
||||
|
@ -4319,13 +4297,7 @@ void PageView::slotRequestVisiblePixmaps( int newValue )
|
|||
Okular::PixmapRequest * p = new Okular::PixmapRequest( this, i->pageNumber(), i->uncroppedWidth(), i->uncroppedHeight(), PAGEVIEW_PRIO, Okular::PixmapRequest::Asynchronous );
|
||||
requestedPixmaps.push_back( p );
|
||||
|
||||
if ( i->page()->hasTilesManager( this ) )
|
||||
{
|
||||
p->setNormalizedRect( expandedVisibleRect );
|
||||
p->setTile( true );
|
||||
}
|
||||
else
|
||||
p->setNormalizedRect( vItem->rect );
|
||||
p->setNormalizedRect( vItem->rect );
|
||||
}
|
||||
|
||||
// look for the item closest to viewport center and the relative
|
||||
|
|
Loading…
Add table
Reference in a new issue