File indexing completed on 2025-01-26 04:11:16

0001 /*
0002  *  SPDX-FileCopyrightText: 2013 Dmitry Kazakov <dimula73@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "kis_brushop_test.h"
0008 
0009 #include <simpletest.h>
0010 #include <qimage_based_test.h>
0011 #include <stroke_testing_utils.h>
0012 #include <brushengine/kis_paint_information.h>
0013 #include <kis_canvas_resource_provider.h>
0014 #include <brushengine/kis_paintop_preset.h>
0015 #include <brushengine/kis_paintop_settings.h>
0016 #include <KisMirrorOptionData.h>
0017 #include <KisStandardOptionData.h>
0018 
0019 class TestBrushOp : public TestUtil::QImageBasedTest
0020 {
0021 public:
0022     TestBrushOp(const QString &presetFileName, const QString &prefix = "simple")
0023         : QImageBasedTest("brushop") {
0024         m_presetFileName = presetFileName;
0025         m_prefix = prefix;
0026     }
0027 
0028     virtual ~TestBrushOp() {}
0029 
0030     void test() {
0031         test(false, false,  0.0);
0032         test(false, false, 10.0);
0033         test(false, false, 20.0);
0034 
0035         test(true, false,  0.0);
0036         test(true, false, 10.0);
0037         test(true, false, 20.0);
0038 
0039         test(false, true,  0.0);
0040         test(false, true, 10.0);
0041         test(false, true, 20.0);
0042 
0043         test(true, true,  0.0);
0044         test(true, true, 10.0);
0045         test(true, true, 20.0);
0046     }
0047 
0048     void test(bool mirrorX, bool mirrorY, qreal rotation) {
0049         test(mirrorX, mirrorY, rotation, false, false);
0050         test(mirrorX, mirrorY, rotation, true,  false);
0051         test(mirrorX, mirrorY, rotation, false, true);
0052         test(mirrorX, mirrorY, rotation, true,  true);
0053     }
0054 
0055     void test(bool mirrorX, bool mirrorY, qreal rotation, bool mirrorDabX, bool mirrorDabY) {
0056         test(mirrorX, mirrorY, rotation, mirrorDabX, mirrorDabY, 0.0);
0057         test(mirrorX, mirrorY, rotation, mirrorDabX, mirrorDabY, 360.0 - 10.0);
0058         test(mirrorX, mirrorY, rotation, mirrorDabX, mirrorDabY, 360.0 - 20.0);
0059     }
0060 
0061     void test(bool mirrorX, bool mirrorY, qreal rotation, bool mirrorDabX, bool mirrorDabY, qreal dabRotation) {
0062 
0063         KisSurrogateUndoStore *undoStore = new KisSurrogateUndoStore();
0064         KisImageSP image = createTrivialImage(undoStore);
0065         image->initialRefreshGraph();
0066 
0067         KisNodeSP paint1 = findNode(image->root(), "paint1");
0068 
0069         QVERIFY(paint1->extent().isEmpty());
0070 
0071         KisPainter gc(paint1->paintDevice());
0072 
0073         QScopedPointer<KoCanvasResourceProvider> manager(
0074             utils::createResourceManager(image, 0, m_presetFileName));
0075 
0076         KisPaintOpPresetSP preset =
0077             manager->resource(KoCanvasResource::CurrentPaintOpPreset).value<KisPaintOpPresetSP>();
0078 
0079         if (mirrorDabX || mirrorDabY) {
0080             KisPaintOpSettingsSP settings = preset->settings()->clone();
0081 
0082             KisMirrorOptionData mirrorData;
0083             mirrorData.read(settings.data());
0084 
0085             mirrorData.isChecked = true;
0086             mirrorData.useCurve = false;
0087 
0088             mirrorData.enableHorizontalMirror = mirrorDabX;
0089             mirrorData.enableVerticalMirror = mirrorDabY;
0090 
0091             mirrorData.write(settings.data());
0092 
0093             preset->setSettings(settings);
0094         }
0095 
0096         if (dabRotation != 0.0) {
0097             KisPaintOpSettingsSP settings = preset->settings()->clone();
0098 
0099             KisRotationOptionData rotationData;
0100             rotationData.read(settings.data());
0101 
0102             rotationData.isChecked = true;
0103             rotationData.useCurve = false;
0104 
0105             rotationData.strengthValue = dabRotation / 360.0;
0106 
0107             rotationData.write(settings.data());
0108 
0109             preset->setSettings(settings);
0110         }
0111 
0112 
0113         QString testName =
0114             QString("%7_cmY_%1_cmX_%2_cR_%3_dmX_%4_dmY_%5_dR_%6")
0115             .arg(mirrorY)
0116             .arg(mirrorX)
0117             .arg(rotation)
0118             .arg(mirrorDabX)
0119             .arg(mirrorDabY)
0120             .arg(std::fmod(360.0 - dabRotation, 360.0))
0121             .arg(m_prefix);
0122 
0123         KisResourcesSnapshotSP resources =
0124             new KisResourcesSnapshot(image,
0125                                      paint1,
0126                                      manager.data());
0127 
0128         resources->setupPainter(&gc);
0129 
0130         doPaint(gc, rotation, mirrorX, mirrorY);
0131 
0132         checkOneLayer(image, paint1, testName);
0133     }
0134 
0135     virtual void doPaint(KisPainter &gc, qreal rotation, bool mirrorX, bool mirrorY) {
0136         KisPaintInformation pi(QPointF(100, 100), 1.0);
0137         pi.setCanvasRotation(rotation);
0138         pi.setCanvasMirroredH(mirrorX);
0139         pi.setCanvasMirroredV(mirrorY);
0140 
0141         KisDistanceInformation dist;
0142         gc.paintAt(pi, &dist);
0143     }
0144 
0145     QString m_presetFileName;
0146     QString m_prefix;
0147 };
0148 
0149 class TestBrushOpLines : public TestBrushOp
0150 {
0151 public:
0152     TestBrushOpLines(const QString &presetFileName)
0153         : TestBrushOp(presetFileName) {
0154     }
0155 
0156     void doPaint(KisPainter &gc, qreal rotation, bool mirrorX, bool mirrorY) override {
0157 
0158         QVector<KisPaintInformation> vector;
0159 
0160         vector << KisPaintInformation(QPointF(100, 100));
0161         vector << KisPaintInformation(QPointF(200, 150));
0162         vector << KisPaintInformation(QPointF(100, 350));
0163 
0164 
0165         for (auto pi : vector) {
0166             pi.setCanvasRotation(rotation);
0167             pi.setCanvasMirroredH(mirrorX);
0168             pi.setCanvasMirroredV(mirrorY);
0169         }
0170 
0171         KisDistanceInformation dist;
0172 
0173         for (int i = 1; i < vector.size(); i++) {
0174             gc.paintLine(vector[i - 1], vector[i], &dist);
0175         }
0176     }
0177 };
0178 
0179 class TestBrushOpPressureLines : public TestBrushOp
0180 {
0181 public:
0182     TestBrushOpPressureLines(const QString &presetFileName, const QString &prefix)
0183         : TestBrushOp(presetFileName, prefix) {
0184     }
0185 
0186     void doPaint(KisPainter &gc, qreal rotation, bool mirrorX, bool mirrorY) override {
0187 
0188         QVector<KisPaintInformation> vector;
0189 
0190         vector << KisPaintInformation(QPointF(0, 0), 0.2);
0191         vector << KisPaintInformation(QPointF(200, 50), 1.0);
0192         vector << KisPaintInformation(QPointF(100, 250), 0.0);
0193         vector << KisPaintInformation(QPointF(200, 150), 1.0);
0194         vector << KisPaintInformation(QPointF(100, 350), 1.0);
0195 
0196         for (auto pi : vector) {
0197             pi.setCanvasRotation(rotation);
0198             pi.setCanvasMirroredH(mirrorX);
0199             pi.setCanvasMirroredV(mirrorY);
0200         }
0201 
0202         KisDistanceInformation dist;
0203 
0204         for (int i = 1; i < vector.size(); i++) {
0205             gc.paintLine(vector[i - 1], vector[i], &dist);
0206         }
0207     }
0208 };
0209 
0210 #include <KoResourcePaths.h>
0211 void KisBrushOpTest::initTestCase()
0212 {
0213     KoResourcePaths::addAssetDir(ResourceType::Brushes, QString(SYSTEM_RESOURCES_DATA_DIR) + "/brushes");
0214 }
0215 
0216 void KisBrushOpTest::testRotationMirroring()
0217 {
0218     TestBrushOp t("LR_simple.kpp");
0219     t.test();
0220 }
0221 
0222 void KisBrushOpTest::testRotationMirroringDrawingAngle()
0223 {
0224     TestBrushOpLines t("LR_drawing_angle.kpp");
0225     t.test();
0226 }
0227 
0228 void KisBrushOpTest::testMagicSeven()
0229 {
0230     /**
0231      * A special preset that forces Qt to bug:
0232      *     mask size: 56
0233      *     brush size: 7
0234      *     therefore scale is: 0.125
0235      *     which causes QTransform work as a pure Translate in the mipmap
0236      */
0237 
0238     TestBrushOpPressureLines t("magic_seven.kpp", "magicseven");
0239     t.test();
0240 }
0241 
0242 SIMPLE_TEST_MAIN(KisBrushOpTest)