// Internal (private) macros and prototypes for the PLplot package. This // header file must be included before all others, including system header // files. This file is typically needed when including driver specific // header files (e.g. pltkd.h). // // Copyright (C) 1993, 1994, 1995 by // Maurice J. LeBrun, Geoff Furnish, Tony Richardson. // // Copyright (C) 2004 Rafael Laboissiere // Copyright (C) 2004 Joao Cardoso // Copyright (C) 2004 Andrew Roach // Copyright (C) 2006 Andrew Ross // Copyright (C) 2006 Hazen Babcock // Copyright (C) 2001-2015 Alan W. Irwin // // // This file is part of PLplot. // // PLplot is free software; you can redistribute it and/or modify // it under the terms of the GNU Library General Public License as published // by the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // PLplot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Library General Public License for more details. // // You should have received a copy of the GNU Library General Public License // along with PLplot; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // // // #ifndef __PLPLOTP_H__ #define __PLPLOTP_H__ //-------------------------------------------------------------------------- // Select environment. Must be done before anything else. // // Basically we want the widest range of system services that are available. // Fortunately on many systems, that is the default. To get "everything", // one of the following must be defined, as appropriate: // // _GNU_SOURCE on Linux (default) // _OSF_SOURCE on OSF1 (default) // _HPUX_SOURCE on HP (not default) // _ALL_SOURCE on AIX (no idea) // // To see where these are set, do the following: // // cd /usr/include; grep SOURCE *.h | fgrep 'define ' // // and the file containing lots of these is the one you want (features.h on // Linux, standards.h on OSF1, etc). Follow the logic to see what needs to be // defined to get "everything", i.e. POSIX.*, XOPEN, etc. // // Note that for specific functionality, we test using autoconf. Still it's // best to stick to ANSI C, POSIX.1, and POSIX.2, in that order, for maximum // portability. //-------------------------------------------------------------------------- // HPUX - if this is no longer needed, please remove it #ifdef _HPUX #define _HPUX_SOURCE #endif // A/IX - if this is no longer needed, please remove it #ifdef _AIX #define _ALL_SOURCE #endif // Add others here as needed. //-------------------------------------------------------------------------- // Configuration settings // // Some of the macros set during configuration are described here. // // If HAVE_TERMIOS_H is set, we employ POSIX.1 tty terminal I/O. // // If STDC_HEADERS is defined, the system's libc is ANSI-compliant. // ANSI libc calls are used for: (a) setting up handlers to be called // before program exit (via the "atexit" call), and (b) for seek // operations. Again, the code is usable without these. An ANSI libc // should be available, given the requirement of an ANSI compiler. Some // reasons why not: (a) the vendor didn't supply a complete ANSI // environment, or (b) the ANSI libc calls are buggy, or (c) you ported // gcc to your system but not glibc (for whatever reason). Note: without // an ANSI C lib, if you ^C out of a program using one of the PLplot tek // drivers, your terminal may be left in a strange state. //-------------------------------------------------------------------------- #include "plConfig.h" #ifdef caddr_t #undef caddr_t #ifndef __USE_BSD typedef char * caddr_t; #endif #endif // System headers #include #include #include #include #include #ifdef PL_HAVE_UNISTD_H #include #endif #include // (AM) Define M_PI if the platform does not include it // (MSVC for instance) #if !defined ( M_PI ) #define M_PI 3.14159265358979323846 #endif // // Macros for file positioning. I tried switching to f[sg]etpos() because I // like the semantics better, but ran into the problem that fpos_t is not // always a base type (it may be a struct). This is a problem because the // metafile driver needs to write relative offsets into the file itself. So // instead we use f{seek,tell} at a low level but keep the f[sg]etpos // semantics using these macros. // #ifdef STDC_FPOS_T #undef STDC_FPOS_T #endif #ifdef STDC_FPOS_T #define FPOS_T fpos_t #define pl_fsetpos( a, b ) fsetpos( a, b ) #define pl_fgetpos( a, b ) fgetpos( a, b ) #else #define FPOS_T long #define pl_fsetpos( a, b ) fseek( a, *b, 0 ) #define pl_fgetpos( a, b ) ( -1L == ( *b = ftell( a ) ) ) #endif #include "pldll.h" // Include all externally-visible definitions and prototypes // plplot.h also includes some handy system header files #include "plplot.h" // plstream definition #include "plstrm.h" // If not including this file from inside of plcore.h, declare plsc #ifndef __PLCORE_H__ #ifdef __cplusplus extern "C" { #endif // extern PLStream PLDLLIMPORT *plsc; extern PLDLLIMPEXP_DATA( PLStream * ) plsc; #ifdef __cplusplus } #endif #include "pldebug.h" #endif //-------------------------------------------------------------------------- // Utility macros //-------------------------------------------------------------------------- #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif // Used to help ensure everything malloc'ed gets freed #define free_mem( a ) \ if ( a != NULL ) { free( (void *) a ); a = NULL; } // Allows multi-argument setup calls to not affect selected arguments #define plsetvar( a, b ) \ if ( b != PL_NOTSET ) a = b; // Lots of cool math macros #ifndef MAX #define MAX( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) ) #endif #ifndef MIN #define MIN( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) ) #endif #ifndef ABS #define ABS( a ) ( ( a ) < 0 ? -( a ) : ( a ) ) #endif #ifndef ROUND #define ROUND( a ) (PLINT) ( ( a ) < 0. ? ( ( a ) - .5 ) : ( ( a ) + .5 ) ) #endif #ifndef BETW #define BETW( ix, ia, ib ) ( ( ( ix ) <= ( ia ) && ( ix ) >= ( ib ) ) || ( ( ix ) >= ( ia ) && ( ix ) <= ( ib ) ) ) #endif #ifndef SSQR #define SSQR( a, b ) sqrt( ( a ) * ( a ) + ( b ) * ( b ) ) #endif #ifndef SIGN #define SIGN( a ) ( ( a ) < 0 ? -1 : 1 ) #endif #ifndef TRANSFORM #define TRANSFORM( x, y, xnew, ynew ) if ( plsc->coordinate_transform ) { plsc->coordinate_transform( ( x ), ( y ), ( xnew ), ( ynew ), plsc->coordinate_transform_data ); } else { *xnew = x; *ynew = y; } #endif // A coordinate value that should never occur #define PL_UNDEFINED -9999999 // Declarations for save string functions #ifdef PL_HAVE_SNPRINTF // In case only _snprintf is declared (as for Visual C++ and // Borland compiler toolset) we redefine the function names #ifdef _PL_HAVE_SNPRINTF #define snprintf _snprintf #define snscanf _snscanf #endif // _PL_HAVE_SNPRINTF #else // !PL_HAVE_SNPRINTF // declare dummy functions which just call the unsafe // functions ignoring the size of the string int plsnprintf( char *buffer, int n, PLCHAR_VECTOR format, ... ); int plsnscanf( PLCHAR_VECTOR buffer, int n, PLCHAR_VECTOR format, ... ); #define snprintf plsnprintf #define snscanf plsnscanf #endif // PL_HAVE_SNPRINTF //-------------------------------------------------------------------------- // Add in missing isnan / isinf functions on some platforms //-------------------------------------------------------------------------- #if defined ( PL__HAVE_ISNAN ) # define isnan _isnan # if defined ( _MSC_VER ) # include # endif #endif #if defined ( PL__HAVE_ISINF ) # define isinf _isinf #endif #if defined ( PL_HAVE_FINITE ) # define isfinite finite #endif #if defined ( PL__HAVE_FINITE ) # define isfinite _finite #endif // Note these replacements follow the old BSD convention and not // C99. In particular isinf does not distinguish +/- inf. #if !defined ( PL_HAVE_ISNAN ) # define isnan( x ) ( ( x ) != ( x ) ) #endif #if !defined ( PL_HAVE_ISINF ) # define isinf( x ) ( !isnan( x ) && isnan( x - x ) ) #endif #if !defined ( PL_HAVE_ISFINITE ) # define isfinite( x ) ( !isnan( x - x ) ) #endif // Check if C99 HUGE_VAL macro is available - if not then // define a replacement #ifndef HUGE_VAL #define HUGE_VAL ( 1.0 / 0.0 ) #endif //-------------------------------------------------------------------------- // PLPLOT control macros //-------------------------------------------------------------------------- // Some constants #define PL_MAXPOLY 256 // Max segments in polyline or polygon #define PL_NSTREAMS 100 // Max number of concurrent streams. #define PL_RGB_COLOR -1 // A hack #define TEXT_MODE 0 #define GRAPHICS_MODE 1 #ifndef PI #define PI 3.1415926535897932384 #endif // These define the virtual coordinate system used by the metafile driver. // Others are free to use it, or some variation, or define their own. // Note desktop monitors of reasonable quality typically have 0.25 mm spacing // between dots which corresponds to 4.0 dots per mm. The parameters here // roughly correspond to a 14" monitor at 1024x768 resolution, which should // work fine at other sizes/resolutions. The number of virtual dots per mm is // scaled by a factor of 32, with pixels scaled accordingly. The customary // x/y ratio of 4:3 is used. // #define PIXELS_X 32768 // Number of virtual pixels in x #define PIXELS_Y 24576 // Number of virtual pixels in x #define DPMM 4. // dots per mm #define VDPMM ( DPMM * 32 ) // virtual dots per mm #define LPAGE_X ( PIXELS_X / VDPMM ) // virtual page length in x in mm (256) #define LPAGE_Y ( PIXELS_Y / VDPMM ) // virtual page length in y in mm (192) // Constants that help to define ideal plspage arguments for devices #define PLPLOT_MM_PER_INCH 25.4 #define PLPLOT_POINTS_PER_INCH 72. #define PLPLOT_WIDTH_A4_MM 297. #define PLPLOT_HEIGHT_A4_MM 210. #define PLPLOT_WIDTH_A5_MM 210. #define PLPLOT_HEIGHT_A5_MM 148. // Devices with pixel units for sizes. // Adopt this default value as reasonable approximation for typical // LCD monitors, but note that the user can replace this default by // setting plsc->[xy]dpi values (e.g., by using the -dpi command-line // option or by calling plspage with non-zero first two arguments). #define PLPLOT_DEFAULT_PIXELS_PER_INCH 90. // These default pixel dimensions correspond to A5 size if actual // pixels per inch is PLPLOT_DEFAULT_PIXELS_PER_INCH #define PLPLOT_DEFAULT_WIDTH_PIXELS ( (int) ( PLPLOT_WIDTH_A5_MM * PLPLOT_DEFAULT_PIXELS_PER_INCH / PLPLOT_MM_PER_INCH ) ) #define PLPLOT_DEFAULT_HEIGHT_PIXELS ( (int) ( PLPLOT_HEIGHT_A5_MM * PLPLOT_DEFAULT_PIXELS_PER_INCH / PLPLOT_MM_PER_INCH ) ) // Devices with real world units for sizes. // N.B. these devices normally use fixed values of units per inch, // i.e., they ignore any attempt by users to set plsc->[xy]dpi values // (e.g., by using the -dpi command-line option or by calling plspage // with non-zero first two arguments). // 1. Devices with mm units for sizes. // These default mm dimensions correspond to A4 size. #define PLPLOT_DEFAULT_WIDTH_MM ( (int) ( PLPLOT_WIDTH_A4_MM ) #define PLPLOT_DEFAULT_HEIGHT_MM ( (int) ( PLPLOT_HEIGHT_A4_MM ) // 2. Devices with points (= 1/72 inch) units for sizes. // These default points dimensions correspond to A4 size. #define PLPLOT_DEFAULT_WIDTH_POINTS ( (int) ( PLPLOT_WIDTH_A4_MM * PLPLOT_POINTS_PER_INCH / PLPLOT_MM_PER_INCH ) ) #define PLPLOT_DEFAULT_HEIGHT_POINTS ( (int) ( PLPLOT_HEIGHT_A4_MM * PLPLOT_POINTS_PER_INCH / PLPLOT_MM_PER_INCH ) ) // This defines the first argument of the plRotPhy invocation that is made // in a number of device drivers (e.g., found in ps.c // and pstex.c) to rotate them "permanently" from portrait mode to non- // portrait mode. ORIENTATION of 1 corresponds to seascape mode (90 deg // clockwise rotation from portrait). This is the traditional value // effectively used in all older versions of PLplot. ORIENTATION of 3 // corresponds to landscape mode (90 deg *counter*-clockwise rotation from // portrait) which is the new default non-portrait orientation. #define ORIENTATION 3 // Switches for state function call. #define PLSTATE_WIDTH 1 // pen width #define PLSTATE_COLOR0 2 // change to color in cmap 0 #define PLSTATE_COLOR1 3 // change to color in cmap 1 #define PLSTATE_FILL 4 // set area fill to a standard pattern #define PLSTATE_CMAP0 5 // change to cmap 0 #define PLSTATE_CMAP1 6 // change to cmap 1 #define PLSTATE_CHR 7 // change character height #define PLSTATE_SYM 8 // change symbol size #define PLSTATE_EOFILL 9 // change to even odd fill rule // Enum for flagging the render status of PLplot enum { AT_BOP, DRAWING, AT_EOP }; // Bit switches used in the driver interface #define PLDI_MAP 0x01 #define PLDI_ORI 0x02 #define PLDI_PLT 0x04 #define PLDI_DEV 0x08 // Default size for family files, in KB. #ifndef PL_FILESIZE_KB #define PL_FILESIZE_KB 1000 #endif // Font file names. #define PLPLOT5_FONTS #ifdef PLPLOT5_FONTS #define PL_XFONT "plxtnd5.fnt" #define PL_SFONT "plstnd5.fnt" #else #define PL_XFONT "plxtnd4.fnt" #define PL_SFONT "plstnd4.fnt" #endif //-------------------------------------------------------------------------- // The following environment variables are defined: // // PLPLOT_BIN # where to find executables // PLPLOT_LIB # where to find library files (fonts, maps, etc) // PLPLOT_TCL # where to find tcl scripts // // PLPLOT_HOME # basename of plplot hierarchy // // search order: // 1) the most specific possible locators, one of // $(PLPLOT_BIN) // $(PLPLOT_LIB) // $(PLPLOT_TCL) // as appropriate // // 2) the current directory // // 3) one of $(PLPLOT_HOME)/bin // $(PLPLOT_HOME)/lib // $(PLPLOT_HOME)/tcl // as appropriate // // 4) as appropriate, the compile-time (Makefile) // BIN_DIR, LIB_DIR, TCL_DIR // // 8 Jun 1994 mj olesen ([email protected]) // // Other notes: // // In addition to the directories above, the following are also used: // // Lib file search path: PLLIBDEV (see plctrl.c). This is checked last, // and is a system-dependent hardwired location. // // Tcl search path: $HOME/tcl is searched before the install location, // TCL_DIR. //-------------------------------------------------------------------------- #define PLPLOT_BIN_ENV "PLPLOT_BIN" #define PLPLOT_LIB_ENV "PLPLOT_LIB" #define PLPLOT_TCL_ENV "PLPLOT_TCL" #define PLPLOT_HOME_ENV "PLPLOT_HOME" // Maximum size for path strings in the plplot code #define PLPLOT_MAX_PATH 1024 // // Some stuff that is included (and compiled into) plsym.h // Other modules might want this, so we will "extern" it // // #ifndef __PLSYM_H__ typedef struct { unsigned int Hershey; PLUNICODE Unicode; char Font; } Hershey_to_Unicode_table; extern int number_of_entries_in_hershey_to_unicode_table; extern Hershey_to_Unicode_table hershey_to_unicode_lookup_table[]; #endif // Greek character translation array (defined in plcore.c) extern const char plP_greek_mnemonic[]; //-------------------------------------------------------------------------- // Function Prototypes // // These typically should not be called directly by the user. //-------------------------------------------------------------------------- #ifdef __cplusplus extern "C" { #endif // Number of elements in the affine vector representation of the affine // transformation matrix. #define NAFFINE 6 // Returns affine identity matrix PLDLLIMPEXP void plP_affine_identity( PLFLT *affine_vector ); // Translate new coordinate system axes relative to the old. PLDLLIMPEXP void plP_affine_translate( PLFLT *affine_vector, PLFLT xtranslate, PLFLT ytranslate ); // Scale new coordinate system axes relative to the old. PLDLLIMPEXP void plP_affine_scale( PLFLT *affine_vector, PLFLT xscale, PLFLT yscale ); // Rotate new coordinate system axes relative to the old. // angle is in degrees. PLDLLIMPEXP void plP_affine_rotate( PLFLT *affine_vector, PLFLT angle ); // Skew new X coordinate axis relative to the old. // angle is in degrees. PLDLLIMPEXP void plP_affine_xskew( PLFLT *affine_vector, PLFLT angle ); // Skew new Y coordinate axis relative to the old. // angle is in degrees. PLDLLIMPEXP void plP_affine_yskew( PLFLT *affine_vector, PLFLT angle ); // Multiply two affine transformation matrices to form a third. // // A = B * C // // PLDLLIMPEXP void plP_affine_multiply( PLFLT *affine_vectorA, PLFLT_VECTOR affine_vectorB, PLFLT_VECTOR affine_vectorC ); // Determines interval between numeric labels void pldtik( PLFLT vmin, PLFLT vmax, PLFLT *tick, PLINT *nsubt, PLBOOL ld ); // Writes numeric labels on side(s) of box in custom locations void label_box_custom( PLCHAR_VECTOR xopt, PLINT n_xticks, PLFLT_VECTOR xticks, PLCHAR_VECTOR yopt, PLINT n_yticks, PLFLT_VECTOR yticks ); // Determine factor to convert date / time in seconds to more natural // units void pldtfac( PLFLT vmin, PLFLT vmax, PLFLT *factor, PLFLT *tstart ); // Determines precision of box labels void pldprec( PLFLT vmin, PLFLT vmax, PLFLT tick, PLINT lf, PLINT *mode, PLINT *prec, PLINT digmax, PLINT *scale ); // Draws a polyline within the clip limits. void plP_pllclp( PLINT *x, PLINT *y, PLINT npts, PLINT xmin, PLINT xmax, PLINT ymin, PLINT ymax, void ( *draw )( short *, short *, PLINT ) ); // Fills a polygon within the clip limits. void plP_plfclp( PLINT *x, PLINT *y, PLINT npts, PLINT xmin, PLINT xmax, PLINT ymin, PLINT ymax, void ( *draw )( short *, short *, PLINT ) ); // Clip a polygon to the 3d bounding plane int plP_clip_poly( int Ni, PLFLT *Vi[3], int axis, PLFLT dir, PLFLT offset ); // Get clipped endpoints int plP_clipline( PLINT *p_x1, PLINT *p_y1, PLINT *p_x2, PLINT *p_y2, PLINT xmin, PLINT xmax, PLINT ymin, PLINT ymax ); // Stores hex digit value into FCI (font characterization integer). void plP_hex2fci( unsigned char hexdigit, unsigned char hexpower, PLUNICODE *pfci ); // Retrieves hex digit value from FCI (font characterization integer). PLDLLIMPEXP void plP_fci2hex( PLUNICODE fci, unsigned char *phexdigit, unsigned char hexpower ); // Pattern fills in software the polygon bounded by the input points. PLDLLIMPEXP void plfill_soft( short *x, short *y, PLINT npts ); // In case of an abort this routine is called. It just prints out an // error message and tries to clean up as much as possible. PLDLLIMPEXP void plexit( PLCHAR_VECTOR errormsg ); // Just a front-end to exit(). void pl_exit( void ); // A handy way to issue warnings, if need be. PLDLLIMPEXP void plwarn( PLCHAR_VECTOR errormsg ); // Same as plwarn(), but appends ", aborting plot" to the error message PLDLLIMPEXP void plabort( PLCHAR_VECTOR errormsg ); // Loads either the standard or extended font. void plfntld( PLINT fnt ); // Release memory for fonts. void plfontrel( void ); // A replacement for strdup(), which isn't portable. PLDLLIMPEXP char * plstrdup( PLCHAR_VECTOR src ); // Bin up cmap 1 space and assign colors to make inverse mapping easy. PLDLLIMPEXP void plcmap1_calc( void ); // Draws a slanting tick at position (mx,my) (measured in mm) of // vector length (dx,dy). void plstik( PLFLT mx, PLFLT my, PLFLT dx, PLFLT dy ); // Prints out a "string" at reference position with physical coordinates // (refx,refy). void plstr( PLINT base, PLFLT *xform, PLINT refx, PLINT refy, PLCHAR_VECTOR string ); // Draws a tick parallel to x. void plxtik( PLINT x, PLINT y, PLINT below, PLINT above ); // Draws a tick parallel to y. void plytik( PLINT x, PLINT y, PLINT left, PLINT right ); // Driver interface filter -- // passes all coordinates through a variety of filters. PLDLLIMPEXP void difilt( PLINT *, PLINT *, PLINT, PLINT *, PLINT *, PLINT *, PLINT * ); // Transforms the clipping region coordinates as necessary // based on the current plot orientation, etc. PLDLLIMPEXP void difilt_clip( PLINT *, PLINT * ); // Calculate scale of font size and scale of magnitude of vertical // offset associated with superscripts and subscripts. PLDLLIMPEXP void plP_script_scale( PLBOOL ifupper, PLINT *level, PLFLT *old_scale, PLFLT *scale, PLFLT *old_offset, PLFLT *offset ); // Driver draws text void plP_text( PLINT base, PLFLT just, PLFLT *xform, PLINT x, PLINT y, PLINT refx, PLINT refy, PLCHAR_VECTOR string ); // Save LC_NUMERIC locale string, then set "C" locale to protect // parts of PLplot which absolutely demand the LC_NUMERIC "C" locale. PLDLLIMPEXP char * plsave_set_locale( void ); // Restore LC_NUMERIC locale that was determined by plsave_set_locale. PLDLLIMPEXP void plrestore_locale( char * save_lc_numeric_locale ); // Writes the Hershey symbol "ch" centred at the physical coordinate (x,y). void plhrsh( PLINT ch, PLINT x, PLINT y ); // where should structure definitions that must be seen by drivers and core source files, be? // structure to be used by plcore.c and anydriver.c, related to plP_text() typedef struct { // Indicates the type of text stored in the structure. This flag // is used by the plot metafiles to correctly store and then render // the contents. enum { PL_STRING_TEXT, PL_STRING_SYMBOL } text_type; // Positioning settings PLINT base; // ref point at base(1) or center(0) of text. Currently plplot only use 0 PLFLT just; // continuos justification, 0 left, 0.5 center, 1 right PLFLT *xform; // transformation (rotation) matrix // raw reference point--after any transformation PLINT x; PLINT y; // processed ref. point--after justification, displacement, etc, processing PLINT refx; PLINT refy; // font face OPTIONALLY used for rendering hershey codes char font_face; // The following 3 fields are used by the alternative text handling pathway. // The alternative text handling pathway allows the driver to process // each character individually for unicode font handling // See drivers/cairo.h for details about how this works. PLUNICODE n_fci; // font storage PLUNICODE n_char; // character storage PLINT n_ctrl_char; // control character // Used by plsym to store a unicode character for use by plfreetype PLUNICODE unicode_char; // an int to hold either a Hershey, ASC-II, or Unicode value for plsym calls // Used to store a processed unicode string. Used by plsym and // text rendering by the driver PLUNICODE *unicode_array; // a pointer to an array of ints holding either a Hershey, ASC-II, or Unicode value for cached plsym unsigned short unicode_array_len; // Non-unicode strings and unprocessed string in the unicode case const char *string; // text to draw PLINT symbol; // plot symbol to draw }EscText; // // structure that contains driver specific information, to be used by // plargs.c and anydriver.c, related to plParseDrvOpts() and plHelpDrvOpts() // typedef struct { PLCHAR_VECTOR opt; // a string with the name of the option PLINT type; // the type of the variable to be set, see bellow the available types void *var_ptr; // a pointer to the variable to be set PLCHAR_VECTOR hlp_msg; // help message of the option } DrvOpt; // the available variable types, DrvOpt.type, for driver specific options enum { DRV_INT, DRV_FLT, DRV_STR }; // parse driver specific options, as in -drvopt