xref: /haiku/src/add-ons/screen_savers/ifs/IFS.cpp (revision d3d8b26997fac34a84981e6d2b649521de2cc45a)
1 /*
2  * Copyright 2006, Haiku.
3  * Copyright (c) 1997 by Massimino Pascal <Pascal.Massimon@ens.fr>
4  *
5  * Distributed under the terms of the MIT License.
6  *
7  * Authors:
8  *		Massimino Pascal <Pascal.Massimon@ens.fr>
9  *		Stephan Aßmus <superstippi@gmx.de>
10  */
11 
12 /*! When shown ifs, Diana Rose (4 years old) said, "It looks like dancing."
13  */
14 
15 #include "IFS.h"
16 
17 #include <new>
18 #include <malloc.h>
19 #include <stdio.h>
20 #include <string.h>
21 
22 #include <Bitmap.h>
23 #include <OS.h>
24 #include <Screen.h>
25 #include <View.h>
26 
27 #include <unistd.h>  // for getpid()
28 #include <sys/time.h> // for gettimeofday()
29 
30 using std::nothrow;
31 
32 #define HALF 0
33 
34 // The following 'random' numbers are taken from CRC, 18th Edition, page 622.
35 // Each array element was taken from the corresponding line in the table,
36 // except that a[0] was from line 100. 8s and 9s in the table were simply
37 // skipped. The high order digit was taken mod 4.
38 
39 #define VectorSize 55
40 static unsigned int a[VectorSize] = {
41  035340171546, 010401501101, 022364657325, 024130436022, 002167303062, //  5
42  037570375137, 037210607110, 016272055420, 023011770546, 017143426366, // 10
43  014753657433, 021657231332, 023553406142, 004236526362, 010365611275, // 14
44  007117336710, 011051276551, 002362132524, 001011540233, 012162531646, // 20
45  007056762337, 006631245521, 014164542224, 032633236305, 023342700176, // 25
46  002433062234, 015257225043, 026762051606, 000742573230, 005366042132, // 30
47  012126416411, 000520471171, 000725646277, 020116577576, 025765742604, // 35
48  007633473735, 015674255275, 017555634041, 006503154145, 021576344247, // 40
49  014577627653, 002707523333, 034146376720, 030060227734, 013765414060, // 45
50  036072251540, 007255221037, 024364674123, 006200353166, 010126373326, // 50
51  015664104320, 016401041535, 016215305520, 033115351014, 017411670323  // 55
52 };
53 
54 static int i1, i2;
55 
56 // ya_random
57 unsigned int
58 ya_random (void)
59 {
60   register int ret = a[i1] + a[i2];
61   a[i1] = ret;
62   if (++i1 >= VectorSize) i1 = 0;
63   if (++i2 >= VectorSize) i2 = 0;
64   return ret;
65 }
66 
67 // ya_rand_init
68 void
69 ya_rand_init(unsigned int seed)
70 {
71   int i;
72   if (seed == 0)
73     {
74       struct timeval tp;
75       struct timezone tzp;
76       gettimeofday(&tp, &tzp);
77       /* ignore overflow */
78       seed = (999*tp.tv_sec) + (1001*tp.tv_usec) + (1003 * getpid());
79     }
80 
81   a[0] += seed;
82   for (i = 1; i < VectorSize; i++)
83     {
84       seed = a[i-1]*1001 + seed*999;
85       a[i] += seed;
86     }
87 
88   i1 = a[0] % VectorSize;
89   i2 = (i1 + 024) % VectorSize;
90 }
91 
92 #define random()   ya_random()
93 #define RAND_MAX   0xFFFFFFFF
94 
95 #define FLOAT_TO_INT(x)  (int32)( (float)(UNIT)*(x) )
96 
97 #define LRAND()			((long) (random() & 0x7fffffff))
98 #define NRAND(n)		((int) (LRAND() % (n)))
99 #define MAXRAND			(2147483648.0) // unsigned 1<<31 as a float
100 #define SRAND(n)		// already seeded by screenhack.c TODO: ?!? is it?
101 
102 
103 // gauss_rand
104 static float
105 gauss_rand(float c, float A, float S)
106 {
107 	float         y;
108 
109 	y = (float) LRAND() / MAXRAND;
110 	y = A * (1.0 - exp(-y * y * S)) / (1.0 - exp(-S));
111 	if (NRAND(2))
112 		return (c + y);
113 	return (c - y);
114 }
115 
116 // half_gauss_rand
117 static float
118 half_gauss_rand(float c, float A, float S)
119 {
120 	float         y;
121 
122 	y = (float) LRAND() / MAXRAND;
123 	y = A * (1.0 - exp(-y * y * S)) / (1.0 - exp(-S));
124 	return (c + y);
125 }
126 
127 // transform
128 inline void
129 transform(SIMI* Simi, int32 xo, int32 yo, int32* x, int32* y)
130 {
131 	int32        xx, yy;
132 
133 	xo = xo - Simi->Cx;
134 	xo = (xo * Simi->R) / UNIT;
135 	yo = yo - Simi->Cy;
136 	yo = (yo * Simi->R) / UNIT;
137 
138 	xx = xo - Simi->Cx;
139 	xx = (xx * Simi->R2) / UNIT;
140 	yy = -yo - Simi->Cy;
141 	yy = (yy * Simi->R2) / UNIT;
142 
143 	*x = ((xo * Simi->Ct - yo * Simi->St + xx * Simi->Ct2 - yy * Simi->St2) / UNIT) + Simi->Cx;
144 	*y = ((xo * Simi->St + yo * Simi->Ct + xx * Simi->St2 + yy * Simi->Ct2) / UNIT) + Simi->Cy;
145 }
146 
147 
148 // constructor
149 IFS::IFS(BRect bounds)
150 	: fRoot(NULL),
151 	  fAdditive(false),
152 	  fCurrentMarkValue(1)
153 {
154 	ya_rand_init(system_time());
155 
156 	int         i;
157 	FRACTAL    *Fractal;
158 
159 	if (fRoot == NULL) {
160 		fRoot = (FRACTAL*) calloc(1, sizeof (FRACTAL));
161 		if (fRoot == NULL)
162 			return;
163 	}
164 	Fractal = fRoot;
165 
166 	_FreeBuffers(Fractal);
167 	i = (NRAND(4)) + 2;	// Number of centers
168 	switch (i) {
169 		case 3:
170 			Fractal->Depth = fAdditive ? MAX_DEPTH_3 + 1 : MAX_DEPTH_3;
171 			Fractal->r_mean = .6;
172 			Fractal->dr_mean = .4;
173 			Fractal->dr2_mean = .3;
174 			break;
175 
176 		case 4:
177 			Fractal->Depth = MAX_DEPTH_4;
178 			Fractal->r_mean = .5;
179 			Fractal->dr_mean = .4;
180 			Fractal->dr2_mean = .3;
181 			break;
182 
183 		case 5:
184 			Fractal->Depth = MAX_DEPTH_5;
185 			Fractal->r_mean = .5;
186 			Fractal->dr_mean = .4;
187 			Fractal->dr2_mean = .3;
188 			break;
189 
190 		default:
191 		case 2:
192 			Fractal->Depth = fAdditive ? MAX_DEPTH_2 + 1 : MAX_DEPTH_2;
193 			Fractal->r_mean = .7;
194 			Fractal->dr_mean = .3;
195 			Fractal->dr2_mean = .4;
196 			break;
197 	}
198 	// fprintf( stderr, "N=%d\n", i );
199 	Fractal->Nb_Simi = i;
200 	Fractal->Max_Pt = Fractal->Nb_Simi - 1;
201 	for (i = 0; i <= Fractal->Depth + 2; ++i)
202 		Fractal->Max_Pt *= Fractal->Nb_Simi;
203 
204 	if ((Fractal->buffer1 = (Point *) calloc(Fractal->Max_Pt,
205 			sizeof (Point))) == NULL) {
206 		_FreeIFS(Fractal);
207 		return;
208 	}
209 	if ((Fractal->buffer2 = (Point *) calloc(Fractal->Max_Pt,
210 			sizeof (Point))) == NULL) {
211 		_FreeIFS(Fractal);
212 		return;
213 	}
214 	Fractal->Speed = 6;
215 #if HALF
216 	Fractal->Width = bounds.IntegerWidth() / 2 + 1;
217 	Fractal->Height = bounds.IntegerHeight() / 2 + 1;
218 #else
219 	Fractal->Width = bounds.IntegerWidth() + 1;
220 	Fractal->Height = bounds.IntegerHeight() + 1;
221 #endif
222 	Fractal->Cur_Pt = 0;
223 	Fractal->Count = 0;
224 	Fractal->Lx = (Fractal->Width - 1) / 2;
225 	Fractal->Ly = (Fractal->Height - 1) / 2;
226 	Fractal->Col = NRAND(Fractal->Width * Fractal->Height - 1) + 1;
227 
228 	_RandomSimis(Fractal, Fractal->Components, 5 * MAX_SIMI);
229 
230 	delete Fractal->bitmap;
231 	Fractal->bitmap = new (nothrow) BBitmap(BRect(0.0, 0.0,
232 											Fractal->Width - 1,
233 											Fractal->Height - 1),
234 											0,
235 											B_RGB32);
236 	delete Fractal->markBitmap;
237 	Fractal->markBitmap = new (nothrow) BBitmap(BRect(0.0, 0.0,
238 												Fractal->Width - 1,
239 												Fractal->Height - 1),
240 												0,
241 												B_GRAY8);
242 	// Allocation checked
243 	if (Fractal->bitmap != NULL && Fractal->bitmap->IsValid()) {
244 		memset(Fractal->bitmap->Bits(), 0, Fractal->bitmap->BitsLength());
245 	} else {
246 		delete Fractal->bitmap;
247 		Fractal->bitmap = NULL;
248 	}
249 	if (Fractal->markBitmap != NULL && Fractal->markBitmap->IsValid()) {
250 		memset(Fractal->markBitmap->Bits(), 0, Fractal->markBitmap->BitsLength());
251 	} else {
252 		delete Fractal->markBitmap;
253 		Fractal->markBitmap = NULL;
254 	}
255 }
256 
257 // destructor
258 IFS::~IFS()
259 {
260 	if (fRoot != NULL) {
261 		_FreeIFS(fRoot);
262 		free((void*) fRoot);
263 	}
264 }
265 
266 // Draw
267 void
268 IFS::Draw(BView* view, const buffer_info* info, int32 frames)
269 {
270 //bigtime_t now = system_time();
271 	int         i;
272 	float         u, uu, v, vv, u0, u1, u2, u3;
273 	SIMI       *S, *S1, *S2, *S3, *S4;
274 	FRACTAL    *F;
275 
276 	if (fRoot == NULL)
277 		return;
278 	F = fRoot;
279 	if (F->buffer1 == NULL)
280 		return;
281 
282 //if (frames > 1)
283 //	printf("skipping %ld frames\n", frames);
284 
285 	// do this as many times as necessary to calculate the missing frames
286 	// so the animation doesn't jerk when we miss a few frames
287 	for (int32 frame = 0; frame < frames; frame++) {
288 
289 		u = (float) (F->Count) * (float) (F->Speed) / 1000.0;
290 		uu = u * u;
291 		v = 1.0 - u;
292 		vv = v * v;
293 		u0 = vv * v;
294 		u1 = 3.0 * vv * u;
295 		u2 = 3.0 * v * uu;
296 		u3 = u * uu;
297 
298 		S = F->Components;
299 		S1 = S + F->Nb_Simi;
300 		S2 = S1 + F->Nb_Simi;
301 		S3 = S2 + F->Nb_Simi;
302 		S4 = S3 + F->Nb_Simi;
303 
304 		for (i = F->Nb_Simi; i; --i, S++, S1++, S2++, S3++, S4++) {
305 			S->c_x = u0 * S1->c_x + u1 * S2->c_x + u2 * S3->c_x + u3 * S4->c_x;
306 			S->c_y = u0 * S1->c_y + u1 * S2->c_y + u2 * S3->c_y + u3 * S4->c_y;
307 			S->r = u0 * S1->r + u1 * S2->r + u2 * S3->r + u3 * S4->r;
308 			S->r2 = u0 * S1->r2 + u1 * S2->r2 + u2 * S3->r2 + u3 * S4->r2;
309 			S->A = u0 * S1->A + u1 * S2->A + u2 * S3->A + u3 * S4->A;
310 			S->A2 = u0 * S1->A2 + u1 * S2->A2 + u2 * S3->A2 + u3 * S4->A2;
311 		}
312 
313 //bigtime_t beforeDraw = system_time();
314 		if (frame == frames - 1)
315 			_DrawFractal(view, info);
316 
317 //bigtime_t draw = system_time() - beforeDraw;
318 
319 		if (F->Count >= 1000 / F->Speed) {
320 			S = F->Components;
321 			S1 = S + F->Nb_Simi;
322 			S2 = S1 + F->Nb_Simi;
323 			S3 = S2 + F->Nb_Simi;
324 			S4 = S3 + F->Nb_Simi;
325 
326 			for (i = F->Nb_Simi; i; --i, S++, S1++, S2++, S3++, S4++) {
327 				S2->c_x = 2.0 * S4->c_x - S3->c_x;
328 				S2->c_y = 2.0 * S4->c_y - S3->c_y;
329 				S2->r = 2.0 * S4->r - S3->r;
330 				S2->r2 = 2.0 * S4->r2 - S3->r2;
331 				S2->A = 2.0 * S4->A - S3->A;
332 				S2->A2 = 2.0 * S4->A2 - S3->A2;
333 
334 				*S1 = *S4;
335 			}
336 			_RandomSimis(F, F->Components + 3 * F->Nb_Simi, F->Nb_Simi);
337 
338 			_RandomSimis(F, F->Components + 4 * F->Nb_Simi, F->Nb_Simi);
339 
340 			F->Count = 0;
341 		} else
342 			F->Count++;
343 //		F->Col++;
344 //bigtime_t finish = (system_time() - now) - draw;
345 //if (info)
346 //printf("draw: %lld\nnon-draw: %lld\n\n", draw, finish);
347 	}
348 
349 }
350 
351 // SetAdditive
352 void
353 IFS::SetAdditive(bool additive)
354 {
355 	fAdditive = additive;
356 }
357 
358 // SetSpeed
359 void
360 IFS::SetSpeed(int32 speed)
361 {
362 	if (fRoot && speed > 0 && speed <= 12)
363 		fRoot->Speed = speed;
364 }
365 
366 // Draw
367 void
368 IFS::_DrawFractal(BView* view, const buffer_info* info)
369 {
370 	FRACTAL* F = fRoot;
371 	int i, j;
372 	int32 x, y, xo, yo;
373 	SIMI* Cur, *Simi;
374 
375 	for (Cur = F->Components, i = F->Nb_Simi; i; --i, Cur++) {
376 		Cur->Cx = FLOAT_TO_INT(Cur->c_x);
377 		Cur->Cy = FLOAT_TO_INT(Cur->c_y);
378 
379 		Cur->Ct = FLOAT_TO_INT(cos(Cur->A));
380 		Cur->St = FLOAT_TO_INT(sin(Cur->A));
381 		Cur->Ct2 = FLOAT_TO_INT(cos(Cur->A2));
382 		Cur->St2 = FLOAT_TO_INT(sin(Cur->A2));
383 
384 		Cur->R = FLOAT_TO_INT(Cur->r);
385 		Cur->R2 = FLOAT_TO_INT(Cur->r2);
386 	}
387 
388 
389 	fCurrentPoint = 0;
390 	fCurrentFractal = F;
391 	fPointBuffer = F->buffer2;
392 	for (Cur = F->Components, i = F->Nb_Simi; i; --i, Cur++) {
393 		xo = Cur->Cx;
394 		yo = Cur->Cy;
395 		for (Simi = F->Components, j = F->Nb_Simi; j; --j, Simi++) {
396 			if (Simi == Cur)
397 				continue;
398 			transform(Simi, xo, yo, &x, &y);
399 			_Trace(F, x, y);
400 		}
401 	}
402 
403 	if (F->bitmap != NULL && F->markBitmap != NULL) {
404 		uint8* bits = (uint8*)F->bitmap->Bits();
405 		uint32 bpr = F->bitmap->BytesPerRow();
406 		uint8* markBits = (uint8*)F->markBitmap->Bits();
407 		uint32 markBPR = F->markBitmap->BytesPerRow();
408 		int32 minX = F->Width;
409 		int32 minY = F->Height;
410 		int32 maxX = 0;
411 		int32 maxY = 0;
412 		// Erase previous dots from bitmap,
413 		// but only if we're not in BDirectWindow mode,
414 		// since the dots will have been erased already
415 		if (!info) {
416 			if (F->Cur_Pt) {
417 				for (int32 i = 0; i <  F->Cur_Pt; i++) {
418 					Point p = F->buffer1[i];
419 					if (p.x >= 0 && p.x < F->Width
420 						&& p.y >= 0 && p.y < F->Height) {
421 						int32 offset = bpr * p.y + p.x * 4;
422 						*(uint32*)&bits[offset] = 0;
423 						if (minX > p.x)
424 							minX = p.x;
425 						if (minY > p.y)
426 							minY = p.y;
427 						if (maxX < p.x)
428 							maxX = p.x;
429 						if (maxY < p.y)
430 							maxY = p.y;
431 					}
432 				}
433 			}
434 		}
435 		// draw the new dots into the bitmap
436 		if (fCurrentPoint) {
437 			if (info) {
438 				for (int32 i = 0; i <  fCurrentPoint; i++) {
439 					Point p = F->buffer2[i];
440 					if (p.x >= 0 && p.x < F->Width
441 						&& p.y >= 0 && p.y < F->Height) {
442 						int32 offset = bpr * p.y + p.x * 4;
443 						if (fAdditive) {
444 							if (bits[offset + 0] < 255) {
445 								bits[offset + 0] += 51;
446 								bits[offset + 1] += 51;
447 								bits[offset + 2] += 51;
448 							}
449 						} else {
450 							*(uint32*)&bits[offset] = 0xffffffff;
451 						}
452 					}
453 				}
454 			} else {
455 				// in this version, remember the bounds rectangle
456 				for (int32 i = 0; i <  fCurrentPoint; i++) {
457 					Point p = F->buffer2[i];
458 					if (p.x >= 0 && p.x < F->Width
459 						&& p.y >= 0 && p.y < F->Height) {
460 						int32 offset = bpr * p.y + p.x * 4;
461 						if (fAdditive) {
462 							if (bits[offset + 0] < 255) {
463 								bits[offset + 0] += 15;
464 								bits[offset + 1] += 15;
465 								bits[offset + 2] += 15;
466 							}
467 						} else {
468 							*(uint32*)&bits[offset] = 0xffffffff;
469 						}
470 						if (minX > p.x)
471 							minX = p.x;
472 						if (minY > p.y)
473 							minY = p.y;
474 						if (maxX < p.x)
475 							maxX = p.x;
476 						if (maxY < p.y)
477 							maxY = p.y;
478 					}
479 				}
480 			}
481 		}
482 		if (info && info->bits) {
483 
484 			uint8* screenBits = (uint8*)info->bits;
485 			uint32 screenBPR = info->bytesPerRow;
486 			int32 left = info->bounds.left;
487 			int32 top = info->bounds.top;
488 			int32 bpp = info->bits_per_pixel;
489 			screenBits += left * bpp + top * bpr;
490 
491 			int32 screenWidth = info->bounds.right - left;
492 			int32 screenHeight = info->bounds.bottom - top;
493 
494 //printf("using BDirectWindow (%p  %dx%d)\n", this, F->Width, F->Height);
495 			// redraw the previous points on screen
496 			// with the contents of the current bitmap
497 			//
498 			// draw the new points, erasing the bitmap as we go
499 			int32 maxPoints = max_c(F->Cur_Pt, fCurrentPoint);
500 			if (maxPoints > 0) {
501 
502 //				BScreen screen(B_MAIN_SCREEN_ID);
503 //				screen.WaitForRetrace();
504 
505 				for (int32 i = 0; i < maxPoints; i++) {
506 					// copy previous points (black)
507 					if (i < F->Cur_Pt) {
508 						Point p = F->buffer1[i];
509 						if (p.x >= 0 && p.x < F->Width && p.x < screenWidth
510 							&& p.y >= 0 && p.y < F->Height && p.y < screenHeight) {
511 							int32 markOffset = markBPR * p.y + p.x;
512 							if (markBits[markOffset] != fCurrentMarkValue) {
513 								int32 offset = bpr * p.y + p.x * 4;
514 								// copy the pixel to the screen
515 								uint32* src = (uint32*)&bits[offset];
516 								if (bpp == 32) {
517 									int32 screenOffset = screenBPR * p.y + p.x * 4;
518 									*(uint32*)&screenBits[screenOffset] = *src;
519 								} else if (bpp == 16) {
520 									int32 screenOffset = screenBPR * p.y + p.x * 2;
521 									*(uint16*)&screenBits[screenOffset] =
522 										(uint16)(((bits[offset + 2] & 0xf8) << 8) |
523 												 ((bits[offset + 1] & 0xfc) << 3) |
524 										  		  (bits[offset] >> 3));
525 								} else if (bpp == 15) {
526 									int32 screenOffset = screenBPR * p.y + p.x * 2;
527 									*(uint16*)&screenBits[screenOffset] =
528 										(uint16)(((bits[offset + 2] & 0xf8) << 7) |
529 												 ((bits[offset + 1] & 0xf8) << 2) |
530 										  		  (bits[offset] >> 3));
531 								} else if (bpp == 8) {
532 									int32 screenOffset = screenBPR * p.y + p.x;
533 									screenBits[screenOffset] = bits[offset];
534 								}
535 								*src = 0;
536 								markBits[markOffset] = fCurrentMarkValue;
537 							} // else it means the pixel has been copied already
538 						}
539 					}
540 					// copy current points (white) and erase them from the bitmap
541 					if (i < fCurrentPoint) {
542 						Point p = F->buffer2[i];
543 						if (p.x >= 0 && p.x < F->Width && p.x < screenWidth
544 							&& p.y >= 0 && p.y < F->Height && p.y < screenHeight) {
545 							int32 markOffset = markBPR * p.y + p.x;
546 							int32 offset = bpr * p.y + p.x * 4;
547 							// copy the pixel to the screen
548 							uint32* src = (uint32*)&bits[offset];
549 							if (markBits[markOffset] != fCurrentMarkValue) {
550 								if (bpp == 32) {
551 									int32 screenOffset = screenBPR * p.y + p.x * 4;
552 									*(uint32*)&screenBits[screenOffset] = *src;
553 								} else if (bpp == 16) {
554 									int32 screenOffset = screenBPR * p.y + p.x * 2;
555 									*(uint16*)&screenBits[screenOffset] =
556 										(uint16)(((bits[offset + 2] & 0xf8) << 8) |
557 												 ((bits[offset + 1] & 0xfc) << 3) |
558 										  		  (bits[offset] >> 3));
559 								} else if (bpp == 15) {
560 									int32 screenOffset = screenBPR * p.y + p.x * 2;
561 									*(uint16*)&screenBits[screenOffset] =
562 										(uint16)(((bits[offset + 2] & 0xf8) << 7) |
563 												 ((bits[offset + 1] & 0xf8) << 2) |
564 										  		  (bits[offset] >> 3));
565 								} else if (bpp == 1) {
566 									int32 screenOffset = screenBPR * p.y + p.x;
567 									screenBits[screenOffset] = bits[offset];
568 								}
569 								markBits[markOffset] = fCurrentMarkValue;
570 							} // else it means the pixel has been copied already
571 							*src = 0;
572 						}
573 					}
574 				}
575 			}
576 		} else {
577 //printf("using BView (%p  %dx%d)\n", this, F->Width, F->Height);
578 			// if not in BDirectWindow mode, draw the bitmap
579 			BRect b(minX, minY, maxX, maxY);
580 			view->DrawBitmapAsync(F->bitmap, b, b);
581 		}
582 	}
583 
584 	// flip buffers
585 	F->Cur_Pt = fCurrentPoint;
586 	fPointBuffer = F->buffer1;
587 	F->buffer1 = F->buffer2;
588 	F->buffer2 = fPointBuffer;
589 	if (fCurrentMarkValue == 255)
590 		fCurrentMarkValue = 0;
591 	else
592 		fCurrentMarkValue++;
593 }
594 
595 // _Trace
596 void
597 IFS::_Trace(FRACTAL* F, int32 xo, int32 yo)
598 {
599 	int32 x, y, i;
600 	SIMI* Cur;
601 
602 	Cur = fCurrentFractal->Components;
603 	for (i = fCurrentFractal->Nb_Simi; i; --i, Cur++) {
604 		transform(Cur, xo, yo, &x, &y);
605 		// fPointBuffer->x = F->Lx + (x * F->Lx / (UNIT * 2));
606 		// fPointBuffer->y = F->Ly - (y * F->Ly / (UNIT * 2));
607 		fPointBuffer->x = (UNIT * 2 + x) * F->Lx / (UNIT * 2);
608 		fPointBuffer->y = (UNIT * 2 - y) * F->Ly / (UNIT * 2);
609 		fPointBuffer++;
610 		fCurrentPoint++;
611 
612 		if (F->Depth && ((x - xo) >> 4) && ((y - yo) >> 4)) {
613 			F->Depth--;
614 			_Trace(F, x, y);
615 			F->Depth++;
616 		}
617 	}
618 }
619 
620 // _RandomSimis
621 void
622 IFS::_RandomSimis(FRACTAL* f, SIMI* cur, int i) const
623 {
624 	while (i--) {
625 		cur->c_x = gauss_rand(0.0, .8, 4.0);
626 		cur->c_y = gauss_rand(0.0, .8, 4.0);
627 		cur->r = gauss_rand(f->r_mean, f->dr_mean, 3.0);
628 		cur->r2 = half_gauss_rand(0.0,f->dr2_mean, 2.0);
629 		cur->A = gauss_rand(0.0, 360.0, 4.0) * (M_PI / 180.0);
630 		cur->A2 = gauss_rand(0.0, 360.0, 4.0) * (M_PI / 180.0);
631 		cur++;
632 	}
633 }
634 
635 // _FreeBuffers
636 void
637 IFS::_FreeBuffers(FRACTAL *f)
638 {
639 	if (f->buffer1) {
640 		free((void*) f->buffer1);
641 		f->buffer1 = (Point*)NULL;
642 	}
643 	if (f->buffer2) {
644 		free((void*) f->buffer2);
645 		f->buffer2 = (Point*)NULL;
646 	}
647 }
648 
649 // _FreeIFS
650 void
651 IFS::_FreeIFS(FRACTAL* f)
652 {
653 	_FreeBuffers(f);
654 	delete f->bitmap;
655 	f->bitmap = NULL;
656 	delete f->markBitmap;
657 	f->markBitmap = NULL;
658 }
659 
660 
661 
662