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