@@ -166,32 +166,47 @@ static char *PSL_label_str =
166166" % same point.\n"
167167"\n"
168168"/setchar % ``setchar'' sets the next\n"
169- " { /char str charcount 1 getinterval def % character in the string along\n"
169+ " % character in the string along\n"
170170" % the path and then updates the\n"
171171" % amount of path we have\n"
172172" % exhausted.\n"
173- " /charcount charcount 1 add def % Increment the character count.\n"
174- " /charwidth char stringwidth pop def % Find the width of the character.\n"
175- " V cpx cpy itransform T % Translate to the current\n"
173+ " { charcount 1 add str length lt % Check if at least 2 chars remain\n"
174+ " {str charcount get 64 eq str charcount 1 add get 126 eq and} {false} ifelse\n"
175+ " { % Found @~ escape: skip it, toggle font, no rendering\n"
176+ " /charcount charcount 2 add def\n"
177+ " /psl_ct_sym psl_ct_sym not def\n"
178+ " psl_ct_sym {\n"
179+ " /psl_ct_origfont currentfont def\n"
180+ " /Symbol findfont PSL_get_fontsize scalefont setfont\n"
181+ " } {\n"
182+ " psl_ct_origfont setfont\n"
183+ " } ifelse\n"
184+ " }\n"
185+ " { % Normal character rendering\n"
186+ " /char str charcount 1 getinterval def\n"
187+ " /charcount charcount 1 add def\n"
188+ " /charwidth char stringwidth pop def\n"
189+ " V cpx cpy itransform T % Translate to the current\n"
176190" % position in user space.\n"
177- " dy dx atan R % Rotate the x-axis to coincide\n"
191+ " dy dx atan R % Rotate the x-axis to coincide\n"
178192" % with the current segment.\n"
179- " 0 justy M\n"
180- " PSL_font_F { % Show text normally, if requested\n"
181- " char show}\n"
182- " if\n"
183- " PSL_font_FO { % Fill first then outline, if requested\n"
184- " currentpoint N M V char true charpath fs U V char false charpath S U char E 0 G\n"
185- " } if\n"
186- " PSL_font_OF { % Outline text then fill, if requested\n"
187- " currentpoint N M V char false charpath S U V char true charpath fs U char E 0 G\n"
188- " } if\n"
189- " 0 justy neg G currentpoint transform\n"
190- " /cpy exch def /cpx exch def % Update the current position\n"
191- " % before we restore ourselves to\n"
193+ " 0 justy M\n"
194+ " PSL_font_F { % Show text normally, if requested\n"
195+ " char show}\n"
196+ " if\n"
197+ " PSL_font_FO { % Fill first then outline, if requested\n"
198+ " currentpoint N M V char true charpath fs U V char false charpath S U char E 0 G\n"
199+ " } if\n"
200+ " PSL_font_OF { % Outline text then fill, if requested\n"
201+ " currentpoint N M V char false charpath S U V char true charpath fs U char E 0 G\n"
202+ " } if\n"
203+ " 0 justy neg G currentpoint transform\n"
204+ " /cpy exch def /cpx exch def % Update the current position\n"
205+ " % before we restore ourselves to\n"
192206" % the untransformed state.\n"
193- " U /setdist setdist charwidth add def % Increment the distance we have\n"
194- " } def % covered by setting characters.\n"
207+ " U /setdist setdist charwidth add def % Increment the distance we have\n"
208+ " } ifelse % covered by setting characters.\n"
209+ " } def\n"
195210"end\n"
196211"\n"
197212"% PSL LABEL CLIP FUNCTIONS\n"
@@ -336,7 +351,7 @@ static char *PSL_label_str =
336351" 0 1 PSL_m1\n"
337352" { /i exch def\n"
338353" PSL_fnt_tmp i get cvx exec % Get and set this label's font attributes\n"
339- " PSL_width_tmp i PSL_str_tmp i get stringwidth pop put % Compute width and store in the array\n"
354+ " PSL_width_tmp i PSL_str_tmp i get PSL_label_sw put % Compute width and store in the array\n"
340355" } for\n"
341356"} def\n"
342357"\n"
@@ -475,6 +490,7 @@ static char *PSL_label_str =
475490" PSL_drawbox % Want to draw outline of box\n"
476491" {V PSL_setboxpen S U} if N\n"
477492" } if\n"
493+ " /psl_ct_sym false def\n"
478494" PSL_CT_placeline psl_label PSL_gap_x PSL_just PSL_height psl_depth PSL_pathtext\n"
479495"} def\n"
480496"\n"
@@ -629,6 +645,110 @@ static char *PSL_label_str =
629645" PSL_eoclip N % Set the new clip path, increment clip counter and clear path\n"
630646"} def\n"
631647"\n"
648+ "% Escape-aware label rendering procedures.\n"
649+ "% These handle the @~ escape sequence (Symbol font toggle) in label strings.\n"
650+ "% When @~ is found, the string is split into segments that alternate between\n"
651+ "% the current font and the Symbol font at the same size.\n"
652+ "\n"
653+ "/PSL_split_esc { % (string) PSL_split_esc => array of substrings split on @~\n"
654+ " /psl_src exch def\n"
655+ " /psl_parts 20 array def\n"
656+ " /psl_np 0 def\n"
657+ " /psl_pos 0 def\n"
658+ " {\n"
659+ " /psl_found false def\n"
660+ " psl_pos 1 psl_src length 2 sub {\n"
661+ " /psl_i exch def\n"
662+ " psl_src psl_i get 64 eq % '@' = ASCII 64\n"
663+ " psl_src psl_i 1 add get 126 eq and % '~' = ASCII 126\n"
664+ " {\n"
665+ " psl_parts psl_np psl_src psl_pos psl_i psl_pos sub getinterval put\n"
666+ " /psl_np psl_np 1 add def\n"
667+ " /psl_pos psl_i 2 add def\n"
668+ " /psl_found true def\n"
669+ " exit\n"
670+ " } if\n"
671+ " } for\n"
672+ " psl_found not {exit} if\n"
673+ " } loop\n"
674+ " psl_pos psl_src length lt {\n"
675+ " psl_parts psl_np psl_src psl_pos psl_src length psl_pos sub getinterval put\n"
676+ " /psl_np psl_np 1 add def\n"
677+ " } if\n"
678+ " psl_parts 0 psl_np getinterval\n"
679+ "} def\n"
680+ "\n"
681+ "/PSL_has_esc { % (string) PSL_has_esc => bool -- true if string contains @~\n"
682+ " /psl_ts exch def\n"
683+ " /psl_he false def\n"
684+ " 0 1 psl_ts length 2 sub {\n"
685+ " /psl_ti exch def\n"
686+ " psl_ts psl_ti get 64 eq psl_ts psl_ti 1 add get 126 eq and\n"
687+ " {/psl_he true def exit} if\n"
688+ " } for\n"
689+ " psl_he\n"
690+ "} def\n"
691+ "\n"
692+ "/PSL_get_fontsize { % => fontsize -- extract size from current font\n"
693+ " currentfont /FontMatrix get 0 get 1000 mul\n"
694+ "} def\n"
695+ "\n"
696+ "/PSL_show_esc { % (string) PSL_show_esc => -- -- show with @~ font toggling\n"
697+ " PSL_split_esc\n"
698+ " /psl_origfont currentfont def\n"
699+ " /psl_sym false def\n"
700+ " /psl_fsz PSL_get_fontsize def\n"
701+ " { /psl_seg exch def\n"
702+ " psl_seg length 0 gt {psl_seg show} if\n"
703+ " /psl_sym psl_sym not def\n"
704+ " psl_sym {/Symbol findfont psl_fsz scalefont setfont}\n"
705+ " {psl_origfont setfont} ifelse\n"
706+ " } forall\n"
707+ " psl_origfont setfont\n"
708+ "} def\n"
709+ "\n"
710+ "/PSL_charpath_esc { % (string) PSL_charpath_esc => -- -- false charpath with @~ toggling\n"
711+ " PSL_split_esc\n"
712+ " /psl_origfont currentfont def\n"
713+ " /psl_sym false def\n"
714+ " /psl_fsz PSL_get_fontsize def\n"
715+ " { /psl_seg exch def\n"
716+ " psl_seg length 0 gt {psl_seg false charpath} if\n"
717+ " /psl_sym psl_sym not def\n"
718+ " psl_sym {/Symbol findfont psl_fsz scalefont setfont}\n"
719+ " {psl_origfont setfont} ifelse\n"
720+ " } forall\n"
721+ " psl_origfont setfont\n"
722+ "} def\n"
723+ "\n"
724+ "/PSL_sw_esc { % (string) PSL_sw_esc => width -- stringwidth with @~ toggling\n"
725+ " PSL_split_esc\n"
726+ " /psl_origfont currentfont def\n"
727+ " /psl_sym false def\n"
728+ " /psl_fsz PSL_get_fontsize def\n"
729+ " /psl_tw 0 def\n"
730+ " { /psl_seg exch def\n"
731+ " psl_seg length 0 gt {/psl_tw psl_tw psl_seg stringwidth pop add def} if\n"
732+ " /psl_sym psl_sym not def\n"
733+ " psl_sym {/Symbol findfont psl_fsz scalefont setfont}\n"
734+ " {psl_origfont setfont} ifelse\n"
735+ " } forall\n"
736+ " psl_origfont setfont\n"
737+ " psl_tw\n"
738+ "} def\n"
739+ "\n"
740+ "/PSL_label_show { % (string) PSL_label_show => --\n"
741+ " dup PSL_has_esc {PSL_show_esc} {show} ifelse\n"
742+ "} def\n"
743+ "\n"
744+ "/PSL_label_charpath { % (string) PSL_label_charpath => --\n"
745+ " dup PSL_has_esc {PSL_charpath_esc} {false charpath} ifelse\n"
746+ "} def\n"
747+ "\n"
748+ "/PSL_label_sw { % (string) PSL_label_sw => width\n"
749+ " dup PSL_has_esc {PSL_sw_esc} {stringwidth pop} ifelse\n"
750+ "} def\n"
751+ "\n"
632752"/PSL_ST_prepare_text % Compute various dimensions and coordinates for one label\n"
633753"{ % The current label has index psl_k\n"
634754" /psl_xp PSL_txt_x psl_k get def % Get text placement x coordinate\n"
@@ -640,7 +760,7 @@ static char *PSL_label_str =
640760" /PSL_just PSL_label_justify psl_k get def % Get text justification (1-11)\n"
641761" /PSL_justx PSL_just 4 mod 1 sub 2 div neg def % This is 0, -0.5, or -1 for relative x-shift \n"
642762" /PSL_justy PSL_just 4 idiv 2 div neg def % This is 0, -0.5, or -1 for relative y-shift \n"
643- " /psl_SW psl_label stringwidth pop def % Width of current label space\n"
763+ " /psl_SW psl_label PSL_label_sw def % Width of current label space\n"
644764" /psl_boxW psl_SW PSL_gap_x 2 mul add def % Width of current label space including clearance\n"
645765" /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"
646766" /psl_y0 PSL_justy PSL_height mul def %\n"
@@ -680,23 +800,23 @@ static char *PSL_label_str =
680800"{\n"
681801" V psl_xp psl_yp T psl_angle R % Set origin at text point and rotate the coordinate system to follow baseline text\n"
682802" psl_SW PSL_justx mul psl_y0 M % Goto LL point on label\n"
683- " psl_label dup sd neg 0 exch G show % Place the text, adjust vertically for any depth below baseline\n"
803+ " psl_label dup sd neg 0 exch G PSL_label_show % Place the text, adjust vertically for any depth below baseline\n"
684804" U % Undo damage to coordinate system\n"
685805"} def\n"
686806"\n"
687807"/PSL_ST_place_label_FO % Just place the current label by filling it, then outlining it\n"
688808"{\n"
689809" V psl_xp psl_yp T psl_angle R % Set origin at text point and rotate the coordinate system to follow baseline text\n"
690810" psl_SW PSL_justx mul psl_y0 M % Goto LL point on label\n"
691- " psl_label dup sd neg 0 exch G false charpath V fs U S N % Place the text, adjust vertically for any depth below baseline\n"
811+ " 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"
692812" U % Undo damage to coordinate system\n"
693813"} def\n"
694814"\n"
695815"/PSL_ST_place_label_OF % Just place the current label by drawing outline, then filling it\n"
696816"{\n"
697817" V psl_xp psl_yp T psl_angle R % Set origin at text point and rotate the coordinate system to follow baseline text\n"
698818" psl_SW PSL_justx mul psl_y0 M % Goto LL point on label\n"
699- " psl_label dup sd neg 0 exch G false charpath V S U fs N % Place the text, adjust vertically for any depth below baseline\n"
819+ " 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"
700820" U % Undo damage to coordinate system\n"
701821"} def\n"
702822"\n"
0 commit comments