Bug 485689 - Vector layer incorrect transform result when both scaled and sheared
Summary: Vector layer incorrect transform result when both scaled and sheared
Status: RESOLVED FIXED
Alias: None
Product: krita
Classification: Applications
Component: Tools/Transform (show other bugs)
Version: nightly build (please specify the git hash!)
Platform: Kubuntu Linux
: NOR normal
Target Milestone: ---
Assignee: Krita Bugs
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2024-04-17 17:59 UTC by stuff
Modified: 2024-04-24 12:03 UTC (History)
0 users

See Also:
Latest Commit:
Version Fixed In:


Attachments
Using krita-5.3.0-prealpha-13fe82adbb-x86_64.appimage (157.69 KB, video/x-matroska)
2024-04-17 17:59 UTC, stuff
Details

Note You need to log in before you can comment on or make changes to this bug.
Description stuff 2024-04-17 17:59:09 UTC
Created attachment 168625 [details]
Using krita-5.3.0-prealpha-13fe82adbb-x86_64.appimage

SUMMARY

If you both shear and scale a vector layer with the free transform tool, the end result will either change (potentially significantly) from the preview, or the the preview itself will also be wrong and visibly break out of its bounding box.  If the preview looks right, changing preview mode will show the wrong result for a split second.

STEPS TO REPRODUCE
1. Make a new *vector* layer
2. Add some shape, like a rectangle or polyline
3. Activate the transform tool
4. Shear both edges to approximate an overall 45 degree rotation
5. Scale out along what was the top edge

OBSERVED RESULT

Either the preview will break out of the handle bounding box, or once you apply the transform you will get a very different result from the preview.

EXPECTED RESULT

The preview should stay within the bounding box, and the end result should match the preview.

SOFTWARE/OS VERSIONS
Linux/KDE Plasma: Kubuntu 23.10
(available in About System)
KDE Plasma Version: 5.27.8
KDE Frameworks Version:  5.110.0
Qt Version: 5.15.10

ADDITIONAL INFORMATION
Affects master, krita-5.3.0-prealpha-13fe82adbb-x86_64.appimage, and 5.2.2
Comment 1 stuff 2024-04-17 20:44:25 UTC
I looked into this: KisTransformWorker::transform() reports its supposed transform, though never uses this function itself.  This reported transform is used for the vector layer's shape transforms and looks like:

    return TS.inverted() * S * TS * SC * R * T;

Whereas KisTransformUtils::MatricesPack::finalTransform() looks like:

    return TS * SC * S * projectedP * T;

Notice that SC and S are in a reverse order!

There are three different transforms in play
    1) the bounding box during free transform (uses MatricesPack)
    2) the rasterized result of KisTransformWorker, using its mathy inner workings
    3) the vector layer result using KisTransformWorker::transform()
I think 1 and 2 currently agree, but 3 doesn't, so I suspect maybe KisTransformWorker is just reporting its own transform wrong?

Through trial and error I've found this function, a slight modification from the current one, seems to fix this problem.
QTransform KisTransformWorker::transform() const
{
    QTransform TS = QTransform::fromTranslate(m_xshearOrigin * m_xscale, m_yshearOrigin * m_yscale);
    QTransform S; S.shear(0, m_yshear); S.shear(m_xshear, 0);
    QTransform SC = QTransform::fromScale(m_xscale, m_yscale);
    QTransform R; R.rotateRadians(m_rotation);
    QTransform T = QTransform::fromTranslate(m_xtranslate, m_ytranslate);

    return SC * TS.inverted() * S * TS * R * T;
}
where I've swapped the order of scale and shear and compensated for that in the translation

Also, with this modified version, at the end of KisTransformUtils::createTransformWorker, MatricesPack(args).finalTransform() tends to be equal or nearly equal (within 1e-5 component-wise) to transformWorker.transform(), where it definitely wasn't before.  There's a comment explaining KisTransformWorker::transform that does match the current code, though, so I'm not sure what's going on.
Comment 2 Dmitry Kazakov 2024-04-24 12:03:48 UTC
Git commit 72446d9edcc45d183ffb769353cef8913873cab5 by Dmitry Kazakov, on behalf of stuffins lastname.
Committed on 24/04/2024 at 12:02.
Pushed by dkazakov into branch 'master'.

Fix Vector layer scale+shear transforms

Removed transform worker's shearOrigin, updated KisImage::shearImpl since it was the only place using it without finding a compensating translation afterward, and fixed KisTransformWorker::transform() to correspond to the actual transform applied.

Also removed the unused out parameter from KisTransformUtils::createTransformWorker.

M  +6    -8    libs/image/kis_image.cc
M  +1    -1    libs/image/kis_paint_device.cc
M  +6    -17   libs/image/kis_transform_worker.cc
M  +3    -17   libs/image/kis_transform_worker.h
M  +2    -2    libs/image/processing/kis_mirror_processing_visitor.cpp
M  +0    -7    libs/image/processing/kis_transform_processing_visitor.cpp
M  +1    -2    libs/image/processing/kis_transform_processing_visitor.h
M  +2    -2    libs/image/tests/kis_processings_test.cpp
M  +0    -18   libs/image/tests/kis_transform_worker_test.cpp
M  +1    -1    libs/ui/KisImageThumbnailStrokeStrategy.cpp
M  +2    -2    libs/ui/kis_file_layer.cpp
M  +2    -2    plugins/tools/tool_smart_patch/kis_inpaint.cpp
M  +8    -10   plugins/tools/tool_transform2/kis_transform_utils.cpp
M  +1    -2    plugins/tools/tool_transform2/kis_transform_utils.h
M  +1    -2    plugins/tools/tool_transform2/strokes/inplace_transform_stroke_strategy.cpp
M  +1    -2    plugins/tools/tool_transform2/strokes/transform_stroke_strategy.cpp

https://invent.kde.org/graphics/krita/-/commit/72446d9edcc45d183ffb769353cef8913873cab5