2
/* Lefteris Koutsofios - AT&T Bell Laboratories */
12
#define WCU widget->u.c
13
#define WINDOW widget->u.c->window
14
#define GC widget->u.c->gc
15
#define ISVISIBLE(r) ( \
16
(r.o.x <= WCU->clip.c.x) && (r.c.x >= WCU->clip.o.x) && \
17
(r.o.y <= WCU->clip.c.y) && (r.c.y >= WCU->clip.o.y) \
20
#define IS8BIT(font) ((font)->min_byte1 == 0 && (font)->max_byte1 == 0)
22
static struct cursormap_t {
25
} cursormap[XC_num_glyphs];
26
static int curcursori = -1;
28
#define max(a, b) (((a) >= (b)) ? (a) : (b))
29
#define min(a, b) (((a) <= (b)) ? (a) : (b))
31
static char gstyles[][2] = {
32
/* G_SOLID */ { 16, 0, },
33
/* G_DASHED */ { 4, 4, },
34
/* G_DOTTED */ { 2, 2, },
35
/* G_LONGDASHED */ { 4, 12, },
36
/* G_SHORTDASHED */ { 12, 4, },
39
static char grays[][4] = {
40
{ 0x00,0x00,0x00,0x00, },
41
{ 0x08,0x00,0x00,0x00, },
42
{ 0x08,0x00,0x02,0x00, },
43
{ 0x0A,0x00,0x02,0x00, },
44
{ 0x0A,0x00,0x0A,0x00, },
45
{ 0x0A,0x04,0x0A,0x00, },
46
{ 0x0A,0x04,0x0A,0x01, },
47
{ 0x0A,0x05,0x0A,0x01, },
48
{ 0x0A,0x05,0x0A,0x05, },
49
{ 0x0E,0x05,0x0A,0x05, },
50
{ 0x0E,0x05,0x0B,0x05, },
51
{ 0x0F,0x05,0x0B,0x05, },
52
{ 0x0F,0x05,0x0F,0x05, },
53
{ 0x0F,0x0D,0x0F,0x05, },
54
{ 0x0F,0x0D,0x0F,0x07, },
55
{ 0x0F,0x0F,0x0F,0x07, },
56
{ 0x0F,0x0F,0x0F,0x0F, },
59
static void bezier (PIXpoint_t, PIXpoint_t, PIXpoint_t, PIXpoint_t);
60
static XFontStruct *findfont (char *, int);
61
static int scalebitmap (Gwidget_t *, Gbitmap_t *, Gsize_t, int, int);
62
static void setgattr (Gwidget_t *, Ggattr_t *);
64
static PIXrect_t rdrawtopix (Gwidget_t *, Grect_t);
65
static PIXpoint_t pdrawtopix (Gwidget_t *, Gpoint_t);
66
static PIXsize_t sdrawtopix (Gwidget_t *, Gsize_t);
67
static Gpoint_t Gppixtodraw (Gwidget_t *, PIXpoint_t);
68
static Gsize_t spixtodraw (Gwidget_t *, PIXsize_t);
69
static Grect_t rpixtodraw (Gwidget_t *, PIXrect_t);
70
static PIXrect_t rdrawtobpix (Gbitmap_t *, Grect_t);
71
static PIXpoint_t pdrawtobpix (Gbitmap_t *, Gpoint_t);
72
static void adjustclip (Gwidget_t *);
74
static Bool cwvpredicate (Display *, XEvent *, XPointer);
75
static void cweventhandler (Widget, XtPointer, XEvent *, Boolean *);
76
static Bool cwepredicate (Display *, XEvent *, XPointer);
78
int GCcreatewidget (Gwidget_t *parent, Gwidget_t *widget,
79
int attrn, Gwattr_t *attrp) {
81
Dimension width, height;
82
#ifdef FEATURE_BACKINGSTORE
83
XSetWindowAttributes xswa;
88
int curi, color, ai, r, g, b, i;
95
Gerr (POS, G_ERRNOPARENTWIDGET);
99
WCU->needredraw = FALSE;
100
WCU->buttonsdown = 0;
101
WCU->bstate[0] = WCU->bstate[1] = WCU->bstate[2] = 0;
102
ps.x = ps.y = MINCWSIZE;
104
for (ai = 0; ai < attrn; ai++) {
105
switch (attrp[ai].id) {
107
GETSIZE (attrp[ai].u.s, ps, MINCWSIZE);
109
case G_ATTRBORDERWIDTH:
110
ADD2ARGS (XtNborderWidth, attrp[ai].u.i);
114
if (Strcmp ("gmap", attrp[ai].u.t) == 0) {
117
Gerr (POS, G_ERRBADATTRVALUE, attrp[ai].u.t);
123
/* will do it after the widget is created */
126
/* will do it after the widget is created */
129
/* will do it after the widget is created */
132
/* will do it after the widget is created */
135
Gerr (POS, G_ERRCANNOTSETATTR1, "windowid");
138
WCU->func = (Gcanvascb) attrp[ai].u.func;
141
widget->udata = attrp[ai].u.u;
144
Gerr (POS, G_ERRBADATTRID, attrp[ai].id);
148
ADD2ARGS (XtNwidth, ps.x);
149
ADD2ARGS (XtNheight, ps.y);
152
vip = pfChooseFBConfig (Gdisplay, -1, NULL);
153
ADD2ARGS (GLwNvisualInfo, vip);
154
if (!(widget->w = XtCreateWidget ("graphics", glwDrawingAreaWidgetClass,
155
parent->w, argp, argn))) {
156
Gerr (POS, G_ERRCANNOTCREATEWIDGET);
160
if (!(widget->w = XtCreateWidget ("graphics", coreWidgetClass,
161
parent->w, argp, argn))) {
162
Gerr (POS, G_ERRCANNOTCREATEWIDGET);
166
WCU->gmapmode = gmapmode;
168
if (!(widget->w = XtCreateWidget ("graphics", coreWidgetClass,
169
parent->w, argp, argn))) {
170
Gerr (POS, G_ERRCANNOTCREATEWIDGET);
174
XtOverrideTranslations (widget->w, Gcwanytable);
175
XtAddEventHandler (widget->w, VisibilityChangeMask | ExposureMask,
176
FALSE, cweventhandler, (XtPointer) 0);
177
Glazymanage (widget->w);
179
#ifdef FEATURE_BACKINGSTORE
180
xswa.backing_store = WhenMapped;
181
XChangeWindowAttributes (Gdisplay, XtWindow (widget->w),
182
CWBackingStore, &xswa);
184
/* wait for window to become visible */
185
XPeekIfEvent (Gdisplay, &ev, cwvpredicate, (XPointer) XtWindow (widget->w));
187
ADD2ARGS (XtNwidth, &width);
188
ADD2ARGS (XtNheight, &height);
189
XtGetValues (widget->w, argp, argn);
190
ps.x = width, ps.y = height;
191
WCU->window = XtWindow (widget->w);
192
WCU->cmap = DefaultColormap (Gdisplay, Gscreenn);
193
WCU->gc = XCreateGC (Gdisplay, WCU->window, 0, NULL);
195
WCU->colors[0].color.pixel = WCU->colors[1].color.pixel = 1000000;
196
ADD2ARGS (XtNbackground, &WCU->colors[0].color.pixel);
197
ADD2ARGS (XtNforeground, &WCU->colors[1].color.pixel);
198
XtGetValues (widget->w, argp, argn);
199
if (WCU->colors[0].color.pixel == 1000000) {
200
if (XGetGCValues (Gdisplay, GC, GCBackground, &gcv) != 0)
201
WCU->colors[0].color.pixel = gcv.background;
203
WCU->colors[0].color.pixel = WhitePixel (Gdisplay, Gscreenn);
205
if (WCU->colors[1].color.pixel == 1000000) {
206
if (XGetGCValues (Gdisplay, GC, GCForeground, &gcv) != 0)
207
WCU->colors[1].color.pixel = gcv.foreground;
209
WCU->colors[1].color.pixel = BlackPixel (Gdisplay, Gscreenn);
211
XQueryColor (Gdisplay, WCU->cmap, &WCU->colors[0].color);
212
WCU->colors[0].inuse = TRUE;
213
XQueryColor (Gdisplay, WCU->cmap, &WCU->colors[1].color);
214
WCU->colors[1].inuse = TRUE;
215
WCU->allocedcolor[0] = WCU->allocedcolor[1] = FALSE;
216
for (i = 2; i < G_MAXCOLORS; i++)
217
WCU->colors[i].inuse = FALSE;
218
WCU->gattr.color = 1;
219
XSetBackground (Gdisplay, GC, WCU->colors[0].color.pixel);
220
XSetForeground (Gdisplay, GC, WCU->colors[1].color.pixel);
221
WCU->gattr.width = 0;
222
WCU->gattr.mode = G_SRC;
224
WCU->gattr.style = 0;
225
WCU->defgattr = WCU->gattr;
227
WCU->wrect.o.x = 0.0, WCU->wrect.o.y = 0.0;
228
WCU->wrect.c.x = 1.0, WCU->wrect.c.y = 1.0;
229
WCU->vsize.x = ps.x, WCU->vsize.y = ps.y;
231
XSetFillStyle (Gdisplay, GC, FillTiled);
232
for (i = 0; i < 17; i++)
233
WCU->grays[i] = XCreatePixmapFromBitmapData (Gdisplay, WCU->window,
234
&grays[i][0], 4, 4, BlackPixel (Gdisplay, Gscreenn),
235
WhitePixel (Gdisplay, Gscreenn), 1);
237
for (ai = 0; ai < attrn; ai++) {
238
switch (attrp[ai].id) {
240
if ((curi = XmuCursorNameToIndex (attrp[ai].u.t)) == -1) {
241
if (Strcmp (attrp[ai].u.t, "default") == 0) {
242
XUndefineCursor (Gdisplay, XtWindow (widget->w));
245
Gerr (POS, G_ERRNOSUCHCURSOR, attrp[ai].u.t);
249
if (!cursormap[curi].id) {
250
cursormap[curi].id = XCreateFontCursor (Gdisplay, curi);
251
strcpy (cursormap[curi].name, attrp[ai].u.t);
253
XDefineCursor (Gdisplay, XtWindow (widget->w),
259
color = attrp[ai].u.c.index;
260
if (color < 0 || color > G_MAXCOLORS) {
261
Gerr (POS, G_ERRBADCOLORINDEX, color);
264
r = attrp[ai].u.c.r * 257;
265
g = attrp[ai].u.c.g * 257;
266
b = attrp[ai].u.c.b * 257;
267
cp = &WCU->colors[color].color;
268
if (WCU->colors[color].inuse)
269
if (cp->red != r || cp->green != g || cp->blue != b)
270
if (color > 1 || WCU->allocedcolor[color])
271
XFreeColors (Gdisplay, WCU->cmap, &cp->pixel, 1, 0);
272
cp->red = r, cp->green = g, cp->blue = b;
273
if (XAllocColor (Gdisplay, WCU->cmap, cp)) {
274
WCU->colors[color].inuse = TRUE;
276
WCU->allocedcolor[color] = TRUE;
278
/* XAllocColor may change the rgb values */
279
cp->red = r, cp->green = g, cp->blue = b;
280
if (color == WCU->gattr.color)
281
WCU->gattr.color = -1;
282
if (color == 0 || color == 1) {
285
ADD2ARGS (XtNbackground, cp->pixel);
287
ADD2ARGS (XtNforeground, cp->pixel);
288
XtSetValues (widget->w, argp, argn);
292
WCU->vsize.x = (int) (attrp[ai].u.s.x + 0.5);
293
WCU->vsize.y = (int) (attrp[ai].u.s.y + 0.5);
295
ADD2ARGS (XtNwidth, WCU->vsize.x);
296
ADD2ARGS (XtNheight, WCU->vsize.y);
297
XtSetValues (widget->w, argp, argn);
300
WCU->wrect = attrp[ai].u.r;
308
int GCsetwidgetattr (Gwidget_t *widget, int attrn, Gwattr_t *attrp) {
311
int curi, color, ai, r, g, b;
314
for (ai = 0; ai < attrn; ai++) {
315
switch (attrp[ai].id) {
317
GETSIZE (attrp[ai].u.s, ps, MINCWSIZE);
318
ADD2ARGS (XtNwidth, ps.x);
319
ADD2ARGS (XtNheight, ps.y);
321
case G_ATTRBORDERWIDTH:
322
ADD2ARGS (XtNborderWidth, attrp[ai].u.i);
325
if ((curi = XmuCursorNameToIndex (attrp[ai].u.t)) == -1) {
326
if (Strcmp (attrp[ai].u.t, "default") == 0) {
327
XUndefineCursor (Gdisplay, XtWindow (widget->w));
330
Gerr (POS, G_ERRNOSUCHCURSOR, attrp[ai].u.t);
334
if (!cursormap[curi].id) {
335
cursormap[curi].id = XCreateFontCursor (Gdisplay, curi);
336
strcpy (cursormap[curi].name, attrp[ai].u.t);
338
XDefineCursor (Gdisplay, XtWindow (widget->w),
345
color = attrp[ai].u.c.index;
346
if (color < 0 || color > G_MAXCOLORS) {
347
Gerr (POS, G_ERRBADCOLORINDEX, color);
350
r = attrp[ai].u.c.r * 257;
351
g = attrp[ai].u.c.g * 257;
352
b = attrp[ai].u.c.b * 257;
353
cp = &WCU->colors[color].color;
354
if (WCU->colors[color].inuse)
355
if (cp->red != r || cp->green != g || cp->blue != b)
356
if (color > 1 || WCU->allocedcolor[color])
357
XFreeColors (Gdisplay, WCU->cmap, &cp->pixel, 1, 0);
358
cp->red = r, cp->green = g, cp->blue = b;
359
if (XAllocColor (Gdisplay, WCU->cmap, cp)) {
360
WCU->colors[color].inuse = TRUE;
362
WCU->allocedcolor[color] = TRUE;
364
/* XAllocColor may change the rgb values */
365
cp->red = r, cp->green = g, cp->blue = b;
366
if (color == WCU->gattr.color)
367
WCU->gattr.color = -1;
370
WCU->vsize.x = (int) (attrp[ai].u.s.x + 0.5);
371
WCU->vsize.y = (int) (attrp[ai].u.s.y + 0.5);
372
ADD2ARGS (XtNwidth, WCU->vsize.x);
373
ADD2ARGS (XtNheight, WCU->vsize.y);
374
XtSetValues (widget->w, argp, argn);
379
WCU->wrect = attrp[ai].u.r;
380
XtSetValues (widget->w, argp, argn);
385
Gerr (POS, G_ERRCANNOTSETATTR2, "windowid");
388
WCU->func = (Gcanvascb) attrp[ai].u.func;
391
widget->udata = attrp[ai].u.u;
394
Gerr (POS, G_ERRBADATTRID, attrp[ai].id);
398
XtSetValues (widget->w, argp, argn);
402
int GCgetwidgetattr (Gwidget_t *widget, int attrn, Gwattr_t *attrp) {
404
Dimension width, height;
407
for (ai = 0; ai < attrn; ai++) {
409
switch (attrp[ai].id) {
411
ADD2ARGS (XtNwidth, &width);
412
ADD2ARGS (XtNheight, &height);
413
XtGetValues (widget->w, argp, argn);
414
attrp[ai].u.s.x = width, attrp[ai].u.s.y = height;
416
case G_ATTRBORDERWIDTH:
417
ADD2ARGS (XtNborderWidth, &width);
418
XtGetValues (widget->w, argp, argn);
419
attrp[ai].u.i = width;
422
attrp[ai].u.t = (curcursori == -1) ?
423
"default" : cursormap[curcursori].name;
426
color = attrp[ai].u.c.index;
427
if (color < 0 || color > G_MAXCOLORS) {
428
Gerr (POS, G_ERRBADCOLORINDEX, color);
431
if (WCU->colors[color].inuse) {
432
cp = &WCU->colors[color].color;
433
attrp[ai].u.c.r = cp->red / 257.0;
434
attrp[ai].u.c.g = cp->green / 257.0;
435
attrp[ai].u.c.b = cp->blue / 257.0;
437
attrp[ai].u.c.r = -1;
438
attrp[ai].u.c.g = -1;
439
attrp[ai].u.c.b = -1;
443
attrp[ai].u.s = WCU->vsize;
446
attrp[ai].u.r = WCU->wrect;
449
sprintf (&Gbufp[0], "0x%lx", XtWindow (widget->w));
450
attrp[ai].u.t = &Gbufp[0];
453
attrp[ai].u.func = WCU->func;
456
attrp[ai].u.u = widget->udata;
459
Gerr (POS, G_ERRBADATTRID, attrp[ai].id);
466
int GCdestroywidget (Gwidget_t *widget) {
467
XtDestroyWidget (widget->w);
471
int GCcanvasclear (Gwidget_t *widget) {
475
XClearWindow (Gdisplay, WINDOW);
477
WCU->needredraw = FALSE;
478
XSync (Gdisplay, False);
480
while (XCheckIfEvent (Gdisplay,
481
&ev, cwepredicate, (XPointer) WINDOW) == True)
488
int GCsetgfxattr (Gwidget_t *widget, Ggattr_t *ap) {
489
setgattr (widget, ap);
490
WCU->defgattr = WCU->gattr;
494
int GCgetgfxattr (Gwidget_t *widget, Ggattr_t *ap) {
495
if ((ap->flags & G_GATTRCOLOR))
496
ap->color = WCU->gattr.color;
497
if ((ap->flags & G_GATTRWIDTH))
498
ap->width = WCU->gattr.width;
499
if ((ap->flags & G_GATTRMODE))
500
ap->mode = WCU->gattr.mode;
501
if ((ap->flags & G_GATTRFILL))
502
ap->fill = WCU->gattr.fill;
503
if ((ap->flags & G_GATTRSTYLE))
504
ap->style = WCU->gattr.style;
508
int GCarrow (Gwidget_t *widget, Gpoint_t gp1, Gpoint_t gp2, Ggattr_t *ap) {
509
PIXpoint_t pp1, pp2, pa, pb, pd;
514
gr.o.x = gp1.x, gr.c.x = gp2.x;
516
gr.o.x = gp2.x, gr.c.x = gp1.x;
518
gr.o.y = gp1.y, gr.c.y = gp2.y;
520
gr.o.y = gp2.y, gr.c.y = gp1.y;
523
pp1 = pdrawtopix (widget, gp1), pp2 = pdrawtopix (widget, gp2);
524
pd.x = pp1.x - pp2.x, pd.y = pp1.y - pp2.y;
525
if (pd.x == 0 && pd.y == 0)
527
tangent = atan2 ((double) pd.y, (double) pd.x);
528
if ((l = sqrt ((double) (pd.x * pd.x + pd.y * pd.y))) > 30)
530
pa.x = l * cos (tangent + M_PI / 7) + pp2.x;
531
pa.y = l * sin (tangent + M_PI / 7) + pp2.y;
532
pb.x = l * cos (tangent - M_PI / 7) + pp2.x;
533
pb.y = l * sin (tangent - M_PI / 7) + pp2.y;
534
setgattr (widget, ap);
535
XDrawLine (Gdisplay, WINDOW, GC, pp1.x, pp1.y, pp2.x, pp2.y);
536
XDrawLine (Gdisplay, WINDOW, GC, pa.x, pa.y, pp2.x, pp2.y);
537
XDrawLine (Gdisplay, WINDOW, GC, pb.x, pb.y, pp2.x, pp2.y);
541
int GCline (Gwidget_t *widget, Gpoint_t gp1, Gpoint_t gp2, Ggattr_t *ap) {
546
gr.o.x = gp1.x, gr.c.x = gp2.x;
548
gr.o.x = gp2.x, gr.c.x = gp1.x;
550
gr.o.y = gp1.y, gr.c.y = gp2.y;
552
gr.o.y = gp2.y, gr.c.y = gp1.y;
555
pp1 = pdrawtopix (widget, gp1), pp2 = pdrawtopix (widget, gp2);
556
setgattr (widget, ap);
557
XDrawLine (Gdisplay, WINDOW, GC, pp1.x, pp1.y, pp2.x, pp2.y);
561
int GCbox (Gwidget_t *widget, Grect_t gr, Ggattr_t *ap) {
566
p.x = gr.o.x, gr.o.x = gr.c.x, gr.c.x = p.x;
568
p.y = gr.o.y, gr.o.y = gr.c.y, gr.c.y = p.y;
571
pr = rdrawtopix (widget, gr);
572
setgattr (widget, ap);
574
XFillRectangle (Gdisplay, WINDOW, GC,
575
pr.o.x, pr.o.y, pr.c.x - pr.o.x, pr.c.y - pr.o.y);
577
XDrawRectangle (Gdisplay, WINDOW, GC,
578
pr.o.x, pr.o.y, pr.c.x - pr.o.x, pr.c.y - pr.o.y);
582
int GCpolygon (Gwidget_t *widget, int gpn, Gpoint_t *gpp, Ggattr_t *ap) {
588
gr.o = gpp[0], gr.c = gpp[0];
589
for (i = 1; i < gpn; i++) {
590
gr.o.x = min (gr.o.x, gpp[i].x);
591
gr.o.y = min (gr.o.y, gpp[i].y);
592
gr.c.x = max (gr.c.x, gpp[i].x);
593
gr.c.y = max (gr.c.y, gpp[i].y);
597
if (gpn + 1 > Gppn) {
598
n = (((gpn + 1) + PPINCR - 1) / PPINCR) * PPINCR;
599
Gppp = Marraygrow (Gppp, (long) n * PPSIZE);
602
for (i = 0; i < gpn; i++)
603
Gppp[i] = pdrawtopix (widget, gpp[i]);
604
setgattr (widget, ap);
605
if (WCU->gattr.fill) {
606
if (Gppp[gpn - 1].x != Gppp[0].x || Gppp[gpn - 1].y != Gppp[0].y)
607
Gppp[gpn] = Gppp[0], gpn++;
608
XFillPolygon (Gdisplay, WINDOW, GC, Gppp, gpn,
609
Complex, CoordModeOrigin);
611
XDrawLines (Gdisplay, WINDOW, GC, Gppp, gpn, CoordModeOrigin);
615
int GCsplinegon (Gwidget_t *widget, int gpn, Gpoint_t *gpp, Ggattr_t *ap) {
616
PIXpoint_t p0, p1, p2, p3;
622
gr.o = gpp[0], gr.c = gpp[0];
623
for (i = 1; i < gpn; i++) {
624
gr.o.x = min (gr.o.x, gpp[i].x);
625
gr.o.y = min (gr.o.y, gpp[i].y);
626
gr.c.x = max (gr.c.x, gpp[i].x);
627
gr.c.y = max (gr.c.y, gpp[i].y);
633
n = (((Gppi + 1) + PPINCR - 1) / PPINCR) * PPINCR;
634
Gppp = Marraygrow (Gppp, (long) n * PPSIZE);
637
Gppp[0] = p3 = pdrawtopix (widget, gpp[0]);
638
for (i = 1; i < gpn; i += 3) {
640
p1 = pdrawtopix (widget, gpp[i]);
641
p2 = pdrawtopix (widget, gpp[i + 1]);
642
p3 = pdrawtopix (widget, gpp[i + 2]);
643
bezier (p0, p1, p2, p3);
645
setgattr (widget, ap);
646
if (WCU->gattr.fill) {
647
if (Gppp[Gppi - 1].x != Gppp[0].x || Gppp[Gppi - 1].y != Gppp[0].y)
648
Gppp[Gppi] = Gppp[0], Gppi++;
649
XFillPolygon (Gdisplay, WINDOW, GC, Gppp, Gppi,
650
Complex, CoordModeOrigin);
652
XDrawLines (Gdisplay, WINDOW, GC, Gppp, Gppi, CoordModeOrigin);
656
static void bezier (PIXpoint_t p0, PIXpoint_t p1,
657
PIXpoint_t p2, PIXpoint_t p3) {
658
Gpoint_t gp0, gp1, gp2;
664
if ((s.x = p3.x - p0.x) < 0)
666
if ((s.y = p3.y - p0.y) < 0)
672
for (i = 0; i <= steps; i++) {
673
t = i / (double) steps;
674
gp0.x = p0.x + t * (p1.x - p0.x);
675
gp0.y = p0.y + t * (p1.y - p0.y);
676
gp1.x = p1.x + t * (p2.x - p1.x);
677
gp1.y = p1.y + t * (p2.y - p1.y);
678
gp2.x = p2.x + t * (p3.x - p2.x);
679
gp2.y = p2.y + t * (p3.y - p2.y);
680
gp0.x = gp0.x + t * (gp1.x - gp0.x);
681
gp0.y = gp0.y + t * (gp1.y - gp0.y);
682
gp1.x = gp1.x + t * (gp2.x - gp1.x);
683
gp1.y = gp1.y + t * (gp2.y - gp1.y);
684
p.x = gp0.x + t * (gp1.x - gp0.x) + 0.5;
685
p.y = gp0.y + t * (gp1.y - gp0.y) + 0.5;
687
n = (((Gppi + 1) + PPINCR - 1) / PPINCR) * PPINCR;
688
Gppp = Marraygrow (Gppp, (long) n * PPSIZE);
695
int GCarc (Gwidget_t *widget, Gpoint_t gc, Gsize_t gs, double ang1,
696
double ang2, Ggattr_t *ap) {
701
gr.o.x = gc.x - gs.x, gr.o.y = gc.y - gs.y;
702
gr.c.x = gc.x + gs.x, gr.c.y = gc.y + gs.y;
705
pc = pdrawtopix (widget, gc), ps = sdrawtopix (widget, gs);
706
setgattr (widget, ap);
708
XFillArc (Gdisplay, WINDOW, GC, pc.x - ps.x, pc.y - ps.y,
709
ps.x * 2, ps.y * 2, (int) (ang1 * 64), (int) (ang2 * 64));
711
XDrawArc (Gdisplay, WINDOW, GC, pc.x - ps.x, pc.y - ps.y,
712
ps.x * 2, ps.y * 2, (int) (ang1 * 64), (int) (ang2 * 64));
716
int GCtext (Gwidget_t *widget, Gtextline_t *tlp, int n, Gpoint_t go,
717
char *fn, double fs, char *justs, Ggattr_t *ap) {
724
int dir, asc, des, x, y, w, h, i;
727
po = pdrawtopix (widget, go);
729
ps = sdrawtopix (widget, gs);
730
if (!(font = findfont (fn, ps.y))) {
731
XDrawRectangle (Gdisplay, WINDOW, GC, po.x, po.y, 1, 1);
734
setgattr (widget, ap);
736
for (w = h = 0, i = 0; i < n; i++) {
738
XTextExtents (font, tlp[i].p, tlp[i].n, &dir, &asc, &des, &txtinfo);
740
XTextExtents16 (font, (XChar2b *) tlp[i].p, tlp[i].n / 2,
741
&dir, &asc, &des, &txtinfo);
742
tlp[i].w = txtinfo.width, tlp[i].h = asc + des;
743
w = max (w, txtinfo.width), h += asc + des;
746
case 'l': po.x += w / 2; break;
747
case 'r': po.x -= w / 2; break;
750
case 'd': po.y -= h; break;
751
case 'c': po.y -= h / 2; break;
753
pr.o.x = po.x - w / 2, pr.o.y = po.y;
754
pr.c.x = po.x + w / 2, pr.c.y = po.y + h;
755
gr = rpixtodraw (widget, pr);
758
for (i = 0; i < n; i++) {
760
case 'l': x = po.x - w / 2; break;
761
case 'n': x = po.x - tlp[i].w / 2; break;
762
case 'r': x = po.x - (tlp[i].w - w / 2); break;
764
y = po.y + (i + 1) * tlp[i].h - des;
766
XDrawString (Gdisplay, WINDOW, GC, x, y, tlp[i].p, tlp[i].n);
768
XDrawString16 (Gdisplay, WINDOW, GC, x, y,
769
(XChar2b *) tlp[i].p, tlp[i].n / 2);
774
int GCgettextsize (Gwidget_t *widget, Gtextline_t *tlp, int n, char *fn,
775
double fs, Gsize_t *gsp) {
779
int i, dir, asc, des;
783
ps = sdrawtopix (widget, gs);
784
if (!(font = findfont (fn, ps.y))) {
785
gsp->x = 1, gsp->y = 1;
789
for (ps.x = ps.y = 0, i = 0; i < n; i++) {
791
XTextExtents (font, tlp[i].p, tlp[i].n, &dir, &asc, &des, &txtinfo);
793
XTextExtents16 (font, (XChar2b *) tlp[i].p, tlp[i].n / 2,
794
&dir, &asc, &des, &txtinfo);
795
ps.x = max (ps.x, txtinfo.width), ps.y += asc + des;
797
*gsp = spixtodraw (widget, ps);
801
static XFontStruct *findfont (char *name, int size) {
805
if (name[0] == '\000')
806
return Gfontp[0].font;
808
sprintf (&Gbufp[0], name, size);
809
for (fi = 0; fi < Gfontn; fi++)
810
if (Strcmp (&Gbufp[0], Gfontp[fi].name) == 0)
811
return Gfontp[fi].font;
812
if (!(font = XLoadQueryFont (Gdisplay, &Gbufp[0]))) {
813
n = strlen (&Gbufp[0]) + 1;
814
for (i = 1; i < size; i++) {
815
sprintf (&Gbufp[n], name, size - i);
816
if ((font = XLoadQueryFont (Gdisplay, &Gbufp[n])))
818
sprintf (&Gbufp[n], name, size + i);
819
if ((font = XLoadQueryFont (Gdisplay, &Gbufp[n])))
824
font = Gfontp[0].font;
826
Gfontp = Marraygrow (Gfontp, (long) (Gfontn + 1) * FONTSIZE);
827
Gfontp[Gfontn].name = strdup (&Gbufp[0]);
828
Gfontp[Gfontn].font = font;
833
int GCcreatebitmap (Gwidget_t *widget, Gbitmap_t *bitmap, Gsize_t s) {
835
Gerr (POS, G_ERRNOPARENTWIDGET);
839
Gerr (POS, G_ERRNOBITMAP);
842
if (!(bitmap->u.bmap.orig = XCreatePixmap (Gdisplay, XtWindow (widget->w),
843
(int) s.x, (int) s.y, Gdepth))) {
844
Gerr (POS, G_ERRCANNOTCREATEBITMAP);
847
bitmap->u.bmap.scaled = 0;
848
bitmap->scale.x = bitmap->scale.y = 1;
849
bitmap->ctype = widget->type;
850
bitmap->canvas = widget - &Gwidgets[0];
855
int GCdestroybitmap (Gbitmap_t *bitmap) {
857
Gerr (POS, G_ERRNOBITMAP);
860
XFreePixmap (Gdisplay, bitmap->u.bmap.orig);
861
if (bitmap->u.bmap.scaled)
862
XFreePixmap (Gdisplay, bitmap->u.bmap.scaled);
866
#define COMPDIFF(a, b) (((a) > (b)) ? (a) - (b) : (b) - (a))
867
#define CDIFF(a, b) (COMPDIFF (a.red, b[0]) + COMPDIFF (a.green, b[1]) + \
868
COMPDIFF (a.blue, b[2]))
869
#define CMINMAXDIFF 20000
871
int GCreadbitmap (Gwidget_t *widget, Gbitmap_t *bitmap, FILE *fp) {
874
XColor colors[G_MAXCOLORS];
879
int cmaxdiff, colori, colorn, bufn, bufi, step, x, y, k;
882
Gerr (POS, G_ERRNOPARENTWIDGET);
886
Gerr (POS, G_ERRNOBITMAP);
892
if (!fgets (bufp, 2048, fp)) {
893
Gerr (POS, G_ERRCANNOTREADBITMAP);
898
for (; *s1 && isspace (*s1); s1++)
900
if (!*s1 || *s1 == '#')
904
if (strncmp (s1, "P6", 2) != 0) {
905
Gerr (POS, G_ERRCANNOTREADBITMAP);
911
for (s2 = s1; *s2 && *s2 >= '0' && *s2 <= '9'; s2++)
914
if (s2 == s1 || (s.x = atoi (s1)) <= 0) {
915
*s2 = c, Gerr (POS, G_ERRCANNOTREADBITMAP);
918
*s2 = c, step++, s1 = s2;
921
for (s2 = s1; *s2 && *s2 >= '0' && *s2 <= '9'; s2++)
924
if (s2 == s1 || (s.y = atoi (s1)) <= 0) {
925
*s2 = c, Gerr (POS, G_ERRCANNOTREADBITMAP);
928
*s2 = c, step++, s1 = s2;
932
if (!(bitmap->u.bmap.orig = XCreatePixmap (Gdisplay, XtWindow (widget->w),
933
(int) s.x, (int) s.y, Gdepth))) {
934
Gerr (POS, G_ERRCANNOTCREATEBITMAP);
937
bitmap->u.bmap.scaled = 0;
938
bitmap->scale.x = bitmap->scale.y = 1;
939
bitmap->ctype = widget->type;
940
bitmap->canvas = widget - &Gwidgets[0];
942
if ((img = XCreateImage (Gdisplay, DefaultVisual (Gdisplay, Gscreenn),
943
Gdepth, ZPixmap, 0, NULL, (int) s.x, (int) s.y, 32, 0)) == NULL) {
944
XFreePixmap (Gdisplay, bitmap->u.bmap.orig);
945
Gerr (POS, G_ERRCANNOTCREATEBITMAP);
948
if ((img->data = malloc (img->bytes_per_line * img->height)) == NULL) {
949
XFreePixmap (Gdisplay, bitmap->u.bmap.orig);
951
Gerr (POS, G_ERRCANNOTCREATEBITMAP);
955
for (colori = 0; colori < G_MAXCOLORS; colori++) {
956
if (widget->u.c->colors[colori].inuse) {
957
colors[colorn] = widget->u.c->colors[colori].color;
963
for (y = 0; y < s.y; y++) {
964
for (x = 0; x < s.x; x++) {
965
for (k = 0; k < 3; k++) {
967
if ((bufn = fread (bufp, 1, 2047, fp)) == 0) {
968
XFreePixmap (Gdisplay, bitmap->u.bmap.orig);
970
Gerr (POS, G_ERRCANNOTCREATEBITMAP);
975
rgb[k] = 257 * (unsigned char) bufp[bufi++];
977
cmaxdiff = CMINMAXDIFF;
979
for (colori = 0; colori < colorn; colori++)
980
if (CDIFF (colors[colori], rgb) < cmaxdiff)
982
if (colori == colorn && colorn < G_MAXCOLORS &&
983
cmaxdiff == CMINMAXDIFF) {
984
colors[colorn].red = rgb[0];
985
colors[colorn].green = rgb[1];
986
colors[colorn].blue = rgb[2];
987
if (XAllocColor (Gdisplay, widget->u.c->cmap, &colors[colorn]))
990
if (colori == colorn) {
994
XPutPixel (img, x, y, colors[colori].pixel);
997
for (colori = 0; colori < G_MAXCOLORS && colori < colorn; colori++) {
998
if (!widget->u.c->colors[colori].inuse) {
999
widget->u.c->colors[colori].color = colors[colori];
1000
widget->u.c->colors[colori].inuse = TRUE;
1003
XPutImage (Gdisplay, bitmap->u.bmap.orig, widget->u.c->gc, img,
1004
0, 0, 0, 0, (int) s.x, (int) s.y);
1005
XDestroyImage (img);
1009
int GCwritebitmap (Gbitmap_t *bitmap, FILE *fp) {
1012
XColor colors[G_MAXCOLORS];
1014
int colori, bufi, x, y, w, h;
1017
Gerr (POS, G_ERRNOBITMAP);
1020
if (bitmap->canvas < 0 || bitmap->canvas >= Gwidgetn ||
1021
!Gwidgets[bitmap->canvas].inuse) {
1022
Gerr (POS, G_ERRBADWIDGETID, bitmap->canvas);
1025
widget = &Gwidgets[bitmap->canvas];
1026
if (widget->type != G_CANVASWIDGET && widget->type != G_PCANVASWIDGET) {
1027
Gerr (POS, G_ERRNOTACANVAS, bitmap->canvas);
1030
for (colori = 0; colori < G_MAXCOLORS; colori++)
1031
colors[colori].pixel = colori;
1032
XQueryColors (Gdisplay, widget->u.c->cmap, &colors[0], G_MAXCOLORS);
1033
if (!(img = XGetImage (Gdisplay, bitmap->u.bmap.orig, 0, 0,
1034
bitmap->size.x, bitmap->size.y, AllPlanes, ZPixmap))) {
1035
Gerr (POS, G_ERRNOBITMAP);
1038
fprintf (fp, "P6\n%d %d 255\n", (int) bitmap->size.x, (int) bitmap->size.y);
1042
for (y = 0; y < h; y++) {
1043
for (x = 0; x < w; x++) {
1044
colori = XGetPixel (img, x, y);
1045
bufp[bufi++] = colors[colori].red / 257;
1046
bufp[bufi++] = colors[colori].green / 257;
1047
bufp[bufi++] = colors[colori].blue / 257;
1048
if (bufi + 3 >= 2048) {
1049
fwrite (bufp, 1, bufi, fp);
1055
fwrite (bufp, 1, bufi, fp);
1056
XDestroyImage (img);
1060
int GCbitblt (Gwidget_t *widget, Gpoint_t gp, Grect_t gr, Gbitmap_t *bitmap,
1061
char *mode, Ggattr_t *ap) {
1067
double tvx, tvy, twx, twy;
1069
if (gr.o.x > gr.c.x)
1070
p.x = gr.o.x, gr.o.x = gr.c.x, gr.c.x = p.x;
1071
if (gr.o.y > gr.c.y)
1072
p.y = gr.o.y, gr.o.y = gr.c.y, gr.c.y = p.y;
1073
if (strcmp (mode, "b2c") == 0) {
1074
if (!ISVISIBLE (gr))
1076
tvx = WCU->vsize.x, tvy = WCU->vsize.y;
1077
twx = WCU->wrect.c.x - WCU->wrect.o.x;
1078
twy = WCU->wrect.c.y - WCU->wrect.o.y;
1079
scale.x = tvx / twx, scale.y = tvy / twy;
1080
if (scale.x >= 1.0 - 1E-4 && scale.x <= 1.0 + 1E-4 &&
1081
scale.y >= 1.0 - 1E-4 && scale.y <= 1.0 + 1E-4) {
1082
pix = bitmap->u.bmap.orig;
1083
bitmap->scale = scale;
1085
if (scale.x != bitmap->scale.x || scale.y != bitmap->scale.y)
1086
scalebitmap (widget, bitmap, scale, TRUE, 1);
1087
pix = bitmap->u.bmap.scaled;
1089
pr = rdrawtopix (widget, gr);
1090
pp = pdrawtobpix (bitmap, gp);
1091
setgattr (widget, ap);
1092
XCopyArea (Gdisplay, pix, WINDOW, GC, pp.x, pp.y - pr.c.y + pr.o.y,
1093
pr.c.x - pr.o.x + 1, pr.c.y - pr.o.y + 1, pr.o.x, pr.o.y);
1094
} else if (strcmp (mode, "c2b") == 0) {
1095
tvx = WCU->vsize.x, tvy = WCU->vsize.y;
1096
twx = WCU->wrect.c.x - WCU->wrect.o.x;
1097
twy = WCU->wrect.c.y - WCU->wrect.o.y;
1098
scale.x = tvx / twx, scale.y = tvy / twy;
1099
if (scale.x >= 1.0 - 1E-4 && scale.x <= 1.0 + 1E-4 &&
1100
scale.y >= 1.0 - 1E-4 && scale.y <= 1.0 + 1E-4) {
1101
pix = bitmap->u.bmap.orig;
1102
bitmap->scale = scale;
1104
if (scale.x != bitmap->scale.x || scale.y != bitmap->scale.y)
1105
scalebitmap (widget, bitmap, scale, FALSE, 1);
1106
pix = bitmap->u.bmap.scaled;
1108
pr = rdrawtobpix (bitmap, gr);
1109
pp = pdrawtopix (widget, gp);
1110
setgattr (widget, ap);
1111
XCopyArea (Gdisplay, WINDOW, pix, GC, pp.x, pp.y - pr.c.y + pr.o.y,
1112
pr.c.x - pr.o.x + 1, pr.c.y - pr.o.y + 1, pr.o.x, pr.o.y);
1113
if (pix != bitmap->u.bmap.orig)
1114
scalebitmap (widget, bitmap, scale, TRUE, -1);
1119
static int scalebitmap (Gwidget_t *widget, Gbitmap_t *bitmap, Gsize_t scale,
1120
int copybits, int dir) {
1123
XImage *oimg, *simg;
1124
XColor colors[G_MAXCOLORS];
1125
int cmaxdiff, colorn, colori, x, y, x2, y2, xp, yp;
1126
double prod, rgb[3], xr2, yr2, xl2, yl2, xf2, yf2, xr, yr, xl, yl;
1130
nsize.x = (int) (bitmap->size.x * scale.x);
1131
nsize.y = (int) (bitmap->size.y * scale.y);
1132
if (!(spix = XCreatePixmap (Gdisplay, XtWindow (widget->w),
1133
(int) nsize.x, (int) nsize.y, Gdepth))) {
1134
Gerr (POS, G_ERRCANNOTCREATEBITMAP);
1137
if (bitmap->u.bmap.scaled)
1138
XFreePixmap (Gdisplay, bitmap->u.bmap.scaled);
1139
bitmap->u.bmap.scaled = spix;
1140
bitmap->scale = scale;
1144
for (colori = 0; colori < G_MAXCOLORS; colori++)
1145
colors[colori].pixel = colori;
1146
colorn = G_MAXCOLORS;
1147
XQueryColors (Gdisplay, widget->u.c->cmap, &colors[0], G_MAXCOLORS);
1149
nsize.x = (int) (bitmap->size.x * scale.x);
1150
nsize.y = (int) (bitmap->size.y * scale.y);
1151
o2n.x = 1 / scale.x, o2n.y = 1 / scale.y;
1152
if (!(oimg = XGetImage (Gdisplay, bitmap->u.bmap.orig, 0, 0,
1153
(int) bitmap->size.x, (int) bitmap->size.y, AllPlanes,
1155
Gerr (POS, G_ERRNOBITMAP);
1158
if (!(spix = XCreatePixmap (Gdisplay, XtWindow (widget->w),
1159
(int) nsize.x, (int) nsize.y, Gdepth))) {
1160
XDestroyImage (oimg);
1161
Gerr (POS, G_ERRCANNOTCREATEBITMAP);
1165
nsize.x = (int) bitmap->size.x;
1166
nsize.y = (int) bitmap->size.y;
1167
o2n.x = scale.x, o2n.y = scale.y;
1168
if (!(oimg = XGetImage (Gdisplay, bitmap->u.bmap.scaled, 0, 0,
1169
(int) (bitmap->size.x * scale.x), (int) (bitmap->size.y *
1170
scale.y), AllPlanes, ZPixmap))) {
1171
Gerr (POS, G_ERRNOBITMAP);
1174
spix = bitmap->u.bmap.orig;
1176
prod = o2n.x * o2n.y;
1177
if (!(simg = XCreateImage (Gdisplay, DefaultVisual (Gdisplay, Gscreenn),
1178
Gdepth, ZPixmap, 0, NULL, (int) nsize.x, (int) nsize.y, 32, 0))) {
1179
XFreePixmap (Gdisplay, spix);
1180
XDestroyImage (oimg);
1181
Gerr (POS, G_ERRCANNOTCREATEBITMAP);
1184
if ((simg->data = malloc (simg->bytes_per_line * simg->height)) == NULL) {
1185
XFreePixmap (Gdisplay, spix);
1186
XDestroyImage (oimg);
1187
XDestroyImage (simg);
1188
Gerr (POS, G_ERRCANNOTCREATEBITMAP);
1194
for (yp = 0; yp < nsize.y; yp++) {
1198
for (xp = 0; xp < nsize.x; xp++) {
1202
rgb[0] = rgb[1] = rgb[2] = 0;
1207
yf2 = (yl2 + yr2 > 1) ? 1 - yl2 : yr2, yr2 -= yf2;
1209
xf2 = (xl2 + xr2 > 1) ? 1 - xl2 : xr2, xr2 -= xf2;
1210
colori = XGetPixel (oimg, x2, y2);
1211
rgb[0] += (colors[colori].red * xf2 * yf2 / prod);
1212
rgb[1] += (colors[colori].green * xf2 * yf2 / prod);
1213
rgb[2] += (colors[colori].blue * xf2 * yf2 / prod);
1224
cmaxdiff = CMINMAXDIFF;
1226
for (colori = 0; colori < colorn; colori++)
1227
if (CDIFF (colors[colori], rgb) < cmaxdiff)
1229
if (colori == colorn) {
1233
XPutPixel (simg, xp, yp, colors[colori].pixel);
1242
XPutImage (Gdisplay, spix, widget->u.c->gc, simg, 0, 0, 0, 0,
1243
(int) nsize.x, (int) nsize.y);
1244
XDestroyImage (simg);
1245
XDestroyImage (oimg);
1247
if (bitmap->u.bmap.scaled)
1248
XFreePixmap (Gdisplay, bitmap->u.bmap.scaled);
1249
bitmap->u.bmap.scaled = spix;
1250
bitmap->scale = scale;
1255
int GCgetmousecoords (Gwidget_t *widget, Gpoint_t *gpp, int *count) {
1261
XQueryPointer (Gdisplay, WINDOW, &rwin, &cwin, &rx, &ry, &x, &y, &mask);
1263
*gpp = Gppixtodraw (widget, pp);
1264
*count = ((mask & Button1Mask) ? 1 : 0) + ((mask & Button2Mask) ? 1 : 0) +
1265
((mask & Button3Mask) ? 1 : 0);
1269
void Gcwbutaction (Widget w, XEvent *evp, char **app, unsigned int *anp) {
1275
widget = findwidget ((unsigned long) w, G_CANVASWIDGET);
1276
switch ((xtype = evp->type)) {
1280
gev.code = (xtype == ButtonPress) ? G_DOWN : G_UP;
1281
gev.data = evp->xbutton.button - Button1;
1282
pp.x = evp->xbutton.x, pp.y = evp->xbutton.y;
1283
gev.p = Gppixtodraw (widget, pp);
1284
bn = WCU->bstate[gev.data];
1285
WCU->bstate[gev.data] = (xtype == ButtonPress) ? 1 : 0;
1286
bn = WCU->bstate[gev.data] - bn;
1287
WCU->buttonsdown += bn;
1293
wi = gev.wi = widget - &Gwidgets[0];
1294
Gpopdownflag = FALSE;
1296
(*WCU->func) (&gev);
1298
Gpopdownflag = FALSE;
1299
if (gev.code == G_DOWN) {
1301
widget = &Gwidgets[wi];
1302
WCU->bstate[gev.data] = 0;
1305
if (widget->inuse && WCU->func)
1306
(*WCU->func) (&gev);
1311
void Gcwkeyaction (Widget w, XEvent *evp, char **app, unsigned int *anp) {
1316
int xtype, rx, ry, x, y;
1320
widget = findwidget ((unsigned long) w, G_CANVASWIDGET);
1321
switch ((xtype = evp->type)) {
1324
if (!XLookupString ((XKeyEvent *) evp, &c, 1, NULL, NULL))
1326
XQueryPointer (Gdisplay, WCU->window, &rwin, &cwin,
1327
&rx, &ry, &x, &y, &mask);
1329
gev.code = (xtype == KeyPress) ? G_DOWN : G_UP;
1332
gev.p = Gppixtodraw (widget, pp);
1337
gev.wi = widget - &Gwidgets[0];
1338
Gpopdownflag = FALSE;
1340
(*WCU->func) (&gev);
1342
Gpopdownflag = FALSE;
1345
static void setgattr (Gwidget_t *widget, Ggattr_t *ap) {
1348
int color, width, mode, style, pati;
1351
if (!(ap->flags & G_GATTRCOLOR))
1352
ap->color = WCU->defgattr.color;
1353
if (!(ap->flags & G_GATTRWIDTH))
1354
ap->width = WCU->defgattr.width;
1355
if (!(ap->flags & G_GATTRMODE))
1356
ap->mode = WCU->defgattr.mode;
1357
if (!(ap->flags & G_GATTRFILL))
1358
ap->fill = WCU->defgattr.fill;
1359
if (!(ap->flags & G_GATTRSTYLE))
1360
ap->style = WCU->defgattr.style;
1362
if (color >= G_MAXCOLORS || !(WCU->colors[color].inuse))
1364
if (color != WCU->gattr.color) {
1365
WCU->gattr.color = color;
1366
if (ap->mode == G_XOR)
1367
XSetForeground (Gdisplay, GC,
1368
WCU->colors[WCU->gattr.color].color.pixel ^
1369
WCU->colors[0].color.pixel);
1371
XSetForeground (Gdisplay, GC,
1372
WCU->colors[WCU->gattr.color].color.pixel);
1374
cp = &WCU->colors[color].color;
1375
intens = (0.3 * cp->blue + 0.59 * cp->red +
1376
0.11 * cp->green) / 65535.0;
1377
pati = (intens <= 0.0625) ? 16 :
1378
-16.0 * (log (intens) / 2.7725887222);
1379
XSetTile (Gdisplay, GC, WCU->grays[pati]);
1383
if (mode != WCU->gattr.mode) {
1384
WCU->gattr.mode = mode;
1385
XSetFunction (Gdisplay, GC, WCU->gattr.mode);
1387
XSetForeground (Gdisplay, GC,
1388
WCU->colors[WCU->gattr.color].color.pixel ^
1389
WCU->colors[0].color.pixel);
1391
XSetForeground (Gdisplay, GC,
1392
WCU->colors[WCU->gattr.color].color.pixel);
1395
if (width != WCU->gattr.width) {
1396
gcv.line_width = WCU->gattr.width = width;
1397
XChangeGC (Gdisplay, GC, GCLineWidth, &gcv);
1399
WCU->gattr.fill = ap->fill;
1401
if (style != WCU->gattr.style) {
1402
WCU->gattr.style = style;
1403
if (style == G_SOLID) {
1404
gcv.line_style = LineSolid;
1405
XChangeGC (Gdisplay, GC, GCLineStyle, &gcv);
1407
XSetDashes (Gdisplay, GC, 0, gstyles[style], 2);
1408
gcv.line_style = LineOnOffDash;
1409
XChangeGC (Gdisplay, GC, GCLineStyle, &gcv);
1414
static PIXrect_t rdrawtopix (Gwidget_t *widget, Grect_t gr) {
1416
double tvx, tvy, twx, twy;
1418
tvx = WCU->vsize.x - 1, tvy = WCU->vsize.y - 1;
1419
twx = WCU->wrect.c.x - WCU->wrect.o.x;
1420
twy = WCU->wrect.c.y - WCU->wrect.o.y;
1421
pr.o.x = tvx * (gr.o.x - WCU->wrect.o.x) / twx + 0.5;
1422
pr.o.y = tvy * (1.0 - (gr.c.y - WCU->wrect.o.y) / twy) + 0.5;
1423
pr.c.x = tvx * (gr.c.x - WCU->wrect.o.x) / twx + 0.5;
1424
pr.c.y = tvy * (1.0 - (gr.o.y - WCU->wrect.o.y) / twy) + 0.5;
1428
static PIXpoint_t pdrawtopix (Gwidget_t *widget, Gpoint_t gp) {
1430
double tvx, tvy, twx, twy;
1432
tvx = WCU->vsize.x - 1, tvy = WCU->vsize.y - 1;
1433
twx = WCU->wrect.c.x - WCU->wrect.o.x;
1434
twy = WCU->wrect.c.y - WCU->wrect.o.y;
1435
pp.x = tvx * (gp.x - WCU->wrect.o.x) / twx + 0.5;
1436
pp.y = tvy * (1.0 - (gp.y - WCU->wrect.o.y) / twy) + 0.5;
1440
static PIXsize_t sdrawtopix (Gwidget_t *widget, Gsize_t gs) {
1442
double tvx, tvy, twx, twy;
1444
tvx = WCU->vsize.x - 1, tvy = WCU->vsize.y - 1;
1445
twx = WCU->wrect.c.x - WCU->wrect.o.x;
1446
twy = WCU->wrect.c.y - WCU->wrect.o.y;
1447
ps.x = tvx * (gs.x - 1) / twx + 1.5;
1448
ps.y = tvy * (gs.y - 1) / twy + 1.5;
1452
static Gpoint_t Gppixtodraw (Gwidget_t *widget, PIXpoint_t pp) {
1454
double tvx, tvy, twx, twy;
1456
tvx = WCU->vsize.x - 1, tvy = WCU->vsize.y - 1;
1457
twx = WCU->wrect.c.x - WCU->wrect.o.x;
1458
twy = WCU->wrect.c.y - WCU->wrect.o.y;
1459
gp.x = (pp.x / tvx) * twx + WCU->wrect.o.x;
1460
gp.y = (1.0 - pp.y / tvy) * twy + WCU->wrect.o.y;
1464
static Gsize_t spixtodraw (Gwidget_t *widget, PIXsize_t ps) {
1466
double tvx, tvy, twx, twy;
1468
tvx = WCU->vsize.x - 1, tvy = WCU->vsize.y - 1;
1469
twx = WCU->wrect.c.x - WCU->wrect.o.x;
1470
twy = WCU->wrect.c.y - WCU->wrect.o.y;
1471
gs.x = ((ps.x - 1) / tvx) * twx + 1;
1472
gs.y = ((ps.y - 1) / tvy) * twy + 1;
1476
static Grect_t rpixtodraw (Gwidget_t *widget, PIXrect_t pr) {
1478
double tvx, tvy, twx, twy, n;
1480
tvx = WCU->vsize.x - 1, tvy = WCU->vsize.y - 1;
1481
twx = WCU->wrect.c.x - WCU->wrect.o.x;
1482
twy = WCU->wrect.c.y - WCU->wrect.o.y;
1483
gr.o.x = (pr.o.x / tvx) * twx + WCU->wrect.o.x;
1484
gr.o.y = (1.0 - pr.c.y / tvy) * twy + WCU->wrect.o.y;
1485
gr.c.x = (pr.c.x / tvx) * twx + WCU->wrect.o.x;
1486
gr.c.y = (1.0 - pr.o.y / tvy) * twy + WCU->wrect.o.y;
1487
if (gr.o.x > gr.c.x)
1488
n = gr.o.x, gr.o.x = gr.c.x, gr.c.x = n;
1489
if (gr.o.y > gr.c.y)
1490
n = gr.o.y, gr.o.y = gr.c.y, gr.c.y = n;
1494
static PIXrect_t rdrawtobpix (Gbitmap_t *bitmap, Grect_t gr) {
1498
tvy = (bitmap->size.y - 1) * bitmap->scale.y;
1499
pr.o.x = gr.o.x + 0.5;
1500
pr.o.y = tvy - gr.c.y + 0.5;
1501
pr.c.x = gr.c.x + 0.5;
1502
pr.c.y = tvy - gr.o.y + 0.5;
1506
static PIXpoint_t pdrawtobpix (Gbitmap_t *bitmap, Gpoint_t gp) {
1510
tvy = (bitmap->size.y - 1) * bitmap->scale.y;
1512
pp.y = tvy - gp.y + 0.5;
1516
static void adjustclip (Gwidget_t *widget) {
1518
Dimension width, height, pwidth, pheight;
1522
parent = &Gwidgets[widget->pwi];
1524
ADD2ARGS (XtNx, &x);
1525
ADD2ARGS (XtNy, &y);
1526
ADD2ARGS (XtNwidth, &width);
1527
ADD2ARGS (XtNheight, &height);
1528
XtGetValues (widget->w, argp, argn);
1530
ADD2ARGS (XtNwidth, &pwidth);
1531
ADD2ARGS (XtNheight, &pheight);
1532
XtGetValues (parent->w, argp, argn);
1533
pr.o.x = max (0, -x);
1534
pr.o.y = max (0, -y);
1535
pr.c.x = min (width, pr.o.x + pwidth);
1536
pr.c.y = min (height, pr.o.y + pheight);
1537
pr.c.x = max (pr.o.x, pr.c.x);
1538
pr.c.y = max (pr.o.y, pr.c.y);
1539
WCU->clip = rpixtodraw (widget, pr);
1541
if (WCU->gmapmode) {
1542
GMAPwinsetsize (XtWindow (widget->w), width, height);
1543
GMAPchansetaspect (XtWindow (widget->w), width, height);
1548
static Bool cwepredicate (Display *display, XEvent *evp, XPointer data) {
1549
if (evp->type == Expose && ((XAnyEvent *) evp)->window == (Window) data)
1554
static void cweventhandler (Widget w, XtPointer data, XEvent *evp,
1558
widget = findwidget ((unsigned long) w, G_CANVASWIDGET);
1559
Gneedredraw = WCU->needredraw = TRUE;
1560
adjustclip (widget);
1563
GMAPneedupdate = TRUE;
1567
static Bool cwvpredicate (Display *display, XEvent *evp, XPointer data) {
1568
if (evp->type == VisibilityNotify &&
1569
((XAnyEvent *) evp)->window == (Window) data)