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