/*--------------------------------------------------------------------
 *
 *	Copyright (c) 2009-2026 by the GMT Team (https://www.generic-mapping-tools.org/team.html)
 *	See LICENSE.TXT file for copying and redistribution conditions.
 *
 *	This program is free software; you can redistribute it and/or modify
 *	it under the terms of the GNU Lesser General Public License as published by
 *	the Free Software Foundation; version 3 or any later version.
 *
 *	This program 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 Lesser General Public License for more details.
 *
 *	Contact info: www.generic-mapping-tools.org
 *--------------------------------------------------------------------*/
/*	PSL_strings.h <auto-generated>
 *
 * The three former include files PSL_label.ps, PSL_text.ps, and PSL_prologue.ps
 * are now represented as three very long string literals instead.  However,
 * they are still the original sources and any edits should be made to them.
 */

/* Placing content of PSL_label.ps */

static char *PSL_label_str =
"%-----------------------------------------------------------------------------\n"
"%-	PS routines for handling contour labels and clipping of\n"
"%-	contour lines going through labels.\n"
"%-\n"
"%-	There are two parts.  First is something straight out of\n"
"%-	the Adobe Cookbook for placing text along a curved line.\n"
"%-	The second part is the functions that assist in finding\n"
"%-	out where labels are placed and setting clip paths etc.\n"
"%-----------------------------------------------------------------------------\n"
"\n"
"/PSL_pathtextdict 26 dict def			% Local storage for the procedure PSL_pathtext.\n"
"\n"
"/PSL_pathtext					% PSL_pathtext'' will place a string\n"
"  {PSL_pathtextdict begin			% of text along any path. It takes\n"
"    /ydepth exch def                            % a string and starting offset\n"
"    /textheight exch def			% distance from the beginning of\n"
"    /just exch def				% the path as its arguments. Note\n"
"    /offset exch def				% that PSL_pathtext assumes that a\n"
"    /str exch def				% path has already been defined\n"
"						% and after it places the text\n"
"						% along the path, it clears the\n"
"						% current path like the ``stroke''\n"
"						% and ``fill'' operators; it also\n"
"						% assumes that a font has been\n"
"						% set. ``pathtext'' begins placing\n"
"						% the characters along the current\n"
"						% path, starting at the offset\n"
"						% distance and continuing until\n"
"						% either the path length is\n"
"						% exhausted or the entire string\n"
"						% has been printed, whichever\n"
"						% occurs first. The results will\n"
"						% be more effective when a small\n"
"						% point size font is used with\n"
"						% sharp curves in the path.\n"
"						\n"
"\n"
"    /pathdist 0 def				% Initialize the distance we have\n"
"						% travelled along the path.\n"
"    /setdist offset def				% Initialize the distance we have\n"
"						% covered by setting characters.\n"
"    /charcount 0 def				% Initialize the character count.\n"
"    /justy just 4 idiv textheight mul 2 div neg ydepth sub def % Compute the y-shift\n"
"    V flattenpath				% Reduce the path to a series of\n"
"						% straight line segments. The\n"
"						% characters will be placed along\n"
"						% the line segments in the\n"
"						% ``linetoproc.''\n"
"	{movetoproc} {linetoproc}		% The basic strategy is to process\n"
"	{curvetoproc} {closepathproc}		% the segments of the path,\n"
"	pathforall				% keeping a running total of the\n"
"						% distance we have travelled so\n"
"						% far (pathdist). We also keep\n"
"						% track of the distance taken up\n"
"						% by the characters that have been\n"
"						% set so far (setdist). When the\n"
"						% distance we have travelled along\n"
"						% the path is greater than the\n"
"						% distance taken up by the set\n"
"						% characters, we are ready to set\n"
"						% the next character (if there are\n"
"						% any left to be set). This\n"
"						% process continues until we have\n"
"						% exhausted the full length of the\n"
"						% path.\n"
"    U N						% Clear the current path.\n"
"    end\n"
"  } def\n"
"\n"
"PSL_pathtextdict begin\n"
"/movetoproc					% ``movetoproc'' is executed when\n"
"  { /newy exch def /newx exch def		% a moveto component has been\n"
"						% encountered in the pathforall\n"
"						% operation.\n"
"    /firstx newx def /firsty newy def		% Remember the ``first point'' in\n"
"						% the path so that when we get a\n"
"						% ``closepath'' component we can\n"
"						% properly handle the text.\n"
"    /ovr 0 def\n"
"    newx newy transform\n"
"    /cpy exch def /cpx exch def			% Explicitly keep track of the\n"
"						% current position in device\n"
"						% space.\n"
"  } def\n"
"\n"
"/linetoproc					% ``linetoproc'' is executed when\n"
"						% a lineto component has been\n"
"						% encountered in the pathforall\n"
"						% operation.\n"
"  { /oldx newx def /oldy newy def		% Update the old point.\n"
"    /newy exch def /newx exch def		% Get the new point.\n"
"    /dx newx oldx sub def\n"
"    /dy newy oldy sub def\n"
"    /dist dx dup mul dy dup mul add sqrt def	% Calculate the distance between\n"
"						% the old and the new point.\n"
"    dist 0 ne\n"
"    { /dsx dx dist div ovr mul def		% dsx and dsy are used to update\n"
"      /dsy dy dist div ovr mul def		% the current position to be just\n"
"						% beyond the width of the previous\n"
"						% character.\n"
"      oldx dsx add oldy dsy add transform\n"
"      /cpy exch def /cpx exch def		% Update the current position.\n"
"      /pathdist pathdist dist add def		% Increment the distance we have\n"
"						% travelled along the path.\n"
"      {setdist pathdist le			% Keep setting characters along\n"
"						% this path segment until we have\n"
"						% exhausted its length.\n"
"	  {charcount str length lt		% As long as there are still\n"
"	      {setchar} {exit} ifelse}		% characters left in the string,\n"
"						% set them.\n"
"	  { /ovr setdist pathdist sub def		% Keep track of how much we have\n"
"	    exit}				% overshot the path segment by\n"
"	  ifelse					% setting the previous character.\n"
"						% This enables us to position the\n"
"						% origin of the following\n"
"						% characters properly on the path.\n"
"      } loop\n"
"    } if\n"
"  } def\n"
"\n"
"/curvetoproc					% ``curvetoproc'' is executed when\n"
"  { (ERROR: No curveto's after flattenpath!)	% a curveto component has been\n"
"    print					% encountered in the pathforall\n"
"  } def						% operation. It prints an error\n"
"						% message since there shouldn't be\n"
"						% any curveto's in a path after\n"
"						% the flattenpath operator has\n"
"						% been executed.\n"
"\n"
"/closepathproc					% ``closepathproc'' is executed\n"
"  {firstx firsty linetoproc			% when a closepath component has\n"
"    firstx firsty movetoproc			% been encountered in the\n"
"  } def						% pathforall operation. It\n"
"						% simulates the action of the\n"
"						% operator ``closepath'' by\n"
"						% executing ``linetoproc'' with\n"
"						% the coordinates of the most\n"
"						% recent ``moveto'' and then\n"
"						% executing ``movetoproc'' to the\n"
"						% same point.\n"
"\n"
"/setchar					% ``setchar'' sets the next\n"
"						% character in the string along\n"
"						% the path and then updates the\n"
"						% amount of path we have\n"
"						% exhausted.\n"
"  { charcount 1 add str length lt		% Check if at least 2 chars remain\n"
"    {str charcount get 64 eq str charcount 1 add get 126 eq and} {false} ifelse\n"
"    {	% Found @~ escape: skip it, toggle font, no rendering\n"
"      /charcount charcount 2 add def\n"
"      /psl_ct_sym psl_ct_sym not def\n"
"      psl_ct_sym {\n"
"        /psl_ct_origfont currentfont def\n"
"        /Symbol findfont PSL_get_fontsize scalefont setfont\n"
"      } {\n"
"        psl_ct_origfont setfont\n"
"      } ifelse\n"
"    }\n"
"    {	% Normal character rendering\n"
"      /char str charcount 1 getinterval def\n"
"      /charcount charcount 1 add def\n"
"      /charwidth char stringwidth pop def\n"
"      V cpx cpy itransform T			% Translate to the current\n"
"						% position in user space.\n"
"        dy dx atan R				% Rotate the x-axis to coincide\n"
"						% with the current segment.\n"
"        0 justy M\n"
"        PSL_font_F {  % Show text normally, if requested\n"
"          char show}\n"
"        if\n"
"        PSL_font_FO { % Fill first then outline, if requested\n"
"          currentpoint N M V char true charpath fs U V char false charpath S U char E 0 G\n"
"        } if\n"
"        PSL_font_OF { % Outline text then fill, if requested\n"
"          currentpoint N M V char false charpath S U V char true charpath fs U char E 0 G\n"
"        } if\n"
"        0 justy neg G currentpoint transform\n"
"        /cpy exch def /cpx exch def		% Update the current position\n"
"      						% before we restore ourselves to\n"
"						% the untransformed state.\n"
"      U /setdist setdist charwidth add def	% Increment the distance we have\n"
"    } ifelse					% covered by setting characters.\n"
"  } def\n"
"end\n"
"\n"
"% PSL LABEL CLIP FUNCTIONS\n"
"\n"
"% Two main functions deals with label placement and clipping:\n"
"% PSL_curved_path_labels: 	handles texts that must follow curved baselines\n"
"% PSL_straight_path_labels:	handles texts that have straight baselines\n"
"%\n"
"% Both functions assume that several variables have been predefined:\n"
"%\n"
"% First we have these two constant settings for all text boxes:\n"
"%\n"
"%   PSL_setboxpen  Function that sets the text box pen attributes (width, texture, color)\n"
"%   PSL_setboxrgb  Function that sets the opaque text box color\n"
"%\n"
"% Then several arrays are placed.  Since a set of several lines segments may each\n"
"% have many labels along them, we end up with these variables:\n"
"%\n"
"%   PSL_n_paths		Total number of segments\n"
"%   PSL_path_x		x coordinates of the paths (all concatenated one after another)\n"
"%   PSL_path_y		y coordinates of the paths (all concatenated one after another)\n"
"%   PSL_path_n		Array with number of points per segment\n"
"%   PSL_label_str  	Array with all the labels for all segments\n"
"%   PSL_label_n		Array with number of labels per segment\n"
"%   PSL_angle		The annotation angle for each label\n"
"%\n"
"% PSL_curved_path_labels expects those labels to be placed along several\n"
"% lines and it needs the node numbers where to place text:\n"
"%\n"
"% PSL_node	Array with (x,y) node number of label position\n"
"%\n"
"% PSL_straight_path_labels are simpler and instead expects\n"
"%\n"
"% PSL_txt_x	(x,y) coordinates of the location of the m labels\n"
"% PSL_txt_y\n"
"\n"
"/PSL_set_label_heights\n"
"{	% Create array PSL_heights with full label heights\n"
"  /PSL_n_labels_minus_1 PSL_n_labels 1 sub def	% Upper limit in loop over labels\n"
"  /PSL_heights PSL_n_labels array def		% Create array with text heights\n"
"  0 1 PSL_n_labels_minus_1			% Loop psl_k = 0 < PSL_n_labels\n"
"  { /psl_k exch def				% Current label index psl_k\n"
"    /psl_label PSL_label_str psl_k get def	% Current text label\n"
"    PSL_label_font psl_k get cvx exec		% Get and set this label's font attributes\n"
"    psl_label sH /PSL_height edef		% Compute the height of this string\n"
"    PSL_heights psl_k PSL_height put		% Store it in the array\n"
"  } for\n"
"} def\n"
"\n"
"% Curved Baseline Text Placement Functions\n"
"\n"
"/PSL_curved_path_labels\n"
"{ /psl_bits exch def				% 4 on/of bit settings as indicated below\n"
"  /PSL_placetext psl_bits 2 and 2 eq def		% true to place text, false to just make space\n"
"  /PSL_clippath psl_bits 4 and 4 eq def		% false inactive, true creates clippath for labels\n"
"  /PSL_strokeline false def			% true draws line, false skips\n"
"  /PSL_fillbox psl_bits 128 and 128 eq def		% true to paint box opaque before placing text, false gives transparent box\n"
"  /PSL_drawbox psl_bits 256 and 256 eq def		% true to draw box outline before placing text, false gives no outline\n"
"  /PSL_font_F  psl_bits 1536 and 0 eq def     % true to paint regular text\n"
"  /PSL_font_FO psl_bits 512 and 512 eq def    % true to fill text first then draw outline\n"
"  /PSL_font_OF psl_bits 1024 and 1024 eq def  % true to draw outline of text first then fill inside\n"
"  /PSL_n_paths1 PSL_n_paths 1 sub def		% one less is the upper limit in for loop over the paths\n"
"  /PSL_usebox PSL_fillbox PSL_drawbox or def	% true if we need box outline for fill or stroke or both\n"
"\n"
"  PSL_clippath {clipsave N clippath} if		% Bracket with clipsave/cliprestore and start clip path\n"
"  /psl_k 0 def\n"
"  /psl_p 0 def\n"
"  0 1 PSL_n_paths1\n"
"  { /psl_kk exch def						% Index into the PSL_n PSL_m arrays\n"
"    /PSL_n PSL_path_n  psl_kk get def				% Get the number of points in this line segment\n"
"    /PSL_m PSL_label_n psl_kk get def				% Get the number of labels for this line segment\n"
"    /PSL_x PSL_path_x psl_k PSL_n getinterval def		% Get the subset that is the current line segment x-coordinates\n"
"    /PSL_y PSL_path_y psl_k PSL_n getinterval def		% Get the subset that is the current line segment y-coordinates\n"
"    /PSL_node_tmp PSL_label_node psl_p PSL_m getinterval def	% Get the subset of node values for current line segment\n"
"    /PSL_angle_tmp PSL_label_angle psl_p PSL_m getinterval def	% Get the subset of angle values for current line segment\n"
"    /PSL_str_tmp PSL_label_str psl_p PSL_m getinterval def		% Get the subset of string values for current line segment\n"
"    /PSL_fnt_tmp PSL_label_font psl_p PSL_m getinterval def		% Get the subset of font settings for current line segment\n"
"    PSL_curved_path_label					% Operate on this segment only\n"
"    /psl_k psl_k PSL_n add def					% Go to next segment start index for path\n"
"    /psl_p psl_p PSL_m add def					% Go to next segment start index for nodes\n"
"  } for  % The loop over segments\n"
"  			\n"
"  PSL_clippath {PSL_eoclip} if N			% Activate clip path and return\n"
"\n"
"} def\n"
"\n"
"/PSL_curved_path_label\n"
"{	% Deals with a single line segment and its labels\n"
"  /PSL_n1 PSL_n 1 sub def	% one less is the upper limit in for loops\n"
"  /PSL_m1 PSL_m 1 sub def	% same\n"
"\n"
"  PSL_CT_calcstringwidth	% Calculate the width of each label string\n"
"  PSL_CT_calclinedist		% Calculate along-track distances\n"
"  PSL_CT_excludelabels		% Possibly eliminate labels outside of line domain\n"
"  PSL_CT_addcutpoints		% Expand path to include the cut points\n"
"\n"
"% Now we have the final xx/yy array and we are ready to simply lay down the lines\n"
"% and place the text along the line where there are labels.  We will use the\n"
"% new array PSL_xp/yp to store the final points prior to use\n"
"\n"
"  /PSL_nn1 PSL_nn 1 sub def		% End index in for loop\n"
"  /n 0 def				% Toggle: 0 means line, 1 means text\n"
"  /k 0 def				% Index of the current text string\n"
"  /j 0 def				% Output point number counter\n"
"  /PSL_seg 0 def			% Line segment number\n"
"  /PSL_xp PSL_nn array def\n"
"  /PSL_yp PSL_nn array def\n"
"  PSL_xp 0 PSL_xx 0 get put		% Place first point in array\n"
"  PSL_yp 0 PSL_yy 0 get put\n"
"  1 1 PSL_nn1				% Loop over rest of points\n"
"  { /i exch def				% Index into PSL_xx/yy arrays\n"
"    /node_type PSL_kind i get def	% Check what kind of point the current point is\n"
"    /j j 1 add def			% Update point count\n"
"    PSL_xp j PSL_xx i get put		% Add this point to the path\n"
"    PSL_yp j PSL_yy i get put\n"
"    node_type 1 eq			% If this is a cut point we either stroke or place text\n"
"    {n 0 eq		% n is 0 so this is the strokable segment\n"
"      {PSL_CT_drawline}\n"
"      {   % here, n = 1 so this is the segment along which text should be placed\n"
"        PSL_CT_reversepath\n"
"	      PSL_CT_textline}\n"
"      ifelse		% Reverse path if needed to place text correctly\n"
"      /j 0 def\n"
"      PSL_xp j PSL_xx i get put		% Place new first point in array\n"
"      PSL_yp j PSL_yy i get put\n"
"    } if\n"
"  } for\n"
"  n 0 eq {PSL_CT_drawline} if	% Finish off the last line segment\n"
"\n"
"} def\n"
"\n"
"/PSL_CT_textline\n"
"{ PSL_fnt k get cvx exec		% Get and set this label's font attributes\n"
"  /PSL_height PSL_heights k get def	% Recall the height of this text\n"
"  PSL_placetext	{PSL_CT_placelabel} if	% If we want to place the text\n"
"  PSL_clippath {PSL_CT_clippath} if\n"
"  /n 0 def /k k 1 add def		% Set n back to 0, goto next label\n"
"} def\n"
"\n"
"/PSL_CT_calcstringwidth			% Calculate the width of each label string\n"
"{ /PSL_width_tmp PSL_m array def	% Assign space for distance\n"
"  0 1 PSL_m1\n"
"  { /i exch def\n"
"    PSL_fnt_tmp i get cvx exec					% Get and set this label's font attributes\n"
"    PSL_width_tmp i PSL_str_tmp i get PSL_label_sw put	% Compute width and store in the array\n"
"  } for\n"
"} def\n"
"\n"
"/PSL_CT_calclinedist			% Calculate the distance along the line\n"
"{ /PSL_newx PSL_x 0 get def\n"
"  /PSL_newy PSL_y 0 get def\n"
"  /dist 0.0 def			% Cumulative distance at first point is 0\n"
"  /PSL_dist PSL_n array def	% Assign array space for distance\n"
"  PSL_dist 0 0.0 put		% Distances start at 0 and the 'th point\n"
"  1 1 PSL_n1			% Loop over the remaining points\n"
"  { /i exch def\n"
"    /PSL_oldx PSL_newx def\n"
"    /PSL_oldy PSL_newy def\n"
"    /PSL_newx PSL_x i get def\n"
"    /PSL_newy PSL_y i get def\n"
"    /dx PSL_newx PSL_oldx sub def\n"
"    /dy PSL_newy PSL_oldy sub def\n"
"    /dist dist dx dx mul dy dy mul add sqrt add def\n"
"    PSL_dist i dist put\n"
"  } for\n"
"} def\n"
"\n"
"% Some labels (in particular first and last per segment) may be too long\n"
"% to actually fit inside the length of the line.  We precalculate the\n"
"% start and end distances for each label and those that exceed the length\n"
"% of the line cannot be plotted and are thus skipped.  The surviving labels\n"
"% and their information is copied to the final PSL arrays\n"
"\n"
"/PSL_CT_excludelabels\n"
"{ /k 0 def				% Current cut point\n"
"  /PSL_width PSL_m array def		% New array of distances\n"
"  /PSL_angle PSL_m array def		% New array of angles\n"
"  /PSL_node PSL_m array def		% New array of nodes\n"
"  /PSL_str PSL_m array def		% New array of strings\n"
"  /PSL_fnt PSL_m array def		% New array of fonts\n"
"  /lastdist PSL_dist PSL_n1 get def	% Length of line \n"
"  0 1 PSL_m1				% For each of the m labels\n"
"  { /i exch def						% Index for label distance\n"
"    /dist PSL_dist PSL_node_tmp i get get def		% Recall the distance to this label center\n"
"    /halfwidth PSL_width_tmp i get 2 div PSL_gap_x add def	% Set the halfwidth + gap distance\n"
"    /L_dist dist halfwidth sub def			% Distance at beginning of label gap\n"
"    /R_dist dist halfwidth add def			% Distance at the end of label gap\n"
"    L_dist 0 gt R_dist lastdist lt and		% Yes, label is inside line ends\n"
"    { % These are the labels we will use\n"
"      PSL_width k PSL_width_tmp i get put	% Copy over width\n"
"      PSL_node k PSL_node_tmp i get put		% Copy over node\n"
"      PSL_angle k PSL_angle_tmp i get put	% Copy over angle\n"
"      PSL_str k PSL_str_tmp i get put		% Copy over text\n"
"      PSL_fnt k PSL_fnt_tmp i get put		% Copy over font\n"
"      /k k 1 add def\n"
"    } if\n"
"  } for\n"
"  /PSL_m k def	% New number of labels\n"
"  /PSL_m1 PSL_m 1 sub def\n"
"} def\n"
"\n"
"% Initialize an array with all the original line points plus the set of 2*m\n"
"% points at the transition from line to labelspace at each label\n"
"% At the end of this section, the PSL_xx/yy array will be the array to use.\n"
"\n"
"/PSL_CT_addcutpoints\n"
"{ /k 0 def				% Current cut point\n"
"  /PSL_nc PSL_m 2 mul 1 add def		% 2*m points + one last acting as infinity\n"
"  /PSL_cuts PSL_nc array def		% The array of distances to each cut\n"
"  /PSL_nc1 PSL_nc 1 sub def		% One less to use in for loop limits\n"
"  0 1 PSL_m1				% For each of the m labels\n"
"  { /i exch def						% Index for label distance\n"
"    /dist PSL_dist PSL_node i get get def		% Recall the distance to this label center\n"
"    /halfwidth PSL_width i get 2 div PSL_gap_x add def	% Set the halfwidth + gap distance\n"
"    PSL_cuts k dist halfwidth sub put			% Distance at beginning of label gap\n"
"    /k k 1 add def					% Was at start, now go to end distance node\n"
"    PSL_cuts k dist halfwidth add put			% Distance at the end of label gap\n"
"    /k k 1 add def					% Was at end, move to next\n"
"  } for\n"
"  PSL_cuts k 100000.0 put				% Last cut has ~infinite distance\n"
"\n"
"  /PSL_nn PSL_n PSL_m 2 mul add def	% The total path will be 2*m points longer\n"
"  /PSL_xx PSL_nn array def		% Assign new space for x and y\n"
"  /PSL_yy PSL_nn array def\n"
"  /PSL_kind PSL_nn array def		% 0 = ordinary point, 1 = added point for label gap\n"
"  /j 0 def				% Index for new track array\n"
"  /k 0 def				% Index for current cut distance\n"
"  /dist 0.0 def				% Current distance along track, starting at zero\n"
"  0 1 PSL_n1				% Loop over every original line point\n"
"  { /i exch def				% Index into current point on original line xy array\n"
"    /last_dist dist def			% Update distance to last point (initially zero)\n"
"    /dist PSL_dist i get def		% Distance to current point\n"
"    k 1 PSL_nc1				% Loop over remaining cuts (starting with all)\n"
"    { /kk exch def			% Index into current cut distance\n"
"      /this_cut PSL_cuts kk get def	% Distance to start of this label gap\n"
"      dist this_cut gt			% Oh, oh, we just stepped over a cut point\n"
"      { /ds dist last_dist sub def	% Change in distance\n"
"	/f ds 0.0 eq {0.0} {dist this_cut sub ds div} ifelse def	% Get fractional change in distance\n"
"	/i1 i 0 eq {0} {i 1 sub} ifelse def\n"
"	PSL_xx j PSL_x i get dup PSL_x i1 get sub f mul sub put	% Calc (x,y) at label start (or stop) point\n"
"	PSL_yy j PSL_y i get dup PSL_y i1 get sub f mul sub put\n"
"	PSL_kind j 1 put		% Set PSL_kind to 1 since it is an added cut point\n"
"	/j j 1 add def			% Go to next output point\n"
"	/k k 1 add def			% Done with this cut point\n"
"      } if\n"
"    } for\n"
"    dist PSL_cuts k get le		% Having dealt with the cut, we may add the regular point\n"
"    {PSL_xx j PSL_x i get put PSL_yy j PSL_y i get put\n"
"      PSL_kind j 0 put			% Ordinary (original) coordinates\n"
"      /j j 1 add def			% Go to next output point\n"
"    } if\n"
"  } for\n"
"} def\n"
"\n"
"/PSL_CT_reversepath\n"
"{PSL_xp j get PSL_xp 0 get lt	% Path must first be reversed to avoid upside-down text\n"
"  {0 1 j 2 idiv		% Loop over half the path and swap left/right points\n"
"    { /left exch def		% Current left point\n"
"      /right j left sub def	% Matching right point\n"
"      /tmp PSL_xp left get def	% Swap left and right values for x then y\n"
"      PSL_xp left PSL_xp right get put\n"
"      PSL_xp right tmp put\n"
"      /tmp PSL_yp left get def\n"
"      PSL_yp left PSL_yp right get put\n"
"      PSL_yp right tmp put\n"
"    } for\n"
"  } if\n"
"  % Now PSL_xp/yp has the correct order to give proper text angles\n"
"} def\n"
"\n"
"/PSL_CT_placelabel\n"
"{ % Places the curved text label on current segment\n"
"  /PSL_just PSL_label_justify k get def	% Get this labels justification\n"
"  /PSL_height PSL_heights k get def	% Recall the height of this string\n"
"  /psl_label PSL_str k get def		% Get the current label\n"
"  /psl_depth psl_label sd def		% Determine depth beneath baseline\n"
"  PSL_usebox		% Want to lay down box outline or fill\n"
"  {PSL_CT_clippath	% Box path now current path\n"
"    PSL_fillbox		% Want to paint box\n"
"    {V PSL_setboxrgb fill U} if\n"
"    PSL_drawbox		% Want to draw outline of box\n"
"    {V PSL_setboxpen S U} if N\n"
"  } if\n"
"  /psl_ct_sym false def\n"
"  PSL_CT_placeline psl_label PSL_gap_x PSL_just PSL_height psl_depth PSL_pathtext\n"
"} def\n"
"\n"
"/PSL_CT_clippath\n"
"{ % Lays down a curved clipbox for one label\n"
"  /H PSL_height 2 div PSL_gap_y add def\n"
"  /xoff j 1 add array def\n"
"  /yoff j 1 add array def\n"
"  /angle 0 def	% So it is at least a defined variable\n"
"  0 1 j {	% Loop over points along line to calculate angle and offsets\n"
"    /ii exch def	% Index\n"
"    /x PSL_xp ii get def\n"
"    /y PSL_yp ii get def\n"
"    ii 0 eq {	% Are we at the first point and hence must calculate angle using 0 and 1?\n"
"      /x1 PSL_xp 1 get def\n"
"      /y1 PSL_yp 1 get def\n"
"      /dx x1 x sub def\n"
"      /dy y1 y sub def\n"
"    }\n"
"    { /i1 ii 1 sub def	% Previous point\n"
"      /x1 PSL_xp i1 get def\n"
"      /y1 PSL_yp i1 get def\n"
"      /dx x x1 sub def\n"
"      /dy y y1 sub def\n"
"    } ifelse\n"
"    dx 0.0 eq dy 0.0 eq and not\n"
"    { /angle dy dx atan 90 add def} if	% Only calculate new angle if not duplicates\n"
"    /sina angle sin def\n"
"    /cosa angle cos def\n"
"    xoff ii H cosa mul put\n"
"    yoff ii H sina mul put\n"
"  } for\n"
"\n"
"  % Lay down next clip segment\n"
"\n"
"  PSL_xp 0 get xoff 0 get add PSL_yp 0 get yoff 0 get add M\n"
"  1 1 j {	% Loop over the rest of the upper line\n"
"    /ii exch def\n"
"    PSL_xp ii get xoff ii get add PSL_yp ii get yoff ii get add L\n"
"  } for\n"
"  j -1 0 {	% Loop backwards over the rest of the lower line\n"
"    /ii exch def\n"
"    PSL_xp ii get xoff ii get sub PSL_yp ii get yoff ii get sub L\n"
"  } for P\n"
"} def\n"
"\n"
"/PSL_CT_drawline\n"
"{\n"
"  /str 20 string def\n"
"  % PSL_strokeline PSL_seg 0 eq and		% If we asked to draw lines...\n"
"  PSL_strokeline				% If we asked to draw lines...\n"
"  {PSL_CT_placeline S} if			% Lay down the rest of the path and stroke it\n"
"  /PSL_seg PSL_seg 1 add def			% Goto next segment number\n"
"  /n 1 def					% Set n to 1\n"
"} def\n"
"\n"
"/PSL_CT_placeline\n"
"{PSL_xp 0 get PSL_yp 0 get M			% Set the anchor point of the path\n"
"  1 1 j { /ii exch def PSL_xp ii get PSL_yp ii get L} for	% Lay down the rest of the path\n"
"} def\n"
"\n"
"% Draw Baseline Text Segment Lines\n"
"% PSL_draw_path_lines will draw the lines that have been stored in the concatenated\n"
"% PSL_path_x and PSL_path_y arrays using the pen attributes in the PSL_path_pen array\n"
"\n"
"/PSL_draw_path_lines\n"
"{	% Draws the lines already stored in the PSL_path_x|y arrays\n"
"  /PSL_n_paths1 PSL_n_paths 1 sub def		% One less is the upper limit in for loop over the paths\n"
"  V\n"
"  /psl_start 0 def					% Start index of segment in concatenated path array\n"
"  0 1 PSL_n_paths1					% Loop over all segments\n"
"  { /psl_k exch def					% Index into the PSL arrays\n"
"    /PSL_n PSL_path_n psl_k get def			% Get the number of points in this line segment\n"
"    /PSL_n1 PSL_n 1 sub def				% One less is the upper limit in for loop over points\n"
"    PSL_path_pen psl_k get cvx exec			% Get and set this line's pen\n"
"    N							% Clean path\n"
"    PSL_path_x psl_start get PSL_path_y psl_start get M	% Place anchor point of this segment\n"
"    1 1 PSL_n1						% Loop over points in this segment\n"
"    { /psl_i exch def					% Local index of next point in segment\n"
"      /psl_kk psl_i psl_start add def			% Equivalent index in concatenated array of all segments\n"
"      PSL_path_x psl_kk get PSL_path_y psl_kk get L	% Draw to next point\n"
"    } for\n"
"    /psl_xclose PSL_path_x psl_kk get PSL_path_x psl_start get sub def	% Difference between first and last x coordinate\n"
"    /psl_yclose PSL_path_y psl_kk get PSL_path_y psl_start get sub def	% Difference between first and last y coordinate\n"
"    psl_xclose 0 eq psl_yclose 0 eq and { P } if	% Explicitly close the path\n"
"    S							% Stroke this path\n"
"    /psl_start psl_start PSL_n add def			% Go to next segment and update start index for path\n"
"  } for\n"
"  U\n"
"} def\n"
"\n"
"% Straight Baseline Text Placement Functions\n"
"% PSL_straight_path_labels deals with straight text labels w/wo textboxes (rect or rounded).\n"
"% Only the (x,y) location of each label is needed.\n"
"% Use <flags> PSL_straight_path_labels to paint|draw textboxes and place text\n"
"% Use <flags> PSL_straight_path_clip to use textboxes to define and activate clipping\n"
"% Subroutines of these functions are called PSL_ST_*\n"
"% Local variables are called psl_*, global are called PSL_*\n"
"\n"
"/PSL_straight_path_labels\n"
"{	% This function will lay down (a) text box paint, (b) text box outline, and (c) text labels\n"
"	% All of these are optionals specified by the bit flag.\n"
"  /psl_bits exch def				% Single bitflag argument passed\n"
"  /PSL_placetext psl_bits 2 and 2 eq def	% true to place text, false to just make space\n"
"  /PSL_rounded psl_bits 32 and 32 eq def	% true for rounded box shape, false gives rectangular box\n"
"  /PSL_fillbox psl_bits 128 and 128 eq def	% true to paint box opaque before placing text\n"
"  /PSL_drawbox psl_bits 256 and 256 eq def  % true to draw box outline before placing text\n"
"  /PSL_font_F  psl_bits 1536 and 0 eq def     % true to paint regular text\n"
"  /PSL_font_FO psl_bits 512 and 512 eq def    % true to fill text first then draw outline\n"
"  /PSL_font_OF psl_bits 1024 and 1024 eq def  % true to draw outline of text first then fill inside\n"
"  /PSL_n_labels_minus_1 PSL_n_labels 1 sub def	% Upper limit in loop over labels\n"
"  /PSL_usebox PSL_fillbox PSL_drawbox or def	% true if we need box outline for fill or stroke or both\n"
"  0 1 PSL_n_labels_minus_1			% Loop psl_k = 0 < PSL_n_labels\n"
"  { /psl_k exch def				% Current label index psl_k\n"
"    PSL_ST_prepare_text				% Get all dimensions, coordinates, etc. for this label\n"
"    PSL_usebox					% If a text box is requested we go in here:\n"
"    {  PSL_rounded				% Place text box path, either straight or rounded, on stack\n"
"        {PSL_ST_textbox_round}\n"
"        {PSL_ST_textbox_rect}\n"
"      ifelse\n"
"      PSL_fillbox {V PSL_setboxrgb fill U} if	% Paint it, if requested\n"
"      PSL_drawbox {V PSL_setboxpen S U} if	% Outline it, if requested\n"
"      N						% Done, so remove path\n"
"    } if\n"
"    PSL_font_F {  % Show text normally, if requested\n"
"      PSL_placetext {PSL_ST_place_label} if\n"
"    } if\n"
"    PSL_font_FO { % Fill first then outline, if requested\n"
"      PSL_placetext {PSL_ST_place_label_FO} if\n"
"    } if\n"
"    PSL_font_OF { % Outline text then fill, if requested\n"
"      PSL_placetext {PSL_ST_place_label_OF} if\n"
"    } if\n"
"  } for\n"
"} def\n"
"\n"
"/PSL_straight_path_clip\n"
"{	% This function will create a total clip path for all the labels in PSL_txt\n"
"  /psl_bits exch def				% Single bit flag argument passed\n"
"  /PSL_rounded psl_bits 32 and 32 eq def	% true for rounded box shape, false gives rectangular box\n"
"  /PSL_n_labels_minus_1 PSL_n_labels 1 sub def	% Upper limit in loop over labels\n"
"\n"
"  N clipsave clippath				% Start clip path by selecting the entire mappable area\n"
"  0 1 PSL_n_labels_minus_1			% Loop over all labels\n"
"  { /psl_k exch def				% Current label index psl_k\n"
"    PSL_ST_prepare_text				% Get all dimensions, coordinates, etc. for this label\n"
"    PSL_rounded					% Get either straight or rounded text box path\n"
"      {PSL_ST_textbox_round}\n"
"      {PSL_ST_textbox_rect}\n"
"    ifelse\n"
"  } for\n"
"  PSL_eoclip N					% Set the new clip path, increment clip counter and clear path\n"
"} def\n"
"\n"
"% Escape-aware label rendering procedures.\n"
"% These handle the @~ escape sequence (Symbol font toggle) in label strings.\n"
"% When @~ is found, the string is split into segments that alternate between\n"
"% the current font and the Symbol font at the same size.\n"
"\n"
"/PSL_split_esc {	% (string) PSL_split_esc => array of substrings split on @~\n"
"  /psl_src exch def\n"
"  /psl_parts 20 array def\n"
"  /psl_np 0 def\n"
"  /psl_pos 0 def\n"
"  {\n"
"    /psl_found false def\n"
"    psl_pos 1 psl_src length 2 sub {\n"
"      /psl_i exch def\n"
"      psl_src psl_i get 64 eq			% '@' = ASCII 64\n"
"      psl_src psl_i 1 add get 126 eq and	% '~' = ASCII 126\n"
"      {\n"
"        psl_parts psl_np psl_src psl_pos psl_i psl_pos sub getinterval put\n"
"        /psl_np psl_np 1 add def\n"
"        /psl_pos psl_i 2 add def\n"
"        /psl_found true def\n"
"        exit\n"
"      } if\n"
"    } for\n"
"    psl_found not {exit} if\n"
"  } loop\n"
"  psl_pos psl_src length lt {\n"
"    psl_parts psl_np psl_src psl_pos psl_src length psl_pos sub getinterval put\n"
"    /psl_np psl_np 1 add def\n"
"  } if\n"
"  psl_parts 0 psl_np getinterval\n"
"} def\n"
"\n"
"/PSL_has_esc {	% (string) PSL_has_esc => bool  -- true if string contains @~\n"
"  /psl_ts exch def\n"
"  /psl_he false def\n"
"  0 1 psl_ts length 2 sub {\n"
"    /psl_ti exch def\n"
"    psl_ts psl_ti get 64 eq psl_ts psl_ti 1 add get 126 eq and\n"
"    {/psl_he true def exit} if\n"
"  } for\n"
"  psl_he\n"
"} def\n"
"\n"
"/PSL_get_fontsize {	% => fontsize  -- extract size from current font\n"
"  currentfont /FontMatrix get 0 get 1000 mul\n"
"} def\n"
"\n"
"/PSL_show_esc {	% (string) PSL_show_esc => --  -- show with @~ font toggling\n"
"  PSL_split_esc\n"
"  /psl_origfont currentfont def\n"
"  /psl_sym false def\n"
"  /psl_fsz PSL_get_fontsize def\n"
"  { /psl_seg exch def\n"
"    psl_seg length 0 gt {psl_seg show} if\n"
"    /psl_sym psl_sym not def\n"
"    psl_sym {/Symbol findfont psl_fsz scalefont setfont}\n"
"            {psl_origfont setfont} ifelse\n"
"  } forall\n"
"  psl_origfont setfont\n"
"} def\n"
"\n"
"/PSL_charpath_esc {	% (string) PSL_charpath_esc => --  -- false charpath with @~ toggling\n"
"  PSL_split_esc\n"
"  /psl_origfont currentfont def\n"
"  /psl_sym false def\n"
"  /psl_fsz PSL_get_fontsize def\n"
"  { /psl_seg exch def\n"
"    psl_seg length 0 gt {psl_seg false charpath} if\n"
"    /psl_sym psl_sym not def\n"
"    psl_sym {/Symbol findfont psl_fsz scalefont setfont}\n"
"            {psl_origfont setfont} ifelse\n"
"  } forall\n"
"  psl_origfont setfont\n"
"} def\n"
"\n"
"/PSL_sw_esc {	% (string) PSL_sw_esc => width  -- stringwidth with @~ toggling\n"
"  PSL_split_esc\n"
"  /psl_origfont currentfont def\n"
"  /psl_sym false def\n"
"  /psl_fsz PSL_get_fontsize def\n"
"  /psl_tw 0 def\n"
"  { /psl_seg exch def\n"
"    psl_seg length 0 gt {/psl_tw psl_tw psl_seg stringwidth pop add def} if\n"
"    /psl_sym psl_sym not def\n"
"    psl_sym {/Symbol findfont psl_fsz scalefont setfont}\n"
"            {psl_origfont setfont} ifelse\n"
"  } forall\n"
"  psl_origfont setfont\n"
"  psl_tw\n"
"} def\n"
"\n"
"/PSL_label_show {	% (string) PSL_label_show => --\n"
"  dup PSL_has_esc {PSL_show_esc} {show} ifelse\n"
"} def\n"
"\n"
"/PSL_label_charpath {	% (string) PSL_label_charpath => --\n"
"  dup PSL_has_esc {PSL_charpath_esc} {false charpath} ifelse\n"
"} def\n"
"\n"
"/PSL_label_sw {	% (string) PSL_label_sw => width\n"
"  dup PSL_has_esc {PSL_sw_esc} {stringwidth pop} ifelse\n"
"} def\n"
"\n"
"/PSL_ST_prepare_text		% Compute various dimensions and coordinates for one label\n"
"{ % The current label has index psl_k\n"
"  /psl_xp PSL_txt_x psl_k get def		% Get text placement x coordinate\n"
"  /psl_yp PSL_txt_y psl_k get def		% Get text placement y coordinate\n"
"  /psl_label PSL_label_str psl_k get def	% Current text label\n"
"  PSL_label_font psl_k get cvx exec		% Get and set this label's font attributes\n"
"  /PSL_height PSL_heights psl_k get def		% Recall the height of this string\n"
"  /psl_boxH PSL_height PSL_gap_y 2 mul add def	% Set height of current label including clearance\n"
"  /PSL_just PSL_label_justify psl_k get def	% Get text justification (1-11)\n"
"  /PSL_justx PSL_just 4 mod 1 sub 2 div neg def % This is 0, -0.5, or -1 for relative x-shift \n"
"  /PSL_justy PSL_just 4 idiv 2 div neg def	% This is 0, -0.5, or -1 for relative y-shift \n"
"  /psl_SW psl_label PSL_label_sw def		% Width of current label space\n"
"  /psl_boxW psl_SW PSL_gap_x 2 mul add def	% Width of current label space including clearance\n"
"  /psl_x0 psl_SW PSL_justx mul def		% (psl_x0,psl_y0) is rotated/adjusted text LL point on inside rectangle relative to psl_xp,psl_yp\n"
"  /psl_y0 PSL_justy PSL_height mul def		%\n"
"  /psl_angle PSL_label_angle psl_k get def	% The angle of text w.r.t. baseline\n"
"} def\n"
"\n"
"/PSL_ST_textbox_rect	% Compute and place rectangular path for current label\n"
"{\n"
"  psl_xp psl_yp T psl_angle R psl_x0 psl_y0 T	% Rotate the coordinate system to follow baseline text and make (psl_x0,psl_y0) the new origin\n"
"  PSL_gap_x neg PSL_gap_y neg M			% Set LL anchor point for rectangular box\n"
"  0 psl_boxH D psl_boxW 0 D 0 psl_boxH neg D P	% Draw text box going CW\n"
"  psl_x0 neg psl_y0 neg T psl_angle neg R psl_xp neg psl_yp neg T	% Unto trans/rot above\n"
"} def\n"
"\n"
"/PSL_ST_textbox_round	% Compute and place rounded rectangular path for current label\n"
"{\n"
"  /psl_BoxR PSL_gap_x PSL_gap_y lt {PSL_gap_x} {PSL_gap_y} ifelse def	% Smallest gap distance is our corner radius\n"
"  /psl_xd PSL_gap_x psl_BoxR sub def 			% When x_gap exceeds y_gap there will be an adjustment in x, else 0\n"
"  /psl_yd PSL_gap_y psl_BoxR sub def 			% When y_gap exceeds x_gap there will be an adjustment in y, else 0\n"
"  /psl_xL PSL_gap_x neg def				% Left-most x coordinate of text box\n"
"  /psl_yB PSL_gap_y neg def				% Bottom y coordinate of text box\n"
"  /psl_yT psl_boxH psl_yB add def			% Top y coordinate of text box\n"
"  /psl_H2 PSL_height psl_yd 2 mul add def		% Inner height when adjusting for any psl_yd offset\n"
"  /psl_W2 psl_SW psl_xd 2 mul add def			% Inner width when adjusting for any psl_xd offset\n"
"  /psl_xR psl_xL psl_boxW add def			% Right-most x coordinate of text box\n"
"  /psl_x0 psl_SW PSL_justx mul def			% (psl_x0,psl_y0) is rotated/adjusted text LL point on inside rectangle relative to psl_xp,psl_yp\n"
"  psl_xp psl_yp T psl_angle R psl_x0 psl_y0 T		% Rotate the coordinate system to follow baseline text and make (psl_x0,psl_y0) the new origin\n"
"  psl_xL psl_yd M					% LL anchor point for rounded box is on lower left side just before rounded corner\n"
"  psl_xL psl_yT psl_xR psl_yT psl_BoxR arct psl_W2 0 D	% Draw UL rounded corner and line to start of UR rounded corner\n"
"  psl_xR psl_yT psl_xR psl_yB psl_BoxR arct 0 psl_H2 neg D	% Draw UR rounded corner and line to LR rounded corner\n"
"  psl_xR psl_yB psl_xL psl_yB psl_BoxR arct psl_W2 neg 0 D	% Draw LR rounded corner and line to LL rounded corner\n"
"  psl_xL psl_yB psl_xL psl_yd psl_BoxR arct P			% Draw LL rounded corner and close the clippath segment\n"
"  psl_x0 neg psl_y0 neg T psl_angle neg R psl_xp neg psl_yp neg T	% Unto trans/rot above\n"
"} def\n"
"\n"
"/PSL_ST_place_label % Just place the current label normally\n"
"{\n"
"    V psl_xp psl_yp T psl_angle R % Set origin at text point and rotate the coordinate system to follow baseline text\n"
"    psl_SW PSL_justx mul psl_y0 M % Goto LL point on label\n"
"    psl_label dup sd neg 0 exch G PSL_label_show  % Place the text, adjust vertically for any depth below baseline\n"
"    U         % Undo damage to coordinate system\n"
"} def\n"
"\n"
"/PSL_ST_place_label_FO % Just place the current label by filling it, then outlining it\n"
"{\n"
"    V psl_xp psl_yp T psl_angle R % Set origin at text point and rotate the coordinate system to follow baseline text\n"
"    psl_SW PSL_justx mul psl_y0 M % Goto LL point on label\n"
"    psl_label dup sd neg 0 exch G PSL_label_charpath V fs U S N % Place the text, adjust vertically for any depth below baseline\n"
"    U         % Undo damage to coordinate system\n"
"} def\n"
"\n"
"/PSL_ST_place_label_OF % Just place the current label by drawing outline, then filling it\n"
"{\n"
"    V psl_xp psl_yp T psl_angle R % Set origin at text point and rotate the coordinate system to follow baseline text\n"
"    psl_SW PSL_justx mul psl_y0 M % Goto LL point on label\n"
"    psl_label dup sd neg 0 exch G PSL_label_charpath V S U fs N % Place the text, adjust vertically for any depth below baseline\n"
"    U         % Undo damage to coordinate system\n"
"} def\n"
"\n"
"/PSL_nclip 0 def							% The depth of clipping in effect\n"
"/PSL_clip {clip /PSL_nclip PSL_nclip 1 add def} def			% Clip and update PSL_nclip\n"
"/PSL_eoclip {eoclip /PSL_nclip PSL_nclip 1 add def} def			% Even-odd clip and update PSL_nclip\n"
"/PSL_cliprestore {cliprestore /PSL_nclip PSL_nclip 1 sub def} def	% Cliprestore and update PSL_nclip\n";

/* Placing content of PSL_text.ps */

static char *PSL_text_str =
"%-----------------------------------------------------------------------------\n"
"%-	P. Wessel, version 1\n"
"%-	Text justification for paragraphs. Invented via PostScript docs a long time ago.\n"
"%-	Kept as separate file because it is easier to edit and see the logic here.\n"
"%-	Knows about flush l,c,r and justified.\n"
"%-	Knows about all GMT @ escapes, composites (but not in paragraph mode)\n"
"%-	and underlining. No hyphenation.  1 page only.\n"
"%-----------------------------------------------------------------------------\n"
"\n"
"/PSL_setfont {	% Set Font, size, and color (if needed)\n"
"  % Expects two arguments: Word flag and word index\n"
"  /f exch def % Gets word flag from stack\n"
"  /k1 exch def % Gets word index from stack\n"
"  /fz PSL_size k1 get def	% Get font size\n"
"  /fn PSL_fnt k1 get def	% Get font number\n"
"  fn PSL_lastfn eq fz PSL_lastfz eq and not { % If fonts or sizes differ we must update\n"
"    fz PSL_fontname fn get Y	% Set font and size\n"
"    /PSL_lastfn fn def\n"
"    /PSL_lastfz fz def\n"
"  } if\n"
"  /fc PSL_color k1 get def  % Get color\n"
"  fc PSL_lastfc ne {  % Not the same, must update color\n"
"    /PSL_c fc 3 mul def\n"
"    0 1 2 {PSL_c add PSL_rgb exch get} for C	% Get and set color\n"
"    /PSL_lastfc fc def\n"
"  } if\n"
"  f 32 and 32 eq { % Turn underline on before plotting text\n"
"    /PSL_UL fz 0.075 mul def\n"
"    fz 0.025 mul W\n"
"    /PSL_show {PSL_ushow} def\n"
"  }\n"
"  {\n"
"    /PSL_show {ashow} def\n"
"  } ifelse\n"
"}!\n"
"\n"
"/PSL_setfont2 {	% Only set font and size\n"
"  % Expects two arguments: Word flag and word index\n"
"  /f exch def % Gets word flag from stack\n"
"  /k1 exch def % Gets word index from stack\n"
"  /fz PSL_size k1 get def	% Get font size\n"
"  /fn PSL_fnt k1 get def	% Get font number\n"
"  fn PSL_lastfn eq fz PSL_lastfz eq and not {\n"
"    fz PSL_fontname fn get Y	% Set font and size\n"
"    /PSL_lastfn fn def\n"
"    /PSL_lastfz fz def\n"
"  } if\n"
"}!\n"
"\n"
"/PSL_wordheight {	% Gets word from stack, then calculates any adjustment to box height\n"
"  0 0 M false charpath flattenpath pathbbox /up exch def pop /down exch def pop newpath\n"
"  down PSL_ymin lt {/PSL_ymin down def} if\n"
"  up PSL_ymax gt {/PSL_ymax up def} if\n"
"}!\n"
"\n"
"/PSL_ushow {  % Related to underline showing text\n"
"  currentpoint /y0 exch def /x0 exch def\n"
"  ashow\n"
"  currentpoint pop /x1 exch def\n"
"  x0 y0 PSL_UL sub M x1 y0 PSL_UL sub L S\n"
"  x1 y0 M\n"
"}!\n"
"\n"
"% Set font, size, and color.  Adjust baseline if needed. Place space and word\n"
"\n"
"/PSL_placeword {\n"
"  % Expects one argument: the word index from stack\n"
"  /k exch def % Gets word index\n"
"  /flag PSL_flag k get def\n"
"  k flag PSL_setfont\n"
"  /sshow {ashow} def\n"
"  PSL_col 0 eq {		% First word on a new line\n"
"    /PSL_t 0 def			% 0 spaces before this word\n"
"    flag 4 and 4 eq {	% Flag says we must skip one TAB (here 4 spaces)\n"
"      pr_char 0 (    ) ashow\n"
"    } if\n"
"  }\n"
"  { % Need to find spaces before this word\n"
"    /f PSL_flag k 1 sub get def	% f is the flag for previous word\n"
"    /PSL_t f 3 and def		% PSL_t is index into PSL_spaces and PSL_spacewidths for previous word\n"
"    f 32 and 32 eq flag 32 and 32 eq and {/sshow {PSL_ushow} def} if\n"
"  } ifelse\n"
"  /thisword_bshift PSL_bshift k get def	% The baseline shift\n"
"  thisword_bshift 0.0 ne {0 thisword_bshift G} if	% Shift baseline\n"
"  flag 8 and 8 eq {	% First composite char (flagged with 8)\n"
"    pr_char 0 PSL_spaces PSL_t get sshow\n"
"    k PSL_composite\n"
"  } if\n"
"  flag 24 and 0 eq {	% Anything but composite chars\n"
"    pr_char 0 PSL_spaces PSL_t get sshow pr_char 0 PSL_word k get PSL_show\n"
"    PSL_width k get 0 gt {/PSL_col PSL_col 1 add def} if\n"
"  } if\n"
"  thisword_bshift 0.0 ne {0 thisword_bshift neg G} if	% Shift baseline\n"
"}!\n"
"\n"
"/PSL_composite {	% Place a composite character\n"
"  % Expects a word index from the stack\n"
"  /k1 exch def % Get word index from stack\n"
"  /k2 k1 1 add def  % Index to the 2nd composite character\n"
"  /char1 PSL_word k1 get def  % First character\n"
"  /char2 PSL_word k2 get def  % Second character\n"
"  /flag2 PSL_flag k2 get def  % Second character flag\n"
"  /w1 char1 stringwidth pop def % Width of first character\n"
"  flag2 64 and 64 eq {  % Here, 64 means we have a font change before the 2nd composite character\n"
"    /fn2 PSL_fnt k2 get def  % Get the other font array number\n"
"    fz PSL_fontname fn2 get Y  % Set font and size for the 2nd composite character\n"
"  } if\n"
"  /w2 char2 stringwidth pop def % Width of second character\n"
"  /delta w1 w2 sub 2 div PSL_scale mul def  % Adjust and center based on w1, w2\n"
"  delta 0.0 gt {\n"
"    /dx1 0 def\n"
"    /dx2 delta def\n"
"  }\n"
"  {\n"
"    /dx1 delta neg def\n"
"    /dx2 0 def\n"
"  } ifelse\n"
"  dx1 0 G currentpoint\n"
"  flag2 64 and 64 eq {  % Must switch back to first composite character font and set it\n"
"   /fn1 PSL_fnt k1 get def  % Get initial font\n"
"    fz PSL_fontname fn1 get Y  % Set font and size\n"
"  } if\n"
"  pr_char 0 char1 PSL_show M  % Place first character\n"
"  delta 0 G  % Adjust relative x to position for overprinting\n"
"  flag2 64 and 64 eq {  % Get 2nd font again\n"
"    fz PSL_fontname fn2 get Y  % Set font and size\n"
"  } if\n"
"  pr_char 0 char2 ashow  % Place 2nd character\n"
"  dx2 0 G  % Adjust relative x to position after this composite glyph\n"
"}!\n"
"\n"
"% Determine how much to expand text and also justify left/center/right\n"
"\n"
"/PSL_expand {\n"
"  /k1 exch def % Get word index from stack\n"
"  /extra PSL_parwidth previous_linewidth sub comp_width add def\n"
"  PSL_CRLF k1 PSL_n1 eq or {/spread 0 def} {/spread extra def} ifelse\n"
"  /PSL_scale previous_linewidth 0.0 gt {PSL_parwidth previous_linewidth div} {1.0} ifelse def\n"
"  /ndiv lsum ncomp sub def\n"
"  ndiv 0 eq {/ndiv 1 def} if\n"
"  PSL_parjust 4 eq {/pr_char spread ndiv div def} {/pr_char 0 def} ifelse\n"
"  PSL_parjust 2 eq {extra 2 div 0 G} if\n"
"  PSL_parjust 3 eq {extra 0 G} if\n"
"  /PSL_col 0 def\n"
"}!\n"
"\n"
"% Calculate text paragraph height or place it:\n"
"\n"
"/PSL_textjustifier {\n"
"  /PSL_mode exch def	% From stack. 0 -> calculate height, no text is placed, 1 -> place text\n"
"  /PSL_col 0 def\n"
"  /PSL_ybase 0 def\n"
"  /PSL_parheight 0 def\n"
"  /PSL_ymin 0 def\n"
"  /PSL_ymax 0 def\n"
"  /PSL_top 0 def\n"
"  /PSL_bottom 0 def\n"
"  /last_font PSL_fnt 0 get def		% The previous font number\n"
"  /last_size PSL_size 0 get def		% The previous font size\n"
"  /last_color PSL_color 0 get def	% The previous color index\n"
"  /previous_linewidth 0 def\n"
"  /stop 0 def\n"
"  /start 0 def\n"
"  /lsum 0 def\n"
"  /line 0 def\n"
"  /ncomp 0 def\n"
"  /comp_width 0 def\n"
"  0 1 PSL_n1 {		% Loop over all the words in the array\n"
"    /i exch def		% The current loop index\n"
"    /thisflag PSL_flag i get def	% Number of space chars to follow this word\n"
"    i 0 eq {  % At the first word\n"
"      /PSL_t 0 def\n"
"      /lastflag 0 def\n"
"    }\n"
"    { /lastflag PSL_flag i 1 sub get def  % Can get the previous flag\n"
"      /PSL_t lastflag 3 and def\n"
"    } ifelse\n"
"    % PSL_t is index into PSL_spaces and PSL_spacewidths\n"
"    i thisflag PSL_setfont2							% Get and set font and size\n"
"    /thisword_width PSL_width i get def\n"
"    /comp_add 0 def\n"
"    /compw_add 0 def\n"
"    /PSL_tabwidth (    ) stringwidth pop def					% Get width of the TAB\n"
"    /PSL_spacewidths PSL_spaces {stringwidth pop} forall 3 array astore def	% and the spaces\n"
"    /ccount PSL_count i get def								% # of characters in this word\n"
"    thisflag 4 and 4 eq {	% Had leading tab\n"
"      /thisword_width thisword_width PSL_tabwidth add def\n"
"      /ccount ccount 4 add def\n"
"    } if\n"
"    lastflag 8 and 8 eq {/PSL_t 0 def /comp_add 1 def /compw_add thisword_width def} if\n"
"    /new_linewidth previous_linewidth thisword_width add PSL_spacewidths PSL_t get add def	% Width of line if word added\n"
"    /PSL_CRLF thisword_width 0.0 eq thisflag 16 and 0 eq and def\n"
"    /special thisflag 16 and 16 eq {true} {thisword_width 0.0 gt} ifelse def\n"
"    new_linewidth PSL_parwidth le special and\n"
"    { % Word will fit on current line\n"
"      PSL_col 0 eq {\n"
"        /PSL_ymin 0 def\n"
"        /PSL_ymax 0 def\n"
"      } if\n"
"      /stop stop 1 add def			% Include this word\n"
"      /PSL_col PSL_col 1 add def		% Column place of next word\n"
"      /previous_linewidth new_linewidth def	% Update the unadjusted line width\n"
"      /lsum lsum ccount add PSL_t add def	% Update character count\n"
"      /ncomp ncomp comp_add add def\n"
"      /comp_width comp_width compw_add add def\n"
"    }\n"
"    { % Must process current line and move to next\n"
"      1 PSL_mode eq {		% Write out the first word on this line\n"
"        % Determine how much to expand text and also justify left/center/right\n"
"        start PSL_expand\n"
"        start PSL_placeword\n"
"      }\n"
"      {PSL_word start get PSL_wordheight\n"
"      } ifelse\n"
"      /last stop 1 sub def\n"
"      /start start 1 add def\n"
"      1 PSL_mode eq {		% Write out the remaining words on this line\n"
"        start 1 last {PSL_placeword} for\n"
"      }\n"
"      {start 1 last {PSL_word exch get PSL_wordheight} for\n"
"        line 0 eq { /PSL_top PSL_ymax def} if	% First outputline\n"
"      } ifelse\n"
"\n"
"      /start stop def\n"
"      /PSL_ybase PSL_ybase PSL_linespace sub def\n"
"      1 PSL_mode eq {0 PSL_ybase M} if	% CR/LF\n"
"      /stop stop 1 add def				% Include this word\n"
"      /previous_linewidth thisword_width def\n"
"      /lsum ccount def\n"
"      /ncomp comp_add def\n"
"      /comp_width compw_add def\n"
"      /PSL_col 0 def\n"
"      /line line 1 add def\n"
"    } ifelse\n"
"  } for\n"
"  /last stop 1 sub def\n"
"  last PSL_n lt {	% One or more words left hanging on last line\n"
"    /PSL_CRLF true def\n"
"    1 PSL_mode eq {\n"
"      % Determine how much to expand text and also justify left/center/right\n"
"      start PSL_expand\n"
"      start PSL_placeword\n"
"      /start start 1 add def\n"
"      start 1 last {PSL_placeword} for\n"
"    }\n"
"    { /PSL_ymin 0 def\n"
"      PSL_word start get PSL_wordheight\n"
"      /start start 1 add def\n"
"      start 1 last {PSL_word exch get PSL_wordheight} for\n"
"      line 0 eq {	% First outputline\n"
"        /PSL_top PSL_ymax def\n"
"      } if\n"
"    } ifelse\n"
"  } if\n"
"  /PSL_bottom PSL_ymin def\n"
"  /PSL_parheight PSL_ybase neg PSL_top add PSL_bottom sub def\n"
"} def % PSL_textjustifier\n";

/* Placing content of PSL_prologue.ps */

static char *PSL_prologue_str =
"%-----------------------------------------------------------------------------\n"
"%-  PS dictionary written to header to all GMT PostScript plots\n"
"%-----------------------------------------------------------------------------\n"
"% Begin pslib header\n"
"250 dict begin\n"
"/! {bind def} bind def\n"
"/# {load def}!\n"
"/A /setgray #\n"
"/B /setdash #\n"
"/C /setrgbcolor #\n"
"/D /rlineto #\n"
"/E {dup stringwidth pop}!\n"
"/F /fill #\n"
"/G /rmoveto #\n"
"/H /sethsbcolor #\n"
"/I /setpattern #\n"
"/K /setcmykcolor #\n"
"/L /lineto #\n"
"/M /moveto #\n"
"/N /newpath #\n"
"/P /closepath #\n"
"/R /rotate #\n"
"/S /stroke #\n"
"/T /translate #\n"
"/U /grestore #\n"
"/V /gsave #\n"
"/W /setlinewidth #\n"
"/Y {findfont exch scalefont setfont}!\n"
"/Z /show #\n"
"/FP {true charpath flattenpath}!\n"
"/MU {matrix setmatrix}!\n"
"/MS {/SMat matrix currentmatrix def}!\n"
"/MR {SMat setmatrix}!\n"
"/edef {exch def}!\n"
"% Path fill\n"
"/FS {/fc edef /fs {V fc F U} def}!\n"
"/FQ {/fs {} def}!\n"
"% Outline off or on\n"
"/O0 {/os {N} def}!\n"
"/O1 {/os {P S} def}!\n"
"% Set both fill and outline\n"
"/FO {fs os}!\n"
"% Star: radius xc yc\n"
"/Sa {M MS dup 0 exch G 0.726542528 mul -72 R dup 0 D 4 {72 R dup 0 D -144 R dup 0 D} repeat pop MR FO}!\n"
"% Box: height width xll yll\n"
"/Sb {M dup 0 D exch 0 exch D neg 0 D FO}!\n"
"% Rounded box: height width radius xll yll\n"
"/SB {MS T /BoxR edef /BoxW edef /BoxH edef BoxR 0 M\n"
"  BoxW 0 BoxW BoxH BoxR arct BoxW BoxH 0 BoxH BoxR arct 0 BoxH 0 0 BoxR arct 0 0 BoxW 0 BoxR arct MR FO}!\n"
"% Circle: radius xc yc\n"
"/Sc {N 3 -1 roll 0 360 arc FO}!\n"
"% Diamond: radius xc yc\n"
"/Sd {M 4 {dup} repeat 0 G neg dup dup D exch D D FO}!\n"
"% Ellipse: major minor angle xc yc\n"
"/Se {N MS T R scale 0 0 1 0 360 arc MR FO}!\n"
"% Octagon: radius xc yc\n"
"/Sg {M MS 22.5 R dup 0 exch G -22.5 R 0.765366865 mul dup 0 D 6 {-45 R dup 0 D} repeat pop MR FO}!\n"
"% Hexagon: radius xc yc\n"
"/Sh {M MS dup 0 G -120 R dup 0 D 4 {-60 R dup 0 D} repeat pop MR FO}!\n"
"% Inverted triangle: radius xc yc\n"
"/Si {M MS dup neg 0 exch G 60 R 1.732050808 mul dup 0 D 120 R 0 D MR FO}!\n"
"% Rotated rectangle: height width angle xc yc\n"
"/Sj {M MS R dup -2 div 2 index -2 div G dup 0 D exch 0 exch D neg 0 D MR FO}!\n"
"% Pentagon: radius xc yc\n"
"/Sn {M MS dup 0 exch G -36 R 1.175570505 mul dup 0 D 3 {-72 R dup 0 D} repeat pop MR FO}!\n"
"% Dot: radius xc yc [hardwired as circle with no outline]\n"
"/Sp {N 3 -1 roll 0 360 arc fs N}!\n"
"% Patch fill: x1 y1 ... xn yn n\n"
"/SP {M {D} repeat FO}!\n"
"% Sphere with 3D shading: radius xc yc\n"
"/SPhere {/yc_SP edef /xc_SP edef /radius_SP edef\n"
"  /SP_flat where {pop} {/SP_flat false def} ifelse\n"
"  /SP_no_fill where {pop} {/SP_no_fill false def} ifelse\n"
"  gsave\n"
"  xc_SP yc_SP matrix currentmatrix transform /yc_SP_user edef /xc_SP_user edef\n"
"  radius_SP 0 matrix currentmatrix dtransform dup mul exch dup mul add sqrt /radius_SP_user edef\n"
"  /SP_lx where {pop /SP_lx_orig SP_lx def /SP_ly_orig SP_ly def} {/SP_lx_orig 0.0 def /SP_ly_orig 0.0 def} ifelse\n"
"  radius_SP_user SP_lx_orig mul /SP_lx_user edef\n"
"  radius_SP_user SP_ly_orig mul /SP_ly_user edef\n"
"  matrix setmatrix\n"
"  SP_no_fill {\n"
"    % No fill (outline only, drawn separately in C code)\n"
"  } {\n"
"    fc\n"
"    SP_flat {\n"
"      % Flat/constant color (no gradient)\n"
"      xc_SP_user yc_SP_user T N 0 0 radius_SP_user 0 360 arc fill\n"
"    } {\n"
"      % 3D gradient shading\n"
"      currentrgbcolor /B_SP edef /G_SP edef /R_SP edef\n"
"      xc_SP_user yc_SP_user T N 0 0 radius_SP_user 0 360 arc\n"
"      /Pattern setcolorspace\n"
"      << /PatternType 2 /Shading << /ShadingType 3 /ColorSpace /DeviceRGB\n"
"      /Coords [SP_lx_user SP_ly_user 0 0 0 radius_SP_user] /Function <<\n"
"      /FunctionType 2 /Domain [0 1] /C0 [1 1 1] /C1 [R_SP G_SP B_SP] /N 1 >> >>\n"
"      >> matrix makepattern setcolor fill\n"
"    } ifelse\n"
"  } ifelse\n"
"  grestore}!\n"
"% Rectangle: height width xc yc\n"
"/Sr {M dup -2 div 2 index -2 div G dup 0 D exch 0 exch D neg 0 D FO}!\n"
"% Rounded rectangle: height width radius xc yc\n"
"/SR {MS T /BoxR edef /BoxW edef /BoxH edef BoxR BoxW -2 div BoxH -2 div T BoxR 0 M\n"
"  BoxW 0 BoxW BoxH BoxR arct BoxW BoxH 0 BoxH BoxR arct 0 BoxH 0 0 BoxR arct 0 0 BoxW 0 BoxR arct MR FO}!\n"
"% Square: radius xc yc\n"
"/Ss {M 1.414213562 mul dup dup dup -2 div dup G 0 D 0 exch D neg 0 D FO}!\n"
"% Triangle: radius xc yc\n"
"/St {M MS dup 0 exch G -60 R 1.732050808 mul dup 0 D -120 R 0 D MR FO}!\n"
"% Single-headed vector\n"
"/SV {0 exch M 0 D D D D D 0 D FO}!\n"
"% Double-headed vector\n"
"/Sv {0 0 M D D 0 D D D D D 0 D D FO}!\n"
"% Pie Wedge: radius angle1 angle2 xc yc\n"
"/Sw {2 copy M 5 2 roll arc FO}!\n"
"% Cross: radius xc yc\n"
"/Sx {M 1.414213562 mul 5 {dup} repeat -2 div dup G D neg 0 G neg D S}!\n"
"% Y-dash: radius xc yc\n"
"/Sy {M dup 0 exch G dup -2 mul dup 0 exch D S}!\n"
"% Plus: radius xc yc\n"
"/S+ {M dup 0 G dup -2 mul dup 0 D exch dup G 0 exch D S}!\n"
"% X-dash: radius xc yc\n"
"/S- {M dup 0 G dup -2 mul dup 0 D S}!\n"
"% String width, height, depth and total height (height-depth)\n"
"/sw {stringwidth pop}!\n"
"/sh {V MU 0 0 M FP pathbbox N 4 1 roll pop pop pop U}!\n"
"/sd {V MU 0 0 M FP pathbbox N pop pop exch pop U}!\n"
"/sH {V MU 0 0 M FP pathbbox N exch pop exch sub exch pop U}!\n"
"/sb {E exch sh}!\n"
"% To align text {bottom,middle,top}{left,center,right}\n"
"/bl {}!\n"
"/bc {E -2 div 0 G}!\n"
"/br {E neg 0 G}!\n"
"/ml {dup 0 exch sh -2 div G}!\n"
"/mc {dup E -2 div exch sh -2 div G}!\n"
"/mr {dup E neg exch sh -2 div G}!\n"
"/tl {dup 0 exch sh neg G}!\n"
"/tc {dup E -2 div exch sh neg G}!\n"
"/tr {dup E neg exch sh neg G}!\n"
"% Maximum of two numbers\n"
"/mx {2 copy lt {exch} if pop}!\n"
"% Translate and memorize advance\n"
"/PSL_xorig 0 def /PSL_yorig 0 def\n"
"/TM {2 copy T PSL_yorig add /PSL_yorig edef PSL_xorig add /PSL_xorig edef}!\n"
"% To re-encode one font with the provided encoding vector\n"
"/PSL_reencode {findfont dup length dict begin\n"
"  {1 index /FID ne {def}{pop pop} ifelse} forall\n"
"  exch /Encoding edef currentdict end definefont pop\n"
"}!\n"
"/PSL_eps_begin {					% Marks begin of EPSF inclusion\n"
"  /PSL_eps_state save def				% Save state for cleanup\n"
"  /PSL_dict_count countdictstack def			% Count objects on dict stack\n"
"  /PSL_op_count count 1 sub def				% Count objects on operand stack\n"
"  userdict begin					% Push userdict stack\n"
"  /showpage {} def					% Deactivate showpage command\n"
"  0 setgray 0 setlinecap 1 setlinewidth			% Prepare clean graphics state\n"
"  0 setlinejoin 10 setmiterlimit [] 0 setdash newpath\n"
"  /languagelevel where	% If level != 1, set strokeadjust and overprint to their defaults\n"
"  {pop languagelevel 1 ne {false setstrokeadjust false setoverprint} if} if\n"
"}!\n"
"/PSL_eps_end {						% Marks end of EPSF inclusion\n"
"  count PSL_op_count sub {pop} repeat			% Clean up operand stack\n"
"  countdictstack PSL_dict_count sub {end} repeat	% Clean up dict stack\n"
"  PSL_eps_state restore					% Restore saved state\n"
"}!\n"
"/PSL_transp {             % Changes the transparency settings\n"
"  /PSL_BM_arg edef /PSL_S_arg edef /PSL_F_arg edef\n"
"  /.setfillconstantalpha where\n"
"  { pop PSL_BM_arg .setblendmode PSL_S_arg .setstrokeconstantalpha PSL_F_arg .setfillconstantalpha }  % Ghostscript\n"
"  { /pdfmark where {pop [ /BM PSL_BM_arg /CA PSL_S_arg /ca PSL_F_arg /SetTransparency pdfmark} if } % Or Adobe\n"
"  ifelse\n"
"}!\n";
