Merged changes in the trunk up to revision 28600.
[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 #include "intern/IMB_bmp.h"
42 }
43
44 using namespace std;
45
46 LIB_STROKE_EXPORT
47 Canvas * Canvas::_pInstance = 0;
48
49 LIB_STROKE_EXPORT
50 const char * Canvas::_MapsPath = 0;
51
52 using namespace std;
53
54 Canvas::Canvas()
55 {
56   _SelectedFEdge = 0;
57   _pInstance = this;
58   PseudoNoise::init(42);
59   _Renderer = 0;
60   _current_sm = NULL;
61   _steerableViewMap = new SteerableViewMap(NB_STEERABLE_VIEWMAP-1);
62   _basic = false;
63 }
64
65 Canvas::Canvas(const Canvas& iBrother)
66 {
67   _SelectedFEdge = iBrother._SelectedFEdge;
68   _pInstance = this;
69   PseudoNoise::init(42);
70   _Renderer = iBrother._Renderer;
71   _current_sm = iBrother._current_sm;
72   _steerableViewMap = new SteerableViewMap(*(iBrother._steerableViewMap));
73   _basic = iBrother._basic;
74 }
75
76 Canvas::~Canvas()
77 {
78   _pInstance = 0;
79
80   Clear();
81   if(_Renderer)
82   {
83     delete _Renderer;
84     _Renderer = 0;
85   }
86   // FIXME: think about an easy control 
87   // for the maps memory management...
88   if(!_maps.empty()){
89     for(mapsMap::iterator m=_maps.begin(), mend=_maps.end();
90     m!=mend;
91     ++m){
92       delete ((*m).second);
93     }
94     _maps.clear();
95   }
96   if(_steerableViewMap)
97     delete _steerableViewMap;
98 }
99
100 void Canvas::preDraw() {}
101
102 void Canvas::Draw()
103 {
104   if(_StyleModules.empty())
105     return;
106   preDraw();
107   TimeStamp *timestamp = TimeStamp::instance();
108
109   for(unsigned i = 0; i < _StyleModules.size(); i++) {
110     _current_sm = _StyleModules[i];
111
112     if (i < _Layers.size() && _Layers[i])
113       delete _Layers[i];
114
115     _Layers[i] = _StyleModules[i]->execute();
116         if (!_Layers[i])
117                 continue;
118
119         stroke_count += _Layers[i]->strokes_size();
120
121     timestamp->increment();
122   }
123   postDraw();
124 }
125
126 void Canvas::postDraw()
127 {
128   update();
129 }
130
131
132 void Canvas::Clear()
133 {
134   if(!_Layers.empty()) {
135     for (deque<StrokeLayer*>::iterator sl=_Layers.begin(), slend=_Layers.end();
136          sl != slend;
137          ++sl)
138       if (*sl)
139         delete (*sl);
140     _Layers.clear();  
141   }
142
143   if(!_StyleModules.empty()) {
144     for (deque<StyleModule*>::iterator s=_StyleModules.begin(), send=_StyleModules.end();
145          s != send;
146          ++s)
147       if (*s)
148         delete (*s);
149     _StyleModules.clear();
150   }
151   if(_steerableViewMap)
152     _steerableViewMap->Reset();
153
154         stroke_count = 0;
155 }
156
157 void Canvas::Erase()
158 {
159   if(!_Layers.empty())
160   {
161     for (deque<StrokeLayer*>::iterator sl=_Layers.begin(), slend=_Layers.end();
162          sl != slend;
163          ++sl)
164       if (*sl)
165         (*sl)->clear();
166   }
167   if(_steerableViewMap)
168     _steerableViewMap->Reset();
169   update();
170
171 stroke_count = 0;
172 }
173
174 void Canvas::PushBackStyleModule(StyleModule *iStyleModule) {
175   StrokeLayer* layer = new StrokeLayer();
176   _StyleModules.push_back(iStyleModule);
177   _Layers.push_back(layer);
178 }
179
180 void Canvas::InsertStyleModule(unsigned index, StyleModule *iStyleModule) {
181   unsigned size = _StyleModules.size();
182   StrokeLayer* layer = new StrokeLayer();
183   if((_StyleModules.empty()) || (index == size)) {
184     _StyleModules.push_back(iStyleModule);
185     _Layers.push_back(layer);
186     return;
187   }
188         _StyleModules.insert(_StyleModules.begin() + index, iStyleModule);
189   _Layers.insert(_Layers.begin()+index, layer);
190 }
191
192 void Canvas::RemoveStyleModule(unsigned index)
193 {
194   unsigned i=0;
195   if (!_StyleModules.empty())
196     {
197       for(deque<StyleModule*>::iterator s=_StyleModules.begin(), send=_StyleModules.end();
198           s!=send;
199           ++s)
200         {
201           if(i == index)
202             { 
203               // remove shader
204               if (*s)
205                 delete *s;
206               _StyleModules.erase(s);
207               break;
208             } 
209           ++i;
210         }
211     }
212   i=0;
213   if(!_Layers.empty())
214   {
215     for(deque<StrokeLayer*>::iterator sl=_Layers.begin(), slend=_Layers.end();
216     sl!=slend;
217     ++sl)
218     {
219       if(i == index)
220       { 
221         // remove layer
222         if (*sl)
223           delete *sl;
224         _Layers.erase(sl);
225         break;
226       } 
227       ++i;
228     }
229   }
230 }
231
232
233 void Canvas::SwapStyleModules(unsigned i1, unsigned i2)
234 {
235   StyleModule* tmp;
236   tmp = _StyleModules[i1];
237   _StyleModules[i1] = _StyleModules[i2];
238   _StyleModules[i2] = tmp;
239
240   StrokeLayer* tmp2;
241   tmp2 = _Layers[i1];
242   _Layers[i1] = _Layers[i2];
243   _Layers[i2] = tmp2;
244 }
245
246 void Canvas::ReplaceStyleModule(unsigned index, StyleModule *iStyleModule)
247 {
248   unsigned i=0;
249   for(deque<StyleModule*>::iterator s=_StyleModules.begin(), send=_StyleModules.end();
250       s != send;
251       ++s)
252     {
253       if(i == index)
254         {
255           if (*s)
256             delete *s;
257           *s = iStyleModule;
258           break;
259         }
260       ++i;
261     }
262 }
263
264 void Canvas::setVisible(unsigned index, bool iVisible) {
265   _StyleModules[index]->setDisplayed(iVisible);
266 }
267  
268 void Canvas::setModified(unsigned index, bool iMod)
269 {
270   _StyleModules[index]->setModified(iMod);
271 }
272
273 void Canvas::resetModified(bool iMod/* =false */)
274 {
275   unsigned size = _StyleModules.size();
276   for(unsigned i = 0; i < size; ++i)
277     setModified(i,iMod);
278 }
279
280 void Canvas::causalStyleModules(vector<unsigned>& vec, unsigned index) {
281   unsigned size = _StyleModules.size();
282
283   for(unsigned i = index; i < size; ++i)
284     if (_StyleModules[i]->getCausal())
285       vec.push_back(i);
286 }
287
288 void Canvas::Render(const StrokeRenderer *iRenderer)
289 {
290   for (unsigned i = 0; i < _StyleModules.size(); i++) {
291     if(!_StyleModules[i]->getDisplayed() || !_Layers[i])
292       continue;
293     _Layers[i]->Render(iRenderer);
294   }
295 }
296
297 void Canvas::RenderBasic(const StrokeRenderer *iRenderer)
298
299 {
300   for (unsigned i = 0; i < _StyleModules.size(); i++) {
301     if(!_StyleModules[i]->getDisplayed() || !_Layers[i])
302       continue;
303     _Layers[i]->RenderBasic(iRenderer);
304   }
305 }
306
307 void Canvas::loadMap(const char *iFileName, const char *iMapName, unsigned int iNbLevels, float iSigma){
308   // check whether this map was already loaded:
309   if(!_maps.empty()){
310     mapsMap::iterator m = _maps.find(iMapName);
311     if(m!=_maps.end()){
312       // lazy check for size changes
313       ImagePyramid * pyramid = (*m).second;
314       if((pyramid->width() != width()) || (pyramid->height() != height())){
315         delete pyramid;
316       }else{
317         return;
318       }
319     }
320   }
321   string filePath;
322   if(_MapsPath){
323     filePath = _MapsPath;
324     filePath += iFileName;
325   }else{
326     filePath = iFileName;
327   }
328
329   //soc
330   // QImage *qimg;
331   // QImage newMap(filePath.c_str()); 
332   // if(newMap.isNull()){
333   //   cout << "Could not load image file " << filePath << endl;
334   //   return;
335   // }
336   // qimg = &newMap;
337         ImBuf *qimg = IMB_loadiffname(filePath.c_str(), 0);;
338         if( qimg == 0 ){
339                 cout << "Could not load image file " << filePath << endl;
340         return; 
341         }
342
343   // soc
344   //resize
345   // QImage scaledImg;
346   // if((newMap.width()!=width()) || (newMap.height()!=height())){
347   //      scaledImg = newMap.scaled(width(), height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
348   //   qimg = &scaledImg;
349   // }
350         ImBuf *scaledImg;
351   if( ( qimg->x != width() ) || ( qimg->y != height() ) ){
352         scaledImg = IMB_dupImBuf(qimg);
353         IMB_scaleImBuf(scaledImg, width(), height());
354   }
355
356
357   // deal with color image 
358   //  if(newMap->depth() != 8){
359   //    int w = newMap->width();
360   //    int h = newMap->height();
361   //    QImage *tmp = new QImage(w, h, 8);
362   //    for(unsigned y=0;y<h;++y){
363   //      for(unsigned x=0;x<w;++x){
364   //        int c = qGray(newMap->pixel(x,y));
365   //        tmp->setPixel(x,y,c);
366   //      }
367   //    }
368   //    delete newMap;
369   //    newMap = tmp;
370   //  }
371
372   int x,y;
373   int w = qimg->x;
374   int h = qimg->y;
375 int rowbytes = w*4;
376   GrayImage tmp(w,h);
377   char *pix;
378   
379   for(y=0; y<h;++y){
380     for(x=0;x<w;++x){
381                 pix = (char*)qimg->rect + y*rowbytes + x*4;
382           float c = (pix[0]*11 + pix[1]*16 + pix[2]*5)/32;
383       tmp.setPixel(x,y,c);
384     }
385   }
386
387   //  GrayImage blur(w,h);
388   //  GaussianFilter gf(4.f);
389   //  //int bound = gf.getBound();
390   //  for(y=0; y<h;++y){
391   //    for(x=0;x<w;++x){
392   //      int c = gf.getSmoothedPixel<GrayImage>(&tmp, x,y);
393   //      blur.setPixel(x,y,c);
394   //    }
395   //  }
396
397   GaussianPyramid *pyramid = new GaussianPyramid(tmp, iNbLevels, iSigma);
398   int ow = pyramid->width(0);
399   int oh = pyramid->height(0);
400   string base(iMapName); //soc
401   for(int i=0; i<pyramid->getNumberOfLevels(); ++i){
402     // save each image:
403     //    w = pyramid.width(i);
404     //    h = pyramid.height(i);
405         
406         //soc  QImage qtmp(ow, oh, QImage::Format_RGB32);
407     ImBuf *qtmp = IMB_allocImBuf(ow, oh, 32, IB_rect, 0);
408
409 //int k = (1<<i);
410     for(y=0;y<oh;++y){
411       for(x=0;x<ow;++x){
412         int c = pyramid->pixel(x,y,i);//255*pyramid->pixel(x,y,i);
413         //soc qtmp.setPixel(x,y,qRgb(c,c,c));
414                 pix = (char*)qtmp->rect + y*rowbytes + x*4;
415                 pix[0] = pix [1] = pix[2] = c;
416       }
417     }
418     //soc qtmp.save(base+QString::number(i)+".bmp", "BMP");
419         stringstream filename;
420         filename << base;
421         filename << i << ".bmp";        
422         imb_savebmp(qtmp, const_cast<char *>(filename.str().c_str()), 0);
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 }