00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 #define SWAP_BALCK_WHEN_WHITE
00073
00074 #include "plDevs.h"
00075
00076 #ifdef PLD_cgm
00077
00078 #include "plplotP.h"
00079 #include "drivers.h"
00080
00081 #include <cd.h>
00082
00083
00084 PLDLLIMPEXP_DRIVER const char* plD_DEVICE_INFO_cgm = "cgm:CGM file:0:cgm:44:cgm\n";
00085
00086
00087
00088 static void fill_polygon( PLStream *pls );
00089 static void setcmap( PLStream *pls );
00090 static void plD_init_cgm_Dev( PLStream *pls );
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102 #define use_experimental_hidden_line_hack
00103
00104 static int force_edges = 0;
00105 static int disable_background = 0;
00106
00107 static DrvOpt cgm_options[] = { { "force_edges", DRV_INT, &force_edges, "Force edges to be drawn on filled polygongs (0|1)" },
00108 { "no_paper", DRV_INT, &disable_background, "Disable background (0|1)" },
00109 { NULL, DRV_INT, NULL, NULL } };
00110
00111
00112
00113
00114 typedef struct
00115 {
00116 cdImagePtr im_out;
00117 PLINT cgmx;
00118 PLINT cgmy;
00119
00120
00121
00122
00123
00124
00125
00126 int colour_index[256];
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136 int colour;
00137 int last_line_colour;
00138 int fill_colour;
00139 int last_fill_colour;
00140
00141 int totcol;
00142 int ncol1;
00143 int scale;
00144
00145 int force_edges;
00146 int disable_background;
00147 } cgm_Dev;
00148
00149 void plD_init_cgm( PLStream * );
00150 void plD_line_cgm( PLStream *, short, short, short, short );
00151 void plD_polyline_cgm( PLStream *, short *, short *, PLINT );
00152 void plD_eop_cgm( PLStream * );
00153 void plD_bop_cgm( PLStream * );
00154 void plD_tidy_cgm( PLStream * );
00155 void plD_state_cgm( PLStream *, PLINT );
00156 void plD_esc_cgm( PLStream *, PLINT, void * );
00157
00158
00159 void plD_dispatch_init_cgm( PLDispatchTable *pdt )
00160 {
00161 #ifndef ENABLE_DYNDRIVERS
00162 pdt->pl_MenuStr = "CGM (Computer Graphics metafile) file";
00163 pdt->pl_DevName = "cgm";
00164 #endif
00165 pdt->pl_type = plDevType_FileOriented;
00166 pdt->pl_seq = 44;
00167 pdt->pl_init = (plD_init_fp) plD_init_cgm;
00168 pdt->pl_line = (plD_line_fp) plD_line_cgm;
00169 pdt->pl_polyline = (plD_polyline_fp) plD_polyline_cgm;
00170 pdt->pl_eop = (plD_eop_fp) plD_eop_cgm;
00171 pdt->pl_bop = (plD_bop_fp) plD_bop_cgm;
00172 pdt->pl_tidy = (plD_tidy_fp) plD_tidy_cgm;
00173 pdt->pl_state = (plD_state_fp) plD_state_cgm;
00174 pdt->pl_esc = (plD_esc_fp) plD_esc_cgm;
00175 }
00176
00177
00178
00179
00180
00181
00182
00183 static void
00184 plD_init_cgm_Dev( PLStream *pls )
00185 {
00186 cgm_Dev *dev;
00187
00188
00189
00190 if ( pls->dev != NULL )
00191 free( (void *) pls->dev );
00192
00193 pls->dev = calloc( 1, (size_t) sizeof ( cgm_Dev ) );
00194 if ( pls->dev == NULL )
00195 plexit( "plD_init_cgm_Dev: Out of memory." );
00196
00197 dev = (cgm_Dev *) pls->dev;
00198
00199
00200
00201 plParseDrvOpts( cgm_options );
00202 dev->force_edges = force_edges;
00203 dev->disable_background = disable_background;
00204
00205 dev->colour = 1;
00206 dev->fill_colour = dev->colour;
00207 dev->last_fill_colour = -1;
00208 dev->last_line_colour = -1;
00209 }
00210
00211
00212
00213
00214
00215
00216
00217 void plD_init_cgm( PLStream *pls )
00218 {
00219 cgm_Dev *dev = NULL;
00220
00221 pls->termin = 0;
00222 pls->icol0 = 1;
00223 pls->bytecnt = 0;
00224 pls->page = 0;
00225 pls->dev_fill0 = 1;
00226
00227 if ( !pls->colorset )
00228 pls->color = 1;
00229
00230 if ( pls->width < 1 )
00231 pls->width = 1;
00232
00233
00234 plFamInit( pls );
00235
00236
00237 plOpenFile( pls );
00238
00239
00240 plD_init_cgm_Dev( pls );
00241 dev = (cgm_Dev *) pls->dev;
00242
00243 if ( pls->xlength <= 0 || pls->ylength <= 0 )
00244 {
00245
00246
00247 plspage( 0., 0., 800, 600, 0, 0 );
00248 }
00249
00250 pls->graphx = GRAPHICS_MODE;
00251
00252 dev->cgmx = pls->xlength - 1;
00253 dev->cgmy = pls->ylength - 1;
00254
00255 #ifdef use_experimental_hidden_line_hack
00256
00257 if ( dev->cgmx > dev->cgmy )
00258 {
00259 dev->scale = ( PIXELS_X - 1 ) / dev->cgmx;
00260 }
00261 else
00262 {
00263 dev->scale = PIXELS_Y / dev->cgmy;
00264 }
00265 #else
00266
00267 dev->scale = 1;
00268
00269 #endif
00270
00271 if ( pls->xdpi <= 0 )
00272 {
00273
00274 plspage( 4. * 25.4, 4. * 25.4, 0, 0, 0, 0 );
00275 }
00276 else
00277 {
00278 pls->ydpi = pls->xdpi;
00279 }
00280
00281 plP_setpxl( dev->scale * pls->xdpi / 25.4, dev->scale * pls->ydpi / 25.4 );
00282
00283 plP_setphy( 0, dev->scale * dev->cgmx, 0, dev->scale * dev->cgmy );
00284 }
00285
00286
00287
00288
00289
00290
00291
00292 void
00293 plD_line_cgm( PLStream *pls, short x1a, short y1a, short x2a, short y2a )
00294 {
00295 cgm_Dev *dev = (cgm_Dev *) pls->dev;
00296 int x1 = x1a / dev->scale, y1 = y1a / dev->scale, x2 = x2a / dev->scale, y2 = y2a / dev->scale;
00297 y1 = y1;
00298 y2 = y2;
00299
00300
00301
00302
00303
00304
00305
00306 if ( dev->last_line_colour != dev->colour )
00307 {
00308 cdSetLineColor( dev->im_out, dev->colour );
00309 dev->last_line_colour = dev->colour;
00310 }
00311
00312 cdLine( dev->im_out, x1, y1, x2, y2 );
00313 }
00314
00315
00316
00317
00318
00319
00320
00321 void
00322 plD_polyline_cgm( PLStream *pls, short *xa, short *ya, PLINT npts )
00323 {
00324 cgm_Dev *dev = (cgm_Dev *) pls->dev;
00325 PLINT i;
00326 cdPoint *points = NULL;
00327
00328 if ( ( points = calloc( npts, (size_t) sizeof ( cdPoint ) ) ) == NULL )
00329 {
00330 plexit( "Memory allocation error in \"plD_polyline_cgm\"" );
00331 }
00332
00333 for ( i = 0; i < npts; i++ )
00334 {
00335 points[i].x = xa[i] / dev->scale;
00336 points[i].y = ( ya[i] / dev->scale );
00337 }
00338
00339
00340
00341
00342
00343
00344
00345 if ( dev->last_line_colour != dev->colour )
00346 {
00347 cdSetLineColor( dev->im_out, dev->colour );
00348 dev->last_line_colour = dev->colour;
00349 }
00350
00351 cdPolyLine( dev->im_out, points, npts );
00352 free( points );
00353 }
00354
00355
00356
00357
00358
00359
00360
00361
00362 static void
00363 fill_polygon( PLStream *pls )
00364 {
00365 cgm_Dev *dev = (cgm_Dev *) pls->dev;
00366
00367 PLINT i;
00368 cdPoint *points = NULL;
00369
00370 if ( pls->dev_npts < 1 )
00371 return;
00372
00373 if ( ( points = calloc( pls->dev_npts, (size_t) sizeof ( cdPoint ) ) ) == NULL )
00374 {
00375 plexit( "Memory allocation error in \"plD_fill_polygon_cgm\"" );
00376 }
00377
00378 for ( i = 0; i < pls->dev_npts; i++ )
00379 {
00380 points[i].x = pls->dev_x[i] / dev->scale;
00381 points[i].y = ( pls->dev_y[i] / dev->scale );
00382 }
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392 if ( ( dev->fill_colour != dev->last_fill_colour ) || ( dev->force_edges == 1 ) )
00393 {
00394 cdSetFillColor( dev->im_out, dev->fill_colour );
00395
00396
00397
00398
00399
00400
00401
00402 if ( dev->force_edges == 1 )
00403 {
00404 cdSetEdgeColor( dev->im_out, dev->fill_colour );
00405 cdSetEdgeVis( dev->im_out, 1 );
00406 }
00407
00408 dev->last_fill_colour = dev->fill_colour;
00409 }
00410
00411 cdPolygon( dev->im_out, points, pls->dev_npts );
00412
00413 if ( dev->force_edges == 1 )
00414 cdSetEdgeVis( dev->im_out, 0 );
00415
00416 free( points );
00417 }
00418
00419
00420
00421
00422
00423
00424
00425 static void
00426 setcmap( PLStream *pls )
00427 {
00428 int i, ncol1 = pls->ncol1;
00429 int ncol0 = pls->ncol0, total_colours;
00430 PLColor cmap1col;
00431 cgm_Dev *dev = (cgm_Dev *) pls->dev;
00432 PLFLT tmp_colour_pos;
00433
00434 cdImageColorClear( dev->im_out );
00435
00436
00437
00438
00439 if ( ncol0 > cdMaxColors / 2 )
00440 {
00441 plwarn( "Too many colours in cmap0." );
00442 ncol0 = cdMaxColors / 2;
00443 pls->ncol0 = ncol0;
00444 }
00445
00446 dev->totcol = 0;
00447
00448 total_colours = ncol0 + ncol1;
00449
00450 if ( total_colours > cdMaxColors )
00451 {
00452 total_colours = cdMaxColors;
00453 ncol1 = total_colours - ncol0;
00454
00455 if ( ncol1 <= 0 )
00456 {
00457 plexit( "Problem setting colourmap in CGM driver." );
00458 }
00459 }
00460
00461 dev->ncol1 = ncol1;
00462
00463
00464
00465
00466
00467
00468 if ( ncol0 > 0 )
00469 {
00470 #ifdef SWAP_BALCK_WHEN_WHITE
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484 if ( ( pls->ncol0 > 15 ) && ( pls->cmap0[0].r > 227 ) && ( pls->cmap0[0].g > 227 ) && ( pls->cmap0[0].b > 227 ) )
00485 {
00486 if ( pls->hack != 1 )
00487 {
00488 pls->cmap0[15].r = 0;
00489 pls->cmap0[15].g = 0;
00490 pls->cmap0[15].b = 0;
00491 }
00492 else
00493 {
00494 pls->cmap0[15].r = pls->cmap0[1].r;
00495 pls->cmap0[15].g = pls->cmap0[1].g;
00496 pls->cmap0[15].b = pls->cmap0[1].b;
00497
00498 pls->cmap0[1].r = 0;
00499 pls->cmap0[1].g = 0;
00500 pls->cmap0[1].b = 0;
00501 }
00502 }
00503
00504 #endif
00505
00506 for ( i = 0; i < ncol0; i++ )
00507 {
00508 if ( (
00509 dev->colour_index[i] = cdImageColorAllocate( dev->im_out,
00510 pls->cmap0[i].r, pls->cmap0[i].g, pls->cmap0[i].b )
00511 ) == -1 )
00512 {
00513 plwarn( "Problem setting cmap0 in CGM driver." );
00514 }
00515 else
00516 ++dev->totcol;
00517 }
00518 }
00519
00520
00521
00522
00523 if ( ncol1 > 0 )
00524 {
00525 for ( i = 0; i < ncol1; i++ )
00526 {
00527 if ( ncol1 < pls->ncol1 )
00528 {
00529
00530
00531
00532
00533
00534
00535
00536
00537 tmp_colour_pos = i > 0 ? pls->ncol1 * ( (PLFLT) i / ncol1 ) : 0;
00538 plcol_interp( pls, &cmap1col, (int) tmp_colour_pos, pls->ncol1 );
00539 }
00540 else
00541 {
00542 plcol_interp( pls, &cmap1col, i, ncol1 );
00543 }
00544
00545
00546 if ( (
00547 dev->colour_index[i + pls->ncol0] = cdImageColorAllocate( dev->im_out,
00548 cmap1col.r, cmap1col.g, cmap1col.b )
00549 ) == -1 )
00550 {
00551 plwarn( "Problem setting cmap1 in CGM driver." );
00552 }
00553 else
00554 ++dev->totcol;
00555 }
00556 }
00557 }
00558
00559
00560
00561
00562
00563
00564
00565
00566 void
00567 plD_state_cgm( PLStream *pls, PLINT op )
00568 {
00569 cgm_Dev *dev = (cgm_Dev *) pls->dev;
00570 PLFLT tmp_colour_pos;
00571
00572 switch ( op )
00573 {
00574 case PLSTATE_WIDTH:
00575 cdSetLineWidth( dev->im_out, pls->width );
00576 break;
00577
00578 case PLSTATE_COLOR0:
00579 dev->colour = pls->icol0;
00580 if ( dev->colour == PL_RGB_COLOR )
00581 {
00582 int r = pls->curcolor.r;
00583 int g = pls->curcolor.g;
00584 int b = pls->curcolor.b;
00585 if ( dev->totcol < cdMaxColors )
00586 {
00587 if ( (
00588 dev->colour_index[++dev->totcol] = cdImageColorAllocate( dev->im_out, r, g, b )
00589 ) == -1 )
00590 plwarn( "Problem changing colour in \"PLSTATE_COLOR0\"" );
00591 else
00592 dev->colour = dev->totcol;
00593 }
00594 }
00595 dev->fill_colour = dev->colour;
00596 break;
00597
00598 case PLSTATE_COLOR1:
00599
00600
00601
00602
00603 if ( dev->ncol1 < pls->ncol1 )
00604 {
00605 tmp_colour_pos = dev->ncol1 * ( (PLFLT) pls->icol1 / ( pls->ncol1 > 0 ? pls->ncol1 : 1 ) );
00606 dev->colour = pls->ncol0 + (int) tmp_colour_pos;
00607 }
00608 else
00609 dev->colour = pls->ncol0 + pls->icol1;
00610
00611 dev->fill_colour = dev->colour;
00612 break;
00613
00614
00615 case PLSTATE_CMAP0:
00616 case PLSTATE_CMAP1:
00617
00618
00619
00620 if ( pls->color )
00621 setcmap( pls );
00622 break;
00623 }
00624 }
00625
00626
00627
00628
00629
00630
00631
00632
00633 void plD_esc_cgm( PLStream *pls, PLINT op, void *ptr )
00634 {
00635 switch ( op )
00636 {
00637 case PLESC_FILL:
00638 fill_polygon( pls );
00639 break;
00640 }
00641 }
00642
00643
00644
00645
00646
00647
00648
00649
00650 void plD_bop_cgm( PLStream *pls )
00651 {
00652 cgm_Dev *dev;
00653
00654 plGetFam( pls );
00655
00656
00657
00658
00659
00660 pls->famadv = 1;
00661
00662 pls->page++;
00663
00664
00665
00666
00667
00668 dev = (cgm_Dev *) pls->dev;
00669
00670 if ( pls->page == 1 )
00671 {
00672 dev->im_out = cdImageCreate( pls->xlength, pls->ylength );
00673 }
00674 else if ( pls->family != 1 )
00675 {
00676 cdCgmNewPic( dev->im_out, 0 );
00677 }
00678
00679 setcmap( pls );
00680
00681
00682
00683 cdSetFillStyle( dev->im_out, 1 );
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699 cdSetEdgeVis( dev->im_out, 1 );
00700
00701 if ( dev->disable_background != 1 )
00702 {
00703 cdSetEdgeWidth( dev->im_out, pls->xlength / 5 );
00704 cdSetEdgeColor( dev->im_out, 0 );
00705 cdSetFillColor( dev->im_out, 0 );
00706 cdRectangle( dev->im_out, 0, 0, pls->xlength - 1, pls->ylength - 1 );
00707 }
00708
00709 cdSetEdgeVis( dev->im_out, 0 );
00710 cdSetEdgeWidth( dev->im_out, 0 );
00711
00712 cdSetLineType( dev->im_out, 1 );
00713 cdSetLineWidth( dev->im_out, pls->width );
00714 }
00715
00716
00717
00718
00719
00720
00721
00722 void plD_tidy_cgm( PLStream *pls )
00723 {
00724 cgm_Dev *dev = (cgm_Dev *) pls->dev;
00725
00726 if ( pls->family != 1 )
00727 {
00728 cdImageCgm( dev->im_out, pls->OutFile );
00729 }
00730
00731 cdImageDestroy( dev->im_out );
00732 plCloseFile( pls );
00733 free_mem( pls->dev );
00734 }
00735
00736
00737
00738
00739
00740
00741
00742 void plD_eop_cgm( PLStream *pls )
00743 {
00744 cgm_Dev *dev = (cgm_Dev *) pls->dev;
00745 int i;
00746
00747 if ( pls->family == 1 )
00748 {
00749 cdImageCgm( dev->im_out, pls->OutFile );
00750 }
00751 for ( i = 0; i < cdMaxColors; ++i )
00752 dev->colour_index[i] = -1;
00753
00754 dev->fill_colour = dev->colour;
00755 dev->last_fill_colour = -1;
00756 dev->last_line_colour = -1;
00757 }
00758
00759
00760
00761
00762
00763 #else
00764 int
00765 pldummy_cgm()
00766 {
00767 return 0;
00768 }
00769
00770 #endif // cgm