PLplot  5.10.0
psttf.cc
Go to the documentation of this file.
00001 //        PLplot PostScript device driver using LASi to provide fonts
00002 //        based on original ps.c PostScript driver
00003 //
00004 //  Copyright (C) 1992, 2001  Geoffrey Furnish
00005 //  Copyright (C) 1992, 1993, 1994, 1995, 2001  Maurice LeBrun
00006 //  Copyright (C) 2000-2011 Alan W. Irwin
00007 //  Copyright (C) 2001, 2002  Joao Cardoso
00008 //  Copyright (C) 2001, 2003, 2004  Rafael Laboissiere
00009 //  Copyright (C) 2004, 2005  Thomas J. Duck
00010 //  Copyright (C) 2005, 2006  Andrew Ross
00011 //
00012 //  This file is part of PLplot.
00013 //
00014 //  PLplot is free software; you can redistribute it and/or modify
00015 //  it under the terms of the GNU Library General Public License as published
00016 //  by the Free Software Foundation; either version 2 of the License, or
00017 //  (at your option) any later version.
00018 //
00019 //  PLplot is distributed in the hope that it will be useful,
00020 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00021 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00022 //  GNU Library General Public License for more details.
00023 //
00024 //  You should have received a copy of the GNU Library General Public License
00025 //  along with PLplot; if not, write to the Free Software
00026 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00027 //
00028 //
00029 
00030 #include "plDevs.h"
00031 
00032 #if defined ( PLD_psttf )
00033 
00034 //#define NEED_PLDEBUG
00035 #include "plplotP.h"
00036 #include "drivers.h"
00037 #include "ps.h"
00038 
00039 #include <string.h>
00040 #include <time.h>
00041 #include "plfreetype.h"
00042 #include <iostream>
00043 #include <fstream>
00044 #include <LASi.h>
00045 
00046 // Define macro to truncate small values to zero - prevents
00047 //  * printf printing -0.000
00048 #define TRMFLT( a )    ( ( fabs( a ) < 5.0e-4 ) ? 0.0 : ( a ) )
00049 
00050 using namespace LASi;
00051 using namespace std;
00052 
00053 // Device info
00054 
00055 PLDLLIMPEXP_DRIVER const char* plD_DEVICE_INFO_psttf =
00056     "psttf:PostScript File (monochrome):0:psttf:55:psttfm\n"
00057     "psttfc:PostScript File (color):0:psttf:56:psttfc\n";
00058 
00059 
00060 // Prototypes for functions in this file.
00061 
00062 void plD_dispatch_init_psttfm( PLDispatchTable *pdt );
00063 void plD_dispatch_init_psttfc( PLDispatchTable *pdt );
00064 
00065 static char  *ps_getdate( void );
00066 static void  ps_init( PLStream * );
00067 static void  fill_polygon( PLStream *pls );
00068 static void  proc_str( PLStream *, EscText * );
00069 //static void  esc_purge( char *, char * );
00070 
00071 #define OUTBUF_LEN    128
00072 static char outbuf[OUTBUF_LEN];
00073 static int  text = 1;
00074 static int  color;
00075 static int  hrshsym = 0;
00076 
00077 // Font style and weight lookup tables
00078 
00079 #define N_Pango_Lookup    5
00080 
00081 const char * DefaultFamilyLookup[N_Pango_Lookup] = {
00082     "sans",
00083     "serif",
00084     "monospace",
00085     "sans,serif",
00086     "sans,serif"
00087 };
00088 
00089 const char * EnvFamilyLookup[N_Pango_Lookup] = {
00090     "PLPLOT_FREETYPE_SANS_FAMILY",
00091     "PLPLOT_FREETYPE_SERIF_FAMILY",
00092     "PLPLOT_FREETYPE_MONO_FAMILY",
00093     "PLPLOT_FREETYPE_SCRIPT_FAMILY",
00094     "PLPLOT_FREETYPE_SYMBOL_FAMILY"
00095 };
00096 
00097 #define FAMILY_LOOKUP_LEN    1024
00098 char             FamilyLookup[N_Pango_Lookup][FAMILY_LOOKUP_LEN];
00099 
00100 const FontWeight WeightLookup[2] = {
00101     NORMAL_WEIGHT,
00102     BOLD
00103 };
00104 
00105 const FontStyle  StyleLookup[3] = {
00106     NORMAL_STYLE,
00107     ITALIC,
00108     OBLIQUE
00109 };
00110 
00111 static DrvOpt    ps_options[] = { { "text",    DRV_INT, &text,    "Use Postscript text (text=0|1)"       },
00112                                   { "color",   DRV_INT, &color,   "Use color (color=0|1)"                },
00113                                   { "hrshsym", DRV_INT, &hrshsym, "Use Hershey symbol set (hrshsym=0|1)" },
00114                                   { NULL,      DRV_INT, NULL,     NULL                                   } };
00115 
00116 // text > 0 uses some postscript tricks, namely a transformation matrix
00117 //   that scales, rotates (with slanting) and offsets text strings.
00118 //   It has yet some bugs for 3d plots.
00119 
00120 
00121 static void psttf_dispatch_init_helper( PLDispatchTable *pdt,
00122                                         const char *menustr, const char *devnam,
00123                                         int type, int seq, plD_init_fp init )
00124 {
00125 #ifndef ENABLE_DYNDRIVERS
00126     pdt->pl_MenuStr = (char *) menustr;
00127     pdt->pl_DevName = (char *) devnam;
00128 #else
00129     (void) menustr;   // Cast to void to silence compiler warnings about unused parameters
00130     (void) devnam;
00131 #endif
00132     pdt->pl_type     = type;
00133     pdt->pl_seq      = seq;
00134     pdt->pl_init     = init;
00135     pdt->pl_line     = (plD_line_fp) plD_line_psttf;
00136     pdt->pl_polyline = (plD_polyline_fp) plD_polyline_psttf;
00137     pdt->pl_eop      = (plD_eop_fp) plD_eop_psttf;
00138     pdt->pl_bop      = (plD_bop_fp) plD_bop_psttf;
00139     pdt->pl_tidy     = (plD_tidy_fp) plD_tidy_psttf;
00140     pdt->pl_state    = (plD_state_fp) plD_state_psttf;
00141     pdt->pl_esc      = (plD_esc_fp) plD_esc_psttf;
00142 }
00143 
00144 void plD_dispatch_init_psttfm( PLDispatchTable *pdt )
00145 {
00146     psttf_dispatch_init_helper( pdt,
00147         "PostScript File (monochrome)", "psttf",
00148         plDevType_FileOriented, 55,
00149         (plD_init_fp) plD_init_psttfm );
00150 }
00151 
00152 void plD_dispatch_init_psttfc( PLDispatchTable *pdt )
00153 {
00154     psttf_dispatch_init_helper( pdt,
00155         "PostScript File (color)", "psttfc",
00156         plDevType_FileOriented, 56,
00157         (plD_init_fp) plD_init_psttfc );
00158 }
00159 
00160 //--------------------------------------------------------------------------
00161 // plD_init_psttf()
00162 //
00163 // Initialize device.
00164 //--------------------------------------------------------------------------
00165 
00166 void
00167 plD_init_psttfm( PLStream *pls )
00168 {
00169     color      = 0;
00170     pls->color = 0;             // Not a color device
00171 
00172     plParseDrvOpts( ps_options );
00173     if ( color )
00174         pls->color = 1;         // But user wants color
00175     ps_init( pls );
00176 }
00177 
00178 void
00179 plD_init_psttfc( PLStream *pls )
00180 {
00181     color      = 1;
00182     pls->color = 1;             // Is a color device
00183     plParseDrvOpts( ps_options );
00184 
00185     if ( !color )
00186         pls->color = 0;         // But user does not want color
00187     ps_init( pls );
00188 }
00189 
00190 #define MAX_NUM_TRIES    10
00191 static void
00192 ps_init( PLStream *pls )
00193 {
00194     int   i;
00195     char  *a;
00196     PSDev *dev;
00197     PostscriptDocument *doc;
00198     PLFLT pxlx, pxly;
00199 
00200     // Set default values - 7.5 x 10 [inches] (72 points = 1 inch)
00201     if ( pls->xlength <= 0 || pls->ylength <= 0 )
00202     {
00203         pls->xlength = 540;
00204         pls->ylength = 720;
00205     }
00206     if ( pls->xdpi <= 0 )
00207         pls->xdpi = 72.;
00208     if ( pls->ydpi <= 0 )
00209         pls->ydpi = 72.;
00210 
00211 
00212     pxlx = YPSSIZE / LPAGE_X;
00213     pxly = XPSSIZE / LPAGE_Y;
00214 
00215     if ( text )
00216     {
00217         pls->dev_text    = 1;     // want to draw text
00218         pls->dev_unicode = 1;     // want unicode
00219         if ( hrshsym )
00220             pls->dev_hrshsym = 1; // want Hershey symbols
00221     }
00222 
00223     pls->dev_fill0 = 1;         // Can do solid fills
00224 
00225 // Initialize family file info
00226 
00227     plFamInit( pls );
00228 
00229 // Prompt for a file name if not already set
00230 
00231     plOpenFile( pls );
00232 
00233 // Create postscript document object
00234     if ( pls->psdoc != NULL )
00235         delete (PostscriptDocument *) pls->psdoc;
00236 
00237     pls->psdoc = new PostscriptDocument();
00238     doc        = (PostscriptDocument *) ( pls->psdoc );
00239     doc->osBody() << fixed;
00240     doc->osBody().precision( 3 );
00241 
00242 // Allocate and initialize device-specific data
00243 
00244     if ( pls->dev != NULL )
00245         free( (void *) pls->dev );
00246 
00247     pls->dev = calloc( 1, (size_t) sizeof ( PSDev ) );
00248     if ( pls->dev == NULL )
00249         plexit( "ps_init: Out of memory." );
00250 
00251     dev = (PSDev *) pls->dev;
00252 
00253     dev->xold = PL_UNDEFINED;
00254     dev->yold = PL_UNDEFINED;
00255 
00256     plP_setpxl( pxlx, pxly );
00257 
00258     dev->llx   = XPSSIZE;
00259     dev->lly   = YPSSIZE;
00260     dev->urx   = 0;
00261     dev->ury   = 0;
00262     dev->ptcnt = 0;
00263 
00264 // Rotate by 90 degrees since portrait mode addressing is used
00265 
00266     dev->xmin = 0;
00267     dev->ymin = 0;
00268     dev->xmax = PSY;
00269     dev->ymax = PSX;
00270     dev->xlen = dev->xmax - dev->xmin;
00271     dev->ylen = dev->ymax - dev->ymin;
00272 
00273     plP_setphy( dev->xmin, dev->xmax, dev->ymin, dev->ymax );
00274 
00275 // If portrait mode is specified, then set up an additional rotation
00276 // transformation with aspect ratio allowed to adjust via freeaspect.
00277 // Default orientation is landscape (ORIENTATION == 3 or 90 deg rotation
00278 // counter-clockwise from portrait).  (Legacy PLplot used seascape
00279 // which was equivalent to ORIENTATION == 1 or 90 deg clockwise rotation
00280 // from portrait.)
00281 
00282     if ( pls->portrait )
00283     {
00284         plsdiori( (PLFLT) ( 4 - ORIENTATION ) );
00285         pls->freeaspect = 1;
00286     }
00287 
00288     // File table for font families using either environment variables
00289     // or defaults.
00290     for ( i = 0; i < N_Pango_Lookup; i++ )
00291     {
00292         if ( ( a = getenv( EnvFamilyLookup[i] ) ) != NULL )
00293         {
00294             strncpy( FamilyLookup[i], a, FAMILY_LOOKUP_LEN - 1 );
00295             FamilyLookup[i][FAMILY_LOOKUP_LEN - 1] = '\0';
00296         }
00297         else
00298         {
00299             strncpy( FamilyLookup[i], DefaultFamilyLookup[i], FAMILY_LOOKUP_LEN );
00300             FamilyLookup[i][FAMILY_LOOKUP_LEN - 1] = '\0';
00301         }
00302     }
00303 }
00304 
00305 
00306 //--------------------------------------------------------------------------
00307 // writeHeader()
00308 //
00309 // Write plplot postscript commands into the header
00310 //--------------------------------------------------------------------------
00311 
00312 void
00313 writeHeader( PLStream *pls )
00314 {
00315     PostscriptDocument *doc = (PostscriptDocument *) ( pls->psdoc );
00316 
00317     doc->osHeader() << "%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
00318 
00319     doc->osHeader() << "%%Title: PLplot Graph\n";
00320     doc->osHeader() << "%%Creator: PLplot Version " << PLPLOT_VERSION << "\n";
00321     doc->osHeader() << "%%CreationDate: " << ps_getdate() << "\n";
00322     doc->osHeader() << "%%Pages: (atend)\n";
00323     doc->osHeader() << "%%EndComments\n\n";
00324 
00325 // Definitions
00326 // Save VM state
00327 
00328     doc->osHeader() << "/PSSave save def\n";
00329 
00330 // Define a dictionary and start using it
00331 
00332     doc->osHeader() << "/PSDict 200 dict def\n";
00333     doc->osHeader() << "PSDict begin\n";
00334 
00335     doc->osHeader() << "/@restore /restore load def\n";
00336     doc->osHeader() << "/restore\n";
00337     doc->osHeader() << "   {vmstatus pop\n";
00338     doc->osHeader() << "    dup @VMused lt {pop @VMused} if\n";
00339     doc->osHeader() << "    exch pop exch @restore /@VMused exch def\n";
00340     doc->osHeader() << "   } def\n";
00341     doc->osHeader() << "/@pri\n";
00342     doc->osHeader() << "   {\n";
00343     doc->osHeader() << "    ( ) print\n";
00344     doc->osHeader() << "    (                                       ) cvs print\n";
00345     doc->osHeader() << "   } def\n";
00346 
00347 // n @copies -
00348 
00349     doc->osHeader() << "/@copies\n";
00350     doc->osHeader() << "   {\n";
00351     doc->osHeader() << "    /#copies exch def\n";
00352     doc->osHeader() << "   } def\n";
00353 
00354 // - @start -  -- start everything
00355 
00356     doc->osHeader() << "/@start\n";
00357     doc->osHeader() << "   {\n";
00358     doc->osHeader() << "    vmstatus pop /@VMused exch def pop\n";
00359     doc->osHeader() << "   } def\n";
00360 
00361 // - @end -  -- finished
00362 
00363     doc->osHeader() << "/@end\n";
00364     doc->osHeader() << "   {flush\n";
00365     doc->osHeader() << "    end\n";
00366     doc->osHeader() << "    PSSave restore\n";
00367     doc->osHeader() << "   } def\n";
00368 
00369 // bop -  -- begin a new page
00370 // Only fill background if we are using color and if the bg isn't white
00371 
00372     doc->osHeader() << "/bop\n";
00373     doc->osHeader() << "   {\n";
00374     doc->osHeader() << "    /SaveImage save def\n";
00375     doc->osHeader() << "   } def\n";
00376 
00377 // - eop -  -- end a page
00378 
00379     doc->osHeader() << "/eop\n";
00380     doc->osHeader() << "   {\n";
00381     doc->osHeader() << "    showpage\n";
00382     doc->osHeader() << "    SaveImage restore\n";
00383     doc->osHeader() << "   } def\n";
00384 
00385 // Set line parameters
00386 
00387     doc->osHeader() << "/@line\n";
00388     doc->osHeader() << "   {0 setlinecap\n";
00389     doc->osHeader() << "    0 setlinejoin\n";
00390     doc->osHeader() << "    1 setmiterlimit\n";
00391     doc->osHeader() << "   } def\n";
00392 
00393 // d @hsize -  horizontal clipping dimension
00394 
00395     doc->osHeader() << "/@hsize   {/hs exch def} def\n";
00396     doc->osHeader() << "/@vsize   {/vs exch def} def\n";
00397 
00398 // d @hoffset - shift for the plots
00399 
00400     doc->osHeader() << "/@hoffset {/ho exch def} def\n";
00401     doc->osHeader() << "/@voffset {/vo exch def} def\n";
00402 
00403 // Set line width
00404 
00405     doc->osHeader() << "/lw " << (int) (
00406         ( pls->width < MIN_WIDTH ) ? DEF_WIDTH :
00407         ( pls->width > MAX_WIDTH ) ? MAX_WIDTH : pls->width ) << " def\n";
00408 
00409 // Setup user specified offsets, scales, sizes for clipping
00410 
00411     doc->osHeader() << "/@SetPlot\n";
00412     doc->osHeader() << "   {\n";
00413     doc->osHeader() << "    ho vo translate\n";
00414     doc->osHeader() << "    XScale YScale scale\n";
00415     doc->osHeader() << "    lw setlinewidth\n";
00416     doc->osHeader() << "   } def\n";
00417 
00418 // Setup x & y scales
00419 
00420     doc->osHeader() << "/XScale\n";
00421     doc->osHeader() << "   {hs " << YPSSIZE << " div} def\n";
00422     doc->osHeader() << "/YScale\n";
00423     doc->osHeader() << "   {vs " << XPSSIZE << " div} def\n";
00424 
00425 // Macro definitions of common instructions, to keep output small
00426 
00427     doc->osHeader() << "/M {moveto} def\n";
00428     doc->osHeader() << "/D {lineto} def\n";
00429     doc->osHeader() << "/A {0.5 0 360 arc} def\n";
00430     doc->osHeader() << "/S {stroke} def\n";
00431     doc->osHeader() << "/Z {stroke newpath} def\n";
00432     if ( pls->dev_eofill )
00433         doc->osHeader() << "/F {closepath gsave eofill grestore stroke} def\n";
00434     else
00435         doc->osHeader() << "/F {closepath gsave fill grestore stroke} def\n";
00436     doc->osHeader() << "/N {newpath} def\n";
00437     doc->osHeader() << "/C {setrgbcolor} def\n";
00438     doc->osHeader() << "/G {setgray} def\n";
00439     doc->osHeader() << "/W {setlinewidth} def\n";
00440     doc->osHeader() << "/R {rotate} def\n";
00441     doc->osHeader() << "/B {Z " << XMIN << " " << YMIN << " M " << XMIN << " " << YMAX << " D " << XMAX << " " << YMAX << " D " << XMAX << " " << YMIN << " D " << XMIN << " " << YMIN << " closepath} def\n";
00442     doc->osHeader() << "/CL {newpath M D D D closepath clip} def\n";
00443 
00444 // End of dictionary definition
00445 
00446     doc->osHeader() << "end\n\n";
00447 
00448 // Set up the plots
00449 
00450     doc->osHeader() << "PSDict begin\n";
00451     doc->osHeader() << "@start\n";
00452     doc->osHeader() << COPIES << " @copies\n";
00453     doc->osHeader() << "@line\n";
00454     doc->osHeader() << YSIZE << " @hsize\n";
00455     doc->osHeader() << XSIZE << " @vsize\n";
00456     doc->osHeader() << YOFFSET << " @hoffset\n";
00457     doc->osHeader() << XOFFSET << " @voffset\n";
00458 
00459     doc->osHeader() << "@SetPlot\n" << endl;
00460 }
00461 
00462 //--------------------------------------------------------------------------
00463 // plD_line_psttf()
00464 //
00465 // Draw a line in the current color from (x1,y1) to (x2,y2).
00466 //--------------------------------------------------------------------------
00467 
00468 void
00469 plD_line_psttf( PLStream *pls, short x1a, short y1a, short x2a, short y2a )
00470 {
00471     PSDev *dev = (PSDev *) pls->dev;
00472     PostscriptDocument *doc = (PostscriptDocument *) pls->psdoc;
00473     PLINT x1 = x1a, y1 = y1a, x2 = x2a, y2 = y2a;
00474 
00475 // Rotate by 90 degrees
00476 
00477     plRotPhy( ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax, &x1, &y1 );
00478     plRotPhy( ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax, &x2, &y2 );
00479 
00480     if ( x1 == dev->xold && y1 == dev->yold && dev->ptcnt < 40 )
00481     {
00482         if ( pls->linepos + 12 > LINELENGTH )
00483         {
00484             doc->osBody() << '\n';
00485             pls->linepos = 0;
00486         }
00487         else
00488             doc->osBody() << ' ';
00489 
00490         snprintf( outbuf, OUTBUF_LEN, "%d %d D", x2, y2 );
00491         dev->ptcnt++;
00492         pls->linepos += 12;
00493     }
00494     else
00495     {
00496         doc->osBody() << " Z\n";
00497         pls->linepos = 0;
00498 
00499         if ( x1 == x2 && y1 == y2 ) // must be a single dot, draw a circle
00500             snprintf( outbuf, OUTBUF_LEN, "%d %d A", x1, y1 );
00501         else
00502             snprintf( outbuf, OUTBUF_LEN, "%d %d M %d %d D", x1, y1, x2, y2 );
00503         dev->llx      = MIN( dev->llx, x1 );
00504         dev->lly      = MIN( dev->lly, y1 );
00505         dev->urx      = MAX( dev->urx, x1 );
00506         dev->ury      = MAX( dev->ury, y1 );
00507         dev->ptcnt    = 1;
00508         pls->linepos += 24;
00509     }
00510     dev->llx = MIN( dev->llx, x2 );
00511     dev->lly = MIN( dev->lly, y2 );
00512     dev->urx = MAX( dev->urx, x2 );
00513     dev->ury = MAX( dev->ury, y2 );
00514 
00515     doc->osBody() << outbuf;
00516     pls->bytecnt += 1 + strlen( outbuf );
00517     dev->xold     = x2;
00518     dev->yold     = y2;
00519 }
00520 
00521 //--------------------------------------------------------------------------
00522 // plD_polyline_psttf()
00523 //
00524 // Draw a polyline in the current color.
00525 //--------------------------------------------------------------------------
00526 
00527 void
00528 plD_polyline_psttf( PLStream *pls, short *xa, short *ya, PLINT npts )
00529 {
00530     PLINT i;
00531 
00532     for ( i = 0; i < npts - 1; i++ )
00533         plD_line_psttf( pls, xa[i], ya[i], xa[i + 1], ya[i + 1] );
00534 }
00535 
00536 //--------------------------------------------------------------------------
00537 // plD_eop_psttf()
00538 //
00539 // End of page.
00540 //--------------------------------------------------------------------------
00541 
00542 void
00543 plD_eop_psttf( PLStream *pls )
00544 {
00545     PostscriptDocument *doc = (PostscriptDocument *) pls->psdoc;
00546     doc->osBody() << " S\neop\n";
00547 }
00548 
00549 //--------------------------------------------------------------------------
00550 // plD_bop_psttf()
00551 //
00552 // Set up for the next page.
00553 // Advance to next family file if necessary (file output).
00554 //--------------------------------------------------------------------------
00555 
00556 void
00557 plD_bop_psttf( PLStream *pls )
00558 {
00559     PSDev *dev = (PSDev *) pls->dev;
00560     PostscriptDocument *doc = (PostscriptDocument *) pls->psdoc;
00561 
00562     dev->xold = PL_UNDEFINED;
00563     dev->yold = PL_UNDEFINED;
00564 
00565     if ( !pls->termin )
00566         plGetFam( pls );
00567 
00568     pls->page++;
00569 
00570     if ( pls->family )
00571         doc->osBody() << "%%Page: " << (int) pls->page << " 1\n";
00572     else
00573         doc->osBody() << "%%Page: " << (int) pls->page << " " << (int) pls->page << "\n";
00574 
00575     doc->osBody() << "bop\n";
00576     if ( pls->color )
00577     {
00578         PLFLT r, g, b;
00579         if ( pls->cmap0[0].r != 0xFF ||
00580              pls->cmap0[0].g != 0xFF ||
00581              pls->cmap0[0].b != 0xFF )
00582         {
00583             r = ( (PLFLT) pls->cmap0[0].r ) / 255.;
00584             g = ( (PLFLT) pls->cmap0[0].g ) / 255.;
00585             b = ( (PLFLT) pls->cmap0[0].b ) / 255.;
00586 
00587             doc->osBody() << "B " << r << " " << g << " " << b << " C F\n";
00588         }
00589     }
00590     pls->linepos = 0;
00591 
00592 // This ensures the color and line width are set correctly at the beginning of
00593 //   each page
00594 
00595     plD_state_psttf( pls, PLSTATE_COLOR0 );
00596     plD_state_psttf( pls, PLSTATE_WIDTH );
00597 }
00598 
00599 //--------------------------------------------------------------------------
00600 // plD_tidy_psttf()
00601 //
00602 // Close graphics file or otherwise clean up.
00603 //--------------------------------------------------------------------------
00604 
00605 void
00606 plD_tidy_psttf( PLStream *pls )
00607 {
00608     PSDev *dev = (PSDev *) pls->dev;
00609     PostscriptDocument *doc = (PostscriptDocument *) pls->psdoc;
00610 
00611     dev->llx /= ENLARGE;
00612     dev->lly /= ENLARGE;
00613     dev->urx /= ENLARGE;
00614     dev->ury /= ENLARGE;
00615     dev->llx += XOFFSET;
00616     dev->lly += YOFFSET;
00617     dev->urx += XOFFSET;
00618     dev->ury += YOFFSET;
00619 
00620 // changed for correct Bounding boundaries Jan Thorbecke  okt 1993
00621 // occurs from the integer truncation -- postscript uses fp arithmetic
00622 
00623     dev->urx += 1;
00624     dev->ury += 1;
00625 
00626     if ( pls->family )
00627         doc->osFooter() << "%%Pages: 1\n";
00628     else
00629         doc->osFooter() << "%%Pages: " << (int) pls->page << "\n";
00630 
00631     doc->osFooter() << "@end" << endl;
00632 
00633 // Now write the rest of the header
00634     writeHeader( pls );
00635 
00636 // Write out postscript document to file and close
00637     // For C++ stream we first need to close the file using
00638 //       the C FILE * handle, then reopen as a ofstream. Yuck!
00639     if ( !strcmp( pls->FileName, "-" ) )
00640     {
00641         doc->write( cout, dev->llx, dev->lly, dev->urx, dev->ury );
00642     }
00643     else
00644     {
00645         plCloseFile( pls );
00646         ofstream out;
00647         out.open( pls->FileName );
00648         doc->write( out, dev->llx, dev->lly, dev->urx, dev->ury );
00649         out.close();
00650     }
00651 
00652     delete doc;
00653     pls->psdoc = NULL;
00654 }
00655 
00656 //--------------------------------------------------------------------------
00657 // plD_state_psttf()
00658 //
00659 // Handle change in PLStream state (color, pen width, fill attribute, etc).
00660 //--------------------------------------------------------------------------
00661 
00662 void
00663 plD_state_psttf( PLStream *pls, PLINT op )
00664 {
00665     PSDev *dev = (PSDev *) pls->dev;
00666     PostscriptDocument *doc = (PostscriptDocument *) pls->psdoc;
00667 
00668     switch ( op )
00669     {
00670     case PLSTATE_WIDTH: {
00671         int width = (int) (
00672             ( pls->width < MIN_WIDTH ) ? DEF_WIDTH :
00673             ( pls->width > MAX_WIDTH ) ? MAX_WIDTH : pls->width );
00674 
00675         doc->osBody() << " S\n" << width << " W";
00676 
00677         dev->xold = PL_UNDEFINED;
00678         dev->yold = PL_UNDEFINED;
00679         break;
00680     }
00681     case PLSTATE_COLOR0:
00682         if ( !pls->color )
00683         {
00684             doc->osBody() << " S\n" << ( pls->icol0 ? 0.0 : 1.0 ) << " G";
00685             break;
00686         }
00687     // else fallthrough
00688     case PLSTATE_COLOR1:
00689         if ( pls->color )
00690         {
00691             PLFLT r = ( (PLFLT) pls->curcolor.r ) / 255.0;
00692             PLFLT g = ( (PLFLT) pls->curcolor.g ) / 255.0;
00693             PLFLT b = ( (PLFLT) pls->curcolor.b ) / 255.0;
00694 
00695             doc->osBody() << " S\n" << r << " " << g << " " << b << " C";
00696         }
00697         else
00698         {
00699             PLFLT r = ( (PLFLT) pls->curcolor.r ) / 255.0;
00700             doc->osBody() << " S\n" << 1.0 - r << " G";
00701         }
00702         break;
00703     }
00704 
00705 // Reinitialize current point location.
00706 
00707     if ( dev->xold != PL_UNDEFINED && dev->yold != PL_UNDEFINED )
00708     {
00709         doc->osBody() << " " << (int) dev->xold << " " << (int) dev->yold << " M \n";
00710     }
00711 }
00712 
00713 //--------------------------------------------------------------------------
00714 // plD_esc_psttf()
00715 //
00716 // Escape function.
00717 //--------------------------------------------------------------------------
00718 
00719 void
00720 plD_esc_psttf( PLStream *pls, PLINT op, void *ptr )
00721 {
00722     switch ( op )
00723     {
00724     case PLESC_FILL:
00725         fill_polygon( pls );
00726         break;
00727     case PLESC_HAS_TEXT:
00728         proc_str( pls, (EscText *) ptr );
00729         break;
00730     }
00731 }
00732 
00733 //--------------------------------------------------------------------------
00734 // fill_polygon()
00735 //
00736 // Fill polygon described in points pls->dev_x[] and pls->dev_y[].
00737 // Only solid color fill supported.
00738 //--------------------------------------------------------------------------
00739 
00740 static void
00741 fill_polygon( PLStream *pls )
00742 {
00743     PSDev *dev = (PSDev *) pls->dev;
00744     PostscriptDocument *doc = (PostscriptDocument *) pls->psdoc;
00745     PLINT n, ix = 0, iy = 0;
00746     PLINT x, y;
00747 
00748     doc->osBody() << " Z\n";
00749 
00750     for ( n = 0; n < pls->dev_npts; n++ )
00751     {
00752         x = pls->dev_x[ix++];
00753         y = pls->dev_y[iy++];
00754 
00755 // Rotate by 90 degrees
00756 
00757         plRotPhy( ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax, &x, &y );
00758 
00759 // First time through start with a x y moveto
00760 
00761         if ( n == 0 )
00762         {
00763             snprintf( outbuf, OUTBUF_LEN, "N %d %d M", x, y );
00764             dev->llx = MIN( dev->llx, x );
00765             dev->lly = MIN( dev->lly, y );
00766             dev->urx = MAX( dev->urx, x );
00767             dev->ury = MAX( dev->ury, y );
00768             doc->osBody() << outbuf;
00769             pls->bytecnt += strlen( outbuf );
00770             continue;
00771         }
00772 
00773         if ( pls->linepos + 21 > LINELENGTH )
00774         {
00775             doc->osBody() << '\n';
00776             pls->linepos = 0;
00777         }
00778         else
00779             doc->osBody() << ' ';
00780 
00781         pls->bytecnt++;
00782 
00783         snprintf( outbuf, OUTBUF_LEN, "%d %d D", x, y );
00784         dev->llx = MIN( dev->llx, x );
00785         dev->lly = MIN( dev->lly, y );
00786         dev->urx = MAX( dev->urx, x );
00787         dev->ury = MAX( dev->ury, y );
00788 
00789         doc->osBody() << outbuf;
00790         pls->bytecnt += strlen( outbuf );
00791         pls->linepos += 21;
00792     }
00793     dev->xold = PL_UNDEFINED;
00794     dev->yold = PL_UNDEFINED;
00795     doc->osBody() << " F ";
00796 }
00797 
00798 //--------------------------------------------------------------------------
00799 // ps_getdate()
00800 //
00801 // Get the date and time
00802 //--------------------------------------------------------------------------
00803 
00804 static char *
00805 ps_getdate( void )
00806 {
00807     int    len;
00808     time_t t;
00809     char   *p;
00810 
00811     t   = time( (time_t *) 0 );
00812     p   = ctime( &t );
00813     len = strlen( p );
00814     *( p + len - 1 ) = '\0';      // zap the newline character
00815     return p;
00816 }
00817 
00818 // 0.8 should mimic the offset of first superscript/subscript level
00819 // implemented in plstr (plsym.c) for Hershey fonts.  However, when
00820 // comparing with -dev xwin and -dev xcairo results changing this
00821 // factor to 0.6 appears to offset the centers of the letters
00822 // appropriately while 0.8 gives much poorer agreement with the
00823 // other devices.
00824 # define RISE_FACTOR    0.6
00825 
00826 //--------------------------------------------------------------------------
00827 // proc_str()
00828 //
00829 // Prints postscript strings.
00830 // N.B. Now unicode only, no string access!
00831 //
00832 //--------------------------------------------------------------------------
00833 
00834 void
00835 proc_str( PLStream *pls, EscText *args )
00836 {
00837     PLFLT *t = args->xform, tt[4];              // Transform matrices
00838     PLFLT theta, shear, stride;                 // Rotation angle and shear from the matrix
00839     PLFLT ft_ht, offset;                        // Font height and offset
00840     PLFLT cs, sn;
00841     PSDev *dev = (PSDev *) pls->dev;
00842     PostscriptDocument *doc = (PostscriptDocument *) pls->psdoc;
00843     char               *font, esc;
00844     FontStyle          style;
00845     FontWeight         weight;
00846     // Be generous.  Used to store lots of font changes which take
00847     // 3 characters per change.
00848   #define PROC_STR_STRING_LENGTH    1000
00849     char   *strp, str[PROC_STR_STRING_LENGTH], *cur_strp,
00850             cur_str[PROC_STR_STRING_LENGTH];
00851     float  font_factor = 1.4;
00852     PLINT  clxmin, clxmax, clymin, clymax;  // Clip limits
00853     PLINT  clipx[4], clipy[4];              // Current clip limits
00854 
00855     PLFLT  scale = 1., up = 0.;             // Font scaling and shifting parameters
00856 
00857     double lineSpacing, xAdvance, ymintmp, ymaxtmp, ymin, ymax, xmin, xmax;
00858     PLINT  xx[4], yy[4];
00859 
00860     // unicode only! so test for it.
00861     if ( args->unicode_array_len > 0 )
00862     {
00863         int             j, s, f;
00864         char            *fonts[PROC_STR_STRING_LENGTH];
00865         FontStyle       styles[PROC_STR_STRING_LENGTH];
00866         FontWeight      weights[PROC_STR_STRING_LENGTH];
00867         const PLUNICODE *cur_text;
00868         PLUNICODE       fci;
00869         unsigned char   fontfamily, fontstyle, fontweight;
00870         PLFLT           old_sscale, sscale, old_soffset, soffset, dup;
00871         PLINT           level = 0;
00872 
00873         // translate from unicode into type 1 font index.
00874         //
00875         // Choose the font family, style, variant, and weight using
00876         // the FCI (font characterization integer).
00877         //
00878 
00879         plgesc( &esc );
00880         plgfci( &fci );
00881         plP_fci2hex( fci, &fontfamily, PL_FCI_FAMILY );
00882         plP_fci2hex( fci, &fontstyle, PL_FCI_STYLE );
00883         plP_fci2hex( fci, &fontweight, PL_FCI_WEIGHT );
00884         font   = (char *) FamilyLookup[fontfamily];
00885         weight = WeightLookup[fontweight];
00886         style  = StyleLookup[fontstyle];
00887         // Need to add some error checking here
00888         if ( false )
00889         {
00890             fprintf( stderr, "fci = 0x%x, font name pointer = NULL \n", fci );
00891             plabort( "proc_str: FCI inconsistent with TrueTypeLookup; "
00892                 "internal PLplot error" );
00893             return;
00894         }
00895         //pldebug("proc_str", "fci = 0x%x, font name = %s\n", fci, font);
00896         cur_text = args->unicode_array;
00897         for ( f = s = j = 0; j < args->unicode_array_len; j++ )
00898         {
00899             if ( cur_text[j] & PL_FCI_MARK )
00900             {
00901                 // process an FCI by saving it and escaping cur_str
00902                 // with an escff to make it a 2-character escape
00903                 // that is not used in legacy Hershey code
00904                 //
00905                 if ( ( f < PROC_STR_STRING_LENGTH ) && ( s + 3 < PROC_STR_STRING_LENGTH ) )
00906                 {
00907                     plP_fci2hex( cur_text[j], &fontfamily, PL_FCI_FAMILY );
00908                     plP_fci2hex( cur_text[j], &fontstyle, PL_FCI_STYLE );
00909                     plP_fci2hex( cur_text[j], &fontweight, PL_FCI_WEIGHT );
00910                     fonts[f]   = (char *) FamilyLookup[fontfamily];
00911                     weights[f] = WeightLookup[fontweight];
00912                     styles[f]  = StyleLookup[fontstyle];
00913                     if ( fonts[f] == NULL )
00914                     {
00915                         fprintf( stderr, "string-supplied FCI = 0x%x, font name pointer = NULL \n", cur_text[j] );
00916                         plabort( "proc_str: string-supplied FCI inconsistent with font lookup;" );
00917                         return;
00918                     }
00919                     //pldebug("proc_str", "string-supplied FCI = 0x%x, font name = %s\n", cur_text[j], fonts[f]);
00920                     cur_str[s++] = esc;
00921                     cur_str[s++] = 'f';
00922                     cur_str[s++] = 'f';
00923                     f++;
00924                 }
00925             }
00926             else if ( s + 1 < PROC_STR_STRING_LENGTH )
00927             {
00928                 s += ucs4_to_utf8( cur_text[j], &cur_str[s] );
00929                 //pldebug("proc_str", "unicode = 0x%x, type 1 code = %d\n",
00930 //                          cur_text[j], cur_str[j]);
00931             }
00932         }
00933         cur_str[s] = '\0';
00934 
00935         // finish previous polyline
00936 
00937         dev->xold = PL_UNDEFINED;
00938         dev->yold = PL_UNDEFINED;
00939 
00940         // Determine the font height
00941         ft_ht = pls->chrht * 72.0 / 25.4; // ft_ht in points, ht is in mm
00942 
00943 
00944         // The transform matrix has only rotations and shears; extract them
00945         plRotationShear( t, &theta, &shear, &stride );
00946         cs    = cos( theta );
00947         sn    = sin( theta );
00948         tt[0] = t[0] * cs + t[2] * sn;
00949         tt[1] = t[1] * cs + t[3] * sn;
00950         tt[2] = -t[0] * sn + t[2] * cs;
00951         tt[3] = -t[1] * sn + t[3] * cs;
00952 
00953         //
00954         // Reference point conventions:
00955         //   If base = 0, it is aligned with the center of the text box
00956         //   If base = 1, it is aligned with the baseline of the text box
00957         //   If base = 2, it is aligned with the top of the text box
00958         //
00959         // Currently plplot only uses base=0
00960         // Postscript uses base=1
00961         //
00962         // We must calculate the difference between the two and apply the offset.
00963         //
00964 
00965         if ( args->base == 2 )             // not supported by plplot
00966             offset = ENLARGE * ft_ht / 2.; // half font height
00967         else if ( args->base == 1 )
00968             offset = 0.;
00969         else
00970             offset = -ENLARGE * ft_ht / 2.;
00971 
00972         // Determine the adjustment for page orientation
00973         theta   -= PI / 2. * pls->diorot;
00974         args->y += (int) ( offset * cos( theta ) );
00975         args->x -= (int) ( offset * sin( theta ) );
00976 
00977         // ps driver is rotated by default
00978         plRotPhy( ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax,
00979             &( args->x ), &( args->y ) );
00980 
00981         // Correct for the fact ps driver uses landscape by default
00982         theta += PI / 2.;
00983 
00984         // Output
00985         // Set clipping
00986         clipx[0] = pls->clpxmi;
00987         clipx[2] = pls->clpxma;
00988         clipy[0] = pls->clpymi;
00989         clipy[2] = pls->clpyma;
00990         clipx[1] = clipx[2];
00991         clipy[1] = clipy[0];
00992         clipx[3] = clipx[0];
00993         clipy[3] = clipy[2];
00994         difilt( clipx, clipy, 4, &clxmin, &clxmax, &clymin, &clymax );
00995         plRotPhy( ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax,
00996             &clipx[0], &clipy[0] );
00997         plRotPhy( ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax,
00998             &clipx[1], &clipy[1] );
00999         plRotPhy( ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax,
01000             &clipx[2], &clipy[2] );
01001         plRotPhy( ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax,
01002             &clipx[3], &clipy[3] );
01003         doc->osBody() << " gsave " << clipx[0] << " " << clipy[0] << " " <<
01004         clipx[1] << " " << clipy[1] << " " << clipx[2] << " " <<
01005         clipy[2] << " " << clipx[3] << " " << clipy[3] << " CL\n";
01006 
01007         // move to string reference point
01008         doc->osBody() << " " << args->x << " " << args->y << " M\n";
01009 
01010         // Save the current position and set the string rotation
01011         doc->osBody() << "gsave " << TRMFLT( theta * 180. / PI ) << " R\n";
01012 
01013         doc->osBody() << "[" << TRMFLT( tt[0] ) << " " << TRMFLT( tt[2] ) << " " << TRMFLT( tt[1] )
01014                       << " " << TRMFLT( tt[3] ) << " 0 0] concat\n";
01015 
01016         xmax = 0;
01017         // Dummy run through the string first to work out the
01018         // length, including any font changes
01019         cur_strp = cur_str;
01020         f        = 0;
01021         do
01022         {
01023             strp = str;
01024 
01025             if ( *cur_strp == esc )
01026             {
01027                 cur_strp++;
01028 
01029                 if ( *cur_strp == esc ) // <esc><esc>
01030                 {
01031                     *strp++ = *cur_strp++;
01032                 }
01033                 else if ( *cur_strp == 'f' )
01034                 {
01035                     cur_strp++;
01036                     if ( *cur_strp++ != 'f' )
01037                     {
01038                         // escff occurs because of logic above. But any suffix
01039                         // other than "f" should never happen.
01040                         plabort( "proc_str, internal PLplot logic error;"
01041                             "wrong escf escape sequence" );
01042                         return;
01043                     }
01044                     font   = fonts[f];
01045                     style  = styles[f];
01046                     weight = weights[f];
01047                     f++;
01048                     continue;
01049                 }
01050                 else
01051                     switch ( *cur_strp++ )
01052                     {
01053                     case 'd': //subscript
01054                     case 'D':
01055                         plP_script_scale( FALSE, &level,
01056                             &old_sscale, &sscale, &old_soffset, &soffset );
01057                         scale = sscale;
01058                         // The correction for the difference in magnitude
01059                         // between the baseline and middle coordinate systems
01060                         // for subscripts should be
01061                         // -0.5*(base font size - superscript/subscript font size).
01062                         dup = -0.5 * ( 1.0 - sscale );
01063                         up  = -font_factor * ENLARGE * ft_ht * ( RISE_FACTOR * soffset + dup );
01064                         break;
01065 
01066                     case 'u': //superscript
01067                     case 'U':
01068                         plP_script_scale( TRUE, &level,
01069                             &old_sscale, &sscale, &old_soffset, &soffset );
01070                         scale = sscale;
01071                         // The correction for the difference in magnitude
01072                         // between the baseline and middle coordinate systems
01073                         // for superscripts should be
01074                         // 0.5*(base font size - superscript/subscript font size).
01075                         dup = 0.5 * ( 1.0 - sscale );
01076                         up  = font_factor * ENLARGE * ft_ht * ( RISE_FACTOR * soffset + dup );
01077                         break;
01078 
01079                     // ignore the next sequences
01080 
01081                     case '+':
01082                     case '-':
01083                     case 'b':
01084                     case 'B':
01085                         plwarn( "'+', '-', and 'b/B' text escape sequences not processed." );
01086                         break;
01087                     }
01088             }
01089 
01090             // copy from current to next token, adding a postscript escape
01091             // char '\' if necessary
01092             //
01093             while ( *cur_strp && *cur_strp != esc )
01094             {
01095                 *strp++ = *cur_strp++;
01096             }
01097             *strp = '\0';
01098 
01099             //     if(fabs(up)<0.001) up = 0.; /* Watch out for small differences */
01100 
01101             // Set the font size
01102             doc->setFont( font, style, weight );
01103             doc->setFontSize( font_factor * ENLARGE * ft_ht * scale );
01104             doc->get_dimensions( (const char *) str, &lineSpacing, &xAdvance, &ymintmp, &ymaxtmp );
01105             xmax += xAdvance;
01106         } while ( *cur_strp );
01107 
01108         // Use the length of the string to calculate offset
01109         // Also used later for bounding box
01110         xmin = -xmax * args->just;
01111         xmax = xmin;
01112         ymin = 0;
01113         ymax = 0;
01114 
01115         // Reset parameters
01116         level = 0;
01117         scale = 1.0;
01118         up    = 0.0;
01119 
01120         // Move relative to position to account for justification
01121         doc->osBody() << " gsave " << TRMFLT( xmin * tt[0] ) << " " <<
01122         TRMFLT( xmin * tt[2] ) << " rmoveto\n";
01123 
01124         // Parse string for PLplot escape sequences and print everything out
01125 
01126         cur_strp = cur_str;
01127         f        = 0;
01128         do
01129         {
01130             strp = str;
01131 
01132             if ( *cur_strp == esc )
01133             {
01134                 cur_strp++;
01135 
01136                 if ( *cur_strp == esc ) // <esc><esc>
01137                 {
01138                     *strp++ = *cur_strp++;
01139                 }
01140                 else if ( *cur_strp == 'f' )
01141                 {
01142                     cur_strp++;
01143                     if ( *cur_strp++ != 'f' )
01144                     {
01145                         // escff occurs because of logic above. But any suffix
01146                         // other than "f" should never happen.
01147                         plabort( "proc_str, internal PLplot logic error;"
01148                             "wrong escf escape sequence" );
01149                         return;
01150                     }
01151                     font   = fonts[f];
01152                     style  = styles[f];
01153                     weight = weights[f];
01154                     f++;
01155                     //pldebug("proc_str", "string-specified fci = 0x%x, font name = %s\n", fci, font);
01156                     continue;
01157                 }
01158                 else
01159                     switch ( *cur_strp++ )
01160                     {
01161                     case 'd': //subscript
01162                     case 'D':
01163                         plP_script_scale( FALSE, &level,
01164                             &old_sscale, &sscale, &old_soffset, &soffset );
01165                         scale = sscale;
01166                         // The correction for the difference in magnitude
01167                         // between the baseline and middle coordinate systems
01168                         // for subscripts should be
01169                         // -0.5*(base font size - superscript/subscript font size).
01170                         dup = -0.5 * ( 1.0 - sscale );
01171                         up  = -font_factor * ENLARGE * ft_ht * ( RISE_FACTOR * soffset + dup );
01172                         break;
01173 
01174                     case 'u': //superscript
01175                     case 'U':
01176                         plP_script_scale( TRUE, &level,
01177                             &old_sscale, &sscale, &old_soffset, &soffset );
01178                         scale = sscale;
01179                         // The correction for the difference in magnitude
01180                         // between the baseline and middle coordinate systems
01181                         // for superscripts should be
01182                         // 0.5*(base font size - superscript/subscript font size).
01183                         dup = 0.5 * ( 1.0 - sscale );
01184                         up  = font_factor * ENLARGE * ft_ht * ( RISE_FACTOR * soffset + dup );
01185                         break;
01186 
01187                     // ignore the next sequences
01188 
01189                     case '+':
01190                     case '-':
01191                     case 'b':
01192                     case 'B':
01193                         plwarn( "'+', '-', and 'b/B' text escape sequences not processed." );
01194                         break;
01195                     }
01196             }
01197 
01198             // copy from current to next token, adding a postscript escape
01199             // char '\' if necessary
01200             //
01201             while ( *cur_strp && *cur_strp != esc )
01202             {
01203                 *strp++ = *cur_strp++;
01204             }
01205             *strp = '\0';
01206 
01207             //     if(fabs(up)<0.001) up = 0.; /* Watch out for small differences */
01208 
01209             // Set the font size
01210             doc->setFont( font, style, weight );
01211             doc->setFontSize( font_factor * ENLARGE * ft_ht * scale );
01212             doc->get_dimensions( (const char *) str, &lineSpacing, &xAdvance, &ymintmp, &ymaxtmp );
01213             ymin  = MIN( ymintmp + up, ymin );
01214             ymax  = MAX( ymaxtmp + up, ymax );
01215             xmax += xAdvance;
01216 
01217             // if up/down escape sequences, save current point and adjust baseline;
01218             // take the shear into account
01219             if ( up != 0. )
01220                 doc->osBody() << "gsave " << TRMFLT( up * tt[1] ) << " " << TRMFLT( up * tt[3] ) << " rmoveto\n";
01221 
01222             // print the string
01223             doc->osBody() << show( (const char *) str );
01224 
01225             // back to baseline
01226             if ( up != 0. )
01227                 doc->osBody() << "grestore " << TRMFLT( xAdvance * tt[0] ) << " " << TRMFLT( xAdvance * tt[2] ) << " rmoveto\n";
01228         } while ( *cur_strp );
01229 
01230         doc->osBody() << "grestore\n";
01231         doc->osBody() << "grestore\n";
01232         doc->osBody() << "grestore\n";
01233 
01234         //
01235         // Estimate text bounding box from LASi get_dimensions function.
01236         // xmin, xmax are text left and right extents,
01237         // ymin, ymax are top and bottom extents.
01238         // These need to be rotated / transformed to get the correct values
01239         //
01240         xx[0] = (PLINT) ( t[0] * xmin + t[1] * ymin );
01241         yy[0] = (PLINT) ( t[2] * xmin + t[3] * ymin );
01242         xx[1] = (PLINT) ( t[0] * xmin + t[1] * ymax );
01243         yy[1] = (PLINT) ( t[2] * xmin + t[3] * ymax );
01244         xx[2] = (PLINT) ( t[0] * xmax + t[1] * ymin );
01245         yy[2] = (PLINT) ( t[2] * xmax + t[3] * ymin );
01246         xx[3] = (PLINT) ( t[0] * xmax + t[1] * ymax );
01247         yy[3] = (PLINT) ( t[2] * xmax + t[3] * ymax );
01248 
01249         plRotPhy( ORIENTATION, 0, 0, 0, 0, &xx[0], &yy[0] );
01250         plRotPhy( ORIENTATION, 0, 0, 0, 0, &xx[1], &yy[1] );
01251         plRotPhy( ORIENTATION, 0, 0, 0, 0, &xx[2], &yy[2] );
01252         plRotPhy( ORIENTATION, 0, 0, 0, 0, &xx[3], &yy[3] );
01253 
01254 
01255         xmin = MIN( MIN( MIN( xx[0], xx[1] ), xx[2] ), xx[3] ) + args->x;
01256         xmax = MAX( MAX( MAX( xx[0], xx[1] ), xx[2] ), xx[3] ) + args->x;
01257         ymin = MIN( MIN( MIN( yy[0], yy[1] ), yy[2] ), yy[3] ) + args->y;
01258         ymax = MAX( MAX( MAX( yy[0], yy[1] ), yy[2] ), yy[3] ) + args->y;
01259 
01260         dev->llx = (int) ( MIN( dev->llx, xmin ) );
01261         dev->lly = (int) ( MIN( dev->lly, ymin ) );
01262         dev->urx = (int) ( MAX( dev->urx, xmax ) );
01263         dev->ury = (int) ( MAX( dev->ury, ymax ) );
01264 //      doc->osBody() << "Z " << xmin << " " << ymin << " M "
01265 //                    << xmin << " " << ymax << " D "
01266 //                    << xmax << " " << ymax << " D "
01267 //                    << xmax << " " << ymin << " D "
01268 //                    << xmin << " " << ymin << " closepath\n"
01269 //                    << "Z " << args->x << " " << args->y << " A closepath\n";
01270     }
01271 }
01272 
01273 //static void
01274 //esc_purge( char *dstr, char *sstr )
01275 //{
01276 //    char esc;
01277 //
01278 //    plgesc( &esc );
01279 //
01280 //    while ( *sstr )
01281 //    {
01282 //        if ( *sstr != esc )
01283 //        {
01284 //            *dstr++ = *sstr++;
01285 //            continue;
01286 //        }
01287 //
01288 //        sstr++;
01289 //        if ( *sstr == esc )
01290 //        {
01291 //            *dstr++ = *sstr++;
01292 //            continue;
01293 //        }
01294 //
01295 //        else
01296 //        {
01297 //            switch ( *sstr++ )
01298 //            {
01299 //            case 'f':
01300 //                sstr++;
01301 //                break; // two chars sequence
01302 //
01303 //            default:
01304 //                break; // single char escape
01305 //            }
01306 //        }
01307 //    }
01308 //    *dstr = '\0';
01309 //}
01310 
01311 #else
01312 int
01313 pldummy_psttf()
01314 {
01315     return 0;
01316 }
01317 
01318 #endif                          // defined(PLD_psttf) || ....
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines