summaryrefslogtreecommitdiff
path: root/fonts/utilities/ps2mf/PSparse.c
diff options
context:
space:
mode:
Diffstat (limited to 'fonts/utilities/ps2mf/PSparse.c')
-rw-r--r--fonts/utilities/ps2mf/PSparse.c1498
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 ();
+}