PLplot  5.10.0
cgm.c
Go to the documentation of this file.
00001 //      PLplot cgm device driver.
00002 //
00003 
00004 //
00005 // This driver generates CGM (computer graphics metafiles) files (bit of a
00006 // tautology that... 'computer graphics metaFILES FILES' - oh well).
00007 //
00008 // The CGM format is vector-based and is widely used as an interchange
00009 // format between drawing and plotting programs. Although I have never
00010 // looked at them, there are apparently both Java applets and browser
00011 // plug-ins for displaying CGM files on web pages.
00012 //
00013 // This plplot driver supports lines, polylines (they make a difference to
00014 // CGM files), fills, and line widths. It is limited to 256 colours, which
00015 // should not be a problem. The plplot CGM driver's source (cgm.c) was
00016 // derived largely from the gd driver (gd.c).
00017 //
00018 // The plplot driver requires libcd.a. libcd.a is very similar to libgd.a
00019 // and has a similar licencing agreement behind it. Unlike libgd,
00020 // development of libcd seems to have crawled to a halt back in 1998 with
00021 // V1.3 of the library. The original host site for the library no longer
00022 // exists, so probably the best source of the library presently is:
00023 //
00024 // http://www.pa.msu.edu/reference/cgmdraw_ref.html
00025 // http://www.pa.msu.edu/ftp/pub/unix/
00026 //
00027 
00028 //
00029 // Two options are supported by the driver via the -drvopt command line
00030 // toggle.
00031 //
00032 // By default CGM files don't have a background as such. The driver adds
00033 // support for different backgrounds by colouring in a large rectangle
00034 // underneath everything else. If for some reason you want the "raw plotted
00035 // junk" and aren't really interested in having an obtrusive piece of paper
00036 // in the back, use the command line toggle "-drvopt no_paper=1" to turn off
00037 // this background paper.
00038 //
00039 // By default the CGM files generated by this driver try to make edges of
00040 // polygons (ie fills) "invisible", which is something CGM files can do.
00041 // Some programs (ie CoreDraw) ignore this field and draw edges in anyway.
00042 // By setting "-drvopt force_edges=1" the driver will render edges on all
00043 // filled polygons, and will set their colour to the same as the polygon.
00044 // Most drivers should not need this, but if you see lines that you don't
00045 // think you should be seeing in your viewer, try this toggle.
00046 //
00047 
00048 //
00049 // Driver supports a hack that manipulates the colour palette when
00050 // a light background is selected. This is basically to make sure
00051 // there are not two "whites" when -bg ffffff is issued at the
00052 // command line.
00053 //
00054 // Related to this change, there is an ability to swap the "new"
00055 // black colour (index 15) with the red colour (index 2) by issuing
00056 // the command line "-hack" option. I like this for web pages, because
00057 // I think that black looks nicer than red (on white) for default
00058 // plotting. That is why it can be enabled with -hack, in case you
00059 // don't like it working this way.
00060 //
00061 // For me, these two changes make it easy to switch from a "screen friendly"
00062 // black background with red first plotting colour, to a "web friendly"
00063 // white background with a black first plotting colour.
00064 //
00065 // These features are enabled on a driver level by defining
00066 // "SWAP_BALCK_WHEN_WHITE". If you wan't the driver to behave 100% like other
00067 // drivers, comment out the define
00068 //
00069 
00070 #define SWAP_BALCK_WHEN_WHITE
00071 
00072 #include "plDevs.h"
00073 
00074 #ifdef PLD_cgm
00075 
00076 #include "plplotP.h"
00077 #include "drivers.h"
00078 
00079 #include <cd.h>
00080 
00081 // Device info
00082 PLDLLIMPEXP_DRIVER const char* plD_DEVICE_INFO_cgm = "cgm:CGM file:0:cgm:44:cgm\n";
00083 
00084 // Prototypes for functions in this file.
00085 
00086 static void     fill_polygon( PLStream *pls );
00087 static void     setcmap( PLStream *pls );
00088 static void     plD_init_cgm_Dev( PLStream *pls );
00089 
00090 // top level declarations
00091 
00092 // In an attempt to fix a problem with the hidden line removal functions
00093 // that results in hidden lines *not* being removed from "small" plot
00094 // pages (ie, like a normal video screen), a "virtual" page of much
00095 // greater size is used to trick the algorithm into working correctly.
00096 // If, in future, this gets fixed on its own, then don't define
00097 // "use_experimental_hidden_line_hack"
00098 //
00099 
00100 #define use_experimental_hidden_line_hack
00101 
00102 static int    force_edges        = 0;
00103 static int    disable_background = 0;
00104 
00105 static DrvOpt cgm_options[] = { { "force_edges", DRV_INT, &force_edges,        "Force edges to be drawn on filled polygongs (0|1)" },
00106                                 { "no_paper",    DRV_INT, &disable_background, "Disable background (0|1)"                          },
00107                                 { NULL,          DRV_INT, NULL,                NULL                                                } };
00108 
00109 
00110 // Struct to hold device-specific info.
00111 
00112 typedef struct
00113 {
00114     cdImagePtr im_out;                          // Graphics pointer
00115     PLINT      cgmx;
00116     PLINT      cgmy;
00117 
00118 // GD does "funny" things with the colour map.
00119 // It can't guarantee that the colours will be where you think they are.
00120 // So we need this "colour_index" table to store where the colour we
00121 // requested happens to be. Messy, but it works.
00122 //
00123 
00124     int colour_index[256];                      // Colour "index" table
00125 
00126 //
00127 // I use two colours for both fill and line drawing - a "last colour" and
00128 // "current colour". The driver only switches colours if they have changed
00129 // and are used. If no fills are ever done, then the instruction to set the
00130 // fill colour is never sent to the CGM file. Should make for smaller and
00131 // more efficient files (I guess).
00132 //
00133 
00134     int colour;                                 // Current Colour
00135     int last_line_colour;                       // Last line colour used
00136     int fill_colour;                            // Current Fill colour
00137     int last_fill_colour;                       // Last Fill colour used
00138 
00139     int totcol;                                 // Total number of colours
00140     int ncol1;                                  // Actual size of ncol1 we got
00141     int scale;                                  // scaling factor to "blow up" to
00142                                                 // the "virtual" page in removing hidden lines
00143     int force_edges;                            // Forces edges to be drawn in fills
00144     int disable_background;                     // Turns off background rectangle
00145 } cgm_Dev;
00146 
00147 void plD_init_cgm( PLStream * );
00148 void plD_line_cgm( PLStream *, short, short, short, short );
00149 void plD_polyline_cgm( PLStream *, short *, short *, PLINT );
00150 void plD_eop_cgm( PLStream * );
00151 void plD_bop_cgm( PLStream * );
00152 void plD_tidy_cgm( PLStream * );
00153 void plD_state_cgm( PLStream *, PLINT );
00154 void plD_esc_cgm( PLStream *, PLINT, void * );
00155 
00156 
00157 void plD_dispatch_init_cgm( PLDispatchTable *pdt )
00158 {
00159 #ifndef ENABLE_DYNDRIVERS
00160     pdt->pl_MenuStr = "CGM (Computer Graphics metafile) file";
00161     pdt->pl_DevName = "cgm";
00162 #endif
00163     pdt->pl_type     = plDevType_FileOriented;
00164     pdt->pl_seq      = 44;
00165     pdt->pl_init     = (plD_init_fp) plD_init_cgm;
00166     pdt->pl_line     = (plD_line_fp) plD_line_cgm;
00167     pdt->pl_polyline = (plD_polyline_fp) plD_polyline_cgm;
00168     pdt->pl_eop      = (plD_eop_fp) plD_eop_cgm;
00169     pdt->pl_bop      = (plD_bop_fp) plD_bop_cgm;
00170     pdt->pl_tidy     = (plD_tidy_fp) plD_tidy_cgm;
00171     pdt->pl_state    = (plD_state_fp) plD_state_cgm;
00172     pdt->pl_esc      = (plD_esc_fp) plD_esc_cgm;
00173 }
00174 
00175 
00176 //--------------------------------------------------------------------------
00177 // plD_init_cgm_Dev()
00178 //
00179 //--------------------------------------------------------------------------
00180 
00181 static void
00182 plD_init_cgm_Dev( PLStream *pls )
00183 {
00184     cgm_Dev *dev;
00185 
00186 // Allocate and initialize device-specific data
00187 
00188     if ( pls->dev != NULL )
00189         free( (void *) pls->dev );
00190 
00191     pls->dev = calloc( 1, (size_t) sizeof ( cgm_Dev ) );
00192     if ( pls->dev == NULL )
00193         plexit( "plD_init_cgm_Dev: Out of memory." );
00194 
00195     dev = (cgm_Dev *) pls->dev;
00196 
00197 // Check for and set up driver options
00198 
00199     plParseDrvOpts( cgm_options );
00200     dev->force_edges        = force_edges;        // force edges (for corel draw etc...)
00201     dev->disable_background = disable_background; // Disable background
00202 
00203     dev->colour           = 1;                    // Set a fall back pen colour in case user doesn't
00204     dev->fill_colour      = dev->colour;          // initially set fill and line colour the same
00205     dev->last_fill_colour = -1;                   // set to -1 = unallocated
00206     dev->last_line_colour = -1;                   // set to -1 = unallocated
00207 }
00208 
00209 //--------------------------------------------------------------------------
00210 // plD_init_cgm()
00211 //
00212 // Initialize device.
00213 //--------------------------------------------------------------------------
00214 
00215 void plD_init_cgm( PLStream *pls )
00216 {
00217     cgm_Dev *dev = NULL;
00218 
00219     pls->termin    = 0;         // Not an interactive device
00220     pls->icol0     = 1;
00221     pls->bytecnt   = 0;
00222     pls->page      = 0;
00223     pls->dev_fill0 = 1;         // Can do solid fills
00224 
00225     if ( !pls->colorset )
00226         pls->color = 1;                       // Is a color device
00227 
00228     if ( pls->width < 1 )
00229         pls->width = 1;                       // set a legal line width
00230 
00231 // Initialize family file info
00232     plFamInit( pls );
00233 
00234 // Prompt for a file name if not already set
00235     plOpenFile( pls );
00236 
00237 // Allocate and initialize device-specific data
00238     plD_init_cgm_Dev( pls );
00239     dev = (cgm_Dev *) pls->dev;
00240 
00241     if ( pls->xlength <= 0 || pls->ylength <= 0 )
00242     {
00243 // use default width, height of 800x600 if not specifed by -geometry option
00244 // or plspage
00245         plspage( 0., 0., 800, 600, 0, 0 );
00246     }
00247 
00248     pls->graphx = GRAPHICS_MODE;
00249 
00250     dev->cgmx = pls->xlength - 1;       // should I use -1 or not???
00251     dev->cgmy = pls->ylength - 1;
00252 
00253 #ifdef use_experimental_hidden_line_hack
00254 
00255     if ( dev->cgmx > dev->cgmy ) // Work out the scaling factor for the
00256     {                            // "virtual" (oversized) page
00257         dev->scale = ( PIXELS_X - 1 ) / dev->cgmx;
00258     }
00259     else
00260     {
00261         dev->scale = PIXELS_Y / dev->cgmy;
00262     }
00263 #else
00264 
00265     dev->scale = 1;
00266 
00267 #endif
00268 
00269     if ( pls->xdpi <= 0 )
00270     {
00271 // This corresponds to a typical monitor resolution of 4 pixels/mm.
00272         plspage( 4. * 25.4, 4. * 25.4, 0, 0, 0, 0 );
00273     }
00274     else
00275     {
00276         pls->ydpi = pls->xdpi;        // Set X and Y dpi's to the same value
00277     }
00278 // Convert DPI to pixels/mm
00279     plP_setpxl( dev->scale * pls->xdpi / 25.4, dev->scale * pls->ydpi / 25.4 );
00280 
00281     plP_setphy( 0, dev->scale * dev->cgmx, 0, dev->scale * dev->cgmy );
00282 }
00283 
00284 //--------------------------------------------------------------------------
00285 // plD_line_cgm()
00286 //
00287 // Draw a line in the current color from (x1,y1) to (x2,y2).
00288 //--------------------------------------------------------------------------
00289 
00290 void
00291 plD_line_cgm( PLStream *pls, short x1a, short y1a, short x2a, short y2a )
00292 {
00293     cgm_Dev *dev = (cgm_Dev *) pls->dev;
00294     int     x1   = x1a / dev->scale, y1 = y1a / dev->scale, x2 = x2a / dev->scale, y2 = y2a / dev->scale;
00295     y1 = y1;
00296     y2 = y2;
00297 
00298 //
00299 // Determine if the colour has changed since the last time a line was
00300 // drawn. If it has, then set the colour NOW otherwise, keep on going like
00301 // "nuthin happened".
00302 //
00303 
00304     if ( dev->last_line_colour != dev->colour )
00305     {
00306         cdSetLineColor( dev->im_out, dev->colour );
00307         dev->last_line_colour = dev->colour;
00308     }
00309 
00310     cdLine( dev->im_out, x1, y1, x2, y2 );
00311 }
00312 
00313 //--------------------------------------------------------------------------
00314 // plD_polyline_cgm()
00315 //
00316 // Draw a polyline in the current color.
00317 //--------------------------------------------------------------------------
00318 
00319 void
00320 plD_polyline_cgm( PLStream *pls, short *xa, short *ya, PLINT npts )
00321 {
00322     cgm_Dev *dev = (cgm_Dev *) pls->dev;
00323     PLINT   i;
00324     cdPoint *points = NULL;
00325 
00326     if ( ( points = calloc( npts, (size_t) sizeof ( cdPoint ) ) ) == NULL )
00327     {
00328         plexit( "Memory allocation error in \"plD_polyline_cgm\"" );
00329     }
00330 
00331     for ( i = 0; i < npts; i++ )
00332     {
00333         points[i].x = xa[i] / dev->scale;
00334         points[i].y = ( ya[i] / dev->scale );
00335     }
00336 
00337 //
00338 // Determine if the colour has changed since the last time a line was
00339 // drawn. If it has, then set the colour NOW otherwise, keep on going like
00340 // "nuthin happened".
00341 //
00342 
00343     if ( dev->last_line_colour != dev->colour )
00344     {
00345         cdSetLineColor( dev->im_out, dev->colour );
00346         dev->last_line_colour = dev->colour;
00347     }
00348 
00349     cdPolyLine( dev->im_out, points, npts );
00350     free( points );
00351 }
00352 
00353 
00354 //--------------------------------------------------------------------------
00355 // fill_polygon()
00356 //
00357 // Fill polygon described in points pls->dev_x[] and pls->dev_y[].
00358 //--------------------------------------------------------------------------
00359 
00360 static void
00361 fill_polygon( PLStream *pls )
00362 {
00363     cgm_Dev *dev = (cgm_Dev *) pls->dev;
00364 
00365     PLINT   i;
00366     cdPoint *points = NULL;
00367 
00368     if ( pls->dev_npts < 1 )
00369         return;
00370 
00371     if ( ( points = calloc( pls->dev_npts, (size_t) sizeof ( cdPoint ) ) ) == NULL )
00372     {
00373         plexit( "Memory allocation error in \"plD_fill_polygon_cgm\"" );
00374     }
00375 
00376     for ( i = 0; i < pls->dev_npts; i++ )
00377     {
00378         points[i].x = pls->dev_x[i] / dev->scale;
00379         points[i].y = ( pls->dev_y[i] / dev->scale );
00380     }
00381 
00382 
00383 //
00384 // Determine if the fill colour has changed since the last time a fill was
00385 // done. If it has, then set the colour NOW otherwise, keep on going like
00386 // "nuthin happened". If it's the first time, we will know 'cause the the
00387 // "last_fill_colour" will be -1.
00388 //
00389 
00390     if ( ( dev->fill_colour != dev->last_fill_colour ) || ( dev->force_edges == 1 ) )
00391     {
00392         cdSetFillColor( dev->im_out, dev->fill_colour );
00393 
00394 //
00395 // Due to a bug in cd V1.3, we have to set the edge colour to the fill
00396 // colour. This is despite telling the library edges should be invisible.
00397 // Seems the invisible edges only work with rectangles.
00398 //
00399 
00400         if ( dev->force_edges == 1 )
00401         {
00402             cdSetEdgeColor( dev->im_out, dev->fill_colour );
00403             cdSetEdgeVis( dev->im_out, 1 );
00404         }
00405 
00406         dev->last_fill_colour = dev->fill_colour;
00407     }
00408 
00409     cdPolygon( dev->im_out, points, pls->dev_npts );
00410 
00411     if ( dev->force_edges == 1 )
00412         cdSetEdgeVis( dev->im_out, 0 );                          // Turn edges off now
00413 
00414     free( points );
00415 }
00416 
00417 //--------------------------------------------------------------------------
00418 // setcmap()
00419 //
00420 // Sets up color palette.
00421 //--------------------------------------------------------------------------
00422 
00423 static void
00424 setcmap( PLStream *pls )
00425 {
00426     int     i, ncol1 = pls->ncol1;
00427     int     ncol0 = pls->ncol0, total_colours;
00428     PLColor cmap1col;
00429     cgm_Dev *dev = (cgm_Dev *) pls->dev;
00430     PLFLT   tmp_colour_pos;
00431 
00432     cdImageColorClear( dev->im_out );           // UNDOCUMENTED FUNCTION TO RESET THE
00433     // INTERNAL COLOUR TABLE OF THE
00434     // CD DRIVER. Seems to work and fix
00435     // the errors
00436 
00437     if ( ncol0 > cdMaxColors / 2 )              // Check for ridiculous number of colours
00438     {                                           // in ncol0, and appropriately adjust the
00439         plwarn( "Too many colours in cmap0." ); // number, issuing a
00440         ncol0      = cdMaxColors / 2;           // warning if it does
00441         pls->ncol0 = ncol0;
00442     }
00443 
00444     dev->totcol = 0;                           // Reset the number of colours counter to zero
00445 
00446     total_colours = ncol0 + ncol1;             // Work out how many colours are wanted
00447 
00448     if ( total_colours > cdMaxColors )         // Do some rather modest error
00449     {                                          // checking to make sure that
00450         total_colours = cdMaxColors;           // we are not defining more colours
00451         ncol1         = total_colours - ncol0; // than we have room for.
00452 
00453         if ( ncol1 <= 0 )
00454         {
00455             plexit( "Problem setting colourmap in CGM driver." );
00456         }
00457     }
00458 
00459     dev->ncol1 = ncol1; // The actual size of ncol1, regardless of what was asked.
00460                         // This is dependent on colour slots available.
00461                         // It might well be the same as ncol1.
00462                         //
00463 
00464 // Initialize cmap 0 colors
00465 
00466     if ( ncol0 > 0 ) // make sure the program actually asked for cmap0 first
00467     {
00468 #ifdef SWAP_BALCK_WHEN_WHITE
00469 
00470 //
00471 // Do a kludge to add a "black" colour back to the palette if the
00472 // background is "almost white" (ie changed through -bg).
00473 //
00474 // Also includes an "optional" change to swap the red colour (1) with the
00475 // black colour (15), which is off by default. (I don't like the red being
00476 // the 'default' colour "1" on a "white" background, or for that matter
00477 // yellow being "2", but I can live more with yellow at number two.)
00478 // Just use "-hack" from the command line to make it take effect.
00479 //
00480 //
00481 
00482         if ( ( pls->ncol0 > 15 ) && ( pls->cmap0[0].r > 227 ) && ( pls->cmap0[0].g > 227 ) && ( pls->cmap0[0].b > 227 ) )
00483         {
00484             if ( pls->hack != 1 ) // just set colour 15 to black
00485             {
00486                 pls->cmap0[15].r = 0;
00487                 pls->cmap0[15].g = 0;
00488                 pls->cmap0[15].b = 0;
00489             }
00490             else // swap colour 15 and colour 1
00491             {
00492                 pls->cmap0[15].r = pls->cmap0[1].r;
00493                 pls->cmap0[15].g = pls->cmap0[1].g;
00494                 pls->cmap0[15].b = pls->cmap0[1].b;
00495 
00496                 pls->cmap0[1].r = 0;
00497                 pls->cmap0[1].g = 0;
00498                 pls->cmap0[1].b = 0;
00499             }
00500         }
00501 
00502 #endif
00503 
00504         for ( i = 0; i < ncol0; i++ )
00505         {
00506             if ( (
00507                      dev->colour_index[i] = cdImageColorAllocate( dev->im_out,
00508                          pls->cmap0[i].r, pls->cmap0[i].g, pls->cmap0[i].b )
00509                      ) == -1 )
00510             {
00511                 plwarn( "Problem setting cmap0 in CGM driver." );
00512             }
00513             else
00514                 ++dev->totcol; // count the number of colours we use as we use them
00515         }
00516     }
00517 
00518 // Initialize any remaining slots for cmap1
00519 
00520 
00521     if ( ncol1 > 0 ) // make sure that we want to define cmap1 first
00522     {
00523         for ( i = 0; i < ncol1; i++ )
00524         {
00525             if ( ncol1 < pls->ncol1 ) // Check the dynamic range of colours
00526             {
00527                 //
00528                 // Ok, now if we have less colour slots available than are being
00529                 // defined by pls->ncol1, then we still want to use the full
00530                 // dynamic range of cmap1 as best we can, so what we do is work
00531                 // out an approximation to the index in the full dynamic range
00532                 // in cases when pls->ncol1 exceeds the number of free colours.
00533                 //
00534 
00535                 tmp_colour_pos = i > 0 ? pls->ncol1 * ( (PLFLT) i / ncol1 ) : 0;
00536                 plcol_interp( pls, &cmap1col, (int) tmp_colour_pos, pls->ncol1 );
00537             }
00538             else
00539             {
00540                 plcol_interp( pls, &cmap1col, i, ncol1 );
00541             }
00542 
00543 
00544             if ( (
00545                      dev->colour_index[i + pls->ncol0] = cdImageColorAllocate( dev->im_out,
00546                          cmap1col.r, cmap1col.g, cmap1col.b )
00547                      ) == -1 )
00548             {
00549                 plwarn( "Problem setting cmap1 in CGM driver." );
00550             }
00551             else
00552                 ++dev->totcol; // count the number of colours we use as we use them
00553         }
00554     }
00555 }
00556 
00557 
00558 //--------------------------------------------------------------------------
00559 // plD_state_cgm()
00560 //
00561 // Handle change in PLStream state (color, pen width, fill attribute, etc).
00562 //--------------------------------------------------------------------------
00563 
00564 void
00565 plD_state_cgm( PLStream *pls, PLINT op )
00566 {
00567     cgm_Dev *dev = (cgm_Dev *) pls->dev;
00568     PLFLT   tmp_colour_pos;
00569 
00570     switch ( op )
00571     {
00572     case PLSTATE_WIDTH:
00573         cdSetLineWidth( dev->im_out, pls->width );
00574         break;
00575 
00576     case PLSTATE_COLOR0:
00577         dev->colour = pls->icol0;
00578         if ( dev->colour == PL_RGB_COLOR )
00579         {
00580             int r = pls->curcolor.r;
00581             int g = pls->curcolor.g;
00582             int b = pls->curcolor.b;
00583             if ( dev->totcol < cdMaxColors )
00584             {
00585                 if ( (
00586                          dev->colour_index[++dev->totcol] = cdImageColorAllocate( dev->im_out, r, g, b )
00587                          ) == -1 )
00588                     plwarn( "Problem changing colour in \"PLSTATE_COLOR0\"" );
00589                 else
00590                     dev->colour = dev->totcol;
00591             }
00592         }
00593         dev->fill_colour = dev->colour;
00594         break;
00595 
00596     case PLSTATE_COLOR1:
00597         //
00598         // Start by checking to see if we have to compensate for cases where
00599         // we don't have the full dynamic range of cmap1 at our disposal
00600         //
00601         if ( dev->ncol1 < pls->ncol1 )
00602         {
00603             tmp_colour_pos = dev->ncol1 * ( (PLFLT) pls->icol1 / ( pls->ncol1 > 0 ? pls->ncol1 : 1 ) );
00604             dev->colour    = pls->ncol0 + (int) tmp_colour_pos;
00605         }
00606         else
00607             dev->colour = pls->ncol0 + pls->icol1;
00608 
00609         dev->fill_colour = dev->colour;
00610         break;
00611 
00612 
00613     case PLSTATE_CMAP0:
00614     case PLSTATE_CMAP1:
00615         //
00616         //  Code to redefine the entire palette
00617         //
00618         if ( pls->color )
00619             setcmap( pls );
00620         break;
00621     }
00622 }
00623 
00624 
00625 //--------------------------------------------------------------------------
00626 // plD_esc_cgm()
00627 //
00628 // Escape function.
00629 //--------------------------------------------------------------------------
00630 
00631 void plD_esc_cgm( PLStream *pls, PLINT op, void *ptr )
00632 {
00633     switch ( op )
00634     {
00635     case PLESC_FILL:    // fill
00636         fill_polygon( pls );
00637         break;
00638     }
00639 }
00640 
00641 //--------------------------------------------------------------------------
00642 // plD_bop_cgm()
00643 //
00644 // Set up for the next page.
00645 // Advance to next family file if necessary (file output).
00646 //--------------------------------------------------------------------------
00647 
00648 void plD_bop_cgm( PLStream *pls )
00649 {
00650     cgm_Dev *dev;
00651 
00652     plGetFam( pls );
00653 // force new file if pls->family set for all subsequent calls to plGetFam
00654 // n.b. putting this after plGetFam call is important since plinit calls
00655 // bop, and you don't want the familying sequence started until after
00656 // that first call to bop.
00657 
00658     pls->famadv = 1;
00659 
00660     pls->page++;
00661 
00662 // n.b. pls->dev can change because of an indirect call to plD_init_cgm
00663 // from plGetFam if familying is enabled.  Thus, wait to define dev until
00664 // now.
00665 
00666     dev = (cgm_Dev *) pls->dev;
00667 
00668     if ( pls->page == 1 )
00669     {
00670         dev->im_out = cdImageCreate( pls->xlength, pls->ylength );
00671     }
00672     else if ( pls->family != 1 )
00673     {
00674         cdCgmNewPic( dev->im_out, 0 );
00675     }
00676 
00677     setcmap( pls );
00678 
00679 // Continue to initialise the driver
00680 
00681     cdSetFillStyle( dev->im_out, 1 ); // Set solid fills
00682 
00683 //
00684 // Due to a border being drawn around the edge of the image, we also
00685 // manually, then turn them off again to make edges turn off. By
00686 // default the driver thinks they are off, so when we tell the driver
00687 // to turn them off it says "they are already off, I wont do anything"
00688 // but in reality they are on by default. So what we do is turn them ON
00689 // manually, then turn them OFF later.
00690 //
00691 // Due to a boarder being drawn around the edge of the image, we also
00692 // want the edges turned on so we can lay down a rectangle coloured in
00693 // the background colour at the start. Once we have drawn our
00694 // background box, we then turn edges off for the rest of the page.
00695 //
00696 
00697     cdSetEdgeVis( dev->im_out, 1 ); // turn edges on so we can turn them off!
00698 
00699     if ( dev->disable_background != 1 )
00700     {
00701         cdSetEdgeWidth( dev->im_out, pls->xlength / 5 );                      // set edge to *really* wide so we can cover the edge of the page completelt
00702         cdSetEdgeColor( dev->im_out, 0 );                                     // set the edge colour to the background colour so we can make a coloured page
00703         cdSetFillColor( dev->im_out, 0 );                                     // set fill colour to background colour so we have a coloured page
00704         cdRectangle( dev->im_out, 0, 0, pls->xlength - 1, pls->ylength - 1 ); // Draw a coloured rectangle to act as our "paper"
00705     }
00706 
00707     cdSetEdgeVis( dev->im_out, 0 );            // Turn edges off now
00708     cdSetEdgeWidth( dev->im_out, 0 );          // Just to be 100% sure
00709 
00710     cdSetLineType( dev->im_out, 1 );           // set solid lines
00711     cdSetLineWidth( dev->im_out, pls->width ); // set initial line width for each page
00712 }
00713 
00714 //--------------------------------------------------------------------------
00715 // plD_tidy_cgm()
00716 //
00717 // Close graphics file or otherwise clean up.
00718 //--------------------------------------------------------------------------
00719 
00720 void plD_tidy_cgm( PLStream *pls )
00721 {
00722     cgm_Dev *dev = (cgm_Dev *) pls->dev;
00723 
00724     if ( pls->family != 1 )
00725     {
00726         cdImageCgm( dev->im_out, pls->OutFile );
00727     }
00728 
00729     cdImageDestroy( dev->im_out );
00730     plCloseFile( pls );
00731     free_mem( pls->dev );
00732 }
00733 
00734 //--------------------------------------------------------------------------
00735 // plD_eop_cgm()
00736 //
00737 // End of page.
00738 //--------------------------------------------------------------------------
00739 
00740 void plD_eop_cgm( PLStream *pls )
00741 {
00742     cgm_Dev *dev = (cgm_Dev *) pls->dev;
00743     int     i;
00744 
00745     if ( pls->family == 1 )
00746     {
00747         cdImageCgm( dev->im_out, pls->OutFile );
00748     }
00749     for ( i = 0; i < cdMaxColors; ++i )
00750         dev->colour_index[i] = -1;
00751 
00752     dev->fill_colour      = dev->colour; // initially set fill and line colour the same
00753     dev->last_fill_colour = -1;          // set to -1 = unallocated
00754     dev->last_line_colour = -1;          // set to -1 = unallocated
00755 }
00756 
00757 
00758 //#endif
00759 
00760 
00761 #else
00762 int
00763 pldummy_cgm()
00764 {
00765     return 0;
00766 }
00767 
00768 #endif                          // cgm
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines