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