PLplot  5.10.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
cgm.c
Go to the documentation of this file.
1 // $Id: cgm.c 11283 2010-10-28 22:38:29Z airwin $
2 //
3 // PLplot cgm device driver.
4 //
5 
6 //
7 // This driver generates CGM (computer graphics metafiles) files (bit of a
8 // tautology that... 'computer graphics metaFILES FILES' - oh well).
9 //
10 // The CGM format is vector-based and is widely used as an interchange
11 // format between drawing and plotting programs. Although I have never
12 // looked at them, there are apparently both Java applets and browser
13 // plug-ins for displaying CGM files on web pages.
14 //
15 // This plplot driver supports lines, polylines (they make a difference to
16 // CGM files), fills, and line widths. It is limited to 256 colours, which
17 // should not be a problem. The plplot CGM driver's source (cgm.c) was
18 // derived largely from the gd driver (gd.c).
19 //
20 // The plplot driver requires libcd.a. libcd.a is very similar to libgd.a
21 // and has a similar licencing agreement behind it. Unlike libgd,
22 // development of libcd seems to have crawled to a halt back in 1998 with
23 // V1.3 of the library. The original host site for the library no longer
24 // exists, so probably the best source of the library presently is:
25 //
26 // http://www.pa.msu.edu/reference/cgmdraw_ref.html
27 // http://www.pa.msu.edu/ftp/pub/unix/
28 //
29 
30 //
31 // Two options are supported by the driver via the -drvopt command line
32 // toggle.
33 //
34 // By default CGM files don't have a background as such. The driver adds
35 // support for different backgrounds by colouring in a large rectangle
36 // underneath everything else. If for some reason you want the "raw plotted
37 // junk" and aren't really interested in having an obtrusive piece of paper
38 // in the back, use the command line toggle "-drvopt no_paper=1" to turn off
39 // this background paper.
40 //
41 // By default the CGM files generated by this driver try to make edges of
42 // polygons (ie fills) "invisible", which is something CGM files can do.
43 // Some programs (ie CoreDraw) ignore this field and draw edges in anyway.
44 // By setting "-drvopt force_edges=1" the driver will render edges on all
45 // filled polygons, and will set their colour to the same as the polygon.
46 // Most drivers should not need this, but if you see lines that you don't
47 // think you should be seeing in your viewer, try this toggle.
48 //
49 
50 //
51 // Driver supports a hack that manipulates the colour palette when
52 // a light background is selected. This is basically to make sure
53 // there are not two "whites" when -bg ffffff is issued at the
54 // command line.
55 //
56 // Related to this change, there is an ability to swap the "new"
57 // black colour (index 15) with the red colour (index 2) by issuing
58 // the command line "-hack" option. I like this for web pages, because
59 // I think that black looks nicer than red (on white) for default
60 // plotting. That is why it can be enabled with -hack, in case you
61 // don't like it working this way.
62 //
63 // For me, these two changes make it easy to switch from a "screen friendly"
64 // black background with red first plotting colour, to a "web friendly"
65 // white background with a black first plotting colour.
66 //
67 // These features are enabled on a driver level by defining
68 // "SWAP_BALCK_WHEN_WHITE". If you wan't the driver to behave 100% like other
69 // drivers, comment out the define
70 //
71 
72 #define SWAP_BALCK_WHEN_WHITE
73 
74 #include "plDevs.h"
75 
76 #ifdef PLD_cgm
77 
78 #include "plplotP.h"
79 #include "drivers.h"
80 
81 #include <cd.h>
82 
83 // Device info
84 PLDLLIMPEXP_DRIVER const char* plD_DEVICE_INFO_cgm = "cgm:CGM file:0:cgm:44:cgm\n";
85 
86 // Prototypes for functions in this file.
87 
88 static void fill_polygon( PLStream *pls );
89 static void setcmap( PLStream *pls );
90 static void plD_init_cgm_Dev( PLStream *pls );
91 
92 // top level declarations
93 
94 // In an attempt to fix a problem with the hidden line removal functions
95 // that results in hidden lines *not* being removed from "small" plot
96 // pages (ie, like a normal video screen), a "virtual" page of much
97 // greater size is used to trick the algorithm into working correctly.
98 // If, in future, this gets fixed on its own, then don't define
99 // "use_experimental_hidden_line_hack"
100 //
101 
102 #define use_experimental_hidden_line_hack
103 
104 static int force_edges = 0;
105 static int disable_background = 0;
106 
107 static DrvOpt cgm_options[] = { { "force_edges", DRV_INT, &force_edges, "Force edges to be drawn on filled polygongs (0|1)" },
108  { "no_paper", DRV_INT, &disable_background, "Disable background (0|1)" },
109  { NULL, DRV_INT, NULL, NULL } };
110 
111 
112 // Struct to hold device-specific info.
113 
114 typedef struct
115 {
116  cdImagePtr im_out; // Graphics pointer
117  PLINT cgmx;
118  PLINT cgmy;
119 
120 // GD does "funny" things with the colour map.
121 // It can't guarantee that the colours will be where you think they are.
122 // So we need this "colour_index" table to store where the colour we
123 // requested happens to be. Messy, but it works.
124 //
125 
126  int colour_index[256]; // Colour "index" table
127 
128 //
129 // I use two colours for both fill and line drawing - a "last colour" and
130 // "current colour". The driver only switches colours if they have changed
131 // and are used. If no fills are ever done, then the instruction to set the
132 // fill colour is never sent to the CGM file. Should make for smaller and
133 // more efficient files (I guess).
134 //
135 
136  int colour; // Current Colour
137  int last_line_colour; // Last line colour used
138  int fill_colour; // Current Fill colour
139  int last_fill_colour; // Last Fill colour used
140 
141  int totcol; // Total number of colours
142  int ncol1; // Actual size of ncol1 we got
143  int scale; // scaling factor to "blow up" to
144  // the "virtual" page in removing hidden lines
145  int force_edges; // Forces edges to be drawn in fills
146  int disable_background; // Turns off background rectangle
147 } cgm_Dev;
148 
149 void plD_init_cgm( PLStream * );
150 void plD_line_cgm( PLStream *, short, short, short, short );
151 void plD_polyline_cgm( PLStream *, short *, short *, PLINT );
152 void plD_eop_cgm( PLStream * );
153 void plD_bop_cgm( PLStream * );
154 void plD_tidy_cgm( PLStream * );
155 void plD_state_cgm( PLStream *, PLINT );
156 void plD_esc_cgm( PLStream *, PLINT, void * );
157 
158 
160 {
161 #ifndef ENABLE_DYNDRIVERS
162  pdt->pl_MenuStr = "CGM (Computer Graphics metafile) file";
163  pdt->pl_DevName = "cgm";
164 #endif
166  pdt->pl_seq = 44;
167  pdt->pl_init = (plD_init_fp) plD_init_cgm;
168  pdt->pl_line = (plD_line_fp) plD_line_cgm;
169  pdt->pl_polyline = (plD_polyline_fp) plD_polyline_cgm;
170  pdt->pl_eop = (plD_eop_fp) plD_eop_cgm;
171  pdt->pl_bop = (plD_bop_fp) plD_bop_cgm;
172  pdt->pl_tidy = (plD_tidy_fp) plD_tidy_cgm;
173  pdt->pl_state = (plD_state_fp) plD_state_cgm;
174  pdt->pl_esc = (plD_esc_fp) plD_esc_cgm;
175 }
176 
177 
178 //--------------------------------------------------------------------------
179 // plD_init_cgm_Dev()
180 //
181 //--------------------------------------------------------------------------
182 
183 static void
184 plD_init_cgm_Dev( PLStream *pls )
185 {
186  cgm_Dev *dev;
187 
188 // Allocate and initialize device-specific data
189 
190  if ( pls->dev != NULL )
191  free( (void *) pls->dev );
192 
193  pls->dev = calloc( 1, (size_t) sizeof ( cgm_Dev ) );
194  if ( pls->dev == NULL )
195  plexit( "plD_init_cgm_Dev: Out of memory." );
196 
197  dev = (cgm_Dev *) pls->dev;
198 
199 // Check for and set up driver options
200 
201  plParseDrvOpts( cgm_options );
202  dev->force_edges = force_edges; // force edges (for corel draw etc...)
203  dev->disable_background = disable_background; // Disable background
204 
205  dev->colour = 1; // Set a fall back pen colour in case user doesn't
206  dev->fill_colour = dev->colour; // initially set fill and line colour the same
207  dev->last_fill_colour = -1; // set to -1 = unallocated
208  dev->last_line_colour = -1; // set to -1 = unallocated
209 }
210 
211 //--------------------------------------------------------------------------
212 // plD_init_cgm()
213 //
214 // Initialize device.
215 //--------------------------------------------------------------------------
216 
217 void plD_init_cgm( PLStream *pls )
218 {
219  cgm_Dev *dev = NULL;
220 
221  pls->termin = 0; // Not an interactive device
222  pls->icol0 = 1;
223  pls->bytecnt = 0;
224  pls->page = 0;
225  pls->dev_fill0 = 1; // Can do solid fills
226 
227  if ( !pls->colorset )
228  pls->color = 1; // Is a color device
229 
230  if ( pls->width < 1 )
231  pls->width = 1; // set a legal line width
232 
233 // Initialize family file info
234  plFamInit( pls );
235 
236 // Prompt for a file name if not already set
237  plOpenFile( pls );
238 
239 // Allocate and initialize device-specific data
240  plD_init_cgm_Dev( pls );
241  dev = (cgm_Dev *) pls->dev;
242 
243  if ( pls->xlength <= 0 || pls->ylength <= 0 )
244  {
245 // use default width, height of 800x600 if not specifed by -geometry option
246 // or plspage
247  plspage( 0., 0., 800, 600, 0, 0 );
248  }
249 
250  pls->graphx = GRAPHICS_MODE;
251 
252  dev->cgmx = pls->xlength - 1; // should I use -1 or not???
253  dev->cgmy = pls->ylength - 1;
254 
255 #ifdef use_experimental_hidden_line_hack
256 
257  if ( dev->cgmx > dev->cgmy ) // Work out the scaling factor for the
258  { // "virtual" (oversized) page
259  dev->scale = ( PIXELS_X - 1 ) / dev->cgmx;
260  }
261  else
262  {
263  dev->scale = PIXELS_Y / dev->cgmy;
264  }
265 #else
266 
267  dev->scale = 1;
268 
269 #endif
270 
271  if ( pls->xdpi <= 0 )
272  {
273 // This corresponds to a typical monitor resolution of 4 pixels/mm.
274  plspage( 4. * 25.4, 4. * 25.4, 0, 0, 0, 0 );
275  }
276  else
277  {
278  pls->ydpi = pls->xdpi; // Set X and Y dpi's to the same value
279  }
280 // Convert DPI to pixels/mm
281  plP_setpxl( dev->scale * pls->xdpi / 25.4, dev->scale * pls->ydpi / 25.4 );
282 
283  plP_setphy( 0, dev->scale * dev->cgmx, 0, dev->scale * dev->cgmy );
284 }
285 
286 //--------------------------------------------------------------------------
287 // plD_line_cgm()
288 //
289 // Draw a line in the current color from (x1,y1) to (x2,y2).
290 //--------------------------------------------------------------------------
291 
292 void
293 plD_line_cgm( PLStream *pls, short x1a, short y1a, short x2a, short y2a )
294 {
295  cgm_Dev *dev = (cgm_Dev *) pls->dev;
296  int x1 = x1a / dev->scale, y1 = y1a / dev->scale, x2 = x2a / dev->scale, y2 = y2a / dev->scale;
297  y1 = y1;
298  y2 = y2;
299 
300 //
301 // Determine if the colour has changed since the last time a line was
302 // drawn. If it has, then set the colour NOW otherwise, keep on going like
303 // "nuthin happened".
304 //
305 
306  if ( dev->last_line_colour != dev->colour )
307  {
308  cdSetLineColor( dev->im_out, dev->colour );
309  dev->last_line_colour = dev->colour;
310  }
311 
312  cdLine( dev->im_out, x1, y1, x2, y2 );
313 }
314 
315 //--------------------------------------------------------------------------
316 // plD_polyline_cgm()
317 //
318 // Draw a polyline in the current color.
319 //--------------------------------------------------------------------------
320 
321 void
322 plD_polyline_cgm( PLStream *pls, short *xa, short *ya, PLINT npts )
323 {
324  cgm_Dev *dev = (cgm_Dev *) pls->dev;
325  PLINT i;
326  cdPoint *points = NULL;
327 
328  if ( ( points = calloc( npts, (size_t) sizeof ( cdPoint ) ) ) == NULL )
329  {
330  plexit( "Memory allocation error in \"plD_polyline_cgm\"" );
331  }
332 
333  for ( i = 0; i < npts; i++ )
334  {
335  points[i].x = xa[i] / dev->scale;
336  points[i].y = ( ya[i] / dev->scale );
337  }
338 
339 //
340 // Determine if the colour has changed since the last time a line was
341 // drawn. If it has, then set the colour NOW otherwise, keep on going like
342 // "nuthin happened".
343 //
344 
345  if ( dev->last_line_colour != dev->colour )
346  {
347  cdSetLineColor( dev->im_out, dev->colour );
348  dev->last_line_colour = dev->colour;
349  }
350 
351  cdPolyLine( dev->im_out, points, npts );
352  free( points );
353 }
354 
355 
356 //--------------------------------------------------------------------------
357 // fill_polygon()
358 //
359 // Fill polygon described in points pls->dev_x[] and pls->dev_y[].
360 //--------------------------------------------------------------------------
361 
362 static void
363 fill_polygon( PLStream *pls )
364 {
365  cgm_Dev *dev = (cgm_Dev *) pls->dev;
366 
367  PLINT i;
368  cdPoint *points = NULL;
369 
370  if ( pls->dev_npts < 1 )
371  return;
372 
373  if ( ( points = calloc( pls->dev_npts, (size_t) sizeof ( cdPoint ) ) ) == NULL )
374  {
375  plexit( "Memory allocation error in \"plD_fill_polygon_cgm\"" );
376  }
377 
378  for ( i = 0; i < pls->dev_npts; i++ )
379  {
380  points[i].x = pls->dev_x[i] / dev->scale;
381  points[i].y = ( pls->dev_y[i] / dev->scale );
382  }
383 
384 
385 //
386 // Determine if the fill colour has changed since the last time a fill was
387 // done. If it has, then set the colour NOW otherwise, keep on going like
388 // "nuthin happened". If it's the first time, we will know 'cause the the
389 // "last_fill_colour" will be -1.
390 //
391 
392  if ( ( dev->fill_colour != dev->last_fill_colour ) || ( dev->force_edges == 1 ) )
393  {
394  cdSetFillColor( dev->im_out, dev->fill_colour );
395 
396 //
397 // Due to a bug in cd V1.3, we have to set the edge colour to the fill
398 // colour. This is despite telling the library edges should be invisible.
399 // Seems the invisible edges only work with rectangles.
400 //
401 
402  if ( dev->force_edges == 1 )
403  {
404  cdSetEdgeColor( dev->im_out, dev->fill_colour );
405  cdSetEdgeVis( dev->im_out, 1 );
406  }
407 
408  dev->last_fill_colour = dev->fill_colour;
409  }
410 
411  cdPolygon( dev->im_out, points, pls->dev_npts );
412 
413  if ( dev->force_edges == 1 )
414  cdSetEdgeVis( dev->im_out, 0 ); // Turn edges off now
415 
416  free( points );
417 }
418 
419 //--------------------------------------------------------------------------
420 // setcmap()
421 //
422 // Sets up color palette.
423 //--------------------------------------------------------------------------
424 
425 static void
426 setcmap( PLStream *pls )
427 {
428  int i, ncol1 = pls->ncol1;
429  int ncol0 = pls->ncol0, total_colours;
430  PLColor cmap1col;
431  cgm_Dev *dev = (cgm_Dev *) pls->dev;
432  PLFLT tmp_colour_pos;
433 
434  cdImageColorClear( dev->im_out ); // UNDOCUMENTED FUNCTION TO RESET THE
435  // INTERNAL COLOUR TABLE OF THE
436  // CD DRIVER. Seems to work and fix
437  // the errors
438 
439  if ( ncol0 > cdMaxColors / 2 ) // Check for ridiculous number of colours
440  { // in ncol0, and appropriately adjust the
441  plwarn( "Too many colours in cmap0." ); // number, issuing a
442  ncol0 = cdMaxColors / 2; // warning if it does
443  pls->ncol0 = ncol0;
444  }
445 
446  dev->totcol = 0; // Reset the number of colours counter to zero
447 
448  total_colours = ncol0 + ncol1; // Work out how many colours are wanted
449 
450  if ( total_colours > cdMaxColors ) // Do some rather modest error
451  { // checking to make sure that
452  total_colours = cdMaxColors; // we are not defining more colours
453  ncol1 = total_colours - ncol0; // than we have room for.
454 
455  if ( ncol1 <= 0 )
456  {
457  plexit( "Problem setting colourmap in CGM driver." );
458  }
459  }
460 
461  dev->ncol1 = ncol1; // The actual size of ncol1, regardless of what was asked.
462  // This is dependent on colour slots available.
463  // It might well be the same as ncol1.
464  //
465 
466 // Initialize cmap 0 colors
467 
468  if ( ncol0 > 0 ) // make sure the program actually asked for cmap0 first
469  {
470 #ifdef SWAP_BALCK_WHEN_WHITE
471 
472 //
473 // Do a kludge to add a "black" colour back to the palette if the
474 // background is "almost white" (ie changed through -bg).
475 //
476 // Also includes an "optional" change to swap the red colour (1) with the
477 // black colour (15), which is off by default. (I don't like the red being
478 // the 'default' colour "1" on a "white" background, or for that matter
479 // yellow being "2", but I can live more with yellow at number two.)
480 // Just use "-hack" from the command line to make it take effect.
481 //
482 //
483 
484  if ( ( pls->ncol0 > 15 ) && ( pls->cmap0[0].r > 227 ) && ( pls->cmap0[0].g > 227 ) && ( pls->cmap0[0].b > 227 ) )
485  {
486  if ( pls->hack != 1 ) // just set colour 15 to black
487  {
488  pls->cmap0[15].r = 0;
489  pls->cmap0[15].g = 0;
490  pls->cmap0[15].b = 0;
491  }
492  else // swap colour 15 and colour 1
493  {
494  pls->cmap0[15].r = pls->cmap0[1].r;
495  pls->cmap0[15].g = pls->cmap0[1].g;
496  pls->cmap0[15].b = pls->cmap0[1].b;
497 
498  pls->cmap0[1].r = 0;
499  pls->cmap0[1].g = 0;
500  pls->cmap0[1].b = 0;
501  }
502  }
503 
504 #endif
505 
506  for ( i = 0; i < ncol0; i++ )
507  {
508  if ( (
509  dev->colour_index[i] = cdImageColorAllocate( dev->im_out,
510  pls->cmap0[i].r, pls->cmap0[i].g, pls->cmap0[i].b )
511  ) == -1 )
512  {
513  plwarn( "Problem setting cmap0 in CGM driver." );
514  }
515  else
516  ++dev->totcol; // count the number of colours we use as we use them
517  }
518  }
519 
520 // Initialize any remaining slots for cmap1
521 
522 
523  if ( ncol1 > 0 ) // make sure that we want to define cmap1 first
524  {
525  for ( i = 0; i < ncol1; i++ )
526  {
527  if ( ncol1 < pls->ncol1 ) // Check the dynamic range of colours
528  {
529  //
530  // Ok, now if we have less colour slots available than are being
531  // defined by pls->ncol1, then we still want to use the full
532  // dynamic range of cmap1 as best we can, so what we do is work
533  // out an approximation to the index in the full dynamic range
534  // in cases when pls->ncol1 exceeds the number of free colours.
535  //
536 
537  tmp_colour_pos = i > 0 ? pls->ncol1 * ( (PLFLT) i / ncol1 ) : 0;
538  plcol_interp( pls, &cmap1col, (int) tmp_colour_pos, pls->ncol1 );
539  }
540  else
541  {
542  plcol_interp( pls, &cmap1col, i, ncol1 );
543  }
544 
545 
546  if ( (
547  dev->colour_index[i + pls->ncol0] = cdImageColorAllocate( dev->im_out,
548  cmap1col.r, cmap1col.g, cmap1col.b )
549  ) == -1 )
550  {
551  plwarn( "Problem setting cmap1 in CGM driver." );
552  }
553  else
554  ++dev->totcol; // count the number of colours we use as we use them
555  }
556  }
557 }
558 
559 
560 //--------------------------------------------------------------------------
561 // plD_state_cgm()
562 //
563 // Handle change in PLStream state (color, pen width, fill attribute, etc).
564 //--------------------------------------------------------------------------
565 
566 void
567 plD_state_cgm( PLStream *pls, PLINT op )
568 {
569  cgm_Dev *dev = (cgm_Dev *) pls->dev;
570  PLFLT tmp_colour_pos;
571 
572  switch ( op )
573  {
574  case PLSTATE_WIDTH:
575  cdSetLineWidth( dev->im_out, pls->width );
576  break;
577 
578  case PLSTATE_COLOR0:
579  dev->colour = pls->icol0;
580  if ( dev->colour == PL_RGB_COLOR )
581  {
582  int r = pls->curcolor.r;
583  int g = pls->curcolor.g;
584  int b = pls->curcolor.b;
585  if ( dev->totcol < cdMaxColors )
586  {
587  if ( (
588  dev->colour_index[++dev->totcol] = cdImageColorAllocate( dev->im_out, r, g, b )
589  ) == -1 )
590  plwarn( "Problem changing colour in \"PLSTATE_COLOR0\"" );
591  else
592  dev->colour = dev->totcol;
593  }
594  }
595  dev->fill_colour = dev->colour;
596  break;
597 
598  case PLSTATE_COLOR1:
599  //
600  // Start by checking to see if we have to compensate for cases where
601  // we don't have the full dynamic range of cmap1 at our disposal
602  //
603  if ( dev->ncol1 < pls->ncol1 )
604  {
605  tmp_colour_pos = dev->ncol1 * ( (PLFLT) pls->icol1 / ( pls->ncol1 > 0 ? pls->ncol1 : 1 ) );
606  dev->colour = pls->ncol0 + (int) tmp_colour_pos;
607  }
608  else
609  dev->colour = pls->ncol0 + pls->icol1;
610 
611  dev->fill_colour = dev->colour;
612  break;
613 
614 
615  case PLSTATE_CMAP0:
616  case PLSTATE_CMAP1:
617  //
618  // Code to redefine the entire palette
619  //
620  if ( pls->color )
621  setcmap( pls );
622  break;
623  }
624 }
625 
626 
627 //--------------------------------------------------------------------------
628 // plD_esc_cgm()
629 //
630 // Escape function.
631 //--------------------------------------------------------------------------
632 
633 void plD_esc_cgm( PLStream *pls, PLINT op, void *ptr )
634 {
635  switch ( op )
636  {
637  case PLESC_FILL: // fill
638  fill_polygon( pls );
639  break;
640  }
641 }
642 
643 //--------------------------------------------------------------------------
644 // plD_bop_cgm()
645 //
646 // Set up for the next page.
647 // Advance to next family file if necessary (file output).
648 //--------------------------------------------------------------------------
649 
650 void plD_bop_cgm( PLStream *pls )
651 {
652  cgm_Dev *dev;
653 
654  plGetFam( pls );
655 // force new file if pls->family set for all subsequent calls to plGetFam
656 // n.b. putting this after plGetFam call is important since plinit calls
657 // bop, and you don't want the familying sequence started until after
658 // that first call to bop.
659 
660  pls->famadv = 1;
661 
662  pls->page++;
663 
664 // n.b. pls->dev can change because of an indirect call to plD_init_cgm
665 // from plGetFam if familying is enabled. Thus, wait to define dev until
666 // now.
667 
668  dev = (cgm_Dev *) pls->dev;
669 
670  if ( pls->page == 1 )
671  {
672  dev->im_out = cdImageCreate( pls->xlength, pls->ylength );
673  }
674  else if ( pls->family != 1 )
675  {
676  cdCgmNewPic( dev->im_out, 0 );
677  }
678 
679  setcmap( pls );
680 
681 // Continue to initialise the driver
682 
683  cdSetFillStyle( dev->im_out, 1 ); // Set solid fills
684 
685 //
686 // Due to a border being drawn around the edge of the image, we also
687 // manually, then turn them off again to make edges turn off. By
688 // default the driver thinks they are off, so when we tell the driver
689 // to turn them off it says "they are already off, I wont do anything"
690 // but in reality they are on by default. So what we do is turn them ON
691 // manually, then turn them OFF later.
692 //
693 // Due to a boarder being drawn around the edge of the image, we also
694 // want the edges turned on so we can lay down a rectangle coloured in
695 // the background colour at the start. Once we have drawn our
696 // background box, we then turn edges off for the rest of the page.
697 //
698 
699  cdSetEdgeVis( dev->im_out, 1 ); // turn edges on so we can turn them off!
700 
701  if ( dev->disable_background != 1 )
702  {
703  cdSetEdgeWidth( dev->im_out, pls->xlength / 5 ); // set edge to *really* wide so we can cover the edge of the page completelt
704  cdSetEdgeColor( dev->im_out, 0 ); // set the edge colour to the background colour so we can make a coloured page
705  cdSetFillColor( dev->im_out, 0 ); // set fill colour to background colour so we have a coloured page
706  cdRectangle( dev->im_out, 0, 0, pls->xlength - 1, pls->ylength - 1 ); // Draw a coloured rectangle to act as our "paper"
707  }
708 
709  cdSetEdgeVis( dev->im_out, 0 ); // Turn edges off now
710  cdSetEdgeWidth( dev->im_out, 0 ); // Just to be 100% sure
711 
712  cdSetLineType( dev->im_out, 1 ); // set solid lines
713  cdSetLineWidth( dev->im_out, pls->width ); // set initial line width for each page
714 }
715 
716 //--------------------------------------------------------------------------
717 // plD_tidy_cgm()
718 //
719 // Close graphics file or otherwise clean up.
720 //--------------------------------------------------------------------------
721 
722 void plD_tidy_cgm( PLStream *pls )
723 {
724  cgm_Dev *dev = (cgm_Dev *) pls->dev;
725 
726  if ( pls->family != 1 )
727  {
728  cdImageCgm( dev->im_out, pls->OutFile );
729  }
730 
731  cdImageDestroy( dev->im_out );
732  plCloseFile( pls );
733  free_mem( pls->dev );
734 }
735 
736 //--------------------------------------------------------------------------
737 // plD_eop_cgm()
738 //
739 // End of page.
740 //--------------------------------------------------------------------------
741 
742 void plD_eop_cgm( PLStream *pls )
743 {
744  cgm_Dev *dev = (cgm_Dev *) pls->dev;
745  int i;
746 
747  if ( pls->family == 1 )
748  {
749  cdImageCgm( dev->im_out, pls->OutFile );
750  }
751  for ( i = 0; i < cdMaxColors; ++i )
752  dev->colour_index[i] = -1;
753 
754  dev->fill_colour = dev->colour; // initially set fill and line colour the same
755  dev->last_fill_colour = -1; // set to -1 = unallocated
756  dev->last_line_colour = -1; // set to -1 = unallocated
757 }
758 
759 
760 //#endif
761 
762 
763 #else
764 int
766 {
767  return 0;
768 }
769 
770 #endif // cgm