@@ -333,6 +333,7 @@ static struct PSL_FONT PSL_standard_fonts[PSL_N_STANDARD_FONTS] = {
333333#define PSL_SUB_DOWN 0.25 /* Baseline shift down in font size for subscript */
334334#define PSL_SUP_UP_LC 0.35 /* Baseline shift up in font size for superscript after lowercase letter */
335335#define PSL_SUP_UP_UC 0.35 /* Baseline shift up in font size for superscript after uppercase letter */
336+ #define PSL_ASCII_ES 27 /* ASCII code for escape (used to prevent +? strings in plain text from being seen as modifiers) */
336337#if 0
337338/* These are potential revisions to some of the settings above but remains to be tested */
338339#define PSL_SUBSUP_SIZE 0.58 /* Relative size of sub/sup-script to normal size */
@@ -4852,6 +4853,45 @@ int PSL_plottextbox (struct PSL_CTRL *PSL, double x, double y, double fontsize,
48524853 return (PSL_NO_ERROR );
48534854}
48544855
4856+ void psl_got_composite_fontswitch (struct PSL_CTRL * PSL , char * text ) {
4857+ /* If a composite character is made from two different fonts then we need to flag these.
4858+ * E.g., Epsilon time-derivative = @!\277@~145@~ using current and Symbol font.
4859+ * Here we need to switch to symbol font for one char, from whatever font we are using.
4860+ * We look for such cases and count the occurrences, plus replace the font changing code
4861+ * @ (either @~ or @%font% with ASCII escape (27)). */
4862+ size_t k ;
4863+ int n = 0 , step ;
4864+ for (k = 0 ; k < strlen (text ); k ++ ) {
4865+ if (text [k ] != '@' ) continue ;
4866+ /* Start of an escape sequence */
4867+ k ++ ;
4868+ if (text [k ] != '!' ) continue ; /* Not a composite character request */
4869+ k ++ ; /* Step to start of character1 */
4870+ if (text [k ] == '\\' ) k += 4 ; else k ++ ; /* Skip the octal or regular first character */
4871+ if (text [k ] != '@' ) continue ; /* No font switching in the composite glyph */
4872+ /* Here we do have such a thing, and we need to avoid the regular string splitting at @ in PSL_plottext and PSL_deftextdim */
4873+ text [k ] = PSL_ASCII_ES ; /* Replace @ with ASCII ESC code for now */
4874+ k ++ ; /* Font code type is ~ or % */
4875+ if (text [k ] == '~' ) { /* Symbol font */
4876+ k ++ ; /* Step to character2 */
4877+ step = 1 ; /* Since we will toggle back with @~ */
4878+ }
4879+ else { /* Some random font switch */
4880+ k ++ ; /* Step past first % */
4881+ while (text [k ] != '%' ) k ++ ; /* Skip past the font name or number */
4882+ step = 2 ; /* Since we will toggle back with @%% */
4883+ k ++ ; /* Step to character2 */
4884+ }
4885+ if (text [k ] == '\\' ) k += 4 ; else k ++ ; /* Skip the octal or regular second character */
4886+ if (text [k ] != '@' ) /* Not ideal, user error presumably */
4887+ PSL_message (PSL , PSL_MSG_WARNING , "Warning: psl_got_composite_fontswitch expected a font-change at end of composite character 2\n" );
4888+ else /* Get passed the font return code */
4889+ text [k ] = PSL_ASCII_ES ; /* Skip to end of text section */
4890+ n ++ ; /* Found one of these cases */
4891+ }
4892+ if (n ) PSL_message (PSL , PSL_MSG_DEBUG , "psl_got_composite_fontswitch found %d composite characters with different fonts/char sets\n" , n );
4893+ }
4894+
48554895int PSL_deftextdim (struct PSL_CTRL * PSL , const char * dim , double fontsize , char * text ) {
48564896 /* Will calculate the dimension of the given text string.
48574897 * Because of possible escape sequences we need to examine the string
@@ -4866,9 +4906,9 @@ int PSL_deftextdim (struct PSL_CTRL *PSL, const char *dim, double fontsize, char
48664906 * depth or both width and height on the PostScript stack.
48674907 */
48684908
4869- char * tempstring = NULL , * piece = NULL , * piece2 = NULL , * ptr = NULL , * string = NULL , * plast = NULL , previous [BUFSIZ ] = {"" };
4870- int dy , font , sub_on , super_on , scaps_on , symbol_on , font_on , size_on , color_on , under_on , old_font , last_chr , kase = PSL_LC ;
4871- bool last_sub = false, last_sup = false, supersub ;
4909+ char * tempstring = NULL , * piece = NULL , * piece2 = NULL , * ptr = NULL , * string = NULL , * plast = NULL , previous [BUFSIZ ] = {"" }, c ;
4910+ int dy , font , font2 , sub_on , super_on , scaps_on , symbol_on , font_on , size_on , color_on , under_on , old_font , last_chr , kase = PSL_LC ;
4911+ bool last_sub = false, last_sup = false, supersub , composite ;
48724912 double orig_size , small_size , size , scap_size , ustep [2 ], dstep ;
48734913
48744914 if (strlen (text ) >= (PSL_BUFSIZ - 1 )) {
@@ -4891,6 +4931,8 @@ int PSL_deftextdim (struct PSL_CTRL *PSL, const char *dim, double fontsize, char
48914931 return (PSL_NO_ERROR );
48924932 }
48934933
4934+ psl_got_composite_fontswitch (PSL , string );
4935+
48944936 /* Here, we have special request for Symbol font and sub/superscript
48954937 * @~ toggles between Symbol font and default font
48964938 * @%<fontno>% switches font number <fontno>; give @%% to reset
@@ -4904,14 +4946,14 @@ int PSL_deftextdim (struct PSL_CTRL *PSL, const char *dim, double fontsize, char
49044946 piece = PSL_memory (PSL , NULL , 2 * PSL_BUFSIZ , char );
49054947 piece2 = PSL_memory (PSL , NULL , PSL_BUFSIZ , char );
49064948
4907- font = old_font = PSL -> current .font_no ;
4949+ font = font2 = old_font = PSL -> current .font_no ;
49084950 orig_size = size = fontsize ;
49094951 small_size = size * PSL -> current .subsupsize ; /* Sub-script/Super-script set at given fraction of font size */
49104952 scap_size = size * PSL -> current .scapssize ; /* Small caps set at given fraction of font size */
49114953 ustep [PSL_LC ] = PSL -> current .sup_up [PSL_LC ] * size ; /* Super-script baseline raised by given fraction of font size for lower case*/
49124954 ustep [PSL_UC ] = PSL -> current .sup_up [PSL_UC ] * size ; /* Super-script baseline raised by given fraction of font size for upper case */
49134955 dstep = PSL -> current .sub_down * size ; /* Sub-script baseline lowered by given fraction of font size */
4914- sub_on = super_on = scaps_on = symbol_on = font_on = size_on = color_on = under_on = false;
4956+ sub_on = super_on = scaps_on = symbol_on = font_on = size_on = color_on = under_on = composite = false;
49154957 supersub = (strstr (string , "@-@+" ) || strstr (string , "@+@-" )); /* Check for sub/super combo */
49164958 tempstring = PSL_memory (PSL , NULL , strlen (string )+ 1 , char ); /* Since strtok steps on it */
49174959 strcpy (tempstring , string );
@@ -4925,13 +4967,51 @@ int PSL_deftextdim (struct PSL_CTRL *PSL, const char *dim, double fontsize, char
49254967 }
49264968
49274969 while (ptr ) {
4928- if (ptr [0 ] == '!' ) { /* Composite character */
4970+ if (ptr [0 ] == '!' ) { /* Composite character. Only use the second character to measure width */
49294971 ptr ++ ;
49304972 if (ptr [0 ] == '\\' ) /* Octal code */
49314973 ptr += 4 ;
49324974 else
49334975 ptr ++ ;
4934- strncpy (piece , ptr , 2 * PSL_BUFSIZ );
4976+ /* Watch out for escaped font change before 2nd character */
4977+ if (ptr [0 ] == PSL_ASCII_ES ) { /* Have a font change on either side of 2nd character */
4978+ ptr ++ ;
4979+ if (ptr [0 ] == '~' ) /* Toggle the symbol font */
4980+ font2 = PSL_SYMBOL_FONT ;
4981+ else { /* Font switching with @%font% ...@%% */
4982+ ptr ++ ;
4983+ font2 = psl_getfont (PSL , ptr );
4984+ while (* ptr != '%' ) ptr ++ ;
4985+ }
4986+ ptr ++ ; /* Now at start of 2nd character */
4987+ }
4988+ else /* No 2nd font */
4989+ font2 = font ;
4990+ if (ptr [0 ] == '\\' ) { /* Octal code */
4991+ c = ptr [4 ];
4992+ ptr [4 ] = '\0' ; /* Temporary chop at end of this code */
4993+ }
4994+ else {
4995+ c = ptr [1 ];
4996+ ptr [1 ] = '\0' ; /* Temporary chop at end of char */
4997+ }
4998+ strncpy (piece , ptr , 2 * PSL_BUFSIZ ); /* Picked character2 */
4999+ if (ptr [0 ] == '\\' ) { /* Octal code */
5000+ ptr [4 ] = c ; /* Restore code */
5001+ ptr += 4 ;
5002+ }
5003+ else {
5004+ ptr [1 ] = c ; /* Restore char */
5005+ ptr ++ ;
5006+ }
5007+ if (font2 != font ) { /* Skip past the font switcher */
5008+ ptr ++ ; /* Step over the implicit @ (ASCII 27) */
5009+ if (font2 == PSL_SYMBOL_FONT )
5010+ ptr ++ ; /* Move past the ~ */
5011+ else
5012+ ptr += 2 ; /* Move past the %% */
5013+ }
5014+ composite = true; /* Flag this case */
49355015 }
49365016 else if (ptr [0 ] == '~' ) { /* Symbol font toggle */
49375017 symbol_on = !symbol_on ;
@@ -5028,6 +5108,10 @@ int PSL_deftextdim (struct PSL_CTRL *PSL, const char *dim, double fontsize, char
50285108 PSL_command (PSL , "PSL_last_width 0 G " ); /* Rewind position to orig baseline */
50295109 last_sub = last_sup = false;
50305110 }
5111+ if (ptr && composite ) {
5112+ strcat (piece , ptr );
5113+ composite = false;
5114+ }
50315115 PSL_command (PSL , "%d F%d (%s) FP " , psl_ip (PSL , size ), font , piece );
50325116 last_chr = ptr [strlen (piece )- 1 ];
50335117 if (!super_on && (last_chr > 0 && last_chr < 255 )) kase = (islower (last_chr )) ? PSL_LC : PSL_UC ;
@@ -5103,7 +5187,7 @@ int PSL_plottext (struct PSL_CTRL *PSL, double x, double y, double fontsize, cha
51035187 const char * justcmd [12 ] = {"" , "bl " , "bc " , "br " , "" , "ml " , "mc " , "mr " , "" , "tl " , "tc " , "tr " };
51045188 /* PS strings to be used dependent on "justify%4". Empty string added for unused value. */
51055189 const char * align [4 ] = {"0" , "-2 div" , "neg" , "" };
5106- int dy , i = 0 , j , font , x_just , y_just , upen , ugap ;
5190+ int dy , i = 0 , j , font , font2 , x_just , y_just , upen , ugap ;
51075191 int sub_on , super_on , scaps_on , symbol_on , font_on , size_on , color_on , under_on , old_font , n_uline , start_uline , stop_uline , last_chr , kase = PSL_LC ;
51085192 bool last_sub = false, last_sup = false, supersub ;
51095193 double orig_size , small_size , size , scap_size , ustep [2 ], dstep , last_rgb [4 ] = {0.0 , 0.0 , 0.0 , 0.0 };
@@ -5148,6 +5232,8 @@ int PSL_plottext (struct PSL_CTRL *PSL, double x, double y, double fontsize, cha
51485232 return (PSL_NO_ERROR );
51495233 }
51505234
5235+ psl_got_composite_fontswitch (PSL , string );
5236+
51515237 /* For more difficult cases we use the PSL_deftextdim machinery to get the size of the font box */
51525238
51535239 if (justify > 1 ) {
@@ -5189,7 +5275,6 @@ int PSL_plottext (struct PSL_CTRL *PSL, double x, double y, double fontsize, cha
51895275 last_chr = ptr [strlen (ptr )- 1 ];
51905276 ptr = strtok_r (NULL , "@" , & plast );
51915277 kase = ((last_chr > 0 && last_chr < 255 ) && islower (last_chr )) ? PSL_LC : PSL_UC ;
5192-
51935278 }
51945279
51955280 font = old_font = PSL -> current .font_no ;
@@ -5216,6 +5301,21 @@ int PSL_plottext (struct PSL_CTRL *PSL, double x, double y, double fontsize, cha
52165301 piece [0 ] = ptr [0 ]; piece [1 ] = 0 ;
52175302 ptr ++ ;
52185303 }
5304+ /* Watch out for escaped font change before 2nd character */
5305+ if (ptr [0 ] == PSL_ASCII_ES ) { /* Have a font change on either side of 2nd character */
5306+ ptr ++ ;
5307+ if (ptr [0 ] == '~' ) /* Toggle the symbol font */
5308+ font2 = PSL_SYMBOL_FONT ;
5309+ else { /* Font switching with @%font% ...@%% */
5310+ ptr ++ ;
5311+ font2 = psl_getfont (PSL , ptr );
5312+ psl_encodefont (PSL , font );
5313+ while (* ptr != '%' ) ptr ++ ;
5314+ }
5315+ ptr ++ ; /* Now at start of 2nd character */
5316+ }
5317+ else
5318+ font2 = font ;
52195319 if (ptr [0 ] == '\\' ) { /* Octal code again */
52205320 strncpy (piece2 , ptr , 4U );
52215321 piece2 [4 ] = 0 ;
@@ -5225,8 +5325,17 @@ int PSL_plottext (struct PSL_CTRL *PSL, double x, double y, double fontsize, cha
52255325 piece2 [0 ] = ptr [0 ]; piece2 [1 ] = 0 ;
52265326 ptr ++ ;
52275327 }
5328+ if (font2 != font ) { /* Skip past the font switcher */
5329+ ptr ++ ; /* Step over the implicit @ (ascii 27) */
5330+ if (font2 == PSL_SYMBOL_FONT )
5331+ ptr ++ ; /* Move past the ~ */
5332+ else
5333+ ptr += 2 ; /* Move past the %% */
5334+ }
52285335 /* Try to center justify these two character to make a composite character - may not be right */
5229- PSL_command (PSL , "%d F%d (%s) E exch %s -2 div dup 0 G\n" , psl_ip (PSL , size ), font , piece2 , op [mode ]);
5336+ PSL_command (PSL , "%d F%d (%s) E exch %s -2 div dup 0 G\n" , psl_ip (PSL , size ), font2 , piece2 , op [mode ]);
5337+ if (font2 != font ) /* Must switch font in the call */
5338+ PSL_command (PSL , "%d F%d\n" , psl_ip (PSL , size ), font );
52305339 PSL_command (PSL , "(%s) E -2 div dup 0 G exch %s sub neg dup 0 lt {pop 0} if 0 G\n" , piece , op [mode ]);
52315340 strncpy (piece , ptr , 2 * PSL_BUFSIZ );
52325341 }
0 commit comments