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