Initial Stable Commit
[synfig.git] / synfig-core / trunk / src / modules / mod_noise / distort.cpp
1 /* === S I N F G =========================================================== */
2 /*!     \file noise.cpp
3 **      \brief blehh
4 **
5 **      $Id: distort.cpp,v 1.1.1.1 2005/01/04 01:23:14 darco Exp $
6 **
7 **      \legal
8 **      Copyright (c) 2002 Robert B. Quattlebaum Jr.
9 **
10 **      This software and associated documentation
11 **      are CONFIDENTIAL and PROPRIETARY property of
12 **      the above-mentioned copyright holder.
13 **
14 **      You may not copy, print, publish, or in any
15 **      other way distribute this software without
16 **      a prior written agreement with
17 **      the copyright holder.
18 **      \endlegal
19 */
20 /* ========================================================================= */
21
22 /* === H E A D E R S ======================================================= */
23
24 #ifdef USING_PCH
25 #       include "pch.h"
26 #else
27 #ifdef HAVE_CONFIG_H
28 #       include <config.h>
29 #endif
30
31 #include "distort.h"
32
33 #include <sinfg/string.h>
34 #include <sinfg/time.h>
35 #include <sinfg/context.h>
36 #include <sinfg/paramdesc.h>
37 #include <sinfg/renddesc.h>
38 #include <sinfg/surface.h>
39 #include <sinfg/value.h>
40 #include <sinfg/valuenode.h>
41
42 #endif
43
44 /* === M A C R O S ========================================================= */
45
46 using namespace sinfg;
47 using namespace std;
48 using namespace etl;
49
50 /* === G L O B A L S ======================================================= */
51
52 SINFG_LAYER_INIT(NoiseDistort);
53 SINFG_LAYER_SET_NAME(NoiseDistort,"noise_distort");
54 SINFG_LAYER_SET_LOCAL_NAME(NoiseDistort,_("Noise Distort"));
55 SINFG_LAYER_SET_CATEGORY(NoiseDistort,_("Distortions"));
56 SINFG_LAYER_SET_VERSION(NoiseDistort,"0.0");
57 SINFG_LAYER_SET_CVS_ID(NoiseDistort,"$Id: distort.cpp,v 1.1.1.1 2005/01/04 01:23:14 darco Exp $");
58
59 /* === P R O C E D U R E S ================================================= */
60
61 /* === M E T H O D S ======================================================= */
62
63 NoiseDistort::NoiseDistort():
64         size(1,1)
65 {
66         set_blend_method(Color::BLEND_STRAIGHT);
67         smooth=2;
68         detail=4;
69         speed=0;
70         random.set_seed(time(NULL));
71         turbulent=false;
72         displacement=Vector(0.25,0.25);
73 }
74
75 inline Color
76 NoiseDistort::color_func(const Point &point, float supersample,Context context)const
77 {
78         Color ret(0,0,0,0);
79         
80         float x(point[0]/size[0]*(1<<detail));
81         float y(point[1]/size[1]*(1<<detail));
82         
83         int i;
84         Time time;
85         time=speed*curr_time;
86         int smooth((!speed && smooth==3)?5:smooth);
87         
88         {
89                 Vector vect(0,0);
90                 for(i=0;i<detail;i++)
91                 {
92                         vect[0]=random(smooth,0+(detail-i)*5,x,y,time)+vect[0]*0.5;
93                         vect[1]=random(smooth,1+(detail-i)*5,x,y,time)+vect[1]*0.5;
94
95                         if(vect[0]<-1)vect[0]=-1;if(vect[0]>1)vect[0]=1;
96                         if(vect[1]<-1)vect[1]=-1;if(vect[1]>1)vect[1]=1;
97                                 
98                         if(turbulent)
99                         {
100                                 vect[0]=abs(vect[0]);
101                                 vect[1]=abs(vect[1]);
102                         }
103                                 
104                         x/=2.0f;
105                         y/=2.0f;
106                 }
107
108                 if(!turbulent)
109                 {
110                         vect[0]=vect[0]/2.0f+0.5f;
111                         vect[1]=vect[1]/2.0f+0.5f;
112                 }
113                 vect[0]=(vect[0]-0.5f)*displacement[0];
114                 vect[1]=(vect[1]-0.5f)*displacement[1];
115                 
116                 ret=context.get_color(point+vect);
117         }
118         return ret;
119 }
120
121 inline float
122 NoiseDistort::calc_supersample(const sinfg::Point &x, float pw,float ph)const
123 {
124         return 0.0f;
125 }
126
127 void
128 NoiseDistort::set_time(sinfg::Context context, sinfg::Time t)const
129 {
130         curr_time=t;
131         context.set_time(t);
132 }
133
134 void
135 NoiseDistort::set_time(sinfg::Context context, sinfg::Time t, const sinfg::Point &point)const
136 {
137         curr_time=t;
138         context.set_time(t,point);
139 }
140
141 sinfg::Layer::Handle
142 NoiseDistort::hit_check(sinfg::Context context, const sinfg::Point &point)const
143 {
144         if(get_blend_method()==Color::BLEND_STRAIGHT && get_amount()>=0.5)
145                 return const_cast<NoiseDistort*>(this);
146         if(get_amount()==0.0)
147                 return context.hit_check(point);
148         if(color_func(point,0,context).get_a()>0.5)
149                 return const_cast<NoiseDistort*>(this);
150         return false;
151 }
152
153 bool
154 NoiseDistort::set_param(const String & param, const ValueBase &value)
155 {
156         if(param=="seed" && value.same_as(int()))
157         {
158                 random.set_seed(value.get(int()));
159                 return true;
160         }
161         IMPORT(size);
162         IMPORT(speed);
163         IMPORT(smooth);
164         IMPORT(detail);
165         IMPORT(turbulent);
166         IMPORT(displacement);
167         return Layer_Composite::set_param(param,value); 
168 }
169
170 ValueBase
171 NoiseDistort::get_param(const String & param)const
172 {
173         if(param=="seed")
174                 return random.get_seed();
175         EXPORT(size);
176         EXPORT(speed);
177         EXPORT(smooth);
178         EXPORT(detail);
179         EXPORT(displacement);
180         EXPORT(turbulent);
181         
182         EXPORT_NAME();
183         EXPORT_VERSION();
184                 
185         return Layer_Composite::get_param(param);       
186 }
187
188 Layer::Vocab
189 NoiseDistort::get_param_vocab()const
190 {
191         Layer::Vocab ret(Layer_Composite::get_param_vocab());
192         
193         ret.push_back(ParamDesc("displacement")
194                 .set_local_name(_("Displacement"))
195         );
196
197         ret.push_back(ParamDesc("size")
198                 .set_local_name(_("Size"))
199         );
200         ret.push_back(ParamDesc("seed")
201                 .set_local_name(_("Random Seed"))
202         );
203         ret.push_back(ParamDesc("smooth")
204                 .set_local_name(_("Interpolation"))
205                 .set_description(_("What type of interpolation to use"))
206                 .set_hint("enum")
207                 .add_enum_value(0,"nearest",_("Nearest Neighbor"))
208                 .add_enum_value(1,"linear",_("Linear"))
209                 .add_enum_value(2,"cosine",_("Cosine"))
210                 .add_enum_value(3,"spline",_("Spline"))
211                 .add_enum_value(4,"cubic",_("Cubic"))
212         );
213         ret.push_back(ParamDesc("detail")
214                 .set_local_name(_("Detail"))
215         );
216         ret.push_back(ParamDesc("speed")
217                 .set_local_name(_("Animation Speed"))
218         );
219         ret.push_back(ParamDesc("turbulent")
220                 .set_local_name(_("Turbulent"))
221         );
222         
223         return ret;
224 }
225
226 Color
227 NoiseDistort::get_color(Context context, const Point &point)const
228 {
229         const Color color(color_func(point,0,context));
230
231         if(get_amount()==1.0 && get_blend_method()==Color::BLEND_STRAIGHT)
232                 return color;
233         else
234                 return Color::blend(color,context.get_color(point),get_amount(),get_blend_method());
235 }
236
237 Rect
238 NoiseDistort::get_bounding_rect(Context context)const
239 {
240         if(is_disabled())
241                 return Rect::zero();
242
243         if(Color::is_onto(get_blend_method()))
244                 return context.get_full_bounding_rect();
245         
246         Rect bounds(context.get_full_bounding_rect().expand_x(displacement[0]).expand_y(displacement[1]));
247         
248         return bounds;
249 }
250
251 /*
252 bool
253 NoiseDistort::accelerated_render(Context context,Surface *surface,int quality, const RendDesc &renddesc, ProgressCallback *cb)const
254 {
255         SuperCallback supercb(cb,0,9500,10000);
256
257         if(get_amount()==1.0 && get_blend_method()==Color::BLEND_STRAIGHT)
258         {
259                 surface->set_wh(renddesc.get_w(),renddesc.get_h());
260         }
261         else
262         {
263                 if(!context.accelerated_render(surface,quality,renddesc,&supercb))
264                         return false;
265                 if(get_amount()==0)
266                         return true;
267         }
268
269                 
270         int x,y;
271
272         Surface::pen pen(surface->begin());
273         const Real pw(renddesc.get_pw()),ph(renddesc.get_ph());
274         Point pos;
275         Point tl(renddesc.get_tl());
276         const int w(surface->get_w());
277         const int h(surface->get_h());
278         
279         if(get_amount()==1.0 && get_blend_method()==Color::BLEND_STRAIGHT)
280         {
281                 for(y=0,pos[1]=tl[1];y<h;y++,pen.inc_y(),pen.dec_x(x),pos[1]+=ph)
282                         for(x=0,pos[0]=tl[0];x<w;x++,pen.inc_x(),pos[0]+=pw)
283                                 pen.put_value(color_func(pos,calc_supersample(pos,pw,ph),context));
284         }
285         else
286         {
287                 for(y=0,pos[1]=tl[1];y<h;y++,pen.inc_y(),pen.dec_x(x),pos[1]+=ph)
288                         for(x=0,pos[0]=tl[0];x<w;x++,pen.inc_x(),pos[0]+=pw)
289                                 pen.put_value(Color::blend(color_func(pos,calc_supersample(pos,pw,ph),context),pen.get_value(),get_amount(),get_blend_method()));
290         }
291
292         // Mark our progress as finished
293         if(cb && !cb->amount_complete(10000,10000))
294                 return false;
295
296         return true;
297 }
298 */