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
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) >
A possibly relevant merge request was started @ https://invent.kde.org/graphics/krita/-/merge_requests/2839
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
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