1//******************************************************************************
2//
3//	File:		tsb.cpp
4//
5//******************************************************************************
6
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.
10*/
11
12#include <Debug.h>
13#include <Window.h>
14
15#include <string.h>
16#include <math.h>
17#include <OS.h>
18#include <Screen.h>
19
20#include "tsb.h"
21
22#ifndef _INTERFACE_DEFS_H
23#include <InterfaceDefs.h>
24#endif
25
26/*------------------------------------------------------------*/
27
28TShowBit	*tsbb;
29
30/*------------------------------------------------------------*/
31long	niter = 256;
32/*------------------------------------------------------------*/
33
34uchar	palette[256];
35
36/*------------------------------------------------------------*/
37
38void	TShowBit::MouseDown(BPoint where)
39{
40	if (!this->Window()->IsActive()) {
41		this->Window()->Activate(TRUE);
42		this->Window()->UpdateIfNeeded();
43	}
44
45	if (busy)
46		return;
47
48	if ((modifiers() & B_SHIFT_KEY) == 0) {
49		change_selection(where.x, where.y);
50		if ((selection.bottom - selection.top) < 4)
51			return;
52	}
53	redraw_mand();
54}
55
56/*------------------------------------------------------------*/
57
58void	TShowBit::redraw_mand()
59{
60	double	px0;
61	double	py0;
62	double	scale0;
63
64	if (modifiers() & B_SHIFT_KEY) {
65		px -= (scale / 2.0);
66		py -= (scale / 2.0);
67		scale *= 2.0;
68	}
69	else {
70		px0 = px + (scale * (selection.left / (1.0*size_x)));
71		py0 = py + (scale * (selection.top / (1.0*size_x)));
72		scale0 = scale * ((selection.bottom-selection.top) / (1.0*size_x));
73
74		px = px0; py = py0; scale = scale0;
75	}
76	selection.Set(-1000, -1000, -1000, -1000);
77	mand(px, py, scale, scale);
78
79}
80
81/*------------------------------------------------------------*/
82
83void	TShowBit::set_iter(long it)
84{
85	if (it != iter) {
86		iter = it;
87		niter = it;
88		selection.Set(-1000, -1000, -1000, -1000);
89		mand(px, py, scale, scale);
90	}
91}
92
93/*------------------------------------------------------------*/
94
95void	TShowBit::set_palette(long code)
96{
97	rgb_color	c = {0, 0, 0, 255};
98	long		i;
99
100	BScreen screen( Window() );
101
102	if (code == 0) {
103		for (i = 0; i < 256; i++)
104			palette[i] = (i >> 1) & 0x1f;
105	}
106	if (code == 1) {
107		for (i = 0; i < 256; i++) {
108			c.red = i * 4;
109			c.green = i * 7;
110			c.blue = 256-(i - i * 5);
111			palette[i] = screen.IndexForColor(c);
112		}
113	}
114
115	if (code == 2) {
116		for (i = 0; i < 256; i++) {
117			c.red = (i * 7);
118			c.green = i/2;
119			c.blue = 256-(i * 3);
120			palette[i] = screen.IndexForColor(c);
121		}
122	}
123
124	if (code == 3) {
125		for (i = 0; i < 256; i++) {
126			c.red = 256-(i * 6);
127			c.green = (i * 7);
128			c.blue = 0;
129			palette[i] = screen.IndexForColor(c);
130		}
131	}
132	mand(px, py, scale, scale);
133}
134
135/*------------------------------------------------------------*/
136
137TShowBit::TShowBit(BRect r, uint32 resizeMask, uint32 flags) :
138	BView(r, "", resizeMask, flags | B_WILL_DRAW | B_PULSE_NEEDED)
139{
140	BRect	bitmap_r;
141	char	*bits;
142
143	busy = FALSE;
144	exit_now = FALSE;
145	tsbb = this;
146	bitmap_r.Set(0, 0, size_x - 1, size_y - 1);
147	selection.Set(-1000, -1000, -1000, -1000);
148	iter = 256;
149
150	the_bitmap = new BBitmap(bitmap_r, B_COLOR_8_BIT);
151	bits = (char *)the_bitmap->Bits();
152	memset(bits, 0x00, size_x*size_y);
153	px = -2.5;
154	py = -2.0;
155	scale = 4.0;
156	set_palette(2);
157}
158
159/*------------------------------------------------------------*/
160
161TShowBit::~TShowBit()
162{
163	delete	the_bitmap;
164}
165
166/*------------------------------------------------------------*/
167
168void	TShowBit::Draw(BRect update_rect)
169{
170	DrawBitmap(the_bitmap, BPoint(0, 0));
171}
172
173
174/*------------------------------------------------------------*/
175
176
177int iterate_double(double a, double b)
178{
179	double	x;
180	double	y;
181	double	xsq;
182	double	ysq;
183	double	ctwo = 2.0, cfour = 4.0;
184	int		i = 0, iter = niter;
185
186	x = 0.0;
187	y = 0.0;
188
189	while (i < iter) {
190		xsq = x * x;
191		ysq = y * y;
192		y = (ctwo * x * y) + b;
193		i++;
194		x = a + (xsq - ysq);
195
196		if ((xsq + ysq) > cfour)
197			return(i);
198	}
199	return(i);
200}
201
202/*------------------------------------------------------------*/
203//extern "C" int iterate(float a, float b);
204/*------------------------------------------------------------*/
205
206int iterate_float(float a, float b)
207{
208	float	x;
209	float	y;
210	float	xsq;
211	float	ysq;
212// These are variables, because the metaware compiler would reload the
213// constants from memory each time through the loop rather than leave them
214// in registers.  Lovely.
215	float	ctwo = 2.0, cfour = 4.0;
216	long	i;
217	int		iter = niter;
218
219	x = 0.0;
220	y = 0.0;
221	i = 0;
222
223	while (i < iter) {
224		xsq = x * x;
225		ysq = y * y;
226		y = (ctwo * x * y) + b;
227		i++;
228		x = a + (xsq - ysq);
229
230		if ((xsq + ysq) > cfour)
231			return(i);
232	}
233	return(i);
234}
235
236/*------------------------------------------------------------*/
237
238double	vvx;
239double	vvy;
240double	ssx;
241char	t1_done;
242char	t2_done;
243
244/*------------------------------------------------------------*/
245
246long	__calc1(void *arg)
247{
248	tsbb->manda(vvx, vvy, ssx, ssx);
249	return B_NO_ERROR;
250}
251
252/*------------------------------------------------------------*/
253
254long	__calc2(void *arg)
255{
256	tsbb->mandb(vvx, vvy, ssx, ssx);
257	return B_NO_ERROR;
258}
259
260/*------------------------------------------------------------*/
261
262uchar	tmp[256];
263uchar	pc[32][32];
264uchar	tmp1[256];
265
266/*------------------------------------------------------------*/
267
268void	TShowBit::mand(double vx, double vy, double sx, double sy)
269{
270	vvx = vx; vvy = vy; ssx = sx;
271	t1_done = 0; t2_done = 0;
272
273	precompute(vx, vy, sx, sy);
274
275	resume_thread(spawn_thread(__calc1, "calc1", B_NORMAL_PRIORITY, NULL));
276	resume_thread(spawn_thread(__calc2, "calc2", B_NORMAL_PRIORITY, NULL));
277	busy = TRUE;
278}
279
280/*------------------------------------------------------------*/
281
282void	TShowBit::Pulse()
283{
284//	PRINT(("pulsing (%d)\n", busy));
285	if (busy) {
286		Draw(BRect(0,0,0,0));
287		if (t1_done && t2_done) {
288			busy = FALSE;
289			exit_now = FALSE;
290		}
291	}
292}
293
294/*------------------------------------------------------------*/
295
296void	TShowBit::precompute(double vx, double vy, double sx, double sy)
297{
298	long	x, y;
299	double	cx, cy;
300	double	scale = sx;
301
302	sx = sx / (32.0);
303	sy = sy / (32.0);
304	cy = vy;
305
306	for (y = 0; y < 32; y++) {
307		cy += sy;
308		cx = vx;
309		if (scale < 0.000025 || niter != 256) {
310			for (x = 0; x < 32; x++) {
311				cx += sx;
312				pc[x][y] = iterate_double(cx, cy);
313			}
314		}
315		else
316		for (x = 0; x < 32; x++) {
317			cx += sx;
318			pc[x][y] = iterate_float(cx, cy);
319		}
320	}
321}
322
323/*------------------------------------------------------------*/
324
325void	TShowBit::mandb(double vx, double vy, double sx, double sy)
326{
327	long	x, y;
328	long	bx;
329	double	cx, cy;
330	int		v;
331	uchar	*bits = (uchar *)the_bitmap->Bits();
332	uchar	*b0;
333	long	y12;
334	long	x12;
335	double	scale = sx;
336
337	sx = sx / (size_x * 1.0);
338	sy = sy / (size_y * 1.0);
339	cy = vy;
340
341	cy += sy;
342	sy *= 2.0;
343	for (y = 1; y < size_y; y+=2) {
344		y12 = y / 12;
345		cy += sy;
346		cx = vx;
347		b0 = bits + (y * size_x);
348		for (bx = 0; bx < size_x; bx += 12) {
349			x12 = (bx+6) / 12;
350			v = pc[x12][y12];
351
352			if (exit_now)
353				goto done;
354
355			if (v == pc[x12+1][y12] &&
356			    v == pc[x12][y12+1] &&
357				v == pc[x12-1][y12] &&
358				v == pc[x12][y12-1] &&
359				v == pc[x12-2][y12]) {
360				for (x = bx; x < (bx+12); x++) {
361					cx += sx;
362					*b0++ = palette[v];
363				}
364			}
365			else {
366				if (scale < 0.000025 || niter != 256) {
367					for (x = bx; x < (bx+12); x++) {
368						cx += sx;
369						v = iterate_double(cx, cy);
370						*b0++ = palette[v];
371					}
372				}
373				else
374				for (x = bx; x < (bx+12); x++) {
375					cx += sx;
376					v = iterate_float(cx, cy);
377					*b0++ = palette[v];
378				}
379			}
380		}
381	}
382done:
383	t2_done = 1;
384}
385
386/*------------------------------------------------------------*/
387
388void	TShowBit::manda(double vx, double vy, double sx, double sy)
389{
390	long	x, y;
391	long	bx;
392	double	cx, cy;
393	int		v;
394	uchar	*bits = (uchar *)the_bitmap->Bits();
395	uchar	*b0;
396	long	y12;
397	long	x12;
398	double	scale = sx;
399
400	sx = sx / (size_x * 1.0);
401	sy = sy / (size_y * 1.0);
402	cy = vy;
403
404	sy *= 2.0;
405	for (y = 0; y < size_y; y+=2) {
406		y12 = y / 12;
407		cy += sy;
408		cx = vx;
409		b0 = bits + (y * size_x);
410		for (bx = 0; bx < size_x; bx += 12) {
411			x12 = (bx+6) / 12;
412			v = pc[x12][y12];
413
414			if (exit_now)
415				goto done;
416
417			if (v == pc[x12+1][y12] &&
418			    v == pc[x12][y12+1] &&
419				v == pc[x12-1][y12] &&
420				v == pc[x12][y12-1] &&
421				v == pc[x12-2][y12]) {
422				for (x = bx; x < (bx+12); x++) {
423					cx += sx;
424					*b0++ = palette[v];
425				}
426			}
427			else {
428				if (scale < 0.000025 || niter != 256) {
429					for (x = bx; x < (bx+12); x++) {
430						cx += sx;
431						v = iterate_double(cx, cy);
432						*b0++ = palette[v];
433					}
434				}
435				else
436				for (x = bx; x < (bx+12); x++) {
437					cx += sx;
438					v = iterate_float(cx, cy);
439					*b0++ = palette[v];
440				}
441			}
442		}
443	}
444done:
445	t1_done = 1;
446}
447
448
449/*------------------------------------------------------------*/
450
451long	TShowBit::limit_v(long v)
452{
453	if (v > (size_y - 1))
454			v = (size_y - 1);
455
456	if (v < 0)
457			v = 0;
458	return(v);
459}
460
461/*------------------------------------------------------------*/
462
463long	TShowBit::limit_h(long v)
464{
465	if (v > (size_x - 1))
466			v = size_x - 1;
467
468	if (v < 0)
469			v = 0;
470	return(v);
471}
472
473/*------------------------------------------------------------*/
474
475BRect	TShowBit::sort_rect(BRect *aRect)
476{
477	BRect	tmp_rect;
478	long	tmp;
479
480	tmp_rect = *aRect;
481	if (tmp_rect.bottom < tmp_rect.top) {
482		tmp = (long)tmp_rect.top;
483		tmp_rect.top = tmp_rect.bottom;
484		tmp_rect.bottom = tmp;
485	}
486
487	if (tmp_rect.left > tmp_rect.right) {
488		tmp = (long) tmp_rect.right;
489		tmp_rect.right = tmp_rect.left;
490		tmp_rect.left = tmp;
491	}
492
493	tmp_rect.top = limit_v(tmp_rect.top);
494	tmp_rect.left = limit_h(tmp_rect.left);
495	tmp_rect.bottom = limit_v(tmp_rect.bottom);
496	tmp_rect.right = limit_h(tmp_rect.right);
497
498	return(tmp_rect);
499}
500
501/*------------------------------------------------------------*/
502
503void	TShowBit::clip(long *h, long *v)
504{
505	if (*h > (size_x - 1))
506			*h = (size_x - 1);
507	if (*h < 0)
508			*h = 0;
509	if (*v > (size_y - 1))
510			*v = size_y - 1;
511	if (*v < 0)
512			*v = 0;
513}
514
515/*------------------------------------------------------------*/
516
517char	TShowBit::has_selection()
518{
519	if (((selection.bottom - selection.top) + (selection.right - selection.left)) < 5)
520		return 0;
521	else
522		return 1;
523}
524
525/*------------------------------------------------------------*/
526
527void	TShowBit::change_selection(long h, long v)
528{
529	ulong	buttons;
530	long	h0;
531	long	v0;
532	BRect	new_select;
533	BRect	old_select;
534	BRect	tmp_rect;
535	long	max;
536	long	width, height;
537
538	clip(&h, &v);
539	new_select.top = v;
540	new_select.left = h;
541	old_select = selection;
542
543	SetDrawingMode(B_OP_INVERT);
544
545	do {
546		BPoint where;
547		GetMouse(&where, &buttons);
548		h0 = (long) where.x;
549		v0 = (long) where.y;
550		width = h0 - h;
551		height = v0 - v;
552		max= ((v0>v) ^ (height < width)) ? height : width;
553
554		h0 = h+max; v0 = v+max;
555
556		clip(&h0, &v0);
557		new_select.right = h0;
558		new_select.bottom = v0;
559
560		if ((old_select.top != new_select.top) ||
561		    (old_select.bottom != new_select.bottom) ||
562		    (old_select.right != new_select.right) ||
563		    (old_select.left != new_select.left)) {
564
565			tmp_rect = sort_rect(&new_select);
566			StrokeRect(tmp_rect);
567
568			tmp_rect = sort_rect(&old_select);
569			StrokeRect(tmp_rect);
570
571			old_select = new_select;
572			Flush();
573		}
574
575		snooze(20000);
576	} while(buttons);
577
578	selection = sort_rect(&new_select);
579	if (!has_selection()) {
580		StrokeRect(selection);
581		selection.Set(-1000, -1000, -1000, -1000);
582	}
583	SetDrawingMode(B_OP_COPY);
584}
585