BRL-CAD
dm-X.c
Go to the documentation of this file.
1 /* D M - X . C
2  * BRL-CAD
3  *
4  * Copyright (c) 1988-2014 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 /** @file libdm/dm-X.c
21  *
22  * An X Window System Display Manager.
23  *
24  */
25 
26 #include "common.h"
27 
28 #ifdef DM_X
29 
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <limits.h>
33 #include <string.h>
34 
35 
36 #define class REDEFINE_CLASS_STRING_TO_AVOID_CXX_CONFLICT
37 #include <X11/Xlib.h>
38 #include <X11/Xutil.h>
39 
40 #define USE_DIALS_AND_BUTTONS 1
41 
42 #ifdef HAVE_X11_XOSDEFS_H
43 # include <X11/Xfuncproto.h>
44 # include <X11/Xosdefs.h>
45 #endif
46 #if USE_DIALS_AND_BUTTONS
47 # include <X11/extensions/XInput.h>
48 #endif
49 #if defined(linux)
50 # undef X_NOT_STDC_ENV
51 # undef X_NOT_POSIX
52 #endif
53 
54 #ifdef HAVE_TK
55 # include "tk.h"
56 #endif
57 
58 #include "vmath.h"
59 #include "bu/endian.h"
60 #include "bn.h"
61 #include "raytrace.h"
62 #include "dm.h"
63 #include "dm-X.h"
64 #include "dm-Null.h"
65 #include "dm/dm_xvars.h"
66 #include "fb.h"
67 #include "fb/fb_X.h"
68 
69 #include "solid.h"
70 
71 #include "dm_private.h"
72 
73 #define PLOTBOUND 1000.0 /* Max magnification in Rot matrix */
74 
75 #define DM_X_DEFAULT_POINT_SIZE 1.0
76 
77 extern void X_allocate_color_cube(Display *, Colormap, long unsigned int *, int, int, int);
78 extern unsigned long X_get_pixel(unsigned char, unsigned char, unsigned char, long unsigned int *, int);
79 
80 
81 struct allocated_colors {
82  struct bu_list l;
83  int r;
84  int g;
85  int b;
86  XColor c;
87 };
88 
89 
90 HIDDEN void
91 get_color(Display *dpy, Colormap cmap, XColor *color)
92 {
93  Status st;
94  static struct allocated_colors *colors = NULL;
95  struct allocated_colors *c;
96  int r, g, b;
97 
98  if (!colors) {
99  BU_ALLOC(colors, struct allocated_colors);
100  BU_LIST_INIT(&(colors->l));
101  colors->r = colors->g = colors->b = -1;
102  }
103 
104  /* allocated colors are stashed into a list in order to avoid
105  * subsequent repeat allocations.
106  */
107  for (BU_LIST_FOR(c, allocated_colors, &(colors->l))) {
108  if (DM_SAME_COLOR(c->r, c->g, c->b, color->red, color->green, color->blue)) {
109  *color = c->c; /* struct copy */
110  return;
111  }
112  }
113 
114  r = color->red;
115  g = color->green;
116  b = color->blue;
117 
118  st = XAllocColor(dpy, cmap, color);
119  switch (st) {
120  case 1:
121  break;
122  case BadColor:
123  bu_log("XAllocColor failed (BadColor) for (%3d, %3d, %3d) %04x, %04x, %04x\n",
124  (r >> 8), (g >> 8), (b >> 8),
125  r, g, b);
126  break;
127 
128  default:
129  bu_log("XAllocColor error for (%3d, %3d, %3d) %04x, %04x, %04x\n",
130  (r >> 8), (g >> 8), (b >> 8),
131  r, g, b);
132  break;
133  }
134 
135  /* got new valid color, add it to our list */
136  BU_ALLOC(c, struct allocated_colors);
137  c->r = r;
138  c->g = g;
139  c->b = b;
140  c->c = *color; /* struct copy */
141  BU_LIST_PUSH(&(colors->l), &(c->l));
142 }
143 
144 
145 HIDDEN void
146 X_reshape(struct dm_internal *dmp, int width, int height)
147 {
148  dmp->dm_height = height;
149  dmp->dm_width = width;
150  dmp->dm_aspect = (fastf_t)dmp->dm_width / (fastf_t)dmp->dm_height;
151 }
152 
153 
154 HIDDEN int
155 X_configureWin_guts(struct dm_internal *dmp, int force)
156 {
157  XWindowAttributes xwa;
158  XFontStruct *newfontstruct;
159  XGCValues gcv;
160  struct dm_xvars *pubvars = (struct dm_xvars *)dmp->dm_vars.pub_vars;
161  struct x_vars *privars = (struct x_vars *)dmp->dm_vars.priv_vars;
162 
163  XGetWindowAttributes(pubvars->dpy,
164  pubvars->win, &xwa);
165 
166  /* nothing to do */
167  if (!force &&
168  dmp->dm_height == xwa.height &&
169  dmp->dm_width == xwa.width)
170  return TCL_OK;
171 
172  X_reshape(dmp, xwa.width, xwa.height);
173 
174  if (dmp->dm_debugLevel) {
175  bu_log("X_configureWin_guts()\n");
176  bu_log("width = %d, height = %d\n", dmp->dm_width, dmp->dm_height);
177  }
178 
179 #ifdef HAVE_TK
180  Tk_FreePixmap(pubvars->dpy,
181  privars->pix);
182  privars->pix =
183  Tk_GetPixmap(pubvars->dpy,
184  DefaultRootWindow(pubvars->dpy),
185  dmp->dm_width,
186  dmp->dm_height,
187  Tk_Depth(pubvars->xtkwin));
188 #endif
189 
190  /* First time through, load a font or quit */
191  if (pubvars->fontstruct == NULL) {
192  if ((pubvars->fontstruct =
193  XLoadQueryFont(pubvars->dpy, FONT9)) == NULL) {
194  /* Try hardcoded backup font */
195  if ((pubvars->fontstruct =
196  XLoadQueryFont(pubvars->dpy, FONTBACK)) == NULL) {
197  bu_log("dm-X: Can't open font '%s' or '%s'\n", FONT9, FONTBACK);
198  return TCL_ERROR;
199  }
200  }
201 
202  gcv.font = pubvars->fontstruct->fid;
203  XChangeGC(pubvars->dpy,
204  privars->gc, GCFont, &gcv);
205  }
206 
207  /* Always try to choose a the font that best fits the window size.
208  */
209 
210  if (dmp->dm_width < 582) {
211  if (pubvars->fontstruct->per_char->width != 5) {
212  if ((newfontstruct = XLoadQueryFont(pubvars->dpy,
213  FONT5)) != NULL) {
214  XFreeFont(pubvars->dpy,
215  pubvars->fontstruct);
216  pubvars->fontstruct = newfontstruct;
217  gcv.font = pubvars->fontstruct->fid;
218  XChangeGC(pubvars->dpy,
219  privars->gc, GCFont, &gcv);
220  }
221  }
222  } else if (dmp->dm_width < 679) {
223  if (pubvars->fontstruct->per_char->width != 6) {
224  if ((newfontstruct = XLoadQueryFont(pubvars->dpy,
225  FONT6)) != NULL) {
226  XFreeFont(pubvars->dpy,
227  pubvars->fontstruct);
228  pubvars->fontstruct = newfontstruct;
229  gcv.font = pubvars->fontstruct->fid;
230  XChangeGC(pubvars->dpy,
231  privars->gc, GCFont, &gcv);
232  }
233  }
234  } else if (dmp->dm_width < 776) {
235  if (pubvars->fontstruct->per_char->width != 7) {
236  if ((newfontstruct = XLoadQueryFont(pubvars->dpy,
237  FONT7)) != NULL) {
238  XFreeFont(pubvars->dpy,
239  pubvars->fontstruct);
240  pubvars->fontstruct = newfontstruct;
241  gcv.font = pubvars->fontstruct->fid;
242  XChangeGC(pubvars->dpy,
243  privars->gc, GCFont, &gcv);
244  }
245  }
246  } else if (dmp->dm_width < 873) {
247  if (pubvars->fontstruct->per_char->width != 8) {
248  if ((newfontstruct = XLoadQueryFont(pubvars->dpy,
249  FONT8)) != NULL) {
250  XFreeFont(pubvars->dpy,
251  pubvars->fontstruct);
252  pubvars->fontstruct = newfontstruct;
253  gcv.font = pubvars->fontstruct->fid;
254  XChangeGC(pubvars->dpy,
255  privars->gc, GCFont, &gcv);
256  }
257  }
258  } else {
259  if (pubvars->fontstruct->per_char->width != 9) {
260  if ((newfontstruct = XLoadQueryFont(pubvars->dpy,
261  FONT9)) != NULL) {
262  XFreeFont(pubvars->dpy,
263  pubvars->fontstruct);
264  pubvars->fontstruct = newfontstruct;
265  gcv.font = pubvars->fontstruct->fid;
266  XChangeGC(pubvars->dpy,
267  privars->gc, GCFont, &gcv);
268  }
269  }
270  }
271 
272  return TCL_OK;
273 }
274 
275 
276 HIDDEN XVisualInfo *
277 X_choose_visual(struct dm_internal *dmp)
278 {
279  XVisualInfo *vip, vitemp, *vibase, *maxvip;
280  int num, i, j;
281  int tries, baddepth;
282  int desire_trueColor = 1;
283  int min_depth = 8;
284  int *good = NULL;
285  int screen;
286  struct dm_xvars *pubvars = (struct dm_xvars *)dmp->dm_vars.pub_vars;
287  struct x_vars *privars = (struct x_vars *)dmp->dm_vars.priv_vars;
288 
289  vibase = XGetVisualInfo(pubvars->dpy, 0, &vitemp, &num);
290  screen = DefaultScreen(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy);
291 
292  good = (int *)bu_malloc(sizeof(int)*num, "alloc good visuals");
293 
294  while (1) {
295  for (i=0, j=0, vip=vibase; i<num; i++, vip++) {
296  /* requirements */
297  if (vip->screen != screen)
298  continue;
299  if (vip->depth < min_depth)
300  continue;
301  if (desire_trueColor) {
302  if (vip->class != TrueColor)
303  continue;
304  } else if (vip->class != PseudoColor)
305  continue;
306 
307  /* this visual meets criteria */
308  good[j++] = i;
309  }
310 
311  baddepth = 1000;
312  for (tries = 0; tries < j; ++tries) {
313  maxvip = vibase + good[0];
314  for (i=1; i<j; i++) {
315  vip = vibase + good[i];
316  if ((vip->depth > maxvip->depth)&&(vip->depth < baddepth)) {
317  maxvip = vip;
318  }
319  }
320 
321  /* make sure Tk handles it */
322  if (desire_trueColor) {
323  pubvars->cmap =
324  XCreateColormap(pubvars->dpy,
325  RootWindow(pubvars->dpy,
326  maxvip->screen),
327  maxvip->visual, AllocNone);
328  privars->is_trueColor = 1;
329  } else {
330  pubvars->cmap =
331  XCreateColormap(pubvars->dpy,
332  RootWindow(pubvars->dpy,
333  maxvip->screen),
334  maxvip->visual, AllocAll);
335  privars->is_trueColor = 0;
336  }
337 
338 #ifdef HAVE_TK
339  if (Tk_SetWindowVisual(pubvars->xtkwin,
340  maxvip->visual,
341  maxvip->depth,
342  pubvars->cmap)) {
343  pubvars->depth = maxvip->depth;
344 
345  bu_free(good, "dealloc good visuals");
346  return maxvip; /* success */
347  } else
348 #endif
349  {
350  /* retry with lesser depth */
351  baddepth = maxvip->depth;
352  XFreeColormap(pubvars->dpy, pubvars->cmap);
353  }
354  }
355 
356  if (desire_trueColor) {
357  desire_trueColor = 0;
358  } else {
359  /* ran out of visuals, give up */
360  break;
361  }
362  }
363 
364  bu_free(good, "dealloc good visuals");
365  return (XVisualInfo *)NULL; /* failure */
366 }
367 
368 
369 /*
370  * Gracefully release the display.
371  */
372 HIDDEN int
373 X_close(struct dm_internal *dmp)
374 {
375  struct dm_xvars *pubvars = (struct dm_xvars *)dmp->dm_vars.pub_vars;
376  struct x_vars *privars = (struct x_vars *)dmp->dm_vars.priv_vars;
377 
378  if (pubvars->dpy) {
379  if (privars->gc)
380  XFreeGC(pubvars->dpy,
381  privars->gc);
382 
383 #ifdef HAVE_TK
384  if (privars->pix)
385  Tk_FreePixmap(pubvars->dpy,
386  privars->pix);
387 #endif
388 
389  /*XXX Possibly need to free the colormap */
390  if (pubvars->cmap)
391  XFreeColormap(pubvars->dpy,
392  pubvars->cmap);
393 
394 #ifdef HAVE_TK
395  if (pubvars->xtkwin)
396  Tk_DestroyWindow(pubvars->xtkwin);
397 #endif
398 
399  }
400 
401  bu_vls_free(&dmp->dm_pathName);
402  bu_vls_free(&dmp->dm_tkName);
403  bu_vls_free(&dmp->dm_dName);
404  bu_free((void *)dmp->dm_vars.priv_vars, "X_close: x_vars");
405  bu_free((void *)dmp->dm_vars.pub_vars, "X_close: dm_xvars");
406  bu_free((void *)dmp, "X_close: dmp");
407 
408  return TCL_OK;
409 }
410 
411 
412 /*
413  * Fire up the display manager, and the display processor.
414  *
415  */
416 struct dm_internal *
417 X_open_dm(Tcl_Interp *interp, int argc, char **argv)
418 {
419  static int count = 0;
420  int make_square = -1;
421  XGCValues gcv;
422 #if USE_DIALS_AND_BUTTONS
423  int j, k;
424  int ndevices;
425  int nclass = 0;
426  int unused;
427  XDeviceInfoPtr olist = NULL, list = NULL;
428  XDevice *dev = NULL;
429  XEventClass e_class[15];
430  XInputClassInfo *cip = NULL;
431 #endif
432  struct bu_vls str = BU_VLS_INIT_ZERO;
433  struct bu_vls init_proc_vls = BU_VLS_INIT_ZERO;
434  struct dm_internal *dmp = (struct dm_internal *)NULL;
435  Tk_Window tkwin = (Tk_Window)NULL;
436  Screen *screen = (Screen *)NULL;
437 
438  struct dm_xvars *pubvars = NULL;
439  struct x_vars *privars = NULL;
440 
441 #ifdef HAVE_TK
442  if ((tkwin = Tk_MainWindow(interp)) == NULL) {
443  return DM_NULL;
444  }
445 #endif
446 
447  BU_ALLOC(dmp, struct dm_internal);
448 
449  *dmp = dm_X; /* struct copy */
450  dmp->dm_interp = interp;
451 
452  BU_ALLOC(dmp->dm_vars.pub_vars, struct dm_xvars);
453  pubvars = (struct dm_xvars *)dmp->dm_vars.pub_vars;
454 
455  BU_ALLOC(dmp->dm_vars.priv_vars, struct x_vars);
456  privars = (struct x_vars *)dmp->dm_vars.priv_vars;
457 
458  bu_vls_init(&dmp->dm_pathName);
459  bu_vls_init(&dmp->dm_tkName);
460  bu_vls_init(&dmp->dm_dName);
461 
462  dm_processOptions(dmp, &init_proc_vls, --argc, ++argv);
463 
464  if (bu_vls_strlen(&dmp->dm_pathName) == 0)
465  bu_vls_printf(&dmp->dm_pathName, ".dm_X%d", count);
466 
467  ++count;
468  if (bu_vls_strlen(&dmp->dm_dName) == 0) {
469  char *dp;
470 
471  dp = getenv("DISPLAY");
472  if (dp)
473  bu_vls_strcpy(&dmp->dm_dName, dp);
474  else
475  bu_vls_strcpy(&dmp->dm_dName, ":0.0");
476  }
477  if (bu_vls_strlen(&init_proc_vls) == 0)
478  bu_vls_strcpy(&init_proc_vls, "bind_dm");
479 
480  /* initialize dm specific variables */
481  pubvars->devmotionnotify = LASTEvent;
482  pubvars->devbuttonpress = LASTEvent;
483  pubvars->devbuttonrelease = LASTEvent;
484  dmp->dm_aspect = 1.0;
485 
486  pubvars->fontstruct = NULL;
487 
488  if (dmp->dm_top) {
489 #ifdef HAVE_TK
490  /* Make xtkwin a toplevel window */
491  pubvars->xtkwin = Tk_CreateWindowFromPath(interp, tkwin,
492  bu_vls_addr(&dmp->dm_pathName),
493  bu_vls_addr(&dmp->dm_dName));
494  pubvars->top = pubvars->xtkwin;
495 #endif
496  } else {
497  char *cp;
498 
499  cp = strrchr(bu_vls_addr(&dmp->dm_pathName), (int)'.');
500  if (cp == bu_vls_addr(&dmp->dm_pathName)) {
501  pubvars->top = tkwin;
502  } else {
503  struct bu_vls top_vls = BU_VLS_INIT_ZERO;
504 
505  bu_vls_strncpy(&top_vls, (const char *)bu_vls_addr(&dmp->dm_pathName), cp - bu_vls_addr(&dmp->dm_pathName));
506 
507 #ifdef HAVE_TK
508  pubvars->top =
509  Tk_NameToWindow(interp, bu_vls_addr(&top_vls), tkwin);
510 #endif
511  bu_vls_free(&top_vls);
512  }
513 
514 #ifdef HAVE_TK
515  /* Make xtkwin an embedded window */
516  pubvars->xtkwin =
517  Tk_CreateWindow(interp, pubvars->top,
518  cp + 1, (char *)NULL);
519 #endif
520  }
521 
522  if (pubvars->xtkwin == NULL) {
523  bu_log("X_open_dm: Failed to open %s\n", bu_vls_addr(&dmp->dm_pathName));
524  (void)X_close(dmp);
525  return DM_NULL;
526  }
527 
528 #ifdef HAVE_TK
529  bu_vls_printf(&dmp->dm_tkName, "%s",
530  (char *)Tk_Name(pubvars->xtkwin));
531 #endif
532 
533  bu_vls_printf(&str, "_init_dm %s %s\n",
534  bu_vls_addr(&init_proc_vls),
535  bu_vls_addr(&dmp->dm_pathName));
536 
537  if (Tcl_Eval(interp, bu_vls_addr(&str)) == TCL_ERROR) {
538  bu_vls_free(&str);
539  (void)X_close(dmp);
540  return DM_NULL;
541  }
542 
543  bu_vls_free(&init_proc_vls);
544  bu_vls_free(&str);
545 
546  pubvars->dpy = NULL;
547 #ifdef HAVE_TK
548  pubvars->dpy = Tk_Display(pubvars->top);
549 #endif
550 
551  /* make sure there really is a display before proceeding. */
552  if (!pubvars->dpy) {
553  bu_log("ERROR: Unable to attach to display (%s)\n", bu_vls_addr(&dmp->dm_pathName));
554  (void)X_close(dmp);
555  return DM_NULL;
556  }
557 
558  screen = DefaultScreenOfDisplay(pubvars->dpy);
559 
560  if (!screen) {
561 #ifdef HAVE_TK
562  /* failed to get a default screen, try harder */
563  screen = Tk_Screen(pubvars->top);
564 #endif
565  }
566 
567  /* make sure there really is a screen before processing. */
568  if (!screen) {
569  bu_log("ERROR: Unable to attach to screen (%s)\n", bu_vls_addr(&dmp->dm_pathName));
570  (void)X_close(dmp);
571  return DM_NULL;
572  }
573 
574  /* FIXME: Applications on Mac OS X linking against the system
575  * Tcl/Tk frameworks may crash here due to dpy being a high (7+
576  * digit) value and the screens[] array it indexes into being 0x0.
577  * Might have better luck calling functions instead of macros.
578  */
579 
580  if (dmp->dm_width == 0) {
581  dmp->dm_width =
582  DisplayWidth(pubvars->dpy,
583  DefaultScreen(pubvars->dpy)) - 30;
584  ++make_square;
585  }
586 
587  if (dmp->dm_height == 0) {
588  dmp->dm_height =
589  DisplayHeight(pubvars->dpy,
590  DefaultScreen(pubvars->dpy)) - 30;
591  ++make_square;
592  }
593 
594  if (make_square > 0) {
595  /* Make window square */
596  if (dmp->dm_height <
597  dmp->dm_width)
598  dmp->dm_width = dmp->dm_height;
599  else
600  dmp->dm_height = dmp->dm_width;
601  }
602 
603 #ifdef HAVE_TK
604  Tk_GeometryRequest(pubvars->xtkwin,
605  dmp->dm_width,
606  dmp->dm_height);
607 #endif
608 
609  /* must do this before MakeExist */
610  if ((pubvars->vip = X_choose_visual(dmp)) == NULL) {
611  bu_log("X_open_dm: Can't get an appropriate visual.\n");
612  (void)X_close(dmp);
613  return DM_NULL;
614  }
615 
616 #ifdef HAVE_TK
617  Tk_MakeWindowExist(pubvars->xtkwin);
618  pubvars->win = Tk_WindowId(pubvars->xtkwin);
619  dmp->dm_id = pubvars->win;
620  privars->pix =
621  Tk_GetPixmap(pubvars->dpy,
622  pubvars->win,
623  dmp->dm_width,
624  dmp->dm_height,
625  Tk_Depth(pubvars->xtkwin));
626 #endif
627 
628  if (privars->is_trueColor) {
629  XColor fg, bg;
630 
631  INIT_XCOLOR(&fg);
632  INIT_XCOLOR(&bg);
633 
634  fg.red = 65535;
635  fg.green = fg.blue = 0;
636 
637  get_color(pubvars->dpy,
638  pubvars->cmap,
639  &fg);
640 
641  privars->fg = fg.pixel;
642 
643  bg.red = bg.green = bg.blue = 0;
644  get_color(pubvars->dpy,
645  pubvars->cmap,
646  &bg);
647 
648  privars->bg = bg.pixel;
649  } else {
650  X_allocate_color_cube(pubvars->dpy,
651  pubvars->cmap,
652  privars->pixels,
653  /* cube dimension, uses XStoreColor */
654  6, CMAP_BASE, 1);
655 
656  privars->bg =
657  X_get_pixel(DM_BLACK,
658  privars->pixels,
660  privars->fg =
661  X_get_pixel(DM_RED,
662  privars->pixels,
664  }
665 
666  gcv.background = privars->bg;
667  gcv.foreground = privars->fg;
668  privars->gc = XCreateGC(pubvars->dpy,
669  pubvars->win,
670  (GCForeground|GCBackground), &gcv);
671 
672  /* First see if the server supports XInputExtension */
673  {
674  int return_val;
675 
676  if (!XQueryExtension(pubvars->dpy,
677  "XInputExtension", &return_val, &return_val, &return_val))
678  goto Skip_dials;
679  }
680 
681 #if USE_DIALS_AND_BUTTONS
682  /*
683  * Take a look at the available input devices. We're looking for
684  * "dial+buttons".
685  */
686  if (XQueryExtension(pubvars->dpy, "XInputExtension", &unused, &unused, &unused)) {
687  olist = list = (XDeviceInfoPtr)XListInputDevices(pubvars->dpy, &ndevices);
688  }
689 
690  if (list == (XDeviceInfoPtr)NULL ||
691  list == (XDeviceInfoPtr)1) goto Done;
692 
693  for (j = 0; j < ndevices; ++j, list++) {
694  if (list->use == IsXExtensionDevice) {
695  if (BU_STR_EQUAL(list->name, "dial+buttons")) {
696  if ((dev = XOpenDevice(pubvars->dpy,
697  list->id)) == (XDevice *)NULL) {
698  bu_log("X_open_dm: Couldn't open the dials+buttons\n");
699  goto Done;
700  }
701 
702  for (cip = dev->classes, k = 0; k < dev->num_classes;
703  ++k, ++cip) {
704  switch (cip->input_class) {
705 #ifdef IR_BUTTONS
706  case ButtonClass:
707  DeviceButtonPress(dev, pubvars->devbuttonpress,
708  e_class[nclass]);
709  ++nclass;
710  DeviceButtonRelease(dev, pubvars->devbuttonrelease,
711  e_class[nclass]);
712  ++nclass;
713  break;
714 #endif
715 #ifdef IR_KNOBS
716  case ValuatorClass:
717  DeviceMotionNotify(dev, pubvars->devmotionnotify,
718  e_class[nclass]);
719  ++nclass;
720  break;
721 #endif
722  default:
723  break;
724  }
725  }
726 
727  XSelectExtensionEvent(pubvars->dpy,
728  pubvars->win, e_class, nclass);
729  goto Done;
730  }
731  }
732  }
733 Done:
734  XFreeDeviceList(olist);
735 #endif
736 
737 Skip_dials:
738  (void)X_configureWin_guts(dmp, 1);
739 
740 #ifdef HAVE_TK
741  Tk_SetWindowBackground(pubvars->xtkwin,
742  privars->bg);
743  Tk_MapWindow(pubvars->xtkwin);
744 #endif
745 
746  MAT_IDN(privars->xmat);
747 
748  return dmp;
749 }
750 
751 
752 HIDDEN int
753 X_drawBegin(struct dm_internal *dmp)
754 {
755  XGCValues gcv;
756  struct dm_xvars *pubvars = (struct dm_xvars *)dmp->dm_vars.pub_vars;
757  struct x_vars *privars = (struct x_vars *)dmp->dm_vars.priv_vars;
758 
759  if (dmp->dm_debugLevel)
760  bu_log("X_drawBegin()\n");
761 
762  /* clear pixmap */
763  gcv.foreground = privars->bg;
764  XChangeGC(pubvars->dpy,
765  privars->gc,
766  GCForeground, &gcv);
767  XFillRectangle(pubvars->dpy,
768  privars->pix,
769  privars->gc, 0,
770  0, dmp->dm_width + 1,
771  dmp->dm_height + 1);
772 
773  /* reset foreground */
774  gcv.foreground = privars->fg;
775  XChangeGC(pubvars->dpy,
776  privars->gc,
777  GCForeground, &gcv);
778 
779  return TCL_OK;
780 }
781 
782 
783 HIDDEN int
784 X_drawEnd(struct dm_internal *dmp)
785 {
786  struct dm_xvars *pubvars = (struct dm_xvars *)dmp->dm_vars.pub_vars;
787  struct x_vars *privars = (struct x_vars *)dmp->dm_vars.priv_vars;
788 
789  if (dmp->dm_debugLevel)
790  bu_log("X_drawEnd()\n");
791 
792  XCopyArea(pubvars->dpy,
793  privars->pix,
794  pubvars->win,
795  privars->gc,
796  0, 0, dmp->dm_width,
797  dmp->dm_height, 0, 0);
798 
799  /* Prevent lag between events and updates */
800  XSync(pubvars->dpy, 0);
801 
802  return TCL_OK;
803 }
804 
805 
806 /*
807  * Load a new transformation matrix. This will be followed by many
808  * calls to X_draw().
809  */
810 HIDDEN int
811 X_loadMatrix(struct dm_internal *dmp, fastf_t *mat, int which_eye)
812 {
813  struct x_vars *privars = (struct x_vars *)dmp->dm_vars.priv_vars;
814 
815  if (dmp->dm_debugLevel) {
816  bu_log("X_loadMatrix()\n");
817 
818  bu_log("which eye = %d\t", which_eye);
819  bu_log("transformation matrix = \n");
820 
821  /* note the row/column ordering */
822  bu_log("%g %g %g %g\n", mat[0], mat[1], mat[2], mat[3]);
823  bu_log("%g %g %g %g\n", mat[4], mat[5], mat[6], mat[7]);
824  bu_log("%g %g %g %g\n", mat[8], mat[9], mat[10], mat[11]);
825  bu_log("%g %g %g %g\n", mat[12], mat[13], mat[14], mat[15]);
826  }
827 
828  MAT_COPY(privars->xmat, mat);
829  return TCL_OK;
830 }
831 
832 
833 HIDDEN int
834 X_drawVList(struct dm_internal *dmp, struct bn_vlist *vp)
835 {
836  extern int vectorThreshold; /* defined in libdm/tcl.c */
837 
838  static vect_t spnt, lpnt, pnt;
839  struct bn_vlist *tvp;
840  XSegment segbuf[1024]; /* XDrawSegments list */
841  XSegment *segp; /* current segment */
842  int nseg; /* number of segments */
843  fastf_t delta;
844  point_t *pt_prev = NULL;
845  fastf_t dist_prev=1.0;
846  static int nvectors = 0;
847  struct dm_xvars *pubvars = (struct dm_xvars *)dmp->dm_vars.pub_vars;
848  struct x_vars *privars = (struct x_vars *)dmp->dm_vars.priv_vars;
849  fastf_t pointSize = DM_X_DEFAULT_POINT_SIZE;
850 
851  if (dmp->dm_debugLevel) {
852  bu_log("X_drawVList()\n");
853  bu_log("vp - %lu, perspective - %d\n", vp, dmp->dm_perspective);
854  }
855 
856  /* delta is used in clipping to insure clipped endpoint is
857  * slightly in front of eye plane (perspective mode only). This
858  * value is a SWAG that seems to work OK.
859  */
860  delta = privars->xmat[15]*0.0001;
861  if (delta < 0.0)
862  delta = -delta;
863  if (delta < SQRT_SMALL_FASTF)
864  delta = SQRT_SMALL_FASTF;
865 
866  nseg = 0;
867  segp = segbuf;
868  for (BU_LIST_FOR(tvp, bn_vlist, &vp->l)) {
869  int i;
870  int nused = tvp->nused;
871  int *cmd = tvp->cmd;
872  point_t *pt = tvp->pt;
873  fastf_t dist;
874 
875  /* Viewing region is from -1.0 to +1.0 */
876  /* 2^31 ~= 2e9 -- dynamic range of a long int */
877  /* 2^(31-11) = 2^20 ~= 1e6 */
878  /* Integerize and let the X server do the clipping */
879  for (i = 0; i < nused; i++, cmd++, pt++) {
880  switch (*cmd) {
881  case BN_VLIST_POLY_START:
883  case BN_VLIST_TRI_START:
885  continue;
886  case BN_VLIST_POLY_MOVE:
887  case BN_VLIST_LINE_MOVE:
888  case BN_VLIST_TRI_MOVE:
889  /* Move, not draw */
890  if (dmp->dm_debugLevel > 2) {
891  bu_log("before transformation:\n");
892  bu_log("pt - %lf %lf %lf\n", V3ARGS(*pt));
893  }
894 
895  if (dmp->dm_perspective > 0) {
896  /* cannot apply perspective transformation to
897  * points behind eye plane!!!!
898  */
899  dist = VDOT(*pt, &privars->xmat[12]) + privars->xmat[15];
900  if (dist <= 0.0) {
901  pt_prev = pt;
902  dist_prev = dist;
903  continue;
904  } else {
905  MAT4X3PNT(lpnt, privars->xmat, *pt);
906  dist_prev = dist;
907  pt_prev = pt;
908  }
909  } else {
910  MAT4X3PNT(lpnt, privars->xmat, *pt);
911  }
912 
913  lpnt[0] *= 2047;
914  lpnt[1] *= 2047 * dmp->dm_aspect;
915  lpnt[2] *= 2047;
916  continue;
917  case BN_VLIST_POLY_DRAW:
918  case BN_VLIST_POLY_END:
919  case BN_VLIST_LINE_DRAW:
920  case BN_VLIST_TRI_DRAW:
921  case BN_VLIST_TRI_END:
922  /* draw */
923  if (dmp->dm_debugLevel > 2) {
924  bu_log("before transformation:\n");
925  bu_log("pt - %lf %lf %lf\n", V3ARGS(*pt));
926  }
927 
928  if (dmp->dm_perspective > 0) {
929  /* cannot apply perspective transformation to
930  * points behind eye plane!!!!
931  */
932  dist = VDOT(*pt, &privars->xmat[12]) + privars->xmat[15];
933  if (dmp->dm_debugLevel > 2)
934  bu_log("dist=%g, dist_prev=%g\n", dist, dist_prev);
935  if (dist <= 0.0) {
936  if (dist_prev <= 0.0) {
937  /* nothing to plot */
938  dist_prev = dist;
939  pt_prev = pt;
940  continue;
941  } else {
942  if (pt_prev) {
943  fastf_t alpha;
944  vect_t diff;
945  point_t tmp_pt;
946 
947  /* clip this end */
948  VSUB2(diff, *pt, *pt_prev);
949  alpha = (dist_prev - delta) / (dist_prev - dist);
950  VJOIN1(tmp_pt, *pt_prev, alpha, diff);
951  MAT4X3PNT(pnt, privars->xmat, tmp_pt);
952  }
953  }
954  } else {
955  if (dist_prev <= 0.0) {
956  if (pt_prev) {
957  fastf_t alpha;
958  vect_t diff;
959  point_t tmp_pt;
960 
961  /* clip other end */
962  VSUB2(diff, *pt, *pt_prev);
963  alpha = (-dist_prev + delta) / (dist - dist_prev);
964  VJOIN1(tmp_pt, *pt_prev, alpha, diff);
965  MAT4X3PNT(lpnt, privars->xmat, tmp_pt);
966  lpnt[0] *= 2047;
967  lpnt[1] *= 2047 * dmp->dm_aspect;
968  lpnt[2] *= 2047;
969  MAT4X3PNT(pnt, privars->xmat, *pt);
970  }
971  } else {
972  MAT4X3PNT(pnt, privars->xmat, *pt);
973  }
974  }
975  dist_prev = dist;
976  } else {
977  MAT4X3PNT(pnt, privars->xmat, *pt);
978  }
979 
980  pnt[0] *= 2047;
981  pnt[1] *= 2047 * dmp->dm_aspect;
982  pnt[2] *= 2047;
983 
984  /* save pnt --- it might get changed by clip() */
985  VMOVE(spnt, pnt);
986  pt_prev = pt;
987 
988  if (dmp->dm_debugLevel > 2) {
989  bu_log("before clipping:\n");
990  bu_log("clipmin - %lf %lf %lf\n",
991  dmp->dm_clipmin[X],
992  dmp->dm_clipmin[Y],
993  dmp->dm_clipmin[Z]);
994  bu_log("clipmax - %lf %lf %lf\n",
995  dmp->dm_clipmax[X],
996  dmp->dm_clipmax[Y],
997  dmp->dm_clipmax[Z]);
998  bu_log("pt1 - %lf %lf %lf\n", lpnt[X], lpnt[Y], lpnt[Z]);
999  bu_log("pt2 - %lf %lf %lf\n", pnt[X], pnt[Y], pnt[Z]);
1000  }
1001 
1002  if (dmp->dm_zclip) {
1003  if (vclip(lpnt, pnt,
1004  dmp->dm_clipmin,
1005  dmp->dm_clipmax) == 0) {
1006  VMOVE(lpnt, spnt);
1007  continue;
1008  }
1009  } else {
1010  fastf_t min_short = (fastf_t)SHRT_MIN;
1011  fastf_t max_short = (fastf_t)SHRT_MAX;
1012 
1013  /* Check to see if lpnt or pnt contain values
1014  * that exceed the capacity of a short (segbuf
1015  * is an array of XSegments which contain
1016  * shorts). If so, do clipping now. Otherwise,
1017  * let the X server do the clipping.
1018  */
1019  if (lpnt[0] < min_short || max_short < lpnt[0] ||
1020  lpnt[1] < min_short || max_short < lpnt[1] ||
1021  pnt[0] < min_short || max_short < pnt[0] ||
1022  pnt[1] < min_short || max_short < pnt[1]) {
1023  /* if the entire line segment will not be
1024  * visible then ignore it.
1025  */
1026  if (clip(&lpnt[0], &lpnt[1], &pnt[0], &pnt[1]) == -1) {
1027  VMOVE(lpnt, spnt);
1028  continue;
1029  }
1030  }
1031  }
1032 
1033  if (dmp->dm_debugLevel > 2) {
1034  bu_log("after clipping:\n");
1035  bu_log("pt1 - %lf %lf %lf\n", lpnt[X], lpnt[Y], lpnt[Z]);
1036  bu_log("pt2 - %lf %lf %lf\n", pnt[X], pnt[Y], pnt[Z]);
1037  }
1038 
1039  /* convert to X window coordinates */
1040  segp->x1 = (short)GED_TO_Xx(dmp, lpnt[0]);
1041  segp->y1 = (short)GED_TO_Xy(dmp, lpnt[1]);
1042  segp->x2 = (short)GED_TO_Xx(dmp, pnt[0]);
1043  segp->y2 = (short)GED_TO_Xy(dmp, pnt[1]);
1044 
1045  nseg++;
1046  segp++;
1047  VMOVE(lpnt, spnt);
1048 
1049  if (nseg == 1024) {
1050  XDrawSegments(pubvars->dpy,
1051  privars->pix,
1052  privars->gc, segbuf, nseg);
1053 
1054  nseg = 0;
1055  segp = segbuf;
1056  }
1057  break;
1058  case BN_VLIST_POINT_DRAW:
1059  if (dmp->dm_debugLevel > 2) {
1060  bu_log("before transformation:\n");
1061  bu_log("pt - %lf %lf %lf\n", V3ARGS(*pt));
1062  }
1063 
1064  if (dmp->dm_perspective > 0) {
1065  dist = VDOT(*pt, &privars->xmat[12]) + privars->xmat[15];
1066 
1067  if (dist <= 0.0) {
1068  /* nothing to plot - point is behind eye plane */
1069  continue;
1070  }
1071  }
1072 
1073  MAT4X3PNT(pnt, privars->xmat, *pt);
1074 
1075  pnt[0] *= 2047;
1076  pnt[1] *= 2047 * dmp->dm_aspect;
1077  pnt[2] *= 2047;
1078 
1079  if (dmp->dm_debugLevel > 2) {
1080  bu_log("after clipping:\n");
1081  bu_log("pt - %lf %lf %lf\n", pnt[X], pnt[Y], pnt[Z]);
1082  }
1083 
1084  if (pointSize <= DM_X_DEFAULT_POINT_SIZE) {
1085  XDrawPoint(pubvars->dpy, privars->pix, privars->gc,
1086  GED_TO_Xx(dmp, pnt[0]), GED_TO_Xy(dmp, pnt[1]));
1087  } else {
1088  int upperLeft[2];
1089 
1090  upperLeft[X] = GED_TO_Xx(dmp, pnt[0]) - pointSize / 2.0;
1091  upperLeft[Y] = GED_TO_Xy(dmp, pnt[1]) - pointSize / 2.0;
1092 
1093  XFillRectangle(pubvars->dpy, privars->pix, privars->gc,
1094  upperLeft[X], upperLeft[Y], pointSize, pointSize);
1095 
1096  }
1097  break;
1098  case BN_VLIST_POINT_SIZE:
1099  pointSize = (*pt)[0];
1100  if (pointSize < DM_X_DEFAULT_POINT_SIZE) {
1101  pointSize = DM_X_DEFAULT_POINT_SIZE;
1102  }
1103  break;
1104  }
1105  }
1106 
1107  nvectors += nused;
1108  if (nvectors >= vectorThreshold) {
1109  if (dmp->dm_debugLevel)
1110  bu_log("X_drawVList(): handle Tcl events\n");
1111 
1112  nvectors = 0;
1113 
1114  /* Handle events in the queue */
1115  while (Tcl_DoOneEvent(TCL_ALL_EVENTS|TCL_DONT_WAIT));
1116  }
1117  }
1118 
1119  if (nseg) {
1120  XDrawSegments(pubvars->dpy,
1121  privars->pix,
1122  privars->gc, segbuf, nseg);
1123  }
1124 
1125  return TCL_OK;
1126 }
1127 
1128 
1129 HIDDEN int
1130 X_draw(struct dm_internal *dmp, struct bn_vlist *(*callback_function)(void *), void **data)
1131 {
1132  struct bn_vlist *vp;
1133  if (!callback_function) {
1134  if (data) {
1135  vp = (struct bn_vlist *)data;
1136  X_drawVList(dmp, vp);
1137  }
1138  } else {
1139  if (!data) {
1140  return TCL_ERROR;
1141  } else {
1142  (void)callback_function(data);
1143  }
1144  }
1145  return TCL_OK;
1146 }
1147 
1148 
1149 /**
1150  * Restore the display processor to a normal mode of operation (i.e.,
1151  * not scaled, rotated, displaced, etc.).
1152  */
1153 HIDDEN int
1154 X_normal(struct dm_internal *dmp)
1155 {
1156  if (dmp->dm_debugLevel)
1157  bu_log("X_normal()\n");
1158 
1159  return TCL_OK;
1160 }
1161 
1162 
1163 /**
1164  * Output a string into the displaylist. The starting position of the
1165  * beam is as specified.
1166  */
1167 HIDDEN int
1168 X_drawString2D(struct dm_internal *dmp, const char *str, fastf_t x, fastf_t y, int size, int use_aspect)
1169 {
1170  int sx, sy;
1171  struct dm_xvars *pubvars = (struct dm_xvars *)dmp->dm_vars.pub_vars;
1172  struct x_vars *privars = (struct x_vars *)dmp->dm_vars.priv_vars;
1173 
1174  if (dmp->dm_debugLevel) {
1175  bu_log("X_drawString2D():\n");
1176  bu_log("\tstr - %s\n", str);
1177  bu_log("\tx - %g\n", x);
1178  bu_log("\ty - %g\n", y);
1179  bu_log("\tsize - %d\n", size);
1180  if (use_aspect) {
1181  bu_log("\tuse_aspect - %d\t\taspect ratio - %g\n", use_aspect, dmp->dm_aspect);
1182  } else
1183  bu_log("\tuse_aspect - 0");
1184  }
1185 
1186  sx = dm_Normal2Xx(dmp, x);
1187  sy = dm_Normal2Xy(dmp, y, use_aspect);
1188 
1189  XDrawString(pubvars->dpy,
1190  privars->pix,
1191  privars->gc,
1192  sx, sy, str, strlen(str));
1193 
1194  return TCL_OK;
1195 }
1196 
1197 
1198 HIDDEN int
1199 X_drawLine2D(struct dm_internal *dmp, fastf_t x_1, fastf_t y_1, fastf_t x_2, fastf_t y_2)
1200 {
1201  int sx1, sy1, sx2, sy2;
1202  struct dm_xvars *pubvars = (struct dm_xvars *)dmp->dm_vars.pub_vars;
1203  struct x_vars *privars = (struct x_vars *)dmp->dm_vars.priv_vars;
1204 
1205  sx1 = dm_Normal2Xx(dmp, x_1);
1206  sx2 = dm_Normal2Xx(dmp, x_2);
1207  sy1 = dm_Normal2Xy(dmp, y_1, 0);
1208  sy2 = dm_Normal2Xy(dmp, y_2, 0);
1209 
1210  if (dmp->dm_debugLevel) {
1211  bu_log("X_drawLine2D()\n");
1212  bu_log("x1 = %g, y1 = %g\n", x_1, y_1);
1213  bu_log("x2 = %g, y2 = %g\n", x_2, y_2);
1214  bu_log("sx1 = %d, sy1 = %d\n", sx1, sy1);
1215  bu_log("sx2 = %d, sy2 = %d\n", sx2, sy2);
1216  }
1217 
1218  XDrawLine(pubvars->dpy,
1219  privars->pix,
1220  privars->gc,
1221  sx1, sy1, sx2, sy2);
1222 
1223  return TCL_OK;
1224 }
1225 
1226 
1227 HIDDEN int
1228 X_drawLine3D(struct dm_internal *dmp, point_t pt1, point_t pt2)
1229 {
1230  return draw_Line3D(dmp, pt1, pt2);
1231 }
1232 
1233 
1234 HIDDEN int
1235 X_drawLines3D(struct dm_internal *dmp, int npoints, point_t *points, int UNUSED(sflag))
1236 {
1237  if (!dmp || npoints < 0 || !points)
1238  return TCL_ERROR;
1239 
1240  return TCL_OK;
1241 }
1242 
1243 
1244 HIDDEN int
1245 X_drawPoint2D(struct dm_internal *dmp, fastf_t x, fastf_t y)
1246 {
1247  int sx, sy;
1248  struct dm_xvars *pubvars = (struct dm_xvars *)dmp->dm_vars.pub_vars;
1249  struct x_vars *privars = (struct x_vars *)dmp->dm_vars.priv_vars;
1250 
1251  sx = dm_Normal2Xx(dmp, x);
1252  sy = dm_Normal2Xy(dmp, y, 0);
1253 
1254  if (dmp->dm_debugLevel) {
1255  bu_log("X_drawPoint2D()\n");
1256  bu_log("x = %g, y = %g\n", x, y);
1257  bu_log("sx = %d, sy = %d\n", sx, sy);
1258  }
1259 
1260  XDrawPoint(pubvars->dpy,
1261  privars->pix,
1262  privars->gc, sx, sy);
1263 
1264  return TCL_OK;
1265 }
1266 
1267 
1268 HIDDEN int
1269 X_setFGColor(struct dm_internal *dmp, unsigned char r, unsigned char g, unsigned char b, int strict, fastf_t transparency)
1270 {
1271  XGCValues gcv;
1272  struct dm_xvars *pubvars = (struct dm_xvars *)dmp->dm_vars.pub_vars;
1273  struct x_vars *privars = (struct x_vars *)dmp->dm_vars.priv_vars;
1274 
1275  if (dmp->dm_debugLevel)
1276  bu_log("X_setFGColor() rgb=[%d, %d, %d] strict=%d transparency=%f\n", r, g, b, strict, transparency);
1277 
1278  dmp->dm_fg[0] = r;
1279  dmp->dm_fg[1] = g;
1280  dmp->dm_fg[2] = b;
1281 
1282  if (privars->is_trueColor) {
1283  XColor color;
1284 
1285  INIT_XCOLOR(&color);
1286 
1287  color.red = r << 8;
1288  color.green = g << 8;
1289  color.blue = b << 8;
1290  get_color(pubvars->dpy,
1291  pubvars->cmap,
1292  &color);
1293 
1294  gcv.foreground = color.pixel;
1295  } else {
1296  gcv.foreground = X_get_pixel(r, g, b, privars->pixels, CUBE_DIMENSION);
1297  }
1298 
1299  /* save foreground pixel */
1300  privars->fg = gcv.foreground;
1301 
1302  XChangeGC(pubvars->dpy,
1303  privars->gc,
1304  GCForeground, &gcv);
1305 
1306  return TCL_OK;
1307 }
1308 
1309 
1310 HIDDEN int
1311 X_setBGColor(struct dm_internal *dmp, unsigned char r, unsigned char g, unsigned char b)
1312 {
1313  struct dm_xvars *pubvars = (struct dm_xvars *)dmp->dm_vars.pub_vars;
1314  struct x_vars *privars = (struct x_vars *)dmp->dm_vars.priv_vars;
1315 
1316  if (dmp->dm_debugLevel)
1317  bu_log("X_setBGColor()\n");
1318 
1319  dmp->dm_bg[0] = r;
1320  dmp->dm_bg[1] = g;
1321  dmp->dm_bg[2] = b;
1322 
1323  if (privars->is_trueColor) {
1324  XColor color;
1325 
1326  INIT_XCOLOR(&color);
1327 
1328  color.red = r << 8;
1329  color.green = g << 8;
1330  color.blue = b << 8;
1331 
1332  get_color(pubvars->dpy,
1333  pubvars->cmap,
1334  &color);
1335 
1336  privars->bg = color.pixel;
1337  } else
1338  privars->bg =
1339  X_get_pixel(r, g, b, privars->pixels, CUBE_DIMENSION);
1340 
1341  return TCL_OK;
1342 }
1343 
1344 
1345 HIDDEN int
1346 X_setLineAttr(struct dm_internal *dmp, int width, int style)
1347 {
1348  int linestyle;
1349  struct dm_xvars *pubvars = (struct dm_xvars *)dmp->dm_vars.pub_vars;
1350  struct x_vars *privars = (struct x_vars *)dmp->dm_vars.priv_vars;
1351 
1352  if (dmp->dm_debugLevel)
1353  bu_log("X_setLineAttr()\n");
1354 
1355  dmp->dm_lineWidth = width;
1356  dmp->dm_lineStyle = style;
1357 
1358  if (width <= 1)
1359  width = 0;
1360 
1361  if (style == DM_DASHED_LINE)
1362  linestyle = LineOnOffDash;
1363  else
1364  linestyle = LineSolid;
1365 
1366  XSetLineAttributes(pubvars->dpy,
1367  privars->gc,
1368  width, linestyle, CapButt, JoinMiter);
1369 
1370  return TCL_OK;
1371 }
1372 
1373 
1374 HIDDEN int
1375 X_debug(struct dm_internal *dmp, int lvl)
1376 {
1377  dmp->dm_debugLevel = lvl;
1378 
1379  return TCL_OK;
1380 }
1381 
1382 
1383 HIDDEN int
1384 X_logfile(struct dm_internal *dmp, const char *filename)
1385 {
1386  bu_vls_sprintf(&dmp->dm_log, "%s", filename);
1387 
1388  return TCL_OK;
1389 }
1390 
1391 
1392 HIDDEN int
1393 X_setWinBounds(struct dm_internal *dmp, fastf_t *w)
1394 {
1395  if (dmp->dm_debugLevel)
1396  bu_log("X_setWinBounds()\n");
1397 
1398  dmp->dm_clipmin[0] = w[0];
1399  dmp->dm_clipmin[1] = w[2];
1400  dmp->dm_clipmin[2] = w[4];
1401  dmp->dm_clipmax[0] = w[1];
1402  dmp->dm_clipmax[1] = w[3];
1403  dmp->dm_clipmax[2] = w[5];
1404 
1405  return TCL_OK;
1406 }
1407 
1408 
1409 HIDDEN int
1410 X_configureWin(struct dm_internal *dmp, int force)
1411 {
1412  /* don't force */
1413  return X_configureWin_guts(dmp, force);
1414 }
1415 
1416 
1417 HIDDEN int
1418 X_setLight(struct dm_internal *dmp, int light_on)
1419 {
1420  if (dmp->dm_debugLevel)
1421  bu_log("X_setLight:\n");
1422 
1423  dmp->dm_light = light_on;
1424 
1425  return TCL_OK;
1426 }
1427 
1428 
1429 HIDDEN int
1430 X_setZBuffer(struct dm_internal *dmp, int zbuffer_on)
1431 {
1432  if (dmp->dm_debugLevel)
1433  bu_log("X_setZBuffer:\n");
1434 
1435  dmp->dm_zbuffer = zbuffer_on;
1436 
1437  return TCL_OK;
1438 }
1439 
1440 
1441 HIDDEN int
1442 X_getDisplayImage(struct dm_internal *dmp, unsigned char **image)
1443 {
1444  XImage *ximage_p;
1445  unsigned char **rows;
1446  unsigned char *idata;
1447  unsigned char *irow;
1448  int bytes_per_pixel;
1449  int bytes_per_pixel_output = 3; /* limit for current bu_image raw pix usage */
1450  int bytes_per_line_output;
1451  int i, j, k;
1452  unsigned char *dbyte0, *dbyte1, *dbyte2;
1453  int red_shift;
1454  int green_shift;
1455  int blue_shift;
1456  int red_bits;
1457  int green_bits;
1458  int blue_bits;
1459 
1460 
1461  ximage_p = XGetImage(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
1462  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->win,
1463  0, 0,
1464  dmp->dm_width,
1465  dmp->dm_height,
1466  ~0, ZPixmap);
1467 
1468  if (!ximage_p) {
1469  bu_log("png: could not get XImage\n", (char *)NULL);
1470  return TCL_ERROR;
1471  }
1472 
1473  bytes_per_pixel = ximage_p->bytes_per_line / ximage_p->width;
1474 
1475  if (bytes_per_pixel == 4) {
1476  unsigned long mask;
1477  unsigned long tmask;
1478 
1479  /* This section assumes 8 bits per channel */
1480 
1481  mask = ximage_p->red_mask;
1482  tmask = 1;
1483  for (red_shift = 0; red_shift < 32; red_shift++) {
1484  if (tmask & mask)
1485  break;
1486  tmask = tmask << 1;
1487  }
1488 
1489  mask = ximage_p->green_mask;
1490  tmask = 1;
1491  for (green_shift = 0; green_shift < 32; green_shift++) {
1492  if (tmask & mask)
1493  break;
1494  tmask = tmask << 1;
1495  }
1496 
1497  mask = ximage_p->blue_mask;
1498  tmask = 1;
1499  for (blue_shift = 0; blue_shift < 32; blue_shift++) {
1500  if (tmask & mask)
1501  break;
1502  tmask = tmask << 1;
1503  }
1504 
1505  /*
1506  * We need to reverse things if the image byte order
1507  * is different from the system's byte order.
1508  */
1509  if (((bu_byteorder() == BU_BIG_ENDIAN) && (ximage_p->byte_order == LSBFirst)) ||
1510  ((bu_byteorder() == BU_LITTLE_ENDIAN) && (ximage_p->byte_order == MSBFirst))) {
1511  DM_REVERSE_COLOR_BYTE_ORDER(red_shift, ximage_p->red_mask);
1512  DM_REVERSE_COLOR_BYTE_ORDER(green_shift, ximage_p->green_mask);
1513  DM_REVERSE_COLOR_BYTE_ORDER(blue_shift, ximage_p->blue_mask);
1514  }
1515 
1516  } else if (bytes_per_pixel == 2) {
1517  unsigned long mask;
1518  unsigned long tmask;
1519  int bpb = 8; /* bits per byte */
1520 
1521  /*XXX
1522  * This section probably needs logic similar
1523  * to the previous section (i.e. bytes_per_pixel == 4).
1524  * That is we may need to reverse things depending on
1525  * the image byte order and the system's byte order.
1526  */
1527 
1528  mask = ximage_p->red_mask;
1529  tmask = 1;
1530  for (red_shift = 0; red_shift < 16; red_shift++) {
1531  if (tmask & mask)
1532  break;
1533  tmask = tmask << 1;
1534  }
1535  for (red_bits = red_shift; red_bits < 16; red_bits++) {
1536  if (!(tmask & mask))
1537  break;
1538  tmask = tmask << 1;
1539  }
1540 
1541  red_bits = red_bits - red_shift;
1542  if (red_shift == 0)
1543  red_shift = red_bits - bpb;
1544  else
1545  red_shift = red_shift - (bpb - red_bits);
1546 
1547  mask = ximage_p->green_mask;
1548  tmask = 1;
1549  for (green_shift = 0; green_shift < 16; green_shift++) {
1550  if (tmask & mask)
1551  break;
1552  tmask = tmask << 1;
1553  }
1554  for (green_bits = green_shift; green_bits < 16; green_bits++) {
1555  if (!(tmask & mask))
1556  break;
1557  tmask = tmask << 1;
1558  }
1559 
1560  green_bits = green_bits - green_shift;
1561  green_shift = green_shift - (bpb - green_bits);
1562 
1563  mask = ximage_p->blue_mask;
1564  tmask = 1;
1565  for (blue_shift = 0; blue_shift < 16; blue_shift++) {
1566  if (tmask & mask)
1567  break;
1568  tmask = tmask << 1;
1569  }
1570  for (blue_bits = blue_shift; blue_bits < 16; blue_bits++) {
1571  if (!(tmask & mask))
1572  break;
1573  tmask = tmask << 1;
1574  }
1575  blue_bits = blue_bits - blue_shift;
1576 
1577  if (blue_shift == 0)
1578  blue_shift = blue_bits - bpb;
1579  else
1580  blue_shift = blue_shift - (bpb - blue_bits);
1581  } else {
1582  bu_log("png: %d bytes per pixel is not yet supported\n", bytes_per_pixel);
1583  return TCL_ERROR;
1584  }
1585 
1586  rows = (unsigned char **)bu_calloc(ximage_p->height, sizeof(unsigned char *), "rows");
1587  idata = (unsigned char *)bu_calloc(ximage_p->height * ximage_p->width, bytes_per_pixel_output, "png data");
1588  *image = idata;
1589 
1590  /* for each scanline */
1591  bytes_per_line_output = ximage_p->width * bytes_per_pixel_output;
1592  for (i = ximage_p->height - 1, j = 0; 0 <= i; --i, ++j) {
1593  /* irow points to the current scanline in ximage_p */
1594  irow = (unsigned char *)(ximage_p->data + ((ximage_p->height-i-1)*ximage_p->bytes_per_line));
1595 
1596  if (bytes_per_pixel == 4) {
1597  unsigned int pixel;
1598 
1599  /* rows[j] points to the current scanline in idata */
1600  rows[j] = (unsigned char *)(idata + ((ximage_p->height-i-1)*bytes_per_line_output));
1601 
1602  /* for each pixel in current scanline of ximage_p */
1603  for (k = 0; k < ximage_p->width; k++) {
1604  pixel = *((unsigned int *)(irow + k*bytes_per_pixel));
1605 
1606  dbyte0 = rows[j] + k*bytes_per_pixel_output;
1607  dbyte1 = dbyte0 + 1;
1608  dbyte2 = dbyte0 + 2;
1609 
1610  *dbyte0 = (pixel & ximage_p->red_mask) >> red_shift;
1611  *dbyte1 = (pixel & ximage_p->green_mask) >> green_shift;
1612  *dbyte2 = (pixel & ximage_p->blue_mask) >> blue_shift;
1613  }
1614  } else if (bytes_per_pixel == 2) {
1615  unsigned short spixel;
1616  unsigned long pixel;
1617 
1618  /* rows[j] points to the current scanline in idata */
1619  rows[j] = (unsigned char *)(idata + ((ximage_p->height-i-1)*bytes_per_line_output));
1620 
1621  /* for each pixel in current scanline of ximage_p */
1622  for (k = 0; k < ximage_p->width; k++) {
1623  spixel = *((unsigned short *)(irow + k*bytes_per_pixel));
1624  pixel = spixel;
1625 
1626  dbyte0 = rows[j] + k*bytes_per_pixel_output;
1627  dbyte1 = dbyte0 + 1;
1628  dbyte2 = dbyte0 + 2;
1629 
1630  if (0 <= red_shift)
1631  *dbyte0 = (pixel & ximage_p->red_mask) >> red_shift;
1632  else
1633  *dbyte0 = (pixel & ximage_p->red_mask) << -red_shift;
1634 
1635  *dbyte1 = (pixel & ximage_p->green_mask) >> green_shift;
1636 
1637  if (0 <= blue_shift)
1638  *dbyte2 = (pixel & ximage_p->blue_mask) >> blue_shift;
1639  else
1640  *dbyte2 = (pixel & ximage_p->blue_mask) << -blue_shift;
1641  }
1642  } else {
1643  bu_free(rows, "rows");
1644  bu_free(idata, "image data");
1645 
1646  bu_log("png: not supported for this platform\n", (char *)NULL);
1647  return TCL_ERROR;
1648  }
1649  }
1650 
1651  bu_free(rows, "rows");
1652  return TCL_OK;
1653 }
1654 
1655 int
1656 X_openFb(struct dm_internal *dmp)
1657 {
1658  struct fb_platform_specific *fb_ps;
1659  struct X24_fb_info *xfb_ps;
1660  struct dm_xvars *pubvars = (struct dm_xvars *)dmp->dm_vars.pub_vars;
1661  struct x_vars *privars = (struct x_vars *)dmp->dm_vars.priv_vars;
1662 
1664  xfb_ps = (struct X24_fb_info *)fb_ps->data;
1665  xfb_ps->dpy = pubvars->dpy;
1666  xfb_ps->win = privars->pix;
1667  xfb_ps->cwinp = pubvars->win;
1668  xfb_ps->cmap = pubvars->cmap;
1669  xfb_ps->vip = pubvars->vip;
1670  xfb_ps->gc = privars->gc;
1671 
1672  dmp->fbp = fb_open_existing("X", dm_get_width(dmp), dm_get_height(dmp), fb_ps);
1673  fb_put_platform_specific(fb_ps);
1674  return 0;
1675 }
1676 
1677 struct bu_structparse X_vparse[] = {
1678  {"%g", 1, "bound", DM_O(dm_bound), dm_generic_hook, NULL, NULL},
1679  {"%d", 1, "useBound", DM_O(dm_boundFlag), dm_generic_hook, NULL, NULL},
1680  {"%d", 1, "zclip", DM_O(dm_zclip), dm_generic_hook, NULL, NULL},
1681  {"%d", 1, "debug", DM_O(dm_debugLevel), dm_generic_hook, NULL, NULL},
1682  {"", 0, (char *)0, 0, BU_STRUCTPARSE_FUNC_NULL, NULL, NULL}
1683 };
1684 
1685 /* Display Manager package interface */
1686 struct dm_internal dm_X = {
1687  X_close,
1688  X_drawBegin,
1689  X_drawEnd,
1690  X_normal,
1691  X_loadMatrix,
1693  X_drawString2D,
1694  X_drawLine2D,
1695  X_drawLine3D,
1696  X_drawLines3D,
1697  X_drawPoint2D,
1700  X_drawVList,
1701  X_drawVList,
1702  X_draw,
1703  X_setFGColor,
1704  X_setBGColor,
1705  X_setLineAttr,
1706  X_configureWin,
1707  X_setWinBounds,
1708  X_setLight,
1711  X_setZBuffer,
1712  X_debug,
1713  X_logfile,
1715  null_endDList,
1719  NULL,
1720  X_getDisplayImage, /* display to image function */
1721  X_reshape,
1723  X_openFb,
1724  NULL,
1725  NULL,
1726  0,
1727  0, /* no displaylist */
1728  0, /* no stereo */
1729  PLOTBOUND, /* zoom-in limit */
1730  1, /* bound flag */
1731  "X",
1732  "X Window System (X11)",
1733  DM_TYPE_X,
1734  1,
1735  0,
1736  0,
1737  0, /* bytes per pixel */
1738  0, /* bits per channel */
1739  0,
1740  0,
1741  1.0, /* aspect ratio */
1742  0,
1743  {0, 0},
1744  NULL,
1745  NULL,
1746  BU_VLS_INIT_ZERO, /* bu_vls path name*/
1747  BU_VLS_INIT_ZERO, /* bu_vls full name drawing window */
1748  BU_VLS_INIT_ZERO, /* bu_vls short name drawing window */
1749  {0, 0, 0}, /* bg color */
1750  {0, 0, 0}, /* fg color */
1751  {GED_MIN, GED_MIN, GED_MIN}, /* clipmin */
1752  {GED_MAX, GED_MAX, GED_MAX}, /* clipmax */
1753  0, /* no debugging */
1754  BU_VLS_INIT_ZERO, /* bu_vls logfile */
1755  0, /* no perspective */
1756  0, /* no lighting */
1757  0, /* no transparency */
1758  0, /* depth buffer is not writable */
1759  0, /* no zbuffer */
1760  0, /* no zclipping */
1761  1, /* clear back buffer after drawing and swap */
1762  0, /* not overriding the auto font size */
1763  X_vparse,
1764  FB_NULL,
1765  0 /* Tcl interpreter */
1766 };
1767 
1768 /* Because class is actually used to access a struct
1769  * entry in this file, preserve our redefinition
1770  * of class for the benefit of avoiding C++ name
1771  * collisions until the end of this file */
1772 #undef class
1773 
1774 #endif /* DM_X */
1775 
1776 /*
1777  * Local Variables:
1778  * mode: C
1779  * tab-width: 8
1780  * indent-tabs-mode: t
1781  * c-file-style: "stroustrup"
1782  * End:
1783  * ex: shiftwidth=4 tabstop=8
1784  */
#define CUBE_DIMENSION
Definition: dm-tk.h:30
#define FONT5
Definition: dm.h:75
void bu_vls_init(struct bu_vls *vp)
Definition: vls.c:56
int null_setDepthMask(struct dm_internal *dmp, int mask)
Definition: dm-Null.c:199
#define BU_LIST_FOR(p, structure, hp)
Definition: list.h:365
char filename[MAXLENGTH]
Definition: human.c:105
size_t nused
elements 0..nused active
Definition: vlist.h:73
#define GED_MAX
Definition: ged.h:253
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
struct bu_list l
magic, forw, back
Definition: vlist.h:72
int devbuttonpress
Definition: dm_xvars.h:82
int dm_top
!0 means toplevel window
Definition: dm_private.h:90
int dm_width
Definition: dm_private.h:91
Definition: list.h:118
void * pub_vars
Definition: dm_private.h:35
ustring interp
#define DM_DASHED_LINE
Definition: dm.h:109
int dm_zclip
!0 means zclipping
Definition: dm_private.h:116
void * data
Definition: fb.h:176
fb * fbp
Framebuffer associated with this display instance.
Definition: dm_private.h:120
int dm_get_width(dm *dmp)
Definition: dm-generic.c:335
int cmd[BN_VLIST_CHUNK]
VL_CMD_*.
Definition: vlist.h:74
#define GED_TO_Xx(_dmp, x)
Definition: dm.h:61
Tk_Window xtkwin
Definition: dm_xvars.h:65
int dm_Normal2Xx(dm *dmp, fastf_t f)
Definition: dm-generic.c:216
int draw_Line3D(struct dm_internal *dmp, point_t pt1, point_t pt2)
Definition: dm_util.c:167
int depth
Definition: dm_xvars.h:66
#define DM_SAME_COLOR(_dr, _dg, _db, _sr, _sg, _sb)
Definition: dm.h:167
#define FONT9
Definition: dm.h:79
vect_t dm_clipmax
maximum clipping vector
Definition: dm_private.h:108
#define st
Tcl_Interp * dm_interp
Tcl interpreter.
Definition: dm_private.h:121
unsigned char dm_fg[3]
foreground color
Definition: dm_private.h:106
int dm_processOptions(dm *dmp, struct bu_vls *init_proc_vls, int argc, char **argv)
Definition: options.c:38
#define FONT6
Definition: dm.h:76
void bu_vls_strncpy(struct bu_vls *vp, const char *s, size_t n)
Definition: vls.c:339
bu_endian_t bu_byteorder(void)
Definition: endian.c:27
long Display
Definition: dm_xvars.h:49
int null_genDLists(struct dm_internal *dmp, size_t range)
Definition: dm-Null.c:252
Header file for the BRL-CAD common definitions.
int null_loadPMatrix(struct dm_internal *dmp, fastf_t *mat)
Definition: dm-Null.c:73
int dm_light
!0 means lighting on
Definition: dm_private.h:112
ustring width
int null_freeDLists(struct dm_internal *dmp, unsigned int list, int range)
Definition: dm-Null.c:245
fastf_t dm_aspect
Definition: dm_private.h:97
#define HIDDEN
Definition: common.h:86
struct fb_platform_specific * fb_get_platform_specific(uint32_t magic)
Definition: fb_generic.c:113
#define BN_VLIST_POLY_MOVE
move to first poly vertex
Definition: vlist.h:85
void * bu_malloc(size_t siz, const char *str)
Definition: malloc.c:314
#define BN_VLIST_TRI_VERTNORM
per-vertex normal, for interpolation
Definition: vlist.h:93
struct bu_vls dm_tkName
short Tcl/Tk name of drawing window
Definition: dm_private.h:103
if(share_geom)
Definition: nmg_mod.c:3829
void bu_vls_free(struct bu_vls *vp)
Definition: vls.c:248
Definition: color.c:49
COMPLEX data[64]
Definition: fftest.c:34
Colormap cmap
Definition: dm_xvars.h:67
#define DM_NULL
Definition: dm.h:43
dm dm_X
unsigned long fg
Definition: dm-X.h:42
#define FB_NULL
Definition: fb.h:95
#define BU_ALLOC(_ptr, _type)
Definition: malloc.h:223
int dm_perspective
!0 means perspective on
Definition: dm_private.h:111
void * bu_calloc(size_t nelem, size_t elsize, const char *str)
Definition: malloc.c:321
unsigned long dm_id
window id
Definition: dm_private.h:82
struct bu_vls dm_log
!NULL && !empty means log debug output to the file
Definition: dm_private.h:110
#define DM_TYPE_X
Definition: dm.h:95
void bu_vls_sprintf(struct bu_vls *vls, const char *fmt,...) _BU_ATTR_PRINTF23
Definition: vls.c:707
#define PLOTBOUND
Definition: dm-plot.c:56
#define BN_VLIST_POLY_START
pt[] has surface normal
Definition: vlist.h:84
int devmotionnotify
Definition: dm_xvars.h:81
#define BN_VLIST_LINE_MOVE
Definition: vlist.h:82
int null_makeCurrent(struct dm_internal *dmp)
Definition: dm-Null.c:272
#define V3ARGS(a)
Definition: color.c:56
long Colormap
Definition: dm_xvars.h:51
struct bu_vls dm_dName
Display name.
Definition: dm_private.h:104
#define SQRT_SMALL_FASTF
Definition: defines.h:346
unsigned long pixels[NUM_PIXELS]
Definition: dm-X.h:43
int vclip(fastf_t *, fastf_t *, fastf_t *, fastf_t *)
#define BN_VLIST_LINE_DRAW
Definition: vlist.h:83
Tk_Window top
Definition: dm_xvars.h:64
int vectorThreshold
Definition: tcl.c:46
#define DM_BLACK
Definition: dm.h:158
size_t bu_vls_strlen(const struct bu_vls *vp)
Definition: vls.c:189
int devbuttonrelease
Definition: dm_xvars.h:83
#define UNUSED(parameter)
Definition: common.h:239
unsigned long bg
Definition: dm-X.h:42
int null_beginDList(struct dm_internal *dmp, unsigned int list)
Definition: dm-Null.c:225
#define BN_VLIST_POLY_DRAW
subsequent poly vertex
Definition: vlist.h:86
#define DM_RED
Definition: dm.h:159
#define GED_MIN
Definition: ged.h:254
#define FONT7
Definition: dm.h:77
int dm_get_height(dm *dmp)
Definition: dm-generic.c:342
char * bu_vls_addr(const struct bu_vls *vp)
Definition: vls.c:111
#define BN_VLIST_TRI_END
last vert (repeats 1st), draw poly
Definition: vlist.h:92
Display * dpy
Definition: dm_xvars.h:62
int dm_lineWidth
Definition: dm_private.h:95
int is_trueColor
Definition: dm-X.h:41
#define BU_STRUCTPARSE_FUNC_NULL
Definition: parse.h:153
struct fg_node fg
Definition: chull3d.cpp:80
ustring alpha
void * Tk_Window
Definition: dm_xvars.h:44
Window win
Definition: dm_xvars.h:63
#define BU_LIST_PUSH(hp, p)
Definition: list.h:246
#define FONT8
Definition: dm.h:78
#define BN_VLIST_TRI_START
pt[] has surface normal
Definition: vlist.h:89
fb * fb_open_existing(const char *file, int _width, int _height, struct fb_platform_specific *fb_p)
Definition: fb_generic.c:146
#define BN_VLIST_POINT_SIZE
specify point pixel size
Definition: vlist.h:95
mat_t xmat
Definition: dm-X.h:40
#define BU_LIST_INIT(_hp)
Definition: list.h:148
void * priv_vars
Definition: dm_private.h:36
vect_t dm_clipmin
minimum clipping vector
Definition: dm_private.h:107
Definition: vlist.h:71
struct dm_vars dm_vars
display manager dependent variables
Definition: dm_private.h:99
int dm_height
Definition: dm_private.h:92
int dm_zbuffer
!0 means zbuffer on
Definition: dm_private.h:115
#define BN_VLIST_POLY_VERTNORM
per-vertex normal, for interpolation
Definition: vlist.h:88
void null_drawDList(unsigned int list)
Definition: dm-Null.c:239
int clip(fastf_t *, fastf_t *, fastf_t *, fastf_t *)
Definition: clip.c:66
#define FB_X24_MAGIC
Definition: magic.h:183
Pixmap pix
Definition: dm-X.h:39
#define BN_VLIST_POLY_END
last vert (repeats 1st), draw poly
Definition: vlist.h:87
void bu_vls_printf(struct bu_vls *vls, const char *fmt,...) _BU_ATTR_PRINTF23
Definition: vls.c:694
int null_setTransparency(struct dm_internal *dmp, int transparency)
Definition: dm-Null.c:192
struct bu_vls dm_pathName
full Tcl/Tk name of drawing window
Definition: dm_private.h:102
#define FONTBACK
Definition: dm.h:74
#define CMAP_BASE
Definition: dm-ogl.h:40
#define DM_O(_m)
Definition: dm.h:47
#define BN_VLIST_TRI_DRAW
subsequent triangle vertex
Definition: vlist.h:91
int dm_Normal2Xy(dm *dmp, fastf_t f, int use_aspect)
Definition: dm-generic.c:233
unsigned char dm_bg[3]
background color
Definition: dm_private.h:105
Definition: color.c:51
int null_drawPoint3D(struct dm_internal *dmp, point_t point)
Definition: dm-Null.c:115
void bu_vls_strcpy(struct bu_vls *vp, const char *s)
Definition: vls.c:310
#define INIT_XCOLOR(c)
Definition: dm_xvars.h:56
void dm_generic_hook(const struct bu_structparse *sdp, const char *name, void *base, const char *value, void *data)
Definition: dm-generic.c:831
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
int null_drawPoints3D(struct dm_internal *dmp, int npoints, point_t *points)
Definition: dm-Null.c:122
Definition: dm-X.h:37
#define BU_VLS_INIT_ZERO
Definition: vls.h:84
#define DM_REVERSE_COLOR_BYTE_ORDER(_shift, _mask)
Definition: dm.h:191
point_t pt[BN_VLIST_CHUNK]
associated 3-point/vect
Definition: vlist.h:75
int dm_debugLevel
!0 means debugging
Definition: dm_private.h:109
int null_endDList(struct dm_internal *dmp)
Definition: dm-Null.c:232
Definition: vls.h:56
HIDDEN const point_t delta
Definition: sh_prj.c:618
double fastf_t
Definition: defines.h:300
#define GED_TO_Xy(_dmp, x)
Definition: dm.h:62
int dm_lineStyle
Definition: dm_private.h:96
Definition: color.c:50
void fb_put_platform_specific(struct fb_platform_specific *fb_p)
Definition: fb_generic.c:129
#define BN_VLIST_POINT_DRAW
Draw a single point.
Definition: vlist.h:94
GC gc
Definition: dm-X.h:38
#define BU_STR_EQUAL(s1, s2)
Definition: str.h:126
#define BN_VLIST_TRI_MOVE
move to first triangle vertex
Definition: vlist.h:90