Fix bugs in previous commit that caused FTBFS in synfig and ETL FTBFS with older...
[synfig.git] / synfig-core / tags / 0.61.09 / src / synfig / layer_motionblur.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file layer_motionblur.cpp
3 **      \brief Implementation of the "Motion Blur" layer
4 **
5 **      $Id$
6 **
7 **      \legal
8 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **      Copyright (c) 2007, 2008 Chris Moore
10 **
11 **      This package is free software; you can redistribute it and/or
12 **      modify it under the terms of the GNU General Public License as
13 **      published by the Free Software Foundation; either version 2 of
14 **      the License, or (at your option) any later version.
15 **
16 **      This package is distributed in the hope that it will be useful,
17 **      but WITHOUT ANY WARRANTY; without even the implied warranty of
18 **      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 **      General Public License for more details.
20 **      \endlegal
21 */
22 /* ========================================================================= */
23
24 /* === H E A D E R S ======================================================= */
25
26 #ifdef USING_PCH
27 #       include "pch.h"
28 #else
29 #ifdef HAVE_CONFIG_H
30 #       include <config.h>
31 #endif
32
33 #include "string.h"
34 #include "layer_motionblur.h"
35 #include "time.h"
36 #include "context.h"
37 #include "paramdesc.h"
38 #include "renddesc.h"
39 #include "surface.h"
40 #include "value.h"
41 #include "valuenode.h"
42 #include "canvas.h"
43
44 #endif
45
46 /* === U S I N G =========================================================== */
47
48 using namespace synfig;
49 using namespace etl;
50 using namespace std;
51
52 /* === G L O B A L S ======================================================= */
53
54 SYNFIG_LAYER_INIT(Layer_MotionBlur);
55 SYNFIG_LAYER_SET_NAME(Layer_MotionBlur,"MotionBlur"); // todo: use motion_blur
56 SYNFIG_LAYER_SET_LOCAL_NAME(Layer_MotionBlur,N_("Motion Blur"));
57 SYNFIG_LAYER_SET_CATEGORY(Layer_MotionBlur,N_("Blurs"));
58 SYNFIG_LAYER_SET_VERSION(Layer_MotionBlur,"0.1");
59 SYNFIG_LAYER_SET_CVS_ID(Layer_MotionBlur,"$Id$");
60
61 /* === M E M B E R S ======================================================= */
62
63 Layer_MotionBlur::Layer_MotionBlur():
64         Layer_Composite (1.0,Color::BLEND_STRAIGHT),
65         aperture                (0)
66 {
67 }
68
69 bool
70 Layer_MotionBlur::set_param(const String &param, const ValueBase &value)
71 {
72
73         IMPORT(aperture);
74         return Layer_Composite::set_param(param,value);
75 }
76
77 ValueBase
78 Layer_MotionBlur::get_param(const String &param)const
79 {
80         EXPORT(aperture);
81
82         EXPORT_NAME();
83         EXPORT_VERSION();
84
85         return Layer_Composite::get_param(param);
86 }
87
88 void
89 Layer_MotionBlur::set_time(Context context, Time time)const
90 {
91         context.set_time(time);
92         time_cur=time;
93 }
94
95 void
96 Layer_MotionBlur::set_time(Context context, Time time, const Point &pos)const
97 {
98         context.set_time(time,pos);
99         time_cur=time;
100 }
101
102 Color
103 Layer_MotionBlur::get_color(Context context, const Point &pos)const
104 {
105 /*      if(aperture)
106         {
107                 Time time(time_cur);
108                 time+=(Vector::value_type)( (signed)(RAND_MAX/2)-(signed)rand() )/(Vector::value_type)(RAND_MAX) *aperture -aperture*0.5;
109                 context.set_time(time, pos);
110         }
111 */
112         return context.get_color(pos);
113 }
114
115 Layer::Vocab
116 Layer_MotionBlur::get_param_vocab()const
117 {
118         Layer::Vocab ret;
119         //ret=Layer_Composite::get_param_vocab();
120
121         ret.push_back(ParamDesc("aperture")
122                 .set_local_name(_("Aperture"))
123                 .set_description(_("Shutter Time"))
124         );
125
126         return ret;
127 }
128
129 bool
130 Layer_MotionBlur::accelerated_render(Context context,Surface *surface,int quality, const RendDesc &renddesc, ProgressCallback *cb)const
131 {
132         if(aperture && quality<=10)
133         {
134                 //int x, y;
135                 SuperCallback subimagecb;
136                 int samples=1;
137                 switch(quality)
138                 {
139                         case 1: // Production Quality
140                                 samples=32;
141                                 break;
142                         case 2: // Excellent Quality
143                                 samples=24;
144                                 break;
145                         case 3: // Good Quality
146                                 samples=16;
147                                 break;
148                         case 4: // Moderate Quality
149                                 samples=12;
150                                 break;
151                         case 5: // Draft Quality
152                                 samples=7;
153                                 break;
154                         case 6:
155                                 samples=6;
156                                 break;
157                         case 7:
158                                 samples=5;
159                                 break;
160                         case 8:
161                                 samples=3;
162                                 break;
163                         case 9:
164                                 samples=2;
165                                 break;
166                         case 10: // Rough Quality
167             default:
168                                 samples=1;
169                                 break;
170
171                 }
172
173                 if (samples == 1) return context.accelerated_render(surface,quality,renddesc,cb);
174
175                 Surface tmp;
176                 int i;
177                 float scale, divisor = 0;
178
179                 surface->set_wh(renddesc.get_w(),renddesc.get_h());
180                 surface->clear();
181
182                 for(i=0;i<samples;i++)
183                 {
184                         subimagecb=SuperCallback(cb,i*(5000/samples),(i+1)*(5000/samples),5000);
185                         context.set_time(time_cur-(aperture*(samples-1-i)/(samples-1)));
186                         if(!context.accelerated_render(&tmp,quality,renddesc,&subimagecb))
187                                 return false;
188                         scale = 1.0/(samples-i);
189                         divisor += scale;
190                         for(int y=0;y<renddesc.get_h();y++)
191                                 for(int x=0;x<renddesc.get_w();x++)
192                                         (*surface)[y][x]+=tmp[y][x].premult_alpha()*scale;
193                 }
194                 for(int y=0;y<renddesc.get_h();y++)
195                         for(int x=0;x<renddesc.get_w();x++)
196                                 (*surface)[y][x]=((*surface)[y][x]/divisor).demult_alpha();
197         }
198         else
199                 return context.accelerated_render(surface,quality,renddesc,cb);
200
201         return true;
202 }