krita

kis_transform_worker.cc

00001 /*
00002  *  Copyright (c) 2004 Michael Thaler <michael.thaler@physik.tu-muenchen.de> filters
00003  *  Copyright (c) 2005 Casper Boemann <cbr@boemann.dk>
00004  *  Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org> right angle rotators
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  */
00020 #include <kdebug.h>
00021 #include <klocale.h>
00022 
00023 #include "kis_debug_areas.h"
00024 #include "kis_paint_device.h"
00025 #include "kis_selection.h"
00026 #include "kis_transform_worker.h"
00027 #include "kis_progress_display_interface.h"
00028 #include "kis_iterators_pixel.h"
00029 #include "kis_filter_strategy.h"
00030 #include "kis_layer.h"
00031 #include "kis_painter.h"
00032 
00033 KisTransformWorker::KisTransformWorker(KisPaintDeviceSP dev, double xscale, double yscale,
00034                     double xshear, double yshear, double rotation,
00035                     Q_INT32 xtranslate, Q_INT32 ytranslate,
00036                     KisProgressDisplayInterface *progress, KisFilterStrategy *filter)
00037 {
00038     m_dev= dev;
00039     m_xscale = xscale;
00040     m_yscale = yscale;
00041     m_xshear = xshear;
00042     m_yshear = yshear;
00043     m_rotation = rotation,
00044     m_xtranslate = xtranslate;
00045     m_ytranslate = ytranslate;
00046     m_progress = progress;
00047     m_filter = filter;
00048 }
00049 
00050 void KisTransformWorker::rotateNone(KisPaintDeviceSP src, KisPaintDeviceSP dst)
00051 {
00052     KisSelectionSP dstSelection;
00053     Q_INT32 pixelSize = src->pixelSize();
00054     QRect r;
00055     KisColorSpace *cs = src->colorSpace();
00056 
00057     if(src->hasSelection())
00058     {
00059         r = src->selection()->selectedExactRect();
00060         dstSelection = dst->selection();
00061     }
00062     else
00063     {
00064         r = src->exactBounds();
00065         dstSelection = new KisSelection(dst); // essentially a dummy to be deleted
00066     }
00067 
00068     KisHLineIteratorPixel hit = src->createHLineIterator(r.x(), r.top(), r.width(), true);
00069     KisHLineIterator vit = dst->createHLineIterator(r.x(), r.top(), r.width(), true);
00070     KisHLineIterator dstSelIt = dstSelection->createHLineIterator(r.x(), r.top(), r.width(), true);
00071     for (Q_INT32 i = 0; i < r.height(); ++i) {
00072             while (!hit.isDone()) {
00073             if (hit.isSelected())  {
00074                 memcpy(vit.rawData(), hit.rawData(), pixelSize);
00075 
00076                 // XXX: Should set alpha = alpha*(1-selectedness)
00077                 cs->setAlpha(hit.rawData(), 0, 1);
00078             }
00079             *(dstSelIt.rawData()) = hit.selectedness();
00080             ++hit;
00081             ++vit;
00082             ++dstSelIt;
00083         }
00084         hit.nextRow();
00085         vit.nextRow();
00086         dstSelIt.nextRow();
00087 
00088         //progress info
00089         m_progressStep += r.width();
00090         if(m_lastProgressReport != (m_progressStep * 100) / m_progressTotalSteps)
00091         {
00092             m_lastProgressReport = (m_progressStep * 100) / m_progressTotalSteps;
00093             emit notifyProgress(m_lastProgressReport);
00094         }
00095         if (m_cancelRequested) {
00096             break;
00097         }
00098     }
00099 }
00100 
00101 void KisTransformWorker::rotateRight90(KisPaintDeviceSP src, KisPaintDeviceSP dst)
00102 {
00103     KisSelectionSP dstSelection;
00104     Q_INT32 pixelSize = src->pixelSize();
00105     QRect r;
00106     KisColorSpace *cs = src->colorSpace();
00107 
00108     if(src->hasSelection())
00109     {
00110         r = src->selection()->selectedExactRect();
00111         dstSelection = dst->selection();
00112     }
00113     else
00114     {
00115         r = src->exactBounds();
00116         dstSelection = new KisSelection(dst); // essentially a dummy to be deleted
00117     }
00118 
00119     for (Q_INT32 y = r.bottom(); y >= r.top(); --y) {
00120         KisHLineIteratorPixel hit = src->createHLineIterator(r.x(), y, r.width(), true);
00121         KisVLineIterator vit = dst->createVLineIterator(-y, r.x(), r.width(), true);
00122         KisVLineIterator dstSelIt = dstSelection->createVLineIterator(-y, r.x(), r.width(), true);
00123 
00124             while (!hit.isDone()) {
00125             if (hit.isSelected())  {
00126                 memcpy(vit.rawData(), hit.rawData(), pixelSize);
00127 
00128                 // XXX: Should set alpha = alpha*(1-selectedness)
00129                 cs->setAlpha(hit.rawData(), 0, 1);
00130             }
00131             *(dstSelIt.rawData()) = hit.selectedness();
00132             ++hit;
00133             ++vit;
00134             ++dstSelIt;
00135         }
00136 
00137         //progress info
00138         m_progressStep += r.width();
00139         if(m_lastProgressReport != (m_progressStep * 100) / m_progressTotalSteps)
00140         {
00141             m_lastProgressReport = (m_progressStep * 100) / m_progressTotalSteps;
00142             emit notifyProgress(m_lastProgressReport);
00143         }
00144         if (m_cancelRequested) {
00145             break;
00146         }
00147     }
00148 }
00149 
00150 void KisTransformWorker::rotateLeft90(KisPaintDeviceSP src, KisPaintDeviceSP dst)
00151 {
00152     kdDebug() << "rotateLeft90 called\n";
00153     KisSelectionSP dstSelection;
00154     Q_INT32 pixelSize = src->pixelSize();
00155     QRect r;
00156     KisColorSpace *cs = src->colorSpace();
00157 
00158     if(src->hasSelection())
00159     {
00160         r = src->selection()->selectedExactRect();
00161         dstSelection = dst->selection();
00162     }
00163     else
00164     {
00165         r = src->exactBounds();
00166         dstSelection = new KisSelection(dst); // essentially a dummy to be deleted
00167     }
00168     Q_INT32 x = 0;
00169 
00170     for (Q_INT32 y = r.top(); y <= r.bottom(); ++y) {
00171         // Read the horizontal line from back to front, write onto the vertical column
00172         KisHLineIteratorPixel hit = src->createHLineIterator(r.x(), y, r.width(), true);
00173         KisVLineIterator vit = dst->createVLineIterator(y, -r.x() - r.width(), r.width(), true);
00174         KisVLineIterator dstSelIt = dstSelection->createVLineIterator(y, -r.x() - r.width(), r.width(), true);
00175 
00176         hit += r.width() - 1;
00177         while (!vit.isDone()) {
00178             if (hit.isSelected()) {
00179                 memcpy(vit.rawData(), hit.rawData(), pixelSize);
00180 
00181                 // XXX: Should set alpha = alpha*(1-selectedness)
00182                 cs->setAlpha(hit.rawData(), 0, 1);
00183             }
00184             *(dstSelIt.rawData()) = hit.selectedness();
00185             --hit;
00186             ++vit;
00187             ++dstSelIt;
00188         }
00189         ++x;
00190 
00191         //progress info
00192         m_progressStep += r.width();
00193         if(m_lastProgressReport != (m_progressStep * 100) / m_progressTotalSteps)
00194         {
00195             m_lastProgressReport = (m_progressStep * 100) / m_progressTotalSteps;
00196             emit notifyProgress(m_lastProgressReport);
00197         }
00198         if (m_cancelRequested) {
00199             break;
00200         }
00201     }
00202 }
00203 
00204 void KisTransformWorker::rotate180(KisPaintDeviceSP src, KisPaintDeviceSP dst)
00205 {
00206     kdDebug() << "Rotating 180\n";
00207     KisSelectionSP dstSelection;
00208     Q_INT32 pixelSize = src->pixelSize();
00209     QRect r;
00210     KisColorSpace *cs = src->colorSpace();
00211 
00212     if(src->hasSelection())
00213     {
00214         r = src->selection()->selectedExactRect();
00215         dstSelection = dst->selection();
00216     }
00217     else
00218     {
00219         r = src->exactBounds();
00220         dstSelection = new KisSelection(dst); // essentially a dummy to be deleted
00221     }
00222 
00223     for (Q_INT32 y = r.top(); y <= r.bottom(); ++y) {
00224         KisHLineIteratorPixel srcIt = src->createHLineIterator(r.x(), y, r.width(), true);
00225         KisHLineIterator dstIt = dst->createHLineIterator(-r.x() - r.width(), -y, r.width(), true);
00226         KisHLineIterator dstSelIt = dstSelection->createHLineIterator(-r.x() - r.width(), -y, r.width(), true);
00227 
00228         srcIt += r.width() - 1;
00229         while (!dstIt.isDone()) {
00230             if (srcIt.isSelected())  {
00231                 memcpy(dstIt.rawData(), srcIt.rawData(), pixelSize);
00232 
00233                 // XXX: Should set alpha = alpha*(1-selectedness)
00234                 cs->setAlpha(srcIt.rawData(), 0, 1);
00235             }
00236             *(dstSelIt.rawData()) = srcIt.selectedness();
00237             --srcIt;
00238             ++dstIt;
00239             ++dstSelIt;
00240         }
00241 
00242         //progress info
00243         m_progressStep += r.width();
00244         if(m_lastProgressReport != (m_progressStep * 100) / m_progressTotalSteps)
00245         {
00246             m_lastProgressReport = (m_progressStep * 100) / m_progressTotalSteps;
00247             emit notifyProgress(m_lastProgressReport);
00248         }
00249         if (m_cancelRequested) {
00250             break;
00251         }
00252     }
00253 }
00254 
00255 template <class iter> iter createIterator(KisPaintDevice *dev, Q_INT32 start, Q_INT32 lineNum, Q_INT32 len);
00256 
00257 template <> KisHLineIteratorPixel createIterator <KisHLineIteratorPixel>
00258 (KisPaintDevice *dev, Q_INT32 start, Q_INT32 lineNum, Q_INT32 len)
00259 {
00260     return dev->createHLineIterator(start, lineNum, len, true);
00261 }
00262 
00263 template <> KisVLineIteratorPixel createIterator <KisVLineIteratorPixel>
00264 (KisPaintDevice *dev, Q_INT32 start, Q_INT32 lineNum, Q_INT32 len)
00265 {
00266     return dev->createVLineIterator(lineNum, start, len, true);
00267 }
00268 
00269 template <class iter> void calcDimensions (KisPaintDevice *dev, Q_INT32 &srcStart, Q_INT32 &srcLen, Q_INT32 &firstLine, Q_INT32 &numLines, Q_INT32 &srcStartData, Q_INT32 &srcLenData);
00270 
00271 template <> void calcDimensions <KisHLineIteratorPixel>
00272         (KisPaintDevice *dev, Q_INT32 &srcStart, Q_INT32 &srcLen, Q_INT32 &firstLine, Q_INT32 &numLines, Q_INT32 &srcStartData, Q_INT32 &srcLenData)
00273 {
00274     dev->exactBounds(srcStartData, firstLine, srcLenData, numLines);
00275     if(dev->hasSelection())
00276     {
00277         QRect r = dev->selection()->selectedExactRect();
00278         r.rect(&srcStart, &firstLine, &srcLen, &numLines);
00279     }
00280     else
00281     {
00282         srcStart = srcStartData;
00283         srcLen = srcLenData;
00284     }
00285 }
00286 
00287 template <> void calcDimensions <KisVLineIteratorPixel>
00288         (KisPaintDevice *dev, Q_INT32 &srcStart, Q_INT32 &srcLen, Q_INT32 &firstLine, Q_INT32 &numLines, Q_INT32 &srcStartData, Q_INT32 &srcLenData)
00289 {
00290     dev->exactBounds(firstLine, srcStartData, numLines, srcLenData);
00291     if(dev->hasSelection())
00292     {
00293         QRect r = dev->selection()->selectedExactRect();
00294         r.rect(&firstLine, &srcStart, &numLines, &srcLen);
00295     }
00296     else
00297     {
00298         srcStart = srcStartData;
00299         srcLen = srcLenData;
00300     }
00301 }
00302 
00303 struct FilterValues
00304 {
00305     Q_UINT8 numWeights;
00306     Q_UINT8 *weight;
00307     ~FilterValues() {delete [] weight;}
00308 };
00309 
00310 template <class T> void KisTransformWorker::transformPass(KisPaintDevice *src, KisPaintDevice *dst, double floatscale, double shear, Q_INT32 dx, KisFilterStrategy *filterStrategy)
00311 {
00312     Q_INT32 lineNum,srcStart,firstLine,srcLen,numLines,srcStartData,srcLenData;
00313     Q_INT32 center, begin, end;    /* filter calculation variables */
00314     Q_UINT8 *data;
00315     Q_UINT8 pixelSize = src->pixelSize();
00316     KisSelectionSP dstSelection;
00317     KisColorSpace * cs = src->colorSpace();
00318     Q_INT32 scale;
00319     Q_INT32 scaleDenom;
00320     Q_INT32 shearFracOffset;
00321 
00322     if(src->hasSelection())
00323         dstSelection = dst->selection();
00324     else
00325         dstSelection = new KisSelection(dst); // essentially a dummy to be deleted
00326 
00327     calcDimensions <T>(src, srcStart, srcLen, firstLine, numLines,srcStartData,srcLenData);
00328 
00329     scale = int(floatscale*srcLen);
00330     scaleDenom = srcLen;
00331 
00332     if(scaleDenom == 0)
00333         return;
00334 
00335     Q_INT32 support = filterStrategy->intSupport();
00336     Q_INT32 dstLen, dstStart;
00337     Q_INT32 invfscale = 256;
00338 
00339     // handle magnification/minification
00340     if(abs(scale) < scaleDenom)
00341     {
00342         support *= scaleDenom;
00343         support /= scale;
00344 
00345         invfscale *= scale;
00346         invfscale /= scaleDenom;
00347         if(scale < 0) // handle mirroring
00348         {
00349             support = -support;
00350             invfscale = -invfscale;
00351         }
00352     }
00353 
00354     // handle mirroring
00355     if(scale < 0)
00356         dstLen = - scale;
00357     else
00358         dstLen = scale;
00359 
00360     // Calculate extra length (in each side) needed due to shear
00361     Q_INT32 extraLen = (support+256)>>8 + 1;
00362 
00363     Q_UINT8 *tmpLine = new Q_UINT8[(srcLen +2*extraLen)* pixelSize];
00364     Q_CHECK_PTR(tmpLine);
00365 
00366     Q_UINT8 *tmpSel = new Q_UINT8[srcLen+2*extraLen];
00367     Q_CHECK_PTR(tmpSel);
00368 
00369     //allocate space for colors
00370     const Q_UINT8 **colors = new const Q_UINT8 *[2*support+1];
00371 
00372     // Precalculate weights
00373     FilterValues *filterWeights = new FilterValues[256];
00374 
00375     for(int center = 0; center<256; ++center)
00376     {
00377         Q_INT32 begin = (255 + center - support)>>8; // takes ceiling by adding 255
00378         Q_INT32 span = ((center + support)>>8) - begin + 1; // takes floor to get end. Subtracts begin to get span
00379         Q_INT32 t = (((begin<<8) - center) * invfscale)>>8;
00380         Q_INT32 dt = invfscale;
00381         filterWeights[center].weight = new Q_UINT8[span];
00382 //printf("%d (",center);
00383         Q_UINT32 sum=0;
00384         for(int num = 0; num<span; ++num)
00385         {
00386             Q_UINT32 tmpw = filterStrategy->intValueAt(t) * invfscale;
00387 
00388             tmpw >>=8;
00389             filterWeights[center].weight[num] = tmpw;
00390 //printf(" %d=%d,%d",t,filterWeights[center].weight[num],tmpw);
00391             t += dt;
00392             sum+=tmpw;
00393         }
00394 //printf(" )%d sum =%d",span,sum);
00395         if(sum!=255)
00396         {
00397             double fixfactor= 255.0/sum;
00398             sum=0;
00399             for(int num = 0; num<span; ++num)
00400             {
00401                 filterWeights[center].weight[num] = int(filterWeights[center].weight[num] * fixfactor);
00402                 sum+=filterWeights[center].weight[num];
00403             }
00404         }
00405 
00406 //printf("  sum2 =%d",sum);
00407         int num = 0; 
00408         while(sum<255 && num*2<span)
00409         {
00410             filterWeights[center].weight[span/2 + num]++;
00411             ++sum;
00412             if(sum<255 && num<span/2)
00413             {
00414                 filterWeights[center].weight[span/2 - num - 1]++;
00415                 ++sum;
00416             }
00417             ++num;
00418         }
00419 //printf("  sum3 =%d\n",sum);
00420 
00421         filterWeights[center].numWeights = span;
00422     }
00423 
00424     for(lineNum = firstLine; lineNum < firstLine+numLines; lineNum++)
00425     {
00426         if(scale < 0)
00427             dstStart = srcStart * scale / scaleDenom - dstLen + dx;
00428         else
00429             dstStart = (srcStart) * scale / scaleDenom + dx;
00430 
00431         shearFracOffset = -int( 256 * (lineNum * shear - floor(lineNum * shear)));
00432         dstStart += int(floor(lineNum * shear));
00433 
00434         // Build a temporary line
00435         T srcIt = createIterator <T>(src, QMAX(srcStart - extraLen, srcStartData), lineNum, srcLen+2*extraLen);
00436         Q_INT32 i = 0;
00437         Q_INT32 x = srcStart - extraLen;
00438         while(i < srcLen + 2*extraLen)
00439         {
00440             Q_UINT8 *data;
00441 
00442             data = srcIt.rawData();
00443             memcpy(&tmpLine[i*pixelSize], data, pixelSize);
00444             if(srcIt.isSelected())
00445             {
00446                 tmpSel[i] = 255;
00447             }
00448             else
00449             {
00450                 tmpSel[i] = 0;
00451             }
00452             if(x >= srcStartData && x < srcStartData + srcLenData - 1)
00453             {
00454                 // XXX: Should set alpha = alpha*(1-selectedness)
00455                 cs->setAlpha(data, 0, 1);
00456                 ++srcIt;
00457             }
00458             i++;
00459             x++;
00460         }
00461 
00462         T dstIt = createIterator <T>(dst, dstStart, lineNum, dstLen);
00463         T dstSelIt = createIterator <T>(dstSelection, dstStart, lineNum, dstLen);
00464 
00465         i=0;
00466         while(!dstIt.isDone())
00467         {
00468             if(scaleDenom<2500)
00469                 center = ((i<<8) * scaleDenom) / scale;
00470             else
00471             {
00472                 if(scaleDenom<46000) // real limit is actually 46340 pixels
00473                     center = ((i * scaleDenom) / scale)<<8;
00474                 else
00475                     center = ((i<<8)/scale * scaleDenom) / scale; // XXX fails for sizes over 2^23 pixels src width
00476             }
00477 
00478             if(scale < 0)
00479                 center += srcLen<<8;
00480 
00481             center += 128*scaleDenom/scale;//xxx doesn't work for scale<0;
00482             center += (extraLen<<8) + shearFracOffset;
00483 
00484             // find contributing pixels
00485             begin = (255 + center - support)>>8; // takes ceiling by adding 255
00486             end = (center + support)>>8; // takes floor
00487 
00489             Q_UINT8 selectedness = tmpSel[center>>8];
00490             if(selectedness)
00491             {
00492                 int num=0;
00493                 for(int srcpos = begin; srcpos <= end; ++srcpos)
00494                 {
00495                     colors[num] = &tmpLine[srcpos*pixelSize];
00496                     num++;
00497                 }
00498                 data = dstIt.rawData();
00499                 cs->mixColors(colors, filterWeights[center&255].weight, filterWeights[center&255].numWeights, data);
00500                 data = dstSelIt.rawData();
00501                 *data = selectedness;
00502             }
00503 
00504             ++dstSelIt;
00505             ++dstIt;
00506             i++;
00507         }
00508 
00509         //progress info
00510         m_progressStep += dstLen;
00511         if(m_lastProgressReport != (m_progressStep * 100) / m_progressTotalSteps)
00512         {
00513             m_lastProgressReport = (m_progressStep * 100) / m_progressTotalSteps;
00514             emit notifyProgress(m_lastProgressReport);
00515         }
00516         if (m_cancelRequested) {
00517             break;
00518         }
00519     }
00520     delete [] colors;
00521     delete [] tmpLine;
00522     delete [] tmpSel;
00523     delete [] filterWeights;
00524 }
00525 
00526 bool KisTransformWorker::run()
00527 {
00528     //progress info
00529     m_cancelRequested = false;
00530     if(m_progress)
00531         m_progress->setSubject(this, true, true);
00532     m_progressTotalSteps = 0;
00533     m_progressStep = 0;
00534     QRect r;
00535     if(m_dev->hasSelection())
00536         r = m_dev->selection()->selectedExactRect();
00537     else
00538         r = m_dev->exactBounds();
00539 
00540     KisPaintDeviceSP tmpdev1 = new KisPaintDevice(m_dev->colorSpace(),"transform_tmpdev1");;
00541     KisPaintDeviceSP tmpdev2 = new KisPaintDevice(m_dev->colorSpace(),"transform_tmpdev2");;
00542     KisPaintDeviceSP tmpdev3 = new KisPaintDevice(m_dev->colorSpace(),"transform_tmpdev2");;
00543     KisPaintDeviceSP srcdev = m_dev;
00544 
00545     double xscale = m_xscale;
00546     double yscale = m_yscale;
00547     double xshear = m_xshear;
00548     double yshear = m_yshear;
00549     double rotation = m_rotation;
00550     Q_INT32 xtranslate = m_xtranslate;
00551     Q_INT32 ytranslate = m_ytranslate;
00552 
00553     if(rotation < 0.0)
00554         rotation = -fmod(-rotation, 2*M_PI) + 2*M_PI;
00555     else
00556         rotation = fmod(rotation, 2*M_PI);
00557     int rotQuadrant = int(rotation /(M_PI/2) + 0.5) & 3;
00558 
00559     // Figure out how we will do the initial right angle rotations
00560     double tmp;
00561     switch(rotQuadrant)
00562     {
00563         default: // just to shut up the compiler
00564         case 0:
00565             m_progressTotalSteps = 0;
00566             break;
00567         case 1:
00568             rotation -= M_PI/2;
00569             tmp = xscale;
00570             xscale=yscale;
00571             yscale=tmp;
00572             m_progressTotalSteps = r.width() * r.height();
00573             break;
00574         case 2:
00575             rotation -= M_PI;
00576             m_progressTotalSteps = r.width() * r.height();
00577             break;
00578         case 3:
00579             rotation -= -M_PI/2 + 2*M_PI;
00580             tmp = xscale;
00581             xscale = yscale;
00582             yscale = tmp;
00583             m_progressTotalSteps = r.width() * r.height();
00584             break;
00585     }
00586 
00587     // Calculate some auxillary values
00588     yshear = sin(rotation);
00589     xshear = -tan(rotation/2);
00590     xtranslate -= int(xshear*ytranslate);
00591 
00592     // Calculate progress steps
00593     m_progressTotalSteps += int(yscale * r.width() * r.height());
00594     m_progressTotalSteps += int(xscale * r.width() * (r.height() * yscale + r.width()*yshear));
00595 
00596     m_lastProgressReport=0;
00597 
00598     // Now that we have everything in place it's time to do the actual right angle rotations
00599     switch(rotQuadrant)
00600     {
00601         default: // just to shut up the compiler
00602         case 0:
00603             break;
00604         case 1:
00605             rotateRight90(srcdev, tmpdev1);
00606             srcdev = tmpdev1;
00607             break;
00608         case 2:
00609             rotate180(srcdev, tmpdev1);
00610             srcdev = tmpdev1;
00611             break;
00612         case 3:
00613             rotateLeft90(srcdev, tmpdev1);
00614             srcdev = tmpdev1;
00615             break;
00616     }
00617 
00618     // Handle simple move case possibly with rotation of 90,180,270
00619     if(rotation == 0.0 && xscale == 1.0 && yscale == 1.0)
00620     {
00621         if(rotQuadrant==0)
00622         {
00623             // Though not nessesay in the general case because we make several passes
00624             // We need to move (not just copy) the data to a temp dev so we can move them back
00625             rotateNone(srcdev, tmpdev1);
00626             srcdev = tmpdev1;
00627         }
00628         if(m_dev->hasSelection())
00629             m_dev->selection()->clear();
00630 
00631         srcdev->move(srcdev->getX() + xtranslate, srcdev->getY() + ytranslate);
00632         rotateNone(srcdev, m_dev);
00633 
00634         //progress info
00635         emit notifyProgressDone();
00636         m_dev->emitSelectionChanged();
00637 
00638         return m_cancelRequested;
00639     }
00640 
00641     if ( m_cancelRequested) {
00642         emit notifyProgressDone();
00643         return false;
00644     }
00645 
00646     transformPass <KisHLineIteratorPixel>(srcdev, tmpdev2, xscale, yscale*xshear, 0, m_filter);
00647     if(m_dev->hasSelection())
00648         m_dev->selection()->clear();
00649 
00650     if ( m_cancelRequested) {
00651         emit notifyProgressDone();
00652         return false;
00653     }
00654 
00655     // Now do the second pass
00656     transformPass <KisVLineIteratorPixel>(tmpdev2.data(), tmpdev3.data(), yscale, yshear, ytranslate, m_filter);
00657 
00658     if(m_dev->hasSelection())
00659         m_dev->selection()->clear();
00660 
00661     if ( m_cancelRequested) {
00662         emit notifyProgressDone();
00663         return false;
00664     }
00665 
00666     if (xshear != 0.0)
00667         transformPass <KisHLineIteratorPixel>(tmpdev3, m_dev, 1.0, xshear, xtranslate, m_filter);
00668     else
00669     {
00670         // No need to filter again when we are only scaling
00671         tmpdev3->move(tmpdev3->getX() + xtranslate, tmpdev3->getY());
00672         rotateNone(tmpdev3, m_dev);
00673     }
00674 
00675     if (m_dev->parentLayer()) {
00676         m_dev->parentLayer()->setDirty();
00677     }
00678     //progress info
00679     emit notifyProgressDone();
00680     m_dev->emitSelectionChanged();
00681 
00682     return m_cancelRequested;
00683 }
KDE Home | KDE Accessibility Home | Description of Access Keys