krita

kis_scale_visitor.h

00001 /*
00002  *  copyright (c) 2004, 2005 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
00003  *
00004  *  this program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the gnu general public license as published by
00006  *  the free software foundation; either version 2 of the license, or
00007  *  (at your option) any later version.
00008  *
00009  *  this program is distributed in the hope that it will be useful,
00010  *  but without any warranty; without even the implied warranty of
00011  *  merchantability or fitness for a particular purpose.  see the
00012  *  gnu general public license for more details.
00013  *
00014  *  you should have received a copy of the gnu general public license
00015  *  along with this program; if not, write to the free software
00016  *  foundation, inc., 675 mass ave, cambridge, ma 02139, usa.
00017  */
00018 
00019 #ifndef KIS_SCALE_VISITOR_H_
00020 #define KIS_SCALE_VISITOR_H_
00021 
00022 #include "klocale.h"
00023 
00024 #include "kis_progress_subject.h"
00025 #include "kis_progress_display_interface.h"
00026 #include "kis_thread.h"
00027 #include "kis_layer_visitor.h"
00028 #include "kis_types.h"
00029 #include "kis_layer.h"
00030 #include "kis_group_layer.h"
00031 #include "kis_paint_layer.h"
00032 #include "kis_adjustment_layer.h"
00033 #include "kis_transaction.h"
00034 #include "kis_undo_adapter.h"
00035 #include "kis_selection.h"
00036 
00037 class KisProgressDisplayInterface;
00038 class KisFilterStrategy;
00039 
00040 class KisScaleWorker : public KisThread {
00041 
00042     /* Structs for the image rescaling routine */
00043     class Contrib {
00044     public:
00045         Q_INT32 m_pixel;
00046         double m_weight;
00047     };
00048 
00049     class ContribList {
00050     public:
00051         Q_INT32  n;  //number of contributors
00052         Contrib *p; //pointer to list of contributions
00053     };
00054 
00055 public:
00056 
00057     KisScaleWorker(KisPaintDevice * dev, double sx, double sy,
00058                    KisFilterStrategy *filterStrategy)
00059         : KisThread()
00060         , m_dev(dev)
00061         , m_sx(sx)
00062         , m_sy(sy)
00063         , m_filterStrategy(filterStrategy) {};
00064 
00065     virtual ~KisScaleWorker() {};
00066 
00067     void run();
00068 
00069 private:
00070     Q_INT32 m_pixelSize;
00071     KisPaintDevice * m_dev;
00072     double m_sx, m_sy;
00073     KisFilterStrategy * m_filterStrategy;
00074 
00075 
00084     int calcContrib(ContribList *contribX, double cale, double fwidth, int srcwidth, KisFilterStrategy *filterStrategy, Q_INT32 i);
00085 
00086     ContribList * contrib;  //array of contribution lists
00087 
00088 
00089 };
00090 
00091 
00092 class KisScaleVisitor : public KisLayerVisitor, KisProgressSubject {
00093 
00094 public:
00095 
00096     KisScaleVisitor(KisImageSP img,
00097                     double sx, 
00098                     double sy, 
00099                     KisProgressDisplayInterface *progress, 
00100                     KisFilterStrategy *filterStrategy) 
00101         : KisLayerVisitor()
00102         , m_img(img)
00103         , m_sx(sx)
00104         , m_sy(sy)
00105         , m_progress(progress)
00106         , m_filterStrategy(filterStrategy)
00107     {
00108         if ( progress )
00109             progress -> setSubject(this, true, true);
00110         emit notifyProgressStage(i18n("Scaling..."),0);
00111     }
00112 
00113     virtual ~KisScaleVisitor()
00114     {
00115         // Wait for all threads to finish
00116         KisThread * t;
00117         int threadcount = m_scalethreads.count();
00118         int i = 0;
00119         for ( t = m_scalethreads.first(); t; t = m_scalethreads.next()) {
00120             //progress info
00121             if (t) t->wait();
00122             emit notifyProgress((100 / threadcount) * i);
00123             ++i;
00124 
00125         }
00126         emit notifyProgressDone();
00127         // Delete all threads
00128         m_scalethreads.setAutoDelete(true);
00129         m_scalethreads.clear();
00130     }
00131 
00132     bool visit(KisPaintLayer *layer) 
00133     {
00134         // XXX: If all is well, then the image's undoadapter will have started a macro for us
00135         //      This will break in a more multi-threaded environment
00136         if (m_img->undoAdapter() && m_img->undoAdapter()->undo()) {
00137             KisTransaction * cmd = new KisTransaction("", layer->paintDevice());
00138             m_img->undoAdapter()->addCommand(cmd);
00139         }
00140 
00141         KisScaleWorker * scaleThread = new KisScaleWorker(layer->paintDevice(),
00142                                                      m_sx, m_sy, m_filterStrategy);
00143         m_scalethreads.append(scaleThread);
00144         scaleThread->start();
00145         //scaleThread->run();
00146         layer->setDirty();
00147         return true;
00148     }
00149 
00150     bool visit(KisGroupLayer *layer)
00151     {
00152         //KisScaleVisitor visitor (m_img, m_sx, m_sy, m_progress, m_filterStrategy);
00153 
00154         // XXX: Maybe faster to scale the projection and do something clever to avoid 
00155     //      recompositing everything?
00156     layer->resetProjection(); 
00157        
00158 
00159         KisLayerSP child = layer->firstChild();
00160         while (child) {
00161             child->accept(*this);
00162             child = child->nextSibling();
00163         }
00164 
00165         return true;
00166     }
00167 
00168     bool visit(KisPartLayer */*layer*/)
00169     {
00170         return true;
00171     }
00172 
00173     virtual bool visit(KisAdjustmentLayer* layer)
00174     {
00175         KisThread * scaleThread = new KisScaleWorker(layer->selection().data(), m_sx, m_sy, m_filterStrategy);
00176         m_scalethreads.append(scaleThread);
00177         scaleThread->start();
00178         layer->resetCache();
00179         layer->setDirty();
00180         return true;
00181     }
00182     
00183     
00184     // Implement KisProgressSubject
00185     virtual void cancel() 
00186     {
00187         KisThread * t;
00188         for ( t = m_scalethreads.first(); t; t = m_scalethreads.next()) {
00189             t->cancel();
00190         }      
00191     }
00192     
00193 
00194 private:
00195 
00196     QPtrList<KisThread> m_scalethreads;
00197     KisImageSP m_img;
00198     double m_sx;
00199     double m_sy;
00200     KisProgressDisplayInterface * m_progress;
00201     KisFilterStrategy * m_filterStrategy;
00202 };
00203 
00204 #endif // KIS_SCALE_VISITOR_H_
KDE Home | KDE Accessibility Home | Description of Access Keys