PLplot  5.10.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
cd.c
Go to the documentation of this file.
1 
2 // cd.c main file for cgmdraw module.
3 //
4 // Written by G. Edward Johnson <mailto:lorax@nist.gov>
5 // Date: April 1996
6 // Copyright: cd software produced by NIST, an agency of the
7 // U.S. government, is by statute not subject to copyright
8 // in the United States. Recipients of this software assume all
9 // responsibilities associated with its operation, modification
10 // and maintenance.
11 //
12 // Portions of this package are from the gd package written by
13 // Thomas Boutell and are copyright 1994, 1995, Quest Protein
14 // Database Center, Cold Spring Harbor Labs. They are marked in the
15 // source code.
16 //
17 
18 #ifndef NOMALLOCH
19 #include <malloc.h>
20 #endif
21 #include <stdio.h>
22 #include <math.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include "defines.h"
26 #include "cd.h"
27 
28 
29 static int cdImageAddColor( cdImagePtr im, int si, int ei );
30 
31 cdImagePtr cdImageCreate( int sx, int sy )
32 // Creates a new image of size (sx,sy). Most people should always
33 // start by calling this function
34 {
35  cdImagePtr im;
36 
37  im = cdImageStartCgm();
38  if ( !im )
39  return 0; // memory allocation failed
40  if ( !cdImageSetSize( im, sx, sy ) )
41  {
42  free( im ); return 0;
43  }
44 
45  if ( !cdCgmHeader( im ) )
46  {
47  free( im ); return 0;
48  }
49 
50  if ( cdCgmPic( im, 0 ) )
51  {
52  return im;
53  }
54  else
55  {
56  free( im );
57  return 0;
58  }
59 }
60 
61 static int cdAppNull( unsigned char *es, int x )
62 {
63 // put x nulls in the string.
64 // return value is number of octets added (1)
65  int y;
66 
67  for ( y = 0; y < x; y++ )
68  {
69  *es = '\0';
70  es++;
71  }
72  return x;
73 }
74 
75 static int cdAppByte( unsigned char *es, short int addme )
76 {
77 // Append an octet to the end of es
78 // Return value is number of octets added
79 // for internal cd functions only, do not call
80 //
81  *es = (unsigned char) addme & 0377;
82  return 1;
83 }
84 
85 static int cdAppShort( unsigned char *es, short int addme )
86 {
87 // Append a short to the end of es
88 // return value is number of octets added
89 // For internal cd functions only, do not call!
90 //
91  short int temp;
92 
93  temp = addme >> 8;
94  *es = (unsigned char) temp & 0377;
95  es++;
96  *es = (unsigned char) addme & 0377;
97  return 2;
98 }
99 
100 // static int cdAppWord(unsigned char *es, int addme){
101 // Append an word to es
102 // Return value is number of octets added
103 // For internal cd functions only, do not call!
104 //
105 //
106 // int temp;
107 // temp = addme >> 24;
108 //es = (unsigned char) temp & 0377;
109 // es++;
110 // temp = addme >> 16;
111 //es = (unsigned char) temp & 0377;
112 // es++;
113 // temp = addme >> 8;
114 //es = (unsigned char) temp & 0377;
115 // es++;
116 //es = (unsigned char) addme & 0377;
117 // es++;
118 // return 4;
119 // }
120 //
121 
122 static int cdcomhead( unsigned char *es, int elemclass, int id, int len )
123 {
124 // sets the command header in the first two bytes of string es
125 // element class is in bits 15-12
126 // element id is in bits 11-5
127 // parameter list length is in bits 4-0
128 //
129  int temp;
130 
131  if ( !es )
132  return 0; // the string must be allocated first
133 
134  // set the element class
135  *es = (unsigned char) elemclass << 4;
136  // set the element id
137  temp = 0177 & id;
138  temp = temp >> 3;
139  *es = *es | temp;
140  es++;
141  id = id << 5;
142  *es = (unsigned char) id;
143  *es = *es | (unsigned char) ( 037 & len );
144 
145  return 1;
146 }
147 
148 static int cdcomheadlong( unsigned char *es, int elemclass, int id, int len )
149 {
150 // sets the command header for the long form.
151 // first 16 bits:
152 // element class is in bits 15-12
153 // element id is in bits 11-5
154 // parameter list length is in bits 4-0 = 31
155 // second 16 bits:
156 // bit 15 = 0 (for last partition)
157 // bit 14-0 param list len
158 //
159 
160  // I'm lazy, call cdcomhead to set the first two bytes
161  if ( !cdcomhead( es, elemclass, id, 31 ) )
162  return 0;
163  es += 2;
164 
165  // now set the second two bytes
166  cdAppShort( es, (short int) len );
167  *es = *es & 0177; // make bit 15 = 0
168  es += 2;
169 
170  return 1;
171 }
172 
173 static int cdAddElem( cdImagePtr im, unsigned char *es, int octet_count )
174 // adds a string, which is a CGM element to the elemlist.
175 // This function is called by other functions in this library and
176 // should NOT be called by users of the library
177 // For internal cd functions only, do not call!
178 //
179 {
180  unsigned char *newlist; // in case memory allocation fails
181  int x; // counter
182 
183  while ( ( octet_count + 1 ) >= im->bytestoend )
184  {
185  // not enough space, must grow elemlist
186  im->listlen = im->listlen + CDGROWLISTSIZE;
187  newlist = (unsigned char *) realloc( im->elemlist, SIZEOF( unsigned char ) * im->listlen );
188  if ( newlist )
189  {
190  // successfully allocated memory
191  im->elemlist = newlist;
193  im->curelemlist = im->elemlist + ( im->listlen - im->bytestoend );
194  }
195  else
196  {
197  // memory allocation failed, save yurself
198  im->listlen = im->listlen - CDGROWLISTSIZE;
199  return 0;
200  }
201  }
202 
203  // ok, if we get to here, there is enough space, so add it.
204  for ( x = 0; x < octet_count; x++ )
205  {
206  *im->curelemlist = (unsigned char) *es;
207  im->curelemlist++;
208  es++;
209  }
210  im->bytestoend = im->bytestoend - octet_count;
211  return 1;
212 }
213 
215 {
216 // add the cgm header to the imagepointer's element list
217 // do it all in a string than call cdAddElem on it
218 // For internal cd functions only, do not call!
219 //
220  unsigned char *headerp;
221  unsigned char *head;
222  const unsigned char *buf, *buf2;
223  int octet_count = 0;
224  int blen; // length of buf
225  int curly;
226  int fontlistlen; // each font in the font list is stored as a string,
227  // with a single octet in front of the string
228  // giving its length, fontlistlen is the sum of
229  // the lengths of all the font strings + the
230  // length octets.
231 
232  if ( im->state != 0 )
233  return 0;
234  headerp = (unsigned char *) calloc( 1024, SIZEOF( unsigned char ) );
235  if ( !headerp )
236  return 0; // memory allocation failed
237  head = headerp;
238 
239  //** Attribute: BegMF; Elem Class 0; Elem ID 1
240  buf = (const unsigned char *) "cd: CgmDraw Library";
241  blen = strlen( (const char *) buf );
242  cdcomhead( head, 0, 1, blen + 1 );
243  head += 2;
244  head += cdAppByte( head, (short int) blen );
245  buf2 = buf;
246  while ( *buf2 )
247  {
248  *head++ = *buf2++;
249  }
250  octet_count += ( blen + 3 );
251  curly = 4 - ( octet_count % 4 );
252  if ( curly % 4 )
253  {
254  octet_count += curly;
255  head += cdAppNull( head, curly );
256  }
257 
258  //** Attribute: MFVersion; Elem Class 1; Elem ID 1
259  cdcomhead( head, 1, 1, 2 );
260  head += 2;
261  head += cdAppShort( head, (short int) 1 );
262  octet_count += 4;
263 
264  //** Attribute: MFDesc; Elem Class 1; Elem ID 2
265  blen = strlen( (char *) im->desc );
266  cdcomheadlong( head, 1, 2, blen + 1 );
267  head += 4;
268  head += cdAppByte( head, (short int) blen );
269  buf2 = im->desc;
270  while ( *buf2 )
271  {
272  *head++ = *buf2++;
273  }
274  octet_count += ( blen + 5 );
275  curly = 4 - ( octet_count % 4 );
276  if ( curly % 4 )
277  {
278  octet_count += curly;
279  head += cdAppNull( head, curly );
280  }
281 
282  //** Attribute: ColrPrec; Elem Class 1; Elem ID 7
283  cdcomhead( head, 1, 7, 2 );
284  head += 2;
285  head += cdAppShort( head, (short int) 8 );
286  octet_count += 4;
287 
288  //** Attribute: ColrIndexPrec; Elem Class 1; Elem ID 8
289  cdcomhead( head, 1, 8, 2 );
290  head += 2;
291  head += cdAppShort( head, (short int) 8 );
292  octet_count += 4;
293 
294  //** Attribute: MaxColrIndex; Elem Class 1; Elem ID 9
295  cdcomhead( head, 1, 9, 1 );
296  head += 2;
297  head += cdAppByte( head, (short int) 255 );
298  octet_count += 4; head++;
299 
300  //** Attribute: MFElemList; Elem Class 1; Elem ID 11
301  // shorthand here. 1 means 1 element specified, (-1,1)
302  // means drawing-plus-control set
303  cdcomhead( head, 1, 11, 6 );
304  head += 2;
305  head += cdAppShort( head, (short int) 1 );
306  head += cdAppShort( head, (short int) -1 );
307  head += cdAppShort( head, (short int) 1 );
308  octet_count += 8;
309 
310  //** Attribute: FontList; Elem Class 1; Elem ID 13
311  // im->fontlist contains a comma separated list of font names
312  // since we don't need the commas, and every font except one has
313  // a comma, and we do need a length octet, that means that
314  // taking the string length will give us one less than the
315  // correct length.
316  buf = im->fontlist;
317  if ( buf ) // don't do this if there aren't any fonts
318  {
319  fontlistlen = strlen( (const char *) buf ) + 1;
320  cdcomheadlong( head, 1, 13, fontlistlen );
321  head += 4;
322 
323  while ( *buf )
324  {
325  blen = 0;
326  buf2 = buf;
327  while ( ( *buf ) && ( *buf != ',' ) )
328  {
329  buf++;
330  blen++;
331  }
332  head += cdAppByte( head, (short int) blen );
333  while ( buf2 < buf )
334  {
335  *head++ = *buf2++;
336  }
337  if ( *buf )
338  {
339  buf++;
340  }
341  }
342  octet_count += ( 4 + fontlistlen );
343  curly = 4 - ( octet_count % 4 );
344  if ( curly % 4 )
345  {
346  octet_count += curly;
347  head += cdAppNull( head, curly );
348  }
349  } // end of check to see if any fonts
350 
351  if ( cdAddElem( im, headerp, octet_count ) )
352  {
353  free( headerp );
354  headerp = 0;
355  return 1;
356  }
357  else
358  {
359  free( headerp );
360  return 0;
361  }
362 }
363 
364 
365 int cdCgmPic( cdImagePtr im, int sticky )
366 {
367 // Start the picture. if the sticky bit is set, set and use the defaults
368 // of the previous picture. Otherwise, reset all defaults.
369 // Gej: sticky = 0 reset defaults, 1 dont reset anything, 2 only
370 // reset the color table
371 //
372  unsigned char *headerp;
373  unsigned char *head;
374  unsigned char *buf, *buf2;
375  char *tb;
376  int octet_count = 0;
377  int blen; // length of buf
378  int x1, x2, x3, x4; // needed for setting defaults
379 
380  if ( ( im->state != 0 ) && ( im->state != 2 ) )
381  return 0;
382  if ( ( sticky > 2 ) || ( sticky < 0 ) )
383  return 0; // invalid sticky bit
384  // increment the picture number
385  im->picnum++;
386  tb = (char *) calloc( 4 * 4, SIZEOF( char ) );
387  if ( !tb )
388  return 0; // memory allocation failed
389  headerp = (unsigned char *) calloc( 1024, SIZEOF( unsigned char ) );
390  if ( !headerp )
391  { // memory allocation failed
392  free( tb );
393  return 0;
394  }
395  head = headerp;
396 
397  //** Attribute: BegPic; Elem Class 0; Elem ID 3
398  sprintf( tb, "picture %d", im->picnum );
399  buf = (unsigned char *) tb;
400  // buf = (unsigned char *) "picture 1";
401  blen = strlen( (char *) buf );
402  cdcomhead( head, 0, 3, blen + 1 );
403  head += 2;
404  head += cdAppByte( head, (short int) blen );
405  buf2 = buf;
406  while ( *buf2 )
407  {
408  *head++ = *buf2++;
409  }
410  free( tb );
411  octet_count += ( blen + 3 );
412  if ( !( blen % 2 ) )
413  {
414  octet_count++;
415  head += cdAppNull( head, 1 );
416  }
417  if ( octet_count % 4 )
418  {
419  octet_count += 2;
420  head += cdAppNull( head, 2 );
421  }
422 
423  //** Attribute: ColrMode; Elem Class 2; Elem ID 2
424  cdcomhead( head, 2, 2, 2 );
425  head += 2;
426  head += cdAppShort( head, (short int) 0 );
427  octet_count += 4;
428  // Picture Descriptor: Line Width Specification Mode;
429  // Elem Class 2; Elem ID 3
430  if ( sticky && ( im->linespec != CDLINESPEC ) )
431  {
432  cdcomhead( head, 2, 3, 2 );
433  head += 2;
434  head += cdAppShort( head, (short int) im->linespec );
435  octet_count += 4;
436  }
437  // Picture Descriptor: Marker Size Specification Mode;
438  // Elem Class 2; Elem ID 4
439  if ( sticky && ( im->markerspec != CDMARKERSPEC ) )
440  {
441  cdcomhead( head, 2, 4, 2 );
442  head += 2;
443  head += cdAppShort( head, (short int) im->markerspec );
444  octet_count += 4;
445  }
446  // Picture Descriptor: Edge Width Specification Mode;
447  // Elem Class 2; Elem ID 5
448  if ( sticky && ( im->edgespec != CDEDGESPEC ) )
449  {
450  cdcomhead( head, 2, 5, 2 );
451  head += 2;
452  head += cdAppShort( head, (short int) im->edgespec );
453  octet_count += 4;
454  }
455 
456  //** Attribute: VDCExt; Elem Class 2; Elem ID 6
457  cdcomhead( head, 2, 6, 8 );
458  head += 2;
459  head += cdAppShort( head, (short int) 0 );
460  head += cdAppShort( head, (short int) 0 );
461  head += cdAppShort( head, (short int) im->sx );
462  head += cdAppShort( head, (short int) im->sy );
463  octet_count += 10;
464 
465  //** Attribute: Begin Picture Body; Elem Class 0; Elem ID 4
466  cdcomhead( head, 0, 4, 0 );
467  head += 2;
468  octet_count += 2;
469 
470  if ( cdAddElem( im, headerp, octet_count ) )
471  {
472  free( headerp );
473  }
474  else
475  {
476  free( headerp );
477  return 0;
478  }
479 
480  if ( sticky )
481  {
482  // keep defaults the way they are
483  if ( sticky == 1 )
484  {
485  // keep the color table
486  if ( cdImageAddColor( im, 0, im->colorsTotal - 1 ) == -1 )
487  {
488  // no colortable
489  return 1;
490  }
491  }
492  else
493  {
494  // Nuke the color table if there is one
495  cdImageColorClear( im );
496  }
497  im->state = 1;
498  x1 = im->ltype; x2 = im->lwidth; x3 = im->lcolor;
499  im->ltype = CDLTYPE; im->lwidth = CDLWIDTH; im->lcolor = CDLCOLOR;
500  if ( !cdSetLineAttrib( im, x1, x2, x3 ) )
501  return 0;
502 
503  x1 = im->shapestyle; x2 = im->shapecolor; x3 = im->shapehatch;
505  im->shapehatch = CDSHAPEHATCH;
506  if ( !cdSetShapeFillAttrib( im, x1, x2, x3 ) )
507  return 0;
508 
509  x1 = im->edgetype; x2 = im->edgewidth;
510  x3 = im->edgecolor; x4 = im->edgevis;
512  im->edgecolor = CDEDGECOLOR; im->edgevis = CDEDGEVIS;
513  if ( !cdSetShapeEdgeAttrib( im, x1, x2, x3, x4 ) )
514  return 0;
515 
516  x1 = im->textfont; x2 = im->textcolor; x3 = im->textheight;
518  im->textheight = CDTEXTHEIGHT;
519  if ( !cdSetTextAttrib( im, x1, x2, x3 ) )
520  return 0;
521 
522  x1 = im->textpath; im->textpath = CDTEXTPATH;
523  if ( !cdSetTextPath( im, x1 ) )
524  return 0;
525 
526  x1 = im->mtype; x2 = im->msize; x3 = im->mcolor;
527  im->ltype = CDMTYPE; im->lwidth = CDMSIZE; im->lcolor = CDMCOLOR;
528  if ( !cdSetMarkerAttrib( im, x1, x2, x3 ) )
529  return 0;
530  }
531  else
532  {
533  // reset all the defaults
534  cdImageSetDefaults( im );
535  // Nuke the color table if there is one
536  cdImageColorClear( im );
537  im->state = 1; // now we are officially in the picture
538  }
539  return 1;
540 }
541 
542 int cdCgmNewPic( cdImagePtr im, int sticky )
543 // The CGM standard allows multiple images in a single file. This function
544 // will close the current picture, then open a new one.
545 // if sticky is 0 then all attributes will be reset to the defaults
546 // if sticky is 1 then all attributes will be inherited from the prevous
547 // picture.
548 // if sticky is 2 all attributes except the color table will be inherited
549 // from the previous picture
550 //
551 {
552  // close the current picture
553  if ( !cdImageEndPic( im ) )
554  return 0;
555 
556  // now start the new picture
557  return ( cdCgmPic( im, sticky ) );
558 }
559 
560 int cdImageCgm( cdImagePtr im, FILE *out )
561 // Gej: Write the image to file *out, which must be open already
562 // does not close the file
563 {
564 //
565 // if (out) {
566 // im->outfile = out;
567 // }
568 //
569  cdImageSetOutput( im, out );
570  return cdImageEndCgm( im );
571 }
572 
573 
574 int cdSetLineType( cdImagePtr im, int lntype )
575 {
576 // Attribute: Line Type; Elem Class 5; Elem ID 2
577 // Set the line type. Possible values are:
578 // 1=solid, 2=dash, 3=dot, 4=dash-dot, 5=dash-dot-dot
579 // Even though new ones can be defined, I am limiting lntype to these values
580 // If you really need more, you can make the proper changes.
581 //
582  unsigned char *es, *esp;
583  int octet_count;
584 
585  // First check and see if the user doesn't want any changes,
586  // if so, just return success
587  if ( lntype == -1 )
588  return 1;
589 
590  // Check and see if the value it is being set to is the current
591  // value, if so, don't make any changes, just return 1
592  if ( lntype == im->ltype )
593  return 1;
594 
595  // Make sure that lntype is between 1 and 5
596  if ( ( lntype < 1 ) || ( lntype > 5 ) )
597  return 0;
598 
599  // allocate sufficent space. should be 32 bits * 4 to be safe
600  es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
601  if ( !es )
602  return 0; // memory allocation failed
603  esp = es;
604 
605  if ( !cdcomhead( es, 5, 2, 2 ) )
606  {
607  free( esp ); return 0;
608  }
609  es += 2;
610  // set Param_List_Len to 2 (signed int at index precision)
611 
612  // add in the value of lntype
613  es += cdAppShort( es, (short int) lntype );
614 
615  octet_count = 4; // we just know this
616 
617  // add it to the buffer
618  if ( cdAddElem( im, esp, octet_count ) )
619  {
620  im->ltype = (short int) lntype;
621  free( esp );
622  return 1;
623  }
624  else
625  {
626  free( esp );
627  return 0;
628  }
629 }
630 
631 int cdSetLineWidth( cdImagePtr im, int lnwidth )
632 {
633 // Attribute: Line Width; Elem Class 5; Elem ID 3
634 // sets the line width. with an image of height X with line width 1
635 // the displayed width will be 1/X%. as an example, if you image is
636 // x=5, y=10, and you set line width = 1, and draw a vertical line, the
637 // resulting line will cover 20% of horizontal area.
638 //
639  unsigned char *es, *esp;
640  int octet_count;
641 
642  // First check and see if the user doesn't want any changes,
643  // if so, just return success
644  if ( lnwidth == -1 )
645  return 1;
646 
647  // Check and see if the value it is being set to is the current
648  // value, if so, don't make any changes, just return 1
649  if ( lnwidth == im->lwidth )
650  return 1;
651 
652  // allocate sufficent space. should be 32 bits * 4 to be safe
653  es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
654  if ( !es )
655  return 0; // memory allocation failed
656  esp = es;
657 
658 
659  //gej: line width is 32 bit floating point number, 16 bits before the
660  // decimal, 16 bits after if Line Spec is default (1, scaled)
661  // if Line Spec is 0 (0, absolute) then it is 16 bit SI
662  if ( im->linespec )
663  {
664  if ( !cdcomhead( es, 5, 3, 4 ) )
665  {
666  free( esp ); return 0;
667  }
668  es += 2;
669  octet_count = 2;
670  es += cdAppShort( es, (short int) lnwidth );
671  octet_count += 2;
672  // the next two (after decimal point) will always be zero
673  es += cdAppNull( es, 2 );
674  octet_count += 2;
675  }
676  else
677  {
678  if ( !cdcomhead( es, 5, 3, 2 ) )
679  {
680  free( esp ); return 0;
681  }
682  octet_count = 2;
683  es += 2;
684  es += cdAppShort( es, (short int) lnwidth );
685  octet_count += 2;
686  }
687 
688 
689  // add it to the buffer
690  if ( cdAddElem( im, esp, octet_count ) )
691  {
692  im->lwidth = lnwidth;
693  free( esp );
694  return 1;
695  }
696  else
697  {
698  free( esp );
699  return 0;
700  }
701 }
702 
703 int cdSetLineColor( cdImagePtr im, int lncolor )
704 {
705 // Attribute: Line Colour; Elem Class 5; Elem ID 4
706 // Sets the line color. lncolor should be an index into the color
707 // table that you have previously allocated.
708 //
709  unsigned char *es, *esp;
710  int octet_count;
711  // First check and see if the user doesn't want any changes,
712  // if so, just return success
713  if ( lncolor == -1 )
714  return 1;
715 
716  // Check and see if the value it is being set to is the current
717  // value, if so, don't make any changes, just return 1
718  if ( lncolor == im->lcolor )
719  return 1;
720 
721  // Make sure the color they want to use has been allocated.
722  // also, that color must be non-negative
723  if ( ( lncolor >= im->colorsTotal ) || ( lncolor < 0 ) )
724  return 0; // you must allocate a color before you use it
725 
726  // allocate sufficent space. should be 32 bits * 4 to be safe
727  es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
728  if ( !es )
729  return 0; // memory allocation failed
730  esp = es;
731 
732 
733  if ( !cdcomhead( es, 5, 4, 1 ) )
734  {
735  free( esp ); return 0;
736  }
737  es += 2;
738 
739  *es = 0377 & lncolor; // mask off last 8 bits and put in es
740  es++;
741 
742  es += cdAppNull( es, 1 );
743 
744  octet_count = 4; // we just know this; 2 octets of header,
745  // 1 octet of data, 1 octet of null data
746 
747  // add it to the buffer
748  if ( cdAddElem( im, esp, octet_count ) )
749  {
750  im->lcolor = (short int) lncolor;
751  free( esp );
752  return 1;
753  }
754  else
755  {
756  free( esp );
757  return 0;
758  }
759 }
760 
761 int cdSetFillStyle( cdImagePtr im, int instyle )
762 {
763 // set the style of the interior of filled area elements.
764 // Attribute: Interior Style; Elem Class 5; Elem ID 22
765 // These attributes stay in effect until changed, so you don't have to output
766 // them every time.
767 // Interior Style: (integers 0-6, corresponding to: hollow, solid,
768 // [not pattern], hatch, empty, [not geometric pattern],
769 // interpolated.)
770 // attribute is 16 bit signed int
771 //
772  unsigned char *es, *esp;
773  int octet_count;
774 
775  // First check and see if the user doesn't want any changes,
776  // if so, just return success
777  if ( instyle == -1 )
778  return 1;
779 
780  // Check and see if the value it is being set to is the current
781  // value, if so, don't make any changes, just return 1
782  if ( instyle == im->shapestyle )
783  return 1;
784 
785  // Make sure that lnhatch is between 0 and 6, but not
786  // 2, 5, or 6
787  if ( ( instyle < 0 ) || ( instyle > 4 ) || ( instyle == 2 ) )
788  return 0;
789 
790  // allocate sufficent space. should be 32 bits * 4 to be safe
791  es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
792  if ( !es )
793  return 0; // memory allocation failed
794  esp = es;
795 
796  // set the header to Class 5, ID 22, Length 2
797  if ( !cdcomhead( es, 5, 22, 2 ) )
798  {
799  free( esp ); return 0;
800  }
801  es += 2;
802 
803  // add in the value of inhatch
804  es += cdAppShort( es, (short int) instyle );
805 
806  octet_count = 4; // we just know this
807 
808  // add it to the buffer
809  if ( cdAddElem( im, esp, octet_count ) )
810  {
811  im->shapestyle = (short int) instyle;
812  free( esp );
813  return 1;
814  }
815  else
816  {
817  free( esp );
818  return 0;
819  }
820 }
821 
822 int cdSetFillColor( cdImagePtr im, int incolor )
823 {
824 // set the color of the interior of filled area elements
825 // Attribute: Fill Colour; Elem Class 5; Elem ID 23
826 // These attributes stay in effect until changed, so you don't have to output
827 // them every time.
828 // Fill Colour: (index into the color table)
829 //
830  unsigned char *es, *esp;
831  int octet_count;
832  // First check and see if the user doesn't want any changes,
833  // if so, just return success
834  if ( incolor == -1 )
835  return 1;
836 
837  // Check and see if the value it is being set to is the current
838  // value, if so, don't make any changes, just return 1
839  if ( incolor == im->shapecolor )
840  return 1;
841 
842  // Make sure the color they want to use has been allocated.
843  // also, that color must be non-negative
844  if ( ( incolor >= im->colorsTotal ) || ( incolor < 0 ) )
845  return 0; // you must allocate a color before you use it
846 
847  // allocate sufficent space. should be 32 bits * 4 to be safe
848  es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
849  if ( !es )
850  return 0; // memory allocation failed
851  esp = es;
852 
853  if ( !cdcomhead( es, 5, 23, 1 ) )
854  {
855  free( esp ); return 0;
856  }
857  es += 2;
858 
859  *es = 0377 & incolor; // mask off last 8 bits and put in es
860  es++;
861  es += cdAppNull( es, 1 );
862 
863  octet_count = 4; // we just know this; 2 octets of header,
864  // 1 octet of data, 1 octet of null data
865 
866  // add it to the buffer
867  if ( cdAddElem( im, esp, octet_count ) )
868  {
869  im->shapecolor = (short int) incolor;
870  free( esp );
871  return 1;
872  }
873  else
874  {
875  free( esp );
876  return 0;
877  }
878 }
879 
880 int cdSetFillHatch( cdImagePtr im, int inhatch )
881 {
882 // Set the hatch pattern for the interior of filled-area elements
883 // the fill style must be set to hatch for this to have an effect.
884 // Attribute: Hatch Index; Elem Class 5; Elem ID 24
885 // These attributes stay in effect until changed, so you don't have to output
886 // them every time.
887 // Hatch Index: (integers 1-6, corresponding to: horizontal lines,
888 // vertical lines, pos. slope parallel lines,
889 // neg. slope parallel lines, horizontal/vertical
890 // crosshatch, positive/negative slope crosshatch)
891 //
892 
893  unsigned char *es, *esp;
894  int octet_count, temp;
895 
896 
897  // First check and see if the user doesn't want any changes,
898  // if so, just return success
899  if ( inhatch == -1 )
900  return 1;
901 
902  // Check and see if the value it is being set to is the current
903  // value, if so, don't make any changes, just return 1
904  if ( inhatch == im->shapehatch )
905  return 1;
906 
907  // Make sure that lnhatch is between 1 and 6
908  if ( ( inhatch < 1 ) || ( inhatch > 6 ) )
909  return 0;
910 
911  // allocate sufficent space. should be 32 bits * 4 to be safe
912  es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
913  if ( !es )
914  return 0; // memory allocation failed
915  esp = es;
916 
917  // set the command header to class 5, id 24, length 2
918  if ( !cdcomhead( es, 5, 24, 2 ) )
919  {
920  free( esp ); return 0;
921  }
922  es += 2;
923 
924  // add in the value of inhatch
925  temp = inhatch >> 8;
926  *es = *es | ( temp & 0377 );
927  es++;
928  *es = *es | ( inhatch & 0377 );
929  es++;
930 
931  octet_count = 4; // we just know this
932 
933  // add it to the buffer
934  if ( cdAddElem( im, esp, octet_count ) )
935  {
936  im->shapehatch = (short int) inhatch;
937  free( esp );
938  return 1;
939  }
940  else
941  {
942  free( esp );
943  return 0;
944  }
945 }
946 
947 int cdSetEdgeType( cdImagePtr im, int edtype )
948 {
949 // set the type of the edge of filled-area elements.
950 // Attribute: Edge Type; Elem Class 5; Elem ID 27
951 // These attributes stay in effect until changed, so you don't have to output
952 // them every time.
953 // Edge Type (integers 1-5, corresponding to: solid, dash, dot,
954 // dash-dot, dash-dot-dot. These are the same as those used
955 // for line type.)
956 // In Part 3 of the standard (Binary Encoding) on page 47 it says that
957 // edge type is integer. This is incorrect. Edge type is Index, just
958 // like line type.
959 // Even though new ones can be defined, I am limiting lntype to these values
960 // If you really need more, you can make the proper changes.
961 //
962  unsigned char *es, *esp;
963  int octet_count;
964 
965  // First check and see if the user doesn't want any changes,
966  // if so, just return success
967  if ( edtype == -1 )
968  return 1;
969 
970  // Check and see if the value it is being set to is the current
971  // value, if so, don't make any changes, just return 1
972  if ( edtype == im->edgetype )
973  return 1;
974 
975  // Make sure that lntype is between 1 and 5
976  if ( ( edtype < 1 ) || ( edtype > 5 ) )
977  return 0;
978 
979  // allocate sufficent space. should be 32 bits * 4 to be safe
980  es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
981  if ( !es )
982  return 0; // memory allocation failed
983  esp = es;
984 
985  if ( !cdcomhead( es, 5, 27, 2 ) )
986  {
987  free( esp ); return 0;
988  }
989  es += 2;
990 
991  // add in the value of edtype
992  es += cdAppShort( es, (short int) edtype );
993 
994  octet_count = 4; // we just know this
995 
996  // add it to the buffer
997  if ( cdAddElem( im, esp, octet_count ) )
998  {
999  im->edgetype = (short int) edtype;
1000  free( esp );
1001  return 1;
1002  }
1003  else
1004  {
1005  free( esp );
1006  return 0;
1007  }
1008 }
1009 
1010 int cdSetEdgeWidth( cdImagePtr im, int edwidth )
1011 {
1012 // Set the width of the edge of filled-area elements.
1013 // Attribute: Edge Width; Elem Class 5; Elem ID 28
1014 // These attributes stay in effect until changed, so you don't have to output
1015 // them every time.
1016 // Edge Width (should be the same as line width)
1017 //
1018  unsigned char *es, *esp;
1019  int octet_count;
1020 
1021  // First check and see if the user doesn't want any changes,
1022  // if so, just return success
1023  if ( edwidth == -1 )
1024  return 1;
1025 
1026  // Check and see if the value it is being set to is the current
1027  // value, if so, don't make any changes, just return 1
1028  if ( edwidth == im->edgewidth )
1029  return 1;
1030 
1031  // allocate sufficent space. should be 32 bits * 4 to be safe
1032  es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
1033  if ( !es )
1034  return 0; // memory allocation failed
1035  esp = es;
1036 
1037  //gej: edge width is 32 bit floating point number, 16 bits before the
1038  // decimal, 16 bits after for default edge spec (1, scaled) if
1039  // edge spec is absolute (0) then just 16 bit SI
1040  if ( im->edgespec )
1041  {
1042  if ( !cdcomhead( es, 5, 28, 4 ) )
1043  {
1044  free( esp ); return 0;
1045  }
1046  es += 2;
1047  octet_count = 2;
1048  es += cdAppShort( es, edwidth );
1049  octet_count += 2;
1050  // the next two (after decimal point) will always be zero
1051  es += cdAppNull( es, 2 );
1052  octet_count += 2;
1053  }
1054  else
1055  {
1056  if ( !cdcomhead( es, 5, 28, 2 ) )
1057  {
1058  free( esp ); return 0;
1059  }
1060  es += 2;
1061  octet_count = 2;
1062  es += cdAppShort( es, edwidth );
1063  octet_count += 2;
1064  }
1065 
1066  // add it to the buffer
1067  if ( cdAddElem( im, esp, octet_count ) )
1068  {
1069  im->edgewidth = edwidth;
1070  free( esp );
1071  return 1;
1072  }
1073  else
1074  {
1075  free( esp );
1076  return 0;
1077  }
1078 }
1079 
1080 int cdSetEdgeColor( cdImagePtr im, int edcolor )
1081 {
1082 // Set the color of the edge of filled-area elements.
1083 // Attribute: Edge Color; Elem Class 5; Elem ID 29
1084 // These attributes stay in effect until changed, so you don't have to output
1085 // them every time.
1086 // Edge Colour (index into the color table)
1087 //
1088  unsigned char *es, *esp;
1089  int octet_count;
1090  // First check and see if the user doesn't want any changes,
1091  // if so, just return success
1092  if ( edcolor == -1 )
1093  return 1;
1094 
1095  // Check and see if the value it is being set to is the current
1096  // value, if so, don't make any changes, just return 1
1097  if ( edcolor == im->edgecolor )
1098  return 1;
1099 
1100  // Make sure the color they want to use has been allocated.
1101  // also, that color must be non-negative
1102  if ( ( edcolor >= im->colorsTotal ) || ( edcolor < 0 ) )
1103  return 0; // you must allocate a color before you use it
1104 
1105  // allocate sufficent space. should be 32 bits * 4 to be safe
1106  es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
1107  if ( !es )
1108  return 0; // memory allocation failed
1109  esp = es;
1110  if ( !cdcomhead( es, 5, 29, 1 ) )
1111  {
1112  free( esp ); return 0;
1113  }
1114  es += 2;
1115 
1116  *es = 0377 & edcolor; // mask off last 8 bits and put in es
1117  es++;
1118  es += cdAppNull( es, 1 );
1119 
1120  octet_count = 4; // we just know this; 2 octets of header,
1121  // 1 octet of data, 1 octet of null data
1122 
1123  // add it to the buffer
1124  if ( cdAddElem( im, esp, octet_count ) )
1125  {
1126  im->edgecolor = (short int) edcolor;
1127  free( esp );
1128  return 1;
1129  }
1130  else
1131  {
1132  free( esp );
1133  return 0;
1134  }
1135 }
1136 
1137 int cdSetEdgeVis( cdImagePtr im, int edvis )
1138 {
1139 // Set the visibility of the edge of filled-area elements.
1140 // Attribute: Edge Visibility; Elem Class 5; Elem ID 30
1141 // These attributes stay in effect until changed, so you don't have to output
1142 // them every time.
1143 // Edge Visibility (integer 0 or 1, corresponding to: Off, On)
1144 // Attribute is 16 bit signed int.
1145 //
1146  unsigned char *es, *esp;
1147  int octet_count, temp;
1148 
1149  // First check and see if the user doesn't want any changes,
1150  // if so, just return success
1151  if ( edvis == -1 )
1152  return 1;
1153 
1154  // Check and see if the value it is being set to is the current
1155  // value, if so, don't make any changes, just return 1
1156  if ( edvis == im->edgevis )
1157  return 1;
1158 
1159  // allocate sufficent space. should be 32 bits * 4 to be safe
1160  es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
1161  if ( !es )
1162  return 0; // memory allocation failed
1163  esp = es;
1164 
1165  if ( !cdcomhead( es, 5, 30, 2 ) )
1166  {
1167  free( esp ); return 0;
1168  }
1169  es += 2; octet_count = 2;
1170  temp = edvis >> 8;
1171  *es = *es | ( temp & 0377 );
1172  es++;
1173  *es = *es | ( edvis & 0377 );
1174  es++;
1175  octet_count += 2;
1176 
1177 
1178  // add it to the buffer
1179  if ( cdAddElem( im, esp, octet_count ) )
1180  {
1181  im->edgevis = (short int) edvis;
1182  free( esp );
1183  return 1;
1184  }
1185  else
1186  {
1187  free( esp );
1188  return 0;
1189  }
1190 }
1191 
1192 int cdSetTextFont( cdImagePtr im, int font )
1193 {
1194 // Attribute: Text Font Index; Elem Class 5; Elem ID 10
1195 // font is an index into the font table. it can have one of the following
1196 // values:
1197 // 1 Times Roman
1198 // 2 Times Bold
1199 // 3 Times Italic
1200 // 4 Times Bold Italic
1201 // 5 Helvetica
1202 // 6 Helvetica Bold
1203 // 7 Helvetica Italic
1204 // 8 Helvetica Bold Italic
1205 // 9 Courier
1206 // 10 Courier Bold
1207 // 11 Courier Italic
1208 // 12 Courier Bold Italic
1209 //
1210  unsigned char *es, *esp;
1211  int octet_count;
1212 
1213  // First check and see if the user doesn't want any changes,
1214  // if so, just return success
1215  if ( font == -1 )
1216  return 1;
1217 
1218  // Check and see if the value it is being set to is the current
1219  // value, if so, don't make any changes, just return 1
1220  if ( font == im->textfont )
1221  return 1;
1222 
1223  // Make sure that font is between 1 and the number of fonts
1224  if ( ( font < 1 ) || ( font > im->numfonts ) )
1225  return 0;
1226 
1227  // allocate sufficent space. should be 32 bits * 4 to be safe
1228  es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
1229  if ( !es )
1230  return 0; // memory allocation failed
1231  esp = es;
1232 
1233  if ( !cdcomhead( es, 5, 10, 2 ) )
1234  {
1235  free( esp ); return 0;
1236  }
1237  es += 2;
1238 
1239  es += cdAppShort( es, (short int) font );
1240 
1241  octet_count = 4; // we just know this
1242 
1243  // add it to the buffer
1244  if ( cdAddElem( im, esp, octet_count ) )
1245  {
1246  im->textfont = (short int) font;
1247  free( esp );
1248  return 1;
1249  }
1250  else
1251  {
1252  free( esp );
1253  return 0;
1254  }
1255 }
1256 
1257 int cdSetTextColor( cdImagePtr im, int color )
1258 {
1259 // Attribute: Text Colour ; Elem Class 5; Elem ID 14
1260 // set the forground color of text
1261 //
1262  unsigned char *es, *esp;
1263  int octet_count;
1264  // First check and see if the user doesn't want any changes,
1265  // if so, just return success
1266  if ( color == -1 )
1267  return 1;
1268 
1269  // Check and see if the value it is being set to is the current
1270  // value, if so, don't make any changes, just return 1
1271  if ( color == im->textcolor )
1272  return 1;
1273 
1274  // Make sure the color they want to use has been allocated.
1275  // also, that color must be non-negative
1276  if ( ( color >= im->colorsTotal ) || ( color < 0 ) )
1277  return 0; // you must allocate a color before you use it
1278 
1279  // allocate sufficent space. should be 32 bits * 4 to be safe
1280  es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
1281  if ( !es )
1282  return 0; // memory allocation failed
1283  esp = es;
1284 
1285  if ( !cdcomhead( es, 5, 14, 1 ) )
1286  {
1287  free( esp ); return 0;
1288  }
1289  es += 2;
1290 
1291  *es = 0377 & color; // mask off last 8 bits and put in es
1292  es++;
1293 
1294  octet_count = 4; // we just know this; 2 octets of header,
1295  // 1 octet of data, 1 octet of null data
1296 
1297  // add it to the buffer
1298  if ( cdAddElem( im, esp, octet_count ) )
1299  {
1300  im->textcolor = (short int) color;
1301  free( esp );
1302  return 1;
1303  }
1304  else
1305  {
1306  free( esp );
1307  return 0;
1308  }
1309 }
1310 
1311 int cdSetTextHeight( cdImagePtr im, int height )
1312 {
1313 // Attribute: Character Height; Elem Class 5; Elem ID 15
1314 // the height is in the same units as line width
1315 //
1316  unsigned char *es, *esp;
1317  int octet_count;
1318  // First check and see if the user doesn't want any changes,
1319  // if so, just return success
1320  if ( height == -1 )
1321  return 1;
1322 
1323  // Check and see if the value it is being set to is the current
1324  // value, if so, don't make any changes, just return 1
1325  if ( height == im->textheight )
1326  return 1;
1327 
1328  // allocate sufficent space. should be 32 bits * 4 to be safe
1329  es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
1330  if ( !es )
1331  return 0; // memory allocation failed
1332  esp = es;
1333 
1334  if ( !cdcomhead( es, 5, 15, 2 ) )
1335  {
1336  free( esp ); return 0;
1337  }
1338  octet_count = 2; es += 2;
1339 
1340  es += cdAppShort( es, height );
1341  octet_count += 2;
1342 
1343  // add it to the buffer
1344  if ( cdAddElem( im, esp, octet_count ) )
1345  {
1346  im->textheight = height;
1347  free( esp );
1348  return 1;
1349  }
1350  else
1351  {
1352  free( esp );
1353  return 0;
1354  }
1355 }
1356 
1357 int cdSetTextPath( cdImagePtr im, int tpath )
1358 {
1359 // Attribute: Text Path; Elem Class 5; Elem ID 17
1360 // Is one of:
1361 // 0 right -- Means the direction of the character base vector
1362 // 1 left -- means 180 degrees from the character base vector
1363 // 2 up -- means the direction of the character up vector
1364 // 3 down -- means 180 degrees from the character up vector
1365 //
1366  unsigned char *es, *esp;
1367  int octet_count;
1368 
1369  // First check and see if the user doesn't want any changes,
1370  // if so, just return success
1371  if ( tpath == -1 )
1372  return 1;
1373 
1374  // Check and see if the value it is being set to is the current
1375  // value, if so, don't make any changes, just return 1
1376  if ( tpath == im->textpath )
1377  return 1;
1378 
1379  // allocate sufficent space. should be 32 bits * 4 to be safe
1380  es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
1381  if ( !es )
1382  return 0; // memory allocation failed
1383  esp = es;
1384  octet_count = 0;
1385 
1386  if ( !cdcomhead( es, 5, 17, 2 ) )
1387  {
1388  free( esp ); return 0;
1389  }
1390  es += 2; octet_count = 2;
1391 
1392  es += cdAppShort( es, (short int) tpath );
1393  octet_count += 2;
1394 
1395  // add it to the buffer
1396  if ( cdAddElem( im, esp, octet_count ) )
1397  {
1398  im->textpath = (short int) tpath;
1399  free( esp );
1400  return 1;
1401  }
1402  else
1403  {
1404  free( esp );
1405  return 0;
1406  }
1407 }
1408 
1409 int cdSetTextOrient( cdImagePtr im, int xup, int yup, int xbase, int ybase )
1410 {
1411 // Attribute: Character Orientation; Elem Class 5; Elem ID 16
1412 // (xbase,ybase) is the run and the rise of the line that the text is
1413 // written along. For regular text at an angle, set xup = -ybase
1414 // and yup = xbase. Setting it to something different will result in
1415 // skewed text (which may be what you want.) Text written from bottom to
1416 // top at a 90 degree angle would have the following parameters
1417 // xup=-1, yup=0, xbase=0, ybase=1
1418 //
1419 // This function adds the Orientation to the metafile every time.
1420 // It does not follow the normal -1 for no change, although if you
1421 // put in the same numbers it won't re-add it to the meta file.
1422 //
1423  unsigned char *es, *esp;
1424  int octet_count;
1425 
1426 
1427  // allocate sufficent space. should be 32 bits * 4 to be safe
1428  es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
1429  if ( !es )
1430  return 0; // memory allocation failed
1431  esp = es;
1432  octet_count = 0;
1433 
1434  if ( !cdcomhead( es, 5, 16, 8 ) )
1435  {
1436  free( esp ); return 0;
1437  }
1438  es += 2; octet_count += 2;
1439 
1440  // In the metafile it is a 16 bit signed integer
1441  // add xup
1442  es += cdAppShort( es, (short int) xup );
1443  octet_count += 2;
1444  // add the rest
1445  es += cdAppShort( es, (short int) yup );
1446  octet_count += 2;
1447  es += cdAppShort( es, (short int) xbase );
1448  octet_count += 2;
1449  es += cdAppShort( es, (short int) ybase );
1450  octet_count += 2;
1451 
1452  // add it to the buffer
1453  if ( cdAddElem( im, esp, octet_count ) )
1454  {
1455  free( esp );
1456  return 1;
1457  }
1458  else
1459  {
1460  free( esp );
1461  return 0;
1462  }
1463 }
1464 
1465 int cdSetMarkerType( cdImagePtr im, int mtype )
1466 {
1467 // Attribute: Marker Type; Elem Class 5; Elem ID 6
1468 // Set the Marker type. Possible values are:
1469 // 1=dot, 2=plus, 3=asterisk, 4=circle, 5=cross
1470 // Even though new ones can be defined, I am limiting lntype to these values
1471 // If you really need more, you can make the proper changes.
1472 //
1473  unsigned char *es, *esp;
1474  int octet_count;
1475 
1476  // First check and see if the user doesn't want any changes,
1477  // if so, just return success
1478  if ( mtype == -1 )
1479  return 1;
1480 
1481  // Check and see if the value it is being set to is the current
1482  // value, if so, don't make any changes, just return 1
1483  if ( mtype == im->mtype )
1484  return 1;
1485 
1486  // Make sure that mtype is between 1 and 5
1487  if ( ( mtype < 1 ) || ( mtype > 5 ) )
1488  return 0;
1489 
1490  // allocate sufficent space. should be 32 bits * 4 to be safe
1491  es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
1492  if ( !es )
1493  return 0; // memory allocation failed
1494  esp = es;
1495 
1496  if ( !cdcomhead( es, 5, 6, 2 ) )
1497  {
1498  free( esp ); return 0;
1499  }
1500  es += 2;
1501  // set Param_List_Len to 2 (signed int at index precision)
1502 
1503  // add in the value of mtype
1504  es += cdAppShort( es, (short int) mtype );
1505 
1506  octet_count = 4; // we just know this
1507 
1508  // add it to the buffer
1509  if ( cdAddElem( im, esp, octet_count ) )
1510  {
1511  im->mtype = (short int) mtype;
1512  free( esp );
1513  return 1;
1514  }
1515  else
1516  {
1517  free( esp );
1518  return 0;
1519  }
1520 }
1521 
1522 int cdSetMarkerSize( cdImagePtr im, int msize )
1523 {
1524 // Attribute: Marker Size; Elem Class 5; Elem ID 7
1525 // sets the marker size. with an image of height X with marker size 1
1526 // the displayed size will be 1/X%. as an example, if you image is
1527 // x=5, y=10, and you set marker size = 1, and draw a marker, the
1528 // resulting marker will cover 20% of horizontal area.
1529 //
1530  unsigned char *es, *esp;
1531  int octet_count;
1532 
1533  // First check and see if the user doesn't want any changes,
1534  // if so, just return success
1535  if ( msize == -1 )
1536  return 1;
1537 
1538  // Check and see if the value it is being set to is the current
1539  // value, if so, don't make any changes, just return 1
1540  if ( msize == im->msize )
1541  return 1;
1542 
1543  // allocate sufficent space. should be 32 bits * 4 to be safe
1544  es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
1545  if ( !es )
1546  return 0; // memory allocation failed
1547  esp = es;
1548 
1549 
1550  //gej: marker size is 32 bit floating point number, 16 bits before the
1551  // decimal, 16 bits after if marker spec is default (1, scaled)
1552  // for absolute mode (0, absolute) it is 16 bit SI
1553  if ( im->markerspec )
1554  {
1555  if ( !cdcomhead( es, 5, 7, 4 ) )
1556  {
1557  free( esp ); return 0;
1558  }
1559  octet_count = 2;
1560  es += 2;
1561  es += cdAppShort( es, (short int) msize );
1562  octet_count += 2;
1563  // the next two (after decimal point) will always be zero
1564  es += cdAppNull( es, 2 );
1565  octet_count += 2;
1566  }
1567  else
1568  {
1569  if ( !cdcomhead( es, 5, 7, 4 ) )
1570  {
1571  free( esp ); return 0;
1572  }
1573  octet_count = 2;
1574  es += 2;
1575  es += cdAppShort( es, (short int) msize );
1576  octet_count += 2;
1577  }
1578 
1579 
1580  // add it to the buffer
1581  if ( cdAddElem( im, esp, octet_count ) )
1582  {
1583  im->msize = msize;
1584  free( esp );
1585  return 1;
1586  }
1587  else
1588  {
1589  free( esp );
1590  return 0;
1591  }
1592 }
1593 
1594 int cdSetMarkerColor( cdImagePtr im, int mcolor )
1595 {
1596 // Attribute: Marker Colour; Elem Class 5; Elem ID 8
1597 // Sets the marker color. mcolor should be an index into the color
1598 // table that you have previously allocated.
1599 //
1600  unsigned char *es, *esp;
1601  int octet_count;
1602  // First check and see if the user doesn't want any changes,
1603  // if so, just return success
1604  if ( mcolor == -1 )
1605  return 1;
1606 
1607  // Check and see if the value it is being set to is the current
1608  // value, if so, don't make any changes, just return 1
1609  if ( mcolor == im->mcolor )
1610  return 1;
1611 
1612  // Make sure the color they want to use has been allocated.
1613  // also, that color must be non-negative
1614  if ( ( mcolor >= im->colorsTotal ) || ( mcolor < 0 ) )
1615  return 0; // you must allocate a color before you use it
1616 
1617  // allocate sufficent space. should be 32 bits * 4 to be safe
1618  es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
1619  if ( !es )
1620  return 0; // memory allocation failed
1621  esp = es;
1622 
1623 
1624  if ( !cdcomhead( es, 5, 8, 1 ) )
1625  {
1626  free( esp ); return 0;
1627  }
1628  es += 2;
1629 
1630  *es = 0377 & mcolor; // mask off last 8 bits and put in es
1631  es++;
1632 
1633  es += cdAppNull( es, 1 );
1634 
1635  octet_count = 4; // we just know this; 2 octets of header,
1636  // 1 octet of data, 1 octet of null data
1637 
1638  // add it to the buffer
1639  if ( cdAddElem( im, esp, octet_count ) )
1640  {
1641  im->mcolor = (short int) mcolor;
1642  free( esp );
1643  return 1;
1644  }
1645  else
1646  {
1647  free( esp );
1648  return 0;
1649  }
1650 }
1651 
1652 int cdSetLineAttrib( cdImagePtr im, int lntype, int lnwidth, int lncolor )
1653 {
1654 // Spits out the attributes of lines. These attributes stay in effect
1655 // until changed, so you don't have to output them every time.
1656 //
1657 
1658  if ( !cdSetLineType( im, lntype ) )
1659  return 0;
1660  if ( !cdSetLineWidth( im, lnwidth ) )
1661  return 0;
1662  if ( !cdSetLineColor( im, lncolor ) )
1663  return 0;
1664 
1665  return 1;
1666 }
1667 
1668 int cdSetShapeFillAttrib( cdImagePtr im, int instyle, int incolor, int inhatch )
1669 {
1670 // Spits out the attributes for the interior of filled-area elements.
1671 // These attributes stay in effect until changed, so you don't have to output
1672 // them every time.
1673 // Set the following attributes:
1674 // Interior Style: (integers 0-6, corresponding to: hollow, solid,
1675 // [not pattern], hatch, empty, [not geometric pattern],
1676 // interpolated.)
1677 // Fill Colour: (index into the color table)
1678 // Hatch Index: (integers 1-6, corresponding to: horizontal lines,
1679 // vertical lines, pos. slope parallel lines,
1680 // neg. slope parallel lines, horizontal/vertical
1681 // crosshatch, positive/negative slope crosshatch)
1682 //
1683  if ( !cdSetFillStyle( im, instyle ) )
1684  return 0;
1685  if ( !cdSetFillColor( im, incolor ) )
1686  return 0;
1687  if ( !cdSetFillHatch( im, inhatch ) )
1688  return 0;
1689 
1690  return 1;
1691 }
1692 
1693 int cdSetShapeEdgeAttrib( cdImagePtr im, int edtype, int edwidth, int edcolor, int edvis )
1694 {
1695 // Spits out the attributes for the edges of filled-area elements. It may
1696 // seem logical that these would be the same as the corresponding line
1697 // attributes, but this is not the case.
1698 // These attributes stay in effect until changed, so you don't have to output
1699 // them every time.
1700 // Set the following attributes:
1701 // Edge Type (integers 1-5, corresponding to: solid, dash, dot,
1702 // dash-dot, dash-dot-dot. These are the same as those used
1703 // for line type.)
1704 // Edge Width (should be the same as line width)
1705 // Edge Colour (index into the color table)
1706 // Edge Visibility (integer 0 or 1, corresponding to: Off, On)
1707 //
1708  if ( !cdSetEdgeType( im, edtype ) )
1709  return 0;
1710  if ( !cdSetEdgeWidth( im, edwidth ) )
1711  return 0;
1712  if ( !cdSetEdgeColor( im, edcolor ) )
1713  return 0;
1714  if ( !cdSetEdgeVis( im, edvis ) )
1715  return 0;
1716 
1717  return 1;
1718 }
1719 
1720 int cdSetTextAttrib( cdImagePtr im, int font, int color, int height )
1721 {
1722 // Set the attributes of text. the font is an integer pointer into the
1723 // font list where:
1724 // 1 Times
1725 // 2 Times Bold
1726 // 3 Times Italic
1727 // 4 Times Bold Italic
1728 // 5 Helvetica
1729 // 6 Helvetica Bold
1730 // 7 Helvetica Italic
1731 // 8 Helvetica Bold Italic
1732 // 9 Courier
1733 // 10 Courier Bold
1734 // 11 Courier Italic
1735 // 12 Courier Bold Italic
1736 // color is an index into the colortable which is the color of the text
1737 // size is the approximate size you want the text written in.
1738 //
1739 
1740  if ( !cdSetTextFont( im, font ) )
1741  return 0;
1742  if ( !cdSetTextColor( im, color ) )
1743  return 0;
1744  if ( !cdSetTextHeight( im, height ) )
1745  return 0;
1746 
1747  return 1;
1748 }
1749 
1750 int cdSetMarkerAttrib( cdImagePtr im, int mtype, int msize, int mcolor )
1751 {
1752 // Spits out the attributes of Markers. These attributes stay in effect
1753 // until changed, so you don't have to output them every time.
1754 //
1755 
1756  if ( !cdSetMarkerType( im, mtype ) )
1757  return 0;
1758  if ( !cdSetMarkerSize( im, msize ) )
1759  return 0;
1760  if ( !cdSetMarkerColor( im, mcolor ) )
1761  return 0;
1762 
1763  return 1;
1764 }
1765 
1767 // gej: should work, unless I make changes to cdImage Struct
1768 {
1769  if ( im->elemlist )
1770  {
1771  free( im->elemlist );
1772  }
1773  if ( im->desc )
1774  {
1775  free( im->desc );
1776  }
1777  if ( im->fontlist )
1778  {
1779  free( im->fontlist );
1780  }
1781  free( im );
1782 
1783  return 1;
1784 }
1785 
1786 int cdImageColorClosest( cdImagePtr im, int r, int g, int b )
1787 // From gd library, see README file for copyright information
1788 // gej: should work unchanged
1789 // gej: 5/96, changed the colors to use short int
1790 {
1791  short int i;
1792  long rd, gd, bd;
1793  int ct = ( -1 );
1794  long mindist = 0;
1795  for ( i = 0; ( i < ( im->colorsTotal ) ); i++ )
1796  {
1797  long dist;
1798  if ( im->open[i] )
1799  {
1800  continue;
1801  }
1802  rd = ( im->red[i] - r );
1803  gd = ( im->green[i] - g );
1804  bd = ( im->blue[i] - b );
1805  dist = rd * rd + gd * gd + bd * bd;
1806  if ( ( i == 0 ) || ( dist < mindist ) )
1807  {
1808  mindist = dist;
1809  ct = i;
1810  }
1811  }
1812  return ct;
1813 }
1814 
1816 {
1817 // mark all entries in the color table as open
1818  short int i;
1819  for ( i = 0; ( i < ( cdMaxColors ) ); i++ )
1820  {
1821  im->open[i] = 1;
1822  }
1823  return 1;
1824 }
1825 
1826 int cdImageColorExact( cdImagePtr im, int r, int g, int b )
1827 // From gd library, see README file for copyright information
1828 // gej: should work unchanged
1829 // gej: 5/96, changed colors to work with short ints
1830 {
1831  short int i;
1832  for ( i = 0; ( i < ( im->colorsTotal ) ); i++ )
1833  {
1834  if ( im->open[i] )
1835  {
1836  continue;
1837  }
1838  if ( ( im->red[i] == r ) &&
1839  ( im->green[i] == g ) &&
1840  ( im->blue[i] == b ) )
1841  {
1842  return i;
1843  }
1844  }
1845  return -1;
1846 }
1847 
1848 static int cdImageAddColorIndex( cdImagePtr im, int r, int g, int b )
1849 // adds the specified color to the colortable in the cdImagePtr.
1850 // does not add it to the cgm file, cdImageAddColor does.
1851 // do not use either of these two functions, use cdImageColorAllocate.
1852 //
1853 {
1854  short int i;
1855  short int ct = ( -1 );
1856  for ( i = 0; ( i < ( im->colorsTotal ) ); i++ )
1857  {
1858  if ( im->open[i] )
1859  {
1860  ct = i;
1861  break;
1862  }
1863  }
1864  if ( ct == ( -1 ) )
1865  {
1866  ct = im->colorsTotal;
1867  if ( ct == cdMaxColors )
1868  {
1869  return -1;
1870  }
1871  im->colorsTotal++;
1872  }
1873  im->red[ct] = (short int) r;
1874  im->green[ct] = (short int) g;
1875  im->blue[ct] = (short int) b;
1876  im->open[ct] = (short int) 0;
1877 
1878  return ct;
1879 }
1880 
1881 static int cdImageAddColor( cdImagePtr im, int si, int ei )
1882 // adds colors to the cgm file, gets values from the color table.
1883 // adds all colors from si to ei inclusive.
1884 // Use cdImageColorAllocate, not this one.
1885 //
1886 {
1887  unsigned char *cts, *ctsp; // GEJ: color table attribute
1888  int octet_count; // GEJ: octet count
1889  int numco, curly;
1890  octet_count = 0;
1891  //
1892  // Attribute: Colour Table; Elem Class 5; Elem ID 34
1893  // two parameters P1: Starting colour table index (1 octet, UI)
1894  // P2: list of direct colour values 3-tuples (3 one-octet values)
1895  //
1896  // G E J: find out how many values are being added
1897  if ( ei < 0 )
1898  return -1; // no colors being added
1899  numco = ei - si + 1;
1900 
1901  if ( ( numco > 0 ) && ( numco < 10 ) )
1902  {
1903  // we can use the short form of the command
1904  // allocate sufficent space. Should be 32 bits * 10 to be safe
1905  cts = (unsigned char *) calloc( 4 * 10, SIZEOF( unsigned char ) );
1906  if ( !cts )
1907  return -1; // memory allocation failed
1908  ctsp = cts;
1909  if ( !cdcomhead( ctsp, 5, 34, ( numco * 3 ) + 1 ) )
1910  {
1911  free( cts ); return -1;
1912  }
1913  ctsp += 2; octet_count += 2;
1914  }
1915  else if ( ( numco > 9 ) && ( numco < 256 ) )
1916  {
1917  // we must use the long form of the command
1918  // allocate sufficent space. Should be 32 bits*256 to be safe
1919  cts = (unsigned char *) calloc( 256 * 4, SIZEOF( unsigned char ) );
1920  if ( !cts )
1921  return -1; // memory allocation failed
1922  ctsp = cts;
1923  if ( !cdcomheadlong( ctsp, 5, 34, ( numco * 3 ) + 1 ) )
1924  {
1925  free( cts ); return -1;
1926  }
1927  ctsp += 4; octet_count += 4;
1928  }
1929  else
1930  {
1931  return -1;
1932  }
1933 
1934  //ctsp += cdAppByte(ctsp, (short int) si);
1935  cdAppByte( ctsp, (short int) si );
1936  ctsp++;
1937  octet_count++;
1938  for ( numco = si; numco <= ei; numco++ )
1939  {
1940  ctsp += cdAppByte( ctsp, im->red[numco] );
1941  ctsp += cdAppByte( ctsp, im->green[numco] );
1942  ctsp += cdAppByte( ctsp, im->blue[numco] );
1943  octet_count += 3;
1944  }
1945 
1946 
1947  curly = 4 - ( octet_count % 4 );
1948  if ( curly % 4 )
1949  {
1950  octet_count += curly;
1951  ctsp += cdAppNull( ctsp, curly );
1952  }
1953  // add it to the buffer
1954  if ( cdAddElem( im, cts, octet_count ) )
1955  {
1956  free( cts );
1957  return 1;
1958  }
1959  else
1960  {
1961  free( cts );
1962  return -1;
1963  }
1964 }
1965 
1966 int cdImageColorAllocate( cdImagePtr im, int r, int g, int b )
1967 // From gd library, see README file for copyright information
1968 // gej: modified to allocate the color in the CGM buffer as well
1969 // as the color table
1970 // gej: 5/96, modified to use short ints for colors
1971 {
1972  short int ct;
1973  ct = cdImageAddColorIndex( im, r, g, b );
1974  if ( ct == -1 )
1975  return -1;
1976  // GEJ: w we have successfully alocated it in the color table
1977  // so let's put it in the CGM as well.
1978  //
1979  if ( cdImageAddColor( im, ct, ct ) == -1 )
1980  {
1981  return -1;
1982  }
1983  else
1984  {
1985  return ct;
1986  }
1987 }
1988 
1990 {
1991 // allocate the 16 basic colors in the windows pallete
1992 //
1993 // cdImageColorAllocate(im, 0, 0, 0);
1994 // cdImageColorAllocate(im, 0, 0, 0);
1995 // cdImageColorAllocate(im, 0, 0, 0);
1996 // cdImageColorAllocate(im, 0, 0, 0);
1997 // cdImageColorAllocate(im, 0, 0, 0);
1998 // cdImageColorAllocate(im, 0, 0, 0);
1999 // cdImageColorAllocate(im, 0, 0, 0);
2000 // cdImageColorAllocate(im, 0, 0, 0);
2001 // cdImageColorAllocate(im, 0, 0, 0);
2002 // cdImageColorAllocate(im, 0, 0, 0);
2003 // cdImageColorAllocate(im, 0, 0, 0);
2004 // cdImageColorAllocate(im, 0, 0, 0);
2005 // cdImageColorAllocate(im, 0, 0, 0);
2006 // cdImageColorAllocate(im, 0, 0, 0);
2007 // cdImageColorAllocate(im, 0, 0, 0);
2008 // cdImageColorAllocate(im, 0, 0, 0);
2009 //
2010  int si, ei, li;
2011  si = cdImageAddColorIndex( im, 255, 255, 255 );
2012  if ( si == -1 )
2013  return 0;
2014  li = -1; ei = si;
2015  ei = cdImageAddColorIndex( im, 0, 0, 0 );
2016  if ( ei != -1 )
2017  {
2018  li = ei;
2019  }
2020  ei = cdImageAddColorIndex( im, 128, 0, 0 );
2021  if ( ei != -1 )
2022  {
2023  li = ei;
2024  }
2025  ei = cdImageAddColorIndex( im, 0, 128, 0 );
2026  if ( ei != -1 )
2027  {
2028  li = ei;
2029  }
2030  ei = cdImageAddColorIndex( im, 128, 128, 0 );
2031  if ( ei != -1 )
2032  {
2033  li = ei;
2034  }
2035  ei = cdImageAddColorIndex( im, 0, 0, 128 );
2036  if ( ei != -1 )
2037  {
2038  li = ei;
2039  }
2040  ei = cdImageAddColorIndex( im, 128, 0, 128 );
2041  if ( ei != -1 )
2042  {
2043  li = ei;
2044  }
2045  ei = cdImageAddColorIndex( im, 0, 128, 128 );
2046  if ( ei != -1 )
2047  {
2048  li = ei;
2049  }
2050  ei = cdImageAddColorIndex( im, 128, 128, 128 );
2051  if ( ei != -1 )
2052  {
2053  li = ei;
2054  }
2055  ei = cdImageAddColorIndex( im, 192, 192, 192 );
2056  if ( ei != -1 )
2057  {
2058  li = ei;
2059  }
2060  ei = cdImageAddColorIndex( im, 255, 0, 0 );
2061  if ( ei != -1 )
2062  {
2063  li = ei;
2064  }
2065  ei = cdImageAddColorIndex( im, 0, 255, 0 );
2066  if ( ei != -1 )
2067  {
2068  li = ei;
2069  }
2070  ei = cdImageAddColorIndex( im, 255, 255, 0 );
2071  if ( ei != -1 )
2072  {
2073  li = ei;
2074  }
2075  ei = cdImageAddColorIndex( im, 0, 0, 255 );
2076  if ( ei != -1 )
2077  {
2078  li = ei;
2079  }
2080  ei = cdImageAddColorIndex( im, 255, 0, 255 );
2081  if ( ei != -1 )
2082  {
2083  li = ei;
2084  }
2085  ei = cdImageAddColorIndex( im, 0, 255, 255 );
2086  if ( ei != -1 )
2087  {
2088  li = ei;
2089  }
2090 
2091  if ( ei == -1 )
2092  {
2093  ei = li;
2094  }
2095  if ( cdImageAddColor( im, si, ei ) == -1 )
2096  {
2097  return -1;
2098  }
2099  else
2100  {
2101  return ei;
2102  }
2103 }
2105 // wogl: the parameter names are commented to avoid compiler warnings
2106 // From gd library, see README file for copyright information
2107 // gej: should work unchanged
2108 {
2109  // Mark it open.
2110  //im->open[color] = 1;
2111  // gej: really can't work, we are not allowing redefinition
2112  // of color table entries
2113  return 0;
2114 }
2115 
2116 int cdLine( cdImagePtr im, int x1, int y1, int x2, int y2 )
2117 // Graphic Primitive: Polyline; Elem Class 4; Elem ID 1
2118 // Actually generate the line, if you are writing a program to use this
2119 // library, use this function, not cdImageLine or cdImageDashedLine,
2120 // those are just in for compatiblilty with gd
2121 //
2122 // This function will draw a line using the current line type, width, and color
2123 //
2124 {
2125  unsigned char *es, *esp;
2126  int octet_count;
2127  short int sweet;
2128  short int sour;
2129 
2130  // check to make sure the line is withing the scope of the picture
2131  // ie. the values you give for drawing the line are within
2132  // the values you created the picture with
2133  if ( !( cdImageBoundsSafe( im, x1, y1 ) ) || !( cdImageBoundsSafe( im, x2, y2 ) ) )
2134  return 0;
2135 
2136  // allocate sufficent space. should be 32 bits * 4 to be safe
2137  es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
2138  if ( !es )
2139  return 0; // memory allocation failed
2140  esp = es;
2141 
2142  if ( !cdcomhead( es, 4, 1, 8 ) )
2143  {
2144  free( esp ); return 0;
2145  }
2146  es += 2;
2147  octet_count = 2;
2148 
2149  // now we are ready for the parameter data
2150  sweet = (short int) x1;
2151  sour = sweet >> 8;
2152  *es = *es | ( sour & 0377 );
2153  es++; octet_count++;
2154  *es = (unsigned char) sweet;
2155  es++; octet_count++;
2156  sweet = (short int) y1;
2157  sour = sweet >> 8;
2158  *es = *es | ( sour & 0377 );
2159  es++; octet_count++;
2160  *es = (unsigned char) sweet;
2161  es++; octet_count++;
2162  sweet = (short int) x2;
2163  sour = sweet >> 8;
2164  *es = *es | ( sour & 0377 );
2165  es++; octet_count++;
2166  *es = (unsigned char) sweet;
2167  es++; octet_count++;
2168  sweet = (short int) y2;
2169  sour = sweet >> 8;
2170  *es = *es | ( sour & 0377 );
2171  es++; octet_count++;
2172  *es = (unsigned char) sweet;
2173  octet_count++;
2174 
2175  // add it to the buffer
2176  if ( cdAddElem( im, esp, octet_count ) )
2177  {
2178  free( esp );
2179  return 1;
2180  }
2181  else
2182  {
2183  free( esp );
2184  return 0;
2185  }
2186 }
2187 
2188 int cdMarker( cdImagePtr im, int x, int y )
2189 // Graphic Primitive: PolyMarker; Elem Class 4; Elem ID 3
2190 // puts a marker in the file, it will have characteristics set by
2191 // cdSetMarkerAttrib
2192 //
2193 {
2194  unsigned char *es, *esp;
2195  int octet_count;
2196 
2197  // check to make sure the line is withing the scope of the picture
2198  // ie. the values you give for drawing the line are within
2199  // the values you created the picture with
2200  if ( !cdImageBoundsSafe( im, x, y ) )
2201  return 0;
2202 
2203  // allocate sufficent space. should be 32 bits * 4 to be safe
2204  es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
2205  if ( !es )
2206  return 0; // memory allocation failed
2207  esp = es;
2208 
2209  if ( !cdcomhead( es, 4, 3, 4 ) )
2210  {
2211  free( esp ); return 0;
2212  }
2213  es += 2;
2214  octet_count = 2;
2215 
2216  octet_count += cdAppShort( es, (short int) x );
2217  es += 2;
2218  octet_count += cdAppShort( es, (short int) y );
2219  es += 2;
2220 
2221  // add it to the buffer
2222  if ( cdAddElem( im, esp, octet_count ) )
2223  {
2224  free( esp );
2225  return 1;
2226  }
2227  else
2228  {
2229  free( esp );
2230  return 0;
2231  }
2232 }
2233 
2234 
2235 int cdRectangle( cdImagePtr im, int x1, int y1, int x2, int y2 )
2236 {
2237 // Graphic Primitive: rectangle; Elem Class 4; Elem ID 11
2238 // Actually generate the rectangle, if you are writing a program to use this
2239 // library, use this function, not cdImageRectangle,
2240 // those are just in for compatiblilty with gd
2241 //
2242 // This function will draw a Rectangle using the current
2243 // edge type, width, color, and visibility, and the current
2244 // fill style, color, and hatch
2245 //
2246  unsigned char *es, *esp;
2247  int octet_count;
2248  short int sweet;
2249  short int sour;
2250 
2251  // check to make sure the line is withing the scope of the picture
2252  // ie. the values you give for drawing the line are within
2253  // the values you created the picture with
2254  if ( !( cdImageBoundsSafe( im, x1, y1 ) ) || !( cdImageBoundsSafe( im, x2, y2 ) ) )
2255  return 0;
2256 
2257  // allocate sufficent space. should be 32 bits * 4 to be safe
2258  es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
2259  if ( !es )
2260  return 0; // memory allocation failed
2261  esp = es;
2262 
2263  // their are four 16 bit signed integers as attributes
2264  if ( !cdcomhead( es, 4, 11, 8 ) )
2265  {
2266  free( esp ); return 0;
2267  }
2268  es += 2; octet_count = 2;
2269 
2270  // now we are ready for the parameter data
2271  sweet = (short int) x1;
2272  sour = sweet >> 8;
2273  *es = *es | ( sour & 0377 );
2274  es++; octet_count++;
2275  *es = (unsigned char) sweet;
2276  es++; octet_count++;
2277  sweet = (short int) y1;
2278  sour = sweet >> 8;
2279  *es = *es | ( sour & 0377 );
2280  es++; octet_count++;
2281  *es = (unsigned char) sweet;
2282  es++; octet_count++;
2283  sweet = (short int) x2;
2284  sour = sweet >> 8;
2285  *es = *es | ( sour & 0377 );
2286  es++; octet_count++;
2287  *es = (unsigned char) sweet;
2288  es++; octet_count++;
2289  sweet = (short int) y2;
2290  sour = sweet >> 8;
2291  *es = *es | ( sour & 0377 );
2292  es++; octet_count++;
2293  *es = (unsigned char) sweet;
2294  octet_count++;
2295 
2296  // add it to the buffer
2297  if ( cdAddElem( im, esp, octet_count ) )
2298  {
2299  free( esp );
2300  return 1;
2301  }
2302  else
2303  {
2304  free( esp );
2305  return 0;
2306  }
2307 }
2308 
2309 int cdCircle( cdImagePtr im, int cx, int cy, int r )
2310 {
2311 // Graphic Primitive: circle; Elem Class 4; Elem ID 12
2312 // cx,cy is the center of the circle, r is the radius
2313 //
2314 // This function will draw a Circle using the current
2315 // edge type, width, color, and visibility, and the current
2316 // fill style, color, and hatch
2317 //
2318  unsigned char *es, *esp;
2319  int octet_count;
2320  short int sweet;
2321  short int sour;
2322 
2323  // check to make sure the circle is withing the scope of the picture
2324  // ie. the values you give for drawing the circle are within
2325  // the values you created the picture with
2326  if ( !( cdImageBoundsSafe( im, cx, cy ) ) )
2327  return 0;
2328 
2329  // allocate sufficent space. should be 32 bits * 4 to be safe
2330  es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
2331  if ( !es )
2332  return 0; // memory allocation failed
2333  esp = es;
2334 
2335  // their are three 16 bit signed integers as attributes
2336  if ( !cdcomhead( es, 4, 12, 6 ) )
2337  {
2338  free( esp ); return 0;
2339  }
2340  es += 2; octet_count = 2;
2341 
2342  // now we are ready for the parameter data
2343  sweet = (short int) cx;
2344  sour = sweet >> 8;
2345  *es = *es | ( sour & 0377 );
2346  es++; octet_count++;
2347  *es = (unsigned char) sweet;
2348  es++; octet_count++;
2349  sweet = (short int) cy;
2350  sour = sweet >> 8;
2351  *es = *es | ( sour & 0377 );
2352  es++; octet_count++;
2353  *es = (unsigned char) sweet;
2354  es++; octet_count++;
2355  sweet = (short int) r;
2356  sour = sweet >> 8;
2357  *es = *es | ( sour & 0377 );
2358  es++; octet_count++;
2359  *es = (unsigned char) sweet;
2360  octet_count++;
2361 
2362 
2363  // add it to the buffer
2364  if ( cdAddElem( im, esp, octet_count ) )
2365  {
2366  free( esp );
2367  return 1;
2368  }
2369  else
2370  {
2371  free( esp );
2372  return 0;
2373  }
2374 }
2375 
2376 int cdArc3Pt( cdImagePtr im, int sx, int sy, int ix, int iy, int ex, int ey )
2377 {
2378 // Graphic Primitive: Cicular Arc 3 Point; Elem Class 4; Elem ID 13
2379 //
2380 // This function will draw a Circular Arc using the current
2381 // Line type, width, and color,
2382 //
2383  unsigned char *es, *esp;
2384  int octet_count;
2385  short int sweet;
2386  short int sour;
2387 
2388  // check to make sure the line is withing the scope of the picture
2389  // ie. the values you give for drawing the line are within
2390  // the values you created the picture with
2391  if ( !( cdImageBoundsSafe( im, sx, sy ) ) || !( cdImageBoundsSafe( im, ix, iy ) ) || !( cdImageBoundsSafe( im, ex, ey ) ) )
2392  return 0;
2393 
2394  // allocate sufficent space. should be 32 bits * 4 to be safe
2395  es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
2396  if ( !es )
2397  return 0; // memory allocation failed
2398  esp = es;
2399 
2400  // their are six 16 bit signed integers as attributes
2401  if ( !cdcomhead( es, 4, 13, 12 ) )
2402  {
2403  free( esp ); return 0;
2404  }
2405  es += 2; octet_count = 2;
2406 
2407  // now we are ready for the parameter data
2408  sweet = (short int) sx;
2409  sour = sweet >> 8;
2410  *es = *es | ( sour & 0377 );
2411  es++; octet_count++;
2412  *es = (unsigned char) sweet;
2413  es++; octet_count++;
2414  sweet = (short int) sy;
2415  sour = sweet >> 8;
2416  *es = *es | ( sour & 0377 );
2417  es++; octet_count++;
2418  *es = (unsigned char) sweet;
2419  es++; octet_count++;
2420  sweet = (short int) ix;
2421  sour = sweet >> 8;
2422  *es = *es | ( sour & 0377 );
2423  es++; octet_count++;
2424  *es = (unsigned char) sweet;
2425  es++; octet_count++;
2426  sweet = (short int) iy;
2427  sour = sweet >> 8;
2428  *es = *es | ( sour & 0377 );
2429  es++; octet_count++;
2430  *es = (unsigned char) sweet;
2431  es++; octet_count++;
2432  sweet = (short int) ex;
2433  sour = sweet >> 8;
2434  *es = *es | ( sour & 0377 );
2435  es++; octet_count++;
2436  *es = (unsigned char) sweet;
2437  es++; octet_count++;
2438  sweet = (short int) ey;
2439  sour = sweet >> 8;
2440  *es = *es | ( sour & 0377 );
2441  es++; octet_count++;
2442  *es = (unsigned char) sweet;
2443  octet_count++;
2444 
2445  // add it to the buffer
2446  if ( cdAddElem( im, esp, octet_count ) )
2447  {
2448  free( esp );
2449  return 1;
2450  }
2451  else
2452  {
2453  free( esp );
2454  return 0;
2455  }
2456 }
2457 
2458 int cdArc3PtClose( cdImagePtr im, int sx, int sy, int ix, int iy, int ex, int ey, int cl )
2459 {
2460 // Graphic Primitive: Cicular Arc 3 Point Close; Elem Class 4; Elem ID 14
2461 //
2462 // This function will draw a Circle using the current
2463 // edge type, width, color, and visibility, and the current
2464 // fill style, color, and hatch
2465 //
2466 // cd is the closure type. It can be either 0 for pie closure or
2467 // 1 for chord closure.
2468 //
2469  unsigned char *es, *esp;
2470  int octet_count;
2471 
2472  // check to make sure the line is withing the scope of the picture
2473  // ie. the values you give for drawing the line are within
2474  // the values you created the picture with
2475  if ( !( cdImageBoundsSafe( im, sx, sy ) ) || !( cdImageBoundsSafe( im, ix, iy ) ) || !( cdImageBoundsSafe( im, ex, ey ) ) )
2476  return 0;
2477 
2478  // make sure that they close the arc either with pie (0) or chord (1)
2479  if ( ( cl != 0 ) && ( cl != 1 ) )
2480  return 0;
2481 
2482  // allocate sufficent space. should be 32 bits * 6 to be safe
2483  es = (unsigned char *) calloc( 4 * 6, SIZEOF( unsigned char ) );
2484  if ( !es )
2485  return 0; // memory allocation failed
2486  esp = es;
2487 
2488  // their are seven 16 bit signed integers as attributes
2489  if ( !cdcomhead( es, 4, 14, 14 ) )
2490  {
2491  free( esp ); return 0;
2492  }
2493  es += 2; octet_count = 2;
2494 
2495  // now we are ready for the parameter data
2496  octet_count += cdAppShort( es, (short int) sx );
2497  es += 2;
2498  octet_count += cdAppShort( es, (short int) sy );
2499  es += 2;
2500  octet_count += cdAppShort( es, (short int) ix );
2501  es += 2;
2502  octet_count += cdAppShort( es, (short int) iy );
2503  es += 2;
2504  octet_count += cdAppShort( es, (short int) ex );
2505  es += 2;
2506  octet_count += cdAppShort( es, (short int) ey );
2507  es += 2;
2508  octet_count += cdAppShort( es, (short int) cl );
2509  es += 2;
2510 
2511  // add it to the buffer
2512  if ( cdAddElem( im, esp, octet_count ) )
2513  {
2514  free( esp );
2515  return 1;
2516  }
2517  else
2518  {
2519  free( esp );
2520  return 0;
2521  }
2522 }
2523 
2524 int cdEllipse( cdImagePtr im, int cx, int cy, int d1x, int d1y, int d2x, int d2y )
2525 {
2526 // Graphic Primitive: Ellipse; Elem Class 4; Elem ID 17
2527 //
2528 // This function will draw an Ellipse using the current
2529 // edge type, width, color, and visibility, and the current
2530 // fill style, color, and hatch
2531 //
2532  unsigned char *es, *esp;
2533  int octet_count;
2534 
2535  // check to make sure the line is withing the scope of the picture
2536  // ie. the values you give for drawing the line are within
2537  // the values you created the picture with
2538  if ( !( cdImageBoundsSafe( im, cx, cy ) ) || !( cdImageBoundsSafe( im, d1x, d1y ) ) || !( cdImageBoundsSafe( im, d2x, d2y ) ) )
2539  return 0;
2540 
2541  // allocate sufficent space. should be 32 bits * 4 to be safe
2542  es = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
2543  if ( !es )
2544  return 0; // memory allocation failed
2545  esp = es;
2546 
2547  // their are six 16 bit signed integers as attributes
2548  if ( !cdcomhead( es, 4, 17, 12 ) )
2549  {
2550  free( esp ); return 0;
2551  }
2552  es += 2; octet_count = 2;
2553 
2554  // now we are ready for the parameter data
2555  octet_count += cdAppShort( es, (short int) cx );
2556  es += 2;
2557  octet_count += cdAppShort( es, (short int) cy );
2558  es += 2;
2559  octet_count += cdAppShort( es, (short int) d1x );
2560  es += 2;
2561  octet_count += cdAppShort( es, (short int) d1y );
2562  es += 2;
2563  octet_count += cdAppShort( es, (short int) d2x );
2564  es += 2;
2565  octet_count += cdAppShort( es, (short int) d2y );
2566  es += 2;
2567 
2568  // add it to the buffer
2569  if ( cdAddElem( im, esp, octet_count ) )
2570  {
2571  free( esp );
2572  return 1;
2573  }
2574  else
2575  {
2576  free( esp );
2577  return 0;
2578  }
2579 }
2580 
2581 int cdPolygon( cdImagePtr im, cdPointPtr p, int n )
2582 {
2583 // Graphic Primitive: Polygon; Elem Class 4; Elem ID 7
2584 //
2585 // cdPointPtr is defined in cd.h, basically, it is two arrays of integers
2586 // p[m].x and p[m].y containing the x and y values respectively. n
2587 // is the number of points in this array (not the index of the last point,
2588 // which is n-1). n must be at least 3 (otherwise
2589 // you really don't have much of a polygon, it is closer to a line.)
2590 //
2591 // This function will draw a Polygon using the current
2592 // edge type, width, color, and visibility, and the current
2593 // fill style, color, and hatch
2594 //
2595  unsigned char *es, *esp;
2596  int octet_count;
2597  int x; // counter
2598 
2599  if ( n < 3 )
2600  return 0; // it is either a point or a line
2601 
2602  if ( n < 8 )
2603  {
2604  // It fits in the short form of the command, lets us
2605  // add it right now, shall we?
2606  // allocate sufficent space. Should be 32 bits*10 to be safe
2607  es = (unsigned char *) calloc( 4 * 10, SIZEOF( unsigned char ) );
2608  if ( !es )
2609  return 0; // memory allocation failed
2610  esp = es;
2611 
2612 
2613  // their are n*2 16 bit signed integers as attributes
2614  if ( !cdcomhead( es, 4, 7, ( n * 4 ) ) )
2615  {
2616  free( esp ); return 0;
2617  }
2618  es += 2; octet_count = 2;
2619  }
2620  else if ( n < 8191 )
2621  {
2622  // there are more than 7 points in it, that sucks
2623  // gej, so basically, for this one, I set the header
2624  // to cdcomhead(es, 4, 7, 31) then write a function for the long
2625  // form that takes the first 15 bits of n and tags a 0 in front
2626  // of it and puts it in es, than I do the for loop all over again
2627  // that doesn't seem too hard. But I will leave that for another
2628  // day.
2629  //
2630  // keep in mind that if CDGROWLISTSIZE is smaller than n*4
2631  // (at most 32769) then things could fail in a most unsavory fashion.
2632  //
2633  // allocate sufficent space. 32 bits*(n+1) to be safe
2634  es = (unsigned char *) calloc( 4 * ( n + 1 ), SIZEOF( unsigned char ) );
2635  if ( !es )
2636  return 0; // memory allocation failed
2637  esp = es;
2638 
2639  if ( !cdcomheadlong( es, 4, 7, ( n * 4 ) ) )
2640  {
2641  free( esp ); return 0;
2642  }
2643  es += 4; octet_count = 4;
2644  }
2645  else
2646  {
2647  // there are more than 8191 points in it, I am not going to implement
2648  // that, if you want it that bad, do it yourself.
2649  return 0;
2650  }
2651 
2652 
2653  for ( x = 0; x < n; x++ )
2654  {
2655  // now we are ready for the parameter data
2656  es += cdAppShort( es, (short int) p->x );
2657  es += cdAppShort( es, (short int) p->y );
2658  octet_count += 4;
2659  p++;
2660  }
2661 
2662  // add it to the buffer
2663  if ( cdAddElem( im, esp, octet_count ) )
2664  {
2665  free( esp );
2666  return 1;
2667  }
2668  else
2669  {
2670  free( esp );
2671  return 0;
2672  }
2673 }
2674 
2676 {
2677 // Graphic Primitive: Polygon; Elem Class 4; Elem ID 8
2678 //
2679 // cdPointPtr is defined in cd.h, basically, it is three arrays of integers
2680 // p[m].x and p[m].y containing the x and y values respectively and p[m].e
2681 // the characteristics of the line leaving point n (0=invisible,1=visible,
2682 // 2=close,invisible, 3=close,visible). n is the number of points in this
2683 // array (not the index of the last point, which is n-1).
2684 // n must be at least 3 (otherwise you really don't have much of a polygon,
2685 // it is closer to a line.)
2686 //
2687 // This function will draw a set of Polygons using the current
2688 // edge type, width, color, and the current
2689 // fill style, color, and hatch
2690 //
2691  unsigned char *es, *esp;
2692  int octet_count;
2693  int x; // counter
2694 
2695  if ( n < 3 )
2696  return 0; // it is either a point or a line
2697 
2698  if ( n < 6 )
2699  {
2700  // It fits in the short form of the command, lets us
2701  // add it right now, shall we?
2702  // allocate sufficent space. Should be 48 bits*10 to be safe
2703  es = (unsigned char *) calloc( 6 * 10, SIZEOF( unsigned char ) );
2704  if ( !es )
2705  return 0; // memory allocation failed
2706  esp = es;
2707 
2708 
2709  // their are n*2 16 bit signed integers as attributes
2710  if ( !cdcomhead( es, 4, 8, ( n * 6 ) ) )
2711  {
2712  free( esp ); return 0;
2713  }
2714  es += 2; octet_count = 2;
2715  }
2716  else if ( n < 5462 )
2717  {
2718  // there are more than 5 points in it, that sucks
2719  // gej, so basically, for this one, I set the header
2720  // to cdcomhead(es, 4, 7, 31) then write a function for the long
2721  // form that takes the first 15 bits of n and tags a 0 in front
2722  // of it and puts it in es, than I do the for loop all over again
2723  // that doesn't seem too hard. But I will leave that for another
2724  // day.
2725  //
2726  // keep in mind that if CDGROWLISTSIZE is smaller than n*6
2727  // (at most 32769) then things could fail in a most unsavory fashion.
2728  //
2729  // allocate sufficent space. 48 bits*(n+1) to be safe
2730  es = (unsigned char *) calloc( 6 * ( n + 1 ), SIZEOF( unsigned char ) );
2731  if ( !es )
2732  return 0; // memory allocation failed
2733  esp = es;
2734 
2735  if ( !cdcomheadlong( es, 4, 8, ( n * 6 ) ) )
2736  {
2737  free( esp ); return 0;
2738  }
2739  es += 4; octet_count = 4;
2740  }
2741  else
2742  {
2743  // there are more than 5462 points in it, I am not going to implement
2744  // that, if you want it that bad, do it yourself.
2745  return 0;
2746  }
2747 
2748 
2749  for ( x = 0; x < n; x++ )
2750  {
2751  // now we are ready for the parameter data
2752  es += cdAppShort( es, (short int) p->x );
2753  es += cdAppShort( es, (short int) p->y );
2754  es += cdAppShort( es, (short int) p->e );
2755  octet_count += 6;
2756  p++;
2757  }
2758 
2759  // add it to the buffer
2760  if ( cdAddElem( im, esp, octet_count ) )
2761  {
2762  free( esp );
2763  return 1;
2764  }
2765  else
2766  {
2767  free( esp );
2768  return 0;
2769  }
2770 }
2771 
2772 int cdPolyLine( cdImagePtr im, cdPointPtr p, int n )
2773 {
2774 // Graphic Primitive: Polyline; Elem Class 4; Elem ID 1
2775 //
2776 // cdPointPtr is defined in cd.h, basically, it is two arrays of integers
2777 // p[m].x and p[m].y containing the x and y values respectively. n
2778 // is the number of points in this array (not the index of the last point,
2779 // which is n-1). if n is 2, it is a regular line, like cdline
2780 //
2781 // This function will draw a Polyline using the current
2782 // line type, width, color, and visibility,
2783 //
2784  unsigned char *es, *esp;
2785  int octet_count;
2786  int x; // counter
2787 
2788  if ( n < 2 )
2789  return 0; // it is a point
2790 
2791  if ( n < 8 )
2792  {
2793  // It fits in the short form of the command, lets us
2794  // add it right now, shall we?
2795  // allocate sufficent space. Should be 32 bits*10 to be safe
2796  es = (unsigned char *) calloc( 4 * 10, SIZEOF( unsigned char ) );
2797  if ( !es )
2798  return 0; // memory allocation failed
2799  esp = es;
2800 
2801 
2802  // their are n*2 16 bit signed integers as attributes
2803  if ( !cdcomhead( es, 4, 1, ( n * 4 ) ) )
2804  {
2805  free( esp ); return 0;
2806  }
2807  es += 2; octet_count = 2;
2808  }
2809  else if ( n < 8191 )
2810  {
2811  // there are more than 7 points in it, that sucks
2812  // gej, so basically, for this one, I set the header
2813  // using the long version cdcomheadlong(es, 4, 1, n*4)
2814  //
2815  // keep in mind that if CDGROWLISTSIZE is smaller than n*4
2816  // (at most 32769) then the list may have to grow several times
2817  //
2818  // allocate sufficent space. 32 bits*(n+1) to be safe
2819  es = (unsigned char *) calloc( 4 * ( n + 1 ), SIZEOF( unsigned char ) );
2820  if ( !es )
2821  return 0; // memory allocation failed
2822  esp = es;
2823 
2824  if ( !cdcomheadlong( es, 4, 1, ( n * 4 ) ) )
2825  {
2826  free( esp ); return 0;
2827  }
2828  es += 4; octet_count = 4;
2829  }
2830  else
2831  {
2832  // there are more than 8191 points in it, I am not going to implement
2833  // that, if you want it that bad, do it yourself.
2834  return 0;
2835  }
2836 
2837  for ( x = 0; x < n; x++ )
2838  {
2839  // now we are ready for the parameter data
2840  es += cdAppShort( es, (short int) p->x );
2841  es += cdAppShort( es, (short int) p->y );
2842  octet_count += 4;
2843  p++;
2844  }
2845 
2846  // add it to the buffer
2847  if ( cdAddElem( im, esp, octet_count ) )
2848  {
2849  free( esp );
2850  return 1;
2851  }
2852  else
2853  {
2854  free( esp );
2855  return 0;
2856  }
2857 }
2858 
2860 {
2861 // Graphic Primitive: PolyMarker; Elem Class 4; Elem ID 3
2862 //
2863 // cdPointPtr is defined in cd.h, basically, it is two arrays of integers
2864 // p[m].x and p[m].y containing the x and y values respectively. n
2865 // is the number of points in this array (not the index of the last point,
2866 // which is n-1). if n is 2, it is a regular line, like cdline
2867 //
2868 // This function will insert n markers using the current
2869 // Marker type, width, color, and visibility,
2870 //
2871  unsigned char *es, *esp;
2872  int octet_count;
2873  int x; // counter
2874 
2875  if ( n < 1 )
2876  return 0; // it is nothing
2877  if ( n < 8 )
2878  {
2879  // It fits in the short form of the command, lets us
2880  // add it right now, shall we?
2881  // allocate sufficent space. Should be 32 bits*10 to be safe
2882  es = (unsigned char *) calloc( 4 * 10, SIZEOF( unsigned char ) );
2883  if ( !es )
2884  return 0; // memory allocation failed
2885  esp = es;
2886 
2887 
2888  // their are n*2 16 bit signed integers as attributes
2889  if ( !cdcomhead( es, 4, 3, ( n * 4 ) ) )
2890  {
2891  free( esp ); return 0;
2892  }
2893  es += 2; octet_count = 2;
2894  }
2895  else if ( n < 8191 )
2896  {
2897  // there are more than 7 points in it, that sucks
2898  // gej, so basically, for this one, I set the header
2899  // using the long version cdcomheadlong(es, 4, 1, n*4)
2900  //
2901  // keep in mind that if CDGROWLISTSIZE is smaller than n*4
2902  // (at most 32769) then the list may have to grow several times
2903  //
2904  // allocate sufficent space. 32 bits*(n+1) to be safe
2905  es = (unsigned char *) calloc( 4 * ( n + 1 ), SIZEOF( unsigned char ) );
2906  if ( !es )
2907  return 0; // memory allocation failed
2908  esp = es;
2909 
2910  if ( !cdcomheadlong( es, 4, 3, ( n * 4 ) ) )
2911  {
2912  free( esp ); return 0;
2913  }
2914  es += 4; octet_count = 4;
2915  }
2916  else
2917  {
2918  // there are more than 8191 points in it, I am not going to implement
2919  // that, if you want it that bad, do it yourself.
2920  return 0;
2921  }
2922 
2923  for ( x = 0; x < n; x++ )
2924  {
2925  // now we are ready for the parameter data
2926  es += cdAppShort( es, (short int) p->x );
2927  es += cdAppShort( es, (short int) p->y );
2928  octet_count += 4;
2929  p++;
2930  }
2931 
2932  // add it to the buffer
2933  if ( cdAddElem( im, esp, octet_count ) )
2934  {
2935  free( esp );
2936  return 1;
2937  }
2938  else
2939  {
2940  free( esp );
2941  return 0;
2942  }
2943 }
2944 
2945 int cdText( cdImagePtr im, int x, int y, const char *ts )
2946 {
2947 // Graphic Primitive: Text; Elem Class 4; Elem ID 4
2948 // add text to the picture. Start it at the point (x,y)
2949 // this should be the lower left corner of where the text is
2950 // the parameters are point, enumerated(set to 1), string
2951 //
2952 // String encoding in CGM is a little strange. After you have the other
2953 // parameter info, the first octet for the string is either 0..254 which
2954 // is the number of octets of string data, or 255 which signifies a long
2955 // string. if it is 255 then the next 16 bits indicate the length of the
2956 // string. the first bit (bit15) is 0 if this is the last part of the
2957 // string and 1 if another part follows it. the next 15 bits are in the
2958 // range 0..32767 and are the number of octets of string info following.
2959 // so the length stored in the command header is the whole enchelada.
2960 //
2961  int tslen, curly;
2962  unsigned char *es, *esp;
2963  int octet_count;
2964 
2965  // check to make sure the Text is within the scope of the picture
2966  // actually, I am only checking the start of it
2967  //
2968  if ( !( cdImageBoundsSafe( im, x, y ) ) )
2969  return 0;
2970 
2971  // allocate sufficent space. should be tslen+ 32 bits * 4 to be safe
2972  tslen = strlen( ts );
2973 
2974  // if there are more than 32700 characters fail
2975  // gej: this could go as high as 32767 I think, but lets
2976  // cut it off at 32700
2977  if ( ( tslen > 32700 ) || ( tslen < 0 ) )
2978  return 0;
2979 
2980  es = (unsigned char *) calloc( ( ( 4 * 4 ) + tslen ), SIZEOF( unsigned char ) );
2981  if ( !es )
2982  return 0; // memory allocation failed
2983  esp = es;
2984 
2985  if ( !cdcomheadlong( es, 4, 4, 9 + tslen ) )
2986  {
2987  free( esp ); return 0;
2988  }
2989  es += 4; octet_count = 4;
2990 
2991  // add the x position, the y position, then 1, which signifies
2992  // that this is all the text, there is none appended after it
2993  es += cdAppShort( es, (short int) x );
2994  es += cdAppShort( es, (short int) y );
2995  es += cdAppShort( es, (short int) 1 );
2996  octet_count += 6;
2997 
2998  // now take care of the string information, for strings 254 bytes
2999  // or less, I could use a short one, but why bother, use the long
3000  // form for everything
3001  es += cdAppByte( es, (short int) 255 );
3002  es += cdAppShort( es, (short int) tslen );
3003  octet_count += 3;
3004  // gej: I should set bit 15 to 0 because it is the final part of a
3005  // string but I am not going to since I already checked that it was
3006  // a 16 number that was non-negative
3007 
3008  while ( *ts )
3009  {
3010  *es++ = (unsigned char) *ts++;
3011  }
3012  octet_count += tslen;
3013  // now if the octet_count is not divisible by 4 add null padding
3014  curly = 4 - ( octet_count % 4 );
3015  if ( curly % 4 )
3016  {
3017  octet_count += curly;
3018  es += cdAppNull( es, curly );
3019  }
3020 
3021  // add it to the buffer
3022  if ( cdAddElem( im, esp, octet_count ) )
3023  {
3024  free( esp );
3025  return 1;
3026  }
3027  else
3028  {
3029  free( esp );
3030  return 0;
3031  }
3032 }
3033 
3034 int cdImageLine( cdImagePtr im, int x1, int y1, int x2, int y2, int color )
3035 // gej: this should be so much easier to do as a cgm
3036 // This is in for compatibility with gd, if you don't need that, use
3037 // cdLine instead
3038 {
3039  int ltstate;
3040 
3041 
3042  // save the linetype state
3043  ltstate = im->ltype;
3044  // set the attributes of the line
3045  if ( !cdSetLineAttrib( im, 1, -1, color ) )
3046  return 0;
3047  if ( !cdLine( im, x1, y1, x2, y2 ) )
3048  return 0; // draw the line
3049  // restore the state If it fails, don't return an error, because
3050  // the line was still drawn
3051  cdSetLineType( im, ltstate );
3052 
3053  return 1;
3054 }
3055 
3056 int cdImageDashedLine( cdImagePtr im, int x1, int y1, int x2, int y2, int color )
3057 // gej: this should be so much easier to do as a cgm
3058 // in order to really get a dashed line you must call cdSetLineType first
3059 // This is in for compatibility with gd, if you don't need that, use
3060 // cdLine instead
3061 {
3062  // set the attributes of the line
3063  if ( !cdSetLineAttrib( im, -1, -1, color ) )
3064  return 0;
3065  // generate the line
3066  if ( !cdLine( im, x1, y1, x2, y2 ) )
3067  return 0;
3068 
3069  // everthing is A-OK
3070  return 1;
3071 }
3072 
3073 int cdImageBoundsSafe( cdImagePtr im, int x, int y )
3074 // From gd library, see README file for copyright information
3075 // gej: this should work unchanged
3076 {
3077  return ( !( ( ( y < 0 ) || ( y >= im->sy ) ) ||
3078  ( ( x < 0 ) || ( x >= im->sx ) ) ) );
3079 }
3080 
3081 
3082 int cdImageRectangle( cdImagePtr im, int x1, int y1, int x2, int y2, int color )
3083 // Graphic Primitive: rectangle; Elem Class 4; Elem ID 11
3084 //
3085 
3086 // gej: but I think I will use the cgm rectangle
3087 {
3088  if ( !cdImageLine( im, x1, y1, x2, y1, color ) )
3089  return 0;
3090  if ( !cdImageLine( im, x1, y2, x2, y2, color ) )
3091  return 0;
3092  if ( !cdImageLine( im, x1, y1, x1, y2, color ) )
3093  return 0;
3094  if ( !cdImageLine( im, x2, y1, x2, y2, color ) )
3095  return 0;
3096 
3097  return 1;
3098 }
3099 
3100 
3101 // Expert functions. If you need more control, you can use these
3102 // functions, but you probably won't need to.
3103 
3104 int cdImageSetSize( cdImagePtr im, int x, int y )
3105 // sets the width and height of subsequent pictures.
3106 {
3107  im->sx = x;
3108  im->sy = y;
3109  return 1;
3110 }
3111 
3112 int cdImageSetLineSpec( cdImagePtr im, int specmode )
3113 // Picture Descriptor: Line Width Specification Mode; Elem Class 2; Elem ID 3
3114 // sets the Line Width Specification mode of subsequent pictures.
3115 // 1 is scaled (default), 2 is absolute
3116 {
3117  if ( ( specmode < 0 ) || ( specmode > 2 ) )
3118  return 0;
3119  im->linespec = specmode;
3120  return 1;
3121 }
3122 
3123 int cdImageSetMarkerSpec( cdImagePtr im, int specmode )
3124 // Picture Descriptor: Marker Size Specification Mode; Elem Class 2; Elem ID 4
3125 // sets the Marker Width Specification mode of subsequent pictures.
3126 // 1 is scaled (default), 2 is absolute
3127 {
3128  if ( ( specmode < 0 ) || ( specmode > 2 ) )
3129  return 0;
3130  im->linespec = specmode;
3131  return 1;
3132 }
3133 
3134 int cdImageSetEdgeSpec( cdImagePtr im, int specmode )
3135 // Picture Descriptor: Edge Width Specification Mode; Elem Class 2; Elem ID 5
3136 // sets the Edge Width Specification mode of subsequent pictures.
3137 // 1 is scaled (default), 2 is absolute
3138 {
3139  if ( ( specmode < 0 ) || ( specmode > 2 ) )
3140  return 0;
3141  im->edgespec = specmode;
3142  return 1;
3143 }
3144 
3145 int cdImageSetOutput( cdImagePtr im, FILE *output )
3146 // sets the output file to *output. which must already be open.
3147 // does not close the file
3148 // Useful if you want to write the file as you go along, or if you
3149 // want to write it to a stream
3150 //
3151 {
3152  if ( output )
3153  {
3154  im->outfile = output;
3155  return 1;
3156  }
3157  else
3158  {
3159  return 0;
3160  }
3161 }
3162 
3163 int cdImageAddFont( cdImagePtr im, const char *fontname )
3164 // adds a font to the list of fonts. This only has an effect
3165 // if you are using the expert functions for starting pictures, and
3166 // have not yet opened the first picture. Returns 0 for failure,
3167 // and the font index on success
3168 {
3169  unsigned char *oldfonts;
3170  int listsize;
3171  oldfonts = im->fontlist;
3172  if ( oldfonts )
3173  {
3174  listsize = strlen( (char *) oldfonts ) + 1 + strlen( fontname ) + 1;
3175  }
3176  else
3177  {
3178  listsize = strlen( fontname ) + 1;
3179  }
3180  im->fontlist = (unsigned char *) calloc( listsize, SIZEOF( unsigned char ) );
3181  if ( !im->fontlist )
3182  return 0; // memory allocation failed
3183  if ( oldfonts )
3184  {
3185  sprintf( (char *) im->fontlist, "%s%s%s", (char *) oldfonts, ",", fontname );
3186  }
3187  else
3188  {
3189  sprintf( (char *) im->fontlist, "%s", fontname );
3190  }
3191  im->numfonts++;
3192  if ( oldfonts )
3193  free( oldfonts );
3194  oldfonts = NULL;
3195  return im->numfonts;
3196 }
3197 
3199 // clears out ALL fonts from the font list, including the ones the
3200 // package has be default. Useful if you want totally different fonts.
3201 //
3202 {
3203  free( im->fontlist );
3204  im->fontlist = NULL;
3205  im->numfonts = 0;
3206  return 1;
3207 }
3208 
3210 // resets the defaults to what is in defines.h
3211 {
3212  // you must be either before any picture has been created,
3213  // or after a picture has closed to call this
3214  if ( ( im->state != 0 ) && ( im->state != 2 ) )
3215  return 0;
3216  // set line_width, line_height, line_color to the defaults
3217  im->ltype = CDLTYPE;
3218  im->lwidth = CDLWIDTH;
3219  im->lcolor = CDLCOLOR;
3220  // interior_style, fill_color, hatch_index
3221  im->shapestyle = CDSHAPESTYLE;
3222  im->shapecolor = CDSHAPECOLOR;
3223  im->shapehatch = CDSHAPEHATCH;
3224  // edge_type, edge_width, edge_color, edge_visibility
3225  im->edgetype = CDEDGETYPE;
3226  im->edgecolor = CDEDGECOLOR;
3227  im->edgewidth = CDEDGEWIDTH;
3228  im->edgevis = CDEDGEVIS;
3229  // text_color, text_height, text_font
3230  im->textcolor = CDTEXTCOLOR;
3231  im->textheight = CDTEXTHEIGHT;
3232  im->textfont = CDTEXTFONT;
3233  im->textpath = CDTEXTPATH;
3234  // set marker_width, marker_size, marker_color to the defaults
3235  im->ltype = CDMTYPE;
3236  im->lwidth = CDMSIZE;
3237  im->lcolor = CDMCOLOR;
3238  // this is set by the expert functions. the defaults should be ok
3239  im->linespec = CDLINESPEC;
3240  im->edgespec = CDEDGESPEC;
3241  im->markerspec = CDMARKERSPEC;
3242 
3243  return 1;
3244 }
3245 
3247 // initializes the CGM and sets up the defaults. If you are using
3248 // the "expert" functions, you should call this first. _ge
3249 {
3250  const char *tmps;
3251  int tmpsl;
3252  cdImagePtr im;
3253  im = (cdImage *) calloc( SIZEOF( cdImage ), 1 );
3254  if ( !im )
3255  return 0; // memory allocation failed
3256  // elemlist is set to some number, when it is full, make it bigger
3257  im->elemlist = (unsigned char *) calloc( CDSTARTLISTSIZE, SIZEOF( unsigned char ) );
3258  if ( !im->elemlist )
3259  {
3260  free( im ); return 0;
3261  } // memory allocation failed
3262  im->colorsTotal = 0;
3263  // you can have multiple pictures in a file, keep track of
3264  // which one you are on
3265  im->picnum = 0;
3266  im->outfile = NULL;
3267  // the next three are used for maintaining the element list
3268  // don't change these ever
3270  im->listlen = CDSTARTLISTSIZE;
3271  im->curelemlist = im->elemlist;
3272 
3273  // don't make this longer than 250 characters
3274  tmps = "'ProfileId: Model-Profile''ProfileEd:1''ColourClass:colour''Source:NIST CGMDraw 1.3''Date: 1996-12-16'";
3275  tmpsl = strlen( tmps );
3276  if ( tmpsl > 250 )
3277  tmpsl = 250;
3278  im->desc = (unsigned char *) calloc( tmpsl + 1, SIZEOF( unsigned char ) );
3279  strncpy( (char *) im->desc, tmps, tmpsl );
3280  // The font list can be quite long, but individual font names can
3281  // can only be 250 chars
3282  tmps = "TIMES_ROMAN,TIMES_BOLD,TIMES_ITALIC,TIMES_BOLD_ITALIC,HELVETICA,HELVETICA_BOLD,HELVETICA_ITALIC,HELVETICA_BOLD_ITALIC,COURIER,COURIER_BOLD,COURIER_ITALIC,COURIER_BOLD_ITALIC";
3283  im->numfonts = 12;
3284  tmpsl = strlen( tmps );
3285  im->fontlist = (unsigned char *) calloc( tmpsl + 1, SIZEOF( unsigned char ) );
3286  strcpy( (char *) im->fontlist, tmps );
3287  im->outfile = NULL;
3288 
3289  if ( !cdImageSetDefaults( im ) )
3290  {
3291  cdImageDestroy( im );
3292  }
3293  // set the state
3294  im->state = 0; // 0 no pictures started, 1 in a picture,
3295  // 2 after a picture
3296 
3297  return im;
3298 }
3299 
3301 // close the current picture
3302 {
3303  unsigned char *es, *esp;
3304  int octet_count = 0;
3305 
3306  // make sure we are really in a picture before ending it
3307  if ( im->state != 1 )
3308  {
3309  return 0;
3310  }
3311 
3312  esp = (unsigned char *) calloc( 1024, SIZEOF( unsigned char ) );
3313  if ( !esp )
3314  return 0; // memory allocation failed
3315  es = esp;
3316 
3317  // Attribute: End Picture; Elem Class 0; Elem ID 5; Length 0
3318  if ( !cdcomhead( es, 0, 5, 0 ) )
3319  {
3320  free( esp ); return 0;
3321  }
3322  octet_count += 2;
3323 
3324  if ( cdAddElem( im, esp, octet_count ) )
3325  {
3326  free( esp );
3327  im->state = 2;
3328  return 1;
3329  }
3330  else
3331  {
3332  free( esp );
3333  return 0;
3334  }
3335 }
3336 
3338 // close the current CGM file. If an output stream is
3339 // defined, write the CGM to it
3340 {
3341  int x; // counter
3342  int used; // number of bytes used in the list
3343  unsigned char *efile, *efilep; // end of file information
3344 
3345  cdImageEndPic( im );
3346  if ( im->state == 2 ) // We have closed the pic, but not the CGM
3347  {
3348  efile = (unsigned char *) calloc( 4 * 4, SIZEOF( unsigned char ) );
3349  if ( !efile )
3350  return 0; // memory allocation failed
3351  efilep = efile;
3352  // Attribute: End Metafile; Elem Class 0; Elem ID 2
3353  cdcomhead( efilep, 0, 2, 0 );
3354 
3355 
3356  if ( cdAddElem( im, efile, 2 ) )
3357  {
3358  free( efile );
3359  efile = 0;
3360  efilep = 0;
3361  }
3362  else
3363  {
3364  free( efile );
3365  return 0;
3366  }
3367  }
3368 
3369  if ( im->outfile )
3370  {
3371  // now output the CGM, one byte at a time
3372  used = im->listlen - im->bytestoend;
3373  for ( x = 0; x < used; x++ )
3374  {
3375  putc( (unsigned char) im->elemlist[x], im->outfile );
3376  }
3377  } // else do nothing
3378 
3379  return 1;
3380 }