Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
jdpurcell committed Jan 1, 2025
1 parent f676d49 commit 68eccfc
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 21 deletions.
57 changes: 37 additions & 20 deletions src/qvgraphicsview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -834,7 +834,7 @@ const QJsonObject QVGraphicsView::getSessionState() const
{
QJsonObject state;

const QTransform transform = getTransformWithNoScaling();
const QTransform transform = getUnspecializedTransform();
const QJsonArray transformValues {
static_cast<int>(transform.m11()),
static_cast<int>(transform.m22()),
Expand Down Expand Up @@ -924,7 +924,7 @@ bool QVGraphicsView::isExpensiveScalingRequested() const

QSizeF QVGraphicsView::getEffectiveOriginalSize() const
{
return getTransformWithNoScaling().mapRect(QRectF(QPoint(), getCurrentFileDetails().loadedPixmapSize)).size() * getDpiAdjustment();
return getUnspecializedTransform().mapRect(QRectF(QPoint(), getCurrentFileDetails().loadedPixmapSize)).size() * getDpiAdjustment();
}

LogicalPixelFitter QVGraphicsView::getPixelFitter() const
Expand All @@ -941,22 +941,19 @@ void QVGraphicsView::matchContentCenter(const QRect target)

QRect QVGraphicsView::getContentRect() const
{
if (!getCurrentFileDetails().isPixmapLoaded)
return {};

// Avoid using loadedPixmapItem and the active transform because the pixmap may have expensive scaling applied
// which introduces a rounding error to begin with, and even worse, the error will be magnified if we're in the
// the process of zooming in and haven't re-applied the expensive scaling yet. If that's the case, callers need
// to know what the content rect will be once the dust settles rather than what's being temporarily displayed.
const QRectF loadedPixmapBoundingRect = QRectF(QPoint(), getCurrentFileDetails().loadedPixmapSize);
const qreal effectiveTransformScale = zoomLevel * appliedDpiAdjustment;
const QTransform effectiveTransform = getTransformWithNoScaling().scale(effectiveTransformScale, effectiveTransformScale);
const QRectF contentRect = effectiveTransform.mapRect(loadedPixmapBoundingRect);
const QSize snappedSize = getPixelFitter().snapSize(contentRect.size());
const bool isHorizontalReversed = effectiveTransform.m11() < 0 || effectiveTransform.m21() < 0;
const bool isVerticalReversed = effectiveTransform.m22() < 0 || effectiveTransform.m12() < 0;
const QPointF topLeftCorrection = QPointF(
isHorizontalReversed ? contentRect.width() - snappedSize.width() : 0,
isVerticalReversed ? contentRect.height() - snappedSize.height() : 0
);
return QRect((contentRect.topLeft() + topLeftCorrection).toPoint(), snappedSize);
const QSizeF pixmapSize = getCurrentFileDetails().loadedPixmapSize;
const QRectF pixmapBoundingRect = QRectF(QPoint(), pixmapSize);
const qreal pixmapScale = zoomLevel * appliedDpiAdjustment;
const QTransform pixmapTransform = normalizeTransformOrigin(getUnspecializedTransform().scale(pixmapScale, pixmapScale), pixmapSize);
const QRectF contentRect = pixmapTransform.mapRect(pixmapBoundingRect);
return QRect(contentRect.topLeft().toPoint(), getPixelFitter().snapSize(contentRect.size()));
}

QRect QVGraphicsView::getUsableViewportRect(const bool addOverscan) const
Expand All @@ -970,10 +967,20 @@ QRect QVGraphicsView::getUsableViewportRect(const bool addOverscan) const

void QVGraphicsView::setTransformScale(qreal value)
{
setTransform(getTransformWithNoScaling().scale(value, value));
setTransformWithNormalization(getUnspecializedTransform().scale(value, value));
}

void QVGraphicsView::setTransformWithNormalization(QTransform matrix)
{
if (!loadedPixmapItem->pixmap().isNull())
{
matrix = normalizeTransformOrigin(matrix, loadedPixmapItem->boundingRect().size());
}
setTransform(matrix);
qDebug() << getContentRect();
}

QTransform QVGraphicsView::getTransformWithNoScaling() const
QTransform QVGraphicsView::getUnspecializedTransform() const
{
const QTransform t = transform();
// Only intended to handle combinations of scaling, mirroring, flipping, and rotation
Expand Down Expand Up @@ -1035,6 +1042,16 @@ MainWindow* QVGraphicsView::getMainWindow() const
return qobject_cast<MainWindow*>(window());
}

QTransform QVGraphicsView::normalizeTransformOrigin(QTransform matrix, const QSizeF pixmapSize)
{
const bool isXNegative = matrix.m11() < 0 || matrix.m12() < 0;
const bool isYNegative = matrix.m22() < 0 || matrix.m21() < 0;
return matrix.translate(
isXNegative ? -pixmapSize.width() : 0,
isYNegative ? -pixmapSize.height() : 0
);
}

void QVGraphicsView::settingsUpdated()
{
auto &settingsManager = qvApp->getSettingsManager();
Expand Down Expand Up @@ -1131,23 +1148,23 @@ void QVGraphicsView::rotateImage(const int relativeAngle)
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));
setTransformWithNormalization(transform().rotate(relativeAngle * (isMirroredOrFlipped ? -1 : 1)));
matchContentCenter(oldRect);
}

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

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

Expand All @@ -1156,6 +1173,6 @@ void QVGraphicsView::resetTransformation()
const QRect oldRect = getContentRect();
const QTransform t = transform();
const qreal scale = qFabs(t.isRotating() ? t.m21() : t.m11());
setTransform(QTransform::fromScale(scale, scale));
setTransformWithNormalization(QTransform::fromScale(scale, scale));
matchContentCenter(oldRect);
}
6 changes: 5 additions & 1 deletion src/qvgraphicsview.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,9 @@ class QVGraphicsView : public QGraphicsView

void setTransformScale(qreal absoluteScale);

QTransform getTransformWithNoScaling() const;
void setTransformWithNormalization(QTransform matrix);

QTransform getUnspecializedTransform() const;

qreal getDpiAdjustment() const;

Expand All @@ -158,6 +160,8 @@ class QVGraphicsView : public QGraphicsView

MainWindow* getMainWindow() const;

static QTransform normalizeTransformOrigin(QTransform matrix, const QSizeF pixmapSize);

private slots:
void animatedFrameChanged(QRect rect);

Expand Down

0 comments on commit 68eccfc

Please sign in to comment.