PLplot
5.10.0
|
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) || ....