File indexing completed on 2025-01-05 04:03:22
0001 0002 /* 0003 Copyright (c) 2003-2007 Clarence Dang <dang@kde.org> 0004 All rights reserved. 0005 0006 Redistribution and use in source and binary forms, with or without 0007 modification, are permitted provided that the following conditions 0008 are met: 0009 0010 1. Redistributions of source code must retain the above copyright 0011 notice, this list of conditions and the following disclaimer. 0012 2. Redistributions in binary form must reproduce the above copyright 0013 notice, this list of conditions and the following disclaimer in the 0014 documentation and/or other materials provided with the distribution. 0015 0016 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 0017 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 0018 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 0019 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 0020 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 0021 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 0022 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 0023 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 0024 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 0025 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 0026 */ 0027 0028 0029 #define DEBUG_KP_TOOL_SKEW 0 0030 #define DEBUG_KP_TOOL_SKEW_DIALOG 0 0031 0032 0033 #include "kpTransformSkewCommand.h" 0034 0035 #include "layers/selections/image/kpAbstractImageSelection.h" 0036 #include "environments/commands/kpCommandEnvironment.h" 0037 #include "kpDefs.h" 0038 #include "document/kpDocument.h" 0039 #include "layers/selections/image/kpFreeFormImageSelection.h" 0040 #include "pixmapfx/kpPixmapFX.h" 0041 #include "layers/selections/image/kpRectangularImageSelection.h" 0042 #include "kpLogCategories.h" 0043 0044 #include <QApplication> 0045 #include <QTransform> 0046 #include <QPolygon> 0047 0048 // TODO: nasty, should avoid using GUI class in this command class 0049 #include "dialogs/imagelib/transforms/kpTransformSkewDialog.h" 0050 0051 #include <KLocalizedString> 0052 0053 //-------------------------------------------------------------------------------- 0054 0055 kpTransformSkewCommand::kpTransformSkewCommand (bool actOnSelection, 0056 int hangle, int vangle, 0057 kpCommandEnvironment *environ) 0058 : kpCommand (environ), 0059 m_actOnSelection (actOnSelection), 0060 m_hangle (hangle), m_vangle (vangle), 0061 m_backgroundColor (environ->backgroundColor (actOnSelection)), 0062 m_oldSelectionPtr (nullptr) 0063 { 0064 } 0065 0066 kpTransformSkewCommand::~kpTransformSkewCommand () 0067 { 0068 delete m_oldSelectionPtr; 0069 } 0070 0071 0072 // public virtual [base kpCommand] 0073 QString kpTransformSkewCommand::name () const 0074 { 0075 QString opName = i18n ("Skew"); 0076 0077 return (m_actOnSelection) ? i18n ("Selection: %1", opName) : opName; 0078 } 0079 0080 0081 // public virtual [base kpCommand] 0082 kpCommandSize::SizeType kpTransformSkewCommand::size () const 0083 { 0084 return ImageSize (m_oldImage) + 0085 SelectionSize (m_oldSelectionPtr); 0086 } 0087 0088 0089 // public virtual [base kpCommand] 0090 void kpTransformSkewCommand::execute () 0091 { 0092 kpDocument *doc = document (); 0093 Q_ASSERT (doc); 0094 0095 0096 QApplication::setOverrideCursor (Qt::WaitCursor); 0097 0098 0099 kpImage newImage = kpPixmapFX::skew (doc->image (m_actOnSelection), 0100 kpTransformSkewDialog::horizontalAngleForPixmapFX (m_hangle), 0101 kpTransformSkewDialog::verticalAngleForPixmapFX (m_vangle), 0102 m_backgroundColor); 0103 0104 if (!m_actOnSelection) 0105 { 0106 m_oldImage = doc->image (m_actOnSelection); 0107 0108 doc->setImage (newImage); 0109 } 0110 else 0111 { 0112 kpAbstractImageSelection *sel = doc->imageSelection (); 0113 Q_ASSERT (sel); 0114 0115 // Save old selection 0116 m_oldSelectionPtr = sel->clone (); 0117 0118 0119 // Calculate skewed points 0120 QPolygon currentPoints = sel->calculatePoints (); 0121 currentPoints.translate (-currentPoints.boundingRect ().x (), 0122 -currentPoints.boundingRect ().y ()); 0123 QTransform skewMatrix = kpPixmapFX::skewMatrix ( 0124 doc->image (m_actOnSelection), 0125 kpTransformSkewDialog::horizontalAngleForPixmapFX (m_hangle), 0126 kpTransformSkewDialog::verticalAngleForPixmapFX (m_vangle)); 0127 currentPoints = skewMatrix.map (currentPoints); 0128 currentPoints.translate (-currentPoints.boundingRect ().x () + m_oldSelectionPtr->x (), 0129 -currentPoints.boundingRect ().y () + m_oldSelectionPtr->y ()); 0130 0131 0132 if (currentPoints.boundingRect ().width () == newImage.width () && 0133 currentPoints.boundingRect ().height () == newImage.height ()) 0134 { 0135 doc->setSelection ( 0136 kpFreeFormImageSelection ( 0137 currentPoints, newImage, 0138 m_oldSelectionPtr->transparency ())); 0139 } 0140 else 0141 { 0142 // TODO: fix the latter "victim of" problem in kpAbstractImageSelection by 0143 // allowing the border width & height != pixmap width & height 0144 // Or maybe autocrop? 0145 #if DEBUG_KP_TOOL_SKEW 0146 qCDebug(kpLogCommands) << "kpTransformSkewCommand::execute() currentPoints.boundingRect=" 0147 << currentPoints.boundingRect () 0148 << " newPixmap: w=" << newImage.width () 0149 << " h=" << newImage.height () 0150 << " (victim of rounding error and/or skewed-a-(rectangular)-pixmap-that-was-transparent-in-the-corners-making-sel-uselessly-bigger-than-needs-be))"; 0151 #endif 0152 doc->setSelection ( 0153 kpRectangularImageSelection ( 0154 QRect (currentPoints.boundingRect ().x (), 0155 currentPoints.boundingRect ().y (), 0156 newImage.width (), 0157 newImage.height ()), 0158 newImage, 0159 m_oldSelectionPtr->transparency ())); 0160 } 0161 0162 environ ()->somethingBelowTheCursorChanged (); 0163 } 0164 0165 0166 QApplication::restoreOverrideCursor (); 0167 } 0168 0169 // public virtual [base kpCommand] 0170 void kpTransformSkewCommand::unexecute () 0171 { 0172 kpDocument *doc = document (); 0173 Q_ASSERT (doc); 0174 0175 0176 QApplication::setOverrideCursor (Qt::WaitCursor); 0177 0178 0179 if (!m_actOnSelection) 0180 { 0181 doc->setImage (m_oldImage); 0182 m_oldImage = kpImage (); 0183 } 0184 else 0185 { 0186 doc->setSelection (*m_oldSelectionPtr); 0187 delete m_oldSelectionPtr; m_oldSelectionPtr = nullptr; 0188 0189 environ ()->somethingBelowTheCursorChanged (); 0190 } 0191 0192 0193 QApplication::restoreOverrideCursor (); 0194 } 0195