Fixed issue with occasional mis-sized tile

It turns out that there were two issues at play here: rounding errors
meant that pixmaps were almost never the same size as pagePainter
thought the tiles should be, and the tile-is-the-size-it-should-be code
path was broken (but only hit in rare cases, seemingly at random).

To help with rounding errors in the future, I added a geometryF function
to NormalizedRect that returns a QRectF. In general,
device-independent-pixel points/rects should be floating point, and
device-pixel rects should be integer.
remotes/origin/esari-master-patch-95617
Max Mueggler 3 years ago committed by Oliver Sander
parent 521ea660ee
commit 8c61b6a2b4
  1. 7
      core/area.cpp
  2. 5
      core/area.h
  3. 20
      gui/pagepainter.cpp

@ -243,6 +243,13 @@ QRect NormalizedRect::roundedGeometry(int xScale, int yScale) const
return QRect(l, t, r - l + 1, b - t + 1); return QRect(l, t, r - l + 1, b - t + 1);
} }
QRectF NormalizedRect::geometryF(float xScale, float yScale) const
{
float l = (left * xScale), t = (top * yScale), r = (right * xScale), b = (bottom * yScale);
return QRectF(l, t, r - l, b - t);
}
void NormalizedRect::transform(const QTransform &matrix) void NormalizedRect::transform(const QTransform &matrix)
{ {
QRectF rect(left, top, right - left, bottom - top); QRectF rect(left, top, right - left, bottom - top);

@ -282,6 +282,11 @@ public:
*/ */
QRect roundedGeometry(int xScale, int yScale) const; QRect roundedGeometry(int xScale, int yScale) const;
/**
* Same functionality as geometry, but nothing is converted into int.
*/
QRectF geometryF(float xScale, float yScale) const;
/** /**
* Returns the normalized bounding rectangle of the normalized rectangle * Returns the normalized bounding rectangle of the normalized rectangle
* combined with the @p other normalized rectangle. * combined with the @p other normalized rectangle.

@ -247,18 +247,18 @@ void PagePainter::paintCroppedPageOnPainter(QPainter *destPainter,
QList<Okular::Tile>::const_iterator tIt = tiles.constBegin(), tEnd = tiles.constEnd(); QList<Okular::Tile>::const_iterator tIt = tiles.constBegin(), tEnd = tiles.constEnd();
while (tIt != tEnd) { while (tIt != tEnd) {
const Okular::Tile &tile = *tIt; const Okular::Tile &tile = *tIt;
QRect tileRect = tile.rect().geometry(scaledWidth, scaledHeight).translated(-scaledCrop.topLeft()); QRectF tileRect = tile.rect().geometryF(scaledWidth, scaledHeight).translated(-scaledCrop.topLeft());
QRect dTileRect = QRectF(tileRect.x() * dpr, tileRect.y() * dpr, tileRect.width() * dpr, tileRect.height() * dpr).toAlignedRect(); QRect dTileRect = tile.rect().geometry(dScaledWidth, dScaledHeight).translated(-dScaledCrop.topLeft());
QRect limitsInTile = limits & tileRect; QRectF limitsInTile = QRectF(limits) & tileRect;
QRectF dLimitsInTile = dLimits & dTileRect; QRect dLimitsInTile = dLimits & dTileRect;
if (!limitsInTile.isEmpty()) { if (!limitsInTile.isEmpty()) {
QPixmap *tilePixmap = tile.pixmap(); QPixmap *tilePixmap = tile.pixmap();
if (tilePixmap->width() == dTileRect.width() && tilePixmap->height() == dTileRect.height()) { if (tilePixmap->width() == dTileRect.width() && tilePixmap->height() == dTileRect.height()) {
destPainter->drawPixmap(limitsInTile.topLeft(), *tilePixmap, dLimitsInTile.translated(-dTileRect.topLeft())); destPainter->drawPixmap(limitsInTile, *tilePixmap, dLimitsInTile.translated(-dTileRect.topLeft()));
} else { } else {
destPainter->drawPixmap(tileRect, *tilePixmap); destPainter->drawPixmap(tileRect, *tilePixmap, tilePixmap->rect());
} }
} }
tIt++; tIt++;
@ -284,16 +284,16 @@ void PagePainter::paintCroppedPageOnPainter(QPainter *destPainter,
QList<Okular::Tile>::const_iterator tIt = tiles.constBegin(), tEnd = tiles.constEnd(); QList<Okular::Tile>::const_iterator tIt = tiles.constBegin(), tEnd = tiles.constEnd();
while (tIt != tEnd) { while (tIt != tEnd) {
const Okular::Tile &tile = *tIt; const Okular::Tile &tile = *tIt;
QRect tileRect = tile.rect().geometry(scaledWidth, scaledHeight).translated(-scaledCrop.topLeft()); QRectF tileRect = tile.rect().geometryF(scaledWidth, scaledHeight).translated(-scaledCrop.topLeft());
QRect dTileRect(QRectF(tileRect.x() * dpr, tileRect.y() * dpr, tileRect.width() * dpr, tileRect.height() * dpr).toAlignedRect()); QRect dTileRect = tile.rect().geometry(dScaledWidth, dScaledHeight).translated(-dScaledCrop.topLeft());
QRect limitsInTile = limits & tileRect; QRectF limitsInTile = QRectF(limits) & tileRect;
QRect dLimitsInTile = dLimits & dTileRect; QRect dLimitsInTile = dLimits & dTileRect;
if (!limitsInTile.isEmpty()) { if (!limitsInTile.isEmpty()) {
QPixmap *tilePixmap = tile.pixmap(); QPixmap *tilePixmap = tile.pixmap();
if (tilePixmap->width() == dTileRect.width() && tilePixmap->height() == dTileRect.height()) { if (tilePixmap->width() == dTileRect.width() && tilePixmap->height() == dTileRect.height()) {
p.drawPixmap(limitsInTile.translated(-limits.topLeft()).topLeft(), *tilePixmap, dLimitsInTile.translated(-dTileRect.topLeft())); p.drawPixmap(limitsInTile.translated(-limits.topLeft()), *tilePixmap, dLimitsInTile.translated(-dTileRect.topLeft()));
} else { } else {
double xScale = tilePixmap->width() / (double)dTileRect.width(); double xScale = tilePixmap->width() / (double)dTileRect.width();
double yScale = tilePixmap->height() / (double)dTileRect.height(); double yScale = tilePixmap->height() / (double)dTileRect.height();

Loading…
Cancel
Save