diff --git a/ChangeLog b/ChangeLog index 2b4512cef..eef80d584 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ Unreleased Version 2.2.2-pre + * Fix: Solve rendering glitches with selection outlines that happen on some systems. Thanks xxxx for reporting. 2024-08-09 Version 2.2.2-beta.3 * Fix: Use more accurate timers for performance profiles if the platform supports it. diff --git a/src/desktop/scene/canvasscene.cpp b/src/desktop/scene/canvasscene.cpp index 2635cfcb3..cfcbce06a 100644 --- a/src/desktop/scene/canvasscene.cpp +++ b/src/desktop/scene/canvasscene.cpp @@ -149,6 +149,12 @@ void CanvasScene::setZoom(qreal zoom) { if(zoom != m_zoom) { m_zoom = zoom; + if(m_pathPreview) { + m_pathPreview->setZoom(zoom); + } + if(m_selection) { + m_selection->setZoom(zoom); + } if(m_transform) { m_transform->setZoom(zoom); } @@ -441,7 +447,7 @@ void CanvasScene::setSelection( if(valid) { if(!m_selection) { m_selection = new SelectionItem( - m_selectionIgnored, m_showSelectionMask, m_group); + m_selectionIgnored, m_showSelectionMask, m_zoom, m_group); m_selection->setUpdateSceneOnRefresh(true); } m_selection->setModel(bounds, mask); @@ -779,7 +785,7 @@ void CanvasScene::setPathPreview(const QPainterPath &path) } else if(m_pathPreview) { m_pathPreview->setPath(path); } else { - m_pathPreview = new PathPreviewItem(path, m_group); + m_pathPreview = new PathPreviewItem(path, m_zoom, m_group); } } diff --git a/src/desktop/scene/pathpreviewitem.cpp b/src/desktop/scene/pathpreviewitem.cpp index e1910b26f..64854f2fb 100644 --- a/src/desktop/scene/pathpreviewitem.cpp +++ b/src/desktop/scene/pathpreviewitem.cpp @@ -3,19 +3,22 @@ #include #include #include +#include namespace drawingboard { PathPreviewItem::PathPreviewItem( - const QPainterPath &path, QGraphicsItem *parent) + const QPainterPath &path, qreal zoom, QGraphicsItem *parent) : BaseItem(parent) , m_path(path) + , m_zoom(zoom) { } QRectF PathPreviewItem::boundingRect() const { - return m_path.boundingRect().marginsAdded(QMarginsF(1.0, 1.0, 1.0, 1.0)); + qreal m = m_zoom > 0.0 ? std::ceil(1.0 / m_zoom) : 1.0; + return m_path.boundingRect().marginsAdded(QMarginsF(m, m, m, m)); } void PathPreviewItem::setPath(const QPainterPath &path) @@ -24,6 +27,14 @@ void PathPreviewItem::setPath(const QPainterPath &path) m_path = path; } +void PathPreviewItem::setZoom(qreal zoom) +{ + if(zoom != m_zoom) { + refreshGeometry(); + m_zoom = zoom; + } +} + void PathPreviewItem::paint( QPainter *painter, const QStyleOptionGraphicsItem *options, QWidget *widget) { diff --git a/src/desktop/scene/pathpreviewitem.h b/src/desktop/scene/pathpreviewitem.h index 2b7fe1f7f..dc0df8f47 100644 --- a/src/desktop/scene/pathpreviewitem.h +++ b/src/desktop/scene/pathpreviewitem.h @@ -10,13 +10,15 @@ class PathPreviewItem final : public BaseItem { public: enum { Type = PathPreviewType }; - PathPreviewItem(const QPainterPath &path, QGraphicsItem *parent = nullptr); + PathPreviewItem( + const QPainterPath &path, qreal zoom, QGraphicsItem *parent = nullptr); QRectF boundingRect() const override; int type() const override { return Type; } void setPath(const QPainterPath &path); + void setZoom(qreal zoom); protected: void paint( @@ -25,6 +27,7 @@ class PathPreviewItem final : public BaseItem { private: QPainterPath m_path; + qreal m_zoom; }; } diff --git a/src/desktop/scene/selectionitem.cpp b/src/desktop/scene/selectionitem.cpp index 0631f1b20..c275c16cf 100644 --- a/src/desktop/scene/selectionitem.cpp +++ b/src/desktop/scene/selectionitem.cpp @@ -1,14 +1,17 @@ // SPDX-License-Identifier: GPL-3.0-or-later #include "desktop/scene/selectionitem.h" #include "libclient/utils/selectionoutlinegenerator.h" +#include #include #include #include namespace drawingboard { -SelectionItem::SelectionItem(bool ignored, bool showMask, QGraphicsItem *parent) +SelectionItem::SelectionItem( + bool ignored, bool showMask, qreal zoom, QGraphicsItem *parent) : BaseObject(parent) + , m_zoom(zoom) , m_ignored(ignored) , m_showMask(showMask) { @@ -29,6 +32,7 @@ void SelectionItem::setModel(const QRect &bounds, const QImage &mask) m_maskOpacity = 0.0; m_haveTemporaryMask = true; updateBoundingRectFromBounds(); + setPos(m_bounds.topLeft()); if(m_bounds.isEmpty()) { qWarning("Selection mask is empty"); } else if(canShowOutline()) { @@ -69,6 +73,14 @@ void SelectionItem::setShowMask(bool showMask) } } +void SelectionItem::setZoom(qreal zoom) +{ + if(zoom != m_zoom) { + m_zoom = zoom; + updateBoundingRectFromBounds(); + } +} + void SelectionItem::animationStep(qreal dt) { bool havePath = !m_path.isEmpty(); @@ -173,8 +185,9 @@ void SelectionItem::setOutline( void SelectionItem::updateBoundingRectFromBounds() { refreshGeometry(); - m_boundingRect = QRectF(QPointF(0.0, 0.0), QSizeF(m_bounds.size())); - setPos(m_bounds.topLeft()); + qreal m = m_zoom > 0.0 ? std::ceil(1.0 / m_zoom) : 1.0; + m_boundingRect = QRectF(QPointF(0.0, 0.0), QSizeF(m_bounds.size())) + .marginsAdded(QMarginsF(m, m, m, m)); } } diff --git a/src/desktop/scene/selectionitem.h b/src/desktop/scene/selectionitem.h index 3e088ccbf..89f1d2220 100644 --- a/src/desktop/scene/selectionitem.h +++ b/src/desktop/scene/selectionitem.h @@ -18,7 +18,9 @@ class SelectionItem final : public BaseObject { public: enum { Type = SelectionType }; - SelectionItem(bool ignored, bool showMask, QGraphicsItem *parent = nullptr); + SelectionItem( + bool ignored, bool showMask, qreal zoom, + QGraphicsItem *parent = nullptr); int type() const override { return Type; } @@ -30,6 +32,7 @@ class SelectionItem final : public BaseObject { void setIgnored(bool ignored); void setShowMask(bool showMask); + void setZoom(qreal zoom); void animationStep(qreal dt); @@ -50,6 +53,7 @@ class SelectionItem final : public BaseObject { QRect m_bounds; QPainterPath m_path; QImage m_mask; + qreal m_zoom; qreal m_marchingAnts = 0.0; qreal m_maskOpacity = 0.0; qreal m_transparentDelay = 0.0; diff --git a/src/desktop/view/canvasscene.cpp b/src/desktop/view/canvasscene.cpp index 51bfdd9d9..1915a960c 100644 --- a/src/desktop/view/canvasscene.cpp +++ b/src/desktop/view/canvasscene.cpp @@ -116,6 +116,12 @@ void CanvasScene::setZoom(qreal zoom) { if(zoom != m_zoom) { m_zoom = zoom; + if(m_pathPreview) { + m_pathPreview->setZoom(zoom); + } + if(m_selection) { + m_selection->setZoom(zoom); + } if(m_transform) { m_transform->setZoom(zoom); } @@ -304,7 +310,7 @@ void CanvasScene::setPathPreview(const QPainterPath &path) } else if(m_pathPreview) { m_pathPreview->setPath(path); } else { - m_pathPreview = new PathPreviewItem(path, m_canvasGroup); + m_pathPreview = new PathPreviewItem(path, m_zoom, m_canvasGroup); m_pathPreview->setUpdateSceneOnRefresh(true); } } @@ -625,7 +631,7 @@ void CanvasScene::setSelection( if(valid) { if(!m_selection) { m_selection = new SelectionItem( - m_selectionIgnored, m_showSelectionMask, m_canvasGroup); + m_selectionIgnored, m_showSelectionMask, m_zoom, m_canvasGroup); m_selection->setUpdateSceneOnRefresh(true); } m_selection->setModel(bounds, mask);