1 /* 2 3 Copyright 1989, 1998 The Open Group 4 5 Permission to use, copy, modify, distribute, and sell this software and its 6 documentation for any purpose is hereby granted without fee, provided that 7 the above copyright notice appear in all copies and that both that 8 copyright notice and this permission notice appear in supporting 9 documentation. 10 11 The above copyright notice and this permission notice shall be included 12 in all copies or substantial portions of the Software. 13 14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 OTHER DEALINGS IN THE SOFTWARE. 21 22 Except as contained in this notice, the name of The Open Group shall 23 not be used in advertising or otherwise to promote the sale, use or 24 other dealings in this Software without prior written authorization 25 from The Open Group. 26 27 */ 28 29 /* 30 * Author: Davor Matic, MIT X Consortium 31 */ 32 33 #ifdef HAVE_CONFIG_H 34 # include "config.h" 35 #endif 36 37 #include <X11/IntrinsicP.h> 38 #include <X11/StringDefs.h> 39 #include <X11/Xfuncs.h> 40 #include "BitmapP.h" 41 #include "Bitmap.h" 42 #include "Requests.h" 43 44 #include <stdio.h> 45 #include <math.h> 46 47 #ifndef abs 48 #define abs(x) (((x) > 0) ? (x) : -(x)) 49 #endif 50 #define min(x, y) (((int)(x) < (int)(y)) ? (x) : (y)) 51 #define max(x, y) (((int)(x) > (int)(y)) ? (x) : (y)) 52 #ifndef rint 53 # if HAVE_LRINT 54 # define rint(x) lrint(x) 55 # else 56 # define rint(x) floor(x + 0.5) 57 # endif 58 #endif 59 60 #ifdef __clang__ 61 /* clang doesn't like (int)floor(d) */ 62 #pragma clang diagnostic push 63 #pragma clang diagnostic ignored "-Wbad-function-cast" 64 #endif 65 66 /*****************************************************************************\ 67 * Graphics * 68 \*****************************************************************************/ 69 70 #define GetBit(image, x, y)\ 71 ((bit)((*(image->data + (x) / 8 + (y) * image->bytes_per_line) &\ 72 (1 << ((x) & 7))) ? 1 : 0)) 73 74 #if 0 75 bit 76 BWGetBit(Widget w, Position x, Position y) 77 { 78 BitmapWidget BW = (BitmapWidget) w; 79 80 if (QueryInBitmap(BW, x, y)) 81 return GetBit(BW->bitmap.image, x, y); 82 else 83 return NotSet; 84 } 85 #endif 86 87 #define InvertBit(image, x, y)\ 88 (*(image->data + (x) / 8 + (y) * image->bytes_per_line) ^=\ 89 (bit) (1 << ((x) % 8))) 90 91 92 #define SetBit(image, x, y)\ 93 (*(image->data + (x) / 8 + (y) * image->bytes_per_line) |=\ 94 (bit) (1 << ((x) % 8))) 95 96 #define ClearBit(image, x, y)\ 97 (*(image->data + (x) / 8 + (y) * image->bytes_per_line) &=\ 98 (bit)~(1 << ((x) % 8))) 99 100 101 #define HighlightSquare(BW, x, y)\ 102 XFillRectangle(XtDisplay(BW), XtWindow(BW),\ 103 BW->bitmap.highlighting_gc,\ 104 InWindowX(BW, x), InWindowY(BW, y),\ 105 BW->bitmap.squareW, BW->bitmap.squareH) 106 /* 107 void 108 HighlightSquare(BitmapWidget BW, Position x, Position y) 109 { 110 XFillRectangle(XtDisplay(BW), XtWindow(BW), 111 BW->bitmap.highlighting_gc, 112 InWindowX(BW, x), InWindowY(BW, y), 113 BW->bitmap.squareW, BW->bitmap.squareH); 114 } 115 */ 116 117 #define DrawSquare(BW, x, y)\ 118 XFillRectangle(XtDisplay(BW), XtWindow(BW),\ 119 BW->bitmap.drawing_gc,\ 120 InWindowX(BW, x), InWindowY(BW, y),\ 121 BW->bitmap.squareW, BW->bitmap.squareH) 122 123 /* 124 void 125 DrawSquare(BitmapWidget BW, Position x, Position y) 126 { 127 XFillRectangle(XtDisplay(BW), XtWindow(BW), 128 BW->bitmap.drawing_gc, 129 InWindowX(BW, x), InWindowY(BW, y), 130 BW->bitmap.squareW, BW->bitmap.squareH); 131 } 132 */ 133 134 #define InvertPoint(BW, x, y)\ 135 {InvertBit(BW->bitmap.image, x, y); DrawSquare(BW, x, y);} 136 137 #define DrawPoint(BW, x, y, value)\ 138 if (GetBit(BW->bitmap.image, x, y) != value)\ 139 InvertPoint(BW, x, y) 140 141 void 142 BWDrawPoint(Widget w, Position x, Position y, bit value) 143 { 144 BitmapWidget BW = (BitmapWidget) w; 145 146 if (QueryInBitmap(BW, x, y)) { 147 if (value == Highlight) 148 HighlightSquare(BW, x, y); 149 else 150 DrawPoint(BW, x, y, value); 151 } 152 } 153 154 static XPoint * 155 HotSpotShape(BitmapWidget BW, Position x, Position y) 156 { 157 static XPoint points[5]; 158 159 points[0].x = InWindowX(BW, x); 160 points[0].y = InWindowY(BW, y + 1.0/2); 161 points[1].x = InWindowX(BW, x + 1.0/2); 162 points[1].y = InWindowY(BW, y + 1); 163 points[2].x = InWindowX(BW, x + 1); 164 points[2].y = InWindowY(BW, y + 1.0/2); 165 points[3].x = InWindowX(BW, x + 1.0/2); 166 points[3].y = InWindowY(BW, y); 167 points[4].x = InWindowX(BW, x); 168 points[4].y = InWindowY(BW, y + 1.0/2); 169 170 return points; 171 } 172 173 #define DrawHotSpot(BW, x, y)\ 174 XFillPolygon(XtDisplay(BW), XtWindow(BW), BW->bitmap.drawing_gc,\ 175 HotSpotShape(BW, x, y), 5, Convex, CoordModeOrigin) 176 177 #define HighlightHotSpot(BW, x, y)\ 178 XFillPolygon(XtDisplay(BW), XtWindow(BW), BW->bitmap.highlighting_gc,\ 179 HotSpotShape(BW, x, y), 5, Convex, CoordModeOrigin) 180 181 /* 182 XImage *CreateBitmapImage(); 183 void DestroyBitmapImage(); 184 */ 185 186 void 187 BWRedrawHotSpot(Widget w) 188 { 189 BitmapWidget BW = (BitmapWidget) w; 190 191 if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)) 192 DrawHotSpot(BW, BW->bitmap.hot.x, BW->bitmap.hot.y); 193 } 194 195 void 196 BWClearHotSpot(Widget w) 197 { 198 BitmapWidget BW = (BitmapWidget) w; 199 200 if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)) { 201 DrawHotSpot(BW, BW->bitmap.hot.x, BW->bitmap.hot.y); 202 BW->bitmap.hot.x = BW->bitmap.hot.y = NotSet; 203 } 204 } 205 206 void 207 BWDrawHotSpot(Widget w, Position x, Position y, int value) 208 { 209 BitmapWidget BW = (BitmapWidget) w; 210 211 if (QueryInBitmap(BW, x, y)) { 212 if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y) && 213 ((BW->bitmap.hot.x == x) && (BW->bitmap.hot.y == y))) { 214 if ((value == Clear) || (value == Invert)) { 215 BWClearHotSpot(w); 216 } 217 } 218 else 219 if ((value == Set) || (value == Invert)) { 220 BWClearHotSpot(w); 221 DrawHotSpot(BW, x, y); 222 BW->bitmap.hot.x = x; 223 BW->bitmap.hot.y = y; 224 } 225 226 if (value == Highlight) 227 HighlightHotSpot(BW, x, y); 228 } 229 } 230 231 void 232 BWSetHotSpot(Widget w, Position x, Position y) 233 { 234 if (QuerySet(x, y)) 235 BWDrawHotSpot(w, x, y, Set); 236 else 237 BWClearHotSpot(w); 238 } 239 240 /* high level procedures */ 241 242 void 243 BWRedrawSquares(Widget w, 244 Position x, Position y, 245 Dimension width, Dimension height) 246 { 247 BitmapWidget BW = (BitmapWidget) w; 248 Position from_x = InBitmapX(BW, x); 249 Position from_y = InBitmapY(BW, y); 250 Position to_x = InBitmapX(BW, x + width); 251 Position to_y = InBitmapY(BW, y + height); 252 253 QuerySwap(from_x, to_x); 254 QuerySwap(from_y, to_y); 255 from_x = max(0, from_x); 256 from_y = max(0, from_y); 257 to_x = min(BW->bitmap.image->width - 1, to_x); 258 to_y = min(BW->bitmap.image->height - 1, to_y); 259 260 for (x = from_x; x <= to_x; x++) 261 for (y = from_y; y <= to_y; y++) 262 if (GetBit(BW->bitmap.image, x, y)) DrawSquare(BW, x, y); 263 } 264 265 void 266 BWDrawGrid(Widget w, 267 Position from_x, Position from_y, 268 Position to_x, Position to_y) 269 { 270 BitmapWidget BW = (BitmapWidget) w; 271 int i; 272 273 QuerySwap(from_x, to_x); 274 QuerySwap(from_y, to_y); 275 from_x = max(0, from_x); 276 from_y = max(0, from_y); 277 to_x = min(BW->bitmap.image->width - 1, to_x); 278 to_y = min(BW->bitmap.image->height - 1, to_y); 279 280 for(i = from_x + (from_x == 0); i <= to_x; i++) 281 XDrawLine(XtDisplay(BW), XtWindow(BW), 282 BW->bitmap.frame_gc, 283 InWindowX(BW, i), InWindowY(BW, from_y), 284 InWindowX(BW, i), InWindowY(BW, to_y + 1)); 285 286 for(i = from_y + (from_y == 0); i <= to_y; i++) 287 XDrawLine(XtDisplay(BW), XtWindow(BW), 288 BW->bitmap.frame_gc, 289 InWindowX(BW, from_x), InWindowY(BW, i), 290 InWindowX(BW, to_x + 1), InWindowY(BW, i)); 291 } 292 293 294 void 295 BWRedrawGrid(Widget w, 296 Position x, Position y, 297 Dimension width, Dimension height) 298 { 299 BitmapWidget BW = (BitmapWidget) w; 300 Position from_x = InBitmapX(BW, x); 301 Position from_y = InBitmapY(BW, y); 302 Position to_x = InBitmapX(BW, x + width); 303 Position to_y = InBitmapY(BW, y + height); 304 305 if (BW->bitmap.grid) 306 BWDrawGrid(w, from_x, from_y, to_x, to_y); 307 } 308 309 void 310 BWDrawLine(Widget w, 311 Position from_x, Position from_y, 312 Position to_x, Position to_y, int value) 313 { 314 Position i; 315 register double x, y; 316 double dx, dy, delta; 317 318 dx = to_x - from_x; 319 dy = to_y - from_y; 320 x = from_x + 0.5; 321 y = from_y + 0.5; 322 delta = max(abs(dx), abs(dy)); 323 if (delta > 0) { 324 dx /= delta; 325 dy /= delta; 326 for(i = 0; i <= delta; i++) { 327 BWDrawPoint(w, (Position) x, (Position) y, value); 328 x += dx; 329 y += dy; 330 } 331 } 332 else 333 BWDrawPoint(w, from_x, from_y, value); 334 } 335 336 void 337 BWBlindLine(Widget w, 338 Position from_x, Position from_y, 339 Position to_x, Position to_y, int value) 340 { 341 Position i; 342 register double x, y; 343 double dx, dy, delta; 344 345 dx = to_x - from_x; 346 dy = to_y - from_y; 347 x = from_x + 0.5; 348 y = from_y + 0.5; 349 delta = max(abs(dx), abs(dy)); 350 if (delta > 0) { 351 dx /= delta; 352 dy /= delta; 353 x += dx; 354 y += dy; 355 for(i = 1; i <= delta; i++) { 356 BWDrawPoint(w, (Position) x, (Position) y, value); 357 x += dx; 358 y += dy; 359 } 360 } 361 else 362 BWDrawPoint(w, from_x, from_y, value); 363 } 364 365 void 366 BWDrawRectangle(Widget w, 367 Position from_x, Position from_y, 368 Position to_x, Position to_y, int value) 369 { 370 register Position i; 371 Dimension delta, width, height; 372 373 QuerySwap(from_x, to_x); 374 QuerySwap(from_y, to_y); 375 376 width = to_x - from_x; 377 height = to_y - from_y; 378 379 delta = max(width, height); 380 381 if (!QueryZero(width, height)) { 382 for (i = 0; (int)i < (int)delta; i++) { 383 if ((int)i < (int)width) { 384 BWDrawPoint(w, from_x + i, from_y, value); 385 BWDrawPoint(w, to_x - i, to_y, value); 386 } 387 if ((int)i < (int)height) { 388 BWDrawPoint(w, from_x, to_y - i, value); 389 BWDrawPoint(w, to_x, from_y + i, value); 390 } 391 } 392 } 393 else 394 BWDrawLine(w, 395 from_x, from_y, 396 to_x, to_y, value); 397 } 398 399 void 400 BWDrawFilledRectangle(Widget w, 401 Position from_x, Position from_y, 402 Position to_x, Position to_y, int value) 403 { 404 register Position x, y; 405 406 QuerySwap(from_x, to_x); 407 QuerySwap(from_y, to_y); 408 409 for (x = from_x; x <= to_x; x++) 410 for (y = from_y; y <= to_y; y++) 411 BWDrawPoint(w, x, y, value); 412 } 413 414 void 415 BWDrawCircle(Widget w, 416 Position origin_x, Position origin_y, 417 Position point_x, Position point_y, int value) 418 { 419 register Position i, delta; 420 Dimension dx, dy, half; 421 double radius; 422 423 dx = abs(point_x - origin_x); 424 dy = abs(point_y - origin_y); 425 radius = sqrt((double) ((int)dx * (int)dx + (int)dy * (int)dy)); 426 if (radius < 1.0) { 427 BWDrawPoint(w, origin_x, origin_y, value); 428 } 429 else { 430 delta =floor(radius); 431 BWDrawPoint(w, origin_x - delta, origin_y, value); 432 BWDrawPoint(w, origin_x + delta, origin_y, value); 433 BWDrawPoint(w, origin_x, origin_y - delta, value); 434 BWDrawPoint(w, origin_x, origin_y + delta, value); 435 } 436 half = radius / sqrt(2.0); 437 for(i = 1; (int)i <= (int)half; i++) { 438 delta = sqrt(radius * radius - i * i); 439 BWDrawPoint(w, origin_x - delta, origin_y - i, value); 440 BWDrawPoint(w, origin_x - delta, origin_y + i, value); 441 BWDrawPoint(w, origin_x + delta, origin_y - i, value); 442 BWDrawPoint(w, origin_x + delta, origin_y + i, value); 443 if (i != delta) { 444 BWDrawPoint(w, origin_x - i, origin_y - delta, value); 445 BWDrawPoint(w, origin_x - i, origin_y + delta, value); 446 BWDrawPoint(w, origin_x + i, origin_y - delta, value); 447 BWDrawPoint(w, origin_x + i, origin_y + delta, value); 448 } 449 } 450 } 451 452 void 453 BWDrawFilledCircle(Widget w, 454 Position origin_x, Position origin_y, 455 Position point_x, Position point_y, int value) 456 { 457 register Position i, j, delta, rad; 458 Dimension dx, dy; 459 double radius; 460 461 dx = abs(point_x - origin_x); 462 dy = abs(point_y - origin_y); 463 radius = sqrt((double) ((int)dx * (int)dx + (int)dy * (int)dy)); 464 rad=floor(radius); 465 for(j = origin_x - rad ; 466 j <= origin_x + rad; 467 j++) 468 BWDrawPoint(w, j, origin_y, value); 469 470 for(i = 1; i <= rad; i++) { 471 delta = sqrt(radius * radius - i * i); 472 for(j = origin_x - delta; j <= origin_x + delta; j++) { 473 BWDrawPoint(w, j, origin_y - i, value); 474 BWDrawPoint(w, j, origin_y + i, value); 475 } 476 } 477 } 478 479 #define QueryFlood(BW, x, y, value)\ 480 ((GetBit(BW->bitmap.image, x, y) !=\ 481 (value & 1)) && QueryInBitmap(BW, x, y)) 482 483 #define Flood(BW, x, y, value)\ 484 {if (value == Highlight) HighlightSquare(BW, x, y);\ 485 else InvertPoint(BW, x, y);} 486 487 /* 488 static void 489 FloodLoop(BitmapWidget BW, Position x, Position y, int value) 490 { 491 if (QueryFlood(BW, x, y, value)) { 492 Flood(BW, x, y, value); 493 FloodLoop(BW, x, y - 1, value); 494 FloodLoop(BW, x - 1, y, value); 495 FloodLoop(BW, x, y + 1, value); 496 FloodLoop(BW, x + 1, y, value); 497 } 498 } 499 */ 500 501 static void 502 FloodLoop(BitmapWidget BW, Position x, Position y, int value) 503 { 504 Position save_x, save_y, x_left, x_right; 505 506 if (QueryFlood(BW, x, y, value)) 507 Flood(BW, x, y, value) 508 509 510 save_x = x; 511 save_y = y; 512 513 x++; 514 while (QueryFlood(BW, x, y, value)) { 515 Flood(BW, x, y, value); 516 x++; 517 } 518 x_right = --x; 519 520 x = save_x; 521 x--; 522 while (QueryFlood(BW, x, y, value)) { 523 Flood(BW, x, y, value); 524 x--; 525 } 526 x_left = ++x; 527 528 529 x = x_left; 530 y = save_y; 531 y++; 532 533 while (x <= x_right) { 534 Boolean flag = False; 535 Position x_enter; 536 537 while (QueryFlood(BW, x, y, value) && (x <= x_right)) { 538 flag = True; 539 x++; 540 } 541 542 if (flag) { 543 if ((x == x_right) && QueryFlood(BW, x, y, value)) 544 FloodLoop(BW, x, y, value); 545 else 546 FloodLoop(BW, x - 1, y, value); 547 } 548 549 x_enter = x; 550 551 while (!QueryFlood(BW, x, y, value) && (x < x_right)) 552 x++; 553 554 if (x == x_enter) x++; 555 } 556 557 x = x_left; 558 y = save_y; 559 y--; 560 561 while (x <= x_right) { 562 Boolean flag = False; 563 Position x_enter; 564 565 while (QueryFlood(BW, x, y, value) && (x <= x_right)) { 566 flag = True; 567 x++; 568 } 569 570 if (flag) { 571 if ((x == x_right) && QueryFlood(BW, x, y, value)) 572 FloodLoop(BW, x, y, value); 573 else 574 FloodLoop(BW, x - 1, y, value); 575 } 576 577 x_enter = x; 578 579 while (!QueryFlood(BW, x, y, value) && (x < x_right)) 580 x++; 581 582 if (x == x_enter) x++; 583 } 584 } 585 586 void 587 BWFloodFill(Widget w, Position x, Position y, int value) 588 { 589 BitmapWidget BW = (BitmapWidget) w; 590 int pixel; 591 592 pixel = GetBit(BW->bitmap.image, x, y); 593 594 if (value == Invert) 595 FloodLoop(BW, x, y, (pixel ? Clear : Set)); 596 else if (value != pixel) 597 FloodLoop(BW, x, y, value); 598 } 599 600 #define QueryHotInMark(BW)\ 601 ((BW->bitmap.hot.x == max(BW->bitmap.mark.from_x,\ 602 min(BW->bitmap.hot.x, BW->bitmap.mark.to_x)))\ 603 &&\ 604 (BW->bitmap.hot.y == max(BW->bitmap.mark.from_y,\ 605 min(BW->bitmap.hot.y, BW->bitmap.mark.to_y)))) 606 607 void 608 BWUpAction(Widget w, _X_UNUSED XEvent *event, 609 _X_UNUSED String *params, _X_UNUSED Cardinal *num_params) 610 { 611 BWUp(w); 612 } 613 614 void 615 BWUp(Widget w) 616 { 617 BitmapWidget BW = (BitmapWidget) w; 618 register Position x, y; 619 bit first, up, down=0; 620 Position from_x, from_y, to_x, to_y; 621 622 if (BWQueryMarked(w)) { 623 from_x = BW->bitmap.mark.from_x; 624 from_y = BW->bitmap.mark.from_y; 625 to_x = BW->bitmap.mark.to_x; 626 to_y = BW->bitmap.mark.to_y; 627 } 628 else { 629 from_x = 0; 630 from_y = 0; 631 to_x = BW->bitmap.width - 1; 632 to_y = BW->bitmap.height - 1; 633 } 634 635 if ((to_y - from_y) == 0) 636 return; 637 638 for(x = from_x; x <= to_x; x++) { 639 first = up = GetBit(BW->bitmap.image, x, to_y); 640 for(y = to_y - 1; y >= from_y; y--) { 641 down = GetBit(BW->bitmap.image, x, y); 642 if (up != down) 643 InvertPoint(BW, x, y); 644 up =down; 645 } 646 if(first != down) 647 InvertPoint(BW, x, to_y); 648 } 649 650 if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y) 651 && 652 !BWQueryMarked(w)) 653 BWSetHotSpot(w, 654 BW->bitmap.hot.x, 655 (BW->bitmap.hot.y - 1 + BW->bitmap.image->height) % 656 BW->bitmap.image->height); 657 658 } 659 660 void 661 BWDownAction(Widget w, _X_UNUSED XEvent *event, 662 _X_UNUSED String *params, _X_UNUSED Cardinal *num_params) 663 { 664 BWDown(w); 665 } 666 667 void 668 BWDown(Widget w) 669 { 670 BitmapWidget BW = (BitmapWidget) w; 671 register Position x, y; 672 bit first, down, up=0; 673 Position from_x, from_y, to_x, to_y; 674 675 if (BWQueryMarked(w)) { 676 from_x = BW->bitmap.mark.from_x; 677 from_y = BW->bitmap.mark.from_y; 678 to_x = BW->bitmap.mark.to_x; 679 to_y = BW->bitmap.mark.to_y; 680 } 681 else { 682 from_x = 0; 683 from_y = 0; 684 to_x = BW->bitmap.width - 1; 685 to_y = BW->bitmap.height - 1; 686 } 687 688 if ((to_y - from_y) == 0) 689 return; 690 691 for(x = from_x; x <= to_x; x++) { 692 first = down = GetBit(BW->bitmap.image, x, from_y); 693 for(y = from_y + 1; y <= to_y; y++) { 694 up = GetBit(BW->bitmap.image, x, y); 695 if (down != up) 696 InvertPoint(BW, x, y); 697 down = up; 698 } 699 if(first != up) 700 InvertPoint(BW, x, from_y); 701 } 702 703 if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y) 704 && 705 !BWQueryMarked(w)) 706 BWSetHotSpot(w, 707 BW->bitmap.hot.x, 708 (BW->bitmap.hot.y + 1) % BW->bitmap.image->height); 709 } 710 711 void 712 BWLeftAction(Widget w, _X_UNUSED XEvent *event, 713 _X_UNUSED String *params, _X_UNUSED Cardinal *num_params) 714 { 715 BWLeft(w); 716 } 717 718 void 719 BWLeft(Widget w) 720 { 721 BitmapWidget BW = (BitmapWidget) w; 722 register Position x, y; 723 bit first, left, right=0; 724 Position from_x, from_y, to_x, to_y; 725 726 if (BWQueryMarked(w)) { 727 from_x = BW->bitmap.mark.from_x; 728 from_y = BW->bitmap.mark.from_y; 729 to_x = BW->bitmap.mark.to_x; 730 to_y = BW->bitmap.mark.to_y; 731 } 732 else { 733 from_x = 0; 734 from_y = 0; 735 to_x = BW->bitmap.width - 1; 736 to_y = BW->bitmap.height - 1; 737 } 738 739 if ((to_x - from_x) == 0) 740 return; 741 742 for(y = from_y; y <= to_y; y++) { 743 first = left = GetBit(BW->bitmap.image, to_x, y); 744 for(x = to_x - 1; x >= from_x; x--) { 745 right = GetBit(BW->bitmap.image, x, y); 746 if (left != right) 747 InvertPoint(BW, x, y); 748 left = right; 749 } 750 if(first != right) 751 InvertPoint(BW, to_x, y); 752 } 753 754 if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y) 755 && 756 !BWQueryMarked(w)) 757 BWSetHotSpot(w, 758 (BW->bitmap.hot.x - 1 + BW->bitmap.image->width) % 759 BW->bitmap.image->width, 760 BW->bitmap.hot.y); 761 } 762 763 void 764 BWRightAction(Widget w, _X_UNUSED XEvent *event, 765 _X_UNUSED String *params, _X_UNUSED Cardinal *num_params) 766 { 767 BWRight(w); 768 } 769 770 void 771 BWRight(Widget w) 772 { 773 BitmapWidget BW = (BitmapWidget) w; 774 register Position x, y; 775 bit first, right, left=0; 776 Position from_x, from_y, to_x, to_y; 777 778 if (BWQueryMarked(w)) { 779 from_x = BW->bitmap.mark.from_x; 780 from_y = BW->bitmap.mark.from_y; 781 to_x = BW->bitmap.mark.to_x; 782 to_y = BW->bitmap.mark.to_y; 783 } 784 else { 785 from_x = 0; 786 from_y = 0; 787 to_x = BW->bitmap.width - 1; 788 to_y = BW->bitmap.height - 1; 789 } 790 791 if ((to_x - from_x) == 0) 792 return; 793 794 for(y = from_y; y <= to_y; y++) { 795 first = right = GetBit(BW->bitmap.image, from_x, y); 796 for(x = from_x + 1; x <= to_x; x++) { 797 left = GetBit(BW->bitmap.image, x, y); 798 if (right != left) 799 InvertPoint(BW, x, y); 800 right = left; 801 } 802 if(first != left) 803 InvertPoint(BW, from_x, y); 804 } 805 806 if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y) 807 && 808 !BWQueryMarked(w)) 809 BWSetHotSpot(w, 810 (BW->bitmap.hot.x + 1) % BW->bitmap.image->width, 811 BW->bitmap.hot.y); 812 } 813 814 /* void TransferImageData(); */ 815 816 void 817 BWFoldAction(Widget w, _X_UNUSED XEvent *event, 818 _X_UNUSED String *params, _X_UNUSED Cardinal *num_params) 819 { 820 BWFold(w); 821 } 822 823 void 824 BWFold(Widget w) 825 { 826 BitmapWidget BW = (BitmapWidget) w; 827 Position x, y, new_x, new_y; 828 Dimension horiz, vert; 829 char *storage_data; 830 XImage *storage; 831 832 storage_data = CreateCleanData(Length(BW->bitmap.image->width, 833 BW->bitmap.image->height)); 834 835 storage = CreateBitmapImage(BW, storage_data, 836 (Dimension) BW->bitmap.image->width, 837 (Dimension) BW->bitmap.image->height); 838 839 TransferImageData(BW->bitmap.image, storage); 840 841 BW->bitmap.fold ^= True; 842 horiz = (BW->bitmap.image->width + BW->bitmap.fold) / 2; 843 vert = (BW->bitmap.image->height + BW->bitmap.fold) / 2; 844 845 for (x = 0; x < BW->bitmap.image->width; x++) 846 for (y = 0; y < BW->bitmap.image->height; y++) { 847 new_x = (int)(x + horiz) % (int)BW->bitmap.image->width; 848 new_y = (int)(y + vert) % (int)BW->bitmap.image->height; 849 if(GetBit(BW->bitmap.image, new_x, new_y) != 850 GetBit(storage, x, y)) 851 InvertPoint(BW, new_x, new_y); 852 } 853 854 DestroyBitmapImage(&storage); 855 856 if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)) 857 BWSetHotSpot(w, 858 (Position) 859 ((int)(BW->bitmap.hot.x+horiz) 860 %(int)BW->bitmap.image->width), 861 (Position) 862 ((int)(BW->bitmap.hot.y+vert) 863 %(int)BW->bitmap.image->height) 864 ); 865 } 866 867 868 void 869 BWClearAction(Widget w, _X_UNUSED XEvent *event, 870 _X_UNUSED String *params, _X_UNUSED Cardinal *num_params) 871 { 872 BWClear(w); 873 } 874 875 void 876 BWClear(Widget w) 877 { 878 BitmapWidget BW = (BitmapWidget) w; 879 register Position x, y; 880 int i, length; 881 882 length = Length(BW->bitmap.image->width, BW->bitmap.image->height); 883 884 for (x = 0; x < BW->bitmap.image->width; x++) 885 for (y = 0; y < BW->bitmap.image->height; y++) 886 if (GetBit(BW->bitmap.image, x, y)) 887 DrawSquare(BW, x, y); 888 889 for (i = 0; i < length; i++) 890 BW->bitmap.image->data[i] = 0; 891 892 } 893 894 void 895 BWSetAction(Widget w, _X_UNUSED XEvent *event, 896 _X_UNUSED String *params, _X_UNUSED Cardinal *num_params) 897 { 898 BWSet(w); 899 } 900 901 void 902 BWSet(Widget w) 903 { 904 BitmapWidget BW = (BitmapWidget) w; 905 register Position x, y; 906 int i, length; 907 908 length = Length(BW->bitmap.image->width, BW->bitmap.image->height); 909 910 for (x = 0; x < BW->bitmap.image->width; x++) 911 for (y = 0; y < BW->bitmap.image->height; y++) 912 if (!GetBit(BW->bitmap.image, x, y)) 913 DrawSquare(BW, x, y); 914 915 for (i = 0; i < length; i++) 916 BW->bitmap.image->data[i] = (char)255; 917 918 } 919 920 void 921 BWRedraw(Widget w, _X_UNUSED XEvent *event, 922 _X_UNUSED String *params, _X_UNUSED Cardinal *num_params) 923 { 924 BitmapWidget BW = (BitmapWidget) w; 925 926 XClearArea(XtDisplay(BW), XtWindow(BW), 927 0, 0, BW->core.width, BW->core.height, 928 True); 929 } 930 931 void 932 BWInvertAction(Widget w, _X_UNUSED XEvent *event, 933 _X_UNUSED String *params, _X_UNUSED Cardinal *num_params) 934 { 935 BWInvert(w); 936 } 937 938 void 939 BWInvert(Widget w) 940 { 941 BitmapWidget BW = (BitmapWidget) w; 942 int i, length; 943 944 length = Length(BW->bitmap.image->width, BW->bitmap.image->height); 945 946 XFillRectangle(XtDisplay(BW), XtWindow(BW), 947 BW->bitmap.drawing_gc, 948 InWindowX(BW, 0), InWindowY(BW, 0), 949 InWindowX(BW, BW->bitmap.image->width) - InWindowX(BW, 0), 950 InWindowY(BW, BW->bitmap.image->height) - InWindowY(BW, 0)); 951 952 for (i = 0; i < length; i++) 953 BW->bitmap.image->data[i] ^= 255; 954 } 955 956 void 957 BWFlipHorizAction(Widget w, _X_UNUSED XEvent *event, 958 _X_UNUSED String *params, _X_UNUSED Cardinal *num_params) 959 { 960 BWFlipHoriz(w); 961 } 962 963 void 964 BWFlipHoriz(Widget w) 965 { 966 BitmapWidget BW = (BitmapWidget) w; 967 register Position x, y; 968 Position from_x, from_y, to_x, to_y; 969 float half; 970 971 if (BWQueryMarked(w)) { 972 from_x = BW->bitmap.mark.from_x; 973 from_y = BW->bitmap.mark.from_y; 974 to_x = BW->bitmap.mark.to_x; 975 to_y = BW->bitmap.mark.to_y; 976 } 977 else { 978 from_x = 0; 979 from_y = 0; 980 to_x = BW->bitmap.width - 1; 981 to_y = BW->bitmap.height - 1; 982 } 983 half = (float) (to_y - from_y) / 2.0 + 0.5; 984 985 if (half == 0.0) 986 return; 987 988 for (x = from_x; x <= to_x; x++) 989 for (y = 0; y < half; y++) 990 if (GetBit(BW->bitmap.image, x, from_y + y) != 991 GetBit(BW->bitmap.image, x, to_y - y)) { 992 InvertPoint(BW, x, from_y + y); 993 InvertPoint(BW, x, to_y - y); 994 } 995 996 if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y) 997 && 998 !BWQueryMarked(w)) 999 BWSetHotSpot(w, 1000 BW->bitmap.hot.x, 1001 BW->bitmap.image->height - 1 - BW->bitmap.hot.y); 1002 } 1003 1004 void 1005 BWFlipVertAction(Widget w, _X_UNUSED XEvent *event, 1006 _X_UNUSED String *params, _X_UNUSED Cardinal *num_params) 1007 { 1008 BWFlipVert(w); 1009 } 1010 1011 void 1012 BWFlipVert(Widget w) 1013 { 1014 BitmapWidget BW = (BitmapWidget) w; 1015 register Position x, y; 1016 Position from_x, from_y, to_x, to_y; 1017 float half; 1018 1019 if (BWQueryMarked(w)) { 1020 from_x = BW->bitmap.mark.from_x; 1021 from_y = BW->bitmap.mark.from_y; 1022 to_x = BW->bitmap.mark.to_x; 1023 to_y = BW->bitmap.mark.to_y; 1024 } 1025 else { 1026 from_x = 0; 1027 from_y = 0; 1028 to_x = BW->bitmap.width - 1; 1029 to_y = BW->bitmap.height - 1; 1030 } 1031 half = (float) (to_x - from_x) / 2.0 + 0.5; 1032 1033 if (half == 0) 1034 return; 1035 1036 for (y = from_y; y <= to_y; y++) 1037 for (x = 0; x < half; x++) 1038 if (GetBit(BW->bitmap.image, from_x + x, y) != 1039 GetBit(BW->bitmap.image, to_x - x, y)) { 1040 InvertPoint(BW, from_x + x, y); 1041 InvertPoint(BW, to_x - x, y); 1042 } 1043 1044 if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y) 1045 && 1046 !BWQueryMarked(w)) 1047 BWSetHotSpot(w, 1048 BW->bitmap.image->width - 1 - BW->bitmap.hot.x, 1049 BW->bitmap.hot.y); 1050 } 1051 1052 1053 void 1054 BWRotateRightAction(Widget w, _X_UNUSED XEvent *event, 1055 _X_UNUSED String *params, _X_UNUSED Cardinal *num_params) 1056 { 1057 BWRotateRight(w); 1058 } 1059 1060 void 1061 BWRotateRight(Widget w) 1062 { 1063 BitmapWidget BW = (BitmapWidget) w; 1064 Position x, y, delta, shift, tmp; 1065 Position half_width, half_height; 1066 XPoint hot; 1067 bit quad1, quad2, quad3, quad4; 1068 Position from_x, from_y, to_x, to_y; 1069 1070 if (BWQueryMarked(w)) { 1071 from_x = BW->bitmap.mark.from_x; 1072 from_y = BW->bitmap.mark.from_y; 1073 to_x = BW->bitmap.mark.to_x; 1074 to_y = BW->bitmap.mark.to_y; 1075 } 1076 else { 1077 from_x = 0; 1078 from_y = 0; 1079 to_x = BW->bitmap.width - 1; 1080 to_y = BW->bitmap.height - 1; 1081 } 1082 1083 half_width = floor((to_x - from_x) / 2.0 + 0.5); 1084 half_height = floor((to_y - from_y ) / 2.0 + 0.5); 1085 shift = min((Position)(to_x - from_x), (Position)(to_y - from_y )) % 2; 1086 delta = min((Position) half_width, (Position) half_height) - shift; 1087 1088 for (x = 0; x <= delta; x++) { 1089 for (y = 1 - shift; y <= delta; y++) { 1090 quad1 = GetBit(BW->bitmap.image, 1091 from_x + (Position)half_width + x, 1092 from_y + (Position)half_height + y); 1093 quad2 = GetBit(BW->bitmap.image, 1094 from_x + (Position)half_width + y, 1095 from_y + (Position)half_height - shift - x); 1096 quad3 = GetBit(BW->bitmap.image, 1097 from_x + (Position)half_width - shift - x, 1098 from_y + (Position)half_height - shift - y); 1099 quad4 = GetBit(BW->bitmap.image, 1100 from_x + (Position)half_width - shift - y, 1101 from_y + (Position)half_height + x); 1102 1103 if (quad1 != quad2) 1104 InvertPoint(BW, 1105 from_x + (Position)half_width + x, 1106 from_y + (Position)half_height + y); 1107 if (quad2 != quad3) 1108 InvertPoint(BW, 1109 from_x + (Position)half_width + y, 1110 from_y + (Position)half_height - shift - x); 1111 if (quad3 != quad4) 1112 InvertPoint(BW, 1113 from_x + (Position)half_width - shift - x, 1114 from_y + (Position)half_height - shift - y); 1115 if (quad4 != quad1) 1116 InvertPoint(BW, 1117 from_x + (Position)half_width - shift - y, 1118 from_y + (Position)half_height + x); 1119 } 1120 } 1121 1122 if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y) 1123 && 1124 !BWQueryMarked(w)) { 1125 hot.x = BW->bitmap.hot.x - half_width; 1126 hot.y = BW->bitmap.hot.y - half_height; 1127 if (hot.x >= 0) hot.x += shift; 1128 if (hot.y >= 0) hot.y += shift; 1129 tmp = hot.x; 1130 hot.x = - hot.y; 1131 hot.y = tmp; 1132 if (hot.x > 0) hot.x -= shift; 1133 if (hot.y > 0) hot.y -= shift; 1134 hot.x += half_width; 1135 hot.y += half_height; 1136 if (QueryInBitmap(BW, hot.x, hot.y)) 1137 BWSetHotSpot(w, hot.x, hot.y); 1138 } 1139 1140 } 1141 1142 void 1143 BWRotateLeftAction(Widget w, _X_UNUSED XEvent *event, 1144 _X_UNUSED String *params, _X_UNUSED Cardinal *num_params) 1145 { 1146 BWRotateLeft(w); 1147 } 1148 1149 void 1150 BWRotateLeft(Widget w) 1151 { 1152 BitmapWidget BW = (BitmapWidget) w; 1153 Position x, y,delta, shift, tmp; 1154 Position half_width, half_height; 1155 XPoint hot; 1156 bit quad1, quad2, quad3, quad4; 1157 Position from_x, from_y, to_x, to_y; 1158 1159 if (BWQueryMarked(w)) { 1160 from_x = BW->bitmap.mark.from_x; 1161 from_y = BW->bitmap.mark.from_y; 1162 to_x = BW->bitmap.mark.to_x; 1163 to_y = BW->bitmap.mark.to_y; 1164 } 1165 else { 1166 from_x = 0; 1167 from_y = 0; 1168 to_x = BW->bitmap.width - 1; 1169 to_y = BW->bitmap.height - 1; 1170 } 1171 1172 half_width = floor((to_x - from_x) / 2.0 + 0.5); 1173 half_height = floor((to_y - from_y ) / 2.0 + 0.5); 1174 shift = min((Position)(to_x - from_x), (Position)(to_y - from_y )) % 2; 1175 delta = min((Position) half_width, (Position) half_height) - shift; 1176 1177 for (x = 0; x <= delta; x++) { 1178 for (y = 1 - shift; y <= delta; y++) { 1179 quad1 = GetBit(BW->bitmap.image, 1180 from_x + (Position)half_width + x, 1181 from_y + (Position)half_height + y); 1182 quad2 = GetBit(BW->bitmap.image, 1183 from_x + (Position)half_width + y, 1184 from_y + (Position)half_height - shift - x); 1185 quad3 = GetBit(BW->bitmap.image, 1186 from_x + (Position)half_width - shift - x, 1187 from_y + (Position)half_height - shift - y); 1188 quad4 = GetBit(BW->bitmap.image, 1189 from_x + (Position)half_width - shift - y, 1190 from_y + (Position)half_height + x); 1191 1192 if (quad1 != quad4) 1193 InvertPoint(BW, 1194 from_x + (Position)half_width + x, 1195 from_y + (Position)half_height + y); 1196 if (quad2 != quad1) 1197 InvertPoint(BW, 1198 from_x + (Position)half_width + y, 1199 from_y + (Position)half_height - shift - x); 1200 if (quad3 != quad2) 1201 InvertPoint(BW, 1202 from_x + (Position)half_width - shift - x, 1203 from_y + (Position)half_height - shift - y); 1204 if (quad4 != quad3) 1205 InvertPoint(BW, 1206 from_x + (Position)half_width - shift - y, 1207 from_y + (Position)half_height + x); 1208 } 1209 } 1210 1211 if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y) 1212 && 1213 !BWQueryMarked(w)) { 1214 hot.x = BW->bitmap.hot.x - half_width; 1215 hot.y = BW->bitmap.hot.y - half_height; 1216 if (hot.x >= 0) hot.x += shift; 1217 if (hot.y >= 0) hot.y += shift; 1218 tmp = hot.x; 1219 hot.x = hot.y; 1220 hot.y = - tmp; 1221 if (hot.x > 0) hot.x -= shift; 1222 if (hot.y > 0) hot.y -= shift; 1223 hot.x += half_width; 1224 hot.y += half_height; 1225 if (QueryInBitmap(BW, hot.x, hot.y)) 1226 BWSetHotSpot(w, hot.x, hot.y); 1227 } 1228 } 1229 1230 1231 void 1232 CopyImageData(XImage *source, XImage *destination, 1233 Position from_x, Position from_y, 1234 Position to_x, Position to_y, 1235 Position at_x, Position at_y) 1236 { 1237 Position x, y, delta_x, delta_y; 1238 1239 delta_x = to_x - from_x + 1; 1240 delta_y = to_y - from_y + 1; 1241 1242 for (x = 0; x < delta_x; x++) 1243 for (y = 0; y < delta_y; y++) 1244 if (GetBit(source, from_x + x, from_y + y)) 1245 SetBit(destination, at_x + x, at_y + y); 1246 else 1247 ClearBit(destination, at_x + x, at_y + y); 1248 } 1249 1250 XImage * 1251 ConvertToBitmapImage(BitmapWidget BW, XImage *image) 1252 { 1253 XImage *bitmap_image; 1254 char *data; 1255 Position x, y; 1256 1257 data = CreateCleanData(Length(image->width, image->height)); 1258 bitmap_image = CreateBitmapImage(BW, data, 1259 (Dimension) image->width, 1260 (Dimension) image->height); 1261 1262 for (x = 0; x < min(image->width, bitmap_image->width); x++) 1263 for (y = 0; y < min(image->height, bitmap_image->height); y++) 1264 if ((XGetPixel(image, x, y) != 0) != GetBit(bitmap_image, x, y)) 1265 InvertBit(bitmap_image, x, y); 1266 1267 return bitmap_image; 1268 } 1269 1270 void 1271 TransferImageData(XImage *source, XImage *destination) 1272 { 1273 Position x, y; 1274 1275 for (x = 0; x < min(source->width, destination->width); x++) 1276 for (y = 0; y < min(source->height, destination->height); y++) 1277 if (GetBit(source, x, y) != GetBit(destination, x, y)) 1278 InvertBit(destination, x, y); 1279 } 1280 1281 void 1282 BWStore(Widget w) 1283 { 1284 BitmapWidget BW = (BitmapWidget) w; 1285 Dimension width, height; 1286 char *storage_data; 1287 1288 if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) { 1289 1290 DestroyBitmapImage(&BW->bitmap.storage); 1291 1292 width = BW->bitmap.mark.to_x - BW->bitmap.mark.from_x + 1; 1293 height = BW->bitmap.mark.to_y - BW->bitmap.mark.from_y + 1; 1294 1295 storage_data = CreateCleanData(Length(width, height)); 1296 1297 BW->bitmap.storage = CreateBitmapImage(BW, 1298 storage_data, 1299 width, height); 1300 1301 CopyImageData(BW->bitmap.image, BW->bitmap.storage, 1302 BW->bitmap.mark.from_x, BW->bitmap.mark.from_y, 1303 BW->bitmap.mark.to_x, BW->bitmap.mark.to_y, 1304 0, 0); 1305 } 1306 } 1307 1308 void 1309 BWClearMarked(Widget w) 1310 { 1311 BitmapWidget BW = (BitmapWidget) w; 1312 1313 if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) 1314 BWDrawFilledRectangle(w, 1315 BW->bitmap.mark.from_x, 1316 BW->bitmap.mark.from_y, 1317 BW->bitmap.mark.to_x, 1318 BW->bitmap.mark.to_y, 1319 Clear); 1320 } 1321 1322 1323 void 1324 BWDragMarked(Widget w, Position at_x, Position at_y) 1325 { 1326 BitmapWidget BW = (BitmapWidget) w; 1327 1328 if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) 1329 BWDrawRectangle(w, 1330 at_x, at_y, 1331 at_x + BW->bitmap.mark.to_x - BW->bitmap.mark.from_x, 1332 at_y + BW->bitmap.mark.to_y - BW->bitmap.mark.from_y, 1333 Highlight); 1334 } 1335 1336 void 1337 BWDragStored(Widget w, Position at_x, Position at_y) 1338 { 1339 BitmapWidget BW = (BitmapWidget) w; 1340 1341 if (BW->bitmap.storage) 1342 BWDrawRectangle(w, 1343 at_x, at_y, 1344 at_x + BW->bitmap.storage->width - 1, 1345 at_y + BW->bitmap.storage->height - 1, 1346 Highlight); 1347 } 1348 1349 static void 1350 DrawImageData(BitmapWidget BW, XImage *image, 1351 Position at_x, Position at_y, int value) 1352 { 1353 Position x, y; 1354 Boolean C, S, I, H; 1355 bit A, B; 1356 1357 C = value == Clear; 1358 S = value == Set; 1359 I = value == Invert; 1360 H = value == Highlight; 1361 1362 for (x = 0; x < image->width; x++) 1363 for (y = 0; y < image->height; y++) { 1364 A = GetBit(image, x, y); 1365 B = GetBit(BW->bitmap.image, at_x + x, at_y + y); 1366 if ((A & C) | ((A | B) & S) | ((A ^ B) & I) | ((A | B) & H)) 1367 value = (A & H) ? Highlight : Set; 1368 else 1369 value = Clear; 1370 BWDrawPoint((Widget) BW, 1371 at_x + x, at_y + y, 1372 value); 1373 } 1374 } 1375 1376 void 1377 BWRestore(Widget w, Position at_x, Position at_y, int value) 1378 { 1379 BitmapWidget BW = (BitmapWidget) w; 1380 1381 if (BW->bitmap.storage) { 1382 DrawImageData(BW, BW->bitmap.storage, at_x, at_y, value); 1383 /*DestroyBitmapImage(&BW->bitmap.storage);*/ 1384 } 1385 } 1386 1387 void 1388 BWCopy(Widget w, Position at_x, Position at_y, int value) 1389 { 1390 BitmapWidget BW = (BitmapWidget) w; 1391 XImage *storage; 1392 char *storage_data; 1393 Dimension width, height; 1394 1395 if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) { 1396 1397 width = BW->bitmap.mark.to_x - BW->bitmap.mark.from_x + 1; 1398 height = BW->bitmap.mark.to_y - BW->bitmap.mark.from_y + 1; 1399 1400 storage_data = CreateCleanData(Length(width, height)); 1401 1402 storage = CreateBitmapImage(BW, storage_data, width, height); 1403 1404 CopyImageData(BW->bitmap.image, storage, 1405 BW->bitmap.mark.from_x, BW->bitmap.mark.from_y, 1406 BW->bitmap.mark.to_x, BW->bitmap.mark.to_y, 1407 0, 0); 1408 1409 DrawImageData(BW, storage, at_x, at_y, value); 1410 1411 DestroyBitmapImage(&storage); 1412 } 1413 } 1414 1415 /* void BWMark(); */ 1416 1417 void 1418 BWMove(Widget w, Position at_x, Position at_y, int value) 1419 { 1420 BitmapWidget BW = (BitmapWidget) w; 1421 XImage *storage; 1422 char *storage_data; 1423 Dimension width, height; 1424 1425 if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) { 1426 1427 width = BW->bitmap.mark.to_x - BW->bitmap.mark.from_x + 1; 1428 height = BW->bitmap.mark.to_y - BW->bitmap.mark.from_y + 1; 1429 1430 storage_data = CreateCleanData(Length(width, height)); 1431 1432 storage = CreateBitmapImage(BW, storage_data, width, height); 1433 1434 CopyImageData(BW->bitmap.image, storage, 1435 BW->bitmap.mark.from_x, BW->bitmap.mark.from_y, 1436 BW->bitmap.mark.to_x, BW->bitmap.mark.to_y, 1437 0, 0); 1438 1439 BWDrawFilledRectangle(w, 1440 BW->bitmap.mark.from_x, BW->bitmap.mark.from_y, 1441 BW->bitmap.mark.to_x, BW->bitmap.mark.to_y, 1442 Clear); 1443 1444 DrawImageData(BW, storage, at_x, at_y, value); 1445 1446 BWMark(w, at_x, at_y, 1447 at_x + BW->bitmap.mark.to_x - BW->bitmap.mark.from_x, 1448 at_y + BW->bitmap.mark.to_y - BW->bitmap.mark.from_y); 1449 1450 DestroyBitmapImage(&storage); 1451 } 1452 } 1453 1454 void 1455 BWRedrawMark(Widget w) 1456 { 1457 BitmapWidget BW = (BitmapWidget) w; 1458 1459 if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) 1460 XFillRectangle(XtDisplay(BW), XtWindow(BW), BW->bitmap.highlighting_gc, 1461 InWindowX(BW, BW->bitmap.mark.from_x), 1462 InWindowY(BW, BW->bitmap.mark.from_y), 1463 InWindowX(BW, BW->bitmap.mark.to_x + 1) - 1464 InWindowX(BW, BW->bitmap.mark.from_x), 1465 InWindowY(BW, BW->bitmap.mark.to_y + 1) - 1466 InWindowY(BW, BW->bitmap.mark.from_y)); 1467 } 1468 1469 void 1470 BWStoreToBufferAction(Widget w, _X_UNUSED XEvent *event, 1471 _X_UNUSED String *params, _X_UNUSED Cardinal *num_params) 1472 { 1473 BWStoreToBuffer(w); 1474 } 1475 1476 void 1477 BWStoreToBuffer(Widget w) 1478 { 1479 BitmapWidget BW = (BitmapWidget) w; 1480 1481 memmove( BW->bitmap.buffer->data, BW->bitmap.image->data, 1482 Length(BW->bitmap.image->width, BW->bitmap.image->height)); 1483 1484 BW->bitmap.buffer_hot = BW->bitmap.hot; 1485 BW->bitmap.buffer_mark = BW->bitmap.mark; 1486 } 1487 1488 void 1489 BWUnmark(Widget w) 1490 { 1491 BitmapWidget BW = (BitmapWidget) w; 1492 1493 BW->bitmap.buffer_mark = BW->bitmap.mark; 1494 1495 if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) { 1496 XFillRectangle(XtDisplay(BW), XtWindow(BW), BW->bitmap.highlighting_gc, 1497 InWindowX(BW, BW->bitmap.mark.from_x), 1498 InWindowY(BW, BW->bitmap.mark.from_y), 1499 InWindowX(BW, BW->bitmap.mark.to_x + 1) - 1500 InWindowX(BW, BW->bitmap.mark.from_x), 1501 InWindowY(BW, BW->bitmap.mark.to_y + 1) - 1502 InWindowY(BW, BW->bitmap.mark.from_y)); 1503 1504 BW->bitmap.mark.from_x = BW->bitmap.mark.from_y = NotSet; 1505 BW->bitmap.mark.to_x = BW->bitmap.mark.to_y = NotSet; 1506 } 1507 } 1508 1509 void 1510 BWMark(Widget w, Position from_x, Position from_y, 1511 Position to_x, Position to_y) 1512 { 1513 BitmapWidget BW = (BitmapWidget) w; 1514 1515 BWUnmark(w); 1516 1517 if (QuerySet(from_x, from_y)) { 1518 if ((from_x == to_x) && (from_y == to_y)) { 1519 /* 1520 BW->bitmap.mark.from_x = 0; 1521 BW->bitmap.mark.from_y = 0; 1522 BW->bitmap.mark.to_x = BW->bitmap.image->width - 1; 1523 BW->bitmap.mark.to_y = BW->bitmap.image->height - 1; 1524 */ 1525 return; 1526 } 1527 else { 1528 QuerySwap(from_x, to_x); 1529 QuerySwap(from_y, to_y); 1530 from_x = max(0, from_x); 1531 from_y = max(0, from_y); 1532 to_x = min(BW->bitmap.image->width - 1, to_x); 1533 to_y = min(BW->bitmap.image->height - 1, to_y); 1534 1535 BW->bitmap.mark.from_x = from_x; 1536 BW->bitmap.mark.from_y = from_y; 1537 BW->bitmap.mark.to_x = to_x; 1538 BW->bitmap.mark.to_y = to_y; 1539 } 1540 1541 XFillRectangle(XtDisplay(BW), XtWindow(BW), BW->bitmap.highlighting_gc, 1542 InWindowX(BW, BW->bitmap.mark.from_x), 1543 InWindowY(BW, BW->bitmap.mark.from_y), 1544 InWindowX(BW, BW->bitmap.mark.to_x + 1) - 1545 InWindowX(BW, BW->bitmap.mark.from_x), 1546 InWindowY(BW, BW->bitmap.mark.to_y +1) - 1547 InWindowY(BW, BW->bitmap.mark.from_y)); 1548 } 1549 } 1550 1551 void 1552 BWMarkAll(Widget w) 1553 { 1554 BitmapWidget BW = (BitmapWidget) w; 1555 1556 BWMark(w, 0, 0, BW->bitmap.image->width - 1, BW->bitmap.image->height - 1); 1557 } 1558 1559 void 1560 BWUndoAction(Widget w, _X_UNUSED XEvent *event, 1561 _X_UNUSED String *params, _X_UNUSED Cardinal *num_params) 1562 { 1563 BWUndo(w); 1564 } 1565 1566 void 1567 BWUndo(Widget w) 1568 { 1569 BitmapWidget BW = (BitmapWidget) w; 1570 Position x, y; 1571 char *tmp_data; 1572 XPoint tmp_hot; 1573 BWArea tmp_mark; 1574 1575 tmp_data = BW->bitmap.image->data; 1576 BW->bitmap.image->data = BW->bitmap.buffer->data; 1577 BW->bitmap.buffer->data = tmp_data; 1578 1579 tmp_hot = BW->bitmap.hot; 1580 tmp_mark = BW->bitmap.mark; 1581 1582 for (x = 0; x < BW->bitmap.image->width; x++) 1583 for (y = 0; y < BW->bitmap.image->height; y++) 1584 if (GetBit(BW->bitmap.image, x, y) != GetBit(BW->bitmap.buffer, x, y)) 1585 DrawSquare(BW, x, y); 1586 1587 BWSetHotSpot(w, BW->bitmap.buffer_hot.x, BW->bitmap.buffer_hot.y); 1588 /* 1589 BWMark(w, BW->bitmap.buffer_mark.from_x, BW->bitmap.buffer_mark.from_y, 1590 BW->bitmap.buffer_mark.to_x, BW->bitmap.buffer_mark.to_y); 1591 */ 1592 BW->bitmap.buffer_hot = tmp_hot; 1593 BW->bitmap.buffer_mark= tmp_mark; 1594 1595 } 1596 1597 void 1598 BWHighlightAxes(Widget w) 1599 { 1600 BitmapWidget BW = (BitmapWidget) w; 1601 1602 XDrawLine(XtDisplay(BW), XtWindow(BW), 1603 BW->bitmap.axes_gc, 1604 InWindowX(BW, 0), 1605 InWindowY(BW, 0), 1606 InWindowX(BW, BW->bitmap.width), 1607 InWindowY(BW, BW->bitmap.height)); 1608 XDrawLine(XtDisplay(BW), XtWindow(BW), 1609 BW->bitmap.axes_gc, 1610 InWindowX(BW, BW->bitmap.width), 1611 InWindowY(BW, 0), 1612 InWindowX(BW, 0), 1613 InWindowY(BW, BW->bitmap.height)); 1614 XDrawLine(XtDisplay(BW), XtWindow(BW), 1615 BW->bitmap.axes_gc, 1616 InWindowX(BW, 0), 1617 InWindowY(BW, (float)BW->bitmap.height / 2.0), 1618 InWindowX(BW, BW->bitmap.width), 1619 InWindowY(BW, (float)BW->bitmap.height / 2.0)); 1620 XDrawLine(XtDisplay(BW), XtWindow(BW), 1621 BW->bitmap.axes_gc, 1622 InWindowX(BW, (float)BW->bitmap.width / 2.0), 1623 InWindowY(BW, 0), 1624 InWindowX(BW, (float)BW->bitmap.width / 2.0), 1625 InWindowY(BW, BW->bitmap.height)); 1626 } 1627 1628 typedef struct { 1629 Position *x, *y; 1630 Dimension *width, *height; 1631 } Table; 1632 1633 XImage * 1634 ScaleBitmapImage(BitmapWidget BW, XImage *src, 1635 double scale_x, double scale_y) 1636 { 1637 char *data; 1638 XImage *dst; 1639 Table table; 1640 Position x, y, w, h; 1641 Dimension width, height; 1642 bit pixel; 1643 1644 width = max(rint(scale_x * src->width), 1); 1645 height = max(rint(scale_y * src->height), 1); 1646 1647 data = CreateCleanData(Length(width, height)); 1648 dst = CreateBitmapImage(BW, data, width, height); 1649 1650 /* 1651 * It would be nice to check if width or height < 1.0 and 1652 * average the skipped pixels. But, it is slow as it is now. 1653 */ 1654 if (scale_x == 1.0 && scale_y == 1.0) 1655 memmove( dst->data, src->data, Length(width, height)); 1656 else { 1657 table.x = (Position *) XtMalloc(sizeof(Position) * src->width); 1658 table.y = (Position *) XtMalloc(sizeof(Position) * src->height); 1659 table.width = (Dimension *) XtMalloc(sizeof(Dimension) * src->width); 1660 table.height = (Dimension *) XtMalloc(sizeof(Dimension) * src->height); 1661 1662 for (x = 0; x < src->width; x++) { 1663 table.x[x] = rint(scale_x * x); 1664 table.width[x] = rint(scale_x * (x + 1)) - rint(scale_x * x); 1665 } 1666 for (y = 0; y < src->height; y++) { 1667 table.y[y] = rint(scale_y * y); 1668 table.height[y] = rint(scale_y * (y + 1)) - rint(scale_y * y); 1669 } 1670 1671 for (x = 0; x < src->width; x++) 1672 for (y = 0; y < src->height; y++) { 1673 pixel = GetBit(src, x, y); 1674 for (w = 0; (int)w < (int)table.width[x]; w++) 1675 for (h = 0; (int)h < (int)table.height[y]; h++) 1676 if (pixel) SetBit(dst, 1677 table.x[x] + w, 1678 table.y[y] + h); 1679 } 1680 1681 XtFree((char *)table.x); 1682 XtFree((char *)table.y); 1683 XtFree((char *)table.width); 1684 XtFree((char *)table.height); 1685 } 1686 1687 return (dst); 1688 } 1689 1690 /*****************************************************************************/ 1691