summaryrefslogtreecommitdiff
path: root/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont
diff options
context:
space:
mode:
authorPeter Breitenlohner <peb@mppmu.mpg.de>2012-09-25 11:35:23 +0000
committerPeter Breitenlohner <peb@mppmu.mpg.de>2012-09-25 11:35:23 +0000
commitf54f97c9d6ff947e8761f0c41662f50155ca630d (patch)
treee5b433dd66f22de02b57e1c66e25e437c77ea9a7 /Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont
parentd9c42331a8d11fdd45efc39195eb8fe3db79e394 (diff)
lcdf-typetools 2.95
git-svn-id: svn://tug.org/texlive/trunk@27803 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont')
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/Makefile.am43
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/Makefile.in612
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/afm.cc586
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/afmparse.cc365
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/afmw.cc190
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/amfm.cc850
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/cff.cc1689
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/encoding.cc29
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/findmet.cc321
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/metrics.cc130
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/otf.cc1496
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/otfcmap.cc480
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/otfdata.cc43
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/otfdescrip.cc717
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/otfgpos.cc328
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/otfgsub.cc1285
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/otfname.cc194
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/otfos2.cc47
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/otfpost.cc212
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/pairop.cc153
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/psres.cc419
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1bounds.cc161
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1cs.cc370
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1csgen.cc633
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1font.cc914
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1fontskel.cc433
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1interp.cc1376
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1item.cc861
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1mm.cc392
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1rw.cc613
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1unparser.cc137
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/ttfcs.cc212
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/ttfhead.cc69
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/ttfkern.cc116
34 files changed, 16476 insertions, 0 deletions
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/Makefile.am b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/Makefile.am
new file mode 100644
index 00000000000..eb09a9686ad
--- /dev/null
+++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/Makefile.am
@@ -0,0 +1,43 @@
+## Process this file with automake to produce Makefile.in
+AUTOMAKE_OPTIONS = foreign
+
+noinst_LIBRARIES = libefont.a
+
+libefont_a_SOURCES = \
+ afm.cc \
+ afmparse.cc \
+ afmw.cc \
+ amfm.cc \
+ cff.cc \
+ encoding.cc \
+ findmet.cc \
+ metrics.cc \
+ otf.cc \
+ otfcmap.cc \
+ otfdata.cc \
+ otfdescrip.cc \
+ otfgpos.cc \
+ otfgsub.cc \
+ otfname.cc \
+ otfos2.cc \
+ otfpost.cc \
+ pairop.cc \
+ psres.cc \
+ t1bounds.cc \
+ t1cs.cc \
+ t1csgen.cc \
+ t1interp.cc \
+ t1item.cc \
+ t1font.cc \
+ t1fontskel.cc \
+ t1mm.cc \
+ t1rw.cc \
+ t1unparser.cc \
+ ttfcs.cc \
+ ttfhead.cc \
+ ttfkern.cc
+
+libefont_a_LIBADD = @TEMPLATE_OBJS@
+CLEANFILES = @TEMPLATE_OBJS@
+
+INCLUDES = -I$(srcdir)/../include
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/Makefile.in b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/Makefile.in
new file mode 100644
index 00000000000..88efa389fb0
--- /dev/null
+++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/Makefile.in
@@ -0,0 +1,612 @@
+# Makefile.in generated by automake 1.12.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2012 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__make_dryrun = \
+ { \
+ am__dry=no; \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+ *) \
+ for am__flg in $$MAKEFLAGS; do \
+ case $$am__flg in \
+ *=*|--*) ;; \
+ *n*) am__dry=yes; break;; \
+ esac; \
+ done;; \
+ esac; \
+ test $$am__dry = yes; \
+ }
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = lcdf-typetools-2.95/libefont
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ $(top_srcdir)/../../build-aux/depcomp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_cxx_template_objs.m4 \
+ $(top_srcdir)/../../m4/kpse-common.m4 \
+ $(top_srcdir)/../../m4/kpse-cxx-hack.m4 \
+ $(top_srcdir)/../../m4/kpse-kpathsea-flags.m4 \
+ $(top_srcdir)/../../m4/kpse-warnings.m4 \
+ $(top_srcdir)/../../m4/kpse-win32.m4 \
+ $(top_srcdir)/../../m4/libtool.m4 \
+ $(top_srcdir)/../../m4/ltoptions.m4 \
+ $(top_srcdir)/../../m4/ltsugar.m4 \
+ $(top_srcdir)/../../m4/ltversion.m4 \
+ $(top_srcdir)/../../m4/lt~obsolete.m4 $(top_srcdir)/version.ac \
+ $(top_srcdir)/ac/lcdf-typetools.ac $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/autoconf.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+ARFLAGS = cru
+libefont_a_AR = $(AR) $(ARFLAGS)
+libefont_a_DEPENDENCIES =
+am_libefont_a_OBJECTS = afm.$(OBJEXT) afmparse.$(OBJEXT) \
+ afmw.$(OBJEXT) amfm.$(OBJEXT) cff.$(OBJEXT) encoding.$(OBJEXT) \
+ findmet.$(OBJEXT) metrics.$(OBJEXT) otf.$(OBJEXT) \
+ otfcmap.$(OBJEXT) otfdata.$(OBJEXT) otfdescrip.$(OBJEXT) \
+ otfgpos.$(OBJEXT) otfgsub.$(OBJEXT) otfname.$(OBJEXT) \
+ otfos2.$(OBJEXT) otfpost.$(OBJEXT) pairop.$(OBJEXT) \
+ psres.$(OBJEXT) t1bounds.$(OBJEXT) t1cs.$(OBJEXT) \
+ t1csgen.$(OBJEXT) t1interp.$(OBJEXT) t1item.$(OBJEXT) \
+ t1font.$(OBJEXT) t1fontskel.$(OBJEXT) t1mm.$(OBJEXT) \
+ t1rw.$(OBJEXT) t1unparser.$(OBJEXT) ttfcs.$(OBJEXT) \
+ ttfhead.$(OBJEXT) ttfkern.$(OBJEXT)
+libefont_a_OBJECTS = $(am_libefont_a_OBJECTS)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/../../build-aux/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libefont_a_SOURCES)
+DIST_SOURCES = $(libefont_a_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CXXLD = @CXXLD@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+KPATHSEA_DEPEND = @KPATHSEA_DEPEND@
+KPATHSEA_INCLUDES = @KPATHSEA_INCLUDES@
+KPATHSEA_LIBS = @KPATHSEA_LIBS@
+LCDF_TYPETOOLS_TREE = @LCDF_TYPETOOLS_TREE@
+LCDF_TYPETOOLS_VERSION = @LCDF_TYPETOOLS_VERSION@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SELECTED_SUBDIRS = @SELECTED_SUBDIRS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TEMPLATE_OBJS = @TEMPLATE_OBJS@
+VERSION = @VERSION@
+WARNING_CFLAGS = @WARNING_CFLAGS@
+WARNING_CXXFLAGS = @WARNING_CXXFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+encdir = @encdir@
+exec_prefix = @exec_prefix@
+glyphlistdir = @glyphlistdir@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AUTOMAKE_OPTIONS = foreign
+noinst_LIBRARIES = libefont.a
+libefont_a_SOURCES = \
+ afm.cc \
+ afmparse.cc \
+ afmw.cc \
+ amfm.cc \
+ cff.cc \
+ encoding.cc \
+ findmet.cc \
+ metrics.cc \
+ otf.cc \
+ otfcmap.cc \
+ otfdata.cc \
+ otfdescrip.cc \
+ otfgpos.cc \
+ otfgsub.cc \
+ otfname.cc \
+ otfos2.cc \
+ otfpost.cc \
+ pairop.cc \
+ psres.cc \
+ t1bounds.cc \
+ t1cs.cc \
+ t1csgen.cc \
+ t1interp.cc \
+ t1item.cc \
+ t1font.cc \
+ t1fontskel.cc \
+ t1mm.cc \
+ t1rw.cc \
+ t1unparser.cc \
+ ttfcs.cc \
+ ttfhead.cc \
+ ttfkern.cc
+
+libefont_a_LIBADD = @TEMPLATE_OBJS@
+CLEANFILES = @TEMPLATE_OBJS@
+INCLUDES = -I$(srcdir)/../include
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cc .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lcdf-typetools-2.95/libefont/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign lcdf-typetools-2.95/libefont/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+libefont.a: $(libefont_a_OBJECTS) $(libefont_a_DEPENDENCIES) $(EXTRA_libefont_a_DEPENDENCIES)
+ -rm -f libefont.a
+ $(libefont_a_AR) libefont.a $(libefont_a_OBJECTS) $(libefont_a_LIBADD)
+ $(RANLIB) libefont.a
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afm.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afmparse.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afmw.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amfm.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cff.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encoding.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/findmet.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/metrics.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/otf.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/otfcmap.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/otfdata.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/otfdescrip.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/otfgpos.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/otfgsub.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/otfname.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/otfos2.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/otfpost.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pairop.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/psres.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t1bounds.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t1cs.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t1csgen.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t1font.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t1fontskel.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t1interp.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t1item.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t1mm.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t1rw.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t1unparser.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ttfcs.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ttfhead.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ttfkern.Po@am__quote@
+
+.cc.o:
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cc.lo:
+@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+cscopelist: $(HEADERS) $(SOURCES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LIBRARIES)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLIBRARIES cscopelist ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/afm.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/afm.cc
new file mode 100644
index 00000000000..9705f91c97f
--- /dev/null
+++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/afm.cc
@@ -0,0 +1,586 @@
+// -*- related-file-name: "../include/efont/afm.hh" -*-
+
+/* afm.{cc,hh} -- Adobe Font Metrics files
+ *
+ * Copyright (c) 1998-2012 Eddie Kohler
+ *
+ * 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 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <efont/afm.hh>
+#include <efont/afmparse.hh>
+#include <efont/t1cs.hh> /* for UNKDOUBLE */
+#include <lcdf/error.hh>
+#include <ctype.h>
+#include <assert.h>
+namespace Efont {
+
+AfmReader::AfmReader(AfmParser &parser, Metrics *afm, AfmMetricsXt *afm_xt,
+ ErrorHandler *errh)
+ : _afm(afm), _afm_xt(afm_xt), _l(parser),
+ _composite_warned(false), _metrics_sets_warned(false), _y_width_warned(0)
+{
+ _errh = errh ? errh : ErrorHandler::silent_handler();
+}
+
+Metrics *
+AfmReader::read(Slurper &slurp, ErrorHandler *errh)
+{
+ AfmParser p(slurp);
+ if (!p.ok())
+ return 0;
+
+ Metrics *afm = new Metrics;
+ AfmMetricsXt *afm_xt = new AfmMetricsXt;
+ afm->add_xt(afm_xt);
+ AfmReader reader(p, afm, afm_xt, errh);
+
+ if (!reader.read()) {
+ delete afm;
+ return 0;
+ } else
+ return afm;
+}
+
+Metrics *
+AfmReader::read(const Filename &fn, ErrorHandler *errh)
+{
+ Slurper slurpy(fn);
+ return read(slurpy, errh);
+}
+
+
+void
+AfmReader::lwarning(const char *format, ...) const
+{
+ va_list val;
+ va_start(val, format);
+ _errh->vxmessage(_l.landmark(), ErrorHandler::e_warning, format, val);
+ va_end(val);
+}
+
+void
+AfmReader::lerror(const char *format, ...) const
+{
+ va_list val;
+ va_start(val, format);
+ _errh->vxmessage(_l.landmark(), ErrorHandler::e_error, format, val);
+ va_end(val);
+}
+
+GlyphIndex
+AfmReader::find_err(PermString name, const char *) const
+{
+ GlyphIndex gi = _afm->find(name);
+ if (gi < 0)
+ lerror("character `%s' doesn't exist", name.c_str());
+ return gi;
+}
+
+void
+AfmReader::composite_warning() const
+{
+ if (!_composite_warned)
+ lwarning("composite fonts not supported");
+ _composite_warned = 1;
+}
+
+void
+AfmReader::metrics_sets_warning() const
+{
+ if (!_metrics_sets_warned)
+ lwarning("only metrics set 0 is supported");
+ _metrics_sets_warned = 1;
+}
+
+void
+AfmReader::y_width_warning() const
+{
+ if (_y_width_warned < 40) {
+ lwarning("character has a nonzero Y width");
+ _y_width_warned++;
+ if (_y_width_warned == 40)
+ lwarning("I won't warn you again.");
+ }
+}
+
+void
+AfmReader::no_match_warning(const char *context) const
+{
+ // keyword() will fail (and a warning won't get printed) only if the string
+ // is all whitespace, which the spec allows
+ PermString keyword = _l.keyword();
+ if (!keyword) return;
+ if (_l.key_matched()) {
+ lwarning(context ? "bad `%s' command in %s:"
+ : "bad `%s' command:", keyword.c_str(), context);
+ lwarning("field %d %s", _l.fail_field(), _l.message().c_str());
+ } else
+ lwarning(context ? "unknown command `%s' in %s"
+ : "unknown command `%s'", keyword.c_str(), context);
+ _l.clear_message();
+}
+
+
+bool
+AfmReader::read()
+{
+ AfmParser &l = _l;
+ assert(_afm && _afm_xt);
+
+ // First, read all opening comments into an array so we can print them out
+ // later.
+ PermString comment;
+ while (l.next_line()) {
+ if (l.isall("Comment %+s", &comment))
+ _afm_xt->opening_comments.push_back(comment);
+ else if (l.isall("StartFontMetrics %g", (double *)0))
+ ;
+ else {
+ l.save_line();
+ break;
+ }
+ }
+
+ _afm->set_scale(1000);
+ unsigned invalid_lines = 0;
+ PermString s;
+ bool isbasefont;
+ int metrics_sets;
+ int direction;
+
+ while (l.next_line())
+ switch (l.first()) {
+
+ case 'A':
+ if (l.isall("Ascender %g", &fd( fdAscender )))
+ break;
+ goto invalid;
+
+ case 'C':
+ if (l.isall("Characters %d", (int *)0))
+ break;
+ if (l.isall("CapHeight %g", &fd( fdCapHeight )))
+ break;
+ if (l.isall("CharacterSet %+s", (PermString *) 0))
+ break;
+ if (l.isall("CharWidth %g %g", (double *)0, (double *)0))
+ break;
+ if (l.isall("Comment %+s", (PermString *) 0))
+ break;
+ goto invalid;
+
+ case 'D':
+ if (l.isall("Descender %g", &fd( fdDescender )))
+ break;
+ goto invalid;
+
+ case 'E':
+ if (l.isall("EncodingScheme %+s", &_afm_xt->encoding_scheme))
+ break;
+ if (l.isall("EndDirection"))
+ break;
+ if (l.isall("EndFontMetrics"))
+ goto done;
+ if (l.isall("EscChar %d", (int *)0)) {
+ composite_warning();
+ break;
+ }
+ goto invalid;
+
+ case 'F':
+ if (l.isall("FontName %+s", &s)) {
+ _afm->set_font_name(s);
+ break;
+ }
+ if (l.isall("FullName %+s", &s)) {
+ _afm->set_full_name(s);
+ break;
+ }
+ if (l.isall("FamilyName %+s", &s)) {
+ _afm->set_family(s);
+ break;
+ }
+ if (l.isall("FontBBox %g %g %g %g",
+ &fd( fdFontBBllx ), &fd( fdFontBBlly ),
+ &fd( fdFontBBurx ), &fd( fdFontBBury )))
+ break;
+ goto invalid;
+
+ case 'I':
+ if (l.isall("ItalicAngle %g", &fd( fdItalicAngle )))
+ break;
+ if (l.isall("IsBaseFont %b", &isbasefont)) {
+ if (isbasefont == 0)
+ composite_warning();
+ break;
+ }
+ if (l.isall("IsFixedV %b", (bool *)0)) {
+ metrics_sets_warning();
+ break;
+ }
+ if (l.isall("IsFixedPitch %b", (bool *)0))
+ break;
+ goto invalid;
+
+ case 'M':
+ if (l.isall("MappingScheme %d", (int *)0)) {
+ composite_warning();
+ break;
+ }
+ if (l.isall("MetricsSets %d", &metrics_sets)) {
+ if (metrics_sets != 0)
+ metrics_sets_warning();
+ break;
+ }
+ goto invalid;
+
+ case 'N':
+ if (l.isall("Notice %+s", &_afm_xt->notice))
+ break;
+ goto invalid;
+
+ case 'S':
+ if (l.isall("StartDirection %d", &direction)) {
+ if (direction != 0)
+ metrics_sets_warning();
+ break;
+ }
+ if (l.isall("StartCharMetrics %d", (int *)0)) {
+ read_char_metrics();
+ break;
+ }
+ if (l.isall("StartKernData")) {
+ read_kerns();
+ break;
+ }
+ if (l.isall("StartComposites %d", (int *)0)) {
+ read_composites();
+ break;
+ }
+ if (l.isall("StdHW %g", &fd( fdStdHW )))
+ break;
+ if (l.isall("StdVW %g", &fd( fdStdVW )))
+ break;
+ if (l.isall("StartFontMetrics %g", (double *)0))
+ break;
+ goto invalid;
+
+ case 'U':
+ if (l.isall("UnderlinePosition %g", &fd( fdUnderlinePosition )))
+ break;
+ if (l.isall("UnderlineThickness %g", &fd( fdUnderlineThickness )))
+ break;
+ goto invalid;
+
+ case 'V':
+ if (l.isall("Version %+s", &s)) {
+ _afm->set_version(s);
+ break;
+ }
+ if (l.isall("VVector %g %g", (double *)0, (double *)0)) {
+ metrics_sets_warning();
+ break;
+ }
+ goto invalid;
+
+ case 'W':
+ if (l.isall("Weight %+s", &s)) {
+ _afm->set_weight(s);
+ break;
+ }
+ goto invalid;
+
+ case 'X':
+ if (l.isall("XHeight %g", &fd( fdXHeight )))
+ break;
+ goto invalid;
+
+ default:
+ invalid:
+ invalid_lines++;
+ no_match_warning();
+
+ }
+
+ done:
+ if (invalid_lines >= l.lineno() - 10)
+ return false;
+ else
+ return true;
+}
+
+
+static Vector<PermString> ligature_left;
+static Vector<PermString> ligature_right;
+static Vector<PermString> ligature_result;
+
+void
+AfmReader::read_char_metric_data() const
+{
+ int c = -1;
+ double wx = UNKDOUBLE;
+ double bllx = UNKDOUBLE, blly = 0, burx = 0, bury = 0;
+ PermString n;
+ PermString ligright, ligresult;
+
+ AfmParser &l = _l;
+
+ l.is("C %d ; WX %g ; N %/s ; B %g %g %g %g ;",
+ &c, &wx, &n, &bllx, &blly, &burx, &bury);
+
+ while (l.left()) {
+
+ switch (l.first()) {
+
+ case 'B':
+ if (l.is("B %g %g %g %g", &bllx, &blly, &burx, &bury))
+ break;
+ goto invalid;
+
+ case 'C':
+ if (l.is("C %d", &c))
+ break;
+ if (l.is("CH <%x>", &c))
+ break;
+ goto invalid;
+
+ case 'E':
+ if (l.isall("EndCharMetrics"))
+ return;
+ goto invalid;
+
+ case 'L':
+ if (l.is("L %/s %/s", &ligright, &ligresult)) {
+ if (!n)
+ lerror("ligature given, but character has no name");
+ else {
+ ligature_left.push_back(n);
+ ligature_right.push_back(ligright);
+ ligature_result.push_back(ligresult);
+ }
+ break;
+ }
+ goto invalid;
+
+ case 'N':
+ if (l.is("N %/s", &n))
+ break;
+ goto invalid;
+
+ case 'W':
+ if (l.is("WX %g", &wx) ||
+ l.is("W0X %g", &wx))
+ break;
+ if (l.is("W %g %g", &wx, (double *)0) ||
+ l.is("W0 %g %g", &wx, (double *)0) ||
+ l.is("W0Y %g", (double *)0)) {
+ y_width_warning();
+ break;
+ }
+ if (l.is("W1X %g", (double *)0) ||
+ l.is("W1Y %g", (double *)0) ||
+ l.is("W1 %g %g", (double *)0, (double *)0)) {
+ metrics_sets_warning();
+ break;
+ }
+ goto invalid;
+
+ default:
+ invalid:
+ // always warn about unknown directives here!
+ no_match_warning("character metrics");
+ l.skip_until(';');
+ break;
+
+ }
+
+ l.is(";"); // get rid of any possible semicolon
+ }
+
+ // create the character
+ if (!n)
+ lwarning("character without a name ignored");
+ else {
+ if (_afm->find(n) != -1)
+ lwarning("character %s defined twice", n.c_str());
+
+ GlyphIndex gi = _afm->add_glyph(n);
+
+ _afm->wd(gi) = wx;
+ _afm->lf(gi) = bllx;
+ _afm->rt(gi) = burx;
+ _afm->tp(gi) = bury;
+ _afm->bt(gi) = blly;
+
+ if (c != -1)
+ _afm->set_code(gi, c);
+ }
+}
+
+
+void
+AfmReader::read_char_metrics() const
+{
+ assert(!ligature_left.size());
+
+ while (_l.next_line())
+ // Grok the whole line. Are we on a character metric data line?
+ switch (_l.first()) {
+
+ case 'C':
+ if (isspace(_l[1]) || (_l[1] == 'H' && isspace(_l[2]))) {
+ read_char_metric_data();
+ break;
+ }
+ if (_l.is("Comment"))
+ break;
+ goto invalid;
+
+ case 'E':
+ if (_l.isall("EndCharMetrics"))
+ goto end_char_metrics;
+ goto invalid;
+
+ default:
+ invalid:
+ no_match_warning();
+
+ }
+
+ end_char_metrics:
+
+ for (int i = 0; i < ligature_left.size(); i++) {
+ GlyphIndex leftgi = find_err(ligature_left[i], "ligature");
+ GlyphIndex rightgi = find_err(ligature_right[i], "ligature");
+ GlyphIndex resultgi = find_err(ligature_result[i], "ligature");
+ if (leftgi >= 0 && rightgi >= 0 && resultgi >= 0)
+ if (_afm->add_lig(leftgi, rightgi, resultgi))
+ lwarning("duplicate ligature; first ignored");
+ }
+ ligature_left.clear();
+ ligature_right.clear();
+ ligature_result.clear();
+}
+
+
+void
+AfmReader::read_kerns() const
+{
+ double kx;
+ PermString left, right;
+ GlyphIndex leftgi, rightgi;
+
+ AfmParser &l = _l;
+ // AFM files have reversed pair programs when read.
+ _afm->pair_program()->set_reversed(true);
+
+ while (l.next_line())
+ switch (l.first()) {
+
+ case 'C':
+ if (l.is("Comment"))
+ break;
+ goto invalid;
+
+ case 'E':
+ if (l.isall("EndKernPairs"))
+ break;
+ if (l.isall("EndKernData"))
+ return;
+ if (l.isall("EndTrackKern"))
+ break;
+ goto invalid;
+
+ case 'K':
+ if (l.isall("KPX %/s %/s %g", &left, &right, &kx)) {
+ goto validkern;
+ }
+ if (l.isall("KP %/s %/s %g %g", &left, &right, &kx, (double *)0)) {
+ y_width_warning();
+ goto validkern;
+ }
+ if (l.isall("KPY %/s %/s %g", &left, &right, (double *)0)) {
+ y_width_warning();
+ break;
+ }
+ if (l.isall("KPH <%x> <%x> %g %g", (int *)0, (int *)0,
+ (double *)0, (double *)0)) {
+ lwarning("KPH not supported");
+ break;
+ }
+ goto invalid;
+
+ validkern:
+ leftgi = find_err(left, "kern");
+ rightgi = find_err(right, "kern");
+ if (leftgi >= 0 && rightgi >= 0)
+ // A kern with 0 amount is NOT useless!
+ // (Because of multiple masters.)
+ if (_afm->add_kern(leftgi, rightgi, _afm->add_kv(kx)))
+ lwarning("duplicate kern; first pair ignored");
+ break;
+
+ case 'S':
+ if (l.isall("StartKernPairs %d", (int *)0) ||
+ l.isall("StartKernPairs0 %d", (int *)0))
+ break;
+ if (l.isall("StartKernPairs1 %d", (int *)0)) {
+ metrics_sets_warning();
+ break;
+ }
+ if (l.isall("StartTrackKern %d", (int *)0))
+ break;
+ goto invalid;
+
+ case 'T':
+ if (l.isall("TrackKern %g %g %g %g %g", (double *)0, (double *)0,
+ (double *)0, (double *)0, (double *)0))
+ break; // FIXME: implement TrackKern
+ goto invalid;
+
+ default:
+ invalid:
+ no_match_warning();
+ break;
+
+ }
+}
+
+
+void
+AfmReader::read_composites() const
+{
+ while (_l.next_line())
+ switch (_l.first()) {
+
+ case 'C':
+ if (_l.is("Comment"))
+ break;
+ if (_l.is("CC"))
+ break;
+ goto invalid;
+
+ case 'E':
+ if (_l.isall("EndComposites"))
+ return;
+ goto invalid;
+
+ default:
+ invalid:
+ no_match_warning();
+ break;
+
+ }
+}
+
+}
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/afmparse.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/afmparse.cc
new file mode 100644
index 00000000000..313b63ec362
--- /dev/null
+++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/afmparse.cc
@@ -0,0 +1,365 @@
+// -*- related-file-name: "../include/efont/afmparse.hh" -*-
+
+/* afmparse.{cc,hh} -- Adobe Font Metrics parsing
+ *
+ * Copyright (c) 1998-2012 Eddie Kohler
+ *
+ * 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 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <efont/afmparse.hh>
+#include <efont/t1cs.hh>
+#include <efont/metrics.hh>
+#include <lcdf/strtonum.h>
+#include <string.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <stdlib.h>
+#if HAVE_BROKEN_STRTOD
+# define strtod good_strtod
+#endif
+namespace Efont {
+
+static bool name_enders[256];
+static char xvalue[256];
+
+
+AfmParser::AfmParser(Slurper &slurp)
+ : _slurper(slurp),
+ _line(0), _pos(0), _length(0)
+{
+ static_initialize();
+}
+
+
+void
+AfmParser::trim_end()
+{
+ int l = _length - 1;
+ while (l >= 0 && isspace(_line[l])) {
+ _line[l] = 0;
+ l--;
+ }
+ _length = l + 1;
+}
+
+
+void
+AfmParser::static_initialize()
+{
+ if (name_enders[(uint8_t)'('])
+ return;
+ name_enders[(uint8_t)' '] = name_enders[(uint8_t)'\t']
+ = name_enders[(uint8_t)'\r'] = name_enders[(uint8_t)'\f']
+ = name_enders[(uint8_t)'\v'] = name_enders[(uint8_t)'\n']
+ = name_enders[(uint8_t)'\0'] = name_enders[(uint8_t)'[']
+ = name_enders[(uint8_t)']'] = name_enders[(uint8_t)'/']
+ = name_enders[(uint8_t)'('] = name_enders[(uint8_t)')']
+ = name_enders[(uint8_t)';'] = true;
+
+ xvalue[(uint8_t)'0'] = 0;
+ xvalue[(uint8_t)'1'] = 1;
+ xvalue[(uint8_t)'2'] = 2;
+ xvalue[(uint8_t)'3'] = 3;
+ xvalue[(uint8_t)'4'] = 4;
+ xvalue[(uint8_t)'5'] = 5;
+ xvalue[(uint8_t)'6'] = 6;
+ xvalue[(uint8_t)'7'] = 7;
+ xvalue[(uint8_t)'8'] = 8;
+ xvalue[(uint8_t)'9'] = 9;
+ xvalue[(uint8_t)'a'] = 10;
+ xvalue[(uint8_t)'b'] = 11;
+ xvalue[(uint8_t)'c'] = 12;
+ xvalue[(uint8_t)'d'] = 13;
+ xvalue[(uint8_t)'e'] = 14;
+ xvalue[(uint8_t)'f'] = 15;
+ xvalue[(uint8_t)'A'] = 10;
+ xvalue[(uint8_t)'B'] = 11;
+ xvalue[(uint8_t)'C'] = 12;
+ xvalue[(uint8_t)'D'] = 13;
+ xvalue[(uint8_t)'E'] = 14;
+ xvalue[(uint8_t)'F'] = 15;
+}
+
+
+// isall == is total == is all of the string
+
+// %s whitespace-terminated PermString - non-zero-length
+// %/s name-terminated PermString - non-zero-length
+// %+s rest of line PermString
+// %= rest of line/until next `=' PermString; beginning & ending spaces
+// elided
+// %d integer
+// %g number
+// %x hex integer
+// %b boolean
+// %c character
+// %< hex string; argument is String *stored
+// %. any non-alphanumeric
+// ???????????? EOS vs. don't-skip-to-EOS ???????????
+
+
+#define FAIL(s) do { _message = s; return 0; } while (0)
+
+unsigned char *
+AfmParser::vis(const char *formatsigned, va_list valist)
+{
+ const unsigned char *format = (const unsigned char *)formatsigned;
+ unsigned char *str = _pos;
+
+ // Oftentimes, we'll get a keyword first. So handle that simple case
+ // with a tight loop for (possibly) better performance and slightly different
+ // semantics. (A keyword that comes first in the format must be followed
+ // by a nonalphanumeric in the input to match.)
+ if (isalpha(*format)) {
+ bool ok = true;
+ for (; *format && *format != ' ' && ok; format++, str++) {
+ assert(isalnum(*format));
+ if (*format != *str) ok = false;
+ }
+ if (!ok || isalnum(*str)) {
+ if (_message) return 0;
+ _fail_field = -1;
+ FAIL("keyword mismatch");
+ }
+ }
+
+ int fplus, fslash;
+ _fail_field = 0;
+ _message = PermString();
+
+ while (1) {
+
+ switch (*format) {
+
+ /* - - - - - - - - percent specifications - - - - - - - */
+ case '%':
+ fplus = fslash = 0;
+ _fail_field++;
+
+ percentspec:
+ switch (*++format) {
+
+ // FLAGS
+ case '+':
+ fplus++;
+ goto percentspec;
+ case '/':
+ fslash++;
+ goto percentspec;
+
+ case '%':
+ goto matchchar;
+
+ case 'b':
+ case 's': {
+ int len;
+
+ if (fplus)
+ len = strlen((char *)str);
+ else if (fslash) {
+ for (len = 0; !name_enders[ str[len] ]; len++)
+ ;
+ if (len == 0)
+ FAIL("should be a string");
+ } else {
+ for (len = 0; !isspace(str[len]) && str[len]; len++)
+ ;
+ if (len == 0)
+ FAIL("should be a string");
+ }
+
+ PermString s = PermString((char *)str, len);
+ str += len;
+
+ // Now we have the string. What to do with it? Depends on format.
+ if (*format == 'b') {
+
+ bool *bstore = va_arg(valist, bool *);
+ if (s == "true") {
+ if (bstore) *bstore = 1;
+ } else if (s == "false") {
+ if (bstore) *bstore = 0;
+ } else
+ FAIL("should be `true' or `false'");
+
+ } else {
+ PermString *sstore = va_arg(valist, PermString *);
+ if (sstore) *sstore = s;
+ }
+ break;
+ }
+
+ case '(': {
+ if (*str++ != '(') FAIL("should be a parenthesized string");
+ unsigned char *last = str;
+ int paren_level = 0;
+ while (*last && paren_level >= 0) {
+ if (*last == '(') paren_level++;
+ if (*last == ')') paren_level--;
+ last++;
+ }
+ if (paren_level >= 0) FAIL("had unbalanced parentheses");
+
+ PermString *sstore = va_arg(valist, PermString *);
+ if (sstore) *sstore = PermString((char *)str, last - str - 1);
+ str = last;
+ break;
+ }
+
+ case 'd':
+ case 'i': {
+ union { unsigned char *uc; char *c; } new_str;
+ int v = strtol((char *)str, &new_str.c, 10);
+ if (new_str.uc == str) FAIL("should be an integer");
+
+ str = new_str.uc;
+ int *istore = va_arg(valist, int *);
+ if (istore) *istore = v;
+ break;
+ }
+
+ case 'x': {
+ union { unsigned char *uc; char *c; } new_str;
+ int v = strtol((char *)str, &new_str.c, 16);
+ if (new_str.uc == str) FAIL("should be a hex integer");
+
+ str = new_str.uc;
+ int *istore = va_arg(valist, int *);
+ if (istore) *istore = v;
+ break;
+ }
+
+ case 'e':
+ case 'f':
+ case 'g': {
+ union { unsigned char *uc; char *c; } new_str;
+ double v = strtonumber((char *)str, &new_str.c);
+ if (v < MIN_KNOWN_DOUBLE) v = MIN_KNOWN_DOUBLE;
+ if (new_str.uc == str) FAIL("should be a real number");
+
+ str = new_str.uc;
+ double *dstore = va_arg(valist, double *);
+ if (dstore) *dstore = v;
+ break;
+ }
+
+ case '<': {
+ unsigned char *endbrack =
+ (unsigned char *)strchr((char *)str, '>');
+ int n = (endbrack ? endbrack - (str + 1) : 0);
+ if (!endbrack || n % 2 != 0)
+ FAIL("should be hex values in <angle brackets>");
+ String s = String::make_uninitialized(n/2);
+ unsigned char *data = s.mutable_udata();
+
+ str++;
+ while (*str != '>') {
+ if (isxdigit(str[0]) && isxdigit(str[1])) {
+ *data++ = xvalue[str[0]] * 16 + xvalue[str[1]];
+ str += 2;
+ } else
+ FAIL("had non-hex digits in the angle brackets");
+ }
+ str++;
+
+ if (String *datastore = va_arg(valist, String *))
+ *datastore = s;
+ break;
+ }
+
+ default:
+ assert(0 /* internal error: bad % */);
+ FAIL("");
+
+ }
+ break;
+ /* - - - - - - - - end percent specifications - - - - - - - */
+
+ case ' ':
+ if (!isspace(*str))
+ FAIL("should be followed by whitespace");
+ /* FALLTHRU */
+
+ case '-':
+ while (isspace(*str)) str++;
+ break;
+
+ case 0:
+ // always eat space at end of format
+ while (isspace(*str)) str++;
+ return str;
+
+ default:
+ matchchar:
+ if (*str++ != *format)
+ FAIL(permprintf("- expected `%c'", *format));
+ break;
+
+ }
+
+ format++;
+ }
+}
+
+
+bool
+AfmParser::isall(const char *format, ...)
+{
+ va_list valist;
+ va_start(valist, format);
+ unsigned char *new_pos = vis(format, valist);
+ va_end(valist);
+ if (new_pos && *new_pos == 0) {
+ _pos = new_pos;
+ return 1;
+ } else
+ return 0;
+}
+
+
+bool
+AfmParser::is(const char *format, ...)
+{
+ va_list valist;
+ va_start(valist, format);
+ unsigned char *new_pos = vis(format, valist);
+ va_end(valist);
+ if (new_pos) {
+ _pos = new_pos;
+ return 1;
+ } else
+ return 0;
+}
+
+
+PermString
+AfmParser::keyword() const
+{
+ const char *f = (const char *)_pos;
+ while (isspace((unsigned char) *f))
+ f++;
+ const char *l = f;
+ while (isalnum((unsigned char) *l) || *l == '_')
+ l++;
+ return PermString(f, l - f);
+}
+
+
+void
+AfmParser::skip_until(unsigned char c)
+{
+ while (*_pos && *_pos != c)
+ _pos++;
+}
+
+}
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/afmw.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/afmw.cc
new file mode 100644
index 00000000000..20840be1332
--- /dev/null
+++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/afmw.cc
@@ -0,0 +1,190 @@
+// -*- related-file-name: "../include/efont/afmw.hh" -*-
+
+/* afmw.{cc,hh} -- Adobe Font Metrics writing
+ *
+ * Copyright (c) 1998-2012 Eddie Kohler
+ *
+ * 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 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <efont/afmw.hh>
+#include <efont/t1cs.hh> /* for KNOWN() */
+namespace Efont {
+
+AfmWriter::AfmWriter(Metrics *m, FILE *f)
+ : _m(m), _afm_xt((AfmMetricsXt *)m->find_xt("AFM")), _f(f)
+{
+}
+
+void
+AfmWriter::write(Metrics *m, FILE *f)
+{
+ AfmWriter w(m, f);
+ w.write();
+}
+
+
+void
+AfmWriter::write()
+{
+ _m->pair_program()->unreverse();
+ _m->pair_program()->optimize();
+
+ fprintf(_f, "StartFontMetrics 4.1\n");
+ if (_afm_xt)
+ for (int i = 0; i < _afm_xt->opening_comments.size(); i++)
+ fprintf(_f, "Comment %s\n", _afm_xt->opening_comments[i].c_str());
+
+ write_prologue();
+
+ fprintf(_f, "StartCharMetrics %d\n", _m->nglyphs());
+
+ GlyphIndex gi;
+ for (int i = 0; i < 256; i++) //FIXME
+ if ((gi = _m->find_code(i)) >= 0)
+ write_char_metric_data(gi, i);
+ for (gi = 0; gi < _m->nglyphs(); gi++)
+ if (_m->code(gi) == -1)
+ write_char_metric_data(gi, -1);
+
+ fprintf(_f, "EndCharMetrics\n");
+
+ write_kerns();
+
+ fprintf(_f, "EndFontMetrics\n");
+}
+
+
+void
+AfmWriter::write_prologue() const
+{
+ if (_m->font_name())
+ fprintf(_f, "FontName %s\n", _m->font_name().c_str());
+ else
+ fprintf(_f, "FontName No-Font-Name-Given\n");
+
+ if (_m->full_name())
+ fprintf(_f, "FullName %s\n", _m->full_name().c_str());
+ if (_m->family())
+ fprintf(_f, "FamilyName %s\n", _m->family().c_str());
+ if (_m->weight())
+ fprintf(_f, "Weight %s\n", _m->weight().c_str());
+
+ if (KNOWN(fd( fdItalicAngle )))
+ fprintf(_f, "ItalicAngle %.8g\n", fd( fdItalicAngle ));
+
+ fprintf(_f, "FontBBox %.8g %.8g %.8g %.8g\n",
+ fd( fdFontBBllx ), fd( fdFontBBlly ),
+ fd( fdFontBBurx ), fd( fdFontBBury ));
+
+ if (KNOWN(fd( fdUnderlinePosition )))
+ fprintf(_f, "UnderlinePosition %.8g\n", fd( fdUnderlinePosition ));
+ if (KNOWN(fd( fdUnderlineThickness )))
+ fprintf(_f, "UnderlineThickness %.8g\n", fd( fdUnderlineThickness ));
+
+ if (_m->version())
+ fprintf(_f, "Version %s\n", _m->version().c_str());
+ if (_afm_xt && _afm_xt->notice)
+ fprintf(_f, "Notice %s\n", _afm_xt->notice.c_str());
+
+ if (_afm_xt && _afm_xt->encoding_scheme)
+ fprintf(_f, "EncodingScheme %s\n", _afm_xt->encoding_scheme.c_str());
+
+ if (KNOWN(fd( fdCapHeight )))
+ fprintf(_f, "CapHeight %.8g\n", fd( fdCapHeight ));
+ if (KNOWN(fd( fdXHeight )))
+ fprintf(_f, "XHeight %.8g\n", fd( fdXHeight ));
+ if (KNOWN(fd( fdAscender )))
+ fprintf(_f, "Ascender %.8g\n", fd( fdAscender ));
+ if (KNOWN(fd( fdDescender )))
+ fprintf(_f, "Descender %.8g\n", fd( fdDescender ));
+ if (KNOWN(fd( fdStdHW )))
+ fprintf(_f, "StdHW %.8g\n", fd( fdStdHW ));
+ if (KNOWN(fd( fdStdVW )))
+ fprintf(_f, "StdVW %.8g\n", fd( fdStdVW ));
+}
+
+
+void
+AfmWriter::write_char_metric_data(GlyphIndex gi, int e) const
+{
+ if (e >= -1 && e < 256)
+ fprintf(_f, "C %d ;", e);
+ else
+ fprintf(_f, "CH <%04X> ;", e);
+
+ double w = _m->wd(gi);
+ if (KNOWN(w))
+ fprintf(_f, " WX %.8g ;", w);
+ else
+ w = 0;
+
+ fprintf(_f, " N %s ;", _m->name(gi).c_str());
+
+ if (KNOWN(_m->lf(gi)))
+ fprintf(_f, " B %.8g %.8g %.8g %.8g ;",
+ _m->lf(gi), _m->bt(gi), _m->rt(gi), _m->tp(gi));
+
+ // Run through the ligature/kern program to find ligatures.
+ PairProgram &pairp = *_m->pair_program();
+ PairOpIndex opi = pairp.find_left(gi);
+ while (opi >= 0) {
+ const PairOp &op = pairp.op(opi);
+ if (op.is_lig()) {
+ if (op.lig_kind() == opLigSimple)
+ fprintf(_f, " L %s %s ;",
+ _m->name( op.right() ).c_str(),
+ _m->name( op.result() ).c_str());
+ //else
+ //warning("strange ligature combination not supported by AFM");
+ }
+ opi = op.next_left();
+ }
+
+ fputc('\n', _f);
+}
+
+
+void
+AfmWriter::write_kerns() const
+{
+ PairProgram &pairp = *_m->pair_program();
+
+ // Damn. First we have to count how many kerning pairs there are.
+ int numkerns = 0;
+ for (PairOpIndex opi = 0; opi < pairp.op_count(); opi++) {
+ const PairOp &op = pairp.op(opi);
+ if (op.is_kern() && _m->kv( op.value() ))
+ numkerns++;
+ }
+
+ if (numkerns == 0) return;
+
+ fprintf(_f, "StartKernData\n");
+ fprintf(_f, "StartKernPairs %d\n", numkerns);
+ for (GlyphIndex gi = 0; gi < _m->nglyphs(); gi++) {
+ PairOpIndex opi = pairp.find_left(gi);
+ while (opi >= 0) {
+ const PairOp &op = pairp.op(opi);
+ if (op.is_kern() && _m->kv( op.value() ))
+ fprintf(_f, "KPX %s %s %.8g\n",
+ _m->name( gi ).c_str(),
+ _m->name( op.right() ).c_str(),
+ _m->kv( op.value() ));
+ opi = op.next_left();
+ }
+ }
+ fprintf(_f, "EndKernPairs\n");
+ fprintf(_f, "EndKernData\n");
+}
+
+}
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/amfm.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/amfm.cc
new file mode 100644
index 00000000000..b38532d55fb
--- /dev/null
+++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/amfm.cc
@@ -0,0 +1,850 @@
+// -*- related-file-name: "../include/efont/amfm.hh" -*-
+
+/* amfm.{cc,hh} -- Adobe Multiple-Master Font Metrics
+ *
+ * Copyright (c) 1998-2012 Eddie Kohler
+ *
+ * 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 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <efont/amfm.hh>
+#include <efont/afm.hh>
+#include <efont/afmparse.hh>
+#include <lcdf/error.hh>
+#include <efont/findmet.hh>
+#include <efont/t1cs.hh>
+#include <lcdf/straccum.hh>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <assert.h>
+#include <string.h>
+namespace Efont {
+
+AmfmMetrics::AmfmMetrics(MetricsFinder *finder)
+ : _finder(finder),
+ _fdv(fdLast, UNKDOUBLE),
+ _nmasters(-1), _naxes(-1), _masters(0), _mmspace(0),
+ _primary_fonts(0), _sanity_afm(0), _uses(0)
+{
+}
+
+AmfmMetrics::~AmfmMetrics()
+{
+ assert(_uses == 0);
+ for (int m = 0; m < _nmasters; m++)
+ if (_masters[m].afm)
+ _masters[m].afm->unuse();
+ delete[] _masters;
+ delete _mmspace;
+ while (_primary_fonts) {
+ AmfmPrimaryFont *pf = _primary_fonts;
+ _primary_fonts = _primary_fonts->next;
+ delete pf;
+ }
+}
+
+
+bool
+AmfmMetrics::sanity(ErrorHandler *errh) const
+{
+ if (!_mmspace) {
+ errh->error("AMFM sanity: no multiple master interpolation information");
+ return false;
+ }
+
+ bool ok = true;
+ for (int m = 0; m < _nmasters; m++)
+ if (!_masters[m].font_name
+ || _masters[m].weight_vector.size() != _nmasters) {
+ errh->error("AMFM sanity: no information for master %d", m);
+ ok = false;
+ }
+
+ if (!_mmspace->check(errh))
+ ok = false;
+
+ return ok;
+}
+
+
+int
+AmfmMetrics::primary_label_value(int ax, PermString label) const
+{
+ assert(ax >= 0 && ax < _naxes);
+ for (AmfmPrimaryFont *pf = _primary_fonts; pf; pf = pf->next) {
+ if (pf->labels[ax] == label)
+ return pf->design_vector[ax];
+ }
+ return -1;
+}
+
+
+inline static bool
+strcompat(PermString a, PermString b)
+{
+ return !a || !b || a == b;
+}
+
+Metrics *
+AmfmMetrics::master(int m, ErrorHandler *errh)
+{
+ AmfmMaster &master = _masters[m];
+
+ if (!master.loaded) {
+ master.loaded = true;
+ DirectoryMetricsFinder directory_finder(_directory);
+ _finder->add_finder(&directory_finder);
+ Metrics *afm = _finder->find_metrics(master.font_name);
+
+ if (!afm) {
+ if (errh)
+ errh->error("%s: can't find AFM file for master `%s'",
+ _font_name.c_str(), master.font_name.c_str());
+
+ } else if (!strcompat(afm->font_name(), master.font_name)
+ || !strcompat(afm->family(), master.family)
+ || !strcompat(afm->full_name(), master.full_name)
+ || !strcompat(afm->version(), master.version)) {
+ if (errh)
+ errh->error("%s: AFM for master `%s' doesn't match AMFM",
+ _font_name.c_str(), master.font_name.c_str());
+
+ } else if (!_sanity_afm) {
+ master.afm = afm;
+ _sanity_afm = afm;
+ afm->use();
+
+ } else {
+ PairProgram *sanity_pairp = _sanity_afm->pair_program();
+ PairProgram *pairp = afm->pair_program();
+ char buf[1024];
+ buf[0] = 0;
+
+ if (afm->nglyphs() != _sanity_afm->nglyphs())
+ sprintf(buf, "glyph count (%d vs. %d)", afm->nglyphs(), _sanity_afm->nglyphs());
+ if (afm->nfd() != _sanity_afm->nfd())
+ sprintf(buf, "fd count (%d vs. %d)", afm->nfd(), _sanity_afm->nfd());
+ if (afm->nkv() != _sanity_afm->nkv())
+ sprintf(buf, "kv count (%d vs. %d)", afm->nkv(), _sanity_afm->nkv());
+ if (pairp->op_count() != sanity_pairp->op_count())
+ sprintf(buf, "pair op count (%d vs. %d)", pairp->op_count(), sanity_pairp->op_count());
+
+ if (!buf[0]) {
+ master.afm = afm;
+ afm->use();
+ } else if (errh)
+ errh->error("%s: AFM for master `%s' failed sanity checks (%s)", _font_name.c_str(), master.font_name.c_str(), buf);
+ }
+ }
+
+ return master.afm;
+}
+
+
+AmfmPrimaryFont *
+AmfmMetrics::find_primary_font(const Vector<double> &design_vector) const
+{
+ assert(design_vector.size() == _naxes);
+ for (AmfmPrimaryFont *pf = _primary_fonts; pf; pf = pf->next) {
+
+ for (int a = 0; a < _naxes; a++)
+ if ((int)design_vector[a] != pf->design_vector[a])
+ goto loser;
+ return pf;
+
+ loser: ;
+ }
+ return 0;
+}
+
+
+Metrics *
+AmfmMetrics::interpolate(const Vector<double> &design_vector,
+ const Vector<double> &weight_vector,
+ ErrorHandler *errh)
+{
+ assert(design_vector.size() == _naxes);
+ assert(weight_vector.size() == _nmasters);
+
+ // FIXME: check masters for correspondence.
+
+ /* 0.
+ * Make sure all necessary AFMs have been loaded. */
+ int m;
+ for (m = 0; m < _nmasters; m++)
+ if (weight_vector[m])
+ if (!master(m, errh))
+ return 0;
+
+ /* 1.
+ * Use the design vector to generate new FontName and FullName. */
+
+ AmfmPrimaryFont *pf = find_primary_font(design_vector);
+ // The primary font is useless to us if it doesn't have axis labels.
+ if (pf && !pf->labels.size())
+ pf = 0;
+
+ StringAccum font_name_sa, full_name_sa;
+ font_name_sa << _font_name;
+ full_name_sa << _full_name;
+ for (int a = 0; a < _naxes; a++) {
+ double dv = design_vector[a];
+ font_name_sa << '_' << dv;
+ full_name_sa << (a == 0 ? '_' : ' ') << dv;
+
+ PermString label;
+ if (pf)
+ label = pf->labels[a];
+ if (!label)
+ label = _mmspace->axis_abbreviation(a);
+ if (label)
+ full_name_sa << ' ' << label;
+ }
+ // Multiple master fonts require an underscore AFTER the font name too
+ font_name_sa << '_';
+
+ /* 2.
+ * Set up the new AFM with the special constructor. */
+
+ // Find the first master with a non-zero component.
+ for (m = 0; m < _nmasters && weight_vector[m] == 0; m++)
+ ;
+ Metrics *afm = new Metrics(font_name_sa.c_str(), full_name_sa.c_str(), *_masters[m].afm);
+ if (MetricsXt *xt = _masters[m].afm->find_xt("AFM")) {
+ AfmMetricsXt *new_xt = new AfmMetricsXt((AfmMetricsXt &)*xt);
+ afm->add_xt(new_xt);
+ }
+
+ /* 2.
+ * Interpolate the old AFM data into the new. */
+
+ afm->interpolate_dimens(*_masters[m].afm, weight_vector[m], false);
+
+ for (m++; m < _nmasters; m++)
+ if (weight_vector[m])
+ afm->interpolate_dimens(*_masters[m].afm, weight_vector[m], true);
+
+ return afm;
+}
+
+
+/*****
+ * AmfmReader
+ **/
+
+AmfmReader::AmfmReader(AfmParser &afmp, AmfmMetrics *amfm, ErrorHandler *errh)
+ : _amfm(amfm), _finder(amfm->_finder), _l(afmp),
+ _mmspace(amfm->_mmspace)
+{
+ _errh = errh ? errh : ErrorHandler::silent_handler();
+}
+
+AmfmMetrics *
+AmfmReader::read(Slurper &slurper, MetricsFinder *finder, ErrorHandler *errh)
+{
+ AfmParser parser(slurper);
+ if (!parser.ok()) return 0;
+ AmfmMetrics *amfm = new AmfmMetrics(finder);
+ AmfmReader reader(parser, amfm, errh);
+ if (!reader.read()) {
+ delete amfm;
+ return 0;
+ } else
+ return amfm;
+}
+
+AmfmMetrics *
+AmfmReader::read(const Filename &fn, MetricsFinder *finder, ErrorHandler *errh)
+{
+ Slurper slurper(fn);
+ return read(slurper, finder, errh);
+}
+
+void
+AmfmReader::add_amcp_file(Slurper &slurper, AmfmMetrics *amfm, ErrorHandler *errh)
+{
+ AfmParser parser(slurper);
+ if (!parser.ok()) return;
+ AmfmReader reader(parser, amfm, errh);
+ reader.read_amcp_file();
+}
+
+
+void
+AmfmReader::lwarning(const char *format, ...) const
+{
+ va_list val;
+ va_start(val, format);
+ _errh->vxmessage(_l.landmark(), ErrorHandler::e_warning, format, val);
+ va_end(val);
+}
+
+void
+AmfmReader::lerror(const char *format, ...) const
+{
+ va_list val;
+ va_start(val, format);
+ _errh->vxmessage(_l.landmark(), ErrorHandler::e_error, format, val);
+ va_end(val);
+}
+
+void
+AmfmReader::no_match_warning(const char *context) const
+{
+ // keyword() will fail (and a warning won't get printed) only if the string
+ // is all whitespace, which the spec allows
+ PermString keyword = _l.keyword();
+ if (!keyword) return;
+ if (_l.key_matched()) {
+ lwarning(context ? "bad `%s' command in %s:"
+ : "bad `%s' command:", keyword.c_str(), context);
+ lwarning("field %d %s", _l.fail_field(), _l.message().c_str());
+ } else
+ lwarning(context ? "unknown command `%s' in %s"
+ : "unknown command `%s'", keyword.c_str(), context);
+ _l.clear_message();
+}
+
+
+void
+AmfmReader::check_mmspace()
+{
+ if (!_mmspace && _amfm->_naxes >= 0 && _amfm->_nmasters >= 0
+ && _amfm->_font_name) {
+ _mmspace = _amfm->_mmspace =
+ new MultipleMasterSpace(_amfm->_font_name, _amfm->_naxes, _amfm->_nmasters);
+ }
+}
+
+
+bool
+AmfmReader::read()
+{
+ assert(_amfm != 0);
+ _mmspace = _amfm->_mmspace;
+
+ AfmParser &l = _l;
+ _amfm->_directory = l.filename().directory();
+
+ // First, read all opening comments into an array so we can print them out
+ // later.
+ PermString comment;
+ while (l.next_line()) {
+ if (l.isall("Comment %+s", &comment))
+ _amfm->_opening_comments.push_back(comment);
+ else if (l.isall("StartMasterFontMetrics %g", (double *)0))
+ ;
+ else {
+ l.save_line();
+ break;
+ }
+ }
+
+ int master = 0, axis = 0;
+
+ while (l.next_line())
+ switch (l[0]) {
+
+ case 'A':
+ if (l.isall("Ascender %g", &fd( fdAscender )))
+ break;
+ if (l.isall("Axes %d", &_amfm->_naxes)) {
+ check_mmspace();
+ break;
+ }
+ goto invalid;
+
+ case 'B':
+ if (l.is("BlendDesignPositions")) {
+ read_positions();
+ break;
+ }
+ if (l.is("BlendDesignMap")) {
+ read_normalize();
+ break;
+ }
+ if (l.is("BlendAxisTypes")) {
+ read_axis_types();
+ break;
+ }
+ goto invalid;
+
+ case 'C':
+ if (l.isall("CapHeight %g", &fd( fdCapHeight )))
+ break;
+ if (l.is("Comment"))
+ break;
+ goto invalid;
+
+ case 'D':
+ if (l.isall("Descender %g", &fd( fdDescender )))
+ break;
+ goto invalid;
+
+ case 'E':
+ if (l.isall("EncodingScheme %+s", &_amfm->_encoding_scheme))
+ break;
+ if (l.isall("EndMasterFontMetrics"))
+ goto done;
+ goto invalid;
+
+ case 'F':
+ if (l.isall("FontName %+s", &_amfm->_font_name)) {
+ check_mmspace();
+ break;
+ }
+ if (l.isall("FullName %+s", &_amfm->_full_name))
+ break;
+ if (l.isall("FamilyName %+s", &_amfm->_family))
+ break;
+ if (l.isall("FontBBox %g %g %g %g",
+ &fd( fdFontBBllx ), &fd( fdFontBBlly ),
+ &fd( fdFontBBurx ), &fd( fdFontBBury )))
+ break;
+ goto invalid;
+
+ case 'I':
+ if (l.isall("IsFixedPitch %b", (bool *)0))
+ break;
+ if (l.isall("ItalicAngle %g", &fd( fdItalicAngle )))
+ break;
+ goto invalid;
+
+ case 'M':
+ if (l.isall("Masters %d", &_amfm->_nmasters)) {
+ check_mmspace();
+ break;
+ }
+ goto invalid;
+
+ case 'N':
+ if (l.isall("Notice %+s", &_amfm->_notice))
+ break;
+ goto invalid;
+
+ case 'S':
+ if (l.isall("StartAxis")) {
+ read_axis(axis++);
+ break;
+ }
+ if (l.isall("StartMaster")) {
+ read_master(master++);
+ break;
+ }
+ if (l.isall("StartPrimaryFonts %d", (int *)0)) {
+ read_primary_fonts();
+ break;
+ }
+ if (l.isall("StartConversionPrograms %d %d", (int *)0, (int *)0)) {
+ read_conversion_programs();
+ break;
+ }
+ if (l.isall("StartMasterFontMetrics %g", (double *)0))
+ break;
+ goto invalid;
+
+ case 'U':
+ if (l.isall("UnderlinePosition %g", &fd( fdUnderlinePosition )))
+ break;
+ else if (l.isall("UnderlineThickness %g", &fd( fdUnderlineThickness )))
+ break;
+ goto invalid;
+
+ case 'V':
+ if (l.isall("Version %+s", &_amfm->_version))
+ break;
+ goto invalid;
+
+ case 'W':
+ if (l.isall("Weight %+s", &_amfm->_weight))
+ break;
+ if (l.is("WeightVector")) {
+ Vector<double> wv;
+ if (!read_simple_array(wv) || !_mmspace)
+ lerror("bad WeightVector");
+ else
+ _mmspace->set_weight_vector(wv);
+ break;
+ }
+ goto invalid;
+
+ case 'X':
+ if (l.isall("XHeight %g", &fd( fdXHeight )))
+ break;
+ goto invalid;
+
+ default:
+ invalid:
+ no_match_warning();
+
+ }
+
+ done:
+ if (!_mmspace) {
+ _errh->error("`%s' is not an AMFM file", String(_l.landmark().file()).c_str());
+ return false;
+ }
+
+ LandmarkErrorHandler pin_errh(_errh, _l.landmark());
+ if (!_amfm->sanity(&pin_errh)) {
+ _errh->lerror(_l.landmark().whole_file(),
+ "bad AMFM file (missing or inconsistent information)");
+ return false;
+ }
+
+ if (!_mmspace->check_intermediate() && _l.filename().directory()) {
+ String name = l.filename().base() + ".amcp";
+ Slurper slurp(_l.filename().from_directory(name));
+ add_amcp_file(slurp, _amfm, _errh);
+ }
+
+ return true;
+}
+
+
+void
+AmfmReader::read_amcp_file()
+{
+ int lines_read = 0;
+
+ while (_l.next_line()) {
+ lines_read++;
+ switch (_l[0]) {
+
+ case 'C':
+ if (_l.is("Comment"))
+ break;
+ goto invalid;
+
+ case 'S':
+ if (_l.isall("StartConversionPrograms %d %d", (int *)0, (int *)0)) {
+ read_conversion_programs();
+ break;
+ }
+ goto invalid;
+
+ default:
+ invalid:
+ no_match_warning("AMCP file");
+
+ }
+ }
+
+ if (_mmspace && !_mmspace->ndv() && !_mmspace->cdv() && lines_read)
+ lwarning("no conversion programs in .amcp file");
+}
+
+
+bool
+AmfmReader::read_simple_array(Vector<double> &vec) const
+{
+ if (!_l.is("[")) return false;
+
+ vec.clear();
+ double d;
+ while (_l.is("%g", &d))
+ vec.push_back(d);
+
+ return _l.is("]");
+}
+
+
+void
+AmfmReader::read_positions() const
+{
+ if (nmasters() < 2 || naxes() < 1) return;
+ Vector<NumVector> positions;
+ if (!_l.is("[") || !_mmspace) goto error;
+
+ for (int i = 0; i < nmasters(); i++) {
+ positions.push_back(NumVector());
+ if (!read_simple_array(positions.back()))
+ goto error;
+ }
+
+ if (!_l.is("]")) goto error;
+ _mmspace->set_master_positions(positions);
+ return;
+
+ error:
+ lerror("bad BlendDesignPositions");
+}
+
+
+void
+AmfmReader::read_normalize() const
+{
+ if (naxes() < 1) return;
+ Vector<NumVector> normalize_in, normalize_out;
+ if (!_l.is("[") || !_mmspace) goto error;
+
+ for (int a = 0; a < naxes(); a++) {
+ if (!_l.is("[")) goto error;
+ normalize_in.push_back(NumVector());
+ normalize_out.push_back(NumVector());
+ double v1, v2;
+ while (_l.is("[-%g %g-]", &v1, &v2)) {
+ normalize_in[a].push_back(v1);
+ normalize_out[a].push_back(v2);
+ }
+ if (!_l.is("]")) goto error;
+ }
+
+ if (!_l.is("]")) goto error;
+ _mmspace->set_normalize(normalize_in, normalize_out);
+ return;
+
+ error:
+ lerror("bad BlendDesignPositions");
+}
+
+
+void
+AmfmReader::read_axis_types() const
+{
+ PermString s;
+ int ax = 0;
+ Vector<PermString> types;
+ if (naxes() < 1) return;
+ if (!_l.is("[") || !_mmspace) goto error;
+ _mmspace->check();
+
+ while (_l.is("/%/s", &s))
+ _mmspace->set_axis_type(ax++, s);
+
+ if (!_l.is("]")) goto error;
+ return;
+
+ error:
+ lerror("bad BlendAxisTypes");
+}
+
+
+void
+AmfmReader::read_axis(int ax) const
+{
+ bool ok = _mmspace && ax < naxes();
+ if (!ok)
+ lerror("bad axis number %d", ax);
+ else
+ _mmspace->check();
+
+ PermString s;
+ while (_l.next_line())
+ switch (_l[0]) {
+
+ case 'A':
+ if (_l.is("AxisType %+s", &s)) {
+ if (ok)
+ _mmspace->set_axis_type(ax, s);
+ break;
+ }
+ if (_l.is("AxisLabel %+s", &s)) {
+ if (ok)
+ _mmspace->set_axis_label(ax, s);
+ break;
+ }
+ goto invalid;
+
+ case 'C':
+ if (_l.is("Comment"))
+ break;
+ goto invalid;
+
+ case 'E':
+ if (_l.isall("EndAxis"))
+ goto endaxis;
+ goto invalid;
+
+ default:
+ invalid:
+ no_match_warning();
+
+ }
+
+ endaxis: ;
+}
+
+
+void
+AmfmReader::read_master(int m) const
+{
+ AmfmMaster *amfmm;
+ AmfmMaster dummy;
+ if (m >= nmasters()) {
+ lerror("too many masters");
+ amfmm = &dummy;
+ } else {
+ if (!_amfm->_masters)
+ _amfm->_masters = new AmfmMaster[ nmasters() ];
+ amfmm = &_amfm->_masters[m];
+ }
+
+ while (_l.next_line())
+ // Grok the whole line. Are we on a character metric data line?
+ switch (_l[0]) {
+
+ case 'C':
+ if (_l.is("Comment"))
+ break;
+ goto invalid;
+
+ case 'E':
+ if (_l.isall("EndMaster"))
+ goto endmaster;
+ goto invalid;
+
+ case 'F':
+ if (_l.isall("FontName %+s", &amfmm->font_name))
+ break;
+ if (_l.isall("FullName %+s", &amfmm->full_name))
+ break;
+ if (_l.isall("FamilyName %+s", &amfmm->family))
+ break;
+ goto invalid;
+
+ case 'V':
+ if (_l.isall("Version %+s", &amfmm->version))
+ break;
+ goto invalid;
+
+ case 'W':
+ if (_l.is("WeightVector")) {
+ if (!(read_simple_array(amfmm->weight_vector) &&
+ amfmm->weight_vector.size() == nmasters())) {
+ lerror("bad WeightVector");
+ amfmm->weight_vector.clear();
+ }
+ break;
+ }
+ goto invalid;
+
+ default:
+ invalid:
+ no_match_warning();
+
+ }
+
+ endmaster: ;
+}
+
+
+void
+AmfmReader::read_one_primary_font() const
+{
+ AmfmPrimaryFont *pf = new AmfmPrimaryFont;
+ pf->design_vector.resize(naxes());
+ pf->labels.resize(naxes());
+
+ while (_l.left()) {
+
+ if (_l.is("PC")) {
+ for (int a = 0; a < naxes(); a++)
+ if (!_l.is("%d", &pf->design_vector[a]))
+ goto error;
+ } else if (_l.is("PL")) {
+ for (int a = 0; a < naxes(); a++)
+ if (!_l.is("(-%/s-)", &pf->labels[a]))
+ goto error;
+ } else if (_l.is("PN %(", &pf->name))
+ ;
+ else
+ no_match_warning("primary font");
+
+ _l.is(";"); // get rid of any possible semicolon
+ }
+
+ pf->next = _amfm->_primary_fonts;
+ _amfm->_primary_fonts = pf;
+ return;
+
+ error:
+ delete pf;
+}
+
+
+void
+AmfmReader::read_primary_fonts() const
+{
+ while (_l.next_line())
+ switch (_l[0]) {
+
+ case 'C':
+ if (_l.is("Comment"))
+ break;
+ goto invalid;
+
+ case 'E':
+ if (_l.isall("EndPrimaryFonts"))
+ goto end_primary_fonts;
+ goto invalid;
+
+ case 'P':
+ if (_l[1] == 'C' && isspace(_l[2])) {
+ read_one_primary_font();
+ break;
+ }
+ goto invalid;
+
+ default:
+ invalid:
+ no_match_warning();
+
+ }
+
+ end_primary_fonts: ;
+}
+
+
+void
+AmfmReader::read_conversion_programs() const
+{
+ String ndv, cdv, s;
+
+ while (_l.next_line())
+ switch (_l[0]) {
+
+ case 'C':
+ if (_l.isall("CDV %<", &s)) {
+ cdv += s;
+ break;
+ }
+ goto invalid;
+
+ case 'E':
+ if (_l.isall("EndConversionPrograms"))
+ goto end_conversion_programs;
+ goto invalid;
+
+ case 'N':
+ if (_l.isall("NDV %<", &s)) {
+ ndv += s;
+ break;
+ }
+ goto invalid;
+
+ default:
+ invalid:
+ no_match_warning();
+ break;
+
+ }
+
+ end_conversion_programs:
+ if (_mmspace) {
+ _mmspace->set_ndv(Type1Charstring(ndv));
+ _mmspace->set_cdv(Type1Charstring(cdv));
+ }
+}
+
+}
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/cff.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/cff.cc
new file mode 100644
index 00000000000..822d57ec94d
--- /dev/null
+++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/cff.cc
@@ -0,0 +1,1689 @@
+// -*- related-file-name: "../include/efont/cff.hh" -*-
+
+/* cff.{cc,hh} -- Compact Font Format fonts
+ *
+ * Copyright (c) 1998-2012 Eddie Kohler
+ *
+ * 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 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <efont/cff.hh>
+#include <lcdf/error.hh>
+#include <efont/t1item.hh>
+#include <lcdf/straccum.hh>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <ctype.h>
+#include <efont/t1unparser.hh>
+
+#ifndef static_assert
+#define static_assert(c) switch (c) case 0: case (c):
+#endif
+
+namespace Efont {
+
+const char * const Cff::operator_names[] = {
+ "version", "Notice", "FullName", "FamilyName",
+ "Weight", "FontBBox", "BlueValues", "OtherBlues",
+ "FamilyBlues", "FamilyOtherBlues", "StdHW", "StdVW",
+ "UNKNOWN_12", "UniqueID", "XUID", "charset",
+ "Encoding", "CharStrings", "Private", "Subrs",
+ "defaultWidthX", "nominalWidthX", "UNKNOWN_22", "UNKNOWN_23",
+ "UNKNOWN_24", "UNKNOWN_25", "UNKNOWN_26", "UNKNOWN_27",
+ "UNKNOWN_28", "UNKNOWN_29", "UNKNOWN_30", "UNKNOWN_31",
+ "Copyright", "isFixedPitch", "ItalicAngle", "UnderlinePosition",
+ "UnderlineThickness", "PaintType", "CharstringType", "FontMatrix",
+ "StrokeWidth", "BlueScale", "BlueShift", "BlueFuzz",
+ "StemSnapH", "StemSnapV", "ForceBold", "UNKNOWN_12_15",
+ "UNKNOWN_12_16", "LanguageGroup", "ExpansionFactor", "initialRandomSeed",
+ "SyntheticBase", "PostScript", "BaseFontName", "BaseFontBlend",
+ "UNKNOWN_12_24", "UNKNOWN_12_25", "UNKNOWN_12_26", "UNKNOWN_12_27",
+ "UNKNOWN_12_28", "UNKNOWN_12_29", "ROS", "CIDFontVersion",
+ "CIDFontRevision", "CIDFontType", "CIDCount", "UIDBase",
+ "FDArray", "FDSelect", "FontName"
+};
+
+const int Cff::operator_types[] = {
+ tSID, tSID, tSID, tSID, // version, Notice, FullName, FamilyName
+ tSID, tArray4, tP+tArray, tP+tArray, // Weight, FontBBox, BlueValues, OtherBlues
+ tP+tArray, tP+tArray, tP+tNumber, tP+tNumber, // FamBlues, FamOthBlues, StdHW, StdVW
+ tNone, tNumber, tArray, tOffset, // escape, UniqueID, XUID, charset
+ tOffset, tOffset, tPrivateType, tP+tLocalOffset, // Encoding, CharStrings, Private, Subrs
+ tP+tNumber, tP+tNumber, tNone, tNone, // defaultWX, nominalWX, 22, 23
+ tNone, tNone, tNone, tNone, // 24, 25, 26, 27
+ tNone, tNone, tNone, tNone, // 28, 29, 30, 31
+ tSID, tBoolean, tNumber, tNumber, // Copyright, isFixedPitch, ItalicAngle, UnderlinePosition
+ tNumber, tNumber, tNumber, tArray6, // UnderlineThickness, PaintType, CharstringType, FontMatrix
+ tNumber, tP+tNumber, tP+tNumber, tP+tNumber, // StrokeWidth, BlueScale, BlueShift, BlueFuzz
+ tP+tArray, tP+tArray, tP+tBoolean, tNone, // StemSnapH, StemSnapV, ForceBold, 12 15
+ tNone, tP+tNumber, tP+tNumber, tP+tNumber, // 12 16, LanguageGroup, ExpansionFactor, initialRandomSeed
+ tNumber, tSID, tSID, tArray, // SyntheticBase, PostScript, BaseFontName, BaseFontBlend
+ tNone, tNone, tNone, tNone, // 12 24, 12 25, 12 26, 12 27
+ tNone, tNone, tArray, tNumber, // 12 28, 12 29, ROS, CIDFontVersion
+ tNumber, tNumber, tNumber, tNumber, // CIDFontRevision, CIDFontType, CIDCount, UIDBase
+ tOffset, tOffset, tSID // FDArray, FDSelect, FontName
+};
+
+static PermString::Initializer initializer;
+static const char * const standard_strings[] = {
+ // Automatically generated from Appendix A of the CFF specification; do
+ // not edit. Size should be 391.
+ ".notdef", "space", "exclam", "quotedbl", "numbersign", "dollar",
+ "percent", "ampersand", "quoteright", "parenleft", "parenright",
+ "asterisk", "plus", "comma", "hyphen", "period", "slash", "zero", "one",
+ "two", "three", "four", "five", "six", "seven", "eight", "nine", "colon",
+ "semicolon", "less", "equal", "greater", "question", "at", "A", "B", "C",
+ "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
+ "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft", "backslash",
+ "bracketright", "asciicircum", "underscore", "quoteleft", "a", "b", "c",
+ "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r",
+ "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright",
+ "asciitilde", "exclamdown", "cent", "sterling", "fraction", "yen",
+ "florin", "section", "currency", "quotesingle", "quotedblleft",
+ "guillemotleft", "guilsinglleft", "guilsinglright", "fi", "fl", "endash",
+ "dagger", "daggerdbl", "periodcentered", "paragraph", "bullet",
+ "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright",
+ "ellipsis", "perthousand", "questiondown", "grave", "acute", "circumflex",
+ "tilde", "macron", "breve", "dotaccent", "dieresis", "ring", "cedilla",
+ "hungarumlaut", "ogonek", "caron", "emdash", "AE", "ordfeminine", "Lslash",
+ "Oslash", "OE", "ordmasculine", "ae", "dotlessi", "lslash", "oslash", "oe",
+ "germandbls", "onesuperior", "logicalnot", "mu", "trademark", "Eth",
+ "onehalf", "plusminus", "Thorn", "onequarter", "divide", "brokenbar",
+ "degree", "thorn", "threequarters", "twosuperior", "registered", "minus",
+ "eth", "multiply", "threesuperior", "copyright", "Aacute", "Acircumflex",
+ "Adieresis", "Agrave", "Aring", "Atilde", "Ccedilla", "Eacute",
+ "Ecircumflex", "Edieresis", "Egrave", "Iacute", "Icircumflex", "Idieresis",
+ "Igrave", "Ntilde", "Oacute", "Ocircumflex", "Odieresis", "Ograve",
+ "Otilde", "Scaron", "Uacute", "Ucircumflex", "Udieresis", "Ugrave",
+ "Yacute", "Ydieresis", "Zcaron", "aacute", "acircumflex", "adieresis",
+ "agrave", "aring", "atilde", "ccedilla", "eacute", "ecircumflex",
+ "edieresis", "egrave", "iacute", "icircumflex", "idieresis", "igrave",
+ "ntilde", "oacute", "ocircumflex", "odieresis", "ograve", "otilde",
+ "scaron", "uacute", "ucircumflex", "udieresis", "ugrave", "yacute",
+ "ydieresis", "zcaron", "exclamsmall", "Hungarumlautsmall",
+ "dollaroldstyle", "dollarsuperior", "ampersandsmall", "Acutesmall",
+ "parenleftsuperior", "parenrightsuperior", "twodotenleader",
+ "onedotenleader", "zerooldstyle", "oneoldstyle", "twooldstyle",
+ "threeoldstyle", "fouroldstyle", "fiveoldstyle", "sixoldstyle",
+ "sevenoldstyle", "eightoldstyle", "nineoldstyle", "commasuperior",
+ "threequartersemdash", "periodsuperior", "questionsmall", "asuperior",
+ "bsuperior", "centsuperior", "dsuperior", "esuperior", "isuperior",
+ "lsuperior", "msuperior", "nsuperior", "osuperior", "rsuperior",
+ "ssuperior", "tsuperior", "ff", "ffi", "ffl", "parenleftinferior",
+ "parenrightinferior", "Circumflexsmall", "hyphensuperior", "Gravesmall",
+ "Asmall", "Bsmall", "Csmall", "Dsmall", "Esmall", "Fsmall", "Gsmall",
+ "Hsmall", "Ismall", "Jsmall", "Ksmall", "Lsmall", "Msmall", "Nsmall",
+ "Osmall", "Psmall", "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall",
+ "Vsmall", "Wsmall", "Xsmall", "Ysmall", "Zsmall", "colonmonetary",
+ "onefitted", "rupiah", "Tildesmall", "exclamdownsmall", "centoldstyle",
+ "Lslashsmall", "Scaronsmall", "Zcaronsmall", "Dieresissmall", "Brevesmall",
+ "Caronsmall", "Dotaccentsmall", "Macronsmall", "figuredash",
+ "hypheninferior", "Ogoneksmall", "Ringsmall", "Cedillasmall",
+ "questiondownsmall", "oneeighth", "threeeighths", "fiveeighths",
+ "seveneighths", "onethird", "twothirds", "zerosuperior", "foursuperior",
+ "fivesuperior", "sixsuperior", "sevensuperior", "eightsuperior",
+ "ninesuperior", "zeroinferior", "oneinferior", "twoinferior",
+ "threeinferior", "fourinferior", "fiveinferior", "sixinferior",
+ "seveninferior", "eightinferior", "nineinferior", "centinferior",
+ "dollarinferior", "periodinferior", "commainferior", "Agravesmall",
+ "Aacutesmall", "Acircumflexsmall", "Atildesmall", "Adieresissmall",
+ "Aringsmall", "AEsmall", "Ccedillasmall", "Egravesmall", "Eacutesmall",
+ "Ecircumflexsmall", "Edieresissmall", "Igravesmall", "Iacutesmall",
+ "Icircumflexsmall", "Idieresissmall", "Ethsmall", "Ntildesmall",
+ "Ogravesmall", "Oacutesmall", "Ocircumflexsmall", "Otildesmall",
+ "Odieresissmall", "OEsmall", "Oslashsmall", "Ugravesmall", "Uacutesmall",
+ "Ucircumflexsmall", "Udieresissmall", "Yacutesmall", "Thornsmall",
+ "Ydieresissmall", "001.000", "001.001", "001.002", "001.003", "Black",
+ "Bold", "Book", "Light", "Medium", "Regular", "Roman", "Semibold"
+};
+static PermString standard_permstrings[Cff::NSTANDARD_STRINGS];
+static HashMap<PermString, int> standard_permstrings_map(-1);
+
+static const int standard_encoding[] = {
+ // Automatically generated from Appendix B of the CFF specification; do
+ // not edit. Size should be 256.
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
+ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
+ 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
+ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
+ 79, 80, 81, 82, 83, 84, 85, 86, 87, 88,
+ 89, 90, 91, 92, 93, 94, 95, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 96, 97, 98, 99, 100, 101, 102, 103, 104,
+ 105, 106, 107, 108, 109, 110, 0, 111, 112, 113,
+ 114, 0, 115, 116, 117, 118, 119, 120, 121, 122,
+ 0, 123, 0, 124, 125, 126, 127, 128, 129, 130,
+ 131, 0, 132, 133, 0, 134, 135, 136, 137, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 138, 0, 139, 0, 0,
+ 0, 0, 140, 141, 142, 143, 0, 0, 0, 0,
+ 0, 144, 0, 0, 0, 145, 0, 0, 146, 147,
+ 148, 149, 0, 0, 0, 0
+};
+
+static const int expert_encoding[] = {
+ // Automatically generated from Appendix B of the CFF specification; do
+ // not edit. Size should be 256.
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 229, 230, 0, 231, 232, 233, 234,
+ 235, 236, 237, 238, 13, 14, 15, 99, 239, 240,
+ 241, 242, 243, 244, 245, 246, 247, 248, 27, 28,
+ 249, 250, 251, 252, 0, 253, 254, 255, 256, 257,
+ 0, 0, 0, 258, 0, 0, 259, 260, 261, 262,
+ 0, 0, 263, 264, 265, 0, 266, 109, 110, 267,
+ 268, 269, 0, 270, 271, 272, 273, 274, 275, 276,
+ 277, 278, 279, 280, 281, 282, 283, 284, 285, 286,
+ 287, 288, 289, 290, 291, 292, 293, 294, 295, 296,
+ 297, 298, 299, 300, 301, 302, 303, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 304, 305, 306, 0, 0, 307, 308, 309, 310,
+ 311, 0, 312, 0, 0, 313, 0, 0, 314, 315,
+ 0, 0, 316, 317, 318, 0, 0, 0, 158, 155,
+ 163, 319, 320, 321, 322, 323, 324, 325, 0, 0,
+ 326, 150, 164, 169, 327, 328, 329, 330, 331, 332,
+ 333, 334, 335, 336, 337, 338, 339, 340, 341, 342,
+ 343, 344, 345, 346, 347, 348, 349, 350, 351, 352,
+ 353, 354, 355, 356, 357, 358, 359, 360, 361, 362,
+ 363, 364, 365, 366, 367, 368, 369, 370, 371, 372,
+ 373, 374, 375, 376, 377, 378
+};
+
+static const int iso_adobe_charset[] = {
+ // Automatically generated from Appendix C of the CFF specification; do
+ // not edit.
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+ 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
+ 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
+ 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
+ 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
+ 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
+ 160, 161, 162, 163, 164, 165, 166, 167, 168, 169,
+ 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
+ 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
+ 190, 191, 192, 193, 194, 195, 196, 197, 198, 199,
+ 200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
+ 210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
+ 220, 221, 222, 223, 224, 225, 226, 227, 228
+};
+
+static const int expert_charset[] = {
+ // Automatically generated from Appendix C of the CFF specification; do
+ // not edit.
+ 0, 1, 229, 230, 231, 232, 233, 234, 235, 236,
+ 237, 238, 13, 14, 15, 99, 239, 240, 241, 242,
+ 243, 244, 245, 246, 247, 248, 27, 28, 249, 250,
+ 251, 252, 253, 254, 255, 256, 257, 258, 259, 260,
+ 261, 262, 263, 264, 265, 266, 109, 110, 267, 268,
+ 269, 270, 271, 272, 273, 274, 275, 276, 277, 278,
+ 279, 280, 281, 282, 283, 284, 285, 286, 287, 288,
+ 289, 290, 291, 292, 293, 294, 295, 296, 297, 298,
+ 299, 300, 301, 302, 303, 304, 305, 306, 307, 308,
+ 309, 310, 311, 312, 313, 314, 315, 316, 317, 318,
+ 158, 155, 163, 319, 320, 321, 322, 323, 324, 325,
+ 326, 150, 164, 169, 327, 328, 329, 330, 331, 332,
+ 333, 334, 335, 336, 337, 338, 339, 340, 341, 342,
+ 343, 344, 345, 346, 347, 348, 349, 350, 351, 352,
+ 353, 354, 355, 356, 357, 358, 359, 360, 361, 362,
+ 363, 364, 365, 366, 367, 368, 369, 370, 371, 372,
+ 373, 374, 375, 376, 377, 378
+};
+
+static const int expert_subset_charset[] = {
+ // Automatically generated from Appendix C of the CFF specification; do
+ // not edit.
+ 0, 1, 231, 232, 235, 236, 237, 238, 13, 14,
+ 15, 99, 239, 240, 241, 242, 243, 244, 245, 246,
+ 247, 248, 27, 28, 249, 250, 251, 253, 254, 255,
+ 256, 257, 258, 259, 260, 261, 262, 263, 264, 265,
+ 266, 109, 110, 267, 268, 269, 270, 272, 300, 301,
+ 302, 305, 314, 315, 158, 155, 163, 320, 321, 322,
+ 323, 324, 325, 326, 150, 164, 169, 327, 328, 329,
+ 330, 331, 332, 333, 334, 335, 336, 337, 338, 339,
+ 340, 341, 342, 343, 344, 345, 346
+};
+
+static const uint8_t default_dict_cff_data[] = {
+ // CFF header
+ 1, 0, // format major and minor version
+ 4, // header size
+ 4, // absolute offset size
+
+ // Name INDEX
+ 0, 1, // one element in index
+ 1, // offset size
+ 1, 14, // offset array
+ '%', 'D', 'E', 'F', 'A', 'U', 'L', 'T', 'D', 'I', 'C', 'T', '%',
+
+ // Top DICT INDEX
+ 0, 1, // one element in index
+ 1, // offset size
+ 1, 92, // offset array
+ // and the DICT
+ 139, 12, 1, // isFixedPitch false
+ 139, 12, 2, // ItalicAngle 0
+ 39, 12, 3, // UnderlinePosition -100
+ 189, 12, 4, // UnderlineThickness 50
+ 139, 12, 5, // PaintType 0
+ 141, 12, 6, // CharstringType 2
+ 30, 0x0A, 0x00, 0x1F, 139, 139, 30, 0x0A, 0x00, 0x1F, 139, 139, 12, 7,
+ // FontMatrix 0.001 0 0 0.001 0 0
+ 139, 139, 139, 139, 5, // FontBBox 0 0 0 0
+ 139, 12, 8, // StrokeWidth 0
+ 139, 15, // charset 0
+ 139, 16, // Encoding 0
+ 139, 12, 31, // CIDFontVersion 0
+ 139, 12, 32, // CIDFontRevision 0
+ 139, 12, 33, // CIDFontType 0
+ 28, 34, 16, 12, 34, // CIDCount 8720
+ 30, 0x0A, 0x03, 0x96, 0x25, 0xFF, 12, 9, // BlueScale 0.039625
+ 146, 12, 10, // BlueShift 7
+ 140, 12, 11, // BlueFuzz 1
+ 139, 12, 14, // ForceBold false
+ 139, 12, 17, // LanguageGroup 0
+ 30, 0x0A, 0x06, 0xFF, 12, 18, // ExpansionFactor 0.06
+ 139, 12, 19, // initialRandomSeed 0
+ 139, 20, // defaultWidthX 0
+ 139, 21, // nominalWidthX 0
+
+ // String INDEX
+ 0, 0,
+
+ // Gsubr INDEX
+ 0, 0
+};
+
+static const Cff::Dict &
+default_dict()
+{
+ static Cff *cff;
+ static Cff::Font *cfffont;
+ if (!cfffont) {
+ cff = new Cff(String::make_stable((const char *) default_dict_cff_data, sizeof(default_dict_cff_data)), ErrorHandler::default_handler());
+ cfffont = (Cff::Font *) cff->font();
+ }
+ return cfffont->top_dict();
+}
+
+
+#define POS_GT(pos1, pos2) ((unsigned)(pos1) > (unsigned)(pos2))
+
+
+Cff::Cff(const String &s, ErrorHandler *errh)
+ : _data_string(s), _data(reinterpret_cast<const uint8_t *>(_data_string.data())), _len(_data_string.length()),
+ _strings_map(-2)
+{
+ static_assert((sizeof(standard_strings) / sizeof(standard_strings[0])) == NSTANDARD_STRINGS);
+ static_assert((sizeof(standard_encoding) / sizeof(standard_encoding[0])) == 256);
+ static_assert((sizeof(expert_encoding) / sizeof(expert_encoding[0])) == 256);
+ _error = parse_header(errh ? errh : ErrorHandler::silent_handler());
+}
+
+Cff::~Cff()
+{
+ for (int i = 0; i < _gsubrs_cs.size(); i++)
+ delete _gsubrs_cs[i];
+}
+
+/*
+ * Parsing the file header
+ */
+
+int
+Cff::parse_header(ErrorHandler *errh)
+{
+ if (_gsubrs_index.error() >= 0) // already done
+ return 0;
+
+ // parse header
+ if (_len == 0)
+ return errh->error("not a PostScript-flavored OpenType font"), -EFAULT;
+ if (_len < HEADER_SIZE)
+ return errh->error("CFF file too small for header (have %d, want %d)", _len, HEADER_SIZE), -EFAULT;
+ if (_data[0] != 1) // major version number
+ return errh->error("bad major version number %d", _data[0]), -ERANGE;
+ int hdrSize = _data[2], offSize = _data[3];
+ if (hdrSize < 4 || hdrSize > _len || offSize < 1 || offSize > 4)
+ return errh->error("corrupted file header"), -EINVAL;
+ int name_index_pos = hdrSize;
+
+ // parse name INDEX
+ IndexIterator niter(_data, name_index_pos, _len, errh, "Name INDEX");
+ if (niter.error() < 0)
+ return niter.error();
+ _name_index.clear();
+ for (; niter; niter++) {
+ const uint8_t *d0 = niter[0];
+ const uint8_t *d1 = niter[1];
+ if (d0 == d1 || d0[0] == 0)
+ _name_index.push_back(PermString());
+ else
+ _name_index.push_back(PermString(reinterpret_cast<const char *>(d0), d1 - d0));
+ }
+ int top_dict_index_pos = niter.index_end() - _data;
+
+ // check top DICT INDEX
+ _top_dict_index = IndexIterator(_data, top_dict_index_pos, _len, errh, "Top DICT INDEX");
+ if (_top_dict_index.error() < 0)
+ return _top_dict_index.error();
+ else if (_top_dict_index.nitems() != nfonts())
+ return errh->error("invalid font: Top DICT INDEX has %d elements, but there are %d fonts", _top_dict_index.nitems(), nfonts()), -EINVAL;
+ int string_index_pos = _top_dict_index.index_end() - _data;
+
+ // check strings INDEX
+ _strings_index = IndexIterator(_data, string_index_pos, _len, errh, "Strings INDEX");
+ if (_strings_index.error() < 0)
+ return _strings_index.error();
+ else if (NSTANDARD_STRINGS + _strings_index.nitems() - 1 > MAX_SID)
+ return errh->error("too many strings defined in font"), -EINVAL;
+ _strings.assign(_strings_index.nitems(), PermString());
+ int global_subr_index_pos = _strings_index.index_end() - _data;
+
+ // check gsubr INDEX
+ _gsubrs_index = IndexIterator(_data, global_subr_index_pos, _len, errh, "Gsubrs INDEX");
+ if (_gsubrs_index.error() < 0)
+ return _gsubrs_index.error();
+ _gsubrs_cs.assign(ngsubrs(), 0);
+
+ return 0;
+}
+
+int
+Cff::sid(PermString s)
+{
+ if (!s) // XXX?
+ return -1;
+
+ // check standard strings
+ if (standard_permstrings_map["a"] < 0)
+ for (int i = 0; i < NSTANDARD_STRINGS; i++) {
+ if (!standard_permstrings[i])
+ standard_permstrings[i] = PermString(standard_strings[i]);
+ standard_permstrings_map.insert(standard_permstrings[i], i);
+ }
+ int sid = standard_permstrings_map[s];
+ if (sid >= 0)
+ return sid;
+
+ // check user strings
+ sid = _strings_map[s];
+ if (sid >= -1)
+ return sid;
+
+ for (int i = 0; i < _strings.size(); i++)
+ if (!_strings[i] && s.length() == _strings_index[i+1] - _strings_index[i] && memcmp(s.c_str(), _strings_index[i], s.length()) == 0) {
+ _strings[i] = s;
+ _strings_map.insert(s, i + NSTANDARD_STRINGS);
+ return i + NSTANDARD_STRINGS;
+ }
+
+ _strings_map.insert(s, -1);
+ return -1;
+}
+
+String
+Cff::sid_string(int sid) const
+{
+ if (sid < 0)
+ return String();
+ else if (sid < NSTANDARD_STRINGS)
+ return String(sid_permstring(sid));
+ else {
+ sid -= NSTANDARD_STRINGS;
+ if (sid >= _strings.size())
+ return String();
+ else if (_strings[sid])
+ return String(_strings[sid]);
+ else
+ return String(reinterpret_cast<const char *>(_strings_index[sid]), _strings_index[sid + 1] - _strings_index[sid]);
+ }
+}
+
+PermString
+Cff::sid_permstring(int sid) const
+{
+ if (sid < 0)
+ return PermString();
+ else if (sid < NSTANDARD_STRINGS) {
+ if (!standard_permstrings[sid])
+ standard_permstrings[sid] = PermString(standard_strings[sid]);
+ return standard_permstrings[sid];
+ } else {
+ sid -= NSTANDARD_STRINGS;
+ if (sid >= _strings.size())
+ return PermString();
+ else if (_strings[sid])
+ return _strings[sid];
+ else {
+ PermString s = PermString(reinterpret_cast<const char *>(_strings_index[sid]), _strings_index[sid + 1] - _strings_index[sid]);
+ _strings[sid] = s;
+ _strings_map.insert(s, sid + NSTANDARD_STRINGS);
+ return s;
+ }
+ }
+}
+
+int
+Cff::font_offset(int findex, int &offset, int &length) const
+{
+ if (findex < 0 || findex >= nfonts())
+ return -ENOENT;
+ offset = _top_dict_index[findex] - _data;
+ length = _top_dict_index[findex + 1] - _top_dict_index[findex];
+ return 0;
+}
+
+int
+Cff::font_offset(PermString name, int &offset, int &length) const
+{
+ for (int i = 0; i < _name_index.size(); i++)
+ if (_name_index[i] == name && name)
+ return font_offset(i, offset, length);
+ return -ENOENT;
+}
+
+Cff::FontParent *
+Cff::font(PermString font_name, ErrorHandler *errh)
+{
+ if (!errh)
+ errh = ErrorHandler::silent_handler();
+
+ if (!ok())
+ return errh->error("invalid CFF"), (FontParent *) 0;
+
+ // search for a font named 'font_name'
+ for (int i = 0; i < _name_index.size(); i++)
+ if (_name_index[i] && (!font_name || font_name == _name_index[i])) {
+ int td_offset = _top_dict_index[i] - _data;
+ int td_length = _top_dict_index[i + 1] - _top_dict_index[i];
+ Dict top_dict(this, td_offset, td_length, errh, "Top DICT");
+ if (!top_dict.ok())
+ return 0;
+ else if (top_dict.has_first(oROS))
+ return new Cff::CIDFont(this, _name_index[i], top_dict, errh);
+ else
+ return new Cff::Font(this, _name_index[i], top_dict, errh);
+ }
+
+ if (!font_name)
+ errh->error("no fonts in CFF");
+ else
+ errh->error("font '%s' not found", font_name.c_str());
+ return 0;
+}
+
+static inline int
+subr_bias(int charstring_type, int nsubrs)
+{
+ if (charstring_type == 1)
+ return 0;
+ else if (nsubrs < 1240)
+ return 107;
+ else if (nsubrs < 33900)
+ return 1131;
+ else
+ return 32768;
+}
+
+Charstring *
+Cff::gsubr(int i)
+{
+ i += subr_bias(2, ngsubrs());
+ if (i < 0 || i >= ngsubrs())
+ return 0;
+ if (!_gsubrs_cs[i]) {
+ const uint8_t *s1 = _gsubrs_index[i];
+ int slen = _gsubrs_index[i + 1] - s1;
+ String cs = data_string().substring(s1 - data(), slen);
+ if (slen == 0)
+ return 0;
+ else
+ _gsubrs_cs[i] = new Type2Charstring(cs);
+ }
+ return _gsubrs_cs[i];
+}
+
+
+/*****
+ * Cff::Charset
+ **/
+
+Cff::Charset::Charset(const Cff *cff, int pos, int nglyphs, int max_sid, ErrorHandler *errh)
+{
+ assign(cff, pos, nglyphs, max_sid, errh);
+}
+
+void
+Cff::Charset::assign(const Cff *cff, int pos, int nglyphs, int max_sid, ErrorHandler *errh)
+{
+ if (!errh)
+ errh = ErrorHandler::silent_handler();
+
+ _sids.reserve(nglyphs);
+
+ if (pos == 0)
+ assign(iso_adobe_charset, sizeof(iso_adobe_charset) / sizeof(int), nglyphs);
+ else if (pos == 1)
+ assign(expert_charset, sizeof(expert_charset) / sizeof(int), nglyphs);
+ else if (pos == 2)
+ assign(expert_subset_charset, sizeof(expert_subset_charset) / sizeof(int), nglyphs);
+ else
+ _error = parse(cff, pos, nglyphs, max_sid, errh);
+
+ if (_error >= 0)
+ for (int g = 0; g < _sids.size(); g++) {
+ if (_gids[_sids[g]] >= 0) {
+ errh->error("glyph '%s' in charset twice", cff->sid_permstring(_sids[g]).c_str());
+ _error = -EEXIST;
+ }
+ _gids[_sids[g]] = g;
+ }
+}
+
+void
+Cff::Charset::assign(const int *data, int size, int nglyphs)
+{
+ if (size < nglyphs)
+ size = nglyphs;
+ _sids.resize(size);
+ memcpy(&_sids[0], data, sizeof(const int) * size);
+ _gids.resize(data[size-1] + 1, -1);
+ _error = 0;
+}
+
+int
+Cff::Charset::parse(const Cff *cff, int pos, int nglyphs, int max_sid, ErrorHandler *errh)
+{
+ const uint8_t *data = cff->data();
+ int len = cff->length();
+
+ if (pos + 1 > len)
+ return errh->error("charset position out of range"), -EFAULT;
+
+ _sids.push_back(0);
+ int actual_max_sid = 0;
+
+ int format = data[pos];
+ if (format == 0) {
+ if (pos + 1 + (nglyphs - 1) * 2 > len)
+ return errh->error("charset [format 0] out of range"), -EFAULT;
+ const uint8_t *p = data + pos + 1;
+ for (; _sids.size() < nglyphs; p += 2) {
+ int sid = (p[0] << 8) | p[1];
+ if (sid > actual_max_sid)
+ actual_max_sid = sid;
+ _sids.push_back(sid);
+ }
+
+ } else if (format == 1) {
+ const uint8_t *p = data + pos + 1;
+ for (; _sids.size() < nglyphs; p += 3) {
+ if (p + 3 > data + len)
+ return errh->error("charset [format 1] out of range"), -EFAULT;
+ int sid = (p[0] << 8) | p[1];
+ int n = p[2];
+ if (sid + n > actual_max_sid)
+ actual_max_sid = sid + n;
+ for (int i = 0; i <= n; i++)
+ _sids.push_back(sid + i);
+ }
+
+ } else if (format == 2) {
+ const uint8_t *p = data + pos + 1;
+ for (; _sids.size() < nglyphs; p += 4) {
+ if (p + 4 > data + len)
+ return errh->error("charset [format 2] out of range"), -EFAULT;
+ int sid = (p[0] << 8) | p[1];
+ int n = (p[2] << 8) | p[3];
+ if (sid + n > actual_max_sid)
+ actual_max_sid = sid + n;
+ for (int i = 0; i <= n; i++)
+ _sids.push_back(sid + i);
+ }
+
+ } else
+ return errh->error("unknown charset format %d", format), -EINVAL;
+
+ if (max_sid >= 0 && actual_max_sid > max_sid)
+ return errh->error("charset [format %d] uses bad SID %d", format, actual_max_sid), -EINVAL;
+ _sids.resize(nglyphs);
+ _gids.resize(actual_max_sid + 1, -1);
+ return 0;
+}
+
+
+/*****
+ * Cff::FDSelect
+ **/
+
+void
+Cff::FDSelect::assign(const Cff *cff, int pos, int nglyphs, ErrorHandler *errh)
+{
+ if (!errh)
+ errh = ErrorHandler::silent_handler();
+ if (_my_fds)
+ delete[] _fds;
+ _fds = 0;
+ _my_fds = false;
+ _nglyphs = nglyphs;
+ _error = parse(cff, pos, nglyphs, errh);
+}
+
+Cff::FDSelect::~FDSelect()
+{
+ if (_my_fds)
+ delete[] _fds;
+}
+
+int
+Cff::FDSelect::parse(const Cff *cff, int pos, int nglyphs, ErrorHandler *errh)
+{
+ const uint8_t *data = cff->data();
+ int len = cff->length();
+
+ if (pos + 1 > len)
+ return errh->error("FDSelect position out of range"), -EFAULT;
+
+ int format = data[pos];
+ if (format == 0) {
+ if (pos + 1 + nglyphs > len)
+ return errh->error("FDSelect [format 0] out of range"), -EFAULT;
+ _fds = data + pos + 1;
+ _my_fds = false;
+ return 0;
+
+ } else if (format == 3) {
+ int nranges = (data[pos+1] << 8) | data[pos+2];
+ if (pos + 3 + 3*nranges + 2 > len)
+ return errh->error("FDSelect [format 3] out of range"), -EFAULT;
+
+ const uint8_t *p = data + pos + 3;
+ int last_glyph = (p[3*nranges] << 8) | p[3*nranges + 1];
+ if (p[0] || p[1] || last_glyph != nglyphs)
+ return errh->error("FDSelect [format 3] bad values"), -EINVAL;
+
+ _fds = new uint8_t[nglyphs];
+ _my_fds = true;
+ int curglyph = 0;
+ for (; curglyph < nglyphs; p += 3) {
+ int nextglyph = (p[3] << 8) | p[4];
+ if (nextglyph > nglyphs || nextglyph < curglyph)
+ return errh->error("FDSelect [format 3] sorting error"), -EINVAL;
+ memset(const_cast<uint8_t *>(_fds + curglyph), p[2], nextglyph - curglyph);
+ curglyph = nextglyph;
+ }
+ return 0;
+
+ } else
+ return errh->error("unknown charset format %d", format), -EINVAL;
+}
+
+
+/*****
+ * Cff::IndexIterator
+ **/
+
+Cff::IndexIterator::IndexIterator(const uint8_t *data, int pos, int len, ErrorHandler *errh, const char *index_name)
+ : _contents(0), _offset(0), _last_offset(0)
+{
+ if (!errh)
+ errh = ErrorHandler::silent_handler();
+
+ // check header
+ int nitems = 0;
+ if (POS_GT(pos + 2, len)) {
+ errh->error("%s: position out of range", index_name);
+ _offsize = -EFAULT;
+ } else if (data[pos] == 0 && data[pos + 1] == 0) {
+ _contents = data + pos + 2;
+ _offsize = 0;
+ } else if (POS_GT(pos + 3, len)) {
+ errh->error("%s: position out of range", index_name);
+ _offsize = -EFAULT;
+ } else if ((_offsize = data[pos + 2]), (_offsize < 1 || _offsize > 4)) {
+ errh->error("%s: offset size %d out of range", index_name, _offsize);
+ _offsize = -EINVAL;
+ } else {
+ nitems = (data[pos] << 8) | data[pos + 1];
+ if (POS_GT(pos + 3 + (nitems + 1) * _offsize, len)) {
+ errh->error("%s: data out of range", index_name);
+ _offsize = -EFAULT;
+ } else {
+ _offset = data + pos + 3;
+ _last_offset = _offset + nitems * _offsize;
+ _contents = _last_offset + _offsize - 1;
+ }
+ }
+
+ // check items in offset array
+ uint32_t max_doff_allowed = len - (pos + 2 + (nitems + 1) * _offsize);
+ uint32_t last_doff = 1;
+ for (const uint8_t *o = _offset; o <= _last_offset && _offsize > 0; o += _offsize) {
+ uint32_t doff = offset_at(o);
+ if (doff > max_doff_allowed) {
+ errh->error("%s: element out of range", index_name);
+ _offsize = -EFAULT;
+ } else if (doff < last_doff) {
+ errh->error("%s: garbled elements", index_name);
+ break;
+ }
+ last_doff = doff;
+ }
+}
+
+const uint8_t *
+Cff::IndexIterator::index_end() const
+{
+ if (_offsize <= 0)
+ return _contents;
+ else
+ return _contents + offset_at(_last_offset);
+}
+
+int
+Cff::IndexIterator::nitems() const
+{
+ if (_offsize <= 0)
+ return 0;
+ else
+ return (_last_offset - _offset) / _offsize;
+}
+
+
+
+/*****
+ * Cff::Dict
+ **/
+
+Cff::Dict::Dict()
+ : _cff(0), _pos(0), _error(-ENOENT)
+{
+}
+
+Cff::Dict::Dict(Cff *cff, int pos, int dict_len, ErrorHandler *errh, const char *dict_name)
+{
+ assign(cff, pos, dict_len, errh, dict_name);
+}
+
+int
+Cff::Dict::assign(Cff *cff, int pos, int dict_len, ErrorHandler *errh, const char *dict_name)
+{
+ _cff = cff;
+ _pos = pos;
+ _operators.clear();
+ _pointers.clear();
+ _operands.clear();
+
+ if (!errh)
+ errh = ErrorHandler::silent_handler();
+
+ const uint8_t *data = cff->data() + pos;
+ const uint8_t *end_data = data + dict_len;
+
+ _pointers.push_back(0);
+ while (data < end_data)
+ switch (data[0]) {
+
+ case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
+ case 8: case 9: case 10: case 11: case 13: case 14: case 15:
+ case 16: case 17: case 18: case 19: case 20: case 21:
+ _operators.push_back(data[0]);
+ _pointers.push_back(_operands.size());
+ data++;
+ break;
+
+ case 22: case 23: case 24: case 25: case 26: case 27: case 31:
+ case 255: // reserved
+ errh->error("%s: reserved operator %d", dict_name, data[0]);
+ return (_error = -ERANGE);
+
+ case 12:
+ if (data + 1 >= end_data)
+ goto runoff;
+ _operators.push_back(32 + data[1]);
+ _pointers.push_back(_operands.size());
+ data += 2;
+ break;
+
+ case 28: {
+ if (data + 2 >= end_data)
+ goto runoff;
+ int16_t val = (data[1] << 8) | data[2];
+ _operands.push_back(val);
+ data += 3;
+ break;
+ }
+
+ case 29: {
+ if (data + 4 >= end_data)
+ goto runoff;
+ int32_t val = (data[1] << 24) | (data[2] << 16) | (data[3] << 8) | data[4];
+ _operands.push_back(val);
+ data += 5;
+ break;
+ }
+
+ case 30: {
+ char buf[1024];
+ int pos = 0;
+ if (data + 1 >= end_data)
+ goto runoff;
+ for (data++; data < end_data && pos < 1020; data++) {
+ int d = *data;
+ for (int i = 0; i < 2; i++, d <<= 4) {
+ int digit = (d >> 4) & 0xF;
+ switch (digit) {
+ case 10:
+ buf[pos++] = '.';
+ break;
+ case 11:
+ buf[pos++] = 'E';
+ break;
+ case 12:
+ buf[pos++] = 'E';
+ buf[pos++] = '-';
+ break;
+ case 13:
+ errh->error("%s: bad digit in real number", dict_name);
+ goto invalid;
+ case 14:
+ buf[pos++] = '-';
+ break;
+ case 15:
+ goto found;
+ default:
+ buf[pos++] = digit + '0';
+ break;
+ }
+ }
+ }
+ // number not found
+ goto runoff;
+ found:
+ char *endptr;
+ buf[pos] = '\0';
+ _operands.push_back(strtod(buf, &endptr));
+ if (*endptr) {
+ errh->error("%s: real number syntax error", dict_name);
+ goto invalid;
+ }
+ data++;
+ break;
+ }
+
+ case 247: case 248: case 249: case 250: {
+ if (data + 1 >= end_data)
+ goto runoff;
+ int val = ((data[0] - 247) << 8) + data[1] + 108;
+ _operands.push_back(val);
+ data += 2;
+ break;
+ }
+
+ case 251: case 252: case 253: case 254: {
+ if (data + 1 >= end_data)
+ goto runoff;
+ int val = -((data[0] - 251) << 8) - data[1] - 108;
+ _operands.push_back(val);
+ data += 2;
+ break;
+ }
+
+ default:
+ _operands.push_back(data[0] - 139);
+ data++;
+ break;
+
+ }
+
+ // not closed by an operator?
+ if (_pointers.back() != _operands.size()) {
+ errh->error("%s: not closed by an operator", dict_name);
+ goto invalid;
+ }
+
+ return (_error = 0);
+
+ runoff:
+ errh->error("%s: runoff end of DICT", dict_name);
+ return (_error = -EFAULT);
+
+ invalid:
+ return (_error = -EINVAL);
+}
+
+int
+Cff::Dict::check(bool is_private, ErrorHandler *errh, const char *dict_name) const
+{
+ if (!errh)
+ errh = ErrorHandler::silent_handler();
+ int before_nerrors = errh->nerrors();
+
+ // keep track of operator reuse
+ Vector<int> operators_used;
+
+ for (int i = 0; i < _operators.size(); i++) {
+ int arity = _pointers[i+1] - _pointers[i];
+ double num = (arity == 0 ? 0 : _operands[_pointers[i]]);
+ double truncnum = floor(num);
+ int op = _operators[i];
+ int type = (op > oLastOperator ? tNone : operator_types[op]);
+
+ // check reuse
+ if (op >= operators_used.size())
+ operators_used.resize(op + 1, 0);
+ if (operators_used[op] && (type & tTypeMask) != tNone)
+ errh->error("%s: operator '%s' specified twice", dict_name, operator_names[op]);
+ operators_used[op]++;
+
+ // check data
+ switch (type & tTypeMask) {
+
+ case tNone:
+ if (op >= 32)
+ errh->warning("%s: unknown operator '12 %d'", dict_name, op - 32);
+ else
+ errh->warning("%s: unknown operator '%d'", dict_name, op);
+ continue;
+
+ case tSID:
+ if (arity != 1 || num != truncnum || num < 0 || num > _cff->max_sid())
+ goto bad_data;
+ break;
+
+ case tFontNumber:
+ if (arity != 1 || num != truncnum || num < 0 || num >= _cff->nfonts())
+ goto bad_data;
+ break;
+
+ case tBoolean:
+ if (arity != 1)
+ goto bad_data;
+ else if (num != 0 && num != 1)
+ errh->warning("%s: data for Boolean operator '%s' not 0 or 1", dict_name, operator_names[op]);
+ break;
+
+ case tNumber:
+ if (arity != 1)
+ goto bad_data;
+ break;
+
+ case tOffset:
+ if (arity != 1 || num != truncnum || num < 0 || num >= _cff->length())
+ goto bad_data;
+ break;
+
+ case tLocalOffset:
+ if (arity != 1 || num != truncnum || _pos + num < 0 || _pos + num >= _cff->length())
+ goto bad_data;
+ break;
+
+ case tPrivateType: {
+ if (arity != 2 || num != truncnum || num < 0)
+ goto bad_data;
+ double off = _operands[_pointers[i] + 1];
+ if (off < 0 || off + num > _cff->length())
+ goto bad_data;
+ break;
+ }
+
+ case tArray2: case tArray3: case tArray4:
+ case tArray5: case tArray6:
+ if (arity != (type & tTypeMask) - tArray2 + 2)
+ goto bad_data;
+ break;
+
+ case tArray:
+ break;
+
+ }
+
+ // check dict location
+ if (((type & tPrivate) != 0) != is_private)
+ errh->warning("%s: operator '%s' in wrong DICT", dict_name, operator_names[op]);
+
+ continue;
+
+ bad_data:
+ errh->error("%s: bad data for operator '%s'", dict_name, operator_names[op]);
+ }
+
+ return (errh->nerrors() != before_nerrors ? -1 : 0);
+}
+
+bool
+Cff::Dict::has(DictOperator op) const
+{
+ for (int i = 0; i < _operators.size(); i++)
+ if (_operators[i] == op)
+ return true;
+ return false;
+}
+
+bool
+Cff::Dict::xvalue(DictOperator op, Vector<double> &out) const
+{
+ out.clear();
+ for (int i = 0; i < _operators.size(); i++)
+ if (_operators[i] == op) {
+ for (int j = _pointers[i]; j < _pointers[i+1]; j++)
+ out.push_back(_operands[j]);
+ return true;
+ }
+ return false;
+}
+
+bool
+Cff::Dict::xvalue(DictOperator op, int *val) const
+{
+ for (int i = 0; i < _operators.size(); i++)
+ if (_operators[i] == op && _pointers[i] + 1 == _pointers[i+1]) {
+ *val = (int) _operands[_pointers[i]];
+ return true;
+ }
+ return false;
+}
+
+bool
+Cff::Dict::xvalue(DictOperator op, double *val) const
+{
+ for (int i = 0; i < _operators.size(); i++)
+ if (_operators[i] == op && _pointers[i] + 1 == _pointers[i+1]) {
+ *val = _operands[_pointers[i]];
+ return true;
+ }
+ return false;
+}
+
+bool
+Cff::Dict::value(DictOperator op, Vector<double> &out) const
+{
+ return xvalue(op, out) || default_dict().xvalue(op, out);
+}
+
+bool
+Cff::Dict::value(DictOperator op, int *val) const
+{
+ return xvalue(op, val) || default_dict().xvalue(op, val);
+}
+
+bool
+Cff::Dict::value(DictOperator op, double *val) const
+{
+ return xvalue(op, val) || default_dict().xvalue(op, val);
+}
+
+void
+Cff::Dict::unparse(ErrorHandler *errh, const char *dict_name) const
+{
+ StringAccum sa;
+ for (int i = 0; i < _operators.size(); i++) {
+ sa.clear();
+ if (_pointers[i] + 1 == _pointers[i+1])
+ sa << _operands[_pointers[i]];
+ else {
+ sa << "[";
+ for (int j = _pointers[i]; j < _pointers[i+1]; j++)
+ sa << _operands[j] << ' ';
+ sa.pop_back();
+ sa << "]";
+ }
+ errh->message("%s: %s %s", dict_name, operator_names[_operators[i]], sa.c_str());
+ }
+}
+
+
+/*****
+ * CffFontParent
+ **/
+
+static int
+handle_private(Cff *cff, const Cff::Dict &top_dict, Cff::Dict &private_dict,
+ double &default_width_x, double &nominal_width_x,
+ Cff::IndexIterator &subrs_index, Vector<Charstring *> &subrs_cs,
+ ErrorHandler *errh)
+{
+ Vector<double> private_info;
+ top_dict.value(Cff::oPrivate, private_info);
+ int private_offset = (int) private_info[1];
+ private_dict.assign(cff, private_offset, (int) private_info[0], errh, "Private DICT");
+ if (private_dict.error() < 0)
+ return private_dict.error();
+ else if (private_dict.check(true, errh, "Private DICT") < 0)
+ return -EINVAL;
+ //private_dict.unparse(errh, "Private DICT");
+
+ private_dict.value(Cff::oDefaultWidthX, &default_width_x);
+ private_dict.value(Cff::oNominalWidthX, &nominal_width_x);
+ if (private_dict.has(Cff::oSubrs)) {
+ int subrs_offset = 0;
+ private_dict.value(Cff::oSubrs, &subrs_offset);
+ subrs_index = Cff::IndexIterator(cff->data(), private_offset + subrs_offset, cff->length(), errh, "Subrs INDEX");
+ if (subrs_index.error() < 0)
+ return subrs_index.error();
+ }
+ subrs_cs.assign(subrs_index.nitems(), 0);
+ return 0;
+}
+
+
+Cff::FontParent::FontParent(Cff *cff)
+ : _cff(cff), _error(-1)
+{
+}
+
+Charstring *
+Cff::FontParent::charstring(const IndexIterator &iiter, int which) const
+{
+ const uint8_t *s1 = iiter[which];
+ int slen = iiter[which + 1] - s1;
+ String cs = _cff->data_string().substring(s1 - _cff->data(), slen);
+ if (slen == 0)
+ return 0;
+ else if (_charstring_type == 1)
+ return new Type1Charstring(cs);
+ else
+ return new Type2Charstring(cs);
+}
+
+Charstring *
+Cff::FontParent::gsubr(int i) const
+{
+ return _cff->gsubr(i);
+}
+
+int
+Cff::FontParent::gsubr_bias() const
+{
+ return Efont::subr_bias(2, ngsubrs_x());
+}
+
+
+/*****
+ * CffFont
+ **/
+
+Cff::Font::Font(Cff *cff, PermString font_name, const Dict &top_dict, ErrorHandler *errh)
+ : ChildFont(cff, 0, 2, top_dict, errh), _font_name(font_name),
+ _t1encoding(0)
+{
+ assert(!_top_dict.has_first(oROS));
+ if (_error < 0)
+ return;
+
+ // extract CharStrings
+ // must use xvalue because we could be creating the default dict!
+ int charstrings_offset = 0;
+ _top_dict.xvalue(oCharStrings, &charstrings_offset);
+ _charstrings_index = Cff::IndexIterator(cff->data(), charstrings_offset, cff->length(), errh, "CharStrings INDEX");
+ if (_charstrings_index.error() < 0) {
+ _error = _charstrings_index.error();
+ return;
+ }
+ _charstrings_cs.assign(_charstrings_index.nitems(), 0);
+
+ int charset = 0;
+ _top_dict.xvalue(oCharset, &charset);
+ _charset.assign(cff, charset, _charstrings_index.nitems(), cff->max_sid(), errh);
+ if (_charset.error() < 0) {
+ _error = _charset.error();
+ return;
+ }
+
+ int Encoding = 0;
+ _top_dict.xvalue(oEncoding, &Encoding);
+ if (parse_encoding(Encoding, errh) < 0)
+ return;
+
+ // success!
+ _error = 0;
+}
+
+Cff::Font::~Font()
+{
+ for (int i = 0; i < _charstrings_cs.size(); i++)
+ delete _charstrings_cs[i];
+ delete _t1encoding;
+}
+
+int
+Cff::Font::parse_encoding(int pos, ErrorHandler *errh)
+{
+ _encoding_pos = pos;
+ for (int i = 0; i < 256; i++)
+ _encoding[i] = 0;
+
+ // check for standard encodings
+ if (pos == 0)
+ return assign_standard_encoding(standard_encoding);
+ else if (pos == 1)
+ return assign_standard_encoding(expert_encoding);
+
+ // otherwise, a custom encoding
+ const uint8_t *data = _cff->data();
+ int len = _cff->length();
+ if (pos + 1 > len)
+ return errh->error("Encoding position out of range"), -EFAULT;
+ bool supplemented = (data[pos] & 0x80) != 0;
+ int format = (data[pos] & 0x7F);
+
+ int retval = 0;
+ int endpos, g = 1;
+ if (format == 0) {
+ endpos = pos + 2 + data[pos + 1];
+ if (endpos > len)
+ return errh->error("Encoding[0] out of range"), -EFAULT;
+ const uint8_t *p = data + pos + 2;
+ int n = data[pos + 1];
+ for (; g <= n; g++, p++) {
+ int e = p[0];
+ if (_encoding[e])
+ retval = 1;
+ _encoding[e] = g;
+ }
+
+ } else if (format == 1) {
+ endpos = pos + 2 + data[pos + 1] * 2;
+ if (endpos > len)
+ return errh->error("Encoding[1] out of range"), -EFAULT;
+ const uint8_t *p = data + pos + 2;
+ int n = data[pos + 1];
+ for (int i = 0; i < n; i++, p += 2) {
+ int first = p[0];
+ int nLeft = p[1];
+ for (int e = first; e <= first + nLeft; e++) {
+ if (_encoding[e])
+ retval = 1;
+ _encoding[e] = g++;
+ }
+ }
+
+ } else
+ return errh->error("unknown Encoding format %d", format), -EINVAL;
+
+ if (g > _charset.nglyphs())
+ return errh->error("Encoding glyph %d out of range", g), -EINVAL;
+
+ // check supplements
+ if (supplemented) {
+ if (endpos + data[endpos] * 3 > len)
+ return -EINVAL;
+ const uint8_t *p = data + endpos + 1;
+ int n = data[endpos];
+ for (int i = 0; i < n; i++, p += 3) {
+ int e = p[0];
+ int s = (p[1] << 8) | p[2];
+ int g = _charset.sid_to_gid(s);
+ if (_encoding[e])
+ retval = 1;
+ if (g < 0 || g >= _charset.nglyphs())
+ return errh->error("Encoding glyph %d out of range", g), -EINVAL;
+ _encoding[e] = g;
+ }
+ }
+
+ // successfully done
+ return retval;
+}
+
+int
+Cff::Font::assign_standard_encoding(const int *standard_encoding)
+{
+ for (int i = 0; i < 256; i++)
+ _encoding[i] = _charset.sid_to_gid(standard_encoding[i]);
+ return 0;
+}
+
+void
+Cff::Font::font_matrix(double matrix[6]) const
+{
+ Vector<double> t1d_matrix;
+ if (dict_value(oFontMatrix, t1d_matrix) && t1d_matrix.size() == 6)
+ memcpy(&matrix[0], &t1d_matrix[0], sizeof(double) * 6);
+ else {
+ matrix[0] = matrix[3] = 0.001;
+ matrix[1] = matrix[2] = matrix[4] = matrix[5] = 0;
+ }
+}
+
+PermString
+Cff::Font::glyph_name(int gid) const
+{
+ if (gid >= 0 && gid < nglyphs())
+ return _cff->sid_permstring(_charset.gid_to_sid(gid));
+ else
+ return PermString();
+}
+
+void
+Cff::Font::glyph_names(Vector<PermString> &gnames) const
+{
+ gnames.resize(nglyphs());
+ for (int i = 0; i < nglyphs(); i++)
+ gnames[i] = _cff->sid_permstring(_charset.gid_to_sid(i));
+}
+
+Charstring *
+Cff::Font::glyph(int gid) const
+{
+ if (gid < 0 || gid >= nglyphs())
+ return 0;
+ if (!_charstrings_cs[gid])
+ _charstrings_cs[gid] = charstring(_charstrings_index, gid);
+ return _charstrings_cs[gid];
+}
+
+Charstring *
+Cff::Font::glyph(PermString name) const
+{
+ int gid = _charset.sid_to_gid(_cff->sid(name));
+ if (gid < 0)
+ return 0;
+ if (!_charstrings_cs[gid])
+ _charstrings_cs[gid] = charstring(_charstrings_index, gid);
+ return _charstrings_cs[gid];
+}
+
+int
+Cff::Font::glyphid(PermString name) const
+{
+ return _charset.sid_to_gid(_cff->sid(name));
+}
+
+Type1Encoding *
+Cff::Font::type1_encoding() const
+{
+ if (_encoding_pos == 0)
+ return Type1Encoding::standard_encoding();
+ if (!_t1encoding)
+ _t1encoding = type1_encoding_copy();
+ return _t1encoding;
+}
+
+Type1Encoding *
+Cff::Font::type1_encoding_copy() const
+{
+ if (_encoding_pos == 0)
+ return Type1Encoding::standard_encoding();
+ Type1Encoding *e = new Type1Encoding;
+ for (int i = 0; i < 256; i++)
+ if (_encoding[i])
+ e->put(i, _cff->sid_permstring(_charset.gid_to_sid(_encoding[i])));
+ return e;
+}
+
+bool
+Cff::Font::dict_has(DictOperator op) const
+{
+ return dict_of(op).has(op);
+}
+
+String
+Cff::Font::dict_string(DictOperator op) const
+{
+ Vector<double> vec;
+ dict_of(op).value(op, vec);
+ if (vec.size() == 1 && vec[0] >= 0 && vec[0] <= _cff->max_sid())
+ return _cff->sid_string((int) vec[0]);
+ else
+ return String();
+}
+
+
+/*****
+ * Cff::CIDFont
+ **/
+
+Cff::CIDFont::CIDFont(Cff *cff, PermString font_name, const Dict &top_dict, ErrorHandler *errh)
+ : FontParent(cff), _font_name(font_name), _top_dict(top_dict)
+{
+ assert(_top_dict.has_first(oROS));
+
+ // parse top DICT
+ _error = -EINVAL;
+ if (_top_dict.check(false, errh, "Top DICT") < 0)
+ return;
+ else if (!_top_dict.has(oCharStrings)) {
+ errh->error("font has no CharStrings dictionary");
+ return;
+ }
+ //_top_dict.unparse(errh, "Top DICT");
+
+ // extract offsets and information from TOP DICT
+ _top_dict.value(oCharstringType, &_charstring_type);
+ if (_charstring_type != 1 && _charstring_type != 2) {
+ errh->error("unknown CharString type %d", _charstring_type);
+ return;
+ }
+
+ int charstrings_offset = 0;
+ _top_dict.value(oCharStrings, &charstrings_offset);
+ _charstrings_index = Cff::IndexIterator(cff->data(), charstrings_offset, cff->length(), errh, "CharStrings INDEX");
+ if (_charstrings_index.error() < 0) {
+ _error = _charstrings_index.error();
+ return;
+ }
+ _charstrings_cs.assign(_charstrings_index.nitems(), 0);
+
+ int charset = 0;
+ _top_dict.value(oCharset, &charset);
+ _charset.assign(cff, charset, _charstrings_index.nitems(), -1, errh);
+ if (_charset.error() < 0) {
+ _error = _charset.error();
+ return;
+ }
+
+ // extract information about child fonts
+ int fdarray_offset = 0;
+ if (!_top_dict.value(oFDArray, &fdarray_offset)) {
+ errh->error("CID-keyed font missing FDArray");
+ return;
+ }
+ IndexIterator fdarray_index(cff->data(), fdarray_offset, cff->length(), errh, "FDArray INDEX");
+ for (; fdarray_index; fdarray_index++) {
+ Dict d(cff, fdarray_index[0] - cff->data(), fdarray_index[1] - fdarray_index[0], errh, "Top DICT");
+ if (!d.ok() || d.check(false, errh, "Top DICT") < 0) {
+ _error = d.error();
+ return;
+ }
+ _child_fonts.push_back(new ChildFont(cff, this, _charstring_type, d, errh));
+ if (!_child_fonts.back()->ok())
+ return;
+ }
+
+ int fdselect_offset = 0;
+ if (!_top_dict.value(oFDSelect, &fdselect_offset)) {
+ errh->error("CID-keyed font missing FDSelect");
+ return;
+ }
+ _fdselect.assign(cff, fdselect_offset, _charstrings_cs.size(), errh);
+ if (_fdselect.error() < 0)
+ return;
+
+ // success!
+ _error = 0;
+ set_parent_program(true);
+}
+
+Cff::CIDFont::~CIDFont()
+{
+ for (int i = 0; i < _charstrings_cs.size(); i++)
+ delete _charstrings_cs[i];
+ for (int i = 0; i < _child_fonts.size(); i++)
+ delete _child_fonts[i];
+}
+
+void
+Cff::CIDFont::font_matrix(double matrix[6]) const
+{
+ // XXX
+ matrix[0] = matrix[3] = 0.001;
+ matrix[1] = matrix[2] = matrix[4] = matrix[5] = 0;
+}
+
+const CharstringProgram *
+Cff::CIDFont::child_program(int gid) const
+{
+ int fd = _fdselect.gid_to_fd(gid);
+ if (fd >= 0 && fd < _child_fonts.size())
+ return _child_fonts.at_u(fd);
+ else
+ return 0;
+}
+
+PermString
+Cff::CIDFont::glyph_name(int gid) const
+{
+ if (gid >= 0 && gid < nglyphs())
+ return permprintf("#%d", _charset.gid_to_sid(gid));
+ else
+ return PermString();
+}
+
+void
+Cff::CIDFont::glyph_names(Vector<PermString> &gnames) const
+{
+ gnames.resize(nglyphs());
+ for (int i = 0; i < nglyphs(); i++)
+ gnames[i] = permprintf("#%d", _charset.gid_to_sid(i));
+}
+
+Charstring *
+Cff::CIDFont::glyph(int gid) const
+{
+ if (gid < 0 || gid >= nglyphs())
+ return 0;
+ if (!_charstrings_cs[gid])
+ _charstrings_cs[gid] = charstring(_charstrings_index, gid);
+ return _charstrings_cs[gid];
+}
+
+int
+Cff::CIDFont::glyphid(PermString name) const
+{
+ if (name.length() <= 1 || name[0] != '#' || !isdigit((unsigned char) name[1]))
+ return -1;
+ char *endptr;
+ long cid = strtol(name.c_str() + 1, &endptr, 10);
+ if (*endptr != 0)
+ return -1;
+ return _charset.sid_to_gid(cid);
+}
+
+Charstring *
+Cff::CIDFont::glyph(PermString name) const
+{
+ return CIDFont::glyph(CIDFont::glyphid(name));
+}
+
+
+/*****
+ * ChildFont
+ **/
+
+Cff::ChildFont::ChildFont(Cff *cff, Cff::CIDFont *parent, int charstring_type, const Dict &top_dict, ErrorHandler *errh)
+ : FontParent(cff), _parent(parent), _top_dict(top_dict)
+{
+ if (!errh)
+ errh = ErrorHandler::silent_handler();
+
+ if (!cff->ok() || !_top_dict.ok()) {
+ errh->error("invalid CFF");
+ _error = -EINVAL;
+ return;
+ }
+
+ // extract offsets and information from TOP DICT
+ _charstring_type = charstring_type;
+ _top_dict.value(oCharstringType, &_charstring_type);
+ if (_charstring_type != 1 && _charstring_type != 2) {
+ errh->error("unknown CharString type %d", _charstring_type);
+ return;
+ }
+
+ // extract information from Private DICT
+ if (_top_dict.has(oPrivate)
+ && (_error = handle_private(cff, _top_dict, _private_dict, _default_width_x, _nominal_width_x, _subrs_index, _subrs_cs, errh)) < 0)
+ return;
+
+ // success!
+ _error = 0;
+}
+
+Cff::ChildFont::~ChildFont()
+{
+ for (int i = 0; i < _subrs_cs.size(); i++)
+ delete _subrs_cs[i];
+}
+
+Charstring *
+Cff::ChildFont::charstring(const IndexIterator &iiter, int which) const
+{
+ const uint8_t *s1 = iiter[which];
+ int slen = iiter[which + 1] - s1;
+ String cs = _cff->data_string().substring(s1 - _cff->data(), slen);
+ if (slen == 0)
+ return 0;
+ else if (_charstring_type == 1)
+ return new Type1Charstring(cs);
+ else
+ return new Type2Charstring(cs);
+}
+
+Charstring *
+Cff::ChildFont::subr(int i) const
+{
+ i += Efont::subr_bias(_charstring_type, nsubrs_x());
+ if (i < 0 || i >= nsubrs_x())
+ return 0;
+ if (!_subrs_cs[i])
+ _subrs_cs[i] = charstring(_subrs_index, i);
+ return _subrs_cs[i];
+}
+
+int
+Cff::ChildFont::subr_bias() const
+{
+ return Efont::subr_bias(_charstring_type, nsubrs_x());
+}
+
+double
+Cff::ChildFont::global_width_x(bool is_nominal) const
+{
+ return (is_nominal ? _nominal_width_x : _default_width_x);
+}
+
+}
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/encoding.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/encoding.cc
new file mode 100644
index 00000000000..a55ecc4db25
--- /dev/null
+++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/encoding.cc
@@ -0,0 +1,29 @@
+// -*- related-file-name: "../include/efont/encoding.hh" -*-
+
+/* encoding.{cc,hh} -- 8-bit encodings
+ *
+ * Copyright (c) 1998-2012 Eddie Kohler
+ *
+ * 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 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <efont/encoding.hh>
+namespace Efont {
+
+void
+Encoding8::reserve_glyphs(int count)
+{
+ if (count <= _codes.size()) return;
+ _codes.resize(count, -1);
+}
+
+}
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/findmet.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/findmet.cc
new file mode 100644
index 00000000000..aa5b8167156
--- /dev/null
+++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/findmet.cc
@@ -0,0 +1,321 @@
+// -*- related-file-name: "../include/efont/findmet.hh" -*-
+
+/* findmet.{cc,hh} -- find font metrics
+ *
+ * Copyright (c) 1998-2012 Eddie Kohler
+ *
+ * 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 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <efont/findmet.hh>
+#include <efont/afmparse.hh>
+#include <efont/afm.hh>
+#include <efont/amfm.hh>
+#include <efont/psres.hh>
+#include <string.h>
+#include <stdlib.h>
+namespace Efont {
+
+MetricsFinder::~MetricsFinder()
+{
+ if (_next)
+ _next->_prev = _prev;
+ if (_prev)
+ _prev->_next = _next;
+}
+
+void
+MetricsFinder::add_finder(MetricsFinder *new_finder)
+{
+ if (_next)
+ _next->add_finder(new_finder);
+ else {
+ assert(!new_finder->_prev);
+ new_finder->_prev = this;
+ _next = new_finder;
+ }
+}
+
+Metrics *
+MetricsFinder::find_metrics(PermString name, ErrorHandler *errh)
+{
+ MetricsFinder *f = this;
+ while (f) {
+ Metrics *m = f->find_metrics_x(name, this, errh);
+ if (m) return m;
+ f = f->_next;
+ }
+ return 0;
+}
+
+AmfmMetrics *
+MetricsFinder::find_amfm(PermString name, ErrorHandler *errh)
+{
+ MetricsFinder *f = this;
+ while (f) {
+ AmfmMetrics *m = f->find_amfm_x(name, this, errh);
+ if (m) return m;
+ f = f->_next;
+ }
+ return 0;
+}
+
+void
+MetricsFinder::record(Metrics *m)
+{
+ record(m, m->font_name());
+}
+
+void
+MetricsFinder::record(Metrics *m, PermString name)
+{
+ if (_next) _next->record(m, name);
+}
+
+void
+MetricsFinder::record(AmfmMetrics *amfm)
+{
+ if (_next) _next->record(amfm);
+}
+
+Metrics *
+MetricsFinder::find_metrics_x(PermString, MetricsFinder *, ErrorHandler *)
+{
+ return 0;
+}
+
+AmfmMetrics *
+MetricsFinder::find_amfm_x(PermString, MetricsFinder *, ErrorHandler *)
+{
+ return 0;
+}
+
+Metrics *
+MetricsFinder::try_metrics_file(const Filename &fn, MetricsFinder *finder,
+ ErrorHandler *errh)
+{
+ if (fn.readable()) {
+ Metrics *afm = AfmReader::read(fn, errh);
+ if (afm) finder->record(afm);
+ return afm;
+ } else
+ return 0;
+}
+
+AmfmMetrics *
+MetricsFinder::try_amfm_file(const Filename &fn, MetricsFinder *finder,
+ ErrorHandler *errh)
+{
+ if (fn.readable()) {
+ AmfmMetrics *amfm = AmfmReader::read(fn, finder, errh);
+ if (amfm) finder->record(amfm);
+ return amfm;
+ } else
+ return 0;
+}
+
+
+/*****
+ * CacheMetricsFinder
+ **/
+
+CacheMetricsFinder::CacheMetricsFinder()
+ : _metrics_map(-1), _amfm_map(-1)
+{
+}
+
+CacheMetricsFinder::~CacheMetricsFinder()
+{
+ clear();
+}
+
+Metrics *
+CacheMetricsFinder::find_metrics_x(PermString name, MetricsFinder *,
+ ErrorHandler *)
+{
+ int index = _metrics_map[name];
+ return index >= 0 ? _metrics[index] : 0;
+}
+
+AmfmMetrics *
+CacheMetricsFinder::find_amfm_x(PermString name, MetricsFinder *,
+ ErrorHandler*)
+{
+ int index = _amfm_map[name];
+ return index >= 0 ? _amfm[index] : 0;
+}
+
+
+void
+CacheMetricsFinder::record(Metrics *m, PermString name)
+{
+ int index = _metrics.size();
+ _metrics.push_back(m);
+ _metrics_map.insert(name, index);
+ m->use();
+ MetricsFinder::record(m, name);
+}
+
+void
+CacheMetricsFinder::record(AmfmMetrics *amfm)
+{
+ int index = _amfm.size();
+ _amfm.push_back(amfm);
+ _amfm_map.insert(amfm->font_name(), index);
+ amfm->use();
+ MetricsFinder::record(amfm);
+}
+
+void
+CacheMetricsFinder::clear()
+{
+ for (int i = 0; i < _metrics.size(); i++)
+ _metrics[i]->unuse();
+ for (int i = 0; i < _amfm.size(); i++)
+ _amfm[i]->unuse();
+ _metrics.clear();
+ _amfm.clear();
+ _metrics_map.clear();
+ _amfm_map.clear();
+}
+
+
+/*****
+ * InstanceMetricsFinder
+ **/
+
+InstanceMetricsFinder::InstanceMetricsFinder(bool call_mmpfb)
+ : _call_mmpfb(call_mmpfb)
+{
+}
+
+Metrics *
+InstanceMetricsFinder::find_metrics_instance(PermString name,
+ MetricsFinder *finder, ErrorHandler *errh)
+{
+ const char *underscore = strchr(name.c_str(), '_');
+ PermString amfm_name =
+ PermString(name.c_str(), underscore - name.c_str());
+
+ AmfmMetrics *amfm = finder->find_amfm(amfm_name, errh);
+ if (!amfm) return 0;
+
+ MultipleMasterSpace *mmspace = amfm->mmspace();
+ if (!mmspace->check_intermediate() && _call_mmpfb) {
+ char *buf = new char[amfm->font_name().length() + 30];
+ sprintf(buf, "mmpfb -q --amcp-info '%s'", amfm->font_name().c_str());
+
+ FILE *f = popen(buf, "r");
+ if (f) {
+ Filename fake("<mmpfb output>");
+ Slurper slurpy(fake, f);
+ AmfmReader::add_amcp_file(slurpy, amfm, errh);
+ pclose(f);
+ }
+
+ delete[] buf;
+ }
+
+ Vector<double> design = mmspace->default_design_vector();
+ int i = 0;
+ while (underscore[0] == '_' && underscore[1]) {
+ double x = strtod(underscore + 1, const_cast<char **>(&underscore));
+ mmspace->set_design(design, i, x, errh);
+ i++;
+ }
+
+ Vector<double> weight;
+ if (!mmspace->design_to_weight(design, weight, errh))
+ return 0;
+ Metrics *new_afm = amfm->interpolate(design, weight, errh);
+ if (new_afm) {
+ finder->record(new_afm);
+ // What if the dimensions changed because the user specified out-of-range
+ // dimens? We don't want to reinterpolate each time, so record the new
+ // AFM under that name as well.
+ if (new_afm->font_name() != name)
+ finder->record(new_afm, name);
+ }
+ return new_afm;
+}
+
+Metrics *
+InstanceMetricsFinder::find_metrics_x(PermString name, MetricsFinder *finder,
+ ErrorHandler *errh)
+{
+ if (strchr(name.c_str(), '_'))
+ return find_metrics_instance(name, finder, errh);
+ else
+ return 0;
+}
+
+
+/*****
+ * PsresMetricsFinder
+ **/
+
+PsresMetricsFinder::PsresMetricsFinder(PsresDatabase *psres)
+ : _psres(psres)
+{
+}
+
+Metrics *
+PsresMetricsFinder::find_metrics_x(PermString name, MetricsFinder *finder,
+ ErrorHandler *errh)
+{
+ return try_metrics_file
+ (_psres->filename_value("FontAFM", name), finder, errh);
+}
+
+AmfmMetrics *
+PsresMetricsFinder::find_amfm_x(PermString name, MetricsFinder *finder,
+ ErrorHandler *errh)
+{
+ return try_amfm_file
+ (_psres->filename_value("FontAMFM", name), finder, errh);
+}
+
+
+/*****
+ * DirectoryMetricsFinder
+ **/
+
+DirectoryMetricsFinder::DirectoryMetricsFinder(PermString d)
+ : _directory(d)
+{
+}
+
+Metrics *
+DirectoryMetricsFinder::find_metrics_x(PermString name, MetricsFinder *finder,
+ ErrorHandler *errh)
+{
+ Metrics *afm = try_metrics_file
+ (Filename(_directory, permcat(name, ".afm")), finder, errh);
+ if (!afm)
+ afm = try_metrics_file
+ (Filename(_directory, permcat(name, ".AFM")), finder, errh);
+ return afm;
+}
+
+AmfmMetrics *
+DirectoryMetricsFinder::find_amfm_x(PermString name, MetricsFinder *finder,
+ ErrorHandler *errh)
+{
+ AmfmMetrics *amfm = try_amfm_file
+ (Filename(_directory, permcat(name, ".amfm")), finder, errh);
+ if (!amfm)
+ amfm = try_amfm_file
+ (Filename(_directory, permcat(name, ".AMFM")), finder, errh);
+ return amfm;
+}
+
+}
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/metrics.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/metrics.cc
new file mode 100644
index 00000000000..0dd308056e2
--- /dev/null
+++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/metrics.cc
@@ -0,0 +1,130 @@
+// -*- related-file-name: "../include/efont/metrics.hh" -*-
+
+/* metrics.{cc,hh} -- generic font metrics
+ *
+ * Copyright (c) 1998-2012 Eddie Kohler
+ *
+ * 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 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <efont/metrics.hh>
+#include <efont/t1cs.hh> /* for UNKDOUBLE */
+namespace Efont {
+
+Metrics::Metrics()
+ : _name_map(-1),
+ _scale(1), _fdv(fdLast, UNKDOUBLE),
+ _xt_map(0),
+ _uses(0)
+{
+ _xt.push_back((MetricsXt *)0);
+}
+
+
+Metrics::Metrics(PermString font_name, PermString full_name, const Metrics &m)
+ : _font_name(font_name),
+ _family(m._family), _full_name(full_name), _version(m._version),
+ _name_map(m._name_map), _names(m._names), _encoding(m._encoding),
+ _scale(1), _fdv(fdLast, UNKDOUBLE),
+ _pairp(m._pairp),
+ _xt_map(0),
+ _uses(0)
+{
+ reserve_glyphs(m._wdv.size());
+ _kernv.resize(m._kernv.size(), UNKDOUBLE);
+ _xt.push_back((MetricsXt *)0);
+}
+
+
+Metrics::~Metrics()
+{
+ assert(_uses == 0);
+ for (int i = 1; i < _xt.size(); i++)
+ delete _xt[i];
+}
+
+
+void
+Metrics::set_font_name(PermString n)
+{
+ assert(!_font_name);
+ _font_name = n;
+}
+
+
+void
+Metrics::reserve_glyphs(int amt)
+{
+ if (amt <= _wdv.size()) return;
+ _wdv.resize(amt, UNKDOUBLE);
+ _lfv.resize(amt, UNKDOUBLE);
+ _rtv.resize(amt, UNKDOUBLE);
+ _tpv.resize(amt, UNKDOUBLE);
+ _btv.resize(amt, UNKDOUBLE);
+ _encoding.reserve_glyphs(amt);
+ _pairp.reserve_glyphs(amt);
+ for (int i = 1; i < _xt.size(); i++)
+ _xt[i]->reserve_glyphs(amt);
+}
+
+
+GlyphIndex
+Metrics::add_glyph(PermString n)
+{
+ if (nglyphs() >= _wdv.size())
+ reserve_glyphs(nglyphs() ? nglyphs() * 2 : 64);
+ GlyphIndex gi = _names.size();
+ _names.push_back(n);
+ _name_map.insert(n, gi);
+ return gi;
+}
+
+
+static void
+set_dimen(Vector<double> &dest, const Vector<double> &src, double scale,
+ bool increment)
+{
+ int c = src.size();
+ if (increment)
+ for (int i = 0; i < c; i++)
+ dest.at_u(i) += src.at_u(i) * scale;
+ else if (scale < 0.9999 || scale > 1.0001)
+ for (int i = 0; i < c; i++)
+ dest.at_u(i) = src.at_u(i) * scale;
+ else
+ dest = src;
+}
+
+void
+Metrics::interpolate_dimens(const Metrics &m, double scale, bool increment)
+{
+ set_dimen(_fdv, m._fdv, scale, increment);
+ set_dimen(_wdv, m._wdv, scale, increment);
+ set_dimen(_lfv, m._lfv, scale, increment);
+ set_dimen(_rtv, m._rtv, scale, increment);
+ set_dimen(_tpv, m._tpv, scale, increment);
+ set_dimen(_btv, m._btv, scale, increment);
+ set_dimen(_kernv, m._kernv, scale, increment);
+}
+
+
+void
+Metrics::add_xt(MetricsXt *mxt)
+{
+ int n = _xt.size();
+ _xt.push_back(mxt);
+ _xt_map.insert(mxt->kind(), n);
+ if (_wdv.size() > 0)
+ mxt->reserve_glyphs(_wdv.size());
+}
+
+}
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/otf.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/otf.cc
new file mode 100644
index 00000000000..fb0abe3806a
--- /dev/null
+++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/otf.cc
@@ -0,0 +1,1496 @@
+// -*- related-file-name: "../include/efont/otf.hh" -*-
+
+/* otf.{cc,hh} -- OpenType font basics
+ *
+ * Copyright (c) 2002-2012 Eddie Kohler
+ *
+ * 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 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <efont/otf.hh>
+#include <lcdf/error.hh>
+#include <lcdf/straccum.hh>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <algorithm>
+#include <efont/otfdata.hh> // for ntohl()
+#include <efont/otfname.hh>
+
+#ifndef static_assert
+#define static_assert(c) switch (c) case 0: case (c):
+#endif
+
+#define USHORT_AT(d) (ntohs(*(const uint16_t *)(d)))
+#define ULONG_AT(d) (ntohl(*(const uint32_t *)(d)))
+#define ULONG_AT2(d) ((USHORT_AT((d)) << 16) | USHORT_AT((d)+2))
+
+namespace Efont { namespace OpenType {
+
+Vector<PermString> debug_glyph_names;
+
+Font::Font(const String &s, ErrorHandler *errh)
+ : _str(s)
+{
+ _str.align(4);
+ _error = parse_header(errh ? errh : ErrorHandler::silent_handler());
+}
+
+int
+Font::parse_header(ErrorHandler *errh)
+{
+ // HEADER FORMAT:
+ // Fixed sfnt version
+ // USHORT numTables
+ // USHORT searchRange
+ // USHORT entrySelector
+ // USHORT rangeShift
+ int len = length();
+ const uint8_t *data = this->data();
+ if (HEADER_SIZE > len)
+ return errh->error("OTF too small for header"), -EFAULT;
+ if ((data[0] != 'O' || data[1] != 'T' || data[2] != 'T' || data[3] != 'O')
+ && (data[0] != '\000' || data[1] != '\001'))
+ return errh->error("not an OpenType font (bad magic number)"), -ERANGE;
+ int ntables = USHORT_AT(data + 4);
+ if (ntables == 0)
+ return errh->error("OTF contains no tables"), -EINVAL;
+ if (HEADER_SIZE + TABLE_DIR_ENTRY_SIZE * ntables > len)
+ return errh->error("OTF table directory out of range"), -EFAULT;
+
+ // TABLE DIRECTORY ENTRY FORMAT:
+ // ULONG tag
+ // ULONG checksum
+ // ULONG offset
+ // ULONG length
+ uint32_t last_tag = 0U;
+ for (int i = 0; i < ntables; i++) {
+ int loc = HEADER_SIZE + TABLE_DIR_ENTRY_SIZE * i;
+ uint32_t tag = ULONG_AT(data + loc);
+ uint32_t offset = ULONG_AT(data + loc + 8);
+ uint32_t length = ULONG_AT(data + loc + 12);
+ if (tag <= last_tag)
+ return errh->error("tags out of order"), -EINVAL;
+ if (offset + length > (uint32_t) len)
+ return errh->error("OTF data for '%s' out of range", Tag(tag).text().c_str()), -EFAULT;
+ last_tag = tag;
+ }
+
+ return 0;
+}
+
+bool
+Font::check_checksums(ErrorHandler *errh) const
+{
+ if (error() < 0)
+ return false;
+ int nt = ntables();
+ bool ok = true;
+ for (int i = 0; i < nt; i++) {
+ const uint8_t *entry = data() + HEADER_SIZE + TABLE_DIR_ENTRY_SIZE * i;
+ String tbl = _str.substring(ULONG_AT(entry + 8), ULONG_AT(entry + 12));
+ uint32_t sum = checksum(tbl);
+ if (ULONG_AT(entry) == 0x68656164 // 'head'
+ && tbl.length() >= 12)
+ sum -= ULONG_AT(tbl.data() + 8);
+ if (sum != ULONG_AT(entry + 4)) {
+ if (errh)
+ errh->error("table '%s' checksum error: %x vs. %x", Tag(ULONG_AT(entry)).text().c_str(), sum, ULONG_AT(entry + 4));
+ ok = false;
+ }
+ }
+ return ok;
+}
+
+int
+Font::ntables() const
+{
+ if (error() < 0)
+ return 0;
+ else
+ return USHORT_AT(data() + 4);
+}
+
+String
+Font::table(Tag tag) const
+{
+ if (error() < 0)
+ return String();
+ const uint8_t *entry = tag.table_entry(data() + HEADER_SIZE, USHORT_AT(data() + 4), TABLE_DIR_ENTRY_SIZE);
+ if (entry)
+ return _str.substring(ULONG_AT(entry + 8), ULONG_AT(entry + 12));
+ else
+ return String();
+}
+
+bool
+Font::has_table(Tag tag) const
+{
+ const uint8_t *entry = 0;
+ if (error() >= 0)
+ entry = tag.table_entry(data() + HEADER_SIZE, USHORT_AT(data() + 4), TABLE_DIR_ENTRY_SIZE);
+ return entry != 0;
+}
+
+uint32_t
+Font::table_checksum(Tag tag) const
+{
+ if (error() < 0)
+ return 0;
+ const uint8_t *entry = tag.table_entry(data() + HEADER_SIZE, USHORT_AT(data() + 4), TABLE_DIR_ENTRY_SIZE);
+ if (entry)
+ return ULONG_AT(entry + 4);
+ else
+ return 0;
+}
+
+Tag
+Font::table_tag(int i) const
+{
+ if (error() < 0 || i < 0 || i >= ntables())
+ return Tag();
+ else
+ return Tag(ULONG_AT(data() + HEADER_SIZE + TABLE_DIR_ENTRY_SIZE * i));
+}
+
+uint32_t
+Font::checksum(const uint8_t *begin, const uint8_t *end)
+{
+ uint32_t sum = 0;
+ if (reinterpret_cast<uintptr_t>(begin) % 4)
+ for (; begin + 3 < end; begin += 4)
+ sum += (begin[0] << 24) + (begin[1] << 16) + (begin[2] << 8) + begin[3];
+ else
+ for (; begin + 3 < end; begin += 4)
+ sum += ULONG_AT(begin);
+ uint32_t leftover = 0;
+ for (int i = 0; i < 4; i++)
+ leftover = (leftover << 8) + (begin < end ? *begin++ : 0);
+ return sum + leftover;
+}
+
+uint32_t
+Font::checksum(const String &s)
+{
+ return checksum(reinterpret_cast<const uint8_t *>(s.begin()), reinterpret_cast<const uint8_t *>(s.end()));
+}
+
+namespace {
+class TagCompar { public:
+ TagCompar(const Vector<Tag> &tags) : _tags(tags) { }
+ bool operator()(int a, int b) { return _tags[a] < _tags[b]; }
+ const Vector<Tag> &_tags;
+};
+}
+
+Font
+Font::make(bool truetype, const Vector<Tag>& tags, const Vector<String>& data)
+{
+ StringAccum sa;
+
+ // create offset table
+ {
+ union {
+ uint8_t c[HEADER_SIZE];
+ uint16_t s[HEADER_SIZE / 2];
+ uint32_t l[HEADER_SIZE / 4];
+ } hdr;
+ hdr.l[0] = (truetype ? htonl(0x00010000) : htonl(0x4F54544F));
+ hdr.s[2] = htons(tags.size());
+ int entrySelector;
+ for (entrySelector = 0; (2 << entrySelector) <= tags.size(); entrySelector++)
+ /* nada */;
+ hdr.s[3] = htons((1 << entrySelector) * 16);
+ hdr.s[4] = htons(entrySelector);
+ hdr.s[5] = htons((tags.size() - (1 << entrySelector)) * 16);
+ sa.append(&hdr.c[0], HEADER_SIZE);
+ }
+
+ // sort tags
+ Vector<int> permut;
+ for (int i = 0; i < tags.size(); i++)
+ permut.push_back(i);
+ std::sort(permut.begin(), permut.end(), TagCompar(tags));
+
+ // table listing
+ uint32_t offset = HEADER_SIZE + TABLE_DIR_ENTRY_SIZE * tags.size();
+ for (int *tp = permut.begin(); tp < permut.end(); tp++) {
+ union {
+ uint8_t c[TABLE_DIR_ENTRY_SIZE];
+ uint32_t l[TABLE_DIR_ENTRY_SIZE / 4];
+ } tdir;
+ tdir.l[0] = htonl(tags[*tp].value());
+
+ // discount current checksum adjustment in head table
+ uint32_t sum = checksum(data[*tp]);
+ if (tags[*tp] == Tag("head") && data[*tp].length() >= 12) {
+ const uint8_t *x = data[*tp].udata() + 8;
+ sum -= (x[0] << 24) + (x[1] << 16) + (x[2] << 8) + x[3];
+ }
+ tdir.l[1] = htonl(sum);
+
+ tdir.l[2] = htonl(offset);
+ tdir.l[3] = htonl(data[*tp].length());
+ sa.append(&tdir.c[0], TABLE_DIR_ENTRY_SIZE);
+ offset += (data[*tp].length() + 3) & ~3;
+ }
+
+ // actual tables
+ for (int *tp = permut.begin(); tp < permut.end(); tp++) {
+ sa << data[*tp];
+ while (sa.length() % 4)
+ sa << '\0';
+ }
+
+ // fix 'head' table
+ for (int i = 0; i < tags.size(); i++) {
+ char *thdr = sa.data() + HEADER_SIZE + TABLE_DIR_ENTRY_SIZE * i;
+ if (ULONG_AT(thdr) == 0x68656164 && ULONG_AT(thdr + 12) >= 12) {
+ uint32_t offset = ULONG_AT(thdr + 8);
+ char *head = sa.data() + offset;
+ memset(head + 8, '\0', 4);
+ uint32_t allsum = checksum(reinterpret_cast<uint8_t *>(sa.data()), reinterpret_cast<uint8_t *>(sa.data() + sa.length()));
+ uint32_t *adj = reinterpret_cast<uint32_t *>(head + 8);
+ *adj = htonl(0xB1B0AFBA - allsum);
+ }
+ }
+
+ return Font(sa.take_string());
+}
+
+
+/**************************
+ * Tag *
+ * *
+ **************************/
+
+Tag::Tag(const char *s)
+ : _tag(0)
+{
+ if (!s)
+ s = "";
+ for (int i = 0; i < 4; i++)
+ if (*s == 0)
+ _tag = (_tag << 8) | 0x20;
+ else if (*s < 32 || *s > 126) { // don't care if s is signed
+ _tag = 0;
+ return;
+ } else
+ _tag = (_tag << 8) | *s++;
+ if (*s)
+ _tag = 0;
+}
+
+Tag::Tag(const String &s)
+ : _tag(0)
+{
+ if (s.length() <= 4) {
+ const char *ss = s.data();
+ for (int i = 0; i < s.length(); i++, ss++)
+ if (*ss < 32 || *ss > 126) {
+ _tag = 0;
+ return;
+ } else
+ _tag = (_tag << 8) | *ss;
+ for (int i = s.length(); i < 4; i++)
+ _tag = (_tag << 8) | 0x20;
+ }
+}
+
+bool
+Tag::valid() const
+{
+ uint32_t tag = _tag;
+ for (int i = 0; i < 4; i++, tag >>= 8)
+ if ((tag & 255) < 32 || (tag & 255) > 126)
+ return false;
+ return true;
+}
+
+String
+Tag::text() const
+{
+ StringAccum sa;
+ uint32_t tag = _tag;
+ for (int i = 0; i < 4; i++, tag = (tag << 8) | 0x20)
+ if (tag != 0x20202020) {
+ uint8_t c = (tag >> 24) & 255;
+ if (c < 32 || c > 126)
+ sa.snprintf(6, "\\%03o", c);
+ else
+ sa << c;
+ }
+ return sa.take_string();
+}
+
+String
+Tag::langsys_text(Tag script, Tag langsys)
+{
+ if (!langsys.null())
+ return script.text() + "." + langsys.text();
+ else
+ return script.text();
+}
+
+const uint8_t *
+Tag::table_entry(const uint8_t *table, int n, int entry_size) const
+{
+ assert(((uintptr_t)table & 1) == 0);
+ int l = 0, r = n;
+ while (l < r) {
+ int m = l + (r - l) / 2;
+ const uint8_t *entry = table + m * entry_size;
+ uint32_t m_tag = ULONG_AT2(entry);
+ if (_tag < m_tag)
+ r = m;
+ else if (_tag == m_tag)
+ return entry;
+ else
+ l = m + 1;
+ }
+ return 0;
+}
+
+
+
+/**************************
+ * ScriptList *
+ * *
+ **************************/
+
+int
+ScriptList::assign(const String &str, ErrorHandler *errh)
+{
+ _str = str;
+ _str.align(4);
+ int result = check_header(errh ? errh : ErrorHandler::silent_handler());
+ if (result < 0)
+ _str = String();
+ return result;
+}
+
+int
+ScriptList::check_header(ErrorHandler *errh)
+{
+ // HEADER FORMAT:
+ // USHORT scriptCount
+ // 6bytes scriptRecord[]
+ int scriptCount;
+ if (_str.length() < SCRIPTLIST_HEADERSIZE
+ || (scriptCount = USHORT_AT(_str.udata()),
+ _str.length() < SCRIPTLIST_HEADERSIZE + scriptCount*SCRIPT_RECSIZE))
+ return errh->error("OTF ScriptList too short");
+
+ // XXX check that scripts are sorted
+
+ return 0;
+}
+
+int
+ScriptList::script_offset(Tag script) const
+{
+ if (_str.length() == 0)
+ return -1;
+ const uint8_t *data = _str.udata();
+ if (const uint8_t *entry = script.table_entry(data + SCRIPTLIST_HEADERSIZE, USHORT_AT(data), SCRIPT_RECSIZE))
+ return USHORT_AT(entry + 4);
+ else
+ return 0;
+}
+
+int
+ScriptList::check_script(Tag tag, int script_off, ErrorHandler *errh) const
+{
+ const uint8_t *data = _str.udata();
+ int langSysCount;
+ if (_str.length() < script_off + SCRIPT_HEADERSIZE
+ || (langSysCount = USHORT_AT(data + script_off + 2),
+ (_str.length() < script_off + SCRIPT_HEADERSIZE + langSysCount*LANGSYS_RECSIZE)))
+ return (errh ? errh->error("OTF Script table for '%s' out of range", tag.text().c_str()) : -1);
+ // XXX check that langsys are sorted
+ return 0;
+}
+
+int
+ScriptList::langsys_offset(Tag script, Tag langsys, ErrorHandler *errh) const
+{
+ int script_off = script_offset(script);
+ if (script_off == 0) {
+ script = Tag("DFLT");
+ script_off = script_offset(script);
+ }
+ if (script_off <= 0)
+ return script_off;
+
+ // check script bounds
+ if (check_script(script, script_off, errh) < 0)
+ return -1;
+
+ // search script table
+ const uint8_t *data = _str.udata();
+ int langSysCount = USHORT_AT(data + script_off + 2);
+ if (const uint8_t *entry = langsys.table_entry(data + script_off + SCRIPT_HEADERSIZE, langSysCount, LANGSYS_RECSIZE))
+ return script_off + USHORT_AT(entry + 4);
+
+ // return default
+ int defaultLangSys = USHORT_AT(data + script_off);
+ if (defaultLangSys != 0)
+ return script_off + defaultLangSys;
+ else
+ return 0;
+}
+
+int
+ScriptList::language_systems(Vector<Tag> &script, Vector<Tag> &langsys, ErrorHandler *errh) const
+{
+ script.clear();
+ langsys.clear();
+
+ const uint8_t *data = _str.udata();
+ int nscripts = USHORT_AT(data);
+ for (int i = 0; i < nscripts; i++) {
+ Tag script_tag(ULONG_AT2(data + SCRIPTLIST_HEADERSIZE + i*SCRIPT_RECSIZE));
+ int script_off = USHORT_AT(data + SCRIPTLIST_HEADERSIZE + i*SCRIPT_RECSIZE + 4);
+ if (check_script(script_tag, script_off, errh) < 0)
+ return -1;
+ const uint8_t *script_table = data + script_off;
+ if (USHORT_AT(script_table) != 0) // default LangSys
+ script.push_back(script_tag), langsys.push_back(Tag());
+ int nlangsys = USHORT_AT(script_table + 2);
+ for (int j = 0; j < nlangsys; j++) {
+ Tag langsys_tag(ULONG_AT2(script_table + SCRIPT_HEADERSIZE + j*LANGSYS_RECSIZE));
+ script.push_back(script_tag), langsys.push_back(langsys_tag);
+ }
+ }
+
+ return 0;
+}
+
+int
+ScriptList::features(Tag script, Tag langsys, int &required_fid, Vector<int> &fids, ErrorHandler *errh, bool clear_fids) const
+{
+ required_fid = -1;
+ if (clear_fids)
+ fids.clear();
+
+ int offset = langsys_offset(script, langsys);
+ if (offset <= 0)
+ return offset;
+
+ // check langsys bounds
+ const uint8_t *data = _str.udata();
+ int featureCount;
+ if (_str.length() < offset + LANGSYS_HEADERSIZE
+ || (featureCount = USHORT_AT(data + offset + 4),
+ (_str.length() < offset + LANGSYS_HEADERSIZE + featureCount*FEATURE_RECSIZE)))
+ return (errh ? errh->error("OTF LangSys table for '%s/%s' out of range", script.text().c_str(), langsys.text().c_str()) : -1);
+
+ // search langsys table
+ int f = USHORT_AT(data + offset + 2);
+ if (f != 0xFFFF)
+ required_fid = f;
+ data += offset + 6;
+ for (int i = 0; i < featureCount; i++, data += FEATURE_RECSIZE)
+ fids.push_back(USHORT_AT(data));
+
+ return 0;
+}
+
+
+
+/**************************
+ * FeatureList *
+ * *
+ **************************/
+
+int
+FeatureList::assign(const String &str, ErrorHandler *errh)
+{
+ _str = str;
+ _str.align(2);
+ int result = check_header(errh ? errh : ErrorHandler::silent_handler());
+ if (result < 0)
+ _str = String();
+ return result;
+}
+
+int
+FeatureList::check_header(ErrorHandler *errh)
+{
+ int featureCount;
+ if (_str.length() < FEATURELIST_HEADERSIZE
+ || (featureCount = USHORT_AT(_str.udata()),
+ _str.length() < FEATURELIST_HEADERSIZE + featureCount*FEATURE_RECSIZE))
+ return errh->error("OTF FeatureList too short");
+ return 0;
+}
+
+Tag
+FeatureList::tag(int fid) const
+{
+ if (_str.length() == 0)
+ return Tag();
+ const uint8_t *data = _str.udata();
+ int nfeatures = USHORT_AT(data);
+ if (fid >= 0 && fid < nfeatures)
+ return Tag(ULONG_AT2(data + FEATURELIST_HEADERSIZE + fid*FEATURE_RECSIZE));
+ else
+ return Tag();
+}
+
+String
+FeatureList::params(int fid, int length, ErrorHandler *errh, bool old_style_offset) const
+{
+ if (_str.length() == 0 || length < 0)
+ return String();
+ if (errh == 0)
+ errh = ErrorHandler::silent_handler();
+
+ const uint8_t *data = _str.udata();
+ int len = _str.length();
+ int nfeatures = USHORT_AT(data);
+ if (fid < 0 || fid >= nfeatures)
+ return errh->error("OTF feature ID '%d' out of range", fid), String();
+ int foff = USHORT_AT(data + FEATURELIST_HEADERSIZE + fid*FEATURE_RECSIZE + 4);
+ if (len < foff + FEATURE_HEADERSIZE)
+ return errh->error("OTF LookupList for feature ID '%d' too short", fid), String();
+ int poff = USHORT_AT(data + foff);
+ if (poff == 0)
+ return String();
+ if (!old_style_offset)
+ poff += foff;
+ if (len < poff + length)
+ return errh->error("OTF feature parameters for feature ID '%d' out of range", fid), String();
+ else
+ return _str.substring(poff, length);
+}
+
+String
+FeatureList::size_params(int fid, const Name &name, ErrorHandler *errh) const
+{
+ // implement 'size' checks from Read Roberts
+ for (int i = 0; i < 2; i++) {
+ String s = params(fid, 10, errh, i != 0);
+ const uint8_t *data = s.udata();
+ // errh->message("trying %d %d %d %d %d\n", USHORT_AT(data), USHORT_AT(data + 2), USHORT_AT(data + 4), USHORT_AT(data + 6), USHORT_AT(data + 8));
+ if (USHORT_AT(data) == 0) // design size == 0
+ continue;
+ if (USHORT_AT(data + 2) == 0 // subfamily ID == 0
+ && USHORT_AT(data + 6) == 0 // range start == 0
+ && USHORT_AT(data + 8) == 0 // range end == 0
+ && USHORT_AT(data + 4) == 0) // menu name ID == 0
+ return s;
+ if (USHORT_AT(data + 6) >= USHORT_AT(data + 8) // range start >= range end
+ || USHORT_AT(data + 4) < 256 // menu name ID < 256
+ || USHORT_AT(data + 4) > 32767 // menu name ID > 32767
+ || !name.english_name(USHORT_AT(data + 4))) // menu name ID is a name ID defined by the font
+ continue;
+ if (USHORT_AT(data) + 1 >= USHORT_AT(data + 6) // design size >= range start (with 1 dp grace)
+ && USHORT_AT(data) <= USHORT_AT(data + 8) + 1) // design size <= range end (with 1 dp grace)
+ return s;
+ else if (i == 1 // old-style feature
+ && USHORT_AT(data + 8) <= 1440 // range end <= 144 point
+ && USHORT_AT(data) <= 1440) { // design size <= 144 point
+ // some old fonts define a bogus feature with design size
+ // not in range (John Owens, Read Roberts)
+ if (errh)
+ errh->warning("invalid 'size' feature: design size not in range");
+ return s;
+ }
+ }
+ if (errh)
+ errh->error("no valid 'size' feature data in the 'size' feature");
+ return String();
+}
+
+int
+FeatureList::find(Tag tag, const Vector<int> &fids) const
+{
+ if (fids.size() == 0 || _str.length() == 0)
+ return -1;
+
+ const uint8_t *data = _str.udata();
+ int nfeatures = USHORT_AT(data);
+ for (const int *fidp = fids.begin(); fidp != fids.end(); fidp++)
+ if (*fidp >= 0 && *fidp < nfeatures) {
+ uint32_t ftag = ULONG_AT2(data + FEATURELIST_HEADERSIZE + (*fidp)*FEATURE_RECSIZE);
+ if (ftag == tag.value())
+ return *fidp;
+ }
+
+ return -1;
+}
+
+void
+FeatureList::filter(Vector<int> &fids, const Vector<Tag> &sorted_ftags) const
+{
+ if (_str.length() == 0)
+ fids.clear();
+ else {
+ std::sort(fids.begin(), fids.end()); // sort fids
+
+ int i = 0, j = 0;
+ while (i < fids.size() && fids[i] < 0)
+ fids[i++] = 0x7FFFFFFF;
+
+ // XXX check that feature list is in alphabetical order
+
+ const uint8_t *data = _str.udata();
+ int nfeatures = USHORT_AT(data);
+ while (i < fids.size() && j < sorted_ftags.size() && fids[i] < nfeatures) {
+ uint32_t ftag = ULONG_AT2(data + FEATURELIST_HEADERSIZE + fids[i]*FEATURE_RECSIZE);
+ if (ftag < sorted_ftags[j].value()) { // not an interesting feature
+ // replace featureID with a large number, remove later
+ fids[i] = 0x7FFFFFFF;
+ i++;
+ } else if (ftag == sorted_ftags[j].value()) // interesting feature
+ i++;
+ else // an interesting feature is not available
+ j++;
+ }
+
+ fids.resize(i); // remove remaining uninteresting features
+ std::sort(fids.begin(), fids.end()); // resort, to move bad ones last
+ while (fids.size() && fids.back() == 0x7FFFFFFF)
+ fids.pop_back();
+ }
+}
+
+int
+FeatureList::lookups(int fid, Vector<int> &results, ErrorHandler *errh, bool clear_results) const
+{
+ if (clear_results)
+ results.clear();
+ if (_str.length() == 0)
+ return -1;
+ if (errh == 0)
+ errh = ErrorHandler::silent_handler();
+
+ const uint8_t *data = _str.udata();
+ int len = _str.length();
+ int nfeatures = USHORT_AT(data);
+ if (fid < 0 || fid >= nfeatures)
+ return errh->error("OTF feature ID '%d' out of range", fid);
+ int foff = USHORT_AT(data + FEATURELIST_HEADERSIZE + fid*FEATURE_RECSIZE + 4);
+ int lookupCount;
+ if (len < foff + FEATURE_HEADERSIZE
+ || (lookupCount = USHORT_AT(data + foff + 2),
+ len < foff + FEATURE_HEADERSIZE + lookupCount*LOOKUPLIST_RECSIZE))
+ return errh->error("OTF LookupList for feature ID '%d' too short", fid);
+ const uint8_t *ldata = data + foff + FEATURE_HEADERSIZE;
+ for (int j = 0; j < lookupCount; j++, ldata += LOOKUPLIST_RECSIZE)
+ results.push_back(USHORT_AT(ldata));
+
+ return 0;
+}
+
+int
+FeatureList::lookups(const Vector<int> &fids, Vector<int> &results, ErrorHandler *errh) const
+{
+ results.clear();
+ if (_str.length() == 0)
+ return -1;
+
+ for (int i = 0; i < fids.size(); i++)
+ if (lookups(fids[i], results, errh, false) < 0)
+ return -1;
+
+ // sort results and remove duplicates
+ std::sort(results.begin(), results.end());
+ int *unique_result = std::unique(results.begin(), results.end());
+ results.resize(unique_result - results.begin());
+ return 0;
+}
+
+int
+FeatureList::lookups(const Vector<int> &required_fids, const Vector<int> &fids, const Vector<Tag> &sorted_ftags, Vector<int> &results, ErrorHandler *errh) const
+{
+ Vector<int> fidsx(fids);
+ filter(fidsx, sorted_ftags);
+ for (int i = 0; i < required_fids.size(); i++)
+ fidsx.push_back(required_fids[i]);
+ return lookups(fidsx, results, errh);
+}
+
+int
+FeatureList::lookups(int required_fid, const Vector<int> &fids, const Vector<Tag> &sorted_ftags, Vector<int> &results, ErrorHandler *errh) const
+{
+ Vector<int> fidsx(fids);
+ filter(fidsx, sorted_ftags);
+ if (required_fid >= 0)
+ fidsx.push_back(required_fid);
+ return lookups(fidsx, results, errh);
+}
+
+int
+FeatureList::lookups(const ScriptList &script_list, Tag script, Tag langsys, const Vector<Tag> &sorted_ftags, Vector<int> &results, ErrorHandler *errh) const
+{
+ int required_fid;
+ Vector<int> fids;
+ int result = script_list.features(script, langsys, required_fid, fids, errh);
+ if (result >= 0) {
+ filter(fids, sorted_ftags);
+ if (required_fid >= 0)
+ fids.push_back(required_fid);
+ result = lookups(fids, results, errh);
+ }
+ return result;
+}
+
+
+/**************************
+ * Coverage *
+ * *
+ **************************/
+
+Coverage::Coverage() throw ()
+{
+}
+
+Coverage::Coverage(Glyph first, Glyph last) throw ()
+{
+ if (first <= last) {
+ _str = String("\000\002\000\001\000\000\000\000\000\000", 10);
+ uint8_t *data = _str.mutable_udata();
+ data[4] = first >> 8;
+ data[5] = first & 255;
+ data[6] = last >> 8;
+ data[7] = last & 255;
+ _str.align(2);
+ }
+}
+
+Coverage::Coverage(const Vector<bool> &gmap) throw ()
+{
+ int end = gmap.size();
+ while (end > 0 && !gmap[end - 1])
+ --end;
+ if (end > 0) {
+ _str = String::make_uninitialized(8 + end);
+ _str.align(4);
+ uint8_t *data = _str.mutable_udata();
+ memset(data, 0, 8 + end);
+ data[1] = 3;
+
+ uint32_t n = 0;
+ const bool *it = gmap.begin();
+ data += 8;
+ for (int i = 0; i < end; ++i, ++it, ++data)
+ if (*it) {
+ *data = 1;
+ ++n;
+ }
+
+ n = htonl(n);
+ memcpy(_str.mutable_udata() + 4, &n, 4);
+ }
+}
+
+Coverage::Coverage(const String &str, ErrorHandler *errh, bool do_check) throw ()
+ : _str(str)
+{
+ _str.align(2);
+ if (do_check) {
+ if (check(errh ? errh : ErrorHandler::silent_handler()) < 0)
+ _str = String();
+ } else { // check()'s shorten-string side effect
+ const uint8_t *data = _str.udata();
+ int count = USHORT_AT(data + 2);
+ if (data[1] == T_LIST)
+ _str = _str.substring(0, HEADERSIZE + count*LIST_RECSIZE);
+ else
+ _str = _str.substring(0, HEADERSIZE + count*RANGES_RECSIZE);
+ }
+}
+
+int
+Coverage::check(ErrorHandler *errh)
+ // side effect: shorten string to cover coverage
+{
+ // HEADER FORMAT:
+ // USHORT coverageFormat
+ // USHORT glyphCount
+ const uint8_t *data = _str.udata();
+ if (_str.length() < HEADERSIZE)
+ return errh->error("OTF coverage table too small for header");
+ int coverageFormat = USHORT_AT(data);
+ int count = USHORT_AT(data + 2);
+
+ int len;
+ switch (coverageFormat) {
+ case T_LIST:
+ len = HEADERSIZE + count*LIST_RECSIZE;
+ if (_str.length() < len)
+ return errh->error("OTF coverage table too short (format 1)");
+ // XXX don't check sorting
+ break;
+ case T_RANGES:
+ len = HEADERSIZE + count*RANGES_RECSIZE;
+ if (_str.length() < len)
+ return errh->error("OTF coverage table too short (format 2)");
+ // XXX don't check sorting
+ // XXX don't check startCoverageIndexes
+ break;
+ default:
+ return errh->error("OTF coverage table has unknown format %d", coverageFormat);
+ }
+
+ _str = _str.substring(0, len);
+ return 0;
+}
+
+int
+Coverage::size() const throw ()
+{
+ if (_str.length() == 0)
+ return -1;
+ const uint8_t *data = _str.udata();
+ if (data[1] == T_LIST)
+ return (_str.length() - HEADERSIZE) / LIST_RECSIZE;
+ else if (data[1] == T_RANGES) {
+ data += _str.length() - RANGES_RECSIZE;
+ return USHORT_AT(data + 4) + USHORT_AT(data + 2) - USHORT_AT(data) + 1;
+ } else if (data[1] == T_X_BYTEMAP)
+ return ULONG_AT(data + 4);
+ else
+ return -1;
+}
+
+int
+Coverage::coverage_index(Glyph g) const throw ()
+{
+ if (_str.length() == 0)
+ return -1;
+
+ const uint8_t *data = _str.udata();
+ int count = USHORT_AT(data + 2);
+ if (data[1] == T_LIST) {
+ int l = 0, r = count;
+ data += HEADERSIZE;
+ while (l < r) {
+ int m = l + (r - l) / 2;
+ int mval = USHORT_AT(data + m * LIST_RECSIZE);
+ if (g < mval)
+ r = m;
+ else if (g == mval)
+ return m;
+ else
+ l = m + 1;
+ }
+ return -1;
+ } else if (data[1] == T_RANGES) {
+ int l = 0, r = count;
+ data += HEADERSIZE;
+ while (l < r) {
+ int m = l + (r - l) / 2;
+ const uint8_t *rec = data + m * RANGES_RECSIZE;
+ if (g < USHORT_AT(rec))
+ r = m;
+ else if (g <= USHORT_AT(rec + 2))
+ return USHORT_AT(rec + 4) + g - USHORT_AT(rec);
+ else
+ l = m + 1;
+ }
+ return -1;
+ } else if (data[1] == T_X_BYTEMAP) {
+ if (g >= 0 && g < _str.length() - 8 && data[8 + g])
+ return g;
+ else
+ return -1;
+ } else
+ return -1;
+}
+
+Glyph
+Coverage::operator[](int cindex) const throw ()
+{
+ if (_str.length() == 0 || cindex < 0)
+ return 0;
+
+ const uint8_t *data = _str.udata();
+ int count = USHORT_AT(data + 2);
+ if (data[1] == T_LIST)
+ return (cindex < count ? USHORT_AT(data + cindex * LIST_RECSIZE) : 0);
+ else if (data[1] == T_RANGES) {
+ int l = 0, r = count;
+ data += HEADERSIZE;
+ while (l < r) {
+ int m = l + (r - l) / 2;
+ const uint8_t *rec = data + m * RANGES_RECSIZE;
+ int start_cindex = USHORT_AT(rec + 4);
+ if (cindex < start_cindex)
+ r = m;
+ else if (cindex < start_cindex + USHORT_AT(rec + 2) - USHORT_AT(rec))
+ return USHORT_AT(rec) + cindex - start_cindex;
+ else
+ l = m + 1;
+ }
+ return 0;
+ } else
+ return 0;
+}
+
+void
+Coverage::unparse(StringAccum &sa) const throw ()
+{
+ const uint8_t *data = _str.udata();
+ if (_str.length() == 0)
+ sa << "@*#!";
+ else if (data[1] == T_LIST) {
+ int count = USHORT_AT(data + 2);
+ for (int i = 0; i < count; i++) {
+ if (i) sa << ',';
+ sa << USHORT_AT(data + HEADERSIZE + i*LIST_RECSIZE);
+ }
+ } else {
+ for (int pos = HEADERSIZE; pos < _str.length(); pos += RANGES_RECSIZE) {
+ Glyph start = USHORT_AT(data + pos);
+ Glyph end = USHORT_AT(data + pos + 2);
+ if (pos > HEADERSIZE) sa << ',';
+ sa << start;
+ if (end != start) sa << '.' << '.' << end;
+ }
+ }
+}
+
+String
+Coverage::unparse() const throw ()
+{
+ StringAccum sa;
+ unparse(sa);
+ return sa.take_string();
+}
+
+Coverage
+operator&(const Coverage &a, const Coverage &b)
+{
+ StringAccum sa;
+ sa << '\000' << '\001' << '\000' << '\000';
+
+ if (b.has_fast_covers()) {
+ for (Coverage::iterator ai = a.begin(); ai; ++ai)
+ if (b.covers(*ai)) {
+ uint16_t x = *ai;
+ sa << (char)(x >> 8) << (char)(x & 0xFF);
+ }
+
+ } else {
+ Coverage::iterator ai = a.begin(), bi = b.begin();
+ while (ai && bi) {
+ if (*ai < *bi)
+ ai.forward_to(*bi);
+ else if (*ai == *bi) {
+ uint16_t x = *ai;
+ sa << (char)(x >> 8) << (char)(x & 0xFF);
+ ai++, bi++;
+ } else
+ bi.forward_to(*ai);
+ }
+ }
+
+ int n = (sa.length() - 4) / 2;
+ sa[2] = (n >> 8);
+ sa[3] = (n & 0xFF);
+ return Coverage(sa.take_string(), 0, false);
+}
+
+bool
+operator<=(const Coverage &a, const Coverage &b)
+{
+ Coverage::iterator ai = a.begin(), bi = b.begin();
+ while (ai && bi) {
+ if (*ai != *bi && !bi.forward_to(*ai))
+ return false;
+ ai++, bi++;
+ }
+ return bi || !ai;
+}
+
+
+/************************
+ * Coverage::iterator *
+ * *
+ ************************/
+
+Coverage::iterator::iterator(const String &str, bool is_end)
+ : _str(str), _value(0)
+{
+ // XXX assume _str has been checked
+ if (!_str.length()) {
+ _pos = 0;
+ return;
+ }
+
+ // shrink _str to fit the coverage table
+ const uint8_t *data = _str.udata();
+ int n = USHORT_AT(data + 2);
+ switch (USHORT_AT(data)) {
+ case T_LIST:
+ _str = _str.substring(0, HEADERSIZE + n*LIST_RECSIZE);
+ normal_pos_setting:
+ _pos = is_end ? _str.length() : HEADERSIZE;
+ _value = _pos >= _str.length() ? 0 : USHORT_AT(data + _pos);
+ break;
+ case T_RANGES:
+ _str = _str.substring(0, HEADERSIZE + n*RANGES_RECSIZE);
+ goto normal_pos_setting;
+ case T_X_BYTEMAP:
+ for (_pos = 8; _pos < _str.length() && !data[_pos]; ++_pos)
+ /* do nothing */;
+ _value = _pos >= _str.length() ? 0 : _pos - 8;
+ break;
+ default:
+ _str = String();
+ _pos = 0;
+ _value = 0;
+ break;
+ }
+}
+
+int
+Coverage::iterator::coverage_index() const
+{
+ const uint8_t *data = _str.udata();
+ assert(_pos < _str.length());
+ if (data[1] == T_LIST)
+ return (_pos - HEADERSIZE) / LIST_RECSIZE;
+ else if (data[1] == T_RANGES)
+ return USHORT_AT(data + _pos + 4) + _value - USHORT_AT(data + _pos);
+ else
+ return _pos - 8;
+}
+
+void
+Coverage::iterator::operator++(int)
+{
+ const uint8_t *data = _str.udata();
+ int len = _str.length();
+ if (_pos >= len
+ || (data[1] == T_RANGES && ++_value <= USHORT_AT(data + _pos + 2)))
+ return;
+ switch (data[1]) {
+ case T_LIST:
+ _pos += LIST_RECSIZE;
+ normal_pos_setting:
+ _value = _pos >= len ? 0 : USHORT_AT(data + _pos);
+ break;
+ case T_RANGES:
+ _pos += RANGES_RECSIZE;
+ goto normal_pos_setting;
+ case T_X_BYTEMAP:
+ for (++_pos; _pos < len && !data[_pos]; ++_pos)
+ /* do nothing */;
+ _value = _pos >= len ? 0 : _pos - 8;
+ break;
+ }
+}
+
+bool
+Coverage::iterator::forward_to(Glyph find)
+{
+ // XXX really should check that this works
+
+ if (find <= _value)
+ return find == _value;
+ else if (_pos >= _str.length())
+ return false;
+
+ const uint8_t *data = _str.udata();
+ if (data[1] == T_LIST) {
+ // check for "common" case: next element
+ _pos += LIST_RECSIZE;
+ if (_pos >= _str.length())
+ return false;
+ else if (find <= USHORT_AT(data + _pos)) {
+ _value = USHORT_AT(data + _pos);
+ return find == _value;
+ }
+
+ // otherwise, binary search over remaining area
+ int l = ((_pos - HEADERSIZE) / LIST_RECSIZE) + 1;
+ int r = (_str.length() - HEADERSIZE) / LIST_RECSIZE;
+ data += HEADERSIZE;
+ while (l < r) {
+ int m = l + (r - l) / 2;
+ Glyph g = USHORT_AT(data + m * LIST_RECSIZE);
+ if (find < g)
+ r = m;
+ else if (find == g)
+ l = r = m;
+ else
+ l = m + 1;
+ }
+ _pos = HEADERSIZE + l * LIST_RECSIZE;
+ _value = (_pos >= _str.length() ? 0 : USHORT_AT(data - HEADERSIZE + _pos));
+
+ } else if (data[1] == T_RANGES) {
+ // check for "common" case: this or next element
+ if (find <= USHORT_AT(data + _pos + 2)) {
+ assert(find >= USHORT_AT(data + _pos));
+ _value = find;
+ return true;
+ }
+ _pos += RANGES_RECSIZE;
+ if (_pos >= _str.length())
+ return false;
+ else if (find <= USHORT_AT(data + _pos + 2)) {
+ _value = (find >= USHORT_AT(data + _pos) ? find : USHORT_AT(data + _pos));
+ return find == _value;
+ }
+
+ // otherwise, binary search over remaining area
+ int l = ((_pos - HEADERSIZE) / RANGES_RECSIZE) + 1;
+ int r = (_str.length() - HEADERSIZE) / RANGES_RECSIZE;
+ data += HEADERSIZE;
+ while (l < r) {
+ int m = l + (r - l) / 2;
+ if (find < USHORT_AT(data + m * RANGES_RECSIZE))
+ r = m;
+ else if (find <= USHORT_AT(data + m * RANGES_RECSIZE + 2)) {
+ _pos = HEADERSIZE + m * RANGES_RECSIZE;
+ _value = find;
+ return true;
+ } else
+ l = m + 1;
+ }
+ _pos = HEADERSIZE + l * LIST_RECSIZE;
+ _value = (_pos >= _str.length() ? 0 : USHORT_AT(data - HEADERSIZE + _pos));
+
+ } else if (data[1] == T_X_BYTEMAP) {
+ _pos = 8 + find;
+ while (_pos < _str.length() && !data[_pos])
+ ++_pos;
+ _pos = _pos >= _str.length() ? _str.length() : _pos;
+ _value = _pos >= _str.length() ? 0 : _pos - 8;
+ }
+
+ return find == _value;
+}
+
+
+/**************************
+ * GlyphSet *
+ * *
+ **************************/
+
+GlyphSet::GlyphSet()
+{
+ memset(_v, 0, sizeof(_v));
+}
+
+GlyphSet::GlyphSet(const GlyphSet &o)
+{
+ for (int i = 0; i < VLEN; i++)
+ if (o._v[i]) {
+ _v[i] = new uint32_t[VULEN];
+ memcpy(_v[i], o._v[i], sizeof(uint32_t) * VULEN);
+ } else
+ _v[i] = 0;
+}
+
+GlyphSet::~GlyphSet()
+{
+ for (int i = 0; i < VLEN; i++)
+ delete[] _v[i];
+}
+
+int
+GlyphSet::change(Glyph g, bool value)
+{
+ if ((unsigned)g > MAXGLYPH)
+ return -1;
+ uint32_t *&u = _v[g >> SHIFT];
+ if (!u) {
+ u = new uint32_t[VULEN];
+ memset(u, 0, sizeof(uint32_t) * VULEN);
+ }
+ uint32_t mask = (1 << (g & 0x1F));
+ if (value)
+ u[(g & MASK) >> 5] |= mask;
+ else
+ u[(g & MASK) >> 5] &= ~mask;
+ return 0;
+}
+
+GlyphSet &
+GlyphSet::operator=(const GlyphSet &o)
+{
+ if (&o != this) {
+ for (int i = 0; i < VLEN; i++)
+ if (o._v[i]) {
+ if (!_v[i])
+ _v[i] = new uint32_t[VULEN];
+ memcpy(_v[i], o._v[i], sizeof(uint32_t) * VULEN);
+ } else if (_v[i])
+ memset(_v[i], 0, sizeof(uint32_t) * VULEN);
+ }
+ return *this;
+}
+
+
+/**************************
+ * ClassDef *
+ * *
+ **************************/
+
+ClassDef::ClassDef(const String &str, ErrorHandler *errh) throw ()
+ : _str(str)
+{
+ _str.align(2);
+ if (check(errh ? errh : ErrorHandler::silent_handler()) < 0)
+ _str = String();
+}
+
+int
+ClassDef::check(ErrorHandler *errh)
+{
+ // HEADER FORMAT:
+ // USHORT coverageFormat
+ // USHORT glyphCount
+ const uint8_t *data = _str.udata();
+ if (_str.length() < 6) // NB: prevents empty format-2 tables
+ return errh->error("OTF class def table too small for header");
+ int classFormat = USHORT_AT(data);
+
+ int len;
+ if (classFormat == T_LIST) {
+ int count = USHORT_AT(data + 4);
+ len = LIST_HEADERSIZE + count*LIST_RECSIZE;
+ // XXX don't check sorting
+ } else if (classFormat == T_RANGES) {
+ int count = USHORT_AT(data + 2);
+ len = RANGES_HEADERSIZE + count*RANGES_RECSIZE;
+ // XXX don't check sorting
+ } else
+ return errh->error("OTF class def table has unknown format %d", classFormat);
+
+ if (len > _str.length())
+ return errh->error("OTF class def table too short");
+ else {
+ _str = _str.substring(0, len);
+ return 0;
+ }
+}
+
+int
+ClassDef::lookup(Glyph g) const throw ()
+{
+ if (_str.length() == 0)
+ return -1;
+
+ const uint8_t *data = _str.udata();
+ int coverageFormat = USHORT_AT(data);
+
+ if (coverageFormat == T_LIST) {
+ Glyph start = USHORT_AT(data + 2);
+ int count = USHORT_AT(data + 4);
+ if (g < start || g >= start + count)
+ return 0;
+ else
+ return USHORT_AT(data + LIST_HEADERSIZE + (g - start) * LIST_RECSIZE);
+ } else if (coverageFormat == T_RANGES) {
+ int l = 0, r = USHORT_AT(data + 2);
+ data += RANGES_HEADERSIZE;
+ while (l < r) {
+ int m = l + (r - l) / 2;
+ const uint8_t *rec = data + m * RANGES_RECSIZE;
+ if (g < USHORT_AT(rec))
+ r = m;
+ else if (g <= USHORT_AT(rec + 2))
+ return USHORT_AT(rec + 4);
+ else
+ l = m + 1;
+ }
+ return 0;
+ } else
+ return 0;
+}
+
+void
+ClassDef::unparse(StringAccum &sa) const throw ()
+{
+ const uint8_t *data = _str.udata();
+ if (_str.length() == 0)
+ sa << "@*#!";
+ else if (data[1] == T_LIST) {
+ Glyph start = USHORT_AT(data + 2);
+ int count = USHORT_AT(data + 4);
+ for (int i = 0; i < count; i++) {
+ if (i) sa << ',';
+ sa << start + i << '=' << USHORT_AT(data + LIST_HEADERSIZE + i*LIST_RECSIZE);
+ }
+ } else {
+ for (int pos = RANGES_HEADERSIZE; pos < _str.length(); pos += RANGES_RECSIZE) {
+ Glyph start = USHORT_AT(data + pos);
+ Glyph end = USHORT_AT(data + pos + 2);
+ if (pos > RANGES_HEADERSIZE) sa << ',';
+ sa << start;
+ if (end != start) sa << '.' << '.' << end;
+ sa << '=' << USHORT_AT(data + pos + 4);
+ }
+ }
+}
+
+String
+ClassDef::unparse() const throw ()
+{
+ StringAccum sa;
+ unparse(sa);
+ return sa.take_string();
+}
+
+
+/******************************
+ * ClassDef::class_iterator *
+ * *
+ ******************************/
+
+ClassDef::class_iterator::class_iterator(const String &str, int pos, int the_class, const Coverage::iterator &coviter)
+ : _str(str), _pos(pos), _class(the_class), _coviter(coviter)
+{
+ // XXX assume _str has been checked
+
+ // cannot handle the_class == 0 when coviter doesn't exist
+ if (_class == 0 && !_coviter)
+ throw Error("cannot iterate over ClassDef class 0");
+
+ // shrink _str to fit the coverage table, and create a fake coverage
+ // iterator if necessary
+ const uint8_t *data = _str.udata();
+ if (_str.length()) {
+ switch (USHORT_AT(data)) {
+ case T_LIST: {
+ Glyph start = USHORT_AT(data + 2);
+ int nglyphs = USHORT_AT(data + 4);
+ _str = _str.substring(0, LIST_HEADERSIZE + nglyphs*LIST_RECSIZE);
+ if (!_coviter)
+ _coviter = Coverage(start, start + nglyphs - 1).begin();
+ if (_class)
+ _coviter.forward_to(start);
+ break;
+ }
+ case T_RANGES: {
+ Glyph start = USHORT_AT(data + RANGES_HEADERSIZE);
+ int nranges = USHORT_AT(data + 2);
+ _str = _str.substring(0, RANGES_HEADERSIZE + nranges*RANGES_RECSIZE);
+ if (!_coviter) {
+ Glyph end = USHORT_AT(data + RANGES_HEADERSIZE + 2 + (nranges - 1)*RANGES_RECSIZE);
+ _coviter = Coverage(start, end).begin();
+ }
+ if (_class)
+ _coviter.forward_to(start);
+ break;
+ }
+ default:
+ _str = String();
+ break;
+ }
+ }
+
+ // move to the first relevant glyph
+ if (_pos >= _str.length())
+ _pos = _str.length();
+ else {
+ _pos = 0;
+ (*this)++;
+ }
+}
+
+void
+ClassDef::class_iterator::increment_class0()
+{
+ const uint8_t *data = _str.udata();
+ int len = _str.length();
+ bool is_list = (data[1] == T_LIST);
+
+ if (_pos != 0)
+ _coviter++;
+ else
+ _pos = FIRST_POS;
+
+ if (_pos == FIRST_POS && _coviter) {
+ if (*_coviter < USHORT_AT(data + (is_list ? 2 : RANGES_HEADERSIZE)))
+ return;
+ _pos = (is_list ? LIST_HEADERSIZE : RANGES_HEADERSIZE);
+ }
+
+ while (_pos > 0 && _pos < len && _coviter) {
+ Glyph g = *_coviter;
+ if (is_list) {
+ _pos = LIST_HEADERSIZE + LIST_RECSIZE*(g - USHORT_AT(data + 2));
+ if (_pos >= len)
+ break;
+ else if (USHORT_AT(data + _pos) == 0) // _class == 0
+ return;
+ _coviter++;
+ } else {
+ if (g < USHORT_AT(data + _pos)) // in a zero range
+ return;
+ else if (g > USHORT_AT(data + _pos + 2))
+ _pos += RANGES_RECSIZE;
+ else if (USHORT_AT(data + _pos + 4) == 0) // _class == 0
+ return;
+ else
+ _coviter.forward_to(USHORT_AT(data + _pos + 2) + 1);
+ }
+ }
+
+ if (_coviter)
+ _pos = LAST_POS;
+ else
+ _pos = len;
+}
+
+void
+ClassDef::class_iterator::operator++(int)
+{
+ if (_class == 0) {
+ increment_class0();
+ return;
+ }
+
+ const uint8_t *data = _str.udata();
+ int len = _str.length();
+ bool is_list = (data[1] == T_LIST);
+
+ if (_pos != 0)
+ _coviter++;
+ else
+ _pos = (is_list ? LIST_HEADERSIZE : RANGES_HEADERSIZE);
+
+ while (_pos < len && _coviter) {
+ Glyph g = *_coviter;
+ if (is_list) {
+ _pos = LIST_HEADERSIZE + LIST_RECSIZE*(g - USHORT_AT(data + 2));
+ if (_pos >= len || USHORT_AT(data + _pos) == _class)
+ return;
+ _coviter++;
+ } else {
+ while (_pos < len && (g > USHORT_AT(data + _pos + 2)
+ || USHORT_AT(data + _pos + 4) != _class))
+ _pos += RANGES_RECSIZE;
+ // now, _pos >= len, or g <= rec.end && class == rec.class
+ if (_pos >= len || g >= USHORT_AT(data + _pos))
+ return;
+ _coviter.forward_to(USHORT_AT(data + _pos));
+ }
+ }
+
+ _pos = len;
+}
+
+
+}}
+
+
+// template instantiations
+#include <lcdf/vector.cc>
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/otfcmap.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/otfcmap.cc
new file mode 100644
index 00000000000..b62b7188b86
--- /dev/null
+++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/otfcmap.cc
@@ -0,0 +1,480 @@
+// -*- related-file-name: "../include/efont/otfcmap.hh" -*-
+
+/* otfcmap.{cc,hh} -- OpenType cmap table
+ *
+ * Copyright (c) 2002-2012 Eddie Kohler
+ *
+ * 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 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <efont/otfcmap.hh>
+#include <lcdf/error.hh>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <efont/otfdata.hh> // for ntohl()
+
+#define USHORT_AT(d) (ntohs(*(const uint16_t *)(d)))
+#define SHORT_AT(d) ((int16_t) ntohs(*(const uint16_t *)(d)))
+#define ULONG_AT(d) (ntohl(*(const uint32_t *)(d)))
+
+namespace Efont { namespace OpenType {
+
+Cmap::Cmap(const String &s, ErrorHandler *errh)
+ : _str(s)
+{
+ _str.align(4);
+ _error = parse_header(errh ? errh : ErrorHandler::silent_handler());
+}
+
+int
+Cmap::parse_header(ErrorHandler *errh)
+{
+ // HEADER FORMAT:
+ // USHORT version
+ // USHORT numTables
+ int len = _str.length();
+ const uint8_t *data = _str.udata();
+ if (HEADER_SIZE > len)
+ return errh->error("OTF cmap too small for header"), -EFAULT;
+ if (!(data[0] == '\000' && data[1] == '\000'))
+ return errh->error("bad cmap version number"), -ERANGE;
+ _ntables = USHORT_AT(data + 2);
+ if (_ntables == 0)
+ return errh->error("OTF cmap contains no tables"), -EINVAL;
+ if (HEADER_SIZE + ENCODING_SIZE * _ntables > len)
+ return errh->error("cmap directory out of range"), -EFAULT;
+
+ // ENCODING ENTRY FORMAT:
+ // USHORT platformID
+ // USHORT encodingID
+ // ULONG offset
+ int last_platform = -1;
+ int last_encoding = -1;
+ int last_language = -1;
+ _first_unicode_table = -1;
+ for (int i = 0; i < _ntables; i++) {
+ int loc = HEADER_SIZE + ENCODING_SIZE * i;
+ int platform = USHORT_AT(data + loc);
+ int encoding = USHORT_AT(data + loc + 2);
+ uint32_t offset = ULONG_AT(data + loc + 4);
+ if (offset + 8 > (uint32_t) len) {
+ length_error:
+ return errh->error("encoding data for entry %d out of range", i);
+ }
+ int format = USHORT_AT(data + offset);
+ int language;
+ if (format == F_BYTE || format == F_HIBYTE || format == F_SEGMENTED
+ || format == F_TRIMMED) {
+ if (USHORT_AT(data + offset + 2) < 6)
+ goto length_error;
+ language = USHORT_AT(data + offset + 4);
+ } else if (format == F_HIBYTE32 || format == F_TRIMMED32
+ || format == F_SEGMENTED32) {
+ if (offset + 12 > (uint32_t) len || ULONG_AT(data + offset + 4) < 12)
+ goto length_error;
+ language = ULONG_AT(data + offset + 8);
+ } else
+ continue;
+ if (!(platform > last_platform
+ || (platform == last_platform
+ && (encoding > last_encoding
+ || (encoding == last_encoding
+ && language > last_language)))))
+ return errh->error("subtables out of order at entry %d", i);
+ if ((platform == 0 || (platform == 3 && encoding == 1))
+ && _first_unicode_table < 0)
+ _first_unicode_table = i;
+ last_platform = platform, last_encoding = encoding, last_language = language;
+ }
+
+ _table_error.assign(_ntables, -2);
+ return 0;
+}
+
+int
+Cmap::first_table(int platform, int encoding) const
+{
+ if (error() < 0)
+ return -1;
+ const uint8_t *data = _str.udata();
+ data += HEADER_SIZE;
+ for (int i = 0; i < _ntables; i++, data += ENCODING_SIZE) {
+ int p = USHORT_AT(data), e = USHORT_AT(data + 2);
+ if (platform == p && (encoding < 0 || encoding == e))
+ return i;
+ }
+ return -1;
+}
+
+int
+Cmap::check_table(int t, ErrorHandler *errh) const
+{
+ if (!errh)
+ errh = ErrorHandler::silent_handler();
+ if (t == USE_FIRST_UNICODE_TABLE && _first_unicode_table == -1) {
+ errh->warning("font appears not to support Unicode");
+ _first_unicode_table = 0;
+ }
+ if (t == USE_FIRST_UNICODE_TABLE)
+ t = _first_unicode_table;
+ if (_error < 0 || t < 0 || t >= _ntables)
+ return errh->error("no such table");
+ if (_table_error[t] > -2)
+ return _table_error[t];
+ _table_error[t] = -1;
+
+ const uint8_t *data = _str.udata();
+ uint32_t offset = ULONG_AT(data + HEADER_SIZE + t * ENCODING_SIZE + 4);
+ uint32_t left = _str.length() - offset;
+ data += offset;
+ int format = USHORT_AT(data);
+ uint32_t length = 0; // value not used
+
+ switch (format) {
+
+ case F_BYTE:
+ if (left < 4
+ || (length = USHORT_AT(data + 2)) > left
+ || length != 259)
+ return errh->error("bad table %d length (format %d)", t, format);
+ break;
+
+ case F_HIBYTE:
+ if (left < 4
+ || (length = USHORT_AT(data + 2)) > left
+ || length < 524)
+ return errh->error("bad table %d length (format %d)", t, format);
+ for (int hi_byte = 0; hi_byte < 256; hi_byte++)
+ if (uint32_t subh_key = USHORT_AT(data + 6 + 2 * hi_byte)) {
+ if ((subh_key & 7) || HIBYTE_SUBHEADERS + subh_key + 8 > length)
+ return errh->error("bad table %d subheader %d offset (format 2)", t, hi_byte);
+ const uint8_t *subh = data + HIBYTE_SUBHEADERS + subh_key;
+ int firstCode = USHORT_AT(subh);
+ int entryCount = USHORT_AT(subh + 2);
+ int idRangeOffset = USHORT_AT(subh + 6);
+ if (firstCode + entryCount > 256 || entryCount == 0)
+ return errh->error("bad table %d subheader %d contents (format 2)", t, hi_byte);
+ if ((HIBYTE_SUBHEADERS + subh_key + 6) // pos[idRangeOffset]
+ + idRangeOffset + entryCount * 2 > length)
+ return errh->error("bad table %d subheader %d length (format 2)", t, hi_byte);
+ }
+ break;
+
+ case F_SEGMENTED: {
+ if (left < 4
+ || (length = USHORT_AT(data + 2)) > left
+ || length < 16)
+ return errh->error("bad table %d length (format %d)", t, format);
+ int segCountX2 = USHORT_AT(data + 6);
+ int searchRange = USHORT_AT(data + 8);
+ int entrySelector = USHORT_AT(data + 10);
+ int rangeShift = USHORT_AT(data + 12);
+ if ((segCountX2 & 1)
+ || segCountX2 == 0
+ || (searchRange & (searchRange - 1)) /* not a power of 2? */
+ || searchRange <= segCountX2/2
+ || (searchRange>>1) > segCountX2/2
+ || 1 << (entrySelector + 1) != searchRange
+ || rangeShift != segCountX2 - searchRange)
+ return errh->error("bad table %d segment counts (format 4)", t);
+ uint32_t segCount = segCountX2 >> 1;
+ if (length < 16 + 8 * segCount)
+ return errh->error("bad table %d length (format %d)", t, format);
+ const uint8_t *endCodes = data + 14;
+ const uint8_t *startCodes = endCodes + 2 + segCountX2;
+ const uint8_t *idDeltas = startCodes + segCountX2;
+ const uint8_t *idRangeOffsets = idDeltas + segCountX2;
+ int last_end = 0;
+ for (int i = 0; i < segCountX2; i += 2) {
+ int endCode = USHORT_AT(endCodes + i);
+ int startCode = USHORT_AT(startCodes + i);
+ /* int idDelta = SHORT_AT(idDeltas + i); // no need to check */
+ int idRangeOffset = USHORT_AT(idRangeOffsets + i);
+ if (endCode < startCode || startCode < last_end)
+ return errh->error("bad table %d overlapping range %d (format %d)", t, i/2, format);
+ if (idRangeOffset
+ && idRangeOffsets + i + idRangeOffset + (endCode - startCode)*2 + 2 > data + length)
+ return errh->error("bad table %d range %d length (format 4)", t, i/2);
+ last_end = endCode + 1;
+ }
+ if (USHORT_AT(endCodes + segCountX2 - 2) != 0xFFFF)
+ return errh->error("bad table %d incorrect final endCode (format 4)", t);
+ break;
+ }
+
+ case F_TRIMMED: {
+ if (left < 4
+ || (length = USHORT_AT(data + 2)) > left
+ || length < 10)
+ return errh->error("bad table %d length (format %d)", t, format);
+ uint32_t entryCount = USHORT_AT(data + 8);
+ if (10 + entryCount * 2 > length)
+ return errh->error("bad table %d length (format %d)", t, format);
+ break;
+ }
+
+ case F_SEGMENTED32: {
+ if (left < 8
+ || (length = ULONG_AT(data + 4)) > left
+ || length < 16)
+ return errh->error("bad table %d length (format %d)", t, format);
+ uint32_t nGroups = ULONG_AT(data + 16);
+ if ((length - 16) / 12 < nGroups)
+ return errh->error("bad table %d length (format %d)", t, format);
+ uint32_t last_post_end = 0;
+ data += 16;
+ for (uint32_t i = 0; i < nGroups; i++, data += 12) {
+ uint32_t startCharCode = ULONG_AT(data);
+ uint32_t endCharCode = ULONG_AT(data + 4);
+ if (startCharCode < last_post_end || endCharCode < startCharCode)
+ return errh->error("bad table %d overlapping range %d (format %d)", t, i, format);
+ last_post_end = endCharCode + 1;
+ }
+ break;
+ }
+
+ case F_HIBYTE32:
+ case F_TRIMMED32:
+ default:
+ return errh->error("bad table %d unsupported format %d", t, format);
+
+ }
+
+ _table_error[t] = 0;
+ return t;
+}
+
+Glyph
+Cmap::map_table(int t, uint32_t uni, ErrorHandler *errh) const
+{
+ if ((t = check_table(t, errh)) < 0)
+ return 0;
+
+ const uint8_t *data = _str.udata();
+ data += ULONG_AT(data + HEADER_SIZE + t * ENCODING_SIZE + 4);
+
+ switch (USHORT_AT(data)) {
+
+ case F_BYTE:
+ if (uni < 256)
+ return data[6 + uni];
+ else
+ return 0;
+
+ case F_HIBYTE: {
+ if (uni >= 65536)
+ return 0;
+ int hi_byte = (uni >> 8) & 255;
+ int subh = USHORT_AT(data + 6 + hi_byte * 2);
+ if (subh == 0 && hi_byte) // XXX?
+ return 0;
+ data += 524 + subh;
+ int firstCode = USHORT_AT(data);
+ int entryCount = USHORT_AT(data + 2);
+ int idDelta = SHORT_AT(data + 4);
+ int idRangeOffset = USHORT_AT(data + 6);
+ int lo_byte = uni & 255;
+ if (lo_byte < firstCode || lo_byte >= firstCode + entryCount)
+ return 0;
+ int answer = USHORT_AT(data + 6 + idRangeOffset + (lo_byte - firstCode) * 2);
+ if (answer == 0)
+ return 0;
+ return (answer + idDelta) & 65535;
+ }
+
+ case F_SEGMENTED: {
+ if (uni >= 65536)
+ return 0;
+ int segCount = USHORT_AT(data + 6) >> 1;
+ const uint8_t *endCounts = data + 14;
+ const uint8_t *startCounts = endCounts + (segCount << 1) + 2;
+ const uint8_t *idDeltas = startCounts + (segCount << 1);
+ const uint8_t *idRangeOffsets = idDeltas + (segCount << 1);
+ int l = 0, r = segCount;
+ while (l < r) {
+ int m = l + (r - l) / 2;
+ uint32_t endCount = USHORT_AT(endCounts + (m << 1));
+ uint32_t startCount = USHORT_AT(startCounts + (m << 1));
+ if (uni < startCount)
+ r = m;
+ else if (uni <= endCount) {
+ int idDelta = SHORT_AT(idDeltas + (m << 1));
+ int idRangeOffset = USHORT_AT(idRangeOffsets + (m << 1));
+ if (idRangeOffset == 0)
+ return (idDelta + uni) & 65535;
+ int g = USHORT_AT(idRangeOffsets + (m << 1) + idRangeOffset + ((uni - startCount) << 1));
+ if (g == 0)
+ return 0;
+ return (idDelta + g) & 65535;
+ } else
+ l = m + 1;
+ }
+ return 0;
+ }
+
+ case F_TRIMMED: {
+ uint32_t firstCode = USHORT_AT(data + 6);
+ uint32_t entryCount = USHORT_AT(data + 8);
+ if (uni < firstCode || uni >= firstCode + entryCount)
+ return 0;
+ return USHORT_AT(data + 10 + ((uni - firstCode) << 1));
+ }
+
+ case F_SEGMENTED32: {
+ uint32_t nGroups = ULONG_AT(data + 12);
+ uint32_t l = 0, r = nGroups;
+ const uint8_t *groups = data + 16;
+ while (l < r) {
+ uint32_t m = l + (r - l) / 2;
+ uint32_t startCharCode = ULONG_AT(groups + m * 12);
+ uint32_t endCharCode = ULONG_AT(groups + m * 12 + 4);
+ if (uni < startCharCode)
+ r = m;
+ else if (uni <= endCharCode)
+ return ULONG_AT(groups + m * 12 + 8) + uni - startCharCode;
+ else
+ l = m + 1;
+ }
+ return 0;
+ }
+
+ default:
+ return 0;
+
+ }
+}
+
+void
+Cmap::dump_table(int t, Vector<uint32_t> &g2c, ErrorHandler *errh) const
+{
+ if ((t = check_table(t, errh)) < 0)
+ return;
+
+ const uint8_t *data = _str.udata();
+ data += ULONG_AT(data + HEADER_SIZE + t * ENCODING_SIZE + 4);
+
+ switch (USHORT_AT(data)) {
+
+ case F_BYTE:
+ g2c.resize(256, 0);
+ for (int c = 0; c < 256; c++)
+ if (int g = data[6 + c])
+ if (!g2c[g])
+ g2c[g] = c;
+ break;
+
+ case F_HIBYTE:
+ assert(USHORT_AT(data + 6) == 0);
+ for (int hi_byte = 0; hi_byte < 256; hi_byte++) {
+ int subh = USHORT_AT(data + 6 + hi_byte * 4);
+ if (subh == 0 && hi_byte > 0)
+ continue;
+ const uint8_t *tdata = data + 524 + subh;
+ int firstCode = USHORT_AT(tdata);
+ int entryCount = USHORT_AT(tdata + 2);
+ int idDelta = SHORT_AT(tdata + 4);
+ int idRangeOffset = USHORT_AT(tdata + 6);
+ const uint8_t *gdata = tdata + 6 + idRangeOffset;
+ for (int i = 0; i < entryCount; i++)
+ if (int g = USHORT_AT(gdata + (i << 1))) {
+ g = (idDelta + g) & 65535;
+ if (g >= g2c.size())
+ g2c.resize(g + 1, 0);
+ if (!g2c[g])
+ g2c[g] = (hi_byte << 8) + firstCode + i;
+ }
+ }
+ break;
+
+ case F_SEGMENTED: {
+ int segCountX2 = USHORT_AT(data + 6);
+ const uint8_t *endCounts = data + 14;
+ const uint8_t *startCounts = endCounts + segCountX2 + 2;
+ const uint8_t *idDeltas = startCounts + segCountX2;
+ const uint8_t *idRangeOffsets = idDeltas + segCountX2;
+ for (int i = 0; i < segCountX2; i += 2) {
+ int endCount = USHORT_AT(endCounts + i);
+ int startCount = USHORT_AT(startCounts + i);
+ int idDelta = SHORT_AT(idDeltas + i);
+ int idRangeOffset = USHORT_AT(idRangeOffsets + i);
+ if (idRangeOffset == 0) {
+ for (int c = startCount; c <= endCount; c++) {
+ Glyph g = (c + idDelta) & 65535;
+ if (g >= g2c.size())
+ g2c.resize(g + 1, 0);
+ if (!g2c[g])
+ g2c[g] = c;
+ }
+ } else {
+ const uint8_t *gdata = idRangeOffsets + i + idRangeOffset;
+ for (int c = startCount; c <= endCount; c++, gdata += 2)
+ if (int g = USHORT_AT(gdata)) {
+ g = (g + idDelta) & 65535;
+ if (g >= g2c.size())
+ g2c.resize(g + 1, 0);
+ if (!g2c[g])
+ g2c[g] = c;
+ }
+ }
+ }
+ break;
+ }
+
+ case F_TRIMMED: {
+ int firstCode = USHORT_AT(data + 6);
+ int entryCount = USHORT_AT(data + 8);
+ for (int i = 0; i < entryCount; i++)
+ if (int g = USHORT_AT(data + 10 + (i << 1))) {
+ if (g >= g2c.size())
+ g2c.resize(g + 1, 0);
+ if (!g2c[g])
+ g2c[g] = firstCode + i;
+ }
+ break;
+ }
+
+ case F_SEGMENTED32: {
+ uint32_t nGroups = ULONG_AT(data + 12);
+ const uint8_t *groups = data + 16;
+ for (uint32_t i = 0; i < nGroups; i++, groups += 12) {
+ uint32_t startCharCode = ULONG_AT(groups);
+ uint32_t nCharCodes = ULONG_AT(groups + 4) - startCharCode;
+ uint32_t startGlyphID = ULONG_AT(groups + 8);
+ if (startGlyphID + nCharCodes >= (uint32_t) g2c.size())
+ g2c.resize(startGlyphID + nCharCodes + 1, 0);
+ for (uint32_t i = 0; i <= nCharCodes; i++)
+ if (!g2c[startGlyphID + i])
+ g2c[startGlyphID + i] = startCharCode + i;
+ }
+ break;
+ }
+
+ default:
+ break;
+
+ }
+}
+
+int
+Cmap::map_uni(const Vector<uint32_t> &vin, Vector<Glyph> &vout) const
+{
+ int t;
+ if ((t = check_table(USE_FIRST_UNICODE_TABLE)) < 0)
+ return -1;
+ vout.resize(vin.size(), 0);
+ for (int i = 0; i < vin.size(); i++)
+ vout[i] = map_table(t, vin[i]);
+ return 0;
+}
+
+}}
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/otfdata.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/otfdata.cc
new file mode 100644
index 00000000000..46c7c885c59
--- /dev/null
+++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/otfdata.cc
@@ -0,0 +1,43 @@
+// -*- related-file-name: "../include/efont/otfdata.hh" -*-
+
+/* otfdata.{cc,hh} -- OpenType bounds-checked string type
+ *
+ * Copyright (c) 2003-2012 Eddie Kohler
+ *
+ * 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 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <efont/otfdata.hh>
+
+namespace Efont { namespace OpenType {
+
+Data
+Data::subtable(unsigned offset) const throw (Bounds)
+{
+ if (offset > (unsigned) _str.length())
+ throw Bounds();
+ return Data(_str.substring(offset));
+}
+
+Data
+Data::offset_subtable(unsigned offset_offset) const throw (Bounds)
+{
+ int offset = u16(offset_offset);
+ if (offset > _str.length())
+ throw Bounds();
+ return Data(_str.substring(offset));
+}
+
+}}
+
+// template instantiations
+#include <lcdf/vector.cc>
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/otfdescrip.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/otfdescrip.cc
new file mode 100644
index 00000000000..307f0b3cb61
--- /dev/null
+++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/otfdescrip.cc
@@ -0,0 +1,717 @@
+/* otfdescrip.cc -- descriptions for OpenType tags
+ *
+ * Copyright (c) 2002-2012 Eddie Kohler
+ *
+ * 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 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <efont/otf.hh>
+
+struct Mapping {
+ uint32_t tag;
+ const char *description;
+};
+
+#define T(str) ((str)[0]<<24 | (str)[1]<<16 | (str)[2]<<8 | (str)[3])
+
+static const Mapping scripts[] = {
+ { T("DFLT"), "Default" },
+ { T("arab"), "Arabic" },
+ { T("armi"), "Imperial Aramaic" },
+ { T("armn"), "Armenian" },
+ { T("avst"), "Avestan" },
+ { T("bali"), "Balinese" },
+ { T("bamu"), "Bamum" },
+ { T("batk"), "Batak" },
+ { T("beng"), "Bengali" },
+ { T("bng2"), "Bengali v.2" },
+ { T("bopo"), "Bopomofo" },
+ { T("brah"), "Brahmi" },
+ { T("brai"), "Braille" },
+ { T("bugi"), "Buginese" },
+ { T("buhd"), "Buhid" },
+ { T("byzm"), "Byzantine Music" },
+ { T("cakm"), "Chakma" },
+ { T("cans"), "Canadian Syllabics" },
+ { T("cari"), "Carian" },
+ { T("cham"), "Cham" },
+ { T("cher"), "Cherokee" },
+ { T("copt"), "Coptic" },
+ { T("cprt"), "Cypriot Syllabary" },
+ { T("cyrl"), "Cyrillic" },
+ { T("dev2"), "Devanagari v.2" },
+ { T("deva"), "Devanagari" },
+ { T("dsrt"), "Deseret" },
+ { T("egyp"), "Egyptian heiroglyphs" },
+ { T("ethi"), "Ethiopic" },
+ { T("geor"), "Georgian" },
+ { T("gjr2"), "Gujarati v.2" },
+ { T("glag"), "Glagolitic" },
+ { T("goth"), "Gothic" },
+ { T("grek"), "Greek" },
+ { T("gujr"), "Gujarati" },
+ { T("gur2"), "Gurmukhi v.2" },
+ { T("guru"), "Gurmukhi" },
+ { T("hang"), "Hangul" },
+ { T("hani"), "CJK Ideographic" },
+ { T("hano"), "Hanunoo" },
+ { T("hebr"), "Hebrew" },
+ { T("ital"), "Old Italic" },
+ { T("jamo"), "Hangul Jamo" },
+ { T("java"), "Javanese" },
+ { T("kali"), "Kayah Li" },
+ { T("kana"), "Hiragana/Katakana" },
+ { T("khar"), "Kharosthi" },
+ { T("khmr"), "Khmer" },
+ { T("knd2"), "Kannada v.2" },
+ { T("knda"), "Kannada" },
+ { T("kthi"), "Kaithi" },
+ { T("lana"), "Tai Tham (Lanna)" },
+ { T("lao "), "Lao" },
+ { T("latn"), "Latin" },
+ { T("lepc"), "Lepcha" },
+ { T("limb"), "Limbu" },
+ { T("linb"), "Linear B" },
+ { T("lisu"), "Lisu (Fraser)" },
+ { T("lyci"), "Lycian" },
+ { T("lydi"), "Lydian" },
+ { T("mand"), "Mandaic, Mandaean" },
+ { T("math"), "Mathematical Alphanumeric Symbols" },
+ { T("merc"), "Meroitic Cursive" },
+ { T("mero"), "Meroitic Hieroglyphs" },
+ { T("mlm2"), "Malayalam v.2" },
+ { T("mlym"), "Malayalam" },
+ { T("mong"), "Mongolian" },
+ { T("mtei"), "Meitei Mayek (Meithei, Meetei)" },
+ { T("musc"), "Musical Symbols" },
+ { T("mymr"), "Myanmar" },
+ { T("nko "), "N'Ko" },
+ { T("ogam"), "Ogham" },
+ { T("olck"), "Ol Chiki" },
+ { T("orkh"), "Old Turkic, Orkhon Runic" },
+ { T("ory2"), "Odia v.2 (formerly Oriya v.2)" },
+ { T("orya"), "Odia (formerly Oriya)" },
+ { T("osma"), "Osmanya" },
+ { T("phag"), "Phags-pa" },
+ { T("phli"), "Inscriptional Pahlavi" },
+ { T("phnx"), "Phoenician" },
+ { T("prti"), "Inscriptional Parthian" },
+ { T("rjng"), "Rejang" },
+ { T("runr"), "Runic" },
+ { T("samr"), "Samaritan" },
+ { T("sarb"), "Old South Arabian" },
+ { T("saur"), "Saurashtra" },
+ { T("shaw"), "Shavian" },
+ { T("shrd"), "Sharada" },
+ { T("sinh"), "Sinhala" },
+ { T("sora"), "Sora Sompeng" },
+ { T("sund"), "Sundanese" },
+ { T("sylo"), "Syloti Nagri" },
+ { T("syrc"), "Syriac" },
+ { T("tagb"), "Tagbanwa" },
+ { T("takr"), "Takri" },
+ { T("tale"), "Tai Le" },
+ { T("talu"), "New Tai Lue" },
+ { T("taml"), "Tamil" },
+ { T("tavt"), "Tai Viet" },
+ { T("tel2"), "Telugu v.2" },
+ { T("telu"), "Telugu" },
+ { T("tfng"), "Tifinagh" },
+ { T("tglg"), "Tagalog" },
+ { T("thaa"), "Thaana" },
+ { T("thai"), "Thai" },
+ { T("tibt"), "Tibetan" },
+ { T("tml2"), "Tamil v.2" },
+ { T("ugar"), "Ugaritic Cuneiform" },
+ { T("vai "), "Vai" },
+ { T("xpeo"), "Old Persian Cuneiform" },
+ { T("xsux"), "Sumero-Akkadian Cuneiform" },
+ { T("yi "), "Yi" }
+};
+
+static const Mapping languages[] = {
+ { T("ABA "), "Abaza" },
+ { T("ABK "), "Abkhazian" },
+ { T("ADY "), "Adyghe" },
+ { T("AFK "), "Afrikaans" },
+ { T("AFR "), "Afar" },
+ { T("AGW "), "Agaw" },
+ { T("ALS "), "Alsatian" },
+ { T("ALT "), "Altai" },
+ { T("AMH "), "Amharic" },
+ { T("APPH"), "Phonetic transcription—Americanist conventions" },
+ { T("ARA "), "Arabic" },
+ { T("ARI "), "Aari" },
+ { T("ARK "), "Arakanese" },
+ { T("ASM "), "Assamese" },
+ { T("ATH "), "Athapaskan" },
+ { T("AVR "), "Avar" },
+ { T("AWA "), "Awadhi" },
+ { T("AYM "), "Aymara" },
+ { T("AZE "), "Azeri" },
+ { T("BAD "), "Badaga" },
+ { T("BAG "), "Baghelkhandi" },
+ { T("BAL "), "Balkar" },
+ { T("BAU "), "Baule" },
+ { T("BBR "), "Berber" },
+ { T("BCH "), "Bench" },
+ { T("BCR "), "Bible Cree" },
+ { T("BEL "), "Belarussian" },
+ { T("BEM "), "Bemba" },
+ { T("BEN "), "Bengali" },
+ { T("BGR "), "Bulgarian" },
+ { T("BHI "), "Bhili" },
+ { T("BHO "), "Bhojpuri" },
+ { T("BIK "), "Bikol" },
+ { T("BIL "), "Bilen" },
+ { T("BKF "), "Blackfoot" },
+ { T("BLI "), "Balochi" },
+ { T("BLN "), "Balante" },
+ { T("BLT "), "Balti" },
+ { T("BMB "), "Bambara" },
+ { T("BML "), "Bamileke" },
+ { T("BOS "), "Bosnian" },
+ { T("BRE "), "Breton" },
+ { T("BRH "), "Brahui" },
+ { T("BRI "), "Braj Bhasha" },
+ { T("BRM "), "Burmese" },
+ { T("BSH "), "Bashkir" },
+ { T("BTI "), "Beti" },
+ { T("CAT "), "Catalan" },
+ { T("CEB "), "Cebuano" },
+ { T("CHE "), "Chechen" },
+ { T("CHG "), "Chaha Gurage" },
+ { T("CHH "), "Chattisgarhi" },
+ { T("CHI "), "Chichewa" },
+ { T("CHK "), "Chukchi" },
+ { T("CHP "), "Chipewyan" },
+ { T("CHR "), "Cherokee" },
+ { T("CHU "), "Chuvash" },
+ { T("CMR "), "Comorian" },
+ { T("COP "), "Coptic" },
+ { T("COS "), "Corsican" },
+ { T("CRE "), "Cree" },
+ { T("CRR "), "Carrier" },
+ { T("CRT "), "Crimean Tatar" },
+ { T("CSL "), "Church Slavonic" },
+ { T("CSY "), "Czech" },
+ { T("DAN "), "Danish" },
+ { T("DAR "), "Dargwa" },
+ { T("DCR "), "Woods Cree" },
+ { T("DEU "), "German" },
+ { T("DGR "), "Dogri" },
+ { T("DHV "), "Dhivehi" }, // deprecated
+ { T("DIV "), "Dhivehi" },
+ { T("DJR "), "Djerma" },
+ { T("DNG "), "Dangme" },
+ { T("DNK "), "Dinka" },
+ { T("DRI "), "Dari" },
+ { T("DUN "), "Dungan" },
+ { T("DZN "), "Dzongkha" },
+ { T("EBI "), "Ebira" },
+ { T("ECR "), "Eastern Cree" },
+ { T("EDO "), "Edo" },
+ { T("EFI "), "Efik" },
+ { T("ELL "), "Greek" },
+ { T("ENG "), "English" },
+ { T("ERZ "), "Erzya" },
+ { T("ESP "), "Spanish" },
+ { T("ETI "), "Estonian" },
+ { T("EUQ "), "Basque" },
+ { T("EVK "), "Evenki" },
+ { T("EVN "), "Even" },
+ { T("EWE "), "Ewe" },
+ { T("FAN "), "French Antillean" },
+ { T("FAR "), "Farsi" },
+ { T("FIN "), "Finnish" },
+ { T("FJI "), "Fijian" },
+ { T("FLE "), "Flemish" },
+ { T("FNE "), "Forest Nenets" },
+ { T("FON "), "Fon" },
+ { T("FOS "), "Faroese" },
+ { T("FRA "), "French" },
+ { T("FRI "), "Frisian" },
+ { T("FRL "), "Friulian" },
+ { T("FTA "), "Futa" },
+ { T("FUL "), "Fulani" },
+ { T("GAD "), "Ga" },
+ { T("GAE "), "Gaelic" },
+ { T("GAG "), "Gagauz" },
+ { T("GAL "), "Galician" },
+ { T("GAR "), "Garshuni" },
+ { T("GAW "), "Garhwali" },
+ { T("GEZ "), "Ge'ez" },
+ { T("GIL "), "Gilyak" },
+ { T("GMZ "), "Gumuz" },
+ { T("GON "), "Gondi" },
+ { T("GRN "), "Greenlandic" },
+ { T("GRO "), "Garo" },
+ { T("GUA "), "Guarani" },
+ { T("GUJ "), "Gujarati" },
+ { T("HAI "), "Haitian" },
+ { T("HAL "), "Halam" },
+ { T("HAR "), "Harauti" },
+ { T("HAU "), "Hausa" },
+ { T("HAW "), "Hawaiian" },
+ { T("HBN "), "Hammer-Banna" },
+ { T("HIL "), "Hiligaynon" },
+ { T("HIN "), "Hindi" },
+ { T("HMA "), "High Mari" },
+ { T("HND "), "Hindko" },
+ { T("HO "), "Ho" },
+ { T("HRI "), "Harari" },
+ { T("HRV "), "Croatian" },
+ { T("HUN "), "Hungarian" },
+ { T("HYE "), "Armenian" },
+ { T("IBO "), "Igbo" },
+ { T("IJO "), "Ijo" },
+ { T("ILO "), "Ilokano" },
+ { T("IND "), "Indonesian" },
+ { T("ING "), "Ingush" },
+ { T("INU "), "Inuktitut" },
+ { T("IPPH"), "Phonetic transcription—IPA conventions" },
+ { T("IRI "), "Irish" },
+ { T("IRT "), "Irish Traditional" },
+ { T("ISL "), "Icelandic" },
+ { T("ISM "), "Inari Sami" },
+ { T("ITA "), "Italian" },
+ { T("IWR "), "Hebrew" },
+ { T("JAN "), "Japanese" },
+ { T("JAV "), "Javanese" },
+ { T("JII "), "Yiddish" },
+ { T("JUD "), "Judezmo" },
+ { T("JUL "), "Jula" },
+ { T("KAB "), "Kabardian" },
+ { T("KAC "), "Kachchi" },
+ { T("KAL "), "Kalenjin" },
+ { T("KAN "), "Kannada" },
+ { T("KAR "), "Karachay" },
+ { T("KAT "), "Georgian" },
+ { T("KAZ "), "Kazakh" },
+ { T("KEB "), "Kebena" },
+ { T("KGE "), "Khutsuri Georgian" },
+ { T("KHA "), "Khakass" },
+ { T("KHK "), "Khanty-Kazim" },
+ { T("KHM "), "Khmer" },
+ { T("KHS "), "Khanty-Shurishkar" },
+ { T("KHV "), "Khanty-Vakhi" },
+ { T("KHW "), "Khowar" },
+ { T("KIK "), "Kikuyu" },
+ { T("KIR "), "Kirghiz" },
+ { T("KIS "), "Kisii" },
+ { T("KKN "), "Kokni" },
+ { T("KLM "), "Kalmyk" },
+ { T("KMB "), "Kamba" },
+ { T("KMN "), "Kumaoni" },
+ { T("KMO "), "Komo" },
+ { T("KMS "), "Komso" },
+ { T("KNR "), "Kanuri" },
+ { T("KOD "), "Kodagu" },
+ { T("KOH "), "Korean Old Hangul" },
+ { T("KOK "), "Konkani" },
+ { T("KON "), "Kikongo" },
+ { T("KOP "), "Komi-Permyak" },
+ { T("KOR "), "Korean" },
+ { T("KOZ "), "Komi-Zyrian" },
+ { T("KPL "), "Kpelle" },
+ { T("KRI "), "Krio" },
+ { T("KRK "), "Karakalpak" },
+ { T("KRL "), "Karelian" },
+ { T("KRM "), "Karaim" },
+ { T("KRN "), "Karen" },
+ { T("KRT "), "Koorete" },
+ { T("KSH "), "Kashmiri" },
+ { T("KSI "), "Khasi" },
+ { T("KSM "), "Kildin Sami" },
+ { T("KUI "), "Kui" },
+ { T("KUL "), "Kulvi" },
+ { T("KUM "), "Kumyk" },
+ { T("KUR "), "Kurdish" },
+ { T("KUU "), "Kurukh" },
+ { T("KUY "), "Kuy" },
+ { T("KYK "), "Koryak" },
+ { T("LAD "), "Ladin" },
+ { T("LAH "), "Lahuli" },
+ { T("LAK "), "Lak" },
+ { T("LAM "), "Lambani" },
+ { T("LAO "), "Lao" },
+ { T("LAT "), "Latin" },
+ { T("LAZ "), "Laz" },
+ { T("LCR "), "L-Cree" },
+ { T("LDK "), "Ladakhi" },
+ { T("LEZ "), "Lezgi" },
+ { T("LIN "), "Lingala" },
+ { T("LMA "), "Low Mari" },
+ { T("LMB "), "Limbu" },
+ { T("LMW "), "Lomwe" },
+ { T("LSB "), "Lower Sorbian" },
+ { T("LSM "), "Lule Sami" },
+ { T("LTH "), "Lithuanian" },
+ { T("LTZ "), "Luxembourgish" },
+ { T("LUB "), "Luba" },
+ { T("LUG "), "Luganda" },
+ { T("LUH "), "Luhya" },
+ { T("LUO "), "Luo" },
+ { T("LVI "), "Latvian" },
+ { T("MAJ "), "Majang" },
+ { T("MAK "), "Makua" },
+ { T("MAL "), "Malayalam Traditional" },
+ { T("MAN "), "Mansi" },
+ { T("MAP "), "Mapudungun" },
+ { T("MAR "), "Marathi" },
+ { T("MAW "), "Marwari" },
+ { T("MBN "), "Mbundu" },
+ { T("MCH "), "Manchu" },
+ { T("MCR "), "Moose Cree" },
+ { T("MDE "), "Mende" },
+ { T("MEN "), "Me'en" },
+ { T("MIZ "), "Mizo" },
+ { T("MKD "), "Macedonian" },
+ { T("MLE "), "Male" },
+ { T("MLG "), "Malagasy" },
+ { T("MLN "), "Malinke" },
+ { T("MLR "), "Malayalam Reformed" },
+ { T("MLY "), "Malay" },
+ { T("MND "), "Mandinka" },
+ { T("MNG "), "Mongolian" },
+ { T("MNI "), "Manipuri" },
+ { T("MNK "), "Maninka" },
+ { T("MNX "), "Manx Gaelic" },
+ { T("MOH "), "Mohawk" },
+ { T("MOK "), "Moksha" },
+ { T("MOL "), "Moldavian" },
+ { T("MON "), "Mon" },
+ { T("MOR "), "Moroccan" },
+ { T("MRI "), "Maori" },
+ { T("MTH "), "Maithili" },
+ { T("MTS "), "Maltese" },
+ { T("MUN "), "Mundari" },
+ { T("NAG "), "Naga-Assamese" },
+ { T("NAN "), "Nanai" },
+ { T("NAS "), "Naskapi" },
+ { T("NCR "), "N-Cree" },
+ { T("NDB "), "Ndebele" },
+ { T("NDG "), "Ndonga" },
+ { T("NEP "), "Nepali" },
+ { T("NEW "), "Newari" },
+ { T("NGR "), "Nagari" },
+ { T("NHC "), "Norway House Cree" },
+ { T("NIS "), "Nisi" },
+ { T("NIU "), "Niuean" },
+ { T("NKL "), "Nkole" },
+ { T("NKO "), "N'Ko" },
+ { T("NLD "), "Dutch" },
+ { T("NOG "), "Nogai" },
+ { T("NOR "), "Norwegian" },
+ { T("NSM "), "Northern Sami" },
+ { T("NTA "), "Northern Tai" },
+ { T("NTO "), "Esperanto" },
+ { T("NYN "), "Nynorsk" },
+ { T("OCI "), "Occitan" },
+ { T("OCR "), "Oji-Cree" },
+ { T("OJB "), "Ojibway" },
+ { T("ORI "), "Odia (formerly Oriya)" },
+ { T("ORO "), "Oromo" },
+ { T("OSS "), "Ossetian" },
+ { T("PAA "), "Palestinian Aramaic" },
+ { T("PAL "), "Pali" },
+ { T("PAN "), "Punjabi" },
+ { T("PAP "), "Palpa" },
+ { T("PAS "), "Pashto" },
+ { T("PGR "), "Polytonic Greek" },
+ { T("PIL "), "Filipino" },
+ { T("PLG "), "Palaung" },
+ { T("PLK "), "Polish" },
+ { T("PRO "), "Provencal" },
+ { T("PTG "), "Portuguese" },
+ { T("QIN "), "Chin" },
+ { T("RAJ "), "Rajasthani" },
+ { T("RBU "), "Russian Buriat" },
+ { T("RCR "), "R-Cree" },
+ { T("RIA "), "Riang" },
+ { T("RMS "), "Rhaeto-Romanic" },
+ { T("ROM "), "Romanian" },
+ { T("ROY "), "Romany" },
+ { T("RSY "), "Rusyn" },
+ { T("RUA "), "Ruanda" },
+ { T("RUS "), "Russian" },
+ { T("SAD "), "Sadri" },
+ { T("SAN "), "Sanskrit" },
+ { T("SAT "), "Santali" },
+ { T("SAY "), "Sayisi" },
+ { T("SEK "), "Sekota" },
+ { T("SEL "), "Selkup" },
+ { T("SGO "), "Sango" },
+ { T("SHN "), "Shan" },
+ { T("SIB "), "Sibe" },
+ { T("SID "), "Sidamo" },
+ { T("SIG "), "Silte Gurage" },
+ { T("SKS "), "Skolt Sami" },
+ { T("SKY "), "Slovak" },
+ { T("SLA "), "Slavey" },
+ { T("SLV "), "Slovenian" },
+ { T("SML "), "Somali" },
+ { T("SMO "), "Samoan" },
+ { T("SNA "), "Sena" },
+ { T("SND "), "Sindhi" },
+ { T("SNH "), "Sinhalese" },
+ { T("SNK "), "Soninke" },
+ { T("SOG "), "Sodo Gurage" },
+ { T("SOT "), "Sotho" },
+ { T("SQI "), "Albanian" },
+ { T("SRB "), "Serbian" },
+ { T("SRK "), "Saraiki" },
+ { T("SRR "), "Serer" },
+ { T("SSL "), "South Slavey" },
+ { T("SSM "), "Southern Sami" },
+ { T("SUR "), "Suri" },
+ { T("SVA "), "Svan" },
+ { T("SVE "), "Swedish" },
+ { T("SWA "), "Swadaya Aramaic" },
+ { T("SWK "), "Swahili" },
+ { T("SWZ "), "Swazi" },
+ { T("SXT "), "Sutu" },
+ { T("SYR "), "Syriac" },
+ { T("TAB "), "Tabasaran" },
+ { T("TAJ "), "Tajiki" },
+ { T("TAM "), "Tamil" },
+ { T("TAT "), "Tatar" },
+ { T("TCR "), "TH-Cree" },
+ { T("TEL "), "Telugu" },
+ { T("TGN "), "Tongan" },
+ { T("TGR "), "Tigre" },
+ { T("TGY "), "Tigrinya" },
+ { T("THA "), "Thai" },
+ { T("THT "), "Tahitian" },
+ { T("TIB "), "Tibetan" },
+ { T("TKM "), "Turkmen" },
+ { T("TMN "), "Temne" },
+ { T("TNA "), "Tswana" },
+ { T("TNE "), "Tundra Nenets" },
+ { T("TNG "), "Tonga" },
+ { T("TOD "), "Todo" },
+ { T("TRK "), "Turkish" },
+ { T("TSG "), "Tsonga" },
+ { T("TUA "), "Turoyo Aramaic" },
+ { T("TUL "), "Tulu" },
+ { T("TUR "), "Turkish" }, // deprecated?
+ { T("TUV "), "Tuvin" },
+ { T("TWI "), "Twi" },
+ { T("UDM "), "Udmurt" },
+ { T("UKR "), "Ukrainian" },
+ { T("URD "), "Urdu" },
+ { T("USB "), "Upper Sorbian" },
+ { T("UYG "), "Uyghur" },
+ { T("UZB "), "Uzbek" },
+ { T("VEN "), "Venda" },
+ { T("VIT "), "Vietnamese" },
+ { T("WA "), "Wa" },
+ { T("WAG "), "Wagdi" },
+ { T("WCR "), "West-Cree" },
+ { T("WEL "), "Welsh" },
+ { T("WLF "), "Wolof" },
+ { T("XBD "), "Tai Lue" },
+ { T("XHS "), "Xhosa" },
+ { T("YAK "), "Sakha" },
+ { T("YBA "), "Yoruba" },
+ { T("YCR "), "Y-Cree" },
+ { T("YIC "), "Yi Classic" },
+ { T("YIM "), "Yi Modern" },
+ { T("ZHH "), "Chinese, Hong Kong SAR" },
+ { T("ZHP "), "Chinese Phonetic" },
+ { T("ZHS "), "Chinese Simplified" },
+ { T("ZHT "), "Chinese Traditional" },
+ { T("ZND "), "Zande" },
+ { T("ZUL "), "Zulu" }
+};
+
+static const Mapping features[] = {
+ { T("aalt"), "Access All Alternates" },
+ { T("abvf"), "Above-base Forms" },
+ { T("abvm"), "Above-base Mark Positioning" },
+ { T("abvs"), "Above-base Substitutions" },
+ { T("afrc"), "Alternative Fractions" },
+ { T("akhn"), "Akhands" },
+ { T("blwf"), "Below-base Forms" },
+ { T("blwm"), "Below-base Mark Positioning" },
+ { T("blws"), "Below-base Substitutions" },
+ { T("c2pc"), "Petite Capitals From Capitals" },
+ { T("c2sc"), "Small Capitals From Capitals" },
+ { T("calt"), "Contextual Alternates" },
+ { T("case"), "Case-Sensitive Forms" },
+ { T("ccmp"), "Glyph Composition/Decomposition" },
+ { T("cfar"), "Conjunct Form After Ro" },
+ { T("cjct"), "Conjunct Forms" },
+ { T("clig"), "Contextual Ligatures" },
+ { T("cpct"), "Centered CJK Punctuation" },
+ { T("cpsp"), "Capital Spacing" },
+ { T("cswh"), "Contextual Swash" },
+ { T("curs"), "Cursive Positioning" },
+ { T("cv01"), "Character Variants 1" },
+ { T("cv02"), "Character Variants 2" },
+ { T("cv03"), "Character Variants 3" },
+ { T("cv04"), "Character Variants 4" },
+ { T("cv05"), "Character Variants 5" },
+ { T("cv06"), "Character Variants 6" },
+ // ... up to cv99
+ { T("dist"), "Distances" },
+ { T("dlig"), "Discretionary Ligatures" },
+ { T("dnom"), "Denominators" },
+ { T("expt"), "Expert Forms" },
+ { T("falt"), "Final Glyph on Line Alternates" },
+ { T("fin2"), "Terminal Forms #2" },
+ { T("fin3"), "Terminal Forms #3" },
+ { T("fina"), "Terminal Forms" },
+ { T("frac"), "Fractions" },
+ { T("fwid"), "Full Widths" },
+ { T("half"), "Half Forms" },
+ { T("haln"), "Halant Forms" },
+ { T("halt"), "Alternate Half Widths" },
+ { T("hist"), "Historical Forms" },
+ { T("hkna"), "Horizontal Kana Alternates" },
+ { T("hlig"), "Historical Ligatures" },
+ { T("hngl"), "Hangul" },
+ { T("hojo"), "Hojo Kanji Forms (JIS X 0212-1990 Kanji Forms)" },
+ { T("hwid"), "Half Widths" },
+ { T("init"), "Initial Forms" },
+ { T("isol"), "Isolated Forms" },
+ { T("ital"), "Italics" },
+ { T("jalt"), "Justification Alternates" },
+ { T("jp04"), "JIS2004 Forms" },
+ { T("jp78"), "JIS78 Forms" },
+ { T("jp83"), "JIS83 Forms" },
+ { T("jp90"), "JIS90 Forms" },
+ { T("kern"), "Kerning" },
+ { T("lfbd"), "Left Bounds" },
+ { T("liga"), "Standard Ligatures" },
+ { T("ljmo"), "Leading Jamo Forms" },
+ { T("lnum"), "Lining Figures" },
+ { T("locl"), "Localized Forms" },
+ { T("ltra"), "Left-to-right alternates" },
+ { T("ltrm"), "Left-to-right mirrored forms" },
+ { T("mark"), "Mark Positioning" },
+ { T("med2"), "Medial Forms #2" },
+ { T("medi"), "Medial Forms" },
+ { T("mgrk"), "Mathematical Greek" },
+ { T("mkmk"), "Mark to Mark Positioning" },
+ { T("mset"), "Mark Positioning via Substitution" },
+ { T("nalt"), "Alternate Annotation Forms" },
+ { T("nlck"), "NLC Kanji Forms" },
+ { T("nukt"), "Nukta Forms" },
+ { T("numr"), "Numerators" },
+ { T("onum"), "Oldstyle Figures" },
+ { T("opbd"), "Optical Bounds" },
+ { T("ordn"), "Ordinals" },
+ { T("ornm"), "Ornaments" },
+ { T("palt"), "Proportional Alternate Widths" },
+ { T("pcap"), "Petite Capitals" },
+ { T("pkna"), "Proportional Kana" },
+ { T("pnum"), "Proportional Figures" },
+ { T("pref"), "Pre-Base Forms" },
+ { T("pres"), "Pre-base Substitutions" },
+ { T("pstf"), "Post-base Forms" },
+ { T("psts"), "Post-base Substitutions" },
+ { T("pwid"), "Proportional Widths" },
+ { T("qwid"), "Quarter Widths" },
+ { T("rand"), "Randomize" },
+ { T("rkrf"), "Rakar Forms" },
+ { T("rlig"), "Required Ligatures" },
+ { T("rphf"), "Reph Forms" },
+ { T("rtbd"), "Right Bounds" },
+ { T("rtla"), "Right-to-left Alternates" },
+ { T("rtlm"), "Right-to-left Mirrored Forms" },
+ { T("ruby"), "Ruby Notation Forms" },
+ { T("salt"), "Stylistic Alternates" },
+ { T("sinf"), "Scientific Inferiors" },
+ { T("size"), "Optical Size" },
+ { T("smcp"), "Small Capitals" },
+ { T("smpl"), "Simplified Forms" },
+ { T("ss01"), "Stylistic Set 1" },
+ { T("ss02"), "Stylistic Set 2" },
+ { T("ss03"), "Stylistic Set 3" },
+ { T("ss04"), "Stylistic Set 4" },
+ { T("ss05"), "Stylistic Set 5" },
+ { T("ss06"), "Stylistic Set 6" },
+ { T("ss07"), "Stylistic Set 7" },
+ { T("ss08"), "Stylistic Set 8" },
+ { T("ss09"), "Stylistic Set 9" },
+ { T("ss10"), "Stylistic Set 10" },
+ { T("ss11"), "Stylistic Set 11" },
+ { T("ss12"), "Stylistic Set 12" },
+ { T("ss13"), "Stylistic Set 13" },
+ { T("ss14"), "Stylistic Set 14" },
+ { T("ss15"), "Stylistic Set 15" },
+ { T("ss16"), "Stylistic Set 16" },
+ { T("ss17"), "Stylistic Set 17" },
+ { T("ss18"), "Stylistic Set 18" },
+ { T("ss19"), "Stylistic Set 19" },
+ { T("ss20"), "Stylistic Set 20" },
+ { T("subs"), "Subscript" },
+ { T("sups"), "Superscript" },
+ { T("swsh"), "Swash" },
+ { T("titl"), "Titling" },
+ { T("tjmo"), "Trailing Jamo Forms" },
+ { T("tnam"), "Traditional Name Forms" },
+ { T("tnum"), "Tabular Figures" },
+ { T("trad"), "Traditional Forms" },
+ { T("twid"), "Third Widths" },
+ { T("unic"), "Unicase" },
+ { T("valt"), "Alternate Vertical Metrics" },
+ { T("vatu"), "Vattu Variants" },
+ { T("vert"), "Vertical Writing" },
+ { T("vhal"), "Alternate Vertical Half Metrics" },
+ { T("vjmo"), "Vowel Jamo Forms" },
+ { T("vkna"), "Vertical Kana Alternates" },
+ { T("vkrn"), "Vertical Kerning" },
+ { T("vpal"), "Proportional Alternate Vertical Metrics" },
+ { T("vrt2"), "Vertical Alternates and Rotation" },
+ { T("zero"), "Slashed Zero" }
+};
+
+namespace Efont { namespace OpenType {
+
+static const char *
+find_description(uint32_t tag, const Mapping *maps, int n)
+{
+ // should use STL...
+ int l = 0, r = n;
+ while (l < r) {
+ int m = l + (r - l) / 2;
+ if (maps[m].tag < tag)
+ l = m + 1;
+ else if (maps[m].tag == tag)
+ return maps[m].description;
+ else
+ r = m;
+ }
+ return 0;
+}
+
+const char *
+Tag::script_description() const
+{
+ return find_description(value(), scripts, sizeof(scripts) / sizeof(Mapping));
+}
+
+const char *
+Tag::language_description() const
+{
+ return find_description(value(), languages, sizeof(languages) / sizeof(Mapping));
+}
+
+const char *
+Tag::feature_description() const
+{
+ return find_description(value(), features, sizeof(features) / sizeof(Mapping));
+}
+
+}}
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/otfgpos.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/otfgpos.cc
new file mode 100644
index 00000000000..eb477256c5c
--- /dev/null
+++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/otfgpos.cc
@@ -0,0 +1,328 @@
+// -*- related-file-name: "../include/efont/otfgpos.hh" -*-
+
+/* otfgpos.{cc,hh} -- OpenType GPOS table
+ *
+ * Copyright (c) 2003-2012 Eddie Kohler
+ *
+ * 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 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <efont/otfgpos.hh>
+#include <lcdf/error.hh>
+#include <lcdf/straccum.hh>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <algorithm>
+
+namespace Efont { namespace OpenType {
+
+
+/**************************
+ * Gpos *
+ * *
+ **************************/
+
+Gpos::Gpos(const Data &d, ErrorHandler *errh) throw (Error)
+{
+ // Fixed Version
+ // Offset ScriptList
+ // Offset FeatureList
+ // Offset LookupList
+ if (d.length() == 0)
+ throw BlankTable("GPOS");
+ if (d.u16(0) != 1)
+ throw Format("GPOS");
+ if (_script_list.assign(d.offset_subtable(4), errh) < 0)
+ throw Format("GPOS script list");
+ if (_feature_list.assign(d.offset_subtable(6), errh) < 0)
+ throw Format("GPOS feature list");
+ _lookup_list = d.offset_subtable(8);
+}
+
+int
+Gpos::nlookups() const
+{
+ return _lookup_list.u16(0);
+}
+
+GposLookup
+Gpos::lookup(unsigned i) const
+{
+ if (i >= _lookup_list.u16(0))
+ throw Error("GPOS lookup out of range");
+ else
+ return GposLookup(_lookup_list.offset_subtable(2 + i*2));
+}
+
+
+/**************************
+ * GposValue *
+ * *
+ **************************/
+
+const int GposValue::nibble_bitcount_x2[] = { 0, 2, 2, 4, 2, 4, 4, 6,
+ 2, 4, 4, 6, 4, 6, 6, 8 };
+
+
+/**************************
+ * GposLookup *
+ * *
+ **************************/
+
+GposLookup::GposLookup(const Data &d) throw (Error)
+ : _d(d)
+{
+ if (_d.length() < 6)
+ throw Format("GPOS Lookup table");
+ _type = _d.u16(0);
+ if (_type == L_EXTENSION && _d.u16(4) != 0) {
+ Data first_subtable = _d.offset_subtable(HEADERSIZE);
+ if (first_subtable.length() < 8 || first_subtable.u16(0) != 1)
+ throw Format("GPOS Extension Lookup table");
+ _type = first_subtable.u16(2);
+ }
+}
+
+Data
+GposLookup::subtable(int i) const
+{
+ Data subd = _d.offset_subtable(HEADERSIZE + i*RECSIZE);
+ if (_d.u16(0) != L_EXTENSION)
+ return subd;
+ else if (subd.length() >= 8 && subd.u16(0) == 1 && subd.u16(2) == _type)
+ return subd.subtable(subd.u32(4));
+ else
+ return Data();
+}
+
+bool
+GposLookup::unparse_automatics(Vector<Positioning> &v, ErrorHandler *errh) const
+{
+ int nlookup = _d.u16(4), success = 0;
+ switch (_type) {
+ case L_SINGLE:
+ for (int i = 0; i < nlookup; i++)
+ try {
+ GposSingle s(subtable(i));
+ s.unparse(v);
+ success++;
+ } catch (Error e) {
+ if (errh)
+ errh->warning("%s, continuing", e.description.c_str());
+ }
+ return success > 0;
+ case L_PAIR:
+ for (int i = 0; i < nlookup; i++)
+ try {
+ GposPair p(subtable(i));
+ p.unparse(v);
+ success++;
+ } catch (Error e) {
+ if (errh)
+ errh->warning("%s, continuing", e.description.c_str());
+ }
+ return success > 0;
+ default:
+ return false;
+ }
+}
+
+
+/**************************
+ * GposSingle *
+ * *
+ **************************/
+
+GposSingle::GposSingle(const Data &d) throw (Error)
+ : _d(d)
+{
+ if (_d[0] != 0
+ || (_d[1] != 1 && _d[1] != 2))
+ throw Format("GPOS Single Positioning");
+ Coverage coverage(_d.offset_subtable(2));
+ if (!coverage.ok()
+ || (_d[1] == 2 && coverage.size() > _d.u16(6)))
+ throw Format("GPOS Single Positioning coverage");
+}
+
+Coverage
+GposSingle::coverage() const throw ()
+{
+ return Coverage(_d.offset_subtable(2), 0, false);
+}
+
+void
+GposSingle::unparse(Vector<Positioning> &v) const
+{
+ if (_d[1] == 1) {
+ int format = _d.u16(4);
+ Data value = _d.subtable(6);
+ for (Coverage::iterator i = coverage().begin(); i; i++)
+ v.push_back(Positioning(Position(*i, format, value)));
+ } else {
+ int format = _d.u16(4);
+ int size = GposValue::size(format);
+ for (Coverage::iterator i = coverage().begin(); i; i++)
+ v.push_back(Positioning(Position(*i, format, _d.subtable(F2_HEADERSIZE + size*i.coverage_index()))));
+ }
+}
+
+
+/**************************
+ * GposPair *
+ * *
+ **************************/
+
+GposPair::GposPair(const Data &d) throw (Error)
+ : _d(d)
+{
+ if (_d[0] != 0
+ || (_d[1] != 1 && _d[1] != 2))
+ throw Format("GPOS Pair Positioning");
+ Coverage coverage(_d.offset_subtable(2));
+ if (!coverage.ok()
+ || (_d[1] == 1 && coverage.size() > _d.u16(8)))
+ throw Format("GPOS Pair Positioning coverage");
+}
+
+Coverage
+GposPair::coverage() const throw ()
+{
+ return Coverage(_d.offset_subtable(2), 0, false);
+}
+
+void
+GposPair::unparse(Vector<Positioning> &v) const
+{
+ if (_d[1] == 1) {
+ int format1 = _d.u16(4);
+ int format2 = _d.u16(6);
+ int f2_pos = PAIRVALUE_HEADERSIZE + GposValue::size(format1);
+ int pairvalue_size = f2_pos + GposValue::size(format2);
+ for (Coverage::iterator i = coverage().begin(); i; i++) {
+ Data pairset = _d.offset_subtable(F1_HEADERSIZE + i.coverage_index()*F1_RECSIZE);
+ int npair = pairset.u16(0);
+ for (int j = 0; j < npair; j++) {
+ Data pair = pairset.subtable(PAIRSET_HEADERSIZE + j*pairvalue_size);
+ v.push_back(Positioning(Position(*i, format1, pair.subtable(PAIRVALUE_HEADERSIZE)),
+ Position(pair.u16(0), format2, pair.subtable(f2_pos))));
+ }
+ }
+ } else { // _d[1] == 2
+ int format1 = _d.u16(4);
+ int format2 = _d.u16(6);
+ int f2_pos = GposValue::size(format1);
+ int recsize = f2_pos + GposValue::size(format2);
+ ClassDef class1(_d.offset_subtable(8));
+ ClassDef class2(_d.offset_subtable(10));
+ Coverage coverage = this->coverage();
+ int nclass1 = _d.u16(12);
+ int nclass2 = _d.u16(14);
+ int offset = F2_HEADERSIZE;
+ for (int c1 = 0; c1 < nclass1; c1++)
+ for (int c2 = 0; c2 < nclass2; c2++, offset += recsize) {
+ Position p1(format1, _d.subtable(offset));
+ Position p2(format2, _d.subtable(offset + f2_pos));
+ if (p1 || p2) {
+ for (ClassDef::class_iterator c1i = class1.begin(c1, coverage); c1i; c1i++)
+ for (ClassDef::class_iterator c2i = class2.begin(c2); c2i; c2i++)
+ v.push_back(Positioning(Position(*c1i, p1), Position(*c2i, p2)));
+ }
+ }
+ }
+}
+
+
+/**************************
+ * Positioning *
+ * *
+ **************************/
+
+static void
+unparse_glyphid(StringAccum &sa, Glyph gid, const Vector<PermString> *gns)
+{
+ if (!gns)
+ gns = &debug_glyph_names;
+ if (gid && gns && gns->size() > gid && (*gns)[gid])
+ sa << (*gns)[gid];
+ else
+ sa << "g" << gid;
+}
+
+void
+Position::unparse(StringAccum &sa, const Vector<PermString> *gns) const
+{
+ unparse_glyphid(sa, g, gns);
+ if (placed())
+ sa << '@' << pdx << ',' << pdy;
+ sa << '+' << adx;
+ if (ady)
+ sa << '/' << ady;
+}
+
+String
+Position::unparse(const Vector<PermString> *gns) const
+{
+ StringAccum sa;
+ unparse(sa, gns);
+ return sa.take_string();
+}
+
+bool
+Positioning::context_in(const Coverage &c) const
+{
+ return (c.covers(_left.g) || !_left.g) && (!_right.g || c.covers(_right.g));
+}
+
+bool
+Positioning::context_in(const GlyphSet &gs) const
+{
+ return (gs.covers(_left.g) || !_left.g) && (!_right.g || gs.covers(_right.g));
+}
+
+void
+Positioning::unparse(StringAccum &sa, const Vector<PermString> *gns) const
+{
+ if (!*this)
+ sa << "NULL[]";
+ else if (is_single()) {
+ sa << "SINGLE[";
+ _left.unparse(sa, gns);
+ sa << ']';
+ } else if (is_pairkern()) {
+ sa << "KERN[";
+ unparse_glyphid(sa, _left.g, gns);
+ sa << ' ';
+ unparse_glyphid(sa, _right.g, gns);
+ sa << "+" << _left.adx << ']';
+ } else if (is_pair()) {
+ sa << "PAIR[";
+ _left.unparse(sa, gns);
+ sa << ' ';
+ _right.unparse(sa, gns);
+ sa << ']';
+ } else
+ sa << "UNKNOWN[]";
+}
+
+String
+Positioning::unparse(const Vector<PermString> *gns) const
+{
+ StringAccum sa;
+ unparse(sa, gns);
+ return sa.take_string();
+}
+
+}}
+
+#include <lcdf/vector.cc>
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/otfgsub.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/otfgsub.cc
new file mode 100644
index 00000000000..10597847270
--- /dev/null
+++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/otfgsub.cc
@@ -0,0 +1,1285 @@
+// -*- related-file-name: "../include/efont/otfgsub.hh" -*-
+
+/* otfgsub.{cc,hh} -- OpenType GSUB table
+ *
+ * Copyright (c) 2003-2012 Eddie Kohler
+ *
+ * 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 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <efont/otfgsub.hh>
+#include <efont/otfname.hh>
+#include <lcdf/error.hh>
+#include <lcdf/straccum.hh>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <algorithm>
+
+namespace Efont { namespace OpenType {
+
+void
+Substitution::clear(Substitute &s, uint8_t &t)
+{
+ switch (t) {
+ case T_GLYPHS:
+ delete[] s.gids;
+ break;
+ case T_COVERAGE:
+ delete s.coverage;
+ break;
+ }
+ t = T_NONE;
+}
+
+void
+Substitution::assign_space(Substitute &s, uint8_t &t, int n)
+{
+ clear(s, t);
+ if (n == 1)
+ t = T_GLYPH;
+ else if (n > 1) {
+ s.gids = new Glyph[n + 1];
+ s.gids[0] = n;
+ t = T_GLYPHS;
+ }
+}
+
+void
+Substitution::assign(Substitute &s, uint8_t &t, Glyph gid)
+{
+ clear(s, t);
+ s.gid = gid;
+ t = T_GLYPH;
+}
+
+void
+Substitution::assign(Substitute &s, uint8_t &t, int ngids, const Glyph *gids)
+{
+ clear(s, t);
+ assert(ngids > 0);
+ if (ngids == 1) {
+ s.gid = gids[0];
+ t = T_GLYPH;
+ } else {
+ s.gids = new Glyph[ngids + 1];
+ s.gids[0] = ngids;
+ memcpy(s.gids + 1, gids, ngids * sizeof(Glyph));
+ t = T_GLYPHS;
+ }
+}
+
+void
+Substitution::assign(Substitute &s, uint8_t &t, const Coverage &coverage)
+{
+ clear(s, t);
+ s.coverage = new Coverage(coverage);
+ t = T_COVERAGE;
+}
+
+void
+Substitution::assign(Substitute &s, uint8_t &t, const Substitute &os, uint8_t ot)
+{
+ if (&s == &os)
+ return;
+ switch (ot) {
+ case T_NONE:
+ clear(s, t);
+ break;
+ case T_GLYPH:
+ assign(s, t, os.gid);
+ break;
+ case T_GLYPHS:
+ assign(s, t, os.gids[0], os.gids + 1);
+ break;
+ case T_COVERAGE:
+ assign(s, t, *os.coverage);
+ break;
+ default:
+ assert(0);
+ }
+}
+
+Substitution::Substitution(const Substitution &o)
+ : _left_is(T_NONE), _in_is(T_NONE), _out_is(T_NONE), _right_is(T_NONE),
+ _alternate(o._alternate)
+{
+ assign(_left, _left_is, o._left, o._left_is);
+ assign(_in, _in_is, o._in, o._in_is);
+ assign(_out, _out_is, o._out, o._out_is);
+ assign(_right, _right_is, o._right, o._right_is);
+}
+
+Substitution::Substitution(Glyph in, Glyph out)
+ : _left_is(T_NONE), _in_is(T_GLYPH), _out_is(T_GLYPH), _right_is(T_NONE)
+{
+ _in.gid = in;
+ _out.gid = out;
+}
+
+Substitution::Substitution(Glyph in, const Vector<Glyph> &out, bool is_alternate)
+ : _left_is(T_NONE), _in_is(T_GLYPH), _out_is(T_NONE), _right_is(T_NONE),
+ _alternate(is_alternate)
+{
+ assert(out.size() > 0);
+ _in.gid = in;
+ assign(_out, _out_is, out.size(), &out[0]);
+}
+
+Substitution::Substitution(Glyph in1, Glyph in2, Glyph out)
+ : _left_is(T_NONE), _in_is(T_GLYPHS), _out_is(T_GLYPH), _right_is(T_NONE)
+{
+ _in.gids = new Glyph[3];
+ _in.gids[0] = 2;
+ _in.gids[1] = in1;
+ _in.gids[2] = in2;
+ _out.gid = out;
+}
+
+Substitution::Substitution(const Vector<Glyph> &in, Glyph out)
+ : _left_is(T_NONE), _in_is(T_NONE), _out_is(T_GLYPH), _right_is(T_NONE)
+{
+ assert(in.size() > 0);
+ assign(_in, _in_is, in.size(), &in[0]);
+ _out.gid = out;
+}
+
+Substitution::Substitution(int nin, const Glyph *in, Glyph out)
+ : _left_is(T_NONE), _in_is(T_NONE), _out_is(T_GLYPH), _right_is(T_NONE)
+{
+ assert(nin > 0);
+ assign(_in, _in_is, nin, in);
+ _out.gid = out;
+}
+
+Substitution::Substitution(int nleft, int nin, int nout, int nright)
+ : _left_is(T_NONE), _in_is(T_NONE), _out_is(T_NONE), _right_is(T_NONE)
+{
+ if (nleft)
+ assign_space(_left, _left_is, nleft);
+ if (nin)
+ assign_space(_in, _in_is, nin);
+ if (nout)
+ assign_space(_out, _out_is, nout);
+ if (nright)
+ assign_space(_right, _right_is, nright);
+}
+
+Substitution::~Substitution()
+{
+ clear(_left, _left_is);
+ clear(_in, _in_is);
+ clear(_out, _out_is);
+ clear(_right, _right_is);
+}
+
+Substitution &
+Substitution::operator=(const Substitution &o)
+{
+ assign(_left, _left_is, o._left, o._left_is);
+ assign(_in, _in_is, o._in, o._in_is);
+ assign(_out, _out_is, o._out, o._out_is);
+ assign(_right, _right_is, o._right, o._right_is);
+ _alternate = o._alternate;
+ return *this;
+}
+
+bool
+Substitution::substitute_in(const Substitute &s, uint8_t t, const Coverage &c)
+{
+ switch (t) {
+ case T_NONE:
+ return true;
+ case T_GLYPH:
+ return c.covers(s.gid);
+ case T_GLYPHS:
+ for (int i = 1; i <= s.gids[0]; i++)
+ if (!c.covers(s.gids[i]))
+ return false;
+ return true;
+ case T_COVERAGE:
+ return *s.coverage <= c;
+ default:
+ assert(0);
+ return false;
+ }
+}
+
+bool
+Substitution::substitute_in(const Substitute &s, uint8_t t, const GlyphSet &gs)
+{
+ switch (t) {
+ case T_NONE:
+ return true;
+ case T_GLYPH:
+ return gs.covers(s.gid);
+ case T_GLYPHS:
+ for (int i = 1; i <= s.gids[0]; i++)
+ if (!gs.covers(s.gids[i]))
+ return false;
+ return true;
+ case T_COVERAGE:
+ for (Coverage::iterator i = s.coverage->begin(); i; i++)
+ if (!gs.covers(*i))
+ return false;
+ return true;
+ default:
+ assert(0);
+ return false;
+ }
+}
+
+bool
+Substitution::context_in(const Coverage &c) const
+{
+ return substitute_in(_left, _left_is, c)
+ && substitute_in(_in, _in_is, c)
+ && substitute_in(_right, _right_is, c);
+}
+
+bool
+Substitution::context_in(const GlyphSet &gs) const
+{
+ return substitute_in(_left, _left_is, gs)
+ && substitute_in(_in, _in_is, gs)
+ && substitute_in(_right, _right_is, gs);
+}
+
+Glyph
+Substitution::extract_glyph(const Substitute &s, uint8_t t) throw ()
+{
+ return (t == T_GLYPH ? s.gid : 0);
+}
+
+Glyph
+Substitution::extract_glyph(const Substitute &s, int which, uint8_t t) throw ()
+{
+ switch (t) {
+ case T_GLYPH:
+ return (which == 0 ? s.gid : 0);
+ case T_GLYPHS:
+ return (s.gids[0] > which ? s.gids[which + 1] : 0);
+ case T_COVERAGE:
+ for (Coverage::iterator ci = s.coverage->begin(); ci; ci++, which--)
+ if (which == 0)
+ return *ci;
+ return 0;
+ default:
+ return 0;
+ }
+}
+
+bool
+Substitution::extract_glyphs(const Substitute &s, uint8_t t, Vector<Glyph> &v, bool coverage_ok) throw ()
+{
+ switch (t) {
+ case T_GLYPH:
+ v.push_back(s.gid);
+ return true;
+ case T_GLYPHS:
+ for (int i = 1; i <= s.gids[0]; i++)
+ v.push_back(s.gids[i]);
+ return true;
+ case T_COVERAGE:
+ if (coverage_ok) {
+ for (Coverage::iterator i = s.coverage->begin(); i; i++)
+ v.push_back(*i);
+ return true;
+ } else
+ return false;
+ default:
+ return false;
+ }
+}
+
+Glyph *
+Substitution::extract_glyphptr(const Substitute &s, uint8_t t) throw ()
+{
+ switch (t) {
+ case T_GLYPH:
+ return const_cast<Glyph *>(&s.gid);
+ case T_GLYPHS:
+ return &s.gids[1];
+ default:
+ return 0;
+ }
+}
+
+int
+Substitution::extract_nglyphs(const Substitute &s, uint8_t t, bool coverage_ok) throw ()
+{
+ switch (t) {
+ case T_GLYPH:
+ return 1;
+ case T_GLYPHS:
+ return s.gids[0];
+ case T_COVERAGE:
+ return (coverage_ok ? 1 : 0);
+ default:
+ return 0;
+ }
+}
+
+bool
+Substitution::matches(const Substitute &s, uint8_t t, int pos, Glyph g) throw ()
+{
+ switch (t) {
+ case T_GLYPH:
+ return (pos == 0 && s.gid == g);
+ case T_GLYPHS:
+ return (pos >= 0 && pos < s.gids[0] && s.gids[1 + pos] == g);
+ case T_COVERAGE:
+ return (pos == 0 && s.coverage->covers(g));
+ default:
+ return false;
+ }
+}
+
+bool
+Substitution::is_noop() const
+{
+ return (_in_is == T_GLYPH && _out_is == T_GLYPH && _in.gid == _out.gid)
+ || (_in_is == T_GLYPHS && _out_is == T_GLYPHS
+ && _in.gids[0] == _out.gids[0]
+ && memcmp(_in.gids, _out.gids, (_in.gids[0] + 1) * sizeof(Glyph)) == 0);
+}
+
+bool
+Substitution::all_in_glyphs(Vector<Glyph> &gs) const
+{
+ bool ok = true;
+ gs.clear();
+ if (_left_is != T_NONE)
+ ok &= extract_glyphs(_left, _left_is, gs, false);
+ ok &= extract_glyphs(_in, _in_is, gs, false);
+ if (_right_is != T_NONE)
+ ok &= extract_glyphs(_right, _right_is, gs, false);
+ return ok;
+}
+
+bool
+Substitution::all_out_glyphs(Vector<Glyph> &v) const
+{
+ bool ok = true;
+ if (_left_is != T_NONE)
+ ok &= extract_glyphs(_left, _left_is, v, false);
+ ok &= extract_glyphs(_out, _out_is, v, false);
+ if (_right_is != T_NONE)
+ ok &= extract_glyphs(_right, _right_is, v, false);
+ return ok;
+}
+
+void
+Substitution::assign_append(Substitute &s, uint8_t &t, const Substitute &ls, uint8_t lt, const Substitute &rs, uint8_t rt)
+{
+ if (lt == T_NONE)
+ assign(s, t, rs, rt);
+ else if (rt == T_NONE)
+ assign(s, t, ls, lt);
+ else if (lt != T_COVERAGE && rt != T_COVERAGE) {
+ int nl = extract_nglyphs(ls, lt, false);
+ int nr = extract_nglyphs(rs, rt, false);
+ Glyph *gids = new Glyph[nl + nr + 1];
+ gids[0] = nl + nr;
+ memcpy(&gids[1], extract_glyphptr(ls, lt), nl * sizeof(Glyph));
+ memcpy(&gids[1 + nl], extract_glyphptr(rs, rt), nr * sizeof(Glyph));
+ clear(s, t);
+ s.gids = gids;
+ t = T_GLYPHS;
+ } else
+ throw Error();
+}
+
+void
+Substitution::assign_append(Substitute &s, uint8_t &t, const Substitute &ls, uint8_t lt, Glyph rg)
+{
+ Substitute rs;
+ rs.gid = rg;
+ assign_append(s, t, ls, lt, rs, T_GLYPH);
+}
+
+Substitution
+Substitution::in_out_append_glyph(Glyph g) const
+{
+ Substitution s;
+ assign(s._left, s._left_is, _left, _left_is);
+ assign(s._right, s._right_is, _right, _right_is);
+ assign_append(s._in, s._in_is, _in, _in_is, g);
+ assign_append(s._out, s._out_is, _out, _out_is, g);
+ return s;
+}
+
+void
+Substitution::add_outer_left(Glyph g)
+{
+ Substitute ls;
+ ls.gid = g;
+ assign_append(_left, _left_is, ls, T_GLYPH, _left, _left_is);
+}
+
+void
+Substitution::remove_outer_left()
+{
+ if (_left_is == T_GLYPH)
+ _left_is = T_NONE;
+ else if (_left_is == T_GLYPHS) {
+ if (_left.gids[0] == 2)
+ assign(_left, _left_is, _left.gids[2]);
+ else {
+ _left.gids[0]--;
+ memmove(_left.gids + 1, _left.gids + 2, _left.gids[0] * sizeof(Glyph));
+ }
+ }
+}
+
+void
+Substitution::add_outer_right(Glyph g)
+{
+ assign_append(_right, _right_is, _right, _right_is, g);
+}
+
+void
+Substitution::remove_outer_right()
+{
+ if (_right_is == T_GLYPH)
+ _right_is = T_NONE;
+ else if (_right_is == T_GLYPHS) {
+ if (_right.gids[0] == 2)
+ assign(_right, _right_is, _right.gids[1]);
+ else
+ _right.gids[0]--;
+ }
+}
+
+bool
+Substitution::out_alter(const Substitution &o, int pos) throw ()
+{
+ const Glyph *g = out_glyphptr();
+ int ng = out_nglyphs();
+ const Glyph *out_g = o.out_glyphptr();
+ int out_ng = o.out_nglyphs();
+ int in_ng = o.in_nglyphs();
+ if (pos + in_ng > ng || out_ng == 0)
+ return false;
+
+ // check that input substitution actually matches us
+ for (int i = 0; i < in_ng; i++)
+ if (!o.in_matches(i, g[pos+i]))
+ return false;
+
+ // actually change output
+ Vector<Glyph> new_g;
+ for (int i = 0; i < pos; i++)
+ new_g.push_back(g[i]);
+ for (int i = 0; i < out_ng; i++)
+ new_g.push_back(out_g[i]);
+ for (int i = pos + in_ng; i < ng; i++)
+ new_g.push_back(g[i]);
+ assign(_out, _out_is, new_g.size(), &new_g[0]);
+
+ return true;
+}
+
+static void
+unparse_glyphid(StringAccum &sa, Glyph gid, const Vector<PermString> *gns) throw ()
+{
+ if (gid > 0 && gns && gns->size() > gid && (*gns)[gid])
+ sa << (*gns)[gid];
+ else
+ sa << "g" << gid;
+}
+
+void
+Substitution::unparse_glyphids(StringAccum &sa, const Substitute &s, uint8_t t, const Vector<PermString> *gns) throw ()
+{
+ if (t == T_GLYPH)
+ unparse_glyphid(sa, s.gid, gns);
+ else if (t == T_GLYPHS) {
+ for (int i = 1; i <= s.gids[0]; i++) {
+ if (i != 1)
+ sa << ' ';
+ unparse_glyphid(sa, s.gids[i], gns);
+ }
+ } else if (t == T_COVERAGE)
+ sa << "<coverage>";
+ else
+ sa << "-";
+}
+
+void
+Substitution::unparse(StringAccum &sa, const Vector<PermString> *gns) const
+{
+ if (!*this)
+ sa << "NULL[]";
+ else {
+ if (is_single())
+ sa << "SINGLE[";
+ else if (is_ligature())
+ sa << "LIGATURE[";
+ else if (is_multiple())
+ sa << "MULTIPLE[";
+ else if (is_alternate())
+ sa << "ALTERNATE[";
+ else if (is_simple_context())
+ sa << "SIMPLECONTEXT[";
+ else
+ sa << "UNKNOWN[";
+
+ if (_left_is != T_NONE) {
+ unparse_glyphids(sa, _left, _left_is, gns);
+ sa << " | ";
+ }
+ unparse_glyphids(sa, _in, _in_is, gns);
+ sa << " => ";
+ unparse_glyphids(sa, _out, _out_is, gns);
+ if (_right_is != T_NONE) {
+ sa << " | ";
+ unparse_glyphids(sa, _right, _right_is, gns);
+ }
+
+ sa << ']';
+ }
+}
+
+String
+Substitution::unparse(const Vector<PermString> *gns) const
+{
+ StringAccum sa;
+ unparse(sa, gns);
+ return sa.take_string();
+}
+
+
+
+/**************************
+ * Gsub *
+ * *
+ **************************/
+
+Gsub::Gsub(const Data &d, const Font *otf, ErrorHandler *errh) throw (Error)
+ : _chaincontext_reverse_backtrack(false)
+{
+ // Fixed Version
+ // Offset ScriptList
+ // Offset FeatureList
+ // Offset LookupList
+ if (d.length() == 0)
+ throw BlankTable("GSUB");
+ if (d.u16(0) != 1)
+ throw Format("GSUB");
+ if (_script_list.assign(d.offset_subtable(4), errh) < 0)
+ throw Format("GSUB script list");
+ if (_feature_list.assign(d.offset_subtable(6), errh) < 0)
+ throw Format("GSUB feature list");
+ _lookup_list = d.offset_subtable(8);
+
+ if (!otf)
+ return;
+
+ // Check for "correct" chaining context rules, as suggested by Adobe's
+ // OpenType FDK
+ try {
+ Name nametable(otf->table("name"), ErrorHandler::silent_handler());
+ _chaincontext_reverse_backtrack = nametable.version_chaincontext_reverse_backtrack();
+ } catch (Error) {
+ }
+}
+
+int
+Gsub::nlookups() const
+{
+ return _lookup_list.u16(0);
+}
+
+GsubLookup
+Gsub::lookup(unsigned i) const
+{
+ if (i >= _lookup_list.u16(0))
+ throw Error("GSUB lookup out of range");
+ else
+ return GsubLookup(_lookup_list.offset_subtable(2 + i*2));
+}
+
+
+/**************************
+ * GsubLookup *
+ * *
+ **************************/
+
+GsubLookup::GsubLookup(const Data &d) throw (Error)
+ : _d(d)
+{
+ if (_d.length() < 6)
+ throw Format("GSUB Lookup table");
+ _type = _d.u16(0);
+ if (_type == L_EXTENSION && _d.u16(4) != 0) {
+ Data first_subtable = _d.offset_subtable(HEADERSIZE);
+ if (first_subtable.length() < 8 || first_subtable.u16(0) != 1)
+ throw Format("GSUB Extension Lookup table");
+ _type = first_subtable.u16(2);
+ }
+}
+
+Data
+GsubLookup::subtable(int i) const
+{
+ Data subd = _d.offset_subtable(HEADERSIZE + i*RECSIZE);
+ if (_d.u16(0) != L_EXTENSION)
+ return subd;
+ else if (subd.length() >= 8 && subd.u16(0) == 1 && subd.u16(2) == _type)
+ return subd.subtable(subd.u32(4));
+ else
+ return Data();
+}
+
+void
+GsubLookup::mark_out_glyphs(const Gsub &gsub, Vector<bool> &gmap) const
+{
+ int nlookup = _d.u16(4);
+ switch (_type) {
+ case L_SINGLE:
+ for (int i = 0; i < nlookup; i++) {
+ GsubSingle x(subtable(i)); // this pattern makes gcc-3.3.4 happier
+ x.mark_out_glyphs(gmap);
+ }
+ return;
+ case L_MULTIPLE:
+ for (int i = 0; i < nlookup; i++) {
+ GsubMultiple x(subtable(i));
+ x.mark_out_glyphs(gmap);
+ }
+ return;
+ case L_ALTERNATE:
+ for (int i = 0; i < nlookup; i++) {
+ GsubMultiple x(subtable(i));
+ x.mark_out_glyphs(gmap);
+ }
+ return;
+ case L_LIGATURE:
+ for (int i = 0; i < nlookup; i++) {
+ GsubLigature x(subtable(i));
+ x.mark_out_glyphs(gmap);
+ }
+ return;
+ case L_CONTEXT:
+ for (int i = 0; i < nlookup; i++) {
+ GsubContext x(subtable(i));
+ x.mark_out_glyphs(gsub, gmap);
+ }
+ return;
+ case L_CHAIN:
+ for (int i = 0; i < nlookup; i++) {
+ GsubChainContext x(subtable(i));
+ x.mark_out_glyphs(gsub, gmap);
+ }
+ return;
+ }
+}
+
+bool
+GsubLookup::unparse_automatics(const Gsub &gsub, Vector<Substitution> &v, const Coverage &limit) const
+{
+ int nlookup = _d.u16(4);
+ switch (_type) {
+ case L_SINGLE:
+ for (int i = 0; i < nlookup; i++) {
+ GsubSingle x(subtable(i)); // this pattern makes gcc-3.3.4 happier
+ x.unparse(v, limit);
+ }
+ return true;
+ case L_MULTIPLE:
+ for (int i = 0; i < nlookup; i++) {
+ GsubMultiple x(subtable(i));
+ x.unparse(v);
+ }
+ return true;
+ case L_ALTERNATE:
+ for (int i = 0; i < nlookup; i++) {
+ GsubMultiple x(subtable(i));
+ x.unparse(v, true);
+ }
+ return true;
+ case L_LIGATURE:
+ for (int i = 0; i < nlookup; i++) {
+ GsubLigature x(subtable(i));
+ x.unparse(v);
+ }
+ return true;
+ case L_CONTEXT: {
+ bool understood = true;
+ for (int i = 0; i < nlookup; i++) {
+ GsubContext x(subtable(i));
+ understood &= x.unparse(gsub, v, limit);
+ }
+ return understood;
+ }
+ case L_CHAIN: {
+ bool understood = true;
+ for (int i = 0; i < nlookup; i++) {
+ GsubChainContext x(subtable(i));
+ understood &= x.unparse(gsub, v, limit);
+ }
+ return understood;
+ }
+ default:
+ return false;
+ }
+}
+
+bool
+GsubLookup::apply(const Glyph *g, int pos, int n, Substitution &s) const
+{
+ int nlookup = _d.u16(4);
+ switch (_type) {
+ case L_SINGLE:
+ for (int i = 0; i < nlookup; i++) {
+ GsubSingle x(subtable(i));
+ if (x.apply(g, pos, n, s))
+ return true;
+ }
+ return false;
+ case L_MULTIPLE:
+ for (int i = 0; i < nlookup; i++) {
+ GsubMultiple x(subtable(i));
+ if (x.apply(g, pos, n, s))
+ return true;
+ }
+ return false;
+ case L_ALTERNATE:
+ for (int i = 0; i < nlookup; i++) {
+ GsubMultiple x(subtable(i));
+ if (x.apply(g, pos, n, s, true))
+ return true;
+ }
+ return false;
+ case L_LIGATURE:
+ for (int i = 0; i < nlookup; i++) {
+ GsubLigature x(subtable(i));
+ if (x.apply(g, pos, n, s))
+ return true;
+ }
+ return false;
+ default: // XXX
+ return false;
+ }
+}
+
+
+/**************************
+ * GsubSingle *
+ * *
+ **************************/
+
+GsubSingle::GsubSingle(const Data &d) throw (Error)
+ : _d(d)
+{
+ if (_d[0] != 0
+ || (_d[1] != 1 && _d[1] != 2))
+ throw Format("GSUB Single Substitution");
+ Coverage coverage(_d.offset_subtable(2));
+ if (!coverage.ok()
+ || (_d[1] == 2 && coverage.size() > _d.u16(4)))
+ throw Format("GSUB Single Substitution coverage");
+}
+
+Coverage
+GsubSingle::coverage() const throw ()
+{
+ return Coverage(_d.offset_subtable(2), 0, false);
+}
+
+Glyph
+GsubSingle::map(Glyph g) const
+{
+ int ci = coverage().coverage_index(g);
+ if (ci < 0)
+ return g;
+ else if (_d[1] == 1)
+ return g + _d.s16(4);
+ else
+ return _d.u16(HEADERSIZE + FORMAT2_RECSIZE*ci);
+}
+
+void
+GsubSingle::mark_out_glyphs(Vector<bool> &gmap) const
+{
+ if (_d[1] == 1) {
+ int delta = _d.s16(4);
+ for (Coverage::iterator i = coverage().begin(); i; i++)
+ gmap[*i + delta] = true;
+ } else {
+ for (Coverage::iterator i = coverage().begin(); i; i++)
+ gmap[_d.u16(HEADERSIZE + i.coverage_index()*FORMAT2_RECSIZE)] = true;
+ }
+}
+
+void
+GsubSingle::unparse(Vector<Substitution> &v, const Coverage &limit) const
+{
+ if (_d[1] == 1) {
+ int delta = _d.s16(4);
+ for (Coverage::iterator it = coverage().begin(); it; ++it)
+ if (limit.covers(*it))
+ v.push_back(Substitution(*it, *it + delta));
+ } else {
+ for (Coverage::iterator it = coverage().begin(); it; ++it)
+ if (limit.covers(*it))
+ v.push_back(Substitution(*it, _d.u16(HEADERSIZE + it.coverage_index()*FORMAT2_RECSIZE)));
+ }
+}
+
+bool
+GsubSingle::apply(const Glyph *g, int pos, int n, Substitution &s) const
+{
+ int ci;
+ if (pos < n && (ci = coverage().coverage_index(g[pos])) >= 0) {
+ if (_d[1] == 1)
+ s = Substitution(g[pos], g[pos] + _d.s16(4));
+ else
+ s = Substitution(g[pos], _d.u16(HEADERSIZE + ci*FORMAT2_RECSIZE));
+ return true;
+ } else
+ return false;
+}
+
+
+/**************************
+ * GsubMultiple *
+ * *
+ **************************/
+
+GsubMultiple::GsubMultiple(const Data &d) throw (Error)
+ : _d(d)
+{
+ if (_d[0] != 0 || _d[1] != 1)
+ throw Format("GSUB Multiple Substitution");
+ Coverage coverage(_d.offset_subtable(2));
+ if (!coverage.ok()
+ || coverage.size() > _d.u16(4))
+ throw Format("GSUB Multiple Substitution coverage");
+}
+
+Coverage
+GsubMultiple::coverage() const throw ()
+{
+ return Coverage(_d.offset_subtable(2), 0, false);
+}
+
+bool
+GsubMultiple::map(Glyph g, Vector<Glyph> &v) const
+{
+ v.clear();
+ int ci = coverage().coverage_index(g);
+ if (ci < 0) {
+ v.push_back(g);
+ return false;
+ } else {
+ Data seq = _d.offset_subtable(HEADERSIZE + ci*RECSIZE);
+ for (int i = 0; i < seq.u16(0); i++)
+ v.push_back(seq.u16(SEQ_HEADERSIZE + i*SEQ_RECSIZE));
+ return true;
+ }
+}
+
+void
+GsubMultiple::mark_out_glyphs(Vector<bool> &gmap) const
+{
+ for (Coverage::iterator i = coverage().begin(); i; ++i) {
+ Data seq = _d.offset_subtable(HEADERSIZE + i.coverage_index()*RECSIZE);
+ for (int j = 0; j < seq.u16(0); ++j)
+ gmap[seq.u16(SEQ_HEADERSIZE + j*SEQ_RECSIZE)] = true;
+ }
+}
+
+void
+GsubMultiple::unparse(Vector<Substitution> &v, bool is_alternate) const
+{
+ Vector<Glyph> result;
+ for (Coverage::iterator i = coverage().begin(); i; i++) {
+ Data seq = _d.offset_subtable(HEADERSIZE + i.coverage_index()*RECSIZE);
+ result.clear();
+ for (int j = 0; j < seq.u16(0); j++)
+ result.push_back(seq.u16(SEQ_HEADERSIZE + j*SEQ_RECSIZE));
+ v.push_back(Substitution(*i, result, is_alternate));
+ }
+}
+
+bool
+GsubMultiple::apply(const Glyph *g, int pos, int n, Substitution &s, bool is_alternate) const
+{
+ int ci;
+ if (pos < n && (ci = coverage().coverage_index(g[pos])) >= 0) {
+ Vector<Glyph> result;
+ Data seq = _d.offset_subtable(HEADERSIZE + ci*RECSIZE);
+ for (int j = 0; j < seq.u16(0); j++)
+ result.push_back(seq.u16(SEQ_HEADERSIZE + j*SEQ_RECSIZE));
+ s = Substitution(g[pos], result, is_alternate);
+ return true;
+ } else
+ return false;
+}
+
+
+/**************************
+ * GsubLigature *
+ * *
+ **************************/
+
+GsubLigature::GsubLigature(const Data &d) throw (Error)
+ : _d(d)
+{
+ if (_d[0] != 0
+ || _d[1] != 1)
+ throw Format("GSUB Ligature Substitution");
+ Coverage coverage(_d.offset_subtable(2));
+ if (!coverage.ok()
+ || coverage.size() > _d.u16(4))
+ throw Format("GSUB Ligature Substitution coverage");
+}
+
+Coverage
+GsubLigature::coverage() const throw ()
+{
+ return Coverage(_d.offset_subtable(2), 0, false);
+}
+
+bool
+GsubLigature::map(const Vector<Glyph> &gs, Glyph &result, int &consumed) const
+{
+ assert(gs.size() > 0);
+ result = gs[0];
+ consumed = 1;
+ int ci = coverage().coverage_index(gs[0]);
+ if (ci < 0)
+ return false;
+ Data ligset = _d.offset_subtable(HEADERSIZE + ci*RECSIZE);
+ int nligset = ligset.u16(0);
+ for (int i = 0; i < nligset; i++) {
+ Data lig = ligset.offset_subtable(SET_HEADERSIZE + i*SET_RECSIZE);
+ int nlig = lig.u16(2);
+ if (nlig > gs.size() - 1)
+ goto bad;
+ for (int j = 0; j < nlig - 1; j++)
+ if (lig.u16(LIG_HEADERSIZE + j*LIG_RECSIZE) != gs[j + 1])
+ goto bad;
+ result = lig.u16(0);
+ consumed = nlig + 1;
+ return true;
+ bad: ;
+ }
+ return false;
+}
+
+void
+GsubLigature::mark_out_glyphs(Vector<bool> &gmap) const
+{
+ for (Coverage::iterator i = coverage().begin(); i; i++) {
+ Data ligset = _d.offset_subtable(HEADERSIZE + i.coverage_index()*RECSIZE);
+ int nligset = ligset.u16(0);
+ Vector<Glyph> components(1, *i);
+ for (int j = 0; j < nligset; j++) {
+ Data lig = ligset.offset_subtable(SET_HEADERSIZE + j*SET_RECSIZE);
+ gmap[lig.u16(0)] = true;
+ }
+ }
+}
+
+void
+GsubLigature::unparse(Vector<Substitution> &v) const
+{
+ for (Coverage::iterator i = coverage().begin(); i; i++) {
+ Data ligset = _d.offset_subtable(HEADERSIZE + i.coverage_index()*RECSIZE);
+ int nligset = ligset.u16(0);
+ Vector<Glyph> components(1, *i);
+ for (int j = 0; j < nligset; j++) {
+ Data lig = ligset.offset_subtable(SET_HEADERSIZE + j*SET_RECSIZE);
+ int nlig = lig.u16(2);
+ components.resize(1);
+ for (int k = 0; k < nlig - 1; k++)
+ components.push_back(lig.u16(LIG_HEADERSIZE + k*LIG_RECSIZE));
+ v.push_back(Substitution(components, lig.u16(0)));
+ }
+ }
+}
+
+bool
+GsubLigature::apply(const Glyph *g, int pos, int n, Substitution &s) const
+{
+ int ci;
+ if (pos < n && (ci = coverage().coverage_index(g[pos])) >= 0) {
+ Data ligset = _d.offset_subtable(HEADERSIZE + ci*RECSIZE);
+ int nligset = ligset.u16(0);
+ for (int j = 0; j < nligset; j++) {
+ Data lig = ligset.offset_subtable(SET_HEADERSIZE + j*SET_RECSIZE);
+ int nlig = lig.u16(2);
+ if (pos + nlig <= n) {
+ for (int k = 0; k < nlig - 1; k++)
+ if (lig.u16(LIG_HEADERSIZE + k*LIG_RECSIZE) != g[pos + k + 1])
+ goto ligature_failed;
+ s = Substitution(nlig, &g[pos], lig.u16(0));
+ return true;
+ }
+ ligature_failed: ;
+ }
+ }
+ return false;
+}
+
+
+/**************************
+ * GsubContext *
+ * *
+ **************************/
+
+GsubContext::GsubContext(const Data &d) throw (Error)
+ : _d(d)
+{
+ switch (_d.u16(0)) {
+ case 1:
+ case 2:
+ break;
+ case 3: {
+ int ninput = _d.u16(2);
+ if (ninput < 1)
+ throw Format("GSUB Context Substitution input sequence");
+ Coverage coverage(_d.offset_subtable(F3_HSIZE));
+ if (!coverage.ok())
+ throw Format("GSUB Context Substitution coverage");
+ break;
+ }
+ default:
+ throw Format("GSUB Context Substitution");
+ }
+}
+
+Coverage
+GsubContext::coverage() const throw ()
+{
+ if (_d[1] == 3)
+ return Coverage(_d.offset_subtable(F3_HSIZE), 0, false);
+ else
+ return Coverage();
+}
+
+void
+GsubContext::f3_mark_out_glyphs(const Data &data, int nsub, int subtab_offset, const Gsub &gsub, Vector<bool> &gmap)
+{
+ for (int j = 0; j < nsub; ++j) {
+ int lookup_index = data.u16(subtab_offset + SUBRECSIZE*j + 2);
+ gsub.lookup(lookup_index).mark_out_glyphs(gsub, gmap);
+ }
+}
+
+void
+GsubContext::mark_out_glyphs(const Gsub &gsub, Vector<bool> &gmap) const
+{
+ if (_d.u16(0) != 3) // XXX
+ return;
+ int nglyph = _d.u16(2);
+ int nsubst = _d.u16(4);
+ f3_mark_out_glyphs(_d, nsubst, F3_HSIZE + nglyph*2, gsub, gmap);
+}
+
+bool
+GsubContext::f3_unparse(const Data &data,
+ int nglyph, int glyphtab_offset, const Coverage &limit,
+ int nsub, int subtab_offset,
+ const Gsub &gsub, Vector<Substitution> &outsubs,
+ const Substitution &prototype_sub)
+{
+ Vector<Substitution> subs;
+ subs.push_back(prototype_sub);
+ Vector<Substitution> work_subs;
+
+ // get array of possible substitutions including contexts
+ for (int i = 0; i < nglyph; i++) {
+ assert(!work_subs.size());
+ Coverage c(data.offset_subtable(glyphtab_offset + i*2));
+ for (Coverage::iterator ci = (c & limit).begin(); ci; ci++)
+ for (int j = 0; j < subs.size(); j++)
+ work_subs.push_back(subs[j].in_out_append_glyph(*ci));
+ subs.clear();
+ subs.swap(work_subs);
+ }
+
+ // now, apply referred lookups to the resulting substitution array
+ Vector<Glyph> in_glyphs;
+ Vector<int> pos_map;
+ Substitution subtab_sub;
+ for (int i = 0; i < subs.size(); i++) {
+ Substitution &s = subs[i];
+ int napplied = 0;
+ for (int j = 0; j < nsub; j++) {
+ int seq_index = data.u16(subtab_offset + SUBRECSIZE*j);
+ int lookup_index = data.u16(subtab_offset + SUBRECSIZE*j + 2);
+ // XXX check seq_index against size of output glyphs?
+ if (gsub.lookup(lookup_index).apply(s.out_glyphptr(), seq_index, s.out_nglyphs(), subtab_sub)) {
+ napplied++;
+ s.out_alter(subtab_sub, seq_index);
+ }
+ }
+ // 26.Jun.2003 -- always push substitution back, since the no-op might
+ // override a following substitution
+ outsubs.push_back(s);
+ }
+
+ return true; // XXX
+}
+
+bool
+GsubContext::unparse(const Gsub &gsub, Vector<Substitution> &v, const Coverage &limit) const
+{
+ if (_d.u16(0) != 3) // XXX
+ return false;
+ int nglyph = _d.u16(2);
+ int nsubst = _d.u16(4);
+ return f3_unparse(_d, nglyph, F3_HSIZE, limit, nsubst, F3_HSIZE + nglyph*2, gsub, v, Substitution());
+}
+
+
+/**************************
+ * GsubChainContext *
+ * *
+ **************************/
+
+GsubChainContext::GsubChainContext(const Data &d) throw (Error)
+ : _d(d)
+{
+ switch (_d.u16(0)) {
+ case 1:
+ case 2:
+ break;
+ case 3: {
+ int nbacktrack = _d.u16(2);
+ int input_offset = F3_HSIZE + nbacktrack*2;
+ int ninput = _d.u16(input_offset);
+ if (ninput < 1)
+ throw Format("GSUB ChainContext Substitution input sequence");
+ Coverage coverage(_d.offset_subtable(input_offset + F3_INPUT_HSIZE));
+ if (!coverage.ok())
+ throw Format("GSUB ChainContext Substitution coverage");
+ break;
+ }
+ default:
+ throw Format("GSUB ChainContext Substitution");
+ }
+}
+
+Coverage
+GsubChainContext::coverage() const throw ()
+{
+ if (_d.u16(0) != 3)
+ return Coverage();
+ int nbacktrack = _d.u16(2);
+ int input_offset = F3_HSIZE + nbacktrack*2;
+ return Coverage(_d.offset_subtable(input_offset + F3_INPUT_HSIZE), 0, false);
+}
+
+void
+GsubChainContext::mark_out_glyphs(const Gsub &gsub, Vector<bool> &gmap) const
+{
+ if (_d.u16(0) != 3)
+ return;
+
+ int nbacktrack = _d.u16(2);
+ int input_offset = F3_HSIZE + nbacktrack*2;
+ int ninput = _d.u16(input_offset);
+ int lookahead_offset = input_offset + F3_INPUT_HSIZE + ninput*2;
+ int nlookahead = _d.u16(lookahead_offset);
+ int subst_offset = lookahead_offset + F3_LOOKAHEAD_HSIZE + nlookahead*2;
+ int nsubst = _d.u16(subst_offset);
+
+ GsubContext::f3_mark_out_glyphs(_d, nsubst, subst_offset + F3_SUBST_HSIZE, gsub, gmap);
+}
+
+bool
+GsubChainContext::unparse(const Gsub &gsub, Vector<Substitution> &v, const Coverage &limit) const
+{
+ if (_d.u16(0) != 3)
+ return false;
+
+ int nbacktrack = _d.u16(2);
+ int input_offset = F3_HSIZE + nbacktrack*2;
+ int ninput = _d.u16(input_offset);
+ int lookahead_offset = input_offset + F3_INPUT_HSIZE + ninput*2;
+ int nlookahead = _d.u16(lookahead_offset);
+ int subst_offset = lookahead_offset + F3_LOOKAHEAD_HSIZE + nlookahead*2;
+ int nsubst = _d.u16(subst_offset);
+
+ Vector<Coverage> backtrackc;
+ Vector<Coverage> lookaheadc;
+ if (gsub.chaincontext_reverse_backtrack()) {
+ for (int i = 0; i < nbacktrack; i++)
+ backtrackc.push_back(Coverage(_d.offset_subtable(F3_HSIZE + i*2)) & limit);
+ } else {
+ for (int i = nbacktrack - 1; i >= 0; i--)
+ backtrackc.push_back(Coverage(_d.offset_subtable(F3_HSIZE + i*2)) & limit);
+ }
+ for (int i = 0; i < nlookahead; i++)
+ lookaheadc.push_back(Coverage(_d.offset_subtable(lookahead_offset + F3_LOOKAHEAD_HSIZE + i*2)) & limit);
+
+ // give up if would generate too many substitutions
+ double n = 1;
+ for (int i = 0; i < nbacktrack; ++i)
+ n *= backtrackc[i].size();
+ for (int i = 0; i < nlookahead; ++i)
+ n *= lookaheadc[i].size();
+ for (int i = 0; i < ninput; ++i)
+ n *= (Coverage(_d.offset_subtable(input_offset + F3_INPUT_HSIZE + i*2)) & limit).size();
+ if (n > 1000000) // arbitrary cutoff
+ return false;
+
+ Vector<Coverage::iterator> backtracki;
+ Vector<Coverage::iterator> lookaheadi;
+ for (int i = 0; i < nbacktrack; i++)
+ backtracki.push_back(backtrackc[i].begin());
+ for (int i = 0; i < nlookahead; i++)
+ lookaheadi.push_back(lookaheadc[i].begin());
+
+ bool any = false;
+
+ while (1) {
+
+ // run GsubContext
+ Substitution s(nbacktrack, 0, 0, nlookahead);
+ Glyph *left_begin = s.left_glyphptr();
+ for (int i = 0; i < nbacktrack; i++)
+ left_begin[i] = *backtracki[i];
+ Glyph *right_begin = s.right_glyphptr();
+ for (int i = 0; i < nlookahead; i++)
+ right_begin[i] = *lookaheadi[i];
+
+ any |= GsubContext::f3_unparse(_d, ninput, input_offset + F3_INPUT_HSIZE, limit, nsubst, subst_offset + F3_SUBST_HSIZE, gsub, v, s);
+
+ // step iterators
+ for (int i = nlookahead - 1; i >= 0; i--) {
+ lookaheadi[i]++;
+ if (lookaheadi[i])
+ goto next;
+ lookaheadi[i] = lookaheadc[i].begin();
+ }
+ for (int i = nbacktrack - 1; i >= 0; i--) {
+ backtracki[i]++;
+ if (backtracki[i])
+ goto next;
+ backtracki[i] = backtrackc[i].begin();
+ }
+ break;
+
+ next: ;
+ }
+
+ return any;
+}
+
+
+}}
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/otfname.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/otfname.cc
new file mode 100644
index 00000000000..642b41fb845
--- /dev/null
+++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/otfname.cc
@@ -0,0 +1,194 @@
+// -*- related-file-name: "../include/efont/otfname.hh" -*-
+
+/* otfname.{cc,hh} -- OpenType name table
+ *
+ * Copyright (c) 2003-2012 Eddie Kohler
+ *
+ * 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 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <efont/otfname.hh>
+#include <lcdf/error.hh>
+#include <lcdf/straccum.hh>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <algorithm>
+
+#define USHORT_AT(d) (ntohs(*(const uint16_t *)(d)))
+
+namespace Efont { namespace OpenType {
+
+static const uint16_t mac_roman_encoding[] = {
+ // 0x80-0x8F
+ 0x00C4, 0x00C5, 0x00C7, 0x00C9, // Adieresis Aring Ccedilla Eacute
+ 0x00D1, 0x00D6, 0x00DC, 0x00E1, // Ntilde Odieresis Udieresis aacute
+ 0x00E0, 0x00E2, 0x00E4, 0x00E3, // agrave acircumflex adieresis atilde
+ 0x00E5, 0x00E7, 0x00E9, 0x00E8, // aring ccedilla eacute egrave
+ // 0x90-0x9F
+ 0x00EA, 0x00EB, 0x00ED, 0x00EC, // ecircumflex edieresis iacute igrave
+ 0x00EE, 0x00EF, 0x00F1, 0x00F3, // icircumflex idieresis ntilde oacute
+ 0x00F2, 0x00F4, 0x00F6, 0x00F5, // ograve ocircumflex odieresis otilde
+ 0x00FA, 0x00F9, 0x00FB, 0x00FC, // uacute ugrave ucircumflex udieresis
+ // 0xA0-0xAF
+ 0x2020, 0x00B0, 0x00A2, 0x00A3, // dagger degree cent sterling
+ 0x00A7, 0x2022, 0x00B6, 0x00DF, // section bullet paragraph germandbls
+ 0x00AE, 0x00A9, 0x2122, 0x00B4, // registered copyright trademark acute
+ 0x00A8, 0x2260, 0x00C6, 0x00D8, // dieresis notequal AE Oslash
+ // 0xB0-0xBF
+ 0x221E, 0x00B1, 0x2264, 0x2265, // infinity plusminus lessequal greaterequal
+ 0x00A5, 0x00B5, 0x2202, 0x2211, // yen mu partialdiff summation
+ 0x220F, 0x03C0, 0x222B, 0x00AA, // product pi integral ordfeminine
+ 0x00BA, 0x03A9, 0x00E6, 0x00F8, // ordmasculine Omegagreek ae oslash
+ // 0xC0-0xCF
+ 0x00BF, 0x00A1, 0x00AC, 0x221A, // questiondown exclamdown logicalnot radical
+ 0x0192, 0x2248, 0x2206, 0x00AB, // florin approxequal increment guillemotleft
+ 0x00BB, 0x2026, 0x00A0, 0x00C0, // guillemotright ellipsis nbspace Agrave
+ 0x00C3, 0x00D5, 0x0152, 0x0153, // Atilde Otilde OE oe
+ // 0xD0-0xDF
+ 0x2013, 0x2014, 0x201C, 0x201D, // endash emdash quotedblleft quotedblright
+ 0x2018, 0x2019, 0x00F7, 0x25CA, // quoteleft quoteright divide lozenge
+ 0x00FF, 0x0178, 0x2044, 0x20AC, // ydieresis Ydieresis fraction Euro
+ 0x2039, 0x203A, 0xFB01, 0xFB02, // guilsinglleft guilsinglright fi fl
+ // 0xE0-0xEF
+ 0x2021, 0x00B7, 0x201A, 0x201E, // daggerdbl middot quotesinglbase quotedblbase
+ 0x2030, 0x00C2, 0x00CA, 0x00C1, // perthousand Acircumflex Ecircumflex Aacute
+ 0x00CB, 0x00C8, 0x00CD, 0x00CE, // Edieresis Egrave Iacute Icircumflex
+ 0x00CF, 0x00CC, 0x00D3, 0x00D4, // Idieresis Igrave Oacute Ocircumflex
+ // 0xF0-0xFF
+ 0xF8FF, 0x00D2, 0x00DA, 0x00DB, // apple Ograve Uacute Ucircumflex
+ 0x00D9, 0x0131, 0x02C6, 0x02DC, // Ugrave dotlessi circumflex tilde
+ 0x00AF, 0x02D8, 0x02D9, 0x02DA, // macron breve dotaccent ring
+ 0x00B8, 0x02DD, 0x02DB, 0x02C7 // cedilla hungarumlaut ogonek caron
+};
+
+
+Name::Name(const String &s, ErrorHandler *errh)
+ : _str(s)
+{
+ _str.align(2);
+ _error = parse_header(errh ? errh : ErrorHandler::silent_handler());
+}
+
+int
+Name::parse_header(ErrorHandler *errh)
+{
+ // HEADER FORMAT:
+ // USHORT version
+ // USHORT numTables
+ int len = _str.length();
+ const uint8_t *data = _str.udata();
+ if (len == 0)
+ return errh->error("font has no %<name%> table"), -EFAULT;
+ if (HEADER_SIZE > len)
+ return errh->error("%<name%> table too small"), -EFAULT;
+ if (!(data[0] == '\000' && data[1] == '\000'))
+ return errh->error("bad %<name%> version number"), -ERANGE;
+ int count = USHORT_AT(data + 2);
+ if (HEADER_SIZE + count*NAMEREC_SIZE > len)
+ return errh->error("%<name%> table too small"), -EFAULT;
+ return 0;
+}
+
+String
+Name::name(const_iterator i) const
+{
+ if (i < end()) {
+ int stringOffset = USHORT_AT(_str.data() + 4);
+ int length = USHORT_AT(reinterpret_cast<const uint8_t *>(i) + 8);
+ int offset = USHORT_AT(reinterpret_cast<const uint8_t *>(i) + 10);
+ if (stringOffset + offset + length <= _str.length())
+ return _str.substring(stringOffset + offset, length);
+ }
+ return String();
+}
+
+String
+Name::utf8_name(const_iterator i) const
+{
+ // This code can handle Microsoft Unicode BMP and Mac Roman encodings,
+ // but that's it
+ if (!(i < end()))
+ return String();
+ int stringOffset = USHORT_AT(_str.data() + 4);
+ int length = USHORT_AT(reinterpret_cast<const uint8_t *>(i) + 8);
+ int offset = USHORT_AT(reinterpret_cast<const uint8_t *>(i) + 10);
+ if (stringOffset + offset + length > _str.length())
+ return String();
+ const char *begins = _str.data() + stringOffset + offset;
+ const char *ends = begins + length;
+ if (platform(*i) == P_MICROSOFT && encoding(*i) == E_MS_UNICODE_BMP) {
+ StringAccum sa;
+ for (const char *s = begins; s + 1 < ends; s += 2)
+ sa.append_utf8(USHORT_AT(s));
+ return sa.take_string();
+ } else if (platform(*i) == P_MACINTOSH && encoding(*i) == E_MAC_ROMAN) {
+ StringAccum sa;
+ for (const char *s = begins; s < ends; s++)
+ if ((unsigned char) *s >= 0x80) {
+ sa.append(begins, s);
+ sa.append_utf8(mac_roman_encoding[*s & 0x7F]);
+ begins = s + 1;
+ }
+ if (!sa)
+ return _str.substring(begins, ends);
+ else {
+ sa.append(begins, ends);
+ return sa.take_string();
+ }
+ } else
+ return _str.substring(begins, ends);
+}
+
+String
+Name::english_name(int nameid) const
+{
+ const_iterator end = this->end();
+ const_iterator it = std::find_if(begin(), end, PlatformPred(nameid, P_MICROSOFT, E_MS_UNICODE_BMP, L_MS_ENGLISH_AMERICAN));
+ if (it == end)
+ it = std::find_if(begin(), end, PlatformPred(nameid, P_MACINTOSH, E_MAC_ROMAN, 0));
+ return utf8_name(it);
+}
+
+bool
+Name::version_chaincontext_reverse_backtrack() const
+{
+ String vstr = name(std::find_if(begin(), end(), PlatformPred(N_VERSION, 1, 0, 0)));
+ const char *v = vstr.begin(), *endv = vstr.end();
+ if (v + 20 <= endv) {
+ if (v[0] != 'O' || v[1] != 'T' || v[2] != 'F' || v[3] == ';')
+ goto try_core;
+ for (v += 4; v < endv && *v != ';'; v++)
+ /* do nothing */;
+ if (v + 3 >= endv || v[1] != 'P' || v[2] != 'S' || v[3] == ';')
+ goto try_core;
+ for (v += 4; v < endv && *v != ';'; v++)
+ /* do nothing */;
+ if (v + 11 >= endv || memcmp(v + 1, "Core 1.0.", 9) != 0
+ || (v[10] != '2' && v[10] != '3')
+ || (v[11] < '0' || v[11] > '9'))
+ goto try_core;
+ return true;
+ }
+ try_core:
+ v = vstr.begin();
+ if (v + 16 > endv
+ || v[0] != 'C' || v[1] != 'o' || v[2] != 'r' || v[3] != 'e')
+ return false;
+ for (v += 4; v < endv && *v != ';'; v++)
+ /* do nothing */;
+ if (v + 12 > endv || memcmp(v, ";makeotf.lib", 12) != 0)
+ return false;
+ return true;
+}
+
+}}
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/otfos2.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/otfos2.cc
new file mode 100644
index 00000000000..9831fb49543
--- /dev/null
+++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/otfos2.cc
@@ -0,0 +1,47 @@
+// -*- related-file-name: "../include/efont/otfos2.hh" -*-
+
+/* otfos2.{cc,hh} -- OpenType OS/2 table
+ *
+ * Copyright (c) 2005-2012 Eddie Kohler
+ *
+ * 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 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <efont/otfos2.hh>
+#include <lcdf/error.hh>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+namespace Efont { namespace OpenType {
+
+Os2::Os2(const Data &data, ErrorHandler *errh)
+ : _data(data)
+{
+ _error = parse_header(errh ? errh : ErrorHandler::silent_handler());
+ if (_error < 0)
+ _data = Data();
+}
+
+int
+Os2::parse_header(ErrorHandler *errh)
+{
+ // HEADER FORMAT:
+ // USHORT version
+ if (HEADER_SIZE > _data.length())
+ return errh->error("OTF OS/2 too small for header"), -EFAULT;
+ if (_data.u16(0) > 4)
+ return errh->error("unexpected OS/2 version number %d", _data.u16(0)), -ERANGE;
+ return 0;
+}
+
+}}
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/otfpost.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/otfpost.cc
new file mode 100644
index 00000000000..b514f234f4b
--- /dev/null
+++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/otfpost.cc
@@ -0,0 +1,212 @@
+// -*- related-file-name: "../include/efont/otfpost.hh" -*-
+
+/* otfpost.{cc,hh} -- OpenType post table
+ *
+ * Copyright (c) 2006-2012 Eddie Kohler
+ *
+ * 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 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <efont/otfpost.hh>
+#include <lcdf/error.hh>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <efont/otfdata.hh> // for ntohl()
+
+#define USHORT_AT(d) (ntohs(*(const uint16_t *)(d)))
+#define SHORT_AT(d) ((int16_t) ntohs(*(const uint16_t *)(d)))
+#define ULONG_AT(d) (ntohl(*(const uint32_t *)(d)))
+#define LONG_AT(d) ((int32_t) ntohl(*(const uint32_t *)(d)))
+
+namespace Efont { namespace OpenType {
+
+static const char * const mac_names[] = {
+ ".notdef", ".null", "nonmarkingreturn", "space", // 0-3
+ "exclam", "quotedbl", "numbersign", "dollar", // 4-7
+ "percent", "ampersand", "quotesingle", "parenleft", // 8-11
+ "parenright", "asterisk", "plus", "comma", // 12-15
+ "hyphen", "period", "slash", "zero", // 16-19
+ "one", "two", "three", "four", // 20-23
+ "five", "six", "seven", "eight", // 24-27
+ "nine", "colon", "semicolon", "less", // 28-31
+ "equal", "greater", "question", "at", // 32-35
+ "A", "B", "C", "D", // 36-39
+ "E", "F", "G", "H", // 40-43
+ "I", "J", "K", "L", // 44-47
+ "M", "N", "O", "P", // 48-51
+ "Q", "R", "S", "T", // 52-55
+ "U", "V", "W", "X", // 56-59
+ "Y", "Z", "bracketleft", "backslash", // 60-63
+ "bracketright", "asciicircum", "underscore", "grave", // 64-67
+ "a", "b", "c", "d", // 68-71
+ "e", "f", "g", "h", // 72-75
+ "i", "j", "k", "l", // 76-79
+ "m", "n", "o", "p", // 80-83
+ "q", "r", "s", "t", // 84-87
+ "u", "v", "w", "x", // 88-91
+ "y", "z", "braceleft", "bar", // 92-95
+ "braceright", "asciitilde", "Adieresis", "Aring", // 96-99
+ "Ccedilla", "Eacute", "Ntilde", "Odieresis", // 100-103
+ "Udieresis", "aacute", "agrave", "acircumflex", // 104-107
+ "adieresis", "atilde", "aring", "ccedilla", // 108-111
+ "eacute", "egrave", "ecircumflex", "edieresis", // 112-115
+ "iacute", "igrave", "icircumflex", "idieresis", // 116-119
+ "ntilde", "oacute", "ograve", "ocircumflex", // 120-123
+ "odieresis", "otilde", "uacute", "ugrave", // 124-127
+ "ucircumflex", "udieresis", "dagger", "degree", // 128-131
+ "cent", "sterling", "section", "bullet", // 132-135
+ "paragraph", "germandbls", "registered", "copyright", // 136-139
+ "trademark", "acute", "dieresis", "notequal", // 140-143
+ "AE", "Oslash", "infinity", "plusminus", // 144-147
+ "lessequal", "greaterequal", "yen", "mu", // 148-151
+ "partialdiff", "summation", "product", "pi", // 152-155
+ "integral", "ordfeminine", "ordmasculine", "Omega", // 156-159
+ "ae", "oslash", "questiondown", "exclamdown", // 160-163
+ "logicalnot", "radical", "florin", "approxequal", // 164-167
+ "Delta", "guillemotleft", "guillemotright", "ellipsis", // 168-171
+ "nonbreakingspace", "Agrave", "Atilde", "Otilde", // 172-175
+ "OE", "oe", "endash", "emdash", // 176-179
+ "quotedblleft", "quotedblright", "quoteleft", "quoteright", // 180-183
+ "divide", "lozenge", "ydieresis", "Ydieresis", // 184-187
+ "fraction", "currency", "guilsinglleft", "guilsinglright", // 188-191
+ "fi", "fl", "daggerdbl", "periodcentered", // 192-195
+ "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex", // 196-199
+ "Ecircumflex", "Aacute", "Edieresis", "Egrave", // 200-203
+ "Iacute", "Icircumflex", "Idieresis", "Igrave", // 204-207
+ "Oacute", "Ocircumflex", "apple", "Ograve", // 208-211
+ "Uacute", "Ucircumflex", "Ugrave", "dotlessi", // 212-215
+ "circumflex", "tilde", "macron", "breve", // 216-219
+ "dotaccent", "ring", "cedilla", "hungarumlaut", // 220-223
+ "ogonek", "caron", "Lslash", "lslash", // 224-227
+ "Scaron", "scaron", "Zcaron", "zcaron", // 228-231
+ "brokenbar", "Eth", "eth", "Yacute", // 232-235
+ "yacute", "Thorn", "thorn", "minus", // 236-239
+ "multiply", "onesuperior", "twosuperior", "threesuperior", // 240-243
+ "onehalf", "onequarter", "threequarters", "franc", // 244-247
+ "Gbreve", "gbreve", "Idotaccent", "Scedilla", // 248-251
+ "scedilla", "Cacute", "cacute", "Ccaron", // 252-255
+ "ccaron", "dcroat" // 256-257
+};
+
+
+Post::Post(const String &s, ErrorHandler *errh)
+ : _str(s), _version(0)
+{
+ _str.align_long();
+ _error = parse_header(errh ? errh : ErrorHandler::silent_handler());
+}
+
+int
+Post::parse_header(ErrorHandler *errh)
+{
+ // HEADER FORMAT:
+ // 0 FIXED version
+ // 4 FIXED italicAngle
+ // 8 FWORD underlinePosition
+ // 10 FWORD underlineThickness
+ // 12 ULONG isFixedPitch
+ // 16 ULONG minMemType42
+ // 20 ULONG maxMemType42
+ // 24 ULONG minMemType1
+ // 28 ULONG maxMemType1
+ int len = _str.length();
+ const uint8_t *data = _str.udata();
+ if (HEADER_SIZE > len)
+ return errh->error("OTF post too small for header"), -EFAULT;
+ _version = USHORT_AT(data); // ignore minor version number
+ // except that version 2.5 isn't compatible
+ if (_version < 1 || _version > 3
+ || (_version == 2 && USHORT_AT(data + 2) == 0x5000))
+ return errh->error("bad post version number"), -ERANGE;
+ if (_version == 2) {
+ // VERSION 2.0 GLYPH NAMES FORMAT:
+ // 32 USHORT numberOfGlyphs
+ // 34 USHORT glyphNameIndex[mumberOfGlyphs]
+ // CHAR names[...]
+ if (HEADER_SIZE + 2 > len
+ || ((_nglyphs = USHORT_AT(data + HEADER_SIZE)),
+ HEADER_SIZE + 2 + 2 * _nglyphs > len))
+ return errh->error("OTF post too small for glyph map"), -EFAULT;
+ const uint8_t *gni = data + HEADER_SIZE + 2;
+ const uint8_t *names = gni + 2 * _nglyphs;
+ int next_name = N_MAC_GLYPHS, g;
+ bool gni_error_reported = false;
+ for (int i = 0; i < _nglyphs; i++, gni += 2)
+ // Some fonts have more than 32768 glyphs. Although the 'post'
+ // spec says name indexes 32768-65535 are reserved, some large
+ // fonts treat those indexes as valid.
+ if ((g = USHORT_AT(gni)) >= 32768 && g >= _nglyphs) {
+ if (!gni_error_reported)
+ errh->error("bad glyph name index in post");
+ gni_error_reported = true;
+ } else
+ while (g >= next_name) {
+ if (names - data > len
+ || (names + 1 + names[0]) - data > len)
+ return errh->error("OTF post too small for glyph names"), -EFAULT;
+ _extend_glyph_names.push_back(names - data);
+ names += 1 + names[0];
+ next_name++;
+ }
+ } else if (_version == 1)
+ _nglyphs = N_MAC_GLYPHS;
+ else
+ _nglyphs = -1;
+
+ return 0;
+}
+
+double
+Post::italic_angle() const
+{
+ if (error() < 0)
+ return -1;
+ return (double) LONG_AT(_str.udata() + 4) / 65536.;
+}
+
+bool
+Post::is_fixed_pitch() const
+{
+ if (error() < 0)
+ return false;
+ return ULONG_AT(_str.udata() + 12) != 0;
+}
+
+bool
+Post::glyph_names(Vector<PermString> &gnames) const
+{
+ gnames.clear();
+ if (error() < 0)
+ return false;
+ if (_version == 1) {
+ for (int i = 0; i < N_MAC_GLYPHS; i++)
+ gnames.push_back(mac_names[i]);
+ return true;
+ } else if (_version == 2) {
+ const uint8_t *data = _str.udata();
+ const uint8_t *gni = data + HEADER_SIZE + 2;
+ for (int i = 0; i < _nglyphs; i++, gni += 2) {
+ int g = USHORT_AT(gni);
+ if (g < N_MAC_GLYPHS)
+ gnames.push_back(mac_names[g]);
+ else {
+ const uint8_t *n = data + _extend_glyph_names[g - N_MAC_GLYPHS];
+ gnames.push_back(PermString((const char *) n + 1, *n));
+ }
+ }
+ return true;
+ } else
+ return false;
+}
+
+}}
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/pairop.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/pairop.cc
new file mode 100644
index 00000000000..5b64be1ac41
--- /dev/null
+++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/pairop.cc
@@ -0,0 +1,153 @@
+// -*- related-file-name: "../include/efont/pairop.hh" -*-
+
+/* pairop.{cc,hh} -- ligature/kern font metrics
+ *
+ * Copyright (c) 1998-2012 Eddie Kohler
+ *
+ * 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 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <efont/pairop.hh>
+#include <stdio.h>
+namespace Efont {
+
+PairProgram::PairProgram(const PairProgram &o)
+ : _reversed(o._reversed),
+ _left_map(o._left_map),
+ _op(o._op)
+{
+}
+
+
+void
+PairProgram::reserve_glyphs(int e)
+{
+ if (e <= _left_map.size()) return;
+ _left_map.resize(e, -1);
+}
+
+
+PairOpIndex
+PairProgram::find(GlyphIndex leftgi, GlyphIndex rightgi) const
+{
+ PairOpIndex opi = find_left(leftgi);
+ while (opi >= 0) {
+ if (op(opi).right() == rightgi)
+ return opi;
+ opi = op(opi).next_left();
+ }
+ return -1;
+}
+
+
+bool
+PairProgram::add_kern(GlyphIndex left, GlyphIndex right, int ki)
+{
+ PairOp newop(left, right, ki, _left_map[left]);
+ int newopi = _op.size();
+ _op.push_back(newop);
+ _left_map[left] = newopi;
+
+ //PairOpIndex duplicate = map[newop];
+ //map.add(newop, newopi);
+
+ return false;
+}
+
+
+bool
+PairProgram::add_lig(GlyphIndex left, GlyphIndex right, GlyphIndex result,
+ int kind)
+{
+ PairOp newop(left, right, result, kind, _left_map[left]);
+ int newopi = _op.size();
+ _op.push_back(newop);
+ _left_map[left] = newopi;
+
+ //PairOpIndex duplicate = map[newop];
+ //map.add(newop, newopi);
+
+ return false;
+}
+
+
+void
+PairProgram::unreverse()
+{
+ if (!_reversed) return;
+
+ _left_map.assign(_left_map.size(), -1);
+
+ for (PairOpIndex opi = _op.size() - 1; opi >= 0; opi--) {
+ PairOp &o = _op[opi];
+ PairOpIndex l = o.left();
+ o.set_next(_left_map[l]);
+ _left_map[l] = opi;
+ }
+
+ _reversed = false;
+}
+
+
+void
+PairProgram::optimize()
+{
+ /* PairOpIndex opi;
+
+ // Get rid of 0-valued kerns.
+ for (opi = 0; opi < opcount(); opi++) {
+ PairOp &o = op(opi);
+ if (o.is_kern() && o.value() == 0)
+ o.noopify();
+ }*/
+}
+
+
+inline const char *
+PairProgram::print_name(GlyphIndex) const
+{
+#if 0
+ if (gi == opAnychar) return "*";
+ else return glyph(gi).name();
+#endif
+ return 0;
+}
+
+
+void
+PairProgram::print() const
+{
+#if 0
+ for (GlyphIndex gi = 0; gi < glyphblock.size(); gi++)
+ if (glyphblock[gi] != -1)
+ printf("%s->B%d ", glyph(gi).name().c_str(), glyphblock[gi]);
+ printf("\n");
+
+ for (int i = 0; i < blocks.size(); i++) {
+ printf("B%-2d: ", i);
+ PairOpBlock &opb = *blocks[i];
+ for (int j = 0; j < opb.size(); j++)
+ if (opb[j].is_lig())
+ printf("%s->%s ", printname(opb[j].right()),
+ printname(opb[j].result()));
+ else if (opb[j].is_kern())
+ printf("%s[%g] ", printname(opb[j].right()), kern(opb[j].value()));
+ else if (opb[j].is_noop())
+ printf(". ");
+ if (blocks[i]->nextblock != -1)
+ printf(" :B%d", blocks[i]->nextblock);
+ printf("\n");
+ }
+#endif
+}
+
+}
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/psres.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/psres.cc
new file mode 100644
index 00000000000..2136a6b3237
--- /dev/null
+++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/psres.cc
@@ -0,0 +1,419 @@
+// -*- related-file-name: "../include/efont/psres.hh" -*-
+
+/* psres.{cc,hh} -- PSres.upr files
+ *
+ * Copyright (c) 1999-2012 Eddie Kohler
+ *
+ * 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 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <efont/psres.hh>
+#include <lcdf/slurper.hh>
+/* Get the correct functions for directory searching */
+#if HAVE_DIRENT_H
+# include <dirent.h>
+# define DIR_NAMLEN(dirent) strlen((dirent)->d_name)
+#else
+# define dirent direct
+# define DIR_NAMLEN(dirent) (dirent)->d_namlen
+# if HAVE_SYS_NDIR_H
+# include <sys/ndir.h>
+# endif
+# if HAVE_SYS_DIR_H
+# include <sys/dir.h>
+# endif
+# if HAVE_NDIR_H
+# include <ndir.h>
+# endif
+#endif
+#include <string.h>
+namespace Efont {
+
+PsresDatabase::PsresDatabase()
+ : _section_map(0)
+{
+ _sections.push_back((PsresDatabaseSection *)0);
+}
+
+PsresDatabase::~PsresDatabase()
+{
+ for (int i = 1; i < _sections.size(); i++)
+ delete _sections[i];
+}
+
+
+PsresDatabaseSection::PsresDatabaseSection(PermString section_name)
+ : _section_name(section_name), _map(0)
+{
+ _directories.push_back(PermString());
+ _values.push_back(String());
+ _value_escaped.push_back(true);
+}
+
+
+/* read_ps_line - gathers a line in `slurper', returns true if it is a normal
+ line, false on end of file or a separator line (starts with `.'). Handles
+ continuation lines but not backslash escaping. Stores location of first
+ non-backslashed equals sign in `*equals_pos', or -1 if none. */
+
+static bool
+read_psres_line(Slurper &slurper, int *equals_pos)
+{
+ if (equals_pos) *equals_pos = -1;
+
+ char *s = slurper.next_line();
+ if (!s) return false;
+
+ bool is_terminator = s[0] == '.';
+ unsigned len, pos = 0, last_escape = ~0;
+ bool found_eq = false;
+
+ while (true) {
+ len = slurper.cur_line_length();
+ if (len == 0) break;
+
+ // process backslash escapes
+ for (; pos < len - 1; pos++) {
+ if (s[pos] == '\\') {
+ // quote the next character
+ pos++;
+ last_escape = pos;
+ } else if (!found_eq && s[pos] == '=') {
+ // an equals sign: store its position
+ if (equals_pos) *equals_pos = pos;
+ found_eq = true;
+ } else if (s[pos] == '%') {
+ // unescaped '%' is a comment; return immediately after shortening line
+ len = pos;
+ goto done;
+ }
+ }
+
+ // stop processing if not a continuation line
+ if (pos == len || s[pos] != '\\') break;
+
+ slurper.shorten_line(pos);
+ s = slurper.append_next_line();
+ }
+
+ if (pos < len && !found_eq && s[pos] == '=' && equals_pos)
+ *equals_pos = pos;
+
+ done:
+ // eat trailing whitespace, except for the space in `\ ' if it ends the line
+ // -- unless the `\' is the second `\' in a `\\'!
+ for (pos = len; pos > 0 && (s[pos-1] == ' ' || s[pos-1] == '\t'); pos--)
+ /* nada */;
+ if (pos == last_escape)
+ pos++;
+ slurper.shorten_line(pos);
+ return !is_terminator;
+}
+
+/* psres_escape: backslash escaping */
+
+static unsigned
+psres_escape(char *s, unsigned len)
+{
+ unsigned pos = 0, delta = 0;
+ while (pos < len) {
+ if (s[pos] == '\\') pos++, delta++;
+ if (delta) s[pos-delta] = s[pos];
+ pos++;
+ }
+ s[pos-delta] = 0;
+ return len-delta;
+}
+
+void
+PsresDatabaseSection::add_psres_file_section
+ (Slurper &slurper, PermString directory, bool override)
+{
+ int equals_pos;
+ bool first_line = true;
+
+ while (read_psres_line(slurper, &equals_pos)) {
+ char *s = slurper.cur_line();
+
+ // check for a directory line
+ if (first_line) {
+ first_line = false;
+ if (s[0] == '/') {
+ psres_escape(s + 1, slurper.cur_line_length() - 1);
+ directory = PermString(s + 1);
+ continue;
+ }
+ }
+
+ if (equals_pos < 0) {
+ // report error?
+ continue;
+ }
+
+ // get the key
+ unsigned len = psres_escape(s, equals_pos);
+ PermString key = PermString(s, len);
+ int index = _map[key];
+ if (!override && index > 0)
+ continue;
+
+ // double equals means absolute pathname
+ if (s[equals_pos + 1] == '=')
+ equals_pos++;
+
+ // get the value. Don't escape it yet
+ len = slurper.cur_line_length() - (equals_pos + 1);
+ String value = String(s + equals_pos + 1, len);
+
+ // stick key and value into our data structure
+ if (index == 0) {
+ index = _directories.size();
+ _directories.push_back(directory);
+ _values.push_back(value);
+ _value_escaped.push_back(false);
+ _map.insert(key, index);
+ } else {
+ _directories[index] = directory;
+ _values[index] = value;
+ _value_escaped[index] = false;
+ }
+ }
+}
+
+
+PsresDatabaseSection *
+PsresDatabase::force_section(PermString name)
+{
+ if (_section_map[name] > 0)
+ return _sections[_section_map[name]];
+ else {
+ PsresDatabaseSection *s = new PsresDatabaseSection(name);
+ int index = _sections.size();
+ _sections.push_back(s);
+ _section_map.insert(name, index);
+ return s;
+ }
+}
+
+bool
+PsresDatabase::add_one_psres_file(Slurper &slurper, bool override)
+{
+ if (!read_psres_line(slurper, 0))
+ return /* error */ false;
+
+ char *s = slurper.cur_line();
+ unsigned len = slurper.cur_line_length();
+ if (len < 12 || memcmp(s, "PS-Resources", 12) != 0)
+ return /* error */ false;
+
+ bool exclusive = (len >= 22 && memcmp(s+12, "-Exclusive", 10) == 0);
+
+ // skip list of sections
+ while (read_psres_line(slurper, 0))
+ /* nada */;
+
+ // now, read each section
+ PermString directory = slurper.filename().directory();
+
+ while (read_psres_line(slurper, 0)) {
+ s = slurper.cur_line();
+ len = psres_escape(s, slurper.cur_line_length());
+ PsresDatabaseSection *section = force_section(PermString(s, len));
+ section->add_psres_file_section(slurper, directory, override);
+ }
+
+ return exclusive;
+}
+
+bool
+PsresDatabase::add_psres_file(Filename &filename, bool override)
+{
+ Slurper slurpy(filename);
+ return add_one_psres_file(slurpy, override);
+}
+
+
+#ifndef WIN32
+
+void
+PsresDatabase::add_psres_directory(PermString directory)
+{
+ DIR *dir = opendir(directory.c_str());
+ if (!dir) return;
+
+ while (struct dirent *dirent = readdir(dir)) {
+ int len = DIR_NAMLEN(dirent);
+ if (len > 4 && dirent->d_name[0] != '.'
+ && memcmp(dirent->d_name + len - 4, ".upr", 4) == 0
+ && (len != 9 || memcmp(dirent->d_name, "PSres.upr", 9) != 0)) {
+ Filename fn(directory, PermString(dirent->d_name, len));
+ add_psres_file(fn, false);
+ }
+ }
+
+ closedir(dir);
+}
+
+#else /* WIN32 */
+
+void
+PsresDatabase::add_psres_directory(PermString directory)
+{
+ WIN32_FIND_DATA find_file_data;
+ HANDLE hnd;
+ int proceed = TRUE;
+
+ PermString search_str = permcat(directory, "/*.*");
+ hnd = FindFirstFile(search_str.c_str(), &find_file_data);
+
+ if (hnd == INVALID_HANDLE_VALUE) {
+ return;
+ }
+ while (proceed) {
+ int len = strlen(find_file_data.cFileName);
+ if (len > 4 && find_file_data.cFileName[0] != '.'
+ && _strnicmp(find_file_data.cFileName + len - 4, ".upr", 4) == 0
+ && (len != 9 || _strnicmp(find_file_data.cFileName, "PSres.upr", 9) != 0)) {
+ Filename fn(directory, PermString(find_file_data.cFileName, len));
+ add_psres_file(fn, false);
+ }
+ proceed = FindNextFile (hnd, &find_file_data);
+ }
+ FindClose(hnd);
+}
+
+#endif /* WIN32 */
+
+
+void
+PsresDatabase::add_psres_path(const char *path, const char *default_path,
+ bool override)
+{
+ if (!path && !default_path)
+ return;
+ else if (!path) {
+ path = default_path;
+ default_path = 0;
+ }
+
+ if (override && _sections.size() > 1) {
+ PsresDatabase new_db;
+ new_db.add_psres_path(path, default_path, false);
+ add_database(&new_db, true);
+ return;
+ }
+
+ while (*path) {
+ const char *epath = path;
+ while (*epath && *epath != ':') epath++;
+
+ PermString directory(path, epath - path);
+ Filename filename(directory, "PSres.upr");
+ if (epath == path) {
+ add_psres_path(default_path, 0, false);
+ default_path = 0; // don't use default path twice
+ } else if (!filename.readable() || !add_psres_file(filename, false))
+ add_psres_directory(directory);
+
+ path = (*epath ? epath+1 : epath);
+ }
+}
+
+
+void
+PsresDatabase::add_database(PsresDatabase *db, bool override)
+{
+ for (int i = 1; i < db->_sections.size(); i++) {
+ PermString section_name = db->_sections[i]->section_name();
+ PsresDatabaseSection *section = force_section(section_name);
+ section->add_section(db->_sections[i], override);
+ }
+}
+
+void
+PsresDatabaseSection::add_section(PsresDatabaseSection *s, bool override)
+{
+ for (HashMap<PermString, int>::const_iterator i = s->_map.begin(); i; i++) {
+ int value = i.value();
+ if (_map[i.key()] <= 0) {
+ int my_index = _directories.size();
+ _directories.push_back(s->_directories[value]);
+ _values.push_back(s->_values[value]);
+ _value_escaped.push_back(s->_value_escaped[value]);
+ _map.insert(i.key(), my_index);
+ } else if (override) {
+ int my_index = _map[i.key()];
+ _directories[my_index] = s->_directories[value];
+ _values[my_index] = s->_values[value];
+ _value_escaped[my_index] = s->_value_escaped[value];
+ }
+ }
+}
+
+
+const String &
+PsresDatabaseSection::value(int index)
+{
+ if (_value_escaped[index])
+ return _values[index];
+ else {
+ char *data = _values[index].mutable_data();
+ int len = psres_escape(data, _values[index].length());
+ _values[index] = _values[index].substring(0, len);
+ _value_escaped[index] = true;
+ return _values[index];
+ }
+}
+
+Filename
+PsresDatabaseSection::filename_value(PermString key)
+{
+ int index = _map[key];
+ if (!index)
+ return Filename();
+ else if (!_directories[index])
+ return Filename(value(index));
+ else
+ return Filename(_directories[index], value(index));
+}
+
+const String &
+PsresDatabase::value(PermString sec, PermString key) const
+{
+ PsresDatabaseSection *s = section(sec);
+ if (s)
+ return s->value(key);
+ else
+ return String::make_empty();
+}
+
+const String &
+PsresDatabase::unescaped_value(PermString sec, PermString key) const
+{
+ PsresDatabaseSection *s = section(sec);
+ if (s)
+ return s->unescaped_value(key);
+ else
+ return String::make_empty();
+}
+
+Filename
+PsresDatabase::filename_value(PermString sec, PermString key) const
+{
+ PsresDatabaseSection *s = section(sec);
+ if (s)
+ return s->filename_value(key);
+ else
+ return Filename();
+}
+
+}
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1bounds.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1bounds.cc
new file mode 100644
index 00000000000..ccea404d4d3
--- /dev/null
+++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1bounds.cc
@@ -0,0 +1,161 @@
+// -*- related-file-name: "../include/efont/t1bounds.hh" -*-
+
+/* t1bounds.{cc,hh} -- charstring bounding box finder
+ *
+ * Copyright (c) 1998-2012 Eddie Kohler
+ *
+ * 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 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <efont/t1bounds.hh>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+namespace Efont {
+
+CharstringBounds::CharstringBounds()
+ : _lb(UNKDOUBLE, UNKDOUBLE), _rt(UNKDOUBLE, UNKDOUBLE),
+ _last_xf_program(0)
+{
+}
+
+CharstringBounds::CharstringBounds(const Transform &nonfont_xf)
+ : _lb(UNKDOUBLE, UNKDOUBLE), _rt(UNKDOUBLE, UNKDOUBLE),
+ _nonfont_xf(nonfont_xf), _last_xf_program(0)
+{
+}
+
+CharstringBounds::CharstringBounds(const Transform &nonfont_xf, const Vector<double> &weight)
+ : CharstringInterp(weight),
+ _lb(UNKDOUBLE, UNKDOUBLE), _rt(UNKDOUBLE, UNKDOUBLE),
+ _nonfont_xf(nonfont_xf), _last_xf_program(0)
+{
+}
+
+void
+CharstringBounds::clear()
+{
+ _lb = _rt = Point(UNKDOUBLE, UNKDOUBLE);
+}
+
+void
+CharstringBounds::xf_mark(const Bezier &b)
+{
+ Bezier b1, b2;
+ b.halve(b1, b2);
+ xf_mark(b1.point(3));
+ if (!xf_controls_inside(b1))
+ xf_mark(b1);
+ if (!xf_controls_inside(b2))
+ xf_mark(b2);
+}
+
+void
+CharstringBounds::act_width(int, const Point &w)
+{
+ _width = w;
+}
+
+void
+CharstringBounds::act_line(int, const Point &p0, const Point &p1)
+{
+ mark(p0);
+ mark(p1);
+}
+
+void
+CharstringBounds::act_curve(int, const Point &p0, const Point &p1, const Point &p2, const Point &p3)
+{
+ Point q0 = p0 * _xf;
+ Point q1 = p1 * _xf;
+ Point q2 = p2 * _xf;
+ Point q3 = p3 * _xf;
+
+ xf_mark(q0);
+ xf_mark(q3);
+
+ if (!xf_inside(q1) || !xf_inside(q2)) {
+ Bezier b(q0, q1, q2, q3);
+ xf_mark(b);
+ }
+}
+
+void
+CharstringBounds::set_xf(const CharstringProgram *program)
+{
+ if (_last_xf_program != program) {
+ _last_xf_program = program;
+ double matrix[6];
+ program->font_matrix(matrix);
+ Transform font_xf = Transform(matrix).scaled(1000);
+ font_xf.check_null(0.001);
+ _xf = _nonfont_xf * font_xf;
+ }
+}
+
+bool
+CharstringBounds::char_bounds(const CharstringContext &g, bool shift)
+{
+ set_xf(g.program);
+ CharstringInterp::interpret(g);
+ if (shift) {
+ _xf.translate(_width);
+ _nonfont_xf.translate(_width);
+ }
+ return error() >= 0;
+}
+
+void
+CharstringBounds::translate(double dx, double dy)
+{
+ _xf.translate(dx, dy);
+ _nonfont_xf.translate(dx, dy);
+}
+
+bool
+CharstringBounds::output(int bb[4], int &width, bool use_cur_width) const
+{
+ if (!KNOWN(_lb.x))
+ bb[0] = bb[1] = bb[2] = bb[3] = 0;
+ else {
+ bb[0] = (int) floor(_lb.x);
+ bb[1] = (int) floor(_lb.y);
+ bb[2] = (int) ceil(_rt.x);
+ bb[3] = (int) ceil(_rt.y);
+ }
+ Point p;
+ if (use_cur_width)
+ p = _width * _xf;
+ else
+ p = Point(0, 0) * _xf;
+ width = (int) ceil(p.x);
+ return error() >= 0;
+}
+
+bool
+CharstringBounds::bounds(const Transform &transform, const CharstringContext &g, int bb[4], int &width)
+{
+ CharstringBounds b(transform);
+ b.char_bounds(g, false);
+ return b.output(bb, width, true);
+}
+
+bool
+CharstringBounds::bounds(const CharstringContext &g, int bb[4], int &width)
+{
+ CharstringBounds b;
+ b.char_bounds(g, false);
+ return b.output(bb, width, true);
+}
+
+}
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1cs.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1cs.cc
new file mode 100644
index 00000000000..4db3afa5a9d
--- /dev/null
+++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1cs.cc
@@ -0,0 +1,370 @@
+// -*- related-file-name: "../include/efont/t1cs.hh" -*-
+
+/* t1cs.{cc,hh} -- Type 1/2 charstrings
+ *
+ * Copyright (c) 1998-2012 Eddie Kohler
+ *
+ * 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 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <efont/t1cs.hh>
+#include <efont/t1interp.hh>
+#include <string.h>
+namespace Efont {
+
+const char * const Charstring::command_names[] = {
+ "error", "hstem", "UNKNOWN_2", "vstem", "vmoveto",
+ "rlineto", "hlineto", "vlineto", "rrcurveto", "closepath",
+
+ "callsubr", "return", "escape", "hsbw", "endchar",
+ "UNKNOWN_15", "blend", "UNKNOWN_17", "hstemhm", "hintmask",
+
+ "cntrmask", "rmoveto", "hmoveto", "vstemhm", "rcurveline",
+ "rlinecurve", "vvcurveto", "hhcurveto", "shortint", "callgsubr",
+
+ "vhcurveto", "hvcurveto", "dotsection", "vstem3", "hstem3",
+ "and", "or", "not", "seac", "sbw",
+
+ "store", "abs", "add", "sub", "div",
+ "load", "neg", "eq", "callothersubr", "pop",
+
+ "drop", "UNKNOWN_12_19", "put", "get", "ifelse",
+ "random", "mul", "UNKNOWN_12_25", "sqrt", "dup",
+
+ "exch", "index", "roll", "UNKNOWN_12_31", "UNKNOWN_12_32",
+ "setcurrentpoint", "hflex", "flex", "hflex1", "flex1"
+};
+
+const char * const Charstring::standard_encoding[256] = {
+ /* 00x */ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 01x */ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 02x */ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 03x */ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 04x */ "space", "exclam", "quotedbl", "numbersign", "dollar", "percent",
+ "ampersand", "quoteright",
+ /* 05x */ "parenleft", "parenright", "asterisk", "plus", "comma", "hyphen",
+ "period", "slash",
+ /* 06x */ "zero", "one", "two", "three", "four", "five", "six", "seven",
+ /* 07x */ "eight", "nine", "colon", "semicolon", "less", "equal",
+ "greater", "question",
+ /* 10x */ "at", "A", "B", "C", "D", "E", "F", "G",
+ /* 11x */ "H", "I", "J", "K", "L", "M", "N", "O",
+ /* 12x */ "P", "Q", "R", "S", "T", "U", "V", "W",
+ /* 13x */ "X", "Y", "Z", "bracketleft", "backslash", "bracketright",
+ "asciicircum", "underscore",
+ /* 14x */ "quoteleft", "a", "b", "c", "d", "e", "f", "g",
+ /* 15x */ "h", "i", "j", "k", "l", "m", "n", "o",
+ /* 16x */ "p", "q", "r", "s", "t", "u", "v", "w",
+ /* 17x */ "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", 0,
+ /* 20x */ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 21x */ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 22x */ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 23x */ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 24x */ 0, "exclamdown", "cent", "sterling", "fraction", "yen",
+ "florin", "section",
+ /* 25x */ "currency", "quotesingle", "quotedblleft", "guillemotleft",
+ "guilsinglleft", "guilsinglright", "fi", "fl",
+ /* 26x */ 0, "endash", "dagger", "daggerdbl", "periodcentered", 0,
+ "paragraph", "bullet",
+ /* 27x */ "quotesinglbase", "quotedblbase", "quotedblright",
+ "guillemotright", "ellipsis", "perthousand", 0, "questiondown",
+ /* 30x */ 0, "grave", "acute", "circumflex", "tilde", "macron",
+ "breve", "dotaccent",
+ /* 31x */ "dieresis", 0, "ring", "cedilla", 0, "hungarumlaut",
+ "ogonek", "caron",
+ /* 32x */ "emdash", 0, 0, 0, 0, 0, 0, 0,
+ /* 33x */ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 34x */ 0, "AE", 0, "ordfeminine", 0, 0, 0, 0,
+ /* 35x */ "Lslash", "Oslash", "OE", "ordmasculine", 0, 0, 0, 0,
+ /* 36x */ 0, "ae", 0, 0, 0, "dotlessi", 0, 0,
+ /* 37x */ "lslash", "oslash", "oe", "germandbls", 0, 0, 0, 0,
+};
+
+
+Charstring::~Charstring()
+{
+}
+
+String
+Charstring::command_name(int cmd)
+{
+ if (cmd >= 0 && cmd <= cLastCommand)
+ return command_names[cmd];
+ else if (cmd < cEscapeDelta + 256)
+ return String("COMMAND_12_") + String(cmd - cEscapeDelta);
+ else
+ return String("<INVALID>");
+}
+
+
+Type1Charstring::Type1Charstring(int lenIV, const String &s)
+ : Charstring(), _key(-1)
+{
+ if (lenIV < 0) // no charstring encryption
+ _s = s;
+ else if (lenIV < s.length()) {
+ const unsigned char *d = reinterpret_cast<const unsigned char*>(s.data());
+ _key = t1R_cs;
+ for (int i = 0; i < lenIV; i++, d++)
+ _key = ((*d + _key) * t1C1 + t1C2) & 0xFFFF;
+ _s = s.substring(lenIV);
+ }
+}
+
+void
+Type1Charstring::prepend(const Type1Charstring &t1cs)
+{
+ if (_key >= 0)
+ decrypt();
+ if (t1cs._key >= 0)
+ t1cs.decrypt();
+ _s = t1cs._s + _s;
+}
+
+void
+Type1Charstring::decrypt() const
+{
+ if (_key >= 0) {
+ int r = _key;
+ uint8_t *d = reinterpret_cast<uint8_t *>(_s.mutable_data());
+ for (int i = 0; i < _s.length(); i++, d++) {
+ uint8_t encrypted = *d;
+ *d = encrypted ^ (r >> 8);
+ r = ((encrypted + r) * t1C1 + t1C2) & 0xFFFF;
+ }
+ _key = -1;
+ }
+}
+
+bool
+Type1Charstring::process(CharstringInterp &interp) const
+{
+ const uint8_t *data = Type1Charstring::data();
+ int left = _s.length();
+
+ while (left > 0) {
+ bool more;
+ int ahead;
+
+ if (*data >= 32 && *data <= 246) { // push small number
+ more = interp.number(data[0] - 139);
+ ahead = 1;
+
+ } else if (*data < 32) { // a command
+ if (*data == cEscape) {
+ if (left < 2)
+ goto runoff_error;
+ more = interp.type1_command(cEscapeDelta + data[1]);
+ ahead = 2;
+ } else if (*data == cShortint) { // short integer
+ if (left < 3)
+ goto runoff_error;
+ int16_t val = (data[1] << 8) | data[2];
+ more = interp.number(val);
+ ahead = 3;
+ } else {
+ more = interp.type1_command(data[0]);
+ ahead = 1;
+ }
+
+ } else if (*data >= 247 && *data <= 250) { // push medium number
+ if (left < 2)
+ goto runoff_error;
+ int val = + ((data[0] - 247) << 8) + 108 + data[1];
+ more = interp.number(val);
+ ahead = 2;
+
+ } else if (*data >= 251 && *data <= 254) { // push negative medium number
+ if (left < 2)
+ goto runoff_error;
+ int val = - ((data[0] - 251) << 8) - 108 - data[1];
+ more = interp.number(val);
+ ahead = 2;
+
+ } else { // 255: push huge number
+ if (left < 5)
+ goto runoff_error;
+ int32_t val = (data[1] << 24) | (data[2] << 16) | (data[3] << 8) | data[4];
+ more = interp.number(val);
+ ahead = 5;
+ }
+
+ if (!more)
+ return interp.error() == CharstringInterp::errOK;
+
+ data += ahead;
+ left -= ahead;
+ }
+
+ runoff_error:
+ interp.error(CharstringInterp::errRunoff);
+ return false;
+}
+
+int
+Type1Charstring::first_caret_after(int pos) const
+{
+ const uint8_t *data = Type1Charstring::data();
+ const uint8_t *edata = data + (pos < length() ? pos : length());
+
+ while (data < edata) {
+ if (*data >= 32 && *data <= 246) // push small number
+ data++;
+ else if (*data < 32) { // a command
+ if (*data == cEscape)
+ data += 2;
+ else if (*data == cShortint)
+ data += 3;
+ else
+ data++;
+ } else if (*data >= 247 && *data <= 254) // push medium number
+ data += 2;
+ else // 255: push huge number
+ data += 5;
+ }
+
+ const uint8_t *odata = Type1Charstring::data();
+ return (data > odata + length() ? length() : data - odata);
+}
+
+void
+Type1Charstring::assign_substring(int pos, int len, const String &cs)
+{
+ if (_key >= 0)
+ decrypt();
+ if (pos < 0 || len < 0 || pos + len >= _s.length())
+ /* do nothing */;
+ else if (cs.length() == len) {
+ char *d = _s.mutable_data();
+ memcpy(d + pos, cs.data(), cs.length());
+ } else if (cs.length() <= len) {
+ char *d = _s.mutable_data();
+ memcpy(d + pos, cs.data(), cs.length());
+ memmove(d + pos + cs.length(), d + pos + len, _s.length() - pos - len);
+ _s = _s.substring(0, cs.length() - len);
+ } else
+ _s = _s.substring(0, pos) + cs + _s.substring(pos + len);
+}
+
+
+bool
+Type2Charstring::process(CharstringInterp &interp) const
+{
+ const uint8_t *data = Type2Charstring::data();
+ int left = _s.length();
+
+ while (left > 0) {
+ bool more;
+ int ahead;
+
+ if (*data >= 32 && *data <= 246) { // push small number
+ more = interp.number(data[0] - 139);
+ ahead = 1;
+
+ } else if (*data < 32) { // a command
+ if (*data == cEscape) {
+ if (left < 2)
+ goto runoff_error;
+ more = interp.type2_command(cEscapeDelta + data[1], 0, 0);
+ ahead = 2;
+ } else if (*data == cShortint) { // short integer
+ if (left < 3)
+ goto runoff_error;
+ int16_t val = (data[1] << 8) | data[2];
+ more = interp.number(val);
+ ahead = 3;
+ } else if (*data == cHintmask || *data == cCntrmask) {
+ int left_ptr = left - 1;
+ more = interp.type2_command(data[0], data + 1, &left_ptr);
+ ahead = 1 + (left - 1) - left_ptr;
+ } else {
+ more = interp.type2_command(data[0], 0, 0);
+ ahead = 1;
+ }
+
+ } else if (*data >= 247 && *data <= 250) { // push medium number
+ if (left < 2)
+ goto runoff_error;
+ int val = + ((data[0] - 247) << 8) + 108 + data[1];
+ more = interp.number(val);
+ ahead = 2;
+
+ } else if (*data >= 251 && *data <= 254) { // push negative medium number
+ if (left < 2)
+ goto runoff_error;
+ int val = - ((data[0] - 251) << 8) - 108 - data[1];
+ more = interp.number(val);
+ ahead = 2;
+
+ } else { // 255: push huge number
+ if (left < 5)
+ goto runoff_error;
+ int32_t val = (data[1] << 24) | (data[2] << 16) | (data[3] << 8) | data[4];
+ more = interp.number(val / 65536.);
+ ahead = 5;
+ }
+
+ if (!more)
+ return interp.error() == CharstringInterp::errOK;
+
+ data += ahead;
+ left -= ahead;
+ }
+
+ runoff_error:
+ interp.error(CharstringInterp::errRunoff);
+ return false;
+}
+
+
+const CharstringProgram *
+CharstringProgram::child_program(int) const
+{
+ return this;
+}
+
+void
+CharstringProgram::font_matrix(double matrix[6]) const
+{
+ matrix[0] = matrix[3] = 0.001;
+ matrix[1] = matrix[2] = matrix[4] = matrix[5] = 0;
+}
+
+int
+CharstringProgram::units_per_em() const
+{
+ return 1000;
+}
+
+void
+CharstringProgram::glyph_names(Vector<PermString> &gnames) const
+{
+ int n = nglyphs();
+ gnames.resize(n);
+ for (int i = 0; i < n; i++)
+ gnames[i] = glyph_name(i);
+}
+
+Vector<double> *
+CharstringProgram::mm_vector(VectorType, bool) const
+{
+ return 0;
+}
+
+double
+CharstringProgram::global_width_x(bool) const
+{
+ return UNKDOUBLE;
+}
+
+}
+
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1csgen.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1csgen.cc
new file mode 100644
index 00000000000..b24c8f21307
--- /dev/null
+++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1csgen.cc
@@ -0,0 +1,633 @@
+// -*- related-file-name: "../include/efont/t1csgen.hh" -*-
+
+/* t1csgen.{cc,hh} -- Type 1 charstring generation
+ *
+ * Copyright (c) 1998-2012 Eddie Kohler
+ *
+ * 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 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <efont/t1csgen.hh>
+#include <efont/t1font.hh>
+#include <efont/t1item.hh>
+#include <math.h>
+namespace Efont {
+
+static const char * const command_desc[] = {
+ 0, 0, 0, 0, "y",
+ "xy", "x", "y", "xyxyxy", 0,
+
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ 0, "xy", "x", 0, 0,
+ 0, 0, 0, 0, 0,
+
+ "yxyx", "xxyy", 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ 0, 0, 0, 0, 0,
+ "XY", 0, 0, 0, 0
+};
+
+Type1CharstringGen::Type1CharstringGen(int precision)
+{
+ if (precision >= 1 && precision <= 107)
+ _precision = precision;
+ else
+ _precision = 5;
+ _f_precision = _precision;
+ clear();
+}
+
+void
+Type1CharstringGen::clear()
+{
+ _ncs.clear();
+ _true = _false = Point(0, 0);
+ _state = S_INITIAL;
+}
+
+
+void
+Type1CharstringGen::gen_rational(int big_val, int divisor)
+{
+ int frac = big_val % divisor;
+ int val = (frac == 0 ? big_val / divisor : big_val);
+
+ if (val >= -107 && val <= 107)
+ _ncs.append((char)(val + 139));
+
+ else if (val >= -1131 && val <= 1131) {
+ int base = val < 0 ? 251 : 247;
+ if (val < 0) val = -val;
+ val -= 108;
+ int w = val % 256;
+ val = (val - w) / 256;
+ _ncs.append((char)(val + base));
+ _ncs.append((char)w);
+
+ } else {
+ _ncs.append('\377');
+ long l = val;
+ _ncs.append((char)((l >> 24) & 0xFF));
+ _ncs.append((char)((l >> 16) & 0xFF));
+ _ncs.append((char)((l >> 8) & 0xFF));
+ _ncs.append((char)((l >> 0) & 0xFF));
+ }
+
+ if (frac != 0) {
+ _ncs.append((char)(divisor + 139));
+ _ncs.append((char)Charstring::cEscape);
+ _ncs.append((char)(Charstring::cDiv - Charstring::cEscapeDelta));
+ }
+}
+
+void
+Type1CharstringGen::gen_number(double float_val, int kind)
+{
+ switch (kind) {
+ case 'x':
+ _true.x += float_val;
+ float_val = _true.x - _false.x;
+ break;
+ case 'y':
+ _true.y += float_val;
+ float_val = _true.y - _false.y;
+ break;
+ case 'X':
+ _true.x = float_val;
+ break;
+ case 'Y':
+ _true.y = float_val;
+ break;
+ }
+
+ // 30.Jul.2003 - Avoid rounding differences between platforms with the
+ // extra 0.00001.
+ int big_val = (int)floor(float_val * _f_precision + 0.50001);
+
+ gen_rational(big_val, _precision);
+
+ float_val = big_val / _f_precision;
+ switch (kind) {
+ case 'x':
+ _false.x += float_val;
+ break;
+ case 'y':
+ _false.y += float_val;
+ break;
+ case 'X':
+ _false.x = float_val;
+ break;
+ case 'Y':
+ _false.y = float_val;
+ break;
+ }
+}
+
+
+void
+Type1CharstringGen::gen_command(int command)
+{
+ if (command >= Charstring::cEscapeDelta) {
+ _ncs.append((char)Charstring::cEscape);
+ _ncs.append((char)(command - Charstring::cEscapeDelta));
+ if (command != Charstring::cSbw)
+ _state = S_GEN;
+ } else {
+ _ncs.append((char)command);
+ if (command > Charstring::cVmoveto && command != Charstring::cHsbw)
+ _state = S_GEN;
+ }
+}
+
+bool
+Type1CharstringGen::gen_stem3_stack(CharstringInterp &interp)
+{
+ // special handling to ensure rounding doesn't generate an invalid stem3
+ // hint
+ if (interp.size() < 6)
+ return false;
+
+ // sort hints
+ int i0, i1, i2;
+ if (interp.at(0) > interp.at(2))
+ i0 = 2, i1 = 0;
+ else
+ i0 = 0, i1 = 2;
+ if (interp.at(4) < interp.at(i0))
+ i2 = i1, i1 = i0, i0 = 4;
+ else if (interp.at(4) < interp.at(i1))
+ i2 = i1, i1 = 4;
+ else
+ i2 = 4;
+
+ // check constraints. count "almost equal" as equal
+ double stemw0 = interp.at(i0+1), stemw2 = interp.at(i2+1);
+ if ((int)(1024*(stemw0 - stemw2) + .5) != 0)
+ return false;
+
+ double c0 = interp.at(i0) + interp.at(i0+1)/2;
+ double c1 = interp.at(i1) + interp.at(i1+1)/2;
+ double c2 = interp.at(i2) + interp.at(i2+1)/2;
+ if ((int)(1024*((c1 - c0) - (c2 - c1)) + .5) != 0)
+ return false;
+
+ // if all constraints are satisfied now, make sure they are also satisfied
+ // after rounding
+ int big_v0 = (int)floor(interp.at(i0) * _f_precision + 0.50001);
+ int big_v2 = (int)floor(interp.at(i2) * _f_precision + 0.50001);
+ int big_stemw0 = (int)floor(stemw0 * _f_precision + 0.50001);
+ int big_stemw1 = (int)floor(interp.at(i1+1) * _f_precision + 0.50001);
+
+ int big_v1_times2 = big_v0 + big_v2 + big_stemw0 - big_stemw1;
+
+ gen_rational(big_v0, _precision);
+ gen_rational(big_stemw0, _precision);
+ if (big_v1_times2 % 2)
+ gen_rational(big_v1_times2, 2 * _precision);
+ else
+ gen_rational(big_v1_times2 / 2, _precision);
+ gen_rational(big_stemw1, _precision);
+ gen_rational(big_v2, _precision);
+ gen_rational(big_stemw0, _precision);
+
+ interp.clear();
+ return true;
+}
+
+void
+Type1CharstringGen::gen_stack(CharstringInterp &interp, int for_cmd)
+{
+ const char *str = ((unsigned)for_cmd <= Charstring::cLastCommand ? command_desc[for_cmd] : (const char *)0);
+ if ((for_cmd == Charstring::cHstem3 || for_cmd == Charstring::cVstem3)
+ && gen_stem3_stack(interp))
+ return;
+
+ int i;
+ for (i = 0; str && *str && i < interp.size(); i++, str++)
+ gen_number(interp.at(i), *str);
+ for (; i < interp.size(); i++)
+ gen_number(interp.at(i));
+ interp.clear();
+}
+
+void
+Type1CharstringGen::gen_moveto(const Point &p, bool closepath, bool always)
+{
+ // make sure we generate some moveto on the first command
+
+ Point d = p - _true;
+ int big_dx = (int)floor(d.x * _f_precision + 0.50001);
+ int big_dy = (int)floor(d.y * _f_precision + 0.50001);
+
+ if (big_dx == 0 && big_dy == 0 && _state != S_INITIAL && !always)
+ /* do nothing */;
+ else {
+ if (closepath)
+ gen_command(Charstring::cClosepath);
+ if (big_dy == 0) {
+ gen_number(d.x, 'x');
+ gen_command(Charstring::cHmoveto);
+ } else if (big_dx == 0) {
+ gen_number(d.y, 'y');
+ gen_command(Charstring::cVmoveto);
+ } else {
+ gen_number(d.x, 'x');
+ gen_number(d.y, 'y');
+ gen_command(Charstring::cRmoveto);
+ }
+ }
+
+ _true = p;
+}
+
+void
+Type1CharstringGen::append_charstring(const String &s)
+{
+ _ncs << s;
+}
+
+Type1Charstring *
+Type1CharstringGen::output()
+{
+ return new Type1Charstring(take_string());
+}
+
+void
+Type1CharstringGen::output(Type1Charstring &cs)
+{
+ cs.assign(take_string());
+}
+
+String
+Type1CharstringGen::callsubr_string(int subr)
+{
+ Type1CharstringGen csg;
+ csg.gen_number(subr);
+ csg.gen_command(Charstring::cCallsubr);
+ return csg._ncs.take_string();
+}
+
+
+/*****
+ * Type1CharstringGenInterp
+ **/
+
+Type1CharstringGenInterp::Type1CharstringGenInterp(int precision)
+ : _csgen(precision), _hint_csgen(precision),
+ _direct_hr(false), _hr_storage(0),
+ _max_flex_height(0), _bad_flex(false)
+{
+}
+
+void
+Type1CharstringGenInterp::set_hint_replacement_storage(Type1Font *font)
+{
+ _hr_storage = font;
+ _hr_firstsubr = font->nsubrs();
+}
+
+
+// generating charstring commands
+
+inline void
+Type1CharstringGenInterp::gen_number(double n, int what)
+{
+ _csgen.gen_number(n, what);
+}
+
+inline void
+Type1CharstringGenInterp::gen_command(int what)
+{
+ _csgen.gen_command(what);
+}
+
+void
+Type1CharstringGenInterp::gen_sbw(bool hints_follow)
+{
+ if (!hints_follow && nhints())
+ act_hintmask(Cs::cHintmask, 0, nhints());
+ else if (left_sidebearing().y == 0 && _width.y == 0) {
+ gen_number(left_sidebearing().x, 'X');
+ gen_number(_width.x);
+ gen_command(Cs::cHsbw);
+ } else {
+ gen_number(left_sidebearing().x, 'X');
+ gen_number(left_sidebearing().y, 'Y');
+ gen_number(_width.x);
+ gen_number(_width.y);
+ gen_command(Cs::cSbw);
+ }
+ _state = S_CLOSED;
+}
+
+void
+Type1CharstringGenInterp::act_width(int, const Point &p)
+{
+ _width = p;
+}
+
+void
+Type1CharstringGenInterp::act_seac(int, double asb, double adx, double ady, int bchar, int achar)
+{
+ if (_state == S_INITIAL)
+ gen_sbw(false);
+ gen_number(asb);
+ gen_number(adx);
+ gen_number(ady);
+ gen_number(bchar);
+ gen_number(achar);
+ gen_command(Cs::cSeac);
+ _state = S_SEAC;
+}
+
+void
+Type1CharstringGenInterp::swap_stem_hints()
+{
+ _stem_pos.clear();
+ _stem_width.clear();
+ _stem_hstem.clear();
+ _in_hr = true;
+}
+
+void
+Type1CharstringGenInterp::act_hstem(int, double pos, double width)
+{
+ if (_state != S_INITIAL && !_in_hr)
+ swap_stem_hints();
+ _stem_pos.push_back(pos);
+ _stem_width.push_back(width);
+ _stem_hstem.push_back(1);
+}
+
+void
+Type1CharstringGenInterp::act_vstem(int, double pos, double width)
+{
+ if (_state != S_INITIAL && !_in_hr)
+ swap_stem_hints();
+ _stem_pos.push_back(pos);
+ _stem_width.push_back(width);
+ _stem_hstem.push_back(0);
+}
+
+String
+Type1CharstringGenInterp::gen_hints(const unsigned char *data, int nhints) const
+{
+ _hint_csgen.clear();
+ unsigned char mask = 0x80;
+ for (int i = 0; i < nhints; i++) {
+ if (*data & mask) {
+ double offset = (_stem_hstem[i] ? left_sidebearing().y : left_sidebearing().x);
+ _hint_csgen.gen_number(_stem_pos[i] - offset);
+ _hint_csgen.gen_number(_stem_width[i]);
+ _hint_csgen.gen_command(_stem_hstem[i] ? Cs::cHstem : Cs::cVstem);
+ }
+ if ((mask >>= 1) == 0)
+ data++, mask = 0x80;
+ }
+ return _hint_csgen.take_string();
+}
+
+void
+Type1CharstringGenInterp::act_hintmask(int cmd, const unsigned char *data, int nhints)
+{
+ if (cmd == Cs::cCntrmask || nhints > Type1CharstringGenInterp::nhints())
+ return;
+
+ String data_holder;
+ if (!data) {
+ data_holder = String::make_fill('\377', ((nhints - 1) >> 3) + 1);
+ data = data_holder.udata();
+ }
+
+ String hints = gen_hints(data, nhints);
+ _in_hr = false;
+
+ if (_state == S_INITIAL || _direct_hr) {
+ _last_hints = hints;
+ if (_state == S_INITIAL)
+ gen_sbw(true);
+ _csgen.append_charstring(hints);
+ } else if (_hr_storage && hints != _last_hints) {
+ _last_hints = hints;
+ hints += (char)(Cs::cReturn);
+
+ int subrno = -1, nsubrs = _hr_storage->nsubrs();
+ for (int i = _hr_firstsubr; i < nsubrs; i++)
+ if (Type1Subr *s = _hr_storage->subr_x(i))
+ if (s->t1cs() == hints) {
+ subrno = i;
+ break;
+ }
+
+ if (subrno < 0 && _hr_storage->set_subr(nsubrs, Type1Charstring(hints)))
+ subrno = nsubrs;
+
+ if (subrno >= 0) {
+ _csgen.gen_number(subrno);
+ _csgen.gen_number(4);
+ _csgen.gen_command(Cs::cCallsubr);
+ }
+ }
+}
+
+void
+Type1CharstringGenInterp::act_line(int cmd, const Point &a, const Point &b)
+{
+ if (_state == S_INITIAL)
+ gen_sbw(false);
+ else if (_in_hr)
+ act_hintmask(cmd, 0, nhints());
+ _csgen.gen_moveto(a, _state == S_OPEN, false);
+ _state = S_OPEN;
+ if (a.x == b.x) {
+ gen_number(b.y - a.y, 'y');
+ gen_command(Cs::cVlineto);
+ } else if (a.y == b.y) {
+ gen_number(b.x - a.x, 'x');
+ gen_command(Cs::cHlineto);
+ } else {
+ gen_number(b.x - a.x, 'x');
+ gen_number(b.y - a.y, 'y');
+ gen_command(Cs::cRlineto);
+ }
+}
+
+void
+Type1CharstringGenInterp::act_curve(int cmd, const Point &a, const Point &b, const Point &c, const Point &d)
+{
+ if (_state == S_INITIAL)
+ gen_sbw(false);
+ else if (_in_hr)
+ act_hintmask(cmd, 0, nhints());
+ _csgen.gen_moveto(a, _state == S_OPEN, false);
+ _state = S_OPEN;
+ if (b.y == a.y && d.x == c.x) {
+ gen_number(b.x - a.x, 'x');
+ gen_number(c.x - b.x, 'x');
+ gen_number(c.y - b.y, 'y');
+ gen_number(d.y - c.y, 'y');
+ gen_command(Cs::cHvcurveto);
+ } else if (b.x == a.x && d.y == c.y) {
+ gen_number(b.y - a.y, 'y');
+ gen_number(c.x - a.x, 'x');
+ gen_number(c.y - b.y, 'y');
+ gen_number(d.x - c.x, 'x');
+ gen_command(Cs::cVhcurveto);
+ } else {
+ gen_number(b.x - a.x, 'x');
+ gen_number(b.y - a.y, 'y');
+ gen_number(c.x - b.x, 'x');
+ gen_number(c.y - b.y, 'y');
+ gen_number(d.x - c.x, 'x');
+ gen_number(d.y - c.y, 'y');
+ gen_command(Cs::cRrcurveto);
+ }
+}
+
+void
+Type1CharstringGenInterp::act_flex(int cmd, const Point &p0, const Point &p1, const Point &p2, const Point &p3_4, const Point &p5, const Point &p6, const Point &p7, double flex_depth)
+{
+ if (_state == S_INITIAL)
+ gen_sbw(false);
+ else if (_in_hr)
+ act_hintmask(cmd, 0, nhints());
+ _csgen.gen_moveto(p0, _state == S_OPEN, false);
+ _state = S_OPEN;
+
+ // 1. Outer endpoints must have same x (or y) coordinate
+ bool v_ok = (p0.x == p7.x);
+ bool h_ok = (p0.y == p7.y);
+
+ // 2. Join point and its neighboring controls must be at an extreme
+ if (v_ok && p2.x == p3_4.x && p3_4.x == p5.x) {
+ double distance = fabs(p3_4.x - p0.x);
+ int sign = (p3_4.x < p0.x ? -1 : 1);
+ if (sign * (p1.x - p0.x) < 0 || sign * (p1.x - p0.x) > distance
+ || sign * (p6.x - p0.x) < 0 || sign * (p6.x - p0.x) > distance)
+ v_ok = false;
+ } else
+ v_ok = false;
+
+ if (h_ok && p2.y == p3_4.y && p3_4.y == p5.y) {
+ double distance = fabs(p3_4.y - p0.y);
+ int sign = (p3_4.y < p0.y ? -1 : 1);
+ if (sign * (p1.y - p0.y) < 0 || sign * (p1.y - p0.y) > distance
+ || sign * (p6.y - p0.y) < 0 || sign * (p6.y - p0.y) > distance)
+ h_ok = false;
+ } else
+ h_ok = false;
+
+ // 3. Flex height <= 20
+ if (v_ok && fabs(p3_4.x - p0.x) > 20)
+ v_ok = false;
+ if (h_ok && fabs(p3_4.y - p0.y) > 20)
+ h_ok = false;
+
+ // generate flex commands
+ if (v_ok || h_ok) {
+ Point p_reference = (h_ok ? Point(p3_4.x, p0.y) : Point(p0.x, p3_4.y));
+
+ _csgen.gen_number(1);
+ _csgen.gen_command(Cs::cCallsubr);
+
+ _csgen.gen_moveto(p_reference, false, true);
+ _csgen.gen_number(2);
+ _csgen.gen_command(Cs::cCallsubr);
+
+ _csgen.gen_moveto(p1, false, true);
+ _csgen.gen_number(2);
+ _csgen.gen_command(Cs::cCallsubr);
+
+ _csgen.gen_moveto(p2, false, true);
+ _csgen.gen_number(2);
+ _csgen.gen_command(Cs::cCallsubr);
+
+ _csgen.gen_moveto(p3_4, false, true);
+ _csgen.gen_number(2);
+ _csgen.gen_command(Cs::cCallsubr);
+
+ _csgen.gen_moveto(p5, false, true);
+ _csgen.gen_number(2);
+ _csgen.gen_command(Cs::cCallsubr);
+
+ _csgen.gen_moveto(p6, false, true);
+ _csgen.gen_number(2);
+ _csgen.gen_command(Cs::cCallsubr);
+
+ _csgen.gen_moveto(p7, false, true);
+ _csgen.gen_number(2);
+ _csgen.gen_command(Cs::cCallsubr);
+
+ _csgen.gen_number(flex_depth);
+ _csgen.gen_number(p7.x, 'X');
+ _csgen.gen_number(p7.y, 'Y');
+ _csgen.gen_number(0);
+ _csgen.gen_command(Cs::cCallsubr);
+
+ double flex_height = fabs(h_ok ? p3_4.y - p0.y : p3_4.x - p0.x);
+ if (flex_height > _max_flex_height)
+ _max_flex_height = flex_height;
+ } else {
+ _bad_flex = true;
+ act_curve(cmd, p0, p1, p2, p3_4);
+ act_curve(cmd, p3_4, p5, p6, p7);
+ }
+}
+
+void
+Type1CharstringGenInterp::act_closepath(int cmd)
+{
+ if (_in_hr)
+ act_hintmask(cmd, 0, nhints());
+ gen_command(Cs::cClosepath);
+ _state = S_CLOSED;
+}
+
+void
+Type1CharstringGenInterp::intermediate_output(Type1Charstring &out)
+{
+ _csgen.output(out);
+ _state = S_INITIAL;
+ act_hintmask(Cs::cEndchar, 0, nhints());
+}
+
+void
+Type1CharstringGenInterp::run(const CharstringContext &g, Type1Charstring &out)
+{
+ _width = Point(0, 0);
+ _csgen.clear();
+ swap_stem_hints();
+ _state = S_INITIAL;
+ _in_hr = false;
+
+ CharstringInterp::interpret(g);
+
+ if (_state == S_INITIAL)
+ gen_sbw(false);
+ else if (_in_hr)
+ act_hintmask(Cs::cEndchar, 0, nhints());
+ if (_state != S_SEAC)
+ _csgen.gen_command(Cs::cEndchar);
+
+ _csgen.output(out);
+}
+
+}
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1font.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1font.cc
new file mode 100644
index 00000000000..05b97fa346e
--- /dev/null
+++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1font.cc
@@ -0,0 +1,914 @@
+// -*- related-file-name: "../include/efont/t1font.hh" -*-
+
+/* t1font.{cc,hh} -- Type 1 font
+ *
+ * Copyright (c) 1998-2012 Eddie Kohler
+ *
+ * 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 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <efont/t1font.hh>
+#include <efont/t1item.hh>
+#include <efont/t1rw.hh>
+#include <efont/t1mm.hh>
+#include <lcdf/error.hh>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+namespace Efont {
+
+static PermString::Initializer initializer;
+static PermString lenIV_str = "lenIV";
+static PermString FontInfo_str = "FontInfo";
+
+Type1Font::Type1Font(PermString name)
+ : _cached_defs(false), _built(true), _font_name(name), _glyph_map(-1),
+ _encoding(0), _cached_mmspace(0), _mmspace(0), _synthetic_item(0)
+{
+ _dict = new HashMap<PermString, Type1Definition *>[dLast];
+ for (int i = 0; i < dLast; i++) {
+ _index[i] = -1;
+ _dict_deltas[i] = 0;
+ _dict[i].set_default_value((Type1Definition *)0);
+ }
+}
+
+Type1Font::Type1Font(Type1Reader &reader)
+ : _cached_defs(false), _built(false), _glyph_map(-1), _encoding(0),
+ _cached_mmspace(0), _mmspace(0), _synthetic_item(0)
+{
+ _dict = new HashMap<PermString, Type1Definition *>[dLast];
+ for (int i = 0; i < dLast; i++) {
+ _index[i] = -1;
+ _dict_deltas[i] = 0;
+ _dict[i].set_default_value((Type1Definition *)0);
+ }
+ read(reader);
+}
+
+Type1Font::~Type1Font()
+{
+ delete[] _dict;
+ for (int i = 0; i < _items.size(); i++)
+ delete _items[i];
+ delete _mmspace;
+ for (int i = 0; i < _subrs.size(); i++)
+ delete _subrs[i];
+ if (!_synthetic_item)
+ for (int i = 0; i < _glyphs.size(); i++)
+ delete _glyphs[i];
+}
+
+void
+Type1Font::set_item(int i, Type1Item *it)
+{
+ delete _items[i];
+ _items[i] = it;
+}
+
+static const char * const dict_starters[] = {
+ "0 dict begin", "/FontInfo 0 dict dup begin", "dup /Private 0 dict dup begin", "/Blend 0 dict dup begin", 0, 0
+};
+
+void
+Type1Font::add_definition(int dict, Type1Definition *t1d)
+{
+ if (_index[dict] < 0) {
+ if (_built && dict_starters[dict])
+ add_item(new Type1CopyItem(dict_starters[dict]));
+ _index[dict] = _items.size();
+ }
+ add_item(t1d);
+ set_dict(dict, t1d->name(), t1d);
+}
+
+void
+Type1Font::add_type1_encoding(Type1Encoding *e)
+{
+ if (_encoding) {
+ for (Type1Item** t1i = _items.begin(); t1i < _items.end(); t1i++)
+ if (*t1i == _encoding) {
+ delete _encoding;
+ *t1i = _encoding = e;
+ return;
+ }
+ }
+ _encoding = e;
+ add_item(e);
+}
+
+void
+Type1Font::add_glyph(Type1Subr *s)
+{
+ int &g = _glyph_map.find_force(s->name(), _glyphs.size());
+ if (g == _glyphs.size())
+ _glyphs.push_back(s);
+ else {
+ delete _glyphs[g];
+ _glyphs[g] = s;
+ }
+}
+
+int
+Type1Font::read(Type1Reader &reader)
+{
+ Dict cur_dict = dFont;
+ int eexec_state = 0;
+ bool have_subrs = false;
+ bool have_charstrings = false;
+ int lenIV = 4;
+ Type1SubrGroupItem *cur_group = 0;
+ int cur_group_count = 0;
+
+ StringAccum accum;
+ while (reader.next_line(accum)) {
+
+ // check for NULL STRING
+ int x_length = accum.length();
+ if (!x_length)
+ continue;
+ const char *x = accum.c_str(); // ensure we don't run off the string
+
+ // check for CHARSTRINGS
+ if (reader.was_charstring()) {
+ Type1Subr *fcs = Type1Subr::make(x, x_length, reader.charstring_start(), reader.charstring_length(), lenIV);
+
+ if (fcs->is_subr()) {
+ if (fcs->subrno() >= _subrs.size())
+ _subrs.resize(fcs->subrno() + 30, (Type1Subr *)0);
+ if (_subrs[fcs->subrno()]) // hybrid font program
+ delete _subrs[fcs->subrno()];
+ _subrs[fcs->subrno()] = fcs;
+ if (!have_subrs && _items.size()) {
+ if (Type1CopyItem *item = _items.back()->cast_copy()) {
+ cur_group = new Type1SubrGroupItem
+ (this, true, item->value());
+ cur_group_count = 0;
+ _items.back() = cur_group;
+ delete item;
+ }
+ have_subrs = true;
+ }
+
+ } else {
+ add_glyph(fcs);
+ if (!have_charstrings && _items.size()) {
+ if (Type1CopyItem *item = _items.back()->cast_copy()) {
+ cur_group = new Type1SubrGroupItem
+ (this, false, item->value());
+ cur_group_count = 0;
+ _items.back() = cur_group;
+ delete item;
+ }
+ have_charstrings = true;
+ }
+ }
+
+ accum.clear();
+ continue;
+ }
+
+ // check for COMMENTS
+ if (x[0] == '%') {
+ add_item(new Type1CopyItem(accum.take_string()));
+ continue;
+ }
+
+ // check for CHARSTRING START
+ // 5/29/1999: beware of charstring start-like things that don't have
+ // `readstring' in them!
+ if (!_charstring_definer
+ && strstr(x, "string currentfile") != 0
+ && strstr(x, "readstring") != 0) {
+ const char *sb = x;
+ while (*sb && *sb != '/')
+ sb++;
+ const char *se = sb + 1;
+ while (*sb && *se && *se != ' ' && *se != '{')
+ se++;
+ if (*sb && *se) {
+ _charstring_definer = permprintf(" %*s ", se - sb - 1, sb + 1);
+ reader.set_charstring_definer(_charstring_definer);
+ add_item(new Type1CopyItem(accum.take_string()));
+ continue;
+ }
+ }
+
+ // check for ENCODING
+ if (!_encoding && strncmp(x, "/Encoding ", 10) == 0) {
+ read_encoding(reader, x + 10);
+ accum.clear();
+ continue;
+ }
+
+ // check for a DEFINITION
+ if (x[0] == '/') {
+ definition_succeed:
+ Type1Definition *t1d = Type1Definition::make(accum, &reader);
+ if (!t1d)
+ goto definition_fail;
+ if (t1d->name() == lenIV_str)
+ t1d->value_int(lenIV);
+ add_definition(cur_dict, t1d);
+ accum.clear();
+ continue;
+ } else if (x[0] == ' ') {
+ const char *y;
+ for (y = x; y[0] == ' '; y++)
+ ;
+ if (y[0] == '/')
+ goto definition_succeed;
+ }
+
+ definition_fail:
+
+ // check for ZEROS special case
+ if (eexec_state == 2) {
+ // In eexec_state 2 (right after turning off eexec), the opening
+ // part of the string will have some 0 bytes followed by '0's.
+ // Change the 0 bytes into textual '0's.
+ int zeros = 0;
+ while (x[zeros] == 0 && x_length > 0)
+ zeros++, x_length--;
+ add_item(new Type1CopyItem(String::make_fill('0', zeros * 2 + x_length)));
+ eexec_state = 3;
+ accum.clear();
+ continue;
+ }
+
+ // check for MODIFIED FONT
+ if (eexec_state == 1 && strstr(x, "FontDirectory") != 0
+ && read_synthetic_font(reader, x, accum)) {
+ accum.clear();
+ continue;
+ }
+
+ // check for END-OF-CHARSTRING-GROUP TEXT
+ if (cur_group) {
+ if (cur_group_count == 0
+ || ((strstr(x, "end") != 0 || strstr(x, "put") != 0)
+ && strchr(x, '/') == 0)) {
+ cur_group->add_end_text(x);
+ cur_group_count++;
+ accum.clear();
+ continue;
+ }
+ cur_group = 0;
+ }
+
+ // add COPY ITEM
+ String s = accum.take_string();
+ add_item(new Type1CopyItem(s));
+ x = s.data();
+
+ if (eexec_state == 0 && strncmp(x, "currentfile eexec", 17) == 0 && (isspace((unsigned char) x[17]) || !x[17])) {
+ // allow arbitrary whitespace after "currentfile eexec".
+ // note: strlen("currentfile eexec") == 17
+ for (x += 17; isspace((unsigned char) *x); x++)
+ /* nada */;
+ reader.switch_eexec(true, (unsigned char *)x, (s.data() + s.length()) - x);
+ set_item(nitems() - 1, new Type1EexecItem(true));
+ eexec_state = 1;
+ } else if (eexec_state == 1 && strstr(x, "currentfile closefile") != 0) {
+ reader.switch_eexec(false, 0, 0);
+ add_item(new Type1EexecItem(false));
+ eexec_state = 2;
+ } else if (strstr(x, "begin") != 0) {
+ // 30.Sep.2002: NuevaMM's BlendFontInfo dict starts with a simple
+ // "/FontInfo ... begin" inside a "/Blend ... begin".
+ Dict was_dict = cur_dict;
+ if (strstr(x, "/Private") != 0)
+ cur_dict = dPrivate;
+ else if (strstr(x, "/FontInfo") != 0)
+ cur_dict = dFontInfo;
+ else
+ cur_dict = dFont;
+ if (strstr(x, "/Blend") != 0)
+ cur_dict = (Dict)(cur_dict + dBlend);
+ else if (was_dict == dBlend && cur_dict == dFontInfo)
+ cur_dict = (Dict)(cur_dict + dBlend);
+ } else if (cur_dict == dFontInfo && strstr(x, "end") != 0)
+ cur_dict = dFont;
+ }
+
+ // set dictionary deltas
+ for (int i = dFI; i < dLast; i++)
+ _dict_deltas[i] = get_dict_size(i) - _dict[i].size();
+ // borrow glyphs and glyph map from _synthetic_item
+ if (!_glyphs.size() && _synthetic_item) {
+ _glyphs = _synthetic_item->included_font()->_glyphs;
+ _glyph_map = _synthetic_item->included_font()->_glyph_map;
+ }
+
+ return (ok() ? 0 : -1);
+}
+
+bool
+Type1Font::ok() const
+{
+ return font_name() && _glyphs.size() > 0;
+}
+
+static char *skip_comment_space(char *s)
+{
+ while (1) {
+ if (isspace((unsigned char) *s))
+ ++s;
+ else if (*s == '%') {
+ for (++s; *s != '\r' && *s != '\n' && *s != '\0'; ++s)
+ /* nada */;
+ } else
+ return s;
+ }
+}
+
+void
+Type1Font::read_encoding(Type1Reader &reader, const char *first_line)
+{
+ while (isspace((unsigned char) *first_line))
+ first_line++;
+ if (strncmp(first_line, "StandardEncoding", 16) == 0) {
+ add_type1_encoding(Type1Encoding::standard_encoding());
+ return;
+ }
+
+ add_type1_encoding(new Type1Encoding);
+
+ bool got_any = false;
+ StringAccum accum;
+
+ while (reader.next_line(accum)) {
+
+ // check for NULL STRING
+ if (!accum.length())
+ continue;
+ accum.append('\0'); // ensure we don't run off the string
+ char *pos = accum.data();
+
+ // skip to first `dup' token
+ if (!got_any) {
+ if (!(pos = strstr(pos, "dup"))) {
+ pos = accum.data();
+ goto check_done;
+ }
+ }
+
+ // parse as many `dup INDEX */CHARNAME put' as there are in the line
+ while (1) {
+ // skip spaces, look for `dup '
+ while (isspace((unsigned char) pos[0]))
+ ++pos;
+ if (pos[0] == '%')
+ pos = skip_comment_space(pos);
+ if (pos[0] != 'd' || pos[1] != 'u' || pos[2] != 'p' || !isspace((unsigned char) pos[3]))
+ break;
+
+ // look for `INDEX */'
+ char *scan;
+ int char_value = strtol(pos + 4, &scan, 10);
+ if (scan[0] == '#' && char_value > 0 && char_value < 37
+ && isalnum((unsigned char) scan[1]))
+ char_value = strtol(scan + 1, &scan, char_value);
+ while (isspace((unsigned char) scan[0]))
+ scan++;
+ if (char_value < 0 || char_value >= 256 || scan[0] != '/')
+ break;
+
+ // look for `CHARNAME put'
+ scan++;
+ char *name_pos = scan;
+ while (!isspace((unsigned char) scan[0]) && scan[0] != '\0')
+ ++scan;
+ char *name_end = scan;
+ while (isspace((unsigned char) scan[0]))
+ ++scan;
+ if (scan[0] != 'p' || scan[1] != 'u' || scan[2] != 't')
+ break;
+
+ _encoding->put(char_value, PermString(name_pos, name_end - name_pos));
+ got_any = true;
+ pos = scan + 3;
+ }
+
+ check_done:
+ // check for end of encoding section
+ // if not over, add COPY ITEM for leftovers we didn't parse
+ if ((strstr(pos, "readonly") != 0 || strstr(pos, "def") != 0)
+ && (got_any || strstr(pos, "for") == 0)) {
+ _encoding->set_definer(String(pos));
+ return;
+ } else if (got_any && *pos)
+ add_item(new Type1CopyItem(String(pos)));
+
+ accum.clear();
+ }
+}
+
+static bool
+read_synthetic_string(Type1Reader &reader, StringAccum &wrong_accum,
+ const char *format, int *value)
+{
+ StringAccum accum;
+ if (!reader.next_line(accum))
+ return false;
+ wrong_accum << accum;
+ accum.append('\0'); // ensure we don't run off the string
+ int n = 0;
+ if (value)
+ sscanf(accum.data(), format, value, &n);
+ else
+ sscanf(accum.data(), format, &n);
+ return (n != 0 && (isspace((unsigned char) accum[n]) || accum[n] == '\0'));
+}
+
+bool
+Type1Font::read_synthetic_font(Type1Reader &reader, const char *first_line,
+ StringAccum &wrong_accum)
+{
+ // read font name
+ PermString font_name;
+ {
+ char *x = new char[strlen(first_line) + 1];
+ int n = 0;
+ sscanf(first_line, "FontDirectory /%[^] \t\r\n[{}/] known {%n", x, &n);
+ if (n && (isspace((unsigned char) first_line[n]) || first_line[n] == 0))
+ font_name = x;
+ delete[] x;
+ if (!font_name)
+ return false;
+ }
+
+ // check UniqueID
+ int unique_id;
+ {
+ StringAccum accum;
+ if (!reader.next_line(accum))
+ return false;
+ wrong_accum << accum;
+ accum.c_str(); // ensure we don't run off the string
+ const char *y = accum.data();
+ if (*y != '/' || strncmp(y + 1, font_name.c_str(), font_name.length()) != 0)
+ return false;
+ int n = 0;
+ sscanf(y + font_name.length() + 1, " findfont%n", &n);
+ y = strstr(y, "/UniqueID get ");
+ if (n == 0 || y == 0)
+ return false;
+ n = 0;
+ sscanf(y + 14, "%d%n", &unique_id, &n);
+ if (n == 0)
+ return false;
+ }
+
+ // check lines that say how much text
+ int multiplier;
+ if (!read_synthetic_string(reader, wrong_accum, "save userdict /fbufstr %d string put%n", &multiplier))
+ return false;
+
+ int multiplicand;
+ if (!read_synthetic_string(reader, wrong_accum, "%d {currentfile fbufstr readstring { pop } { clear currentfile%n", &multiplicand))
+ return false;
+
+ if (!read_synthetic_string(reader, wrong_accum, "closefile /fontdownload /unexpectedEOF /.error cvx exec } ifelse } repeat%n", 0))
+ return false;
+
+ int extra;
+ if (!read_synthetic_string(reader, wrong_accum, "currentfile %d string readstring { pop } { clear currentfile%n", &extra))
+ return false;
+
+ if (!read_synthetic_string(reader, wrong_accum, "closefile /fontdownload /unexpectedEOF /.error cvx exec } ifelse%n", 0))
+ return false;
+
+ if (!read_synthetic_string(reader, wrong_accum, "restore } if } if%n", 0))
+ return false;
+
+ Type1SubsetReader subreader(&reader, multiplier*multiplicand + extra);
+ Type1Font *synthetic = new Type1Font(subreader);
+ if (!synthetic->ok())
+ delete synthetic;
+ else {
+ _synthetic_item = new Type1IncludedFont(synthetic, unique_id);
+ add_item(_synthetic_item);
+ }
+ return true;
+}
+
+
+void
+Type1Font::undo_synthetic()
+{
+ // A synthetic font doesn't share arbitrary code with its base font; it
+ // shares just the CharStrings dictionary, according to Adobe Type 1 Font
+ // Format. We take advantage of this.
+
+ if (!_synthetic_item)
+ return;
+
+ int mod_ii;
+ for (mod_ii = nitems() - 1; mod_ii >= 0; mod_ii--)
+ if (_items[mod_ii] == _synthetic_item)
+ break;
+ if (mod_ii < 0)
+ return;
+
+ // remove synthetic item and the reference to the included font
+ _items[mod_ii] = new Type1NullItem;
+ if (Type1CopyItem *copy = _items[mod_ii+1]->cast_copy())
+ if (copy->value().find_left("findfont") >= 0) {
+ delete copy;
+ _items[mod_ii+1] = new Type1NullItem;
+ }
+
+ Type1Font *f = _synthetic_item->included_font();
+ // its glyphs are already stored in our _glyphs array
+
+ // copy SubrGroupItem from `f' into `this'
+ Type1SubrGroupItem *oth_subrs = 0, *oth_glyphs = 0;
+ for (int i = 0; i < f->nitems(); i++)
+ if (Type1SubrGroupItem *subr_grp = f->_items[i]->cast_subr_group()) {
+ if (subr_grp->is_subrs())
+ oth_subrs = subr_grp;
+ else
+ oth_glyphs = subr_grp;
+ }
+
+ assert(oth_glyphs != 0);
+
+ for (int i = nitems() - 1; i >= 0; i--)
+ if (Type1SubrGroupItem *subr_grp = _items[i]->cast_subr_group()) {
+ assert(subr_grp->is_subrs());
+ if (oth_subrs)
+ subr_grp->set_end_text(oth_subrs->end_text());
+ shift_indices(i + 1, 1);
+ Type1SubrGroupItem *nsubr = new Type1SubrGroupItem(*oth_glyphs, this);
+ _items[i + 1] = nsubr;
+ break;
+ }
+
+ // delete included font
+ f->_glyphs.clear(); // don't delete glyphs; we've stolen them
+ delete _synthetic_item;
+ _synthetic_item = 0;
+}
+
+
+Type1Charstring *
+Type1Font::subr(int e) const
+{
+ if (e >= 0 && e < _subrs.size() && _subrs[e])
+ return &_subrs[e]->t1cs();
+ else
+ return 0;
+}
+
+PermString
+Type1Font::glyph_name(int i) const
+{
+ if (i >= 0 && i < _glyphs.size() && _glyphs[i])
+ return _glyphs[i]->name();
+ else
+ return PermString();
+}
+
+Type1Charstring *
+Type1Font::glyph(int i) const
+{
+ if (i >= 0 && i < _glyphs.size() && _glyphs[i])
+ return &_glyphs[i]->t1cs();
+ else
+ return 0;
+}
+
+Type1Charstring *
+Type1Font::glyph(PermString name) const
+{
+ int i = _glyph_map[name];
+ if (i >= 0)
+ return &_glyphs[i]->t1cs();
+ else
+ return 0;
+}
+
+
+bool
+Type1Font::set_subr(int e, const Type1Charstring &t1cs, PermString definer)
+{
+ if (e < 0)
+ return false;
+ if (e >= _subrs.size())
+ _subrs.resize(e + 1, (Type1Subr *)0);
+
+ if (!definer) {
+ Type1Subr *pattern_subr = _subrs[e];
+ for (int i = 0; i < _subrs.size() && !pattern_subr; i++)
+ pattern_subr = _subrs[i];
+ if (!pattern_subr)
+ return false;
+ definer = pattern_subr->definer();
+ }
+
+ delete _subrs[e];
+ _subrs[e] = Type1Subr::make_subr(e, t1cs, definer);
+ return true;
+}
+
+bool
+Type1Font::remove_subr(int e)
+{
+ if (e < 0 || e >= _subrs.size())
+ return false;
+ delete _subrs[e];
+ _subrs[e] = 0;
+ return true;
+}
+
+void
+Type1Font::fill_in_subrs()
+{
+ while (_subrs.size() && _subrs.back() == 0)
+ _subrs.pop_back();
+ for (int i = 0; i < _subrs.size(); i++)
+ if (!_subrs[i])
+ set_subr(i, Type1Charstring(String::make_stable("\013", 1)));
+}
+
+void
+Type1Font::renumber_subrs(const Vector<int> &renumbering)
+{
+ Vector<Type1Subr *> old_subrs;
+ old_subrs.swap(_subrs);
+ for (int i = 0; i < old_subrs.size() && i < renumbering.size(); i++) {
+ int r = renumbering[i];
+ Type1Subr *s = old_subrs[i];
+ if (r >= 0 && s)
+ set_subr(r, s->t1cs(), s->definer());
+ else
+ delete s;
+ }
+ for (int i = renumbering.size(); i < old_subrs.size(); i++)
+ delete old_subrs[i];
+}
+
+
+void
+Type1Font::shift_indices(int move_index, int delta)
+{
+ if (delta > 0) {
+ _items.resize(_items.size() + delta, (Type1Item *)0);
+ memmove(&_items[move_index + delta], &_items[move_index],
+ sizeof(Type1Item *) * (_items.size() - move_index - delta));
+
+ for (int i = dFont; i < dLast; i++)
+ if (_index[i] > move_index)
+ _index[i] += delta;
+
+ } else {
+ memmove(&_items[move_index], &_items[move_index - delta],
+ sizeof(Type1Item *) * (_items.size() - (move_index - delta)));
+ _items.resize(_items.size() + delta);
+
+ for (int i = dFont; i < dLast; i++)
+ if (_index[i] >= move_index) {
+ if (_index[i] < move_index - delta)
+ _index[i] = move_index;
+ else
+ _index[i] += delta;
+ }
+ }
+}
+
+Type1Definition *
+Type1Font::ensure(Dict dict, PermString name)
+{
+ assert(_index[dict] >= 0);
+ Type1Definition *def = _dict[dict][name];
+ if (!def) {
+ def = new Type1Definition(name, 0, "def");
+ int move_index = _index[dict];
+ shift_indices(move_index, 1);
+ _items[move_index] = def;
+ set_dict(dict, name, def);
+ }
+ return def;
+}
+
+void
+Type1Font::add_header_comment(const String &comment)
+{
+ int i;
+ for (i = 0; i < _items.size(); i++) {
+ Type1CopyItem *copy = _items[i]->cast_copy();
+ if (!copy || copy->value()[0] != '%')
+ break;
+ }
+ shift_indices(i, 1);
+ _items[i] = new Type1CopyItem(comment);
+}
+
+
+Type1Item *
+Type1Font::dict_size_item(int d) const
+{
+ switch (d) {
+
+ case dF:
+ if (_built && _index[d] > 0)
+ return _items[_index[d] - 1];
+ break;
+
+ case dFI: case dP: case dB:
+ if (_index[d] > 0)
+ return _items[_index[d] - 1];
+ break;
+
+ case dBFI:
+ if (Type1Item *t1i = b_dict("FontInfo"))
+ return t1i;
+ else if (_index[dBFI] > 0)
+ return _items[_index[dBFI] - 1];
+ break;
+
+ case dBP:
+ if (Type1Item *t1i = b_dict("Private"))
+ return t1i;
+ else if (_index[dBP] > 0)
+ return _items[_index[dBP] - 1];
+ break;
+
+ }
+ return 0;
+}
+
+int
+Type1Font::get_dict_size(int d) const
+{
+ Type1Item *item = dict_size_item(d);
+ if (!item)
+ /* nada */;
+ else if (Type1Definition *t1d = item->cast_definition()) {
+ int num;
+ if (strstr(t1d->definer().c_str(), "dict") && t1d->value_int(num))
+ return num;
+ } else if (Type1CopyItem *copy = item->cast_copy()) {
+ String value = copy->value();
+ int pos = value.find_left(" dict");
+ if (pos >= 1 && isdigit((unsigned char) value[pos - 1])) {
+ while (pos >= 1 && isdigit((unsigned char) value[pos - 1]))
+ pos--;
+ return strtol(value.data() + pos, 0, 10);
+ }
+ }
+ return -1;
+}
+
+void
+Type1Font::set_dict_size(int d, int size)
+{
+ Type1Item *item = dict_size_item(d);
+ if (!item)
+ return;
+ if (Type1Definition *t1d = item->cast_definition()) {
+ int num;
+ if (strstr(t1d->definer().c_str(), "dict") && t1d->value_int(num))
+ t1d->set_int(size);
+ } else if (Type1CopyItem *copy = item->cast_copy()) {
+ String value = copy->value();
+ int pos = value.find_left(" dict");
+ if (pos >= 1 && isdigit((unsigned char) value[pos - 1])) {
+ int numpos = pos - 1;
+ while (numpos >= 1 && isdigit((unsigned char) value[numpos - 1]))
+ numpos--;
+ StringAccum accum;
+ accum << value.substring(0, numpos) << size << value.substring(pos);
+ copy->set_value(accum.take_string());
+ }
+ }
+}
+
+void
+Type1Font::write(Type1Writer &w)
+{
+ Type1Definition *lenIV_def = p_dict("lenIV");
+ int lenIV = 4;
+ if (lenIV_def)
+ lenIV_def->value_int(lenIV);
+ w.set_charstring_start(_charstring_definer);
+ w.set_lenIV(lenIV);
+
+ // change dict sizes
+ for (int i = dF; i < dLast; i++)
+ set_dict_size(i, _dict[i].size() + _dict_deltas[i]);
+ // XXX what if dict had nothing, but now has something?
+
+ for (int i = 0; i < _items.size(); i++)
+ _items[i]->gen(w);
+
+ w.flush();
+}
+
+void
+Type1Font::cache_defs() const
+{
+ Type1Definition *t1d = dict("FontName");
+ if (t1d)
+ t1d->value_name(_font_name);
+ _cached_defs = true;
+}
+
+MultipleMasterSpace *
+Type1Font::mmspace() const
+{
+ if (!_cached_mmspace)
+ create_mmspace();
+ return _mmspace;
+}
+
+MultipleMasterSpace *
+Type1Font::create_mmspace(ErrorHandler *errh) const
+{
+ if (_cached_mmspace)
+ return _mmspace;
+ _cached_mmspace = 1;
+
+ Type1Definition *t1d;
+
+ Vector< Vector<double> > master_positions;
+ t1d = fi_dict("BlendDesignPositions");
+ if (!t1d || !t1d->value_numvec_vec(master_positions))
+ return 0;
+
+ int nmasters = master_positions.size();
+ if (nmasters <= 0) {
+ errh->error("bad BlendDesignPositions");
+ return 0;
+ }
+ int naxes = master_positions[0].size();
+ _mmspace = new MultipleMasterSpace(font_name(), naxes, nmasters);
+ _mmspace->set_master_positions(master_positions);
+
+ Vector< Vector<double> > normalize_in, normalize_out;
+ t1d = fi_dict("BlendDesignMap");
+ if (t1d && t1d->value_normalize(normalize_in, normalize_out))
+ _mmspace->set_normalize(normalize_in, normalize_out);
+
+ Vector<PermString> axis_types;
+ t1d = fi_dict("BlendAxisTypes");
+ if (t1d && t1d->value_namevec(axis_types) && axis_types.size() == naxes)
+ for (int a = 0; a < naxes; a++)
+ _mmspace->set_axis_type(a, axis_types[a]);
+
+ int ndv, cdv;
+ Type1Charstring *cs;
+ t1d = p_dict("NDV");
+ if (t1d && t1d->value_int(ndv) && (cs = subr(ndv)))
+ _mmspace->set_ndv(*cs);
+ t1d = p_dict("CDV");
+ if (t1d && t1d->value_int(cdv) && (cs = subr(cdv)))
+ _mmspace->set_cdv(*cs);
+
+ Vector<double> design_vector;
+ t1d = dict("DesignVector");
+ if (t1d && t1d->value_numvec(design_vector))
+ _mmspace->set_design_vector(design_vector);
+
+ Vector<double> weight_vector;
+ t1d = dict("WeightVector");
+ if (t1d && t1d->value_numvec(weight_vector))
+ _mmspace->set_weight_vector(weight_vector);
+
+ if (!_mmspace->check(errh)) {
+ delete _mmspace;
+ _mmspace = 0;
+ }
+ return _mmspace;
+}
+
+void
+Type1Font::uncache_defs()
+{
+ _cached_defs = false;
+}
+
+void
+Type1Font::font_matrix(double matrix[6]) const
+{
+ Vector<double> t1d_matrix;
+ Type1Definition *t1d = dict("FontMatrix");
+ if (t1d && t1d->value_numvec(t1d_matrix) && t1d_matrix.size() == 6)
+ memcpy(&matrix[0], &t1d_matrix[0], sizeof(double) * 6);
+ else {
+ matrix[0] = matrix[3] = 0.001;
+ matrix[1] = matrix[2] = matrix[4] = matrix[5] = 0;
+ }
+}
+
+}
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1fontskel.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1fontskel.cc
new file mode 100644
index 00000000000..e5e48023348
--- /dev/null
+++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1fontskel.cc
@@ -0,0 +1,433 @@
+/* t1fontskel.cc -- Type 1 font skeleton
+ *
+ * Copyright (c) 1998-2012 Eddie Kohler
+ *
+ * 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 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <efont/t1font.hh>
+#include <efont/t1item.hh>
+#include <efont/t1rw.hh>
+#include <efont/t1mm.hh>
+#include <lcdf/error.hh>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+namespace Efont {
+
+static const char *othersubrs_code = "% Copyright (c) 1987-1990 Adobe Systems Incorporated.\n"
+"% All Rights Reserved.\n"
+"% This code to be used for Flex and hint replacement.\n"
+"% Version 1.1\n"
+"/OtherSubrs\n"
+"[systemdict /internaldict known\n"
+"{1183615869 systemdict /internaldict get exec\n"
+"/FlxProc known {save true} {false} ifelse}\n"
+"{userdict /internaldict known not {\n"
+"userdict /internaldict\n"
+"{count 0 eq\n"
+"{/internaldict errordict /invalidaccess get exec} if\n"
+"dup type /integertype ne\n"
+"{/internaldict errordict /invalidaccess get exec} if\n"
+"dup 1183615869 eq\n"
+"{pop 0}\n"
+"{/internaldict errordict /invalidaccess get exec}\n"
+"ifelse\n"
+"}\n"
+"dup 14 get 1 25 dict put\n"
+"bind executeonly put\n"
+"} if\n"
+"1183615869 userdict /internaldict get exec\n"
+"/FlxProc known {save true} {false} ifelse}\n"
+"ifelse\n"
+"[\n"
+"systemdict /internaldict known not\n"
+"{ 100 dict /begin cvx /mtx matrix /def cvx } if\n"
+"systemdict /currentpacking known {currentpacking true setpacking} if\n"
+"{\n"
+"systemdict /internaldict known {\n"
+"1183615869 systemdict /internaldict get exec\n"
+"dup /$FlxDict known not {\n"
+"dup dup length exch maxlength eq\n"
+"{ pop userdict dup /$FlxDict known not\n"
+"{ 100 dict begin /mtx matrix def\n"
+"\n"
+"dup /$FlxDict currentdict put end } if }\n"
+"{ 100 dict begin /mtx matrix def\n"
+"dup /$FlxDict currentdict put end }\n"
+"ifelse\n"
+"} if\n"
+"/$FlxDict get begin\n"
+"} if\n"
+"grestore\n"
+"/exdef {exch def} def\n"
+"/dmin exch abs 100 div def\n"
+"/epX exdef /epY exdef\n"
+"/c4y2 exdef /c4x2 exdef /c4y1 exdef /c4x1 exdef /c4y0 exdef /c4x0 exdef\n"
+"/c3y2 exdef /c3x2 exdef /c3y1 exdef /c3x1 exdef /c3y0 exdef /c3x0 exdef\n"
+"/c1y2 exdef /c1x2 exdef /c2x2 c4x2 def /c2y2 c4y2 def\n"
+"/yflag c1y2 c3y2 sub abs c1x2 c3x2 sub abs gt def\n"
+"/PickCoords {\n"
+"{c1x0 c1y0 c1x1 c1y1 c1x2 c1y2 c2x0 c2y0 c2x1 c2y1 c2x2 c2y2 }\n"
+"{c3x0 c3y0 c3x1 c3y1 c3x2 c3y2 c4x0 c4y0 c4x1 c4y1 c4x2 c4y2 }\n"
+"ifelse\n"
+"/y5 exdef /x5 exdef /y4 exdef /x4 exdef /y3 exdef /x3 exdef\n"
+"/y2 exdef /x2 exdef /y1 exdef /x1 exdef /y0 exdef /x0 exdef\n"
+"} def\n"
+"mtx currentmatrix pop\n"
+"mtx 0 get abs .00001 lt mtx 3 get abs .00001 lt or\n"
+"{/flipXY -1 def }\n"
+"{mtx 1 get abs .00001 lt mtx 2 get abs .00001 lt or\n"
+"{/flipXY 1 def }\n"
+"{/flipXY 0 def }\n"
+"ifelse }\n"
+"ifelse\n"
+"/erosion 1 def\n"
+"systemdict /internaldict known {\n"
+"1183615869 systemdict /internaldict get exec dup\n"
+"/erosion known\n"
+"{/erosion get /erosion exch def}\n"
+"{pop}\n"
+"ifelse\n"
+"} if\n"
+"yflag\n"
+"{flipXY 0 eq c3y2 c4y2 eq or\n"
+"{false PickCoords }\n"
+"{/shrink c3y2 c4y2 eq\n"
+"{0}{c1y2 c4y2 sub c3y2 c4y2 sub div abs} ifelse def\n"
+"/yshrink {c4y2 sub shrink mul c4y2 add} def\n"
+"/c1y0 c3y0 yshrink def /c1y1 c3y1 yshrink def\n"
+"/c2y0 c4y0 yshrink def /c2y1 c4y1 yshrink def\n"
+"/c1x0 c3x0 def /c1x1 c3x1 def /c2x0 c4x0 def /c2x1 c4x1 def\n"
+"/dY 0 c3y2 c1y2 sub round\n"
+"dtransform flipXY 1 eq {exch} if pop abs def\n"
+"dY dmin lt PickCoords\n"
+"y2 c1y2 sub abs 0.001 gt {\n"
+"c1x2 c1y2 transform flipXY 1 eq {exch} if\n"
+"/cx exch def /cy exch def\n"
+"/dY 0 y2 c1y2 sub round dtransform flipXY 1 eq {exch}\n"
+"if pop def\n"
+"dY round dup 0 ne\n"
+"{/dY exdef }\n"
+"{pop dY 0 lt {-1}{1} ifelse /dY exdef }\n"
+"ifelse\n"
+"/erode PaintType 2 ne erosion 0.5 ge and def\n"
+"erode {/cy cy 0.5 sub def} if\n"
+"/ey cy dY add def\n"
+"/ey ey ceiling ey sub ey floor add def\n"
+"erode {/ey ey 0.5 add def} if\n"
+"ey cx flipXY 1 eq {exch} if itransform exch pop\n"
+"y2 sub /eShift exch def\n"
+"/y1 y1 eShift add def /y2 y2 eShift add def /y3 y3\n"
+"eShift add def\n"
+"} if\n"
+"} ifelse\n"
+"}\n"
+"{flipXY 0 eq c3x2 c4x2 eq or\n"
+"{false PickCoords }\n"
+"{/shrink c3x2 c4x2 eq\n"
+"{0}{c1x2 c4x2 sub c3x2 c4x2 sub div abs} ifelse def\n"
+"/xshrink {c4x2 sub shrink mul c4x2 add} def\n"
+"/c1x0 c3x0 xshrink def /c1x1 c3x1 xshrink def\n"
+"/c2x0 c4x0 xshrink def /c2x1 c4x1 xshrink def\n"
+"/c1y0 c3y0 def /c1y1 c3y1 def /c2y0 c4y0 def /c2y1 c4y1 def\n"
+"/dX c3x2 c1x2 sub round 0 dtransform\n"
+"flipXY -1 eq {exch} if pop abs def\n"
+"dX dmin lt PickCoords\n"
+"x2 c1x2 sub abs 0.001 gt {\n"
+"c1x2 c1y2 transform flipXY -1 eq {exch} if\n"
+"/cy exch def /cx exch def\n"
+"/dX x2 c1x2 sub round 0 dtransform flipXY -1 eq {exch} if pop def\n"
+"dX round dup 0 ne\n"
+"{/dX exdef }\n"
+"{pop dX 0 lt {-1}{1} ifelse /dX exdef }\n"
+"ifelse\n"
+"/erode PaintType 2 ne erosion .5 ge and def\n"
+"erode {/cx cx .5 sub def} if\n"
+"/ex cx dX add def\n"
+"/ex ex ceiling ex sub ex floor add def\n"
+"erode {/ex ex .5 add def} if\n"
+"ex cy flipXY -1 eq {exch} if itransform pop\n"
+"x2 sub /eShift exch def\n"
+"/x1 x1 eShift add def /x2 x2 eShift add def /x3 x3 eShift add def\n"
+"} if\n"
+"} ifelse\n"
+"} ifelse\n"
+"x2 x5 eq y2 y5 eq or\n"
+"{ x5 y5 lineto }\n"
+"{ x0 y0 x1 y1 x2 y2 curveto\n"
+"x3 y3 x4 y4 x5 y5 curveto }\n"
+"ifelse\n"
+"epY epX\n"
+"}\n"
+"systemdict /currentpacking known {exch setpacking} if\n"
+"/exec cvx /end cvx ] cvx\n"
+"executeonly\n"
+"exch\n"
+"{pop true exch restore}\n"
+"{\n"
+"systemdict /internaldict known not\n"
+"{1183615869 userdict /internaldict get exec\n"
+"exch /FlxProc exch put true}\n"
+"{1183615869 systemdict /internaldict get exec\n"
+"dup length exch maxlength eq\n"
+"{false}\n"
+"{1183615869 systemdict /internaldict get exec\n"
+"exch /FlxProc exch put true}\n"
+"ifelse}\n"
+"ifelse}\n"
+"ifelse\n"
+"{systemdict /internaldict known\n"
+"{{1183615869 systemdict /internaldict get exec /FlxProc get exec}}\n"
+"{{1183615869 userdict /internaldict get exec /FlxProc get exec}}\n"
+"ifelse executeonly\n"
+"} if\n"
+"{gsave currentpoint newpath moveto} executeonly\n"
+"{currentpoint grestore gsave currentpoint newpath moveto}\n"
+"executeonly\n"
+"{systemdict /internaldict known not\n"
+"{pop 3}\n"
+"{1183615869 systemdict /internaldict get exec\n"
+"dup /startlock known\n"
+"{/startlock get exec}\n"
+"{dup /strtlck known\n"
+"{/strtlck get exec}\n"
+"{pop 3}\n"
+"ifelse}\n"
+"ifelse}\n"
+"ifelse\n"
+"} executeonly\n"
+"] noaccess def";
+
+
+Type1Font *
+Type1Font::skeleton_make(PermString font_name, const String &version)
+{
+ Type1Font *output = new Type1Font(font_name);
+
+ // %!PS-Adobe-Font comment
+ StringAccum sa;
+ sa << "%!PS-AdobeFont-1.0: " << font_name;
+ if (version)
+ sa << ' ' << version;
+ output->add_item(new Type1CopyItem(sa.take_string()));
+
+ output->_dict_deltas[dF] = 3; // Private, FontInfo, Encoding
+ output->_dict_deltas[dP] = 3; // OtherSubrs, Subrs, CharStrings
+
+ return output;
+}
+
+void
+Type1Font::skeleton_comments_end()
+{
+ // count members of font dictionary
+ add_definition(dF, new Type1Definition("FontName", "/" + String(_font_name), "def"));
+}
+
+void
+Type1Font::skeleton_fontinfo_end()
+{
+ if (first_dict_item(Type1Font::dFI) >= 0)
+ add_item(new Type1CopyItem("end readonly def"));
+ else
+ add_item(new Type1CopyItem("% no FontInfo dict"));
+}
+
+void
+Type1Font::skeleton_fontdict_end()
+{
+ // switch to eexec
+ add_item(new Type1CopyItem("currentdict end"));
+ add_item(new Type1EexecItem(true));
+
+ // Private dictionary
+ add_definition(Type1Font::dP, Type1Definition::make_literal("-|", "{string currentfile exch readstring pop}", "executeonly def"));
+ set_charstring_definer(" -| ");
+ add_definition(Type1Font::dP, Type1Definition::make_literal("|-", "{noaccess def}", "executeonly def"));
+ add_definition(Type1Font::dP, Type1Definition::make_literal("|", "{noaccess put}", "executeonly def"));
+}
+
+void
+Type1Font::skeleton_private_end()
+{
+ add_item(new Type1CopyItem(othersubrs_code));
+
+ // Subrs
+ add_item(new Type1SubrGroupItem(this, true, "/Subrs 0 array"));
+ add_item(new Type1CopyItem("|-"));
+
+ // CharStrings
+ add_item(new Type1SubrGroupItem(this, false, "2 index /CharStrings 0 dict dup begin"));
+
+ // completion
+ add_item(new Type1CopyItem("end\n\
+end\n\
+readonly put\n\
+noaccess put\n\
+dup /FontName get exch definefont pop\n\
+mark currentfile closefile"));
+ add_item(new Type1EexecItem(false));
+ add_item(new Type1CopyItem("\
+0000000000000000000000000000000000000000000000000000000000000000\n\
+0000000000000000000000000000000000000000000000000000000000000000\n\
+0000000000000000000000000000000000000000000000000000000000000000\n\
+0000000000000000000000000000000000000000000000000000000000000000\n\
+0000000000000000000000000000000000000000000000000000000000000000\n\
+0000000000000000000000000000000000000000000000000000000000000000\n\
+0000000000000000000000000000000000000000000000000000000000000000\n\
+0000000000000000000000000000000000000000000000000000000000000000\n\
+cleartomark"));
+}
+
+void
+Type1Font::skeleton_common_subrs()
+{
+ // - first four Subrs have fixed definitions
+ // - 0: "3 0 callothersubr pop pop setcurrentpoint return"
+ set_subr(0, Type1Charstring(String::make_stable("\216\213\014\020\014\021\014\021\014\041\013", 11)), " |");
+ // - 1: "0 1 callothersubr return"
+ set_subr(1, Type1Charstring(String::make_stable("\213\214\014\020\013", 5)), " |");
+ // - 2: "0 2 callothersubr return"
+ set_subr(2, Type1Charstring(String::make_stable("\213\215\014\020\013", 5)), " |");
+ // - 3: "return"
+ set_subr(3, Type1Charstring(String::make_stable("\013", 1)), " |");
+ // - 4: "1 3 callothersubr pop callsubr return"
+ set_subr(4, Type1Charstring(String::make_stable("\214\216\014\020\014\021\012\013", 8)), " |");
+}
+
+
+static void
+add_number_def(Type1Font *output, int dict, PermString name, const Type1Font *font)
+{
+ double v;
+ if (Type1Definition *t1d = font->dict(dict, name))
+ if (t1d->value_num(v))
+ output->add_definition(dict, Type1Definition::make(name, v, "def"));
+}
+
+static void
+add_copy_def(Type1Font *output, int dict, PermString name, const Type1Font *font, const char *definer = "def")
+{
+ if (Type1Definition *t1d = font->dict(dict, name))
+ output->add_definition(dict, Type1Definition::make_literal(name, t1d->value(), definer));
+}
+
+static String
+font_dict_string(const Type1Font *font, int dict, PermString name)
+{
+ String s;
+ if (Type1Definition *d = font->dict(dict, name))
+ if (d->value_string(s))
+ return s;
+ return String();
+}
+
+Type1Font *
+Type1Font::skeleton_make_copy(const Type1Font *font, PermString font_name, const Vector<double> *xuid_extension)
+{
+ String version = font_dict_string(font, dFI, "version");
+ Type1Font *output = skeleton_make(font_name, version);
+
+ // other comments from font header
+ for (int i = 0; i < font->nitems(); i++)
+ if (Type1CopyItem *c = font->item(i)->cast_copy()) {
+ if (c->length() > 1 && c->value()[0] == '%') {
+ if (c->value()[1] != '!')
+ output->add_item(new Type1CopyItem(c->value()));
+ } else
+ break;
+ } else
+ break;
+
+ output->skeleton_comments_end();
+
+ // FontInfo dictionary
+ if (version)
+ output->add_definition(dFI, Type1Definition::make_string("version", version, "readonly def"));
+ if (String s = font_dict_string(font, dFI, "Notice"))
+ output->add_definition(dFI, Type1Definition::make_string("Notice", s, "readonly def"));
+ if (String s = font_dict_string(font, dFI, "Copyright"))
+ output->add_definition(dFI, Type1Definition::make_string("Copyright", s, "readonly def"));
+ if (String s = font_dict_string(font, dFI, "FullName"))
+ output->add_definition(dFI, Type1Definition::make_string("FullName", s, "readonly def"));
+ if (String s = font_dict_string(font, dFI, "FamilyName"))
+ output->add_definition(dFI, Type1Definition::make_string("FamilyName", s, "readonly def"));
+ if (String s = font_dict_string(font, dFI, "Weight"))
+ output->add_definition(dFI, Type1Definition::make_string("Weight", s, "readonly def"));
+ if (Type1Definition *t1d = font->fi_dict("isFixedPitch")) {
+ bool v;
+ if (t1d->value_bool(v))
+ output->add_definition(dFI, Type1Definition::make_literal("isFixedPitch", (v ? "true" : "false"), "def"));
+ }
+ add_number_def(output, dFI, "ItalicAngle", font);
+ add_number_def(output, dFI, "UnderlinePosition", font);
+ add_number_def(output, dFI, "UnderlineThickness", font);
+ output->skeleton_fontinfo_end();
+
+ // Encoding, other font dictionary entries
+ output->add_type1_encoding(new Type1Encoding(*font->type1_encoding()));
+ add_number_def(output, dF, "PaintType", font);
+ add_number_def(output, dF, "FontType", font);
+ add_copy_def(output, dF, "FontMatrix", font, "readonly def");
+ add_number_def(output, dF, "StrokeWidth", font);
+ if (!xuid_extension)
+ add_number_def(output, dF, "UniqueID", font);
+ add_copy_def(output, dF, "XUID", font, "readonly def");
+ if (xuid_extension) {
+ Vector<double> xuid;
+ if (Type1Definition *xuid_def = output->dict("XUID"))
+ xuid_def->value_numvec(xuid);
+ if (!xuid.size()) {
+ Type1Definition *uid_def = font->dict("UniqueID");
+ int uid;
+ if (uid_def && uid_def->value_int(uid)) {
+ xuid.push_back(1);
+ xuid.push_back(uid);
+ }
+ }
+ if (xuid.size()) {
+ for (int i = 0; i < xuid_extension->size(); i++)
+ xuid.push_back((*xuid_extension)[i]);
+ Type1Definition *xuid_def = output->ensure(dF, "XUID");
+ xuid_def->set_numvec(xuid);
+ }
+ }
+ add_copy_def(output, dF, "FontBBox", font, "readonly def");
+ output->skeleton_fontdict_end();
+
+ // Private dictionary
+ add_copy_def(output, dP, "BlueValues", font);
+ add_copy_def(output, dP, "OtherBlues", font);
+ add_copy_def(output, dP, "FamilyBlues", font);
+ add_copy_def(output, dP, "FamilyOtherBlues", font);
+ add_number_def(output, dP, "BlueScale", font);
+ add_number_def(output, dP, "BlueShift", font);
+ add_number_def(output, dP, "BlueFuzz", font);
+ add_copy_def(output, dP, "StdHW", font);
+ add_copy_def(output, dP, "StdVW", font);
+ add_copy_def(output, dP, "StemSnapH", font);
+ add_copy_def(output, dP, "StemSnapV", font);
+ add_copy_def(output, dP, "ForceBold", font);
+ add_number_def(output, dP, "LanguageGroup", font);
+ add_number_def(output, dP, "ExpansionFactor", font);
+ if (!xuid_extension)
+ add_number_def(output, dP, "UniqueID", font);
+ output->add_definition(dP, Type1Definition::make_literal("MinFeature", "{16 16}", "|-"));
+ output->add_definition(dP, Type1Definition::make_literal("password", "5839", "def"));
+ output->add_definition(dP, Type1Definition::make_literal("lenIV", "0", "def"));
+ output->skeleton_private_end();
+
+ return output;
+}
+
+}
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1interp.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1interp.cc
new file mode 100644
index 00000000000..7b607bb407d
--- /dev/null
+++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1interp.cc
@@ -0,0 +1,1376 @@
+// -*- related-file-name: "../include/efont/t1interp.hh" -*-
+
+/* t1interp.{cc,hh} -- Type 1/2 charstring interpretation
+ *
+ * Copyright (c) 1998-2012 Eddie Kohler
+ *
+ * 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 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <efont/t1interp.hh>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#ifdef WIN32
+# define random() rand()
+#endif
+
+#define CHECK_STACK(numargs) do { if (size() < numargs) return error(errUnderflow, cmd); } while (0)
+#define CHECK_STATE() do { if (_state < S_IPATH) return error(errOrdering, cmd); } while (0)
+#define CHECK_PATH_START() do { _state = S_PATH; } while (0)
+#define CHECK_PATH_END() do { if (_state == S_PATH) { act_closepath(cmd); } _state = S_IPATH; } while (0)
+
+#ifndef static_assert
+# define static_assert(c) switch (c) case 0: case (c):
+#endif
+
+namespace Efont {
+
+static const char * const error_formats[] = {
+ "charstring OK", // errOK
+ "charstring internal error in '%C'", // errInternal
+ "charstring commands past end", // errRunoff
+ "charstring command '%C' unimplemented", // errUnimplemented
+ "charstring stack overflow", // errOverflow
+ "charstring stack underflow in '%C'", // errUnderflow
+ "charstring bad vector operation in '%C'", // errVector
+ "charstring bad value in '%C'", // errValue
+ "charstring bad subroutine number %d", // errSubr
+ "charstring bad glyph number '%d'", // errGlyph
+ "charstring no current point in '%C'", // errCurrentPoint
+ "charstring flex error", // errFlex
+ "charstring multiple master error in '%C'", // errMultipleMaster
+ "charstring open stroke", // errOpenStroke
+ "charstring late sidebearing command '%C'", // errLateSidebearing
+ "charstring bad othersubr number %d", // errOthersubr
+ "charstring ordering constraints violated at '%C'", // errOrdering
+ "charstring inappropriate hintmask", // errHintmask
+ "charstring subrs nested too deep at '%d'" // errSubrDepth
+};
+
+double CharstringInterp::double_for_error;
+
+
+CharstringInterp::CharstringInterp()
+ : _error(errOK), _careful(false), _sp(0), _ps_sp(0),
+ _scratch_vector(SCRATCH_SIZE, 0), _program(0)
+{
+}
+
+CharstringInterp::CharstringInterp(const Vector<double> &weight_vector)
+ : _error(errOK), _careful(false), _sp(0), _ps_sp(0),
+ _weight_vector(weight_vector),
+ _scratch_vector(SCRATCH_SIZE, 0), _program(0)
+{
+}
+
+void
+CharstringInterp::initialize()
+{
+ clear();
+ ps_clear();
+ _lsb = _cp = _seac_origin = Point(0, 0);
+ _state = S_INITIAL;
+ _flex = false;
+ _t2nhints = 0;
+ _subr_depth = 0;
+ _done = false;
+ _error = errOK;
+}
+
+bool
+CharstringInterp::interpret(const CharstringProgram *program, const Charstring *cs)
+{
+ if (cs) {
+ initialize();
+ _program = program;
+ cs->process(*this);
+ return _error == errOK;
+ } else
+ return error(errGlyph, 0);
+}
+
+bool
+CharstringInterp::error(int err, int error_data)
+{
+ _error = err;
+ _error_data = error_data;
+ return false;
+}
+
+String
+CharstringInterp::error_string(int error, int error_data)
+{
+ static_assert(-errLastError == (sizeof(error_formats) / sizeof(error_formats[0])) - 1);
+ if (error >= 0)
+ return error_formats[0];
+ else if (error < errLastError)
+ return "charstring unknown error number " + String(error);
+ String format = error_formats[-error];
+ int percent = format.find_left('%');
+ if (percent >= 0 && format[percent + 1] == 'C')
+ return format.substring(0, percent) + Charstring::command_name(error_data) + format.substring(percent + 2);
+ else if (percent >= 0 && format[percent + 1] == 'd')
+ return format.substring(0, percent) + String(error_data) + format.substring(percent + 2);
+ else
+ return format;
+}
+
+bool
+CharstringInterp::number(double v)
+{
+ push(v);
+ return true;
+}
+
+void
+CharstringInterp::fetch_weight_vector()
+{
+ if (_program)
+ if (Vector<double> *wv = _program->mm_vector(CharstringProgram::VEC_WEIGHT, false))
+ _weight_vector = *wv;
+}
+
+bool
+CharstringInterp::vector_command(int cmd)
+{
+ CharstringProgram::VectorType which_vector;
+ int vectoroff, offset, num, i;
+ Vector<double> *v = 0;
+
+ switch (cmd) {
+
+ case Cs::cPut:
+ CHECK_STACK(2);
+ offset = (int)top(0);
+ vec(&_scratch_vector, offset) = top(1);
+ pop(2);
+ break;
+
+ case Cs::cGet:
+ CHECK_STACK(1);
+ offset = (int)top();
+ top() = vec(&_scratch_vector, offset);
+ break;
+
+ case Cs::cStore:
+ CHECK_STACK(4);
+ which_vector = (CharstringProgram::VectorType)((int)top(3));
+ vectoroff = (int)top(2);
+ offset = (int)top(1);
+ num = (int)top(0);
+ pop(4);
+
+ if (!_program)
+ return error(errVector, cmd);
+ v = _program->mm_vector(which_vector, true);
+ if (!v)
+ return error(errVector, cmd);
+
+ for (i = 0; i < num; i++, offset++, vectoroff++)
+ vec(v, vectoroff) = vec(&_scratch_vector, offset);
+ // erase our weight vector if the global weight vector has changed
+ if (which_vector == CharstringProgram::VEC_WEIGHT)
+ _weight_vector.clear();
+ break;
+
+ case Cs::cLoad:
+ CHECK_STACK(3);
+ which_vector = (CharstringProgram::VectorType)((int)top(2));
+ offset = (int)top(1);
+ num = (int)top(0);
+ pop(3);
+
+ if (!_program)
+ return error(errVector, cmd);
+ v = _program->mm_vector(which_vector, false);
+ // use our weight vector if appropriate
+ if (!v && which_vector == CharstringProgram::VEC_WEIGHT && _weight_vector.size())
+ v = &_weight_vector;
+ if (!v)
+ return error(errVector, cmd);
+
+ for (i = 0; i < num; i++, offset++)
+ vec(&_scratch_vector, offset) = vec(v, i);
+ break;
+
+ default:
+ return error(errUnimplemented, cmd);
+
+ }
+
+ return true;
+}
+
+bool
+CharstringInterp::blend_command()
+{
+ const int cmd = Cs::cBlend;
+ CHECK_STACK(1);
+ int nargs = (int)pop();
+
+ ensure_weight_vector();
+ if (!_weight_vector.size())
+ return error(errVector, cmd);
+
+ int nmasters = _weight_vector.size();
+ CHECK_STACK(nargs * nmasters);
+
+ int base = _sp - nargs * nmasters;
+ int off = base + nargs;
+ for (int j = 0; j < nargs; j++) {
+ double &val = _s[base + j];
+ for (int i = 1; i < nmasters; i++, off++)
+ val += _weight_vector.at_u(i) * _s[off];
+ }
+
+ pop(nargs * (nmasters - 1));
+ return true;
+}
+
+bool
+CharstringInterp::roll_command()
+{
+ const int cmd = Cs::cRoll;
+ CHECK_STACK(2);
+ int amount = (int)pop();
+ int n = (int)pop();
+ if (n <= 0)
+ return error(errValue, cmd);
+ CHECK_STACK(n);
+
+ int base = _sp - n;
+ while (amount < 0)
+ amount += n;
+
+ int i;
+ double copy_stack[STACK_SIZE];
+ for (i = 0; i < n; i++)
+ copy_stack[i] = _s[ base + (i+amount) % n ];
+ for (i = 0; i < n; i++)
+ _s[base + i] = copy_stack[i];
+
+ return true;
+}
+
+bool
+CharstringInterp::arith_command(int cmd)
+{
+ int i;
+ double d;
+
+ switch (cmd) {
+
+ case Cs::cBlend:
+ return blend_command();
+
+ case Cs::cAbs:
+ CHECK_STACK(1);
+ if (top() < 0)
+ top() = -top();
+ break;
+
+ case Cs::cAdd:
+ CHECK_STACK(1);
+ d = pop();
+ top() += d;
+ break;
+
+ case Cs::cSub:
+ CHECK_STACK(1);
+ d = pop();
+ top() -= d;
+ break;
+
+ case Cs::cDiv:
+ CHECK_STACK(2);
+ d = pop();
+ top() /= d;
+ break;
+
+ case Cs::cNeg:
+ CHECK_STACK(1);
+ top() = -top();
+ break;
+
+ case Cs::cRandom: {
+ double d;
+ do {
+ d = random() / ((double)RAND_MAX);
+ } while (d == 0);
+ push(d);
+ break;
+ }
+
+ case Cs::cMul:
+ CHECK_STACK(2);
+ d = pop();
+ top() *= d;
+ break;
+
+ case Cs::cSqrt:
+ CHECK_STACK(1);
+ if (top() < 0)
+ return error(errValue, cmd);
+ top() = sqrt(top());
+ break;
+
+ case Cs::cDrop:
+ CHECK_STACK(1);
+ pop();
+ break;
+
+ case Cs::cExch:
+ CHECK_STACK(2);
+ d = top(0);
+ top(0) = top(1);
+ top(1) = d;
+ break;
+
+ case Cs::cIndex:
+ CHECK_STACK(1);
+ i = (int)top();
+ if (i < 0)
+ return error(errValue, cmd);
+ CHECK_STACK(i + 2);
+ top() = top(i+1);
+ break;
+
+ case Cs::cRoll:
+ return roll_command();
+
+ case Cs::cDup:
+ CHECK_STACK(1);
+ push(top());
+ break;
+
+ case Cs::cAnd:
+ CHECK_STACK(2);
+ d = pop();
+ top() = (top() != 0) && (d != 0);
+ break;
+
+ case Cs::cOr:
+ CHECK_STACK(2);
+ d = pop();
+ top() = (top() != 0) || (d != 0);
+ break;
+
+ case Cs::cNot:
+ CHECK_STACK(1);
+ top() = (top() == 0);
+ break;
+
+ case Cs::cEq:
+ CHECK_STACK(2);
+ d = pop();
+ top() = (top() == d);
+ break;
+
+ case Cs::cIfelse:
+ CHECK_STACK(4);
+ if (top(1) > top(0))
+ top(3) = top(2);
+ pop(3);
+ break;
+
+ case Cs::cPop:
+ if (ps_size() < 1)
+ return error(errUnderflow, cmd);
+ push(ps_pop());
+ break;
+
+ case 15:
+ // this command is found with no explanation in JansonText-Roman
+ CHECK_STACK(2);
+ pop(2);
+ return true;
+
+ default:
+ return error(errUnimplemented, cmd);
+
+ }
+
+ return true;
+}
+
+bool
+CharstringInterp::callsubr_command()
+{
+ const int cmd = Cs::cCallsubr;
+ CHECK_STACK(1);
+ int which = (int)pop();
+
+ Charstring *subr_cs = get_subr(which);
+ if (!subr_cs)
+ return error(errSubr, which);
+
+ if (_subr_depth >= MAX_SUBR_DEPTH)
+ return error(errSubrDepth, which);
+ _subr_depth++;
+
+ subr_cs->process(*this);
+
+ _subr_depth--;
+ if (_error != errOK)
+ return false;
+ return !done();
+}
+
+bool
+CharstringInterp::callgsubr_command()
+{
+ const int cmd = Cs::cCallgsubr;
+ CHECK_STACK(1);
+ int which = (int)pop();
+
+ Charstring *subr_cs = get_gsubr(which);
+ if (!subr_cs)
+ return error(errSubr, which);
+
+ if (_subr_depth >= MAX_SUBR_DEPTH)
+ return error(errSubrDepth, which);
+ _subr_depth++;
+
+ subr_cs->process(*this);
+
+ _subr_depth--;
+ if (_error != errOK)
+ return false;
+ return !done();
+}
+
+bool
+CharstringInterp::mm_command(int command, int on_stack)
+{
+ ensure_weight_vector();
+ if (!_weight_vector.size())
+ return error(errVector, command);
+
+ int nargs;
+ switch (command) {
+ case Cs::othcMM1: nargs = 1; break;
+ case Cs::othcMM2: nargs = 2; break;
+ case Cs::othcMM3: nargs = 3; break;
+ case Cs::othcMM4: nargs = 4; break;
+ case Cs::othcMM6: nargs = 6; break;
+ default: return error(errInternal, command);
+ }
+
+ int nmasters = _weight_vector.size();
+ if (size() < nargs * nmasters
+ || on_stack != nargs * nmasters)
+ return error(errMultipleMaster, command);
+
+ int base = size() - on_stack;
+
+ int off = base + nargs;
+ for (int j = 0; j < nargs; j++) {
+ double &val = at(base + j);
+ for (int i = 1; i < nmasters; i++, off++)
+ val += _weight_vector.at_u(i) * at(off);
+ }
+
+ for (int i = nargs - 1; i >= 0; i--)
+ ps_push(at(base + i));
+
+ pop(on_stack);
+ return true;
+}
+
+bool
+CharstringInterp::itc_command(int command, int on_stack)
+{
+ ensure_weight_vector();
+ if (!_weight_vector.size())
+ return error(errVector, command);
+
+ int base = size() - on_stack;
+ switch (command) {
+
+ case Cs::othcITC_load: {
+ if (on_stack != 1)
+ return error(errOthersubr, command);
+ int offset = (int)at(base);
+ for (int i = 0; i < _weight_vector.size(); i++)
+ vec(&_scratch_vector, offset+i) = _weight_vector.at_u(i);
+ break;
+ }
+
+ case Cs::othcITC_put: {
+ if (on_stack != 2)
+ return error(errOthersubr, command);
+ int offset = (int)at(base+1);
+ vec(&_scratch_vector, offset) = at(base);
+ break;
+ }
+
+ case Cs::othcITC_get: {
+ if (on_stack != 1)
+ return error(errOthersubr, command);
+ int offset = (int)at(base);
+ ps_push(vec(&_scratch_vector, offset));
+ break;
+ }
+
+ case Cs::othcITC_add: {
+ if (on_stack != 2)
+ return error(errOthersubr, command);
+ ps_push(at(base) + at(base+1));
+ break;
+ }
+
+ case Cs::othcITC_sub: {
+ if (on_stack != 2)
+ return error(errOthersubr, command);
+ ps_push(at(base) - at(base+1));
+ break;
+ }
+
+ case Cs::othcITC_mul: {
+ if (on_stack != 2)
+ return error(errOthersubr, command);
+ ps_push(at(base) * at(base+1));
+ break;
+ }
+
+ case Cs::othcITC_div: {
+ if (on_stack != 2)
+ return error(errOthersubr, command);
+ ps_push(at(base) / at(base+1));
+ break;
+ }
+
+ case Cs::othcITC_ifelse: {
+ if (on_stack != 4)
+ return error(errOthersubr, command);
+ if (at(base+2) <= at(base+3))
+ ps_push(at(base));
+ else
+ ps_push(at(base+1));
+ break;
+ }
+
+ default:
+ return error(errOthersubr, command);
+
+ }
+
+ pop(on_stack);
+ return true;
+}
+
+
+inline void
+CharstringInterp::actp_rmoveto(int /*cmd*/, double dx, double dy)
+{
+ _cp.shift(dx, dy);
+}
+
+inline void
+CharstringInterp::actp_rlineto(int cmd, double dx, double dy)
+{
+ Point p0(_cp);
+ _cp.shift(dx, dy);
+ act_line(cmd, p0, _cp);
+}
+
+void
+CharstringInterp::actp_rrcurveto(int cmd, double dx1, double dy1, double dx2, double dy2, double dx3, double dy3)
+{
+ Point p0(_cp);
+ Point p1(p0, dx1, dy1);
+ Point p2(p1, dx2, dy2);
+ _cp = p2.shifted(dx3, dy3);
+ act_curve(cmd, p0, p1, p2, _cp);
+}
+
+void
+CharstringInterp::actp_rrflex(int cmd, double dx1, double dy1, double dx2, double dy2, double dx3, double dy3, double dx4, double dy4, double dx5, double dy5, double dx6, double dy6, double flex_depth)
+{
+ Point p0(_cp);
+ Point p1(p0, dx1, dy1);
+ Point p2(p1, dx2, dy2);
+ Point p3_4(p2, dx3, dy3);
+ Point p5(p3_4, dx4, dy4);
+ Point p6(p5, dx5, dy5);
+ _cp = p6.shifted(dx6, dy6);
+ act_flex(cmd, p0, p1, p2, p3_4, p5, p6, _cp, flex_depth);
+}
+
+
+bool
+CharstringInterp::callothersubr_command(int othersubrnum, int n)
+{
+ switch (othersubrnum) {
+
+ case Cs::othcFlexend:
+ if (n != 3)
+ goto unknown;
+ if (!_flex || ps_size() != 16)
+ return error(errFlex);
+ CHECK_PATH_START();
+ act_flex(Cs::cCallothersubr, Point(ps_at(0), ps_at(1)),
+ Point(ps_at(4), ps_at(5)), Point(ps_at(6), ps_at(7)),
+ Point(ps_at(8), ps_at(9)), Point(ps_at(10), ps_at(11)),
+ Point(ps_at(12), ps_at(13)), Point(ps_at(14), ps_at(15)),
+ top(2));
+ ps_clear();
+ ps_push(top(0));
+ ps_push(top(1));
+ _flex = false;
+ _state = S_PATH;
+ break;
+
+ case Cs::othcFlexbegin:
+ if (n != 0)
+ goto unknown;
+ if (_flex)
+ return error(errFlex);
+ ps_clear();
+ ps_push(_cp.x);
+ ps_push(_cp.y);
+ _flex = true;
+ _state = S_IPATH;
+ break;
+
+ case Cs::othcFlexmiddle:
+ if (n != 0)
+ goto unknown;
+ if (!_flex)
+ return error(errFlex);
+ ps_push(_cp.x);
+ ps_push(_cp.y);
+ break;
+
+ case Cs::othcReplacehints:
+ if (n != 1)
+ goto unknown;
+ ps_clear();
+ ps_push(top());
+ break;
+
+ case Cs::othcMM1:
+ case Cs::othcMM2:
+ case Cs::othcMM3:
+ case Cs::othcMM4:
+ case Cs::othcMM6:
+ return mm_command(othersubrnum, n);
+
+ case Cs::othcITC_load:
+ case Cs::othcITC_add:
+ case Cs::othcITC_sub:
+ case Cs::othcITC_mul:
+ case Cs::othcITC_div:
+ case Cs::othcITC_put:
+ case Cs::othcITC_get:
+ case Cs::othcITC_unknown:
+ case Cs::othcITC_ifelse:
+ case Cs::othcITC_random:
+ return itc_command(othersubrnum, n);
+
+ default: // unknown
+ unknown:
+ ps_clear();
+ for (int i = 0; i < n; i++)
+ ps_push(top(i));
+ break;
+
+ }
+
+ pop(n);
+ return true;
+}
+
+bool
+CharstringInterp::type1_command(int cmd)
+{
+ switch (cmd) {
+
+ case Cs::cReturn:
+ return false;
+
+ case Cs::cHsbw:
+ CHECK_STACK(2);
+ if (_state > S_SEAC && _careful)
+ return error(errOrdering, cmd);
+ else {
+ _lsb = _cp = _seac_origin.shifted(at(0), 0);
+ if (_state == S_INITIAL) {
+ act_sidebearing(cmd, _lsb);
+ act_width(cmd, Point(at(1), 0));
+ }
+ if (_state <= S_SEAC)
+ _state = S_SBW;
+ }
+ break;
+
+ case Cs::cSbw:
+ CHECK_STACK(4);
+ if (_state > S_SEAC && _careful)
+ return error(errOrdering, cmd);
+ else {
+ _lsb = _cp = _seac_origin.shifted(at(0), at(1));
+ if (_state == S_INITIAL) {
+ act_sidebearing(cmd, _lsb);
+ act_width(cmd, Point(at(2), at(3)));
+ }
+ if (_state <= S_SEAC)
+ _state = S_SBW;
+ }
+ break;
+
+ case Cs::cSeac:
+ CHECK_STACK(5);
+ if (_state > S_SBW)
+ return error(errOrdering, cmd);
+ act_seac(cmd, at(0), at(1), at(2), (int)at(3), (int)at(4));
+ clear();
+ return false;
+
+ case Cs::cCallsubr:
+ return callsubr_command();
+
+ case Cs::cCallothersubr: {
+ CHECK_STACK(2);
+ int othersubrnum = (int)top(0);
+ int n = (int)top(1);
+ pop(2);
+ if (othersubrnum < 0 || size() < n)
+ return error(errOthersubr, cmd);
+ return callothersubr_command(othersubrnum, n);
+ }
+
+ case Cs::cPut:
+ case Cs::cGet:
+ case Cs::cStore:
+ case Cs::cLoad:
+ return vector_command(cmd);
+
+ case Cs::cBlend:
+ case Cs::cAbs:
+ case Cs::cAdd:
+ case Cs::cSub:
+ case Cs::cDiv:
+ case Cs::cNeg:
+ case Cs::cRandom:
+ case Cs::cMul:
+ case Cs::cSqrt:
+ case Cs::cDrop:
+ case Cs::cExch:
+ case Cs::cIndex:
+ case Cs::cRoll:
+ case Cs::cDup:
+ case Cs::cAnd:
+ case Cs::cOr:
+ case Cs::cNot:
+ case Cs::cEq:
+ case Cs::cIfelse:
+ case Cs::cPop:
+ return arith_command(cmd);
+
+ case Cs::cHlineto:
+ CHECK_STACK(1);
+ CHECK_PATH_START();
+ actp_rlineto(cmd, at(0), 0);
+ break;
+
+ case Cs::cHmoveto:
+ CHECK_STACK(1);
+ CHECK_PATH_END();
+ actp_rmoveto(cmd, at(0), 0);
+ break;
+
+ case Cs::cHvcurveto:
+ CHECK_STACK(4);
+ CHECK_PATH_START();
+ actp_rrcurveto(cmd, at(0), 0, at(1), at(2), 0, at(3));
+ break;
+
+ case Cs::cRlineto:
+ CHECK_STACK(2);
+ CHECK_PATH_START();
+ actp_rlineto(cmd, at(0), at(1));
+ break;
+
+ case Cs::cRmoveto:
+ CHECK_STACK(2);
+ CHECK_PATH_END();
+ actp_rmoveto(cmd, at(0), at(1));
+ break;
+
+ case Cs::cRrcurveto:
+ CHECK_STACK(6);
+ CHECK_PATH_START();
+ actp_rrcurveto(cmd, at(0), at(1), at(2), at(3), at(4), at(5));
+ break;
+
+ case Cs::cVhcurveto:
+ CHECK_STACK(4);
+ CHECK_PATH_START();
+ actp_rrcurveto(cmd, 0, at(0), at(1), at(2), at(3), 0);
+ break;
+
+ case Cs::cVlineto:
+ CHECK_STACK(1);
+ CHECK_PATH_START();
+ actp_rlineto(cmd, 0, at(0));
+ break;
+
+ case Cs::cVmoveto:
+ CHECK_STACK(1);
+ CHECK_PATH_END();
+ actp_rmoveto(cmd, 0, at(0));
+ break;
+
+ case Cs::cDotsection:
+ break;
+
+ case Cs::cHstem:
+ CHECK_STACK(2);
+ act_hstem(cmd, _lsb.y + at(0), at(1));
+ break;
+
+ case Cs::cHstem3:
+ CHECK_STACK(6);
+ act_hstem3(cmd, _lsb.y + at(0), at(1), _lsb.y + at(2), at(3), _lsb.y + at(4), at(5));
+ break;
+
+ case Cs::cVstem:
+ CHECK_STACK(2);
+ act_vstem(cmd, _lsb.x + at(0), at(1));
+ break;
+
+ case Cs::cVstem3:
+ CHECK_STACK(6);
+ act_vstem3(cmd, _lsb.x + at(0), at(1), _lsb.x + at(2), at(3), _lsb.x + at(4), at(5));
+ break;
+
+ case Cs::cSetcurrentpoint:
+ CHECK_STACK(2);
+ _cp = Point(at(0), at(1));
+ break;
+
+ case Cs::cClosepath:
+ CHECK_PATH_END();
+ break;
+
+ case Cs::cEndchar:
+ CHECK_PATH_END();
+ set_done();
+ return false;
+
+ case Cs::cError:
+ default:
+ return error(errUnimplemented, cmd);
+
+ }
+
+ clear();
+ return error() >= 0;
+}
+
+
+#undef DEBUG_TYPE2
+
+int
+CharstringInterp::type2_handle_width(int cmd, bool have_width)
+{
+ _cp = _lsb = _seac_origin;
+ if (_state != S_INITIAL)
+ /* ignore width */;
+ else if (have_width)
+ act_nominal_width_delta(cmd, at(0));
+ else
+ act_default_width(cmd);
+ return (have_width ? 1 : 0);
+}
+
+bool
+CharstringInterp::type2_command(int cmd, const uint8_t *data, int *left)
+{
+ int bottom = 0;
+
+#ifdef DEBUG_TYPE2
+ fprintf(stderr, "%s [%d/%d]\n", Charstring::command_name(cmd).c_str(), _t2nhints, size());
+#endif
+
+ switch (cmd) {
+
+ case Cs::cHstem:
+ case Cs::cHstemhm:
+ CHECK_STACK(2);
+ if (_state <= S_SEAC)
+ bottom = type2_handle_width(cmd, (size() % 2) == 1);
+ if (_state > S_HSTEM)
+ return error(errOrdering, cmd);
+ _state = S_HSTEM;
+ for (double pos = 0; bottom + 1 < size(); bottom += 2) {
+ _t2nhints++;
+ act_hstem(cmd, pos + at(bottom), at(bottom + 1));
+ pos += at(bottom) + at(bottom + 1);
+ }
+ break;
+
+ case Cs::cVstem:
+ case Cs::cVstemhm:
+ CHECK_STACK(2);
+ if (_state <= S_SEAC)
+ bottom = type2_handle_width(cmd, (size() % 2) == 1);
+ if (_state > S_VSTEM)
+ return error(errOrdering, cmd);
+ _state = S_VSTEM;
+ for (double pos = 0; bottom + 1 < size(); bottom += 2) {
+ _t2nhints++;
+ act_vstem(cmd, pos + at(bottom), at(bottom + 1));
+ pos += at(bottom) + at(bottom + 1);
+ }
+ break;
+
+ case Cs::cHintmask:
+ case Cs::cCntrmask:
+ if (_state <= S_SEAC && size() >= 1) {
+ bottom = type2_handle_width(cmd, (size() % 2) == 1);
+ for (double pos = 0; bottom + 1 < size(); bottom += 2) {
+ _t2nhints++;
+ act_hstem(cmd, pos + at(bottom), at(bottom + 1));
+ pos += at(bottom) + at(bottom + 1);
+ }
+ }
+ if ((_state == S_HSTEM || _state == S_VSTEM) && size() >= 2)
+ for (double pos = 0; bottom + 1 < size(); bottom += 2) {
+ _t2nhints++;
+ act_vstem(cmd, pos + at(bottom), at(bottom + 1));
+ pos += at(bottom) + at(bottom + 1);
+ }
+ if (_state < S_HINTMASK)
+ _state = S_HINTMASK;
+ if (_t2nhints == 0)
+ return error(errHintmask, cmd);
+ if (!data || !left)
+ return error(errInternal, cmd);
+ if (((_t2nhints - 1) >> 3) + 1 > *left)
+ return error(errRunoff, cmd);
+ act_hintmask(cmd, data, _t2nhints);
+ *left -= ((_t2nhints - 1) >> 3) + 1;
+ break;
+
+ case Cs::cRmoveto:
+ CHECK_STACK(2);
+ if (_state <= S_SEAC)
+ bottom = type2_handle_width(cmd, size() > 2);
+ CHECK_PATH_END();
+ actp_rmoveto(cmd, at(bottom), at(bottom + 1));
+#if DEBUG_TYPE2
+ bottom += 2;
+#endif
+ break;
+
+ case Cs::cHmoveto:
+ CHECK_STACK(1);
+ if (_state <= S_SEAC)
+ bottom = type2_handle_width(cmd, size() > 1);
+ CHECK_PATH_END();
+ actp_rmoveto(cmd, at(bottom), 0);
+#if DEBUG_TYPE2
+ bottom++;
+#endif
+ break;
+
+ case Cs::cVmoveto:
+ CHECK_STACK(1);
+ if (_state <= S_SEAC)
+ bottom = type2_handle_width(cmd, size() > 1);
+ CHECK_PATH_END();
+ actp_rmoveto(cmd, 0, at(bottom));
+#if DEBUG_TYPE2
+ bottom++;
+#endif
+ break;
+
+ case Cs::cRlineto:
+ CHECK_STACK(2);
+ CHECK_STATE();
+ CHECK_PATH_START();
+ for (; bottom + 1 < size(); bottom += 2)
+ actp_rlineto(cmd, at(bottom), at(bottom + 1));
+ break;
+
+ case Cs::cHlineto:
+ CHECK_STACK(1);
+ CHECK_STATE();
+ CHECK_PATH_START();
+ while (bottom < size()) {
+ actp_rlineto(cmd, at(bottom++), 0);
+ if (bottom < size())
+ actp_rlineto(cmd, 0, at(bottom++));
+ }
+ break;
+
+ case Cs::cVlineto:
+ CHECK_STACK(1);
+ CHECK_STATE();
+ CHECK_PATH_START();
+ while (bottom < size()) {
+ actp_rlineto(cmd, 0, at(bottom++));
+ if (bottom < size())
+ actp_rlineto(cmd, at(bottom++), 0);
+ }
+ break;
+
+ case Cs::cRrcurveto:
+ CHECK_STACK(6);
+ CHECK_STATE();
+ CHECK_PATH_START();
+ for (; bottom + 5 < size(); bottom += 6)
+ actp_rrcurveto(cmd, at(bottom), at(bottom + 1), at(bottom + 2), at(bottom + 3), at(bottom + 4), at(bottom + 5));
+ break;
+
+ case Cs::cHhcurveto:
+ CHECK_STACK(4);
+ CHECK_STATE();
+ CHECK_PATH_START();
+ if (size() % 2 == 1) {
+ actp_rrcurveto(cmd, at(bottom + 1), at(bottom), at(bottom + 2), at(bottom + 3), at(bottom + 4), 0);
+ bottom += 5;
+ }
+ for (; bottom + 3 < size(); bottom += 4)
+ actp_rrcurveto(cmd, at(bottom), 0, at(bottom + 1), at(bottom + 2), at(bottom + 3), 0);
+ break;
+
+ case Cs::cHvcurveto:
+ CHECK_STACK(4);
+ CHECK_STATE();
+ CHECK_PATH_START();
+ while (bottom + 3 < size()) {
+ double dx3 = (bottom + 5 == size() ? at(bottom + 4) : 0);
+ actp_rrcurveto(cmd, at(bottom), 0, at(bottom + 1), at(bottom + 2), dx3, at(bottom + 3));
+ bottom += 4;
+ if (bottom + 3 < size()) {
+ double dy3 = (bottom + 5 == size() ? at(bottom + 4) : 0);
+ actp_rrcurveto(cmd, 0, at(bottom), at(bottom + 1), at(bottom + 2), at(bottom + 3), dy3);
+ bottom += 4;
+ }
+ }
+#if DEBUG_TYPE2
+ if (bottom + 1 == size())
+ bottom++;
+#endif
+ break;
+
+ case Cs::cRcurveline:
+ CHECK_STACK(8);
+ CHECK_STATE();
+ CHECK_PATH_START();
+ for (; bottom + 7 < size(); bottom += 6)
+ actp_rrcurveto(cmd, at(bottom), at(bottom + 1), at(bottom + 2), at(bottom + 3), at(bottom + 4), at(bottom + 5));
+ actp_rlineto(cmd, at(bottom), at(bottom + 1));
+#if DEBUG_TYPE2
+ bottom += 2;
+#endif
+ break;
+
+ case Cs::cRlinecurve:
+ CHECK_STACK(8);
+ CHECK_STATE();
+ CHECK_PATH_START();
+ for (; bottom + 7 < size(); bottom += 2)
+ actp_rlineto(cmd, at(bottom), at(bottom + 1));
+ actp_rrcurveto(cmd, at(bottom), at(bottom + 1), at(bottom + 2), at(bottom + 3), at(bottom + 4), at(bottom + 5));
+#if DEBUG_TYPE2
+ bottom += 6;
+#endif
+ break;
+
+ case Cs::cVhcurveto:
+ CHECK_STACK(4);
+ CHECK_STATE();
+ CHECK_PATH_START();
+ while (bottom + 3 < size()) {
+ double dy3 = (bottom + 5 == size() ? at(bottom + 4) : 0);
+ actp_rrcurveto(cmd, 0, at(bottom), at(bottom + 1), at(bottom + 2), at(bottom + 3), dy3);
+ bottom += 4;
+ if (bottom + 3 < size()) {
+ double dx3 = (bottom + 5 == size() ? at(bottom + 4) : 0);
+ actp_rrcurveto(cmd, at(bottom), 0, at(bottom + 1), at(bottom + 2), dx3, at(bottom + 3));
+ bottom += 4;
+ }
+ }
+#if DEBUG_TYPE2
+ if (bottom + 1 == size())
+ bottom++;
+#endif
+ break;
+
+ case Cs::cVvcurveto:
+ CHECK_STACK(4);
+ CHECK_STATE();
+ CHECK_PATH_START();
+ if (size() % 2 == 1) {
+ actp_rrcurveto(cmd, at(bottom), at(bottom + 1), at(bottom + 2), at(bottom + 3), 0, at(bottom + 4));
+ bottom += 5;
+ }
+ for (; bottom + 3 < size(); bottom += 4)
+ actp_rrcurveto(cmd, 0, at(bottom), at(bottom + 1), at(bottom + 2), 0, at(bottom + 3));
+ break;
+
+ case Cs::cFlex:
+ CHECK_STACK(13);
+ CHECK_STATE();
+ CHECK_PATH_START();
+ assert(bottom == 0);
+ actp_rrflex(cmd,
+ at(0), at(1), at(2), at(3), at(4), at(5),
+ at(6), at(7), at(8), at(9), at(10), at(11),
+ at(12));
+#if DEBUG_TYPE2
+ bottom += 13;
+#endif
+ break;
+
+ case Cs::cHflex:
+ CHECK_STACK(7);
+ CHECK_STATE();
+ CHECK_PATH_START();
+ assert(bottom == 0);
+ actp_rrflex(cmd,
+ at(0), 0, at(1), at(2), at(3), 0,
+ at(4), 0, at(5), -at(2), at(6), 0,
+ 50);
+#if DEBUG_TYPE2
+ bottom += 7;
+#endif
+ break;
+
+ case Cs::cHflex1:
+ CHECK_STACK(9);
+ CHECK_STATE();
+ CHECK_PATH_START();
+ assert(bottom == 0);
+ actp_rrflex(cmd,
+ at(0), at(1), at(2), at(3), at(4), 0,
+ at(5), 0, at(6), at(7), at(8), -(at(1) + at(3) + at(7)),
+ 50);
+#if DEBUG_TYPE2
+ bottom += 9;
+#endif
+ break;
+
+ case Cs::cFlex1: {
+ CHECK_STACK(11);
+ CHECK_STATE();
+ CHECK_PATH_START();
+ assert(bottom == 0);
+ double dx = at(0) + at(2) + at(4) + at(6) + at(8);
+ double dy = at(1) + at(3) + at(5) + at(7) + at(9);
+ if (fabs(dx) > fabs(dy))
+ actp_rrflex(cmd,
+ at(0), at(1), at(2), at(3), at(4), at(5),
+ at(6), at(7), at(8), at(9), at(10), -dy,
+ 50);
+ else
+ actp_rrflex(cmd,
+ at(0), at(1), at(2), at(3), at(4), at(5),
+ at(6), at(7), at(8), at(9), -dx, at(10),
+ 50);
+ break;
+#if DEBUG_TYPE2
+ bottom += 11;
+#endif
+ }
+
+ case Cs::cEndchar:
+ if (_state <= S_SEAC)
+ bottom = type2_handle_width(cmd, size() > 0 && size() != 4);
+ if (bottom + 3 < size() && _state == S_INITIAL)
+ act_seac(cmd, 0, at(bottom), at(bottom + 1), (int)at(bottom + 2), (int)at(bottom + 3));
+ CHECK_PATH_END();
+ set_done();
+ clear();
+ return false;
+
+ case Cs::cReturn:
+ return false;
+
+ case Cs::cCallsubr:
+ return callsubr_command();
+
+ case Cs::cCallgsubr:
+ return callgsubr_command();
+
+ case Cs::cPut:
+ case Cs::cGet:
+ case Cs::cStore:
+ case Cs::cLoad:
+ return vector_command(cmd);
+
+ case Cs::cBlend:
+ case Cs::cAbs:
+ case Cs::cAdd:
+ case Cs::cSub:
+ case Cs::cDiv:
+ case Cs::cNeg:
+ case Cs::cRandom:
+ case Cs::cMul:
+ case Cs::cSqrt:
+ case Cs::cDrop:
+ case Cs::cExch:
+ case Cs::cIndex:
+ case Cs::cRoll:
+ case Cs::cDup:
+ case Cs::cAnd:
+ case Cs::cOr:
+ case Cs::cNot:
+ case Cs::cEq:
+ case Cs::cIfelse:
+ case Cs::cPop:
+ return arith_command(cmd);
+
+ case Cs::cDotsection:
+ break;
+
+ case Cs::cError:
+ default:
+ return error(errUnimplemented, cmd);
+
+ }
+
+#if DEBUG_TYPE2
+ if (bottom != size())
+ fprintf(stderr, "[left %d on stack] ", size() - bottom);
+#endif
+
+ clear();
+ return error() >= 0;
+}
+
+
+void
+CharstringInterp::act_sidebearing(int, const Point &)
+{
+ /* do nothing */
+}
+
+void
+CharstringInterp::act_width(int, const Point &)
+{
+ /* do nothing */
+}
+
+void
+CharstringInterp::act_default_width(int cmd)
+{
+ double d = (_program ? _program->global_width_x(false) : UNKDOUBLE);
+ if (KNOWN(d))
+ act_width(cmd, Point(d, 0));
+}
+
+void
+CharstringInterp::act_nominal_width_delta(int cmd, double delta)
+{
+ double d = (_program ? _program->global_width_x(true) : UNKDOUBLE);
+ if (KNOWN(d))
+ act_width(cmd, Point(d + delta, 0));
+}
+
+void
+CharstringInterp::act_seac(int cmd, double asb, double adx, double ady, int bchar, int achar)
+{
+ Charstring *acs = 0, *bcs = 0;
+ if (achar < 0 || achar >= 256 || bchar < 0 || bchar >= 256
+ || !_program || _program->parent_program()
+ || !(acs = get_glyph(Charstring::standard_encoding[achar]))
+ || !(bcs = get_glyph(Charstring::standard_encoding[bchar]))) {
+ error(errGlyph, cmd);
+ return;
+ }
+
+ Point apos = Point(adx + _lsb.x - asb, ady + _lsb.y);
+ Point save_lsb = _lsb;
+ Point save_seac_origin = _seac_origin;
+
+ CharstringInterp::initialize();
+ _seac_origin = apos;
+ _state = S_SEAC;
+ acs->process(*this);
+ if (error() == errOK) {
+ CharstringInterp::initialize();
+ _seac_origin = save_seac_origin;
+ _state = S_SEAC;
+ bcs->process(*this);
+ }
+
+ _lsb = save_lsb;
+}
+
+void
+CharstringInterp::act_line(int cmd, const Point &p0, const Point &p1)
+{
+ act_curve(cmd, p0, p0, p1, p1);
+}
+
+void
+CharstringInterp::act_curve(int cmd, const Point &, const Point &, const Point &, const Point &)
+{
+ error(errUnimplemented, cmd);
+}
+
+void
+CharstringInterp::act_flex(int cmd, const Point &p0, const Point &p1, const Point &p2, const Point &p3_4, const Point &p5, const Point &p6, const Point &p7, double flex_depth)
+{
+ (void) flex_depth;
+ act_curve(cmd, p0, p1, p2, p3_4);
+ act_curve(cmd, p3_4, p5, p6, p7);
+}
+
+void
+CharstringInterp::act_closepath(int)
+{
+ /* do nothing */
+}
+
+void
+CharstringInterp::act_hstem(int, double, double)
+{
+ /* do nothing */
+}
+
+void
+CharstringInterp::act_vstem(int, double, double)
+{
+ /* do nothing */
+}
+
+void
+CharstringInterp::act_hstem3(int cmd, double y0, double dy0, double y1, double dy1, double y2, double dy2)
+{
+ act_hstem(cmd, y0, dy0);
+ act_hstem(cmd, y1, dy1);
+ act_hstem(cmd, y2, dy2);
+}
+
+void
+CharstringInterp::act_vstem3(int cmd, double x0, double dx0, double x1, double dx1, double x2, double dx2)
+{
+ act_vstem(cmd, x0, dx0);
+ act_vstem(cmd, x1, dx1);
+ act_vstem(cmd, x2, dx2);
+}
+
+void
+CharstringInterp::act_hintmask(int, const uint8_t *, int)
+{
+ /* do nothing */
+}
+
+}
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1item.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1item.cc
new file mode 100644
index 00000000000..5e169b66f13
--- /dev/null
+++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1item.cc
@@ -0,0 +1,861 @@
+// -*- related-file-name: "../include/efont/t1item.hh" -*-
+
+/* t1item.{cc,hh} -- items in a Type 1 font
+ *
+ * Copyright (c) 1998-2012 Eddie Kohler
+ *
+ * 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 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <efont/t1item.hh>
+#include <efont/t1rw.hh>
+#include <efont/t1interp.hh>
+#include <efont/t1font.hh>
+#include <lcdf/strtonum.h>
+#include <ctype.h>
+#include <string.h>
+#include <sys/stat.h>
+#ifndef WIN32
+# include <unistd.h>
+#endif
+#if HAVE_BROKEN_STRTOD
+# define strtod good_strtod
+#endif
+namespace Efont {
+
+/*****
+ * Type1NullItem
+ **/
+
+void
+Type1NullItem::gen(Type1Writer &)
+{
+}
+
+/*****
+ * Type1CopyItem
+ **/
+
+void
+Type1CopyItem::gen(Type1Writer &w)
+{
+ w << _value << '\n';
+}
+
+
+/*****
+ * Type1EexecItem
+ **/
+
+void
+Type1EexecItem::gen(Type1Writer &w)
+{
+ if (_eexec_on)
+ w << "currentfile eexec\n";
+ w.switch_eexec(_eexec_on);
+}
+
+
+/*****
+ * Type1Definition
+ **/
+
+typedef Vector<double> NumVector;
+
+
+Type1Definition::Type1Definition(PermString n, const String &v, PermString d)
+ : _name(n), _val(v), _definer(d)
+{
+ _val.c_str(); // ensure it ends with '\0'
+}
+
+Type1Definition *
+Type1Definition::make_string(PermString n, const String &v, PermString d)
+{
+ Type1Definition *t1d = new Type1Definition(n, "", d);
+ t1d->set_string(v);
+ return t1d;
+}
+
+int
+Type1Definition::slurp_string(StringAccum &accum, int pos, Type1Reader *reader)
+{
+ int paren_level = 0;
+ char *s = accum.data() + pos;
+
+ do {
+ switch (*s++) {
+ case '(': paren_level++; break;
+ case ')': paren_level--; break;
+ case '\\': if (paren_level && *s) s++; break;
+ case 0:
+ if (!reader) return -1;
+ pos = s - accum.data();
+ accum.append('\n'); // add \n
+ if (!reader->next_line(accum)) return -1;
+ accum.c_str(); // ensure null termination
+ s = accum.data() + pos;
+ break;
+ }
+ } while (paren_level);
+
+ return s - accum.data();
+}
+
+int
+Type1Definition::slurp_proc(StringAccum &accum, int pos, Type1Reader *reader)
+{
+ int paren_level = 0;
+ int brace_level = 0;
+ char *s = accum.data() + pos;
+
+ do {
+ switch (*s++) {
+ case '{': if (!paren_level) brace_level++; break;
+ case '}': if (!paren_level) brace_level--; break;
+ case '(': paren_level++; break;
+ case ')': paren_level--; break;
+ case '\\': if (paren_level && *s) s++; break;
+ case '%':
+ if (!paren_level)
+ while (*s != '\n' && *s != '\r' && *s)
+ s++;
+ break;
+ case 0:
+ if (!reader) return -1;
+ pos = s - accum.data();
+ accum.append('\n'); // add \n
+ if (!reader->next_line(accum)) return -1;
+ accum.c_str(); // ensure null termination
+ s = accum.data() + pos;
+ break;
+ }
+ } while (brace_level);
+
+ return s - accum.data();
+}
+
+Type1Definition *
+Type1Definition::make(StringAccum &accum, Type1Reader *reader,
+ bool force_definition)
+{
+ char *s = accum.data();
+ while (isspace((unsigned char) *s))
+ s++;
+ if (*s != '/')
+ return 0;
+ s++;
+ int name_start_pos = s - accum.data();
+
+ // find NAME LENGTH
+ while (!isspace((unsigned char) *s) && *s != '[' && *s != '{' && *s != '('
+ && *s != ']' && *s != '}' && *s != ')' && *s)
+ s++;
+ if (!*s)
+ return 0;
+ int name_end_pos = s - accum.data();
+
+ while (isspace((unsigned char) *s))
+ s++;
+ int val_pos = s - accum.data();
+ int val_end_pos = -1;
+ bool check_def = false;
+
+ if (*s == '}' || *s == ']' || *s == ')' || *s == 0)
+ return 0;
+
+ else if (*s == '(')
+ val_end_pos = slurp_string(accum, val_pos, reader);
+
+ else if (*s == '{')
+ val_end_pos = slurp_proc(accum, val_pos, reader);
+
+ else if (*s == '[') {
+ int brack_level = 0;
+ do {
+ switch (*s++) {
+ case '[': brack_level++; break;
+ case ']': brack_level--; break;
+ case '(': case ')': case 0: return 0;
+ }
+ } while (brack_level);
+ val_end_pos = s - accum.data();
+
+ } else {
+ while (!isspace((unsigned char) *s) && *s)
+ s++;
+ val_end_pos = s - accum.data();
+ if (!force_definition) check_def = true;
+ }
+
+ if (val_end_pos < 0)
+ return 0;
+ s = accum.data() + val_end_pos;
+ while (isspace((unsigned char) *s))
+ s++;
+ if (check_def && (s[0] != 'd' || s[1] != 'e' || s[2] != 'f'))
+ if (strncmp(s, "dict def", 8) != 0)
+ return 0;
+
+ PermString name(accum.data()+name_start_pos, name_end_pos - name_start_pos);
+ PermString def(s, accum.length() - (s - accum.data()));
+ String value = String(accum.data() + val_pos, val_end_pos - val_pos);
+ return new Type1Definition(name, value, def);
+}
+
+void
+Type1Definition::gen(Type1Writer &w)
+{
+ w << '/' << _name << ' ' << _val << ' ' << _definer << '\n';
+}
+
+void
+Type1Definition::gen(StringAccum &sa)
+{
+ sa << '/' << _name << ' ' << _val << ' ' << _definer;
+}
+
+
+bool
+Type1Definition::value_bool(bool &b) const
+{
+ if (_val == "true") {
+ b = true;
+ return true;
+ } else if (_val == "false") {
+ b = false;
+ return true;
+ } else
+ return false;
+}
+
+bool
+Type1Definition::value_int(int &i) const
+{
+ char *s;
+ i = strtol(_val.data(), &s, 10);
+ return (*s == 0);
+}
+
+bool
+Type1Definition::value_num(double &d) const
+{
+ char *s;
+ d = strtonumber(_val.data(), &s);
+ return (*s == 0);
+}
+
+bool
+Type1Definition::value_string(String &str) const
+{
+ if (_val.length() == 0 || _val[0] != '(' || _val.back() != ')')
+ return false;
+ StringAccum sa;
+ int pos, first_pos = 1, len = _val.length() - 1;
+ for (pos = 1; pos < len; pos++)
+ if (_val[pos] == '\\') {
+ sa.append(_val.data() + first_pos, pos - first_pos);
+ pos++;
+ switch (pos < len ? _val[pos] : -1) {
+ case '\r':
+ pos++;
+ if (pos < len && _val[pos] == '\n')
+ pos++;
+ break;
+ case '\n':
+ pos++;
+ break;
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7': {
+ int c = _val[pos++] - '0';
+ for (int i = 1; pos < len && i < 3 && _val[pos] >= '0' && _val[pos] <= '7'; i++, pos++)
+ c = (c << 3) | (_val[pos] - '0');
+ sa.append((char) c);
+ break;
+ }
+ case 'n':
+ sa << '\n';
+ pos++;
+ break;
+ case 'r':
+ sa << '\r';
+ pos++;
+ break;
+ case 't':
+ sa << '\t';
+ pos++;
+ break;
+ case 'b':
+ sa << '\b';
+ pos++;
+ break;
+ case 'f':
+ sa << '\f';
+ pos++;
+ break;
+ default:
+ sa << _val[pos];
+ pos++;
+ break;
+ }
+ first_pos = pos;
+ }
+ sa.append(_val.data() + first_pos, len - first_pos);
+ str = sa.take_string();
+ return true;
+}
+
+bool
+Type1Definition::value_name(PermString &str) const
+{
+ if (_val.length() == 0 || _val[0] != '/')
+ return false;
+ int pos;
+ for (pos = 1; pos < _val.length(); pos++)
+ if (isspace((unsigned char) _val[pos]) || _val[pos] == '/')
+ return false;
+ str = PermString(_val.data() + 1, pos - 1);
+ return true;
+}
+
+static bool
+strtonumvec(const char *f, const char **endf, NumVector &v)
+{
+ v.clear();
+ char *s = (char *)f;
+ if (*s != '[' && *s != '{')
+ return false;
+ s++;
+ while (1) {
+ while (isspace((unsigned char) *s))
+ s++;
+ if (isdigit((unsigned char) *s) || *s == '.' || *s == '-')
+ v.push_back( strtonumber(s, &s) );
+ else {
+ if (endf)
+ *endf = s + 1;
+ return (*s == ']' || *s == '}');
+ }
+ }
+}
+
+bool
+Type1Definition::value_numvec(NumVector &v) const
+{
+ return strtonumvec(_val.data(), 0, v);
+}
+
+static bool
+strtonumvec_vec(const char *f, const char **endf, Vector<NumVector> &v)
+{
+ v.clear();
+ const char *s = f;
+ if (*s != '[' && *s != '{')
+ return false;
+ s++;
+ while (1) {
+ while (isspace((unsigned char) *s))
+ s++;
+ if (*s == '[' || *s == '{') {
+ NumVector subv;
+ if (!strtonumvec(s, &s, subv))
+ return false;
+ v.push_back(subv);
+ } else {
+ if (endf)
+ *endf = s + 1;
+ return (*s == ']' || *s == '}');
+ }
+ }
+}
+
+bool
+Type1Definition::value_numvec_vec(Vector<NumVector> &v) const
+{
+ return strtonumvec_vec(_val.data(), 0, v);
+}
+
+bool
+Type1Definition::value_normalize(Vector<NumVector> &in,
+ Vector<NumVector> &out) const
+{
+ in.clear();
+ out.clear();
+ const char *s = _val.data();
+ if (*s++ != '[')
+ return false;
+ while (1) {
+ while (isspace((unsigned char) *s))
+ s++;
+ if (*s == '[') {
+ Vector<NumVector> sub;
+ if (!strtonumvec_vec(s, &s, sub))
+ return false;
+
+ NumVector subin;
+ NumVector subout;
+ for (int i = 0; i < sub.size(); i++)
+ if (sub[i].size() == 2) {
+ subin.push_back(sub[i][0]);
+ subout.push_back(sub[i][1]);
+ } else
+ return false;
+ in.push_back(subin);
+ out.push_back(subout);
+ } else
+ return (*s == ']');
+ }
+}
+
+bool
+Type1Definition::value_namevec(Vector<PermString> &v) const
+{
+ v.clear();
+ const char *s = _val.data();
+ if (*s++ != '[')
+ return false;
+ while (1) {
+ while (isspace((unsigned char) *s))
+ s++;
+ if (*s == '/')
+ s++;
+ if (isalnum((unsigned char) *s)) {
+ const char *start = s;
+ while (*s && !isspace((unsigned char) *s) && *s != ']' && *s != '/')
+ s++;
+ v.push_back(PermString(start, s - start));
+ } else
+ return (*s == ']');
+ }
+}
+
+
+void
+Type1Definition::set_bool(bool b)
+{
+ set_val(b ? "true" : "false");
+}
+
+void
+Type1Definition::set_int(int i)
+{
+ set_val(String(i));
+}
+
+void
+Type1Definition::set_num(double n)
+{
+ set_val(String(n));
+}
+
+void
+Type1Definition::set_string(const String &v)
+{
+ const char *s = v.data();
+ int len = v.length();
+ int left = 0;
+ StringAccum sa;
+ sa << '(';
+ for (int pos = 0; pos < len; pos++)
+ if ((s[pos] < ' ' && !isspace((unsigned char) s[pos])) || ((unsigned char)s[pos]) > 0176 || s[pos] == '(' || s[pos] == ')' || s[pos] == '\\') {
+ sa << v.substring(left, pos - left) << '\\';
+ if (s[pos] == '(' || s[pos] == ')' || s[pos] == '\\')
+ sa << s[pos];
+ else
+ sprintf(sa.reserve(8), "%03o", (unsigned char) (s[pos]));
+ left = pos + 1;
+ }
+ sa << v.substring(left) << ')';
+ _val = sa.take_string();
+}
+
+void
+Type1Definition::set_name(PermString str, bool name)
+{
+ StringAccum sa;
+ if (name)
+ sa << '/';
+ sa << str;
+ set_val(sa);
+}
+
+static void
+accum_numvec(StringAccum &sa, const NumVector &nv, bool executable)
+{
+ char open = (executable ? '{' : '[');
+ for (int i = 0; i < nv.size(); i++)
+ sa << (i ? ' ' : open) << nv[i];
+ sa << (executable ? '}' : ']');
+}
+
+void
+Type1Definition::set_numvec(const NumVector &nv, bool executable)
+{
+ StringAccum sa;
+ accum_numvec(sa, nv, executable);
+ set_val(sa);
+}
+
+void
+Type1Definition::set_numvec_vec(const Vector<NumVector> &nv)
+{
+ StringAccum sa;
+ sa << '[';
+ for (int i = 0; i < nv.size(); i++)
+ accum_numvec(sa, nv[i], false);
+ sa << ']';
+ set_val(sa);
+}
+
+void
+Type1Definition::set_normalize(const Vector<NumVector> &vin,
+ const Vector<NumVector> &vout)
+{
+ StringAccum sa;
+ sa << '[';
+ for (int i = 0; i < vin.size(); i++) {
+ const NumVector &vini = vin[i];
+ const NumVector &vouti = vout[i];
+ sa << '[';
+ for (int j = 0; j < vini.size(); j++)
+ sa << '[' << vini[j] << ' ' << vouti[j] << ']';
+ sa << ']';
+ }
+ sa << ']';
+ set_val(sa);
+}
+
+void
+Type1Definition::set_namevec(const Vector<PermString> &v, bool executable)
+{
+ StringAccum sa;
+ sa << '[';
+ for (int i = 0; i < v.size(); i++) {
+ if (i) sa << ' ';
+ if (executable) sa << '/';
+ sa << v[i];
+ }
+ sa << ']';
+ set_val(sa);
+}
+
+
+/*****
+ * Type1Encoding
+ **/
+
+static PermString::Initializer initializer;
+static PermString dot_notdef(".notdef");
+
+
+Type1Encoding::Type1Encoding()
+ : _v(new PermString[256]), _copy_of(0), _definer("readonly def")
+{
+ for (int i = 0; i < 256; i++)
+ _v[i] = dot_notdef;
+}
+
+Type1Encoding::Type1Encoding(const Type1Encoding &o)
+ : Type1Item(), _definer(o._definer)
+{
+ if (o._copy_of) {
+ _v = o._v;
+ _copy_of = o._copy_of;
+ } else {
+ _v = new PermString[256];
+ _copy_of = 0;
+ for (int i = 0; i < 256; i++)
+ _v[i] = o._v[i];
+ }
+}
+
+Type1Encoding::Type1Encoding(Type1Encoding *copy_of)
+ : _v(copy_of->_v), _copy_of(copy_of), _definer(copy_of->_definer)
+{
+}
+
+Type1Encoding::~Type1Encoding()
+{
+ if (!_copy_of)
+ delete[] _v;
+}
+
+void
+Type1Encoding::unshare()
+{
+ if (_copy_of) {
+ PermString *new_v = new PermString[256];
+ memcpy(new_v, _v, sizeof(PermString) * 256);
+ _v = new_v;
+ _copy_of = 0;
+ }
+}
+
+void
+Type1Encoding::clear()
+{
+ unshare();
+ for (int i = 0; i < 256; i++)
+ _v[i] = dot_notdef;
+}
+
+
+static Type1Encoding *canonical_standard_encoding;
+
+Type1Encoding *
+Type1Encoding::standard_encoding()
+{
+ if (!canonical_standard_encoding) {
+ canonical_standard_encoding = new Type1Encoding;
+ for (int i = 0; i < 256; i++)
+ if (Charstring::standard_encoding[i])
+ canonical_standard_encoding->put(i, Charstring::standard_encoding[i]);
+ }
+ // Return a copy of the cached encoding. When it's deleted, we won't be.
+ return new Type1Encoding(canonical_standard_encoding);
+}
+
+
+void
+Type1Encoding::gen(Type1Writer &w)
+{
+ if (_copy_of && _copy_of == canonical_standard_encoding)
+ w << "/Encoding StandardEncoding def\n";
+ else {
+ w << "/Encoding 256 array\n0 1 255 {1 index exch /.notdef put} for\n";
+ for (int i = 0; i < 256; i++)
+ if (_v[i] != dot_notdef)
+ w << "dup " << i << " /" << _v[i] << " put\n";
+ w << _definer << '\n';
+ }
+}
+
+
+/*****
+ * Type1Subr
+ **/
+
+Type1Subr::Type1Subr(PermString n, int num, PermString definer,
+ int lenIV, const String &s)
+ : _name(n), _subrno(num), _definer(definer), _cs(lenIV, s)
+{
+}
+
+Type1Subr::Type1Subr(PermString n, int num, PermString definer,
+ const Type1Charstring &t1cs)
+ : _name(n), _subrno(num), _definer(definer), _cs(t1cs)
+{
+}
+
+Type1Subr *
+Type1Subr::make(const char *s_in, int s_len, int cs_pos, int cs_len, int lenIV)
+{
+ /* USAGE NOTE: You must ensure that s_in contains a valid subroutine string
+ before calling Type1Subr::make. Type1Reader::was_charstring() is a good
+ guarantee of this.
+ A valid subroutine string is one of the following:
+ /[char_name] ### charstring_start ........
+ dup [subrno] ### charstring_start .... */
+
+ const char *s = s_in;
+ PermString name;
+ int subrno = 0;
+
+ // Force literal spaces rather than isspace().
+ if (*s == '/') {
+ const char *nstart = ++s;
+ while (!isspace((unsigned char) *s) && *s)
+ s++;
+ name = PermString(nstart, s - nstart);
+
+ } else {
+ // dup [subrno] ...
+ s += 3;
+ while (isspace((unsigned char) *s))
+ s++;
+ subrno = strtol(s, (char **)&s, 10);
+ }
+
+ s = s_in + cs_pos;
+
+ // Lazily decrypt the charstring.
+ PermString definer = PermString(s + cs_len, s_len - cs_len - cs_pos);
+ return new Type1Subr(name, subrno, definer, lenIV, String(s, cs_len));
+}
+
+Type1Subr *
+Type1Subr::make_subr(int subrno, const Type1Charstring &cs, PermString definer)
+{
+ return new Type1Subr(PermString(), subrno, definer, cs);
+}
+
+Type1Subr *
+Type1Subr::make_glyph(PermString glyph, const Type1Charstring &cs, PermString definer)
+{
+ return new Type1Subr(glyph, -1, definer, cs);
+}
+
+
+void
+Type1Subr::gen(Type1Writer &w)
+{
+ int len = _cs.length();
+ const unsigned char *data = _cs.data();
+
+ if (is_subr())
+ w << "dup " << _subrno << ' ' << len + w.lenIV() << w.charstring_start();
+ else
+ w << '/' << _name << ' ' << len + w.lenIV() << w.charstring_start();
+
+ if (w.lenIV() < 0) {
+ // lenIV < 0 means charstrings are unencrypted
+ w.print((const char *)data, len);
+
+ } else {
+ // PERFORMANCE NOTE: Putting the charstring in a buffer of known length
+ // and printing that buffer rather than one char at a time is an OK
+ // optimization. (around 10%)
+ unsigned char *buf = new unsigned char[len + w.lenIV()];
+ unsigned char *t = buf;
+
+ int r = t1R_cs;
+ for (int i = 0; i < w.lenIV(); i++) {
+ unsigned char c = (unsigned char)(r >> 8);
+ *t++ = c;
+ r = ((c + r) * t1C1 + t1C2) & 0xFFFF;
+ }
+ for (int i = 0; i < len; i++, data++) {
+ unsigned char c = (*data ^ (r >> 8));
+ *t++ = c;
+ r = ((c + r) * t1C1 + t1C2) & 0xFFFF;
+ }
+
+ w.print((char *)buf, len + w.lenIV());
+ delete[] buf;
+ }
+
+ w << _definer << '\n';
+}
+
+/*****
+ * Type1SubrGroupItem
+ **/
+
+Type1SubrGroupItem::Type1SubrGroupItem(Type1Font *font, bool is_subrs, const String &value)
+ : _font(font), _is_subrs(is_subrs), _value(value)
+{
+}
+
+Type1SubrGroupItem::Type1SubrGroupItem(const Type1SubrGroupItem &from, Type1Font *font)
+ : _font(font), _is_subrs(from._is_subrs),
+ _value(from._value), _end_text(from._end_text)
+{
+}
+
+void
+Type1SubrGroupItem::add_end_text(const String &s)
+{
+ _end_text += s + "\n";
+}
+
+void
+Type1SubrGroupItem::gen(Type1Writer &w)
+{
+ Type1Font *font = _font;
+
+ int pos = _value.find_left(_is_subrs ? " array" : " dict");
+ if (pos >= 1 && isdigit((unsigned char) _value[pos - 1])) {
+ int numpos = pos - 1;
+ while (numpos >= 1 && isdigit((unsigned char) _value[numpos - 1]))
+ numpos--;
+
+ int n;
+ if (_is_subrs) {
+ n = font->nsubrs();
+ while (n && !font->subr(n - 1))
+ n--;
+ } else
+ n = font->nglyphs();
+
+ w << _value.substring(0, numpos) << n << _value.substring(pos);
+ } else
+ w << _value;
+
+ w << '\n';
+
+ if (_is_subrs) {
+ int count = font->nsubrs();
+ for (int i = 0; i < count; i++)
+ if (Type1Subr *g = font->subr_x(i))
+ g->gen(w);
+ } else {
+ int count = font->nglyphs();
+ for (int i = 0; i < count; i++)
+ if (Type1Subr *g = font->glyph_x(i))
+ g->gen(w);
+ }
+
+ w << _end_text;
+}
+
+/*****
+ * Type1IncludedFont
+ **/
+
+Type1IncludedFont::Type1IncludedFont(Type1Font *font, int unique_id)
+ : _included_font(font), _unique_id(unique_id)
+{
+}
+
+Type1IncludedFont::~Type1IncludedFont()
+{
+ delete _included_font;
+}
+
+void
+Type1IncludedFont::gen(Type1Writer &w)
+{
+ FILE *f = tmpfile();
+ if (!f)
+ return;
+
+ // write included font
+ Type1PFAWriter new_w(f);
+ _included_font->write(new_w);
+ fflush(f);
+
+ struct stat s;
+ fstat(fileno(f), &s);
+
+ w << "FontDirectory /" << _included_font->font_name() << " known{\n"
+ << "/" << _included_font->font_name()
+ << " findfont dup /UniqueID known {dup /UniqueID get "
+ << _unique_id
+ << " eq exch /FontType get 1 eq and}{pop false}ifelse {\nsave userdict/fbufstr 512 string put\n"
+ << (int)(s.st_size / 512)
+ << "{currentfile fbufstr readstring{pop}{clear currentfile\nclosefile/fontdownload/unexpectedEOF/.error cvx exec}ifelse}repeat\ncurrentfile "
+ << (int)(s.st_size % 512)
+ << " string readstring{pop}{clear currentfile\nclosefile/fontdownload/unexpectedEOF/.error cvx exec}ifelse\nrestore}if}if\n";
+
+ rewind(f);
+ char str[2048];
+ while (1) {
+ int r = fread(str, 1, 2048, f);
+ if (r <= 0)
+ break;
+ w.print(str, r);
+ }
+
+ fclose(f);
+}
+
+}
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1mm.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1mm.cc
new file mode 100644
index 00000000000..404335a8f20
--- /dev/null
+++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1mm.cc
@@ -0,0 +1,392 @@
+// -*- related-file-name: "../include/efont/t1mm.hh" -*-
+
+/* t1mm.{cc,hh} -- Type 1 multiple master font information
+ *
+ * Copyright (c) 1998-2012 Eddie Kohler
+ *
+ * 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 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <efont/t1mm.hh>
+#include <efont/t1interp.hh>
+#include <lcdf/error.hh>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+namespace Efont {
+
+MultipleMasterSpace::MultipleMasterSpace(PermString fn, int na, int nm)
+ : _ok(false), _font_name(fn), _naxes(na), _nmasters(nm),
+ _axis_types(na, PermString()), _axis_labels(na, PermString()),
+ _design_vector(0), _norm_design_vector(0), _weight_vector(0)
+{
+}
+
+
+void
+MultipleMasterSpace::set_master_positions(const Vector<NumVector> &mp)
+{
+ _master_positions = mp;
+}
+
+void
+MultipleMasterSpace::set_normalize(const Vector<NumVector> &nin,
+ const Vector<NumVector> &nout)
+{
+ _normalize_in = nin;
+ _normalize_out = nout;
+}
+
+void
+MultipleMasterSpace::set_axis_type(int ax, PermString t)
+{
+ _axis_types[ax] = t;
+}
+
+void
+MultipleMasterSpace::set_axis_label(int ax, PermString t)
+{
+ _axis_labels[ax] = t;
+}
+
+void
+MultipleMasterSpace::set_design_vector(const NumVector &v)
+{
+ _default_design_vector = v;
+}
+
+void
+MultipleMasterSpace::set_weight_vector(const NumVector &v)
+{
+ _default_weight_vector = v;
+}
+
+
+PermString
+MultipleMasterSpace::axis_abbreviation(PermString atype)
+{
+ if (atype == "Weight")
+ return "wt";
+ else if (atype == "Width")
+ return "wd";
+ else if (atype == "OpticalSize")
+ return "op";
+ else if (atype == "Style")
+ return "st";
+ else
+ return atype;
+}
+
+
+bool
+MultipleMasterSpace::error(ErrorHandler *errh, const char *s, ...) const
+{
+ if (errh) {
+ char buf[1024];
+ va_list val;
+ va_start(val, s);
+ assert(strlen(s) < 800);
+ sprintf(buf, (s[0] == ' ' ? "%.200s%s" : "%.200s: %s"),
+ _font_name.c_str(), s);
+ errh->vxmessage(ErrorHandler::e_error, buf, val);
+ va_end(val);
+ }
+ return false;
+}
+
+
+bool
+MultipleMasterSpace::check(ErrorHandler *errh)
+{
+ if (_ok)
+ return true;
+
+ if (_nmasters <= 0 || _nmasters > 16)
+ return error(errh, "number of masters must be between 1 and 16");
+ if (_naxes <= 0 || _naxes > 4)
+ return error(errh, "number of axes must be between 1 and 4");
+
+ if (_master_positions.size() != _nmasters)
+ return error(errh, "bad BlendDesignPositions");
+ for (int i = 0; i < _nmasters; i++)
+ if (_master_positions[i].size() != _naxes)
+ return error(errh, "inconsistent BlendDesignPositions");
+
+ if (_normalize_in.size() != _naxes || _normalize_out.size() != _naxes)
+ return error(errh, "bad BlendDesignMap");
+ for (int i = 0; i < _naxes; i++)
+ if (_normalize_in[i].size() != _normalize_out[i].size())
+ return error(errh, "bad BlendDesignMap");
+
+ if (!_axis_types.size())
+ _axis_types.assign(_naxes, PermString());
+ if (_axis_types.size() != _naxes)
+ return error(errh, "bad BlendAxisTypes");
+
+ if (!_axis_labels.size())
+ _axis_labels.assign(_naxes, PermString());
+ if (_axis_labels.size() != _naxes)
+ return error(errh, "bad axis labels");
+
+ if (!_default_design_vector.size())
+ _default_design_vector.assign(_naxes, UNKDOUBLE);
+ if (_default_design_vector.size() != _naxes)
+ return error(errh, "inconsistent design vector");
+
+ if (!_default_weight_vector.size())
+ _default_weight_vector.assign(_nmasters, UNKDOUBLE);
+ if (_default_weight_vector.size() != _nmasters)
+ return error(errh, "inconsistent weight vector");
+
+ _ok = true;
+ return true;
+}
+
+bool
+MultipleMasterSpace::check_intermediate(ErrorHandler *errh)
+{
+ if (!_ok || _cdv)
+ return true;
+
+ for (int a = 0; a < _naxes; a++)
+ for (int m = 0; m < _nmasters; m++)
+ if (_master_positions[m][a] != 0 && _master_positions[m][a] != 1) {
+ if (errh)
+ errh->warning("%s requires intermediate master conversion programs",
+ _font_name.c_str());
+ return false;
+ }
+
+ return true;
+}
+
+
+int
+MultipleMasterSpace::axis(PermString ax) const
+{
+ for (int a = 0; a < _naxes; a++)
+ if (_axis_types[a] == ax || _axis_labels[a] == ax)
+ return a;
+ return -1;
+}
+
+double
+MultipleMasterSpace::axis_low(int ax) const
+{
+ return _normalize_in[ax][0];
+}
+
+double
+MultipleMasterSpace::axis_high(int ax) const
+{
+ return _normalize_in[ax].back();
+}
+
+
+Vector<double>
+MultipleMasterSpace::empty_design_vector() const
+{
+ return Vector<double>(_naxes, UNKDOUBLE);
+}
+
+bool
+MultipleMasterSpace::set_design(NumVector &design_vector, int ax, double value,
+ ErrorHandler *errh) const
+{
+ if (ax < 0 || ax >= _naxes)
+ return error(errh, " has only %d axes", _naxes);
+
+ if (value < axis_low(ax)) {
+ value = axis_low(ax);
+ if (errh)
+ errh->warning("raising %s's %s to %g", _font_name.c_str(),
+ _axis_types[ax].c_str(), value);
+ }
+ if (value > axis_high(ax)) {
+ value = axis_high(ax);
+ if (errh)
+ errh->warning("lowering %s's %s to %g", _font_name.c_str(),
+ _axis_types[ax].c_str(), value);
+ }
+
+ design_vector[ax] = value;
+ return true;
+}
+
+bool
+MultipleMasterSpace::set_design(NumVector &design_vector, PermString ax_name,
+ double val, ErrorHandler *errh) const
+{
+ int ax = axis(ax_name);
+ if (ax < 0)
+ return error(errh, " has no `%s' axis", ax_name.c_str());
+ else
+ return set_design(design_vector, ax, val, errh);
+}
+
+
+bool
+MultipleMasterSpace::normalize_vector(ErrorHandler *errh) const
+{
+ NumVector &design = *_design_vector;
+ NumVector &norm_design = *_norm_design_vector;
+
+ for (int a = 0; a < _naxes; a++)
+ if (!KNOWN(design[a])) {
+ if (errh)
+ errh->error("must specify %s's %s coordinate", _font_name.c_str(), _axis_types[a].c_str());
+ return false;
+ }
+
+ // Move to normalized design coordinates.
+ norm_design.assign(_naxes, UNKDOUBLE);
+
+ if (_ndv) {
+ CharstringInterp ai;
+ if (!ai.interpret(this, &_ndv))
+ return error(errh, "%s in NDV program", ai.error_string().c_str());
+
+ } else
+ for (int a = 0; a < _naxes; a++) {
+ double d = design[a];
+ double nd = UNKDOUBLE;
+ const Vector<double> &norm_in = _normalize_in[a];
+ const Vector<double> &norm_out = _normalize_out[a];
+
+ if (d < norm_in[0])
+ nd = norm_out[0];
+ for (int i = 1; i < norm_in.size(); i++)
+ if (d >= norm_in[i-1] && d < norm_in[i]) {
+ nd = norm_out[i-1]
+ + ((d - norm_in[i-1])
+ * (norm_out[i] - norm_out[i-1])
+ / (norm_in[i] - norm_in[i-1]));
+ goto done;
+ }
+ if (d >= norm_in.back())
+ nd = norm_out.back();
+
+ done:
+ norm_design[a] = nd;
+ }
+
+ for (int a = 0; a < _naxes; a++)
+ if (!KNOWN(norm_design[a]))
+ return error(errh, "bad normalization");
+
+ return true;
+}
+
+
+bool
+MultipleMasterSpace::convert_vector(ErrorHandler *errh) const
+{
+ NumVector &norm_design = *_norm_design_vector;
+ NumVector &weight = *_weight_vector;
+
+ weight.assign(_nmasters, 1);
+
+ if (_cdv) {
+ CharstringInterp ai;
+ if (!ai.interpret(this, &_cdv))
+ return error(errh, "%s in CDV program", ai.error_string().c_str());
+
+ } else
+ for (int a = 0; a < _naxes; a++)
+ for (int m = 0; m < _nmasters; m++) {
+ if (_master_positions[m][a] == 0)
+ weight[m] *= 1 - norm_design[a];
+ else if (_master_positions[m][a] == 1)
+ weight[m] *= norm_design[a];
+ else
+ return error(errh, " requires intermediate master conversion programs");
+ }
+
+ return true;
+}
+
+
+bool
+MultipleMasterSpace::design_to_norm_design(const NumVector &design_in,
+ NumVector &norm_design,
+ ErrorHandler *errh) const
+{
+ NumVector design(design_in);
+ NumVector weight;
+
+ _design_vector = &design;
+ _norm_design_vector = &norm_design;
+ _weight_vector = &weight;
+ if (!normalize_vector(errh))
+ return false;
+ _design_vector = _norm_design_vector = _weight_vector = 0;
+
+ return true;
+}
+
+
+bool
+MultipleMasterSpace::design_to_weight(const NumVector &design_in, NumVector &weight, ErrorHandler *errh) const
+{
+ NumVector design(design_in);
+ NumVector norm_design;
+
+ bool dirty = false;
+ for (int i = 0; i < _naxes; i++)
+ if (design[i] != _default_design_vector[i])
+ dirty = true;
+
+ if (dirty) {
+ _design_vector = &design;
+ _norm_design_vector = &norm_design;
+ _weight_vector = &weight;
+ if (!normalize_vector(errh))
+ return false;
+ if (!convert_vector(errh))
+ return false;
+ _design_vector = _norm_design_vector = _weight_vector = 0;
+ } else
+ weight = _default_weight_vector;
+
+ double sum = 0;
+ for (int m = 0; m < _nmasters; m++)
+ sum += weight[m];
+ if (sum < 0.9999 || sum > 1.0001)
+ return error(errh, "bad conversion: weight vector doesn't sum to 1");
+
+ // adjust weight vector to max 4 decimal digits of precision, and make it
+ // sum to exactly 1
+ sum = 0;
+ for (int m = 0; m < _nmasters - 1; m++) {
+ weight[m] = floor(weight[m] * 10000. + 0.5) / 10000.;
+ sum += weight[m];
+ }
+ weight[_nmasters - 1] = 1 - sum;
+
+ return true;
+}
+
+
+Vector<double> *
+MultipleMasterSpace::mm_vector(VectorType t, bool writable) const
+{
+ if (t == VEC_WEIGHT)
+ return _weight_vector;
+ else if (t == VEC_NORM_DESIGN)
+ return _norm_design_vector;
+ else if (t == VEC_DESIGN && !writable)
+ return _design_vector;
+ else
+ return 0;
+}
+
+}
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1rw.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1rw.cc
new file mode 100644
index 00000000000..846297e6b67
--- /dev/null
+++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1rw.cc
@@ -0,0 +1,613 @@
+// -*- related-file-name: "../include/efont/t1rw.hh" -*-
+
+/* t1rw.{cc,hh} -- Type 1 font reading and writing
+ *
+ * Copyright (c) 1998-2012 Eddie Kohler
+ *
+ * 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 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <efont/t1rw.hh>
+#include <efont/t1cs.hh>
+#include <lcdf/straccum.hh>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+namespace Efont {
+
+unsigned char Type1Reader::xvalue_store[257];
+unsigned char *Type1Reader::xvalue = &Type1Reader::xvalue_store[1];
+
+void
+Type1Reader::static_initialize()
+{
+ if (xvalue['A'])
+ return;
+ // rely on static data being initialized to 0
+ xvalue['0'] = 0; xvalue['1'] = 1; xvalue['2'] = 2; xvalue['3'] = 3;
+ xvalue['4'] = 4; xvalue['5'] = 5; xvalue['6'] = 6; xvalue['7'] = 7;
+ xvalue['8'] = 8; xvalue['9'] = 9;
+ xvalue['A'] = 10; xvalue['B'] = 11; xvalue['C'] = 12; xvalue['D'] = 13;
+ xvalue['E'] = 14; xvalue['F'] = 15;
+ xvalue['a'] = 10; xvalue['b'] = 11; xvalue['c'] = 12; xvalue['d'] = 13;
+ xvalue['e'] = 14; xvalue['f'] = 15;
+}
+
+
+Type1Reader::Type1Reader()
+ : _data(new unsigned char[DATA_SIZE]), _len(0), _pos(0),
+ _ungot(-1), _eexec(false)
+{
+ static_initialize();
+}
+
+Type1Reader::~Type1Reader()
+{
+ delete[] _data;
+}
+
+
+void
+Type1Reader::set_charstring_definer(PermString x)
+{
+ _charstring_definer = x;
+}
+
+void
+Type1Reader::switch_eexec(bool on, unsigned char *data, int len)
+{
+ if (on) {
+ if (_pos < len + 3) {
+ unsigned char *new_data = new unsigned char[len + 3 + DATA_SIZE];
+ assert(_len <= DATA_SIZE);
+ memcpy(new_data + len + 3, _data + _pos, _len - _pos);
+ _len = len + 3 + _len - _pos;
+ _pos = len + 3;
+ delete[] _data;
+ _data = new_data;
+ }
+ int original_pos = _pos;
+ // don't forget _ungot!!
+ if (_ungot >= 0)
+ _data[--_pos] = _ungot, _ungot = -1;
+ if (_crlf == 0 || _crlf == 2)
+ _data[--_pos] = '\n';
+ if (_crlf == 1 || _crlf == 2)
+ _data[--_pos] = '\r';
+ memcpy(_data + _pos - len, data, len);
+ _pos -= len;
+ start_eexec(original_pos - _pos);
+ }
+ _eexec = on;
+}
+
+
+int
+Type1Reader::more_data()
+{
+ _pos = 0;
+ _len = more_data(_data, DATA_SIZE);
+ if (_len < 0)
+ return -1;
+ else
+ return _data[_pos++];
+}
+
+
+inline int
+Type1Reader::get_base()
+{
+ if (_pos >= _len)
+ return more_data();
+ else
+ return _data[_pos++];
+}
+
+
+inline int
+Type1Reader::eexec(int c)
+{
+ unsigned char answer = (unsigned char)(c ^ (_r >> 8));
+ _r = (((unsigned char)c + _r) * t1C1 + t1C2) & 0xFFFF;
+ return answer;
+}
+
+
+int
+Type1Reader::ascii_eexec_get()
+{
+ int d1 = get_base();
+ while (isspace(d1))
+ d1 = get_base();
+
+ int d2 = get_base();
+ while (isspace(d2))
+ d2 = get_base();
+ if (d2 < 0)
+ return -1;
+
+ return eexec((xvalue[d1] << 4) | (xvalue[d2]));
+}
+
+
+inline int
+Type1Reader::get()
+{
+ if (!_eexec)
+ return get_base();
+
+ else if (_binary_eexec) {
+ int c = get_base();
+ return c < 0 ? c : eexec(c);
+
+ } else
+ return ascii_eexec_get();
+}
+
+
+void
+Type1Reader::start_eexec(int initial_ascii)
+{
+ /* God damn this _ungot thing!! It makes sense not to check it on every
+ char fetch, since it can only be set at the end of next_line; therefore,
+ only the first get() into a user-visible function might need to check
+ _ungot. The problem is I forgot start_eexec() was such a function! */
+ int c = _ungot < 0 ? get_base() : _ungot;
+ initial_ascii--;
+ _ungot = -1;
+
+ /* Strictly speaking, I should look for whitespace even in binary sections
+ of PFB fonts; but it turns out some PFBs would be unreadable with that
+ pedantic rule. */
+ while (isspace(c) && (initial_ascii >= 0 || !preserve_whitespace()))
+ c = get_base(), initial_ascii--;
+
+ /* Differentiate between ASCII eexec and binary eexec. */
+ int rand_bytes[4];
+ _binary_eexec = false;
+ for (int i = 0; i < 4; i++) {
+ if (i)
+ c = get_base();
+ rand_bytes[i] = c;
+ if (!isxdigit(c))
+ _binary_eexec = true;
+ }
+
+ _r = t1R_ee;
+ if (_binary_eexec)
+ for (int i = 0; i < 4; i++)
+ eexec(rand_bytes[i]);
+ else {
+ for (int i = 0; i < 2; i++) {
+ c = xvalue[rand_bytes[i*2]] * 16 + xvalue[rand_bytes[i*2+1]];
+ eexec(c);
+ }
+ ascii_eexec_get();
+ ascii_eexec_get();
+ }
+}
+
+
+bool
+Type1Reader::test_charstring(StringAccum &str)
+{
+ /* PERFORMANCE NOTE: This function is definitely a bottleneck. Making it
+ more efficient cut time by about 40%. */
+
+ if (!_charstring_definer)
+ return false;
+ if (_charstring_len >= 0)
+ return str.length() <= _charstring_start + _charstring_len;
+
+ str.append('\0'); // protect against running off end of string
+ char *s = str.data();
+ char *start;
+ while (*s == ' ')
+ s++;
+
+ if (s[0] == '/')
+ s++;
+ else if (s[0] == 'd' && s[1] == 'u' && s[2] == 'p' && isspace((unsigned char) s[3])) {
+ s += 4;
+ // 17.Jan.2000 -- some fonts have extra space here.
+ while (isspace((unsigned char) *s))
+ s++;
+ } else
+ goto not_charstring;
+
+ // Force one literal space rather than isspace().
+ // Why? Consistency: we force 1 literal space around _charstring_definer.
+ while (*s != ' ' && *s)
+ s++;
+ if (*s++ != ' ' || !isdigit((unsigned char) *s))
+ goto not_charstring;
+ start = s;
+ s++;
+ while (*s != ' ' && *s)
+ s++;
+ if (strncmp(s, _charstring_definer.c_str(), _charstring_definer.length()) != 0)
+ goto not_charstring;
+
+ _charstring_len = strtol(start, 0, 10);
+ _charstring_start = (s - str.data()) + _charstring_definer.length();
+ str.pop_back();
+ return str.length() <= _charstring_start + _charstring_len;
+
+ not_charstring:
+ str.pop_back();
+ return false;
+}
+
+
+/* PERFORMANCE NOTE: All kinds of speedup tricks tried with eexec -- buffering
+ (doing eexec processing at more_data time), etc., and all this stuff -- and
+ found to have essentially zero effect for PFB fonts. Now, it might be
+ effective for PFAs; but who cares? I hate PFAs. */
+
+bool
+Type1Reader::next_line(StringAccum &s)
+{
+ if (_len < 0)
+ return false;
+
+ // Can't be a charstring if incoming accumulator has nonzero length.
+ _charstring_start = 0;
+ _charstring_len = (s.length() > 0 ? 0 : -1);
+
+ int first_char = _ungot < 0 ? get() : _ungot;
+ _ungot = -1;
+
+ for (int c = first_char; c >= 0; c = get())
+ switch (c) {
+
+ case '\n':
+ if (test_charstring(s))
+ goto normal;
+ else {
+ _crlf = 0;
+ goto done;
+ }
+
+ case '\r':
+ // check for \r\n (counts as only one line ending)
+ if (test_charstring(s))
+ goto normal;
+ c = get();
+ if (c != '\n' || preserve_whitespace())
+ _ungot = c, _crlf = 1;
+ else
+ _crlf = 2;
+ goto done;
+
+ normal:
+ default:
+ s.append((char)c);
+ break;
+
+ }
+
+ done:
+ return true;
+}
+
+
+int
+Type1Reader::get_data(unsigned char *data, int len)
+{
+ if (_len < 0)
+ return -1;
+ if (len <= 0)
+ return 0;
+
+ int pos = 0;
+ if (_ungot >= 0) {
+ *data++ = _ungot;
+ pos++;
+ _ungot = -1;
+ }
+
+ for (; pos < len; pos++) {
+ int c = get();
+ if (c < 0)
+ break;
+ *data++ = c;
+ }
+
+ return pos;
+}
+
+
+/*****
+ * Type1PFAReader
+ **/
+
+Type1PFAReader::Type1PFAReader(FILE *f)
+ : _f(f)
+{
+}
+
+int
+Type1PFAReader::more_data(unsigned char *data, int len)
+{
+ size_t size = fread(data, 1, len, _f);
+ return size ? (int)size : -1;
+}
+
+
+/*****
+ * Type1PFBReader
+ **/
+
+Type1PFBReader::Type1PFBReader(FILE *f)
+ : _f(f), _binary(false), _left(0)
+{
+}
+
+int
+Type1PFBReader::more_data(unsigned char *data, int len)
+{
+ while (_left == 0) {
+ int c = getc(_f);
+ if (c != 128)
+ return -1;
+
+ c = getc(_f);
+ if (c == 3 || c < 1 || c > 3)
+ return -1;
+ _binary = (c == 2);
+
+ _left = getc(_f);
+ _left |= getc(_f) << 8;
+ _left |= getc(_f) << 16;
+ _left |= getc(_f) << 24;
+ }
+
+ if (_left < 0)
+ return -1;
+
+ if (len > _left)
+ len = _left;
+ _left -= len;
+
+ return fread(data, 1, len, _f);
+}
+
+bool
+Type1PFBReader::preserve_whitespace() const
+{
+ return _binary;
+}
+
+
+/*****
+ * Type1SubsetReader
+ **/
+
+Type1SubsetReader::Type1SubsetReader(Type1Reader *r, int left)
+ : _reader(r), _left(left)
+{
+}
+
+int
+Type1SubsetReader::more_data(unsigned char *data, int len)
+{
+ if (_left <= 0)
+ return -1;
+ if (len > _left)
+ len = _left;
+ int how_much = _reader->get_data(data, len);
+ if (how_much > 0)
+ _left -= how_much;
+ return how_much;
+}
+
+bool
+Type1SubsetReader::preserve_whitespace() const
+{
+ return _reader->preserve_whitespace();
+}
+
+
+/*****
+ * Writer
+ **/
+
+Type1Writer::Type1Writer()
+ : _buf(new unsigned char[BufSize]), _pos(0),
+ _eexec(false), _eexec_start(-1), _eexec_end(-1), _lenIV(4)
+{
+}
+
+
+Type1Writer::~Type1Writer()
+{
+ assert(!_pos);
+ delete[] _buf;
+}
+
+
+inline unsigned char
+Type1Writer::eexec(int p)
+{
+ unsigned char c = ((unsigned char)p ^ (_r >> 8)) & 0xFF;
+ _r = ((c + _r) * t1C1 + t1C2) & 0xFFFF;
+ return c;
+}
+
+
+void
+Type1Writer::flush()
+{
+ local_flush();
+}
+
+
+/* PERFORMANCE NOTE: Doing eexec processing during flush -- which streamlines
+ code for the print() methods -- seems to save some time (4-5%). It also
+ makes write performance more consistent. But I have mixed feelings. */
+
+void
+Type1Writer::local_flush()
+{
+ if (_eexec_start >= 0 && _eexec_end < 0)
+ _eexec_end = _pos;
+ for (int p = _eexec_start; p < _eexec_end; p++)
+ _buf[p] = eexec(_buf[p]);
+ print0(_buf, _pos);
+ _pos = 0;
+ _eexec_start = _eexec ? 0 : -1;
+ _eexec_end = -1;
+}
+
+
+void
+Type1Writer::print(const char *s, int n)
+{
+ while (n > 0) {
+ if (_pos >= BufSize)
+ local_flush();
+ int copy = BufSize - _pos;
+ if (copy > n) copy = n;
+ memcpy(_buf + _pos, s, copy);
+ _pos += copy;
+ s += copy;
+ n -= copy;
+ }
+}
+
+
+Type1Writer &
+Type1Writer::operator<<(int x)
+{
+ char str[128];
+ sprintf(str, "%d", x);
+ print(str, strlen(str));
+ return *this;
+}
+
+
+Type1Writer &
+Type1Writer::operator<<(double x)
+{
+ char str[256];
+ sprintf(str, "%g", x);
+ print(str, strlen(str));
+ return *this;
+}
+
+
+void
+Type1Writer::switch_eexec(bool on)
+{
+ _eexec = on;
+ if (_eexec) {
+ _eexec_start = _pos;
+ _r = t1R_ee;
+ print("SUCK", 4);
+ } else
+ _eexec_end = _pos;
+}
+
+
+/*****
+ * Type1PFAWriter
+ **/
+
+Type1PFAWriter::Type1PFAWriter(FILE *f)
+ : _f(f), _hex_line(0)
+{
+}
+
+Type1PFAWriter::~Type1PFAWriter()
+{
+ flush();
+}
+
+
+void
+Type1PFAWriter::switch_eexec(bool on)
+{
+ flush();
+ _hex_line = 0;
+ Type1Writer::switch_eexec(on);
+}
+
+void
+Type1PFAWriter::print0(const unsigned char *c, int l)
+{
+ if (eexecing()) {
+ const char *hex = "0123456789ABCDEF";
+ for (; l; c++, l--) {
+ putc(hex[*c / 16], _f);
+ putc(hex[*c % 16], _f);
+ if (++_hex_line == 39) {
+ putc('\n', _f);
+ _hex_line = 0;
+ }
+ }
+ } else {
+ ssize_t result = fwrite(c, 1, l, _f);
+ (void) result;
+ }
+}
+
+
+/*****
+ * Type1PFBWriter
+ **/
+
+Type1PFBWriter::Type1PFBWriter(FILE *f)
+ : _f(f), _binary(false)
+{
+}
+
+Type1PFBWriter::~Type1PFBWriter()
+{
+ flush();
+ fputc(128, _f);
+ fputc(3, _f);
+}
+
+void
+Type1PFBWriter::flush()
+{
+ Type1Writer::flush();
+ if (_save.length()) {
+ fputc(128, _f);
+ fputc(_binary ? 2 : 1, _f);
+ long l = _save.length();
+ fputc(l & 0xFF, _f);
+ fputc((l >> 8) & 0xFF, _f);
+ fputc((l >> 16) & 0xFF, _f);
+ fputc((l >> 24) & 0xFF, _f);
+ ssize_t result = fwrite(_save.data(), 1, _save.length(), _f);
+ (void) result;
+ _save.clear();
+ }
+}
+
+void
+Type1PFBWriter::switch_eexec(bool on)
+{
+ flush();
+ Type1Writer::switch_eexec(on);
+ _binary = on;
+}
+
+void
+Type1PFBWriter::print0(const unsigned char *c, int l)
+{
+ char *m = _save.extend(l);
+ memcpy(m, c, l);
+}
+
+}
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1unparser.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1unparser.cc
new file mode 100644
index 00000000000..993253deec9
--- /dev/null
+++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/t1unparser.cc
@@ -0,0 +1,137 @@
+// -*- related-file-name: "../include/efont/t1unparser.hh" -*-
+
+/* t1unparser.{cc,hh} -- debug printing of Type 1 fonts
+ *
+ * Copyright (c) 1998-2012 Eddie Kohler
+ *
+ * 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 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <efont/t1unparser.hh>
+namespace Efont {
+
+CharstringUnparser::CharstringUnparser()
+ : CharstringInterp(),
+ _one_command_per_line(false), _start_of_line(true)
+{
+}
+
+CharstringUnparser::CharstringUnparser(const CharstringUnparser &o)
+ : CharstringInterp(o),
+ _one_command_per_line(o._one_command_per_line),
+ _start_of_line(o._start_of_line)
+{
+}
+
+void
+CharstringUnparser::clear()
+{
+ _sa.clear();
+ _start_of_line = true;
+}
+
+bool
+CharstringUnparser::number(double n)
+{
+ if (_start_of_line) {
+ _sa << _indent;
+ _start_of_line = false;
+ } else
+ _sa << ' ';
+ _sa << n;
+ return true;
+}
+
+bool
+CharstringUnparser::type1_command(int cmd)
+{
+ if (_start_of_line) {
+ _sa << _indent;
+ _start_of_line = false;
+ } else
+ _sa << ' ';
+ if (cmd >= 0 && cmd <= Cs::cLastCommand)
+ _sa << Cs::command_names[cmd];
+ else
+ _sa << "UNKNOWN_12_" << (cmd - 32);
+ if (_one_command_per_line) {
+ _sa << '\n';
+ _start_of_line = true;
+ }
+ return true;
+}
+
+bool
+CharstringUnparser::type2_command(int cmd, const unsigned char *data, int *left)
+{
+ if (_start_of_line) {
+ _sa << _indent;
+ _start_of_line = false;
+ } else
+ _sa << ' ';
+
+ if (cmd >= 0 && cmd <= Cs::cLastCommand)
+ _sa << Cs::command_names[cmd];
+ else
+ _sa << "UNKNOWN_12_" << (cmd - 32);
+
+ switch (cmd) {
+ case Cs::cHstem: case Cs::cHstemhm: case Cs::cVstem: case Cs::cVstemhm:
+ case Cs::cHintmask: case Cs::cCntrmask:
+ CharstringInterp::type2_command(cmd, data, left);
+ break;
+ }
+
+ if (_one_command_per_line) {
+ _sa << '\n';
+ _start_of_line = true;
+ }
+
+ return true;
+}
+
+void
+CharstringUnparser::act_hintmask(int, const unsigned char *data, int nhints)
+{
+ _sa << '[';
+ for (int i = 0; i < nhints; i++, data++)
+ sprintf(_sa.extend(2), "%02X", *data);
+ _sa << ']';
+}
+
+String
+CharstringUnparser::value()
+{
+ _start_of_line = true;
+ return _sa.take_string();
+}
+
+String
+CharstringUnparser::unparse(const Charstring *cs)
+{
+ if (cs) {
+ CharstringUnparser u;
+ u.interpret(0, cs);
+ return u.value();
+ } else
+ return "(null)";
+}
+
+String
+CharstringUnparser::unparse(const Charstring &cs)
+{
+ CharstringUnparser u;
+ u.interpret(0, &cs);
+ return u.value();
+}
+
+}
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/ttfcs.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/ttfcs.cc
new file mode 100644
index 00000000000..d427cf17bcc
--- /dev/null
+++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/ttfcs.cc
@@ -0,0 +1,212 @@
+// -*- related-file-name: "../include/efont/ttfcs.hh" -*-
+
+/* ttfcs.{cc,hh} -- TrueType "charstring" emulation
+ *
+ * Copyright (c) 2006-2012 Eddie Kohler
+ *
+ * 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 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <efont/ttfcs.hh>
+#include <efont/ttfhead.hh>
+#include <efont/t1csgen.hh>
+#include <efont/otfpost.hh>
+#include <efont/otfcmap.hh>
+#include <lcdf/hashmap.hh>
+namespace Efont {
+
+TrueTypeBoundsCharstringProgram::TrueTypeBoundsCharstringProgram(const OpenType::Font *otf)
+ : _otf(otf), _nglyphs(-1), _loca_long(false), _units_per_em(1024),
+ _loca(otf->table("loca")), _glyf(otf->table("glyf")),
+ _hmtx(otf->table("hmtx")), _got_glyph_names(false), _got_unicodes(false)
+{
+ OpenType::Data maxp(otf->table("maxp"));
+ if (maxp.length() >= 6)
+ _nglyphs = maxp.u16(4);
+
+ OpenType::Head head(otf->table("head"), 0);
+ if (head.ok()) {
+ _loca_long = head.index_to_loc_format() != 0;
+ _units_per_em = head.units_per_em();
+ }
+ if (_loca_long)
+ _loca.align_long();
+ int loca_onesize = (_loca_long ? 4 : 2);
+ if (_nglyphs >= _loca.length() / loca_onesize)
+ _nglyphs = (_loca.length() / loca_onesize) - 1;
+
+ // horizontal metrics
+ OpenType::Data hhea(_otf->table("hhea"));
+ // HHEA format:
+ // 0 Fixed Table version number 0x00010000 for version 1.0.
+ // 4 FWORD Ascender
+ // 6 FWORD Descender
+ // 8 FWORD LineGap
+ // 10 UFWORD advanceWidthMax
+ // 12 FWORD minLeftSideBearing
+ // 14 FWORD minRightSideBearing
+ // 16 FWORD xMaxExtent
+ // 18 SHORT caretSlopeRise
+ // 20 SHORT caretSlopeRun
+ // 22 SHORT caretOffset
+ // 24 SHORT (reserved)
+ // 26 SHORT (reserved)
+ // 28 SHORT (reserved)
+ // 30 SHORT (reserved)
+ // 32 SHORT metricDataFormat
+ // 34 USHORT numberOfHMetrics
+ if (hhea.length() >= 36
+ && hhea.u32(0) == 0x10000)
+ _nhmtx = hhea.u16(34);
+ if (_nhmtx * 4 > _hmtx.length())
+ _nhmtx = _hmtx.length() / 4;
+}
+
+TrueTypeBoundsCharstringProgram::~TrueTypeBoundsCharstringProgram()
+{
+ for (Charstring **cs = _charstrings.begin(); cs < _charstrings.end(); cs++)
+ delete *cs;
+}
+
+int
+TrueTypeBoundsCharstringProgram::units_per_em() const
+{
+ return _units_per_em;
+}
+
+int
+TrueTypeBoundsCharstringProgram::nglyphs() const
+{
+ return _nglyphs;
+}
+
+PermString
+TrueTypeBoundsCharstringProgram::glyph_name(int gi) const
+{
+ // generate glyph names based on what pdftex can understand
+ if (gi == 0)
+ return PermString(".notdef");
+
+ // try 'post' table glyph names
+ if (!_got_glyph_names) {
+ OpenType::Post post(_otf->table("post"));
+ if (post.ok())
+ post.glyph_names(_glyph_names);
+ _got_glyph_names = true;
+ }
+ if (gi >= 0 && gi < _glyph_names.size())
+ return _glyph_names[gi];
+
+ // try 'uniXXXX' names
+ if (!_got_unicodes) {
+ OpenType::Cmap cmap(_otf->table("cmap"));
+ if (cmap.ok())
+ cmap.unmap_all(_unicodes);
+ // make sure we only use uniquely identified glyphs
+ HashMap<uint32_t, int> unicode_usage(-1);
+ for (int g = 0; g < _unicodes.size(); g++)
+ if (_unicodes[g]) {
+ int i = unicode_usage.find_force(_unicodes[g], g);
+ if (i != g)
+ _unicodes[i] = _unicodes[g] = 0;
+ }
+ _got_unicodes = true;
+ }
+
+ if (gi >= 0 && gi < _unicodes.size() && _unicodes[gi] > 0 && _unicodes[gi] <= 0xFFFF) {
+ char buf[10];
+ sprintf(buf, "uni%04X", _unicodes[gi]);
+ return PermString(buf);
+ } else
+ return permprintf("index%d", gi);
+}
+
+void
+TrueTypeBoundsCharstringProgram::glyph_names(Vector<PermString> &gn) const
+{
+ gn.clear();
+ for (int gi = 0; gi < _nglyphs; gi++)
+ gn.push_back(glyph_name(gi));
+}
+
+Charstring *
+TrueTypeBoundsCharstringProgram::glyph(int gi) const
+{
+ if (gi < 0 || gi >= _nglyphs)
+ return 0;
+ if (_charstrings.size() <= gi)
+ _charstrings.resize(gi + 1, (Charstring *) 0);
+ if (!_charstrings[gi]) {
+ // calculate glyf offsets
+ uint32_t offset, end_offset;
+ if (_loca_long) {
+ offset = _loca.u32(gi * 4);
+ end_offset = _loca.u32(gi * 4 + 4);
+ } else {
+ offset = _loca.u16(gi * 2) * 2;
+ end_offset = _loca.u16(gi * 2 + 2) * 2;
+ }
+
+ // fetch bounding box from glyf
+ int ncontours, xmin, ymin, xmax, ymax;
+ if (offset != end_offset) {
+ if (offset > end_offset || offset + 10 > end_offset
+ || end_offset > (uint32_t) _glyf.length())
+ return 0;
+
+ ncontours = _glyf.s16(offset);
+ xmin = _glyf.s16(offset + 2);
+ ymin = _glyf.s16(offset + 4);
+ xmax = _glyf.s16(offset + 6);
+ ymax = _glyf.s16(offset + 8);
+ } else
+ ncontours = xmin = ymin = xmax = ymax = 0;
+
+ // fetch horizontal metrics
+ int advance_width, lsb;
+ if (gi >= _nhmtx) {
+ advance_width = (_nhmtx ? _hmtx.u16((_nhmtx - 1) * 4) : 0);
+ int hmtx_offset = _nhmtx * 4 + (gi - _nhmtx) * 2;
+ lsb = (hmtx_offset + 2 <= _hmtx.length() ? _hmtx.s16(hmtx_offset) : 0);
+ } else {
+ advance_width = _hmtx.u16(gi * 4);
+ lsb = _hmtx.s16(gi * 4 + 2);
+ }
+
+ // make charstring
+ Type1CharstringGen gen;
+ if (ncontours == 0) {
+ gen.gen_number(0, 'X');
+ gen.gen_number(advance_width);
+ gen.gen_command(Charstring::cHsbw);
+ } else {
+ gen.gen_number(lsb, 'X');
+ gen.gen_number(advance_width);
+ gen.gen_command(Charstring::cHsbw);
+ gen.gen_moveto(Point(xmin, ymin), false, false);
+ if (xmax != xmin || ymax == ymin)
+ gen.gen_number(xmax - xmin, 'x');
+ if (ymax != ymin)
+ gen.gen_number(ymax - ymin, 'y');
+ gen.gen_command(ymax == ymin ? Charstring::cHlineto
+ : (xmax == xmin ? Charstring::cVlineto
+ : Charstring::cRlineto));
+ gen.gen_command(Charstring::cClosepath);
+ }
+ gen.gen_command(Charstring::cEndchar);
+
+ _charstrings[gi] = gen.output();
+ }
+ return _charstrings[gi];
+}
+
+}
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/ttfhead.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/ttfhead.cc
new file mode 100644
index 00000000000..5be8676c64c
--- /dev/null
+++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/ttfhead.cc
@@ -0,0 +1,69 @@
+// -*- related-file-name: "../include/efont/ttfhead.hh" -*-
+
+/* ttfhead.{cc,hh} -- TrueType head table
+ *
+ * Copyright (c) 2007-2012 Eddie Kohler
+ *
+ * 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 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <efont/ttfhead.hh>
+#include <lcdf/error.hh>
+#include <lcdf/straccum.hh>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <algorithm>
+
+namespace Efont { namespace OpenType {
+
+Head::Head(const String &s, ErrorHandler *errh)
+ : _d(s)
+{
+ _error = parse_header(errh ? errh : ErrorHandler::silent_handler());
+}
+
+int
+Head::parse_header(ErrorHandler *errh)
+{
+ // HEAD format:
+ // 0 Fixed Table version number 0x00010000 (ver. 1.0)
+ // 4 Fixed fontRevision
+ // 8 ULONG checkSumAdjustment
+ // 12 ULONG magicNumber Set to 0x5F0F3CF5
+ // 16 USHORT flags
+ // 18 USHORT unitsPerEm
+ // 20 LONGDATETIME created
+ // 28 LONGDATETIME modified
+ // 36 USHORT xMin
+ // 38 SHORT yMin
+ // 40 SHORT xMax
+ // 42 SHORT yMax
+ // 44 USHORT macStyle
+ // 46 USHORT lowestRecPPEM
+ // 48 SHORT fontDirectionHint
+ // 50 SHORT indexToLocFormat
+ // 52 SHORT glyphDataFormat
+ int len = _d.length();
+ const uint8_t *data = _d.udata();
+ if (len == 0)
+ return errh->error("font has no 'head' table"), -EFAULT;
+ if (54 > len)
+ return errh->error("'head' table too small"), -EFAULT;
+ if (!(data[0] == '\000' && data[1] == '\001'))
+ return errh->error("bad 'head' version number"), -ERANGE;
+ if (_d.u32(12) != 0x5F0F3CF5)
+ return errh->error("bad 'head' magic number"), -ERANGE;
+ return 0;
+}
+
+}}
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/ttfkern.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/ttfkern.cc
new file mode 100644
index 00000000000..824922457ac
--- /dev/null
+++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.95/libefont/ttfkern.cc
@@ -0,0 +1,116 @@
+// -*- related-file-name: "../include/efont/ttfkern.hh" -*-
+
+/* ttfkern.{cc,hh} -- TrueType kern table
+ *
+ * Copyright (c) 2009-2012 Eddie Kohler
+ *
+ * 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 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <efont/ttfkern.hh>
+#include <lcdf/error.hh>
+#include <lcdf/straccum.hh>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <algorithm>
+
+namespace Efont { namespace OpenType {
+
+inline Data
+KernTable::subtable(uint32_t &off_in_out) const throw (Error)
+{
+ uint32_t off = off_in_out, len;
+ if (_version == 0) {
+ if (_d.u16(off) != 0)
+ throw new Format("kern subtable");
+ len = _d.u16(off + 2);
+ } else
+ len = _d.u32(off);
+ if (len < 6 || off + len > (uint32_t) _d.length())
+ throw new Bounds();
+ off_in_out = off + len;
+ return _d.substring(off, len);
+}
+
+KernTable::KernTable(const Data &d, ErrorHandler *) throw (Error)
+ : _d(d), _error(-1)
+{
+ // USHORT Version
+ // USHORT nTables
+ if (d.length() == 0)
+ throw BlankTable("kern");
+
+ uint32_t ntables, off;
+ if (d.u16(0) == 0) {
+ ntables = d.u16(2);
+ _version = 0;
+ off = 4;
+ } else if (d.u16(0) == 1) {
+ ntables = d.u32(4);
+ _version = 1;
+ off = 8;
+ } else
+ throw Format("kern");
+
+ for (uint32_t i = 0; i < ntables; ++i)
+ (void) subtable(off);
+
+ _error = 0;
+}
+
+bool
+KernTable::unparse_automatics(Vector<Positioning> &v, ErrorHandler *errh) const
+{
+ uint32_t ntables = this->ntables();
+ uint32_t off = first_offset();
+ int success = 0;
+ if (_error < 0)
+ return false;
+
+ for (uint16_t i = 0; i < ntables; ++i) {
+ Data subt = _d.subtable(off);
+ uint16_t coverage = subt.u16(4);
+
+ if (_version == 0) {
+ if ((coverage & COV_V0_HORIZONTAL) == 0
+ || (coverage & (COV_V0_MINIMUM | COV_V0_CROSS_STREAM
+ | COV_V0_OVERRIDE)) != 0
+ || (coverage & COV_V0_FORMAT) != COV_V0_FORMAT0)
+ continue;
+ } else {
+ if ((coverage & (COV_V1_VERTICAL | COV_V1_CROSS_STREAM
+ | COV_V1_VARIATION)) != 0
+ || (coverage & COV_V1_FORMAT) != COV_V1_FORMAT0)
+ continue;
+ }
+
+ try {
+ uint32_t off = (_version ? 16 : 14);
+ uint16_t npairs = subt.u16(off - 8);
+ for (uint16_t j = 0; j < npairs; ++j, off += 6) {
+ v.push_back(Positioning(Position(subt.u16(off), 0, 0, subt.s16(off + 4), 0),
+ Position(subt.u16(off + 2), 0, 0, 0, 0)));
+ ++success;
+ }
+ } catch (Error e) {
+ if (errh)
+ errh->warning("%s, continuing", e.description.c_str());
+ }
+ }
+
+ return success > 0;
+}
+
+}}
+
+#include <lcdf/vector.cc>