Fix bugs in previous commit that caused FTBFS in synfig and ETL FTBFS with older...
[synfig.git] / synfig-core / tags / synfig_0_61_05 / synfig-core / src / modules / lyr_std / julia.cpp
1 /*! ========================================================================
2 ** Synfig
3 ** Template File
4 ** $Id: julia.cpp,v 1.1.1.1 2005/01/04 01:23:10 darco Exp $
5 **
6 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
7 **
8 **      This package is free software; you can redistribute it and/or
9 **      modify it under the terms of the GNU General Public License as
10 **      published by the Free Software Foundation; either version 2 of
11 **      the License, or (at your option) any later version.
12 **
13 **      This package is distributed in the hope that it will be useful,
14 **      but WITHOUT ANY WARRANTY; without even the implied warranty of
15 **      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 **      General Public License for more details.
17 **
18 ** === N O T E S ===========================================================
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 "julia.h"
32
33 #include <synfig/string.h>
34 #include <synfig/time.h>
35 #include <synfig/context.h>
36 #include <synfig/paramdesc.h>
37 #include <synfig/renddesc.h>
38 #include <synfig/surface.h>
39 #include <synfig/value.h>
40 #include <synfig/valuenode.h>
41
42 #endif
43
44 /* === M A C R O S ========================================================= */
45
46 #define LOG_OF_2                0.69314718055994528623
47
48 /* === G L O B A L S ======================================================= */
49
50 SYNFIG_LAYER_INIT(Julia);
51 SYNFIG_LAYER_SET_NAME(Julia,"julia");
52 SYNFIG_LAYER_SET_LOCAL_NAME(Julia,_("Julia Set"));
53 SYNFIG_LAYER_SET_CATEGORY(Julia,_("Fractals"));
54 SYNFIG_LAYER_SET_VERSION(Julia,"0.1");
55 SYNFIG_LAYER_SET_CVS_ID(Julia,"$Id: julia.cpp,v 1.1.1.1 2005/01/04 01:23:10 darco Exp $");
56
57 /* === P R O C E D U R E S ================================================= */
58
59 inline void
60 color_neg_flip(Color &color)
61 {
62         if(color.get_a()==0)
63         {
64                 color=Color::alpha();
65                 return;
66         }
67
68         if(color.get_a()<0)
69                 color=-color;
70
71         if(color.get_r()<0)
72         {
73                 color.set_g(color.get_g()-color.get_r());
74                 color.set_b(color.get_b()-color.get_r());
75                 color.set_r(0);
76         }
77         if(color.get_g()<0)
78         {
79                 color.set_r(color.get_r()-color.get_g());
80                 color.set_b(color.get_b()-color.get_g());
81                 color.set_g(0);
82         }
83         if(color.get_b()<0)
84         {
85                 color.set_r(color.get_r()-color.get_b());
86                 color.set_g(color.get_g()-color.get_b());
87                 color.set_b(0);
88         }
89 }
90
91 /* === M E T H O D S ======================================================= */
92
93 Julia::Julia():color_shift(angle::degrees(0))
94 {
95         icolor=Color::black();
96         ocolor=Color::black();
97         iterations=32;
98         color_shift=Angle::deg(0);
99
100         distort_inside=true;
101         distort_outside=true;
102         shade_inside=true;
103         shade_outside=true;
104         solid_inside=false;
105         solid_outside=false;
106         invert_inside=false;
107         invert_outside=false;
108         color_inside=true;
109         color_outside=false;
110         color_cycle=false;
111         smooth_outside=true;
112         broken=false;
113         seed=Point(0,0);
114
115         bailout=4;
116         lp=log(log(bailout));
117 }
118         
119 bool
120 Julia::set_param(const String & param, const ValueBase &value)
121 {
122
123         IMPORT(icolor);
124         IMPORT(ocolor);
125         IMPORT(color_shift);
126         IMPORT(seed);
127
128         IMPORT(distort_inside);
129         IMPORT(distort_outside);
130         IMPORT(shade_inside);
131         IMPORT(shade_outside);
132         IMPORT(solid_inside);
133         IMPORT(solid_outside);
134         IMPORT(invert_inside);
135         IMPORT(invert_outside);
136         IMPORT(color_inside);
137         IMPORT(color_outside);
138
139         IMPORT(color_cycle);
140         IMPORT(smooth_outside);
141         IMPORT(broken);
142
143         if(param=="iterations" && value.same_as(iterations))
144         {
145                 iterations=value.get(iterations);
146                 if(iterations<0)
147                         iterations=0;
148                 if(iterations>500000)
149                         iterations=500000;
150                 return true;
151         }
152         if(param=="bailout" && value.same_as(bailout))
153         {
154                 bailout=value.get(bailout);
155                 bailout*=bailout;
156                 lp=log(log(bailout));
157                 return true;
158         }
159
160         return false;
161 }
162
163 ValueBase
164 Julia::get_param(const String & param)const
165 {
166         EXPORT(icolor);
167         EXPORT(ocolor);
168         EXPORT(color_shift);
169         EXPORT(iterations);
170         EXPORT(seed);
171
172         EXPORT(distort_inside);
173         EXPORT(distort_outside);
174         EXPORT(shade_inside);
175         EXPORT(shade_outside);
176         EXPORT(solid_inside);
177         EXPORT(solid_outside);
178         EXPORT(invert_inside);
179         EXPORT(invert_outside);
180         EXPORT(color_inside);
181         EXPORT(color_outside);
182         EXPORT(color_cycle);
183         EXPORT(smooth_outside);
184         EXPORT(broken);
185
186         if(param=="bailout")
187                 return sqrt(bailout);
188
189         EXPORT_NAME();
190         EXPORT_VERSION();
191                 
192         return ValueBase();     
193 }
194
195 Color
196 Julia::get_color(Context context, const Point &pos)const
197 {
198         Real
199                 cr, ci,
200                 zr, zi,
201                 zr_hold;
202         
203         ColorReal
204                 depth, mag;
205         
206         Color
207                 ret;
208         
209         cr=seed[0];
210         ci=seed[1];
211         zr=pos[0];
212         zi=pos[1];
213         
214         for(int i=0;i<iterations;i++)
215         {
216                 // Perform complex multiplication
217                 zr_hold=zr;
218                 zr=zr*zr-zi*zi + cr;
219                 zi=zr_hold*zi*2 + ci;
220
221                 // Use "broken" algorithm, if requested (looks weird)
222                 if(broken)zr+=zi;
223                 
224                 // Calculate Magnitude
225                 mag=zr*zr+zi*zi;
226
227                 if(mag>4)
228                 {       
229                         if(smooth_outside)
230                         {
231                                 // Darco's original mandelbrot smoothing algo
232                                 // depth=((Point::value_type)i+(2.0-sqrt(mag))/PI);
233
234                                 // Linas Vepstas algo (Better than darco's)
235                                 // See (http://linas.org/art-gallery/escape/smooth.html)
236                                 depth= (ColorReal)i - log(log(sqrt(mag))) / LOG_OF_2;
237
238                                 // Clamp
239                                 if(depth<0) depth=0;
240                         }
241                         else
242                                 depth=static_cast<ColorReal>(i);
243
244                         if(solid_outside)
245                                 ret=ocolor;
246                         else
247                                 if(distort_outside)
248                                         ret=context.get_color(Point(zr,zi));
249                                 else
250                                         ret=context.get_color(pos);
251
252                         if(invert_outside)
253                                 ret=~ret;
254
255                         if(color_outside)
256                                 ret=ret.set_uv(zr,zi).clamped_negative();
257
258                         if(color_cycle)
259                                 ret=ret.rotate_uv(color_shift.operator*(depth)).clamped_negative();
260                         
261                         if(shade_outside)
262                         {
263                                 ColorReal alpha=depth/static_cast<ColorReal>(iterations);
264                                 ret=(ocolor-ret)*alpha+ret;
265                         }
266                         return ret;
267                 }
268         }
269
270         if(solid_inside)
271                 ret=icolor;
272         else
273                 if(distort_inside)
274                         ret=context.get_color(Point(zr,zi));
275                 else
276                         ret=context.get_color(pos);
277
278         if(invert_inside)
279                 ret=~ret;
280
281         if(color_inside)
282                 ret=ret.set_uv(zr,zi).clamped_negative();
283
284         if(shade_inside)
285                 ret=(icolor-ret)*mag+ret;
286
287         return ret;
288 }
289         
290 Layer::Vocab
291 Julia::get_param_vocab()const
292 {
293         Layer::Vocab ret;
294         
295         ret.push_back(ParamDesc("icolor")
296                 .set_local_name(_("Inside Color"))
297                 .set_description(_("Color of the Set"))
298         );
299         ret.push_back(ParamDesc("ocolor")
300                 .set_local_name(_("Outside Color"))
301                 .set_description(_("Color outside the Set"))
302         );
303         ret.push_back(ParamDesc("color_shift")
304                 .set_local_name(_("Color Shift"))
305         );
306         ret.push_back(ParamDesc("iterations")
307                 .set_local_name(_("Iterations"))
308         );
309         ret.push_back(ParamDesc("seed")
310                 .set_local_name(_("Seed Point"))
311         );
312         ret.push_back(ParamDesc("bailout")
313                 .set_local_name(_("Bailout ValueBase"))
314         );
315         
316         ret.push_back(ParamDesc("distort_inside")
317                 .set_local_name(_("Distort Inside"))
318         );
319         ret.push_back(ParamDesc("shade_inside")
320                 .set_local_name(_("Shade Inside"))
321         );
322         ret.push_back(ParamDesc("solid_inside")
323                 .set_local_name(_("Solid Inside"))
324         );
325         ret.push_back(ParamDesc("invert_inside")
326                 .set_local_name(_("Invert Inside"))
327         );
328         ret.push_back(ParamDesc("color_inside")
329                 .set_local_name(_("Color Inside"))
330         );
331         ret.push_back(ParamDesc("distort_outside")
332                 .set_local_name(_("Distort Outside"))
333         );
334         ret.push_back(ParamDesc("shade_outside")
335                 .set_local_name(_("Shade Outside"))
336         );
337         ret.push_back(ParamDesc("solid_outside")
338                 .set_local_name(_("Solid Outside"))
339         );
340         ret.push_back(ParamDesc("invert_outside")
341                 .set_local_name(_("Invert Outside"))
342         );
343         ret.push_back(ParamDesc("color_outside")
344                 .set_local_name(_("Color Outside"))
345         );
346         
347         ret.push_back(ParamDesc("color_cycle")
348                 .set_local_name(_("Color Cycle"))
349         );
350         ret.push_back(ParamDesc("smooth_outside")
351                 .set_local_name(_("Smooth Outside"))
352                 .set_description(_("Smooth the coloration outside the set"))
353         );
354         ret.push_back(ParamDesc("broken")
355                 .set_local_name(_("Break Set"))
356                 .set_description(_("Modify equation to achieve interesting results"))
357         );
358         
359         
360         return ret;
361 }