BPicture: Fix archive constructor.
[haiku.git] / src / apps / mandelbrot / tsb.cpp
blob0146990d3109fee94db24030d3c7e935cd0b9b75
1 //******************************************************************************
2 //
3 // File: tsb.cpp
4 //
5 //******************************************************************************
7 /*
8 Copyright 1993-1999, Be Incorporated. All Rights Reserved.
9 This file may be used under the terms of the Be Sample Code License.
12 #include <Debug.h>
13 #include <Window.h>
15 #include <algorithm>
16 #include <string.h>
17 #include <math.h>
18 #include <OS.h>
19 #include <Screen.h>
21 #include "tsb.h"
23 #ifndef _INTERFACE_DEFS_H
24 #include <InterfaceDefs.h>
25 #endif
27 /*------------------------------------------------------------*/
29 static TShowBit *tsbb;
30 static long niter = 256;
31 static uchar palette[256];
34 void TShowBit::MouseDown(BPoint where)
36 if (!this->Window()->IsActive()) {
37 this->Window()->Activate(TRUE);
38 this->Window()->UpdateIfNeeded();
41 if (busy)
42 return;
44 if ((modifiers() & B_SHIFT_KEY) == 0) {
45 change_selection(where.x, where.y);
46 if ((selection.bottom - selection.top) < 4)
47 return;
49 redraw_mand();
53 void
54 TShowBit::MessageReceived(BMessage* message)
56 switch(message->what) {
57 case B_MOUSE_WHEEL_CHANGED:
59 //float factor = 1;
60 float change = message->FindFloat("be:wheel_delta_y");
61 BPoint where;
62 GetMouse(&where, 0, 0);
64 selection = Bounds();
66 if (change < 0) {
67 // zoom in
68 selection.top = (where.y + selection.top) / 2;
69 selection.bottom = (where.y + selection.bottom) / 2;
70 selection.left = (where.x + selection.left) / 2;
71 selection.right = (where.x + selection.right) / 2;
72 } else {
73 // zoom out
74 selection.top = - where.y + selection.top * 2;
75 selection.bottom = - where.y + selection.bottom * 2;
76 selection.left = - where.x + selection.left * 2;
77 selection.right = - where.x + selection.right * 2;
79 redraw_mand();
80 break;
82 default:
83 BView::MessageReceived(message);
88 void TShowBit::redraw_mand()
90 double px0;
91 double py0;
92 double scale0;
94 if (modifiers() & B_SHIFT_KEY) {
95 px -= (scale / 2.0);
96 py -= (scale / 2.0);
97 scale *= 2.0;
98 } else {
99 px0 = px + (scale * (selection.left / (1.0*size_x)));
100 py0 = py + (scale * (selection.top / (1.0*size_x)));
101 scale0 = scale * ((selection.bottom-selection.top) / (1.0*size_x));
103 px = px0; py = py0; scale = scale0;
105 selection.Set(-1000, -1000, -1000, -1000);
106 mand(px, py, scale, scale);
110 /*------------------------------------------------------------*/
112 void TShowBit::set_iter(long it)
114 if (it != iter) {
115 iter = it;
116 niter = it;
117 selection.Set(-1000, -1000, -1000, -1000);
118 mand(px, py, scale, scale);
122 /*------------------------------------------------------------*/
124 void TShowBit::set_palette(long code)
126 rgb_color c = {0, 0, 0, 255};
127 long i;
129 BScreen screen( Window() );
131 if (code == 0) {
132 for (i = 0; i < 256; i++)
133 palette[i] = (i >> 1) & 0x1f;
135 if (code == 1) {
136 for (i = 0; i < 256; i++) {
137 c.red = i * 4;
138 c.green = i * 7;
139 c.blue = 256-(i - i * 5);
140 palette[i] = screen.IndexForColor(c);
144 if (code == 2) {
145 for (i = 0; i < 256; i++) {
146 c.red = (i * 7);
147 c.green = i/2;
148 c.blue = 256-(i * 3);
149 palette[i] = screen.IndexForColor(c);
153 if (code == 3) {
154 for (i = 0; i < 256; i++) {
155 c.red = 256-(i * 6);
156 c.green = (i * 7);
157 c.blue = 0;
158 palette[i] = screen.IndexForColor(c);
161 mand(px, py, scale, scale);
164 /*------------------------------------------------------------*/
166 TShowBit::TShowBit(BRect r, uint32 resizeMask, uint32 flags) :
167 BView(r, "", resizeMask, flags | B_WILL_DRAW | B_PULSE_NEEDED)
169 BRect bitmap_r;
170 char *bits;
172 busy = FALSE;
173 exit_now = FALSE;
174 tsbb = this;
175 bitmap_r.Set(0, 0, size_x - 1, size_y - 1);
176 selection.Set(-1000, -1000, -1000, -1000);
177 iter = 256;
179 the_bitmap = new BBitmap(bitmap_r, B_COLOR_8_BIT);
180 bits = (char *)the_bitmap->Bits();
181 memset(bits, 0x00, size_x*size_y);
182 px = -2.5;
183 py = -2.0;
184 scale = 4.0;
185 set_palette(2);
188 /*------------------------------------------------------------*/
190 TShowBit::~TShowBit()
192 delete the_bitmap;
195 /*------------------------------------------------------------*/
197 void TShowBit::Draw(BRect update_rect)
199 DrawBitmap(the_bitmap, BPoint(0, 0));
203 /*------------------------------------------------------------*/
206 int iterate_double(double a, double b)
208 double x;
209 double y;
210 double xsq;
211 double ysq;
212 int i = 0, iter = niter;
214 x = 0.0;
215 y = 0.0;
217 while (i < iter) {
218 xsq = x * x;
219 ysq = y * y;
220 y = (2.0 * x * y) + b;
221 i++;
222 x = a + (xsq - ysq);
224 if ((xsq + ysq) > 4.0)
225 return(i);
227 return(i);
230 /*------------------------------------------------------------*/
231 //extern "C" int iterate(float a, float b);
232 /*------------------------------------------------------------*/
234 int iterate_float(float a, float b)
236 float x;
237 float y;
238 float xsq;
239 float ysq;
240 long i;
241 int iter = niter;
243 x = 0.0;
244 y = 0.0;
245 i = 0;
247 while (i < iter) {
248 xsq = x * x;
249 ysq = y * y;
250 y = (2.0f * x * y) + b;
251 i++;
252 x = a + (xsq - ysq);
254 if ((xsq + ysq) > 4.0f)
255 return(i);
257 return(i);
260 /*------------------------------------------------------------*/
262 double vvx;
263 double vvy;
264 double ssx;
265 char t1_done;
266 char t2_done;
268 /*------------------------------------------------------------*/
270 int32 __calc1(void *arg)
272 tsbb->manda(vvx, vvy, ssx, ssx);
273 return B_NO_ERROR;
276 /*------------------------------------------------------------*/
278 int32 __calc2(void *arg)
280 tsbb->mandb(vvx, vvy, ssx, ssx);
281 return B_NO_ERROR;
284 /*------------------------------------------------------------*/
286 uchar tmp[256];
287 uchar pc[32][32];
288 uchar tmp1[256];
290 /*------------------------------------------------------------*/
292 void TShowBit::mand(double vx, double vy, double sx, double sy)
294 vvx = vx; vvy = vy; ssx = sx;
295 t1_done = 0; t2_done = 0;
297 precompute(vx, vy, sx, sy);
299 resume_thread(spawn_thread(__calc1, "calc1", B_NORMAL_PRIORITY, NULL));
300 resume_thread(spawn_thread(__calc2, "calc2", B_NORMAL_PRIORITY, NULL));
301 busy = TRUE;
304 /*------------------------------------------------------------*/
306 void TShowBit::Pulse()
308 // PRINT(("pulsing (%d)\n", busy));
309 if (busy) {
310 Draw(BRect(0,0,0,0));
311 if (t1_done && t2_done) {
312 busy = FALSE;
313 exit_now = FALSE;
318 /*------------------------------------------------------------*/
320 void TShowBit::precompute(double vx, double vy, double sx, double sy)
322 long x, y;
323 double cx, cy;
324 double scale = sx;
326 sx = sx / (32.0);
327 sy = sy / (32.0);
328 cy = vy;
330 for (y = 0; y < 32; y++) {
331 cy += sy;
332 cx = vx;
333 if (scale < 0.000025 || niter != 256) {
334 for (x = 0; x < 32; x++) {
335 cx += sx;
336 pc[x][y] = iterate_double(cx, cy);
339 else
340 for (x = 0; x < 32; x++) {
341 cx += sx;
342 pc[x][y] = iterate_float(cx, cy);
347 /*------------------------------------------------------------*/
349 void TShowBit::mandb(double vx, double vy, double sx, double sy)
351 long x, y;
352 long bx;
353 double cx, cy;
354 int v;
355 uchar *bits = (uchar *)the_bitmap->Bits();
356 uchar *b0;
357 long y12;
358 long x12;
359 double scale = sx;
361 sx = sx / (size_x * 1.0);
362 sy = sy / (size_y * 1.0);
363 cy = vy;
365 cy += sy;
366 sy *= 2.0;
367 for (y = 1; y < size_y; y+=2) {
368 y12 = y / 12;
369 cy += sy;
370 cx = vx;
371 b0 = bits + (y * size_x);
372 for (bx = 0; bx < size_x; bx += 12) {
373 x12 = (bx+6) / 12;
374 v = pc[x12][y12];
376 if (exit_now)
377 goto done;
379 if (v == pc[x12+1][y12] &&
380 v == pc[x12][y12+1] &&
381 v == pc[x12-1][y12] &&
382 v == pc[x12][y12-1] &&
383 v == pc[x12-2][y12]) {
384 for (x = bx; x < (bx+12); x++) {
385 cx += sx;
386 *b0++ = palette[v & 0xff];
389 else {
390 if (scale < 0.000025 || niter != 256) {
391 for (x = bx; x < (bx+12); x++) {
392 cx += sx;
393 v = iterate_double(cx, cy);
394 *b0++ = palette[v & 0xff];
397 else
398 for (x = bx; x < (bx+12); x++) {
399 cx += sx;
400 v = iterate_float(cx, cy);
401 *b0++ = palette[v & 0xff];
406 done:
407 t2_done = 1;
410 /*------------------------------------------------------------*/
412 void TShowBit::manda(double vx, double vy, double sx, double sy)
414 long x, y;
415 long bx;
416 double cx, cy;
417 int v;
418 uchar *bits = (uchar *)the_bitmap->Bits();
419 uchar *b0;
420 long y12;
421 long x12;
422 double scale = sx;
424 sx = sx / (size_x * 1.0);
425 sy = sy / (size_y * 1.0);
426 cy = vy;
428 sy *= 2.0;
429 for (y = 0; y < size_y; y+=2) {
430 y12 = y / 12;
431 cy += sy;
432 cx = vx;
433 b0 = bits + (y * size_x);
434 for (bx = 0; bx < size_x; bx += 12) {
435 x12 = (bx+6) / 12;
436 v = pc[x12][y12];
438 if (exit_now)
439 goto done;
441 if (v == pc[x12+1][y12] &&
442 v == pc[x12][y12+1] &&
443 v == pc[x12-1][y12] &&
444 v == pc[x12][y12-1] &&
445 v == pc[x12-2][y12]) {
446 for (x = bx; x < (bx+12); x++) {
447 cx += sx;
448 *b0++ = palette[v & 0xff];
451 else {
452 if (scale < 0.000025 || niter != 256) {
453 for (x = bx; x < (bx+12); x++) {
454 cx += sx;
455 v = iterate_double(cx, cy);
456 *b0++ = palette[v & 0xff];
459 else
460 for (x = bx; x < (bx+12); x++) {
461 cx += sx;
462 v = iterate_float(cx, cy);
463 *b0++ = palette[v & 0xff];
468 done:
469 t1_done = 1;
473 /*------------------------------------------------------------*/
475 long TShowBit::limit_v(long v)
477 if (v > (size_y - 1))
478 v = (size_y - 1);
480 if (v < 0)
481 v = 0;
482 return(v);
485 /*------------------------------------------------------------*/
487 long TShowBit::limit_h(long v)
489 if (v > (size_x - 1))
490 v = size_x - 1;
492 if (v < 0)
493 v = 0;
494 return(v);
497 /*------------------------------------------------------------*/
499 BRect TShowBit::sort_rect(BRect *aRect)
501 BRect tmp_rect;
502 long tmp;
504 tmp_rect = *aRect;
505 if (tmp_rect.bottom < tmp_rect.top) {
506 tmp = (long)tmp_rect.top;
507 tmp_rect.top = tmp_rect.bottom;
508 tmp_rect.bottom = tmp;
511 if (tmp_rect.left > tmp_rect.right) {
512 tmp = (long) tmp_rect.right;
513 tmp_rect.right = tmp_rect.left;
514 tmp_rect.left = tmp;
517 tmp_rect.top = limit_v(tmp_rect.top);
518 tmp_rect.left = limit_h(tmp_rect.left);
519 tmp_rect.bottom = limit_v(tmp_rect.bottom);
520 tmp_rect.right = limit_h(tmp_rect.right);
522 return(tmp_rect);
525 /*------------------------------------------------------------*/
527 void TShowBit::clip(long *h, long *v)
529 if (*h > (size_x - 1))
530 *h = (size_x - 1);
531 if (*h < 0)
532 *h = 0;
533 if (*v > (size_y - 1))
534 *v = size_y - 1;
535 if (*v < 0)
536 *v = 0;
539 /*------------------------------------------------------------*/
541 char TShowBit::has_selection()
543 if (((selection.bottom - selection.top) + (selection.right - selection.left)) < 5)
544 return 0;
545 else
546 return 1;
550 void TShowBit::change_selection(long h, long v)
552 uint32 buttons;
553 long h0;
554 long v0;
555 BRect new_select;
556 BRect old_select;
557 BRect tmp_rect;
558 long max;
559 long width, height;
561 clip(&h, &v);
562 new_select.top = v;
563 new_select.left = h;
564 old_select = selection;
566 SetDrawingMode(B_OP_INVERT);
568 do {
569 BPoint where;
570 GetMouse(&where, &buttons);
571 h0 = (long) where.x;
572 v0 = (long) where.y;
573 width = h0 - h;
574 height = v0 - v;
576 max = std::max(std::abs(height), std::abs(width));
578 v0 = (v0 > v) ? (v + max) : (v - max);
579 h0 = (h0 > h) ? (h + max) : (h - max);
581 clip(&h0, &v0);
582 new_select.right = h0;
583 new_select.bottom = v0;
585 if ((old_select.top != new_select.top)
586 || (old_select.bottom != new_select.bottom)
587 || (old_select.right != new_select.right)
588 || (old_select.left != new_select.left)) {
590 tmp_rect = sort_rect(&new_select);
591 StrokeRect(tmp_rect);
593 tmp_rect = sort_rect(&old_select);
594 StrokeRect(tmp_rect);
596 old_select = new_select;
597 Flush();
600 snooze(20000);
601 } while (buttons);
603 selection = sort_rect(&new_select);
604 if (!has_selection()) {
605 StrokeRect(selection);
606 selection.Set(-1000, -1000, -1000, -1000);
608 SetDrawingMode(B_OP_COPY);