Merged changes in the trunk up to revision 28685.
[blender.git] / source / blender / freestyle / intern / stroke / Canvas.cpp
1
2 //
3 //  Copyright (C) : Please refer to the COPYRIGHT file distributed 
4 //   with this source distribution. 
5 //
6 //  This program is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU General Public License
8 //  as published by the Free Software Foundation; either version 2
9 //  of the License, or (at your option) any later version.
10 //
11 //  This program is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 //  GNU General Public License for more details.
15 //
16 //  You should have received a copy of the GNU General Public License
17 //  along with this program; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19 //
20 ///////////////////////////////////////////////////////////////////////////////
21
22 #include "StrokeRenderer.h"
23 #include <vector>
24 #include "../system/FreestyleConfig.h"
25 #include "../system/TimeStamp.h"
26 #include "../system/PseudoNoise.h"
27 #include "Canvas.h"
28 #include "../image/Image.h"
29 #include "../image/GaussianFilter.h"
30 #include "../image/ImagePyramid.h"
31 #include "../view_map/SteerableViewMap.h"
32 #include "StyleModule.h"
33
34 //soc #include <qimage.h>
35 //soc #include <QString>
36 #include <sstream>      
37
38 extern "C" {
39 #include "IMB_imbuf.h"
40 #include "IMB_imbuf_types.h"
41 }
42
43 using namespace std;
44
45 LIB_STROKE_EXPORT
46 Canvas * Canvas::_pInstance = 0;
47
48 LIB_STROKE_EXPORT
49 const char * Canvas::_MapsPath = 0;
50
51 using namespace std;
52
53 Canvas::Canvas()
54 {
55   _SelectedFEdge = 0;
56   _pInstance = this;
57   PseudoNoise::init(42);
58   _Renderer = 0;
59   _current_sm = NULL;
60   _steerableViewMap = new SteerableViewMap(NB_STEERABLE_VIEWMAP-1);
61   _basic = false;
62 }
63
64 Canvas::Canvas(const Canvas& iBrother)
65 {
66   _SelectedFEdge = iBrother._SelectedFEdge;
67   _pInstance = this;
68   PseudoNoise::init(42);
69   _Renderer = iBrother._Renderer;
70   _current_sm = iBrother._current_sm;
71   _steerableViewMap = new SteerableViewMap(*(iBrother._steerableViewMap));
72   _basic = iBrother._basic;
73 }
74
75 Canvas::~Canvas()
76 {
77   _pInstance = 0;
78
79   Clear();
80   if(_Renderer)
81   {
82     delete _Renderer;
83     _Renderer = 0;
84   }
85   // FIXME: think about an easy control 
86   // for the maps memory management...
87   if(!_maps.empty()){
88     for(mapsMap::iterator m=_maps.begin(), mend=_maps.end();
89     m!=mend;
90     ++m){
91       delete ((*m).second);
92     }
93     _maps.clear();
94   }
95   if(_steerableViewMap)
96     delete _steerableViewMap;
97 }
98
99 void Canvas::preDraw() {}
100
101 void Canvas::Draw()
102 {
103   if(_StyleModules.empty())
104     return;
105   preDraw();
106   TimeStamp *timestamp = TimeStamp::instance();
107
108   for(unsigned i = 0; i < _StyleModules.size(); i++) {
109     _current_sm = _StyleModules[i];
110
111     if (i < _Layers.size() && _Layers[i])
112       delete _Layers[i];
113
114     _Layers[i] = _StyleModules[i]->execute();
115         if (!_Layers[i])
116                 continue;
117
118         stroke_count += _Layers[i]->strokes_size();
119
120     timestamp->increment();
121   }
122   postDraw();
123 }
124
125 void Canvas::postDraw()
126 {
127   update();
128 }
129
130
131 void Canvas::Clear()
132 {
133   if(!_Layers.empty()) {
134     for (deque<StrokeLayer*>::iterator sl=_Layers.begin(), slend=_Layers.end();
135          sl != slend;
136          ++sl)
137       if (*sl)
138         delete (*sl);
139     _Layers.clear();  
140   }
141
142   if(!_StyleModules.empty()) {
143     for (deque<StyleModule*>::iterator s=_StyleModules.begin(), send=_StyleModules.end();
144          s != send;
145          ++s)
146       if (*s)
147         delete (*s);
148     _StyleModules.clear();
149   }
150   if(_steerableViewMap)
151     _steerableViewMap->Reset();
152
153         stroke_count = 0;
154 }
155
156 void Canvas::Erase()
157 {
158   if(!_Layers.empty())
159   {
160     for (deque<StrokeLayer*>::iterator sl=_Layers.begin(), slend=_Layers.end();
161          sl != slend;
162          ++sl)
163       if (*sl)
164         (*sl)->clear();
165   }
166   if(_steerableViewMap)
167     _steerableViewMap->Reset();
168   update();
169
170 stroke_count = 0;
171 }
172
173 void Canvas::PushBackStyleModule(StyleModule *iStyleModule) {
174   StrokeLayer* layer = new StrokeLayer();
175   _StyleModules.push_back(iStyleModule);
176   _Layers.push_back(layer);
177 }
178
179 void Canvas::InsertStyleModule(unsigned index, StyleModule *iStyleModule) {
180   unsigned size = _StyleModules.size();
181   StrokeLayer* layer = new StrokeLayer();
182   if((_StyleModules.empty()) || (index == size)) {
183     _StyleModules.push_back(iStyleModule);
184     _Layers.push_back(layer);
185     return;
186   }
187         _StyleModules.insert(_StyleModules.begin() + index, iStyleModule);
188   _Layers.insert(_Layers.begin()+index, layer);
189 }
190
191 void Canvas::RemoveStyleModule(unsigned index)
192 {
193   unsigned i=0;
194   if (!_StyleModules.empty())
195     {
196       for(deque<StyleModule*>::iterator s=_StyleModules.begin(), send=_StyleModules.end();
197           s!=send;
198           ++s)
199         {
200           if(i == index)
201             { 
202               // remove shader
203               if (*s)
204                 delete *s;
205               _StyleModules.erase(s);
206               break;
207             } 
208           ++i;
209         }
210     }
211   i=0;
212   if(!_Layers.empty())
213   {
214     for(deque<StrokeLayer*>::iterator sl=_Layers.begin(), slend=_Layers.end();
215     sl!=slend;
216     ++sl)
217     {
218       if(i == index)
219       { 
220         // remove layer
221         if (*sl)
222           delete *sl;
223         _Layers.erase(sl);
224         break;
225       } 
226       ++i;
227     }
228   }
229 }
230
231
232 void Canvas::SwapStyleModules(unsigned i1, unsigned i2)
233 {
234   StyleModule* tmp;
235   tmp = _StyleModules[i1];
236   _StyleModules[i1] = _StyleModules[i2];
237   _StyleModules[i2] = tmp;
238
239   StrokeLayer* tmp2;
240   tmp2 = _Layers[i1];
241   _Layers[i1] = _Layers[i2];
242   _Layers[i2] = tmp2;
243 }
244
245 void Canvas::ReplaceStyleModule(unsigned index, StyleModule *iStyleModule)
246 {
247   unsigned i=0;
248   for(deque<StyleModule*>::iterator s=_StyleModules.begin(), send=_StyleModules.end();
249       s != send;
250       ++s)
251     {
252       if(i == index)
253         {
254           if (*s)
255             delete *s;
256           *s = iStyleModule;
257           break;
258         }
259       ++i;
260     }
261 }
262
263 void Canvas::setVisible(unsigned index, bool iVisible) {
264   _StyleModules[index]->setDisplayed(iVisible);
265 }
266  
267 void Canvas::setModified(unsigned index, bool iMod)
268 {
269   _StyleModules[index]->setModified(iMod);
270 }
271
272 void Canvas::resetModified(bool iMod/* =false */)
273 {
274   unsigned size = _StyleModules.size();
275   for(unsigned i = 0; i < size; ++i)
276     setModified(i,iMod);
277 }
278
279 void Canvas::causalStyleModules(vector<unsigned>& vec, unsigned index) {
280   unsigned size = _StyleModules.size();
281
282   for(unsigned i = index; i < size; ++i)
283     if (_StyleModules[i]->getCausal())
284       vec.push_back(i);
285 }
286
287 void Canvas::Render(const StrokeRenderer *iRenderer)
288 {
289   for (unsigned i = 0; i < _StyleModules.size(); i++) {
290     if(!_StyleModules[i]->getDisplayed() || !_Layers[i])
291       continue;
292     _Layers[i]->Render(iRenderer);
293   }
294 }
295
296 void Canvas::RenderBasic(const StrokeRenderer *iRenderer)
297
298 {
299   for (unsigned i = 0; i < _StyleModules.size(); i++) {
300     if(!_StyleModules[i]->getDisplayed() || !_Layers[i])
301       continue;
302     _Layers[i]->RenderBasic(iRenderer);
303   }
304 }
305
306 void Canvas::loadMap(const char *iFileName, const char *iMapName, unsigned int iNbLevels, float iSigma){
307   // check whether this map was already loaded:
308   if(!_maps.empty()){
309     mapsMap::iterator m = _maps.find(iMapName);
310     if(m!=_maps.end()){
311       // lazy check for size changes
312       ImagePyramid * pyramid = (*m).second;
313       if((pyramid->width() != width()) || (pyramid->height() != height())){
314         delete pyramid;
315       }else{
316         return;
317       }
318     }
319   }
320   string filePath;
321   if(_MapsPath){
322     filePath = _MapsPath;
323     filePath += iFileName;
324   }else{
325     filePath = iFileName;
326   }
327
328   //soc
329   // QImage *qimg;
330   // QImage newMap(filePath.c_str()); 
331   // if(newMap.isNull()){
332   //   cout << "Could not load image file " << filePath << endl;
333   //   return;
334   // }
335   // qimg = &newMap;
336         ImBuf *qimg = IMB_loadiffname(filePath.c_str(), 0);;
337         if( qimg == 0 ){
338                 cout << "Could not load image file " << filePath << endl;
339         return; 
340         }
341
342   // soc
343   //resize
344   // QImage scaledImg;
345   // if((newMap.width()!=width()) || (newMap.height()!=height())){
346   //      scaledImg = newMap.scaled(width(), height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
347   //   qimg = &scaledImg;
348   // }
349         ImBuf *scaledImg;
350   if( ( qimg->x != width() ) || ( qimg->y != height() ) ){
351         scaledImg = IMB_dupImBuf(qimg);
352         IMB_scaleImBuf(scaledImg, width(), height());
353   }
354
355
356   // deal with color image 
357   //  if(newMap->depth() != 8){
358   //    int w = newMap->width();
359   //    int h = newMap->height();
360   //    QImage *tmp = new QImage(w, h, 8);
361   //    for(unsigned y=0;y<h;++y){
362   //      for(unsigned x=0;x<w;++x){
363   //        int c = qGray(newMap->pixel(x,y));
364   //        tmp->setPixel(x,y,c);
365   //      }
366   //    }
367   //    delete newMap;
368   //    newMap = tmp;
369   //  }
370
371   int x,y;
372   int w = qimg->x;
373   int h = qimg->y;
374 int rowbytes = w*4;
375   GrayImage tmp(w,h);
376   char *pix;
377   
378   for(y=0; y<h;++y){
379     for(x=0;x<w;++x){
380                 pix = (char*)qimg->rect + y*rowbytes + x*4;
381           float c = (pix[0]*11 + pix[1]*16 + pix[2]*5)/32;
382       tmp.setPixel(x,y,c);
383     }
384   }
385
386   //  GrayImage blur(w,h);
387   //  GaussianFilter gf(4.f);
388   //  //int bound = gf.getBound();
389   //  for(y=0; y<h;++y){
390   //    for(x=0;x<w;++x){
391   //      int c = gf.getSmoothedPixel<GrayImage>(&tmp, x,y);
392   //      blur.setPixel(x,y,c);
393   //    }
394   //  }
395
396   GaussianPyramid *pyramid = new GaussianPyramid(tmp, iNbLevels, iSigma);
397   int ow = pyramid->width(0);
398   int oh = pyramid->height(0);
399   string base(iMapName); //soc
400   for(int i=0; i<pyramid->getNumberOfLevels(); ++i){
401     // save each image:
402     //    w = pyramid.width(i);
403     //    h = pyramid.height(i);
404         
405         //soc  QImage qtmp(ow, oh, QImage::Format_RGB32);
406     ImBuf *qtmp = IMB_allocImBuf(ow, oh, 32, IB_rect, 0);
407
408 //int k = (1<<i);
409     for(y=0;y<oh;++y){
410       for(x=0;x<ow;++x){
411         int c = pyramid->pixel(x,y,i);//255*pyramid->pixel(x,y,i);
412         //soc qtmp.setPixel(x,y,qRgb(c,c,c));
413                 pix = (char*)qtmp->rect + y*rowbytes + x*4;
414                 pix[0] = pix [1] = pix[2] = c;
415       }
416     }
417     //soc qtmp.save(base+QString::number(i)+".bmp", "BMP");
418         stringstream filename;
419         filename << base;
420         filename << i << ".bmp";        
421         qtmp->ftype= BMP;
422         IMB_saveiff(qtmp, const_cast<char *>(filename.str().c_str()), IB_rect);
423         
424   }
425   //  QImage *qtmp = new QImage(w, h, 32);
426   //  for(y=0;y<h;++y){
427   //    for(x=0;x<w;++x){
428   //      int c = (int)blur.pixel(x,y);
429   //      qtmp->setPixel(x,y,qRgb(c,c,c));
430   //    }
431   //  }
432   //  delete newMap;
433   //  newMap = qtmp;
434   //
435   _maps[iMapName] = pyramid;
436   //  newMap->save("toto.bmp", "BMP");
437 }
438
439 float Canvas::readMapPixel(const char *iMapName, int level, int x, int y){
440   if(_maps.empty()){
441     cout << "readMapPixel warning: no map was loaded "<< endl;
442     return -1;
443   }
444   mapsMap::iterator m = _maps.find(iMapName);
445   if(m==_maps.end()){
446     cout << "readMapPixel warning: no map was loaded with the name " << iMapName << endl;
447     return -1;
448   }
449   ImagePyramid *pyramid = (*m).second;
450   if((x<0) || (x>=pyramid->width()) || (y<0) || (y>=pyramid->height()))
451     return 0;
452   
453   return pyramid->pixel(x,height()-1-y,level);
454 }