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