diff options
Diffstat (limited to 'fonts/utilities/ps2mf/PSparse.c')
-rw-r--r-- | fonts/utilities/ps2mf/PSparse.c | 1498 |
1 files changed, 1498 insertions, 0 deletions
diff --git a/fonts/utilities/ps2mf/PSparse.c b/fonts/utilities/ps2mf/PSparse.c new file mode 100644 index 0000000000..f58e4221a4 --- /dev/null +++ b/fonts/utilities/ps2mf/PSparse.c @@ -0,0 +1,1498 @@ +/* PSparse.c */ + +#include <stdio.h> +#ifndef AIX +#include <stdlib.h> +#endif +#include <string.h> +#include <math.h> +#include <ctype.h> +#include "defines.h" +#include "myopen.h" +#include "mymalloc.h" +#include "ps2mf.h" +#include "ps2mfutl.h" +#include "PSparse.h" +#ifdef MSDOS +#include <float.h> +#endif + +float x_scale, y_scale; + +void write_MF_header () +{ + int i; + + fprintf (mf_file, "%% %s\n", font_name); + fprintf (mf_file, "mode_setup;\n"); + fprintf (mf_file, "if unknown FontSize: FontSize := 10pt#; fi\n"); + fprintf (mf_file, "FX# := FontSize * %.4f;\n", x_scale); + fprintf (mf_file, "FY# := FontSize * %.4f;\n", y_scale); + fprintf (mf_file, "bot_blues.n := %d;\n", num_of_other_blues + 1); + fprintf (mf_file, "bot_blues1o := %d;\n", blue_values [0] . overshoot); + fprintf (mf_file, "bot_blues1p := %d;\n", blue_values [0] . position); + for (i = 0; i < num_of_other_blues; i ++) + { + fprintf (mf_file, "bot_blues%do := %d;\n", i + 2, + other_blues [i] . overshoot); + fprintf (mf_file, "bot_blues%dp := %d;\n", i + 2, + other_blues [i] . position); + } + fprintf (mf_file, "top_blues.n := %d;\n", num_of_blue_values - 1); + for (i = 1; i < num_of_blue_values; i ++) + { + fprintf (mf_file, "top_blues%do := %d;\n", i, + blue_values [i] . overshoot); + fprintf (mf_file, "top_blues%dp := %d;\n", i, + blue_values [i] . position); + } + fprintf (mf_file, "blue_scale := %g;\n", blue_scale); + fprintf (mf_file, "blue_shift := %d;\n", blue_shift); + fprintf (mf_file, "blue_fuzz := %d;\n", blue_fuzz); + fprintf (mf_file, "\ninput hints;\n"); +} + +void write_MF_trailer () +{ + fprintf (mf_file, "\nfont_slant := %.4f;\n", 1 - cos (italic_angle)); + fprintf (mf_file, "font_normal_space := %d * FX#;\n", font_space); + fprintf (mf_file, "font_normal_stretch := %d * FX#;\n", + (int) (font_space / 2.0)); + fprintf (mf_file, "font_normal_shrink := %d * FX#;\n", + (int) (font_space / 3.0)); + fprintf (mf_file, "font_x_height := %d * FY#;\n", (int) x_height); + if (font_quad > 0) + { + fprintf (mf_file, "font_quad := %d * FX#;\n", font_quad); + } + else + { + fprintf (mf_file, "font_quad := %d * FX#;\n", (font_space * 3)); + } + fprintf (mf_file, "designsize := FontSize;\n"); + fprintf (mf_file, "font_coding_scheme := \"%s\";\n", coding_scheme); + fprintf (mf_file, "font_identifier := \"%s\";\n", font_name); + fprintf (mf_file, "end.\n"); + fprintf (mf_file, "%% That's all, Folks!\n"); +} + +#ifdef __STDC__ +void push (float fl) +#else +void push (fl) +float fl; +#endif +{ + if (top_of_stack >= MAX_stack) error ("! stack overflow"); + stack [top_of_stack] = fl; + top_of_stack ++; +} + +float pop () +{ + top_of_stack --; + if (top_of_stack < 0) error ("! stack underflow"); + return (stack [top_of_stack]); +} + +#ifdef __STDC__ +void eat_this_character (char * s) +#else +void eat_this_character (s) +char * s; +#endif +{ + char * this_param_string; + + do + { + get_token (ps_file); + this_param_string = param_string (); + } + while (! (strequ (this_param_string, "ND") + || strequ (this_param_string, "|-"))); +} + +#ifdef __STDC__ +bool ignore_this_character (char * s) +# else +bool ignore_this_character (s) +char * s; +# endif +{ + ignore_info_tp * ii; + + for (ii = ignore_list; ii; ii = ii -> next) + { + if (strequ (ii -> AFM_name, s)) return (TRUE); + } + return (FALSE); +} + +#ifdef __STDC__ +int charstring_command (char * s) +#else +int charstring_command (s) +char * s; +#endif +{ + char ** p; + int n; + + if (s [0] == '/') + { + s ++; + if (ignore_this_character (s) + || ((strstr (obuffer, "seac") != NULL) + && ! processing_seacs) + || ((strstr (obuffer, "seac") == NULL) + && processing_seacs)) + { + if (! have_found_seacs) have_found_seacs = TRUE; + eat_this_character (s); + return (not_a_charstring_command); + } + strcpy (current_char, s); + return (charstring_command_char); + } + for (p = charstring_commands, n = 0; * p; p ++, n ++) + if (strequ (s, * p)) return (n); + if (sscanf (s, "%f", & numeric_val) == 1) + return (charstring_command_numeric); + if (strequ (s, "end")) return (charstring_commands_end); + return (not_a_charstring_command); +} + +#ifdef __STDC__ +int PS_header_command () +#else +int PS_header_command () +#endif +{ + char ** p; + int n; + + for (p = PS_header_commands, n = 0; * p; p ++, n ++) + if (strstr (obuffer, * p) != NULL) return (n); + return (not_a_PS_header_command); +} + +/* Charstring Command Handling */ + +/* Commands for Starting and Finishing */ + +bool candidate_for_seac () +{ + char ** p; + + for (p = seac_candidates; * p; p ++) + if (strequ (current_char, * p)) + return (TRUE); + return (FALSE); +} + +void do_endchar () +{ + /* + finishes a charstring outline definition and must be the last command + in a character's outline (except for accented character defined using + *seac*). When *endchar* is executed, Type 1 BuildChar performs several + tasks. It executes a *setcachedevice* operation, using a bounding box + it computes directly from the character outline and using the width + information acquired from a previous *hsbw* or *sbw* operation. (Note + that this is not the same order of events as in Type 3 Fonts.) + BuildChar then calls a special version of *fill* or *stroke* depending + on the value of *PaintType* in the font dictionary. The Type 1 font + format supports only *PaintType* 0 (fill) and 2 (outline). Note that + this single *fill* or *stroke* implies that there can be only one path + (possibly containing several subpaths) that can be created to be + filled or stroked by the *endchar* command. + */ + + if (active_path) do_closepath (); + if (candidate_for_seac ()) + { + fprintf (mf_file, "chp[%d]:=currentpicture;\n", + current_AFM_num); + } + fprintf (mf_file, "endchar;\n"); +} + +#ifdef __STDC__ +void do_hsbw (float sbx, float wx) +#else +void do_hsbw (sbx, wx) +float sbx, wx; +#endif +{ + /* + sets the left sidebearing point at (sbx, 0) and sets the character + width vector to (wx, 0) in character space. This command also sets the + currentpoint to (sbx, 0), but does not place the point in the + character path. Use *rmoveto* for the first point in the path. The + name *hsbw* stands for horizontal sidebearing and width; horizontal + indicates that the y component of both the sidebearing and width is 0. + Either *sbw* or *hsbw* must be used once as the first command in a + character outline definition. It must be used only once. In + non-marking characters, such as the space character, the left + sidebearing point should be (0, 0). + */ + + do_sbw (sbx, 0.0, wx, 0.0); +} + +#ifdef __STDC__ +void do_seac (float asb, float adx, float ady, int bchar, int achar) +#else +void do_seac (asb, adx, ady, bchar, achar) +float asb, adx, ady; +int bchar, achar; +#endif +{ + /* + for standard encoding accented character, makes an accented character + from two other characters in its font program. The asb argument is the + x component of the left sidebearing of the accent; this value must be + the same as the sidebearing value given in the *hsbw* or *sbw* command + in the accent's own charstring. The origin of the accent is placed at + (adx, ady) relative to the origin of the base character. The bchar + argument is the character code of the base character, and the achar + argument is the the character code of the accent character. Both bchar + and achar are codes that these characters are assigned in the Adobe + StandardEncoding vector, given in an Appendix in the PostScript + Language Reference Manual. Furthermore, the characters represented by + achar and bchar must be in the same position in the font's encoding + vector as the positions they occupy in the Adobe StandardEncoding + vector. If the name of both components of an accented character do not + appear in the Adobe StandardEncoding vector, the accented character + cannot be build using the *seac* command. + + The *FontBBox* entry in the font dictionary must be large enough to + accommodate both parts of the accented character. The *sbw* or *hsbw* + command that begins the accented character must be the same as the + corresponding command in the base character. Finally, *seac* is the + last command in the charstring for the accented character because the + accent and base characters' charstrings each already end with their + own *endchar* commands. + + The use of this command saves space in a Type 1 font program, but its + use is restricted to those characters whose parts are defined in the + Adobe StandardEncoding vector. In situations where use of the *seac* + command is not possible, use of *Subrs* subroutines is a more general + means for creating accented characters. + */ + fprintf (mf_file, "seac(%d,%d,%g,%g)\n", achar, bchar, + adx + current_point . x - asb, ady); + fprintf (mf_file, "endchar;\n"); +} + +#ifdef __STDC__ +void do_sbw (float sbx, float sby, float wx, float wy) +#else +void do_sbw (sbx, sby, wx, wy) +float sbx, sby, wx, wy; +#endif +{ + /* + sets the left sidebearing point to (sbx, sby) and sets the character + width vector to (wx, wy) in character space. This command also sets + the current point to (sbx, sby), but does not place the point in the + character path. Use *rmoveto* for the first point in the path. The + name *sbw* stands for sidebearing and width; the x and y components of + both the left sidebearing and width must be specified. If the y + components of both the left sidebearing and the width are 0, then the + *hsbw* command should be used. Either *sbw* or *hsbw* must be used + once as the first command in a character outline definition. It must + be used only once. + */ + + current_point . x = sbx; + current_point . y = sby; + the_sbx = sbx; +} + +/* Path Construction Commands */ + +void do_closepath () +{ + /* + *closepath* closes a subpath. Adobe strongly recommends that all + character subpaths end with a *closepath* command, otherwise when an + outline is stroked (by setting *PaintType* equal to 2) you may get + unexpected behaviour where lines join. Note that, unlike the + *closepath* command in the PostScript language, this command does not + reposition the current point. Any subsequent *rmoveto* must be + relative to the current point in force before the Type 1 format + *closepath* command was given. + + Make sure that any subpath section formed by the *closepath* command + intended to be zero length, is zero length. If not, the *closepath* + command may cause a "spike" or "hangnail" (if the subpath doubles back + onto itself) with unexpected results. + */ + + fprintf (mf_file, " )cp\n"); + active_path = FALSE; + after_hint = FALSE; +} + +#ifdef __STDC__ +void do_hlineto (float dx) +#else +void do_hlineto (dx) +float dx; +#endif +{ + /* + for horizontal lineto. Equivalent to dx 0 *rlineto*. + */ + + do_rlineto (dx, 0.0); +} + +#ifdef __STDC__ +void do_hmoveto (float dx) +#else +void do_hmoveto (dx) +float dx; +#endif +{ + /* + for horizontal lineto. Equivalent to dx 0 *rmoveto*. + */ + + do_rmoveto (dx, 0.0); +} + +#ifdef __STDC__ +void do_hvcurveto (float dx1, float dx2, float dy2, float dy3) +#else +void do_hvcurveto (dx1, dx2, dy2, dy3) +float dx1, dx2, dy2, dy3; +#endif +{ + /* + for horizontal-vertical curveto. Equivalent to dx1 0 dx2 dy2 0 dy3 + *rrcurveto*. This command eliminates two arguments from an *rrcurveto* + call when the first B'ezier tangent is horizontal and the second + B'ezier tangent is vertical. + */ + + do_rrcurveto (dx1, 0.0, dx2, dy2, 0.0, dy3); +} + +#ifdef __STDC__ +void do_rlineto (float dx, float dy) +#else +void do_rlineto (dx, dy) +float dx, dy; +#endif +{ + /* + (relative *lineto*) appends a straight line segment to the current + path in the same manner as *lineto*. However, the number pair is + interpreted as a displacement relative to the current point (x, y) + rather than as an absolute coordinate. That is, *rlineto* constructs a + line from (x, y) to (x + dx, y + dy) and makes (x + dx, y + dy) the + new current point. If the current point is undefined because the + current path is empty, *rlineto* executes the error *nocurrentpoint*. + */ + + current_point . x += dx; + current_point . y += dy; + fprintf (mf_file, "lt%s(%g,%g)\n", + after_hint ? "h" : "", + current_point . x, + current_point . y); + after_hint = FALSE; +} + +#ifdef __STDC__ +void do_rmoveto (float dx, float dy) +#else +void do_rmoveto (dx, dy) +float dx, dy; +#endif +{ + /* + (relative *moveto*) starts a new subpath of the current path in the + same manner as *moveto*. However, the number pair is interpreted as a + displacement relative to the current point (x, y) rather than as an + absolute coordinate. That is, *rmoveto* makes (x + dx, y + dy) the new + currentpoint, without connecting it to the previous point. If the + current point is undefined because the current path is empty, *moveto* + executes the error *nocurrentpoint*. + */ + + current_point . x += dx; + current_point . y += dy; + if (active_path) do_closepath (); + path_number ++; active_path = TRUE; + if (after_hint) fprintf (mf_file, "ih\n"); + fprintf (mf_file, "dr\n"); + fprintf (mf_file, "ah((%g,%g)\n", current_point . x, + current_point . y); + after_hint = FALSE; +} + +#ifdef __STDC__ +void do_rrcurveto (float dx1, float dy1, float dx2, float dy2, float dx3, + float dy3) +#else +void do_rrcurveto (dx1, dy1, dx2, dy2, dx3, dy3) +float dx1, dy1, dx2, dy2, dx3, dy3; +#endif +{ + /* + for relative *rcurveto*. Whereas the arguments to the *rcurveto* + operator in the PostScript language are all relative to the current + point, the arguments to *rrcurveto* are relative to each other. + Equivalent to dx1 dy1 (dx1 + dx2) (dy1 + dy2) (dx1 + dx2 + dx3, dy1 + + dy2 + dy3) *rcurveto*. + */ + + do_rcurveto (dx1, dy1, dx1 + dx2, dy1 + dy2, dx1 + dx2 + dx3, + dy1 + dy2 + dy3); +} + +#ifdef __STDC__ +void do_vhcurveto (float dy1, float dx2, float dy2, float dx3) +#else +void do_vhcurveto (dy1, dx2, dy2, dx3) +float dy1, dx2, dy2, dx3; +#endif +{ + /* + for vertical-horizontal curveto. Equivalent to 0 dy1 dx2 dy2 dx3 0 + *rrcurveto*. This command eliminates two arguments from an *rrcurveto* + call when the first B'ezier tangent is vertical and the second B'ezier + tangent is horizontal. + */ + + do_rrcurveto (0.0, dy1, dx2, dy2, dx3, 0.0); +} + +#ifdef __STDC__ +void do_vlineto (float dy) +#else +void do_vlineto (dy) +float dy; +#endif +{ + /* + for vertical lineto. This is equivalent to 0 dy *rlineto*. + */ + + do_rlineto (0.0, dy); +} + +#ifdef __STDC__ +void do_vmoveto (float dy) +#else +void do_vmoveto (dy) +float dy; +#endif +{ + /* + for vertical moveto. This is equivalent to 0 dy *rmoveto*. + */ + + do_rmoveto (0.0, dy); +} + +void do_dotsection () +{ + /* + brackets an outline section for the dots in letters such as "i", "j" + and "!". This is a hint command that indicates that a section of a + charstring should be understood as describing such a feature, rather + than as port of the main outline. + */ + +} + +#ifdef __STDC__ +void do_hstem (float y, float dy) +#else +void do_hstem (y, dy) +float y, dy; +#endif +{ + /* + declares the vertical range of a horizontal stem zone between the y + coordinates y and y + dy, where y is relative to the y coordinate of + the left sidebearing point. Horizontal stem zones within a set of stem + hints for a single character may not overlap other horizontal stem + zones. Use hint replacement to avoid stem hint overlaps. + */ + + if (dy >= 0) fprintf (mf_file, "dh(\"hs(%g,%g)\")\n", y, y + dy); + else fprintf (mf_file, "dh(\"hs(%g,%g)\")\n", y + dy, y); + after_hint = TRUE; +} + +#ifdef __STDC__ +void do_hstem3 (float y0, float dy0, float y1, float dy1, float y2, float dy2) +#else +void do_hstem3 (y0, dy0, y1, dy1, y2, dy2) +float y0, dy0, y1, dy1, y2, dy2; +#endif +{ + /* + declares the vertical ranges of three horizontal stem zones between + the y coordinates y0 and y0 + dy0, y1 and y1 + dy2, and between y2 and + y2 + dy2, where y0, y1 and y2 are all relative to the y coordinate of + the left sidebearing point. The *hstem3* command sorts these zones by + the y values to obtain the lowest, middle and highest zones, called + ymin, ymid and ymax respectively. The corresponding dy values are + called dymin, dymid and dymax. These stems and the counters between + them will all be controled. These coordinates must obey certain + restrictions: + + . dymin = dymax + + . The distance from ymin + dymin/2 to ymid + dymid/2 must equal the + distance from ymid + dymid/2 to ymax + dymax/2. In other words, the + distance from the center of the bottom stem to the center of the + middle stem must be the same as the distance from the center of the + middle stem to the center of the top stem. + + If a charstring uses an *hstem3* command in the hints for a character, + the charstring must not use *hstem* commands and it must use the same + *hstem3* command consistently if hint replacement is performed. + + The *hstem3* command is especially suited for controlling the stems + and counters of symbols with three horizontally oriented features with + equal vertical widths and with equal white space between these + features, such as the mathematical equivalence symbol or the division + symbol. + */ + + do_hstem (y0, dy0); + do_hstem (y1, dy1); + do_hstem (y2, dy2); + fprintf (mf_file, "dh(\"hst\")\n"); +} + +#ifdef __STDC__ +void do_vstem (float x, float dx) +# else +void do_vstem (x, dx) +float x, dx; +# endif +{ + /* + declares the horizontal range of a vertical stem zone between the x + coordinates x and x + dx, where x is relative to the x coordinate of + the left sidebearing point. Vertical stem zones within a set of stem + hints for a single character may not overlap other vertical stem + zones. Use hint replacement to avoid stem hint overlap. + */ + + if (dx >= 0) fprintf (mf_file, "dh(\"vs(%g,%g)\")\n", x + the_sbx, + x + dx + the_sbx); + else fprintf (mf_file, "dh(\"vs(%g,%g)\")\n", x + dx + the_sbx, + x + the_sbx); + after_hint = TRUE; +} + +#ifdef __STDC__ +void do_vstem3 (float x0, float dx0, float x1, float dx1, float x2, float dx2) +#else +void do_vstem3 (x0, dx0, x1, dx1, x2, dx2) +float x0, dx0, x1, dx1, x2, dx2; +#endif +{ + /* + declares the horizontal ranges of three vertical stem zones between + the x coordinates x0 and x0 + dx0, x1 and x1 + dx2, and x2 and x2 + + dx2, where x0, x1 and x2 are all relative to the x coordinate of the + left sidebearing point. The *vstem3* command sorts these zones by the + x values to obtain the leftmost, middle and rightmost zones, called + xmin, xmid and xmax respectively. The corresponding dx values are + called dxmin, dxmid and dxmax. These stems and the counters between + them will all be controled. These coordinates must obey certain + restrictions: + + . dxmin = dxmax + + . The distance from xmin + dxmin/2 to xmid + dxmid/2 must equal the + distance from xmid + dxmid/2 to xmax + dxmax/2. In other words, the + distance from the center of the left stem to the center of the + middle stem must be the same as the distance from the center of the + middle stem to the center of the right stem. + + If a charstring uses an *vstem3* command in the hints for a character, + the charstring must not use *vstem* commands and it must use the same + *vstem3* command consistently if hint replacement is performed. + + The *vstem3* command is especially suited for controlling the stems + and counters of characters such as a lower case "m". + */ + + do_vstem (x0, dx0); + do_vstem (x1, dx1); + do_vstem (x2, dx2); + fprintf (mf_file, "dh(\"vst\")\n"); +} + +#ifdef __STDC__ +void do_rcurveto (float dx1, float dy1, float dx2, float dy2, float dx3, + float dy3) +#else +void do_rcurveto (dx1, dy1, dx2, dy2, dx3, dy3) +float dx1, dy1, dx2, dy2, dx3, dy3; +#endif +{ + /* + (relative *curveto*) adds a B'ezier cubic section to the current path + in the same manner as *curveto*. However, the three number pairs are + interpreted as displacements relative to the current point (x0, y0) + rather than as absolute coordinates. That is, *rcurveto* constructs a + curve from (x0, y0) to (x0 + dx3, y0 + dy3), using (x0 + dx1, y0 + + dy1) and (x0 + dx2, y0 + dy2) as B'ezier control points. + */ + + fprintf (mf_file, "ct%s(%g,%g,%g,%g,%g,%g)\n", + after_hint ? "h" : "", + current_point . x + dx1, + current_point . y + dy1, + current_point . x + dx2, + current_point . y + dy2, + current_point . x + dx3, + current_point . y + dy3); + current_point . x += dx3; + current_point . y += dy3; + after_hint = FALSE; +} + +/* Arithmetic Command */ + +#ifdef __STDC__ +void do_div (float num1, float num2) +#else +void do_div (num1, num2) +float num1, num2; +#endif +{ + /* + divides num1 by num2, producing a result that is always a real even if + both operands are integers + */ + + push (num1 / num2); +} + +/* Subroutine Commands */ + +#ifdef __STDC__ +void do_moveto_for_flex (float dx, float dy) +# else +void do_moveto_for_flex (dx, dy) +float dx, dy; +#endif +{ + current_point . x += dx; + current_point . y += dy; + flex . x [flex . n] = current_point . x; + flex . y [flex . n] = current_point . y; +} + +#ifdef __STDC__ +void do_callothersubr (int othersubr, int n) +#else +void do_callothersubr (othersubr, n) +int othersubr, n; +#endif +{ + /* + is a mechanism used by Type 1 BuildChar to make calls on the + PostScript interpreter. Arguments argn through arg1 are pushed onto + the PostScript interpreter operand stack, and the PostScript language + procedure in the othersubr# position in the *OtherSubrs* array in the + *Private* dictionary (or a built-in function equivalent to this + procedure) is executed. Note that the argument order will be reversed + when pushed onto the PostScript interpreter operand stack. After the + arguments are pushed onto the PostScript interpreter operand stack, + the PostScript interpreter performs a *begin* operation on + *systemdict* followed by a *begin* operation on the font dictionary + prior to executing the *OtherSubrs* entry. When the *OtherSubrs* entry + completes its execution, the PostScript interpreter performs two *end* + operations prior to returning to Type 1 BuildChar charstring + execution. Use *pop* commands to retrieve results from the PostScript + operand stack back to the Type 1 BuildChar operand stack. + */ + + float flex_h; + + switch (othersubr) + { + case 0: + { + (void) pop (); /* end point y */ + (void) pop (); /* end point x */ + flex_h = pop (); /* flex feature height */ + if (! active_flex) + error ("! othersub 1 required before Flex othersub 0\n"); + if (flex . n != 7) + error ("! seven calls to othersub 2 required before Flex othersub 0\n"); + fprintf (mf_file, + " fl%s(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g)\n", + after_hint ? "h" : "", + flex . x [0], flex . y [0], + flex . x [1], flex . y [1], + flex . x [2], flex . y [2], + flex . x [3], flex . y [3], + flex . x [4], flex . y[4], + flex . x [5], flex . y [5], + flex . x [6], flex . y [6], + flex_h); + active_flex = after_hint = FALSE; + } + break; + case 1: + { + active_flex = TRUE; + flex . n = 0; + } + break; + case 2: + { + flex . n ++; + } + break; + case 3: + { + if (active_path && ! after_hint) + fprintf (mf_file, " )\n"); + } + break; + } +} + +#ifdef __STDC__ +void do_callsubr (int subr_no) +#else +void do_callsubr (subr_no) +int subr_no; +#endif +{ + /* + calls a charstring subroutine with index subr# form the *Subrs* array + in the *private* dictionary. Each element of the *Subrs* array is a + charstring encoded and encrypted like any other charstring. Arguments + pushed on the Type 1 BuildChar operand stack prior to calling the + subroutine, and results pushed on the stack by the subroutine, act + according to the manner in which the subroutine is coded. These + subroutines are generally used to encode sequences of path commands + that are repeated throughout the font program, for example, serif + outline sequences. Subroutine calls may be nested 10 deep. + */ + + if (Subrs_entries [subr_no] == NULL) + { + error ("! Undefined subroutine called"); + } + processing_Subr = TRUE; + current_Subr ++; + Subrs_stack [current_Subr] = Subrs_entries [subr_no]; +} + +float do_pop () +{ + /* + removes a number from the top of the PostScript interpreter operand + stack and pushes that number onto the Type1 BuildChar operand stack. + This command is used only to retrieve a result from an *OtherSubrs* + procedure. + */ + + return (0.0); +} + +void do_return () +{ + /* + returns from a *Subrs* array charstring subroutine (that had been + called with a *callsubr* command) and continues execution in the + calling charstring. + */ + + current_Subr --; + if (current_Subr < 0) processing_Subr = FALSE; +} + +#ifdef __STDC__ +void do_setcurrentpoint (float x, float y) +#else +void do_setcurrentpoint (x, y) +float x, y; +#endif +{ + /* + sets the current point in the Type 1 format *BuildChar* to (x, y) in + absolute character space coordinates without performing a charstring + *moveto* command. This establishes the current point for a subsequent + relative path building command. The *setcurrentpoint* command is used + only in conjunction with results from *OtherSubrs* procedures. + */ + + current_point . x = x; + current_point . y = y; +} + +void process_hstem () /* hstem: |- y dy hstem (1) |- */ +{ + float y, dy; + + dy = pop (); + y = pop (); + do_hstem (y, dy); +} + + +void process_vstem () /* vstem: |- x dx vstem (3) |- */ +{ + float x, dx; + + dx = pop (); + x = pop (); + do_vstem (x, dx); +} + + +void process_vmoveto () /* vmoveto: |- dy vmoveto (4) |- */ +{ + float dy; + + dy = pop (); + if (active_flex) do_moveto_for_flex (0.0, dy); + else do_vmoveto (dy); +} + +void process_rlineto () /* rlineto: |- dx dy rlineto (5) |- */ +{ + float dx, dy; + + dy = pop (); + dx = pop (); + do_rlineto (dx, dy); +} + +void process_hlineto () /* hlineto: |- dx hlineto (6) |- */ +{ + float dx; + + dx = pop (); + do_hlineto (dx); +} + +void process_vlineto () /* vlineto: |- dy vlineto (7) |- */ +{ + do_vlineto (pop ()); +} + +void process_rrcurveto () /* rrcurveto: |- dx1 dy1 dx2 dy2 dx3 dy3 rrcurveto (8) |- */ +{ + float dx1, dy1, dx2, dy2, dx3, dy3; + + dy3 = pop (); + dx3 = pop (); + dy2 = pop (); + dx2 = pop (); + dy1 = pop (); + dx1 = pop (); + do_rrcurveto (dx1, dy1, dx2, dy2, dx3, dy3); +} + +void process_closepath () /* - closepath (9) |- */ +{ + do_closepath (); +} + +void process_callsubr () /* subr# callsubr */ +{ + do_callsubr ((int) pop ()); +} + +void process_return () /* - return (11) - */ +{ + /* + returns from a *Subrs* array charstring subroutine (that had been + called with a *callsubr* command) and continues execution in the + calling charstring. + */ + + do_return (); +} + +void process_escape () /* escape (12) */ +{ + /* skip */; +} + +void process_hsbw () /* |- sbx wx hsbw (13) |- */ +{ + float sbx, wx; + + wx = pop (); + sbx = pop (); + do_hsbw (sbx, wx); +} + +void process_endchar () /* - endchar (14) |- */ +{ + do_endchar (); +} + +void process_rmoveto () /* |- dx dy rmoveto (21) |- */ +{ + float dx, dy; + + dy = pop (); + dx = pop (); + if (active_flex) do_moveto_for_flex (dx, dy); + else do_rmoveto (dx, dy); +} + +void process_hmoveto () /* |- dx hmoveto (22) |- */ +{ + float dx; + + dx = pop (); + if (active_flex) do_moveto_for_flex (dx, 0.0); + else do_hmoveto (dx); +} + +void process_vhcurveto () /* |- dy1 dx2 dy2 dx3 vhcurveto (30) |- */ +{ + float dy1, dx2, dy2, dx3; + + dx3 = pop (); + dy2 = pop (); + dx2 = pop (); + dy1 = pop (); + do_vhcurveto (dy1, dx2, dy2, dx3); +} + +void process_hvcurveto () /* |- dx1 dx2 dy2 dy3 hvcurveto (31) |- */ +{ + float dx1, dx2, dy2, dy3; + + dy3 = pop (); + dy2 = pop (); + dx2 = pop (); + dx1 = pop (); + do_hvcurveto (dx1, dx2, dy2, dy3); +} + +void process_dotsection () /* - dotsection (12 0) |- */ +{ + do_dotsection (); +} + +void process_vstem3 () /* |- x0 dx0 x1 dx1 x2 dx2 vstem3 (12 1) |- */ +{ + float x0, dx0, x1, dx1, x2, dx2; + + dx2 = pop (); + x2 = pop (); + dx1 = pop (); + x1 = pop (); + dx0 = pop (); + x0 = pop (); + do_vstem3 (x0, dx0, x1, dx1, x2, dx2); +} + +void process_hstem3 () /* |- y0 dy0 y1 dy1 y2 dy2 hstem3 (12 2) |- */ +{ + float y0, dy0, y1, dy1, y2, dy2; + + dy2 = pop (); + y2 = pop (); + dy1 = pop (); + y1 = pop (); + dy0 = pop (); + y0 = pop (); + do_hstem3 (y0, dy0, y1, dy1, y2, dy2); +} + +void process_seac () /* |- asb adx ady bchar achar seac (12 6) |- */ +{ + float asb, adx, ady; + int bchar, achar; + + achar = (int) pop (); + bchar = (int) pop (); + ady = pop (); + adx = pop (); + asb = pop (); + do_seac (asb, adx, ady, bchar, achar); +} + +void process_sbw () /* |- sbx sby wx wy sbw (12 7) |- */ +{ + float sbx, sby, wx, wy; + + wy = pop (); + wx = pop (); + sby = pop (); + sbx = pop (); + do_sbw (sbx, sby, wx, wy); +} + +void process_div () /* num1 num2 div (12 12) quotient */ +{ + float num1, num2; + + num2 = pop (); + num1 = pop (); + do_div (num1, num2); +} + +void process_callothersubr () /* arg1 ... argn n othersubr# callothersubr (12 16) - */ +{ + int othersubr, n; + + othersubr = (int) pop (); + n = (int) pop (); + do_callothersubr (othersubr, n); +} + +float process_pop () +{ + return (do_pop ()); +} + +void process_setcurrentpoint () /* |- x y setcurrentpoint (12 33) |- */ +{ + float x, y; + + y = pop (); + x = pop (); + do_setcurrentpoint (x, y); +} + + +#ifdef __STDC__ +void start_char (char * name) +#else +void start_char (name) +char * name; +#endif +{ + AFM_info_tp * ai; + + ai = find_AFM_info_for (name); + if (ai == NULL || ai -> TeX_num == -1) + { +/* fprintf (stderr, "No TeX coding found for character %s\n", + name); */ + eat_this_character (name); + return; + } + if (first_time_generating) + { + fprintf (stderr, "Generating MF code for %s", name); + linepos = strlen ("Generating MF code for "); + linepos += strlen (name); + first_time_generating = FALSE; + } + else + { + if (linepos + strlen (name) + 3 < 79) + { + fprintf (stderr, ", %s", name); + linepos += strlen (name) + 3; + } + else + { + fprintf (stderr, ",\n %s", name); + linepos = strlen (name) + 2; + } + } + fprintf (mf_file, "\nbeginchar(%d,%d*FX#,%d*FY#,%d*FY#);\n", + ai -> TeX_num, ai -> width, ai -> bbox_ury, + (ai -> bbox_lly == 0) ? 0 : -ai -> bbox_lly); + fprintf (mf_file, "\"%s\";\n", ai -> AFM_name); + path_number = 0; active_path = FALSE; + ai -> in_MF_file = TRUE; + current_AFM_num = ai -> AFM_num; +} + +Subrs_entry_tp * new_Subrs_entry () +{ + Subrs_entry_tp * nse; + + nse = (Subrs_entry_tp *) my_malloc (sizeof (Subrs_entry_tp)); + nse -> token = NULL; + nse -> next = NULL; + return (nse); +} + +void process_one_Subrs_entry () +{ + Subrs_entry_tp * se, * nse, * lse; + char * p; + int n; + bool stop; + + stop = FALSE; + expect ("dup"); + n = param_num (); + if (n >= MAX_Subrs_entries) error ("! Too many Subrs"); + se = new_Subrs_entry (); + lse = se; + while (! stop) + { + nse = new_Subrs_entry (); + nse -> token = param_new_string (); + if (strequ (nse -> token, "return")) stop = TRUE; + lse -> next = nse; + lse = nse; + if (! * param) get_line (ps_file); + } + Subrs_entries [n] = se; +} + +void process_Subrs_entries () +{ + int i; + + while (get_line (ps_file)) + { + if (strstr (obuffer, "dup") == NULL) return; + else process_one_Subrs_entry (); + } +} + +void get_paint_type () +{ + char * dummy_string; + int dummy_int; + + dummy_string = param_string (); + dummy_int = param_num (); + if (dummy_int != 0) error ("! Can only handle outlinefonts"); +} + +void get_font_type () +{ + char * dummy_string; + int dummy_int; + + dummy_string = param_string (); + dummy_int = param_num (); + if (dummy_int != 1) error ("! Can only translate Type 1 fonts"); +} + +void get_font_matrix () +{ + char * dummy_string; + float dummy_float; + + dummy_string = param_string (); + if (* param == '[') + { + param ++; + while (* param == ' ') param ++; + } + x_scale = param_float (); + dummy_float = param_float (); + dummy_float = param_float (); + y_scale = param_float (); +} + +void get_italic_angle () +{ + char * dummy_string; + float dummy_float; + + dummy_string = param_string (); + if (italic_angle != param_float ()) + { + error ("! PS en AFM do not match"); + } +} + +void get_is_fixed_pitch () +{ + char * dummy_string; + + dummy_string = param_string (); + if (fixed_pitch != ((* param == 't' || * param == 'T') ? TRUE : FALSE)) + { + error ("! PS en AFM do not match"); + } +} + +void get_blue_scale () +{ + char * dummy_string; + float dummy_float; + int dummy_int; + + dummy_string = param_string (); + blue_scale = param_float (); +} + +void get_blue_shift () +{ + char * dummy_string; + float dummy_float; + int dummy_int; + + dummy_string = param_string (); + blue_shift = param_num (); +} + +void get_blue_fuzz () +{ + char * dummy_string; + float dummy_float; + int dummy_int; + + dummy_string = param_string (); + blue_fuzz = param_num (); +} + +void get_blue_values () +{ + char * dummy_string; + + num_of_blue_values = 0; + dummy_string = param_string (); + if (* param == '[') + { + param ++; + while (* param == ' ') param ++; + } + while (isdigit (* param) || * param == '-') /* added ILH */ + { + if (num_of_blue_values == 0) + { + blue_values [num_of_blue_values] . overshoot + = param_num (); + blue_values [num_of_blue_values] . position + = param_num (); + } + else + { + blue_values [num_of_blue_values] . position + = param_num (); + blue_values [num_of_blue_values] . overshoot + = param_num (); + } + num_of_blue_values ++; +/* if (num_of_blue_values >= MAX_blue_values) */ + } +} + +void get_other_blues () +{ + char * dummy_string; + float dummy_float; + int dummy_int; + + num_of_other_blues = 0; + dummy_string = param_string (); + if (* param == '[') + { + param ++; + while (* param == ' ') param ++; + } + while (isdigit (* param) || * param == '-') /* added ILH */ + { + other_blues [num_of_other_blues] . overshoot = param_num (); + other_blues [num_of_other_blues] . position = param_num (); + num_of_other_blues ++; +/* if (num_of_other_blues >= MAX_other_blues) */ + } +} + +void parse_PS_header () +{ + /* Skip PS file until FontInfo entry -- the FontInfo case below will + not be called because we eat it now */ + while (get_line (ps_file) && PS_header_command () != FontInfo) + /* skip */; + while (get_line (ps_file)) + { + switch (PS_header_command ()) + { + case FontInfo: break; + case FontName: break; + case Encoding: break; + case PaintType: + { + get_paint_type (); + } + break; + case FontType: + { + get_font_type (); + } + break; + case FontMatrix: + { + get_font_matrix (); + } + break; + case FontBBox: break; + case UniqueID: break; + case Metrics: break; + case StrokeWidth: break; + case Private: break; + case CharStrings: + { + get_line (ps_file); + return; + } + case FID: break; + case version: break; + case Notice: break; + case FullName: break; + case FamilyName: break; + case Weight: break; + case ItalicAngle: + { + get_italic_angle (); + } + break; + case isFixedPitch: + { + get_is_fixed_pitch (); + } + break; + case UnderlinePosition: break; + case UnderlineThickness: break; + case BlueFuzz: + { + get_blue_fuzz (); + } + break; + case BlueScale: + { + get_blue_scale (); + } + break; + case BlueShift: + { + get_blue_shift (); + } + break; + case BlueValues: + { + get_blue_values (); + } + break; + case ExpansionFactor: break; + case FamilyBlues: break; + case FamilyOtherBlues: break; + case ForceBold: break; + case LanguageGroup: break; + case lenIV: break; + case MinFeature: break; + case ND: break; + case NP: break; + case OtherSubrs: break; + case OtherBlues: + { + get_other_blues (); + } + break; + case password: break; + case RD: break; + case RndStemUp: break; + case StdHW: break; + case StdVW: break; + case StemSnapH: break; + case StemSnapV: break; + case Subrs: + { + process_Subrs_entries (); + } + break; + case not_a_PS_header_command: break; + default: break; + } + } +} + +char * next_param_string () +{ + if (! processing_Subr) return (param_string ()); + Subrs_stack [current_Subr] = Subrs_stack [current_Subr] -> next; + return (Subrs_stack [current_Subr] -> token); +} + +void parse_charstrings_dictionary () +{ + float dummy; + + processing_Subr = FALSE; + current_Subr = -1; + while (get_token (ps_file)) + { + switch (charstring_command (next_param_string ())) + { + case hstem: process_hstem (); break; + case vstem: process_vstem (); break; + case vmoveto: process_vmoveto (); break; + case rlineto: process_rlineto (); break; + case hlineto: process_hlineto (); break; + case vlineto: process_vlineto (); break; + case rrcurveto: process_rrcurveto (); break; + case closepath: process_closepath (); break; + case callsubr: process_callsubr (); break; + case return_command: process_return (); break; + case escape: process_escape (); break; + case hsbw: process_hsbw (); break; + case endchar: process_endchar (); break; + case rmoveto: process_rmoveto (); break; + case hmoveto: process_hmoveto (); break; + case vhcurveto: process_vhcurveto (); break; + case hvcurveto: process_hvcurveto (); break; + case dotsection: process_dotsection (); break; + case vstem3: process_vstem3 (); break; + case hstem3: process_hstem3 (); break; + case seac: process_seac (); break; + case sbw: process_sbw (); break; + case div: process_div (); break; + case callothersubr: process_callothersubr (); + break; + case pop_command: dummy = process_pop (); break; + case charstring_command_numeric: + push (numeric_val); break; + case charstring_command_char: + start_char (current_char); + break; + case charstring_commands_end: return; + default: break; + } + } +} + +void parse_PS () +{ + top_of_stack = 0; + x_scale = 1000; y_scale = 1000; + have_found_seacs = FALSE; after_hint = FALSE; + the_sbx = 0.0; + blue_scale = 0.039625; blue_shift = 7; blue_fuzz = 1; + first_time_generating = TRUE; + parse_PS_header (); + write_MF_header (); + charstring_position = ftell (ps_file); + processing_seacs = FALSE; + parse_charstrings_dictionary (); + if (have_found_seacs) + { + fseek (ps_file, charstring_position, 0); + processing_seacs = TRUE; + parse_charstrings_dictionary (); + } + fprintf (stderr, ".\n"); + process_ligatures_and_kerns (); + write_MF_trailer (); +} |