File indexing completed on 2024-12-22 04:12:52

0001 /*
0002  * This file contains tests for:
0003  *
0004  * - KisPaintingAssistantsDecoration
0005  * - ParallelRulerAssistant
0006  * - PerspectiveAssistant
0007  *
0008  *  SPDX-License-Identifier: GPL-3.0-or-later
0009  */
0010 
0011 #include <testutil.h>
0012 #include "qimage_based_test.h"
0013 
0014 #include <KoCanvasResourceProvider.h>
0015 #include "kis_canvas_resource_provider.h"
0016 #include <util.h>
0017 #include <KisMainWindow.h>
0018 #include <KisDocument.h>
0019 #include <KisPart.h>
0020 #include <KisView.h>
0021 #include <KisViewManager.h>
0022 #include <KisDecorationsManager.h>
0023 
0024 #include "kis_painting_assistants_decoration.h"
0025 #include "KisPart.h"
0026 #include "testui.h"
0027 #include <kis_config.h>
0028 #include <testutil.h>
0029 #include <KoResourcePaths.h>
0030 #include "opengl/kis_opengl.h"
0031 #include "kis_painting_assistants_decoration_test.h"
0032 
0033 void KisPaintingAssistantsDecorationTest::initTestCase()
0034 {
0035     /* A bit of a heavy handed way to force the plugins to be loaded and get
0036      * access to the paintingAssistantsDecoration but can't find another way
0037      * at the moment
0038      */
0039     m_document = createEmptyDocument();
0040     m_mainWindow = KisPart::instance()->createMainWindow();
0041     m_view = new KisView(m_document, m_mainWindow->viewManager(), m_mainWindow);
0042     m_viewManager = new KisViewManager(m_mainWindow, m_mainWindow->actionCollection());
0043     QApplication::processEvents();
0044 }
0045 
0046 
0047 void KisPaintingAssistantsDecorationTest::cleanupTestCase()
0048 {
0049     /* Clean-up properly otherwise there will be an
0050      * assert during application exit.
0051      */
0052     m_mainWindow->hide();
0053     QApplication::processEvents();
0054     delete m_view;
0055     delete m_document;
0056     delete m_mainWindow;
0057 }
0058 
0059 /*
0060  * Test Perspective Assistant construction and using it for brush position
0061  * Adjustment
0062  */
0063 void KisPaintingAssistantsDecorationTest::testPerspectiveAssistant()
0064 {
0065     KisPaintingAssistantsDecorationSP paintingAssistantsDecoration =
0066         m_view->canvasBase()->paintingAssistantsDecoration();
0067 
0068     const KisPaintingAssistantFactoryRegistry* r = KisPaintingAssistantFactoryRegistry::instance();
0069     QVERIFY(r);
0070 
0071     KisPaintingAssistantFactory* factory = r->get("perspective");
0072     QVERIFY(factory);
0073 
0074     KisPaintingAssistantSP assistant = toQShared(factory->createPaintingAssistant());
0075 
0076     QVERIFY(assistant->isAssistantComplete() == false);
0077 
0078     KisPaintingAssistantHandleSP h1 = new KisPaintingAssistantHandle(10.0, 10.0);
0079     KisPaintingAssistantHandleSP h2 = new KisPaintingAssistantHandle(20.0, 90.0);
0080     KisPaintingAssistantHandleSP h3 = new KisPaintingAssistantHandle(60.0, 90.0);
0081     KisPaintingAssistantHandleSP h4 = new KisPaintingAssistantHandle(70.0, 10.0);
0082 
0083     assistant->addHandle(h1, NORMAL);
0084     assistant->addHandle(h2, NORMAL);
0085     assistant->addHandle(h3, NORMAL);
0086     assistant->addHandle(h4, NORMAL);
0087 
0088     QVERIFY(assistant->isAssistantComplete() == true);
0089 
0090     // Move straight up.
0091     QPointF startPosition(14.0, 14.0);
0092     QPointF p2(14.0, 90.0);
0093     QPointF adjustedPosition;
0094     // Compute twice to make sure state variables get taken into account
0095     adjustedPosition = assistant->adjustPosition(p2, startPosition, true, 4.0);
0096     adjustedPosition = assistant->adjustPosition(p2, startPosition, true, 4.0);
0097     // Should lead to a adjustment
0098     QVERIFY(adjustedPosition != p2);
0099 }
0100 
0101 
0102 /*
0103  * Test adjusting the brush position based on one or more Parallel rulers via
0104  * the PaintingAssistantDecoration.
0105  */
0106 void KisPaintingAssistantsDecorationTest::testParallelRulerAdjustPosition()
0107 {
0108     KisPaintingAssistantsDecorationSP paintingAssistantsDecoration =
0109         m_view->canvasBase()->paintingAssistantsDecoration();
0110 
0111     QVERIFY(paintingAssistantsDecoration->isEditingAssistants() == false);
0112 
0113     const KisPaintingAssistantFactoryRegistry* r = KisPaintingAssistantFactoryRegistry::instance();
0114     QVERIFY(r);
0115 
0116     KisPaintingAssistantFactory* factory = r->get("parallel ruler");
0117     QVERIFY(factory);
0118 
0119     KisPaintingAssistantSP assistant = toQShared(factory->createPaintingAssistant());
0120 
0121     QVERIFY(assistant->isAssistantComplete() == false);
0122 
0123     // A horizontal parallel ruler
0124     KisPaintingAssistantHandleSP h1 = new KisPaintingAssistantHandle(10.0, 10.0);
0125     KisPaintingAssistantHandleSP h2 = new KisPaintingAssistantHandle(90.0, 10.0);
0126     assistant->addHandle(h1, NORMAL);
0127     assistant->addHandle(h2, NORMAL);
0128     // A parallel ruler assistant needs two handles so now it should be
0129     // complete
0130     QVERIFY(assistant->numHandles() == 2);
0131     QVERIFY(assistant->isAssistantComplete() == true);
0132     // The assistant is now complete and can be used for computing brush
0133     // position adjustments
0134 
0135 
0136     // Move in a slanted direction
0137     QPointF startPosition(10.0, 50.0);
0138     QPointF p2(90.0, 90.0);
0139     QPointF adjustedPosition;
0140 
0141     // When the paintingAssistantsDecoration does not contain any assistants
0142     // there should be no position adjustments.
0143     // (Test twice to make sure state variables get taken into account).
0144     adjustedPosition = paintingAssistantsDecoration->adjustPosition(p2, startPosition);
0145     QVERIFY(adjustedPosition == p2);
0146     adjustedPosition = paintingAssistantsDecoration->adjustPosition(p2, startPosition);
0147     QVERIFY(adjustedPosition == p2);
0148 
0149     // Add an assistant
0150     paintingAssistantsDecoration->addAssistant(assistant);
0151 
0152     // First compute directly via the assistant
0153     adjustedPosition = assistant->adjustPosition(p2, startPosition, true, 4.0);
0154     // The position should be adjusted to the horizontal direction
0155     QVERIFY(adjustedPosition.x() == 90.0);
0156     QVERIFY(adjustedPosition.y() == 50.0);
0157     // Compute the same adjustment via the PaintingAssistantDecoration
0158     QPointF adjustedPosition2 = paintingAssistantsDecoration->adjustPosition(p2, startPosition);
0159     // Resulting positions should match
0160     QVERIFY(adjustedPosition == adjustedPosition2);
0161 
0162     // Add two more assistants
0163 
0164     // (1) A vertical parallel ruler
0165     KisPaintingAssistantSP assistant_2 = toQShared(factory->createPaintingAssistant());
0166     KisPaintingAssistantHandleSP h3 = new KisPaintingAssistantHandle(10.0, 10.0);
0167     KisPaintingAssistantHandleSP h4 = new KisPaintingAssistantHandle(10.0, 90.0);
0168     assistant_2->addHandle(h3, NORMAL);
0169     assistant_2->addHandle(h4, NORMAL);
0170 
0171     // (2) A 45 degree parallel ruler
0172     KisPaintingAssistantSP assistant_3 = toQShared(factory->createPaintingAssistant());
0173     KisPaintingAssistantHandleSP h5 = new KisPaintingAssistantHandle(10.0, 10.0);
0174     KisPaintingAssistantHandleSP h6 = new KisPaintingAssistantHandle(90.0, 90.0);
0175     assistant_3->addHandle(h5, NORMAL);
0176     assistant_3->addHandle(h6, NORMAL);
0177 
0178     paintingAssistantsDecoration->addAssistant(assistant_2);
0179     paintingAssistantsDecoration->addAssistant(assistant_3);
0180 
0181     // startPosition == 10.0, 50.0
0182     QPointF p3(11.0, 50.1); // Less than |4| from the start position
0183     QPointF p4(15.0, 50.1); // More than |4| from the start position
0184     QPointF p5(18.0, 51.1); // Almost horizontal line
0185     QPointF p6(11.0, 65.1); // Almost vertical line
0186 
0187     // Switch to the more were we continuously snap to the best matching
0188     // assistant
0189     paintingAssistantsDecoration->setOnlyOneAssistantSnap(false);
0190     adjustedPosition = paintingAssistantsDecoration->adjustPosition(p3, startPosition);
0191 
0192     adjustedPosition = paintingAssistantsDecoration->adjustPosition(p4, startPosition);
0193     adjustedPosition = paintingAssistantsDecoration->adjustPosition(p5, startPosition);
0194     // Horizontal ruler should be the best match
0195     QVERIFY(adjustedPosition.y() == 50.0);
0196     adjustedPosition = paintingAssistantsDecoration->adjustPosition(p6, startPosition);
0197     // Vertical ruler should be the best match
0198     QVERIFY(adjustedPosition.x() == 10.0);
0199     paintingAssistantsDecoration->endStroke();
0200 
0201     // Switch to the more were first find the best matching
0202     // assistant and then keep using it
0203     paintingAssistantsDecoration->setOnlyOneAssistantSnap(true);
0204     adjustedPosition = paintingAssistantsDecoration->adjustPosition(p3, startPosition);
0205     adjustedPosition = paintingAssistantsDecoration->adjustPosition(p4, startPosition);
0206     adjustedPosition = paintingAssistantsDecoration->adjustPosition(p5, startPosition);
0207     // Horizontal ruler should be the best match
0208     QVERIFY(adjustedPosition.y() == 50.0);
0209     adjustedPosition = paintingAssistantsDecoration->adjustPosition(p6, startPosition);
0210     // Horizontal ruler should still be the best match, even though we moved
0211     // vertically
0212     QVERIFY(adjustedPosition.y() == 50.0);
0213     paintingAssistantsDecoration->endStroke();
0214 
0215 }
0216 
0217 
0218 KISTEST_MAIN(KisPaintingAssistantsDecorationTest)
0219