Bug 520602 - Transforming something with the perspective transform tool to an inverted position locks up the app
Summary: Transforming something with the perspective transform tool to an inverted pos...
Status: RESOLVED FIXED
Alias: None
Product: krita
Classification: Applications
Component: Tools/Transform (other bugs)
Version First Reported In: nightly build (please specify the git hash!)
Platform: Appimage Linux
: NOR crash
Target Milestone: ---
Assignee: Krita Bugs
URL:
Keywords: qt6
Depends on:
Blocks:
 
Reported: 2026-05-24 16:14 UTC by Iris
Modified: 2026-07-09 08:55 UTC (History)
1 user (show)

See Also:
Latest Commit:
Version Fixed/Implemented In:
Sentry Crash Report:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Iris 2026-05-24 16:14:14 UTC
DESCRIPTION


STEPS TO REPRODUCE
1. Select something
2. Select the transform tool
3. From the tool options, set the mode to perspective
4. Grab it from the top left corner and drag it to the bottom left side

OBSERVED RESULT
When it gets past the middle point, the transform tool stops responding, the layer shows a progress bar and on the bottom status bar you see a Transform 0% progress bar. After that you can no longer draw, save the file, quit krita normally, or anything. There is a transform task pending that never finishes and you can't cancel. This has caused me to lose progress.

EXPECTED RESULT
It transforms to an inverted perspective, or it stops me at the middle point, with everything working after.

SOFTWARE/OS VERSIONS
Operating System: Fedora Atomic
Krita Version: 6.1.0-prealpha (git 99e91d0)
Qt Version: 6.8.0

ADDITIONAL INFORMATION
Reproducible in both Wayland and x11
Not reproducible in stable 5.3
Comment 1 Freya Lupen 2026-06-28 19:31:10 UTC
Confirmed, happens on 6.0.0 and my 6.1.x-803fe0449-Qt6.11 build but not 5.3.2.1 or my 5.4.x-803fe0449-updated-deps build.

Trying to close Krita pops up the 'Waiting for image operation to complete' dialog; closing that with the X in the corner causes Krita to crash somewhere in ~KisMainWindow().
Backtrace of another thread shows the transform job running:
> Thread 11:: Thread (pooled)
> 0   QtGui                         	       0x10a1a7368 QPainterPath::contains(QPointF const&) const + 1256
> 1   QtGui                         	       0x10a1a77d0 QPainterPath::intersects(QRectF const&) const + 448
> 2   libkritaimage.21.0.0.dylib    	       0x108a2d918 KritaUtils::splitPath(QPainterPath const&) + 276 (krita_utils.cpp:173)
> 3   libkritaimage.21.0.0.dylib    	       0x108a0a6e4 KisPerspectiveTransformWorker::fillParams(QRectF const&, QRect const&, KisRegion*, QPolygonF*) + 364 (kis_perspectivetransform_worker.cpp:76)
> 4   libkritaimage.21.0.0.dylib    	       0x108a0a3b8 KisPerspectiveTransformWorker::init(QTransform const&) + 312 (kis_perspectivetransform_worker.cpp:93)
> 5   libkritaimage.21.0.0.dylib    	       0x108a0a538 KisPerspectiveTransformWorker::KisPerspectiveTransformWorker(KisSharedPtr<KisPaintDevice>, QTransform const&, bool, QPointer<KoUpdater>) + 184 (kis_perspectivetransform_worker.cpp:55)
> 6   kritatooltransform.so         	       0x14ca90cb4 (anonymous namespace)::transformDeviceImpl(ToolTransformArgs const&, KisSharedPtr<KisPaintDevice>, KisSharedPtr<KisPaintDevice>, KisProcessingVisitor::ProgressHelper*, bool, bool) + 1004 (kis_transform_utils.cpp:359)
> 7   kritatooltransform.so         	       0x14ca9083c KisTransformUtils::transformDevice(ToolTransformArgs const&, KisSharedPtr<KisPaintDevice>, KisSharedPtr<KisPaintDevice>, KisProcessingVisitor::ProgressHelper*) + 84 (kis_transform_utils.cpp:376)
> 8   kritatooltransform.so         	       0x14ca925e8 KisTransformUtils::transformAndMergeDevice(ToolTransformArgs const&, KisSharedPtr<KisPaintDevice>, KisSharedPtr<KisPaintDevice>, KisProcessingVisitor::ProgressHelper*) + 312 (kis_transform_utils.cpp:586)
> 9   kritatooltransform.so         	       0x14caaf850 InplaceTransformStrokeStrategy::transformNode(KisSharedPtr<KisNode>, ToolTransformArgs const&, int) + 776 (inplace_transform_stroke_strategy.cpp:830)
> 10  kritatooltransform.so         	       0x14cab8a10 InplaceTransformStrokeStrategy::reapplyTransform(ToolTransformArgs, QList<KisStrokeJobData*>&, int, bool)::$_1::operator()() const + 40 (inplace_transform_stroke_strategy.cpp:978) [inlined]
> 11  kritatooltransform.so         	       0x14cab8a10 decltype(std::declval<InplaceTransformStrokeStrategy::reapplyTransform(ToolTransformArgs, QList<KisStrokeJobData*>&, int, bool)::$_1&>()()) std::__1::__invoke[abi:ne190102]<InplaceTransformStrokeStrategy::reapplyTransform(ToolTransformArgs, QList<KisStrokeJobData*>&, int, bool)::$_1&>(InplaceTransformStrokeStrategy::reapplyTransform(ToolTransformArgs, QList<KisStrokeJobData*>&, int, bool)::$_1&) + 40 (invoke.h:149) [inlined]
> 12  kritatooltransform.so         	       0x14cab8a10 void std::__1::__invoke_void_return_wrapper<void, true>::__call[abi:ne190102]<InplaceTransformStrokeStrategy::reapplyTransform(ToolTransformArgs, QList<KisStrokeJobData*>&, int, bool)::$_1&>(InplaceTransformStrokeStrategy::reapplyTransform(ToolTransformArgs, QList<KisStrokeJobData*>&, int, bool)::$_1&) + 40 (invoke.h:224) [inlined]
> 13  kritatooltransform.so         	       0x14cab8a10 std::__1::__function::__alloc_func<InplaceTransformStrokeStrategy::reapplyTransform(ToolTransformArgs, QList<KisStrokeJobData*>&, int, bool)::$_1, std::__1::allocator<InplaceTransformStrokeStrategy::reapplyTransform(ToolTransformArgs, QList<KisStrokeJobData*>&, int, bool)::$_1>, void ()>::operator()[abi:ne190102]() + 40 (function.h:171) [inlined]
> 14  kritatooltransform.so         	       0x14cab8a10 std::__1::__function::__func<InplaceTransformStrokeStrategy::reapplyTransform(ToolTransformArgs, QList<KisStrokeJobData*>&, int, bool)::$_1, std::__1::allocator<InplaceTransformStrokeStrategy::reapplyTransform(ToolTransformArgs, QList<KisStrokeJobData*>&, int, bool)::$_1>, void ()>::operator()() + 64 (function.h:313)
> 15  libkritaimage.21.0.0.dylib    	       0x1086b78cc KisUpdateJobItem::runImpl() + 360 (kis_update_job_item.h:100) [inlined]
> 16  libkritaimage.21.0.0.dylib    	       0x1086b78cc KisUpdateJobItem::run() + 392 (kis_update_job_item.h:49)
> 17  QtCore                        	       0x10c548210 QThreadPoolThread::run() + 252
> 18  QtCore                        	       0x10c5f6524 QThreadPrivate::start(void*) + 392
> 19  libsystem_pthread.dylib       	       0x18af17bc8 _pthread_start + 136
> 20  libsystem_pthread.dylib       	       0x18af12b80 thread_start + 8

Investigation shows that it is getting stuck in KritaUtils::splitPath() because the QPainterPath passed by KisPerspectiveTransformWorker::fillParams() has become huge, after the m_dev->exactBounds() it's derived from has somehow gone far off-canvas:

> KisPerspectiveTransformWorker::init transform QTransform(type=TxProject, 11=2.00622 12=4.09944 13=0.00931691 21=-0.51276 22=-1.04106 23=-0.00474779 31=8.48005 32=10.9923 33=1.0667) m_srcRect QRectF(106,212 111x226) m_dev->exactBounds QRect(107,213 109x224)
> KisPerspectiveTransformWorker::fillParams splitPath( QPainterPath: Element count=6
>  -> MoveTo(x=107.309, y=214.579)
>  -> LineTo(x=160.968, y=326.554)
>  -> LineTo(x=217.299, y=440.647)
>  -> LineTo(x=-1017.1, y=-3300)
>  -> LineTo(x=-1052.47, y=-3300)
>  -> LineTo(x=107.309, y=214.579)
> 
> KisPerspectiveTransformWorker::fillParams )splitPath
> KisPerspectiveTransformWorker::init transform QTransform(type=TxProject, 11=990434 12=1.97694e+06 13=-0.00917431 21=488754 22=989202 23=-8.19564e-08 31=-4.48804e+12 32=-9.04135e+12 33=13980.3) m_srcRect QRectF(1.52368e+06,6.09472e+06 111x226) m_dev->exactBounds QRect(1523685,6094717 109x224)
> KisPerspectiveTransformWorker::fillParams splitPath( QPainterPath: Element count=6
>  -> MoveTo(x=-4.57139e+06, y=-1.10324e+07)
>  -> LineTo(x=6.09518e+06, y=1.00639e+07)
>  -> LineTo(x=6.09518e+06, y=1.53456e+07)
>  -> LineTo(x=1.261e+06, y=5.56309e+06)
>  -> LineTo(x=-4.57139e+06, y=-6.2412e+06)
>  -> LineTo(x=-4.57139e+06, y=-1.10324e+07)
>
Comment 2 Bug Janitor Service 2026-06-30 10:37:03 UTC
A possibly relevant merge request was started @ https://invent.kde.org/graphics/krita/-/merge_requests/2839
Comment 3 Luna 2026-07-09 08:54:53 UTC
Git commit 7eaaef7ba568561468d0344f777d189e5b59df13 by Luna Lovecraft.
Committed on 09/07/2026 at 08:14.
Pushed by dkazakov into branch 'master'.

Fix deadlock when doing perspective transform

When the perspective transform shape becomes convex, perspecive
calculations explode causing a deadlock. So we just prevent that from
happening by blocking further handle movement when the shape stops being
convex.

M  +11   -0    plugins/tools/tool_transform2/kis_perspective_transform_strategy.cpp

https://invent.kde.org/graphics/krita/-/commit/7eaaef7ba568561468d0344f777d189e5b59df13
Comment 4 Dmitry Kazakov 2026-07-09 08:55:19 UTC
Git commit aff131a066d8d0fa376ec2a3fc46e878acf0b588 by Dmitry Kazakov, on behalf of Luna Lovecraft.
Committed on 09/07/2026 at 08:55.
Pushed by dkazakov into branch 'krita/6.0'.

Fix deadlock when doing perspective transform

When the perspective transform shape becomes convex, perspecive
calculations explode causing a deadlock. So we just prevent that from
happening by blocking further handle movement when the shape stops being
convex.

M  +11   -0    plugins/tools/tool_transform2/kis_perspective_transform_strategy.cpp

https://invent.kde.org/graphics/krita/-/commit/aff131a066d8d0fa376ec2a3fc46e878acf0b588