summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog592
-rw-r--r--GNUmakefile.in235
-rw-r--r--NEWS66
-rw-r--r--README47
-rw-r--r--charspace/ChangeLog406
-rw-r--r--charspace/GNUmakefile30
-rw-r--r--charspace/M.depend105
-rw-r--r--charspace/README24
-rw-r--r--charspace/char.c382
-rw-r--r--charspace/char.h82
-rw-r--r--charspace/cmi.h18
-rw-r--r--charspace/cmi.y339
-rw-r--r--charspace/input-cmi.c60
-rw-r--r--charspace/input-cmi.h37
-rw-r--r--charspace/kern.c52
-rw-r--r--charspace/kern.h41
-rw-r--r--charspace/main.c330
-rw-r--r--charspace/main.h41
-rw-r--r--charspace/old-output.c357
-rw-r--r--charspace/output.c362
-rw-r--r--charspace/output.h36
-rw-r--r--charspace/realstrval.h46
-rw-r--r--charspace/symtab.c322
-rw-r--r--charspace/symtab.h78
-rw-r--r--charspace/test.cmi11
-rw-r--r--charspace/version.c1
-rw-r--r--configure.in20
-rw-r--r--doc/ChangeLog103
-rw-r--r--doc/Makefile.in99
-rw-r--r--doc/bpltobzr.texi283
-rw-r--r--doc/bugs.texi247
-rw-r--r--doc/bzredit.texi238
-rw-r--r--doc/bzrto.texi1008
-rw-r--r--doc/charspace.texi852
-rw-r--r--doc/enhance.texi360
-rw-r--r--doc/filefmts.texi442
-rw-r--r--doc/fontcvt.texi398
-rw-r--r--doc/fontu.texi395
-rw-r--r--doc/freedom.texi268
-rw-r--r--doc/gsrenderf.texi246
-rw-r--r--doc/imageto.texi518
-rw-r--r--doc/imgrotate.texi145
-rw-r--r--doc/index.texi8
-rw-r--r--doc/install.texi341
-rw-r--r--doc/intro.texi33
-rw-r--r--doc/limn.texi970
-rw-r--r--doc/overview.texi704
-rw-r--r--doc/update.el6
-rw-r--r--doc/xbfe.texi351
-rw-r--r--fontconvert/ChangeLog604
-rw-r--r--fontconvert/GNUmakefile29
-rw-r--r--fontconvert/README18
-rw-r--r--fontconvert/filter.c101
-rw-r--r--fontconvert/filter.h33
-rw-r--r--fontconvert/main.c747
-rw-r--r--fontconvert/main.h34
-rw-r--r--fontconvert/output-epsf.c135
-rw-r--r--fontconvert/output-epsf.h30
-rw-r--r--fontconvert/output-gf.c86
-rw-r--r--fontconvert/output-gf.h31
-rw-r--r--fontconvert/output-tfm.c279
-rw-r--r--fontconvert/output-tfm.h45
-rw-r--r--fontconvert/random.c171
-rw-r--r--fontconvert/random.h37
-rw-r--r--fontconvert/version.c1
-rw-r--r--gf/ChangeLog308
-rw-r--r--gf/GNUmakefile27
-rw-r--r--gf/README12
-rw-r--r--gf/gf_input.c976
-rw-r--r--gf/gf_opcodes.h58
-rw-r--r--gf/gf_output.c438
-rw-r--r--imageto/ChangeLog1113
-rw-r--r--imageto/GNUmakefile43
-rw-r--r--imageto/README46
-rw-r--r--imageto/bitmap2.c83
-rw-r--r--imageto/bitmap2.h34
-rw-r--r--imageto/extract.c239
-rw-r--r--imageto/extract.h50
-rw-r--r--imageto/ifi.c196
-rw-r--r--imageto/ifi.h91
-rw-r--r--imageto/image-char.c69
-rw-r--r--imageto/image-char.h89
-rw-r--r--imageto/image-header.h35
-rw-r--r--imageto/input-img.c159
-rw-r--r--imageto/input-img.h43
-rw-r--r--imageto/input-pbm.c88
-rw-r--r--imageto/input-pbm.h44
-rw-r--r--imageto/main.c416
-rw-r--r--imageto/main.h42
-rw-r--r--imageto/out-chars.c750
-rw-r--r--imageto/out-chars.h34
-rw-r--r--imageto/out-epsf.c166
-rw-r--r--imageto/out-epsf.h28
-rw-r--r--imageto/out-strips.c94
-rw-r--r--imageto/out-strips.h27
-rw-r--r--imageto/strips.tex85
-rw-r--r--imageto/version.c1
-rw-r--r--lib/ChangeLog1414
-rw-r--r--lib/GNUmakefile38
-rw-r--r--lib/README73
-rw-r--r--lib/atou.obin0 -> 4976 bytes
-rw-r--r--lib/basename.obin0 -> 4956 bytes
-rw-r--r--lib/bb-list.c76
-rw-r--r--lib/bb-outline.c114
-rw-r--r--lib/bitmap.c258
-rw-r--r--lib/bounding-box.c78
-rw-r--r--lib/charcode.c85
-rw-r--r--lib/charspec.c63
-rw-r--r--lib/cmdline.c63
-rw-r--r--lib/concat.c41
-rw-r--r--lib/concat3.c40
-rw-r--r--lib/concat4.c43
-rw-r--r--lib/concat5.c45
-rw-r--r--lib/dlsym.c28
-rw-r--r--lib/edge.c265
-rw-r--r--lib/encoding.c191
-rw-r--r--lib/file-input.c158
-rw-r--r--lib/file-output.c73
-rw-r--r--lib/filename.c99
-rw-r--r--lib/fix-num.c43
-rw-r--r--lib/float-ok.c60
-rw-r--r--lib/fmod.c145
-rw-r--r--lib/font.c466
-rw-r--r--lib/fontmap.c210
-rw-r--r--lib/gmalloc.c1172
-rw-r--r--lib/hexify.c46
-rw-r--r--lib/identity.c38
-rw-r--r--lib/integer-ok.c44
-rw-r--r--lib/libfile.c130
-rw-r--r--lib/line.c63
-rw-r--r--lib/list.c64
-rw-r--r--lib/logreport.c36
-rw-r--r--lib/make-prefix.c41
-rw-r--r--lib/math.c173
-rw-r--r--lib/now.c38
-rw-r--r--lib/numtoa.c50
-rw-r--r--lib/pathsrch.c509
-rw-r--r--lib/rand.c70
-rw-r--r--lib/report.c27
-rw-r--r--lib/safe-free.c37
-rw-r--r--lib/scaled-num.c75
-rw-r--r--lib/spline.c216
-rw-r--r--lib/statistics.c79
-rw-r--r--lib/str-lcase.c49
-rw-r--r--lib/str-to-bit.c111
-rw-r--r--lib/strstr.obin0 -> 5172 bytes
-rw-r--r--lib/substring.c50
-rw-r--r--lib/varstring.c97
-rw-r--r--lib/vector.c272
-rw-r--r--lib/xchdir.c29
-rw-r--r--lib/xfseek.obin0 -> 3592 bytes
-rw-r--r--lib/xftell.obin0 -> 3648 bytes
-rw-r--r--lib/xgetcwd.c104
-rw-r--r--lib/xmessage.c101
-rw-r--r--lib/xopendir.c47
-rw-r--r--lib/xrename.c44
-rw-r--r--lib/xstrdup.c29
-rw-r--r--pbm/ChangeLog41
-rw-r--r--pbm/GNUmakefile27
-rw-r--r--pbm/README2
-rw-r--r--pbm/libpbm.h18
-rw-r--r--pbm/libpbm1.c449
-rw-r--r--pbm/libpbm2.c134
-rw-r--r--pbm/libpbm4.c80
-rwxr-xr-xpbm/pbmasciibin0 -> 72252 bytes
-rw-r--r--pbm/pbmascii.c37
-rw-r--r--pk/ChangeLog138
-rw-r--r--pk/GNUmakefile26
-rw-r--r--pk/README13
-rw-r--r--pk/pk_input.c729
-rw-r--r--pk/pk_opcodes.h41
-rw-r--r--tfm/ChangeLog371
-rw-r--r--tfm/GNUmakefile27
-rw-r--r--tfm/README17
-rw-r--r--tfm/fontdimen.c183
-rw-r--r--tfm/tfm_char.c56
-rw-r--r--tfm/tfm_fontdim.c194
-rw-r--r--tfm/tfm_header.c92
-rw-r--r--tfm/tfm_input.c506
-rw-r--r--tfm/tfm_kern.c75
-rw-r--r--tfm/tfm_ligature.c48
-rw-r--r--tfm/tfm_output.c371
182 files changed, 32085 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..d8bf3cd
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,592 @@
+Fri May 13 15:18:27 1994 Karl Berry (karl@cs.umb.edu)
+
+ * configure.in: Include kpathsea/common.ac.
+
+Sat Jul 31 11:38:21 1993 Karl Berry (karl@cs.umb.edu)
+
+ * configure.in: Remove AC_PREFIX.
+
+Wed Jun 2 08:09:17 1993 Karl Berry (karl@cs.umb.edu)
+
+ * configure.in: Call AC_PROG_CPP explicitly. Don't bother with
+ AC_GCC_TRADITIONAL.
+
+Sat May 22 11:22:57 1993 Karl Berry (karl@cs.umb.edu)
+
+ * GNUmakefile.in (dist): Run gzip -9.
+
+Thu May 20 16:59:38 1993 Karl Berry (karl@cs.umb.edu)
+
+ * GNUmakefile.in (default_tfm_path): Put . first.
+
+Tue May 18 14:02:05 1993 Karl Berry (karl@cs.umb.edu)
+
+ * Makefile.in (install-*): mkdirchain on install dirs, and put
+ mkdirchain in the dist.
+
+Sun Apr 11 14:59:50 1993 Karl Berry (karl@cs.umb.edu)
+
+ * GNUmakefile.in (dist): Copy info files to the local info directory.
+
+Sat Apr 10 14:58:43 1993 Karl Berry (karl@cs.umb.edu)
+
+ * configure.in: Do AC_XENIR_DIR after AC_DIR_HEADER.
+
+Thu Mar 25 16:01:51 1993 Karl Berry (karl@cs.umb.edu)
+
+ * configure.in (AC_ISC_WLIBS): Remove.
+ * aclocal.m4: New version, see web2c ChangeLog.
+
+Tue Feb 23 16:52:13 1993 Karl Berry (karl@cs.umb.edu)
+
+ * GNUmakefile.in (dist): Copy info files to my local info directory.
+
+Sat Jan 9 15:22:51 1993 Karl Berry (karl@cs.umb.edu)
+
+ * GNUmakefile.in (configure, config.status): cd $(srcdir) first.
+
+Fri Jan 1 13:57:15 1993 Karl Berry (karl@cs.umb.edu)
+
+ * configure.in: Changes for new Autoconf.
+
+Sun Dec 13 16:39:23 1992 Karl Berry (karl@cs.umb.edu)
+
+ * GNUmakefile.in (default_tfm_path): Use $(texdatadir).
+
+Thu Dec 10 10:34:30 1992 Karl Berry (karl@cs.umb.edu)
+
+ * GNUmakefile.in (GNUmakefile): Add $(srcdir) to dependency, and
+ use $(SHELL) instead of sh.
+ (config.status): Use $(SHELL).
+
+Sun Nov 29 17:17:46 1992 Karl Berry (karl@cs.umb.edu)
+
+ * GNUmakefile.in (emacslispdir): Doc fix.
+
+Wed Oct 28 15:09:29 1992 Karl Berry (karl@claude.cs.umb.edu)
+
+ * Version 0.6.
+
+ * GNUmakefile.in (install): Install data files with file as second
+ arg, not directory.
+
+Sun Oct 25 15:29:19 1992 Karl Berry (karl@cs.umb.edu)
+
+ * GNUmakefile.in (realclean): Depend on distclean.
+
+ * GNUmakefile.in (installargs): Passed texinputdir as mfinputdir.
+
+ * GNUmakefile.in (install): Correct to `emacs_datadir' in the mkdir.
+
+Thu Oct 15 08:35:21 1992 Karl Berry (karl@cs.umb.edu)
+
+ * configure: Ran Autoconf 1.2.
+
+Mon Oct 5 10:24:15 1992 Karl Berry (karl@cs.umb.edu)
+
+ * configure.in: Generate doc/Makefile. (arif@stat.fsu.edu)
+
+ * GNUmakefile.in (install): Install common.cmi. (ab@meiko.co.uk)
+
+Sun Oct 4 11:22:45 1992 Karl Berry (karl@cs.umb.edu)
+
+ * GNUmakefile.in (examplefiles): Remove; just make links.
+ (dist): Don't copy them.
+
+Sun Sep 20 12:53:29 1992 Karl Berry (karl@cs.umb.edu)
+
+ * GNUmakefile.in (config.status): use sh to run configure --no-create.
+
+ * GNUmakefile.in (realclean): OK, don't remove configure.
+
+Mon Sep 14 17:50:54 1992 Karl Berry (karl@hayley)
+
+ * GNUmakefile.in (realclean): separate from distclean.
+ (distclean): remove GNUmakefile.
+ (config.status): new target.
+ (GNUmakefile): depend on config.status.
+
+Sat Sep 12 14:53:31 1992 Karl Berry (karl@hayley)
+
+ * GNUmakefile.in (dist): replace remaining occurrences of
+ `fontutils-$(version) with `$(top_distdir)'.
+
+Thu Sep 10 08:57:02 1992 Karl Berry (karl@hayley)
+
+ * GNUmakefile.in (dist): changed where the COPYING* files are kept.
+
+ * GNUmakefile.in (xincludedir, xlibdir): say that these are
+ options, not just directories.
+
+ * GNUmakefile.in (realclean): remove configure.
+
+Tue Sep 8 16:42:04 1992 Karl Berry (karl@hayley)
+
+ * configure.in: test for more Unix variants.
+
+Fri Sep 4 08:39:15 1992 Karl Berry (karl@hayley)
+
+ * GNUmakefile.in (extraclean): new target.
+
+Thu Sep 3 08:54:12 1992 Karl Berry (karl@hayley)
+
+ * Version 0.5.
+
+ * GNUmakefile.in (distargs): pass $(version) down.
+
+Sat Aug 29 16:11:47 1992 Karl Berry (karl@hayley)
+
+ * GNUmakefile.in (tex{data,input}dir): new variables.
+ (installargs): pass texinputdir.
+
+Thu Aug 27 08:56:47 1992 Karl Berry (karl@hayley)
+
+ * configure: regenerated from Autoconf 1.1.
+
+Wed Aug 19 07:55:50 1992 Karl Berry (karl@hayley)
+
+ * GNUmakefile.in (install): do make install in `doc', and install
+ the .enc and encoding.map files from `data'.
+
+Tue Aug 18 15:50:55 1992 Karl Berry (karl@hayley)
+
+ * GNUmakefile.in (completedirs): remove `doc' (yay!).
+
+Sat Aug 15 13:32:38 1992 Karl Berry (karl@hayley)
+
+ * GNUmakefile.in (mfdatadir, mfinputdir): new variables.
+ (installargs): pass mfinputdir.
+
+Mon Aug 3 16:00:58 1992 Karl Berry (karl@hayley)
+
+ * GNUmakefile.in (emacs_datadir, emacslispdir): new variables.
+ (install): mkdir them.
+ (installargs): pass emacslispdir down.
+
+Fri Jul 31 17:02:22 1992 Karl Berry (karl@hayley)
+
+ * GNUmakefile.in (dist): include our aclocal.m4.
+
+ * GNUmakefile.in (LIBS): include $(extralibs) for the user to
+ define.
+
+Wed Jul 22 08:42:46 1992 Karl Berry (karl@hayley)
+
+ * GNUmakefile.in (topfiles): add `NEWS'.
+ * NEWS: new file.
+
+ * configure.in: changes for Autoconf 1.0.
+
+Thu Jul 2 15:26:14 1992 Karl Berry (karl@hayley)
+
+ * GNUmakefile.in (makeargs): pass srcdir and CFLAGS.
+ (CCFLAGS): remove.
+
+ * Run Autoconf 0.119.
+
+Mon Jun 29 08:58:37 1992 Karl Berry (karl@hayley)
+
+ * GNUmakefile.in (paths.h): delete it before creating it.
+ Also, new target `GNUmakefile'.
+ (fu_datadir): new variable for the subdirectory in $(datadir)
+ which we create.
+ (install): mkdir all the directories we install into.
+ (CFLAGS): change to CCFLAGS, so the user can set CFLAGS on the
+ command line.
+
+Sat Jun 27 11:04:17 1992 Karl Berry (karl@hayley)
+
+ * GNUmakefile.in (paths.h): depend on GNUmakefile.in and GNUmakefile.
+
+Sun Jun 21 12:43:32 1992 Karl Berry (karl@hayley)
+
+ * GNUmakefile.in (app_defaults): change default and describe better.
+
+Thu Jun 11 09:07:01 1992 Karl Berry (karl@hayley)
+
+ * GNUmakefile.in (.NOEXPORT): new target, since Autoconf doesn't add
+ it automatically any more.
+
+Sun Jun 7 08:09:17 1992 Karl Berry (karl@hayley)
+
+ * GNUmakefile.in (examplefiles): new variable.
+ (dist): copy $(examplefiles) into doc/example.
+
+Thu Jun 4 08:24:46 1992 Karl Berry (karl@hayley)
+
+ * configure.in (AC_HEADER_FILE): rename to AC_CONFIG_HEADER, for
+ Autoconf 0.115.
+
+Wed Jun 3 08:41:33 1992 Karl Berry (karl@hayley)
+
+ * GNUmakefile.in (dist): add-version in top_distdir.
+
+Fri May 29 08:36:46 1992 Karl Berry (karl@hayley)
+
+ * GNUmakefile.in (completedirs): add `doc' (temporarily).
+
+Thu May 21 15:00:30 1992 Karl Berry (karl@hayley)
+
+ * GNUmakefile.in (programs): `imagetofont' => `imageto'.
+
+Mon May 18 12:01:42 1992 Karl Berry (karl@hayley)
+
+ * configure.in: change top-level Makefile name to `GNUmakefile.in'.
+ * GNUmakefile.in: renamed from Makefile.in.
+
+ * Makefile.in (dist): rewrite to `make dist' in subdirs.
+
+ * Makefile.in (alldirs): move `doc' here.
+ (completedirs): from here.
+
+ * Makefile.in (dist): copy testfont.tex into `data'.
+
+Sat May 16 10:09:34 1992 Karl Berry (karl@hayley)
+
+ * configure.in: PROG_CPP must come before GCC_TRADITIONAL.
+
+Fri May 15 09:05:22 1992 Karl Berry (karl@hayley)
+
+ * configure.in: add AC_GCC_TRADITIONAL and AC_PROG_CPP.
+
+ * configure.in: AC_HEADER_MISSING is now AC_HEADER_CHECK.
+
+ * Makefile.in (exec_prefix): new variable.
+ (bindir): use it.
+
+Thu May 14 06:41:19 1992 Karl Berry (karl@hayley)
+
+ * Makefile.in (app_defaults_dir): -> app-defaults.
+
+Wed May 13 08:55:11 1992 Karl Berry (karl@hayley)
+
+ * Makefile.in (VPATH): change for new Autoconf.
+
+Sat May 9 10:21:08 1992 Karl Berry (karl@hayley)
+
+ * Makefile.in (dist): make dist in doc; copy COPYING*.
+
+Thu May 7 08:10:40 1992 Karl Berry (karl@hayley)
+
+ * Makefile.in (dist): don't link include/*.in, we've already got it.
+
+Mon May 4 14:24:39 1992 Karl Berry (karl@hayley)
+
+ * Makefile.in (gsrenderfont): remove this target.
+ (all): don't depend on it.
+
+Tue Apr 28 10:16:39 1992 Karl Berry (karl@hayley)
+
+ * configure.in: Autoconf's prefix is now AC_, not M_.
+
+Thu Apr 23 07:32:29 1992 Karl Berry (karl@hayley)
+
+ * configure.in: test $GCC instead of grepping for `gcc' in $CC.
+
+ * Makefile.in (dist): distribute include/*.in.
+
+ * Makefile.in (.NOEXPORT): remove this, as configure now puts it
+ in automatically.
+
+Wed Apr 22 12:58:49 1992 Karl Berry (karl@hayley)
+
+ * Makefile.in (prefix): set to /usr/local; configure doesn't do
+ M_SUBST.
+
+ * configure.in: M_MEMORY_H is now M_NEED_MEMORY_H.
+
+Sun Apr 19 10:41:07 1992 Karl Berry (karl@hayley)
+
+ * Makefile.in (distclean): add this as a target.
+
+Sun Apr 12 14:08:35 1992 Karl Berry (karl@hayley)
+
+ * Makefile.in (bzrtospecial): add *.el to the distributed list.
+
+Wed Apr 8 09:31:37 1992 Karl Berry (karl@hayley)
+
+ * Makefile.in (all): depend on gsrenderfont.
+ (gsrenderfont/gsrenderfont): make it by substituting for the lib-path.
+ (gsrenderspecial): dist gsrf.in instead of gsrenderfont.
+ (versionfiles): likewise.
+
+Tue Apr 7 13:58:50 1992 Karl Berry (karl@hayley)
+
+ * Makefile.in (dist): copy the .ad files into the distribution
+ directory, not the working dirs.
+
+Sun Mar 29 08:42:54 1992 Karl Berry (karl at hayley)
+
+ * Makefile.in (programs, libraries, etc.): use $(MAKE), not `make'.
+
+Sat Mar 28 07:44:42 1992 Karl Berry (karl at hayley)
+
+ * Version 0.4.
+
+ * Change copyright years to 1992 only.
+
+Fri Mar 27 19:46:49 1992 Karl Berry (karl at hayley)
+
+ * PROJECTS: move to doc.
+ * Makefile.in (topfiles): remove it.
+
+Thu Mar 26 19:54:28 1992 Karl Berry (karl at claude.cs.umb.edu)
+
+ * Makefile.in (makeargs): pass xlibdir.
+
+ * Makefile.in (installargs): missing quote.
+ (install): do `install' in subdirs.
+
+Thu Mar 26 06:37:55 1992 Karl Berry (karl at hayley)
+
+ * Makefile.in (dist): remove include/paths.h.
+
+Wed Mar 25 07:20:10 1992 Karl Berry (karl at hayley)
+
+ * Makefile.in (topfiles): remove PROBLEMS, add COPYING.LIB.
+
+Tue Mar 10 10:48:19 1992 Karl Berry (karl at hayley)
+
+ * Makefile.in (programs): replace xbce and xlse with xbfe.
+ (dist): similarly.
+
+Sun Mar 8 12:48:52 1992 Karl Berry (karl at hayley)
+
+ * configure.in: guess the value for `prefix'.
+ * Makefile.in (prefix): define it as a substitution.
+
+ * Makefile.in (mostlyclean): new target.
+ (distclean): remove.
+ (clean): remove the config files here, not at realclean.
+
+Sat Mar 7 13:34:55 1992 Karl Berry (karl at fosse)
+
+ * Makefile.in (xincludedir): new variable.
+ (CFLAGS): use it.
+ * configure.in: test for it.
+
+Sat Mar 7 09:59:10 1992 Karl Berry (karl at hayley)
+
+ * configure.in: change config-auto.h to c-auto.h.
+
+ * configure.in: substitute for LDFLAGS.
+
+Thu Mar 5 17:31:06 1992 Karl Berry (karl at claude.cs.umb.edu)
+
+ * Makefile.in (makeargs): don't double the $'s.
+
+Thu Mar 5 07:12:13 1992 Karl Berry (karl at hayley)
+
+ * Makefile.in (dist): add version numbers automatically; add in
+ special files in bzrto and gsrenderfont.
+ (bzrtospecial, gsrenderspecial): new variables.
+
+Wed Mar 4 11:24:12 1992 Karl Berry (karl at hayley)
+
+ * gnuw: rename to `widgets'.
+ * Makefile.in (libraries): corresponding.
+
+Sun Mar 1 12:59:09 1992 Karl Berry (karl at hayley)
+
+ * Makefile.in (libraries): add pbm.
+ pbm: new directory.
+
+Tue Feb 25 10:48:47 1992 Karl Berry (karl at hayley)
+
+ * AUTHORS: new file.
+ Makefile.in (topfiles): dist it.
+
+Mon Feb 24 08:36:00 1992 Karl Berry (karl at hayley)
+
+ * configure.in [isc]: include -shlib in LDFLAGS.
+
+Sun Feb 23 09:04:51 1992 Karl Berry (karl at hayley)
+
+ * GNUmakefile (dist): update for various new directories and files.
+
+Tue Feb 11 09:56:23 1992 Karl Berry (karl at hayley)
+
+ * configure.in: test for memcpy et al. only in <memory.h>.
+
+ * configure.in: test for <limits.h> missing.
+
+ * configure.in: test for extra window system libraries.
+ Makefile.in (wlibs): new variables.
+ (makeargs): pass it down to submakes.
+
+ * configure.in: test M_ISC early, before any compiles.
+
+ * Makefile.in (copt): remove it; use CC instead.
+
+Mon Feb 10 09:36:22 1992 Karl Berry (karl at hayley)
+
+ * Makefile.in (copt): new variable.
+
+Sat Feb 8 14:48:28 1992 Karl Berry (karl at hayley)
+
+ * Makefile.in (realclean): remove config.status and Makefile.
+
+Sun Feb 2 13:50:53 1992 Karl Berry (karl at hayley)
+
+ * Makefile.in: rename paths.h-dist to paths.h.in.
+
+Sat Feb 1 14:57:12 1992 Karl Berry (karl at hayley)
+
+ * Makefile.in (default_subdir_path): remove.
+ (default_tfm_path): change to new syntax for subdirs.
+
+Wed Jan 15 13:00:59 1992 Karl Berry (karl at hayley)
+
+ * configure.in: do not test for getwd.
+
+Sun Jan 12 12:13:59 1992 Karl Berry (karl at hayley)
+
+ * Makefile.in (default_lib_path): remove `.', as it is added
+ automatically now.
+
+ * Makefile.in (.NOEXPORT): new target.
+
+Sat Jan 11 09:53:56 1992 Karl Berry (karl at hayley)
+
+ * Makefile.in (CFLAGS): remove -I$(srcdir), and use
+ -I../$(srcdir)/include.
+
+Fri Jan 10 15:36:17 1992 Karl Berry (karl at hayley)
+
+ * Makefile.in (default_tfm_path): set to null.
+
+Wed Jan 8 15:41:13 1992 Karl Berry (karl at hayley)
+
+ * config: we don't need this directory any more.
+ * configure: or this script.
+ * fontutils.in: the input to autoconf, so it can make the
+ configure script.
+
+ * GNUmakefile (programs): remove ospace and gsrenderfont, add
+ charspace.
+
+ * rename `lib' as `data', and `kbase' as `lib'. Merge `getopt'
+ into `lib'.
+ * GNUmakefile (libraries): change to match.
+
+Tue Dec 24 16:41:51 1991 Kathy Hargreaves (kathy at hayley)
+
+ * GNUmakefile (DEFAULT_LIB_PATH): define using $(shell pwd), not
+ the nonexistent $(PWD).
+
+Tue Oct 1 10:07:34 1991 Karl Berry (karl at hayley)
+
+ * all files: change copyright notices to not use dashes.
+
+Tue Jul 30 13:16:38 1991 Karl Berry (karl at ra.cs.umb.edu)
+
+ * Version 0.3.
+
+Fri Jul 26 10:33:26 1991 Karl Berry (karl at hayley)
+
+ * PROJECTS: new file.
+
+ * GNUmakefile (programs): `fit-outlines' is now `limn'; include
+ `gsrenderfont'.
+
+Wed Jul 24 15:17:33 1991 Karl Berry (karl at ra.cs.umb.edu)
+
+ * configure: exit 0 at the end.
+
+Mon Jul 22 06:08:10 1991 Karl Berry (karl at hayley)
+
+ * GNUmakefile (programs): add imagetofont.
+
+Fri Jul 19 08:31:06 1991 Karl Berry (karl at hayley)
+
+ * GNUmakefile: add many variables to be overridden.
+
+ * config: rename to configure.
+ * configfiles: rename to config.
+
+Wed Jun 12 05:42:44 1991 Karl Berry (karl at hayley)
+
+ * GNUmakefile (tags): rename to `TAGS'.
+ (distclean): new target.
+
+Thu Jun 6 07:11:45 1991 Karl Berry (karl at hayley)
+
+ * COPYING: change to version 2 of the GPL.
+
+Sun Mar 24 16:17:03 1991 Karl Berry (karl at hayley)
+
+ * GNUmakefile (dist): new dependencies `depend' and `TAGS'.
+
+Mon Mar 11 08:19:59 1991 Karl Berry (karl at hayley)
+
+ * GNUmakefile (dist): put bzrto/KKBuildChar.PS in the
+ distribution.
+
+Sun Mar 10 16:26:14 1991 Karl Berry (karl at hayley)
+
+ * GNUmakefile (DEFAULT_TFM_PATH): change the default to `.'.
+
+Fri Mar 8 08:42:49 1991 Karl Berry (karl at hayley)
+
+ * GNUmakefile (install): pass bindir as an arg to make.
+
+ * GNUmakefile (dist): make an empty directory `bin'. (from
+ rich@rice.edu)
+
+ * GNUmakefile (include/s.h): run ./config, not config, for the
+ sake of people who might have a system config earlier in their
+ path. (from ian@sq.com)
+
+Thu Mar 7 07:30:59 1991 Karl Berry (karl at hayley)
+
+ * Version 0.2.
+
+Wed Mar 6 10:05:28 1991 Kathy Hargreaves (kathy at hayley)
+
+ * config: use `sunosNNN' instead of `sunNNN'.
+
+Mon Mar 4 15:14:41 1991 Karl Berry (karl at hayley)
+
+ * GNUmakefile (programs): fontconcat is gone.
+
+Fri Mar 1 09:53:28 1991 Karl Berry (karl at hayley)
+
+ * GNUmakefile (completedirs, topfiles): new variables to help in
+ `make dist'.
+
+Mon Feb 25 09:20:37 1991 Karl Berry (karl at hayley)
+
+ * GNUmakefile (programs): include `bzrto'.
+
+ * GNUmakefile (DEFAULT_LIB_PATH): include `pwd`/lib.
+
+Sun Feb 17 09:54:28 1991 Karl Berry (karl at hayley)
+
+ * GNUmakefile (realclean): remove include/{s,paths}.h.
+
+Sat Feb 16 17:21:39 1991 Karl Berry (karl at hayley)
+
+ * GNUmakefile (all): new dependencies, on include/paths.h
+ and include/s.h.
+ * GNUmakefile (include/paths.h): new target.
+
+Sat Nov 17 11:28:25 1990 Karl Berry (karl at hayley)
+
+ * GNUmakefile (programs): add fit-outlines.
+
+Thu Nov 1 08:51:29 1990 Karl Berry (karl at hayley)
+
+ * INSTALL: DEFAULT_TFM_PATH has moved from kbase/filename.c to
+ kbase/font.c.
+
+Wed Oct 24 14:57:57 1990 Karl Berry (karl at aten)
+
+ * Version 0.1.
+
+Sun Oct 21 16:23:20 1990 Karl Berry (karl at hayley)
+
+ * GNUmakefile (libraries): add gnuw.
+
+Sun Sep 30 08:43:44 1990 Karl Berry (karl at hayley)
+
+ * GNUmakefile (programs): add fontconcat.
diff --git a/GNUmakefile.in b/GNUmakefile.in
new file mode 100644
index 0000000..ed51c74
--- /dev/null
+++ b/GNUmakefile.in
@@ -0,0 +1,235 @@
+# Master GNU makefile for font utilities.
+#
+# Copyright (C) 1992, 93, 2004 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.
+
+# Version number of this release.
+version = .6g
+
+# Installation prefixes. Since GNU programs and the TeX system may be
+# installed in different places, we have different prefixes.
+prefix = /usr/local
+exec_prefix = $(prefix)
+texmf_prefix = /usr/local
+
+# Installation directories.
+bindir = $(exec_prefix)/bin
+infodir = $(prefix)/info
+datadir = $(prefix)/lib
+fu_datadir = $(datadir)/fontutil
+emacs_datadir = $(datadir)/emacs
+# Emacs 18 and Emacs 19 both have different directories for this.
+emacslispdir = $(emacs_datadir)/elisp # Where to install .el files.
+
+mfdatadir = $(texmf_prefix)/lib/mf
+mfinputdir = $(mfdatadir)/macros
+texdatadir = $(texmf_prefix)/lib/tex
+texinputdir = $(texdatadir)/macros
+
+# Where the default resource files for X programs get installed. If you
+# don't want to or can't write in the standard app-defaults directory,
+# you can set this to any directory you like as long as you set the
+# XAPPLRESDIR environment variable to the same directory. See the
+# tutorial on resources in the X distribution
+# (.../mit/doc/tutorial/resources.txt) for more information.
+app_defaults = $(prefix)/lib/app-defaults
+
+# Default paths for you to override. You can either change these and
+# run `make', or copy include/paths.h.in to include/paths.h and change
+# them manually. These paths are overridden by various environment
+# variables; see the documentation. The font paths here should probably
+# match TeX's default paths.
+default_lib_path = .:$(shell pwd)/data:$(fu_datadir)
+default_tfm_path = .:$(texdatadir)/fonts//
+default_pk_path = $(default_tfm_path)
+default_gf_path = $(default_tfm_path)
+
+SHELL = /bin/sh
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+# Compiler option for #include <X11/...>, i.e., should start with `-I',
+# or -DX_DISPLAY_MISSING if X is not supported.
+xincludedir = @X_CFLAGS@
+
+# Loader option for -lX..., i.e., should start with `-L'.
+xlibdir = @X_LDFLAGS@
+
+CC = @CC@
+CFLAGS = -g
+
+# Need DEFS to get -DHAVE_CONFIG_H. It's included in CPPFLAGS via
+# data/defs.make.
+DEFS = @DEFS@
+
+LDFLAGS = $(xlibdir) $(CFLAGS) $(XLDFLAGS)
+LIBS = @LIBS@ -lm $(extralibs)
+wlibs = @wlibs@
+
+RANLIB = @RANLIB@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+
+# You shouldn't need to change anything below here.
+
+# If X is not supported, don't try to make the widget library or the
+# bitmap editor.
+#
+ifeq "$(xincludedir)" "-DX_DISPLAY_MISSING"
+widgets =
+xbfe =
+else
+widgets = widgets
+xbfe = xbfe
+endif
+
+libraries = gf lib pbm pk tfm
+programs = charspace fontconvert imageto
+alldirs = $(libraries) $(programs) doc
+
+default: all
+
+.PHONY: all install libraries clean distclean extraclean realclean depend dist
+
+makeargs = $(MFLAGS) \
+ SHELL="$(SHELL)" CC="$(CC)" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" \
+ LIBS="$(LIBS)" RANLIB="$(RANLIB)" srcdir=$(srcdir) \
+ wlibs="$(wlibs)" xlibdir="$(xlibdir)" xincludedir="$(xincludedir)" \
+ widgets="$(widgets)"
+
+all: libraries
+ for dir in $(programs); \
+ do \
+ (cd $${dir}; $(MAKE) $(makeargs) all); \
+ done
+
+libraries: include/paths.h
+ for dir in $(libraries); \
+ do \
+ (cd $${dir}; $(MAKE) $(makeargs)); \
+ done
+
+include/paths.h: include/paths.h.in GNUmakefile GNUmakefile.in
+ rm -f $@
+ echo "/* Generated from paths.h.in (`date`). */" > $@
+ sed -e "s,replace-with-lib-path,$(default_lib_path)," \
+ -e "s,replace-with-tfm-path,$(default_tfm_path)," \
+ -e "s,replace-with-pk-path,$(default_pk_path)," \
+ -e "s,replace-with-gf-path,$(default_gf_path)," \
+ $< >> $@
+
+
+installargs = bindir=$(bindir) \
+ fu_datadir=$(fu_datadir) \
+ emacslispdir=$(emacslispdir) \
+ mfinputdir=$(mfinputdir) \
+ texinputdir=$(texinputdir) \
+ app_defaults=$(app_defaults) \
+ INSTALL="$(INSTALL)" \
+ INSTALL_DATA="$(INSTALL_DATA)" \
+ INSTALL_PROGRAM="$(INSTALL_PROGRAM)"
+
+install:
+ PATH=.:$PATH mkdirchain $(bindir) $(infodir) \
+ $(fu_datadir) $(emacslispdir) $(app_defaults)
+ for dir in $(programs) doc; do \
+ (cd $${dir}; $(MAKE) $(installargs) install); \
+ done
+ cd data; for f in *.enc *.map common.cmi; do \
+ $(INSTALL_DATA) $$f $(fu_datadir); done
+
+
+configure: configure.in
+ cd $(srcdir); autoconf
+
+config.status: configure
+ cd $(srcdir); $(SHELL) configure --no-create
+
+GNUmakefile: $(srcdir)/GNUmakefile.in config.status
+ $(SHELL) config.status
+
+include/c-auto.h.in: configure.in ../kpathsea/common.ac
+ autoheader
+
+# Prevent GNU make 3 from overflowing arg limit on system V.
+.NOEXPORT:
+
+# Files in the top level directory to be distributed.
+topfiles = AUTHORS ChangeLog NEWS README configure *.in
+
+# Directories whose complete contents (almost) are to be distributed.
+completedirs = bin data include
+
+# Files which have version number or date templates.
+versionfiles = gsrenderfont/gsrf.in */version.c
+
+top_distdir = fontutils-$(version)
+
+distargs = top_distdir=$(top_distdir) app_defaults=$(app_defaults) \
+ version=$(version) srcdir=$(srcdir)
+
+dist:: # TAGS # depend
+ rm -rf $(top_distdir)
+ -mkdir $(top_distdir)
+# Set up the top-level files.
+ ln $(topfiles) $(top_distdir)
+ cp -p $(HOME)/gnu/gnuorg/COPYING* $(top_distdir)
+ cp -p $(gnu)/lib/aclocal.m4 $(top_distdir)
+# Set up the directories whose complete contents get distributed.
+ cd $(top_distdir); for dir in $(completedirs); do \
+ (mkdir $$dir; ln ../$$dir/* $$dir); done
+ cp -p $(HOME)/bin/mkdirchain $(top_distdir)/bin
+ cp -p $(plain)/testfont.tex $(top_distdir)/data
+ cp -p $(ktex)/macros/printeps.tex $(top_distdir)/data
+ rm -f $(top_distdir)/include/c-auto.h $(top_distdir)/include/paths.h
+# Set up the other subdirectories.
+ for dir in $(alldirs); do \
+ (cd $$dir; $(MAKE) $(distargs) dir=$$dir dist) done
+# Add version numbers. Have to do this after creating the
+# $(versionfiles), naturally.
+ cd $(top_distdir); add-version $(version) $(versionfiles)
+ GZIP=-9 tar czf $(top_distdir). $(top_distdir)
+# Put the new info files in the local directory.
+ cp -pf $(top_distdir)/doc/fontu.info* $(info)
+ rm -rf $(top_distdir)
+
+TAGS:
+ for dir in $(programs); \
+ do \
+ (cd $${dir}; $(MAKE) $@); \
+ done
+
+depend: include/paths.h
+ for dir in $(alldirs); \
+ do \
+ (cd $${dir}; $(MAKE) $@); \
+ done
+
+mostlyclean clean distclean extraclean realclean::
+ for dir in $(alldirs); \
+ do \
+ (cd $${dir}; $(MAKE) $@); \
+ done
+
+distclean::
+ rm -f include/c-auto.h include/paths.h config.status GNUmakefile
+
+realclean:: distclean
+
+extraclean:: distclean
+ rm -f *~ *\#*
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..a62147d
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,66 @@
+This file records user-visible changes.
+
+Version 0.7
+
+* If the X window system is lacking, as much of the distribution as
+ possible is compiled anyway.
+* Imageto looks for TFM widths in an existing TFM file before resorting
+ to the pixel widths.
+
+Version 0.6 (28 October 1992)
+
+* Imageto changes:
+ - Automatically removes all pieces of adjacent characters; the
+ `-clean-threshold' kludge is gone.
+ - `-info-filename' option renamed to `-ifi-filename'.
+ - Writes a complete GF font if the image file is incomplete.
+ - No longer crashes on a filename lacking an extension.
+
+* BZRto changes:
+ - No longer requires TFM files as input along with the BZR files.
+ - Doesn't guess that the CCC file is the same as the BZR file.
+ - Ligature/kern Metafont output doesn't crash on missing characters.
+ - Metafont output does better at not overflowing MF's memory.
+
+* GSrenderfont changes:
+ - Handles invisible characters, such as spaces.
+ - Reads Type 3 PostScript fonts, as well as Type 1.
+ - No longer requires an output encoding; default is same as input.
+ - Reads fonts that aren't known to Ghostscript by default.
+
+* Other program changes:
+ - Limn doesn't try to log uninitialized floating-point numbers.
+ - All the programs handle fontnames containing `.' better.
+ - Verbose output usually goes to standard output, instead of standard error.
+ - Minor installation and configuration fixes.
+
+* Documentation changes:
+ - The chapter on bug reporting has some further explanation of the
+ purpose of what we ask for, and clarifications. Please read before
+ submitting bug reports.
+ - The chapter on Imageto has been substantially rewritten. I hope the
+ difficulties people encountered using that program because of
+ deficiencies in the manual will be cleared up now.
+
+Version 0.5 (3 September 1992)
+
+* Manual written!
+
+* New program `BPLtoBZR' and new Emacs Lisp BZR editing mode bzredit.el.
+
+* BZRto provides for character construction (of, e.g., pre-accented
+ files) via CCC files.
+ Can also merge fonts, scaling them all to the same size.
+
+* Charspace reads CMI files instead of SBI files; pretty much the same
+ idea, but many changes to the syntax, etc.
+
+* Fontconvert can put a space character in its output.
+ Can do some things via character names, instead of only character codes.
+
+* Imageto uses character names instead of codes, and
+ can write EPS files.
+
+Version 0.4 (28 Mar 1992)
+
+First public release.
diff --git a/README b/README
new file mode 100644
index 0000000..77210ad
--- /dev/null
+++ b/README
@@ -0,0 +1,47 @@
+--
+ fontutils needs a maintainer, see project at
+ http://savannah.gnu.org and/or email karl@gnu.org.
+
+ The web page at http://www.gnu.org/software/fontutils/ describes
+ what's still potentially useful and what isn't from the last release.
+
+ Everything here is out of date.
+--
+
+This directory contains the GNU font utilities. See `GNUmakefile.in'
+for the version number. See `NEWS' for changes by release.
+
+See the Texinfo manual in doc/ for installation and usage information.
+The file INSTALL contains a copy of the installation instructions, as
+plain text.
+
+Send bug reports for the programs or documentation to
+bug-gnu-utils@gnu.org. (See the `Bugs' section of the manual
+for discussion of how to submit an effective bug report.)
+
+Suggestions for improvements (in either the programs or the manual), no
+matter how small, are welcome.
+
+The default installation prefix (we'll call it `$prefix') is the parent
+of the directory that contains the command `gcc'. Installing this
+package will create a number of programs in $prefix/bin, and some files
+in $prefix/lib/fontutil which support the programs. (These directories
+will also be created, if they do not exist.)
+
+The GNU font utilities are free software. See the files COPYING*
+for copying permissions.
+
+We need volunteers to help create fonts for the GNU project. You do not
+need to be an expert type designer to help, but you do need to know
+enough about TeX and/or PostScript to be able to install and test new
+fonts. Example: if you know neither (1) the purpose of TeX utility
+program `gftopk' nor (2) what the PostScript `scalefont' command does,
+you probably need more experience before you can help.
+
+If you can volunteer, the first step is to compile the font utilities.
+After that, contact me (karl@gnu.ai.mit.edu). I will get you a scanned
+type specimen image. The manual explains how to use these utilities to
+turn that into a font you can use in TeX or PostScript.
+
+Karl Berry karl@cs.umb.edu
+Kathryn Hargreaves letters@cs.umb.edu
diff --git a/charspace/ChangeLog b/charspace/ChangeLog
new file mode 100644
index 0000000..d0cd360
--- /dev/null
+++ b/charspace/ChangeLog
@@ -0,0 +1,406 @@
+Thu Nov 23 09:06:06 1995 Kathy Hargreaves <karl@cs.umb.edu>
+
+ * main.c: replaced find_tfm_filename with kpse_find_tfm.
+
+Sat Aug 7 11:53:23 1993 Karl Berry (karl@cs.umb.edu)
+
+ * cmi.y, *.h: c-ctype.h and types.h now in kpathsea.
+
+Fri Dec 11 14:59:42 1992 Karl Berry (karl@cs.umb.edu)
+
+ * symtab.c (symval_as_string): `dtoa' is now `xdtoa'.
+
+ * cmi.y: Change ctype references to use uppercase macros.
+
+Thu Dec 3 15:40:40 1992 Karl Berry (karl@cs.umb.edu)
+
+ * main.c: Don't bother to include getopt.h, cmdline.h already does.
+
+Tue Oct 27 13:01:50 1992 Karl Berry (karl@cs.umb.edu)
+
+ * Version 0.6.
+
+Thu Sep 3 09:29:46 1992 Karl Berry (karl@hayley)
+
+ * Version 0.5.
+
+Sun Aug 23 13:36:19 1992 Karl Berry (karl@hayley)
+
+ * main.c (USAGE): put a newline before GETOPT_USAGE.
+
+Mon Aug 17 08:35:30 1992 Karl Berry (karl@hayley)
+
+ * input-cmi.h: doc fix.
+
+Sun Aug 16 21:38:23 1992 Karl Berry (karl@hayley)
+
+ * cmi.y (NOT_A_TOKEN): parenthesize the definition, for safety.
+
+Sun Jul 19 08:32:13 1992 Karl Berry (karl@hayley)
+
+ * char.c (update_width): char-width now gives the lsb as a
+ percentage, not a hard number.
+ * cmi.y: doc fix.
+
+Tue Jul 14 16:41:54 1992 Karl Berry (karl@hayley)
+
+ * output.c: doc fix.
+
+ * cmi.y (char_width): new rule for the char-width cmd.
+ * realstrval.h (symval_tag_type): new value `symval_char_width'.
+ * char.c (update_via_name): handle this case.
+ (update_width, update_metrics): new routines.
+ (update_sidebearings): call update_metrics.
+
+Tue Jul 7 16:43:08 1992 Karl Berry (karl@hayley)
+
+ * output.c (write_tfm): use same algorithm for TFM output names
+ as fontconvert/output-tfm.c
+
+Sun Jul 5 10:41:10 1992 Karl Berry (karl@hayley)
+
+ * cmi.y (yylex): allow `+' to start a numeric constant.
+
+Fri Jul 3 17:46:36 1992 Karl Berry (karl@hayley)
+
+ * main.c (read_encoding_info): default the encoding scheme, if the
+ user hasn't specified one.
+
+Sun Jun 14 07:19:12 1992 Karl Berry (karl@hayley)
+
+ * output.c (make_gf_char): copied TFM width from `gf_char' instead
+ of `bitmap_char'. Argh.
+
+ * output.c (write_tfm): check chars between `starting_char' and
+ `ending_char', *inclusive*.
+
+ * cmi.y (yylex): `-' can start a numeric constant.
+
+ * char.c (do_char): do the reporting of the charcodes (as we
+ process them) here.
+ * main.c (main): not here.
+ * char.h (do_char): void now, not boolean.
+
+ * symtab.c (symval_as_string): new routine.
+ * symtab.h (symval_as_string): declare it.
+ * char.c (resolve_sidebearing): complain if the sb defn can't be
+ resolved.
+
+ * main.c (main): the symbol table value of `designsize' should be
+ in pixels, not points.
+ * output.c (update_tfm_info_from_symtab, find_tfm_info, write_gf):
+ convert back to points.
+ * char.c (get_designsize_in_points): new routine.
+ (update_sidebearings): convert back here, too.
+ * char.h: declare it.
+
+ * main.c (read_encoding_info): use an existing TFM file as a last
+ resort to guess the codingscheme.
+
+ * output.c (find_tfm_info): guess the x-height; implies passing in
+ `chars' now, sigh.
+ (xheight_char): new global.
+ * output.h (xheight_char): declare it.
+ * main.c (read_command_line): new option `-xheight-char'.
+ (USAGE): document it.
+
+ * symtab.c, output.c, main.c: remove all the logging junk; include
+ report.h instead of logreport.h.
+
+ * output.c (find_tfm_info): call `tfm_set_fontsize'.
+
+ * cmi.y (char): reversed sense of condition for preserving old kerns.
+
+ * main.c (main): set `dpi_real' near the beginning.
+
+Sat Jun 13 09:33:37 1992 Karl Berry (karl@hayley)
+
+ * symtab.c (symtab_char_node): call `init_char' on the new value.
+
+ * cmi.y (yylex): keep track of line numbers.
+ (lineno): new static.
+ (yyerror): print the filename and line number.
+
+ * output.c (update_tfm_info_from_symtab): don't call symtab_lookup
+ with a possibly NULL name.
+
+ * cmi.y (token_number): if have a normal identifier, save its
+ name in yylval.
+
+ * input-cmi.c (read_cmi_file): call `libfile_start'.
+
+ * all files: misc. changes for compilation.
+
+ * symtab.c (symtab_lookup, symtab_lookup_real): finally get around
+ to defining these.
+
+ * char.c: update for new list fn names.
+
+ * output.c: complete rewrite.
+
+Fri Jun 12 11:06:05 1992 Karl Berry (karl@hayley)
+
+ * char.c (do_char): move here.
+ * main.c: from here.
+ * char.h: declare it.
+
+Thu Jun 11 11:06:47 1992 Karl Berry (karl@hayley)
+
+ * char.h (char_type): new field `tfm_info'.
+ (CHAR_TFM_INFO): new macro to access it.
+
+Wed Jun 10 08:27:07 1992 Karl Berry (karl@hayley)
+
+ * input-cmi.[ch]: new files extracted from main.c.
+ * GNUmakefile (c_and_h): add `input-cmi'.
+ * cmi.y: include input-cmi.h.
+
+Tue Jun 9 10:25:30 1992 Karl Berry (karl@hayley)
+
+ * main.c (do_char): complete rewrite for new data structures.
+ * symtab.c (symtab_resolve, resolve_string): new routines to chase
+ names and do multiplications after the CMI stuff has all been read.
+
+ * realstrval.h: new file to declare the common parts to the char
+ and symval structures.
+
+ * GNUmakefile (c_and_h): add `kern'.
+ * kern.[ch]: new files.
+ * symtab.c: call `char_set_kern'.
+
+Mon Jun 8 09:09:46 1992 Karl Berry (karl@hayley)
+
+ * cmi.c: rewrite as a Bison grammar, cmi.y.
+ * GNUmakefile (y): define to be `cmi'.
+ (c_and_h): remove `cmi'.
+ * main.c (read_cmi_file): move here, and call yyparse.
+ (main): define `designsize' in the symbol table.
+
+Sun Jun 7 19:35:15 1992 Karl Berry (karl@hayley)
+
+ * GNUmakefile (c_and_h): delete `perctab'.
+ * perctab.[ch]: don't need these anymore.
+ * symtab.[ch]: generalize to include the percentages.
+
+ * main.c (read_command_line): not a fatal error if -encoding was
+ not specified.
+
+ * sbi.[ch]: change to cmi.[ch].
+ * main.c: change `sbi' to `cmi' throughout.
+ * GNUmakefile (c_and_h): likewise.
+
+Fri Jun 5 09:19:16 1992 Karl Berry (karl@hayley)
+
+ * main.c (main): `return 0' instead of `exit (0)'. (From Paul Eggert)
+
+Wed Jun 3 06:19:18 1992 Karl Berry (karl@hayley)
+
+ * output.c (output_font): throw away the checksum from an existing
+ TFM.
+
+ * output.c (write_files): report the output filenames.
+
+ * symtab.c (new_symbol): call xstrdup on the key.
+ * perctab.c (new_perc_def): likewise.
+
+ * sbi.c: report each line we parse.
+
+Tue Jun 2 12:04:29 1992 Karl Berry (karl@hayley)
+
+ * char.h (alloc_char): declare this.
+ * char.c (alloc_char): new function.
+
+ * sbi.c: rewrite to make each cmd a separate function.
+
+Mon Jun 1 08:54:43 1992 Karl Berry (karl@hayley)
+
+ * sbi.h, main.h, sbi.c (give_warnings): rename to `warn_p'.
+
+ * main.c (do_char): keep a local var instead of doing a bunch of
+ returns.
+
+ * char.c (get_kern{_character,}_element: take an unsigned for
+ `index', instead of an int.
+ * char.h: change decls.
+
+ * char.c (init_char): return a new character, instead of changing
+ an allocated one.
+ * char.h (init_char): change decl correspondingly.
+ * main.c (main): do not initialize the array at the beginning;
+ make it a static array of pointers instead.
+ * {sbi,output}.h: change decl of `chars'.
+ * output.c (find_widths, output_font): same.
+ * sbi.c (read_sbi_file): same.
+
+ * main.c (read_sbi_file_list): use * instead of indexing to go
+ through the sbi file list.
+
+ * main.c (main): open the log file in current directory.
+
+ * sbi.c (WORD_MAX): remove, as it's unused.
+
+ * main.h: remove unneeded externs.
+
+ * main.h (DEBUG*): remove these macros.
+ * main.c (debug) [DEBUG]: remove.
+ * {perctab,sbi,symtab}.c: change DEBUG calls to LOG.
+
+ * main.c (alphabet_sbi_name): remove, since there's no need for
+ an option anyway. Is there?
+
+ * main.c (encoding_name): make static.
+
+ * sbi.c (input_name): remove this global, as it's no longer used.
+ * sbi.h: remove decl.
+ * main.c (main): do not set it.
+
+ * main.c ({start,end}ing_char): declare as `charcode_type', not `int'.
+
+Sat May 30 15:31:50 1992 Karl Berry (karl@hayley)
+
+ * main.c (main): change call to `tfm_convert_pl'.
+
+Fri May 29 11:44:57 1992 Karl Berry (karl@hayley)
+
+ * main.c (main): change return type to `int'.
+
+Wed May 6 09:19:20 1992 Karl Berry (karl@hayley)
+
+ * main.c (read_sbi_file_list): don't loop through a null list.
+
+ * main.c: doc fix.
+
+Thu Apr 30 09:29:34 1992 Karl Berry (karl@hayley)
+
+ * char.c (init_char): initialize the lig/kern lists.
+
+ * char.h: doc fixes.
+
+ * main.c (unparsed_range): remove.
+
+Wed Apr 15 15:25:55 1992 Karl Berry (karl@hayley)
+
+ * output.c: `make_output_filename' is now `extend_filename'.
+
+Sun Mar 29 19:10:12 1992 Karl Berry (karl at hayley)
+
+ * main.c (read_command_line): remove empty else.
+
+Sat Mar 28 07:46:29 1992 Karl Berry (karl at hayley)
+
+ * Version 0.4.
+
+ * Change copyright years to 1992 only.
+
+Fri Mar 27 14:57:14 1992 Karl Berry (karl at hayley)
+
+ * symbol_table.?: rename to symtab.?.
+ * perc_table.?: to perctab.?.
+ * GNUmakefile (c_and_h): as above.
+
+Wed Mar 25 08:31:49 1992 Karl Berry (karl at hayley)
+
+ * perc_table.c (add_to_perc_def_table): use xstrdup, not strdup.
+
+Wed Mar 11 14:03:53 1992 Kathy Hargreaves (kathy at hayley)
+
+ * char.c (get_char_info): make CODE charcode_type.
+
+ * main.c (main): make `charcode' type `charcode_type'.
+ (do_char): ditto for CODE.
+
+ * sbi.c (read_sbi_file): added `encoding_name' and `displacement'.
+
+ * main.c [USAGE]: corrected -sbi-files option comment.
+
+Mon Mar 9 12:26:26 1992 Kathy Hargreaves (kathy at hayley)
+
+ * sbi.h: changed comment.
+
+Sat Mar 7 13:06:11 1992 Kathy Hargreaves (kathy at hayley)
+
+ * main.c (main): fatal if the output filename has a suffix.
+
+Sat Mar 7 09:32:20 1992 Karl Berry (karl at hayley)
+
+ * GNUmakefile (files): replace with `c_and_h', etc.
+
+ * GNUmakefile (libraries): define correctly.
+
+Wed Mar 4 14:46:33 1992 Kathy Hargreaves (kathy at hayley)
+
+ * output.c (write_files): construct output filenames using
+ make_output_filename.
+
+Wed Mar 4 11:54:05 1992 Karl Berry (karl at hayley)
+
+ * input.c: rename to sbi.c.
+ * GNUmakefile (files): corresponding.
+
+Sun Feb 16 12:24:16 1992 Kathy Hargreaves (kathy at hayley)
+
+ * output.c (find_widths): set freed tfm char kern list to NULL.
+
+Sat Feb 1 15:04:16 1992 Karl Berry (karl at hayley)
+
+ * main.c (read_sbi_file_list): use basename, not depath.
+
+Fri Jan 31 17:04:20 1992 Karl Berry (karl at hayley)
+
+ * main.c (read_command_line): declare `option_index' (for new
+ getopt).
+
+Wed Jan 22 13:12:21 1992 Kathy Hargreaves (kathy at hayley)
+
+ * input.c (read_sbi_file): copy the string before doing the below.
+
+ * input.c (read_sbi_file): in case char-percent, assign a string
+ to the displacement field of the character.
+
+ * char.h (displacement_type): made the displacement field a string.
+
+ * char.c (sym_string_to_value): changed sb_string_to_value to this
+ name.
+ (do_displacement): call sym_string_to_value on the character's
+ displacement.
+
+ * input.c (read_sbi_file): added `char-percent' command.
+
+ * char.h [CHAR_UNSET_VALUE]: added definition.
+
+ * char.c (init_char): added routine to initialize the parts of a
+ character needed to calculate sidebearings.
+
+ * main.c (do_char): now call do_displacement if the character's
+ displacement and left sidebearing percentage are set; otherwise
+ call do_sidebearings.
+
+ * char.c (do_displacement): added routine to calculate
+ sidebearings using a displacement and a left sidebearing
+ percentage.
+
+ * output.c (write_files): now give a warning and prepend an `x'
+ instead of an `o' to the filename if the output file is the same
+ one as the input file.
+
+Mon Jan 20 13:51:42 1992 Kathy Hargreaves (kathy at hayley)
+
+ * main.c (read_sbi_file_list): call `depath' on the current sbi name in
+ the list and on `font_name' when comparing them.
+
+Wed Jan 15 12:25:26 1992 Kathy Hargreaves (kathy at hayley)
+
+ * main.c (scan_string_list, read_sbi_files): added these so could
+ read a list of SBI files.
+
+ * main.c: call add_perc_defs_to_symbol_table instead of
+ calculating percentages ``by hand.''
+
+ * input.c (read_sbi_file): added `define_perc' case.
+
+ * perc_def_table.[ch]: added for percentage definitions.
+
+ * input.c (read_sbi_file): don't fatal, only give warnings about
+ characters in SBI files which aren't in the encoding if a
+ boolean is sent in. (This gets around getting warnings for the
+ default alphabet SBI file.)
diff --git a/charspace/GNUmakefile b/charspace/GNUmakefile
new file mode 100644
index 0000000..1fbff67
--- /dev/null
+++ b/charspace/GNUmakefile
@@ -0,0 +1,30 @@
+# Makefile for character spacing program.
+#
+# 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.
+
+program = charspace
+
+c_and_h = char input-cmi kern main output symtab
+c_only = version
+y = cmi
+
+libraries = $(bitmap_libs) tfm
+
+include ../data/defs.make
+include ../data/defsprog.make
+
+include M.depend
diff --git a/charspace/M.depend b/charspace/M.depend
new file mode 100644
index 0000000..59bbc57
--- /dev/null
+++ b/charspace/M.depend
@@ -0,0 +1,105 @@
+cmi.o: .././include/config.h .././include/c-std.h \
+ .././include/c-unistd.h .././include/c-memstr.h \
+ .././include/c-errno.h .././include/c-minmax.h \
+ .././include/c-limits.h .././include/c-proto.h .././include/global.h \
+ .././include/moretypes.h .././include/libfile.h \
+ .././include/varstring.h input-cmi.h main.h .././include/encoding.h \
+ .././include/font.h .././include/bitmap.h .././include/bounding-box.h \
+ .././include/tfm.h .././include/fix-num.h .././include/list.h \
+ symtab.h char.h realstrval.h
+char.o: char.c .././include/config.h $(kpathsea_srcdir)/config.h \
+ .././include/c-auto.h $(kpathsea_srcdir)/c-std.h \
+ $(kpathsea_srcdir)/c-unistd.h $(kpathsea_srcdir)/systypes.h \
+ $(kpathsea_srcdir)/c-memstr.h \
+ $(kpathsea_srcdir)/c-errno.h \
+ $(kpathsea_srcdir)/c-minmax.h \
+ $(kpathsea_srcdir)/c-limits.h \
+ $(kpathsea_srcdir)/c-proto.h $(kpathsea_srcdir)/debug.h \
+ $(kpathsea_srcdir)/types.h $(kpathsea_srcdir)/lib.h $(kpathsea_srcdir)/progname.h \
+ .././include/c-std.h .././include/c-unistd.h .././include/c-memstr.h \
+ .././include/c-errno.h .././include/c-minmax.h \
+ .././include/c-limits.h .././include/c-proto.h .././include/global.h \
+ .././include/moretypes.h .././include/list.h .././include/report.h \
+ char.h .././include/font.h .././include/bitmap.h \
+ .././include/bounding-box.h .././include/tfm.h .././include/fix-num.h \
+ realstrval.h kern.h symtab.h main.h .././include/encoding.h
+input-cmi.o: input-cmi.c .././include/config.h $(kpathsea_srcdir)/config.h \
+ .././include/c-auto.h $(kpathsea_srcdir)/c-std.h \
+ $(kpathsea_srcdir)/c-unistd.h $(kpathsea_srcdir)/systypes.h \
+ $(kpathsea_srcdir)/c-memstr.h \
+ $(kpathsea_srcdir)/c-errno.h \
+ $(kpathsea_srcdir)/c-minmax.h \
+ $(kpathsea_srcdir)/c-limits.h \
+ $(kpathsea_srcdir)/c-proto.h $(kpathsea_srcdir)/debug.h \
+ $(kpathsea_srcdir)/types.h $(kpathsea_srcdir)/lib.h $(kpathsea_srcdir)/progname.h \
+ .././include/c-std.h .././include/c-unistd.h .././include/c-memstr.h \
+ .././include/c-errno.h .././include/c-minmax.h \
+ .././include/c-limits.h .././include/c-proto.h .././include/global.h \
+ .././include/moretypes.h .././include/libfile.h input-cmi.h
+kern.o: kern.c .././include/config.h $(kpathsea_srcdir)/config.h \
+ .././include/c-auto.h $(kpathsea_srcdir)/c-std.h \
+ $(kpathsea_srcdir)/c-unistd.h $(kpathsea_srcdir)/systypes.h \
+ $(kpathsea_srcdir)/c-memstr.h \
+ $(kpathsea_srcdir)/c-errno.h \
+ $(kpathsea_srcdir)/c-minmax.h \
+ $(kpathsea_srcdir)/c-limits.h \
+ $(kpathsea_srcdir)/c-proto.h $(kpathsea_srcdir)/debug.h \
+ $(kpathsea_srcdir)/types.h $(kpathsea_srcdir)/lib.h $(kpathsea_srcdir)/progname.h \
+ .././include/c-std.h .././include/c-unistd.h .././include/c-memstr.h \
+ .././include/c-errno.h .././include/c-minmax.h \
+ .././include/c-limits.h .././include/c-proto.h .././include/global.h \
+ .././include/moretypes.h kern.h symtab.h char.h .././include/font.h \
+ .././include/bitmap.h .././include/bounding-box.h .././include/tfm.h \
+ .././include/fix-num.h .././include/list.h realstrval.h
+main.o: main.c .././include/config.h $(kpathsea_srcdir)/config.h \
+ .././include/c-auto.h $(kpathsea_srcdir)/c-std.h \
+ $(kpathsea_srcdir)/c-unistd.h $(kpathsea_srcdir)/systypes.h \
+ $(kpathsea_srcdir)/c-memstr.h \
+ $(kpathsea_srcdir)/c-errno.h \
+ $(kpathsea_srcdir)/c-minmax.h \
+ $(kpathsea_srcdir)/c-limits.h \
+ $(kpathsea_srcdir)/c-proto.h $(kpathsea_srcdir)/debug.h \
+ $(kpathsea_srcdir)/types.h $(kpathsea_srcdir)/lib.h $(kpathsea_srcdir)/progname.h \
+ .././include/c-std.h .././include/c-unistd.h .././include/c-memstr.h \
+ .././include/c-errno.h .././include/c-minmax.h \
+ .././include/c-limits.h .././include/c-proto.h .././include/global.h \
+ .././include/moretypes.h .././include/cmdline.h \
+ .././include/filename.h .././include/getopt.h .././include/encoding.h \
+ .././include/font.h .././include/bitmap.h .././include/bounding-box.h \
+ .././include/tfm.h .././include/fix-num.h .././include/list.h \
+ .././include/report.h char.h realstrval.h input-cmi.h main.h output.h \
+ symtab.h cmi.h
+output.o: output.c .././include/config.h $(kpathsea_srcdir)/config.h \
+ .././include/c-auto.h $(kpathsea_srcdir)/c-std.h \
+ $(kpathsea_srcdir)/c-unistd.h $(kpathsea_srcdir)/systypes.h \
+ $(kpathsea_srcdir)/c-memstr.h \
+ $(kpathsea_srcdir)/c-errno.h \
+ $(kpathsea_srcdir)/c-minmax.h \
+ $(kpathsea_srcdir)/c-limits.h \
+ $(kpathsea_srcdir)/c-proto.h $(kpathsea_srcdir)/debug.h \
+ $(kpathsea_srcdir)/types.h $(kpathsea_srcdir)/lib.h $(kpathsea_srcdir)/progname.h \
+ .././include/c-std.h .././include/c-unistd.h .././include/c-memstr.h \
+ .././include/c-errno.h .././include/c-minmax.h \
+ .././include/c-limits.h .././include/c-proto.h .././include/global.h \
+ .././include/moretypes.h .././include/encoding.h .././include/font.h \
+ .././include/bitmap.h .././include/bounding-box.h .././include/tfm.h \
+ .././include/fix-num.h .././include/list.h .././include/filename.h \
+ .././include/gf.h .././include/libfile.h .././include/report.h char.h \
+ realstrval.h main.h output.h symtab.h
+symtab.o: symtab.c .././include/config.h $(kpathsea_srcdir)/config.h \
+ .././include/c-auto.h $(kpathsea_srcdir)/c-std.h \
+ $(kpathsea_srcdir)/c-unistd.h $(kpathsea_srcdir)/systypes.h \
+ $(kpathsea_srcdir)/c-memstr.h \
+ $(kpathsea_srcdir)/c-errno.h \
+ $(kpathsea_srcdir)/c-minmax.h \
+ $(kpathsea_srcdir)/c-limits.h \
+ $(kpathsea_srcdir)/c-proto.h $(kpathsea_srcdir)/debug.h \
+ $(kpathsea_srcdir)/types.h $(kpathsea_srcdir)/lib.h $(kpathsea_srcdir)/progname.h \
+ .././include/c-std.h .././include/c-unistd.h .././include/c-memstr.h \
+ .././include/c-errno.h .././include/c-minmax.h \
+ .././include/c-limits.h .././include/c-proto.h .././include/global.h \
+ .././include/moretypes.h kern.h symtab.h char.h .././include/font.h \
+ .././include/bitmap.h .././include/bounding-box.h .././include/tfm.h \
+ .././include/fix-num.h .././include/list.h realstrval.h main.h \
+ .././include/encoding.h
+version.o: version.c
diff --git a/charspace/README b/charspace/README
new file mode 100644
index 0000000..2b8cac5
--- /dev/null
+++ b/charspace/README
@@ -0,0 +1,24 @@
+This program adds sidebearings to a bitmap font, and outputs a revised
+bitmap font and a TFM file. It reads several auxiliary ``character
+metric information'' (CMI) files to determine the side bearings.
+
+The ideas behind the CMI files are based on Harry Smith's (Linotype)
+principles, as explicated by Walter Tracy in his book `Letters of
+Credit'. (A book we highly recommend for those interested in type.)
+
+@book{Tracy:LC86,
+ author = "Walter Tracy",
+ title = "Letters of Credit",
+ publisher = "David R. Godine",
+ address = "Boston",
+ year = 1986,
+ price = "$27.50",
+ annote = "Two parts: the first
+ on general history and principles of type design, the
+ second a critical discussion of the work of Jan van
+ Krimpen, Frederic Goudy, Rudolf Koch, W.A. Dwiggins,
+ and Stanley Morison. Tracy was head of type design for
+ Linotype in Britain.",
+}
+
+(This BibTeX entry is from the type.bib file on math.utah.edu:pub/tex/bib.)
diff --git a/charspace/char.c b/charspace/char.c
new file mode 100644
index 0000000..695eb40
--- /dev/null
+++ b/charspace/char.c
@@ -0,0 +1,382 @@
+/* char.c: functions to muck with `char_type's.
+
+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 "list.h"
+#include "report.h"
+
+#include "char.h"
+#include "kern.h"
+#include "main.h"
+#include "symtab.h"
+
+
+static boolean resolve_sidebearing (sidebearing_type *);
+static void update_kerns (char_type *, tfm_char_type *);
+static void update_metrics (real, real, char_info_type *, tfm_char_type *);
+static void update_sidebearings (char_type *, char_info_type *,
+ tfm_char_type *);
+static char_type *update_via_name (string, char_info_type *, tfm_char_type *);
+static void update_width (char_type *, char_info_type *, tfm_char_type *);
+
+/* Initialize the parts of the character structure. */
+
+char_type
+init_char ()
+{
+ char_type c;
+
+ CHAR_BITMAP_INFO (c) = NULL;
+ CHAR_TFM_INFO (c) = NULL;
+ CHAR_LSB (c) = NULL;
+ CHAR_RSB (c) = NULL;
+ CHAR_KERNS (c) = list_init ();
+
+ return c;
+}
+
+/* Our goal here is to extract the information about the character CODE
+ from the symbol table, and fill in the information from the bitmap
+ and TFM fonts. We also read ligature information from the encoding
+ vector. C_PTR_ADDR is the address of a pointer to the `char_type' we
+ fill in (or will be).
+
+ Thus far, we have information only in the symbol table, and thus
+ can be retrieved only by character name. But when it comes
+ time to output, we obviously have to do it by number. If we can find
+ `encoding_info's name for CODE in the symbol table, great -- we can
+ make *C_PTR_ADDR point at that character and fill it in. If not,
+ then we allocate some new space -- just because the character wasn't
+ mentioned in the CMI files shouldn't mean it doesn't get output.
+ (Only if we can't find bitmap information for a character do we not
+ output it.)
+
+ We return true if CODE will be output, false if not. */
+
+void
+do_char (charcode_type code, char_type **c_ptr_addr)
+{
+ static unsigned char_count = 0;
+ string char_name;
+ tfm_char_type *tfm_char = NULL;
+
+ /* Check that the character CODE exists in the input font. */
+ char_info_type *bitmap_char = get_char (input_name, code);
+
+ /* If no bitmap information, give up. Everything else we can fake. */
+ if (bitmap_char == NULL)
+ return;
+
+ REPORT1 ("[%d", CHARCODE (*bitmap_char));
+
+ /* Look for existing TFM information. */
+ if (have_tfm)
+ tfm_char = tfm_get_char (code);
+
+ /* If no prior TFM file, or if the character CODE wasn't there,
+ initialize `tfm_char' from the bitmap information. */
+ if (tfm_char == NULL)
+ {
+ tfm_char = XTALLOC1 (tfm_char_type);
+ *tfm_char = tfm_new_char ();
+
+ TFM_CHAR_EXISTS (*tfm_char) = true;
+ TFM_CHARCODE (*tfm_char) = code;
+ TFM_HEIGHT (*tfm_char)
+ = PIXELS_TO_POINTS (CHAR_HEIGHT (*bitmap_char), dpi_real);
+ TFM_DEPTH (*tfm_char)
+ = PIXELS_TO_POINTS (CHAR_DEPTH (*bitmap_char), dpi_real);
+ /* Leave the italic correction at zero, since we don't know how to
+ compute a reasonable value. And don't bother to compute the
+ width, since we do so below. */
+ }
+
+ /* We've initialized the TFM and bitmap information from previously
+ existing files. Next, get the character name from the global
+ `encoding_info', so we can get at info in the symbol table. */
+ char_name = ENCODING_CHAR_NAME (encoding_info, code);
+
+ if (char_name == NULL)
+ WARNING1 ("No character name for character %d", code);
+ else
+ *c_ptr_addr = update_via_name (char_name, bitmap_char, tfm_char);
+
+ /* If we haven't allocated a `char_type' yet, do so. The fields which
+ get used for the CMI stuff -- the side bearings and kern list --
+ don't need to be initialized. */
+ if (*c_ptr_addr == NULL)
+ *c_ptr_addr = XTALLOC1 (char_type);
+
+ /* Set the pointers in *C_PTR_ADDR to the new bitmap and TFM info. */
+ CHAR_BITMAP_INFO (**c_ptr_addr) = bitmap_char;
+ CHAR_TFM_INFO (**c_ptr_addr) = tfm_char;
+
+ REPORT1 ("]%c", ++char_count % 13 == 0 ? '\n' : ' ');
+
+ return;
+}
+
+/* Assume that CHAR_NAME exists in the encoding vector. If looking up
+ CHAR_NAME in the symbol table yields a character, return a pointer to
+ the `char_type' in the symbol table with updated side bearing
+ information. Otherwise we return NULL. In any case, update TFM_CHAR
+ with the ligatures from the global `encoding_info'. */
+
+static char_type *
+update_via_name (string char_name, char_info_type *bitmap_char,
+ tfm_char_type *tfm_char)
+{
+ list_type enc_ligs;
+ unsigned l;
+ char_type *c_ptr = NULL;
+
+ /* We have a character name, so look for side bearing info. */
+ symval_type *sv = symtab_lookup (char_name);
+
+ if (sv == NULL)
+ WARNING1 ("%s: Undefined in CMI files", char_name);
+
+ else if (SYMVAL_TAG (*sv) == symval_char)
+ {
+ /* We'll return `c_ptr', a pointer to the struct in the symbol table. */
+ c_ptr = &SYMVAL_CHAR (*sv);
+
+ update_sidebearings (c_ptr, bitmap_char, tfm_char);
+ update_kerns (c_ptr, tfm_char);
+ }
+
+ else if (SYMVAL_TAG (*sv) == symval_char_width)
+ {
+ /* We'll return `c_ptr', a pointer to the struct in the symbol table. */
+ c_ptr = &SYMVAL_CHAR (*sv);
+
+ update_width (c_ptr, bitmap_char, tfm_char);
+ update_kerns (c_ptr, tfm_char);
+ }
+
+ else
+ WARNING1 ("%s: Not defined as a character", char_name);
+
+ /* Regardless of whether CHAR_NAME was in the symbol table, we can
+ also update the ligature list from `encoding_info'. */
+ enc_ligs = ENCODING_CHAR_LIG (encoding_info, CHARCODE (*bitmap_char));
+ for (l = 0; l < LIST_SIZE (enc_ligs); l++)
+ {
+ tfm_ligature_type *lig = LIST_ELT (enc_ligs, l);
+ tfm_set_ligature (&TFM_LIGATURE (*tfm_char), lig->character,
+ lig->ligature);
+ }
+
+ return c_ptr;
+}
+
+/* Update the set width and sidebearings for a character defined with
+ `char-width'. We take the RSB info in C_PTR to be the desired set
+ width and the LSB to be the percentage of whitespace to make the left
+ side bearing. We update BITMAP_CHAR and TFM_CHAR correspondingly. */
+
+static void
+update_width (char_type *c_ptr, char_info_type *bitmap_char,
+ tfm_char_type *tfm_char)
+{
+ real lsb_percent = 0.0;
+ charcode_type code = CHARCODE (*bitmap_char);
+ /* We might not have info for the character, though, so set up the
+ defaults as the existing metrics. */
+ boolean changed_metrics = false;
+ real lsb = CHAR_MIN_COL (*bitmap_char);
+ real real_width = CHAR_SET_WIDTH (*bitmap_char);
+
+ /* Find the lsb percent. */
+ if (CHAR_LSB (*c_ptr) == NULL)
+ WARNING1 ("char %d: No left side bearing information", code);
+ else if (resolve_sidebearing (CHAR_LSB (*c_ptr)))
+ {
+ lsb_percent = SB_REAL (*CHAR_LSB (*c_ptr));
+ if (lsb_percent <= 0.0)
+ WARNING2 ("char %d: lsb percent (%f) must be nonnegative",
+ code, lsb_percent);
+ }
+
+ if (CHAR_RSB (*c_ptr) == NULL)
+ WARNING1 ("char %d: No set width information", CHARCODE (*bitmap_char));
+ else if (resolve_sidebearing (CHAR_RSB (*c_ptr)))
+ {
+ real_width = SB_REAL (*CHAR_RSB (*c_ptr));
+ changed_metrics = true;
+ }
+
+ /* If we have a positive percent, figure out the new lsb. */
+ if (lsb_percent > 0.0)
+ {
+ real whitespace = real_width - CHAR_BITMAP_WIDTH (*bitmap_char);
+ lsb = whitespace * lsb_percent;
+ changed_metrics = true;
+ }
+
+ /* If necessary, update the widths. */
+ if (changed_metrics)
+ update_metrics (real_width, lsb, bitmap_char, tfm_char);
+}
+
+
+/* Call `resolve_sidebearing' on the sidebearing info in C_PTR. If that
+ succeeds, update the various widths and side bearing info in
+ BITMAP_CHAR and TFM_CHAR. This is called for characters defined with
+ the `char' command. */
+
+static void
+update_sidebearings (char_type *c_ptr, char_info_type *bitmap_char,
+ tfm_char_type *tfm_char)
+{
+ /* We might not have side bearing info for it, so set up the defaults
+ as the existing side bearings. */
+ boolean changed_sb = false;
+ real lsb = CHAR_MIN_COL (*bitmap_char);
+ real rsb = CHAR_SET_WIDTH (*bitmap_char) - CHAR_MAX_COL (*bitmap_char);
+
+ /* Compute the side bearings. */
+ if (CHAR_LSB (*c_ptr) == NULL)
+ WARNING1 ("char %d: No left side bearing information",
+ CHARCODE (*bitmap_char));
+ else if (resolve_sidebearing (CHAR_LSB (*c_ptr)))
+ {
+ lsb = SB_REAL (*CHAR_LSB (*c_ptr));
+ changed_sb = true;
+ }
+
+ if (CHAR_RSB (*c_ptr) == NULL)
+ WARNING1 ("char %d: No right side bearing information",
+ CHARCODE (*bitmap_char));
+ else if (resolve_sidebearing (CHAR_RSB (*c_ptr)))
+ {
+ rsb = SB_REAL (*CHAR_RSB (*c_ptr));
+ changed_sb = true;
+ }
+
+ /* If the side bearings changed, then update the widths. */
+ if (changed_sb)
+ {
+ real real_width = lsb + CHAR_BITMAP_WIDTH (*bitmap_char) + rsb;
+ update_metrics (real_width, lsb, bitmap_char, tfm_char);
+ }
+}
+
+/* Following routines are called by both `update_sidebearings' and
+ `update_width'. */
+
+/* Try to make the definition of SB into a number, by looking up names
+ in the symbol table. */
+
+static boolean
+resolve_sidebearing (sidebearing_type *sb)
+{
+ boolean ok;
+ symval_type sv;
+
+ /* This should have already been checked. */
+ assert (sb != NULL);
+
+ /* Make SB into a symval so we can resolve it. */
+ SYMVAL_TAG (sv) = SB_TAG (*sb);
+ SYMVAL_REAL_STRING (sv) = SB_VALUE (*sb);
+
+ ok = symval_resolve (&sv);
+
+ if (ok)
+ {
+ SB_TAG (*sb) = symval_real;
+ SB_REAL (*sb) = SYMVAL_REAL (sv);
+ }
+ else
+ {
+ string desc = symval_as_string (sv);
+ WARNING1 ("Unresolvable sidebearing definition `%s'", desc);
+ free (desc);
+ }
+
+ return ok;
+}
+
+
+/* Update the widths and side bearings in BITMAP_CHAR and TFM_CHAR
+ according to REAL_WIDTH and LSB. */
+
+static void
+update_metrics (real real_width, real lsb, char_info_type *bitmap_char,
+ tfm_char_type *tfm_char)
+{
+ int pixel_width = ROUND (real_width);
+ real point_width = PIXELS_TO_POINTS (real_width, dpi_real);
+ real ds = get_designsize_in_points ();
+
+ TFM_WIDTH (*tfm_char) = point_width;
+ CHAR_TFM_WIDTH (*bitmap_char) = real_to_fix (point_width / ds);
+ CHAR_SET_WIDTH (*bitmap_char) = pixel_width;
+ CHAR_MIN_COL (*bitmap_char) = lsb;
+ CHAR_MAX_COL (*bitmap_char) = lsb + CHAR_BITMAP_WIDTH (*bitmap_char);
+}
+
+/* Update the kern list in TFM_CHAR from any kerns in *C_PTR. */
+
+static void
+update_kerns (char_type *c_ptr, tfm_char_type *tfm_char)
+{
+ unsigned k;
+ list_type char_kerns = CHAR_KERNS (*c_ptr);
+
+ for (k = 0; k < LIST_SIZE (char_kerns); k++)
+ {
+ char_kern_type *kern_elt = LIST_ELT (char_kerns, k);
+
+ /* If the name of the kern character isn't in the global
+ `encoding_info', skip it. */
+ int code = encoding_number (encoding_info, kern_elt->character);
+
+ if (code != -1)
+ {
+ if (symval_resolve (&kern_elt->kern))
+ {
+ real pixel_kern = SYMVAL_REAL (kern_elt->kern);
+ real points_kern = PIXELS_TO_POINTS (pixel_kern, dpi_real);
+
+ tfm_set_kern (&TFM_KERN (*tfm_char), code, points_kern);
+ }
+ else
+ {
+ string desc = symval_as_string (kern_elt->kern);
+ WARNING2 ("%s: Unresolvable kern value `%s'",
+ kern_elt->character, desc);
+ free (desc);
+ }
+ }
+ }
+}
+
+/* We need to do this several times, so... Have to use the global
+ `dpi-real'. */
+
+real
+get_designsize_in_points ()
+{
+ real ds_pixels = symtab_lookup_real ("designsize");
+ real ds_points = PIXELS_TO_POINTS (ds_pixels, dpi_real);
+
+ return ds_points;
+}
diff --git a/charspace/char.h b/charspace/char.h
new file mode 100644
index 0000000..541ca5f
--- /dev/null
+++ b/charspace/char.h
@@ -0,0 +1,82 @@
+/* char.h: the definition of `char_type'.
+
+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. */
+
+#ifndef CHAR_H
+#define CHAR_H
+
+#include "font.h"
+#include "list.h"
+#include "realstrval.h"
+
+/* We want these to mean the values in our own structure. */
+#undef CHAR_LSB
+#undef CHAR_RSB
+
+
+/* A side bearing can be defined almost like a symbol (no `char_type'). */
+typedef struct
+{
+ symval_tag_type tag;
+ real_string_val_type value;
+} sidebearing_type;
+
+#define SB_TAG(sb) ((sb).tag)
+#define SB_VALUE(sb) ((sb).value)
+#define SB_REAL(sb) ((sb).value.real_val)
+#define SB_STRING(sb) ((sb).value.string_val)
+
+/* The information about each character in which we're interested. */
+typedef struct
+{
+ char_info_type *char_info;
+ tfm_char_type *tfm_info;
+ sidebearing_type *lsb, *rsb;
+ list_type kerns; /* We use `char_kern_type' for the elements. */
+} char_type;
+
+
+/* The information from the bitmap font. */
+#define CHAR_BITMAP_INFO(c) ((c).char_info)
+#define CHAR_CHARCODE(c) CHARCODE (*CHAR_BITMAP_INFO (c))
+
+/* The information from the TFM file. */
+#define CHAR_TFM_INFO(c) ((c).tfm_info)
+
+/* Information we've collected for the sidebearings. */
+#define CHAR_LSB(c) ((c).lsb)
+#define CHAR_LSB_TAG(c) (CHAR_LSB (c)->tag)
+#define CHAR_LSB_VALUE(c) (CHAR_LSB (c)->value)
+
+#define CHAR_RSB(c) ((c).rsb)
+#define CHAR_RSB_TAG(c) (CHAR_RSB (c)->tag)
+#define CHAR_RSB_VALUE(c) (CHAR_RSB (c)->value)
+
+#define CHAR_KERNS(c) ((c).kerns)
+
+/* Initialize the various fields. */
+extern char_type init_char (void);
+
+/* Get the font information for CODE, and update *C_PTR_ADDR from the
+ symbol table and encoding vector. */
+extern void do_char (charcode_type code, char_type **c_ptr_addr);
+
+/* Looks up `designsize' in the symbol table and converts the result
+ back to printer's points. */
+extern real get_designsize_in_points (void);
+
+#endif /* not CHAR_H */
diff --git a/charspace/cmi.h b/charspace/cmi.h
new file mode 100644
index 0000000..c51cad3
--- /dev/null
+++ b/charspace/cmi.h
@@ -0,0 +1,18 @@
+typedef union
+{
+ real realval;
+ symval_type symval;
+ string strval;
+} YYSTYPE;
+#define TR_CHAR 258
+#define TR_CHAR_WIDTH 259
+#define TR_CODINGSCHEME 260
+#define TR_DEFINE 261
+#define TR_FONTDIMEN 262
+#define TR_KERN 263
+#define T_IDENTIFIER 264
+#define T_STRING 265
+#define T_REAL 266
+
+
+extern YYSTYPE yylval;
diff --git a/charspace/cmi.y b/charspace/cmi.y
new file mode 100644
index 0000000..22cbc7a
--- /dev/null
+++ b/charspace/cmi.y
@@ -0,0 +1,339 @@
+%{
+/* cmi.y: parse a character metric information file, entering what we
+ find into the symbol table.
+
+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 <kpathsea/c-ctype.h>
+#include "libfile.h"
+#include "varstring.h"
+
+#include "input-cmi.h"
+#include "main.h"
+#include "symtab.h"
+
+
+static void yyerror (string);
+static int yylex (void);
+%}
+
+%union
+{
+ real realval;
+ symval_type symval;
+ string strval;
+}
+
+%token TR_CHAR TR_CHAR_WIDTH TR_CODINGSCHEME TR_DEFINE TR_FONTDIMEN TR_KERN
+%token <strval> T_IDENTIFIER T_STRING
+%token <realval> T_REAL
+
+/* A <symval> is not a symbol, it's the value of a symbol. */
+%type <symval> expr
+
+%%
+statements:
+ /* empty */
+ | statements statement
+ ;
+
+statement:
+ char
+ | char_width
+ | codingscheme
+ | define
+ | fontdimen
+ | kern
+ ;
+
+/* The two expr's are the left and right side bearings. We have to
+ preserve any existing kerns. */
+char:
+ TR_CHAR T_IDENTIFIER expr ',' expr
+ { symval_type *old_sv = symtab_lookup ($2);
+ symval_type new_sv = symtab_char_node ($3, $5);
+
+ if (old_sv != NULL && SYMVAL_TAG (*old_sv) == symval_char)
+ CHAR_KERNS (SYMVAL_CHAR (new_sv))
+ = CHAR_KERNS (SYMVAL_CHAR (*old_sv));
+
+ symtab_define ($2, new_sv);
+ }
+ ;
+
+/* The two expr's here are the set width and the percentage of
+ (set width - bitmap width) to make the left side bearing. We cheat
+ and use the rsb to store the width expression in the interest of not
+ complicating the `char_type' structure even more. We use the symbol
+ tag to distinguish the different ways of defining characters. */
+char_width:
+ TR_CHAR_WIDTH T_IDENTIFIER expr ',' expr
+ { symval_type *old_sv = symtab_lookup ($2);
+ symval_type new_sv = symtab_char_node ($5, $3);
+ SYMVAL_TAG (new_sv) = symval_char_width;
+
+ if (old_sv != NULL && SYMVAL_TAG (*old_sv) == symval_char)
+ CHAR_KERNS (SYMVAL_CHAR (new_sv))
+ = CHAR_KERNS (SYMVAL_CHAR (*old_sv));
+
+ symtab_define ($2, new_sv);
+ }
+ ;
+
+codingscheme:
+ TR_CODINGSCHEME T_STRING
+ { symtab_define ("codingscheme", symtab_string_node ($2)); }
+ ;
+
+define:
+ TR_DEFINE T_IDENTIFIER expr
+ { symtab_define ($2, $3); }
+ ;
+
+fontdimen:
+ TR_FONTDIMEN T_IDENTIFIER expr
+ { if (tfm_fontdimen_number ($2) == 0)
+ WARNING1 ("%s: Not the name of a fontdimen", $2);
+
+ symtab_define ($2, $3);
+ }
+ ;
+
+kern:
+ TR_KERN T_IDENTIFIER T_IDENTIFIER expr
+ { symtab_define_kern ($2, $3, $4); }
+ ;
+
+expr:
+ T_REAL
+ { $$ = symtab_real_node ($1); }
+ | T_IDENTIFIER
+ { $$ = symtab_string_node ($1); }
+ | T_REAL T_IDENTIFIER
+ { $$ = symtab_real_string_node ($1, $2); }
+ ;
+%%
+
+/* Let's hope Bison will never use this value as a token code. */
+#define NOT_A_TOKEN (-1)
+
+/* Keep track of line numbers for error messages. */
+static unsigned lineno = 1;
+
+static int get_numeric_token (FILE *);
+static int get_word_token (FILE *);
+static int get_string_token (FILE *);
+static int token_number (string);
+
+
+/* Return the next token from `cmi_file'. */
+
+static int
+yylex (void)
+{
+ int t = NOT_A_TOKEN;
+
+ do
+ {
+ int c = getc (cmi_file);
+
+ /* Skip whitespace. */
+ while (c != EOF && ISSPACE (c))
+ {
+ if (c == '\n') lineno++;
+ c = getc (cmi_file);
+ }
+
+ switch (c)
+ {
+ case EOF:
+ t = 0;
+ lineno = 1; /* For the next file. */
+ break;
+
+ /* Comments begin with % and go to the end of the line. */
+ case '%':
+ while ((c = getc (cmi_file)) != '\n' && c != EOF)
+ ;
+ if (c == '\n') lineno++;
+ break;
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ case '.': case '-': case '+':
+ ungetc (c, cmi_file);
+ t = get_numeric_token (cmi_file);
+ break;
+
+ case '"':
+ t = get_string_token (cmi_file);
+ break;
+
+ case ',':
+ t = c;
+ break;
+
+ default:
+ ungetc (c, cmi_file);
+ t = get_word_token (cmi_file);
+ break;
+ }
+ }
+ while (t == NOT_A_TOKEN);
+
+ return t;
+}
+
+
+/* Assume we've opened the file with `libfile_start'. We've been
+ keeping track of the line numbers ourselves, though. */
+
+static void
+yyerror (string s)
+{
+ fprintf (stderr, "%s:%u: %s\n", libfilename (), lineno, s);
+}
+
+/* Read a numeric decimal constant from the file F. Always return T_REAL
+ and set yylval.realval. */
+
+static int
+get_numeric_token (FILE *f)
+{
+ variable_string vs = vs_init ();
+ int c = getc (f);
+
+ /* Look for a sign. */
+ if (c == '+' || c == '-')
+ {
+ vs_append_char (&vs, c);
+ c = getc (f);
+ }
+
+ /* Collect leading digits. */
+ while (ISDIGIT (c))
+ {
+ vs_append_char (&vs, c);
+ c = getc (f);
+ }
+
+ /* If we're at a decimal point, keep going. */
+ if (c == '.')
+ {
+ /* Collect more digits. Append first, so we grab the `.'. */
+ do
+ {
+ vs_append_char (&vs, c);
+ c = getc (f);
+ }
+ while (ISDIGIT (c));
+
+ /* Don't bother to allow `e<exponent>' at the end. */
+ }
+
+ /* Add the terminating null and convert the string to a number. */
+ vs_append_char (&vs, 0);
+
+ yylval.realval = atof (VS_CHARS (vs));
+ vs_free (&vs);
+
+ return T_REAL;
+}
+
+/* Read a string constant from the file F. We make no provision for
+ quoting " characters; the string just consists of everything from one
+ " to the next. We return T_STRING and set yylval.strval. */
+
+static int
+get_string_token (FILE *f)
+{
+ int c;
+ variable_string vs = vs_init ();
+
+ while ((c = getc (f)) != EOF && c != '"')
+ vs_append_char (&vs, c);
+
+ if (c == EOF)
+ FATAL ("CMI file ended in the midst of a string");
+
+ /* Add the terminating null. */
+ vs_append_char (&vs, 0);
+
+ yylval.strval = VS_CHARS (vs);
+
+ return T_STRING;
+}
+
+/* Return the Bison-defined value for the token equal to the
+ next (space-delimited) identifier in the file F. That is, if it's a
+ reserved word return the corresponding value TR_..., else return
+ T_IDENTIFIER. */
+
+static int
+get_word_token (FILE *f)
+{
+ int c, t;
+ variable_string word = vs_init ();
+
+ while ((c = getc (f)) != EOF && !ISSPACE (c))
+ vs_append_char (&word, c);
+
+ if (c != EOF)
+ ungetc (c, f);
+
+ /* Add the terminating null. */
+ vs_append_char (&word, 0);
+
+ t = token_number (VS_CHARS (word));
+
+ /* We don't need the characters in the identifier again. */
+ vs_free (&word);
+
+ return t;
+}
+
+
+/* Return the token code corresponding to the word STR. If STR is not
+ one of the reserved words, return T_IDENTIFIER. */
+
+static int
+token_number (string word)
+{
+ int t;
+
+ if (STREQ (word, "char"))
+ t = TR_CHAR;
+ else if (STREQ (word, "char-width"))
+ t = TR_CHAR_WIDTH;
+ else if (STREQ (word, "codingscheme"))
+ t = TR_CODINGSCHEME;
+ else if (STREQ (word, "define"))
+ t = TR_DEFINE;
+ else if (STREQ (word, "fontdimen"))
+ t = TR_FONTDIMEN;
+ else if (STREQ (word, "kern"))
+ t = TR_KERN;
+ else
+ {
+ t = T_IDENTIFIER;
+ yylval.strval = xstrdup (word);
+ }
+
+ return t;
+}
diff --git a/charspace/input-cmi.c b/charspace/input-cmi.c
new file mode 100644
index 0000000..ffba878
--- /dev/null
+++ b/charspace/input-cmi.c
@@ -0,0 +1,60 @@
+/* input-cmi.c: routines to control the CMI parsing.
+
+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 "libfile.h"
+
+#include "input-cmi.h"
+
+
+/* Font-specific sidebearing and other information. (-cmi-files)
+ `cmi_file' is used as the input file in `cmi.y'. */
+FILE *cmi_file;
+string *cmi_names = NULL;
+
+/* Call `read_cmi_file' on each CMI file in CMI_NAMES. DPI is
+ simply passed along. */
+
+void
+read_cmi_file_list (string *cmi_names, string dpi)
+{
+ if (cmi_names == NULL)
+ return;
+
+ for ( ; *cmi_names != NULL; cmi_names++)
+ {
+ read_cmi_file (*cmi_names, dpi);
+ }
+}
+
+
+/* Read the CMI file `NAME.DPIcmi', unless NAME has a suffix, in which
+ case don't append the `.DPIcmi'. This uses the global `cmi_file' to
+ communicate with the Bison parser. */
+
+void
+read_cmi_file (string name, string dpi)
+{
+ extern int yyparse ();
+
+ cmi_file = libfile_start (name, concat (dpi, "cmi"));
+ yyparse ();
+
+ libfile_close ();
+}
diff --git a/charspace/input-cmi.h b/charspace/input-cmi.h
new file mode 100644
index 0000000..469c6b0
--- /dev/null
+++ b/charspace/input-cmi.h
@@ -0,0 +1,37 @@
+/* input-cmi.h: declarations for top-level CMI reading.
+
+Copyright (C) 1992, 93 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. */
+
+#ifndef INPUT_CMI_H
+#define INPUT_CMI_H
+
+#include <stdio.h>
+#include <kpathsea/types.h>
+
+
+/* See `input-cmi.c'. */
+extern FILE *cmi_file;
+extern string *cmi_names;
+
+
+/* Read the CMI file NAME. If NAME has no extension, supply `.DPIcmi'. */
+extern void read_cmi_file (string name, string dpi);
+
+/* Call `read_cmi_file' on each name in NAME_LIST. */
+extern void read_cmi_file_list (string *name_list, string dpi);
+
+#endif /* not INPUT_CMI_H */
diff --git a/charspace/kern.c b/charspace/kern.c
new file mode 100644
index 0000000..80a2ea9
--- /dev/null
+++ b/charspace/kern.c
@@ -0,0 +1,52 @@
+/* kern.c: kerns in the CMI file.
+
+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 "kern.h"
+
+
+/* This is taken from `tfm_set_kern', except RIGHT is a character name,
+ instead of a character code, and the value of the kern K is a
+ `symval_type' (since it is useful, as well as more consistent, to
+ define kerns like side bearings) instead of a real. */
+
+void
+char_set_kern (list_type *kern_list, string right, symval_type k)
+{
+ unsigned this_right;
+ char_kern_type *new_kern;
+
+ assert (kern_list != NULL);
+
+ for (this_right = 0; this_right < LIST_SIZE (*kern_list); this_right++)
+ {
+ char_kern_type *kern = LIST_ELT (*kern_list, this_right);
+
+ if (STREQ (kern->character, right))
+ { /* Already there, just replace the value. */
+ kern->kern = k;
+ return;
+ }
+ }
+
+ /* RIGHT wasn't in the existing list. Add it to the end. */
+ new_kern = LIST_TAPPEND (kern_list, char_kern_type);
+ new_kern->character = right;
+ new_kern->kern = k;
+}
diff --git a/charspace/kern.h b/charspace/kern.h
new file mode 100644
index 0000000..6df17ca
--- /dev/null
+++ b/charspace/kern.h
@@ -0,0 +1,41 @@
+/* kern.h: handle kerns in the CMI file.
+
+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. */
+
+#ifndef KERN_H
+#define KERN_H
+
+#include "symtab.h"
+#include <kpathsea/types.h>
+
+/* The kern list. This differs from `tfm_kern_type' in that it
+ uses character names instead of (integer) codes, and uses
+ `symval_type' for the value. Thus, the user can symbolically define
+ kerns in the same way as sidebearings. */
+
+typedef struct
+{
+ string character;
+ symval_type kern;
+} char_kern_type;
+
+
+/* Make the kern for the character named RIGHT in the list of
+ `char_kern_type's KERN_LIST be K, replacing any kern already present. */
+extern void char_set_kern (list_type *kern_list, string right, symval_type k);
+
+#endif /* not KERN_H */
diff --git a/charspace/main.c b/charspace/main.c
new file mode 100644
index 0000000..500c9a6
--- /dev/null
+++ b/charspace/main.c
@@ -0,0 +1,330 @@
+/* charspace -- find intercharacter spacing based on user information.
+
+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 <kpathsea/tex-file.h>
+#include <kpathsea/pathsearch.h>
+#include <kpathsea/paths.h>
+
+#include "cmdline.h"
+#include "encoding.h"
+#include "font.h"
+#include "report.h"
+
+#include "char.h"
+#include "input-cmi.h"
+#include "main.h"
+#include "output.h"
+#include "symtab.h"
+
+/* Must come after `symtab.h', since it uses `symval_type'. (It's
+ generated by Bison, so we can't fix it.) */
+#include "cmi.h"
+
+
+/* The resolution of the font we will read, in pixels per inch. We
+ don't deal with nonsquare pixels. (-dpi) */
+string dpi = "300";
+real dpi_real;
+
+/* The name of the encoding file specified by the user, and the
+ structure we parse it into. (-encoding) */
+static string encoding_name = NULL;
+encoding_info_type encoding_info;
+
+/* Whether or not there was a TFM file corresponding to `input_name'.
+ If true, `tfm_get_char' can be called -- otherwise not. */
+boolean have_tfm = false;
+
+/* The name of the bitmap font we input. */
+string input_name;
+
+/* Whether or not to output a GF file. (-no-gf) */
+boolean no_gf = false;
+
+/* Says which characters we should process. This is independent of the
+ ordering in the font file. (-range) */
+charcode_type starting_char = 0;
+charcode_type ending_char = MAX_CHARCODE;
+
+
+static string read_command_line (int, string[]);
+static encoding_info_type read_encoding_info (string);
+static string *scan_string_list (string);
+
+/* Charspace computes side bearing values to put in a font. It doesn't
+ do so automatically, unfortunately: auxiliary files have to specify
+ everything. The basic idea is due to Harry Carter as described in
+ Walter Tracy's book (see README for the citation): space a few of the
+ letters (O, H, o, n) by hand amongst themselves. Then a reasonable
+ value for most of the other side bearings can be determined
+ (independent of the typeface) as a percentage of those ``control
+ letters'' sidebearings.
+
+ The basic strategy is to first read `common.cmi', which specifies the
+ font-independent side bearing apportionments. Then we read
+ font-specific CMI files to actually define the side bearing values,
+ specify kerns, and so on.
+
+ This defines a whole bunch of things in the symbol table (see
+ `symtab.c'). We then resolve the side bearing information for all
+ the characters we will output, after all the definitions have been
+ read.
+
+ Then we output the revised GF and TFM files. We read an existing TFM
+ file and an encoding file, as well as accepting various options, to
+ get lig/kern and other TFM information. */
+
+int
+main (int argc, string argv[])
+{
+ /* This is static only because we want it to be initialized entirely
+ to NULL pointers, and it's too painful to write out 256 NULL's. */
+ static char_type *chars[MAX_CHARCODE + 1];
+ unsigned code;
+ bitmap_font_type font;
+ string font_rootname;
+ string tfm_name;
+
+ /* Get the bitmap font we're reading. */
+ input_name = read_command_line (argc, argv);
+ font = get_bitmap_font (input_name, atou (dpi));
+ font_rootname = remove_suffix (basename (input_name));
+
+ /* Make sure the output name is ok. */
+ if (output_name == NULL)
+ output_name = input_name;
+
+ if (!no_gf && find_suffix (output_name) != NULL)
+ FATAL ("You can't specify a suffix and more than one output file");
+
+ tfm_name = kpse_find_tfm (input_name);
+ if (tfm_name != NULL)
+ {
+ if (!tfm_open_input_file (tfm_name))
+ FATAL1 ("%s: Could not open TFM file", tfm_name);
+ else
+ have_tfm = true;
+ }
+
+ /* Set the numeric counterpart of `dpi', for use in lots of places. */
+ dpi_real = atof (dpi);
+
+ /* If the user didn't specify CMI files to read, then use
+ `<input_name>.<dpi>cmi'. */
+ if (cmi_names == NULL)
+ cmi_names = scan_string_list (input_name);
+
+ /* Define the designsize, so the CMI files can refer to it. */
+ {
+ real ds_points = BITMAP_FONT_DESIGN_SIZE (font);
+ real ds_pixels = POINTS_TO_REAL_PIXELS (ds_points, dpi_real);
+ symtab_define ("designsize", symtab_real_node (ds_pixels));
+ }
+
+ /* Read all the CMI information. */
+ read_cmi_file ("common.cmi", "");
+ read_cmi_file_list (cmi_names, dpi);
+
+ /* Figure out the font encoding scheme. Must be done after reading
+ the CMI files, since they can specify the codingscheme. */
+ encoding_info = read_encoding_info (encoding_name);
+
+ /* The main loop: compute each character's information. */
+ for (code = starting_char; code <= ending_char; code++)
+ {
+ do_char (code, &chars[code]);
+ }
+
+ /* Output what we've so laboriously collected. */
+ output_font (font, chars);
+
+ close_font (input_name);
+ if (have_tfm)
+ tfm_close_input_file ();
+
+ return 0;
+}
+
+/* Return the font encoding. Use
+ 1) USER_NAME (if it's non-null);
+ 2) the value of `codingscheme' in the symbol table (if it's a string);
+ 3) the codingscheme from an existing TFM file (if we have one).
+
+ Otherwise, give a fatal error. */
+
+static encoding_info_type
+read_encoding_info (string user_name)
+{
+ encoding_info_type ei;
+
+ if (user_name != NULL)
+ ei = read_encoding_file (user_name);
+ else
+ {
+ string enc_name;
+ string codingscheme = NULL;
+ symval_type *sv = symtab_lookup ("codingscheme");
+
+ if (sv == NULL)
+ codingscheme = have_tfm ? tfm_get_coding_scheme () : DEFAULT_ENCODING;
+
+ else if (SYMVAL_TAG (*sv) == symval_string)
+ codingscheme = SYMVAL_STRING (*sv);
+
+ else
+ FATAL ("codingscheme: defined (in CMI file) as a non-string");
+
+ assert (codingscheme != NULL);
+
+ enc_name = coding_scheme_to_filename (codingscheme);
+ ei = read_encoding_file (enc_name);
+ }
+
+ return ei;
+}
+
+/* Reading the options. */
+
+/* This is defined in version.c. */
+extern string version_string;
+
+#define USAGE "Options:
+<font_name> should be a filename, possibly with a resolution, e.g.,
+ `cmr10' or `cmr10.300'.\n" \
+ GETOPT_USAGE \
+"cmi-files <file1>,<file2>,...: read the CMI files
+ `<file1>.<dpi>cmi', `<file2>.<dpi>cmi', etc., after reading
+ `common.cmi'; default is `<font-name>.<dpi>cmi'. The <dpi>cmi is not
+ appended to any of the <file>s which already have a suffix.
+dpi <unsigned>: use this resolution; default is 300.
+encoding <filename>: read ligature and other encoding information
+ from <filename>.enc; there is no default. (A TFM file <font-name>.tfm
+ is also read, if it exists.)
+fontdimens <fontdimen>:<real>,<fontdimen>:<real>,...: assign <value>
+ to each <fontdimen> given, when outputting a TFM file. A <fontdimen>
+ can be either one of the standard names (in either upper or
+ lowercase), or a number between 1 and 30. Each <real> is taken to be
+ in points (except in the case of the <fontdimen> `SLANT' (parameter
+ 1), which is a dimensionless number).
+no-gf: don't output a GF file.
+output-file <filename>: write the TFM file to `<filename>.tfm' and the
+ GF file to `<filename>.<dpi>gf'; <filename> shouldn't have a suffix;
+ default is <font-name>.tfm and <font-name>.<dpi>gf, or, if those would
+ overwrite the input, those preceded by `x'.
+range <char1>-<char2>: only process characters between <char1> and
+ <char2>, inclusive.
+verbose: print brief progress reports on stdout.
+version: print the version number of this program.
+xheight-char <charcode>: use the height of this character as the
+ default x-height (for the TFM output); default is 120 (ASCII `x').
+"
+
+static string
+read_command_line (int argc, string argv[])
+{
+ int g; /* `getopt' return code. */
+ int option_index;
+ boolean explicit_dpi = false;
+ boolean printed_version = false;
+ struct option long_options[]
+ = { { "dpi", 1, 0, 0 },
+ { "cmi-files", 1, 0, 0 },
+ { "encoding", 1, 0, 0 },
+ { "fontdimens", 1, 0, 0 },
+ { "help", 0, 0, 0 },
+ { "no-gf", 0, (int *) &no_gf, 1 },
+ { "output-file", 1, 0, 0 },
+ { "range", 1, 0, 0 },
+ { "verbose", 0, (int *) &verbose, 1 },
+ { "version", 0, (int *) &printed_version, 1 },
+ { "xheight-char", 1, 0, 0 },
+ { 0, 0, 0, 0 } };
+
+ while (true)
+ {
+ g = getopt_long_only (argc, argv, "", long_options, &option_index);
+
+ if (g == EOF)
+ break;
+
+ if (g == '?')
+ continue; /* Unknown option. */
+
+ assert (g == 0); /* We have no short option names. */
+
+ if (ARGUMENT_IS ("cmi-files"))
+ cmi_names = scan_string_list (optarg);
+
+ else if (ARGUMENT_IS ("dpi"))
+ dpi = optarg;
+
+ else if (ARGUMENT_IS ("encoding"))
+ encoding_name = optarg;
+
+ else if (ARGUMENT_IS ("fontdimens"))
+ fontdimens = optarg;
+
+ else if (ARGUMENT_IS ("help"))
+ {
+ fprintf (stderr, "Usage: %s [options] <font_name>.\n", argv[0]);
+ fprintf (stderr, USAGE);
+ exit (0);
+ }
+
+ else if (ARGUMENT_IS ("output-file"))
+ output_name = optarg;
+
+ else if (ARGUMENT_IS ("range"))
+ GET_RANGE (optarg, starting_char, ending_char);
+
+ else if (ARGUMENT_IS ("version"))
+ printf ("%s.\n", version_string);
+
+ else if (ARGUMENT_IS ("xheight-char"))
+ xheight_char = xparse_charcode (optarg);
+
+ /* Else it was just a flag; getopt has already done the assignment. */
+ }
+
+ FINISH_COMMAND_LINE ();
+}
+
+
+/* Take a string L consisting of unsigned strings separated by commas
+ and return a vector of the strings, as pointers.
+ Append an element to the vector. */
+
+static string *
+scan_string_list (string l)
+{
+ string map;
+ unsigned length = 1;
+ string *vector = xmalloc (sizeof (string));
+
+ for (map = strtok (l, ","); map != NULL; map = strtok (NULL, ","))
+ {
+ length++;
+ vector = xrealloc (vector, length * sizeof (string));
+ vector[length - 2] = map;
+ }
+
+ vector[length - 1] = NULL;
+ return vector;
+}
diff --git a/charspace/main.h b/charspace/main.h
new file mode 100644
index 0000000..431f3e3
--- /dev/null
+++ b/charspace/main.h
@@ -0,0 +1,41 @@
+/* main.h: global variable declarations.
+
+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. */
+
+#ifndef MAIN_H
+#define MAIN_H
+
+#include <stdio.h>
+#include <kpathsea/types.h>
+
+#include "encoding.h"
+
+
+/* See main.c. */
+extern FILE *cmi_file;
+extern string dpi;
+extern real dpi_real;
+extern encoding_info_type encoding_info;
+extern boolean have_tfm;
+extern string input_name;
+extern boolean no_gf;
+extern charcode_type starting_char, ending_char;
+
+/* This is defined in version.c. */
+extern string version_string;
+
+#endif /* not MAIN_H */
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;
+}
diff --git a/charspace/output.c b/charspace/output.c
new file mode 100644
index 0000000..82afe97
--- /dev/null
+++ b/charspace/output.c
@@ -0,0 +1,362 @@
+/* output.c: use the `char_type's' information to output a new font.
+
+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 "encoding.h"
+#include "filename.h"
+#include "gf.h"
+#include "libfile.h"
+#include "report.h"
+#include "tfm.h"
+
+#include "char.h"
+#include "main.h"
+#include "output.h"
+#include "symtab.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;
+}
diff --git a/charspace/output.h b/charspace/output.h
new file mode 100644
index 0000000..f10c7dc
--- /dev/null
+++ b/charspace/output.h
@@ -0,0 +1,36 @@
+/* output.h: declarations for outputting the newly spaced font.
+
+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. */
+
+#ifndef OUTPUT_H
+#define OUTPUT_H
+
+#include "font.h"
+#include "char.h"
+
+
+/* See output.c. */
+extern string fontdimens;
+extern string output_name;
+extern charcode_type xheight_char;
+
+/* Output a TFM and (perhaps) GF file with the new spacings for the
+ characters CHARS. Use the font B for the character bitmaps. The
+ font is written to the current directory. */
+extern void output_font (bitmap_font_type b, char_type *chars[]);
+
+#endif /* not OUTPUT_H */
diff --git a/charspace/realstrval.h b/charspace/realstrval.h
new file mode 100644
index 0000000..6a1b7f9
--- /dev/null
+++ b/charspace/realstrval.h
@@ -0,0 +1,46 @@
+/* realstrval.h: types common to `char.h' and `symtab.h'.
+
+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. */
+
+#ifndef REALSTRVAL_H
+#define REALSTRVAL_H
+
+#include <kpathsea/types.h>
+
+
+/* This structure is used both as part of `char_type' and as part of
+ `symval_type', so we must define it separately.
+
+ We use `symval_tag_type' to remember which parts of the struct count,
+ although `symval_char' is irrelevant to a `real_string_val'. If both
+ the real and string parts are set, the value is taken to be the
+ product. */
+
+typedef enum
+{
+ symval_real, symval_string, symval_real_string, symval_char,
+ symval_char_width
+} symval_tag_type;
+
+
+typedef struct
+{
+ real real_val;
+ string string_val;
+} real_string_val_type;
+
+#endif /* not REALSTRVAL_H */
diff --git a/charspace/symtab.c b/charspace/symtab.c
new file mode 100644
index 0000000..1004b5a
--- /dev/null
+++ b/charspace/symtab.c
@@ -0,0 +1,322 @@
+/* symtab.c: create and update a symbol table. We use a simple linear
+ representation, since there will be a few hundred entries at
+ the very most.
+
+ The numbers which get stored in the symbol table should all be in
+ pixels. That's what the rest of the program expects. (Unfortunately
+ there's no way to check this at the time of definition.)
+
+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 "kern.h"
+#include "main.h"
+#include "symtab.h"
+
+
+/* Every identifier in the CMI files -- character names and fontdimen
+ names as well as `define'd quantities -- gets put into our symbol
+ table. We do not resolve any definitions until they are actually
+ needed, so that later definitions will replace earlier ones. */
+struct symbol
+{
+ string key;
+ symval_type value;
+ struct symbol *next;
+};
+
+/* These all work on pointers instead of structures, since that's what
+ we need to pass around in this file. */
+#define SYM_KEY(s) ((s)->key)
+#define SYM_NEXT(s) ((s)->next)
+#define SYM_VAL(s) ((s)->value)
+
+typedef struct symbol symbol_type;
+
+
+/* We have only one symbol table. Here it is. */
+static symbol_type *symbol_table = NULL;
+
+
+static symbol_type *symtab_find (string);
+static boolean resolve_string (symval_type *, real);
+
+/* Routines to create symval nodes. */
+
+symval_type
+symtab_char_node (symval_type lsb, symval_type rsb)
+{
+ symval_type sv;
+
+ SYMVAL_TAG (sv) = symval_char;
+ SYMVAL_CHAR (sv) = init_char ();
+
+ CHAR_LSB (SYMVAL_CHAR (sv)) = XTALLOC1 (sidebearing_type);
+ CHAR_LSB_TAG (SYMVAL_CHAR (sv)) = SYMVAL_TAG (lsb);
+ CHAR_LSB_VALUE (SYMVAL_CHAR (sv)) = SYMVAL_REAL_STRING (lsb);
+
+ CHAR_RSB (SYMVAL_CHAR (sv)) = XTALLOC1 (sidebearing_type);
+ CHAR_RSB_TAG (SYMVAL_CHAR (sv)) = SYMVAL_TAG (rsb);
+ CHAR_RSB_VALUE (SYMVAL_CHAR (sv)) = SYMVAL_REAL_STRING (rsb);
+
+ return sv;
+}
+
+
+symval_type
+symtab_real_node (real r)
+{
+ symval_type sv;
+
+ SYMVAL_TAG (sv) = symval_real;
+ SYMVAL_REAL (sv) = r;
+
+ return sv;
+}
+
+
+symval_type
+symtab_real_string_node (real r, string s)
+{
+ symval_type sv;
+
+ SYMVAL_TAG (sv) = symval_real_string;
+ SYMVAL_REAL (sv) = r;
+ SYMVAL_STRING (sv) = s;
+
+ return sv;
+}
+
+
+symval_type
+symtab_string_node (string s)
+{
+ symval_type sv;
+
+ SYMVAL_TAG (sv) = symval_string;
+ SYMVAL_STRING (sv) = s;
+
+ return sv;
+}
+
+/* Define the identifier KEY to be the value V. We do no checking on V,
+ we just plop it in. Overwrite any previous definition of KEY. If
+ KEY was not previously defined, we malloc a new symbol. */
+
+void
+symtab_define (string key, symval_type v)
+{
+ symbol_type *s = symtab_find (key);
+
+ if (s == NULL)
+ {
+ s = XTALLOC1 (symbol_type);
+
+ /* Make a private copy of KEY so outside assignments or
+ deallocations don't affect the symbol table. */
+ SYM_KEY (s) = xstrdup (key);
+ SYM_NEXT (s) = symbol_table;
+ symbol_table = s;
+ }
+
+ /* Whether we just created it or not, put in the new value. */
+ SYM_VAL (s) = v;
+}
+
+/* Define a kern of K pixels between the characters named LEFT and
+ RIGHT. If no kern for that pair previously existed, we create it.
+ If the character LEFT was not previously in the symbol table, we add
+ it. But if LEFT was in the symbol table, we have to preserve any
+ kerns or side bearing information that have already been stored. */
+
+void
+symtab_define_kern (string left, string right, symval_type k)
+{
+ symval_type sv;
+ symbol_type *s = symtab_find (left);
+
+ if (s == NULL || SYMVAL_TAG (SYM_VAL (s)) != symval_char)
+ {
+ list_type *kern_list_ptr;
+ char_kern_type *new_kern;
+
+ SYMVAL_TAG (sv) = symval_char;
+ SYMVAL_CHAR (sv) = init_char ();
+
+ kern_list_ptr = &CHAR_KERNS (SYMVAL_CHAR (sv));
+ new_kern = LIST_TAPPEND (kern_list_ptr, char_kern_type);
+ new_kern->character = right;
+ new_kern->kern = k;
+ }
+ else
+ {
+ sv = SYM_VAL (s);
+ char_set_kern (&CHAR_KERNS (SYMVAL_CHAR (sv)), right, k);
+ }
+
+ symtab_define (left, sv);
+}
+
+/* Look up KEY in `symbol_table'. If found, return a pointer to the
+ corresponding symval, else NULL. */
+
+symval_type *
+symtab_lookup (string key)
+{
+ symbol_type *s = symtab_find (key);
+ symval_type *sv = s ? &SYM_VAL (s) : NULL;
+
+ return sv;
+}
+
+
+/* Look up KEY in `symbol_table', resolve its definition to a real, and
+ return the result. If the value cannot be resolved, or if KEY isn't
+ defined, give a fatal error. */
+
+real
+symtab_lookup_real (string key)
+{
+ real r;
+ symval_type *sv = symtab_lookup (key);
+
+ if (sv == NULL)
+ FATAL1 ("%s: Undefined symbol", key);
+
+ if (symval_resolve (sv))
+ r = SYMVAL_REAL (*sv);
+ else
+ FATAL1 ("%s: Cannot be resolved to a real", key);
+
+ return r;
+}
+
+
+/* Look up KEY in `symbol_table'. If found, return the containing
+ symbol, otherwise NULL. */
+
+static symbol_type *
+symtab_find (string key)
+{
+ symbol_type *s;
+
+ assert (key != NULL);
+
+ for (s = symbol_table; s != NULL && !STREQ (SYM_KEY (s), key);
+ s = SYM_NEXT (s))
+ ;
+
+ return s;
+}
+
+/* Resolve (to a real) the symbol value SV. Change SV if we succeed.
+ Return success. */
+
+boolean
+symval_resolve (symval_type *sv)
+{
+ boolean ok;
+
+ if (sv == NULL)
+ return false;
+
+ switch (SYMVAL_TAG (*sv))
+ {
+ case symval_char:
+ ok = false;
+ break;
+
+ case symval_real:
+ ok = true;
+ break;
+
+ case symval_real_string:
+ ok = resolve_string (sv, SYMVAL_REAL (*sv));
+ break;
+
+ case symval_string:
+ ok = resolve_string (sv, 1.0);
+ break;
+
+ default:
+ abort (); /* We have listed all the cases. */
+ }
+
+ return ok;
+}
+
+
+/* Assume SV is non-null, and that its SYMVAL_STRING field is
+ meaningful. Look up that string, resolve the result. If that
+ succeeds, multiply by FACTOR, change SV, and return success. */
+
+static boolean
+resolve_string (symval_type *sv, real factor)
+{
+ boolean ok = false;
+
+ symval_type *sv_aux = symtab_lookup (SYMVAL_STRING (*sv));
+
+ if (symval_resolve (sv_aux))
+ {
+ SYMVAL_TAG (*sv) = symval_real;
+ SYMVAL_REAL (*sv) = SYMVAL_REAL (*sv_aux) * factor;
+ ok = true;
+ }
+
+ return ok;
+}
+
+/* Return a description of SV as a string. */
+
+string
+symval_as_string (symval_type sv)
+{
+ string desc;
+
+ switch (SYMVAL_TAG (sv))
+ {
+ case symval_char:
+ {
+ string charcode = CHAR_BITMAP_INFO (SYMVAL_CHAR (sv)) != NULL
+ ? concat (" ", utoa (CHAR_CHARCODE (SYMVAL_CHAR (sv))))
+ : "";
+ desc = concat ("character", charcode);
+ if (*charcode != 0)
+ free (charcode);
+ }
+ break;
+
+ case symval_real:
+ desc = xdtoa (SYMVAL_REAL (sv));
+ break;
+
+ case symval_real_string:
+ desc = concat (xdtoa (SYMVAL_REAL (sv)), SYMVAL_STRING (sv));
+ break;
+
+ case symval_string:
+ desc = xstrdup (SYMVAL_STRING (sv));
+ break;
+
+ default:
+ abort (); /* We have listed all the cases. */
+ }
+
+ return desc;
+}
diff --git a/charspace/symtab.h b/charspace/symtab.h
new file mode 100644
index 0000000..e792ca8
--- /dev/null
+++ b/charspace/symtab.h
@@ -0,0 +1,78 @@
+/* symtab.h: declarations for our symbol table manipulations.
+
+Copyright (C) 1992, 93 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. */
+
+#ifndef SYMTAB_H
+#define SYMTAB_H
+
+#include <kpathsea/types.h>
+#include "char.h"
+#include "realstrval.h"
+
+
+/* What a single symbol looks like. */
+
+typedef struct
+{
+ symval_tag_type tag;
+
+ union
+ {
+ real_string_val_type real_string_val;
+ char_type char_val;
+ } value;
+} symval_type;
+
+/* Accessor macros. */
+#define SYMVAL_TAG(s) ((s).tag)
+#define SYMVAL_CHAR(s) ((s).value.char_val)
+#define SYMVAL_REAL(s) ((s).value.real_string_val.real_val)
+#define SYMVAL_REAL_STRING(s) ((s).value.real_string_val)
+#define SYMVAL_STRING(s)((s).value.real_string_val.string_val)
+
+
+/* Create new value nodes of the various types. */
+extern symval_type symtab_char_node (symval_type lsb, symval_type rsb);
+extern symval_type symtab_real_node (real);
+extern symval_type symtab_real_string_node (real, string);
+extern symval_type symtab_string_node (string);
+
+/* Define the identifier KEY to be the value V. Overwrite any
+ previous definition of KEY. */
+extern void symtab_define (string key, symval_type v);
+
+/* Define a kern K between the characters named LEFT and RIGHT. */
+extern void symtab_define_kern (string left, string right, symval_type k);
+
+
+/* Return the value of KEY, or NULL. */
+extern symval_type *symtab_lookup (string key);
+
+/* Resolve KEY to a real if possible and return the result. If it
+ cannot be resolved, give a fatal error. */
+extern real symtab_lookup_real (string key);
+
+
+/* Resolve the definition of SV to a real, if possible. Return success. */
+extern boolean symval_resolve (symval_type *sv);
+
+
+/* Return a string describing SV (e.g., for error messages). The string
+ is allocated with malloc. */
+extern string symval_as_string (symval_type sv);
+
+#endif /* not SYMTAB_H */
diff --git a/charspace/test.cmi b/charspace/test.cmi
new file mode 100644
index 0000000..da98b7a
--- /dev/null
+++ b/charspace/test.cmi
@@ -0,0 +1,11 @@
+char not in bitmap font
+
+char in bf but not in encoding
+
+char in bf & encoding, but not CMI
+
+char in bf, encoding, & cmi, but not a character
+
+char with only one SB defined?
+
+codingscheme non-string
diff --git a/charspace/version.c b/charspace/version.c
new file mode 100644
index 0000000..998c94c
--- /dev/null
+++ b/charspace/version.c
@@ -0,0 +1 @@
+char *version_string = "charspace version REPLACE-WITH-VERSION";
diff --git a/configure.in b/configure.in
new file mode 100644
index 0000000..d53b6ac
--- /dev/null
+++ b/configure.in
@@ -0,0 +1,20 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(limn/fit.c)
+
+dnl Write output here, instead of putting -D's on the command line.
+AC_CONFIG_HEADER(include/c-auto.h)
+
+sinclude(../kpathsea/common.ac)
+
+# We must have gcc.
+[if test -n "$GCC"
+then :
+else
+ echo "Warning: these programs are written in GNU C,"
+ echo "so you need to have gcc."
+fi]
+
+AC_FIND_XTRA
+
+# This will generate `Makefile'(s), `config.status', and our header file.
+AC_OUTPUT(GNUmakefile doc/Makefile)
diff --git a/doc/ChangeLog b/doc/ChangeLog
new file mode 100644
index 0000000..7e409bb
--- /dev/null
+++ b/doc/ChangeLog
@@ -0,0 +1,103 @@
+Mon Apr 8 08:32:57 1996 Kathy Hargreaves <letters@cs.umb.edu>
+
+ * overview.texi: added direction to CCC arrow.
+
+Sat Mar 30 07:09:01 1996 Kathy Hargreaves <letters@cs.umb.edu>
+
+ * overview.texi: added TFM output line from fontconvert to
+ imageto. Added directions to arrows for GF<->fontconvert and
+ CMI->fontconvert.
+
+Sat Dec 9 08:05:30 1995 Kathy Hargreaves <karl@cs.umb.edu>
+
+ * fontcvt.texi (Character manipulation options): filtering
+ eliminates small features, such as serifs (not features).
+
+Sun May 16 15:46:54 1993 Karl Berry (karl@cs.umb.edu)
+
+ * fontu.texi: Change title to `GNU font utilities'.
+
+Wed Feb 17 06:31:03 1993 Karl Berry (karl@cs.umb.edu)
+
+ * Makefile.in (INSTALL): Use tr instead of grep to remove the
+ Info control characters.
+
+Sun Feb 7 14:22:45 1993 Karl Berry (karl@cs.umb.edu)
+
+ * Makefile.in (install): Give filename as second arg.
+ (info, dvi): New (synonym) targets.
+
+Sat Dec 5 17:15:31 1992 Karl Berry (karl@cs.umb.edu)
+
+ * bpltobzr.texi: Comment syntax is now `; ... \n', a la Lisp.
+
+Thu Oct 29 06:39:04 1992 Karl Berry (karl@cs.umb.edu)
+
+ * Makefile.in (distfiles): Add ChangeLog.
+
+Tue Oct 27 13:02:33 1992 Karl Berry (karl@cs.umb.edu)
+
+ * Version 0.6.
+
+ * Makefile.in (dist): Need Makefile temporarily.
+
+Sun Oct 25 15:30:46 1992 Karl Berry (karl@cs.umb.edu)
+
+ * Makefile.in (distclean): Depend on clean, and remove Makefile.
+
+ * Makefile.in (.NOEXPORT): Add this.
+
+ * Makefile.in (distfiles): Do Makefile.in, not Makefile.
+
+Sat Oct 24 05:18:03 1992 Karl Berry (karl@cs.umb.edu)
+
+ * imageto.texi: Default encoding is none now, not ASCII.
+ * gsrenderf.texi: Likewise.
+
+Fri Oct 23 14:16:19 1992 Karl Berry (karl@cs.umb.edu)
+
+ * fontcvt.texi: The -space option is gone.
+ * gsrenderf.texi: This doesn't use Fontconvert anymore.
+
+Tue Oct 20 14:49:21 1992 Karl Berry (karl@cs.umb.edu)
+
+ * bzrto.texi: Document -ps-font-info option.
+
+Mon Oct 5 09:19:32 1992 Karl Berry (karl@cs.umb.edu)
+
+ * Makefile.in: Renamed from Makefile (so $(prefix) gets configured.)
+
+ * bugs.texi: Add more info about criteria and philosophy,
+ restructure into sections.
+
+ * imageto.texi: Rewrite major portions.
+
+Sun Oct 4 11:18:43 1992 Karl Berry (karl@cs.umb.edu)
+
+ * {imageto,overview}.texi: Remove doc on -clean-threshold.
+
+Mon Sep 21 11:03:32 1992 Karl Berry (karl@cs.umb.edu)
+
+ * imageto.texi: document -ifi-file.
+
+Sun Sep 13 10:33:41 1992 Karl Berry (karl@hayley)
+
+ * fontu.texi: the FSF should approve permissions, not me.
+
+Sat Sep 12 16:14:39 1992 Karl Berry (karl@hayley)
+
+ * Makefile (dist): use $(MAKE).
+
+Tue Sep 8 17:41:02 1992 Karl Berry (karl@hayley)
+
+ * Makefile (clean): remove dvi files etc. here.
+ (distclean): remove empty sorted index files here.
+ (dist): not here.
+
+Fri Sep 4 08:41:16 1992 Karl Berry (karl@hayley)
+
+ * Makefile (extraclean): new target.
+
+Thu Sep 3 09:30:07 1992 Karl Berry (karl@hayley)
+
+ * Version 0.5.
diff --git a/doc/Makefile.in b/doc/Makefile.in
new file mode 100644
index 0000000..2acc2ce
--- /dev/null
+++ b/doc/Makefile.in
@@ -0,0 +1,99 @@
+# Makefile for the various bits of documentation.
+#
+# 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 1, 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.
+
+# For `install'.
+prefix = /usr/local
+infodir = $(prefix)/info
+
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+
+MAKEINFO = makeinfo
+MAKEINFO_FLAGS = --paragraph-indent=2 -I$(HOME)/gnu/gnuorg
+# That -I is purely for my own benefit in doing `make dist'. It won't
+# hurt anything for you (I hope).
+
+TEX = tex '\nonstopmode \input'
+TEXINDEX = texindex
+
+SHELL = /bin/sh
+
+default: fontu.info
+
+all: INSTALL dvi
+
+dvi: fontu.dvi
+fontu.dvi: fontu.cps
+ $(TEX) fontu.texi
+fontu.cps: fontu.cp
+ $(TEXINDEX) fontu.??
+fontu.cp: *.texi
+ $(TEX) fontu.texi
+
+info: fontu.info
+fontu.info: *.texi
+ $(MAKEINFO) $(MAKEINFO_FLAGS) ../$(srcdir)/doc/fontu.texi
+
+install: fontu.info
+ for i in fontu.info*; do $(INSTALL_DATA) $$i $(infodir)/$$i; done
+
+update:
+ emacs -batch -l update.el
+
+# We don't automatically generate dependencies.
+depend:
+
+# Separate the installation instructions into a separate file, for the
+# benefit of people who don't want to look at the info file.
+INSTALL: fontu.info
+ sed -n '/Node: Installation/,/Good luck./p' fontu.info-1 \
+ | tr -d '\037' > $@
+
+# Prevent GNU make 3 from overflowing arg limit on system V.
+.NOEXPORT:
+
+# `make dist' should only be called from the top-level Makefile, as it
+# depends on $(version), $(top_distdir), and $(dir).
+#
+distdir = ../$(top_distdir)/$(dir)
+distfiles = ChangeLog Makefile.in update.el *.texi
+
+dist::
+ mkdir $(distdir)
+ ln Makefile $(distfiles) $(distdir)
+ cp -p $(plain)/texinfo.tex $(distdir)
+#
+# Have to add the version number and date before making the Info file.
+ (cd $(distdir); \
+ add-version $(version) fontu.texi intro.texi; \
+ add-date fontu.texi; \
+ $(MAKE) INSTALL fontu.cps distclean)
+ mv $(distdir)/INSTALL ../$(top_distdir)/INSTALL
+
+clean mostlyclean:
+ rm -f fontu.?? *.dvi *.log *.toc
+
+distclean: clean
+ rm -f Makefile
+ for f in fontu.??s; do if test ! -s $$f; then rm -f $$f; fi; done
+
+extraclean: distclean
+ rm -f *~ \#* patch* *.orig *.rej *.bak *.ckp core a.out
+
+realclean: distclean
+ rm -f *.info* fontu.??? INSTALL
diff --git a/doc/bpltobzr.texi b/doc/bpltobzr.texi
new file mode 100644
index 0000000..157b5f4
--- /dev/null
+++ b/doc/bpltobzr.texi
@@ -0,0 +1,283 @@
+@c Copyright (C) 1992 Free Software Foundation.
+@c This is part of the GNU font utilities manual.
+@c For copying conditions, see the file fontutil.texi.
+
+@node BPLtoBZR, XBfe, BZRto, Top
+@chapter BPLtoBZR
+
+@pindex bpltobzr
+@cindex converting BPL files to BZR
+@cindex editing BZR fonts
+
+BPLtoBZR translates a human-readable (and -editable) text file in BPL
+format (see below) to the binary BZR (Bezier) font format.
+
+Of the two, only BZR files can be changed into font formats which
+typesetting programs can use. So after editing a BPL file, you need to
+run this program. BZRedit likewise invokes it when necessary
+(@pxref{BZRedit}).
+
+@menu
+* BPL files:: Bezier property list file format.
+* Invoking BPLtoBZR:: Command-line options.
+@end menu
+
+
+@node BPL files, Invoking BPLtoBZR, , BPLtoBZR
+@section BPL files
+
+@cindex BPL files
+@cindex Bezier property list files
+@cindex plain text BZR files
+
+Bezier property list (BPL) files are free-format text files which
+describe an outline font. They are a transliteration of the binary
+BZR font format (@pxref{BZR files}).
+
+@cindex Lisp
+@cindex BPL syntax
+@cindex syntax, of BPL files
+A BPL file is a sequence of entries of the form
+@example
+(@var{property-name} @var{value1} @var{value2} @dots{})
+@end example
+
+@cindex data types in BPL files
+@cindex types of data in BPL files
+@cindex BPL data types
+@cindex realstr data type
+The @var{property-name} is one of a small set of keywords understood by
+BPLtoBZR. The @var{value}s vary depending on the property being
+defined. BPL files have four types of values: unsigned integers, reals,
+strings (enclosed in typewriter double-quote @samp{"} marks), and
+@dfn{real strings} (@dfn{realstr} for short)---a real number in quotes.
+@xref{Editing BPL files}, for an explanation of why realstrs are
+necessary.
+
+@cindex comments in BPL files
+@cindex BPL comments
+@cmindex comment @r{BPL property}
+A semicolon not inside a string constant begins a comment, which
+continues until the end of the line.
+
+BPL files have three parts: a preamble, character definitions, and a
+postamble. They must appear in that order. In many cases, the order in
+which you give the properties within a part is also significant.
+
+@menu
+* Preamble: BPL preamble. The beginning.
+* Characters: BPL characters. The middle.
+* Postamble: BPL postamble. The end.
+@end menu
+
+
+@node BPL preamble, BPL characters, , BPL files
+@subsection BPL preamble
+
+@cindex BPL preamble
+@cindex preamble in BPL files
+
+The @dfn{preamble} of a BPL file consists of the following three
+properties:
+
+@enumerate
+
+@cmindex fontfile @r{BPL property}
+@cindex BZR filename in BPL files
+@item
+@code{(fontfile @var{string})}. This merely documents the filename of
+the BZR font from which BZRto made this BPL file. It is ignored.
+
+@cmindex fontcomment @r{BPL property}
+@cindex maximum length of BPL comment
+@cindex BPL comment, maximum length
+@item
+@code{(fontcomment @var{string})}. This is an arbitrary string written
+as the ``comment'' in the BZR file. BZR-reading programs ignore this
+comment. It typically identifies the source and time of
+creation. If @var{string} is longer than 255 characters, it is
+truncated (due to limitations of the BZR format).
+
+@cmindex designsize @r{BPL property}
+@item
+@code{(designsize @var{real})}. The design size of the font, in
+printer's points.
+@end enumerate
+
+
+@node BPL characters, BPL postamble, BPL preamble, BPL files
+@subsection BPL characters
+
+@cindex BPL characters
+@cindex character definitions in BPL files
+
+A BPL file must have one or more @dfn{character definitions}. These
+have the following form:
+
+@cmindex char @r{BPL property}
+@example
+(char @var{unsigned}
+ @var{width}
+ @var{bounding-box}
+ @var{outline1}
+ @var{outline2}
+ @dots{}
+)
+@end example
+
+The @var{unsigned} number directly after the @code{char} command
+specifies the character code. If it is larger than 255 (the maximum
+character code in BZR files, and all other font formats the font
+utilities deal with) then BPLtoBZR issues a warning and uses its value
+modulo 256.
+
+The other pieces are specified as properties:
+
+@itemize @bullet
+
+@cmindex width @r{BPL property}
+@cindex set width in BPL files
+@item
+@code{(width @var{realstr})}. The set width of the character in
+printer's points.
+
+@cmindex bb @r{BPL property}
+@cindex character bounding box in BPL files
+@cindex bounding box of characters in BPL files
+@cindex side bearings in BPL files
+@cindex left side bearing in BPL files
+@cindex right side bearing in BPL files
+@item
+@code{(bb @var{llx} @var{lly} @var{urx} @var{ury})}. The bounding box
+of the character in printer's points, defined by the lower-left @math{x}
+coordinate and the upper-right @math{y} coordinate. Each value is a
+realstr. The left side bearing is defined by @var{llx}, and the right
+side bearing is defined by the difference between the set width and
+@var{urx}.
+
+@end itemize
+
+Each @var{outline} specifies a geometrical outline, i.e., a closed
+curve. For example, an @samp{o} would have two @var{outline}s. If the
+character is entirely blank, the BPL file has no @var{outline}s at all.
+
+The outline property is somewhat more complex than the rest, so we
+describe it below.
+
+@menu
+* BPL outlines:: Representation of character outlines.
+@end menu
+
+
+@node BPL outlines, , , BPL characters
+@subsubsection BPL outlines
+
+@cindex BPL outlines
+@cindex outlines in BPL files
+@cindex character shape in BPL files
+
+You specify an @dfn{outline} in a BPL file as a sequence of straight
+lines and cubic splines, in any order:
+
+@cmindex outline @r{BPL property}
+@example
+(outline @var{start-x} @var{start-y}
+ @var{piece1} @var{piece2} @dots{}
+)
+@end example
+
+@var{start-x} and @var{start-y} are realstrs which specify the initial
+position for drawing this outline. Each successive piece of the outline
+is relative to a current point, and also updates the current point.
+
+At least one @var{piece} must be present. Each @var{piece} can be one of the
+following two properties:
+
+@enumerate
+
+@cmindex line @r{BPL property}
+@cindex straight lines in BPL files
+@item
+@code{line @math{x} @math{y}}. Draw a straight line from the current
+point to @math{(x,y)}. Then set the current point to @math{(x,y)}.
+@math{x} and @math{y} are realstrs.
+
+@cmindex spline @r{BPL property}
+@cindex cubic splines in BPL files
+@cindex Bezier splines in BPL files
+@cindex curves in BPL files
+@item
+@code{spline @var{c1x} @var{c1y} @var{c2x} @var{c2y} @var{ex} @var{ey}}.
+Draw the Bezier cubic using the current point as the starting point,
+@math{(@var{c1x},@var{c1y})} and @math{(@var{c2x},@var{c2y})} as the control
+points, and @math{(@var{ex},@var{ey})} as the endpoint. Then set the
+current point to the endpoint. All coordinates are realstrs.
+
+@end enumerate
+
+If the last point the last piece of the @code{outline} is not the same
+as the starting point, the result is undefined.
+
+
+@node BPL postamble, , BPL characters, BPL files
+@subsection BPL postamble
+
+@cindex BPL postamble
+@cindex postamble, of BPL files
+
+The final piece of a BPL file is the @dfn{postamble}. It has two
+components:
+
+@enumerate
+
+@cmindex fontbb @r{BPL property}
+@cindex font bounding box in BPL files
+@item
+@code{(fontbb @var{llx} @var{lly} @var{urx} @var{ury})}. Defines the
+bounding box for the entire font in the same way as the @code{bb}
+property defines the bounding box for a character. @xref{BPL characters}.
+
+@cmindex nchars @r{BPL property}
+@cindex character count in BPL files
+@item
+@code{(nchars @var{unsigned})}. The number of characters in the BPL
+file. This is purely for informational purposes; BPLtoBZR ignores it.
+
+@end enumerate
+
+
+@node Invoking BPLtoBZR, , BPL files, BPLtoBZR
+@section Invoking BPLtoBZR
+
+@cindex invocation of BPLtoBZR
+@cindex BPLtoBZR options
+@cindex options for BPLtoBZR
+
+This section describes the options that BPLtoBZR accepts.
+@xref{Command-line options}, for general option syntax.
+
+@table @samp
+
+@opindex -help
+@item -help
+Print a usage message. @xref{Common options}.
+
+@opindex -output-file
+@item -output-file @var{filename}
+Output to @var{filename} (if it has a suffix) or to
+@file{@var{filename}.bzr} (if it doesn't).
+
+@opindex -range
+@item -range @var{char1}-@var{char2}
+Only output characters with codes between @var{char1} and @var{char2},
+inclusive. (@xref{Common options}, and @ref{Specifying character codes}.)
+
+@opindex -verbose
+@item -verbose
+Output progress reports.
+
+@opindex -version
+@item -version
+Print the version number of this program.
+
+@end table
diff --git a/doc/bugs.texi b/doc/bugs.texi
new file mode 100644
index 0000000..9fef45c
--- /dev/null
+++ b/doc/bugs.texi
@@ -0,0 +1,247 @@
+@c Copyright (C) 1992 Free Software Foundation.
+@c This is part of the GNU font utilities manual.
+@c For copying conditions, see the file fontutil.texi.
+
+@node Bugs, File formats, Overview, Top
+@chapter Bugs
+
+(This chapter is adapted from the analogous one in the GCC manual,
+written by Richard Stallman.)
+
+@cindex bug reports, purpose of
+Your bug reports are essential in making these programs reliable.
+
+@cindex service directory
+Reporting a bug may help you by bringing a solution to your problem, or
+it may not. (If it does not, look in the service directory, which is
+part of the GNU CC and GNU Emacs distributions.) In any case, the
+principal function of a bug report is to help the entire community by
+making the next release work better.
+
+@cindex improvements, suggesting
+Send bug reports for the GNU font utilities, or for their documentation,
+to the address @code{bug-gnu-utils@@prep.ai.mit.edu}. We also welcome
+suggestions for improvements, no matter how small.
+
+In order for a bug report to serve its purpose, you must include the
+information that makes for fixing the bug, as described below.
+
+Thanks (in advance)!
+
+@menu
+* Bug criteria:: Have you found a bug?
+* Bug reporting:: How to effectively report a bug.
+@end menu
+
+
+@node Bug criteria, Bug reporting, , Bugs
+@section Bug criteria
+
+@cindex criteria for bugs
+@cindex bugs, criteria for
+
+If you are not sure whether you have found a bug, here are some
+guidelines:
+
+@itemize @bullet
+
+@item
+@cindex fatal signals
+If a program gets a fatal signal, for any input whatsoever, that
+is a bug. Reliable programs never crash.
+
+@item
+@cindex invalid output fonts
+@cindex bad output fonts
+@cindex validity of fonts, checking
+@cindex fatal errors and invalid output fonts
+@pindex gftype@r{, checking validity font}
+@pindex tftopl@r{, checking validity font}
+If a program produces an invalid font, for any input whatsoever, that is
+a bug---unless the program reported a fatal error that forced it to quit
+prematurely. For example, if Metafont gives errors reading the output
+of @code{bzrto -mf}, that is a bug. You can run the @TeX{} utility
+programs GFtype and TFtoPL to check the validity of a GF or TFM file.
+
+@item
+@cindex error messages, spurious
+@cindex spurious error messages
+If a program gives an error message for valid input, that is a bug.
+Similarly, if a program gives a fatal error when it could continue
+processing, that is a bug. It is sometimes hard to tell if these
+conditions obtain; you must use your best judgement.
+
+@item
+@cindex error messages, missing
+If a program does not give an error message for invalid input, that is a bug.
+
+@end itemize
+
+
+@node Bug reporting, , Bug criteria, Bugs
+@section Bug reporting
+
+@cindex bugs, reporting
+@cindex compilation bugs, reporting
+@cindex installation bugs, reporting
+
+The purpose of a bug report is to enable someone to
+fix the bug if it is not known. It isn't important what happens if the
+bug is already known. Therefore, always write your bug reports on the
+assumption that the bug is not known.
+
+Sometimes people give a few sketchy facts and ask, ``Does this ring a
+bell?'' or ``Should this be happening?'' This cannot help us fix a bug,
+so it is basically useless. We can only respond by asking for the
+details below, so we can investigate. You might as well expedite
+matters by sending them to begin with.
+
+Try to make your bug report self-contained. If we ask you for more
+information, it is best if you include all the original information in
+your response, as well as the new information. We might have discarded
+the previous message, or even if we haven't, it takes us time to search
+for it. Similarly, if you've reported bugs before, it is still best to
+send all the information; we can't possibly remember what environment
+everyone uses!
+
+@menu
+* Necessary information:: What you need to send.
+* Unnecessary information:: What you don't need to send.
+* Documentation bugs:: Report the bugs in the manual, too.
+@end menu
+
+
+@node Necessary information, Unnecessary information, , Bug reporting
+@subsection Necessary information
+
+To enable us to fix a bug, please include all the information below. If
+the bug was in compilation or installation, as opposed to in actually
+running one of the programs, the last two items are irrelevant. But in
+that case, please also make sure it is not a known problem before
+reporting it. @xref{Problems}.
+
+You should include all of the following in your bug report:
+
+@itemize @bullet
+
+@item
+The version number of the program. You can get this from the top-level
+files @file{ChangeLog} or @file{GNUmakefile.in}, or from the
+@samp{-version} option which all the programs have.
+
+@item
+The type of machine you are using, and the operating system name
+and version number.
+
+@item
+A description of the bug. For example, ``The program gets a fatal
+signal,'' or ``The baselines in the generated font are too high.''
+
+@item
+All the command-line arguments you gave the program.
+
+@item
+The relevant input files. Since fonts and images are typically binary
+files, be sure to use @file{uuencode} or @file{btoa} before mailing
+them. Be sure to include the TFM file as well as the bitmap (GF or
+PK) or BZR file, if the program needs both as input.
+
+Bugs typically apply to a single character in a font; you can find out
+what character is being processed with the @samp{-verbose} option. It
+should then be straightforward to cut that single character out of the
+font with either the @samp{-range} option and/or the @samp{fontconvert}
+program, to make a new (very small) font. It is easier for us to deal
+with small files.
+
+But if you don't want to take the time to break up the font, please send
+in the bug report anyway (with the entire font). We much prefer that to
+you not reporting the bug at all!
+
+@end itemize
+
+In other words, we need enough information so that we can run the
+offending program under the debugger, so we can find out what's
+happening. Without all the command-line arguments, or the input file in
+question, we cannot do this. Since you must have found the bug by
+running the program with a particular set of options and on a particular
+input file, you already have this information; all you need to do is
+send it!
+
+
+@node Unnecessary information, Documentation bugs, Necessary information, Bug reporting
+@subsection Unnecessary information
+
+Here are some things that are not necessary to include in a bug report.
+
+@itemize @bullet
+
+@item
+@cindex envelope of bugs
+@cindex bugs, envelope of
+A description of the envelope of the bug.
+
+Often people who encounter a bug spend a lot of time investigating which
+changes to the input file or command-line options will make the bug go
+away and which changes will not affect it.
+
+This is often time consuming and not very useful, because the way we
+will find the bug is by running a single example under the debugger with
+breakpoints, not by pure deduction from a series of examples. You might
+as well save your time for something else.
+
+@item
+@cindex patches for bugs
+@cindex bugs, sending patches for
+@cindex sending patches for bugs
+A patch for the bug.
+
+A patch for the bug is useful if it is a good one. But don't omit the
+necessary information, such as the test case, on the assumption that a
+patch is all we need. We might see problems with your patch and decide
+to fix the problem another way, or we might not understand the patch at
+all. Without an example, we won't be able to verify that the bug is
+fixed.
+
+Also, if we can't understand what bug you are trying to fix, or why your
+patch should be an improvement, we won't install it. A test case will
+help us to understand.
+
+@xref{Sending Patches, , Sending Patches for GNU CC, gcc, GCC Manual},
+for more details on the best way to write changes.
+
+@item
+@cindex bugs, sending backtraces for
+@cindex backtraces, sending for bugs
+Sometimes people send just a backtrace, but that is not useful by
+itself. It is usually the values of local or global variables which
+matter, sometimes very far away from the location where you noticed the
+bug. We need to be able to run the debugger ourselves to investigate.
+
+@item
+@cindex bugs, guesses about cause
+@cindex guesses about bugs
+A guess about what the bug is or what it depends on.
+
+Such guesses are not useful, and often wrong. It is impossible to guess
+correctly without using the debugger to find the facts, so you might as
+well save your imagination for other things!
+
+@end itemize
+
+
+@node Documentation bugs, , Unnecessary information, Bug reporting
+@subsection Documentation bugs
+
+@cindex manual bugs, reporting
+@cindex documentation bugs, reporting
+
+It is just as important to report bugs in the documentation as in the
+programs. If you want to do something using these programs, and reading
+the manual doesn't tell you how, that is probably a bug. In fact, the
+best way to report it is something like: ``I want to do @var{x}; I
+looked in the manual in sections @var{a} and @var{b}, but they didn't
+explain it.''
+
+If your bug report makes it clear that you've actually made an attempt
+to find the answers using the manual, we will be much more likely to
+take action (since we won't have to search the manual ourselves).
diff --git a/doc/bzredit.texi b/doc/bzredit.texi
new file mode 100644
index 0000000..caa51b9
--- /dev/null
+++ b/doc/bzredit.texi
@@ -0,0 +1,238 @@
+@c Copyright (C) 1992 Free Software Foundation.
+@c This is part of the GNU font utilities manual.
+@c For copying conditions, see the file fontutil.texi.
+
+@node BZRedit, GSrenderfont, XBfe, Top
+@chapter BZRedit
+
+@pindex bzredit
+@cindex editing BZR fonts
+@cindex BZR fonts, editing
+@cindex editing outlines
+@cindex outline fonts, editing
+
+BZRedit allows hand-editing of outline fonts in the BZR font format
+output by Limn (@pxref{Limn}).
+
+@cindex Emacs, prerequisite for BZRedit
+@cindex Ghostscript, prerequisite for BZRedit
+It is written in GNU Emacs Lisp, and thus works only inside GNU Emacs
+(@pxref{Top, , , emacs, GNU Emacs Manual}). It uses Ghostscript to
+display the character images, and thus you must have Ghostscript
+installed to use it. @xref{Archives}, for information on how to obtain
+GNU software.
+
+BZRedit provides only a simple form of editing: you change the textual
+representation of the BZR font in an Emacs buffer; when you wish to see
+the image corresponding to the particular character you have been
+editing, you type an explicit command to tell Emacs to send the image in
+PostScript form to a Ghostscript subprocess.
+
+BZRedit uses BPL format for the ``textual representation''. @xref{BPL
+files}, for the precise details on what BPL files contain; however, you
+will probably find them fairly self-explanatory.
+
+@cindex interactive outline editing
+@cindex hints, editing
+A more featureful editor would allow interactive manipulation of the
+outlines, say via a mouse in an X window. It would also be useful to
+allow adding or editing of hints (additional commands which improve
+rasterization at low resolution and/or small sizes); right now, none of
+the programs do anything at all about hints.
+
+@menu
+* BZRedit usage:: Operating the editor.
+@end menu
+
+
+@node BZRedit usage, , , BZRedit
+@section BZRedit usage
+
+@cindex BZRedit usage
+@cindex usage of BZRedit
+
+The sections below detail using BZRedit.
+
+@menu
+* BZRedit installation:: Additional installation is needed.
+* BZR: Editing BZR files. Editing files in the binary format.
+* BPL: Editing BPL files. Editing files in the textual format.
+@end menu
+
+
+@node BZRedit installation, Editing BZR files, , BZRedit usage
+@subsection BZRedit installation
+
+@flindex bzredit.el
+@flindex default.el
+@flindex .emacs
+BZRedit is contained in the file @file{bzrto/bzredit.el}. Installation
+of the font utilities (@pxref{Installation}) copies this file into a
+directory where Emacs can find it. But you still need to tell Emacs
+what functions @file{bzredit.el} defines. To do this, put the following
+definitions into either your own @file{.emacs} file (@pxref{Init File, ,
+The Init File: @file{.emacs}, elisp, GNU Emacs Lisp Manual}), if you are
+the only person planning to use BZRedit, or into the system
+initialization file @file{default.el} (@pxref{Start-up Summary, ,
+Summary: Sequence of Actions at Start Up, elisp, GNU Emacs Lisp
+Manual}), for a public installation:
+
+@example
+(autoload 'bpl-mode "bzredit" "Mode for editing BPL files." t)
+(autoload 'bzredit "bzredit" "Set up to editing a BZR file." t)
+@end example
+
+If you want the first function to be called automatically when you visit a
+file with extension @file{.bpl}, you can add the
+following code to (presumably) the same file:
+
+@example
+(setq auto-mode-alist
+ (append auto-mode-alist (list '("\\.bpl\\'" . bpl-mode))))
+@end example
+
+@noindent If you do not do this, then to make the editing commands
+(described in the following sections) available you must type @kbd{M-x
+bpl-mode} after visiting a BPL file.
+
+
+@node Editing BZR files, Editing BPL files, BZRedit installation, BZRedit usage
+@subsection Editing BZR files
+
+@cindex editing BZR files
+@cindex BZR files, editing
+@findex bzredit
+
+To edit a BZR file, type @kbd{M-x bzredit} to Emacs. (See the previous
+section for how to make this function known to Emacs.) This will ask
+you for the filename of the BZR font. After typing the filename, type
+@kbd{RET}.
+
+The @code{bzredit} function then calls BZRto with the @samp{-text}
+option (@pxref{BZRto}) to produce a BPL file---the textual form of the
+BZR font. Then it calls @code{bpl-mode} and makes the resulting buffer
+visible (if it isn't already).
+
+The next section describes @code{bpl-mode}.
+
+
+@node Editing BPL files, , Editing BZR files, BZRedit usage
+@subsection Editing BPL files
+
+@cindex editing BPL files,
+@cindex BPL files, editing
+@findex bpl-mode
+
+To edit a BPL file in @code{bpl-mode}, the usual Emacs editing commands
+work: cursor motion, deletion, and insertion all work just as with
+normal text files.
+
+Here is an example of a piece of a BPL file. @xref{BPL files}, for a
+full description of BPL files.
+
+@example
+(char 0 ; hex 0x0
+ (width "6.263")
+ (bb "0.241" "5.782" "-0.241" "6.745")
+ (outline "0.482" "6.745"
+ (line "1.445" "6.504")
+ (line "1.445" "0.241")
+ (line "0.482" "0.241")
+ (line "3.613" "0.000")
+ (spline "1.682" "1.264" "2.409" "4.436" "2.409" "6.504")
+ @dots{}
+ )
+)
+@end example
+
+@noindent The most usual editing session is changing the numbers in the
+@code{line} and @code{spline} commands, which are the coordinates that
+determine the character outline. But you can do anything you want:
+change a @code{line} to @code{spline} (and add the requisite other
+coordinates) or vice versa, change the set width, etc.
+
+You must retain the quotation marks around the floating-point numbers,
+however. (They are necessary because Emacs 18 does not recognize
+floating-point constants.) If you inadvertently delete one, then when
+you go to display the edited character (see below), you will get an
+error from Emacs.
+
+When @code{bpl-mode} is first invoked, it starts up Ghostscript in a
+subprocess. The section below describes the details of this. It is
+Ghostscript which does the actual displaying.
+
+@code{bpl-mode} provides three additional commands (we show the default
+bindings in parentheses):
+
+@enumerate
+
+@item
+@findex bpl-quit
+@cindex quitting @code{bpl-mode}
+@cindex leaving @code{bpl-mode}
+@kindex C-c q
+@kindex C-c C-q
+@code{bpl-quit} (@kbd{C-c q} and @kbd{C-c C-q}), which kills the
+Ghostscript subprocess and then removes the BPL buffer from the screen.
+@code{bpl-quit} does not convert the BPL file (back) to BZR form; that's
+left for you to do by hand.
+
+@item
+@findex bpl-erasepage
+@findex erasepage
+@kindex C-c e
+@kindex C-c C-e
+@code{bpl-erasepage} (@kbd{C-c e} and @kbd{C-c C-e}), which sends an
+@code{erasepage} command to Ghostscript, thus erasing whatever is
+currently displayed.
+
+@item
+@findex bpl-show-char
+@cindex showing edited characters
+@cindex displaying edited characters
+@kindex C-c c
+@kindex C-c C-C
+@code{bpl-show-char} (@kbd{C-c c} and @kbd{C-c C-c}), which sends to
+Ghostscript a PostScript translation of the character that point is in.
+
+@end enumerate
+
+@findex bpl-mode-hook
+@cindex hook, for @code{bpl-mode}
+@code{bpl-mode} calls @code{bpl-mode-hook} as its last action. You can
+define this to take additional actions if you like.
+
+@menu
+* BZRedit and Ghostscript:: Customizing the use of Ghostscript.
+@end menu
+
+
+@node BZRedit and Ghostscript, , , Editing BPL files
+@subsubsection BZRedit and Ghostscript
+
+@cindex BZRedit and Ghostscript
+@cindex Ghostscript and BZRedit
+
+As mentioned above, BZRedit uses Ghostscript, the GNU PostScript
+interpreter, to display the character images. @xref{Archives}, for how
+to obtain Ghostscript.
+
+BZRedit assumes that Ghostscript's default output device is the correct
+one to use---presumably a window on an X display. The actual default
+depends on how Ghostscript was installed.
+
+The following variables control various attributes of the Ghostscript
+output:
+
+@defvar bzr-gs-width
+The width of the window, in pixels. Default is 300.
+@end defvar
+
+@defvar bzr-gs-height
+The height of the window, in pixels. Default is 300.
+@end defvar
+
+@defvar bzr-gs-dpi
+The resolution at which Ghostscript renders images, in pixels per inch.
+Default is 300.
+@end defvar
diff --git a/doc/bzrto.texi b/doc/bzrto.texi
new file mode 100644
index 0000000..5895ff6
--- /dev/null
+++ b/doc/bzrto.texi
@@ -0,0 +1,1008 @@
+@c Copyright (C) 1992 Free Software Foundation.
+@c This is part of the GNU font utilities manual.
+@c For copying conditions, see the file fontutil.texi.
+
+@node BZRto, BPLtoBZR, Limn, Top
+@chapter BZRto
+
+@pindex bzrto
+@cindex outline conversion
+
+BZRto translates an outline font that's in our home-grown BZR outline
+font format (described below) to some other form: Metafont, Type 1
+PostScript, Type 3 PostScript, or BPL.
+
+BPL format is simply a human-readable form of BZR files. @xref{BPL
+files}. We discuss the other output forms below.
+
+Besides straight format conversion, BZRto can also:
+
+@itemize @bullet
+@item
+merge fonts, possibly of different sizes (see the @samp{-concat} option
+in @ref{Invoking BZRto});
+
+@item
+slant fonts, so the oblique version of a font can be made without
+respecifying the character shapes (see the @samp{-oblique-angle}
+option);
+
+@item
+create new characters by combining existing ones, via a fairly general
+command language (@pxref{CCC files}).
+
+@end itemize
+
+@menu
+* Metafont and BZRto:: Output as a Metafont program.
+* Type 1 and BZRto:: Output as a Type 1 PostScript font.
+* Type 3 and BZRto:: Output as a Type 3 PostScript font.
+* CCC files:: Creating additional characters.
+* Invoking BZRto:: Command-line options.
+* BZR files:: The technical definition of BZR format.
+@end menu
+
+
+@node Metafont and BZRto, Type 1 and BZRto, , BZRto
+@section Metafont and BZRto
+
+@cindex Metafont output from BZR files
+@cindex converting from BZR to Metafont
+@cindex BZR files, converting to Metafont
+
+@cindex Knuth, Donald E.
+Metafont is a language for specifying graphic shapes, particularly
+characters in a font of a type, as well as the name of the program which
+interprets the language. It is commonly used to generate fonts for
+@TeX{} and related software (@TeX{} and Metafont were developed
+more-or-less simultaneously by Donald Knuth during the years
+1977--1985). @xref{Archives}, for how to obtain the Metafont program.
+
+@opindex -metafont
+BZRto generates a Metafont font @file{@var{foo}.mf} from the input file
+@file{@var{foo}10.bzr} (the @samp{10} being the design size of the
+input) if you specify the @samp{-metafont} option, as in:
+
+@example
+bzrto -metafont @var{foo}
+@end example
+
+Presuming Metafont has been installed properly at your site, you can
+then make both a TFM and a GF file for @var{foo} at a size of 10@dmn{pt}
+and rasterized for your most common output device with the command:
+
+@cindex GF file, generating with Metafont
+@example
+mf '\mode:=localfont; input @var{foo}'
+@end example
+
+@noindent (The single quotes are not seen by Metafont; they just protect
+the backslash and semicolon from interpretation by your shell.)
+
+@vindex localfont @r{Metafont mode}
+@cindex Metafont mode
+@cindex modes in Metafont
+The assignment to @code{mode} tells Metafont the name of your output
+device. @code{localfont} should be a synonym for some real output
+device, defined when Metafont was installed. The GF file will be named
+@file{@var{foo}.@var{dpi}gf}, where @var{dpi} is the resolution of the
+@code{localfont} device.
+
+Given the TFM and GF file, you can now use the font in @TeX{}.
+
+@menu
+* Metafont output at any size:: Making larger or smaller fonts.
+* Proofing with Metafont:: Metafont can help with debugging fonts.
+@end menu
+
+
+@node Metafont output at any size, Proofing with Metafont, , Metafont and BZRto
+@subsection Metafont output at any size
+
+@cindex Metafont output, at different sizes
+
+@vindex designsize @r{Metafont parameter}
+@cindex point size, specifying to Metafont
+We described above how to get Metafont output at a size of 10@dmn{pt}.
+To generate a GF file for a font @var{foo} at a different size, assign
+to @code{designsize} on the command line, as follows:
+
+@example
+mf '\mode:=localfont; designsize:=@var{integer}; input @var{foo}
+@end example
+
+@noindent
+For example, if @code{localfont} corresponds to a 300@dmn{dpi}
+device, and you specify @samp{designsize:=6}, this command creates
+@file{@var{foo}.180gf}, i.e., a 40% reduction from
+@file{@var{foo}.300gf}.
+
+@cindex magnification
+@findex \magnification
+In some cases, it may be more convenient to specify a magnification
+factor than a new point size. (For example, this is the case if you are
+enlarging or reducing an entire document by some constant factor, as
+with @TeX{}'s @code{\magnification} command.) You can do this by
+assigning to @code{mag}:
+
+@example
+mf '\mode:=localfont; mag:=@var{real}; input @var{foo}
+@end example
+
+@noindent
+By default, @code{mag} is 1.0. You can also assign to both @code{mag}
+and @code{designsize}. For example, if you set @code{designsize} to 5
+and @code{mag} to 4, the output will be a 20@dmn{pt} font.
+
+@cindex nonlinear scaling
+@cindex scaling of Metafont fonts
+@cindex anamorphic scaling
+Although the Metafont language allows nonlinear scaling of fonts, so
+that the 6@dmn{pt} font would not simply be a reduced version of the
+10@dmn{pt} font, BZRto cannot take advantage of this sophistication.
+The reason is that BZR files specify a single set of outlines, and the
+nonlinear scaling cannot be deduced from that. Perhaps we will extend
+the programs someday to handle interpolation between outlines of
+different sizes.
+
+
+@node Proofing with Metafont, , Metafont output at any size, Metafont and BZRto
+@subsection Proofing with Metafont
+
+@cindex proofing fonts
+@cindex fonts, proofing
+@cindex debugging fonts
+@cindex blowing up fonts
+
+@pindex gftodvi
+While creating fonts, it is useful to enlarge the character shapes
+enough to be able to make out small details. This blowing-up process is
+called @dfn{proofing}. Metafont works together with GFtoDVI, another
+program created as part of the @TeX{} project, to do this.
+
+@cindex gray proofs
+@cindex smoke proofs
+You can make two kinds of proofs with Metafont: @dfn{gray proofs} and
+@dfn{smoke proofs}. Metafont calls the former @code{proof} mode, and
+the latter @code{smoke} mode. @code{proof} mode is the default, so if
+you do not assign to @code{mode} at all, you get gray proofs. To get
+smoke proofs for a font @var{foo}, you run Metafont as follows:
+
+@example
+mf '\mode:=smoke; input @var{foo}'
+@end example
+
+@findex nodisplays
+@noindent (See the preceding sections for general information on running
+Metafont.) In @code{proof} or @code{smoke} mode, by default Metafont
+will display the characters online as it runs (if you are on a terminal
+capable of this, e.g., running under X). If you aren't interested in
+seeing this online output, you can say @samp{nodisplays;} on the command
+line.
+
+@vindex designsize @r{and proofing}
+@cindex proof_size
+In both kinds of proofs, the font is produced at a very high resolution,
+typically thousands of pixels per inch, to minimize (or eliminate)
+distortion due to rasterization difficulties. To be more precise, the
+resolution is chosen so that the @code{designsize} of the font fills
+@code{proof_size} inches; by default, @code{proof_size} is 7, which
+works well enough for both letter-size and A4 paper.
+
+@vindex proof_resolution
+In order to calculate this, Metafont must also know the resolution of
+the final output device. This is called @code{proof_resolution}, and is
+300 by default.
+
+@flindex bzrsetup.mf@r{, computing proof values}
+You can change the values of @code{proof_size} and
+@code{proof_resolution} on the command line; the actual calculation is
+done in @file{bzrsetup.mf}.
+
+After running Metafont, you will have a GF file, e.g.,
+@file{@var{foo}.2602gf}. You can then make a DVI file you can preview
+or print with:
+@example
+gftodvi @var{foo}.2602gf
+@end example
+@noindent This creates @file{@var{foo}.dvi}. In the DVI output from
+GFtoDVI, each character in the font has its own page. Some additional
+information is also present, as follows:
+
+@cindex gray fonts
+@cindex control points of splines, seeing
+@cindex endpoints of splines, seeings
+In @code{proof} mode, the character shapes are printed in a ``gray''
+font, and the starting and ending points of each spline (or line) in the
+character outline are shown. (Thus, you can see if Limn did a good job
+choosing those points.) If you set @math{@code{proofing} > 2}, the
+control points for each spline will also be shown. If a point would
+otherwise overlap with others on the output, an equation is put off to
+the right defining where it appears.
+
+@cindex Wall, The
+In @code{smoke} mode, the character shapes are printed in black; if you
+put the output on the wall and stand back, you can get an idea of how
+the font is coming along. The character is also shown at its true size
+off to the right (assuming you have made the font at the true-size
+resolution, of course).
+
+@opindex -overflow-label-offset
+@cindex losing proof information
+@cindex proof information, losing
+@cindex overflow equations, losing
+You may find that the extra information to the right of the character
+(``overflow equations'' in @code{proof} mode; the true-size character in
+@code{smoke} mode) is being lost off the edge of the page. You can
+change where GFtoDVI puts this with the @samp{-overflow-label-offset}
+option to GFtoDVI.
+
+See the @cite{Metafontbook} and the GFtoDVI documentation for more
+details.
+
+
+@node Type 1 and BZRto, Type 3 and BZRto, Metafont and BZRto, BZRto
+@section Type 1 PostScript fonts and BZRto
+
+@cindex Type 1 output from BZR files
+@cindex PostScript Type 1 output from BZR files
+@cindex converting from BZR to Type 1
+@cindex BZR files, converting to Type 1
+
+The Type 1 font format, invented by Adobe Systems, Inc., is the most
+common representation for PostScript fonts. Adobe first published its
+specification in the book @cite{Adobe Type 1 Font Format} in 1990. It
+defines a limited set of operations; general PostScript programs cannot
+be represented as Type 1 fonts. It also defines hints---ways of
+improving characters' appearances at low resolution and/or small
+sizes---which cannot be represented in PostScript proper.
+
+@opindex -pstype1
+BZRto generates a Type 1 font @file{@var{foo}.gsf} from the input file
+@file{@var{foo}10.bzr} (the @samp{10} being the design size of the
+input) if you specify the @samp{-pstype1} option, as in:
+
+@example
+bzrto -pstype1 @var{foo}
+@end example
+
+The file @file{@var{foo}.gsf} consists only of plain text (it's not
+really ``human-readable'', since Type 1 format requires encryption
+of the character outlines).
+
+@cindex encryption of Type 1 fonts
+@cindex Type 1 fonts, encryption of
+@cindex unencrypted Type 1 fonts
+Although Type 1 format also allows for encryption of the entire font,
+this is not required, and BZRto does not do it. Some deficient
+PostScript interpreters do not recognize unencrypted fonts; but
+Ghostscript, the GNU quasi-PostScript interpreter, has no trouble. We
+do not know of any utilities for encrypting an unencrypted Type 1 font,
+but presumably such a program would not be hard to write.
+
+
+@node Type 3 and BZRto, CCC files, Type 1 and BZRto, BZRto
+@section Type 3 PostScript fonts and BZRto
+
+@cindex Type 3 output from BZR files
+@cindex PostScript Type 3 output from BZR files
+@cindex converting from BZR to Type 3
+@cindex BZR files, converting to Type 3
+
+Type 3 PostScript fonts are not defined in a singular format, as are
+Type 1 fonts (see the previous section). Rather, they are general
+PostScript programs which happen to meet the PostScript language's
+(liberal) requirements for being a font. They can therefore be used
+with any PostScript interpreter.
+
+@opindex -pstype3
+BZRto generates a Type 3 font @file{@var{foo}.pf3} from an input BZR
+file @file{@var{foo}.bzr} if you specify the @samp{-pstype3} option, as
+in:
+
+@example
+bzrto -pstype3 @var{foo}
+@end example
+
+@cindex PF3 abbreviation
+We do not know of any conventional extension for Type 3 fonts; we made
+up @file{pf3} to stand for ``PostScript font Type 3''.
+
+@findex BuildChar @r{in Type 3 fonts}
+The most important part of a Type 3 font is the @code{BuildChar}
+routine, which does the actual rendering from the character program.
+Unlike Type 1 fonts, whose @code{BuildChar} routine is built into the
+PostScript interpreter, each Type 3 font supplies its own
+@code{BuildChar} routine.
+
+@flindex bzrbuildch.PS
+@findex run @r{PostScript command}
+The Type 3 fonts output by BZRto use a @code{BuildChar} routine defined
+in a separate file @file{bzrbuildch.PS} (distributed in the @file{bzr}
+directory). They use the PostScript @code{run} command to read that
+file; so if you want to download one to a printer (which naturally will
+not have access to the file on your computer), you must replace the
+@code{run} command with the contents of the file. For PostScript
+interpreters which run on a host computer, such as Ghostscript, you have
+to install @file{bzrbuildch.PS} in a directory where it will be found,
+but you need not modify the fonts.
+
+
+@node CCC files, Invoking BZRto, Type 3 and BZRto, BZRto
+@section CCC files
+
+@cindex CCC files
+
+@cindex pre-accented characters
+@cindex accented characters
+@cindex piece accents
+@cindex characters, accented
+The CCC (composite character construction) language allows you to define
+new characters in terms of existing ones. This is useful for building
+such characters as pre-accented A's (from a piece accent and an `A').
+
+A CCC file consists of a sequence of character definitions, each of
+which looks like:
+
+@example
+define @var{name} = @var{statements} end
+@end example
+
+@noindent
+where @var{name} is a character name, presumably from the encoding file
+specified with the @samp{-encoding} option (@pxref{Invoking BZRto}).
+@xref{Character names}, for the details of character names.
+
+We describe the possible @var{statements} below.
+
+You may also include comments starting with a @samp{%} character and
+continuing to the end of the line.
+
+@menu
+* setchar: CCC setchar. Statements for including a character.
+* move: CCC move. Statements for moving to a new position.
+@end menu
+
+
+@node CCC setchar, CCC move, , CCC files
+@subsection CCC @code{setchar} statements
+
+@cmindex setchar @r{CCC commands}
+@cmindex setcharbb @r{CCC commands}
+To use an existing character as part of a new character, you can use
+either the @code{setchar} or @code{setcharbb} statement. They both take
+a character name in parentheses as their argument, as in:
+
+@example
+setchar ( @var{name} )
+setcharbb ( @var{name} )
+@end example
+
+@xref{Character names}, for the details of character names.
+
+@cindex side bearings in CCC files
+The difference between the two commands lies in their treatment of the
+existing character's sidebearings: the @code{setchar} command includes
+them, and @code{setcharbb} does not. @code{setcharbb} also removes
+any white space above and below the character shapes, as is usually
+present in accent characters.
+
+This difference lets you construct characters without worrying about
+interaction between their side bearings. For example, you could make an
+`A' with an acute accent centered over the body of the `A' as follows:
+
+@vindex Aacute @r{character, constructing}
+@example
+define Aacute =
+ setchar (A)
+ hmove -.5 width (A)
+ vmove height (A)
+ setcharbb (acute)
+end
+@end example
+
+@noindent
+(See the next section for a description of the @code{hmove} and
+@code{vmove} commands.) Without the @code{setcharbb} command, this
+definition would be complicated by the side bearings on the @code{acute}
+character.
+
+
+@node CCC move, , CCC setchar, CCC files
+@subsection CCC @code{move} statements
+
+@cindex moves in CCC files
+
+To change the current position in a CCC file, you can use the
+@code{hmove} or @code{vmove} command; as you might expect, the former
+moves horizontally and the latter vertically.
+
+@cindex dimensions in CCC files
+Both take a single argument: a @dfn{dimension}, which is an optional
+real number followed by a unit of measure. The real number is a
+multiplying factor. For example, one of the units is @code{pt}
+(signifying printer's points, as usual), so the command @samp{hmove 3pt}
+moves three points to the right (a pretty small distance).
+
+Here are the possible units of measure:
+
+@table @samp
+
+@item bbheight ( @var{name} )
+@vindex bbheight @r{CCC dimension}
+The height exclusive of blank space above or below the shape of the
+character @var{name} if it exists.
+
+@item bbwidth ( @var{name} )
+@vindex bbwidth @r{CCC dimension}
+The width exclusive of side bearings of the character @var{name} if it
+exists.
+
+@item capheight
+@vindex capheight @r{CCC dimension}
+The height of the capital letters, e.g., @samp{H}. See @samp{xheight}
+for how this is determined.
+
+@item depth ( @var{name} )
+@vindex depth @r{CCC dimension}
+The depth of the character @var{name}.
+
+@item designsize
+@vindex designsize @r{CCC dimension}
+The design size of the main input BZR font.
+
+@item em
+@vindex em @r{CCC dimension}
+The quad width of the font. This value is determined analogously to
+@samp{xheight}, below.
+
+@item fontdepth
+@vindex fontdepth @r{CCC dimension}
+The maximum depth any character in the font descends below the baseline.
+Again, this is determined analogously to @samp{xheight}.
+
+@item height ( @var{name} )
+@vindex height @r{CCC dimension}
+The height of the character @var{name}.
+
+@item pt
+@vindex pt @r{CCC dimension}
+Printer's points; 72.27@dmn{pt} = 1@dmn{in}. Since dimensions specified
+in points are absolute distances, they do not scale when the font size
+changes.
+
+@item width ( @var{name} )
+@vindex width @r{CCC dimension}
+The set width of the character @var{name}.
+
+@item xheight
+@vindex xheight @r{CCC dimension}
+The x-height of the main input font. If a TFM file corresponding to the
+main BZR file exists and defines this, that value is used; otherwise, the
+height of a suitable character (e.g., @samp{x}) is used if one exists;
+otherwise, it's zero. BZRto treats the other font-related units of
+measure in the same way.
+
+@end table
+
+If the character @var{name} does not exist, an error is given, and the
+command ignored.
+
+
+@node Invoking BZRto, BZR files, CCC files, BZRto
+@section Invoking BZRto
+
+@cindex BZRto options
+@cindex Invoking BZRto
+@cindex options, for BZRto
+
+This section describes the options that BZRto accepts.
+@xref{Command-line options}, for general option syntax.
+
+The root of the main input fontname is called @var{font-name} below.
+
+@table @samp
+
+@item -concat @var{bzr-name1}, @var{bzr-name2}, @dots{}
+@opindex -concat
+@cindex concatenating outline fonts
+@cindex merging outline fonts
+@cindex outline fonts, concatenating
+@cindex font concatenation
+Concatenate the main input file with the given @var{bzr-name}s; if a
+character code exists in more than one of the BZR files, it's the first
+occurrence that counts. The BZR files can have any design size; the
+output is normalized to the size of the main input file.
+
+@item -ccc-file @var{filename}
+@opindex -ccc-file
+Read the CCC file @var{filename} (if @var{filename} has a suffix) or
+@file{@var{filename}.ccc} (if it doesn't). Default is to use
+@var{font-name} for @var{filename}, but if BZRto does not find
+the file @file{@var{font-name}.ccc}, it does not complain.
+
+@item -encoding @var{filename}
+@opindex -encoding
+@cindex encoding of input fonts
+Specify the encoding file for the input font, so character names in the
+CCC files can be matched to character codes. If @var{filename} has no
+suffix, use @file{@var{filename}.enc}, otherwise just @var{filename}.
+The default is to guess the encoding from the @samp{codingscheme} string
+in a TFM file corresponding to the main input file, if such exists.
+
+@item -help
+@opindex -help
+Print a usage message. @xref{Common options}.
+
+@item -metafont
+@opindex -metafont
+Translate the input to a Metafont program; write to
+@file{@var{font-name}.mf}. @xref{Metafont and BZRto}.
+
+@item -mf
+@opindex -mf
+Synonym for @samp{-metafont}.
+
+@item -oblique-angle @var{angle-in-degrees}
+@opindex -oblique-angle
+@cindex slanted fonts, making
+@cindex oblique fonts, making
+Angle in degrees from the vertical by which to slant the shapes; default
+is zero.
+
+@item -output-file @var{filename}
+@opindex -output-file
+Output to @var{filename} (if it has a suffix) or to
+@file{@var{filename}.@var{font-format}} (if it doesn't), where
+@var{font-format} is @file{mf}, @file{gsf}, etc. If you give more than
+one of the output format options (i.e., @samp{metafont}, @samp{pstype1} and
+@samp{pstype3}), @var{filename} cannot have a suffix. The default is
+@var{font-name} with a trailing number removed, so that, for example, an
+input filename of @file{cmr10} becomes @file{cmr}.
+
+@item -ps-font-info @var{name1}:@var{value1},@dots{}
+@opindex -ps-font-info
+@vindex FontInfo
+Assign each @var{value} to the corresponding @var{name} when outputting
+a PostScript font (either Type 1 or Type 3). Case is significant in
+both the @var{name}s and @var{value}s. You can specify the following:
+
+@table @samp
+
+@item FontName:@var{string}
+@vindex FontName @r{in PostScript fonts}
+@vindex unknown @r{font name}
+The full PostScript name of the font; e.g., @code{Times-BoldItalic}.
+The default is @code{unknown}.
+
+@item FamilyName:@var{string}
+@vindex FamilyName @r{in PostScript fonts}
+The name of the typeface family to which this font belongs; e.g.,
+@code{Times}. The default is to use @code{FontName} up to the first
+@samp{-}.
+
+@item Weight:@var{string}
+@vindex Weight @r{in PostScript fonts}
+The typographic weight of the font, e.g., @code{Bold}. If
+@code{FontName} contains one of the strings @samp{Black}, @samp{Book},
+@samp{Bold}, @samp{Demi}, @samp{ExtraBold}, @samp{Light}, @samp{Heavy},
+@samp{Regular}, @samp{Semibold}, or @samp{Ultra}, that is the
+weight. Otherwise, BZRto uses @samp{Medium}.
+
+@item ItalicAngle:@var{real}
+@vindex ItalicAngle @r{in PostScript fonts}
+The angle in degrees by which the font slopes to the right from the
+vertical. Default is zero. Typical slanted or italic fonts have values
+between 10--20.
+
+@item isFixedPitch:@code{true} @r{or} @code{false}
+@vindex isFixedPitch @r{in PostScript fonts}
+@cindex monospaced PostScript fonts
+Whether or not this font is monospaced. If a TFM file corresponding to
+the main BZR file exists, and specifies a zero interword stretch and
+shrink, and a nonzero interword space, the default is @code{true}.
+Otherwise, it's @code{false}.
+
+@item UnderlinePosition:@var{real}
+@vindex UnderlinePosition @r{in PostScript fonts}
+Distance from the baseline for positioning underlines, in units of the
+character coordinate system. Default is @math{-100}.
+
+@item UnderlineThickness:@var{real}
+@vindex UnderlineThickness @r{in PostScript fonts}
+Thickness of underlines. Default is 50.
+
+@item UniqueID:@var{non-negative integer}
+@vindex UniqueID @r{in PostScript fonts}
+An integer in the range 0 to 16777215 (2^24 - 1) uniquely identifying
+this font. The default is zero, meaning (for our purposes) not to
+output any @code{UniqueID}. This avoids unlikely-but-possible conflicts
+with existing fonts.
+
+@item version:@var{string}
+@vindex version @r{in PostScript fonts}
+Identification for the particular version of this font. If a TFM file
+corresponding to the main BZR file exists, and specifies a version
+number, that is the default; otherwise, there is none.
+
+@end table
+
+@noindent All values except @code{FontName} and @code{UniqueID} go in
+the @code{FontInfo} dictionary.
+
+@item -pstype1
+@opindex -pstype1
+Translate the input to (unencrypted) PostScript Type 1 font format;
+write to @file{@var{font-name}.gsf}. @xref{Type 1 and BZRto}.
+
+@item -pstype3
+@opindex -pstype3
+Translate the input to PostScript Type 3 font format; write to
+@file{@var{font-name}.pf3}. @xref{Type 3 and BZRto}.
+
+@item -range @var{char1}-@var{char2}
+@opindex -range
+Only process characters between the character codes @var{char1} and
+@var{char2}, inclusive.
+
+@item -text
+@opindex -text
+Translate the font to a BPL file, i.e., human-readable text; write to
+standard output. @xref{BPL files}.
+
+@item -verbose
+@opindex -verbose
+Output progress reports to standard output, unless @samp{-text} is
+specified, in which case output to standard error.
+
+@item -version
+@opindex -version
+Print the version number.
+
+@end table
+
+
+@node BZR files, , Invoking BZRto, BZRto
+@section BZR files
+
+@cindex BZR file format, definition of
+
+@flindex bzr @r{source directory}
+This section describes the technical definition of the BZR file format. It
+is intended for programmers who wish to write other programs which read
+or write such files. The present distribution includes a subroutine
+library which can be shared among programs (Limn, BPLtoBZR, and BZRto
+all use it); new programs can and probably should use the existing
+library as well. The source code is in the @file{bzr} directory.
+
+The BZR file format shares the philosophy of the @TeX{} project file
+formats (DVI, GF, PK, etc.): machine-independence; compactness; and
+easy interpretation.
+
+BZR files have three parts: a preamble, character definitions, and a
+postamble. We describe each below, as well as some general
+considerations.
+
+@menu
+* Intro: BZR format introduction. General concepts and definitions.
+* Preamble: BZR preamble. The beginning.
+* Chars: BZR characters. The middle.
+* Postamble: BZR postamble. The end.
+@end menu
+
+
+@node BZR format introduction, BZR preamble, , BZR files
+@subsection BZR format introduction
+
+This section describes some general conventions of the BZR format.
+
+@cindex opcodes in BZR files
+@flindex bzr_opcodes.h
+@cindex notation, for BZR format
+In the following sections, we use the notation @var{name}[@var{n}] to
+mean that some constituent @var{name} of the BZR file takes up @var{n}
+bytes. If @var{name} is all capital letters, it is an opcode, i.e., a
+command byte, and therefore we give no [@var{n}] after @var{name}, since
+all opcodes are a single byte. The numerical value of each opcode is
+given in the source file @file{bzr/bzr_opcodes.h}.
+
+@cindex pointers in BZR files
+Some values in BZR files are ``pointers''. These values give the
+location of some other byte in the file. The first byte is numbered
+0, the next byte numbered 1, and so on.
+
+@cmindex NO_OP @r{opcode in BZR files}
+Besides commands which actually define the font, the BZR format has a
+@code{NO_OP} command, which does nothing. Any number of @code{NO_OP}'s
+can occur between the preamble and the character definitions, between
+character definitions and commands within characters, between the
+character definitions and the postamble, and after the postamble. But
+they may not occur within the preamble, the postamble, or between a
+command and its parameters.
+
+@cindex types in BZR format
+@cindex designsize-scaled numbers in BZR files
+Besides simple integers, BZR format uses a fixed-point representation of
+real numbers called a @dfn{scaled}, which is three bytes: two bytes of
+fraction and one byte of integer. We can get away with such a small
+range because almost all numbers are scaled by the design size; i.e., in
+a 10-point font, a designsize-scaled value of 1.0 would represent 10
+points (quite a large distance, relatively speaking).
+
+In fact, designsize-scaled numbers are typically less than 1.0, so the
+BZR format provides for abbreviating such, thus making the font smaller,
+as detailed in the following sections.
+
+@cindex two's complement in BZR files
+@cindex negative numbers in BZR files
+@cindex multibyte values in BZR files
+@cindex BigEndian order in BZR files
+@cindex portability of BZR files
+Negative numbers are represented in 2's complement notation, and
+multibyte values are stored in BigEndian order, regardless of the
+conventions of the host computer. This makes a BZR font file
+portable between different architectures.
+
+
+@node BZR preamble, BZR characters, BZR format introduction, BZR files
+@subsection BZR preamble
+
+@cindex BZR preamble
+@cindex preamble in BZR files
+
+The preamble of a BZR file has two components, the font's design size
+and a comment: @code{designsize}[3], @code{k}[1],
+@code{comment}[@code{k}].
+
+@xref{BZR format introduction}, for general information about BZR files
+and for the definition of the types used here.
+
+@cindex designsize in BZR files
+The @code{designsize} is a @code{scaled} number in printer's points.
+
+@cindex comment in BZR files
+@cindex identification in BZR files
+@cindex date of creation in BZR files
+The @var{k}-byte long @code{comment} typically identifies the
+source and creation date of the BZR file.
+
+
+@node BZR characters, BZR postamble, BZR preamble, BZR files
+@subsection BZR characters
+
+@cindex character definitions in BZR files
+
+@cmindex EOC @r{opcode in BZR files}
+BZR characters consist of an identifying command, metric
+information, shape information, and a terminating @code{EOC} command.
+
+We describe these parts below.
+
+@menu
+* BOC: BZR character beginnings. Giving character metrics.
+* Shape: BZR character shapes. Defining the outline(s).
+@end menu
+
+
+@node BZR character beginnings, BZR character shapes, , BZR characters
+@subsubsection BZR character beginnings
+
+@cindex BZR character beginning
+@cindex beginning of characters in BZR files
+
+BZR format provides two ways to start characters: an abbreviated one,
+which saves space in common cases, and a longer form which (we hope)
+will always suffice.
+
+The short form looks like this:
+
+@display
+@code{BOC_ABBREV} @cmindex BOC_ABBREV
+@code{charcode}[1]
+@code{set-width}[2]
+@code{llx}[2] @code{lly}[2] @code{urx}[2] @code{ury}[2]
+@end display
+
+The long form:
+
+@display
+@code{BOC} @cmindex BOC
+@code{charcode}[1]
+@code{set-width}[3]
+@code{llx}[3] @code{lly}[3] @code{urx}[3] @code{ury}[3]
+@end display
+
+Here is a description of these components:
+
+@itemize @bullet
+
+@item
+The @code{BOC} or @code{BOC_ABBREV} opcode byte introduces the character.
+
+@cindex character code in BZR files
+@item
+@code{charcode} defines the character code in question.
+
+@cindex set width in BZR files
+@item
+@code{set-width} defines the set width of the character, given as a
+design-size scaled, in printer's points.
+
+@item
+@code{llx} @dots{} @code{ury} (which stand for ``lower left @math{x}'',
+``lower left @math{y}'', ``upper right @math{x}'', and ``upper right
+@math{y}'') define the bounding box for this character. The values are
+designsize-scaled, in printer's points. The bounding box is not
+guaranteed to be the tightest possible, because it is difficult to
+compute the exact path of any splines in the character shape (@pxref{BZR
+character shapes}).
+
+@end itemize
+
+As with other formats, the left side bearing is defined by @code{llx},
+and the right side bearing by @code{set-width} @minus{} @code{urx}.
+
+@xref{BZR format introduction}, for general information about BZR files
+and for the definition of the types used here.
+
+
+@node BZR character shapes, , BZR character beginnings, BZR characters
+@subsubsection BZR character shapes
+
+@cindex BZR character shapes
+@cindex character shapes in BZR files
+@cindex shapes of characters in BZR files
+@cindex outlines of characters in BZR files
+
+In the BZR format, a character shape is defined as a sequence of
+(non-contiguous) closed paths, i.e., outlines. Each path can contain
+straight lines and Bezier cubic splines. As a BZR-reading program
+interprets the character definition, it keeps track of a ``current
+point'', which is initially undefined.
+
+@cmindex PATH @r{opcode in BZR files}
+@cindex path command in BZR files
+Each path---and therefore also the character shape itself---starts with a
+path command: @code{PATH}, @code{x}[3], @code{y}[3]. This
+finishes off any previous outline and starts a new one, setting the
+current point to @code{(x,y)}. @code{x} and @code{y} are
+designsize-scaled values in printer's points.
+
+After a path command has started an outline, a sequence of zero or more
+line and/or spline commands, intermixed in any order, follows. (A path
+command followed by another path command is allowed, but does nothing
+useful.)
+
+@cindex outside curves
+@cindex inside curves
+@cindex counterclockwise drawing of curves
+@cindex clockwise drawing of curves
+Although the BZR format itself does not require it, for the font to work
+properly when translated to some other formats, the ``outside curves''
+must be drawn counterclockwise, and the inside ones clockwise.
+
+The BZR format defines both abbreviated and long versions of both straight
+line and spline commands, as follows.
+
+@cindex straight lines in BZR files
+The abbreviated line command is:
+
+@display
+@code{LINE_ABBREV} @cmindex LINE_ABBREV @r{opcode in BZR files}
+@code{ex}[2]
+@code{ey}[2]
+@end display
+
+@noindent which defines a straight line from the current point to
+@code{(ex,ey)}. @code{ex} and @code{ey} are designsize-scaled numbers
+in points. After drawing the line, the current point is set to
+@code{(ex,ey)}.
+
+@cmindex LINE @r{opcode in BZR files}
+The long form of the line command differs only in starting with a
+@code{LINE} opcode, and the coordinate parameters being three bytes long,
+instead of two.
+
+@cindex splines in BZR files
+The spline commands are analogous. Here is the abbreviated form:
+
+@display
+@code{SPLINE_ABBREV} @cmindex SPLINE_ABBREV @r{opcode in BZR files}
+@code{c1x}[2] @code{c1y}[2]
+@code{c2x}[2] @code{c2y}[2]
+@code{ex}[2] @code{ey}[2]
+@end display
+
+@noindent This defines a Bezier spline with initial point the
+current point, control points @code{(c1x,c1y)} and @code{(c2x,c2y)}, and
+ending point @code{(ex,ey)}. The current point is then set to
+@code{(ex,ey)}. As with the line commands, the coordinate parameters
+are designsize-scaled in units of points.
+
+@cmindex SPLINE @r{opcode in BZR files}
+Also as with the line commands, the long form of the spline command
+differs only in starting with a @code{SPLINE} opcode and the other
+parameters being three bytes long instead of two.
+
+
+@node BZR postamble, , BZR characters, BZR files
+@subsection BZR postamble
+
+@cindex BZR postamble
+@cindex postamble in BZR files
+
+The postamble of a BZR file consists of the following. @xref{BZR format
+introduction}, for general information about BZR files and for the
+definition of the types used here.
+
+@display
+@code{POST} @cmindex POST @r{opcode in BZR files}
+@code{llx}[3] @code{lly}[3] @code{urx}[3] @code{ury}[3]
+character locators (see below)
+@code{POST_POST} @cmindex POST_POST @r{opcode in BZR files}
+@code{nchars}[1]
+@code{post-ptr}[4]
+@code{id}[1]
+1 to any number of @code{NO_OP}'s
+@end display
+@cmindex NO_OP @r{opcode in BZR files}
+
+Here is a description of these components:
+
+@itemize @bullet
+
+@cindex font bounding box in BZR files
+@cindex bounding box of font in BZR files
+@item
+@code{llx} @dots{} @code{ury} are all designsize-scaled
+numbers. They define the bounding box for the entire font, which is
+simply the smallest box that encloses all the characters. @xref{BZR
+character beginnings}.
+
+@cindex character locators in BZR files
+@item
+A character locators provides a pointer to the first byte of the
+corresponding character description, i.e., its @code{BOC}. There are
+two forms of character locators: one abbreviates the common case of the
+pointer being less than 65536; the other allows for a full four-byte
+pointer value.
+
+@cmindex CHAR_LOC_ABBREV @r{opcode in BZR files}
+More precisely, an abbreviated character locator consists of:
+
+@example
+CHAR_LOC_ABBREV charcode@r{[1]} pointer@r{[2]}
+@end example
+
+@cmindex CHAR_LOC @r{opcode in BZR files}
+@noindent and a long character locator consists of:
+
+@display
+@code{CHAR_LOC} @code{charcode}[1] @code{pointer}[4]
+@end display
+
+@cindex number of characters in BZR files
+@cindex character count in BZR files
+@item
+@code{nchars} is the number of characters defined in the BZR file.
+
+@cindex postamble pointer in BZR files
+@item
+@code{post-ptr} points to the @code{POST} byte.
+
+@cindex identification of BZR format
+@cindex BZR format, identification
+@item
+@code{id} identifies the version of BZR format; this is currently 75.
+
+@end itemize
+
+@cindex BZR files, algorithm for reading
+This way of ending BZR files makes it straightforward to process a BZR
+file from end to beginning, even though it must of course be written
+beginning to end. The BZR-reading program can position itself at the
+end of the file, skip over the @code{NO_OP} bytes at the end to the
+@code{id} byte, and then read the pointer to the postamble proper, which
+provides enough information to read each character individually. This
+eliminates the need to read the entire (potentially large) BZR file into
+memory before doing any processing.
diff --git a/doc/charspace.texi b/doc/charspace.texi
new file mode 100644
index 0000000..fe85de9
--- /dev/null
+++ b/doc/charspace.texi
@@ -0,0 +1,852 @@
+@c Copyright (C) 1992 Free Software Foundation.
+@c This is part of the GNU font utilities manual.
+@c For copying conditions, see the file fontutil.texi.
+
+@node Charspace, Limn, Fontconvert, Top
+@chapter Charspace
+
+@pindex charspace
+@cindex side bearings, adding
+@cindex spacing, character
+@cindex character spacing
+
+Charspace lets you add @dfn{side bearings} (the blank spaces on either
+side of a character) to a bitmap font. This is necessary because
+scanned images typically do not include side bearing information, and
+therefore Imageto (@pxref{Imageto}) cannot determine it.
+
+The input is a bitmap (GF or PK) font, together with one or more CMI
+files (@pxref{CMI files}), which specify character metric information. If a
+corresponding TFM file exists, it is read to get default values for the
+character dimensions (Charspace promptly overwrites the widths). The
+output is a TFM file and (typically) a revised GF file with the new
+width information.
+
+@cindex Smith, Harry
+@cindex Tracy, Walter
+@cindex Letters of Credit
+The basic idea for Charspace came from Harry Smith, via Walter Tracy's
+book @cite{Letters of Credit}. See @file{charspace/README} for the full
+citation.
+
+@menu
+* Charspace usage:: Details on improving the character metrics.
+* CMI files:: You specify the metrics in a separate file.
+* Invoking Charspace:: Command-line options.
+@end menu
+
+
+@node Charspace usage, CMI files, , Charspace
+@section Charspace usage
+
+@cindex Charspace usage
+@cindex usage of Charspace
+
+Charspace makes no attempt to be intelligent about the side bearings it
+computes; it just follows the instructions in the CMI files.
+
+The CMI files must be created by human hands, since the information they
+contain usually cannot be determined automatically. See the next
+section for the details on what CMI files contain.
+
+@flindex common.cmi
+We supply one CMI file, @file{common.cmi} (distributed in the
+@file{data} directory), which defines more-or-less typeface-independent
+definitions for most common characters. Charspace reads
+@file{common.cmi} before any of the CMI files you supply, so your
+definitions override its.
+
+@file{common.cmi} can be used for all typefaces because its definitions
+are entirely symbolic; therefore, your CMI file must define actual
+values for the identifiers it uses. For example, @file{common.cmi}
+defines the right side bearing of @samp{K} to be @code{uc-min-sb}; you
+yourself must define @code{uc-min-sb}.
+
+You must also define side bearings for characters not in
+@file{common.cmi}. And you can redefine side bearings that @emph{are}
+in @file{common.cmi}, if you find its definitions unsuitable.
+
+Once you have prepared a CMI file, you can run Charspace, e.g.:
+@example
+charspace -verbose -encoding=@var{enc-file} @var{fontname}.@var{dpi} \
+ -output-file=@var{out-fontname}
+@end example
+
+@noindent where @var{enc-file} specifies the encoding,
+@var{fontname} the input font, @var{dpi} the resolution, and
+@var{out-fontname} the name of the output font.
+
+@flindex testfont.tex
+With these options, Charspace will write files
+@file{@var{out-fontname}.tfm} and @file{@var{out-fontname}.@var{dpi}gf}.
+You can then run @TeX{} on @file{testfont.tex}, telling @TeX{} to use
+the font @var{out-fontname}. This produces a DVI file which you can
+print or preview as you usually do with @TeX{} documents.
+
+This will probably reveal problems in your CMI file, e.g., the spacing
+for some characters or character combinations will be poor. So you need
+to iterate.
+
+However, if you are planning to eventually run your bitmap font through
+Limn (@pxref{Limn}) and BZRto (@pxref{BZRto}) to make an outline font,
+there's little point in excessively fine-tuning the spacing of the
+original bitmap font. The reason is that the generated outline font
+will inevitably rasterize differently than the original bitmaps, and the
+change in character shapes will almost certainly affect the spacing.
+
+
+@node CMI files, Invoking Charspace, Charspace usage, Charspace
+@section CMI files
+
+@cindex CMI files
+@cindex character metric information files
+@cindex side bearing information files
+@cindex side bearings, definition of
+
+@dfn{Character metric information} (CMI) files are free-format text
+files which (primarily) describe the side bearings for characters in a
+font. @dfn{Side bearings} are the blank spaces to the left and right of
+a character which makeprinted type easier to read, as well as more pleasing
+visually.
+
+In addition to side bearing definitions, CMI files can also contain
+kerns, which insert or remove space between particular letter
+pairs, and font dimensions, global information about the font
+stored in the TFM file (@pxref{TFM fontdimens}).
+
+If your font is named @file{@var{foo}.300gf} (or @file{@dots{} pk}), it
+is customary to name the corresponding CMI file @file{@var{foo}.300cmi}.
+That is what Charspace looks for by default. If you name it something
+else, you must use the @samp{-cmi-files} option to tell Charspace its
+name. It is reasonable to use the resolution as part of the CMI
+filename, since the values written in it are (for the most part) in
+pixels.
+
+@xref{Common file syntax}, for a precise description of syntax elements
+common to all data files processed by these programs, including
+comments.
+
+@flindex ggmr.1200cmi
+@cindex CMI example
+See the file @file{data/ggmr.1200cmi} in the distribution for an example.
+
+In the following sections, we describe the individual commands, the
+tokens that comprise them, and the way Charspace processes them.
+
+@menu
+* CMI tokens:: The building blocks of CMI files.
+* char command:: Defining a character's side bearings.
+* char-width command:: Defining side bearings via the set width.
+* define command:: Introducing a new identifier.
+* kern command:: Defining a kerning pair.
+* codingscheme command:: Specifying the font encoding.
+* fontdimen command:: Defining additional font parameters.
+* CMI processing:: How Charspace reads CMI files.
+@end menu
+
+
+@node CMI tokens, char command, , CMI files
+@subsection CMI tokens
+
+@cindex tokens in CMI files
+@cindex CMI file tokens
+Tokens in a CMI file are one of the following.
+
+@enumerate
+
+@cindex real constants
+@cindex floating-point constants
+@cindex numbers
+@item
+A numeric constant consists of (in order) an optional sign, zero or more
+digits, an optional decimal point, and zero or more digits---but at
+least one digit must be present. For example, @samp{+0}, @samp{-0},
+@samp{0}, @samp{.0}, and @samp{-0.0} are all valid ways to write the
+number zero.
+
+@cindex string constants
+@item
+A string constant consists of all characters between two double-quote
+characters @samp{"}. We made no provision for quoting @samp{"}, because
+our particular uses for string constants never need quote characters.
+
+@cindex comma token
+@item
+A comma is a self-terminating token. It serves merely to separate two
+expressions.
+
+@cindex identifiers
+@cindex names
+@findex isspace
+@item
+An identifier is any number of characters starting with a non-whitespace
+character (whitespace being defined by the C facility @code{isspace})
+not listed above, and terminated by a whitespace character.
+
+@cindex character names
+In some contexts, an identifier is taken as a @dfn{character name}---a name
+from the encoding file Charspace is using, either the default or one you
+specified with @samp{-encoding} (@pxref{Invoking Charspace}).
+@xref{Encoding files}, for the definition of encoding files.
+
+In all other cases, identifiers are internal to Charspace. The particular
+commands describe the semantics which apply to them.
+
+@cindex reserved words
+@cindex keywords
+Some identifiers are @dfn{reserved}, i.e., they cannot be used in any
+context except as described in the following sections. Reserved words
+are always shown in typewriter type.
+
+@end enumerate
+
+@cindex expressions @r{in CMI files}
+An expression in a CMI file is one of: a number, an identifier, or a
+number followed by an identifier. This last, as in @samp{.75 foo},
+denotes multiplication.
+
+
+@node char command, char-width command, CMI tokens, CMI files
+@subsection @code{char} command
+
+@cmindex char @r{CMI command}
+@cindex side bearings, defining in CMI files
+
+The @code{char} command specifies both side bearings for a single
+character. It has the form:
+
+@example
+char @var{charname} @var{expr1} , @var{expr2}
+@end example
+
+@noindent where:
+
+@table @var
+
+@item charname
+is a character name from the font encoding. @xref{Invoking Charspace},
+for how to specify the encoding file.
+
+@cindex left side bearing in @code{char} command
+@cindex right side bearing in @code{char} command
+@cindex side bearings in @code{char} command
+@itemx expr1
+@item expr2
+specify the left and right side bearings, in pixels, respectively: the
+character widths in the output TFM and GF files are @math{@var{expr1} +
+@var{expr2} + @code{width} (@var{charname})}. If these
+expressions contain identifiers, the values of those identifiers are not
+resolved until after Charspace has read all the CMI files.
+
+@end table
+
+Giving the side bearings symbolically is useful when the character
+definition is intended to be used for more than one typeface. For
+example, @file{common.cmi} (@pxref{Charspace usage}) contains:
+
+@example
+char K H-sb , uc-min-sb
+char L H-sb , uc-min-sb
+@end example
+
+Then the CMI file you write for a particular font can define @code{H-sb}
+and @code{uc-min-sb}, and not have to redefine the side bearings for
+@code{K} and @code{L}.
+
+
+@node char-width command, define command, char command, CMI files
+@subsection @code{char-width} command
+
+@cmindex char-width @r{CMI command}
+@cindex side bearings, defining in CMI files
+
+The @code{char-width} command specifies the set width and left side
+bearing as a percentage of the total remaining space for a single
+character. It has the form:
+
+@example
+char-width @var{charname} @var{width-expr} , @var{lsb-%-expr}
+@end example
+
+@noindent where:
+
+@table @var
+
+@item charname
+is a character name from the font encoding. @xref{Invoking Charspace},
+for how to specify the encoding file.
+
+@cindex width in @code{char-width} command
+@cindex character width in @code{char-width} command
+@cindex set width in @code{char-width} command
+@item width-expr
+specifies the set width of the character in pixels. The @dfn{set width}
+is the sum of the bitmap width, left side bearing, and right side
+bearing.
+
+@cindex left side bearing in @code{char-width} command
+@item lsb-%-expr
+specifies the left side bearing as a percentage of @var{width-expr}
+minus the bitmap width of the character. Expressing the lsb as a
+percentage means that you need not think about the width of the
+character image: if you want to center a character, for example,
+@samp{.5} for @var{lsb-%-expr} will always work.
+
+@end table
+
+The @code{char-width} command is useful when you want a character to
+have a particular set width, since it's much simpler to specify that
+width and the left side bearing (and let the program compute the right
+side bearing) than to somehow estimate the bitmap width and then choose
+the side bearings to add up to the desired set width.
+
+@cindex widths of numerals
+@cindex numeral widths
+@vindex numeral-width @r{variable in @file{common.cmi}}
+@flindex common.cmi@r{, numerals in}
+For example, in most fonts, the numerals all have the same width, to
+ease typesetting of columns of them in tables. Thus, @file{common.cmi}
+defines @code{eight} (the name for the numeral @samp{8}) as follows:
+
+@example
+char-width eight numeral-width , eight-lsb-percent
+@end example
+
+@noindent Since the numeral width is traditionally one-half the em width of
+the font, @file{common.cmi} defines @code{numeral-width} as
+@code{enspace}, which in turn is defined to be half the @code{quad}
+fontdimen.
+
+@code{eight-lsb-percent} is defined to be @samp{.5}, thus centering the
+@samp{8}.
+
+The other numerals are also defined to have width @code{numeral-width},
+but the @code{lsb-percent}s vary according to the character shapes.
+
+
+@node define command, kern command, char-width command, CMI files
+@subsection @code{define} command
+
+@cmindex define @r{CMI command}
+@cindex identifier, defining in CMI files
+
+The @code{define} command defines an identifier as a number. This is
+useful to give a symbolic name to a constant used in more than one
+character or fontdimen definition, for ease of change.
+It has the form:
+
+@example
+define @var{id} @var{expr}
+@end example
+
+The identifier @var{id} is defined to be the expression @var{expr}. Any
+previous definition of @var{id} is replaced. The @var{id} can be used
+prior to the @code{define} command; Charspace doesn't try to resolve any
+definitions in the CMI files until after all files have been read.
+
+
+@node kern command, codingscheme command, define command, CMI files
+@subsection @code{kern} command
+
+@cmindex kern @r{CMI command}
+@cindex kerns, defining in CMI files
+
+The @code{kern} command defines a space to insert or remove between two
+particular characters. The kerning information is written only to the
+TFM file. It has the form:
+
+@example
+kern @var{name1} @var{name2} @var{expr}
+@end example
+
+@noindent where @var{name1} and @var{name2} are character names, as in
+the @code{char} command (@pxref{char command}), and @var{expr} is the
+amount of the kern in pixels.
+
+For example:
+
+@example
+kern F dot -7.5
+@end example
+
+@noindent would put an entry in the TFM file's kerning table such that
+when @TeX{} typesets a @samp{F} followed by a @samp{.}, it inserts
+an additional space equivalent to @math{-7.5} pixels in the resolution of
+Charspace's input font, i.e., it moves the two characters closer together.
+
+
+@node codingscheme command, fontdimen command, kern command, CMI files
+@subsection @code{codingscheme} command
+
+@cmindex codingscheme @r{CMI command}
+@cindex encoding scheme, specifying
+@cindex font encoding, specifying
+
+The @code{codingscheme} command defines the encoding scheme to be used
+for the output files. (@xref{Encoding files}, for a full description of
+font encodings.) It has the form:
+
+@example
+codingscheme @var{string-constant}
+@end example
+
+@flindex encoding.map
+@noindent where @var{string-constant} is a coding scheme string; for
+example, @samp{"GNU Latin text"}. This string is looked up in the data
+file @file{encoding.map} to find the name of the corresponding encoding
+file (@pxref{Coding scheme map file}).
+
+
+@node fontdimen command, CMI processing, codingscheme command, CMI files
+@subsection @code{fontdimen} command
+
+@cmindex fontdimen @r{CMI command}
+@cindex fontdimens in CMI files
+
+The @code{fontdimen} command defines a font parameter to be put in the
+TFM file. It has the form:
+
+@example
+fontdimen @var{fontdimen-name} @var{expr}
+@end example
+
+@noindent where @var{fontdimen-name} is any of the fontdimen names
+listed in the section below, and @var{expr} gives the new value of the
+fontdimen, in pixels.
+
+For example, @file{common.cmi} (@pxref{Charspace usage}) makes the
+following definitions:
+
+@example
+fontdimen quad designsize
+fontdimen space .333 quad
+@end example
+
+@noindent This defines the fontdimen @code{quad}, which determines the
+width of the @code{em} dimension in @TeX{}, to be the same as the design
+size of the font. (This is traditionally the case, although it is not a
+hard-and-fast rule.) Then it defines the fontdimen @code{space}, which
+is the normal interword space in @TeX{}, to be one-third of the quad.
+
+Because of the way that Charspace processes the CMI files
+(@pxref{CMI processing}), if you redefine the @code{quad} fontdimen in
+another CMI file, the value of @code{space} will change correspondingly.
+
+The section below lists all the TFM fontdimen names Charspace
+recognizes, and their meaning to @TeX{}.
+
+@menu
+* TFM fontdimens:: All the valid fontdimens.
+@end menu
+
+
+@node TFM fontdimens, , , fontdimen command
+@subsubsection TFM fontdimens
+
+@cindex fontdimens in TFM files
+@cindex TFM fontdimens
+@cindex global font parameters
+@cindex parameters, global in TFM files
+
+This section lists all the TFM fontdimens recognized by these programs:
+all those recognized by @TeX{}, plus a few others we thought would prove
+useful when writing @TeX{} macros.
+
+A @dfn{fontdimen} is an arbitrary number, in all cases but one
+(@code{slant}, see below) measured in printer's points, which is
+associated with a particular font. Their values are stored in the TFM
+file for the font. We also refer, context permitting, to fontdimens as
+``font parameters'', or simply ``parameters''.
+
+Fontdimens affect many aspects of @TeX{}'s behavior: the interword
+spacing, accent placement, and math formula construction. The math
+fontdimens in particular are fairly obscure; if you don't have a firm
+grasp on how @TeX{} constructs math formulas, the explanations below
+will probably be meaningless to you, and---unless you're making a font
+for math typesetting---can be ignored.
+
+@flindex common.cmi
+The @file{common.cmi} file which Charspace reads sets reasonable
+defaults for the fontdimens relevant to normal text typesetting.
+
+@cindex fontdimens, scaled fonts and
+When @TeX{} (or other programs) scale a font, its fontdimen values are
+scaled proportionally to the design size. For example, suppose the
+designsize of some font @var{f} is 10@dmn{pt}, and some fontdimen in
+@var{f} has the value 7.5@dmn{pt}. Then if the font is used scaled to
+20@dmn{pt}, the fontdimen's value is scaled to 15@dmn{pt}.
+
+@pindex pltotf
+You can get the table of fontdimen values in a particular TFM file by
+running the standard @TeX{} utility program PLtoTF and inspecting its
+(human-readable text) output.
+
+In our programs and in PLtoTF, fontdimens are typically shown by their
+names. But each also has a number, starting at 1. You can use either
+the number or the name on the command line (in the argument to the
+@samp{-fontdimens} option). The numbers are given in parentheses after
+the name in the table below.
+
+@cindex math symbol fonts
+@cindex math extension fonts
+@cindex extension, math fonts
+@cindex math families in @TeX{}
+In a few cases (fontdimens 8--13), the same number fontdimen has two
+different names, and two different meanings. This does not cause
+problems in practice, because these fontdimens are used only in the
+@TeX{} math symbol and math extension fonts, which @TeX{} can
+distinguish via its ``math families'' (see @cite{The @TeX{}book} for
+the details).
+
+@c The variable index doesn't seem quite right for the fontdimen names,
+@c but I can't think of anything better, and it doesn't make any
+@c practical difference, since we conglomerate all the indices into one anyway.
+@table @code
+
+@vindex slant @r{fontdimen}
+@cindex font slant
+@item slant @r{(1)}
+Unlike all other fontdimens, the @code{slant} parameter is not scaled
+with the font when it is loaded. It defines the ``slant per pt'' of the
+font; for example, a @code{slant} of 0.2 means a 1@dmn{pt}-high
+character stem would end 0.2@dmn{pt} to the right of where it began.
+This value is typical for slanted or italic fonts; for normal upright
+fonts, @code{slant} is zero, naturally. @TeX{} uses this to position
+accents.
+
+@vindex space @r{fontdimen}
+@cindex font spacing
+@cindex interword space
+@item space @r{(2)}
+The @code{space} parameter defines the normal interword space of the
+font. This is typically about one-third of the design size, but it
+varies according to the type design: a narrow, spiky typeface will
+have a small interword space relative to a wide, regular one.
+Exception: in math fonts, the interword space is zero.
+
+@vindex stretch @r{fontdimen}
+@item stretch @r{(3)}
+The @code{stretch} parameter defines the interword stretch of the font.
+This is typically about one-half of the @code{space} parameter. @TeX{}
+is reluctant to increase interword spacing beyond the width
+@math{@code{space} + @code{stretch}}. In monospaced fonts, the stretch
+is typically zero.
+
+@vindex shrink @r{fontdimen}
+@item shrink @r{(4)}
+The @code{shrink} parameter defines the interword shrink of the font.
+This is typically about one-third of the @code{space} parameter. @TeX{}
+does not decrease interword spacing beyond the width @math{@code{space}
+- @code{shrink}}. In monospaced fonts, the shrink is typically zero.
+
+@vindex xheight @r{fontdimen}
+@item xheight @r{(5)}
+The @code{xheight} parameter defines the x-height of the font, i.e., the
+main body size. The height of the lowercase `x' is often used for this,
+since neither the top nor the bottom of `x' are curves. There is no
+hard-and-fast rule in @TeX{} that the x-height must equal the height of
+`x', however.
+
+@vindex ex @r{@TeX{} dimension}
+This fontdimen defines the value of the @code{ex} dimension in @TeX{}.
+@TeX{} also uses this to position: it assumes the accents in the font
+are properly positioned over a character that is exactly 1@dmn{ex} high.
+
+@vindex quad @r{fontdimen}
+@vindex em @r{@TeX{} dimension}
+@item quad @r{(6)}
+The @code{quad} fontdimen defines the value of the @code{em} dimension
+in @TeX{}. This is often the same as the design size of the font, but
+as usual, that's not an absolute requirement.
+
+Typesetters often use @code{em}s and @code{ex}s instead of hardwiring
+dimensions in terms of (say) points; that way, experimenting with
+different fonts for a particular job does not require changing the
+dimensions.
+
+@vindex extraspace @r{fontdimen}
+@cindex sentence-ending space
+@findex \spacefactor
+@item extraspace @r{(7)}
+The @code{extraspace} fontdimen defines the space @TeX{} puts at the end
+of sentence. (Technically, when the @code{\spacefactor} is 20000 or
+more.) This is typically about one-sixth of the normal interword space.
+
+@vindex num1 @r{fontdimen}
+@item num1 @r{(8)}
+
+@vindex num2 @r{fontdimen}
+@item num2 @r{(9)}
+
+@vindex num3 @r{fontdimen}
+@item num3 @r{(10)}
+
+@vindex denom1 @r{fontdimen}
+@item denom1 @r{(11)}
+
+@vindex denom2 @r{fontdimen}
+@item denom2 @r{(12)}
+
+@vindex sup1 @r{fontdimen}
+@item sup1 @r{(13)}
+
+@vindex sup2 @r{fontdimen}
+@item sup2 @r{(14)}
+
+@vindex sup3 @r{fontdimen}
+@item sup3 @r{(15)}
+
+@vindex sub1 @r{fontdimen}
+@item sub1 @r{(16)}
+
+@vindex sub2 @r{fontdimen}
+@item sub2 @r{(17)}
+
+@vindex supdrop @r{fontdimen}
+@item supdrop @r{(18)}
+
+@vindex subdrop @r{fontdimen}
+@item subdrop @r{(19)}
+
+@vindex delim1 @r{fontdimen}
+@item delim1 @r{(20)}
+
+@vindex delim2 @r{fontdimen}
+@item delim2 @r{(21)}
+
+@vindex axisheight @r{fontdimen}
+@item axisheight @r{(22)}
+
+@vindex defaultrulethickness @r{fontdimen}
+@item defaultrulethickness @r{(8)}
+
+@vindex bigopspacing1 @r{fontdimen}
+@item bigopspacing1 @r{(9)}
+
+@vindex bigopspacing2 @r{fontdimen}
+@item bigopspacing2 @r{(10)}
+
+@vindex bigopspacing3 @r{fontdimen}
+@item bigopspacing3 @r{(11)}
+
+@vindex bigopspacing4 @r{fontdimen}
+@item bigopspacing4 @r{(12)}
+
+@vindex bigopspacing5 @r{fontdimen}
+@item bigopspacing5 @r{(13)}
+
+(Sorry, we haven't written a description of the math fontdimens yet.)
+
+@vindex leadingheight @r{fontdimen}
+@cindex leading
+@cindex interline space
+@cindex space, between lines
+@cindex strut height
+@findex \strutbox
+@item leadingheight @r{(23)}
+The @code{leadingheight} parameter defines the height component of the
+recommended leading for this font. @dfn{Leading} is the
+baseline-to-baseline distance when setting lines of type.
+
+@TeX{} does not automatically use this fontdimen, and the standard
+@TeX{} fonts do not define it, but you may wish to include it in new
+fonts for the benefit of future @TeX{} macros. This fontdimen is a GNU
+extension.
+
+@vindex leadingdepth @r{fontdimen}
+@item leadingdepth @r{(24)}
+The @code{leadingdepth} parameters defines the depth of the recommended
+leading for this font. See @code{leadingheight} directly above. This
+fontdimen is a GNU extension.
+
+@vindex fontsize @r{fontdimen}
+@item fontsize @r{(25)}
+The @code{fontsize} parameter is the design size of the font. This is
+needed for @TeX{} macros to find the font's design size. This fontdimen
+is a GNU extension.
+
+@vindex version @r{fontdimen}
+@cindex character dimensions, changing
+@cindex ligkern table, changing
+@cindex compatibility of fonts
+@item version @r{(26)}
+The @code{version} parameter identifies a particular version of the TFM
+file. Whenever the character dimensions, kerns, or ligature table for a
+font changes, it is good to increment the version number. It is also good
+to keep such changes to a minimum, since they can change the line breaks
+and page breaks in documents typeset with previous versions. This
+fontdimen is a GNU extension.
+@end table
+
+
+@node CMI processing, , fontdimen command, CMI files
+@subsection CMI processing
+
+@cindex CMI files, processing
+
+Here are some further details on how Charspace processes the CMI files:
+
+@itemize @bullet
+
+@cindex namespace in CMI files
+@cindex redefining identifiers in CMI files
+@cindex identifiers, redefining in CMI files
+@item
+Charspace uses a single @dfn{namespace}; i.e., each defined identifier,
+whether it be a character name, an internal identifier, a fontdimen
+name, or whatever, is stored in the same table. Furthermore, Charspace
+does not complain, or even warn, about redefinition of identifiers: as
+we build up CMI files to be shared among different fonts, we felt such
+redefinition would be common.
+
+@cindex use-before-definition in CMI files
+@cindex definition-before-use in CMI files
+@item
+Charspace does not insist that identifiers be used before they are
+defined. For example, the following sequence:
+
+@example
+define foo bar
+define bar 1.0
+char A foo , bar
+@end example
+
+@noindent is valid, and defines both side bearings of @samp{A} to be
+1.0. (See the preceding sections for the definition of the various
+commands allowed in CMI files.)
+
+@cindex resolution of definitions
+@item
+Charspace only tries to resolve the definitions of those identifiers
+which are actually used to produce the output files (i.e., those in a
+sidebearing definition, a kern value, or a fontdimen value). Thus,
+something like
+
+@example
+define foo bar
+@end example
+
+@noindent will elicit no complaint, if @samp{foo} is not needed to make
+the output files.
+
+@item
+Charspace reads the contents of all the CMI files before attempting to
+resolve any definitions. Thus, it is the last definition which counts.
+For example:
+
+@example
+define bar 100
+define foo 2 bar
+define bar 1
+char A foo , foo
+@end example
+
+@noindent defines both side bearings of @samp{A} to be 2, not 200.
+
+@vindex designsize @r{predefined for CMI files}
+@item
+Charspace predefines one identifier, @code{designsize}, to be the
+design size of the input font (in pixels). It can be redefined like any
+other identifier.
+
+@end itemize
+
+@flindex char.c
+@flindex cmi.y
+If you can read programs in the C language, you may find it instructive
+to examine the implementation of CMI file processing in the source files
+@file{charspace/char.c} and @file{charspace/cmi.y}. The source provides
+the full details of CMI processing.
+
+
+@node Invoking Charspace, , CMI files, Charspace
+@section Invoking Charspace
+
+@cindex Charspace options
+@cindex invocation of Charspace
+@cindex options for Charspace
+
+This section describes the options that Charspace accepts.
+@xref{Command-line options}, for general option syntax.
+
+The root of the main input fontname is called @var{font-name} below.
+
+@table @samp
+
+@opindex -cmi-files
+@item -cmi-files @var{file1},@var{file2},@dots{}
+read the CMI files @file{@var{file1}.@var{dpi}cmi},
+@file{@var{file2}.@var{dpi}cmi}, etc., where @var{dpi} is the resolution
+of the main input font. Default is to read
+@file{@var{font-name}.@var{dpi}cmi}. The @file{.@var{dpi}cmi} is not
+appended to any of the @var{file}s which already have a suffix.
+
+@flindex common.cmi
+@file{common.cmi} is read before any of these files.
+
+@opindex -dpi
+@item -dpi @var{unsigned}
+The resolution, in pixels per inch. @xref{Common options}.
+
+@opindex -encoding
+@item -encoding @var{enc-file}
+The encoding file to read for the mapping between character codes in the
+input font and character names. @xref{Encoding files}. If
+@var{enc-file} has no suffix, @samp{.enc} is appended. The default is
+to read the encoding file specified via the @code{codingscheme} command
+(@pxref{codingscheme command}).
+
+If a TFM file @file{@var{font-name}.tfm} exists, it is also read for
+default ligature, headerbyte, and fontdimen information. Definitions in
+the CMI files override those in such a TFM file.
+
+@opindex -fontdimens
+@item -fontdimens @var{fd1}:@var{value1},@var{fd2}:@var{value2},@dots{}
+@xref{TFM fontdimens}.
+
+@opindex -help
+@item -help
+Print a usage message. @xref{Common options}.
+
+@opindex -no-gf
+@item -no-gf
+Don't output a revised GF file. This is primarily useful while
+debugging the TFM output, since without a bitmap font to match the TFM
+output, you can't actually print anything reliably.
+
+@opindex -output-file
+@cindex output file, naming
+@item -output-file @var{filename}
+If @var{filename} does not have a suffix, write the output to
+@file{@var{filename}.tfm} and (if @samp{-no-gf} was not specified)
+@file{@var{filename}.@var{dpi}gf}. If this would overwrite an input
+file, prepend an @samp{x} to the output name.
+
+If @var{filename} has a suffix, and @samp{-no-gf} was not specified,
+Charspace complains and gives up, since it can't output two files with
+the same name.
+
+By default, use the name of the main input font for @var{filename}.
+
+@opindex -range
+@item -range @var{char1}-@var{char2}
+Only output characters with codes between @var{char1} and @var{char2},
+inclusive. (@xref{Common options}, and @ref{Specifying character codes}.)
+
+@opindex -verbose
+@item -verbose
+Output progress reports.
+
+@opindex -version
+@item -version
+Print the version number.
+
+@opindex -xheight-char
+@item -xheight-char @var{code}
+Use the TFM height of @var{code} for the @code{xheight} fontdimen
+(@pxref{TFM fontdimens}); default is 120 (ASCII @samp{x}). (It is
+reasonable to use 120 instead of whatever @samp{x} is in the underlying
+character set because most font encoding schemes are based on ASCII
+regardless of the host computer's character set.)
+
+@end table
diff --git a/doc/enhance.texi b/doc/enhance.texi
new file mode 100644
index 0000000..8846a34
--- /dev/null
+++ b/doc/enhance.texi
@@ -0,0 +1,360 @@
+@c Copyright (C) 1992 Free Software Foundation.
+@c This is part of the GNU font utilities manual.
+@c For copying conditions, see the file fontutil.texi.
+
+@node Enhancements, Copying, GSrenderfont, Top
+@chapter Enhancements
+
+@cindex enhancements, future
+@cindex improvements, possible future
+@cindex future enhancements
+@cindex projects
+
+@cindex volunteering
+@cindex contribution, making your own
+Like all software, the font utilities can all be (probably endlessly)
+improved. Following are some possible projects.
+
+If you would like to contribute, send mail to
+@samp{bug-gnu-utils@@prep.ai.mit.edu} first, so we can coordinate the
+work.
+
+@menu
+* Additional fonts:: GNU needs more fonts.
+* Program features:: These programs can be improved.
+* Portability:: Assumptions about the programming environment.
+* Implementation:: Conventions we used in the sources.
+@end menu
+
+
+@node Additional fonts, Program features, , Enhancements
+@section Additional fonts
+
+The original purpose of these programs was to create fonts for
+Ghostscript, the GNU PostScript-compatible interpreter written by Peter
+Deutsch. Adobe and many other vendors sell fonts which Ghostscript can
+use, but they place many restrictions on the use of those fonts. These
+restrictions certainly include modification and copying; in some cases,
+they even include using the font on more than one printer or display!
+These restrictions are contrary to the aims of the GNU project.
+
+Obviously we cannot compete in volume with Adobe, Bitstream, or other
+vendors, all of whom probably have dozens if not hundreds of people
+working on nothing but font production, and additional people hired as
+programmers in support. The present authors (both working half-time)
+are the entire FSF ``font production'' department, both for design and
+for programming.
+
+Fortunately, we do not need to compete in volume (certainly we haven't
+needed the thousands of Adobe fonts in our practice as typographers).
+Our aim is to produce the basic typefaces for typography: Garamond,
+Bodoni, Gill Sans, Univers, Baskerville, and perhaps a few others. If
+someone wants some other typeface, they could use our programs to make
+it, and, we hope, contribute it back to GNU for others to use.
+
+We do need volunteers to help create fonts for the GNU project. You do
+not need to be an expert type designer to help, but you do need to know
+enough about @TeX{} and/or PostScript to be able to install and test new
+fonts. Example: if you know neither (1) the purpose of TeX utility
+program @code{gftopk} nor (2) what the PostScript @code{scalefont}
+command does, you probably need more experience before you can help.
+
+If you can volunteer, the first step is to compile the font utilities
+(@pxref{Installation}). After that, contact us at
+@samp{karl@@gnu.ai.mit.edu}. I will get you a scanned type specimen
+image. @xref{Creating fonts}, for how to use these utilities to turn
+that into a font you can use in @TeX{} or PostScript.
+
+
+@node Program features, Portability, Additional fonts, Enhancements
+@section Program features
+
+@cindex features, lacking
+
+Here are some possible projects:
+
+@table @asis
+
+@item BZRedit
+@itemize @bullet
+@item
+Rewrite as a C program along the lines of XBfe (in fact, seeing the
+bitmap and the generated splines simultaneously would be useful).
+@item
+@cindex hints
+Add support for hints.
+@end itemize
+
+@item BZRto
+@itemize @bullet
+@item
+@cindex TrueType
+Output more font formats, e.g., TrueType.
+@item
+Output hints for Metafont and Type 1 fonts.
+@item
+@vindex FontInfo
+Make better guesses for the @code{FontInfo} information.
+@item
+@cindex obliquing
+Handle obliquing fonts by changing the transform matrix in the output,
+instead of changing the numbers in the splines.
+@item
+@cindex nonlinear scaling
+@cindex scaling, nonlinear
+@cindex anamorphic scaling
+@cindex optical scaling
+Do nonlinear scaling.
+@item
+@cindex italic corrections
+Handle italic corrections in the Metafont output somehow. Probably have
+to do the same in Charspace.
+@end itemize
+
+@item Fontconvert
+@itemize @bullet
+@item
+@cindex virtual fonts
+Output virtual fonts as an option, instead of another bitmap font.
+@item
+@cindex encodings, translating between
+Allow specifying entire input encodings and output encodings (the
+same @file{.enc} files that the other programs read).
+@end itemize
+
+@item GF library
+@itemize @bullet
+@item
+Support multiple simultaneous open fonts, like the PK library does now.
+@cindex checksum
+@item
+Output a checksum.
+@end itemize
+
+@item GSrenderfont
+@itemize @bullet
+@item
+@cindex size of characters, maximum
+@cindex limit on character size
+Allow for characters larger than 1 inch square in the original font.
+@item
+@cindex slanted fonts
+@cindex extended fonts
+@cindex small caps
+Implement slanting, extending, and small caps, a la Dvips.
+@end itemize
+
+@item Imageto
+@itemize @bullet
+@item
+@cindex Tiff
+Recognize more image formats, e.g., Tiff.
+@item
+@cindex splitting characters
+@cindex characters, splitting
+Perhaps the @samp{-column-split} option in Fontconvert should be
+removed, and the equivalent information specified in the IFI file.
+@end itemize
+
+@item IMGrotate
+@itemize @bullet
+@item
+Perhaps combine with Imageto.
+@item
+@pindex pnmrotate
+@cindex rotation algorithm
+Implement a good rotation algorithm, perhaps as described in: ``A Fast
+Algorithm for General Raster Rotation'', by Alan Paeth, @cite{Graphics
+Interface '86}, pages 77--81. (We'd be interested in hearing of
+optimized alternatives for the case of 90 degree rotation only). The
+program @code{pnmrotate}, which mentions that article, in the PBMplus
+distribution could perhaps be adapted.
+@end itemize
+
+@item @code{lib}
+@itemize @bullet
+@item
+Extend the encoding files to allow defining math attributes, probably by
+rewriting the parsing routines as a Bison grammar.
+@item
+@findex string_to_bitmap
+@flindex font.c
+@cindex typesetting kerns and ligatures
+@cindex kerns, typesetting
+@cindex ligatures, typesetting
+Write a variant of @code{string_to_bitmap} (in @file{font.c}) which
+understands kerns and ligatures.
+@item
+@cindex BDF format
+Add support for BDF or other bitmap formats. Unrelated utility programs
+now exist for handling the X11 BDF format (specifically, Bdf2gf and
+GFto), but it might be useful to integrate BDF support.
+@end itemize
+
+@item Limn
+Handle the standard X toolkit options.
+
+@item PK library
+Implement output of PK files.
+
+@item TFM library
+@itemize @bullet
+@item
+Support multiple simultaneous open fonts, like PK does now.
+@cindex ligatures in TFM files
+@item
+Support ligatures in their full generality.
+@item
+Output a checksum.
+@end itemize
+
+@item XBfe
+@itemize @bullet
+@item
+Allow showing more than one character at a time.
+@cindex guidelines
+@item
+Adjusting (or at least seeing) the baseline, cap height, x-height, or
+arbitrary guidelines.
+@item
+Handle multiple fonts.
+@item
+Notice if the window it's given is too small, and give up.
+@item
+@cindex window size for XBfe
+Ask the window manager for a window big enough for the largest character
+in the font, not the first character.
+@end itemize
+
+@end table
+
+In addition, one general enhancement would be to allow more than 256
+characters per font. The bitmap formats allow this already, and the TFM
+format has some support for it.
+
+Two other smaller general improvements: combine multiple @samp{-range}
+options; allow for omitting ranges.
+
+
+@node Portability, Implementation, Program features, Enhancements
+@section Portability
+
+@cindex portability of sources
+@cindex GNU C extensions
+
+We didn't worry about making the programs work with any C compiler;
+instead, we used GNU C extensions where they were useful. Likewise for
+GNU make.
+
+@cindex GNU evangelism
+We allowed ourselves this luxury because these programs are not
+historical utilities which people would expect to find on any Unix
+system. Rather, they are application programs. Perhaps having them
+work only with other GNU programs will encourage people to switch to
+GNU programs, or at least become aware of them.
+
+It probably would not be too hard to change the programs to work with
+other ANSI C compilers. Changing them to work with old C compilers
+would be more painful. Thus far, the dependency on GCC hasn't proved a
+serious problem, because GCC runs on so many machines.
+
+@cindex GNU make, dependency on
+It would be dull but straightforward to write Makefiles for the
+programs which didn't use any of GNU make's special features. As with
+GCC, though, GNU make is so widely available that we haven't felt it
+necessary to do so.
+
+@cindex path searching, implementation of
+The one exception is to this are the dozen or so files in the @file{lib}
+and @file{include} directories which implement the path searching
+algorithm. Because these files are shared with the @TeX{}, Dvips, and
+XDvi distributions, they are written to work with old C compilers.
+
+@xref{Archives}, for information on how to obtain GCC and the other
+programs mentioned. @xref{Portability, , Portability as it applies to
+GNU, standards, GNU Coding Standards}, for more discussion of the
+portability of GNU programs in general.
+
+
+@node Implementation, , Portability, Enhancements
+@section Implementation
+
+@cindex implementation
+@cindex coding standards
+@cindex programming conventions
+
+@c Texinfo has no good way of referring to a whole manual. Argh.
+This section describes some of the conventions we used in the
+organization of the source code. @xref{Top, , , standards, GNU Coding
+Standards}, for the general GNU conventions.
+
+In our sources, @file{.c} files include @file{config.h} first, which in
+turn includes @file{global.h}, which includes @file{types.h} and other
+header files which define ubiquitous identifiers.
+
+@cindex header files
+@file{.h} files, on the other hand, do not include @file{config.h}.
+They only include whatever headers are needed to define what they
+themselves use---typically including but not limited to @file{types.h}.
+
+All @file{.h} files are protected with @code{#ifndef @var{unique-symbol}}.
+
+The upshot of these conventions is that headers can be included in any
+order, as many times as necessary. In a @file{.c} file, only those
+headers which define symbols needed in the C source need be included,
+without worrying that some headers depend on others. (ANSI C defines its
+headers to follow these same rules.)
+
+@ignore
+@c Skip this, who cares? Anyway, we aren't perfectly consistent.
+Since the headers can be included in any order, we arbitrarily chose to
+have three groups of @code{#include}s: @file{config.h}; system or
+library headers, such as @file{<sys/stat.h>} or @file{line.h}; and
+program-specific headers.
+@end ignore
+
+Virtually all @file{.c} files---the only exceptions are (sometimes)
+@file{main.c} and some library files---have a corresponding @file{.h}
+file, which defines all the public symbols (e.g., non-@code{static}
+routines and types). in the @file{.h} file are intended to explain the
+external interface; comments in the @file{.c} file assume you already
+know what's in the @file{.h} file, to avoid having the same information
+in two places, and try to explain only implementation details.
+
+@opindex -Wmissing-prototypes
+@cindex missing prototypes
+@cindex prototypes, missing
+Therefore, a @file{.c} file should always include its corresponding
+@file{.h} file, to ensure consistency between the definitions and the
+declarations. GCC 2's @samp{-Wmissing-prototypes} option can be used to
+check this.
+
+@cindex main program
+@flindex main.c
+The main program is always in a file named @file{main.c}. Typically it
+loops through all the characters in the input font, doing something with
+them. Parsing arguments is also done in @file{main.c}, in a function
+named @code{read_command_line}, using @code{getopt}. @xref{Command-line
+options}, for more information on option parsing.
+
+@pindex configure@r{, creation of}
+@flindex include/c-auto.h@r{, creation of}
+The @file{configure} script used to determine system dependencies is
+generated by GNU Autoconf from @file{configure.in}. When
+@file{configure} runs, it creates @file{include/c-auto.h} from
+@file{include/c-auto.h.in} to record what it discovers. @file{config.h}
+includes this file.
+
+@cindex structure types
+We access members of most structure types via macros instead of with
+@code{.} or @code{->} directly. We pass and return whole structures
+without hesitation; this has not resulted in any noticeable performance
+loss. When we use pointers to structures, it's almost always because we
+need a distinguishable value (i.e., @code{NULL}).
+@vindex NULL
+
+@cindex functions, declaring @code{const}
+When a function has no side effects (e.g., assignments to global
+variables), and does not examine any values except its arguments (e.g.
+if a pointer is passed, it does not examine the data pointed to),
+we declare it @code{const}. (This is a GNU C extension.)
diff --git a/doc/filefmts.texi b/doc/filefmts.texi
new file mode 100644
index 0000000..56eb7e8
--- /dev/null
+++ b/doc/filefmts.texi
@@ -0,0 +1,442 @@
+@c Copyright (C) 1992 Free Software Foundation.
+@c This is part of the GNU font utilities manual.
+@c For copying conditions, see the file fontutil.texi.
+
+@node File formats, Imageto, Bugs, Top
+@chapter File formats
+
+@cindex file formats
+@cindex auxiliary files
+@cindex data files
+
+These programs use various data files to specify font encodings,
+auxliary information for a font, and other things. Some of these data
+files are distributed in the directory @file{data}; others must be
+constructed on a font-by-font basis.
+
+@vindex FONTUTIL_LIB @r{environment variable}
+@cindex data file searching
+If the environment variable @code{FONTUTIL_LIB} is set, data files are
+looked up along the path it specifies, using the same algorithm as is
+used for font searching (@pxref{Font searching}). Otherwise, the
+default path is set in the top-level Makefile.
+
+The following sections (in other chapters of the manual) also describe
+file formats:
+
+@itemize @bullet
+
+@item
+@ref{BZR files}.
+
+@item
+@ref{CCC files}.
+
+@item
+@ref{CMI files}.
+
+@item
+@ref{IFI files}.
+
+@end itemize
+
+@menu
+* File format abbreviations:: The alphabet soup of font formats.
+* Common file syntax:: Some elements of auxiliary files are constant.
+* Encoding files:: The character code-to-shape mapping.
+* Coding scheme map file:: The coding scheme string-to-filename mapping.
+@end menu
+
+
+@node File format abbreviations, Common file syntax, , File formats
+@section File format abbreviations
+
+@cindex abbreviations, of file formats
+@cindex file format abbreviations
+@cindex meaning, of file format abbreviations
+
+For the sake of brevity, we do not spell out every abbreviation
+(typically of file format names) in the manual every time we use it.
+This section collects and defines all the common abbreviations we use.
+
+@table @asis
+
+@cindex BPL abbrevation
+@item BPL
+The `Bezier property list' format output by BZRto and read by BPLtoBZR.
+This is a transliteration of the binary BZR format into human-readable
+(and -editable) text. @xref{BPL files}.
+
+@cindex BZR abbrevation
+@item BZR
+The `Bezier' outline format output by Limn and read by BZRto. We
+invented this format ourselves. @xref{BZR files}.
+
+@cindex CCC abbreviation
+@item CCC
+The `cookie-cutter character' (er, `composite character construction')
+files read by BZRto to add pre-accented and other such characters to a
+font. @xref{CCC files}.
+
+@cindex CMI abbreviation
+@item CMI
+The `character metric information' files read by Charspace to add side
+bearings to a font. @xref{CMI files}.
+
+@cindex GF abbreviation
+@item GF
+The `generic font' bitmap format output by Metafont (and by most of
+these programs). See the sources for Metafont or one of the other
+@TeX{} font utility programs (GFtoPK, etc.) for the definition.
+
+@cindex DVI abbreviation
+@item DVI
+The `device independent' format output by @TeX{}, GFtoDVI, etc. Many
+``DVI driver'' programs have been written to translate DVI format to
+something that can actually be printed or previewed. See sources for
+@TeX{} or DVItype for the definition.
+
+@cindex EPS abbreviation
+@cindex advertising
+@item EPS
+The `Encapsulated PostScript' format output by many programs, including
+Imageto (@pxref{Viewing an image}) and Fontconvert (@pxref{Fontconvert
+output options}). An EPS file differs from a plain PostScript file in
+that it contains information about the PostScript image it produces: its
+bounding box, for example. (This information is contained in comments,
+since PostScript has no good way to express such information directly.)
+
+@cindex IFI abbreviation
+@item IFI
+The `image font information' files read by Imageto when making a font
+from an image. @xref{IFI files}.
+
+@cindex GSF abbrevation
+@pindex bdftops
+@cindex Ghostscript font format
+@item GSF
+The `Ghostscript font' format output by BZRto and the @file{bdftops}
+program in the Ghostscript distribution. This is nothing more than the
+Adobe Type 1 font format, unencrypted. The Adobe Type 1 format is
+defined in a book published by Adobe. (Many PostScript interpreters
+cannot read unencrypted Type 1 fonts, despite the fact that the
+definition says encryption is not required. Ghostscript can read both
+encrypted and unencrypted Type 1 fonts.)
+
+@cindex IMG abbreviation
+@cindex GEM
+@cindex DOS image format
+@item IMG
+The `image' format used by some GEM (a window system sometimes used
+under DOS) programs; specifically, by the program which drives our
+scanner.
+
+@cindex MF abbreviation
+@cindex Knuth, Donald E.
+@item MF
+The `Meta-Font' programming language for designing typefaces invented by
+Donald Knuth. His @cite{Metafontbook} is the only manual written to
+date (that we know of).
+
+@cindex PBM abbreviation
+@cindex Poskanzer, Jef
+@item PBM
+The `portable bitmap' format used by the PBMplus programs,
+Ghostscript, Imageto, etc. It was invented by Jef Poskanzer (we
+believe), the author of PBMplus.
+
+@cindex PFA abbreviation
+@item PFA
+The `printer font ASCII' format in which Type 1 PostScript fonts are
+sometimes distributed. This format uses the ASCII hexadecimal
+characters @samp{0} to @samp{9} and @samp{a} to @samp{f} (and/or
+@samp{A} to @samp{F}) to represent an @code{eexec}-encrypted Type 1
+font.
+
+@cindex PFB abbreviation
+@item PFB
+The `printer font binary' format in which Type 1 PostScript fonts are
+sometimes distributed. This format is most commonly used on DOS
+systems. (Personally, we find the existence of this format truly
+despicable, as one of the major advantages of PostScript is its being
+defined entirely in terms of plain text files (in Level 1 PostScript,
+anyway). Having an unportable binary font format completely defeats
+this.)
+
+@cindex PK abbreviation
+@cindex Rokicki, Tom
+@pindex gftopk
+@item PK
+The `packed font' bitmap format output by GFtoPK. PK format has (for
+all practical purposes) the same information as GF format, and does a
+better job of packing: typically a font in PK format will be one-half to
+two-thirds of the size of the same font in GF format. It was invented
+by Tom Rokicki as part of the @TeX{} project. See the GFtoPK source for
+the definition.
+
+@cindex PL abbreviation
+@cindex property list format
+@cindex editing TFM files
+@pindex tftopl
+@item PL
+The `property list' format output by TFtoPL. This is a transliteration
+of the binary TFM format into human-readable (and -editable) text. Some
+of these programs output a PL file and call PLtoTF to make a TFM from
+it. (For technical reasons it is easier to do this than to output a TFM
+file directly.) See the PLtoTF source for the details.
+
+@cindex TFM abbreviation
+@cindex @TeX{} font metric format
+@cindex font metrics
+@pindex pltotf
+@item TFM
+The `@TeX{} font metric' format output by Metafont, PLtoTF, and other
+programs, and read by @TeX{}. TFM files include only character
+dimension information (widths, heights, depths, and italic corrections),
+kerns, ligatures, and font parameters; in particular, there is no
+information about the character shapes. See the @TeX{} or Metafont
+source for the definition.
+
+@end table
+
+
+@node Common file syntax, Encoding files, File format abbreviations, File formats
+@section Common file syntax
+
+@cindex syntax, common data file
+@cindex common data file syntax
+@cindex file syntax, common
+@cindex data file syntax, common
+
+Data files read by these programs are text files that share certain
+syntax elements:
+
+@itemize @bullet
+
+@cindex comments in data files
+@cindex data files, comments in
+@item
+Comments begin with a @samp{%} character and continue to the end of the
+line. The content of comments is entirely ignored.
+
+@cindex blank lines in data files
+@cindex data files, blank lines in
+@cindex whitespace characters in data files
+@cindex data files, whitespace characters in
+@findex isspace
+@item
+Blank lines are allowed, and ignored. Whitespace characters (as
+defined by the C facility @code{isspace}) are ignored at the beginning of
+a line.
+
+@cindex null byte in data files
+@cindex ASCII NUL in data files
+@cindex data files, valid characters in
+@item
+Any character except ASCII NUL---character zero---is acceptable in data
+files. (We would allow NULs, too, at the expense of complicating the
+code, if we knew of any useful purpose for them.)
+
+@end itemize
+
+@cindex line length in data files
+A line can be as long as you want.
+
+
+@node Encoding files, Coding scheme map file, Common file syntax, File formats
+@section Encoding files
+
+@cindex encoding files
+@cindex font encoding, files for
+@cindex character mapping
+@cindex mapping, of characters
+
+The @dfn{encoding} of a font specifies the mapping from character codes
+(an integer, typically between zero and 255) to the characters
+themselves; e.g., does a character with code 92 wind up printing as a
+backslash (as it does under the ASCII encoding) or as a double left
+quote (as it does under the most common @TeX{} font encoding)? Put
+another way, the encoding is the arrangement of the characters in the
+font.
+
+It is sad but true that no single encoding has been widely adopted, even
+for basic text fonts. (Text fonts and, say, math fonts or symbol fonts
+will clearly have different encodings.) Every typesetting program
+and/or font source seems to come up with a new encoding; GNU is no
+exception (see below). Therefore, when you decide on the encoding for
+the fonts you create, you should choose whatever is most convenient for
+the typesetting programs you intend to run it with. (Decent typesetting
+systems would make it trivial to set font encodings; unfortunately,
+almost nothing is decent in that regard!)
+
+@flindex .enc @r{suffix}
+The @dfn{encoding file} format we invented is a font-format-independent
+representation of an encoding. Encoding files are ``data files'' which
+have the basic syntax elements described above (@pxref{Common file
+syntax}). They are usually named with the extension @code{.enc}.
+
+The first nonblank non-comment line in an encoding file is a string to
+put into TFM files as the ``coding scheme'' to describe the encoding;
+some common coding schemes are @samp{TeX text}, @samp{TeX math symbol},
+@samp{Adobe standard}. Case is irrelevant; that is, any programs which
+use the coding scheme should pay no attention to its case.
+
+Thereafter, each nonblank non-comment line defines the character for the
+corresponding code: the first such line defines the character with code
+zero, the next with code one, and so on.
+
+Each character consists of a name, optionally followed by ligature
+information. (All fonts using the same encoding should have the same
+ligatures, it seems to us.)
+
+@menu
+* Character names:: How to write character names.
+* Ligature definitions:: How to define ligatures.
+* GNU encodings:: Why we invented new encodings for GNU.
+@end menu
+
+
+@node Character names, Ligature definitions, , Encoding files
+@subsection Character names
+
+@cindex character names
+@cindex names of characters
+
+The @dfn{character name} in an encoding file is an arbitrary sequence of
+nonblank characters (except it can't include a @code{%}, since that
+starts a comment). Conventionally, it consists of only lowercase
+letters, except where an uppercase letter is actually involved. (For
+example, @code{eacute} is a lowercase @code{e} with an acute accent;
+@code{Eacute} is an uppercase @code{E} with an acute accent.
+
+@vindex .notdef
+@cindex blank positions in fonts
+@cindex undefined characters in fonts
+@cindex fonts, undefined characters in
+If a character code has no equivalent character in the font, i.e., the
+font table has a ``blank spot'', you should use the name @code{.notdef}
+for that code. This is the only name you can usefully give more than
+once. If any other name is used more than once, the results are
+undefined.
+
+To avoid unnecessary proliferation of character names, you should use
+names from existing @file{.enc} files where possible. All the
+@file{.enc} files we have created are distributed in the @file{data}
+directory.
+
+
+@node Ligature definitions, GNU encodings, Character names, Encoding files
+@subsection Ligature definitions
+
+@cindex ligature definitions
+@cindex defining ligatures
+@cindex encoding, ligatures in
+
+The ligature information for a character in an encoding file is
+optional. More than one ligature specification may be given. Each
+specification looks like:
+
+@example
+lig @var{second-char} =: @var{lig-char}
+@end example
+
+This means that a ligature character @var{lig-char} should be present in
+the font for the current character (the one being defined on this line
+of the encoding file) followed by @var{second-char}. You give
+@var{second-char} and @var{lig-char} as character codes
+(@pxref{Specifying character codes}). For example, in most text
+encodings (which involve Latin characters), some variation on the
+following line will be present:
+
+@example
+f lig f =: 013 lig i =: 014 lig l =: 015
+@end example
+
+This will produce a ligature in the font such that when a typesetting
+program sees the two character sequence @samp{ff} in the input, it
+replaces those two characters in the output with the single character at
+position octal 13 (presumably the `fi' ligature) of the font; when it
+sees @samp{fi}, the character at position octal 14 is output; when
+it sees @samp{fl}, the character at position octal 15 is output.
+
+@cindex ligatures in Metafont 2
+Metafont version 2 allows a more general ligature scheme; if there is a
+demand for it, it wouldn't be hard to add.
+
+
+@node GNU encodings, , Ligature definitions, Encoding files
+@subsection GNU encodings
+
+@cindex encodings, GNU
+@cindex GNU encodings
+
+@cindex Cork encoding
+@cindex PostScript encodings
+@cindex Adobe encodings
+@cindex @TeX{} encodings
+When we started making fonts for the GNU project, we had to decide on
+some font encoding. We hoped to use an existing one, but none that we
+found seemed suitable: the @TeX{} font encodings, including the ``Cork
+encoding'' described in TUGboat 11#4, lacked many standard PostScript
+characters; conversely, the standard PostScript encodings lacked useful
+@TeX{} characters. Since we knew that Ghostscript and @TeX{} would be
+the two main applications using the fonts, we thought it unacceptable to
+favor one at the expense of the other.
+
+@flindex gnulatin.enc
+Therefore, we invented two new encodings. The first one, ``GNU Latin
+text'' (distributed in @file{data/gnulatin.enc}), is based on ISO Latin
+1, and is close to a superset of both the basic @TeX{} text encoding and
+the Adobe standard text encoding. We felt it was best to use ISO Latin
+1 as the foundation, since some existing systems actually use ISO Latin
+1 instead of ASCII. We also left the first eight positions open, so
+particular fonts could add more ligatures or other unusual characters.
+
+@cindex expert encoding
+The second, ``GNU Latin text complement'' (distributed in
+@file{data/gnulcomp.enc}), includes the remaining pre-accented
+characters from the Cork encoding, the PostScript expert encoding, swash
+characters, small caps, etc.
+
+@c todo discuss encodings in more detail, show tables, etc.
+
+
+@node Coding scheme map file, , Encoding files, File formats
+@section Coding scheme map file
+
+@cindex coding scheme mapping
+@cindex finding encodings
+
+When a program reads a TFM file, it's given an arbitrary string (at
+best) for the coding scheme. To be useful, it needs to find the
+corresponding encoding file. We couldn't think of any way to name our
+@file{.enc} files that would allow the filename to be guessed
+automatically. Therefore, we invented another data file which maps the
+TFM coding scheme strings to our @file{.enc} filenames.
+
+@flindex encoding.map
+This file is distributed as @file{data/encoding.map}. @xref{Common file
+syntax}, for a description of the common syntax elements.
+
+Each nonblank non-comment line in @file{encoding.map} has two entries:
+the first word (contiguous nonblank characters) is the @file{.enc}
+filename; the rest of the line, after ignoring whitespace, is the string
+in the TFM file. This should be the same string that appears on the
+first line of the @file{.enc} file (@pxref{Encoding files}).
+
+Programs should ignore case when using the coding scheme string.
+
+Here is the coding scheme map file we distribute:
+
+@example
+adobestd Adobe standard
+ascii ASCII
+dvips dvips
+dvips TeX text + adobestandardencoding
+gnulatin GNU Latin text
+gnulcomp GNU Latin text complement
+psymbol PostScript Symbol
+texlatin Extended TeX Latin
+textext TeX text
+zdingbat Zapf Dingbats
+@end example
diff --git a/doc/fontcvt.texi b/doc/fontcvt.texi
new file mode 100644
index 0000000..5341df7
--- /dev/null
+++ b/doc/fontcvt.texi
@@ -0,0 +1,398 @@
+@c Copyright (C) 1992, 93 Free Software Foundation.
+@c This is part of the GNU font utilities manual.
+@c For copying conditions, see the file fontutil.texi.
+
+@node Fontconvert, Charspace, IMGrotate, Top
+@chapter Fontconvert
+
+@pindex fontconvert
+@cindex manipulation, of bitmap fonts
+@cindex bitmap font manipulation
+
+Fontconvert performs manipulations on bitmap fonts: conversion to other
+formats, merging multiple fonts, adjusting individual characters, moving
+characters around within a font, @dots{}
+
+The input is either a GF or a PK bitmap font, and in some
+circumstances, a TFM file. (@xref{File format abbreviations}.) The
+output varies according to the options specified.
+
+@menu
+* Invoking Fontconvert:: Command-line options.
+@end menu
+
+
+@node Invoking Fontconvert, , , Fontconvert
+@section Invoking Fontconvert
+
+@cindex Fontconvert options
+@cindex invocation of Fontconvert
+@cindex options for Fontconvert
+
+In the following sections we describe all the options Fontconvert
+accepts, grouped according to general function.
+
+@menu
+* Fontconvert output options:: Specifying the output format(s).
+* Character selection options:: What characters to operate on.
+* Character manipulation options:: Changing characters' appearance.
+* Fontwide information options:: Changing global information in a font.
+* Miscellaneous options:: Other options.
+@end menu
+
+
+@node Fontconvert output options, Character selection options, , Invoking Fontconvert
+@subsection Fontconvert output options
+
+@cindex Fontconvert output formats
+@cindex output formats
+@cindex formats, Fontconvert output
+
+The following table describes the options which affect the output
+file(s) Fontconvert writes. You can specify as many as you like. If
+you don't specify any, the default is to write nothing at all.
+
+In the following, @var{font-name} stands for the root part of the main
+input file (@pxref{Main input file}). The output filenames here are the
+defaults; you can override them with the @samp{-output-file} option
+(@pxref{Miscellaneous options}).
+
+@table @samp
+
+@opindex -epsf
+@cindex EPS
+@cindex Encapsulated PostScript
+@item -epsf
+Output each character in the font as an Encapsulated PostScript (EPS)
+file named @file{@var{font-name}-@var{code}.eps}, where @var{code} is
+the character code (in decimal). This may be useful if the input
+``font'' is actually a collection of images.
+
+@opindex -gf
+@cindex GF output
+@flindex x @r{prefix}
+@item -gf
+Output a GF font @file{@var{font-name}.@var{dpi}gf}, where @var{dpi} is
+the resolution of the input font in dots per inch. If this would
+overwrite the input file (presumably because it, too, is a GF font),
+then prepend @samp{x} to the output name.
+
+This is mainly useful in conjunction with options that change the
+characters in the input font in some way.
+
+@opindex -text
+@cindex text output
+@cindex bitmaps, viewing
+@cindex GFtype
+@cindex PKtype
+@item -text
+Write the output in a human-readable plain text form to standard output.
+The bitmap for each character is shown using @samp{*} and @samp{ }.
+This is an easy way to see what output is being generated, without going
+to the trouble of running @TeX{} and a DVI driver. (The standard @TeX{}
+programs GFtype and PKtype, which serve a similar purpose, do not always
+write the entire bitmap.)
+
+@opindex -tfm
+@cindex TFM output
+@item -tfm
+Write a TFM file to @file{@var{font-name}.tfm}. If a TFM file
+@file{@var{font-name}.tfm} can be found, it is read, and an @samp{x} is
+prepended to the output name.
+
+If an existing TFM file is found, then Fontconvert uses it (by default)
+for the TFM header information, and for the ligature and kern
+information. Unless the @samp{-baseline-adjust}, @samp{-column-split},
+filtering, or randomizing options were specified, Fontconvert also uses
+it for the character dimensions. (Those options radically change the
+appearance and size of the characters, so using the dimensions of the
+originals would be inappropriate.)
+
+@xref{Fontwide information options}, for how to specify the global TFM
+information yourself, overriding the default.
+
+@end table
+
+
+@node Character selection options, Character manipulation options, Fontconvert output options, Invoking Fontconvert
+@subsection Character selection options
+
+@cindex character selection
+@cindex selection, of characters
+
+The following table describes the options which affect the set of
+characters Fontconvert writes.
+
+@table @samp
+
+@opindex -concat
+@cindex concatenation of bitmap fonts
+@cindex bitmap fonts, concatenating
+@cindex font concatenation
+@item -concat @var{font1},@var{font2},@dots{}
+After processing the main input file (@pxref{Main input file}), process
+the additional fonts @var{font1}, @var{font2}, etc. Multiple
+@samp{-concat} options do combine, e.g., @samp{-concat @var{font1}
+-concat @var{font2}} is the same as @samp{-concat
+@var{font1},@var{font2}}.
+
+@cindex duplicated characters
+@cindex repeated characters
+@cindex characters, duplicated
+@cindex characters, repeated
+If a character appears in more than one font, its first appearance is
+the one that counts. Fontconvert issues a warning about such repeated
+characters.
+
+The design size, resolution, and other global information in the output
+font is always taken from the main input font, not from the concatenated
+fonts.
+
+@opindex -column-split
+@cindex splitting characters
+@cindex characters, splitting
+@cindex muddy images
+@item -column-split @var{charspec}@@@var{col_1},@dots{},@var{col_n}
+Split the input character at position @var{charspec} before each of the
+@var{N} @var{column}s, thus producing @var{n} new characters.
+
+The new characters have codes @var{charspec}, @math{@var{charspec}+1},
+@dots{}, @math{@var{charspec}+@var{n}}. (These character codes are
+subject to the remapping specified by @samp{-remap}; see below. Any
+previous characters at those codes are overwritten.)
+
+The bitmaps of the new characters are slices from the original
+character: 0 to column @math{@var{col_1}-1}, @dots{}, @var{col_n} to the
+bitmap width. You specify the column numbers in bitmap coordinates,
+i.e., the first column is numbered zero.
+
+To split more than one character, simply specify @samp{-column-split}
+for each.
+
+This option is useful when two different characters in a scanned image
+of a font were printed so closely together that their images overlap.
+In this case, Imageto cannot break the characters apart, because they
+are a single bounding box. But you can split them with this option; you
+have to use your best judgement for the exact column at which to split.
+(Probably judicious hand-editing with XBfe (@pxref{XBfe}) will be
+necessary after you do this.)
+
+@opindex -range
+@item -range @var{char1}-@var{char2}
+Only output characters with codes between @var{char1} and @var{char2},
+inclusive. (@xref{Common options}, and @ref{Specifying character codes}.)
+
+@opindex -omit
+@cindex omitting characters
+@cindex characters, omitting
+@cindex deleting characters
+@cindex characters, deleting
+@item -omit @var{charspec1},@var{charspec2},@dots{}
+Omit the characters with the specified codes (before remapping) from the
+output. Multiple @samp{-omit} options combine.
+
+@opindex -remap
+@cindex remapping characters
+@cindex characters, remapping
+@cindex translating characters
+@cindex characters, translating
+@item -remap @var{src1}:@var{dest1},@var{src2}:@var{dest2},@dots{}
+For each pair of character specifications @var{src}/@var{dest}, change
+the character with code @var{src} in the input font to have code
+@var{dest} in the output.
+
+@end table
+
+
+@node Character manipulation options, Fontwide information options, Character selection options, Invoking Fontconvert
+@subsection Character manipulation options
+
+The following options affect individual characters.
+
+When any of them are specified, the dimensions of the output character
+are likely to be quite different than those of the input characters;
+therefore, Fontconvert does not copy the TFM information (when writing a
+TFM file) from an existing TFM file.
+
+@table @samp
+
+@opindex -baseline-adjust
+@cindex baseline adjustment
+@cindex adjustment, to baseline
+@item -baseline-adjust @var{code1}:@var{delta1},@var{code2}:@var{delta2},@dots{}
+Adjust the baseline of the output (i.e., after remapping) character
+@var{code} by the corresponding @var{delta}. A negative @var{delta}
+moves the baseline down, a positive one up. Multiple
+@samp{-baseline-adjust} options combine.
+
+@opindex -filter-passes
+@opindex -filter-size
+@opindex -filter-threshold
+@cindex smoothing bitmaps
+@cindex filtering bitmaps
+@cindex bitmaps, filtering
+@cindex averaging filter
+@item -filter-passes @var{passes}
+@itemx -filter-size @var{half-cell-size}
+@itemx -filter-threshold @var{intensity}
+Run each character through an ``averaging filter'' @var{passes} times.
+This tends to smooth rough edges on characters or irregular curves. By
+the same token, it tends to shrink or eliminate small features, such as
+serifs. Experimentation is necessary to determine the best values for
+any particular font.
+
+For the pixel at coordinate @math{(x,y)}, Fontconvert looks at its
+neighbors in rows @math{y} @minus{} @var{half-cell-size}, @dots{},
+@math{y-1}, @math{y+1}, @dots{}, @math{y} + @var{half-cell-size}, and
+similarly for the columns.
+
+Fontconvert computes the average intensity of this square; if the result
+is greater than @var{intensity}, it outputs a black pixel at
+@math{(x,y)}; a white one, otherwise.
+
+This process is repeated for every pixel in every character, and every
+character is filtered @var{passes} times.
+
+The default is to do no filtering, i.e., @var{passes} is zero. The
+default for @var{half-cell-size} is one; the default for @var{intensity}
+is @math{.5}.
+
+@opindex -random
+@opindex -random-threshold
+@cindex randomizing bitmaps
+@cindex bitmaps, randomizing
+@cindex distorting characters
+@item -random @var{distance}
+@itemx -random-threshold @var{probability}
+In every character, randomly move each black pixel. We implemented this
+as part of our research (to see how much characters could be distorted
+before they became noticeably harder to read---the answer is a lot), but
+left it in the program for its amusement value.
+
+For each black pixel, a first random number between zero and one is
+compared to @var{probability}. If it is greater, nothing happens.
+Otherwise, a second random number is chosen, this one between
+@math{-@var{distance}} and @var{distance}. The pixel is ``moved'' that
+far horizontally. Then repeat for the vertical axis.
+
+The default is to do no randomization, i.e., @var{distance} is zero.
+The default for @var{probability} is @math{.2}.
+
+@end table
+
+
+@node Fontwide information options, Miscellaneous options, Character manipulation options, Invoking Fontconvert
+@subsection Fontwide information options
+
+These options provide a way for you to set the global information in TFM
+and GF files. They override the default values (which are taken from
+the input bitmap or TFM files).
+
+@table @samp
+
+@opindex -designsize
+@cindex designsize
+@cindex font size
+@item -designsize @var{real}
+Set the design size in both the TFM and GF output files to @var{real}.
+You give @var{real} in printer's points.
+
+You might want to use this after seeing the Metafont or PostScript fonts
+output by BZRto, and deciding they look too small. For example, the
+original Garamond type specimen we scanned was (nominally) printed in
+30@dmn{pt}. But when scaled down to 10@dmn{pt} via Metafont, the
+characters looked too small. So we ran Fontconvert with
+@samp{-designsize=26} on the bitmap font made from the original image,
+and then reran Limn, BZRto, and Metafont to see the result. (We settled
+on 26 after several trials.) @xref{Creating fonts}, for a description
+of all the steps in creating fonts from scanned images.
+
+@opindex -fontdimens
+@item -fontdimens @var{fd1}:@var{value1},@var{fd2}:@var{value2},@dots{}
+@xref{TFM fontdimens}.
+
+@opindex -tfm-header
+@cindex TFM header bytes
+@cindex header bytes in TFM
+@item -tfm-header @var{name1}:@var{value1},@var{name2}:@var{value2},@dots{}
+Assign each @var{value} to the corresponding @var{name} in the header
+information written to the TFM file. The standard @TeX{} names are
+recognized:
+
+@table @samp
+
+@cindex checksum, specifying in TFM header
+@item checksum
+The corresponding @var{value} should be an unsigned integer, which should
+uniquely identify this TFM file. A checksum of zero disables testing.
+The default is zero.
+
+@cindex design size, specifying in TFM header
+@item designsize
+The corresponding @var{value} should be a real number between 1 and 2048
+(this limit is in the TFM file format). This overrides (for the TFM
+output only) the @samp{-designsize} option, if both are specified. The
+default is the design size of the input.
+
+@cindex codingscheme, specifying in TFM header
+@item codingscheme
+The corresponding @var{value} should be a string of length less than 40,
+containing no parentheses or commas. Again, these restrictions are due
+to the TFM file format. This coding scheme declares the font's
+encoding vector. @xref{Coding scheme map file}.
+
+@end table
+
+@end table
+
+
+@node Miscellaneous options, , Fontwide information options, Invoking Fontconvert
+@subsection Miscellaneous options
+
+These options are the generic ones accepted by most (in some cases, all)
+programs. @xref{Common options}.
+
+@table @samp
+
+@opindex -dpi
+@item -dpi @var{unsigned}
+The resolution of the main input font, in pixels per inch.
+
+@opindex -encoding
+@cindex encoding of input fonts
+@item -encoding @var{enc-file}
+The encoding file to read for the mapping between character names and
+character codes. @xref{Encoding files}. If @var{enc-file} has no
+suffix, @samp{.enc} is appended. There is no default. Without an
+encoding file, the options listed in @ref{Character selection options}
+which take character specs will just complain if you supply character
+names, instead of character codes.
+
+@opindex -help
+@item -help
+Print a usage message. @xref{Common options}.
+
+@item -output-file @var{filename}
+@opindex -output-file
+@cindex output file, naming
+If @var{filename} has a suffix and if only one output file is to be
+written, write to @var{filename}. If @var{filename} has a suffix and
+you've specified options which imply more than one output file,
+Fontconvert complains and gives up.
+
+If @var{filename} does not have a suffix, extend @var{filename} with
+whatever is appropriate for the output format(s). In the case of GF and
+TFM output, if this would overwrite the input, prepend an @samp{x} to
+the output name.
+
+By default, use the name of the main input font for @var{filename}.
+
+@item -verbose
+@opindex -verbose
+Output progress reports.
+
+@item -version
+@opindex -version
+Print the version number.
+
+@end table
diff --git a/doc/fontu.texi b/doc/fontu.texi
new file mode 100644
index 0000000..a4deb01
--- /dev/null
+++ b/doc/fontu.texi
@@ -0,0 +1,395 @@
+\input texinfo
+@c %**start of header
+@setfilename fontu.info
+@settitle GNU font utilities
+@c %**end of header
+
+@c Define new indices for commands in auxiliary files, filenames, and options.
+@defcodeindex cm
+@defcodeindex fl
+@defcodeindex op
+
+@c Put everything in one index (arbitrarily chosen to be the concept index).
+@syncodeindex cm cp
+@syncodeindex fl cp
+@syncodeindex fn cp
+@syncodeindex ky cp
+@syncodeindex op cp
+@syncodeindex pg cp
+@syncodeindex vr cp
+
+@c Here is what we use in the Info `dir' file:
+@c * Fontutils: (fontu). Programs for font manipulation.
+
+
+@ifinfo
+This file documents the GNU font utilities.
+
+Copyright (C) 1992, 93 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries a copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+@end ignore
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+sections entitled ``Freedom'' and ``GNU General Public License'' are
+included exactly as in the original, and provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that the sections entitled ``Freedom'' and ``GNU General Public
+License'' may be included in a translation approved by the Free Software
+Foundation instead of in the original English.
+@end ifinfo
+
+
+@titlepage
+
+@title GNU font utilities
+@subtitle for version REPLACE-WITH-VERSION
+@subtitle REPLACE-WITH-MONTH-YEAR
+@author Karl Berry
+@author with Kathryn A. Hargreaves
+
+@page
+
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1992 Free Software Foundation.
+
+Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+sections entitled ``Regain your programming freedom'' and ``GNU General
+Public License'' are included exactly as in the original, and provided
+that the entire resulting derived work is distributed under the terms of
+a permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that the sections entitled ``Regain your programming freedom''
+and ``GNU General Public License'' may be included in a translation
+approved by the Free Software Foundation instead of in the original English.
+
+@end titlepage
+
+
+@ifinfo
+@node Top, Introduction, (dir), (dir)
+@top GNU font utilities
+
+This manual documents how to install and run the GNU font utilities. It
+corresponds to version REPLACE-WITH-VERSION (released in
+REPLACE-WITH-MONTH-YEAR).
+
+The introduction briefly describes the purpose and philosophy of the
+font utilities. The overview gives details on their general usage,
+especially how they interact, and describes various things which are
+common to all or most of the programs.
+
+The first part of this master menu lists the major nodes in this Info
+document, including the index. The rest of the menu lists all the
+lower level nodes in the document.
+
+@menu
+* Introduction:: A brief introduction.
+* Installation:: How to compile and install the font utilities.
+* Overview:: Commonalities to the programs,
+ a roadmap to how they fit together,
+ and examples of usage.
+* Bugs:: How, why, and where to report bugs.
+* File formats:: These programs read and write many files.
+* Imageto:: Extracting a font from a scanned image.
+* IMGrotate:: Rotating an image.
+* Fontconvert:: Manipulation of bitmap fonts.
+* Charspace:: Adding character metrics to a font.
+* Limn:: Making outlines from bitmaps.
+* BZRto:: Converting generic outlines to other formats.
+* BPLtoBZR:: Converting plain text to binary BZR fonts.
+* XBfe:: Hand editor for bitmap fonts under X11.
+* BZRedit:: Hand editor for outline fonts under Emacs.
+* GSrenderfont:: Rasterize PostScript fonts.
+* Enhancements:: Future projects.
+* Copying:: Conditions for copying and sharing.
+* Freedom:: Regain your programming freedom.
+* Index:: General index.
+
+ --- The Detailed Node Listing ---
+
+Installation
+
+* Prereqs:: What's needed before installation.
+* Problems:: Known trouble.
+
+Prerequisites
+
+* Archives:: Where to find programs.
+
+Overview
+
+* Picture:: A pictorial overview.
+* Creating fonts:: How to use the programs together.
+* Command-line options:: Many aspects of the command line are
+ common to all programs.
+* Font searching:: How fonts and other files are looked for.
+* Font naming:: How to name fonts.
+
+Creating fonts
+
+* Font creation example:: A real-life example.
+
+Command-line options
+
+* Main input file:: Each program operates on a ``main'' font.
+* Options: Common options. Some options are accepted by all programs.
+* Specifying character codes:: Ways of specifying single characters.
+* Values: Common option values. Some options need more information.
+
+Specifying character codes
+
+* Named character codes:: Character names are looked up in the encoding.
+* Numeric character codes:: Decimal, octal, hex, or ASCII.
+
+Bugs
+
+* Bug criteria:: Have you found a bug?
+* Bug reporting:: How to effectively report a bug.
+
+Bug reporting
+
+* Necessary information:: What you need to send.
+* Unnecessary information:: What you don't need to send.
+* Documentation bugs:: Report the bugs in the manual, too.
+
+File formats
+
+* File format abbreviations:: The alphabet soup of font formats.
+* Common file syntax:: Some elements of auxiliary files are constant.
+* Encoding files:: The character code-to-shape mapping.
+* Coding scheme map file:: The coding scheme string-to-filename mapping.
+
+Encoding files
+
+* Character names:: How to write character names.
+* Ligature definitions:: How to define ligatures.
+* GNU encodings:: Why we invented new encodings for GNU.
+
+Imageto
+
+* Imageto usage:: Process for extracting fonts from an image.
+* IFI files:: IFI files supply extra information.
+* Invoking Imageto:: Command-line options.
+
+Imageto usage
+
+* Viewing an image:: Seeing what's in an image.
+* Image to font conversion:: Extracting a font.
+* Dirty images:: Handling scanning artifacts or other noise.
+
+IMGrotate
+
+* IMGrotate usage:: Doing the image rotation.
+* Invoking IMGrotate:: Command-line options.
+
+IMGrotate usage
+
+* Clockwise rotation:: Rotating clockwise.
+* Flip rotation:: FLipping end-for-end.
+
+Fontconvert
+
+* Invoking Fontconvert:: Command-line options.
+
+Invoking Fontconvert
+
+* Fontconvert output options:: Specifying the output format(s).
+* Character selection options:: What characters to operate on.
+* Character manipulation options:: Changing characters' appearance.
+* Fontwide information options:: Changing global information in a font.
+* Miscellaneous options:: Other options.
+
+Charspace
+
+* Charspace usage:: Details on improving the character metrics.
+* CMI files:: You specify the metrics in a separate file.
+* Invoking Charspace:: Command-line options.
+
+CMI files
+
+* CMI tokens:: The building blocks of CMI files.
+* char command:: Defining a character's side bearings.
+* char-width command:: Defining side bearings via the set width.
+* define command:: Introducing a new identifier.
+* kern command:: Defining a kerning pair.
+* codingscheme command:: Specifying the font encoding.
+* fontdimen command:: Defining additional font parameters.
+* CMI processing:: How Charspace reads CMI files.
+
+@code{fontdimen} command
+
+* TFM fontdimens:: All the valid fontdimens.
+
+Limn
+
+* Limn algorithm:: How Limn fits outlines to bitmaps.
+* Invoking Limn:: Command-line options.
+
+Limn algorithm
+
+* Finding pixel outlines:: Extracting the edges from the bitmap.
+* Finding corners:: Finding subsections of each outline.
+* Removing knees:: Removing extraneous points.
+* Filtering curves:: Smoothing the outlines.
+* Fitting the bitmap curve:: Doing the fitting.
+* Changing splines to lines:: Use straight lines where possible.
+* Changing lines to splines:: Sometimes it isn't possible.
+* Aligning endpoints:: If points are close enough, line them out.
+* Displaying fitting online:: Seeing the results as Limn runs.
+
+Fitting the bitmap curve
+
+* Initializing t:: Initializing the parameter values.
+* Finding tangents:: Computing the direction of the curve at
+ the endpoints.
+* Finding the spline:: Where are the control points?
+* Reparameterization:: Changing the parameter values.
+* Subdivision:: Splitting the curve into pieces.
+
+BZRto
+
+* Metafont and BZRto:: Output as a Metafont program.
+* Type 1 and BZRto:: Output as a Type 1 PostScript font.
+* Type 3 and BZRto:: Output as a Type 3 PostScript font.
+* CCC files:: Creating additional characters.
+* Invoking BZRto:: Command-line options.
+* BZR files:: The technical definition of BZR format.
+
+Metafont and BZRto
+
+* Metafont output at any size:: Making larger or smaller fonts.
+* Proofing with Metafont:: Metafont can help with debugging fonts.
+
+CCC files
+
+* setchar: CCC setchar. Statements for including a character.
+* move: CCC move. Statements for moving to a new position.
+
+BZR files
+
+* Intro: BZR format introduction. General concepts and definitions.
+* Preamble: BZR preamble. The beginning.
+* Chars: BZR characters. The middle.
+* Postamble: BZR postamble. The end.
+
+BZR characters
+
+* BOC: BZR character beginnings. Giving character metrics.
+* Shape: BZR character shapes. Defining the outline(s).
+
+BPLtoBZR
+
+* BPL files:: Bezier property list file format.
+* Invoking BPLtoBZR:: Command-line options.
+
+BPL files
+
+* Preamble: BPL preamble. The beginning.
+* Characters: BPL characters. The middle.
+* Postamble: BPL postamble. The end.
+
+BPL characters
+
+* BPL outlines:: Representation of character outlines.
+
+XBfe
+
+* XBfe usage:: How to edit fonts.
+* Invoking XBfe:: Command-line options.
+
+XBfe usage
+
+* Controlling XBfe :: Controlling XBfe
+* Shape: XBfe shape editing. Changing the pixels.
+* Metrics: XBfe metrics editing. Changing the side bearings.
+
+XBfe shape editing
+
+* Selections:: Marking pixel regions for later operations.
+* Enlarging the bitmap:: Give yourself more room at the edges.
+
+BZRedit
+
+* BZRedit usage:: Operating the editor.
+
+BZRedit usage
+
+* BZRedit installation:: Additional installation is needed.
+* BZR: Editing BZR files. Editing files in the binary format.
+* BPL: Editing BPL files. Editing files in the textual format.
+
+Editing BPL files
+
+* BZRedit and Ghostscript:: Customizing the use of Ghostscript.
+
+GSrenderfont
+
+* GSrenderfont usage:: Making bitmap fonts from PostScript.
+* Invoking GSrenderfont:: Command-line options.
+
+GSrenderfont usage
+
+* Names: GSrenderfont font names. Supplying PostScript names and filenames.
+* Size: GSrenderfont output size. Specifying the size and resolution.
+* Encoding: GSrenderfont encoding. Specifying the output encoding.
+
+Enhancements
+
+* Additional fonts:: GNU needs more fonts.
+* Program features:: These programs can be improved.
+* Portability:: Assumptions about the programming environment.
+* Implementation:: Conventions we used in the sources.
+
+Regain your programming freedom
+
+* Software patents:: Algorithm monopolies.
+* User interface copyright:: Forbidding upward-compatibility.
+* What to do?:: What to do?
+@end menu
+@end ifinfo
+
+@include intro.texi
+@include install.texi
+@include overview.texi
+@include bugs.texi
+@include filefmts.texi
+@include imageto.texi
+@include imgrotate.texi
+@include fontcvt.texi
+@include charspace.texi
+@include limn.texi
+@include bzrto.texi
+@include bpltobzr.texi
+@include xbfe.texi
+@include bzredit.texi
+@include gsrenderf.texi
+@include enhance.texi
+@include copying.texi
+@include freedom.texi
+@include index.texi
+
+@summarycontents
+@contents
+
+@bye
diff --git a/doc/freedom.texi b/doc/freedom.texi
new file mode 100644
index 0000000..c8a09b7
--- /dev/null
+++ b/doc/freedom.texi
@@ -0,0 +1,268 @@
+@c Copyright (C) 1992 Karl Berry.
+@c For copying conditions, see the file copying.texi.
+
+@node Freedom, Index, Copying, Top
+@appendix Regain your programming freedom
+
+@cindex freedom, programming
+Until a few years ago, programmers in the United States could write any
+program they wished. This freedom has now been taken away by two
+developments: software patents, which grant the patent holder an
+absolute monopoly on some programming technique, and user interface
+copyright, which forbid compatible implementations of an existing user
+interface.
+
+In Europe, especially through the GATT treaty, things are rapidly
+approaching the same pass.
+
+@menu
+* Software patents:: Algorithm monopolies.
+* User interface copyright:: Forbidding upward-compatibility.
+* What to do?:: What to do?
+@end menu
+
+
+@node Software patents, User interface copyright, , Freedom
+@section Software patents
+
+@cindex patents, software
+@cindex software patents
+
+The U.S. Patent and Trademark Office has granted numerous software
+patents on software techniques. Patents are an absolute
+monopoly---independent reinvention is precluded. This monopoly lasts
+for seventeen years, i.e., forever (with respect to computer science).
+
+One patent relevant to @TeX{} is patent 4,956,809, issued to the Mark
+Williams company on September 11, 1990, applied for in 1982, which
+covers (among other things)
+@quotation
+representing in a standardized order
+consisting of a standard binary structure file stored on auxiliary
+memory or transported on a communications means, said standardized
+order being different from a different order used on at least one
+of the different computers;
+
+Converting in each of the different computers binary data read from an
+auxiliary data storage or communications means from the standardized
+order to the natural order of the respective host computer after said
+binary data are read from said auxiliary data storage or
+communications means and before said binary data are used by the
+respective host computer; and
+
+Converting in each of the different computers binary data written into
+auxiliary data storage or communications means from the natural order
+of the respective host computer to the standardized order prior to
+said writing.
+@end quotation
+
+@noindent @dots{} in other words, storing data on disk in
+a machine-independent order, as the DVI, TFM, GF, and PK file formats
+specify. Even though @TeX{} is ``prior art'' in this respect, the
+patent was granted (the patent examiners not being computer scientists,
+even less computer typographers). Since there is a strong presumption
+in the courts of a patent's validity once it has been granted, there is
+a good chance that users or implementors of @TeX{} could be successfully
+sued on the issue.
+
+As another example, the X window system, which was intended to be able
+to be used freely by everyone, is now being threatened by two patents:
+4,197,590 on the use of exclusive-or to redraw cursors, held by Cadtrak,
+a litigation company (this has been upheld twice in court); and
+4,555,775, held by AT&T, on the use of backing store to redraw windows
+quickly.
+
+Here is one excerpt from a recent mailing by the League for Programming
+Freedom (@pxref{What to do?}) which I feel sums up the situation rather
+well. It comes from an article in @cite{Think} magazine, issue #5,
+1990. The comments after the quote were written by Richard Stallman.
+
+@quotation
+ ``You get value from patents in two ways,'' says Roger Smith, IBM
+ Assistant General Counsel, intellectual property law. ``Through fees,
+ and through licensing negotiations that give IBM access to other
+ patents.
+
+ ``The IBM patent portfolio gains us the freedom to do what we need to
+ do through cross-licensing---it gives us access to the inventions of
+ others that are the key to rapid innovation. Access is far more
+ valuable to IBM than the fees it receives from its 9,000 active
+ patents. There's no direct calculation of this value, but it's many
+ times larger than the fee income, perhaps an order of magnitude
+ larger.''
+@end quotation
+
+This information should dispel the belief that the patent system will
+``protect'' a small software developer from competition from IBM. IBM
+can always find patents in its collection which the small developer is
+infringing, and thus obtain a cross-license.
+
+However, the patent system does cause trouble for the smaller
+companies which, like IBM, need access to patented techniques in order
+to do useful work in software. Unlike IBM, the smaller companies do
+not have 9,000 patents and cannot usually get a cross-license. No
+matter how hard they try, they cannot have enough patents to do this.
+
+Only the elimination of patents from the software field can enable
+most software developers to continue with their work.
+
+The value IBM gets from cross-licensing is a measure of the amount of
+harm that the patent system would do to IBM if IBM could not avoid it.
+IBM's estimate is that the trouble could easily be ten times the good
+one can expect from one's own patents---even for a company with 9,000
+of them.
+
+
+@node User interface copyright, What to do?, Software patents, Freedom
+@section User interface copyright
+
+@cindex rms
+@cindex user interface copyright
+@cindex interface copyright
+(This section is copied from the GCC manual, by Richard Stallman.)
+
+@quotation
+@i{This section is a political message from the League for Programming
+Freedom to the users of the GNU font utilities. It is included here as
+an expression of support for the League on my part.}
+@end quotation
+
+Apple, Lotus and Xerox are trying to create a new form of
+legal monopoly: a copyright on a class of user interfaces. These
+monopolies would cause serious problems for users and developers of
+computer software and systems.
+
+Until a few years ago, the law seemed clear: no one could restrict
+others from using a user interface; programmers were free to implement
+any interface they chose. Imitating interfaces, sometimes with changes,
+was standard practice in the computer field. The interfaces we know
+evolved gradually in this way; for example, the Macintosh user interface
+drew ideas from the Xerox interface, which in turn drew on work done at
+Stanford and SRI. 1-2-3 imitated VisiCalc, and dBase imitated a
+database program from JPL.
+
+Most computer companies, and nearly all computer users, were happy with
+this state of affairs. The companies that are suing say it does not
+offer ``enough incentive'' to develop their products, but they must have
+considered it ``enough'' when they made their decision to do so. It
+seems they are not satisfied with the opportunity to continue to compete
+in the marketplace---not even with a head start.
+
+If Xerox, Lotus, and Apple are permitted to make law through
+the courts, the precedent will hobble the software industry:
+
+@itemize @bullet
+@item
+Gratuitous incompatibilities will burden users. Imagine if each
+car manufacturer had to arrange the pedals in a different order.
+
+@item
+Software will become and remain more expensive. Users will be
+``locked in'' to proprietary interfaces, for which there is no real
+competition.
+
+@item
+Large companies have an unfair advantage wherever lawsuits become
+commonplace. Since they can easily afford to sue, they can intimidate
+small companies with threats even when they don't really have a case.
+
+@item
+User interface improvements will come slower, since incremental
+evolution through creative imitation will no longer be permitted.
+
+@item
+Even Apple, etc., will find it harder to make improvements if
+they can no longer adapt the good ideas that others introduce, for
+fear of weakening their own legal positions. Some users suggest that
+this stagnation may already have started.
+
+@item
+If you use GNU software, you might find it of some concern that user
+interface copyright will make it hard for the Free Software Foundation
+to develop programs compatible with the interfaces that you already
+know.
+@end itemize
+
+
+@node What to do?, , User interface copyright, Freedom
+@section What to do?
+
+(This section is copied from the GCC manual, by Richard Stallman.)
+
+To protect our freedom from lawsuits like these, a group of programmers
+and users have formed a new grass-roots political organization, the
+League for Programming Freedom.
+
+The purpose of the League is to oppose new monopolistic practices such
+as user-interface copyright and software patents; it calls for a return
+to the legal policies of the recent past, in which these practices were
+not allowed. The League is not concerned with free software as an
+issue, and not affiliated with the Free Software Foundation.
+
+The League's membership rolls include John McCarthy, inventor of Lisp,
+Marvin Minsky, founder of the Artificial Intelligence lab, Guy L.
+Steele, Jr., author of well-known books on Lisp and C, as well as
+Richard Stallman, the developer of GNU CC. Please join and add your
+name to the list. Membership dues in the League are $42 per year for
+programmers, managers and professionals; $10.50 for students; $21 for
+others.
+
+The League needs both activist members and members who only pay their
+dues.
+
+To join, or for more information, phone (617) 492-0023 or write to:
+
+@display
+League for Programming Freedom
+1 Kendall Square #143
+P.O. Box 9171
+Cambridge, MA 02139
+@end display
+
+You can also send electronic mail to @code{league@@prep.ai.mit.edu}.
+
+Here are some suggestions from the League for things you can do to
+protect your freedom to write programs:
+
+@itemize @bullet
+@item
+Don't buy from Xerox, Lotus or Apple. Buy from their competitors or
+from the defendants they are suing.
+
+@item
+Don't develop software to work with the systems made by these companies.
+
+@item
+Port your existing software to competing systems, so that you encourage
+users to switch.
+
+@item
+Write letters to company presidents to let them know their conduct
+is unacceptable.
+
+@item
+Tell your friends and colleagues about this issue and how it threatens
+to ruin the computer industry.
+
+@item
+Above all, don't work for the look-and-feel plaintiffs, and don't
+accept contracts from them.
+
+@item
+Write to Congress to explain the importance of this issue.
+
+@display
+House Subcommittee on Intellectual Property
+2137 Rayburn Bldg
+Washington, DC 20515
+
+Senate Subcommittee on Patents, Trademarks and Copyrights
+United States Senate
+Washington, DC 20510
+@end display
+
+(These committees have received lots of mail already; let's give them
+even more.)
+@end itemize
+
+Express your opinion! You can make a difference.
diff --git a/doc/gsrenderf.texi b/doc/gsrenderf.texi
new file mode 100644
index 0000000..a7896cd
--- /dev/null
+++ b/doc/gsrenderf.texi
@@ -0,0 +1,246 @@
+@c Copyright (C) 1992, 93 Free Software Foundation.
+@c This is part of the GNU font utilities manual.
+@c For copying conditions, see the file fontutil.texi.
+
+@node GSrenderfont, Enhancements, BZRedit, Top
+@chapter GSrenderfont
+
+@pindex gsrenderfont
+@cindex converting PostScript fonts to bitmaps
+@cindex bitmap fonts, making from PostScript
+@cindex PostScript fonts, converting to bitmaps
+@cindex previewing @TeX{} documents with PostScript fonts
+@cindex DVI files with PostScript fonts, previewing
+@cindex @TeX{} documents with PostScript fonts, previewing
+@cindex Ghostscript, prerequisite for GSrenderfont
+
+GSrenderfont uses Ghostscript to rasterize a PostScript outline font at
+a particular point size and resolution. The final result is a bitmap
+font in PK form, which can be used by any DVI-processing program, unlike
+the original PostScript font. In particular, you can then use your
+favorite previewer with @TeX{} documents which use PostScript fonts.
+
+@pindex ghostview
+An alternative to using such PK fonts is to use a DVI-to-PostScript
+translator and then use Ghostscript or Ghostview directly on the result.
+The PostScript file consumes quite a bit of disk space, however; also,
+the extra step after running @TeX{} can be quite inconvenient.
+
+@pindex ps2pk
+An alternative to using GSrenderfont is the standalone C program
+@code{ps2pk}. It does the same job: rasterizing PostScript fonts. It
+is available by ftp from @samp{ftp.urc.tue.nl}.
+
+@flindex gsrenderfont/main.c
+@cindex GSrenderfont, prerequisites for
+@pindex awk
+@pindex gawk
+@pindex bbcount
+@pindex gftopk
+@pindex tail
+@pindex wc
+@cindex Imageto, used by GSrenderfont
+Besides Ghostscript, GSrenderfont uses @code{gawk} (GNU Awk), the
+standard Unix utilities @code{tail} and @code{wc}, the standard @TeX{}
+utility @code{gftopk}, another programs from this distribution
+(Imageto), and one small program written expressly for it,
+@code{bbcount}. Since this last is of doubtful value for anything but
+GSrenderfont, it is not documented here. See @file{gsrenderfont/main.c}
+if you are interested in what it does.
+
+GSrenderfont has nothing in particular to do with the main task of
+creating typefaces, but it seemed a small enough job (given the other
+programs' existence) and widely enough asked for to be worthwhile.
+
+@menu
+* GSrenderfont usage:: Making bitmap fonts from PostScript.
+* Invoking GSrenderfont:: Command-line options.
+@end menu
+
+
+@node GSrenderfont usage, Invoking GSrenderfont, , GSrenderfont
+@section GSrenderfont usage
+
+@cindex GSrenderfont usage
+@cindex usage of GSrenderfont
+
+GSrenderfont needs several bits of information to do its job, as
+described in the sections below.
+
+@menu
+* Names: GSrenderfont font names. Supplying PostScript names and filenames.
+* Size: GSrenderfont output size. Specifying the size and resolution.
+* Encoding: GSrenderfont encoding. Specifying the output encoding.
+@end menu
+
+
+@node GSrenderfont font names, GSrenderfont output size, , GSrenderfont usage
+@subsection GSrenderfont font names
+
+@cindex font names in GSrenderfont
+@cindex GSrenderfont font names
+@cindex names of fonts in GSrenderfont
+
+@cindex PostScript font names, as filenames
+GSrenderfont needs two names to do its job: the PostScript font name
+(e.g., @samp{Times-Roman}), and the output filename (e.g., @file{ptmr}).
+(The PostScript font name cannot also be used as the filename because of
+its length. At best, the result would be unwieldy, and at worst,
+invalid because of operating system restrictions.) If the font is not
+known to Ghostscript (i.e., in its @file{Fontmap}
+@flindex Fontmap
+file), then an input filename is also needed.
+
+@opindex -font
+@opindex -output-file
+You can explicitly specify the first with the @samp{-font} option, the
+second with the @samp{-output-file} option, and the third with a
+non-option argument. If you specify them all, as in
+
+@example
+gsrenderfont -font=Myfont -out=test myfont.ps
+@end example
+
+@noindent then GSrenderfont simply uses what you've given.
+
+@opindex -map
+@flindex psfonts.map
+@flindex /usr/local/lib/tex/dvips/psfonts.map
+@cindex mapping file for PostScript fonts
+@cindex PostScript fonts, mapping file for
+But if you specify only the font name or the input filename,
+GSrenderfont tries to guess the other using a @dfn{mapping file}. On
+each line of this file the first (whitespace-delimited) @dfn{word} is
+the filename (possibly preceded by an @samp{r}; @pxref{Top, ,
+Introduction, fontname, Filenames for fonts}, for why), the second word
+is the PostScript font name, and any remaining stuff is ignored. Unlike
+the other data files, GSrenderfont does not use path searching to find
+this file; it just uses the default:
+
+@example
+/usr/local/lib/tex/dvips/psfonts.map
+@end example
+
+@noindent
+unless you specify a different file with the @samp{-map} option. The
+reason for this is that @file{psfonts.map} should contain all the
+PostScript fonts in use at your site.
+
+GSrenderfont complains and gives up if you specify neither the
+PostScript font name nor the input filename. It also gives up if it
+can't determine the filename from the PostScript name or vice versa.
+
+The default for the output filename is the input filename.
+
+
+@node GSrenderfont output size, GSrenderfont encoding, GSrenderfont font names, GSrenderfont usage
+@subsection GSrenderfont output size
+
+@cindex point size of GSrenderfont output
+@cindex resolution of GSrenderfont output
+@cindex GSrenderfont output, resolution of
+
+@opindex -point-size
+@opindex -dpi
+For convenience, GSrenderfont allows you to independently specify the
+point size and the resolution of the output font: the @samp{-point-size}
+option, as an integer in points, and the latter with
+@samp{-dpi} in pixels per inch. The defaults are 10@dmn{pt} and
+300@dmn{dpi}.
+
+@cindex PostScript font size, default
+@cindex default PostScript font size
+Because PostScript fonts are (in practice) linearly scaled, however,
+GSrenderfont does not put the point size in the output filename.
+Instead, it simply computes the final resolution as the @samp{dpi}
+multiplied by the @samp{point-size} divided by 10. This assumes that
+the default size of the fonts as used in @TeX{} is 10@dmn{pt}, which is
+true for the PostScript fonts distributed with Dvips.
+
+For example, supposing the output filename is @file{ptmr}, and you
+specify @samp{-point-size=12}, the bitmap font will be named
+@file{ptmr.360pk}.
+
+
+@node GSrenderfont encoding, , GSrenderfont output size, GSrenderfont usage
+@subsection GSrenderfont encoding
+
+@cindex GSrenderfont output encoding
+@cindex encoding, with GSrenderfont
+@cindex font encoding, with GSrenderfont
+
+You specify the encoding for the new bitmap font with the
+@samp{-encoding} option; the default is to use the encoding of the input
+font. GSrenderfont reads the same encoding files as the other programs.
+@xref{Encoding files}.
+
+As with all other data files in the other programs, GSrenderfont
+searches for the encoding file using the path specified by the
+environment variable @code{FONTUTIL_LIB} if it is set; otherwise it uses
+the default path set during compilation. @xref{Font searching}, for the
+details of the path searching algorithm.
+
+
+@node Invoking GSrenderfont, , GSrenderfont usage, GSrenderfont
+@section Invoking GSrenderfont
+
+@cindex GSrenderfont options
+@cindex invocation of GSrenderfont
+@cindex options for GSrenderfont
+
+This section describes the options that GSrenderfont accepts.
+@xref{Command-line options}, for general option syntax.
+
+You must specify either @samp{-font} or a single non-option
+argument, so GSrenderfont knows what font to work on. See the previous
+section for more details.
+
+@table @samp
+
+@opindex -dpi
+@item -dpi @var{unsigned}
+Render the output at a resolution of @var{unsigned} pixels per inch;
+default is 300.
+
+@opindex -encoding
+@cindex data file searching
+@item -encoding @var{scheme}
+Read @file{@var{scheme}.enc} to define the encoding of the output font;
+default is @file{dvips}.
+
+@opindex -font
+@item -font @var{FontName}
+Render the PostScript font @var{FontName} (e.g., @samp{Times-Roman}).
+
+@opindex -help
+@item -help
+Print a usage message. @xref{Common options}.
+
+@opindex -map
+@flindex psfonts.map
+@item -map @var{filename}
+Use @var{filename} for the filename-to-PostScript name mapping file;
+default is
+
+@example
+/usr/local/lib/tex/dvips/psfonts.map
+@end example
+
+@item -output-file @var{filename}
+@opindex -output-file
+@cindex output file, naming
+Use @file{@var{filename}.@var{dpi}pk} for the final PK output.
+
+@opindex -point-size
+@item -point-size @var{unsigned}
+Render the output at @var{unsigned} points; default is 10.
+
+@opindex -verbose
+@item -verbose
+Output progress reports.
+
+@opindex -version
+@item -version
+Print the version number.
+
+@end table
diff --git a/doc/imageto.texi b/doc/imageto.texi
new file mode 100644
index 0000000..1d9e95c
--- /dev/null
+++ b/doc/imageto.texi
@@ -0,0 +1,518 @@
+@c Copyright (C) 1992 Free Software Foundation.
+@c This is part of the GNU font utilities manual.
+@c For copying conditions, see the file fontutil.texi.
+
+@node Imageto, IMGrotate, File formats, Top
+@chapter Imageto
+
+@pindex imageto
+
+Imageto converts an image file (currently either in portable bitmap
+format (PBM) or GEM's IMG format) to either a bitmap font or an Encapsulated
+PostScript file (EPSF). An @dfn{image file} is simply a large bitmap.
+
+If the output is a font, it can be constructed either by outputting a
+constant number of scanlines from the image as each ``character'' or
+(more usually) by extracting the ``real'' characters from the image.
+
+@cindex image input formats
+The current selection of input formats is rather arbitrary. We
+implemented the IMG format because that is what our scanner outputs, and
+the PBM format because Ghostscript can output it (@pxref{GSrenderfont}).
+Other formats could easily be added.
+
+@menu
+* Imageto usage:: Process for extracting fonts from an image.
+* IFI files:: IFI files supply extra information.
+* Invoking Imageto:: Command-line options.
+@end menu
+
+
+@node Imageto usage, IFI files, , Imageto
+@section Imageto usage
+
+@cindex Imageto usage
+@cindex usage of Imageto
+
+Usually there are two prerequisites to extracting a usable font from an
+image file. First, looking at the image, so you can see what you've
+got. Second, preparing the IFI file describing the contents of the
+image: the character codes to output, any baseline adjustment (as for,
+e.g., @samp{j}), and how many pieces each character has. Each
+is a separate invocation of Imageto; the first time with either the
+@samp{-strips} or @samp{-epsf} option, the second time with neither.
+
+@cindex scanlines, definition of
+@cindex image rows, definition of
+@cindex bounding boxes in Imageto
+In the second step, Imageto considers the input image as a series of
+@dfn{image rows}. Each image row consists of all the scanlines between
+a nonblank scanline and the next entirely blank scanline. (A
+@dfn{scanline} is a single horizontal row of pixels in the image.)
+Within each image row, Imageto looks top-to-bottom, left-to-right, for
+@dfn{bounding boxes}: closed contours, i.e., an area whose edge
+you can trace with a pencil without lifting it.
+
+@cindex type specimen image, example of
+@cindex problems in scanned images, example
+For example, in the following image Imageto would find two image rows,
+the first from scanlines 1 to scanline 7, the second consisting of only
+scanline 10. There are six bounding boxes in the first image row, only
+one in the second. (This example also shows some typical problems in
+scanned images: the baseline of the @samp{m} is not aligned with those
+of the @samp{i}, @samp{j}, and @samp{l}; a meaningless black line is
+present; the @samp{i} and @samp{j} overlap.)
+
+@example
+ 01234567890123456789
+ 0
+ 1 x
+ 2 x x x
+ 3 x
+ 4 x x x xxxxx
+ 5 x x x x x x
+ 6 x x x x
+ 7 xx
+ 8
+ 9
+10 xxxxxxxxxxxxxxx
+@end example
+
+@menu
+* Viewing an image:: Seeing what's in an image.
+* Image to font conversion:: Extracting a font.
+* Dirty images:: Handling scanning artifacts or other noise.
+@end menu
+
+
+@node Viewing an image, Image to font conversion, , Imageto usage
+@subsection Viewing an image
+
+@cindex EPS
+@cindex Encapsulated PostScript
+@pindex gs
+@cindex Ghostscript
+
+@cindex image file, viewing
+@cindex viewing image files
+Typically, the first step in extracting a font from an image is to see
+exactly what is in the image. (Clearly, this is unnecessary if you
+already know what your image file contains.)
+
+@opindex -epsf
+@cindex Ghostscript, using to look at images
+The simplest way to get a look at the image file, if you have
+Ghostscript or some other suitable PostScript interpreter, is to convert
+the image file into an EPSF file with the @samp{-epsf} option. Here is
+a possible invocation:
+
+@example
+imageto -epsf ggmr.img
+@end example
+
+Here we read an input file @file{ggmr.img}; the output is
+@file{ggmr.eps}. You can then view the EPS file with
+
+@example
+gs ggmr.eps
+@end example
+
+@noindent (presuming that @file{gs} invokes your PostScript interpreter).
+
+@opindex -strips
+If you don't have both a suitable PostScript interpreter and enough
+disk space to store the EPS file (it uses approximately twice as much
+disk space as the original image), the above won't work. Instead, to
+view the image you must make a font with the @samp{-strips} option:
+
+@example
+imageto -strips ggmr.img
+@end example
+
+The output of this will be @file{ggmrsp.1200gf} (our image having a
+resolution of 1200 dpi). Although the GF font cannot be conveniently
+viewed directly, you can use @TeX{} and your favorite DVI processor to
+look at it, as follows:
+
+@flindex strips.tex
+@example
+fontconvert -tfm ggmrsp.1200
+echo ggmrsp | tex strips
+@end example
+
+This outputs in @file{strips.dvi}, which you can view with your favorite
+DVI driver. (@xref{Archives}, for how to obtain the DVI drivers for
+PostScript and X we recommend.)
+
+@file{strips.tex} is distributed in the @file{imageto} directory.
+
+
+@node Image to font conversion, Dirty images, Viewing an image, Imageto usage
+@subsection Image to font conversion
+
+@cindex image to font conversion
+@cindex conversion, of image to font
+@cindex extracting characters
+@cindex characters, extracting from image
+@cindex optical character recognition
+
+Once you can see what is in the image, the next step is to prepare the
+IFI file (@pxref{IFI files}) corresponding to its characters. Imageto
+relies completely on the IFI files to describe the image; it makes no
+attempt at optical character recognition, i.e., guessing what the
+characters are from their shapes.
+
+You must also decide on a few more aspects of the output font, which you
+specify with options:
+
+@itemize @bullet
+
+@item
+@cindex design size in image
+@opindex -designsize
+The @emph{design size}, which you specify with the @samp{-designsize}
+option. The default is 10@dmn{pt}. Even if you know the true design
+size of the original scanned image, you may wish to change it. For
+example, some of our original specimens were stated to be 30@dmn{pt},
+but that resulted in the 10@dmn{pt} size being too small to our
+(20th-century) eyes. So we specified a design size of 26@dmn{pt}.
+
+@item
+@cindex baselines in image
+@opindex -baselines
+@opindex -print-guidelines
+The @emph{baselines}, which you specify with the @samp{-baselines}
+option. You can specify the baseline for each image row (the bottom
+scanline of each image row is numbered zero, with coordinates increasing
+upward). You can make an adjustment for individual characters in the
+IFI files, but you save yourself at least some of this hassle by
+specifying a general baseline for each row.
+
+For instance, in the example image in @ref{Imageto usage}, it would be
+best to specify @samp{-baselines=2,0}. The @samp{2} is scanline #5 in
+that image. The @samp{0} is an arbitrary value for scanline #10, which
+we will ignore via the IFI file (@pxref{IFI files}).
+
+@opindex -print-guidelines @r{example}
+For each character written, the @samp{-print-guidelines} option produces
+output on the terminal that looks like:
+@example
+75 (K) 5/315
+@end example
+
+@noindent This means that character code 75, whose name in
+the encoding file is @samp{K}, has its bottom row at row 5, and its top
+row at row 315; i.e., the character has five blank rows above the
+origin. This is almost certainly wrong (the letter `K' should sit on
+the typesetting baseline), so we would want to adjust the baseline
+upwards to 0 via an individual character baseline adjustment of 5
+in the IFI file (@pxref{IFI files}).
+
+@end itemize
+
+The final invocation to produce the font might look something like this:
+
+@example
+imageto -baselines=121,130,120 -designsize=26 ggmr
+@end example
+
+The output from this would be @file{ggmr26.1200gf}.
+
+
+@node Dirty images, , Image to font conversion, Imageto usage
+@subsection Dirty images
+
+@cindex sex
+@cindex dirty images
+@cindex noisy images
+@cindex spots
+@cindex clean images, not having
+@cindex scanning artifacts
+@cindex artifacts, of scanning
+
+Your image may not be completely ``clean'', i.e., the scanning process
+may have introduced artifacts: black lines at the edge of the paper;
+blotches where the original had a speck of dirt or ink; broken lines
+where the image had a continuous line. To get a correct output font,
+you must correct these problems.
+
+@cindex blotches in image, ignoring
+@vindex .notdef@r{, removing blotches with}
+To remove blotches, you can simply put @code{.notdef} in the appropriate
+place in the IFI file. You can find the ``appropriate place'' when you
+look at the output font; some character will be nothing but a (possibly
+tiny) speck, and all the characters following will be in the wrong
+position.
+
+@opindex -print-clean-info @r{example}
+@cindex bounding boxes, assigned to characters
+@cindex characters, bounding boxes assigned
+The @samp{-print-clean-info} option might also help you to
+diagnose which bounding boxes are being assigned to which characters,
+when you are in doubt. Here is an example of its output:
+
+@example
+[Cleaning 149x383 bitmap:
+ checking (0,99)-(10,152) ... clearing.
+ checking (0,203)-(35,263) ... clearing.
+ checking (0,99)-(130,382) ... keeping.
+ checking (113,0)-(149,37) ... keeping.
+106]
+@end example
+
+@noindent The final @samp{106} is the character code output (ASCII
+@samp{j}). The size of the overall bitmap which contains the `j' is 149
+pixels wide and 383 pixels high. The bitmap contained four bounding
+boxes, the last two of which belonged to the `j' and were kept, and the
+first two from the adjacent character (`i') and were erased. (As shown
+in the example image above, the tail of the `j' often overlaps the `i'
+in type specimens.)
+
+If the image has blobs you have not removed with @code{.notdef}, you
+will see a small bounding box in this output. The numbers shown are in
+``bitmap coordinates'': (0,0) is the upper left-hand pixel of the
+bitmap.
+
+
+@cindex baselines and blotches
+@opindex -baselines @r{and blotches}
+If a blotch appears outside of the row of characters, Imageto will
+consider it to be its own (very small) image row. If you are using
+@samp{-baselines}, you must specify an arbitrary value corresponding to
+the blotch, even though the bounding box in the image will be ignored.
+See the section above for an example.
+
+
+@node IFI files, Invoking Imageto, Imageto usage, Imageto
+@section IFI files
+
+@cindex IFI files
+@cindex image font information files
+
+An @dfn{image font information} (IFI) file is a text file which
+describes the contents of an image file. You yourself must create it;
+as we will see, the information it contains usually cannot be determined
+automatically.
+
+@cindex IFI files, naming
+@cindex naming IFI files
+If your image file is named @file{@var{foo}.img} (or
+@file{@var{foo}.pbm}), it is customary to name the corresponding IFI
+file @file{@var{foo}.ifi}. That is what Imageto looks for by default.
+If you name it something else, you must specify the name with the
+@samp{-ifi-file} option.
+
+Imageto does not look for an IFI file if either the @samp{-strips} or
+@samp{-epsf} options were specified.
+
+@cindex characters, defining in IFI files
+Each nonblank non-comment line in the IFI file represents a a sequence
+of bounding boxes in the image, and a corresponding character in the
+output font. @xref{Common file syntax}, for a description of syntax
+elements common to all data files processed by these programs, including
+comments.
+
+@cindex entries in IFI files
+Each line has one to five @dfn{entries}, separated by spaces and/or
+tabs. If a line contains fewer than five entries, suitable defaults (as
+described below) are taken for the missing trailing entries. (It is
+impossible to supply a value for entry #3, say, without also supplying
+values for entries #1 and #2.)
+
+Here is the meaning of each entry, in order:
+
+@enumerate
+
+@item
+@cindex character name in IFI files
+The character name of the output character. Usually, Imageto outputs
+the bounding boxes from the image as a character in the output font,
+assigning it the character code of the name as defined in the encoding
+vector (@pxref{Invoking Imageto}). However, if the character name is
+@code{.notdef}, or if the character name is not specified in the
+encoding, Imageto just throws away the bounding boxes. @xref{Encoding
+files}, for general information on encoding files.
+
+@item
+@cindex baseline in IFI files
+@cindex baseline adjustment
+@cindex adjustment, to baseline
+An adjustment to the baseline of the output character, as a (possibly
+signed) decimal number. The default baseline is either the bottom
+scanline of the image row, or the value you specified with the
+@samp{-baselines} option. The number given here, in the IFI file, is
+subtracted from that default. Thus, a positive adjustment moves the
+baseline up (i.e., moves the character down relative to the typesetting
+baseline), a negative one down. The default adjustment is zero.
+
+@item
+@cindex bounding box count in IFI files
+@cindex alternating bounding boxes
+@cindex mixed-up characters in image
+@cindex out-of-order characters in image
+@cindex characters, out-of-order in image
+The number of bounding boxes which comprise this character, as a decimal
+number. The default is one. If this number is negative, it indicates
+that the bounding boxes for this character are not consecutive in the
+image; instead, they alternate with the following character. For
+example, the tail of an italic `j' might protrude to the left of the
+`i'; then Imageto will find the tail of the `j' first (so it should come
+first in the IFI file), but it will find the dot of the `i' next. In
+this case, the bounding box count for both the `i' and the `j' should be
+@code{-2}.
+
+@item
+@cindex side bearings in IFI files
+@cindex left side bearing in IFI files
+The left side bearing (lsb). Most type specimens unfortunately don't
+include side bearing information, but if you happen to have such, you
+can give it here. (GSrenderfont (@pxref{GSrenderfont}) uses this
+feature). The default is zero.
+
+You can run Charspace (@pxref{Charspace}) to add side bearings to a font
+semi-automatically. This is usually less work than trying to guess
+at numbers here.
+
+@cindex right side bearing in IFI files
+@item
+The right side bearing. As with the lsb, the default is zero.
+
+@end enumerate
+
+Here is a possible IFI file for the image in @ref{Imageto usage}. We
+throw away the black line that is the second image row. (Imagine that
+it is a scanner artifact.)
+
+@example
+% IFI file for example image.
+i 0 2
+j 0 2
+l
+m 1
+.notdef % Ignore the black line at the bottom.
+@end example
+
+
+@node Invoking Imageto, , IFI files, Imageto
+@section Invoking Imageto
+
+@cindex Imageto options
+@cindex invocation of Imageto
+@cindex options for Imageto
+
+This section describes the options that Imageto accepts.
+@xref{Command-line options}, for general option syntax.
+
+The main input filename (@pxref{Main input file}) is called
+@var{image-name} below.
+
+@table @samp
+
+@item -baselines @var{scanline1},@var{scanline2},@dots{}
+@opindex -baselines
+@cindex baselines in image
+Define the baselines for each image row. The default baseline for the
+characters in the first image row is taken to be @var{scanline1}, etc.
+The @var{scanline}s are @emph{not} cumulative: the top scanline in each
+image row is numbered zero.
+
+@item -designsize @var{real}
+@opindex -designsize
+@cindex design size, specifying
+@cindex fontsize
+Set the design size of the output font to @var{real}; default is 10.0.
+
+@item -dpi @var{unsigned}
+@opindex -dpi
+The resolution of the input image, in pixels per inch (required for PBM
+input). @xref{Common options}.
+
+@item -encoding @var{enc-file}
+@opindex -encoding
+The encoding file to read for the mapping between character names and
+character codes. @xref{Encoding files}. If @var{enc-file} has no
+suffix, @samp{.enc} is appended. Default is to assign successive
+character codes to the character names in the IFI file.
+
+@item -epsf
+@opindex -epsf
+Write the image to @file{@var{image-name}.eps} as an Encapsulated
+PostScript file.
+
+@item -help
+@opindex -help
+Print a usage message. @xref{Common options}.
+
+@opindex -ifi-file
+@itemx -ifi-file @var{filename}
+Set the name of the IFI file to @var{filename} (if @var{filename} has an
+extension) or @file{@var{filename}.ifi} (if it doesn't). The default is
+@file{@var{image-name}.ifi}.
+
+@item -input-format @var{format}
+@opindex -input-format
+Specify the format of the input image; @var{format} must be
+one of @samp{pbm} or @samp{img}. The default is taken from
+@var{image-name}, if possible.
+
+@item -nchars @var{unsigned}
+@opindex -nchars
+Only write the first @var{unsigned} (approximately) characters from the
+image to the output font; default is all the characters.
+
+@item -output-file @var{filename}
+@opindex -output-file
+@cindex output file, naming
+Write to @var{filename} if @var{filename} has a suffix. If it doesn't,
+then if writing strips, write to @var{filename}sp.@var{dpi}gf; else
+write to @file{@var{filename}.@var{dpi}gf}. By default, use
+`@var{image-name} @var{designsize}' for @var{filename}.
+
+@item -print-clean-info
+@opindex -print-clean-info
+Print the size of each bounding box considered for removal, and the size
+of the containing bitmaps. This option implies @samp{-verbose}.
+@xref{Dirty images}, for a full explanation of its output.
+
+@item -print-guidelines
+@opindex -print-guidelines
+Print the numbers of the top and bottom scanlines for each
+character. This implies @samp{verbose}. @xref{Image to font
+conversion}, for a full explanation of its output.
+
+@item -range @var{char1}-@var{char2}
+@opindex -range
+Only output characters with codes between @var{char1} and @var{char2},
+inclusive. (@xref{Common options}, and @ref{Specifying character codes}.)
+
+@item -strips
+@opindex -strips
+Take a constant number of scanlines from the image as each character in
+the output font, instead of using an IFI file to analyze the image.
+
+@item -trace-scanlines
+@cindex scanlines, tracing
+@cindex image, converting to ASCII
+@opindex -trace-scanlines
+Show every scanline as we read it as plain text, using @samp{*} and
+space characters. This is still another way to view the image
+(@pxref{Viewing an image}), but the result takes an enormous amount of
+disk space (over eight times as much as the original image) and is quite
+difficult to look at (because it's so big). To be useful at all, we
+start a giant XTerm window with the smallest possible font and look at
+the resulting file in Emacs. This option is primarily for debugging.
+
+@item -verbose
+@opindex -verbose
+@kindex . @r{in Imageto verbose output}
+@kindex + @r{in Imageto verbose output}
+Output progress reports. @xref{Common options}. Specifically, a
+@samp{.} is output for every 100 scanlines read, a @samp{+} is
+output when an image row does not end on a character boundary, and the
+character code is output inside brackets.
+
+@item -version
+@opindex -version
+Print the version number. @xref{Common options}.
+
+@end table
diff --git a/doc/imgrotate.texi b/doc/imgrotate.texi
new file mode 100644
index 0000000..f4f044d
--- /dev/null
+++ b/doc/imgrotate.texi
@@ -0,0 +1,145 @@
+@c Copyright (C) 1992 Free Software Foundation.
+@c This is part of the GNU font utilities manual.
+@c For copying conditions, see the file fontutil.texi.
+
+@node IMGrotate, Fontconvert, Imageto, Top
+@chapter IMGrotate
+
+@pindex imgrotate
+@cindex rotation, of images
+@cindex image rotation
+
+IMGrotate rotates an IMG file, either 90 or 180 degrees clockwise. We
+call the latter---somewhat inaccurately---a ``flip''. (We haven't
+needed other rotation angles, so we haven't implemented them.)
+
+The IMG format is an image format output by a few programs, including the
+one that drives the scanner we have. (Again, we haven't needed other
+image formats, so we haven't implemented them.)
+
+Both the input and output are IMG files.
+
+The current implementation of IMGrotate uses an extremely slow and
+stupid algorithm, because it was a quick hack. It would be useful to
+replace it with a better algorithm. @xref{Program features}, for a
+reference.
+
+@menu
+* IMGrotate usage:: Doing the image rotation.
+* Invoking IMGrotate:: Command-line options.
+@end menu
+
+
+@node IMGrotate usage, Invoking IMGrotate, , IMGrotate
+@section IMGrotate usage
+
+@cindex IMGrotate usage
+@cindex usage of IMGrotate
+
+The physical construction of a source to be scanned may make it hard
+or impossible to end up with an upright image. But the task of
+extracting characters from an image is complicated by allowing for a
+rotated image. Hence this program to turn rotated images upright.
+
+@flindex x @r{prefix}
+By default, the name of the output file is the same as the input file;
+both are extended with @file{.img} if necessary. If this would result
+in the output overwriting the input, @samp{x} is prepended to the output
+name.
+
+@menu
+* Clockwise rotation:: Rotating clockwise.
+* Flip rotation:: FLipping end-for-end.
+@end menu
+
+
+@node Clockwise rotation, Flip rotation, , IMGrotate usage
+@subsection Clockwise rotation
+
+@cindex clockwise rotation
+@cindex rotation, clockwise
+@opindex -rotate-clockwise
+
+You specify clockwise rotation of an image with the option
+@samp{-rotate-clockwise}. This rotates the input 90 degrees clockwise.
+For example, the following (an @samp{h} on its side):
+
+@example
+ *****
+ *
+ *
+***********
+@end example
+
+@noindent turns upright.
+
+
+@node Flip rotation, , Clockwise rotation, IMGrotate usage
+@subsection Flip rotation
+
+@cindex flip rotation
+@cindex rotation, flip
+
+You specify ``flip'' rotation of an image with the option @samp{-flip}.
+This flips the input end for end and reverses left and right, i.e., does
+a 180 degree rotation. For example, the following (an @samp{h} upside
+down and backwards):
+
+@example
+ * *
+ * *
+ * *
+ ***
+ *
+ *
+ *
+@end example
+
+@noindent turns upright.
+
+
+@node Invoking IMGrotate, , IMGrotate usage, IMGrotate
+@section Invoking IMGrotate
+
+@cindex IMGrotate options
+@cindex invocation of IMGrotate
+@cindex options for IMGrotate
+
+This section describes the options that IMGrotate accepts.
+@xref{Command-line options}, for general option syntax.
+
+The name of the main input file (@pxref{Main input file}) is called
+@var{image-name} below.
+
+@table @samp
+
+@opindex -flip
+@item -flip
+Rotate the input 180 degrees, i.e., flip it end for end and left to
+right. @xref{Flip rotation}.
+
+@opindex -help
+@item -help
+Print a usage message. @xref{Common options}.
+
+@opindex -output-file
+@cindex output file, naming
+@item -output-file @var{filename}
+Write to @var{filename} if @var{filename} has a suffix. If it doesn't,
+write to @file{@var{filename}.img}, unless that would overwrite the
+input, in which case write to @file{x@var{filename}.img}. By default,
+use @var{image-name} for @var{filename}.
+
+@opindex -rotate-clockwise
+@item -rotate-clockwise
+Rotate the input 90 degrees clockwise. @xref{Clockwise rotation}.
+
+@opindex -verbose
+@item -verbose
+Output progress reports. @xref{Common options}.
+
+@opindex -version
+@item -version
+Print the version number. @xref{Common options}.
+
+@end table
diff --git a/doc/index.texi b/doc/index.texi
new file mode 100644
index 0000000..62455ad
--- /dev/null
+++ b/doc/index.texi
@@ -0,0 +1,8 @@
+@c Copyright (C) 1992 Free Software Foundation.
+@c This is part of the GNU font utilities manual.
+@c For copying conditions, see the file fontutil.texi.
+
+@node Index, , Freedom, Top
+@unnumbered Index
+
+@printindex cp
diff --git a/doc/install.texi b/doc/install.texi
new file mode 100644
index 0000000..bf4e219
--- /dev/null
+++ b/doc/install.texi
@@ -0,0 +1,341 @@
+@c Copyright (C) 1992, 93 Free Software Foundation.
+@c This is part of the GNU font utilities manual.
+@c For copying conditions, see the file fontutil.texi.
+
+@node Installation
+@chapter Installation
+
+@cindex installation
+@cindex configuration
+
+@xref{Prereqs}, for what you need to have installed before you can
+compile these programs.
+
+After that, here's what to do:
+
+@enumerate
+
+@item
+Run @code{sh configure} in the top-level directory. This tries to figure
+out system dependencies and the installation prefix.
+@xref{configure, , The @code{configure} script, kpathsea, Kpathsearch
+library}, for options and other information about @code{configure}.
+
+@flindex GNUmakefile@r{, editing}
+@flindex include/c-auto.h@r{, editing}
+@cindex search paths, defining default
+@item
+If necessary, edit the paths or other definitions in the top-level
+@file{GNUmakefile} and in @file{include/c-auto.h}.
+
+@item
+Run GNU make. For example, if it's installed as @file{make}, just type
+@samp{make} in the top-level directory. If all goes well, this will
+compile all the programs.
+
+@item
+Install the programs and supporting data files with @code{make install}.
+
+@end enumerate
+
+If you encounter problems anywhere along the line, let us know. Known
+problems are listed below (@pxref{Problems}).
+@xref{Bugs}, for details on how to submit a useful bug report.
+
+@menu
+* Prereqs:: What's needed before installation.
+* Problems:: Known trouble.
+@end menu
+
+
+@node Prereqs
+@section Prerequisites
+
+@cindex prerequisites to compilation
+
+To compile and use these programs, the following are necessary:
+
+@itemize @bullet
+
+@pindex gcc
+@cindex GNU C compiler
+@item
+The GNU C compiler, version 1.40 or newer.
+
+@cindex GNU make
+@pindex make
+@item
+GNU Make; probably any version newer than 3.50 or so will do.
+
+@cindex X11 libraries
+@cindex libraries, X11
+@item
+X11R4 or R5 unshared libraries and headers. These are only necessary to
+run XBfe (@pxref{XBfe}) or for Limn (@pxref{Limn}) to display its
+results online. (You also need an X11 server, naturally.) You might be
+able to compile using the X11 shared libraries, but we haven't tried
+that.
+
+@pindex gftopk
+@pindex pltotf
+@cindex Metafont
+@cindex @TeX{}
+@item
+To make any substantial use of the fonts you create, you will probably
+need @TeX{}, Metafont, and their friends, especially @code{PLtoTF} and
+@code{GFtoPK}.
+
+@cindex Ghostscript
+@pindex gs
+@item
+Ghostscript, version 2.4 or newer.
+You only need this if you want to use GSrenderfont or BZRedit.
+
+@pindex gawk @r{prerequisite to GSrenderfont}
+@item
+The GNU Awk program, @code{gawk}. This is only needed if you want to
+use GSrenderfont.
+
+@end itemize
+
+See the section below for information on how to get all these programs.
+
+@menu
+* Archives:: Where to find programs.
+@end menu
+
+
+@node Archives
+@subsection Archives
+
+@cindex software archives
+@cindex ftp archives
+@cindex archives, software
+
+@cindex GNU software, obtaining
+@flindex prep.ai.mit.edu
+The canonical source for all GNU software, including the GNU C compiler,
+GNU make, and Ghostscript, is @file{prep.ai.mit.edu:pub/gnu}. That
+directory is replicated at many other sites around the world, including:
+
+@table @asis
+
+@item United States:
+@example
+wuarchive.wustl.edu, ftp.cs.widener.edu,
+ uxc.cso.uiuc.edu, col.hp.com:/mirrors/gnu,
+ gatekeeper.dec.com:/pub/GNU, ftp.uu.net:/systems/gnu
+@end example
+
+@item Europe:
+@example
+src.doc.ic.ac.uk:/gnu, ftp.informatik.tu-muenchen.de,
+ ftp.informatik.rwth-aachen.de:/pub/gnu, nic.funet.fi:/pub/gnu,
+ ugle.unit.no, isy.liu.se, ftp.stacken.kth.se, ftp.win.tue.nl,
+ ftp.denet.dk, ftp.eunet.ch, nic.switch.ch:/mirror/gnu,
+ archive.eu.net, irisa.irisa.fr:/pub/gnu
+@end example
+
+@item Australia:
+@example
+archie.oz.au:/gnu @r{(@samp{archie.oz} or @samp{archie.oz.au} for ACSnet)}
+@end example
+
+@item Asia
+@example
+ftp.cs.titech.ac.jp, utsun.s.u-tokyo.ac.jp:/ftpsync/prep,
+ cair.kaist.ac.kr:/pub/gnu
+@end example
+
+@end table
+
+@flindex DISTRIB
+@cindex prices for GNU software
+@cindex ordering GNU software
+You can also order tapes with GNU software from the Free Software
+Foundation (thereby supporting the development of the font utilities and
+the rest of the GNU project); send mail to @samp{gnu@@prep.ai.mit.edu}
+for the latest prices and ordering information, or retrieve the file
+@file{DISTRIB} from a GNU archive.
+
+@cindex X window system, obtaining
+@flindex export.lcs.mit.edu
+@flindex gatekeeper.dec.com
+The canonical source for the X window system is
+@file{export.lcs.mit.edu:pub/R5}. That directory is also shadowed at
+many other sites, including @samp{gatekeeper.dec.com}. The FSF also
+sells X distribution tapes.
+
+@cindex @TeX{}, obtaining
+@flindex byron.u.washington.edu
+@TeX{} is more scattered. A complete Unix @TeX{} distribution is
+available by ordering a tape from the University of Washington (send
+email to @samp{elisabet@@u.washington.edu}. Three archives with
+complete (and identical) @TeX{} collections:
+
+@example
+ftp.uni-stuttgart.de:/soft/tex
+ftp.tex.ac.uk:/pub/archive
+pip.shsu.edu:/tex-archive
+@end example
+
+@pindex web2c
+@flindex ftp.cs.umb.edu
+@flindex ics.uci.edu
+@flindex ftp.th-darmstadt.de
+The canonical sources for just Web2C---the port of just @TeX{},
+Metafont, and friends to Unix, without DVI processors, fonts, macro
+packages, etc.---are:
+
+@example
+ftp.cs.umb.edu:pub/tex/ @r{(Boston)}
+ics.uci.edu:TeX/ @r{(California)}
+ftp.th-darmstadt.de:pub/tex/src/web2c/ @r{(Germany)}
+@end example
+
+@flindex web.tar.Z
+@flindex web2c.tar.Z
+At all these sites, the files to retrieve are @file{web.tar.Z} and
+@file{web2c.tar.Z}.
+
+@pindex dvips
+@pindex xdvi
+@cindex Rokicki, Tom
+@cindex Vojta, Paul
+@flindex labrea.stanford.edu
+The DVI-to-PostScript driver we recommend is Tom Rokicki's Dvips, and
+the X window system driver we recommend is Paul Vojta's XDvi. These
+programs are available from, respectively,
+@example
+labrea.stanford.edu:pub/dvips*
+export.lcs.mit.edu:contrib/xdvi.tar.Z
+@end example
+
+@cindex path searching
+We have modified XDvi and Dvips to use the same path searching code as
+the current distribution of @TeX{} and these font utilities; the
+modified versions are available from @file{ftp.cs.umb.edu:pub/tex}.
+
+@flindex modes.mf
+@cindex Metafont modes
+To use Metafont, you must have a file defining output devices.
+(@xref{Metafont and BZRto}.) We recommend you obtain @file{modes.mf}
+from
+@example
+ftp.cs.umb.edu:pub/tex/modes.mf
+@end example
+
+@flindex fontname.texi
+@cindex naming scheme for @TeX{} fonts
+@cindex filenames for fonts
+You can retrieve the document describing all the details of the naming
+scheme for @TeX{} fonts from
+
+@example
+ftp.cs.umb.edu:pub/tex/fontname.tar.Z
+@end example
+
+
+@node Problems
+@section Problems
+
+@cindex problems in installation
+@cindex trouble in installation
+@cindex installation problems
+
+This section lists some things which have caused trouble during
+installation. If you encounter other problems, please send a bug
+report. @xref{Bugs}, for how to submit a useful bug report.
+
+@itemize @bullet
+
+@opindex -static
+@cindex static linking, warning about
+@item
+You may get a warning from the compiler about @samp{-static} being an
+unrecognized option. Ignore it. (This has already been reported to
+@samp{bug-gcc}.)
+
+@cindex dynamic linking
+@cindex static linking vs.@: dynamic linking
+@cindex linking, dynamic
+@cindex SunOS linking
+@pindex /bin/ld
+@item
+Under SunOS 4.x, the programs which use X (XBfe and Limn) cannot be
+dynamically linked, because (apparently) @file{/bin/ld} pulls in the
+entire @file{.sa} file, and the Form, Label, and Viewport widgets are
+multiply defined. (To us, this seems to defeat the whole purpose of
+having libraries. It also seems bizarre to us that X was written so
+that these multibyte functions are always needed (via
+@code{__Xsi@dots{}}), and furthermore that the multibyte functions need
+to specifically call the dynamic linking functions.)
+
+@findex dlsym
+@findex dlclose
+@findex dlopen
+The file @file{lib/dlsym.c} (from the MIT X distribution) defines the
+@code{dlsym}, @code{dlclose}, and @code{dlopen} symbols, so static
+linking should work now.
+
+@cindex Xaw library, linking with
+If the current setup fails, it might work to change @samp{-lXaw} in
+the definition of @code{X_libraries} in @file{lib/defs.make} to
+the full pathname of the Xaw library.
+
+@cindex GCC crash
+@cindex compiler crash
+@flindex imageto/main.c
+@item
+On many machines (Sun 3 or Sun 4 running SunOS 4.1, Sun386i running
+4.0.2, 386 running ISC 2.2), GCC 1.40 gets a fatal error compiling
+@file{imageto/main.c} with @samp{-O}. Just use @samp{-g} for that file,
+or use a newer version of GCC.
+
+@flindex math.h@r{, wrong}
+@findex fmod@r{, wrong prototype for}
+@cindex Interactive Unix
+@item
+On a 386 running Interactive UNIX 2.2, @file{<math.h>} declares the
+wrong prototype for @code{fmod}: the routine takes two doubles, not one.
+We simply corrected our system include file.
+
+@findex XtIsRealized
+@findex XtWindowOfObject
+@vindex NULL
+@cindex warnings in @file{Bitmap.c}
+@cindex compiler warnings in @file{Bitmap.c}
+@flindex Bitmap.c
+@flindex widgets/Bitmap.c
+@flindex IntrinsicP.h
+@flindex X11/IntrinsicP.h
+You may get compiler warnings for the file @file{widgets/Bitmap.c} at
+the lines which use the Xt function @code{XtIsRealized} on systems which
+define @code{NULL} as @code{(void *) 0}. The reason is that macro
+definition of @code{XtIsRealized} in @file{<X11/IntrinsicP.h>}
+incorrectly compares the result of @code{XtWindowOfObject} to
+@code{NULL}, instead of @code{0}. If the warnings bother you, fix
+@file{IntrinsicP.h}.
+
+@flindex XBfe @r{resource file}
+@cindex XBfe failing
+@cindex Limn online display failing
+@flindex Limn @r{resource file}
+@cindex X programs failing
+@cindex X resources unrecognized
+@cindex application resources, under X
+@vindex XAPPLRESDIR
+@item
+The application resource files @file{limn/Limn} and @file{xbfe/XBfe}
+must be installed in a directory where your X server can find them.
+This directory varies according to how X was installed; in the default X
+distribution, it is @file{/usr/lib/X11/app-defaults}. If you cannot (or
+do not want to) write in the default directory, you can install them
+elsewhere and set the @code{XAPPLRESDIR} environment variable to that
+directory. See the tutorial on resources that comes with the MIT X
+distribution (@file{mit/doc/tutorial/resources.txt}) for more
+information.
+
+@end itemize
+
+Good luck.
diff --git a/doc/intro.texi b/doc/intro.texi
new file mode 100644
index 0000000..addd75c
--- /dev/null
+++ b/doc/intro.texi
@@ -0,0 +1,33 @@
+@c Copyright (C) 1992 Free Software Foundation.
+@c This is part of the GNU font utilities manual.
+@c For copying conditions, see the file fontutil.texi.
+
+@node Introduction, Installation, Top, Top
+@chapter Introduction
+
+@cindex introduction
+
+This manual corresponds to version REPLACE-WITH-VERSION of the GNU font
+utilities.
+
+You can manipulate fonts in various ways using the utilities: conversion
+of a scanned image to a bitmap font, hand-editing of bitmaps, conversion
+of a bitmap font to an outline font, and more. More generally, you can
+start with a scanned image of artwork and work your way through to a
+finished font with side bearings, accented characters, ligatures, and so
+on.
+
+@cindex Knuth, Donald E.
+The font formats recognized by these programs are primarily those used
+by the (freely available) @TeX{} typesetting system developed by
+@w{Donald E.} Knuth from 1977--1990. The filenames, font searching, and
+other aspects of their usage are also based on @TeX{}. They also
+support output of PostScript Type 1 fonts.
+
+@cindex Morris, Robert A.
+@cindex Martin, Rick
+Some of this software was originally written as part of the research
+program in digital typography at the University of Massachusetts at
+Boston, directed by @w{Robert A.} Morris. The staff at UMB, Rick Martin in
+particular, has been kind enough to let us to continue to use their
+computers, despite our completing the Master's program there in 1989.
diff --git a/doc/limn.texi b/doc/limn.texi
new file mode 100644
index 0000000..7c38f08
--- /dev/null
+++ b/doc/limn.texi
@@ -0,0 +1,970 @@
+@c Copyright (C) 1992, 93 Free Software Foundation.
+@c This is part of the GNU font utilities manual.
+@c For copying conditions, see the file fontutil.texi.
+
+@node Limn, BZRto, Charspace, Top
+@chapter Limn
+
+@pindex limn
+@cindex bitmap to outline conversion
+@cindex outline fonts, making from bitmap
+@cindex spline fitting
+
+@cindex outline font, definition of
+@cindex bitmap font, definition of
+These days, fonts to be used on computers are represented in one of two
+ways: as a @dfn{bitmap font}, which specifies each individual pixel in
+the image of a character; and/or as an @dfn{outline font}, which
+specifies the image as a collection of mathematically-specified curves.
+Each method has its own advantages and disadvantages; typesetting
+programs, page description languages, and output devices can generally
+deal with both.
+
+@cindex autotracing
+@cindex tracing outlines on a bitmap
+Limn converts a font from a bitmap to an outline by fitting curves to
+the pixels. Non-shape-related information in the bitmap font, such as
+that for the side bearings, is preserved in the outline output.
+
+Specifically, the input is a bitmap (GF or PK) font. The output is a
+BZR outline font (@pxref{BZR files}), which can then be converted to
+(for example) Metafont or PostScript with BZRto (@pxref{BZRto}).
+
+@cindex Schneider, Philip
+@cindex Phoenix
+@cindex Plass, Michael
+@cindex Stone, Maureen
+@cindex Gonczarowski, Jakob
+There is a fair amount of literature on converting bitmaps to outlines.
+We found three particularly helpful: Philip Schneider's Master's thesis
+on his system Phoenix; Michael Plass and Maureen Stone's article
+`Curve-fitting with piecewise parametric cubics' published in SIGGRAPH;
+and Jakob Gonczarowski's article `A fast approach to auto-tracing (with
+parametric cubics)' in the RIDT 91 conference proceedings. See
+the file @file{limn/README} for the full citations.
+
+@menu
+* Limn algorithm:: How Limn fits outlines to bitmaps.
+* Invoking Limn:: Command-line options.
+@end menu
+
+
+@node Limn algorithm, Invoking Limn, , Limn
+@section Limn algorithm
+
+@cindex Limn algorithm
+@cindex algorithm for spline fitting
+@cindex spline fitting, algorithm for
+
+Limn can always (barring bugs, of course) fit some sort of outline to
+the bitmap input. But its default fit is likely to be far from the
+ideal: character features may disappear, curves distorted, straight
+lines turned into curves and curves into straight lines, and on and on.
+
+To control the fitting process, you must specify options to override
+Limn's defaults. To describe those options, we must describe the
+algorithm Limn uses to do the fitting, which we do in this section. We
+mention the options at the appropriate point.
+
+The next section summarizes all the options, in alphabetical order.
+
+@flindex fit.c
+Here is a schematic of the algorithm. The subsections below go into
+detail for each step. Except for the very first step, this is
+implemented in @file{limn/fit.c}.
+
+@example
+find pixel outlines
+for each pixel outline:
+ find corners, yielding curve lists
+ for each curve list:
+ remove knees
+ filter
+ if too small:
+ fit with straight line
+ otherwise fit with spline:
+ set initial t values
+ find tangents
+ fit with one spline
+ while error > reparameterize-threshold, reparameterize
+ if error > error-threshold, subdivide and recurse
+ if linearity < line-threshold, change to straight line
+ revert bad lines
+ align endpoints
+@end example
+
+@menu
+* Finding pixel outlines:: Extracting the edges from the bitmap.
+* Finding corners:: Finding subsections of each outline.
+* Removing knees:: Removing extraneous points.
+* Filtering curves:: Smoothing the outlines.
+* Fitting the bitmap curve:: Doing the fitting.
+* Changing splines to lines:: Use straight lines where possible.
+* Changing lines to splines:: Sometimes it isn't possible.
+* Aligning endpoints:: If points are close enough, line them out.
+* Displaying fitting online:: Seeing the results as Limn runs.
+@end menu
+
+
+@node Finding pixel outlines, Finding corners, , Limn algorithm
+@subsection Finding pixel outlines
+
+@cindex pixel outlines, finding in bitmaps
+@cindex cyclic curves
+
+The first step in the conversion from a character shape represented as a
+bitmap to a list of mathematical curves is to find all the cyclical
+outlines (i.e., closed curves) in the bitmap image. The resulting list
+is called a @dfn{pixel outline list}. Each @dfn{pixel outline} in the
+list consists of the pixel coordinates of each edge on the outline.
+
+For example, the pixel outline list for an @samp{i} has two elements:
+one for the dot, and one for the stem. The pixel outline list for an
+@samp{o} also has two elements: one for the outside of the shape, and
+one for the inside.
+
+@cindex outside outlines
+@cindex inside outlines
+@cindex clockwise ordering of outlines
+@cindex filling outlines
+But we must differentiate between an @dfn{outside outline} (whose
+interior is to be filled with black to render the character) and an
+@dfn{inside outline} (whose interior is to be filled with white).
+Limn's convention is to write the pixel coordinates for outside outlines
+in counterclockwise order, and those for inside outlines in clockwise
+order.
+
+@cindex type 1 outlines
+This counterclockwise movement of outside outlines is required by the
+Type 1 format used for PostScript fonts, which is why we adopted that
+convention for Limn.
+
+For example, consider a pixel outline consisting of a single black pixel
+at the origin. The pixel has four corners, and hence the outline will
+have four coordinates. Limn looks for starting pixels from top to
+bottom, left to right, within a bitmap image. Thus, the list of pixel
+coordinates will start at (0,1) and proceed counterclockwise: (0,0)
+(1,0) (1,1). Here is a picture:
+
+@example
+start => (0,1)<-(1,1)
+ | ^
+ v |
+ (0,0)->(0,1)
+@end example
+
+
+Because finding pixel outlines does not involve approximation or
+estimation, there are no options to control the process. Put another
+way, Limn will always find the correct pixel coordinates for each
+outline.
+
+Once these pixel outlines have been found, each is then processed
+independently; i.e., all the remaining steps, described in the following
+sections, operate on each pixel outline individually.
+
+@flindex pxl-outline.c
+@flindex edge.c
+The source code for this is in @file{limn/pxl-outline.c} and
+@file{lib/edge.c}.
+
+
+@node Finding corners, Removing knees, Finding pixel outlines, Limn algorithm
+@subsection Finding corners
+
+@cindex corners, finding
+
+Recall that our final goal is to fit splines, i.e., continuous curves,
+to the discrete bitmap image. To that end, Limn looks for @dfn{corners}
+in each pixel outline (see the previous section)---points where the
+outline makes such a sharp turn that a single curve cannot
+possibly fit well. Two corners mark the endpoints of a @dfn{curve}.
+
+@cindex curve list, definition of
+We call the result a @dfn{curve list}, i.e., a list of curves on the
+pixel outline: the first curve begins at that first corner and continues
+through the second corner; and so on, until the last, which begins with
+the last corner found and continues through the first corner. (Each
+pixel outline is cyclic by definition; again, see the previous section.)
+
+@cindex fitting algorithm, adjusting
+The corner-finding algorithm described below works fairly well in
+practice, but you will probably need to adjust the parameters it uses.
+Finding good corners is perhaps the most important part of the entire
+fitting algorithm: missing a corner usually leads to a sharp point in
+the original image being rounded off to almost nothing; finding an
+extraneous corner usually leads to an extremely ugly blob.
+
+Here is Limn's basic strategy for guessing if a given point @math{p} is
+a corner: compute the total displacement (in both @math{x} and @math{y})
+for some number @math{n} of points before @math{p}; do the same for
+@math{n} points after @math{p}; find the angle @math{a} between those
+two vectors; if that angle is less than some threshold, @math{p} is a
+corner.
+
+@itemize @bullet
+
+@cindex resolution, dependency of fitting algorithm on
+@opindex -corner-surround
+The number @math{n} of points to consider is 4 by default; you can
+specify a different number with the @samp{-corner-surround} option. If
+the resolution of the input font is not 300@dmn{dpi},
+@samp{-corner-surround} should almost certainly be changed
+proportionately.
+
+@opindex -corner-threshold
+The threshold is 100 degrees by default; you can change this with the
+@samp{-corner-threshold} option. You can see the angles at the chosen
+corners via @samp{-log}.
+
+@end itemize
+
+However, when Limn finds a point @var{p} whose angle is below
+@samp{corner-threshold}, it won't necessarily take @var{p} as the
+corner. Instead, it continues looking for another
+@samp{corner-surround} points; if it finds another point @math{q} whose
+angle is less than that of @math{p}, @var{q} will become the corner.
+(And then Limn looks for another @samp{corner-surround} points beyond
+@var{q}, and so on.)
+
+This continued searching prevents having two corners near each other,
+which is usually wrong, if the angles at the two would-be corners are
+approximately the same. On the other hand, sometimes there are
+extremely sharp turns in the outline within @samp{corner-surround}
+pixels; in that case, one does want nearby corners after all.
+
+@opindex -corner-always-threshold
+So Limn has one more option, @samp{-corner-always-threshold}. If the
+angle at a point is below this value (60 degrees by default), then that
+point is considered a corner, regardless of how close it is to other
+corners. The search for another corner within @samp{corner-surround}
+pixels continues, however.
+
+
+@node Removing knees, Filtering curves, Finding corners, Limn algorithm
+@subsection Removing knees
+
+@cindex knees, removing
+@cindex extra pixels, removing
+
+For each curve in the curve list determined by the corners on the pixel
+outline (see the previous section), Limn next removes
+@dfn{knees}---points on the inside of the outline that form a ``right
+angle'' with its predecessor and successor. That is, either (1) its
+predecessor differs only in @math{x}, and its successor only in
+@math{y}; or (2) its predecessor differs only in @math{y}, and its
+successor only in @math{x}.
+
+It is hard to describe in words, but here is a picture:
+
+@example
+**
+ X*
+ *
+@end example
+
+@noindent The point @samp{X} is a knee, if we're moving in a clockwise
+direction.
+
+Such a ``right angle'' point can be on either the inside or the outside
+of the outline. Points on the inside do nothing useful, they just slow
+things down and, more importantly, make the curve being fit less
+accurate. So we remove them. But points on the outside help to define
+the shape of the curve, so we keep those. (For example, if @samp{X} was
+moved up one diagonally, we certainly want it as a part of the curve.)
+
+Although we haven't found a case where removing knees produces an
+inferior result, there's no theory about it always helping. Also, you
+may just be curious what difference it makes (as we were when we
+programmed the operation). So Limn provides an option
+@samp{-keep-knees}; if you specify it, Limn simply skips this step.
+
+
+@node Filtering curves, Fitting the bitmap curve, Removing knees, Limn algorithm
+@subsection Filtering curves
+
+@cindex filtering curves
+@cindex curves, filtering
+@cindex smoothing curves
+
+After generating the final pixel coordinates for each curve (see the
+previous sections), Limn next @dfn{filters} the curves to smooth them.
+Before this step, all the coordinates are on integer boundaries, which
+makes the curves rather bumpy and difficult to fit well.
+
+@opindex -filter-percent
+@cindex filtering, weighting
+To filter a point @math{p}, Limn does the following:
+
+@enumerate
+
+@item
+Computes the sum of the distances of @math{n} neighbors (points before
+and after @math{p}) to @math{p}. These neighbors are always taken from
+the original curve, since we don't want a newly filtered point to affect
+subsequent points as we continue along the curve; that leads to strange
+results.
+
+@item
+Multiplies that sum by a weight, and adds the result to @math{p}. The
+weight is one-third by default; you can change this with the
+@samp{-filter-percent} option, which takes an integer between zero and
+100.
+
+@end enumerate
+
+@cindex filter iterations
+@opindex -filter-iterations
+Repeatedly filtering a curve leads to even more smoothing, at the
+expense of fidelity to the original. By default, Limn filters each
+curve 4 times; you can change this with the @samp{-filter-iterations}
+option.
+
+@cindex filtering, minimum size of curve for
+If the curve has less than five points, filtering is omitted altogether,
+since such a short curve tends to collapse down to a single point.
+
+@opindex -filter-alternative-surround
+@opindex -filter-epsilon
+@opindex -filter-surround
+The most important filtering parameter is the number @math{n} of
+surrounding points which are used to produce the new point. Limn has
+two different possibilities for this, to keep features from disappearing
+in the original curve. Let's call these possibilities @var{n} and
+@var{alt_n}; typically @var{alt_n} is smaller than @var{n}. Limn
+computes the total distance along the curve both coming into and going
+out of the point @math{p} for both @var{n} and @var{alt_n} surrounding
+points. Then it computes the angles between the in and out vectors for
+both. If those two angles differ by more than some threshold (10
+degrees by default; you can change it with
+@opindex -filter-epsilon
+the @samp{-filter-epsilon} option), then Limn uses @var{alt_n} to
+compute the new point; otherwise, it uses @var{n}.
+
+Geometrically, this means that if using @var{n} points would result in a
+much different new point than using @var{alt_n}, use the latter, smaller
+number, thus (hopefully) distorting the curve less.
+
+@cindex resolution of input, dependency on
+@opindex -filter-alternative-surround
+@opindex -filter-surround
+Limn uses 2 for @var{n} and 1 for @var{alt_n} by default. You can use
+the options @samp{-filter-surround} and
+@samp{-filter-alternative-surround} to change them. If the resolution
+of the input font is not 300@dmn{dpi}, you should scale them
+proportionately. (For a 1200@dmn{dpi} font, we've had good results with
+@samp{-filter-surround=12} and @samp{filter-alternative-surround= 6}.)
+
+
+@node Fitting the bitmap curve, Changing splines to lines, Filtering curves, Limn algorithm
+@subsection Fitting the bitmap curve
+
+@cindex fitting bitmap curves
+
+The steps in the previous sections are preliminary to the main fitting
+process. But once we have the final coordinates for each (bitmap)
+curve, we can proceed to fit it with some kind of continuous
+(mathematical) function: Limn uses both straight lines (polynomials of
+degree 1) and Bezier splines (degree 3).
+
+@cindex fitting with straight lines
+@cindex lines, fitting with
+To begin with, to use a spline the curve must have at least four points.
+If it has fewer, we simply use the line going through its first and last
+points. (There is no point in doing a fancy ``best fit'' for this case,
+since the original curve is so short.)
+
+@cindex cubic splines, fitting with
+@cindex Bezier splines, fitting with
+@cindex spline representation
+@cindex representation of splines
+Otherwise, if the curve has four or more points, we try to fit it with
+a (piece of a) Bezier cubic spline. This spline is represented as a
+starting point, an ending point, and two ``control points''. Limn uses the
+endpoints of the curve as the endpoints of the spline, and adjusts the
+control points to try to match the curve.
+
+@cindex Bezier cubics, drawing
+A complete description of the geometric and mathematical properties of
+Bezier cubics is beyond the scope of this document. See a computer
+graphics textbook for the details.
+
+We will use the terms ``splines'', ``cubics'', ``Bezier splines'',
+``cubic splines'', and so on interchangeably, as is common practice.
+(Although Bezier splines are not the only kind of cubic splines, they
+are the only kind we use.)
+
+The sections below describe the spline-fitting process in more detail.
+
+@menu
+* Initializing t:: Initializing the parameter values.
+* Finding tangents:: Computing the direction of the curve at
+ the endpoints.
+* Finding the spline:: Where are the control points?
+* Reparameterization:: Changing the parameter values.
+* Subdivision:: Splitting the curve into pieces.
+@end menu
+
+
+@node Initializing t, Finding tangents, , Fitting the bitmap curve
+@subsubsection Initializing @math{t}
+
+@cindex initializing t
+@cindex t, initializing
+@cindex curve parameter initialization
+
+Limn must have some way to relate the discrete curve made from the
+original bitmap to the continuous spline being fitted to that curve.
+This is done by associating another number, traditionally called
+@math{t}, with each point on the curve.
+
+@cindex t, meaning of
+Imagine moving along the spline through the points on the curve. Then
+@math{t} for a point @math{p} corresponds to how far along the spline
+you have traveled to get to @math{p}. In practice, of course, the
+spline does not perfectly fit all the points, and so Limn adjusts the
+@math{t} values to improve the fit (@pxref{Reparameterization}). (It
+also adjusts the spline itself, as mentioned above.)
+
+@cindex chord-length parameterization
+Limn initializes the @math{t} value for each point on the curve using a
+method called @dfn{chord-length parameterization}. The details of how
+this works do not affect how you use the program, so we will omit them
+here. (See the Plass & Stone article cited in @file{limn/README} if
+you're curious about them.)
+
+
+@node Finding tangents, Finding the spline, Initializing t, Fitting the bitmap curve
+@subsubsection Finding tangents
+
+@cindex blending of adjacent curves
+@cindex adjacent curves, blending
+As mentioned above, Limn moves the control points on the spline
+to optimally fit the bitmap. But it cannot just move them arbitrarily,
+because it must make sure that the spline fitting one part of the bitmap
+blends smoothly with those fit to adjacent parts.
+
+@cindex continuity of curves
+@cindex zero-order continuity
+@cindex first-order continuity
+@cindex G1 continuity
+Technically, this smooth blending is called @dfn{continuity}, and it
+comes in degrees. Limn is concerned with the first two degrees: zero-
+and first-order. Zero-order continuity between two curves simply means
+the curves are connected; first-order geometric (G1) continuity means
+the tangents to each curve at the point of connection have the same
+direction. (There are other kinds of continuity besides ``geometric'',
+but they are not important for our purposes.)
+
+Informally, this means that the final shape will not abruptly turn at
+the point where two splines meet. (Any computer graphics textbook will
+discuss the properties of tangents, continuity, and splines, if you're
+unfamiliar with the subject.)
+
+@cindex control points, constraints on
+To achieve G1 continuity, Limn puts the first control point of a spline
+on a line going in the direction of the tangent to the start of the
+spline; and it puts the second control point on a line in the direction
+of the tangent to the end of the spline. (It would be going far afield
+to prove that this together with the properties of Bezier splines imply
+G1 continuity, but they do. See Schneider's thesis referenced in
+@file{limn/README} for a complete mathematical treatment.)
+
+@cindex tangents, computing
+@cindex resolution of input, dependency on
+@opindex -tangent-surround
+For the purposes of using Limn, the important thing is that Limn must
+compute the tangents to the spline at the beginning and end, and must do
+so accurately in order to achieve a good fit to the bitmap. Since Limn
+has available only samples (i.e., the pixel coordinates) of the curve
+being fit, it cannot compute the true tangent. Instead, it must
+approximate the tangent by looking at some number of coordinates on
+either side of a point. By default, the number is 3, but you can
+specify a different number with the @samp{-tangent-surround} option. If
+the resolution of the input font is different than 300@dmn{dpi}, or if
+the outline Limn fits to the bitmap seems off, you will want to scale it
+proportionately.
+
+
+@node Finding the spline, Reparameterization, Finding tangents, Fitting the bitmap curve
+@subsubsection Finding the spline
+
+@cindex error in fitting
+@cindex minimizing error
+At last, after all the preprocessing steps described in the previous
+sections, we can actually fit a spline to the bitmap. Subject to the
+tangent constraints (see the previous section), Limn finds the spline which
+minimizes the @dfn{error}---the overall distance to the pixel coordinates.
+
+@cindex least-squares error metric
+@cindex sum of squares of distances
+More precisely, Limn uses a @dfn{least-squares error metric} to measure
+the ``goodness'' of the fit. This metric minimizes the sum of the
+squares of the distance between each point on the bitmap curve and its
+corresponding point on the fitted spline. (It is appropriate to square
+the distance because it is equally bad for the fitted spline to diverge
+from the curve in a positive or negative direction.)
+
+@cindex t parameter
+The correspondence between the fitted spline and the bitmap curve is
+defined by the @math{t} value that is associated with each point
+(@pxref{Initializing t}).
+
+@cindex formula for best control points
+For a given set of @math{t} values and given endpoints on the spline,
+the control points which minimize the least-squares metric are unique.
+The formula which determines them is derived in Schneider's thesis (see
+the reference in @file{limn/README}); Limn implements that formula.
+
+Once we have the control points, we can ask how well the resulting
+spline actually does fit the bitmap curve. Limn can do two things to
+improve the fit: change the @math{t} values (reparameterization); or
+break the curve into two pieces and then try to fit each piece
+separately (subdivision).
+
+The following two sections describe these operations in more detail.
+
+
+@node Reparameterization, Subdivision, Finding the spline, Fitting the bitmap curve
+@subsubsection Reparameterization
+
+@cindex reparameterization
+
+@dfn{Reparameterization} changes the @math{t} value for each point
+@math{p} on the bitmap curve, thus changing the place on the spline
+which corresponds to @math{p}. Given these new @math{t} values, Limn
+will then fit a new spline (see the previous section) to the bitmap, one
+which presumably matches it more closely.
+
+Reparameterization is almost always a win. Only if the initial fit
+(@pxref{Initializing t}) was truly terrible will reparameterization be a
+waste of time, and be omitted in favor of immediate subdivision (see the
+next section).
+
+@opindex -reparameterize-threshold
+@cindex threshold for reparameterization
+Limn sets the default threshold for not reparameterizing to be 30
+``square pixels'' (this number is compared to the least-squares error;
+see the previous section). This is usually only exceeded in cases such
+as that of an outline of @samp{o}, where one spline cannot possibly fit
+the entire more-or-less oval outline. You can change the threshold with
+the option @samp{-reparameterize-threshold}.
+
+@opindex -reparameterize-improve
+@cindex improvement threshold for reparameterization
+If the error is less than @samp{reparameterize-threshold}, Limn
+reparameterizes and refits the curve until the difference in the error
+from the last iteration is less than some percentage (10 by default; you
+can change this with the option @samp{-reparameterize-improve}).
+
+After Limn has given up reparameterization (either because the initial
+fit did not meet the @samp{reparameterize-threshold}, or because the
+error did not decrease by at least @samp{reparameterize-improve}), the
+final error is compared to another threshold, 2.0 by default. (You can
+specify this with the option @samp{-error-threshold}.) If the error is
+larger, Limn subdivides the bitmap curve (see the next section) and fits
+each piece separately. Otherwise, Limn saves the fitted spline and goes
+on to the next piece of the pixel outline.
+
+
+@node Subdivision, , Reparameterization, Fitting the bitmap curve
+@subsubsection Subdivision
+
+@cindex subdivision of curves
+@cindex housing developments
+@cindex recursive fitting
+
+When Limn cannot fit a bitmap curve within the @samp{error-threshold}
+(see the previous section), it must subdivide the curve into two pieces
+and fit each independently, applying the fitting algorithm recursively.
+
+@cindex subdivision vs. reparameterization
+@cindex reparameterization vs. subdivision
+
+As a strategy to improve the fit, subdivision is inferior to
+reparameterization, because it increases the number of splines in the
+character definition. This increases the memory required to store the
+character, and also the time to render it. However, subdivision is
+unavoidable in some circumstances: for example, the outlines on an
+@samp{o} cannot be fit by a single spline.
+
+@cindex subdivision point, choosing
+@cindex worst fit, in subdivision
+For the initial guess of the point at which to subdivide, Limn chooses
+the point of worst error---the point where the fitted spline is farthest
+from the bitmap curve. Although this is usually a good choice,
+minimizing the chance that further subdivision will be necessary,
+occasionally it is not the best: in order to preserve straight lines,
+it is better to subdivide at the point where a straight becomes a curve
+if that point is close to the worst point. For example, this happens
+where a serif joins the stem.
+
+Limn has three options to control this process:
+
+@enumerate
+
+@opindex -subdivide-search
+@item
+@samp{-subdivide-search @var{percent}} specifies how far away from the
+worst point to search for a better subdivision point, as a percentage of
+the total number of points in the curve; the default is 10. If you find
+Limn missing a join as a subdivision point, resulting in a straight line
+becoming a curve, you probably need to increase this.
+
+@opindex -subdivide-threshold
+@item
+@samp{-subdivide-threshold @var{real}}: if the distance between a point
+@math{p} (within the search range) and a straight line is less than
+this, subdivide at @math{p}; default is .03 pixels.
+
+@opindex -subdivide-surround
+@item
+@samp{-subdivide-surround @var{unsigned}}: when calculating the linearity
+of the curve surrounding a potential subdivision, use this many points;
+default is 4.
+
+@end enumerate
+
+Because fitting a shorter curve is easier, this process will always
+terminate. (Eventually the curve will be short enough to fit with a
+straight line (@pxref{Fitting the bitmap curve}), if nothing else.)
+
+
+@node Changing splines to lines, Changing lines to splines, Fitting the bitmap curve, Limn algorithm
+@subsection Changing splines to lines
+
+@cindex splines to lines
+@cindex lines, changing splines to
+
+Upon accepting a fitted spline (see the previous sections), Limn checks
+if a straight line would fit the curve as well. If so, that is
+preferable, since it is much faster to render straight lines than cubic
+splines.
+
+More precisely, after fitting a cubic spline to a particular (segment of
+a) curve, Limn finds the straight line between the spline's endpoints,
+and computes the average distance (@pxref{Finding the spline}) between
+the line and the curve. If the result is less than some threshold, 1 by
+default, then the spline is provisionally (see the next section) changed
+to a line.
+
+@opindex -line-threshold
+@cindex threshold, for splines to lines
+You can change the theshold with the @samp{-line-threshold} option.
+
+
+@node Changing lines to splines, Aligning endpoints, Changing splines to lines, Limn algorithm
+@subsection Changing lines to splines
+
+@cindex lines to splines
+@cindex splines, changing lines to
+@cindex reversion of lines to splines
+
+Once an entire curve (i.e., the bitmap outline between two corners; see
+@ref{Finding corners}) has been fit, Limn checks for straight lines that
+are adjacent to splines. Unless such lines fit the bitmap
+@emph{extremely} well, they must be changed to splines.
+
+@cindex join point of lines and splines
+The reason is that the point at which the line and spline meet will be a
+visible ``bump'' in the typeset character unless the two blend smoothly.
+Where two splines meet, the continuity is guaranteed from the way we
+constructed the splines (@pxref{Finding tangents}). But where a line
+and spline meet, nothing makes the join smooth.
+
+For example, if the outline of a @samp{o} has been subdivided many times
+(as typically happens), a spline may end up fitting just a few
+pixels---so few that a line would fit just as well. The actions
+described in the previous section will therefore change the spline to a
+line. But since the adjacent parts of the @samp{o} are being fit with
+curves, that line will result in a noticeable flat spot in the final
+output. So we must change it back to a spline.
+
+@cindex threshold for line reversion
+We want this reversion to be more likely for short curves than long
+curves, since short curves are more likely to be the result of a small
+piece of a curved shape. So Limn divides the total distance between the
+fitted line and the bitmap curve by the square of the curve length, and
+compares the result to a threshold, .01 by default. You can change this
+with the @samp{-line-reversion-threshold} option.
+
+
+@node Aligning endpoints, Displaying fitting online, Changing lines to splines, Limn algorithm
+@subsection Aligning endpoints
+
+@cindex aligning endpoints
+@cindex endpoints, aligning
+
+After fitting a mathematical outline of splines and lines to a pixel
+outline (@pxref{Finding pixel outlines}), Limn aligns the endpoints on
+the fitted outline. This involves simply checking each spline to see if
+its starting point and ending point (in either axis) are ``close
+enough'' to each other. If they are, then they are made equal to their
+average.
+
+This is useful because even a slight offset of the endpoints can be
+produce a noticeable result, especially for straight lines and corners.
+
+@opindex -align-threshold
+By default, ``close enough'' is half a pixel. You can change this with
+the @samp{-align-threshold} option.
+
+
+@node Displaying fitting online, , Aligning endpoints, Limn algorithm
+@subsection Displaying fitting online
+
+@cindex online display of fitted outline
+@cindex displaying fitted outline online
+@cindex fitted outline, displaying online
+
+@opindex -display
+While experimenting with the various fitting options listed in the
+preceding sections, you may find it useful to see the results of the
+fitting online. Limn can display the filtered (@pxref{Filtering
+curves}) bitmap and the fitted outline online if it is run under the X
+window system and you specify @samp{-do-display}.
+
+@opindex -display-continue
+Ordinarily, Limn stops at the end of fitting every character for you to
+hit return, so you have a chance to examine the result. If you just
+want to get a brief glimpse or something, you can specify
+@samp{-display-continue}. Then Limn won't stop.
+
+@vindex DISPLAY @r{environment variable}
+@cindex X server, specifying
+If you specify @samp{-do-display}, you must set the environment variable
+@code{DISPLAY} to the X server you want Limn to use. For example, in
+Bourne-compatible shells, you might do:
+
+@example
+DISPLAY=:0 ; export DISPLAY
+@end example
+
+The output is shown on a grid, in which each square represents several
+pixels in the input. Corners are shown as filled squares; other pixels
+are shown as hollow squares.
+
+Limn has several options that change the appearance of the online
+output:
+
+@itemize @bullet
+
+@opindex -display-grid-size
+@cindex grid lines, space between
+@item @samp{-display-grid-size @var{unsigned}}
+The number of expanded pixels shown between the grid lines; default is 10.
+
+@opindex -display-pixel-size
+@cindex expansion of displayed pixels
+@cindex displayed pixels, expansion of
+@item @samp{-display-pixel-size @var{unsigned}}
+The expansion factor; i.e., each input pixel is expanded to a square
+this many pixels on a side; default is 9.
+
+@opindex -display-rectangle-size
+@item @samp{-display-rectangle-size @var{unsigned}}
+The pixel size; i.e., each pixel shown is a square this many pixels on a
+side; default is 6. This must be less than the
+@samp{display-pixel-size}, so that black pixels don't merge into each
+other.
+
+@end itemize
+
+@vindex geometry @r{resource}
+@cindex size of Limn window
+@cindex Limn window size
+@flindex .Xdefaults
+@cindex resources for X
+@cindex X resources
+You can change the size of the window Limn creates with the
+@code{geometry} resource in your @file{.Xdefaults} file (see the
+documentation in the file @file{mit/doc/tutorials/resources.txt} in the
+X distribution if you aren't
+familiar with X resources). The class name is @code{Limn}. For
+example:
+
+@example
+Limn*geometry: 300x400-0-0
+@end example
+
+@noindent makes the window 300 pixels wide, 400 pixels high, and located
+in the lower right corner of the screen.
+
+
+@node Invoking Limn, , Limn algorithm, Limn
+@section Invoking Limn
+
+@cindex Limn options
+@cindex invocation of Limn
+@cindex options for Limn
+
+This section lists the options that Limn accepts in alphabetic
+order. The previous section described many of these options in the
+context of the fitting algorithm.
+
+@xref{Command-line options}, for general option syntax.
+
+The root of the main input fontname is called @var{font-name} below.
+
+@table @samp
+
+@opindex -align-threshold
+@item -align-threshold @var{real}
+If either coordinate of the endpoints on a spline is closer than this,
+make them the same; default is .5. @xref{Aligning endpoints}.
+
+@opindex -corner-always-threshold
+@item -corner-always-threshold @var{angle-in-degrees}
+If the angle at a pixel is less than this, it is considered a corner,
+even if it is within @samp{corner-surround} pixels of another corner;
+default is 60. @xref{Finding corners}.
+
+@opindex -corner-surround
+@item -corner-surround @var{unsigned}
+Number of pixels on either side of a point to consider when determining
+if that point is a corner; default is 4. @xref{Finding corners}.
+
+@opindex -corner-threshold
+@item -corner-threshold @var{angle-in-degrees}
+If a pixel, its predecessor(s), and its successor(s) meet at an angle
+smaller than this, it's a corner; default is 100. @xref{Finding corners}.
+
+@opindex -display-continue
+@item -display-continue
+If you specified @samp{-do-display}, do not wait for you to hit return
+after displaying each character online. @xref{Displaying fitting online}.
+
+@opindex -display-grid-size
+@item -display-grid-size @var{unsigned}
+Number of expanded pixels between the grid lines; default is 10.
+@xref{Displaying fitting online}.
+
+@opindex -display-pixel-size
+@item -display-pixel-size @var{unsigned}
+Length of one side of the square that each pixel expands into; default
+is 9. @xref{Displaying fitting online}.
+
+@opindex -display-rectangle-size
+@item -display-rectangle-size @var{unsigned}
+Length of one side of the square drawn to represent input pixels;
+default is 6. Must be less than @samp{display-pixel-size}.
+@xref{Displaying fitting online}.
+
+@opindex -do-display
+@item -do-display
+Show the results of the fitting in an X window, if the X server
+specified in the @code{DISPLAY} environment variable can be opened.
+@xref{Displaying fitting online}.
+
+@opindex -dpi
+@item -dpi @var{unsigned}
+The resolution, in pixels per inch. @xref{Common options}.
+
+@opindex -error-threshold
+@item -error-threshold @var{real}
+Subdivide fitted curves that are off by more pixels than this; default
+is 2.0. @xref{Reparameterization}.
+
+@opindex -filter-alternative-surround
+@item -filter-alternative-surround @var{unsigned}
+Another choice for filter-surround; default is 1. @xref{Filtering curves}.
+
+@opindex -filter-epsilon
+@item -filter-epsilon @var{real}
+If the angles using @samp{filter-surround} and
+@samp{filter-alternative-surround} points differ by more than this, use
+the latter; default is 10.0. @xref{Filtering curves}.
+
+@opindex -filter-iterations
+@item -filter-iterations @var{unsigned}
+Smooth the curve this many times before fitting; default is 4.
+@xref{Filtering curves}.
+
+@opindex -filter-percent
+@item -filter-percent @var{percent}
+When filtering, use the old point plus distance of neighbors multiplied
+by this (as a percentage) to determine the new point; default is 33.
+@xref{Filtering curves}.
+
+@opindex -filter-surround
+@item -filter-surround @var{unsigned}
+Number of pixels on either side of a point to consider when filtering
+that point; default is 2. @xref{Filtering curves}.
+
+@opindex -help
+@item -help
+Print a usage message. @xref{Common options}.
+
+@opindex -keep-knees
+@item -keep-knees
+Do not remove ``knees''---points on the inside of the outline that are
+between two others. @xref{Removing knees}.
+
+@opindex -line-reversion-threshold
+@item -line-reversion-threshold @var{real}
+If a spline is closer to a straight line than this, keep it a straight
+line even if it is a list with curves; default is .01 pixels.
+@xref{Changing lines to splines}.
+
+@opindex -line-threshold
+@item -line-threshold @var{real}
+If a spline is not more than this far away from the straight line
+defined by its endpoints, then output a straight line; default is 1.
+@xref{Changing splines to lines}.
+
+@opindex -log
+@item -log
+Write detailed progress reports to @file{@var{font_name}.log}.
+
+@opindex -output-file
+@cindex output file, naming
+@item -output-file @var{filename}
+Write to @var{filename} if it has a suffix and to
+@file{@var{filename}.bzr} if it doesn't. Default is
+@file{@var{font-name}.bzr}.
+
+@opindex -range
+@item -range @var{char1}-@var{char2}
+Only output characters with codes between @var{char1} and @var{char2},
+inclusive. (@xref{Common options}, and @ref{Specifying character codes}.)
+
+@opindex -reparameterize-improve
+@item -reparameterize-improve @var{percent}
+If reparameterization doesn't improve the fit by this much, as a
+percentage, then stop reparameterizing; default is 10.
+@xref{Reparameterization}.
+
+@opindex -reparameterize-threshold
+@item -reparameterize-threshold @var{real}
+If an initial fit is off by more pixels than this, don't bother to
+reparameterize; default is 30. @xref{Reparameterization}.
+
+@opindex -subdivide-search
+@item -subdivide-search @var{percent}
+Percentage of the curve from the initial guess for a subdivision point
+to look for a better one; default is 10. @xref{Subdivision}.
+
+@opindex -subdivide-surround
+@item -subdivide-surround @var{unsigned}
+Number of points on either side of a point to consider when looking for
+a subdivision point; default is 4. @xref{Subdivision}.
+
+@opindex -subdivide-threshold
+@item -subdivide-threshold @var{real}
+If a point is this close or closer to a straight line, subdivide there;
+default is .03 pixels. @xref{Subdivision}.
+
+@opindex -tangent-surround
+@item -tangent-surround @var{unsigned}
+Number of points on either side of a point to consider when computing
+the tangent at that point; default is 3. @xref{Finding tangents}.
+
+@opindex -verbose
+@item -verbose
+Output progress reports.
+
+@opindex -version
+@item -version
+Print the version number.
+
+@end table
diff --git a/doc/overview.texi b/doc/overview.texi
new file mode 100644
index 0000000..987d10f
--- /dev/null
+++ b/doc/overview.texi
@@ -0,0 +1,704 @@
+@c Copyright (C) 1992, 93 Free Software Foundation.
+@c This is part of the GNU font utilities manual.
+@c For copying conditions, see the file fontutil.texi.
+
+@node Overview
+@chapter Overview
+
+@cindex overview
+
+This chapter gives an overview of what you do to create fonts using
+these programs. It also describes some things which are common to all
+the programs.
+
+Throughout this document, we refer to various source files in the
+implementation. If you can read C programs, you may find these
+references useful as points of entry into the source when you are
+confused about some program's behavior, or are just curious.
+
+@menu
+* Picture:: A pictorial overview.
+* Creating fonts:: How to use the programs together.
+* Command-line options:: Many aspects of the command line are
+ common to all programs.
+* Font searching:: How fonts and other files are looked for.
+* Font naming:: How to name fonts.
+@end menu
+
+
+@node Picture
+@section Picture
+
+@cindex picture of program flow
+@cindex information flow, picture of
+
+Following is a pictorial representation of the typical order in which
+these programs are used, as well as their input and output.
+
+GSrenderfont is not in the picture since it is intended for an entirely
+separate purpose (namely, making bitmaps from PostScript outlines).
+Fontconvert also has many functions which are not needed for the basic
+task of font creation from scanned images.
+
+@smallexample
+ ---------------
+ / --------------------- | fontconvert |
+ / ---------------
+ | ^ ^
+scanned v |---------------| |
+image TFM v v
+and IFI ----------- GF ------------- TFM, GF -------- BZR
+========> | imageto | ======> | charspace | =========> | limn | ======...
+ ^ ----------- ------------- ^ --------
+ | ^ | (continued)
+ v CMI v
+------------- --------
+| imgrotate | | xbfe |
+------------- --------
+
+
+
+ Metafont source ------ GF, TFM
+ |=====================> | mf | =========
+ (continued) | ------
+ |
+ BZR --------- TFM, | PostScript Type 1 (gsf)
+... ======> | bzrto |========|=======================
+ --------- |
+ ^ |
+ | | PostScript Type 3 (pf3)
+ CCC |======================
+ |
+ |
+ | BPL ------------ BZR
+ |=========> | bpltobzr | =====
+ ------------
+@end smallexample
+
+@xref{File formats}, for more information on these file formats.
+
+
+@node Creating fonts
+@section Creating fonts
+
+@cindex creating fonts, overview of
+@cindex font creation, overview of
+@cindex information flow, description of
+@cindex overview of font creation
+
+The previous section described pictorially the usual order in which these
+programs are used. This section will do the same in words.
+
+Naturally, you may not need to go through all the steps described here.
+For example, if you are not starting with a scanned image, but already
+have a bitmap font, then the first step---running Imageto---is
+irrelevant.
+
+Here is a description of the usual font creation process, starting with
+a scanned image of a type specimen and ending with fonts which can be
+used by Ghostscript, @TeX{}, etc.
+
+@enumerate
+
+@item
+@cindex image file, viewing
+@cindex scanned image, viewing
+To see what an image @var{I} consists of, run Imageto with either
+@samp{-strips} or @samp{-epsf}. This produces a bitmap font
+@file{@var{I}sp} in which each character is simply a constant number of
+scanlines from the image.
+
+@item
+Run Fontconvert (@pxref{Fontconvert}) on @file{@var{I}sp} with the
+@samp{-tfm} option, to produce a TFM file. This is because of
+the next step:
+
+@item
+@flindex strips.tex
+Run @TeX{} on @file{imageto/strips.tex}, telling @TeX{} to use the
+font @file{@var{I}sp}. This produces a DVI file which you can print or
+preview as you usually do with @TeX{} documents. (If you don't know how
+to do this, you'll have to ask someone knowledgeable at your site, or
+otherwise investigate.) This will (finally) show you what is in the
+image.
+
+An alternative to the above steps is to run Imageto with the
+@samp{-epsf} option. This outputs an Encapsulated PostScript file with
+the image given as a simple PostScript bitmap. Then you can use
+Ghostscript or some other PostScript interpreter to look at the EPS file.
+This method is simpler, but has the disadvantage of using much more
+disk space, and needing a PostScript interpreter.
+
+@item
+If the original was not scanned in the normal orientation, the image
+must be rotated 90 degrees in some direction and/or flipped end for end.
+(Sometimes we have not scanned in the normal orientation because the
+physical construction of the book we were scanning made it difficult or
+impossible.) In this case, you must rotate the image to be upright.
+The program IMGrotate does this, given the @samp{-flip} or
+@samp{rotate-clockwise} option. Given an image @var{RI}, this outputs
+the upright image @var{I}.
+
+@item
+Once you have an upright image @var{I}, you can use Imageto
+(@pxref{Imageto}) to extract the characters from the image and make a
+bitmap font @file{@var{I}.@var{dpi}gf}, where @var{dpi} is the
+resolution of the image in pixels per inch. (If the image itself does
+not contain the resolution, you must specify it on the command line with
+@samp{-dpi}.) To do this, you must first prepare an IFI file describing
+the image. @xref{IFI files}, for a description of IFI files.
+
+@item
+@flindex testfont.tex
+To view the resulting GF file, run Fontconvert to make a TFM file, as
+above. Then run @TeX{} on @file{testfont.tex} and use the @code{\table}
+or @code{\sample} commands to produce a font table. Next, print or
+preview the DVI file that @TeX{} outputs, as before. This will probably
+reveal problems in your IFI file, e.g., that not all the characters are
+present, or that they are not in the right positions. So you need to
+iterate until the image is correctly processed.
+
+@file{testfont.tex} should have come with your @TeX{} distribution. If
+for some reason you do not have it, you can use the one distributed in
+the @file{data} directory.
+
+@item
+Once all the characters have been properly extracted from the image, you
+have a bitmap font. Unlike the above, the following steps all interact
+with each other, in the sense that fixing problems found at one stage may
+imply changes in an earlier stage. As a result, you must expect to
+iterate them several (billion) times.
+
+At any rate, given a bitmap font @var{f} you then run Charspace
+(@pxref{Charspace}) to add side bearings to @var{f}, producing a new
+bitmap font, say @var{g}, and a corresponding TFM file
+@file{@var{g}.tfm}. To do this, you must prepare a CMI file specifying
+the side bearings. @xref{CMI files}, for a description of CMI files.
+
+@item
+To fit outlines to the characters in a bitmap font, run Limn
+(@pxref{Limn}). Given the bitmap font @var{g}, it produces the BZR
+(@pxref{BZR files}) outline font @file{@var{g}.bzr}. The side bearings
+in @var{g} are carried along.
+
+Although Limn will (should) always be able to fit some sort of outline
+to the bitmaps, you can get the best results only by fiddling with the
+(unfortunately numerous) parameters. @xref{Invoking Limn}.
+
+@item
+To convert from the BZR file @file{@var{g}.bzr} that Limn outputs to a
+font format that a typesetting program can use, run BZRto
+(@pxref{BZRto}). While developing a font, we typically convert it to a
+Metafont program (with the @samp{-metafont} option).
+
+As you get closer to a finished font, you may want to prepare a CCC file
+(@pxref{CCC files}) to tell BZRto how construct composite characters
+(pre-accented `A's, for example) to complete the font.
+
+@item
+Given the font in Metafont form, you can then either make
+the font at its true size for some device, or make an enlarged version
+to examine the characters closely. @xref{Metafont and BZRto}, for the
+full details.
+
+Briefly, to do the former, run Metafont with a @code{mode} of whatever
+device you wish (the mode @code{localfont} will get you the most
+common local device, if Metafont has been installed properly). Then you
+can use @file{testfont.tex} to get a font sample, as described above.
+
+To do the latter, run Metafont with no assignment to @code{mode}. This
+should get you @code{proof} mode. You can then use GFtoDVI to get a DVI
+file with one character per page, showing you the control points Limn
+chose for the outlines.
+
+@item
+Problems can arise at any stage. For example, the character spacing
+might look wrong; in that case, you should fix the CMI files and rerun
+Charspace (and all subsequent programs, naturally). Or the outlines
+might not match the bitmaps very well; then you can change the
+parameters to Limn, or use XBfe (@pxref{XBfe}) to hand-edit the bitmaps
+so Limn will do a better job. (To eliminate some of tedium of fixing
+digitization problems in the scanned image, you might want to use the
+filtering options in Fontconvert before hand-editing; see @ref{Character
+manipulation options}.)
+
+Inevitably, as one problem gets fixed you notice new ones @dots{}
+
+@end enumerate
+
+
+@menu
+* Font creation example:: A real-life example.
+@end menu
+
+@node Font creation example, , , Creating fonts
+@subsection Font creation example
+
+@cindex font creation, example of
+@cindex creating a font, example of
+@cindex example of font creation
+@cindex Garamond roman, creating
+
+@cindex English, Paul
+This section gives a real-life example of font creation for the Garamond
+roman typeface, which we worked on concomitantly with developing the
+programs. We started from a scanned type specimen of 30 point Monotype
+Garamond, scanned using a Xerox 9700 scanner loaned to us from
+Interleaf, Inc. (Thanks to Paul English and others at Interleaf for
+this loan.)
+
+@enumerate
+
+To begin, we used Imageto as follows to look at the image file we had
+scanned (@pxref{Viewing an image}). Each line is a separate command.
+@example
+imageto -strips ggmr.img
+fontconvert -tfm ggmrsp.1200
+echo ggmrsp | tex strips.tex
+xdvi -p 1200 -s 10 strips.dvi
+@end example
+
+@item
+@flindex ggmr.ifi
+Next, we created the file @file{ggmr.ifi} (distributed in the
+@file{data} directory), listing the characters in the order they
+appeared in the image, guessing at baseline offsets and (if necessary)
+including bounding box counts. Then we ran Imageto again, this time to
+get information about the baselines and spurious blotches in the image.
+We use the @samp{-encoding} option since some of the characters in the
+image are not in the default @code{ASCII} encoding.
+@example
+imageto -print-guidelines -print-clean-info -encoding=gnulatin ggmr.img
+@end example
+
+@item
+Based on the information gleaned from that run, we decided on the final
+baselines, adjusted the bounding box counts for broken-up characters,
+and extracted the font (@pxref{Image to font conversion}). (In truth,
+this took several iterations.) The design size of the original image
+was stated in the book to be 30@dmn{pt}. We noticed several
+blotches in the image we needed to ignore, and so we added
+@code{.notdef} lines to @file{ggmr.ifi} as appropriate.
+@example
+imageto -verbose -baselines=121,130,120 \
+ -designsize=30 -encoding=gnulatin ggmr.img
+@end example
+
+@item
+To smooth some of the rough edges caused by the scanner's rasterization
+errors, we filtered the bitmaps with Fontconvert (@pxref{Fontconvert}).
+@example
+fontconvert -verbose -gf -tfm -filter-passes=3 -filter-size=3 \
+ ggmr30.1200 -output=ggmr30a
+@end example
+
+@item
+For a first attempt at intercharacter and interword spacing, we created
+@file{ggmr.1200cmi} (also distributed in the @file{data} directory) and
+ran Charspace (@pxref{Charspace}), producing @file{ggmr30b.1200gf} and
+@file{ggmr30b.tfm}. To see the results, we ran @file{ggmr30b} through
+@file{testfont.tex}, modified the CMI file, reran Charspace, etc., until
+the output was somewhat reasonable. We didn't try to fine-tune the
+spacing here, since we knew the following steps would affect the
+character shapes, which in turn would affect the spacing.
+@example
+charspace -verbose -cmi=ggmr.1200cmi ggmr30a.1200 -output=ggmr30b
+@end example
+
+@item
+Next we ran @file{ggmr30b.1200gf}, created by Charspace, through Limn to
+produce the outline font in BZR form, @file{ggmr30b.bzr}. We couldn't
+know what the best values of all the fitting parameters were the first
+time, so we just increased the ones which are relative to the
+resolution.
+@example
+limn -verbose -corner-surround=4 -filter-surround=6 \
+ -filter-alternative-surround=3 -subdivide-surround=6 \
+ -tangent-surround=6 ggmr30b.1200
+@end example
+
+@item
+Then we converted @file{ggmr30b.bzr} to a Metafont program using BZRto
+(@pxref{BZRto}), and then ran Metafont to create TFM and GF files we
+could typeset with (@pxref{Metafont and BZRto}). In order to keep the
+Metafont-generated files distinct from the original TFM and GF files, we
+use the output stem @file{ggmr30B}. To see the results at the usual
+10@dmn{pt}, we then ran the Metafont output through @file{sample.tex} (a
+one-line wrapper for @file{testfont.tex}: @samp{\input testfont \sample
+\end}).
+@example
+bzrto -verbose -metafont ggmr30b -output=ggmr30B
+mf '\mode:=localfont; input ggmr30B'
+echo ggmr30B | tex sample
+dvips sample
+@end example
+
+@item
+This 10@dmn{pt} output looked too small to us. So we changed the design
+size to 26@dmn{pt} (finding the value took several iterations) with
+Fontconvert (@pxref{Fontconvert}), then reran Charspace, Limn, BZRto,
+Metafont, etc., as above. We only show the Fontconvert step here; the
+others have only the filenames changed from the invocations above.
+@example
+fontconvert -verbose -gf -tfm -designsize=26 ggmr30b.1200 -output=ggmr26c
+@end example
+
+@item
+After this, the real work begins. We ran the Metafont program
+@file{ggmr26D.mf} in @code{proof} mode, followed by GFtoDVI, so we could
+see how well Limn did at choosing the control points for the outlines.
+@xref{Proofing with Metafont}. (The @code{nodisplays} tells Metafont
+not to bother displaying each character in a window online.)
+@example
+mf '\mode:=proof; nodisplays; input ggmr26D'
+gftodvi ggmr26D.3656gf
+@end example
+
+@item
+From this, we went and hand-edited the font @file{ggmr26d.1200gf} with
+XBfe (@pxref{XBfe}), and/or tinkered with the options to Limn, trying to
+make the outlines reasonable. We still haven't finished @dots{}
+@end enumerate
+
+
+@node Command-line options
+@section Command-line options
+
+@cindex arguments, specifying program
+@cindex command-line options, syntax of
+@cindex options, specifying program
+@cindex program arguments, syntax of
+@cindex syntax of command-line options
+
+@findex getopt_long_only
+Since these programs do not have counterparts on historical Unix
+systems, they need not conform to an existing interface. We chose to
+have all the programs use the GNU function @code{getopt_long_only} to
+parse command lines.
+
+As a result, you can give the options in any order, interspersed as you
+wish with non-option arguments; you can use @samp{-} or @samp{--} to
+start an option; you can use any unambiguous abbreviation for an option
+name; you can separate option names and values with either @samp{=} or
+one or more spaces; and you can use filenames that would otherwise look
+like options by putting them after an option @samp{--}.
+
+By convention, all the programs accept only one non-option argument,
+which is taken to be the name of the main input file.
+
+If a particular option with a value is given more than once, it is the
+last value which is used.
+
+For example, the following command line specifies the options
+@samp{foo}, @samp{bar}, and @samp{verbose}; gives the value @samp{abc}
+to the @samp{baz} option, and the value @samp{xyz} to the @samp{quux}
+option; and specifies the filename @file{-myfile-}.
+
+@example
+-foo --bar -verb -abc=baz -quux karl -quux xyz -- -myfile-
+@end example
+
+@menu
+* Main input file:: Each program operates on a ``main'' font.
+* Options: Common options. Some options are accepted by all programs.
+* Specifying character codes:: Ways of specifying single characters.
+* Values: Common option values. Some options need more information.
+@end menu
+
+
+@node Main input file, Common options, , Command-line options
+@subsection The main input file
+
+@cindex main input files
+@cindex input filename, specifying
+
+By convention, all the programs accept only one non-option argument,
+which they take to be the name of the main input file.
+
+Usually this is the name of a bitmap font. By their nature, bitmap
+fonts are for a particular resolution. You can specify the resolution
+in two ways: with the @samp{-dpi} option (see the next section), or by
+giving an extension to the font name on the command line.
+
+For example, you could specify the font @code{foo} at a resolution of
+300@dmn{dpi} to the program @var{program} in either of these two ways
+(@samp{$ } being the shell prompt):
+@example
+$ @var{program} foo.300
+$ @var{program} -dpi=300 foo
+@end example
+
+You can also say, e.g., @samp{@var{program} foo.300gf}, but the @samp{gf} is
+ignored. These programs always look for a given font in PK format
+before looking for it in GF format, under the assumption that if both
+fonts exist, and have the same stem, they are the same.
+
+@xref{File lookups, , File lookups, kpathsea, Kpathsearch library}, for
+more details of the filename lookup.
+
+
+@node Common options
+@subsection Common options
+
+@cindex options, common
+@cindex arguments, common command-line
+
+Certain options are available in all or most of the programs. Rather
+than writing identical descriptions in the chapters for each of the
+programs, they are described here.
+
+This first table lists common options which do not convey anything about
+the input. They merely direct the program to print additional output.
+
+@table @samp
+
+@item -help
+@opindex -help
+@cindex help, online
+Prints a usage message listing all available options on standard error.
+The program exits after doing so.
+
+@item -log
+@opindex -log
+@cindex log file
+Write information about everything the program is doing to the file
+@file{@var{foo}.log}, where @var{foo} is the root part of the main input
+file.
+
+@item -verbose
+@opindex -verbose
+@cindex verbose output
+@cindex progress reports
+@cindex status reports
+@cindex standard output, used for verbose output
+@cindex file used for verbose output
+Prints brief status reports as the program runs, typically the character
+code of each character as it is processed. This usually goes to
+standard output; but if the program is outputting other information
+there, it goes to standard error.
+
+@item -version
+@opindex -version
+@cindex version number, finding
+Prints the version number of the program on standard output. If a main
+input file is supplied, processing continues; otherwise, the program
+exits normally.
+
+@end table
+
+This second table lists common options which change the program's
+behavior in more substantive ways.
+
+@table @samp
+
+@item -dpi @var{dpi}
+@cindex dpi, specifying explicitly
+@cindex resolution, specifying explicitly
+@opindex -dpi
+Look for the main input font at a resolution of @var{dpi} pixels per
+inch. The default is to infer the information from the main input
+filename (@pxref{Main input file}).
+
+@item -output-file @var{fname}
+@opindex -output-file
+Write the main output of the program to @var{fname}. If @var{fname} has
+a suffix, it is used unchanged; otherwise, it is extended with some
+standard suffix, such as @file{@var{resolution}gf}. Unless @var{fname}
+is an absolute or explicitly relative pathname, the file is written in
+the current directory.
+
+@item -range @code{@var{start}-@var{end}}
+@opindex -range
+Only look at the characters between the character codes @var{start} and
+@var{end}, inclusive. The default is to look at all characters in the
+font. @xref{Specifying character codes}, for the precise syntax of
+character codes.
+
+@end table
+
+
+@node Specifying character codes, Common option values, Common options, Command-line options
+@subsection Specifying character codes
+
+@cindex character codes, specifying
+
+@flindex charcode.c
+@flindex charspec.c
+Most of the programs allow you to specify character codes for various
+purposes. Character codes are always parsed in the same way (using the
+routines in @file{lib/charcode.c} and @file{lib/charspec.c}).
+
+You can specify the character code directly, as a numeric value,
+or indirectly, as a character name to be looked up in an encoding
+vector.
+
+@menu
+* Named character codes:: Character names are looked up in the encoding.
+* Numeric character codes:: Decimal, octal, hex, or ASCII.
+@end menu
+
+
+@node Named character codes, Numeric character codes, , Specifying character codes
+@subsubsection Named character codes
+
+@cindex character codes, as names
+@cindex naming characters
+
+If a string being parsed as a character code is more than one character
+long, or starts with a non-digit, it is always looked up as a name in
+an encoding vector before being considered as a numeric code. We do
+this because you can always specify a particular value in one of the
+numeric formats, if that's what you want.
+
+The encoding vector used varies with the program; you can always define
+an explicit encoding vector with the @samp{-encoding} option. If you
+don't specify one explicitly, programs which must have an encoding
+vector use a default; programs which can proceed without one do not.
+@xref{Encoding files}, for more details on encoding vectors.
+
+As a practical matter, the only character names which have length one
+are the 52 letters, @samp{A}--@samp{Z}, @samp{a}--@samp{z}. In virtually
+all common cases, the encoding vector and the underlying character set
+both have these in their ASCII positions. (The exception is machines
+that use the EBCDIC encoding.)
+
+
+@node Numeric character codes, , Named character codes, Specifying character codes
+@subsubsection Numeric character codes
+
+@cindex character codes, numeric
+
+The following variations for numeric character codes are allowed. The
+examples all assume the character set is ASCII.
+
+@itemize @bullet
+
+@item
+@cindex octal character code
+Octal numerals preceded by a zero are taken to be an octal number. For
+example, @kbd{0113} also means decimal 75. If a would-be character code
+starts with a zero but contains any characters other than the digits
+@samp{0} through @samp{7}, it is invalid.
+
+@item
+@cindex hexadecimal character code
+Hexadecimal ``digits'' preceded by @samp{0x} or @samp{0X} are taken to
+be a hexadecimal number. Case is irrelevant. For example, @kbd{0x4b},
+@kbd{0X4b}, @kbd{0x4B}, and @kbd{0X4B} all mean decimal 75. As with
+octal, a would-be character code starting with @samp{0x} and containing
+any characters other than @samp{0}--@samp{9}, @samp{a}--@samp{f}, and
+@samp{A}--@samp{F} is invalid.
+
+@item
+@cindex decimal character code
+A decimal number (consisting of more than one numeral) is itself. For
+example, @kbd{75} means the character code decimal 75. As before, a
+would-be character code starting with @samp{1}--@samp{9} and containing
+any characters other than @samp{0}--@samp{9} is invalid.
+
+@item
+A single digit, or a single character not in the encoding vector as a
+name, is taken to represent its value in the underlying character set.
+For example, @kbd{K} means the character code decimal 75, and @kbd{0}
+(the numeral zero) means the character code decimal 48 (if the machine
+uses ASCII).
+
+@item
+If the string being parsed as a character code starts with a digit, the
+appropriate one of the previous cases is applied. If it starts with any
+other character, the string is first looked up as a name.
+
+@end itemize
+
+@cindex maximum character code
+Character codes must be between zero and 255 (decimal), inclusive.
+
+
+@node Common option values, , Specifying character codes, Command-line options
+@subsection Common option values
+
+@cindex common option values
+@cindex option values
+The programs have a few common conventions for how to specify option
+values that are more complicated than simple numbers or strings.
+
+@cindex list as option values
+@cindex option value of a list
+@cindex option values, taking from a file
+Some options take not a single value, but a list. In this case, the
+individual values are separated by commas or whitespace, as in
+@samp{-omit=1,2,3} or @samp{-omit="1 2 3"}. Although using whitespace to
+separate the values is less convenient when typing them interactively,
+it is useful when you have a list that is so long you want to put it in
+the file. Then you can use @file{cat} in conjunction with shell quoting
+to get the value: @samp{-omit="`cat file`"}.
+
+@cindex keyword/value list as option values
+@cindex option value of a keyword/value list
+Other options take a list of values, but each value is a keyword
+and a corresponding quantity, as in @samp{-fontdimens
+@var{name}:@var{real},@var{name},@var{real}}.
+
+@cindex percentages as option values
+@cindex option value of a percentage
+Finally, a few options take percentages, which you specify as an integer
+between 0 and 100, inclusive.
+
+
+@node Font searching
+@section Font searching
+
+@cindex font searching algorithm
+
+These programs use the same environment variables and algorithms for
+finding font files as does (the Unix port of) @TeX{} and its friends.
+
+You specify the default paths in the top-level Makefile. The
+environment variables @code{TEXFONTS}, @code{PKFONTS}, @code{TEXPKS},
+and @code{GFFONTS} override those paths. Both the default paths and the
+environment variable values should consist of a colon-separated list of
+directories.
+
+@vindex GFFONTS @r{environment variable}
+@vindex PKFONTS @r{environment variable}
+@vindex TEXFONTS @r{environment variable}
+@vindex TEXPKS @r{environment variable}
+Specifically, a TFM file is looked for along the path specified by
+@code{TEXFONTS}; a GF file along @code{GFFONTS}, then @code{TEXFONTS}; a
+PK file along @code{PKFONTS}, then @code{TEXPKS}, then @code{TEXFONTS}.
+
+@xref{Path specifications, , Path specifications, kpathsea, Kpathsea
+library}, for details of interpretation of environment variable values.
+
+
+@node Font naming
+@section Font naming
+
+@cindex naming font files
+@cindex font files, naming
+
+Naming font files has always been a difficult proposition at best. On
+the one hand, the names should be as portable as possible, so the
+fonts themselves can be used on almost any platform. On the
+other hand, the names should be as descriptive and comprehensive as
+possible. The best compromise we have been able to work out is
+described in a separate document: @ref{Top, , Introduction, fontname,
+Filenames for @TeX{} fonts}. @xref{Archives}, for where to obtain.
+
+Filenames for GNU project fonts should start with @samp{g}, for the
+``source'' abbreviation of ``GNU''.
+
+@cindex fonts, versions of
+Aside from a general font naming scheme, when @emph{developing} fonts
+you must keep the different versions straight. We do this by appending
+a ``version letter'' @samp{a}, @samp{b}, @dots{} to the main bitmap
+filename. For example, the original Garamond roman font we scanned was
+a 30 point size, so the main filename was @file{ggmr30} (@samp{g} for
+GNU, @samp{gm} for Garamond, @samp{r} for roman). As we ran the font
+through the various programs, we named the output @file{ggmr30b},
+@file{ggmr30c}, and so on.
+
+@cindex outline fonts, naming
+Since the outline fonts produced by BZRto are scalable, we do not
+include the design size in their names. (BZRto removes a trailing
+number from the input name by default.)
diff --git a/doc/update.el b/doc/update.el
new file mode 100644
index 0000000..4611cc9
--- /dev/null
+++ b/doc/update.el
@@ -0,0 +1,6 @@
+;;;; Driver to update all the node pointers and menus in the Texinfo source.
+
+(setq load-path (append '("/usr/local/gnu/lib/emacs/elisp") load-path))
+(require 'texinfo)
+(texinfo-multiple-files-update "fontu.texi" t t)
+(save-some-buffers t)
diff --git a/doc/xbfe.texi b/doc/xbfe.texi
new file mode 100644
index 0000000..46975ee
--- /dev/null
+++ b/doc/xbfe.texi
@@ -0,0 +1,351 @@
+@c Copyright (C) 1992 Free Software Foundation.
+@c This is part of the GNU font utilities manual.
+@c For copying conditions, see the file fontutil.texi.
+
+@node XBfe, BZRedit, BPLtoBZR, Top
+@chapter XBfe
+
+@pindex xbfe
+@cindex bitmap fonts, hand-editing
+@cindex hand-editing bitmap fonts
+@cindex editing bitmap fonts
+
+XBfe (X Bitmap Font Editor) allows you to hand-edit a bitmap font---both
+the shapes (i.e., the pixels) and the metric information (set widths,
+side bearings, and kerning tables).
+
+The input is both a bitmap (GF or PK) font and a corresponding TFM file.
+If you have only a bitmap font for some reason, you can make a TFM file
+with Fontconvert (@pxref{Fontconvert output options}). XBfe outputs (at
+your command) the edited files in the current directory @emph{with the
+same name}, thus possibly replacing the input file.
+
+XBfe is intended to edit existing fonts, not create new ones. For
+example, it does not provide a way to create new characters in a font.
+(you can add characters to a font using Fontconvert, though;
+@pxref{Character selection options}). In terms of its interaction with
+the other font utilities, it is most useful for making character shapes
+more amenable to Limn's outline fitting (@pxref{Limn}).
+
+@menu
+* XBfe usage:: How to edit fonts.
+* Invoking XBfe:: Command-line options.
+@end menu
+
+
+@node XBfe usage, Invoking XBfe, , XBfe
+@section XBfe usage
+
+@cindex XBfe usage
+@cindex usage of XBfe
+
+XBfe attempts to follow established user interface conventions for X
+programs:
+
+@itemize @bullet
+
+@item
+The location of the mouse determines where keyboard input goes.
+
+@item
+In general, it is the release of a mouse button, and not its being
+pressed, that causes action.
+
+@item
+When you've finished typing a piece of information in one of the items
+in the XBfe window, you must hit @key{RET} to cause action.
+
+@findex AsciiText @r{widget}
+@cindex key bindings @r{in XBfe}
+@item
+The text editing facilities for such information are the defaults for
+the @code{AsciiText} widget, which is Emacs-like bindings.
+
+@flindex .Xdefaults
+@cindex XBfe resources, customizing
+@cindex customizing XBfe resources
+@item
+You can customize the bindings of all actions described below, the fonts
+used, window sizes, and so on, via your resource file @file{.Xdefaults}.
+See the documentation in the file
+
+@example
+.../mit/doc/tutorials/resources.txt
+@end example
+
+@cindex class name of XBfe
+@noindent in the X distribution if you aren't familiar with X resources. The
+class name is @code{XBfe}. The font utilities distribution comes with
+an application resource file @file{XBfe} (which must be installed for
+the program to function properly); see that file for possibilities of
+what you might change.
+
+@end itemize
+
+The sections below describe the specific operations XBfe provides.
+
+@menu
+* Controlling XBfe:: Controlling XBfe.
+* Shape: XBfe shape editing. Changing the pixels.
+* Metrics: XBfe metrics editing. Changing the side bearings.
+@end menu
+
+
+@node Controlling XBfe , XBfe shape editing, , XBfe usage
+@subsection Controlling XBfe
+
+This section describes a few operations which do not directly involve
+editing, but rather managing of the editing session itself.
+
+@cindex XBfe, exiting
+@cindex exiting XBfe
+To exit XBfe, click on the @samp{Exit} button. Any changes made since
+the last save are lost.
+
+@cindex XBfe, saving changes
+@cindex saving changes in XBfe
+@vindex TMPDIR
+@flindex /tmp
+To save changes, click on the @samp{Save} button. The new files are
+written in the current directory---unless that would overwrite the input
+files, in which case they are written to the directory @file{/tmp} (or
+the value of the environment variable @code{TMPDIR}, if it's set). When
+you exit XBfe normally, the files are moved from the temporary directory
+to your current directory, thus possibly overwriting the input.
+
+@cindex XBfe, reverting characters
+@cindex reverting characters in XBfe
+@cindex undoing changes in XBfe
+To go back to the last saved version of a character you are editing,
+click on the @samp{Revert} button. This is useful when you've made
+changes you didn't intend. If you exit without saving first, all
+changes (since the last save) will be lost, as mentioned above.
+
+@cindex XBfe, changing characters
+@cindex changing characters in XBfe
+@cindex moving between characters in XBfe
+@cindex next character, finding in XBfe
+@cindex previous character, finding in XBfe
+You can move to the previous character in the font, i.e., the one with
+the character code next smallest to the current one, by clicking on the
+@samp{Prev} button. Similarly, you can move to the next character by
+clicking on the @samp{Next} button. You can move to a specified
+character by typing its character code in the @samp{Char} item and
+hitting @key{RET}. @xref{Specifying character codes}, for the various
+possibilities for character codes.
+
+
+@node XBfe shape editing, XBfe metrics editing, Controlling XBfe , XBfe usage
+@subsection XBfe shape editing
+
+@cindex shape editing
+@cindex character bitmap hand-editing
+@cindex editing character bitmaps
+@cindex hand-editing character bitmaps
+
+@cindex changing pixels
+@cindex inverting pixels
+@cindex pixels, changing
+The most basic operation for editing character bitmaps is to change
+black pixels to white or the reverse; put another way, inverting the
+pixel the mouse is on. You do this by clicking the third mouse button.
+
+@cindex pen tracks
+Technically, this is just a special case of changing more than one
+pixel: when you press the third button, the current pixel inverts; then,
+as you move the mouse, the pixels it touches change to the @emph{color
+the first pixel changed to}. Thus, if you press the third button on a
+white pixel, the mouse effectively becomes a ``black pen'' (until you
+release the button).
+
+@menu
+* Selections:: Marking pixel regions for later operations.
+* Enlarging the bitmap:: Give yourself more room at the edges.
+@end menu
+
+
+@node Selections, Enlarging the bitmap, , XBfe shape editing
+@subsubsection Selections
+
+@cindex selection of rectangles in bitmaps
+@cindex bitmaps, selecting rectangles from
+XBfe supports selection, pasting, and filling operations on a
+rectangle of pixels, as follows.
+
+To select an arbitrary rectangle, press the left mouse button to
+determine the first corner; then move the mouse (with the button still
+down) to update the other corner of the rectangle; and release the
+button to define the rectangle. (If you release the button when the mouse
+is off the character bitmap, the selection rectangle remains unchanged.)
+
+@cindex pasting selections
+@cindex selections, pasting
+Once a rectangle has been selected, you can @dfn{paste} it, either
+within the same character from which it was selected, or in a different
+character. To do this, press the middle button; this outlines the
+region that will be changed; as you move the mouse (with the button
+still down), the outline moves accordingly; when you release the
+middle button, the selected rectangle is pasted onto the current bitmap,
+erasing whatever was in the affected area.
+
+@cindex pasting and flipping or rotating
+@cindex flipping and pasting
+@cindex rotation and flipping
+Pasting has several variations: if you have the @kbd{Alt} (a.k.a.@:
+Meta) key down when you release the middle button, the selection is
+flipped vertically; if the @kbd{Control} key is down, the selection is
+flipped horizontally; and if both are down, the selection is flipped in
+both directions. Here is a minimal example:
+
+@example
+@r{original} @r{vertical} @r{horizontal} @r{both}
+ ** * ** *
+ * ** * **
+@end example
+
+@cindex serifs, unifying
+@cindex consistent serifs
+@noindent This is useful when pasting serifs, since serifs are attached
+to the main stems in different orientations. (Incidentally,
+making the serif shapes consist of exactly the same pixels may actually
+make the serifs look different, because of surrounding character
+features or the difference in orientation. But it is still a good place
+to start.)
+
+@cindex filling rectangles in XBfe
+@cindex erasing rectangles in XBfe
+@cindex selections, filling in XBfe
+@cindex selections, erasing in XBfe
+@cindex rectangles, filling in XBfe
+@cindex rectangles, erasing in XBfe
+You can also fill the selected rectangle, i.e., change it to entirely
+black or white, by holding the @key{Alt} key down and pressing the right
+mouse button. The selection is filled with the color of the pixel the
+mouse is on. This is how you entirely erase a portion of the bitmap.
+
+
+@node Enlarging the bitmap, , Selections, XBfe shape editing
+@subsubsection Enlarging the bitmap
+
+@cindex enlarging bitmaps
+@cindex bitmaps, enlarging
+
+You can enlarge the bitmap on all four sides by clicking on the
+@samp{Expand} button; i.e., this adds one blank row at the top and
+bottom, and one blank column at the left and right. This is useful when
+you need to fill out a truncated curve, lengthen a stem or serif, etc.
+
+XBfe correspondingly changes the side bearings and baseline position so
+that the origin of the character does not change. In other words, the
+new row at the bottom is below the baseline, and the new columns are in
+what was the side bearing space. You can change the baselines with
+Fontconvert (@pxref{Character manipulation options}, and the side
+bearings with Charspace (@pxref{Charspace}).
+
+
+@node XBfe metrics editing, , XBfe shape editing, XBfe usage
+@subsection XBfe metrics editing
+
+@cindex character metrics, hand-editing
+@cindex metrics, hand-editing
+@cindex hand-editing character metrics
+@cindex editing character metrics
+
+@cindex side bearings, hand-editing
+@cindex hand-editing side bearings
+@cindex editing side bearings
+You can change the left side bearing for the current character by typing
+the new value in the @samp{lsb} item (and hitting @key{RET}, as always
+for information you type). Likewise for the right side bearing and the
+@samp{rsb} item. The side bearing values must be integers.
+
+@cindex kerns, hand-editing
+@cindex hand-editing kerns
+@cindex editing kerns
+XBfe shows a box with any kerns for the current character. Each item in
+the kern box looks like @samp{@var{code}: @var{kern}}, where @var{code}
+is the character code (in decimal) of the character kerned with, and
+@var{kern} is the kern distance (in pixels). You can edit the kern
+distances just as with the side bearings; the values here are real
+numbers.
+
+@cindex adding kerns
+@cindex kerns, adding
+@cindex deleting kerns
+@cindex kerns, deleting
+You can add new kerns by typing the character code of the new
+kerned-with character in the @samp{Add kern} item; then a kern item with
+that code is added to the kern box, with a distance of zero (which you
+can then change to whatever you want). Similarly, you can delete a kern
+by typing the character code in the @samp{Del kern} item.
+
+
+@node Invoking XBfe, , XBfe usage, XBfe
+@section Invoking XBfe
+
+@cindex XBfe options
+@cindex invocation of XBfe
+@cindex options for XBfe
+
+This section describes the options that XBfe accepts.
+@xref{Command-line options}, for general option syntax.
+
+@table @samp
+
+@opindex -dpi
+@item -dpi @var{unsigned}
+The resolution, in pixels per inch. @xref{Common options}.
+
+@opindex -expansion
+@cindex pixel expansion
+@cindex expansion pixel display
+@cindex displaying pixels
+@item -expansion @var{unsigned}
+Expand each pixel in the character bitmaps to this many pixels
+square on the display; default is 12, i.e., each pixel in the original
+bitmap will become a 12 by 12 rectangle.
+
+You can't use `=' here to separate the option name and value.
+
+@flindex .Xdefaults
+@cindex resources for X
+@cindex X resources
+@vindex expansion @r{resource}
+You can also set this value by setting the resource @samp{expansion} in
+@file{.Xdefaults}.
+
+@opindex -initial-char
+@cindex first character displayed
+@cindex initial character displayed
+@cindex character displayed, first
+@item -initial-char @var{charcode}
+Initially display the character @var{charcode}; default is the first
+character in the font, i.e., the one with the lowest character code.
+
+@opindex -help
+@item -help
+Print a usage message. @xref{Common options}.
+
+@opindex -output-file
+@item -output-file @var{filename}
+Write the output to @file{@var{filename}.@var{dpi}gf} and
+@file{@var{filename}.tfm}. The default is to use the name of the main
+input file for @var{filename}.
+
+@opindex -version
+@item -version
+Print the version number.
+
+@end table
+
+@cindex X toolkit options
+@cindex options, X toolkit
+@opindex -display
+@cindex X server, specifying
+In addition to the above options, XBfe also accepts the standard X
+toolkit options (and resources), such as @samp{-display} to specify the
+X server to use. See the documentation for any X program for a
+description of these options. Unlike the options above, you cannot use
+@samp{--} to start X toolkit options, nor can you use @samp{=} to
+separate option names and values; for example, neither @samp{--display
+host:0} nor @samp{-display=host:0} are recognized.
diff --git a/fontconvert/ChangeLog b/fontconvert/ChangeLog
new file mode 100644
index 0000000..ec8be64
--- /dev/null
+++ b/fontconvert/ChangeLog
@@ -0,0 +1,604 @@
+Sat Mar 30 07:17:23 1996 Kathy Hargreaves <letters@cs.umb.edu>
+
+ * output-epsf.c: don't assign NAME to OUTPUT_NAME, as NAME is
+ already it. Doc fix.
+
+ * output-gf.c (gf_start_output): copy gf_name and write actual
+ filenames when prepending an `x' to the output filename.
+
+Fri Nov 24 07:03:53 1995 Kathy Hargreaves <karl@cs.umb.edu>
+
+ * main.c: call kpse_set_progname(argv[0]).
+
+Thu Nov 23 06:25:51 1995 Kathy Hargreaves <karl@cs.umb.edu>
+
+ * output-tfm.c: (tfm_start_output): call kpse_find_tfm instead of
+ find_tfm_filename.
+
+ * main.c (tfm): Added warning about below to help.
+
+ * output-tfm.c: (tfm_start_output): Added warning about outputting
+ to a file with the input PL filename except with an `x' prepended,
+ analogous to the one for the GF output filename.
+
+Mon Oct 16 06:11:45 1995 Kathy Hargreaves <karl@cs.umb.edu>
+
+ * output-tfm.c (tfm_start_output): no longer extend output_root to
+ have .pl for pl_name, as pltotf adds it (which may be a bug).
+
+Sat Aug 7 11:55:02 1993 Karl Berry (karl@cs.umb.edu)
+
+ * *.h: types.h now in kpathsea.
+
+Thu Dec 3 15:40:46 1992 Karl Berry (karl@cs.umb.edu)
+
+ * main.c: Don't bother to include getopt.h, cmdline.h already does.
+
+Tue Oct 27 13:01:55 1992 Karl Berry (karl@cs.umb.edu)
+
+ * Version 0.6.
+
+Fri Oct 23 14:15:22 1992 Karl Berry (karl@cs.umb.edu)
+
+ * main.c (main): Remove the -space option.
+ * output-gf.c (gf_finish_output): And remove the code that
+ implemented it.
+ (space_char): And this global.
+ * output-gf.h (space_char): And the decl.
+
+Tue Oct 20 11:54:55 1992 Karl Berry (karl@cs.umb.edu)
+
+ * main.c (main): Change the reporting so the space or newline
+ comes before the character, not after.
+
+ * main.c (main): Don't remove the suffix when making the output
+ filename, as we already did; pass the input name to
+ `gf_start_output', not the full bitmap filename.
+
+Mon Oct 5 10:12:03 1992 Karl Berry (karl@cs.umb.edu)
+
+ * main.c (read_command_line): If -text is given, set `report_file'
+ to stderr.
+
+Sun Oct 4 14:03:53 1992 Karl Berry (karl@cs.umb.edu)
+
+ * output-tfm.c (tfm_start_output): Report the TFM filename if we
+ are reading one.
+
+ * main.c (main): Report the full pathname of the font, not just
+ what the user gave us.
+
+ * main.c (main): Call `tfm_finish_output' before `gf_finish_output'.
+
+Tue Sep 22 16:30:25 1992 Karl Berry (karl@cs.umb.edu)
+
+ * output-gf.c (gf_finish_output): output a newline after the space
+ char's code.
+
+Thu Sep 3 09:30:31 1992 Karl Berry (karl@hayley)
+
+ * Version 0.5.
+
+Mon Aug 24 16:41:02 1992 Karl Berry (karl@hayley)
+
+ * random.c (random_number): seed the random number with the
+ process ID.
+
+Sun Aug 23 13:37:00 1992 Karl Berry (karl@hayley)
+
+ * main.c (USAGE): put a newline before concatenating GETOPT_USAGE.
+
+Fri Jul 3 19:12:36 1992 Karl Berry (karl@hayley)
+
+ * main.c (encoding_name, encoding_info_ptr): delete these globals.
+ (most parsing routines): just use `encoding_info'.
+
+ * main.c (read_command_line): use xparse_charspec for -space.
+
+Sat Jun 27 11:10:01 1992 Kathy Hargreaves (kathy@hayley)
+
+ * main.c (charspec.h, encoding.h, libfile.h): included.
+ (encoding_name, encoding_info, encoding_info_ptr): added.
+ (main): added newline after font_name report.
+ (USAGE): added `encoding', updated `omit'
+ (read_command_line): added `encoding' option.
+ (scan_*): use ARG_SEP instead of a comma. Use xparse_charspec
+ instead of xparse_charcode.
+
+Sun Jun 14 08:45:21 1992 Karl Berry (karl@hayley)
+
+ * output-tfm.c (tfm_output_char): compare elt of `baseline_adjust'
+ to 0, not NULL.
+
+ * output-tfm.c (tfm_do_chars_defaults): update for new tfm routines.
+
+Mon Jun 8 15:24:49 1992 Karl Berry (karl@hayley)
+
+ * output-tfm.c (tfm_do_chars_defaults): pass kern list to
+ tfm_set_kern instead of the whole TFM char.
+
+Fri Jun 5 09:19:27 1992 Karl Berry (karl@hayley)
+
+ * filter.c (filter_once): look at all the pixels, and don't crash
+ when `filter_size' is bigger than the bitmap.
+
+ * main.c (main): `return 0' instead of `exit (0)'. (From Paul Eggert)
+
+Sun May 31 08:04:27 1992 Karl Berry (karl@hayley)
+
+ * main.c: rename `design-size' option to `designsize'.
+
+ * main.c (read_command_line): have the arg to -space be optional,
+ and make the default 32.
+ * output-gf.c (gf_finish_output): report the charcode of the space
+ if we output it.
+
+ * output-tfm.c (tfm_start_font): new routine.
+ (main_input_font_p): new static.
+ (tfm_output_char): don't look in TFM file for the main font if
+ we're on some subsequent (concatenated) font.
+ * output-tfm.h (tfm_start_font): declare it.
+ * main.c (main): call it as we start each font.
+
+ * main.c (main): report the input font names as we process them.
+
+ * main.c (USAGE): doc fix.
+
+Sat May 30 14:54:37 1992 Karl Berry (karl@hayley)
+
+ * output-tfm.c (tfm_start_output): remove any suffix before adding
+ `pl'; prepend an `x' if we'd overwrite the input.
+ (output_tfm_name): new static.
+
+Fri May 29 11:45:05 1992 Karl Berry (karl@hayley)
+
+ * main.c (main): change return type to `int'.
+
+Wed May 27 10:38:45 1992 Karl Berry (karl@hayley)
+
+ * main.c (main): remove `output_basename', and redo the code for
+ deciding on the output name.
+
+Sun May 24 12:40:38 1992 Kathy Hargreaves (kathy@hayley)
+
+ * main.c (fontname_list): doc change.
+
+Fri May 15 09:04:39 1992 Karl Berry (karl@hayley)
+
+ * random.c (random_number): `srand' is now `seed_rand', `rand'
+ is `k_rand'.
+
+Mon May 4 09:31:34 1992 Karl Berry (karl@hayley)
+
+ * output-tfm.c (tfm_do_chars_defaults, tfm_output_char,
+ tfm_finish_output): if we don't have an existing file, don't
+ read from it.
+
+ * output-tfm.c (tfm_start_output): fix designsize algorithm.
+
+ * main.c (report): remove; it's defined in report.c.
+
+Wed Apr 15 15:26:30 1992 Karl Berry (karl@hayley)
+
+ * output-{gf,tfm}.c: `make_output_filename' is now `extend_filename'.
+
+Thu Apr 9 08:20:46 1992 Karl Berry (karl@hayley)
+
+ * output-gf.c (gf_finish_output): convert the space width from
+ points to fixes.
+
+Wed Apr 8 15:16:17 1992 Karl Berry (karl@hayley)
+
+ * output-gf.c (gf_finish_output): output a space character, if
+ desired.
+ (space_char): new global.
+ * gf-output.h (space_char): declare it.
+ * main.c (read_command_line): new option `-space' to set it.
+ (USAGE): document it.
+
+Fri Apr 3 13:30:02 1992 Karl Berry (karl@hayley)
+
+ * random.c: include rand.h; remove conditional decls of RAND_MAX,
+ rand, srand.
+
+Sun Mar 29 19:10:18 1992 Karl Berry (karl at hayley)
+
+ * main.c (read_command_line): remove empty else.
+
+Sat Mar 28 07:48:07 1992 Karl Berry (karl at hayley)
+
+ * Version 0.4.
+
+ * Change copyright years to 1992 only.
+
+Wed Mar 25 08:30:41 1992 Karl Berry (karl at hayley)
+
+ * random.c [!STDC_HEADERS]: declare rand, srand.
+ [!RAND_MAX]: define RAND_MAX.
+ (random_number): use rand instead of drand48.
+
+Mon Mar 23 14:59:49 1992 Kathy Hargreaves (kathy at hayley)
+
+ * output-tfm.c (tfm_start_output): only try to set design size to
+ user's if it's been set.
+
+Sun Mar 22 13:46:31 1992 Kathy Hargreaves (kathy at hayley)
+
+ * output_gf.[hc] (gf_output_char): added DESIGN_SIZE_RATIO.
+ Multiply char's TFM width by this.
+
+ * main.c [design_size_ratio]: added.
+
+ * main.c (main): if unset, set design_size to the bitmap one *after*
+ calling tfm_set_design_size, and then check that it's in range.
+
+ * output_tfm.c (tfm_start_output): added USER_DESIGN_SIZE.
+ Call with `design_size' for USER_DESIGN_SIZE and the bitmap's
+ design size for DEFAULT_DESIGN_SIZE.
+ After saving value in new variable `tfm_file_design_size', zero
+ out tfm_info's design size if got it from a TFM file. After
+ calling tfm_set_header, try setting design_size in following
+ order: to USER_DESIGN_SIZE, tfm_file_design_size,
+ DEFAULT_DESIGN_SIZE.
+
+Sat Mar 21 11:53:04 1992 Kathy Hargreaves (kathy at hayley)
+
+ * output_tfm.c (tfm_start_output): set the fontsize if wasn't done
+ already as a TFM header option.
+ Move TFM_CHECK_DESIGNSIZE from main.
+ Set design size to the default only if it isn't set yet.
+
+Thu Mar 19 12:52:46 1992 Kathy Hargreaves (kathy at hayley)
+
+ * output_tfm.c (tfm_output_char): OR (not AND) the conditions for
+ recalculating dimensions and italic corrections.
+
+Wed Mar 18 12:20:38 1992 Kathy Hargreaves (kathy at hayley)
+
+ * output-tfm.c (tfm_do_chars_defaults): added.
+
+ * output-tfm.c (tfm_output_char): only recalculate dimensions and
+ initialize the italic correction if we've altered the bitmap;
+ otherwise, use that of the original TFM character.
+
+ * output-tfm.c (tfm_finish_output): moved tfm_close_input_file
+ from tfm_start_output to here.
+
+Tue Mar 17 16:01:09 1992 Kathy Hargreaves (kathy at hayley)
+
+ * main.c [USAGE], (read_command_line): added design-size option.
+ (global): moved `design_size' from main.
+
+ * main.c (do_char): filter bitmap if `filter_passes' > 0.
+
+ * filter.[hc]: deleted `wants_filter'; default `filter_passes' to 0.
+
+ * main.c [USAGE], (read_command_line): deleted -filter option.
+
+ * output_tfm.c (tfm_start_ouput): fill in nonrequested TFM header
+ items and fontdimens with tfm_info from input_basename.tfm, if
+ it exists. If it does, zero out the checksum.
+
+
+Mon Mar 16 12:28:15 1992 Kathy Hargreaves (kathy at hayley)
+
+ * output_tfm.c (tfm_start_ouput): call tfm_set_header.
+ Set tfm_info's design size only if unset.
+
+ * main.c [USAGE], (read_command_line): added -tfm-header option.
+
+Sun Mar 15 16:49:32 1992 Karl Berry (karl at hayley)
+
+ * main.c: doc fix.
+
+Sat Mar 7 13:11:59 1992 Kathy Hargreaves (kathy at hayley)
+
+ * main.c (main): fatal if wants_gf and want_tfm and the output
+ filename has a suffix.
+
+Sat Mar 7 09:52:57 1992 Karl Berry (karl at hayley)
+
+ * GNUmakefile (libraries): define again.
+ (files, headers, sources): replace with `c_and_h', etc.
+
+Thu Mar 5 17:50:04 1992 Karl Berry (karl at claude.cs.umb.edu)
+
+ * main.c (do_char): do the baseline adjustment after
+ randomization, to preserve the baselines when randomizing.
+ * random.c (randomize_bitmap): return the number of rows/columns
+ added at each side of the bitmap.
+ * random.h (randomize_bitmap): change declaration.
+
+ * main.c (do_char): use puts instead of printf where possible.
+
+Wed Mar 4 15:31:23 1992 Kathy Hargreaves (kathy at hayley)
+
+ * output_tfm.c (tfm_start_output): changed OUTPUT_BASENAME to
+ OUTPUT_NAME and call make_output_filename to make pl_name.
+
+ * output_epst.c (epsf_start_output): changed global
+ `output_basename' to `output_name' and BASE_NAME to NAME.
+ Fatal if NAME has a suffix.
+
+ * output-gf.c (gf_start_output): changed `font_basename' to
+ `output_name' and call make_output_filename to make gf_name.
+
+Wed Mar 4 11:18:22 1992 Karl Berry (karl at hayley)
+
+ * GNUmakefile (libraries): remove.
+
+Mon Feb 10 16:09:25 1992 Karl Berry (karl at claude.cs.umb.edu)
+
+ * random.c (random_threshold): new global to say how often to move a
+ pixel at all.
+ * random.h (random_threshold): declare it.
+ * main.c (read_command_line): new option `random-threshold.
+
+ * output-tfm.c (tfm_start_output): check for a TFM file if the
+ user hasn't given us a fontdimen string. Take the input
+ filename to construct the TFM name.
+ * output-tfm.h (tfm_start_output): change declaration.
+ * main.c (main): change call.
+
+Mon Feb 10 10:04:00 1992 Karl Berry (karl at hayley)
+
+ * main.c (do_split_char, do_char): free the bitmap here.
+ (main): not here.
+
+ * random.c (randomize_bitmap): fix algorithm for pixels moved more
+ than one.
+
+Thu Feb 6 18:26:11 1992 Karl Berry (karl at claude.cs.umb.edu)
+
+ * random.c (enlarge_bitmap): return the result, of changing an arg.
+
+ * random.c: do not include global.h and <math.h>; they already are.
+
+Sat Feb 1 15:16:13 1992 Karl Berry (karl at hayley)
+
+ * output-gf.c: include filename.h.
+
+Fri Jan 31 17:07:31 1992 Karl Berry (karl at hayley)
+
+ * main.c (read_command_line): declare `option_index' (for new
+ getopt).
+
+Wed Jan 22 12:49:25 1992 Kathy Hargreaves (kathy at hayley)
+
+ * output-gf.c (gf_start_output): use make_prefix instead of concat
+ when prepending an `x' onto a filename.
+
+Thu Jan 9 08:30:12 1992 Karl Berry (karl at hayley)
+
+ * main.c (scan_column_split): rename `scan_integer_list' to
+ `scan_unsigned_list'.
+
+ * *.c: do not include global.h.
+
+ * *.h: remove #pragma once.
+
+Wed Jan 8 15:28:56 1992 Karl Berry (karl at hayley)
+
+ * update copyright messages.
+
+ * change `allocate to `xmalloc', `reallocate' to `xrealloc', and
+ `string_copy' to `strdup'.
+
+Mon Jan 6 16:49:26 1992 Karl Berry (karl at claude.cs.umb.edu)
+
+ * main.c (USAGE): new option `randomize'.
+ (do_char): if set, call `randomize_bitmap'.
+ * random.[ch]: new files.
+ (random_max): new global.
+
+Thu Sep 12 10:24:14 1991 Karl Berry (karl at hayley)
+
+ * main.c (read_command_line): new option, `-epsf'.
+ (main): initialize and finalize epsf output (if desired).
+ (do_char): output the characters in epsf (if desired).
+ * epsf-output.[ch]: new files.
+ * GNUmakefile (files): add `epsf-output'.
+
+ * output-tfm.c (tfm_output_char): set the character code.
+
+Tue Jul 30 13:17:47 1991 Karl Berry (karl at ra.cs.umb.edu)
+
+ * Version 0.3.
+
+Mon Jun 17 15:21:49 1991 Karl Berry (karl at hayley)
+
+ * output-tfm.c (tfm_output_char): change calls to `PIXELS_TO_POINTS'.
+
+Thu Jun 6 07:26:13 1991 Karl Berry (karl at hayley)
+
+ * All files: change to version 2 of the GPL.
+
+Sun Mar 24 16:22:44 1991 Karl Berry (karl at hayley)
+
+ * main.c (read_command_line): don't concatenate with the old
+ fontdimens, just assign `fontdimens' from the argument.
+ * output-tfm.c (fontdimens): move definition of global here from
+ `main.c'.
+ * output-tfm.h (fontdimens): declare it.
+
+Sun Mar 10 10:21:52 1991 Karl Berry (karl at hayley)
+
+ * output-tfm.c (tfm_start_output): call `tfm_init_global_info',
+ and don't bother setting the checksum and coding scheme.
+
+Sat Mar 9 16:17:39 1991 Karl Berry (karl at hayley)
+
+ * GNUmakefile (files): add main, since we now have main.h.
+ * main.h: new file.
+ * main.c (read_command_line): new option `-fontdimens'.
+ * output-tfm.c (tfm_start_output): set the font parameters
+ according to -fontdimens.
+
+Thu Mar 7 07:32:21 1991 Karl Berry (karl at hayley)
+
+ * Version 0.2.
+
+Tue Mar 5 15:19:04 1991 Karl Berry (karl at hayley)
+
+ * main.c (scan_baseline_adjust): new routine.
+ (baseline_adjust): new global variable.
+ (read_command_line): new option `-baseline-adjust'.
+ (do_char): adjust the baselines of each character before we
+ process it.
+
+Mon Mar 4 14:42:30 1991 Karl Berry (karl at hayley)
+
+ * main.c (do_char): don't do a character if we've already done it.
+
+ * main.c (fontname_list): new global variable to hold all the
+ fonts we deal with.
+ (read_command_line): new option `-concat-lists'.
+
+Tue Feb 26 06:45:57 1991 Karl Berry (karl at hayley)
+
+ * output-tfm.c (tfm_finish_output): call `tfm_convert_pl' with the
+ argument `verbose'.
+
+Mon Feb 25 13:30:57 1991 Karl Berry (karl at hayley)
+
+ * output-gf.c: use `gf_...' instead of `..._gf_...'.
+
+ * output-tfm.c: use `tfm_...' instead of `..._tfm_...'.
+
+ * output-gf.c: include file-misc.h.
+
+Sun Feb 17 09:30:23 1991 Karl Berry (karl at hayley)
+
+ * *.c: include config.h.
+
+Sun Jan 13 16:49:03 1991 Karl Berry (karl at hayley)
+
+ * main.c (read_command_line): set `explicit_dpi' via the option
+ table.
+
+Mon Jan 7 15:09:15 1991 Karl Berry (karl at hayley)
+
+ * main.c: include file-misc.h.
+
+Sun Nov 4 09:23:28 1990 Karl Berry (karl at hayley)
+
+ * filter.c (read_command_line): use atou to do -filter-size.
+
+ * These changes suggested by rich@rice.edu:
+ * filter.h (filter_passes): declare it.
+ * filter.c (filter_passes): new variable.
+ (filter_bitmap): loop through the number of passes.
+ (filter_once): new routine.
+ * main.c (read_command_line): new option, `filter-passes'.
+ * README: warn that filtering rounds off corners.
+
+Wed Oct 24 14:58:15 1990 Karl Berry (karl at aten)
+
+ * Version 0.1.
+
+Sun Oct 14 07:05:51 1990 Karl Berry (karl at hayley)
+
+ * filter.c (filter_bitmap): don't invert the pixel, set it to the
+ right intensity.
+
+Tue Oct 9 09:43:03 1990 Karl Berry (karl at hayley)
+
+ * main.c (read_command_line): new option, -output-file.
+ (output_name): new global.
+ (main): use it, if it's set.
+
+ * main.c (do_split_char, do_char, scan_column_split): new
+ routines.
+ (read_command_line): new argument, -column-split.
+ (main): split each character at given columns, if requested.
+
+Mon Oct 8 05:55:50 1990 Karl Berry (karl at hayley)
+
+ * main.c: include cmdline.h.
+
+ * main.c (main): filter the character, if desired.
+ (read_command_line): new options -filter, -filter-size,
+ -filter-threshold.
+ * filter.h, filter.c: new files.
+ * GNUmakefile (files): add filter.
+ (This stuff contributed by rich@rice.edu.)
+
+Tue Oct 2 17:25:22 1990 Karl Berry (karl at hayley)
+
+ * output-gf.c (gf_start_output): assign to gf_name after the
+ warning, not before.
+
+Sat Sep 29 07:10:11 1990 Karl Berry (karl at hayley)
+
+ * output-gf.c (gf_start_output): announce it to the user when we
+ change the output filename.
+
+ * main.c (main): use atou (dpi), not atoi.
+
+Fri Sep 28 13:47:34 1990 Karl Berry (karl at hayley)
+
+ * main.c (read_command_line): new argument, `omit'.
+ (scan_remap_list): don't make a target character code of -1 mean
+ omit the original.
+ (scan_omit_list): new routine.
+
+Fri Sep 21 11:32:45 1990 Karl Berry (karl at hayley)
+
+ * main.c (read_command_line): return NULL at the end.
+
+Fri Sep 14 12:01:26 1990 Karl Berry (karl at hayley)
+
+ * main.c: include "getopt.h", not <getopt.h>.
+
+Thu Sep 13 10:58:45 1990 Karl Berry (karl at hayley)
+
+ * main.c (main): report omitted characters.
+
+Tue Sep 11 07:02:50 1990 Karl Berry (karl at hayley)
+
+ * main.c (scan_remap_list): set `omit' if a target ``character
+ code'' is -1. Also, parse the character codes correctly.
+ (omit): new global variable.
+ (main): if `omit' is true, skip the character.
+
+Sat Sep 8 10:58:03 1990 Karl Berry (karl at hayley)
+
+ * main.c (scan_remap_list): use PARSE_CHAR_CODE.
+
+ * main.c (read_command_line): use GET_RANGE.
+
+Thu Sep 6 06:42:24 1990 Karl Berry (karl at hayley)
+
+ * main.c (scan_remap_list): new routine.
+ (read_command_line): new option, -remap.
+ (translate): new global to remap character codes.
+ (main): map each character as we read it.
+
+Wed Sep 5 06:22:18 1990 Karl Berry (karl at hayley)
+
+ * output-gf.c (gf_start_output): don't overwrite the input file.
+ * main.c (main): pass the filename of the input font.
+
+ * main.c (main): output a GF file if asked.
+ (read_command_line): new option, -gf.
+ * output-gf.[ch]: new files.
+ * GNUmakefile (files): add them.
+
+ * main.c (main): free the bitmap for each character. */
+
+ * main.c (main): output a TFM file if asked.
+ (read_command_line): new option, -tfm.
+ * output-tfm.[ch]: new files.
+ * GNUmakefile (files): add them.
+
+Sat Sep 1 09:27:14 1990 Karl Berry (karl at hayley)
+
+ * main.c (main): output a newline at the end of the program if
+ warranted.
+
+ * main.c (main): use `get_bitmap_font' instead of `get_font'.
+
+Sat Aug 25 13:52:43 1990 Karl Berry (karl at hayley)
+
+ * main.c (main): print a newline before each character output as
+ text.
diff --git a/fontconvert/GNUmakefile b/fontconvert/GNUmakefile
new file mode 100644
index 0000000..f8dec27
--- /dev/null
+++ b/fontconvert/GNUmakefile
@@ -0,0 +1,29 @@
+# Makefile for font conversion program.
+#
+# 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.
+
+program = fontconvert
+
+c_and_h = filter main output-epsf output-gf output-tfm random
+c_only = version
+
+libraries = $(bitmap_libs) tfm
+
+include ../data/defs.make
+include ../data/defsprog.make
+
+include M.depend
diff --git a/fontconvert/README b/fontconvert/README
new file mode 100644
index 0000000..e5da2ac
--- /dev/null
+++ b/fontconvert/README
@@ -0,0 +1,18 @@
+This program converts a bitmap font file to ``something else''. For
+example, a representation as plain text; a TFM file; or a GF file.
+
+Plain text is useful if you want to see exactly which pixels are on and
+off in the bitmaps.
+
+Having a TFM file is necessary to use the font with TeX. No side
+bearings, kerning, or ligature information is added to the TFM file, so
+it is only useful for proofing, but that's better than nothing.
+
+You can also select a range of characters, omit individual characters,
+and change the character codes. With these options, you want to output
+another bitmap file; hence, the last option.
+
+You can also filter the bitmaps through a simple averaging filter. This
+is useful as a preliminary cleanup of scanned images. The filtering
+removes a fair amount of the noise, but it also fills in and/or rounds
+off sharp corners.
diff --git a/fontconvert/filter.c b/fontconvert/filter.c
new file mode 100644
index 0000000..29fed9d
--- /dev/null
+++ b/fontconvert/filter.c
@@ -0,0 +1,101 @@
+/* filter.c: run an averaging filter over a bitmap.
+ This code is based on an initial implementation written by Richard Murphey.
+
+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 "filter.h"
+
+
+/* How many passes to make over the bitmap. (-filter-passes) */
+unsigned filter_passes = 0;
+
+/* How many rows and columns of neighbors to look at; i.e., a side of
+ the filter cell is `filter_size' * 2 - 1. Although only values > 0
+ are meaningful, if we make it unsigned, comparisons to ints below
+ fail. (-filter-size) */
+int filter_size = 1;
+
+/* The filter threshold at which we change the pixel.
+ (-filter-threshold) */
+real filter_threshold = .5;
+
+
+static void filter_once (bitmap_type);
+
+/* Filter the bitmap B `filter_passes' times. */
+
+void
+filter_bitmap (bitmap_type b)
+{
+ unsigned this_pass;
+
+ for (this_pass = 0; this_pass < filter_passes; this_pass++)
+ filter_once (b);
+}
+
+
+/* Filter the bitmap in B with an averaging filter. See, for example,
+ Digital Image Processing, by Rosenfeld and Kak. The general idea is
+ to average the intensity of the neighbors of each pixel. If the
+ difference between the pixel value and the intensity is more than
+ `filter_threshold', flip the value of the pixel. */
+
+static void
+filter_once (bitmap_type b)
+{
+ unsigned row, col;
+ unsigned all_black = SQUARE (2 * filter_size + 1) - 1;
+ unsigned t = filter_threshold * all_black; /* Rounded threshold. */
+
+ /* For each pixel in the bitmap... */
+ for (row = 0; row < BITMAP_HEIGHT (b); row++)
+ {
+ /* Don't look at pixels outside the bitmap. */
+ unsigned min_row = MAX ((int) row - filter_size, 0);
+ unsigned max_row = MIN (row + filter_size, BITMAP_HEIGHT (b) - 1);
+
+ for (col = 0; col < BITMAP_WIDTH (b); col++)
+ {
+ int cell_row, cell_col;
+ unsigned sum = 0;
+
+ unsigned min_col = MAX ((int) col - filter_size, 0);
+ unsigned max_col = MIN (col + filter_size, BITMAP_WIDTH (b) - 1);
+
+ /* For each pixel in the cell... */
+ for (cell_row = min_row; cell_row <= max_row; cell_row++)
+ for (cell_col = min_col; cell_col <= max_col; cell_col++)
+ {
+ sum += BITMAP_PIXEL (b, cell_row, cell_col);
+ }
+
+ /* Subtract the value for the pixel we're actually on. I'm not
+ sure why this is a good idea. (It is much more efficient to
+ do this than test for every pixel, though.) */
+ sum -= BITMAP_PIXEL (b, row, col);
+
+ /* We've computed the sum of the neighbors. Now change the
+ pixel if the difference is greater than the threshold. Doing
+ integer arithmetic is not as precise as floating point (since
+ the threshold is rounded), but it's much faster. */
+ if (abs (sum - (all_black * BITMAP_PIXEL (b, row, col))) > t)
+ BITMAP_PIXEL (b, row, col) = ((double) sum) / all_black;
+ }
+ }
+}
diff --git a/fontconvert/filter.h b/fontconvert/filter.h
new file mode 100644
index 0000000..0e1dc4b
--- /dev/null
+++ b/fontconvert/filter.h
@@ -0,0 +1,33 @@
+/* filter.h: declarations for filtering a bitmap.
+
+Copyright (C) 1992, 93 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. */
+
+#ifndef FILTER_H
+#define FILTER_H
+
+#include <kpathsea/types.h>
+#include "bitmap.h"
+
+
+/* See filter.c. */
+extern unsigned filter_passes;
+extern int filter_size;
+extern real filter_threshold;
+
+extern void filter_bitmap (bitmap_type);
+
+#endif /* not FILTER_H */
diff --git a/fontconvert/main.c b/fontconvert/main.c
new file mode 100644
index 0000000..a50b311
--- /dev/null
+++ b/fontconvert/main.c
@@ -0,0 +1,747 @@
+/* fontconvert -- various operations on a bitmap font.
+
+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 "charspec.h"
+#include "cmdline.h"
+#include "encoding.h"
+#include "font.h"
+#include "libfile.h"
+#include "list.h"
+#include "report.h"
+
+#include "filter.h"
+#include "output-epsf.h"
+#include "output-gf.h"
+#include "output-tfm.h"
+#include "random.h"
+
+
+/* How much to adjust the baseline of output characters by. We rely on
+ this being initialized to all zeros by C. (-baseline-adjust) */
+int baseline_adjust[MAX_CHARCODE + 1];
+
+/* If `column_split[N]' is non-NULL, we break character N into new
+ characters at each of the columns specified. We depend on this being
+ initialized to all zeros. (-column-split) */
+int *column_split[MAX_CHARCODE + 1];
+
+/* The names of fonts to be concatenated onto the main font in the
+ output. (-concat) */
+list_type fontname_list;
+
+/* The resolution of the font we will read, in pixels per inch. We
+ don't deal with nonsquare pixels. (-dpi) */
+string dpi = "300";
+
+/* The design size which will affect both the GF and TFM output, unless
+ the tfm-header `designsize' option overrides it. (-designsize)
+ `design_size_ratio' is the ratio of the input design size to the
+ output design size. */
+real design_size = 0.0;
+static real design_size_ratio;
+
+/* The name of the encoding file specified by the user, and the
+ structure we parse it into. (-encoding) */
+static encoding_info_type *encoding_info = NULL;
+
+/* If `omit[n]' is true for an element N, we throw away that character
+ in that output. (-omit) */
+static boolean omit[MAX_CHARCODE + 1];
+
+/* An explicitly specified output filename. (-output-file) */
+const_string output_name = NULL;
+
+/* Says which characters we should process. This is independent of the
+ ordering in the font file. (-range) */
+int starting_char = 0;
+int ending_char = MAX_CHARCODE;
+
+/* The variable `translate' maps character codes in the input font to
+ character codes in the output; by default, maps everything to
+ themselves. (-remap) */
+charcode_type translate[MAX_CHARCODE + 1];
+
+/* Says whether to output an EPS file for each character. (-epsf) */
+boolean wants_epsf = false;
+
+/* Says whether to output a GF file. (-gf) */
+boolean wants_gf = false;
+
+/* Says whether to output the font as plain text. (-text) */
+boolean wants_text = false;
+
+/* Says whether to output a TFM file. (-tfm) */
+boolean wants_tfm = false;
+
+
+
+static void append_concat_list (list_type *, string);
+static bitmap_type column_extract (bitmap_type, unsigned, unsigned);
+static void do_char (char_info_type);
+static void do_split_char (char_info_type, int[]);
+static string read_command_line (int, string []);
+static void scan_baseline_adjust (string);
+static void scan_column_split (string);
+static void scan_omit_list (string);
+static void scan_remap_list (string);
+
+/* Fontconvert provides a grabbag of operations: almost every
+ manipulation on bitmap fonts we found useful we threw here. */
+
+int
+main (int argc, string argv[])
+{
+ int code;
+ bitmap_font_type f;
+ string *first_element;
+ string font_name;
+ unsigned this_font;
+ unsigned char_count = 0;
+
+ /* Use Kpathsea path searching. */
+ kpse_set_progname (argv[0]);
+
+ /* Initialize the character code translation array before parsing the
+ command line, since we probably will not be told to remap every
+ character. */
+ for (code = 0; code <= MAX_CHARCODE; code++)
+ translate[code] = code;
+
+ /* Initialize the list of fonts to do to have one empty element at the
+ beginning, which we will fill in with the main font name. */
+ fontname_list = list_init ();
+ first_element = LIST_TAPPEND (&fontname_list, string);
+
+ /* Read all the arguments. */
+ font_name = read_command_line (argc, argv);
+
+ /* Put the main font name in the list. */
+ *first_element = font_name;
+
+ /* If no output name was specified on the command line, use the root
+ part of the input name. We've already removed the suffix in
+ `read_command_line'. */
+ if (output_name == NULL)
+ output_name = basename (font_name);
+
+ if (wants_gf && wants_tfm && find_suffix (output_name) != NULL)
+ FATAL ("The GF and TFM output files' suffixes can't be the same");
+
+ /* Open the main font specially, since we need to know some basic
+ information for most of the output formats. We don't need to close
+ it again, as opening a font twice does no harm. */
+ f = get_bitmap_font (font_name, atou (dpi));
+
+ if (wants_epsf)
+ epsf_start_output (output_name);
+ if (wants_gf)
+ gf_start_output (font_name, output_name, dpi,
+ BITMAP_FONT_COMMENT (f));
+ if (wants_tfm)
+ tfm_start_output (font_name, output_name, design_size,
+ BITMAP_FONT_DESIGN_SIZE (f));
+
+
+ /* Have to do this after `tfm_start_output', as it needs to know if
+ design_size is set or not. */
+ if (design_size == 0.0)
+ design_size = BITMAP_FONT_DESIGN_SIZE (f);
+
+ design_size_ratio = BITMAP_FONT_DESIGN_SIZE (f) / design_size;
+
+ /* Go through each input font. */
+ for (this_font = 0; this_font < LIST_SIZE (fontname_list); this_font++)
+ {
+ string font_name = *(string *) LIST_ELT (fontname_list, this_font);
+ f = get_bitmap_font (font_name, atou (dpi));
+
+ if (wants_tfm)
+ tfm_start_font (font_name);
+
+ REPORT1 ("(%s", BITMAP_FONT_FILENAME (f));
+
+ /* The main loop: convert each character. */
+ for (code = starting_char; code <= ending_char; code++)
+ {
+ char_info_type *c = get_char (font_name, code);
+
+ if (c == NULL) continue;
+
+ REPORT2 ("%c[%u", ++char_count % 8 ? ' ' : '\n', code);
+
+ if (omit[code])
+ REPORT (" omit");
+ else
+ {
+ /* If this character isn't supposed to split, just output it.
+ Otherwise, output each of the pieces after splitting. */
+ if (column_split[code] == NULL)
+ do_char (*c);
+ else
+ do_split_char (*c, column_split[code]);
+ }
+
+ REPORT ("]");
+ }
+
+ close_font (font_name);
+ REPORT (")\n");
+ }
+
+ if (wants_epsf)
+ epsf_finish_output ();
+
+ /* We must finish the TFM output before GF, because `gf_finish_output'
+ might want to open a TFM file -- and we can only have one TFM file
+ open at a time. (Because we haven't rewritten the TFM library.) */
+ if (wants_tfm)
+ tfm_finish_output ();
+
+ if (wants_gf)
+ gf_finish_output (design_size, atof (dpi));
+
+ return 0;
+}
+
+/* Output the character in whatever forms have been requested. */
+
+static void
+do_char (char_info_type c)
+{
+ static boolean char_done_p[MAX_CHARCODE + 1];
+
+ charcode_type original_code = CHARCODE (c);
+
+ /* Do the character code translation. */
+ charcode_type code = CHARCODE (c) = translate[original_code];
+
+ if (char_done_p[code])
+ {
+ WARNING1 ("Character %d already output", CHARCODE (c));
+ return;
+ }
+
+ char_done_p[code] = true;
+
+ if (filter_passes > 0)
+ filter_bitmap (CHAR_BITMAP (c));
+
+ if (random_max > 0.0)
+ {
+ bounding_box_type adjust_bb;
+ randomize_bitmap (&CHAR_BITMAP (c), &adjust_bb);
+ CHAR_MIN_ROW (c) -= MIN_ROW (adjust_bb);
+ CHAR_MAX_ROW (c) += MAX_ROW (adjust_bb);
+ CHAR_MIN_COL (c) -= MIN_COL (adjust_bb);
+ CHAR_MAX_COL (c) += MAX_COL (adjust_bb);
+ }
+
+ /* If the `baseline_adjust' value is positive, the baseline should
+ move up, i.e., we subtract from the height and add to the depth.
+ But since the depth is represented as the minimum row, which can be
+ negative, we must subtract from it to make it ``larger''. */
+ CHAR_MIN_ROW (c) -= baseline_adjust[code];
+ CHAR_MAX_ROW (c) -= baseline_adjust[code];
+
+ /* Text output is already implemented in the library. */
+ if (wants_text)
+ {
+ puts ("\f");
+ print_char (stdout, c);
+ }
+
+ if (wants_epsf)
+ epsf_output_char (c);
+
+ if (wants_gf)
+ gf_output_char (c, design_size_ratio);
+
+ if (wants_tfm)
+ tfm_output_char (c, atof (dpi));
+
+ if (original_code != code)
+ REPORT1 ("->%u", code);
+
+ /* Free the space here, instead of in the caller, since we may
+ change the bitmap. */
+ free_bitmap (&CHAR_BITMAP (c));
+}
+
+
+/* Output the character C in pieces, the division points being the
+ columns in SPLIT. */
+
+static void
+do_split_char (char_info_type c, int split[])
+{
+ unsigned last_col = 0;
+ unsigned n_split = 0;
+
+ REPORT (" (");
+
+ /* We exit the loop after splitting the last character. */
+ while (true)
+ {
+ int diff;
+ char_info_type split_char = c;
+ int this_col = *split++;
+ unsigned split_col = this_col != -1
+ ? this_col : BITMAP_WIDTH (CHAR_BITMAP (c));
+
+ /* Change the character code of this piece. */
+ CHARCODE (split_char) += n_split;
+
+ REPORT1 ("%u", CHARCODE (split_char));
+
+ /* Take the chunk from the big bitmap. */
+ CHAR_BITMAP (split_char)
+ = column_extract (CHAR_BITMAP (c), last_col, split_col);
+
+ /* Move the right column over. */
+ diff = BITMAP_WIDTH (CHAR_BITMAP (c))
+ - BITMAP_WIDTH (CHAR_BITMAP (split_char));
+ CHAR_MAX_COL (split_char) -= diff;
+ CHAR_SET_WIDTH (split_char) -= diff;
+
+ /* Output it. */
+ do_char (split_char);
+
+ /* Exit the loop if we just output the last piece. */
+ if (this_col == -1)
+ break;
+
+ n_split++;
+ last_col = this_col;
+ REPORT (",");
+ }
+
+ REPORT (")");
+ free_bitmap (&CHAR_BITMAP (c));
+}
+
+/* Return the part of the bitmap SOURCE that lies between the columns
+ START and FINISH - 1, inclusive. */
+
+static bitmap_type
+column_extract (bitmap_type source, unsigned start, unsigned finish)
+{
+ unsigned this_row;
+ dimensions_type d = { BITMAP_HEIGHT (source), finish - start };
+ bitmap_type answer = new_bitmap (d);
+
+ /* Move to the given starting column. */
+ BITMAP_BITS (source) += start;
+
+ for (this_row = 0; this_row < BITMAP_HEIGHT (source); this_row++)
+ {
+ one_byte *answer_row = BITMAP_ROW (answer, this_row);
+
+ memcpy (answer_row, BITMAP_BITS (source), BITMAP_WIDTH (answer));
+ BITMAP_BITS (source) += BITMAP_WIDTH (source);
+ }
+
+ return answer;
+}
+
+/* Reading the options. */
+
+/* This is defined in version.c. */
+extern string version_string;
+
+#define USAGE "Options:
+<font_name> should be a filename, possibly with a resolution, e.g.,
+ `cmr10' or `cmr10.300'.\n" \
+ GETOPT_USAGE \
+"baseline-adjust <char1>:<integer1>,<char2>:<integer2>,...: move the baseline
+ of each <char> by the corresponding <integer>. A positive number
+ moves the baseline up, a negative one down.
+column-split <char>@<column1>,...,<columnN>: split the character with
+ code <char> (before remapping) before each of the <column>s, producing n
+ new characters, with codes <char>, <char> + 1, ..., <char> + n, whose
+ bitmaps go from 0 to <column1> - 1 (inclusive), then <column1> to
+ <column2> - 1, ..., from <columnN> to the bitmap width.
+ Give the <column>s in bitmap coordinates, i.e., starting at zero.
+ To split more than one character, give this option for each.
+concat <font_name>,<font_name>,...: concatenate the main input font with
+ the given <font_name>s; if a character code exists in more than one
+ font, it's the first occurrence that counts.
+designsize <real>: use this as the design size for both the GF and TFM
+ output files, if any, unless overridden by `designsize' in the
+ `tfm-header' option.
+dpi <unsigned>: use a resolution of <unsigned>; default is 300.
+encoding <filename>: read encoding information for the character specs
+ from `<filename>.enc'; there is no default. Must come before any
+ options which use character specs.
+epsf: output each character as an Encapsulated PostScript file named
+ <font_name>-<code>.eps, where <code> is the character code in decimal.
+filter-passes <unsigned>: do the filtering this many times on each
+ character; default is 0.
+filter-size <unsigned>: half the size of the filter cell, i.e., a side
+ is this number * 2 + 1; default is 1.
+filter-threshold <real>: if the average of the pixels in the filter cell
+ is greater than this, change the pixel; default is .5.
+fontdimens <fontdimen>:<real>,<fontdimen>:<real>,...: assign each <real>
+ to the corresponding <fontdimen> when outputting a TFM file. A
+ <fontdimen> can be either one of the standard names (in either upper
+ or lowercase), or a number between 1 and 30. Each <real> is taken to
+ be in points (except in the case of the <fontdimen> `slant' (parameter
+ 1), which is a dimensionless number).
+gf: write a GF file to `<font_name>.<dpi>gf'. If this would overwrite the
+ input file, write to `x<font_name>.<dpi>gf' instead.
+help: print this message.
+omit <char1>,<char2>,...: omit the characters with the given codes or names
+ (before remapping) from the output.
+output-file <filename>: use <filename> as the output filename if it has
+ a suffix, and as the base of the output files if it doesn't. It
+ cannot have a suffix if using the `epsf' option, or both the `gf' and the
+ `tfm' option. Default is the base part of the input font name.
+random <real>: move each pixel a (uniformly) random distance between
+ -<real> and <real> in both x and y; default is 0.
+random-threshold <real>: if randomizing, do not move pixels with
+ probability <real>; default is 0.2.
+range <char1>-<char2>: only process characters between <char1> and
+ <char2> in the input font, inclusive.
+remap <char1>:<char2>,<char1>:<char2>,...: for each pair, make the input
+ character with code <char1> have code <char2> in the output.
+text: output the font to stdout as plain text, using `*'s and ` 's.
+tfm: write a TFM file to `<font_name>.tfm'. If this would overwrite the
+ input file, write to `x<font_name>.tfm' instead.
+tfm-header: <header-item>:<value>,<header-item>:<value>,...: assign each
+ <value> to the corresponding <header-item> when outputting a TFM file.
+ A <header-item> is one of `checksum', `designsize' or `codingscheme',
+ with casefolding. `checksum' requires an unsigned integer,
+ `designsize' a real, with 1.0 <= designsize < 2048, and `codingscheme'
+ a string of length less than 40 containing no parens or commas.
+verbose: print brief progress reports on stdout.
+version: print the version number of this program.
+"
+
+/* We return the name of the font to process. */
+
+static string
+read_command_line (int argc, string argv[])
+{
+ int g; /* `getopt' return code. */
+ int option_index;
+ boolean explicit_dpi = false;
+ boolean printed_version = false;
+ struct option long_options[]
+ = { { "baseline-adjust", 1, 0, 0 },
+ { "column-split", 1, 0, 0 },
+ { "concat", 1, 0, 0 },
+ { "designsize", 1, 0, 0 },
+ { "dpi", 1, (int *) &explicit_dpi, 1 },
+ { "encoding", 1, 0, 0 },
+ { "epsf", 0, (int *) &wants_epsf, 1 },
+ { "filter-passes", 1, 0, 0 },
+ { "filter-size", 1, 0, 0 },
+ { "filter-threshold", 1, 0, 0 },
+ { "fontdimens", 1, 0, 0 },
+ { "gf", 0, (int *) &wants_gf, 1 },
+ { "help", 0, 0, 0 },
+ { "omit", 1, 0, 0 },
+ { "output-file", 1, 0, 0 },
+ { "random", 1, 0, 0 },
+ { "random-threshold", 1, 0, 0 },
+ { "range", 1, 0, 0 },
+ { "remap", 1, 0, 0 },
+ { "text", 0, (int *) &wants_text, 1 },
+ { "tfm", 0, (int *) &wants_tfm, 1 },
+ { "tfm-header", 1, 0, 0 },
+ { "verbose", 0, (int *) &verbose, 1 },
+ { "version", 0, (int *) &printed_version, 1 },
+ { 0, 0, 0, 0 } };
+
+ while (true)
+ {
+ g = getopt_long_only (argc, argv, "", long_options, &option_index);
+
+ if (g == EOF)
+ break;
+
+ if (g == '?')
+ exit (1); /* Unknown option. */
+
+ assert (g == 0); /* We have no short option names. */
+
+ if (ARGUMENT_IS ("baseline-adjust"))
+ scan_baseline_adjust (optarg);
+
+ else if (ARGUMENT_IS ("column-split"))
+ scan_column_split (optarg);
+
+ else if (ARGUMENT_IS ("concat"))
+ append_concat_list (&fontname_list, optarg);
+
+ else if (ARGUMENT_IS ("designsize"))
+ {
+ design_size = atof (optarg);
+ TFM_CHECK_DESIGN_SIZE (design_size);
+ }
+
+ else if (ARGUMENT_IS ("dpi"))
+ dpi = optarg;
+
+ else if (ARGUMENT_IS ("encoding"))
+ {
+ if (encoding_info == NULL)
+ encoding_info = XTALLOC1 (encoding_info_type);
+ *encoding_info = read_encoding_file (optarg);
+ }
+
+ else if (ARGUMENT_IS ("filter-passes"))
+ filter_passes = atou (optarg);
+
+ else if (ARGUMENT_IS ("filter-size"))
+ filter_size = atou (optarg);
+
+ else if (ARGUMENT_IS ("filter-threshold"))
+ {
+ filter_threshold = atof (optarg);
+ if (filter_threshold <= 0.0)
+ FATAL1 ("The filter threshold should be positive, not %f",
+ filter_threshold);
+ }
+
+ else if (ARGUMENT_IS ("fontdimens"))
+ fontdimens = optarg;
+
+ else if (ARGUMENT_IS ("help"))
+ {
+ fprintf (stderr, "Usage: %s [options] <font_name>.\n", argv[0]);
+ fprintf (stderr, USAGE);
+ exit (0);
+ }
+
+ else if (ARGUMENT_IS ("omit"))
+ scan_omit_list (optarg);
+
+ else if (ARGUMENT_IS ("output-file"))
+ output_name = optarg;
+
+ else if (ARGUMENT_IS ("range"))
+ GET_RANGE (optarg, starting_char, ending_char);
+
+ else if (ARGUMENT_IS ("random"))
+ random_max = atof (optarg);
+
+ else if (ARGUMENT_IS ("random-threshold"))
+ random_threshold = atof (optarg);
+
+ else if (ARGUMENT_IS ("remap"))
+ scan_remap_list (optarg);
+
+ else if (ARGUMENT_IS ("text"))
+ report_file = stderr;
+
+ else if (ARGUMENT_IS ("tfm-header"))
+ tfm_header = optarg;
+
+ else if (ARGUMENT_IS ("version"))
+ printf ("%s.\n", version_string);
+
+ /* Else it was just a flag; getopt has already done the assignment. */
+ }
+
+ FINISH_COMMAND_LINE ();
+}
+
+/* The string S specifies baseline adjustments for individual
+ characters: `<charcode>:<adjustment>,...'. We set the element
+ <charcode> of the global array `baseline_adjust' to the <adjustment>. */
+
+static void
+scan_baseline_adjust (string s)
+{
+ string spec;
+
+ for (spec = strtok (s, ARG_SEP); spec != NULL; spec = strtok (NULL, ARG_SEP))
+ {
+ string code;
+ string adjust = strchr (spec, ':');
+
+ if (adjust == NULL)
+ FATAL1 ("Baseline adjustments look like `<code>:<integer>', not `%s'",
+ spec);
+
+ code = substring (spec, 0, adjust - spec - 1);
+
+ baseline_adjust[xparse_charspec (code, encoding_info)]
+ = atoi (adjust + 1);
+ }
+}
+
+
+/* The string S says how to split a single character into multiple
+ characters: `<charcode>@<column1>,...<columnN>'. We set the element
+ <charcode> of the global array `column_split' to the list of the
+ integers. */
+
+static void
+scan_column_split (string s)
+{
+ string code;
+ string column_list = strchr (s, '@');
+
+ if (column_list == NULL)
+ FATAL1 ("Column splits look like `<code>@<column>,<column>,...', not `%s'",
+ s);
+
+ code = substring (s, 0, column_list - s - 1);
+
+ column_split[xparse_charspec (code, encoding_info)]
+ = scan_unsigned_list (column_list + 1);
+}
+
+
+/* The string S is a list of font names, separated by commas. We append
+ each onto CONCAT_LIST. */
+
+static void
+append_concat_list (list_type *concat_list, string s)
+{
+ string name;
+
+ /* The main routine must initialize CONCAT_LIST before we are called. */
+ assert (concat_list != NULL && LIST_SIZE (*concat_list) > 0);
+
+ for (name = strtok (s, ARG_SEP); name != NULL; name = strtok (NULL, ARG_SEP))
+ {
+ string *new = LIST_TAPPEND (concat_list, string);
+ *new = name;
+ }
+}
+
+
+/* The string L is a list of character codes separated by commas; we
+ omit those characters in the output. Here, we parse the list and set
+ elements of the global array `omit' according to what we find. */
+
+static void
+scan_omit_list (string l)
+{
+ string map;
+
+ for (map = strtok (l, ARG_SEP); map != NULL; map = strtok (NULL, ARG_SEP))
+ {
+ charcode_type code = xparse_charspec (map, encoding_info);
+ omit[code] = true;
+ }
+}
+
+
+/* The string L is a list of remappings to apply, in the form
+ <code1>:<code2>,<code1>:<code2>,... where <code1> is a character
+ code in the original font, and <code2> is the character code to write
+ it as. No checking for remappings to or from the same character is
+ done here.
+
+ We set elements of the global array `translate' according to what we
+ find. */
+
+static void
+scan_remap_list (string l)
+{
+ string map; /* A single remapping. */
+
+ for (map = strtok (l, ARG_SEP); map != NULL; map = strtok (NULL, ARG_SEP))
+ {
+ one_byte original, target;
+ string original_str, target_str;
+ unsigned length = strlen (map);
+
+ /* Ignore empty mappings, as in `a:b,,c:d'. */
+ if (length == 0)
+ continue;
+
+ else if (length < 3)
+ {
+ WARNING1 ("Mapping `%s' too short to be valid", map);
+ continue;
+ }
+
+ else if (*map == ':')
+ { /* Must have form `::<code>'. */
+ original_str = ":";
+ if (*(map + 1) != ':')
+ {
+ WARNING1 ("Mapping `%s' doesn't have form `<code>:<code>'", map);
+ continue;
+ }
+ target_str = map + 2;
+ }
+
+ else if (*(map + length - 1) == ':')
+ { /* Must have form `<code>::'. */
+ target_str = ":";
+ if (*(map + length - 2) != ':')
+ {
+ WARNING1 ("Mapping `%s' doesn't have form `<code>:<code>'", map);
+ continue;
+ }
+ original_str = substring (map, 0, length - 3);
+ }
+
+ else
+ { /* Must have form `<code>:<code>'. */
+ target_str = strchr (map, ':');
+ if (target_str == NULL)
+ {
+ WARNING1 ("Mapping `%s' doesn't have form `<code>:<code>'", map);
+ continue;
+ }
+ target_str++;
+ original_str = substring (map, 0, target_str - 2 - map);
+ }
+
+ original = xparse_charspec (original_str, encoding_info);
+ target = xparse_charspec (target_str, encoding_info);
+ translate[original] = target;
+ }
+}
+
+
+
+/* xx use the macro instead */
+/*string
+finish_command_line()
+{
+ do
+ {
+ if (printed_version && optind == argc) exit (0);
+
+ if (optind + 1 == argc && *argv[optind] != 0)
+ {
+ FIND_CMDLINE_DPI ();
+ return MAYBE_REMOVE_SUFFIX (argv[optind]);
+ }
+ else
+ {
+ fprintf (stderr, "Usage: %s [options] <font_name>.\n", argv[0]);
+ fprintf (stderr, "(%s.)\n", optind == argc ? "Missing <font_name>"
+ : "Too many <font_name>s");
+ fputs ("For more information, use ``-help''.\n", stderr);
+ exit (1);
+ }
+ return NULL;
+ }
+ while (0)
+}
+*/
diff --git a/fontconvert/main.h b/fontconvert/main.h
new file mode 100644
index 0000000..8e4aeaf
--- /dev/null
+++ b/fontconvert/main.h
@@ -0,0 +1,34 @@
+/* main.h: global variable declarations.
+
+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. */
+
+#ifndef MAIN_H
+#define MAIN_H
+
+#include <kpathsea/types.h>
+#include "font.h"
+
+/* See main.c for explanations of these globals. */
+extern int baseline_adjust[MAX_CHARCODE + 1];
+extern int *column_split[MAX_CHARCODE + 1];
+extern string fontdimens;
+extern charcode_type translate[MAX_CHARCODE + 1];
+extern boolean verbose;
+
+#endif /* not MAIN_H */
+
+
diff --git a/fontconvert/output-epsf.c b/fontconvert/output-epsf.c
new file mode 100644
index 0000000..d7de3ba
--- /dev/null
+++ b/fontconvert/output-epsf.c
@@ -0,0 +1,135 @@
+/* output-epsf.c: output EPS files.
+
+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 "output-epsf.h"
+
+
+/* The base part of the fontname to output to. */
+static string output_name;
+
+
+/* It's a fatal error if NAME has a suffix, since that could mean
+ overwriting the same file several times with different information. */
+
+void
+epsf_start_output (const_string name)
+{
+ if (find_suffix (name) != NULL)
+ FATAL ("You can't specify a suffix and EPS output");
+}
+
+
+/* Write a single character to the file `output_name-CODE.eps',
+ where CODE is the character code. */
+
+/* Output the lower eight bits of VALUE to FILE as two hex digits. For
+ reasons I don't understand, when I write these same expressions in
+ the arguments to the fprintf, values less than 128 are copied into
+ the high nybble; that is, 1 is output as `11'. */
+#define OUTPUT_HEX(file, value) \
+ do \
+ { one_byte v1 = (value) & 0xf0; \
+ one_byte v2 = (value) & 0xf; \
+ fprintf (file, "%x%x", v1 >> 4, v2); \
+ } \
+ while (0)
+
+void
+epsf_output_char (char_info_type c)
+{
+ unsigned row;
+ bitmap_type b = CHAR_BITMAP (c);
+ unsigned height = BITMAP_HEIGHT (b);
+ unsigned width = BITMAP_WIDTH (b);
+ charcode_type code = CHARCODE (c);
+ string title = concat3 (output_name, "-", itoa (code));
+ string eps_name = concat (title, ".eps");
+ FILE *eps = xfopen (eps_name, "w");
+
+ /* Write the header. */
+ fputs ("%!PS-Adobe-3.0 EPSF-3.0\n", eps);
+ fprintf (eps, "%%%%BoundingBox: 0 0 %u %u\n",
+ BITMAP_WIDTH (b), BITMAP_HEIGHT (b));
+ fprintf (eps, "%%%%Title: (%s)\n", title);
+ fputs ("%%Creator: fontconvert -epsf\n", eps);
+ fprintf (eps, "%%%%CreationDate: %s\n", now ());
+ fputs ("%%EndComments\n", eps);
+
+ /* Write the bitmap as an image. */
+
+ /* First arrange to scale the image to its original size. */
+ fprintf (eps, "%u %u scale\n", width, height);
+
+ /* Push the imagemask parameters. */
+ fprintf (eps, "%u %u true [%u 0 0 -%u 0 %u]\n",
+ width, height, width, height, height);
+
+ /* Output the bits. */
+ fputs ("{<", eps);
+ for (row = 0; row < height; row++)
+ {
+ unsigned col;
+ one_byte byte = 0;
+ unsigned bit = 7;
+
+ for (col = 0; col < width; col++)
+ {
+ byte |= BITMAP_PIXEL (b, row, col) << bit;
+
+ /* Output eight bits at a time, since imagemask expects that. */
+ if (bit == 0)
+ {
+ OUTPUT_HEX (eps, byte);
+ byte = 0;
+ bit = 8;
+ }
+
+ /* Decrement `bit' after, so that the test `bit == 0' above is
+ true at the right time. */
+ bit--;
+ }
+
+ /* If the width isn't a multiple of eight, have to output the
+ remainder. */
+ if (bit < 7)
+ OUTPUT_HEX (eps, byte);
+
+ /* In any case, output a newline, just to make the output easier
+ to read, in case somebody wants to read it. */
+ fputs ("\n", eps);
+ }
+ fputs (">}\nimagemask\n", eps);
+
+ /* Write the trailer. */
+ fputs ("showpage\n", eps);
+ fputs ("%%EOF\n", eps);
+
+ xfclose (eps, eps_name);
+ free (eps_name);
+ free (title);
+}
+
+
+/* We don't have anything to do at the end. */
+
+void
+epsf_finish_output (void)
+{
+}
diff --git a/fontconvert/output-epsf.h b/fontconvert/output-epsf.h
new file mode 100644
index 0000000..2d243ea
--- /dev/null
+++ b/fontconvert/output-epsf.h
@@ -0,0 +1,30 @@
+/* output-epsf.h: declarations for writing EPS files.
+
+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. */
+
+#ifndef OUTPUT_EPSF_H
+#define OUTPUT_EPSF_H
+
+#include <kpathsea/types.h>
+#include "font.h"
+
+
+extern void epsf_start_output (const_string base_name);
+extern void epsf_output_char (char_info_type);
+extern void epsf_finish_output (void);
+
+#endif /* not OUTPUT_EPSF_H */
diff --git a/fontconvert/output-gf.c b/fontconvert/output-gf.c
new file mode 100644
index 0000000..9a64171
--- /dev/null
+++ b/fontconvert/output-gf.c
@@ -0,0 +1,86 @@
+/* output-gf.c: write a GF file.
+
+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 "gf.h"
+#include "report.h"
+
+#include "output-gf.h"
+
+/* The basename of the input file. */
+static string input_basename;
+
+/* Open the output file and write the preamble. We don't bother to
+ change the comment to identify ourselves, since the changes we will
+ make aren't likely to be drastic. We have to ensure that we do not
+ overwrite the input file; if INPUT_NAME and our constructed output
+ name do refer to the same file, we simply prepend an `x' to the
+ output name. Not very elegant, but it does solve the problem. */
+
+void
+gf_start_output (string input_name, const_string output_name, string dpi,
+ string comment)
+{
+ string gf_name = extend_filename (output_name, concat (dpi, "gf"));
+
+ if (same_file_p (input_name, gf_name))
+ {
+ string old_gf_name = gf_name;
+
+ gf_name = make_prefix ("x", gf_name);
+ WARNING2 ("fontconvert: The output file (%s) is also the \
+the input file, so I am writing to `%s'", old_gf_name, gf_name);
+ }
+
+ if (!gf_open_output_file (gf_name))
+ FATAL_PERROR (gf_name);
+
+ gf_put_preamble (comment);
+
+ /* We might need this in `gf_finish_output', to open the TFM file. */
+ input_basename = basename (input_name);
+}
+
+/* Write a single character. */
+
+void
+gf_output_char (char_info_type c, real design_size_ratio)
+{
+ gf_char_type gf_char;
+
+ GF_CHARCODE (gf_char) = CHARCODE (c);
+ GF_BITMAP (gf_char) = CHAR_BITMAP (c);
+ GF_CHAR_BB (gf_char) = CHAR_BB (c);
+ GF_H_ESCAPEMENT (gf_char) = CHAR_SET_WIDTH (c);
+ GF_TFM_WIDTH (gf_char) = design_size_ratio * CHAR_TFM_WIDTH (c);
+
+ gf_put_char (gf_char);
+}
+
+/* Write the postamble and close the file. */
+
+
+void
+gf_finish_output (real design_size, real dpi)
+{
+ gf_put_postamble (real_to_fix (design_size), dpi, dpi);
+ gf_close_output_file ();
+}
+
diff --git a/fontconvert/output-gf.h b/fontconvert/output-gf.h
new file mode 100644
index 0000000..ac0a953
--- /dev/null
+++ b/fontconvert/output-gf.h
@@ -0,0 +1,31 @@
+/* output-gf.h: declarations for writing a GF file.
+
+Copyright (C) 1992, 93 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. */
+
+#ifndef OUTPUT_GF_H
+#define OUTPUT_GF_H
+
+#include <kpathsea/types.h>
+#include "font.h"
+
+/* Initialize GF output, output a character, and finish it up. */
+extern void gf_start_output
+ (string input_name, const_string base_name, string dpi, string comment);
+extern void gf_output_char (char_info_type, real design_size_ratio);
+extern void gf_finish_output (real design_size, real dpi);
+
+#endif /* not OUTPUT_GF_H */
diff --git a/fontconvert/output-tfm.c b/fontconvert/output-tfm.c
new file mode 100644
index 0000000..62f7a0b
--- /dev/null
+++ b/fontconvert/output-tfm.c
@@ -0,0 +1,279 @@
+/* output-tfm.c: write a TFM file.
+
+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 <kpathsea/tex-file.h>
+#include <kpathsea/pathsearch.h>
+#include <kpathsea/paths.h>
+
+#include "filename.h"
+#include "random.h"
+#include "report.h"
+#include "tfm.h"
+
+#include "filter.h"
+#include "main.h"
+#include "output-tfm.h"
+
+
+/* User assignments to the TFM character header values. */
+string tfm_header = NULL;
+
+/* User assignments to the TFM fontdimen values. */
+string fontdimens = NULL;
+
+
+/* `false' if we're doing any font other than the main one (which is
+ done first). */
+static boolean main_input_font_p = true;
+
+/* `true' if we have an input TFM file from which to get defaults. */
+static boolean have_file_info = false;
+
+/* This accumulates the information about each character. */
+static tfm_char_type *tfm_chars;
+
+/* This holds the information about each character old TFM character. */
+static tfm_char_type *old_tfm_chars;
+
+/* The name of the TFM file we finally write. */
+static string output_tfm_name;
+
+
+static void tfm_do_chars_defaults (void);
+
+/* At the beginning, we can set up the output file and write the fontwide
+ information. This includes the fontdimen parameters (in the global
+ `fontdimens'), and the header bytes (in `tfm_header'), if the user
+ specified them. */
+
+void
+tfm_start_output (string input_name, const_string output_name,
+ real user_design_size, real default_design_size)
+{
+ tfm_global_info_type tfm_info;
+ string input_tfm_name = kpse_find_tfm (input_name);
+
+ /* 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_name, "pl");
+ 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))
+ {
+ string old_pl_name = pl_name;
+ string old_output_tfm_name = output_tfm_name;
+
+ pl_name = make_prefix ("x", pl_name);
+ output_tfm_name = make_prefix ("x", output_tfm_name);
+
+ WARNING2 ("fontconvert: The output file (%s) is also the \
+the input file, so I am writing to `%s'", old_pl_name, pl_name);
+ WARNING2 ("fontconvert: The output file (%s) is also the \
+the input file, so I am writing to `%s'", old_output_tfm_name,\
+output_tfm_name);
+ }
+
+ if (!tfm_open_pl_output_file (pl_name))
+ FATAL_PERROR (pl_name);
+
+ /* Initialize `tfm_info' with the data from an existing file, if we
+ have it.
+
+ For the design size in the output TFM file, use the following, in
+ order of preference:
+ 1) `designsize' parameter given by the user in the -tfm-header option;
+ 2) `-design-size' option (which is `user_design_size');
+ 3) the designsize from an existing TFM file;
+ 4) the `default_design_size' passed in (which is the designsize in
+ the input bitmap font). */
+
+ if (input_tfm_name != NULL && tfm_open_input_file (input_tfm_name))
+ {
+ tfm_info = tfm_get_global_info ();
+ have_file_info = true;
+
+ REPORT1 ("Reading %s.\n", input_tfm_name);
+
+ /* Never carry along the checksum. */
+ TFM_CHECKSUM (tfm_info) = 0;
+
+ /* A user-supplied design size (#2) overrides the design size from
+ the file (#3). (The -tfm-header (#1) override is below.) */
+ if (user_design_size != 0.0)
+ TFM_DESIGN_SIZE (tfm_info) = user_design_size;
+ }
+ else
+ { /* No existing TFM file. */
+ tfm_info = tfm_init_global_info ();
+
+ /* Use the bitmap font's design size (#4). */
+ TFM_DESIGN_SIZE (tfm_info) = default_design_size;
+ }
+
+ /* Be sure the design size in the header bytes and the fontdimen
+ parameter agree. */
+ tfm_set_fontsize (&tfm_info);
+
+ /* Update `tfm_info' with any user-supplied strings. */
+ if (tfm_header != NULL)
+ tfm_set_header (tfm_header, &tfm_info);
+
+ if (fontdimens != NULL)
+ tfm_set_fontdimens (fontdimens, &tfm_info);
+
+ /* Output this to start us off. */
+ tfm_put_global_info (tfm_info);
+
+ /* Initialize the array where we will store the character information. */
+ tfm_chars = tfm_new_chars ();
+}
+
+/* We could do something more complicated here, if we wanted to get the
+ TFM information for each input font: close the first font (after
+ first getting everything we need), open the next one, then close it
+ next time we're called, etc. (Or make the TFM library able to handle
+ more than one open font.) Then we could combine all the lig/kern
+ information, besides using the character dimensions. But none of
+ this seems worth it (i.e., we haven't needed to do it yet).
+
+ So instead we just remember whether we're doing the first font --
+ which is the main one -- so we can skip looking in the TFM file for
+ font #1 when we're doing fonts #2, #3, ... */
+
+void
+tfm_start_font (string font_name)
+{
+ if (main_input_font_p)
+ main_input_font_p = false;
+}
+
+/* Store the relevant information about the character C into `tfm_chars'. */
+
+void
+tfm_output_char (char_info_type c, real dpi_real)
+{
+ tfm_char_type *new_tfm_char = &tfm_chars[CHARCODE (c)];
+
+ TFM_CHAR_EXISTS (*new_tfm_char) = true;
+ TFM_CHARCODE (*new_tfm_char) = CHARCODE (c);
+
+ /* If we're doing radical things to the characters, don't use the
+ default information from an existing file even if we have one. */
+ if (baseline_adjust[CHARCODE (c)] != 0
+ || column_split[CHARCODE (c)] != NULL
+ || filter_passes > 0
+ || random_max > 0.0
+ || !have_file_info
+ || !main_input_font_p)
+ {
+ TFM_WIDTH (*new_tfm_char)
+ = PIXELS_TO_POINTS (CHAR_SET_WIDTH (c), dpi_real);
+
+ TFM_HEIGHT (*new_tfm_char)
+ = PIXELS_TO_POINTS (CHAR_HEIGHT (c), dpi_real);
+
+ TFM_DEPTH (*new_tfm_char) = PIXELS_TO_POINTS (CHAR_DEPTH (c), dpi_real);
+ TFM_ITALIC_CORRECTION (*new_tfm_char) = 0.0;
+ }
+ else
+ {
+ tfm_char_type *old_tfm_char = tfm_get_char (CHARCODE (c));
+
+ TFM_WIDTH (*new_tfm_char) = TFM_WIDTH (*old_tfm_char);
+ TFM_HEIGHT (*new_tfm_char) = TFM_HEIGHT (*old_tfm_char);
+ TFM_DEPTH (*new_tfm_char) = TFM_DEPTH (*old_tfm_char);
+ TFM_ITALIC_CORRECTION (*new_tfm_char)
+ = TFM_ITALIC_CORRECTION (*old_tfm_char);
+ }
+
+ /* We do the ligatures and kerns when we have gone through all the
+ characters. */
+}
+
+
+/* If we have an existing TFM file, use it to get the lig/kern info. */
+
+static void
+tfm_do_chars_defaults ()
+{
+ unsigned code;
+
+ if (!have_file_info)
+ return;
+
+ old_tfm_chars = tfm_get_chars ();
+
+ for (code = 0; code < TFM_SIZE; code++)
+ {
+ tfm_char_type *new_tfm_char = &tfm_chars[code];
+
+ if (TFM_CHAR_EXISTS (*new_tfm_char))
+ {
+ unsigned this_one;
+ tfm_char_type *old_tfm_char = &old_tfm_chars[code];
+ list_type old_kern_table = TFM_KERN (*old_tfm_char);
+ list_type old_lig_table = TFM_LIGATURE (*old_tfm_char);
+
+ for (this_one = 0; this_one < LIST_SIZE (old_kern_table); this_one++)
+ {
+ tfm_kern_type *old_kern = LIST_ELT (old_kern_table, this_one);
+ tfm_char_type *old_kern_char
+ = &tfm_chars[translate[old_kern->character]];
+
+ if (TFM_CHAR_EXISTS (*old_kern_char))
+ tfm_set_kern (&TFM_KERN (*new_tfm_char),
+ CHARCODE (*old_kern_char), old_kern->kern);
+ }
+
+ for (this_one = 0; this_one < LIST_SIZE (old_lig_table); this_one++)
+ {
+ tfm_ligature_type *old_lig = LIST_ELT (old_lig_table, this_one);
+ tfm_char_type *old_lig_char
+ = &tfm_chars[translate[old_lig->character]];
+ tfm_char_type *old_lig_ligature
+ = &tfm_chars[translate[old_lig->ligature]];
+
+ if (TFM_CHAR_EXISTS (*old_lig_char)
+ && TFM_CHAR_EXISTS (*old_lig_ligature))
+ tfm_set_ligature (&TFM_LIGATURE (*new_tfm_char),
+ CHARCODE (*old_lig_char),
+ CHARCODE (*old_lig_ligature));
+ }
+ } /* new TFM char exists */
+ }
+}
+
+/* Output `tfm_chars' and close up. */
+
+void
+tfm_finish_output ()
+{
+ tfm_do_chars_defaults ();
+
+ tfm_put_chars (tfm_chars);
+ tfm_convert_pl (output_tfm_name, verbose);
+ tfm_close_pl_output_file ();
+
+ if (have_file_info)
+ tfm_close_input_file ();
+}
diff --git a/fontconvert/output-tfm.h b/fontconvert/output-tfm.h
new file mode 100644
index 0000000..b819ceb
--- /dev/null
+++ b/fontconvert/output-tfm.h
@@ -0,0 +1,45 @@
+/* output-tfm.h: declarations for writing a TFM file.
+
+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. */
+
+#ifndef OUTPUT_TFM_H
+#define OUTPUT_TFM_H
+
+#include <kpathsea/types.h>
+#include "font.h"
+
+
+/* See tfm_output.c. */
+extern string tfm_header;
+extern string fontdimens;
+
+
+/* Called once at the beginning to initialize things. */
+extern void tfm_start_output (string input_name, const_string output_name,
+ real user_design_size, real default_design_size);
+
+/* Called per each input font: the main one first and then each one
+ specified with -concat. */
+extern void tfm_start_font (string font_name);
+
+/* Called for every character in every font. */
+extern void tfm_output_char (char_info_type, real dpi);
+
+/* Called at the very end. */
+extern void tfm_finish_output (void);
+
+#endif /* not OUTPUT_TFM_H */
diff --git a/fontconvert/random.c b/fontconvert/random.c
new file mode 100644
index 0000000..f683377
--- /dev/null
+++ b/fontconvert/random.c
@@ -0,0 +1,171 @@
+/* random.c: distort a bitmap.
+
+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 "rand.h"
+
+#include "random.h"
+
+/* Distort the bitmap (see below). (-randomize) */
+real random_max = 0.0;
+real random_threshold = 0.2;
+
+
+static bitmap_type enlarge_bitmap (bitmap_type, int, int);
+static real random_number (void);
+
+
+
+/* Randomize the bitmap B by moving each black pixel a randomly chosen
+ distance between -random_max and random_max (both horizontally and
+ vertically). Return the enlargement of B on all four side in ADJUST.
+ */
+
+void
+randomize_bitmap (bitmap_type *b, bounding_box_type *adjust)
+{
+ unsigned this_row, this_col;
+
+ MIN_ROW (*adjust) = MAX_ROW (*adjust) = MIN_COL (*adjust) = MAX_COL (*adjust)
+ = 0;
+
+ for (this_row = 0; this_row < BITMAP_HEIGHT (*b); this_row++)
+ for (this_col = 0; this_col < BITMAP_WIDTH (*b); this_col++)
+ {
+ if (BITMAP_PIXEL (*b, this_row, this_col) != WHITE)
+ {
+ int row_enlarge, col_enlarge;
+ /* Generate two random numbers between -random_max and
+ random_max to give rise to the new x and y. */
+ real random1 = random_number ();
+ int row_delta = random1 + .5 * SIGN (random1);
+ int new_row = this_row + row_delta;
+
+ real random2 = random_number ();
+ int col_delta = random2 + .5 * SIGN (random2);
+ int new_col = this_col + col_delta;
+
+ /* Clear the old location before we (possibly) mess with the
+ bitmap dimensions. */
+ BITMAP_PIXEL (*b, this_row, this_col) = WHITE;
+
+ /* Check if the new location is outside the current bitmap. */
+ if (new_row < 0)
+ {
+ row_enlarge = new_row;
+ /* Negative rows are off the top of the bitmap -- it's
+ in C coordinates, not Cartesian. */
+ MAX_ROW (*adjust) -= row_enlarge;
+ }
+ else if (new_row >= BITMAP_HEIGHT (*b))
+ {
+ row_enlarge = new_row - BITMAP_HEIGHT (*b) + 1;
+ MIN_ROW (*adjust) += row_enlarge;
+ }
+ else
+ row_enlarge = 0;
+
+ if (new_col < 0)
+ {
+ col_enlarge = new_col;
+ MIN_COL (*adjust) -= col_enlarge;
+ }
+ else if (new_col >= BITMAP_WIDTH (*b))
+ {
+ col_enlarge = new_col - BITMAP_WIDTH (*b) + 1;
+ MAX_COL (*adjust) += col_enlarge;
+ }
+ else
+ col_enlarge = 0;
+
+ if (row_delta != 0 || col_delta != 0)
+ { /* Enlarge the bitmap to make the new location valid. */
+ bitmap_type new_b
+ = enlarge_bitmap (*b, row_enlarge, col_enlarge);
+ free_bitmap (b);
+ *b = new_b;
+
+ /* We've made the new row/column at the edge. */
+ if (new_row < 0) new_row = 0;
+ if (new_col < 0) new_col = 0;
+ }
+
+ BITMAP_PIXEL (*b, new_row, new_col) = BLACK;
+ }
+ }
+}
+
+
+/* Return the enlargement of the bitmap B by ROW_DELTA and COL_DELTA.
+ Negative deltas enlarge to the bottom/left, positive to the
+ top/right. */
+
+static bitmap_type
+enlarge_bitmap (bitmap_type b, int row_delta, int col_delta)
+{
+ bitmap_type new;
+ dimensions_type new_size;
+ unsigned row;
+ int row_addend = row_delta < 0 ? abs (row_delta) : 0;
+ int col_addend = col_delta < 0 ? abs (col_delta) : 0;
+
+ DIMENSIONS_HEIGHT (new_size) = BITMAP_HEIGHT (b) + abs (row_delta);
+ DIMENSIONS_WIDTH (new_size) = BITMAP_WIDTH (b) + abs (col_delta);
+
+ new = new_bitmap (new_size);
+
+ /* `new_bitmap' initializes all the pixels to white, so we don't have
+ to do anything to the new rows and columns. */
+ for (row = 0; row < BITMAP_HEIGHT (b); row++)
+ {
+ one_byte *source = BITMAP_ROW (b, row);
+ one_byte *target = BITMAP_ROW (new, row + row_addend) + col_addend;
+
+ memcpy (target, source, BITMAP_WIDTH (b));
+ }
+
+ return new;
+}
+
+
+
+/* Return a random number between -random_max and random_max. */
+
+static real
+random_number ()
+{
+ static boolean initialized = false;
+ real r;
+
+ if (!initialized)
+ {
+ seed_rand (getpid ());
+ initialized = true;
+ }
+
+ /* If the random number is less than `random_threshold', return zero.
+ Otherwise, return a random number in the interval
+ [-random_max,random_max]. */
+ r = (real) k_rand () / RAND_MAX;
+ r = r > random_threshold
+ ? (real) k_rand () / RAND_MAX * random_max - random_max
+ : 0;
+
+ return r;
+}
diff --git a/fontconvert/random.h b/fontconvert/random.h
new file mode 100644
index 0000000..3fa60e9
--- /dev/null
+++ b/fontconvert/random.h
@@ -0,0 +1,37 @@
+/* random.h: declarations for randomizing a bitmap.
+
+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. */
+
+#ifndef RANDOM_H
+#define RANDOM_H
+
+#include <kpathsea/types.h>
+#include "bitmap.h"
+#include "bounding-box.h"
+
+/* See random.c. */
+extern real random_max;
+extern real random_threshold;
+
+/* Move each pixel in B by a random amount between -random_max and
+ random_max (enlarging the bitmap as necessary). Return the number of
+ rows/columns added at each side of bitmap (i.e., all numbers are
+ positive) in ADJUST. (This is not actually a bounding box, but that
+ type is a convenient way to return the four numbers.) */
+extern void randomize_bitmap (bitmap_type *b, bounding_box_type *adjust);
+
+#endif /* not RANDOM_H */
diff --git a/fontconvert/version.c b/fontconvert/version.c
new file mode 100644
index 0000000..66aab18
--- /dev/null
+++ b/fontconvert/version.c
@@ -0,0 +1 @@
+char *version_string = "fontconvert version REPLACE-WITH-VERSION";
diff --git a/gf/ChangeLog b/gf/ChangeLog
new file mode 100644
index 0000000..b7178de
--- /dev/null
+++ b/gf/ChangeLog
@@ -0,0 +1,308 @@
+Sun Feb 20 17:08:21 1994 Kathy Hargreaves (karl@cs.umb.edu)
+
+ * gf_output.c: changed doc.
+
+Tue Oct 27 12:56:09 1992 Karl Berry (karl@cs.umb.edu)
+
+ * Version 0.6.
+
+Mon Sep 21 13:20:29 1992 Karl Berry (karl@cs.umb.edu)
+
+ * gf_output.c (start_put_char): don't claim we are part of the
+ nonexistent put_gf_char in the warning.
+
+Thu Sep 3 09:30:43 1992 Karl Berry (karl@hayley)
+
+ * Version 0.5.
+
+Sat Jun 6 10:03:52 1992 Karl Berry (karl@hayley)
+
+ * gf_input.c (gf_get_postamble): if the input file is empty, give
+ a decent error message.
+
+Mon May 4 09:28:57 1992 Karl Berry (karl@hayley)
+
+ * gf_output.c (start_put_char): use `put_gf_char' in the warning.
+
+Sat Apr 4 13:53:55 1992 Karl Berry (karl@hayley)
+
+ * gf_output.c (gf_put_char): remove unneeded local `charcode'.
+
+Sat Mar 28 07:48:16 1992 Karl Berry (karl at hayley)
+
+ * Version 0.4.
+
+ * Change copyright years to 1992 only.
+
+Sat Mar 7 13:18:42 1992 Karl Berry (karl at fosse)
+
+ * gf_input.c (gf_get_three): complete prototype.
+ * gf_output.c (init_locators, put_locators): likewise.
+
+Sat Mar 7 09:12:14 1992 Karl Berry (karl at hayley)
+
+ * GNUmakefile (files, headers, sources): replace with `c_and_h', etc.
+
+ * gf_input.c (get_character_bitmap): use puts instead of printf
+ where possible.
+
+Thu Jan 9 08:30:06 1992 Karl Berry (karl at hayley)
+
+ * *.c: do not include global.h.
+
+ * *.h: remove #pragma once.
+
+Wed Jan 8 15:28:34 1992 Karl Berry (karl at hayley)
+
+ * update copyright messages.
+
+ * change `allocate to `xmalloc', `reallocate' to `xrealloc', and
+ `string_copy' to `strdup'.
+
+Wed Jan 1 16:45:14 1992 Kathy Hargreaves (kathy at hayley)
+
+ * gf_output.c (gf_put_preamble): Just truncate comment if it's too
+ long, instead of fataling.
+
+Tue Oct 1 07:52:47 1991 Karl Berry (karl at hayley)
+
+ * gf_input.c (deblank): remove blank rows at the top and bottom.
+
+Tue Jul 30 13:18:02 1991 Karl Berry (karl at ra.cs.umb.edu)
+
+ * Version 0.3.
+
+Sat Jun 15 09:50:04 1991 Karl Berry (karl at hayley)
+
+ * all files: change `checked_' to `x'.
+
+Thu Jun 6 07:28:10 1991 Karl Berry (karl at hayley)
+
+ * all files: change to version 2 of the GPL.
+
+Tue Apr 23 13:39:09 1991 Karl Berry (karl at ra.cs.umb.edu)
+
+ * gf_input.c (get_paint): remove assertion that we're at a valid
+ location.
+
+Thu Mar 7 07:32:38 1991 Karl Berry (karl at hayley)
+
+ * Version 0.2.
+
+Mon Feb 25 16:15:06 1991 Karl Berry (karl at hayley)
+
+ * gf_output.c (put_boc): declare static
+
+ * gf_{input,output}.c: change names to `gf_...' from `..._gf_...'.
+
+ * GNUmakefile (sources): remove `gf_common.c'.
+ * gf_input.c (gf_get_postamble): initialize the postamble inline.
+
+Sun Feb 17 09:31:14 1991 Karl Berry (karl at hayley)
+
+ * *.c: include config.h.
+
+Sun Jan 13 09:37:11 1991 Karl Berry (karl at hayley)
+
+ * gf_input.c (get_raw_gf_char, append_byte, append_n_bytes): use
+ `raw_char_type' instead of `raw_gf_char_type', and RAW_...
+ macros instead of GF_RAW...
+ * gf_output.c (put_raw_gf_char): likewise.
+
+ * gf_input.c (get_raw_gf_char): loop until eoc reading the
+ character, instead of while (0).
+
+ * gf_input.c (ENSURE_AVAILABLE): loop as long as we need more
+ space, instead of testing once.
+
+ * gf_input.c (get_raw_gf_char): allocate the space for the new
+ character before storing into it.
+
+Sat Jan 12 14:56:18 1991 Karl Berry (karl at hayley)
+
+ * gf_input.c (get_raw_gf_char, append_byte, append_n_bytes,
+ new_gf_raw_char): new routines to handle reading raw characters.
+ * gf_output.c (start_put_char, put_raw_gf_char): more new
+ routines.
+
+Sat Nov 17 12:46:52 1990 Karl Berry (karl at hayley)
+
+ * gf_input.c, gf_output.c: include appropriate file-...h files.
+
+Wed Oct 17 18:06:17 1990 Karl Berry (karl at aten)
+
+ * gf_input.c (deblank): when the bitmap is all zero, ensure that
+ all its dimensions are also zero.
+
+Fri Oct 5 07:03:35 1990 Karl Berry (karl at hayley)
+
+ * gf_input.c (close_gf_input_file): null the elements of
+ `char_list'.
+ (get_given_gf_char): make `char_list' global to the file.
+
+Wed Aug 29 14:13:08 1990 Karl Berry (karl at hayley)
+
+ * gf_input.c (gf_get_byte, ...): pass gf_input_filename, and
+ rewrite as macros.
+ * gf_output.c (gf_put_byte, ...): likewise.
+
+Tue Jul 24 13:19:40 1990 Karl Berry (karl at hayley)
+
+ * gf_output.c (put_gf_postamble): the pointer after the POST byte
+ is still wrong.
+
+Thu Jul 5 06:30:56 1990 Karl Berry (karl at hayley)
+
+ * gf_output.c (put_gf_postamble): output the right pointer after
+ the POST byte.
+
+Wed Jul 4 09:00:19 1990 Karl Berry (karl at hayley)
+
+ * gf_input.c (get_full_boc): allow the character with code
+ MAX_CHAR_CODE.
+
+Wed Jun 20 07:24:23 1990 Karl Berry (karl at hayley)
+
+ * gf_output.c (put_gf_preamble): just output the characters of the
+ comment here, instead of calling gf_put_string. Also, don't give
+ a fatal message if the comment is too long.
+ (gf_put_string): delete this.
+
+ * gf_input.c (gf_cur_pos): use checked_ftell; rename to gf_ftell,
+ and change callers.
+ (gf_set_pos): rename to gf_fseek.
+ * gf_output.c (gf_cur_pos): likewise.
+
+Tue Jun 19 10:56:10 1990 Karl Berry (karl at hayley)
+
+ * gf_input.c (open_gf_input_file): complain if the input file
+ already exists and the caller tries to open a second.
+
+Sun Jun 3 11:06:31 1990 Karl Berry (karl at hayley)
+
+ * gf_input.c (get_character_bitmap): ignore NO_OPs before the EOC
+ of a blank character.
+
+Fri Jun 1 15:14:29 1990 Karl Berry (karl at hayley)
+
+ * gf_output.c (close_gf_output_file): use checked_fclose.
+
+ * gf_output.c (open_gf_output_file): make sure the output file
+ hasn't already been opened.
+
+Wed May 30 15:36:46 1990 Karl Berry (karl at hayley)
+
+ * gf_input.c (get_full_boc): make sure the character code is in
+ range.
+
+Thu May 3 09:29:17 1990 Karl Berry (karl at hayley)
+
+ * gf_common.c (new_gf_char): delete this.
+ * gf_input.c (get_gf_char): don't call it.
+
+Sat Apr 21 09:43:34 1990 Karl Berry (karl at hayley)
+
+ * gf_input.c (gf_get_string): add a trailing null to the end of
+ the returned string.
+
+Thu Apr 19 16:10:21 1990 Karl Berry (karl at hayley)
+
+ * gf_common.c (new_gf_postamble): forgot to initialize character
+ #255 in a new postamble.
+
+ * gf_input.c (get_postamble): don't ignore the checksum.
+
+Mon Apr 16 07:21:42 1990 Karl Berry (karl at hayley)
+
+ * gf_opcodes.h: add #pragma once.
+
+Sat Apr 14 17:04:40 1990 Karl Berry (karl at hayley)
+
+ * gf_input.c (get_character_bitmap): call get_specials when we see
+ a special opcode, so that we skip over the arguments.
+
+Mon Apr 9 07:11:48 1990 Karl Berry (karl at hayley)
+
+ * gf_common.c (new_gf_postamble): remove references to the
+ specials; upcase `max_char_code' and `null_byte_ptr'.
+ (new_gf_char): new name for `new_generic_char'; remove references
+ to the specials.
+ gf_input.c (thoughout): use macros to look at the postamble and
+ character structures; upcase `fatal' and other global macros.
+ gf_output.c: likewise.
+ GNUmakefile: remove references to gf_util.c and generic.h.
+
+Tue Apr 3 17:32:24 1990 Karl Berry (karl at hayley)
+
+ * gf_input.c (deblank): forgot to initialize width and height.
+
+Thu Mar 1 11:19:06 1990 Karl Berry (karl at hayley)
+
+ * gf_output.c (put_gf_char): don't fail when a character is output
+ more than once; just give a warning (and only outpt the first one).
+
+ * gf_input.c (deblank): don't fail if the character is all white
+ (in which case white_on_right=white_on_left, and we don't want to
+ subtract them both from the width).
+
+ * gf_input.c (get_character_bitmap): and fix the same off-by-one
+ bug fixed on Feb 23, this time for the height. Will I ever get
+ this right?
+ [no, rescind that. The height IS inclusive, and the width is NOT
+ inclusive.]
+
+ * gf_input.c (get_character_bitmap): if the character is zero
+ wide, read the EOC following.
+
+ * gf_input.c (get_character_bitmap): don't assert that the
+ max_row >= min_row (or col), because if the character is zero
+ high (or wide), it won't be.
+ (deblank): make this_col be int, not unsigned, since we subtract
+ one from it.
+
+Tue Feb 27 20:58:52 1990 Kathy Hargreaves (kathy at hayley)
+
+ * gf_input.c (gf_get_string): if the length is zero, don't try to
+ read anything from the file.
+
+Fri Feb 23 13:28:07 1990 Karl Berry (karl at hayley)
+
+ * gf_input.c (get_character_bitmap): fix off-by-one in deciding how
+ wide the bitmap should be.
+
+Sat Feb 3 10:28:28 1990 Karl Berry (karl at hayley)
+
+ * Makefile: rename to GNUmakefile.
+
+Wed Jan 24 17:49:01 1990 Karl Berry (karl at hayley)
+
+ * gf_util.c (ascender_part): new routine.
+
+Mon Oct 30 18:41:42 1989 Karl Berry (karl at hayley)
+
+ * all files: add the copyleft.
+
+Sun Oct 29 07:33:50 1989 Karl Berry (karl at hayley)
+
+ * gf_output.c (put_boc): have to test the maximums of the bounding
+ box for sign, as well as the deltas.
+
+Sat Oct 28 15:20:26 1989 Karl Berry (karl at hayley)
+
+ * gf_output.c (put_skip): correct misinterpretation of the SKIP0
+ opcode.
+
+ * gf_output.c (put_paint, put_skip, put_new_row): define these.
+
+ * gf_output.c (font_bb): initialize using MAXINT, from <values.h>.
+
+Tue Oct 17 21:36:31 1989 Karl Berry (karl at hayley)
+
+ * gf_input.c (get_locators): CHAR_LOC commands take a one-byte
+ character residue, like CHAR_LOC0 commands, not four-byte
+ character codes.
+
+Fri Oct 6 19:18:58 1989 Karl Berry (karl at hayley)
+
+ * gf_util.c (print_gf_char): pass in a file parameter, instead of
+ always writing to stdout.
diff --git a/gf/GNUmakefile b/gf/GNUmakefile
new file mode 100644
index 0000000..d5e2d01
--- /dev/null
+++ b/gf/GNUmakefile
@@ -0,0 +1,27 @@
+# Makefile for the GF library.
+#
+# 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.
+#
+library = gf
+
+h_only = gf_opcodes
+c_only = gf_input gf_output
+
+include ../data/defs.make
+include ../data/defslib.make
+
+include M.depend
diff --git a/gf/README b/gf/README
new file mode 100644
index 0000000..9e071d5
--- /dev/null
+++ b/gf/README
@@ -0,0 +1,12 @@
+This library provides for reading and writing of generic font (GF)
+bitmap files. Only a single file may be read or written at a time.
+
+None of the code that processes the GF commands actually explains what
+the precise definition of those commands are. For that, you should look
+at the definition of the GF format in Metafont: The Program, by Don
+Knuth, chapter 45. It is also in the METAFONTware programs that convert
+to or from GF format.
+
+The header file is ../include/gf.h. It explains the basics of how to
+use the routines. The source files in this directory do not repeat that
+explanation.
diff --git a/gf/gf_input.c b/gf/gf_input.c
new file mode 100644
index 0000000..d0c81e6
--- /dev/null
+++ b/gf/gf_input.c
@@ -0,0 +1,976 @@
+/* gf_input.c: read objects from one GF file.
+
+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 "file-input.h"
+#include "gf.h"
+#include "scaled-num.h"
+
+#include "gf_opcodes.h"
+
+
+/* If true, print out what we read. */
+static boolean tracing_gf_input = false;
+
+
+/* These identify the file we're reading, for our own use. */
+static string gf_input_filename;
+static FILE *gf_input_file;
+
+
+/* Low-level input. These macros call the corresponding routines in
+ kbase, using the static variables for the input file and filename. */
+
+#define GF_FTELL() xftell (gf_input_file, gf_input_filename)
+#define GF_FSEEK(offset, from_where) \
+ xfseek (gf_input_file, offset, from_where, gf_input_filename)
+#define GF_GET_BYTE() get_byte (gf_input_file, gf_input_filename)
+#define GF_GET_PREVIOUS() get_previous_byte (gf_input_file, gf_input_filename)
+#define GF_GET_TWO() get_two (gf_input_file, gf_input_filename)
+#define GF_GET_FOUR() get_four (gf_input_file, gf_input_filename)
+#define GF_GET_SIGNED_FOUR() \
+ get_signed_four (gf_input_file, gf_input_filename)
+#define GF_GET_PREVIOUS_FOUR() \
+ get_previous_four (gf_input_file, gf_input_filename)
+#define GF_MATCH_BYTE(expected) \
+ match_byte (expected, gf_input_file, gf_input_filename)
+
+static void get_specials (byte_count_type special_ptr);
+static string gf_get_string (unsigned string_length);
+static four_bytes gf_get_three (void);
+
+
+/* We have occasion to refer to the postamble when reading the characters,
+ so we keep a copy for ourselves. */
+static gf_postamble_type *private_postamble;
+
+/* This reads into `private_postamble'. */
+static void get_postamble (void);
+
+static void get_locators (void);
+
+
+/* Pointers to the characters we have read. */
+static gf_char_type *char_list[MAX_CHARCODE + 1];
+
+
+/* Subroutines for reading a character. */
+static void get_full_boc (gf_char_type *);
+static void get_abbreviated_boc (gf_char_type *);
+static void get_character_bitmap (gf_char_type *);
+static void get_postamble_info (gf_char_type *);
+static void deblank (gf_char_type *);
+
+/* Subroutines for reading the bitmap. */
+static void get_paint (coordinate_type *, boolean *, one_byte, gf_char_type *);
+static void get_skip (coordinate_type *, boolean *, one_byte, gf_char_type *);
+static void get_new_row
+ (coordinate_type *, boolean *, one_byte, gf_char_type *);
+
+/* For handling raw characters. */
+static void append_byte (raw_char_type *, one_byte);
+static void append_n_bytes (raw_char_type *, four_bytes, one_byte *);
+static raw_char_type new_raw_gf_char (gf_char_locator_type);
+
+/* Start reading FILENAME. Return false if it can't be opened. */
+
+boolean
+gf_open_input_file (string filename)
+{
+ if (gf_input_file != NULL)
+ FATAL2 ("gf_open_input_file: Attempt to open `%s', but `%s' is
+already open", filename, gf_input_filename);
+
+ gf_input_filename = filename;
+ gf_input_file = fopen (filename, "r");
+
+ return gf_input_file != NULL;
+}
+
+
+void
+gf_close_input_file ()
+{
+ unsigned code;
+
+ assert (gf_input_file != NULL);
+
+ xfclose (gf_input_file, gf_input_filename);
+
+ gf_input_filename = NULL;
+ gf_input_file = NULL;
+ private_postamble = NULL;
+
+ for (code = 0; code <= MAX_CHARCODE; code++)
+ char_list[code] = NULL;
+}
+
+/* The only interesting thing in the preamble, either to the user or to
+ us, is the comment.
+
+ It is wrong to save and restore the position in the gf file, since
+ this routine is primarily useful if the user intends to use
+ `gf_get_next_char', i.e., read the characters in the order they
+ appear. In that case, the user has to read the preamble first. */
+
+string
+gf_get_preamble ()
+{
+ one_byte comment_length;
+ string answer;
+
+ assert (gf_input_file != NULL);
+
+ GF_MATCH_BYTE (PRE);
+ GF_MATCH_BYTE (GF_ID);
+
+ comment_length = GF_GET_BYTE ();
+ answer = gf_get_string (comment_length);
+
+ return answer;
+}
+
+/* Reading the postamble. This is the user-level call. We make no
+ assumptions about the current position of the file pointer. */
+
+gf_postamble_type
+gf_get_postamble ()
+{
+ one_byte b;
+ byte_count_type old_pos, post_ptr;
+ unsigned this_char;
+
+ assert (gf_input_file != NULL);
+
+ if (private_postamble != NULL) /* Previously read it? */
+ return *private_postamble;
+
+ old_pos = GF_FTELL ();
+ GF_FSEEK (0, SEEK_END);
+
+ /* If the input file is empty, give a better message than `Invalid
+ argument' (because we are trying to seek before the beginning). */
+ if (GF_FTELL () == 0)
+ FATAL1 ("%s: empty file", gf_input_filename);
+
+ do
+ b = GF_GET_PREVIOUS ();
+ while (b == GF_SIGNATURE);
+
+ if (b != GF_ID)
+ FATAL2 ("Expected GF id (%u), found %u", GF_ID, b);
+
+ post_ptr = GF_GET_PREVIOUS_FOUR ();
+
+ private_postamble = xmalloc (sizeof (gf_postamble_type));
+
+ for (this_char = 0; this_char <= MAX_CHARCODE; this_char++)
+ {
+ GF_CHAR_LOC (*private_postamble, this_char).charcode
+ = this_char;
+ GF_CHAR_LOC (*private_postamble, this_char).char_pointer
+ = NULL_BYTE_PTR;
+ }
+
+ GF_FSEEK (post_ptr, SEEK_SET);
+ get_postamble (); /* Fills in `private_postamble'. */
+
+ GF_FSEEK (old_pos, SEEK_SET);
+ return *private_postamble;
+}
+
+
+/* Assume we are positioned at the beginning of the postamble. Fill in
+ `private_postamble' with what we find. */
+
+static void
+get_postamble ()
+{
+ GF_MATCH_BYTE (POST);
+
+ (void) GF_GET_FOUR (); /* Ignore the special pointer. */
+
+ GF_DESIGN_SIZE (*private_postamble) = GF_GET_FOUR ();
+ GF_CHECKSUM (*private_postamble) = GF_GET_FOUR ();
+
+ /* The resolution values are stored in the file as pixels per point,
+ scaled by 2^16. */
+ GF_H_RESOLUTION (*private_postamble) = GF_GET_FOUR ();
+ GF_V_RESOLUTION (*private_postamble) = GF_GET_FOUR ();
+
+ MIN_COL (GF_FONT_BB (*private_postamble)) = GF_GET_SIGNED_FOUR ();
+ MAX_COL (GF_FONT_BB (*private_postamble)) = GF_GET_SIGNED_FOUR ();
+ MIN_ROW (GF_FONT_BB (*private_postamble)) = GF_GET_SIGNED_FOUR ();
+ MAX_ROW (GF_FONT_BB (*private_postamble)) = GF_GET_SIGNED_FOUR ();
+
+ get_locators ();
+}
+
+
+/* We do not know in advance how many character locators exist, but we do
+ place a maximum on it (contrary to what the GF format definition
+ says), namely, MAX_CHARCODE. */
+
+static void
+get_locators ()
+{
+ do
+ {
+ one_byte code;
+ one_byte b = GF_GET_BYTE ();
+
+ if (b == POST_POST)
+ break;
+
+ code = GF_GET_BYTE ();
+
+ if (b == CHAR_LOC)
+ {
+ GF_CHAR_LOC (*private_postamble, code).h_escapement
+ = scaled_to_real (GF_GET_FOUR ()) + .5;
+ (void) GF_GET_FOUR (); /* Ignore vertical escapement. */
+ }
+ else if (b == CHAR_LOC0)
+ GF_CHAR_LOC (*private_postamble, code).h_escapement = GF_GET_BYTE ();
+ else
+ FATAL1 ("Expected a char_loc command, not %u", b);
+
+ GF_CHAR_LOC (*private_postamble, code).tfm_width = GF_GET_FOUR ();
+ GF_CHAR_LOC (*private_postamble, code).char_pointer = GF_GET_FOUR ();
+ }
+ while (true);
+}
+
+/* Unlike `gf_get_next_char' (which comes next), this routine will get any
+ character by its code. It is meant to be called by the user. We
+ save all the characters we read in the static `char_list', to avoid
+ going out to the file each time. */
+
+gf_char_type *
+gf_get_char (one_byte charcode)
+{
+ gf_char_locator_type char_locator;
+ byte_count_type char_pointer;
+
+ if (char_list[charcode] != NULL)
+ return char_list[charcode];
+
+ (void) gf_get_postamble ();
+ assert (private_postamble != NULL);
+
+ char_locator = GF_CHAR_LOC (*private_postamble, charcode);
+ char_pointer = char_locator.char_pointer;
+
+ if (char_pointer != NULL_BYTE_PTR)
+ {
+ boolean found;
+ byte_count_type old_pos = GF_FTELL ();
+ GF_FSEEK (char_pointer, SEEK_SET);
+
+ char_list[charcode] = xmalloc (sizeof (gf_char_type));
+ *(char_list[charcode]) = gf_get_next_char (&found);
+ assert (found);
+
+ GF_FSEEK (old_pos, SEEK_SET);
+ }
+
+ return char_list[charcode];
+}
+
+
+/* This reads the character starting from the current position (but some
+ specials might come first). */
+
+gf_char_type
+gf_get_next_char (boolean *found)
+{
+ one_byte c;
+ gf_char_type gf_char;
+
+ get_specials (GF_FTELL ());
+
+ c = GF_GET_BYTE ();
+
+ if (c == BOC)
+ get_full_boc (&gf_char);
+
+ else if (c == BOC1)
+ get_abbreviated_boc (&gf_char);
+
+ else if (c == POST)
+ {
+ *found = false;
+ return gf_char; /* We are returning garbage, but that's OK. */
+ }
+
+ else
+ FATAL1 ("Expected a character (or the postamble), found %u", c);
+
+ get_character_bitmap (&gf_char);
+ get_postamble_info (&gf_char);
+
+ deblank (&gf_char);
+
+ *found = true;
+ return gf_char;
+}
+
+
+/* If the back pointer actually points somewhere, this character is a
+ ``residue'', and the font is probably too big. */
+
+static void
+get_full_boc (gf_char_type *gf_char)
+{
+ signed_4_bytes back_pointer, charcode;
+
+ charcode = GF_GET_SIGNED_FOUR ();
+ if (charcode < 0 || charcode > MAX_CHARCODE)
+ /* Someone is trying to use a font with character codes that are
+ out of our range. */
+ FATAL1 ("Character code %d out of range 0..255 in GF file (sorry)",
+ charcode);
+
+ GF_CHARCODE (*gf_char) = charcode;
+
+ back_pointer = GF_GET_SIGNED_FOUR ();
+ if (back_pointer != -1)
+ WARNING2 ("Character %u has a non-null back pointer (to %d)",
+ GF_CHARCODE (*gf_char), back_pointer);
+
+ GF_CHAR_MIN_COL (*gf_char) = GF_GET_SIGNED_FOUR ();
+ GF_CHAR_MAX_COL (*gf_char) = GF_GET_SIGNED_FOUR ();
+ GF_CHAR_MIN_ROW (*gf_char) = GF_GET_SIGNED_FOUR ();
+ GF_CHAR_MAX_ROW (*gf_char) = GF_GET_SIGNED_FOUR ();
+}
+
+
+static void
+get_abbreviated_boc (gf_char_type *gf_char)
+{
+ one_byte col_delta, row_delta;
+
+ GF_CHARCODE (*gf_char) = GF_GET_BYTE ();
+
+ col_delta = GF_GET_BYTE ();
+ GF_CHAR_MAX_COL (*gf_char) = GF_GET_BYTE ();
+ GF_CHAR_MIN_COL (*gf_char) = GF_CHAR_MAX_COL (*gf_char) - col_delta;
+
+ row_delta = GF_GET_BYTE ();
+ GF_CHAR_MAX_ROW (*gf_char) = GF_GET_BYTE ();
+ GF_CHAR_MIN_ROW (*gf_char) = GF_CHAR_MAX_ROW (*gf_char) - row_delta;
+}
+
+
+/* We also want to return the horizontal escapement (i.e., set width)
+ and the TFM width as part of the character, although this information is
+ not part of the boc..eoc, but rather the postamble. */
+
+static void
+get_postamble_info (gf_char_type *gf_char)
+{
+ gf_char_locator_type char_locator;
+
+ (void) gf_get_postamble (); /* Use `private_postamble'. */
+ assert (private_postamble != NULL);
+
+ char_locator = GF_CHAR_LOC (*private_postamble, GF_CHARCODE (*gf_char));
+
+ GF_H_ESCAPEMENT (*gf_char) = char_locator.h_escapement;
+ GF_TFM_WIDTH (*gf_char) = char_locator.tfm_width;
+}
+
+
+/* The GF format does not guarantee that the bounding box is the
+ smallest possible, i.e., that the character bitmap does not have
+ blank rows or columns at an edge. We want to remove such blanks. */
+
+static void
+deblank (gf_char_type *gf_char)
+{
+ boolean all_white;
+ bitmap_type gf_bitmap = GF_BITMAP (*gf_char);
+ unsigned width = BITMAP_WIDTH (gf_bitmap),
+ height = BITMAP_HEIGHT (gf_bitmap);
+ unsigned white_on_left = 0, white_on_right = 0,
+ white_on_top = 0, white_on_bottom = 0;
+ int this_col, this_row; /* int in case GF_CHAR is zero pixels wide. */
+
+ /* Let's start with blank columns at the left-hand side. */
+ all_white = true;
+ for (this_col = 0; this_col < width && all_white; this_col++)
+ {
+ for (this_row = 0; this_row < height && all_white; this_row++)
+ {
+ if (BITMAP_PIXEL (gf_bitmap, this_row, this_col) != 0)
+ all_white = false;
+ }
+ if (all_white)
+ white_on_left++;
+ }
+
+ /* Now let's check the right-hand side. */
+ all_white = true;
+ for (this_col = width - 1; this_col >= 0 && all_white; this_col--)
+ {
+ for (this_row = 0; this_row < height && all_white; this_row++)
+ {
+ if (BITMAP_PIXEL (gf_bitmap, this_row, this_col) != WHITE)
+ all_white = false;
+ }
+ if (all_white)
+ white_on_right++;
+ }
+
+ /* Check for all-white rows on top now. */
+ all_white = true;
+ for (this_row = 0; this_row < height && all_white; this_row++)
+ {
+ for (this_col = 0; this_col < width && all_white; this_col++)
+ {
+ if (BITMAP_PIXEL (gf_bitmap, this_row, this_col) != WHITE)
+ all_white = false;
+ }
+ if (all_white)
+ white_on_top++;
+ }
+
+ /* And, last, for all-white rows on the bottom. */
+ all_white = true;
+ for (this_row = height - 1; this_row >= 0 && all_white; this_row--)
+ {
+ for (this_col = 0; this_col < width && all_white; this_col++)
+ {
+ if (BITMAP_PIXEL (gf_bitmap, this_row, this_col) != WHITE)
+ all_white = false;
+ }
+ if (all_white)
+ white_on_bottom++;
+ }
+
+ /* If we have to remove columns at either the left or the right, we
+ have to reallocate the memory, since much code depends on the fact
+ that the bitmap is in contiguous memory. If we have to remove
+ rows, we don't necessarily have to reallocate the memory, but we
+ might as well, to save space. */
+ if (white_on_left > 0 || white_on_right > 0
+ || white_on_top > 0 || white_on_bottom > 0)
+ {
+ bitmap_type condensed;
+
+ if (white_on_left + white_on_right > width)
+ { /* The character was entirely blank. */
+ BITMAP_WIDTH (condensed) = BITMAP_HEIGHT (condensed) = 0;
+ GF_CHAR_MIN_COL (*gf_char) = GF_CHAR_MAX_COL (*gf_char)
+ = GF_CHAR_MIN_ROW (*gf_char) = GF_CHAR_MAX_ROW (*gf_char) = 0;
+ BITMAP_BITS (condensed) = NULL;
+ }
+ else
+ {
+ dimensions_type d;
+ DIMENSIONS_HEIGHT (d) = height - white_on_top - white_on_bottom;
+ DIMENSIONS_WIDTH (d) = width - white_on_left - white_on_right;
+ condensed = new_bitmap (d);
+
+ for (this_row = 0; this_row < BITMAP_HEIGHT (condensed); this_row++)
+ for (this_col = 0; this_col < BITMAP_WIDTH (condensed); this_col++)
+ {
+ BITMAP_PIXEL (condensed, this_row, this_col)
+ = BITMAP_PIXEL (gf_bitmap, this_row + white_on_top,
+ this_col + white_on_left);
+ }
+ GF_CHAR_MIN_ROW (*gf_char) += white_on_bottom;
+ GF_CHAR_MAX_ROW (*gf_char) -= white_on_top;
+ GF_CHAR_MIN_COL (*gf_char) += white_on_left;
+ GF_CHAR_MAX_COL (*gf_char) -= white_on_right;
+ }
+
+ free_bitmap (&GF_BITMAP (*gf_char));
+ GF_BITMAP (*gf_char) = condensed;
+ }
+}
+
+
+/* The ``bitmap'' is a sequence of commands that describe it in terms of
+ run-length encoding.
+
+ GF's row and column numbers are the lower left corner of a pixel.
+ GF (0,0) is the Cartesian unit square: 0 <= x (col) <= 1,
+ 0 <= y (row) <= 1. Yes, it's <=, not <. What does this mean for
+ the maxes and mins? Let's take the height first: if a character has
+ min_row = 0 and max_row = 10, we start the ``current'' y at 10,
+ (possibly) paint some pixels on that row, ..., and end up with it at
+ zero, (possibly) painting some pixels on that row. Thus, there are
+ 11 (10 - 0 + 1) rows in which we might paint pixels. Now the width:
+ if a character has min_row = 0 and max_row = 4, the current x starts
+ at zero, we paint four pixels (let's say), and now the current x is
+ four (the max possible), so we cannot paint any more. Thus there are
+ four (4 - 0) columns in which we might paint pixels.
+
+ Weird, huh? */
+
+static void
+get_character_bitmap (gf_char_type *gf_char)
+{
+ /* We expect these to be >= 0, but if the GF file is improper, they
+ might turn to be negative. */
+ int height, width;
+ dimensions_type matrix_dimensions;
+ coordinate_type current; /* This will be the GF position. */
+ boolean painting_black = false;
+
+ current.x = GF_CHAR_MIN_COL (*gf_char);
+ current.y = GF_CHAR_MAX_ROW (*gf_char);
+
+ width = GF_CHAR_MAX_COL (*gf_char) - GF_CHAR_MIN_COL (*gf_char);
+ height = GF_CHAR_MAX_ROW (*gf_char) - GF_CHAR_MIN_ROW (*gf_char) + 1;
+
+ /* If the character has zero or negative extent in either dimension,
+ it's not going to have a bitmap. (If this happens, the GF file is
+ incorrect; but the discrepancy isn't serious, so we may as well not
+ bomb out when it happens, especially since PKtoGF has a bug that
+ produces such a bounding box when the character is all blank.) */
+ if (width <= 0 || height <= 0)
+ {
+ one_byte b;
+ BITMAP_HEIGHT (GF_BITMAP (*gf_char))
+ = BITMAP_WIDTH (GF_BITMAP (*gf_char))
+ = 0;
+ BITMAP_BITS (GF_BITMAP (*gf_char)) = NULL;
+
+ /* The next non-NO_OP byte should be EOC. */
+ while ((b = GF_GET_BYTE ()) == NO_OP)
+ /* do nothing */ ;
+ if (b != EOC)
+ FATAL1 ("Expected eoc (for a blank character), found %u", b);
+
+ return;
+ }
+
+ DIMENSIONS_HEIGHT (matrix_dimensions) = height;
+ DIMENSIONS_WIDTH (matrix_dimensions) = width;
+ GF_BITMAP (*gf_char) = new_bitmap (matrix_dimensions);
+
+ do
+ {
+ one_byte c = GF_GET_BYTE ();
+
+ if (c == EOC)
+ break;
+
+ /* No need to test if `PAINT_0 <= c'; it must be, since PAINT_0 is
+ zero and `c' is unsigned. */
+ if (/* PAINT_0 <= c && */ c <= PAINT3)
+ get_paint (&current, &painting_black, c, gf_char);
+
+ else if (SKIP0 <= c && c <= SKIP3)
+ get_skip (&current, &painting_black, c, gf_char);
+
+ else if (NEW_ROW_0 <= c && c <= NEW_ROW_164)
+ get_new_row (&current, &painting_black, c, gf_char);
+
+ else if (c == NO_OP)
+ /* do nothing */ ;
+
+ else if ((XXX1 <= c && c <= XXX4) || c == YYY)
+ get_specials (GF_FTELL ());
+
+ else
+ FATAL1 ("Expected paint or skip or new_row, found %u", c);
+ }
+ while (true);
+
+ if (tracing_gf_input)
+ puts ("");
+}
+
+
+/* The paint commands come in two varieties -- either with the length
+ implicitly part of the command, or where it is specified as a separate
+ parameter. */
+
+static void
+get_paint (coordinate_type *current, boolean *painting_black,
+ one_byte command, gf_char_type *gf_char)
+{
+ unsigned length;
+
+ /* No need to test if `PAINT_0 <= command'; it must be, since PAINT_0 is
+ zero and `command' is unsigned. */
+ if (/* PAINT_0 <= command && */ command <= PAINT_63)
+ length = command - PAINT_0;
+ else
+ {
+ switch (command)
+ {
+ case PAINT1:
+ length = GF_GET_BYTE ();
+ break;
+
+ case PAINT2:
+ length = GF_GET_TWO ();
+ break;
+
+ case PAINT3:
+ length = gf_get_three ();
+ break;
+
+ default:
+ FATAL1 ("Expected a paint command, found %u", command);
+ }
+ }
+
+ /* We have to translate from Cartesian to C coordinates. That means the
+ x's are the same, but the y's are flipped. */
+ if (*painting_black)
+ {
+ unsigned matrix_y = GF_CHAR_MAX_ROW (*gf_char) - current->y;
+
+ if (tracing_gf_input)
+ printf ("%u", length);
+
+ for (; length != 0; length--)
+ {
+ unsigned matrix_x = current->x - GF_CHAR_MIN_COL (*gf_char);
+
+ BITMAP_PIXEL (GF_BITMAP (*gf_char), matrix_y, matrix_x) = 1;
+
+ current->x++;
+ }
+ }
+ else
+ {
+ current->x += length;
+
+ if (tracing_gf_input)
+ printf ("(%u)", length);
+ }
+ *painting_black = !*painting_black;
+}
+
+
+/* Skip commands move down in the GF character, leaving blank rows. */
+
+static void
+get_skip (coordinate_type * current, boolean * painting_black,
+ one_byte command, gf_char_type *gf_char)
+{
+ unsigned rows_to_skip;
+
+ switch (command)
+ {
+ case SKIP0:
+ rows_to_skip = 0;
+ break;
+
+ case SKIP1:
+ rows_to_skip = GF_GET_BYTE ();
+ break;
+
+ case SKIP2:
+ rows_to_skip = GF_GET_TWO ();
+ break;
+
+ case SKIP3:
+ rows_to_skip = gf_get_three ();
+ break;
+
+ default:
+ FATAL1 ("Expected skip command, found %u", command);
+ }
+
+ current->y -= rows_to_skip + 1;
+ current->x = GF_CHAR_MIN_COL (*gf_char);
+ *painting_black = false;
+
+ if (tracing_gf_input)
+ printf ("\nskip %u (y now %d) ", rows_to_skip + 1, current->y);
+}
+
+
+/* `new_row' commands move to the next line down and then over. */
+
+static void
+get_new_row (coordinate_type *current, boolean *painting_black,
+ one_byte command, gf_char_type *gf_char)
+{
+ current->y--;
+ current->x = GF_CHAR_MIN_COL (*gf_char) + command - NEW_ROW_0;
+ *painting_black = true;
+
+ if (tracing_gf_input)
+ printf ("\nnew_row %u (x,y now %d,%d) ", command - NEW_ROW_0,
+ current->x, current->y);
+}
+
+/* Instead of building a bitmap, this routine just reads the bytes that
+ define the character CHARCODE. If the character doesn't exist, we
+ return NULL. */
+
+/* Append the byte `b' to the buffer in `raw_char', followed by (if
+ WITH_SIZE_P is true) SIZE, followed SIZE bytes of the input. */
+#define COMMON_APPEND(size, with_size_p) \
+ do \
+ { \
+ append_byte (raw_char, b); \
+ if (with_size_p) append_byte (raw_char, size); \
+ if (size > 0) append_n_bytes (raw_char, size, get_n_bytes (size, \
+ gf_input_file, gf_input_filename)); \
+ } \
+ while (0)
+
+#define APPEND_BYTES(n) COMMON_APPEND (n, false)
+#define APPEND_VAR_BYTES(n) COMMON_APPEND (n, true)
+
+raw_char_type *
+gf_get_raw_char (one_byte charcode)
+{
+ one_byte b; /* Command byte we've just read. */
+ gf_char_locator_type char_locator;
+ byte_count_type char_pointer;
+ byte_count_type old_pos;
+ raw_char_type *raw_char;
+
+ (void) gf_get_postamble ();
+ assert (private_postamble != NULL);
+
+ char_locator = GF_CHAR_LOC (*private_postamble, charcode);
+ char_pointer = char_locator.char_pointer;
+
+ /* If the character doesn't exist in the font, we're done. */
+ if (char_pointer == NULL_BYTE_PTR)
+ return NULL;
+
+ /* Save where we are in the file; we'll restore it when we're done. */
+ old_pos = GF_FTELL ();
+ GF_FSEEK (char_pointer, SEEK_SET);
+
+ raw_char = xmalloc (sizeof (raw_char_type));
+ *raw_char = new_raw_gf_char (char_locator);
+
+ /* Unfortunately, the GF format doesn't tell us how many bytes long
+ the character description is. So, we must decode it enough to
+ figure out how much to read. */
+
+ /* The first step is the boc: it might be either the one-byte or
+ four-byte variant. */
+ b = GF_GET_BYTE ();
+ if (b == BOC)
+ /* The character code, the backpointer (which will probably be wrong
+ in the new file, if it exists, but we don't handle non-null
+ backpointers anyway), the bounding box. */
+ APPEND_BYTES (24);
+ else /* b == BOC1 */
+ APPEND_BYTES (5);
+
+ /* Read the character definition; exit when we get to EOC. */
+ while ((b = GF_GET_BYTE ()) != EOC)
+ {
+ /* First test all the commands that have no parameters. No need to
+ test if `PAINT_0 <= b'; it must be, since PAINT_0 is zero and
+ `b' is unsigned. */
+ if ((/* PAINT_0 <= b && */ b <= PAINT_63)
+ || b == SKIP0
+ || (NEW_ROW_0 <= b && b <= NEW_ROW_164))
+ APPEND_BYTES (0);
+
+ /* Now the ones with a one-byte parameter. */
+ else if (b == PAINT1 || b == SKIP1)
+ APPEND_BYTES (1);
+
+ /* A two-byte parameter. */
+ else if (b == PAINT2 || b == SKIP2)
+ APPEND_BYTES (2);
+
+ /* Three-byte. */
+ else if (b == PAINT3 || b == SKIP3)
+ APPEND_BYTES (3);
+
+ /* Four. */
+ else if (b == YYY)
+ APPEND_BYTES (4);
+
+ /* Commands with a variable-size parameter. */
+ else if (b == XXX1)
+ {
+ one_byte size = GF_GET_BYTE ();
+ APPEND_VAR_BYTES (size);
+ }
+
+ else if (b == XXX2)
+ {
+ two_bytes size = GF_GET_TWO ();
+ APPEND_VAR_BYTES (size);
+ }
+
+ else if (b == XXX3)
+ {
+ four_bytes size = gf_get_three ();
+ APPEND_VAR_BYTES (size);
+ }
+
+ else if (b == XXX4)
+ {
+ four_bytes size = GF_GET_FOUR ();
+ APPEND_VAR_BYTES (size);
+ }
+
+ else if (b == NO_OP)
+ /* do nothing */;
+
+ else
+ FATAL1 ("gf_get_raw_char: Bad command byte %u", b);
+ }
+
+ /* This appends the `eoc'---and now we're done. */
+ APPEND_BYTES (0);
+
+ GF_FSEEK (old_pos, SEEK_SET);
+ return raw_char;
+}
+
+
+/* This macro makes sure the raw character RGC has at least NEEDED
+ bytes free. */
+#define ENSURE_AVAILABLE(rgc, needed) \
+ while (RAW_CHAR_ALLOCATED (rgc) - RAW_CHAR_USED (rgc) < needed) \
+ { \
+ RAW_CHAR_ALLOCATED (rgc) *= 2; \
+ RAW_CHAR_BYTES (rgc) \
+ = xrealloc (RAW_CHAR_BYTES (rgc), RAW_CHAR_ALLOCATED (rgc)); \
+ }
+
+
+/* Append the byte B to the end of the RAW_CHAR's buffer. */
+
+static void
+append_byte (raw_char_type *raw_char, one_byte b)
+{
+ ENSURE_AVAILABLE (*raw_char, 1);
+ RAW_CHAR_UNUSED_START (*raw_char) = b;
+ RAW_CHAR_USED (*raw_char)++;
+}
+
+
+/* Append the N bytes of data pointed to by DATA to the end of
+ RAW_CHAR's buffer. Free DATA after copying. */
+
+static void
+append_n_bytes (raw_char_type *raw_char, four_bytes n, one_byte *data)
+{
+ ENSURE_AVAILABLE (*raw_char, n);
+ memcpy (&RAW_CHAR_UNUSED_START (*raw_char), data, n);
+ RAW_CHAR_USED (*raw_char) += n;
+ free (data);
+}
+
+
+/* Make a new raw character. We have to start off the buffer with some
+ nonempty amount of memory, so that the reallocation will have
+ something to double. */
+
+static raw_char_type
+new_raw_gf_char (gf_char_locator_type locator)
+{
+ raw_char_type c;
+
+ RAW_CHAR_ALLOCATED (c) = 1;
+ RAW_CHAR_BYTES (c) = xmalloc (RAW_CHAR_ALLOCATED (c));
+ RAW_CHAR_USED (c) = 0;
+
+ GF_CHARCODE (c) = locator.charcode;
+ GF_H_ESCAPEMENT (c) = locator.h_escapement;
+ GF_TFM_WIDTH (c) = locator.tfm_width;
+ GF_CHAR_BB (c) = GF_FONT_BB (*private_postamble);
+
+ /* Since we don't want to interpret the bounding box information in
+ the character, we just make our bounding box be the font bounding
+ box. Since the only thing a raw character is good for is being
+ immediately written back out, this doesn't hurt. (The actual
+ bounding box information in the character isn't lost.) */
+ return c;
+}
+
+/* Read all specials beginning from the given location, leaving the file
+ pointer at the first non-special. We do not save the specials,
+ though. */
+
+static void
+get_specials (byte_count_type special_ptr)
+{
+ boolean found_special = true;
+
+ GF_FSEEK (special_ptr, SEEK_SET);
+
+ do
+ {
+ one_byte c = GF_GET_BYTE ();
+
+ switch (c)
+ {
+ case XXX1:
+ (void) gf_get_string (GF_GET_BYTE ());
+ break;
+
+ case XXX2:
+ (void) gf_get_string (GF_GET_TWO ());
+ break;
+
+ case XXX3:
+ (void) gf_get_string (gf_get_three ());
+ break;
+
+ case YYY:
+ (void) GF_GET_FOUR ();
+ break;
+
+ default:
+ found_special = false;
+ GF_FSEEK (-1, SEEK_CUR);
+ }
+ }
+ while (found_special);
+}
+
+
+static string
+gf_get_string (unsigned length)
+{
+ string s;
+
+ if (length == 0) return "";
+
+ s = get_n_bytes (length, gf_input_file, gf_input_filename);
+ s = xrealloc (s, length + 1);
+ s[length] = 0;
+ return s;
+}
+
+
+/* C does not provide an obvious type for a 24-bit quantity, so we
+ return a 32-bit one. */
+
+static four_bytes
+gf_get_three ()
+{
+ four_bytes v = get_two (gf_input_file, gf_input_filename) << 8;
+ v |= get_byte (gf_input_file, gf_input_filename);
+
+ return v;
+}
diff --git a/gf/gf_opcodes.h b/gf/gf_opcodes.h
new file mode 100644
index 0000000..f8014bf
--- /dev/null
+++ b/gf/gf_opcodes.h
@@ -0,0 +1,58 @@
+/* gf_opcodes.h: symbolic names for the GF commands.
+
+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. */
+
+#ifndef GF_OPCODES_H
+#define GF_OPCODES_H
+
+#define PRE 247
+#define POST 248
+#define POST_POST 249
+
+#define GF_SIGNATURE 223
+#define GF_ID 131
+
+#define BOC 67
+#define BOC1 68
+#define EOC 69
+
+#define PAINT_0 0
+#define PAINT_63 63
+#define PAINT1 64
+#define PAINT2 65
+#define PAINT3 66
+
+#define SKIP0 70
+#define SKIP1 71
+#define SKIP2 72
+#define SKIP3 73
+
+#define NEW_ROW_0 74
+#define NEW_ROW_164 238
+
+#define XXX1 239
+#define XXX2 240
+#define XXX3 241
+#define XXX4 242
+#define YYY 243
+
+#define NO_OP 244
+
+#define CHAR_LOC 245
+#define CHAR_LOC0 246
+
+#endif /* not GF_OPCODES_H */
diff --git a/gf/gf_output.c b/gf/gf_output.c
new file mode 100644
index 0000000..933b0cc
--- /dev/null
+++ b/gf/gf_output.c
@@ -0,0 +1,438 @@
+/* gf_output.c: write objects to one GF file.
+
+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 "file-output.h"
+#include "gf.h"
+#include "scaled-num.h"
+
+#include "gf_opcodes.h"
+
+
+/* The file we are writing to. */
+static FILE *gf_output_file = NULL;
+static string gf_output_filename;
+
+
+/* The bounding box of all the characters we have written. The values
+ here should be the largest and smallest possible integers. */
+static bounding_box_type font_bb
+ = { INT_MAX, INT_MIN, INT_MAX, INT_MIN };
+
+
+/* We keep track of the character locator information as we output
+ characters, to save the caller from doing the bookkeeping. */
+static gf_char_locator_type char_loc[MAX_CHARCODE + 1];
+
+static void init_locators (void);
+static void put_locators (void);
+
+
+/* Other parts of the GF file that deserve their own routines. */
+static void put_boc (gf_char_type);
+static void put_bitmap (bitmap_type);
+
+
+/* Subroutines for writing the bitmap. */
+static void put_paint (unsigned);
+static void put_skip (unsigned);
+static void put_new_row (unsigned);
+
+/* Low-level output. These macros call the corresponding routines in
+ fontutils, using the static variables for the input file and filename. */
+
+#define GF_FTELL() xftell (gf_output_file, gf_output_filename)
+#define GF_PUT_BYTE(b) put_byte (b, gf_output_file, gf_output_filename)
+#define GF_PUT_TWO(b) put_two (b, gf_output_file, gf_output_filename)
+#define GF_PUT_THREE(n) put_three (n, gf_output_file, gf_output_filename)
+#define GF_PUT_FOUR(n) put_four (n, gf_output_file, gf_output_filename)
+#define GF_PUT_SIGNED_FOUR(n) \
+ put_signed_four (n, gf_output_file, gf_output_filename);
+
+/* Routines to start and end writing a file. (For the user to call.)
+ We make sure the caller can't have two output files open
+ simultaneously. */
+
+boolean
+gf_open_output_file (string filename)
+{
+ assert (gf_output_file == NULL);
+
+ gf_output_filename = filename;
+ gf_output_file = fopen (filename, "w");
+
+ if (gf_output_file != NULL)
+ {
+ init_locators ();
+ return true;
+ }
+ else
+ return false;
+}
+
+
+void
+gf_close_output_file ()
+{
+ assert (gf_output_file != NULL);
+
+ xfclose (gf_output_file, gf_output_filename);
+
+ gf_output_filename = NULL;
+ gf_output_file = NULL;
+}
+
+/* Write the preamble. */
+
+void
+gf_put_preamble (string comment)
+{
+ unsigned comment_length, c;
+
+ assert (gf_output_file != NULL);
+
+ GF_PUT_BYTE (PRE);
+ GF_PUT_BYTE (GF_ID);
+
+ comment_length = strlen (comment);
+
+ if (comment_length > 255)
+ comment_length = 255;
+
+ GF_PUT_BYTE (comment_length);
+ /* We can't just output all the characters in the string, since the
+ string might have been too long. */
+ for (c = 0; c < comment_length; c++)
+ GF_PUT_BYTE (*(comment + c));
+}
+
+/* Write the postamble. */
+
+void
+gf_put_postamble (fix_word design_size, real h_resolution, real v_resolution)
+{
+ byte_count_type post_ptr;
+ unsigned i;
+
+ assert (gf_output_file != NULL);
+
+ fflush (gf_output_file);
+ post_ptr = GF_FTELL ();
+ GF_PUT_BYTE (POST);
+ GF_PUT_FOUR (post_ptr); /* No specials before the postamble. */
+ GF_PUT_FOUR (design_size);
+ GF_PUT_FOUR (0); /* Don't bother with a checksum. */
+
+ /* The resolution values are given to us in pixels per inch, but we
+ must write them in pixels per point (as well as scaling them). */
+ GF_PUT_FOUR (real_to_scaled (h_resolution / POINTS_PER_INCH));
+ GF_PUT_FOUR (real_to_scaled (h_resolution / POINTS_PER_INCH));
+
+ GF_PUT_SIGNED_FOUR (MIN_COL (font_bb));
+ GF_PUT_SIGNED_FOUR (MAX_COL (font_bb));
+ GF_PUT_SIGNED_FOUR (MIN_ROW (font_bb));
+ GF_PUT_SIGNED_FOUR (MAX_ROW (font_bb));
+
+ put_locators ();
+
+ GF_PUT_BYTE (POST_POST);
+ GF_PUT_FOUR (post_ptr);
+ GF_PUT_BYTE (GF_ID);
+
+ for (i = 0; i < 4; i++)
+ GF_PUT_BYTE (GF_SIGNATURE);
+}
+
+
+/* Here we output the information we have accumulated in the `char_loc'
+ array. GF format allows for two different `char_loc' commands, one
+ more efficient (but less general) than the other. We use the
+ appropriate one. */
+
+static void
+put_locators ()
+{
+ unsigned this_char;
+
+ for (this_char = 0; this_char <= MAX_CHARCODE; this_char++)
+ {
+ gf_char_locator_type this_char_loc = char_loc[this_char];
+
+ if (this_char_loc.char_pointer != NULL_BYTE_PTR)
+ {
+ int h_escapement = this_char_loc.h_escapement;
+
+ /* Decide if we can use CHAR_LOC0. */
+ if (h_escapement >= 0 && h_escapement < ONE_BYTE_BIG)
+ {
+ GF_PUT_BYTE (CHAR_LOC0);
+ GF_PUT_BYTE (this_char);
+ GF_PUT_BYTE (h_escapement);
+ }
+ else
+ {
+ GF_PUT_BYTE (CHAR_LOC);
+ GF_PUT_BYTE (this_char);
+ GF_PUT_FOUR (real_to_scaled ((real) h_escapement));
+ GF_PUT_FOUR (0); /* No vertical escapement. */
+ }
+
+ GF_PUT_FOUR (this_char_loc.tfm_width);
+ GF_PUT_SIGNED_FOUR (this_char_loc.char_pointer);
+ }
+ }
+}
+
+
+/* We must initialize the character locators to all null values. */
+
+static void
+init_locators ()
+{
+ unsigned this_char;
+
+ for (this_char = 0; this_char <= MAX_CHARCODE; this_char++)
+ char_loc[this_char].char_pointer = NULL_BYTE_PTR;
+}
+
+/* Do what's necessary to prepare for outputting a character. */
+
+static void
+start_put_char (charcode_type charcode, unsigned h_escapement,
+ fix_word tfm_width, bounding_box_type char_bb)
+{
+ gf_char_locator_type *this_char_loc = &(char_loc[charcode]);
+
+ assert (gf_output_file != NULL);
+
+ if (this_char_loc->char_pointer != NULL_BYTE_PTR)
+ {
+ WARNING1 ("gf_put_char: Character %u already output", charcode);
+ return;
+ }
+
+ /* Update the character locator information (part of the postamble). */
+ this_char_loc->char_pointer = GF_FTELL ();
+ this_char_loc->h_escapement = h_escapement;
+ this_char_loc->tfm_width = tfm_width;
+ this_char_loc->charcode = charcode;
+
+ /* Update the font bounding box. */
+ if (MIN_COL (char_bb) < MIN_COL (font_bb))
+ MIN_COL (font_bb) = MIN_COL (char_bb);
+ if (MAX_COL (char_bb) > MAX_COL (font_bb))
+ MAX_COL (font_bb) = MAX_COL (char_bb);
+ if (MIN_ROW (char_bb) < MIN_ROW (font_bb))
+ MIN_ROW (font_bb) = MIN_ROW (char_bb);
+ if (MAX_ROW (char_bb) > MAX_ROW (font_bb))
+ MAX_ROW (font_bb) = MAX_ROW (char_bb);
+}
+
+
+/* Output the character GF_CHAR. */
+
+void
+gf_put_char (gf_char_type gf_char)
+{
+ start_put_char (GF_CHARCODE (gf_char), GF_H_ESCAPEMENT (gf_char),
+ GF_TFM_WIDTH (gf_char), GF_CHAR_BB (gf_char));
+ put_boc (gf_char);
+ put_bitmap (GF_BITMAP (gf_char));
+ GF_PUT_BYTE (EOC);
+}
+
+
+/* Output the BOC command that begins each character. BOC commands come
+ in two flavors, one of which takes less space but is less general. */
+
+static void
+put_boc (gf_char_type gf_char)
+{
+ signed_4_bytes row_delta = (GF_CHAR_MAX_ROW (gf_char)
+ - GF_CHAR_MIN_ROW (gf_char));
+ signed_4_bytes col_delta = (GF_CHAR_MAX_COL (gf_char)
+ - GF_CHAR_MIN_COL (gf_char));
+
+ /* Decide if we can use BOC1, the abbreviated form. */
+ if (row_delta < ONE_BYTE_BIG && row_delta >= 0
+ && col_delta < ONE_BYTE_BIG && col_delta >= 0
+ && GF_CHAR_MAX_ROW (gf_char) < ONE_BYTE_BIG
+ && GF_CHAR_MAX_ROW (gf_char) >= 0
+ && GF_CHAR_MAX_COL (gf_char) < ONE_BYTE_BIG
+ && GF_CHAR_MAX_COL (gf_char) >= 0)
+ {
+ GF_PUT_BYTE (BOC1);
+ GF_PUT_BYTE (GF_CHARCODE (gf_char));
+ GF_PUT_BYTE (col_delta);
+ GF_PUT_BYTE (GF_CHAR_MAX_COL (gf_char));
+ GF_PUT_BYTE (row_delta);
+ GF_PUT_BYTE (GF_CHAR_MAX_ROW (gf_char));
+ }
+ else
+ {
+ GF_PUT_BYTE (BOC);
+ GF_PUT_FOUR (GF_CHARCODE (gf_char));
+ GF_PUT_SIGNED_FOUR (NULL_BYTE_PTR); /* We never have a backpointer. */
+ GF_PUT_SIGNED_FOUR (GF_CHAR_MIN_COL (gf_char));
+ GF_PUT_SIGNED_FOUR (GF_CHAR_MAX_COL (gf_char));
+ GF_PUT_SIGNED_FOUR (GF_CHAR_MIN_ROW (gf_char));
+ GF_PUT_SIGNED_FOUR (GF_CHAR_MAX_ROW (gf_char));
+ }
+}
+
+
+/* Bitmaps in GF format are run-encoded. There are three commands:
+ `paint', which writes a run of pixels (either black or white);
+ `skip', which leaves entirely blank rows; and `new_row', which begins
+ a new row with the first black pixel some number of pixels from the
+ left edge. */
+
+static void
+put_bitmap (bitmap_type b)
+{
+ unsigned run = 0; /* Length of the current run. */
+ one_byte current_color = WHITE;
+ boolean recent_eol = false; /* Have we seen only white since eol? */
+ unsigned all_white = 0; /* Count of entirely blank rows. */
+ unsigned this_row, this_col;
+
+
+ for (this_row = 0; this_row < BITMAP_HEIGHT (b); this_row++)
+ {
+ for (this_col = 0; this_col < BITMAP_WIDTH (b); this_col++)
+ {
+ one_byte p = BITMAP_PIXEL (b, this_row, this_col);
+
+ if (p == current_color)
+ run++;
+ else
+ {
+ if (recent_eol)
+ { /* First transition to black on new row? */
+ recent_eol = false;
+ put_skip (all_white);
+ all_white = 0;
+ /* We've seen only white up to now, since
+ `current_color' is zero after each row. */
+ put_new_row (run);
+ }
+ else
+ put_paint (run);
+
+ current_color = p;
+ run = 1;
+ }
+ }
+
+ if (current_color == BLACK)
+ {
+ put_paint (run); /* The row ended with black. */
+ current_color = WHITE;
+ }
+
+ else if (recent_eol)
+ all_white++; /* The row was entirely white. */
+
+ recent_eol = true;
+ run = 0;
+ }
+}
+
+
+/* Routines to output the actual GF commands that describe the bitmap.
+ We use the shortest possible command. */
+
+static void
+put_paint (unsigned run)
+{
+ if (run < 64)
+ GF_PUT_BYTE (run);
+ else if (run < ONE_BYTE_BIG)
+ {
+ GF_PUT_BYTE (PAINT1);
+ GF_PUT_BYTE (run);
+ }
+ else if (run < TWO_BYTES_BIG)
+ {
+ GF_PUT_BYTE (PAINT2);
+ GF_PUT_TWO (run);
+ }
+ else if (run < THREE_BYTES_BIG)
+ {
+ GF_PUT_BYTE (PAINT3);
+ GF_PUT_THREE (run);
+ }
+ else
+ FATAL1 ("put_paint: Run of %u pixels too long for GF format", run);
+}
+
+
+static void
+put_skip (unsigned all_white)
+{
+ if (all_white == 0)
+ ; /* Do nothing. */
+ else if (all_white == 1)
+ GF_PUT_BYTE (SKIP0);
+ else if (all_white < ONE_BYTE_BIG)
+ {
+ GF_PUT_BYTE (SKIP1);
+ GF_PUT_BYTE (all_white - 1);
+ }
+ else if (all_white < TWO_BYTES_BIG)
+ {
+ GF_PUT_BYTE (SKIP2);
+ GF_PUT_TWO (all_white - 1);
+ }
+ else if (all_white < THREE_BYTES_BIG)
+ {
+ GF_PUT_BYTE (SKIP3);
+ GF_PUT_THREE (all_white - 1);
+ }
+ else
+ FATAL1 ("put_skip: %u rows is too many for GF format", all_white);
+}
+
+
+static void
+put_new_row (unsigned indent)
+{
+ if (indent <= 164)
+ GF_PUT_BYTE (NEW_ROW_0 + indent);
+ else
+ {
+ /* Too large for a new_row command; have to skip and then paint. */
+ GF_PUT_BYTE (SKIP0);
+ put_paint (indent);
+ }
+}
+
+
+/* Output a raw character. */
+
+void
+gf_put_raw_char (raw_char_type raw_char)
+{
+ one_byte charcode = GF_CHARCODE (raw_char);
+
+ start_put_char (charcode, GF_H_ESCAPEMENT (raw_char),
+ GF_TFM_WIDTH (raw_char), GF_CHAR_BB (raw_char));
+ put_n_bytes (RAW_CHAR_USED (raw_char), RAW_CHAR_BYTES (raw_char),
+ gf_output_file, gf_output_filename);
+}
diff --git a/imageto/ChangeLog b/imageto/ChangeLog
new file mode 100644
index 0000000..7870509
--- /dev/null
+++ b/imageto/ChangeLog
@@ -0,0 +1,1113 @@
+Mon Apr 8 09:25:30 1996 Kathy Hargreaves <letters@cs.umb.edu>
+
+ * out-chars.c: doc fix.
+
+Sat Dec 9 07:21:29 1995 Kathy Hargreaves <karl@cs.umb.edu>
+
+ * out-chars.c: (do_image_line): doc fix.
+
+Wed Dec 6 08:28:15 1995 Kathy Hargreaves <karl@cs.umb.edu>
+
+ * out-chars.c: (output_chars): doc fix.
+
+Tue Dec 5 09:40:23 1995 Kathy Hargreaves <karl@cs.umb.edu>
+
+ * out-chars.c: doc fix.
+
+Mon Dec 4 07:40:24 1995 Kathy Hargreaves <karl@cs.umb.edu>
+
+ * main.c (USAGE): doc fix.
+
+ * out-chars.c: doc fix. Changed image_bitmap to image_line_bitmap.
+ (do_image_line): Changed original_box_count to previous_box_count.
+
+Sun Dec 3 09:05:05 1995 Kathy Hargreaves <karl@cs.umb.edu>
+
+ * out-chars.c: (do_image_line): doc fix.
+
+Thu Nov 30 09:03:47 1995 Kathy Hargreaves <karl@cs.umb.edu>
+
+ * out-chars.c: (output_chars): doc fix.
+
+Tue Nov 28 09:47:19 1995 Kathy Hargreaves <karl@cs.umb.edu>
+
+ * out-chars.c: (output_chars): reconsider the current bounding box
+ if the current character is ignored.
+
+Thu Nov 23 08:36:07 1995 Kathy Hargreaves <karl@cs.umb.edu>
+
+ * out-chars.c: (bitmap_to_gf_char): call kpse_find_tfm instead of
+ find_tfm_filename.
+
+Thu Nov 16 09:01:31 1995 Kathy Hargreaves <karl@cs.umb.edu>
+
+ * out-chars.c: (bitmap_to_gf_char): Remove output_name's suffix
+ before calling find_tfm_filename with it.
+
+ * main.c: (OUTPUT_NAME): Made on-static so could do below.
+
+ * main.h: Added output_name extern declaration.
+
+ * out-chars.c: (bitmap_to_gf_char): Call kpse_find_tfm with
+ find_tfm_filename(output_name) instead of something built with
+ input_name, so that will have the design size in the name.
+
+Tue Nov 14 07:28:21 1995 Kathy Hargreaves <karl@cs.umb.edu>
+
+ * ifi.c: (read_ifi_file): increment n after setting the charcode,
+ not before, so first character will have charcode 0.
+
+Sat Oct 14 14:54:27 1995 Kathy Hargreaves <karl@cs.umb.edu>
+
+ * out-chars.c: (bitmap_to_gf_char): Also have to call
+ remove_suffix on input name passed to kpse_find_tfm.
+
+Thu Oct 12 10:44:23 1995 Karl Berry <karl@cs.umb.edu>
+
+ * out-chars.c (bitmap_to_gf_char): Have to call basename on the
+ input name passed to kpse_find_tfm.
+
+Sun Aug 13 18:01:11 1995 Karl Berry <karl@cs.umb.edu>
+
+ * main.c: Call kpse_set_progname.
+
+Sun May 15 11:32:54 1994 Karl Berry (karl@cs.umb.edu)
+
+ * out-chars.c (output_chars): Change `x' to `<ignored>'.
+
+Fri May 13 15:27:29 1994 Karl Berry (karl@cs.umb.edu)
+
+ * out-chars.c (bitmap_to_gf_char): Call kpse_find_tfm, now that it
+ exists.
+
+Sun Aug 22 13:32:49 1993 Karl Berry (karl@cs.umb.edu)
+
+ * out-epsf.c (PIXELS_TO_BP): No longer needed.
+
+Sat Aug 7 13:44:10 1993 Karl Berry (karl@cs.umb.edu)
+
+ * input-img.c (img_get_header): Allow grayscale images.
+
+ * *.h: types.h now in kpathsea.
+
+Tue Jul 27 09:04:12 1993 Karl Berry (karl@cs.umb.edu)
+
+ * GNUmakefile (libraries): Add tfm.
+
+Sun Jul 25 19:20:04 1993 Karl Berry (karl@cs.umb.edu)
+
+ * out-chars.c (bitmap_to_gf_char): Get TFM width from existing TFM
+ file, if we can find one. Convert for use with kpathsea.
+
+Thu May 20 17:11:25 1993 Karl Berry (karl@cs.umb.edu)
+
+ * ifi.c: Doc fix.
+
+Mon Nov 9 09:46:32 1992 Karl Berry (karl@cs.umb.edu)
+
+ * image-header.h: Doc fix.
+
+Tue Oct 27 13:02:04 1992 Karl Berry (karl@cs.umb.edu)
+
+ * Version 0.6.
+
+Sat Oct 24 05:13:02 1992 Karl Berry (karl@cs.umb.edu)
+
+ * ifi.c (read_ifi_file): Just do successive character codes if we
+ don't have an encoding file.
+ * main.c (USAGE): Change doc.
+
+Fri Oct 23 10:43:46 1992 Karl Berry (karl@cs.umb.edu)
+
+ * out-chars.c (output_chars): Free the bounding box list we construct.
+
+ * out-chars.c (output_chars): If the IFI struct says no bounding
+ boxes, don't read any of the bitmap, and reconsider the current bb.
+
+Tue Oct 20 17:17:26 1992 Karl Berry (karl@cs.umb.edu)
+
+ * GNUmakefile (install): Make the second arg a file, not a directory.
+
+Fri Oct 16 15:40:53 1992 Karl Berry (karl@cs.umb.edu)
+
+ * out-epsf.c: Doc fix.
+
+Mon Oct 5 09:31:30 1992 Karl Berry (karl@cs.umb.edu)
+
+ * main.c (read_command_line): Make -print-clean-info imply -verbose.
+ (main): Remove now-redundant test for `print_clean_info'.
+
+ * out-chars.c (write_image_chars): Only report "+" if we have to
+ keep reading vertically, not horizontally.
+ (do_image_line): Remove the report from here.
+
+Sun Oct 4 08:59:55 1992 Karl Berry (karl@cs.umb.edu)
+
+ * out-chars.c (write_image_chars): Don't keep adding to
+ `row_height' for appended image rows, just assign.
+
+ * main.c (main): Test for zero resolution here.
+ (set_input_format): Not here.
+
+ * out-chars.c (clean_threshold): Remove.
+ * out-chars.h: Likewise.
+ * main.c (USAGE, read_command_line): And here.
+
+ * out-chars.c (bb_equal_p): New fn.
+
+ * out-chars.c (offset_bb_list): Function moved here from bb-outline.c.
+
+ * out-chars.c (clean_bitmap): Rewrite to take a list of known
+ boxes, and remove those that aren't in the list.
+ (output_chars): Only call `clean_bitmap' once, after we've
+ combined everything.
+ (image_to_bitmap_bbs): New fn.
+
+Sat Oct 3 13:54:39 1992 Karl Berry (karl@cs.umb.edu)
+
+ * out-chars.c (write_image_chars): Don't abort if the image ends
+ prematurely, just give a warning and return.
+
+ * out-chars.c (OUTPUT_CHAR_P): New macro.
+ (output_chars): Use it, instead of repeating the same expr several
+ times.
+
+Fri Oct 2 16:14:03 1992 Karl Berry (karl@cs.umb.edu)
+
+ * out-chars.[ch]: New files constructed from main.[ch].
+ * main.c: Include out-chars.h.
+
+ * extract.c (REPORT_SCANLINE): use REPORT.
+
+ * main.c (-info-filename): remove this option.
+
+ * {epsf,strips}.[ch]: Rename to out-*.
+ * GNUmakefile (c_and_h): Likewise.
+
+ * ifi.[ch]: New files constructed from image-char.[ch] and main.c.
+ * main.c: include ifi.h.
+ (extract_chars): Change call to read_ifi_file.
+ * GNUmakefile (c_and_h): add `ifi', remove `image-char'.
+
+Mon Sep 28 11:11:59 1992 Karl Berry (karl@cs.umb.edu)
+
+ * main.c: change `fprintf (stderr's to use REPORT*.
+
+ * main.c (clean_bitmap): print the size of the bounding box being
+ cleaned, not that of the enclosing character. (halvers@sol.crd.ge.com)
+
+Tue Sep 22 13:01:54 1992 Karl Berry (karl@cs.umb.edu)
+
+ * main.c (read_ifi_file): call make_suffix to make the default IFI
+ filename, instead of appending to the root.
+ (input_rootname): remove.
+ (main): don't assign to input_rootname; just set output_name to
+ the fn call.
+ (input_name): new static.
+
+ * main.c (clean_bitmap): if clean_threshold is 1.0, do nothing;
+ else only clean if the gray value is > threshold, not >=.
+
+ * main.c: make diagnostic messages consistent.
+
+ * main.c (do_image_line): set `bb_offset' to just the width
+ of the previous bb, since we're already incorporating the
+ interbb whitespace in the second bb.
+
+Mon Sep 21 10:32:07 1992 Karl Berry (karl@cs.umb.edu)
+
+ * main.c (read_command_line): new option -ifi-file, a synonym for
+ -info-file.
+ (USAGE): document it.
+
+ * main.c (set_input_format): don't call strcmp on NULL if the
+ input filename lacks an extension.
+
+Thu Sep 3 09:30:54 1992 Karl Berry (karl@hayley)
+
+ * Version 0.5.
+
+Sat Aug 29 16:14:35 1992 Karl Berry (karl@hayley)
+
+ * GNUmakefile (dist, install): new targets to deal with strips.tex.
+
+Fri Aug 21 16:14:10 1992 Karl Berry (karl@hayley)
+
+ * main.c (read_ifi_file): improve warning message.
+
+Mon Jul 13 16:58:44 1992 Karl Berry (karl@hayley)
+
+ * epsf.c (write_epsf): use `width_used' for the width of image buffer.
+
+Thu Jul 2 14:06:09 1992 Kathy Hargreaves (kathy@hayley)
+
+ * main.c (BB_TO_CARTESIAN): subtract IMAGE_CHAR_BASELINE_ADJUST(.)
+ instead of adding it.
+
+ * main.c (bitmap_to_gf_char): removed `char_baseline'.
+
+Sun Jun 28 11:54:23 1992 Kathy Hargreaves (kathy@hayley)
+
+ * main.c (bitmap_to_gf_char): added cartesian_bb; fill it using
+ BB_TO_CARTESIAN and assign to the GF char. Print out the GF
+ char's rows for baseline adjustment.
+
+Fri Jun 26 13:45:20 1992 Kathy Hargreaves (kathy@hayley)
+
+ * main.c (read_ifi_file): changed warning to include encoding name.
+
+Mon Jun 15 07:37:29 1992 Karl Berry (karl@hayley)
+
+ * extract.c (get_image_row): allocate more than one row at a time.
+
+ * extract.c (get_image_row): don't realloc if we're keeping
+ leading white rows.
+
+ * main.c (extract_chars): change `nchars_per_line' to one if
+ `print_guidelines' is true.
+
+ * main.c (read_ifi_file): if the character name is undefined in
+ the encoding, omit it from the output.
+
+ * main.c (get_image_info): rename to `read_ifi_file'.
+
+ * main.c (get_image_info): make `.notdef' mean omission, instead
+ of `-1'.
+
+ * image-char.h (image_char_type): new field `charname'.
+ (IMAGE_CHARNAME): new accessor macro.
+ * main.c (bitmap_to_gf_char): print the character name, instead of
+ relying on %c.
+ (get_image_info): set it.
+
+ * main.h (print_scanline): new routine.
+ * main.c (print_scanline): define it.
+ * input-img.c (img_get_scanline): print the scanlines if
+ `trace_scanlines' is set.
+ * input-pbm.c (pbm_get_scanline): call it, instead of doing the
+ printing inline.
+
+Sat Jun 13 12:04:00 1992 Kathy Hargreaves (kathy@hayley)
+
+ * main.c (get_image_info): renamed charcode_str to charname_str.
+ Removed comment-handling stuff.
+
+ * main.c (encoding_name, encoding_info): added.
+ (get_image_info): added `encoding_info'; call `encoding_number'
+ on `charcode_str' instead of `xparse_charcode'.
+ (USAGE, read_command_line): added -encoding option.
+
+Tue Jun 9 13:45:42 1992 Kathy Hargreaves (kathy@hayley)
+
+ * main.c (output_chars): deleted clean_all_bbs.
+ (clean_bitmap): deleted CLEAN_ALL_BBS; call find_outline_bbs
+ with false instead of this. Updated doc. Now only check
+ bounding boxes which don't enclose the whole character, instead
+ of those which also are on the edge, unless clean_all_bbs is
+ true, whereupon check those also.
+ (get_image_info): don't handle CLEAN_ALL_BBS_FLAG anymore.
+
+ * image-char.h (image_char_type): deleted clean_inner_bbs field.
+ (IMAGE_CHAR_CLEAN_ALL_BBS, CLEAN_ALL_BBS_FLAG): deleted
+
+Mon Jun 8 12:33:45 1992 Kathy Hargreaves (kathy@hayley)
+
+ * input-pbm.c (pbm_get_scanline): increment scanline_count after
+ printing it.
+
+ * main.c (BB_TO_CARTESIAN): added.
+ (bitmap_to_gf_char): when print-guidelines is true, print the
+ bounding box's max and min (in that order) row in Cartesian
+ coordinates, not the GF char's min and max row.
+
+Fri Jun 5 21:18:12 1992 Kathy Hargreaves (kathy@hayley)
+
+ * main.c (output_chars): don't clean bounding boxes unless
+ outputting the character.
+
+ * main.c (get_image_info): set clean_all_bbs field of `c' false if
+ there's not a CLEAN_ALL_BBS_FLAG at the end of the character string.
+
+Fri Jun 5 09:19:48 1992 Karl Berry (karl@hayley)
+
+ * main.c (main): `return 0' instead of `exit (0)'. (From Paul Eggert)
+
+Tue Jun 2 18:03:52 1992 Kathy Hargreaves (kathy@hayley)
+
+ * main.c (output_chars): call clean_bitmap with 0's for LEFT_MARK
+ and RIGHT_MARK if clean_all_bbs is true.
+
+Mon Jun 1 11:19:46 1992 Kathy Hargreaves (kathy@hayley)
+
+ * main.c (output_chars): added clean_all_bbs to send to clean_bitmap.
+
+ * main.c (clean_bitmap): clean only those boxes which are on the
+ edges only if CLEAN_ALL_BBS is false; otherwise, clean them all.
+
+ * main.c (get_image_info): if there's a CLEAN_ALL_BBS_FLAG appended
+ to the character code, then set the clean_all_bbs field of c.
+
+ * image-char.h (image_char_type): added clean_all_bbs field.
+
+Sun May 31 13:10:48 1992 Karl Berry (karl@hayley)
+
+ * main.c: rename `design-size' option to `designsize'.
+
+ * epsf.c (write_epsf): change the EPS output to not write one
+ gigantic image.
+
+Sat May 30 11:58:02 1992 Kathy Hargreaves (kathy@hayley)
+
+ * main.c (USAGE -clean-threshold): doc fix.
+
+Fri May 29 11:34:52 1992 Karl Berry (karl@hayley)
+
+ * main.c (main): declare to return an int.
+
+Tue May 26 07:56:34 1992 Karl Berry (karl@hayley)
+
+ * main.c: simplify comments on IFI file format, since now the real
+ documentation describes it.
+
+Mon May 25 11:45:49 1992 Karl Berry (karl@hayley)
+
+ * main.c (clean_bitmap): wasn't printing clean info for bbs that
+ weren't cleared.
+
+ * main.c (read_command_line): make -print-guidelines => -verbose.
+ (USAGE): document this.
+ (main): don't bother to test `print_guidelines' anymore when we
+ doing verbose things.
+
+ * main.c (main): use `output_name', not `gf_name' (which we no
+ longer need).
+
+ * main.c (set_{pbm,img}_input_format): set `input_extension' to
+ just `pbm' or `img', omitting the leading `.'.
+
+Sun May 24 18:03:09 1992 Karl Berry (karl@hayley)
+
+ * main.c (read_command_line): in -input-format, complain if they
+ give an unrecognized input format.
+ (main): call set_input_format.
+ (set_input_format): new routine to intuit the input format from
+ the input filename if they didn't specify.
+ (set_{pbm,img}_input_format): new routines.
+
+Thu May 21 10:59:23 1992 Karl Berry (karl@hayley)
+
+ * GNUmakefile, version.c, main.c: change `imagetofont' to `imageto'.
+
+ * strips.c (write_chars_as_strips): don't bother to initialize
+ `gf_row'.
+
+Wed May 20 07:34:38 1992 Karl Berry (karl@hayley)
+
+ * strips.h: include image-header.h, not input-img.h.
+
+ * main.c (extract_chars): new fn (to shorten main).
+ (main): call it.
+
+ * main.c (do_epsf): new global.
+ (read_command_line): new option `-epsf'.
+ (main): call `write_epsf' if set.
+ * GNUmakefile (c_and_h): add epsf.
+ * epsf.[ch]: new files.
+
+Mon May 4 09:27:55 1992 Karl Berry (karl@hayley)
+
+ * main.c (main): don't lose the `<dpi>gf' from the output name.
+
+ * strips.c (write_chars_as_strips): add one to `lines_per_char' to
+ compensate for roundoff error.
+
+ * main.c (verbose): remove this, as it's defined in report.c.
+
+Sun May 3 19:31:29 1992 Karl Berry (karl@hayley)
+
+ * strips.c (write_chars_as_strips): use REPORT for the progress
+ report.
+
+Tue Apr 21 07:44:36 1992 Karl Berry (karl@hayley)
+
+ * extract.c (append_next_image_row): use XTALLOC1.
+
+Mon Apr 20 12:53:43 1992 Karl Berry (karl@hayley)
+
+ * main.c (main): simplify logic again for figuring out the output
+ filename; remove any suffix from the input filename before it is
+ used to make the IFI or output filename.
+ (get_image_info): the variable is named `input_rootname' now, not
+ `input_basename'.
+
+Wed Apr 15 15:26:53 1992 Karl Berry (karl@hayley)
+
+ * main.c (main): `make_output_filename' is now `extend_filename'.
+
+Wed Apr 8 12:28:59 1992 Karl Berry (karl@hayley)
+
+ * main.c (do_image_line): don't increment the max_col transition
+ in the horizontally concatenated block, either.
+
+ * main.c: make most of the globals static.
+ * main.h: remove declarations for unneeded globals.
+
+ * main.c (debug): add this.
+
+Mon Apr 6 16:43:39 1992 Karl Berry (karl@hayley)
+
+ * extract.c (get_image_row): count white rows in image size; free
+ the scanline storage after we've copied it.
+
+Sun Apr 5 11:46:33 1992 Karl Berry (karl@hayley)
+
+ * main.c (do_image_line): don't increment the transition which we
+ use for the maximum column.
+
+Sat Apr 4 12:57:15 1992 Karl Berry (karl@hayley)
+
+ * main.c (do_image_line): move test for enough boxes to above
+ dealing with the current bitmap, so garbage at the end doesn't
+ mess us up. (from wales@cs.ucla.edu)
+
+Wed Apr 1 16:17:18 1992 Karl Berry (karl at hayley)
+
+ * main.c (main): simplify the output name creation code.
+
+ * main.c (font_name_extension): rename to `input_extension', and
+ don't bother to initialize it.
+
+Sat Mar 28 07:48:43 1992 Karl Berry (karl at hayley)
+
+ * Version 0.4.
+
+ * Change copyright years to 1992 only.
+
+Mon Mar 9 16:46:10 1992 Kathy Hargreaves (kathy at hayley)
+
+ * main.c (main): move setting of dpi to above (and out of)
+ do_strips test.
+
+ * main.c (main): set output_name_suffix with static strings
+ and xmalloc dpi and design_size_str.
+
+ * main.c (main): if output_name has no suffix, append either
+ output_name_suffix or design_size to its stem before appending
+ a suffix.
+
+Sat Mar 7 09:55:42 1992 Karl Berry (karl at hayley)
+
+ * GNUmakefile (libraries): define again.
+ (files, headers, sources): replace with `c_and_h', etc.
+
+Thu Mar 5 06:47:26 1992 Karl Berry (karl at hayley)
+
+ * main.c (output_filename): rename to `output_name', and remove
+ the other `output_name' declaration.
+
+Wed Mar 4 17:21:32 1992 Kathy Hargreaves (kathy at hayley)
+
+ * main.c (main) changed `output_basename' to `output_name'.
+ Deleted add_suffix and add_design_size.
+ Added dpi, design_size_str, and output_name_suffix.
+ Use make_output_filename to check if output name has a suffix.
+ If output_name not given and not doing strips, set design_size_str.
+ If doing strips, set output_name_suffix to "sp".
+ Always set dpi.
+
+Mon Mar 2 12:15:52 1992 Karl Berry (karl at hayley)
+
+ * main.c (main): decrease nchars_per_line to 11.
+
+Sun Mar 1 13:03:23 1992 Karl Berry (karl at hayley)
+
+ * GNUmakefile (files): remove bb-outline.
+
+ * GNUmakefile (need_pbm_library): define.
+ (sources): remove the PBM stuff.
+
+Fri Feb 28 07:53:09 1992 Karl Berry (karl at hayley)
+
+ * extract.c (image_row_transitions): new routine.
+ (some_black_to_all_white_row): call it after getting the image row.
+ (append_next_image_row): call it after appending.
+ (get_image_row): do not compute the transitions here.
+
+ * main.c (bitmap_to_gf_char): the GF min_row is the depth, the GF
+ max_row is the height; we had it the other way around. Also,
+ `row_baseline' is one-origin, but char rows are 0-origin.
+
+Tue Feb 25 14:40:54 1992 Karl Berry (karl at hayley)
+
+ * main.c (main): decrease number of chars reported without
+ guidelines to 12.
+
+ * input-pbm.c (pbm_get_scanline): declare the test character for
+ EOF as int, not char. Also, print the scanlines if
+ trace_scanlines is set.
+ * main.c (trace_scanlines): new global.
+ (read_command_line): new option.
+
+ * bitmap2.c (bitmap_vconcat): put one blank row between the
+ bitmaps, to compensate for what some_black... removed.
+
+ * extract.c (get_image_row): don't keep leading white rows if
+ there weren't any; always append scanline, even if there were.
+
+Fri Jan 31 17:08:38 1992 Karl Berry (karl at hayley)
+
+ * main.c (read_command_line): declare `option_index' (for new
+ getopt).
+
+Tue Jan 21 11:47:26 1992 Kathy Hargreaves (kathy at hayley)
+
+ * main.c (main): wasn't putting the suffix on the gf name when
+ gave an output filename without a suffix because was finding the
+ dot in the pathname `../fonts'.
+
+ * main.c (bitmap_to_gf_char): were switching the minimum and
+ maximum rows when assigning to the gf char.
+
+ * main.c (main): malloc gf_name more precisely.
+
+ * main.c (bitmap_to_gf_char): fixed calculation of gf char's rows.
+ (main): changed how build the gf output filename: if the user
+ specifies an output file, don't ever add on a design size and don't
+ add a suffix if there's one already.
+
+ * main.c (bitmap_to_gf_char): now print gf character's (baseline-
+ adjusted) row instead of the bounding box's (unadjusted) ones.
+
+Mon Jan 20 14:46:16 1992 Kathy Hargreaves (kathy at hayley)
+
+ * main.c (main): added variable `output_basename' so user could
+ specify an output file basename.
+ (read_command_line): Added `output-file' option.
+
+Tue Jan 14 13:14:46 1992 Kathy Hargreaves (kathy at hayley)
+
+ * main.c (get_image_info): when call libfile_start with
+ info_filename, specify "ifi" as the (now-default) suffix.
+
+ * main.c [USAGE] (info-file): use <filename>.ifi if <filename>
+ doesn't have a dotted suffix; otherwise use <filename>.
+
+Thu Jan 9 08:29:52 1992 Karl Berry (karl at hayley)
+
+ * main.c (read_command_line): rename `scan_integer_list' to
+ `scan_unsigned_list'.
+
+ * *.c: do not include global.h.
+
+ * *.h: remove #pragma once.
+
+Wed Jan 8 15:28:00 1992 Karl Berry (karl at hayley)
+
+ * update copyright messages.
+
+ * change `allocate to `xmalloc', `reallocate' to `xrealloc', and
+ `string_copy' to `strdup'.
+
+Tue Jul 30 13:18:48 1991 Karl Berry (karl at ra.cs.umb.edu)
+
+ * Version 0.3.
+
+Fri Jul 26 07:02:28 1991 Karl Berry (karl at hayley)
+
+ * main.c (get_image_info): read the left and side bearings from
+ the IFI file, if present.
+ (bitmap_to_gf_char): use these numbers.
+ * image-char.h (image_char_type): new members `lsb' and `rsb'.
+ (IMAGE_CHAR_{L,R}SB): new accessor macros.
+
+Wed Jul 24 06:07:11 1991 Karl Berry (karl at hayley)
+
+ * bitmap2.c (bitmap_concat): the height of the result is the
+ height of one, not twice that.
+
+ * main.c (do_image_line): rename `concat_bitmaps' to
+ `bitmap_concat'.
+ * GNUmakefile (files): new file `bitmap2'.
+
+ * main.c (do_image_line): return a boolean saying if we need
+ another image row.
+ (main): if `do_image_line' fails, read more of the image.
+ * extract.h (append_next_image_row): declare new routine.
+ * extract.c (append_next_image_row): define it.
+ (get_image_row): new routine.
+ (some_black_to_all_white_row): call `get_image_row'.
+
+ * make-gsfont.ps (octal-value): prepend 0 to the character code.
+
+ * extract.c (some_black_to_all_white_row): use xcalloc to initialize
+ `or_of_all', not allocate. We need it to be all zeroes
+ initially.
+
+ * main.c, version.c: change `imgtogf' to `imagetofont'.
+
+ * make-gsfont.ps: remove all the if-verbose's.
+
+ * main.c: doc fix.
+
+Mon Jul 22 07:54:42 1991 Karl Berry (karl at hayley)
+
+ * make-gsfont.ps (output-encoding): set /output-encoding to the
+ dictionary.
+
+ * main.c: output ``imagetofont'' as our name in the GF file header,
+ instead of ``IMGtoGF''.
+
+ * make-gsfont.ps (print-char-dimensions-if-verbose): lose the
+ `-if-verbose'.
+
+ * make-gsfont.ps (octal-value): `get' the character name, don't
+ `load' it, so we find it in the right dictionary.
+
+ * libpbm1.c: declare parms, external functions to avoid warnings.
+
+Sat Jun 15 09:50:46 1991 Karl Berry (karl at hayley)
+
+ * input-*.c: change `checked_' to `x'.
+
+Thu Jun 6 07:29:06 1991 Karl Berry (karl at hayley)
+
+ * All files: change to version 2 of the GPL.
+
+Sat Jun 1 15:18:11 1991 Kathy Hargreaves (kathy at hayley)
+
+ * main.c (get_image_info): Now build an info filename if the
+ variable info_filename *is* NULL, not when it's not.
+ (USAGE): Deleted that resolution was set only for pbm input.
+ Stated that input-format is required and shortened comment.
+
+Fri May 31 14:30:01 1991 Kathy Hargreaves (kathy at hayley)
+
+ * imgtogf: Moved directory to `imagetofont'.
+
+ * GNUmakefile: Changed program name from `imgtogf' to `imagetofont'.
+
+ * main.c (get_image_info): Make default image info file be
+ <fontname>.ifi instead of imginf.<fontname>.
+
+ * main.[hc], input-*.[hc]: *_get_header now don't return a
+ header but rather modify the global header in main.c. Changed
+ all references to `[img, pbm]_header->' to `image_header.'.
+
+ * main.c, image-char.[hc]: Replaced all instances of `img_char'
+ with `image_char'.
+
+ * image-char.[hc]: Moved from img-char.[hc].
+
+ * main.h (image_header): Made this visible to the outside.
+
+ * input-[pbm, img].c ([pbm, img]_get_header): Set h to
+ image_header in main.c. #include main.h.
+
+ * main.c (read_command_line): Cast the assignment to
+ image_header.hres to type two_bytes.
+
+ * image-header.h, input-*.[hc], main.[hc]: Changed `img-header.h'
+ to `image-header.h'.
+
+ * main.c: Replaced all instances of `img_header*' with
+ `image_header*'. Moved `img_' and `pbm_' to the front of the
+ function names.
+
+ * img-header.h: Moved to image_header.h and replaced all
+ instances of `img_header*' with `image_header*'.
+
+ * input-img.[hc] (*_img_*): Moved `img_' to the front of the
+ variable names. Replaced instances of `img_header_type' with
+ `image_header_type'.
+
+ * input-pbm.[hc] (*_pbm_*): Moved `pbm_' to the front of the
+ variable names.
+
+ * extract.c, strips.c: (ptr_get_scanline): Removed `ptr_' from in
+ front of this function's name and replaced it with `image'.
+ Replaced instances of `img_header*' with `image_header*', if any.
+
+ * main.h (ptr_open_input_file, ptr_close_input_file, ptr_get_header,
+ ptr_get_scanline): Removed `ptr_' from the front of all these
+ names and replaced it with `image'. Replaced `img_header_type'
+ with `image_header_type'.
+
+ * main.c (ptr_open_input_file, ptr_close_input_file, ptr_get_header,
+ ptr_get_scanline): Moved and set all to NULL.
+ Removed `ptr_' from the front of all these names and replaced it
+ with `image'.
+ (read_command_line): Remove "img-input-format" from option
+ structure.
+ Removed variable need_resolutions, as don't need it.
+ Force them to specify the input format on the command line
+ rather than having a default.
+
+Wed May 29 16:19:57 1991 Kathy Hargreaves (kathy at hayley)
+
+ * input-pbm.c (line_in_bytes): Deleted this global variable, as
+ don't need it. (pbm_readpbmrow reads right into line_in_bits in
+ get_pbm_scanline.)
+
+ * pbm.h: Took out #include for types.h.
+
+ * input-pbm.c (get_pbm_scanline): Check if at EOF before calling
+ pbm_readpbmrow.
+
+ * libpbm2.c (pbm_readpbmrow): Restored to original; can test if at
+ EOF in the wrapper get_pbm_scanline.
+ Took out #include for types.h.
+
+ * input-pbm.c (get_pbm_scanline): Hooked up to libpbm2.c routine.
+
+ * main.c (read_command_line): Combined some options and changed
+ their names and their input.
+ Make input-format take an argument.
+
+Mon May 27 14:52:45 1991 Kathy Hargreaves (kathy at hayley)
+
+ * main.c (read_commandline): If both resolutions are missing and
+ are required on the commandline, print that they both are, not
+ just that the horizontal one is.
+
+ * bb-outline.c (is_outline_edge): Changed VALID_LOCATION to
+ BITMAP_VALID_PIXEL.
+
+ * pbmplus.h: Commented out malloc, etc. declarations.
+
+ * libpbm2.c (pbmreadpbmrow): Make it return a boolean instead of a
+ void, so will fit into our code.
+ Make it return false instead of an error message.
+
+ * pbm.h (top): pbmplus.h is in the current directory, so take out
+ the `../' before it in the #include.
+ (pbmreadpbmrow): Make it return a boolean instead of a void, so
+ will fit into our code.
+
+ * extract.c (top): Now #include input-pbm.h.
+ (some_black_to_all_white_row): Changed all instances of
+ get_img_scanline to get_scanline.
+
+ * input-img.c (top): Now #include img-header.h.
+ (get_img_header): Got rid of variable format, as now put that in
+ the header.
+
+ * main.c: (open_input_file, close_input_file, get_header,
+ get_scanline): Declared these pointers to functions so could set
+ them to a set of routines belonging to the type of input we're
+ using. Set them to .pbm input format routines as a default.
+ (font_name_extension): Added this static variable so could set
+ it when get read the input format on the command line. Set to
+ `.pbm' by default.
+ (main): Initialize img_header to all zeros so will know if the
+ user set them using the command line.
+ Changed call to open_img_input_file to open_input_file and
+ concat font_name_extension instead of ".img" for the argument.
+ Changed some comments.
+ Changed the call to get_img_header to get_header.
+ Changed the call to close_img_input_file to close_input_file.
+ (USAGE): Added horz-resolution, img-input-format,
+ pbm-input-format, and vert-resolution.
+ (read_command_line): Added boolean variable need_resolutions to
+ keep track of whether or not the user needs to input the
+ horizontal and vertical resolutions on the command line.
+ Added horz-resolution, img-input-format, pbm-input-format, and
+ vert-resolution to the option variable long_options.
+ If the argument is horz-resolution or vert-resolution, then set
+ the appropriate field in the header.
+ If the argument if img-input-format or pbm-input-format, the set
+ the input function pointers in main to the appropriate set of
+ functions that belong to the input format. If the argument is
+ the former, then set needs_resolution to false; if it's the latter,
+ set it to true.
+ If the user wants .pbm input format, then check that the header's
+ resolutions are set; if not, issue an error message and exit.
+
+ * main.h (open_input_file, close_input_file, get_header, get_scanline):
+ Added these function pointer declarations so extract.c and strips.c
+ could use them.
+
+ * strips.c (top): Now #include input-pbm.h.
+ (write_chars_as_strips): Changed the call to get_img_scanline to
+ a call to get_scanline.
+
+Sat Apr 13 17:13:51 1991 Karl Berry (karl at hayley)
+
+ * main.c (get_image_info): use the libfile routines to read the
+ image info files.
+
+ * main.c, input-img.c: new includes from the library
+ rearrangements.
+
+Mon Feb 25 16:32:45 1991 Karl Berry (karl at hayley)
+
+ * main.c, strips.c: use `gf_...' instead of `..._gf_...'.
+
+Sun Feb 17 09:39:20 1991 Karl Berry (karl at hayley)
+
+ * *.c: include config.h.
+
+Tue Jan 22 15:43:19 1991 Karl Berry (karl at hayley)
+
+ * extract.[ch] (extract_subimage): move to kbase.
+
+Thu Jan 17 10:32:09 1991 Karl Berry (karl at hayley)
+
+ * main.c (main): don't put the day of the week in the font comment.
+
+Tue Oct 9 09:07:02 1990 Karl Berry (karl at hayley)
+
+ * main.c (scan_baseline_list): move to kbase.
+ (baseline_list): make a vector of ints, not unsigneds.
+ (main): test for the end of the baseline list being -1, not 0.
+
+Mon Oct 8 16:37:07 1990 Karl Berry (karl at hayley)
+
+ * main.c: #include cmdline.h.
+ (read_command_line): call FINISH_COMMAND_LINE.
+
+Sun Sep 30 09:15:25 1990 Karl Berry (karl at hayley)
+
+ * main.c (do_image_line): don't give a report when we read part of
+ the line, after all.
+
+Fri Sep 28 13:47:15 1990 Karl Berry (karl at hayley)
+
+ * main.c (scan_integer_list): use strtok, instead of doing the
+ work ourselves.
+
+Sat Sep 22 06:16:49 1990 Karl Berry (karl at hayley)
+
+ * main.c (output_chars): don't increment `current_char' if we've
+ already seen the box.
+
+Fri Sep 21 08:40:49 1990 Karl Berry (karl at hayley)
+
+ * img-char.h (img_char_type): new element, `alternating'.
+ (IMG_CHAR_BB_ALTERNATING): macro to access it.
+ * main.c (get_image_info): if the bb count is negative, set
+ `alternating' (and make it positive).
+ (output_chars): handle the bounding boxes alternating.
+
+ * main.c (do_image_line): give a progress report when we read part
+ of the line.
+
+ * main.c (read_command_line): return NULL at the end; the POSIX
+ include files don't declare `exit' as volatile, more's the pity.
+ * bb-output.c (is_outline_edge): return false at the end, for the
+ same reason.
+
+Sun Sep 16 11:13:43 1990 Karl Berry (karl at hayley)
+
+ * main.c: include "getopt.h" instead of <getopt.h>.
+
+ * main.c (read_command_line): change call of PARSE_CHAR_CODE to
+ xparse_char_code.
+
+ * main.c (main): make the default info filename `imginf.<name>',
+ not `imginfo.<name>'.
+
+Sat Sep 8 10:06:19 1990 Karl Berry (karl at hayley)
+
+ * main.c (read_command_line): remove any suffix on the font name
+ before returning it.
+
+ * main.c (read_command_line): use GET_RANGE.
+
+ * main.c (get_image_info): use PARSE_CHAR_CODE to get the
+ character code from the file.
+
+Thu Sep 6 06:16:29 1990 Karl Berry (karl at hayley)
+
+ * main.c (scan_integer_list): doc fix.
+
+Wed Sep 5 06:19:53 1990 Karl Berry (karl at hayley)
+
+ * main.c (USAGE): doc fix in -range.
+
+Tue Sep 4 09:33:49 1990 Karl Berry (karl at hayley)
+
+ * main.c (do_image_line): pass the current character to
+ output_chars, not the current box count.
+
+ * extract.c (REPORT_SCANLINE): output to stderr instead of stdout.
+
+ * main.c (get_image_info): always assign to the character code and
+ omit fields.
+
+Mon Sep 3 16:57:02 1990 Karl Berry (karl at hayley)
+
+ * main.c (get_image_info): use NULL in subsequent calls to strtok.
+
+ * main.c (get_encoding): replace with get_image_info; change
+ callers.
+ * img-char.[ch]: new files to support the data structure.
+
+Thu Aug 16 08:00:19 1990 Karl Berry (karl at hayley)
+
+ * bb-outline.c (free_bounding_box_list): check if the list is
+ allocated before freeing it.
+
+ * main.c (do_image_line): only say that we've read too many boxes
+ once.
+
+Wed Aug 8 08:06:53 1990 Karl Berry (karl at hayley)
+
+ * main.c (read_command_line): change `encoding-file' to
+ `info-file'.
+
+Tue Aug 7 08:53:13 1990 Karl Berry (karl at hayley)
+
+ * main.c (main): use the basename of the image filename to
+ construct the output name, instead of the full name.
+
+ * main.c (USAGE): explain `-baselines' better.
+
+Thu Jul 26 06:54:56 1990 Karl Berry (karl at hayley)
+
+ * extract.c (find_transitions): move to kbase.
+
+Tue Jul 24 13:09:38 1990 Karl Berry (karl at hayley)
+
+ * main.c: don't include time.h.
+
+Thu Jul 19 15:22:29 1990 Karl Berry (karl at aten)
+
+ * main.c (main): don't dereference baseline_list if it's null.
+
+Mon Jul 16 08:56:41 1990 Karl Berry (karl at hayley)
+
+ * main.c (clean_bitmap): only print the `. ' if we're printing the
+ cleaning info.
+
+Sun Jul 15 08:27:52 1990 Karl Berry (karl at hayley)
+
+ * bb-outline.c (append_bounding_box_list): don't change anything
+ if we're appending a list of length zero.
+
+Fri Jul 13 11:35:15 1990 Karl Berry (karl at hayley)
+
+ * main.c (clean_bitmap): also potentially clean bounding boxes on
+ the bottom edge.
+
+ * main.c (SET_EDGES): make coordinates relative to the bitmap of
+ the character.
+
+ * main.c (clean_bitmap): only test the gray value for bounding
+ boxes that are on the edge.
+
+ * main.c (output_chars): return the number of characters actually
+ output, omitting the ones out of range.
+
+ * main.c (clean_bitmap): print gray values for the bounding boxes
+ if requested.
+ (read_command_line): new option, `print_clean_info'.
+
+Thu Jul 12 06:08:33 1990 Karl Berry (karl at hayley)
+
+ * extract.c (some_black_to_all_white_row): don't output a newline
+ after reading the scanlines.
+
+ * main.h: new file.
+ * extract.c: include it, remove declaration of verbose.
+
+ * strips.[ch]: new files.
+ * main.c (main): cut the image into strips if requested.
+ (read_command_line): new option `strips'.
+
+ * extract.c (find_transitions): new routine.
+ (some_black_to_all_white_row): call it, at the end, with a new
+ variable that is the logical or of all the rows we read.
+ (some_black_to_all_white_column, found_color_in_column): these
+ routines aren't needed any more.
+ * main.c (do_image_line): use the transition vector to set
+ `char_bitmap'.
+
+ * main.c (scan_integer_list): increment length after checking the
+ exit condition.
+
+ * main.c (do_image_line): new routine, consisting of a lot of the
+ main loop.
+
+ * main.c (bitmap_to_gf_char): determine the baseline.
+ (read_command_line): new option `baselines' to set the baselines.
+ (scan_integer_list): new routine.
+
+ * extract.c (found_color_in_column): start halfway down the
+ bitmap.
+
+Wed Jul 11 06:19:51 1990 Karl Berry (karl at hayley)
+
+ * main.c (bitmap_to_gf_char): take another argument, the character
+ code, to consolidate where the GF char is set.
+
+ * main.c (nchars_per_line): new static to say how many characters
+ we can report on per line; different for `print_guidelines' being
+ set and not set.
+
+ * main.c (print_guidelines): new global.
+ (read_command_line): new option to set it.
+ (bitmap_to_gf_char): print the row numbers if it's set.
+
+ * bb-outline.c (find_outline_bbs): take two additional arguments:
+ column numbers between which we don't look.
+ * bb-outline.h (find_outline_bbs): change the declaration.
+ * main.c (main), (clean_bitmap): change the calls.
+
+ * bb-outline.c (append_bounding_box_list): reallocate based on the
+ element size, not the list size.
+
+ * bb-outline.c (set_bounding_box_list_offset): replace by
+ `offset_bounding_box_list'.
+ (append_bb): don't offset the bounding boxes as they come in.
+ * bb-outline.h (set_bounding_box_list_offset): likewise.
+ * main.c (main): change call.
+
+ * main.c (output_chars): set char_code to *next_code at the bottom
+ of the loop, and increment next_code.
+
+Tue Jul 10 06:10:05 1990 Karl Berry (karl at hayley)
+
+ * bb-outline.c (set_bounding_box_list_offset): new routine.
+ (append_bb): move the bounding box to the right by the offset.
+ * bb-outline.h (set_bounding_box_list_offset): declare it.
+
+ * main.c (get_char_code): rename to get_encoding, and read the
+ whole file.
+
+ * bb-outline.h (init_bounding_box_list, append_bounding_box_list):
+ declare new routines.
+ bb-outline.c (same): define them.
+
+Mon Jul 9 08:10:20 1990 Karl Berry (karl at hayley)
+
+ * main.c (main): don't split each line at white columns.
+
+ * extract.c (clean_bitmap): set verbose to false before calling
+ find_outline_bbs.
+
+ * main.c (get_char_code): make sure we actually find a character
+ code.
+
+ * main.c (output_chars): don't extract or clean anything if the
+ character isn't within range.
+
+ * extract.c (REPORT_SCANLINE): report every 100 scanlines.
+
+ * main.c (output_chars): only give the status report if we
+ actually output the character.
+
+Sat Jul 7 10:43:18 1990 Karl Berry (karl at hayley)
+
+ * bb-outline.c (append_bb): changed MAX_ROW, instead of MAX_COL.
+
+ * main.c (clean_bitmap): new routine.
+ (output_gf_chars): call it.
+ * bb-outline.c (find_outline_bbs): take an additional parameter to
+ determine whether to look for inside outlines or not.
+
+ * extract.c (REPORT_SCANLINE): report every 50 scanlines, instead
+ of every 10.
+
+ * bb-outline.c (find_outline_bbs): look for outlines in
+ column-major order, instead of row-major.
+
diff --git a/imageto/GNUmakefile b/imageto/GNUmakefile
new file mode 100644
index 0000000..2fcac49
--- /dev/null
+++ b/imageto/GNUmakefile
@@ -0,0 +1,43 @@
+# Makefile for image conversion program.
+#
+# 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.
+
+program = imageto
+
+c_and_h = bitmap2 extract ifi input-img input-pbm main \
+ out-chars out-epsf out-strips
+h_only = image-header
+c_only = version
+
+libraries = gf pbm tfm
+
+include ../data/defs.make
+include ../data/defsprog.make
+
+check:
+ cd /w/ourfonts/dingbats ; gftopk -v g111236.1200gf
+
+
+dist::
+ ln strips.tex $(distdir)
+
+install::
+ $(INSTALL_DATA) strips.tex $(texinputdir)/strips.tex
+
+include M.depend
+
+
diff --git a/imageto/README b/imageto/README
new file mode 100644
index 0000000..31f228f
--- /dev/null
+++ b/imageto/README
@@ -0,0 +1,46 @@
+This program extracts the characters from a big image to a GF font file.
+Information about the image is given in an ``image font information''
+(IFI) file; that file format is described in the documentation.
+
+Currently the program can read the IMG files output by the Scan7650
+software, which works with the fancy Xerox 9750 scanner. (I think IMG
+output is used by other GEM applications as well.) These images are
+used by the Interleaf desktop publishing program. The image format
+isn't proprietary, though -- it doesn't have any novel features. The
+message below describes the format.
+
+It can also read PBM files.
+
+
+Date: Thu, 5 Jul 90 11:22:55 EDT
+From: rgw@hq.ileaf.com (Bob Watkins x5545)
+To: karl@cs.umb.edu
+
+The image file consists of an OPSHEADER followed by an IMGHEADER, followed
+by raster data. The version field of the OPSHEADER determines which of the
+IMGHEADER structures to use. Most likely this will be 2, but there is a
+chance that it might be 1 -- it depends on how recently the software for
+that scanner was written.
+
+When reading the headers structures, it is a good idea to read them a field
+at a time rather than all at once, since not all compilers use the same
+structure padding conventions.
+
+The resolution numbers are in pixels/inch. Their primary purpose is to
+allow TPS to scale the image to the correct physical dimensions when it is
+pasted into the document. Other than that, they aren't that useful.
+
+The flags field should be zero -- there is a stupid marketing reason why it
+is there at all, but I won't go into that.
+
+The w and h fields are the width and height of the image in pixels; the d
+field is the depth in bits/pixel. The depth is either 1 or 8, depending on
+whether the image is a lineart image or a contone image.
+
+The format field specifies the encoding of the raster data. A format of 0
+means that the data is uncompressed. The data itself is stored in scanline-
+major order. In the case of lineart image, 8 pixels are packed into each
+byte, with most-to-least significant order within the byte representing left-
+to-right order in the image. A 0 bit corresponds to a black pixel, and a 1
+bit corresponds to a white pixel. If necessary, the scanlines are padded out
+to the next 16-bit boundary.
diff --git a/imageto/bitmap2.c b/imageto/bitmap2.c
new file mode 100644
index 0000000..67d3d09
--- /dev/null
+++ b/imageto/bitmap2.c
@@ -0,0 +1,83 @@
+/* bitmap2.c: extra bitmap manipulation routines.
+
+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 "bitmap.h"
+
+#include "bitmap2.h"
+
+
+
+/* Put B2 to the right of B1, changing B1. For example, if B1 looked
+ like `A' and B2 like `B', the result would look like `AB'. The two
+ bitmaps must have the same number of rows. */
+
+void
+bitmap_concat (bitmap_type *b1, bitmap_type b2)
+{
+ bitmap_type new;
+ dimensions_type new_dimens;
+ unsigned row;
+
+ assert (BITMAP_HEIGHT (*b1) == BITMAP_HEIGHT (b2));
+
+ DIMENSIONS_WIDTH (new_dimens) = BITMAP_WIDTH (*b1) + BITMAP_WIDTH (b2);
+ DIMENSIONS_HEIGHT (new_dimens) = BITMAP_HEIGHT (b2);
+ new = new_bitmap (new_dimens);
+
+ /* Choice of `b2' or `b1' here is arbitrary, of course. */
+ for (row = 0; row < BITMAP_HEIGHT (b2); row++)
+ {
+ one_byte *target1 = BITMAP_ROW (new, row);
+ one_byte *target2 = target1 + BITMAP_WIDTH (*b1);
+
+ memcpy (target1, BITMAP_ROW (*b1, row), BITMAP_WIDTH (*b1));
+ memcpy (target2, BITMAP_ROW (b2, row), BITMAP_WIDTH (b2));
+ }
+
+ free_bitmap (b1);
+ *b1 = new;
+}
+
+
+/* Return a bitmap which consists of B1, one blank row, and B2. The two
+ bitmaps must have the same width. (The blank row is necessary
+ because one blank row is removed the first time we call
+ some_black_to_all_white; consider the row consisting of just an `!'.)*/
+
+bitmap_type
+bitmap_vconcat (bitmap_type b1, bitmap_type b2)
+{
+ bitmap_type new;
+ dimensions_type new_dimens;
+ unsigned width = BITMAP_WIDTH (b1);
+ unsigned size1 = width * BITMAP_HEIGHT (b1);
+ unsigned size2 = width * BITMAP_HEIGHT (b2);
+
+ assert (width == BITMAP_WIDTH (b2));
+
+ DIMENSIONS_WIDTH (new_dimens) = width;
+ DIMENSIONS_HEIGHT (new_dimens) = BITMAP_HEIGHT (b1) + BITMAP_HEIGHT (b2) + 1;
+ new = new_bitmap (new_dimens);
+
+ memcpy (BITMAP_BITS (new), BITMAP_BITS (b1), size1);
+ memcpy (BITMAP_BITS (new) + size1 + width, BITMAP_BITS (b2), size2);
+
+ return new;
+}
diff --git a/imageto/bitmap2.h b/imageto/bitmap2.h
new file mode 100644
index 0000000..d643117
--- /dev/null
+++ b/imageto/bitmap2.h
@@ -0,0 +1,34 @@
+/* bitmap2.h: declare extra bitmap manipulation routines.
+
+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. */
+
+#ifndef BITMAP2_H
+#define BITMAP2_H
+
+#include "bitmap.h"
+
+
+/* Put B2 to the right of B1, changing B2. The two bitmaps must have
+ the same number of rows. */
+extern void bitmap_concat (bitmap_type *b1, bitmap_type b2);
+
+
+/* Put B2 below B1. The two bitmaps must have the same number of
+ columns. */
+extern bitmap_type bitmap_vconcat (bitmap_type b1, bitmap_type b2);
+
+#endif /* not BITMAP2_H */
diff --git a/imageto/extract.c b/imageto/extract.c
new file mode 100644
index 0000000..2482646
--- /dev/null
+++ b/imageto/extract.c
@@ -0,0 +1,239 @@
+/* extract.c: operations on bitmaps. These could be put in
+ lib/bitmap.c, but since they are not particularly common
+ operations, we may as well define them separately for now.
+
+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 "bitmap.h"
+#include "bounding-box.h"
+#include "report.h"
+
+#include "bitmap2.h"
+#include "extract.h"
+#include "main.h"
+#include "input-img.h"
+#include "input-pbm.h"
+
+static bitmap_type *get_image_row (boolean, unsigned);
+static unsigned *image_row_transitions (bitmap_type);
+
+
+
+
+/* Combine the images in the bitmaps B1 and B2, returning the result in
+ B1. The relative position of the bitmaps is given by the bounding
+ boxes BB1 and BB2. We update the bounding box, also. */
+
+void
+combine_images (bitmap_type *b1, bitmap_type b2,
+ bounding_box_type *bb1, bounding_box_type bb2)
+{
+ int this_row, this_col;
+ bitmap_type whole_bitmap;
+ bounding_box_type whole_bb;
+
+ /* If either of the bitmaps are nonexistent, we have nothing
+ significant to do. */
+ if (BITMAP_BITS (b2) == NULL)
+ return;
+ if (BITMAP_BITS (*b1) == NULL)
+ {
+ *b1 = b2;
+ return;
+ }
+
+ MIN_ROW (whole_bb) = MIN (MIN_ROW (*bb1), MIN_ROW (bb2));
+ MAX_ROW (whole_bb) = MAX (MAX_ROW (*bb1), MAX_ROW (bb2));
+ MIN_COL (whole_bb) = MIN (MIN_COL (*bb1), MIN_COL (bb2));
+ MAX_COL (whole_bb) = MAX (MAX_COL (*bb1), MAX_COL (bb2));
+
+ whole_bitmap = new_bitmap (bb_to_dimensions (whole_bb));
+
+ /* First, copy the first image in. */
+ for (this_row = MIN_ROW (*bb1); this_row <= MAX_ROW (*bb1); this_row++)
+ {
+ one_byte *target_row
+ = BITMAP_BITS (whole_bitmap)
+ + (this_row - MIN_ROW (whole_bb)) * BITMAP_WIDTH (whole_bitmap)
+ + MIN_COL (*bb1) - MIN_COL (whole_bb);
+ one_byte *source_row
+ = BITMAP_BITS (*b1)
+ + (this_row - MIN_ROW (*bb1)) * BITMAP_WIDTH (*b1);
+
+ memcpy (target_row, source_row, BITMAP_WIDTH (*b1));
+ }
+
+ /* Put the second image in. */
+ for (this_row = MIN_ROW (bb2); this_row <= MAX_ROW (bb2); this_row++)
+ for (this_col = MIN_COL (bb2); this_col < MAX_COL (bb2); this_col++)
+ {
+ if (BITMAP_PIXEL (b2, this_row - MIN_ROW (bb2),
+ this_col - MIN_COL (bb2)) == BLACK)
+ BITMAP_PIXEL (whole_bitmap, this_row - MIN_ROW (whole_bb),
+ this_col - MIN_COL (whole_bb))
+ = BLACK;
+ }
+
+ free_bitmap (b1);
+ *b1 = whole_bitmap;
+ *bb1 = whole_bb;
+}
+
+/* Get the next image row of width WIDTH, ignoring leading white rows.
+ Return the columns at which there are black-to-white or white-black
+ transitions in TRANSITIONS. */
+
+bitmap_type *
+some_black_to_all_white_row (unsigned width, unsigned **transitions)
+{
+ bitmap_type *new = get_image_row (false, width);
+ if (new == NULL)
+ return NULL;
+
+ *transitions = image_row_transitions (*new);
+ return new;
+}
+
+
+/* Get the next image row, including leading blank rows, concatenating
+ it below B with one blank row between. Otherwise like
+ `some_black_to_all_white_row'. */
+
+bitmap_type *
+append_next_image_row (bitmap_type b, unsigned width, unsigned **transitions)
+{
+ bitmap_type *new = XTALLOC1 (bitmap_type);
+ bitmap_type *next = get_image_row (true, width);
+
+ if (next == NULL)
+ return NULL;
+
+ *new = bitmap_vconcat (b, *next);
+ *transitions = image_row_transitions (*new);
+ return new;
+}
+
+/* Because scanlines take a relatively long time to read, we will want
+ some kind of status report. */
+
+#define REPORT_SCANLINE() if (++scanline_count % 100 == 0) REPORT (".")
+
+/* Read scanlines of width WIDTH from the image file until we get one
+ that has at least one black pixel in it (i.e., found part of a
+ character). Then read scanlines until we get one that is entirely
+ white. If KEEP_LEADING_WHITE_ROWS, then include the white rows we
+ found at the beginning in the returned bitmap; otherwise, it's just
+ the rows from the first-black to the one before the all-white. */
+
+static bitmap_type *
+get_image_row (boolean keep_leading_white_rows, unsigned width)
+{
+ static unsigned scanline_count = 0;
+ bitmap_type *bitmap;
+ boolean found_white_row;
+ one_byte *image;
+ unsigned rows_used, rows_allocated;
+ boolean found_black_row = false;
+ one_byte *scanline = xmalloc (width);
+ unsigned white_row_count = 0;
+
+ while ((*image_get_scanline) (scanline))
+ {
+ REPORT_SCANLINE ();
+
+ found_black_row = memchr (scanline, BLACK, width) != NULL;
+ if (found_black_row)
+ break;
+
+ white_row_count++;
+ }
+
+ /* If reached end of the image before finding a black row, return NULL. */
+ if (!found_black_row)
+ return NULL;
+
+ /* Initialize the image to either the scanline with some black that we
+ just found, or to a bitmap with as many all-white rows as we've
+ seen, depending on `keep_leading_white_rows'. */
+ rows_used = 1;
+ if (keep_leading_white_rows && white_row_count > 0)
+ { /* We clear the last row unnecessarily, since the next we do is
+ memcpy into it -- but that's better than realloc-ing. */
+ image = xcalloc (white_row_count + 1, width);
+ rows_used += white_row_count;
+ memcpy (image + white_row_count * width, scanline, width);
+ free (scanline);
+ }
+ else
+ image = scanline;
+
+ /* Found the row with a black pixel; now look for the all-white row.
+ When we start off here, we've allocated exactly as much space as
+ we've used so far. */
+ rows_allocated = rows_used;
+ found_white_row = false;
+ while (!found_white_row)
+ { /* Since we only need one more row at a time, we don't need a
+ `while' loop here. */
+ if (rows_used + 1 > rows_allocated)
+ { /* Perhaps doubling is the wrong thing to do here, as it may
+ waste quite a bit of memory. But it's simple. */
+ rows_allocated += 100 /* ;<<= 1*/;
+ image = xrealloc (image, rows_allocated * width);
+ }
+
+ scanline = image + rows_used * width;
+ if (!(*image_get_scanline) (scanline))
+ break;
+ REPORT_SCANLINE ();
+ rows_used++;
+ found_white_row = memchr (scanline, BLACK, width) == NULL;
+ }
+
+ bitmap = XTALLOC1 (bitmap_type);
+ BITMAP_WIDTH (*bitmap) = width;
+ BITMAP_HEIGHT (*bitmap) = rows_used;
+ BITMAP_BITS (*bitmap) = image;
+
+ return bitmap;
+}
+
+
+/* Return a vector of the column numbers at which B changes from black
+ to white or white to black, terminated with an element which is B's
+ width + 1. */
+
+static unsigned *
+image_row_transitions (bitmap_type b)
+{
+ unsigned *transitions;
+ unsigned row, col;
+ unsigned width = BITMAP_WIDTH (b);
+ one_byte *or_of_all = xcalloc (width, 1);
+
+ for (row = 0; row < BITMAP_HEIGHT (b); row++)
+ for (col = 0; col < width; col++)
+ or_of_all[col] |= BITMAP_PIXEL (b, row, col);
+
+ /* We use `or_of_all' to find transitions: its ith column is 1
+ if any row in the image had a black pixel at the ith column. */
+ transitions = bitmap_find_transitions (or_of_all, width);
+
+ return transitions;
+}
diff --git a/imageto/extract.h b/imageto/extract.h
new file mode 100644
index 0000000..b1c29e3
--- /dev/null
+++ b/imageto/extract.h
@@ -0,0 +1,50 @@
+/* extract.h: declare operations on bitmaps.
+
+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. */
+
+#ifndef EXTRACT_H
+#define EXTRACT_H
+
+#include "bitmap.h"
+#include "bounding-box.h"
+
+
+/* Return the segment in B starting after the column START that begins
+ with a column with at least one black pixel, to a column that is all
+ white (or the end of the bitmap). If no such segment is found,
+ return NULL. */
+extern bitmap_type *some_black_to_all_white_column (bitmap_type b);
+
+/* Read scanlines of width WIDTH (in pixels) from the input file until
+ we find a segment starting with a row with at least one black pixel,
+ and ending with a row that is all white (or the end of the file). If
+ no such segment is found, return NULL. In TRANSITIONS we return the
+ column numbers where white changes to black or black to white. The
+ first transition is black-to-white. */
+extern bitmap_type *some_black_to_all_white_row (unsigned width,
+ unsigned **transitions);
+
+/* Like `some_black_to_all_white_row', except appends both the white
+ rows and then the black ones to B. */
+extern bitmap_type *append_next_image_row
+ (bitmap_type b, unsigned width, unsigned **transitions);
+
+/* Combine the bitmaps B1 and B2 based on the bounding boxes, returning
+ the result in B1. Also combine the bounding boxes. */
+extern void combine_images (bitmap_type *b1, bitmap_type b2,
+ bounding_box_type *, bounding_box_type);
+#endif /* not EXTRACT_H */
diff --git a/imageto/ifi.c b/imageto/ifi.c
new file mode 100644
index 0000000..45d6b4c
--- /dev/null
+++ b/imageto/ifi.c
@@ -0,0 +1,196 @@
+/* ifi.c: read an IFI file. */
+
+#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;
+}
diff --git a/imageto/ifi.h b/imageto/ifi.h
new file mode 100644
index 0000000..e013d26
--- /dev/null
+++ b/imageto/ifi.h
@@ -0,0 +1,91 @@
+/* ifi.h: information about the characters in the image.
+
+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. */
+
+#ifndef IFI_H
+#define IFI_H
+
+#include <kpathsea/types.h>
+
+
+/* See ifi.c. */
+extern string encoding_name, ifi_filename;
+
+
+/* A single character in the image. */
+typedef struct
+{
+ charcode_type charcode;
+ string charname;
+ boolean omit;
+ int baseline_adjust;
+ unsigned bb_count;
+ boolean alternating;
+ int lsb, rsb;
+} image_char_type;
+
+/* The character code. This is garbage if `omit' is true. */
+#define IMAGE_CHARCODE(c) ((c).charcode)
+
+/* The character name. */
+#define IMAGE_CHARNAME(c) ((c).charname)
+
+/* Says whether this character should be output. */
+#define IMAGE_CHAR_OMIT(c) ((c).omit)
+
+/* How far the baseline should be moved from the row's baseline. */
+#define IMAGE_CHAR_BASELINE_ADJUST(c) ((c).baseline_adjust)
+
+/* How many bounding boxes comprise this character. */
+#define IMAGE_CHAR_BB_COUNT(c) ((c).bb_count)
+
+/* Says whether the bounding boxes in this character are consecutive
+ (the usual case) or alternate. */
+#define IMAGE_CHAR_BB_ALTERNATING(c) ((c).alternating)
+
+/* The side bearings. */
+#define IMAGE_CHAR_LSB(c) ((c).lsb)
+#define IMAGE_CHAR_RSB(c) ((c).rsb)
+
+
+/* A list of the above. */
+typedef struct
+{
+ image_char_type *data;
+ unsigned length;
+} image_char_list_type;
+
+/* The Nth element of the list L. */
+#define IMAGE_CHAR(l, n) ((l).data[n])
+
+/* The list as a whole. */
+#define IMAGE_CHAR_LIST_DATA(l) ((l).data)
+
+/* The length of the list. */
+#define IMAGE_CHAR_LIST_LENGTH(l) ((l).length)
+
+
+/* Read the IFI file IFI_FILENAME. Return the total number of characters
+ read in TOTAL_COUNT. */
+extern image_char_list_type read_ifi_file (unsigned *total_count);
+
+/* Return false if the box BOX_COUNT boxes beyond FIRST_CHAR in LIST
+ is in the middle of a character, true otherwise. */
+extern boolean box_at_char_boundary_p
+ (image_char_list_type list, unsigned first_char, unsigned box_count);
+
+#endif /* not IFI_H */
diff --git a/imageto/image-char.c b/imageto/image-char.c
new file mode 100644
index 0000000..2f9fc56
--- /dev/null
+++ b/imageto/image-char.c
@@ -0,0 +1,69 @@
+/* image-char.c: manipulate information about the characters in the image.
+
+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 "image-char.h"
+
+
+/* Return an initialized, empty list. */
+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 CURRENT_CHAR in LIST
+ is in the middle of a character, true otherwise. To do this, we must
+ 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 current_char,
+ unsigned box_count)
+{
+ unsigned count = 0;
+
+ while (count < box_count && current_char < IMAGE_CHAR_LIST_LENGTH (list))
+ {
+ image_char_type c = IMAGE_CHAR (list, current_char);
+ count += IMAGE_CHAR_BB_COUNT (c);
+ current_char++;
+ }
+
+ return count == box_count;
+}
diff --git a/imageto/image-char.h b/imageto/image-char.h
new file mode 100644
index 0000000..c1b2880
--- /dev/null
+++ b/imageto/image-char.h
@@ -0,0 +1,89 @@
+/* image-char.h: information about the characters in the image.
+
+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. */
+
+#ifndef IMAGE_CHAR_H
+#define IMAGE_CHAR_H
+
+#include "types.h"
+
+
+/* A single character in the image. */
+typedef struct
+{
+ charcode_type charcode;
+ string charname;
+ boolean omit;
+ int baseline_adjust;
+ unsigned bb_count;
+ boolean alternating;
+ int lsb, rsb;
+} image_char_type;
+
+/* The character code. This is garbage if `omit' is true. */
+#define IMAGE_CHARCODE(c) ((c).charcode)
+
+/* The character name. */
+#define IMAGE_CHARNAME(c) ((c).charname)
+
+/* Says whether this character should be output. */
+#define IMAGE_CHAR_OMIT(c) ((c).omit)
+
+/* How far the baseline should be moved from the row's baseline. */
+#define IMAGE_CHAR_BASELINE_ADJUST(c) ((c).baseline_adjust)
+
+/* How many bounding boxes comprise this character. */
+#define IMAGE_CHAR_BB_COUNT(c) ((c).bb_count)
+
+/* Says whether the bounding boxes in this character are consecutive
+ (the usual case) or alternate. */
+#define IMAGE_CHAR_BB_ALTERNATING(c) ((c).alternating)
+
+/* The side bearings. */
+#define IMAGE_CHAR_LSB(c) ((c).lsb)
+#define IMAGE_CHAR_RSB(c) ((c).rsb)
+
+
+/* A list of the above. */
+typedef struct
+{
+ image_char_type *data;
+ unsigned length;
+} image_char_list_type;
+
+/* The Nth element of the list L. */
+#define IMAGE_CHAR(l, n) ((l).data[n])
+
+/* The list as a whole. */
+#define IMAGE_CHAR_LIST_DATA(l) ((l).data)
+
+/* The length of the list. */
+#define IMAGE_CHAR_LIST_LENGTH(l) ((l).length)
+
+
+/* Return an empty list. */
+extern image_char_list_type new_image_char_list (void);
+
+/* Append the character C to the list L. */
+extern void append_image_char (image_char_list_type *l, image_char_type c);
+
+/* Return false if the box BOX_COUNT boxes beyond FIRST_CHAR in LIST
+ is in the middle of a character, true otherwise. */
+extern boolean box_at_char_boundary_p
+ (image_char_list_type list, unsigned first_char, unsigned box_count);
+
+#endif /* not IMAGE_CHAR_H */
diff --git a/imageto/image-header.h b/imageto/image-header.h
new file mode 100644
index 0000000..9d48a60
--- /dev/null
+++ b/imageto/image-header.h
@@ -0,0 +1,35 @@
+/* image-header.h: declarations for a generic image header.
+
+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. */
+
+#ifndef IMAGE_HEADER_H
+#define IMAGE_HEADER_H
+
+#include <kpathsea/types.h>
+
+/* The important general information about the image data.
+ See `get_{img,pbm}_header' for the full details of the headers for
+ the particular formats. */
+typedef struct
+{
+ two_bytes hres, vres; /* In pixels per inch. */
+ two_bytes width, height; /* In bits. */
+ two_bytes depth;
+ unsigned format; /* (for pbm) Whether packed or not. */
+} image_header_type;
+
+#endif /* not IMAGE_HEADER_H */
diff --git a/imageto/input-img.c b/imageto/input-img.c
new file mode 100644
index 0000000..1930350
--- /dev/null
+++ b/imageto/input-img.c
@@ -0,0 +1,159 @@
+/* input-img.c: read Interleaf .img files.
+
+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 "file-input.h"
+
+#include "main.h"
+#include "image-header.h"
+#include "input-img.h"
+
+
+/* Where the input comes from. */
+static FILE *img_input_file;
+static string img_input_filename;
+
+/* What we'll read the raw data for each scanline into. */
+static one_byte *line_in_bytes;
+
+/* How big `line_in_bytes' is, in both bytes and pixels. */
+static unsigned byte_width;
+static unsigned pixel_width;
+static unsigned pixel_depth;
+
+/* Macros for convenient input. The routines are defined in kbase. */
+#define IMG_MATCH_BYTE(v) match_byte (v, img_input_file, img_input_filename)
+
+#define IMG_GET_TWO() get_two (img_input_file, img_input_filename)
+#define IMG_GET_FOUR() get_four (img_input_file, img_input_filename)
+
+/* Only one file can be open at a time. We do no path searching. If
+ FILENAME can't be opened, we quit. */
+
+void
+img_open_input_file (string filename)
+{
+ assert (img_input_file == NULL);
+
+ img_input_file = xfopen (filename, "r");
+ img_input_filename = filename;
+}
+
+
+/* Close the input file. If it hasn't been opened, we quit. */
+
+void
+img_close_input_file ()
+{
+ assert (img_input_file != NULL);
+
+ xfclose (img_input_file, img_input_filename);
+ img_input_file = NULL;
+}
+
+/* Read the header information.
+ Modifies the global image_header in main.c. */
+
+void
+img_get_header ()
+{
+ unsigned flags;
+ unsigned pixels_per_short;
+ unsigned short_width;
+
+ /* The ``magic number''. */
+ IMG_MATCH_BYTE (0211);
+ IMG_MATCH_BYTE ('O');
+ IMG_MATCH_BYTE ('P');
+ IMG_MATCH_BYTE ('S');
+
+ /* The version number. */
+ IMG_MATCH_BYTE (0);
+ IMG_MATCH_BYTE (2);
+
+ image_header.hres = IMG_GET_TWO ();
+ image_header.vres = IMG_GET_TWO ();
+ flags = IMG_GET_FOUR ();
+ if (flags != 0)
+ FATAL1 ("img_get_header: Expected flags to be zero, not %u", flags);
+ image_header.width = IMG_GET_TWO ();
+ image_header.height = IMG_GET_TWO ();
+ pixel_depth = image_header.depth = IMG_GET_TWO ();
+ image_header.format = IMG_GET_TWO ();
+ if (image_header.format != 0)
+ FATAL1 ("img_get_header: Expected format to be zero, not %u",
+ image_header.format);
+
+ /* Allocate the space that we will read into (since that space is the
+ same from scanline to scanline). The width is derived from the
+ header information, which must already have been read.
+ Specifically, the width in the header is given in bits. Each
+ scanline is padded to a 16-bit boundary. For example, suppose the
+ header width = 1516, that is 94.75 shorts; we round up to 95,
+ thus getting a scanline width of 1520 bits, or 190 bytes. (For
+ monochrome images.) */
+ pixel_width = image_header.width;
+ pixels_per_short = 16 / image_header.depth;
+ short_width = pixel_width / pixels_per_short
+ + (pixel_width % pixels_per_short != 0);
+ byte_width = short_width * 2;
+ line_in_bytes = xmalloc (byte_width);
+}
+
+/* Read one scanline of the image, returning each bit of the scanline in
+ a separate byte. We may use the `line_in_bytes' variable, allocated in
+ `img_get_header' just above, to read into. */
+
+boolean
+img_get_scanline (one_byte *line_in_pixels)
+{
+ /* No point in using temp. buffer if pixels and bytes are the same. */
+ if (fread (line_in_bytes, byte_width, 1, img_input_file) != 1)
+ {
+ if (feof (img_input_file))
+ return false;
+ else
+ FATAL1 ("img_get_scanline: fread of %u bytes failed", byte_width);
+ }
+
+ /* Don't handle cases other than depth 1 or 8. */
+ if (pixel_depth == 1)
+ {
+ unsigned this_bit, this_byte, mask;
+ for (this_bit = 0, this_byte = 0, mask = 0x80;
+ this_bit < pixel_width; this_bit++)
+ {
+ /* Somewhere along the line, black and white got reversed. */
+ line_in_pixels[this_bit] = (line_in_bytes[this_byte] & mask) == 0;
+ if (this_bit % 8 == 0)
+ {
+ this_byte = this_bit / 8;
+ mask = 0x80;
+ }
+ else
+ mask >>= 1;
+ }
+ }
+ else
+ memcpy (line_in_pixels, line_in_bytes, byte_width);
+
+ print_scanline (line_in_pixels, pixel_width);
+
+ return true;
+}
diff --git a/imageto/input-img.h b/imageto/input-img.h
new file mode 100644
index 0000000..afbaaeb
--- /dev/null
+++ b/imageto/input-img.h
@@ -0,0 +1,43 @@
+/* input-img.h: declarations for reading an IMG file.
+
+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. */
+
+#ifndef INPUT_IMG_H
+#define INPUT_IMG_H
+
+#include <kpathsea/types.h>
+#include "image-header.h"
+
+
+/* Prepare to read FILENAME. */
+extern void img_open_input_file (string filename);
+
+/* Close up gracefully. */
+extern void img_close_input_file (void);
+
+
+/* Read the header. */
+extern void img_get_header (void);
+
+
+/* Read a single scanline into P. P must point to a large-enough block
+ for one entire scanline (the width of the image is given in the
+ header). If at the end of the input file, returns false, else
+ returns true. */
+extern boolean img_get_scanline (one_byte *p);
+
+#endif /* not INPUT_IMG_H */
diff --git a/imageto/input-pbm.c b/imageto/input-pbm.c
new file mode 100644
index 0000000..9fe47ba
--- /dev/null
+++ b/imageto/input-pbm.c
@@ -0,0 +1,88 @@
+/* input-pbm.c: read PBM files.
+
+Copyright (C) 1990, 1991, 19 19ANY 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 "file-input.h"
+
+#include "main.h"
+#include "image-header.h"
+#include "input-pbm.h"
+
+#include "pbmplus.h"
+#include "pbm.h"
+
+
+/* Where the input comes from. */
+static FILE *pbm_input_file;
+static string pbm_input_filename;
+
+
+
+/* Only one file can be open at a time. We do no path searching. If
+ FILENAME can't be opened, we quit. */
+
+void
+pbm_open_input_file (string filename)
+{
+ assert (pbm_input_file == NULL);
+
+ pbm_input_file = xfopen (filename, "r");
+ pbm_input_filename = filename;
+}
+
+
+/* Close the input file. If it hasn't been opened, we quit. */
+
+void
+pbm_close_input_file ()
+{
+ assert (pbm_input_file != NULL);
+
+ xfclose (pbm_input_file, pbm_input_filename);
+ pbm_input_file = NULL;
+}
+
+
+
+/* Read the header information.
+ Modifies the global image_header in main.c. */
+
+void
+pbm_get_header ()
+{
+ int width, height, format;
+
+ pbm_readpbminit (pbm_input_file, &width, &height, &format);
+ image_header.width = (two_bytes) width;
+ image_header.height = (two_bytes) height;
+ image_header.depth = 0;
+ image_header.format = (two_bytes) format;
+}
+
+
+
+/* Read one scanline of the image. */
+
+boolean
+pbm_get_scanline (one_byte *line_in_bits)
+{
+ int c = getc (pbm_input_file);
+
+ if (c == EOF)
+ return false;
+
+ ungetc (c, pbm_input_file);
+ pbm_readpbmrow (pbm_input_file, line_in_bits, image_header.width,
+ image_header.format);
+
+ print_scanline (line_in_bits, image_header.width);
+ return true;
+}
diff --git a/imageto/input-pbm.h b/imageto/input-pbm.h
new file mode 100644
index 0000000..522d2de
--- /dev/null
+++ b/imageto/input-pbm.h
@@ -0,0 +1,44 @@
+/* input-pbm.h: declarations for reading an PBM file.
+
+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. */
+
+#ifndef INPUT_PBM_H
+#define INPUT_PBM_H
+
+#include <kpathsea/types.h>
+#include "image-header.h"
+
+
+/* Prepare to read FILENAME. */
+extern void pbm_open_input_file (string filename);
+
+/* Close up gracefully. */
+extern void pbm_close_input_file (void);
+
+
+/* Read the header. */
+extern void pbm_get_header (void);
+
+
+/* Read a single scanline into P. P must point to a large-enough block
+ for one entire scanline (the width of the image is given in the
+ header). If at the end of the input file, returns false, else
+ returns true. */
+extern boolean pbm_get_scanline (one_byte *p);
+
+#endif /* not INPUT_PBM_H */
+
diff --git a/imageto/main.c b/imageto/main.c
new file mode 100644
index 0000000..e3215c8
--- /dev/null
+++ b/imageto/main.c
@@ -0,0 +1,416 @@
+/* imageto -- convert a scanned image.
+
+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 <kpathsea/concatn.h>
+
+#define CMDLINE_NO_DPI /* It's not in the input filename. */
+#include "cmdline.h"
+#include "encoding.h" /* For `DEFAULT_ENCODING'. */
+#include "getopt.h"
+#include "gf.h"
+#include "report.h"
+
+#include "ifi.h" /* For `encoding_name'. */
+#include "image-header.h"
+#include "input-img.h"
+#include "input-pbm.h"
+#include "main.h"
+#include "out-chars.h"
+#include "out-epsf.h"
+#include "out-strips.h"
+
+
+/* General information about the image. Set by the input routines. */
+image_header_type image_header;
+
+/* Pointers to functions based on input format. (-input-format) */
+void (*image_open_input_file) (string) = NULL;
+void (*image_close_input_file) (void) = NULL;
+void (*image_get_header) (void) = NULL;
+boolean (*image_get_scanline) (one_byte *) = NULL;
+
+/* The filename for the input image. */
+string input_name;
+
+/* Show every scanline on the terminal as we read it? (-trace-scanlines) */
+boolean trace_scanlines = false;
+
+/* Private variables. */
+
+/* The design size of the font we're creating. (-designsize) */
+static real design_size = 10.0;
+
+/* The suffix for the image file. */
+static string input_extension;
+
+/* If set, write an EPSF file. (-epsf) */
+static boolean output_epsf = false;
+
+/* The name of the file we're going to write. (-output-file) */
+string output_name;
+
+/* If set, make each ``character'' a (more or less) constant number of
+ scanlines. (-strips) */
+static boolean do_strips = false;
+
+
+static string read_command_line (int, string[]);
+static void set_img_input_format (void);
+static void set_input_format (string);
+static void set_pbm_input_format (void);
+
+/* We have three different strategies for processing the image:
+ 1) (normal) analyze the image and write out the ``true'' characters,
+ 2) (-strips) takes a constant number of scanlines as each character,
+ 3) (-epsf) write out the image as an Encapsulated PostScript file.
+
+ The output name is, correspondingly, constructed differently:
+ 1) if `output_name' was supplied, and has a suffix, that's it.
+ 2) if `output_name' was supplied, but has no suffix, append `.eps'
+ if we're doing EPSF, else append `<suffix>.<dpi>gf', where
+ <suffix> is
+ a) `sp', if we are doing strips;
+ b) the design size, if not.
+ 3) if `output_name' was not supplied, use the basename of the input
+ filename extended as in #2.
+ */
+
+int
+main (int argc, string argv[])
+{
+ boolean writing_gf;
+
+ kpse_set_progname (argv[0]);
+
+ input_name = read_command_line (argc, argv);
+ writing_gf = !output_epsf;
+
+ set_input_format (input_name);
+
+ /* If the input format is PBM, then they must also tell us the dpi. */
+ if (image_open_input_file == pbm_open_input_file
+ && image_header.hres == 0)
+ {
+ fprintf (stderr, "If you use PBM format, you must supply the dpi.\n");
+ fprintf (stderr, "For more information, use ``-help''.\n");
+ exit (1);
+ }
+
+ /* Open the main input file. */
+ (*image_open_input_file) (extend_filename (input_name, input_extension));
+
+ /* We need the horizontal resolution before we can make the GF name,
+ so, at least for IMG input, have to read the header. */
+ (*image_get_header) ();
+
+ /* If the user didn't give an output name, use the input name. */
+ if (output_name == NULL)
+ output_name = remove_suffix (basename (input_name));
+
+ /* If they didn't give an output name with a suffix, use ours. */
+ if (find_suffix (output_name) == NULL)
+ {
+ if (writing_gf)
+ {
+ char dpi[MAX_INT_LENGTH + 1];
+ string suffix = do_strips ? "sp" : itoa ((unsigned) design_size);
+
+ sprintf (dpi, "%u", image_header.hres);
+ output_name = concatn (output_name, suffix, ".", dpi, "gf", NULL);
+ }
+ else if (output_epsf)
+ output_name = concat (output_name, ".eps");
+ else
+ abort (); /* Should never happen. */
+ }
+
+ /* If necessary, open the GF file. */
+ if (writing_gf)
+ {
+ if (!gf_open_output_file (output_name))
+ FATAL_PERROR (output_name);
+
+ /* Identify ourselves in the GF comment. */
+ gf_put_preamble (concat ("imageto output ", now () + 4));
+ }
+
+ /* Do the real work, whichever the user wants. */
+ if (do_strips)
+ { /* The design size is irrelevant when we're creating strips,
+ but it should be pretty large, lest the relative dimensions in
+ the TFM file get too big. */
+ design_size = 100.0;
+ write_chars_as_strips (image_header, design_size);
+ }
+ else if (output_epsf)
+ write_epsf (output_name, image_header);
+ else
+ write_image_chars (image_header, design_size);
+
+ /* Clean up. */
+ if (verbose)
+ REPORT ("\n");
+
+ if (writing_gf)
+ {
+ /* We've read all the characters we're supposed to (or else the whole
+ image). Finish up the font. */
+ gf_put_postamble (real_to_fix (design_size),
+ (real) image_header.hres, (real) image_header.vres);
+ gf_close_output_file ();
+ }
+
+ (*image_close_input_file) ();
+
+ return 0;
+}
+
+/* We are semi-clever about printing this, for the sake of huge images. */
+
+void
+print_scanline (one_byte line[], unsigned width)
+{
+ static unsigned scanline_count = 0;
+
+ if (trace_scanlines)
+ {
+ printf ("%7d:", scanline_count++);
+
+ /* If the line is entirely white, don't print anything. */
+ if (memchr (line, BLACK, width))
+ {
+ unsigned c;
+
+ for (c = 0; c < width; c++)
+ { /* Compress eight consecutive spaces to a tab, if we're at
+ the beginning of a tab mark. This handles the usual
+ case, although we could do still better. */
+ if (c % 8 == 0 && c + 7 < width
+ && memchr (line + c, BLACK, 8) == NULL)
+ {
+ putchar ('\t');
+ c += 7;
+ }
+ else
+ putchar (line[c] ? '*' : ' ');
+ }
+ }
+
+ putchar ('\n');
+ }
+}
+
+/* Reading the options. */
+
+/* This is defined in version.c. */
+extern string version_string;
+
+#define USAGE "Options:
+<font_name> should be a base filename, e.g., `ggmr'. (More properly, it
+is an <image_name>, not a <font_name>.)" \
+ GETOPT_USAGE \
+"baselines <row1>,<row2>,...: define the baselines for each image row.
+ The baseline of the first image row is taken to be scanline <row1>, etc.
+designsize <real>: set the designsize of the font to <real>; default is 10.0.
+dpi <unsigned>: resolution (required for pbm input).
+encoding <filename>: read ligature and other encoding information
+ from `<filename>.enc'; the default is to assign successive character codes.
+epsf: write the image as an Encapsulated PostScript file, instead of a
+ bitmap font.
+help: print this message.
+ifi-file <filename>: use <filename>.ifi (if <filename doesn't have a
+ suffix; otherwise use <filename>) for the IFI filename; default is
+ `<font_name>.ifi'.
+input-format <format>: specify format of input image; <format> must be
+ one of `pbm' or `img'.
+nchars <unsigned>: only write the first <unsigned> (approximately)
+ characters to the font; default is infinity.
+output-file <filename>: write to <filename> if <filename> has a suffix.
+ If <filename> doesn't have a suffix, then if writing strips, write to
+ <filename>sp.<dpi>gf and to <filename>.<dpi>gf if not. By default,
+ use <font_name> for <filename>.
+print-clean-info: print gray values for the bounding boxes that are
+ considered for cleaning. This implies `-verbose'.
+print-guidelines: print the numbers of the top and bottom rows (in that
+ order) of each character. This implies `-verbose'.
+range <char1>-<char2>: only output characters between <char1> and
+ <char2>, inclusive.
+strips: take a constant number of scanlines as each character,
+ instead of using an IFI file to analyze the image.
+trace-scanlines: show every scanline as we read it.
+verbose: output progress reports.
+version: print the version number of this program.
+"
+
+static string
+read_command_line (int argc, string argv[])
+{
+ int g; /* `getopt' return code. */
+ int option_index;
+ boolean printed_version = false;
+ struct option long_options[]
+ = { { "baselines", 1, 0, 0 },
+ { "designsize", 1, 0, 0 },
+ { "encoding", 1, 0, 0 },
+ { "epsf", 0, (int *) &output_epsf, 1 },
+ { "help", 0, 0, 0 },
+ { "dpi", 1, 0, 0 },
+ { "ifi-file", 1, 0, 0 },
+ { "nchars", 1, 0, 0 },
+ { "input-format", 1, 0, 0 },
+ { "output-file", 1, 0, 0 },
+ { "print-clean-info", 0, (int *) &print_clean_info, 1 },
+ { "print-guidelines", 0, (int *) &print_guidelines, 1 },
+ { "range", 1, 0, 0 },
+ { "strips", 0, (int *) &do_strips, 1 },
+ { "trace-scanlines", 0, (int *) &trace_scanlines, 1 },
+ { "verbose", 0, (int *) &verbose, 1 },
+ { "version", 0, (int *) &printed_version, 1 },
+ { 0, 0, 0, 0 } };
+
+ while (true)
+ {
+ g = getopt_long_only (argc, argv, "", long_options, &option_index);
+
+ if (g == EOF)
+ break;
+
+ if (g == '?')
+ exit (1); /* Unknown option. */
+
+ assert (g == 0); /* We have no short option names. */
+
+ if (ARGUMENT_IS ("baselines"))
+ baseline_list = scan_unsigned_list (optarg);
+
+ else if (ARGUMENT_IS ("designsize"))
+ design_size = atof (optarg);
+
+ else if (ARGUMENT_IS ("dpi"))
+ {
+ image_header.hres = (two_bytes) atou (optarg);
+ image_header.vres = image_header.hres;
+ }
+
+ else if (ARGUMENT_IS ("encoding"))
+ encoding_name = optarg;
+
+ else if (ARGUMENT_IS ("help"))
+ {
+ fprintf (stderr, "Usage: %s [options] <font_name>.\n", argv[0]);
+ fprintf (stderr, USAGE);
+ exit (0);
+ }
+
+ else if (ARGUMENT_IS ("ifi-file"))
+ ifi_filename = optarg;
+
+ else if (ARGUMENT_IS ("input-format"))
+ {
+ if (STREQ ("pbm", optarg))
+ set_pbm_input_format ();
+ else if (STREQ ("img", optarg))
+ set_img_input_format ();
+ else
+ FATAL1 ("imageto: Unknown input format `%s'; expected one of \
+`img' or `pbm'", optarg);
+ }
+
+ else if (ARGUMENT_IS ("nchars"))
+ nchars_wanted = atou (optarg);
+
+ else if (ARGUMENT_IS ("output-file"))
+ output_name = optarg;
+
+ else if (ARGUMENT_IS ("print-clean-info")
+ || ARGUMENT_IS ("print-guidelines"))
+ verbose = true;
+
+ else if (ARGUMENT_IS ("range"))
+ GET_RANGE (optarg, starting_char, ending_char);
+
+ else if (ARGUMENT_IS ("version"))
+ printf ("%s.\n", version_string);
+
+ /* Else it was a flag; getopt has already done the assignment. */
+ }
+
+ if (do_strips && output_epsf)
+ FATAL ("imageto: Sorry, -strips and -epsf are mutually exclusive");
+
+ FINISH_COMMAND_LINE ();
+}
+
+/* If the input format wasn't explicitly set on the command line,
+ attempt to intuit it from FILENAME, and set the necessary variables.
+ If we can't tell what the format should be, quit. */
+
+static void
+set_input_format (string filename)
+{
+ string input_extension;
+
+ /* If it's already set, just return. */
+ if (image_open_input_file != NULL)
+ return;
+
+ /* Try to guess based on FILENAME. */
+ input_extension = find_suffix (filename) ? : "";
+
+ if (STREQ (input_extension, "img"))
+ set_img_input_format ();
+
+ else if (STREQ (input_extension, "pbm"))
+ set_pbm_input_format ();
+
+ else /* Can't guess it; quit. */
+ {
+ fprintf (stderr, "You must supply an input format.\n");
+ fprintf (stderr, "(I can't guess from the filename `%s'.)\n", filename);
+ fprintf (stderr, "For more information, use ``-help''.\n");
+ exit (1);
+ }
+}
+
+
+/* Set up for reading a PBM file. */
+
+static void
+set_pbm_input_format ()
+{
+ image_open_input_file = pbm_open_input_file;
+ image_close_input_file = pbm_close_input_file;
+ image_get_header = pbm_get_header;
+ image_get_scanline = pbm_get_scanline;
+ input_extension = "pbm";
+}
+
+
+/* Set up for reading an IMG file. */
+
+static void
+set_img_input_format ()
+{
+ image_open_input_file = img_open_input_file;
+ image_close_input_file = img_close_input_file;
+ image_get_header = img_get_header;
+ image_get_scanline = img_get_scanline;
+ input_extension = "img";
+}
diff --git a/imageto/main.h b/imageto/main.h
new file mode 100644
index 0000000..7d2f7c1
--- /dev/null
+++ b/imageto/main.h
@@ -0,0 +1,42 @@
+/* main.h: global variable declarations.
+
+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. */
+
+#ifndef MAIN_H
+#define MAIN_H
+
+#include <kpathsea/types.h>
+#include "image-header.h"
+
+
+/* See main.c for explanations of these globals. */
+extern boolean trace_scanlines;
+extern image_header_type image_header;
+extern string input_name;
+extern string output_name;
+
+/* Generic routines to manipulate the image. */
+extern void (*image_open_input_file) (string filename);
+extern void (*image_close_input_file) (void);
+extern void (*image_get_header) (void);
+extern boolean (*image_get_scanline) (one_byte *);
+
+
+/* Print a scanline LINE of width WIDTH, if `trace_scanlines' is true.. */
+extern void print_scanline (one_byte line[], unsigned width);
+
+#endif /* not MAIN_H */
diff --git a/imageto/out-chars.c b/imageto/out-chars.c
new file mode 100644
index 0000000..b0dc6f4
--- /dev/null
+++ b/imageto/out-chars.c
@@ -0,0 +1,750 @@
+/* out-chars.c: try to extract the real characters from the image.
+
+Copyright (C) 1992, 93 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 <kpathsea/tex-file.h>
+#include <kpathsea/pathsearch.h>
+#include <kpathsea/paths.h>
+
+#include "bb-outline.h"
+#include "gf.h"
+#include "report.h"
+
+#include "bitmap2.h"
+#include "extract.h"
+#include "ifi.h"
+#include "image-header.h"
+#include "main.h"
+#include "out-strips.h"
+
+/*xx*/
+FILE *testfileptr;
+const char* whole_bitmap_filename = "test-whole-bitmap";
+const char* bb_whole_bitmap_filename = "test-bb-whole-bitmap";
+const char* subbitmap_filename = "test-subbitmap";
+const char* bb_subbitmap_filename = "test-bb-subbitmap";
+const char* line_subbitmap_filename = "test-line-subbitmap";
+const char* line_bb_subbitmap_filename = "test-line-bb-subbitmap";
+const char* gf_bitmap_filename = "test-gf-bitmap";
+const char* gf_bb_bitmap_filename = "test-gf-bb-bitmap";
+
+
+
+/* A list of the image rows on which the baselines occur. The end of
+ the list is marked with an element -1. (-baselines) */
+int *baseline_list = NULL;
+
+/* Find about this many characters in the image, then stop. This is
+ useful only for testing, because converting the entire image takes a long
+ time. So we might in truth output a few more characters than
+ specified here. (-nchars) */
+unsigned nchars_wanted = MAX_CHARCODE + 1;
+
+/* If set, prints diagnostics about which boxes are and aren't cleaned.
+ (-print-clean-info) */
+boolean print_clean_info = false;
+
+/* Says whether to print the row numbers of each character as we go,
+ so that the user can decide how to adjust jumping baselines.
+ (-print-guidelines) */
+boolean print_guidelines = false;
+
+/* Says which characters to output. This is independent of the
+ ordering in the font file. (-range) */
+int starting_char = 0;
+int ending_char = MAX_CHARCODE;
+
+/* The design size of the font we're creating. */
+static real design_size;
+
+/* Where the baseline of the current row is in the image. The first row
+ is #1, and so on. We start over at row 1 at each image row.*/
+static unsigned row_baseline;
+static unsigned row_height;
+
+/* How many boxes total the characters take up. */
+static unsigned total_boxes_expected;
+
+
+static boolean bb_equal_p (bounding_box_type, bounding_box_type);
+static gf_char_type bitmap_to_gf_char
+ (bitmap_type, real, bounding_box_type, image_char_type);
+static void clean_bitmap (bitmap_type *, bb_list_type);
+static boolean do_image_line
+ (bitmap_type, unsigned *, unsigned *, real, image_char_list_type);
+static void image_to_bitmap_bbs (bb_list_type *);
+extern void offset_bb_list (bb_list_type *l, int offset);
+static unsigned output_chars
+ (bb_list_type, bitmap_type, real, image_char_list_type, unsigned);
+
+/* Analyze the input image, outputting the characters we find. */
+
+void
+write_image_chars (image_header_type image_header, real ds)
+{
+ bitmap_type *image_line_bitmap;
+ unsigned nchars_done = 0;
+
+ /* Read the image information. This tells us to which character
+ each bounding box belongs, among other things. */
+ image_char_list_type image_char_list = read_ifi_file (&total_boxes_expected);
+
+ /* Remember this so we don't need to pass it through all the
+ intervening routines to the low-level output. */
+ design_size = ds;
+
+ /* The main loop also (and more commonly) exits when we've read the
+ entire image. */
+ while (nchars_done < nchars_wanted)
+ {
+ /* Vector of column numbers where the image column alternates
+ between some black to all white; used to get the bounding box
+ column min and max for each character. */
+ unsigned *transitions;
+
+ /* Read one line of characters, noting the transitions (see
+ above), in the image. After this, `image_line_bitmap' is, for
+ example, `a...z', with blank columns at the left and right.
+ Whatever is in the original image. */
+ image_line_bitmap
+ = some_black_to_all_white_row (image_header.width, &transitions);
+
+ if (image_line_bitmap == NULL)
+ break; /* We've read the whole image file. */
+
+ if (baseline_list == NULL || *baseline_list == -1)
+ {
+ if (baseline_list != NULL)
+ WARNING ("imageto: Not enough baselines specified");
+ row_baseline = 0;
+ }
+ else
+ row_baseline = *baseline_list++;
+
+ row_height = BITMAP_HEIGHT (*image_line_bitmap);
+
+ /* Process one line of characters. If `do_image_line' fails, we
+ need to read the next row in the image, and put it directly
+ below the current line to complete a character. For example,
+ if a line has only an `!' on it, we will only get the stem on
+ the first call to `some_black_to_all_white_row'. We want to
+ get the dot in there, too. */
+ while (!do_image_line (*image_line_bitmap, transitions, &nchars_done,
+ (real) image_header.hres, image_char_list))
+ {
+ bitmap_type *revised
+ = append_next_image_row (*image_line_bitmap, image_header.width,
+ &transitions);
+ if (revised == NULL)
+ {
+ WARNING ("imageto: Image ended in the midst of a character");
+ break;
+ }
+
+ /* Tell the user the image row didn't end on a character. */
+ REPORT ("+");
+
+ free_bitmap (image_line_bitmap);
+ image_line_bitmap = revised;
+ if (baseline_list == NULL)
+ row_baseline = 0;
+
+ row_height = BITMAP_HEIGHT (*image_line_bitmap);
+ }
+
+ free_bitmap (image_line_bitmap);
+ }
+}
+
+/* Analyze and output all of the bitmap IMAGE, which is one line of type
+ in the original. The resolution of the image is H_RESOLUTION, and
+ we've read NCHARS characters (including .notdefs) so far. We use
+ IMAGE_CHAR_LIST, a list of character information from the IFI file,
+ and the transition vector TRANSITIONS, which has in it how IMAGE
+ breaks into characters or character groups.
+
+ We return false if we need to be given another image row to complete
+ a character. */
+
+#define NEXT_TRANSITION() ({ \
+ if (*transitions == BITMAP_WIDTH (image) + 1) \
+ { \
+ WARNING ("imageto: Expected more transitions"); \
+ break; \
+ } \
+ *transitions++; \
+})
+
+static boolean
+do_image_line (bitmap_type image, unsigned *transitions, unsigned *nchars,
+ real h_resolution, image_char_list_type image_char_list)
+{
+ static unsigned box_count = 0;
+ bounding_box_type bb;
+
+ /* We always use the entire image line vertically. */
+ MIN_ROW (bb) = 0;
+ MAX_ROW (bb) = BITMAP_HEIGHT (image) - 1;
+
+ /* `nchars_wanted' is an option to the program, defined at the top.
+ Go through the whole line, unless we've found as many characters
+ as the user requested. */
+ while (*nchars < nchars_wanted && *transitions != BITMAP_WIDTH (image) + 1)
+ {
+ int bb_offset = 0;
+ unsigned previous_box_count = box_count;
+ bb_list_type boxes = bb_list_init ();
+ bitmap_type *char_bitmap = XTALLOC1 (bitmap_type);
+ bitmap_type *temp_bitmap = XTALLOC1 (bitmap_type);
+
+ /* The first element of TRANSITIONS is white-to-black.
+ Thereafter, they alternate. */
+ MIN_COL (bb) = NEXT_TRANSITION ();
+ MAX_COL (bb) = NEXT_TRANSITION ();
+
+ /* Get the bitmap of the first transition. `char_bitmap' is
+ either a single character (if the character didn't overlap with
+ a consecutive one in the font specimen) or more than one (if
+ the characters did overlap). For example, it might contain
+ just an `a' this time through the loop (with blank rows above
+ and below, because `a' has neither a descender nor an
+ ascender), then next time a `b', and so on. Or it might
+ contain `ij' (if they overlap in the specimen) instead of `i'
+ this time and `j' next time. */
+ *char_bitmap = extract_subbitmap (image, bb);
+ *temp_bitmap = copy_bitmap (*char_bitmap);
+/*xx*/
+if ((testfileptr = fopen(line_subbitmap_filename, "w")) != NULL)
+print_bitmap(testfileptr, *temp_bitmap);
+else
+printf("Bad file pointer for printing subbitmap.\n");
+fclose(testfileptr);
+if ((testfileptr = fopen(line_bb_subbitmap_filename, "w")) != NULL)
+print_bounded_bitmap(testfileptr, *temp_bitmap, bb);
+else
+printf("Bad file pointer for printing bb-subbitmap.\n");
+fclose(testfileptr);
+
+ /* Unless we've read enough boxes, find the ones in the current
+ character(s), and exit, either: 1) to output a character if the
+ boxes ``finish'' a character, or 2) to exit the routine with
+ false, if they don't. If don't find all the boxes needed to
+ finish a character (i.e., it has vertical white space in it,
+ loop around getting more ``transitions'' until we do. */
+ while (true)
+ {
+ bb_list_type temp_boxes;
+ bounding_box_type previous_bb;
+
+ /* If we've read all the bounding boxes specified (in the IFI
+ file), we're done. */
+ if (box_count == total_boxes_expected)
+ break;
+
+ /* If we've read more boxes than we expected to, trouble. */
+ if (box_count > total_boxes_expected)
+ {
+ WARNING2 ("imageto: Read box #%u but expected only %u",
+ box_count, total_boxes_expected);
+ /* No point in giving this message more than once. */
+ total_boxes_expected = INT_MAX;
+ }
+
+ /* Find the bounding boxes around all the shapes in `temp_bitmap'.
+ (The first time through the loop, `temp_bitmap' is the same
+ as `char_bitmap.') Continuing the above `ij' example, this
+ would result in four bounding boxes (one for the ``dotless''
+ part of the `i,' one for the ``dotless'' part of the `j'
+ and two for each of the dots). */
+ temp_boxes = find_outline_bbs (*temp_bitmap, false, 0, 0);
+
+ /* The subimages we've created all start at column zero. But
+ if there are overlapping characters (the `ij' example
+ above), we want to put the images (for, e.g., `i' and `j')
+ side-by-side instead of overlaying them. So we change the
+ bounding box numbers for `temp_boxes' by adding `bb_offset.' */
+ offset_bb_list (&temp_boxes, bb_offset);
+
+ box_count += BB_LIST_LENGTH (temp_boxes);
+ bb_list_splice (&boxes, temp_boxes);
+
+ /* Break if the number of boxes indicated for the current
+ character(s) coincide with the end of a character. This
+ translates to: if the white column was at the end of some
+ character in the list, exit the loop to output what we've got. */
+ if (box_at_char_boundary_p (image_char_list, *nchars,
+ box_count - previous_box_count))
+ break;
+
+ /* If we're at the end of the image row, return to our caller
+ that we had to quit in the middle of a character. */
+ if (*transitions == BITMAP_WIDTH (image) + 1)
+ { /* Forget that we've seen these boxes. */
+ box_count = previous_box_count;
+ return false;
+ }
+ /* If the character has white vertical space between its
+ parts, e.g., double quotes or ellipses, have to get the
+ rest of its bitmap. */
+ previous_bb = bb;
+ MIN_COL (bb) = NEXT_TRANSITION ();
+ MAX_COL (bb) = NEXT_TRANSITION ();
+
+ /* Leave in the white space between the character parts. */
+ MIN_COL (bb) = MAX_COL (previous_bb);
+
+ free_bitmap (temp_bitmap);
+ *temp_bitmap = extract_subbitmap (image, bb);
+/*xx*/
+if ((testfileptr = fopen(line_subbitmap_filename, "w")) != NULL)
+print_bitmap(testfileptr, *temp_bitmap);
+else
+printf("Bad file pointer for printing subbitmap.\n");
+fclose(testfileptr);
+if ((testfileptr = fopen(line_bb_subbitmap_filename, "w")) != NULL)
+print_bounded_bitmap(testfileptr, *temp_bitmap, bb);
+else
+printf("Bad file pointer for printing bb-subbitmap.\n");
+fclose(testfileptr);
+ if (temp_bitmap == NULL)
+ {
+ WARNING1 ("imageto: Expected more bounding boxes for `%d'",
+ IMAGE_CHARCODE (IMAGE_CHAR (image_char_list, *nchars)));
+ break;
+ }
+
+ /* Next time through the loop, the boxes `temp_bitmap' should
+ be just to the right of the bitmap we've accumulated in
+ `char_bitmap'. This happens if the character has vertical
+ white space between its parts. */
+ bb_offset = BITMAP_WIDTH (*char_bitmap);
+
+ /* When this happens, it usually means that the IFI file
+ didn't specify enough bounding boxes for some character,
+ and so things are out of sync. */
+ if (BITMAP_HEIGHT (*char_bitmap) != BITMAP_HEIGHT (*temp_bitmap))
+ {
+ WARNING ("imageto: Line ended inside a character");
+ break;
+ }
+ bitmap_concat (char_bitmap, *temp_bitmap);
+ } /* while (true) */
+
+ free_bitmap (temp_bitmap);
+
+ /* Convert the bits inside those bounding boxes into one (if not
+ overlapping with another) or more (if overlapping) characters
+ in the GF font. */
+ *nchars += output_chars (boxes, *char_bitmap, h_resolution,
+ image_char_list, *nchars);
+ free_bitmap (char_bitmap);
+ bb_list_free (&boxes);
+ } /* end while (*nchars < nchars_wanted
+ && *transitions != BITMAP_WIDTH (image) + 1) */
+
+ return true;
+}
+
+/* Move all the elements in BB_LIST to the right by OFFSET. */
+
+void
+offset_bb_list (bb_list_type *bb_list, int offset)
+{
+ unsigned this_bb;
+
+ for (this_bb = 0; this_bb < BB_LIST_LENGTH (*bb_list); this_bb++)
+ {
+ bounding_box_type *bb = &BB_LIST_ELT (*bb_list, this_bb);
+ MIN_COL (*bb) += offset;
+ MAX_COL (*bb) += offset;
+ }
+}
+
+
+/* Return true if BB1 and BB2 are equal. */
+
+static boolean
+bb_equal_p (bounding_box_type bb1, bounding_box_type bb2)
+{
+ return
+ MIN_COL (bb1) == MIN_COL (bb2)
+ && MIN_ROW (bb1) == MIN_ROW (bb2)
+ && MAX_COL (bb1) == MAX_COL (bb2)
+ && MAX_ROW (bb1) == MAX_ROW (bb2);
+}
+
+/* For each bounding box in the list BOXES, extract from IMAGE_LINE_BITMAP
+ and turn the resulting bitmap into a single character in the font.
+ The information in IMAGE_CHAR_LIST maps bounding boxes to character codes;
+ consecutive bounding boxes may belong to the same character. For
+ example, `i' will appear twice, once for the dot and once for the
+ stem. We assume that all the bounding boxes for a given character
+ will appear in IMAGE_LINE_BITMAP.
+
+ We return the number of characters (not bounding boxes) found,
+ including characters that were omitted. */
+
+/* Predicate to tell us if we want to actually write the character. */
+#define OUTPUT_CHAR_P(code, image_char) \
+ ((code) >= starting_char && (code) <= ending_char \
+ && !IMAGE_CHAR_OMIT (image_char))
+
+static unsigned
+output_chars (bb_list_type boxes, bitmap_type image_line_bitmap,
+ real h_resolution, image_char_list_type image_char_list,
+ unsigned current_char)
+{
+ static unsigned char_count = 0;
+ int this_box; /* Because we might have to subtract when it's zero. */
+ boolean done[BB_LIST_LENGTH (boxes)];
+
+ /* Since we report (a lot) more information when `print_guidelines' is
+ true, we can fit fewer characters per line. */
+ unsigned nchars_per_line = print_guidelines ? 1 : 11;
+
+ unsigned nchars_written = 0;
+
+ for (this_box = 0; this_box < BB_LIST_LENGTH (boxes); this_box++)
+ done[this_box] = false;
+
+ for (this_box = 0; this_box < BB_LIST_LENGTH (boxes); this_box++)
+ {
+ bounding_box_type bb;
+ bitmap_type bitmap;
+ image_char_type c;
+ charcode_type charcode;
+ bb_list_type bb_list = bb_list_init ();
+
+ /* `done[this_box]' will be set if we get to a bounding box that
+ has already been combined with a previous one, because of
+ an alternating combination. Since we never go backwards, we
+ don't bother to set `done' for every box we look at. */
+ if (done[this_box])
+ continue;
+
+ c = IMAGE_CHAR (image_char_list, current_char++);
+ charcode = IMAGE_CHARCODE (c);
+
+ REPORT ("[");
+
+ /* Only bother to collect the character image if we're going to
+ output it; otherwise, it just wastes a lot of time and space. */
+ if (OUTPUT_CHAR_P (charcode, c))
+ { /* A character consisting of zero bounding boxes is invisible;
+ e.g., a space. We don't want to read any of the bitmap for
+ such a thing. */
+ if (IMAGE_CHAR_BB_COUNT (c) == 0)
+ {
+ BITMAP_HEIGHT (bitmap) = 0;
+ BITMAP_WIDTH (bitmap) = 0;
+ BITMAP_BITS (bitmap) = NULL;
+ bb = (bounding_box_type) { 0, 0, 0, 0 };
+
+ /* Since we're not eating up any bounding boxes,
+ reconsider the current one. */
+ this_box--;
+ }
+ else
+ {
+ bb = BB_LIST_ELT (boxes, this_box);
+ bitmap = extract_subbitmap (image_line_bitmap, bb);
+/*xx*/
+if ((testfileptr = fopen(subbitmap_filename, "w")) != NULL)
+print_bitmap(testfileptr, bitmap);
+else
+printf("Bad file pointer for printing subbitmap.\n");
+fclose(testfileptr);
+if ((testfileptr = fopen(bb_subbitmap_filename, "w")) != NULL)
+print_bounded_bitmap(testfileptr, bitmap, bb);
+else
+printf("Bad file pointer for printing bb-subbitmap.\n");
+fclose(testfileptr);
+ bb_list_append (&bb_list, bb);
+ }
+ }
+
+ while (IMAGE_CHAR_BB_COUNT (c)-- > 1)
+ {
+ unsigned combine_box;
+
+ if (IMAGE_CHAR_BB_ALTERNATING (c))
+ {
+ /* Don't increment `this_box', since it is incremented at
+ the end of the loop, and the next box is part of
+ another character. */
+ combine_box = this_box + 2;
+ /* Don't look at the second box again in the outer loop. */
+ done[combine_box] = true;
+ }
+ else
+ /* Increment `this_box' so can keep combining nonalternating
+ bounding boxes until they are used up or we hit an
+ alternating one. */
+ combine_box = ++this_box;
+
+ /* combine_box starts at 0 and BB_LIST_LENGTH starts at 1, so... */
+ if (combine_box >= BB_LIST_LENGTH (boxes))
+ {
+ WARNING1 ("imageto: Not enough outlines for char %u",
+ (unsigned) charcode);
+ break;
+ }
+
+ if (OUTPUT_CHAR_P (charcode, c))
+ {
+ /* Get the shape to combine with `bitmap'. */
+ bounding_box_type next_bb = BB_LIST_ELT (boxes, combine_box);
+ bitmap_type next_bitmap
+ = extract_subbitmap (image_line_bitmap, next_bb);
+/*xx*/
+if ((testfileptr = fopen(subbitmap_filename, "w")) != NULL)
+print_bitmap(testfileptr, next_bitmap);
+else
+printf("Bad file pointer for printing subbitmap.\n");
+fclose(testfileptr);
+if ((testfileptr = fopen(bb_subbitmap_filename, "w")) != NULL)
+print_bounded_bitmap(testfileptr, next_bitmap, next_bb);
+else
+printf("Bad file pointer for printing bb-subbitmap.\n");
+fclose(testfileptr);
+ bb_list_append (&bb_list, next_bb);
+ combine_images (&bitmap, next_bitmap, &bb, next_bb);
+/*xx*/
+if ((testfileptr = fopen(whole_bitmap_filename, "w")) != NULL)
+print_bitmap(testfileptr, bitmap);
+else
+printf("Bad file pointer for printing whole_bitmap.\n");
+fclose(testfileptr);
+if ((testfileptr = fopen(bb_whole_bitmap_filename, "w")) != NULL)
+print_bounded_bitmap(testfileptr, bitmap, bb);
+else
+printf("Bad file pointer for printing bb_whole_bitmap.\n");
+fclose(testfileptr);
+ free_bitmap (&next_bitmap);
+ }
+ } /* while (IMAGE_CHAR_BB_COUNT (c)-- > 1) */
+
+ if (OUTPUT_CHAR_P (charcode, c))
+ {
+ gf_char_type gf_char;
+
+ if (BITMAP_BITS (bitmap) != NULL)
+ clean_bitmap (&bitmap, bb_list);
+
+ gf_char = bitmap_to_gf_char (bitmap, h_resolution, bb, c);
+ gf_put_char (gf_char);
+
+ /* This and the GF character's bitmap are the same, so we only
+ need to free one of the two. */
+ if (BITMAP_BITS (bitmap) != NULL)
+ free_bitmap (&bitmap);
+ }
+ else
+ {
+ REPORT ("<ignored>"); /* We're ignoring this character. */
+/*xx this_box--;*//* Reconsider the bounding box. */
+ }
+ REPORT1 ("]%c", ++char_count % nchars_per_line ? ' ' : '\n');
+ nchars_written++;
+
+ bb_list_free (&bb_list);
+ } /* for (this_box = 0; this_box < BB_LIST_LENGTH (boxes); this_box++) */
+
+
+ return nchars_written;
+}
+
+/* Remove bits of adjacent characters that may have crept into B because
+ of overlapping characters in the original image. KNOWN_BOXES lists
+ all the known parts of B; if we find other bounding boxes in B, we
+ remove them. */
+
+static void
+clean_bitmap (bitmap_type *b, bb_list_type known_boxes)
+{
+ unsigned test;
+ bb_list_type test_boxes = find_outline_bbs (*b, false, BITMAP_WIDTH (*b), 0);
+
+ if (print_clean_info)
+ REPORT2 ("Cleaning %ux%u bitmap:\n",
+ BITMAP_WIDTH (*b), BITMAP_HEIGHT (*b));
+
+ /* Convert KNOWN_BOXES to the same coordinates as `test_boxes'. */
+ image_to_bitmap_bbs (&known_boxes);
+
+ for (test = 0; test < BB_LIST_LENGTH (test_boxes); test++)
+ {
+ unsigned known;
+ unsigned known_length = BB_LIST_LENGTH (known_boxes);
+ bounding_box_type test_bb = BB_LIST_ELT (test_boxes, test);
+
+ if (print_clean_info)
+ REPORT4 (" checking (%d,%d)-(%d,%d) ... ",
+ MIN_COL (test_bb), MIN_ROW (test_bb),
+ MAX_COL (test_bb), MAX_ROW (test_bb));
+
+ /* If we want to keep `test_bb', it will be one of the elements of
+ BB_LIST. Otherwise, it is a piece of an adjacent character,
+ and we should erase it. */
+ for (known = 0; known < known_length && !bb_equal_p (test_bb,
+ BB_LIST_ELT (known_boxes, known));
+ known++)
+ ;
+
+ if (known == known_length)
+ {
+ unsigned r;
+ int test_bb_width = BB_WIDTH (test_bb);
+
+ assert (test_bb_width > 0);
+
+ if (print_clean_info)
+ REPORT ("clearing.\n");
+
+ for (r = MIN_ROW (test_bb); r <= MAX_ROW (test_bb); r++)
+ {
+ one_byte *row = BITMAP_ROW (*b, r);
+ memset (row + MIN_COL (test_bb), 0, test_bb_width);
+ }
+ }
+ else if (print_clean_info)
+ REPORT ("keeping.\n");
+ }
+}
+
+
+/* Translate the elements of BOXES to the origin, i.e., shift each down
+ by the minimum row and column. We use this in `clean_bitmap' to
+ change bounding boxes in the coordinates of the entire image to the
+ coordinates of the single character we are cleaning. */
+
+static void
+image_to_bitmap_bbs (bb_list_type *boxes)
+{
+ unsigned b;
+ unsigned min_col = UINT_MAX;
+ unsigned min_row = UINT_MAX;
+
+ /* First find the minimum row and column of all the bb's in BOXES. */
+ for (b = 0; b < BB_LIST_LENGTH (*boxes); b++)
+ {
+ bounding_box_type bb = BB_LIST_ELT (*boxes, b);
+
+ assert (MIN_COL (bb) >= 0 && MIN_ROW (bb) >= 0);
+
+ MIN_EQUALS (min_col, MIN_COL (bb));
+ MIN_EQUALS (min_row, MIN_ROW (bb));
+ }
+
+ /* Now translate all the bb's by those minimums. */
+ for (b = 0; b < BB_LIST_LENGTH (*boxes); b++)
+ {
+ bounding_box_type *bb = &BB_LIST_ELT (*boxes, b);
+
+ MIN_COL (*bb) -= min_col;
+ MAX_COL (*bb) -= min_col;
+ MIN_ROW (*bb) -= min_row;
+ MAX_ROW (*bb) -= min_row;
+ }
+}
+
+/* Derive the information necessary to output the font character from
+ the bitmap B, and return it. The resolution of the bitmap is given
+ in pixels per inch as H_RESOLUTION. The bounding box BB encloses the
+ character in the image coordinates. We use BB and the static
+ variables `row_baseline' and `row_height' to determine the
+ positioning of the GF character. */
+
+#define BB_TO_CARTESIAN(x) \
+ (row_height - 1 - (x) - row_baseline \
+ - IMAGE_CHAR_BASELINE_ADJUST (image_char))
+
+static gf_char_type
+bitmap_to_gf_char (bitmap_type b, real h_resolution,
+ bounding_box_type bb, image_char_type image_char)
+{
+ static boolean first = true;
+ static boolean have_tfm_file = false;
+ gf_char_type gf_char;
+ bounding_box_type cartesian_bb;
+ charcode_type charcode = IMAGE_CHARCODE (image_char);
+ boolean have_tfm_width = false;
+
+/*xx*/
+if(b.bitmap){
+if ((testfileptr = fopen(gf_bitmap_filename, "w")) != NULL)
+print_bitmap(testfileptr, b);
+else
+printf("Bad file pointer for printing gf_bitmap.\n");
+fclose(testfileptr);
+if ((testfileptr = fopen(gf_bb_bitmap_filename, "w")) != NULL)
+print_bounded_bitmap(testfileptr, b, bb);
+else
+printf("Bad file pointer for printing gf_bb_bitmap.\n");
+fclose(testfileptr);
+}
+ MIN_ROW (cartesian_bb) = BB_TO_CARTESIAN (MAX_ROW (bb));
+ MAX_ROW (cartesian_bb) = BB_TO_CARTESIAN (MIN_ROW (bb));
+
+ REPORT1 ("%u", charcode);
+
+ GF_CHARCODE (gf_char) = charcode;
+ GF_BITMAP (gf_char) = b;
+ GF_CHAR_MIN_COL (gf_char) = IMAGE_CHAR_LSB (image_char);
+ GF_CHAR_MAX_COL (gf_char) = GF_CHAR_MIN_COL (gf_char) + BITMAP_WIDTH (b);
+ GF_CHAR_MIN_ROW (gf_char) = MIN_ROW (cartesian_bb);
+ GF_CHAR_MAX_ROW (gf_char) = MAX_ROW (cartesian_bb);
+
+ GF_H_ESCAPEMENT (gf_char) = (GF_CHAR_MAX_COL (gf_char)
+ + IMAGE_CHAR_RSB (image_char));
+ if (first)
+ {
+ string tfm_name = kpse_find_tfm (remove_suffix (output_name));
+
+ if (tfm_name)
+ have_tfm_file = tfm_open_input_file (tfm_name);
+ first = false;
+ }
+
+ have_tfm_width = false;
+ if (have_tfm_file)
+ {
+ tfm_char_type *tfm_char = tfm_get_char (charcode);
+ if (tfm_char)
+ {
+ GF_TFM_WIDTH (gf_char) = TFM_FIX_WIDTH (*tfm_char);
+ have_tfm_width = true;
+ }
+ }
+
+ /* If no TFM file, or the TFM file doesn't define this character,
+ use the pixel width for the TFM value. */
+ if (!have_tfm_width)
+ {
+ real width_in_points
+ = GF_H_ESCAPEMENT (gf_char) * POINTS_PER_INCH / h_resolution;
+ GF_TFM_WIDTH (gf_char) = real_to_fix (width_in_points / design_size);
+ }
+
+ if (print_guidelines)
+ REPORT3 (" (%s) %d/%d", IMAGE_CHARNAME (image_char),
+ MIN_ROW (cartesian_bb), MAX_ROW (cartesian_bb));
+
+ return gf_char;
+}
diff --git a/imageto/out-chars.h b/imageto/out-chars.h
new file mode 100644
index 0000000..0b91ade
--- /dev/null
+++ b/imageto/out-chars.h
@@ -0,0 +1,34 @@
+/* out-chars.h: extract the characters from the image.
+
+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. */
+
+#ifndef OUT_CHARS_H
+#define OUT_CHARS_H
+
+#include "image-header.h"
+
+
+/* See out-chars.c. */
+extern int *baseline_list;
+extern boolean print_clean_info, print_guidelines;
+extern unsigned nchars_wanted;
+extern int starting_char, ending_char;
+
+
+extern void write_image_chars (image_header_type, real design_size);
+
+#endif /* not OUT_CHARS_H */
diff --git a/imageto/out-epsf.c b/imageto/out-epsf.c
new file mode 100644
index 0000000..564807c
--- /dev/null
+++ b/imageto/out-epsf.c
@@ -0,0 +1,166 @@
+/* out-epsf.c: output the whole image as an EPS file.
+
+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 "hexify.h"
+#include "report.h"
+
+#include "main.h"
+#include "out-epsf.h"
+
+extern string version_string;
+
+static void pack_scanline (one_byte *, unsigned);
+
+/* Abbreviations for output to `eps_file'. */
+#define OUT_STRING(s) fprintf (eps_file, "%s", s)
+#define OUT_SIMPLE(s) fprintf (eps_file, "%%%%%s\n", s)
+#define OUT_COMMENT(s, v) fprintf (eps_file, "%%%%%s: %s\n", s, v)
+#define OUT1(s, v1) fprintf (eps_file, s, v1)
+#define OUT2(s, v1, v2) fprintf (eps_file, s, v1, v2)
+#define OUT3(s, v1, v2, v3) fprintf (eps_file, s, v1, v2, v3)
+
+/* Write an Encapsulated PostScript file corresponding to the image. */
+
+void
+write_epsf (string output_name, image_header_type image_header)
+{
+ /* Just black & white, or do we have grayscale? */
+ boolean monochrome_p = image_header.depth == 1;
+
+ /* Just for convenience. */
+ unsigned width = image_header.width;
+ unsigned height = image_header.height;
+
+ /* We pack the image tightly if it's monochrome. */
+ unsigned width_used = monochrome_p ? width / 8 + !!(width % 8) : width;
+
+ /* Buffer into which we'll read the image data. */
+ unsigned scanline_count = 0;
+ one_byte *scanline = xmalloc (width);
+
+ /* Open the output file OUTPUT_NAME. */
+ FILE *eps_file = xfopen (output_name, "w");
+
+ OUT_STRING ("%!PS-Adobe-3.0 EPSF-3.0\n");
+ OUT2 ("%%%%BoundingBox: 0 0 %u %u\n", width, height);
+ OUT_COMMENT ("Creator", version_string);
+ OUT_COMMENT ("Title", output_name);
+ OUT_COMMENT ("CreationDate", now ());
+ OUT_COMMENT ("DocumentData", "Clean7Bit");
+ OUT_SIMPLE ("EndComments");
+
+ /* We map the image to the unit square for image(mask) and scale the
+ coordinate system to get back to the original size. I can't grasp
+ how to use the matrix argument to image(mask) to avoid the scaling,
+ but I'm sure it's possible. */
+ OUT2 ("gsave\n %u %u scale\n", width, height);
+
+ /* We need a buffer to hold the string chunks as we read them. It
+ can't be of arbitrary size: it must be an exact multiple of the
+ total number of data characters. Otherwise, we will read past the
+ end of the data. */
+ OUT1 ("/image-buffer %u string def\n", width_used);
+
+ /* If we are monochrome, we use the `imagemask' operator; else `image'. */
+ OUT2 (" %u %u", width, height);
+
+ if (monochrome_p)
+ OUT_STRING (" true"); /* The `invert' argument. */
+ else
+ OUT1 (" %u", image_header.depth); /* bits/sample */
+
+ OUT3 (" [%u 0 0 -%u 0 %u]\n", width, height, height);
+ OUT_STRING ("{currentfile image-buffer readhexstring pop}\n");
+ OUT1 ("%s\n", monochrome_p ? "imagemask" : "image");
+
+ /* Read the image. */
+ while ((*image_get_scanline) (scanline))
+ {
+ string h;
+ unsigned loc;
+
+ scanline_count++;
+ if (scanline_count % 10 == 0)
+ REPORT1 (".%s", scanline_count % 790 == 0 ? "\n" : "");
+
+ /* Monochrome images are output with eight samples/byte; grayscale
+ images are output with one sample/byte. */
+ if (monochrome_p)
+ pack_scanline (scanline, width);
+
+ /* Convert binary to ASCII hexadecimal. */
+ h = hexify (scanline, width_used);
+
+ /* Adobe says lines in EPS files should be no more than 255
+ characters. How silly. */
+ for (loc = 1; loc <= 2 * width_used; loc++)
+ {
+ putc (h[loc - 1], eps_file);
+ if (loc % 255 == 0)
+ putc ('\n', eps_file);
+ }
+
+ free (h);
+ putc ('\n', eps_file);
+ }
+
+ /* Restore the ctm. */
+ OUT_STRING ("grestore\n");
+
+ if (scanline_count != image_header.height)
+ WARNING2 ("Expected %u scanlines, read %u", image_header.height,
+ scanline_count);
+
+ OUT_SIMPLE ("TRAILER");
+ OUT_SIMPLE ("EOF");
+}
+
+/* Change the one bit/byte representation (call each byte a `cell') of
+ LENGTH bits in DATA to be eight bits/byte. Pad the last byte with
+ zero. We don't change those bytes beyond the end of packed portion,
+ thus assuming they are not looked at. */
+
+static void
+pack_scanline (one_byte *data, unsigned length)
+{
+ unsigned cell; /* Which bit in the original data we're on. */
+ unsigned packing_loc = 0; /* Which byte we're currently packing. */
+ unsigned packing_bit = 8; /* How much to shift. */
+
+ /* The very first cell has to be treated specially, because we must
+ initialize it with itself shifted left (if we're going to use data
+ in place, that is.) */
+ data[0] <<= 7;
+
+ for (cell = 0; cell < length; cell++)
+ {
+ packing_bit--;
+ data[packing_loc] |= data[cell] << packing_bit;
+ if (packing_bit == 0)
+ {
+ packing_bit = 8;
+ packing_loc++;
+
+ /* After the first byte, we can just clear the byte at
+ `packing_loc', since `cell' has already moved beyond it. */
+ data[packing_loc] = 0;
+ }
+ }
+}
diff --git a/imageto/out-epsf.h b/imageto/out-epsf.h
new file mode 100644
index 0000000..c664772
--- /dev/null
+++ b/imageto/out-epsf.h
@@ -0,0 +1,28 @@
+/* out-epsf.h: output the whole image as an EPS file.
+
+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. */
+
+#ifndef OUT_EPSF_H
+#define OUT_EPSF_H
+
+#include "image-header.h"
+
+
+/* Output an EPS file for the image with header H to OUTPUT_NAME. */
+extern void write_epsf (string output_name, image_header_type h);
+
+#endif /* not OUT_EPSF_H */
diff --git a/imageto/out-strips.c b/imageto/out-strips.c
new file mode 100644
index 0000000..a43a411
--- /dev/null
+++ b/imageto/out-strips.c
@@ -0,0 +1,94 @@
+/* out-strips.c: cut the entire image into strips.
+
+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 "gf.h"
+#include "report.h"
+
+#include "main.h"
+#include "out-strips.h"
+
+/* Output a ``font'' in which each ``character'' is a constant number of
+ scanlines from the image. This might use less than resources than
+ the giant PostScript file that -epsf outputs.
+
+ We only output the GF characters here; we assume the postamble and
+ preamble are written by the caller. */
+
+void
+write_chars_as_strips (image_header_type image_header, real design_size)
+{
+ dimensions_type char_dimens;
+ gf_char_type gf_char;
+ unsigned gf_row;
+ unsigned lines_per_char;
+ one_byte *scanline;
+ real width_in_points;
+ boolean first_char = true;
+ unsigned scanline_count = 0;
+
+ /* Set up for the first character. We divide the image into 256 parts,
+ each of which will turn into one ``character''. */
+ lines_per_char = image_header.height / 256 + 1;
+ GF_CHARCODE (gf_char) = 0;
+ DIMENSIONS_WIDTH (char_dimens) = image_header.width;
+ DIMENSIONS_HEIGHT (char_dimens) = lines_per_char;
+ GF_BITMAP (gf_char) = new_bitmap (char_dimens);
+ GF_CHAR_MIN_COL (gf_char) = GF_CHAR_MIN_ROW (gf_char) = 0;
+ GF_CHAR_MAX_COL (gf_char) = DIMENSIONS_WIDTH (char_dimens);
+ GF_CHAR_MAX_ROW (gf_char) = DIMENSIONS_HEIGHT (char_dimens) - 1;
+
+ /* We aren't going to have any side bearings. */
+ GF_H_ESCAPEMENT (gf_char) = DIMENSIONS_WIDTH (char_dimens);
+ width_in_points = DIMENSIONS_WIDTH (char_dimens) * POINTS_PER_INCH
+ / (real) image_header.hres;
+ GF_TFM_WIDTH (gf_char) = real_to_fix (width_in_points / design_size);
+
+
+ /* Read the image. */
+ while (true)
+ {
+ if (scanline_count % lines_per_char == 0)
+ {
+ /* We get here when scanline_count == 0, and we haven't read
+ anything, so we can't write anything. */
+ if (!first_char)
+ {
+ gf_put_char (gf_char);
+ REPORT2 ("[%u]%c", GF_CHARCODE (gf_char),
+ (GF_CHARCODE (gf_char) + 1) % 13 ? ' ' : '\n');
+ GF_CHARCODE (gf_char)++;
+ }
+ else
+ first_char = false;
+ gf_row = 0;
+ }
+
+ scanline = BITMAP_BITS (GF_BITMAP (gf_char))
+ + gf_row * DIMENSIONS_WIDTH (char_dimens);
+ if (!(*image_get_scanline) (scanline)) break;
+
+ scanline_count++;
+ gf_row++;
+ }
+
+ if (scanline_count != image_header.height)
+ WARNING2 ("Expected %u scanlines, read %u", image_header.height,
+ scanline_count);
+}
diff --git a/imageto/out-strips.h b/imageto/out-strips.h
new file mode 100644
index 0000000..401c124
--- /dev/null
+++ b/imageto/out-strips.h
@@ -0,0 +1,27 @@
+/* out-strips.h: cut the image into strips.
+
+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. */
+
+#ifndef OUT_STRIPS_H
+#define OUT_STRIPS_H
+
+#include "image-header.h"
+
+
+extern void write_chars_as_strips (image_header_type, real design_size);
+
+#endif /* not OUT_STRIPS_H */
diff --git a/imageto/strips.tex b/imageto/strips.tex
new file mode 100644
index 0000000..1b7a3ee
--- /dev/null
+++ b/imageto/strips.tex
@@ -0,0 +1,85 @@
+% TeX file to display a ``font'' made from imagetofont's -strips option.
+
+% Set up our font.
+\message{Fontname? }
+\read -1 to \testfontname
+\font\testfont = \testfontname\space
+\testfont
+
+% \monthname produces the name of the month, abbreviated to three
+% letters. The primitive \month should never be zero.
+%
+\def\monthname{%
+ \ifcase\month
+ \or Jan\or Feb\or Mar\or Apr\or May\or Jun%
+ \or Jul\or Aug\or Sep\or Oct\or Nov\or Dec%
+ \fi
+}%
+
+% \timestring produces the current time, in a format like `1:14 p.m.'.
+%
+\def\timestring{\begingroup
+ \count0 = \time
+ \divide\count0 by 60
+ \count2 = \count0 % The hour, from zero to 23.
+ %
+ \count4 = \time
+ \multiply\count0 by 60
+ \advance\count4 by -\count0 % The minute, from zero to 59.
+ % But we need the minutes with a leading zero, if necessary.
+ \ifnum\count4<10
+ \toks1 = {0}%
+ \else
+ \toks1 = {}%
+ \fi
+ %
+ % Convert the hour into `a.m.' or `p.m.', and make it mod 12.
+ \ifnum\count2<12
+ \toks0 = {a.m.}%
+ \else
+ \toks0 = {p.m.}%
+ \advance\count2 by -12
+ \fi
+ %
+ % If it's midnight, call it `12', not `0'.
+ \ifnum\count2=0
+ \count2 = 12
+ \fi
+ %
+ % Produce the output.
+ \number\count2:\the\toks1 \number\count4 \thinspace \the\toks0
+\endgroup}%
+%
+%
+% \timestamp produces a text string for the whole thing like
+% `23 Apr 1964 1:14 p.m.'.
+%
+\def\timestamp{\number\day\space\monthname\space\number\year\quad\timestring}%
+
+\nopagenumbers
+\headline = {\hfil \tt \testfontname \quad \timestamp}
+
+% Use as much of the page as we dare.
+\hoffset = -5pc \hsize = 49pc
+\voffset = -5pc \vsize = 64pc
+
+% Don't worry if there's no good place to break pages.
+\vbadness = 10000
+
+% No leading between ``lines''.
+\offinterlineskip
+
+% Don't worry if the font doesn't have exactly 256 characters, since
+% roundoff error makes this likely.
+\tracinglostchars = 0
+
+
+\count255 = 0
+\loop
+ %\setbox0 = \hbox{\char\count255}
+ \leftline{\char\count255}
+ \advance\count255 by 1
+ \ifnum\count255<256
+\repeat
+
+\end
diff --git a/imageto/version.c b/imageto/version.c
new file mode 100644
index 0000000..b39f56a
--- /dev/null
+++ b/imageto/version.c
@@ -0,0 +1 @@
+char *version_string = "imageto version REPLACE-WITH-VERSION";
diff --git a/lib/ChangeLog b/lib/ChangeLog
new file mode 100644
index 0000000..0f3ff5d
--- /dev/null
+++ b/lib/ChangeLog
@@ -0,0 +1,1414 @@
+Tue Dec 26 10:16:08 1995 Kathy Hargreaves <kathy@cs.umb.edu>
+
+ * identity.c (get_identity): Added.
+
+Sun Nov 26 12:47:00 1995 Kathy Hargreaves <karl@cs.umb.edu>
+
+ * bb-outline.c: (find_outline_bbs): Doc fix.
+
+ * edge.c: (next_unmarked_outline_edge): Doc fix.
+
+Fri Nov 24 05:48:20 1995 Kathy Hargreaves <karl@cs.umb.edu>
+
+ * concat*.c: made arguments const_string's to conform to .h files.
+ Call assert on the arguments, that they aren't NULL, because it
+ makes strlen blow up if they are. Set answer to NULL, and only
+ work on it if all the arguments are non-NULL.
+
+Thu Nov 23 09:08:00 1995 Kathy Hargreaves <karl@cs.umb.edu>
+
+ * font.c: (get_font): replaced find_tfm_filename with kpse_find_tfm.
+
+Thu Aug 24 16:00:46 1995 Karl Berry <karl@cs.umb.edu>
+
+ * GNUmakefile (c_only): strstr is now in kpathsea.
+
+Sat May 27 13:52:19 1995 Karl Berry <karl@cs.umb.edu>
+
+ * GNUmakefile (c_only): atou is in kpathsea.
+
+Fri Apr 14 15:56:43 1995 Karl Berry <karl@cs.umb.edu>
+
+ * GNUmakefile (c_only): Remove xfseek and xftell.
+
+Mon Oct 24 19:04:34 1994 Karl Berry <karl@cs.umb.edu>
+
+ * GNUmakefile (c_only): basename is in kpathsea now.
+
+Sun May 1 15:31:10 1994 Karl Berry (karl@cs.umb.edu)
+
+ * vector.c (Vangle): Declare const.
+
+Thu Sep 30 10:13:45 1993 Karl Berry (karl@cs.umb.edu)
+
+ * str-to-bit.c (string_to_bitmap): Call close_font.
+
+Sun Aug 1 09:56:42 1993 Karl Berry (karl@cs.umb.edu)
+
+ * Most *.c: Include files now in kpathsea.
+
+ * GNUmakefile (c_only): Add statistics, remove many things now in
+ kpathsea.
+
+Tue Jul 27 09:24:08 1993 Karl Berry (karl@cs.umb.edu)
+
+ * GNUmakefile (c_only): Remove dir-p and find-suffix (now in kpathsea).
+
+Fri May 21 13:45:30 1993 Karl Berry (karl@cs.umb.edu)
+
+ * gmalloc.c (my_memmove): New routine, since ISC doesn't have a
+ real memmove.
+
+Thu May 20 19:11:05 1993 Karl Berry (karl@cs.umb.edu)
+
+ * gmalloc.c: New file from the malloc distribution (plus a few
+ edits).
+ * GNUmakefile (malloc): Define to be gmalloc, and toss the old
+ malloc.c.
+
+Thu Apr 22 17:03:53 1993 Karl Berry (karl@cs.umb.edu)
+
+ * remove-suffx.c (remove_suffix): If no suffix, return the string,
+ not NULL.
+
+Tue Apr 6 19:58:45 1993 Karl Berry (karl@cs.umb.edu)
+
+ * malloc.c (getpagesize.h): Do not include.
+ (memalign, valloc): Remove, since we don't need them.
+
+ * filename.c (find_tfm_filename): Call extend_filename to get the
+ `.tfm', instead of just concatenating. Not sure if this is a good
+ idea, but periods in font names are problematic all over, I think.
+
+Tue Mar 16 07:47:38 1993 Karl Berry (karl@cs.umb.edu)
+
+ * fontmap.c (map_lookup): Don't extend the filename if there was
+ no suffix.
+
+Wed Mar 3 06:20:09 1993 Karl Berry (karl@cs.umb.edu)
+
+ * xftell.c (xftell): Declare as unsigned long.
+
+Mon Jan 18 15:43:02 1993 Karl Berry (karl@cs.umb.edu)
+
+ * xrealloc.c: Doc fix.
+
+Sun Jan 3 19:36:39 1993 Karl Berry (karl@cs.umb.edu)
+
+ * pathsrch.c (R_OK): Defined in the config files now.
+
+Fri Dec 11 15:00:31 1992 Karl Berry (karl@cs.umb.edu)
+
+ * font.c (print_char): Change ctype references to use uppercase macros.
+ * libfile.c (libfile_line),
+ * pathsrch.c (absolute_p),
+ * str-to-bit.c (string_to_bitmap),
+ * float-ok.c (float_ok),
+ * integer-ok.c (integer_ok),
+ * charspec.c (xparse_charspec): Likewise.
+
+Sun Nov 29 17:05:40 1992 Karl Berry (karl@cs.umb.edu)
+
+ * xmessage.c [X_DISPLAY_MISSING]: Conditionalize whole file.
+
+ * numtoa.c (xdtoa): Rename from `dtoa', to avoid Linux conflict.
+ (awasthi@cps.msu.edu)
+
+Tue Nov 17 09:25:58 1992 Karl Berry (karl@cs.umb.edu)
+
+ * hexify.c: Doc fix.
+
+Mon Nov 16 16:08:39 1992 Karl Berry (karl@cs.umb.edu)
+
+ * malloc.c (calloc): Complain if the malloc fails.
+
+Tue Oct 27 12:56:15 1992 Karl Berry (karl@cs.umb.edu)
+
+ * Version 0.6.
+
+Sun Oct 25 06:26:42 1992 Karl Berry (karl@cs.umb.edu)
+
+ * getopt.c: New version.
+
+Thu Oct 22 17:58:12 1992 Karl Berry (karl@cs.umb.edu)
+
+ * make-suffix.c: Doc fix.
+
+Tue Oct 20 11:57:57 1992 Karl Berry (karl@cs.umb.edu)
+
+ * filename.c (find_{gf,pk,tfm}_filename): Just concatenate the
+ suffix onto the main font name, don't replace a suffix.
+
+Mon Oct 5 10:07:59 1992 Karl Berry (karl@cs.umb.edu)
+
+ * report.c (report_file): New variable.
+
+Sun Oct 4 09:13:24 1992 Karl Berry (karl@cs.umb.edu)
+
+ * bb-list.c: New file, from bb-outline.c.
+ * GNUmakefile (c_only): Add it.
+ * bb-outline.c: Change calls and decls for new improved names.
+
+Sat Oct 3 16:58:38 1992 Karl Berry (karl@cs.umb.edu)
+
+ * bb-outline.c: Doc fix.
+
+Tue Sep 22 12:46:49 1992 Karl Berry (karl@cs.umb.edu)
+
+ * malloc.c (realloc): abort if we can't malloc enough memory to do
+ the realloc.
+
+ * bitmap.c (bb_ensure_bounds): new routine.
+ (extract_subbitmap): call it.
+
+Mon Sep 21 12:00:35 1992 Karl Berry (karl@cs.umb.edu)
+
+ * malloc.c: define NO_NEW_HANDLER.
+
+Thu Sep 3 09:31:06 1992 Karl Berry (karl@hayley)
+
+ * Version 0.5.
+
+Thu Aug 27 09:06:25 1992 Karl Berry (karl@hayley)
+
+ * getopt.c: update from MIT.
+
+Mon Aug 24 15:50:03 1992 Karl Berry (karl@hayley)
+
+ * rand.c (k_rand): use Ghostscript's algorithm exactly, to avoid
+ overflow problems.
+
+ * rand.c (seed_rand): Our simplification was a loser if the
+ state ever became zero, so set the state to the seed + 1, and
+ subtract again before output.
+
+Wed Aug 19 07:10:12 1992 Karl Berry (karl@hayley)
+
+ * charspec.c: doc fix.
+
+Mon Aug 17 15:43:42 1992 Karl Berry (karl@hayley)
+
+ * encoding.c: doc fix.
+
+Mon Aug 10 11:11:52 1992 Karl Berry (karl@hayley)
+
+ * rand.c (x): change the default seed to 1.
+
+Mon Jul 27 15:29:33 1992 Karl Berry (karl@hayley)
+
+ * charspec.c (xparse_charspec): use an `int' while figuring out
+ the charcode.
+
+Sat Jul 25 14:38:23 1992 Karl Berry (karl@hayley)
+
+ * getopt.c: new version.
+
+ * pathsrch.c (expand_tilde): cast the result of getpwnam.
+
+Sat Jul 18 16:35:41 1992 Karl Berry (karl@hayley)
+
+ * edge.c: add ^L's.
+
+Fri Jul 3 15:26:12 1992 Karl Berry (karl@hayley)
+
+ * charspec.c (xparse_charspec): if arg is one character long, and
+ undefined in the encoding, use its value in C.
+
+Fri Jun 26 16:53:39 1992 Karl Berry (karl@hayley)
+
+ * charspec.c: new file.
+ * GNUmakefile: add it.
+
+Thu Jun 25 07:04:49 1992 Karl Berry (karl@hayley)
+
+ * pathsrch.c (readable) [ENAMETOOLONG]: conditionalize the test
+ for doing our own truncating, since it appears not all systems
+ have ENAMETOOLONG.
+
+Sun Jun 14 08:11:32 1992 Karl Berry (karl@hayley)
+
+ * font.c (get_font): remove computation of NCHARS (and reading of
+ all the TFM chars).
+
+ * str-lcase.c (str_to_lower): assert the arg is non-null.
+
+Sat Jun 13 16:28:08 1992 Karl Berry (karl@hayley)
+
+ * libfile.c (libfile_start): return the FILE * we open.
+
+Sat Jun 13 13:52:30 1992 Kathy Hargreaves (kathy@hayley)
+
+ * encoding.c (DEFAULT_ENCODING): moved to .h file.
+
+Sat Jun 13 09:24:12 1992 Karl Berry (karl@hayley)
+
+ * encoding.c: include `str-lcase.h', not `str-casefold.h'.
+
+ * xmessage.c (x_message): cast initializer in `popup_args' to
+ avoid warning.
+
+ * str-to-bit.c (string_to_bitmap): `TFM_FONT_PARAMETER' is now
+ `TFM_FONTDIMEN'.
+
+ * pathsrch.c (absolute_p): add parens to stop GCC 2's stupid warning.
+
+ * encoding.c: change for new list fn names.
+ * font.c: likewise.
+
+ * list.c (new_list): rename to `list_init', and rewrite to use
+ accessor macros.
+ (append_element): rename to `list_append', and likewise rewrite.
+ (list_free): new routine.
+
+Sun Jun 7 17:25:43 1992 Karl Berry (karl@hayley)
+
+ * encoding.c (coding_scheme_to_filename): rewrite to avoid
+ sentinel boolean, lowercasing the passed codingscheme more than
+ once, etc.
+
+ * str-casefold.c (str_to_lower): rewrite to use ? :.
+ (str_to_upper): remove this.
+ Rename to str-lcase.c.
+ * GNUmakefile (c_only): change str-casefold to str-lcase.
+
+Sun Jun 7 14:39:09 1992 Kathy Hargreaves (kathy@hayley)
+
+ * bb-outline.c (find_outline_bbs): don't calculate edge if it's an
+ interior pixel.
+
+ * bb-outline.c (find_outline_bbs): deleted avoiding finding a
+ bounding box which corresponds to a counterform by not looking
+ inside existing bounding boxes.
+ Added finding the bounding box for a counterform (i.e., marking
+ its edges) but not adding it to the list unless find_all is true.
+ Changed find_all to find_inner.
+
+Sun Jun 7 08:55:31 1992 Karl Berry (karl@hayley)
+
+ * GNUmakefile (c_only): add `str-to-bit'.
+ * font.c (string_to_bitmap): extract the interword space out of
+ the TFM information, instead of expecting it in the main font
+ structure. Also, move this fn to its own file, `str-to-bit.c'.
+
+ * float-ok.c (float_ok): don't accept the empty string, or just a
+ sign, or just a sign and a `.', etc.
+ * integer-ok.c (integer_ok): likewise.
+
+Thu Jun 4 08:11:36 1992 Karl Berry (karl@hayley)
+
+ * pathsrch.c (absolute_p): `k./' should not be considered
+ explicitly relative.
+
+Tue Jun 2 11:40:32 1992 Karl Berry (karl@hayley)
+
+ * encoding.c (encoding_number): don't crash if NAME is NULL.
+
+Mon Jun 1 15:16:15 1992 Karl Berry (karl@hayley)
+
+ * GNUmakefile (c_only): add `integer-ok' and `float-ok'.
+ * {integer,float}-ok.c: new files.
+
+ * libfile.c (libfile_start): use extend_filename.
+
+ * encoding.c (read_encoding_file): initialize the return structure
+ after we know the file exists.
+
+Fri May 29 08:29:26 1992 Karl Berry (karl@hayley)
+
+ * getopt*.c: new versions.
+
+Sat May 23 15:51:53 1992 Karl Berry (karl@hayley)
+
+ * charcode.c (parse_charcode): ensure there are no extra
+ characters at the end of the charcode; change return type to
+ charcode_type.
+ (xparse_charcode): change return type.
+
+Sat May 23 12:33:32 1992 Kathy Hargreaves (kathy@hayley)
+
+ * str-casefold.c (str_to_lower): added variable `length'; put 0 at
+ end of return string.
+
+Sat May 23 06:27:28 1992 Karl Berry (karl@hayley)
+
+ * dir-p.c (leaf_dir_p): remove; `expand_subdir' now calls stat
+ itself, for efficiency.
+
+ * pathsrch.c (expand_subdir): rewrite to always look for subdirs.
+ (initialize_path_list): check for the dir-ness of `foo' in
+ `foo//'. This change makes symlinks under `foo' be considered.
+
+ * pathsrch.c (add_directory): don't check for the arg being a
+ directory.
+ (initialize_path_list): check here for the directory-ness of a
+ path element.
+ (expand_subdir): check here, too.
+
+ * pathsrch.c (expand_subdir): call closedir after we read the
+ directory contents.
+
+Thu May 21 11:40:53 1992 Karl Berry (karl@hayley)
+
+ * hexify.c (hexify): take a block of memory and a length, instead
+ of a varstring.
+
+Tue May 19 16:43:43 1992 Kathy Hargreaves (kathy@hayley)
+
+ * line.c (read_line): return a string if not at EOF.
+
+Sat May 16 21:22:57 1992 Kathy Hargreaves (kathy@hayley)
+
+ * varstring.c (vs_concat): added.
+
+Fri May 15 10:22:27 1992 Karl Berry (karl@hayley)
+
+ * getopt.c: new version.
+
+Thu May 14 22:05:10 1992 Karl Berry (karl@claude.cs.umb.edu)
+
+ * rand.c (srand): -> seed_rand, to avoid header conflicts.
+ (rand): -> k_rand, same reason.
+
+Sun May 10 10:05:36 1992 Karl Berry (karl@hayley)
+
+ * encoding.c (coding_scheme_to_filename): don't xstrdup the return
+ value.
+ (DEFAULT_ENCODING): new macro.
+
+Fri May 8 15:38:38 1992 Karl Berry (karl@hayley)
+
+ * pathshare from dvips.
+
+Thu May 7 16:44:14 1992 Karl Berry (karl@hayley)
+
+ * GNUmakefile (c_only): add dlsym.
+ * dlsym.c: new file.
+
+Wed May 6 10:08:09 1992 Karl Berry (karl@hayley)
+
+ * bitmap.c (bitmap_find_transitions): don't look outside the
+ current row when it's only one pixel long.
+
+Tue May 5 08:46:48 1992 Karl Berry (karl@hayley)
+
+ * dir-p.c: doc fix.
+
+Sat May 2 07:51:53 1992 Karl Berry (karl@hayley)
+
+ * pathsrch.c (add_directory): use ?:.
+
+Thu Apr 30 08:52:34 1992 Karl Berry (karl@hayley)
+
+ * pathsrch.c (parse_envpath): expand the ~ here;
+ (add_directory): not here.
+
+ * pathsrch.c (expand_tilde): free space for the login name.
+
+ * dir-p.c (leaf_dir_p): use stat, not xlstat, so we don't bomb
+ out on missing directories in paths, and so we get info about
+ the (potential) dir, not the link.
+
+Tue Apr 21 07:44:52 1992 Karl Berry (karl@hayley)
+
+ * bitmap.c (bitmap_find_transitions): use XTALLOC1.
+ * font.c (get_char): likewise.
+
+Mon Apr 20 08:35:23 1992 Karl Berry (karl@hayley)
+
+ * pathsrch.c: doc fix.
+
+ * malloc.c: don't include config.h.
+ (my_bzero, my_bcopy): new routines to simplify things.
+
+Sat Apr 18 12:22:29 1992 Kathy Hargreaves (kathy@hayley)
+
+ * str-casefold.c: added.
+
+ * encoding.c (coding_scheme_to_filename): compare case-folded
+ versions of the coding scheme and the mapped scheme.
+
+Wed Apr 15 15:23:20 1992 Karl Berry (karl@hayley)
+
+ * make-output.c: rename to `extend-fname.c'; rename the fn to
+ `extend_filename'.
+ * GNUmakefile (c_only): analogously.
+
+Wed Apr 15 13:20:11 1992 Kathy Hargreaves (kathy@hayley)
+
+ * encoding.c (coding_scheme_to_filename): changed some variable
+ names; added `mapped_coding' and set it to a second call to
+ strtok with `mapping'.
+
+Tue Apr 14 13:46:45 1992 Karl Berry (karl@hayley)
+
+ * scaled-num.c (scaled_to_real): as below.
+
+Sun Apr 12 15:06:58 1992 Karl Berry (karl@hayley)
+
+ * scaled-num.c (real_to_scaled): simplify to just multiply the
+ real by SCALED_UNITY.
+
+Fri Apr 10 16:36:33 1992 Karl Berry (karl@hayley)
+
+ * concat.c: put concat[345] in separate files.
+ * GNUmakefile (c_only): update.
+
+ * filename.c: remove prefix/suffix routines.
+ ({make-{output,prefix,suffix},remove-suffx,find-suffix}.c): new files.
+ * GNUmakefile (c_only): update.
+
+ * pathsrch.c (initialize_path_list): remove cwd_first_p.
+ * filename.c (find_*_filename): change calls.
+ * libfile.c (libfile_start): change call.
+
+Mon Apr 6 13:46:36 1992 Kathy Hargreaves (kathy@fosse)
+
+ * encoding.c (encoding_scheme_to_filename): added.
+
+Fri Apr 3 13:17:22 1992 Karl Berry (karl@hayley)
+
+ * rand.c: new file.
+ * GNUmakefile (c_only): include it.
+
+Wed Apr 1 14:14:01 1992 Karl Berry (karl at hayley)
+
+ * (pathshare from web2c)
+
+ * filename.c (make_output_filename): don't duplicate the input
+ string, just return it.
+
+ * filename.c (remove_suffix): remove.
+
+ * edge.c: new file.
+ * GNUmakefile (c_only): add it.
+ * bb-outline.c: remove edge stuff in favor of this new file.
+
+Tue Mar 31 13:35:51 1992 Karl Berry (karl at hayley)
+
+ * bitmap.c (bitmap_find_transitions): handle a row with a single
+ black pixel at the end correctly.
+
+Sun Mar 29 10:58:27 1992 Karl Berry (karl at hayley)
+
+ * xrealloc.c (xrealloc): cast the ptr.
+
+ * file-input.c (get_n_bytes): had args switched to fatal.
+
+ * bb-outline.c (is_outline_edge): remove the assertion that we're
+ at a valid pixel, since it's half-implied by the types, anyway.
+
+ * GNUmakefile (malloc.o): remove the special rule and vars.
+ * malloc.c [STDC_HEADERS | USG]: add the former for memset etc.
+
+Sat Mar 28 07:49:09 1992 Karl Berry (karl at hayley)
+
+ * malloc.c: new version, from libg++ 2.0.
+
+ * GNUmakefile (malloc_stats): don't define this.
+
+ * Version 0.4.
+
+ * Change copyright years to 1992 only.
+
+Wed Mar 25 08:37:28 1992 Karl Berry (karl at hayley)
+
+ * GNUmakefile (c_only): add fmod.
+ * fmod.c: new file.
+
+Thu Mar 19 07:47:30 1992 Karl Berry (karl at hayley)
+
+ * pathsearch.c, libfile.c, filename.c: include paths.h.
+
+ * pathsearch.c: rename to pathsrch.c; new version.
+
+Wed Mar 11 10:03:12 1992 Karl Berry (karl at hayley)
+
+ * bitmap.c (bitmap_find_transitions): handle the pixel at the end
+ of the row specially, unfortunately.
+
+Tue Mar 10 12:17:09 1992 Kathy Hargreaves (kathy at hayley)
+
+ * libfile.c (libfile_start): use find_suffix instead of finding a
+ dot position.
+
+Mon Mar 9 16:42:49 1992 Kathy Hargreaves (kathy at hayley)
+
+ * filename.c (make_stem_suffix): remove suffix from name before
+ adding stem_suffix and putting suffix back on.
+
+ * filename.c (make_stem_suffix): don't add a dot if no suffix.
+
+ * filename.c (make_stem_suffix): added.
+
+Sun Mar 8 17:08:06 1992 Kathy Hargreaves (kathy at hayley)
+
+ * filename.c (make_output_filename): put dot between NAME and
+ DEFAULT_SUFFIX.
+
+Sun Mar 8 08:37:46 1992 Karl Berry (karl at fosse)
+
+ * numtoa.c (dtoa): rename from ftoa.
+
+ * strstr.c: new file.
+ GNUmakefile (c_only): add strstr.
+
+Sat Mar 7 17:00:44 1992 Kathy Hargreaves (kathy at hayley)
+
+ * filename.c (sizeless_font_name): removed.
+
+Sat Mar 7 13:21:33 1992 Karl Berry (karl at fosse)
+
+ * xmessage.c: include xmessage.h.
+
+ * GNUmakefile (c_only): remove statistics; we never use it.
+
+ * pathsearch.c: add prototypes for the subroutines.
+
+ * line.c: include line.h.
+
+ * bb-outline.c (find_outlines_bbs): rename parameters to avoid
+ shadow warnings.
+
+Sat Mar 7 09:14:00 1992 Karl Berry (karl at hayley)
+
+ * GNUmakefile (files, headers, sources): replace with `c_and_h', etc.
+
+ * scaled-num.c (print_scaled): use putchar instead of printf where
+ possible.
+
+Wed Mar 4 10:40:02 1992 Karl Berry (karl at hayley)
+
+ * filename.c (remove_suffix): don't include the `.' in what we
+ return.
+
+Tue Mar 3 16:28:38 1992 Karl Berry (karl at hayley)
+
+ * filename.c (find_suffix): new routine.
+ (remove_suffix, make_output_filename, make_suffix): write in terms
+ of it.
+
+Sun Mar 1 16:33:49 1992 Kathy Hargreaves (kathy at hayley)
+
+ * filename.c (make_output_file): use concat instead of make_suffix.
+
+Sun Mar 1 15:17:28 1992 Karl Berry (karl at hayley)
+
+ * GNUmakefile (files): add bb-outline.
+
+Sun Mar 1 14:48:41 1992 Kathy Hargreaves (kathy at hayley)
+
+ * filename.c (make_output_file): added.
+
+Mon Feb 24 08:38:56 1992 Karl Berry (karl at hayley)
+
+ * pathsearch.c (truncate_pathname): separate this out from `readable'.
+
+ * concat.c dir-p.c file-p.c pathsearch.c xmalloc.c xopendir.c
+ xrealloc.c xstat.c xstrdup.c: redo with (un)prototype macros.
+
+Wed Feb 19 10:00:35 1992 Karl Berry (karl at hayley)
+
+ * varstring.c (vs_set_char): set the allocated field after we
+ allocate more space.
+
+ * hexify.c (hexify): add 'a' to each hex char to make it visible
+ ASCII; shift the upper nybble down before adding.
+
+Mon Feb 17 07:38:27 1992 Karl Berry (karl at hayley)
+
+ * filename.c (sizeless_font_name): new routine.
+
+ * line.c (read_line): use vs_append_char, and generally simplify.
+
+ * varstring.c (vs_append_char): don't append a null afterwards.
+
+ * GNUmakefile (files): add it.
+ * hexify.c: new file.
+
+Sun Feb 16 10:31:41 1992 Karl Berry (karl at hayley)
+
+ * pathsearch.c (readable): keep track of the component lengths
+ properly; do the second test on the new name, not the old.
+
+Sat Feb 15 16:10:30 1992 Karl Berry (karl at hayley)
+
+ * pathsearch.c (READABLE): redo the macro as a function, and
+ truncate the pathname if necessary.
+
+Fri Feb 14 07:26:35 1992 Karl Berry (karl at hayley)
+
+ * varstring.c (vs_append_char): use VS_USED instead of strlen.
+ (vs_init): initialize VS_USED to zero.
+ (vs_set_char): set VS_USED.
+ All routines: rename `VS_LENGTH to `VS_ALLOCATED'.
+
+ * varstring.c (vs_free): new routine.
+
+ * math.c (acosd): clear errno before testing it.
+
+Thu Feb 13 13:32:54 1992 Karl Berry (karl at hayley)
+
+ * pathsearch.c (READABLE): call it readable if the error is
+ ENAMETOOLONG; include <errno.h> and declare errno if that is
+ undefined.
+
+Sun Feb 2 16:08:44 1992 Karl Berry (karl at hayley)
+
+ * filename.c (find_{gf,pk}_filename): allocate enough space for
+ the null sprintf writes.
+
+Sat Feb 1 14:53:39 1992 Karl Berry (karl at hayley)
+
+ * filename.c (depath): remove.
+
+ * pathsearch.c (initialize_path_list): subdirectories are now
+ indicated by // terminating a path element, instead of as
+ a separate envvar/path.
+ * filename.c (find*filename): remove subdirectory stuff.
+ * libfile.c (libfile_start): likewise.
+
+Mon Jan 20 11:09:10 1992 Kathy Hargreaves (kathy at hayley)
+
+ * filename.c (depath): added this routine to take the path off the
+ front of a filename.
+
+ * filename.c (make_prefix): added this routine to add a prefix to
+ a filename which may or may not be the full pathname.
+
+Wed Jan 15 16:57:36 1992 Kathy Hargreaves (kathy at hayley)
+
+ * libfile.c (libfile_start): when FATAL, report `name', not it
+ concatenated with the default suffix.
+
+Wed Jan 15 13:01:30 1992 Karl Berry (karl at hayley)
+
+ * GNUmakefile (c_only): remove xchdir and xgetcwd, as we don't
+ need them anymore.
+ * pathsearch.c: changes from TeX.
+
+Wed Jan 15 11:59:56 1992 Kathy Hargreaves (kathy at hayley)
+
+ * filename.c (find_*_filename): only free `name' if it's not the
+ same string as `*_name'.
+
+Tue Jan 14 12:36:15 1992 Kathy Hargreaves (kathy at hayley)
+
+ * bitmap.c (bitmap_find_transitions): make the last transition
+ always imply a black-to-white transition, even if ROW's last
+ pixel is black.
+
+ * libfile.c (libfile_start): make FATAL2 report `name', not
+ `filename' as the library file not found. Also, only add suffix
+ to the library file name if it doesn't have one already.
+
+Sun Jan 12 16:29:11 1992 Kathy Hargreaves (kathy at hayley)
+
+ * filename.c (make_suffix): copy suffix into new_s, not s.
+
+Sun Jan 12 14:57:24 1992 Karl Berry (karl at hayley)
+
+ * pathsearch.c (check_subdir): add every existing subdirectory,
+ even if it's not a leaf.
+
+Sun Jan 12 12:47:57 1992 Kathy Hargreaves (kathy at hayley)
+
+ * libfile.c (libfile_start): don't prepend a dot to the suffix.
+
+ * dir-p.c (dir_p): call stat instead of xstat.
+
+Sat Jan 11 15:01:02 1992 Karl Berry (karl at hayley)
+
+ * filename.c (find_*_filename): set cwd_first_p.
+
+ * pathsearch.c (initialize_path_list): take an additional
+ argument, saying whether to search `.' first.
+
+Fri Jan 10 07:40:50 1992 Karl Berry (karl at hayley)
+
+ * xgetcwd.c (xgetcwd) [GETWD_MISSING]: if it's not missing, use
+ it.
+
+ * filename.c (find_*_filename): only initialize the path lists
+ once.
+
+ * pathsearch.c (expand_colon): if env_path is null, return the
+ default path.
+
+ * file-input.c (MOVE_BACK): use xfseek.
+
+ * filename.c (*_suffix): use strrchr instead of rpos.
+
+ * varstring.c: change names to start with `vs'.
+
+ * memory.c: split into various files.
+
+ * math.c (adjacent_points): rename to `points_adjacent_p'.
+
+ * math.c (find_bounds): use MAXDOUBLE and MINDOUBLE instead of
+ MAXFLOAT and MINFLOAT.
+
+ * filename.c (find_dpi): move to cmdline.c.
+ (basename): move to basename.c.
+
+Thu Jan 9 08:57:39 1992 Karl Berry (karl at hayley)
+
+ * convert.c: split into various files.
+ * GNUmakefile: update.
+
+ * cmdline.c (scan_integer_list): rename to `scan_unsigned_list'.
+
+ * *.c: do not include global.h.
+
+ * arith.c: split into `scaled-num.c' and `fix-num.c'.
+ * GNUmakefile: update.
+
+Wed Jan 8 09:14:45 1992 Karl Berry (karl at hayley)
+
+ * update copyright messages.
+
+ * change `allocate to `xmalloc', `reallocate' to `xrealloc', and
+ `string_copy' to `strdup'.
+
+ * list.c: doc fix.
+
+Tue Jan 7 17:28:07 1992 Karl Berry (karl at hayley)
+
+ * filename.c (expand_colon): don't put the default value at the
+ end if we've already put it at the beginning.
+
+Thu Sep 12 11:06:58 1991 Karl Berry (karl at hayley)
+
+ * malloc.c (malloc_sanity_check): new function.
+
+ * bitmap.c (bitmap_find_transitions): rearrange logic for clarity.
+
+ * malloc.c, getpagesize.h: new files.
+ * GNUmakefile (c_only): add Doug Lea's malloc.
+ (malloc_stats, malloc_inline): new variables.
+ (malloc.o): rule to explicitly use them.
+
+Tue Jul 30 13:18:12 1991 Karl Berry (karl at ra.cs.umb.edu)
+
+ * Version 0.3.
+
+Wed Jul 24 06:34:11 1991 Karl Berry (karl at hayley)
+
+ * bitmap.c (concat_bitmaps): remove; it's only used in one program.
+
+ * bitmap.c (new_bitmap): call it.
+
+ * memory.c (xcalloc): new routine.
+
+Tue Jul 16 08:24:08 1991 Karl Berry (karl at hayley)
+
+ * memory.c (allocate): don't do assignment inside if.
+
+ * bitmap.c (bitmap_find_transitions): we don't need to look at the
+ first black pixel twice.
+
+Fri Jun 28 09:09:59 1991 Karl Berry (karl at hayley)
+
+ * font.c (close_font): only close the TFM file if the font is not
+ bitmap-only.
+
+Sat Jun 15 09:51:45 1991 Karl Berry (karl at hayley)
+
+ * font.c (get_font): set the new `tfm_font' and `tfm_filename'
+ members.
+
+ * {dirio,file-misc,file-open,filename,libfile}.c: change
+ `checked_' to `x'.
+
+Tue Jun 11 16:46:25 1991 Karl Berry (karl at hayley)
+
+ * font.c (get_char): use XTALLOC.
+
+ * font.c (close_font): close the TFM file here, instead of in
+ `get_font'.
+
+Sun Jun 9 13:23:59 1991 Karl Berry (karl at hayley)
+
+ * font.c (string_to_bitmap): use `BITMAP_PIXEL (CHAR_BITMAP'...
+ instead of `CHAR_BITMAP_PIXEL'.
+
+Thu Jun 6 07:30:07 1991 Karl Berry (karl at hayley)
+
+ * All files: change to version 2 of the GPL.
+
+Sat Jun 1 16:00:03 1991 Kathy Hargreaves (kathy at hayley)
+
+ * libfile.c (libfile_start): Don't concat a `.' to suffix if it's
+ the empty string.
+
+Thu May 16 07:35:47 1991 Karl Berry (karl at hayley)
+
+ * GNUmakefile (files): include `xmessage' (from xbce).
+ * xmessage.c: new file.
+
+Sun Apr 21 17:38:48 1991 Karl Berry (karl at hayley)
+
+ * bitmap.c (bitmap_to_bb): declare the arg as const.
+
+Sun Apr 14 13:45:29 1991 Karl Berry (karl at hayley)
+
+ * bitmap.c (print_bitmap): use `bitmap_to_bb' instead of
+ `dimensions_to_bb'.
+
+Fri Apr 12 15:12:32 1991 Karl Berry (karl at hayley)
+
+ * math.c: doc fix.
+
+ * GNUmakefile (files): add `report' and `logreport'.
+ * {log,}report.c: new files.
+
+Wed Apr 10 11:27:49 1991 Karl Berry (karl at hayley)
+
+ * font.c (save_internal_font): omit needless casts.
+
+Mon Apr 8 07:57:20 1991 Karl Berry (karl at hayley)
+
+ * font.c (ascender_part): move to ospace.
+
+ * encoding.c (parse_encoding_line): make a copy of the character
+ name, since the line gets freed.
+
+ * encoding.c (read_encoding_file): reinitialize the character
+ code, so we fill up the right array.
+
+ * libfile.c (libfile_start): prepend the `.' to the suffix.
+
+Sun Apr 7 14:34:06 1991 Karl Berry (karl at hayley)
+
+ * file-output.c (put_signed_four): declare this as a macro in the
+ .h file.
+
+Thu Apr 4 07:03:36 1991 Karl Berry (karl at hayley)
+
+ * font.c (get_char): don't allocate any space unless the character
+ actually exists in the font.
+
+Mon Apr 1 07:57:58 1991 Karl Berry (karl at hayley)
+
+ * {encoding,libfile}.c: new files.
+ GNUmakefile (files): add them to the list.
+
+Sat Mar 23 16:42:39 1991 Karl Berry (karl at hayley)
+
+ * font.c (delete_internal_font): free the memory for the internal
+ font, and for the font name.
+
+Sat Mar 9 17:06:57 1991 Karl Berry (karl at hayley)
+
+ * string.c: declare args to routines as const.
+
+ * string.c (lowercasify): new routine.
+
+Thu Mar 7 07:33:05 1991 Karl Berry (karl at hayley)
+
+ * Version 0.2.
+
+Mon Mar 4 15:06:59 1991 Karl Berry (karl at hayley)
+
+ * font.c (delete_internal_font): new routine.
+ (close_font): call it, thus preventing us from finding a font that
+ has been closed.
+
+Mon Feb 25 15:58:21 1991 Karl Berry (karl at hayley)
+
+ * font.c (get_font): use `tfm_...' instead of `..._tfm_...'; use
+ `pk_...' instead of `..._pk_...'; use `gf_...' instead of
+ `..._gf_...'.
+
+Sun Feb 24 15:34:36 1991 Karl Berry (karl at ra.cs.umb.edu)
+
+ * math.c (int_distance): cast the arguments to `double'.
+
+Sun Feb 17 09:43:06 1991 Karl Berry (karl at hayley)
+
+ * *.c: include config.h.
+
+Sat Feb 16 16:54:18 1991 Karl Berry (karl at hayley)
+
+ * dirio.c (checked_lstat) [HAVE_SYMBOLIC_LINKS]: change
+ conditional from being on S_ISLNK and S_IFLNK.
+
+Tue Jan 22 15:44:43 1991 Karl Berry (karl at hayley)
+
+ * bitmap.c (extract_subbitmap): new routine from imgtogf.
+
+Fri Jan 18 08:14:23 1991 Karl Berry (karl at hayley)
+
+ * vector.c (all routines): declare args to be const.
+
+ * vector.c (Vabs): new routine.
+
+Tue Jan 15 15:29:38 1991 Karl Berry (karl at hayley)
+
+ * spline.c (append_spline): use LAST_SPLINE_LIST_ELT.
+
+ * spline.c (new_spline_list_array, free_spline_list_array,
+ append_spline_list): new routines.
+
+ * spline.c (append_spline_list): rename to concat_spline_lists.
+
+Sun Jan 13 09:48:56 1991 Karl Berry (karl at hayley)
+
+ * font.c (bitmap_format_type): move to font.h.
+
+ * file-output.c (put_n_bytes): give the arguments to fwrite in the
+ correct order.
+
+Sat Jan 12 16:46:44 1991 Karl Berry (karl at hayley)
+
+ * file-output.c (put_n_bytes): use fwrite to do all the bytes at
+ one shot.
+
+Mon Jan 7 10:42:22 1991 Karl Berry (karl at hayley)
+
+ * spline.c (evaluate_spline): no compiler bug anymore without
+ temporaries (as of gcc 1.38).
+
+Sat Dec 29 17:43:40 1990 Karl Berry (karl at hayley)
+
+ * spline.c (print_spline): make the output lines shorter.
+
+Wed Dec 26 15:13:26 1990 Karl Berry (karl at hayley)
+
+ * math.c (find_bounds): use MAXFLOAT and MINFLOAT, instead of
+ MAXDOUBLE and MINDOUBLE, since Sun's atof can't deal with
+ the latter.
+
+Sun Dec 9 11:02:20 1990 Karl Berry (karl at hayley)
+
+ * spline.c: doc fix.
+
+ * dirio.c (getwd): close each directory after we read it.
+
+ * filename.c (find_subdir_path_filename): use getwd instead of
+ getcwd, and use checked_chdir.
+
+ * dirio.c (checked_opendir, is_dir): make arguments be const strings.
+
+ * dirio.c (checked_chdir, checked_stat, checked_lstat, getwd): new
+ routines.
+
+Sat Nov 17 11:09:56 1990 Karl Berry (karl at hayley)
+
+ * file-*.c: include the appropriate file-....h file.
+
+ * math.c (distance): put this back; it's too annoying to call
+ hypot with the x and y arguments.
+
+Thu Oct 18 15:00:32 1990 Karl Berry (karl at hayley)
+
+ * filename.c (find_subdir_path_filename): initialize the list of
+ subdirectories to the empty string.
+
+Wed Oct 17 17:54:40 1990 Karl Berry (karl at aten)
+
+ * filename.c (find_subdir_path_filename): do not do strlen when
+ the path is empty.
+
+Tue Oct 9 08:59:43 1990 Karl Berry (karl at hayley)
+
+ * filename.c (find_dpi): don't crash if the argument doesn't have
+ a `.' at all.
+
+ * cmdline.c: new file.
+ * GNUmakefile (files): add it.
+
+Mon Oct 8 09:08:30 1990 Karl Berry (karl at hayley)
+
+ * filename.c (find_dpi): new routine.
+
+Wed Oct 3 07:33:07 1990 Karl Berry (karl at hayley)
+
+ * filename.c (find_tfm_filename, find_pk_filename,
+ find_gf_filename): new routines.
+
+Sat Sep 29 08:34:52 1990 Karl Berry (karl at hayley)
+
+ * bitmap.c (new_bitmap): don't use memset if the bitmap is null.
+
+ * font.c (find_internal_font): use STREQ.
+
+Fri Sep 28 08:30:04 1990 Karl Berry (karl at hayley)
+
+ * filename.c (next_component): return NULL after we've read all
+ the directories in the list.
+
+ * filename.c (next_component): omit the path separator from the
+ returned directory.
+
+Thu Sep 27 11:45:36 1990 Karl Berry (karl at hayley)
+
+ * font.c (DEFAULT_SUBDIR_PATH): new macro.
+ (get_bitmap_font): try to open the PK and GF files using
+ subdirectories if opening without them fails.
+ (get_font): likewise, for the TFM file.
+ * filename.c (get_subdir_path_filename): new routine.
+ (next_component): new routine, replaces `find_components'.
+
+Fri Sep 21 09:15:28 1990 Karl Berry (karl at hayley)
+
+ * dirio.o (is_dir): use S_ISDIR.
+
+Thu Sep 13 10:38:32 1990 Karl Berry (karl at hayley)
+
+ * convert.c (parse_char_code): new routine to replace the
+ PARSE_CHAR_CODE macro; return a status indicator.
+ (xparse_char_code): like the above, but gives a fatal error.
+
+Wed Sep 12 18:19:13 1990 Karl Berry (karl at aten)
+
+ * font.c (get_font): set `bitmap_only' to false.
+ (save_internal_font): overwrite the old value if we're called with
+ the same key twice.
+
+Sun Sep 9 07:10:29 1990 Karl Berry (karl at hayley)
+
+ * convert.c: new file for some numeric conversions.
+ * math.c: move atou to convert.c.
+
+Mon Sep 3 11:05:19 1990 Karl Berry (karl at hayley)
+
+ * line.c (read_line): doc fix.
+
+Fri Aug 31 11:04:02 1990 Karl Berry (karl at hayley)
+
+ * font.c (get_bitmap_font): new routine, taken from get_font.
+
+Thu Aug 30 16:32:25 1990 Karl Berry (karl at hayley)
+
+ * file-misc.c (same_file_p): new function.
+
+Wed Aug 29 11:37:24 1990 Karl Berry (karl at hayley)
+
+ * fileio.c: split up into several new files: file-open.c,
+ file-input.c, file-output.c, file-misc.c.
+
+Thu Aug 23 07:26:58 1990 Karl Berry (karl at hayley)
+
+ * filename.c (remove_suffix): new routine.
+ (make_suffix): if the `.' is before a `/', it doesn't start the
+ extension.
+
+Thu Aug 16 07:10:48 1990 Karl Berry (karl at hayley)
+
+ * memory.c (safe_free): use fprintf instead of FATAL, so the core dump
+ will happen.
+
+Thu Jul 26 06:53:33 1990 Karl Berry (karl at hayley)
+
+ * bitmap.c (bitmap_find_transitions): new routine (from imgtogf).
+
+Wed Jul 25 08:20:12 1990 Karl Berry (karl at hayley)
+
+ * string.c (concat5): new routine.
+
+Tue Jul 24 10:24:59 1990 Karl Berry (karl at hayley)
+
+ * font.c (get_font): save the design size in points instead of
+ pixels.
+
+ * filename.c: new file.
+ * fileio.c (find_path_filename): move there.
+ * string.c (make_suffix): ditto.
+
+ * font.c (get_char): retrieve the TFM width also.
+
+Mon Jul 16 07:30:33 1990 Karl Berry (karl at hayley)
+
+ * bitmap.c (bitmap_to_bb): new routine.
+
+Thu Jul 12 06:01:16 1990 Karl Berry (karl at hayley)
+
+ * bitmap.c (copy_bitmap): don't use `new_bitmap', to avoid setting
+ all the bits twice.
+
+Tue Jul 10 06:23:54 1990 Karl Berry (karl at hayley)
+
+ * bitmap.c (concat_bitmaps): new routine.
+
+Mon Jul 9 08:27:09 1990 Karl Berry (karl at hayley)
+
+ * bitmap.c (get_bitmap_bounding_box): delete this.
+ (print_bitmap): use dimensions_to_bb.
+
+ * bitmap.c (free_bitmap): don't free the bitmap if it's null.
+
+ * bitmap.c (new_bitmap): use memset.
+ (copy_bitmap): use memcpy if the bitmap's size is greater than
+ zero.
+
+Sat Jul 7 18:22:55 1990 Karl Berry (karl at hayley)
+
+ * memory.c (safe_free): dump core if we are freeing a null item.
+
+Fri Jul 6 14:21:07 1990 Karl Berry (karl at hayley)
+
+ * bounding-box.c (bb_to_dimensions): ensure that the dimensions
+ are nonnegative.
+
+Wed Jul 4 12:06:49 1990 Karl Berry (karl at hayley)
+
+ * memory.c (allocate): dump core if we run out of memory.
+ (reallocate): ditto.
+
+ * bounding-box.c (dimensions_to_bb): don't subtract one from the
+ width, so it will work with the GF routines.
+ (bb_to_dimensions): use BB_WIDTH and BB_HEIGHT, instead of doing
+ the subtraction out here.
+
+ * bounding-box.c (update_bounding_box): new routine.
+
+Sun Jul 1 15:11:56 1990 Karl Berry (karl at hayley)
+
+ * font.c (ascender_part): new routine.
+
+Tue Jun 26 11:27:15 1990 Karl Berry (karl at hayley)
+
+ * spline.c (evaluate_spline): use temporaries in the computation
+ to avoid a compiler bug.
+
+ * vector.c (Padd, Pmult_scalar): remove definitions, since they
+ are defined as macros now.
+
+Sun Jun 24 15:31:34 1990 Karl Berry (karl at claude)
+
+ * font.c (get_font): don't check the checksums if either one is
+ zero.
+
+Sat Jun 23 12:11:47 1990 Karl Berry (karl at hayley)
+
+ * font.c (print_char): change precision for printing the row numbers.
+
+Tue Jun 19 11:50:52 1990 Karl Berry (karl at hayley)
+
+ * fileio.c (move_to_byte): delete this.
+
+ * fileio.c (cur_pos): rename to checked_ftell, and take a filename
+ argument for perror.
+
+Mon Jun 18 12:47:17 1990 Karl Berry (karl at hayley)
+
+ * font.c (find_internal_font): return a pointer to an
+ internal_font_type, instead of a structure, and change callers.
+ (get_font): if we have already saved the font, return it, instead
+ of opening the files again.
+
+Mon Jun 4 16:20:32 1990 Karl Berry (karl at hayley)
+
+ * math.c (find_bounds): use MAXDOUBLE and MINDOUBLE, instead of
+ MAXFLOAT and MINFLOAT.
+
+ * spline.c (spline_bounding_box): remove this routine.
+
+Sun Jun 3 10:51:28 1990 Karl Berry (karl at hayley)
+
+ * arith.c, math.c, vector.c: add const declarations.
+
+ * fileio.c (get_two, get_four): don't bother to initialize the
+ variable before we read it.
+
+ * fileio.c (get_n_bytes): improve the error message if the read
+ fails.
+
+Sat Jun 2 07:51:08 1990 Karl Berry (karl at hayley)
+
+ * bounding-box.c (increase_int_bound): remove this.
+
+ * spline.c (print_spline): print different things for lines and
+ splines.
+
+Wed May 30 16:02:26 1990 Karl Berry (karl at hayley)
+
+ * bitmap.c (new_bitmap): if the bitmap is going to be zero bits,
+ don't try to allocate it.
+
+ * font.c (get_font): figure out how many characters are in the
+ font by testing the `exists' member of the TFM structure.
+
+ * font.c (get_font): don't try to open the GF file if we couldn't
+ find it.
+
+Tue May 22 09:51:20 1990 Karl Berry (karl at hayley)
+
+ * fileio.c (find_path_filename): close the directories in the path.
+
+Sat May 19 10:30:39 1990 Karl Berry (karl at hayley)
+
+ * fileio.c (find_path_filename): return NULL if we can't find the
+ file, instead of the original name.
+ * font.c (get_font): rewrite the file-opening code.
+
+Wed May 16 18:02:54 1990 Karl Berry (karl at aten)
+
+ * font.c (string_to_bitmap): if the character doesn't exist in the
+ font, don't crash.
+
+ * fileio.c (find_path_filename): don't get a fatal error when a
+ directory in the path doesn't exist.
+
+Sun May 13 13:45:12 1990 Karl Berry (karl at hayley)
+
+ * dirio.c (is_dir): new routine.
+
+ * fileio.c (find_path_filename): just return the name we're given
+ if the path is relative; move the suffix concatenation out of the
+ loop; search in subdirectories.
+
+Tue May 8 12:08:57 1990 Karl Berry (karl at hayley)
+
+ * math.c: doc fix.
+
+Thu May 3 10:45:05 1990 Karl Berry (karl at hayley)
+
+ * line.c (read_line): use VS_CHARS.
+
+Wed May 2 12:25:08 1990 Karl Berry (karl at claude)
+
+ * font.c (string_to_bitmap): don't close the font when we're done.
+
+Wed Apr 25 13:16:28 1990 Karl Berry (karl at aten)
+
+ * font.c (string_to_bitmap): don't asked for chars[x] when x is a
+ character that isn't there.
+
+Tue Apr 24 18:35:08 1990 Karl Berry (karl at hayley)
+
+ * math.c (real_to_int_coord): new routine.
+
+Sun Apr 22 06:42:37 1990 Karl Berry (karl at hayley)
+
+ * font.c (string_to_bitmap): initialize char_y properly.
+ [whoops, I mean test it properly, and initialize y.]
+ Pass the row and column to BITMAP_PIXEL in the right order.
+ Give the row and column to the constructor in the right order,
+ too. Use MAX to find the depth, not MIN.
+
+ * font.c (print_char): print the bitmap here, so we can print out
+ the Cartesian row number, instead of calling `print_bitmap'.
+
+Sat Apr 21 09:49:42 1990 Karl Berry (karl at hayley)
+
+ * fileio.c (get_n_bytes): use fread to read the whole block,
+ instead of getting them one byte at a time.
+
+Thu Apr 19 16:19:33 1990 Karl Berry (karl at hayley)
+
+ * font.c (get_font): do checksum test before getting the
+ postamble.
+
+Tue Apr 17 16:53:31 1990 Karl Berry (karl at hayley)
+
+ * font.c (print_char): new routine to print a text representation
+ of a character.
+
+Mon Apr 16 11:12:28 1990 Karl Berry (karl at hayley)
+
+ * font.c (get_font): get the design size from the TFM file,
+ instead of the bitmap file.
+
+Sun Apr 15 07:34:19 1990 Karl Berry (karl at hayley)
+
+ * font.c (get_font): do not set the font bounding box.
+
+Sat Apr 14 15:11:19 1990 Karl Berry (karl at hayley)
+
+ * fileio.c (checked_fseek): make argument type be
+ seek_direction_type.
+
+ * fileio.c (checked_fclose): new (trivial) routine.
+
+Thu Apr 12 12:06:17 1990 Karl Berry (karl at hayley)
+
+ * GNUmakefile: do not define USG and USGr3.
+
+ * time.c: include <sys/types.h> and declare time(2) and ctime(3)
+ using time_t.
+
+ * fileio.c (find_path_filename): use access(2) instead of
+ fopen(3); pass the default path to find_components.
+ (find_components): use a default path if the environment variable
+ doesn't exist.
+
+Mon Apr 9 08:19:53 1990 Karl Berry (karl at hayley)
+
+ * math.c (distance): remove this, I came across hypot(3).
+
+ * all files: upcase macro names.
+
+Sun Mar 18 14:58:23 1990 Kathy Hargreaves (kathy at hayley)
+
+ * bounding_box.[hc] (increase_int_bound): added this to increase a
+ bounding boxes bounds nicely, i.e., if the bound is negative, it
+ gets decreased, and increased otherwise.
+
+Tue Feb 27 21:01:24 1990 Kathy Hargreaves (kathy at hayley)
+
+ * fileio.c (get_n_bytes): don't try to read zero bytes.
+
+Wed Feb 7 17:00:47 1990 Karl Berry (karl at hayley)
+
+ * time.c (now): chop off the trailing space.
+
+Mon Jan 29 12:46:56 1990 Karl Berry (karl at hayley)
+
+ * bounding-box.c (bb_to_dimensions): new routine.
+
+ * math.c (atou): like atoi but < 0 is a fatal error.
+
+Sun Jan 21 09:55:14 1990 Karl Berry (karl at hayley)
+
+ * Makefile: rename to GNUmakefile.
+
+ * bounding_box.c (dimensions_to_bounding_box): rename to
+ dimensions_bb. Remove other conversion routines. And rename to
+ bounding-box.c.
+
+Tue Oct 31 07:24:05 1989 Karl Berry (karl at hayley)
+
+ * math.c (int_to_real_coordinate): remove this.
+
+Mon Oct 30 14:03:57 1989 Karl Berry (karl at hayley)
+
+ * all files: add the copyleft.
+
+ * string.c (concat4): define this.
+
+Sun Oct 29 18:37:33 1989 Karl Berry (karl at claude)
+
+ * math.c (undefined_real_coordinate): remove this.
+
+Sat Oct 28 15:55:59 1989 Karl Berry (karl at hayley)
+
+ * arith.c (real_to_scaled, real_to_fix): multiply the integer part
+ by scaled_one and fix_one, respectively.
+
+ * fileio.c (put_three): define this.
+ (put_three, put_four): had the mask wrong for the
+ low-order byte.
+ (put_two, put_three, put_four): a & b >> c is
+ a & (b >> c), not (a & b) >> c.
+
+Fri Oct 27 22:14:05 1989 Karl Berry (karl at hayley)
+
+ * bitmap.c (new_bitmap): use the bitmap_dimensions macro.
+
+Sun Oct 8 15:41:01 1989 Karl Berry (karl at hayley)
+
+ * math.c (epsilon_equal): new function to test if two values are
+ within epsilon of each other.
+ (acosd): changed to call that one.
+
+ * bitmap.c (free_bitmap): new function to deallocate storage
+ used in a bitmap_type.
+
+ * math.c (acosd): normalize to 1.0 or -1.0 if the argument is
+ within an epsilon of that anyway.
+
+Fri Oct 6 22:12:05 1989 Karl Berry (karl at hayley)
+
+ * line.c (read_line): overwrite the newline at the end of the
+ string with a null.
diff --git a/lib/GNUmakefile b/lib/GNUmakefile
new file mode 100644
index 0000000..ed258fa
--- /dev/null
+++ b/lib/GNUmakefile
@@ -0,0 +1,38 @@
+# Makefile for the fontutils library.
+#
+# Copyright (C) 1992, 93 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.
+
+library = lib
+
+# If this gives you trouble, just remove it. The system malloc will
+# probably work well enough.
+#malloc = gmalloc
+
+# The headers are in the `include' directory, so don't use `c_and_h'.
+
+c_only = $(malloc) bb-list bb-outline bitmap bounding-box \
+charcode charspec cmdline concat concat3 concat4 concat5 dlsym edge \
+encoding float-ok fmod file-input file-output filename fix-num font \
+getopt getopt1 hexify identity integer-ok libfile line list logreport \
+make-prefix math now numtoa pathsrch rand report safe-free scaled-num \
+spline statistics str-lcase str-to-bit substring varstring vector \
+xmessage xopendir xrename
+
+include ../data/defs.make
+include ../data/defslib.make
+
+include M.depend
diff --git a/lib/README b/lib/README
new file mode 100644
index 0000000..4d0c220
--- /dev/null
+++ b/lib/README
@@ -0,0 +1,73 @@
+This library contains many miscellanous functions that are used by the
+other programs we have written.
+
+The declarations for the functions are in ../include. config.h must be
+included first in a .c file; that includes global.h, which declares a
+few of the most commonly used functions here. The rest have their own
+include files, e.g., line.h.
+
+Some functions merely call a C library routine or make a system call,
+check the return status, and abort if the function failed. (In the
+programs this has been used for, that was all that we ever wanted.)
+
+Here is a brief description of what's here (aside from the files which
+have just one function in them and other ``obvious'' ones):
+
+bb-outline find the outlines in a bitmap character.
+
+bitmap operations on bitmaps, with each pixel represented by a
+ byte in memory.
+
+bounding-box conversions to and from bounding boxes, both integer
+ and real.
+
+cmdline standard things for reading option lists.
+
+dirio directory operations.
+
+encoding read a font encoding specification in a .enc file.
+
+file-input read BigEndian values.
+
+file-open wrappers for fopen and fclose.
+
+file-output write BigEndian values.
+
+filename operations on filenames.
+
+fix-num conversions for the `fix_word' fixed-point fraction
+ type, used in TFM files et al.
+
+font read a bitmap font, or a bitmap font and its metrics.
+
+hexify convert a sequence of binary data to its hex representation.
+
+libfile read a `library', i.e., an auxiliary data, file.
+
+line read an arbitrarily long line from a file, returning a string.
+
+list generic list operations. It is a tossup as to whether
+ it is easier to repeat this code for the particular
+ lists you desire, or to use these, often with an extra
+ level of pointers. Unfortunately, C does not support
+ generic types.
+
+math distance, slope, etc., between two points; operations on
+ arrays as a collection of numeric data.
+
+now the current time as in date(1).
+
+pathsearch look up a filename along a path in an environment variable.
+
+report online progress reporting.
+
+scaled-num routines for the `scaled' fixed-point fraction
+ type, used in GF files et al.
+
+spline operations on Bezier splines.
+
+statistics find the mean/standard deviation of an array of numbers.
+
+varstring variable-length strings.
+
+vector operations on vectors and point/vector combinations.
diff --git a/lib/atou.o b/lib/atou.o
new file mode 100644
index 0000000..d15e642
--- /dev/null
+++ b/lib/atou.o
Binary files differ
diff --git a/lib/basename.o b/lib/basename.o
new file mode 100644
index 0000000..8242dd6
--- /dev/null
+++ b/lib/basename.o
Binary files differ
diff --git a/lib/bb-list.c b/lib/bb-list.c
new file mode 100644
index 0000000..e3df94e
--- /dev/null
+++ b/lib/bb-list.c
@@ -0,0 +1,76 @@
+/* bb-list.c: operations on bounding box lists.
+
+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 "bb-list.h"
+
+
+/* This routine returns an initialized empty list. */
+
+bb_list_type
+bb_list_init ()
+{
+ bb_list_type bb_list;
+
+ BB_LIST_LENGTH (bb_list) = 0;
+ BB_LIST_DATA (bb_list) = NULL;
+
+ return bb_list;
+}
+
+/* Append BB to BB_LIST. */
+
+void
+bb_list_append (bb_list_type *bb_list, bounding_box_type bb)
+{
+ BB_LIST_LENGTH (*bb_list)++;
+ XRETALLOC (BB_LIST_DATA (*bb_list), BB_LIST_LENGTH (*bb_list),
+ bounding_box_type);
+
+ BB_LIST_ELT (*bb_list, BB_LIST_LENGTH (*bb_list) - 1) = bb;
+}
+
+/* Append the elements in the list B2 onto the end of B1. */
+
+void
+bb_list_splice (bb_list_type *b1, bb_list_type b2)
+{
+ unsigned new_length;
+ unsigned this_bb;
+
+ if (BB_LIST_LENGTH (b2) == 0)
+ return;
+
+ assert (b1 != NULL);
+
+ new_length = BB_LIST_LENGTH (*b1) + BB_LIST_LENGTH (b2);
+ XRETALLOC (BB_LIST_DATA (*b1), new_length, bounding_box_type);
+
+ for (this_bb = 0; this_bb < BB_LIST_LENGTH (b2); this_bb++)
+ BB_LIST_ELT (*b1, BB_LIST_LENGTH (*b1)++) = BB_LIST_ELT (b2, this_bb);
+}
+
+/* Free the memory in a list. */
+
+void
+bb_list_free (bb_list_type *bb_list)
+{
+ if (BB_LIST_DATA (*bb_list) != NULL)
+ safe_free ((address *) &BB_LIST_DATA (*bb_list));
+}
diff --git a/lib/bb-outline.c b/lib/bb-outline.c
new file mode 100644
index 0000000..1f0e3fa
--- /dev/null
+++ b/lib/bb-outline.c
@@ -0,0 +1,114 @@
+/* bb-outline.c: find the bounding boxes enclosing outlines.
+
+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 "bb-outline.h"
+#include "edge.h"
+
+
+static bounding_box_type find_one_bb
+ (bitmap_type, edge_type, unsigned, unsigned, bitmap_type *);
+
+/* A character is made up of a list of one or more outlines. Here, we
+ go through a character's bitmap marking edges on pixels, top to
+ bottom, left to right, looking for the next pixel with an unmarked
+ edge that is also on the character's outline. Each one of these
+ pixels we find is the starting place for one outline. We then get the
+ bounding boxes of the outlines, and put them in a list to return. We
+ don't look at pixels that are at or after the column LEFT_MARK or
+ before RIGHT_MARK. If FIND_INNER is false, we return only outside
+ outlines; otherwise, we return both inside and outside. */
+
+bb_list_type
+find_outline_bbs (bitmap_type b, boolean find_inner,
+ int left_mark, int right_mark)
+{
+ unsigned row, col;
+ bb_list_type bb_list = bb_list_init ();
+ bitmap_type marked = new_bitmap (BITMAP_DIMENSIONS (b));
+
+ /* By looking through the bitmap in column-major order, we preserve
+ the original ordering of the characters in the image. Otherwise,
+ `b' would be found before `a' (for example), because of the
+ ascender. */
+ for (col = 0; col < BITMAP_WIDTH (b); col++)
+ if (col < left_mark || col >= right_mark)
+ for (row = 0; row < BITMAP_HEIGHT (b); row++)
+ {
+ edge_type edge;
+
+ if (BITMAP_PIXEL (b, row, col) == WHITE
+ || BITMAP_INTERIOR_PIXEL (b, row, col))
+ continue;
+
+ /* Get the next unmarked edge on this pixel, if there is one. */
+ edge = next_unmarked_outline_edge (row, col, START_EDGE, b, marked);
+
+ /* If there is an unmarked outline edge on this pixel... */
+ if (edge != no_edge)
+ {
+ /* Want to mark edges in inner boxes, too. */
+ bounding_box_type bb = find_one_bb (b, edge, row, col, &marked);
+
+ /* If edge != START_EDGE, it's on an inner bounding box. */
+ if (find_inner || edge == START_EDGE)
+ {
+ /* The numbers in BB, as it comes in, refer to pixels;
+ we have to change the maximum row so that it refers
+ to the edge beyond the last pixel. */
+ MAX_COL (bb)++;
+
+ bb_list_append (&bb_list, bb);
+ }
+ }
+ }
+
+ free_bitmap (&marked);
+ return bb_list;
+}
+
+/* Here we find one of a character's outlines. We're passed the
+ position (ORIGINAL_ROW and ORIGINAL_COL) of a starting pixel and one
+ of its unmarked edges, ORIGINAL_EDGE. We traverse the adjacent edges
+ of the outline pixels but keep the bounding box in pixel coordinates.
+ We keep track of the marked edges in MARKED, which should be
+ initialized to zeros before we get it. */
+
+static bounding_box_type
+find_one_bb (bitmap_type b, edge_type original_edge,
+ unsigned original_row, unsigned original_col,
+ bitmap_type *marked)
+{
+ bounding_box_type bb = { INT_MAX, INT_MIN, INT_MAX, INT_MIN };
+ unsigned row = original_row, col = original_col;
+ edge_type edge = original_edge;
+
+ do
+ {
+ coordinate_type p = { col, row };
+ update_bounding_box (&bb, p);
+
+ mark_edge (edge, row, col, marked);
+ next_outline_edge (b, &edge, &row, &col);
+ }
+ while (!(row == original_row && col == original_col
+ && edge == original_edge));
+
+ return bb;
+}
diff --git a/lib/bitmap.c b/lib/bitmap.c
new file mode 100644
index 0000000..9223c66
--- /dev/null
+++ b/lib/bitmap.c
@@ -0,0 +1,258 @@
+/* bitmap.c: operations on bitmaps.
+
+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 "bitmap.h"
+#include "bounding-box.h"
+
+static void bb_ensure_bounds (bounding_box_type *, bitmap_type, string);
+
+/* Make sure the bitmap is entirely white to begin with. */
+
+bitmap_type
+new_bitmap (dimensions_type d)
+{
+ bitmap_type answer;
+ unsigned size = DIMENSIONS_WIDTH (d) * DIMENSIONS_HEIGHT (d);
+
+ BITMAP_DIMENSIONS (answer) = d;
+ BITMAP_BITS (answer) = size > 0 ? xcalloc (size, 1) : NULL;
+
+ return answer;
+}
+
+
+/* Free the storage that is allocated for a bitmap. On the other hand,
+ the bitmap might not have any storage allocated for it if it is zero
+ in either dimension; in that case, don't free it. */
+
+void
+free_bitmap (bitmap_type *b)
+{
+ if (BITMAP_BITS (*b) != NULL)
+ safe_free ((address *) &BITMAP_BITS (*b));
+}
+
+
+/* Copy an existing bitmap into new memory. We don't want to use
+ `new_bitmap' here, since that routine clears the bitmap's bits, and
+ we are going to set all the bits ourselves, anyway. */
+
+bitmap_type
+copy_bitmap (bitmap_type bitmap)
+{
+ bitmap_type answer;
+ unsigned size = BITMAP_WIDTH (bitmap) * BITMAP_HEIGHT (bitmap);
+
+ BITMAP_DIMENSIONS (answer) = BITMAP_DIMENSIONS (bitmap);
+ BITMAP_BITS (answer) = size > 0 ? xmalloc (size) : NULL;
+
+ if (size > 0)
+ memcpy (BITMAP_BITS (answer), BITMAP_BITS (bitmap), size);
+
+ return answer;
+}
+
+
+/* Return the part of the bitmap SOURCE enclosed by the bounding box BB.
+ BB is interpreted in bitmap coordinates, with y increasing downwards;
+ for example, if MIN_ROW (BB) == 10, the subimage will start in the
+ tenth row from the top of SOURCE. */
+
+bitmap_type
+extract_subbitmap (bitmap_type source, bounding_box_type bb)
+{
+ unsigned this_row;
+ bitmap_type sub = new_bitmap (bb_to_dimensions (bb));
+
+ /* Move to the bit at which we want to start copying. */
+ BITMAP_BITS (source) += MIN_ROW (bb) * BITMAP_WIDTH (source) + MIN_COL (bb);
+
+ bb_ensure_bounds (&bb, source, "extract_subbitmap");
+
+ for (this_row = MIN_ROW (bb); this_row <= MAX_ROW (bb); this_row++)
+ {
+ one_byte *target = BITMAP_ROW (sub, this_row - MIN_ROW (bb));
+
+ memcpy (target, BITMAP_BITS (source), BITMAP_WIDTH (sub));
+ BITMAP_BITS (source) += BITMAP_WIDTH (source);
+ }
+
+ return sub;
+}
+
+
+/* If any of the elements of BB (taken to be in bitmap coordinates) are
+ outside the bounds of the bitmap SOURCE, give a warning (using NAME)
+ and update them. */
+
+static void
+bb_ensure_bounds (bounding_box_type *bb, bitmap_type source, string name)
+{
+ if (MIN_COL (*bb) < 0)
+ {
+ WARNING2 ("%s: min col=%d outside source image", name, MIN_COL (*bb));
+ MIN_COL (*bb) = 0;
+ }
+
+ if (MIN_ROW (*bb) < 0)
+ {
+ WARNING2 ("%s: min row=%d outside source image", name, MIN_ROW (*bb));
+ MIN_COL (*bb) = 0;
+ }
+
+ /* See comments at `get_character_bitmap' in gf_input.c for why the
+ width and height are treated asymetrically. */
+ if (MAX_COL (*bb) > BITMAP_WIDTH (source))
+ {
+ WARNING2 ("%s: max col=%d outside source image", name, MAX_COL (*bb));
+ MAX_COL (*bb) = BITMAP_WIDTH (source) - 1;
+ }
+
+ if (MAX_ROW (*bb) >= BITMAP_HEIGHT (source))
+ {
+ WARNING2 ("%s: max row=%d outside source image", name, MAX_ROW (*bb));
+ MAX_COL (*bb) = BITMAP_HEIGHT (source) - 1;
+ }
+}
+
+/* The bounding boxes that we make in this routine are unlike the
+ bounding boxes used elsewhere. These are in bitmap coordinates, not
+ Cartesian, and they refer to pixels, not edges. So we have to adjust
+ the maximum column by one. */
+
+const bounding_box_type
+bitmap_to_bb (const bitmap_type b)
+{
+ bounding_box_type bb = dimensions_to_bb (BITMAP_DIMENSIONS (b));
+ if (MAX_COL (bb) != 0) MAX_COL (bb)--;
+
+ return bb;
+}
+
+/* Return the (zero-based) column numbers in which ROW changes from
+ black to white or white to black. The first element marks a
+ white-to-black transition, and the last element marks a
+ black-to-white transition, imagining that ROW is surrounded by white.
+ (In other words, there is always an even number of transitions.) We
+ mark the end of the vector with an element WIDTH + 1. */
+
+/* We use `length - 2' because we need to save one element at the end
+ for our sentinel. */
+#define INSERT_TRANSITION(e) \
+ do { \
+ XRETALLOC (vector, ++length, unsigned); \
+ vector[length - 2] = e; \
+ } while (0)
+
+unsigned *
+bitmap_find_transitions (const one_byte *row, unsigned width)
+{
+ unsigned col;
+ unsigned start;
+ one_byte color = BLACK;
+ unsigned length = 1;
+
+ /* We want to make sure we start at a column with some black. */
+ char *start_ptr = memchr (row, BLACK, width);
+
+ /* Save the last element for the sentinel. */
+ unsigned *vector = XTALLOC1 (unsigned);
+
+ if (start_ptr == NULL)
+ start = width; /* Don't go through the loop. */
+ else
+ {
+ INSERT_TRANSITION (start_ptr - (char *) row);
+ start = vector[0] + 1; /* Don't look at this pixel again. */
+ }
+
+ for (col = start; col < width - 1; col++)
+ {
+ if (row[col] != color)
+ {
+ INSERT_TRANSITION (col);
+ color = row[col];
+ }
+ }
+
+ /* We have to treat the last pixel in ROW specially. There are
+ several cases:
+ 1) if it's white, and the previous pixel is white, or the row is
+ one pixel long, do nothing;
+ 2) if it's white, and the previous pixel is black,
+ insert one element in `vector' (marking the end of a run);
+ 3) if it's black, and either the previous pixel is black or this was the
+ first black pixel in the row, insert one element (marking the
+ end of a run because we're at the end of the row);
+ 4) if it's black, and the previous pixel is white and there was a
+ previous black pixel, or the row was one pixel long, insert
+ two elements (marking the start and end of this one-pixel run).
+ */
+ if (row[width - 1] == WHITE)
+ {
+ if (width > 1 && row[width - 2] == BLACK)
+ INSERT_TRANSITION (width - 1);
+ }
+ else
+ { /* Last pixel is black. If previous pixel was also black, just
+ finish off the run. */
+ if (width > 1 && row[width - 2] == BLACK)
+ INSERT_TRANSITION (width);
+ else
+ { /* Last pixel is black, previous pixel was white. If this was
+ the only black pixel in the row, we've already inserted the
+ start of the run via `start' above, so just insert the end of
+ the run. Otherwise, insert both the start and end of this
+ one-pixel run. */
+ if (start != width)
+ INSERT_TRANSITION (width - 1);
+ INSERT_TRANSITION (width);
+ }
+ }
+
+ vector[length - 1] = width + 1; /* Sentinel for the end of the vector. */
+ return vector;
+}
+
+/* Print a part of the bitmap in human-readable form. */
+
+void
+print_bounded_bitmap (FILE *f, bitmap_type bitmap, bounding_box_type bb)
+{
+ unsigned this_row, this_col;
+
+ fprintf (f, "Printing bitmap between (%u,%u) and (%u,%u):\n",
+ MIN_COL (bb), MIN_ROW (bb),
+ MAX_COL (bb), MAX_ROW (bb));
+ for (this_row = MIN_ROW (bb); this_row <= MAX_ROW (bb); this_row++)
+ {
+ for (this_col = MIN_COL (bb); this_col <= MAX_COL (bb); this_col++)
+ putc (BITMAP_PIXEL (bitmap, this_row, this_col) ? '*' : ' ', f);
+
+ fprintf (f, "%u\n", this_row);
+ }
+}
+
+
+void
+print_bitmap (FILE *f, bitmap_type b)
+{
+ print_bounded_bitmap (f, b, bitmap_to_bb (b));
+}
diff --git a/lib/bounding-box.c b/lib/bounding-box.c
new file mode 100644
index 0000000..25f0b74
--- /dev/null
+++ b/lib/bounding-box.c
@@ -0,0 +1,78 @@
+/* bounding-box.c: definitions for bounding box operations.
+
+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 "bounding-box.h"
+
+
+/* See the comments at `get_character_bitmap' in gf_input.c for why the
+ width and height are treated asymmetrically. */
+
+const bounding_box_type
+dimensions_to_bb (dimensions_type dimensions)
+{
+ bounding_box_type answer;
+
+ MIN_ROW (answer) = 0;
+ MIN_COL (answer) = 0;
+ MAX_ROW (answer) = MAX ((int) DIMENSIONS_HEIGHT (dimensions) - 1, 0);
+ MAX_COL (answer) = MAX (DIMENSIONS_WIDTH (dimensions), 0);
+
+ return answer;
+}
+
+
+/* Dimensions can't be negative, even though bounding boxes can, so we
+ have to check. */
+
+const dimensions_type
+bb_to_dimensions (bounding_box_type bb)
+{
+ dimensions_type d;
+
+ DIMENSIONS_WIDTH (d) = MAX (BB_WIDTH (bb), 0);
+ DIMENSIONS_HEIGHT (d) = MAX (BB_HEIGHT (bb), 0);
+
+ return d;
+}
+
+
+/* If the point P lies outside of any of the current bounds in BB,
+ update BB. */
+
+void
+update_real_bounding_box (real_bounding_box_type *bb, real_coordinate_type p)
+{
+ if (p.x < MIN_COL (*bb)) MIN_COL (*bb) = p.x;
+ if (p.x > MAX_COL (*bb)) MAX_COL (*bb) = p.x;
+ if (p.y < MIN_ROW (*bb)) MIN_ROW (*bb) = p.y;
+ if (p.y > MAX_ROW (*bb)) MAX_ROW (*bb) = p.y;
+
+}
+
+
+void
+update_bounding_box (bounding_box_type *bb, coordinate_type p)
+{
+ if (p.x < MIN_COL (*bb)) MIN_COL (*bb) = p.x;
+ if (p.x > MAX_COL (*bb)) MAX_COL (*bb) = p.x;
+ if (p.y < MIN_ROW (*bb)) MIN_ROW (*bb) = p.y;
+ if (p.y > MAX_ROW (*bb)) MAX_ROW (*bb) = p.y;
+
+}
diff --git a/lib/charcode.c b/lib/charcode.c
new file mode 100644
index 0000000..931928f
--- /dev/null
+++ b/lib/charcode.c
@@ -0,0 +1,85 @@
+/* charcode.c: parse character code strings into their values.
+
+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"
+
+
+/* This routine parses the string CHARCODE as a character code (see the
+ .h file). If CHARCODE cannot be parsed, *VALID is set to false and
+ the value returned is unpredictable; otherwise, it is set to true and
+ the value returned is the character code. */
+
+charcode_type
+parse_charcode (string charcode, boolean *valid)
+{
+ int code = 75; /* OK, it's not *really* unpredictable. */
+ unsigned length = strlen (charcode);
+
+ if (charcode == NULL || length == 0)
+ *valid = false;
+ else
+ { /* We need this to ensure that there are no extra characters after
+ the character code. */
+ char dummy;
+
+ /* If a single character, return its value. */
+ if (length == 1)
+ {
+ *valid = true;
+ code = *charcode;
+ }
+
+ else if (*charcode == '0')
+ { /* Either octal or hex. */
+ if (*(charcode + 1) == 'x' || *(charcode + 1) == 'X')
+ /* It seems not all scanf's ignore a leading `0x'. */
+ *valid = sscanf (charcode + 2, "%x%c", &code, &dummy) == 1;
+ else
+ /* octal */
+ *valid = sscanf (charcode, "%o%c", &code, &dummy) == 1;
+ }
+
+ else
+ /* decimal */
+ *valid = sscanf (charcode, "%d%c", &code, &dummy) == 1;
+
+ /* Since our return type can only hold numbers up to 255 (typically),
+ we are justified in using the numeric constant here, instead of
+ `MAX_CHARCODE'. */
+ if (*valid)
+ *valid = 0 <= code && code <= 255;
+ }
+
+ return code;
+}
+
+
+/* This routine calls `parse_charcode', and, if the character code is
+ invalid, gives a fatal error. */
+
+charcode_type
+xparse_charcode (string charcode)
+{
+ boolean valid;
+ charcode_type code = parse_charcode (charcode, &valid);
+
+ if (!valid)
+ FATAL1 ("xparse_charcode: Invalid character code `%s'", charcode);
+
+ return code;
+}
diff --git a/lib/charspec.c b/lib/charspec.c
new file mode 100644
index 0000000..cf7c407
--- /dev/null
+++ b/lib/charspec.c
@@ -0,0 +1,63 @@
+/* charspec.c: parse a character code or name.
+
+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 <kpathsea/c-ctype.h>
+#include "charspec.h"
+#include "encoding.h"
+
+
+charcode_type
+xparse_charspec (string spec, encoding_info_type *enc)
+{
+ int code;
+
+ /* It's an error to call this with SPEC == NULL or the empty string. */
+ assert (spec != NULL && *spec);
+
+ if (ISDIGIT (*spec))
+ code = xparse_charcode (spec);
+
+ else if (enc == NULL)
+ {
+ /* If ENC is null, and SPEC is longer than a single character, we
+ don't know what to do. */
+ if (spec[1] != 0)
+ FATAL1 ("%s: Unparseable character specification", spec);
+ else
+ code = *spec;
+ }
+
+ else
+ {
+ int code = encoding_number (*enc, spec);
+
+ /* If SPEC is not in the encoding, and it's one character long,
+ just use its value as a C integer. */
+ if (code == -1)
+ {
+ if (spec[1] == 0)
+ code = spec[0];
+ else
+ FATAL1 ("%s: Undefined character name", spec);
+ }
+ }
+
+ return (charcode_type) code;
+}
diff --git a/lib/cmdline.c b/lib/cmdline.c
new file mode 100644
index 0000000..3552fae
--- /dev/null
+++ b/lib/cmdline.c
@@ -0,0 +1,63 @@
+/* cmdline.c: routines to help in parsing command lines.
+
+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 "cmdline.h"
+
+
+/* This routine takes a string L consisting of unsigned integers
+ separated by commas and returns a vector of the integers, as numbers.
+ A element is appended to the vector. */
+
+int *
+scan_unsigned_list (string l)
+{
+ string map;
+ unsigned length = 1;
+ int *vector = xmalloc (sizeof (int));
+
+ for (map = strtok (l, ","); map != NULL; map = strtok (NULL, ","))
+ {
+ length++;
+ vector = xrealloc (vector, length * sizeof (int));
+ vector[length - 2] = atou (map);
+ if (vector[length - 2] < 0)
+ WARNING1 ("Unsigned number %u is too large", vector[length - 2]);
+ }
+
+ vector[length - 1] = -1;
+ return vector;
+}
+
+
+/* Return the <number> substring in `<name>.<number><stuff>', if S has
+ that form. If it doesn't, return NULL. */
+
+string
+find_dpi (string s)
+{
+ unsigned dpi_number;
+ string extension = strrchr (s, '.');
+
+ if (extension != NULL)
+ if (sscanf (extension + 1, "%u", &dpi_number) == 1)
+ return utoa (dpi_number);
+
+ return NULL;
+}
diff --git a/lib/concat.c b/lib/concat.c
new file mode 100644
index 0000000..946ed19
--- /dev/null
+++ b/lib/concat.c
@@ -0,0 +1,41 @@
+/* concat.c: dynamic string concatenation.
+
+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"
+
+/* Return the concatenation of S1 and S2. This would be a prime place
+ to use varargs. */
+
+string
+concat P2C(const_string, s1, const_string, s2)
+{
+ string answer = NULL;
+
+ assert (s1 != NULL);
+ assert (s2 != NULL);
+
+ if (s1 != NULL && s2 != NULL)
+ {
+ answer = (string) xmalloc (strlen (s1) + strlen (s2) + 1);
+
+ strcpy (answer, s1);
+ strcat (answer, s2);
+ }
+
+ return answer;
+}
diff --git a/lib/concat3.c b/lib/concat3.c
new file mode 100644
index 0000000..383a54c
--- /dev/null
+++ b/lib/concat3.c
@@ -0,0 +1,40 @@
+/* concat3.c: concatenate three strings.
+
+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"
+
+string
+concat3 P3C(const_string, s1, const_string, s2, const_string, s3)
+{
+ string answer = NULL;
+
+ assert (s1 != NULL);
+ assert (s2 != NULL);
+ assert (s3 != NULL);
+
+ if (s1 != NULL && s2 != NULL && s3 != NULL)
+ {
+ answer = (string) xmalloc (strlen (s1) + strlen (s2) + strlen (s3) + 1);
+
+ strcpy (answer, s1);
+ strcat (answer, s2);
+ strcat (answer, s3);
+ }
+
+ return answer;
+}
diff --git a/lib/concat4.c b/lib/concat4.c
new file mode 100644
index 0000000..f8b3d06
--- /dev/null
+++ b/lib/concat4.c
@@ -0,0 +1,43 @@
+/* concat4.c: concatenate four strings.
+
+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"
+
+string
+concat4 P4C(const_string, s1, const_string, s2, const_string, s3,
+ const_string, s4)
+{
+ string answer = NULL;
+
+ assert (s1 != NULL);
+ assert (s2 != NULL);
+ assert (s3 != NULL);
+ assert (s4 != NULL);
+
+ if (s1 != NULL && s2 != NULL && s3 != NULL && s4 != NULL)
+ {
+ answer = (string) xmalloc (strlen (s1) + strlen (s2)
+ + strlen (s3) + strlen (s4) + 1);
+ strcpy (answer, s1);
+ strcat (answer, s2);
+ strcat (answer, s3);
+ strcat (answer, s4);
+ }
+
+ return answer;
+}
diff --git a/lib/concat5.c b/lib/concat5.c
new file mode 100644
index 0000000..fbf9601
--- /dev/null
+++ b/lib/concat5.c
@@ -0,0 +1,45 @@
+/* concat5.c: concatenate five strings.
+
+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"
+
+string
+concat5 P5C(const_string, s1, const_string, s2, const_string, s3,
+ const_string, s4, const_string, s5)
+{
+ string answer = NULL;
+
+ assert (s1 != NULL);
+ assert (s2 != NULL);
+ assert (s3 != NULL);
+ assert (s4 != NULL);
+ assert (s5 != NULL);
+
+ if (s1 != NULL && s2 != NULL && s3 != NULL && s4 != NULL && s5 != NULL)
+ {
+ answer = (string) xmalloc (strlen (s1) + strlen (s2) + strlen (s3)
+ + strlen (s4) + strlen (s5) + 1);
+ strcpy (answer, s1);
+ strcat (answer, s2);
+ strcat (answer, s3);
+ strcat (answer, s4);
+ strcat (answer, s5);
+ }
+
+ return answer;
+}
diff --git a/lib/dlsym.c b/lib/dlsym.c
new file mode 100644
index 0000000..c14ffdd
--- /dev/null
+++ b/lib/dlsym.c
@@ -0,0 +1,28 @@
+/*
+ * Stub interface to dynamic linker routines
+ * that SunOS uses but didn't ship with 4.1.
+ *
+ * The C library routine wcstombs in SunOS 4.1 tries to dynamically
+ * load some routines using the dlsym interface, described in dlsym(3x).
+ * Unfortunately SunOS 4.1 does not include the necessary library, libdl.
+ *
+ * The R5 Xlib uses wcstombs. If you link dynamcally, your program can
+ * run even with the unresolved reference to dlsym. However, if you
+ * link statically, you will encounter this bug. One workaround
+ * is to include these stub routines when you link.
+ */
+
+void *dlopen()
+{
+ return 0;
+}
+
+void *dlsym()
+{
+ return 0;
+}
+
+int dlclose()
+{
+ return -1;
+}
diff --git a/lib/edge.c b/lib/edge.c
new file mode 100644
index 0000000..7bec506
--- /dev/null
+++ b/lib/edge.c
@@ -0,0 +1,265 @@
+/* edge.c: operations on edges in bitmaps.
+
+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 "edge.h"
+
+
+/* We can move in any of eight directions as we are traversing
+ the outline. These numbers are not arbitrary; TRY_PIXEL depends on
+ them. */
+
+typedef enum
+{
+ north = 0, northwest = 1, west = 2, southwest = 3, south = 4,
+ southeast = 5, east = 6, northeast = 7
+} direction_type;
+
+
+static boolean is_marked_edge (edge_type, unsigned, unsigned, bitmap_type);
+static boolean is_outline_edge (edge_type, bitmap_type, unsigned, unsigned);
+static edge_type next_edge (edge_type);
+
+/* The following macros are used (directly or indirectly) by the
+ `next_outline_edge' routine. */
+
+/* Given the direction DIR of the pixel to test, decide which edge on
+ that pixel we are supposed to test. Because we've chosen the mapping
+ from directions to numbers carefully, we don't have to do much. */
+
+#define FIND_TEST_EDGE(dir) ((dir) / 2)
+
+
+/* Find how to move in direction DIR on the axis AXIS (either `ROW' or
+ `COL'). We are in the ``display'' coordinate system, with y
+ increasing downward and x increasing to the right. Therefore, we are
+ implementing the following table:
+
+ direction row delta col delta
+ north -1 0
+ south +1 0
+ east 0 +1
+ west 0 +1
+
+ with the other four directions (e.g., northwest) being the sum of
+ their components (e.g., north + west).
+
+ The first macro, `COMPUTE_DELTA', handles splitting up the latter
+ cases, all of which have been assigned odd numbers. */
+
+#define COMPUTE_DELTA(axis, dir) \
+ ((dir) % 2 != 0 \
+ ? COMPUTE_##axis##_DELTA ((dir) - 1) \
+ + COMPUTE_##axis##_DELTA (((dir) + 1) % 8) \
+ : COMPUTE_##axis##_DELTA (dir) \
+ )
+
+/* Now it is trivial to implement the four cardinal directions. */
+#define COMPUTE_ROW_DELTA(dir) \
+ ((dir) == north ? -1 : (dir) == south ? +1 : 0)
+
+#define COMPUTE_COL_DELTA(dir) \
+ ((dir) == west ? -1 : (dir) == east ? +1 : 0)
+
+
+/* See if the appropriate edge on the pixel from (row,col) in direction
+ DIR is on the outline. If so, update `row', `col', and `edge', and
+ break. We also use the variable `character' as the bitmap in which
+ to look. */
+
+#define TRY_PIXEL(dir) \
+ { \
+ int delta_r = COMPUTE_DELTA (ROW, dir); \
+ int delta_c = COMPUTE_DELTA (COL, dir); \
+ int test_row = *row + delta_r; \
+ int test_col = *col + delta_c; \
+ edge_type test_edge = FIND_TEST_EDGE (dir); \
+ \
+ if (BITMAP_VALID_PIXEL (character, test_row, test_col) \
+ && is_outline_edge (test_edge, character, test_row, test_col)) \
+ { \
+ *row = test_row; \
+ *col = test_col; \
+ *edge = test_edge; \
+ break; \
+ } \
+ }
+
+/* Finally, we are ready to implement the routine that finds the next
+ edge on the outline. We look first for an adjacent edge that is not
+ on the current pixel. We want to go around outside outlines
+ counterclockwise, and inside outlines clockwise (because that is how
+ both Metafont and Adobe Type 1 format want their curves to be drawn).
+
+ The very first outline (an outside one) on each character starts on a
+ top edge (STARTING_EDGE in edge.h defines this); so, if we're at a
+ top edge, we want to go only to the left (on the pixel to the west)
+ or down (on the same pixel), to begin with. Then, when we're on a
+ left edge, we want to go to the top edge (on the southwest pixel) or
+ to the left edge (on the south pixel).
+
+ All well and good. But if you draw a rasterized circle (or whatever),
+ eventually we have to come back around to the beginning; at that
+ point, we'll be on a top edge, and we'll have to go to the right edge
+ on the northwest pixel. Draw pictures.
+
+ The upshot is, if we find an edge on another pixel, we return (in ROW
+ and COL) the position of the new pixel, and (in EDGE) the kind of
+ edge it is. If we don't find such an edge, we return (in EDGE) the
+ next (in a counterclockwise direction) edge on the current pixel. */
+
+void
+next_outline_edge (bitmap_type character, edge_type *edge,
+ unsigned *row, unsigned *col)
+{
+ unsigned original_row = *row;
+ unsigned original_col = *col;
+
+ switch (*edge)
+ {
+ case right:
+ TRY_PIXEL (north);
+ TRY_PIXEL (northeast);
+ break;
+
+ case top:
+ TRY_PIXEL (west);
+ TRY_PIXEL (northwest);
+ break;
+
+ case left:
+ TRY_PIXEL (south);
+ TRY_PIXEL (southwest);
+ break;
+
+ case bottom:
+ TRY_PIXEL (east);
+ TRY_PIXEL (southeast);
+ break;
+
+ default:
+ FATAL1 ("next_outline_edge: Bad edge value (%d)", *edge);
+
+ }
+
+ /* If we didn't find an adjacent edge on another pixel, return the
+ next edge on the current pixel. */
+ if (*row == original_row && *col == original_col)
+ *edge = next_edge (*edge);
+}
+
+/* We return the next edge on the pixel at position ROW and COL which is
+ an unmarked outline edge. By ``next'' we mean either the one sent in
+ in STARTING_EDGE, if it qualifies, or the next such returned by
+ `next_edge'. Otherwise, it returns NO_EDGE. */
+
+edge_type
+next_unmarked_outline_edge (unsigned row, unsigned col,
+ edge_type starting_edge, bitmap_type character,
+ bitmap_type marked)
+{
+ edge_type edge = starting_edge;
+
+ assert (edge != no_edge);
+
+ while (is_marked_edge (edge, row, col, marked)
+ || !is_outline_edge (edge, character, row, col))
+ {
+ edge = next_edge (edge);
+ if (edge == starting_edge)
+ return no_edge;
+ }
+
+ return edge;
+}
+
+
+/* We check to see if the edge EDGE of the pixel at position ROW and COL
+ is an outline edge; i.e., that it is a black pixel which shares that
+ edge with a white pixel. The position ROW and COL should be inside
+ the bitmap CHARACTER. */
+
+boolean
+is_outline_edge (edge_type edge, bitmap_type character,
+ unsigned row, unsigned col)
+{
+ /* If this pixel isn't black, it's not part of the outline. */
+ if (BITMAP_PIXEL (character, row, col) == WHITE)
+ return false;
+
+ switch (edge)
+ {
+ case left:
+ return col == 0 || BITMAP_PIXEL (character, row, col - 1) == WHITE;
+
+ case top:
+ return row == 0 || BITMAP_PIXEL (character, row - 1, col) == WHITE;
+
+ case right:
+ return col == BITMAP_WIDTH (character) - 1
+ || BITMAP_PIXEL (character, row, col + 1) == WHITE;
+
+ case bottom:
+ return row == BITMAP_HEIGHT (character) - 1
+ || BITMAP_PIXEL (character, row + 1, col) == WHITE;
+
+ case no_edge:
+ default:
+ FATAL1 ("is_outline_edge: Bad edge value(%d)", edge);
+ }
+
+ return 0; /* NOTREACHED */
+}
+
+/* If EDGE is not already marked, we mark it; otherwise, it's a fatal error.
+ The position ROW and COL should be inside the bitmap MARKED. EDGE can
+ be `no_edge'; we just return false. */
+
+void
+mark_edge (edge_type edge, unsigned row, unsigned col, bitmap_type *marked)
+{
+ assert (!is_marked_edge (edge, row, col, *marked));
+
+ if (edge != no_edge)
+ BITMAP_PIXEL (*marked, row, col) |= 1 << edge;
+}
+
+
+/* Test if the edge EDGE at ROW/COL in MARKED is marked. */
+
+static boolean
+is_marked_edge (edge_type edge, unsigned row, unsigned col, bitmap_type marked)
+{
+ return
+ edge == no_edge ? false : BITMAP_PIXEL (marked, row, col) & (1 << edge);
+}
+
+
+/* Return the edge which is counterclockwise-adjacent to EDGE. This
+ code makes use of the ``numericness'' of C enumeration constants;
+ sorry about that. */
+
+#define NUM_EDGES no_edge
+
+static edge_type
+next_edge (edge_type edge)
+{
+ return edge == no_edge ? edge : (edge + 1) % NUM_EDGES;
+}
+
diff --git a/lib/encoding.c b/lib/encoding.c
new file mode 100644
index 0000000..a40d281
--- /dev/null
+++ b/lib/encoding.c
@@ -0,0 +1,191 @@
+/* encoding.c: read a font encoding (.enc) file.
+
+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 "encoding.h"
+#include "libfile.h"
+#include "str-lcase.h"
+#include "tfm.h"
+
+
+static encoding_char_type parse_encoding_line (string);
+static tfm_ligature_type parse_ligature (void);
+
+/* Look through INFO for NAME. */
+
+int
+encoding_number (encoding_info_type info, string name)
+{
+ unsigned code;
+
+ if (name == NULL)
+ return -1;
+
+ for (code = 0; code <= MAX_CHARCODE; code++)
+ if (ENCODING_CHAR_NAME (info, code) != NULL
+ && STREQ (ENCODING_CHAR_NAME (info, code), name))
+ return code;
+
+ return -1;
+}
+
+/* Return the basename for the encoding file in which the encoding
+ CODING_SCHEME can be found. If we can't find CODING_SCHEME, return
+ DEFAULT_ENCODING. */
+
+string
+coding_scheme_to_filename (string coding_scheme)
+{
+ string mapping_line, enc_name;
+ string lc_coding_scheme = str_to_lower (coding_scheme);
+
+ libfile_start ("encoding", "map");
+
+ while ((mapping_line = libfile_line ()) != NULL)
+ {
+ string test_coding_scheme, lc_test_coding_scheme;
+
+ enc_name = strtok (mapping_line, " \t");
+ test_coding_scheme = strtok (NULL, "\t");
+ lc_test_coding_scheme = str_to_lower (test_coding_scheme);
+
+ if (STREQ (lc_coding_scheme, lc_test_coding_scheme))
+ break;
+
+ free (lc_test_coding_scheme);
+ free (mapping_line);
+ }
+
+ libfile_close ();
+
+ if (mapping_line == NULL)
+ {
+ WARNING3 ("%s: unknown encoding `%s'; using default `%s'",
+ "encoding.map", coding_scheme, DEFAULT_ENCODING);
+ enc_name = DEFAULT_ENCODING;
+ }
+
+ free (lc_coding_scheme);
+
+ return enc_name;
+}
+
+/* Parse the encoding file `FILENAME.enc' and return a structure
+ describing what we read. If the file doesn't exist, give a fatal
+ error. */
+
+encoding_info_type
+read_encoding_file (string filename)
+{
+ encoding_info_type info;
+ string line;
+ unsigned code;
+
+ /* Prepare to read from FILENAME. */
+ libfile_start (filename, "enc");
+
+ /* Start with an empty encoding. */
+ for (code = 0; code <= MAX_CHARCODE; code++)
+ ENCODING_CHAR_NAME (info, code) = NULL;
+
+ /* The entire first line is the TFM `CODINGSCHEME'. */
+ ENCODING_SCHEME_NAME (info) = libfile_line ();
+
+ /* Each remaining line defines one character. */
+ code = 0;
+ while ((line = libfile_line ()) != NULL)
+ {
+ ENCODING_CHAR_ELT (info, code) = parse_encoding_line (line);
+ code++;
+ free (line);
+ }
+
+ return info;
+}
+
+/* Parse one line of the encoding file; this specifies one character.
+ The BNF is:
+
+ <line> ::= <word> <ligatures>
+
+ <ligatures> ::= <ligature> [<ligature>]?
+ | <empty>
+
+ <ligature> ::= lig <charcode> =: <charcode>
+
+ Whitespace must be between all elements.
+
+ If the line is malformed, we give a fatal error. */
+
+#define WORD_SEPARATOR " \t"
+#define GET_WORD() strtok (NULL, WORD_SEPARATOR)
+
+static encoding_char_type
+parse_encoding_line (string line)
+{
+ encoding_char_type c;
+
+ c.name = xstrdup (strtok (line, WORD_SEPARATOR));
+ c.ligature = list_init ();
+
+ do
+ {
+ tfm_ligature_type *lig;
+ string t = GET_WORD ();
+
+ if (t == NULL) /* Do we have more ligature specs? */
+ break;
+
+ if (!STREQ (t, "lig"))
+ LIBFILE_ERROR1 ("Expected `lig', found `%s'", t);
+
+ lig = LIST_TAPPEND (&c.ligature, tfm_ligature_type);
+ *lig = parse_ligature ();
+ }
+ while (true);
+
+ return c;
+}
+
+
+/* Parse a single ligature: <charcode> =: <charcode>. */
+
+static tfm_ligature_type
+parse_ligature ()
+{
+ tfm_ligature_type lig;
+ boolean valid;
+ string t = GET_WORD ();
+
+ lig.character = parse_charcode (t, &valid);
+
+ if (!valid)
+ LIBFILE_ERROR1 ("Invalid right character code `%s'", t);
+
+ t = GET_WORD ();
+ if (!STREQ (t, "=:"))
+ LIBFILE_ERROR1 ("Expected `=:', found `%s'", t);
+
+ t = GET_WORD ();
+ lig.ligature = parse_charcode (t, &valid);
+ if (!valid)
+ LIBFILE_ERROR1 ("Invalid ligature character code `%s'", t);
+
+ return lig;
+}
diff --git a/lib/file-input.c b/lib/file-input.c
new file mode 100644
index 0000000..1bc138b
--- /dev/null
+++ b/lib/file-input.c
@@ -0,0 +1,158 @@
+/* file-input.c: file reading routines for binary files in BigEndian
+ order, 2's complement representation.
+
+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 "file-input.h"
+
+
+one_byte
+get_byte (FILE *f, string filename)
+{
+ one_byte b;
+
+ if (fread (&b, 1, 1, f) != 1)
+ FATAL_PERROR (concat3 ("get_byte (", filename, ")"));
+
+ return b;
+}
+
+
+two_bytes
+get_two (FILE *f, string filename)
+{
+ two_bytes b;
+
+ b = get_byte (f, filename) << 8;
+ b |= get_byte (f, filename);
+
+ return b;
+}
+
+
+four_bytes
+get_four (FILE *f, string filename)
+{
+ four_bytes b;
+
+ b = get_byte (f, filename) << 24;
+ b |= get_byte (f, filename) << 16;
+ b |= get_byte (f, filename) << 8;
+ b |= get_byte (f, filename);
+
+ return b;
+}
+
+
+/* In order to get a signed value, we merely read an unsigned value and
+ cast it; the value in the file is assumed to be 2's complement. */
+
+signed_4_bytes
+get_signed_four (FILE *f, string filename)
+{
+ return (signed_4_bytes) get_four (f, filename);
+}
+
+
+/* Return the next N bytes in the file F as an array. */
+
+address
+get_n_bytes (unsigned n, FILE *f, string filename)
+{
+ one_byte *b;
+
+ if (n == 0)
+ FATAL1 ("get_n_bytes (%s): can't get zero bytes", filename);
+
+ b = xmalloc (n);
+
+ if (fread (b, n, 1, f) != 1)
+ FATAL2 ("get_n_bytes (%s): fread of %u bytes failed", filename, n);
+
+ return b;
+}
+
+
+
+/* Reading backwards. This macro is shared among all the routines by assuming
+ the name `f' for the file pointer. */
+
+#define MOVE_BACK(size) xfseek (f, (long) -size, SEEK_CUR, filename)
+
+one_byte
+get_previous_byte (FILE *f, string filename)
+{
+ one_byte b;
+
+ MOVE_BACK (1);
+ b = get_byte (f, filename);
+ MOVE_BACK (1);
+ return b;
+}
+
+
+two_bytes
+get_previous_two (FILE *f, string filename)
+{
+ two_bytes b;
+
+ MOVE_BACK (2);
+ b = get_two (f, filename);
+ MOVE_BACK (2);
+
+ return b;
+}
+
+
+
+four_bytes
+get_previous_four (FILE *f, string filename)
+{
+ four_bytes b;
+
+ MOVE_BACK (4);
+ b = get_four (f, filename);
+ MOVE_BACK (4);
+
+ return b;
+}
+
+
+
+/* Looking for specific values in the input. */
+
+void
+match_byte (one_byte expected, FILE *f, string filename)
+{
+ one_byte b = get_byte (f, filename);
+
+ if (b != expected)
+ FATAL3 ("%s: Expected byte value %u, found %u", filename, expected, b);
+}
+
+
+void
+match_previous_byte (one_byte expected, FILE *f, string filename)
+{
+ one_byte b = get_previous_byte (f, filename);
+
+ if (b != expected)
+ FATAL3 ("%s: Expected previous byte value %u, found %u", filename,
+ expected, b);
+}
diff --git a/lib/file-output.c b/lib/file-output.c
new file mode 100644
index 0000000..94559ec
--- /dev/null
+++ b/lib/file-output.c
@@ -0,0 +1,73 @@
+/* file-output.c: file writing routines for binary files in BigEndian
+ order, 2's complement representation.
+
+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 "file-output.h"
+
+
+/* Output in BigEndian order. We could do these more efficiently by
+ checking if the hardware already uses BigEndian order, but it's not
+ worth it. These routines are never the bottleneck (in the ways
+ they've been used so far, anyway). We assume that we write negative
+ numbers in 2's complement, also. */
+
+void
+put_byte (one_byte b, FILE *f, string filename)
+{
+ if (fwrite (&b, 1, 1, f) != 1)
+ FATAL2 ("%s: Could not write byte %u", filename, b);
+}
+
+
+void
+put_two (two_bytes b, FILE *f, string filename)
+{
+ put_byte ((b & 0xff00) >> 8, f, filename); /* High-order byte. */
+ put_byte (b & 0x00ff, f, filename); /* And low-order. */
+}
+
+
+void
+put_three (four_bytes b, FILE *f, string filename)
+{
+ put_byte ((b & 0x00ff0000) >> 16, f, filename);
+ put_byte ((b & 0x0000ff00) >> 8, f, filename);
+ put_byte (b & 0x000000ff, f, filename);
+}
+
+
+void
+put_four (four_bytes b, FILE *f, string filename)
+{
+ put_byte ((b & 0xff000000) >> 24, f, filename);
+ put_byte ((b & 0x00ff0000) >> 16, f, filename);
+ put_byte ((b & 0x0000ff00) >> 8, f, filename);
+ put_byte (b & 0x000000ff, f, filename);
+}
+
+
+void
+put_n_bytes (unsigned n, address b, FILE *f, string filename)
+{
+ one_byte *data_b = b; /* We can't dereference a pure `address'. */
+
+ if (fwrite (data_b, n, 1, f) != 1)
+ FATAL2 ("%s: Could not write %u-byte block", filename, n);
+}
diff --git a/lib/filename.c b/lib/filename.c
new file mode 100644
index 0000000..b85d095
--- /dev/null
+++ b/lib/filename.c
@@ -0,0 +1,99 @@
+/* filename.c: routines to manipulate filenames.
+
+Copyright (C) 1992, 93 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 "paths.h"
+
+#include "filename.h"
+#include "pathsrch.h"
+
+
+/* Try to find the PK font FONT_NAME at resolution DPI, using various
+ paths (see `filename.h'). The filename must have the resolution as
+ part of the extension, e.g., `cmr10.300pk', for it to be found. */
+
+string
+find_pk_filename (string font_name, unsigned dpi)
+{
+ static string *dirs = NULL;
+ string pk_var, pk_name, name;
+ char suffix[MAX_INT_LENGTH + sizeof ".pk"];
+
+ sprintf (suffix, ".%dpk", dpi);
+
+ pk_var = getenv ("PKFONTS") ? "PKFONTS"
+ : getenv ("TEXPKS") ? "TEXPKS" : "TEXFONTS";
+
+ if (dirs == NULL)
+ dirs = initialize_path_list (pk_var, DEFAULT_PK_PATH);
+
+ name = concat (font_name, suffix);
+ pk_name = find_path_filename (name, dirs);
+
+ if (name != pk_name)
+ free (name);
+
+ return pk_name;
+}
+
+
+/* Like `find_pk_filename', but search for a font in GF format. */
+
+string
+find_gf_filename (string font_name, unsigned dpi)
+{
+ static string *dirs = NULL;
+ string gf_var, gf_name, name;
+ char suffix[MAX_INT_LENGTH + sizeof ".pk"];
+
+ sprintf (suffix, ".%dgf", dpi);
+
+ gf_var = getenv ("GFFONTS") ? "GFFONTS" : "TEXFONTS";
+
+ if (dirs == NULL)
+ dirs = initialize_path_list (gf_var, DEFAULT_GF_PATH);
+
+ name = concat (font_name, suffix);
+ gf_name = find_path_filename (name, dirs);
+
+ if (name != gf_name)
+ free (name);
+
+ return gf_name;
+}
+
+
+/* Like `find_pk_filename', except search for a TFM file. */
+
+string
+find_tfm_filename (string font_name)
+{
+ static string *dirs = NULL;
+ string tfm_name, name;
+
+ if (dirs == NULL)
+ dirs = initialize_path_list ("TEXFONTS", DEFAULT_TFM_PATH);
+
+ name = extend_filename (font_name, "tfm");
+ tfm_name = find_path_filename (name, dirs);
+
+ if (name != tfm_name)
+ free (name);
+
+ return tfm_name;
+}
diff --git a/lib/fix-num.c b/lib/fix-num.c
new file mode 100644
index 0000000..2827d2c
--- /dev/null
+++ b/lib/fix-num.c
@@ -0,0 +1,43 @@
+/* fix-num.c: conversions on ``fixnums'', which are a 32-bit
+ word with 20 bits of fraction.
+
+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 "fix-num.h"
+
+
+#define FIX_UNITY (1 << 20)
+
+
+const real
+fix_to_real (fix_word f)
+{
+ real r = f / FIX_UNITY + ((real) (f % FIX_UNITY) / (real) FIX_UNITY);
+
+ return r;
+}
+
+
+const fix_word
+real_to_fix (real r)
+{
+ fix_word f = floor (r) * FIX_UNITY + (r - floor (r)) * FIX_UNITY;
+
+ return f;
+}
diff --git a/lib/float-ok.c b/lib/float-ok.c
new file mode 100644
index 0000000..b3e81d6
--- /dev/null
+++ b/lib/float-ok.c
@@ -0,0 +1,60 @@
+/* float-ok.c: test if a string is a valid floating-point number.
+
+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 <kpathsea/c-ctype.h>
+
+
+/* Actually, we don't worry about a trailing exponent. */
+
+boolean
+float_ok (string str)
+{
+ boolean found_digit = false;
+
+ if (str == NULL)
+ return false;
+
+ /* Allow leading `-' or `+' sign (but digits must follow). */
+ if (*str == '-' || *str == '+')
+ {
+ str++;
+ }
+
+ /* Skip decimal digits. */
+ while (ISDIGIT (*str))
+ {
+ str++;
+ found_digit = true;
+ }
+
+ /* If a `.' follows, can have more digits. */
+ if (*str == '.')
+ {
+ str++;
+ while (ISDIGIT (*str))
+ {
+ str++;
+ found_digit = true;
+ }
+ }
+
+ return *str == 0 && found_digit;
+}
+
diff --git a/lib/fmod.c b/lib/fmod.c
new file mode 100644
index 0000000..0c78f52
--- /dev/null
+++ b/lib/fmod.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that: (1) source distributions retain this entire copyright
+ * notice and comment, and (2) distributions including binaries display
+ * the following acknowledgement: ``This product includes software
+ * developed by the University of California, Berkeley and its contributors''
+ * in the documentation or other materials provided with the distribution
+ * and in all advertising materials mentioning features or use of this
+ * software. Neither the name of the University nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)fmod.c 5.2 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+/* fmod.c
+ *
+ * SYNOPSIS
+ *
+ * #include <math.h>
+ * double fmod(double x, double y)
+ *
+ * DESCRIPTION
+ *
+ * The fmod function computes the floating-point remainder of x/y.
+ *
+ * RETURNS
+ *
+ * The fmod function returns the value x-i*y, for some integer i
+ * such that, if y is nonzero, the result has the same sign as x and
+ * magnitude less than the magnitude of y.
+ *
+ * On a VAX or CCI,
+ *
+ * fmod(x,0) traps/faults on floating-point divided-by-zero.
+ *
+ * On IEEE-754 conforming machines with "isnan()" primitive,
+ *
+ * fmod(x,0), fmod(INF,y) are invalid operations and NaN is returned.
+ *
+ */
+#include <math.h> /* changed from "mathimpl.h" --karl */
+
+#if !defined(vax) && !defined(tahoe)
+extern int isnan(),finite();
+#endif /* !defined(vax) && !defined(tahoe) */
+extern double frexp(),ldexp(),fabs();
+
+#ifdef TEST_FMOD
+static double
+_fmod(x,y)
+#else /* TEST_FMOD */
+double
+fmod(x,y)
+#endif /* TEST_FMOD */
+double x,y;
+{
+ int ir,iy;
+ double r,w;
+
+ if (y == (double)0
+#if 0 /* removed this --karl */
+#if !defined(vax) && !defined(tahoe) /* per "fmod" manual entry, SunOS 4.0 */
+ || isnan(y) || !finite(x)
+#endif /* !defined(vax) && !defined(tahoe) */
+#endif
+ )
+ return (x*y)/(x*y);
+
+ r = fabs(x);
+ y = fabs(y);
+ (void)frexp(y,&iy);
+ while (r >= y) {
+ (void)frexp(r,&ir);
+ w = ldexp(y,ir-iy);
+ r -= w <= r ? w : w*(double)0.5;
+ }
+ return x >= (double)0 ? r : -r;
+}
+
+#ifdef TEST_FMOD
+extern long random();
+extern double fmod();
+
+#define NTEST 10000
+#define NCASES 3
+
+static int nfail = 0;
+
+static void
+doit(x,y)
+double x,y;
+{
+ double ro = fmod(x,y),rn = _fmod(x,y);
+ if (ro != rn) {
+ (void)printf(" x = 0x%08.8x %08.8x (%24.16e)\n",x,x);
+ (void)printf(" y = 0x%08.8x %08.8x (%24.16e)\n",y,y);
+ (void)printf(" fmod = 0x%08.8x %08.8x (%24.16e)\n",ro,ro);
+ (void)printf("_fmod = 0x%08.8x %08.8x (%24.16e)\n",rn,rn);
+ (void)printf("\n");
+ }
+}
+
+main()
+{
+ register int i,cases;
+ double x,y;
+
+ srandom(12345);
+ for (i = 0; i < NTEST; i++) {
+ x = (double)random();
+ y = (double)random();
+ for (cases = 0; cases < NCASES; cases++) {
+ switch (cases) {
+ case 0:
+ break;
+ case 1:
+ y = (double)1/y; break;
+ case 2:
+ x = (double)1/x; break;
+ default:
+ abort(); break;
+ }
+ doit(x,y);
+ doit(x,-y);
+ doit(-x,y);
+ doit(-x,-y);
+ }
+ }
+ if (nfail)
+ (void)printf("Number of failures: %d (out of a total of %d)\n",
+ nfail,NTEST*NCASES*4);
+ else
+ (void)printf("No discrepancies were found\n");
+ exit(0);
+}
+#endif /* TEST_FMOD */
diff --git a/lib/font.c b/lib/font.c
new file mode 100644
index 0000000..e2b9a71
--- /dev/null
+++ b/lib/font.c
@@ -0,0 +1,466 @@
+/* font.c: define (more or less) format-independent font operations.
+
+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 <kpathsea/tex-file.h>
+#include <kpathsea/pathsearch.h>
+#include <kpathsea/paths.h>
+#include <kpathsea/c-ctype.h>
+
+#include "filename.h"
+#include "font.h"
+#include "gf.h"
+#include "list.h"
+#include "pk.h"
+#include "tfm.h"
+
+
+/* We want to allow reading of multiple fonts, so we keep some
+ information around for each font we read. */
+
+typedef struct
+{
+ bitmap_format_type bitmap_format;
+ boolean bitmap_only;
+ font_info_type info;
+} internal_font_type;
+
+/* The format of the bitmap file for this font. */
+#define INTERNAL_BITMAP_FORMAT(i) ((i).bitmap_format)
+
+/* If the font was opened with `get_bitmap_font', this field is true;
+ if with `get_font', false. */
+#define INTERNAL_BITMAP_ONLY(i) ((i).bitmap_only)
+
+/* The filename for the bitmap font. */
+#define INTERNAL_BITMAP_NAME(i) ((i).bitmap_name)
+
+/* The fontwide information. The parts of this that are found in the
+ TFM file are garbage if INTERNAL_BITMAP_ONLY (I) is true. */
+#define INTERNAL_FONT_INFO(i) ((i).info)
+
+
+static void delete_internal_font (string filename);
+static internal_font_type *find_internal_font (string font_name);
+static void save_internal_font (string font_name, internal_font_type);
+
+/* Starting with FONT_NAME as the base filename, e.g., `cmr10', we try
+ various extensions to find a PK or GF file at resolution DPI. This
+ bitmap font defines the shapes of the characters. */
+
+bitmap_font_type
+get_bitmap_font (string font_name, unsigned dpi)
+{
+ bitmap_font_type font;
+ internal_font_type internal_f;
+ internal_font_type *internal_font_ptr;
+ string pk_name, gf_name;
+ boolean found_pk = false, found_gf = false;
+
+ /* If we are passed a null pointer or the empty string, it's got to be
+ a mistake. */
+ assert (font_name && *font_name);
+
+ /* If we already have the font saved, we just return it, thus (1) saving
+ going out to the file system, and (2) causing multiple calls with
+ the same FONT_NAME not to open more and more bitmap files. */
+ internal_font_ptr = find_internal_font (font_name);
+ if (internal_font_ptr != NULL)
+ return FONT_BITMAP_FONT (INTERNAL_FONT_INFO (*internal_font_ptr));
+
+ pk_name = find_pk_filename (font_name, dpi);
+ if (pk_name != NULL)
+ { /* Found the PK file, so unless something strange is happening
+ (like the file being removed between the `find_path_filename'
+ call and the `pk_open_input_file' call), we will be able to
+ open it. */
+ found_pk = pk_open_input_file (pk_name);
+ if (!found_pk)
+ FATAL_PERROR (pk_name);
+ }
+ else if ((gf_name = find_gf_filename (font_name, dpi)) != NULL)
+ {
+ found_gf = gf_open_input_file (gf_name);
+ if (!found_gf)
+ {
+ perror (gf_name);
+ FATAL1 ("(I couldn't find the PK file `%s', either.)", pk_name);
+ }
+ }
+ else
+ FATAL2 ("%s.%d{gf,pk}: Nowhere in path", font_name, dpi);
+
+
+ /* We've opened the files; get the information we need to return. */
+ if (found_pk)
+ {
+ pk_preamble_type preamble = pk_get_preamble (pk_name);
+
+ BITMAP_FONT_DESIGN_SIZE (font)
+ = fix_to_real (PK_DESIGN_SIZE (preamble));
+ BITMAP_FONT_COMMENT (font) = PK_COMMENT (preamble);
+ BITMAP_FONT_CHECKSUM (font) = PK_CHECKSUM (preamble);
+ BITMAP_FONT_FILENAME (font) = pk_name;
+
+ INTERNAL_BITMAP_FORMAT (internal_f) = pk_format;
+ }
+ else if (found_gf)
+ {
+ gf_postamble_type postamble = gf_get_postamble ();
+
+ BITMAP_FONT_DESIGN_SIZE (font)
+ = fix_to_real (GF_DESIGN_SIZE (postamble));
+ BITMAP_FONT_COMMENT (font) = gf_get_preamble ();
+ BITMAP_FONT_CHECKSUM (font) = GF_CHECKSUM (postamble);
+ BITMAP_FONT_FILENAME (font) = gf_name;
+
+ INTERNAL_BITMAP_FORMAT (internal_f) = gf_format;
+ }
+ else
+ FATAL ("No bitmap file found, but I must have found one");
+
+ FONT_BITMAP_FONT (INTERNAL_FONT_INFO (internal_f)) = font;
+ INTERNAL_BITMAP_ONLY (internal_f) = true;
+
+ save_internal_font (font_name, internal_f);
+
+ return font;
+}
+
+
+/* Look for both a bitmap font named FONT_NAME, and for the TFM file
+ FONT_NAME.tfm. We call `get_bitmap_font' to find the bitmap font.
+ For the TFM file, we use the path in the environment variable
+ TEXFONTS; if TEXFONTS isn't set, we use the default defined above.
+
+ If FONT_NAME was previously opened with `get_bitmap_font', we give a
+ fatal error. */
+
+font_info_type
+get_font (string font_name, unsigned dpi)
+{
+ unsigned bitmap_checksum;
+ font_info_type font;
+ internal_font_type internal_f;
+ internal_font_type *internal_font_ptr;
+ unsigned tfm_checksum;
+ string tfm_name;
+
+ /* If we are passed a null pointer or the empty string, it's got to be
+ a mistake. */
+ assert (font_name != NULL && *font_name);
+
+ /* If we already have the font saved, we just return it, thus (1) saving
+ going out to the file system, and (2) causing multiple calls with
+ the same FONT_NAME not to open more and more bitmap files. */
+ internal_font_ptr = find_internal_font (font_name);
+ if (internal_font_ptr != NULL)
+ if (INTERNAL_BITMAP_ONLY (*internal_font_ptr))
+ FATAL1 ("get_font: `%s' was opened with get_bitmap_font", font_name);
+ else
+ return INTERNAL_FONT_INFO (*internal_font_ptr);
+
+ /* If we don't have the font saved, we have to look for the TFM file. */
+ tfm_name = kpse_find_tfm (font_name);
+
+ if (tfm_name == NULL)
+ FATAL1 ("%s.tfm: Nowhere in path", font_name);
+
+ if (!tfm_open_input_file (tfm_name))
+ FATAL_PERROR (tfm_name);
+
+
+ /* The TFM file is opened. Save some global information. */
+ FONT_TFM_FONT (font) = tfm_get_global_info ();
+ FONT_TFM_FILENAME (font) = tfm_name;
+
+ /* Read the (we hope) corresponding bitmap file. */
+ FONT_BITMAP_FONT (font) = get_bitmap_font (font_name, dpi);
+
+ /* We have found the bitmap font on the filesystem, so it should be in
+ our internal list now. We will overwrite it below. */
+ internal_font_ptr = find_internal_font (font_name);
+ assert (internal_font_ptr != NULL);
+
+ /* We've opened the files; now get the information we're supposed to
+ return. */
+
+ /* Let's check the checksums. */
+ tfm_checksum = tfm_get_checksum ();
+ bitmap_checksum = BITMAP_FONT_CHECKSUM (FONT_BITMAP_FONT (font));
+
+ if (tfm_checksum != 0 && bitmap_checksum != 0
+ && tfm_checksum != bitmap_checksum)
+ WARNING1 ("%s: TFM and bitmap checksums don't match", font_name);
+
+ INTERNAL_FONT_INFO (internal_f) = font;
+ INTERNAL_BITMAP_ONLY (internal_f) = false;
+ INTERNAL_BITMAP_FORMAT (internal_f)
+ = INTERNAL_BITMAP_FORMAT (*internal_font_ptr);
+ save_internal_font (font_name, internal_f);
+
+ return font;
+}
+
+/* Close the files we have opened, for tidiness. */
+
+void
+close_font (string font_name)
+{
+ internal_font_type *f = find_internal_font (font_name);
+
+ if (f == NULL)
+ FATAL1 ("close_font: Font `%s' not open", font_name);
+
+ switch (INTERNAL_BITMAP_FORMAT (*f))
+ {
+ case pk_format:
+ {
+ string pk_name
+ = BITMAP_FONT_FILENAME (FONT_BITMAP_FONT (INTERNAL_FONT_INFO (*f)));
+ pk_close_input_file (pk_name);
+ }
+ break;
+
+ case gf_format:
+ gf_close_input_file ();
+ break;
+
+ default:
+ FATAL1 ("Impossible bitmap format (%d)", INTERNAL_BITMAP_FORMAT (*f));
+ }
+
+ if (!INTERNAL_BITMAP_ONLY (*f))
+ tfm_close_input_file ();
+
+ delete_internal_font (font_name);
+}
+
+/* Look for the character numbered CODE in the font FONT_NAME. If it
+ doesn't exist, return NULL. Otherwise, fill in a `char_info_type'
+ structure and return a pointer to it.
+
+ This merely calls the get-a-character routine in the appropriate
+ library. */
+
+char_info_type *
+get_char (string font_name, one_byte code)
+{
+ char_info_type *c;
+ internal_font_type *f = find_internal_font (font_name);
+
+ if (f == NULL)
+ FATAL1 ("get_char: Font `%s' not open", font_name);
+
+ switch (INTERNAL_BITMAP_FORMAT (*f))
+ {
+ case pk_format:
+ {
+ string pk_name
+ = BITMAP_FONT_FILENAME (FONT_BITMAP_FONT (INTERNAL_FONT_INFO (*f)));
+ pk_char_type *pk_char = pk_get_char (code, pk_name);
+ if (pk_char == NULL) return NULL;
+
+ c = XTALLOC1 (char_info_type);
+ CHARCODE (*c) = PK_CHARCODE (*pk_char);
+ CHAR_SET_WIDTH (*c) = PK_H_ESCAPEMENT (*pk_char);
+ CHAR_TFM_WIDTH (*c) = PK_TFM_WIDTH (*pk_char);
+ CHAR_BB (*c) = PK_CHAR_BB (*pk_char);
+ CHAR_BITMAP (*c) = PK_BITMAP (*pk_char);
+ }
+ break;
+
+ case gf_format:
+ {
+ gf_char_type *gf_char = gf_get_char (code);
+ if (gf_char == NULL) return NULL;
+
+ c = XTALLOC1 (char_info_type);
+ CHARCODE (*c) = GF_CHARCODE (*gf_char);
+ CHAR_SET_WIDTH (*c) = GF_H_ESCAPEMENT (*gf_char);
+ CHAR_TFM_WIDTH (*c) = GF_TFM_WIDTH (*gf_char);
+ CHAR_BB (*c) = GF_CHAR_BB (*gf_char);
+ CHAR_BITMAP (*c) = GF_BITMAP (*gf_char);
+ }
+ break;
+
+ default:
+ FATAL1 ("Impossible bitmap format (%d)", INTERNAL_BITMAP_FORMAT (*f));
+ }
+
+ return c;
+}
+
+/* Look for the character numbered CODE in the font FONT_NAME. If it
+ doesn't exist, return NULL. Otherwise, fill in a `raw_char_type'
+ structure and return a pointer to it.
+
+ This merely calls the corresponding routine in the appropriate
+ library. */
+
+raw_char_type *
+get_raw_char (string font_name, one_byte code)
+{
+ raw_char_type *c;
+ internal_font_type *f = find_internal_font (font_name);
+
+ if (f == NULL)
+ FATAL1 ("get_raw_char: Font `%s' not open", font_name);
+
+ switch (INTERNAL_BITMAP_FORMAT (*f))
+ {
+ case pk_format:
+ c = NULL;
+ break;
+
+ case gf_format:
+ c = gf_get_raw_char (code);
+ break;
+
+ default:
+ FATAL1 ("Impossible bitmap format (%d)", INTERNAL_BITMAP_FORMAT (*f));
+ }
+
+ if (c != NULL)
+ RAW_CHAR_BITMAP_FORMAT (*c) = INTERNAL_BITMAP_FORMAT (*f);
+ return c;
+}
+
+
+/* Free the information in the raw character RAW_CHAR, including the
+ character itself. */
+
+void
+free_raw_char (raw_char_type *raw_char)
+{
+ free (RAW_CHAR_BYTES (*raw_char));
+ free (raw_char);
+}
+
+/* Print the character C to the file F, using ordinary characters. */
+
+void
+print_char (FILE *f, char_info_type c)
+{
+ unsigned this_row, this_col;
+ bitmap_type b = CHAR_BITMAP (c);
+
+ fprintf (f, "Character 0x%x=%u", CHARCODE (c), CHARCODE (c));
+ if (ISPRINT (CHARCODE (c)))
+ fprintf (f, " (%c)", CHARCODE (c));
+
+ fprintf (f, ":\n");
+
+ fprintf (f, " min/max col %d/%d, min/max row %d/%d, set width %d.\n",
+ CHAR_MIN_COL (c), CHAR_MAX_COL (c),
+ CHAR_MIN_ROW (c), CHAR_MAX_ROW (c), CHAR_SET_WIDTH (c));
+
+ /* We don't call `print_bitmap' because we want to print the Cartesian
+ row number, as well as the bitmap row number. */
+
+ for (this_row = 0; this_row < BITMAP_HEIGHT (b); this_row++)
+ {
+ for (this_col = 0; this_col < BITMAP_WIDTH (b); this_col++)
+ putc (BITMAP_PIXEL (b, this_row, this_col) ? '*' : ' ', f);
+
+ fprintf (f, "%3d\t%u\n", CHAR_MAX_ROW (c) - this_row, this_row);
+ }
+}
+
+/* We want to implement a typical key/value setup: here we are given the
+ key (FONT_NAME) and the value (F). We assign an index number to
+ FONT_NAME, and store it and F in parallel lists. If we are passed a
+ FONT_NAME that is already in the list, we overwrite the old value. */
+
+static list_type font_name_list, internal_font_list;
+
+static void
+save_internal_font (string font_name, internal_font_type f)
+{
+ string *new_name;
+ internal_font_type *new_font;
+ static boolean first_call = true;
+
+ if (first_call)
+ { /* Have to construct our lists. */
+ font_name_list = list_init ();
+ internal_font_list = list_init ();
+ first_call = false;
+ }
+
+ new_font = find_internal_font (font_name);
+ if (new_font == NULL)
+ {
+ /* Add another pointer to the end of the lists. */
+ new_name = LIST_TAPPEND (&font_name_list, string);
+ new_font = LIST_TAPPEND (&internal_font_list, internal_font_type);
+
+ /* Save the information. */
+ *new_name = xstrdup (font_name);
+ }
+
+ /* Either update the existing font, or save the new one. */
+ *new_font = f;
+}
+
+
+/* This routine returns the font information previously stored with
+ FONT_NAME. If FONT_NAME hasn't been saved, we return NULL. */
+
+static internal_font_type *
+find_internal_font (string font_name)
+{
+ unsigned e;
+
+ for (e = 0; e < LIST_SIZE (font_name_list); e++)
+ if (STREQ (*(string *) LIST_ELT (font_name_list, e), font_name))
+ return (internal_font_type *) LIST_ELT (internal_font_list, e);
+
+ return NULL;
+}
+
+
+/* Remove FILENAME from `font_name_list', by setting the name in
+ `font_name_list' to the empty string, so that the element is useless.
+ (We don't have any actual memory to free.) What a kludge. */
+
+static void
+delete_internal_font (string filename)
+{
+ unsigned e;
+
+ /* We can't use `find_internal_font', since we need to know the list
+ element index, not just the internal font information. */
+ for (e = 0; e < LIST_SIZE (font_name_list); e++)
+ if (STREQ (*(string *) LIST_ELT (font_name_list, e), filename))
+ {
+ string *name = LIST_ELT (font_name_list, e);
+ internal_font_type *i
+ = (internal_font_type *) LIST_ELT (internal_font_list, e);
+
+ free (*name);
+ *name = "";
+
+ free (i);
+
+ return;
+ }
+
+ FATAL1 ("The font `%s' hasn't been saved", filename);
+}
diff --git a/lib/fontmap.c b/lib/fontmap.c
new file mode 100644
index 0000000..2b4f0b7
--- /dev/null
+++ b/lib/fontmap.c
@@ -0,0 +1,210 @@
+/* fontmap.c: read a file for additional font names.
+
+Copyright (C) 1993 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 "c-pathmx.h"
+#include "fontmap.h"
+
+
+
+/* Fontname mapping. We use a straightforward hash table. */
+
+#define MAP_SIZE 199
+
+
+/* The hash function. We go for simplicity here. */
+
+static unsigned
+map_hash (key)
+ char *key;
+{
+ unsigned n = 0;
+
+ /* There are very few font names which are anagrams of each other (I
+ think), so no point in weighting the characters. */
+ while (*key != 0)
+ n += *key++;
+
+ n %= MAP_SIZE;
+
+ return n;
+}
+
+/* Look up STR in MAP. Return the corresponding `value' or NULL. */
+
+static char *
+map_lookup_str (map, key)
+ map_type map;
+ char *key;
+{
+ map_element_type *p;
+ unsigned n = map_hash (key);
+
+ for (p = map[n]; p != NULL; p = p->next)
+ if (STREQ (key, p->key))
+ return p->value;
+
+ return NULL;
+}
+
+
+/* Look up KEY in MAP; if it's not found, remove any suffix from KEY and
+ try again. */
+
+char *
+map_lookup (map, key)
+ map_type map;
+ char *key;
+{
+ extern string extend_filename ();
+ string suffix = find_suffix (key);
+ string ret = map_lookup_str (map, key);
+
+ if (!ret)
+ {
+ /* OK, the original KEY didn't work. Let's check for the KEY without
+ an extension -- perhaps they gave foobar.tfm, but the mapping only
+ defines `foobar'. */
+ if (suffix)
+ {
+ string base_key = remove_suffix (key);
+
+ ret = map_lookup_str (map, base_key);
+
+ free (base_key);
+ }
+ }
+
+ /* Append the same suffix we took off, if necessary. */
+ if (ret && suffix)
+ ret = extend_filename (ret, suffix);
+
+ return ret;
+}
+
+/* If KEY is not already in MAP, insert it and VALUE. */
+
+static void
+map_insert (map, key, value)
+ map_type map;
+ char *key;
+ char *value;
+{
+ unsigned n = map_hash (key);
+ map_element_type **p = &map[n];
+ map_element_type ***trailer = &p;
+
+ while (*p != NULL && !STREQ (key, (*p)->key))
+ {
+ *p = (*p)->next;
+ trailer = &p;
+ }
+
+ if (*p == NULL)
+ {
+ **trailer = XTALLOC (MAP_SIZE, map_element_type);
+ (**trailer)->key = xstrdup (key);
+ (**trailer)->value = xstrdup (value);
+ (**trailer)->next = NULL;
+ }
+}
+
+/* Open and read the mapping file FILENAME, putting its entries into
+ MAP. Comments begin with % and continue to the end of the line. Each
+ line of the file defines an entry: the first word is the real
+ filename (e.g., `ptmr'), the second word is the alias (e.g.,
+ `Times-Roman'), and any subsequent words are ignored. .tfm is added
+ if either the filename or the alias have no extension. This is the
+ same order as in Dvips' psfonts.map; unfortunately, we can't have TeX
+ read that same file, since most of the real filenames start with an
+ `r', because of the virtual fonts Dvips uses. */
+
+static void
+map_file_parse (map, map_filename)
+ map_type map;
+ char *map_filename;
+{
+ extern FILE *xfopen (); /* In xfopen.c. */
+ extern char *read_line (); /* In line.c. */
+ char *l;
+ unsigned map_lineno = 0;
+ FILE *f = xfopen (map_filename, FOPEN_R_MODE);
+
+ while ((l = read_line (f)) != NULL)
+ {
+ string filename;
+ string comment_loc = strrchr (l, '%');
+
+ map_lineno++;
+
+ /* Ignore anything after a %. */
+ if (comment_loc)
+ *comment_loc = 0;
+
+ /* If we don't have any filename, that's ok, the line is blank. */
+ filename = strtok (l, " \t");
+ if (filename)
+ {
+ string alias = strtok (NULL, " \t");
+
+ /* But if we have a filename and no alias, something's wrong. */
+ if (alias == NULL || *alias == 0)
+ fprintf (stderr, "%s:%u: Alias missing for filename `%s'.\n",
+ map_filename, map_lineno, filename);
+ else
+ {
+ /* We've got everything. Insert the new entry. */
+ map_insert (map, alias, filename);
+ }
+ }
+
+ free (l);
+ }
+
+ xfclose (f, map_filename);
+}
+
+
+/* Look for the file `texfonts.map' in each of the directories in
+ DIR_LIST. Entries in earlier files override later files. */
+
+map_type
+map_create (dir_list)
+ string *dir_list;
+{
+ map_type map = (map_type) xcalloc (MAP_SIZE, sizeof (map_element_type *));
+
+ while (*dir_list)
+ {
+ char filename[PATH_MAX];
+
+ /* We don't bother with the filename truncation that `readable' in
+ `pathsrch.c' does, since we ourselves are giving the filename,
+ and I don't think it's worth worrying about too-long
+ intermediate directory names in the path. */
+ strcpy (filename, *dir_list);
+ strcat (filename, "texfonts.map");
+
+ if (access (filename, R_OK) == 0)
+ map_file_parse (map, filename);
+
+ dir_list++;
+ }
+ return map;
+}
diff --git a/lib/gmalloc.c b/lib/gmalloc.c
new file mode 100644
index 0000000..bf4c70f
--- /dev/null
+++ b/lib/gmalloc.c
@@ -0,0 +1,1172 @@
+/* DO NOT EDIT THIS FILE -- it is automagically generated. -*- C -*- */
+
+#define _MALLOC_INTERNAL
+
+/* The malloc headers and source files from the C library follow here. */
+
+/* Declarations for `malloc' and friends.
+ Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Written May 1989 by Mike Haertel.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+This library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.
+
+ The author may be reached (Email) at the address mike@ai.mit.edu,
+ or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#ifndef _MALLOC_H
+
+#define _MALLOC_H 1
+
+#ifdef _MALLOC_INTERNAL
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if defined(_LIBC) || defined(STDC_HEADERS) || defined(USG)
+#include <string.h>
+#else
+#ifndef memset
+#define memset(s, zero, n) bzero ((s), (n))
+#endif
+#ifndef memcpy
+#define memcpy(d, s, n) bcopy ((s), (d), (n))
+#endif
+#ifndef memmove
+#define memmove(d, s, n) bcopy ((s), (d), (n))
+#endif
+#endif
+
+#if defined(__GNU_LIBRARY__) || defined(__STDC__)
+#include <limits.h>
+#else
+#define CHAR_BIT 8
+#endif
+
+#endif /* _MALLOC_INTERNAL. */
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#if defined (__cplusplus) || (defined (__STDC__) && __STDC__)
+#undef __P
+#define __P(args) args
+#undef __ptr_t
+#define __ptr_t void *
+#else /* Not C++ or ANSI C. */
+#undef __P
+#define __P(args) ()
+#undef const
+#define const
+#undef __ptr_t
+#define __ptr_t char *
+#endif /* C++ or ANSI C. */
+
+#ifdef __STDC__
+#include <stddef.h>
+#else
+#undef size_t
+#define size_t unsigned int
+#undef ptrdiff_t
+#define ptrdiff_t int
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+
+/* Allocate SIZE bytes of memory. */
+extern __ptr_t malloc __P ((size_t __size));
+/* Re-allocate the previously allocated block
+ in __ptr_t, making the new block SIZE bytes long. */
+extern __ptr_t realloc __P ((__ptr_t __ptr, size_t __size));
+/* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */
+extern __ptr_t calloc __P ((size_t __nmemb, size_t __size));
+/* Free a block allocated by `malloc', `realloc' or `calloc'. */
+extern void free __P ((__ptr_t __ptr));
+
+/* Allocate SIZE bytes allocated to ALIGNMENT bytes. */
+extern __ptr_t memalign __P ((size_t __alignment, size_t __size));
+
+/* Allocate SIZE bytes on a page boundary. */
+extern __ptr_t valloc __P ((size_t __size));
+
+
+#ifdef _MALLOC_INTERNAL
+
+/* The allocator divides the heap into blocks of fixed size; large
+ requests receive one or more whole blocks, and small requests
+ receive a fragment of a block. Fragment sizes are powers of two,
+ and all fragments of a block are the same size. When all the
+ fragments in a block have been freed, the block itself is freed. */
+#define INT_BIT (CHAR_BIT * sizeof(int))
+#define BLOCKLOG (INT_BIT > 16 ? 12 : 9)
+#define BLOCKSIZE (1 << BLOCKLOG)
+#define BLOCKIFY(SIZE) (((SIZE) + BLOCKSIZE - 1) / BLOCKSIZE)
+
+/* Determine the amount of memory spanned by the initial heap table
+ (not an absolute limit). */
+#define HEAP (INT_BIT > 16 ? 4194304 : 65536)
+
+/* Number of contiguous free blocks allowed to build up at the end of
+ memory before they will be returned to the system. */
+#define FINAL_FREE_BLOCKS 8
+
+/* Data structure giving per-block information. */
+typedef union
+ {
+ /* Heap information for a busy block. */
+ struct
+ {
+ /* Zero for a large block, or positive giving the
+ logarithm to the base two of the fragment size. */
+ int type;
+ union
+ {
+ struct
+ {
+ size_t nfree; /* Free fragments in a fragmented block. */
+ size_t first; /* First free fragment of the block. */
+ } frag;
+ /* Size (in blocks) of a large cluster. */
+ size_t size;
+ } info;
+ } busy;
+ /* Heap information for a free block
+ (that may be the first of a free cluster). */
+ struct
+ {
+ size_t size; /* Size (in blocks) of a free cluster. */
+ size_t next; /* Index of next free cluster. */
+ size_t prev; /* Index of previous free cluster. */
+ } free;
+ } malloc_info;
+
+/* Pointer to first block of the heap. */
+extern char *_heapbase;
+
+/* Table indexed by block number giving per-block information. */
+extern malloc_info *_heapinfo;
+
+/* Address to block number and vice versa. */
+#define BLOCK(A) (((char *) (A) - _heapbase) / BLOCKSIZE + 1)
+#define ADDRESS(B) ((__ptr_t) (((B) - 1) * BLOCKSIZE + _heapbase))
+
+/* Current search index for the heap table. */
+extern size_t _heapindex;
+
+/* Limit of valid info table indices. */
+extern size_t _heaplimit;
+
+/* Doubly linked lists of free fragments. */
+struct list
+ {
+ struct list *next;
+ struct list *prev;
+ };
+
+/* Free list headers for each fragment size. */
+extern struct list _fraghead[];
+
+/* List of blocks allocated with `memalign' (or `valloc'). */
+struct alignlist
+ {
+ struct alignlist *next;
+ __ptr_t aligned; /* The address that memaligned returned. */
+ __ptr_t exact; /* The address that malloc returned. */
+ };
+extern struct alignlist *_aligned_blocks;
+
+/* Instrumentation. */
+extern size_t _chunks_used;
+extern size_t _bytes_used;
+extern size_t _chunks_free;
+extern size_t _bytes_free;
+
+/* Internal version of `free' used in `morecore' (malloc.c). */
+extern void _free_internal __P ((__ptr_t __ptr));
+
+#endif /* _MALLOC_INTERNAL. */
+
+/* Underlying allocation function; successive calls should
+ return contiguous pieces of memory. */
+extern __ptr_t (*__morecore) __P ((ptrdiff_t __size));
+
+/* Default value of `__morecore'. */
+extern __ptr_t __default_morecore __P ((ptrdiff_t __size));
+
+/* If not NULL, this function is called after each time
+ `__morecore' is called to increase the data size. */
+extern void (*__after_morecore_hook) __P ((void));
+
+/* Nonzero if `malloc' has been called and done its initialization. */
+extern int __malloc_initialized;
+
+/* Hooks for debugging versions. */
+extern void (*__free_hook) __P ((__ptr_t __ptr));
+extern __ptr_t (*__malloc_hook) __P ((size_t __size));
+extern __ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, size_t __size));
+
+/* Activate a standard collection of debugging hooks. */
+extern int mcheck __P ((void (*__func) __P ((void))));
+
+/* Activate a standard collection of tracing hooks. */
+extern void mtrace __P ((void));
+
+/* Statistics available to the user. */
+struct mstats
+ {
+ size_t bytes_total; /* Total size of the heap. */
+ size_t chunks_used; /* Chunks allocated by the user. */
+ size_t bytes_used; /* Byte total of user-allocated chunks. */
+ size_t chunks_free; /* Chunks in the free list. */
+ size_t bytes_free; /* Byte total of chunks in the free list. */
+ };
+
+/* Pick up the current statistics. */
+extern struct mstats mstats __P ((void));
+
+/* Call WARNFUN with a warning message when memory usage is high. */
+extern void memory_warnings __P ((__ptr_t __start,
+ void (*__warnfun) __P ((__const char *))));
+
+
+/* Relocating allocator. */
+
+/* Allocate SIZE bytes, and store the address in *HANDLEPTR. */
+extern __ptr_t r_alloc __P ((__ptr_t *__handleptr, size_t __size));
+
+/* Free the storage allocated in HANDLEPTR. */
+extern void r_alloc_free __P ((__ptr_t *__handleptr));
+
+/* Adjust the block at HANDLEPTR to be SIZE bytes long. */
+extern __ptr_t r_re_alloc __P ((__ptr_t *__handleptr, size_t __size));
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* malloc.h */
+/* Memory allocator `malloc'.
+ Copyright 1990, 1991, 1992, 1993 Free Software Foundation
+ Written May 1989 by Mike Haertel.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+This library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.
+
+ The author may be reached (Email) at the address mike@ai.mit.edu,
+ or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#ifndef _MALLOC_INTERNAL
+#define _MALLOC_INTERNAL
+#include <malloc.h>
+#endif
+
+/* How to really get more memory. */
+__ptr_t (*__morecore) __P ((ptrdiff_t __size)) = __default_morecore;
+
+/* Debugging hook for `malloc'. */
+__ptr_t (*__malloc_hook) __P ((size_t __size));
+
+/* Pointer to the base of the first block. */
+char *_heapbase;
+
+/* Block information table. Allocated with align/__free (not malloc/free). */
+malloc_info *_heapinfo;
+
+/* Number of info entries. */
+static size_t heapsize;
+
+/* Search index in the info table. */
+size_t _heapindex;
+
+/* Limit of valid info table indices. */
+size_t _heaplimit;
+
+/* Free lists for each fragment size. */
+struct list _fraghead[BLOCKLOG];
+
+/* Instrumentation. */
+size_t _chunks_used;
+size_t _bytes_used;
+size_t _chunks_free;
+size_t _bytes_free;
+
+/* Are you experienced? */
+int __malloc_initialized;
+
+void (*__after_morecore_hook) __P ((void));
+
+/* Aligned allocation. */
+static __ptr_t align __P ((size_t));
+static __ptr_t
+align (size)
+ size_t size;
+{
+ __ptr_t result;
+ unsigned long int adj;
+
+ result = (*__morecore) (size);
+ adj = (unsigned long int) ((unsigned long int) ((char *) result -
+ (char *) NULL)) % BLOCKSIZE;
+ if (adj != 0)
+ {
+ adj = BLOCKSIZE - adj;
+ (void) (*__morecore) (adj);
+ result = (char *) result + adj;
+ }
+
+ if (__after_morecore_hook)
+ (*__after_morecore_hook) ();
+
+ return result;
+}
+
+/* Set everything up and remember that we have. */
+static int initialize __P ((void));
+static int
+initialize ()
+{
+ heapsize = HEAP / BLOCKSIZE;
+ _heapinfo = (malloc_info *) align (heapsize * sizeof (malloc_info));
+ if (_heapinfo == NULL)
+ return 0;
+ memset (_heapinfo, 0, heapsize * sizeof (malloc_info));
+ _heapinfo[0].free.size = 0;
+ _heapinfo[0].free.next = _heapinfo[0].free.prev = 0;
+ _heapindex = 0;
+ _heapbase = (char *) _heapinfo;
+ __malloc_initialized = 1;
+ return 1;
+}
+
+/* Get neatly aligned memory, initializing or
+ growing the heap info table as necessary. */
+static __ptr_t morecore __P ((size_t));
+static __ptr_t
+morecore (size)
+ size_t size;
+{
+ __ptr_t result;
+ malloc_info *newinfo, *oldinfo;
+ size_t newsize;
+
+ result = align (size);
+ if (result == NULL)
+ return NULL;
+
+ /* Check if we need to grow the info table. */
+ if ((size_t) BLOCK ((char *) result + size) > heapsize)
+ {
+ newsize = heapsize;
+ while ((size_t) BLOCK ((char *) result + size) > newsize)
+ newsize *= 2;
+ newinfo = (malloc_info *) align (newsize * sizeof (malloc_info));
+ if (newinfo == NULL)
+ {
+ (*__morecore) (-size);
+ return NULL;
+ }
+ memset (newinfo, 0, newsize * sizeof (malloc_info));
+ memcpy (newinfo, _heapinfo, heapsize * sizeof (malloc_info));
+ oldinfo = _heapinfo;
+ newinfo[BLOCK (oldinfo)].busy.type = 0;
+ newinfo[BLOCK (oldinfo)].busy.info.size
+ = BLOCKIFY (heapsize * sizeof (malloc_info));
+ _heapinfo = newinfo;
+ _free_internal (oldinfo);
+ heapsize = newsize;
+ }
+
+ _heaplimit = BLOCK ((char *) result + size);
+ return result;
+}
+
+/* Allocate memory from the heap. */
+__ptr_t
+malloc (size)
+ size_t size;
+{
+ __ptr_t result;
+ size_t block, blocks, lastblocks, start;
+ register size_t i;
+ struct list *next;
+
+ /* ANSI C allows `malloc (0)' to either return NULL, or to return a
+ valid address you can realloc and free (though not dereference).
+
+ It turns out that some extant code (sunrpc, at least Ultrix's version)
+ expects `malloc (0)' to return non-NULL and breaks otherwise.
+ Be compatible. */
+
+#if 0
+ if (size == 0)
+ return NULL;
+#endif
+
+ if (__malloc_hook != NULL)
+ return (*__malloc_hook) (size);
+
+ if (!__malloc_initialized)
+ if (!initialize ())
+ return NULL;
+
+ if (size < sizeof (struct list))
+ size = sizeof (struct list);
+
+ /* Determine the allocation policy based on the request size. */
+ if (size <= BLOCKSIZE / 2)
+ {
+ /* Small allocation to receive a fragment of a block.
+ Determine the logarithm to base two of the fragment size. */
+ register size_t log = 1;
+ --size;
+ while ((size /= 2) != 0)
+ ++log;
+
+ /* Look in the fragment lists for a
+ free fragment of the desired size. */
+ next = _fraghead[log].next;
+ if (next != NULL)
+ {
+ /* There are free fragments of this size.
+ Pop a fragment out of the fragment list and return it.
+ Update the block's nfree and first counters. */
+ result = (__ptr_t) next;
+ next->prev->next = next->next;
+ if (next->next != NULL)
+ next->next->prev = next->prev;
+ block = BLOCK (result);
+ if (--_heapinfo[block].busy.info.frag.nfree != 0)
+ _heapinfo[block].busy.info.frag.first = (unsigned long int)
+ ((unsigned long int) ((char *) next->next - (char *) NULL)
+ % BLOCKSIZE) >> log;
+
+ /* Update the statistics. */
+ ++_chunks_used;
+ _bytes_used += 1 << log;
+ --_chunks_free;
+ _bytes_free -= 1 << log;
+ }
+ else
+ {
+ /* No free fragments of the desired size, so get a new block
+ and break it into fragments, returning the first. */
+ result = malloc (BLOCKSIZE);
+ if (result == NULL)
+ return NULL;
+
+ /* Link all fragments but the first into the free list. */
+ for (i = 1; i < (size_t) (BLOCKSIZE >> log); ++i)
+ {
+ next = (struct list *) ((char *) result + (i << log));
+ next->next = _fraghead[log].next;
+ next->prev = &_fraghead[log];
+ next->prev->next = next;
+ if (next->next != NULL)
+ next->next->prev = next;
+ }
+
+ /* Initialize the nfree and first counters for this block. */
+ block = BLOCK (result);
+ _heapinfo[block].busy.type = log;
+ _heapinfo[block].busy.info.frag.nfree = i - 1;
+ _heapinfo[block].busy.info.frag.first = i - 1;
+
+ _chunks_free += (BLOCKSIZE >> log) - 1;
+ _bytes_free += BLOCKSIZE - (1 << log);
+ _bytes_used -= BLOCKSIZE - (1 << log);
+ }
+ }
+ else
+ {
+ /* Large allocation to receive one or more blocks.
+ Search the free list in a circle starting at the last place visited.
+ If we loop completely around without finding a large enough
+ space we will have to get more memory from the system. */
+ blocks = BLOCKIFY (size);
+ start = block = _heapindex;
+ while (_heapinfo[block].free.size < blocks)
+ {
+ block = _heapinfo[block].free.next;
+ if (block == start)
+ {
+ /* Need to get more from the system. Check to see if
+ the new core will be contiguous with the final free
+ block; if so we don't need to get as much. */
+ block = _heapinfo[0].free.prev;
+ lastblocks = _heapinfo[block].free.size;
+ if (_heaplimit != 0 && block + lastblocks == _heaplimit &&
+ (*__morecore) (0) == ADDRESS (block + lastblocks) &&
+ (morecore ((blocks - lastblocks) * BLOCKSIZE)) != NULL)
+ {
+ _heapinfo[block].free.size = blocks;
+ _bytes_free += (blocks - lastblocks) * BLOCKSIZE;
+ continue;
+ }
+ result = morecore (blocks * BLOCKSIZE);
+ if (result == NULL)
+ return NULL;
+ block = BLOCK (result);
+ _heapinfo[block].busy.type = 0;
+ _heapinfo[block].busy.info.size = blocks;
+ ++_chunks_used;
+ _bytes_used += blocks * BLOCKSIZE;
+ return result;
+ }
+ }
+
+ /* At this point we have found a suitable free list entry.
+ Figure out how to remove what we need from the list. */
+ result = ADDRESS (block);
+ if (_heapinfo[block].free.size > blocks)
+ {
+ /* The block we found has a bit left over,
+ so relink the tail end back into the free list. */
+ _heapinfo[block + blocks].free.size
+ = _heapinfo[block].free.size - blocks;
+ _heapinfo[block + blocks].free.next
+ = _heapinfo[block].free.next;
+ _heapinfo[block + blocks].free.prev
+ = _heapinfo[block].free.prev;
+ _heapinfo[_heapinfo[block].free.prev].free.next
+ = _heapinfo[_heapinfo[block].free.next].free.prev
+ = _heapindex = block + blocks;
+ }
+ else
+ {
+ /* The block exactly matches our requirements,
+ so just remove it from the list. */
+ _heapinfo[_heapinfo[block].free.next].free.prev
+ = _heapinfo[block].free.prev;
+ _heapinfo[_heapinfo[block].free.prev].free.next
+ = _heapindex = _heapinfo[block].free.next;
+ --_chunks_free;
+ }
+
+ _heapinfo[block].busy.type = 0;
+ _heapinfo[block].busy.info.size = blocks;
+ ++_chunks_used;
+ _bytes_used += blocks * BLOCKSIZE;
+ _bytes_free -= blocks * BLOCKSIZE;
+ }
+
+ return result;
+}
+/* Free a block of memory allocated by `malloc'.
+ Copyright 1990, 1991, 1992 Free Software Foundation
+ Written May 1989 by Mike Haertel.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+This library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.
+
+ The author may be reached (Email) at the address mike@ai.mit.edu,
+ or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#ifndef _MALLOC_INTERNAL
+#define _MALLOC_INTERNAL
+#include <malloc.h>
+#endif
+
+/* Debugging hook for free. */
+void (*__free_hook) __P ((__ptr_t __ptr));
+
+/* List of blocks allocated by memalign. */
+struct alignlist *_aligned_blocks = NULL;
+
+/* Return memory to the heap.
+ Like `free' but don't call a __free_hook if there is one. */
+void
+_free_internal (ptr)
+ __ptr_t ptr;
+{
+ int type;
+ size_t block, blocks;
+ register size_t i;
+ struct list *prev, *next;
+
+ block = BLOCK (ptr);
+
+ type = _heapinfo[block].busy.type;
+ switch (type)
+ {
+ case 0:
+ /* Get as many statistics as early as we can. */
+ --_chunks_used;
+ _bytes_used -= _heapinfo[block].busy.info.size * BLOCKSIZE;
+ _bytes_free += _heapinfo[block].busy.info.size * BLOCKSIZE;
+
+ /* Find the free cluster previous to this one in the free list.
+ Start searching at the last block referenced; this may benefit
+ programs with locality of allocation. */
+ i = _heapindex;
+ if (i > block)
+ while (i > block)
+ i = _heapinfo[i].free.prev;
+ else
+ {
+ do
+ i = _heapinfo[i].free.next;
+ while (i > 0 && i < block);
+ i = _heapinfo[i].free.prev;
+ }
+
+ /* Determine how to link this block into the free list. */
+ if (block == i + _heapinfo[i].free.size)
+ {
+ /* Coalesce this block with its predecessor. */
+ _heapinfo[i].free.size += _heapinfo[block].busy.info.size;
+ block = i;
+ }
+ else
+ {
+ /* Really link this block back into the free list. */
+ _heapinfo[block].free.size = _heapinfo[block].busy.info.size;
+ _heapinfo[block].free.next = _heapinfo[i].free.next;
+ _heapinfo[block].free.prev = i;
+ _heapinfo[i].free.next = block;
+ _heapinfo[_heapinfo[block].free.next].free.prev = block;
+ ++_chunks_free;
+ }
+
+ /* Now that the block is linked in, see if we can coalesce it
+ with its successor (by deleting its successor from the list
+ and adding in its size). */
+ if (block + _heapinfo[block].free.size == _heapinfo[block].free.next)
+ {
+ _heapinfo[block].free.size
+ += _heapinfo[_heapinfo[block].free.next].free.size;
+ _heapinfo[block].free.next
+ = _heapinfo[_heapinfo[block].free.next].free.next;
+ _heapinfo[_heapinfo[block].free.next].free.prev = block;
+ --_chunks_free;
+ }
+
+ /* Now see if we can return stuff to the system. */
+ blocks = _heapinfo[block].free.size;
+ if (blocks >= FINAL_FREE_BLOCKS && block + blocks == _heaplimit
+ && (*__morecore) (0) == ADDRESS (block + blocks))
+ {
+ register size_t bytes = blocks * BLOCKSIZE;
+ _heaplimit -= blocks;
+ (*__morecore) (-bytes);
+ _heapinfo[_heapinfo[block].free.prev].free.next
+ = _heapinfo[block].free.next;
+ _heapinfo[_heapinfo[block].free.next].free.prev
+ = _heapinfo[block].free.prev;
+ block = _heapinfo[block].free.prev;
+ --_chunks_free;
+ _bytes_free -= bytes;
+ }
+
+ /* Set the next search to begin at this block. */
+ _heapindex = block;
+ break;
+
+ default:
+ /* Do some of the statistics. */
+ --_chunks_used;
+ _bytes_used -= 1 << type;
+ ++_chunks_free;
+ _bytes_free += 1 << type;
+
+ /* Get the address of the first free fragment in this block. */
+ prev = (struct list *) ((char *) ADDRESS (block) +
+ (_heapinfo[block].busy.info.frag.first << type));
+
+ if (_heapinfo[block].busy.info.frag.nfree == (BLOCKSIZE >> type) - 1)
+ {
+ /* If all fragments of this block are free, remove them
+ from the fragment list and free the whole block. */
+ next = prev;
+ for (i = 1; i < (size_t) (BLOCKSIZE >> type); ++i)
+ next = next->next;
+ prev->prev->next = next;
+ if (next != NULL)
+ next->prev = prev->prev;
+ _heapinfo[block].busy.type = 0;
+ _heapinfo[block].busy.info.size = 1;
+
+ /* Keep the statistics accurate. */
+ ++_chunks_used;
+ _bytes_used += BLOCKSIZE;
+ _chunks_free -= BLOCKSIZE >> type;
+ _bytes_free -= BLOCKSIZE;
+
+ free (ADDRESS (block));
+ }
+ else if (_heapinfo[block].busy.info.frag.nfree != 0)
+ {
+ /* If some fragments of this block are free, link this
+ fragment into the fragment list after the first free
+ fragment of this block. */
+ next = (struct list *) ptr;
+ next->next = prev->next;
+ next->prev = prev;
+ prev->next = next;
+ if (next->next != NULL)
+ next->next->prev = next;
+ ++_heapinfo[block].busy.info.frag.nfree;
+ }
+ else
+ {
+ /* No fragments of this block are free, so link this
+ fragment into the fragment list and announce that
+ it is the first free fragment of this block. */
+ prev = (struct list *) ptr;
+ _heapinfo[block].busy.info.frag.nfree = 1;
+ _heapinfo[block].busy.info.frag.first = (unsigned long int)
+ ((unsigned long int) ((char *) ptr - (char *) NULL)
+ % BLOCKSIZE >> type);
+ prev->next = _fraghead[type].next;
+ prev->prev = &_fraghead[type];
+ prev->prev->next = prev;
+ if (prev->next != NULL)
+ prev->next->prev = prev;
+ }
+ break;
+ }
+}
+
+/* Return memory to the heap. */
+void
+free (ptr)
+ __ptr_t ptr;
+{
+ register struct alignlist *l;
+
+ if (ptr == NULL)
+ return;
+
+ for (l = _aligned_blocks; l != NULL; l = l->next)
+ if (l->aligned == ptr)
+ {
+ l->aligned = NULL; /* Mark the slot in the list as free. */
+ ptr = l->exact;
+ break;
+ }
+
+ if (__free_hook != NULL)
+ (*__free_hook) (ptr);
+ else
+ _free_internal (ptr);
+}
+/* Copyright (C) 1991, 1993 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#ifndef _MALLOC_INTERNAL
+#define _MALLOC_INTERNAL
+#include <malloc.h>
+#endif
+
+#undef cfree
+
+#ifdef _LIBC
+
+#include <ansidecl.h>
+#include <gnu-stabs.h>
+
+function_alias(cfree, free, void, (ptr),
+ DEFUN(cfree, (ptr), PTR ptr))
+
+#else
+
+void
+cfree (ptr)
+ __ptr_t ptr;
+{
+ free (ptr);
+}
+
+#endif
+/* Change the size of a block allocated by `malloc'.
+ Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Written May 1989 by Mike Haertel.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+This library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.
+
+ The author may be reached (Email) at the address mike@ai.mit.edu,
+ or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#ifndef _MALLOC_INTERNAL
+#define _MALLOC_INTERNAL
+#include <malloc.h>
+#endif
+
+#define min(A, B) ((A) < (B) ? (A) : (B))
+
+/* Debugging hook for realloc. */
+__ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, size_t __size));
+
+/* Resize the given region to the new size, returning a pointer
+ to the (possibly moved) region. This is optimized for speed;
+ some benchmarks seem to indicate that greater compactness is
+ achieved by unconditionally allocating and copying to a
+ new region. This module has incestuous knowledge of the
+ internals of both free and malloc. */
+__ptr_t
+realloc (ptr, size)
+ __ptr_t ptr;
+ size_t size;
+{
+ __ptr_t result;
+ int type;
+ size_t block, blocks, oldlimit;
+
+ if (size == 0)
+ {
+ free (ptr);
+ return malloc (0);
+ }
+ else if (ptr == NULL)
+ return malloc (size);
+
+ if (__realloc_hook != NULL)
+ return (*__realloc_hook) (ptr, size);
+
+ block = BLOCK (ptr);
+
+ type = _heapinfo[block].busy.type;
+ switch (type)
+ {
+ case 0:
+ /* Maybe reallocate a large block to a small fragment. */
+ if (size <= BLOCKSIZE / 2)
+ {
+ result = malloc (size);
+ if (result != NULL)
+ {
+ memcpy (result, ptr, size);
+ free (ptr);
+ return result;
+ }
+ }
+
+ /* The new size is a large allocation as well;
+ see if we can hold it in place. */
+ blocks = BLOCKIFY (size);
+ if (blocks < _heapinfo[block].busy.info.size)
+ {
+ /* The new size is smaller; return
+ excess memory to the free list. */
+ _heapinfo[block + blocks].busy.type = 0;
+ _heapinfo[block + blocks].busy.info.size
+ = _heapinfo[block].busy.info.size - blocks;
+ _heapinfo[block].busy.info.size = blocks;
+ free (ADDRESS (block + blocks));
+ result = ptr;
+ }
+ else if (blocks == _heapinfo[block].busy.info.size)
+ /* No size change necessary. */
+ result = ptr;
+ else
+ {
+ /* Won't fit, so allocate a new region that will.
+ Free the old region first in case there is sufficient
+ adjacent free space to grow without moving. */
+ blocks = _heapinfo[block].busy.info.size;
+ /* Prevent free from actually returning memory to the system. */
+ oldlimit = _heaplimit;
+ _heaplimit = 0;
+ free (ptr);
+ _heaplimit = oldlimit;
+ result = malloc (size);
+ if (result == NULL)
+ {
+ /* Now we're really in trouble. We have to unfree
+ the thing we just freed. Unfortunately it might
+ have been coalesced with its neighbors. */
+ if (_heapindex == block)
+ (void) malloc (blocks * BLOCKSIZE);
+ else
+ {
+ __ptr_t previous = malloc ((block - _heapindex) * BLOCKSIZE);
+ (void) malloc (blocks * BLOCKSIZE);
+ free (previous);
+ }
+ return NULL;
+ }
+ if (ptr != result)
+ memmove (result, ptr, blocks * BLOCKSIZE);
+ }
+ break;
+
+ default:
+ /* Old size is a fragment; type is logarithm
+ to base two of the fragment size. */
+ if (size > (size_t) (1 << (type - 1)) && size <= (size_t) (1 << type))
+ /* The new size is the same kind of fragment. */
+ result = ptr;
+ else
+ {
+ /* The new size is different; allocate a new space,
+ and copy the lesser of the new size and the old. */
+ result = malloc (size);
+ if (result == NULL)
+ return NULL;
+ memcpy (result, ptr, min (size, (size_t) 1 << type));
+ free (ptr);
+ }
+ break;
+ }
+
+ return result;
+}
+/* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+This library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.
+
+ The author may be reached (Email) at the address mike@ai.mit.edu,
+ or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#ifndef _MALLOC_INTERNAL
+#define _MALLOC_INTERNAL
+#include <malloc.h>
+#endif
+
+/* Allocate an array of NMEMB elements each SIZE bytes long.
+ The entire array is initialized to zeros. */
+__ptr_t
+calloc (nmemb, size)
+ register size_t nmemb;
+ register size_t size;
+{
+ register __ptr_t result = malloc (nmemb * size);
+
+ if (result != NULL)
+ (void) memset (result, 0, nmemb * size);
+
+ return result;
+}
+/* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library 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.
+
+The GNU C Library 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 the GNU C Library; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef _MALLOC_INTERNAL
+#define _MALLOC_INTERNAL
+#include <malloc.h>
+#endif
+
+#ifndef __GNU_LIBRARY__
+#define __sbrk sbrk
+#endif
+
+extern __ptr_t __sbrk __P ((int increment));
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+/* Allocate INCREMENT more bytes of data space,
+ and return the start of data space, or NULL on errors.
+ If INCREMENT is negative, shrink data space. */
+__ptr_t
+__default_morecore (increment)
+ ptrdiff_t increment;
+{
+ __ptr_t result = __sbrk ((int) increment);
+ if (result == (__ptr_t) -1)
+ return NULL;
+ return result;
+}
+/* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+This library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#ifndef _MALLOC_INTERNAL
+#define _MALLOC_INTERNAL
+#include <malloc.h>
+#endif
+
+__ptr_t
+memalign (alignment, size)
+ size_t alignment;
+ size_t size;
+{
+ __ptr_t result;
+ unsigned long int adj;
+
+ size = ((size + alignment - 1) / alignment) * alignment;
+
+ result = malloc (size);
+ if (result == NULL)
+ return NULL;
+ adj = (unsigned long int) ((unsigned long int) ((char *) result -
+ (char *) NULL)) % alignment;
+ if (adj != 0)
+ {
+ struct alignlist *l;
+ for (l = _aligned_blocks; l != NULL; l = l->next)
+ if (l->aligned == NULL)
+ /* This slot is free. Use it. */
+ break;
+ if (l == NULL)
+ {
+ l = (struct alignlist *) malloc (sizeof (struct alignlist));
+ if (l == NULL)
+ {
+ free (result);
+ return NULL;
+ }
+ }
+ l->exact = result;
+ result = l->aligned = (char *) result + alignment - adj;
+ l->next = _aligned_blocks;
+ _aligned_blocks = l;
+ }
+
+ return result;
+}
+/* Allocate memory on a page boundary.
+ Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+This library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.
+
+ The author may be reached (Email) at the address mike@ai.mit.edu,
+ or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#ifndef _MALLOC_INTERNAL
+#define _MALLOC_INTERNAL
+#include <malloc.h>
+#endif
+
+#ifdef __GNU_LIBRARY__
+extern size_t __getpagesize __P ((void));
+#else
+#include "getpagesize.h"
+#define __getpagesize() getpagesize()
+#endif
+
+static size_t pagesize;
+
+__ptr_t
+valloc (size)
+ size_t size;
+{
+ if (pagesize == 0)
+ pagesize = __getpagesize ();
+
+ return memalign (pagesize, size);
+}
diff --git a/lib/hexify.c b/lib/hexify.c
new file mode 100644
index 0000000..e3941b2
--- /dev/null
+++ b/lib/hexify.c
@@ -0,0 +1,46 @@
+/* hexify.c: change a binary string to ASCII hex characters.
+
+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 "hexify.h"
+
+
+/* Convert the number N (assumed to be small enough) to a lowercase hex
+ character. */
+#define HEX_DIGIT(n) ((n) < 10 ? (n) + '0' : (n) - 10 + 'a')
+
+string
+hexify (one_byte *data, unsigned length)
+{
+ unsigned i;
+ /* Each byte in S turns into two hex chars, plus the terminating null. */
+ string h = xmalloc (length * 2 + 1);
+
+ for (i = 0; i < length; i++)
+ {
+ unsigned char n = (data[i] & 0xf0) >> 4;
+ h[i * 2] = HEX_DIGIT (n);
+
+ n = data[i] & 0x0f;
+ h[i * 2 + 1] = HEX_DIGIT (n);
+ }
+ h[i * 2] = 0;
+
+ return h;
+}
diff --git a/lib/identity.c b/lib/identity.c
new file mode 100644
index 0000000..ffe0e1d
--- /dev/null
+++ b/lib/identity.c
@@ -0,0 +1,38 @@
+/* identity.c.
+
+Copyright (C) 1995 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 <stdio.h>
+#include <kpathsea/c-proto.h>
+#include <kpathsea/lib.h>
+#include <kpathsea/progname.h>
+
+/* Return `hostname:pid' as a string. */
+
+string
+get_identity ()
+{
+ char s[1024];
+ int i;
+
+ i = XmuGetHostname (s, sizeof (s));
+ if (i == 0)
+ FATAL ("limn: Could not get hostname");
+
+ sprintf (&s[i], ":%d", getpid ());
+ return (string)xstrdup (s);
+}
diff --git a/lib/integer-ok.c b/lib/integer-ok.c
new file mode 100644
index 0000000..5af9214
--- /dev/null
+++ b/lib/integer-ok.c
@@ -0,0 +1,44 @@
+/* integer-ok.c: test if a string is a valid integer.
+
+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 <kpathsea/c-ctype.h>
+
+
+boolean
+integer_ok (string str)
+{
+ boolean found_digit = false;
+
+ if (str == NULL)
+ return false;
+
+ /* Allow leading `-' or `+' sign. */
+ if (*str == '-' || *str == '+')
+ str++;
+
+ /* Skip decimal digits. */
+ while (ISDIGIT (*str))
+ {
+ str++;
+ found_digit = true;
+ }
+
+ return *str == 0 && found_digit;
+}
diff --git a/lib/libfile.c b/lib/libfile.c
new file mode 100644
index 0000000..7ce3633
--- /dev/null
+++ b/lib/libfile.c
@@ -0,0 +1,130 @@
+/* libfile.c: open and read a single auxiliary data file.
+
+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 "paths.h"
+
+#include <kpathsea/c-ctype.h>
+#include <kpathsea/line.h>
+#include "libfile.h"
+#include "pathsrch.h"
+
+
+/* Private variables to hold the auxiliary file we're reading from, and
+ its name. */
+static FILE *lib_file = NULL;
+static string lib_filename;
+static unsigned lib_file_line_number;
+
+
+/* Prepare to read the ``library file'' FILENAME.DEFAULT_SUFFIX (if
+ FILENAME has no suffix), or just FILENAME (if it has). Give a fatal
+ error if it cannot be opened. Return the resulting FILE * (although
+ usually this will just be ignored by the caller). */
+
+FILE *
+libfile_start (string filename, string default_suffix)
+{
+ string *lib_dirs = initialize_path_list (LIB_ENVVAR, DEFAULT_LIB_PATH);
+ string name = extend_filename (filename, default_suffix);
+
+ lib_filename = find_path_filename (name, lib_dirs);
+
+ if (lib_filename == NULL)
+ FATAL1 ("%s: Cannot find library file in path", name);
+
+ lib_file = xfopen (lib_filename, "r");
+ lib_file_line_number = 1;
+
+ return lib_file;
+}
+
+
+/* Close our current open file. If we don't have any file open, give a
+ fatal error. */
+
+void
+libfile_close ()
+{
+ assert (lib_file != NULL);
+
+ fclose (lib_file);
+ lib_file = NULL;
+}
+
+/* Return the name of the currently open file, or NULL if none. */
+
+string
+libfilename ()
+{
+ return lib_file == NULL ? NULL : lib_filename;
+}
+
+
+/* Analogously, for the current line number. */
+
+unsigned
+libfile_linenumber ()
+{
+ return lib_file == NULL ? 0 : lib_file_line_number;
+}
+
+/* Return the next nonblank non-comment line from `lib_file', or NULL if
+ we are at EOF. Also remove any trailing comment on the line. */
+
+string
+libfile_line ()
+{
+ string s;
+ string line;
+ boolean skip = true;
+
+ assert (lib_file != NULL);
+
+ do
+ {
+ line = read_line (lib_file);
+ lib_file_line_number++;
+
+ /* If at EOF, quit the loop. */
+ if (line == NULL)
+ break;
+
+ s = line;
+
+ /* Move ahead to the first nonblank character. */
+ while (*s != 0 && ISSPACE (*s))
+ s++;
+
+ /* Keep going if the line was blank or a comment. */
+ if (*s == 0 || *s == '%')
+ free (line);
+ else
+ skip = false;
+ }
+ while (skip);
+
+ if (line != NULL)
+ {
+ s = strrchr (line, '%');
+ if (s != NULL)
+ *s = 0;
+ }
+
+ return line;
+}
diff --git a/lib/line.c b/lib/line.c
new file mode 100644
index 0000000..6c2e16e
--- /dev/null
+++ b/lib/line.c
@@ -0,0 +1,63 @@
+/* line.c: return the next line from a file, or NULL.
+
+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"
+
+
+#define BLOCK_SIZE 40
+
+char *
+read_line (f)
+ FILE *f;
+{
+ int c;
+ unsigned limit = BLOCK_SIZE;
+ unsigned loc = 0;
+ char *line = (char *) xmalloc (limit);
+
+ while ((c = getc (f)) != EOF && c != '\n')
+ {
+ line[loc] = c;
+ loc++;
+
+ /* By testing after the assignment, we guarantee that we'll always
+ have space for the null we append below. We know we always
+ have room for the first char, since we start with BLOCK_SIZE. */
+ if (loc == limit)
+ {
+ limit += BLOCK_SIZE;
+ line = (char *) xrealloc (line, limit);
+ }
+ }
+
+ /* If we read anything, return it. This can't represent a last
+ ``line'' which doesn't end in a newline, but so what. */
+ if (c != EOF)
+ {
+ /* Terminate the string. We can't represent nulls in the file,
+ either. Again, it doesn't matter. */
+ line[loc] = 0;
+ }
+ else /* At end of file. */
+ {
+ free (line);
+ line = NULL;
+ }
+
+ return line;
+}
diff --git a/lib/list.c b/lib/list.c
new file mode 100644
index 0000000..8dcca72
--- /dev/null
+++ b/lib/list.c
@@ -0,0 +1,64 @@
+/* list.c: simple list (represented as arrays) manipulation.
+
+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 "list.h"
+
+
+list_type
+list_init ()
+{
+ list_type answer;
+
+ LIST_DATA (answer) = NULL;
+ LIST_SIZE (answer) = 0;
+
+ return answer;
+}
+
+
+/* Free the memory for both the elements and the list itself. */
+
+void
+list_free (list_type *list)
+{
+ if (list != NULL && LIST_DATA (*list) != NULL)
+ {
+ unsigned e;
+
+ for (e = 0; e < LIST_SIZE (*list); e++)
+ free (LIST_ELT (*list, e));
+
+ free (LIST_DATA (*list));
+ }
+}
+
+/* The list consists entirely of pointers to objects. We allocate the
+ space for the objects pointed to here, though, and return a pointer to
+ the newly-created final element in the list. */
+
+address
+list_append (list_type *list, unsigned element_size)
+{
+ LIST_SIZE (*list)++;
+ XRETALLOC (LIST_DATA (*list), LIST_SIZE (*list), address);
+ LIST_LAST_ELT (*list) = xmalloc (element_size);
+
+ return LIST_LAST_ELT (*list);
+}
diff --git a/lib/logreport.c b/lib/logreport.c
new file mode 100644
index 0000000..93d2dff
--- /dev/null
+++ b/lib/logreport.c
@@ -0,0 +1,36 @@
+/* logreport.c: showing information to the user.
+
+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 "logreport.h"
+
+
+/* Says whether to output detailed progress reports, i.e., all the data
+ on the fitting, as we run. (-log) */
+boolean logging = false;
+
+FILE *log_file = NULL;
+
+
+void
+flush_log_output ()
+{
+ if (logging)
+ fflush (log_file);
+}
diff --git a/lib/make-prefix.c b/lib/make-prefix.c
new file mode 100644
index 0000000..fe4fcd4
--- /dev/null
+++ b/lib/make-prefix.c
@@ -0,0 +1,41 @@
+/* make-prefix.c: construct a pathname prefix.
+
+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 <kpathsea/concatn.h>
+
+
+string
+make_prefix (string prefix, string pathname)
+{
+ string slash_pos = strrchr (pathname, '/');
+
+ if (slash_pos == NULL)
+ return concat (prefix, pathname);
+ else
+ {
+ string answer = NULL;
+ string path_only = xstrdup (pathname);
+ path_only[slash_pos - pathname] = 0;
+ answer = concatn (path_only, "/", prefix, slash_pos + 1, NULL);
+ free (path_only);
+
+ return answer;
+ }
+}
diff --git a/lib/math.c b/lib/math.c
new file mode 100644
index 0000000..0939d8e
--- /dev/null
+++ b/lib/math.c
@@ -0,0 +1,173 @@
+/* math.c: define some simple array operations, and other functions.
+
+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"
+
+
+/* Numerical errors sometimes make a floating point number just slightly
+ larger or smaller than its true value. When it matters, we need to
+ compare with some tolerance, REAL_EPSILON, defined in kbase.h. */
+
+const boolean
+epsilon_equal (real v1, real v2)
+{
+ return
+ v1 == v2 /* Usually they'll be exactly equal, anyway. */
+ || fabs (v1 - v2) <= REAL_EPSILON;
+}
+
+
+/* Return the Euclidean distance between P1 and P2. */
+
+const real
+distance (real_coordinate_type p1, real_coordinate_type p2)
+{
+ return hypot (p1.x - p2.x, p1.y - p2.y);
+}
+
+
+/* Same thing, for integer points. */
+const real
+int_distance (coordinate_type p1, coordinate_type p2)
+{
+ return hypot ((double) p1.x - p2.x, (double) p1.y - p2.y);
+}
+
+
+/* Return the arc cosine of V, in degrees in the range zero to 180. V
+ is taken to be in radians. */
+
+const real
+acosd (real v)
+{
+ real a;
+
+ if (epsilon_equal (v, 1.0))
+ v = 1.0;
+ else if (epsilon_equal (v, -1.0))
+ v = -1.0;
+
+ errno = 0;
+ a = acos (v);
+ if (errno == ERANGE || errno == EDOM)
+ FATAL_PERROR ("acosd");
+
+ return a * 180.0 / M_PI;
+}
+
+
+/* The slope of the line defined by COORD1 and COORD2. */
+
+const real
+slope (real_coordinate_type coord1, real_coordinate_type coord2)
+{
+ assert (coord2.x - coord1.x != 0);
+
+ return (coord2.y - coord1.y) / (coord2.x - coord1.x);
+}
+
+
+/* Turn an integer point into a real one, and vice versa. */
+
+const real_coordinate_type
+int_to_real_coord (coordinate_type int_coord)
+{
+ real_coordinate_type real_coord;
+
+ real_coord.x = int_coord.x;
+ real_coord.y = int_coord.y;
+
+ return real_coord;
+}
+
+
+const coordinate_type
+real_to_int_coord (real_coordinate_type real_coord)
+{
+ coordinate_type int_coord;
+
+ int_coord.x = ROUND (real_coord.x);
+ int_coord.y = ROUND (real_coord.y);
+
+ return int_coord;
+}
+
+
+/* See if two points (described by their row and column) are adjacent. */
+
+const boolean
+points_adjacent_p (int row1, int col1, int row2, int col2)
+{
+ int row_diff = abs (row1 - row2);
+ int col_diff = abs (col1 - col2);
+
+ return
+ (row_diff == 1 && col_diff == 1)
+ || (row_diff == 0 && col_diff == 1)
+ || (row_diff == 1 && col_diff == 0);
+}
+
+
+
+
+/* Find the largest and smallest elements in an array of reals. */
+
+void
+find_bounds (real *values, unsigned value_count, real *min, real *max)
+{
+ unsigned this_value;
+
+ /* We must use FLT_MAX and FLT_MIN, instead of the corresponding
+ values for double, because gcc uses the native atof to parse
+ floating point constants, and many atof's choke on the extremes. */
+ *min = FLT_MAX;
+ *max = FLT_MIN;
+
+ for (this_value = 0; this_value < value_count; this_value++)
+ {
+ if (values[this_value] < *min)
+ *min = values[this_value];
+
+ if (values[this_value] > *max)
+ *max = values[this_value];
+ }
+}
+
+
+
+/* Map a range of numbers, some positive and some negative, into all
+ positive, with the greatest being at one and the least at zero.
+
+ This allocates new memory. */
+
+real *
+map_to_unit (real *values, unsigned value_count)
+{
+ real smallest, largest;
+ int this_value;
+ real *mapped_values = xmalloc (sizeof (real) * value_count);
+
+ find_bounds (values, value_count, &smallest, &largest);
+
+ largest -= smallest; /* We never care about largest itself. */
+
+ for (this_value = 0; this_value < value_count; this_value++)
+ mapped_values[this_value] = (values[this_value] - smallest) / largest;
+
+ return mapped_values;
+}
diff --git a/lib/now.c b/lib/now.c
new file mode 100644
index 0000000..aabf718
--- /dev/null
+++ b/lib/now.c
@@ -0,0 +1,38 @@
+/* time.c: the current date and time.
+
+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"
+
+
+/* Get the current date and time as a string. The 26 here is defined in
+ the manual page for ctime(3). */
+
+string
+now ()
+{
+ extern time_t time (long *);
+ extern string ctime (time_t *);
+
+ string time_string = xmalloc (26);
+ time_t t = time (0);
+
+ strcpy (time_string, ctime (&t));
+ time_string[24] = 0; /* No newline. */
+
+ return time_string;
+}
diff --git a/lib/numtoa.c b/lib/numtoa.c
new file mode 100644
index 0000000..53c1a7d
--- /dev/null
+++ b/lib/numtoa.c
@@ -0,0 +1,50 @@
+/* numtoa.c: change numbers back to strings.
+
+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"
+
+/* Declarations for these are in global.h. */
+
+string
+itoa (int i)
+{
+ char a[MAX_INT_LENGTH];
+
+ sprintf (a, "%d", i);
+ return xstrdup (a);
+}
+
+string
+utoa (unsigned u)
+{
+ char a[MAX_INT_LENGTH];
+
+ sprintf (a, "%u", u);
+ return xstrdup (a);
+}
+
+string
+xdtoa (double d)
+{
+ /* I'm not sure if this is really enough, but I also don't know how to
+ compute what *would* be enough. */
+ char a[500];
+
+ sprintf (a, "%f", d);
+ return xstrdup (a);
+}
diff --git a/lib/pathsrch.c b/lib/pathsrch.c
new file mode 100644
index 0000000..e513df5
--- /dev/null
+++ b/lib/pathsrch.c
@@ -0,0 +1,509 @@
+/* pathsrch.c: look for files based on paths, i.e., colon-separated
+ lists of directories.
+
+ We should allow % specifiers in the paths for the resolution, mode
+ name, etc.
+
+Copyright (C) 1992, 93 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 <kpathsea/c-stat.h>
+#include "c-pathch.h"
+#include "c-namemx.h"
+#include "c-pathmx.h"
+#include "paths.h"
+
+#include <kpathsea/c-ctype.h>
+#if !defined (DOS) && !defined (VMS) && !defined (VMCMS)
+#include <pwd.h>
+#endif
+#include "dirio.h"
+#include "pathsrch.h"
+
+static boolean absolute_p P1H(string filename);
+static void add_directory P3H(string **, unsigned *, string);
+static void expand_subdir P3H(string **, unsigned *, string);
+static string *find_dir_list P1H(string);
+static string readable P1H(string);
+static void save_dir_list P2H(string, string *);
+static string truncate_pathname P1H(string);
+
+/* If FILENAME is absolute or explicitly relative (i.e., starts with
+ `/', `./', or `../'), or if DIR_LIST is null, we return whether
+ FILENAME is readable as-is. Otherwise, we test if FILENAME is in any of
+ the directories listed in DIR_LIST. (The last entry of DIR_LIST must
+ be null.) We return the complete path if found, NULL else.
+
+ In the interests of doing minimal work here, we assume that each
+ element of DIR_LIST already ends with a `/'.
+
+ DIR_LIST is most conveniently made by calling `initialize_path_list'.
+ This is a separate routine because we allow recursive searching, and
+ it may take some time to discover the list of directories.
+ We do not want to incur that overhead every time we want to look for
+ a file.
+
+ (Actually, `/' is not hardwired into this routine; we use PATH_SEP,
+ defined above.) */
+
+string
+find_path_filename P2C(string, filename, string *, dir_list)
+{
+ string found_name = NULL;
+
+ /* Do this before testing for absolute-ness, as a leading ~ will be an
+ absolute pathname. */
+ filename = expand_tilde (filename);
+
+ /* If FILENAME is absolute or explicitly relative, or if DIR_LIST is
+ null, only check if FILENAME is readable. */
+ if (absolute_p (filename) || dir_list == NULL)
+ found_name = readable (filename);
+ else
+ { /* Test if FILENAME is in any of the directories in DIR_LIST. */
+ string save_filename = filename;
+
+ while (*dir_list != NULL)
+ {
+ filename = concat (*dir_list, save_filename);
+ found_name = readable (filename);
+ if (found_name == NULL)
+ {
+ free (filename);
+ dir_list++;
+ }
+ else
+ {
+ if (found_name != filename)
+ free (filename);
+ break;
+ }
+ }
+ }
+
+ return found_name;
+}
+
+
+/* If NAME is readable, return it. If the error is ENAMETOOLONG,
+ truncate any too-long path components and return the result (unless
+ there were no too-long components, i.e., a overall too-long name
+ caused the error, in which case return NULL). On any other error,
+ return NULL.
+
+ POSIX invented this brain-damage of not necessarily truncating
+ pathname components; the system's behavior is defined by the value of
+ the symbol _POSIX_NO_TRUNC, but you can't change it dynamically! */
+
+static string
+readable (name)
+ string name;
+{
+ string ret;
+
+ if (access (name, R_OK) == 0 && !dir_p (name))
+ ret = name;
+#ifdef ENAMETOOLONG
+ else if (errno == ENAMETOOLONG)
+ {
+ ret = truncate_pathname (name);
+
+ /* Perhaps some other error will occur with the truncated name, so
+ let's call access again. */
+ if (!(access (ret, R_OK) == 0 && !dir_p (ret)))
+ { /* Failed. */
+ free (ret);
+ ret = NULL;
+ }
+ }
+#endif
+ else
+ ret = NULL; /* Some other error. */
+
+ return ret;
+}
+
+
+
+/* Truncate any too-long path components in NAME, returning the result. */
+
+static string
+truncate_pathname (name)
+ string name;
+{
+ unsigned c_len = 0; /* Length of current component. */
+ unsigned ret_len = 0; /* Length of constructed result. */
+ string ret = (string) xmalloc (PATH_MAX + 1);
+
+ for (; *name; name++)
+ {
+ if (IS_PATH_SEP (*name))
+ { /* At a directory delimiter, reset component length. */
+ c_len = 0;
+ }
+ else if (c_len > NAME_MAX)
+ { /* If past the max for a component, ignore this character. */
+ continue;
+ }
+
+ /* If we've already copied the max, give up. */
+ if (ret_len == PATH_MAX)
+ {
+ free (ret);
+ return NULL;
+ }
+
+ /* Copy this character. */
+ ret[ret_len++] = *name;
+ c_len++;
+ }
+ ret[ret_len] = 0;
+
+ return ret;
+}
+
+
+/* Return true if FILENAME is absolute or explicitly relative, else false. */
+
+static boolean
+absolute_p P1C(string, filename)
+{
+ boolean absolute = IS_PATH_SEP (*filename)
+#ifdef DOS
+ || ISALPHA (*filename) && filename[1] == ':'
+#endif
+ ;
+ boolean explicit_relative
+ = (*filename == '.'
+ && (IS_PATH_SEP (filename[1])
+ || (filename[1] == '.' && IS_PATH_SEP (filename[2]))));
+
+ return absolute || explicit_relative;
+}
+
+/* Return a NULL-terminated array of directory names, each name ending
+ with PATH_SEP, created by parsing the PATH_DELIMITER-separated list
+ in the value of the environment variable ENV_NAME, or DEFAULT_PATH if
+ the envvar is not set.
+
+ A leading or trailing colon in the value of ENV_NAME is replaced by
+ DEFAULT_PATH.
+
+ Any element of the path that ends with double PATH_SEP characters
+ (e.g., `foo//') is replaced by all its subdirectories.
+
+ If ENV_NAME is null, only parse DEFAULT_PATH. If both are null, do
+ nothing and return NULL. */
+
+string *
+initialize_path_list P2C(string, env_name, string, default_path)
+{
+ string dir, path;
+ string *dir_list;
+ unsigned dir_count = 0;
+ string env_value = env_name ? getenv (env_name) : NULL;
+ string orig_path = expand_default (env_value, default_path);
+
+ if (orig_path == NULL || *orig_path == 0)
+ return NULL;
+
+ /* If we've already seen this colon-separated list, then just get it
+ back instead of going back to the filesystem. */
+ dir_list = find_dir_list (orig_path);
+ if (dir_list != NULL)
+ return dir_list;
+
+ /* Be sure `path' is in writable memory. */
+ path = (orig_path == env_value || orig_path == default_path
+ ? xstrdup (orig_path) : orig_path);
+
+ /* Find each element in the path in turn. */
+ for (dir = strtok (path, PATH_DELIMITER_STRING); dir != NULL;
+ dir = strtok (NULL, PATH_DELIMITER_STRING))
+ {
+ int len;
+ /* If the path starts with ~ or ~user, expand it. Do this
+ before calling `expand_subdir' or `add_directory', so that
+ 1) we don't expand the same ~ for every subdirectory; and
+ 2) pathnames in `expand_subdir' don't have a `~' in them
+ (since the system won't grok `~/foo' as a directory). */
+ dir = expand_tilde (dir);
+ len = strlen (dir);
+
+ /* If `dir' is the empty string, ignore it. */
+ if (len == 0)
+ continue;
+
+ /* If `dir' ends in double slashes, do subdirectories (and remove
+ the second slash, so the final pathnames we return don't look
+ like foo//bar). Because we obviously want to do subdirectories
+ of `dir', we don't check if it is a leaf. This means that if
+ `dir' is `foo//', and `foo' contains only symlinks (so our leaf
+ test below would be true), the symlinks are chased. */
+ if (len > 2 && IS_PATH_SEP (dir[len - 1]) && IS_PATH_SEP (dir[len - 2]))
+ {
+ dir[len - 1] = 0;
+ if (dir_p (dir))
+ {
+ add_directory (&dir_list, &dir_count, dir);
+ expand_subdir (&dir_list, &dir_count, dir);
+ }
+ }
+ else
+ { /* Don't bother to add the directory if it doesn't exist. */
+ if (dir_p (dir))
+ add_directory (&dir_list, &dir_count, dir);
+ }
+ }
+
+ /* Add the terminating null entry to `dir_list'. */
+ dir_count++;
+ XRETALLOC (dir_list, dir_count, string);
+ dir_list[dir_count - 1] = NULL;
+
+ /* Save the directory list we just found. */
+ save_dir_list (orig_path, dir_list);
+
+ return dir_list;
+}
+
+/* Subroutines for `initialize_path_list'. */
+
+/* Add a newly-allocated copy of DIR to the end of the array pointed to
+ by DIR_LIST_PTR. Increment DIR_COUNT_PTR. Append a `/' to DIR if
+ necessary. We assume DIR is a directory, to avoid unnecessary an
+ unnecessary call to `stat'. */
+
+static void
+add_directory (dir_list_ptr, dir_count_ptr, dir)
+ string **dir_list_ptr;
+ unsigned *dir_count_ptr;
+ string dir;
+{
+ /* If `dir' does not end with a `/', add it. We can't just
+ write it in place, since that would overwrite the null that
+ strtok may have put in. So we always make a copy of DIR. */
+ dir = (IS_PATH_SEP (dir[strlen (dir) - 1]) ? xstrdup (dir)
+ : concat (dir, PATH_SEP_STRING));
+
+ /* Add `dir' to the list of the directories. */
+ (*dir_count_ptr)++;
+ XRETALLOC (*dir_list_ptr, *dir_count_ptr, string);
+ (*dir_list_ptr)[*dir_count_ptr - 1] = dir;
+}
+
+
+/* Add DIRNAME to DIR_LIST and look for subdirectories, recursively. We
+ assume DIRNAME is the name of a directory. */
+
+static void
+expand_subdir (dir_list_ptr, dir_count_ptr, dirname)
+ string **dir_list_ptr;
+ unsigned *dir_count_ptr;
+ string dirname;
+{
+ DIR *dir;
+ struct dirent *e;
+ unsigned length;
+ char potential[PATH_MAX];
+ struct stat st;
+
+ /* We will be looking at its contents. */
+ dir = opendir (dirname);
+ if (dir == NULL)
+ return;
+
+ /* Compute the length of DIRNAME, since it's loop-invariant. */
+ length = strlen (dirname);
+
+ /* Construct the part of the pathname that doesn't change. */
+ strcpy (potential, dirname);
+ if (!IS_PATH_SEP (potential[length - 1]))
+ {
+ potential[length] = PATH_SEP;
+ potential[length + 1] = 0;
+ length++;
+ }
+
+ while ((e = readdir (dir)) != NULL)
+ { /* If it's . or .., never mind. */
+ if (!(e->d_name[0] == '.'
+ && (e->d_name[1] == 0
+ || (e->d_name[1] == '.' && e->d_name[2] == 0))))
+ { /* If it's not a directory, we will skip it on the
+ recursive call. */
+ strcat (potential, e->d_name);
+
+ /* If we can't stat it, or if it isn't a directory, continue. */
+ if (stat (potential, &st) == 0 && S_ISDIR (st.st_mode))
+ { /* It's a subdirectory; add `potential' to the list. */
+ add_directory (dir_list_ptr, dir_count_ptr, potential);
+
+ /* If it's not a leaf, quit. Assume that leaf
+ directories have two links (one for . and one for ..).
+ This means that symbolic links to directories do not affect
+ the leaf-ness. This is arguably wrong, but the only
+ alternative I know of is to stat every entry in the
+ directory, and that is unacceptably slow.
+
+ The #ifdef here at least makes this configurable at
+ compile-time, so that if we're using VMS directories or
+ some such, we can still find subdirectories, even if it
+ is much slower. */
+#ifdef UNIX_ST_NLINK
+ if (st.st_nlink > 2)
+#endif
+ { /* All criteria are met; find subdirectories. */
+ expand_subdir (dir_list_ptr, dir_count_ptr, potential);
+ }
+ }
+
+ /* ``Remove'' the directory entry name. */
+ potential[length] = 0;
+ }
+ }
+
+ closedir (dir);
+}
+
+/* These routines, while not strictly needed to be exported, are
+ plausibly useful to be called by outsiders. */
+
+/* Replace a leading or trailing `:' in ENV_PATH with DEFAULT_PATH. If
+ neither is present, return ENV_PATH if that is non-null, else
+ DEFAULT_PATH. */
+
+string
+expand_default (env_path, default_path)
+ string env_path;
+ string default_path;
+{
+ string expansion;
+
+ if (env_path == NULL)
+ expansion = default_path;
+ else if (*env_path == PATH_DELIMITER)
+ expansion = concat (default_path, env_path);
+ else if (env_path[strlen (env_path) - 1] == PATH_DELIMITER)
+ expansion = concat (env_path, default_path);
+ else
+ expansion = env_path;
+
+ return expansion;
+}
+
+
+/* Expand a leading ~ or ~user, Unix-style, unless we are some weirdo
+ operating system. */
+
+string
+expand_tilde P1C(string, name)
+{
+#if defined (DOS) || defined (VMS) || defined (VMCMS)
+ return name;
+#else
+ string expansion;
+ string home;
+
+ /* If no leading tilde, do nothing. */
+ if (*name != '~')
+ expansion = name;
+
+ /* If `~' or `~/', use $HOME if it exists, or `.' if it doesn't. */
+ else if (IS_PATH_SEP (name[1]) || name[1] == 0)
+ {
+ home = getenv ("HOME");
+ if (home == NULL)
+ home = ".";
+
+ expansion
+ = name[1] == 0 ? home : concat3 (home, PATH_SEP_STRING, name + 2);
+ }
+
+ /* If `~user' or `~user/', look up user in the passwd database. */
+ else
+ {
+ struct passwd *p;
+ string user;
+ unsigned c = 2;
+ while (!IS_PATH_SEP (name[c]) && name[c] != 0)
+ c++;
+
+ user = (string) xmalloc (c);
+ strncpy (user, name + 1, c - 1);
+ user[c - 1] = 0;
+
+ /* We only need the cast here for those (old deficient) systems
+ which do not declare `getpwnam' in <pwd.h>. */
+ p = (struct passwd *) getpwnam (user);
+ free (user);
+ /* If no such user, just use `.'. */
+ home = p == NULL ? "." : p->pw_dir;
+
+ expansion = name[c] == 0 ? home : concat (home, name + c);
+ }
+
+ return expansion;
+#endif /* not (DOS or VMS or VM/CMS) */
+}
+
+/* Routines to save and retrieve a directory list keyed by the original
+ colon-separated path. This is useful because 1) it can take a
+ significant amount of time to discover all the subdirectories of a
+ given directory, and 2) many paths all have the same basic default,
+ and thus would recompute the directory list. */
+
+typedef struct
+{
+ string path;
+ string *dir_list;
+} saved_path_entry;
+
+static saved_path_entry *saved_paths = NULL;
+static unsigned saved_paths_length = 0;
+
+
+/* We implement the data structure as a simple linear list, since it's
+ unlikely to ever be more than a dozen or so elements long. We don't
+ bother to check here if PATH has already been saved; we always add it
+ to our list. */
+
+static void
+save_dir_list P2C(string, path, string *, dir_list)
+{
+ saved_paths_length++;
+ XRETALLOC (saved_paths, saved_paths_length, saved_path_entry);
+ saved_paths[saved_paths_length - 1].path = path;
+ saved_paths[saved_paths_length - 1].dir_list = dir_list;
+}
+
+/* When we retrieve, just check the list in order. */
+
+static string *
+find_dir_list P1C(string, path)
+{
+ unsigned p;
+
+ for (p = 0; p < saved_paths_length; p++)
+ {
+ if (strcmp (saved_paths[p].path, path) == 0)
+ return saved_paths[p].dir_list;
+ }
+
+ return NULL;
+}
diff --git a/lib/rand.c b/lib/rand.c
new file mode 100644
index 0000000..78cc7fa
--- /dev/null
+++ b/lib/rand.c
@@ -0,0 +1,70 @@
+/* rand.c: a simple pseudo-random number generator.
+
+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 "rand.h"
+
+
+/* Current state of the random number generator. ANSI C says that the
+ default should be as if `srand' was called with the value 1. At all
+ times this will be a random number between 1 and RAND_MAX+1. */
+static long rand_state = 2;
+
+
+/* Set the state. It's ok if `seed' doesn't fit in a long, since we
+ check for negative values before we return anything. On the other
+ hand, we cannot allow our state to become zero, since then we will
+ produce zero forever. */
+
+void
+seed_rand (unsigned seed)
+{
+ rand_state = seed + 1;
+}
+
+
+/* Return a pseudo-random number based on `x' in the range [0, RAND_MAX].
+ We use the Ghostscript computation (from the function `zrand' in the
+ file `zmath.c'). */
+
+int
+k_rand ()
+{
+ /* We use an algorithm from CACM 31(10), pp. 1192-1201, October 1988.
+ According to a posting by Ed Taft on comp.lang.postscript, Level 2
+ (Adobe) PostScript interpreters use this algorithm too:
+
+ x[n+1] = (16807 * x[n]) mod (2^31 - 1)
+
+ The complication ensues from the fact that the multiplication may
+ lead to a 46-bit number. */
+
+#define A 16807
+#define M 0x7fffffff
+#define Q 127773 /* M / A */
+#define R 2836 /* M % A */
+ rand_state = A * (rand_state % Q) - R * (rand_state / Q);
+ while ( rand_state <= 0 ) rand_state += M;
+
+ /* OK, `rand_state' is our new random number between 1 and 2^31 - 1.
+ Now we have to subtract one, so that we return a number in the
+ range zero to RAND_MAX (inclusive). We obviously must define our
+ RAND_MAX to be 2^31 - 2, which we do (in `rand.h'). */
+ return rand_state - 1;
+}
diff --git a/lib/report.c b/lib/report.c
new file mode 100644
index 0000000..fc732b2
--- /dev/null
+++ b/lib/report.c
@@ -0,0 +1,27 @@
+/* report.c: showing information to the user online.
+
+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"
+
+
+/* Says whether to output short progress reports as we run. (-verbose) */
+boolean verbose = false;
+
+/* Where to output the reports. If a particular program uses standard
+ output for real output, this gets changed to `stderr'. */
+FILE *report_file = stdout;
diff --git a/lib/safe-free.c b/lib/safe-free.c
new file mode 100644
index 0000000..7c56d0a
--- /dev/null
+++ b/lib/safe-free.c
@@ -0,0 +1,37 @@
+/* safe-free.c: free with error checking.
+
+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"
+
+
+/* `free' itself does not return an error status. So all we can do here
+ is check for nulls. */
+
+void
+safe_free (address *item)
+{
+ if (item == NULL || *item == NULL)
+ {
+ fprintf (stderr, "safe_free: Attempt to free a null item.\n");
+ abort ();
+ }
+
+ free (*item);
+
+ *item = NULL;
+}
diff --git a/lib/scaled-num.c b/lib/scaled-num.c
new file mode 100644
index 0000000..cf4a18f
--- /dev/null
+++ b/lib/scaled-num.c
@@ -0,0 +1,75 @@
+/* scaled-num.c: conversions on ``scaled'' numbers, which are a 32-bit
+ word with 16 bits of fraction.
+
+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 "scaled-num.h"
+
+
+#define SCALED_UNITY (1 << 16) /* 2^16, represents 1.00000. */
+
+
+/* This prints a scaled number, rounded to five digits. */
+
+void
+print_scaled (scaled s)
+{
+ scaled delta;
+
+ if (s < 0)
+ { /* Print sign, if negative. */
+ putchar ('-');
+ s = -s;
+ }
+
+ printf ("%u", s / SCALED_UNITY); /* Print integer part. */
+ putchar ('.');
+
+ s = 10 * (s % SCALED_UNITY) + 5;
+ delta = 10;
+
+ do
+ {
+ if (delta > SCALED_UNITY)
+ s += 0100000 - (delta / 2); /* Round the last digit. */
+
+ printf ("%c", '0' + (s / SCALED_UNITY));
+ s = 10 * (s % SCALED_UNITY);
+ delta *= 10;
+ }
+ while (s > delta);
+}
+
+
+const real
+scaled_to_real (scaled s)
+{
+ real r = (real) s / SCALED_UNITY;
+
+ return r;
+}
+
+
+const scaled
+real_to_scaled (real r)
+{
+ scaled s = r * SCALED_UNITY;
+
+ return s;
+}
diff --git a/lib/spline.c b/lib/spline.c
new file mode 100644
index 0000000..cdfc25f
--- /dev/null
+++ b/lib/spline.c
@@ -0,0 +1,216 @@
+/* spline.c: spline and spline list (represented as arrays) manipulation.
+
+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 "bounding-box.h"
+#include "spline.h"
+#include "vector.h"
+
+
+/* Return a new spline structure, initialized with (recognizable)
+ garbage. */
+
+spline_type
+new_spline ()
+{
+ spline_type spline;
+
+ START_POINT (spline)
+ = CONTROL1 (spline)
+ = CONTROL2 (spline)
+ = END_POINT (spline)
+ = (real_coordinate_type) { -100.0, -100.0 };
+ SPLINE_DEGREE (spline) = -1;
+
+ return spline;
+}
+
+
+/* Print a spline in human-readable form. */
+
+void
+print_spline (FILE *f, spline_type s)
+{
+ if (SPLINE_DEGREE (s) == LINEAR)
+ fprintf (f, "(%.3f,%.3f)--(%.3f,%.3f).\n",
+ START_POINT (s).x, START_POINT (s).y,
+ END_POINT (s).x, END_POINT (s).y);
+
+ else if (SPLINE_DEGREE (s) == CUBIC)
+ fprintf (f, "(%.3f,%.3f)..ctrls(%.3f,%.3f)&(%.3f,%.3f)..(%.3f,%.3f).\n",
+ START_POINT (s).x, START_POINT (s).y,
+ CONTROL1 (s).x, CONTROL1 (s).y,
+ CONTROL2 (s).x, CONTROL2 (s).y,
+ END_POINT (s).x, END_POINT (s).y);
+
+ else
+ FATAL1 ("print_spline: strange degree (%d)", SPLINE_DEGREE (s));
+}
+
+
+
+
+/* Evaluate the spline S at a given T value. This is an implementation
+ of de Casteljau's algorithm. See Schneider's thesis (reference in
+ ../limn/README), p.37. The variable names are taken from there. */
+
+real_coordinate_type
+evaluate_spline (spline_type s, real t)
+{
+ spline_type V[4]; /* We need degree+1 splines, but assert degree <= 3. */
+ unsigned i, j;
+ real one_minus_t = 1.0 - t;
+ polynomial_degree degree = SPLINE_DEGREE (s);
+
+ for (i = 0; i <= degree; i++)
+ V[0].v[i] = s.v[i];
+
+ for (j = 1; j <= degree; j++)
+ for (i = 0; i <= degree - j; i++)
+ {
+ real_coordinate_type t1 = Pmult_scalar (V[j - 1].v[i], one_minus_t);
+ real_coordinate_type t2 = Pmult_scalar (V[j - 1].v[i + 1], t);
+ V[j].v[i] = Padd (t1, t2);
+ }
+
+ return V[degree].v[0];
+}
+
+
+
+
+/* Return a new, empty, spline list. */
+
+spline_list_type *
+new_spline_list ()
+{
+ spline_list_type *answer = xmalloc (sizeof (spline_list_type));
+
+ SPLINE_LIST_DATA (*answer) = NULL;
+ SPLINE_LIST_LENGTH (*answer) = 0;
+
+ return answer;
+}
+
+
+/* Return a new spline list with SPLINE as the first element. */
+
+spline_list_type *
+init_spline_list (spline_type spline)
+{
+ spline_list_type *answer = xmalloc (sizeof (spline_list_type));
+
+ SPLINE_LIST_DATA (*answer) = xmalloc (sizeof (spline_type));
+ SPLINE_LIST_ELT (*answer, 0) = spline;
+ SPLINE_LIST_LENGTH (*answer) = 1;
+
+ return answer;
+}
+
+
+/* Free the storage in a spline list. We don't have to free the
+ elements, since they are arrays in automatic storage. And we don't
+ want to free the list if it was empty. */
+
+void
+free_spline_list (spline_list_type *spline_list)
+{
+ if (SPLINE_LIST_DATA (*spline_list) != NULL)
+ safe_free ((address *) &(SPLINE_LIST_DATA (*spline_list)));
+}
+
+
+/* Append the spline S to the list SPLINE_LIST. */
+
+void
+append_spline (spline_list_type *l, spline_type s)
+{
+ assert (l != NULL);
+
+ SPLINE_LIST_LENGTH (*l)++;
+ SPLINE_LIST_DATA (*l) = xrealloc (SPLINE_LIST_DATA (*l),
+ SPLINE_LIST_LENGTH (*l) * sizeof (spline_type));
+ LAST_SPLINE_LIST_ELT (*l) = s;
+}
+
+
+/* Tack the elements in the list S2 onto the end of S1.
+ S2 is not changed. */
+
+void
+concat_spline_lists (spline_list_type *s1, spline_list_type s2)
+{
+ unsigned this_spline;
+ unsigned new_length;
+
+ assert (s1 != NULL);
+
+ new_length = SPLINE_LIST_LENGTH (*s1) + SPLINE_LIST_LENGTH (s2);
+
+ XRETALLOC (SPLINE_LIST_DATA (*s1), new_length, spline_type);
+
+ for (this_spline = 0; this_spline < SPLINE_LIST_LENGTH (s2); this_spline++)
+ SPLINE_LIST_ELT (*s1, SPLINE_LIST_LENGTH (*s1)++)
+ = SPLINE_LIST_ELT (s2, this_spline);
+}
+
+
+
+/* Return a new, empty, spline list array. */
+
+spline_list_array_type
+new_spline_list_array ()
+{
+ spline_list_array_type answer;
+
+ SPLINE_LIST_ARRAY_DATA (answer) = NULL;
+ SPLINE_LIST_ARRAY_LENGTH (answer) = 0;
+
+ return answer;
+}
+
+
+/* Free the storage in a spline list array. We don't
+ want to free the list if it is empty. */
+
+void
+free_spline_list_array (spline_list_array_type *spline_list_array)
+{
+ unsigned this_list;
+
+ for (this_list = 0;
+ this_list < SPLINE_LIST_ARRAY_LENGTH (*spline_list_array);
+ this_list++)
+ free_spline_list (&SPLINE_LIST_ARRAY_ELT (*spline_list_array, this_list));
+
+ if (SPLINE_LIST_ARRAY_DATA (*spline_list_array) != NULL)
+ safe_free ((address *) &(SPLINE_LIST_ARRAY_DATA (*spline_list_array)));
+}
+
+
+/* Append the spline S to the list SPLINE_LIST_ARRAY. */
+
+void
+append_spline_list (spline_list_array_type *l, spline_list_type s)
+{
+ SPLINE_LIST_ARRAY_LENGTH (*l)++;
+ XRETALLOC (SPLINE_LIST_ARRAY_DATA (*l),
+ SPLINE_LIST_ARRAY_LENGTH (*l), spline_list_type);
+ LAST_SPLINE_LIST_ARRAY_ELT (*l) = s;
+}
diff --git a/lib/statistics.c b/lib/statistics.c
new file mode 100644
index 0000000..c786ce9
--- /dev/null
+++ b/lib/statistics.c
@@ -0,0 +1,79 @@
+/* statistics.c: find various statistics.
+
+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 "statistics.h"
+
+
+/* The mean. The array A might have been filtered (for example), in
+ which case it will have many zeros in it that shouldn't be counted
+ when computing the statistics. PERTINENT is the number of elements
+ that are actually valid. COUNT, on the other hand, is the number of
+ elements in the array. */
+
+real
+mean (real *a, unsigned count, unsigned pertinent)
+{
+ unsigned this_variable;
+ real sum = 0.0;
+
+ assert (pertinent > 0);
+
+ for (this_variable = 0; this_variable < count; this_variable++)
+ sum += a[this_variable];
+
+ return sum / pertinent;
+}
+
+
+/* The standard deviation. We have to subtract one from the number of
+ samples, because we lost a degree of freedom because of the mean. */
+
+real
+standard_deviation (real *a, real mean, unsigned count, unsigned pertinent)
+{
+ real sum = 0.0;
+ int this_variable;
+
+ assert (pertinent > 0);
+
+ for (this_variable = 0; this_variable < count; this_variable++)
+ {
+ real x = a[this_variable] - mean;
+ sum += x * x;
+ }
+
+ return sqrt (sum / (pertinent > 1 ? (pertinent - 1) : 1));
+}
+
+
+/* Here's a routine to fill up the statistics structure. */
+
+statistics_type
+statistics (real *data, unsigned data_length, unsigned pertinent)
+{
+ statistics_type s;
+
+ s.mean = mean (data, data_length, pertinent);
+
+ s.variance = standard_deviation (data, s.mean, data_length, pertinent);
+ s.variance *= s.variance;
+
+ return s;
+}
diff --git a/lib/str-lcase.c b/lib/str-lcase.c
new file mode 100644
index 0000000..0c21a4c
--- /dev/null
+++ b/lib/str-lcase.c
@@ -0,0 +1,49 @@
+/* str-casefold.c: make a string either all uppercase or all lowercase.
+
+Copyright (C) 1992 Free Software Foundation, Inc.
+This file was part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include "config.h"
+
+#include <kpathsea/c-ctype.h>
+#include "str-lcase.h"
+
+
+/* Return a malloced copy of S with all its uppercase letters replaced
+ with their lowercase counterparts. S must not be NULL. */
+
+string
+str_to_lower (string s)
+{
+ unsigned c;
+ string lc;
+ unsigned length;
+
+ assert (s != NULL);
+
+ length = strlen (s);
+ lc = xmalloc (length + 1);
+
+ for (c = 0; c < length; c++)
+ lc[c] = ISUPPER (s[c]) ? TOLOWER (s[c]) : s[c];
+
+ lc[length] = 0;
+
+ return lc;
+
+}
diff --git a/lib/str-to-bit.c b/lib/str-to-bit.c
new file mode 100644
index 0000000..83ffa42
--- /dev/null
+++ b/lib/str-to-bit.c
@@ -0,0 +1,111 @@
+/* str-to-bit.c: typeset a text string in some font, producing a bitmap.
+
+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 <kpathsea/c-ctype.h>
+#include "font.h"
+
+
+/* Turn the C string TEXT into a bitmap, taking the characters from the
+ font FONT_NAME at resolution DPI. Any space characters in TEXT turn
+ into the natural interword space for this font. No escapes are
+ recognized in TEXT. */
+
+bitmap_type
+string_to_bitmap (string text, string font_name, unsigned dpi)
+{
+ bitmap_type b;
+ unsigned this_char;
+ char_info_type *chars[strlen (text)];
+ font_info_type font = get_font (font_name, dpi);
+ int width = 0, height = 0, depth = 0;
+ int x = 0, y = 0; /* Our current position. */
+ real tfm_space
+ = TFM_SAFE_FONTDIMEN (FONT_TFM_FONT (font), TFM_SPACE_PARAMETER, 0);
+ int font_space = POINTS_TO_PIXELS (tfm_space, dpi);
+
+ for (this_char = 0; this_char < strlen (text); this_char++)
+ {
+ /* Turn any kind of space character into a normal interword space. */
+ if (ISSPACE (text[this_char]))
+ width += font_space;
+ else
+ {
+ chars[this_char] = get_char (font_name, text[this_char]);
+
+ /* If the character doesn't exist in this font, just keep
+ going. */
+ if (chars[this_char] == NULL)
+ continue;
+
+ /* The set width should be equal to the left side bearing plus
+ the bitmap width plus the right side bearing. */
+ width += CHAR_SET_WIDTH (*chars[this_char]);
+ height = MAX (height, CHAR_HEIGHT (*chars[this_char]));
+ depth = MAX (depth, CHAR_DEPTH (*chars[this_char]));
+ }
+ }
+
+ /* Unless the image is nonnegative both horizontally and vertically,
+ it is invisible. */
+ if (width <= 0 || (height + depth + 1 <= 0))
+ {
+ BITMAP_WIDTH (b) = 0;
+ BITMAP_HEIGHT (b) = 0;
+ BITMAP_BITS (b) = NULL;
+ return b;
+ }
+
+ /* The image is going to be visible. */
+ b = new_bitmap ((dimensions_type) { height + depth + 1, width });
+
+ for (this_char = 0; this_char < strlen (text); this_char++)
+ {
+ if (ISSPACE (text[this_char]))
+ x += font_space;
+ else
+ {
+ int char_x, char_y;
+ char_info_type c;
+
+ if (chars[this_char] == NULL)
+ continue;
+
+ c = *chars[this_char];
+
+ x += CHAR_LSB (c);
+ x = MAX (x, 0); /* In case the lsb was negative. */
+
+ /* Copy the character image to the bitmap we are building, one
+ column at a time, from top to bottom. */
+ for (char_x = 0; char_x < CHAR_BITMAP_WIDTH (c); char_x++, x++)
+ for (char_y = 0, y = height - CHAR_HEIGHT (c);
+ char_y < CHAR_BITMAP_HEIGHT (c);
+ char_y++, y++)
+ BITMAP_PIXEL (b, y, x)
+ = BITMAP_PIXEL (CHAR_BITMAP (c), char_y, char_x);
+
+ x += CHAR_RSB (c);
+ }
+ }
+
+ close_font (font_name);
+
+ return b;
+}
diff --git a/lib/strstr.o b/lib/strstr.o
new file mode 100644
index 0000000..a882b08
--- /dev/null
+++ b/lib/strstr.o
Binary files differ
diff --git a/lib/substring.c b/lib/substring.c
new file mode 100644
index 0000000..8ef7174
--- /dev/null
+++ b/lib/substring.c
@@ -0,0 +1,50 @@
+/* substring.c: copy a chunk from a string.
+
+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"
+
+
+/* Return a fresh copy of SOURCE[START..LIMIT], or NULL if LIMIT<START.
+ If LIMIT>strlen(START), it is reassigned. */
+
+string
+substring (string source, const unsigned start, const unsigned limit)
+{
+ string result;
+ unsigned this_char;
+ unsigned length = strlen (source);
+ unsigned lim = limit;
+
+ /* Upper bound out of range? */
+ if (lim >= length)
+ lim = length - 1;
+
+ /* Null substring? */
+ if (start > limit)
+ return "";
+
+ /* The `2' here is one for the null and one for limit - start inclusive. */
+ result = xmalloc (limit - start + 2);
+
+ for (this_char = start; this_char <= limit; this_char++)
+ result[this_char - start] = source[this_char];
+
+ result[this_char - start] = 0;
+
+ return result;
+}
diff --git a/lib/varstring.c b/lib/varstring.c
new file mode 100644
index 0000000..0107abd
--- /dev/null
+++ b/lib/varstring.c
@@ -0,0 +1,97 @@
+/* varstring.c: variable-length strings.
+
+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 "varstring.h"
+
+
+/* You use variable-length stringsd by calling `init_string' first, then
+ assigning to particular elements via `set_string_element'. The string
+ will initially be `INITIAL_SIZE' characters, and be incremented in
+ blocks of size `INCREMENT_SIZE'. */
+
+#define INITIAL_SIZE 16
+#define INCREMENT_SIZE 64
+
+variable_string
+vs_init ()
+{
+ variable_string vs;
+
+ VS_CHARS (vs) = xmalloc (INITIAL_SIZE);
+ *VS_CHARS (vs) = 0;
+ VS_ALLOCATED (vs) = INITIAL_SIZE;
+ VS_USED (vs) = 0;
+
+ return vs;
+}
+
+
+/* Free the data we've allocated for VS. */
+
+void
+vs_free (variable_string *vs)
+{
+ free (VS_CHARS (*vs));
+ VS_CHARS (*vs) = NULL;
+}
+
+
+/* We do not put a NULL after we insert NEW_CHAR at the (zero-based)
+ index LOC. The caller is responsible for that. */
+
+void
+vs_set_char (variable_string *vs, unsigned loc, char new_char)
+{
+ /* Do we need more space? */
+ if (loc >= VS_ALLOCATED (*vs))
+ { /* Yes. Make sure to allocate enough. */
+ unsigned extra = MAX (INCREMENT_SIZE, loc - VS_ALLOCATED (*vs) + 1);
+ VS_CHARS (*vs) = xrealloc (VS_CHARS (*vs), VS_ALLOCATED (*vs) + extra);
+ VS_ALLOCATED (*vs) += extra;
+ }
+
+ VS_CHARS (*vs)[loc] = new_char;
+ VS_USED (*vs) = loc + 1;
+}
+
+
+/* Append NEW_CHAR to VS. */
+
+void
+vs_append_char (variable_string *vs, char new_char)
+{
+ vs_set_char (vs, VS_USED (*vs), new_char);
+}
+
+
+variable_string
+vs_concat (variable_string vs1, variable_string vs2)
+{
+ variable_string vs;
+ unsigned used = VS_USED (vs1) + VS_USED (vs2);
+
+ VS_CHARS (vs) = xmalloc (used + 1);
+ memcpy (VS_CHARS (vs), VS_CHARS (vs1), VS_USED (vs1));
+ memcpy (VS_CHARS (vs) + VS_USED (vs1), VS_CHARS (vs2), VS_USED (vs2));
+ VS_ALLOCATED (vs) = used + 1;
+ VS_USED (vs) = used;
+
+ return vs;
+}
diff --git a/lib/vector.c b/lib/vector.c
new file mode 100644
index 0000000..354af2d
--- /dev/null
+++ b/lib/vector.c
@@ -0,0 +1,272 @@
+/* vector.c: vector/point operations.
+
+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 "vector.h"
+
+
+/* Given the point COORD, return the corresponding vector. */
+
+const vector_type
+make_vector (const real_coordinate_type c)
+{
+ vector_type v;
+
+ v.dx = c.x;
+ v.dy = c.y;
+
+ return v;
+}
+
+
+/* And the converse: given a vector, return the corresponding point. */
+
+const real_coordinate_type
+vector_to_point (const vector_type v)
+{
+ real_coordinate_type coord;
+
+ coord.x = v.dx;
+ coord.y = v.dy;
+
+ return coord;
+}
+
+
+
+const real
+magnitude (const vector_type v)
+{
+ return hypot (v.dx, v.dy);
+}
+
+
+const vector_type
+normalize (const vector_type v)
+{
+ vector_type new_v;
+ real m = magnitude (v);
+
+ assert (m > 0.0);
+
+ new_v.dx = v.dx / m;
+ new_v.dy = v.dy / m;
+
+ return new_v;
+}
+
+
+const vector_type
+Vadd (const vector_type v1, const vector_type v2)
+{
+ vector_type new_v;
+
+ new_v.dx = v1.dx + v2.dx;
+ new_v.dy = v1.dy + v2.dy;
+
+ return new_v;
+}
+
+
+const real
+Vdot (const vector_type v1, const vector_type v2)
+{
+ return v1.dx * v2.dx + v1.dy * v2.dy;
+}
+
+
+const vector_type
+Vmult_scalar (const vector_type v, const real r)
+{
+ vector_type new_v;
+
+ new_v.dx = v.dx * r;
+ new_v.dy = v.dy * r;
+
+ return new_v;
+}
+
+
+/* Given the IN_VECTOR and OUT_VECTOR, return the angle between them in
+ degrees, in the range zero to 180. */
+
+const real
+Vangle (const vector_type in_vector, const vector_type out_vector)
+{
+ vector_type v1 = normalize (in_vector);
+ vector_type v2 = normalize (out_vector);
+
+ return acosd (Vdot (v2, v1));
+}
+
+
+const real_coordinate_type
+Vadd_point (const real_coordinate_type c, const vector_type v)
+{
+ real_coordinate_type new_c;
+
+ new_c.x = c.x + v.dx;
+ new_c.y = c.y + v.dy;
+ return new_c;
+}
+
+
+const real_coordinate_type
+Vsubtract_point (const real_coordinate_type c, const vector_type v)
+{
+ real_coordinate_type new_c;
+
+ new_c.x = c.x - v.dx;
+ new_c.y = c.y - v.dy;
+ return new_c;
+}
+
+
+const coordinate_type
+Vadd_int_point (const coordinate_type c, const vector_type v)
+{
+ coordinate_type a;
+
+ a.x = ROUND ((real) c.x + v.dx);
+ a.y = ROUND ((real) c.y + v.dy);
+ return a;
+}
+
+
+const vector_type
+Vabs (const vector_type v)
+{
+ vector_type new_v;
+
+ new_v.dx = fabs (v.dx);
+ new_v.dy = fabs (v.dy);
+ return new_v;
+}
+
+
+
+/* Operations on points. */
+
+/* This is a macro now. */
+#if 0
+const real_coordinate_type
+Padd (real_coordinate_type coord1, real_coordinate_type coord2)
+{
+ real_coordinate_type sum;
+
+ sum.x = coord1.x + coord2.x;
+ sum.y = coord1.y + coord2.y;
+
+ return sum;
+}
+
+
+const real_coordinate_type
+Pmult_scalar (const real_coordinate_type coord, const real r)
+{
+ real_coordinate_type answer;
+
+ answer.x = coord.x * r;
+ answer.y = coord.y * r;
+
+ return answer;
+}
+#endif /* 0 */
+
+
+const vector_type
+Psubtract (const real_coordinate_type c1, const real_coordinate_type c2)
+{
+ vector_type v;
+
+ v.dx = c1.x - c2.x;
+ v.dy = c1.y - c2.y;
+
+ return v;
+}
+
+
+
+/* Operations on integer points. */
+
+const vector_type
+IPsubtract (const coordinate_type coord1, const coordinate_type coord2)
+{
+ vector_type v;
+
+ v.dx = coord1.x - coord2.x;
+ v.dy = coord1.y - coord2.y;
+
+ return v;
+}
+
+
+const coordinate_type
+IPsubtractP (const coordinate_type c1, const coordinate_type c2)
+{
+ coordinate_type c;
+
+ c.x = c1.x - c2.x;
+ c.y = c1.y - c2.y;
+
+ return c;
+}
+
+
+const coordinate_type
+IPadd (const coordinate_type c1, const coordinate_type c2)
+{
+ coordinate_type c;
+
+ c.x = c1.x + c2.x;
+ c.y = c1.y + c2.y;
+
+ return c;
+}
+
+
+const coordinate_type
+IPmult_scalar (const coordinate_type c, const int i)
+{
+ coordinate_type a;
+
+ a.x = c.x * i;
+ a.y = c.y * i;
+
+ return a;
+}
+
+
+const real_coordinate_type
+IPmult_real (const coordinate_type c, const real r)
+{
+ real_coordinate_type a;
+
+ a.x = c.x * r;
+ a.y = c.y * r;
+
+ return a;
+}
+
+
+const boolean
+IPequal (const coordinate_type c1, const coordinate_type c2)
+{
+ return c1.x == c2.x && c1.y == c2.y;
+}
diff --git a/lib/xchdir.c b/lib/xchdir.c
new file mode 100644
index 0000000..9831663
--- /dev/null
+++ b/lib/xchdir.c
@@ -0,0 +1,29 @@
+/* xchdir.c: chdir with error checking.
+
+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 "dirio.h"
+
+
+void
+xchdir (string dirname)
+{
+ if (chdir (dirname) != 0)
+ FATAL_PERROR (dirname);
+}
diff --git a/lib/xfseek.o b/lib/xfseek.o
new file mode 100644
index 0000000..fc2e725
--- /dev/null
+++ b/lib/xfseek.o
Binary files differ
diff --git a/lib/xftell.o b/lib/xftell.o
new file mode 100644
index 0000000..0dfe6f8
--- /dev/null
+++ b/lib/xftell.o
Binary files differ
diff --git a/lib/xgetcwd.c b/lib/xgetcwd.c
new file mode 100644
index 0000000..8f3e4a9
--- /dev/null
+++ b/lib/xgetcwd.c
@@ -0,0 +1,104 @@
+/* xgetcwd.c: a from-scratch version of getwd. Based on the tcsh 5.20
+ source, apparently uncopyrighted.
+
+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 "c-pathmx.h"
+
+#include "dirio.h"
+#include "xstat.h"
+
+/* Return the pathname of the current directory, or give a fatal error. */
+
+string
+xgetcwd ()
+{
+ /* If the system provides getwd, use it. But don't use getcwd;
+ forking a process is even more expensive than all the stat calls we
+ make figuring out the cwd. */
+#ifdef GETWD_MISSING /* whole function */
+ struct stat root_stat, cwd_stat;
+ string cwd_path = xmalloc (1);
+
+ *cwd_path = 0;
+
+ /* Find the inodes of the root and current directories. */
+ root_stat = xstat ("/");
+ cwd_stat = xstat (".");
+
+ /* Go up the directory hierarchy until we get to root, prepending each
+ directory we pass through to `cwd_path'. */
+ while (!SAME_FILE_P (root_stat, cwd_stat))
+ {
+ struct dirent *e;
+ DIR *parent_dir;
+ boolean found = false;
+
+ xchdir ("..");
+ parent_dir = xopendir (".");
+
+ /* Look through the parent directory for the entry with the same
+ inode, so we can get its name. */
+ while ((e = readdir (parent_dir)) != NULL && !found)
+ {
+ struct stat test_stat = xlstat (e->d_name);
+
+ if (SAME_FILE_P (test_stat, cwd_stat))
+ {
+ /* We've found it. Prepend the pathname. */
+ string temp = cwd_path;
+ cwd_path = concat3 ("/", e->d_name, cwd_path);
+ free (temp);
+
+ /* Set up to test the next parent. */
+ cwd_stat = xstat (".");
+
+ /* Stop reading this directory. */
+ found = true;
+ }
+ }
+ if (!found)
+ FATAL2 ("No inode %d/device %d in parent directory",
+ cwd_stat.st_ino, cwd_stat.st_dev);
+
+ xclosedir (parent_dir);
+ }
+
+ /* If the current directory is the root, cwd_path will be the empty
+ string, and we will have not gone through the loop. */
+ if (*cwd_path == 0)
+ cwd_path = "/";
+ else
+ /* Go back to where we were. */
+ xchdir (cwd_path);
+
+ return cwd_path;
+
+#else /* not GETWD_MISSING */
+
+ string path = xmalloc (PATH_MAX + 1);
+
+ if (getwd (path) == 0)
+ {
+ fprintf (stderr, "getwd: %s", path);
+ exit (1);
+ }
+
+ return path;
+#endif /* not GETWD_MISSING */
+}
diff --git a/lib/xmessage.c b/lib/xmessage.c
new file mode 100644
index 0000000..1b8331a
--- /dev/null
+++ b/lib/xmessage.c
@@ -0,0 +1,101 @@
+/* xmessage.c: pop up a message for five seconds and then go away.
+
+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. */
+
+#ifndef X_DISPLAY_MISSING /* whole file */
+
+#include "config.h"
+
+#include "xt-common.h"
+#include <X11/Shell.h>
+#include <X11/Xaw/Label.h>
+
+#include "xmessage.h"
+
+static void message_over (XtPointer, XtIntervalId *);
+
+
+
+/* Make a popup child of the widget PARENT displaying the string S. We
+ pass the ARGS and N_ARGS parameters to the creation routine. */
+
+void
+x_message (Widget parent, string s, ArgList args, Cardinal n_args)
+{
+ Dimension parent_height;
+ Position popup_x, popup_y;
+ Widget popup;
+
+ XtAppContext app_con = XtWidgetToApplicationContext (parent);
+ Arg parent_args[]
+ = { { XtNheight, (XtArgVal) &parent_height },
+ };
+ Arg popup_args[]
+ = { { XtNx, 0 }, /* We assign to the position below. */
+ { XtNy, 0 },
+ { XtNgeometry, (XtArgVal) NULL }, /* Don't use parent's geometry. */
+ };
+
+ Arg default_args[] = { { XtNlabel, (XtArgVal) s } };
+ ArgList all_args
+ = XtMergeArgLists (args, n_args, default_args, XtNumber (default_args));
+
+ /* Put the message at the left edge of and about halfway down PARENT's
+ window. We pass the address of true Position variables rather
+ than the address of the Arg values; in the latter case, the
+ endianness of the computer determines which half of the word the
+ answers get stored in, which is clearly bad. */
+ XtGetValues (parent, parent_args, XtNumber (parent_args));
+ XtTranslateCoords (parent, 0, parent_height / 2, &popup_x, &popup_y);
+ popup_args[0].value = popup_x;
+ popup_args[1].value = popup_y;
+
+ popup = XtCreatePopupShell ("message shell", transientShellWidgetClass,
+ parent, popup_args, XtNumber (popup_args));
+
+ /* We can't use XtNumber on `all_args', since it's a pointer. */
+ (void)
+ XtCreateManagedWidget ("message", labelWidgetClass, popup, all_args,
+ n_args + XtNumber (default_args));
+
+ /* XtPopup realizes the window, etc. */
+ XtPopup (popup, XtGrabNone);
+
+ /* Leave the message there for five seconds. */
+ (void) XtAppAddTimeOut (app_con, 5000, message_over, popup);
+}
+
+
+/* Just a convenient interface to the above. */
+
+void
+x_warning (Widget parent, string s)
+{
+ x_message (parent, concat (s, "."), NULL, 0);
+}
+
+
+
+static void
+message_over (XtPointer client_data, XtIntervalId *interval_id)
+{
+ Widget popup = (Widget) client_data;
+
+ XtPopdown (popup);
+}
+
+#endif /* not X_DISPLAY_MISSING */
diff --git a/lib/xopendir.c b/lib/xopendir.c
new file mode 100644
index 0000000..02709ac
--- /dev/null
+++ b/lib/xopendir.c
@@ -0,0 +1,47 @@
+/* xopendir.c: opendir and closedir with error checking.
+
+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 "dirio.h"
+
+
+DIR *
+xopendir P1C(string, dirname)
+{
+ DIR *d = opendir (dirname);
+
+ if (d == NULL)
+ FATAL_PERROR (dirname);
+
+ return d;
+}
+
+
+void
+xclosedir P1C(DIR *, d)
+{
+#ifdef VOID_CLOSEDIR
+ closedir (d);
+#else
+ int ret = closedir (d);
+
+ if (ret != 0)
+ FATAL ("closedir failed");
+#endif
+}
diff --git a/lib/xrename.c b/lib/xrename.c
new file mode 100644
index 0000000..c840805
--- /dev/null
+++ b/lib/xrename.c
@@ -0,0 +1,44 @@
+/* xrename.c: conceptually rename with error checking.
+
+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"
+
+
+/* Copy FROM to TO, then unlink FROM. It would probably be faster to
+ read and write buffers, but the files we use this for aren't big
+ enough for it to make a substantial difference. */
+
+void
+xrename (string from, string to)
+{
+ int c;
+ FILE *input = xfopen (from, "r");
+ FILE *output = xfopen (to, "w");
+
+ while ((c = getc (input)) != EOF || !feof (input))
+ putc (c, output);
+
+ xfclose (input, from);
+ xfclose (output, to);
+
+ if (unlink (from) != 0)
+ {
+ fprintf (stderr, "warning: Could not unlink ");
+ perror (from);
+ }
+}
diff --git a/lib/xstrdup.c b/lib/xstrdup.c
new file mode 100644
index 0000000..3ce69e9
--- /dev/null
+++ b/lib/xstrdup.c
@@ -0,0 +1,29 @@
+/* xstrdup.c: strdup with error checking.
+
+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"
+
+
+/* Return a copy of S in new storage. */
+
+string
+xstrdup P1C(string, s)
+{
+ string new_string = (string) xmalloc (strlen (s) + 1);
+ return strcpy (new_string, s);
+}
diff --git a/pbm/ChangeLog b/pbm/ChangeLog
new file mode 100644
index 0000000..65afe89
--- /dev/null
+++ b/pbm/ChangeLog
@@ -0,0 +1,41 @@
+Sat Aug 7 11:51:41 1993 Karl Berry (karl@cs.umb.edu)
+
+ * libpbm1.c: c-ctype.h now in kpathsea.
+
+Fri Dec 11 15:06:54 1992 Karl Berry (karl@cs.umb.edu)
+
+ * libpbm1.c (pm_keymatch): Change ctype references to use
+ uppercase macros.
+
+Tue Oct 27 12:56:21 1992 Karl Berry (karl@cs.umb.edu)
+
+ * Version 0.6.
+
+Tue Sep 15 08:39:17 1992 Karl Berry (karl@hayley)
+
+ * libpbm1.c (malloc, free, exit): don't declare these, rely on
+ config.h.
+
+Thu Sep 3 09:31:14 1992 Karl Berry (karl@hayley)
+
+ * Version 0.5.
+
+Wed Apr 15 09:01:07 1992 Karl Berry (karl@hayley)
+
+ * pbmascii.c: new file for debugging.
+
+Sat Mar 28 07:49:22 1992 Karl Berry (karl at hayley)
+
+ * Version 0.4.
+
+ * Change copyright years to 1992 only.
+
+Sat Mar 7 10:00:47 1992 Karl Berry (karl at hayley)
+
+ * GNUmakefile (files, headers, sources): replace with `c_and_h', etc.
+
+ * libpbm1.c: use #if __STDC__, not #ifdef.
+
+Thu Mar 5 07:53:37 1992 Karl Berry (karl at hayley)
+
+ * Created.
diff --git a/pbm/GNUmakefile b/pbm/GNUmakefile
new file mode 100644
index 0000000..3d970e5
--- /dev/null
+++ b/pbm/GNUmakefile
@@ -0,0 +1,27 @@
+# Makefile for (part of) Jef Poskanzer's PBM library.
+#
+# 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.
+#
+library = pbm
+
+h_only = libpbm
+c_only = libpbm1 libpbm2 libpbm4
+
+include ../data/defs.make
+include ../data/defslib.make
+
+include M.depend
diff --git a/pbm/README b/pbm/README
new file mode 100644
index 0000000..f7e0f64
--- /dev/null
+++ b/pbm/README
@@ -0,0 +1,2 @@
+These are some of the files from Jef Poskanzer's PBM library. They are
+essentially unmodified.
diff --git a/pbm/libpbm.h b/pbm/libpbm.h
new file mode 100644
index 0000000..7b80f2f
--- /dev/null
+++ b/pbm/libpbm.h
@@ -0,0 +1,18 @@
+/* libpbm.h - internal header file for libpbm portable bitmap library
+*/
+
+#ifndef _LIBPBM_H_
+#define _LIBPBM_H_
+
+/* Here are some routines internal to the pbm library. */
+
+char pbm_getc ARGS(( FILE* file ));
+unsigned char pbm_getrawbyte ARGS(( FILE* file ));
+int pbm_getint ARGS(( FILE* file ));
+
+int pbm_readmagicnumber ARGS(( FILE* file ));
+
+void pbm_readpbminitrest ARGS(( FILE* file, int* colsP, int* rowsP ));
+
+#endif /*_LIBPBM_H_*/
+
diff --git a/pbm/libpbm1.c b/pbm/libpbm1.c
new file mode 100644
index 0000000..5b8258a
--- /dev/null
+++ b/pbm/libpbm1.c
@@ -0,0 +1,449 @@
+/* libpbm1.c - pbm utility library part 1
+**
+** Copyright (C) 1988 by Jef Poskanzer.
+**
+** Permission to use, copy, modify, and distribute this software and its
+** documentation for any purpose and without fee is hereby granted, provided
+** that the above copyright notice appear in all copies and that both that
+** copyright notice and this permission notice appear in supporting
+** documentation. This software is provided "as is" without express or
+** implied warranty.
+**
+** Minor configuration changes for GNU --karl.
+*/
+
+#include "pbm.h"
+#include "libpbm.h"
+
+#include <kpathsea/c-ctype.h>
+#include <varargs.h>
+
+#if 0 /* karl */
+extern char *malloc ();
+extern void free ();
+extern void exit ();
+#endif
+
+/* Variable-sized arrays. */
+
+char*
+pm_allocrow( cols, size )
+ int cols, size;
+ {
+ register char* itrow;
+
+ itrow = (char*) malloc( cols * size );
+ if ( itrow == (char*) 0 )
+ pm_error( "out of memory allocating a row", 0,0,0,0,0 );
+ return itrow;
+ }
+
+void
+pm_freerow( itrow )
+ char* itrow;
+ {
+ free( itrow );
+ }
+
+
+char**
+pm_allocarray( cols, rows, size )
+ int cols, rows;
+ int size;
+ {
+ char** its;
+ int i;
+
+ its = (char**) malloc( rows * sizeof(char*) );
+ if ( its == (char**) 0 )
+ pm_error( "out of memory allocating an array", 0,0,0,0,0 );
+ its[0] = (char*) malloc( rows * cols * size );
+ if ( its[0] == (char*) 0 )
+ pm_error( "out of memory allocating an array", 0,0,0,0,0 );
+ for ( i = 1; i < rows; ++i )
+ its[i] = &(its[0][i * cols * size]);
+ return its;
+ }
+
+void
+pm_freearray( its, rows )
+ char** its;
+ int rows;
+ {
+ free( its[0] );
+ free( its );
+ }
+
+
+/* Case-insensitive keyword matcher. */
+
+int
+pm_keymatch( str, keyword, minchars )
+ char* str;
+ char* keyword;
+ int minchars;
+ {
+ register int len;
+
+ len = strlen( str );
+ if ( len < minchars )
+ return 0;
+ while ( --len >= 0 )
+ {
+ register char c1, c2;
+
+ c1 = *str++;
+ c2 = *keyword++;
+ if ( c2 == '\0' )
+ return 0;
+ if ( ISUPPER( c1 ) )
+ c1 = TOLOWER( c1 );
+ if ( ISUPPER( c2 ) )
+ c1 = TOLOWER( c2 );
+ if ( c1 != c2 )
+ return 0;
+ }
+ return 1;
+ }
+
+
+/* Log base two hacks. */
+
+int
+pm_maxvaltobits( maxval )
+ int maxval;
+ {
+ if ( maxval <= 1 )
+ return 1;
+ else if ( maxval <= 3 )
+ return 2;
+ else if ( maxval <= 7 )
+ return 3;
+ else if ( maxval <= 15 )
+ return 4;
+ else if ( maxval <= 31 )
+ return 5;
+ else if ( maxval <= 63 )
+ return 6;
+ else if ( maxval <= 127 )
+ return 7;
+ else if ( maxval <= 255 )
+ return 8;
+ else if ( maxval <= 511 )
+ return 9;
+ else if ( maxval <= 1023 )
+ return 10;
+ else if ( maxval <= 2047 )
+ return 11;
+ else if ( maxval <= 4095 )
+ return 12;
+ else if ( maxval <= 8191 )
+ return 13;
+ else if ( maxval <= 16383 )
+ return 14;
+ else if ( maxval <= 32767 )
+ return 15;
+ else if ( maxval <= 65535 )
+ return 16;
+ else
+ pm_error( "maxval of %d is too large!", maxval, 0,0,0,0 );
+ return 0; /* Avoid dumb warning. */
+ }
+
+int
+pm_bitstomaxval( bits )
+ int bits;
+ {
+ return ( 1 << bits ) - 1;
+ }
+
+
+/* Initialization. */
+
+static char* pm_progname;
+
+void
+pm_init( argcP, argv )
+ int* argcP;
+ char* argv[];
+ {
+ pm_progname = rindex( argv[0], '/');
+ if ( pm_progname == NULL )
+ pm_progname = argv[0];
+ else
+ ++pm_progname;
+ }
+
+void
+pbm_init( argcP, argv )
+ int* argcP;
+ char* argv[];
+ {
+ pm_init( argcP, argv );
+ }
+
+/* Error handling. */
+
+/* I'd use varargs here, but it can't be done portably, because (a) vfprintf()
+** is not very widespread, and (b) varargs itself is not powerful enough to
+** allow me to include a portable vfprintf().
+**
+** So instead, we have the gross hack of a fixed number of args. It's not
+** even clear how portable this hack is, but it does seem to work everywhere
+** I've tried it.
+*/
+
+void
+pm_message( fmt, v1, v2, v3, v4, v5 )
+ char* fmt;
+ char *v1, *v2, *v3, *v4, *v5;
+ {
+ fprintf( stderr, "%s: ", pm_progname );
+ fprintf( stderr, fmt, v1, v2, v3, v4, v5 );
+ fputc( '\n', stderr );
+ }
+
+void
+pm_error( fmt, v1, v2, v3, v4, v5 )
+ char* fmt;
+ char *v1, *v2, *v3, *v4, *v5;
+ {
+ pm_message( fmt, v1, v2, v3, v4, v5 );
+ exit( 1 );
+ }
+
+void
+pm_perror( reason )
+ char* reason;
+ {
+ extern char* sys_errlist[];
+ extern int errno;
+ char* e;
+
+ e = sys_errlist[errno];
+
+ if ( reason != 0 && reason[0] != '\0' )
+ pm_error( "%s - %s", reason, e, 0,0,0 );
+ else
+ pm_error( "%s", e, 0,0,0,0 );
+ }
+
+void
+pm_usage( usage )
+ char* usage;
+ {
+ fprintf( stderr, "usage: %s %s\n", pm_progname, usage );
+ exit( 1 );
+ }
+
+
+/* File open/close that handles "-" as stdin and checks errors. */
+
+FILE*
+pm_openr( name )
+ char* name;
+ {
+ FILE* f;
+
+ if ( strcmp( name, "-" ) == 0 )
+ f = stdin;
+ else
+ {
+#ifdef MSDOS
+ f = fopen( name, "rb" );
+#else /*MSDOS*/
+ f = fopen( name, "r" );
+#endif /*MSDOS*/
+ if ( f == NULL )
+ {
+ pm_perror( name );
+ exit( 1 );
+ }
+ }
+ return f;
+ }
+
+FILE*
+pm_openw( name )
+ char* name;
+ {
+ FILE* f;
+
+#ifdef MSDOS
+ f = fopen( name, "wb" );
+#else /*MSDOS*/
+ f = fopen( name, "w" );
+#endif /*MSDOS*/
+ if ( f == NULL )
+ {
+ pm_perror( name );
+ exit( 1 );
+ }
+ return f;
+ }
+
+void
+pm_close( f )
+ FILE* f;
+ {
+ if ( f != stdin )
+ if ( fclose( f ) != 0 )
+ pm_perror( "fclose" );
+ }
+
+/* Broken putc() fix. */
+
+#ifdef PBMPLUS_BROKENPUTC2
+int
+putc( c, stream )
+ char c;
+ FILE* stream;
+ {
+ return fwrite( &c, 1, 1, stream ) == 1 ? c : EOF;
+ }
+#endif /*PBMPLUS_BROKENPUTC2*/
+
+/* Endian I/O.
+*/
+
+int
+pm_readbigshort( in, sP )
+ FILE* in;
+ short* sP;
+ {
+ int c;
+
+ if ( (c = getc( in )) == EOF )
+ return -1;
+ *sP = ( c & 0xff ) << 8;
+ if ( (c = getc( in )) == EOF )
+ return -1;
+ *sP |= c & 0xff;
+ return 0;
+ }
+
+#if __STDC__
+int
+pm_writebigshort( FILE* out, short s )
+#else /*not __STDC__*/
+int
+pm_writebigshort( out, s )
+ FILE* out;
+ short s;
+#endif /*not __STDC__*/
+ {
+ if ( putc( ( s >> 8 ) & 0xff, out ) == EOF )
+ return -1;
+ if ( putc( s & 0xff, out ) == EOF )
+ return -1;
+ return 0;
+ }
+
+int
+pm_readbiglong( in, lP )
+ FILE* in;
+ long* lP;
+ {
+ int c;
+
+ if ( (c = getc( in )) == EOF )
+ return -1;
+ *lP = ( c & 0xff ) << 24;
+ if ( (c = getc( in )) == EOF )
+ return -1;
+ *lP |= ( c & 0xff ) << 16;
+ if ( (c = getc( in )) == EOF )
+ return -1;
+ *lP |= ( c & 0xff ) << 8;
+ if ( (c = getc( in )) == EOF )
+ return -1;
+ *lP |= c & 0xff;
+ return 0;
+ }
+
+int
+pm_writebiglong( out, l )
+ FILE* out;
+ long l;
+ {
+ if ( putc( ( l >> 24 ) & 0xff, out ) == EOF )
+ return -1;
+ if ( putc( ( l >> 16 ) & 0xff, out ) == EOF )
+ return -1;
+ if ( putc( ( l >> 8 ) & 0xff, out ) == EOF )
+ return -1;
+ if ( putc( l & 0xff, out ) == EOF )
+ return -1;
+ return 0;
+ }
+
+int
+pm_readlittleshort( in, sP )
+ FILE* in;
+ short* sP;
+ {
+ int c;
+
+ if ( (c = getc( in )) == EOF )
+ return -1;
+ *sP = c & 0xff;
+ if ( (c = getc( in )) == EOF )
+ return -1;
+ *sP |= ( c & 0xff ) << 8;
+ return 0;
+ }
+
+#if __STDC__
+int
+pm_writelittleshort( FILE* out, short s )
+#else /*not __STDC__*/
+int
+pm_writelittleshort( out, s )
+ FILE* out;
+ short s;
+#endif /*not __STDC__*/
+ {
+ if ( putc( s & 0xff, out ) == EOF )
+ return -1;
+ if ( putc( ( s >> 8 ) & 0xff, out ) == EOF )
+ return -1;
+ return 0;
+ }
+
+int
+pm_readlittlelong( in, lP )
+ FILE* in;
+ long* lP;
+ {
+ int c;
+
+ if ( (c = getc( in )) == EOF )
+ return -1;
+ *lP = c & 0xff;
+ if ( (c = getc( in )) == EOF )
+ return -1;
+ *lP |= ( c & 0xff ) << 8;
+ if ( (c = getc( in )) == EOF )
+ return -1;
+ *lP |= ( c & 0xff ) << 16;
+ if ( (c = getc( in )) == EOF )
+ return -1;
+ *lP |= ( c & 0xff ) << 24;
+ return 0;
+ }
+
+int
+pm_writelittlelong( out, l )
+ FILE* out;
+ long l;
+ {
+ if ( putc( l & 0xff, out ) == EOF )
+ return -1;
+ if ( putc( ( l >> 8 ) & 0xff, out ) == EOF )
+ return -1;
+ if ( putc( ( l >> 16 ) & 0xff, out ) == EOF )
+ return -1;
+ if ( putc( ( l >> 24 ) & 0xff, out ) == EOF )
+ return -1;
+ return 0;
+ }
diff --git a/pbm/libpbm2.c b/pbm/libpbm2.c
new file mode 100644
index 0000000..afae0dc
--- /dev/null
+++ b/pbm/libpbm2.c
@@ -0,0 +1,134 @@
+/* libpbm2.c - pbm utility library part 2
+**
+** Copyright (C) 1988 by Jef Poskanzer.
+**
+** Permission to use, copy, modify, and distribute this software and its
+** documentation for any purpose and without fee is hereby granted, provided
+** that the above copyright notice appear in all copies and that both that
+** copyright notice and this permission notice appear in supporting
+** documentation. This software is provided "as is" without express or
+** implied warranty.
+*/
+
+#include "pbmplus.h"
+#include "pbm.h"
+#include "libpbm.h"
+
+static bit
+pbm_getbit( file )
+ FILE* file;
+ {
+ register char ch;
+
+ do
+ {
+ ch = pbm_getc( file );
+ }
+ while ( ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' );
+
+ if ( ch != '0' && ch != '1' )
+ pm_error( "junk in file where bits should be", 0,0,0,0,0 );
+
+ return ( ch == '1' ) ? 1 : 0;
+ }
+
+int
+pbm_readmagicnumber( file )
+ FILE* file;
+ {
+ int ich1, ich2;
+
+ ich1 = getc( file );
+ if ( ich1 == EOF )
+ pm_error( "EOF / read error reading magic number", 0,0,0,0,0 );
+ ich2 = getc( file );
+ if ( ich2 == EOF )
+ pm_error( "EOF / read error reading magic number", 0,0,0,0,0 );
+ return ich1 * 256 + ich2;
+ }
+
+void
+pbm_readpbminitrest( file, colsP, rowsP )
+ FILE* file;
+ int* colsP;
+ int* rowsP;
+ {
+ /* Read size. */
+ *colsP = pbm_getint( file );
+ *rowsP = pbm_getint( file );
+ }
+
+void
+pbm_readpbminit( file, colsP, rowsP, formatP )
+ FILE* file;
+ int* colsP;
+ int* rowsP;
+ int* formatP;
+ {
+ /* Check magic number. */
+ *formatP = pbm_readmagicnumber( file );
+ switch ( PBM_FORMAT_TYPE(*formatP) )
+ {
+ case PBM_TYPE:
+ pbm_readpbminitrest( file, colsP, rowsP );
+ break;
+
+ default:
+ pm_error( "bad magic number - not a pbm file", 0,0,0,0,0 );
+ }
+ }
+
+void
+pbm_readpbmrow( file, bitrow, cols, format )
+ FILE* file;
+ bit* bitrow;
+ int cols, format;
+ {
+ register int col, bitshift;
+ register unsigned char item;
+ register bit* bP;
+
+ switch ( format )
+ {
+ case PBM_FORMAT:
+ for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
+ *bP = pbm_getbit( file );
+ break;
+
+ case RPBM_FORMAT:
+ bitshift = -1;
+ for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
+ {
+ if ( bitshift == -1 )
+ {
+ item = pbm_getrawbyte( file );
+ bitshift = 7;
+ }
+ *bP = ( item >> bitshift ) & 1;
+ --bitshift;
+ }
+ break;
+
+ default:
+ pm_error( "can't happen", 0,0,0,0,0 );
+ }
+ }
+
+bit**
+pbm_readpbm( file, colsP, rowsP )
+ FILE* file;
+ int* colsP;
+ int* rowsP;
+ {
+ register bit** bits;
+ int format, row;
+
+ pbm_readpbminit( file, colsP, rowsP, &format );
+
+ bits = pbm_allocarray( *colsP, *rowsP );
+
+ for ( row = 0; row < *rowsP; ++row )
+ pbm_readpbmrow( file, bits[row], *colsP, format );
+
+ return bits;
+ }
diff --git a/pbm/libpbm4.c b/pbm/libpbm4.c
new file mode 100644
index 0000000..7a74424
--- /dev/null
+++ b/pbm/libpbm4.c
@@ -0,0 +1,80 @@
+/* libpbm4.c - pbm utility library part 4
+**
+** Copyright (C) 1988 by Jef Poskanzer.
+**
+** Permission to use, copy, modify, and distribute this software and its
+** documentation for any purpose and without fee is hereby granted, provided
+** that the above copyright notice appear in all copies and that both that
+** copyright notice and this permission notice appear in supporting
+** documentation. This software is provided "as is" without express or
+** implied warranty.
+*/
+
+#include "pbm.h"
+#include "libpbm.h"
+
+char
+pbm_getc( file )
+ FILE* file;
+ {
+ register int ich;
+ register char ch;
+
+ ich = getc( file );
+ if ( ich == EOF )
+ pm_error( "EOF / read error", 0,0,0,0,0 );
+ ch = (char) ich;
+
+ if ( ch == '#' )
+ {
+ do
+ {
+ ich = getc( file );
+ if ( ich == EOF )
+ pm_error( "EOF / read error", 0,0,0,0,0 );
+ ch = (char) ich;
+ }
+ while ( ch != '\n' );
+ }
+
+ return ch;
+ }
+
+unsigned char
+pbm_getrawbyte( file )
+ FILE* file;
+ {
+ register int iby;
+
+ iby = getc( file );
+ if ( iby == EOF )
+ pm_error( "EOF / read error", 0,0,0,0,0 );
+ return (unsigned char) iby;
+ }
+
+int
+pbm_getint( file )
+ FILE* file;
+ {
+ register char ch;
+ register int i;
+
+ do
+ {
+ ch = pbm_getc( file );
+ }
+ while ( ch == ' ' || ch == '\t' || ch == '\n' );
+
+ if ( ch < '0' || ch > '9' )
+ pm_error( "junk in file where an integer should be", 0,0,0,0,0 );
+
+ i = 0;
+ do
+ {
+ i = i * 10 + ch - '0';
+ ch = pbm_getc( file );
+ }
+ while ( ch >= '0' && ch <= '9' );
+
+ return i;
+ }
diff --git a/pbm/pbmascii b/pbm/pbmascii
new file mode 100755
index 0000000..ffa329c
--- /dev/null
+++ b/pbm/pbmascii
Binary files differ
diff --git a/pbm/pbmascii.c b/pbm/pbmascii.c
new file mode 100644
index 0000000..945190e
--- /dev/null
+++ b/pbm/pbmascii.c
@@ -0,0 +1,37 @@
+/* pbmascii -- dump a PBM file (from stdin) on stdout. */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main (int argc, char *argv[])
+{
+ int width, height, format;
+ unsigned row;
+ unsigned char *image_row;
+
+ pbm_readpbminit (stdin, &width, &height, &format);
+
+ image_row = malloc (width);
+
+ for (row = 0; row < height; row++)
+ {
+ int c;
+
+ pbm_readpbmrow (stdin, image_row, width, format);
+
+ printf ("%5d:", row);
+ for (c = 0; c < width; c++)
+ putchar (image_row[c] ? '*' : ' ');
+ putchar ('\n');
+ }
+
+ return 0;
+}
+
+
+/*
+Local variables:
+compile-command: "gcc -g -posix -o pbmascii pbmascii.c pbm.a"
+End:
+*/
diff --git a/pk/ChangeLog b/pk/ChangeLog
new file mode 100644
index 0000000..9ee8f4d
--- /dev/null
+++ b/pk/ChangeLog
@@ -0,0 +1,138 @@
+Tue Oct 27 12:56:27 1992 Karl Berry (karl@cs.umb.edu)
+
+ * Version 0.6.
+
+Thu Sep 3 09:31:18 1992 Karl Berry (karl@hayley)
+
+ * Version 0.5.
+
+Sat Jun 13 11:45:30 1992 Karl Berry (karl@hayley)
+
+ * pk_input.c: change for new names of list fns.
+
+Sat Mar 28 07:49:27 1992 Karl Berry (karl at hayley)
+
+ * Version 0.4.
+
+ * Change copyright years to 1992 only.
+
+Sat Mar 7 14:07:52 1992 Karl Berry (karl at fosse)
+
+ * pk_input.c: complete prototypes for static fns.
+
+Sat Mar 7 11:16:20 1992 Karl Berry (karl at hayley)
+
+ * GNUmakefile (files, headers, sources): replace with `c_and_h', etc.
+
+Thu Jan 9 08:29:21 1992 Karl Berry (karl at hayley)
+
+ * *.c: do not include global.h.
+
+ * *.h: remove #pragma once.
+
+Wed Jan 8 15:05:33 1992 Karl Berry (karl at hayley)
+
+ * update copyright messages.
+
+ * change `allocate to `xmalloc', `reallocate' to `xrealloc', and
+ `string_copy' to `strdup'.
+
+Tue Jul 30 13:19:47 1991 Karl Berry (karl at ra.cs.umb.edu)
+
+ * Version 0.3.
+
+Sat Jun 15 09:53:33 1991 Karl Berry (karl at hayley)
+
+ * all files: change `checked_' to `x'.
+
+Thu Jun 6 07:31:28 1991 Karl Berry (karl at hayley)
+
+ * All files: change to version 2 of the GPL.
+
+Thu Mar 7 07:33:24 1991 Karl Berry (karl at hayley)
+
+ * Version 0.2.
+
+Mon Mar 4 15:00:02 1991 Karl Berry (karl at hayley)
+
+ * pk_input.c: doc fix.
+
+Mon Feb 25 16:04:52 1991 Karl Berry (karl at hayley)
+
+ * pk_input.c: use `pk_...' instead of `..._pk_...'.
+
+Sun Feb 17 09:48:32 1991 Karl Berry (karl at hayley)
+
+ * pk_input.c: include config.h.
+
+Sat Nov 17 12:52:59 1990 Karl Berry (karl at hayley)
+
+ * pk_input.c: include appropriate file-...h files.
+
+Sat Sep 29 09:01:25 1990 Karl Berry (karl at hayley)
+
+ * pk_input.c (find_internal_font): return null at the end.
+
+Sun Sep 9 12:37:53 1990 Karl Berry (karl at hayley)
+
+ * pk_input.c (pk_get_string): append a trailing null to the
+ string.
+
+Wed Aug 29 14:23:26 1990 Karl Berry (karl at hayley)
+
+ * pk_input.c (pk_get_byte, ...): add the filename argument, and
+ rewrite as macros.
+
+Sat Aug 25 13:42:42 1990 Karl Berry (karl at hayley)
+
+ * pk_input.c (get_bitmap): ignore bits remaining in the last byte.
+
+Wed May 30 15:32:37 1990 Karl Berry (karl at hayley)
+
+ * pk_input.c (get_one_pk_char): give a better error message if the
+ character code is out of range; allow for it to be negative.
+
+Wed May 2 12:14:57 1990 Karl Berry (karl at claude)
+
+ * pk_input.c (delete_internal_font): new routine.
+ (close_pk_input_file): call it, instead of doing the work here.
+
+Sun Apr 22 07:04:07 1990 Karl Berry (karl at hayley)
+
+ * pk_input.c (unpack): off by one in calculation of the minimum row.
+
+Tue Apr 17 07:17:33 1990 Karl Berry (karl at hayley)
+
+ * pk_input.c (pk_get_two): new routine.
+ (get_one_pk_char): call it to get the packet length in the
+ extended short format.
+
+ * pk_input.c (unpack): get the h and v_offset values as signed
+ numbers.
+
+ * pk_input.c: make `do_upper_nybble' visible to the file, so that
+ we can set it to true before reading each character.
+
+Mon Apr 16 16:53:36 1990 Karl Berry (karl at hayley)
+
+ * pk_input.c (get_packed_bitmap): don't overwrite the repeat count
+ for a row on a subsequent run count.
+
+ * pk_input.c (get_run_count): forgot to initialize *repeat_count
+ to zero, and to only look for it once.
+
+ * pk_input.c (data_get_nybble): returned the upper nybble when we
+ wanted the lower, and vice versa.
+
+ * pk_input.c (get_one_pk_char): tested wrong bit to see which
+ preamble format we were supposed to read.
+
+ * pk_input.c (get_one_pk_char): allocate the space for each packed
+ character before we fill it in.
+
+ * pk_input.c (get_one_pk_char): the flag byte has already been
+ read; get it as a parameter, not by reading it from the file.
+
+ * pk_input.c (get_all_pk_chars): test for a non-command first,
+ since that is so common. And give a fatal error if we hit a
+ command that isn't undefined.
diff --git a/pk/GNUmakefile b/pk/GNUmakefile
new file mode 100644
index 0000000..2845c19
--- /dev/null
+++ b/pk/GNUmakefile
@@ -0,0 +1,26 @@
+# Makefile for the PK library.
+#
+# 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.
+#
+library = pk
+
+c_only = pk_input
+
+include ../data/defs.make
+include ../data/defslib.make
+
+include M.depend
diff --git a/pk/README b/pk/README
new file mode 100644
index 0000000..6677bca
--- /dev/null
+++ b/pk/README
@@ -0,0 +1,13 @@
+This library provides for reading of packed font (PK) bitmap files. An
+arbitrary number of fonts may be read simultaneously. Routines to write
+a PK file have not been written; instead, use the TeX utility routine
+gftopk.
+
+None of the code that processes the PK commands actually explains what
+the precise definition of those commands are. For that, you should look
+at the definition of the PK format in the TeX utility programs that
+convert to and from PK format.
+
+The header file is ../include/pk.h. It explains the basics of how to
+use the routines. The source files in this directory do not repeat that
+explanation.
diff --git a/pk/pk_input.c b/pk/pk_input.c
new file mode 100644
index 0000000..de5599e
--- /dev/null
+++ b/pk/pk_input.c
@@ -0,0 +1,729 @@
+/* pk_input.c: read from any number of PK files. The basic idea is to
+ read the entire file into memory the first time the client asks for a
+ character. Since PK files tend to be quite small, this does not use
+ an enormous amount of memory. But we only bother to unpack a
+ character's bitmap when the client asks for that particular
+ character.
+
+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 "file-input.h"
+#include "list.h"
+#include "pk.h"
+#include "pk_opcodes.h"
+
+
+/* The `packed_char_type' structure holds the character description,
+ taken directly from the input file, before it is unpacked into a
+ bitmap. This type is only used as part of the `internal_font_type'
+ structure, above. (In contrast, the `pk_char_type' structure holds
+ the unpacked information, in the form convenient for clients.) */
+
+typedef struct
+{
+ unsigned dyn_f : 4;
+ unsigned black_first : 1;
+ unsigned parameter_length : 3;
+ unsigned packet_length;
+ one_byte *data;
+} packed_char_type;
+
+/* This is the number of one-nybble run counts. It is at most 14. */
+#define PACKED_DYN_F(c) ((c).dyn_f)
+
+/* This says whether the first run count is black or white. */
+#define PACKED_BLACK_FIRST(c) ((c).black_first)
+
+/* This says how long the size parameters in the character preamble are.
+ It is either 1, 2, or 4. Either 1 or 2 means we're using a ``short
+ format''; 4 means we're using the ``long format''. */
+#define PACKED_PARAM_LENGTH(c) ((c).parameter_length)
+#define LONG_FORMAT(c) (PACKED_PARAM_LENGTH (c) == 4)
+
+/* This is the length of the packed character data, in bytes. */
+#define PACKED_DATA_LENGTH(c) ((c).packet_length)
+
+/* And the packed data, as an array of `packet_length' bytes. */
+#define PACKED_DATA(c) ((c).data)
+
+
+/* We save an instance of this structure for each font we are asked to
+ open. */
+
+typedef struct
+{
+ FILE *file;
+ pk_char_type *chars[MAX_CHARCODE + 1];
+ packed_char_type *packed_chars[MAX_CHARCODE + 1];
+ boolean chars_read;
+} internal_font_type;
+
+/* The file pointer for the font F. */
+#define INTERNAL_FILE(f) ((f).file)
+
+/* This pointer is null if the character C in the internal font F has
+ not yet been unpacked. */
+#define INTERNAL_PK_CHAR(f, c) ((f).chars[c])
+
+/* This pointer is null if the character C does not exist in F. */
+#define INTERNAL_PACKED_CHAR(f, c) ((f).packed_chars[c])
+
+/* This remembers whether we have read the character info from the file. */
+#define INTERNAL_CHARS_READ(f) ((f).chars_read)
+
+
+/* These macros get at the members of the packed character numbered C,
+ in the internal font F. */
+
+#define INTERNAL_PACKED_DYN_F(f, c) \
+ PACKED_DYN_F (*INTERNAL_PACKED_CHAR (f, c))
+#define INTERNAL_PACKED_BLACK_FIRST(f, c) \
+ PACKED_BLACK_FIRST (*INTERNAL_PACKED_CHAR (f, c))
+#define INTERNAL_PACKED_PARAM_LENGTH(f, c) \
+ PACKED_PARAM_LENGTH (*INTERNAL_PACKED_CHAR (f, c))
+#define INTERNAL_PACKED_DATA_LENGTH(f, c) \
+ PACKED_DATA_LENGTH (*INTERNAL_PACKED_CHAR (f, c))
+#define INTERNAL_PACKED_DATA(f, c) \
+ PACKED_DATA (*INTERNAL_PACKED_CHAR (f, c))
+
+/* File I/O. */
+static FILE *pk_input_file; /* The file we're currently reading. */
+static string current_filename; /* Its pathname. */
+
+/* Low-level input. These macros call the corresponding routines in
+ kbase, using the static variables for the input file and filename. */
+
+#define PK_MATCH_BYTE(expected) \
+ match_byte (expected, pk_input_file, current_filename)
+#define PK_GET_BYTE() get_byte (pk_input_file, current_filename)
+#define PK_GET_TWO() get_two (pk_input_file, current_filename)
+#define PK_GET_FOUR() get_four (pk_input_file, current_filename)
+#define PK_GET_N_BYTES(n) get_n_bytes (n, pk_input_file, current_filename)
+
+static four_bytes pk_get_n_byte_value (unsigned);
+static string pk_get_string (unsigned);
+
+static void get_all_pk_chars (internal_font_type *);
+static void get_one_pk_char (internal_font_type *, one_byte);
+
+/* Memory ``I/O''. */
+static pk_char_type *unpack (packed_char_type);
+static void get_bitmap (pk_char_type *);
+static void get_packed_bitmap (pk_char_type *, packed_char_type);
+static unsigned get_run_count (one_byte, unsigned *);
+
+static one_byte *pk_input_data = NULL; /* Where we are reading from. */
+static boolean do_upper_nybble = true; /* Which nybble we're reading. */
+
+static one_byte data_get_bit (void);
+static one_byte data_get_nybble (void);
+static four_bytes data_get_three (void);
+static four_bytes data_get_four (void);
+static four_bytes data_get_n_byte_value (one_byte);
+static signed_4_bytes data_get_signed_n_byte_value (one_byte);
+
+
+/* Handle multiple fonts. */
+static internal_font_type *find_internal_font (string);
+static void save_internal_font (string, FILE *);
+static void delete_internal_font (string);
+
+/* Prepare for reading FILENAME. Return false if it can't be opened.
+ We allow the same file to be opened twice; I'm not sure if that's a
+ good idea or not, but it doesn't seem to matter much. */
+
+boolean
+pk_open_input_file (string filename)
+{
+ FILE *f = fopen (filename, "r");
+
+ if (f == NULL) return false;
+
+ save_internal_font (filename, f);
+ return true;
+}
+
+
+/* Close the file associated with FILENAME, if we have it open. If it's
+ not open, the caller must have made a mistake, so
+ `delete_internal_font' gives a fatal error. */
+
+void
+pk_close_input_file (string filename)
+{
+ delete_internal_font (filename);
+}
+
+/* The PK preamble contains the fontwide information we are supposed to
+ return. If FONT_NAME isn't open for reading, we give a fatal error. */
+
+pk_preamble_type
+pk_get_preamble (string filename)
+{
+ pk_preamble_type p;
+ unsigned comment_length;
+ internal_font_type *f = find_internal_font (filename);
+
+ assert (INTERNAL_FILE (*f) != NULL);
+ pk_input_file = INTERNAL_FILE (*f);
+ current_filename = filename;
+
+ /* The preamble is at the beginning of the file, so move there. */
+ xfseek (pk_input_file, 0, SEEK_SET, filename);
+
+ PK_MATCH_BYTE (PK_PRE);
+ PK_MATCH_BYTE (PK_ID);
+ comment_length = PK_GET_BYTE ();
+ PK_COMMENT (p) = pk_get_string (comment_length);
+ PK_DESIGN_SIZE (p) = PK_GET_FOUR ();
+ PK_CHECKSUM (p) = PK_GET_FOUR ();
+ PK_H_RESOLUTION (p) = PK_GET_FOUR ();
+ PK_V_RESOLUTION (p) = PK_GET_FOUR ();
+
+ /* We read (but not unpack) the entire file. */
+ get_all_pk_chars (f);
+
+ return p;
+}
+
+/* Return the information for the character CODE in the font FILENAME,
+ or null if the character doesn't exist in that font. */
+
+pk_char_type *
+pk_get_char (one_byte code, string filename)
+{
+ internal_font_type *f = find_internal_font (filename);
+
+ assert (INTERNAL_FILE (*f) != NULL);
+ pk_input_file = INTERNAL_FILE (*f);
+ current_filename = filename;
+
+ if (!INTERNAL_CHARS_READ (*f))
+ /* This routine sets the character info in F (among other things). */
+ get_all_pk_chars (f);
+
+ /* The PK_CHAR is null until we unpack the bitmap. If the character
+ is not in the font at all, then the PACKED_CHAR is null. */
+ if (INTERNAL_PK_CHAR (*f, code) != NULL)
+ /* We've already unpacked this character. */
+ return INTERNAL_PK_CHAR (*f, code);
+
+ else if (INTERNAL_PACKED_CHAR (*f, code) == NULL)
+ /* The character is not in the font. */
+ return NULL;
+
+ else
+ { /* We need to unpack the character. */
+ INTERNAL_PK_CHAR (*f, code) = unpack (*INTERNAL_PACKED_CHAR (*f, code));
+ PK_CHARCODE (*INTERNAL_PK_CHAR (*f, code)) = code;
+ return INTERNAL_PK_CHAR (*f, code);
+ }
+}
+
+
+/* This routine reads the contents of the entire `pk_input_file' (which
+ should be set before calling it). The results go into F. */
+
+static void
+get_all_pk_chars (internal_font_type *f)
+{
+ while (true) /* The loop exits when we see PK_POST. */
+ {
+ one_byte command = PK_GET_BYTE ();
+
+ if (command < PK_XXX1)
+ get_one_pk_char (f, command);
+
+ else if (PK_XXX1 <= command && command <= PK_XXX4)
+ /* The length of the string is given by the next 1--4 bytes,
+ according to the opcode. We just ignore all specials. */
+ (void) PK_GET_N_BYTES (pk_get_n_byte_value (command - PK_XXX1 + 1));
+
+ else if (command == PK_YYY)
+ (void) PK_GET_FOUR ();
+
+ else if (command == PK_POST)
+ break;
+
+ else if (command == PK_NO_OP)
+ /* do nothing */;
+
+ else
+ FATAL1 ("Undefined command byte %u in PK file", command);
+ }
+
+ INTERNAL_CHARS_READ (*f) = true;
+}
+
+
+/* Read a single character, starting at the current position of
+ `pk_input_file'. The results go into F. */
+
+static void
+get_one_pk_char (internal_font_type *f, one_byte flag)
+{
+ unsigned parameter_length, packet_length;
+ int charcode;
+ one_byte dyn_f = flag >> 4;
+
+ if (dyn_f == 15)
+ FATAL1 ("Unrecognized command %u", flag);
+
+ if (!(flag & 4))
+ { /* Short format. */
+ parameter_length = 1;
+ packet_length = ((flag & 3) << 8) + PK_GET_BYTE ();
+ charcode = PK_GET_BYTE ();
+ }
+ else if (!(flag & 1))
+ { /* Extended short format. */
+ parameter_length = 2;
+ packet_length = ((flag & 3) << 16) + PK_GET_TWO ();
+ charcode = PK_GET_BYTE ();
+ }
+ else
+ { /* Long format. */
+ parameter_length = 4;
+ packet_length = PK_GET_FOUR ();
+ charcode = PK_GET_FOUR ();
+ if (charcode > MAX_CHARCODE || charcode < 0)
+ /* Someone is trying to use a font with character codes that are
+ out of our range. */
+ FATAL1 ("Character code %d out of range 0..255 in PK file (sorry)",
+ charcode);
+ }
+
+ INTERNAL_PACKED_CHAR (*f, charcode) = xmalloc (sizeof (packed_char_type));
+ INTERNAL_PACKED_DYN_F (*f, charcode) = dyn_f;
+ INTERNAL_PACKED_BLACK_FIRST (*f, charcode) = (flag & 8) != 0;
+ INTERNAL_PACKED_PARAM_LENGTH (*f, charcode) = parameter_length;
+ INTERNAL_PACKED_DATA_LENGTH (*f, charcode) = packet_length;
+ INTERNAL_PACKED_DATA (*f, charcode)
+ = (one_byte *) PK_GET_N_BYTES (packet_length);
+}
+
+
+/* This routine unpacks a character C into the raster image. All the
+ fields but one in the `pk_char_type' structure are filled in. The
+ exception is the character code, which our caller does. */
+
+static pk_char_type *
+unpack (packed_char_type c)
+{
+ dimensions_type d;
+ signed_4_bytes h_offset, v_offset;
+ pk_char_type *pk_char = xmalloc (sizeof (pk_char_type));
+
+ /* So it doesn't have to be a parameter to all the routines. */
+ pk_input_data = PACKED_DATA (c);
+ do_upper_nybble = true; /* The data always starts on a byte boundary. */
+
+ /* The TFM width is three bytes in the short formats, four in the
+ long format. */
+ PK_TFM_WIDTH (*pk_char)
+ = LONG_FORMAT (c) ? data_get_four () : data_get_three ();
+
+ /* The horizontal escapement is the next PARAMETER_LENGTH bytes. In
+ addition, if we're using the long format, it is in pixels
+ multiplied by 2^16, and we want to unscale it. */
+ PK_H_ESCAPEMENT (*pk_char)
+ = data_get_n_byte_value (PACKED_PARAM_LENGTH (c));
+ if (LONG_FORMAT (c))
+ {
+ PK_H_ESCAPEMENT (*pk_char) >>= 16;/* Don't bother to round. */
+ (void) data_get_four (); /* Ignore the vertical escapement. */
+ }
+
+ /* Next comes the size of the bitmap. */
+ DIMENSIONS_WIDTH (d) = data_get_n_byte_value (PACKED_PARAM_LENGTH (c));
+ DIMENSIONS_HEIGHT (d) = data_get_n_byte_value (PACKED_PARAM_LENGTH (c));
+ PK_BITMAP (*pk_char) = new_bitmap (d);
+
+ /* The last two values in the character preamble are the offsets from
+ the upper left pixel to the reference pixel. */
+ h_offset = data_get_signed_n_byte_value (PACKED_PARAM_LENGTH (c));
+ v_offset = data_get_signed_n_byte_value (PACKED_PARAM_LENGTH (c));
+ MIN_COL (PK_CHAR_BB (*pk_char)) = -h_offset;
+ MAX_COL (PK_CHAR_BB (*pk_char)) = -h_offset + DIMENSIONS_WIDTH (d);
+ MIN_ROW (PK_CHAR_BB (*pk_char)) = v_offset + 1 - DIMENSIONS_HEIGHT (d);
+ MAX_ROW (PK_CHAR_BB (*pk_char)) = v_offset;
+
+ if (PACKED_DYN_F (c) == PK_BITMAP_FLAG)
+ get_bitmap (pk_char);
+ else
+ get_packed_bitmap (pk_char, c);
+
+ return pk_char;
+}
+
+
+/* Turn the packed bitmap in the character C into a real bitmap, in
+ PK_CHAR. The bitmap storage and sizes in PK_CHAR must already be
+ set. The packed data should encode exactly as many bits as are in
+ the bitmap. */
+
+static void
+get_packed_bitmap (pk_char_type *pk_char, packed_char_type c)
+{
+ bitmap_type b = PK_BITMAP (*pk_char);
+ unsigned row = 0;
+ unsigned col = 0;
+ unsigned row_repeat_count = 0;
+ one_byte color = PACKED_BLACK_FIRST (c);
+
+ while (row < BITMAP_HEIGHT (b))
+ {
+ unsigned i;
+ unsigned cmd_repeat_count;
+ unsigned run_count = get_run_count (PACKED_DYN_F (c), &cmd_repeat_count);
+
+ if (cmd_repeat_count != 0)
+ {
+ if (row_repeat_count != 0)
+ FATAL2 ("Two repeat counts (%u and %u) in PK row",
+ row_repeat_count, cmd_repeat_count);
+ row_repeat_count = cmd_repeat_count;
+ }
+
+ /* Start painting pixels. */
+ for (i = 0; i < run_count; i++)
+ {
+ BITMAP_PIXEL (b, row, col) = color;
+ col++;
+
+ /* It is inefficient to test this here. Sorry. */
+ if (col == BITMAP_WIDTH (b))
+ { /* We've finished a row. If we saw a repeat count
+ somewhere within it, we should duplicate it.
+ If the PK file is correct, `row' will not increase past
+ the height of the bitmap from repeat counts, but we may
+ as well be safe. */
+ for (row++;
+ row_repeat_count > 0 && row < BITMAP_HEIGHT (b);
+ row_repeat_count--, row++)
+ for (col = 0; col < BITMAP_WIDTH (b); col++)
+ BITMAP_PIXEL (b, row, col) = BITMAP_PIXEL (b, row - 1, col);
+
+ /* Start painting pixels from the run count at the
+ beginning of the next row. */
+ col = 0;
+ }
+ }
+
+ color = !color;
+ }
+
+ if (col != 0)
+ FATAL ("The PK bitmap ended in a strange place");
+}
+
+
+/* This routine is called `pk_packed_num' in the PK documentation, but
+ as far as the caller is concerned, it doesn't return a packed number,
+ it returns a run count. Due to the definition of packed data, it is
+ impractical to return repeat counts in any other way except together
+ with a run count. */
+
+static unsigned
+get_run_count (one_byte dyn_f, unsigned *repeat_count)
+{
+ unsigned n = data_get_nybble ();
+
+ *repeat_count = 0;
+
+ if (n == LONG_RUN_COUNT_FLAG)
+ { /* Get a three nybble (or more) value, represented as some number
+ of zeros, followed by that many hexadecimal values. The
+ largest such number that we'll be asked to find will fit in
+ 32 bits. */
+ unsigned zero_count = 0;
+ do
+ {
+ n = data_get_nybble ();
+ zero_count++;
+ }
+ while (n == 0);
+
+ for ( ; zero_count > 0; zero_count --)
+ n = (n << 4) + data_get_nybble ();
+
+ /* The smallest three-nybble value is one more than the largest
+ two nybble value. */
+ return n - 15 + ((13 - dyn_f) << 4) + dyn_f;
+ }
+
+ else if (n <= dyn_f)
+ /* The value we just read is itself the number. */
+ return n;
+
+ else if (n < REPEAT_COUNT_FLAG)
+ /* Get a two-nybble value. */
+ return ((n - dyn_f - 1) << 4) + data_get_nybble () + dyn_f + 1;
+
+ else if (n == REPEAT_COUNT_FLAG)
+ /* If the PK file is valid, this recursion will go only one level
+ deep, because a repeat count should never be followed by another
+ repeat count. In other words, the next nybble must be a ``run
+ count'' in some form. (This is why this routine is called
+ `pk_packed_num' in other programs.) */
+ *repeat_count = get_run_count (dyn_f, &n);
+
+ else
+ *repeat_count = 1;
+
+ /* We only get here if we saw a repeat count. Now we have to get the
+ run count which should be next; there won't be any repeat count. */
+ return get_run_count (dyn_f, &n);
+}
+
+
+/* The PK format also allows for a straight bitmap representation in the
+ file, one pixel per bit. Here we put each pixel into a byte. */
+
+static void
+get_bitmap (pk_char_type *pk_char)
+{
+ unsigned row;
+ unsigned col;
+ one_byte extra_bits;
+ bitmap_type b = PK_BITMAP (*pk_char);
+
+ for (row = 0; row < BITMAP_HEIGHT (b); row++)
+ for (col = 0; col < BITMAP_WIDTH (b); col++)
+ BITMAP_PIXEL (b, row, col) = data_get_bit ();
+
+ /* If the bitmap did not completely fill the last byte, we should read
+ and ignore the remaining bits. */
+ extra_bits = 8 - (row * col) % 8;
+ while (extra_bits-- > 0)
+ (void) data_get_bit ();
+}
+
+/* Low-level routines that read from the disk file. */
+
+static string
+pk_get_string (unsigned length)
+{
+ string s;
+
+ if (length == 0) return "";
+
+ s = PK_GET_N_BYTES (length);
+ s = xrealloc (s, length + 1);
+ s[length] = 0;
+ return s;
+}
+
+
+/* N must be <= 4. */
+
+static four_bytes
+pk_get_n_byte_value (unsigned n)
+{
+ four_bytes v = 0;
+
+ for ( ; n > 0; n--)
+ v |= PK_GET_BYTE () << ((n - 1) * 8);
+
+ return v;
+}
+
+/* These routines do not read from a disk file. Instead, they read from
+ memory (where we have put each character's definition, directly from
+ the file.) They use the semi-global `pk_input_data'. */
+
+
+/* This routine is used when the character is defined as a bitmap,
+ instead of run-encoded. */
+
+static one_byte
+data_get_bit ()
+{
+ static one_byte mask = 0;
+ static one_byte n;
+ one_byte value;
+
+ if (mask == 0)
+ {
+ n = data_get_nybble ();
+ mask = 0x8;
+ }
+
+ value = (n & mask) != 0;
+ mask >>= 1;
+
+ return value;
+}
+
+
+/* Since the PK format is based on nybbles, this routine is by far the
+ most frequently called. */
+
+static one_byte
+data_get_nybble ()
+{
+ do_upper_nybble = !do_upper_nybble;
+
+ /* Double inversion gets us back the original value. After we have
+ done the lower nybble, we advance to the next byte. */
+ return !do_upper_nybble ? *pk_input_data >> 4 : *pk_input_data++ & 0xf;
+}
+
+
+/* We assume (correctly) that we are not in the middle of a byte
+ when any of the following routines are called. */
+
+static four_bytes
+data_get_three ()
+{
+ return data_get_n_byte_value (3);
+}
+
+
+static four_bytes
+data_get_four ()
+{
+ return data_get_n_byte_value (4);
+}
+
+
+static four_bytes
+data_get_n_byte_value (one_byte n)
+{
+ four_bytes v = 0;
+
+ for ( ; n > 0; n--)
+ v |= *pk_input_data++ << ((n - 1) * 8);
+
+ return v;
+}
+
+
+static signed_4_bytes
+data_get_signed_n_byte_value (one_byte passed_n)
+{
+ signed_4_bytes v = 0;
+ unsigned n = passed_n;
+
+ assert (n <= 4);
+
+ for ( ; n > 0; n--)
+ v |= (*pk_input_data++ << ((n - 1) * 8));
+
+ if (passed_n == 1)
+ return (signed_byte) (v & 0xff);
+ else if (passed_n == 2)
+ return (signed_2_bytes) (v & 0xffff);
+ else if (passed_n == 3)
+ return (signed_4_bytes) (v & 0xffffff);
+ else
+ return (signed_4_bytes) v;
+
+ return v;
+}
+
+/* We assign an index number to NAME, and store both NAME and the
+ `internal_font_type' that we construct in parallel lists. The file F
+ goes into the `internal_font_list'. */
+
+static list_type font_name_list, internal_font_list;
+
+static void
+save_internal_font (string name, FILE *f)
+{
+ unsigned c;
+ string *new_name;
+ internal_font_type *new_font;
+ static boolean first_call = true;
+
+ if (first_call)
+ { /* We have to construct our lists. */
+ font_name_list = list_init ();
+ internal_font_list = list_init ();
+ first_call = false;
+ }
+
+ new_name = (string *) LIST_TAPPEND (&font_name_list, string);
+ new_font = (internal_font_type *)
+ LIST_TAPPEND (&internal_font_list, internal_font_type);
+
+ /* Save the information. */
+ *new_name = xstrdup (name);
+ INTERNAL_FILE (*new_font) = f;
+
+ /* We also have to initialize other parts of `new_font'. */
+ for (c = 0; c <= MAX_CHARCODE; c++)
+ {
+ INTERNAL_PK_CHAR (*new_font, c) = NULL;
+ INTERNAL_PACKED_CHAR (*new_font, c) = NULL;
+ }
+ INTERNAL_CHARS_READ (*new_font) = false;
+}
+
+
+/* Here we return the `internal_font_type' previously stored along with
+ NAME. If NAME hasn't been saved, we give a fatal error. */
+
+static internal_font_type *
+find_internal_font (string name)
+{
+ unsigned e;
+
+ for (e = 0; e < LIST_SIZE (font_name_list); e++)
+ if (STREQ (*(string *) LIST_ELT (font_name_list, e), name))
+ return (internal_font_type *) LIST_ELT (internal_font_list, e);
+
+ FATAL1 ("The PK font `%s' hasn't been saved", name);
+ return NULL; /* NOTREACHED */
+}
+
+
+/* Free the memory and file pointer used by the font FILENAME. We don't
+ delete the list element for now, since removing elements from the
+ middle of an array is painful. Instead, we simply set the name in
+ `font_name_list' to the empty string, so that the element is useless.
+ Yes, this is disgusting. */
+
+static void
+delete_internal_font (string filename)
+{
+ unsigned e;
+
+ /* We can't use `find_internal_font', since we need to know the list
+ element index, not just the internal font information. */
+ for (e = 0; e < LIST_SIZE (font_name_list); e++)
+ if (STREQ (*(string *) LIST_ELT (font_name_list, e), filename))
+ {
+ unsigned c;
+ internal_font_type *f = LIST_ELT (internal_font_list, e);
+
+ assert (INTERNAL_FILE (*f) != NULL);
+ xfclose (INTERNAL_FILE (*f), filename);
+ INTERNAL_FILE (*f) = NULL;
+
+ if (INTERNAL_CHARS_READ (*f))
+ for (c = 0; c <= MAX_CHARCODE; c++)
+ if (INTERNAL_PK_CHAR (*f, c) != NULL)
+ free (INTERNAL_PK_CHAR (*f, c));
+
+ *(string *) LIST_ELT (font_name_list, e) = "";
+ return;
+ }
+ FATAL1 ("The PK font `%s' hasn't been saved", filename);
+}
diff --git a/pk/pk_opcodes.h b/pk/pk_opcodes.h
new file mode 100644
index 0000000..854ed52
--- /dev/null
+++ b/pk/pk_opcodes.h
@@ -0,0 +1,41 @@
+/* pk_opcodes.h: symbolic names for some of the GF commands and special
+ values.
+
+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. */
+
+#ifndef PK_OPCODES_H
+#define PK_OPCODES_H
+
+/* Some of the command bytes. */
+#define PK_PRE 247
+#define PK_ID 89
+#define PK_XXX1 240
+#define PK_XXX4 243
+#define PK_YYY 244
+#define PK_POST 245
+#define PK_NO_OP 246
+
+/* If the `dyn_f' value for a character is this, the bitmap is
+ represented as a bitmap, instead of being packed. */
+#define PK_BITMAP_FLAG 14
+
+/* These values are for the first nybble in packed numbers. */
+#define LONG_RUN_COUNT_FLAG 0
+#define REPEAT_COUNT_FLAG 14
+#define REPEAT_ONE 15
+
+#endif /* not PK_OPCODES_H */
diff --git a/tfm/ChangeLog b/tfm/ChangeLog
new file mode 100644
index 0000000..044da8f
--- /dev/null
+++ b/tfm/ChangeLog
@@ -0,0 +1,371 @@
+Fri May 13 16:57:15 1994 Karl Berry (karl@cs.umb.edu)
+
+ * tfm_output.c (tfm_convert_pl): Add NULL to the concatn.
+
+Sun May 1 15:32:11 1994 Karl Berry (karl@cs.umb.edu)
+
+ * tfm_output.c: Use concatn instead of the no-longer-existing concat5.
+
+Tue Oct 27 12:56:39 1992 Karl Berry (karl@cs.umb.edu)
+
+ * Version 0.6.
+
+Mon Oct 19 08:11:44 1992 Karl Berry (karl@cs.umb.edu)
+
+ * tfm_input.c (tfm_get_chars): Return the newly malloced array,
+ not the static variable.
+
+Thu Sep 3 09:31:23 1992 Karl Berry (karl@hayley)
+
+ * Version 0.5.
+
+Tue Jul 7 16:42:47 1992 Karl Berry (karl@hayley)
+
+ * tfm_input.c (tfm_input_filename): new routine.
+ (tfm_input_filename): change var name to just `tfm_input_name'.
+
+Sat Jun 13 07:55:29 1992 Karl Berry (karl@hayley)
+
+ * all files: change `font_param{,eter}' to `fontdimen', globally.
+
+ * tfm_fontdim.c: rename from `fontdimen.c'.
+ * GNUmakefile (c_only): change here.
+
+Fri Jun 12 09:45:31 1992 Karl Berry (karl@hayley)
+
+ * fontdimen.c (tfm_set_fontdimen): rename from
+ `tfm_set_font_parameter', and rearrange args.
+
+ * tfm_ligature.c (tfm_set_ligature): take a lig list as the
+ parameter instead of a TFM char.
+
+Tue Jun 9 13:57:18 1992 Karl Berry (karl@hayley)
+
+ * fontdimen.c (tfm_set_fontdimens): call `float_ok' on the
+ potential fontdimen value.
+
+ * fontdimen.c: new file with all the fontdimen stuff.
+ * tfm_kern.c: new file with the kern stuff.
+ * tfm_ligature.c: and the ligature stuff.
+ * tfm_char.c: rename from tfm_util, since that's all that's left.
+
+Mon Jun 8 15:27:59 1992 Karl Berry (karl@hayley)
+
+ * tfm_util.c (tfm_set_kern): take a kern list as the parameter instead
+ of the whole TFM character.
+
+Sun May 31 10:56:10 1992 Karl Berry (karl@hayley)
+
+ * tfm_output.c (tfm_put_char): use `epsilon_equal'.
+
+Sat May 30 14:58:33 1992 Karl Berry (karl@hayley)
+
+ * tfm_output.c (tfm_convert_pl): allow for passing in the TFM name.
+
+ * tfm_output.c (tfm_convert_pl): free `cmd'.
+
+Thu May 14 22:20:14 1992 Karl Berry (karl@claude.cs.umb.edu)
+
+ * tfm_util.c (tfm_set_fontsize): make non-static.
+
+Wed May 13 09:16:19 1992 Karl Berry (karl@hayley)
+
+ * tfm_input.c (get_tfm_header): initialize the parameter count in
+ global_info here.
+ (get_tfm_params): not here.
+
+Tue Apr 21 07:45:29 1992 Karl Berry (karl@hayley)
+
+ * tfm_input.c (tfm_get_global_info): use XTALLOC1.
+
+Sun Mar 29 19:02:25 1992 Karl Berry (karl at hayley)
+
+ * tfm_input.c (get_tfm_params): forgot arg to printf.
+
+Sat Mar 28 07:49:38 1992 Karl Berry (karl at hayley)
+
+ * Version 0.4.
+
+ * Change copyright years to 1992 only.
+
+Sat Mar 21 10:59:51 1992 Kathy Hargreaves (kathy at hayley)
+
+ * tfm_util.c (tfm_set_design_size): set design size unconditionally.
+
+ * tfm_util.c (tfm_set_design_size): added.
+
+ * tfm_util.c (tfm_set_header): deleted DEFAULT_DESIGN_SIZE.
+
+ * tfm_util.c (tfm_set_fontsize): made extern.
+
+ * tfm_util.c [TFM_CHECK_DESIGNSIZE]: changed name from
+ CHECK_DESIGNSIZE.
+
+ * tfm_util.c (tfm_set_font_parameter, tfm_set_fontsize): added.
+ (tfm_set_fontdimens): use tfm_set_font_parameter.
+
+Thu Mar 19 13:24:14 1992 Kathy Hargreaves (kathy at hayley)
+
+ * tfm_util.c (tfm_set_header): use CHECK_DESIGN_SIZE.
+ Don't range of check default design size; expect it to be valid.
+
+ * tfm_util.h [CHECK_DESIGN_SIZE]: added.
+
+ * tfm_util.c (tfm_set_header): took `design_size' out of
+ `designsize' else clause. Added DEFAULT_DESIGN_SIZE. If either
+ variable is set, then arrange to set fontsize.
+ Set tfm_info's design size to DEFAULT_DESIGN_SIZE if it's not
+ set by the tfm-header design-size option.
+
+ * tfm_util.c (set_fontsize): changed name from set_fontsize_if_unset.
+ (tfm_set_header): if -design-size tfm-header option is used, set
+ the font parameter count so will change the fontsize.
+
+Wed Mar 18 12:27:44 1992 Kathy Hargreaves (kathy at hayley)
+
+ * tfm_util.c (tfm_set_ligature): added.
+
+ * tfm_util.c (tfm_set_header): dox fix.
+
+Mon Mar 16 12:22:42 1992 Kathy Hargreaves (kathy at hayley)
+
+ * tfm_util.c (tfm_set_header): set design size correctly.
+
+ * tfm_util.c (set_fontsize_if_unset): added.
+ (tfm_set_header, tfm_set_fontdimens): call set_fontsize_if_unset.
+
+ * tfm_util.c (tfm_set_header): added.
+
+Thu Jan 9 11:22:04 1992 Karl Berry (karl at hayley)
+
+ * *.c: do not include global.h.
+
+Wed Jan 8 15:25:17 1992 Karl Berry (karl at hayley)
+
+ * update copyright messages.
+
+ * change `allocate to `xmalloc', `reallocate' to `xrealloc', and
+ `string_copy' to `strdup'.
+
+Tue Sep 17 16:54:26 1991 Karl Berry (karl at hayley)
+
+ * tfm_input.c (tfm_get_bcpl_string): append a null to the data.
+
+Tue Jul 30 13:20:02 1991 Karl Berry (karl at ra.cs.umb.edu)
+
+ * Version 0.3.
+
+Tue Jul 16 17:21:19 1991 Karl Berry (karl at hayley)
+
+ * tfm_util.c (tfm_get_kern): move from tfm_input.c, and take a tfm
+ char as an arg, instead of using the tfm_char_table from the font.
+
+Sun Jun 16 07:47:49 1991 Karl Berry (karl at hayley)
+
+ * tfm_output.c (put_lig_kern_info): output a `stop' after each
+ character, since it isn't implied by a `label'.
+
+ * tfm_output.c (tfm_put_global_info): don't output a checksum
+ property if the checksum is zero.
+
+Sat Jun 15 09:54:19 1991 Karl Berry (karl at hayley)
+
+ * tfm_input.c (tfm_get_chars, tfm_get_char): set the `code' member
+ of the TFM character structure.
+
+ * tfm_output.c (put_pl_lig_kern_table): rename to
+ `put_lig_kern_info' and rewrite to take a single character.
+ (tfm_put_char): new routine to output only one character.
+ (tfm_put_chars): call `tfm_put_char'.
+
+ * all files: change `checked_' to `x'.
+
+Tue Jun 11 15:17:51 1991 Karl Berry (karl at hayley)
+
+ * tfm_util.c (tfm_new_chars): use XTALLOC.
+
+ * tfm_input.c (tfm_get_char): new routine.
+
+ * tfm_input.c (tfm_get_kern): check if the character exists before
+ looking at its kern list. Also, use LIST_... macros instead of
+ doing direct selection. Also, use `charcode_type' instead of
+ `one_byte'.
+ * tfm_util.c (tfm_set_kern): likewise.
+
+ * tfm_input.c (tfm_get_global_info, tfm_get_chars): don't save and
+ restore the file position.
+
+ * tfm_input.c (get_tfm_char): rename to `get_char'.
+
+Thu Jun 6 07:31:49 1991 Karl Berry (karl at hayley)
+
+ * All files: change to version 2 of the GPL.
+
+Thu Apr 4 05:48:15 1991 Karl Berry (karl at hayley)
+
+ * tfm_util.c (tfm_new_chars): call `tfm_new_char'.
+
+ * tfm_output.c (put_pl_lig_kern_table): test different characters
+ as we go through the loop! How did this one get past? Ohh, now
+ I see -- I was incrementing the pointer.
+
+ * tfm_output.c (put_pl_lig_kern_table): test >0 instead of !=0 on
+ the (unsigned) count variables.
+
+Wed Apr 3 11:43:28 1991 Karl Berry (karl at hayley)
+
+ * tfm_output.c (tfm_init_global_info): initialize the number of
+ parameters to zero.
+
+ * tfm_output.c (put_pl_lig_kern_table): don't output a lig/kern
+ program for a character that doesn't exist -- either the left or
+ the right.
+
+Tue Apr 2 06:48:27 1991 Karl Berry (karl at hayley)
+
+ * tfm_util.c (tfm_set_fontdimens): assign zero to all the
+ intervening fontdimens when we set the fontsize; reset the
+ parameter count.
+
+ * tfm_output.c (tfm_put_global_info): output the number of
+ parameters we have, instead of trying to find the last nonzero
+ one.
+
+ * tfm_output.c (put_string_prop): don't output a space if there is
+ no value to the string property.
+
+Sun Mar 10 13:12:51 1991 Karl Berry (karl at hayley)
+
+ * tfm_input.c (get_tfm_params): save the number of parameters we
+ read.
+
+ * tfm_output.c (tfm_put_global_info): output as many parameters as
+ we have, instead of just the first six.
+ * tfm_input.c (get_tfm_params): likewise, for reading.
+
+ * tfm_output.c (tfm_init_global_info): new routine.
+
+Sat Mar 9 17:23:42 1991 Karl Berry (karl at hayley)
+
+ * tfm_util.c (tfm_set_fontdimens): new routine.
+
+Thu Mar 7 07:33:33 1991 Karl Berry (karl at hayley)
+
+ * Version 0.2.
+
+Tue Mar 5 15:34:26 1991 Karl Berry (karl at hayley)
+
+ * tfm_output.c (tfm_convert_pl): use output redirection instead of
+ -v to make tftopl be quiet.
+
+Mon Feb 25 15:42:09 1991 Karl Berry (karl at hayley)
+
+ * tfm_output.c (tfm_convert_pl): take a new parameter which says
+ whether to operate silently.
+
+ * tfm_output.c (INDENT_INCR): define as 2.
+
+ * tfm_input.c (tfm_open_filename): give an error if the caller
+ tries to open more than one file.
+
+ * tfm_{input,output,util}.c: rename external routines to start with
+ `tfm'; change error messages, etc.
+
+Sun Feb 17 09:51:50 1991 Karl Berry (karl at hayley)
+
+ * *.c: include config.h.
+
+Sun Dec 9 15:08:57 1990 Karl Berry (karl at hayley)
+
+ * tfm_input.c, tfm_output.c: doc fix.
+
+Sat Nov 17 12:54:02 1990 Karl Berry (karl at hayley)
+
+ * tfm_input.c, tfm_output.c: include appropriate file-...h files.
+
+Thu Aug 30 16:29:51 1990 Karl Berry (karl at hayley)
+
+ * tfm_input.c (tfm_get_byte, ...): pass the input filename, and
+ rewrite as macros.
+
+Tue Jul 24 11:09:46 1990 Karl Berry (karl at hayley)
+
+ * tfm_output.c: include filename.h.
+
+Fri Jul 13 16:48:56 1990 Karl Berry (karl at hayley)
+
+ * tfm_input.c (get_tfm_chars): declare `this_char' as unsigned,
+ not one_byte, since it might have to become 256.
+
+Wed Jul 4 08:39:28 1990 Karl Berry (karl at hayley)
+
+ * tfm_output.c (put_tfm_chars): look at the `exists' member of the
+ character structure, instead of checking for the width being zero.
+
+Wed Jun 20 07:32:49 1990 Karl Berry (karl at hayley)
+
+ * tfm_input.c (tfm_cur_pos): rename to tfm_ftell, and use
+ checked_ftell.
+ (tfm_set_pos): rename to tfm_fseek.
+
+Fri Jun 1 15:36:38 1990 Karl Berry (karl at hayley)
+
+ * tfm_input.c (close_tfm_input_file): use checked_fclose.
+ * tfm_output.c (close_pl_output_file): likewise.
+
+Wed May 30 16:21:43 1990 Karl Berry (karl at hayley)
+
+ * tfm_input.c (get_tfm_char): set the `exists' member of the
+ character structure.
+ * tfm_util.c (new_tfm_char): initialize the `exists' member.
+
+Thu Apr 12 14:58:24 1990 Karl Berry (karl at hayley)
+
+ * tfm_input.c (get_interword_space): rename to
+ `tfm_get_interword_space'.
+
+Mon Apr 9 12:10:26 1990 Karl Berry (karl at hayley)
+
+ * (all files): upcase macro names.
+
+Sun Apr 8 11:42:53 1990 Karl Berry (karl at hayley)
+
+ * tfm_input.c (get_tfm_global_info): if we've already read the
+ global info, just return the structure, instead of reading it
+ again.
+
+Fri Feb 23 08:43:02 1990 Karl Berry (karl at hayley)
+
+ * tfm_input.c (get_tfm_char): remember the dimensions in their
+ original fix_word units, as well as in points.
+
+Wed Feb 7 17:22:27 1990 Karl Berry (karl at hayley)
+
+ * tfm_input.c (tfm_get_design_size): new routine.
+ (tfm_get_coding_scheme): rename `get_coding_scheme'.
+
+Sun Jan 28 14:48:35 1990 Karl Berry (karl at hayley)
+
+ * tfm_util.c (set_kern): move this routine from tfm_input.c.
+
+ * tfm_output.c (change_pl_to_tfm): check that pl_output_filename
+ is non-NULL.
+
+Fri Dec 22 17:33:30 1989 Karl Berry (karl at hayley)
+
+ * tfm_input.c (tfm_get_x_height): new routine.
+
+Mon Oct 30 12:37:02 1989 Karl Berry (karl at hayley)
+
+ * all files: add the copyleft.
+
+ * tfm_util.c: define new_tfm_chars.
+
+ * tfm_output.c (put_tfm_global_info): take a structure as input,
+ not a pointer.
+ (new_tfm_char): move to tfm_util.c.
+
+Sun Oct 29 08:13:05 1989 Karl Berry (karl at hayley)
+
+ * tfm_output.c (put_pl_file): remove this, and add put_tfm_chars
+ and put_tfm_global_info in its place.
diff --git a/tfm/GNUmakefile b/tfm/GNUmakefile
new file mode 100644
index 0000000..7b0201a
--- /dev/null
+++ b/tfm/GNUmakefile
@@ -0,0 +1,27 @@
+# Makefile for the TFM library.
+#
+# 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.
+#
+library = tfm
+
+c_only = tfm_char tfm_fontdim tfm_header tfm_input tfm_kern tfm_ligature \
+tfm_output
+
+include ../data/defs.make
+include ../data/defslib.make
+
+include M.depend
diff --git a/tfm/README b/tfm/README
new file mode 100644
index 0000000..cbbdf5e
--- /dev/null
+++ b/tfm/README
@@ -0,0 +1,17 @@
+This library provides for reading and writing of TeX font metric (TFM)
+files. Only a single file may be read or written at a time.
+
+None of the code that processes the TFM commands actually explains what
+the precise definition of those commands are. For that, you should look
+at the definition of the TFM format in Metafont: The Program, by Don
+Knuth, chapter 46. It is also in the TeXware program tftopl,
+TeX: The Program, and other places.
+
+The header file is ../include/tfm.h. It explains the basics of how to
+use these routines. The source files in this directory do not repeat
+that explanation.
+
+TFM format was extended in 1990 to allow for complicated ligatures.
+We do not recognize all the distinctions; all ligatures are simply
+collapsed into the pre-1990 form, character A followed by character B
+leads to character C.
diff --git a/tfm/fontdimen.c b/tfm/fontdimen.c
new file mode 100644
index 0000000..dadd516
--- /dev/null
+++ b/tfm/fontdimen.c
@@ -0,0 +1,183 @@
+/* fontdimen.c: handle TFM fontdimens a.k.a. font parameters.
+
+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 "tfm.h"
+
+
+/* This structure maps font parameter names to numbers. */
+typedef struct
+{
+ string name;
+ unsigned number;
+} font_param_type;
+
+/* The list of fontdimen names and their corresponding numbers. I wish
+ I could figure out a good way to give this list only once (in tfm.h),
+ instead of three times. */
+
+static font_param_type font_param[] = {
+ { "slant", TFM_SLANT_PARAMETER },
+ { "space", TFM_SPACE_PARAMETER },
+ { "stretch", TFM_STRETCH_PARAMETER },
+ { "shrink", TFM_SHRINK_PARAMETER },
+ { "xheight", TFM_XHEIGHT_PARAMETER },
+ { "quad", TFM_QUAD_PARAMETER },
+ { "extraspace", TFM_EXTRASPACE_PARAMETER },
+ { "num1", TFM_NUM1_PARAMETER },
+ { "num2", TFM_NUM2_PARAMETER },
+ { "num3", TFM_NUM3_PARAMETER },
+ { "denom1", TFM_DENOM1_PARAMETER },
+ { "denom2", TFM_DENOM2_PARAMETER },
+ { "sup1", TFM_SUP1_PARAMETER },
+ { "sup2", TFM_SUP2_PARAMETER },
+ { "sup3", TFM_SUP3_PARAMETER },
+ { "sub1", TFM_SUB1_PARAMETER },
+ { "sub2", TFM_SUB2_PARAMETER },
+ { "supdrop", TFM_SUPDROP_PARAMETER },
+ { "subdrop", TFM_SUBDROP_PARAMETER },
+ { "delim1", TFM_DELIM1_PARAMETER },
+ { "delim2", TFM_DELIM2_PARAMETER },
+ { "axisheight", TFM_AXISHEIGHT_PARAMETER },
+ { "defaultrulethickness", TFM_DEFAULTRULETHICKNESS_PARAMETER },
+ { "bigopspacing1", TFM_BIGOPSPACING1_PARAMETER },
+ { "bigopspacing2", TFM_BIGOPSPACING2_PARAMETER },
+ { "bigopspacing3", TFM_BIGOPSPACING3_PARAMETER },
+ { "bigopspacing4", TFM_BIGOPSPACING4_PARAMETER },
+ { "bigopspacing5", TFM_BIGOPSPACING5_PARAMETER },
+ { "leadingheight", TFM_LEADINGHEIGHT_PARAMETER },
+ { "leadingdepth", TFM_LEADINGDEPTH_PARAMETER },
+ { "fontsize", TFM_FONTSIZE_PARAMETER },
+ { "version", TFM_VERSION_PARAMETER },
+};
+
+/* Set the font parameter entries in TFM_INFO according to the string S.
+ If S is non-null and non-empty, it should look like
+ <fontdimen>:<real>,<fontdimen>:<real>,..., where each <fontdimen> is
+ either a standard name or a number between 1 and 30 (the 30 comes
+ from the default value in PLtoTF, it's not critical).
+
+ Also, if the `design_size' member of TFM_INFO is nonzero, we set the
+ `FONTSIZE' parameter to 1.0 (meaning it's equal to the design size),
+ unless the `FONTSIZE' parameter is already set. */
+
+void
+tfm_set_fontdimens (string s, tfm_global_info_type *tfm_info)
+{
+ string spec;
+
+ /* If S is empty, we have nothing more to do. */
+ if (s == NULL || *s == 0)
+ return;
+
+ /* Parse the specification string. */
+ for (spec = strtok (s, ","); spec != NULL; spec = strtok (NULL, ","))
+ {
+ string fontdimen;
+ real value;
+ unsigned param_number = 0;
+ string value_string = strchr (spec, ':');
+
+ if (value_string == NULL || !float_ok (value_string))
+ FATAL1 ("Fontdimens look like `<fontdimen>:<real>', not `%s'",
+ spec);
+
+ value = atof (value_string + 1);
+ fontdimen = substring (spec, 0, value_string - spec - 1);
+
+ /* If `fontdimen' is all numerals, we'll take it to be an integer. */
+ if (strspn (fontdimen, "0123456789") == strlen (fontdimen))
+ {
+ param_number = atou (fontdimen);
+
+ if (param_number == 0 || param_number > TFM_MAX_FONT_PARAMETERS)
+ FATAL2 ("Font parameter %u is not between 1 and the maximum (%u)",
+ param_number, TFM_MAX_FONT_PARAMETERS);
+ }
+ else
+ { /* It wasn't a number; see if it's a valid name. */
+ param_number = tfm_fontdimen_number (fontdimen);
+
+ if (param_number == 0)
+ FATAL1 ("I don't know the font parameter name `%s'", fontdimen);
+ }
+
+ /* If we got here, `param_number' is the number of the font
+ parameter we are supposed to assign to. */
+ tfm_set_font_parameter (param_number, value, tfm_info);
+
+ /* If `param_number' is past the last fontdimen previously
+ assigned, we have to assign zero to all the intervening ones.
+ But this can never happen, because we always assign the
+ `fontsize' parameter, which happens to be the last one. */
+ assert (param_number <= TFM_FONT_PARAMETER_COUNT (*tfm_info));
+ }
+}
+
+/* Return zero if we do not recognize S as the name of a fontdimen, else
+ its corresponding number. We just do a linear search through the
+ structure, since it's so small. */
+
+unsigned
+tfm_fontdimen_number (string s)
+{
+ unsigned this_param;
+ unsigned param_number = 0;
+
+ for (this_param = 0;
+ this_param < TFM_MAX_FONT_PARAMETERS && param_number == 0;
+ this_param++)
+ if (STREQ (s, font_param[this_param].name))
+ param_number = font_param[this_param].number;
+
+ return param_number;
+}
+
+/* Set the PARAMETER-th font parameter of TFM_INFO to VALUE. If
+ PARAMETER is beyond the current last parameter of TFM_INFO, set
+ all the intervening parameters to zero. */
+
+void
+tfm_set_fontdimen (tfm_global_info_type *tfm_info,
+ unsigned parameter, real value,
+{
+ if (TFM_FONT_PARAMETER_COUNT (*tfm_info) < parameter)
+ {
+ unsigned p;
+
+ for (p = TFM_FONT_PARAMETER_COUNT (*tfm_info) + 1; p < parameter; p++)
+ TFM_FONT_PARAMETER (*tfm_info, p) = 0.0;
+
+ /* Now we have more parameters. */
+ TFM_FONT_PARAMETER_COUNT (*tfm_info) = parameter;
+ }
+
+ TFM_FONT_PARAMETER (*tfm_info, parameter) = value;
+}
+
+
+/* Set the `FONTSIZE' parameter of TFM_INFO, if the design size is set. */
+
+void
+tfm_set_fontsize (tfm_global_info_type *tfm_info)
+{
+ if (TFM_DESIGN_SIZE (*tfm_info) != 0.0)
+ tfm_set_font_parameter (TFM_FONTSIZE_PARAMETER,
+ TFM_DESIGN_SIZE (*tfm_info), tfm_info);
+}
diff --git a/tfm/tfm_char.c b/tfm/tfm_char.c
new file mode 100644
index 0000000..dad8a02
--- /dev/null
+++ b/tfm/tfm_char.c
@@ -0,0 +1,56 @@
+/* tfm_util.c: routines independent of reading or writing a particular font.
+
+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 "tfm.h"
+
+
+/* A constructor for the TFM character type. */
+
+tfm_char_type
+tfm_new_char ()
+{
+ tfm_char_type ch;
+
+ ch.code = 0;
+ ch.width = ch.height = ch.depth = ch.italic_correction = 0.0;
+ ch.fix_width = ch.fix_height = ch.fix_depth = ch.fix_italic_correction = 0;
+
+ ch.ligature = list_init ();
+ ch.kern = list_init ();
+
+ ch.exists = false;
+
+ return ch;
+}
+
+
+/* Return an initialized array of `tfm_char_type's. */
+
+tfm_char_type *
+tfm_new_chars ()
+{
+ unsigned i;
+ tfm_char_type *chars = XTALLOC (TFM_SIZE, tfm_char_type);
+
+ for (i = 0; i < TFM_SIZE; i++)
+ chars[i] = tfm_new_char ();
+
+ return chars;
+}
diff --git a/tfm/tfm_fontdim.c b/tfm/tfm_fontdim.c
new file mode 100644
index 0000000..454b12e
--- /dev/null
+++ b/tfm/tfm_fontdim.c
@@ -0,0 +1,194 @@
+/* fontdimen.c: handle TFM fontdimens a.k.a. font parameters.
+
+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 "tfm.h"
+
+
+/* This structure maps fontdimen names to numbers (and vice versa). */
+typedef struct
+{
+ string name;
+ unsigned number;
+} fontdimen_type;
+
+/* The list of fontdimen names and their corresponding numbers. I wish
+ I could figure out a good way to give this list only once (in tfm.h),
+ instead of three times. */
+
+static fontdimen_type fontdimen[] = {
+ { "slant", TFM_SLANT_PARAMETER },
+ { "space", TFM_SPACE_PARAMETER },
+ { "stretch", TFM_STRETCH_PARAMETER },
+ { "shrink", TFM_SHRINK_PARAMETER },
+ { "xheight", TFM_XHEIGHT_PARAMETER },
+ { "quad", TFM_QUAD_PARAMETER },
+ { "extraspace", TFM_EXTRASPACE_PARAMETER },
+ { "num1", TFM_NUM1_PARAMETER },
+ { "num2", TFM_NUM2_PARAMETER },
+ { "num3", TFM_NUM3_PARAMETER },
+ { "denom1", TFM_DENOM1_PARAMETER },
+ { "denom2", TFM_DENOM2_PARAMETER },
+ { "sup1", TFM_SUP1_PARAMETER },
+ { "sup2", TFM_SUP2_PARAMETER },
+ { "sup3", TFM_SUP3_PARAMETER },
+ { "sub1", TFM_SUB1_PARAMETER },
+ { "sub2", TFM_SUB2_PARAMETER },
+ { "supdrop", TFM_SUPDROP_PARAMETER },
+ { "subdrop", TFM_SUBDROP_PARAMETER },
+ { "delim1", TFM_DELIM1_PARAMETER },
+ { "delim2", TFM_DELIM2_PARAMETER },
+ { "axisheight", TFM_AXISHEIGHT_PARAMETER },
+ { "defaultrulethickness", TFM_DEFAULTRULETHICKNESS_PARAMETER },
+ { "bigopspacing1", TFM_BIGOPSPACING1_PARAMETER },
+ { "bigopspacing2", TFM_BIGOPSPACING2_PARAMETER },
+ { "bigopspacing3", TFM_BIGOPSPACING3_PARAMETER },
+ { "bigopspacing4", TFM_BIGOPSPACING4_PARAMETER },
+ { "bigopspacing5", TFM_BIGOPSPACING5_PARAMETER },
+ { "leadingheight", TFM_LEADINGHEIGHT_PARAMETER },
+ { "leadingdepth", TFM_LEADINGDEPTH_PARAMETER },
+ { "fontsize", TFM_FONTSIZE_PARAMETER },
+ { "version", TFM_VERSION_PARAMETER },
+};
+
+/* How many entries we have in the `fontdimen' array. */
+static unsigned fontdimen_array_size
+ = sizeof (fontdimen) / sizeof (fontdimen_type);
+
+/* Set the font parameter entries in TFM_INFO according to the string S.
+ If S is non-null and non-empty, it should look like
+ <fontdimen>:<real>,<fontdimen>:<real>,..., where each <fontdimen> is
+ either a standard name (in the list above) or a number between 1 and
+ TFM_MAX_FONTDIMENS (which is currently 30, the default value in
+ PLtoTF). */
+
+void
+tfm_set_fontdimens (string s, tfm_global_info_type *tfm_info)
+{
+ string spec;
+
+ /* If S is empty, we have nothing more to do. */
+ if (s == NULL || *s == 0)
+ return;
+
+ /* Parse the specification string. */
+ for (spec = strtok (s, ","); spec != NULL; spec = strtok (NULL, ","))
+ {
+ string fontdimen;
+ real value;
+ unsigned param_number = 0;
+ string value_string = strchr (spec, ':');
+
+ if (value_string == NULL || !float_ok (value_string))
+ FATAL1 ("Fontdimens look like `<fontdimen>:<real>', not `%s'",
+ spec);
+
+ value = atof (value_string + 1);
+ fontdimen = substring (spec, 0, value_string - spec - 1);
+
+ /* If `fontdimen' is all numerals, we'll take it to be an integer. */
+ if (strspn (fontdimen, "0123456789") == strlen (fontdimen))
+ {
+ param_number = atou (fontdimen);
+
+ if (param_number == 0 || param_number > TFM_MAX_FONTDIMENS)
+ FATAL2 ("Font parameter %u is not between 1 and the maximum (%u)",
+ param_number, TFM_MAX_FONTDIMENS);
+ }
+ else
+ { /* It wasn't a number; see if it's a valid name. */
+ param_number = tfm_fontdimen_number (fontdimen);
+
+ if (param_number == 0)
+ FATAL1 ("I don't know the font parameter name `%s'", fontdimen);
+ }
+
+ /* If we got here, `param_number' is the number of the font
+ parameter we are supposed to assign to. */
+ tfm_set_fontdimen (tfm_info, param_number, value);
+ }
+}
+
+/* Return zero if we do not recognize S as the name of a fontdimen, else
+ its corresponding number. We just do a linear search through the
+ structure, since it's so small. */
+
+unsigned
+tfm_fontdimen_number (string s)
+{
+ unsigned i; /* Index into the `fontdimen' array. */
+ unsigned param_number = 0;
+
+ for (i = 0; i < fontdimen_array_size && param_number == 0; i++)
+ if (STREQ (s, fontdimen[i].name))
+ param_number = fontdimen[i].number;
+
+ return param_number;
+}
+
+
+/* Return the name in `fontdimens' corresponding to the number N. */
+
+string
+tfm_fontdimen_name (unsigned n)
+{
+ unsigned i;
+ string name = NULL;
+
+ for (i = 0; i < fontdimen_array_size && name == NULL; i++)
+ {
+ if (fontdimen[i].number == n)
+ name = fontdimen[i].name;
+ }
+
+ return name;
+}
+
+/* Set the PARAMETER-th font parameter of TFM_INFO to VALUE. If
+ PARAMETER is beyond the current last parameter of TFM_INFO, set
+ all the intervening parameters to zero. */
+
+void
+tfm_set_fontdimen (tfm_global_info_type *tfm_info,
+ unsigned parameter, real value)
+{
+ if (TFM_FONTDIMEN_COUNT (*tfm_info) < parameter)
+ {
+ unsigned p;
+
+ for (p = TFM_FONTDIMEN_COUNT (*tfm_info) + 1; p < parameter; p++)
+ TFM_FONTDIMEN (*tfm_info, p) = 0.0;
+
+ /* Now we have more parameters. */
+ TFM_FONTDIMEN_COUNT (*tfm_info) = parameter;
+ }
+
+ TFM_FONTDIMEN (*tfm_info, parameter) = value;
+}
+
+
+/* Set the `FONTSIZE' parameter of TFM_INFO, if the design size is set. */
+
+void
+tfm_set_fontsize (tfm_global_info_type *tfm_info)
+{
+ if (TFM_DESIGN_SIZE (*tfm_info) != 0.0)
+ tfm_set_fontdimen (tfm_info,
+ TFM_FONTSIZE_PARAMETER, TFM_DESIGN_SIZE (*tfm_info));
+}
diff --git a/tfm/tfm_header.c b/tfm/tfm_header.c
new file mode 100644
index 0000000..33ecd1d
--- /dev/null
+++ b/tfm/tfm_header.c
@@ -0,0 +1,92 @@
+/* tfm_header.c: deal with the TFM header bytes.
+
+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 "tfm.h"
+
+
+/* Set the header in TFM_INFO according to the string S. */
+
+void
+tfm_set_header (string s, tfm_global_info_type *tfm_info)
+{
+ string spec;
+
+ /* If S is empty, we have nothing more to do. */
+ if (s == NULL || *s == 0)
+ return;
+
+ /* Parse the specification string. */
+ for (spec = strtok (s, ","); spec != NULL; spec = strtok (NULL, ","))
+ {
+ string header_item;
+ string value_string = strchr (spec, ':');
+
+ if (value_string == NULL)
+ FATAL1 ("TFM headers look like `<header-item>:<value>', not `%s'",
+ spec);
+
+ header_item = substring (spec, 0, value_string - spec - 1);
+
+ /* Advance past the `:'. */
+ value_string++;
+
+ if (STREQ (header_item, "checksum"))
+ {
+ if (!integer_ok (value_string))
+ FATAL1 ("%s: Invalid integer constant (for checksum)",
+ value_string);
+ TFM_CHECKSUM (*tfm_info) = atoi (value_string);
+ }
+
+ else if (STREQ (header_item, "designsize"))
+ {
+ if (!float_ok (value_string))
+ FATAL1 ("%s: Invalid floating-point constant (for designsize)",
+ value_string);
+ tfm_set_design_size (atof (value_string), tfm_info);
+ }
+
+ else if (STREQ (header_item, "codingscheme"))
+ {
+ unsigned length = strlen (value_string);
+
+ if (strchr (value_string, '(') != NULL
+ || strchr (value_string, ')') != NULL)
+ FATAL1 ("Your coding scheme `%s' may not contain parentheses",
+ value_string);
+
+ if (length > TFM_MAX_CODINGSCHEME_LENGTH)
+ WARNING3 ("Your coding scheme `%s' of length %d will be \
+truncated to %d", value_string, length, TFM_MAX_CODINGSCHEME_LENGTH);
+
+ TFM_CODING_SCHEME (*tfm_info) = xstrdup (value_string);
+ }
+ }
+}
+
+/* Set the design and font size of TFM_INFO to DESIGN_SIZE. */
+
+void
+tfm_set_design_size (real design_size, tfm_global_info_type *tfm_info)
+{
+ TFM_CHECK_DESIGN_SIZE (design_size);
+ TFM_DESIGN_SIZE (*tfm_info) = design_size;
+ tfm_set_fontsize (tfm_info);
+}
diff --git a/tfm/tfm_input.c b/tfm/tfm_input.c
new file mode 100644
index 0000000..5e2c8e1
--- /dev/null
+++ b/tfm/tfm_input.c
@@ -0,0 +1,506 @@
+/* tfm_input.c: read a TFM file.
+
+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 "file-input.h"
+#include "tfm.h"
+
+
+/* If true, print out what we read. */
+static boolean tracing_tfm_input = false;
+
+/* These identify the file we're reading. */
+static FILE *tfm_input_file;
+static string tfm_input_name;
+
+
+/* A copy of the character information. We rely on the `exists' member
+ of all these characters being initialized to zero (i.e., `false') by
+ virtue of the variable being static. */
+static tfm_char_type tfm_char_table[TFM_SIZE];
+
+/* A copy of the global information. */
+static tfm_global_info_type *global_info = NULL;
+
+/* Global information which is only useful to us, not the user. The
+ `..._pos' members record the location of the various components of
+ the file. The member `param_word_count' says how many words of
+ header information are present in this TFM file. */
+typedef struct
+{
+ byte_count_type char_info_pos;
+ byte_count_type width_pos;
+ byte_count_type height_pos;
+ byte_count_type depth_pos;
+ byte_count_type italic_correction_pos;
+ byte_count_type lig_kern_pos;
+ byte_count_type kern_pos;
+ unsigned param_word_count;
+} tfm_header_type;
+
+static tfm_header_type tfm_header;
+
+
+/* Low-level input. These macros call the corresponding routines in
+ kbase, using the static variables for the input file and filename. */
+#define TFM_FTELL() xftell (tfm_input_file, tfm_input_name)
+#define TFM_FSEEK(offset, from_where) \
+ xfseek (tfm_input_file, offset, from_where, tfm_input_name)
+#define TFM_GET_BYTE() get_byte (tfm_input_file, tfm_input_name)
+#define TFM_GET_TWO() get_two (tfm_input_file, tfm_input_name)
+#define TFM_GET_FOUR() get_four (tfm_input_file, tfm_input_name)
+
+
+static tfm_char_type get_char ();
+static string tfm_get_bcpl_string (void);
+static real tfm_get_fix_word (void);
+static void get_lig_kern_program (list_type *, list_type *);
+static real tfm_get_scaled_fix (void);
+static void get_tfm_header (void);
+static void get_tfm_params (void);
+
+/* Routines to start and finish reading a file. (For the user to call.) */
+
+boolean
+tfm_open_input_file (string filename)
+{
+ if (tfm_input_file != NULL)
+ FATAL2 ("tfm_open_input_file: Attempt to open `%s', but `%s' is
+already open", filename, tfm_input_name);
+
+ tfm_input_name = filename;
+ tfm_input_file = fopen (filename, "r");
+
+ return tfm_input_file != NULL;
+}
+
+
+void
+tfm_close_input_file ()
+{
+ assert (tfm_input_file != NULL);
+
+ xfclose (tfm_input_file, tfm_input_name);
+
+ tfm_input_file = NULL;
+ tfm_input_name = NULL;
+ global_info = NULL;
+}
+
+
+/* This is just avoids all callers having to keep a global around with
+ the TFM name they used. */
+
+string
+tfm_input_filename ()
+{
+ if (tfm_input_file == NULL)
+ return NULL;
+
+ return tfm_input_name;
+}
+
+/* Some of the global information comes from the beginning of the file,
+ and some from the end. If we've already read the information from
+ the file, we don't do it again. */
+
+tfm_global_info_type
+tfm_get_global_info ()
+{
+ assert (tfm_input_file != NULL);
+
+ /* Only read the file once. */
+ if (global_info != NULL) return *global_info;
+
+ global_info = XTALLOC1 (tfm_global_info_type);
+ get_tfm_header ();
+ get_tfm_params ();
+
+ return *global_info;
+}
+
+
+/* Now comes convenience routines to get particular parts of the global
+ info. */
+
+unsigned
+tfm_get_checksum ()
+{
+ (void) tfm_get_global_info ();
+ return TFM_CHECKSUM (*global_info);
+}
+
+
+double
+tfm_get_design_size ()
+{
+ (void) tfm_get_global_info ();
+ return TFM_DESIGN_SIZE (*global_info);
+}
+
+
+string
+tfm_get_coding_scheme ()
+{
+ (void) tfm_get_global_info ();
+ return TFM_CODING_SCHEME (*global_info);
+}
+
+
+double
+tfm_get_interword_space ()
+{
+ (void) tfm_get_global_info ();
+ return TFM_FONTDIMEN (*global_info, TFM_SPACE_PARAMETER);
+}
+
+
+double
+tfm_get_x_height ()
+{
+ (void) tfm_get_global_info ();
+ return TFM_FONTDIMEN (*global_info, TFM_XHEIGHT_PARAMETER);
+}
+
+
+/* Here we read the information at the beginning of the file. We store
+ the result into the static variables `global_info' and
+ `tfm_header'. */
+
+static void
+get_tfm_header ()
+{
+ two_bytes file_length, header_length;
+ two_bytes width_word_count, height_word_count, depth_word_count;
+ two_bytes italic_correction_word_count, lig_kern_word_count;
+ two_bytes kern_word_count, extensible_word_count;
+
+ /* The header is at the beginning of the file, naturally. */
+ TFM_FSEEK (0, SEEK_SET);
+
+ file_length = TFM_GET_TWO ();
+ header_length = TFM_GET_TWO ();
+
+ global_info->first_charcode = TFM_GET_TWO ();
+ global_info->last_charcode = TFM_GET_TWO ();
+ width_word_count = TFM_GET_TWO ();
+ height_word_count = TFM_GET_TWO ();
+ depth_word_count = TFM_GET_TWO ();
+ italic_correction_word_count = TFM_GET_TWO ();
+ lig_kern_word_count = TFM_GET_TWO ();
+ kern_word_count = TFM_GET_TWO ();
+ extensible_word_count = TFM_GET_TWO ();
+ tfm_header.param_word_count = TFM_GET_TWO ();
+ TFM_FONTDIMEN_COUNT (*global_info) = tfm_header.param_word_count;
+
+ tfm_header.char_info_pos = (6 + header_length) * 4;
+ tfm_header.width_pos = tfm_header.char_info_pos
+ + (global_info->last_charcode
+ - global_info->first_charcode + 1) * 4;
+ tfm_header.height_pos = tfm_header.width_pos + width_word_count * 4;
+ tfm_header.depth_pos = tfm_header.height_pos + height_word_count * 4;
+ tfm_header.italic_correction_pos = tfm_header.depth_pos
+ + depth_word_count * 4;
+ tfm_header.lig_kern_pos = tfm_header.italic_correction_pos
+ + italic_correction_word_count * 4;
+ tfm_header.kern_pos = tfm_header.lig_kern_pos + lig_kern_word_count * 4;
+ /* We don't care about the extensible table. */
+
+ if (header_length < 2)
+ FATAL2 ("TFM header of `%s' has only %u word(s)", tfm_input_name,
+ header_length);
+
+ TFM_CHECKSUM (*global_info) = TFM_GET_FOUR ();
+ TFM_DESIGN_SIZE (*global_info) = tfm_get_fix_word ();
+
+ /* Although the coding scheme might be interesting to the caller, the
+ font family and face byte probably aren't. So we don't read them. */
+ TFM_CODING_SCHEME (*global_info)
+ = header_length > 2 ? tfm_get_bcpl_string () : "unspecified";
+
+ if (tracing_tfm_input)
+ printf ("TFM checksum = %u, design_size = %fpt, coding scheme = `%s'.\n",
+ TFM_CHECKSUM (*global_info),
+ TFM_DESIGN_SIZE (*global_info),
+ TFM_CODING_SCHEME (*global_info));
+}
+
+
+/* Although TFM files are only usable by TeX if they have at least seven
+ parameters, that is not a requirement of the file format itself, so
+ we don't impose it. And they can have many more than seven, of
+ course. We do impose a limit of TFM_MAX_FONT_PARAMETERS. We assume
+ that `tfm_header' has already been filled in. */
+
+static void
+get_tfm_params ()
+{
+ unsigned this_param;
+
+ /* If we have no font parameters at all, we're done. */
+ if (tfm_header.param_word_count == 0)
+ return;
+
+ /* Move to the beginning of the parameter table in the file. */
+ TFM_FSEEK (-4 * tfm_header.param_word_count, SEEK_END);
+
+ /* It's unlikely but possible that this TFM file has more fontdimens
+ than we can deal with. */
+ if (tfm_header.param_word_count > TFM_MAX_FONTDIMENS)
+ {
+ WARNING3 ("%s: TFM file has %u parameters, which is more than the
+%u I can handle",
+ tfm_input_name, tfm_header.param_word_count,
+ TFM_MAX_FONTDIMENS);
+ tfm_header.param_word_count = TFM_MAX_FONTDIMENS;
+ }
+
+ /* The first parameter is different than all the rest, because it
+ isn't scaled by the design size. */
+ TFM_FONTDIMEN (*global_info, TFM_SLANT_PARAMETER) = tfm_get_fix_word ();
+
+ for (this_param = 2; this_param <= tfm_header.param_word_count;
+ this_param++)
+ TFM_FONTDIMEN (*global_info, this_param) = tfm_get_scaled_fix ();
+
+ if (tracing_tfm_input)
+ {
+ for (this_param = 1; this_param <= tfm_header.param_word_count;
+ this_param++)
+ printf ("TFM parameter %d: %.3f", this_param,
+ TFM_FONTDIMEN (*global_info, this_param));
+ }
+}
+
+/* Read every character in the TFM file, storing the result in the
+ static `tfm_char_table'. We return a copy of that variable. */
+
+tfm_char_type *
+tfm_get_chars ()
+{
+ tfm_char_type *tfm_chars;
+ unsigned this_char;
+
+ assert (tfm_input_file != NULL);
+
+ tfm_get_global_info ();
+
+ for (this_char = global_info->first_charcode;
+ this_char <= global_info->last_charcode;
+ this_char++)
+ /* This fills in the `tfm_char_table' global. */
+ (void) tfm_get_char (this_char);
+
+ /* Return a copy, so our information can't get corrupted. */
+ tfm_chars = XTALLOC (TFM_SIZE, tfm_char_type);
+ memcpy (tfm_chars, tfm_char_table, sizeof (tfm_char_table));
+ return tfm_chars;
+}
+
+
+/* Read the character CODE. If the character doesn't exist, return
+ NULL. If it does, save the information in `tfm_char_table', as well
+ as returning it. */
+
+tfm_char_type *
+tfm_get_char (charcode_type code)
+{
+ assert (tfm_input_file != NULL);
+
+ tfm_get_global_info ();
+
+ /* If the character is outside the declared bounds in the file, don't
+ try to read it. Just return NULL. */
+ if (code < global_info->first_charcode
+ || code > global_info->last_charcode)
+ return NULL;
+
+ /* Move to the appropriate place in the `char_info' array. */
+ TFM_FSEEK (tfm_header.char_info_pos
+ + (code - global_info->first_charcode) * 4,
+ SEEK_SET);
+
+ /* Read the character. */
+ tfm_char_table[code] = get_char ();
+
+ /* If it exists, return a pointer to it. We return a copy, so our
+ information can't get corrupted. */
+ if (!TFM_CHAR_EXISTS (tfm_char_table[code]))
+ return NULL;
+ else
+ {
+ tfm_char_type *c = XTALLOC1 (tfm_char_type);
+
+ TFM_CHARCODE (tfm_char_table[code]) = code;
+ *c = tfm_char_table[code];
+ return c;
+ }
+}
+
+
+/* We assume we are positioned at the beginning of a `char_info' word.
+ We read that word to get the indexes into the dimension tables; then
+ we go read the tables to get the values (if the character exists). */
+
+static tfm_char_type
+get_char ()
+{
+ one_byte width_index, height_index, depth_index, italic_correction_index;
+ one_byte packed;
+ one_byte tag, remainder;
+ tfm_char_type tfm_char;
+
+ /* Read the char_info word. */
+ width_index = TFM_GET_BYTE ();
+
+ packed = TFM_GET_BYTE ();
+ height_index = (packed & 0xf0) >> 4;
+ depth_index = packed & 0x0f;
+
+ packed = TFM_GET_BYTE ();
+ italic_correction_index = (packed & 0xfc) >> 6;
+ tag = packed & 0x3;
+
+ remainder = TFM_GET_BYTE ();
+
+ tfm_char = tfm_new_char ();
+
+#define GET_CHAR_DIMEN(d) \
+ if (d##_index != 0) \
+ { \
+ TFM_FSEEK (tfm_header.##d##_pos + d##_index*4, SEEK_SET); \
+ tfm_char.fix_##d = TFM_GET_FOUR (); \
+ tfm_char.##d = fix_to_real (tfm_char.fix_##d) \
+ * global_info->design_size; \
+ }
+
+ GET_CHAR_DIMEN (width);
+ GET_CHAR_DIMEN (height);
+ GET_CHAR_DIMEN (depth);
+ GET_CHAR_DIMEN (italic_correction);
+
+ /* The other condition for a character existing is that it be between
+ the first and last character codes given in the header. We've
+ already assumed that's true (or we couldn't be positioned at a
+ `char_info_word'). */
+ TFM_CHAR_EXISTS (tfm_char) = width_index != 0;
+
+ if (tracing_tfm_input)
+ {
+ printf (" width = %f, height = %f, ", tfm_char.width, tfm_char.height);
+ printf ("depth = %f, ic = %f.\n", tfm_char.depth,
+ tfm_char.italic_correction);
+ }
+
+ if (tag == 1)
+ {
+ TFM_FSEEK (tfm_header.lig_kern_pos + remainder * 4, SEEK_SET);
+ get_lig_kern_program (&(tfm_char.ligature), &(tfm_char.kern));
+ }
+
+ /* We don't handle the other tags. */
+ return tfm_char;
+}
+
+/* Read a ligature/kern program at the current position, storing the
+ result into *LIGATURE and *KERN. We don't distinguish all the kinds
+ of ligatures that Metafont can output. */
+
+#define STOP_FLAG 128
+#define KERN_FLAG 128
+
+static void
+get_lig_kern_program (list_type *ligature, list_type *kern)
+{
+ boolean end_of_program;
+
+ assert (ligature != NULL && kern != NULL);
+
+ do
+ {
+ one_byte next_char;
+ boolean kern_step;
+ one_byte remainder;
+
+ end_of_program = TFM_GET_BYTE () >= STOP_FLAG;
+
+ next_char = TFM_GET_BYTE ();
+ kern_step = TFM_GET_BYTE () >= KERN_FLAG;
+ remainder = TFM_GET_BYTE ();
+
+ if (tracing_tfm_input)
+ printf (" if next = %u (%c), ", next_char, next_char);
+
+ if (kern_step)
+ {
+ byte_count_type old_pos = TFM_FTELL ();
+ tfm_kern_type *kern_element = LIST_TAPPEND (kern, tfm_kern_type);
+
+ kern_element->character = next_char;
+
+ TFM_FSEEK (tfm_header.kern_pos + remainder * 4, SEEK_SET);
+ kern_element->kern = tfm_get_scaled_fix ();
+ TFM_FSEEK (old_pos, SEEK_SET);
+
+ if (tracing_tfm_input)
+ printf ("kern %f.\n", kern_element->kern);
+ }
+ else
+ {
+ tfm_ligature_type *ligature_element
+ = LIST_TAPPEND (ligature, tfm_ligature_type);
+
+ ligature_element->character = next_char;
+ ligature_element->ligature = remainder;
+
+ if (tracing_tfm_input)
+ printf ("ligature %d (hex %x).\n",
+ ligature_element->ligature, ligature_element->ligature);
+ }
+ } while (!end_of_program);
+}
+
+/* Most quantities are fixed-point fractions. */
+
+static real
+tfm_get_fix_word ()
+{
+ return fix_to_real (TFM_GET_FOUR ());
+}
+
+
+/* Dimensions are a `fix_word' scaled by the design size. */
+
+static real
+tfm_get_scaled_fix ()
+{
+ return tfm_get_fix_word () * global_info->design_size;
+}
+
+
+static string
+tfm_get_bcpl_string ()
+{
+ unsigned string_length = TFM_GET_BYTE ();
+ string s = get_n_bytes (string_length, tfm_input_file, tfm_input_name);
+ s = xrealloc (s, string_length + 1);
+ s[string_length] = 0;
+
+ return s;
+}
diff --git a/tfm/tfm_kern.c b/tfm/tfm_kern.c
new file mode 100644
index 0000000..414c892
--- /dev/null
+++ b/tfm/tfm_kern.c
@@ -0,0 +1,75 @@
+/* tfm_kern.c: deal with TFM kern lists.
+
+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 "list.h"
+#include "tfm.h"
+
+
+/* The character RIGHT may or may not be in the list of kerns already. */
+
+void
+tfm_set_kern (list_type *kern_table, charcode_type right, real k)
+{
+ unsigned this_right;
+ tfm_kern_type *new_kern;
+
+ assert (kern_table != NULL);
+
+ for (this_right = 0; this_right < LIST_SIZE (*kern_table); this_right++)
+ {
+ tfm_kern_type *kern = LIST_ELT (*kern_table, this_right);
+
+ if (kern->character == right)
+ { /* Already there, just replace the value. */
+ kern->kern = k;
+ return;
+ }
+ }
+
+ /* RIGHT wasn't in the existing list. Add it to the end. */
+ new_kern = LIST_TAPPEND (kern_table, tfm_kern_type);
+ new_kern->character = right;
+ new_kern->kern = k;
+}
+
+/* Find the kern between the characters LEFT and RIGHT. (Return zero if
+ none such.) */
+
+real
+tfm_get_kern (tfm_char_type left, charcode_type right)
+{
+ list_type kern_table;
+ unsigned r;
+
+ if (!TFM_CHAR_EXISTS (left))
+ return 0.0;
+
+ kern_table = left.kern;
+
+ for (r = 0; r < LIST_SIZE (kern_table); r++)
+ {
+ tfm_kern_type *kern = LIST_ELT (kern_table, r);
+
+ if (kern->character == right)
+ return kern->kern;
+ }
+
+ return 0.0;
+}
diff --git a/tfm/tfm_ligature.c b/tfm/tfm_ligature.c
new file mode 100644
index 0000000..4e3db36
--- /dev/null
+++ b/tfm/tfm_ligature.c
@@ -0,0 +1,48 @@
+/* tfm_ligature.c: deal with TFM ligature lists.
+
+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 "tfm.h"
+
+
+/* The character RIGHT may or may not be in LIG_LIST already.
+ Update it if so, otherwise add it. */
+
+void
+tfm_set_ligature (list_type *lig_list, charcode_type right, charcode_type l)
+{
+ unsigned this_right;
+ tfm_ligature_type *new_ligature;
+
+ for (this_right = 0; this_right < LIST_SIZE (*lig_list); this_right++)
+ {
+ tfm_ligature_type *ligature = LIST_ELT (*lig_list, this_right);
+
+ if (ligature->character == right)
+ {
+ ligature->ligature = l;
+ return;
+ }
+ }
+
+ /* RIGHT wasn't in the existing list. Add it to the end. */
+ new_ligature = LIST_TAPPEND (lig_list, tfm_ligature_type);
+ new_ligature->character = right;
+ new_ligature->ligature = l;
+}
diff --git a/tfm/tfm_output.c b/tfm/tfm_output.c
new file mode 100644
index 0000000..2ff7cb4
--- /dev/null
+++ b/tfm/tfm_output.c
@@ -0,0 +1,371 @@
+/* tfm_output.c: write property list files (a human-readable equivalent
+ of TFM files), and convert them to TFM format. PL format is
+ described in the source code to the TeX utility PLtoTF, by Donald
+ Knuth.
+
+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 <kpathsea/concatn.h>
+
+#include "file-output.h"
+#include "report.h"
+#include "tfm.h"
+
+
+/* These identify the output file. (Only one may be open at a time.) */
+static FILE *pl_output_file;
+static string pl_output_filename;
+
+/* The design size for the font is used to scale almost all numbers in
+ the file. It is in units of printer's points. */
+static real design_size;
+
+
+/* Subroutines for output. */
+static void put_lig_kern_info (tfm_char_type);
+
+
+/* Routines to actually write the properties. */
+static void start_prop_list (string);
+static void finish_prop_list (void);
+static void start_integer_prop_list (string, unsigned);
+static void put_integer_prop (string, unsigned);
+static void put_octal_prop (string, unsigned);
+static void put_real_prop (string, real);
+static void put_scaled_prop (string, real);
+static void put_string_prop (string, string);
+static void put_indentation (void);
+
+static void put_lig_prop (tfm_ligature_type *);
+static void put_kern_prop (tfm_kern_type *);
+
+/* Routines to start and finish reading a file. (For the user to call.) */
+
+boolean
+tfm_open_pl_output_file (string filename)
+{
+ assert (pl_output_file == NULL);
+
+ pl_output_filename = filename;
+ pl_output_file = fopen (filename, "w");
+
+ return pl_output_file != NULL;
+}
+
+
+void
+tfm_close_pl_output_file ()
+{
+ assert (pl_output_file != NULL);
+
+ xfclose (pl_output_file, pl_output_filename);
+
+ pl_output_file = NULL;
+ pl_output_filename = NULL;
+}
+
+
+/* An argument to allow the PL file to be deleted might be in order
+ here, and maybe returning the exit status. If TFM_NAME is NULL, we
+ replace any suffix on `pl_output_filename' with `tfm' and use that.
+ Otherwise, we use exactly TFM_NAME. */
+
+void
+tfm_convert_pl (string tfm_name, boolean verbose)
+{
+ string cmd;
+ int status;
+ string arg = verbose ? "" : " >/dev/null 2>&1";
+
+ if (pl_output_filename == NULL)
+ {
+ fprintf (stderr, "No PL output file to convert to TFM format.\n");
+ fprintf (stderr, "(Perhaps you called tfm_close_pl_output_file?)\n");
+ return;
+ }
+
+ if (tfm_name == NULL)
+ tfm_name = make_suffix (pl_output_filename, "tfm");
+
+ cmd = concatn ("pltotf ", pl_output_filename, " ", tfm_name, arg, NULL);
+
+ /* Make sure that all data we have written will be read. */
+ if (fflush (pl_output_file) == EOF)
+ FATAL1 ("%s: could not flush", pl_output_filename);
+
+ /* Convert to TFM. */
+ if (verbose)
+ printf ("Executing `%s'.\n", cmd);
+ status = system (cmd);
+
+ free (cmd);
+
+ if (verbose && status != 0)
+ printf ("Exit status = %d.\n", status);
+}
+
+/* Return an initialized structure. */
+
+tfm_global_info_type
+tfm_init_global_info ()
+{
+ tfm_global_info_type info;
+ unsigned this_param;
+
+ TFM_CHECKSUM (info) = 0;
+ TFM_DESIGN_SIZE (info) = 0.0;
+ TFM_CODING_SCHEME (info) = "unspecified";
+ TFM_FONTDIMEN_COUNT (info) = 0;
+ for (this_param = 1; this_param <= TFM_MAX_FONTDIMENS; this_param++)
+ TFM_FONTDIMEN (info, this_param) = 0.0;
+
+ return info;
+}
+
+
+/* Output the fontwide information in INFO. */
+
+void
+tfm_put_global_info (tfm_global_info_type info)
+{
+ unsigned this_param;
+
+ /* Save the design size so we can scale the other reals. */
+ design_size = TFM_DESIGN_SIZE (info);
+
+ put_string_prop ("comment", now ());
+ put_real_prop ("designsize", design_size);
+ put_string_prop ("codingscheme", TFM_CODING_SCHEME (info));
+
+ /* If the checksum is zero, don't output it; then PLtoTF will compute
+ one for us. */
+ if (TFM_CHECKSUM (info) != 0)
+ put_octal_prop ("checksum", TFM_CHECKSUM (info));
+
+ start_prop_list ("fontdimen");
+
+ for (this_param = 1; this_param <= TFM_FONTDIMEN_COUNT (info);
+ this_param++)
+ {
+ real param_value = TFM_FONTDIMEN (info, this_param);
+
+ /* Parameter #1 (the font slant) is different than all the
+ rest, because it's not scaled by the design size. */
+ if (this_param == 1)
+ put_real_prop ("slant", param_value);
+ else
+ put_scaled_prop (concat ("parameter d ", utoa (this_param)),
+ param_value);
+ }
+
+ finish_prop_list ();
+}
+
+
+/* We don't bother to keep track of the `nextlarger' and `varchar'
+ properties, which are used in TeX's math mode.
+
+ TFM_CHAR should be an array of (exactly) `TFM_SIZE' elements. */
+
+void
+tfm_put_chars (tfm_char_type *tfm_char)
+{
+ unsigned this_char;
+
+ for (this_char = 0; this_char < TFM_SIZE; this_char++, tfm_char++)
+ {
+ if (TFM_CHAR_EXISTS (*tfm_char))
+ tfm_put_char (*tfm_char);
+ }
+}
+
+
+/* Output the single character C to the PL file. Although the width and
+ height are not zero often enough to matter, the depth and italic
+ correction are often zero, so we may as well check first. */
+
+void
+tfm_put_char (tfm_char_type c)
+{
+ /* If we're being called, the character should exist. */
+ assert (TFM_CHAR_EXISTS (c));
+
+ start_integer_prop_list ("character", TFM_CHARCODE (c));
+
+ put_scaled_prop ("charwd", TFM_WIDTH (c));
+ put_scaled_prop ("charht", TFM_HEIGHT (c));
+
+ if (!epsilon_equal (TFM_DEPTH (c), 0.0))
+ put_scaled_prop ("chardp", TFM_DEPTH (c));
+
+ if (!epsilon_equal (TFM_ITALIC_CORRECTION (c), 0.0))
+ put_scaled_prop ("charic", TFM_ITALIC_CORRECTION (c));
+
+ finish_prop_list ();
+
+ put_lig_kern_info (c);
+}
+
+/* Output any ligature/kern information in the tfm character C. */
+
+static void
+put_lig_kern_info (tfm_char_type c)
+{
+ unsigned ligature_count = LIST_SIZE (c.ligature);
+ unsigned kern_count = LIST_SIZE (c.kern);
+
+ assert (TFM_CHAR_EXISTS (c));
+
+ /* Do nothing if there's neither ligatures nor kerns. */
+ if (ligature_count > 0 || kern_count > 0)
+ {
+ unsigned step;
+
+ start_prop_list ("ligtable");
+ put_integer_prop ("label", TFM_CHARCODE (c));
+
+ /* We shouldn't output a lig/kern step unless all the characters
+ involved exist. But we don't know which characters exist until
+ the end, when we convert to PL. So for now, we just output
+ everything we get, instead of saving the information away. It
+ doesn't actually affect the validity of the results -- it's
+ just that PLtoTF might give some warnings. */
+ for (step = 0; step < ligature_count; step++)
+ {
+ tfm_ligature_type *lig = LIST_ELT (c.ligature, step);
+#if 0
+ if (TFM_CHAR_EXISTS (tfm_char[lig->character])
+ && TFM_CHAR_EXISTS (tfm_char[lig->ligature]))
+#endif
+ put_lig_prop (lig);
+ }
+
+ for (step = 0; step < kern_count; step++)
+ {
+ tfm_kern_type *k = LIST_ELT (c.kern, step);
+#if 0
+ if (TFM_CHAR_EXISTS (tfm_char[k->character]))
+#endif
+ put_kern_prop (k);
+ }
+
+ put_string_prop ("stop", "");
+ finish_prop_list ();
+ }
+}
+
+/* It makes the output more readable to make the property lists
+ indented. */
+
+static unsigned indentation = 0;
+#define INDENT_INCR 2
+
+
+static void
+start_prop_list (string prop_list_name)
+{
+ put_indentation ();
+ fprintf (pl_output_file, "(%s\n", prop_list_name);
+ indentation += INDENT_INCR;
+}
+
+
+static void
+start_integer_prop_list (string prop, unsigned v)
+{
+ put_indentation ();
+ fprintf (pl_output_file, "(%s d %u\n", prop, v);
+ indentation += INDENT_INCR;
+}
+
+
+static void
+finish_prop_list ()
+{
+ put_indentation ();
+ fprintf (pl_output_file, ")\n");
+ indentation -= INDENT_INCR;
+}
+
+
+static void
+put_lig_prop (tfm_ligature_type *lig)
+{
+ put_indentation ();
+ fprintf (pl_output_file, "(lig d %u d %u)\n",
+ lig->character, lig->ligature);
+}
+
+
+static void
+put_kern_prop (tfm_kern_type *kern)
+{
+ put_indentation ();
+ fprintf (pl_output_file, "(krn d %u r %f)\n",
+ kern->character, kern->kern / design_size);
+}
+
+
+static void
+put_integer_prop (string prop_name, unsigned v)
+{
+ put_indentation ();
+ fprintf (pl_output_file, "(%s d %u)\n", prop_name, v);
+}
+
+
+static void
+put_octal_prop (string prop_name, unsigned v)
+{
+ put_indentation ();
+ fprintf (pl_output_file, "(%s o %o)\n", prop_name, v);
+}
+
+
+static void
+put_scaled_prop (string prop_name, real v)
+{
+ put_real_prop (prop_name, v / design_size);
+}
+
+
+static void
+put_real_prop (string prop_name, real v)
+{
+ put_indentation ();
+ fprintf (pl_output_file, "(%s r %f)\n", prop_name, v);
+}
+
+
+static void
+put_string_prop (string prop_name, string v)
+{
+ put_indentation ();
+ fprintf (pl_output_file, "(%s%s%s)\n",
+ prop_name, strlen (v) > 0 ? " " : "", v);
+}
+
+
+static void
+put_indentation ()
+{
+ unsigned this_space;
+
+ for (this_space = 0; this_space < indentation; this_space++)
+ fprintf (pl_output_file, " ");
+}