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)