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