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 #include "plDevs.h"
00032
00033 #define DEBUG
00034
00035 #ifdef PLD_ps
00036 #define NEED_PLDEBUG
00037 #include "plplotP.h"
00038 #include "drivers.h"
00039 #include "ps.h"
00040
00041 #include <string.h>
00042 #include <time.h>
00043 #include "plunicode-type1.h"
00044 #include "plfci-type1.h"
00045
00046
00047
00048 #define TRMFLT( a ) ( ( fabs( a ) < 5.0e-4 ) ? 0.0 : ( a ) )
00049
00050
00051
00052 PLDLLIMPEXP_DRIVER const char* plD_DEVICE_INFO_ps =
00053 "ps:PostScript File (monochrome):0:ps:29:psm\n"
00054 "psc:PostScript File (color):0:ps:30:psc\n";
00055
00056
00057
00058
00059 void plD_dispatch_init_psm( PLDispatchTable *pdt );
00060 void plD_dispatch_init_psc( PLDispatchTable *pdt );
00061
00062 static char *ps_getdate( void );
00063 static void ps_init( PLStream * );
00064 static void fill_polygon( PLStream *pls );
00065 static void proc_str( PLStream *, EscText * );
00066 static void esc_purge( unsigned char *, unsigned char * );
00067
00068 #define OUTBUF_LEN 128
00069 static char outbuf[OUTBUF_LEN];
00070 static int text = 1;
00071 static int color;
00072 static int hrshsym = 1;
00073
00074 static DrvOpt ps_options[] = { { "text", DRV_INT, &text, "Use Postscript text (text=0|1)" },
00075 { "color", DRV_INT, &color, "Use color (color=0|1)" },
00076 { "hrshsym", DRV_INT, &hrshsym, "Use Hershey symbol set (hrshsym=0|1)" },
00077 { NULL, DRV_INT, NULL, NULL } };
00078
00079 static unsigned char
00080 plunicode2type1( const PLUNICODE index,
00081 const Unicode_to_Type1_table lookup[],
00082 const int number_of_entries );
00083
00084 static char *
00085 get_font( PSDev* dev, PLUNICODE fci );
00086
00087
00088
00089
00090
00091
00092 static void ps_dispatch_init_helper( PLDispatchTable *pdt,
00093 char *menustr, char *devnam,
00094 int type, int seq, plD_init_fp init )
00095 {
00096 #ifndef ENABLE_DYNDRIVERS
00097 pdt->pl_MenuStr = menustr;
00098 pdt->pl_DevName = devnam;
00099 #endif
00100 pdt->pl_type = type;
00101 pdt->pl_seq = seq;
00102 pdt->pl_init = init;
00103 pdt->pl_line = (plD_line_fp) plD_line_ps;
00104 pdt->pl_polyline = (plD_polyline_fp) plD_polyline_ps;
00105 pdt->pl_eop = (plD_eop_fp) plD_eop_ps;
00106 pdt->pl_bop = (plD_bop_fp) plD_bop_ps;
00107 pdt->pl_tidy = (plD_tidy_fp) plD_tidy_ps;
00108 pdt->pl_state = (plD_state_fp) plD_state_ps;
00109 pdt->pl_esc = (plD_esc_fp) plD_esc_ps;
00110 }
00111
00112 void plD_dispatch_init_psm( PLDispatchTable *pdt )
00113 {
00114 ps_dispatch_init_helper( pdt,
00115 "PostScript File (monochrome)", "ps",
00116 plDevType_FileOriented, 29,
00117 (plD_init_fp) plD_init_psm );
00118 }
00119
00120 void plD_dispatch_init_psc( PLDispatchTable *pdt )
00121 {
00122 ps_dispatch_init_helper( pdt,
00123 "PostScript File (color)", "psc",
00124 plDevType_FileOriented, 30,
00125 (plD_init_fp) plD_init_psc );
00126 }
00127
00128
00129
00130
00131
00132
00133
00134 void
00135 plD_init_psm( PLStream *pls )
00136 {
00137 color = 0;
00138 pls->color = 0;
00139
00140 plParseDrvOpts( ps_options );
00141 if ( color )
00142 pls->color = 1;
00143 ps_init( pls );
00144 }
00145
00146 void
00147 plD_init_psc( PLStream *pls )
00148 {
00149 color = 1;
00150 pls->color = 1;
00151 plParseDrvOpts( ps_options );
00152
00153 if ( !color )
00154 pls->color = 0;
00155 ps_init( pls );
00156 }
00157
00158 static void
00159 ps_init( PLStream *pls )
00160 {
00161 PSDev *dev;
00162
00163 PLFLT pxlx, pxly;
00164
00165
00166 if ( pls->xlength <= 0 || pls->ylength <= 0 )
00167 {
00168 pls->xlength = 540;
00169 pls->ylength = 720;
00170 pls->xoffset = 32;
00171 pls->yoffset = 32;
00172 }
00173 if ( pls->xdpi <= 0 )
00174 pls->xdpi = 72.;
00175 if ( pls->ydpi <= 0 )
00176 pls->ydpi = 72.;
00177
00178 pxlx = YPSSIZE / LPAGE_X;
00179 pxly = XPSSIZE / LPAGE_Y;
00180
00181 if ( text )
00182 {
00183 pls->dev_text = 1;
00184 pls->dev_unicode = 1;
00185 if ( hrshsym )
00186 pls->dev_hrshsym = 1;
00187 }
00188
00189 pls->dev_fill0 = 1;
00190
00191
00192
00193 plFamInit( pls );
00194
00195
00196
00197 plOpenFile( pls );
00198
00199
00200
00201 if ( pls->dev != NULL )
00202 free( (void *) pls->dev );
00203
00204 pls->dev = calloc( 1, (size_t) sizeof ( PSDev ) );
00205 if ( pls->dev == NULL )
00206 plexit( "ps_init: Out of memory." );
00207
00208 dev = (PSDev *) pls->dev;
00209
00210 dev->xold = PL_UNDEFINED;
00211 dev->yold = PL_UNDEFINED;
00212
00213 plP_setpxl( pxlx, pxly );
00214
00215 dev->llx = XPSSIZE;
00216 dev->lly = YPSSIZE;
00217 dev->urx = 0;
00218 dev->ury = 0;
00219 dev->ptcnt = 0;
00220
00221
00222
00223 dev->xmin = 0;
00224 dev->ymin = 0;
00225 dev->xmax = PSY;
00226 dev->ymax = PSX;
00227 dev->xlen = dev->xmax - dev->xmin;
00228 dev->ylen = dev->ymax - dev->ymin;
00229
00230 plP_setphy( dev->xmin, dev->xmax, dev->ymin, dev->ymax );
00231
00232
00233
00234
00235
00236
00237
00238
00239 if ( pls->portrait )
00240 {
00241 plsdiori( (PLFLT) ( 4 - ORIENTATION ) );
00242 pls->freeaspect = 1;
00243 }
00244
00245
00246
00247 fprintf( OF, "%%!PS-Adobe-2.0 EPSF-2.0\n" );
00248 fprintf( OF, "%%%%BoundingBox: \n" );
00249 fprintf( OF, "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n" );
00250
00251 fprintf( OF, "%%%%Title: PLplot Graph\n" );
00252 fprintf( OF, "%%%%Creator: PLplot Version %s\n", VERSION );
00253 fprintf( OF, "%%%%CreationDate: %s\n", ps_getdate() );
00254 fprintf( OF, "%%%%Pages: (atend)\n" );
00255 fprintf( OF, "%%%%EndComments\n\n" );
00256
00257
00258
00259
00260 fprintf( OF, "/PSSave save def\n" );
00261
00262
00263
00264 fprintf( OF, "/PSDict 200 dict def\n" );
00265 fprintf( OF, "PSDict begin\n" );
00266
00267 fprintf( OF, "/@restore /restore load def\n" );
00268 fprintf( OF, "/restore\n" );
00269 fprintf( OF, " {vmstatus pop\n" );
00270 fprintf( OF, " dup @VMused lt {pop @VMused} if\n" );
00271 fprintf( OF, " exch pop exch @restore /@VMused exch def\n" );
00272 fprintf( OF, " } def\n" );
00273 fprintf( OF, "/@pri\n" );
00274 fprintf( OF, " {\n" );
00275 fprintf( OF, " ( ) print\n" );
00276 fprintf( OF, " ( ) cvs print\n" );
00277 fprintf( OF, " } def\n" );
00278
00279
00280
00281 fprintf( OF, "/@copies\n" );
00282 fprintf( OF, " {\n" );
00283 fprintf( OF, " /#copies exch def\n" );
00284 fprintf( OF, " } def\n" );
00285
00286
00287
00288 fprintf( OF, "/@start\n" );
00289 fprintf( OF, " {\n" );
00290 fprintf( OF, " vmstatus pop /@VMused exch def pop\n" );
00291 fprintf( OF, " } def\n" );
00292
00293
00294
00295 fprintf( OF, "/@end\n" );
00296 fprintf( OF, " {flush\n" );
00297 fprintf( OF, " end\n" );
00298 fprintf( OF, " PSSave restore\n" );
00299 fprintf( OF, " } def\n" );
00300
00301
00302
00303
00304 fprintf( OF, "/bop\n" );
00305 fprintf( OF, " {\n" );
00306 fprintf( OF, " /SaveImage save def\n" );
00307 fprintf( OF, " } def\n" );
00308
00309
00310
00311 fprintf( OF, "/eop\n" );
00312 fprintf( OF, " {\n" );
00313 fprintf( OF, " showpage\n" );
00314 fprintf( OF, " SaveImage restore\n" );
00315 fprintf( OF, " } def\n" );
00316
00317
00318
00319 fprintf( OF, "/@line\n" );
00320 fprintf( OF, " {0 setlinecap\n" );
00321 fprintf( OF, " 0 setlinejoin\n" );
00322 fprintf( OF, " 1 setmiterlimit\n" );
00323 fprintf( OF, " } def\n" );
00324
00325
00326
00327 fprintf( OF, "/@hsize {/hs exch def} def\n" );
00328 fprintf( OF, "/@vsize {/vs exch def} def\n" );
00329
00330
00331
00332 fprintf( OF, "/@hoffset {/ho exch def} def\n" );
00333 fprintf( OF, "/@voffset {/vo exch def} def\n" );
00334
00335
00336
00337 fprintf( OF, "/lw %d def\n", (int) (
00338 ( pls->width < MIN_WIDTH ) ? DEF_WIDTH :
00339 ( pls->width > MAX_WIDTH ) ? MAX_WIDTH : pls->width ) );
00340
00341
00342
00343 fprintf( OF, "/@SetPlot\n" );
00344 fprintf( OF, " {\n" );
00345 fprintf( OF, " ho vo translate\n" );
00346 fprintf( OF, " XScale YScale scale\n" );
00347 fprintf( OF, " lw setlinewidth\n" );
00348 fprintf( OF, " } def\n" );
00349
00350
00351
00352 fprintf( OF, "/XScale\n" );
00353 fprintf( OF, " {hs %d div} def\n", YPSSIZE );
00354 fprintf( OF, "/YScale\n" );
00355 fprintf( OF, " {vs %d div} def\n", XPSSIZE );
00356
00357
00358
00359 fprintf( OF, "/M {moveto} def\n" );
00360 fprintf( OF, "/D {lineto} def\n" );
00361 fprintf( OF, "/A {0.5 0 360 arc} def\n" );
00362 fprintf( OF, "/S {stroke} def\n" );
00363 fprintf( OF, "/Z {stroke newpath} def\n" );
00364
00365
00366
00367 if ( pls->dev_eofill )
00368 fprintf( OF, "/F {closepath gsave eofill grestore stroke} def " );
00369 else
00370 fprintf( OF, "/F {closepath gsave fill grestore stroke} def " );
00371 fprintf( OF, "/N {newpath} def" );
00372 fprintf( OF, "/C {setrgbcolor} def\n" );
00373 fprintf( OF, "/G {setgray} def\n" );
00374 fprintf( OF, "/W {setlinewidth} def\n" );
00375 fprintf( OF, "/SF {selectfont} def\n" );
00376 fprintf( OF, "/R {rotate} def\n" );
00377 fprintf( OF, "/SW {stringwidth 2 index mul exch 2 index mul exch rmoveto pop} bind def\n" );
00378 fprintf( OF, "/B {Z %d %d M %d %d D %d %d D %d %d D %d %d closepath} def\n",
00379 XMIN, YMIN, XMIN, YMAX, XMAX, YMAX, XMAX, YMIN, XMIN, YMIN );
00380 fprintf( OF, "/CL {newpath M D D D closepath clip} def\n" );
00381
00382
00383
00384 fprintf( OF, "end\n\n" );
00385
00386
00387
00388 fprintf( OF, "PSDict begin\n" );
00389 fprintf( OF, "@start\n" );
00390 fprintf( OF, "%d @copies\n", COPIES );
00391 fprintf( OF, "@line\n" );
00392 fprintf( OF, "%d @hsize\n", YSIZE );
00393 fprintf( OF, "%d @vsize\n", XSIZE );
00394 fprintf( OF, "%d @hoffset\n", YOFFSET );
00395 fprintf( OF, "%d @voffset\n", XOFFSET );
00396
00397 fprintf( OF, "@SetPlot\n\n" );
00398 }
00399
00400
00401
00402
00403
00404
00405
00406 void
00407 plD_line_ps( PLStream *pls, short x1a, short y1a, short x2a, short y2a )
00408 {
00409 PSDev *dev = (PSDev *) pls->dev;
00410 PLINT x1 = x1a, y1 = y1a, x2 = x2a, y2 = y2a;
00411
00412
00413
00414 plRotPhy( ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax, &x1, &y1 );
00415 plRotPhy( ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax, &x2, &y2 );
00416
00417 if ( x1 == dev->xold && y1 == dev->yold && dev->ptcnt < 40 )
00418 {
00419 if ( pls->linepos + 12 > LINELENGTH )
00420 {
00421 putc( '\n', OF );
00422 pls->linepos = 0;
00423 }
00424 else
00425 putc( ' ', OF );
00426
00427 snprintf( outbuf, OUTBUF_LEN, "%d %d D", x2, y2 );
00428 dev->ptcnt++;
00429 pls->linepos += 12;
00430 }
00431 else
00432 {
00433 fprintf( OF, " Z\n" );
00434 pls->linepos = 0;
00435
00436 if ( x1 == x2 && y1 == y2 )
00437 snprintf( outbuf, OUTBUF_LEN, "%d %d A", x1, y1 );
00438 else
00439 snprintf( outbuf, OUTBUF_LEN, "%d %d M %d %d D", x1, y1, x2, y2 );
00440 dev->llx = MIN( dev->llx, x1 );
00441 dev->lly = MIN( dev->lly, y1 );
00442 dev->urx = MAX( dev->urx, x1 );
00443 dev->ury = MAX( dev->ury, y1 );
00444 dev->ptcnt = 1;
00445 pls->linepos += 24;
00446 }
00447 dev->llx = MIN( dev->llx, x2 );
00448 dev->lly = MIN( dev->lly, y2 );
00449 dev->urx = MAX( dev->urx, x2 );
00450 dev->ury = MAX( dev->ury, y2 );
00451
00452 fprintf( OF, "%s", outbuf );
00453 pls->bytecnt += 1 + strlen( outbuf );
00454 dev->xold = x2;
00455 dev->yold = y2;
00456 }
00457
00458
00459
00460
00461
00462
00463
00464 void
00465 plD_polyline_ps( PLStream *pls, short *xa, short *ya, PLINT npts )
00466 {
00467 PLINT i;
00468
00469 for ( i = 0; i < npts - 1; i++ )
00470 plD_line_ps( pls, xa[i], ya[i], xa[i + 1], ya[i + 1] );
00471 }
00472
00473
00474
00475
00476
00477
00478
00479 void
00480 plD_eop_ps( PLStream *pls )
00481 {
00482 fprintf( OF, " S\neop\n" );
00483 }
00484
00485
00486
00487
00488
00489
00490
00491
00492 void
00493 plD_bop_ps( PLStream *pls )
00494 {
00495 PSDev *dev = (PSDev *) pls->dev;
00496
00497 dev->xold = PL_UNDEFINED;
00498 dev->yold = PL_UNDEFINED;
00499
00500 if ( !pls->termin )
00501 plGetFam( pls );
00502
00503 pls->page++;
00504
00505 if ( pls->family )
00506 fprintf( OF, "%%%%Page: %d %d\n", (int) pls->page, 1 );
00507 else
00508 fprintf( OF, "%%%%Page: %d %d\n", (int) pls->page, (int) pls->page );
00509
00510 fprintf( OF, "bop\n" );
00511 if ( pls->color )
00512 {
00513 PLFLT r, g, b;
00514 if ( pls->cmap0[0].r != 0xFF ||
00515 pls->cmap0[0].g != 0xFF ||
00516 pls->cmap0[0].b != 0xFF )
00517 {
00518 r = ( (PLFLT) pls->cmap0[0].r ) / 255.;
00519 g = ( (PLFLT) pls->cmap0[0].g ) / 255.;
00520 b = ( (PLFLT) pls->cmap0[0].b ) / 255.;
00521
00522 fprintf( OF, "B %.4f %.4f %.4f C F\n", r, g, b );
00523 }
00524 }
00525 pls->linepos = 0;
00526
00527
00528
00529
00530 plD_state_ps( pls, PLSTATE_COLOR0 );
00531 plD_state_ps( pls, PLSTATE_WIDTH );
00532 }
00533
00534
00535
00536
00537
00538
00539
00540 void
00541 plD_tidy_ps( PLStream *pls )
00542 {
00543 PSDev *dev = (PSDev *) pls->dev;
00544
00545 fprintf( OF, "\n%%%%Trailer\n" );
00546
00547 dev->llx /= ENLARGE;
00548 dev->lly /= ENLARGE;
00549 dev->urx /= ENLARGE;
00550 dev->ury /= ENLARGE;
00551 dev->llx += XOFFSET;
00552 dev->lly += YOFFSET;
00553 dev->urx += XOFFSET;
00554 dev->ury += YOFFSET;
00555
00556
00557
00558
00559 dev->urx += 1;
00560 dev->ury += 1;
00561
00562 if ( pls->family )
00563 fprintf( OF, "%%%%Pages: %d\n", (int) 1 );
00564 else
00565 fprintf( OF, "%%%%Pages: %d\n", (int) pls->page );
00566
00567 fprintf( OF, "@end\n" );
00568 fprintf( OF, "%%%%EOF\n" );
00569
00570
00571
00572
00573 rewind( OF );
00574 fprintf( OF, "%%!PS-Adobe-2.0 EPSF-2.0\n" );
00575 fprintf( OF, "%%%%BoundingBox: %d %d %d %d\n",
00576 dev->llx, dev->lly, dev->urx, dev->ury );
00577 plCloseFile( pls );
00578 }
00579
00580
00581
00582
00583
00584
00585
00586 void
00587 plD_state_ps( PLStream *pls, PLINT op )
00588 {
00589 PSDev *dev = (PSDev *) pls->dev;
00590
00591 switch ( op )
00592 {
00593 case PLSTATE_WIDTH: {
00594 int width =
00595 ( pls->width < MIN_WIDTH ) ? DEF_WIDTH :
00596 ( pls->width > MAX_WIDTH ) ? MAX_WIDTH : pls->width;
00597
00598 fprintf( OF, " S\n%d W", width );
00599
00600 dev->xold = PL_UNDEFINED;
00601 dev->yold = PL_UNDEFINED;
00602 break;
00603 }
00604 case PLSTATE_COLOR0:
00605 if ( !pls->color )
00606 {
00607 fprintf( OF, " S\n%.4f G", ( pls->icol0 ? 0.0 : 1.0 ) );
00608 break;
00609 }
00610
00611 case PLSTATE_COLOR1:
00612 if ( pls->color )
00613 {
00614 PLFLT r = ( (PLFLT) pls->curcolor.r ) / 255.0;
00615 PLFLT g = ( (PLFLT) pls->curcolor.g ) / 255.0;
00616 PLFLT b = ( (PLFLT) pls->curcolor.b ) / 255.0;
00617
00618 fprintf( OF, " S\n%.4f %.4f %.4f C", r, g, b );
00619 }
00620 else
00621 {
00622 PLFLT r = ( (PLFLT) pls->curcolor.r ) / 255.0;
00623 fprintf( OF, " S\n%.4f G", 1.0 - r );
00624 }
00625 break;
00626 }
00627
00628
00629
00630 if ( dev->xold != PL_UNDEFINED && dev->yold != PL_UNDEFINED )
00631 {
00632 fprintf( OF, " %d %d M \n", (int) dev->xold, (int) dev->yold );
00633 }
00634 }
00635
00636
00637
00638
00639
00640
00641
00642 void
00643 plD_esc_ps( PLStream *pls, PLINT op, void *ptr )
00644 {
00645 switch ( op )
00646 {
00647 case PLESC_FILL:
00648 fill_polygon( pls );
00649 break;
00650 case PLESC_HAS_TEXT:
00651 proc_str( pls, (EscText *) ptr );
00652 break;
00653 }
00654 }
00655
00656
00657
00658
00659
00660
00661
00662
00663 static void
00664 fill_polygon( PLStream *pls )
00665 {
00666 PSDev *dev = (PSDev *) pls->dev;
00667 PLINT n, ix = 0, iy = 0;
00668 PLINT x, y;
00669
00670 fprintf( OF, " Z\n" );
00671
00672 for ( n = 0; n < pls->dev_npts; n++ )
00673 {
00674 x = pls->dev_x[ix++];
00675 y = pls->dev_y[iy++];
00676
00677
00678
00679 plRotPhy( ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax, &x, &y );
00680
00681
00682
00683 if ( n == 0 )
00684 {
00685 snprintf( outbuf, OUTBUF_LEN, "N %d %d M", x, y );
00686 dev->llx = MIN( dev->llx, x );
00687 dev->lly = MIN( dev->lly, y );
00688 dev->urx = MAX( dev->urx, x );
00689 dev->ury = MAX( dev->ury, y );
00690 fprintf( OF, "%s", outbuf );
00691 pls->bytecnt += strlen( outbuf );
00692 continue;
00693 }
00694
00695 if ( pls->linepos + 21 > LINELENGTH )
00696 {
00697 putc( '\n', OF );
00698 pls->linepos = 0;
00699 }
00700 else
00701 putc( ' ', OF );
00702
00703 pls->bytecnt++;
00704
00705 snprintf( outbuf, OUTBUF_LEN, "%d %d D", x, y );
00706 dev->llx = MIN( dev->llx, x );
00707 dev->lly = MIN( dev->lly, y );
00708 dev->urx = MAX( dev->urx, x );
00709 dev->ury = MAX( dev->ury, y );
00710
00711 fprintf( OF, "%s", outbuf );
00712 pls->bytecnt += strlen( outbuf );
00713 pls->linepos += 21;
00714 }
00715 dev->xold = PL_UNDEFINED;
00716 dev->yold = PL_UNDEFINED;
00717 fprintf( OF, " F " );
00718 }
00719
00720
00721
00722
00723
00724
00725
00726 static char *
00727 ps_getdate( void )
00728 {
00729 int len;
00730 time_t t;
00731 char *p;
00732
00733 t = time( (time_t *) 0 );
00734 p = ctime( &t );
00735 len = strlen( p );
00736 *( p + len - 1 ) = '\0';
00737 return p;
00738 }
00739
00740
00741
00742
00743
00744
00745
00746
00747 # define RISE_FACTOR 0.6
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757 void
00758 proc_str( PLStream *pls, EscText *args )
00759 {
00760 PLFLT *t = args->xform, tt[4];
00761 PLFLT theta, shear, stride;
00762 PLFLT ft_ht, offset;
00763 PLFLT cs, sn, l1, l2;
00764 PSDev *dev = (PSDev *) pls->dev;
00765 char *font, esc;
00766
00767
00768 #define PROC_STR_STRING_LENGTH 1000
00769 unsigned char *strp, str[PROC_STR_STRING_LENGTH], *cur_strp,
00770 cur_str[PROC_STR_STRING_LENGTH];
00771 float font_factor = 1.4f;
00772 PLINT clxmin, clxmax, clymin, clymax;
00773 PLINT clipx[4], clipy[4];
00774
00775 PLFLT scale = 1., up = 0.;
00776
00777 int i = 0;
00778
00779
00780 if ( args->unicode_array_len > 0 )
00781 {
00782 int j, s, f;
00783 char *fonts[PROC_STR_STRING_LENGTH];
00784 const PLUNICODE *cur_text;
00785 PLUNICODE fci, fci_save;
00786 PLFLT old_sscale, sscale, old_soffset, soffset, dup;
00787 PLINT level = 0;
00788
00789
00790
00791
00792
00793
00794 plgesc( &esc );
00795 plgfci( &fci );
00796 fci_save = fci;
00797 font = get_font( dev, fci );
00798 cur_text = args->unicode_array;
00799 for ( f = s = j = 0; j < args->unicode_array_len; j++ )
00800 {
00801 if ( cur_text[j] & PL_FCI_MARK )
00802 {
00803
00804
00805
00806
00807 if ( ( f < PROC_STR_STRING_LENGTH ) && ( s + 3 < PROC_STR_STRING_LENGTH ) )
00808 {
00809 fci_save = cur_text[j];
00810 fonts[f++] = get_font( dev, fci_save );
00811 cur_str[s++] = esc;
00812 cur_str[s++] = 'f';
00813 cur_str[s++] = 'f';
00814 }
00815 }
00816 else if ( s + 4 < PROC_STR_STRING_LENGTH )
00817 {
00818 #undef PL_TEST_TYPE1
00819 #ifdef PL_TEST_TYPE1
00820
00821
00822
00823 PLINT ifamily, istyle, iweight;
00824 plgfont( &ifamily, &istyle, &iweight );
00825 if ( 0 <= cur_text[j] && cur_text[j] < 256 )
00826 cur_str[s++] = cur_text[j];
00827 else
00828 cur_str[s++] = 32;
00829
00830 if ( ifamily == PL_FCI_SYMBOL )
00831 font = get_font( dev, 0 );
00832 else
00833 font = get_font( dev, fci );
00834 #else
00835 cur_str[s] = plunicode2type1( cur_text[j], dev->lookup, dev->nlookup );
00836 if ( cur_text[j] != ' ' && cur_str[s] == ' ' )
00837 {
00838
00839 if ( !dev->if_symbol_font )
00840 {
00841
00842
00843
00844 fonts[f++] = get_font( dev, 0 );
00845 cur_str[s++] = esc;
00846 cur_str[s++] = 'f';
00847 cur_str[s++] = 'f';
00848 cur_str[s++] = plunicode2type1( cur_text[j], dev->lookup, dev->nlookup );
00849 }
00850 else
00851 {
00852
00853
00854
00855 fonts[f++] = get_font( dev, fci_save );
00856 cur_str[s++] = esc;
00857 cur_str[s++] = 'f';
00858 cur_str[s++] = 'f';
00859 cur_str[s++] = plunicode2type1( cur_text[j], dev->lookup, dev->nlookup );
00860 }
00861 }
00862 else
00863 {
00864
00865 s++;
00866 }
00867 #endif
00868 pldebug( "proc_str", "unicode = 0x%x, type 1 code = %d\n",
00869 cur_text[j], cur_str[s - 1] );
00870 }
00871 }
00872 cur_str[s] = '\0';
00873
00874
00875
00876 dev->xold = PL_UNDEFINED;
00877 dev->yold = PL_UNDEFINED;
00878
00879
00880 ft_ht = pls->chrht * 72.0 / 25.4;
00881
00882
00883
00884 plRotationShear( t, &theta, &shear, &stride );
00885 cs = cos( theta );
00886 sn = sin( theta );
00887 tt[0] = t[0] * cs + t[2] * sn;
00888 tt[1] = t[1] * cs + t[3] * sn;
00889 tt[2] = -t[0] * sn + t[2] * cs;
00890 tt[3] = -t[1] * sn + t[3] * cs;
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904 if ( args->base == 2 )
00905 offset = ENLARGE * ft_ht / 2.;
00906 else if ( args->base == 1 )
00907 offset = 0.;
00908 else
00909 offset = -ENLARGE * ft_ht / 2.;
00910
00911
00912 theta -= PI / 2. * pls->diorot;
00913 args->y += (PLINT) ( offset * cos( theta ) );
00914 args->x -= (PLINT) ( offset * sin( theta ) );
00915
00916
00917 plRotPhy( ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax,
00918 &( args->x ), &( args->y ) );
00919
00920
00921 theta += PI / 2.;
00922
00923
00924
00925 clipx[0] = pls->clpxmi;
00926 clipx[2] = pls->clpxma;
00927 clipy[0] = pls->clpymi;
00928 clipy[2] = pls->clpyma;
00929 clipx[1] = clipx[2];
00930 clipy[1] = clipy[0];
00931 clipx[3] = clipx[0];
00932 clipy[3] = clipy[2];
00933 difilt( clipx, clipy, 4, &clxmin, &clxmax, &clymin, &clymax );
00934 plRotPhy( ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax,
00935 &clipx[0], &clipy[0] );
00936 plRotPhy( ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax,
00937 &clipx[1], &clipy[1] );
00938 plRotPhy( ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax,
00939 &clipx[2], &clipy[2] );
00940 plRotPhy( ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax,
00941 &clipx[3], &clipy[3] );
00942 fprintf( OF, " gsave %d %d %d %d %d %d %d %d CL\n", clipx[0], clipy[0], clipx[1], clipy[1], clipx[2], clipy[2], clipx[3], clipy[3] );
00943
00944
00945 fprintf( OF, " %d %d M\n", args->x, args->y );
00946
00947
00948 fprintf( OF, "gsave %.3f R\n", TRMFLT( theta * 180. / PI ) );
00949
00950
00951
00952
00953
00954
00955 esc_purge( str, cur_str );
00956
00957 fprintf( OF, "/%s %.3f SF\n", font, TRMFLT( font_factor * ENLARGE * ft_ht ) );
00958
00959
00960
00961
00962 fprintf( OF, "%.3f (", TRMFLT( -args->just ) );
00963 while ( str[i] != '\0' )
00964 {
00965 if ( str[i] == '(' || str[i] == ')' || str[i] == '\\' )
00966 fprintf( OF, "\\%c", str[i] );
00967 else
00968 fprintf( OF, "%c", str[i] );
00969 i++;
00970 }
00971 fprintf( OF, ") SW\n" );
00972
00973
00974
00975
00976 cur_strp = cur_str;
00977 f = 0;
00978 do
00979 {
00980 strp = str;
00981
00982 if ( *cur_strp == esc )
00983 {
00984 cur_strp++;
00985
00986 if ( *cur_strp == esc )
00987 {
00988 *strp++ = *cur_strp++;
00989 }
00990 else if ( *cur_strp == 'f' )
00991 {
00992 cur_strp++;
00993 if ( *cur_strp++ != 'f' )
00994 {
00995
00996
00997 plabort( "proc_str, internal PLplot logic error;"
00998 "wrong escf escape sequence" );
00999 return;
01000 }
01001 font = fonts[f++];
01002 pldebug( "proc_str", "string-specified fci = 0x%x, font name = %s\n", fci, font );
01003 continue;
01004 }
01005 else
01006 switch ( *cur_strp++ )
01007 {
01008 case 'd':
01009 case 'D':
01010 plP_script_scale( FALSE, &level,
01011 &old_sscale, &sscale, &old_soffset, &soffset );
01012 scale = sscale;
01013
01014
01015
01016
01017 dup = -0.5 * ( 1.0 - sscale );
01018 up = -font_factor * ENLARGE * ft_ht * ( RISE_FACTOR * soffset + dup );
01019 break;
01020
01021 case 'u':
01022 case 'U':
01023 plP_script_scale( TRUE, &level,
01024 &old_sscale, &sscale, &old_soffset, &soffset );
01025 scale = sscale;
01026
01027
01028
01029
01030 dup = 0.5 * ( 1.0 - sscale );
01031 up = font_factor * ENLARGE * ft_ht * ( RISE_FACTOR * soffset + dup );
01032 break;
01033
01034
01035
01036 case '+':
01037 case '-':
01038 case 'b':
01039 case 'B':
01040 plwarn( "'+', '-', and 'b/B' text escape sequences not processed." );
01041 break;
01042 }
01043 }
01044
01045
01046
01047
01048 while ( *cur_strp && *cur_strp != esc )
01049 {
01050 if ( *cur_strp == '(' || *cur_strp == ')' || *cur_strp == '\\' )
01051 *strp++ = '\\';
01052 *strp++ = *cur_strp++;
01053 }
01054 *strp = '\0';
01055
01056 if ( fabs( up ) < 0.001 )
01057 up = 0.;
01058
01059
01060 fprintf( OF, "/%s [%.3f %.3f %.3f %.3f 0 0] SF\n",
01061 font,
01062 TRMFLT( tt[0] * font_factor * ENLARGE * ft_ht * scale ),
01063 TRMFLT( tt[2] * font_factor * ENLARGE * ft_ht * scale ),
01064 TRMFLT( tt[1] * font_factor * ENLARGE * ft_ht * scale ),
01065 TRMFLT( tt[3] * font_factor * ENLARGE * ft_ht * scale ) );
01066
01067
01068
01069 if ( up != 0. )
01070 fprintf( OF, "gsave %.3f %.3f rmoveto\n", TRMFLT( up * tt[1] ), TRMFLT( up * tt[3] ) );
01071
01072
01073 fprintf( OF, "(%s) show\n", str );
01074
01075
01076 if ( up != 0. )
01077 fprintf( OF, "grestore (%s) stringwidth rmoveto\n", str );
01078 } while ( *cur_strp );
01079
01080 fprintf( OF, "grestore\n" );
01081 fprintf( OF, "grestore\n" );
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092 cs = cos( theta );
01093 sn = sin( theta );
01094 l1 = -i * args->just;
01095 l2 = i * ( 1. - args->just );
01096
01097
01098 l1 *= 0.6;
01099 l2 *= 0.6;
01100
01101 dev->llx = (int) ( MIN( dev->llx, args->x + ( MIN( l1 * cs, l2 * cs ) - 1.5 ) * font_factor * ft_ht * ENLARGE ) );
01102 dev->lly = (int) ( MIN( dev->lly, args->y + ( MIN( l1 * sn, l2 * sn ) - 1.5 ) * font_factor * ft_ht * ENLARGE ) );
01103 dev->urx = (int) ( MAX( dev->urx, args->x + ( MAX( l1 * cs, l2 * cs ) + 1.5 ) * font_factor * ft_ht * ENLARGE ) );
01104 dev->ury = (int) ( MAX( dev->ury, args->y + ( MAX( l1 * sn, l2 * sn ) + 1.5 ) * font_factor * ft_ht * ENLARGE ) );
01105 }
01106 }
01107
01108 static void
01109 esc_purge( unsigned char *dstr, unsigned char *sstr )
01110 {
01111 char esc;
01112
01113 plgesc( &esc );
01114
01115 while ( *sstr )
01116 {
01117 if ( *sstr != esc )
01118 {
01119 *dstr++ = *sstr++;
01120 continue;
01121 }
01122
01123 sstr++;
01124 if ( *sstr == esc )
01125 {
01126 *dstr++ = *sstr++;
01127 continue;
01128 }
01129
01130 else
01131 {
01132 switch ( *sstr++ )
01133 {
01134 case 'f':
01135 sstr++;
01136 break;
01137
01138 default:
01139 break;
01140 }
01141 }
01142 }
01143 *dstr = '\0';
01144 }
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157 static unsigned char
01158 plunicode2type1( const PLUNICODE index,
01159 const Unicode_to_Type1_table lookup[],
01160 const int nlookup )
01161 {
01162 int jlo = -1, jmid, jhi = nlookup;
01163 while ( jhi - jlo > 1 )
01164 {
01165
01166
01167
01168
01169 jmid = ( jlo + jhi ) / 2;
01170 if ( index > lookup[jmid].Unicode )
01171 jlo = jmid;
01172 else if ( index < lookup[jmid].Unicode )
01173 jhi = jmid;
01174 else
01175
01176
01177
01178 return ( lookup[jmid].Type1 );
01179 }
01180
01181
01182
01183
01184
01185 return ( ' ' );
01186 }
01187
01188
01189
01190
01191
01192
01193 static char *
01194 get_font( PSDev* dev, PLUNICODE fci )
01195 {
01196 char *font;
01197
01198
01199
01200 if ( fci == 0 )
01201 {
01202 font = "Symbol";
01203 dev->nlookup = number_of_entries_in_unicode_to_symbol_table;
01204 dev->lookup = unicode_to_symbol_lookup_table;
01205 dev->if_symbol_font = 1;
01206 }
01207 else
01208 {
01209
01210 font = plP_FCI2FontName( fci, Type1Lookup, N_Type1Lookup );
01211 dev->nlookup = number_of_entries_in_unicode_to_standard_table;
01212 dev->lookup = unicode_to_standard_lookup_table;
01213 dev->if_symbol_font = 0;
01214 }
01215 pldebug( "set_font", "fci = 0x%x, font name = %s\n", fci, font );
01216 return ( font );
01217 }
01218
01219 #else
01220 int
01221 pldummy_ps()
01222 {
01223 return 0;
01224 }
01225
01226 #endif // PLD_ps