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