@@ -333,6 +333,7 @@ static struct PSL_FONT PSL_standard_fonts[PSL_N_STANDARD_FONTS] = {
333
333
#define PSL_SUB_DOWN 0.25 /* Baseline shift down in font size for subscript */
334
334
#define PSL_SUP_UP_LC 0.35 /* Baseline shift up in font size for superscript after lowercase letter */
335
335
#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) */
336
337
#if 0
337
338
/* These are potential revisions to some of the settings above but remains to be tested */
338
339
#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,
4852
4853
return (PSL_NO_ERROR );
4853
4854
}
4854
4855
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
+
4855
4895
int PSL_deftextdim (struct PSL_CTRL * PSL , const char * dim , double fontsize , char * text ) {
4856
4896
/* Will calculate the dimension of the given text string.
4857
4897
* 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
4866
4906
* depth or both width and height on the PostScript stack.
4867
4907
*/
4868
4908
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 ;
4872
4912
double orig_size , small_size , size , scap_size , ustep [2 ], dstep ;
4873
4913
4874
4914
if (strlen (text ) >= (PSL_BUFSIZ - 1 )) {
@@ -4891,6 +4931,8 @@ int PSL_deftextdim (struct PSL_CTRL *PSL, const char *dim, double fontsize, char
4891
4931
return (PSL_NO_ERROR );
4892
4932
}
4893
4933
4934
+ psl_got_composite_fontswitch (PSL , string );
4935
+
4894
4936
/* Here, we have special request for Symbol font and sub/superscript
4895
4937
* @~ toggles between Symbol font and default font
4896
4938
* @%<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
4904
4946
piece = PSL_memory (PSL , NULL , 2 * PSL_BUFSIZ , char );
4905
4947
piece2 = PSL_memory (PSL , NULL , PSL_BUFSIZ , char );
4906
4948
4907
- font = old_font = PSL -> current .font_no ;
4949
+ font = font2 = old_font = PSL -> current .font_no ;
4908
4950
orig_size = size = fontsize ;
4909
4951
small_size = size * PSL -> current .subsupsize ; /* Sub-script/Super-script set at given fraction of font size */
4910
4952
scap_size = size * PSL -> current .scapssize ; /* Small caps set at given fraction of font size */
4911
4953
ustep [PSL_LC ] = PSL -> current .sup_up [PSL_LC ] * size ; /* Super-script baseline raised by given fraction of font size for lower case*/
4912
4954
ustep [PSL_UC ] = PSL -> current .sup_up [PSL_UC ] * size ; /* Super-script baseline raised by given fraction of font size for upper case */
4913
4955
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;
4915
4957
supersub = (strstr (string , "@-@+" ) || strstr (string , "@+@-" )); /* Check for sub/super combo */
4916
4958
tempstring = PSL_memory (PSL , NULL , strlen (string )+ 1 , char ); /* Since strtok steps on it */
4917
4959
strcpy (tempstring , string );
@@ -4925,13 +4967,51 @@ int PSL_deftextdim (struct PSL_CTRL *PSL, const char *dim, double fontsize, char
4925
4967
}
4926
4968
4927
4969
while (ptr ) {
4928
- if (ptr [0 ] == '!' ) { /* Composite character */
4970
+ if (ptr [0 ] == '!' ) { /* Composite character. Only use the second character to measure width */
4929
4971
ptr ++ ;
4930
4972
if (ptr [0 ] == '\\' ) /* Octal code */
4931
4973
ptr += 4 ;
4932
4974
else
4933
4975
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 */
4935
5015
}
4936
5016
else if (ptr [0 ] == '~' ) { /* Symbol font toggle */
4937
5017
symbol_on = !symbol_on ;
@@ -5028,6 +5108,10 @@ int PSL_deftextdim (struct PSL_CTRL *PSL, const char *dim, double fontsize, char
5028
5108
PSL_command (PSL , "PSL_last_width 0 G " ); /* Rewind position to orig baseline */
5029
5109
last_sub = last_sup = false;
5030
5110
}
5111
+ if (ptr && composite ) {
5112
+ strcat (piece , ptr );
5113
+ composite = false;
5114
+ }
5031
5115
PSL_command (PSL , "%d F%d (%s) FP " , psl_ip (PSL , size ), font , piece );
5032
5116
last_chr = ptr [strlen (piece )- 1 ];
5033
5117
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
5103
5187
const char * justcmd [12 ] = {"" , "bl " , "bc " , "br " , "" , "ml " , "mc " , "mr " , "" , "tl " , "tc " , "tr " };
5104
5188
/* PS strings to be used dependent on "justify%4". Empty string added for unused value. */
5105
5189
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 ;
5107
5191
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 ;
5108
5192
bool last_sub = false, last_sup = false, supersub ;
5109
5193
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
5148
5232
return (PSL_NO_ERROR );
5149
5233
}
5150
5234
5235
+ psl_got_composite_fontswitch (PSL , string );
5236
+
5151
5237
/* For more difficult cases we use the PSL_deftextdim machinery to get the size of the font box */
5152
5238
5153
5239
if (justify > 1 ) {
@@ -5189,7 +5275,6 @@ int PSL_plottext (struct PSL_CTRL *PSL, double x, double y, double fontsize, cha
5189
5275
last_chr = ptr [strlen (ptr )- 1 ];
5190
5276
ptr = strtok_r (NULL , "@" , & plast );
5191
5277
kase = ((last_chr > 0 && last_chr < 255 ) && islower (last_chr )) ? PSL_LC : PSL_UC ;
5192
-
5193
5278
}
5194
5279
5195
5280
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
5216
5301
piece [0 ] = ptr [0 ]; piece [1 ] = 0 ;
5217
5302
ptr ++ ;
5218
5303
}
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 ;
5219
5319
if (ptr [0 ] == '\\' ) { /* Octal code again */
5220
5320
strncpy (piece2 , ptr , 4U );
5221
5321
piece2 [4 ] = 0 ;
@@ -5225,8 +5325,17 @@ int PSL_plottext (struct PSL_CTRL *PSL, double x, double y, double fontsize, cha
5225
5325
piece2 [0 ] = ptr [0 ]; piece2 [1 ] = 0 ;
5226
5326
ptr ++ ;
5227
5327
}
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
+ }
5228
5335
/* 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 );
5230
5339
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 ]);
5231
5340
strncpy (piece , ptr , 2 * PSL_BUFSIZ );
5232
5341
}
0 commit comments