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
BWDrawPoint(Widget w,Position x,Position y,bit value)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 *
HotSpotShape(BitmapWidget BW,Position x,Position y)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
BWRedrawHotSpot(Widget w)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
BWClearHotSpot(Widget w)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
BWDrawHotSpot(Widget w,Position x,Position y,int value)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
BWSetHotSpot(Widget w,Position x,Position y)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
BWRedrawSquares(Widget w,Position x,Position y,Dimension width,Dimension height)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
BWDrawGrid(Widget w,Position from_x,Position from_y,Position to_x,Position to_y)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
BWRedrawGrid(Widget w,Position x,Position y,Dimension width,Dimension height)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
BWDrawLine(Widget w,Position from_x,Position from_y,Position to_x,Position to_y,int value)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
BWBlindLine(Widget w,Position from_x,Position from_y,Position to_x,Position to_y,int value)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
BWDrawRectangle(Widget w,Position from_x,Position from_y,Position to_x,Position to_y,int value)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
BWDrawFilledRectangle(Widget w,Position from_x,Position from_y,Position to_x,Position to_y,int value)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
BWDrawCircle(Widget w,Position origin_x,Position origin_y,Position point_x,Position point_y,int value)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 BWDrawPoint(w, origin_x - (Position) floor(radius), origin_y, value);
431 BWDrawPoint(w, origin_x + (Position) floor(radius), origin_y, value);
432 BWDrawPoint(w, origin_x, origin_y - (Position) floor(radius), value);
433 BWDrawPoint(w, origin_x, origin_y + (Position) floor(radius), value);
434 }
435 half = radius / sqrt(2.0);
436 for(i = 1; (int)i <= (int)half; i++) {
437 delta = sqrt(radius * radius - i * i);
438 BWDrawPoint(w, origin_x - delta, origin_y - i, value);
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 if (i != delta) {
443 BWDrawPoint(w, origin_x - i, origin_y - delta, value);
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 }
448 }
449 }
450
451 void
BWDrawFilledCircle(Widget w,Position origin_x,Position origin_y,Position point_x,Position point_y,int value)452 BWDrawFilledCircle(Widget w,
453 Position origin_x, Position origin_y,
454 Position point_x, Position point_y, int value)
455 {
456 register Position i, j, delta;
457 Dimension dx, dy;
458 double radius;
459
460 dx = abs(point_x - origin_x);
461 dy = abs(point_y - origin_y);
462 radius = sqrt((double) ((int)dx * (int)dx + (int)dy * (int)dy));
463 for(j = origin_x - (Position) floor(radius);
464 j <= origin_x + (Position) floor(radius); j++)
465 BWDrawPoint(w, j, origin_y, value);
466 for(i = 1; i <= (Position) floor(radius); i++) {
467 delta = sqrt(radius * radius - i * i);
468 for(j = origin_x - delta; j <= origin_x + delta; j++) {
469 BWDrawPoint(w, j, origin_y - i, value);
470 BWDrawPoint(w, j, origin_y + i, value);
471 }
472 }
473 }
474
475 #define QueryFlood(BW, x, y, value)\
476 ((GetBit(BW->bitmap.image, x, y) !=\
477 (value & 1)) && QueryInBitmap(BW, x, y))
478
479 #define Flood(BW, x, y, value)\
480 {if (value == Highlight) HighlightSquare(BW, x, y);\
481 else InvertPoint(BW, x, y);}
482
483 /*
484 static void
485 FloodLoop(BitmapWidget BW, Position x, Position y, int value)
486 {
487 if (QueryFlood(BW, x, y, value)) {
488 Flood(BW, x, y, value);
489 FloodLoop(BW, x, y - 1, value);
490 FloodLoop(BW, x - 1, y, value);
491 FloodLoop(BW, x, y + 1, value);
492 FloodLoop(BW, x + 1, y, value);
493 }
494 }
495 */
496
497 static void
FloodLoop(BitmapWidget BW,Position x,Position y,int value)498 FloodLoop(BitmapWidget BW, Position x, Position y, int value)
499 {
500 Position save_x, save_y, x_left, x_right;
501
502 if (QueryFlood(BW, x, y, value))
503 Flood(BW, x, y, value)
504
505
506 save_x = x;
507 save_y = y;
508
509 x++;
510 while (QueryFlood(BW, x, y, value)) {
511 Flood(BW, x, y, value);
512 x++;
513 }
514 x_right = --x;
515
516 x = save_x;
517 x--;
518 while (QueryFlood(BW, x, y, value)) {
519 Flood(BW, x, y, value);
520 x--;
521 }
522 x_left = ++x;
523
524
525 x = x_left;
526 y = save_y;
527 y++;
528
529 while (x <= x_right) {
530 Boolean flag = False;
531 Position x_enter;
532
533 while (QueryFlood(BW, x, y, value) && (x <= x_right)) {
534 flag = True;
535 x++;
536 }
537
538 if (flag) {
539 if ((x == x_right) && QueryFlood(BW, x, y, value))
540 FloodLoop(BW, x, y, value);
541 else
542 FloodLoop(BW, x - 1, y, value);
543 }
544
545 x_enter = x;
546
547 while (!QueryFlood(BW, x, y, value) && (x < x_right))
548 x++;
549
550 if (x == x_enter) x++;
551 }
552
553 x = x_left;
554 y = save_y;
555 y--;
556
557 while (x <= x_right) {
558 Boolean flag = False;
559 Position x_enter;
560
561 while (QueryFlood(BW, x, y, value) && (x <= x_right)) {
562 flag = True;
563 x++;
564 }
565
566 if (flag) {
567 if ((x == x_right) && QueryFlood(BW, x, y, value))
568 FloodLoop(BW, x, y, value);
569 else
570 FloodLoop(BW, x - 1, y, value);
571 }
572
573 x_enter = x;
574
575 while (!QueryFlood(BW, x, y, value) && (x < x_right))
576 x++;
577
578 if (x == x_enter) x++;
579 }
580 }
581
582 void
BWFloodFill(Widget w,Position x,Position y,int value)583 BWFloodFill(Widget w, Position x, Position y, int value)
584 {
585 BitmapWidget BW = (BitmapWidget) w;
586 int pixel;
587
588 pixel = GetBit(BW->bitmap.image, x, y);
589
590 if (value == Invert)
591 FloodLoop(BW, x, y, (pixel ? Clear : Set));
592 else if (value != pixel)
593 FloodLoop(BW, x, y, value);
594 }
595
596 #define QueryHotInMark(BW)\
597 ((BW->bitmap.hot.x == max(BW->bitmap.mark.from_x,\
598 min(BW->bitmap.hot.x, BW->bitmap.mark.to_x)))\
599 &&\
600 (BW->bitmap.hot.y == max(BW->bitmap.mark.from_y,\
601 min(BW->bitmap.hot.y, BW->bitmap.mark.to_y))))
602
603 void
BWUp(Widget w)604 BWUp(Widget w)
605 {
606 BitmapWidget BW = (BitmapWidget) w;
607 register Position x, y;
608 bit first, up, down=0;
609 Position from_x, from_y, to_x, to_y;
610
611 if (BWQueryMarked(w)) {
612 from_x = BW->bitmap.mark.from_x;
613 from_y = BW->bitmap.mark.from_y;
614 to_x = BW->bitmap.mark.to_x;
615 to_y = BW->bitmap.mark.to_y;
616 }
617 else {
618 from_x = 0;
619 from_y = 0;
620 to_x = BW->bitmap.width - 1;
621 to_y = BW->bitmap.height - 1;
622 }
623
624 if ((to_y - from_y) == 0)
625 return;
626
627 for(x = from_x; x <= to_x; x++) {
628 first = up = GetBit(BW->bitmap.image, x, to_y);
629 for(y = to_y - 1; y >= from_y; y--) {
630 down = GetBit(BW->bitmap.image, x, y);
631 if (up != down)
632 InvertPoint(BW, x, y);
633 up =down;
634 }
635 if(first != down)
636 InvertPoint(BW, x, to_y);
637 }
638
639 if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)
640 &&
641 !BWQueryMarked(w))
642 BWSetHotSpot(w,
643 BW->bitmap.hot.x,
644 (BW->bitmap.hot.y - 1 + BW->bitmap.image->height) %
645 BW->bitmap.image->height);
646
647 }
648
649 void
BWDown(Widget w)650 BWDown(Widget w)
651 {
652 BitmapWidget BW = (BitmapWidget) w;
653 register Position x, y;
654 bit first, down, up=0;
655 Position from_x, from_y, to_x, to_y;
656
657 if (BWQueryMarked(w)) {
658 from_x = BW->bitmap.mark.from_x;
659 from_y = BW->bitmap.mark.from_y;
660 to_x = BW->bitmap.mark.to_x;
661 to_y = BW->bitmap.mark.to_y;
662 }
663 else {
664 from_x = 0;
665 from_y = 0;
666 to_x = BW->bitmap.width - 1;
667 to_y = BW->bitmap.height - 1;
668 }
669
670 if ((to_y - from_y) == 0)
671 return;
672
673 for(x = from_x; x <= to_x; x++) {
674 first = down = GetBit(BW->bitmap.image, x, from_y);
675 for(y = from_y + 1; y <= to_y; y++) {
676 up = GetBit(BW->bitmap.image, x, y);
677 if (down != up)
678 InvertPoint(BW, x, y);
679 down = up;
680 }
681 if(first != up)
682 InvertPoint(BW, x, from_y);
683 }
684
685 if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)
686 &&
687 !BWQueryMarked(w))
688 BWSetHotSpot(w,
689 BW->bitmap.hot.x,
690 (BW->bitmap.hot.y + 1) % BW->bitmap.image->height);
691 }
692
693 void
BWLeft(Widget w)694 BWLeft(Widget w)
695 {
696 BitmapWidget BW = (BitmapWidget) w;
697 register Position x, y;
698 bit first, left, right=0;
699 Position from_x, from_y, to_x, to_y;
700
701 if (BWQueryMarked(w)) {
702 from_x = BW->bitmap.mark.from_x;
703 from_y = BW->bitmap.mark.from_y;
704 to_x = BW->bitmap.mark.to_x;
705 to_y = BW->bitmap.mark.to_y;
706 }
707 else {
708 from_x = 0;
709 from_y = 0;
710 to_x = BW->bitmap.width - 1;
711 to_y = BW->bitmap.height - 1;
712 }
713
714 if ((to_x - from_x) == 0)
715 return;
716
717 for(y = from_y; y <= to_y; y++) {
718 first = left = GetBit(BW->bitmap.image, to_x, y);
719 for(x = to_x - 1; x >= from_x; x--) {
720 right = GetBit(BW->bitmap.image, x, y);
721 if (left != right)
722 InvertPoint(BW, x, y);
723 left = right;
724 }
725 if(first != right)
726 InvertPoint(BW, to_x, y);
727 }
728
729 if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)
730 &&
731 !BWQueryMarked(w))
732 BWSetHotSpot(w,
733 (BW->bitmap.hot.x - 1 + BW->bitmap.image->width) %
734 BW->bitmap.image->width,
735 BW->bitmap.hot.y);
736 }
737
738 void
BWRight(Widget w)739 BWRight(Widget w)
740 {
741 BitmapWidget BW = (BitmapWidget) w;
742 register Position x, y;
743 bit first, right, left=0;
744 Position from_x, from_y, to_x, to_y;
745
746 if (BWQueryMarked(w)) {
747 from_x = BW->bitmap.mark.from_x;
748 from_y = BW->bitmap.mark.from_y;
749 to_x = BW->bitmap.mark.to_x;
750 to_y = BW->bitmap.mark.to_y;
751 }
752 else {
753 from_x = 0;
754 from_y = 0;
755 to_x = BW->bitmap.width - 1;
756 to_y = BW->bitmap.height - 1;
757 }
758
759 if ((to_x - from_x) == 0)
760 return;
761
762 for(y = from_y; y <= to_y; y++) {
763 first = right = GetBit(BW->bitmap.image, from_x, y);
764 for(x = from_x + 1; x <= to_x; x++) {
765 left = GetBit(BW->bitmap.image, x, y);
766 if (right != left)
767 InvertPoint(BW, x, y);
768 right = left;
769 }
770 if(first != left)
771 InvertPoint(BW, from_x, y);
772 }
773
774 if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)
775 &&
776 !BWQueryMarked(w))
777 BWSetHotSpot(w,
778 (BW->bitmap.hot.x + 1) % BW->bitmap.image->width,
779 BW->bitmap.hot.y);
780 }
781
782 /* void TransferImageData(); */
783
784 void
BWFold(Widget w)785 BWFold(Widget w)
786 {
787 BitmapWidget BW = (BitmapWidget) w;
788 Position x, y, new_x, new_y;
789 Dimension horiz, vert;
790 char *storage_data;
791 XImage *storage;
792
793 storage_data = CreateCleanData(Length(BW->bitmap.image->width,
794 BW->bitmap.image->height));
795
796 storage = CreateBitmapImage(BW, storage_data,
797 (Dimension) BW->bitmap.image->width,
798 (Dimension) BW->bitmap.image->height);
799
800 TransferImageData(BW->bitmap.image, storage);
801
802 BW->bitmap.fold ^= True;
803 horiz = (BW->bitmap.image->width + BW->bitmap.fold) / 2;
804 vert = (BW->bitmap.image->height + BW->bitmap.fold) / 2;
805
806 for (x = 0; x < BW->bitmap.image->width; x++)
807 for (y = 0; y < BW->bitmap.image->height; y++) {
808 new_x = (int)(x + horiz) % (int)BW->bitmap.image->width;
809 new_y = (int)(y + vert) % (int)BW->bitmap.image->height;
810 if(GetBit(BW->bitmap.image, new_x, new_y) !=
811 GetBit(storage, x, y))
812 InvertPoint(BW, new_x, new_y);
813 }
814
815 DestroyBitmapImage(&storage);
816
817 if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y))
818 BWSetHotSpot(w,
819 (Position)
820 ((int)(BW->bitmap.hot.x+horiz)
821 %(int)BW->bitmap.image->width),
822 (Position)
823 ((int)(BW->bitmap.hot.y+vert)
824 %(int)BW->bitmap.image->height)
825 );
826 }
827
828
829 void
BWClear(Widget w)830 BWClear(Widget w)
831 {
832 BitmapWidget BW = (BitmapWidget) w;
833 register Position x, y;
834 int i, length;
835
836 length = Length(BW->bitmap.image->width, BW->bitmap.image->height);
837
838 for (x = 0; x < BW->bitmap.image->width; x++)
839 for (y = 0; y < BW->bitmap.image->height; y++)
840 if (GetBit(BW->bitmap.image, x, y))
841 DrawSquare(BW, x, y);
842
843 for (i = 0; i < length; i++)
844 BW->bitmap.image->data[i] = 0;
845
846 }
847
848 void
BWSet(Widget w)849 BWSet(Widget w)
850 {
851 BitmapWidget BW = (BitmapWidget) w;
852 register Position x, y;
853 int i, length;
854
855 length = Length(BW->bitmap.image->width, BW->bitmap.image->height);
856
857 for (x = 0; x < BW->bitmap.image->width; x++)
858 for (y = 0; y < BW->bitmap.image->height; y++)
859 if (!GetBit(BW->bitmap.image, x, y))
860 DrawSquare(BW, x, y);
861
862 for (i = 0; i < length; i++)
863 BW->bitmap.image->data[i] = (char)255;
864
865 }
866
867 void
BWRedraw(Widget w)868 BWRedraw(Widget w)
869 {
870 BitmapWidget BW = (BitmapWidget) w;
871
872 XClearArea(XtDisplay(BW), XtWindow(BW),
873 0, 0, BW->core.width, BW->core.height,
874 True);
875 }
876
877 void
BWInvert(Widget w)878 BWInvert(Widget w)
879 {
880 BitmapWidget BW = (BitmapWidget) w;
881 int i, length;
882
883 length = Length(BW->bitmap.image->width, BW->bitmap.image->height);
884
885 XFillRectangle(XtDisplay(BW), XtWindow(BW),
886 BW->bitmap.drawing_gc,
887 InWindowX(BW, 0), InWindowY(BW, 0),
888 InWindowX(BW, BW->bitmap.image->width) - InWindowX(BW, 0),
889 InWindowY(BW, BW->bitmap.image->height) - InWindowY(BW, 0));
890
891 for (i = 0; i < length; i++)
892 BW->bitmap.image->data[i] ^= 255;
893 }
894
895 void
BWFlipHoriz(Widget w)896 BWFlipHoriz(Widget w)
897 {
898 BitmapWidget BW = (BitmapWidget) w;
899 register Position x, y;
900 Position from_x, from_y, to_x, to_y;
901 float half;
902
903 if (BWQueryMarked(w)) {
904 from_x = BW->bitmap.mark.from_x;
905 from_y = BW->bitmap.mark.from_y;
906 to_x = BW->bitmap.mark.to_x;
907 to_y = BW->bitmap.mark.to_y;
908 }
909 else {
910 from_x = 0;
911 from_y = 0;
912 to_x = BW->bitmap.width - 1;
913 to_y = BW->bitmap.height - 1;
914 }
915 half = (float) (to_y - from_y) / 2.0 + 0.5;
916
917 if (half == 0.0)
918 return;
919
920 for (x = from_x; x <= to_x; x++)
921 for (y = 0; y < half; y++)
922 if (GetBit(BW->bitmap.image, x, from_y + y) !=
923 GetBit(BW->bitmap.image, x, to_y - y)) {
924 InvertPoint(BW, x, from_y + y);
925 InvertPoint(BW, x, to_y - y);
926 }
927
928 if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)
929 &&
930 !BWQueryMarked(w))
931 BWSetHotSpot(w,
932 BW->bitmap.hot.x,
933 BW->bitmap.image->height - 1 - BW->bitmap.hot.y);
934 }
935
936 void
BWFlipVert(Widget w)937 BWFlipVert(Widget w)
938 {
939 BitmapWidget BW = (BitmapWidget) w;
940 register Position x, y;
941 Position from_x, from_y, to_x, to_y;
942 float half;
943
944 if (BWQueryMarked(w)) {
945 from_x = BW->bitmap.mark.from_x;
946 from_y = BW->bitmap.mark.from_y;
947 to_x = BW->bitmap.mark.to_x;
948 to_y = BW->bitmap.mark.to_y;
949 }
950 else {
951 from_x = 0;
952 from_y = 0;
953 to_x = BW->bitmap.width - 1;
954 to_y = BW->bitmap.height - 1;
955 }
956 half = (float) (to_x - from_x) / 2.0 + 0.5;
957
958 if (half == 0)
959 return;
960
961 for (y = from_y; y <= to_y; y++)
962 for (x = 0; x < half; x++)
963 if (GetBit(BW->bitmap.image, from_x + x, y) !=
964 GetBit(BW->bitmap.image, to_x - x, y)) {
965 InvertPoint(BW, from_x + x, y);
966 InvertPoint(BW, to_x - x, y);
967 }
968
969 if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)
970 &&
971 !BWQueryMarked(w))
972 BWSetHotSpot(w,
973 BW->bitmap.image->width - 1 - BW->bitmap.hot.x,
974 BW->bitmap.hot.y);
975 }
976
977
978 void
BWRotateRight(Widget w)979 BWRotateRight(Widget w)
980 {
981 BitmapWidget BW = (BitmapWidget) w;
982 Position x, y, delta, shift, tmp;
983 Position half_width, half_height;
984 XPoint hot;
985 bit quad1, quad2, quad3, quad4;
986 Position from_x, from_y, to_x, to_y;
987
988 if (BWQueryMarked(w)) {
989 from_x = BW->bitmap.mark.from_x;
990 from_y = BW->bitmap.mark.from_y;
991 to_x = BW->bitmap.mark.to_x;
992 to_y = BW->bitmap.mark.to_y;
993 }
994 else {
995 from_x = 0;
996 from_y = 0;
997 to_x = BW->bitmap.width - 1;
998 to_y = BW->bitmap.height - 1;
999 }
1000
1001 half_width = floor((to_x - from_x) / 2.0 + 0.5);
1002 half_height = floor((to_y - from_y ) / 2.0 + 0.5);
1003 shift = min((Position)(to_x - from_x), (Position)(to_y - from_y )) % 2;
1004 delta = min((Position) half_width, (Position) half_height) - shift;
1005
1006 for (x = 0; x <= delta; x++) {
1007 for (y = 1 - shift; y <= delta; y++) {
1008 quad1 = GetBit(BW->bitmap.image,
1009 from_x + (Position)half_width + x,
1010 from_y + (Position)half_height + y);
1011 quad2 = GetBit(BW->bitmap.image,
1012 from_x + (Position)half_width + y,
1013 from_y + (Position)half_height - shift - x);
1014 quad3 = GetBit(BW->bitmap.image,
1015 from_x + (Position)half_width - shift - x,
1016 from_y + (Position)half_height - shift - y);
1017 quad4 = GetBit(BW->bitmap.image,
1018 from_x + (Position)half_width - shift - y,
1019 from_y + (Position)half_height + x);
1020
1021 if (quad1 != quad2)
1022 InvertPoint(BW,
1023 from_x + (Position)half_width + x,
1024 from_y + (Position)half_height + y);
1025 if (quad2 != quad3)
1026 InvertPoint(BW,
1027 from_x + (Position)half_width + y,
1028 from_y + (Position)half_height - shift - x);
1029 if (quad3 != quad4)
1030 InvertPoint(BW,
1031 from_x + (Position)half_width - shift - x,
1032 from_y + (Position)half_height - shift - y);
1033 if (quad4 != quad1)
1034 InvertPoint(BW,
1035 from_x + (Position)half_width - shift - y,
1036 from_y + (Position)half_height + x);
1037 }
1038 }
1039
1040 if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)
1041 &&
1042 !BWQueryMarked(w)) {
1043 hot.x = BW->bitmap.hot.x - half_width;
1044 hot.y = BW->bitmap.hot.y - half_height;
1045 if (hot.x >= 0) hot.x += shift;
1046 if (hot.y >= 0) hot.y += shift;
1047 tmp = hot.x;
1048 hot.x = - hot.y;
1049 hot.y = tmp;
1050 if (hot.x > 0) hot.x -= shift;
1051 if (hot.y > 0) hot.y -= shift;
1052 hot.x += half_width;
1053 hot.y += half_height;
1054 if (QueryInBitmap(BW, hot.x, hot.y))
1055 BWSetHotSpot(w, hot.x, hot.y);
1056 }
1057
1058 }
1059
1060 void
BWRotateLeft(Widget w)1061 BWRotateLeft(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 != quad4)
1104 InvertPoint(BW,
1105 from_x + (Position)half_width + x,
1106 from_y + (Position)half_height + y);
1107 if (quad2 != quad1)
1108 InvertPoint(BW,
1109 from_x + (Position)half_width + y,
1110 from_y + (Position)half_height - shift - x);
1111 if (quad3 != quad2)
1112 InvertPoint(BW,
1113 from_x + (Position)half_width - shift - x,
1114 from_y + (Position)half_height - shift - y);
1115 if (quad4 != quad3)
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
CopyImageData(XImage * source,XImage * destination,Position from_x,Position from_y,Position to_x,Position to_y,Position at_x,Position at_y)1143 CopyImageData(XImage *source, XImage *destination,
1144 Position from_x, Position from_y,
1145 Position to_x, Position to_y,
1146 Position at_x, Position at_y)
1147 {
1148 Position x, y, delta_x, delta_y;
1149
1150 delta_x = to_x - from_x + 1;
1151 delta_y = to_y - from_y + 1;
1152
1153 for (x = 0; x < delta_x; x++)
1154 for (y = 0; y < delta_y; y++)
1155 if (GetBit(source, from_x + x, from_y + y))
1156 SetBit(destination, at_x + x, at_y + y);
1157 else
1158 ClearBit(destination, at_x + x, at_y + y);
1159 }
1160
1161 XImage *
ConvertToBitmapImage(BitmapWidget BW,XImage * image)1162 ConvertToBitmapImage(BitmapWidget BW, XImage *image)
1163 {
1164 XImage *bitmap_image;
1165 char *data;
1166 Position x, y;
1167
1168 data = CreateCleanData(Length(image->width, image->height));
1169 bitmap_image = CreateBitmapImage(BW, data,
1170 (Dimension) image->width,
1171 (Dimension) image->height);
1172
1173 for (x = 0; x < min(image->width, bitmap_image->width); x++)
1174 for (y = 0; y < min(image->height, bitmap_image->height); y++)
1175 if ((XGetPixel(image, x, y) != 0) != GetBit(bitmap_image, x, y))
1176 InvertBit(bitmap_image, x, y);
1177
1178 return bitmap_image;
1179 }
1180
1181 void
TransferImageData(XImage * source,XImage * destination)1182 TransferImageData(XImage *source, XImage *destination)
1183 {
1184 Position x, y;
1185
1186 for (x = 0; x < min(source->width, destination->width); x++)
1187 for (y = 0; y < min(source->height, destination->height); y++)
1188 if (GetBit(source, x, y) != GetBit(destination, x, y))
1189 InvertBit(destination, x, y);
1190 }
1191
1192 void
BWStore(Widget w)1193 BWStore(Widget w)
1194 {
1195 BitmapWidget BW = (BitmapWidget) w;
1196 Dimension width, height;
1197 char *storage_data;
1198
1199 if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) {
1200
1201 DestroyBitmapImage(&BW->bitmap.storage);
1202
1203 width = BW->bitmap.mark.to_x - BW->bitmap.mark.from_x + 1;
1204 height = BW->bitmap.mark.to_y - BW->bitmap.mark.from_y + 1;
1205
1206 storage_data = CreateCleanData(Length(width, height));
1207
1208 BW->bitmap.storage = CreateBitmapImage(BW,
1209 storage_data,
1210 width, height);
1211
1212 CopyImageData(BW->bitmap.image, BW->bitmap.storage,
1213 BW->bitmap.mark.from_x, BW->bitmap.mark.from_y,
1214 BW->bitmap.mark.to_x, BW->bitmap.mark.to_y,
1215 0, 0);
1216 }
1217 }
1218
1219 void
BWClearMarked(Widget w)1220 BWClearMarked(Widget w)
1221 {
1222 BitmapWidget BW = (BitmapWidget) w;
1223
1224 if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y))
1225 BWDrawFilledRectangle(w,
1226 BW->bitmap.mark.from_x,
1227 BW->bitmap.mark.from_y,
1228 BW->bitmap.mark.to_x,
1229 BW->bitmap.mark.to_y,
1230 Clear);
1231 }
1232
1233
1234 void
BWDragMarked(Widget w,Position at_x,Position at_y)1235 BWDragMarked(Widget w, Position at_x, Position at_y)
1236 {
1237 BitmapWidget BW = (BitmapWidget) w;
1238
1239 if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y))
1240 BWDrawRectangle(w,
1241 at_x, at_y,
1242 at_x + BW->bitmap.mark.to_x - BW->bitmap.mark.from_x,
1243 at_y + BW->bitmap.mark.to_y - BW->bitmap.mark.from_y,
1244 Highlight);
1245 }
1246
1247 void
BWDragStored(Widget w,Position at_x,Position at_y)1248 BWDragStored(Widget w, Position at_x, Position at_y)
1249 {
1250 BitmapWidget BW = (BitmapWidget) w;
1251
1252 if (BW->bitmap.storage)
1253 BWDrawRectangle(w,
1254 at_x, at_y,
1255 at_x + BW->bitmap.storage->width - 1,
1256 at_y + BW->bitmap.storage->height - 1,
1257 Highlight);
1258 }
1259
1260 static void
DrawImageData(BitmapWidget BW,XImage * image,Position at_x,Position at_y,int value)1261 DrawImageData(BitmapWidget BW, XImage *image,
1262 Position at_x, Position at_y, int value)
1263 {
1264 Position x, y;
1265 Boolean C, S, I, H;
1266 bit A, B;
1267
1268 C = value == Clear;
1269 S = value == Set;
1270 I = value == Invert;
1271 H = value == Highlight;
1272
1273 for (x = 0; x < image->width; x++)
1274 for (y = 0; y < image->height; y++) {
1275 A = GetBit(image, x, y);
1276 B = GetBit(BW->bitmap.image, at_x + x, at_y + y);
1277 if ((A & C) | ((A | B) & S) | ((A ^ B) & I) | ((A | B) & H))
1278 value = (A & H) ? Highlight : Set;
1279 else
1280 value = Clear;
1281 BWDrawPoint((Widget) BW,
1282 at_x + x, at_y + y,
1283 value);
1284 }
1285 }
1286
1287 void
BWRestore(Widget w,Position at_x,Position at_y,int value)1288 BWRestore(Widget w, Position at_x, Position at_y, int value)
1289 {
1290 BitmapWidget BW = (BitmapWidget) w;
1291
1292 if (BW->bitmap.storage) {
1293 DrawImageData(BW, BW->bitmap.storage, at_x, at_y, value);
1294 /*DestroyBitmapImage(&BW->bitmap.storage);*/
1295 }
1296 }
1297
1298 void
BWCopy(Widget w,Position at_x,Position at_y,int value)1299 BWCopy(Widget w, Position at_x, Position at_y, int value)
1300 {
1301 BitmapWidget BW = (BitmapWidget) w;
1302 XImage *storage;
1303 char *storage_data;
1304 Dimension width, height;
1305
1306 if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) {
1307
1308 width = BW->bitmap.mark.to_x - BW->bitmap.mark.from_x + 1;
1309 height = BW->bitmap.mark.to_y - BW->bitmap.mark.from_y + 1;
1310
1311 storage_data = CreateCleanData(Length(width, height));
1312
1313 storage = CreateBitmapImage(BW, storage_data, width, height);
1314
1315 CopyImageData(BW->bitmap.image, storage,
1316 BW->bitmap.mark.from_x, BW->bitmap.mark.from_y,
1317 BW->bitmap.mark.to_x, BW->bitmap.mark.to_y,
1318 0, 0);
1319
1320 DrawImageData(BW, storage, at_x, at_y, value);
1321
1322 DestroyBitmapImage(&storage);
1323 }
1324 }
1325
1326 /* void BWMark(); */
1327
1328 void
BWMove(Widget w,Position at_x,Position at_y,int value)1329 BWMove(Widget w, Position at_x, Position at_y, int value)
1330 {
1331 BitmapWidget BW = (BitmapWidget) w;
1332 XImage *storage;
1333 char *storage_data;
1334 Dimension width, height;
1335
1336 if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) {
1337
1338 width = BW->bitmap.mark.to_x - BW->bitmap.mark.from_x + 1;
1339 height = BW->bitmap.mark.to_y - BW->bitmap.mark.from_y + 1;
1340
1341 storage_data = CreateCleanData(Length(width, height));
1342
1343 storage = CreateBitmapImage(BW, storage_data, width, height);
1344
1345 CopyImageData(BW->bitmap.image, storage,
1346 BW->bitmap.mark.from_x, BW->bitmap.mark.from_y,
1347 BW->bitmap.mark.to_x, BW->bitmap.mark.to_y,
1348 0, 0);
1349
1350 BWDrawFilledRectangle(w,
1351 BW->bitmap.mark.from_x, BW->bitmap.mark.from_y,
1352 BW->bitmap.mark.to_x, BW->bitmap.mark.to_y,
1353 Clear);
1354
1355 DrawImageData(BW, storage, at_x, at_y, value);
1356
1357 BWMark(w, at_x, at_y,
1358 at_x + BW->bitmap.mark.to_x - BW->bitmap.mark.from_x,
1359 at_y + BW->bitmap.mark.to_y - BW->bitmap.mark.from_y);
1360
1361 DestroyBitmapImage(&storage);
1362 }
1363 }
1364
1365 void
BWRedrawMark(Widget w)1366 BWRedrawMark(Widget w)
1367 {
1368 BitmapWidget BW = (BitmapWidget) w;
1369
1370 if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y))
1371 XFillRectangle(XtDisplay(BW), XtWindow(BW), BW->bitmap.highlighting_gc,
1372 InWindowX(BW, BW->bitmap.mark.from_x),
1373 InWindowY(BW, BW->bitmap.mark.from_y),
1374 InWindowX(BW, BW->bitmap.mark.to_x + 1) -
1375 InWindowX(BW, BW->bitmap.mark.from_x),
1376 InWindowY(BW, BW->bitmap.mark.to_y + 1) -
1377 InWindowY(BW, BW->bitmap.mark.from_y));
1378 }
1379
1380 void
BWStoreToBuffer(Widget w)1381 BWStoreToBuffer(Widget w)
1382 {
1383 BitmapWidget BW = (BitmapWidget) w;
1384
1385 memmove( BW->bitmap.buffer->data, BW->bitmap.image->data,
1386 Length(BW->bitmap.image->width, BW->bitmap.image->height));
1387
1388 BW->bitmap.buffer_hot = BW->bitmap.hot;
1389 BW->bitmap.buffer_mark = BW->bitmap.mark;
1390 }
1391
1392 void
BWUnmark(Widget w)1393 BWUnmark(Widget w)
1394 {
1395 BitmapWidget BW = (BitmapWidget) w;
1396
1397 BW->bitmap.buffer_mark = BW->bitmap.mark;
1398
1399 if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) {
1400 XFillRectangle(XtDisplay(BW), XtWindow(BW), BW->bitmap.highlighting_gc,
1401 InWindowX(BW, BW->bitmap.mark.from_x),
1402 InWindowY(BW, BW->bitmap.mark.from_y),
1403 InWindowX(BW, BW->bitmap.mark.to_x + 1) -
1404 InWindowX(BW, BW->bitmap.mark.from_x),
1405 InWindowY(BW, BW->bitmap.mark.to_y + 1) -
1406 InWindowY(BW, BW->bitmap.mark.from_y));
1407
1408 BW->bitmap.mark.from_x = BW->bitmap.mark.from_y = NotSet;
1409 BW->bitmap.mark.to_x = BW->bitmap.mark.to_y = NotSet;
1410 }
1411 }
1412
1413 void
BWMark(Widget w,Position from_x,Position from_y,Position to_x,Position to_y)1414 BWMark(Widget w, Position from_x, Position from_y,
1415 Position to_x, Position to_y)
1416 {
1417 BitmapWidget BW = (BitmapWidget) w;
1418
1419 BWUnmark(w);
1420
1421 if (QuerySet(from_x, from_y)) {
1422 if ((from_x == to_x) && (from_y == to_y)) {
1423 /*
1424 BW->bitmap.mark.from_x = 0;
1425 BW->bitmap.mark.from_y = 0;
1426 BW->bitmap.mark.to_x = BW->bitmap.image->width - 1;
1427 BW->bitmap.mark.to_y = BW->bitmap.image->height - 1;
1428 */
1429 return;
1430 }
1431 else {
1432 QuerySwap(from_x, to_x);
1433 QuerySwap(from_y, to_y);
1434 from_x = max(0, from_x);
1435 from_y = max(0, from_y);
1436 to_x = min(BW->bitmap.image->width - 1, to_x);
1437 to_y = min(BW->bitmap.image->height - 1, to_y);
1438
1439 BW->bitmap.mark.from_x = from_x;
1440 BW->bitmap.mark.from_y = from_y;
1441 BW->bitmap.mark.to_x = to_x;
1442 BW->bitmap.mark.to_y = to_y;
1443 }
1444
1445 XFillRectangle(XtDisplay(BW), XtWindow(BW), BW->bitmap.highlighting_gc,
1446 InWindowX(BW, BW->bitmap.mark.from_x),
1447 InWindowY(BW, BW->bitmap.mark.from_y),
1448 InWindowX(BW, BW->bitmap.mark.to_x + 1) -
1449 InWindowX(BW, BW->bitmap.mark.from_x),
1450 InWindowY(BW, BW->bitmap.mark.to_y +1) -
1451 InWindowY(BW, BW->bitmap.mark.from_y));
1452 }
1453 }
1454
1455 void
BWMarkAll(Widget w)1456 BWMarkAll(Widget w)
1457 {
1458 BitmapWidget BW = (BitmapWidget) w;
1459
1460 BWMark(w, 0, 0, BW->bitmap.image->width - 1, BW->bitmap.image->height - 1);
1461 }
1462
1463 void
BWUndo(Widget w)1464 BWUndo(Widget w)
1465 {
1466 BitmapWidget BW = (BitmapWidget) w;
1467 Position x, y;
1468 char *tmp_data;
1469 XPoint tmp_hot;
1470 BWArea tmp_mark;
1471
1472 tmp_data = BW->bitmap.image->data;
1473 BW->bitmap.image->data = BW->bitmap.buffer->data;
1474 BW->bitmap.buffer->data = tmp_data;
1475
1476 tmp_hot = BW->bitmap.hot;
1477 tmp_mark = BW->bitmap.mark;
1478
1479 for (x = 0; x < BW->bitmap.image->width; x++)
1480 for (y = 0; y < BW->bitmap.image->height; y++)
1481 if (GetBit(BW->bitmap.image, x, y) != GetBit(BW->bitmap.buffer, x, y))
1482 DrawSquare(BW, x, y);
1483
1484 BWSetHotSpot(w, BW->bitmap.buffer_hot.x, BW->bitmap.buffer_hot.y);
1485 /*
1486 BWMark(w, BW->bitmap.buffer_mark.from_x, BW->bitmap.buffer_mark.from_y,
1487 BW->bitmap.buffer_mark.to_x, BW->bitmap.buffer_mark.to_y);
1488 */
1489 BW->bitmap.buffer_hot = tmp_hot;
1490 BW->bitmap.buffer_mark= tmp_mark;
1491
1492 }
1493
1494 void
BWHighlightAxes(Widget w)1495 BWHighlightAxes(Widget w)
1496 {
1497 BitmapWidget BW = (BitmapWidget) w;
1498
1499 XDrawLine(XtDisplay(BW), XtWindow(BW),
1500 BW->bitmap.axes_gc,
1501 InWindowX(BW, 0),
1502 InWindowY(BW, 0),
1503 InWindowX(BW, BW->bitmap.width),
1504 InWindowY(BW, BW->bitmap.height));
1505 XDrawLine(XtDisplay(BW), XtWindow(BW),
1506 BW->bitmap.axes_gc,
1507 InWindowX(BW, BW->bitmap.width),
1508 InWindowY(BW, 0),
1509 InWindowX(BW, 0),
1510 InWindowY(BW, BW->bitmap.height));
1511 XDrawLine(XtDisplay(BW), XtWindow(BW),
1512 BW->bitmap.axes_gc,
1513 InWindowX(BW, 0),
1514 InWindowY(BW, (float)BW->bitmap.height / 2.0),
1515 InWindowX(BW, BW->bitmap.width),
1516 InWindowY(BW, (float)BW->bitmap.height / 2.0));
1517 XDrawLine(XtDisplay(BW), XtWindow(BW),
1518 BW->bitmap.axes_gc,
1519 InWindowX(BW, (float)BW->bitmap.width / 2.0),
1520 InWindowY(BW, 0),
1521 InWindowX(BW, (float)BW->bitmap.width / 2.0),
1522 InWindowY(BW, BW->bitmap.height));
1523 }
1524
1525 typedef struct {
1526 Position *x, *y;
1527 Dimension *width, *height;
1528 } Table;
1529
1530 XImage *
ScaleBitmapImage(BitmapWidget BW,XImage * src,double scale_x,double scale_y)1531 ScaleBitmapImage(BitmapWidget BW, XImage *src,
1532 double scale_x, double scale_y)
1533 {
1534 char *data;
1535 XImage *dst;
1536 Table table;
1537 Position x, y, w, h;
1538 Dimension width, height;
1539 bit pixel;
1540
1541 width = max(rint(scale_x * src->width), 1);
1542 height = max(rint(scale_y * src->height), 1);
1543
1544 data = CreateCleanData(Length(width, height));
1545 dst = CreateBitmapImage(BW, data, width, height);
1546
1547 /*
1548 * It would be nice to check if width or height < 1.0 and
1549 * average the skipped pixels. But, it is slow as it is now.
1550 */
1551 if (scale_x == 1.0 && scale_y == 1.0)
1552 memmove( dst->data, src->data, Length(width, height));
1553 else {
1554 table.x = (Position *) XtMalloc(sizeof(Position) * src->width);
1555 table.y = (Position *) XtMalloc(sizeof(Position) * src->height);
1556 table.width = (Dimension *) XtMalloc(sizeof(Dimension) * src->width);
1557 table.height = (Dimension *) XtMalloc(sizeof(Dimension) * src->height);
1558
1559 for (x = 0; x < src->width; x++) {
1560 table.x[x] = rint(scale_x * x);
1561 table.width[x] = rint(scale_x * (x + 1)) - rint(scale_x * x);
1562 }
1563 for (y = 0; y < src->height; y++) {
1564 table.y[y] = rint(scale_y * y);
1565 table.height[y] = rint(scale_y * (y + 1)) - rint(scale_y * y);
1566 }
1567
1568 for (x = 0; x < src->width; x++)
1569 for (y = 0; y < src->height; y++) {
1570 pixel = GetBit(src, x, y);
1571 for (w = 0; (int)w < (int)table.width[x]; w++)
1572 for (h = 0; (int)h < (int)table.height[y]; h++)
1573 if (pixel) SetBit(dst,
1574 table.x[x] + w,
1575 table.y[y] + h);
1576 }
1577
1578 XtFree((char *)table.x);
1579 XtFree((char *)table.y);
1580 XtFree((char *)table.width);
1581 XtFree((char *)table.height);
1582 }
1583
1584 return (dst);
1585 }
1586
1587 /*****************************************************************************/
1588