File indexing completed on 2025-03-09 04:03:39
0001 /* This file is part of the KDE project 0002 * SPDX-FileCopyrightText: 2006 Jan Hambrecht <jaham@gmx.net> 0003 * SPDX-FileCopyrightText: 2006, 2007 Thorsten Zachmann <zachmann@kde.org> 0004 * 0005 * SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "KoPathControlPointMoveCommand.h" 0009 #include <klocalizedstring.h> 0010 #include <math.h> 0011 #include "kis_command_ids.h" 0012 0013 KoPathControlPointMoveCommand::KoPathControlPointMoveCommand( 0014 const KoPathPointData &pointData, 0015 const QPointF &offset, 0016 KoPathPoint::PointType pointType, 0017 KUndo2Command *parent) 0018 : KUndo2Command(parent) 0019 , m_pointData(pointData) 0020 , m_pointType(pointType) 0021 { 0022 Q_ASSERT(offset.x() < 1e14 && offset.y() < 1e14); 0023 KoPathShape * pathShape = m_pointData.pathShape; 0024 KoPathPoint * point = pathShape->pointByIndex(m_pointData.pointIndex); 0025 if (point) { 0026 m_offset = offset; 0027 } 0028 0029 setText(kundo2_i18n("Move control point")); 0030 } 0031 0032 void KoPathControlPointMoveCommand::redo() 0033 { 0034 KUndo2Command::redo(); 0035 KoPathShape * pathShape = m_pointData.pathShape; 0036 KoPathPoint * point = pathShape->pointByIndex(m_pointData.pointIndex); 0037 if (point) { 0038 const QRectF oldDirtyRect = pathShape->boundingRect(); 0039 0040 if (m_pointType == KoPathPoint::ControlPoint1) { 0041 point->setControlPoint1(point->controlPoint1() + m_offset); 0042 if (point->properties() & KoPathPoint::IsSymmetric) { 0043 // set the other control point so that it lies on the line between the moved 0044 // control point and the point, with the same distance to the point as the moved point 0045 point->setControlPoint2(2.0 * point->point() - point->controlPoint1()); 0046 } else if (point->properties() & KoPathPoint::IsSmooth) { 0047 // move the other control point so that it lies on the line through point and control point 0048 // keeping its distance to the point 0049 QPointF direction = point->point() - point->controlPoint1(); 0050 direction /= sqrt(direction.x() * direction.x() + direction.y() * direction.y()); 0051 QPointF distance = point->point() - point->controlPoint2(); 0052 qreal length = sqrt(distance.x() * distance.x() + distance.y() * distance.y()); 0053 point->setControlPoint2(point->point() + length * direction); 0054 } 0055 } else if (m_pointType == KoPathPoint::ControlPoint2) { 0056 point->setControlPoint2(point->controlPoint2() + m_offset); 0057 if (point->properties() & KoPathPoint::IsSymmetric) { 0058 // set the other control point so that it lies on the line between the moved 0059 // control point and the point, with the same distance to the point as the moved point 0060 point->setControlPoint1(2.0 * point->point() - point->controlPoint2()); 0061 } else if (point->properties() & KoPathPoint::IsSmooth) { 0062 // move the other control point so that it lies on the line through point and control point 0063 // keeping its distance to the point 0064 QPointF direction = point->point() - point->controlPoint2(); 0065 direction /= sqrt(direction.x() * direction.x() + direction.y() * direction.y()); 0066 QPointF distance = point->point() - point->controlPoint1(); 0067 qreal length = sqrt(distance.x() * distance.x() + distance.y() * distance.y()); 0068 point->setControlPoint1(point->point() + length * direction); 0069 } 0070 } 0071 0072 pathShape->normalize(); 0073 pathShape->updateAbsolute(oldDirtyRect | pathShape->boundingRect()); 0074 } 0075 } 0076 0077 void KoPathControlPointMoveCommand::undo() 0078 { 0079 KUndo2Command::undo(); 0080 m_offset *= -1.0; 0081 redo(); 0082 m_offset *= -1.0; 0083 } 0084 0085 int KoPathControlPointMoveCommand::id() const 0086 { 0087 return KisCommandUtils::ChangePathShapeControlPointId; 0088 } 0089 0090 bool KoPathControlPointMoveCommand::mergeWith(const KUndo2Command *command) 0091 { 0092 const KoPathControlPointMoveCommand *other = dynamic_cast<const KoPathControlPointMoveCommand*>(command); 0093 0094 if (!other || 0095 other->m_pointData != m_pointData || 0096 other->m_pointType != m_pointType) { 0097 0098 return false; 0099 } 0100 0101 m_offset += other->m_offset; 0102 0103 return true; 0104 }