• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

psttf.cc

Go to the documentation of this file.
00001 // $Id: psttf.cc 11795 2011-07-06 02:28:50Z airwin $
00002 //
00003 //        PLplot PostScript device driver using LASi to provide fonts
00004 //        based on original ps.c PostScript driver
00005 //
00006 //  Copyright (C) 1992, 2001  Geoffrey Furnish
00007 //  Copyright (C) 1992, 1993, 1994, 1995, 2001  Maurice LeBrun
00008 //  Copyright (C) 2000-2011 Alan W. Irwin
00009 //  Copyright (C) 2001, 2002  Joao Cardoso
00010 //  Copyright (C) 2001, 2003, 2004  Rafael Laboissiere
00011 //  Copyright (C) 2004, 2005  Thomas J. Duck
00012 //  Copyright (C) 2005, 2006  Andrew Ross
00013 //
00014 //  This file is part of PLplot.
00015 //
00016 //  PLplot is free software; you can redistribute it and/or modify
00017 //  it under the terms of the GNU Library General Public License as published
00018 //  by the Free Software Foundation; either version 2 of the License, or
00019 //  (at your option) any later version.
00020 //
00021 //  PLplot is distributed in the hope that it will be useful,
00022 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00023 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00024 //  GNU Library General Public License for more details.
00025 //
00026 //  You should have received a copy of the GNU Library General Public License
00027 //  along with PLplot; if not, write to the Free Software
00028 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
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 // Define macro to truncate small values to zero - prevents
00051 //  * printf printing -0.000
00052 #define TRMFLT( a )    ( ( fabs( a ) < 5.0e-4 ) ? 0.0 : ( a ) )
00053 
00054 using namespace LASi;
00055 using namespace std;
00056 
00057 // Device info
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 // Prototypes for functions in this file.
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 // Font style and weight lookup tables
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 // text > 0 uses some postscript tricks, namely a transformation matrix
00121 //   that scales, rotates (with slanting) and offsets text strings.
00122 //   It has yet some bugs for 3d plots.
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 // plD_init_psttf()
00163 //
00164 // Initialize device.
00165 //--------------------------------------------------------------------------
00166 
00167 void
00168 plD_init_psttfm( PLStream *pls )
00169 {
00170     color      = 0;
00171     pls->color = 0;             // Not a color device
00172 
00173     plParseDrvOpts( ps_options );
00174     if ( color )
00175         pls->color = 1;         // But user wants color
00176     ps_init( pls );
00177 }
00178 
00179 void
00180 plD_init_psttfc( PLStream *pls )
00181 {
00182     color      = 1;
00183     pls->color = 1;             // Is a color device
00184     plParseDrvOpts( ps_options );
00185 
00186     if ( !color )
00187         pls->color = 0;         // But user does not want color
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     // Set default values - 7.5 x 10 [inches] (72 points = 1 inch)
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;     // want to draw text
00219         pls->dev_unicode = 1;     // want unicode
00220         if ( hrshsym )
00221             pls->dev_hrshsym = 1; // want Hershey symbols
00222     }
00223 
00224     pls->dev_fill0 = 1;         // Can do solid fills
00225 
00226 // Initialize family file info
00227 
00228     plFamInit( pls );
00229 
00230 // Prompt for a file name if not already set
00231 
00232     plOpenFile( pls );
00233 
00234 // Create postscript document object
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 // Allocate and initialize device-specific data
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 // Rotate by 90 degrees since portrait mode addressing is used
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 // If portrait mode is specified, then set up an additional rotation
00277 // transformation with aspect ratio allowed to adjust via freeaspect.
00278 // Default orientation is landscape (ORIENTATION == 3 or 90 deg rotation
00279 // counter-clockwise from portrait).  (Legacy PLplot used seascape
00280 // which was equivalent to ORIENTATION == 1 or 90 deg clockwise rotation
00281 // from portrait.)
00282 
00283     if ( pls->portrait )
00284     {
00285         plsdiori( (PLFLT) ( 4 - ORIENTATION ) );
00286         pls->freeaspect = 1;
00287     }
00288 
00289     // File table for font families using either environment variables
00290     // or defaults.
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 // writeHeader()
00309 //
00310 // Write plplot postscript commands into the header
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 // Definitions
00327 // Save VM state
00328 
00329     doc->osHeader() << "/PSSave save def\n";
00330 
00331 // Define a dictionary and start using it
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 // n @copies -
00349 
00350     doc->osHeader() << "/@copies\n";
00351     doc->osHeader() << "   {\n";
00352     doc->osHeader() << "    /#copies exch def\n";
00353     doc->osHeader() << "   } def\n";
00354 
00355 // - @start -  -- start everything
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 // - @end -  -- finished
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 // bop -  -- begin a new page
00371 // Only fill background if we are using color and if the bg isn't white
00372 
00373     doc->osHeader() << "/bop\n";
00374     doc->osHeader() << "   {\n";
00375     doc->osHeader() << "    /SaveImage save def\n";
00376     doc->osHeader() << "   } def\n";
00377 
00378 // - eop -  -- end a page
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 // Set line parameters
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 // d @hsize -  horizontal clipping dimension
00395 
00396     doc->osHeader() << "/@hsize   {/hs exch def} def\n";
00397     doc->osHeader() << "/@vsize   {/vs exch def} def\n";
00398 
00399 // d @hoffset - shift for the plots
00400 
00401     doc->osHeader() << "/@hoffset {/ho exch def} def\n";
00402     doc->osHeader() << "/@voffset {/vo exch def} def\n";
00403 
00404 // Set line width
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 // Setup user specified offsets, scales, sizes for clipping
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 // Setup x & y scales
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 // Macro definitions of common instructions, to keep output small
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 // End of dictionary definition
00446 
00447     doc->osHeader() << "end\n\n";
00448 
00449 // Set up the plots
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 // plD_line_psttf()
00465 //
00466 // Draw a line in the current color from (x1,y1) to (x2,y2).
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 // Rotate by 90 degrees
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 ) // must be a single dot, draw a circle
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 // plD_polyline_psttf()
00524 //
00525 // Draw a polyline in the current color.
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 // plD_eop_psttf()
00539 //
00540 // End of page.
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 // plD_bop_psttf()
00552 //
00553 // Set up for the next page.
00554 // Advance to next family file if necessary (file output).
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 // This ensures the color and line width are set correctly at the beginning of
00594 //   each page
00595 
00596     plD_state_psttf( pls, PLSTATE_COLOR0 );
00597     plD_state_psttf( pls, PLSTATE_WIDTH );
00598 }
00599 
00600 //--------------------------------------------------------------------------
00601 // plD_tidy_psttf()
00602 //
00603 // Close graphics file or otherwise clean up.
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 // changed for correct Bounding boundaries Jan Thorbecke  okt 1993
00622 // occurs from the integer truncation -- postscript uses fp arithmetic
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 // Now write the rest of the header
00635     writeHeader( pls );
00636 
00637 // Write out postscript document to file and close
00638     // For C++ stream we first need to close the file using
00639 //       the C FILE * handle, then reopen as a ofstream. Yuck!
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 // plD_state_psttf()
00659 //
00660 // Handle change in PLStream state (color, pen width, fill attribute, etc).
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     // else fallthrough
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 // Reinitialize current point location.
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 // plD_esc_psttf()
00716 //
00717 // Escape function.
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 // fill_polygon()
00736 //
00737 // Fill polygon described in points pls->dev_x[] and pls->dev_y[].
00738 // Only solid color fill supported.
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 // Rotate by 90 degrees
00757 
00758         plRotPhy( ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax, &x, &y );
00759 
00760 // First time through start with a x y moveto
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 // ps_getdate()
00801 //
00802 // Get the date and time
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';      // zap the newline character
00816     return p;
00817 }
00818 
00819 // 0.8 should mimic the offset of first superscript/subscript level
00820 // implemented in plstr (plsym.c) for Hershey fonts.  However, when
00821 // comparing with -dev xwin and -dev xcairo results changing this
00822 // factor to 0.6 appears to offset the centers of the letters
00823 // appropriately while 0.8 gives much poorer agreement with the
00824 // other devices.
00825 # define RISE_FACTOR    0.6
00826 
00827 //--------------------------------------------------------------------------
00828 // proc_str()
00829 //
00830 // Prints postscript strings.
00831 // N.B. Now unicode only, no string access!
00832 //
00833 //--------------------------------------------------------------------------
00834 
00835 void
00836 proc_str( PLStream *pls, EscText *args )
00837 {
00838     PLFLT *t = args->xform, tt[4];              // Transform matrices
00839     PLFLT theta, shear, stride;                 // Rotation angle and shear from the matrix
00840     PLFLT ft_ht, offset;                        // Font height and 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     // Be generous.  Used to store lots of font changes which take
00848     // 3 characters per change.
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; // Clip limits
00854     PLINT   clipx[4], clipy[4];             // Current clip limits
00855 
00856     PLFLT   scale = 1., up = 0.;            // Font scaling and shifting parameters
00857 
00858     double  lineSpacing, xAdvance, ymintmp, ymaxtmp, ymin, ymax, xmin, xmax;
00859     PLINT   xx[4], yy[4];
00860 
00861     FT_Data *FT;
00862 
00863     // unicode only! so test for it.
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         // translate from unicode into type 1 font index.
00878         //
00879         // Choose the font family, style, variant, and weight using
00880         // the FCI (font characterization integer).
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         // Need to add some error checking here
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         //pldebug("proc_str", "fci = 0x%x, font name = %s\n", fci, font);
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                 // process an FCI by saving it and escaping cur_str
00906                 // with an escff to make it a 2-character escape
00907                 // that is not used in legacy Hershey code
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                     //pldebug("proc_str", "string-supplied FCI = 0x%x, font name = %s\n", cur_text[j], fonts[f]);
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                 //pldebug("proc_str", "unicode = 0x%x, type 1 code = %d\n",
00934 //                          cur_text[j], cur_str[j]);
00935             }
00936         }
00937         cur_str[s] = '\0';
00938 
00939         // finish previous polyline
00940 
00941         dev->xold = PL_UNDEFINED;
00942         dev->yold = PL_UNDEFINED;
00943 
00944         // Determine the font height
00945         ft_ht = pls->chrht * 72.0 / 25.4; // ft_ht in points, ht is in mm
00946 
00947 
00948         // The transform matrix has only rotations and shears; extract them
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         // Reference point conventions:
00959         //   If base = 0, it is aligned with the center of the text box
00960         //   If base = 1, it is aligned with the baseline of the text box
00961         //   If base = 2, it is aligned with the top of the text box
00962         //
00963         // Currently plplot only uses base=0
00964         // Postscript uses base=1
00965         //
00966         // We must calculate the difference between the two and apply the offset.
00967         //
00968 
00969         if ( args->base == 2 )             // not supported by plplot
00970             offset = ENLARGE * ft_ht / 2.; // half font height
00971         else if ( args->base == 1 )
00972             offset = 0.;
00973         else
00974             offset = -ENLARGE * ft_ht / 2.;
00975 
00976         // Determine the adjustment for page orientation
00977         theta   -= PI / 2. * pls->diorot;
00978         args->y += (int) ( offset * cos( theta ) );
00979         args->x -= (int) ( offset * sin( theta ) );
00980 
00981         // ps driver is rotated by default
00982         plRotPhy( ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax,
00983             &( args->x ), &( args->y ) );
00984 
00985         // Correct for the fact ps driver uses landscape by default
00986         theta += PI / 2.;
00987 
00988         // Output
00989         // Set clipping
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         // move to string reference point
01012         doc->osBody() << " " << args->x << " " << args->y << " M\n";
01013 
01014         // Save the current position and set the string rotation
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         // Dummy run through the string first to work out the
01022         // length, including any font changes
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 ) // <esc><esc>
01034                 {
01035                     *strp++ = *cur_strp++;
01036                 }
01037                 else if ( *cur_strp == 'f' )
01038                 {
01039                     cur_strp++;
01040                     if ( *cur_strp++ != 'f' )
01041                     {
01042                         // escff occurs because of logic above. But any suffix
01043                         // other than "f" should never happen.
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': //subscript
01058                     case 'D':
01059                         plP_script_scale( FALSE, &level,
01060                             &old_sscale, &sscale, &old_soffset, &soffset );
01061                         scale = sscale;
01062                         // The correction for the difference in magnitude
01063                         // between the baseline and middle coordinate systems
01064                         // for subscripts should be
01065                         // -0.5*(base font size - superscript/subscript font size).
01066                         dup = -0.5 * ( 1.0 - sscale );
01067                         up  = -font_factor * ENLARGE * ft_ht * ( RISE_FACTOR * soffset + dup );
01068                         break;
01069 
01070                     case 'u': //superscript
01071                     case 'U':
01072                         plP_script_scale( TRUE, &level,
01073                             &old_sscale, &sscale, &old_soffset, &soffset );
01074                         scale = sscale;
01075                         // The correction for the difference in magnitude
01076                         // between the baseline and middle coordinate systems
01077                         // for superscripts should be
01078                         // 0.5*(base font size - superscript/subscript font size).
01079                         dup = 0.5 * ( 1.0 - sscale );
01080                         up  = font_factor * ENLARGE * ft_ht * ( RISE_FACTOR * soffset + dup );
01081                         break;
01082 
01083                     // ignore the next sequences
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             // copy from current to next token, adding a postscript escape
01095             // char '\' if necessary
01096             //
01097             while ( *cur_strp && *cur_strp != esc )
01098             {
01099                 *strp++ = *cur_strp++;
01100             }
01101             *strp = '\0';
01102 
01103             //     if(fabs(up)<0.001) up = 0.; /* Watch out for small differences */
01104 
01105             // Set the font size
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         // Use the length of the string to calculate offset
01113         // Also used later for bounding box
01114         xmin = -xmax * args->just;
01115         xmax = xmin;
01116         ymin = 0;
01117         ymax = 0;
01118 
01119         // Reset parameters
01120         level = 0;
01121         scale = 1.0;
01122         up    = 0.0;
01123 
01124         // Move relative to position to account for justification
01125         doc->osBody() << " gsave " << TRMFLT( xmin * tt[0] ) << " " <<
01126         TRMFLT( xmin * tt[2] ) << " rmoveto\n";
01127 
01128         // Parse string for PLplot escape sequences and print everything out
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 ) // <esc><esc>
01141                 {
01142                     *strp++ = *cur_strp++;
01143                 }
01144                 else if ( *cur_strp == 'f' )
01145                 {
01146                     cur_strp++;
01147                     if ( *cur_strp++ != 'f' )
01148                     {
01149                         // escff occurs because of logic above. But any suffix
01150                         // other than "f" should never happen.
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                     //pldebug("proc_str", "string-specified fci = 0x%x, font name = %s\n", fci, font);
01160                     continue;
01161                 }
01162                 else
01163                     switch ( *cur_strp++ )
01164                     {
01165                     case 'd': //subscript
01166                     case 'D':
01167                         plP_script_scale( FALSE, &level,
01168                             &old_sscale, &sscale, &old_soffset, &soffset );
01169                         scale = sscale;
01170                         // The correction for the difference in magnitude
01171                         // between the baseline and middle coordinate systems
01172                         // for subscripts should be
01173                         // -0.5*(base font size - superscript/subscript font size).
01174                         dup = -0.5 * ( 1.0 - sscale );
01175                         up  = -font_factor * ENLARGE * ft_ht * ( RISE_FACTOR * soffset + dup );
01176                         break;
01177 
01178                     case 'u': //superscript
01179                     case 'U':
01180                         plP_script_scale( TRUE, &level,
01181                             &old_sscale, &sscale, &old_soffset, &soffset );
01182                         scale = sscale;
01183                         // The correction for the difference in magnitude
01184                         // between the baseline and middle coordinate systems
01185                         // for superscripts should be
01186                         // 0.5*(base font size - superscript/subscript font size).
01187                         dup = 0.5 * ( 1.0 - sscale );
01188                         up  = font_factor * ENLARGE * ft_ht * ( RISE_FACTOR * soffset + dup );
01189                         break;
01190 
01191                     // ignore the next sequences
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             // copy from current to next token, adding a postscript escape
01203             // char '\' if necessary
01204             //
01205             while ( *cur_strp && *cur_strp != esc )
01206             {
01207                 *strp++ = *cur_strp++;
01208             }
01209             *strp = '\0';
01210 
01211             //     if(fabs(up)<0.001) up = 0.; /* Watch out for small differences */
01212 
01213             // Set the font size
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             // if up/down escape sequences, save current point and adjust baseline;
01222             // take the shear into account
01223             if ( up != 0. )
01224                 doc->osBody() << "gsave " << TRMFLT( up * tt[1] ) << " " << TRMFLT( up * tt[3] ) << " rmoveto\n";
01225 
01226             // print the string
01227             doc->osBody() << show( (const char *) str );
01228 
01229             // back to baseline
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         // Estimate text bounding box from LASi get_dimensions function.
01240         // xmin, xmax are text left and right extents,
01241         // ymin, ymax are top and bottom extents.
01242         // These need to be rotated / transformed to get the correct values
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 //      doc->osBody() << "Z " << xmin << " " << ymin << " M "
01269 //                    << xmin << " " << ymax << " D "
01270 //                    << xmax << " " << ymax << " D "
01271 //                    << xmax << " " << ymin << " D "
01272 //                    << xmin << " " << ymin << " closepath\n"
01273 //                    << "Z " << args->x << " " << args->y << " A closepath\n";
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; // two chars sequence
01306 
01307             default:
01308                 break; // single char escape
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) || ....

Generated on Wed Oct 12 2011 20:42:23 for PLplot by  doxygen 1.7.1