/* ifi.c: read an IFI file. Copyright (C) 1992, 2011 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 3, 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 "encoding.h" #include "libfile.h" #include "ifi.h" #include "main.h" /* The name of the encoding file specified by the user, and the structure we parse it into. (-encoding) */ string encoding_name = NULL; /* The name of the IFI file. (-ifi-file) */ string ifi_filename = NULL; static void append_image_char (image_char_list_type *l, image_char_type c); static image_char_list_type new_image_char_list (void); /* Read the IFI file `ifi_filename' (or construct the IFI filename from `input_name'), which gives us information about the image we are going to read. See the documentation for full details and examples of IFI files. Here we just sketch the bare bones. Each (non-blank, non-comment) line in this file represents a ``character'' in the image, and has one to five entries, separated by spaces and/or tabs. Comments start with `%' and continue to the end of the line. The first entry represents the character code. See the documentation for the various forms of charcodes. We also allow `.notdef', meaning the ``character'' should not be output in the font. The second entry, if it exists, is an adjustment to the baseline. We move the baseline down for negative numbers, and up for positive ones. Default is zero. The third entry, if it exists, is the number of bounding boxes that comprise this character. If it is negative, the bounding boxes are not consecutive in the image; instead, they alternate with bounding boxes for some other character. The fourth and fifth entries, if they exist, are the left and right side bearings, respectively. */ image_char_list_type read_ifi_file (unsigned *total_count) { string line; int bb_count; encoding_info_type *encoding_info; int n = 0; image_char_list_type image_char_list = new_image_char_list (); if (encoding_name) { encoding_info = XTALLOC1 (encoding_info_type); *encoding_info = read_encoding_file (encoding_name); } else encoding_info = NULL; if (!ifi_filename) ifi_filename = make_suffix (input_name, "ifi"); libfile_start (ifi_filename, "ifi"); *total_count = 0; while ((line = libfile_line ()) != NULL) { image_char_type c; string baseline_adjust_str, bb_count_str, charname; string lsb_str, rsb_str; string save_line = line; /* So we can free it. */ /* The character name. */ charname = strtok (line, " \t"); /* `libfile_line' should never return an empty line. */ assert (charname != NULL); if (STREQ (charname, ".notdef")) IMAGE_CHAR_OMIT (c) = true; else { if (encoding_info) n = encoding_number (*encoding_info, charname); /* Otherwise, start n at 0. */ if (n == -1) { LIBFILE_WARN2 ("Character `%s' undefined in encoding `%s'", charname, ENCODING_SCHEME_NAME (*encoding_info)); IMAGE_CHAR_OMIT (c) = true; } else { IMAGE_CHARCODE (c) = n++; IMAGE_CHARNAME (c) = xstrdup (charname); IMAGE_CHAR_OMIT (c) = false; } } /* The baseline adjustment. */ baseline_adjust_str = strtok (NULL, " \t"); IMAGE_CHAR_BASELINE_ADJUST (c) = baseline_adjust_str == NULL ? 0 : atoi (baseline_adjust_str); /* The bounding box count. */ bb_count_str = strtok (NULL, " \t"); bb_count = bb_count_str == NULL ? 1 : atoi (bb_count_str); if (bb_count < 0) { IMAGE_CHAR_BB_COUNT (c) = -bb_count; IMAGE_CHAR_BB_ALTERNATING (c) = true; } else { IMAGE_CHAR_BB_COUNT (c) = bb_count; IMAGE_CHAR_BB_ALTERNATING (c) = false; } /* The left side bearing. */ lsb_str = strtok (NULL, " \t"); IMAGE_CHAR_LSB (c) = lsb_str == NULL ? 0 : atoi (lsb_str); /* The right side bearing. */ rsb_str = strtok (NULL, " \t"); IMAGE_CHAR_RSB (c) = rsb_str == NULL ? 0 : atoi (rsb_str); *total_count += IMAGE_CHAR_BB_COUNT (c); append_image_char (&image_char_list, c); free (save_line); } libfile_close (); if (encoding_info) free (encoding_info); return image_char_list; } /* Return an initialized, empty list. */ static image_char_list_type new_image_char_list () { image_char_list_type l; IMAGE_CHAR_LIST_LENGTH (l) = 0; IMAGE_CHAR_LIST_DATA (l) = NULL; return l; } /* Append the character C to the list L. */ void append_image_char (image_char_list_type *l, image_char_type c) { IMAGE_CHAR_LIST_LENGTH (*l)++; IMAGE_CHAR_LIST_DATA (*l) = xrealloc (IMAGE_CHAR_LIST_DATA (*l), IMAGE_CHAR_LIST_LENGTH (*l) * sizeof (image_char_type)); IMAGE_CHAR (*l, IMAGE_CHAR_LIST_LENGTH (*l) - 1) = c; } /* Return false if the box BOX_COUNT boxes beyond FIRST_CHAR in LIST is in the middle of a character, true otherwise. To do this, we add up all the box counts for characters starting at FIRST_CHAR, until we see where we land. */ boolean box_at_char_boundary_p (image_char_list_type list, unsigned first_char, unsigned box_count) { unsigned count = 0; while (count < box_count && first_char < IMAGE_CHAR_LIST_LENGTH (list)) { image_char_type c = IMAGE_CHAR (list, first_char); count += IMAGE_CHAR_BB_COUNT (c); first_char++; } return count == box_count; }