2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: cgmcmds.c /main/12 1996/11/11 11:32:39 cde-hal $ */
24 /* module to process the CGM binary format commands */
25 /* optimised for calling XLib commands */
26 #include "cgm.h" /* our defs */
27 #include <math.h> /* math functions */
28 #include <stdio.h> /* math functions */
29 /* everything is in C rather than C++ for portability */
30 /* means we must use some file-scope globals */
31 #define MAXCOLRS 1024 /* allow only this many colours for mapped devices */
32 static Display *display;
37 static int visualClass, visualID, colormap_size, bits_per_rgb;
38 static unsigned long redMask, greenMask, blueMask;
39 static unsigned int visualDepth;
40 /* in case we need this for error messages */
41 static char *visualNames[6] = {"StaticGrey", "GrayScale", "StaticColor",
42 "PseudoColor", "TrueColor", "DirectColor"};
43 static Dimension *ret_width;
44 static Dimension *ret_height;
45 static XColor my_colrs[MAXCOLRS];
46 static Pixel **ret_colrs;
47 static int *ret_number;
49 static int max_size = 512, max_y, max_x;
51 static Pixmap *retPixmap;
52 /* Graphics Contexts, and ancillaries */
53 static GC fillGC, edgeGC, textGC, markGC, lineGC, cellGC;
54 static XGCValues myStruct; /* for convenience */
55 static unsigned long mask;
56 static Pixel blackPixel, whitePixel;
57 static float xPxlMM, yPxlMM; /* pixels per mm */
59 static int setBackColr = 0; /* has the background colour been set ? */
60 /* index into this for dashed line specs */
61 static char lineArray[6] = {9, 9, 3, 3, 3, 3};
62 /* deal with Colour map */
63 #define COLCONV 65535.0 /* for conversion to XColors */
64 static Pixel coltabPixels[MAXCOLRS];
66 static Region clipRegion, extRegion;
68 static partialText *textPtr;
69 static int textW, textH, textX, textY;
72 static float ScaleFactor;
73 /* now the Binary format specific routines that read the various data types */
74 /* all of these routines take the address of a pointer and step the pointer */
75 /* forward before they return */
76 /* the general Binary format string */
77 static b_str(unsigned char **in_ptr, char **out_ptr)
79 int p_len, data_left, i;
80 unsigned char *my_ptr;
82 p_len = (int) *(*in_ptr)++;
83 if (p_len == 255) { /* more to come */
84 data_left = (**in_ptr >> 7) && 1;
85 p_len = ((**in_ptr & 127) << 8) + (int) *(*in_ptr + 1);
86 *in_ptr += 2; /* skip over this bit */
87 if (data_left) { /* fix later */
88 burp(stderr, "truncating string at %d bytes\n", p_len);
92 if (!(my_ptr = (unsigned char *) malloc(p_len + 1))) {
93 burp(stderr, "couldn't grab %d bytes in b_str\n", p_len + 1);
96 *out_ptr = (char *) my_ptr;
97 for (i=0; i<p_len; ++i) *my_ptr++ = *(*in_ptr)++;
98 *my_ptr = (unsigned char) 0;
102 /* now the integers */
103 /* unsigned CGM integer at arbitrary legal precision */
104 static unsigned int b_guint(in_ptr, bits_p)
105 unsigned char **in_ptr; /* pointer to the input data pointer */
106 int bits_p; /* no. of bits precision */
112 for (i=1; i<(bits_p / 8); ++i)
113 val = (val << 8) | *(*in_ptr)++;
117 /* signed CGM integer at arbitrary legal precision */
118 static int b_gsint(in_ptr, bits_p)
119 unsigned char **in_ptr; /* pointer to the input data pointer */
120 int bits_p; /* no. of bits precision */
123 /* have to worry about sign extension, may not have signed char */
124 if (**in_ptr & (1 << 7)) val = (-1 ^ 255) | *(*in_ptr)++;
125 else val = *(*in_ptr)++;
126 for (i=1; i<(bits_p / 8); ++i)
127 val = (val << 8) | *(*in_ptr)++;
132 /* the fixed point real */
133 static double b_fixed(dat_ptr, prec)
134 unsigned char **dat_ptr;
138 /* do it in two parts; the big (first) part and fractional (second) part */
140 ret = (double) b_gsint(dat_ptr, prec->exp); /* first part */
141 ret += (double) b_guint(dat_ptr, prec->fract) / (1 << prec->fract);
145 /* the IEEE floating point */
146 static double b_ieee(dat_ptr, prec)
147 unsigned char **dat_ptr;
150 #define TABLESIZE 128
151 static double shift_table[TABLESIZE];
153 int is_neg, i; /* is it a negative number ? */
154 unsigned long big_part, small_part;
155 /* use table for both speed and safety */
156 if (shift_table[0] == 0) {
157 for (i=0; i<TABLESIZE; ++i) shift_table[i] = 1.0 / (1 << i);
160 /* this is basically copied from the IEEE spec */
162 is_neg = (**dat_ptr >> 7) & 1;
164 if ((prec->exp + prec->fract) == 32) { /* 32-bit precision */
165 big_part = (((*dat_ptr)[0] & 127) << 1) + (((*dat_ptr)[1] >> 7) & 1);
166 small_part = (((*dat_ptr)[1] & 127) << 16) +
167 ((*dat_ptr)[2] << 8) + (*dat_ptr)[3];
168 *dat_ptr += 4; /* skip forward */
169 /* now check for special cases */
170 if (big_part == 255) {
171 if (small_part == 0) {
172 /* ret = (double) HUGE_VAL; biggest possible */
173 ret = (double) 1000000; /* biggest possible */
175 burp(stderr, "IEEE undefined real, small part = %ld, != 0\n",
179 } else if (big_part == 0) {
180 if (small_part == 0) {
183 ret = small_part * pow(2.0, -149.0);
186 else { /* normal case */
187 /* ret = 1.0 + small_part * pow(2.0, -23.0); */
188 ret = 1.0 + small_part * shift_table[23];
189 /* ret *= pow(2.0, (double) big_part - 127.0); */
190 if (big_part < TABLESIZE)
191 ret *= shift_table[TABLESIZE - 1 - big_part];
192 else ret *= pow(2.0, (double) big_part - 127.0);
193 /* avoid use of pow, gives trouble on some compilers */
195 } else if ((prec->exp + prec->fract) == 64) { /* 64-bit precision */
196 big_part = ((**dat_ptr & 127) << 4) +
197 ((*(*dat_ptr + 1) >> 4) & 15);
198 dsp = (double) (*(*dat_ptr + 1) & 15);
199 for (i=2; i<8; ++i) {
201 dsp += (double) *(*dat_ptr + i);
203 *dat_ptr += 8; /* skip forward */
204 if (big_part == 2047) {
206 /* ret = (double) HUGE_VAL; biggest possible */
207 ret = (double) 1000000; /* biggest possible */
209 burp(stderr, "IEEE undefined real, dsp = %f, != 0.0\n", dsp);
212 } else if (big_part == 0) {
213 if (dsp == 0.0) ret = 0.0;
214 else ret = dsp * pow(2.0, -1074.0);
216 ret = 1.0 + dsp * pow(2.0, -52.0);
217 ret *= pow(2.0, (double) big_part - 1023.0);
220 burp(stderr, "illegal precision in IEEE\n");
223 if (is_neg) ret = -ret;
227 /* the general real */
228 static double b_real(dat_ptr, rprec)
229 unsigned char **dat_ptr;
232 if (rprec->fixed == 0) { /* floating point */
233 return(b_ieee(dat_ptr, rprec));
234 } else if (rprec->fixed == 1) { /* fixed */
235 return(b_fixed(dat_ptr, rprec));
237 burp(stderr, "illegal real precision %d\n", rprec->fixed);
241 /* XLib specific functions */
242 /* the setup routine */
243 xl_setup(Screen *screen, Display *inDisplay, Window inWin, int inDepth,
244 Colormap inCmap, Visual *inVis, GC inGC, Dimension *in_width,
245 Dimension *in_height, Pixel **in_colrs, int *in_number,
246 Pixmap *inPixmap, unsigned short sf)
248 XVisualInfo myTemp, *myInfo;
250 ScaleFactor = (float)sf;
251 ScaleFactor /= 100.0;
258 ret_width = in_width;
259 ret_height = in_height;
260 ret_colrs = in_colrs;
261 /* figure out our visual class */
262 visualID = XVisualIDFromVisual(inVis);
263 myTemp.visualid = visualID;
264 /* get the visual info */
265 myInfo = XGetVisualInfo(display, VisualIDMask, &myTemp, &tmp);
266 visualClass = myInfo->class; /* crazy for XLib to use this word ! */
267 visualDepth = myInfo->depth;
268 redMask = myInfo->red_mask;
269 greenMask = myInfo->green_mask;
270 blueMask = myInfo->blue_mask;
271 colormap_size = myInfo->colormap_size;
272 bits_per_rgb = myInfo->bits_per_rgb;
274 fprintf(stderr, "visual class is %s\n", visualNames[visualClass]);
275 fprintf(stderr, "depth = %d, mask = (%ld, %ld, %ld), cmap_size = %d, bits = %d\n",
276 visualDepth, redMask, greenMask, blueMask, colormap_size,
280 /* get the memory now for in_colrs in case we get a malformed cgm file */
281 *ret_colrs = (Pixel *) malloc(MAXCOLRS * sizeof(Pixel));
282 ret_number = in_number;
284 retPixmap = inPixmap; /* so we can change *inPixmap later */
286 myStruct.line_width = 0; /* default to 0 for speed */
287 myStruct.line_style = LineSolid;
288 myStruct.fill_style = FillSolid;
289 myStruct.cap_style = CapButt;
290 myStruct.join_style = JoinBevel; /* screws up with Miter */
297 fillGC = XCreateGC(display, win, mask, &myStruct);
298 edgeGC = XCreateGC(display, win, mask, &myStruct);
299 textGC = XCreateGC(display, win, mask, &myStruct);
300 markGC = XCreateGC(display, win, mask, &myStruct);
301 lineGC = XCreateGC(display, win, mask, &myStruct);
302 cellGC = XCreateGC(display, win, mask, &myStruct);
303 /* take the foreground and background colours from the input GC */
307 XCopyGC(display, inGC, mask, fillGC);
308 XCopyGC(display, inGC, mask, edgeGC);
309 XCopyGC(display, inGC, mask, textGC);
310 XCopyGC(display, inGC, mask, textGC);
311 XCopyGC(display, inGC, mask, lineGC);
313 /* get our black and white pixels */
314 blackPixel = BlackPixelOfScreen(screen);
315 whitePixel = WhitePixelOfScreen(screen);
316 xPxlMM = ((float) WidthOfScreen(screen)) / WidthMMOfScreen(screen);
317 yPxlMM = ((float) HeightOfScreen(screen)) / HeightMMOfScreen(screen);
320 /* how we get a X coordinate, use float, probably truncate later */
321 static float getX(unsigned char **dat_ptr, cgm_s_type *cgm_s)
323 switch (cgm_s->vdctype) {
324 case VDC_INT: return xScale *
325 (b_gsint(dat_ptr, cgm_s->vdcintprec) - cgm_s->vdcextent[0].i);
326 case VDC_REAL: return xScale *
327 (b_real(dat_ptr, &(cgm_s->vdcrprec)) - cgm_s->vdcextent[0].r);
328 default: return 0; /* where did this come from ? */
331 /* how we get a Y coordinate, use float, probably truncate later */
332 static float getY(unsigned char **dat_ptr, cgm_s_type *cgm_s)
334 switch (cgm_s->vdctype) {
335 case VDC_INT: return xScale *
336 (b_gsint(dat_ptr, cgm_s->vdcintprec) - cgm_s->vdcextent[1].i);
337 case VDC_REAL: return xScale *
338 (b_real(dat_ptr, &(cgm_s->vdcrprec)) - cgm_s->vdcextent[1].r);
339 default: return 0; /* where did this come from ? */
342 /* how we get a VDC, use float, probably truncate later, no offset needed */
343 static float getVDC(unsigned char **dat_ptr, cgm_s_type *cgm_s)
345 switch (cgm_s->vdctype) {
346 case VDC_INT: return xScale * b_gsint(dat_ptr, cgm_s->vdcintprec);
347 case VDC_REAL: return xScale * b_real(dat_ptr, &(cgm_s->vdcrprec));
348 default: return 0; /* where did this come from ? */
351 /* quick macro for colour difference */
352 #define XCOLRDIF(colr1, colr2) \
353 (abs(colr1.red - colr2.red) + \
354 abs(colr1.green - colr2.green) + \
355 abs(colr1.blue - colr2.blue))
356 /* this is where all colours are sorted out, even indexed colours */
357 static Pixel getPixel(cgm_s_type *cgm_s, int iColrs[3])
364 unsigned short r, g, b;
366 unsigned int bestDif, tempDif;
367 /* normalize colours for X routines */
368 for (i=0; i<3; ++i) {
369 fDiv = cgm_s->cvextent[i+3] - cgm_s->cvextent[i]; /* for safety */
370 dColrs[i] = (iColrs[i] - cgm_s->cvextent[i]) / fDiv;
372 /* we split up by visual class */
373 switch (visualClass) {
374 case 5: /* DirectColor */
375 case 2: /* StaticColor */
376 case 4: /* TrueColor */
377 /* can get the pixel directly for these classes */
378 /* assume it's better to do that than work with the colour map */
379 bestPixel = (redMask & (int) (redMask * dColrs[0])) |
380 (greenMask & (int) (greenMask * dColrs[1])) |
381 (blueMask & (int) (blueMask * dColrs[2]));
383 /* now the visuals for which XAllocColor makes sense */
384 default: /* just in case */
385 case 1: /* GreyScale */
386 case 0 : /* Static Grey */
387 if (visualDepth == 2) { /* monochrome, a common display */
388 return ((dColrs[0] + dColrs[1] + dColrs[2]) > 0.9) ? blackPixel :
391 /* else fall thru to the pseudo colour visual for XAllocColor */
392 case 3: /* PseudoColor */
393 /* just ask for closest colour */
394 inColr.red = (unsigned short) (dColrs[0] * COLCONV + 0.4999);
395 inColr.green = (unsigned short) (dColrs[1] * COLCONV + 0.4999);
396 inColr.blue = (unsigned short) (dColrs[2] * COLCONV + 0.4999);
397 ret = XAllocColor(display, cmap, &inColr);
399 /* lets see if it's a new one or not */
400 for (i=0; i<*ret_number; ++i) {
401 if (my_colrs[i].pixel == inColr.pixel)
403 XFreeColors(display, cmap, &inColr.pixel,1, 0);
407 /* must be a new one */
408 my_colrs[*ret_number].red = inColr.red;
409 my_colrs[*ret_number].green = inColr.green;
410 my_colrs[*ret_number].blue = inColr.blue;
411 my_colrs[*ret_number].pixel = inColr.pixel;
412 if (*ret_number < (MAXCOLRS - 1))
418 /* look for best so far */
419 /* if nothing, fall back on black/white */
420 if (!*ret_number) return ((dColrs[0] + dColrs[1] + dColrs[2]) > 0.9)
421 ? blackPixel : whitePixel;
422 /* at least have some to work with */
424 bestPixel = my_colrs[bestI].pixel;
425 bestDif = XCOLRDIF(my_colrs[bestI], inColr);
426 for (i=1; i<*ret_number; ++i) { /* real ugly, but do for now */
427 tempDif = XCOLRDIF(my_colrs[i], inColr);
428 if (tempDif < bestDif) {
429 bestPixel = my_colrs[i].pixel;
436 } /* end of switch */
438 /* a direct colour */
439 static void setRGB(cgm_s_type *cgm_s, int iColrs[3], GC inGC)
442 usePixel = getPixel(cgm_s, iColrs);
443 XSetForeground(display, inGC, usePixel);
445 /* an indexed colour */
446 static Pixel getIPixel(int index)
448 if ((index >= 0) && (index < MAXCOLRS) && coltabPixels[index]) {
449 return coltabPixels[index];
450 } else return blackPixel;;
452 static void setIndex(cgm_s_type *cgm_s, int index, GC inGC)
454 XSetForeground(display, inGC, getIPixel(index));
456 /* now the functions that do the work */
459 static bmf(unsigned char *dat_ptr, struct cmd_info_s *cmd_ptr,
462 /* nothing for now */
466 static emf(unsigned char *dat_ptr, struct cmd_info_s *cmd_ptr,
469 /* nothing for now */
473 static bpic(unsigned char *dat_ptr, struct cmd_info_s *cmd_ptr,
476 /* nothing for now */
479 /* Begin Picture Body */
480 static bpicbody(unsigned char *dat_ptr, struct cmd_info_s *cmd_ptr,
483 XPoint myClipRect[4];
485 /* look at VDC extent and figure out Pixmap size and scaling */
486 float x0, x1, y0, y1, w, h, maxWH;
488 if (cgm_s->vdctype) { /* real VDC's */
489 x0 = cgm_s->vdcextent[0].r;
490 y0 = cgm_s->vdcextent[1].r;
491 x1 = cgm_s->vdcextent[2].r;
492 y1 = cgm_s->vdcextent[3].r;
493 } else { /* integer VDC'c */
494 x0 = cgm_s->vdcextent[0].i;
495 y0 = cgm_s->vdcextent[1].i;
496 x1 = cgm_s->vdcextent[2].i;
497 y1 = cgm_s->vdcextent[3].i;
499 w = (x1 > x0) ? x1 - x0 : x0 - x1;
500 h = (y1 > y0) ? y1 - y0 : y0 - y1;
501 /* presently have max_size for size of the window */
502 /* need to override max_size if we have metric scaling set */
503 if (cgm_s->scalmode) { /* metric scaling */
504 /* there are supposed to be cgm_s->scalmode_f millimetres per vdc unit */
505 /* find the biggest direction */
506 maxWH = (w > h) ? w : h;
507 /* assuming square pixels, how many do we need ? */
508 max_size = (int) (xPxlMM * maxWH * cgm_s->scalmode_f);
511 if (h > w) { /* taller than wide */
512 xScale = max_size / h;
513 max_y = *ret_height = max_size;
514 max_x = *ret_width = max_size * w / h;
515 } else { /* wider than tall */
516 if (w == 0) w = 1; /* just in case */
517 xScale = max_size / w;
518 max_x = *ret_width = max_size;
519 max_y = *ret_height = max_size * h / w;
523 max_y = *ret_height = ScaleFactor * max_y;
524 max_x = *ret_width = ScaleFactor * max_x;
525 /*max_size *= ScaleFactor; */
526 xScale *= ScaleFactor;
530 /* set up for clipping */
531 myClipRect[0].x = myClipRect[0].y = myClipRect[3].x = myClipRect[1].y = 0;
532 myClipRect[1].x = myClipRect[2].x = max_x;
533 myClipRect[2].y = myClipRect[3].y = max_y;
534 clipRegion = XPolygonRegion(myClipRect, 4, EvenOddRule);
535 extRegion = XPolygonRegion(myClipRect, 4, EvenOddRule);
536 /* make the Pixmap */
537 *retPixmap = P = XCreatePixmap(display, win, *ret_width, *ret_height, depth);
538 /* fill it with the right background colour */
539 if (setBackColr) { /* set explicitly */
540 myStruct.foreground = getPixel(cgm_s, cgm_s->backcolr);
541 } else { /* use incoming GC */
542 mask = GCBackground | GCForeground;
543 XGetGCValues(display, lineGC, mask, &myStruct);
544 /* now put the background colr in the foreground and do the fill */
545 myStruct.foreground = myStruct.background;
547 myStruct.fill_style = FillSolid;
548 mask = GCFillStyle | GCForeground;
549 clearGC = XCreateGC(display, win, mask, &myStruct);
550 XFillRectangle(display, P, clearGC, 0, 0, *ret_width, *ret_height);
551 /* no text yet to set */
556 static epic(unsigned char *dat_ptr, struct cmd_info_s *cmd_ptr,
559 /* need to fill out the pixels array */
561 for (i=0; i < *ret_number; ++i) {
562 (*ret_colrs)[i] = my_colrs[i].pixel;
566 /* Metafile Descriptors */
567 /* Metafile Version */
568 static mfversion(dat_ptr, cmd_ptr, cgm_s)
569 unsigned char *dat_ptr;
570 struct cmd_info_s *cmd_ptr;
573 /* nothing for now */
576 /* Metafile Descriptor */
577 static mfdescrip(dat_ptr, cmd_ptr, cgm_s)
578 unsigned char *dat_ptr;
579 struct cmd_info_s *cmd_ptr;
582 /* nothing for now */
586 static vdctype(dat_ptr, cmd_ptr, cgm_s)
587 unsigned char *dat_ptr;
588 struct cmd_info_s *cmd_ptr;
591 /* 0=>integer, 1=>real */
593 cgm_s->vdctype = b_gsint(&dat_ptr, 16);
597 /* Integer Precision */
598 static intprec(dat_ptr, cmd_ptr, cgm_s)
599 unsigned char *dat_ptr;
600 struct cmd_info_s *cmd_ptr;
603 cgm_s->intprec = b_gsint(&dat_ptr, cgm_s->intprec);
607 static realprec(dat_ptr, cmd_ptr, cgm_s)
608 unsigned char *dat_ptr;
609 struct cmd_info_s *cmd_ptr;
612 cgm_s->realprec.fixed = b_gsint(&dat_ptr, cgm_s->intprec);
613 cgm_s->realprec.exp = b_gsint(&dat_ptr, cgm_s->intprec);
614 cgm_s->realprec.fract = b_gsint(&dat_ptr, cgm_s->intprec);
618 /* Index Precision */
619 static indexprec(dat_ptr, cmd_ptr, cgm_s)
620 unsigned char *dat_ptr;
621 struct cmd_info_s *cmd_ptr;
624 cgm_s->indexprec = b_gsint(&dat_ptr, cgm_s->intprec);
627 /* Colour Precision */
628 static colprec(dat_ptr, cmd_ptr, cgm_s)
629 unsigned char *dat_ptr;
630 struct cmd_info_s *cmd_ptr;
633 cgm_s->colprec = b_gsint(&dat_ptr, cgm_s->intprec);
636 /* Colour Index Precision */
637 static cindprec(dat_ptr, cmd_ptr, cgm_s)
638 unsigned char *dat_ptr;
639 struct cmd_info_s *cmd_ptr;
642 cgm_s->cindprec = b_gsint(&dat_ptr, cgm_s->intprec);
645 /* Maximum Colour Index */
646 static maxcind(dat_ptr, cmd_ptr, cgm_s)
647 unsigned char *dat_ptr;
648 struct cmd_info_s *cmd_ptr;
651 cgm_s->maxcind = b_guint(&dat_ptr, cgm_s->cindprec);
654 /* Colour Value Extent */
655 static cvextent(dat_ptr, cmd_ptr, cgm_s)
656 unsigned char *dat_ptr;
657 struct cmd_info_s *cmd_ptr;
662 cgm_s->cvextent[i] = b_guint(&dat_ptr, cgm_s->colprec);
663 /* don't allow problems */
664 for (i=0; i<3; ++i) {
665 if (cgm_s->cvextent[i+3] == cgm_s->cvextent[i]) {
666 cgm_s->cvextent[i+3] = 0;
667 cgm_s->cvextent[i+3] = 255;
672 /* Metafile Element List */
673 static mfellist(dat_ptr, cmd_ptr, cgm_s)
674 unsigned char *dat_ptr;
675 struct cmd_info_s *cmd_ptr;
679 cgm_s->mfellist_s = b_gsint(&dat_ptr, cgm_s->intprec);
680 if (!(cgm_s->mfellist = (int *) malloc(sizeof(int) * 2 *
681 cgm_s->mfellist_s))) {
682 burp(stderr, "couldn't get memory for MF ellement list\n");
685 for (i=0; i<2 * cgm_s->mfellist_s; ++i)
686 *(cgm_s->mfellist + i) = b_gsint(&dat_ptr, cgm_s->indexprec);
689 /* Metafile Defaults Replacement, a complex element */
690 static mfdefrep(dat_ptr, cmd_ptr, cgm_s)
691 unsigned char *dat_ptr;
692 struct cmd_info_s *cmd_ptr;
695 struct cmd_info_s new_cmd; /* for the new commands */
696 int i, ret = 1, new_len, b_to_move, data_left;
697 unsigned char *out_ptr, *end_ptr, *new_ptr, *start_ptr;
699 /* in this element, many other elements can be encoded in its */
700 /* parameter list. So we take them one at a time and hand them over */
701 /* to do_b_cmd. Thus do_b_cmd is being called recursively. */
702 if (!(out_ptr = (unsigned char *) malloc(cmd_ptr->p_len))) {
704 "couldn't make memory for metafile defaults replacement\n");
706 } /* made some memory for decoded commands */
707 /* now put the decoded commands into the new memory */
710 end_ptr = dat_ptr + cmd_ptr->p_len;
711 /* initialise the new command pointer */
712 new_cmd.no = cmd_ptr->no;
715 while (dat_ptr < end_ptr) { /* some input left */
716 start_ptr = dat_ptr; /* mark place */
717 /* now decipher the command header (lots of magic numbers !)*/
718 new_cmd.Class = (int) ((dat_ptr[0] >> 4) & 15);
719 new_cmd.element = (int) (((dat_ptr[0] << 3) & 127) |
720 ((dat_ptr[1] >> 5) & 7));
721 new_cmd.p_len = (int) (dat_ptr[1] & 31);
722 if ((new_cmd.Class != B_PDESCLASS) &&
723 (new_cmd.Class != B_CTRLCLASS) &&
724 (new_cmd.Class != B_ATTRCLASS)) {
725 burp(stderr, "illegal command in Metafile Defaults Replacement: ");
726 burp(stderr, "class = %d, element = %d\n", new_cmd.Class,
729 dat_ptr += 2; /* skip over header */
730 if (new_cmd.p_len < 31) { /* short form */
731 b_to_move = (new_cmd.p_len % 2) ? new_cmd.p_len + 1
733 for (i=0; i<b_to_move; ++i) *out_ptr++ = *dat_ptr++;
734 } else { /* long form */
736 new_cmd.p_len = 0; /* start fresh */
737 while (data_left) { /* some data still to get */
738 /* how much to come ? */
739 new_len = (int) (((dat_ptr[0] & 127) << 8) |
741 /* any more to come ? */
742 data_left = (dat_ptr[0] >> 7) & 1;
743 new_cmd.p_len += new_len;
745 b_to_move = (new_len % 2) ? new_len + 1 : new_len;
746 for (i=0; i<b_to_move; ++i) *out_ptr++ = *dat_ptr++;
749 /* now make the call */
750 if (!do_b_cmd(&new_cmd, new_ptr, cgm_s)) {
751 burp(stderr, "error in do_b_cmd while replacing defaults\n");
755 new_cmd.byte_no += (dat_ptr - start_ptr);
756 out_ptr = new_ptr; /* back to the beginning */
759 /* now tell the devices that we are finished replacing defaults */
762 /* Font List, store the data, but ignored for now */
763 static fontlist(dat_ptr, cmd_ptr, cgm_s)
764 unsigned char *dat_ptr;
765 struct cmd_info_s *cmd_ptr;
769 unsigned char *my_ptr = NULL;
772 for (i=0; (i<MAX_FONTS) && (my_ptr < (dat_ptr + cmd_ptr->p_len - 3));
774 if (!b_str(&my_ptr, cgm_s->fontlist + i)) {
775 burp(stderr, "couldn't get font name\n");
779 /* zero out the rest of the fonts */
780 for (; i>MAX_FONTS; ++i) cgm_s->fontlist[i] = NULL;
784 /* Character Set List, stored but ignored */
785 static charlist(dat_ptr, cmd_ptr, cgm_s)
786 unsigned char *dat_ptr;
787 struct cmd_info_s *cmd_ptr;
791 unsigned char *my_ptr = NULL;
794 for (i=0; (i<MAX_FONTS) && (my_ptr < (dat_ptr + cmd_ptr->p_len - 3));
796 cgm_s->chartype[i] = b_gsint(&my_ptr, 16);
797 if (!b_str(&my_ptr, cgm_s->charlist + i)) {
798 burp(stderr, "couldn't get character set list\n");
802 /* zero out the rest */
803 for (; i<MAX_FONTS; ++i) {
804 cgm_s->charlist[i] = NULL;
805 cgm_s->chartype[i] = 0;
809 /* Character Announcer */
810 static charannounce(dat_ptr, cmd_ptr, cgm_s)
811 unsigned char *dat_ptr;
812 struct cmd_info_s *cmd_ptr;
815 cgm_s->charannounce = b_gsint(&dat_ptr, 16);
818 /* Picture Descriptors */
820 static scalmode(dat_ptr, cmd_ptr, cgm_s)
821 unsigned char *dat_ptr;
822 struct cmd_info_s *cmd_ptr;
826 cgm_s->scalmode = b_gsint(&dat_ptr, 16);
827 if (cgm_s->scalmode) cgm_s->scalmode_f =
828 b_ieee(&dat_ptr, &(cgm_s->realprec)); /* strange default */
832 /* Colour Selection Mode */
833 static colselmode(dat_ptr, cmd_ptr, cgm_s)
834 unsigned char *dat_ptr;
835 struct cmd_info_s *cmd_ptr;
839 cgm_s->colselmode = b_gsint(&dat_ptr, 16);
842 /* Line Width Specification Mode */
843 static lwidspecmode(dat_ptr, cmd_ptr, cgm_s)
844 unsigned char *dat_ptr;
845 struct cmd_info_s *cmd_ptr;
848 cgm_s->lwidspecmode = b_gsint(&dat_ptr, 16);
851 /* Marker Size Specification Mode */
852 static marksizspecmode(dat_ptr, cmd_ptr, cgm_s)
853 unsigned char *dat_ptr;
854 struct cmd_info_s *cmd_ptr;
857 cgm_s->marksizspecmode = b_gsint(&dat_ptr, 16);
860 /* Edge Width Specification Mode */
861 static edwidspecmode(dat_ptr, cmd_ptr, cgm_s)
862 unsigned char *dat_ptr;
863 struct cmd_info_s *cmd_ptr;
866 cgm_s->edwidspecmode = b_gsint(&dat_ptr, 16);
870 static vdcextent(dat_ptr, cmd_ptr, cgm_s)
871 unsigned char *dat_ptr;
872 struct cmd_info_s *cmd_ptr;
877 switch (cgm_s->vdctype) {
878 case VDC_INT: for (i=0; i<4; ++i) cgm_s->vdcextent[i].i =
879 b_gsint(&dat_ptr, cgm_s->vdcintprec);
881 case VDC_REAL: for (i=0; i<4; ++i) cgm_s->vdcextent[i].r =
882 b_real(&dat_ptr, &(cgm_s->vdcrprec));
887 /* Background Colour */
888 static backcolr(dat_ptr, cmd_ptr, cgm_s)
889 unsigned char *dat_ptr;
890 struct cmd_info_s *cmd_ptr;
895 cgm_s->backcolr[i] = b_guint(&dat_ptr, cgm_s->colprec);
899 /* Control Elements */
900 /* VDC Integer Precision */
901 static vdcintprec(dat_ptr, cmd_ptr, cgm_s)
902 unsigned char *dat_ptr;
903 struct cmd_info_s *cmd_ptr;
906 cgm_s->vdcintprec = b_gsint(&dat_ptr, cgm_s->intprec);
909 /* VDC Real Precision */
910 static vdcrprec(dat_ptr, cmd_ptr, cgm_s)
911 unsigned char *dat_ptr;
912 struct cmd_info_s *cmd_ptr;
915 cgm_s->vdcrprec.fixed = b_gsint(&dat_ptr, cgm_s->intprec);
916 cgm_s->vdcrprec.exp = b_gsint(&dat_ptr, cgm_s->intprec);
917 cgm_s->vdcrprec.fract = b_gsint(&dat_ptr, cgm_s->intprec);
921 /* Auxiliary Colour */
922 static auxcolr(dat_ptr, cmd_ptr, cgm_s)
923 unsigned char *dat_ptr;
924 struct cmd_info_s *cmd_ptr;
928 switch(cgm_s->colselmode) {
929 case I_C_M: cgm_s->auxcolr[3] = b_guint(&dat_ptr, cgm_s->cindprec);
931 case D_C_M: for (i=0; i<3; ++i)
932 cgm_s->auxcolr[i] = b_gsint(&dat_ptr, cgm_s->colprec);
938 static transp(dat_ptr, cmd_ptr, cgm_s)
939 unsigned char *dat_ptr;
940 struct cmd_info_s *cmd_ptr;
943 cgm_s->transp = b_gsint(&dat_ptr, 16);
946 /* return a set of XPoints, and their number */
947 unsigned int getXPoints(unsigned char *dat_ptr,
948 struct cmd_info_s *cmd_ptr, cgm_s_type *cgm_s,
952 static XPoint *myPtr = NULL;
953 static int mySize = 0;
954 if (cgm_s->vdctype == VDC_INT) {
955 noPts = (8 * cmd_ptr->p_len) / (2 * cgm_s->vdcintprec);
956 } else if (cgm_s->vdctype == VDC_REAL) {
957 noPts = (8 * cmd_ptr->p_len) /
958 (2 * (cgm_s->vdcrprec.fract + cgm_s->vdcrprec.exp));
960 if (noPts < 1) return 0;
961 if (noPts > mySize) { /* need more points memory */
962 if (myPtr) free(myPtr); /* eliminate old memory */
963 myPtr = (XPoint *) malloc(sizeof(XPoint) * noPts);
967 for (i=0; i<noPts; ++i) {
968 myPtr[i].x = getX(&dat_ptr, cgm_s);
969 myPtr[i].y = max_y - getY(&dat_ptr, cgm_s);
971 /* fill out the return values */
975 /* Clipping Rectangle */
976 static cliprect(unsigned char *dat_ptr, struct cmd_info_s *cmd_ptr,
980 XPoint *myPtr = NULL, myClipRect[4];
981 noPts = getXPoints(dat_ptr, cmd_ptr, cgm_s, &myPtr);
982 if ((noPts < 2 ) || !myPtr) return 0;
983 /* have to get clipping rectangle set up correctly */
984 if (myPtr[0].x < myPtr[1].x) {
985 myClipRect[0].x = myClipRect[3].x = myPtr[0].x - 1;
986 myClipRect[1].x = myClipRect[2].x = myPtr[1].x - 1;
988 myClipRect[0].x = myClipRect[3].x = myPtr[1].x - 1;
989 myClipRect[1].x = myClipRect[2].x = myPtr[0].x - 1;
991 if (myPtr[0].y < myPtr[1].y) {
992 myClipRect[0].y = myClipRect[1].y = myPtr[0].y - 1;
993 myClipRect[2].y = myClipRect[3].y = myPtr[1].y - 1;
995 myClipRect[0].y = myClipRect[1].y = myPtr[1].y - 1;
996 myClipRect[2].y = myClipRect[3].y = myPtr[0].y - 1;
998 clipRegion = XPolygonRegion(myClipRect, 4, EvenOddRule);
1000 /* if clipping is on, set the clipping area */
1001 if (cgm_s->clipindic) {
1002 XSetRegion(display, lineGC, clipRegion);
1003 XSetRegion(display, textGC, clipRegion);
1004 XSetRegion(display, fillGC, clipRegion);
1005 XSetRegion(display, edgeGC, clipRegion);
1006 XSetRegion(display, cellGC, clipRegion);
1007 XSetRegion(display, markGC, clipRegion);
1012 /* Clipping Indicator */
1013 static clipindic(unsigned char *dat_ptr, struct cmd_info_s *cmd_ptr,
1017 cgm_s->clipindic = b_gsint(&dat_ptr, 16);
1018 if (cgm_s->clipindic) {
1019 XSetRegion(display, lineGC, clipRegion);
1020 XSetRegion(display, textGC, clipRegion);
1021 XSetRegion(display, fillGC, clipRegion);
1022 XSetRegion(display, edgeGC, clipRegion);
1023 XSetRegion(display, cellGC, clipRegion);
1024 XSetRegion(display, markGC, clipRegion);
1026 XSetRegion(display, lineGC, extRegion);
1027 XSetRegion(display, textGC, extRegion);
1028 XSetRegion(display, fillGC, extRegion);
1029 XSetRegion(display, edgeGC, extRegion);
1030 XSetRegion(display, cellGC, extRegion);
1031 XSetRegion(display, markGC, extRegion);
1035 /* Graphical primitives */
1036 unsigned int getXSegments(unsigned char *dat_ptr,
1037 struct cmd_info_s *cmd_ptr, cgm_s_type *cgm_s,
1041 XSegment *myPtr = NULL;
1042 /* figure out how many segments we have */
1043 if (cgm_s->vdctype == VDC_INT) {
1044 noSegments = (8 * cmd_ptr->p_len) / (4 * cgm_s->vdcintprec);
1045 } else if (cgm_s->vdctype == VDC_REAL) {
1046 noSegments = (8 * cmd_ptr->p_len) /
1047 (4 *(cgm_s->vdcrprec.fract + cgm_s->vdcrprec.exp));
1049 if (noSegments < 1) return 0;
1050 /* make memory for our segments */
1051 myPtr = (XSegment *) malloc(sizeof(XSegment) * noSegments);
1052 /* and fill it out */
1053 for (i=0; i<noSegments; ++i) {
1054 myPtr[i].x1 = getX(&dat_ptr, cgm_s);
1055 myPtr[i].y1 = max_y - getY(&dat_ptr, cgm_s);
1056 myPtr[i].x2 = getX(&dat_ptr, cgm_s);
1057 myPtr[i].y2 = max_y - getY(&dat_ptr, cgm_s);
1059 /* return our values */
1064 static polyline(dat_ptr, cmd_ptr, cgm_s)
1065 unsigned char *dat_ptr;
1066 struct cmd_info_s *cmd_ptr;
1070 XPoint *myPtr = NULL;
1071 noPts = getXPoints(dat_ptr, cmd_ptr, cgm_s, &myPtr);
1072 if ((noPts < 1) || !myPtr) return 0;
1073 XDrawLines(display, P, lineGC, myPtr, noPts, CoordModeOrigin);
1076 /* Disjoint Polyline, on/off segments */
1077 static dispoly(dat_ptr, cmd_ptr, cgm_s)
1078 unsigned char *dat_ptr;
1079 struct cmd_info_s *cmd_ptr;
1083 XSegment *myPtr = NULL;
1085 noSegments = getXSegments(dat_ptr, cmd_ptr, cgm_s, &myPtr);
1086 if ((noSegments < 1) || !myPtr) return 0;
1087 XDrawSegments(display, P, lineGC, myPtr, noSegments);
1088 if (myPtr) free(myPtr);
1092 static polymarker(dat_ptr, cmd_ptr, cgm_s)
1093 unsigned char *dat_ptr;
1094 struct cmd_info_s *cmd_ptr;
1097 int noPts, i, x, y, size, asize;
1098 /* figure out the number of points */
1099 if (cgm_s->vdctype == VDC_INT) {
1100 noPts = (8 * cmd_ptr->p_len) / (2 * cgm_s->vdcintprec);
1101 } else if (cgm_s->vdctype == VDC_REAL) {
1102 noPts = (8 * cmd_ptr->p_len) /
1103 (2 * (cgm_s->vdcrprec.fract + cgm_s->vdcrprec.exp));
1105 if (noPts < 1) return 0;
1107 /* go thru the points, drawing the markers */
1108 size = cgm_s->msize.i / 2;
1109 if (size < 1) size = 1; /* minimum size */
1110 asize = 0.7 * size; /* asterisk/cross size */
1111 if (asize < 1) asize = 1; /* minimum size */
1113 for (i=0; i<noPts; ++i) {
1114 x = getX(&dat_ptr, cgm_s);
1115 y = max_y - getY(&dat_ptr, cgm_s);
1116 switch(cgm_s->mtype) { /* what type of marker */
1118 XDrawPoint(display, P, markGC, x, y);
1121 XDrawLine(display, P, markGC, x - size, y, x + size, y);
1122 XDrawLine(display, P, markGC, x, y - size, x, y + size);
1124 case 4: /* circle */
1125 XDrawArc(display, P, markGC, x - size, y - size,
1126 2 * size, 2 * size, 0, 360 * 64);
1128 case 3: /* asterisk, use fallthru */
1129 XDrawLine(display, P, markGC, x - size, y, x + size, y);
1130 XDrawLine(display, P, markGC, x, y - size, x, y + size);
1132 XDrawLine(display, P, markGC, x - asize, y - asize, x + asize, y + asize);
1133 XDrawLine(display, P, markGC, x - asize, y + asize, x + asize, y - asize);
1135 default: /* do nothing */
1142 /* actually draw some text */
1143 void draw_cgm_text(Display*, Drawable, GC, cgm_s_type*, int, int, int, int,
1145 /* got a final flag, so actually draw text */
1146 void doText(cgm_s_type *cgm_s)
1148 partialText *myPtr, *tmpPtr;
1150 draw_cgm_text(display, P, textGC, cgm_s, textX, textY, textW, textH, textPtr);
1151 /* clean up memory */
1152 for (myPtr = textPtr; myPtr; myPtr = tmpPtr) {
1153 tmpPtr = myPtr->next;
1158 textX = textY = textW = textH = 0;
1161 static text(dat_ptr, cmd_ptr, cgm_s)
1162 unsigned char *dat_ptr;
1163 struct cmd_info_s *cmd_ptr;
1167 unsigned char *out_ptr;
1168 partialText *newPtr, *myPtr;
1169 /* clean up in case we didn't get a final flag (e.g., old NCAR) */
1170 if (textPtr) doText(cgm_s);
1172 /* first get the point for the string */
1173 textX = getX(&dat_ptr, cgm_s);
1174 textY = max_y - getY(&dat_ptr, cgm_s);
1175 /* make some memory */
1176 newPtr = (partialText *) malloc(sizeof(partialText));
1177 newPtr->text = NULL;
1178 newPtr->next = NULL;
1179 newPtr->tcolr = cgm_s->tPixel;
1180 newPtr->cexpfac = cgm_s->cexpfac;
1181 newPtr->cspace = cgm_s->cspace;
1182 newPtr->cheight = cgm_s->cheight.i;
1183 /* now the final/not final flag */
1184 final_flag = b_gsint(&dat_ptr, 16);
1187 /* now the string */
1188 if (!b_str(&dat_ptr, &(newPtr->text))) {
1189 burp(stderr, "couldn't get text string\n");
1192 /* append it to our pointer */
1194 for (myPtr = textPtr; myPtr->next; myPtr = myPtr->next);
1195 myPtr->next = newPtr;
1196 } else textPtr = newPtr;
1197 /* any more to come ? */
1198 if (final_flag) doText(cgm_s);
1201 /* Restricted Text */
1202 static restext(dat_ptr, cmd_ptr, cgm_s)
1203 unsigned char *dat_ptr;
1204 struct cmd_info_s *cmd_ptr;
1208 partialText *newPtr, *myPtr;
1210 /* first the width and height */
1211 textW = getVDC(&dat_ptr, cgm_s);
1212 textH = getVDC(&dat_ptr, cgm_s);
1213 /* now get the point for the string */
1214 textX = getX(&dat_ptr, cgm_s);
1215 textY = max_y - getY(&dat_ptr, cgm_s);
1216 /* now the final/not final flag */
1217 final_flag = b_gsint(&dat_ptr, 16);
1218 /* make some memory */
1219 newPtr = (partialText *) malloc(sizeof(partialText));
1220 newPtr->text = NULL;
1221 newPtr->next = NULL;
1222 newPtr->tcolr = cgm_s->tPixel;
1223 newPtr->cexpfac = cgm_s->cexpfac;
1224 newPtr->cspace = cgm_s->cspace;
1225 newPtr->cheight = cgm_s->cheight.i;
1227 /* now the string */
1228 if (!b_str(&dat_ptr, &(newPtr->text))) {
1229 burp(stderr, "couldn't get text string\n");
1232 /* append it to our pointer */
1234 for (myPtr = textPtr; myPtr->next; myPtr = myPtr->next);
1235 myPtr->next = newPtr;
1236 } else textPtr = newPtr;
1237 /* any more to come ? */
1238 if (final_flag) doText(cgm_s);
1242 static apptext(dat_ptr, cmd_ptr, cgm_s)
1243 unsigned char *dat_ptr;
1244 struct cmd_info_s *cmd_ptr;
1247 int i, ret, final_flag;
1248 partialText *newPtr, *myPtr;
1249 if (!textPtr) return; /* can't append if there's nothing started ! */
1251 /* first the final/not final flag */
1252 final_flag = b_gsint(&dat_ptr, 16);
1253 /* make some memory */
1254 newPtr = (partialText *) malloc(sizeof(partialText));
1255 newPtr->text = NULL;
1256 newPtr->next = NULL;
1257 newPtr->tcolr = cgm_s->tPixel;
1258 newPtr->cexpfac = cgm_s->cexpfac;
1259 newPtr->cspace = cgm_s->cspace;
1260 newPtr->cheight = cgm_s->cheight.i;
1262 /* now the string */
1263 if (!b_str(&dat_ptr, &(newPtr->text))) {
1264 burp(stderr, "couldn't get text string\n");
1267 /* append it to our pointer */
1268 /* find last partial text */
1269 for (myPtr = textPtr; myPtr->next; myPtr = myPtr->next);
1270 myPtr->next = newPtr;
1274 static polygon(dat_ptr, cmd_ptr, cgm_s)
1275 unsigned char *dat_ptr;
1276 struct cmd_info_s *cmd_ptr;
1280 XPoint *myPtr = NULL;
1281 noPts = getXPoints(dat_ptr, cmd_ptr, cgm_s, &myPtr);
1282 if ((noPts < 2) || !myPtr) return 0;
1283 /* fill the polygon */
1284 XFillPolygon(display, P, fillGC, myPtr, noPts, Complex, CoordModeOrigin);
1285 /* draw the edge ? */
1286 if (cgm_s->evis) { /* not necessary, but here for optimization */
1287 XDrawLines(display, P, edgeGC, myPtr, noPts, CoordModeOrigin);
1288 /* close the edge */
1289 XDrawLine(display, P, edgeGC, myPtr[0].x, myPtr[0].y,
1290 myPtr[noPts - 1].x, myPtr[noPts - 1].y);
1295 static polyset(dat_ptr, cmd_ptr, cgm_s)
1296 unsigned char *dat_ptr;
1297 struct cmd_info_s *cmd_ptr;
1300 int i, j, noPts, *vPtr, lastFill;
1303 /* get the number of pts */
1304 switch (cgm_s->vdctype) {
1305 case VDC_INT: noPts = (8 * cmd_ptr->p_len) / (2 * cgm_s->vdcintprec + 16);
1307 case VDC_REAL: noPts = (8 * cmd_ptr->p_len) /
1308 (2 * (cgm_s->vdcrprec.fract + cgm_s->vdcrprec.exp) + 16);
1310 default: return 0; /* shouldn't happen */
1312 /* now make the memory */
1313 myPtr = (XPoint *) malloc(sizeof(XPoint) * noPts);
1314 vPtr = (int *) malloc(sizeof(int) * noPts);
1315 /* check we got it */
1316 if ((noPts < 2) || !myPtr || !vPtr) return 0;
1317 /* and fill it out */
1318 for (i=0; i<noPts; ++i) {
1319 myPtr[i].x = getX(&dat_ptr, cgm_s);
1320 myPtr[i].y = max_y - getY(&dat_ptr, cgm_s);
1321 vPtr[i] = b_gsint(&dat_ptr, 16); /* the flag */
1323 /* draw the polygon set */
1324 lastFill = 0; /* no closure pts yet */
1325 for (i=0; i<noPts; ++i) {
1326 /* check the edge out flag */
1328 case 0: /* invisible edge */
1330 case 1: /* visible edge */
1331 if (i < (noPts - 1))
1332 XDrawLine(display, P, edgeGC, myPtr[i].x, myPtr[i].y,
1333 myPtr[i + 1].x, myPtr[i + 1].y);
1335 case 2: /* close, invisible edge */
1336 if (i > (lastFill + 2))
1337 XFillPolygon(display, P, fillGC, myPtr + lastFill, i - lastFill + 1,
1338 Complex, CoordModeOrigin);
1341 case 3: /* close, visible edge */
1342 if (i > (lastFill + 2))
1343 XFillPolygon(display, P, fillGC, myPtr + lastFill, i - lastFill + 1,
1344 Complex, CoordModeOrigin);
1346 XDrawLine(display, P, edgeGC, myPtr[i].x, myPtr[i].y,
1347 myPtr[lastFill].x, myPtr[lastFill].y);
1350 default: /* do nothing */
1354 /* free the memory */
1360 /* need specific functions to deal with cell array colours */
1361 /* macro to get an unsigned integer value from a cell array */
1363 #define UINT unsigned int
1364 #define AINT(ptr, prec, out, done) switch(prec) {\
1365 case 32: out = (((UINT)ptr[0]) << 24) + (((UINT)ptr[1]) << 16)\
1366 + (((UINT)ptr[2]) << 8) + ptr[3]; ptr += 4; break;\
1367 case 24: out = (((UINT)ptr[0]) << 16)\
1368 + (((UINT)ptr[1]) << 8) + ptr[2]; ptr += 3; break;\
1369 case 16: out = (((UINT)ptr[0]) << 8) + ptr[1]; ptr += 2; break;\
1370 case 8: out = *ptr++; break;\
1371 case 4: if(!(temp=(((done + 1) * prec) % 8))) out = *ptr++ & 15; \
1372 else out = (*ptr >> temp) & 15; break;\
1373 case 2: if(!(temp=(((done + 1) * prec) % 8))) out = *ptr++ & 3; \
1374 else out = (*ptr >> (8 - temp)) & 3; break;\
1375 case 1: if(!(temp=(((done + 1) * prec) % 8))) out = *ptr++ & 1; \
1376 else out = (*ptr >> (8 - temp)) & 1; break;}
1377 /* get a packed list */
1378 static void getListPixels(unsigned char *datPtr, cgm_s_type *cgm_s,
1379 int nx, int ny, int prec, Pixel *retPtr)
1381 unsigned char *startPtr;
1382 int rowSize, i, j, k, maxCol, done, iCol, iColrs[3];
1383 /* may be in direct colour mode or indexed colour mode */
1384 switch (cgm_s->colselmode) {
1385 case D_C_M: /* direct colour */
1386 rowSize = (nx * 3 * prec + 7) / 8; /* no of bytes per row */
1387 if (rowSize % 2) ++rowSize; /* round up */
1388 for (i = 0; i < ny; ++i) {
1391 for (j = 0; j < nx; ++j) {
1392 for (k=0; k<3; ++k) {
1393 AINT(startPtr, prec, iColrs[k], done);
1396 *retPtr++ = getPixel(cgm_s, iColrs);
1402 rowSize = (nx * prec + 7) / 8; /* no of bytes per row */
1403 if (rowSize % 2) ++rowSize; /* round up */
1404 for (i = 0; i < ny; ++i) {
1407 for (j = 0; j < nx; ++j) {
1408 AINT(startPtr, prec, iCol, done);
1410 *retPtr++ = getIPixel(iCol);
1415 default: /* nothing */ break;
1418 /* get a run-length encoded list */
1419 static void getRLPixels(unsigned char *dat_ptr, cgm_s_type *cgm_s,
1420 int nx, int ny, int prec, Pixel *retPtr)
1422 static unsigned char bitMask[8] = {255, 127, 63, 31, 15, 7, 3, 1};
1423 unsigned char *rowPtr;
1425 int i, j, k, done, iCol, iColrs[3], bitOffset,count;
1428 for (i=0; i<ny; ++i) { /* loop through the rows */
1429 done = j = bitOffset = 0;
1431 while (j < nx) { /* still some left in this row */
1432 /* pick up the count of repeated colours, may span bytes */
1433 count = (bitOffset) ?
1434 (dat_ptr[0] & bitMask[bitOffset] << (bitOffset + 8)) +
1435 (dat_ptr[1] << bitOffset) +
1436 (dat_ptr[2] >> (8 - bitOffset)) :
1437 (dat_ptr[0] << 8) + dat_ptr[1];
1438 if ((j + count) > nx) return; /* too many pixels */
1441 /* now get the next colour and replicate it count times */
1442 switch (cgm_s->colselmode) {
1443 case D_C_M: /* direct colour */
1444 /* get the r, g, b values */
1445 for (k=0; k<3; ++k) {
1446 AINT(dat_ptr, prec, iColrs[k], done);
1449 myPixel = getPixel(cgm_s, iColrs);
1450 for (k=0; k<count; ++k) retPtr[i * nx + j + k] = myPixel;
1455 AINT(dat_ptr, prec, iCol, done);
1456 tP = getIPixel(iCol);
1457 /* and replicate it */
1458 for (k=0; k<count; ++k) {
1459 retPtr[i * nx + j + k] = tP
1465 default: /* nothing */ break;
1466 } /* end of switch */
1467 bitOffset = (done * prec) % 8;
1469 /* may have to skip to end of row */
1470 if (bitOffset) ++dat_ptr; /* incomplete byte */
1471 if (((size_t) dat_ptr - (size_t) rowPtr) % 2) ++dat_ptr; /* need round up */
1472 } /* end of cell array */
1476 /* build a pixel array, (x, y) = (x + y * nx) storage */
1477 static Pixel *getPixels(unsigned char *dat_ptr, cgm_s_type *cgm_s,
1478 int nx, int ny, int localPrec, int repMode)
1482 retPtr = (Pixel *) malloc(nx * ny * sizeof(Pixel));
1483 if (!retPtr) return NULL;
1484 /* get the local colour precision */
1485 if (!localPrec) localPrec =
1486 (cgm_s->colselmode) ? cgm_s->colprec :cgm_s->cindprec;
1488 /* get the pixels for each case */
1489 if (repMode) { /* packed list */
1490 getListPixels(dat_ptr, cgm_s, nx, ny, localPrec, retPtr);
1491 } else { /* run-length encoded */
1492 getRLPixels(dat_ptr, cgm_s, nx, ny, localPrec, retPtr);
1496 /* actually get the cellarray command */
1497 static cellarray(dat_ptr, cmd_ptr, cgm_s)
1498 unsigned char *dat_ptr;
1499 struct cmd_info_s *cmd_ptr;
1502 int i, j, x[3], y[3], nx, ny, local_prec, rep_mode, xSize, ySize;
1503 int Qx, Qy, Rx, Ry, det, xMin, xMax, yMin, yMax, newX, newY, ix, iy,
1505 double ddet, axx, axy, ayx, ayy;
1509 /* first get the corner co-ordinates */
1510 for (i=0; i<3; ++i) {
1511 x[i] = getX(&dat_ptr, cgm_s);
1512 y[i] = getY(&dat_ptr, cgm_s);
1514 /* now the bit array specifics */
1515 nx = b_gsint(&dat_ptr, cgm_s->intprec);
1516 ny = b_gsint(&dat_ptr, cgm_s->intprec);
1517 local_prec = b_gsint(&dat_ptr, cgm_s->intprec);
1518 rep_mode = b_gsint(&dat_ptr, 16);
1519 /* get the expanded cell array */
1520 if (!(myPixels = getPixels(dat_ptr, cgm_s, nx, ny, local_prec, rep_mode)))
1523 /* make sure we're not co-linear */
1528 /* figure out the determinant */
1529 if (!(det = Rx * Qy - Ry * Qx)) return 1; /* co-linear */
1530 ddet = (double) det; /* explicit cast for Ultrix bug */
1531 /* figure out the transformation matrix */
1532 /* need nx+1, ny+1, because o integer arithmetic expanding range */
1533 axx = (nx + 1) * (Qy - Ry) / ddet;
1534 axy = (nx + 1) * (Rx - Qx) / ddet;
1535 ayx = - (ny + 1) * Ry / ddet;
1536 ayy = (ny + 1) * Rx / ddet;
1537 /* figure out the 4th pt and use it as beginning of bounding rectangle */
1538 xMin = xMax = x[0] + x[1] - x[2];
1539 yMin = yMax = y[0] + y[1] - y[2];
1540 for (i=0; i<3; ++i) {
1541 if (x[i] < xMin) xMin = x[i];
1542 if (x[i] > xMax) xMax = x[i];
1543 if (y[i] < yMin) yMin = y[i];
1544 if (y[i] > yMax) yMax = y[i];
1546 /* make sure we're inside the pixmap */
1547 if (xMin < 0) xMin = 0;
1548 if (yMin < 0) yMin = 0;
1549 if (xMax > max_x) xMax = max_x;
1550 if (yMax > max_y) yMax = max_y;
1552 xSize = xMax - xMin;
1553 ySize = yMax - yMin;
1554 myImage = XGetImage(display, P, xMin, max_y - yMax, xSize, ySize,
1556 /* now go thru the screen pixels */
1557 for (iy=1; iy <= ySize; ++iy) {
1558 /* get the real Image y coord, relative to (x0, y0) */
1559 oldY = iy - (y[0] - yMin);
1560 for (ix=0; ix<xSize; ++ix) {
1561 /* get the real Image x coord, relative to (x0, y0) */
1562 oldX = ix - (x[0] - xMin);
1563 /* see if we have data for the transformed point */
1564 newX = (int) (axx * oldX + axy * oldY - 0.99);
1565 newY = (int) (ayx * oldX + ayy * oldY - 0.99);
1566 if ((newX >= 0) && (newX < nx) && (newY >= 0) && (newY < ny)) {
1567 XPutPixel(myImage, ix, ySize - iy, myPixels[newX + newY * nx]);
1571 /* copy the XImage back */
1573 XPutImage(display, P, cellGC, myImage, 0, 0, xMin, max_y - yMax,
1575 /* return the memory */
1576 XDestroyImage(myImage);
1581 static rectangle(dat_ptr, cmd_ptr, cgm_s)
1582 unsigned char *dat_ptr;
1583 struct cmd_info_s *cmd_ptr;
1586 int i, xPts[2], yPts[2], x, y, old_style;
1589 /* just 2 pts to grab */
1590 for (i=0; i<2; ++i) {
1591 xPts[i] = getX(&dat_ptr, cgm_s);
1592 yPts[i] = max_y - getY(&dat_ptr, cgm_s);
1594 /* now arrange them to the satisfaction of XLib */
1595 if (xPts[0] < xPts[1]) {
1596 w = xPts[1] - xPts[0];
1599 w = xPts[0] - xPts[1];
1602 if (yPts[0] < yPts[1]) {
1603 h = yPts[1] - yPts[0];
1606 h = yPts[0] - yPts[1];
1609 /* and fill the rectangle */
1610 XFillRectangle(display, P, fillGC, x, y, w, h);
1611 /* and the edge, have to make sure corners look OK */
1612 /* store the old value of cap style */
1613 XGetGCValues(display, edgeGC, GCCapStyle, &myStruct);
1614 old_style = myStruct.cap_style;
1615 myStruct.cap_style = CapProjecting;
1616 XChangeGC(display, edgeGC, GCCapStyle, &myStruct);
1617 /* draw the lines */
1618 XDrawLine(display, P, edgeGC, x, y, x + w, y);
1619 XDrawLine(display, P, edgeGC, x + w, y, x + w, y + h);
1620 XDrawLine(display, P, edgeGC, x + w, y + h, x, y + h);
1621 XDrawLine(display, P, edgeGC, x, y + h, x, y);
1622 /* restore the old value */
1623 myStruct.cap_style = old_style;
1624 XChangeGC(display, edgeGC, GCCapStyle, &myStruct);
1628 static circle(dat_ptr, cmd_ptr, cgm_s)
1629 unsigned char *dat_ptr;
1630 struct cmd_info_s *cmd_ptr;
1634 /* get the center position and radius */
1635 x = getX(&dat_ptr, cgm_s);
1636 y = max_y - getY(&dat_ptr, cgm_s);
1637 r = getVDC(&dat_ptr, cgm_s);
1638 if (r < 0) return 0;
1639 /* fill the circle */
1640 XSetArcMode(display, fillGC, ArcChord); /* for safety */
1641 XFillArc(display, P, fillGC, x - r, y - r, 2 * r, 2 * r, 0, 360 * 64);
1643 XDrawArc(display, P, edgeGC, x - r, y - r, 2 * r, 2 * r, 0, 360 * 64);
1646 /* get radius, center and angles from 3 pts */
1647 static int getArc(float inX[3], float inY[3], int *outXC, int *outYC,
1648 double *outTheta0, double *outDtheta)
1651 double theta[3], dtheta;
1652 float m1, m2, x[5], y[5];
1653 /* for convenience */
1654 for (i=0; i<3; ++i) {
1658 /* get the midpoints between the pts */
1659 for (i=0; i<2; ++i) {
1660 x[i+3] = (x[i] + x[i+1]) / 2;
1661 y[i+3] = (y[i] + y[i+1]) / 2;
1664 the perpendiculars to the 2 lines thru their midpts will meet at the center
1665 thus we have 4 eqns for 4 unknowns:
1666 xc = x3 + a * (y1 - y0)
1667 yc = y3 - a * (x1 - x0)
1668 xc = x4 + b * (y2 - y1)
1669 yc = y4 - b * (x2 - x1)
1670 we can eliminate a and b to find xc and yc
1671 (xc - x3) / (y1 - y0) = - (yc - y3) / (x1 - x0)
1672 (xc - x4) / (y2 - y1) = - (yc - y4) / (x2 - x1)
1675 if (y[1] == y[0]) xc = x[3];
1676 else if (y[2] == y[1]) xc = x[4];
1677 else { /* divisors are non-zero, get radii slopes */
1678 m1 = -(x[1] - x[0]) / (y[1] - y[0]);
1679 m2 = -(x[2] - x[1]) / (y[2] - y[1]);
1680 /* (xc - x3) * m1 + y3 = (xc - x4) * m2 + y4, i.e.,
1681 xc * (m1 - m2) = m1 * x3 - m2 * x4 + y4 - y3 */
1682 xc = (m1 * x[3] - m2 * x[4] + y[4] - y[3]) / (m1 - m2);
1684 if (xc == x[3]) yc = y[3];
1685 else yc = y[3] + m1 * (xc - x[3]);
1686 /* have the center, now get the radius */
1687 #define SQ(x) ((double) ((x) * (x)))
1688 r = sqrt(SQ(x[0] - xc) + SQ(y[0] - yc));
1690 /* now get the angles */
1692 for (i=0; i<3; ++i) {
1693 theta[i] = atan2(y[i] - yc, x[i] - xc);
1694 if (theta[i] < 0) theta[i] += 2 * pi; /* for XLib coords */
1696 /* figure out the delta theta angle */
1697 dtheta = theta[2] - theta[0];
1698 if (theta[1] > theta[0]) { /* need to go clockwise */
1699 if (dtheta < 0) dtheta += 2 * pi;
1700 } else { /* need to go anticlockwise */
1701 if (dtheta > 0) dtheta -= 2 * pi;
1705 *outTheta0 = theta[0];
1706 *outDtheta = dtheta;
1709 /* Circular Arc, set by 3 points */
1710 static circ3(dat_ptr, cmd_ptr, cgm_s)
1711 unsigned char *dat_ptr;
1712 struct cmd_info_s *cmd_ptr;
1716 double theta0, dtheta;
1717 float det1, x[3], y[3];
1719 /* just 3 pts to grab */
1720 for (i=0; i<3; ++i) {
1721 x[i] = getX(&dat_ptr, cgm_s);
1722 y[i] = getY(&dat_ptr, cgm_s);
1724 /* get the determinant, find out if they're co-linear */
1725 det1 = (x[2] - x[0]) * (y[1] - y[0])
1726 - (x[1] - x[0]) * (y[2] - y[0]);
1727 if (det1 == 0) { /* co-linear, just connect points */
1728 XDrawLine(display, P, lineGC, x[0], max_y - y[0], x[1], max_y - y[1]);
1729 XDrawLine(display, P, lineGC, x[1], max_y - y[1], x[2], max_y - y[2]);
1732 /* now need to figure out arc in appropriate coordinates */
1733 r = getArc(x, y, &xc, &yc, &theta0, &dtheta);
1734 /* convert to left handed XLib coords */
1736 if (r == 0) return 0;
1737 XDrawArc(display, P, lineGC, xc - r, yc - r, 2 * r, 2 * r,
1738 (int) ((theta0 / pi) * 180 * 64),
1739 (int) ((dtheta / pi) * 180 * 64));
1742 /* Circular Arc, set by 3 points, close */
1743 static circ3close(dat_ptr, cmd_ptr, cgm_s)
1744 unsigned char *dat_ptr;
1745 struct cmd_info_s *cmd_ptr;
1748 int xc, yc, r, i, close_type, x0, y0, x2, y2;
1749 float det1, x[3], y[3]; /* use floats since we must manipulate them */
1750 double theta0, dtheta;
1751 /* just 3 pts plus an eint to grab */
1752 for (i=0; i<3; ++i) {
1753 x[i] = getX(&dat_ptr, cgm_s);
1754 y[i] = getY(&dat_ptr, cgm_s);
1756 close_type = b_gsint(&dat_ptr, 16); /* how do we close the arc ? */
1757 /* get the determinant, find out if they're co-linear */
1758 det1 = (x[2] - x[0]) * (y[1] - y[0])
1759 - (x[1] - x[0]) * (y[2] - y[0]);
1760 if (det1 == 0) { /* co-linear, just connect points */
1761 XDrawLine(display, P, lineGC, x[0], max_y - y[0], x[1], max_y - y[1]);
1762 XDrawLine(display, P, lineGC, x[1], max_y - y[1], x[2], max_y - y[2]);
1765 /* now need to figure out arc in appropriate coordinates */
1766 r = getArc(x, y, &xc, &yc, &theta0, &dtheta);
1767 if (r == 0) return 0;
1768 /* convert to left handed XLib coords */
1770 /* need the ends, use angles so things match up */
1771 x0 = (int) (xc + r * cos(theta0));
1772 y0 = (int) (yc - r * sin(theta0));
1773 x2 = (int) (xc + r * cos(theta0 + dtheta));
1774 y2 = (int) (yc - r * sin(theta0 + dtheta));
1775 /* fill the arc, use the correct type of close */
1776 if (close_type) XSetArcMode(display, fillGC, ArcChord);
1777 else XSetArcMode(display, fillGC, ArcPieSlice);
1778 /* now the actual fill */
1779 XFillArc(display, P, fillGC, xc - r, yc - r, 2 * r, 2 * r,
1780 (int) ((theta0 / pi) * 180 * 64),
1781 (int) ((dtheta / pi) * 180 * 64));
1782 /* and draw the edge */
1783 XDrawArc(display, P, edgeGC, xc - r, yc - r, 2 * r, 2 * r,
1784 (int) ((theta0 / pi) * 180 * 64),
1785 (int) ((dtheta / pi) * 180 * 64));
1787 if (close_type) { /* chord closure */
1788 XDrawLine(display, P, edgeGC, x0, y0, x2, y2);
1789 } else { /* pie closure */
1790 XDrawLine(display, P, edgeGC, x0, y0, xc, yc);
1791 XDrawLine(display, P, edgeGC, xc, yc, x2, y2);
1795 /* return angles from directions in radians */
1796 static double getAngles(int xc, int yc, float dxy[4], double *outTheta0)
1799 double theta[2], dtheta;
1800 for (i=0; i<2; ++i) {
1801 theta[i] = atan2(dxy[2 * i + 1], dxy[2 * i]);
1802 if (theta[i] < 0) theta[i] += 2 * pi; /* for XLib coords */
1804 dtheta = theta[1] - theta[0];
1805 /* need to go in the positive direction */
1806 if (dtheta < 0) dtheta += 2 * pi;
1807 *outTheta0 = theta[0];
1810 /* Circular Arc, set by center */
1811 static circcentre(dat_ptr, cmd_ptr, cgm_s)
1812 unsigned char *dat_ptr;
1813 struct cmd_info_s *cmd_ptr;
1817 double theta0, dtheta;
1819 /* get the center */
1820 xc = getX(&dat_ptr, cgm_s);
1821 yc = getY(&dat_ptr, cgm_s);
1822 /* get the tangent vectors */
1823 for (i=0; i<4; ++i) dxy[i] = getVDC(&dat_ptr, cgm_s);
1824 /* get the radius */
1825 r = getVDC(&dat_ptr, cgm_s);
1826 if (r == 0) return 1;
1827 /* get the angles */
1828 dtheta = getAngles(xc, yc, dxy, &theta0);
1829 if (dtheta == 0) return 1;
1830 /* convert to left handed XLib coords */
1832 XDrawArc(display, P, lineGC, xc - r, yc - r, 2 * r, 2 * r,
1833 (int) ((theta0 / pi) * 180 * 64),
1834 (int) ((dtheta / pi) * 180 * 64));
1838 /* Circular Arc, set by center, close */
1839 static circcclose(dat_ptr, cmd_ptr, cgm_s)
1840 unsigned char *dat_ptr;
1841 struct cmd_info_s *cmd_ptr;
1844 int i, xc, yc, r, close_type, x0, y0, x1, y1;
1845 double theta0, dtheta;
1848 /* get the center */
1849 xc = getX(&dat_ptr, cgm_s);
1850 yc = getY(&dat_ptr, cgm_s);
1851 /* get the tangent vectors */
1852 for (i=0; i<4; ++i) dxy[i] = getVDC(&dat_ptr, cgm_s);
1853 /* get the radius */
1854 r = getVDC(&dat_ptr, cgm_s);
1855 /* get the close type */
1856 close_type = b_gsint(&dat_ptr, 16);
1857 /* get the angles */
1858 dtheta = getAngles(xc, yc, dxy, &theta0);
1859 if (dtheta == 0) return 1;
1860 /* convert to left handed XLib coords */
1862 /* need to get the ends */
1863 x0 = xc + r * cos(theta0);
1864 y0 = yc - r * sin(theta0);
1865 x1 = xc + r * cos(theta0 + dtheta);
1866 y1 = yc - r * sin(theta0 + dtheta);
1867 /* fill the arc, use the correct type of close */
1868 if (close_type) XSetArcMode(display, fillGC, ArcChord);
1869 else XSetArcMode(display, fillGC, ArcPieSlice);
1870 XFillArc(display, P, fillGC, xc - r, yc - r, 2 * r, 2 * r,
1871 (int) ((theta0 / pi) * 180 * 64),
1872 (int) ((dtheta / pi) * 180 * 64));
1873 /* now draw the edge */
1874 XDrawArc(display, P, edgeGC, xc - r, yc - r, 2 * r, 2 * r,
1875 (int) ((theta0 / pi) * 180 * 64),
1876 (int) ((dtheta / pi) * 180 * 64));
1878 if (close_type) { /* chord closure */
1879 XDrawLine(display, P, edgeGC, x0, y0, x1, y1);
1880 } else { /* pie closure */
1881 XDrawLine(display, P, edgeGC, x0, y0, xc, yc);
1882 XDrawLine(display, P, edgeGC, xc, yc, x1, y1);
1887 /* generate a set of points for an elliptical outline between 2 angles */
1888 /* assume centred at the origin, we get two conjugate diameters */
1889 /* dxy gives tangent of angles */
1891 when the ellipse is parallel to the axes we have:
1892 x = a cos(theta), y = b sin(theta), where theta is parametric
1893 when we rotate thru an angle alpha we have
1894 x = a cos(theta) * cos(alpha) - b sin(theta) * sin(alpha),
1895 y = b sin(theta) * cos(alpha) + a * cos(theta) * sin(alpha)
1896 use formulae and variable names from theory of conjugate diameters
1897 (not misleading formulae in ANSI document)
1899 static int getEllipseXPoints(int x1, int y1, int x2, int y2,
1900 float dxy[4], XPoint **outPtr)
1903 double D, S, alpha, a, b, ca, sa, c0, c1, s0, s1, cd, sd;
1904 double meanR, theta1, theta2, dtheta, alpha1, alpha2, dalpha, delta;
1907 D = x2 * y1 - y2 * x1;
1908 S = (SQ(x1) + SQ(x2) + SQ(y1) + SQ(y2)) / 2.0;
1910 a = sqrt(S + sqrt(SQ(S) - SQ(D)));
1911 b = sqrt(S - sqrt(SQ(S) - SQ(D)));
1912 /* the angle of axes rotation */
1913 argy = 2.0 * (x1 * y1 + x2 * y2);
1914 argx = (SQ(x1) + SQ(x2) - SQ(y1) - SQ(y2)) / 2.0;
1916 /* atan2(y,x) takes the arctangent of y/x. One would assumen
1917 ** that if x is zero, then things blow up. This is not so for
1918 ** solaris. It seems that the solris math lib knows how to handle
1919 ** atan(0,0) which is the case here. However, things blow up on
1920 ** hp. So, if argx is 0, then make argy zero and argx 1.
1927 alpha = atan2(argy, argx);
1930 /* we need to figure out the direction of parametric rotation */
1931 /* we always go in the direction from CD 1 to 2 thru smallest angle */
1932 alpha1 = atan2((double) y1, (double) x1);
1933 alpha2 = atan2((double) y2, (double) x2);
1934 dalpha = (alpha2 > alpha1) ? alpha2 - alpha1 : alpha1 - alpha2;
1935 rot = ((dalpha <= pi) && (alpha2 > alpha1)) ||
1936 ((dalpha <= pi) && (alpha2 < alpha1)) ? 1 : -1;
1937 /* we need to relate the incoming angles to the parametric angles */
1938 argy = a * (ca * dxy[1] - sa * dxy[0]);
1939 argx = b * (ca * dxy[0] + sa * dxy[1]);
1945 theta1 = atan2(argy, argx);
1947 argy = a * (ca * dxy[3] - sa * dxy[2]);
1948 argx = b * (ca * dxy[2] + sa * dxy[3]);
1954 theta2 = atan2(argy, argx);
1956 theta1 = atan2(a * (ca * dxy[1] - sa * dxy[0]),
1957 b * (ca * dxy[0] + sa * dxy[1]));
1958 theta2 = atan2(a * (ca * dxy[3] - sa * dxy[2]),
1959 b * (ca * dxy[2] + sa * dxy[3]));
1961 /* need to figure out angle to move thru in parameter space */
1962 /* always start at theta1 and move to theta2 */
1963 /* note (theta1 == theta2) => delta = 2 * pi */
1964 if (rot > 0) { /* move in clockwise direction */
1965 delta = (theta2 > theta1) ? theta2 - theta1 : theta2 + 2 * pi - theta1;
1966 } else { /* move in anticlockwise direction */
1967 delta = (theta2 < theta1) ? theta2 - theta1 : theta2 - 2 * pi - theta1;
1969 /* choose a reasonable number of steps */
1970 meanR = sqrt(SQ(a) + SQ(b)) / 2;
1971 /* relate number of steps to circumference */
1972 nSteps = meanR * delta;
1973 if (nSteps < 0) nSteps = - nSteps;
1974 ++nSteps; /* so that we always have at least 2 points */
1976 dtheta = delta / nSteps;
1977 /* make the points memory, always add two so it can be closed */
1978 myPtr = (XPoint *) malloc(sizeof(XPoint) * (nSteps + 2));
1981 /* and fill it out */
1986 for (i=0; i<nSteps; ++i) {
1987 myPtr[i].x = a * c0 * ca - b * s0 * sa;
1988 myPtr[i].y = a * c0 * sa + b * s0 * ca;
1989 /* use recursion relation to step cos and sin */
1990 c1 = c0 * cd - s0 * sd;
1991 s1 = c0 * sd + s0 * cd;
1995 /* fill out the return */
2000 static ellipse(dat_ptr, cmd_ptr, cgm_s)
2001 unsigned char *dat_ptr;
2002 struct cmd_info_s *cmd_ptr;
2005 int xc, yc, cdx0, cdy0, cdx1, cdy1, x0, y0, w, h, noPts, i;
2006 XPoint *myPtr = NULL;
2007 static float dxy[4] = {1, 0, 1, 0}; /* make a full ellipse */
2008 /* get the Ellipse centre */
2009 xc = getX(&dat_ptr, cgm_s);
2010 yc = getY(&dat_ptr, cgm_s);
2011 /* get the first conjugate diameter endpoint */
2012 cdx0 = getX(&dat_ptr, cgm_s);
2013 cdy0 = getY(&dat_ptr, cgm_s);
2014 /* get the second conjugate diameter endpoint */
2015 cdx1 = getX(&dat_ptr, cgm_s);
2016 cdy1 = getY(&dat_ptr, cgm_s);
2017 /* have to go ahead and get the points on the curve for a polyline call */
2018 /* subtract out the centre for simplicity */
2019 noPts = getEllipseXPoints(cdx0 - xc, cdy0 - yc, cdx1 - xc, cdy1 - yc,
2021 if (noPts == 0) return 0;
2022 /* convert to LH co-ord system, add centre back in */
2023 for (i=0; i<noPts; ++i) {
2024 myPtr[i].x = xc + myPtr[i].x;
2025 myPtr[i].y = max_y - (yc + myPtr[i].y);
2027 /* make sure it closes */
2028 myPtr[noPts].x = myPtr[0].x;
2029 myPtr[noPts].y = myPtr[0].y;
2030 /* fill the ellipse */
2031 XFillPolygon(display, P, fillGC, myPtr, noPts, Convex, CoordModeOrigin);
2032 /* draw the outline */
2033 XDrawLines(display, P, edgeGC, myPtr, noPts + 1, CoordModeOrigin);
2037 /* Elliptical arc */
2038 static elarc(dat_ptr, cmd_ptr, cgm_s)
2039 unsigned char *dat_ptr;
2040 struct cmd_info_s *cmd_ptr;
2043 int xc, yc, cdx0, cdy0, cdx1, cdy1, i, noPts;
2045 XPoint *myPtr = NULL;
2046 /* get the Ellipse centre */
2047 xc = getX(&dat_ptr, cgm_s);
2048 yc = getY(&dat_ptr, cgm_s);
2049 /* get the first conjugate diameter endpoint */
2050 cdx0 = getX(&dat_ptr, cgm_s);
2051 cdy0 = getY(&dat_ptr, cgm_s);
2052 /* get the second conjugate diameter endpoint */
2053 cdx1 = getX(&dat_ptr, cgm_s);
2054 cdy1 = getY(&dat_ptr, cgm_s);
2055 /* get the tangent vectors */
2056 for (i=0; i<4; ++i) dxy[i] = getVDC(&dat_ptr, cgm_s);
2057 /* have to go ahead and get the points on the curve for a polyline call */
2058 /* subtract out the centre for simplicity */
2059 noPts = getEllipseXPoints(cdx0 - xc, cdy0 - yc, cdx1 - xc, cdy1 - yc,
2061 if (noPts == 0) return 0;
2062 /* convert to LH co-ord system, add centre back in */
2063 for (i=0; i<noPts; ++i) {
2064 myPtr[i].x = xc + myPtr[i].x;
2065 myPtr[i].y = max_y - (yc + myPtr[i].y);
2067 /* draw the outline */
2068 XDrawLines(display, P, lineGC, myPtr, noPts, CoordModeOrigin);
2073 /* Elliptical arc, close */
2074 static elarcclose(dat_ptr, cmd_ptr, cgm_s)
2075 unsigned char *dat_ptr;
2076 struct cmd_info_s *cmd_ptr;
2079 int xc, yc, cdx0, cdy0, cdx1, cdy1, i, close_type, noPts;
2081 XPoint *myPtr = NULL;
2082 /* get the Ellipse centre */
2083 xc = getX(&dat_ptr, cgm_s);
2084 yc = getY(&dat_ptr, cgm_s);
2085 /* get the first conjugate diameter endpoint */
2086 cdx0 = getX(&dat_ptr, cgm_s);
2087 cdy0 = getY(&dat_ptr, cgm_s);
2088 /* get the second conjugate diameter endpoint */
2089 cdx1 = getX(&dat_ptr, cgm_s);
2090 cdy1 = getY(&dat_ptr, cgm_s);
2091 /* get the tangent vectors */
2092 for (i=0; i<4; ++i) dxy[i] = getVDC(&dat_ptr, cgm_s);
2093 /* get the close type */
2094 close_type = b_gsint(&dat_ptr, 16);
2095 /* have to go ahead and get the points on the curve for a polyline call */
2096 /* subtract out the centre for simplicity */
2097 noPts = getEllipseXPoints(cdx0 - xc, cdy0 - yc, cdx1 - xc, cdy1 - yc,
2099 if (noPts == 0) return 0;
2100 /* convert to LH co-ord system, add centre back in */
2101 for (i=0; i<noPts; ++i) {
2102 myPtr[i].x = xc + myPtr[i].x;
2103 myPtr[i].y = max_y - (yc + myPtr[i].y);
2105 /* now add in the closure */
2106 if (close_type) { /* chord closure */
2107 myPtr[noPts].x = myPtr[0].x;
2108 myPtr[noPts].y = myPtr[0].y;
2110 } else { /* pie closure */
2111 myPtr[noPts].x = xc;
2112 myPtr[noPts].y = max_y - yc;
2113 myPtr[noPts + 1].x = myPtr[0].x;
2114 myPtr[noPts + 1].y = myPtr[0].y;
2118 XFillPolygon(display, P, fillGC, myPtr, noPts, Convex, CoordModeOrigin);
2119 /* draw the outline */
2120 XDrawLines(display, P, edgeGC, myPtr, noPts, CoordModeOrigin);
2125 /* Attribute elements */
2126 static int setLineType(int inType, GC inGC)
2131 myStruct.line_style = LineSolid;
2132 XChangeGC(display, inGC, GCLineStyle, &myStruct);
2135 myStruct.line_style = LineOnOffDash;
2136 XChangeGC(display, inGC, GCLineStyle, &myStruct);
2137 XSetDashes(display, inGC, 0, lineArray, 2);
2140 myStruct.line_style = LineOnOffDash;
2141 XChangeGC(display, inGC, GCLineStyle, &myStruct);
2142 XSetDashes(display, inGC, 0, lineArray + 2, 2);
2144 case 4: /* dash-dot */
2145 myStruct.line_style = LineOnOffDash;
2146 XChangeGC(display, inGC, GCLineStyle, &myStruct);
2147 XSetDashes(display, inGC, 0, lineArray, 4);
2149 case 5: /* dash-dot-dot */
2150 myStruct.line_style = LineOnOffDash;
2151 XChangeGC(display, inGC, GCLineStyle, &myStruct);
2152 XSetDashes(display, inGC, 0, lineArray, 6);
2154 default: return 1; /* no idea */
2159 static ltype(dat_ptr, cmd_ptr, cgm_s)
2160 unsigned char *dat_ptr;
2161 struct cmd_info_s *cmd_ptr;
2164 /* get the line type */
2165 cgm_s->ltype = b_gsint(&dat_ptr, cgm_s->indexprec);
2166 return setLineType(cgm_s->ltype, lineGC);
2169 static lwidth(dat_ptr, cmd_ptr, cgm_s)
2170 unsigned char *dat_ptr;
2171 struct cmd_info_s *cmd_ptr;
2174 switch (cgm_s->lwidspecmode) {
2176 switch (cgm_s->vdctype) {
2177 case VDC_INT: cgm_s->lwidth.i = xScale * b_gsint(&dat_ptr, cgm_s->vdcintprec);
2179 case VDC_REAL: cgm_s->lwidth.r = xScale * b_real(&dat_ptr, &(cgm_s->vdcrprec));
2180 cgm_s->lwidth.i = cgm_s->lwidth.r;
2184 case SCALED: cgm_s->lwidth.s = b_real(&dat_ptr, &(cgm_s->realprec));
2185 cgm_s->lwidth.i = cgm_s->lwidth.s; /* scale from 1 */
2188 /* some servers can't handle widths of 1 */
2189 myStruct.line_width = (cgm_s->lwidth.i < 2) ? 0 : cgm_s->lwidth.i;
2190 XChangeGC(display, lineGC, GCLineWidth, &myStruct);
2194 static lcolr(dat_ptr, cmd_ptr, cgm_s)
2195 unsigned char *dat_ptr;
2196 struct cmd_info_s *cmd_ptr;
2201 /* may be in direct colour mode or indexed colour mode */
2202 switch (cgm_s->colselmode) {
2203 case D_C_M: for (i=0; i<3; ++i) cgm_s->lcolr[i] =
2204 b_guint(&dat_ptr, cgm_s->colprec);
2205 setRGB(cgm_s, cgm_s->lcolr, lineGC);
2207 case I_C_M: cgm_s->lcolr[3] = b_guint(&dat_ptr, cgm_s->cindprec);
2208 setIndex(cgm_s, cgm_s->lcolr[3], lineGC);
2210 default: /* nothing */ break;
2215 static mtype(dat_ptr, cmd_ptr, cgm_s)
2216 unsigned char *dat_ptr;
2217 struct cmd_info_s *cmd_ptr;
2220 /* get the line type */
2221 cgm_s->mtype = b_gsint(&dat_ptr, cgm_s->indexprec);
2226 static msize(dat_ptr, cmd_ptr, cgm_s)
2227 unsigned char *dat_ptr;
2228 struct cmd_info_s *cmd_ptr;
2231 switch (cgm_s->marksizspecmode) {
2233 switch (cgm_s->vdctype) {
2236 cgm_s->msize.i = getVDC(&dat_ptr, cgm_s);
2240 case SCALED: cgm_s->msize.s = b_real(&dat_ptr, &(cgm_s->realprec));
2241 cgm_s->msize.i = (int) (cgm_s->msize.s * 5);
2247 static mcolr(dat_ptr, cmd_ptr, cgm_s)
2248 unsigned char *dat_ptr;
2249 struct cmd_info_s *cmd_ptr;
2253 /* may be in direct colour mode or indexed colour mode */
2254 switch (cgm_s->colselmode) {
2255 case D_C_M: for (i=0; i<3; ++i) cgm_s->mcolr[i] =
2256 b_guint(&dat_ptr, cgm_s->colprec);
2257 setRGB(cgm_s, cgm_s->mcolr, markGC);
2259 case I_C_M: cgm_s->mcolr[3] = b_guint(&dat_ptr, cgm_s->cindprec);
2260 setIndex(cgm_s, cgm_s->mcolr[3], markGC);
2265 /* Text Font Index, ignored at the moment */
2266 static tfindex(unsigned char *dat_ptr, struct cmd_info_s *cmd_ptr,
2269 /* get the text font index */
2270 cgm_s->tfindex = b_gsint(&dat_ptr, cgm_s->indexprec);
2274 /* Text Precision, ignored at the moment; stroke everything */
2275 static tprec(unsigned char *dat_ptr, struct cmd_info_s *cmd_ptr,
2278 /* get the text font index */
2279 cgm_s->tprec = b_gsint(&dat_ptr, 16);
2283 /* Character Expansion Factor */
2284 static cexpfac(unsigned char *dat_ptr, struct cmd_info_s *cmd_ptr,
2287 cgm_s->cexpfac = b_real(&dat_ptr, &(cgm_s->realprec));
2291 /* Character Space */
2292 static cspace(unsigned char *dat_ptr, struct cmd_info_s *cmd_ptr,
2295 cgm_s->cspace = b_real(&dat_ptr, &(cgm_s->realprec));
2300 static tcolr(unsigned char *dat_ptr, struct cmd_info_s *cmd_ptr,
2305 /* may be in direct colour mode or indexed colour mode */
2306 switch (cgm_s->colselmode) {
2308 for (i=0; i<3; ++i) {
2309 cgm_s->tcolr[i] = b_guint(&dat_ptr, cgm_s->colprec);
2311 cgm_s->tPixel = getPixel(cgm_s, cgm_s->tcolr);
2314 cgm_s->tcolr[3] = index = b_guint(&dat_ptr, cgm_s->cindprec);
2315 if ((index >= 0) && (index < MAXCOLRS) && coltabPixels[index]) {
2316 cgm_s->tPixel = coltabPixels[index];
2317 } else cgm_s->tPixel = blackPixel;
2323 /* Character Height */
2324 static cheight(unsigned char *dat_ptr, struct cmd_info_s *cmd_ptr,
2327 /* just 1 VDC to grab */
2328 cgm_s->cheight.i = getVDC(&dat_ptr, cgm_s);
2331 /* Character Orientation */
2332 static corient(unsigned char *dat_ptr,struct cmd_info_s *cmd_ptr,
2337 /* just 4 VDC's to grab */
2338 switch (cgm_s->vdctype) {
2339 case VDC_INT: for (i=0; i<4; ++i)
2340 cgm_s->corient[i].i = b_gsint(&dat_ptr, cgm_s->vdcintprec);
2342 case VDC_REAL: for (i=0; i<4; ++i)
2343 cgm_s->corient[i].r = b_real(&dat_ptr, &(cgm_s->vdcrprec));
2349 static tpath(unsigned char *dat_ptr, struct cmd_info_s *cmd_ptr,
2352 cgm_s->tpath = b_gsint(&dat_ptr, 16);
2356 /* Text Alignment */
2357 static talign(unsigned char *dat_ptr, struct cmd_info_s *cmd_ptr,
2362 /* first the 2 enumerated types */
2363 for (i=0; i<2; ++i) cgm_s->talign[i].i = b_gsint(&dat_ptr, 16);
2364 /* now the 2 real bits */
2365 for (i=0; i<2; ++i) cgm_s->talign[i].r =
2366 b_real(&dat_ptr, &(cgm_s->realprec));
2370 /* Character Set Index */
2371 static csetindex(dat_ptr, cmd_ptr, cgm_s)
2372 unsigned char *dat_ptr;
2373 struct cmd_info_s *cmd_ptr;
2376 cgm_s->csetindex = b_gsint(&dat_ptr, cgm_s->indexprec);
2380 /* Alternate Character Set Index */
2381 static altcsetindex(dat_ptr, cmd_ptr, cgm_s)
2382 unsigned char *dat_ptr;
2383 struct cmd_info_s *cmd_ptr;
2386 cgm_s->altcsetindex = b_gsint(&dat_ptr, cgm_s->indexprec);
2390 /* Interior Style */
2391 static intstyle(dat_ptr, cmd_ptr, cgm_s)
2392 unsigned char *dat_ptr;
2393 struct cmd_info_s *cmd_ptr;
2396 cgm_s->intstyle = b_gsint(&dat_ptr, 16);
2397 switch (cgm_s->intstyle) {
2398 case 0: /* hollow, implementation dependent, make it the same as empty */
2399 case 4: /* empty, don't fill */
2400 XSetFunction(display, fillGC, GXnoop);
2403 case 2: /* pattern */
2404 case 3: /* hatch, fill all of these */
2405 XSetFunction(display, fillGC, GXcopy);
2406 XSetFillStyle(display, fillGC, FillSolid);
2408 default: /* do nothing */
2415 static fillcolr(dat_ptr, cmd_ptr, cgm_s)
2416 unsigned char *dat_ptr;
2417 struct cmd_info_s *cmd_ptr;
2422 /* may be in direct colour mode or indexed colour mode */
2423 switch (cgm_s->colselmode) {
2424 case D_C_M: for (i=0; i<3; ++i) cgm_s->fillcolr[i] =
2425 b_guint(&dat_ptr, cgm_s->colprec);
2426 setRGB(cgm_s, cgm_s->fillcolr, fillGC);
2428 case I_C_M: cgm_s->fillcolr[3] = b_guint(&dat_ptr, cgm_s->cindprec);
2429 setIndex(cgm_s, cgm_s->fillcolr[3], fillGC);
2436 static hatchindex(dat_ptr, cmd_ptr, cgm_s)
2437 unsigned char *dat_ptr;
2438 struct cmd_info_s *cmd_ptr;
2441 cgm_s->hatchindex = b_gsint(&dat_ptr, cgm_s->indexprec);
2446 static patindex(dat_ptr, cmd_ptr, cgm_s)
2447 unsigned char *dat_ptr;
2448 struct cmd_info_s *cmd_ptr;
2451 cgm_s->patindex = b_gsint(&dat_ptr, cgm_s->indexprec);
2456 static etype(dat_ptr, cmd_ptr, cgm_s)
2457 unsigned char *dat_ptr;
2458 struct cmd_info_s *cmd_ptr;
2461 cgm_s->etype = b_gsint(&dat_ptr, cgm_s->indexprec);
2462 return setLineType(cgm_s->etype, edgeGC);
2465 static ewidth(dat_ptr, cmd_ptr, cgm_s)
2466 unsigned char *dat_ptr;
2467 struct cmd_info_s *cmd_ptr;
2470 switch (cgm_s->edwidspecmode) {
2472 switch (cgm_s->vdctype) {
2473 case VDC_INT: cgm_s->ewidth.i = xScale * b_gsint(&dat_ptr, cgm_s->vdcintprec);
2475 case VDC_REAL: cgm_s->ewidth.r = xScale * b_real(&dat_ptr, &(cgm_s->vdcrprec));
2476 cgm_s->ewidth.i = cgm_s->ewidth.r;
2480 case SCALED: cgm_s->ewidth.s = b_real(&dat_ptr, &(cgm_s->realprec));
2481 cgm_s->ewidth.i = cgm_s->ewidth.s; /* scale from 1 */
2484 /* some servers can't handle widths of 1 */
2485 myStruct.line_width = (cgm_s->ewidth.i < 2) ? 0 : cgm_s->ewidth.i;
2486 XChangeGC(display, edgeGC, GCLineWidth, &myStruct);
2490 static ecolr(dat_ptr, cmd_ptr, cgm_s)
2491 unsigned char *dat_ptr;
2492 struct cmd_info_s *cmd_ptr;
2497 /* may be in direct colour mode or indexed colour mode */
2498 switch (cgm_s->colselmode) {
2499 case D_C_M: for (i=0; i<3; ++i) cgm_s->ecolr[i] =
2500 b_guint(&dat_ptr, cgm_s->colprec);
2501 setRGB(cgm_s, cgm_s->ecolr, edgeGC);
2503 case I_C_M: cgm_s->ecolr[3] = b_guint(&dat_ptr, cgm_s->cindprec);
2504 setIndex(cgm_s, cgm_s->ecolr[3], edgeGC);
2510 /* Edge Visibility */
2511 static evis(dat_ptr, cmd_ptr, cgm_s)
2512 unsigned char *dat_ptr;
2513 struct cmd_info_s *cmd_ptr;
2516 cgm_s->evis = b_gsint(&dat_ptr, 16);
2517 if (cgm_s->evis) { /* visible edge */
2518 XSetFunction(display, edgeGC, GXcopy);
2519 } else { /* invisible edge */
2520 XSetFunction(display, edgeGC, GXnoop);
2525 static coltab(dat_ptr, cmd_ptr, cgm_s)
2526 unsigned char *dat_ptr;
2527 struct cmd_info_s *cmd_ptr;
2530 int i, j, first_index, no_entries, iColrs[3];
2532 /* get the starting index */
2533 first_index = b_guint(&dat_ptr, cgm_s->cindprec);
2535 /* how many entries do we have ? */
2536 no_entries = (cmd_ptr->p_len * 8 - cgm_s->cindprec) /
2537 (3 * cgm_s->colprec);
2539 for (i=0; (i < no_entries) && ((i+first_index) < MAXCOLRS); ++i) {
2540 for (j=0; j<3; ++j) {
2541 iColrs[j] = b_guint(&dat_ptr, cgm_s->colprec);
2543 coltabPixels[i+first_index] = getPixel(cgm_s, iColrs);
2548 /* this is the external entry point */
2549 do_b_cmd(struct cmd_info_s *cmd_ptr, unsigned char *dat_ptr,
2552 /* for convenience define and argument list macro */
2553 #define ARG_LIST dat_ptr,cmd_ptr, cgm_s
2555 /* split it up by classes, and then by element */
2556 switch (cmd_ptr->Class) {
2557 /* the Delimiters (Class 0) */
2558 case B_DELIMCLASS: switch (cmd_ptr->element) {
2559 case B_NOOP: return 1;
2560 case B_BMF: return(bmf(ARG_LIST));
2561 case B_EMF: return(emf(ARG_LIST));
2562 case B_BPIC: return(bpic(ARG_LIST));
2563 case B_BPICBODY: return(bpicbody(ARG_LIST));
2564 case B_EPIC: return(epic(ARG_LIST));
2565 default: burp(stderr, "illegal Delimiter element %d\n",
2569 /* the Metafile descriptor elements (Class 1) */
2570 case B_MDESCLASS: switch (cmd_ptr->element) {
2571 case B_MFVERSION: return(mfversion(ARG_LIST));
2572 case B_MFDESCRIP: return(mfdescrip(ARG_LIST));
2573 case B_VDCTYPE: return(vdctype(ARG_LIST));
2574 case B_INTPREC: return(intprec(ARG_LIST));
2575 case B_REALPREC: return(realprec(ARG_LIST));
2576 case B_INDEXPREC: return(indexprec(ARG_LIST));
2577 case B_COLPREC: return(colprec(ARG_LIST));
2578 case B_CINDPREC: return(cindprec(ARG_LIST));
2579 case B_MAXCIND: return(maxcind(ARG_LIST));
2580 case B_CVEXTENT: return(cvextent(ARG_LIST));
2581 case B_MFELLIST: return(mfellist(ARG_LIST));
2582 case B_MFDEFREP: return(mfdefrep(ARG_LIST)); /* special */
2583 case B_FONTLIST: return(fontlist(ARG_LIST));
2584 case B_CHARLIST: return(charlist(ARG_LIST));
2585 case B_CHARANNOUNCE: return(charannounce(ARG_LIST));
2586 default: burp(stderr, "illegal Metafile descriptor element %d\n",
2591 /* the Picture descriptor elements (Class 2) */
2592 case B_PDESCLASS: switch (cmd_ptr->element) {
2593 case B_SCALMODE: return(scalmode(ARG_LIST));
2594 case B_COLSELMODE: return(colselmode(ARG_LIST));
2595 case B_LWIDSPECMODE: return(lwidspecmode(ARG_LIST));
2596 case B_MARKSIZSPECMODE: return(marksizspecmode(ARG_LIST));
2597 case B_EDWIDSPECMODE: return(edwidspecmode(ARG_LIST));
2598 case B_VDCEXTENT: return(vdcextent(ARG_LIST));
2599 case B_BACKCOLR: return(backcolr(ARG_LIST));
2600 default: burp(stderr, "illegal Picture Descriptor element %d\n",
2604 /* the Control elements (Class 3) */
2605 case B_CTRLCLASS: switch( cmd_ptr->element) {
2606 case B_VDCINTPREC: return(vdcintprec(ARG_LIST));
2607 case B_VDCRPREC: return(vdcrprec(ARG_LIST));
2608 case B_AUXCOLR: return(auxcolr(ARG_LIST));
2609 case B_TRANSP: return(transp(ARG_LIST));
2610 case B_CLIPRECT: return(cliprect(ARG_LIST));
2611 case B_CLIPINDIC: return(clipindic(ARG_LIST));
2612 default: burp(stderr, "illegal Control element %d\n",
2616 /* the Graphical Primitives (Class 4) */
2617 case B_GPRIMCLASS: switch (cmd_ptr->element) {
2618 case B_POLYLINE: return(polyline(ARG_LIST));
2619 case B_DISPOLY: return(dispoly(ARG_LIST));
2620 case B_POLYMARKER: return(polymarker(ARG_LIST));
2621 case B_TEXT: return(text(ARG_LIST));
2622 case B_RESTEXT: return(restext(ARG_LIST));
2623 case B_APPTEXT: return(apptext(ARG_LIST));
2624 case B_POLYGON: return(polygon(ARG_LIST));
2625 case B_POLYSET: return(polyset(ARG_LIST));
2626 case B_CELLARRAY: return(cellarray(ARG_LIST));
2627 case B_GENDPRIM: return 1; /* not used here */
2628 case B_RECTANGLE: return(rectangle(ARG_LIST));
2629 case B_CIRCLE: return(circle(ARG_LIST));
2630 case B_CIRC3: return(circ3(ARG_LIST));
2631 case B_CIRC3CLOSE: return(circ3close(ARG_LIST));
2632 case B_CIRCCENTRE: return(circcentre(ARG_LIST));
2633 case B_CIRCCCLOSE: return(circcclose(ARG_LIST));
2634 case B_ELLIPSE: return(ellipse(ARG_LIST));
2635 case B_ELARC: return(elarc(ARG_LIST));
2636 case B_ELARCCLOSE: return(elarcclose(ARG_LIST));
2637 default: burp(stderr, "illegal Graphical Primitive element %d\n",
2641 /* the Attribute elements (Class 5) */
2642 case B_ATTRCLASS: switch (cmd_ptr->element) {
2643 case B_LBINDEX: return 1;
2644 case B_LTYPE: return(ltype(ARG_LIST));
2645 case B_LWIDTH: return(lwidth(ARG_LIST));
2646 case B_LCOLR: return(lcolr(ARG_LIST));
2647 case B_MBINDEX: return 1;
2648 case B_MTYPE: return(mtype(ARG_LIST));
2649 case B_MSIZE: return(msize(ARG_LIST));
2650 case B_MCOLR: return(mcolr(ARG_LIST));
2651 case B_TBINDEX: return 1;
2652 case B_TFINDEX: return(tfindex(ARG_LIST));
2653 case B_TPREC: return(tprec(ARG_LIST));
2654 case B_CEXPFAC: return(cexpfac(ARG_LIST));
2655 case B_CSPACE: return(cspace(ARG_LIST));
2656 case B_TCOLR: return(tcolr(ARG_LIST));
2657 case B_CHEIGHT: return(cheight(ARG_LIST));
2658 case B_CORIENT: return(corient(ARG_LIST));
2659 case B_TPATH: return(tpath(ARG_LIST));
2660 case B_TALIGN: return(talign(ARG_LIST));
2661 case B_CSETINDEX: return(csetindex(ARG_LIST));
2662 case B_ALTCSETINDEX: return(altcsetindex(ARG_LIST));
2663 case B_FILLBINDEX: return 1;
2664 case B_INTSTYLE: return(intstyle(ARG_LIST));
2665 case B_FILLCOLR: return(fillcolr(ARG_LIST));
2666 case B_HATCHINDEX: return(hatchindex(ARG_LIST));
2667 case B_PATINDEX: return(patindex(ARG_LIST));
2668 case B_EDBINDEX: return 1;
2669 case B_ETYPE: return(etype(ARG_LIST));
2670 case B_EWIDTH: return(ewidth(ARG_LIST));
2671 case B_ECOLR: return(ecolr(ARG_LIST));
2672 case B_EVIS: return(evis(ARG_LIST));
2673 case B_FILLREF: return 1;
2674 case B_PATTAB: return 1;
2675 case B_PATSIZE: return 1;
2676 case B_COLTAB: return(coltab(ARG_LIST));
2677 case B_ASPSFLAGS: return 1;
2678 default: burp(stderr, "illegal Attribute element %d\n",
2682 /* the Escape element (Class 6) */
2683 case B_ESCCLASS: return 1;
2684 /* the External elements (Class 7) */
2685 case B_EXTCLASS: return 1;
2686 /* any other class */
2687 default: burp(stderr, "illegal class %d\n", cmd_ptr->Class);