PLplot
5.10.0
|
00001 // Misc. control routines, like begin, end, exit, change graphics/text 00002 // mode, change color. Includes some spillage from plcore.c. If you 00003 // don't know where it should go, put it here. 00004 // 00005 // Copyright (C) 2004 Joao Cardoso 00006 // Copyright (C) 2004 Rafael Laboissiere 00007 // Copyright (C) 2008 Hazen Babcock 00008 // Copyright (C) 2009-2014 Alan W. Irwin 00009 // Copyright (C) 2011 Hezekiah M. Carty 00010 // 00011 // This file is part of PLplot. 00012 // 00013 // PLplot is free software; you can redistribute it and/or modify 00014 // it under the terms of the GNU Library General Public License as published 00015 // by the Free Software Foundation; either version 2 of the License, or 00016 // (at your option) any later version. 00017 // 00018 // PLplot is distributed in the hope that it will be useful, 00019 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00020 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00021 // GNU Library General Public License for more details. 00022 // 00023 // You should have received a copy of the GNU Library General Public License 00024 // along with PLplot; if not, write to the Free Software 00025 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00026 // 00027 // 00028 00034 00035 #define DEBUG 00036 00037 #define NEED_PLDEBUG 00038 #include "plplotP.h" 00039 #ifdef macintosh 00040 #include "mac.h" 00041 // for plMacLibOpen prototype; used in plLibOpen 00042 #endif 00043 00044 #ifdef DJGPP // dos386/djgpp 00045 #ifdef __unix 00046 #undef __unix 00047 #endif 00048 #endif 00049 00050 #ifdef __unix 00051 #include <sys/types.h> 00052 #include <sys/stat.h> 00053 #ifdef PL_HAVE_UNISTD_H 00054 #include <unistd.h> 00055 #endif 00056 #include <errno.h> 00057 #endif 00058 00059 // Random number generator (Mersenne Twister) 00060 #include "mt19937ar.h" 00061 00062 #define BUFFER_SIZE 256 00063 #define COLLEN 30 00064 #define PALLEN 160 00065 #define MSGLEN 1024 00066 00067 // small epsilon for fuzzy range checks that is still large enough to 00068 // work even in the single precision floating point case. 00069 #define FUZZ_EPSILON 1.e-4 00070 00071 // Static functions 00072 00073 // Used by any external init code to suggest a path 00074 char PLDLLIMPEXP * plplotLibDir = 0; 00075 00076 static void 00077 color_set( PLINT i, U_CHAR r, U_CHAR g, U_CHAR b, PLFLT a, const char *name ); 00078 00079 static void 00080 strcat_delim( char *dirspec ); 00081 00082 static int 00083 ( *exit_handler )( const char *errormsg ); 00084 00085 static void 00086 ( *abort_handler )( const char *errormsg ); 00087 00088 static void 00089 plcmap0_def( int imin, int imax ); 00090 00091 static void 00092 plcmap1_def( void ); 00093 00094 static PLFLT 00095 value( double n1, double n2, double hue ); 00096 00097 static char * 00098 read_line( char *buffer, int length, FILE *fp ); 00099 00100 static void 00101 cmap0_palette_read( const char *filename, 00102 int *number_colors, unsigned int **r, unsigned int **g, 00103 unsigned int **b, double **a ); 00104 00105 // An additional hardwired location for lib files. 00106 // I have no plans to change these again, ever. 00107 00108 #if defined ( DJGPP ) 00109 #ifndef PLLIBDEV 00110 #define PLLIBDEV "c:/plplot/lib" 00111 #endif 00112 00113 #elif defined ( MSDOS ) 00114 #ifndef PLLIBDEV 00115 #define PLLIBDEV "c:\\plplot\\lib" 00116 #endif 00117 00118 #else 00119 00120 // Anything else is assumed to be Unix 00121 00122 #ifndef PLLIBDEV 00123 #define PLLIBDEV "/usr/local/plplot/lib" 00124 #endif 00125 00126 #endif 00127 00128 //-------------------------------------------------------------------------- 00129 // Routines that deal with colors & color maps. 00130 //-------------------------------------------------------------------------- 00131 00132 //-------------------------------------------------------------------------- 00133 // plcol0() 00134 // 00139 00140 void 00141 c_plcol0( PLINT icol0 ) 00142 { 00143 if ( plsc->level < 1 ) 00144 { 00145 plabort( "plcol0: Please call plinit first" ); 00146 return; 00147 } 00148 if ( icol0 < 0 || icol0 >= plsc->ncol0 ) 00149 { 00150 char buffer[BUFFER_SIZE]; 00151 snprintf( buffer, BUFFER_SIZE, "plcol0: Invalid color map entry: %d", (int) icol0 ); 00152 plabort( buffer ); 00153 return; 00154 } 00155 00156 plsc->icol0 = icol0; 00157 plsc->curcolor.r = plsc->cmap0[icol0].r; 00158 plsc->curcolor.g = plsc->cmap0[icol0].g; 00159 plsc->curcolor.b = plsc->cmap0[icol0].b; 00160 plsc->curcolor.a = plsc->cmap0[icol0].a; 00161 00162 plsc->curcmap = 0; 00163 plP_state( PLSTATE_COLOR0 ); 00164 } 00165 00166 //-------------------------------------------------------------------------- 00167 // plcol1() 00168 // 00173 00174 void 00175 c_plcol1( PLFLT col1 ) 00176 { 00177 PLINT icol1; 00178 00179 if ( plsc->level < 1 ) 00180 { 00181 plabort( "plcol1: Please call plinit first" ); 00182 return; 00183 } 00184 if ( col1 < 0 || col1 > 1 || isnan( col1 ) ) 00185 { 00186 char buffer[BUFFER_SIZE]; 00187 snprintf( buffer, BUFFER_SIZE, "plcol1: Invalid color map position: %f", (PLFLT) col1 ); 00188 plabort( buffer ); 00189 return; 00190 } 00191 00192 icol1 = (PLINT) ( col1 * plsc->ncol1 ); 00193 icol1 = MIN( icol1, plsc->ncol1 - 1 ); 00194 00195 plsc->icol1 = icol1; 00196 plsc->curcolor.r = plsc->cmap1[plsc->icol1].r; 00197 plsc->curcolor.g = plsc->cmap1[plsc->icol1].g; 00198 plsc->curcolor.b = plsc->cmap1[plsc->icol1].b; 00199 plsc->curcolor.a = plsc->cmap1[plsc->icol1].a; 00200 00201 plsc->curcmap = 1; 00202 plP_state( PLSTATE_COLOR1 ); 00203 } 00204 00205 //-------------------------------------------------------------------------- 00206 // plscolbg() 00207 // 00213 00214 void 00215 c_plscolbg( PLINT r, PLINT g, PLINT b ) 00216 { 00217 plscol0( 0, r, g, b ); 00218 } 00219 00220 //-------------------------------------------------------------------------- 00221 // plscolbga() 00222 // 00230 00231 //-------------------------------------------------------------------------- 00232 00233 void 00234 c_plscolbga( PLINT r, PLINT g, PLINT b, PLFLT alpha ) 00235 { 00236 plscol0a( 0, r, g, b, alpha ); 00237 } 00238 00239 //-------------------------------------------------------------------------- 00240 // plgcolbg() 00241 // 00247 00248 void 00249 c_plgcolbg( PLINT *r, PLINT *g, PLINT *b ) 00250 { 00251 plgcol0( 0, r, g, b ); 00252 } 00253 00254 //-------------------------------------------------------------------------- 00255 // plgcolbga() 00256 // 00263 00264 void 00265 c_plgcolbga( PLINT *r, PLINT *g, PLINT *b, PLFLT *alpha ) 00266 { 00267 plgcol0a( 0, r, g, b, alpha ); 00268 } 00269 00270 //-------------------------------------------------------------------------- 00271 // plscol0() 00272 // 00280 00281 void 00282 c_plscol0( PLINT icol0, PLINT r, PLINT g, PLINT b ) 00283 { 00284 if ( plsc->cmap0 == NULL ) 00285 plscmap0n( 0 ); 00286 if ( icol0 < 0 || icol0 >= plsc->ncol0 ) 00287 { 00288 char buffer[BUFFER_SIZE]; 00289 snprintf( buffer, BUFFER_SIZE, "plscol0: Illegal color table value: %d", (int) icol0 ); 00290 plabort( buffer ); 00291 return; 00292 } 00293 if ( ( r < 0 || r > 255 ) || ( g < 0 || g > 255 ) || ( b < 0 || b > 255 ) ) 00294 { 00295 char buffer[BUFFER_SIZE]; 00296 snprintf( buffer, BUFFER_SIZE, "plscol0: Invalid RGB color: %d, %d, %d", 00297 (int) r, (int) g, (int) b ); 00298 plabort( buffer ); 00299 return; 00300 } 00301 00302 plscol0a( icol0, r, g, b, 1.0 ); 00303 } 00304 00305 //-------------------------------------------------------------------------- 00306 // plscol0a() 00307 // 00316 00317 void 00318 c_plscol0a( PLINT icol0, PLINT r, PLINT g, PLINT b, PLFLT alpha ) 00319 { 00320 if ( plsc->cmap0 == NULL ) 00321 plscmap0n( 0 ); 00322 if ( icol0 < 0 || icol0 >= plsc->ncol0 ) 00323 { 00324 char buffer[BUFFER_SIZE]; 00325 snprintf( buffer, BUFFER_SIZE, "plscol0a: Illegal color table value: %d", (int) icol0 ); 00326 plabort( buffer ); 00327 return; 00328 } 00329 if ( ( r < 0 || r > 255 ) || ( g < 0 || g > 255 ) || ( b < 0 || b > 255 ) || ( alpha < 0. || alpha > 1.0 ) ) 00330 { 00331 char buffer[BUFFER_SIZE]; 00332 snprintf( buffer, BUFFER_SIZE, "plscol0a: Invalid RGB color: %d, %d, %d, %f", 00333 (int) r, (int) g, (int) b, (double) alpha ); 00334 plabort( buffer ); 00335 return; 00336 } 00337 00338 plsc->cmap0[icol0].r = (unsigned char) r; 00339 plsc->cmap0[icol0].g = (unsigned char) g; 00340 plsc->cmap0[icol0].b = (unsigned char) b; 00341 plsc->cmap0[icol0].a = alpha; 00342 00343 if ( plsc->level > 0 ) 00344 plP_state( PLSTATE_CMAP0 ); 00345 } 00346 00347 //-------------------------------------------------------------------------- 00348 // plgcol0() 00349 // 00357 00358 void 00359 c_plgcol0( PLINT icol0, PLINT *r, PLINT *g, PLINT *b ) 00360 { 00361 if ( plsc->cmap0 == NULL ) 00362 plscmap0n( 0 ); 00363 00364 *r = -1; 00365 *g = -1; 00366 *b = -1; 00367 00368 if ( icol0 < 0 || icol0 > plsc->ncol0 ) 00369 { 00370 char buffer[BUFFER_SIZE]; 00371 snprintf( buffer, BUFFER_SIZE, "plgcol0: Invalid color index: %d", (int) icol0 ); 00372 plabort( buffer ); 00373 return; 00374 } 00375 00376 *r = plsc->cmap0[icol0].r; 00377 *g = plsc->cmap0[icol0].g; 00378 *b = plsc->cmap0[icol0].b; 00379 00380 return; 00381 } 00382 00383 //-------------------------------------------------------------------------- 00384 // plgcol0a() 00385 // 00394 00395 void 00396 c_plgcol0a( PLINT icol0, PLINT *r, PLINT *g, PLINT *b, PLFLT *alpha ) 00397 { 00398 if ( plsc->cmap0 == NULL ) 00399 plscmap0n( 0 ); 00400 00401 *r = -1; 00402 *g = -1; 00403 *b = -1; 00404 *alpha = -1.0; 00405 00406 if ( icol0 < 0 || icol0 > plsc->ncol0 ) 00407 { 00408 char buffer[BUFFER_SIZE]; 00409 snprintf( buffer, BUFFER_SIZE, "plgcol0: Invalid color index: %d", (int) icol0 ); 00410 plabort( buffer ); 00411 return; 00412 } 00413 00414 *r = plsc->cmap0[icol0].r; 00415 *g = plsc->cmap0[icol0].g; 00416 *b = plsc->cmap0[icol0].b; 00417 *alpha = plsc->cmap0[icol0].a; 00418 00419 return; 00420 } 00421 00422 //-------------------------------------------------------------------------- 00423 // plscmap0() 00424 // 00432 00433 void 00434 c_plscmap0( const PLINT *r, const PLINT *g, const PLINT *b, PLINT ncol0 ) 00435 { 00436 int i; 00437 00438 plscmap0n( ncol0 ); 00439 00440 for ( i = 0; i < plsc->ncol0; i++ ) 00441 { 00442 if ( ( r[i] < 0 || r[i] > 255 ) || 00443 ( g[i] < 0 || g[i] > 255 ) || 00444 ( b[i] < 0 || b[i] > 255 ) ) 00445 { 00446 char buffer[BUFFER_SIZE]; 00447 snprintf( buffer, BUFFER_SIZE, "plscmap0: Invalid RGB color: %d, %d, %d", 00448 (int) r[i], (int) g[i], (int) b[i] ); 00449 plabort( buffer ); 00450 return; 00451 } 00452 00453 plsc->cmap0[i].r = (unsigned char) r[i]; 00454 plsc->cmap0[i].g = (unsigned char) g[i]; 00455 plsc->cmap0[i].b = (unsigned char) b[i]; 00456 plsc->cmap0[i].a = 1.0; 00457 } 00458 00459 if ( plsc->level > 0 ) 00460 plP_state( PLSTATE_CMAP0 ); 00461 } 00462 00463 //-------------------------------------------------------------------------- 00464 // plscmap0a() 00465 // 00474 00475 void 00476 c_plscmap0a( const PLINT *r, const PLINT *g, const PLINT *b, const PLFLT *alpha, PLINT ncol0 ) 00477 { 00478 int i; 00479 00480 plscmap0n( ncol0 ); 00481 00482 for ( i = 0; i < plsc->ncol0; i++ ) 00483 { 00484 if ( ( r[i] < 0 || r[i] > 255 ) || 00485 ( g[i] < 0 || g[i] > 255 ) || 00486 ( b[i] < 0 || b[i] > 255 ) || 00487 ( alpha[i] < 0.0 || alpha[i] > 1.0 ) ) 00488 { 00489 char buffer[BUFFER_SIZE]; 00490 snprintf( buffer, BUFFER_SIZE, "plscmap0a: Invalid RGB color: %d, %d, %d, %f", 00491 (int) r[i], (int) g[i], (int) b[i], (double) alpha[i] ); 00492 plabort( buffer ); 00493 return; 00494 } 00495 00496 plsc->cmap0[i].r = (unsigned char) r[i]; 00497 plsc->cmap0[i].g = (unsigned char) g[i]; 00498 plsc->cmap0[i].b = (unsigned char) b[i]; 00499 plsc->cmap0[i].a = alpha[i]; 00500 } 00501 00502 if ( plsc->level > 0 ) 00503 plP_state( PLSTATE_CMAP0 ); 00504 } 00505 00506 //-------------------------------------------------------------------------- 00507 // plscmap1() 00508 // 00516 00517 void 00518 c_plscmap1( const PLINT *r, const PLINT *g, const PLINT *b, PLINT ncol1 ) 00519 { 00520 int i; 00521 00522 plscmap1n( ncol1 ); 00523 00524 for ( i = 0; i < plsc->ncol1; i++ ) 00525 { 00526 if ( ( r[i] < 0 || r[i] > 255 ) || 00527 ( g[i] < 0 || g[i] > 255 ) || 00528 ( b[i] < 0 || b[i] > 255 ) ) 00529 { 00530 char buffer[BUFFER_SIZE]; 00531 snprintf( buffer, BUFFER_SIZE, "plscmap1: Invalid RGB color: %d, %d, %d", 00532 (int) r[i], (int) g[i], (int) b[i] ); 00533 plabort( buffer ); 00534 return; 00535 } 00536 plsc->cmap1[i].r = (unsigned char) r[i]; 00537 plsc->cmap1[i].g = (unsigned char) g[i]; 00538 plsc->cmap1[i].b = (unsigned char) b[i]; 00539 plsc->cmap1[i].a = 1.0; 00540 } 00541 00542 if ( plsc->level > 0 ) 00543 plP_state( PLSTATE_CMAP1 ); 00544 } 00545 00546 //-------------------------------------------------------------------------- 00547 // plscmap1a() 00548 // 00557 00558 void 00559 c_plscmap1a( const PLINT *r, const PLINT *g, const PLINT *b, const PLFLT *alpha, PLINT ncol1 ) 00560 { 00561 int i; 00562 00563 plscmap1n( ncol1 ); 00564 00565 for ( i = 0; i < plsc->ncol1; i++ ) 00566 { 00567 if ( ( r[i] < 0 || r[i] > 255 ) || 00568 ( g[i] < 0 || g[i] > 255 ) || 00569 ( b[i] < 0 || b[i] > 255 ) || 00570 ( alpha[i] < 0.0 || alpha[i] > 1.0 ) ) 00571 { 00572 char buffer[BUFFER_SIZE]; 00573 snprintf( buffer, BUFFER_SIZE, "plscmap1a: Invalid RGB color: %d, %d, %d, %f", 00574 (int) r[i], (int) g[i], (int) b[i], (double) alpha[i] ); 00575 plabort( buffer ); 00576 return; 00577 } 00578 plsc->cmap1[i].r = (unsigned char) r[i]; 00579 plsc->cmap1[i].g = (unsigned char) g[i]; 00580 plsc->cmap1[i].b = (unsigned char) b[i]; 00581 plsc->cmap1[i].a = alpha[i]; 00582 } 00583 00584 if ( plsc->level > 0 ) 00585 plP_state( PLSTATE_CMAP1 ); 00586 } 00587 00588 //-------------------------------------------------------------------------- 00589 // plscmap1l() 00590 // 00639 00640 void 00641 c_plscmap1l( PLINT itype, PLINT npts, const PLFLT *intensity, 00642 const PLFLT *coord1, const PLFLT *coord2, const PLFLT *coord3, const PLINT *alt_hue_path ) 00643 { 00644 int n; 00645 PLFLT h, l, s, r, g, b; 00646 00647 if ( npts < 2 ) 00648 { 00649 plabort( "plscmap1l: Must specify at least two control points" ); 00650 return; 00651 } 00652 00653 if ( ( intensity[0] != 0 ) || ( intensity[npts - 1] != 1 ) ) 00654 { 00655 plabort( "plscmap1l: First, last control points must lie on boundary" ); 00656 return; 00657 } 00658 00659 if ( npts > PL_MAX_CMAP1CP ) 00660 { 00661 plabort( "plscmap1l: exceeded maximum number of control points" ); 00662 return; 00663 } 00664 00665 // Allocate if not done yet 00666 00667 if ( plsc->cmap1 == NULL ) 00668 plscmap1n( 0 ); 00669 00670 // Save control points 00671 00672 plsc->ncp1 = npts; 00673 00674 for ( n = 0; n < npts; n++ ) 00675 { 00676 if ( itype == 0 ) 00677 { 00678 h = coord1[n]; 00679 l = coord2[n]; 00680 s = coord3[n]; 00681 } 00682 else 00683 { 00684 r = coord1[n]; 00685 g = coord2[n]; 00686 b = coord3[n]; 00687 c_plrgbhls( r, g, b, &h, &l, &s ); 00688 } 00689 00690 plsc->cmap1cp[n].h = h; 00691 plsc->cmap1cp[n].l = l; 00692 plsc->cmap1cp[n].s = s; 00693 plsc->cmap1cp[n].p = intensity[n]; 00694 plsc->cmap1cp[n].a = 1.0; 00695 00696 if ( alt_hue_path == NULL ) 00697 plsc->cmap1cp[n].alt_hue_path = 0; 00698 else 00699 if ( n != npts - 1 ) 00700 plsc->cmap1cp[n].alt_hue_path = alt_hue_path[n]; 00701 else 00702 // Note final element is unused, so we set to zero for completeness. 00703 plsc->cmap1cp[n].alt_hue_path = 0; 00704 } 00705 00706 // Calculate and set color map 00707 00708 plcmap1_calc(); 00709 } 00710 00711 //-------------------------------------------------------------------------- 00712 // plscmap1la() 00713 // 00725 00726 void 00727 c_plscmap1la( PLINT itype, PLINT npts, const PLFLT *intensity, 00728 const PLFLT *coord1, const PLFLT *coord2, const PLFLT *coord3, const PLFLT *alpha, const PLINT *alt_hue_path ) 00729 { 00730 int n; 00731 PLFLT h, l, s, r, g, b; 00732 00733 if ( npts < 2 ) 00734 { 00735 plabort( "plscmap1la: Must specify at least two control points" ); 00736 return; 00737 } 00738 00739 if ( ( intensity[0] != 0 ) || ( intensity[npts - 1] != 1 ) ) 00740 { 00741 plabort( "plscmap1la: First, last control points must lie on boundary" ); 00742 return; 00743 } 00744 00745 if ( npts > PL_MAX_CMAP1CP ) 00746 { 00747 plabort( "plscmap1la: exceeded maximum number of control points" ); 00748 return; 00749 } 00750 00751 // Allocate if not done yet 00752 00753 if ( plsc->cmap1 == NULL ) 00754 plscmap1n( 0 ); 00755 00756 // Save control points 00757 00758 plsc->ncp1 = npts; 00759 00760 for ( n = 0; n < npts; n++ ) 00761 { 00762 if ( itype == 0 ) 00763 { 00764 h = coord1[n]; 00765 l = coord2[n]; 00766 s = coord3[n]; 00767 } 00768 else 00769 { 00770 r = coord1[n]; 00771 g = coord2[n]; 00772 b = coord3[n]; 00773 c_plrgbhls( r, g, b, &h, &l, &s ); 00774 } 00775 00776 plsc->cmap1cp[n].h = h; 00777 plsc->cmap1cp[n].l = l; 00778 plsc->cmap1cp[n].s = s; 00779 plsc->cmap1cp[n].p = intensity[n]; 00780 plsc->cmap1cp[n].a = alpha[n]; 00781 00782 if ( alt_hue_path == NULL ) 00783 plsc->cmap1cp[n].alt_hue_path = 0; 00784 else 00785 if ( n != npts - 1 ) 00786 plsc->cmap1cp[n].alt_hue_path = alt_hue_path[n]; 00787 else 00788 // Note final element is unused, so we set to zero for completeness. 00789 plsc->cmap1cp[n].alt_hue_path = 0; 00790 } 00791 00792 // Calculate and set color map 00793 00794 plcmap1_calc(); 00795 } 00796 00797 //-------------------------------------------------------------------------- 00798 // plcmap1_calc() 00799 // 00802 00803 void 00804 plcmap1_calc( void ) 00805 { 00806 int i, n; 00807 PLFLT delta, dp, dh, dl, ds, da; 00808 PLFLT h, l, s, p, r, g, b, a; 00809 00810 // Loop over all control point pairs 00811 00812 for ( n = 0; n < plsc->ncp1 - 1; n++ ) 00813 { 00814 if ( plsc->cmap1cp[n].p == plsc->cmap1cp[n + 1].p ) 00815 continue; 00816 00817 // Differences in p, h, l, s between ctrl pts 00818 00819 dp = plsc->cmap1cp[n + 1].p - plsc->cmap1cp[n].p; 00820 dh = plsc->cmap1cp[n + 1].h - plsc->cmap1cp[n].h; 00821 dl = plsc->cmap1cp[n + 1].l - plsc->cmap1cp[n].l; 00822 ds = plsc->cmap1cp[n + 1].s - plsc->cmap1cp[n].s; 00823 da = plsc->cmap1cp[n + 1].a - plsc->cmap1cp[n].a; 00824 00825 // Adjust dh if we are to go around "the back side" 00826 00827 if ( plsc->cmap1cp[n].alt_hue_path ) 00828 dh = ( dh > 0 ) ? dh - 360 : dh + 360; 00829 00830 // Loop over all color cells. Only interested in cells located (in 00831 // cmap1 space) between n_th and n+1_th control points 00832 00833 for ( i = 0; i < plsc->ncol1; i++ ) 00834 { 00835 p = (double) i / ( plsc->ncol1 - 1.0 ); 00836 if ( ( p < plsc->cmap1cp[n].p ) || 00837 ( p > plsc->cmap1cp[n + 1].p ) ) 00838 continue; 00839 00840 // Interpolate based on position of color cell in cmap1 space 00841 00842 delta = ( p - plsc->cmap1cp[n].p ) / dp; 00843 00844 // Linearly interpolate to get color cell h, l, s values 00845 00846 h = plsc->cmap1cp[n].h + dh * delta; 00847 l = plsc->cmap1cp[n].l + dl * delta; 00848 s = plsc->cmap1cp[n].s + ds * delta; 00849 a = plsc->cmap1cp[n].a + da * delta; 00850 00851 while ( h >= 360. ) 00852 h -= 360.; 00853 00854 while ( h < 0. ) 00855 h += 360.; 00856 00857 c_plhlsrgb( h, l, s, &r, &g, &b ); 00858 00859 plsc->cmap1[i].r = (unsigned char) MAX( 0, MIN( 255, (int) ( 256. * r ) ) ); 00860 plsc->cmap1[i].g = (unsigned char) MAX( 0, MIN( 255, (int) ( 256. * g ) ) ); 00861 plsc->cmap1[i].b = (unsigned char) MAX( 0, MIN( 255, (int) ( 256. * b ) ) ); 00862 plsc->cmap1[i].a = a; 00863 } 00864 } 00865 00866 if ( plsc->level > 0 ) 00867 plP_state( PLSTATE_CMAP1 ); 00868 } 00869 00870 //-------------------------------------------------------------------------- 00882 //-------------------------------------------------------------------------- 00883 00884 void 00885 c_plscmap1_range( PLFLT min_color, PLFLT max_color ) 00886 { 00887 if ( min_color > max_color || max_color < 0.0 || min_color > 1.0 ) 00888 { 00889 plwarn( "plscmap1_range called with invalid color range" ); 00890 return; 00891 } 00892 if ( min_color < 0.0 ) 00893 { 00894 plwarn( "plscmap1_range called with a negative minimum color value" ); 00895 min_color = 0.0; 00896 } 00897 if ( max_color > 1.0 ) 00898 { 00899 plwarn( "plscmap1_range called with an out of range maximum color value" ); 00900 max_color = 1.0; 00901 } 00902 plsc->cmap1_min = min_color; 00903 plsc->cmap1_max = max_color; 00904 } 00905 00906 //-------------------------------------------------------------------------- 00911 //-------------------------------------------------------------------------- 00912 00913 void 00914 c_plgcmap1_range( PLFLT *min_color, PLFLT *max_color ) 00915 { 00916 *min_color = plsc->cmap1_min; 00917 *max_color = plsc->cmap1_max; 00918 } 00919 00920 //-------------------------------------------------------------------------- 00921 // plscmap0n() 00922 // 00930 00931 void 00932 c_plscmap0n( PLINT ncol0 ) 00933 { 00934 int ncol, size, imin, imax; 00935 00936 // No change 00937 00938 if ( ncol0 > 0 && plsc->ncol0 == ncol0 ) 00939 return; 00940 00941 // Handle all possible startup conditions 00942 00943 if ( plsc->ncol0 <= 0 && ncol0 <= 0 ) 00944 ncol = 16; 00945 else if ( ncol0 <= 0 ) 00946 ncol = plsc->ncol0; 00947 else 00948 ncol = ncol0; 00949 00950 imax = ncol - 1; 00951 size = ncol * (int) sizeof ( PLColor ); 00952 00953 // Allocate the space 00954 00955 if ( plsc->cmap0 == NULL ) 00956 { 00957 if ( ( plsc->cmap0 = (PLColor *) calloc( 1, (size_t) size ) ) == NULL ) 00958 { 00959 plexit( "c_plscmap0n: Insufficient memory" ); 00960 } 00961 imin = 0; 00962 } 00963 else 00964 { 00965 if ( ( plsc->cmap0 = (PLColor *) realloc( plsc->cmap0, (size_t) size ) ) == NULL ) 00966 { 00967 plexit( "c_plscmap0n: Insufficient memory" ); 00968 } 00969 imin = plsc->ncol0; 00970 } 00971 00972 // Fill in default entries 00973 00974 plsc->ncol0 = ncol; 00975 plcmap0_def( imin, imax ); 00976 00977 if ( plsc->level > 0 ) 00978 plP_state( PLSTATE_CMAP0 ); 00979 } 00980 00981 //-------------------------------------------------------------------------- 00982 // color_set() 00983 // 00992 00993 void 00994 color_set( PLINT i, U_CHAR r, U_CHAR g, U_CHAR b, PLFLT a, const char *name ) 00995 { 00996 plsc->cmap0[i].r = r; 00997 plsc->cmap0[i].g = g; 00998 plsc->cmap0[i].b = b; 00999 plsc->cmap0[i].a = a; 01000 plsc->cmap0[i].name = name; 01001 } 01002 01003 #define color_def( i, r, g, b, a, n ) \ 01004 if ( i >= imin && i <= imax ) color_set( i, r, g, b, a, n ); 01005 01006 //-------------------------------------------------------------------------- 01007 // plcmap0_def() 01008 // 01014 01015 void 01016 plcmap0_def( int imin, int imax ) 01017 { 01018 int i; 01019 unsigned int *r, *g, *b; 01020 double *a; 01021 int number_colors; 01022 if ( imin <= imax ) 01023 { 01024 cmap0_palette_read( "", &number_colors, &r, &g, &b, &a ); 01025 for ( i = imin; i <= MIN( ( number_colors - 1 ), imax ); i++ ) 01026 color_def( i, (U_CHAR) r[i], (U_CHAR) g[i], (U_CHAR) b[i], a[i], 01027 "colors defined by default cmap0 palette file" ); 01028 free( r ); 01029 free( g ); 01030 free( b ); 01031 free( a ); 01032 } 01033 else 01034 { 01035 number_colors = 0; 01036 } 01037 01038 // Initialize all colours undefined by the default colour palette file 01039 // to opaque red as a warning. 01040 for ( i = MAX( number_colors, imin ); i <= imax; i++ ) 01041 color_def( i, 255, 0, 0, 1.0, 01042 "opaque red colour to mark not defined by palette file" ); 01043 } 01044 01045 //-------------------------------------------------------------------------- 01046 // plscmap1n() 01047 // 01055 01056 void 01057 c_plscmap1n( PLINT ncol1 ) 01058 { 01059 PLINT ncol; 01060 size_t size; 01061 01062 // No change 01063 01064 if ( ncol1 > 0 && plsc->ncol1 == ncol1 ) 01065 return; 01066 01067 // Handle all possible startup conditions 01068 01069 if ( plsc->ncol1 <= 0 && ncol1 <= 0 ) 01070 ncol = 128; 01071 else if ( ncol1 <= 0 ) 01072 ncol = plsc->ncol1; 01073 else 01074 ncol = ncol1; 01075 01076 size = (size_t) ncol * sizeof ( PLColor ); 01077 01078 // Allocate the space 01079 01080 if ( plsc->ncol1 > 0 ) 01081 { 01082 if ( ( plsc->cmap1 = (PLColor *) realloc( plsc->cmap1, size ) ) == NULL ) 01083 { 01084 plexit( "c_plscmap1n: Insufficient memory" ); 01085 } 01086 } 01087 else 01088 { 01089 if ( ( plsc->cmap1 = (PLColor *) calloc( (size_t) ncol, sizeof ( PLColor ) ) ) == NULL ) 01090 { 01091 plexit( "c_plscmap1n: Insufficient memory" ); 01092 } 01093 } 01094 01095 // Fill in default entries 01096 01097 plsc->ncol1 = ncol; 01098 if ( plsc->ncp1 == 0 ) 01099 plcmap1_def(); 01100 else 01101 plcmap1_calc(); 01102 } 01103 01104 //-------------------------------------------------------------------------- 01105 // plcmap1_def() 01106 // 01116 01117 void 01118 plcmap1_def( void ) 01119 { 01120 PLFLT i[6], h[6], l[6], s[6], midpt = 0., vertex = 0.; 01121 01122 // Positions of control points 01123 01124 i[0] = 0; // left boundary 01125 i[1] = 0.44; // a little left of center 01126 i[2] = 0.50; // at center 01127 i[3] = 0.50; // at center 01128 i[4] = 0.56; // a little right of center 01129 i[5] = 1; // right boundary 01130 01131 // For center control points, pick black or white, whichever is closer to bg 01132 // Be careful to pick just short of top or bottom else hue info is lost 01133 01134 if ( plsc->cmap0 != NULL ) 01135 vertex = ( (PLFLT) plsc->cmap0[0].r + 01136 (PLFLT) plsc->cmap0[0].g + 01137 (PLFLT) plsc->cmap0[0].b ) / 3. / 255.; 01138 01139 if ( vertex < 0.5 ) 01140 { 01141 vertex = 0.01; 01142 midpt = 0.10; 01143 } 01144 else 01145 { 01146 vertex = 0.99; 01147 midpt = 0.90; 01148 } 01149 01150 // Set hue 01151 01152 h[0] = 260; // low: blue-violet 01153 h[1] = 260; // only change as we go over vertex 01154 h[2] = 260; // only change as we go over vertex 01155 h[3] = 0; // high: red 01156 h[4] = 0; // high: red 01157 h[5] = 0; // keep fixed 01158 01159 // Set lightness 01160 01161 l[0] = 0.5; // low 01162 l[1] = midpt; // midpoint value 01163 l[2] = vertex; // bg 01164 l[3] = vertex; // bg 01165 l[4] = midpt; // midpoint value 01166 l[5] = 0.5; // high 01167 01168 // Set saturation -- keep at maximum 01169 01170 s[0] = 1; 01171 s[1] = 1; 01172 s[2] = 1; 01173 s[3] = 1; 01174 s[4] = 1; 01175 s[5] = 1; 01176 01177 c_plscmap1l( 0, 6, i, h, l, s, NULL ); 01178 01179 if ( plsc->level > 0 ) 01180 plP_state( PLSTATE_CMAP1 ); 01181 } 01182 01183 //-------------------------------------------------------------------------- 01184 // plscolor() 01185 // 01189 //-------------------------------------------------------------------------- 01190 01191 void 01192 c_plscolor( PLINT color ) 01193 { 01194 plsc->colorset = 1; 01195 plsc->color = color; 01196 } 01197 01198 //-------------------------------------------------------------------------- 01199 // void value() 01200 // 01206 //-------------------------------------------------------------------------- 01207 01208 PLFLT 01209 value( double n1, double n2, double hue ) 01210 { 01211 PLFLT val; 01212 01213 while ( hue >= 360. ) 01214 hue -= 360.; 01215 while ( hue < 0. ) 01216 hue += 360.; 01217 01218 if ( hue < 60. ) 01219 val = n1 + ( n2 - n1 ) * hue / 60.; 01220 else if ( hue < 180. ) 01221 val = n2; 01222 else if ( hue < 240. ) 01223 val = n1 + ( n2 - n1 ) * ( 240. - hue ) / 60.; 01224 else 01225 val = n1; 01226 01227 return ( val ); 01228 } 01229 01230 //-------------------------------------------------------------------------- 01231 // void c_plhlsrgb() 01232 // 01249 01250 void 01251 c_plhlsrgb( PLFLT h, PLFLT l, PLFLT s, PLFLT *p_r, PLFLT *p_g, PLFLT *p_b ) 01252 { 01253 PLFLT m1, m2; 01254 01255 if ( l <= .5 ) 01256 m2 = l * ( s + 1. ); 01257 else 01258 m2 = l + s - l * s; 01259 01260 m1 = 2 * l - m2; 01261 01262 *p_r = value( m1, m2, h + 120. ); 01263 *p_g = value( m1, m2, h ); 01264 *p_b = value( m1, m2, h - 120. ); 01265 } 01266 01267 //-------------------------------------------------------------------------- 01268 // void c_plrgbhls() 01269 // 01282 01283 void 01284 c_plrgbhls( PLFLT r, PLFLT g, PLFLT b, PLFLT *p_h, PLFLT *p_l, PLFLT *p_s ) 01285 { 01286 PLFLT h, l, s, d, rc, gc, bc, rgb_min, rgb_max; 01287 01288 rgb_min = MIN( r, MIN( g, b ) ); 01289 rgb_max = MAX( r, MAX( g, b ) ); 01290 01291 l = ( rgb_min + rgb_max ) / 2.0; 01292 01293 if ( rgb_min == rgb_max ) 01294 { 01295 s = 0; 01296 h = 0; 01297 } 01298 else 01299 { 01300 d = rgb_max - rgb_min; 01301 if ( l < 0.5 ) 01302 s = 0.5 * d / l; 01303 else 01304 s = 0.5 * d / ( 1. - l ); 01305 01306 rc = ( rgb_max - r ) / d; 01307 gc = ( rgb_max - g ) / d; 01308 bc = ( rgb_max - b ) / d; 01309 01310 if ( r == rgb_max ) 01311 h = bc - gc; 01312 else if ( g == rgb_max ) 01313 h = rc - bc + 2; 01314 else 01315 h = gc - rc - 2; 01316 01317 h = h * 60; 01318 if ( h < 0 ) 01319 h = h + 360; 01320 else if ( h >= 360 ) 01321 h = h - 360; 01322 } 01323 *p_h = h; 01324 *p_l = l; 01325 *p_s = s; 01326 } 01327 01328 //-------------------------------------------------------------------------- 01329 // read_line() 01330 // 01340 01341 static char * 01342 read_line( char *buffer, int length, FILE *fp ) 01343 { 01344 char *pchr; 01345 01346 // Read the string 01347 if ( fgets( buffer, length, fp ) == NULL ) 01348 { 01349 return NULL; 01350 } 01351 01352 // Sanitize the string we read - it may contain EOL characters 01353 // Make sure file reading starts at the next line 01354 pchr = strchr( buffer, '\n' ); 01355 if ( pchr != NULL ) 01356 { 01357 *pchr = '\0'; 01358 } 01359 else 01360 { 01361 if ( fscanf( fp, "%*[^\n]\n" ) == EOF && ferror( fp ) ) 01362 { 01363 return NULL; 01364 } 01365 } 01366 01367 01368 pchr = strchr( buffer, '\r' ); 01369 if ( pchr != NULL ) 01370 { 01371 *pchr = '\0'; 01372 } 01373 01374 // Remove trailing blanks 01375 pchr = buffer + strlen( buffer ) - 1; 01376 while ( pchr != buffer && *pchr == ' ' ) 01377 { 01378 *pchr = '\0'; 01379 pchr--; 01380 } 01381 01382 return buffer; 01383 } 01384 01385 //-------------------------------------------------------------------------- 01386 // cmap0_palette_read() 01387 // 01397 01398 void 01399 cmap0_palette_read( const char *filename, 01400 int *number_colors, unsigned int **r, unsigned int **g, unsigned int **b, double **a ) 01401 { 01402 int i, err = 0; 01403 char color_info[COLLEN]; 01404 char msgbuf[MSGLEN]; 01405 FILE *fp; 01406 char * save_locale = plsave_set_locale(); 01407 01408 if ( strlen( filename ) == 0 ) 01409 { 01410 fp = plLibOpen( PL_DEFAULT_CMAP0_FILE ); 01411 if ( fp == NULL ) 01412 { 01413 snprintf( msgbuf, MSGLEN, "Unable to open cmap0 file %s\n", PL_DEFAULT_CMAP0_FILE ); 01414 plwarn( msgbuf ); 01415 err = 1; 01416 } 01417 } 01418 else 01419 { 01420 fp = plLibOpen( filename ); 01421 if ( fp == NULL ) 01422 { 01423 snprintf( msgbuf, MSGLEN, "Unable to open cmap0 file %s\n", filename ); 01424 plwarn( msgbuf ); 01425 err = 1; 01426 } 01427 } 01428 if ( !err && ( fscanf( fp, "%d\n", number_colors ) != 1 || *number_colors < 1 ) ) 01429 { 01430 fclose( fp ); 01431 snprintf( msgbuf, MSGLEN, "Unrecognized cmap0 header\n" ); 01432 plwarn( msgbuf ); 01433 err = 1; 01434 } 01435 01436 if ( !err ) 01437 { 01438 // Allocate arrays to hold r, g, b, and a data for calling routine. 01439 // The caller must free these after it is finished with them. 01440 if ( ( ( *r = (unsigned int *) malloc( (size_t) ( *number_colors ) * sizeof ( unsigned int ) ) ) == NULL ) || 01441 ( ( *g = (unsigned int *) malloc( (size_t) ( *number_colors ) * sizeof ( unsigned int ) ) ) == NULL ) || 01442 ( ( *b = (unsigned int *) malloc( (size_t) ( *number_colors ) * sizeof ( unsigned int ) ) ) == NULL ) || 01443 ( ( *a = (double *) malloc( (size_t) ( *number_colors ) * sizeof ( double ) ) ) == NULL ) ) 01444 { 01445 fclose( fp ); 01446 plexit( "cmap0_palette_read: insufficient memory" ); 01447 } 01448 01449 for ( i = 0; i < *number_colors; i++ ) 01450 { 01451 if ( read_line( color_info, COLLEN, fp ) == NULL ) 01452 { 01453 err = 1; 01454 break; 01455 } 01456 01457 // Get the color data 01458 if ( strlen( color_info ) == 7 ) 01459 { 01460 if ( sscanf( color_info, "#%2x%2x%2x", 01461 (unsigned int *) ( *r + i ), (unsigned int *) ( *g + i ), 01462 (unsigned int *) ( *b + i ) ) != 3 ) 01463 { 01464 err = 1; 01465 break; 01466 } 01467 *( *a + i ) = 1.0; 01468 } 01469 else if ( strlen( color_info ) > 9 ) 01470 { 01471 if ( sscanf( color_info, "#%2x%2x%2x %lf", 01472 (unsigned int *) ( *r + i ), (unsigned int *) ( *g + i ), 01473 (unsigned int *) ( *b + i ), (double *) ( *a + i ) ) != 4 ) 01474 { 01475 err = 1; 01476 break; 01477 } 01478 // fuzzy range check. 01479 if ( *( *a + i ) < -FUZZ_EPSILON || *( *a + i ) > ( 1. + FUZZ_EPSILON ) ) 01480 { 01481 err = 1; 01482 break; 01483 } 01484 else if ( *( *a + i ) < 0. ) 01485 { 01486 *( *a + i ) = 0.; 01487 } 01488 else if ( *( *a + i ) > 1. ) 01489 { 01490 *( *a + i ) = 1.; 01491 } 01492 } 01493 else 01494 { 01495 err = 1; 01496 break; 01497 } 01498 } 01499 fclose( fp ); 01500 if ( err ) 01501 { 01502 snprintf( msgbuf, MSGLEN, "Unrecognized cmap0 format data line. Line is %s\n", 01503 color_info ); 01504 plwarn( msgbuf ); 01505 free( *r ); 01506 free( *g ); 01507 free( *b ); 01508 free( *a ); 01509 } 01510 } 01511 // Fall back to opaque red on opaque white as visual warning of any 01512 // error above. 01513 if ( err ) 01514 { 01515 *number_colors = 16; 01516 if ( ( ( *r = (unsigned int *) malloc( (size_t) ( *number_colors ) * sizeof ( int ) ) ) == NULL ) || 01517 ( ( *g = (unsigned int *) malloc( (size_t) ( *number_colors ) * sizeof ( unsigned int ) ) ) == NULL ) || 01518 ( ( *b = (unsigned int *) malloc( (size_t) ( *number_colors ) * sizeof ( unsigned int ) ) ) == NULL ) || 01519 ( ( *a = (double *) malloc( (size_t) ( *number_colors ) * sizeof ( double ) ) ) == NULL ) ) 01520 { 01521 plexit( "cmap0_palette_read: insufficient memory" ); 01522 } 01523 **r = 255; 01524 **g = 255; 01525 **b = 255; 01526 **a = 1.; 01527 for ( i = 1; i < *number_colors; i++ ) 01528 { 01529 *( *r + i ) = 255; 01530 *( *g + i ) = 0; 01531 *( *b + i ) = 0; 01532 *( *a + i ) = 1.0; 01533 } 01534 } 01535 01536 plrestore_locale( save_locale ); 01537 } 01538 01539 //-------------------------------------------------------------------------- 01540 // void c_plspal0(filename) 01541 // 01546 01547 void 01548 c_plspal0( const char *filename ) 01549 { 01550 int i; 01551 unsigned int *r, *g, *b; 01552 double *a; 01553 int number_colors; 01554 cmap0_palette_read( filename, &number_colors, &r, &g, &b, &a ); 01555 // Allocate default number of cmap0 colours if cmap0 allocation not 01556 // done already. 01557 plscmap0n( 0 ); 01558 // Allocate sufficient cmap0 colours to contain present data. 01559 if ( number_colors > plsc->ncol0 ) 01560 { 01561 plscmap0n( number_colors ); 01562 } 01563 for ( i = 0; i < number_colors; i++ ) 01564 { 01565 c_plscol0a( i, (PLINT) r[i], (PLINT) g[i], (PLINT) b[i], a[i] ); 01566 } 01567 free( r ); 01568 free( g ); 01569 free( b ); 01570 free( a ); 01571 } 01572 01582 #define fuzzy_range_check( value, min, max, fuzz, err_number ) \ 01583 if ( value < ( min - fuzz ) || value > ( max + fuzz ) ) { \ 01584 snprintf( msgbuf, MSGLEN, "Unrecognized cmap1 format data line. Error number is %d. Line is %s\n", err_number, color_info ); \ 01585 plwarn( msgbuf ); \ 01586 err = 1; \ 01587 break; \ 01588 } else if ( value < min ) { \ 01589 value = min; \ 01590 } else if ( value > max ) { \ 01591 value = max; \ 01592 } 01593 01594 //-------------------------------------------------------------------------- 01595 // void c_plspal1(filename) 01596 // 01602 01603 void 01604 c_plspal1( const char *filename, PLBOOL interpolate ) 01605 { 01606 int i; 01607 int number_colors; 01608 int format_version, err; 01609 PLBOOL rgb; 01610 char color_info[PALLEN]; 01611 unsigned int r_i, g_i, b_i; 01612 int pos_i, alt_hue_path_i; 01613 double r_d, g_d, b_d, a_d, pos_d; 01614 PLFLT *r, *g, *b, *a, *pos; 01615 PLINT *ri, *gi, *bi; 01616 PLBOOL *alt_hue_path; 01617 FILE *fp; 01618 char msgbuf[MSGLEN]; 01619 char * save_locale = plsave_set_locale(); 01620 01621 rgb = TRUE; 01622 err = 0; 01623 format_version = 0; 01624 if ( strlen( filename ) == 0 ) 01625 { 01626 fp = plLibOpen( PL_DEFAULT_CMAP1_FILE ); 01627 if ( fp == NULL ) 01628 { 01629 snprintf( msgbuf, MSGLEN, "Unable to open cmap1 .pal file %s\n", PL_DEFAULT_CMAP1_FILE ); 01630 plwarn( msgbuf ); 01631 goto finish; 01632 } 01633 } 01634 else 01635 { 01636 fp = plLibOpen( filename ); 01637 if ( fp == NULL ) 01638 { 01639 snprintf( msgbuf, MSGLEN, "Unable to open cmap1 .pal file %s\n", filename ); 01640 plwarn( msgbuf ); 01641 goto finish; 01642 } 01643 } 01644 // Check for new file format 01645 if ( read_line( color_info, PALLEN, fp ) == NULL ) 01646 { 01647 snprintf( msgbuf, MSGLEN, "Error reading cmap1 .pal file %s\n", filename ); 01648 plwarn( msgbuf ); 01649 fclose( fp ); 01650 goto finish; 01651 } 01652 if ( strncmp( color_info, "v2 ", 2 ) == 0 ) 01653 { 01654 format_version = 1; 01655 if ( strncmp( &color_info[3], "hls", 3 ) == 0 ) 01656 rgb = FALSE; 01657 else if ( strncmp( &color_info[3], "rgb", 3 ) == 0 ) 01658 rgb = TRUE; 01659 else 01660 { 01661 snprintf( msgbuf, MSGLEN, "Invalid color space %s - assuming RGB\n", &color_info[3] ); 01662 plwarn( msgbuf ); 01663 rgb = TRUE; 01664 } 01665 if ( read_line( color_info, PALLEN, fp ) == NULL ) 01666 { 01667 snprintf( msgbuf, MSGLEN, "Error reading cmap1 .pal file %s\n", filename ); 01668 plwarn( msgbuf ); 01669 fclose( fp ); 01670 goto finish; 01671 } 01672 } 01673 01674 if ( sscanf( color_info, "%d\n", &number_colors ) != 1 || number_colors < 2 ) 01675 { 01676 snprintf( msgbuf, MSGLEN, "Unrecognized cmap1 format (wrong number of colors) %s\n", color_info ); 01677 plwarn( msgbuf ); 01678 fclose( fp ); 01679 goto finish; 01680 } 01681 01682 r = (PLFLT *) malloc( (size_t) number_colors * sizeof ( PLFLT ) ); 01683 g = (PLFLT *) malloc( (size_t) number_colors * sizeof ( PLFLT ) ); 01684 b = (PLFLT *) malloc( (size_t) number_colors * sizeof ( PLFLT ) ); 01685 ri = (PLINT *) malloc( (size_t) number_colors * sizeof ( PLINT ) ); 01686 gi = (PLINT *) malloc( (size_t) number_colors * sizeof ( PLINT ) ); 01687 bi = (PLINT *) malloc( (size_t) number_colors * sizeof ( PLINT ) ); 01688 a = (PLFLT *) malloc( (size_t) number_colors * sizeof ( PLFLT ) ); 01689 pos = (PLFLT *) malloc( (size_t) number_colors * sizeof ( PLFLT ) ); 01690 alt_hue_path = (PLBOOL *) malloc( (size_t) ( number_colors - 1 ) * sizeof ( PLBOOL ) ); 01691 01692 if ( format_version == 0 ) 01693 { 01694 int return_sscanf = -1, return_sscanf_old = 0; 01695 // Old tk file format 01696 for ( i = 0; i < number_colors; i++ ) 01697 { 01698 if ( read_line( color_info, PALLEN, fp ) == NULL ) 01699 { 01700 snprintf( msgbuf, MSGLEN, "Error reading cmap1 .pal file %s\n", filename ); 01701 plwarn( msgbuf ); 01702 fclose( fp ); 01703 goto finish; 01704 } 01705 // Ensure string is null terminated if > 160 characters 01706 color_info[PALLEN - 1] = '\0'; 01707 return_sscanf = sscanf( color_info, "#%2x%2x%2x %d %d", &r_i, &g_i, &b_i, &pos_i, &alt_hue_path_i ); 01708 if ( return_sscanf < 4 || ( return_sscanf_old != 0 && return_sscanf != return_sscanf_old ) ) 01709 { 01710 snprintf( msgbuf, MSGLEN, "Unrecognized cmap1 format (wrong number of items for version 1 of format) %s\n", color_info ); 01711 plwarn( msgbuf ); 01712 err = 1; 01713 break; 01714 } 01715 return_sscanf_old = return_sscanf; 01716 // For old format, input colours range from 0 to 255 and 01717 // need to be renormalized to the range from 0. to 1.. 01718 r[i] = (PLFLT) r_i / 255.; 01719 g[i] = (PLFLT) g_i / 255.; 01720 b[i] = (PLFLT) b_i / 255.; 01721 a[i] = 1.0; 01722 pos[i] = 0.01 * (PLFLT) pos_i; 01723 fuzzy_range_check( r[i], 0., 1., FUZZ_EPSILON, 1 ); 01724 fuzzy_range_check( g[i], 0., 1., FUZZ_EPSILON, 2 ); 01725 fuzzy_range_check( b[i], 0., 1., FUZZ_EPSILON, 3 ); 01726 fuzzy_range_check( pos[i], 0., 1., FUZZ_EPSILON, 4 ); 01727 if ( ( return_sscanf == 5 ) && ( i != number_colors - 1 ) ) 01728 { 01729 // Next to oldest tk format with alt_hue_path specified. 01730 alt_hue_path[i] = (PLBOOL) alt_hue_path_i; 01731 } 01732 } 01733 if ( return_sscanf == 4 ) 01734 { 01735 // Oldest tk format. No alt_hue_path specified. 01736 free( alt_hue_path ); 01737 alt_hue_path = NULL; 01738 } 01739 } 01740 else 01741 { 01742 // New floating point file version with support for alpha and alt_hue_path values 01743 for ( i = 0; i < number_colors; i++ ) 01744 { 01745 if ( read_line( color_info, PALLEN, fp ) == NULL ) 01746 { 01747 snprintf( msgbuf, MSGLEN, "Error reading cmap1 .pal file %s\n", filename ); 01748 plwarn( msgbuf ); 01749 fclose( fp ); 01750 goto finish; 01751 } 01752 if ( sscanf( color_info, "%lf %lf %lf %lf %lf %d", &pos_d, &r_d, &g_d, &b_d, &a_d, &alt_hue_path_i ) != 6 ) 01753 { 01754 snprintf( msgbuf, MSGLEN, "Unrecognized cmap1 format (wrong number of items for version 2 of format) %s\n", color_info ); 01755 plwarn( msgbuf ); 01756 err = 1; 01757 break; 01758 } 01759 01760 r[i] = (PLFLT) r_d; 01761 g[i] = (PLFLT) g_d; 01762 b[i] = (PLFLT) b_d; 01763 a[i] = (PLFLT) a_d; 01764 pos[i] = (PLFLT) pos_d; 01765 // Check that all rgba and pos data within range from 0. to 01766 // 1. except for the hls colour space case where the first 01767 // coordinate is checked within range from 0. to 360. 01768 if ( rgb ) 01769 { 01770 fuzzy_range_check( r[i], 0., 1., FUZZ_EPSILON, 5 ); 01771 } 01772 else 01773 { 01774 fuzzy_range_check( r[i], 0., 360., ( 360. * FUZZ_EPSILON ), 6 ); 01775 } 01776 fuzzy_range_check( g[i], 0., 1., FUZZ_EPSILON, 7 ); 01777 fuzzy_range_check( b[i], 0., 1., FUZZ_EPSILON, 8 ); 01778 fuzzy_range_check( a[i], 0., 1., FUZZ_EPSILON, 9 ); 01779 fuzzy_range_check( pos[i], 0., 1., FUZZ_EPSILON, 10 ); 01780 01781 if ( i != number_colors - 1 ) 01782 alt_hue_path[i] = (PLBOOL) alt_hue_path_i; 01783 } 01784 } 01785 fclose( fp ); 01786 01787 if ( !err ) 01788 { 01789 if ( interpolate ) 01790 { 01791 c_plscmap1la( rgb, number_colors, pos, r, g, b, a, alt_hue_path ); 01792 } 01793 else 01794 { 01795 for ( i = 0; i < number_colors; i++ ) 01796 { 01797 ri[i] = (PLINT) ( r[i] * 255.0 ); 01798 gi[i] = (PLINT) ( g[i] * 255.0 ); 01799 bi[i] = (PLINT) ( b[i] * 255.0 ); 01800 } 01801 c_plscmap1a( ri, gi, bi, a, number_colors ); 01802 } 01803 } 01804 else 01805 { 01806 // Fall back to red scale as visual warning if some problem occurred 01807 // above. 01808 free( r ); 01809 free( g ); 01810 free( b ); 01811 free( pos ); 01812 number_colors = 2; 01813 r = (PLFLT *) malloc( (size_t) number_colors * sizeof ( PLFLT ) ); 01814 g = (PLFLT *) malloc( (size_t) number_colors * sizeof ( PLFLT ) ); 01815 b = (PLFLT *) malloc( (size_t) number_colors * sizeof ( PLFLT ) ); 01816 pos = (PLFLT *) malloc( (size_t) number_colors * sizeof ( PLFLT ) ); 01817 r[0] = 0.; 01818 r[1] = 1.; 01819 g[0] = 0.; 01820 g[1] = 0.; 01821 b[0] = 0.; 01822 b[1] = 0.; 01823 pos[0] = 0.; 01824 pos[1] = 1.; 01825 c_plscmap1l( TRUE, number_colors, pos, r, g, b, NULL ); 01826 } 01827 01828 free( r ); 01829 free( g ); 01830 free( b ); 01831 free( ri ); 01832 free( gi ); 01833 free( bi ); 01834 free( a ); 01835 free( pos ); 01836 free( alt_hue_path ); 01837 01838 finish: plrestore_locale( save_locale ); 01839 } 01840 01841 //-------------------------------------------------------------------------- 01842 // A grab-bag of various control routines. 01843 //-------------------------------------------------------------------------- 01844 01845 //-------------------------------------------------------------------------- 01846 // void plwarn() 01847 // 01851 01852 void 01853 plwarn( const char *errormsg ) 01854 { 01855 int was_gfx = 0; 01856 01857 if ( plsc->graphx == 1 ) 01858 { 01859 was_gfx = 1; 01860 pltext(); 01861 } 01862 01863 fprintf( stderr, "\n*** PLPLOT WARNING ***\n" ); 01864 if ( *errormsg != '\0' ) 01865 fprintf( stderr, "%s\n", errormsg ); 01866 01867 if ( was_gfx == 1 ) 01868 plgra(); 01869 } 01870 01871 //-------------------------------------------------------------------------- 01872 // void plabort() 01873 // 01882 01883 void 01884 plabort( const char *errormsg ) 01885 { 01886 if ( abort_handler != NULL ) 01887 ( *abort_handler )( errormsg ); 01888 01889 if ( plsc->errcode != NULL ) 01890 *( plsc->errcode ) = 1; 01891 01892 if ( plsc->errmsg != NULL ) 01893 { 01894 sprintf( plsc->errmsg, "\n*** PLPLOT ERROR, ABORTING OPERATION ***\n" ); 01895 if ( *errormsg != '\0' ) 01896 sprintf( plsc->errmsg, "%s, aborting operation\n", errormsg ); 01897 } 01898 else 01899 { 01900 int was_gfx = 0; 01901 01902 if ( plsc->graphx == 1 ) 01903 { 01904 was_gfx = 1; 01905 pltext(); 01906 } 01907 01908 fprintf( stderr, "\n*** PLPLOT ERROR, ABORTING OPERATION ***\n" ); 01909 if ( *errormsg != '\0' ) 01910 fprintf( stderr, "%s, aborting operation\n", errormsg ); 01911 01912 if ( was_gfx == 1 ) 01913 plgra(); 01914 } 01915 } 01916 01917 01918 //-------------------------------------------------------------------------- 01919 // void plsabort() 01920 // 01925 //-------------------------------------------------------------------------- 01926 01927 void 01928 plsabort( void ( *handler )( const char * ) ) 01929 { 01930 abort_handler = handler; 01931 } 01932 01933 //-------------------------------------------------------------------------- 01934 // void plexit() 01935 // 01945 //-------------------------------------------------------------------------- 01946 01947 void 01948 plexit( const char *errormsg ) 01949 { 01950 int status = 1; 01951 01952 if ( exit_handler != NULL ) 01953 status = ( *exit_handler )( errormsg ); 01954 01955 plsc->nopause = 1; 01956 if ( *errormsg != '\0' ) 01957 { 01958 fprintf( stderr, "\n*** PLPLOT ERROR, IMMEDIATE EXIT ***\n" ); 01959 fprintf( stderr, "%s\n", errormsg ); 01960 } 01961 plend(); 01962 01963 fprintf( stderr, "Program aborted\n" ); 01964 exit( status ); 01965 } 01966 01967 //-------------------------------------------------------------------------- 01968 // void plsexit() 01969 // 01974 //-------------------------------------------------------------------------- 01975 01976 void 01977 plsexit( int ( *handler )( const char * ) ) 01978 { 01979 exit_handler = handler; 01980 } 01981 01982 //-------------------------------------------------------------------------- 01983 // void plgra() 01984 // 01990 //-------------------------------------------------------------------------- 01991 01992 void 01993 c_plgra( void ) 01994 { 01995 if ( plsc->level > 0 ) 01996 plP_esc( PLESC_GRAPH, NULL ); 01997 } 01998 01999 //-------------------------------------------------------------------------- 02000 // void plxormod() 02001 // 02006 02007 void 02008 c_plxormod( PLINT mode, PLINT *status ) // xor mode 02009 { 02010 static int ostate = 0; 02011 02012 if ( !plsc->dev_xor ) 02013 { 02014 *status = 0; 02015 return; 02016 } 02017 02018 if ( plsc->level > 0 ) 02019 { 02020 plP_esc( PLESC_XORMOD, &mode ); 02021 if ( mode ) 02022 { 02023 ostate = plsc->plbuf_write; 02024 plsc->plbuf_write = 0; 02025 } 02026 else 02027 plsc->plbuf_write = ostate; 02028 } 02029 *status = 1; 02030 } 02031 02032 //-------------------------------------------------------------------------- 02037 void 02038 c_plsdrawmode( PLINT mode ) 02039 { 02040 if ( !plsc->dev_modeset ) 02041 { 02042 plwarn( "plsdrawmode: Mode setting is not supported by this device" ); 02043 } 02044 else if ( plsc->level > 0 ) 02045 { 02046 plP_esc( PLESC_MODESET, &mode ); 02047 } 02048 else 02049 { 02050 plwarn( "plsdrawmode: Initialize PLplot first" ); 02051 } 02052 return; 02053 } 02054 02055 //-------------------------------------------------------------------------- 02060 PLINT 02061 c_plgdrawmode( void ) 02062 { 02063 PLINT mode; 02064 02065 if ( !plsc->dev_modeset ) 02066 { 02067 plwarn( "plgdrawmode: Mode getting is not supported by this device" ); 02068 mode = PL_DRAWMODE_UNKNOWN; 02069 } 02070 else if ( plsc->level > 0 ) 02071 { 02072 plP_esc( PLESC_MODEGET, &mode ); 02073 } 02074 else 02075 { 02076 plwarn( "plsdrawmode: Initialize PLplot first" ); 02077 mode = PL_DRAWMODE_UNKNOWN; 02078 } 02079 02080 return ( mode ); 02081 } 02082 02083 //-------------------------------------------------------------------------- 02084 // void pltext() 02085 // 02087 //-------------------------------------------------------------------------- 02088 02089 void 02090 c_pltext( void ) 02091 { 02092 if ( plsc->level > 0 ) 02093 plP_esc( PLESC_TEXT, NULL ); 02094 } 02095 02096 //-------------------------------------------------------------------------- 02097 // void pl_cmd() 02098 // 02105 //-------------------------------------------------------------------------- 02106 02107 void 02108 pl_cmd( PLINT op, void *ptr ) 02109 { 02110 plP_esc( op, ptr ); 02111 } 02112 02113 //-------------------------------------------------------------------------- 02114 // char *plFindCommand 02115 // 02132 //-------------------------------------------------------------------------- 02133 02134 char * 02135 plFindCommand( const char *fn ) 02136 { 02137 char *fs = NULL, *dn; 02138 02139 //*** see if in build tree ** 02140 if ( plInBuildTree() == 1 ) 02141 { 02142 plGetName( BUILD_DIR, "bindings/tk", fn, &fs ); 02143 if ( !plFindName( fs ) ) 02144 return fs; 02145 else 02146 { 02147 plGetName( SOURCE_DIR, "scripts", fn, &fs ); 02148 if ( !plFindName( fs ) ) 02149 return fs; 02150 } 02151 } 02152 02153 // PLPLOT_BIN_ENV = $(PLPLOT_BIN) 02154 02155 #if defined ( PLPLOT_BIN_ENV ) 02156 if ( ( dn = getenv( PLPLOT_BIN_ENV ) ) != NULL ) 02157 { 02158 plGetName( dn, "", fn, &fs ); 02159 if ( !plFindName( fs ) ) 02160 return fs; 02161 fprintf( stderr, PLPLOT_BIN_ENV "=\"%s\"\n", dn ); // what IS set? 02162 } 02163 #endif // PLPLOT_BIN_ENV 02164 02165 // Current directory 02166 02167 plGetName( ".", "", fn, &fs ); 02168 if ( !plFindName( fs ) ) 02169 return fs; 02170 02171 // PLPLOT_HOME_ENV/bin = $(PLPLOT_HOME)/bin 02172 02173 #if defined ( PLPLOT_HOME_ENV ) 02174 if ( ( dn = getenv( PLPLOT_HOME_ENV ) ) != NULL ) 02175 { 02176 plGetName( dn, "bin", fn, &fs ); 02177 if ( !plFindName( fs ) ) 02178 return fs; 02179 fprintf( stderr, PLPLOT_HOME_ENV "=\"%s\"\n", dn ); // what IS set? 02180 } 02181 #endif // PLPLOT_HOME_ENV 02182 02183 // BIN_DIR 02184 02185 #if defined ( BIN_DIR ) 02186 plGetName( BIN_DIR, "", fn, &fs ); 02187 if ( !plFindName( fs ) ) 02188 return fs; 02189 #endif 02190 02191 // Crapped out 02192 02193 free_mem( fs ); 02194 fprintf( stderr, "plFindCommand: cannot locate command: %s\n", fn ); 02195 #if defined ( BIN_DIR ) 02196 fprintf( stderr, "bin dir=\"" BIN_DIR "\"\n" ); // what WAS set? 02197 #endif // BIN_DIR 02198 return NULL; 02199 } 02200 02201 //-------------------------------------------------------------------------- 02202 // FILE *plLibOpen(fn) 02203 // 02215 //-------------------------------------------------------------------------- 02216 02217 FILE * 02218 plLibOpen( const char *fn ) 02219 { 02220 FILE *ret = NULL; 02221 02222 PDFstrm *pdfs = plLibOpenPdfstrm( fn ); 02223 if ( pdfs == NULL ) 02224 { 02225 return NULL; 02226 } 02227 if ( pdfs->file != NULL ) 02228 { 02229 ret = pdfs->file; 02230 pdfs->file = NULL; 02231 } 02232 pdf_close( pdfs ); 02233 return ret; 02234 } 02235 02236 //-------------------------------------------------------------------------- 02237 // FILE *plLibOpenPdfstrm(fn) 02238 // 02250 //-------------------------------------------------------------------------- 02251 PDFstrm * 02252 plLibOpenPdfstrm( const char *fn ) 02253 { 02254 PDFstrm *file; 02255 char *fs = NULL, *dn = NULL; 02256 02257 //*** search build tree *** 02258 02259 if ( plInBuildTree() == 1 ) 02260 { 02261 plGetName( SOURCE_DIR, "data", fn, &fs ); 02262 02263 if ( ( file = pdf_fopen( fs, "rb" ) ) != NULL ) 02264 goto done; 02265 } 02266 02267 //*** search PLPLOT_LIB_ENV = $(PLPLOT_LIB) *** 02268 02269 #if defined ( PLPLOT_LIB_ENV ) 02270 if ( ( dn = getenv( PLPLOT_LIB_ENV ) ) != NULL ) 02271 { 02272 plGetName( dn, "", fn, &fs ); 02273 02274 if ( ( file = pdf_fopen( fs, "rb" ) ) != NULL ) 02275 goto done; 02276 fprintf( stderr, PLPLOT_LIB_ENV "=\"%s\"\n", dn ); // what IS set? 02277 } 02278 #endif // PLPLOT_LIB_ENV 02279 02280 //*** search current directory *** 02281 02282 if ( ( file = pdf_fopen( fn, "rb" ) ) != NULL ) 02283 { 02284 pldebug( "plLibOpenPdfstr", "Found file %s in current directory.\n", fn ); 02285 free_mem( fs ); 02286 return ( file ); 02287 } 02288 02289 //*** search PLPLOT_HOME_ENV/lib = $(PLPLOT_HOME)/lib *** 02290 02291 #if defined ( PLPLOT_HOME_ENV ) 02292 if ( ( dn = getenv( PLPLOT_HOME_ENV ) ) != NULL ) 02293 { 02294 plGetName( dn, "lib", fn, &fs ); 02295 02296 if ( ( file = pdf_fopen( fs, "rb" ) ) != NULL ) 02297 goto done; 02298 fprintf( stderr, PLPLOT_HOME_ENV "=\"%s\"\n", dn ); // what IS set? 02299 } 02300 #endif // PLPLOT_HOME_ENV/lib 02301 02302 //*** search installed location *** 02303 02304 #if defined ( DATA_DIR ) 02305 plGetName( DATA_DIR, "", fn, &fs ); 02306 02307 if ( ( file = pdf_fopen( fs, "rb" ) ) != NULL ) 02308 goto done; 02309 #endif // DATA_DIR 02310 02311 //*** search hardwired location *** 02312 02313 #ifdef PLLIBDEV 02314 plGetName( PLLIBDEV, "", fn, &fs ); 02315 02316 if ( ( file = pdf_fopen( fs, "rb" ) ) != NULL ) 02317 goto done; 02318 #endif // PLLIBDEV 02319 02320 #ifdef macintosh 02321 file = plMacLibOpen( fn ); 02322 if ( file != NULL ) 02323 goto done; 02324 #endif // macintosh 02325 02326 if ( plplotLibDir != NULL ) 02327 { 02328 plGetName( plplotLibDir, "", fn, &fs ); 02329 if ( ( file = pdf_fopen( fs, "rb" ) ) != NULL ) 02330 goto done; 02331 } 02332 02333 //*** not found, give up *** 02334 pldebug( "plLibOpenPdfstr", "File %s not found.\n", fn ); 02335 free_mem( fs ); 02336 return NULL; 02337 02338 done: 02339 pldebug( "plLibOpenPdfstr", "Found file %s\n", fs ); 02340 free_mem( fs ); 02341 return ( file ); 02342 } 02343 02344 //-------------------------------------------------------------------------- 02345 // int plFindName 02346 // 02364 //-------------------------------------------------------------------------- 02365 02366 #ifdef __unix 02367 int 02368 plFindName( char *p ) 02369 { 02370 ssize_t n; 02371 char buf[PLPLOT_MAX_PATH], *cp; 02372 struct stat sbuf; 02373 02374 pldebug( "plFindName", "Trying to find %s\n", p ); 02375 while ( ( n = readlink( p, buf, PLPLOT_MAX_PATH ) ) > 0 ) 02376 { 02377 pldebug( "plFindName", "Readlink read %d chars at: %s\n", n, p ); 02378 if ( buf[0] == '/' ) 02379 { 02380 // Link is an absolute path 02381 02382 strncpy( p, buf, (size_t) n ); 02383 p[n] = '\0'; 02384 pldebug( "plFindName", "Link is absolute: %s\n", p ); 02385 } 02386 else 02387 { 02388 // Link is relative to its directory; make it absolute 02389 02390 cp = 1 + strrchr( p, '/' ); 02391 strncpy( cp, buf, (size_t) n ); 02392 cp[n] = '\0'; 02393 pldebug( "plFindName", 02394 "Link is relative: %s\n\tTotal path:%s\n", cp, p ); 02395 } 02396 } 02397 02398 // This macro not defined on the NEC SX-3 02399 02400 #ifdef SX 02401 #define S_ISREG( mode ) ( mode & S_IFREG ) 02402 #endif 02403 02404 // SGI machines return ENXIO instead of EINVAL Dubois 11/92 02405 02406 if ( errno == EINVAL || errno == ENXIO ) 02407 { 02408 pldebug( "plFindName", "%s may be the one...\n", p ); 02409 if ( ( stat( p, &sbuf ) == 0 ) && S_ISREG( sbuf.st_mode ) ) 02410 { 02411 pldebug( "plFindName", "%s is a regular file\n", p ); 02412 return ( access( p, X_OK ) ); 02413 } 02414 } 02415 pldebug( "plFindName", "%s found but is not executable\n", p ); 02416 return ( errno ? errno : -1 ); 02417 } 02418 02419 #else 02420 int 02421 plFindName( char *p ) 02422 { 02423 return 1; 02424 } 02425 #endif 02426 02427 //-------------------------------------------------------------------------- 02428 // void plGetName() 02429 // 02439 //-------------------------------------------------------------------------- 02440 02441 void 02442 plGetName( const char *dir, const char *subdir, const char *filename, char **filespec ) 02443 { 02444 size_t lfilespec; 02445 02446 // Malloc space for filespec 02447 02448 free_mem( *filespec ); 02449 // Be slightly generous since 3 (two delimiters + NULL byte) should be 02450 // enough. 02451 lfilespec = strlen( dir ) + strlen( subdir ) + strlen( filename ) + 10; 02452 if ( ( *filespec = (char *) malloc( lfilespec ) ) == NULL ) 02453 { 02454 plexit( "plGetName: Insufficient memory" ); 02455 } 02456 02457 strcpy( *filespec, dir ); 02458 02459 if ( *subdir != '\0' ) 02460 { 02461 strcat_delim( *filespec ); 02462 strcat( *filespec, subdir ); 02463 } 02464 if ( *filename != '\0' ) 02465 { 02466 strcat_delim( *filespec ); 02467 strcat( *filespec, filename ); 02468 } 02469 #ifdef WIN32 02470 // According to http://msdn.microsoft.com/en-us/library/vstudio/tcxf1dw6.aspx 02471 // and also Wine tests, Microsoft does not support the c99 standard %zu 02472 // format. Instead, %lu is recommended for size_t. 02473 pldebug( "plGetName", "Maximum length of full pathname of file to be found is %lu\n", lfilespec - 1 ); 02474 #else 02475 pldebug( "plGetName", "Maximum length of full pathname of file to be found is %zu\n", lfilespec - 1 ); 02476 #endif 02477 pldebug( "plGetName", "Full pathname of file to be found is %s\n", *filespec ); 02478 } 02479 02480 //-------------------------------------------------------------------------- 02481 // void strcat_delim() 02482 // 02487 //-------------------------------------------------------------------------- 02488 02489 void 02490 strcat_delim( char *dirspec ) 02491 { 02492 size_t ldirspec = strlen( dirspec ); 02493 #if defined ( MSDOS ) || defined ( WIN32 ) 02494 if ( dirspec[ldirspec - 1] != '\\' ) 02495 strcat( dirspec, "\\" ); 02496 #elif defined ( macintosh ) 02497 if ( dirspec[ldirspec - 1] != ':' ) 02498 strcat( dirspec, ":" ); 02499 #else // unix is the default 02500 if ( dirspec[ldirspec - 1] != '/' ) 02501 strcat( dirspec, "/" ); 02502 #endif 02503 } 02504 02505 //-------------------------------------------------------------------------- 02506 // plcol_interp() 02507 // 02516 //-------------------------------------------------------------------------- 02517 02518 void 02519 plcol_interp( PLStream *pls, PLColor *newcolor, int i, int ncol ) 02520 { 02521 PLFLT x, delta; 02522 int il, ir; 02523 02524 x = (double) ( i * ( pls->ncol1 - 1 ) ) / (double) ( ncol - 1 ); 02525 il = (int) x; 02526 ir = il + 1; 02527 delta = x - il; 02528 02529 if ( ir > pls->ncol1 || il < 0 ) 02530 fprintf( stderr, "Invalid color\n" ); 02531 02532 else if ( ir == pls->ncol1 || ( delta == 0. ) ) 02533 { 02534 newcolor->r = pls->cmap1[il].r; 02535 newcolor->g = pls->cmap1[il].g; 02536 newcolor->b = pls->cmap1[il].b; 02537 newcolor->a = pls->cmap1[il].a; 02538 } 02539 else 02540 { 02541 newcolor->r = (unsigned char) ( ( 1. - delta ) * pls->cmap1[il].r + delta * pls->cmap1[ir].r ); 02542 newcolor->g = (unsigned char) ( ( 1. - delta ) * pls->cmap1[il].g + delta * pls->cmap1[ir].g ); 02543 newcolor->b = (unsigned char) ( ( 1. - delta ) * pls->cmap1[il].b + delta * pls->cmap1[ir].b ); 02544 newcolor->a = ( 1. - delta ) * pls->cmap1[il].a + delta * pls->cmap1[ir].a; 02545 } 02546 } 02547 02548 //-------------------------------------------------------------------------- 02549 // plOpenFile() 02550 // 02556 //-------------------------------------------------------------------------- 02557 02558 #define MAX_NUM_TRIES 10 02559 void 02560 plOpenFile( PLStream *pls ) 02561 { 02562 int i = 0, count = 0; 02563 size_t len; 02564 char line[BUFFER_SIZE]; 02565 02566 while ( pls->OutFile == NULL ) 02567 { 02568 // Setting pls->FileName = NULL forces creation of a new family member 02569 // You should also free the memory associated with it if you do this 02570 02571 if ( pls->family && pls->BaseName != NULL ) 02572 plP_getmember( pls ); 02573 02574 // Prompt if filename still not known 02575 02576 if ( pls->FileName == NULL ) 02577 { 02578 do 02579 { 02580 fprintf( stdout, "Enter graphics output file name: " ); 02581 plio_fgets( line, sizeof ( line ), stdin ); 02582 len = strlen( line ); 02583 if ( len ) 02584 len--; 02585 line[len] = '\0'; // strip new-line 02586 count++; // count zero entries 02587 } while ( !len && count < MAX_NUM_TRIES ); 02588 plP_sfnam( pls, line ); 02589 } 02590 02591 // If name is "-", send to stdout 02592 02593 if ( !strcmp( pls->FileName, "-" ) ) 02594 { 02595 pls->OutFile = stdout; 02596 pls->output_type = 1; 02597 break; 02598 } 02599 02600 // Need this here again, for prompted family initialization 02601 02602 if ( pls->family && pls->BaseName != NULL ) 02603 plP_getmember( pls ); 02604 02605 if ( i++ > 10 ) 02606 plexit( "Too many tries." ); 02607 02608 if ( ( pls->OutFile = fopen( pls->FileName, "wb+" ) ) == NULL ) 02609 fprintf( stderr, "Can't open %s.\n", pls->FileName ); 02610 else 02611 pldebug( "plOpenFile", "Opened %s\n", pls->FileName ); 02612 } 02613 } 02614 02615 //-------------------------------------------------------------------------- 02616 // plCloseFile() 02617 // 02621 //-------------------------------------------------------------------------- 02622 02623 void 02624 plCloseFile( PLStream *pls ) 02625 { 02626 if ( pls->OutFile != NULL ) 02627 { 02628 // Don't close if the output file was stdout 02629 if ( pls->FileName && strcmp( pls->FileName, "-" ) == 0 ) 02630 return; 02631 02632 fclose( pls->OutFile ); 02633 pls->OutFile = NULL; 02634 } 02635 } 02636 02637 //-------------------------------------------------------------------------- 02638 // plP_getmember() 02639 // 02643 //-------------------------------------------------------------------------- 02644 02645 void 02646 plP_getmember( PLStream *pls ) 02647 { 02648 char tmp[BUFFER_SIZE]; 02649 char prefix[BUFFER_SIZE]; 02650 char * suffix; 02651 char num[BUFFER_SIZE]; 02652 size_t maxlen; 02653 02654 maxlen = strlen( pls->BaseName ) + 10; 02655 if ( pls->FileName == NULL ) 02656 { 02657 if ( ( pls->FileName = (char *) malloc( maxlen ) ) == NULL ) 02658 { 02659 plexit( "plP_getmember: Insufficient memory" ); 02660 } 02661 } 02662 02663 suffix = strstr( pls->BaseName, "%n" ); 02664 02665 snprintf( tmp, BUFFER_SIZE, "%%0%1ii", (int) pls->fflen ); 02666 snprintf( num, BUFFER_SIZE, tmp, pls->member ); 02667 02668 if ( suffix == NULL ) 02669 snprintf( pls->FileName, maxlen, "%s.%s", pls->BaseName, num ); 02670 else 02671 { 02672 strncpy( prefix, pls->BaseName, BUFFER_SIZE - 1 ); 02673 prefix [( suffix - pls->BaseName < BUFFER_SIZE ) ? ( suffix - pls->BaseName ) : BUFFER_SIZE - 1] = '\0'; 02674 snprintf( pls->FileName, maxlen, "%s%s%s", prefix, num, suffix + 2 ); 02675 } 02676 } 02677 02678 //-------------------------------------------------------------------------- 02679 // plP_sfnam() 02680 // 02686 //-------------------------------------------------------------------------- 02687 02688 void 02689 plP_sfnam( PLStream *pls, const char *fnam ) 02690 { 02691 char prefix[BUFFER_SIZE]; 02692 char * suffix; 02693 size_t maxlen; 02694 pls->OutFile = NULL; 02695 02696 if ( pls->FileName != NULL ) 02697 free( (void *) pls->FileName ); 02698 02699 maxlen = 10 + strlen( fnam ); 02700 if ( ( pls->FileName = (char *) malloc( maxlen ) ) == NULL ) 02701 { 02702 plexit( "plP_sfnam: Insufficient memory" ); 02703 } 02704 02705 suffix = strstr( fnam, "%n" ); 02706 02707 if ( suffix == NULL ) 02708 { 02709 strncpy( pls->FileName, fnam, maxlen - 1 ); 02710 pls->FileName[maxlen - 1] = '\0'; 02711 } 02712 else 02713 { 02714 strncpy( prefix, fnam, BUFFER_SIZE - 1 ); 02715 prefix [( suffix - fnam ) < BUFFER_SIZE ? ( suffix - fnam ) : BUFFER_SIZE - 1] = '\0'; 02716 snprintf( pls->FileName, maxlen, "%s%s", prefix, suffix + 2 ); 02717 } 02718 02719 if ( pls->BaseName != NULL ) 02720 free( (void *) pls->BaseName ); 02721 02722 if ( ( pls->BaseName = (char *) malloc( maxlen ) ) == NULL ) 02723 { 02724 plexit( "plP_sfnam: Insufficient memory" ); 02725 } 02726 02727 strncpy( pls->BaseName, fnam, maxlen - 1 ); 02728 pls->BaseName[maxlen - 1] = '\0'; 02729 } 02730 02731 //-------------------------------------------------------------------------- 02732 // plFamInit() 02733 // 02737 //-------------------------------------------------------------------------- 02738 02739 void 02740 plFamInit( PLStream *pls ) 02741 { 02742 if ( pls->family ) 02743 { 02744 pls->bytecnt = 0; 02745 if ( !pls->member ) 02746 pls->member = 1; 02747 if ( !pls->finc ) 02748 pls->finc = 1; 02749 if ( !pls->fflen ) 02750 pls->fflen = 1; 02751 if ( !pls->bytemax ) 02752 pls->bytemax = PL_FILESIZE_KB * 1000; 02753 } 02754 } 02755 02756 //-------------------------------------------------------------------------- 02757 // plGetFam() 02758 // 02766 //-------------------------------------------------------------------------- 02767 02768 void 02769 plGetFam( PLStream *pls ) 02770 { 02771 PLFLT xpmm_loc, ypmm_loc; 02772 if ( pls->family ) 02773 { 02774 if ( pls->bytecnt > pls->bytemax || pls->famadv ) 02775 { 02776 PLINT local_page_status = pls->page_status; 02777 plP_tidy(); 02778 pls->member += pls->finc; 02779 pls->famadv = 0; 02780 plP_init(); 02781 // Restore page status (normally AT_BOP) that was changed 02782 // to AT_EOP by plP_init. 02783 pls->page_status = local_page_status; 02784 02785 // Apply compensating factor to original xpmm and ypmm so that 02786 // character aspect ratio is preserved when overall aspect ratio 02787 // is changed. 02788 plP_gpixmm( &xpmm_loc, &ypmm_loc ); 02789 plP_setpxl( xpmm_loc * plsc->caspfactor, ypmm_loc / plsc->caspfactor ); 02790 return; 02791 } 02792 } 02793 } 02794 02795 //-------------------------------------------------------------------------- 02796 // plRotPhy() 02797 // 02810 //-------------------------------------------------------------------------- 02811 02812 void 02813 plRotPhy( PLINT orient, PLINT xmin, PLINT ymin, PLINT xmax, PLINT ymax, 02814 PLINT *px, PLINT *py ) 02815 { 02816 int x, y; 02817 02818 x = *px; 02819 y = *py; 02820 02821 switch ( orient % 4 ) 02822 { 02823 case 1: 02824 *px = xmin + ( y - ymin ); 02825 *py = ymin + ( xmax - x ); 02826 break; 02827 02828 case 2: 02829 *px = xmin + ( xmax - x ); 02830 *py = ymin + ( ymax - y ); 02831 break; 02832 02833 case 3: 02834 *px = xmin + ( ymax - y ); 02835 *py = ymin + ( x - xmin ); 02836 break; 02837 02838 default: 02839 break; // do nothing 02840 } 02841 } 02842 02843 //-------------------------------------------------------------------------- 02844 // plAllocDev() 02845 // 02852 //-------------------------------------------------------------------------- 02853 02854 PLDev * 02855 plAllocDev( PLStream *pls ) 02856 { 02857 if ( pls->dev != NULL ) 02858 free( (void *) pls->dev ); 02859 02860 pls->dev = calloc( 1, (size_t) sizeof ( PLDev ) ); 02861 if ( pls->dev == NULL ) 02862 plexit( "plAllocDev: cannot allocate memory\n" ); 02863 02864 return (PLDev *) pls->dev; 02865 } 02866 02867 //-------------------------------------------------------------------------- 02868 // plGinInit() 02869 // 02873 //-------------------------------------------------------------------------- 02874 02875 void 02876 plGinInit( PLGraphicsIn *gin ) 02877 { 02878 gin->type = 0; 02879 gin->state = 0; 02880 gin->keysym = 0; 02881 gin->button = 0; 02882 gin->string[0] = '\0'; 02883 gin->pX = gin->pY = -1; 02884 gin->dX = gin->dY = 0.; 02885 gin->wX = gin->wY = 0.; 02886 } 02887 02888 //-------------------------------------------------------------------------- 02889 // plGetInt() 02890 // 02896 //-------------------------------------------------------------------------- 02897 02898 PLINT 02899 plGetInt( const char *s ) 02900 { 02901 int m; 02902 int i = 0; 02903 char line[BUFFER_SIZE]; 02904 02905 while ( i++ < 10 ) 02906 { 02907 fputs( s, stdout ); 02908 plio_fgets( line, sizeof ( line ), stdin ); 02909 02910 #ifdef MSDOS 02911 m = atoi( line ); 02912 return ( m ); 02913 #else 02914 if ( sscanf( line, "%d", &m ) == 1 ) 02915 return ( m ); 02916 fprintf( stdout, "No value or value out of range; please try again\n" ); 02917 #endif 02918 } 02919 plexit( "Too many tries." ); 02920 return ( 0 ); 02921 } 02922 02923 //-------------------------------------------------------------------------- 02924 // plGetFlt() 02925 // 02931 //-------------------------------------------------------------------------- 02932 02933 PLFLT 02934 plGetFlt( const char *s ) 02935 { 02936 PLFLT m; 02937 double m1; 02938 int i = 0; 02939 char line[BUFFER_SIZE]; 02940 02941 while ( i++ < 10 ) 02942 { 02943 fputs( s, stdout ); 02944 plio_fgets( line, sizeof ( line ), stdin ); 02945 02946 #ifdef MSDOS 02947 m = atof( line ); 02948 return ( m ); 02949 #else 02950 if ( sscanf( line, "%lf", &m1 ) == 1 ) 02951 { 02952 m = (PLFLT) m1; 02953 return ( m ); 02954 } 02955 fprintf( stdout, "No value or value out of range; please try again\n" ); 02956 #endif 02957 } 02958 plexit( "Too many tries." ); 02959 return ( 0. ); 02960 } 02961 02962 //-------------------------------------------------------------------------- 02963 // plstrdup() 02964 // 02971 //-------------------------------------------------------------------------- 02972 02973 char PLDLLIMPEXP * 02974 plstrdup( const char *src ) 02975 { 02976 char *dest = (char *) malloc( ( strlen( src ) + 1 ) * sizeof ( char ) ); 02977 if ( dest != NULL ) 02978 strcpy( dest, src ); 02979 else 02980 plabort( "Out of memory" ); 02981 02982 return dest; 02983 } 02984 02985 #ifndef PL_HAVE_SNPRINTF 02986 //-------------------------------------------------------------------------- 02987 // plsnprintf() 02988 // 02999 //-------------------------------------------------------------------------- 03000 03001 int 03002 plsnprintf( char *buffer, int n, const char *format, ... ) 03003 { 03004 int ret; 03005 03006 va_list args; 03007 va_start( args, format ); 03008 ret = vsprintf( buffer, format, args ); 03009 va_end( args ); 03010 03011 // Check if overrun occured 03012 if ( ret > n - 1 ) 03013 plabort( "plsnprintf: buffer overrun" ); 03014 03015 return ret; 03016 } 03017 03018 //-------------------------------------------------------------------------- 03019 // plsnscanf() 03020 // 03031 //-------------------------------------------------------------------------- 03032 03033 int 03034 plsnscanf( const char *buffer, int n, const char *format, ... ) 03035 { 03036 int ret; 03037 03038 va_list args; 03039 va_start( args, format ); 03040 ret = vsscanf( buffer, format, args ); 03041 va_end( args ); 03042 03043 return ret; 03044 } 03045 03046 #endif // PL_HAVE_SNPRINTF 03047 03048 //-------------------------------------------------------------------------- 03049 // plseed() 03050 // 03054 //-------------------------------------------------------------------------- 03055 03056 void 03057 c_plseed( unsigned int seed ) 03058 { 03059 init_genrand( seed ); 03060 } 03061 03062 //-------------------------------------------------------------------------- 03063 // plrandd() 03064 // 03067 //-------------------------------------------------------------------------- 03068 03069 PLFLT 03070 c_plrandd( void ) 03071 { 03072 return (PLFLT) ( genrand_real1() ); 03073 } 03074 03075 //-------------------------------------------------------------------------- 03076 // plsave_set_locale() 03077 // 03087 //-------------------------------------------------------------------------- 03088 03089 char * 03090 plsave_set_locale( void ) 03091 { 03092 char * setlocale_ptr; 03093 char * saved_lc_numeric_locale; 03094 03095 if ( !( saved_lc_numeric_locale = (char *) malloc( 100 * sizeof ( char ) ) ) ) 03096 { 03097 plexit( "plsave_set_locale: out of memory" ); 03098 } 03099 03100 //save original LC_NUMERIC locale for restore below. 03101 if ( !( setlocale_ptr = setlocale( LC_NUMERIC, NULL ) ) ) 03102 { 03103 plexit( "plsave_set_locale: LC_NUMERIC locale could not be determined for NULL locale.\n" ); 03104 } 03105 strncpy( saved_lc_numeric_locale, setlocale_ptr, 100 ); 03106 saved_lc_numeric_locale[99] = '\0'; 03107 03108 // Do not use pldebug since get overflowed stack (infinite recursion) 03109 // if device is interactive (i.e., pls->termin is set). 03110 // comment out fprintf (unless there is some emergency debugging to do) 03111 // because output is too voluminous. 03112 // 03113 // fprintf(stderr, "plsave_set_locale: saved LC_NUMERIC locale is \"%s\"\n", saved_lc_numeric_locale); 03114 // 03115 03116 if ( !( setlocale( LC_NUMERIC, "C" ) ) ) 03117 { 03118 plexit( "plsave_set_locale: LC_NUMERIC locale could not be set to \"C\"" ); 03119 } 03120 return saved_lc_numeric_locale; 03121 } 03122 03123 //-------------------------------------------------------------------------- 03124 // plrestore_locale() 03125 // 03131 //-------------------------------------------------------------------------- 03132 03133 void 03134 plrestore_locale( char *saved_lc_numeric_locale ) 03135 { 03136 // Do not use pldebug since get overflowed stack (infinite recursion) 03137 // if device is interactive (i.e., pls->termin is set). 03138 // comment out fprintf (unless there is some emergency debugging to do) 03139 // because output is too voluminous. 03140 // 03141 // fprintf(stderr, "plrestore_locale: restored LC_NUMERIC locale is \"%s\"\n", saved_lc_numeric_locale); 03142 // 03143 03144 if ( !( setlocale( LC_NUMERIC, saved_lc_numeric_locale ) ) ) 03145 { 03146 char msgbuf[1024]; 03147 snprintf( msgbuf, 1024, "plrestore_locale: LC_NUMERIC could not be restored to the default \"%s\" locale.\n", saved_lc_numeric_locale ); 03148 plexit( msgbuf ); 03149 } 03150 free( saved_lc_numeric_locale ); 03151 } 03152