Skip to content

Commit

Permalink
Make some calculations more robust
Browse files Browse the repository at this point in the history
* getContentRect now returns QRect because in practice, GraphicsView always snaps to whole pixels when displaying. This also prevents use of getContentRect().size().toSize() which can in theory round differently than getContentRect().toRect().size() (probably not in practice since we don't translate by fractional amounts), so this forces rounding to happen the same way it will end up getting displayed.
* isExpensiveScalingRequested shouldn't use getContentRect because the current pixmap may already have been scaled expensively and have some rounding errors built in. We only want to take the the future pixmap into account, the size of which will be recalculated from ideal values.
* Increase the error tolerance slightly for expensive scaling (even though it probably doesn't need it now?) because there's no downside if the threshold is a tad high, but if it's too low we'll miss scaling a fitted image.
  • Loading branch information
jdpurcell committed Dec 22, 2024
1 parent a83df56 commit 2228d2f
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 16 deletions.
26 changes: 13 additions & 13 deletions src/qvgraphicsview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ QVGraphicsView::QVGraphicsView(QWidget *parent) : QGraphicsView(parent)
scrollHelper = new ScrollHelper(this,
[this](ScrollHelper::Parameters &p)
{
p.contentRect = getContentRect().toRect();
p.contentRect = getContentRect();
p.usableViewportRect = getUsableViewportRect();
p.shouldConstrain = isConstrainedPositioningEnabled;
p.shouldCenter = isConstrainedSmallCenteringEnabled;
Expand Down Expand Up @@ -766,7 +766,7 @@ void QVGraphicsView::recalculateZoom()
void QVGraphicsView::centerImage()
{
const QRect viewRect = getUsableViewportRect();
const QRect contentRect = getContentRect().toRect();
const QRect contentRect = getContentRect();
const int hOffset = isRightToLeft() ?
horizontalScrollBar()->minimum() + horizontalScrollBar()->maximum() - contentRect.left() :
contentRect.left();
Expand Down Expand Up @@ -892,9 +892,9 @@ bool QVGraphicsView::isExpensiveScalingRequested() const
if (!isSmoothScalingRequested() || smoothScalingMode != Qv::SmoothScalingMode::Expensive || !getCurrentFileDetails().isPixmapLoaded)
return false;

// If we are above maximum scaling size
const QSize contentSize = getContentRect().size().toSize();
const QSize maxSize = getUsableViewportRect(true).size() * (expensiveScalingAboveWindowSize ? 3 : 1) + QSize(1, 1);
// Don't go over the maximum scaling size (a small tolerance is added to cover rounding errors)
const QSize contentSize = (getEffectiveOriginalSize() * zoomLevel).toSize();
const QSize maxSize = getUsableViewportRect(true).size() * (expensiveScalingAboveWindowSize ? 3 : 1) + QSize(2, 2);
return contentSize.width() <= maxSize.width() && contentSize.height() <= maxSize.height();
}

Expand All @@ -903,15 +903,15 @@ QSizeF QVGraphicsView::getEffectiveOriginalSize() const
return getTransformWithNoScaling().mapRect(QRectF(QPoint(), getCurrentFileDetails().loadedPixmapSize)).size() * getDpiAdjustment();
}

void QVGraphicsView::matchContentCenter(const QRectF target)
void QVGraphicsView::matchContentCenter(const QRect target)
{
const QPointF delta = getContentRect().center() - target.center();
const QPointF delta = QRectF(getContentRect()).center() - QRectF(target).center();
scrollHelper->move(QPointF(delta.x() * (isRightToLeft() ? -1 : 1), delta.y()));
}

QRectF QVGraphicsView::getContentRect() const
QRect QVGraphicsView::getContentRect() const
{
return transform().mapRect(loadedPixmapItem->boundingRect());
return transform().mapRect(loadedPixmapItem->boundingRect()).toRect();
}

QRect QVGraphicsView::getUsableViewportRect(const bool addOverscan) const
Expand Down Expand Up @@ -1090,7 +1090,7 @@ void QVGraphicsView::setSpeed(const int &desiredSpeed)

void QVGraphicsView::rotateImage(const int relativeAngle)
{
const QRectF oldRect = getContentRect();
const QRect oldRect = getContentRect();
const QTransform t = transform();
const bool isMirroredOrFlipped = t.isRotating() ? (t.m12() < 0 == t.m21() < 0) : (t.m11() < 0 != t.m22() < 0);
rotate(relativeAngle * (isMirroredOrFlipped ? -1 : 1));
Expand All @@ -1099,23 +1099,23 @@ void QVGraphicsView::rotateImage(const int relativeAngle)

void QVGraphicsView::mirrorImage()
{
const QRectF oldRect = getContentRect();
const QRect oldRect = getContentRect();
const int rotateCorrection = transform().isRotating() ? -1 : 1;
scale(-1 * rotateCorrection, 1 * rotateCorrection);
matchContentCenter(oldRect);
}

void QVGraphicsView::flipImage()
{
const QRectF oldRect = getContentRect();
const QRect oldRect = getContentRect();
const int rotateCorrection = transform().isRotating() ? -1 : 1;
scale(1 * rotateCorrection, -1 * rotateCorrection);
matchContentCenter(oldRect);
}

void QVGraphicsView::resetTransformation()
{
const QRectF oldRect = getContentRect();
const QRect oldRect = getContentRect();
const QTransform t = transform();
const qreal scale = qFabs(t.isRotating() ? t.m21() : t.m11());
setTransform(QTransform::fromScale(scale, scale));
Expand Down
6 changes: 3 additions & 3 deletions src/qvgraphicsview.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,9 @@ class QVGraphicsView : public QGraphicsView

bool isExpensiveScalingRequested() const;

void matchContentCenter(const QRectF target);
void matchContentCenter(const QRect target);

QRectF getContentRect() const;
QRect getContentRect() const;

QRect getUsableViewportRect(const bool addOverscan = false) const;

Expand Down Expand Up @@ -200,7 +200,7 @@ private slots:
QPointF lastZoomRoundingError;
bool isCursorAutoHideFullscreenEnabled {true};
bool isCursorVisible {true};
QRectF lastImageContentRect;
QRect lastImageContentRect;

QVImageCore imageCore {this};

Expand Down

0 comments on commit 2228d2f

Please sign in to comment.