summaryrefslogtreecommitdiff
path: root/charspace/old-output.c
diff options
context:
space:
mode:
Diffstat (limited to 'charspace/old-output.c')
-rw-r--r--charspace/old-output.c357
1 files changed, 357 insertions, 0 deletions
diff --git a/charspace/old-output.c b/charspace/old-output.c
new file mode 100644
index 0000000..9d9f7a7
--- /dev/null
+++ b/charspace/old-output.c
@@ -0,0 +1,357 @@
+/* output.c: output
+
+Copyright (C) 1992 Free Software Foundation, Inc.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "config.h"
+
+#include "filename.h"
+#include "libfile.h"
+#include "report.h"
+
+#include "main.h"
+#include "output.h"
+
+
+/* The assignments to the TFM fontdimen values. (-fontdimens) */
+string fontdimens = NULL;
+
+/* The name of the output file specified by the user. (-output-file) */
+string output_name = NULL;
+
+/* The character code to use for the x-height. (-xheight-char) */
+charcode_type xheight_char = 120; /* `x' in ASCII. */
+
+
+static void finalize_kern_list (tfm_char_type *, char_type *[]);
+static void finalize_lig_list (tfm_char_type *, char_type *[]);
+static tfm_global_info_type find_tfm_info (char_type *[]);
+static gf_char_type make_gf_char (char_info_type);
+static void update_tfm_info_from_symtab (tfm_global_info_type *);
+static void write_gf (bitmap_font_type, char_type *[]);
+static void write_tfm (char_type *[]);
+static boolean write_tfm_char (charcode_type, char_type *[]);
+
+/* Output a TFM and (optionally) GF file with the characters in CHARS.
+ Use the characters from BITMAP_FONT for the shapes. We use an
+ existing TFM file, the encoding file, and command line arguments to
+ determine the metric information. */
+
+void
+output_font (bitmap_font_type bitmap_font, char_type *chars[])
+{
+ write_tfm (chars);
+
+ if (!no_gf)
+ write_gf (bitmap_font, chars);
+}
+
+/* Write a TFM file with CHARS. */
+
+static void
+write_tfm (char_type *chars[])
+{
+ unsigned this_char;
+ unsigned char_count = 0;
+ string pl_output_name = extend_filename (output_name, "pl");
+ tfm_global_info_type tfm_info = find_tfm_info (chars);
+
+ /* If `have_tfm', we've already opened the input file. */
+ string input_tfm_name = have_tfm ? tfm_input_filename () : NULL;
+
+ /* We remove the suffix before making the PL name because if the user
+ said `-output-file=foo.bar', it's the TFM file which should be
+ named `foo.bar'; the PL file is still named `foo.pl'. */
+ string output_root = remove_suffix (output_name);
+ string pl_name = extend_filename (output_root, "pl");
+ string output_tfm_name = extend_filename (output_name, "tfm");
+
+ /* If we'd overwrite the input, change the name. */
+ if (input_tfm_name != NULL && same_file_p (input_tfm_name, output_tfm_name))
+ {
+ pl_name = make_prefix ("x", pl_name);
+ output_tfm_name = make_prefix ("x", output_tfm_name);
+ }
+
+ /* Let's write the TFM file first, but to a PL file, which is easier. */
+ if (!tfm_open_pl_output_file (pl_output_name))
+ FATAL_PERROR (pl_output_name);
+
+ REPORT1 ("\nWriting PL file `%s':\n", pl_output_name);
+
+ /* Write the global information we just figured out. */
+ tfm_put_global_info (tfm_info);
+
+ /* Only look between `starting_char' and `ending_char', i.e., the
+ user's -range. */
+ for (this_char = starting_char; this_char <= ending_char; this_char++)
+ {
+ if (write_tfm_char (this_char, chars))
+ REPORT2 ("[%d]%c", this_char, ++char_count % 13 == 0 ? '\n' : ' ');
+ }
+
+ if (char_count % 13 != 0)
+ REPORT ("\n");
+
+ tfm_convert_pl (output_tfm_name, verbose);
+ tfm_close_pl_output_file ();
+}
+
+
+/* Return the global TFM information structure: we read from an existing
+ TFM file, if the global `have_tfm' is true, then from the encoding
+ information in the global `encoding_info', then from the symbol
+ table, and finally from the command line (i.e., the global
+ `fontdimens). */
+
+static tfm_global_info_type
+find_tfm_info (char_type *chars[])
+{
+ tfm_global_info_type tfm_info;
+
+ if (have_tfm)
+ {
+ tfm_info = tfm_get_global_info ();
+ TFM_CHECKSUM (tfm_info) = 0; /* Can't use the old checksum. */
+ }
+ else
+ { /* No TFM file to be found, so initialize the structure
+ with the defaults. */
+ tfm_info = tfm_init_global_info ();
+ TFM_DESIGN_SIZE (tfm_info) = get_designsize_in_points ();
+ }
+
+ /* `encoding_info' has been set at this point, one way or another; use
+ whatever codingscheme it says. */
+ TFM_CODING_SCHEME (tfm_info) = ENCODING_SCHEME_NAME (encoding_info);
+
+ /* The `fontsize' fontdimen is typically the same as the designsize.
+ (I can't imagine when it would be anything else, but it seems
+ prudent to let the user-specified values in the symbol table or
+ commandline override this.) */
+ tfm_set_fontsize (&tfm_info);
+
+ /* Use the bitmap height of `xheight_char', if it exists, for the
+ default x-height. If not, guess .5 of the designsize. */
+ TFM_FONTDIMEN (tfm_info, TFM_XHEIGHT_PARAMETER)
+ = chars[xheight_char] != NULL
+ ? PIXELS_TO_POINTS (
+ CHAR_HEIGHT (*CHAR_BITMAP_INFO (*chars[xheight_char])), dpi_real)
+ : .5 * TFM_DESIGN_SIZE (tfm_info);
+
+ /* If any fontdimens were set in the CMI files, use them. */
+ update_tfm_info_from_symtab (&tfm_info);
+
+ /* Finally, update the fontdimens from the command line. */
+ tfm_set_fontdimens (fontdimens, &tfm_info);
+
+ return tfm_info;
+}
+
+
+/* It is not an error for the user to use a fontdimen name for something
+ else, so we do not complain if we cannot resolve such a name. */
+
+static void
+update_tfm_info_from_symtab (tfm_global_info_type *tfm_info)
+{
+ unsigned p;
+
+ for (p = 1; p <= TFM_MAX_FONTDIMENS; p++)
+ {
+ string name = tfm_fontdimen_name (p);
+ symval_type *sv = name ? symtab_lookup (name) : NULL;
+ if (sv != NULL)
+ {
+ if (symval_resolve (sv))
+ tfm_set_fontdimen (tfm_info, p,
+ PIXELS_TO_POINTS (SYMVAL_REAL (*sv), dpi_real));
+ }
+ }
+}
+
+
+/* Return true if we have TFM info for CODE in CHARS. */
+
+static boolean
+have_tfm_char (charcode_type code, char_type *chars[])
+{
+ boolean ok;
+
+ /* If we have no `char_type' for CODE, have to give up. */
+ if (chars[code] == NULL)
+ ok = false;
+
+ /* If we have no TFM info in the `char_type', have to give up. */
+ else if (CHAR_TFM_INFO (*chars[code]) == NULL)
+ ok = false;
+
+/* xx what about _EXISTS? */
+
+ else
+ ok = true;
+
+ return ok;
+}
+
+
+/* Write the single character CODE from CHARS to the TFM file (assume
+ the latter is open), if we have all the information. Return true if
+ we wrote it, else false. */
+
+static boolean
+write_tfm_char (charcode_type code, char_type *chars[])
+{
+ boolean ok;
+
+ if (have_tfm_char (code, chars))
+ {
+ tfm_char_type c = *CHAR_TFM_INFO (*chars[code]);
+
+ /* The remaining thing to check is that the kerns and ligatures
+ refer only to (other) characters which will be output. */
+ finalize_kern_list (&c, chars);
+ finalize_lig_list (&c, chars);
+
+ /* Write the character. */
+ tfm_put_char (c);
+
+ ok = true;
+ }
+ else
+ ok = false;
+
+ return ok;
+}
+
+
+/* Look through the kern list in C for kerns which refer to characters
+ in CHARS we won't be outputting. Remove such. */
+
+static void
+finalize_kern_list (tfm_char_type *c, char_type *chars[])
+{
+ unsigned e;
+ list_type good_list = list_init ();
+
+ for (e = 0; e < LIST_SIZE (TFM_KERN (*c)); e++)
+ {
+ tfm_kern_type *k = LIST_ELT (TFM_KERN (*c), e);
+
+ if (have_tfm_char (k->character, chars))
+ {
+ tfm_kern_type *new_kern = LIST_TAPPEND (&good_list, tfm_kern_type);
+ *new_kern = *k;
+ }
+ }
+
+ /* Throw away the old list. */
+ list_free (&TFM_KERN (*c));
+
+ /* Insert the good list. */
+ TFM_KERN (*c) = good_list;
+}
+
+
+/* Routine for ligatures analogous to `finalize_kern_list'. */
+
+static void
+finalize_lig_list (tfm_char_type *c, char_type *chars[])
+{
+ unsigned e;
+ list_type good_list = list_init ();
+
+ for (e = 0; e < LIST_SIZE (TFM_LIGATURE (*c)); e++)
+ {
+ tfm_ligature_type *lig = LIST_ELT (TFM_LIGATURE (*c), e);
+
+ if (have_tfm_char (lig->character, chars)
+ && have_tfm_char (lig->ligature, chars))
+ {
+ tfm_ligature_type *new_lig
+ = LIST_TAPPEND (&good_list, tfm_ligature_type);
+ *new_lig = *lig;
+ }
+ }
+
+ /* Throw away the old list. */
+ list_free (&TFM_LIGATURE (*c));
+
+ /* Insert the good list. */
+ TFM_LIGATURE (*c) = good_list;
+}
+
+/* Write a GF file using BITMAP_FONT and CHARS. Don't overwrite an
+ existing file named `BITMAP_FONT_FILENAME (FONT)'. */
+
+static void
+write_gf (bitmap_font_type font, char_type *chars[])
+{
+ unsigned this_char;
+ unsigned char_count = 0;
+ /* We depend upon `output_name' being set when we are called. */
+ string gf_output_name = extend_filename (output_name, concat (dpi, "gf"));
+
+ if (same_file_p (BITMAP_FONT_FILENAME (font), gf_output_name))
+ gf_output_name = make_prefix ("x", gf_output_name);
+
+ if (!gf_open_output_file (gf_output_name))
+ FATAL_PERROR (gf_output_name);
+
+ REPORT1 ("\nWriting GF file `%s':\n", gf_output_name);
+
+ /* Write the first part of the file. */
+ gf_put_preamble (concat4 ("charspace output ", now () + 4, " from ",
+ BITMAP_FONT_COMMENT (font)));
+
+ for (this_char = starting_char; this_char <= ending_char; this_char++)
+ {
+ if (chars[this_char] != NULL
+ && CHAR_BITMAP_INFO (*chars[this_char]) != NULL)
+ {
+ gf_put_char (make_gf_char (*CHAR_BITMAP_INFO (*chars[this_char])));
+ REPORT2 ("[%d]%c", this_char, ++char_count % 13 == 0 ? '\n' : ' ');
+ }
+ }
+
+ if (char_count % 13 != 0)
+ REPORT ("\n");
+
+ /* Write the last part of the file. */
+ gf_put_postamble (real_to_fix (get_designsize_in_points ()),
+ dpi_real, dpi_real);
+
+ gf_close_output_file ();
+}
+
+
+/* Turn BITMAP_CHAR (the generic structure) into a `gf_char_type'. We
+ assume there are no real changes to be made in BITMAP_CHAR, i.e.,
+ that we need only copy the relevant fields. */
+
+static gf_char_type
+make_gf_char (char_info_type bitmap_char)
+{
+ gf_char_type gf_char;
+
+ GF_CHARCODE (gf_char) = CHARCODE (bitmap_char);
+ GF_BITMAP (gf_char) = CHAR_BITMAP (bitmap_char);
+ GF_CHAR_BB (gf_char) = CHAR_BB (bitmap_char);
+ GF_H_ESCAPEMENT (gf_char) = CHAR_SET_WIDTH (bitmap_char);
+ GF_TFM_WIDTH (gf_char) = CHAR_TFM_WIDTH (bitmap_char);
+
+ return gf_char;
+}