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