Don't paint a partial pixmap over a fully rendered pixmap, even if dirty

This preserves fully rendered areas when zooming in or out instead of
replacing them with partially rendered pixmaps.
This commit is contained in:
Max Mueggler 2022-11-23 19:56:58 -05:00 committed by Oliver Sander
parent aa0386dccd
commit a1cf3f9e5e
2 changed files with 24 additions and 2 deletions

View File

@ -226,6 +226,10 @@ void TilesManager::Private::setPixmap(const QPixmap *pixmap, const NormalizedRec
if (!tile.rect.intersects(rect)) { if (!tile.rect.intersects(rect)) {
return; return;
} }
// Avoid painting partial pixmaps over tiles that already have a fully rendered pixmap, even if dirty
if (isPartialPixmap && tile.pixmap != nullptr && !tile.partial) {
return;
}
// if the tile is not entirely within the viewport (the tile intersects an // 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 // edged of the viewport), attempt to set the pixmap in the children tiles
@ -239,13 +243,17 @@ void TilesManager::Private::setPixmap(const QPixmap *pixmap, const NormalizedRec
delete tile.pixmap; delete tile.pixmap;
tile.pixmap = nullptr; tile.pixmap = nullptr;
} }
// We could paint the pixmap over part of the tile here, but
// there is little reason to as it will usually be offscreen
// and it will be overwritten later if more tiles enter the screen,
// as we only track the dirty state of whole tiles, not rects.
return; return;
} }
// the tile lies entirely within the viewport // the tile lies entirely within the viewport
if (tile.nTiles == 0) { if (tile.nTiles == 0) {
tile.dirty = isPartialPixmap; tile.dirty = isPartialPixmap;
tile.partial = isPartialPixmap;
// check whether the tile size is big and split it if necessary // check whether the tile size is big and split it if necessary
if (!splitBigTiles(tile, rect)) { if (!splitBigTiles(tile, rect)) {
@ -276,8 +284,11 @@ void TilesManager::Private::setPixmap(const QPixmap *pixmap, const NormalizedRec
QRect tileRect = tile.rect.geometry(width, height); QRect tileRect = tile.rect.geometry(width, height);
// sets the pixmap of the children tiles. if the tile's size is too // sets the pixmap of the children tiles. if the tile's size is too
// small, discards the children tiles and use the current one // small, discards the children tiles and use the current one
if (tileRect.width() * tileRect.height() >= TILES_MAXSIZE) { // Never join small tiles during a partial update in order to
// not lose existing image data
if (tileRect.width() * tileRect.height() >= TILES_MAXSIZE || isPartialPixmap) {
tile.dirty = isPartialPixmap; tile.dirty = isPartialPixmap;
tile.partial = isPartialPixmap;
if (tile.pixmap) { if (tile.pixmap) {
totalPixels -= tile.pixmap->width() * tile.pixmap->height(); totalPixels -= tile.pixmap->width() * tile.pixmap->height();
delete tile.pixmap; delete tile.pixmap;
@ -312,6 +323,7 @@ void TilesManager::Private::setPixmap(const QPixmap *pixmap, const NormalizedRec
tile.pixmap = nullptr; tile.pixmap = nullptr;
} }
tile.dirty = isPartialPixmap; tile.dirty = isPartialPixmap;
tile.partial = isPartialPixmap;
} }
} }
} }
@ -471,6 +483,8 @@ void TilesManager::cleanupPixmapMemory(qulonglong numberOfBytes, const Normalize
delete tile->pixmap; delete tile->pixmap;
tile->pixmap = nullptr; tile->pixmap = nullptr;
tile->partial = true;
d->markParentDirty(*tile); d->markParentDirty(*tile);
} }
} }
@ -625,6 +639,7 @@ TileNode::TileNode()
: pixmap(nullptr) : pixmap(nullptr)
, rotation(Rotation0) , rotation(Rotation0)
, dirty(true) , dirty(true)
, partial(true)
, distance(-1) , distance(-1)
, tiles(nullptr) , tiles(nullptr)
, nTiles(0) , nTiles(0)

View File

@ -66,6 +66,13 @@ public:
*/ */
bool dirty; bool dirty;
/**
Whether the tile contains a partially rendered pixmap.
Some backends, such as PDF, can send partial updates that contain
only some of the page's elements (e.g. only a background image) drawn.
*/
bool partial;
/** /**
* Distance between the tile and the viewport. * Distance between the tile and the viewport.
* This is used by the evicting algorithm. * This is used by the evicting algorithm.