summaryrefslogtreecommitdiff
path: root/imageto/ifi.c
blob: 655cad79a58687399b58ac0e266d7a491fae0b06 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
# 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 of the License, 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, see <http://www.gnu.org/licenses/>.
#


#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;
}