Commit e37f64c4 authored by Dmitry Kazakov's avatar Dmitry Kazakov

Fix outline in Move Tool, when a layer has a Transform Mask

We need to take layer's masks' change rect into account. We cannot
use normal changeRect() call, because it never shrinks the update rect
and adds projection device bounds (obviously, because it is supposed
to render stuff and not just shwo a decoration).

That is why the patch introduces KisLayer::tightUserVisibleBounds(), which
calculates tight bounding rect of the layer, taking all the masks into
account.

BUG:410163
parent 7a709c54
......@@ -63,6 +63,11 @@ QRect KisDumbProjectionPlane::needRectForOriginal(const QRect &rect) const
return rect;
}
QRect KisDumbProjectionPlane::tightUserVisibleBounds() const
{
return QRect();
}
KisPaintDeviceList KisDumbProjectionPlane::getLodCapableDevices() const
{
// arghm...
......
......@@ -85,6 +85,13 @@ public:
*/
virtual QRect needRectForOriginal(const QRect &rect) const = 0;
/**
* Return a tight rectange, where the contents of the plane
* is placed from user's point of view. It includes everything
* belonging to the plane (e.g. layer styles).
*/
virtual QRect tightUserVisibleBounds() const = 0;
/**
* Returns a list of devices which should synchronize the lod cache on update
*/
......@@ -105,7 +112,7 @@ public:
QRect changeRect(const QRect &rect, KisLayer::PositionToFilthy pos) const override;
QRect accessRect(const QRect &rect, KisLayer::PositionToFilthy pos) const override;
QRect needRectForOriginal(const QRect &rect) const override;
QRect tightUserVisibleBounds() const override;
KisPaintDeviceList getLodCapableDevices() const override;
};
......
......@@ -810,6 +810,21 @@ KisPaintDeviceSP KisLayer::projection() const
m_d->safeProjection->getDeviceLazy(originalDevice) : originalDevice;
}
QRect KisLayer::tightUserVisibleBounds() const
{
QRect changeRect = exactBounds();
/// we do not use incomingChangeRect() here, because
/// exactBounds() already takes it into account (it
/// was used while preparing original())
bool changeRectVaries;
changeRect = outgoingChangeRect(changeRect);
changeRect = masksChangeRect(effectMasks(), changeRect, changeRectVaries);
return changeRect;
}
QRect KisLayer::changeRect(const QRect &rect, PositionToFilthy pos) const
{
QRect changeRect = rect;
......
......@@ -251,6 +251,14 @@ public:
QImage createThumbnailForFrame(qint32 w, qint32 h, int time) override;
/**
* Return a tight rectange, where the contents of the layer
* is placed from user's point of view. This rectangle includes
* all the masks and effects the layer has (excluding layer
* styles, they report their bounds via projection plane).
*/
QRect tightUserVisibleBounds() const;
public:
/**
* Returns true if there are any effect masks present
......
......@@ -156,3 +156,8 @@ QRect KisLayerProjectionPlane::needRectForOriginal(const QRect &rect) const
return m_d->layer->needRectForOriginal(rect);
}
QRect KisLayerProjectionPlane::tightUserVisibleBounds() const
{
return m_d->layer->tightUserVisibleBounds();
}
......@@ -42,6 +42,7 @@ public:
QRect changeRect(const QRect &rect, KisLayer::PositionToFilthy pos) const override;
QRect accessRect(const QRect &rect, KisLayer::PositionToFilthy pos) const override;
QRect needRectForOriginal(const QRect &rect) const override;
QRect tightUserVisibleBounds() const override;
KisPaintDeviceList getLodCapableDevices() const override;
......
......@@ -1635,11 +1635,11 @@ namespace KisLayerUtils {
}
}
QRect recursiveNodeExactBounds(KisNodeSP rootNode)
QRect recursiveTightNodeVisibleBounds(KisNodeSP rootNode)
{
QRect exactBounds;
recursiveApplyNodes(rootNode, [&exactBounds] (KisNodeSP node) {
exactBounds |= node->exactBounds();
exactBounds |= node->projectionPlane()->tightUserVisibleBounds();
});
return exactBounds;
}
......
......@@ -44,7 +44,7 @@ namespace KisLayerUtils
KRITAIMAGE_EXPORT bool checkIsChildOf(KisNodeSP node, const KisNodeList &parents);
KRITAIMAGE_EXPORT void filterUnlockedNodes(KisNodeList &nodes);
KRITAIMAGE_EXPORT void refreshHiddenAreaAsync(KisImageSP image, KisNodeSP rootNode, const QRect &preparedArea);
KRITAIMAGE_EXPORT QRect recursiveNodeExactBounds(KisNodeSP rootNode);
KRITAIMAGE_EXPORT QRect recursiveTightNodeVisibleBounds(KisNodeSP rootNode);
/**
* Returns true if:
......
......@@ -84,3 +84,8 @@ QRect KisMaskProjectionPlane::needRectForOriginal(const QRect &rect) const
return rect;
}
QRect KisMaskProjectionPlane::tightUserVisibleBounds() const
{
return QRect();
}
......@@ -44,6 +44,7 @@ public:
QRect changeRect(const QRect &rect, KisNode::PositionToFilthy pos) const override;
QRect accessRect(const QRect &rect, KisNode::PositionToFilthy pos) const override;
QRect needRectForOriginal(const QRect &rect) const override;
QRect tightUserVisibleBounds() const override;
KisPaintDeviceList getLodCapableDevices() const override;
......
......@@ -153,3 +153,13 @@ QRect KisLayerStyleFilterProjectionPlane::needRectForOriginal(const QRect &rect)
return needRect(rect, KisLayer::N_ABOVE_FILTHY);
}
QRect KisLayerStyleFilterProjectionPlane::tightUserVisibleBounds() const
{
KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(m_d->filter, QRect());
KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(m_d->sourceLayer, QRect());
return m_d->filter->changedRect(m_d->sourceLayer->exactBounds(),
m_d->style,
m_d->environment.data());
}
......@@ -44,6 +44,7 @@ public:
QRect changeRect(const QRect &rect, KisLayer::PositionToFilthy pos) const override;
QRect accessRect(const QRect &rect, KisLayer::PositionToFilthy pos) const override;
QRect needRectForOriginal(const QRect &rect) const override;
QRect tightUserVisibleBounds() const override;
KisPaintDeviceList getLodCapableDevices() const override;
......
......@@ -402,6 +402,18 @@ QRect KisLayerStyleProjectionPlane::needRectForOriginal(const QRect &rect) const
return needRect;
}
QRect KisLayerStyleProjectionPlane::tightUserVisibleBounds() const
{
KisAbstractProjectionPlaneSP sourcePlane = m_d->sourceProjectionPlane.toStrongRef();
QRect rect = sourcePlane->tightUserVisibleBounds();
Q_FOREACH (const KisAbstractProjectionPlaneSP plane, m_d->allStyles()) {
rect |= plane->tightUserVisibleBounds();
}
return rect;
}
QRect KisLayerStyleProjectionPlane::stylesNeedRect(const QRect &rect) const
{
QRect needRect = rect;
......
......@@ -43,6 +43,7 @@ public:
QRect changeRect(const QRect &rect, KisLayer::PositionToFilthy pos) const override;
QRect accessRect(const QRect &rect, KisLayer::PositionToFilthy pos) const override;
QRect needRectForOriginal(const QRect &rect) const override;
QRect tightUserVisibleBounds() const override;
KisPaintDeviceList getLodCapableDevices() const override;
......
......@@ -112,7 +112,7 @@ void MoveStrokeStrategy::initStrokeCallback()
Q_FOREACH(KisNodeSP node, m_nodes) {
saveInitialNodeOffsets(node);
handlesRect |= KisLayerUtils::recursiveNodeExactBounds(node);
handlesRect |= KisLayerUtils::recursiveTightNodeVisibleBounds(node);
}
KisStrokeStrategyUndoCommandBased::initStrokeCallback();
......
......@@ -36,7 +36,7 @@ void KisMoveBoundsCalculationJob::run()
QRect handlesRect;
Q_FOREACH (KisNodeSP node, m_nodes) {
handlesRect |= KisLayerUtils::recursiveNodeExactBounds(node);
handlesRect |= KisLayerUtils::recursiveTightNodeVisibleBounds(node);
}
if (m_selection) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment