00001
00002
00003
00004
00005 #include "plDevs.h"
00006
00007 #ifdef PLD_xfig
00008
00009 #include "plplotP.h"
00010 #include "drivers.h"
00011
00012
00013 PLDLLIMPEXP_DRIVER const char* plD_DEVICE_INFO_xfig = "xfig:Fig file:0:xfig:31:xfig\n";
00014
00015 typedef struct
00016 {
00017 PLINT xold, yold;
00018
00019 PLINT xmin, xmax;
00020 PLINT ymin, ymax;
00021
00022 PLFLT xscale_dev, yscale_dev;
00023
00024 int *buffptr, bufflen;
00025 int count;
00026 int curwid;
00027 int curcol;
00028 int firstline;
00029 long cmap0_pos, cmap1_pos;
00030 int cmap0_ncol, cmap1_ncol;
00031 int offset, offset_inc;
00032 } xfig_Dev;
00033
00034
00035
00036 void plD_dispatch_init_xfig( PLDispatchTable *pdt );
00037
00038 void plD_init_xfig( PLStream * );
00039 void plD_line_xfig( PLStream *, short, short, short, short );
00040 void plD_polyline_xfig( PLStream *, short *, short *, PLINT );
00041 void plD_eop_xfig( PLStream * );
00042 void plD_bop_xfig( PLStream * );
00043 void plD_tidy_xfig( PLStream * );
00044 void plD_state_xfig( PLStream *, PLINT );
00045 void plD_esc_xfig( PLStream *, PLINT, void * );
00046
00047 static void flushbuffer( PLStream * );
00048
00049
00050
00051 #define FIGX 297 // portrait A4 mm
00052 #define FIGY 210
00053 #define DPI 1200
00054
00055
00056
00057
00058
00059 #define BSIZE 25
00060 #define XFIG_COLBASE 33 // xfig first user color, plplot colormap0[0],
00061
00062
00063
00064 static void stcmap0( PLStream * );
00065 static void stcmap1( PLStream * );
00066 static void proc_str( PLStream *, EscText * );
00067
00068 static int text = 0;
00069
00070 static DrvOpt xfig_options[] = { { "text", DRV_INT, &text, "Use Postscript text (text=1|0)" },
00071 { NULL, DRV_INT, NULL, NULL } };
00072
00073 void plD_dispatch_init_xfig( PLDispatchTable *pdt )
00074 {
00075 #ifndef ENABLE_DYNDRIVERS
00076 pdt->pl_MenuStr = "Xfig file";
00077 pdt->pl_DevName = "xfig";
00078 #endif
00079 pdt->pl_type = plDevType_FileOriented;
00080 pdt->pl_seq = 31;
00081 pdt->pl_init = (plD_init_fp) plD_init_xfig;
00082 pdt->pl_line = (plD_line_fp) plD_line_xfig;
00083 pdt->pl_polyline = (plD_polyline_fp) plD_polyline_xfig;
00084 pdt->pl_eop = (plD_eop_fp) plD_eop_xfig;
00085 pdt->pl_bop = (plD_bop_fp) plD_bop_xfig;
00086 pdt->pl_tidy = (plD_tidy_fp) plD_tidy_xfig;
00087 pdt->pl_state = (plD_state_fp) plD_state_xfig;
00088 pdt->pl_esc = (plD_esc_fp) plD_esc_xfig;
00089 }
00090
00091
00092
00093
00094
00095
00096
00097 void
00098 plD_init_xfig( PLStream *pls )
00099 {
00100 xfig_Dev *dev;
00101
00102 plParseDrvOpts( xfig_options );
00103 if ( text )
00104 pls->dev_text = 1;
00105
00106
00107
00108 plFamInit( pls );
00109
00110
00111
00112 plOpenFile( pls );
00113
00114
00115
00116 if ( pls->dev != NULL )
00117 free( (void *) pls->dev );
00118
00119 pls->dev = calloc( 1, (size_t) sizeof ( xfig_Dev ) );
00120
00121 if ( pls->dev == NULL )
00122 plexit( "plD_init_xfig: cannot allocate memory\n" );
00123
00124 dev = (xfig_Dev *) pls->dev;
00125
00126 dev->curwid = pls->width < 1 ? 1 : pls->width;
00127 dev->firstline = 1;
00128
00129 dev->xold = PL_UNDEFINED;
00130 dev->yold = PL_UNDEFINED;
00131 dev->xmin = 0;
00132 dev->xmax = FIGX;
00133 dev->ymin = 0;
00134 dev->ymax = FIGY;
00135 dev->xscale_dev = DPI / 25.4;
00136 dev->yscale_dev = DPI / 25.4;
00137 dev->offset_inc = dev->ymax * (PLINT) dev->yscale_dev;
00138 dev->offset = -dev->offset_inc;
00139 pls->dev_fill0 = 1;
00140 if ( !pls->colorset )
00141 pls->color = 1;
00142
00143 plP_setpxl( dev->xscale_dev, dev->xscale_dev );
00144 plP_setphy( 0, (PLINT) ( FIGX * dev->xscale_dev ), 0, (PLINT) ( FIGY * dev->yscale_dev ) );
00145
00146
00147
00148 fprintf( pls->OutFile, "#FIG 3.2\n" );
00149 fprintf( pls->OutFile, "Landscape\n" );
00150 fprintf( pls->OutFile, "Center\n" );
00151 fprintf( pls->OutFile, "Metric\n" );
00152 fprintf( pls->OutFile, "A4\n" );
00153 fprintf( pls->OutFile, "100.0\n" );
00154 fprintf( pls->OutFile, "Single\n" );
00155 fprintf( pls->OutFile, "-2\n" );
00156 fprintf( pls->OutFile, "%d 2\n", DPI );
00157
00158
00159 dev->cmap0_ncol = 2 * pls->ncol0;
00160 dev->cmap0_pos = ftell( pls->OutFile );
00161 stcmap0( pls );
00162
00163
00164 dev->cmap1_ncol = 2 * pls->ncol1;
00165 dev->cmap1_pos = ftell( pls->OutFile );
00166 stcmap1( pls );
00167
00168 dev->bufflen = 2 * BSIZE;
00169 dev->buffptr = (int *) malloc( sizeof ( int ) * dev->bufflen );
00170 if ( dev->buffptr == NULL )
00171 plexit( "plD_init_xfig: Out of memory!" );
00172 }
00173
00174 void
00175 stcmap0( PLStream *pls )
00176 {
00177 xfig_Dev *dev;
00178 long cur_pos;
00179 int i;
00180
00181 dev = (xfig_Dev *) pls->dev;
00182
00183 if ( pls->ncol0 > dev->cmap0_ncol )
00184 plwarn( "Too many colors for cmap0. Preallocate using command line '-ncol0 n.\n'" );
00185
00186 cur_pos = ftell( pls->OutFile );
00187
00188 if ( fseek( pls->OutFile, dev->cmap0_pos, SEEK_SET ) )
00189 plexit( "Sorry, only file based output, no pipes.\n" );
00190
00191
00192 for ( i = 0; i < pls->ncol0; i++ )
00193 fprintf( pls->OutFile, "0 %d #%.2x%.2x%.2x\n", i + XFIG_COLBASE,
00194 pls->cmap0[i].r, pls->cmap0[i].g, pls->cmap0[i].b );
00195
00196
00197 for ( i = pls->ncol0; i < dev->cmap0_ncol; i++ )
00198 fprintf( pls->OutFile, "0 %d #000000\n", i + XFIG_COLBASE );
00199
00200 if ( cur_pos != dev->cmap0_pos )
00201 fseek( pls->OutFile, cur_pos, SEEK_SET );
00202 }
00203
00204 void
00205 stcmap1( PLStream *pls )
00206 {
00207 xfig_Dev *dev;
00208 long cur_pos;
00209 int i;
00210
00211 dev = (xfig_Dev *) pls->dev;
00212
00213 if ( pls->ncol1 > dev->cmap1_ncol )
00214 plwarn( "Too many colors for cmap1. Preallocate using command line '-ncol1 n.\n'" );
00215
00216 cur_pos = ftell( pls->OutFile );
00217
00218 if ( fseek( pls->OutFile, dev->cmap1_pos, SEEK_SET ) )
00219 plexit( "Sorry, only file based output, no pipes.\n" );
00220
00221
00222 for ( i = 0; i < pls->ncol1; i++ )
00223 fprintf( pls->OutFile, "0 %d #%.2x%.2x%.2x\n", i + XFIG_COLBASE + dev->cmap0_ncol,
00224 pls->cmap1[i].r, pls->cmap1[i].g, pls->cmap1[i].b );
00225
00226
00227 for ( i = pls->ncol1; i < dev->cmap1_ncol; i++ )
00228 fprintf( pls->OutFile, "0 %d #000000\n", i + XFIG_COLBASE + dev->cmap0_ncol );
00229
00230 if ( cur_pos != dev->cmap1_pos )
00231 fseek( pls->OutFile, cur_pos, SEEK_SET );
00232 }
00233
00234
00235
00236
00237
00238
00239
00240 void
00241 plD_line_xfig( PLStream *pls, short x1a, short y1a, short x2a, short y2a )
00242 {
00243 xfig_Dev *dev = (xfig_Dev *) pls->dev;
00244 int x1 = x1a, y1 = y1a, x2 = x2a, y2 = y2a;
00245 int *tempptr;
00246 int count;
00247
00248
00249
00250
00251
00252 if ( dev->firstline )
00253 {
00254 count = 0;
00255 *( dev->buffptr + count++ ) = x1;
00256 *( dev->buffptr + count++ ) = y1;
00257 *( dev->buffptr + count++ ) = x2;
00258 *( dev->buffptr + count++ ) = y2;
00259 dev->firstline = 0;
00260 }
00261 else if ( x1 == dev->xold && y1 == dev->yold )
00262 {
00263 count = dev->count;
00264 if ( count + 2 >= dev->bufflen )
00265 {
00266 dev->bufflen += 2 * BSIZE;
00267 tempptr = (int *)
00268 realloc( (void *) dev->buffptr, dev->bufflen * sizeof ( int ) );
00269 if ( tempptr == NULL )
00270 {
00271 free( (void *) dev->buffptr );
00272 plexit( "plD_line_xfig: Out of memory!" );
00273 }
00274 dev->buffptr = tempptr;
00275 }
00276 *( dev->buffptr + count++ ) = x2;
00277 *( dev->buffptr + count++ ) = y2;
00278 }
00279 else
00280 {
00281 flushbuffer( pls );
00282 count = dev->count;
00283 *( dev->buffptr + count++ ) = x1;
00284 *( dev->buffptr + count++ ) = y1;
00285 *( dev->buffptr + count++ ) = x2;
00286 *( dev->buffptr + count++ ) = y2;
00287 }
00288 dev->count = count;
00289 dev->xold = x2;
00290 dev->yold = y2;
00291 }
00292
00293
00294
00295
00296
00297
00298
00299 void
00300 plD_polyline_xfig( PLStream *pls, short *xa, short *ya, PLINT npts )
00301 {
00302 PLINT i;
00303
00304 for ( i = 0; i < npts - 1; i++ )
00305 plD_line_xfig( pls, xa[i], ya[i], xa[i + 1], ya[i + 1] );
00306 }
00307
00308
00309
00310
00311
00312
00313
00314 void
00315 plD_eop_xfig( PLStream *pls )
00316 {
00317 xfig_Dev *dev = (xfig_Dev *) pls->dev;
00318
00319 if ( !dev->firstline )
00320 flushbuffer( pls );
00321 }
00322
00323
00324
00325
00326
00327
00328
00329
00330 void
00331 plD_bop_xfig( PLStream *pls )
00332 {
00333 xfig_Dev *dev;
00334
00335 if ( !pls->termin )
00336 plGetFam( pls );
00337
00338 dev = (xfig_Dev *) pls->dev;
00339
00340 dev->xold = PL_UNDEFINED;
00341 dev->yold = PL_UNDEFINED;
00342 dev->firstline = 1;
00343
00344 pls->famadv = 1;
00345 pls->page++;
00346
00347 dev->offset += dev->offset_inc;
00348 flushbuffer( pls );
00349
00350
00351 dev->curcol = XFIG_COLBASE;
00352 fprintf( pls->OutFile, "2 1 0 1 %d %d 50 0 20 0.0 0 0 -1 0 0 5\n", dev->curcol, dev->curcol );
00353 fprintf( pls->OutFile, "%d %d %d %d %d %d %d %d %d %d\n",
00354 0, dev->offset,
00355 0, (int) ( FIGY * dev->yscale_dev ) + dev->offset,
00356 (int) ( FIGX * dev->xscale_dev ), (int) ( FIGY * dev->yscale_dev ) + dev->offset,
00357 (int) ( FIGX * dev->xscale_dev ), dev->offset,
00358 0, dev->offset );
00359 }
00360
00361
00362
00363
00364
00365
00366
00367 void
00368 plD_tidy_xfig( PLStream *pls )
00369 {
00370 xfig_Dev *dev = (xfig_Dev *) pls->dev;
00371
00372 flushbuffer( pls );
00373 free( (void *) dev->buffptr );
00374 plCloseFile( pls );
00375 }
00376
00377
00378
00379
00380
00381
00382
00383 void
00384 plD_state_xfig( PLStream *pls, PLINT op )
00385 {
00386 xfig_Dev *dev = (xfig_Dev *) pls->dev;
00387
00388 switch ( op )
00389 {
00390 case PLSTATE_WIDTH:
00391 flushbuffer( pls );
00392 dev->firstline = 1;
00393 dev->curwid = pls->width < 1 ? 1 : pls->width;
00394 break;
00395
00396 case PLSTATE_COLOR0:
00397 flushbuffer( pls );
00398 dev->curcol = pls->icol0 + XFIG_COLBASE;
00399 break;
00400
00401 case PLSTATE_COLOR1:
00402 flushbuffer( pls );
00403 dev->curcol = pls->icol1 + XFIG_COLBASE + pls->ncol0;
00404 break;
00405
00406 case PLSTATE_CMAP0:
00407 stcmap0( pls );
00408 break;
00409
00410 case PLSTATE_CMAP1:
00411 stcmap1( pls );
00412 break;
00413 }
00414 }
00415
00416
00417
00418
00419
00420
00421
00422
00423 void
00424 plD_esc_xfig( PLStream *pls, PLINT op, void *ptr )
00425 {
00426 xfig_Dev *dev = pls->dev;
00427 int i, npts;
00428
00429 switch ( op )
00430 {
00431 case PLESC_FILL:
00432
00433 npts = pls->dev_npts;
00434
00435 flushbuffer( pls );
00436 fprintf( pls->OutFile, "2 1 0 1 %d %d 50 0 20 0.0 0 0 0 0 0 %d\n",
00437 dev->curcol, dev->curcol, npts );
00438
00439 for ( i = 0; i < npts; i++ )
00440 fprintf( pls->OutFile, "%d %d ", pls->dev_x[i],
00441 dev->offset + dev->ymax * (int) dev->xscale_dev - pls->dev_y[i] );
00442
00443 fprintf( pls->OutFile, "\n" );
00444 break;
00445
00446 case PLESC_HAS_TEXT:
00447 proc_str( pls, ptr );
00448 break;
00449 }
00450 }
00451
00452
00453
00454
00455
00456 static void
00457 flushbuffer( PLStream *pls )
00458 {
00459 xfig_Dev *dev = pls->dev;
00460 int i = 0;
00461
00462 if ( dev->count == 0 )
00463 return;
00464
00465 fprintf( pls->OutFile, "2 1 0 %d %d 0 50 0 -1 0.0 0 0 0 0 0 %d\n",
00466 dev->curwid, dev->curcol, dev->count / 2 );
00467 while ( i < dev->count )
00468 {
00469 fprintf( pls->OutFile, "%d %d ", *( dev->buffptr + i ),
00470 dev->offset + dev->ymax * (int) dev->yscale_dev - *( dev->buffptr + i + 1 ) );
00471 i += 2;
00472 }
00473 fprintf( pls->OutFile, "\n" );
00474 dev->count = 0;
00475 }
00476
00477 void
00478 proc_str( PLStream *pls, EscText *args )
00479 {
00480 PLFLT *t = args->xform;
00481 PLFLT a1, alpha, ft_ht, angle, ref;
00482 xfig_Dev *dev = (xfig_Dev *) pls->dev;
00483 PLINT clxmin, clxmax, clymin, clymax;
00484 int jst, font;
00485
00486
00487 ft_ht = pls->chrht * 72.0 / 25.4;
00488
00489
00490 angle = pls->diorot * 90.;
00491 a1 = acos( t[0] ) * 180. / PI;
00492 if ( t[2] > 0. )
00493 alpha = a1 - angle;
00494 else
00495 alpha = 360. - a1 - angle;
00496
00497 alpha = alpha * PI / 180.;
00498
00499
00500
00501
00502
00503 difilt( &args->x, &args->y, 1, &clxmin, &clxmax, &clymin, &clymax );
00504
00505
00506
00507
00508
00509
00510 if ( args->x < clxmin || args->x > clxmax || args->y < clymin || args->y > clymax )
00511 return;
00512
00513
00514
00515
00516
00517
00518
00519 if ( args->just == 0.5 )
00520 jst = 1;
00521 else if ( args->just == 1. )
00522 jst = 2;
00523 else
00524 {
00525 jst = 0;
00526 args->x = args->refx;
00527 args->y = args->refy;
00528 }
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539 if ( args->base == 2 )
00540 ref = -DPI / 72. * ft_ht / 2.;
00541 else if ( args->base == 1 )
00542 ref = 0.;
00543 else
00544 ref = DPI / 72. * ft_ht / 2.;
00545
00546
00547 args->y = (PLINT) ( dev->offset + dev->ymax * (int) dev->xscale_dev - ( args->y - ref * cos( alpha ) ) );
00548 args->x = (PLINT) ( args->x + ref * sin( alpha ) );
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560 switch ( pls->cfont )
00561 {
00562 case ( 1 ): font = 0; break;
00563 case ( 2 ): font = 1; break;
00564 case ( 3 ): font = 3; break;
00565 case ( 4 ): font = 4; break;
00566 default: font = 0;
00567 }
00568
00569 fprintf( pls->OutFile, "4 %d %d 50 0 %d %f %f 4 1 1 %d %d %s\\001\n",
00570 jst, dev->curcol, font, 1.8 * ft_ht, alpha, args->x, args->y, args->string );
00571 }
00572
00573 #else
00574 int
00575 pldummy_xfig()
00576 {
00577 return 0;
00578 }
00579
00580 #endif // PLD_xfig