PLplot
5.10.0
|
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