summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/pdftexdir
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2006-01-17 21:41:51 +0000
committerKarl Berry <karl@freefriends.org>2006-01-17 21:41:51 +0000
commit487ca4806cc046076293cf6cc5fbba0db282bac7 (patch)
tree847b412ab5158dd7bdd7ed7e5a4cc3fbca94be32 /Build/source/texk/web2c/pdftexdir
parenta3d3111bfe26b8e5f5bc6049dfb2a4ca2edc7881 (diff)
texk 1
git-svn-id: svn://tug.org/texlive/trunk@1485 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/web2c/pdftexdir')
-rw-r--r--Build/source/texk/web2c/pdftexdir/ChangeLog104
-rw-r--r--Build/source/texk/web2c/pdftexdir/Makefile.in60
-rw-r--r--Build/source/texk/web2c/pdftexdir/NEWS400
-rw-r--r--Build/source/texk/web2c/pdftexdir/README90
-rw-r--r--Build/source/texk/web2c/pdftexdir/avl.c890
-rw-r--r--Build/source/texk/web2c/pdftexdir/avl.h123
-rw-r--r--Build/source/texk/web2c/pdftexdir/avlstuff.c131
-rw-r--r--Build/source/texk/web2c/pdftexdir/avlstuff.h29
-rw-r--r--Build/source/texk/web2c/pdftexdir/change-files.txt132
-rw-r--r--Build/source/texk/web2c/pdftexdir/depend.mak0
-rw-r--r--Build/source/texk/web2c/pdftexdir/depend.mk54
-rw-r--r--Build/source/texk/web2c/pdftexdir/epdf.c75
-rw-r--r--Build/source/texk/web2c/pdftexdir/epdf.h103
-rw-r--r--Build/source/texk/web2c/pdftexdir/hz.ch1935
-rw-r--r--Build/source/texk/web2c/pdftexdir/image.h104
-rw-r--r--Build/source/texk/web2c/pdftexdir/macnames.c312
-rw-r--r--Build/source/texk/web2c/pdftexdir/mapfile.c1150
-rw-r--r--Build/source/texk/web2c/pdftexdir/misc.ch21
-rw-r--r--Build/source/texk/web2c/pdftexdir/noligatures.ch116
-rw-r--r--Build/source/texk/web2c/pdftexdir/pdfstrcmp.ch609
-rw-r--r--Build/source/texk/web2c/pdftexdir/pdftex.ch6853
-rw-r--r--Build/source/texk/web2c/pdftexdir/pdftex.defines105
-rw-r--r--Build/source/texk/web2c/pdftexdir/pdftex.h50
-rw-r--r--Build/source/texk/web2c/pdftexdir/pdftex.mak199
-rw-r--r--Build/source/texk/web2c/pdftexdir/pdftex.mk201
-rw-r--r--Build/source/texk/web2c/pdftexdir/pdftex2.ch89
-rw-r--r--Build/source/texk/web2c/pdftexdir/pdftexextra.in40
-rw-r--r--Build/source/texk/web2c/pdftexdir/pdftexlib.mk76
-rw-r--r--Build/source/texk/web2c/pdftexdir/pdftoepdf.cc1072
-rw-r--r--Build/source/texk/web2c/pdftexdir/pdftosrc.cc130
-rw-r--r--Build/source/texk/web2c/pdftexdir/pdftosrc.rc35
-rw-r--r--Build/source/texk/web2c/pdftexdir/pkin.c427
-rw-r--r--Build/source/texk/web2c/pdftexdir/ptexlib.h219
-rw-r--r--Build/source/texk/web2c/pdftexdir/ptexmac.h196
-rw-r--r--Build/source/texk/web2c/pdftexdir/randoms.ch569
-rw-r--r--Build/source/texk/web2c/pdftexdir/tex.ch042
-rw-r--r--Build/source/texk/web2c/pdftexdir/tex.ch139
-rw-r--r--Build/source/texk/web2c/pdftexdir/tex.pch355
-rw-r--r--Build/source/texk/web2c/pdftexdir/ttf2afm.c998
-rw-r--r--Build/source/texk/web2c/pdftexdir/ttf2afm.rc35
-rw-r--r--Build/source/texk/web2c/pdftexdir/utils.c1129
-rw-r--r--Build/source/texk/web2c/pdftexdir/vadjust.ch273
-rw-r--r--Build/source/texk/web2c/pdftexdir/vfpacket.c116
-rw-r--r--Build/source/texk/web2c/pdftexdir/win32.mak71
-rw-r--r--Build/source/texk/web2c/pdftexdir/writeenc.c145
-rw-r--r--Build/source/texk/web2c/pdftexdir/writefont.c318
-rw-r--r--Build/source/texk/web2c/pdftexdir/writeimg.c354
-rw-r--r--Build/source/texk/web2c/pdftexdir/writejpg.c227
-rw-r--r--Build/source/texk/web2c/pdftexdir/writepng.c593
-rw-r--r--Build/source/texk/web2c/pdftexdir/writet1.c1780
-rw-r--r--Build/source/texk/web2c/pdftexdir/writet3.c389
-rw-r--r--Build/source/texk/web2c/pdftexdir/writettf.c1257
-rw-r--r--Build/source/texk/web2c/pdftexdir/writettf.h130
-rw-r--r--Build/source/texk/web2c/pdftexdir/writezip.c82
54 files changed, 25032 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/pdftexdir/ChangeLog b/Build/source/texk/web2c/pdftexdir/ChangeLog
new file mode 100644
index 00000000000..a0a770ed962
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/ChangeLog
@@ -0,0 +1,104 @@
+2004-10-29 Jan Nieuwenhuizen <janneke@gnu.org>
+
+ * pdftex.mk (pdftex): Build fix: pdftexextra.c depends on
+ pdftexextra.h.
+
+2004-09-07 The pdfTeX team:
+
+ * README: pdftex version 1.20a.
+
+ * NEWS: pdftex version 1.20a.
+
+ * pdftex.ch: pdftex version 1.20a.
+
+2004-08-26 Olaf Weber <olaf@infovore.xs4all.nl>
+
+ * pdftexlib.mk (pdftexdir/libpdf.a): Add pdftexdir/pdftexextra.h
+ to the dependencies, so it gets built before we go and try to
+ build the library.
+
+ * pdftex.version: Is from now on a generated file.
+
+ * pdftexextra.in: Renamed from pdftexextra.h; the current pdfTeX
+ version is substituted from pdftex.version. Variant of code
+ supplied by Peter Breitenlohner <peb@mppmu.mpg.de>.
+
+ * pdftex.mk: Added rules to extract current pdfTeX version from
+ pdftex.ch and insert into pdftex.version and pdftexextra.h.
+ Variant of code supplied by Peter Breitenlohner
+ <peb@mppmu.mpg.de>.
+
+2004-08-25 Olaf Weber <olaf@infovore.xs4all.nl>
+
+ * vadjust.ch: Moved here from pdfxtexdir.
+
+ * pdftex.mk: vadjust.ch moved to this directory from pdfxtexdir.
+
+2004-08-23 Olaf Weber <olaf@infovore.xs4all.nl>
+
+ * pdftex.mk: Scrap rules for pdftexinfo. These are obsolete.
+
+ * pdftex.mak: Scrap rules for pdftexinfo.
+
+2004-08-06 Olaf Weber <olaf@infovore.xs4all.nl>
+
+ * Makefile.in: The .cc.o suffix rule should use ALL_CXXFLAGS (as
+ is done for ALL_CFLAGS). From Jan Nieuwenhuizen
+ <janneke@gnu.org>.
+
+2004-07-29 Peter Breitenlohner <peb@mppmu.mpg.de>
+
+ * pdftex.ch, hz.ch: Somewhat rearrange handling of kern and
+ math nodes in order to reduce interference between eTeX and
+ pdfTeX change files. Somewhat disentangle margin kerns such
+ that pdftex.web and pdfetex.web can be built with or without
+ hz.ch (not true for pdf*tex.ch).
+
+2004-07-25 Peter Breitenlohner <peb@mppmu.mpg.de>
+
+ * pdftex.ch: Reorganize additional command codes for convert
+ and last_item in order to reduce interference between eTeX and
+ pdfTeX change files.
+
+ * change-files.txt: Adjust to current status.
+
+2004-07-23 Peter Breitenlohner <peb@mppmu.mpg.de>
+
+ * pdftex.ch, tex.ch[01], tex.pch: Reorganize handling of banner
+ string in order to reduce interference between eTeX, pdfTeX,
+ and web2c change files.
+
+2004-07-22 Peter Breitenlohner <peb@mppmu.mpg.de>
+
+ * pdftex.ch: Removed unused token types for pdfTeX's additional
+ token list parameters.
+
+2004-07-19 Peter Breitenlohner <peb@mppmu.mpg.de>
+
+ * hz.ch, pdftex.ch, tex.ch[01], tex.pch: Reorganize handling of
+ additional token list and integer parameters in order to reduce
+ interference between eTeX, pdfTeX, and web2c change files.
+
+ * pdftex.ch: Add a note that this file not only defines pdftex.web
+ in terms of changes to be applies to tex.web, but in addition
+ is used to define pdfetex.web.
+
+ * tex.pch: Add a note that this file is used to construct the
+ web2c change files for both pdfTeX and pfdeTeX.
+
+ * pdftex.mk (pdftex.ch): Remove tex.ch2 from build rules.
+
+ * tex.ch2: Removed
+
+2004-07-17 Peter Breitenlohner <peb@mppmu.mpg.de>
+
+ * pdftex.mk: Rewrite build rules for pdftex.{web,ch}.
+
+ * pdftex.ch: Adapt glue and leader box rounding to TeX 3.141592.
+ Remove a few modules that were identical copies of those in TeX.
+
+2004-07-16 Peter Breitenlohner <peb@mppmu.mpg.de>
+
+ * ttf2afm.c: Add various const's, to avoid compiler warnings.
+
+ * ChangeLog: New file.
diff --git a/Build/source/texk/web2c/pdftexdir/Makefile.in b/Build/source/texk/web2c/pdftexdir/Makefile.in
new file mode 100644
index 00000000000..631e10c9861
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/Makefile.in
@@ -0,0 +1,60 @@
+# Makefile for libpdf - te@dbs.uni-hannover.de
+# $Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/Makefile.in#23 $
+
+kpse_include ../make/common.mk
+kpse_include ../make/programs.mk
+kpse_include ../make/library.mk
+
+kpathsea_srcdir_parent = $(srcdir)/../..
+kpathsea_dir_parent = ../..
+
+ALL_CXXFLAGS = @CXXFLAGS@ @DEFS@ $(XXCFLAGS) -I. -I$(srcdir) -I$(kpathsea_dir_parent) -I$(kpathsea_srcdir_parent) @LIBXPDFCPPFLAGS@
+CXX = @CXX@
+
+.SUFFIXES: .cc .o
+.cc.o:
+ $(CXX) $(ALL_CXXFLAGS) -c $<
+
+# XCFLAGS=-Wstrict-prototypes -Wmissing-prototypes
+
+LIBPNGDIR=../../../libs/libpng
+LIBPNGSRCDIR=$(srcdir)/$(LIBPNGDIR)
+
+ZLIBDIR=../../../libs/zlib
+ZLIBSRCDIR=$(srcdir)/$(ZLIBDIR)
+
+LIBXPDFDIR=../../../libs/xpdf
+LIBXPDFSRCDIR=$(srcdir)/$(LIBXPDFDIR)
+
+LIBMD5DIR=../../../libs/md5
+LIBMD5SRCDIR=$(srcdir)/$(LIBMD5DIR)
+
+XCPPFLAGS=-I.. -I$(srcdir)/.. -I../.. -I$(srcdir)/../.. -I$(LIBMD5DIR) -I$(LIBMD5SRCDIR)\
+@LIBPNGCPPFLAGS@ @ZLIBCPPFLAGS@ -DpdfTeX
+
+
+OBJS = epdf.o mapfile.o utils.o vfpacket.o pkin.o \
+writefont.o writet1.o writet3.o writezip.o writeenc.o writettf.o \
+writejpg.o writepng.o writeimg.o pdftoepdf.o avl.o avlstuff.o
+
+all: libpdf.a
+
+pdftosrc.o: $(srcdir)/pdftosrc.cc
+
+libpdf.a: $(OBJS)
+ rm -f $@
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+ $(RANLIB) $@
+
+kpse_include ../make/clean.mk
+
+clean::
+ rm -f libpdf.a ttf2afm pdftosrc
+
+depend:
+ rm -f $(OBJS) ttf2afm.o pdftosrc.o
+ XXCFLAGS=-MM XCFLAGS=-MM $(MAKE) -k $(OBJS) ttf2afm.o pdftosrc.o | \
+ grep -v "^$(CC)\|$(CXX)\|$(AR)\|make\|klibtool" | \
+ sed 's: [^ ]*/\.\./libs/[^ ]*::g' > $(srcdir)/depend.mk
+
+kpse_include pdftexdir/depend.mk
diff --git a/Build/source/texk/web2c/pdftexdir/NEWS b/Build/source/texk/web2c/pdftexdir/NEWS
new file mode 100644
index 00000000000..98e30db8b7f
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/NEWS
@@ -0,0 +1,400 @@
+-------------------------------------------------
+pdfTeX 3.141592-1.30.4 was released on 2005-10-17
+-------------------------------------------------
+- bugfix: whitespaces in filenames didn't work on Unix anymore (bug 377)
+- bugfix: two \immediates cancel themselves (bug 437)
+- bugfix: wrong file name in error messages of image inclusion (bug 435)
+
+-------------------------------------------------
+pdfTeX 3.141592-1.30.3 was released on 2005-09-04
+-------------------------------------------------
+- bugfix: \write18
+
+-------------------------------------------------
+pdfTeX 3.141592-1.30.2 was released on 2005-08-25
+-------------------------------------------------
+- fixed some build problems and minor bugs introduced in 1.30.1
+
+-------------------------------------------------
+pdfTeX 3.141592-1.30.1 was released on 2005-08-21
+-------------------------------------------------
+- the eTeX extensions can now be enabled with the cmdline switch -etex
+- pdfTeX uses xpdf 3.01
+
+-------------------------------------------------
+pdfTeX 3.141592-1.30.0 was released on 2005-08-01
+-------------------------------------------------
+- pdfxtex (introduced with 1.20a) is gone; all extensions are now in pdf(e)tex.
+- Some primitives have been renamed; the old names will still work, but are
+ deprecated and some give a warning that they are obsolete:
+ \pdfoptionpdfminorversion -> \pdfminorversion
+ \pdfoptionalwaysusepdfpagebox -> \pdfforcepagebox
+ \pdfoptionpdfinclusionerrorlevel -> \pdfinclusionerrorlevel
+- pdftex knows two new units:
+ - new Didot (1nd=0.375mm)
+ - new Cicero (1nc=12nd)
+- New primitives:
+ - Inclusion of pngs has been greatly improved: It now does
+ - alpha channel and transparency (only if %!PDF >=1.4)
+ - 16-bit colour (only if %!PDF >=1.5); this must be enabled by setting
+ \pdfimagehicolor to 1.
+ - gamma correction; this must be enabled by setting \pdfimageapplygamma to
+ 1. The device gamma is taken from \pdfgamma. If no embedded value can be
+ found in the png image, then the value of \pdfimagegamma is used instead.
+ - fast direct embedding of png streams, if their structure allows this; the
+ automatic fall-back is to decompress and re-compress as before.
+ - pdfTeX now has an interface to the precise system time (if available) as an
+ aid in benchmarking TeX macro code.
+ - \pdfelapsedtime is a read-only integer that (initially) returns the
+ amount of time passed since the start of this run. This amount is given
+ in `scaled seconds': the value 65536 counts as one second. If more time
+ has passed than 32767 seconds, (2^31)-1 will be returned.
+ - \pdfresettimer updates the internal timer, such that subsequent calls to
+ \pdfelapsedtime will restart from 0.
+ - pdfTeX can now generate random numbers:
+ - \pdfuniformdeviate <count> generates a uniformly distributed random
+ integer value between 0 (inclusive) and <count> (exclusive).
+ - \pdfnormaldeviate expands to a random integer value with a mean of 0 and
+ a unit of 65536.
+ - \pdfrandomseed allows access to the current seed value.
+ - \pdfsetrandomseed <count> sets the random seed to a specific value.
+ - \pdfnoligatures\f disables ligatures for the loaded font \f.
+ - Escaping strings:
+ - \pdfescapestring{<a>} escapes the string <a> so that it can be used as
+ PDF string.
+ - \pdfescapename{<a>} escapes the string <a> so that it can be used as PDF
+ name.
+ - \pdfescapehex{<a>} converts the string <a> to uppercase hexadecimal
+ representation.
+ - \pdfunescapehex{<b>} reverses the effect of \pdfescapehex
+ - \pdfcreationdate expands to the date string that pdfTeX uses in the info
+ dict as default.
+ - \pdffilemoddate{<file>} expands to the modification date of <file> in the
+ same format as \pdfcreationdate (PDF date format).
+ - \pdffilesize{<file>} expands to the size of <file> as string.
+ - \pdfmdfivesum{<abc>} or \pdfmdfivesum file {<file>} calculates the md5
+ sum (of a string or a file) and converts it to uppercase hexadecimal format
+ (same as \pdfescapehex).
+ - \pdffiledump [offset <int>] [length <int>] <general text>
+ Expands to a hex dump of the file given in <general text>, starting at
+ given offset or 0 with given length.
+ - \pdfshellescape is a read-only integer that is 1 if \write18 is enabled, 0
+ otherwise.
+ - \pdfxformname <object number>, which expands to the number in the
+ corresponding form XObject name.
+ - \leftmarginkern <box number> and \rightmarginkern <box number> tell the
+ margin kern at the left and right side of the horizontal list stored in box
+ <box number>.
+ - \pdfpkmode is a token register that sets the MF mode for pixel font
+ generation. The contents of this register is dumped into the format, so one
+ can (optionally) preset it e.g. in part of pdftexconfig.tex.
+ - \pdftracingfonts: An integer variable controlling the tracing of font
+ expansion. It is zero by default; then we get a log (with fontexpansion)
+ like this
+ ...\tenrm t
+ ...\tenrm (+20) e
+ Without font expansion, this default should be compatible with TeX's
+ original log output.
+ If \pdftracingfonts is set to 1 (or greater), we get a more verbose log:
+ ...\xivtt (cmtt10@14.0pt) t
+ ...\xivtt (cmtt10+20@14.0pt) e
+ See also bug 304.
+- New experimental primitives:
+ - \pdfmatch [icase] [subcount <number>}] {<pattern>}{<string>}
+ Implements pattern matching using the POSIX regex.
+ It returns the same values as \pdfstrcmp, but with the following semantics:
+ -1: error case (invalid pattern, ...)
+ 0: no match
+ 1: match found
+ Options:
+ * icase: case insensitive matching
+ * subcount: it sets the table size for found subpatterns.
+ A number "-1" resets the table size to the start default.
+ - \pdflastmatch <number>
+ The result of \pdfmatch is stored in an array. The entry "0" contains the
+ match, the following entries submatches. The positions of the matches are
+ also available. They are encoded:
+ <position> "->" <match string>
+ The position "-1" with an empty string indicates that this entry is not
+ set.
+ - \pdfstrcmp{<a>}{<b>} compares two strings and returns the strings "0" if
+ <a> equals <b>, "-1" if <a> is less than <b>, "1" if <a> is greater than
+ <b>
+- The primitive \pdfmovechars has been removed (bug 294)
+- Bugfixes:
+ - empty strings are not supressed anymore (bug 335)
+ - \unhboxing and character protusion didn't work well together (bug 292)
+ - --jobname didn't work if there was no filename at all (bug 302)
+ - Some problem with fonts on solaris (bug 315)
+ - Dangling font objects with non-replacable fonts (bug 311).
+ - \pdfxform didn't work with box>255 (bug 310)
+ - cmap: unicode ???? is mapped to multiple glyphs (bug 306).
+- pdfTeX uses zlib 1.2.3
+
+------------------------------------------------
+pdfTeX 3.141592-1.21a was released on 2005-02-04
+------------------------------------------------
+- ttf2afm 1.0:
+ - added support for refering to glyphs via unicode in encoding files (ie 'uniXXX')
+ - added some more info to the AFM output
+ - some minor bug fixes
+ - a short documentation available
+- pdftex now understand forms 'uniXXXX' in encoding files (only makes sense
+ with TrueType fonts)
+- added subset tag for TrueType fonts
+- PDF strings are now printed as following:
+ (This is a string) -> (This is a string)
+ This is a string -> (This is a string)
+ <a1b245c1a2...> -> <a1b245c1a2...>
+- check for double newline char to get rid of empty lines in PDF output
+- Fixed a bug in the scanning of map lines introduced in the fix of bug #242 in
+ 1.20b.
+- Fixed three problems in xpdf; xpdf is now 3.00pl3
+- \ifeof18 is a simple method to test if \write18 is enabled.
+- a few extensions in pdfxtex:
+ - \pdflastximagecolordepth returns the last color depth
+ - \pdfximage supports a keyword "colorspace" following an object number
+ representing a ColorSpace object
+ - \pdfstrcmp compares two strings
+ - \pdfescapestring/\pdflastescapedstring provide a way to escape string
+ - \pdffirstlineheight/\pdflastlinedepth/\pdfeachlineheight/\pdfeachlinedepth
+ allow fixing line dimen
+ - patches from Taco
+ - px dimen unit
+ - tagcode patch
+ - quitvmode patch
+
+------------------------------------------------
+pdfTeX 3.141592-1.20b was released on 2004-12-22
+------------------------------------------------
+- Fixed some minor bugs, mostly with hz
+- The info line "output format initialized to PDF/DVI" isn't shown anymore, as
+ this info wasn't reliable (bug 112).
+- Now the PDF-related statistics (PDF objects...) in the .log file is only
+ shown in PDF output mode. It start with a line "PDF statistics:".
+- \pdfimageresolution is not limited to 2400 [dpi] anymore, can now be between
+ 0 and 65535 [dpi].
+- pdfTeX uses xpdf 3.00pl2
+- pdfTeX uses libpng 1.2.8, which fixes some png-related bugs.
+
+------------------------------------------------
+pdfTeX 3.141592-1.20a was released on 2004-09-06
+------------------------------------------------
+- There is a new program pdfxtex, which contains experimental features which
+ might end up in pdftex in the future.
+- Most distributions now use eTeX as the default engine, so when you call
+ pdftex you will get pdfeTeX. Most distributions now also use pdfTeX as the
+ default engine, so when you call latex you will get pdfeTeX running LaTeX.:-)
+- We are setting up pdfTeX as a project at sarovar
+ (http://sarovar.org/projects/pdftex/). Please report bugs etc. through the
+ site.
+- Support for the file pdftex.cfg is gone completely. All parameters that had
+ previously been set by it can be set through primitives; their values are
+ dumped to the format file.
+- The searchpath for encoding and mapfiles has been changed.
+ See http://tug.org/pipermail/tex-live/2004-January/004734.html and
+ http://tug.org/pipermail/tex-live/2004-January/004791.html
+- eTeX is now version 2.2, incorporating the last changes to TeX (3.141592).
+- New options for \pdfmapfile:
+ General functionality: Map items (map files, new: also single map lines; see
+ \pdfmapline) are put in list of pending map items. During the next shipout,
+ pending map items are sequentially scanned for their map entries, and an
+ internal map entry database is updated, using the modes below. Then the list
+ of pending map items is cleared. Map entries of fonts already in use are left
+ untouched. New: All \pdfmapfile and \pdfmapline commands can also be given
+ after shipout of the first page.
+ - \pdfmapfile {foo.map} clears the list of pending map items and starts a new
+ list with the only pending file foo.map. When the map entry lines of
+ foo.map are scanned, duplicate map entries are ignored and a warning is
+ issued. This is the old behaviour.
+ - \pdfmapfile {+foo.map} puts foo.map in the list of pending map items. When
+ the map entry lines of foo.map are scanned, duplicate map entries are
+ ignored and a warning is issued.
+ - \pdfmapfile {=foo.map} puts foo.map in the list of pending map items. When
+ foo.map is scanned, matching map entries in database are replaced by new
+ entries from foo.map.
+ - \pdfmapfile {-foo.map} puts foo.map in the list of pending map items. When
+ foo.map is scanned, matching map entries are deleted from database.
+ - \pdfmapfile {} clears the list of pending map items. It does not affect map
+ entries already registered into the database. This is the old behaviour.
+- New command \pdfmapline {line}. It's like \pdfmapfile but here you can set
+ single map lines like in the map files directly. The modifiers (+-=) have the
+ same effect as with \pdfmapfile.
+- Simplified the handling of the 14 Type 1 "standard fonts" (Times,
+ Helvetica...): They are now more or less handled like any other Type 1 font.
+ See http://www.ntg.nl/pipermail/ntg-pdftex/2004-July/000648.html
+- hz: So far the font expansion feature required that the user must be able to
+ create expanded tfms (eg cmr10+10.tfm). Now font expansion can be used
+ without creating these tfms.
+ See http://www.ntg.nl/pipermail/ntg-pdftex/2004-May/000504.html
+- hz: Changed \pdffontexpand primitive --> the expand factor is now fixed to
+ 1000 and the argument is ignored. This will lead to spurious texts of "1000"
+ in your output if you compile old documents.
+- New command \pdftexbanner which returns a string with the full banner of the
+ current binary (e.g. "This is pdfTeX, Version 3.141592-1.20a (Web2C 7.5.3)
+ kpathsea version 3.5.3")
+- The PTEX.FullBanner key is now inserted in the document info dict instead of
+ the catalog. Newer versions of Acrobat display it.
+- Now includes support for encTeX.
+- Extended \pdfannot to use reserveobjnum/useobjnum
+ See http://www.ntg.nl/pipermail/ntg-pdftex/2004-March/000424.html
+- Bugfix: pdfTeX would read an .xpdfrc when including pdfs.
+ See http://tug.org/pipermail/pdftex/2004-March/004835.html
+- Bugfix: The strings in /ID would sometimes be empty.
+- Bugfix: Even when mapfiles or encodings or PostScript font files were
+ missing, pdfTeX still produced a (most often corrupt) pdf. Now it aborts with
+ an error in these cases.
+- numerous small bugfixes.
+- pdfTeX now uses the GNU libavl from Ben Pfaff for managing of fontmap
+ entries.
+- pdfTeX uses zlib 1.2.1
+- pdfTeX uses xpdf 3.00
+- pdfTeX uses libpng 1.2.7
+
+------------------------------------------------
+pdfTeX 3.141592-1.11b was released on 2003-10-06
+------------------------------------------------
+- Bugfix: The handling of /Rotate produced displaced images when /Rotate was 90
+ or 270.
+
+------------------------------------------------
+pdfTeX 3.141592-1.11a was released on 2003-08-02
+------------------------------------------------
+- New command \pdftrailer analogue to \pdfcatalog whose argument ends up in the
+ trailer dictionary.
+- The behaviour when an included pdf has a newer version than the one specified
+ with \pdfoptionpdfminorversion can be controlled by the new internal integer
+ \pdfoptionpdfinclusionerrorlevel: If it's 0, pdfTeX gives only a warning; if
+ it's 1, it raises an error.
+ This can also be set in pdftex.cfg with pdf_inclusion_errorlevel
+- The syntax for outlines has been extended to allow attributes:
+ <outline spec> --> <attr spec> <action spec> [count <number>] <general text>
+ See http://www.ntg.nl/pipermail/ntg-pdftex/2003-June/000165.html
+- The syntax of \pdfobj has been extended:
+ \pdfobj <object type spec> (h, v, m)
+ <object type spec> --> reserveobjnum
+ | [useobjnum <number>] [<attr spec>] [stream [<attr spec>]] <object contents>
+ <object contents> --> <file spec>
+ | <general text>
+ When the optional keyword `reserveobjnum' and `useobjnum' is not given, the
+ behaviour is unchanged.
+ See also http://tug.org/mailman/htdig/pdftex/2003-March/003814.html
+- Bugfix: /CreationDate didn't care for the timezone and could be fooled.
+ See http://www.ntg.nl/pipermail/ntg-pdftex/2003-July/000223.html
+- Bugfix: The translation of 8-bit characters in included pdfs that had their
+ eighth bit set sometimes got wrong because of a missing typecast.
+ See http://www.ntg.nl/pipermail/ntg-pdftex/2003-July/000216.html
+- Bugfix: pdfTeX -ini would crash with a minimal file because it didn't read
+ it's config and so didn't know anything about fonts.
+ See http://tug.org/pipermail/pdftex/2003-July/004262.html
+- Bugfix: \pdfstartlink would produce spurious /NewWindow entries. Also the
+ syntax of <action spec> and <goto-action spec> has been cleaned up.
+ See http://www.ntg.nl/pipermail/ntg-pdftex/2003-June/000167.html
+- Bugfix: \pdffontattr was not used for T3 fonts.
+ See http://tug.org/pipermail/pdftex/2003-June/004127.html
+- Bugfix: The cropbox of an included pdf would sometimes not be used.
+ See http://tug.org/pipermail/pdftex/2003-May/004037.html
+- pdfTeX uses xpdf 2.02
+
+------------------------------------------------
+pdfTeX 3.141592-1.10b was released on 2003-02-26
+------------------------------------------------
+- The numbers in transformation matrices are allways written with maximum
+ precision (see http://tug.org/pipermail/pdftex/2003-February/003596.html).
+- Incorporated the new version of TeX: 3.141592
+- Bugfix: Numbers in pdfs would sometimes be just a wee bit of (changed
+ implementation of pdftoepdf.convertNumToPDF).
+- Bugfix: When setting the /Producer, /Creator or /CreationDate keys with
+ /pdfinfo pdfTeX would also insert default values which caused duplicate keys
+ in the info dict (see
+ http://tug.org/pipermail/pdftex/2003-February/003524.html).
+- The reading of mapfiles is much faster (see
+ http://tug.org/pipermail/pdftex/2002-July/002843.html).
+- Bugfix: AR5 had problems with the CTM when displaying in "fit visible" mode
+ (see http://tug.org/pipermail/pdftex/2002-May/002688.html).
+- Bugfix: str_in_str had wrong indices (see
+ http://tug.org/pipermail/pdftex/2002-March/002367.html).
+- Bugfix: decimal_digits defaulted to 0, which caused problems with included
+ images when including pdfs (see
+ http://tug.org/pipermail/pdftex/2003-February/003518.html).
+ It now defaults to 4.
+- Bugfix: the type of included images was decided based only on the extensions;
+ now pdfTeX looks for magic bytes at the start of files (see
+ http://tug.org/pipermail/pdftex/2003-February/003519.html)
+
+-----------------------------------------------
+pdfTeX 3.14159-1.10a was released on 2003-01-16
+-----------------------------------------------
+- pdfTeX is now able to produce pdf1.4 (which is also the default) and has
+ almost complete support for including pdf1.4 files:
+ - Additional attributes like MetaData are copied from included pdfs.
+ - Currently the Page Group attribute (see sections 7.3.6 and 7.5.5 of the pdf
+ 1.4 reference) of included pdfs is NOT copied (as we don't know how to
+ handle this when imposing pdfs).
+ This means including pdfs with transparency features will work as long as
+ the included pdf doesn't use Page Groups; if it does, the result might not
+ be what is expected (One application known to use Page Groups is Adobe
+ Illustrator v9++). The distributed pdfTeX binaries will give a warning
+ about any occurance of a Page Group in an included pdf and ignore the Page
+ Group (thus producing syntactically correct pdfs but probably not the
+ intended output).
+ Acrobat 5++ and newer versions of Jaws display files without Page Groups
+ correctly, so this might not really be a problem.
+ See pdftoepdf.cc for preprocessor flags which allow this behaviour to be
+ changed (copying the Page Group (most likely producing incorrect pdf) or
+ treating Page Groups as errors).
+- The new primitive \pdfoptionpdfminorversion sets the pdf version of the
+ generated file and the latest allowed pdf version of included pdfs:
+ \pdfoptionpdfminorversion=3
+ tells pdfTeX to set the pdf version to 1.3 and allows only included pdfs with
+ versions <= 1.3 .
+ The default for \pdfoptionpdfminorversion is 4 for pdf 1.4
+ This must appear before any data is written to the generated pdf file, so
+ you should put it at the very start of your files.
+ This can also be set in pdftex.cfg with pdf_minorversion
+- It is now possible to specify the pdf page box to use when including pdfs.
+ The syntax has been extended:
+ \pdfximage [<image attr spec>] <general text> (h, v, m)
+ <image attr spec> --> [<rule spec>] [<attr spec>] [<page spec>] [<pdf box spec>]
+ <pdf box spec> --> mediabox|cropbox|bleedbox|trimbox|artbox
+ The default is cropbox (which defaults to mediabox), to be compatible with
+ previous versions of pdfTeX.
+ The page box specified at \pdfximage can be globally overridden with the
+ config parameter always_use_pdfpagebox and the command
+ \pdfoptionalwaysusepdfpagebox <integer>, where 0 is the default (use whatever
+ is specified with \pdfximage), 1 is media, 2 is crop, 3 is bleed, 4 is trim
+ and 5 is artbox. This can only be set once per object, i.e. the value used at
+ \pdfximage is remembered.
+ See the pdf reference for an explanation of the boxes.
+- The support for the inclusion of jpeg images has been extended to allow the
+ inclusion of JPEG/Exif files which are produced by digital photo cameras
+ (thanks to Hartmut Henkel).
+- The support for the inclusion of tif images has been removed as it was of
+ limited use (it worked only for gray-scale and rgb images) and produced wrong
+ results (all other images types where treated as rgb images).
+ Tif images can be converted on *nix on-the-fly to pngs with the help of
+ ImageMagick, epstopdf.sty or pdftex.def v0.4 or newer, and this rule:
+ \DeclareGraphicsRule{.tif}{png}{.png}{`convert #1 `basename #1 .tif`.png}
+- The extensions for pdf encryption have been removed, since they make the
+ pdfTeX code overly complex. Those needing pdf encryption are encouraged to
+ produce a standalone program for encrypting pdfs.
+- pdfTeX now writes a usage statistic about the pdfTeX specific memory to the
+ log.
+- numerous bugfixes, most of them in the inclusion of pdfs.
+- pdfTeX uses xpdf 2.01
+- pdfTeX uses libpng 1.2.5
+
+---------------------------------------------------------------------
+pdfTeX 3.14159-1.00a-pretest-20011127-ojmw was released on 2002-01-29
+---------------------------------------------------------------------
+
+----------------------------------------------------------------
+pdfTeX 3.14159-1.00a-pretest-20010806 was released on 2001-08-06
+----------------------------------------------------------------
+
+----------------------------------------------------------------
+pdfTeX 3.14159-1.00a-pretest-20010804 was released on 2001-08-04
+----------------------------------------------------------------
+
+$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/NEWS#88 $
+// vim: tw=79:ts=2:expandtab:autoindent
diff --git a/Build/source/texk/web2c/pdftexdir/README b/Build/source/texk/web2c/pdftexdir/README
new file mode 100644
index 00000000000..c56f359cbbe
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/README
@@ -0,0 +1,90 @@
+pdfTeX
+======
+
+README for version 3.14159-1.30.4 of $Date: 2005/10/17 $
+========================================================
+
+This directory contains the version 1.30.4 of pdfTeX, an extended version of
+TeX that can create PDF directly from TeX source files and enhance the
+result of TeX typesetting with the help of PDF. When PDF output is not
+selected, pdfTeX produces normal DVI output, otherwise it produces PDF
+output that looks identical to the DVI output. An important aspect of this
+project is to investigate alternative justification algorithms, optionally
+making use of multiple master fonts.
+
+pdfeTeX is an even more extended version of TeX than pdfTeX because it is
+not based on TeX but on eTeX, an extended version of TeX.
+
+pdfTeX is based on the original TeX sources and Web2c, and has been
+successfully compiled on Unix, Win32 and DOS systems. It is still under
+development and features may change; it produces reasonable PDF code.
+
+See the file NEWS for changes to the program.
+
+Documentation about pdfTeX can be found at http://www.pdftex.org
+
+There is also a mailing list on pdfTeX; go to
+http://tug.org/mailman/listinfo/pdftex for more information about it. Its
+searchable archive can be found at http://tug.org/pipermail/pdftex/
+Please read http://www.catb.org/~esr/faqs/smart-questions.html before
+asking any questions on the pdfTeX mailing list.
+
+A mailing list for the developement of pdfTeX can be found at
+http://www.ntg.nl/mailman/listinfo/ntg-pdftex
+
+
+LEGAL ISSUES
+============
+
+pdfTeX is copyright (c) 1996-2005 Han The Thanh, <thanh@pdftex.org>
+
+pdfTeX 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.
+
+pdfTeX is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+details.
+
+You should have received a copy of the GNU General Public License along
+with pdfTeX; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place, Suite 330, Boston, MA 02111-1307 USA
+
+pdfTeX uses code from TeX; for these parts the original copyright by Don
+Knuth applies. See the source files for details.
+
+pdfeTeX uses code from eTeX; for these parts the original copyright by
+Peter Breitenlohner applies. See the source files for details.
+
+
+WHAT TO DO IF YOU BELIEVE YOU HAVE FOUND A BUG IN pdfTeX
+========================================================
+
+Please read http://www.chiark.greenend.org.uk/~sgtatham/bugs.html and
+follow the guidelines there. Then go to the sarovar site of pdfTeX
+(http://sarovar.org/projects/pdftex/) and submit your bug report there.
+Here you can also report feature requests or patches.
+
+
+CONTRIBUTORS
+============
+
+Peter Breitenlohner, Ricardo Sanchez Carmenes, Otfried Cheong, Thomas
+Esser, Hans Hagen, Hartmut Henkel, Taco Hoekwater, Pawel Jackowski, Tom
+Kacvinsky, Akira Kakuto, Reinhard Kotucha, Derek B. Noonburg, Heiko
+Oberdiek, Jiri Osoba, Fabrice Popineau, Sebastian Rahtz, Tomas Rokicki,
+Martin Schröder, Petr Sojka, Olaf Weber, Jiri Zlatuska.
+
+pdfTeX is built on top of TeX, written by Donald Knuth cum suis (Liang and
+so), and eTeX, written by Peter Breitenlohner cum suis; part of the
+paragraph optimization is inspired by the work of Hermann Zapf.
+
+
+------------------------------------------------------------------------------
+
+Please send bug reports, offers of help, etc. to martin@pdftex.org
+
+$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/README#33 $
+// vim: tw=75
diff --git a/Build/source/texk/web2c/pdftexdir/avl.c b/Build/source/texk/web2c/pdftexdir/avl.c
new file mode 100644
index 00000000000..7b6bc17eac0
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/avl.c
@@ -0,0 +1,890 @@
+/* Produced by texiweb from libavl.w on 2003/01/06 at 18:07. */
+
+/* libavl - library for manipulation of binary trees.
+ Copyright (C) 1998-2002 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The author may be contacted at <blp@gnu.org> on the Internet, or
+ write to Ben Pfaff, Stanford University, Computer Science Dept., 353
+ Serra Mall, Stanford CA 94305, USA.
+*/
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "avl.h"
+
+/* Creates and returns a new table
+ with comparison function |compare| using parameter |param|
+ and memory allocator |allocator|.
+ Returns |NULL| if memory allocation failed. */
+struct avl_table *
+avl_create (avl_comparison_func *compare, void *param,
+ struct libavl_allocator *allocator)
+{
+ struct avl_table *tree;
+
+ assert (compare != NULL);
+
+ if (allocator == NULL)
+ allocator = &avl_allocator_default;
+
+ tree = allocator->libavl_malloc (allocator, sizeof *tree);
+ if (tree == NULL)
+ return NULL;
+
+ tree->avl_root = NULL;
+ tree->avl_compare = compare;
+ tree->avl_param = param;
+ tree->avl_alloc = allocator;
+ tree->avl_count = 0;
+ tree->avl_generation = 0;
+
+ return tree;
+}
+
+/* Search |tree| for an item matching |item|, and return it if found.
+ Otherwise return |NULL|. */
+void *
+avl_find (const struct avl_table *tree, const void *item)
+{
+ const struct avl_node *p;
+
+ assert (tree != NULL && item != NULL);
+ for (p = tree->avl_root; p != NULL; )
+ {
+ int cmp = tree->avl_compare (item, p->avl_data, tree->avl_param);
+
+ if (cmp < 0)
+ p = p->avl_link[0];
+ else if (cmp > 0)
+ p = p->avl_link[1];
+ else /* |cmp == 0| */
+ return p->avl_data;
+ }
+
+ return NULL;
+}
+
+/* Inserts |item| into |tree| and returns a pointer to |item|'s address.
+ If a duplicate item is found in the tree,
+ returns a pointer to the duplicate without inserting |item|.
+ Returns |NULL| in case of memory allocation failure. */
+void **
+avl_probe (struct avl_table *tree, void *item)
+{
+ struct avl_node *y, *z; /* Top node to update balance factor, and parent. */
+ struct avl_node *p, *q; /* Iterator, and parent. */
+ struct avl_node *n; /* Newly inserted node. */
+ struct avl_node *w; /* New root of rebalanced subtree. */
+ int dir; /* Direction to descend. */
+
+ unsigned char da[AVL_MAX_HEIGHT]; /* Cached comparison results. */
+ int k = 0; /* Number of cached results. */
+
+ assert (tree != NULL && item != NULL);
+
+ z = (struct avl_node *) &tree->avl_root;
+ y = tree->avl_root;
+ dir = 0;
+ for (q = z, p = y; p != NULL; q = p, p = p->avl_link[dir])
+ {
+ int cmp = tree->avl_compare (item, p->avl_data, tree->avl_param);
+ if (cmp == 0)
+ return &p->avl_data;
+
+ if (p->avl_balance != 0)
+ z = q, y = p, k = 0;
+ da[k++] = dir = cmp > 0;
+ }
+
+ n = q->avl_link[dir] =
+ tree->avl_alloc->libavl_malloc (tree->avl_alloc, sizeof *n);
+ if (n == NULL)
+ return NULL;
+
+ tree->avl_count++;
+ n->avl_data = item;
+ n->avl_link[0] = n->avl_link[1] = NULL;
+ n->avl_balance = 0;
+ if (y == NULL)
+ return &n->avl_data;
+
+ for (p = y, k = 0; p != n; p = p->avl_link[da[k]], k++)
+ if (da[k] == 0)
+ p->avl_balance--;
+ else
+ p->avl_balance++;
+
+ if (y->avl_balance == -2)
+ {
+ struct avl_node *x = y->avl_link[0];
+ if (x->avl_balance == -1)
+ {
+ w = x;
+ y->avl_link[0] = x->avl_link[1];
+ x->avl_link[1] = y;
+ x->avl_balance = y->avl_balance = 0;
+ }
+ else
+ {
+ assert (x->avl_balance == +1);
+ w = x->avl_link[1];
+ x->avl_link[1] = w->avl_link[0];
+ w->avl_link[0] = x;
+ y->avl_link[0] = w->avl_link[1];
+ w->avl_link[1] = y;
+ if (w->avl_balance == -1)
+ x->avl_balance = 0, y->avl_balance = +1;
+ else if (w->avl_balance == 0)
+ x->avl_balance = y->avl_balance = 0;
+ else /* |w->avl_balance == +1| */
+ x->avl_balance = -1, y->avl_balance = 0;
+ w->avl_balance = 0;
+ }
+ }
+ else if (y->avl_balance == +2)
+ {
+ struct avl_node *x = y->avl_link[1];
+ if (x->avl_balance == +1)
+ {
+ w = x;
+ y->avl_link[1] = x->avl_link[0];
+ x->avl_link[0] = y;
+ x->avl_balance = y->avl_balance = 0;
+ }
+ else
+ {
+ assert (x->avl_balance == -1);
+ w = x->avl_link[0];
+ x->avl_link[0] = w->avl_link[1];
+ w->avl_link[1] = x;
+ y->avl_link[1] = w->avl_link[0];
+ w->avl_link[0] = y;
+ if (w->avl_balance == +1)
+ x->avl_balance = 0, y->avl_balance = -1;
+ else if (w->avl_balance == 0)
+ x->avl_balance = y->avl_balance = 0;
+ else /* |w->avl_balance == -1| */
+ x->avl_balance = +1, y->avl_balance = 0;
+ w->avl_balance = 0;
+ }
+ }
+ else
+ return &n->avl_data;
+ z->avl_link[y != z->avl_link[0]] = w;
+
+ tree->avl_generation++;
+ return &n->avl_data;
+}
+
+/* Inserts |item| into |table|.
+ Returns |NULL| if |item| was successfully inserted
+ or if a memory allocation error occurred.
+ Otherwise, returns the duplicate item. */
+void *
+avl_insert (struct avl_table *table, void *item)
+{
+ void **p = avl_probe (table, item);
+ return p == NULL || *p == item ? NULL : *p;
+}
+
+/* Inserts |item| into |table|, replacing any duplicate item.
+ Returns |NULL| if |item| was inserted without replacing a duplicate,
+ or if a memory allocation error occurred.
+ Otherwise, returns the item that was replaced. */
+void *
+avl_replace (struct avl_table *table, void *item)
+{
+ void **p = avl_probe (table, item);
+ if (p == NULL || *p == item)
+ return NULL;
+ else
+ {
+ void *r = *p;
+ *p = item;
+ return r;
+ }
+}
+
+/* Deletes from |tree| and returns an item matching |item|.
+ Returns a null pointer if no matching item found. */
+void *
+avl_delete (struct avl_table *tree, const void *item)
+{
+ /* Stack of nodes. */
+ struct avl_node *pa[AVL_MAX_HEIGHT]; /* Nodes. */
+ unsigned char da[AVL_MAX_HEIGHT]; /* |avl_link[]| indexes. */
+ int k; /* Stack pointer. */
+
+ struct avl_node *p; /* Traverses tree to find node to delete. */
+ int cmp; /* Result of comparison between |item| and |p|. */
+
+ assert (tree != NULL && item != NULL);
+
+ k = 0;
+ p = (struct avl_node *) &tree->avl_root;
+ for (cmp = -1; cmp != 0;
+ cmp = tree->avl_compare (item, p->avl_data, tree->avl_param))
+ {
+ int dir = cmp > 0;
+
+ pa[k] = p;
+ da[k++] = dir;
+
+ p = p->avl_link[dir];
+ if (p == NULL)
+ return NULL;
+ }
+ item = p->avl_data;
+
+ if (p->avl_link[1] == NULL)
+ pa[k - 1]->avl_link[da[k - 1]] = p->avl_link[0];
+ else
+ {
+ struct avl_node *r = p->avl_link[1];
+ if (r->avl_link[0] == NULL)
+ {
+ r->avl_link[0] = p->avl_link[0];
+ r->avl_balance = p->avl_balance;
+ pa[k - 1]->avl_link[da[k - 1]] = r;
+ da[k] = 1;
+ pa[k++] = r;
+ }
+ else
+ {
+ struct avl_node *s;
+ int j = k++;
+
+ for (;;)
+ {
+ da[k] = 0;
+ pa[k++] = r;
+ s = r->avl_link[0];
+ if (s->avl_link[0] == NULL)
+ break;
+
+ r = s;
+ }
+
+ s->avl_link[0] = p->avl_link[0];
+ r->avl_link[0] = s->avl_link[1];
+ s->avl_link[1] = p->avl_link[1];
+ s->avl_balance = p->avl_balance;
+
+ pa[j - 1]->avl_link[da[j - 1]] = s;
+ da[j] = 1;
+ pa[j] = s;
+ }
+ }
+
+ tree->avl_alloc->libavl_free (tree->avl_alloc, p);
+
+ assert (k > 0);
+ while (--k > 0)
+ {
+ struct avl_node *y = pa[k];
+
+ if (da[k] == 0)
+ {
+ y->avl_balance++;
+ if (y->avl_balance == +1)
+ break;
+ else if (y->avl_balance == +2)
+ {
+ struct avl_node *x = y->avl_link[1];
+ if (x->avl_balance == -1)
+ {
+ struct avl_node *w;
+ assert (x->avl_balance == -1);
+ w = x->avl_link[0];
+ x->avl_link[0] = w->avl_link[1];
+ w->avl_link[1] = x;
+ y->avl_link[1] = w->avl_link[0];
+ w->avl_link[0] = y;
+ if (w->avl_balance == +1)
+ x->avl_balance = 0, y->avl_balance = -1;
+ else if (w->avl_balance == 0)
+ x->avl_balance = y->avl_balance = 0;
+ else /* |w->avl_balance == -1| */
+ x->avl_balance = +1, y->avl_balance = 0;
+ w->avl_balance = 0;
+ pa[k - 1]->avl_link[da[k - 1]] = w;
+ }
+ else
+ {
+ y->avl_link[1] = x->avl_link[0];
+ x->avl_link[0] = y;
+ pa[k - 1]->avl_link[da[k - 1]] = x;
+ if (x->avl_balance == 0)
+ {
+ x->avl_balance = -1;
+ y->avl_balance = +1;
+ break;
+ }
+ else
+ x->avl_balance = y->avl_balance = 0;
+ }
+ }
+ }
+ else
+ {
+ y->avl_balance--;
+ if (y->avl_balance == -1)
+ break;
+ else if (y->avl_balance == -2)
+ {
+ struct avl_node *x = y->avl_link[0];
+ if (x->avl_balance == +1)
+ {
+ struct avl_node *w;
+ assert (x->avl_balance == +1);
+ w = x->avl_link[1];
+ x->avl_link[1] = w->avl_link[0];
+ w->avl_link[0] = x;
+ y->avl_link[0] = w->avl_link[1];
+ w->avl_link[1] = y;
+ if (w->avl_balance == -1)
+ x->avl_balance = 0, y->avl_balance = +1;
+ else if (w->avl_balance == 0)
+ x->avl_balance = y->avl_balance = 0;
+ else /* |w->avl_balance == +1| */
+ x->avl_balance = -1, y->avl_balance = 0;
+ w->avl_balance = 0;
+ pa[k - 1]->avl_link[da[k - 1]] = w;
+ }
+ else
+ {
+ y->avl_link[0] = x->avl_link[1];
+ x->avl_link[1] = y;
+ pa[k - 1]->avl_link[da[k - 1]] = x;
+ if (x->avl_balance == 0)
+ {
+ x->avl_balance = +1;
+ y->avl_balance = -1;
+ break;
+ }
+ else
+ x->avl_balance = y->avl_balance = 0;
+ }
+ }
+ }
+ }
+
+ tree->avl_count--;
+ tree->avl_generation++;
+ return (void *) item;
+}
+
+/* Refreshes the stack of parent pointers in |trav|
+ and updates its generation number. */
+static void
+trav_refresh (struct avl_traverser *trav)
+{
+ assert (trav != NULL);
+
+ trav->avl_generation = trav->avl_table->avl_generation;
+
+ if (trav->avl_node != NULL)
+ {
+ avl_comparison_func *cmp = trav->avl_table->avl_compare;
+ void *param = trav->avl_table->avl_param;
+ struct avl_node *node = trav->avl_node;
+ struct avl_node *i;
+
+ trav->avl_height = 0;
+ for (i = trav->avl_table->avl_root; i != node; )
+ {
+ assert (trav->avl_height < AVL_MAX_HEIGHT);
+ assert (i != NULL);
+
+ trav->avl_stack[trav->avl_height++] = i;
+ i = i->avl_link[cmp (node->avl_data, i->avl_data, param) > 0];
+ }
+ }
+}
+
+/* Initializes |trav| for use with |tree|
+ and selects the null node. */
+void
+avl_t_init (struct avl_traverser *trav, struct avl_table *tree)
+{
+ trav->avl_table = tree;
+ trav->avl_node = NULL;
+ trav->avl_height = 0;
+ trav->avl_generation = tree->avl_generation;
+}
+
+/* Initializes |trav| for |tree|
+ and selects and returns a pointer to its least-valued item.
+ Returns |NULL| if |tree| contains no nodes. */
+void *
+avl_t_first (struct avl_traverser *trav, struct avl_table *tree)
+{
+ struct avl_node *x;
+
+ assert (tree != NULL && trav != NULL);
+
+ trav->avl_table = tree;
+ trav->avl_height = 0;
+ trav->avl_generation = tree->avl_generation;
+
+ x = tree->avl_root;
+ if (x != NULL)
+ while (x->avl_link[0] != NULL)
+ {
+ assert (trav->avl_height < AVL_MAX_HEIGHT);
+ trav->avl_stack[trav->avl_height++] = x;
+ x = x->avl_link[0];
+ }
+ trav->avl_node = x;
+
+ return x != NULL ? x->avl_data : NULL;
+}
+
+/* Initializes |trav| for |tree|
+ and selects and returns a pointer to its greatest-valued item.
+ Returns |NULL| if |tree| contains no nodes. */
+void *
+avl_t_last (struct avl_traverser *trav, struct avl_table *tree)
+{
+ struct avl_node *x;
+
+ assert (tree != NULL && trav != NULL);
+
+ trav->avl_table = tree;
+ trav->avl_height = 0;
+ trav->avl_generation = tree->avl_generation;
+
+ x = tree->avl_root;
+ if (x != NULL)
+ while (x->avl_link[1] != NULL)
+ {
+ assert (trav->avl_height < AVL_MAX_HEIGHT);
+ trav->avl_stack[trav->avl_height++] = x;
+ x = x->avl_link[1];
+ }
+ trav->avl_node = x;
+
+ return x != NULL ? x->avl_data : NULL;
+}
+
+/* Searches for |item| in |tree|.
+ If found, initializes |trav| to the item found and returns the item
+ as well.
+ If there is no matching item, initializes |trav| to the null item
+ and returns |NULL|. */
+void *
+avl_t_find (struct avl_traverser *trav, struct avl_table *tree, void *item)
+{
+ struct avl_node *p, *q;
+
+ assert (trav != NULL && tree != NULL && item != NULL);
+ trav->avl_table = tree;
+ trav->avl_height = 0;
+ trav->avl_generation = tree->avl_generation;
+ for (p = tree->avl_root; p != NULL; p = q)
+ {
+ int cmp = tree->avl_compare (item, p->avl_data, tree->avl_param);
+
+ if (cmp < 0)
+ q = p->avl_link[0];
+ else if (cmp > 0)
+ q = p->avl_link[1];
+ else /* |cmp == 0| */
+ {
+ trav->avl_node = p;
+ return p->avl_data;
+ }
+
+ assert (trav->avl_height < AVL_MAX_HEIGHT);
+ trav->avl_stack[trav->avl_height++] = p;
+ }
+
+ trav->avl_height = 0;
+ trav->avl_node = NULL;
+ return NULL;
+}
+
+/* Attempts to insert |item| into |tree|.
+ If |item| is inserted successfully, it is returned and |trav| is
+ initialized to its location.
+ If a duplicate is found, it is returned and |trav| is initialized to
+ its location. No replacement of the item occurs.
+ If a memory allocation failure occurs, |NULL| is returned and |trav|
+ is initialized to the null item. */
+void *
+avl_t_insert (struct avl_traverser *trav, struct avl_table *tree, void *item)
+{
+ void **p;
+
+ assert (trav != NULL && tree != NULL && item != NULL);
+
+ p = avl_probe (tree, item);
+ if (p != NULL)
+ {
+ trav->avl_table = tree;
+ trav->avl_node =
+ ((struct avl_node *)
+ ((char *) p - offsetof (struct avl_node, avl_data)));
+ trav->avl_generation = tree->avl_generation - 1;
+ return *p;
+ }
+ else
+ {
+ avl_t_init (trav, tree);
+ return NULL;
+ }
+}
+
+/* Initializes |trav| to have the same current node as |src|. */
+void *
+avl_t_copy (struct avl_traverser *trav, const struct avl_traverser *src)
+{
+ assert (trav != NULL && src != NULL);
+
+ if (trav != src)
+ {
+ trav->avl_table = src->avl_table;
+ trav->avl_node = src->avl_node;
+ trav->avl_generation = src->avl_generation;
+ if (trav->avl_generation == trav->avl_table->avl_generation)
+ {
+ trav->avl_height = src->avl_height;
+ memcpy (trav->avl_stack, (const void *) src->avl_stack,
+ sizeof *trav->avl_stack * trav->avl_height);
+ }
+ }
+
+ return trav->avl_node != NULL ? trav->avl_node->avl_data : NULL;
+}
+
+/* Returns the next data item in inorder
+ within the tree being traversed with |trav|,
+ or if there are no more data items returns |NULL|. */
+void *
+avl_t_next (struct avl_traverser *trav)
+{
+ struct avl_node *x;
+
+ assert (trav != NULL);
+
+ if (trav->avl_generation != trav->avl_table->avl_generation)
+ trav_refresh (trav);
+
+ x = trav->avl_node;
+ if (x == NULL)
+ {
+ return avl_t_first (trav, trav->avl_table);
+ }
+ else if (x->avl_link[1] != NULL)
+ {
+ assert (trav->avl_height < AVL_MAX_HEIGHT);
+ trav->avl_stack[trav->avl_height++] = x;
+ x = x->avl_link[1];
+
+ while (x->avl_link[0] != NULL)
+ {
+ assert (trav->avl_height < AVL_MAX_HEIGHT);
+ trav->avl_stack[trav->avl_height++] = x;
+ x = x->avl_link[0];
+ }
+ }
+ else
+ {
+ struct avl_node *y;
+
+ do
+ {
+ if (trav->avl_height == 0)
+ {
+ trav->avl_node = NULL;
+ return NULL;
+ }
+
+ y = x;
+ x = trav->avl_stack[--trav->avl_height];
+ }
+ while (y == x->avl_link[1]);
+ }
+ trav->avl_node = x;
+
+ return x->avl_data;
+}
+
+/* Returns the previous data item in inorder
+ within the tree being traversed with |trav|,
+ or if there are no more data items returns |NULL|. */
+void *
+avl_t_prev (struct avl_traverser *trav)
+{
+ struct avl_node *x;
+
+ assert (trav != NULL);
+
+ if (trav->avl_generation != trav->avl_table->avl_generation)
+ trav_refresh (trav);
+
+ x = trav->avl_node;
+ if (x == NULL)
+ {
+ return avl_t_last (trav, trav->avl_table);
+ }
+ else if (x->avl_link[0] != NULL)
+ {
+ assert (trav->avl_height < AVL_MAX_HEIGHT);
+ trav->avl_stack[trav->avl_height++] = x;
+ x = x->avl_link[0];
+
+ while (x->avl_link[1] != NULL)
+ {
+ assert (trav->avl_height < AVL_MAX_HEIGHT);
+ trav->avl_stack[trav->avl_height++] = x;
+ x = x->avl_link[1];
+ }
+ }
+ else
+ {
+ struct avl_node *y;
+
+ do
+ {
+ if (trav->avl_height == 0)
+ {
+ trav->avl_node = NULL;
+ return NULL;
+ }
+
+ y = x;
+ x = trav->avl_stack[--trav->avl_height];
+ }
+ while (y == x->avl_link[0]);
+ }
+ trav->avl_node = x;
+
+ return x->avl_data;
+}
+
+/* Returns |trav|'s current item. */
+void *
+avl_t_cur (struct avl_traverser *trav)
+{
+ assert (trav != NULL);
+
+ return trav->avl_node != NULL ? trav->avl_node->avl_data : NULL;
+}
+
+/* Replaces the current item in |trav| by |new| and returns the item replaced.
+ |trav| must not have the null item selected.
+ The new item must not upset the ordering of the tree. */
+void *
+avl_t_replace (struct avl_traverser *trav, void *new)
+{
+ void *old;
+
+ assert (trav != NULL && trav->avl_node != NULL && new != NULL);
+ old = trav->avl_node->avl_data;
+ trav->avl_node->avl_data = new;
+ return old;
+}
+
+static void
+copy_error_recovery (struct avl_node **stack, int height,
+ struct avl_table *new, avl_item_func *destroy)
+{
+ assert (stack != NULL && height >= 0 && new != NULL);
+
+ for (; height > 2; height -= 2)
+ stack[height - 1]->avl_link[1] = NULL;
+ avl_destroy (new, destroy);
+}
+
+/* Copies |org| to a newly created tree, which is returned.
+ If |copy != NULL|, each data item in |org| is first passed to |copy|,
+ and the return values are inserted into the tree,
+ with |NULL| return values taken as indications of failure.
+ On failure, destroys the partially created new tree,
+ applying |destroy|, if non-null, to each item in the new tree so far,
+ and returns |NULL|.
+ If |allocator != NULL|, it is used for allocation in the new tree.
+ Otherwise, the same allocator used for |org| is used. */
+struct avl_table *
+avl_copy (const struct avl_table *org, avl_copy_func *copy,
+ avl_item_func *destroy, struct libavl_allocator *allocator)
+{
+ struct avl_node *stack[2 * (AVL_MAX_HEIGHT + 1)];
+ int height = 0;
+
+ struct avl_table *new;
+ const struct avl_node *x;
+ struct avl_node *y;
+
+ assert (org != NULL);
+ new = avl_create (org->avl_compare, org->avl_param,
+ allocator != NULL ? allocator : org->avl_alloc);
+ if (new == NULL)
+ return NULL;
+ new->avl_count = org->avl_count;
+ if (new->avl_count == 0)
+ return new;
+
+ x = (const struct avl_node *) &org->avl_root;
+ y = (struct avl_node *) &new->avl_root;
+ for (;;)
+ {
+ while (x->avl_link[0] != NULL)
+ {
+ assert (height < 2 * (AVL_MAX_HEIGHT + 1));
+
+ y->avl_link[0] =
+ new->avl_alloc->libavl_malloc (new->avl_alloc,
+ sizeof *y->avl_link[0]);
+ if (y->avl_link[0] == NULL)
+ {
+ if (y != (struct avl_node *) &new->avl_root)
+ {
+ y->avl_data = NULL;
+ y->avl_link[1] = NULL;
+ }
+
+ copy_error_recovery (stack, height, new, destroy);
+ return NULL;
+ }
+
+ stack[height++] = (struct avl_node *) x;
+ stack[height++] = y;
+ x = x->avl_link[0];
+ y = y->avl_link[0];
+ }
+ y->avl_link[0] = NULL;
+
+ for (;;)
+ {
+ y->avl_balance = x->avl_balance;
+ if (copy == NULL)
+ y->avl_data = x->avl_data;
+ else
+ {
+ y->avl_data = copy (x->avl_data, org->avl_param);
+ if (y->avl_data == NULL)
+ {
+ y->avl_link[1] = NULL;
+ copy_error_recovery (stack, height, new, destroy);
+ return NULL;
+ }
+ }
+
+ if (x->avl_link[1] != NULL)
+ {
+ y->avl_link[1] =
+ new->avl_alloc->libavl_malloc (new->avl_alloc,
+ sizeof *y->avl_link[1]);
+ if (y->avl_link[1] == NULL)
+ {
+ copy_error_recovery (stack, height, new, destroy);
+ return NULL;
+ }
+
+ x = x->avl_link[1];
+ y = y->avl_link[1];
+ break;
+ }
+ else
+ y->avl_link[1] = NULL;
+
+ if (height <= 2)
+ return new;
+
+ y = stack[--height];
+ x = stack[--height];
+ }
+ }
+}
+
+/* Frees storage allocated for |tree|.
+ If |destroy != NULL|, applies it to each data item in inorder. */
+void
+avl_destroy (struct avl_table *tree, avl_item_func *destroy)
+{
+ struct avl_node *p, *q;
+
+ assert (tree != NULL);
+
+ for (p = tree->avl_root; p != NULL; p = q)
+ if (p->avl_link[0] == NULL)
+ {
+ q = p->avl_link[1];
+ if (destroy != NULL && p->avl_data != NULL)
+ destroy (p->avl_data, tree->avl_param);
+ tree->avl_alloc->libavl_free (tree->avl_alloc, p);
+ }
+ else
+ {
+ q = p->avl_link[0];
+ p->avl_link[0] = q->avl_link[1];
+ q->avl_link[1] = p;
+ }
+
+ tree->avl_alloc->libavl_free (tree->avl_alloc, tree);
+}
+
+/* Allocates |size| bytes of space using |malloc()|.
+ Returns a null pointer if allocation fails. */
+void *
+avl_malloc (struct libavl_allocator *allocator, size_t size)
+{
+ assert (allocator != NULL && size > 0);
+ return malloc (size);
+}
+
+/* Frees |block|. */
+void
+avl_free (struct libavl_allocator *allocator, void *block)
+{
+ assert (allocator != NULL && block != NULL);
+ free (block);
+}
+
+/* Default memory allocator that uses |malloc()| and |free()|. */
+struct libavl_allocator avl_allocator_default =
+ {
+ avl_malloc,
+ avl_free
+ };
+
+#undef NDEBUG
+#include <assert.h>
+
+/* Asserts that |avl_insert()| succeeds at inserting |item| into |table|. */
+void
+(avl_assert_insert) (struct avl_table *table, void *item)
+{
+ void **p = avl_probe (table, item);
+ assert (p != NULL && *p == item);
+}
+
+/* Asserts that |avl_delete()| really removes |item| from |table|,
+ and returns the removed item. */
+void *
+(avl_assert_delete) (struct avl_table *table, void *item)
+{
+ void *p = avl_delete (table, item);
+ assert (p != NULL);
+ return p;
+}
+
diff --git a/Build/source/texk/web2c/pdftexdir/avl.h b/Build/source/texk/web2c/pdftexdir/avl.h
new file mode 100644
index 00000000000..446a11a0ba9
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/avl.h
@@ -0,0 +1,123 @@
+/* Produced by texiweb from libavl.w on 2003/01/06 at 18:07. */
+
+/* libavl - library for manipulation of binary trees.
+ Copyright (C) 1998-2002 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The author may be contacted at <blp@gnu.org> on the Internet, or
+ write to Ben Pfaff, Stanford University, Computer Science Dept., 353
+ Serra Mall, Stanford CA 94305, USA.
+*/
+
+#ifndef AVL_H
+#define AVL_H 1
+
+#include <stddef.h>
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* Function types. */
+typedef int avl_comparison_func (const void *avl_a, const void *avl_b,
+ void *avl_param);
+typedef void avl_item_func (void *avl_item, void *avl_param);
+typedef void *avl_copy_func (void *avl_item, void *avl_param);
+
+#ifndef LIBAVL_ALLOCATOR
+#define LIBAVL_ALLOCATOR
+/* Memory allocator. */
+struct libavl_allocator
+ {
+ void *(*libavl_malloc) (struct libavl_allocator *, size_t libavl_size);
+ void (*libavl_free) (struct libavl_allocator *, void *libavl_block);
+ };
+#endif
+
+/* Default memory allocator. */
+extern struct libavl_allocator avl_allocator_default;
+void *avl_malloc (struct libavl_allocator *, size_t);
+void avl_free (struct libavl_allocator *, void *);
+
+/* Maximum AVL height. */
+#ifndef AVL_MAX_HEIGHT
+#define AVL_MAX_HEIGHT 32
+#endif
+
+/* Tree data structure. */
+struct avl_table
+ {
+ struct avl_node *avl_root; /* Tree's root. */
+ avl_comparison_func *avl_compare; /* Comparison function. */
+ void *avl_param; /* Extra argument to |avl_compare|. */
+ struct libavl_allocator *avl_alloc; /* Memory allocator. */
+ size_t avl_count; /* Number of items in tree. */
+ unsigned long avl_generation; /* Generation number. */
+ };
+
+/* An AVL tree node. */
+struct avl_node
+ {
+ struct avl_node *avl_link[2]; /* Subtrees. */
+ void *avl_data; /* Pointer to data. */
+ signed char avl_balance; /* Balance factor. */
+ };
+
+/* AVL traverser structure. */
+struct avl_traverser
+ {
+ struct avl_table *avl_table; /* Tree being traversed. */
+ struct avl_node *avl_node; /* Current node in tree. */
+ struct avl_node *avl_stack[AVL_MAX_HEIGHT];
+ /* All the nodes above |avl_node|. */
+ size_t avl_height; /* Number of nodes in |avl_parent|. */
+ unsigned long avl_generation; /* Generation number. */
+ };
+
+/* Table functions. */
+struct avl_table *avl_create (avl_comparison_func *, void *,
+ struct libavl_allocator *);
+struct avl_table *avl_copy (const struct avl_table *, avl_copy_func *,
+ avl_item_func *, struct libavl_allocator *);
+void avl_destroy (struct avl_table *, avl_item_func *);
+void **avl_probe (struct avl_table *, void *);
+void *avl_insert (struct avl_table *, void *);
+void *avl_replace (struct avl_table *, void *);
+void *avl_delete (struct avl_table *, const void *);
+void *avl_find (const struct avl_table *, const void *);
+void avl_assert_insert (struct avl_table *, void *);
+void *avl_assert_delete (struct avl_table *, void *);
+
+#define avl_count(table) ((size_t) (table)->avl_count)
+
+/* Table traverser functions. */
+void avl_t_init (struct avl_traverser *, struct avl_table *);
+void *avl_t_first (struct avl_traverser *, struct avl_table *);
+void *avl_t_last (struct avl_traverser *, struct avl_table *);
+void *avl_t_find (struct avl_traverser *, struct avl_table *, void *);
+void *avl_t_insert (struct avl_traverser *, struct avl_table *, void *);
+void *avl_t_copy (struct avl_traverser *, const struct avl_traverser *);
+void *avl_t_next (struct avl_traverser *);
+void *avl_t_prev (struct avl_traverser *);
+void *avl_t_cur (struct avl_traverser *);
+void *avl_t_replace (struct avl_traverser *, void *);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* avl.h */
diff --git a/Build/source/texk/web2c/pdftexdir/avlstuff.c b/Build/source/texk/web2c/pdftexdir/avlstuff.c
new file mode 100644
index 00000000000..1fab93223f1
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/avlstuff.c
@@ -0,0 +1,131 @@
+/*
+Copyright (c) 2004 Han The Thanh, <thanh@pdftex.org>
+
+This file is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by Free
+Software Foundation; either version 2 of the License, or (at your option)
+any later version.
+
+This file is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with this file; if not, write to the Free Software Foundation, Inc.,
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/avlstuff.c#5 $
+
+formatted by indent -kr
+*/
+
+#include "ptexlib.h"
+#include <kpathsea/c-vararg.h>
+#include <kpathsea/c-proto.h>
+#include "avl.h"
+
+static const char perforce_id[] =
+ "$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/avlstuff.c#5 $";
+
+/* One AVL tree for each obj_type 0...pdfobjtypemax */
+
+static struct avl_table *PdfObjTree[pdfobjtypemax + 1] =
+ { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
+
+
+/* memory management functions for avl */
+
+void *avl_xmalloc(struct libavl_allocator *allocator, size_t size)
+{
+ assert(allocator != NULL && size > 0);
+ return xmalloc(size);
+}
+
+void avl_xfree(struct libavl_allocator *allocator, void *block)
+{
+ assert(allocator != NULL && block != NULL);
+ xfree(block);
+}
+
+struct libavl_allocator avl_xallocator = {
+ avl_xmalloc,
+ avl_xfree
+};
+
+
+/* AVL sort objentry into avl_table[] */
+
+int compare_info(const void *pa, const void *pb, void *param)
+{
+ integer a, b;
+ int as, ae, bs, be, al, bl;
+
+ a = ((const objentry *) pa)->int0;
+ b = ((const objentry *) pb)->int0;
+ if (a < 0 && b < 0) { /* string comparison */
+ as = strstart[-a];
+ ae = strstart[-a + 1]; /* start of next string in pool */
+ bs = strstart[-b];
+ be = strstart[-b + 1];
+ al = ae - as;
+ bl = be - bs;
+ if (al < bl) /* compare first by string length */
+ return -1;
+ else if (al > bl)
+ return 1;
+ else
+ for (; as < ae; as++, bs++) {
+ if (strpool[as] < strpool[bs])
+ return -1;
+ if (strpool[as] > strpool[bs])
+ return 1;
+ }
+ return 0;
+ } else { /* integer comparison */
+ if (a < b)
+ return -1;
+ else if (a > b)
+ return 1;
+ else
+ return 0;
+ }
+}
+
+
+void avlputobj(integer objptr, integer t)
+{
+ static void **pp;
+
+ if (PdfObjTree[t] == NULL) {
+ PdfObjTree[t] = avl_create(compare_info, NULL, &avl_xallocator);
+ if (PdfObjTree[t] == NULL)
+ pdftex_fail("avlstuff.c: avl_create() PdfObjTree failed");
+ }
+ pp = avl_probe(PdfObjTree[t], &(objtab[objptr]));
+ if (pp == NULL)
+ pdftex_fail("avlstuff.c: avl_probe() out of memory in insertion");
+}
+
+
+/* replacement for linear search pascal function "find_obj" */
+
+integer avlfindobj(integer t, integer i, integer byname)
+{
+ static objentry *p;
+ static objentry tmp;
+
+ if (byname > 0)
+ tmp.int0 = -i;
+ else
+ tmp.int0 = i;
+ if (PdfObjTree[t] == NULL)
+ return 0;
+ p = (objentry *) avl_find(PdfObjTree[t], &tmp);
+ if (p == NULL)
+ return 0;
+ else
+ return (int) (p - (objentry *) objtab);
+}
+
+/* end of file avlstuff.c */
diff --git a/Build/source/texk/web2c/pdftexdir/avlstuff.h b/Build/source/texk/web2c/pdftexdir/avlstuff.h
new file mode 100644
index 00000000000..2ffa57b627d
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/avlstuff.h
@@ -0,0 +1,29 @@
+/*
+Copyright (c) 2004 Han The Thanh, <thanh@pdftex.org>
+
+This file is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by Free
+Software Foundation; either version 2 of the License, or (at your option)
+any later version.
+
+This file is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with this file; if not, write to the Free Software Foundation, Inc.,
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/avlstuff.h#5 $
+
+formatted by indent -kr
+*/
+
+#include "avl.h"
+
+/* memory management functions for avl */
+
+extern struct libavl_allocator avl_xallocator;
+
+/* end of file avlstuff.h */
diff --git a/Build/source/texk/web2c/pdftexdir/change-files.txt b/Build/source/texk/web2c/pdftexdir/change-files.txt
new file mode 100644
index 00000000000..496c1e313ed
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/change-files.txt
@@ -0,0 +1,132 @@
+How change files are applied for pdftex/pdfetex?
+
+============================= pdftex =============================
+
+1) pdftex.web is generated from
+ ./tie -m pdftex.web $(srcdir)/tex.web \
+ $(srcdir)/pdftexdir/pdftex.ch \
+ $(srcdir)/pdftexdir/hz.ch \
+ $(srcdir)/pdftexdir/misc.ch
+
+Input:
+ tex.web:
+ the original tex sources
+
+ pdftexdir/pdftex.ch:
+ PDF-specific changes
+
+ pdftexdir/hz.ch:
+ HZ extension
+
+ pdftexdir/misc.ch:
+ miscellany extensions
+
+
+Output:
+ pdftex.web:
+ pdftex without system-dependent changes
+
+2) pdftex.ch is generated from
+ ./tie -c pdftex.ch pdftex.web \
+ $(srcdir)/pdftexdir/tex.ch0 \
+ $(srcdir)/tex.ch \
+ $(srcdir)/pdftexdir/tex.ch1 \
+ $(srcdir)/pdftexdir/tex.pch
+
+Input:
+ pdftex.web:
+ from step 1), ie pdftex without system-dependent changes
+
+ pdftexdir/tex.ch0:
+ % Change file to assist in creating the web2c-specific change file.
+ % This one comes first, resolves inconsistencies between the
+ % generated pdftex.web and tex.ch
+
+ change the pdftex banner to tex banner, so tex.ch can be applied
+
+ tex.ch:
+ the main web2c-specific (or other system-dependent) change file
+
+ pdftexdir/tex.ch1:
+ % Change file to assist in creating the web2c-specific change file.
+ % This one resolves inconsistencies between tex.ch and tex.pch.
+
+ change the tex banner to pdftex banner (reverse tex.ch0)
+
+ pdftexdir/tex.pch:
+ % Change file containing web2c-specific or system-dependent changes to
+ % pdftex
+
+Output:
+ pdftex.ch (not pdftexdir/pdftex.ch):
+ additional & system-dependent changes
+
+
+============================= pdfetex =============================
+
+1) pdfetex.web is generated from
+ ./tie -m pdfetex.web $(srcdir)/tex.web \
+ $(srcdir)/etexdir/etex.ch \
+ $(srcdir)/pdfetexdir/pdfetex.ch1 \
+ $(srcdir)/pdftexdir/pdftex.ch \
+ $(srcdir)/pdftexdir/hz.ch \
+ $(srcdir)/pdftexdir/misc.ch \
+ $(srcdir)/pdfetexdir/pdfetex.ch2
+
+ pdfetex.web should contain system-independent changes only;
+
+Input:
+ etexdir/etex.ch:
+ system-independent changes by etex
+
+ pdfetexdir/pdfetex.ch1:
+ reverse some etex changes so system-independent pdftex change files can
+ be applied
+
+ pdftexdir/{pdftex,hz,misc}.ch:
+ system-independent changes by pdftex
+
+ pdfetexdir/pdfetex.ch2:
+ merge changes by etexdir/etex.ch & pdftexdir/{pdftex,hz,...}.ch
+
+Output:
+ pdfetex.web:
+ pdfetex without system-dependent changes
+
+
+2) pdfetex.ch is generated from
+ ./tie -c pdfetex.ch pdfetex.web \
+ $(srcdir)/pdfetexdir/tex.ch0 \
+ $(srcdir)/tex.ch \
+ $(srcdir)/etexdir/tex.ch1 \
+ $(srcdir)/etexdir/tex.ech \
+ $(srcdir)/pdfetexdir/tex.ch1 \
+ $(srcdir)/pdftexdir/tex.pch
+
+Input:
+ pdfetex.web:
+ from step 1), ie pdfetex without system-dependent changes
+
+ pdfetexdir/tex.ch0:
+ % Change file to assist in creating the web2c-specific change file.
+ % This one comes first, resolves inconsistencies between the generated
+ % pdfetex.web and tex.ch
+
+ change the pdfetex banner to tex banner, so tex.ch can be applied
+
+ tex.ch:
+ the main web2c-specific (or other system-dependent) change file
+
+ the etex changes files:
+ system-dependent changes by etex
+
+ pdfetexdir/tex.ch1:
+ reverses some system-dependent changes by etex (the banner) so
+ pdftexdir/tex.pch can be applied
+
+ pdftexdir/tex.pch:
+ system-dependent changes by pdftex
+
+Output:
+ pdfetex.ch:
+ additional & system-dependent changes
diff --git a/Build/source/texk/web2c/pdftexdir/depend.mak b/Build/source/texk/web2c/pdftexdir/depend.mak
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/depend.mak
diff --git a/Build/source/texk/web2c/pdftexdir/depend.mk b/Build/source/texk/web2c/pdftexdir/depend.mk
new file mode 100644
index 00000000000..3f83c3d34d9
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/depend.mk
@@ -0,0 +1,54 @@
+epdf.o: epdf.c ptexlib.h ../pdftexd.h ../texmfmp.h ../cpascal.h \
+ ../config.h ../help.h ../texmfmem.h ../pdftexcoerce.h ptexmac.h
+mapfile.o: mapfile.c ptexlib.h ../pdftexd.h ../texmfmp.h ../cpascal.h \
+ ../config.h ../help.h ../texmfmem.h ../pdftexcoerce.h ptexmac.h
+papersiz.o: papersiz.c ptexlib.h ../pdftexd.h ../texmfmp.h \
+ ../cpascal.h ../config.h ../help.h ../texmfmem.h ../pdftexcoerce.h \
+ ptexmac.h
+utils.o: utils.c ptexlib.h ../pdftexd.h ../texmfmp.h ../cpascal.h \
+ ../config.h ../help.h ../texmfmem.h ../pdftexcoerce.h ptexmac.h \
+ ../../../libs/zlib/zlib.h ../../../libs/zlib/zconf.h \
+ ../../../libs/md5/md5.h pdftexextra.h
+vfpacket.o: vfpacket.c ptexlib.h ../pdftexd.h ../texmfmp.h \
+ ../cpascal.h ../config.h ../help.h ../texmfmem.h ../pdftexcoerce.h \
+ ptexmac.h
+pkin.o: pkin.c ptexlib.h ../pdftexd.h ../texmfmp.h ../cpascal.h \
+ ../config.h ../help.h ../texmfmem.h ../pdftexcoerce.h ptexmac.h
+writefont.o: writefont.c ../../../libs/xpdf/goo/gmem.h ptexlib.h \
+ ../pdftexd.h ../texmfmp.h ../cpascal.h ../config.h ../help.h \
+ ../texmfmem.h ../pdftexcoerce.h ptexmac.h
+writet1.o: writet1.c ptexlib.h ../pdftexd.h ../texmfmp.h ../cpascal.h \
+ ../config.h ../help.h ../texmfmem.h ../pdftexcoerce.h ptexmac.h
+writet3.o: writet3.c ptexlib.h ../pdftexd.h ../texmfmp.h ../cpascal.h \
+ ../config.h ../help.h ../texmfmem.h ../pdftexcoerce.h ptexmac.h
+writezip.o: writezip.c ptexlib.h ../pdftexd.h ../texmfmp.h \
+ ../cpascal.h ../config.h ../help.h ../texmfmem.h ../pdftexcoerce.h \
+ ptexmac.h ../../../libs/zlib/zlib.h ../../../libs/zlib/zconf.h
+writeenc.o: writeenc.c ptexlib.h ../pdftexd.h ../texmfmp.h \
+ ../cpascal.h ../config.h ../help.h ../texmfmem.h ../pdftexcoerce.h \
+ ptexmac.h
+writettf.o: writettf.c ptexlib.h ../pdftexd.h ../texmfmp.h \
+ ../cpascal.h ../config.h ../help.h ../texmfmem.h ../pdftexcoerce.h \
+ ptexmac.h macnames.c
+writejpg.o: writejpg.c ptexlib.h ../pdftexd.h ../texmfmp.h \
+ ../cpascal.h ../config.h ../help.h ../texmfmem.h ../pdftexcoerce.h \
+ ptexmac.h image.h
+writepng.o: writepng.c ptexlib.h ../pdftexd.h ../texmfmp.h \
+ ../cpascal.h ../config.h ../help.h ../texmfmem.h ../pdftexcoerce.h \
+ ptexmac.h image.h
+writeimg.o: writeimg.c ptexlib.h ../pdftexd.h ../texmfmp.h \
+ ../cpascal.h ../config.h ../help.h ../texmfmem.h ../pdftexcoerce.h \
+ ptexmac.h image.h
+pdftoepdf.o: pdftoepdf.cc ../../../libs/xpdf/xpdf/Object.h \
+ ../../../libs/xpdf/goo/gmem.h ../../../libs/xpdf/xpdf/Array.h \
+ ../../../libs/xpdf/xpdf/Dict.h ../../../libs/xpdf/xpdf/Stream.h \
+ ../../../libs/xpdf/xpdf/XRef.h ../../../libs/xpdf/xpdf/Catalog.h \
+ ../../../libs/xpdf/xpdf/Page.h ../../../libs/xpdf/xpdf/GfxFont.h \
+ ../../../libs/xpdf/xpdf/Error.h epdf.h
+ttf2afm.o: ttf2afm.c macnames.c
+pdftosrc.o: pdftosrc.cc ../../../libs/xpdf/xpdf/Object.h \
+ ../../../libs/xpdf/xpdf/Array.h ../../../libs/xpdf/xpdf/Dict.h \
+ ../../../libs/xpdf/xpdf/Stream.h ../../../libs/xpdf/xpdf/XRef.h \
+ ../../../libs/xpdf/xpdf/Catalog.h ../../../libs/xpdf/xpdf/Page.h \
+ ../../../libs/xpdf/xpdf/PDFDoc.h ../../../libs/xpdf/xpdf/Link.h \
+ ../../../libs/xpdf/xpdf/Error.h ../../../libs/xpdf/xpdf/config.h
diff --git a/Build/source/texk/web2c/pdftexdir/epdf.c b/Build/source/texk/web2c/pdftexdir/epdf.c
new file mode 100644
index 00000000000..95000755b0d
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/epdf.c
@@ -0,0 +1,75 @@
+/*
+Copyright (c) 1996-2002 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX 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.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/epdf.c#10 $
+*/
+
+#include "ptexlib.h"
+#include <kpathsea/c-vararg.h>
+#include <kpathsea/c-proto.h>
+
+integer pdfbufmax = pdfbufsize;
+
+extern void epdf_check_mem(void);
+
+int is_subsetable(fm_entry *fm)
+{
+ return is_included(fm) && is_subsetted(fm);
+}
+
+int is_type1(fm_entry *fm)
+{
+ return is_t1fontfile(fm);
+}
+
+void mark_glyphs(fm_entry *fm, char *charset)
+{
+ char *new_charset = fm->charset;
+ if (charset == NULL)
+ return;
+ if (new_charset == NULL)
+ new_charset = xstrdup(charset);
+ else {
+ xretalloc(new_charset, strlen(new_charset)+strlen(charset)+1, char);
+ strcat(new_charset, charset);
+ }
+ fm->charset = new_charset;
+}
+
+void embed_whole_font(fm_entry *fm)
+{
+ fm->all_glyphs = true;
+}
+
+integer get_fontfile(fm_entry *fm)
+{
+ return fm->ff_objnum;
+}
+
+integer get_fontname(fm_entry *fm)
+{
+ if (fm->fn_objnum == 0)
+ fm->fn_objnum = pdfnewobjnum();
+ return fm->fn_objnum;
+}
+
+void epdf_free(void)
+{
+ epdf_check_mem();
+}
diff --git a/Build/source/texk/web2c/pdftexdir/epdf.h b/Build/source/texk/web2c/pdftexdir/epdf.h
new file mode 100644
index 00000000000..27ce221061d
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/epdf.h
@@ -0,0 +1,103 @@
+/*
+Copyright (c) 1996-2004 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX 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.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/epdf.h#17 $
+*/
+
+extern "C" {
+
+#include <kpathsea/c-auto.h>
+
+/* the following code is extremly ugly but needed for including web2c/config.h */
+
+#include <kpathsea/c-proto.h> /* define P?H macros */
+
+typedef const char *const_string; /* including kpathsea/types.h doesn't work on some systems */
+
+#define KPATHSEA_CONFIG_H /* avoid including other kpathsea header files */
+ /* from web2c/config.h */
+
+#ifdef CONFIG_H /* CONFIG_H has been defined by some xpdf */
+#undef CONFIG_H /* header file */
+#endif
+
+#include <web2c/c-auto.h> /* define SIZEOF_LONG */
+#include <web2c/config.h> /* define type integer */
+
+#include <web2c/pdftexdir/ptexmac.h>
+
+#define pdfbufsize pdfbufmax
+
+extern float epdf_width;
+extern float epdf_height;
+extern float epdf_orig_x;
+extern float epdf_orig_y;
+extern integer epdf_selected_page;
+extern integer epdf_num_pages;
+extern integer epdf_page_box;
+extern integer epdf_always_use_pdf_pagebox;
+extern void *epdf_doc;
+extern void *epdf_xref;
+
+extern integer pdfstreamlength;
+extern integer pdfptr;
+typedef unsigned char eightbits ;
+extern eightbits pdfbuf[];
+extern integer pdfbufmax;
+
+extern char notdef[];
+
+extern int is_subsetable(struct fm_entry *);
+extern int is_type1(struct fm_entry *);
+extern struct fm_entry * lookup_fontmap(char *);
+extern integer get_fontfile(struct fm_entry *);
+extern integer get_fontname(struct fm_entry *);
+extern integer pdfnewobjnum(void);
+extern integer read_pdf_info(char*, char*, integer, integer, integer, integer);
+extern void embed_whole_font(struct fm_entry *);
+extern void epdf_check_mem(void);
+extern void epdf_delete(void);
+extern void epdf_free(void);
+extern void mark_glyphs(struct fm_entry *, char *);
+extern void pdf_printf(const char *fmt,...);
+extern void pdf_puts(const char *);
+extern void pdfbeginstream(void);
+extern void pdfendobj(void);
+extern void pdfendstream(void);
+extern void pdfflush(void);
+extern void pdftex_fail(const char *fmt,...);
+extern void pdftex_warn(const char *fmt,...);
+extern void tex_printf(const char *, ...);
+extern void write_enc(char **, struct enc_entry *, integer);
+extern void write_epdf(void);
+extern void zpdfbegindict(integer);
+extern void zpdfbeginobj(integer);
+extern void zpdfcreateobj(integer, integer);
+extern void zpdfnewdict(integer, integer);
+
+/* utils.c */
+extern char *convertStringToPDFString(char *in, int len);
+
+/* config.c */
+extern integer cfgpar(integer);
+
+/* avlstuff.c */
+extern void avl_put_obj (integer, integer);
+extern integer avl_find_obj (integer, integer, integer);
+}
diff --git a/Build/source/texk/web2c/pdftexdir/hz.ch b/Build/source/texk/web2c/pdftexdir/hz.ch
new file mode 100644
index 00000000000..d8ec58fb5e7
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/hz.ch
@@ -0,0 +1,1935 @@
+% WEB change file containing HZ extensions for pdfTeX
+%
+% Copyright (c) 1996-2002 Han Th\^e\llap{\raise 0.5ex\hbox{\'{}}} Th\`anh, <thanh@pdftex.org>
+%
+% This file is part of pdfTeX.
+%
+% pdfTeX 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.
+%
+% pdfTeX is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with pdfTeX; if not, write to the Free Software
+% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+%
+% $Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/hz.ch#15 $
+
+@x [155] - margin kerning
+@d acc_kern=2 {|subtype| of kern nodes from accents}
+@y
+@d acc_kern=2 {|subtype| of kern nodes from accents}
+
+@# {memory structure for marginal kerns}
+@d margin_kern_node = 40
+@d margin_kern_node_size = 3
+@d margin_char(#) == info(# + 2)
+
+@# {|subtype| of marginal kerns}
+@d left_side == 0
+@d right_side == 1
+
+@# {base for lp/rp/ef codes starts from 2:
+ 0 for |hyphen_char|,
+ 1 for |skew_char|}
+@d lp_code_base == 2
+@d rp_code_base == 3
+@d ef_code_base == 4
+
+@d max_hlist_stack = 512 {maximum fill level for |hlist_stack|}
+{maybe good if larger than |2 * max_quarterword|, so that box nesting level would overflow first}
+@z
+
+@x [183] - margin kerning
+ kern_node: @<Display kern |p|@>;
+@y
+ margin_kern_node: begin
+ print_esc("kern");
+ print_scaled(width(p));
+ if subtype(p) = left_side then
+ print(" (left margin)")
+ else
+ print(" (right margin)");
+ end;
+ kern_node: @<Display kern |p|@>;
+@z
+
+@x [202] - margin kerning
+ kern_node,math_node,penalty_node: do_nothing;
+@y
+ kern_node,math_node,penalty_node: do_nothing;
+ margin_kern_node: begin
+ free_avail(margin_char(p));
+ free_node(p, margin_kern_node_size);
+ goto done;
+ end;
+@z
+
+@x [206] - margin kerning
+kern_node,math_node,penalty_node: begin r:=get_node(small_node_size);
+ words:=small_node_size;
+ end;
+@y
+kern_node,math_node,penalty_node: begin r:=get_node(small_node_size);
+ words:=small_node_size;
+ end;
+margin_kern_node: begin
+ r := get_node(margin_kern_node_size);
+ fast_get_avail(margin_char(r));
+ font(margin_char(r)) := font(margin_char(p));
+ character(margin_char(r)) := character(margin_char(p));
+ words := small_node_size;
+ end;
+@z
+
+@x [236]
+@d pdf_int_pars=pdftex_first_integer_code + 17 {total number of \pdfTeX's integer parameters}
+@y
+@d pdf_adjust_spacing_code = pdftex_first_integer_code + 17 {level of spacing adjusting}
+@d pdf_protrude_chars_code = pdftex_first_integer_code + 18 {protrude chars at left/right edge of paragraphs}
+@d pdf_tracing_fonts_code = pdftex_first_integer_code + 19 {level of font detail in log}
+@d pdf_int_pars=pdftex_first_integer_code + 20 {total number of \pdfTeX's integer parameters}
+@z
+
+@x [236]
+@d error_context_lines==int_par(error_context_lines_code)
+@y
+@d error_context_lines==int_par(error_context_lines_code)
+@#
+@d pdf_adjust_spacing == int_par(pdf_adjust_spacing_code)
+@d pdf_protrude_chars == int_par(pdf_protrude_chars_code)
+@d pdf_tracing_fonts == int_par(pdf_tracing_fonts_code)
+@z
+
+@x [237]
+error_context_lines_code:print_esc("errorcontextlines");
+@y
+error_context_lines_code:print_esc("errorcontextlines");
+@#
+pdf_adjust_spacing_code: print_esc("pdfadjustspacing");
+pdf_protrude_chars_code: print_esc("pdfprotrudechars");
+pdf_tracing_fonts_code: print_esc("pdftracingfonts");
+@z
+
+@x [238]
+primitive("errorcontextlines",assign_int,int_base+error_context_lines_code);@/
+@!@:error_context_lines_}{\.{\\errorcontextlines} primitive@>
+@y
+primitive("errorcontextlines",assign_int,int_base+error_context_lines_code);@/
+@!@:error_context_lines_}{\.{\\errorcontextlines} primitive@>
+primitive("pdfadjustspacing",assign_int,int_base+pdf_adjust_spacing_code);@/
+@!@:pdf_adjust_spacing_}{\.{\\pdfadjustspacing} primitive@>
+primitive("pdfprotrudechars",assign_int,int_base+pdf_protrude_chars_code);@/
+@!@:pdf_protrude_chars_}{\.{\\pdfprotrudechars} primitive@>
+primitive("pdftracingfonts",assign_int,int_base+pdf_tracing_fonts_code);@/
+@!@:pdf_tracing_fonts_}{\.{\\pdftracingfonts} primitive@>
+@z
+
+@x [267] - displaying fonts
+@<Print the font identifier for |font(p)|@>=
+print_esc(font_id_text(font(p)))
+@y
+@<Print the font identifier for |font(p)|@>=
+begin
+ print_esc(font_id_text(font(p)));
+ if pdf_tracing_fonts > 0 then begin
+ print(" (");
+ print(font_name[font(p)]);
+ if font_size[font(p)] <> font_dsize[font(p)] then begin
+ print("@@");
+ print_scaled(font_size[font(p)]);
+ print("pt");
+ end;
+ print(")");
+ end else
+ if pdf_font_expand_ratio[font(p)] <> 0 then begin
+ print(" (");
+ if pdf_font_expand_ratio[font(p)] > 0 then
+ print("+");
+ print_int(pdf_font_expand_ratio[font(p)]);
+ print(")");
+ end;
+end
+@z
+
+@x [413] - font expansion
+var m:halfword; {|chr_code| part of the operand token}
+@y
+var m:halfword; {|chr_code| part of the operand token}
+ n, k: integer; {accumulators}
+@z
+
+@x [426] - font expansion, margin kerning
+begin scan_font_ident;
+if m=0 then scanned_result(hyphen_char[cur_val])(int_val)
+else scanned_result(skew_char[cur_val])(int_val);
+@y
+begin scan_font_ident;
+if m=0 then scanned_result(hyphen_char[cur_val])(int_val)
+else if m=1 then scanned_result(skew_char[cur_val])(int_val)
+else begin
+ n := cur_val;
+ scan_char_num;
+ k := cur_val;
+ case m of
+ lp_code_base: scanned_result(get_lp_code(n, k))(int_val);
+ rp_code_base: scanned_result(get_rp_code(n, k))(int_val);
+ ef_code_base: scanned_result(get_ef_code(n, k))(int_val);
+ end;
+end;
+@z
+
+@x [468]
+@d pdftex_convert_codes = pdftex_first_expand_code + 9 {end of \pdfTeX's command codes}
+@y
+@d left_margin_kern_code = pdftex_first_expand_code + 9 {command code for \.{\\leftmarginkern}}
+@d right_margin_kern_code = pdftex_first_expand_code + 10 {command code for \.{\\rightmarginkern}}
+@d pdftex_convert_codes = pdftex_first_expand_code + 11 {end of \pdfTeX's command codes}
+@z
+
+@x [468]
+primitive("pdfpageref",convert,pdf_page_ref_code);@/
+@!@:pdf_page_ref_}{\.{\\pdfpageref} primitive@>
+@y
+primitive("pdfpageref",convert,pdf_page_ref_code);@/
+@!@:pdf_page_ref_}{\.{\\pdfpageref} primitive@>
+primitive("leftmarginkern",convert,left_margin_kern_code);@/
+@!@:left_margin_kern_}{\.{\\leftmarginkern} primitive@>
+primitive("rightmarginkern",convert,right_margin_kern_code);@/
+@!@:right_margin_kern_}{\.{\\rightmarginkern} primitive@>
+@z
+
+@x [469]
+ pdf_page_ref_code: print_esc("pdfpageref");
+@y
+ pdf_page_ref_code: print_esc("pdfpageref");
+ left_margin_kern_code: print_esc("leftmarginkern");
+ right_margin_kern_code: print_esc("rightmarginkern");
+@z
+
+@x [470]
+var old_setting:0..max_selector; {holds |selector| setting}
+@y
+var old_setting:0..max_selector; {holds |selector| setting}
+p, q: pointer;
+@z
+
+@x [471]
+pdf_page_ref_code: begin
+ scan_int;
+ if cur_val <= 0 then
+ pdf_error("pageref", "invalid page number");
+end;
+@y
+pdf_page_ref_code: begin
+ scan_int;
+ if cur_val <= 0 then
+ pdf_error("pageref", "invalid page number");
+end;
+left_margin_kern_code, right_margin_kern_code: begin
+ scan_int;
+ if (box(cur_val) = null) or (type(box(cur_val)) <> hlist_node) then
+ pdf_error("marginkern", "a non-empty hbox expected")
+end;
+@z
+
+@x [472]
+pdf_page_ref_code: print_int(get_obj(obj_type_page, cur_val, false));
+@y
+pdf_page_ref_code: print_int(get_obj(obj_type_page, cur_val, false));
+left_margin_kern_code: begin
+ p := list_ptr(box(cur_val));
+ if (p <> null) and (not is_char_node(p)) and
+ (type(p) = glue_node) and (subtype(p) = left_skip_code + 1) then
+ p := link(p);
+ if (p <> null) and (not is_char_node(p)) and
+ (type(p) = margin_kern_node) and (subtype(p) = left_side) then
+ print_scaled(width(p))
+ else
+ print("0");
+ print("pt");
+end;
+right_margin_kern_code: begin
+ q := list_ptr(box(cur_val));
+ p := null;
+ if q <> null then begin
+ p := prev_rightmost(q, null);
+ if (p <> null) and (not is_char_node(p)) and
+ (type(p) = glue_node) and (subtype(p) = right_skip_code + 1) then
+ p := prev_rightmost(q, p);
+ end;
+ if (p <> null) and (not is_char_node(p)) and
+ (type(p) = margin_kern_node) and (subtype(p) = right_side) then
+ print_scaled(width(p))
+ else
+ print("0");
+ print("pt");
+end;
+@z
+
+@x [622] - margin kerning
+glue_node: @<Move right or output leaders@>;
+@y
+glue_node: @<Move right or output leaders@>;
+margin_kern_node,
+@z
+
+
+@x [???] - font expansion
+@!tmp_f: internal_font_number; {for use with |pdf_init_font|}
+
+@y
+@!tmp_f: internal_font_number; {for use with |pdf_init_font|}
+@ Here come some subroutines to deal with expanded fonts for HZ-algorithm.
+
+@p
+function init_font_base(v: integer): integer;
+var i, j: integer;
+begin
+ i := pdf_get_mem(256);
+ for j := 0 to 255 do
+ pdf_mem[i + j] := v;
+ init_font_base := i;
+end;
+
+procedure set_lp_code(f: internal_font_number; c: eight_bits; i: integer);
+begin
+ if pdf_font_lp_base[f] = 0 then
+ pdf_font_lp_base[f] := init_font_base(0);
+ pdf_mem[pdf_font_lp_base[f] + c] := fix_int(i, -1000, 1000);
+end;
+
+procedure set_rp_code(f: internal_font_number; c: eight_bits; i: integer);
+begin
+ if pdf_font_rp_base[f] = 0 then
+ pdf_font_rp_base[f] := init_font_base(0);
+ pdf_mem[pdf_font_rp_base[f] + c] := fix_int(i, -1000, 1000);
+end;
+
+procedure set_ef_code(f: internal_font_number; c: eight_bits; i: integer);
+begin
+ if pdf_font_ef_base[f] = 0 then
+ pdf_font_ef_base[f] := init_font_base(1000);
+ pdf_mem[pdf_font_ef_base[f] + c] := fix_int(i, 0, 1000);
+end;
+
+function expand_font_name(f: internal_font_number; e: integer): str_number;
+var old_setting:0..max_selector; {holds |selector| setting}
+begin
+ old_setting:=selector; selector:=new_string;
+ print(font_name[f]);
+ if e > 0 then
+ print("+"); {minus sign will be printed by |print_int|}
+ print_int(e);
+ selector:=old_setting;
+ expand_font_name := make_string;
+end;
+
+function auto_expand_font(f: internal_font_number; e: integer): internal_font_number;
+{creates an expanded font from the base font; doesn't load expanded tfm at all}
+var k: internal_font_number;
+ nw, nk, ni, i, j: integer;
+begin
+ k := font_ptr + 1;
+ incr(font_ptr);
+ if (font_ptr >= font_max) then
+ overflow("maximum internal font number (font_max)", font_max);
+ font_name[k] := expand_font_name(f, e);
+ font_area[k] := font_area[f];
+ font_id_text(k) := font_id_text(f);
+ hyphen_char[k] := hyphen_char[f];
+ skew_char[k] := skew_char[f];
+ font_bchar[k] := font_bchar[f];
+ font_false_bchar[k] := font_false_bchar[f];
+ font_bc[k] := font_bc[f];
+ font_ec[k] := font_ec[f];
+ font_size[k] := font_size[f];
+ font_dsize[k] := font_dsize[f];
+ font_params[k] := font_params[f];
+ font_glue[k] := font_glue[f];
+ bchar_label[k] := bchar_label[f];
+
+ char_base[k] := char_base[f];
+ height_base[k] := height_base[f];
+ depth_base[k] := depth_base[f];
+ lig_kern_base[k] := lig_kern_base[f];
+ exten_base[k] := exten_base[f];
+ param_base[k] := param_base[f];
+
+ nw := height_base[f] - width_base[f];
+ ni := lig_kern_base[f] - italic_base[f];
+ nk := exten_base[f] - (kern_base[f] + kern_base_offset);
+ if (fmem_ptr + nw + ni + nk >= font_mem_size) then
+ overflow("number of words of font memory (font_mem_size)", font_mem_size);
+ width_base[k] := fmem_ptr;
+ italic_base[k] := width_base[k] + nw;
+ kern_base[k] := italic_base[k] + ni - kern_base_offset;
+ fmem_ptr := fmem_ptr + nw + ni + nk;
+
+ for i := 0 to nw - 1 do
+ font_info[width_base[k] + i].sc :=
+ round_xn_over_d(font_info[width_base[f] + i].sc, 1000 + e, 1000);
+ for i := 0 to ni - 1 do
+ font_info[italic_base[k] + i].sc :=
+ round_xn_over_d(font_info[italic_base[f] + i].sc, 1000 + e, 1000);
+ for i := 0 to nk - 1 do
+ font_info[kern_base[k] + kern_base_offset + i].sc :=
+ round_xn_over_d(font_info[kern_base[f] + kern_base_offset + i].sc, 1000 + e, 1000);
+
+ auto_expand_font := k;
+end;
+
+procedure set_expand_param(k, f: internal_font_number; e: integer);
+var i, j: integer;
+begin
+ if pdf_font_rp_base[f] = 0 then
+ pdf_font_rp_base[f] := init_font_base(0);
+ if pdf_font_lp_base[f] = 0 then
+ pdf_font_lp_base[f] := init_font_base(0);
+ if pdf_font_ef_base[f] = 0 then
+ pdf_font_ef_base[f] := init_font_base(1000);
+ pdf_font_expand_ratio[k] := e;
+ pdf_font_step[k] := pdf_font_step[f];
+ pdf_font_auto_expand[k] := pdf_font_auto_expand[f];
+ pdf_font_blink[k] := f; {???}
+ pdf_font_lp_base[k] := pdf_font_lp_base[f];
+ pdf_font_rp_base[k] := pdf_font_rp_base[f];
+ pdf_font_ef_base[k] := pdf_font_ef_base[f];
+end;
+
+function tfm_lookup(s: str_number; fs: scaled): internal_font_number;
+{looks up for a TFM with name |s| loaded at |fs| size; if found then flushes |s|}
+var k: internal_font_number;
+begin
+ if fs <> 0 then begin
+ for k := font_base + 1 to font_ptr do
+ if str_eq_str(font_name[k], s) and (font_size[k] = fs) then begin
+ flush_str(s);
+ tfm_lookup := k;
+ return;
+ end;
+ end
+ else begin
+ for k := font_base + 1 to font_ptr do
+ if str_eq_str(font_name[k], s) then begin
+ flush_str(s);
+ tfm_lookup := k;
+ return;
+ end;
+ end;
+ tfm_lookup := null_font;
+end;
+
+function load_expand_font(f: internal_font_number; e: integer): internal_font_number;
+{loads font |f| expanded by |e| thousandths into font memory; |e| is nonzero
+and is a multiple of |pdf_font_step[f]|}
+label found;
+var s: str_number; {font name}
+ k: internal_font_number;
+begin
+ s := expand_font_name(f, e);
+ k := tfm_lookup(s, font_size[f]);
+ if k = null_font then begin
+ if pdf_font_auto_expand[f] then
+ k := auto_expand_font(f, e)
+ else
+ k := read_font_info(null_cs, s, "", font_size[f]);
+ end;
+ set_expand_param(k, f, e);
+ load_expand_font := k;
+end;
+
+function auto_expand_vf(f: internal_font_number): boolean;
+{check for a virtual auto-expanded font}
+var save_f, bf, lf, k: internal_font_number;
+ e: integer;
+begin
+ auto_expand_vf := false;
+ if (not pdf_font_auto_expand[f]) or (pdf_font_blink[f] = null_font) then
+ return; {not an auto-expanded font}
+ bf := pdf_font_blink[f];
+ if pdf_font_type[bf] = new_font_type then {we must process the base font first}
+ begin
+ save_f := tmp_f;
+ tmp_f := bf;
+ do_vf;
+ tmp_f := save_f;
+ end;
+
+ if pdf_font_type[bf] <> virtual_font_type then
+ return; {not a virtual font}
+
+ e := pdf_font_expand_ratio[f];
+ for k := 0 to vf_local_font_num[bf] - 1 do begin
+ lf := vf_default_font[bf] + k;
+ vf_e_fnts[vf_nf] := vf_e_fnts[lf];
+ vf_i_fnts[vf_nf] := auto_expand_font(vf_i_fnts[lf], e);
+ set_expand_param(vf_i_fnts[vf_nf], vf_i_fnts[lf], e);
+ incr(vf_nf);
+ end;
+ vf_packet_base[f] := vf_packet_base[bf];
+ vf_local_font_num[f] := vf_local_font_num[bf];
+ vf_default_font[f] := vf_nf - vf_local_font_num[f];
+
+ pdf_font_type[f] := virtual_font_type;
+ auto_expand_vf := true;
+end;
+
+function fix_expand_value(f: internal_font_number; e: integer): integer;
+{return the multiple of |pdf_font_step[f]| that is nearest to |e|}
+var step: integer;
+ max_expand: integer;
+ neg: boolean;
+begin
+ fix_expand_value := 0;
+ if e = 0 then
+ return;
+ if e < 0 then begin
+ e := -e;
+ neg := true;
+ max_expand := -pdf_font_expand_ratio[pdf_font_shrink[f]];
+ end
+ else begin
+ neg := false;
+ max_expand := pdf_font_expand_ratio[pdf_font_stretch[f]];
+ end;
+ if e > max_expand then
+ e := max_expand
+ else begin
+ step := pdf_font_step[f];
+ if e mod step > 0 then
+ e := step*round_xn_over_d(e, 1, step);
+ end;
+ if neg then
+ e := -e;
+ fix_expand_value := e;
+end;
+
+function get_expand_font(f: internal_font_number; e: integer): internal_font_number;
+{look up and create if not found an expanded version of |f|; |f| is an
+expandable font; |e| is nonzero and is a multiple of |pdf_font_step[f]|}
+var k: internal_font_number;
+begin
+ k := pdf_font_elink[f];
+ while k <> null_font do begin
+ if pdf_font_expand_ratio[k] = e then begin
+ get_expand_font := k;
+ return;
+ end;
+ k := pdf_font_elink[k];
+ end;
+ k := load_expand_font(f, e);
+ pdf_font_elink[k] := pdf_font_elink[f];
+ pdf_font_elink[f] := k;
+ get_expand_font := k;
+end;
+
+function expand_font(f: internal_font_number; e: integer): internal_font_number;
+{looks up for font |f| expanded by |e| thousandths, |e| is an arbitrary value
+between max stretch and max shrink of |f|; if not found then creates it}
+var max_expand: integer;
+begin
+ expand_font := f;
+ if e = 0 then
+ return;
+ e := fix_expand_value(f, e);
+ if e = 0 then
+ return;
+ if pdf_font_elink[f] = null_font then
+ pdf_error("font expansion", "uninitialized pdf_font_elink");
+ expand_font := get_expand_font(f, e);
+end;
+
+procedure read_expand_font; {read font expansion spec and load expanded font}
+var font_shrink, font_stretch, font_step: integer;
+ f: internal_font_number;
+ auto_expand: boolean;
+begin
+ {read font expansion parameters}
+ scan_font_ident;
+ f := cur_val;
+ if f = null_font then
+ pdf_error("font expansion", "invalid font identifier");
+ scan_optional_equals;
+ scan_int;
+ font_stretch := fix_int(cur_val, 0, 1000);
+ scan_int;
+ font_shrink := fix_int(cur_val, 0, 1000);
+ scan_int;
+ font_step := fix_int(cur_val, 0, 1000);
+ if font_step = 0 then
+ pdf_error("font expansion", "invalid step");
+ font_stretch := font_stretch - font_stretch mod font_step;
+ if font_stretch < 0 then
+ font_stretch := 0;
+ font_shrink := font_shrink - font_shrink mod font_step;
+ if font_shrink < 0 then
+ font_shrink := 0;
+ if font_shrink = 1000 then
+ font_shrink := font_shrink - font_step; {don't allow zero-width font}
+ if (font_stretch = 0) and (font_shrink = 0) then
+ pdf_error("font expansion", "invalid limit");
+ auto_expand := false;
+ if scan_keyword("autoexpand") then begin
+ auto_expand := true;
+ @<Scan an optional space@>; end;
+
+ {check if the font can be expanded}
+ if (pdf_font_expand_ratio[f] <> 0) then
+ pdf_error("font expansion", "this font has been expanded by another font so it cannot be used now");
+ if (pdf_font_step[f] <> 0) then
+ {this font has been expanded, ensure the expansion parameters are identical}
+ begin
+ if (pdf_font_step[f] <> font_step) or
+ ((pdf_font_stretch[f] = null_font) and (font_stretch <> 0)) or
+ ((pdf_font_stretch[f] <> null_font) and
+ (pdf_font_expand_ratio[pdf_font_stretch[f]] <> font_stretch)) or
+ ((pdf_font_shrink[f] = null_font) and (font_shrink <> 0)) or
+ ((pdf_font_shrink[f] <> null_font) and
+ (pdf_font_expand_ratio[pdf_font_shrink[f]] <> -font_shrink)) or
+ (pdf_font_auto_expand[f] <> auto_expand)
+ then
+ pdf_error("font expansion", "font has been expanded with different parameters");
+ end
+ else begin
+ pdf_font_step[f] := font_step;
+ pdf_font_auto_expand[f] := auto_expand;
+ if font_stretch > 0 then
+ pdf_font_stretch[f] := get_expand_font(f, font_stretch);
+ if font_shrink > 0 then
+ pdf_font_shrink[f] := get_expand_font(f, -font_shrink);
+ end;
+end;
+@z
+
+@x [32f] - margin kerning
+glue_node: @<(\pdfTeX) Move right or output leaders@>;
+@y
+glue_node: @<(\pdfTeX) Move right or output leaders@>;
+margin_kern_node,
+@z
+
+@x [649] - font expansion
+@ Here now is |hpack|, which contains few if any surprises.
+
+@p function hpack(@!p:pointer;@!w:scaled;@!m:small_number):pointer;
+@y
+@ @<Glob...@>=
+@!pdf_font_blink: ^internal_font_number; {link to base font (used for expanded fonts only)}
+@!pdf_font_elink: ^internal_font_number; {link to expanded fonts (used for base fonts only)}
+@!pdf_font_stretch: ^integer; {limit of stretching}
+@!pdf_font_shrink: ^integer; {limit of shrinking}
+@!pdf_font_step: ^integer; {amount of one step of expansion}
+@!pdf_font_expand_ratio: ^integer; {expansion ratio of a particular font}
+@!pdf_font_auto_expand: ^boolean; {this font is auto-expanded?}
+@!pdf_font_lp_base: ^integer; {base of left-protruding factor}
+@!pdf_font_rp_base: ^integer; {base of right-protruding factor}
+@!pdf_font_ef_base: ^integer; {base of font expansion factor}
+@!font_expand_ratio: integer; {current expansion ratio}
+@!last_leftmost_char: pointer;
+@!last_rightmost_char: pointer;
+@!hlist_stack:array[0..max_hlist_stack] of pointer; {stack for |find_protchar_left()| and |find_protchar_right()|}
+@!hlist_stack_level:0..max_hlist_stack; {fill level for |hlist_stack|}
+
+@ @d cal_margin_kern_var(#) ==
+begin
+ character(cp) := character(#);
+ font(cp) := font(#);
+ do_subst_font(cp, 1000);
+ if font(cp) <> font(#) then
+ margin_kern_stretch := margin_kern_stretch + left_pw(#) - left_pw(cp);
+ font(cp) := font(#);
+ do_subst_font(cp, -1000);
+ if font(cp) <> font(#) then
+ margin_kern_shrink := margin_kern_shrink + left_pw(cp) - left_pw(#);
+end
+
+@<Calculate variations of marginal kerns@>=
+begin
+ lp := last_leftmost_char;
+ rp := last_rightmost_char;
+ fast_get_avail(cp);
+ if lp <> null then
+ cal_margin_kern_var(lp);
+ if rp <> null then
+ cal_margin_kern_var(rp);
+ free_avail(cp);
+end
+
+@ Here is |hpack|, which is place where we do font substituting when
+font expansion is being used. We define some constants used when calling
+|hpack| to deal with font expansion.
+
+@d cal_expand_ratio == 2 {calculate amount for font expansion after breaking
+ paragraph into lines}
+@d subst_ex_font == 3 {substitute fonts}
+
+@d substituted = 3 {|subtype| of kern nodes that should be substituted}
+
+@d left_pw(#) == char_pw(#, left_side)
+@d right_pw(#) == char_pw(#, right_side)
+
+@p
+function check_expand_pars(f: internal_font_number): boolean;
+var k: internal_font_number;
+begin
+ check_expand_pars := false;
+ if (pdf_font_step[f] = 0) or ((pdf_font_stretch[f] = null_font) and
+ (pdf_font_shrink[f] = null_font)) then
+ return;
+ if cur_font_step < 0 then
+ cur_font_step := pdf_font_step[f]
+ else if cur_font_step <> pdf_font_step[f] then
+ pdf_error("font expansion", "using fonts with different step of expansion in one paragraph is not allowed");
+ k := pdf_font_stretch[f];
+ if k <> null_font then begin
+ if max_stretch_ratio < 0 then
+ max_stretch_ratio := pdf_font_expand_ratio[k]
+ else if max_stretch_ratio <> pdf_font_expand_ratio[k] then
+ pdf_error("font expansion", "using fonts with different limit of expansion in one paragraph is not allowed");
+ end;
+ k := pdf_font_shrink[f];
+ if k <> null_font then begin
+ if max_shrink_ratio < 0 then
+ max_shrink_ratio := pdf_font_expand_ratio[k]
+ else if max_shrink_ratio <> pdf_font_expand_ratio[k] then
+ pdf_error("font expansion", "using fonts with different limit of expansion in one paragraph is not allowed");
+ end;
+ check_expand_pars := true;
+end;
+
+function char_stretch(f: internal_font_number; c: eight_bits): scaled;
+var k: internal_font_number;
+ dw: scaled;
+ ef: integer;
+begin
+ char_stretch := 0;
+ k := pdf_font_stretch[f];
+ ef := get_ef_code(f, c);
+ if (k <> null_font) and (ef > 0) then begin
+ dw := char_width(k)(char_info(k)(c)) - char_width(f)(char_info(f)(c));
+ if dw > 0 then
+ char_stretch := round_xn_over_d(dw, ef, 1000);
+ end;
+end;
+
+function char_shrink(f: internal_font_number; c: eight_bits): scaled;
+var k: internal_font_number;
+ dw: scaled;
+ ef: integer;
+begin
+ char_shrink := 0;
+ k := pdf_font_shrink[f];
+ ef := get_ef_code(f, c);
+ if (k <> null_font) and (ef > 0) then begin
+ dw := char_width(f)(char_info(f)(c)) - char_width(k)(char_info(k)(c));
+ if dw > 0 then
+ char_shrink := round_xn_over_d(dw, ef, 1000);
+ end;
+end;
+
+function get_kern(f: internal_font_number; lc, rc: eight_bits): scaled;
+label continue;
+var i: four_quarters;
+ j: four_quarters;
+ k: font_index;
+ p: pointer;
+ s: integer;
+begin
+ get_kern := 0;
+ i := char_info(f)(lc);
+ if char_tag(i) <> lig_tag then
+ return;
+ k := lig_kern_start(f)(i);
+ j := font_info[k].qqqq;
+ if skip_byte(j) <= stop_flag then
+ goto continue + 1;
+ k := lig_kern_restart(f)(j);
+continue:
+ j := font_info[k].qqqq;
+continue + 1:
+ if (next_char(j) = rc) and (skip_byte(j) <= stop_flag) and
+ (op_byte(j) >= kern_flag)
+ then begin
+ get_kern := char_kern(f)(j);
+ return;
+ end;
+ if skip_byte(j) = qi(0) then
+ incr(k)
+ else begin
+ if skip_byte(j) >= stop_flag then
+ return;
+ k := k + qo(skip_byte(j)) + 1;
+ end;
+ goto continue;
+end;
+
+function kern_stretch(p: pointer): scaled;
+var l, r: pointer;
+ d: scaled;
+begin
+ kern_stretch := 0;
+ if (prev_char_p = null) or (link(prev_char_p) <> p) or (link(p) = null)
+ then
+ return;
+ l := prev_char_p;
+ r := link(p);
+ if type(l) = ligature_node then
+ l := lig_char(l);
+ if type(r) = ligature_node then
+ r := lig_char(r);
+ if not (is_char_node(l) and is_char_node(r) and
+ (font(l) = font(r)) and
+ (pdf_font_stretch[font(l)] <> null_font))
+ then
+ return;
+ d := get_kern(pdf_font_stretch[font(l)], character(l), character(r));
+ kern_stretch := round_xn_over_d(d - width(p),
+ get_ef_code(font(l), character(l)), 1000);
+end;
+
+function kern_shrink(p: pointer): scaled;
+var l, r: pointer;
+ d: scaled;
+begin
+ kern_shrink := 0;
+ if (prev_char_p = null) or (link(prev_char_p) <> p) or (link(p) = null)
+ then
+ return;
+ l := prev_char_p;
+ r := link(p);
+ if type(l) = ligature_node then
+ l := lig_char(l);
+ if type(r) = ligature_node then
+ r := lig_char(r);
+ if not (is_char_node(l) and is_char_node(r) and
+ (font(l) = font(r)) and
+ (pdf_font_shrink[font(l)] <> null_font))
+ then
+ return;
+ d := get_kern(pdf_font_shrink[font(l)], character(l), character(r));
+ kern_shrink := round_xn_over_d(width(p) - d,
+ get_ef_code(font(l), character(l)), 1000);
+end;
+
+procedure do_subst_font(p: pointer; ex_ratio: integer);
+var f, k: internal_font_number;
+ r: pointer;
+ ef: integer;
+begin
+ if not is_char_node(p) and (type(p) = disc_node) then begin
+ r := pre_break(p);
+ while r <> null do begin
+ if is_char_node(r) or (type(r) = ligature_node) then
+ do_subst_font(r, ex_ratio);
+ r := link(r);
+ end;
+ r := post_break(p);
+ while r <> null do begin
+ if is_char_node(r) or (type(r) = ligature_node) then
+ do_subst_font(r, ex_ratio);
+ r := link(r);
+ end;
+ return;
+ end;
+ if is_char_node(p) then
+ r := p
+ else if type(p) = ligature_node then
+ r := lig_char(p)
+ else begin
+ {|short_display_n(p, 5);|}
+ pdf_error("font expansion", "invalid node type");
+ end;
+ f := font(r);
+ ef := get_ef_code(f, character(r));
+ if ef = 0 then
+ return;
+ if (pdf_font_stretch[f] <> null_font) and (ex_ratio > 0) then
+ k := expand_font(f, divide_scaled(ex_ratio*
+ pdf_font_expand_ratio[pdf_font_stretch[f]]*ef,
+ 1000000, 0))
+ else if (pdf_font_shrink[f] <> null_font) and (ex_ratio < 0) then
+ k := expand_font(f, -divide_scaled(ex_ratio*
+ pdf_font_expand_ratio[pdf_font_shrink[f]]*ef,
+ 1000000, 0))
+ else
+ k := f;
+ if k <> f then begin
+ font(r) := k;
+ if not is_char_node(p) then begin
+ r := lig_ptr(p);
+ while r <> null do begin
+ font(r) := k;
+ r := link(r);
+ end;
+ end;
+ end;
+end;
+
+function char_pw(p: pointer; side: small_number): scaled;
+var f: internal_font_number;
+ c: integer;
+begin
+ char_pw := 0;
+ if side = left_side then
+ last_leftmost_char := null
+ else
+ last_rightmost_char := null;
+ if p = null then
+ return;
+ if not is_char_node(p) then begin
+ if type(p) = ligature_node then
+ p := lig_char(p)
+ else
+ return;
+ end;
+ f := font(p);
+ if side = left_side then begin
+ c := get_lp_code(f, character(p));
+ last_leftmost_char := p;
+ end
+ else begin
+ c := get_rp_code(f, character(p));
+ last_rightmost_char := p;
+ end;
+ if c = 0 then
+ return;
+ char_pw :=
+ round_xn_over_d(quad(f), c, 1000);
+end;
+
+function new_margin_kern(w: scaled; p: pointer; side: small_number): pointer;
+var k: pointer;
+begin
+ k := get_node(margin_kern_node_size);
+ type(k) := margin_kern_node;
+ subtype(k) := side;
+ width(k) := w;
+ if p = null then
+ pdf_error("margin kerning", "invalid pointer to marginal char node");
+ fast_get_avail(margin_char(k));
+ character(margin_char(k)) := character(p);
+ font(margin_char(k)) := font(p);
+ new_margin_kern := k;
+end;
+
+function hpack(@!p:pointer;@!w:scaled;@!m:small_number):pointer;
+@z
+
+@x [649] - font expansion
+begin last_badness:=0; r:=get_node(box_node_size); type(r):=hlist_node;
+subtype(r):=min_quarterword; shift_amount(r):=0;
+q:=r+list_offset; link(q):=p;@/
+@y
+font_stretch: scaled;
+font_shrink: scaled;
+k: scaled;
+begin last_badness:=0; r:=get_node(box_node_size); type(r):=hlist_node;
+subtype(r):=min_quarterword; shift_amount(r):=0;
+q:=r+list_offset; link(q):=p;@/
+if m = cal_expand_ratio then begin
+ prev_char_p := null;
+ font_stretch := 0;
+ font_shrink := 0;
+ font_expand_ratio := 0;
+end;
+@z
+
+@x [649] - font expansion
+hpack:=r;
+@y
+if (m = cal_expand_ratio) and (font_expand_ratio <> 0) then begin
+ font_expand_ratio := fix_int(font_expand_ratio, -1000, 1000);
+ q := list_ptr(r);
+ free_node(r, box_node_size);
+ r := hpack(q, w, subst_ex_font);
+end;
+hpack:=r;
+@z
+
+@x [651] - font expansion
+ kern_node: x:=x+width(p);
+@y
+ margin_kern_node: begin
+ if m = cal_expand_ratio then begin
+ f := font(margin_char(p));
+ do_subst_font(margin_char(p), 1000);
+ if f <> font(margin_char(p)) then
+ font_stretch := font_stretch - width(p) -
+ char_pw(margin_char(p), subtype(p));
+ font(margin_char(p)) := f;
+ do_subst_font(margin_char(p), -1000);
+ if f <> font(margin_char(p)) then
+ font_shrink := font_shrink - width(p) -
+ char_pw(margin_char(p), subtype(p));
+ font(margin_char(p)) := f;
+ end
+ else if m = subst_ex_font then begin
+ do_subst_font(margin_char(p), font_expand_ratio);
+ width(p) := -char_pw(margin_char(p), subtype(p));
+ end;
+ x := x + width(p);
+ end;
+ kern_node: begin
+ if (m = cal_expand_ratio) and (subtype(p) = normal) then begin
+ k := kern_stretch(p);
+ if k <> 0 then begin
+ subtype(p) := substituted;
+ font_stretch := font_stretch + k;
+ end;
+ k := kern_shrink(p);
+ if k <> 0 then begin
+ subtype(p) := substituted;
+ font_shrink := font_shrink + k;
+ end;
+ end
+ else if (m = subst_ex_font) and (subtype(p) = substituted) then begin
+ if type(link(p)) = ligature_node then
+ width(p) := get_kern(font(prev_char_p),
+ character(prev_char_p),
+ character(lig_char(link(p))))
+ else
+ width(p) := get_kern(font(prev_char_p),
+ character(prev_char_p),
+ character(link(p)))
+ end;
+ x := x + width(p);
+ end;
+@z
+
+@x [651] - font expansion
+ ligature_node: @<Make node |p| look like a |char_node|
+ and |goto reswitch|@>;
+@y
+ ligature_node: begin
+ if m = subst_ex_font then
+ do_subst_font(p, font_expand_ratio);
+ @<Make node |p| look like a |char_node| and |goto reswitch|@>;
+ end;
+ disc_node:
+ if m = subst_ex_font then
+ do_subst_font(p, font_expand_ratio);
+@z
+
+@x [654] - font expansion
+begin f:=font(p); i:=char_info(f)(character(p)); hd:=height_depth(i);
+@y
+begin
+if m >= cal_expand_ratio then begin
+ prev_char_p := p;
+ case m of
+ cal_expand_ratio: begin
+ f := font(p);
+ add_char_stretch(font_stretch)(character(p));
+ add_char_shrink(font_shrink)(character(p));
+ end;
+ subst_ex_font:
+ do_subst_font(p, font_expand_ratio);
+ endcases;
+end;
+f:=font(p); i:=char_info(f)(character(p)); hd:=height_depth(i);
+@z
+
+@x [658] - font expansion
+@ @<Determine horizontal glue stretch setting...@>=
+begin @<Determine the stretch order@>;
+@y
+@ If |hpack| is called with |m=cal_expand_ratio| we calculate
+|font_expand_ratio| and return without checking for overfull or underfull box.
+
+@<Determine horizontal glue stretch setting...@>=
+begin @<Determine the stretch order@>;
+if (m = cal_expand_ratio) and (o = normal) and (font_stretch > 0) then begin
+ font_expand_ratio := divide_scaled(x, font_stretch, 3);
+ return;
+end;
+@z
+
+@x [664] - font expansion
+@ @<Determine horizontal glue shrink setting...@>=
+begin @<Determine the shrink order@>;
+@y
+@ @<Determine horizontal glue shrink setting...@>=
+begin @<Determine the shrink order@>;
+if (m = cal_expand_ratio) and (o = normal) and (font_shrink > 0) then begin
+ font_expand_ratio := divide_scaled(x, font_shrink, 3);
+ return;
+end;
+@z
+
+@x [822] - font expansion
+@d delta_node_size=7 {number of words in a delta node}
+@y
+@d delta_node_size=9 {number of words in a delta node}
+@z
+
+@x [823] - font expansion, margin kerning, avoiding overfull boxes
+@<Glo...@>=
+@!active_width:array[1..6] of scaled;
+ {distance from first active node to~|cur_p|}
+@!cur_active_width:array[1..6] of scaled; {distance from current active node}
+@!background:array[1..6] of scaled; {length of an ``empty'' line}
+@!break_width:array[1..6] of scaled; {length being computed after current break}
+@y
+@d do_seven_eight(#) == if pdf_adjust_spacing > 1 then begin #(7);#(8); end
+@d do_all_eight(#) == do_all_six(#); do_seven_eight(#)
+@d do_one_seven_eight(#) == #(1); do_seven_eight(#)
+
+@d total_font_stretch == cur_active_width[7]
+@d total_font_shrink == cur_active_width[8]
+
+@d save_active_width(#) == prev_active_width[#] := active_width[#]
+@d restore_active_width(#) == active_width[#] := prev_active_width[#]
+
+@<Glo...@>=
+@!active_width:array[1..8] of scaled;
+ {distance from first active node to~|cur_p|}
+@!cur_active_width:array[1..8] of scaled; {distance from current active node}
+@!background:array[1..8] of scaled; {length of an ``empty'' line}
+@!break_width:array[1..8] of scaled; {length being computed after current break}
+@#
+@!auto_breaking: boolean; {make |auto_breaking| accessible out of |line_break|}
+@!prev_p: pointer; {make |prev_p| accessible out of |line_break|}
+@!first_p: pointer; {to access the first node of the paragraph}
+@!prev_char_p: pointer; {pointer to the previous char of an implicit kern}
+@!next_char_p: pointer; {pointer to the next char of an implicit kern}
+@#
+@!try_prev_break: boolean; {force break at the previous legal breakpoint?}
+@!prev_legal: pointer; {the previous legal breakpoint}
+@!prev_prev_legal: pointer; {to save |prev_p| corresponding to |prev_legal|}
+@!prev_auto_breaking: boolean; {to save |auto_breaking| corresponding to |prev_legal|}
+@!prev_active_width: array[1..8] of scaled; {to save |active_width| corresponding to |prev_legal|}
+@!rejected_cur_p: pointer; {the last |cur_p| that has been rejected}
+@!before_rejected_cur_p: boolean; {|cur_p| is still before |rejected_cur_p|?}
+@#
+@!max_stretch_ratio: integer; {maximal stretch ratio of expanded fonts}
+@!max_shrink_ratio: integer; {maximal shrink ratio of expanded fonts}
+@!cur_font_step: integer; {the current step of expanded fonts}
+@z
+
+@x [827] - font expansion
+background[6]:=shrink(q)+shrink(r);
+@y
+background[6]:=shrink(q)+shrink(r);
+if pdf_adjust_spacing > 1 then begin
+ background[7] := 0;
+ background[8] := 0;
+ max_stretch_ratio := -1;
+ max_shrink_ratio := -1;
+ cur_font_step := -1;
+ prev_char_p := null;
+end;
+@z
+
+@x [829] - margin kerning
+@<Declare subprocedures for |line_break|@>=
+procedure try_break(@!pi:integer;@!break_type:small_number);
+@y
+@d cp_skipable(#) == {skipable nodes at the margins during character protrusion}
+(
+ not is_char_node(#) and
+ (
+ (type(#) = ins_node)
+ or (type(#) = mark_node)
+ or (type(#) = adjust_node)
+ or (type(#) = penalty_node)
+ or ((type(#) = whatsit_node) and
+ (subtype(#) <> pdf_refximage_node) and
+ (subtype(#) <> pdf_refxform_node)) {reference to an image or XObject form}
+ or ((type(#) = disc_node) and
+ (pre_break(#) = null) and
+ (post_break(#) = null) and
+ (replace_count(#) = 0)) {an empty |disc_node|}
+ or ((type(#) = math_node) and (width(#) = 0))
+ or ((type(#) = kern_node) and
+ ((width(#) = 0) or (subtype(#) = normal)))
+ or ((type(#) = glue_node) and (glue_ptr(#) = zero_glue))
+ or ((type(#) = hlist_node) and (width(#) = 0) and (height(#) = 0) and
+ (depth(#) = 0) and (list_ptr(#) = null))
+ )
+)
+
+
+@<Declare subprocedures for |line_break|@>=
+procedure push_node(p: pointer);
+begin
+ if hlist_stack_level > max_hlist_stack then
+ pdf_error("push_node", "stack overflow");
+ hlist_stack[hlist_stack_level] := p;
+ hlist_stack_level := hlist_stack_level + 1;
+end;
+
+function pop_node: pointer;
+begin
+ hlist_stack_level := hlist_stack_level - 1;
+ if hlist_stack_level < 0 then {would point to some bug}
+ pdf_error("pop_node", "stack underflow (internal error)");
+ pop_node := hlist_stack[hlist_stack_level];
+end;
+
+function find_protchar_left(l: pointer; d: boolean): pointer;
+{searches left to right from list head |l|, returns 1st non-skipable item}
+var t: pointer;
+ run: boolean;
+begin
+ if (link(l) <> null) and (type(l) = hlist_node) and (width(l) = 0)
+ and (height(l) = 0) and (depth(l) = 0) and (list_ptr(l) = null) then
+ l := link(l) {for paragraph start with \.{\\parindent = 0pt}}
+ else if d then
+ while (link(l) <> null) and (not (is_char_node(l) or non_discardable(l))) do
+ l := link(l); {std.\ discardables at line break, \TeX book, p 95}
+ hlist_stack_level := 0;
+ run := true;
+ repeat
+ t := l;
+ while run and (type(l) = hlist_node) and (list_ptr(l) <> null) do begin
+ push_node(l);
+ l := list_ptr(l);
+ end;
+ while run and cp_skipable(l) do begin
+ while (link(l) = null) and (hlist_stack_level > 0) do begin
+ l := pop_node; {don't visit this node again}
+ end;
+ if link(l) <> null then
+ l := link(l)
+ else if hlist_stack_level = 0 then run := false
+ end;
+ until t = l;
+ find_protchar_left := l;
+end;
+
+function find_protchar_right(l, r: pointer): pointer;
+{searches right to left from list tail |r| to head |l|, returns 1st non-skipable item}
+var t: pointer;
+ run: boolean;
+begin
+ find_protchar_right := null;
+ if r = null then return;
+ hlist_stack_level := 0;
+ run := true;
+ repeat
+ t := r;
+ while run and (type(r) = hlist_node) and (list_ptr(r) <> null) do begin
+ push_node(l);
+ push_node(r);
+ l := list_ptr(r);
+ r := l;
+ while link(r) <> null do
+ r := link(r);
+ end;
+ while run and cp_skipable(r) do begin
+ while (r = l) and (hlist_stack_level > 0) do begin
+ r := pop_node; {don't visit this node again}
+ l := pop_node;
+ end;
+ if (r <> l) and (r <> null) then
+ r := prev_rightmost(l, r)
+ else if (r = l) and (hlist_stack_level = 0) then run := false
+ end;
+ until t = r;
+ find_protchar_right := r;
+end;
+
+function total_pw(q, p: pointer): scaled;
+{returns the total width of character protrusion of a line;
+|cur_break(break_node(q))| and |p| is the leftmost resp. rightmost node in the
+horizontal list representing the actual line}
+var l, r, s: pointer;
+ n: integer;
+begin
+ if break_node(q) = null then
+ l := first_p
+ else
+ l := cur_break(break_node(q));
+ r := prev_rightmost(prev_p, p); {get |link(r)=p|}
+ {let's look at the right margin first}
+ {|
+ short_display_n(r, 2);
+ print("&");
+ short_display_n(p, 2);
+ print_ln;
+ |}
+ if (p <> null) and (type(p) = disc_node) and (pre_break(p) <> null) then
+ {a |disc_node| with non-empty |pre_break|, protrude the last char of |pre_break|}
+ begin
+ r := pre_break(p);
+ while link(r) <> null do
+ r := link(r);
+ end else r := find_protchar_right(l, r);
+ {now the left margin}
+ {|
+ short_display_n(l, 2);
+ print_ln;
+ breadth_max := 10;
+ depth_threshold := 2;
+ show_node_list(l);
+ print_ln;
+ |}
+ if (l <> null) and (type(l) = disc_node) then begin
+ if post_break(l) <> null then begin
+ l := post_break(l); {protrude the first char}
+ goto done;
+ end else {discard |replace_count(l)| nodes}
+ begin
+ n := replace_count(l);
+ l := link(l);
+ while n > 0 do begin
+ if link(l) <> null then
+ l := link(l);
+ decr(n);
+ end;
+ end;
+ end;
+ l := find_protchar_left(l, true);
+done:
+ total_pw := left_pw(l) + right_pw(r);
+end;
+
+procedure try_break(@!pi:integer;@!break_type:small_number);
+@z
+
+@x
+var r:pointer; {runs through the active list}
+@y
+var r:pointer; {runs through the active list}
+@!margin_kern_stretch: scaled;
+@!margin_kern_shrink: scaled;
+@!lp, rp, cp: pointer;
+@z
+
+
+@x [829] - font expansion
+do_all_six(copy_to_cur_active);
+@y
+do_all_eight(copy_to_cur_active);
+@z
+
+@x [832] - font expansion
+ begin do_all_six(update_width);
+@y
+ begin do_all_eight(update_width);
+@z
+
+@x [837] - font expansion
+begin no_break_yet:=false; do_all_six(set_break_width_to_background);
+@y
+begin no_break_yet:=false; do_all_eight(set_break_width_to_background);
+@z
+
+@x [839] - font expansion
+@<Glob...@>=
+@!disc_width:scaled; {the length of discretionary material preceding a break}
+@y
+@d reset_disc_width(#) == disc_width[#] := 0
+
+@d add_disc_width_to_break_width(#) ==
+ break_width[#] := break_width[#] + disc_width[#]
+
+@d add_disc_width_to_active_width(#) ==
+ active_width[#] := active_width[#] + disc_width[#]
+
+@d sub_disc_width_from_active_width(#) ==
+ active_width[#] := active_width[#] - disc_width[#]
+
+@d add_char_stretch_end(#) == char_stretch(f, #)
+@d add_char_stretch(#) == # := # + add_char_stretch_end
+
+@d add_char_shrink_end(#) == char_shrink(f, #)
+@d add_char_shrink(#) == # := # + add_char_shrink_end
+
+@d sub_char_stretch_end(#) == char_stretch(f, #)
+@d sub_char_stretch(#) == # := # - sub_char_stretch_end
+
+@d sub_char_shrink_end(#) == char_shrink(f, #)
+@d sub_char_shrink(#) == # := # - sub_char_shrink_end
+
+@d add_kern_stretch_end(#) == kern_stretch(#)
+@d add_kern_stretch(#) == # := # + add_kern_stretch_end
+
+@d add_kern_shrink_end(#) == kern_shrink(#)
+@d add_kern_shrink(#) == # := # + add_kern_shrink_end
+
+@d sub_kern_stretch_end(#) == kern_stretch(#)
+@d sub_kern_stretch(#) == # := # - sub_kern_stretch_end
+
+@d sub_kern_shrink_end(#) == kern_shrink(#)
+@d sub_kern_shrink(#) == # := # - sub_kern_shrink_end
+
+@<Glob...@>=
+@!disc_width: array[1..8] of scaled; {the length of discretionary material preceding a break}
+@z
+
+@x [840] - font expansion
+break_width[1]:=break_width[1]+disc_width;
+@y
+do_one_seven_eight(add_disc_width_to_break_width);
+@z
+
+@x [841] - font expansion
+ break_width[1]:=break_width[1]-char_width(f)(char_info(f)(character(v)));
+@y
+ break_width[1]:=break_width[1]-char_width(f)(char_info(f)(character(v)));
+ if (pdf_adjust_spacing > 1) and check_expand_pars(f) then begin
+ prev_char_p := v;
+ sub_char_stretch(break_width[7])(character(v));
+ sub_char_shrink(break_width[8])(character(v));
+ end;
+@z
+
+@x [841] - font expansion
+ break_width[1]:=@|break_width[1]-
+ char_width(f)(char_info(f)(character(lig_char(v))));
+@y
+ break_width[1]:=@|break_width[1]-
+ char_width(f)(char_info(f)(character(lig_char(v))));
+ if (pdf_adjust_spacing > 1) and check_expand_pars(f) then begin
+ prev_char_p := v;
+ sub_char_stretch(break_width[7])(character(lig_char(v)));
+ sub_char_shrink(break_width[8])(character(lig_char(v)));
+ end;
+@z
+
+@x [841] - font expansion
+ hlist_node,vlist_node,rule_node,kern_node:
+ break_width[1]:=break_width[1]-width(v);
+@y
+ hlist_node,vlist_node,rule_node,kern_node: begin
+ break_width[1]:=break_width[1]-width(v);
+ if (type(v) = kern_node) and
+ (pdf_adjust_spacing > 1) and (subtype(v) = normal)
+ then begin
+ sub_kern_stretch(break_width[7])(v);
+ sub_kern_shrink(break_width[8])(v);
+ end;
+ end;
+@z
+
+@x [842] - font expansion
+ break_width[1]:=@|break_width[1]+char_width(f)(char_info(f)(character(s)));
+@y
+ break_width[1]:=@|break_width[1]+char_width(f)(char_info(f)(character(s)));
+ if (pdf_adjust_spacing > 1) and check_expand_pars(f) then begin
+ prev_char_p := s;
+ add_char_stretch(break_width[7])(character(s));
+ add_char_shrink(break_width[8])(character(s));
+ end;
+@z
+
+@x [842] - font expansion
+ break_width[1]:=break_width[1]+
+ char_width(f)(char_info(f)(character(lig_char(s))));
+@y
+ break_width[1]:=break_width[1]+
+ char_width(f)(char_info(f)(character(lig_char(s))));
+ if (pdf_adjust_spacing > 1) and check_expand_pars(f) then begin
+ prev_char_p := s;
+ add_char_stretch(break_width[7])(character(lig_char(s)));
+ add_char_shrink(break_width[8])(character(lig_char(s)));
+ end;
+@z
+
+@x [842] - font expansion
+ hlist_node,vlist_node,rule_node,kern_node:
+ break_width[1]:=break_width[1]+width(s);
+@y
+ hlist_node,vlist_node,rule_node,kern_node: begin
+ break_width[1]:=break_width[1]+width(s);
+ if (type(s) = kern_node) and
+ (pdf_adjust_spacing > 1) and (subtype(s) = normal)
+ then begin
+ add_kern_stretch(break_width[7])(s);
+ add_kern_shrink(break_width[8])(s);
+ end;
+ end;
+@z
+
+@x [843] - font expansion
+ begin do_all_six(convert_to_break_width);
+@y
+ begin do_all_eight(convert_to_break_width);
+@z
+
+@x [843] - font expansion
+ begin do_all_six(store_break_width);
+@y
+ begin do_all_eight(store_break_width);
+@z
+
+@x [843] - font expansion
+ do_all_six(new_delta_to_break_width);
+@y
+ do_all_eight(new_delta_to_break_width);
+@z
+
+@x [844] - font expansion
+ do_all_six(new_delta_from_break_width);
+@y
+ do_all_eight(new_delta_from_break_width);
+@z
+
+@x [851] - font expansion, margin kerning
+shortfall:=line_width-cur_active_width[1]; {we're this much too short}
+@y
+shortfall:=line_width-cur_active_width[1]; {we're this much too short}
+
+{|
+if pdf_output > 2 then begin
+print_ln;
+if (r <> null) and (break_node(r) <> null) then
+ short_display_n(cur_break(break_node(r)), 5);
+print_ln;
+short_display_n(cur_p, 5);
+print_ln;
+end;
+|}
+
+if pdf_protrude_chars > 1 then
+ shortfall := shortfall + total_pw(r, cur_p);
+if (pdf_adjust_spacing > 1) and (shortfall <> 0) then begin
+ margin_kern_stretch := 0;
+ margin_kern_shrink := 0;
+ if pdf_protrude_chars > 1 then
+ @<Calculate variations of marginal kerns@>;
+ if (shortfall > 0) and ((total_font_stretch + margin_kern_stretch) > 0)
+ then begin
+ if (total_font_stretch + margin_kern_stretch) > shortfall then
+ shortfall := ((total_font_stretch + margin_kern_stretch) div
+ (max_stretch_ratio div cur_font_step)) div 2
+ else
+ shortfall := shortfall - (total_font_stretch + margin_kern_stretch);
+ end
+ else if (shortfall < 0) and ((total_font_shrink + margin_kern_shrink) > 0)
+ then begin
+ if (total_font_shrink + margin_kern_shrink) > -shortfall then
+ shortfall := -((total_font_shrink + margin_kern_shrink) div
+ (max_shrink_ratio div cur_font_step)) div 2
+ else
+ shortfall := shortfall + (total_font_shrink + margin_kern_shrink);
+ end;
+end;
+@z
+
+@x [860] - font expansion
+ begin do_all_six(downdate_width);
+@y
+ begin do_all_eight(downdate_width);
+@z
+
+@x [860] - font expansion
+ begin do_all_six(update_width);
+ do_all_six(combine_two_deltas);
+@y
+ begin do_all_eight(update_width);
+ do_all_eight(combine_two_deltas);
+@z
+
+@x [861] - font expansion
+ begin do_all_six(update_active);
+ do_all_six(copy_to_cur_active);
+@y
+ begin do_all_eight(update_active);
+ do_all_eight(copy_to_cur_active);
+@z
+
+@x [862] - margin kerning, avoiding overfull boxes
+@!auto_breaking:boolean; {is node |cur_p| outside a formula?}
+@!prev_p:pointer; {helps to determine when glue nodes are breakpoints}
+@y
+@z
+
+@x [863] - margin kerning, avoiding overfull boxes
+ while (cur_p<>null)and(link(active)<>last_active) do
+@y
+ prev_char_p := null;
+ prev_legal := null;
+ rejected_cur_p := null;
+ try_prev_break := false;
+ before_rejected_cur_p := false;
+ first_p := cur_p; {to access the first node of paragraph as the first active
+ node has |break_node=null|}
+ while (cur_p<>null)and(link(active)<>last_active) do
+@z
+
+@x [864] - font expansion
+do_all_six(store_background);@/
+@y
+do_all_eight(store_background);@/
+@z
+
+@x [666] - font expansion
+ else act_width:=act_width+width(cur_p);
+@y
+ else begin
+ act_width:=act_width+width(cur_p);
+ if (pdf_adjust_spacing > 1) and (subtype(cur_p) = normal) then begin
+ add_kern_stretch(active_width[7])(cur_p);
+ add_kern_shrink(active_width[8])(cur_p);
+ end;
+ end;
+@z
+
+@x [866] - font expansion
+ act_width:=act_width+char_width(f)(char_info(f)(character(lig_char(cur_p))));
+@y
+ act_width:=act_width+char_width(f)(char_info(f)(character(lig_char(cur_p))));
+ if (pdf_adjust_spacing > 1) and check_expand_pars(f) then begin
+ prev_char_p := cur_p;
+ add_char_stretch(active_width[7])(character(lig_char(cur_p)));
+ add_char_shrink(active_width[8])(character(lig_char(cur_p)));
+ end;
+@z
+
+@x [867] - font expansion
+act_width:=act_width+char_width(f)(char_info(f)(character(cur_p)));
+@y
+act_width:=act_width+char_width(f)(char_info(f)(character(cur_p)));
+if (pdf_adjust_spacing > 1) and check_expand_pars(f) then begin
+ prev_char_p := cur_p;
+ add_char_stretch(active_width[7])(character(cur_p));
+ add_char_shrink(active_width[8])(character(cur_p));
+end;
+@z
+
+@x [869] - font expansion
+begin s:=pre_break(cur_p); disc_width:=0;
+@y
+begin s:=pre_break(cur_p);
+do_one_seven_eight(reset_disc_width);
+@z
+
+@x [869] - font expansion
+ act_width:=act_width+disc_width;
+ try_break(hyphen_penalty,hyphenated);
+ act_width:=act_width-disc_width;
+@y
+ do_one_seven_eight(add_disc_width_to_active_width);
+ try_break(hyphen_penalty,hyphenated);
+ do_one_seven_eight(sub_disc_width_from_active_width);
+@z
+
+@x [870] - font expansion
+ disc_width:=disc_width+char_width(f)(char_info(f)(character(s)));
+@y
+ disc_width[1]:=disc_width[1]+char_width(f)(char_info(f)(character(s)));
+ if (pdf_adjust_spacing > 1) and check_expand_pars(f) then begin
+ prev_char_p := s;
+ add_char_stretch(disc_width[7])(character(s));
+ add_char_shrink(disc_width[8])(character(s));
+ end;
+@z
+
+@x [870] - font expansion
+ disc_width:=disc_width+
+ char_width(f)(char_info(f)(character(lig_char(s))));
+@y
+ disc_width[1]:=disc_width[1]+
+ char_width(f)(char_info(f)(character(lig_char(s))));
+ if (pdf_adjust_spacing > 1) and check_expand_pars(f) then begin
+ prev_char_p := s;
+ add_char_stretch(disc_width[7])(character(lig_char(s)));
+ add_char_shrink(disc_width[8])(character(lig_char(s)));
+ end;
+@z
+
+@x [870] - font expansion
+ hlist_node,vlist_node,rule_node,kern_node:
+ disc_width:=disc_width+width(s);
+@y
+ hlist_node,vlist_node,rule_node,kern_node: begin
+ disc_width[1]:=disc_width[1]+width(s);
+ if (type(s) = kern_node) and
+ (pdf_adjust_spacing > 1) and (subtype(s) = normal)
+ then begin
+ add_kern_stretch(disc_width[7])(s);
+ add_kern_shrink(disc_width[8])(s);
+ end;
+ end;
+@z
+
+@x [871] - font expansion
+ act_width:=act_width+char_width(f)(char_info(f)(character(s)));
+@y
+ act_width:=act_width+char_width(f)(char_info(f)(character(s)));
+ if (pdf_adjust_spacing > 1) and check_expand_pars(f) then begin
+ prev_char_p := s;
+ add_char_stretch(active_width[7])(character(s));
+ add_char_shrink(active_width[8])(character(s));
+ end;
+@z
+
+@x [871] - font expansion
+ act_width:=act_width+
+ char_width(f)(char_info(f)(character(lig_char(s))));
+@y
+ act_width:=act_width+
+ char_width(f)(char_info(f)(character(lig_char(s))));
+ if (pdf_adjust_spacing > 1) and check_expand_pars(f) then begin
+ prev_char_p := s;
+ add_char_stretch(active_width[7])(character(lig_char(s)));
+ add_char_shrink(active_width[8])(character(lig_char(s)));
+ end;
+@z
+
+@x [871] - font expansion
+ hlist_node,vlist_node,rule_node,kern_node:
+ act_width:=act_width+width(s);
+@y
+ hlist_node,vlist_node,rule_node,kern_node: begin
+ act_width:=act_width+width(s);
+ if (type(s) = kern_node) and
+ (pdf_adjust_spacing > 1) and (subtype(s) = normal)
+ then begin
+ add_kern_stretch(active_width[7])(s);
+ add_kern_shrink(active_width[8])(s);
+ end;
+ end;
+@z
+
+@x [877] - margin kerning
+var q,@!r,@!s:pointer; {temporary registers for list manipulation}
+@y
+var q,@!r,@!s:pointer; {temporary registers for list manipulation}
+ p, k: pointer;
+ w: scaled;
+ glue_break: boolean; {was a break at glue?}
+ ptmp: pointer;
+@z
+
+@x [881] - margin kerning
+q:=cur_break(cur_p); disc_break:=false; post_disc_break:=false;
+@y
+q:=cur_break(cur_p); disc_break:=false; post_disc_break:=false;
+glue_break := false;
+@z
+
+@x [881] - margin kerning
+ subtype(q):=right_skip_code+1; add_glue_ref(right_skip);
+ goto done;
+@y
+ subtype(q):=right_skip_code+1; add_glue_ref(right_skip);
+ glue_break := true;
+ goto done;
+@z
+
+@x [881] - margin kerning
+@<Put the \(r)\.{\\rightskip} glue after node |q|@>;
+done:
+@y
+done:
+
+{at this point |q| is the rightmost breakpoint; the only exception is the case
+of a discretionary break with non-empty |pre_break|, then |q| has been changed
+to the last node of the |pre_break| list}
+
+if pdf_protrude_chars > 0 then begin
+ if disc_break and (is_char_node(q) or (type(q) <> disc_node))
+ {|q| has been reset to the last node of |pre_break|}
+ then begin
+ p := q;
+ ptmp := p;
+ end else begin
+ p := prev_rightmost(temp_head, q); {get |link(p) = q|}
+ ptmp := p;
+ p := find_protchar_right(temp_head, p);
+ end;
+ {|
+ short_display_n(p, 1);
+ print_ln;
+ |}
+ w := right_pw(p);
+ if w <> 0 then {we have found a marginal kern, append it after |ptmp|}
+ begin
+ k := new_margin_kern(-w, last_rightmost_char, right_side);
+ link(k) := link(ptmp);
+ link(ptmp) := k;
+ if (ptmp = q) then
+ q := link(q);
+ end;
+end;
+
+{if |q| was not a breakpoint at glue and has been reset to |rightskip| then
+ we append |rightskip| after |q| now}
+if not glue_break then begin
+ @<Put the \(r)\.{\\rightskip} glue after node |q|@>;
+end;
+@z
+
+@x [887] - margin kerning
+if left_skip<>zero_glue then
+@y
+{at this point |q| is the leftmost node; all discardable nodes have been discarded}
+if pdf_protrude_chars > 0 then begin
+ p := q;
+ p := find_protchar_left(p, false); {no more discardables}
+ w := left_pw(p);
+ if w <> 0 then begin
+ k := new_margin_kern(-w, last_leftmost_char, left_side);
+ link(k) := q;
+ q := k;
+ end;
+end;
+if left_skip<>zero_glue then
+@z
+
+@x [889] - font expansion, pre vadjust
+just_box:=hpack(q,cur_width,exactly);
+@y
+if pdf_adjust_spacing > 0 then
+ just_box := hpack(q, cur_width, cal_expand_ratio)
+else
+ just_box := hpack(q, cur_width, exactly);
+@z
+
+@x [1110] - margin kerning
+var p:pointer; {the box}
+@y
+var p:pointer; {the box}
+ r: pointer; {to remove marginal kern nodes}
+@z
+
+@x [1110] - margin kerning
+while link(tail)<>null do tail:=link(tail);
+@y
+while link(tail) <> null do begin
+ r := link(tail);
+ if not is_char_node(r) and (type(r) = margin_kern_node) then begin
+ link(tail) := link(r);
+ free_avail(margin_char(r));
+ free_node(r, margin_kern_node_size);
+ end;
+ tail:=link(tail);
+end;
+@z
+
+@x [1147] - margin kerning
+ligature_node:@<Make node |p| look like a |char_node|...@>;
+@y
+ligature_node:@<Make node |p| look like a |char_node|...@>;
+margin_kern_node: d:=width(p);
+@z
+
+@x [1253] - font expansion
+assign_font_int: begin n:=cur_chr; scan_font_ident; f:=cur_val;
+ scan_optional_equals; scan_int;
+ if n=0 then hyphen_char[f]:=cur_val@+else skew_char[f]:=cur_val;
+ end;
+@y
+assign_font_int: begin n:=cur_chr; scan_font_ident; f:=cur_val;
+ if n < lp_code_base then begin
+ scan_optional_equals; scan_int;
+ if n=0 then hyphen_char[f]:=cur_val@+else skew_char[f]:=cur_val;
+ end
+ else begin
+ scan_char_num; p := cur_val;
+ scan_optional_equals; scan_int;
+ case n of
+ lp_code_base: set_lp_code(f, p, cur_val);
+ rp_code_base: set_rp_code(f, p, cur_val);
+ ef_code_base: set_ef_code(f, p, cur_val);
+ end;
+ end;
+end;
+@z
+
+@x [1254] - font expansion
+primitive("skewchar",assign_font_int,1);
+@!@:skew_char_}{\.{\\skewchar} primitive@>
+@y
+primitive("skewchar",assign_font_int,1);
+@!@:skew_char_}{\.{\\skewchar} primitive@>
+primitive("lpcode",assign_font_int,lp_code_base);
+@!@:lp_code_}{\.{\\lpcode} primitive@>
+primitive("rpcode",assign_font_int,rp_code_base);
+@!@:rp_code_}{\.{\\rpcode} primitive@>
+primitive("efcode",assign_font_int,ef_code_base);
+@!@:ef_code_}{\.{\\efcode} primitive@>
+@z
+
+@x [1255] - font expansion
+assign_font_int: if chr_code=0 then print_esc("hyphenchar")
+ else print_esc("skewchar");
+@y
+assign_font_int: case chr_code of
+0: print_esc("hyphenchar");
+1: print_esc("skewchar");
+lp_code_base: print_esc("lpcode");
+rp_code_base: print_esc("rpcode");
+ef_code_base: print_esc("efcode");
+endcases;
+@z
+
+@x [1344]
+@d pdftex_last_extension_code == pdftex_first_extension_code + 27
+@y
+@d pdf_font_expand_code == pdftex_first_extension_code + 28
+@d pdftex_last_extension_code == pdftex_first_extension_code + 28
+@z
+
+@x [1344]
+primitive("setlanguage",extension,set_language_code);@/
+@!@:set_language_}{\.{\\setlanguage} primitive@>
+@y
+primitive("setlanguage",extension,set_language_code);@/
+@!@:set_language_}{\.{\\setlanguage} primitive@>
+primitive("pdffontexpand",extension,pdf_font_expand_code);@/
+@!@:pdf_font_expand_}{\.{\\pdffontexpand} primitive@>
+@z
+
+@x [1346]
+ immediate_code:print_esc("immediate");
+ set_language_code:print_esc("setlanguage");
+@y
+ immediate_code:print_esc("immediate");
+ set_language_code:print_esc("setlanguage");
+ pdf_font_expand_code: print_esc("pdffontexpand");
+@z
+
+@x [1348]
+set_language_code:@<Implement \.{\\setlanguage}@>;
+@y
+set_language_code:@<Implement \.{\\setlanguage}@>;
+pdf_font_expand_code: @<Implement \.{\\pdffontexpand}@>;
+@z
+
+@x [1354]
+@<Implement \.{\\special}@>=
+begin new_whatsit(special_node,write_node_size); write_stream(tail):=null;
+p:=scan_toks(false,true); write_tokens(tail):=def_ref;
+end
+@y
+@<Implement \.{\\special}@>=
+begin new_whatsit(special_node,write_node_size); write_stream(tail):=null;
+p:=scan_toks(false,true); write_tokens(tail):=def_ref;
+end
+
+@ @<Implement \.{\\pdffontexpand}@>=
+ read_expand_font
+@z
+
+@x [15??]
+@<Declare procedures that need to be declared forward for pdftex@>=
+@y
+@<Declare procedures that need to be declared forward for pdftex@>=
+function prev_rightmost(s, e: pointer): pointer;
+{finds the node preceding the rightmost node |e|; |s| is some node
+before |e|}
+var p: pointer;
+begin
+ prev_rightmost := null;
+ p := s;
+ if p = null then
+ return;
+ while link(p) <> e do begin
+ p := link(p);
+ if p = null then
+ return;
+ end;
+ prev_rightmost := p;
+end;
+@z
+
diff --git a/Build/source/texk/web2c/pdftexdir/image.h b/Build/source/texk/web2c/pdftexdir/image.h
new file mode 100644
index 00000000000..2f9dcc94171
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/image.h
@@ -0,0 +1,104 @@
+/*
+Copyright (c) 1996-2002 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX 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.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/image.h#10 $
+*/
+
+#include <png.h>
+
+/* JPG_IMAGE_INFO is main structure for interchange of image data */
+
+#define JPG_UINT16 unsigned int
+#define JPG_UINT32 unsigned long
+#define JPG_UINT8 unsigned char
+
+typedef struct {
+ int color_space; /* used color space. See JPG_ constants */
+ JPG_UINT8 bits_per_component; /* bits per component */
+ JPG_UINT32 length; /* length of file/data */
+ FILE *file; /* jpg file */
+} JPG_IMAGE_INFO;
+
+typedef struct {
+ png_structp png_ptr;
+ png_infop info_ptr;
+} png_image_struct;
+
+typedef struct {
+ integer orig_x;
+ integer orig_y;
+ integer selected_page;
+ integer page_box;
+ integer always_use_pdfpagebox;
+ void *doc;
+} pdf_image_struct;
+
+typedef struct {
+ char *image_name;
+ int image_type;
+ int color_type;
+ integer width;
+ integer height;
+ integer x_res;
+ integer y_res;
+ integer num_pages;
+ integer colorspace_ref;
+ union {
+ pdf_image_struct *pdf;
+ png_image_struct png;
+ JPG_IMAGE_INFO *jpg;
+ } image_struct;
+} image_entry;
+
+extern image_entry *image_ptr, *image_array;
+extern integer image_max;
+
+#define IMAGE_TYPE_NONE 0
+#define IMAGE_TYPE_PDF 1
+#define IMAGE_TYPE_PNG 2
+#define IMAGE_TYPE_JPG 3
+#define IMAGE_TYPE_TIF 4
+
+#define IMAGE_COLOR_B 1
+#define IMAGE_COLOR_C 2
+#define IMAGE_COLOR_I 4
+
+#define img_ptr(N) (image_array + (N))
+#define img_name(N) (img_ptr(N)->image_name)
+#define img_type(N) (img_ptr(N)->image_type)
+#define img_color(N) (img_ptr(N)->color_type)
+#define img_colorspace_ref(N) (img_ptr(N)->colorspace_ref)
+#define img_pages(N) (img_ptr(N)->num_pages)
+#define img_width(N) (img_ptr(N)->width)
+#define img_height(N) (img_ptr(N)->height)
+#define img_xres(N) (img_ptr(N)->x_res)
+#define img_yres(N) (img_ptr(N)->y_res)
+#define png_ptr(N) (img_ptr(N)->image_struct.png.png_ptr)
+#define png_info(N) (img_ptr(N)->image_struct.png.info_ptr)
+#define pdf_ptr(N) (img_ptr(N)->image_struct.pdf)
+#define jpg_ptr(N) (img_ptr(N)->image_struct.jpg)
+#define tif_ptr(N) (img_ptr(N)->image_struct.tif)
+
+extern integer read_pdf_info(char*, char*, integer, integer, integer, integer);
+extern void write_epdf(void);
+extern void epdf_delete(void);
+extern void read_png_info(integer);
+extern void write_png(integer);
+extern void read_jpg_info(integer);
+extern void write_jpg(integer);
diff --git a/Build/source/texk/web2c/pdftexdir/macnames.c b/Build/source/texk/web2c/pdftexdir/macnames.c
new file mode 100644
index 00000000000..7f2005e8e20
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/macnames.c
@@ -0,0 +1,312 @@
+/*
+Copyright (c) 1996-2002 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX 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.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/macnames.c#5 $
+*/
+
+const char notdef[] = ".notdef";
+
+const char *mac_glyph_names[] = {
+/* 0x00 */
+ notdef,
+ ".null",
+ "CR",
+ "space",
+ "exclam",
+ "quotedbl",
+ "numbersign",
+ "dollar",
+ "percent",
+ "ampersand",
+ "quotesingle",
+ "parenleft",
+ "parenright",
+ "asterisk",
+ "plus",
+ "comma",
+/* 0x10 */
+ "hyphen",
+ "period",
+ "slash",
+ "zero",
+ "one",
+ "two",
+ "three",
+ "four",
+ "five",
+ "six",
+ "seven",
+ "eight",
+ "nine",
+ "colon",
+ "semicolon",
+ "less",
+/* 0x20 */
+ "equal",
+ "greater",
+ "question",
+ "at",
+ "A",
+ "B",
+ "C",
+ "D",
+ "E",
+ "F",
+ "G",
+ "H",
+ "I",
+ "J",
+ "K",
+ "L",
+/* 0x30 */
+ "M",
+ "N",
+ "O",
+ "P",
+ "Q",
+ "R",
+ "S",
+ "T",
+ "U",
+ "V",
+ "W",
+ "X",
+ "Y",
+ "Z",
+ "bracketleft",
+ "backslash",
+/* 0x40 */
+ "bracketright",
+ "asciicircum",
+ "underscore",
+ "grave",
+ "a",
+ "b",
+ "c",
+ "d",
+ "e",
+ "f",
+ "g",
+ "h",
+ "i",
+ "j",
+ "k",
+ "l",
+/* 0x50 */
+ "m",
+ "n",
+ "o",
+ "p",
+ "q",
+ "r",
+ "s",
+ "t",
+ "u",
+ "v",
+ "w",
+ "x",
+ "y",
+ "z",
+ "braceleft",
+ "bar",
+/* 0x60 */
+ "braceright",
+ "asciitilde",
+ "Adieresis",
+ "Aring",
+ "Ccedilla",
+ "Eacute",
+ "Ntilde",
+ "Odieresis",
+ "Udieresis",
+ "aacute",
+ "agrave",
+ "acircumflex",
+ "adieresis",
+ "atilde",
+ "aring",
+ "ccedilla",
+/* 0x70 */
+ "eacute",
+ "egrave",
+ "ecircumflex",
+ "edieresis",
+ "iacute",
+ "igrave",
+ "icircumflex",
+ "idieresis",
+ "ntilde",
+ "oacute",
+ "ograve",
+ "ocircumflex",
+ "odieresis",
+ "otilde",
+ "uacute",
+ "ugrave",
+/* 0x80 */
+ "ucircumflex",
+ "udieresis",
+ "dagger",
+ "degree",
+ "cent",
+ "sterling",
+ "section",
+ "bullet",
+ "paragraph",
+ "germandbls",
+ "registered",
+ "copyright",
+ "trademark",
+ "acute",
+ "dieresis",
+ "notequal",
+/* 0x90 */
+ "AE",
+ "Oslash",
+ "infinity",
+ "plusminus",
+ "lessequal",
+ "greaterequal",
+ "yen",
+ "mu",
+ "partialdiff",
+ "Sigma",
+ "Pi",
+ "pi",
+ "integral",
+ "ordfeminine",
+ "ordmasculine",
+ "Omega",
+/* 0xa0 */
+ "ae",
+ "oslash",
+ "questiondown",
+ "exclamdown",
+ "logicalnot",
+ "radical",
+ "florin",
+ "approxequal",
+ "Delta",
+ "guillemotleft",
+ "guillemotright",
+ "ellipsis",
+ "nbspace",
+ "Agrave",
+ "Atilde",
+ "Otilde",
+/* 0xb0 */
+ "OE",
+ "oe",
+ "endash",
+ "emdash",
+ "quotedblleft",
+ "quotedblright",
+ "quoteleft",
+ "quoteright",
+ "divide",
+ "lozenge",
+ "ydieresis",
+ "Ydieresis",
+ "fraction",
+ "currency",
+ "guilsinglleft",
+ "guilsinglright",
+/* 0xc0 */
+ "fi",
+ "fl",
+ "daggerdbl",
+ "periodcentered",
+ "quotesinglbase",
+ "quotedblbase",
+ "perthousand",
+ "Acircumflex",
+ "Ecircumflex",
+ "Aacute",
+ "Edieresis",
+ "Egrave",
+ "Iacute",
+ "Icircumflex",
+ "Idieresis",
+ "Igrave",
+/* 0xd0 */
+ "Oacute",
+ "Ocircumflex",
+ "applelogo",
+ "Ograve",
+ "Uacute",
+ "Ucircumflex",
+ "Ugrave",
+ "dotlessi",
+ "circumflex",
+ "tilde",
+ "macron",
+ "breve",
+ "dotaccent",
+ "ring",
+ "cedilla",
+ "hungarumlaut",
+/* 0xe0 */
+ "ogonek",
+ "caron",
+ "Lslash",
+ "lslash",
+ "Scaron",
+ "scaron",
+ "Zcaron",
+ "zcaron",
+ "brokenbar",
+ "Eth",
+ "eth",
+ "Yacute",
+ "yacute",
+ "Thorn",
+ "thorn",
+ "minus",
+/* 0xf0 */
+ "multiply",
+ "onesuperior",
+ "twosuperior",
+ "threesuperior",
+ "onehalf",
+ "onequarter",
+ "threequarters",
+ "franc",
+ "Gbreve",
+ "gbreve",
+ "Idot",
+ "Scedilla",
+ "scedilla",
+ "Cacute",
+ "cacute",
+ "Ccaron",
+/* 0x100 */
+ "ccaron",
+ "dmacron"
+};
+
+const char *ambiguous_names[] = {
+ "Delta", /* increment */
+ "Omega", /* Ohm */
+ "Pi", /* product */
+ "Sigma", /* summation */
+ "dmacron", /* dslash */
+ "macron", /* overscore */
+ "periodcentered", /* middot */
+ NULL
+};
diff --git a/Build/source/texk/web2c/pdftexdir/mapfile.c b/Build/source/texk/web2c/pdftexdir/mapfile.c
new file mode 100644
index 00000000000..758290127ca
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/mapfile.c
@@ -0,0 +1,1150 @@
+/*
+Copyright (c) 1996-2005 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX 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.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/mapfile.c#30 $
+
+source code indentation by "indent -kr -nut"
+*/
+
+#include <math.h>
+#include "ptexlib.h"
+#include <kpathsea/c-auto.h>
+#include <kpathsea/c-memstr.h>
+#include "avlstuff.h"
+
+static const char perforce_id[] =
+ "$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/mapfile.c#30 $";
+
+#define FM_BUF_SIZE 1024
+
+static FILE *fm_file;
+
+#define fm_open() \
+ open_input (&fm_file, kpse_fontmap_format, FOPEN_RBIN_MODE)
+#define fm_close() xfclose(fm_file, cur_file_name)
+#define fm_getchar() xgetc(fm_file)
+#define fm_eof() feof(fm_file)
+
+enum _mode { FM_DUPIGNORE, FM_REPLACE, FM_DELETE };
+enum _ltype { MAPFILE, MAPLINE };
+enum _tfmavail { TFM_UNCHECKED, TFM_FOUND, TFM_NOTFOUND };
+
+typedef struct mitem {
+ int mode; /* FM_DUPIGNORE or FM_REPLACE or FM_DELETE */
+ int type; /* map file or map line */
+ char *line; /* pointer to map file name or map line */
+ int lineno; /* line number in map file */
+ struct mitem *next; /* pointer to next item, or NULL */
+} mapitem;
+mapitem *miptr, *mapitems = NULL;
+
+fm_entry *fm_cur;
+static const char nontfm[] = "<nontfm>";
+static fm_entry *loaded_tfm_found;
+static fm_entry *avail_tfm_found;
+static fm_entry *non_tfm_found;
+static fm_entry *not_avail_tfm_found;
+
+#define read_field(r, q, buf) do { \
+ for (q = buf; *r != ' ' && *r != 10; *q++ = *r++); \
+ *q = 0; \
+ skip (r, ' '); \
+} while (0)
+
+#define set_field(F) do { \
+ if (q > buf) \
+ fm->F = xstrdup(buf); \
+ if (*r == 10) \
+ goto done; \
+} while (0)
+
+static fm_entry *new_fm_entry(void)
+{
+ fm_entry *fm;
+ fm = xtalloc(1, fm_entry);
+ fm->tfm_name = NULL;
+ fm->ps_name = NULL;
+ fm->flags = 0;
+ fm->ff_name = NULL;
+ fm->subset_tag = NULL;
+ fm->encoding = NULL;
+ fm->tfm_num = getnullfont();
+ fm->tfm_avail = TFM_UNCHECKED;
+ fm->type = 0;
+ fm->slant = 0;
+ fm->extend = 0;
+ fm->ff_objnum = 0;
+ fm->fn_objnum = 0;
+ fm->fd_objnum = 0;
+ fm->charset = NULL;
+ fm->all_glyphs = false;
+ fm->links = 0;
+ return fm;
+}
+
+static void delete_fm_entry(fm_entry * fm)
+{
+ xfree(fm->tfm_name);
+ xfree(fm->ps_name);
+ xfree(fm->ff_name);
+ xfree(fm->subset_tag);
+ xfree(fm->charset);
+ xfree(fm);
+}
+
+static ff_entry *new_ff_entry(void)
+{
+ ff_entry *ff;
+ ff = xtalloc(1, ff_entry);
+ ff->ff_name = NULL;
+ ff->ff_path = NULL;
+ return ff;
+}
+
+static void delete_ff_entry(ff_entry * ff)
+{
+ xfree(ff->ff_name);
+ xfree(ff->ff_path);
+ xfree(ff);
+}
+
+static fm_entry *dummy_fm_entry()
+{
+ static const fm_entry const_fm_entry;
+ return (fm_entry *) & const_fm_entry;
+}
+
+char *mk_base_tfm(char *tfmname, int *i)
+{
+ static char buf[SMALL_BUF_SIZE];
+ char *p = tfmname, *r = strend(p) - 1, *q = r;
+ while (q > p && isdigit(*q))
+ --q;
+ if (!(q > p) || q == r || (*q != '+' && *q != '-'))
+ return NULL;
+ check_buf(q - p + 1, SMALL_BUF_SIZE);
+ strncpy(buf, p, (unsigned) (q - p));
+ buf[q - p] = 0;
+ *i = atoi(q);
+ return buf;
+}
+
+static fmentryptr fmlookup(internalfontnumber);
+
+boolean hasfmentry(internalfontnumber f)
+{
+ if (pdffontmap[f] == NULL)
+ pdffontmap[f] = fmlookup(f);
+ assert(pdffontmap[f] != NULL);
+ return pdffontmap[f] != (fmentryptr) dummy_fm_entry();
+}
+
+/**********************************************************************/
+
+struct avl_table *tfm_tree = NULL;
+struct avl_table *ps_tree = NULL;
+struct avl_table *ff_tree = NULL;
+
+/* AVL sort fm_entry into tfm_tree by tfm_name */
+
+static int comp_fm_entry_tfm(const void *pa, const void *pb, void *p)
+{
+ return strcmp(((const fm_entry *) pa)->tfm_name,
+ ((const fm_entry *) pb)->tfm_name);
+}
+
+#define cmp_return(a, b) \
+ if (a > b) \
+ return 1; \
+ if (a < b) \
+ return -1
+
+/* AVL sort fm_entry into ps_tree by ps_name, slant, and extend */
+
+static int comp_fm_entry_ps(const void *pa, const void *pb, void *p)
+{
+ const fm_entry *p1 = (const fm_entry *) pa, *p2 =
+ (const fm_entry *) pb;
+ int i;
+ assert(p1->ps_name != NULL && p2->ps_name != NULL);
+ if ((i = strcmp(p1->ps_name, p2->ps_name)) != 0)
+ return i;
+ cmp_return(p1->slant, p2->slant);
+ cmp_return(p1->extend, p2->extend);
+ if (p1->tfm_name != NULL && p2->tfm_name != NULL &&
+ (i = strcmp(p1->tfm_name, p2->tfm_name)) != 0)
+ return i;
+ return 0;
+}
+
+/* AVL sort ff_entry into ff_tree by ff_name */
+
+static int comp_ff_entry(const void *pa, const void *pb, void *p)
+{
+ return strcmp(((const ff_entry *) pa)->ff_name,
+ ((const ff_entry *) pb)->ff_name);
+}
+
+static void create_avl_trees()
+{
+ if (tfm_tree == NULL) {
+ tfm_tree = avl_create(comp_fm_entry_tfm, NULL, &avl_xallocator);
+ assert(tfm_tree != NULL);
+ }
+ if (ps_tree == NULL) {
+ ps_tree = avl_create(comp_fm_entry_ps, NULL, &avl_xallocator);
+ assert(ps_tree != NULL);
+ }
+ if (ff_tree == NULL) {
+ ff_tree = avl_create(comp_ff_entry, NULL, &avl_xallocator);
+ assert(ff_tree != NULL);
+ }
+}
+
+/*
+The function avl_do_entry() is not completely symmetrical with regards
+to tfm_name and ps_name handling, e. g. a duplicate tfm_name gives a
+"goto exit", and no ps_name link is tried. This is to keep it compatible
+with the original version.
+*/
+
+static int avl_do_entry(fm_entry * fp, int mode)
+{
+ fm_entry *p, *p2;
+ void *a;
+ void **aa;
+ struct avl_traverser trav;
+
+ /* handle tfm_name link */
+
+ if (strcmp(fp->tfm_name, nontfm) != 0) {
+ p = (fm_entry *) avl_find(tfm_tree, fp);
+ if (p != NULL) {
+ if (mode == FM_DUPIGNORE) {
+ pdftex_warn
+ ("fontmap entry for `%s' already exists, duplicates ignored",
+ fp->tfm_name);
+ goto exit;
+ } else { /* mode == FM_REPLACE / FM_DELETE */
+ if (fontused[p->tfm_num]) {
+ pdftex_warn
+ ("fontmap entry for `%s' has been used, replace/delete not allowed",
+ fp->tfm_name);
+ goto exit;
+ }
+ a = avl_delete(tfm_tree, p);
+ assert(a != NULL);
+ unset_tfmlink(p);
+ if (!has_pslink(p))
+ delete_fm_entry(p);
+ }
+ }
+ if (mode != FM_DELETE) {
+ aa = avl_probe(tfm_tree, fp);
+ assert(aa != NULL);
+ set_tfmlink(fp);
+ }
+ }
+
+ /* handle ps_name link */
+
+ if (fp->ps_name != NULL) {
+ assert(fp->tfm_name != NULL);
+ p = (fm_entry *) avl_find(ps_tree, fp);
+ if (p != NULL) {
+ if (mode == FM_DUPIGNORE) {
+ pdftex_warn
+ ("ps_name entry for `%s' already exists, duplicates ignored",
+ fp->ps_name);
+ goto exit;
+ } else { /* mode == FM_REPLACE / FM_DELETE */
+ if (fontused[p->tfm_num]) {
+ /* REPLACE/DELETE not allowed */
+ pdftex_warn
+ ("fontmap entry for `%s' has been used, replace/delete not allowed",
+ p->tfm_name);
+ goto exit;
+ }
+ a = avl_delete(ps_tree, p);
+ assert(a != NULL);
+ unset_pslink(p);
+ if (!has_tfmlink(p))
+ delete_fm_entry(p);
+ }
+ }
+ if (mode != FM_DELETE) {
+ aa = avl_probe(ps_tree, fp);
+ assert(aa != NULL);
+ set_pslink(fp);
+ }
+ }
+ exit:
+ if (!has_tfmlink(fp) && !has_pslink(fp)) /* e. g. after FM_DELETE */
+ return 1; /* deallocation of fm_entry structure required */
+ else
+ return 0;
+}
+
+/**********************************************************************/
+/* consistency check for map entry, with warn flag */
+
+int check_fm_entry(fm_entry * fm, boolean warn)
+{
+ int a = 0;
+ assert(fm != NULL);
+ if (fm->ps_name != NULL) {
+ if (is_basefont(fm)) {
+ if (is_fontfile(fm) && !is_included(fm)) {
+ if (warn)
+ pdftex_warn
+ ("invalid entry for `%s': font file must be included or omitted for base fonts",
+ fm->tfm_name);
+ a += 1;
+ }
+ } else { /* not a base font */
+ /* if no font file given, drop this entry */
+ if (!is_fontfile(fm)) {
+ if (warn)
+ pdftex_warn
+ ("invalid entry for `%s': font file missing",
+ fm->tfm_name);
+ a += 2;
+ }
+ }
+ }
+ if (is_truetype(fm) && is_reencoded(fm) && !is_subsetted(fm)) {
+ if (warn)
+ pdftex_warn
+ ("invalid entry for `%s': only subsetted TrueType font can be reencoded",
+ fm->tfm_name);
+ a += 4;
+ }
+ if ((fm->slant != 0 || fm->extend != 0) &&
+ (!is_included(fm) || is_truetype(fm))) {
+ if (warn)
+ pdftex_warn
+ ("invalid entry for `%s': SlantFont/ExtendFont can be used only with embedded T1 fonts",
+ fm->tfm_name);
+ a += 8;
+ }
+ if (abs(fm->slant) > 1000) {
+ if (warn)
+ pdftex_warn
+ ("invalid entry for `%s': too big value of SlantFont (%g)",
+ fm->tfm_name, fm->slant / 1000.0);
+ a += 16;
+ }
+ if (abs(fm->extend) > 2000) {
+ if (warn)
+ pdftex_warn
+ ("invalid entry for `%s': too big value of ExtendFont (%g)",
+ fm->tfm_name, fm->extend / 1000.0);
+ a += 32;
+ }
+ return a;
+}
+
+/**********************************************************************/
+/* returns true if s is one of the 14 std. font names; speed-trimmed. */
+
+boolean check_basefont(char *s)
+{
+ static const char *basefont_names[] = {
+ "Courier", /* 0:7 */
+ "Courier-Bold", /* 1:12 */
+ "Courier-Oblique", /* 2:15 */
+ "Courier-BoldOblique", /* 3:19 */
+ "Helvetica", /* 4:9 */
+ "Helvetica-Bold", /* 5:14 */
+ "Helvetica-Oblique", /* 6:17 */
+ "Helvetica-BoldOblique", /* 7:21 */
+ "Symbol", /* 8:6 */
+ "Times-Roman", /* 9:11 */
+ "Times-Bold", /* 10:10 */
+ "Times-Italic", /* 11:12 */
+ "Times-BoldItalic", /* 12:16 */
+ "ZapfDingbats" /* 13:12 */
+ };
+ static const int index[] =
+ { -1, -1, -1, -1, -1, -1, 8, 0, -1, 4, 10, 9, -1, -1, 5, 2, 12, 6,
+ -1, 3, -1, 7
+ };
+ int n = strlen(s), k = -1;
+ if (n > 21)
+ return false;
+ if (n == 12) { /* three names have length 12 */
+ switch (*s) {
+ case 'C':
+ k = 1; /* Courier-Bold */
+ break;
+ case 'T':
+ k = 11; /* Times-Italic */
+ break;
+ case 'Z':
+ k = 13; /* ZapfDingbats */
+ break;
+ default:
+ return false;
+ }
+ } else
+ k = index[n];
+ if (k > -1 && strcmp(basefont_names[k], s) == 0)
+ return true;
+ return false;
+};
+
+/**********************************************************************/
+
+static void fm_scan_line(mapitem * mitem)
+{
+ int a, b, c, j, u = 0, v = 0;
+ float d;
+ char fm_line[FM_BUF_SIZE], buf[FM_BUF_SIZE];
+ fm_entry *fm;
+ char *p, *q, *r, *s;
+ p = fm_line;
+ switch (mitem->type) {
+ case MAPFILE:
+ do {
+ c = fm_getchar();
+ append_char_to_buf(c, p, fm_line, FM_BUF_SIZE);
+ }
+ while (c != 10);
+ break;
+ case MAPLINE:
+ s = mitem->line;
+ while ((c = *s++) != 0)
+ append_char_to_buf(c, p, fm_line, FM_BUF_SIZE);
+ break;
+ default:
+ assert(0);
+ }
+ append_eol(p, fm_line, FM_BUF_SIZE);
+ if (is_cfg_comment(*fm_line))
+ return;
+ r = fm_line;
+ read_field(r, q, buf);
+ fm = new_fm_entry();
+ set_field(tfm_name);
+ p = r;
+ read_field(r, q, buf);
+ if (*buf != '<' && *buf != '"')
+ set_field(ps_name);
+ else
+ r = p; /* unget the field */
+ if (isdigit(*r)) { /* font flags given */
+ fm->flags = atoi(r);
+ while (isdigit(*r))
+ r++;
+ } else
+ fm->flags = 4; /* treat as Symbol font */
+ while (1) { /* loop through "specials", encoding, font file */
+ skip(r, ' ');
+ switch (*r) {
+ case 10:
+ goto done;
+ case '"': /* opening quote */
+ r++;
+ u = v = 0;
+ do {
+ skip(r, ' ');
+ if (sscanf(r, "%f %n", &d, &j) > 0) {
+ s = r + j; /* jump behind number, eat also blanks, if any */
+ if (*(s - 1) == 'E' || *(s - 1) == 'e')
+ s--; /* e. g. 0.5ExtendFont: %f = 0.5E */
+ if (strncmp(s, "SlantFont", strlen("SlantFont")) == 0) {
+ d *= 1000.0; /* correct rounding also for neg. numbers */
+ fm->slant = (integer) (d > 0 ? d + 0.5 : d - 0.5);
+ r = s + strlen("SlantFont");
+ } else
+ if (strncmp(s, "ExtendFont", strlen("ExtendFont"))
+ == 0) {
+ d *= 1000.0;
+ fm->extend = (integer) (d > 0 ? d + 0.5 : d - 0.5);
+ if (fm->extend == 1000)
+ fm->extend = 0;
+ r = s + strlen("ExtendFont");
+ } else { /* unknown name */
+ for (r = s; *r != ' ' && *r != '"' && *r != 10; r++); /* jump over name */
+ c = *r; /* remember char for temporary end of string */
+ *r = '\0';
+ pdftex_warn
+ ("invalid entry for `%s': unknown name `%s' ignored",
+ fm->tfm_name, s);
+ *r = c;
+ }
+ } else
+ for (; *r != ' ' && *r != '"' && *r != 10; r++);
+ }
+ while (*r == ' ');
+ if (*r == '"') /* closing quote */
+ r++;
+ else {
+ pdftex_warn
+ ("invalid entry for `%s': closing quote missing",
+ fm->tfm_name);
+ goto bad_line;
+ }
+ break;
+ default: /* encoding or font file specification */
+ a = b = 0;
+ if (*r == '<') {
+ a = *r++;
+ if (*r == '<' || *r == '[')
+ b = *r++;
+ }
+ read_field(r, q, buf);
+ /* encoding, formats: '8r.enc' or '<8r.enc' or '<[8r.enc' */
+ if (strlen(buf) > 4
+ && strcasecmp(strend(buf) - 4, ".enc") == 0) {
+ fm->encoding = add_enc(buf);
+ u = v = 0; /* u, v used if intervening blank: "<< foo" */
+ } else if (strlen(buf) > 0) { /* file name given */
+ /* font file, formats:
+ * subsetting: '<cmr10.pfa'
+ * no subsetting: '<<cmr10.pfa'
+ * no embedding: 'cmr10.pfa'
+ */
+ if (a == '<' || u == '<') {
+ set_included(fm);
+ if ((a == '<' && b == 0) || (a == 0 && v == 0))
+ set_subsetted(fm);
+ /* otherwise b == '<' (or '[') => no subsetting */
+ }
+ set_field(ff_name);
+ u = v = 0;
+ } else {
+ u = a;
+ v = b;
+ }
+ }
+ }
+ done:
+ if (fm->ps_name != NULL && check_basefont(fm->ps_name))
+ set_basefont(fm);
+ if (is_fontfile(fm)
+ && strcasecmp(strend(fm_fontfile(fm)) - 4, ".ttf") == 0)
+ set_truetype(fm);
+ if (check_fm_entry(fm, true) != 0)
+ goto bad_line;
+ /*
+ Until here the map line has been completely scanned without errors;
+ fm points to a valid, freshly filled-out fm_entry structure.
+ Now follows the actual work of registering/deleting.
+ */
+ if (avl_do_entry(fm, mitem->mode) == 0) /* if success */
+ return;
+ bad_line:
+ delete_fm_entry(fm);
+}
+
+/**********************************************************************/
+
+void fm_read_info()
+{
+ mapitem *tmp;
+ create_avl_trees();
+ while (mapitems != NULL) {
+ assert(mapitems->line != NULL);
+ mapitems->lineno = 1;
+ switch (mapitems->type) {
+ case MAPFILE:
+ set_cur_file_name(mapitems->line);
+ if (!fm_open()) {
+ pdftex_warn("cannot open font map file");
+ } else {
+ cur_file_name = (char *) nameoffile + 1;
+ tex_printf("{%s", cur_file_name);
+ while (!fm_eof()) {
+ fm_scan_line(mapitems);
+ mapitems->lineno++;
+ }
+ fm_close();
+ tex_printf("}");
+ fm_file = NULL;
+ }
+ break;
+ case MAPLINE:
+ cur_file_name = NULL; /* makes pdftex_warn() shorter */
+ fm_scan_line(mapitems);
+ break;
+ default:
+ assert(0);
+ }
+ tmp = mapitems;
+ mapitems = mapitems->next;
+ xfree(tmp->line);
+ xfree(tmp);
+ }
+ cur_file_name = NULL;
+ return;
+}
+
+/**********************************************************************/
+
+/*
+char *mk_exname(char *basename, int e)
+{
+ static char buf[SMALL_BUF_SIZE];
+ char *p = basename, *r;
+ if ((r = strrchr(p, '.')) == NULL)
+ r = strend(p);
+ check_buf(r - p + strlen(r) + 10, SMALL_BUF_SIZE);
+ strncpy(buf, p, (unsigned) (r - p));
+ sprintf(buf + (r - p), "%+i", e);
+ strcat(buf, r);
+ return buf;
+}
+*/
+
+internalfontnumber tfmoffm(fmentryptr fm_pt)
+{
+ return ((fm_entry *) fm_pt)->tfm_num;
+}
+
+static fm_entry *mk_ex_fm(internalfontnumber f, fm_entry * basefm, int ex)
+{
+ fm_entry *fm;
+ integer e = basefm->extend;
+ if (e == 0)
+ e = 1000;
+ fm = new_fm_entry();
+ fm->flags = basefm->flags;
+ fm->encoding = basefm->encoding;
+ fm->type = basefm->type;
+ fm->slant = basefm->slant;
+ fm->extend = roundxnoverd(e, 1000 + ex, 1000); /* modify ExtentFont to simulate expansion */
+ if (fm->extend == 1000)
+ fm->extend = 0;
+ fm->tfm_name = xstrdup(makecstring(fontname[f]));
+ if (basefm->ps_name != NULL)
+ fm->ps_name = xstrdup(basefm->ps_name);
+ fm->ff_name = xstrdup(basefm->ff_name);
+ fm->ff_objnum = pdfnewobjnum();
+ fm->tfm_num = f;
+ fm->tfm_avail = TFM_FOUND;
+ assert(strcmp(fm->tfm_name, nontfm) != 0);
+ return fm;
+}
+
+static void init_fm(fm_entry * fm, internalfontnumber f)
+{
+ if (fm->fd_objnum == 0 && !no_font_desc(fm))
+ fm->fd_objnum = pdfnewobjnum();
+ if (fm->ff_objnum == 0 && is_included(fm))
+ fm->ff_objnum = pdfnewobjnum();
+ if (fm->tfm_num == getnullfont()) {
+ fm->tfm_num = f;
+ fm->tfm_avail = TFM_FOUND;
+ }
+}
+
+static fmentryptr fmlookup(internalfontnumber f)
+{
+ char *tfm, *p;
+ fm_entry *fm, *exfm;
+ fm_entry tmp;
+ int ai, e;
+ if (tfm_tree == NULL || mapitems != NULL)
+ fm_read_info();
+ tfm = makecstring(fontname[f]);
+ assert(strcmp(tfm, nontfm) != 0);
+
+ /* Look up for full <tfmname>[+-]<expand> */
+ tmp.tfm_name = tfm;
+ fm = (fm_entry *) avl_find(tfm_tree, &tmp);
+ if (fm != NULL) {
+ init_fm(fm, f);
+ return (fmentryptr) fm;
+ }
+ tfm = mk_base_tfm(makecstring(fontname[f]), &e);
+ if (tfm == NULL) /* not an expanded font, nothing to do */
+ return (fmentryptr) dummy_fm_entry();
+
+ tmp.tfm_name = tfm;
+ fm = (fm_entry *) avl_find(tfm_tree, &tmp);
+ if (fm != NULL) { /* found an entry with the base tfm name, e.g. cmr10 */
+ if (!is_t1fontfile(fm) || !is_included(fm)) {
+ pdftex_warn
+ ("font %s cannot be expanded (not an included Type1 font)",
+ tfm);
+ return (fmentryptr) dummy_fm_entry();
+ }
+ exfm = mk_ex_fm(f, fm, e); /* copies all fields from fm except tfm name */
+ init_fm(exfm, f);
+ ai = avl_do_entry(exfm, FM_DUPIGNORE);
+ assert(ai == 0);
+ return (fmentryptr) exfm;
+ }
+ return (fmentryptr) dummy_fm_entry();
+}
+
+/*
+ Early check whether a font file exists. Used e. g. for replacing fonts
+ of embedded PDF files: Without font file, the font within the embedded
+ PDF-file is used. Search tree ff_tree is used in 1st instance, as it
+ may be faster than the kpse_find_file(), and kpse_find_file() is called
+ only once per font file name + expansion parameter. This might help
+ keeping speed, if many PDF pages with same fonts are to be embedded.
+
+ The ff_tree contains only font files, which are actually needed,
+ so this tree typically is much smaller than the tfm_tree or ps_tree.
+*/
+
+ff_entry *check_ff_exist(fm_entry * fm)
+{
+ ff_entry *ff;
+ ff_entry tmp;
+ char *ex_ffname;
+ void **aa;
+
+ assert(fm->ff_name != NULL);
+ tmp.ff_name = fm->ff_name;
+ ff = (ff_entry *) avl_find(ff_tree, &tmp);
+ if (ff == NULL) { /* not yet in database */
+ ff = new_ff_entry();
+ ff->ff_name = xstrdup(fm->ff_name);
+ if (is_truetype(fm))
+ ff->ff_path =
+ kpse_find_file(fm->ff_name, kpse_truetype_format, 0);
+ else
+ ff->ff_path =
+ kpse_find_file(fm->ff_name, kpse_type1_format, 0);
+ aa = avl_probe(ff_tree, ff);
+ assert(aa != NULL);
+ }
+ return ff;
+}
+
+/**********************************************************************/
+
+static boolean used_tfm(fm_entry * p)
+{
+ internalfontnumber f;
+ strnumber s;
+ ff_entry *ff;
+
+ /* check if the font file is not a TrueType font */
+ /* font replacement makes sense only for included Type1 files */
+ if (is_truetype(p) || !is_included(p))
+ return false;
+
+ /* check if the font file is available */
+ ff = check_ff_exist(p);
+ if (ff->ff_path == NULL)
+ return false;
+
+ /* check whether this font has been used */
+ if (fontused[p->tfm_num])
+ return true;
+ assert(p->tfm_name != NULL);
+
+ /* check whether we didn't find a loaded font yet,
+ * and this font has been loaded */
+ if (loaded_tfm_found == NULL && strcmp(p->tfm_name, nontfm) != 0) {
+ s = maketexstring(p->tfm_name);
+ if ((f = tfmlookup(s, 0)) != getnullfont()) {
+ loaded_tfm_found = p;
+ if (pdffontmap[f] == NULL)
+ pdffontmap[f] = (fmentryptr) p;
+ if (p->tfm_num == getnullfont())
+ p->tfm_num = f;
+ assert(p->tfm_num == f);
+ /* don't call flushstr() here as it has been called by tfmlookup() */
+ } else
+ flushstr(s);
+ }
+
+ /* check whether we didn't find either a loaded or a loadable font yet,
+ * and this font is loadable */
+ if (avail_tfm_found == NULL && loaded_tfm_found == NULL &&
+ strcmp(p->tfm_name, nontfm) != 0) {
+ if (p->tfm_avail == TFM_UNCHECKED) {
+ if (kpse_find_file(p->tfm_name, kpse_tfm_format, 0) != NULL) {
+ avail_tfm_found = p;
+ p->tfm_avail = TFM_FOUND;
+ } else {
+ p->tfm_avail = TFM_NOTFOUND;
+ if (not_avail_tfm_found == NULL)
+ not_avail_tfm_found = p;
+ }
+ }
+ }
+
+ /* check whether the current entry is a <nontfm> entry */
+ if (non_tfm_found == NULL && strcmp(p->tfm_name, nontfm) == 0)
+ non_tfm_found = p;
+
+ return false;
+}
+
+/* lookup_ps_name looks for an entry with a given ps name + slant + extend;
+ * return NULL if not found.
+ *
+ * As there may exist several such entries, we need to select the `right'
+ * one. We do so by checking all such entries and return the first one that
+ * fulfils the following criteria (in descending priority):
+ *
+ * - the tfm has been used (some char from this font has been typeset)
+ * - the tfm has been loaded (but not used yet)
+ * - the tfm can be loaded (but not loaded yet)
+ * - the tfm is present in map files, but cannot be loaded. In this case a
+ * dummy tfm can be loaded instead, and a warning should be written out
+ */
+
+static fm_entry *lookup_ps_name(fm_entry * fm)
+{
+ fm_entry *p, *p2;
+ struct avl_traverser t, t2;
+ strnumber s;
+ int a;
+
+ loaded_tfm_found = NULL;
+ avail_tfm_found = NULL;
+ non_tfm_found = NULL;
+ not_avail_tfm_found = NULL;
+
+ assert(fm->tfm_name == NULL);
+ p = (fm_entry *) avl_t_find(&t, ps_tree, fm);
+ if (p == NULL)
+ return NULL;
+ t2 = t;
+ p2 = avl_t_prev(&t2);
+
+ /* search forward */
+ do {
+ if (used_tfm(p))
+ return p;
+ p = avl_t_next(&t);
+ }
+ while (p != NULL && comp_fm_entry_ps(fm, p, NULL) == 0);
+
+ /* search backward */
+ while (p2 != NULL && comp_fm_entry_ps(fm, p2, NULL) == 0) {
+ if (used_tfm(p2))
+ return p2;
+ p2 = avl_t_prev(&t2);
+ }
+
+ if (loaded_tfm_found != NULL)
+ p = loaded_tfm_found;
+ else if (avail_tfm_found != NULL) {
+ p = avail_tfm_found;
+ p->tfm_num = readfontinfo(getnullcs(), maketexstring(p->tfm_name),
+ getnullstr(), -1000);
+ p->tfm_avail = TFM_FOUND;
+ } else if (non_tfm_found != NULL) {
+ p = non_tfm_found;
+ p->tfm_num = newdummyfont();
+ p->tfm_avail = TFM_FOUND;
+ } else if (not_avail_tfm_found != NULL) {
+ p = not_avail_tfm_found;
+ pdftex_warn("`%s' not loadable, use a dummy tfm instead",
+ p->tfm_name);
+ p2 = new_fm_entry();
+ p2->flags = p->flags;
+ p2->encoding = p->encoding;
+ p2->type = p->type;
+ p2->slant = p->slant;
+ p2->extend = p->extend;
+ p2->tfm_name = xstrdup(nontfm);
+ p2->ps_name = xstrdup(p->ps_name);
+ if (p->ff_name != NULL)
+ p2->ff_name = xstrdup(p->ff_name);
+ p2->tfm_num = newdummyfont();
+ p2->tfm_avail = TFM_FOUND;
+ a = avl_do_entry(p2, FM_DUPIGNORE);
+ assert(a == 0);
+ p = p2;
+ } else
+ return NULL;
+ assert(p->tfm_num != getnullfont());
+ return p;
+}
+
+/* Lookup fontmap for /BaseFont entries of embedded PDF-files;
+ * return dummy_fm_entry() if not found */
+
+fm_entry *lookup_fontmap(char *bname)
+{
+ fm_entry *fm, *fmx;
+ fm_entry tmp, tmpx;
+ ff_entry *ff;
+ char buf[SMALL_BUF_SIZE];
+ char *a, *b, *c, *d, *e, *s;
+ strnumber str;
+ int i, sl, ex, ai;
+ if (tfm_tree == NULL || mapitems != NULL)
+ fm_read_info();
+ if (bname == NULL)
+ return NULL;
+ if (strlen(bname) >= SMALL_BUF_SIZE)
+ pdftex_fail("Font name too long: `%s'", bname);
+ strcpy(buf, bname); /* keep bname untouched for later */
+ s = buf;
+ if (strlen(buf) > 7) { /* check for subsetted name tag */
+ for (i = 0; i < 6; i++, s++)
+ if (*s < 'A' || *s > 'Z')
+ break;
+ if (i == 6 && *s == '+')
+ s++; /* if name tag found, skip behind it */
+ else
+ s = buf;
+ }
+
+ /*
+ Scan -Slant_<slant> and -Extend_<extend> font name extensions;
+ three valid formats:
+ <fontname>-Slant_<slant>
+ <fontname>-Slant_<slant>-Extend_<extend>
+ <fontname>-Extend_<extend>
+ Slant entry must come _before_ Extend entry
+ */
+
+ tmp.slant = 0;
+ tmp.extend = 0;
+ if ((a = strstr(s, "-Slant_")) != NULL) {
+ b = a + strlen("-Slant_");
+ sl = (int) strtol(b, &e, 10);
+ if ((e != b) && (e == strend(b))) {
+ tmp.slant = sl;
+ *a = 0; /* bname string ends before "-Slant_" */
+ } else {
+ if (e != b) { /* only if <slant> is valid number */
+ if ((c = strstr(e, "-Extend_")) != NULL) {
+ d = c + strlen("-Extend_");
+ ex = (int) strtol(d, &e, 10);
+ if ((e != d) && (e == strend(d))) {
+ tmp.slant = sl;
+ tmp.extend = ex;
+ *a = 0; /* bname string ends before "-Slant_" */
+ }
+ }
+ }
+ }
+ } else {
+ if ((a = strstr(s, "-Extend_")) != NULL) {
+ b = a + strlen("-Extend_");
+ ex = (int) strtol(b, &e, 10);
+ if ((e != b) && (e == strend(b))) {
+ tmp.extend = ex;
+ *a = 0; /* bname string ends before "-Extend_" */
+ }
+ }
+ }
+ tmp.ps_name = s;
+ tmp.tfm_name = NULL;
+ fm = lookup_ps_name(&tmp);
+ if (fm != NULL) {
+ if (!(is_type1(fm) && is_included(fm))) {
+ pdftex_warn
+ ("PS name '%s' is found but ignored (not an included Type1 font)",
+ tmp.ps_name);
+ return NULL;
+ }
+ i = fm->tfm_num;
+ assert(i != getnullfont());
+ if (pdffontmap[i] == NULL)
+ pdffontmap[i] = (fmentryptr) fm;
+ if (fm->ff_objnum == 0 && is_included(fm))
+ fm->ff_objnum = pdfnewobjnum();
+ if (!fontused[i])
+ pdfinitfont(i);
+ return fm;
+ }
+/*
+ The following code snipplet handles fonts with "Slant" and "Extend"
+ name extensions in embedded PDF files, which don't yet have an
+ fm_entry. If such a font is found (e. g. CMR10-Extend_1020), and no
+ fm_entry for this is found in the ps_tree (e. g. ps_name = "CMR10",
+ extend = 1020), and if an unextended base font (e. g. CMR10) is found,
+ a new <nontfm> fm_entry is created and put into the ps_tree. Then
+ the lookup_fontmap() function is (recursively) called again, which
+ then should find the new fm_entry. The same can be done manually by
+ a map entry e. g.:
+
+ \pdfmapline{+<nontfm> CMR10 "1.02 ExtendFont" <cmr10.pfb}
+
+ This would also match the embedded font CMR10-Extend_1020, and replace
+ it by an extended copy of cmr10.pfb. -- But not by an expanded version;
+ no MM files (e.g. cmr10+20.pfb) would be used.
+*/
+
+ tmpx.ps_name = s;
+ tmpx.tfm_name = NULL;
+ tmpx.slant = 0;
+ tmpx.extend = 0;
+/* fm = (fm_entry *) avl_find(ps_tree, &tmpx); */
+ fm = lookup_ps_name(&tmpx);
+ if (fm != NULL) {
+ if (is_truetype(fm) || !is_included(fm))
+ return NULL;
+ ff = check_ff_exist(fm);
+ if (ff->ff_path == NULL)
+ return NULL;
+ fmx = new_fm_entry();
+ fmx->flags = fm->flags;
+ fmx->encoding = fm->encoding;
+ fmx->type = fm->type;
+ fmx->slant = tmp.slant;
+ fmx->extend = tmp.extend;
+ fmx->tfm_name = xstrdup(nontfm);
+ fmx->ps_name = xstrdup(s);
+ fmx->ff_name = xstrdup(fm->ff_name);
+ ai = avl_do_entry(fmx, FM_DUPIGNORE);
+ assert(ai == 0);
+ fm = lookup_fontmap(bname); /* new try */
+ assert(fm != NULL);
+ return fm;
+ }
+ return NULL;
+}
+
+/**********************************************************************/
+/*
+Add map file name or map line contents to the linked list "mapitems".
+Items not beginning with [+-=] flush list with pending items. Leading
+blanks and blanks immediately following [+-=] are ignored.
+*/
+
+char *add_map_item(char *s, int type)
+{
+ char *p;
+ int l; /* length of map item (without [+-=]) */
+ mapitem *tmp;
+ int mode;
+ for (; *s == ' '; s++); /* ignore leading blanks */
+ switch (*s) {
+ case '+': /* +mapfile.map, +mapline */
+ mode = FM_DUPIGNORE; /* insert entry, if it is not duplicate */
+ s++;
+ break;
+ case '=': /* =mapfile.map, =mapline */
+ mode = FM_REPLACE; /* try to replace earlier entry */
+ s++;
+ break;
+ case '-': /* -mapfile.map, -mapline */
+ mode = FM_DELETE; /* try to delete entry */
+ s++;
+ break;
+ default:
+ mode = FM_DUPIGNORE; /* also flush pending list */
+ while (mapitems != NULL) {
+ tmp = mapitems;
+ mapitems = mapitems->next;
+ xfree(tmp->line);
+ xfree(tmp);
+ }
+ }
+ for (; *s == ' '; s++); /* ignore blanks after [+-=] */
+ p = s; /* map item starts here */
+ switch (type) { /* find end of map item */
+ case MAPFILE:
+ for (; *p != 0 && *p != ' ' && *p != 10; p++);
+ break;
+ case MAPLINE: /* blanks allowed */
+ for (; *p != 0 && *p != 10; p++);
+ break;
+ default:
+ assert(0);
+ }
+ l = p - s;
+ if (l > 0) { /* only if real item to add */
+ tmp = xtalloc(1, mapitem);
+ if (mapitems == NULL)
+ mapitems = tmp; /* start new list */
+ else
+ miptr->next = tmp;
+ miptr = tmp;
+ miptr->mode = mode;
+ miptr->type = type;
+ miptr->line = xtalloc(l + 1, char);
+ *(miptr->line) = 0;
+ strncat(miptr->line, s, l);
+ miptr->next = NULL;
+ }
+ return p;
+}
+
+void pdfmapfile(integer t)
+{
+ add_map_item(makecstring(tokenstostring(t)), MAPFILE);
+ flushstr(lasttokensstring);
+}
+
+void pdfmapline(integer t)
+{
+ add_map_item(makecstring(tokenstostring(t)), MAPLINE);
+ flushstr(lasttokensstring);
+}
+
+void pdfinitmapfile(string map_name)
+{
+ if (mapitems == NULL) {
+ mapitems = xtalloc(1, mapitem);
+ miptr = mapitems;
+ miptr->mode = FM_DUPIGNORE;
+ miptr->type = MAPFILE;
+ miptr->line = xstrdup(map_name);
+ miptr->next = NULL;
+ }
+}
+
+/**********************************************************************/
+/* cleaning up... */
+
+static void destroy_fm_entry_tfm(void *pa, void *pb)
+{
+ fm_entry *fm;
+ fm = (fm_entry *) pa;
+ if (!has_pslink(fm))
+ delete_fm_entry(fm);
+ else
+ unset_tfmlink(fm);
+}
+
+static void destroy_fm_entry_ps(void *pa, void *pb)
+{
+ fm_entry *fm;
+ fm = (fm_entry *) pa;
+ if (!has_tfmlink(fm))
+ delete_fm_entry(fm);
+ else
+ unset_pslink(fm);
+}
+
+static void destroy_ff_entry(void *pa, void *pb)
+{
+ ff_entry *ff;
+ ff = (ff_entry *) pa;
+ delete_ff_entry(ff);
+}
+
+void fm_free(void)
+{
+ if (tfm_tree != NULL)
+ avl_destroy(tfm_tree, destroy_fm_entry_tfm);
+ if (ps_tree != NULL)
+ avl_destroy(ps_tree, destroy_fm_entry_ps);
+ if (ff_tree != NULL)
+ avl_destroy(ff_tree, destroy_ff_entry);
+}
+
+/**********************************************************************/
+/* end of mapfile.c */
diff --git a/Build/source/texk/web2c/pdftexdir/misc.ch b/Build/source/texk/web2c/pdftexdir/misc.ch
new file mode 100644
index 00000000000..0d69f25597c
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/misc.ch
@@ -0,0 +1,21 @@
+% WEB change file containing miscellany extensions for pdfTeX
+%
+% Copyright (c) 1996-2002 Han Th\^e\llap{\raise 0.5ex\hbox{\'{}}} Th\`anh, <thanh@pdftex.org>
+%
+% This file is part of pdfTeX.
+%
+% pdfTeX 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.
+%
+% pdfTeX is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with pdfTeX; if not, write to the Free Software
+% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+%
+% $Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/misc.ch#5 $
diff --git a/Build/source/texk/web2c/pdftexdir/noligatures.ch b/Build/source/texk/web2c/pdftexdir/noligatures.ch
new file mode 100644
index 00000000000..2a8ef91f4a1
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/noligatures.ch
@@ -0,0 +1,116 @@
+% Copyright (c) 2005 Han Th\^e\llap{\raise 0.5ex\hbox{\'{}}} Th\`anh, <thanh@pdftex.org>
+%
+% This file is part of pdfTeX.
+%
+% pdfTeX 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.
+%
+% pdfTeX is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with pdfTeX; if not, write to the Free Software
+% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+%
+% $Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/pdftex.ch#163 $
+@ This change file creates an extra primitive named \.{\\pdfnoligatures}, allowing
+you to destroy all ligatures of a loaded font. The command code is
+|assign_font_int|, with the new modifier value |no_lig_code|.
+
+Nothing other than the |char_tag| value is changed, and nothing is saved.
+The primitive works directly on |font_info|, so all changes are global,
+the same as for the other font assignment primitives. Usage is quite
+straightforward: \.{\\pdfnoligatures \\f } disables ligatures for font \.{\\f}.
+The expansion of \.{\\pdfnoligatures \\f } is either |1|, when the font has
+no ligatures, or |0|, when the font does have ligatures.
+
+Thanh: this patch uses |orig_char_info| because it is to be inserted
+after tex.pch. If you merge this into pdftex.ch, you may want to change
+back to |char_info|. It would not compile without using the
+|orig| trick because |effective_char| is not yet known at the spot
+where |test_no_ligatures| is used. sigh.
+
+@x [230]
+@d ef_code_base == 4
+@y
+@d ef_code_base == 4
+@d no_lig_code == 6 {|tag_code| is 5 }
+@z
+
+@x [230]
+begin scan_font_ident;
+if m=0 then scanned_result(hyphen_char[cur_val])(int_val)
+else if m=1 then scanned_result(skew_char[cur_val])(int_val)
+@y
+begin scan_font_ident;
+if m=0 then scanned_result(hyphen_char[cur_val])(int_val)
+else if m=1 then scanned_result(skew_char[cur_val])(int_val)
+else if m=no_lig_code then scanned_result(test_no_ligatures(cur_val))(int_val)
+@z
+
+@x [577]
+@<Declare procedures that scan font-related stuff@>=
+function get_tag_code(f: internal_font_number; c: eight_bits): integer;
+@y
+@<Declare procedures that scan font-related stuff@>=
+function test_no_ligatures(f: internal_font_number): integer;
+label exit;
+var c:integer;
+begin
+ test_no_ligatures:= 1;
+ for c := font_bc[f] to font_ec[f] do
+ if char_exists(orig_char_info(f)(c)) then
+ if odd(char_tag(orig_char_info(f)(c))) then begin
+ test_no_ligatures:= 0;
+ return;
+ end;
+ exit:
+end;
+
+function get_tag_code(f: internal_font_number; c: eight_bits): integer;
+@z
+
+@x [???]
+function init_font_base(v: integer): integer;
+@y
+procedure set_no_ligatures(f: internal_font_number);
+var c:integer;
+begin
+ for c := font_bc[f] to font_ec[f] do
+ if char_exists(orig_char_info(f)(c)) then
+ if char_tag(orig_char_info(f)(c))=lig_tag then
+ op_byte(orig_char_info(f)(c)) := (op_byte(orig_char_info(f)(c))) - lig_tag;
+end;
+
+function init_font_base(v: integer): integer;
+@z
+
+@x [1253]
+assign_font_int: begin n:=cur_chr; scan_font_ident; f:=cur_val;
+ if n < lp_code_base then begin
+@y
+assign_font_int: begin n:=cur_chr; scan_font_ident; f:=cur_val;
+ if n = no_lig_code then set_no_ligatures(f)
+ else if n < lp_code_base then begin
+@z
+
+@x [1254]
+primitive("efcode",assign_font_int,ef_code_base);
+@!@:ef_code_}{\.{\\efcode} primitive@>
+@y
+primitive("efcode",assign_font_int,ef_code_base);
+@!@:ef_code_}{\.{\\efcode} primitive@>
+primitive("pdfnoligatures",assign_font_int,no_lig_code);
+@!@:no_lig_code_}{\.{\\pdfnoligatures} primitive@>
+@z
+
+@x [1255]
+ef_code_base: print_esc("efcode");
+@y
+ef_code_base: print_esc("efcode");
+no_lig_code: print_esc("pdfnoligatures");
+@z
diff --git a/Build/source/texk/web2c/pdftexdir/pdfstrcmp.ch b/Build/source/texk/web2c/pdftexdir/pdfstrcmp.ch
new file mode 100644
index 00000000000..071ba74f281
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/pdfstrcmp.ch
@@ -0,0 +1,609 @@
+% Copyright (c) 2005 Han Th\^e\llap{\raise 0.5ex\hbox{\'{}}} Th\`anh, <thanh@pdftex.org>
+%
+% This file is part of pdfTeX.
+%
+% pdfTeX 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.
+%
+% pdfTeX is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with pdfTeX; if not, write to the Free Software
+% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+%
+% $Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/pdftex.ch#163 $
+%
+% experimental patch to make \pdfstrcmp expandable
+%
+% put it after tex.pch
+%
+% x line numbers of file pdfetex-org.web before patch
+%
+%***********************************************************************
+
+@x 9388
+@d pdftex_last_item_codes = pdftex_first_rint_code + 10 {end of \pdfTeX's command codes}
+@y
+@d pdf_shell_escape_code = pdftex_first_rint_code + 11 {code for \.{\\pdfshellescape}}
+@d pdftex_last_item_codes = pdftex_first_rint_code + 11 {end of \pdfTeX's command codes}
+@z
+
+@x 9442
+primitive("pdfelapsedtime",last_item,elapsed_time_code);
+@!@:elapsed_time_}{\.{\\pdfelapsedtime} primitive@>
+@y
+primitive("pdfelapsedtime",last_item,elapsed_time_code);
+@!@:elapsed_time_}{\.{\\pdfelapsedtime} primitive@>
+primitive("pdfshellescape",last_item,pdf_shell_escape_code);
+@!@:elapsed_time_}{\.{\\pdfshellescape} primitive@>
+@z
+
+@x 9470
+ elapsed_time_code: print_esc("pdfelapsedtime");
+@y
+ elapsed_time_code: print_esc("pdfelapsedtime");
+ pdf_shell_escape_code: print_esc("pdfshellescape");
+@z
+
+@x 9561
+ elapsed_time_code: cur_val := get_microinterval;
+@y
+ elapsed_time_code: cur_val := get_microinterval;
+ pdf_shell_escape_code:
+ begin
+ if shell_enabled_p then cur_val := 1
+ else cur_val := 0;
+ end;
+@z
+
+@x 10332
+@d pdf_last_escaped_string_code = pdftex_first_expand_code + 7 {command code for \.{\\pdflastescapedstring}}
+@d pdf_last_escaped_name_code = pdftex_first_expand_code + 8 {command code for \.{\\pdflastescapename}}
+@y
+@d pdf_escape_string_code = pdftex_first_expand_code + 7 {command code for \.{\\pdfescapestring}}
+@d pdf_escape_name_code = pdftex_first_expand_code + 8 {command code for \.{\\pdfescapename}}
+@z
+
+@x 10336
+@d pdftex_convert_codes = pdftex_first_expand_code + 11 {end of \pdfTeX's command codes}
+@y
+@d pdf_strcmp_code = pdftex_first_expand_code + 11 {command code for \.{\\pdfstrcmp}}
+@d pdf_escape_hex_code = pdftex_first_expand_code + 12 {command code for \.{\\pdfescapehex}}
+@d pdf_unescape_hex_code = pdftex_first_expand_code + 13 {command code for \.{\\pdfunescapehex}}
+@d pdf_creation_date_code = pdftex_first_expand_code + 14 {command code for \.{\\pdfcreationdate}}
+@d pdf_file_mod_date_code = pdftex_first_expand_code + 15 {command code for \.{\\pdffilemoddate}}
+@d pdf_file_size_code = pdftex_first_expand_code + 16 {command code for \.{\\pdffilesize}}
+@d pdf_mdfive_sum_code = pdftex_first_expand_code + 17 {command code for \.{\\pdfmdfivesum}}
+@d pdf_file_dump_code = pdftex_first_expand_code + 18 {command code for \.{\\pdffiledump}}
+@d pdf_match_code = pdftex_first_expand_code + 19 {command code for \.{\\pdfmatch}}
+@d pdf_last_match_code = pdftex_first_expand_code + 20 {command code for \.{\\pdflastmatch}}
+@d pdftex_convert_codes = pdftex_first_expand_code + 21 {end of \pdfTeX's command codes}
+@z
+
+%***********************************************************************
+
+@x 10369
+primitive("pdflastescapedstring",convert,pdf_last_escaped_string_code);@/
+@!@:pdf_last_escaped_string_}{\.{\\pdflastescapedstring} primitive@>
+primitive("pdflastescapedname",convert,pdf_last_escaped_name_code);@/
+@!@:pdf_last_escaped_name_}{\.{\\pdflastescapedname} primitive@>
+@y
+primitive("pdfescapestring",convert,pdf_escape_string_code);@/
+@!@:pdf_escape_string_}{\.{\\pdfescapestring} primitive@>
+primitive("pdfescapename",convert,pdf_escape_name_code);@/
+@!@:pdf_escape_name_}{\.{\\pdfescapename} primitive@>
+primitive("pdfescapehex",convert,pdf_escape_hex_code);@/
+@!@:pdf_escape_hex_}{\.{\\pdfescapehex} primitive@>
+primitive("pdfunescapehex",convert,pdf_unescape_hex_code);@/
+@!@:pdf_unescape_hex_}{\.{\\pdfunescapehex} primitive@>
+primitive("pdfcreationdate",convert,pdf_creation_date_code);@/
+@!@:pdf_creation_date_}{\.{\\pdfcreationdate} primitive@>
+primitive("pdffilemoddate",convert,pdf_file_mod_date_code);@/
+@!@:pdf_file_mod_date_}{\.{\\pdffilemoddate} primitive@>
+primitive("pdffilesize",convert,pdf_file_size_code);@/
+@!@:pdf_file_size_}{\.{\\pdffilesize} primitive@>
+primitive("pdfmdfivesum",convert,pdf_mdfive_sum_code);@/
+@!@:pdf_mdfive_sum_}{\.{\\pdfmdfivesum} primitive@>
+primitive("pdffiledump",convert,pdf_file_dump_code);@/
+@!@:pdf_file_dump_}{\.{\\pdffiledump} primitive@>
+primitive("pdfmatch",convert,pdf_match_code);@/
+@!@:pdf_match_}{\.{\\pdfmatch} primitive@>
+primitive("pdflastmatch",convert,pdf_last_match_code);@/
+@!@:pdf_last_match_}{\.{\\pdflastmatch} primitive@>
+primitive("pdfstrcmp",convert,pdf_strcmp_code);@/
+@!@:pdf_strcmp_}{\.{\\pdfstrcmp} primitive@>
+@z
+
+%***********************************************************************
+
+@x 10394
+ pdf_last_escaped_string_code: print_esc("pdflastescapedstring");
+ pdf_last_escaped_name_code: print_esc("pdflastescapedname");
+@y
+ pdf_escape_string_code: print_esc("pdfescapestring");
+ pdf_escape_name_code: print_esc("pdfescapename");
+ pdf_escape_hex_code: print_esc("pdfescapehex");
+ pdf_unescape_hex_code: print_esc("pdfunescapehex");
+ pdf_creation_date_code: print_esc("pdfcreationdate");
+ pdf_file_mod_date_code: print_esc("pdffilemoddate");
+ pdf_file_size_code: print_esc("pdffilesize");
+ pdf_mdfive_sum_code: print_esc("pdfmdfivesum");
+ pdf_file_dump_code: print_esc("pdffiledump");
+ pdf_match_code: print_esc("pdfmatch");
+ pdf_last_match_code: print_esc("pdflastmatch");
+ pdf_strcmp_code: print_esc("pdfstrcmp");
+@z
+
+%***********************************************************************
+
+@x 10403
+@p procedure conv_toks;
+var old_setting:0..max_selector; {holds |selector| setting}
+p, q: pointer;
+@!c:number_code..job_name_code; {desired type of conversion}
+@!save_scanner_status:small_number; {|scanner_status| upon entry}
+@!b:pool_pointer; {base of temporary string}
+@!i, l: integer; {index to access escaped string or name}
+begin c:=cur_chr; @<Scan the argument for command |c|@>;
+old_setting:=selector; selector:=new_string; b:=pool_ptr;
+@<Print the result of command |c|@>;
+selector:=old_setting; link(garbage):=str_toks(b); ins_list(link(temp_head));
+end;
+@y
+@p procedure conv_toks;
+label exit;
+var old_setting:0..max_selector; {holds |selector| setting}
+p, q: pointer;
+@!c:number_code..job_name_code; {desired type of conversion}
+@!save_scanner_status:small_number; {|scanner_status| upon entry}
+@!save_def_ref: pointer; {|def_ref| upon entry, important if inside `\.{\\message}'}
+@!save_warning_index: pointer;
+@!bool: boolean; {temp boolean}
+@!i: integer; {first temp integer}
+@!j: integer; {second temp integer}
+@!b:pool_pointer; {base of temporary string}
+@!s: str_number; {first temp string}
+@!t: str_number; {second temp string}
+begin c:=cur_chr; @<Scan the argument for command |c|@>;
+old_setting:=selector; selector:=new_string; b:=pool_ptr;
+@<Print the result of command |c|@>;
+selector:=old_setting; link(garbage):=str_toks(b); ins_list(link(temp_head));
+exit:end;
+@z
+
+@x 10450
+pdf_last_escaped_string_code: do_nothing;
+pdf_last_escaped_name_code: do_nothing;
+job_name_code: if job_name=0 then open_log_file;
+@y
+pdf_escape_string_code:
+ begin
+ save_scanner_status := scanner_status;
+ save_warning_index := warning_index;
+ save_def_ref := def_ref;
+ scan_pdf_ext_toks;
+ s := tokens_to_string(def_ref);
+ delete_token_ref(def_ref);
+ def_ref := save_def_ref;
+ warning_index := save_warning_index;
+ scanner_status := save_scanner_status;
+ b := pool_ptr;
+ escapestring(str_start[s]);
+ link(garbage) := str_toks(b);
+ flush_str(s);
+ ins_list(link(temp_head));
+ return;
+ end;
+pdf_escape_name_code:
+ begin
+ save_scanner_status := scanner_status;
+ save_warning_index := warning_index;
+ save_def_ref := def_ref;
+ scan_pdf_ext_toks;
+ s := tokens_to_string(def_ref);
+ delete_token_ref(def_ref);
+ def_ref := save_def_ref;
+ warning_index := save_warning_index;
+ scanner_status := save_scanner_status;
+ b := pool_ptr;
+ escapename(str_start[s]);
+ link(garbage) := str_toks(b);
+ flush_str(s);
+ ins_list(link(temp_head));
+ return;
+ end;
+pdf_escape_hex_code:
+ begin
+ save_scanner_status := scanner_status;
+ save_warning_index := warning_index;
+ save_def_ref := def_ref;
+ scan_pdf_ext_toks;
+ s := tokens_to_string(def_ref);
+ delete_token_ref(def_ref);
+ def_ref := save_def_ref;
+ warning_index := save_warning_index;
+ scanner_status := save_scanner_status;
+ b := pool_ptr;
+ escapehex(str_start[s]);
+ link(garbage) := str_toks(b);
+ flush_str(s);
+ ins_list(link(temp_head));
+ return;
+ end;
+pdf_unescape_hex_code:
+ begin
+ save_scanner_status := scanner_status;
+ save_warning_index := warning_index;
+ save_def_ref := def_ref;
+ scan_pdf_ext_toks;
+ s := tokens_to_string(def_ref);
+ delete_token_ref(def_ref);
+ def_ref := save_def_ref;
+ warning_index := save_warning_index;
+ scanner_status := save_scanner_status;
+ b := pool_ptr;
+ unescapehex(str_start[s]);
+ link(garbage) := str_toks(b);
+ flush_str(s);
+ ins_list(link(temp_head));
+ return;
+ end;
+pdf_creation_date_code:
+ begin
+ b := pool_ptr;
+ getcreationdate;
+ link(garbage) := str_toks(b);
+ ins_list(link(temp_head));
+ return;
+ end;
+pdf_file_mod_date_code:
+ begin
+ save_scanner_status := scanner_status;
+ save_warning_index := warning_index;
+ save_def_ref := def_ref;
+ scan_pdf_ext_toks;
+ s := tokens_to_string(def_ref);
+ delete_token_ref(def_ref);
+ def_ref := save_def_ref;
+ warning_index := save_warning_index;
+ scanner_status := save_scanner_status;
+ b := pool_ptr;
+ getfilemoddate(s);
+ link(garbage) := str_toks(b);
+ flush_str(s);
+ ins_list(link(temp_head));
+ return;
+ end;
+pdf_file_size_code:
+ begin
+ save_scanner_status := scanner_status;
+ save_warning_index := warning_index;
+ save_def_ref := def_ref;
+ scan_pdf_ext_toks;
+ s := tokens_to_string(def_ref);
+ delete_token_ref(def_ref);
+ def_ref := save_def_ref;
+ warning_index := save_warning_index;
+ scanner_status := save_scanner_status;
+ b := pool_ptr;
+ getfilesize(s);
+ link(garbage) := str_toks(b);
+ flush_str(s);
+ ins_list(link(temp_head));
+ return;
+ end;
+pdf_mdfive_sum_code:
+ begin
+ save_scanner_status := scanner_status;
+ save_warning_index := warning_index;
+ save_def_ref := def_ref;
+ bool := scan_keyword("file");
+ scan_pdf_ext_toks;
+ s := tokens_to_string(def_ref);
+ delete_token_ref(def_ref);
+ def_ref := save_def_ref;
+ warning_index := save_warning_index;
+ scanner_status := save_scanner_status;
+ b := pool_ptr;
+ getmd5sum(s, bool);
+ link(garbage) := str_toks(b);
+ flush_str(s);
+ ins_list(link(temp_head));
+ return;
+ end;
+pdf_file_dump_code:
+ begin
+ save_scanner_status := scanner_status;
+ save_warning_index := warning_index;
+ save_def_ref := def_ref;
+ {scan offset}
+ cur_val := 0;
+ if (scan_keyword("offset")) then begin
+ scan_int;
+ if (cur_val < 0) then begin
+ print_err("Bad file offset");
+@.Bad file offset@>
+ help2("A file offset must be between 0 and 2^{31}-1,")@/
+ ("I changed this one to zero.");
+ int_error(cur_val);
+ cur_val := 0;
+ end;
+ end;
+ i := cur_val;
+ {scan length}
+ cur_val := 0;
+ if (scan_keyword("length")) then begin
+ scan_int;
+ if (cur_val < 0) then begin
+ print_err("Bad dump length");
+@.Bad dump length@>
+ help2("A dump length must be between 0 and 2^{31}-1,")@/
+ ("I changed this one to zero.");
+ int_error(cur_val);
+ cur_val := 0;
+ end;
+ end;
+ j := cur_val;
+ {scan file name}
+ scan_pdf_ext_toks;
+ s := tokens_to_string(def_ref);
+ delete_token_ref(def_ref);
+ def_ref := save_def_ref;
+ warning_index := save_warning_index;
+ scanner_status := save_scanner_status;
+ b := pool_ptr;
+ getfiledump(s, i, j);
+ link(garbage) := str_toks(b);
+ flush_str(s);
+ ins_list(link(temp_head));
+ return;
+ end;
+pdf_match_code:
+ begin
+ save_scanner_status := scanner_status;
+ save_warning_index := warning_index;
+ save_def_ref := def_ref;
+ {scan for icase}
+ bool := scan_keyword("icase");
+ {scan for subcount}
+ i := -1; {default for subcount}
+ if scan_keyword("subcount") then begin
+ scan_int;
+ i := cur_val;
+ end;
+ scan_pdf_ext_toks;
+ s := tokens_to_string(def_ref);
+ delete_token_ref(def_ref);
+ scan_pdf_ext_toks;
+ t := tokens_to_string(def_ref);
+ delete_token_ref(def_ref);
+ def_ref := save_def_ref;
+ warning_index := save_warning_index;
+ scanner_status := save_scanner_status;
+ b := pool_ptr;
+ matchstrings(s, t, i, bool);
+ link(garbage) := str_toks(b);
+ flush_str(t);
+ flush_str(s);
+ ins_list(link(temp_head));
+ return;
+ end;
+pdf_last_match_code:
+ begin
+ scan_int;
+ if cur_val < 0 then begin
+ print_err("Bad match number");
+@.Bad match number@>
+ help2("Since I expected zero or a positive number,")@/
+ ("I changed this one to zero.");
+ int_error(cur_val);
+ cur_val := 0;
+ end;
+ b := pool_ptr;
+ getmatch(cur_val);
+ link(garbage) := str_toks(b);
+ ins_list(link(temp_head));
+ return;
+ end;
+pdf_strcmp_code:
+ begin
+ save_scanner_status := scanner_status;
+ save_warning_index := warning_index;
+ save_def_ref := def_ref;
+ compare_strings;
+ def_ref := save_def_ref;
+ warning_index := save_warning_index;
+ scanner_status := save_scanner_status;
+ end;
+job_name_code: if job_name=0 then open_log_file;
+@z
+
+%***********************************************************************
+
+@x 10512
+pdf_last_escaped_string_code: begin
+ l := escapedstrlen;
+ for i := 0 to l - 1 do
+ print_char(getescapedstrchar(i));
+end;
+pdf_last_escaped_name_code: begin
+ l := escapednamelen;
+ for i := 0 to l - 1 do
+ print_char(getescapednamechar(i));
+end;
+job_name_code: print(job_name);
+@y
+pdf_strcmp_code: print_int(cur_val);
+job_name_code: print(job_name);
+@z
+
+%***********************************************************************
+
+@x 32168
+@d pdf_strcmp_code == pdftex_first_extension_code + 24
+@d pdf_escape_string_code == pdftex_first_extension_code + 25
+@d pdf_escape_name_code == pdftex_first_extension_code + 26
+@d reset_timer_code == pdftex_first_extension_code + 27
+@d pdf_font_expand_code == pdftex_first_extension_code + 28
+@d pdftex_last_extension_code == pdftex_first_extension_code + 28
+@y
+@d reset_timer_code == pdftex_first_extension_code + 24
+@d pdf_font_expand_code == pdftex_first_extension_code + 25
+@d pdftex_last_extension_code == pdftex_first_extension_code + 25
+@z
+
+%***********************************************************************
+
+@x 32239
+primitive("pdfstrcmp",extension,pdf_strcmp_code);@/
+@!@:pdf_strcmp_}{\.{\\pdfstrcmp} primitive@>
+primitive("pdfescapestring",extension,pdf_escape_string_code);@/
+@!@:pdf_escape_string_}{\.{\\pdfescapestring} primitive@>
+primitive("pdfescapename",extension,pdf_escape_name_code);@/
+@!@:pdf_escape_name_}{\.{\\pdfescapename} primitive@>
+@y
+@z
+
+%***********************************************************************
+
+@x 32287
+ pdf_strcmp_code: print_esc("pdfstrcmp");
+ pdf_escape_string_code: print_esc("pdfescapestring");
+ pdf_escape_name_code: print_esc("pdfescapename");
+@y
+@z
+
+%***********************************************************************
+
+@x 32337
+pdf_strcmp_code: @<Implement \.{\\pdfstrcmp}@>;
+pdf_escape_string_code: @<Implement \.{\\pdfescapestring}@>;
+pdf_escape_name_code: @<Implement \.{\\pdfescapename}@>;
+@y
+@z
+
+%***********************************************************************
+
+@x 32463
+procedure compare_strings; {to implement \.{\\pdfstrcmp}}
+label done;
+var s1, s2: str_number;
+ i1, i2, j1, j2: pool_pointer;
+ result: integer;
+begin
+ call_func(scan_toks(false, true));
+ s1 := tokens_to_string(def_ref);
+ delete_token_ref(def_ref);
+ call_func(scan_toks(false, true));
+ s2 := tokens_to_string(def_ref);
+ delete_token_ref(def_ref);
+ i1 := str_start[s1];
+ j1 := str_start[s1 + 1];
+ i2 := str_start[s2];
+ j2 := str_start[s2 + 1];
+ while (i1 < j1) and (i2 < j2) do begin
+ if str_pool[i1] < str_pool[i2] then begin
+ result := -1;
+ goto done;
+ end;
+ if str_pool[i1] > str_pool[i2] then begin
+ result := 1;
+ goto done;
+ end;
+ incr(i1);
+ incr(i2);
+ end;
+ if (i1 = j1) and (i2 = j2) then
+ result := 0
+ else if i1 < j1 then
+ result := 1
+ else
+ result := -1;
+done:
+ pdf_retval := result;
+ flush_str(s2);
+ flush_str(s1);
+end;
+@y
+procedure compare_strings; {to implement \.{\\pdfstrcmp}}
+label done;
+var s1, s2: str_number;
+ i1, i2, j1, j2: pool_pointer;
+begin
+ call_func(scan_toks(false, true));
+ s1 := tokens_to_string(def_ref);
+ delete_token_ref(def_ref);
+ call_func(scan_toks(false, true));
+ s2 := tokens_to_string(def_ref);
+ delete_token_ref(def_ref);
+ i1 := str_start[s1];
+ j1 := str_start[s1 + 1];
+ i2 := str_start[s2];
+ j2 := str_start[s2 + 1];
+ while (i1 < j1) and (i2 < j2) do begin
+ if str_pool[i1] < str_pool[i2] then begin
+ cur_val := -1;
+ goto done;
+ end;
+ if str_pool[i1] > str_pool[i2] then begin
+ cur_val := 1;
+ goto done;
+ end;
+ incr(i1);
+ incr(i2);
+ end;
+ if (i1 = j1) and (i2 = j2) then
+ cur_val := 0
+ else if i1 < j1 then
+ cur_val := 1
+ else
+ cur_val := -1;
+done:
+ flush_str(s2);
+ flush_str(s1);
+ cur_val_level := int_val;
+end;
+@z
+
+%***********************************************************************
+
+@x 33387
+@ @<Implement \.{\\pdfescapestring}@>=
+begin
+ scan_pdf_ext_toks;
+ escapestr(tokens_to_string(def_ref));
+ flush_str(last_tokens_string);
+ delete_token_ref(def_ref);
+end
+
+@ @<Implement \.{\\pdfescapename}@>=
+begin
+ scan_pdf_ext_toks;
+ escapename(tokens_to_string(def_ref));
+ flush_str(last_tokens_string);
+ delete_token_ref(def_ref);
+end
+@y
+@z
+
+@x 33406
+@ @<Implement \.{\\pdfstrcmp}@>=
+compare_strings
+@y
+@z
+
+@x 33409
+@ @<Set initial values of key variables@>=
+ seconds_and_micros(epochseconds,microseconds);
+@y
+@ @<Set initial values of key variables@>=
+ seconds_and_micros(epochseconds,microseconds);
+ init_start_time;
+@z
+
+%***********************************************************************
diff --git a/Build/source/texk/web2c/pdftexdir/pdftex.ch b/Build/source/texk/web2c/pdftexdir/pdftex.ch
new file mode 100644
index 00000000000..6ae23335465
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/pdftex.ch
@@ -0,0 +1,6853 @@
+% WEB change file containing code for pdfTeX features extending TeX; % to be applied to tex.web (Version 3.141592) in order to define the
+% pdfTeX program.
+%
+% Note: This file, pdftex.ch, defines pdftex.web in terms of changes to be
+% applied to tex.web; in terms of a program such as TIE (or equivalent),
+%
+% tex.web )
+% + ) => tie -m ... => etex.web
+% pdftexdir/pdftex.ch )
+%
+% In addition, this file is used to define pdfetex.web, a combination
+% of e-TeX and pdfTeX as follows:
+%
+% tex.web )
+% + )
+% etexdir/etex.ch )
+% + )
+% pdfetexdir/pdfetex.ch1 ) => tie -m ... => pdfetex.web
+% + )
+% pdftexdir/pdftex.ch )
+% + )
+% pdfetexdir/pdfetex.ch2 )
+%
+% where the two (small) files pdfetexdir/pdfetex.ch[12] take care of
+% interferences between e-Tex changes (etexdir/etex.ch) and pdfTeX changes
+% (pdftexdir/pdftex.ch). Consequently, changes in these files have to be
+% coordinated.
+%
+% Copyright (c) 1996-2005 Han Th\^e\llap{\raise 0.5ex\hbox{\'{}}} Th\`anh, <thanh@pdftex.org>
+%
+% This file is part of pdfTeX.
+%
+% pdfTeX 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.
+%
+% pdfTeX is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with pdfTeX; if not, write to the Free Software
+% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+%
+% $Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/pdftex.ch#171 $
+%
+% The TeX program is copyright (C) 1982 by D. E. Knuth.
+% TeX is a trademark of the American Mathematical Society.
+%
+% all pdfTeX new primitives have the prefix "\pdf", apart from:
+% o extension of \vadjust
+% o extension of \font
+% o \efcode
+% o \lpcode, \rpcode
+% o \leftmarginkern, \rightmarginkern
+
+@x limbo
+\def\PASCAL{Pascal}
+@y
+\def\PASCAL{Pascal}
+\def\pdfTeX{pdf\TeX}
+\def\PDF{PDF}
+@z
+
+@x [2] - This change is made for TeX 3.141592
+@d banner=='This is TeX, Version 3.141592' {printed when \TeX\ starts}
+@y
+@d pdftex_version==130 { \.{\\pdftexversion} }
+@d pdftex_revision=="4" { \.{\\pdftexrevision} }
+@d pdftex_version_string=='-1.30.4' {current \pdfTeX\ version}
+@#
+@d pdfTeX_banner=='This is pdfTeX, Version 3.141592',pdftex_version_string
+ {printed when \pdfTeX\ starts}
+@#
+@d TeX_banner=='This is TeX, Version 3.141592' {printed when \TeX\ starts}
+@#
+@d banner==pdfTeX_banner
+@z
+
+% Some procedures that need to be declared forward
+@x [173]
+@* \[12] Displaying boxes.
+@y
+@<Declare procedures that need to be declared forward for pdftex@>@;
+
+@* \[12] Displaying boxes.
+@z
+
+% Define pdftex token list parameters
+@x [230]
+@d toks_base=local_base+10 {table of 256 token list registers}
+@y
+@d tex_toks=local_base+10 {end of \TeX's token list parameters}
+@#
+@d pdftex_first_loc = tex_toks {base for \pdfTeX's token list parameters}
+@d pdf_pages_attr_loc = pdftex_first_loc + 0 {points to token list for \.{\\pdfpagesattr}}
+@d pdf_page_attr_loc = pdftex_first_loc + 1 {points to token list for \.{\\pdfpageattr}}
+@d pdf_page_resources_loc = pdftex_first_loc + 2 {points to token list for \.{\\pdfpageresources}}
+@d pdf_pk_mode_loc = pdftex_first_loc + 3 {points to token list for \.{\\pdfpkmode}}
+@d pdf_toks=pdftex_first_loc+4 {end of \pdfTeX's token list parameters}
+@#
+@d toks_base=pdf_toks {table of 256 token list registers}
+@z
+
+@x [230]
+@d err_help==equiv(err_help_loc)
+@y
+@d err_help==equiv(err_help_loc)
+@d pdf_pages_attr==equiv(pdf_pages_attr_loc)
+@d pdf_page_attr==equiv(pdf_page_attr_loc)
+@d pdf_page_resources==equiv(pdf_page_resources_loc)
+@d pdf_pk_mode==equiv(pdf_pk_mode_loc)
+@z
+
+@x [230]
+primitive("errhelp",assign_toks,err_help_loc);
+@!@:err_help_}{\.{\\errhelp} primitive@>
+@y
+primitive("errhelp",assign_toks,err_help_loc);
+@!@:err_help_}{\.{\\errhelp} primitive@>
+primitive("pdfpagesattr",assign_toks,pdf_pages_attr_loc);
+@!@:pdf_pages_attr_}{\.{\\pdfpagesattr} primitive@>
+primitive("pdfpageattr",assign_toks,pdf_page_attr_loc);
+@!@:pdf_page_attr_}{\.{\\pdfpageattr} primitive@>
+primitive("pdfpageresources",assign_toks,pdf_page_resources_loc);
+@!@:pdf_page_resources_}{\.{\\pdfpageresources} primitive@>
+primitive("pdfpkmode",assign_toks,pdf_pk_mode_loc);
+@!@:pdf_pk_mode_}{\.{\\pdfpkmode} primitive@>
+@z
+
+@x [231]
+ othercases print_esc("errhelp")
+@y
+ pdf_pages_attr_loc: print_esc("pdfpagesattr");
+ pdf_page_attr_loc: print_esc("pdfpageattr");
+ pdf_page_resources_loc: print_esc("pdfpageresources");
+ pdf_pk_mode_loc: print_esc("pdfpkmode");
+ othercases print_esc("errhelp")
+@z
+
+% Define pdftex integer parameters
+@x [236]
+@d int_pars=55 {total number of integer parameters}
+@y
+@d tex_int_pars=55 {total number of \TeX's integer parameters}
+@#
+@d pdftex_first_integer_code = tex_int_pars {base for \pdfTeX's integer parameters}
+@d pdf_output_code = pdftex_first_integer_code + 0 {switch on PDF output if positive}
+@d pdf_compress_level_code = pdftex_first_integer_code + 1 {compress level of streams}
+@d pdf_decimal_digits_code = pdftex_first_integer_code + 2 {digits after the decimal point of numbers}
+@d pdf_move_chars_code = pdftex_first_integer_code + 3 {move chars 0..31 to higher area if possible}
+@d pdf_image_resolution_code = pdftex_first_integer_code + 4 {default image resolution}
+@d pdf_pk_resolution_code = pdftex_first_integer_code + 5 {default resolution of PK font}
+@d pdf_unique_resname_code = pdftex_first_integer_code + 6 {generate unique names for resouces}
+@d pdf_option_always_use_pdfpagebox_code = pdftex_first_integer_code + 7 {if the pdf inclusion should always use a specific pdf page box}
+@d pdf_option_pdf_inclusion_errorlevel_code = pdftex_first_integer_code + 8 {if the pdf inclusion should treat pdfs newer than |pdf_minor_version| as an error}
+@d pdf_minor_version_code = pdftex_first_integer_code + 9 {fractional part of the pdf version produced}
+@d pdf_force_pagebox_code = pdftex_first_integer_code + 10 {if the pdf inclusion should always use a specific pdf page box}
+@d pdf_inclusion_errorlevel_code = pdftex_first_integer_code + 11 {if the pdf inclusion should treat pdfs newer than |pdf_minor_version| as an error}
+@d pdf_gamma_code = pdftex_first_integer_code + 12
+@d pdf_image_gamma_code = pdftex_first_integer_code + 13
+@d pdf_image_hicolor_code = pdftex_first_integer_code + 14
+@d pdf_image_apply_gamma_code = pdftex_first_integer_code + 15
+@d pdf_px_dimen_code = pdftex_first_integer_code + 16 {the code for the pixel dimen value}
+@d pdf_int_pars=pdftex_first_integer_code + 17 {total number of \pdfTeX's integer parameters}
+@#
+@d int_pars=pdf_int_pars {total number of integer parameters}
+@z
+
+@x [236]
+@d error_context_lines==int_par(error_context_lines_code)
+@y
+@d error_context_lines==int_par(error_context_lines_code)
+@#
+@d pdf_output == int_par(pdf_output_code)
+@d pdf_compress_level == int_par(pdf_compress_level_code)
+@d pdf_decimal_digits == int_par(pdf_decimal_digits_code)
+@d pdf_move_chars == int_par(pdf_move_chars_code)
+@d pdf_image_resolution == int_par(pdf_image_resolution_code)
+@d pdf_pk_resolution == int_par(pdf_pk_resolution_code)
+@d pdf_unique_resname == int_par(pdf_unique_resname_code)
+@d pdf_option_always_use_pdfpagebox == int_par(pdf_option_always_use_pdfpagebox_code)
+@d pdf_option_pdf_inclusion_errorlevel == int_par(pdf_option_pdf_inclusion_errorlevel_code)
+@d pdf_minor_version == int_par(pdf_minor_version_code)
+@d pdf_force_pagebox == int_par(pdf_force_pagebox_code)
+@d pdf_inclusion_errorlevel == int_par(pdf_inclusion_errorlevel_code)
+@d pdf_gamma == int_par(pdf_gamma_code)
+@d pdf_image_gamma == int_par(pdf_image_gamma_code)
+@d pdf_image_hicolor == int_par(pdf_image_hicolor_code)
+@d pdf_image_apply_gamma == int_par(pdf_image_apply_gamma_code)
+@d pdf_px_dimen == int_par(pdf_px_dimen_code)
+@z
+
+@x [237]
+error_context_lines_code:print_esc("errorcontextlines");
+@y
+error_context_lines_code:print_esc("errorcontextlines");
+@#
+pdf_output_code: print_esc("pdfoutput");
+pdf_compress_level_code: print_esc("pdfcompresslevel");
+pdf_decimal_digits_code: print_esc("pdfdecimaldigits");
+pdf_move_chars_code: print_esc("pdfmovechars");
+pdf_image_resolution_code: print_esc("pdfimageresolution");
+pdf_pk_resolution_code: print_esc("pdfpkresolution");
+pdf_unique_resname_code: print_esc("pdfuniqueresname");
+pdf_option_always_use_pdfpagebox_code: print_esc("pdfoptionalwaysusepdfpagebox");
+pdf_option_pdf_inclusion_errorlevel_code: print_esc("pdfoptionpdfinclusionerrorlevel");
+pdf_minor_version_code: print_esc("pdfminorversion");
+pdf_force_pagebox_code: print_esc("pdfforcepagebox");
+pdf_inclusion_errorlevel_code: print_esc("pdfinclusionerrorlevel");
+pdf_gamma_code: print_esc("pdfgamma");
+pdf_image_gamma_code: print_esc("pdfimagegamma");
+pdf_image_hicolor_code: print_esc("pdfimagehicolor");
+pdf_image_apply_gamma_code: print_esc("pdfimageapplygamma");
+pdf_px_dimen_code: print_esc("pdfpxdimen");
+@z
+
+@x [238]
+primitive("errorcontextlines",assign_int,int_base+error_context_lines_code);@/
+@!@:error_context_lines_}{\.{\\errorcontextlines} primitive@>
+@y
+primitive("errorcontextlines",assign_int,int_base+error_context_lines_code);@/
+@!@:error_context_lines_}{\.{\\errorcontextlines} primitive@>
+primitive("pdfoutput",assign_int,int_base+pdf_output_code);@/
+@!@:pdf_output_}{\.{\\pdfoutput} primitive@>
+primitive("pdfcompresslevel",assign_int,int_base+pdf_compress_level_code);@/
+@!@:pdf_compress_level_}{\.{\\pdfcompresslevel} primitive@>
+primitive("pdfdecimaldigits",assign_int,int_base+pdf_decimal_digits_code);@/
+@!@:pdf_decimal_digits_}{\.{\\pdfdecimaldigits} primitive@>
+primitive("pdfmovechars",assign_int,int_base+pdf_move_chars_code);@/
+@!@:pdf_move_chars_}{\.{\\pdfmovechars} primitive@>
+primitive("pdfimageresolution",assign_int,int_base+pdf_image_resolution_code);@/
+@!@:pdf_image_resolution_}{\.{\\pdfimageresolution} primitive@>
+primitive("pdfpkresolution",assign_int,int_base+pdf_pk_resolution_code);@/
+@!@:pdf_pk_resolution_}{\.{\\pdfpkresolution} primitive@>
+primitive("pdfuniqueresname",assign_int,int_base+pdf_unique_resname_code);@/
+@!@:pdf_unique_resname_}{\.{\\pdfuniqueresname} primitive@>
+primitive("pdfoptionpdfminorversion",assign_int,int_base+pdf_minor_version_code);@/
+@!@:pdf_minor_version_}{\.{\\pdfoptionpdfminorversion} primitive@>
+primitive("pdfoptionalwaysusepdfpagebox",assign_int,int_base+pdf_option_always_use_pdfpagebox_code);@/
+@!@:pdf_option_always_use_pdfpagebox_}{\.{\\pdfoptionalwaysusepdfpagebox} primitive@>
+primitive("pdfoptionpdfinclusionerrorlevel",assign_int,int_base+pdf_option_pdf_inclusion_errorlevel_code);@/
+@!@:pdf_option_pdf_inclusion_errorlevel_}{\.{\\pdfoptionpdfinclusionerrorlevel} primitive@>
+primitive("pdfminorversion",assign_int,int_base+pdf_minor_version_code);@/
+@!@:pdf_minor_version_}{\.{\\pdfminorversion} primitive@>
+primitive("pdfforcepagebox",assign_int,int_base+pdf_force_pagebox_code);@/
+@!@:pdf_force_pagebox_}{\.{\\pdfforcepagebox} primitive@>
+primitive("pdfinclusionerrorlevel",assign_int,int_base+pdf_inclusion_errorlevel_code);@/
+@!@:pdf_inclusion_errorlevel_}{\.{\\pdfinclusionerrorlevel} primitive@>
+primitive("pdfgamma",assign_int,int_base+pdf_gamma_code);@/
+@!@:pdf_gamma_}{\.{\\pdfgamma} primitive@>
+primitive("pdfimagegamma",assign_int,int_base+pdf_image_gamma_code);@/
+@!@:pdf_image_gamma_}{\.{\\pdfimagegamma} primitive@>
+primitive("pdfimagehicolor",assign_int,int_base+pdf_image_hicolor_code);@/
+@!@:pdf_image_hicolor_}{\.{\\pdfimagehicolor} primitive@>
+primitive("pdfimageapplygamma",assign_int,int_base+pdf_image_apply_gamma_code);@/
+@!@:pdf_image_apply_gamma_}{\.{\\pdfimageapplygamma} primitive@>
+primitive("pdfpxdimen",assign_int,int_base+pdf_px_dimen_code);@/
+@!@:pdf_px_dimen_}{\.{\\pdfpxdimen} primitive@>
+@z
+
+@x [240] - pxdimen
+for k:=int_base to del_code_base-1 do eqtb[k].int:=0;
+@y
+for k:=int_base to del_code_base-1 do eqtb[k].int:=0;
+pdf_px_dimen := unity;
+@z
+
+% Define pdftex dimension parameters
+@x [247]
+@d emergency_stretch_code=20 {reduces badnesses on final pass of line-breaking}
+@y
+@d emergency_stretch_code=20 {reduces badnesses on final pass of line-breaking}
+@d pdftex_first_dimen_code = 21 {first number defined in this section}
+@d pdf_h_origin_code = pdftex_first_dimen_code + 0 {horigin of the PDF output}
+@d pdf_v_origin_code = pdftex_first_dimen_code + 1 {vorigin of the PDF output}
+@d pdf_page_width_code = pdftex_first_dimen_code + 2 {page width of the PDF output}
+@d pdf_page_height_code = pdftex_first_dimen_code + 3 {page height of the PDF output}
+@d pdf_link_margin_code = pdftex_first_dimen_code + 4 {link margin in the PDF output}
+@d pdf_dest_margin_code = pdftex_first_dimen_code + 5 {dest margin in the PDF output}
+@d pdf_thread_margin_code = pdftex_first_dimen_code + 6 {thread margin in the PDF output}
+@d pdf_first_line_height_code = pdftex_first_dimen_code + 7
+@d pdf_last_line_depth_code = pdftex_first_dimen_code + 8
+@d pdf_each_line_height_code = pdftex_first_dimen_code + 9
+@d pdf_each_line_depth_code = pdftex_first_dimen_code + 10
+@d pdftex_last_dimen_code = pdftex_first_dimen_code + 10 {last number defined in this section}
+@z
+
+@x
+@d dimen_pars=21 {total number of dimension parameters}
+@y
+@d dimen_pars = pdftex_last_dimen_code + 1 {total number of dimension parameters}
+@z
+
+@x [247]
+@d emergency_stretch==dimen_par(emergency_stretch_code)
+@y
+@d emergency_stretch==dimen_par(emergency_stretch_code)
+@d pdf_h_origin == dimen_par(pdf_h_origin_code)
+@d pdf_v_origin == dimen_par(pdf_v_origin_code)
+@d pdf_page_width == dimen_par(pdf_page_width_code)
+@d pdf_page_height == dimen_par(pdf_page_height_code)
+@d pdf_link_margin == dimen_par(pdf_link_margin_code)
+@d pdf_dest_margin == dimen_par(pdf_dest_margin_code)
+@d pdf_thread_margin == dimen_par(pdf_thread_margin_code)
+@d pdf_first_line_height == dimen_par(pdf_first_line_height_code)
+@d pdf_last_line_depth == dimen_par(pdf_last_line_depth_code)
+@d pdf_each_line_height == dimen_par(pdf_each_line_height_code)
+@d pdf_each_line_depth == dimen_par(pdf_each_line_depth_code)
+@z
+
+@x [247]
+emergency_stretch_code:print_esc("emergencystretch");
+@y
+emergency_stretch_code:print_esc("emergencystretch");
+pdf_h_origin_code: print_esc("pdfhorigin");
+pdf_v_origin_code: print_esc("pdfvorigin");
+pdf_page_width_code: print_esc("pdfpagewidth");
+pdf_page_height_code: print_esc("pdfpageheight");
+pdf_link_margin_code: print_esc("pdflinkmargin");
+pdf_dest_margin_code: print_esc("pdfdestmargin");
+pdf_thread_margin_code: print_esc("pdfthreadmargin");
+pdf_first_line_height_code: print_esc("pdffirstlineheight");
+pdf_last_line_depth_code: print_esc("pdflastlinedepth");
+pdf_each_line_height_code: print_esc("pdfeachlineheight");
+pdf_each_line_depth_code: print_esc("pdfeachlinedepth");
+@z
+
+@x [248]
+primitive("emergencystretch",assign_dimen,dimen_base+emergency_stretch_code);@/
+@!@:emergency_stretch_}{\.{\\emergencystretch} primitive@>
+@y
+primitive("emergencystretch",assign_dimen,dimen_base+emergency_stretch_code);@/
+@!@:emergency_stretch_}{\.{\\emergencystretch} primitive@>
+primitive("pdfhorigin",assign_dimen,dimen_base+pdf_h_origin_code);@/
+@!@:pdf_h_origin_}{\.{\\pdfhorigin} primitive@>
+primitive("pdfvorigin",assign_dimen,dimen_base+pdf_v_origin_code);@/
+@!@:pdf_v_origin_}{\.{\\pdfvorigin} primitive@>
+primitive("pdfpagewidth",assign_dimen,dimen_base+pdf_page_width_code);@/
+@!@:pdf_page_width_}{\.{\\pdfpagewidth} primitive@>
+primitive("pdfpageheight",assign_dimen,dimen_base+pdf_page_height_code);@/
+@!@:pdf_page_height_}{\.{\\pdfpageheight} primitive@>
+primitive("pdflinkmargin",assign_dimen,dimen_base+pdf_link_margin_code);@/
+@!@:pdf_link_margin_}{\.{\\pdflinkmargin} primitive@>
+primitive("pdfdestmargin",assign_dimen,dimen_base+pdf_dest_margin_code);@/
+@!@:pdf_dest_margin_}{\.{\\pdfdestmargin} primitive@>
+primitive("pdfthreadmargin",assign_dimen,dimen_base+pdf_thread_margin_code);@/
+@!@:pdf_thread_margin_}{\.{\\pdfthreadmargin} primitive@>
+primitive("pdffirstlineheight",assign_dimen,dimen_base+pdf_first_line_height_code);@/
+@!@:pdf_first_line_height_}{\.{\\pdffirstlineheight} primitive@>
+primitive("pdflastlinedepth",assign_dimen,dimen_base+pdf_last_line_depth_code);@/
+@!@:pdf_last_line_depth_}{\.{\\pdflastlinedepth} primitive@>
+primitive("pdfeachlineheight",assign_dimen,dimen_base+pdf_each_line_height_code);@/
+@!@:pdf_each_line_height_}{\.{\\pdfeachlineheight} primitive@>
+primitive("pdfeachlinedepth",assign_dimen,dimen_base+pdf_each_line_depth_code);@/
+@!@:pdf_each_line_depth_}{\.{\\pdfeachlinedepth} primitive@>
+@z
+
+% Define some read-only pdfTeX primitives
+@x [416]
+|glue_val|, |input_line_no_code|, or |badness_code|.
+@y
+|glue_val|, |input_line_no_code|, or |badness_code|.
+\pdfTeX\ adds the codes for its extensions: |pdftex_version_code|, \dots\ .
+@z
+
+@x [416]
+@d badness_code=glue_val+2 {code for \.{\\badness}}
+@y
+@d badness_code=input_line_no_code+1 {code for \.{\\badness}}
+@#
+@d pdftex_first_rint_code = badness_code + 1 {base for \pdfTeX's command codes}
+@d pdftex_version_code = pdftex_first_rint_code + 0 {code for \.{\\pdftexversion}}
+@d pdf_last_obj_code = pdftex_first_rint_code + 1 {code for \.{\\pdflastobj}}
+@d pdf_last_xform_code = pdftex_first_rint_code + 2 {code for \.{\\pdflastxform}}
+@d pdf_last_ximage_code = pdftex_first_rint_code + 3 {code for \.{\\pdflastximage}}
+@d pdf_last_ximage_pages_code = pdftex_first_rint_code + 4 {code for \.{\\pdflastximagepages}}
+@d pdf_last_annot_code = pdftex_first_rint_code + 5 {code for \.{\\pdflastannot}}
+@d pdf_last_x_pos_code = pdftex_first_rint_code + 6 {code for \.{\\pdflastxpos}}
+@d pdf_last_y_pos_code = pdftex_first_rint_code + 7 {code for \.{\\pdflastypos}}
+@d pdf_retval_code = pdftex_first_rint_code + 8 {global multi-purpose return value}
+@d pdf_last_ximage_colordepth_code = pdftex_first_rint_code + 9 {code for \.{\\pdflastximagecolordepth}}
+@d elapsed_time_code = pdftex_first_rint_code + 10 {code for \.{\\pdfelapsedtime}}
+@d pdftex_last_item_codes = pdftex_first_rint_code + 10 {end of \pdfTeX's command codes}
+@z
+
+@x [416]
+primitive("badness",last_item,badness_code);
+@!@:badness_}{\.{\\badness} primitive@>
+@y
+primitive("badness",last_item,badness_code);
+@!@:badness_}{\.{\\badness} primitive@>
+primitive("pdftexversion",last_item,pdftex_version_code);@/
+@!@:pdftex_version_}{\.{\\pdftexversion} primitive@>
+primitive("pdflastobj",last_item,pdf_last_obj_code);@/
+@!@:pdf_last_obj_}{\.{\\pdflastobj} primitive@>
+primitive("pdflastxform",last_item,pdf_last_xform_code);@/
+@!@:pdf_last_xform_}{\.{\\pdflastxform} primitive@>
+primitive("pdflastximage",last_item,pdf_last_ximage_code);@/
+@!@:pdf_last_ximage_}{\.{\\pdflastximage} primitive@>
+primitive("pdflastximagepages",last_item,pdf_last_ximage_pages_code);@/
+@!@:pdf_last_ximage_pages_}{\.{\\pdflastximagepages} primitive@>
+primitive("pdflastannot",last_item,pdf_last_annot_code);@/
+@!@:pdf_last_annot_}{\.{\\pdflastannot} primitive@>
+primitive("pdflastxpos",last_item,pdf_last_x_pos_code);@/
+@!@:pdf_last_x_pos_}{\.{\\pdflastxpos} primitive@>
+primitive("pdflastypos",last_item,pdf_last_y_pos_code);@/
+@!@:pdf_last_y_pos_}{\.{\\pdflastypos} primitive@>
+primitive("pdfretval",last_item,pdf_retval_code);@/
+@!@:pdf_retval_}{\.{\\pdfretval} primitive@>
+primitive("pdflastximagecolordepth",last_item,pdf_last_ximage_colordepth_code);@/
+@!@:pdf_last_ximage_colordepth_}{\.{\\pdflastximagecolordepth} primitive@>
+primitive("pdfelapsedtime",last_item,elapsed_time_code);
+@!@:elapsed_time_}{\.{\\pdfelapsedtime} primitive@>
+@z
+
+@x [417]
+ othercases print_esc("badness")
+@y
+ pdftex_version_code: print_esc("pdftexversion");
+ pdf_last_obj_code: print_esc("pdflastobj");
+ pdf_last_xform_code: print_esc("pdflastxform");
+ pdf_last_ximage_code: print_esc("pdflastximage");
+ pdf_last_ximage_pages_code: print_esc("pdflastximagepages");
+ pdf_last_annot_code: print_esc("pdflastannot");
+ pdf_last_x_pos_code: print_esc("pdflastxpos");
+ pdf_last_y_pos_code: print_esc("pdflastypos");
+ pdf_retval_code: print_esc("pdfretval");
+ pdf_last_ximage_colordepth_code: print_esc("pdflastximagecolordepth");
+ elapsed_time_code: print_esc("pdfelapsedtime");
+ othercases print_esc("badness")
+@z
+
+@x [424]
+if cur_chr>glue_val then
+@y
+if m>=input_line_no_code then
+@z
+
+@x [424]
+ begin if cur_chr=input_line_no_code then cur_val:=line
+ else cur_val:=last_badness; {|cur_chr=badness_code|}
+@y
+ begin case m of
+ input_line_no_code: cur_val:=line;
+ badness_code: cur_val:=last_badness;
+ pdftex_version_code: cur_val := pdftex_version;
+ pdf_last_obj_code: cur_val := pdf_last_obj;
+ pdf_last_xform_code: cur_val := pdf_last_xform;
+ pdf_last_ximage_code: cur_val := pdf_last_ximage;
+ pdf_last_ximage_pages_code: cur_val := pdf_last_ximage_pages;
+ pdf_last_annot_code: cur_val := pdf_last_annot;
+ pdf_last_x_pos_code: cur_val := pdf_last_x_pos;
+ pdf_last_y_pos_code: cur_val := pdf_last_y_pos;
+ pdf_retval_code: cur_val := pdf_retval;
+ pdf_last_ximage_colordepth_code: cur_val := pdf_last_ximage_colordepth;
+ elapsed_time_code: cur_val := get_microinterval;
+ end; {there are no other cases}
+@z
+
+@x [455] - pxdimen
+else if scan_keyword("ex") then v:=(@<The x-height for |cur_font|@>)
+@.ex@>
+@y
+else if scan_keyword("ex") then v:=(@<The x-height for |cur_font|@>)
+@.ex@>
+else if scan_keyword("px") then v:=pdf_px_dimen
+@.px@>
+@z
+
+@x new Didot (1nd=0.375mm), new Cicero (1nc=12nd)
+@ The necessary conversion factors can all be specified exactly as
+fractions whose numerator and denominator are 32768 or less.
+According to the definitions here, $\rm2660\,dd\approx1000.33297\,mm$;
+this agrees well with the value $\rm1000.333\,mm$ cited by Bosshard
+@^Bosshard, Hans Rudolf@>
+in {\sl Technische Grundlagen zur Satzherstellung\/} (Bern, 1980).
+@y
+@ The necessary conversion factors can all be specified exactly as
+fractions whose numerator and denominator are 65535 or less.
+According to the definitions here, $\rm2660\,dd\approx1000.33297\,mm$;
+this agrees well with the value $\rm1000.333\,mm$ cited by Bosshard
+@^Bosshard, Hans Rudolf@>
+in {\sl Technische Grundlagen zur Satzherstellung\/} (Bern, 1980).
+The Didot point has been newly standardized in 1978;
+it's now exactly $\rm 1\,nd=0.375\,mm$.
+Conversion uses the equation $0.375=21681/20320/72.27\cdot25.4$.
+The new Cicero follows the new Didot point; $\rm 1\,nc=12\,nd$.
+@z
+
+@x new Didot (1nd=0.375mm), new Cicero (1nc=12nd)
+else if scan_keyword("cc") then set_conversion(14856)(1157)
+@.cc@>
+@y
+else if scan_keyword("cc") then set_conversion(14856)(1157)
+@.cc@>
+else if scan_keyword("nd") then set_conversion(21681)(20320)
+@.nd@>
+else if scan_keyword("nc") then set_conversion(65043)(5080)
+@.nc@>
+@z
+
+@x new Didot (1nd=0.375mm), new Cicero (1nc=12nd)
+ ("cm, mm, dd, cc, bp, or sp; but yours is a new one!")@/
+@y
+ ("cm, mm, dd, cc, nd, nc, bp, or sp; but yours is a new one!")@/
+@z
+
+% Define some char token producing pdfTeX primitives
+@x [468]
+@d number_code=0 {command code for \.{\\number}}
+@y
+\pdfTeX\ adds \.{\\eTeXrevision}, \.{\\pdftexrevision}, \.{\\pdftexbanner},
+\.{\\pdffontname}, \.{\\pdffontobjnum}, \.{\\pdffontsize}, and \.{\\pdfpageref}
+such that |job_name_code| remains last.
+
+@d number_code=0 {command code for \.{\\number}}
+@z
+
+@x [468]
+@d job_name_code=5 {command code for \.{\\jobname}}
+@y
+@d pdftex_first_expand_code = 5 {base for \pdfTeX's command codes}
+@d pdftex_revision_code = pdftex_first_expand_code + 0 {command code for \.{\\pdftexrevision}}
+@d pdftex_banner_code = pdftex_first_expand_code + 1 {command code for \.{\\pdftexbanner}}
+@d pdf_font_name_code = pdftex_first_expand_code + 2 {command code for \.{\\pdffontname}}
+@d pdf_font_objnum_code = pdftex_first_expand_code + 3 {command code for \.{\\pdffontobjnum}}
+@d pdf_font_size_code = pdftex_first_expand_code + 4 {command code for \.{\\pdffontsize}}
+@d pdf_page_ref_code = pdftex_first_expand_code + 5 {command code for \.{\\pdfpageref}}
+@d pdf_xform_name_code = pdftex_first_expand_code + 6 {command code for \.{\\pdfxformname}}
+@d pdf_last_escaped_string_code = pdftex_first_expand_code + 7 {command code for \.{\\pdflastescapedstring}}
+@d pdf_last_escaped_name_code = pdftex_first_expand_code + 8 {command code for \.{\\pdflastescapename}}
+@d pdftex_convert_codes = pdftex_first_expand_code + 9 {end of \pdfTeX's command codes}
+@d job_name_code=pdftex_convert_codes {command code for \.{\\jobname}}
+@z
+
+@x [468]
+primitive("jobname",convert,job_name_code);@/
+@y
+@#
+primitive("pdftexrevision",convert,pdftex_revision_code);@/
+@!@:pdftex_revision_}{\.{\\pdftexrevision} primitive@>
+primitive("pdftexbanner",convert,pdftex_banner_code);@/
+@!@:pdftex_banner_}{\.{\\pdftexbanner} primitive@>
+primitive("pdffontname",convert,pdf_font_name_code);@/
+@!@:pdf_font_name_}{\.{\\pdffontname} primitive@>
+primitive("pdffontobjnum",convert,pdf_font_objnum_code);@/
+@!@:pdf_font_objnum_}{\.{\\pdffontobjnum} primitive@>
+primitive("pdffontsize",convert,pdf_font_size_code);@/
+@!@:pdf_font_size_}{\.{\\pdffontsize} primitive@>
+primitive("pdfpageref",convert,pdf_page_ref_code);@/
+@!@:pdf_page_ref_}{\.{\\pdfpageref} primitive@>
+primitive("pdfxformname",convert,pdf_xform_name_code);@/
+@!@:pdf_xform_name_}{\.{\\pdfxformname} primitive@>
+primitive("pdflastescapedstring",convert,pdf_last_escaped_string_code);@/
+@!@:pdf_last_escaped_string_}{\.{\\pdflastescapedstring} primitive@>
+primitive("pdflastescapedname",convert,pdf_last_escaped_name_code);@/
+@!@:pdf_last_escaped_name_}{\.{\\pdflastescapedname} primitive@>
+@#
+primitive("jobname",convert,job_name_code);@/
+@z
+
+@x [469]
+ othercases print_esc("jobname")
+@y
+ pdftex_revision_code: print_esc("pdftexrevision");
+ pdftex_banner_code: print_esc("pdftexbanner");
+ pdf_font_name_code: print_esc("pdffontname");
+ pdf_font_objnum_code: print_esc("pdffontobjnum");
+ pdf_font_size_code: print_esc("pdffontsize");
+ pdf_page_ref_code: print_esc("pdfpageref");
+ pdf_xform_name_code: print_esc("pdfxformname");
+ pdf_last_escaped_string_code: print_esc("pdflastescapedstring");
+ pdf_last_escaped_name_code: print_esc("pdflastescapedname");
+ othercases print_esc("jobname")
+@z
+
+@x [465] - pdfescapestring
+@!b:pool_pointer; {base of temporary string}
+@y
+@!b:pool_pointer; {base of temporary string}
+@!i, l: integer; {index to access escaped string or name}
+@z
+
+@x [471]
+job_name_code: if job_name=0 then open_log_file;
+@y
+pdftex_revision_code: do_nothing;
+pdftex_banner_code: do_nothing;
+pdf_font_name_code, pdf_font_objnum_code, pdf_font_size_code: begin
+ scan_font_ident;
+ if cur_val = null_font then
+ pdf_error("font", "invalid font identifier");
+ if c <> pdf_font_size_code then begin
+ pdf_check_vf(cur_val);
+ if not font_used[cur_val] then
+ pdf_init_font(cur_val);
+ end;
+end;
+pdf_page_ref_code: begin
+ scan_int;
+ if cur_val <= 0 then
+ pdf_error("pageref", "invalid page number");
+end;
+pdf_xform_name_code: begin
+ scan_int;
+ pdf_check_obj(obj_type_xform, cur_val);
+end;
+pdf_last_escaped_string_code: do_nothing;
+pdf_last_escaped_name_code: do_nothing;
+job_name_code: if job_name=0 then open_log_file;
+@z
+
+@x [472]
+job_name_code: print(job_name);
+@y
+pdftex_revision_code: print(pdftex_revision);
+pdftex_banner_code: print(pdftex_banner);
+pdf_font_name_code, pdf_font_objnum_code: begin
+ set_ff(cur_val);
+ if c = pdf_font_name_code then
+ print_int(obj_info(pdf_font_num[ff]))
+ else
+ print_int(pdf_font_num[ff]);
+end;
+pdf_font_size_code: begin
+ print_scaled(font_size[cur_val]);
+ print("pt");
+end;
+pdf_page_ref_code: print_int(get_obj(obj_type_page, cur_val, false));
+pdf_xform_name_code: print_int(obj_info(cur_val));
+pdf_last_escaped_string_code: begin
+ l := escapedstrlen;
+ for i := 0 to l - 1 do
+ print_char(getescapedstrchar(i));
+end;
+pdf_last_escaped_name_code: begin
+ l := escapednamelen;
+ for i := 0 to l - 1 do
+ print_char(getescapednamechar(i));
+end;
+job_name_code: print(job_name);
+@z
+
+@x [577] - tagcode
+@<Declare procedures that scan font-related stuff@>=
+procedure scan_font_ident;
+@y
+@<Declare procedures that scan font-related stuff@>=
+function get_tag_code(f: internal_font_number; c: eight_bits): integer;
+var i:small_number;
+begin
+ if is_valid_char(c) then
+ begin i := char_tag(char_info(f)(c));
+ if i = lig_tag then
+ get_tag_code := 1
+ else if i = list_tag then
+ get_tag_code := 2
+ else if i = ext_tag then
+ get_tag_code := 4
+ else
+ get_tag_code := 0;
+ end
+ else
+ get_tag_code := -1;
+end;
+procedure scan_font_ident;
+@z
+
+% Shipping out to PDF
+@x [638]
+@ The |hlist_out| and |vlist_out| procedures are now complete, so we are
+ready for the |ship_out| routine that gets them started in the first place.
+
+@p procedure ship_out(@!p:pointer); {output the box |p|}
+@y
+@ The |hlist_out| and |vlist_out| procedures are now complete, so we are
+ready for the |dvi_ship_out| routine that gets them started in the first place.
+
+@p procedure dvi_ship_out(@!p:pointer); {output the box |p|}
+@z
+
+@x [644]
+@* \[33] Packaging.
+@y
+
+@* \[32a] \pdfTeX\ basic.
+
+Initialize pdftex's parameters to some useful default value.
+Helpful in case one forgets to set them during initex run.
+
+@<Initialize table entries...@>=
+pdf_h_origin := (one_hundred_inch + 50) div 100;
+pdf_v_origin := (one_hundred_inch + 50) div 100;
+pdf_compress_level := 9;
+pdf_decimal_digits := 4;
+pdf_image_resolution := 72;
+pdf_minor_version := 4;
+pdf_gamma := 1000;
+pdf_image_gamma := 2200;
+pdf_image_hicolor := 1;
+pdf_image_apply_gamma := 0;
+
+@ The subroutines define the corresponding macros so we can use them
+in C.
+
+@d flushable(#) == (# = str_ptr - 1)
+
+@d is_valid_char(#)==((font_bc[f] <= #) and (# <= font_ec[f]) and
+ char_exists(char_info(f)(#)))
+
+@p function get_pdf_compress_level: integer;
+begin
+ get_pdf_compress_level := pdf_compress_level;
+end;
+
+function get_nullfont: internal_font_number;
+begin
+ get_nullfont := null_font;
+end;
+
+function get_nullcs: pointer;
+begin
+ get_nullcs := null_cs;
+end;
+
+function get_nullptr: pointer;
+begin
+ get_nullptr := null;
+end;
+
+function get_tex_int(code: integer): integer;
+begin
+ get_tex_int := int_par(code);
+end;
+
+function get_tex_dimen(code: integer): scaled;
+begin
+ get_tex_dimen := dimen_par(code);
+end;
+
+function get_x_height(f: internal_font_number): scaled;
+begin
+ get_x_height := x_height(f);
+end;
+
+function get_charwidth(f: internal_font_number; c: eight_bits): scaled;
+begin
+ if is_valid_char(c) then
+ get_charwidth := char_width(f)(char_info(f)(c))
+ else
+ get_charwidth := 0;
+end;
+
+function get_charheight(f: internal_font_number; c: eight_bits): scaled;
+begin
+ if is_valid_char(c) then
+ get_charheight := char_height(f)(height_depth(char_info(f)(c)))
+ else
+ get_charheight := 0;
+end;
+
+function get_chardepth(f: internal_font_number; c: eight_bits): scaled;
+begin
+ if is_valid_char(c) then
+ get_chardepth := char_depth(f)(height_depth(char_info(f)(c)))
+ else
+ get_chardepth := 0;
+end;
+
+function get_quad(f: internal_font_number): scaled;
+begin
+ get_quad := quad(f);
+end;
+
+function get_slant(f: internal_font_number): scaled;
+begin
+ get_slant := slant(f);
+end;
+
+function new_dummy_font: internal_font_number;
+begin
+ new_dummy_font := read_font_info(null_cs, "dummy", "", -1000);
+end;
+
+@ Helper for debugging purposes
+
+@p procedure short_display_n(@!p, m:integer); {prints highlights of list |p|}
+var n:integer; {for replacement counts}
+ i: integer;
+begin
+i := 0;
+font_in_short_display:=null_font;
+if p = null then
+ return;
+while p>mem_min do
+ begin if is_char_node(p) then
+ begin if p<=mem_end then
+ begin if font(p)<>font_in_short_display then
+ begin if (font(p)<font_base)or(font(p)>font_max) then
+ print_char("*")
+@.*\relax@>
+ else @<Print the font identifier for |font(p)|@>;
+ print_char(" "); font_in_short_display:=font(p);
+ end;
+ print_ASCII(qo(character(p)));
+ end;
+ end
+ else begin
+ if (type(p) = glue_node) or
+ (type(p) = disc_node) or
+ (type(p) = penalty_node) or
+ ((type(p) = kern_node) and (subtype(p) = explicit)) then
+ incr(i);
+ if i >= m then
+ return;
+ if (type(p) = disc_node) then begin
+ print("|");
+ short_display(pre_break(p));
+ print("|");
+ short_display(post_break(p));
+ print("|");
+ n:=replace_count(p);
+ while n>0 do
+ begin if link(p)<>null then p:=link(p);
+ decr(n);
+ end;
+ end
+ else
+ @<Print a short indication of the contents of node |p|@>;
+ end;
+ p:=link(p);
+ if p = null then
+ return;
+ end;
+ update_terminal;
+end;
+
+@ Sometimes it is neccesary to allocate memory for PDF output that cannot
+be deallocated then, so we use |pdf_mem| for this purpose.
+
+@<Constants...@>=
+@!inf_pdf_mem_size = 10000; {min size of the |pdf_mem| array}
+@!sup_pdf_mem_size = 10000000; {max size of the |pdf_mem| array}
+
+@ @<Glob...@>=
+@!pdf_mem_size: integer;
+@!pdf_mem: ^integer;
+@!pdf_mem_ptr: integer;
+
+@ @<Set init...@>=
+pdf_mem_ptr := 1; {the first word is not used so we can use zero as a value for testing
+whether a pointer to |pdf_mem| is valid}
+pdf_mem_size := inf_pdf_mem_size; {allocated size of |pdf_mem| array}
+
+@ We use |pdf_get_mem| to allocate memory in |pdf_mem|
+
+@p function pdf_get_mem(s: integer): integer; {allocate |s| words in |pdf_mem|}
+var a: integer;
+begin
+ if s > sup_pdf_mem_size - pdf_mem_size then
+ overflow("PDF memory size (pdf_mem_size)", pdf_mem_size);
+ if pdf_mem_ptr + s > pdf_mem_size then begin
+ a := 0.2 * pdf_mem_size;
+ if pdf_mem_ptr + s > pdf_mem_size + a then
+ pdf_mem_size := pdf_mem_ptr + s
+ else if pdf_mem_size < sup_pdf_mem_size - a then
+ pdf_mem_size := pdf_mem_size + a
+ else
+ pdf_mem_size := sup_pdf_mem_size;
+ pdf_mem := xrealloc_array(pdf_mem, integer, pdf_mem_size);
+ end;
+ pdf_get_mem := pdf_mem_ptr;
+ pdf_mem_ptr := pdf_mem_ptr + s;
+end;
+
+@* \[32b] \pdfTeX\ output low-level subroutines.
+We use the similiar subroutines to handle the output buffer for
+PDF output. When compress is used, the state of writing to buffer
+is held in |zip_write_state|. We must write the header of PDF
+output file in initialization to ensure that it will be the first
+written bytes.
+
+@<Constants...@>=
+@!pdf_buf_size = 16384; {size of the PDF buffer}
+
+@ The following macros are similar as for \.{DVI} buffer handling
+
+@d pdf_offset == (pdf_gone + pdf_ptr) {the file offset of last byte in PDF
+buffer that |pdf_ptr| points to}
+
+@d no_zip == 0 {no \.{ZIP} compression}
+@d zip_writing == 1 {\.{ZIP} compression being used}
+@d zip_finish == 2 {finish \.{ZIP} compression}
+
+@d pdf_quick_out(#) == {output a byte to PDF buffer without checking of
+overflow}
+begin
+ pdf_buf[pdf_ptr] := #;
+ incr(pdf_ptr);
+end
+
+@d pdf_room(#) == {make sure that there are at least |n| bytes free in PDF
+buffer}
+begin
+ if pdf_buf_size < # then
+ overflow("PDF output buffer", pdf_buf_size);
+ if pdf_ptr + # > pdf_buf_size then
+ pdf_flush;
+end
+
+@d pdf_out(#) == {do the same as |pdf_quick_out| and flush the PDF
+buffer if necessary}
+begin
+ if pdf_ptr > pdf_buf_size then
+ pdf_flush;
+ pdf_quick_out(#);
+end
+
+@<Glob...@>=
+@!pdf_file: byte_file; {the PDF output file}
+@!pdf_buf: array[0..pdf_buf_size] of eight_bits; {the PDF buffer}
+@!pdf_ptr: integer; {pointer to the first unused byte in the PDF buffer}
+@!pdf_gone: integer; {number of bytes that were flushed to output}
+@!pdf_save_offset: integer; {to save |pdf_offset|}
+@!zip_write_state: integer; {which state of compression we are in}
+@!fixed_pdf_minor_version: integer; {fixed minor part of the pdf version}
+@!pdf_minor_version_written: boolean; {flag if the pdf version has been written}
+@!fixed_pdfoutput: integer; {fixed output format}
+@!fixed_pdfoutput_set: boolean; {|fixed_pdfoutput| has been set?}
+@!fixed_gamma: integer;
+@!fixed_image_gamma: integer;
+@!fixed_image_hicolor: boolean;
+@!fixed_image_apply_gamma: integer;
+@!epochseconds: integer;
+@!microseconds: integer;
+
+@ @<Set init...@>=
+pdf_buf[0] := "%";
+pdf_buf[1] := "P";
+pdf_buf[2] := "D";
+pdf_buf[3] := "F";
+pdf_buf[4] := "-";
+pdf_buf[5] := "1";
+pdf_buf[6] := ".";
+pdf_buf[7] := "4";
+pdf_buf[8] := pdf_new_line_char;
+pdf_buf[9] := "%";
+pdf_buf[10] := 208;
+pdf_buf[11] := 212;
+pdf_buf[12] := 197;
+pdf_buf[13] := 216;
+pdf_buf[14] := pdf_new_line_char;
+pdf_ptr := 15;
+pdf_gone := 0;
+zip_write_state := no_zip;
+pdf_minor_version_written := false;
+fixed_pdfoutput_set := false;
+fixed_gamma := 1000;
+fixed_image_gamma := 2200;
+fixed_image_hicolor := 1;
+fixed_image_apply_gamma := 0;
+
+@ @p
+function fix_int(val, min, max: integer): integer;
+begin
+ if val < min then
+ fix_int := min
+ else if val > max then
+ fix_int := max
+ else
+ fix_int := val;
+end;
+
+@ This checks that |pdfminorversion| can only be set before any
+bytes have been written to the generated pdf file. It should be called
+directly after every |ensure_pdf_open|.
+
+@p procedure check_pdfminorversion;
+begin
+ if not pdf_minor_version_written then begin
+ pdf_minor_version_written := true;
+ if (pdf_minor_version < 0) or (pdf_minor_version > 9) then begin
+ print_err("pdfTeX error (illegal pdfminorversion)");
+ print_ln;
+ help2 ("The pdfminorversion must be between 0 and 9.")@/
+ ("I changed this to 4.");
+ int_error (pdf_minor_version);
+ pdf_minor_version := 4;
+ end;
+ fixed_pdf_minor_version := pdf_minor_version;
+ pdf_buf[7] := chr(ord("0") + fixed_pdf_minor_version);
+ fixed_gamma := fix_int(pdf_gamma, 0, 1000000);
+ fixed_image_gamma := fix_int(pdf_image_gamma, 0, 1000000);
+ fixed_image_hicolor := fix_int(pdf_image_hicolor, 0, 1);
+ fixed_image_apply_gamma := fix_int(pdf_image_apply_gamma, 0, 1);
+ end
+ else begin
+ if fixed_pdf_minor_version <> pdf_minor_version then
+ pdf_error("setup",
+ "\pdfminorversion cannot be changed after data is written to the pdf file");
+ end;
+end;
+
+@ Checks that we have a name for the generated pdf file and that it's open.
+|check_pdfminorversion| should be called directly
+hereafter.
+
+@p procedure ensure_pdf_open;
+begin
+ if output_file_name <> 0 then
+ return;
+ if job_name = 0 then
+ open_log_file;
+ pack_job_name(".pdf");
+ while not b_open_out(pdf_file) do
+ prompt_file_name("file name for output",".pdf");
+ output_file_name := b_make_name_string(pdf_file);
+end;
+
+@ The PDF buffer is flushed by calling |pdf_flush|, which checks the
+variable |zip_write_state| and will compress the buffer before flushing if
+neccesary. We call |pdf_begin_stream| to begin a stream and |pdf_end_stream|
+to finish it. The stream contents will be compressed if compression is turn on.
+
+@p procedure pdf_flush; {flush out the |pdf_buf|}
+begin
+ ensure_pdf_open;
+ check_pdfminorversion;
+ case zip_write_state of
+ no_zip: if pdf_ptr > 0 then begin
+ write_pdf(0, pdf_ptr - 1);
+ pdf_gone := pdf_gone + pdf_ptr;
+ end;
+ zip_writing:
+ write_zip(false);
+ zip_finish: begin
+ write_zip(true);
+ zip_write_state := no_zip;
+ end;
+ end;
+ pdf_ptr := 0;
+end;
+
+procedure pdf_begin_stream; {begin a stream}
+begin
+ ensure_pdf_open;
+ check_pdfminorversion;
+ pdf_print_ln("/Length ");
+ pdf_stream_length_offset := pdf_offset - 11;
+ pdf_stream_length := 0;
+ if pdf_compress_level > 0 then begin
+ pdf_print_ln("/Filter /FlateDecode");
+ pdf_print_ln(">>");
+ pdf_print_ln("stream");
+ pdf_flush;
+ zip_write_state := zip_writing;
+ end
+ else begin
+ pdf_print_ln(">>");
+ pdf_print_ln("stream");
+ pdf_save_offset := pdf_offset;
+ end;
+end;
+
+procedure pdf_end_stream; {end a stream}
+begin
+ if pdf_compress_level > 0 then
+ zip_write_state := zip_finish
+ else
+ pdf_stream_length := pdf_offset - pdf_save_offset;
+ pdf_flush;
+ write_stream_length(pdf_stream_length, pdf_stream_length_offset);
+ if pdf_compress_level > 0 then
+ pdf_out(pdf_new_line_char);
+ pdf_print_ln("endstream");
+ pdf_end_obj;
+end;
+
+@ Basic printing procedures for PDF output are very similiar to \TeX\ basic
+printing ones but the output is going to PDF buffer. Subroutines with
+suffix |_ln| append a new-line character to the PDF output.
+
+@d pdf_new_line_char == 10 {new-line character for UNIX platforms}
+
+@d pdf_print_nl == {output a new-line character to PDF buffer}
+if (pdf_ptr > 0) and (pdf_buf[pdf_ptr - 1] <> pdf_new_line_char) then
+ pdf_out(pdf_new_line_char)
+
+@d pdf_print_ln(#) == {print out a string to PDF buffer followed by
+a new-line character}
+begin
+ pdf_print(#);
+ pdf_print_nl;
+end
+
+@d pdf_print_int_ln(#) == {print out an integer to PDF buffer followed by
+a new-line character}
+begin
+ pdf_print_int(#);
+ pdf_print_nl;
+end
+
+@<Declare procedures that need to be declared forward for pdftex@>=
+procedure pdf_error(t, p: str_number);
+begin
+ normalize_selector;
+ print_err("pdfTeX error");
+ if t <> 0 then begin
+ print(" (");
+ print(t);
+ print(")");
+ end;
+ print(": "); print(p);
+ succumb;
+end;
+
+procedure pdf_warning(t, p: str_number; append_nl: boolean);
+begin
+ print_err("pdfTeX warning");
+ if t <> 0 then begin
+ print(" (");
+ print(t);
+ print(")");
+ end;
+ print(": "); print(p);
+ if append_nl then
+ print_ln;
+end;
+
+procedure remove_last_space;
+begin
+ if (pdf_ptr > 0) and (pdf_buf[pdf_ptr - 1] = 32) then
+ decr(pdf_ptr);
+end;
+
+procedure pdf_print_octal(n: integer); {prints an integer in octal form to
+PDF buffer}
+var k:0..23; {index to current digit; we assume that $|n|<10^{23}$}
+begin
+ k:=0;
+ repeat dig[k]:=n mod 8; n:=n div 8; incr(k);
+ until n=0;
+ if k = 1 then begin
+ pdf_out("0");
+ pdf_out("0");
+ end;
+ if k = 2 then
+ pdf_out("0");
+ while k>0 do begin
+ decr(k);
+ pdf_out("0"+dig[k]);
+ end;
+end;
+
+procedure pdf_print_char(f: internal_font_number; c: integer);
+{ print out a character to PDF buffer; the character will be printed in octal
+ form in the following cases: chars <= 32, backslash (92), left parenthesis
+ (40) and right parenthesis (41) }
+begin
+ if c <= 32 then
+ c := pdf_char_map[f, c];
+ pdf_mark_char(f, c);
+ if (c <= 32) or (c = 92) or (c = 40) or (c = 41) or (c > 127) then begin
+ pdf_out(92); {output a backslash}
+ pdf_print_octal(c);
+ end
+ else
+ pdf_out(c);
+end;
+
+procedure pdf_print(s: str_number); {print out a string to PDF buffer}
+var j: pool_pointer; {current character code position}
+ c: integer;
+begin
+ j := str_start[s];
+ while j < str_start[s + 1] do begin
+ c := str_pool[j];
+ pdf_out(c);
+ incr(j);
+ end;
+end;
+
+function str_in_str(s, r: str_number; i: integer): boolean;
+ {test equality of strings}
+label not_found; {loop exit}
+var j, k: pool_pointer; {running indices}
+@!result: boolean; {result of comparison}
+begin
+ str_in_str := false;
+ if length(s) < i + length(r) then
+ return;
+ j := i + str_start[s];
+ k := str_start[r];
+ while (j < str_start[s + 1]) and (k < str_start[r + 1]) do begin
+ if str_pool[j] <> str_pool[k] then
+ return;
+ incr(j);
+ incr(k);
+ end;
+ str_in_str := true;
+end;
+
+procedure literal(s: str_number; literal_mode: integer; warn: boolean);
+var j: pool_pointer; {current character code position}
+begin
+ j:=str_start[s];
+ if literal_mode = scan_special then begin
+ if not (str_in_str(s, "PDF:", 0) or str_in_str(s, "pdf:", 0)) then begin
+ if warn and not (str_in_str(s, "SRC:", 0)
+ or str_in_str(s, "src:", 0)
+ or (length(s) = 0)) then
+ print_nl("Non-PDF special ignored!");
+ return;
+ end;
+ j := j + length("PDF:");
+ if str_in_str(s, "direct:", length("PDF:")) then begin
+ j := j + length("direct:");
+ literal_mode := direct_always; end
+ else if str_in_str(s, "page:", length("PDF:")) then begin
+ j := j + length("page:");
+ literal_mode := direct_page; end
+ else
+ literal_mode := reset_origin;
+ end;
+ case literal_mode of
+ reset_origin: begin
+ pdf_end_text;
+ pdf_set_origin;
+ end;
+ direct_page:
+ pdf_end_text;
+ direct_always: begin
+ pdf_first_space_corr := 0;
+ pdf_end_string;
+ pdf_print_nl;
+ end;
+ othercases confusion("literal1")
+ endcases;
+ while j<str_start[s+1] do begin
+ pdf_out(str_pool[j]);
+ incr(j);
+ end;
+ pdf_print_nl;
+end;
+
+procedure pdf_print_int(n:integer); {print out a integer to PDF buffer}
+var k:integer; {index to current digit ($0\le k\le23$); we assume that $|n|<10^{23}$}
+m:integer; {used to negate |n| in possibly dangerous cases}
+begin
+ k:=0;
+ if n<0 then
+ begin pdf_out("-");
+ if n>-100000000 then negate(n)
+ else begin m:=-1-n; n:=m div 10; m:=(m mod 10)+1; k:=1;
+ if m<10 then dig[0]:=m
+ else begin dig[0]:=0; incr(n);
+ end;
+ end;
+ end;
+ repeat dig[k]:=n mod 10; n:=n div 10; incr(k);
+ until n=0;
+ pdf_room(k);
+ while k>0 do begin
+ decr(k);
+ pdf_quick_out("0"+dig[k]);
+ end;
+end;
+
+procedure pdf_print_two(n:integer); {prints two least significant digits in
+decimal form to PDF buffer}
+begin n:=abs(n) mod 100; pdf_out("0"+(n div 10));
+pdf_out("0"+(n mod 10));
+end;
+
+function tokens_to_string(p: pointer): str_number; {return a string from tokens
+list}
+begin
+ if selector = new_string then
+ pdf_error("tokens", "tokens_to_string() called while selector = new_string");
+ old_setting:=selector; selector:=new_string;
+ show_token_list(link(p),null,pool_size-pool_ptr);
+ selector:=old_setting;
+ last_tokens_string := make_string;
+ tokens_to_string := last_tokens_string;
+end;
+
+
+@ To print |scaled| value to PDF output we need some subroutines to ensure
+accurary.
+
+@d max_integer == @"7FFFFFFF {$2^{31}-1$}
+@d call_func(#) == begin if # <> 0 then do_nothing end
+
+@<Glob...@>=
+@!one_bp: scaled; {scaled value corresponds to 1bp}
+@!one_hundred_bp: scaled; {scaled value corresponds to 100bp}
+@!one_hundred_inch: scaled; {scaled value corresponds to 100in}
+@!ten_pow: array[0..9] of integer; {$10^0..10^9$}
+@!scaled_out: integer; {amount of |scaled| that was taken out in
+|divide_scaled|}
+@!init_pdf_output: boolean;
+
+@ @<Set init...@>=
+one_bp := 65782; {65781.76}
+one_hundred_bp := 6578176;
+one_hundred_inch := 473628672;
+ten_pow[0] := 1;
+for i := 1 to 9 do
+ ten_pow[i] := 10*ten_pow[i - 1];
+init_pdf_output := false;
+
+
+@ The following function divides |s| by |m|. |dd| is number of decimal digits.
+
+@<Declare procedures that need to be declared forward for pdftex@>=
+function divide_scaled(s, m: scaled; dd: integer): scaled;
+var q, r: scaled;
+ sign, i: integer;
+begin
+ sign := 1;
+ if s < 0 then begin
+ sign := -sign;
+ s := -s;
+ end;
+ if m < 0 then begin
+ sign := -sign;
+ m := -m;
+ end;
+ if m = 0 then
+ pdf_error("arithmetic", "divided by zero")
+ else if m >= (max_integer div 10) then
+ pdf_error("arithmetic", "number too big");
+ q := s div m;
+ r := s mod m;
+ for i := 1 to dd do begin
+ q := 10*q + (10*r) div m;
+ r := (10*r) mod m;
+ end;
+ if 2*r >= m then begin
+ incr(q);
+ r := r - m;
+ end;
+ scaled_out := sign*(s - (r div ten_pow[dd]));
+ divide_scaled := sign*q;
+end;
+
+function round_xn_over_d(@!x:scaled; @!n,@!d:integer):scaled;
+var positive:boolean; {was |x>=0|?}
+@!t,@!u,@!v:nonnegative_integer; {intermediate quantities}
+begin if x>=0 then positive:=true
+else begin negate(x); positive:=false;
+ end;
+t:=(x mod @'100000)*n;
+u:=(x div @'100000)*n+(t div @'100000);
+v:=(u mod d)*@'100000 + (t mod @'100000);
+if u div d>=@'100000 then arith_error:=true
+else u:=@'100000*(u div d) + (v div d);
+v := v mod d;
+if 2*v >= d then
+ incr(u);
+if positive then
+ round_xn_over_d := u
+else
+ round_xn_over_d := -u;
+end;
+
+
+@ Next subroutines are needed for controling spacing in PDF page description.
+The procedure |adv_char_width| advances |pdf_h| by the amount |w|, which is
+the character width. We cannot simply add |w| to |pdf_h|, but must
+calculate the amount corresponding to |w| in the PDF output. For PK fonts
+things are more complicated, as we have to deal with scaling bitmaps as well.
+
+@p
+procedure adv_char_width(f: internal_font_number; w: scaled); {update |pdf_h|
+by character width |w| from font |f|}
+begin
+ if hasfmentry(f) then begin
+ call_func(divide_scaled(w, pdf_font_size[f], 3));
+ pdf_h := pdf_h + scaled_out;
+ end
+ else
+ pdf_h := pdf_h + get_pk_char_width(f, w);
+end;
+
+procedure pdf_print_real(m, d: integer); {print $m/10^d$ as real}
+var n: integer;
+begin
+ if m < 0 then begin
+ pdf_out("-");
+ m := -m;
+ end;
+ n := ten_pow[d];
+ pdf_print_int(m div n);
+ m := m mod n;
+ if m > 0 then begin
+ pdf_out(".");
+ n := n div 10;
+ while m < n do begin
+ pdf_out("0");
+ n := n div 10;
+ end;
+ while m mod 10 = 0 do
+ m := m div 10;
+ pdf_print_int(m);
+ end;
+end;
+
+procedure pdf_print_bp(s: scaled); {print scaled as |bp|}
+begin
+ pdf_print_real(divide_scaled(s, one_hundred_bp, fixed_decimal_digits + 2),
+ fixed_decimal_digits);
+end;
+
+procedure pdf_print_mag_bp(s: scaled); {take |mag| into account}
+begin
+ prepare_mag;
+ if mag <> 1000 then
+ s := round_xn_over_d(s, mag, 1000);
+ pdf_print_bp(s);
+end;
+
+@* \[32c] PDF page description.
+
+@d pdf_x(#) == ((#) - pdf_origin_h) {convert $x$-coordinate from \.{DVI} to
+PDF}
+@d pdf_y(#) == (pdf_origin_v - (#)) {convert $y$-coordinate from \.{DVI} to
+PDF}
+
+@<Glob...@>=
+@!pdf_f: internal_font_number; {the current font in PDF output page}
+@!pdf_h: scaled; {current horizontal coordinate in PDF output page}
+@!pdf_v: scaled; {current vertical coordinate in PDF output page}
+@!pdf_last_h: scaled; {last horizontal coordinate in PDF output page}
+@!pdf_last_v: scaled; {last vertical coordinate in PDF output page}
+@!pdf_origin_h: scaled; {current horizontal origin in PDF output page}
+@!pdf_origin_v: scaled; {current vertical origin in PDF output page}
+@!pdf_first_space_corr: integer; {amount of first word spacing while drawing a string;
+for some reason it is not taken into account of the length of the string, so we
+have to save it in order to adjust spacing when string drawing is finished}
+@!pdf_doing_string: boolean; {we are writing string to PDF file?}
+@!pdf_doing_text: boolean; {we are writing text section to PDF file?}
+@!pdf_font_changed: boolean; {current font has been changed?}
+@!min_bp_val: scaled;
+@!fixed_pk_resolution: integer;
+@!fixed_decimal_digits: integer;
+@!pk_scale_factor: integer;
+@!pdf_output_option: integer;
+@!pdf_output_value: integer;
+
+@ Following procedures implement low-level subroutines to convert \TeX{}
+internal structures to PDF page description.
+
+@p procedure pdf_set_origin; {set the origin to |cur_h|, |cur_v|}
+begin
+ if (abs(cur_h - pdf_origin_h) >= min_bp_val) or
+ (abs(cur_v - pdf_origin_v) >= min_bp_val) then begin
+ pdf_print("1 0 0 1 ");
+ pdf_print_bp(cur_h - pdf_origin_h);
+ pdf_origin_h := pdf_origin_h + scaled_out;
+ pdf_out(" ");
+ pdf_print_bp(pdf_origin_v - cur_v);
+ pdf_origin_v := pdf_origin_v - scaled_out;
+ pdf_print_ln(" cm");
+ end;
+ pdf_h := pdf_origin_h;
+ pdf_last_h := pdf_origin_h;
+ pdf_v := pdf_origin_v;
+ pdf_last_v := pdf_origin_v;
+end;
+
+procedure pdf_end_string; {end the current string}
+begin
+ if pdf_doing_string then begin
+ pdf_print(")]TJ");
+ if pdf_first_space_corr <> 0 then begin
+ pdf_h := pdf_h - pdf_first_space_corr;
+ pdf_first_space_corr := 0;
+ end;
+ pdf_doing_string := false;
+ end;
+end;
+
+procedure pdf_moveto(v, v_out: scaled); {set the next starting point to |cur_h|, |cur_v|}
+begin
+ pdf_out(" ");
+ pdf_print_bp(cur_h - pdf_last_h);
+ pdf_h := pdf_last_h + scaled_out;
+ pdf_out(" ");
+ pdf_print_real(v, fixed_decimal_digits);
+ pdf_print(" Td");
+ pdf_v := pdf_last_v - v_out;
+ pdf_last_h := pdf_h;
+ pdf_last_v := pdf_v;
+end;
+
+procedure pdf_begin_text; forward;
+
+procedure pdf_print_font_tag(f: internal_font_number);
+begin
+ if pdf_font_expand_ratio[f] = 0 then
+ return;
+ if pdf_font_expand_ratio[f] > 0 then
+ pdf_print("+"); {minus sign will be printed by |pdf_print_int|}
+ pdf_print_int(pdf_font_expand_ratio[f]);
+end;
+
+procedure pdf_set_font(f: internal_font_number);
+label found;
+var p: pointer;
+ k: internal_font_number;
+begin
+ if not font_used[f] then
+ pdf_init_font(f);
+ set_ff(f);
+ k := ff;
+ p := pdf_font_list;
+ while p <> null do begin
+ set_ff(info(p));
+ if ff = k then
+ goto found;
+ p := link(p);
+ end;
+ pdf_append_list(f)(pdf_font_list); {|f| not found in |pdf_font_list|}
+found:
+ pdf_begin_text;
+ pdf_print("/F");
+ pdf_print_int(k);
+ pdf_print_font_tag(f);
+ pdf_print_resname_prefix;
+ pdf_out(" ");
+ pdf_print_bp(font_size[f]);
+ pdf_print(" Tf");
+ pdf_f := f;
+ pdf_font_changed := true;
+end;
+
+procedure pdf_begin_text; {begin a text section}
+var temp_cur_h, temp_cur_v: scaled;
+begin
+ if not pdf_doing_text then begin
+ temp_cur_h := cur_h;
+ temp_cur_v := cur_v;
+ cur_h := 0;
+ cur_v := cur_page_height;
+ pdf_set_origin;
+ cur_h := temp_cur_h;
+ cur_v := temp_cur_v;
+ pdf_print_ln("BT");
+ pdf_doing_text := true;
+ pdf_f := null_font;
+ pdf_first_space_corr := 0;
+ pdf_doing_string := false;
+ end;
+end;
+
+procedure pdf_begin_string(f: internal_font_number); {begin to draw a string}
+var b: boolean; {|b| is true only when we must adjust word spacing
+at the beginning of string}
+ s, s_out, v, v_out: scaled;
+begin
+ pdf_begin_text;
+ if f <> pdf_f then begin
+ pdf_end_string;
+ pdf_set_font(f);
+ end;
+ b := false;
+ s := divide_scaled(cur_h - pdf_h, pdf_font_size[f], 3);
+ s_out := scaled_out;
+ if abs(cur_v - pdf_v) >= min_bp_val then begin
+ v := divide_scaled(pdf_last_v - cur_v, one_hundred_bp,
+ fixed_decimal_digits + 2);
+ v_out := scaled_out;
+ end
+ else begin
+ v := 0;
+ v_out := 0;
+ end;
+ if pdf_font_changed or (v <> 0) or (abs(s) >= @'100000) then begin
+ pdf_end_string;
+ pdf_moveto(v, v_out);
+ pdf_font_changed := false;
+ s := 0;
+ s_out := 0;
+ end;
+ if pdf_doing_string then begin
+ if s <> 0 then
+ pdf_out(")");
+ end
+ else begin
+ pdf_out("[");
+ if s <> 0 then
+ b := true
+ else
+ pdf_out("(");
+ pdf_doing_string := true;
+ end;
+ if s <> 0 then begin
+ pdf_print_int(-s);
+ if b then
+ pdf_first_space_corr := s_out;
+ pdf_out("(");
+ pdf_h := pdf_h + s_out;
+ end;
+end;
+
+procedure pdf_end_text; {end a text section}
+begin
+ if pdf_doing_text then begin
+ pdf_end_string;
+ pdf_print_nl;
+ pdf_print_ln("ET");
+ pdf_doing_text := false;
+ end;
+end;
+
+procedure pdf_set_rule(x, y, w, h: scaled); {draw a rule}
+begin
+ pdf_end_text;
+ pdf_set_origin;
+ if h <= one_bp then begin
+ pdf_print_ln("q");
+ pdf_print_ln("[]0 d");
+ pdf_print_ln("0 J");
+ pdf_print_bp(h); pdf_print_ln(" w");
+ pdf_print("0 "); pdf_print_bp((h + 1)/2); pdf_print_ln(" m");
+ pdf_print_bp(w); pdf_print(" "); pdf_print_bp((h + 1)/2);
+ pdf_print_ln(" l");
+ pdf_print_ln("S");
+ pdf_print_ln("Q");
+ end
+ else if w <= one_bp then begin
+ pdf_print_ln("q");
+ pdf_print_ln("[]0 d");
+ pdf_print_ln("0 J");
+ pdf_print_bp(w); pdf_print_ln(" w");
+ pdf_print_bp((w + 1)/2); pdf_print_ln(" 0 m");
+ pdf_print_bp((w + 1)/2); pdf_print(" "); pdf_print_bp(h);
+ pdf_print_ln(" l");
+ pdf_print_ln("S");
+ pdf_print_ln("Q");
+ end
+ else begin
+ pdf_print_bp(pdf_x(x)); pdf_out(" ");
+ pdf_print_bp(pdf_y(y)); pdf_out(" ");
+ pdf_print_bp(w); pdf_out(" ");
+ pdf_print_bp(h); pdf_print_ln(" re f");
+ end;
+end;
+
+
+procedure pdf_rectangle(left, top, right, bottom: scaled); {output a
+rectangle specification to PDF file}
+begin
+ prepare_mag;
+ pdf_print("/Rect [");
+ pdf_print_mag_bp(pdf_x(left)); pdf_out(" ");
+ pdf_print_mag_bp(pdf_y(bottom)); pdf_out(" ");
+ pdf_print_mag_bp(pdf_x(right)); pdf_out(" ");
+ pdf_print_mag_bp(pdf_y(top));
+ pdf_print_ln("]");
+end;
+
+@* \[32d] The cross-reference table.
+
+The cross-reference table |obj_tab| is an array of |obj_tab_size| of
+|tab_entry|. Each entry contains four integer fields and represents an object
+in PDF file whose object number is the index of this entry in |obj_tab|.
+Objects in |obj_tab| maybe linked into list; objects in such a linked list have
+the same type.
+
+@<Types...@>=
+@!obj_entry = record@;@/
+ int0, int1, int2, int3: integer;
+end;
+
+@ The first field contains information representing identifier of this object.
+It is usally a number for most of object types, but it may be a string number
+for named destination or named thread.
+
+The second field of |obj_entry| contains link to the next
+object in |obj_tab| if this object in linked in a list.
+
+The third field holds the byte offset of the object in the output PDF file.
+Objects that have been not written yet have this field set to zero. However
+sometimes we have to use this field to store some info before the object is
+written out.
+
+The last field usually represents the pointer to some auxiliary data
+structure depending on the object type; however it may be used as a counter as
+well.
+
+@d obj_info(#) == obj_tab[#].int0 {information representing identifier of this object}
+@d obj_link(#) == obj_tab[#].int1 {link to the next entry in linked list}
+@d obj_offset(#) == obj_tab[#].int2 {byte offset of this object in PDF output file}
+@d obj_aux(#) == obj_tab[#].int3 {auxiliary pointer}
+@d is_obj_written(#) == (obj_offset(#) <> 0)
+
+@# {types of objects}
+@d obj_type_others == 0 {objects which are not linked in any list}
+@d obj_type_page == 1 {index of linked list of Page objects}
+@d obj_type_pages == 2 {index of linked list of Pages objects}
+@d obj_type_font == 3 {index of linked list of Fonts objects}
+@d obj_type_outline == 4 {index of linked list of outline objects}
+@d obj_type_dest == 5 {index of linked list of destination objects}
+@d obj_type_obj == 6 {index of linked list of raw objects}
+@d obj_type_xform == 7 {index of linked list of XObject forms}
+@d obj_type_ximage == 8 {index of linked list of XObject image}
+@d obj_type_thread == 9 {index of linked list of num article threads}
+@d head_tab_max == obj_type_thread {max index of |head_tab|}
+
+@# {max number of kids for balanced trees}
+@d pages_tree_kids_max == 6 {max number of kids of Pages tree node}
+@d name_tree_kids_max == @'100000 {max number of kids of node of name tree for
+name destinations}
+
+@# {when a whatsit node representing annotation is created, words |1..3| are
+width, height and depth of this annotation; after shipping out words |1..4|
+are rectangle specification of annotation. For whatsit node representing
+destination |pdf_left| and |pdf_top| are used for some types of destinations}
+
+@# {coordinates of destinations/threads/annotations (in whatsit node)}
+@d pdf_left(#) == mem[# + 1].sc
+@d pdf_top(#) == mem[# + 2].sc
+@d pdf_right(#) == mem[# + 3].sc
+@d pdf_bottom(#) == mem[# + 4].sc
+
+@# {dimesion of destinations/threads/annotations (in whatsit node)}
+@d pdf_width(#) == mem[# + 1].sc
+@d pdf_height(#) == mem[# + 2].sc
+@d pdf_depth(#) == mem[# + 3].sc
+
+@# {data structure for \.{\\pdfliteral}}
+@d pdf_literal_data(#) == link(#+1) {data}
+@d pdf_literal_mode(#) == info(#+1) {mode of resetting the text matrix
+ while writing data to the page stream}
+@# {modes of resetting the text matrix}
+@d reset_origin == 0 {end text (ET) if needed, reset text matrix}
+@d direct_page == 1 {end text (ET) if needed, don't reset text matrix}
+@d direct_always == 2 {don't reset text matrix}
+@d scan_special == 3 {look into special text}
+
+@# {data structure for \.{\\pdfobj} and \.{\\pdfrefobj}}
+@d pdf_refobj_node_size == 2 {size of whatsit node representing the raw object}
+@d pdf_obj_objnum(#) == info(# + 1) {number of the raw object}
+@d obj_data_ptr == obj_aux {pointer to |pdf_mem|}
+@d pdfmem_obj_size == 4 {size of memory in |pdf_mem| which
+ |obj_data_ptr| holds}
+@d obj_obj_data(#) == pdf_mem[obj_data_ptr(#) + 0] {object data}
+@d obj_obj_is_stream(#) == pdf_mem[obj_data_ptr(#) + 1] {will this object
+ be written as a stream instead of a dictionary?}
+@d obj_obj_stream_attr(#) == pdf_mem[obj_data_ptr(#) + 2] {additional
+ object attributes for streams}
+@d obj_obj_is_file(#) == pdf_mem[obj_data_ptr(#) + 3] {data should be
+ read from an external file?}
+
+@# {data structure for \.{\\pdfxform} and \.{\\pdfrefxform}}
+@d pdf_refxform_node_size == 5 {size of whatsit node for xform; words 1..3 are
+ form dimensions}
+@d pdf_xform_objnum(#) == info(# + 4) {object number}
+@d pdfmem_xform_size == 6 {size of memory in |pdf_mem| which
+ |obj_data_ptr| holds}
+@d obj_xform_width(#) == pdf_mem[obj_data_ptr(#) + 0]
+@d obj_xform_height(#) == pdf_mem[obj_data_ptr(#) + 1]
+@d obj_xform_depth(#) == pdf_mem[obj_data_ptr(#) + 2]
+@d obj_xform_box(#) == pdf_mem[obj_data_ptr(#) + 3] {this field holds
+ pointer to the corresponding box}
+@d obj_xform_attr(#) == pdf_mem[obj_data_ptr(#) + 4] {additional xform
+ attributes}
+@d obj_xform_resources(#) == pdf_mem[obj_data_ptr(#) + 5] {additional xform
+ Resources}
+
+@# {data structure for \.{\\pdfximage} and \.{\\pdfrefximage}}
+@d pdf_refximage_node_size == 5 {size of whatsit node for ximage; words 1..3
+ are image dimensions}
+@d pdf_ximage_objnum(#) == info(# + 4) {object number}
+@d pdfmem_ximage_size == 5 {size of memory in |pdf_mem| which
+ |obj_data_ptr| holds}
+@d obj_ximage_width(#) == pdf_mem[obj_data_ptr(#) + 0]
+@d obj_ximage_height(#) == pdf_mem[obj_data_ptr(#) + 1]
+@d obj_ximage_depth(#) == pdf_mem[obj_data_ptr(#) + 2]
+@d obj_ximage_attr(#) == pdf_mem[obj_data_ptr(#) + 3] {additional ximage attributes}
+@d obj_ximage_data(#) == pdf_mem[obj_data_ptr(#) + 4] {pointer to image data}
+
+@# {data structure of annotations; words 1..4 represent the coordinates of
+ the annotation}
+@d obj_annot_ptr == obj_aux {pointer to corresponding whatsit node}
+@d pdf_annot_node_size == 7 {size of whatsit node representing annotation}
+@d pdf_annot_data(#) == info(# + 5) {raw data of general annotations}
+@d pdf_link_attr(#) == info(# + 5) {attributes of link annotations}
+@d pdf_link_action(#) == link(# + 5) {pointer to action structure}
+@d pdf_annot_objnum(#) == mem[# + 6].int {object number of corresponding object}
+
+@# {types of actions}
+@d pdf_action_page == 0 {Goto action}
+@d pdf_action_goto == 1 {Goto action}
+@d pdf_action_thread == 2 {Thread action}
+@d pdf_action_user == 3 {user-defined action}
+
+@# {data structure of actions}
+@d pdf_action_size == 3 {size of action structure in |mem|}
+@d pdf_action_type == type {action type}
+@d pdf_action_named_id == subtype {identifier is type of name}
+@d pdf_action_id == link {destination/thread name identifier}
+@d pdf_action_file(#) == info(# + 1) {file name for external action}
+@d pdf_action_new_window(#)== link(# + 1) {open a new window?}
+@d pdf_action_page_tokens(#) == info(# + 2) {specification of goto page action}
+@d pdf_action_user_tokens(#) == info(# + 2) {user-defined action string}
+@d pdf_action_refcount(#) == link(# + 2) {counter of references to this action}
+
+@# {data structure of outlines; it's not able to write out outline entries
+before all outline entries are defined, so memory allocated for outline
+entries can't not be deallocated and will stay in memory. For this reason we
+will store data of outline entries in |pdf_mem| instead of |mem|}
+
+@d pdfmem_outline_size == 8 {size of memory in |pdf_mem| which
+|obj_outline_ptr| points to}
+@d obj_outline_count == obj_info{count of all opened children}
+@d obj_outline_ptr == obj_aux {pointer to |pdf_mem|}
+@d obj_outline_title(#) == pdf_mem[obj_outline_ptr(#)]
+@d obj_outline_parent(#) == pdf_mem[obj_outline_ptr(#) + 1]
+@d obj_outline_prev(#) == pdf_mem[obj_outline_ptr(#) + 2]
+@d obj_outline_next(#) == pdf_mem[obj_outline_ptr(#) + 3]
+@d obj_outline_first(#) == pdf_mem[obj_outline_ptr(#) + 4]
+@d obj_outline_last(#) == pdf_mem[obj_outline_ptr(#) + 5]
+@d obj_outline_action_objnum(#) == pdf_mem[obj_outline_ptr(#) + 6] {object number of
+action}
+@d obj_outline_attr(#) == pdf_mem[obj_outline_ptr(#) + 7]
+
+@# {types of destinations}
+@d pdf_dest_xyz == 0
+@d pdf_dest_fit == 1
+@d pdf_dest_fith == 2
+@d pdf_dest_fitv == 3
+@d pdf_dest_fitb == 4
+@d pdf_dest_fitbh == 5
+@d pdf_dest_fitbv == 6
+@d pdf_dest_fitr == 7
+
+@# {data structure of destinations}
+@d obj_dest_ptr == obj_aux {pointer to |pdf_dest_node|}
+@d pdf_dest_node_size == 7 {size of whatsit node for destination;
+words |1..4| hold dest dimensions, word |6| identifier type, subtype
+and identifier of destination, word |6| the corresponding object number}
+@d pdf_dest_type(#) == type(# + 5) {type of destination}
+@d pdf_dest_named_id(#) == subtype(# + 5) {is named identifier?}
+@d pdf_dest_id(#) == link(# + 5) {destination identifier}
+@d pdf_dest_xyz_zoom(#) == info(# + 6) {zoom factor for |destxyz| destination}
+@d pdf_dest_objnum(#) == link(# + 6) {object number of corresponding
+object}
+
+@# {data structure of threads; words 1..4 represent the coordinates of the
+ corners}
+@d pdf_thread_node_size == 7
+@d pdf_thread_named_id(#) == subtype(# + 5) {is a named identifier}
+@d pdf_thread_id(#) == link(# + 5) {thread identifier}
+@d pdf_thread_attr(#) == info(# + 6) {attributes of thread}
+@d obj_thread_first == obj_aux {pointer to the first bead}
+
+@# {data structure of beads}
+@d pdfmem_bead_size == 5 {size of memory in |pdf_mem| which
+ |obj_bead_ptr| points to}
+@d obj_bead_ptr == obj_aux {pointer to |pdf_mem|}
+@d obj_bead_rect(#) == pdf_mem[obj_bead_ptr(#)]
+@d obj_bead_page(#) == pdf_mem[obj_bead_ptr(#) + 1]
+@d obj_bead_next(#) == pdf_mem[obj_bead_ptr(#) + 2]
+@d obj_bead_prev(#) == pdf_mem[obj_bead_ptr(#) + 3]
+@d obj_bead_attr(#) == pdf_mem[obj_bead_ptr(#) + 4]
+@d obj_bead_data == obj_bead_rect {pointer to the corresponding
+whatsit node; |obj_bead_rect| is needed only when the bead rectangle has
+been written out and after that |obj_bead_data| is not needed any more
+so we can use this field for both}
+
+@<Constants...@>=
+@!inf_obj_tab_size = 32000; {min size of the cross-reference table for PDF output}
+@!sup_obj_tab_size = 8388607; {max size of the cross-reference table for PDF output}
+@!inf_dest_names_size = 10000; {min size of the destination names table for PDF output}
+@!sup_dest_names_size = 131072; {max size of the destination names table for PDF output}
+@!pdf_objtype_max = head_tab_max;
+@!pdf_pdf_box_spec_media = 0;
+@!pdf_pdf_box_spec_crop = 1;
+@!pdf_pdf_box_spec_bleed = 2;
+@!pdf_pdf_box_spec_trim = 3;
+@!pdf_pdf_box_spec_art = 4;
+
+@ @<Glob...@>=
+@!obj_tab_size:integer;
+@!obj_tab:^obj_entry;
+@!head_tab: array[1..head_tab_max] of integer;
+@!obj_ptr: integer; {objects counter}
+@!pdf_last_pages: integer; {pointer to most recently generated pages object}
+@!pdf_last_page: integer; {pointer to most recently generated page object}
+@!pdf_last_stream: integer; {pointer to most recently generated stream}
+@!pdf_stream_length: integer; {length of most recently generated stream}
+@!pdf_stream_length_offset: integer; {file offset of the last stream length}
+@!pdf_append_list_arg: integer; {for use with |pdf_append_list|}
+@!ff: integer; {for use with |set_ff|}
+
+@ @<Set init...@>=
+obj_ptr := 0;
+for k := 1 to head_tab_max do
+ head_tab[k] := 0;
+
+@ Here we implement subroutines for work with objects and related things.
+Some of them are used in former parts too, so we need to declare them
+forward.
+
+@d pdf_append_list_end(#) == # := append_ptr(#, pdf_append_list_arg); end
+@d pdf_append_list(#) == begin pdf_append_list_arg := #; pdf_append_list_end
+@d set_ff(#) == begin
+ if pdf_font_num[#] < 0 then
+ ff := -pdf_font_num[#]
+ else
+ ff := #;
+end
+
+@<Declare procedures that need to be declared forward for pdftex@>=
+procedure append_dest_name(s: str_number; n: integer);
+begin
+ if pdf_dest_names_ptr = dest_names_size then
+ overflow("number of destination names", dest_names_size);
+ dest_names[pdf_dest_names_ptr].objname := s;
+ dest_names[pdf_dest_names_ptr].objnum := n;
+ incr(pdf_dest_names_ptr);
+end;
+
+procedure pdf_create_obj(t, i: integer); {create an object with type |t| and
+identifier |i|}
+label done;
+var p, q: integer;
+begin
+ if obj_ptr = obj_tab_size then
+ overflow("indirect objects table size", obj_tab_size);
+ incr(obj_ptr);
+ obj_info(obj_ptr) := i;
+ obj_offset(obj_ptr) := 0;
+ obj_aux(obj_ptr) := 0;
+ avl_put_obj(obj_ptr, t);
+ if t = obj_type_page then begin
+ p := head_tab[t];
+ {find the right position to insert newly created object}@/
+ if (p = 0) or (obj_info(p) < i) then begin
+ obj_link(obj_ptr) := p;
+ head_tab[t] := obj_ptr;
+ end
+ else begin
+ while p <> 0 do begin
+ if obj_info(p) < i then
+ goto done;
+ q := p;
+ p := obj_link(p);
+ end;
+done:
+ obj_link(q) := obj_ptr;
+ obj_link(obj_ptr) := p;
+ end;
+ end
+ else if t <> obj_type_others then begin
+ obj_link(obj_ptr) := head_tab[t];
+ head_tab[t] := obj_ptr;
+ if (t = obj_type_dest) and (i < 0) then
+ append_dest_name(-obj_info(obj_ptr), obj_ptr);
+ end;
+end;
+
+function pdf_new_objnum: integer; {create a new object and return its number}
+begin
+ pdf_create_obj(obj_type_others, 0);
+ pdf_new_objnum := obj_ptr;
+end;
+
+procedure pdf_begin_obj(i: integer); {begin a PDF object}
+begin
+ ensure_pdf_open;
+ check_pdfminorversion;
+ obj_offset(i) := pdf_offset;
+ pdf_print_int(i);
+ pdf_print_ln(" 0 obj");
+end;
+
+procedure pdf_end_obj;
+begin
+ pdf_print_ln("endobj"); {end a PDF object}
+end;
+
+procedure pdf_begin_dict(i: integer); {begin a PDF dictionary object}
+begin
+ obj_offset(i) := pdf_offset;
+ pdf_print_int(i);
+ pdf_print_ln(" 0 obj <<");
+end;
+
+procedure pdf_end_dict; {end a PDF object of type dictionary}
+begin
+ pdf_print_ln(">> endobj");
+end;
+
+procedure pdf_new_obj(t, i: integer); {begin to a new object}
+begin
+ pdf_create_obj(t, i);
+ pdf_begin_obj(obj_ptr);
+end;
+
+procedure pdf_new_dict(t, i: integer); {begin a new object with type dictionary}
+begin
+ pdf_create_obj(t, i);
+ pdf_begin_dict(obj_ptr);
+end;
+
+function append_ptr(p: pointer; i: integer): pointer; {appends a pointer with
+info |i| to the end of linked list with head |p|}
+var q: pointer;
+begin
+ append_ptr := p;
+ fast_get_avail(q);
+ info(q) := i;
+ link(q) := null;
+ if p = null then begin
+ append_ptr := q;
+ return;
+ end;
+ while link(p) <> null do
+ p := link(p);
+ link(p) := q;
+end;
+
+function pdf_lookup_list(p: pointer; i: integer): pointer; {looks up for pointer
+with info |i| in list |p|}
+begin
+ pdf_lookup_list := null;
+ while p <> null do begin
+ if info(p) = i then begin
+ pdf_lookup_list := p;
+ return;
+ end;
+ p := link(p);
+ end;
+end;
+
+@ @<Glob...@>=
+@!pdf_image_procset: integer; {collection of image types used in current page/form}
+@!pdf_text_procset: boolean; {mask of used ProcSet's in the current page/form}
+
+@ Subroutines to print out various PDF objects
+
+@d is_hex_char(#) == (((# >= '0') and (# <= '9')) or
+ ((# >= 'A') and (# <= 'F')) or
+ ((# >= 'a') and (# <= 'f')))
+
+@p procedure pdf_print_fw_int(n, w: integer); {print out an integer with
+fixed width; used for outputting cross-reference table}
+var k:integer; {$0\le k\le23$}
+begin
+ k:=0;
+ repeat dig[k]:=n mod 10; n:=n div 10; incr(k);
+ until k = w;
+ pdf_room(k);
+ while k>0 do begin
+ decr(k);
+ pdf_quick_out("0"+dig[k]);
+ end;
+end;
+
+procedure pdf_int_entry(s: str_number; v: integer); {print out an entry in
+dictionary with integer value to PDF buffer}
+begin
+ pdf_out("/");
+ pdf_print(s);
+ pdf_out(" ");
+ pdf_print_int(v);
+end;
+
+procedure pdf_int_entry_ln(s: str_number; v: integer);
+begin
+ pdf_int_entry(s, v);
+ pdf_print_nl;
+end;
+
+procedure pdf_indirect(s: str_number; o: integer); {print out an indirect
+entry in dictionary}
+begin
+ pdf_out("/");
+ pdf_print(s);
+ pdf_out(" ");
+ pdf_print_int(o);
+ pdf_print(" 0 R");
+end;
+
+procedure pdf_indirect_ln(s: str_number; o: integer);
+begin
+ pdf_indirect(s, o);
+ pdf_print_nl;
+end;
+
+procedure pdf_print_str(s: str_number); {print out |s| as string in PDF
+output}
+label done;
+var i, j, k: pool_pointer;
+ is_hex_string: boolean;
+begin
+ i := str_start[s];
+ j := i + length(s) - 1;
+ if i > j then begin
+ pdf_print("()"); {null string}
+ return;
+ end;
+ if (str_pool[i] = '(') and (str_pool[j] = ')') then begin
+ pdf_print(s);
+ return;
+ end;
+ is_hex_string := false;
+ if (str_pool[i] <> '<') or (str_pool[j] <> '>') or odd(length(s)) then
+ goto done;
+ incr(i);
+ decr(j);
+ while i < j do begin
+ if is_hex_char(str_pool[i]) and is_hex_char(str_pool[i + 1]) then
+ i := i + 2
+ else
+ goto done;
+ end;
+ is_hex_string := true;
+done:
+ if is_hex_string then
+ pdf_print(s)
+ else begin
+ pdf_out("(");
+ pdf_print(s);
+ pdf_out(")");
+ end;
+end;
+
+procedure pdf_print_str_ln(s: str_number); {print out |s| as string in PDF
+output}
+begin
+ pdf_print_str(s);
+ pdf_print_nl;
+end;
+
+procedure pdf_str_entry(s, v: str_number); {print out an entry in
+dictionary with string value to PDF buffer}
+begin
+ if v = 0 then
+ return;
+ pdf_out("/");
+ pdf_print(s);
+ pdf_out(" ");
+ pdf_print_str(v);
+end;
+
+procedure pdf_str_entry_ln(s, v: str_number);
+begin
+ if v = 0 then
+ return;
+ pdf_str_entry(s, v);
+ pdf_print_nl;
+end;
+
+@* \[32e] Font processing.
+
+As pdfTeX should also act as a back-end driver, it needs to support virtual
+font too. Information about virtual font can be found in source of some
+\.{DVI}-related programs.
+
+Whenever we want to write out a character in a font to PDF output, we
+should check whether the used font is new font (has not been used yet),
+virtual font or real font. The array |pdf_font_type| holds flag of each used
+font. After initialization flag of each font is set to |new_font_type|.
+The first time when a character of a font is written out, pdfTeX looks for
+the corresponding virtual font. If the corresponding virtual font exists, then
+the font type is set to |virtual_font_type|; otherwise it will be set to
+|real_font_type|. |subst_font_type| indicates fonts that have been substituted
+during adjusting spacing. Such fonts are linked via the |pdf_font_elink| array.
+
+@d new_font_type = 0 {new font (has not been used yet)}
+@d virtual_font_type = 1 {virtual font}
+@d real_font_type = 2 {real font}
+@d subst_font_type = 3 {substituted font}
+@d pdf_init_font(#) == begin tmp_f := #; pdf_create_font_obj; end
+@d pdf_check_vf(#) == begin
+ tmp_f := #;
+ do_vf;
+ if pdf_font_type[#] = virtual_font_type then
+ pdf_error("font", "command cannot be used with virtual font");
+end
+
+@d pdf_check_new_font(#) ==
+ if pdf_font_type[#] = new_font_type then begin
+ tmp_f := #;
+ do_vf;
+ end
+
+@<Declare procedures that need to be declared forward...@>=
+procedure pdf_create_font_obj; forward;
+procedure do_vf; forward;
+procedure scan_pdf_ext_toks; forward;
+
+@ @<Glob...@>=
+@!pdf_font_type: ^eight_bits; {the type of font}
+@!pdf_font_attr: ^str_number; {pointer to additional attributes}
+@!tmp_f: internal_font_number; {for use with |pdf_init_font|}
+
+@ To set PDF font we need to find out fonts with the same name, because \TeX\
+can load the same font several times for various sizes. For such fonts we
+define only one font resource. The array |pdf_font_num| holds the object
+number of font resource. A negative value of an entry of |pdf_font_num|
+indicates that the corresponding font shares the font resource with the font
+whose internal number is the absolute value of the entry. For partial
+downloading we also need to hold flags indicating which characters in particular
+font are used in array |pdf_char_used|.
+
+@d pdf_print_resname_prefix ==
+if pdf_resname_prefix <> 0 then
+ pdf_print(pdf_resname_prefix)
+
+@p procedure pdf_use_font(f: internal_font_number; fontnum: integer);
+begin
+ call_func(divide_scaled(font_size[f], one_hundred_bp,
+ fixed_decimal_digits + 2));
+ pdf_font_size[f] := scaled_out;
+ font_used[f] := true;
+ pdf_font_num[f] := fontnum;
+ if pdf_move_chars > 0 then begin
+ pdf_warning(0,"Primitive \pdfmovechars is obsolete.",true);
+ pdf_move_chars := 0; {warn only once}
+ end;
+end;
+
+procedure pdf_create_font_obj;
+var f, k: internal_font_number;
+begin
+ f := tmp_f;
+ if not font_used[f] then begin
+ if hasfmentry(f) then begin
+ {this font is scaleable, so different sizes can share a single font object}
+ k := tfm_of_fm(pdf_font_map[f]);
+ if (k <> f) and str_eq_str(font_name[k], font_name[f]) then begin
+ pdf_use_font(f, -k);
+ return;
+ end;
+ end;
+ pdf_create_obj(obj_type_font, f);
+ pdf_use_font(f, obj_ptr);
+ end;
+end;
+
+@ We need to hold information about used characters in each font for partial
+downloading.
+
+@<Types...@>=
+char_used_array = array[0..31] of eight_bits;
+char_map_array = array[0..32] of eight_bits; {move chars in range 0..32}
+fm_entry_ptr = ^integer;
+
+@ @<Glob...@>=
+@!pdf_char_used: ^char_used_array; {to mark used chars}
+@!pdf_char_map: ^char_map_array; {where to map chars 0..32}
+@!pdf_font_size: ^scaled; {used size of font in PDF file}
+@!pdf_font_num: ^integer; {mapping between internal font number in \TeX\ and
+ font name defined in resources in PDF file}
+@!pdf_font_map: ^fm_entry_ptr; {pointer into AVL tree of font mappings}
+@!pdf_font_list: pointer; {list of used fonts in current page}
+@!pdf_resname_prefix: str_number; {global prefix of resources name}
+@!last_tokens_string: str_number; {the number of the most recently string
+created by |tokens_to_string|}
+
+@ @<Set init...@>=
+pdf_resname_prefix := 0;
+last_tokens_string := 0;
+
+
+@ Here we implement reading information from \.{VF} file.
+
+@d vf_max_packet_length = 10000 {max length of character packet in \.{VF} file}
+
+@#
+@d vf_error = 61 {label to go to when an error occur}
+@d do_char = 70 {label to go to typesetting a character of virtual font}
+@#
+@d long_char = 242 {\.{VF} command for general character packet}
+@d vf_id = 202 {identifies \.{VF} files}
+@d put1=133 {typeset a character}
+
+@#
+@d vf_byte == getc(vf_file) {get a byte from\.{VF} file}
+@d vf_packet(#) == vf_packet_start[vf_packet_base[#] + vf_packet_end
+@d vf_packet_end(#) == #]
+
+@#
+@d bad_vf(#) == begin vf_err_str := #; goto vf_error; end {go out \.{VF}
+processing with an error message}
+@d four_cases(#) == #,#+1,#+2,#+3
+
+@#
+@d tmp_b0 == tmp_w.qqqq.b0
+@d tmp_b1 == tmp_w.qqqq.b1
+@d tmp_b2 == tmp_w.qqqq.b2
+@d tmp_b3 == tmp_w.qqqq.b3
+@d tmp_int == tmp_w.int
+
+@#
+@d scaled3u == {convert |tmp_b1..tmp_b3| to an unsigned scaled dimension}
+(((((tmp_b3*vf_z)div@'400)+(tmp_b2*vf_z))div@'400)+(tmp_b1*vf_z))div vf_beta
+@d scaled4(#) == {convert |tmp_b0..tmp_b3| to a scaled dimension}
+ #:=scaled3u;
+ if tmp_b0>0 then if tmp_b0=255 then # := # - vf_alpha
+@d scaled3(#) == {convert |tmp_b1..tmp_b3| to a scaled dimension}
+ #:=scaled3u; @+ if tmp_b1>127 then # := # - vf_alpha
+@d scaled2 == {convert |tmp_b2..tmp_b3| to a scaled dimension}
+ if tmp_b2>127 then tmp_b1:=255 else tmp_b1:=0;
+ scaled3
+@d scaled1 == {convert |tmp_b3| to a scaled dimension}
+ if tmp_b3>127 then tmp_b1:=255 else tmp_b1:=0;
+ tmp_b2:=tmp_b1; scaled3
+
+@<Glob...@>=
+@!vf_packet_base: ^integer; {base addresses of character packets from virtual fonts}
+@!vf_default_font: ^internal_font_number; {default font in a \.{VF} file}
+@!vf_local_font_num: ^internal_font_number; {number of local fonts in a \.{VF} file}
+@!vf_packet_length: integer; {length of the current packet}
+@!vf_file: byte_file;
+@!vf_nf: internal_font_number; {the local fonts counter}
+@!vf_e_fnts: ^integer; {external font numbers}
+@!vf_i_fnts: ^internal_font_number; {corresponding internal font numbers}
+@!tmp_w: memory_word; {accumulator}
+@!vf_z: integer; {multiplier}
+@!vf_alpha: integer; {correction for negative values}
+@!vf_beta: 1..16; {divisor}
+
+@ @<Set init...@>=
+vf_nf := 0;
+
+@ The |do_vf| procedure attempts to read the \.{VF} file for a font, and sets
+|pdf_font_type| to |real_font_type| if the \.{VF} file could not be found
+or loaded, otherwise sets |pdf_font_type| to |virtual_font_type|. At this
+time, |tmp_f| is the internal font number of the current \.{TFM} font. To
+process font definitions in virtual font we call |vf_def_font|.
+
+@p procedure vf_replace_z;
+begin
+ vf_alpha:=16;
+ while vf_z>=@'40000000 do begin
+ vf_z:=vf_z div 2;
+ vf_alpha:=vf_alpha+vf_alpha;
+ end;
+ vf_beta:=256 div vf_alpha;
+ vf_alpha:=vf_alpha*vf_z;
+end;
+
+function vf_read(k: integer): integer; {read |k| bytes as an integer from \.{VF} file}
+var i: integer;
+begin
+ i := 0;
+ while k > 0 do begin
+ i := i*256 + vf_byte;
+ decr(k);
+ end;
+ vf_read := i;
+end;
+
+procedure vf_local_font_warning(f, k: internal_font_number; s: str_number);
+{print a warning message if an error ocurrs during processing local fonts in
+\.{VF} file}
+begin
+ print_nl(s);
+ print(" in local font ");
+ print(font_name[k]);
+ print(" in virtual font ");
+ print(font_name[f]);
+ print(".vf ignored.");
+end;
+
+function vf_def_font(f: internal_font_number): internal_font_number;
+{process a local font in \.{VF} file}
+var k: internal_font_number;
+ s: str_number;
+ ds, fs: scaled;
+ cs: four_quarters;
+ c: integer;
+begin
+ cs.b0 := vf_byte; cs.b1 := vf_byte; cs.b2 := vf_byte; cs.b3 := vf_byte;
+ tmp_b0 := vf_byte; tmp_b1 := vf_byte; tmp_b2 := vf_byte; tmp_b3 := vf_byte;
+ scaled4(fs);
+ ds := vf_read(4) div @'20;
+ tmp_b0 := vf_byte;
+ tmp_b1 := vf_byte;
+ while tmp_b0 > 0 do begin
+ decr(tmp_b0);
+ if vf_byte > 0 then
+ do_nothing; {skip the font path}
+ end;
+ str_room(tmp_b1);
+ while tmp_b1 > 0 do begin
+ decr(tmp_b1);
+ append_char(vf_byte);
+ end;
+ s := make_string;
+ k := tfm_lookup(s, fs);
+ if k = null_font then
+ k := read_font_info(null_cs, s, "", fs);
+ if k <> null_font then begin
+ if ((cs.b0 <> 0) or (cs.b1 <> 0) or (cs.b2 <> 0) or (cs.b3 <> 0)) and
+ ((font_check[k].b0 <> 0) or (font_check[k].b1 <> 0) or
+ (font_check[k].b2 <> 0) or (font_check[k].b3 <> 0)) and
+ ((cs.b0 <> font_check[k].b0) or (cs.b1 <> font_check[k].b1) or
+ (cs.b2 <> font_check[k].b2) or (cs.b3 <> font_check[k].b3)) then
+ vf_local_font_warning(f, k, "checksum mismatch");
+ if ds <> font_dsize[k] then
+ vf_local_font_warning(f, k, "design size mismatch");
+ end;
+ if pdf_font_expand_ratio[f] <> 0 then
+ set_expand_param(k, f, pdf_font_expand_ratio[f]);
+ vf_def_font := k;
+end;
+
+procedure do_vf; {process \.{VF} file with font internal number |f|}
+label vf_error;
+var cmd, k, n: integer;
+ cc, cmd_length: integer;
+ tfm_width: scaled;
+ vf_err_str, s: str_number;
+ stack_level: vf_stack_index;
+ save_vf_nf: internal_font_number;
+ f: internal_font_number;
+
+begin
+ f := tmp_f;
+ pdf_font_type[f] := real_font_type;
+ if auto_expand_vf(f) then
+ return; {auto-expanded virtual font}
+ stack_level := 0;
+ @<Open |vf_file|, return if not found@>;
+ @<Process the preamble@>;@/
+ @<Process the font definitions@>;@/
+ @<Allocate memory for the new virtual font@>;@/
+ while cmd <= long_char do begin@/
+ @<Build a character packet@>;@/
+ end;
+ if cmd <> post then
+ bad_vf("POST command expected");
+ b_close(vf_file);
+ pdf_font_type[f] := virtual_font_type;
+ return;
+vf_error:
+ print_nl("Error in processing VF font (");
+ print(font_name[f]);
+ print(".vf): ");
+ print(vf_err_str);
+ print(", virtual font will be ignored");
+ print_ln;
+ b_close(vf_file);
+ update_terminal;
+end;
+
+@ @<Open |vf_file|, return if not found@>=
+pack_file_name(font_name[f], "", ".vf");
+if not vf_b_open_in(vf_file) then
+ return
+
+@ @<Process the preamble@>=
+if vf_byte <> pre then
+ bad_vf("PRE command expected");
+if vf_byte <> vf_id then
+ bad_vf("wrong id byte");
+cmd_length := vf_byte;
+for k := 1 to cmd_length do
+ tmp_int := vf_byte;
+tmp_b0 := vf_byte; tmp_b1 := vf_byte; tmp_b2 := vf_byte; tmp_b3 := vf_byte;
+if ((tmp_b0 <> 0) or (tmp_b1 <> 0) or (tmp_b2 <> 0) or (tmp_b3 <> 0)) and
+ ((font_check[f].b0 <> 0) or (font_check[f].b1 <> 0) or
+ (font_check[f].b2 <> 0) or (font_check[f].b3 <> 0)) and
+ ((tmp_b0 <> font_check[f].b0) or (tmp_b1 <> font_check[f].b1) or
+ (tmp_b2 <> font_check[f].b2) or (tmp_b3 <> font_check[f].b3)) then begin
+ print_nl("checksum mismatch in font ");
+ print(font_name[f]);
+ print(".vf ignored");
+end;
+if vf_read(4) div @'20 <> font_dsize[f] then begin
+ print_nl("design size mismatch in font ");
+ print(font_name[f]);
+ print(".vf ignored");
+end;
+update_terminal;
+vf_z := font_size[f];
+vf_replace_z
+
+@ @<Process the font definitions@>=
+cmd := vf_byte;
+save_vf_nf := vf_nf;
+while (cmd >= fnt_def1) and (cmd <= fnt_def1 + 3) do begin
+ vf_e_fnts[vf_nf] := vf_read(cmd - fnt_def1 + 1);
+ vf_i_fnts[vf_nf] := vf_def_font(f);
+ incr(vf_nf);
+ cmd := vf_byte;
+end;
+vf_default_font[f] := save_vf_nf;
+vf_local_font_num[f] := vf_nf - save_vf_nf;
+
+@ @<Allocate memory for the new virtual font@>=
+ vf_packet_base[f] := new_vf_packet(f)
+
+@ @<Build a character packet@>=
+if cmd = long_char then begin
+ vf_packet_length := vf_read(4);
+ cc := vf_read(4);
+ if not is_valid_char(cc) then
+ bad_vf("invalid character code");
+ tmp_b0 := vf_byte; tmp_b1 := vf_byte; tmp_b2 := vf_byte; tmp_b3 := vf_byte;
+ scaled4(tfm_width);
+end
+else begin
+ vf_packet_length := cmd;
+ cc := vf_byte;
+ if not is_valid_char(cc) then
+ bad_vf("invalid character code");
+ tmp_b1 := vf_byte; tmp_b2 := vf_byte; tmp_b3 := vf_byte;
+ scaled3(tfm_width);
+end;
+if vf_packet_length < 0 then
+ bad_vf("negative packet length");
+if vf_packet_length > vf_max_packet_length then
+ bad_vf("packet length too long");
+if (tfm_width <> char_width(f)(char_info(f)(cc))) then begin
+ print_nl("character width mismatch in font ");
+ print(font_name[f]);
+ print(".vf ignored");
+end;
+str_room(vf_packet_length);
+while vf_packet_length > 0 do begin
+ cmd := vf_byte;
+ decr(vf_packet_length);
+ @<Cases of \.{DVI} commands that can appear in character packet@>;
+ if cmd <> nop then
+ append_char(cmd);
+ vf_packet_length := vf_packet_length - cmd_length;
+ while cmd_length > 0 do begin
+ decr(cmd_length);
+ append_char(vf_byte);
+ end;
+end;
+if stack_level <> 0 then
+ bad_vf("more PUSHs than POPs in character packet");
+if vf_packet_length <> 0 then
+ bad_vf("invalid packet length or DVI command in packet");
+@<Store the packet being built@>;
+cmd := vf_byte
+
+@ @<Store the packet being built@>=
+s := make_string;
+storepacket(f, cc, s);
+flush_str(s)
+
+@ @<Cases of \.{DVI} commands that can appear in character packet@>=
+if (cmd >= set_char_0) and (cmd <= set_char_0 + 127) then
+ cmd_length := 0
+else if ((fnt_num_0 <= cmd) and (cmd <= fnt_num_0 + 63)) or
+ ((fnt1 <= cmd) and (cmd <= fnt1 + 3)) then begin
+ if cmd >= fnt1 then begin
+ k := vf_read(cmd - fnt1 + 1);
+ vf_packet_length := vf_packet_length - (cmd - fnt1 + 1);
+ end
+ else
+ k := cmd - fnt_num_0;
+ if k >= 256 then
+ bad_vf("too many local fonts");
+ n := 0;
+ while (n < vf_local_font_num[f]) and
+ (vf_e_fnts[vf_default_font[f] + n] <> k) do
+ incr(n);
+ if n = vf_local_font_num[f] then
+ bad_vf("undefined local font");
+ if k <= 63 then
+ append_char(fnt_num_0 + k)
+ else begin
+ append_char(fnt1);
+ append_char(k);
+ end;
+ cmd_length := 0;
+ cmd := nop;
+end
+else case cmd of
+set_rule, put_rule: cmd_length := 8;
+four_cases(set1): cmd_length := cmd - set1 + 1;
+four_cases(put1): cmd_length := cmd - put1 + 1;
+four_cases(right1): cmd_length := cmd - right1 + 1;
+four_cases(w1): cmd_length := cmd - w1 + 1;
+four_cases(x1): cmd_length := cmd - x1 + 1;
+four_cases(down1): cmd_length := cmd - down1 + 1;
+four_cases(y1): cmd_length := cmd - y1 + 1;
+four_cases(z1): cmd_length := cmd - z1 + 1;
+four_cases(xxx1): begin
+ cmd_length := vf_read(cmd - xxx1 + 1);
+ vf_packet_length := vf_packet_length - (cmd - xxx1 + 1);
+ if cmd_length > vf_max_packet_length then
+ bad_vf("packet length too long");
+ if cmd_length < 0 then
+ bad_vf("string of negative length");
+ append_char(xxx1);
+ append_char(cmd_length);
+ cmd := nop; {|cmd| has been already stored above as |xxx1|}
+end;
+w0, x0, y0, z0, nop:
+ cmd_length := 0;
+push, pop: begin
+ cmd_length := 0;
+ if cmd = push then
+ if stack_level = vf_stack_size then
+ overflow("virtual font stack size", vf_stack_size)
+ else
+ incr(stack_level)
+ else
+ if stack_level = 0 then
+ bad_vf("more POPs than PUSHs in character")
+ else
+ decr(stack_level);
+end;
+othercases
+ bad_vf("improver DVI command");
+endcases
+
+@ The |do_vf_packet| procedure is called in order to interpret the
+character packet for a virtual character. Such a packet may contain the
+instruction to typeset a character from the same or an other virtual
+font; in such cases |do_vf_packet| calls itself recursively. The
+recursion level, i.e., the number of times this has happened, is kept
+in the global variable |vf_cur_s| and should not exceed |vf_max_recursion|.
+
+@<Constants...@>=
+@!vf_max_recursion=10; {\.{VF} files shouldn't recurse beyond this level}
+@!vf_stack_size=100; {\.{DVI} files shouldn't |push| beyond this depth}
+
+@ @<Types...@>=
+@!vf_stack_index=0..vf_stack_size; {an index into the stack}
+@!vf_stack_record=record
+ stack_h, stack_v, stack_w, stack_x, stack_y, stack_z: scaled;
+end;
+
+@ @<Glob...@>=
+@!vf_cur_s: 0..vf_max_recursion; {current recursion level}
+@!vf_stack: array [vf_stack_index] of vf_stack_record;
+@!vf_stack_ptr: vf_stack_index; {pointer into |vf_stack|}
+
+@ @<Set init...@>=
+vf_cur_s := 0;
+vf_stack_ptr := 0;
+
+@ Some functions for processing character packets.
+
+@p function packet_read(k: integer): integer; {read |k| bytes as an integer from
+character packet}
+var i: integer;
+begin
+ i := 0;
+ while k > 0 do begin
+ i := i*256 + packet_byte;
+ decr(k);
+ end;
+ packet_read := i;
+end;
+
+function packet_scaled(k: integer): integer; {get |k| bytes from packet as a
+scaled}
+var s: scaled;
+begin
+ case k of
+ 1: begin
+ tmp_b3 := packet_byte;
+ scaled1(s);
+ end;
+ 2: begin
+ tmp_b2 := packet_byte;
+ tmp_b3 := packet_byte;
+ scaled2(s);
+ end;
+ 3: begin
+ tmp_b1 := packet_byte;
+ tmp_b2 := packet_byte;
+ tmp_b3 := packet_byte;
+ scaled3(s);
+ end;
+ 4: begin
+ tmp_b0 := packet_byte;
+ tmp_b1 := packet_byte;
+ tmp_b2 := packet_byte;
+ tmp_b3 := packet_byte;
+ scaled4(s);
+ end;
+ othercases pdf_error("vf", "invalid number size");
+ endcases;
+ packet_scaled := s;
+end;
+
+procedure do_vf_packet(f: internal_font_number; c: eight_bits); {typeset the \.{DVI} commands in the
+character packet for character |c| in current font |f|}
+label do_char, continue;
+var save_packet_ptr, save_packet_length: pool_pointer;
+ save_vf, k, n: internal_font_number;
+ base_line, save_h, save_v: scaled;
+ cmd: integer;
+ char_move: boolean;
+ w, x, y, z: scaled;
+ s: str_number;
+begin
+ incr(vf_cur_s);
+ if vf_cur_s > vf_max_recursion then
+ overflow("max level recursion of virtual fonts", vf_max_recursion);
+ push_packet_state;
+ start_packet(f, c);
+ vf_z := font_size[f];
+ vf_replace_z;
+ save_vf := f;
+ f := vf_i_fnts[vf_default_font[save_vf]];
+ save_v := cur_v;
+ save_h := cur_h;
+ w := 0; x := 0; y := 0; z := 0;
+ while vf_packet_length > 0 do begin
+ cmd := packet_byte;
+ @<Do typesetting the \.{DVI} commands in virtual character packet@>;
+continue:
+ end;
+ cur_h := save_h;
+ cur_v := save_v;
+ pop_packet_state;
+ vf_z := font_size[f];
+ vf_replace_z;
+ decr(vf_cur_s);
+end;
+
+@ The following code typesets a character to PDF output.
+
+@d output_one_char(#)==begin
+ pdf_check_new_font(f);
+ if pdf_font_type[f] = virtual_font_type then
+ do_vf_packet(f, #)
+ else begin
+ pdf_begin_string(f);
+ pdf_print_char(f, #);
+ adv_char_width(f, char_width(f)(char_info(f)(#)));
+ end;
+end
+
+
+@<Do typesetting the \.{DVI} commands in virtual character packet@>=
+if (cmd >= set_char_0) and (cmd <= set_char_0 + 127) then begin
+ if not is_valid_char(cmd) then begin
+ char_warning(f, cmd);
+ goto continue;
+ end;
+ c := cmd;
+ char_move := true;
+ goto do_char;
+end
+else if ((fnt_num_0 <= cmd) and (cmd <= fnt_num_0 + 63)) or (cmd = fnt1) then begin
+ if cmd = fnt1 then
+ k := packet_byte
+ else
+ k := cmd - fnt_num_0;
+ n := 0;
+ while (n < vf_local_font_num[save_vf]) and
+ (vf_e_fnts[vf_default_font[save_vf] + n] <> k) do
+ incr(n);
+ if (n = vf_local_font_num[save_vf]) then
+ f := null_font
+ else
+ f := vf_i_fnts[vf_default_font[save_vf] + n];
+end
+else case cmd of
+push: begin
+ vf_stack[vf_stack_ptr].stack_h := cur_h;
+ vf_stack[vf_stack_ptr].stack_v := cur_v;
+ vf_stack[vf_stack_ptr].stack_w := w;
+ vf_stack[vf_stack_ptr].stack_x := x;
+ vf_stack[vf_stack_ptr].stack_y := y;
+ vf_stack[vf_stack_ptr].stack_z := z;
+ incr(vf_stack_ptr);
+end;
+pop: begin
+ decr(vf_stack_ptr);
+ cur_h := vf_stack[vf_stack_ptr].stack_h;
+ cur_v := vf_stack[vf_stack_ptr].stack_v;
+ w := vf_stack[vf_stack_ptr].stack_w;
+ x := vf_stack[vf_stack_ptr].stack_x;
+ y := vf_stack[vf_stack_ptr].stack_y;
+ z := vf_stack[vf_stack_ptr].stack_z;
+end;
+four_cases(set1), four_cases(put1): begin
+ if (set1 <= cmd) and (cmd <= set1 + 3) then begin
+ tmp_int := packet_read(cmd - set1 + 1);
+ char_move := true;
+ end
+ else begin
+ tmp_int := packet_read(cmd - put1 + 1);
+ char_move := false;
+ end;
+ if not is_valid_char(tmp_int) then begin
+ char_warning(f, tmp_int);
+ goto continue;
+ end;
+ c := tmp_int;
+ goto do_char;
+end;
+set_rule, put_rule: begin
+ rule_ht := packet_scaled(4);
+ rule_wd := packet_scaled(4);
+ if (rule_wd > 0) and (rule_ht > 0) then begin
+ pdf_set_rule(cur_h, cur_v, rule_wd, rule_ht);
+ if cmd = set_rule then
+ cur_h := cur_h + rule_wd;
+ end;
+end;
+four_cases(right1):
+ cur_h := cur_h + packet_scaled(cmd - right1 + 1);
+w0, four_cases(w1): begin
+ if cmd > w0 then
+ w := packet_scaled(cmd - w0);
+ cur_h := cur_h + w;
+end;
+x0, four_cases(x1): begin
+ if cmd > x0 then
+ x := packet_scaled(cmd - x0);
+ cur_h := cur_h + x;
+end;
+four_cases(down1):
+ cur_v := cur_v + packet_scaled(cmd - down1 + 1);
+y0, four_cases(y1): begin
+ if cmd > y0 then
+ y := packet_scaled(cmd - y0);
+ cur_v := cur_v + y;
+end;
+z0, four_cases(z1): begin
+ if cmd > z0 then
+ z := packet_scaled(cmd - z0);
+ cur_v := cur_v + z;
+end;
+four_cases(xxx1): begin
+ tmp_int := packet_read(cmd - xxx1 + 1);
+ str_room(tmp_int);
+ while tmp_int > 0 do begin
+ decr(tmp_int);
+ append_char(packet_byte);
+ end;
+ s := make_string;
+ literal(s, scan_special, false);
+ flush_str(s);
+end;
+othercases pdf_error("vf", "invalid DVI command");
+endcases;
+goto continue;
+do_char:
+if is_valid_char(c) then
+ output_one_char(c)
+else
+ char_warning(f, c);
+if char_move then
+ cur_h := cur_h + char_width(f)(char_info(f)(c))
+
+@* \[32f] PDF shipping out.
+To ship out a \TeX\ box to PDF page description we need to implement
+|pdf_hlist_out|, |pdf_vlist_out| and |pdf_ship_out|, which are equivalent to
+the \TeX' original |hlist_out|, |vlist_out| and |ship_out| resp. But first we
+need to declare some procedures needed in |pdf_hlist_out| and |pdf_vlist_out|.
+
+@<Declare procedures needed in |pdf_hlist_out|, |pdf_vlist_out|@>=
+procedure pdf_out_literal(p:pointer);
+var old_setting:0..max_selector; {holds print |selector|}
+ s: str_number;
+begin
+ old_setting:=selector; selector:=new_string;
+ show_token_list(link(pdf_literal_data(p)),null,pool_size-pool_ptr);
+ selector:=old_setting;
+ s := make_string;
+ literal(s, pdf_literal_mode(p), false);
+ flush_str(s);
+end;
+
+procedure pdf_special(p: pointer);
+var old_setting:0..max_selector; {holds print |selector|}
+ s: str_number;
+begin
+ old_setting:=selector; selector:=new_string;
+ show_token_list(link(write_tokens(p)),null,pool_size-pool_ptr);
+ selector:=old_setting;
+ s := make_string;
+ literal(s, scan_special, true);
+ flush_str(s);
+end;
+
+procedure pdf_print_toks(p: pointer); {print tokens list |p|}
+var s: str_number;
+begin
+ s := tokens_to_string(p);
+ if length(s) > 0 then
+ pdf_print(s);
+ flush_str(s);
+end;
+
+procedure pdf_print_toks_ln(p: pointer); {print tokens list |p|}
+var s: str_number;
+begin
+ s := tokens_to_string(p);
+ if length(s) > 0 then begin
+ pdf_print(s);
+ pdf_print_nl;
+ end;
+ flush_str(s);
+end;
+
+@ Similiar to |vlist_out|, |pdf_vlist_out| needs to be declared forward
+
+@p procedure@?pdf_vlist_out; forward;
+
+@ The implementation of procedure |pdf_hlist_out| is similiar to |hlist_out|
+
+@p @t\4@>@<Declare procedures needed in |pdf_hlist_out|, |pdf_vlist_out|@>@t@>@/
+
+procedure pdf_hlist_out; {output an |hlist_node| box}
+label reswitch, move_past, fin_rule, next_p;
+var base_line: scaled; {the baseline coordinate for this box}
+@!left_edge: scaled; {the left coordinate for this box}
+@!save_h: scaled; {what |cur_h| should pop to}
+@!this_box: pointer; {pointer to containing box}
+@!g_order: glue_ord; {applicable order of infinity for glue}
+@!g_sign: normal..shrinking; {selects type of glue}
+@!p:pointer; {current position in the hlist}
+@!leader_box:pointer; {the leader box being replicated}
+@!leader_wd:scaled; {width of leader box being replicated}
+@!lx:scaled; {extra space between leader boxes}
+@!outer_doing_leaders:boolean; {were we doing leaders?}
+@!edge:scaled; {left edge of sub-box, or right edge of leader space}
+@!running_link: pointer; {pointer to `running' link if exists}
+@!glue_temp:real; {glue value before rounding}
+@!cur_glue:real; {glue seen so far}
+@!cur_g:scaled; {rounded equivalent of |cur_glue| times the glue ratio}
+begin cur_g:=0; cur_glue:=float_constant(0);
+this_box:=temp_ptr; g_order:=glue_order(this_box);
+g_sign:=glue_sign(this_box); p:=list_ptr(this_box);
+incr(cur_s);
+base_line:=cur_v; left_edge:=cur_h;
+running_link := null;
+@<Create link annotation for the current hbox if needed@>;
+while p<>null do
+ @<Output node |p| for |pdf_hlist_out| and move to the next node,
+ maintaining the condition |cur_v=base_line|@>;
+decr(cur_s);
+end;
+
+@ @<Create link annotation for the current hbox if needed@>=
+if running_link = null then begin
+ if is_running(pdf_link_wd) and (pdf_link_level = cur_s) then begin
+ append_link(this_box, left_edge, base_line);
+ running_link := last_link;
+ end;
+end
+else
+ last_link := running_link
+
+@ @<Output node |p| for |pdf_hlist_out|...@>=
+reswitch: if is_char_node(p) then
+ begin
+ repeat f:=font(p); c:=character(p);
+ if is_valid_char(c) then
+ output_one_char(c)
+ else
+ char_warning(f, c);
+ cur_h:=cur_h+char_width(f)(char_info(f)(c));
+ p:=link(p);
+ until not is_char_node(p);
+ end
+else @<Output the non-|char_node| |p| for |pdf_hlist_out|
+ and move to the next node@>
+
+@ @<Output the non-|char_node| |p| for |pdf_hlist_out|...@>=
+begin case type(p) of
+hlist_node,vlist_node:@<(\pdfTeX) Output a box in an hlist@>;
+rule_node: begin rule_ht:=height(p); rule_dp:=depth(p); rule_wd:=width(p);
+ goto fin_rule;
+ end;
+whatsit_node: @<Output the whatsit node |p| in |pdf_hlist_out|@>;
+glue_node: @<(\pdfTeX) Move right or output leaders@>;
+kern_node,math_node:cur_h:=cur_h+width(p);
+ligature_node: @<Make node |p| look like a |char_node| and |goto reswitch|@>;
+othercases do_nothing
+endcases;@/
+goto next_p;
+fin_rule: @<(\pdfTeX) Output a rule in an hlist@>;
+move_past: cur_h:=cur_h+rule_wd;
+next_p:p:=link(p);
+end
+
+@ @<(\pdfTeX) Output a box in an hlist@>=
+if list_ptr(p)=null then cur_h:=cur_h+width(p)
+else begin
+ cur_v:=base_line+shift_amount(p); {shift the box down}
+ temp_ptr:=p; edge:=cur_h;
+ if type(p)=vlist_node then pdf_vlist_out@+else pdf_hlist_out;
+ cur_h:=edge+width(p); cur_v:=base_line;
+ end
+
+@ @<(\pdfTeX) Output a rule in an hlist@>=
+if is_running(rule_ht) then rule_ht:=height(this_box);
+if is_running(rule_dp) then rule_dp:=depth(this_box);
+rule_ht:=rule_ht+rule_dp; {this is the rule thickness}
+if (rule_ht>0)and(rule_wd>0) then {we don't output empty rules}
+ begin cur_v:=base_line+rule_dp;
+ pdf_set_rule(cur_h, cur_v, rule_wd, rule_ht);
+ cur_v:=base_line;
+ end
+
+@ @<(\pdfTeX) Move right or output leaders@>=
+begin g:=glue_ptr(p); rule_wd:=width(g)-cur_g;
+if g_sign<>normal then
+ begin if g_sign=stretching then
+ begin if stretch_order(g)=g_order then
+ begin cur_glue:=cur_glue+stretch(g);
+ vet_glue(float(glue_set(this_box))*cur_glue);
+@^real multiplication@>
+ cur_g:=round(glue_temp);
+ end;
+ end
+ else if shrink_order(g)=g_order then
+ begin cur_glue:=cur_glue-shrink(g);
+ vet_glue(float(glue_set(this_box))*cur_glue);
+ cur_g:=round(glue_temp);
+ end;
+ end;
+rule_wd:=rule_wd+cur_g;
+if subtype(p)>=a_leaders then
+ @<(\pdfTeX) Output leaders in an hlist, |goto fin_rule| if a rule
+ or to |next_p| if done@>;
+goto move_past;
+end
+
+@ @<(\pdfTeX) Output leaders in an hlist...@>=
+begin leader_box:=leader_ptr(p);
+if type(leader_box)=rule_node then
+ begin rule_ht:=height(leader_box); rule_dp:=depth(leader_box);
+ goto fin_rule;
+ end;
+leader_wd:=width(leader_box);
+if (leader_wd>0)and(rule_wd>0) then
+ begin rule_wd:=rule_wd+10; {compensate for floating-point rounding}
+ edge:=cur_h+rule_wd; lx:=0;
+ @<Let |cur_h| be the position of the first box, and set |leader_wd+lx|
+ to the spacing between corresponding parts of boxes@>;
+ while cur_h+leader_wd<=edge do
+ @<(\pdfTeX) Output a leader box at |cur_h|,
+ then advance |cur_h| by |leader_wd+lx|@>;
+ cur_h:=edge-10; goto next_p;
+ end;
+end
+
+@ @<(\pdfTeX) Output a leader box at |cur_h|, ...@>=
+begin cur_v:=base_line+shift_amount(leader_box);@/
+save_h:=cur_h; temp_ptr:=leader_box;
+outer_doing_leaders:=doing_leaders; doing_leaders:=true;
+if type(leader_box)=vlist_node then pdf_vlist_out@+else pdf_hlist_out;
+doing_leaders:=outer_doing_leaders;
+cur_v:=base_line;
+cur_h:=save_h+leader_wd+lx;
+end
+
+@ The |pdf_vlist_out| routine is similar to |pdf_hlist_out|, but a bit simpler.
+@p procedure pdf_vlist_out; {output a |pdf_vlist_node| box}
+label move_past, fin_rule, next_p;
+var left_edge: scaled; {the left coordinate for this box}
+@!top_edge: scaled; {the top coordinate for this box}
+@!save_v: scaled; {what |cur_v| should pop to}
+@!this_box: pointer; {pointer to containing box}
+@!g_order: glue_ord; {applicable order of infinity for glue}
+@!g_sign: normal..shrinking; {selects type of glue}
+@!p:pointer; {current position in the vlist}
+@!leader_box:pointer; {the leader box being replicated}
+@!leader_ht:scaled; {height of leader box being replicated}
+@!lx:scaled; {extra space between leader boxes}
+@!outer_doing_leaders:boolean; {were we doing leaders?}
+@!edge:scaled; {bottom boundary of leader space}
+@!glue_temp:real; {glue value before rounding}
+@!cur_glue:real; {glue seen so far}
+@!cur_g:scaled; {rounded equivalent of |cur_glue| times the glue ratio}
+begin cur_g:=0; cur_glue:=float_constant(0);
+this_box:=temp_ptr; g_order:=glue_order(this_box);
+g_sign:=glue_sign(this_box); p:=list_ptr(this_box);
+incr(cur_s);
+left_edge:=cur_h; cur_v:=cur_v-height(this_box); top_edge:=cur_v;
+@<Create thread for the current vbox if needed@>;
+while p<>null do
+ @<Output node |p| for |pdf_vlist_out| and move to the next node,
+ maintaining the condition |cur_h=left_edge|@>;
+decr(cur_s);
+end;
+
+@ @<Create thread for the current vbox if needed@>=
+if (last_thread <> null) and is_running(pdf_thread_dp) and
+ (pdf_thread_level = cur_s) then
+ append_thread(this_box, left_edge, top_edge + height(this_box))
+
+@ @<Output node |p| for |pdf_vlist_out|...@>=
+begin if is_char_node(p) then confusion("pdfvlistout")
+@:this can't happen pdfvlistout}{\quad pdfvlistout@>
+else @<Output the non-|char_node| |p| for |pdf_vlist_out|@>;
+next_p:p:=link(p);
+end
+
+@ @<Output the non-|char_node| |p| for |pdf_vlist_out|@>=
+begin case type(p) of
+hlist_node,vlist_node:@<(\pdfTeX) Output a box in a vlist@>;
+rule_node: begin rule_ht:=height(p); rule_dp:=depth(p); rule_wd:=width(p);
+ goto fin_rule;
+ end;
+whatsit_node: @<Output the whatsit node |p| in |pdf_vlist_out|@>;
+glue_node: @<(\pdfTeX) Move down or output leaders@>;
+kern_node:cur_v:=cur_v+width(p);
+othercases do_nothing
+endcases;@/
+goto next_p;
+fin_rule: @<(\pdfTeX) Output a rule in a vlist, |goto next_p|@>;
+move_past: cur_v:=cur_v+rule_ht;
+end
+
+@ @<(\pdfTeX) Output a box in a vlist@>=
+if list_ptr(p)=null then cur_v:=cur_v+height(p)+depth(p)
+else begin cur_v:=cur_v+height(p); save_v:=cur_v;
+ cur_h:=left_edge+shift_amount(p); {shift the box right}
+ temp_ptr:=p;
+ if type(p)=vlist_node then pdf_vlist_out@+else pdf_hlist_out;
+ cur_v:=save_v+depth(p); cur_h:=left_edge;
+ end
+
+@ @<(\pdfTeX) Output a rule in a vlist...@>=
+if is_running(rule_wd) then rule_wd:=width(this_box);
+rule_ht:=rule_ht+rule_dp; {this is the rule thickness}
+cur_v:=cur_v+rule_ht;
+if (rule_ht>0)and(rule_wd>0) then {we don't output empty rules}
+ pdf_set_rule(cur_h, cur_v, rule_wd, rule_ht);
+goto next_p
+
+@ @<(\pdfTeX) Move down or output leaders@>=
+begin g:=glue_ptr(p); rule_ht:=width(g)-cur_g;
+if g_sign<>normal then
+ begin if g_sign=stretching then
+ begin if stretch_order(g)=g_order then
+ begin cur_glue:=cur_glue+stretch(g);
+ vet_glue(float(glue_set(this_box))*cur_glue);
+@^real multiplication@>
+ cur_g:=round(glue_temp);
+ end;
+ end
+ else if shrink_order(g)=g_order then
+ begin cur_glue:=cur_glue-shrink(g);
+ vet_glue(float(glue_set(this_box))*cur_glue);
+ cur_g:=round(glue_temp);
+ end;
+ end;
+rule_ht:=rule_ht+cur_g;
+if subtype(p)>=a_leaders then
+ @<(\pdfTeX) Output leaders in a vlist, |goto fin_rule| if a rule
+ or to |next_p| if done@>;
+goto move_past;
+end
+
+@ @<(\pdfTeX) Output leaders in a vlist...@>=
+begin leader_box:=leader_ptr(p);
+if type(leader_box)=rule_node then
+ begin rule_wd:=width(leader_box); rule_dp:=0;
+ goto fin_rule;
+ end;
+leader_ht:=height(leader_box)+depth(leader_box);
+if (leader_ht>0)and(rule_ht>0) then
+ begin rule_ht:=rule_ht+10; {compensate for floating-point rounding}
+ edge:=cur_v+rule_ht; lx:=0;
+ @<Let |cur_v| be the position of the first box, and set |leader_ht+lx|
+ to the spacing between corresponding parts of boxes@>;
+ while cur_v+leader_ht<=edge do
+ @<(\pdfTeX) Output a leader box at |cur_v|,
+ then advance |cur_v| by |leader_ht+lx|@>;
+ cur_v:=edge-10; goto next_p;
+ end;
+end
+
+@ @<(\pdfTeX) Output a leader box at |cur_v|, ...@>=
+begin cur_h:=left_edge+shift_amount(leader_box);@/
+cur_v:=cur_v+height(leader_box); save_v:=cur_v;
+temp_ptr:=leader_box;
+outer_doing_leaders:=doing_leaders; doing_leaders:=true;
+if type(leader_box)=vlist_node then pdf_vlist_out@+else pdf_hlist_out;
+doing_leaders:=outer_doing_leaders;
+cur_h:=left_edge;
+cur_v:=save_v-height(leader_box)+leader_ht+lx;
+end
+
+@ |fix_pdfoutput| freezes |pdfoutput| when something has been written to
+the output.
+
+@p procedure fix_pdfoutput;
+begin
+ if not fixed_pdfoutput_set then begin
+ fixed_pdfoutput := pdf_output;
+ fixed_pdfoutput_set := true;
+ end
+ else if fixed_pdfoutput <> pdf_output then
+ pdf_error("setup",
+ "\pdfoutput can only be changed before anything is written to the output");
+end;
+
+
+@ |pdf_ship_out| is used instead of |ship_out| to shipout a box to PDF
+output. If |shipping_page| is not set then the output will be a Form object,
+otherwise it will be a Page object.
+
+@p procedure pdf_ship_out(p: pointer; shipping_page: boolean); {output the box |p|}
+label done, done1;
+var i,j,k:integer; {general purpose accumulators}
+r: integer; {accumulator to copy node for pending link annotation}
+save_font_list: pointer; {to save |pdf_font_list| during flushing pending forms}
+save_obj_list: pointer; {to save |pdf_obj_list|}
+save_ximage_list: pointer; {to save |pdf_ximage_list|}
+save_xform_list: pointer; {to save |pdf_xform_list|}
+save_image_procset: integer; {to save |pdf_image_procset|}
+save_text_procset: integer; {to save |pdf_text_procset|}
+pdf_last_resources: integer; {pointer to most recently generated Resources object}
+s:str_number;
+old_setting:0..max_selector; {saved |selector| setting}
+begin if tracing_output>0 then
+ begin print_nl(""); print_ln;
+ print("Completed box being shipped out");
+@.Completed box...@>
+ end;
+if not init_pdf_output then begin
+ @<Initialize variables for \.{PDF} output@>;
+ init_pdf_output := true;
+end;
+is_shipping_page := shipping_page;
+if shipping_page then begin
+ if term_offset>max_print_line-9 then print_ln
+ else if (term_offset>0)or(file_offset>0) then print_char(" ");
+ print_char("["); j:=9;
+ while (count(j)=0)and(j>0) do decr(j);
+ for k:=0 to j do
+ begin print_int(count(k));
+ if k<j then print_char(".");
+ end;
+ update_terminal;
+end;
+if tracing_output>0 then
+ begin if shipping_page then print_char("]");
+ begin_diagnostic; show_box(p); end_diagnostic(true);
+ end;
+@<(\pdfTeX) Ship box |p| out@>;
+if (tracing_output<=0) and shipping_page then print_char("]");
+dead_cycles:=0;
+update_terminal; {progress report}
+@<Flush the box from memory, showing statistics if requested@>;
+end;
+
+@ @<(\pdfTeX) Ship box |p| out@>=
+@<Update the values of |max_h| and |max_v|; but if the page is too large,
+ |goto done|@>;
+@<Initialize variables as |pdf_ship_out| begins@>;
+if type(p)=vlist_node then pdf_vlist_out@+else pdf_hlist_out;
+if shipping_page then
+ incr(total_pages);
+cur_s:=-1;
+@<Finish shipping@>;
+done:
+
+@ @<Initialize variables as |pdf_ship_out| begins@>=
+fix_pdfoutput;
+temp_ptr:=p;
+prepare_mag;
+pdf_last_resources := pdf_new_objnum;
+@<Reset resources lists@>;
+if not shipping_page then begin
+ pdf_xform_width := width(p);
+ pdf_xform_height := height(p);
+ pdf_xform_depth := depth(p);
+ pdf_begin_dict(pdf_cur_form);
+ pdf_last_stream := pdf_cur_form;
+ cur_v := height(p);
+ cur_h := 0;
+ pdf_origin_h := 0;
+ pdf_origin_v := pdf_xform_height + pdf_xform_depth;
+end
+else begin
+ @<Calculate page dimensions and margins@>;
+ pdf_last_page := get_obj(obj_type_page, total_pages + 1, 0);
+ obj_aux(pdf_last_page) := 1; {mark that this page has beed created}
+ pdf_new_dict(obj_type_others, 0);
+ pdf_last_stream := obj_ptr;
+ cur_h := cur_h_offset;
+ cur_v := height(p) + cur_v_offset;
+ pdf_origin_h := 0;
+ pdf_origin_v := cur_page_height;
+ @<Reset PDF mark lists@>;
+end;
+if not shipping_page then begin
+ @<Write out Form stream header@>;
+end;
+@<Start stream of page/form contents@>
+
+@ @<Reset resources lists@>=
+pdf_font_list := null;
+pdf_obj_list := null;
+pdf_xform_list := null;
+pdf_ximage_list := null;
+pdf_text_procset := false;
+pdf_image_procset := 0
+
+@ @<Reset PDF mark lists@>=
+pdf_annot_list := null;
+pdf_link_list := null;
+pdf_dest_list := null;
+pdf_bead_list := null;
+last_link := null;
+last_thread := null
+
+@ @<Calculate page dimensions and margins@>=
+cur_h_offset := pdf_h_origin + h_offset;
+cur_v_offset := pdf_v_origin + v_offset;
+if pdf_page_width <> 0 then
+ cur_page_width := pdf_page_width
+else
+ cur_page_width := width(p) + 2*cur_h_offset;
+if pdf_page_height <> 0 then
+ cur_page_height := pdf_page_height
+else
+ cur_page_height := height(p) + depth(p) + 2*cur_v_offset
+
+@ Here we write out the header for Form.
+
+@<Write out Form stream header@>=
+pdf_print_ln("/Type /XObject");
+pdf_print_ln("/Subtype /Form");
+if obj_xform_attr(pdf_cur_form) <> null then begin
+ pdf_print_toks_ln(obj_xform_attr(pdf_cur_form));
+ delete_toks(obj_xform_attr(pdf_cur_form));
+end;
+pdf_print("/BBox [");
+pdf_print("0 0 ");
+pdf_print_bp(pdf_xform_width); pdf_out(" ");
+pdf_print_bp(pdf_xform_height + pdf_xform_depth); pdf_print_ln("]");
+pdf_print_ln("/FormType 1");
+pdf_print_ln("/Matrix [1 0 0 1 0 0]");
+pdf_indirect_ln("Resources", pdf_last_resources)
+
+@ @<Start stream of page/form contents@>=
+pdf_begin_stream;
+if shipping_page then begin
+ @<Adjust transformation matrix for the magnification ratio@>;
+end
+
+@ @<Adjust transformation matrix for the magnification ratio@>=
+prepare_mag;
+if mag <> 1000 then begin
+ pdf_print_real(mag, 3);
+ pdf_print(" 0 0 ");
+ pdf_print_real(mag, 3);
+ pdf_print_ln(" 0 0 cm");
+end
+
+@ @<Finish shipping@>=
+@<Finish stream of page/form contents@>;
+if shipping_page then begin
+ @<Write out page object@>;
+end;
+@<Flush out pending raw objects@>;
+@<Flush out pending forms@>;
+@<Flush out pending images@>;
+if shipping_page then begin
+ @<Flush out pending PDF marks@>;
+end;
+@<Write out resources dictionary@>;
+@<Flush resources lists@>;
+if shipping_page then begin
+ @<Flush PDF mark lists@>;
+end
+
+@ @<Finish stream of page/form contents@>=
+pdf_end_text;
+pdf_end_stream
+
+@ @<Write out resources dictionary@>=
+pdf_begin_dict(pdf_last_resources);
+@<Print additional resources@>;
+@<Generate font resources@>;
+@<Generate XObject resources@>;
+@<Generate ProcSet@>;
+pdf_end_dict
+
+@ @<Print additional resources@>=
+if shipping_page then begin
+ if pdf_page_resources <> null then
+ pdf_print_toks_ln(pdf_page_resources);
+end
+else begin
+ if obj_xform_resources(pdf_cur_form) <> null then begin
+ pdf_print_toks_ln(obj_xform_resources(pdf_cur_form));
+ delete_toks(obj_xform_resources(pdf_cur_form));
+ end;
+end
+
+@ In the end of shipping out a page we reset all the lists holding objects
+have been created during the page shipping.
+
+@d delete_toks(#) == begin delete_token_ref(#); # := null; end
+
+@<Flush resources lists@>=
+flush_list(pdf_font_list);
+flush_list(pdf_obj_list);
+flush_list(pdf_xform_list);
+flush_list(pdf_ximage_list)
+
+@ @<Flush PDF mark lists@>=
+flush_list(pdf_annot_list);
+flush_list(pdf_link_list);
+flush_list(pdf_dest_list);
+flush_list(pdf_bead_list)
+
+@ @<Generate font resources@>=
+if pdf_font_list <> null then begin
+ pdf_print("/Font << ");
+ k := pdf_font_list;
+ while k <> null do begin
+ pdf_print("/F");
+ set_ff(info(k));
+ pdf_print_int(ff);
+ pdf_print_font_tag(info(k));
+ pdf_print_resname_prefix;
+ pdf_out(" ");
+ pdf_print_int(pdf_font_num[ff]);
+ pdf_print(" 0 R ");
+ k := link(k);
+ end;
+ pdf_print_ln(">>");
+ pdf_text_procset := true;
+end
+
+@ @<Generate XObject resources@>=
+if (pdf_xform_list <> null) or (pdf_ximage_list <> null) then begin
+ pdf_print("/XObject << ");
+ k := pdf_xform_list;
+ while k <> null do begin
+ pdf_print("/Fm");
+ pdf_print_int(obj_info(info(k)));
+ pdf_print_resname_prefix;
+ pdf_out(" ");
+ pdf_print_int(info(k));
+ pdf_print(" 0 R ");
+ k := link(k);
+ end;
+ k := pdf_ximage_list;
+ while k <> null do begin
+ pdf_print("/Im");
+ pdf_print_int(obj_info(info(k)));
+ pdf_print_resname_prefix;
+ pdf_out(" ");
+ pdf_print_int(info(k));
+ pdf_print(" 0 R ");
+ update_image_procset(obj_ximage_data(info(k)));
+ k := link(k);
+ end;
+ pdf_print_ln(">>");
+end
+
+@ @<Generate ProcSet@>=
+pdf_print("/ProcSet [ /PDF");
+if pdf_text_procset then
+ pdf_print(" /Text");
+if check_image_b(pdf_image_procset) then
+ pdf_print(" /ImageB");
+if check_image_c(pdf_image_procset) then
+ pdf_print(" /ImageC");
+if check_image_i(pdf_image_procset) then
+ pdf_print(" /ImageI");
+pdf_print_ln(" ]")
+
+@ @<Write out page object@>=
+pdf_begin_dict(pdf_last_page);
+pdf_print_ln("/Type /Page");
+pdf_indirect_ln("Contents", pdf_last_stream);
+pdf_indirect_ln("Resources", pdf_last_resources);
+pdf_print("/MediaBox [0 0 ");
+pdf_print_mag_bp(cur_page_width); pdf_out(" ");
+pdf_print_mag_bp(cur_page_height);
+pdf_print_ln("]");
+if pdf_page_attr <> null then
+ pdf_print_toks_ln(pdf_page_attr);
+@<Generate parent pages object@>;
+@<Generate array of annotations or beads in page@>;
+pdf_end_dict
+
+@ @<Generate parent pages object@>=
+if total_pages mod pages_tree_kids_max = 1 then begin
+ pdf_create_obj(obj_type_pages, pages_tree_kids_max);
+ pdf_last_pages := obj_ptr;
+end;
+pdf_indirect_ln("Parent", pdf_last_pages)
+
+@ @<Generate array of annotations or beads in page@>=
+if (pdf_annot_list <> null) or (pdf_link_list <> null) then begin
+ pdf_print("/Annots [ ");
+ k := pdf_annot_list;
+ while k <> null do begin
+ pdf_print_int(info(k));
+ pdf_print(" 0 R ");
+ k := link(k);
+ end;
+ k := pdf_link_list;
+ while k <> null do begin
+ pdf_print_int(info(k));
+ pdf_print(" 0 R ");
+ k := link(k);
+ end;
+ pdf_print_ln("]");
+end;
+if pdf_bead_list <> null then begin
+ k := pdf_bead_list;
+ pdf_print("/B [ ");
+ while k <> null do begin
+ pdf_print_int(info(k));
+ pdf_print(" 0 R ");
+ k := link(k);
+ end;
+ pdf_print_ln("]");
+end
+
+@ @<Declare procedures needed in |pdf_hlist_out|, |pdf_vlist_out|@>=
+procedure pdf_write_obj(n: integer); {write a raw PDF object}
+var s: str_number;
+ f: byte_file;
+begin
+ s := tokens_to_string(obj_obj_data(n));
+ delete_toks(obj_obj_data(n));
+ if obj_obj_is_stream(n) > 0 then begin
+ pdf_begin_dict(n);
+ if obj_obj_stream_attr(n) <> null then begin
+ pdf_print_toks_ln(obj_obj_stream_attr(n));
+ delete_toks(obj_obj_stream_attr(n));
+ end;
+ pdf_begin_stream;
+ end
+ else
+ pdf_begin_obj(n);
+ if obj_obj_is_file(n) > 0 then begin
+ cur_name := s;
+ cur_area := "";
+ cur_ext := "";
+ pack_cur_name;
+ if not tex_b_openin(f) then
+ pdf_error("ext5", "cannot open file for embedding");
+ print("<<");
+ print(s);
+ while not eof(f) do
+ pdf_out(getc(f));
+ print(">>");
+ b_close(f);
+ end
+ else if obj_obj_is_stream(n) > 0 then
+ pdf_print(s)
+ else
+ pdf_print_ln(s);
+ if obj_obj_is_stream(n) > 0 then
+ pdf_end_stream
+ else
+ pdf_end_obj;
+ flush_str(s);
+end;
+
+procedure flush_whatsit_node(p: pointer; s: small_number);
+begin
+ type(p) := whatsit_node;
+ subtype(p) := s;
+ if link(p) <> null then
+ pdf_error("flush_whatsit_node", "link(p) is not null");
+ flush_node_list(p);
+end;
+
+@ @<Flush out pending raw objects@>=
+if pdf_obj_list <> null then begin
+ k := pdf_obj_list;
+ while k <> null do begin
+ if not is_obj_written(info(k)) then
+ pdf_write_obj(info(k));
+ k := link(k);
+ end;
+end
+
+@ When flushing pending forms we need to save and restore resources lists
+ (|pdf_font_list|, |pdf_obj_list|, |pdf_xform_list| and |pdf_ximage_list|),
+ which are also used by page shipping.
+
+@<Flush out pending forms@>=
+if pdf_xform_list <> null then begin
+ k := pdf_xform_list;
+ while k <> null do begin
+ if not is_obj_written(info(k)) then begin
+ pdf_cur_form := info(k);
+ @<Save resources lists@>;
+ @<Reset resources lists@>;
+ pdf_ship_out(obj_xform_box(pdf_cur_form), false);
+ @<Restore resources lists@>;
+ end;
+ k := link(k);
+ end;
+end
+
+@ @<Save resources lists@>=
+save_font_list := pdf_font_list;
+save_obj_list := pdf_obj_list;
+save_xform_list := pdf_xform_list;
+save_ximage_list := pdf_ximage_list;
+save_text_procset := pdf_text_procset;
+save_image_procset := pdf_image_procset
+
+@ @<Restore resources lists@>=
+pdf_font_list := save_font_list;
+pdf_obj_list := save_obj_list;
+pdf_xform_list := save_xform_list;
+pdf_ximage_list := save_ximage_list;
+pdf_text_procset := save_text_procset;
+pdf_image_procset := save_image_procset
+
+@ @<Declare procedures needed in |pdf_hlist_out|, |pdf_vlist_out|@>=
+procedure pdf_write_image(n: integer); {write an image}
+begin
+ pdf_begin_dict(n);
+ if obj_ximage_attr(n) <> null then begin
+ pdf_print_toks_ln(obj_ximage_attr(n));
+ delete_toks(obj_ximage_attr(n));
+ end;
+ write_image(obj_ximage_data(n));
+ delete_image(obj_ximage_data(n));
+end;
+
+@ @<Flush out pending images@>=
+if pdf_ximage_list <> null then begin
+ k := pdf_ximage_list;
+ while k <> null do begin
+ if not is_obj_written(info(k)) then
+ pdf_write_image(info(k));
+ k := link(k);
+ end;
+end
+
+@ @<Flush out pending PDF marks@>=
+pdf_origin_h := 0;
+pdf_origin_v := cur_page_height;
+@<Flush out PDF annotations@>;
+@<Flush out PDF link annotations@>;
+@<Flush out PDF mark destinations@>;
+@<Flush out PDF bead rectangle specifications@>
+
+@ @<Flush out PDF annotations@>=
+if pdf_annot_list <> null then begin
+ k := pdf_annot_list;
+ while k <> null do begin
+ i := obj_annot_ptr(info(k)); {|i| points to |pdf_annot_node|}
+ pdf_begin_dict(info(k));
+ pdf_print_ln("/Type /Annot");
+ pdf_print_toks_ln(pdf_annot_data(i));
+ pdf_rectangle(pdf_left(i), pdf_top(i), pdf_right(i), pdf_bottom(i));
+ pdf_end_dict;
+ k := link(k);
+ end;
+end
+
+@ @<Flush out PDF link annotations@>=
+if pdf_link_list <> null then begin
+ @<Write out PDF link annotations@>;
+ @<Free PDF link annotations@>;
+end
+
+@ @<Write out PDF link annotations@>=
+k := pdf_link_list;
+while k <> null do begin
+ i := obj_annot_ptr(info(k));
+ pdf_begin_dict(info(k));
+ pdf_print_ln("/Type /Annot");
+ if pdf_link_attr(i) <> null then
+ pdf_print_toks_ln(pdf_link_attr(i));
+ pdf_rectangle(pdf_left(i), pdf_top(i), pdf_right(i), pdf_bottom(i));
+ if pdf_action_type(pdf_link_action(i)) <> pdf_action_user
+ then begin
+ pdf_print_ln("/Subtype /Link");
+ pdf_print("/A ");
+ end;
+ write_action(pdf_link_action(i));
+ pdf_end_dict;
+ k := link(k);
+end
+
+@ @<Free PDF link annotations@>=
+k := pdf_link_list;
+while k <> null do begin
+ i := obj_annot_ptr(info(k));
+ {nodes with |info = null| were created by |append_link| and
+ must be flushed here, as they are not linked in any list}
+ if info(i) = max_halfword then
+ flush_whatsit_node(i, pdf_start_link_node);
+ k := link(k);
+end
+
+@ @<Flush out PDF mark destinations@>=
+if pdf_dest_list <> null then begin
+ k := pdf_dest_list;
+ while k <> null do begin
+ if is_obj_written(info(k)) then
+ pdf_error("ext5",
+ "destination has been already written (this shouldn't happen)")
+ else begin
+ i := obj_dest_ptr(info(k));
+ if pdf_dest_named_id(i) > 0 then begin
+ pdf_begin_dict(info(k));
+ pdf_print("/D ");
+ end
+ else
+ pdf_begin_obj(info(k));
+ pdf_out("["); pdf_print_int(pdf_last_page); pdf_print(" 0 R ");
+ case pdf_dest_type(i) of
+ pdf_dest_xyz: begin
+ pdf_print("/XYZ ");
+ pdf_print_mag_bp(pdf_x(pdf_left(i))); pdf_out(" ");
+ pdf_print_mag_bp(pdf_y(pdf_top(i))); pdf_out(" ");
+ if pdf_dest_xyz_zoom(i) = null then
+ pdf_print("null")
+ else begin
+ pdf_print_int(pdf_dest_xyz_zoom(i) div 1000);
+ pdf_out(".");
+ pdf_print_int((pdf_dest_xyz_zoom(i) mod 1000));
+ end;
+ end;
+ pdf_dest_fit:
+ pdf_print("/Fit");
+ pdf_dest_fith: begin
+ pdf_print("/FitH ");
+ pdf_print_mag_bp(pdf_y(pdf_top(i)));
+ end;
+ pdf_dest_fitv: begin
+ pdf_print("/FitV ");
+ pdf_print_mag_bp(pdf_x(pdf_left(i)));
+ end;
+ pdf_dest_fitb:
+ pdf_print("/FitB");
+ pdf_dest_fitbh: begin
+ pdf_print("/FitBH ");
+ pdf_print_mag_bp(pdf_y(pdf_top(i)));
+ end;
+ pdf_dest_fitbv: begin
+ pdf_print("/FitBV ");
+ pdf_print_mag_bp(pdf_x(pdf_left(i)));
+ end;
+ pdf_dest_fitr: begin
+ pdf_print("/FitR ");
+ pdf_print_rect_spec(i);
+ end;
+ othercases pdf_error("ext5", "unknown dest type");
+ endcases;
+ pdf_print_ln("]");
+ if pdf_dest_named_id(i) > 0 then
+ pdf_end_dict
+ else
+ pdf_end_obj;
+ end;
+ k := link(k);
+ end;
+end
+
+@ @<Declare procedures needed in |pdf_hlist_out|, |pdf_vlist_out|@>=
+procedure pdf_print_rect_spec(r: pointer); {prints a rect spec}
+begin
+ pdf_print_mag_bp(pdf_x(pdf_left(r)));
+ pdf_out(" ");
+ pdf_print_mag_bp(pdf_y(pdf_bottom(r)));
+ pdf_out(" ");
+ pdf_print_mag_bp(pdf_x(pdf_right(r)));
+ pdf_out(" ");
+ pdf_print_mag_bp(pdf_y(pdf_top(r)));
+end;
+
+@ @<Flush out PDF bead rectangle specifications@>=
+if pdf_bead_list <> null then begin
+ k := pdf_bead_list;
+ while k <> null do begin
+ pdf_new_obj(obj_type_others, 0);
+ pdf_out("[");
+ i := obj_bead_data(info(k)); {pointer to a whatsit or whatsit-like node}
+ pdf_print_rect_spec(i);
+ if info(i) = max_halfword then {not a whatsit node, so must be destroyed here}
+ flush_whatsit_node(i, pdf_start_thread_node);
+ pdf_print_ln("]");
+ obj_bead_rect(info(k)) := obj_ptr; {rewrite |obj_bead_data|}
+ pdf_end_obj;
+ k := link(k);
+ end;
+end
+
+@ In the end we must flush PDF objects that cannot be written out
+immediately after shipping out pages.
+
+@ @<Output outlines@>=
+if pdf_first_outline <> 0 then begin
+ pdf_new_dict(obj_type_others, 0);
+ outlines := obj_ptr;
+ l := pdf_first_outline; k := 0;
+ repeat
+ incr(k);
+ a := open_subentries(l);
+ if obj_outline_count(l) > 0 then
+ k := k + a;
+ obj_outline_parent(l) := obj_ptr;
+ l := obj_outline_next(l);
+ until l = 0;
+ pdf_print_ln("/Type /Outlines");
+ pdf_indirect_ln("First", pdf_first_outline);
+ pdf_indirect_ln("Last", pdf_last_outline);
+ pdf_int_entry_ln("Count", k);
+ pdf_end_dict;
+ @<Output PDF outline entries@>;
+end
+else
+ outlines := 0
+
+@ @<Output PDF outline entries@>=
+k := head_tab[obj_type_outline];
+while k <> 0 do begin
+ if obj_outline_parent(k) = pdf_parent_outline then begin
+ if obj_outline_prev(k) = 0 then
+ pdf_first_outline := k;
+ if obj_outline_next(k) = 0 then
+ pdf_last_outline := k;
+ end;
+ pdf_begin_dict(k);
+ pdf_indirect_ln("Title", obj_outline_title(k));
+ pdf_indirect_ln("A", obj_outline_action_objnum(k));
+ if obj_outline_parent(k) <> 0 then
+ pdf_indirect_ln("Parent", obj_outline_parent(k));
+ if obj_outline_prev(k) <> 0 then
+ pdf_indirect_ln("Prev", obj_outline_prev(k));
+ if obj_outline_next(k) <> 0 then
+ pdf_indirect_ln("Next", obj_outline_next(k));
+ if obj_outline_first(k) <> 0 then
+ pdf_indirect_ln("First", obj_outline_first(k));
+ if obj_outline_last(k) <> 0 then
+ pdf_indirect_ln("Last", obj_outline_last(k));
+ if obj_outline_count(k) <> 0 then
+ pdf_int_entry_ln("Count", obj_outline_count(k));
+ if obj_outline_attr(k) <> 0 then begin
+ pdf_print_toks_ln(obj_outline_attr(k));
+ delete_toks(obj_outline_attr(k));
+ end;
+ pdf_end_dict;
+ k := obj_link(k);
+end
+
+@ @<Output article threads@>=
+if head_tab[obj_type_thread] <> 0 then begin
+ pdf_new_obj(obj_type_others, 0);
+ threads := obj_ptr;
+ pdf_out("[");
+ k := head_tab[obj_type_thread];
+ while k <> 0 do begin
+ pdf_print_int(k);
+ pdf_print(" 0 R ");
+ k := obj_link(k);
+ end;
+ remove_last_space;
+ pdf_print_ln("]");
+ pdf_end_obj;
+ k := head_tab[obj_type_thread];
+ while k <> 0 do begin
+ out_thread(k);
+ k := obj_link(k);
+ end;
+end
+else
+ threads := 0
+
+@ Now we are ready to declare our new procedure |ship_out|. It will call
+|pdf_ship_out| if the integer parameter |pdf_output| is positive; otherwise it
+will call |dvi_ship_out|, which is the \TeX\ original |ship_out|.
+
+@p procedure ship_out(p:pointer); {output the box |p|}
+begin
+ fix_pdfoutput;
+ if pdf_output > 0 then
+ pdf_ship_out(p, true)
+ else
+ dvi_ship_out(p);
+end;
+
+@ @<Initialize variables for \.{PDF} output@>=
+ensure_pdf_open;
+check_pdfminorversion;
+prepare_mag;
+fixed_decimal_digits := fix_int(pdf_decimal_digits, 0, 4);
+min_bp_val :=
+ divide_scaled(one_hundred_bp, ten_pow[fixed_decimal_digits + 2], 0);
+fixed_pk_resolution := fix_int(pdf_pk_resolution, 72, 2400);
+pk_scale_factor :=
+ divide_scaled(72, fixed_pk_resolution, 5 + fixed_decimal_digits);
+if pdf_pk_mode <> null then begin
+ kpse_init_prog('PDFTEX', fixed_pk_resolution,
+ make_cstring(tokens_to_string(pdf_pk_mode)), nil);
+ flush_string;
+end else
+ kpse_init_prog('PDFTEX', fixed_pk_resolution, nil, nil);
+if not kpse_var_value('MKTEXPK') then
+ kpse_set_program_enabled (kpse_pk_format, 1, kpse_src_cmdline);
+set_job_id(year, month, day, time, pdftex_version, pdftex_revision);
+if (pdf_unique_resname > 0) and (pdf_resname_prefix = 0) then
+ pdf_resname_prefix := get_resname_prefix
+
+@ Finishing the PDF output file.
+
+The following procedures sort the table of destination names
+@p function str_less_str(s1, s2: str_number): boolean; {compare two strings}
+var j1, j2: pool_pointer;
+ l, i: integer;
+begin
+ j1 := str_start[s1];
+ j2 := str_start[s2];
+ if length(s1) < length(s2) then
+ l := length(s1)
+ else
+ l := length(s2);
+ i := 0;
+ while (i < l) and (str_pool[j1 + i] = str_pool[j2 + i]) do
+ incr(i);
+ if ((i < l) and (str_pool[j1 + i] < str_pool[j2 + i])) or
+ ((i = l) and (length(s1) < length(s2))) then
+ str_less_str := true
+ else
+ str_less_str := false;
+end;
+
+procedure sort_dest_names(l, r: integer); {sorts |dest_names| by names}
+var i, j: integer;
+ s: str_number;
+ x, y: integer;
+ e: dest_name_entry;
+begin
+ i := l;
+ j := r;
+ s := dest_names[(l + r) div 2].objname;
+ repeat
+ while str_less_str(dest_names[i].objname, s) do
+ incr(i);
+ while str_less_str(s, dest_names[j].objname) do
+ decr(j);
+ if i <= j then begin
+ e := dest_names[i];
+ dest_names[i] := dest_names[j];
+ dest_names[j] := e;
+ incr(i);
+ decr(j);
+ end;
+ until i > j;
+ if l < j then
+ sort_dest_names(l, j);
+ if i < r then
+ sort_dest_names(i, r);
+end;
+
+@ Now the finish of PDF output file. At this moment all Page objects
+are already written completely to PDF output file.
+
+@<Finish the PDF file@>=
+if total_pages=0 then print_nl("No pages of output.")
+@.No pages of output@>
+else begin
+ pdf_flush; {to make sure that the output file name has been already
+ created}
+ if total_pages mod pages_tree_kids_max <> 0 then
+ obj_info(pdf_last_pages) := total_pages mod pages_tree_kids_max;
+ {last pages object may have less than |pages_tree_kids_max| chilrend}
+ @<Check for non-existing pages@>;
+ @<Reverse the linked list of Page and Pages objects@>;
+ @<Check for non-existing destinations@>;
+ @<Output fonts definition@>;
+ @<Output pages tree@>;
+ @<Output outlines@>;
+ @<Output name tree@>;
+ @<Output article threads@>;
+ @<Output the catalog object@>;
+ pdf_print_info;
+ @<Output the |obj_tab|@>;
+ @<Output the trailer@>;
+ pdf_flush;
+ print_nl("Output written on "); print_file_name(0, output_file_name, 0);
+ @.Output written on x@>
+ print(" ("); print_int(total_pages); print(" page");
+ if total_pages<>1 then print_char("s");
+ print(", "); print_int(pdf_offset); print(" bytes).");
+ libpdffinish;
+ b_close(pdf_file);
+end
+
+@ Destinations that have been referenced but don't exists have
+|obj_dest_ptr=null|. Leaving them undefined might cause troubles for
+PDF browsers, so we need to fix them.
+
+@p procedure pdf_fix_dest(k: integer);
+begin
+ if obj_dest_ptr(k) <> null then
+ return;
+ pdf_warning("dest", "", false);
+ if obj_info(k) < 0 then begin
+ print("name{");
+ print(-obj_info(k));
+ print("}");
+ end
+ else begin
+ print("num");
+ print_int(obj_info(k));
+ end;
+ print(" has been referenced but does not exist, replaced by a fixed one");
+ print_ln; print_ln;
+ pdf_begin_obj(k);
+ pdf_out("[");
+ pdf_print_int(head_tab[obj_type_page]);
+ pdf_print_ln(" 0 R /Fit]");
+ pdf_end_obj;
+end;
+
+@ @<Check for non-existing destinations@>=
+k := head_tab[obj_type_dest];
+while k <> 0 do begin
+ pdf_fix_dest(k);
+ k := obj_link(k);
+end
+
+@ @<Check for non-existing pages@>=
+k := head_tab[obj_type_page];
+while obj_aux(k) = 0 do begin
+ pdf_warning("dest", "Page ", false);
+ print_int(obj_info(k));
+ print(" has been referenced but does not exist!");
+ print_ln; print_ln;
+ k := obj_link(k);
+end;
+head_tab[obj_type_page] := k
+
+@ @<Reverse the linked list of Page and Pages objects@>=
+k := head_tab[obj_type_page];
+l := 0;
+repeat
+ i := obj_link(k);
+ obj_link(k) := l;
+ l := k;
+ k := i;
+until k = 0;
+head_tab[obj_type_page] := l;
+k := head_tab[obj_type_pages];
+l := 0;
+repeat
+ i := obj_link(k);
+ obj_link(k) := l;
+ l := k;
+ k := i;
+until k = 0;
+head_tab[obj_type_pages] := l
+
+@ @<Output fonts definition@>=
+for k := font_base + 1 to font_ptr do
+ if font_used[k] and hasfmentry(k) then begin
+ if pdf_font_num[k] < 0 then
+ i := -pdf_font_num[k]
+ else
+ i := tfm_of_fm(pdf_font_map[k]);
+ if i <> k then
+ for j := 0 to 255 do
+ if pdf_char_marked(k, j) then
+ pdf_mark_char(i, j);
+ end;
+k := head_tab[obj_type_font];
+while k <> 0 do begin
+ f := obj_info(k);
+ do_pdf_font(k, f);
+ k := obj_link(k);
+end
+
+@ We will generate in each single step the parents of all Pages/Page objects in
+the previous level. These new generated Pages object will create a new level of
+Pages tree. We will repeat this until search only one Pages object. This one
+will be the Root object.
+
+@<Output pages tree@>=
+a := obj_ptr + 1; {all Pages objects whose children are not Page objects
+should have index greater than |a|}
+l := head_tab[obj_type_pages]; {|l| is the index of current Pages object which is
+being output}
+k := head_tab[obj_type_page]; {|k| is the index of current child of |l|}
+if obj_link(l) = 0 then
+ is_root := true {only Pages object; total pages is not greater than
+ |pages_tree_kids_max|}
+else
+ is_root := false;
+b := obj_ptr + 1; {to init |c| in next step}
+repeat
+ i := 0; {counter of Pages object in current level}
+ c := b; {first Pages object in previous level}
+ b := obj_ptr + 1; {succcesor of last created object}
+ repeat
+ if not is_root then begin
+ if i mod pages_tree_kids_max = 0 then begin {create a new Pages object for next level}
+ pdf_last_pages := pdf_new_objnum;
+ obj_info(pdf_last_pages) := obj_info(l);
+ end
+ else
+ obj_info(pdf_last_pages) := obj_info(pdf_last_pages) +
+ obj_info(l);
+ end;
+ @<Output the current Pages object in this level@>;
+ incr(i);
+ if l < a then
+ l := obj_link(l)
+ else
+ incr(l);
+ until (l = 0) or (l = b);
+ if l = 0 then
+ l := a;
+ if b = obj_ptr then
+ is_root := true;
+until false;
+done:
+
+@ @<Output the current Pages object in this level@>=
+pdf_begin_dict(l);
+pdf_print_ln("/Type /Pages");
+pdf_int_entry_ln("Count", obj_info(l));
+if not is_root then
+ pdf_indirect_ln("Parent", pdf_last_pages);
+pdf_print("/Kids [");
+j := 0;
+repeat
+ pdf_print_int(k);
+ pdf_print(" 0 R ");
+ if k < a then {the next Pages/Page object must be |obj_link(k)|}
+ k := obj_link(k)
+ else {|k >= a|, the next Pages object is |k + 1|}
+ incr(k);
+ incr(j);
+until ((l < a) and (j = obj_info(l))) or
+ (k = 0) or (k = c) or
+ (j = pages_tree_kids_max);
+remove_last_space;
+pdf_print_ln("]");
+if k = 0 then begin
+ if head_tab[obj_type_pages] <> 0 then begin {we are in Page objects list}
+ k := head_tab[obj_type_pages];
+ head_tab[obj_type_pages] := 0;
+ end
+ else {we are in Pages objects list}
+ k := a;
+end;
+if is_root and (pdf_pages_attr <> null) then
+ pdf_print_toks_ln(pdf_pages_attr);
+pdf_end_dict;
+if is_root then
+ goto done
+
+@ The name tree is very similiar to Pages tree so its construction should be
+certain from Pages tree construction. For intermediate node |obj_info| will be
+the first name and |obj_link| will be the last name in \.{\\Limits} array.
+Note that |pdf_dest_names_ptr| will be less than |obj_ptr|, so we test if
+|k < pdf_dest_names_ptr| then |k| is index of leaf in |dest_names|; else
+|k| will be index in |obj_tab| of some intermediate node.
+
+@<Output name tree@>=
+if pdf_dest_names_ptr = 0 then begin
+ dests := 0;
+ goto done1;
+end;
+sort_dest_names(0, pdf_dest_names_ptr - 1);
+a := obj_ptr + 1; {first intermediate node of name tree}
+l := a; {index of node being output}
+k := 0; {index of current child of |l|; if |k < pdf_dest_names_ptr| then this is
+pointer to |dest_names| array; otherwise it is the pointer to |obj_tab|
+(object number) }
+repeat
+ c := obj_ptr + 1; {first node in current level}
+ repeat
+ pdf_create_obj(obj_type_others, 0); {create a new node for next level}
+ @<Output the current node in this level@>;
+ incr(l);
+ incr(i);
+ until k = c;
+until false;
+done1:
+if (dests <> 0) or (pdf_names_toks <> null) then begin
+ pdf_new_dict(obj_type_others, 0);
+ if (dests <> 0) then
+ pdf_indirect_ln("Dests", dests);
+ if pdf_names_toks <> null then begin
+ pdf_print_toks_ln(pdf_names_toks);
+ delete_toks(pdf_names_toks);
+ end;
+ pdf_end_dict;
+ names_tree := obj_ptr;
+end
+else
+ names_tree := 0
+
+@ @<Output the current node in this level@>=
+pdf_begin_dict(l);
+j := 0;
+if k < pdf_dest_names_ptr then begin
+ obj_info(l) := dest_names[k].objname;
+ pdf_print("/Names [");
+ repeat
+ pdf_print_str(dest_names[k].objname);
+ pdf_out(" ");
+ pdf_print_int(dest_names[k].objnum);
+ pdf_print(" 0 R ");
+ incr(j);
+ incr(k);
+ until (j = name_tree_kids_max) or (k = pdf_dest_names_ptr);
+ remove_last_space;
+ pdf_print_ln("]");
+ obj_link(l) := dest_names[k - 1].objname;
+ if k = pdf_dest_names_ptr then
+ k := a;
+end
+else begin
+ obj_info(l) := obj_info(k);
+ pdf_print("/Kids [");
+ repeat
+ pdf_print_int(k);
+ pdf_print(" 0 R ");
+ incr(j);
+ incr(k);
+ until (j = name_tree_kids_max) or (k = c);
+ remove_last_space;
+ pdf_print_ln("]");
+ obj_link(l) := obj_link(k - 1);
+end;
+if (l > k) or (l = a) then begin
+ pdf_print("/Limits [");
+ pdf_print_str(obj_info(l));
+ pdf_out(" ");
+ pdf_print_str(obj_link(l));
+ pdf_print_ln("]");
+ pdf_end_dict;
+end
+else begin
+ pdf_end_dict;
+ dests := l;
+ goto done1;
+end
+
+@ @<Output the catalog object@>=
+pdf_new_dict(obj_type_others, 0);
+root := obj_ptr;
+pdf_print_ln("/Type /Catalog");
+pdf_indirect_ln("Pages", pdf_last_pages);
+if threads <> 0 then
+ pdf_indirect_ln("Threads", threads);
+if outlines <> 0 then
+ pdf_indirect_ln("Outlines", outlines);
+if names_tree <> 0 then
+ pdf_indirect_ln("Names", names_tree);
+if pdf_catalog_toks <> null then begin
+ pdf_print_toks_ln(pdf_catalog_toks);
+ delete_toks(pdf_catalog_toks);
+end;
+if pdf_catalog_openaction <> 0 then
+ pdf_indirect_ln("OpenAction", pdf_catalog_openaction);
+pdf_end_dict
+
+@ If the same keys in a dictionary are given several times,
+then it is not defined which value is choosen by an application.
+Therefore the keys |/Producer| and |/Creator| are only set,
+if the token list |pdf_info_toks|, converted to a string does
+not contain these key strings.
+
+@p function substr_of_str(s, t: str_number):boolean;
+label continue,exit;
+var j, k, kk: pool_pointer; {running indices}
+begin
+ k:=str_start[t];
+ while (k < str_start[t+1] - length(s)) do begin
+ j:=str_start[s];
+ kk:=k;
+ while (j < str_start[s+1]) do begin
+ if str_pool[j] <> str_pool[kk] then
+ goto continue;
+ incr(j);
+ incr(kk);
+ end;
+ substr_of_str:=true;
+ return;
+ continue: incr(k);
+ end;
+ substr_of_str:=false;
+end;
+
+procedure pdf_print_info; {print info object}
+var s: str_number;
+ creator_given, producer_given, creationdate_given: boolean;
+begin
+ pdf_new_dict(obj_type_others, 0);
+ creator_given:=false;
+ producer_given:=false;
+ creationdate_given:=false;
+ if pdf_info_toks <> null then begin
+ s:=tokens_to_string(pdf_info_toks);
+ creator_given:=substr_of_str("/Creator", s);
+ producer_given:=substr_of_str("/Producer", s);
+ creationdate_given:=substr_of_str("/CreationDate", s);
+ end;
+ if not producer_given then begin
+ @<Print the Producer key@>;
+ end;
+ if pdf_info_toks <> null then begin
+ if length(s) > 0 then begin
+ pdf_print(s);
+ pdf_print_nl;
+ end;
+ flush_str(s);
+ delete_toks(pdf_info_toks);
+ end;
+ if not creator_given then
+ pdf_str_entry_ln("Creator", "TeX");
+ if not creationdate_given then begin
+ @<Print the CreationDate key@>;
+ end;
+ pdf_str_entry_ln("PTEX.Fullbanner", pdftex_banner);
+ pdf_end_dict;
+end;
+
+@ @<Print the Producer key@>=
+pdf_print("/Producer (pdfTeX-");
+pdf_print_int(pdftex_version div 100);
+pdf_out(".");
+pdf_print_int(pdftex_version mod 100);
+pdf_out(".");
+pdf_print(pdftex_revision);
+pdf_print_ln(")")
+
+@ @<Print the CreationDate key@>=
+print_creation_date;
+
+@ @<Glob...@>=
+@!pdftex_banner: str_number; {the complete banner}
+
+@ @<Output the |obj_tab|@>=
+l := 0;
+for k := 1 to obj_ptr do
+ if obj_offset(k) = 0 then begin
+ obj_link(l) := k;
+ l := k;
+ end;
+obj_link(l) := 0;
+pdf_save_offset := pdf_offset;
+pdf_print_ln("xref");
+pdf_print("0 "); pdf_print_int_ln(obj_ptr + 1);
+pdf_print_fw_int(obj_link(0), 10);
+pdf_print_ln(" 65535 f ");
+for k := 1 to obj_ptr do begin
+ if obj_offset(k) = 0 then begin
+ pdf_print_fw_int(obj_link(k), 10);
+ pdf_print_ln(" 00000 f ");
+ end
+ else begin
+ pdf_print_fw_int(obj_offset(k), 10);
+ pdf_print_ln(" 00000 n ");
+ end;
+end
+
+@ @<Output the trailer@>=
+pdf_print_ln("trailer");
+pdf_print("<< ");
+pdf_int_entry_ln("Size", obj_ptr + 1);
+pdf_indirect_ln("Root", root);
+pdf_indirect_ln("Info", obj_ptr);
+if pdf_trailer_toks <> null then begin
+ pdf_print_toks_ln(pdf_trailer_toks);
+ delete_toks(pdf_trailer_toks);
+end;
+print_ID(output_file_name);
+pdf_print_ln(" >>");
+pdf_print_ln("startxref");
+pdf_print_int_ln(pdf_save_offset);
+pdf_print_ln("%%EOF")
+
+@* \[33] Packaging.
+@z
+
+@x [649]
+exit: hpack:=r;
+@y
+exit: {|hpack|}
+hpack:=r;
+@z
+
+@x [651]
+ kern_node,math_node: x:=x+width(p);
+@y
+ kern_node: x:=x+width(p);
+ math_node: x:=x+width(p);
+@z
+
+@x [888] - fixlinedimen
+append_to_vlist(just_box);
+@y
+if pdf_each_line_height <> 0 then
+ height(just_box) := pdf_each_line_height;
+if pdf_each_line_depth <> 0 then
+ depth(just_box) := pdf_each_line_depth;
+if (pdf_first_line_height <> 0) and (cur_line = prev_graf + 1) then
+ height(just_box) := pdf_first_line_height;
+if (pdf_last_line_depth <> 0) and (cur_line + 1 = best_line) then
+ depth(just_box) := pdf_last_line_depth;
+append_to_vlist(just_box);
+@z
+
+@x [889]
+adjust_tail:=adjust_head; just_box:=hpack(q,cur_width,exactly);
+@y
+adjust_tail:=adjust_head;
+just_box:=hpack(q,cur_width,exactly);
+@z
+
+@x [1088] - quitvmode
+@ A paragraph begins when horizontal-mode material occurs in vertical mode,
+or when the paragraph is explicitly started by `\.{\\indent}' or
+`\.{\\noindent}'.
+
+@<Put each...@>=
+primitive("indent",start_par,1);
+@!@:indent_}{\.{\\indent} primitive@>
+primitive("noindent",start_par,0);
+@!@:no_indent_}{\.{\\noindent} primitive@>
+@y
+@ Here is a really small patch to add a new primitive called
+\.{\\quitvmode}. In vertical modes, it is identical to \.{\\indent},
+but in horizontal and math modes it is really a no-op (as opposed to
+\.{\\indent}, which executes the |indent_in_hmode| procedure).
+
+A paragraph begins when horizontal-mode material occurs in vertical mode,
+or when the paragraph is explicitly started by `\.{\\quitvmode}',
+`\.{\\indent}' or `\.{\\noindent}'.
+
+@<Put each...@>=
+primitive("indent",start_par,1);
+@!@:indent_}{\.{\\indent} primitive@>
+primitive("noindent",start_par,0);
+@!@:no_indent_}{\.{\\noindent} primitive@>
+primitive("quitvmode",start_par,2);
+@!@:quit_vmode_}{\.{\\quitvmode} primitive@>
+@z
+
+@x [1089] - quitvmode
+start_par: if chr_code=0 then print_esc("noindent")@+ else print_esc("indent");
+@y
+start_par: if chr_code=0 then print_esc("noindent")@+ else if chr_code=1 then print_esc("indent")@+ else print_esc("quitvmode");
+@z
+
+@x [1092] - quitvmode
+hmode+start_par,mmode+start_par: indent_in_hmode;
+@y
+hmode+start_par,mmode+start_par: if cur_chr<>2 then indent_in_hmode;
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Declare the necessary variables for finishing PDF file
+% Close PDF output if necessary
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x [1333]
+procedure close_files_and_terminate;
+var k:integer; {all-purpose index}
+begin @<Finish the extensions@>;
+@!stat if tracing_stats>0 then @<Output statistics about this job@>;@;@+tats@/
+wake_up_terminal; @<Finish the \.{DVI} file@>;
+@y
+procedure close_files_and_terminate;
+label done, done1;
+var a, b, c, i, j, k, l: integer; {all-purpose index}
+ is_root: boolean; {|pdf_last_pages| is root of Pages tree?}
+ root, outlines, threads, names_tree, dests, fixed_dest: integer;
+begin @<Finish the extensions@>;
+@!stat if tracing_stats>0 then @<Output statistics about this job@>;@;@+tats@/
+wake_up_terminal;
+if fixed_pdfoutput > 0 then begin
+ if history = fatal_error_stop then
+ print_err(" ==> Fatal error occurred, the output PDF file is not finished!")
+ else begin
+ @<Finish the PDF file@>;
+ end;
+end
+else begin
+ @<Finish the \.{DVI} file@>;
+end;
+@z
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Output statistics about the pdftex specific sizes only in PDF mode.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x [1334]
+ wlog_ln(' ',max_in_stack:1,'i,',max_nest_stack:1,'n,',@|
+ max_param_stack:1,'p,',@|
+ max_buf_stack+1:1,'b,',@|
+ max_save_stack+6:1,'s stack positions out of ',@|
+ stack_size:1,'i,',
+ nest_size:1,'n,',
+ param_size:1,'p,',
+ buf_size:1,'b,',
+ save_size:1,'s');
+ end
+@y
+ wlog_ln(' ',max_in_stack:1,'i,',max_nest_stack:1,'n,',@|
+ max_param_stack:1,'p,',@|
+ max_buf_stack+1:1,'b,',@|
+ max_save_stack+6:1,'s stack positions out of ',@|
+ stack_size:1,'i,',
+ nest_size:1,'n,',
+ param_size:1,'p,',
+ buf_size:1,'b,',
+ save_size:1,'s');
+ if (pdf_output > 0) then begin
+ wlog_ln('PDF statistics:');
+ wlog_ln(' ',obj_ptr:1,' PDF objects out of ',obj_tab_size:1);
+ wlog_ln(' ',pdf_dest_names_ptr:1,' named destinations out of ',dest_names_size:1);
+ wlog_ln(' ',pdf_mem_ptr:1,' words of extra memory for PDF output out of ',pdf_mem_size:1);
+ end;
+ end
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Override pdf_output value from format file with command line option
+% and initialize other options
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+ while (loc<limit)and(buffer[loc]=" ") do incr(loc);
+ end;
+@y
+ while (loc<limit)and(buffer[loc]=" ") do incr(loc);
+ end;
+if (pdf_output_option <> 0) then pdf_output := pdf_output_value;
+pdf_init_map_file('pdftex.map');
+@z
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% PDF-speficic extensions that don't fall to any previous category
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x [1344]
+@d set_language_code=5 {command modifier for \.{\\setlanguage}}
+@y
+@d set_language_code=5 {command modifier for \.{\\setlanguage}}
+@d pdftex_first_extension_code = 6
+@d pdf_literal_node == pdftex_first_extension_code + 0
+@d pdf_obj_code == pdftex_first_extension_code + 1
+@d pdf_refobj_node == pdftex_first_extension_code + 2
+@d pdf_xform_code == pdftex_first_extension_code + 3
+@d pdf_refxform_node == pdftex_first_extension_code + 4
+@d pdf_ximage_code == pdftex_first_extension_code + 5
+@d pdf_refximage_node == pdftex_first_extension_code + 6
+@d pdf_annot_node == pdftex_first_extension_code + 7
+@d pdf_start_link_node == pdftex_first_extension_code + 8
+@d pdf_end_link_node == pdftex_first_extension_code + 9
+@d pdf_outline_code == pdftex_first_extension_code + 10
+@d pdf_dest_node == pdftex_first_extension_code + 11
+@d pdf_thread_node == pdftex_first_extension_code + 12
+@d pdf_start_thread_node == pdftex_first_extension_code + 13
+@d pdf_end_thread_node == pdftex_first_extension_code + 14
+@d pdf_save_pos_node == pdftex_first_extension_code + 15
+@d pdf_info_code == pdftex_first_extension_code + 16
+@d pdf_catalog_code == pdftex_first_extension_code + 17
+@d pdf_names_code == pdftex_first_extension_code + 18
+@d pdf_font_attr_code == pdftex_first_extension_code + 19
+@d pdf_include_chars_code == pdftex_first_extension_code + 20
+@d pdf_map_file_code == pdftex_first_extension_code + 21
+@d pdf_map_line_code == pdftex_first_extension_code + 22
+@d pdf_trailer_code == pdftex_first_extension_code + 23
+@d pdf_strcmp_code == pdftex_first_extension_code + 24
+@d pdf_escape_string_code == pdftex_first_extension_code + 25
+@d pdf_escape_name_code == pdftex_first_extension_code + 26
+@d reset_timer_code == pdftex_first_extension_code + 27
+@d pdftex_last_extension_code == pdftex_first_extension_code + 27
+@z
+
+@x [1344]
+primitive("setlanguage",extension,set_language_code);@/
+@!@:set_language_}{\.{\\setlanguage} primitive@>
+@y
+primitive("setlanguage",extension,set_language_code);@/
+@!@:set_language_}{\.{\\setlanguage} primitive@>
+primitive("pdfliteral",extension,pdf_literal_node);@/
+@!@:pdf_literal_}{\.{\\pdfliteral} primitive@>
+primitive("pdfobj",extension,pdf_obj_code);@/
+@!@:pdf_obj_}{\.{\\pdfobj} primitive@>
+primitive("pdfrefobj",extension,pdf_refobj_node);@/
+@!@:pdf_refobj_}{\.{\\pdfrefobj} primitive@>
+primitive("pdfxform",extension,pdf_xform_code);@/
+@!@:pdf_xform_}{\.{\\pdfxform} primitive@>
+primitive("pdfrefxform",extension,pdf_refxform_node);@/
+@!@:pdf_refxform_}{\.{\\pdfrefxform} primitive@>
+primitive("pdfximage",extension,pdf_ximage_code);@/
+@!@:pdf_ximage_}{\.{\\pdfximage} primitive@>
+primitive("pdfrefximage",extension,pdf_refximage_node);@/
+@!@:pdf_refximage_}{\.{\\pdfrefximage} primitive@>
+primitive("pdfannot",extension,pdf_annot_node);@/
+@!@:pdf_annot_}{\.{\\pdfannot} primitive@>
+primitive("pdfstartlink",extension,pdf_start_link_node);@/
+@!@:pdf_start_link_}{\.{\\pdfstartlink} primitive@>
+primitive("pdfendlink",extension,pdf_end_link_node);@/
+@!@:pdf_end_link_}{\.{\\pdfendlink} primitive@>
+primitive("pdfoutline",extension,pdf_outline_code);@/
+@!@:pdf_outline_}{\.{\\pdfoutline} primitive@>
+primitive("pdfdest",extension,pdf_dest_node);@/
+@!@:pdf_dest_}{\.{\\pdfdest} primitive@>
+primitive("pdfthread",extension,pdf_thread_node);@/
+@!@:pdf_thread_}{\.{\\pdfthread} primitive@>
+primitive("pdfstartthread",extension,pdf_start_thread_node);@/
+@!@:pdf_start_thread_}{\.{\\pdfstartthread} primitive@>
+primitive("pdfendthread",extension,pdf_end_thread_node);@/
+@!@:pdf_end_thread_}{\.{\\pdfendthread} primitive@>
+primitive("pdfsavepos",extension,pdf_save_pos_node);@/
+@!@:pdf_save_pos_}{\.{\\pdfsavepos} primitive@>
+primitive("pdfinfo",extension,pdf_info_code);@/
+@!@:pdf_info_}{\.{\\pdfinfo} primitive@>
+primitive("pdfcatalog",extension,pdf_catalog_code);@/
+@!@:pdf_catalog_}{\.{\\pdfcatalog} primitive@>
+primitive("pdfnames",extension,pdf_names_code);@/
+@!@:pdf_names_}{\.{\\pdfnames} primitive@>
+primitive("pdfincludechars",extension,pdf_include_chars_code);@/
+@!@:pdf_include_chars_}{\.{\\pdfincludechars} primitive@>
+primitive("pdffontattr",extension,pdf_font_attr_code);@/
+@!@:pdf_font_attr_}{\.{\\pdffontattr} primitive@>
+primitive("pdfmapfile",extension,pdf_map_file_code);@/
+@!@:pdf_map_file_}{\.{\\pdfmapfile} primitive@>
+primitive("pdfmapline",extension,pdf_map_line_code);@/
+@!@:pdf_map_line_}{\.{\\pdfmapline} primitive@>
+primitive("pdftrailer",extension,pdf_trailer_code);@/
+@!@:pdf_trailer_}{\.{\\pdftrailer} primitive@>
+primitive("pdfstrcmp",extension,pdf_strcmp_code);@/
+@!@:pdf_strcmp_}{\.{\\pdfstrcmp} primitive@>
+primitive("pdfescapestring",extension,pdf_escape_string_code);@/
+@!@:pdf_escape_string_}{\.{\\pdfescapestring} primitive@>
+primitive("pdfescapename",extension,pdf_escape_name_code);@/
+@!@:pdf_escape_name_}{\.{\\pdfescapename} primitive@>
+primitive("pdfresettimer",extension,reset_timer_code);@/
+@!@:reset_timer_}{\.{\\pdfresettimer} primitive@>
+@z
+
+@x [1346]
+ set_language_code:print_esc("setlanguage");
+@y
+ set_language_code:print_esc("setlanguage");
+ pdf_literal_node: print_esc("pdfliteral");
+ pdf_obj_code: print_esc("pdfobj");
+ pdf_refobj_node: print_esc("pdfrefobj");
+ pdf_xform_code: print_esc("pdfxform");
+ pdf_refxform_node: print_esc("pdfrefxform");
+ pdf_ximage_code: print_esc("pdfximage");
+ pdf_refximage_node: print_esc("pdfrefximage");
+ pdf_annot_node: print_esc("pdfannot");
+ pdf_start_link_node: print_esc("pdfstartlink");
+ pdf_end_link_node: print_esc("pdfendlink");
+ pdf_outline_code: print_esc("pdfoutline");
+ pdf_dest_node: print_esc("pdfdest");
+ pdf_thread_node: print_esc("pdfthread");
+ pdf_start_thread_node: print_esc("pdfstartthread");
+ pdf_end_thread_node: print_esc("pdfendthread");
+ pdf_save_pos_node: print_esc("pdfsavepos");
+ pdf_info_code: print_esc("pdfinfo");
+ pdf_catalog_code: print_esc("pdfcatalog");
+ pdf_names_code: print_esc("pdfnames");
+ pdf_include_chars_code: print_esc("pdfincludechars");
+ pdf_font_attr_code: print_esc("pdffontattr");
+ pdf_map_file_code: print_esc("pdfmapfile");
+ pdf_map_line_code: print_esc("pdfmapline");
+ pdf_trailer_code: print_esc("pdftrailer");
+ pdf_strcmp_code: print_esc("pdfstrcmp");
+ pdf_escape_string_code: print_esc("pdfescapestring");
+ pdf_escape_name_code: print_esc("pdfescapename");
+ reset_timer_code: print_esc("pdfresettimer");
+@z
+
+@x [1348]
+immediate_code:@<Implement \.{\\immediate}@>;
+set_language_code:@<Implement \.{\\setlanguage}@>;
+@y
+immediate_code:@<Implement \.{\\immediate}@>;
+set_language_code:@<Implement \.{\\setlanguage}@>;
+pdf_literal_node: @<Implement \.{\\pdfliteral}@>;
+pdf_obj_code: @<Implement \.{\\pdfobj}@>;
+pdf_refobj_node: @<Implement \.{\\pdfrefobj}@>;
+pdf_xform_code: @<Implement \.{\\pdfxform}@>;
+pdf_refxform_node: @<Implement \.{\\pdfrefxform}@>;
+pdf_ximage_code: @<Implement \.{\\pdfximage}@>;
+pdf_refximage_node: @<Implement \.{\\pdfrefximage}@>;
+pdf_annot_node: @<Implement \.{\\pdfannot}@>;
+pdf_start_link_node: @<Implement \.{\\pdfstartlink}@>;
+pdf_end_link_node: @<Implement \.{\\pdfendlink}@>;
+pdf_outline_code: @<Implement \.{\\pdfoutline}@>;
+pdf_dest_node: @<Implement \.{\\pdfdest}@>;
+pdf_thread_node: @<Implement \.{\\pdfthread}@>;
+pdf_start_thread_node: @<Implement \.{\\pdfstartthread}@>;
+pdf_end_thread_node: @<Implement \.{\\pdfendthread}@>;
+pdf_save_pos_node: @<Implement \.{\\pdfsavepos}@>;
+pdf_info_code: @<Implement \.{\\pdfinfo}@>;
+pdf_catalog_code: @<Implement \.{\\pdfcatalog}@>;
+pdf_names_code: @<Implement \.{\\pdfnames}@>;
+pdf_include_chars_code: @<Implement \.{\\pdfincludechars}@>;
+pdf_font_attr_code: @<Implement \.{\\pdffontattr}@>;
+pdf_map_file_code: @<Implement \.{\\pdfmapfile}@>;
+pdf_map_line_code: @<Implement \.{\\pdfmapline}@>;
+pdf_trailer_code: @<Implement \.{\\pdftrailer}@>;
+pdf_strcmp_code: @<Implement \.{\\pdfstrcmp}@>;
+pdf_escape_string_code: @<Implement \.{\\pdfescapestring}@>;
+pdf_escape_name_code: @<Implement \.{\\pdfescapename}@>;
+reset_timer_code: @<Implement \.{\\pdfresettimer}@>;
+@z
+
+@x [1354]
+@<Implement \.{\\special}@>=
+begin new_whatsit(special_node,write_node_size); write_stream(tail):=null;
+p:=scan_toks(false,true); write_tokens(tail):=def_ref;
+end
+@y
+@<Implement \.{\\special}@>=
+begin new_whatsit(special_node,write_node_size); write_stream(tail):=null;
+p:=scan_toks(false,true); write_tokens(tail):=def_ref;
+end
+
+@ The following macros are needed for further manipulation with whatsit nodes
+for \pdfTeX{} extensions (copying, destroying etc.)
+
+@d add_action_ref(#) == incr(pdf_action_refcount(#)) {increase count of
+references to this action}
+
+@d delete_action_ref(#) == {decrease count of references to this
+action; free it if there is no reference to this action}
+begin
+ if pdf_action_refcount(#) = null then begin
+ if pdf_action_type(#) = pdf_action_user then
+ delete_token_ref(pdf_action_user_tokens(#))
+ else begin
+ if pdf_action_file(#) <> null then
+ delete_token_ref(pdf_action_file(#));
+ if pdf_action_type(#) = pdf_action_page then
+ delete_token_ref(pdf_action_page_tokens(#))
+ else if pdf_action_named_id(#) > 0 then
+ delete_token_ref(pdf_action_id(#));
+ end;
+ free_node(#, pdf_action_size);
+ end
+ else
+ decr(pdf_action_refcount(#));
+end
+
+@ We have to check whether \.{\\pdfoutput} is set for using \pdfTeX{}
+ extensions.
+@<Declare procedures needed in |do_ext...@>=
+procedure check_pdfoutput(s: str_number; is_error : boolean);
+begin
+ if pdf_output <= 0 then
+ if is_error then
+ pdf_error(s, "used while \pdfoutput is not set")
+ else
+ pdf_warning(s, "used while \pdfoutput is not set; ignoring it", true);
+end;
+
+procedure scan_pdf_ext_toks;
+begin
+ call_func(scan_toks(false, true)); {like \.{\\special}}
+end;
+
+procedure compare_strings; {to implement \.{\\pdfstrcmp}}
+label done;
+var s1, s2: str_number;
+ i1, i2, j1, j2: pool_pointer;
+ result: integer;
+begin
+ call_func(scan_toks(false, true));
+ s1 := tokens_to_string(def_ref);
+ delete_token_ref(def_ref);
+ call_func(scan_toks(false, true));
+ s2 := tokens_to_string(def_ref);
+ delete_token_ref(def_ref);
+ i1 := str_start[s1];
+ j1 := str_start[s1 + 1];
+ i2 := str_start[s2];
+ j2 := str_start[s2 + 1];
+ while (i1 < j1) and (i2 < j2) do begin
+ if str_pool[i1] < str_pool[i2] then begin
+ result := -1;
+ goto done;
+ end;
+ if str_pool[i1] > str_pool[i2] then begin
+ result := 1;
+ goto done;
+ end;
+ incr(i1);
+ incr(i2);
+ end;
+ if (i1 = j1) and (i2 = j2) then
+ result := 0
+ else if i1 < j1 then
+ result := 1
+ else
+ result := -1;
+done:
+ pdf_retval := result;
+ flush_str(s2);
+ flush_str(s1);
+end;
+
+@ @<Implement \.{\\pdfliteral}@>=
+begin
+ check_pdfoutput("\pdfliteral", true);
+ new_whatsit(pdf_literal_node, write_node_size);
+ if scan_keyword("direct") then
+ pdf_literal_mode(tail) := direct_always
+ else if scan_keyword("page") then
+ pdf_literal_mode(tail) := direct_page
+ else
+ pdf_literal_mode(tail) := reset_origin;
+ scan_pdf_ext_toks;
+ pdf_literal_data(tail) := def_ref;
+end
+
+@ The \.{\\pdfobj} primitive is used to create a ``raw'' object in the PDF
+ output file. The object contents will be hold in memory and will be written
+ out only when the object is referenced by \.{\\pdfrefobj}. When \.{\\pdfobj}
+ is used with \.{\\immediate}, the object contents will be written out
+ immediately. Objects referenced in the current page are appended into
+ |pdf_obj_list|.
+
+@<Glob...@>=
+@!pdf_last_obj: integer;
+
+@ @<Implement \.{\\pdfobj}@>=
+begin
+ check_pdfoutput("\pdfobj", true);
+ if scan_keyword("reserveobjnum") then begin
+ @<Scan an optional space@>;
+ incr(pdf_obj_count);
+ pdf_create_obj(obj_type_obj, pdf_obj_count);
+ pdf_last_obj := obj_ptr;
+ end
+ else begin
+ k := -1;
+ if scan_keyword("useobjnum") then begin
+ scan_int;
+ k := cur_val;
+ if (k <= 0) or (k > obj_ptr) or (obj_data_ptr(k) <> 0) then begin
+ pdf_warning("\pdfobj", "invalid object number being ignored", true);
+ pdf_retval := -1; {signal the problem}
+ k := -1; {will be generated again}
+ end;
+ end;
+ if k < 0 then begin
+ incr(pdf_obj_count);
+ pdf_create_obj(obj_type_obj, pdf_obj_count);
+ k := obj_ptr;
+ end;
+ obj_data_ptr(k) := pdf_get_mem(pdfmem_obj_size);
+ if scan_keyword("stream") then begin
+ obj_obj_is_stream(k) := 1;
+ if scan_keyword("attr") then begin
+ scan_pdf_ext_toks;
+ obj_obj_stream_attr(k) := def_ref;
+ end
+ else
+ obj_obj_stream_attr(k) := null;
+ end
+ else
+ obj_obj_is_stream(k) := 0;
+ if scan_keyword("file") then
+ obj_obj_is_file(k) := 1
+ else
+ obj_obj_is_file(k) := 0;
+ scan_pdf_ext_toks;
+ obj_obj_data(k) := def_ref;
+ pdf_last_obj := k;
+ end;
+end
+
+@ We need to check whether the referenced object exists.
+
+@<Declare procedures that need to be declared forward for pdftex@>=
+procedure pdf_check_obj(t, n: integer);
+var k: integer;
+begin
+ k := head_tab[t];
+ while (k <> 0) and (k <> n) do
+ k := obj_link(k);
+ if k = 0 then
+ pdf_error("ext1", "cannot find referenced object");
+end;
+
+@ @<Implement \.{\\pdfrefobj}@>=
+begin
+ check_pdfoutput("\pdfrefobj", true);
+ scan_int;
+ pdf_check_obj(obj_type_obj, cur_val);
+ new_whatsit(pdf_refobj_node, pdf_refobj_node_size);
+ pdf_obj_objnum(tail) := cur_val;
+end
+
+@ \.{\\pdfxform} and \.{\\pdfrefxform} are similiar to \.{\\pdfobj} and
+ \.{\\pdfrefobj}
+
+@<Glob...@>=
+@!pdf_last_xform: integer;
+
+@ @<Implement \.{\\pdfxform}@>=
+begin
+ check_pdfoutput("\pdfxform", true);
+ incr(pdf_xform_count);
+ pdf_create_obj(obj_type_xform, pdf_xform_count);
+ k := obj_ptr;
+ obj_data_ptr(k) := pdf_get_mem(pdfmem_xform_size);
+ if scan_keyword("attr") then begin
+ scan_pdf_ext_toks;
+ obj_xform_attr(k) := def_ref;
+ end
+ else
+ obj_xform_attr(k) := null;
+ if scan_keyword("resources") then begin
+ scan_pdf_ext_toks;
+ obj_xform_resources(k) := def_ref;
+ end
+ else
+ obj_xform_resources(k) := null;
+ scan_int;
+ if box(cur_val) = null then
+ pdf_error("ext1", "\pdfxform cannot be used with a void box");
+ obj_xform_width(k) := width(box(cur_val));
+ obj_xform_height(k) := height(box(cur_val));
+ obj_xform_depth(k) := depth(box(cur_val));
+ obj_xform_box(k) := box(cur_val); {save pointer to the box}
+ box(cur_val) := null;
+ pdf_last_xform := k;
+end
+
+@ @<Implement \.{\\pdfrefxform}@>=
+begin
+ check_pdfoutput("\pdfrefxform", true);
+ scan_int;
+ pdf_check_obj(obj_type_xform, cur_val);
+ new_whatsit(pdf_refxform_node, pdf_refxform_node_size);
+ pdf_xform_objnum(tail) := cur_val;
+ pdf_width(tail) := obj_xform_width(cur_val);
+ pdf_height(tail) := obj_xform_height(cur_val);
+ pdf_depth(tail) := obj_xform_depth(cur_val);
+end
+
+@ \.{\\pdfximage} and \.{\\pdfrefximage} are similiar to \.{\\pdfxform} and
+ \.{\\pdfrefxform}. As we have to scan |<rule spec>| quite often, it is better
+ have a |rule_node| that holds the most recently scanned |<rule spec>|.
+
+@<Glob...@>=
+@!pdf_last_ximage: integer;
+@!pdf_last_ximage_pages: integer;
+@!pdf_last_ximage_colordepth: integer;
+@!alt_rule: pointer;
+@!pdf_last_pdf_box_spec: integer;
+
+@ @<Set init...@>=
+alt_rule := null;
+
+@ @<Declare procedures needed in |do_ext...@>=
+procedure scale_image(n: integer);
+var x, y, xr, yr: integer; {size and resolution of image}
+ w, h: scaled; {indeed size corresponds to image resolution}
+ default_res: integer;
+begin
+ x := image_width(obj_ximage_data(n));
+ y := image_height(obj_ximage_data(n));
+ xr := image_x_res(obj_ximage_data(n));
+ yr := image_y_res(obj_ximage_data(n));
+ if (xr > 65535) or (yr > 65535) then begin
+ xr := 0;
+ yr := 0;
+ pdf_warning("ext1", "too large image resolution ignored", true);
+ end;
+ if (x <= 0) or (y <= 0) or (xr < 0) or (yr < 0) then
+ pdf_error("ext1", "invalid image dimensions");
+ if is_pdf_image(obj_ximage_data(n)) then begin
+ w := x;
+ h := y;
+ end
+ else begin
+ default_res := fix_int(pdf_image_resolution, 0, 65535);
+ if (default_res > 0) and ((xr = 0) or (yr = 0)) then begin
+ xr := default_res;
+ yr := default_res;
+ end;
+ if is_running(obj_ximage_width(n)) and
+ is_running(obj_ximage_height(n)) then
+ begin
+ if (xr > 0) and (yr > 0) then begin
+ w := ext_xn_over_d(one_hundred_inch, x, 100*xr);
+ h := ext_xn_over_d(one_hundred_inch, y, 100*yr);
+ end
+ else begin
+ w := ext_xn_over_d(one_hundred_inch, x, 7200);
+ h := ext_xn_over_d(one_hundred_inch, y, 7200);
+ end;
+ end;
+ end;
+ if is_running(obj_ximage_width(n)) and is_running(obj_ximage_height(n)) and
+ is_running(obj_ximage_depth(n)) then begin
+ obj_ximage_width(n) := w;
+ obj_ximage_height(n) := h;
+ obj_ximage_depth(n) := 0;
+ end
+ else if is_running(obj_ximage_width(n)) then begin
+ {image depth or height is explicitly specified}
+ if is_running(obj_ximage_height(n)) then begin
+ {image depth is explicitly specified}
+ obj_ximage_width(n) := ext_xn_over_d(h, x, y);
+ obj_ximage_height(n) := h - obj_ximage_depth(n);
+ end
+ else if is_running(obj_ximage_depth(n)) then begin
+ {image height is explicitly specified}
+ obj_ximage_width(n) := ext_xn_over_d(obj_ximage_height(n), x, y);
+ obj_ximage_depth(n) := 0;
+ end
+ else begin
+ {both image depth and height are explicitly specified}
+ obj_ximage_width(n) := ext_xn_over_d(obj_ximage_height(n) +
+ obj_ximage_depth(n), x, y);
+ end;
+ end
+ else begin
+ {image width is explicitly specified}
+ if is_running(obj_ximage_height(n)) and
+ is_running(obj_ximage_depth(n)) then begin
+ {both image depth and height are not specified}
+ obj_ximage_height(n) := ext_xn_over_d(obj_ximage_width(n), y, x);
+ obj_ximage_depth(n) := 0;
+ end
+ {image depth is explicitly specified}
+ else if is_running(obj_ximage_height(n)) then begin
+ obj_ximage_height(n) :=
+ ext_xn_over_d(obj_ximage_width(n), y, x) - obj_ximage_depth(n);
+ end
+ {image height is explicitly specified}
+ else if is_running(obj_ximage_depth(n)) then begin
+ obj_ximage_depth(n) := 0;
+ end
+ {both image depth and height are explicitly specified}
+ else
+ do_nothing;
+ end;
+end;
+
+procedure scan_pdf_box_spec; {scans pdf-box-spec to |pdf_last_pdf_box_spec|}
+begin
+ pdf_last_pdf_box_spec := pdf_pdf_box_spec_crop;
+
+ if scan_keyword("mediabox") then
+ pdf_last_pdf_box_spec := pdf_pdf_box_spec_media
+ else if scan_keyword("cropbox") then
+ pdf_last_pdf_box_spec := pdf_pdf_box_spec_crop
+ else if scan_keyword("bleedbox") then
+ pdf_last_pdf_box_spec := pdf_pdf_box_spec_bleed
+ else if scan_keyword("trimbox") then
+ pdf_last_pdf_box_spec := pdf_pdf_box_spec_trim
+ else if scan_keyword("artbox") then
+ pdf_last_pdf_box_spec := pdf_pdf_box_spec_art
+end;
+
+procedure scan_alt_rule; {scans rule spec to |alt_rule|}
+label reswitch;
+begin
+ if alt_rule = null then
+ alt_rule := new_rule;
+ width(alt_rule) := null_flag;
+ height(alt_rule) := null_flag;
+ depth(alt_rule) := null_flag;
+reswitch:
+ if scan_keyword("width") then begin
+ scan_normal_dimen;
+ width(alt_rule) := cur_val;
+ goto reswitch;
+ end;
+ if scan_keyword("height") then begin
+ scan_normal_dimen;
+ height(alt_rule) := cur_val;
+ goto reswitch;
+ end;
+ if scan_keyword("depth") then begin
+ scan_normal_dimen;
+ depth(alt_rule) := cur_val;
+ goto reswitch;
+ end;
+end;
+
+procedure scan_image;
+label reswitch;
+var p: pointer;
+ k: integer;
+ named: str_number;
+ s: str_number;
+ page, colorspace: integer;
+begin
+ incr(pdf_ximage_count);
+ pdf_create_obj(obj_type_ximage, pdf_ximage_count);
+ k := obj_ptr;
+ obj_data_ptr(k) := pdf_get_mem(pdfmem_ximage_size);
+ scan_alt_rule; {scans |<rule spec>| to |alt_rule|}
+ obj_ximage_width(k) := width(alt_rule);
+ obj_ximage_height(k) := height(alt_rule);
+ obj_ximage_depth(k) := depth(alt_rule);
+ if scan_keyword("attr") then begin
+ scan_pdf_ext_toks;
+ obj_ximage_attr(k) := def_ref;
+ end
+ else
+ obj_ximage_attr(k) := null;
+ named := 0;
+ if scan_keyword("named") then begin
+ scan_pdf_ext_toks;
+ named := tokens_to_string(def_ref);
+ delete_token_ref(def_ref);
+ end
+ else if scan_keyword("page") then begin
+ scan_int;
+ page := cur_val;
+ end
+ else
+ page := 1;
+ if scan_keyword("colorspace") then begin
+ scan_int;
+ colorspace := cur_val;
+ end
+ else
+ colorspace := 0;
+ scan_pdf_box_spec; {scans pdf-box-spec to |pdf_last_pdf_box_spec|}
+ scan_pdf_ext_toks;
+ s := tokens_to_string(def_ref);
+ delete_token_ref(def_ref);
+ if pdf_option_always_use_pdfpagebox <> 0 then begin
+ pdf_warning(0,"Primitive \pdfoptionalwaysusepdfpagebox is obsolete; use \pdfforcepagebox instead.",true);
+ pdf_force_pagebox := pdf_option_always_use_pdfpagebox;
+ pdf_option_always_use_pdfpagebox := 0; {warn once}
+ end;
+ if pdf_option_pdf_inclusion_errorlevel <> 0 then begin
+ pdf_warning(0,"Primitive \pdfoptionpdfinclusionerrorlevel is obsolete; use \pdfinclusionerrorlevel instead.",true);
+ pdf_inclusion_errorlevel := pdf_option_pdf_inclusion_errorlevel;
+ pdf_option_pdf_inclusion_errorlevel := 0; {warn once}
+ end;
+ if pdf_force_pagebox > 0 then begin
+ print_err("pdfTeX warning (image inclusion): ");
+ print ("\pdfforcepagebox is in use (");
+ print_int (pdf_force_pagebox);
+ print (")");
+ print_ln;
+ end;
+ obj_ximage_data(k) := read_image(s, page, named, colorspace,
+ pdf_minor_version,
+ pdf_force_pagebox,
+ pdf_inclusion_errorlevel);
+ if named <> 0 then flush_str(named);
+ flush_str(s);
+ scale_image(k);
+ pdf_last_ximage := k;
+ pdf_last_ximage_pages := image_pages(obj_ximage_data(k));
+ pdf_last_ximage_colordepth := image_colordepth(obj_ximage_data(k));
+end;
+
+@ @<Implement \.{\\pdfximage}@>=
+begin
+ check_pdfoutput("\pdfximage", true);
+ check_pdfminorversion;
+ scan_image;
+end
+
+@ @<Implement \.{\\pdfrefximage}@>=
+begin
+ check_pdfoutput("\pdfrefximage", true);
+ scan_int;
+ pdf_check_obj(obj_type_ximage, cur_val);
+ new_whatsit(pdf_refximage_node, pdf_refximage_node_size);
+ pdf_ximage_objnum(tail) := cur_val;
+ pdf_width(tail) := obj_ximage_width(cur_val);
+ pdf_height(tail) := obj_ximage_height(cur_val);
+ pdf_depth(tail) := obj_ximage_depth(cur_val);
+end
+
+@ The following function finds object with identifier |i| and type |t|.
+ |i < 0| indicates that |-i| should be treated as a string number. If no
+ such object exists then it will be created. This function is used mainly to
+ find destination for link annotations and outlines; however it is also used
+ in |pdf_ship_out| (to check whether a Page object already exists) so we need
+ to declare it together with subroutines needed in |pdf_hlist_out| and
+ |pdf_vlist_out|.
+
+@<Declare procedures that need to be declared forward for pdftex@>=
+function find_obj(t, i: integer; byname: boolean): integer;
+begin
+ find_obj := avl_find_obj(t, i, byname);
+end;
+
+procedure flush_str(s: str_number); {flush a string if possible}
+begin
+ if flushable(s) then
+ flush_string;
+end;
+
+function get_obj(t, i: integer; byname: boolean): integer;
+var r: integer;
+ s: str_number;
+begin
+ if byname > 0 then begin
+ s := tokens_to_string(i);
+ r := find_obj(t, s, true);
+ end
+ else begin
+ s := 0;
+ r := find_obj(t, i, false);
+ end;
+ if r = 0 then begin
+ if byname > 0 then begin
+ pdf_create_obj(t, -s);
+ s := 0;
+ end
+ else
+ pdf_create_obj(t, i);
+ r := obj_ptr;
+ if t = obj_type_dest then
+ obj_dest_ptr(r) := null;
+ end;
+ if s <> 0 then
+ flush_str(s);
+ get_obj := r;
+end;
+
+function get_microinterval:integer;
+var s,@!m:integer; {seconds and microseconds}
+begin
+ seconds_and_micros(s,m);
+ if (s-epochseconds)>32767 then
+ get_microinterval := max_integer
+ else if (microseconds>m) then
+ get_microinterval := ((s-1-epochseconds)*65536)+ (((m+1000000-microseconds)/100)*65536)/10000
+ else
+ get_microinterval := ((s-epochseconds)*65536) + (((m-microseconds)/100)*65536)/10000;
+end;
+
+
+@ @<Declare procedures needed in |do_ext...@>=
+function scan_action: pointer; {read an action specification}
+var p, t: integer;
+ s: str_number;
+begin
+ p := get_node(pdf_action_size);
+ scan_action := p;
+ pdf_action_file(p) := null;
+ pdf_action_refcount(p) := null;
+ if scan_keyword("user") then
+ pdf_action_type(p) := pdf_action_user
+ else if scan_keyword("goto") then
+ pdf_action_type(p) := pdf_action_goto
+ else if scan_keyword("thread") then
+ pdf_action_type(p) := pdf_action_thread
+ else
+ pdf_error("ext1", "action type missing");
+ if pdf_action_type(p) = pdf_action_user then begin
+ scan_pdf_ext_toks;
+ pdf_action_user_tokens(p) := def_ref;
+ return;
+ end;
+ if scan_keyword("file") then begin
+ scan_pdf_ext_toks;
+ pdf_action_file(p) := def_ref;
+ end;
+ if scan_keyword("page") then begin
+ if pdf_action_type(p) <> pdf_action_goto then
+ pdf_error("ext1", "only GoTo action can be used with `page'");
+ pdf_action_type(p) := pdf_action_page;
+ scan_int;
+ if cur_val <= 0 then
+ pdf_error("ext1", "page number must be positive");
+ pdf_action_id(p) := cur_val;
+ pdf_action_named_id(p) := 0;
+ scan_pdf_ext_toks;
+ pdf_action_page_tokens(p) := def_ref;
+ end
+ else if scan_keyword("name") then begin
+ scan_pdf_ext_toks;
+ pdf_action_named_id(p) := 1;
+ pdf_action_id(p) := def_ref;
+ end
+ else if scan_keyword("num") then begin
+ if (pdf_action_type(p) = pdf_action_goto) and
+ (pdf_action_file(p) <> null) then
+ pdf_error("ext1",
+ "`goto' option cannot be used with both `file' and `num'");
+ scan_int;
+ if cur_val <= 0 then
+ pdf_error("ext1", "num identifier must be positive");
+ pdf_action_named_id(p) := 0;
+ pdf_action_id(p) := cur_val;
+ end
+ else
+ pdf_error("ext1", "identifier type missing");
+ if scan_keyword("newwindow") then begin
+ pdf_action_new_window(p) := 1;
+ @<Scan an optional space@>; end
+ else if scan_keyword("nonewwindow") then begin
+ pdf_action_new_window(p) := 2;
+ @<Scan an optional space@>; end
+ else
+ pdf_action_new_window(p) := 0;
+ if (pdf_action_new_window(p) > 0) and
+ (((pdf_action_type(p) <> pdf_action_goto) and
+ (pdf_action_type(p) <> pdf_action_page)) or
+ (pdf_action_file(p) = null)) then
+ pdf_error("ext1",
+ "`newwindow'/`nonewwindow' must be used with `goto' and `file' option");
+end;
+
+procedure new_annot_whatsit(w, s: small_number); {create a new whatsit node for
+annotation}
+var p: pointer;
+begin
+ new_whatsit(w, s);
+ scan_alt_rule; {scans |<rule spec>| to |alt_rule|}
+ pdf_width(tail) := width(alt_rule);
+ pdf_height(tail) := height(alt_rule);
+ pdf_depth(tail) := depth(alt_rule);
+ if (w = pdf_start_link_node) then begin
+ if scan_keyword("attr") then begin
+ scan_pdf_ext_toks;
+ pdf_link_attr(tail) := def_ref;
+ end
+ else
+ pdf_link_attr(tail) := null;
+ end;
+ if (w = pdf_thread_node) or (w = pdf_start_thread_node) then begin
+ if scan_keyword("attr") then begin
+ scan_pdf_ext_toks;
+ pdf_thread_attr(tail) := def_ref;
+ end
+ else
+ pdf_thread_attr(tail) := null;
+ end;
+end;
+
+@ @<Glob...@>=
+@!pdf_last_annot: integer;
+
+@ @<Implement \.{\\pdfannot}@>=
+begin
+ check_pdfoutput("\pdfannot", true);
+ if scan_keyword("reserveobjnum") then begin
+ pdf_last_annot := pdf_new_objnum;
+ @<Scan an optional space@>; end
+ else begin
+ if scan_keyword("useobjnum") then begin
+ scan_int;
+ k := cur_val;
+ if (k <= 0) or (k > obj_ptr) or (obj_annot_ptr(k) <> 0) then
+ pdf_error("ext1", "invalid object number");
+ end
+ else
+ k := pdf_new_objnum;
+ new_annot_whatsit(pdf_annot_node, pdf_annot_node_size);
+ pdf_annot_objnum(tail) := k;
+ scan_pdf_ext_toks;
+ pdf_annot_data(tail) := def_ref;
+ pdf_last_annot := k;
+ end
+end
+
+@ @<Implement \.{\\pdfstartlink}@>=
+begin
+ check_pdfoutput("\pdfstartlink", true);
+ if abs(mode) = vmode then
+ pdf_error("ext1", "\pdfstartlink cannot be used in vertical mode");
+ new_annot_whatsit(pdf_start_link_node, pdf_annot_node_size);
+ pdf_link_action(tail) := scan_action;
+end
+
+@ @<Implement \.{\\pdfendlink}@>=
+begin
+ check_pdfoutput("\pdfendlink", true);
+ if abs(mode) = vmode then
+ pdf_error("ext1", "\pdfendlink cannot be used in vertical mode");
+ new_whatsit(pdf_end_link_node, small_node_size);
+end
+
+@ @<Declare procedures needed in |do_ext...@>=
+function outline_list_count(p: pointer): integer; {return number of outline
+entries in the same level with |p|}
+var k: integer;
+begin
+ k := 1;
+ while obj_outline_prev(p) <> 0 do begin
+ incr(k);
+ p := obj_outline_prev(p);
+ end;
+ outline_list_count := k;
+end;
+
+@ @<Implement \.{\\pdfoutline}@>=
+begin
+ check_pdfoutput("\pdfoutline", true);
+ if scan_keyword("attr") then begin
+ scan_pdf_ext_toks;
+ r := def_ref;
+ end
+ else
+ r := 0;
+ p := scan_action;
+ if scan_keyword("count") then begin
+ scan_int;
+ i := cur_val;
+ end
+ else
+ i := 0;
+ scan_pdf_ext_toks;
+ q := def_ref;
+ pdf_new_obj(obj_type_others, 0);
+ j := obj_ptr;
+ write_action(p);
+ pdf_end_obj;
+ delete_action_ref(p);
+ pdf_create_obj(obj_type_outline, 0);
+ k := obj_ptr;
+ obj_outline_ptr(k) := pdf_get_mem(pdfmem_outline_size);
+ obj_outline_action_objnum(k) := j;
+ obj_outline_count(k) := i;
+ pdf_new_obj(obj_type_others, 0);
+ pdf_print_str_ln(tokens_to_string(q));
+ flush_str(last_tokens_string);
+ delete_token_ref(q);
+ pdf_end_obj;
+ obj_outline_title(k) := obj_ptr;
+ obj_outline_prev(k) := 0;
+ obj_outline_next(k) := 0;
+ obj_outline_first(k) := 0;
+ obj_outline_last(k) := 0;
+ obj_outline_parent(k) := pdf_parent_outline;
+ obj_outline_attr(k) := r;
+ if pdf_first_outline = 0 then
+ pdf_first_outline := k;
+ if pdf_last_outline = 0 then begin
+ if pdf_parent_outline <> 0 then
+ obj_outline_first(pdf_parent_outline) := k;
+ end
+ else begin
+ obj_outline_next(pdf_last_outline) := k;
+ obj_outline_prev(k) := pdf_last_outline;
+ end;
+ pdf_last_outline := k;
+ if obj_outline_count(k) <> 0 then begin
+ pdf_parent_outline := k;
+ pdf_last_outline := 0;
+ end
+ else if (pdf_parent_outline <> 0) and
+ (outline_list_count(k) = abs(obj_outline_count(pdf_parent_outline))) then
+ begin
+ j := pdf_last_outline;
+ repeat
+ obj_outline_last(pdf_parent_outline) := j;
+ j := pdf_parent_outline;
+ pdf_parent_outline := obj_outline_parent(pdf_parent_outline);
+ until (pdf_parent_outline = 0) or
+ (outline_list_count(j) < abs(obj_outline_count(pdf_parent_outline)));
+ if pdf_parent_outline = 0 then
+ pdf_last_outline := pdf_first_outline
+ else
+ pdf_last_outline := obj_outline_first(pdf_parent_outline);
+ while obj_outline_next(pdf_last_outline) <> 0 do
+ pdf_last_outline := obj_outline_next(pdf_last_outline);
+ end;
+end
+
+@ When a destination is created we need to check whether another destination
+with the same identifier already exists and give a warning if needed.
+
+@<Declare procedures needed in |pdf_hlist_out|, |pdf_vlist_out|@>=
+procedure warn_dest_dup(id: integer; byname: small_number; s1, s2: str_number);
+begin
+ pdf_warning(s1, "destination with the same identifier (", false);
+ if byname > 0 then begin
+ print("name");
+ print_mark(id);
+ end
+ else begin
+ print("num");
+ print_int(id);
+ end;
+ print(") ");
+ print(s2);
+ print_ln;
+ show_context;
+end;
+
+@ Notice that |scan_keyword| doesn't care if two words have same prefix; so
+we should be careful when scan keywords with same prefix. The main rule: if
+there are two or more keywords with the same prefix, then always test in
+order from the longest one to the shortest one.
+
+@<Implement \.{\\pdfdest}@>=
+begin
+ check_pdfoutput("\pdfdest", true);
+ q := tail;
+ new_whatsit(pdf_dest_node, pdf_dest_node_size);
+ if scan_keyword("num") then begin
+ scan_int;
+ if cur_val <= 0 then
+ pdf_error("ext1", "num identifier must be positive");
+ if cur_val > max_halfword then
+ pdf_error("ext1", "number too big");
+ pdf_dest_id(tail) := cur_val;
+ pdf_dest_named_id(tail) := 0;
+ end
+ else if scan_keyword("name") then begin
+ scan_pdf_ext_toks;
+ pdf_dest_id(tail) := def_ref;
+ pdf_dest_named_id(tail) := 1;
+ end
+ else
+ pdf_error("ext1", "identifier type missing");
+ if scan_keyword("xyz") then begin
+ pdf_dest_type(tail) := pdf_dest_xyz;
+ if scan_keyword("zoom") then begin
+ scan_int;
+ if cur_val > max_halfword then
+ pdf_error("ext1", "number too big");
+ pdf_dest_xyz_zoom(tail) := cur_val;
+ end
+ else
+ pdf_dest_xyz_zoom(tail) := null;
+ end
+ else if scan_keyword("fitbh") then
+ pdf_dest_type(tail) := pdf_dest_fitbh
+ else if scan_keyword("fitbv") then
+ pdf_dest_type(tail) := pdf_dest_fitbv
+ else if scan_keyword("fitb") then
+ pdf_dest_type(tail) := pdf_dest_fitb
+ else if scan_keyword("fith") then
+ pdf_dest_type(tail) := pdf_dest_fith
+ else if scan_keyword("fitv") then
+ pdf_dest_type(tail) := pdf_dest_fitv
+ else if scan_keyword("fitr") then
+ pdf_dest_type(tail) := pdf_dest_fitr
+ else if scan_keyword("fit") then
+ pdf_dest_type(tail) := pdf_dest_fit
+ else
+ pdf_error("ext1", "destination type missing");
+ @<Scan an optional space@>;
+ if pdf_dest_type(tail) = pdf_dest_fitr then begin
+ scan_alt_rule; {scans |<rule spec>| to |alt_rule|}
+ pdf_width(tail) := width(alt_rule);
+ pdf_height(tail) := height(alt_rule);
+ pdf_depth(tail) := depth(alt_rule);
+ end;
+ if pdf_dest_named_id(tail) <> 0 then begin
+ i := tokens_to_string(pdf_dest_id(tail));
+ k := find_obj(obj_type_dest, i, true);
+ flush_str(i);
+ end
+ else
+ k := find_obj(obj_type_dest, pdf_dest_id(tail), false);
+ if (k <> 0) and (obj_dest_ptr(k) <> null) then begin
+ warn_dest_dup(pdf_dest_id(tail), pdf_dest_named_id(tail),
+ "ext4", "has been already used, duplicate ignored");
+ flush_node_list(tail);
+ tail := q;
+ link(q) := null;
+ end;
+end
+
+@ @<Declare procedures needed in |do_ext...@>=
+procedure scan_thread_id;
+begin
+ if scan_keyword("num") then begin
+ scan_int;
+ if cur_val <= 0 then
+ pdf_error("ext1", "num identifier must be positive");
+ if cur_val > max_halfword then
+ pdf_error("ext1", "number too big");
+ pdf_thread_id(tail) := cur_val;
+ pdf_thread_named_id(tail) := 0;
+ end
+ else if scan_keyword("name") then begin
+ scan_pdf_ext_toks;
+ pdf_thread_id(tail) := def_ref;
+ pdf_thread_named_id(tail) := 1;
+ end
+ else
+ pdf_error("ext1", "identifier type missing");
+end;
+
+@ @<Implement \.{\\pdfthread}@>=
+begin
+ check_pdfoutput("\pdfthread", true);
+ new_annot_whatsit(pdf_thread_node, pdf_thread_node_size);
+ scan_thread_id;
+end
+
+@ @<Implement \.{\\pdfstartthread}@>=
+begin
+ check_pdfoutput("\pdfstartthread", true);
+ new_annot_whatsit(pdf_start_thread_node, pdf_thread_node_size);
+ scan_thread_id;
+end
+
+@ @<Implement \.{\\pdfendthread}@>=
+begin
+ check_pdfoutput("\pdfendthread", true);
+ new_whatsit(pdf_end_thread_node, small_node_size);
+end
+
+@ @<Glob...@>=
+@!pdf_last_x_pos: integer;
+@!pdf_last_y_pos: integer;
+
+@ @<Implement \.{\\pdfsavepos}@>=
+begin
+ check_pdfoutput("\pdfsavepos", true);
+ new_whatsit(pdf_save_pos_node, small_node_size);
+end
+
+@ To implement primitives as \.{\\pdfinfo}, \.{\\pdfcatalog} or
+\.{\\pdfnames} we need to concatenate tokens lists.
+
+@<Declare procedures needed in |do_ext...@>=
+function concat_tokens(q, r: pointer): pointer; {concat |q| and |r| and
+returns the result tokens list}
+var p: pointer;
+begin
+ if q = null then begin
+ concat_tokens := r;
+ return;
+ end;
+ p := q;
+ while link(p) <> null do
+ p := link(p);
+ link(p) := link(r);
+ free_avail(r);
+ concat_tokens := q;
+end;
+
+@ @<Implement \.{\\pdfinfo}@>=
+begin
+ check_pdfoutput("\pdfinfo", false);
+ scan_pdf_ext_toks;
+ if pdf_output > 0 then
+ pdf_info_toks := concat_tokens(pdf_info_toks, def_ref);
+end
+
+@ @<Implement \.{\\pdfcatalog}@>=
+begin
+ check_pdfoutput("\pdfcatalog", false);
+ scan_pdf_ext_toks;
+ if pdf_output > 0 then
+ pdf_catalog_toks := concat_tokens(pdf_catalog_toks, def_ref);
+ if scan_keyword("openaction") then
+ if pdf_catalog_openaction <> 0 then
+ pdf_error("ext1", "duplicate of openaction")
+ else begin
+ p := scan_action;
+ pdf_new_obj(obj_type_others, 0);
+ if pdf_output > 0 then
+ pdf_catalog_openaction := obj_ptr;
+ write_action(p);
+ pdf_end_obj;
+ delete_action_ref(p);
+ end;
+end
+
+@ @<Implement \.{\\pdfnames}@>=
+begin
+ check_pdfoutput("\pdfnames", true);
+ scan_pdf_ext_toks;
+ pdf_names_toks := concat_tokens(pdf_names_toks, def_ref);
+end
+
+@ @<Implement \.{\\pdftrailer}@>=
+begin
+ check_pdfoutput("\pdftrailer", false);
+ scan_pdf_ext_toks;
+ if pdf_output > 0 then
+ pdf_trailer_toks := concat_tokens(pdf_trailer_toks, def_ref);
+end
+
+@ @<Implement \.{\\pdfescapestring}@>=
+begin
+ scan_pdf_ext_toks;
+ escapestr(tokens_to_string(def_ref));
+ flush_str(last_tokens_string);
+ delete_token_ref(def_ref);
+end
+
+@ @<Implement \.{\\pdfescapename}@>=
+begin
+ scan_pdf_ext_toks;
+ escapename(tokens_to_string(def_ref));
+ flush_str(last_tokens_string);
+ delete_token_ref(def_ref);
+end
+
+@ @<Glob...@>=
+@!pdf_retval: integer; {global multi-purpose return value}
+
+@ @<Implement \.{\\pdfstrcmp}@>=
+compare_strings
+
+@ @<Set initial values of key variables@>=
+ seconds_and_micros(epochseconds,microseconds);
+
+@ @<Implement \.{\\pdfresettimer}@>=
+begin
+ seconds_and_micros(epochseconds,microseconds);
+end
+
+
+@ The following subroutines are about PDF-specific font issues.
+
+@<Declare procedures needed in |do_ext...@>=
+procedure pdf_include_chars;
+var s: str_number;
+ k: pool_pointer; {running indices}
+ f: internal_font_number;
+begin
+ scan_font_ident;
+ f := cur_val;
+ if f = null_font then
+ pdf_error("font", "invalid font identifier");
+ pdf_check_vf(f);
+ if not font_used[f] then
+ pdf_init_font(f);
+ scan_pdf_ext_toks;
+ s := tokens_to_string(def_ref);
+ delete_token_ref(def_ref);
+ k := str_start[s];
+ while k < str_start[s + 1] do begin
+ pdf_mark_char(f, str_pool[k]);
+ incr(k);
+ end;
+ flush_str(s);
+end;
+
+
+@ @<Implement \.{\\pdfincludechars}@>=
+begin
+ check_pdfoutput("\pdfincludechars", true);
+ pdf_include_chars;
+end
+
+@ @<Implement \.{\\pdffontattr}@>=
+begin
+ check_pdfoutput("\pdffontattr", true);
+ scan_font_ident;
+ k := cur_val;
+ if k = null_font then
+ pdf_error("font", "invalid font identifier");
+ scan_pdf_ext_toks;
+ pdf_font_attr[k] := tokens_to_string(def_ref);
+end
+
+@ @<Implement \.{\\pdfmapfile}@>=
+begin
+ check_pdfoutput("\pdfmapfile", true);
+ scan_pdf_ext_toks;
+ pdfmapfile(def_ref);
+ delete_token_ref(def_ref);
+end
+
+@ @<Implement \.{\\pdfmapline}@>=
+begin
+ check_pdfoutput("\pdfmapline", true);
+ scan_pdf_ext_toks;
+ pdfmapline(def_ref);
+ delete_token_ref(def_ref);
+end
+
+@ The following function are needed for outputing article thread.
+
+@<Declare procedures needed in |do_ext...@>=
+procedure thread_title(thread: integer);
+begin
+ pdf_print("/Title (");
+ if obj_info(thread) < 0 then
+ pdf_print(-obj_info(thread))
+ else
+ pdf_print_int(obj_info(thread));
+ pdf_print_ln(")");
+end;
+
+procedure pdf_fix_thread(thread: integer);
+var a: pointer;
+begin
+ pdf_warning("thread", "destination ", false);
+ if obj_info(thread) < 0 then begin
+ print("name{");
+ print(-obj_info(thread));
+ print("}");
+ end
+ else begin
+ print("num");
+ print_int(obj_info(thread));
+ end;
+ print(" has been referenced but does not exist, replaced by a fixed one");
+ print_ln; print_ln;
+ pdf_new_dict(obj_type_others, 0);
+ a := obj_ptr;
+ pdf_indirect_ln("T", thread);
+ pdf_indirect_ln("V", a);
+ pdf_indirect_ln("N", a);
+ pdf_indirect_ln("P", head_tab[obj_type_page]);
+ pdf_print("/R [0 0 ");
+ pdf_print_bp(pdf_page_width); pdf_out(" ");
+ pdf_print_bp(pdf_page_height);
+ pdf_print_ln("]");
+ pdf_end_dict;
+ pdf_begin_dict(thread);
+ pdf_print_ln("/I << ");
+ thread_title(thread);
+ pdf_print_ln(">>");
+ pdf_indirect_ln("F", a);
+ pdf_end_dict;
+end;
+
+procedure out_thread(thread: integer);
+var a, b, c: pointer;
+ last_attr: integer;
+begin
+ if obj_thread_first(thread) = 0 then begin
+ pdf_fix_thread(thread);
+ return;
+ end;
+ pdf_begin_dict(thread);
+ a := obj_thread_first(thread);
+ b := a;
+ last_attr := 0;
+ repeat
+ if obj_bead_attr(a) <> 0 then
+ last_attr := obj_bead_attr(a);
+ a := obj_bead_next(a);
+ until a = b;
+ if last_attr <> 0 then
+ pdf_print_ln(last_attr)
+ else begin
+ pdf_print_ln("/I << ");
+ thread_title(thread);
+ pdf_print_ln(">>");
+ end;
+ pdf_indirect_ln("F", a);
+ pdf_end_dict;
+ repeat
+ pdf_begin_dict(a);
+ if a = b then
+ pdf_indirect_ln("T", thread);
+ pdf_indirect_ln("V", obj_bead_prev(a));
+ pdf_indirect_ln("N", obj_bead_next(a));
+ pdf_indirect_ln("P", obj_bead_page(a));
+ pdf_indirect_ln("R", obj_bead_rect(a));
+ pdf_end_dict;
+ a := obj_bead_next(a);
+ until a = b;
+end;
+
+@ @<Display <rule spec> for whatsit node created by \pdfTeX@>=
+print("(");
+print_rule_dimen(pdf_height(p));
+print_char("+");
+print_rule_dimen(pdf_depth(p));
+print(")x");
+print_rule_dimen(pdf_width(p))
+@z
+
+@x [1356]
+othercases print("whatsit?")
+@y
+pdf_literal_node: begin
+ print_esc("pdfliteral");
+ case pdf_literal_mode(p) of
+ reset_origin:
+ do_nothing;
+ direct_page:
+ print(" page");
+ direct_always:
+ print(" direct");
+ othercases confusion("literal2")
+ endcases;
+ print_mark(pdf_literal_data(p));
+end;
+pdf_refobj_node: begin
+ print_esc("pdfrefobj");
+ if obj_obj_is_stream(pdf_obj_objnum(p)) > 0 then begin
+ if obj_obj_stream_attr(pdf_obj_objnum(p)) <> null then begin
+ print(" attr");
+ print_mark(obj_obj_stream_attr(pdf_obj_objnum(p)));
+ end;
+ print(" stream");
+ end;
+ if obj_obj_is_file(pdf_obj_objnum(p)) > 0 then
+ print(" file");
+ print_mark(obj_obj_data(pdf_obj_objnum(p)));
+end;
+pdf_refxform_node: begin
+ print_esc("pdfrefxform");
+ print("(");
+ print_scaled(obj_xform_height(pdf_xform_objnum(p)));
+ print_char("+");
+ print_scaled(obj_xform_depth(pdf_xform_objnum(p)));
+ print(")x");
+ print_scaled(obj_xform_width(pdf_xform_objnum(p)));
+end;
+pdf_refximage_node: begin
+ print_esc("pdfrefximage");
+ print("(");
+ print_scaled(obj_ximage_height(pdf_ximage_objnum(p)));
+ print_char("+");
+ print_scaled(obj_ximage_depth(pdf_ximage_objnum(p)));
+ print(")x");
+ print_scaled(obj_ximage_width(pdf_ximage_objnum(p)));
+end;
+pdf_annot_node: begin
+ print_esc("pdfannot");
+ @<Display <rule spec> for whatsit node created by \pdfTeX@>;
+ print_mark(pdf_annot_data(p));
+end;
+pdf_start_link_node: begin
+ print_esc("pdflink");
+ @<Display <rule spec> for whatsit node created by \pdfTeX@>;
+ if pdf_link_attr(p) <> null then begin
+ print(" attr");
+ print_mark(pdf_link_attr(p));
+ end;
+ print(" action");
+ if pdf_action_type(pdf_link_action(p)) = pdf_action_user then begin
+ print(" user");
+ print_mark(pdf_action_user_tokens(pdf_link_action(p)));
+ return;
+ end;
+ if pdf_action_file(pdf_link_action(p)) <> null then begin
+ print(" file");
+ print_mark(pdf_action_file(pdf_link_action(p)));
+ end;
+ case pdf_action_type(pdf_link_action(p)) of
+ pdf_action_goto: begin
+ if pdf_action_named_id(pdf_link_action(p)) > 0 then begin
+ print(" goto name");
+ print_mark(pdf_action_id(pdf_link_action(p)));
+ end
+ else begin
+ print(" goto num");
+ print_int(pdf_action_id(pdf_link_action(p)))
+ end;
+ end;
+ pdf_action_page: begin
+ print(" page");
+ print_int(pdf_action_id(pdf_link_action(p)));
+ print_mark(pdf_action_page_tokens(pdf_link_action(p)));
+ end;
+ pdf_action_thread: begin
+ if pdf_action_named_id(pdf_link_action(p)) > 0 then begin
+ print(" thread name");
+ print_mark(pdf_action_id(pdf_link_action(p)));
+ end
+ else begin
+ print(" thread num");
+ print_int(pdf_action_id(pdf_link_action(p)));
+ end;
+ end;
+ othercases pdf_error("displaying", "unknown action type");
+ endcases;
+end;
+pdf_end_link_node: print_esc("pdfendlink");
+pdf_dest_node: begin
+ print_esc("pdfdest");
+ if pdf_dest_named_id(p) > 0 then begin
+ print(" name");
+ print_mark(pdf_dest_id(p));
+ end
+ else begin
+ print(" num");
+ print_int(pdf_dest_id(p));
+ end;
+ print(" ");
+ case pdf_dest_type(p) of
+ pdf_dest_xyz: begin
+ print("xyz");
+ if pdf_dest_xyz_zoom(p) <> null then begin
+ print(" zoom");
+ print_int(pdf_dest_xyz_zoom(p));
+ end;
+ end;
+ pdf_dest_fitbh: print("fitbh");
+ pdf_dest_fitbv: print("fitbv");
+ pdf_dest_fitb: print("fitb");
+ pdf_dest_fith: print("fith");
+ pdf_dest_fitv: print("fitv");
+ pdf_dest_fitr: begin
+ print("fitr");
+ @<Display <rule spec> for whatsit node created by \pdfTeX@>;
+ end;
+ pdf_dest_fit: print("fit");
+ othercases print("unknown!");
+ endcases;
+end;
+pdf_thread_node,
+pdf_start_thread_node: begin
+ if subtype(p) = pdf_thread_node then
+ print_esc("pdfthread")
+ else
+ print_esc("pdfstartthread");
+ print("("); print_rule_dimen(pdf_height(p)); print_char("+");
+ print_rule_dimen(pdf_depth(p)); print(")x");
+ print_rule_dimen(pdf_width(p));
+ if pdf_thread_attr(p) <> null then begin
+ print(" attr");
+ print_mark(pdf_thread_attr(p));
+ end;
+ if pdf_thread_named_id(p) > 0 then begin
+ print(" name");
+ print_mark(pdf_thread_id(p));
+ end
+ else begin
+ print(" num");
+ print_int(pdf_thread_id(p));
+ end;
+end;
+pdf_end_thread_node: print_esc("pdfendthread");
+pdf_save_pos_node: print_esc("pdfsavepos");
+othercases print("whatsit?")
+@z
+
+@x [1357]
+othercases confusion("ext2")
+@y
+pdf_literal_node: begin
+ r := get_node(write_node_size);
+ add_token_ref(pdf_literal_data(p));
+ words := write_node_size;
+end;
+pdf_refobj_node: begin
+ r := get_node(pdf_refobj_node_size);
+ words := pdf_refobj_node_size;
+end;
+pdf_refxform_node: begin
+ r := get_node(pdf_refxform_node_size);
+ words := pdf_refxform_node_size;
+end;
+pdf_refximage_node: begin
+ r := get_node(pdf_refximage_node_size);
+ words := pdf_refximage_node_size;
+end;
+pdf_annot_node: begin
+ r := get_node(pdf_annot_node_size);
+ add_token_ref(pdf_annot_data(p));
+ words := pdf_annot_node_size;
+end;
+pdf_start_link_node: begin
+ r := get_node(pdf_annot_node_size);
+ pdf_height(r) := pdf_height(p);
+ pdf_depth(r) := pdf_depth(p);
+ pdf_width(r) := pdf_width(p);
+ pdf_link_attr(r) := pdf_link_attr(p);
+ if pdf_link_attr(r) <> null then
+ add_token_ref(pdf_link_attr(r));
+ pdf_link_action(r) := pdf_link_action(p);
+ add_action_ref(pdf_link_action(r));
+end;
+pdf_end_link_node:
+ r := get_node(small_node_size);
+pdf_dest_node: begin
+ r := get_node(pdf_dest_node_size);
+ if pdf_dest_named_id(p) > 0 then
+ add_token_ref(pdf_dest_id(p));
+ words := pdf_dest_node_size;
+end;
+pdf_thread_node,
+pdf_start_thread_node: begin
+ r := get_node(pdf_thread_node_size);
+ if pdf_thread_named_id(p) > 0 then
+ add_token_ref(pdf_thread_id(p));
+ if pdf_thread_attr(p) <> null then
+ add_token_ref(pdf_thread_attr(p));
+ words := pdf_thread_node_size;
+end;
+pdf_end_thread_node:
+ r := get_node(small_node_size);
+pdf_save_pos_node:
+ r := get_node(small_node_size);
+othercases confusion("ext2")
+@z
+
+@x [1358]
+othercases confusion("ext3")
+@y
+pdf_literal_node: begin
+ delete_token_ref(pdf_literal_data(p));
+ free_node(p, write_node_size);
+end;
+pdf_refobj_node:
+ free_node(p, pdf_refobj_node_size);
+pdf_refxform_node:
+ free_node(p, pdf_refxform_node_size);
+pdf_refximage_node:
+ free_node(p, pdf_refximage_node_size);
+pdf_annot_node: begin
+ delete_token_ref(pdf_annot_data(p));
+ free_node(p, pdf_annot_node_size);
+end;
+pdf_start_link_node: begin
+ if pdf_link_attr(p) <> null then
+ delete_token_ref(pdf_link_attr(p));
+ delete_action_ref(pdf_link_action(p));
+ free_node(p, pdf_annot_node_size);
+end;
+pdf_end_link_node:
+ free_node(p, small_node_size);
+pdf_dest_node: begin
+ if pdf_dest_named_id(p) > 0 then
+ delete_token_ref(pdf_dest_id(p));
+ free_node(p, pdf_dest_node_size);
+end;
+pdf_thread_node,
+pdf_start_thread_node: begin
+ if pdf_thread_named_id(p) > 0 then
+ delete_token_ref(pdf_thread_id(p));
+ if pdf_thread_attr(p) <> null then
+ delete_token_ref(pdf_thread_attr(p));
+ free_node(p, pdf_thread_node_size);
+end;
+pdf_end_thread_node:
+ free_node(p, small_node_size);
+pdf_save_pos_node:
+ free_node(p, small_node_size);
+othercases confusion("ext3")
+@z
+
+@x [1359]
+@ @<Incorporate a whatsit node into a vbox@>=do_nothing
+@y
+@ @<Incorporate a whatsit node into a vbox@>=
+if (subtype(p) = pdf_refxform_node) or (subtype(p) = pdf_refximage_node) then
+begin x:=x+d+pdf_height(p); d:=pdf_depth(p);
+s:=0;
+if pdf_width(p)+s>w then w:=pdf_width(p)+s;
+end
+@z
+
+@x [1360]
+@ @<Incorporate a whatsit node into an hbox@>=do_nothing
+@y
+@ @<Incorporate a whatsit node into an hbox@>=
+if (subtype(p) = pdf_refxform_node) or (subtype(p) = pdf_refximage_node) then
+begin x:=x+pdf_width(p);
+s:=0;
+if pdf_height(p)-s>h then h:=pdf_height(p)-s;
+if pdf_depth(p)+s>d then d:=pdf_depth(p)+s;
+end
+@z
+
+@x [1361]
+@ @<Let |d| be the width of the whatsit |p|@>=d:=0
+@y
+@ @<Let |d| be the width of the whatsit |p|@>=
+if (subtype(p) = pdf_refxform_node) or (subtype(p) = pdf_refximage_node) then
+ d := pdf_width(p)
+else
+ d := 0
+@z
+
+@x [1362]
+@<Advance \(p)past a whatsit node in the \(l)|line_break| loop@>=@+
+adv_past(cur_p)
+@y
+@<Advance \(p)past a whatsit node in the \(l)|line_break| loop@>=@+
+begin
+adv_past(cur_p);
+if (subtype(cur_p) = pdf_refxform_node) or (subtype(cur_p) = pdf_refximage_node) then
+ act_width:=act_width+pdf_width(cur_p);
+end
+@z
+
+@x [1364]
+@ @<Prepare to move whatsit |p| to the current page, then |goto contribute|@>=
+goto contribute
+@y
+@ @<Prepare to move whatsit |p| to the current page, then |goto contribute|@>=
+begin
+ if (subtype(p) = pdf_refxform_node) or (subtype(p) = pdf_refximage_node) then
+ begin page_total:=page_total+page_depth+pdf_height(p);
+ page_depth:=pdf_depth(p);
+ end;
+ goto contribute;
+end
+@z
+
+@x [1365]
+@ @<Process whatsit |p| in |vert_break| loop, |goto not_found|@>=
+goto not_found
+@y
+@ @<Process whatsit |p| in |vert_break| loop, |goto not_found|@>=
+begin
+ if (subtype(p) = pdf_refxform_node) or (subtype(p) = pdf_refximage_node) then
+ begin cur_height:=cur_height+prev_dp+pdf_height(p); prev_dp:=pdf_depth(p);
+ end;
+ goto not_found;
+end
+@z
+
+@x [1375]
+@<Implement \.{\\immediate}@>=
+begin get_x_token;
+if (cur_cmd=extension)and(cur_chr<=close_node) then
+ begin p:=tail; do_extension; {append a whatsit node}
+ out_what(tail); {do the action immediately}
+ flush_node_list(tail); tail:=p; link(p):=null;
+ end
+else back_input;
+end
+@y
+@<Implement \.{\\immediate}@>=
+begin get_x_token;
+if cur_cmd=extension then begin
+ if cur_chr<=close_node then
+ begin p:=tail; do_extension; {append a whatsit node}
+ out_what(tail); {do the action immediately}
+ flush_node_list(tail); tail:=p; link(p):=null;
+ end
+ else case cur_chr of
+ pdf_obj_code: begin
+ do_extension; {scan object and set |pdf_last_obj|}
+ if obj_data_ptr(pdf_last_obj) = 0 then {this object has not been initialized yet}
+ pdf_error("ext1", "`\pdfobj reserveobjnum' cannot be used with \immediate");
+ pdf_write_obj(pdf_last_obj);
+ end;
+ pdf_xform_code: begin
+ do_extension; {scan form and set |pdf_last_xform|}
+ pdf_cur_form := pdf_last_xform;
+ pdf_ship_out(obj_xform_box(pdf_last_xform), false);
+ end;
+ pdf_ximage_code: begin
+ do_extension; {scan image and set |pdf_last_ximage|}
+ pdf_write_image(pdf_last_ximage);
+ end;
+ othercases back_input
+ endcases;
+end
+else
+ back_input;
+end
+@z
+
+@x [1378]
+@ @<Finish the extensions@>=
+for k:=0 to 15 do if write_open[k] then a_close(write_file[k])
+@y
+@ @<Finish the extensions@>=
+for k:=0 to 15 do if write_open[k] then a_close(write_file[k])
+
+@ Shipping out PDF marks.
+
+@<Types...@>=
+dest_name_entry = record
+ objname: str_number; {destination name}
+ objnum: integer; {destination object number}
+end;
+
+@ @<Glob...@>=
+@!cur_page_width: scaled; {width of page being shipped}
+@!cur_page_height: scaled; {height of page being shipped}
+@!cur_h_offset: scaled; {horizontal offset of page being shipped}
+@!cur_v_offset: scaled; {vertical offset of page being shipped}
+@!pdf_obj_list: pointer; {list of objects in the current page}
+@!pdf_xform_list: pointer; {list of forms in the current page}
+@!pdf_ximage_list: pointer; {list of images in the current page}
+@!pdf_link_level: integer; {depth of nesting of box containing link annotation}
+@!last_link: pointer; {pointer to the last link annotation}
+@!pdf_link_ht, pdf_link_dp, pdf_link_wd: scaled; {dimensions of the last link
+annotation}
+@!last_thread: pointer; {pointer to the last thread}
+@!pdf_thread_ht, pdf_thread_dp, pdf_thread_wd: scaled; {dimensions of the last
+thread}
+@!pdf_last_thread_id: halfword; {identifier of the last thread}
+@!pdf_last_thread_named_id: boolean; {is identifier of the last thread named}
+@!pdf_thread_level: integer; {depth of nesting of box containing the last thread}
+@!pdf_annot_list: pointer; {list of annotations in the current page}
+@!pdf_link_list: pointer; {list of link annotations in the current page}
+@!pdf_dest_list: pointer; {list of destinations in the current page}
+@!pdf_bead_list: pointer; {list of thread beads in the current page}
+@!pdf_obj_count: integer; {counter of objects}
+@!pdf_xform_count: integer; {counter of forms}
+@!pdf_ximage_count: integer; {counter of images}
+@!pdf_cur_form: integer; {the form being output}
+@!pdf_first_outline, pdf_last_outline, pdf_parent_outline: integer;
+@!pdf_xform_width,
+@!pdf_xform_height,
+@!pdf_xform_depth: scaled; {dimension of the current form}
+@!pdf_info_toks: pointer; {additional keys of Info dictionary}
+@!pdf_catalog_toks: pointer; {additional keys of Catalog dictionary}
+@!pdf_catalog_openaction: integer;
+@!pdf_names_toks: pointer; {additional keys of Names dictionary}
+@!pdf_dest_names_ptr: integer; {first unused position in |dest_names|}
+@!dest_names_size: integer; {maximum number of names in name tree of PDF output file}
+@!dest_names: ^dest_name_entry;
+@!image_orig_x, image_orig_y: integer; {origin of cropped pdf images}
+@!link_level_stack: pointer; {stack to save |pdf_link_level|}
+@!pdf_trailer_toks: pointer; {additional keys of Trailer dictionary}
+
+@ @<Set init...@>=
+pdf_link_level := -1;
+link_level_stack := null;
+pdf_first_outline:= 0;
+pdf_last_outline:= 0;
+pdf_parent_outline:= 0;
+pdf_obj_count := 0;
+pdf_xform_count := 0;
+pdf_ximage_count := 0;
+pdf_dest_names_ptr := 0;
+pdf_info_toks := null;
+pdf_catalog_toks := null;
+pdf_names_toks := null;
+pdf_catalog_openaction := 0;
+pdf_trailer_toks := null;
+
+@ The following procedures are needed for outputing whatsit nodes for
+pdfTeX.
+
+@<Declare procedures needed in |pdf_hlist_out|, |pdf_vlist_out|@>=
+procedure write_action(p: pointer); {write an action specification}
+var s: str_number;
+ d: integer;
+begin
+ if pdf_action_type(p) = pdf_action_user then begin
+ pdf_print_toks_ln(pdf_action_user_tokens(p));
+ return;
+ end;
+ pdf_print("<< ");
+ if pdf_action_file(p) <> null then begin
+ pdf_print("/F ");
+ s := tokens_to_string(pdf_action_file(p));
+ if (str_pool[str_start[s]] = 40) and
+ (str_pool[str_start[s] + length(s) - 1] = 41) then
+ pdf_print(s)
+ else begin
+ pdf_print_str(s);
+ end;
+ flush_str(s);
+ pdf_print(" ");
+ if pdf_action_new_window(p) > 0 then begin
+ pdf_print("/NewWindow ");
+ if pdf_action_new_window(p) = 1 then
+ pdf_print("true ")
+ else
+ pdf_print("false ");
+ end;
+ end;
+ case pdf_action_type(p) of
+ pdf_action_page: begin
+ if pdf_action_file(p) = null then begin
+ pdf_print("/S /GoTo /D [");
+ pdf_print_int(get_obj(obj_type_page, pdf_action_id(p), false));
+ pdf_print(" 0 R");
+ end
+ else begin
+ pdf_print("/S /GoToR /D [");
+ pdf_print_int(pdf_action_id(p) - 1);
+ end;
+ pdf_out(" ");
+ pdf_print(tokens_to_string(pdf_action_page_tokens(p)));
+ flush_str(last_tokens_string);
+ pdf_out("]");
+ end;
+ pdf_action_goto: begin
+ if pdf_action_file(p) = null then begin
+ pdf_print("/S /GoTo ");
+ d := get_obj(obj_type_dest, pdf_action_id(p),
+ pdf_action_named_id(p));
+ end
+ else
+ pdf_print("/S /GoToR ");
+ if pdf_action_named_id(p) > 0 then begin
+ pdf_str_entry("D", tokens_to_string(pdf_action_id(p)));
+ flush_str(last_tokens_string);
+ end
+ else if pdf_action_file(p) = null then
+ pdf_indirect("D", d)
+ else
+ pdf_error("ext4", "`goto' option cannot be used with both `file' and `num'");
+ end;
+ pdf_action_thread: begin
+ pdf_print("/S /Thread ");
+ if pdf_action_file(p) = null then
+ d := get_obj(obj_type_thread, pdf_action_id(p),
+ pdf_action_named_id(p));
+ if pdf_action_named_id(p) > 0 then begin
+ pdf_str_entry("D", tokens_to_string(pdf_action_id(p)));
+ flush_str(last_tokens_string);
+ end
+ else if pdf_action_file(p) = null then
+ pdf_indirect("D", d)
+ else
+ pdf_int_entry("D", pdf_action_id(p));
+ end;
+ endcases;
+ pdf_print_ln(" >>");
+end;
+
+procedure set_rect_dimens(p, parent_box: pointer; x, y, w, h, d, margin: scaled);
+begin
+ pdf_left(p) := cur_h;
+ if is_running(w) then
+ pdf_right(p) := x + width(parent_box)
+ else
+ pdf_right(p) := cur_h + w;
+ if is_running(h) then
+ pdf_top(p) := y - height(parent_box)
+ else
+ pdf_top(p) := cur_v - h;
+ if is_running(d) then
+ pdf_bottom(p) := y + depth(parent_box)
+ else
+ pdf_bottom(p) := cur_v + d;
+ pdf_left(p) := pdf_left(p) - margin;
+ pdf_top(p) := pdf_top(p) - margin;
+ pdf_right(p) := pdf_right(p) + margin;
+ pdf_bottom(p) := pdf_bottom(p) + margin;
+end;
+
+procedure do_annot(p, parent_box: pointer; x, y: scaled);
+begin
+ if not is_shipping_page then
+ pdf_error("ext4", "annotations cannot be inside an XForm");
+ if doing_leaders then
+ return;
+ set_rect_dimens(p, parent_box, x, y,
+ pdf_width(p), pdf_height(p), pdf_depth(p), 0);
+ obj_annot_ptr(pdf_annot_objnum(p)) := p;
+ pdf_append_list(pdf_annot_objnum(p))(pdf_annot_list);
+end;
+
+@ To implement nesting link annotations, we need a stack to save box testing
+level of each link that has been broken. Each stack entry holds the
+box nesting level and pointer the whatsit node created for
+corresponding \.{\\pdfstartlink}.
+
+@d link_level(#) == info(#)
+@d link_ptr(#) == info(# + 1)
+
+@<Declare procedures needed in |pdf_hlist_out|, |pdf_vlist_out|@>=
+procedure save_link_level(l: pointer);
+var p, r: pointer;
+begin
+ pdf_link_level := cur_s;
+ r := copy_node_list(l);
+ pdf_link_wd := pdf_width(r);
+ pdf_link_ht := pdf_height(r);
+ pdf_link_dp := pdf_depth(r);
+ p := get_node(small_node_size);
+ link_level(p) := pdf_link_level;
+ link_ptr(p) := r;
+ link(p) := link_level_stack;
+ link_level_stack := p;
+end;
+
+procedure do_link(p, parent_box: pointer; x, y: scaled);
+begin
+ if not is_shipping_page then
+ pdf_error("ext4", "link annotations cannot be inside an XForm");
+ if type(parent_box) <> hlist_node then
+ pdf_error("ext4", "link annotations can be inside hbox only");
+ save_link_level(p);
+ set_rect_dimens(p, parent_box, x, y,
+ pdf_link_wd, pdf_link_ht, pdf_link_dp, pdf_link_margin);
+ last_link := p;
+ pdf_create_obj(obj_type_others, 0);
+ obj_annot_ptr(obj_ptr) := p;
+ pdf_append_list(obj_ptr)(pdf_link_list);
+end;
+
+procedure restore_link_level;
+var p, r: pointer;
+begin
+ if link_level_stack = null then
+ pdf_error("ext4", "invalid stack of link nesting level");
+ p := link_level_stack;
+ link_level_stack := link(p);
+ r := link_ptr(p);
+ flush_node_list(r);
+ free_node(p, small_node_size);
+ p := link_level_stack;
+ if p = null then
+ pdf_link_level := -1
+ else begin
+ pdf_link_level := link_level(p);
+ r := link_ptr(p);
+ pdf_link_wd := pdf_width(r);
+ pdf_link_ht := pdf_height(r);
+ pdf_link_dp := pdf_depth(r);
+ end;
+end;
+
+procedure end_link;
+begin
+ if pdf_link_level <> cur_s then
+ pdf_error("ext4", "\pdfendlink ended up in different nesting level than \pdfstartlink");
+ if is_running(pdf_link_wd) and (last_link <> null) then
+ pdf_right(last_link) := cur_h + pdf_link_margin;
+ restore_link_level;
+ last_link := null;
+end;
+
+@ For ``running'' annotations we must append a new node when the end of
+annotation is in other box than its start. The new created node is identical to
+corresponding whatsit node representing the start of annotation, but its
+|info| field is |null|. We set |info| field just before destroying the node, in
+order to use |flush_node_list| to do the job.
+
+@<Declare procedures needed in |pdf_hlist_out|, |pdf_vlist_out|@>=
+procedure append_link(parent_box: pointer; x, y: scaled); {append a new
+|pdf_start_link_node| to |pdf_link_list| and update |last_link|}
+var p, r: integer;
+begin
+ if type(parent_box) <> hlist_node then
+ pdf_error("ext4", "link annotations can be inside hbox only");
+ r := copy_node_list(link_ptr(link_level_stack)); {copy link node to |r|}
+ info(r) := max_halfword; {mark that this node is not a whatsit node}
+ link(r) := null; {this node will be destroyed separately}
+ set_rect_dimens(r, parent_box, x, y,
+ pdf_link_wd, pdf_link_ht, pdf_link_dp, pdf_link_margin);
+ pdf_create_obj(obj_type_others, 0);
+ obj_annot_ptr(obj_ptr) := r;
+ last_link := r;
+ pdf_append_list(obj_ptr)(pdf_link_list);
+end;
+
+@ Threads are handled in similar way as link annotations.
+
+@<Declare procedures needed in |pdf_hlist_out|, |pdf_vlist_out|@>=
+procedure append_bead(p: pointer);
+var a, b, c, t: integer;
+begin
+ if not is_shipping_page then
+ pdf_error("ext4", "threads cannot be inside an XForm");
+ t := get_obj(obj_type_thread, pdf_thread_id(p), pdf_thread_named_id(p));
+ b := pdf_new_objnum;
+ obj_bead_ptr(b) := pdf_get_mem(pdfmem_bead_size);
+ obj_bead_page(b) := pdf_last_page;
+ obj_bead_data(b) := p;
+ if pdf_thread_attr(p) <> null then
+ obj_bead_attr(b) := tokens_to_string(pdf_thread_attr(p))
+ else
+ obj_bead_attr(b) := 0;
+ if obj_thread_first(t) = 0 then begin
+ obj_thread_first(t) := b;
+ obj_bead_next(b) := b;
+ obj_bead_prev(b) := b;
+ end
+ else begin
+ a := obj_thread_first(t);
+ c := obj_bead_prev(a);
+ obj_bead_prev(b) := c;
+ obj_bead_next(b) := a;
+ obj_bead_prev(a) := b;
+ obj_bead_next(c) := b;
+ end;
+ pdf_append_list(b)(pdf_bead_list);
+end;
+
+procedure do_thread(p, parent_box: pointer; x, y: scaled);
+begin
+ if doing_leaders then
+ return;
+ if subtype(p) = pdf_start_thread_node then begin
+ pdf_thread_wd := pdf_width(p);
+ pdf_thread_ht := pdf_height(p);
+ pdf_thread_dp := pdf_depth(p);
+ pdf_last_thread_id := pdf_thread_id(p);
+ pdf_last_thread_named_id := (pdf_thread_named_id(p) > 0);
+ if pdf_last_thread_named_id then
+ add_token_ref(pdf_thread_id(p));
+ pdf_thread_level := cur_s;
+ end;
+ set_rect_dimens(p, parent_box, x, y,
+ pdf_width(p), pdf_height(p), pdf_depth(p),
+ pdf_thread_margin);
+ append_bead(p);
+ last_thread := p;
+end;
+
+procedure append_thread(parent_box: pointer; x, y: scaled);
+var p: pointer;
+begin
+ p := get_node(pdf_thread_node_size);
+ info(p) := max_halfword; {this is not a whatsit node}
+ link(p) := null; {this node will be destroyed separately}
+ pdf_width(p) := pdf_thread_wd;
+ pdf_height(p) := pdf_thread_ht;
+ pdf_depth(p) := pdf_thread_dp;
+ pdf_thread_attr(p) := null;
+ pdf_thread_id(p) := pdf_last_thread_id;
+ if pdf_last_thread_named_id then begin
+ add_token_ref(pdf_thread_id(p));
+ pdf_thread_named_id(p) := 1;
+ end
+ else
+ pdf_thread_named_id(p) := 0;
+ set_rect_dimens(p, parent_box, x, y,
+ pdf_width(p), pdf_height(p), pdf_depth(p),
+ pdf_thread_margin);
+ append_bead(p);
+ last_thread := p;
+end;
+
+procedure end_thread;
+begin
+ if pdf_thread_level <> cur_s then
+ pdf_error("ext4", "\pdfendthread ended up in different nesting level than \pdfstartthread");
+ if is_running(pdf_thread_dp) and (last_thread <> null) then
+ pdf_bottom(last_thread) := cur_v + pdf_thread_margin;
+ if pdf_last_thread_named_id then
+ delete_token_ref(pdf_last_thread_id);
+ last_thread := null;
+end;
+
+function open_subentries(p: pointer): integer;
+var k, c: integer;
+ l, r: integer;
+begin
+ k := 0;
+ if obj_outline_first(p) <> 0 then begin
+ l := obj_outline_first(p);
+ repeat
+ incr(k);
+ c := open_subentries(l);
+ if obj_outline_count(l) > 0 then
+ k := k + c;
+ obj_outline_parent(l) := p;
+ r := obj_outline_next(l);
+ if r = 0 then
+ obj_outline_last(p) := l;
+ l := r;
+ until l = 0;
+ end;
+ if obj_outline_count(p) > 0 then
+ obj_outline_count(p) := k
+ else
+ obj_outline_count(p) := -k;
+ open_subentries := k;
+end;
+
+procedure do_dest(p, parent_box: pointer; x, y: scaled);
+var k: integer;
+begin
+ if not is_shipping_page then
+ pdf_error("ext4", "destinations cannot be inside an XForm");
+ if doing_leaders then
+ return;
+ k := get_obj(obj_type_dest, pdf_dest_id(p), pdf_dest_named_id(p));
+ if obj_dest_ptr(k) <> null then begin
+ warn_dest_dup(pdf_dest_id(p), pdf_dest_named_id(p),
+ "ext4", "has been already used, duplicate ignored");
+ return;
+ end;
+ obj_dest_ptr(k) := p;
+ pdf_append_list(k)(pdf_dest_list);
+ case pdf_dest_type(p) of
+ pdf_dest_xyz: begin
+ pdf_left(p) := cur_h;
+ pdf_top(p) := cur_v;
+ end;
+ pdf_dest_fith,
+ pdf_dest_fitbh:
+ pdf_top(p) := cur_v;
+ pdf_dest_fitv,
+ pdf_dest_fitbv:
+ pdf_left(p) := cur_h;
+ pdf_dest_fit,
+ pdf_dest_fitb:
+ do_nothing;
+ pdf_dest_fitr:
+ set_rect_dimens(p, parent_box, x, y,
+ pdf_width(p), pdf_height(p), pdf_depth(p),
+ pdf_dest_margin);
+ endcases;
+end;
+
+procedure out_form(p: pointer);
+begin
+ pdf_end_text;
+ pdf_print_ln("q");
+ if pdf_lookup_list(pdf_xform_list, pdf_xform_objnum(p)) = null then
+ pdf_append_list(pdf_xform_objnum(p))(pdf_xform_list);
+ cur_v := cur_v + obj_xform_depth(pdf_xform_objnum(p));
+ pdf_print("1 0 0 1 ");
+ pdf_print_bp(pdf_x(cur_h)); pdf_out(" ");
+ pdf_print_bp(pdf_y(cur_v));
+ pdf_print_ln(" cm");
+ pdf_print("/Fm");
+ pdf_print_int(obj_info(pdf_xform_objnum(p)));
+ pdf_print_resname_prefix;
+ pdf_print_ln(" Do");
+ pdf_print_ln("Q");
+end;
+
+procedure out_image(p: pointer);
+var image: integer;
+begin
+ image := obj_ximage_data(pdf_ximage_objnum(p));
+ pdf_end_text;
+ pdf_print_ln("q");
+ if pdf_lookup_list(pdf_ximage_list, pdf_ximage_objnum(p)) = null then
+ pdf_append_list(pdf_ximage_objnum(p))(pdf_ximage_list);
+ if not is_pdf_image(image) then begin
+ pdf_print_real(ext_xn_over_d(pdf_width(p),
+ ten_pow[6], one_hundred_bp), 4);
+ pdf_print(" 0 0 ");
+ pdf_print_real(ext_xn_over_d(pdf_height(p) + pdf_depth(p),
+ ten_pow[6], one_hundred_bp), 4);
+ pdf_out(" ");
+ pdf_print_bp(pdf_x(cur_h)); pdf_out(" ");
+ pdf_print_bp(pdf_y(cur_v));
+ end
+ else begin
+ pdf_print_real(ext_xn_over_d(pdf_width(p),
+ ten_pow[6], image_width(image)), 6);
+ pdf_print(" 0 0 ");
+ pdf_print_real(ext_xn_over_d(pdf_height(p) + pdf_depth(p),
+ ten_pow[6], image_height(image)), 6);
+ pdf_out(" ");
+ pdf_print_bp(pdf_x(cur_h) -
+ ext_xn_over_d(pdf_width(p), epdf_orig_x(image),
+ image_width(image)));
+ pdf_out(" ");
+ pdf_print_bp(pdf_y(cur_v) -
+ ext_xn_over_d(pdf_height(p), epdf_orig_y(image),
+ image_height(image)));
+ end;
+ pdf_print_ln(" cm");
+ pdf_print("/Im");
+ pdf_print_int(obj_info(pdf_ximage_objnum(p)));
+ pdf_print_resname_prefix;
+ pdf_print_ln(" Do");
+ pdf_print_ln("Q");
+end;
+
+
+@ @<Output the whatsit node |p| in |pdf_vlist_out|@>=
+case subtype(p) of
+pdf_literal_node:
+ pdf_out_literal(p);
+pdf_refobj_node:
+ pdf_append_list(pdf_obj_objnum(p))(pdf_obj_list);
+pdf_refxform_node:
+ @<Output a Form node in a vlist@>;
+pdf_refximage_node:
+ @<Output a Image node in a vlist@>;
+pdf_annot_node:
+ do_annot(p, this_box, left_edge, top_edge + height(this_box));
+pdf_start_link_node:
+ pdf_error("ext4", "\pdfstartlink ended up in vlist");
+pdf_end_link_node:
+ pdf_error("ext4", "\pdfendlink ended up in vlist");
+pdf_dest_node:
+ do_dest(p, this_box, left_edge, top_edge + height(this_box));
+pdf_thread_node,
+pdf_start_thread_node:
+ do_thread(p, this_box, left_edge, top_edge + height(this_box));
+pdf_end_thread_node:
+ end_thread;
+pdf_save_pos_node:
+ @<Save current position to |pdf_last_x_pos|, |pdf_last_y_pos|@>;
+special_node:
+ pdf_special(p);
+othercases out_what(p);
+endcases
+
+@ @<Glob...@>=
+@!is_shipping_page: boolean; {set to |shipping_page| when |pdf_ship_out| starts}
+
+@ @<Save current position to |pdf_last_x_pos|, |pdf_last_y_pos|@>=
+begin
+ pdf_last_x_pos := cur_h;
+ if is_shipping_page then
+ pdf_last_y_pos := cur_page_height - cur_v
+ else
+ pdf_last_y_pos := pdf_xform_height + pdf_xform_depth - cur_v;
+end
+
+@ @<Output a Image node in a vlist@>=
+begin cur_v:=cur_v+pdf_height(p)+pdf_depth(p); save_v:=cur_v;
+ cur_h:=left_edge;
+ out_image(p);
+ cur_v:=save_v; cur_h:=left_edge;
+ end
+
+@ @<Output a Form node in a vlist@>=
+begin cur_v:=cur_v+pdf_height(p); save_v:=cur_v;
+ cur_h:=left_edge;
+ out_form(p);
+ cur_v:=save_v+pdf_depth(p); cur_h:=left_edge;
+ end
+
+@ @<Output the whatsit node |p| in |pdf_hlist_out|@>=
+case subtype(p) of
+pdf_literal_node:
+ pdf_out_literal(p);
+pdf_refobj_node:
+ pdf_append_list(pdf_obj_objnum(p))(pdf_obj_list);
+pdf_refxform_node:
+ @<Output a Form node in a hlist@>;
+pdf_refximage_node:
+ @<Output a Image node in a hlist@>;
+pdf_annot_node:
+ do_annot(p, this_box, left_edge, base_line);
+pdf_start_link_node:
+ do_link(p, this_box, left_edge, base_line);
+pdf_end_link_node: begin
+ end_link;
+ @<Create link annotation for the current hbox if needed@>;
+end;
+pdf_dest_node:
+ do_dest(p, this_box, left_edge, base_line);
+pdf_thread_node:
+ do_thread(p, this_box, left_edge, base_line);
+pdf_start_thread_node:
+ pdf_error("ext4", "\pdfstartthread ended up in hlist");
+pdf_end_thread_node:
+ pdf_error("ext4", "\pdfendthread ended up in hlist");
+pdf_save_pos_node:
+ @<Save current position to |pdf_last_x_pos|, |pdf_last_y_pos|@>;
+special_node:
+ pdf_special(p);
+othercases out_what(p);
+endcases
+
+@ @<Output a Image node in a hlist@>=
+begin
+ cur_v:=base_line+pdf_depth(p);
+ edge:=cur_h;
+ out_image(p);
+ cur_h:=edge+pdf_width(p); cur_v:=base_line;
+ end
+
+@ @<Output a Form node in a hlist@>=
+begin
+ cur_v:=base_line;
+ edge:=cur_h;
+ out_form(p);
+ cur_h:=edge+pdf_width(p); cur_v:=base_line;
+ end
+@z
diff --git a/Build/source/texk/web2c/pdftexdir/pdftex.defines b/Build/source/texk/web2c/pdftexdir/pdftex.defines
new file mode 100644
index 00000000000..2bd9ef1fefa
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/pdftex.defines
@@ -0,0 +1,105 @@
+{
+Copyright (c) 1996-2005 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX 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.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/pdftex.defines#15 $
+}
+
+{ pdftex.defines: additions for pdfTeX }
+
+{ macros from pdftex.h }
+@define function pdfcharmarked();
+@define function getlpcode();
+@define function getrpcode();
+@define function getefcode();
+@define function texbopenin();
+@define function vfbopenin ();
+@define procedure pdfmarkchar();
+@define procedure writepdf();
+
+{ functions from mapfile.c }
+@define function hasfmentry();
+@define function tfmoffm();
+@define procedure checkextfm();
+@define procedure pdfmapfile();
+@define procedure pdfmapline();
+@define procedure pdfinitmapfile();
+
+{ functions from utils.c }
+@define procedure escapehex();
+@define procedure escapename();
+@define procedure escapestring();
+@define function extxnoverd();
+@define procedure getcreationdate;
+@define procedure getfiledump();
+@define procedure getfilemoddate();
+@define procedure getfilesize();
+@define procedure getmatch();
+@define procedure getmd5sum();
+@define function getresnameprefix;
+@define procedure initstarttime;
+@define function isquotebad;
+@define function makecstring();
+@define procedure matchstrings();
+@define procedure libpdffinish;
+@define procedure makepdftexbanner;
+@define procedure printcreationdate;
+@define procedure printID();
+@define procedure setjobid();
+@define procedure unescapehex();
+@define procedure writestreamlength();
+
+
+{ functions from vfpacket.c }
+@define function newvfpacket();
+@define function packetbyte;
+@define procedure startpacket();
+@define procedure storepacket();
+
+{ functions from writefont.c }
+@define procedure dopdffont();
+
+{ functions from writeimg.c }
+@define function checkimageb();
+@define function checkimagec();
+@define function checkimagei();
+@define function epdforigx();
+@define function epdforigy();
+@define function imageheight();
+@define function imagepages();
+@define function imagecolordepth();
+@define function imagewidth();
+@define function imagexres();
+@define function imageyres();
+@define function ispdfimage();
+@define function readimage();
+@define procedure deleteimage();
+@define procedure updateimageprocset();
+@define procedure writeimage();
+
+{ functions from writet3.c }
+@define function getpkcharwidth();
+
+{ functions from writezip.c }
+@define procedure writezip();
+
+{ functions from avlstuff.c }
+@define procedure avlputobj();
+@define function avlfindobj();
+
+{ end of pdftex.defines }
diff --git a/Build/source/texk/web2c/pdftexdir/pdftex.h b/Build/source/texk/web2c/pdftexdir/pdftex.h
new file mode 100644
index 00000000000..837d3f5a2e9
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/pdftex.h
@@ -0,0 +1,50 @@
+/*
+Copyright (c) 1996-2002 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX 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.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/pdftex.h#4 $
+*/
+
+/* Additions to texmfmp.h for pdfTeX */
+
+/* mark a char in font */
+#define pdfmarkchar(f, c) pdfcharused[f][c/8] |= (1<<(c%8))
+
+/* test whether a char in font is marked */
+#define pdfcharmarked(f, c) (boolean)(pdfcharused[f][c/8] & (1<<(c%8)))
+
+/* writepdf() always writes by fwrite() */
+#define writepdf(a, b) \
+ (void) fwrite ((char *) &pdfbuf[a], sizeof (pdfbuf[a]), \
+ (int) ((b) - (a) + 1), pdffile)
+
+#define getlpcode(f, c) \
+ (pdffontlpbase[f] == 0 ? 0 : pdfmem[pdffontlpbase[f] + c])
+
+#define getrpcode(f, c) \
+ (pdffontrpbase[f] == 0 ? 0 : pdfmem[pdffontrpbase[f] + c])
+
+#define getefcode(f, c) \
+ (pdffontefbase[f] == 0 ? 1000 : pdfmem[pdffontefbase[f] + c])
+
+#define texbopenin(f) \
+ open_input (&(f), kpse_tex_format, FOPEN_RBIN_MODE)
+#define vfbopenin(f) \
+ open_input (&(f), kpse_vf_format, FOPEN_RBIN_MODE)
+
+#include <pdftexdir/ptexlib.h>
diff --git a/Build/source/texk/web2c/pdftexdir/pdftex.mak b/Build/source/texk/web2c/pdftexdir/pdftex.mak
new file mode 100644
index 00000000000..1acfb87c4e9
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/pdftex.mak
@@ -0,0 +1,199 @@
+################################################################################
+#
+# Makefile : pdftex, web2c win32.mak fragment to build pdfTeX
+# Author : Fabrice Popineau <Fabrice.Popineau@supelec.fr>
+# Platform : Win32, Microsoft VC++ 6.0, depends upon fpTeX 0.5 sources
+# Time-stamp: <04/03/20 16:40:35 popineau>
+#
+################################################################################
+
+# The libraries are not mentioned. As the matter stands, a change in their
+# number or how they are configured requires changes to the main distribution
+# anyway.
+
+Makefile: pdftexdir\pdftex.mk
+
+pdftex_bin = $(objdir)\pdftex.exe $(objdir)\pdfetex.exe $(objdir)\ttf2afm.exe $(objdir)\pdftosrc.exe
+# pdftex_exe = pdftex.exe pdfetex.exe ttf2afm.exe pdftosrc.exe
+pdftex_pool = pdftex.pool pdfetex.pool
+# linux_build_dir = $(HOME)\pdftex\build\linux\texk\web2c
+
+# We build pdftex
+pdftex = $(objdir)\pdftex.exe
+!ifdef TEX_DLL
+pdftex = $(pdftex) $(objdir)\$(library_prefix)pdftex.dll
+!endif
+
+# The C sources.
+pdftex_c = pdftex.c
+pdftex_o = $(objdir)\pdftex.obj
+
+# Making pdftex
+!ifdef TEX_DLL
+$(objdir)\$(library_prefix)pdftex.exp: $(objdir)\$(library_prefix)pdftex.lib
+
+$(objdir)\$(library_prefix)pdftex.lib: $(pdftex_o)
+ $(archive) /DEF $(pdftex_o)
+
+$(objdir)\$(library_prefix)pdftex.dll: $(pdftex_o) $(objdir)\$(library_prefix)pdftex.exp $(objdir)\pdftex.res $(pdftexlibs) $(kpathsealib) $(proglib)
+ $(link_dll) $(**) $(socketlibs) $(conlibs)
+
+$(objdir)\pdftex.exe: $(objdir)\win32main.obj $(objdir)\$(library_prefix)pdftex.lib $(kpathsealib) $(proglib)
+ $(link) $(**) $(conlibs)
+!else
+$(objdir)\pdftex.exe: $(pdftex_o) $(objdir)\win32main.obj $(objdir)\pdftex.res $(pdftexlibs) $(kpathsealib) $(proglib)
+ $(link) $(**) $(socketlibs) $(conlibs)
+!endif
+
+# C file dependencies.
+$(pdftex_c) pdftexcoerce.h pdftexd.h: pdftex.p $(web2c_texmf)
+ $(web2c) pdftex
+
+# Tangling.
+pdftex.p pdftex.pool: .\$(objdir)\tangle.exe pdftex.web pdftex.ch
+ .\$(objdir)\tangle pdftex.web pdftex.ch
+
+# Generation of the web and ch files.
+pdftex.web: $(objdir)\tie.exe \
+ tex.web \
+ pdftexdir/pdftex.ch \
+ pdftexdir/hz.ch \
+ pdftexdir/misc.ch \
+ # pdftexdir\pdftex.mak
+ .\$(objdir)\tie -m pdftex.web tex.web \
+ pdftexdir\pdftex.ch \
+ $(srcdir)/pdftexdir/hz.ch \
+ $(srcdir)/pdftexdir/misc.ch
+
+pdftex.ch: $(objdir)\tie.exe pdftex.web \
+ pdftexdir\tex.ch0 \
+ tex.ch \
+ tex-supp-w32.ch \
+ pdftexdir\tex.ch1 \
+ pdftexdir\tex.pch \
+ pdftexdir\tex.ch2
+# pdftexdir\pdftex.mak
+ .\$(objdir)\tie -c pdftex.ch \
+ pdftex.web \
+ $(srcdir)\pdftexdir\tex.ch0 \
+ tex.ch \
+ tex-supp-w32.ch \
+ $(srcdir)\pdftexdir\tex.ch1 \
+ $(srcdir)\pdftexdir\tex.pch \
+ $(srcdir)\pdftexdir\tex.ch2
+
+# Tests...
+check: pdftex-check
+pdftex-check: pdftex pdftex.fmt
+
+# Cleaning up.
+clean:: pdftex-clean
+pdftex-clean:
+# $(LIBTOOL) --mode=clean $(RM) pdftex
+ -@echo $(verbose) & ( \
+ for %%i in ($(pdftex_o) $(pdftex_c) pdftexextra.c pdftexcoerce.h \
+ pdftexd.h pdftex.p pdftex.pool pdftex.web pdftex.ch \
+ pdftex.fmt pdftex.log) do $(del) %%i $(redir_stderr) \
+ )
+
+# Dumps.
+# all_pdffmts = pdftex.fmt $(pdffmts)
+
+# dumps: pdffmts
+# pdffmts: $(all_pdffmts)
+# pdftex.fmt: $(pdftex)
+# $(dumpenv) $(make) progname=pdftex files="plain.tex cmr10.tfm" prereq-check
+# $(dumpenv) .\$(objdir)\pdftex --progname=pdftex --jobname=pdftex --ini "\pdfoutput=1 \input plain \dump" <nul
+#
+# pdfolatex.fmt: $(pdftex)
+# $(dumpenv) $(make) progname=pdfolatex files="latex.ltx" prereq-check
+# $(dumpenv) .\$(objdir)\pdftex --progname=pdfolatex --jobname=pdfolatex --ini "\pdfoutput=1 \input latex.ltx" <nul
+#
+# pdflatex.fmt: $(pdftex)
+# $(dumpenv) $(make) progname=pdflatex files="latex.ltx" prereq-check
+# $(dumpenv) .\$(objdir)\pdftex --progname=pdflatex --jobname=pdflatex --ini "\pdfoutput=1 \input latex.ltx" <nul
+#
+#
+# Installation.
+install-pdftex: install-pdftex-exec install-pdftex-data
+install-pdftex-exec: install-pdftex-links
+# install-pdftex-data: install-pdftex-dumps
+install-pdftex-dumps: install-pdftex-fmts
+
+# The actual binary executables and pool files.
+install-programs: install-pdftex-programs
+install-pdftex-programs: $(pdftex) $(bindir)
+ -@echo $(verbose) & ( \
+ for %%p in ($(pdftex)) do $(copy) %%p $(bindir) \
+ ) $(redir_stdout)
+
+# install-links: install-pdftex-links
+install-pdftex-links: install-pdftex-programs
+# -@echo $(verbose) & ( \
+# pushd $(bindir) & \
+# $(del) .\pdfinitex.exe .\pdfvirtex.exe & \
+# $(lnexe) .\pdftex.exe $(bindir)\pdfinitex.exe & \
+# $(lnexe) .\pdftex.exe $(bindir)\pdfvirtex.exe & \
+# popd \
+# ) $(redir_stdout)
+ -@echo $(verbose) & ( \
+ if not "$(pdffmts)"=="" \
+ for %%i in ($(pdffmts)) do \
+ pushd $(bindir) & \
+ $(del) .\%%~ni.exe & \
+ $(lnexe) .\pdftex.exe $(bindir)\%%~ni.exe & \
+ popd \
+ ) $(redir_stdout)
+
+# install-fmts: install-pdftex-fmts
+install-pdftex-fmts: pdffmts $(fmtdir)
+ -@echo $(verbose) & ( \
+ for %%f in ($(all_pdffmts)) \
+ do $(copy) %%f $(fmtdir)\%%f \
+ ) $(redir_stdout)
+
+# Auxiliary files.
+install-data:: install-pdftex-data
+install-pdftex-data: $(texpooldir)
+ @$(copy) pdftex.pool $(texpooldir)\pdftex.pool $(redir_stdout)
+
+#
+# ttf2afm
+ttf2afm = $(objdir)\ttf2afm.exe
+
+$(objdir)\ttf2afm.exe: $(objdir)\ttf2afm.obj
+ $(link) $(**) $(kpathsealib) $(proglib) $(conlibs)
+
+$(objdir)\ttf2afm.obj: pdftexdir\ttf2afm.c pdftexdir\macnames.c
+ $(compile) -I.\pdftexdir pdftexdir\ttf2afm.c
+check: ttf2afm-check
+ttf2afm-check: $(objdir)\ttf2afm.exe
+clean:: ttf2afm-clean
+ttf2afm-clean:
+# $(LIBTOOL) --mode=clean $(RM) ttf2afm
+ -@echo $(verbose) & ( \
+ for %%i in ($(objdir)\ttf2afm.obj $(objdir)\macnames.obj \
+ ttf2afm.c macnames.c) do $(del) %%i $(redir_stderr) \
+ )
+#
+# pdftosrc
+pdftosrc = $(objdir)\pdftosrc.exe
+
+$(objdir)\pdftosrc.exe: $(objdir)\pdftosrc.obj $(xpdflib)
+ $(link) $(objdir)\pdftosrc.obj $(xpdflib) $(kpathsealib) $(proglib) $(conlibs)
+
+$(objdir)\pdftosrc.obj: pdftexdir\pdftosrc.cc
+ $(compile) /Tp $(**)
+check: pdftosrc-check
+pdftosrc-check: $(objdir)\pdftosrc.exe
+clean:: pdftosrc-clean
+pdftosrc-clean:
+# $(LIBTOOL) --mode=clean $(RM) pdftosrc
+ -@$(del) $(objdir)\pdftosrc.obj $(redir_stderr)
+
+# end of pdftex.mak
+#
+# Local variables:
+# page-delimiter: "^# \f"
+# mode: Makefile
+# End:
diff --git a/Build/source/texk/web2c/pdftexdir/pdftex.mk b/Build/source/texk/web2c/pdftexdir/pdftex.mk
new file mode 100644
index 00000000000..56a770546cf
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/pdftex.mk
@@ -0,0 +1,201 @@
+# Makefile fragment for pdfTeX and web2c. --infovore@xs4all.nl. Public domain.
+# This fragment contains the parts of the makefile that are most likely to
+# differ between releases of pdfTeX.
+
+# The libraries are not mentioned. As the matter stands, a change in their
+# number or how they are configured requires changes to the main distribution
+# anyway.
+
+# $Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/pdftex.mk#38 $
+
+Makefile: pdftexdir/pdftex.mk
+
+pdftex_bin = pdftex pdfetex ttf2afm pdftosrc
+linux_build_dir = $(HOME)/pdftex/build/linux/texk/web2c
+
+# We build pdftex
+pdftex = @PTEX@ pdftex
+pdftexdir = pdftexdir
+
+# Extract pdftex version
+pdftexdir/pdftex.version: pdftexdir/pdftex.ch
+ grep '^@d pdftex_version_string==' $(srcdir)/pdftexdir/pdftex.ch \
+ | sed "s/^.*'-//;s/'.*$$//" \
+ >pdftexdir/pdftex.version
+
+# The C sources.
+pdftex_c = pdftexini.c pdftex0.c pdftex1.c pdftex2.c pdftex3.c
+pdftex_o = pdftexini.o pdftex0.o pdftex1.o pdftex2.o pdftex3.o pdftexextra.o
+
+# Making pdftex
+pdftex: $(pdftex_o) $(pdftexextra_o) $(pdftexlibsdep)
+ @CXXHACKLINK@ $(pdftex_o) $(pdftexextra_o) $(pdftexlibs) $(socketlibs) @CXXHACKLDLIBS@ @CXXLDEXTRA@
+
+# C file dependencies.
+$(pdftex_c) pdftexcoerce.h pdftexd.h: pdftex.p $(web2c_texmf)
+ $(web2c) pdftex
+pdftexextra.c: pdftexdir/pdftexextra.h lib/texmfmp.c
+ sed s/TEX-OR-MF-OR-MP/pdftex/ $(srcdir)/lib/texmfmp.c >$@
+pdftexdir/pdftexextra.h: pdftexdir/pdftexextra.in pdftexdir/pdftex.version
+ sed s/PDFTEX-VERSION/`cat pdftexdir/pdftex.version`/ \
+ $(srcdir)/pdftexdir/pdftexextra.in >$@
+
+# Tangling.
+pdftex.p pdftex.pool: tangle pdftex.web pdftex.ch
+ $(TANGLE) pdftex.web pdftex.ch
+
+# Generation of the web and ch files.
+# Sources for pdftex.web:
+pdftex_web_srcs = $(srcdir)/tex.web \
+ $(srcdir)/pdftexdir/pdftex.ch \
+ $(srcdir)/pdftexdir/hz.ch \
+ $(srcdir)/pdftexdir/misc.ch \
+ $(srcdir)/pdftexdir/vadjust.ch \
+ $(srcdir)/pdftexdir/pdftex2.ch
+# Sources for etex.ch:
+pdftex_ch_srcs = pdftex.web \
+ $(srcdir)/pdftexdir/tex.ch0 \
+ $(srcdir)/tex.ch \
+ $(srcdir)/pdftexdir/tex.ch1 \
+ $(srcdir)/pdftexdir/tex.pch \
+ $(srcdir)/pdftexdir/noligatures.ch \
+ $(srcdir)/pdftexdir/pdfstrcmp.ch \
+ $(srcdir)/pdftexdir/randoms.ch
+# Rules:
+pdftex.web: tie pdftexdir/pdftex.mk $(pdftex_web_srcs)
+ $(TIE) -m pdftex.web $(pdftex_web_srcs)
+pdftex.ch: $(pdftex_ch_srcs)
+ $(TIE) -c pdftex.ch $(pdftex_ch_srcs)
+
+# for developing only
+pdftex-org.web: $(pdftex_ch_srcs_org)
+ $(TIE) -m $@ $(pdftex_ch_srcs_org)
+pdftex-all.web: pdftex.web pdftex.ch
+ $(TIE) -m $@ pdftex.web pdftex.ch
+
+# Tests...
+check: @PTEX@ pdftex-check
+pdftex-check: pdftex pdftex.fmt
+
+# Cleaning up.
+clean:: pdftex-clean
+pdftex-clean:
+ $(LIBTOOL) --mode=clean $(RM) pdftex
+ rm -f $(pdftex_o) $(pdftex_c) pdftexextra.c pdftexcoerce.h
+ rm -f pdftexdir/pdftexextra.h pdftexdir/pdftex.version
+ rm -f pdftexd.h pdftex.p pdftex.pool pdftex.web pdftex.ch
+ rm -f pdftex.fmt pdftex.log
+
+# Dumps.
+all_pdffmts = @FMU@ pdftex.fmt $(pdffmts)
+
+dumps: @PTEX@ pdffmts
+pdffmts: $(all_pdffmts)
+
+pdffmtdir = $(web2cdir)/pdftex
+$(pdffmtdir)::
+ $(SHELL) $(top_srcdir)/../mkinstalldirs $(pdffmtdir)
+
+pdftex.fmt: pdftex
+ $(dumpenv) $(MAKE) progname=pdftex files="plain.tex cmr10.tfm" prereq-check
+ $(dumpenv) ./pdftex --progname=pdftex --jobname=pdftex --ini \\pdfoutput=1 \\input plain \\dump </dev/null
+
+pdfolatex.fmt: pdftex
+ $(dumpenv) $(MAKE) progname=pdfolatex files="latex.ltx" prereq-check
+ $(dumpenv) ./pdftex --progname=pdfolatex --jobname=pdfolatex --ini \\pdfoutput=1 \\input latex.ltx </dev/null
+
+#pdflatex.fmt: pdftex
+# $(dumpenv) $(MAKE) progname=pdflatex files="latex.ltx" prereq-check
+# $(dumpenv) ./pdftex --progname=pdflatex --jobname=pdflatex --ini \\pdfoutput=1 \\input latex.ltx </dev/null
+
+#
+# Installation.
+install-pdftex: install-pdftex-exec install-pdftex-data
+install-pdftex-exec: install-pdftex-links
+install-pdftex-data: install-pdftex-pool @FMU@ install-pdftex-dumps
+install-pdftex-dumps: install-pdftex-fmts
+
+# The actual binary executables and pool files.
+install-programs: @PTEX@ install-pdftex-programs
+install-pdftex-programs: pdftex $(bindir)
+ for p in pdftex; do $(INSTALL_LIBTOOL_PROG) $$p $(bindir); done
+
+install-links: @PTEX@ install-pdftex-links
+install-pdftex-links: install-pdftex-programs
+ #cd $(bindir) && (rm -f pdfinitex pdfinitex; \
+ # $(LN) pdftex pdfinitex; $(LN) pdftex pdfvirtex)
+
+install-fmts: @PTEX@ install-pdftex-fmts
+install-pdftex-fmts: pdffmts $(pdffmtdir)
+ pdffmts="$(all_pdffmts)"; \
+ for f in $$pdffmts; do $(INSTALL_DATA) $$f $(pdffmtdir)/$$f; done
+ pdffmts="$(pdffmts)"; \
+ for f in $$pdffmts; do base=`basename $$f .fmt`; \
+ (cd $(bindir) && (rm -f $$base; $(LN) pdftex $$base)); done
+
+# Auxiliary files.
+install-data:: @PTEX@ install-pdftex-data
+install-pdftex-pool: pdftex.pool $(texpooldir)
+ $(INSTALL_DATA) pdftex.pool $(texpooldir)/pdftex.pool
+
+
+#
+# ttf2afm
+ttf2afm = ttf2afm
+
+ttf2afm: ttf2afm.o
+ $(kpathsea_link) ttf2afm.o $(kpathsea)
+ttf2afm.o: ttf2afm.c macnames.c
+ $(compile) -c $< -o $@
+ttf2afm.c:
+ cp $(srcdir)/pdftexdir/ttf2afm.c .
+macnames.c:
+ cp $(srcdir)/pdftexdir/macnames.c .
+check: ttf2afm-check
+ttf2afm-check: ttf2afm
+clean:: ttf2afm-clean
+ttf2afm-clean:
+ $(LIBTOOL) --mode=clean $(RM) ttf2afm
+ rm -f ttf2afm.o macnames.o
+ rm -f ttf2afm.c macnames.c
+#
+# pdftosrc
+pdftosrc = pdftosrc
+
+pdftosrc: pdftexdir/pdftosrc.o $(LIBXPDFDEP)
+ @CXXHACKLINK@ pdftexdir/pdftosrc.o $(LDLIBXPDF) -lm @CXXLDEXTRA@
+pdftexdir/pdftosrc.o:$(srcdir)/pdftexdir/pdftosrc.cc
+ cd pdftexdir && $(MAKE) pdftosrc.o
+check: pdftosrc-check
+pdftosrc-check: pdftosrc
+clean:: pdftosrc-clean
+pdftosrc-clean:
+ $(LIBTOOL) --mode=clean $(RM) pdftosrc
+#
+# pdftex binaries archive
+pdftexbin:
+ $(MAKE) $(pdftex_bin)
+
+pdftex-cross:
+ $(MAKE) web2c-cross
+ $(MAKE) pdftexbin
+
+web2c-cross: $(web2c_programs)
+ @if test ! -x $(linux_build_dir)/tangle; then echo Error: linux_build_dir not ready; exit -1; fi
+ rm -f web2c/fixwrites web2c/splitup web2c/web2c
+ cp -f $(linux_build_dir)/web2c/fixwrites web2c
+ cp -f $(linux_build_dir)/web2c/splitup web2c
+ cp -f $(linux_build_dir)/web2c/web2c web2c
+ touch web2c/fixwrites web2c/splitup web2c/web2c
+ $(MAKE) tangleboot && rm -f tangleboot && \
+ cp -f $(linux_build_dir)/tangleboot . && touch tangleboot
+ $(MAKE) ctangleboot && rm -f ctangleboot && \
+ cp -f $(linux_build_dir)/ctangleboot . && touch ctangleboot
+ $(MAKE) ctangle && rm -f ctangle && \
+ cp -f $(linux_build_dir)/ctangle . && touch ctangle
+ $(MAKE) tie && rm -f tie && \
+ cp -f $(linux_build_dir)/tie . && touch tie
+ $(MAKE) tangle && rm -f tangle && \
+ cp -f $(linux_build_dir)/tangle . && touch tangle
+
+# end of pdftex.mk
diff --git a/Build/source/texk/web2c/pdftexdir/pdftex2.ch b/Build/source/texk/web2c/pdftexdir/pdftex2.ch
new file mode 100644
index 00000000000..227cb474242
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/pdftex2.ch
@@ -0,0 +1,89 @@
+% WEB change file containing pdftex codes that are conveninent to be here
+% instead of pdftex.ch due to changes files coming after pdftex.ch (hz.ch &
+% vadjust.ch)
+%
+% Copyright (c) 1996-2005 Han Th\^e\llap{\raise 0.5ex\hbox{\'{}}} Th\`anh, <thanh@pdftex.org>
+%
+% This file is part of pdfTeX.
+%
+% pdfTeX 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.
+%
+% pdfTeX is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with pdfTeX; if not, write to the Free Software
+% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+%
+% $Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/pdftex2.ch#5 $
+
+@x [230] - tagcode
+@d ef_code_base == 4
+@y
+@d ef_code_base == 4
+@d tag_code == 5
+@z
+
+@x [230] - tagcode
+ ef_code_base: scanned_result(get_ef_code(n, k))(int_val);
+@y
+ ef_code_base: scanned_result(get_ef_code(n, k))(int_val);
+ tag_code: scanned_result(get_tag_code(n, k))(int_val);
+@z
+
+@x [???] - tagcode
+function init_font_base(v: integer): integer;
+@y
+procedure set_tag_code(f: internal_font_number; c: eight_bits; i: integer);
+var fixedi:integer;
+begin
+ if is_valid_char(c) then
+ begin fixedi := abs(fix_int(i,-7,0));
+ if fixedi >= 4 then begin
+ if char_tag(char_info(f)(c)) = ext_tag then
+ op_byte(char_info(f)(c)) := (op_byte(char_info(f)(c))) - ext_tag;
+ fixedi := fixedi - 4;
+ end;
+ if fixedi >= 2 then begin
+ if char_tag(char_info(f)(c)) = list_tag then
+ op_byte(char_info(f)(c)) := (op_byte(char_info(f)(c))) - list_tag;
+ fixedi := fixedi - 2;
+ end;
+ if fixedi >= 1 then begin
+ if char_tag(char_info(f)(c)) = lig_tag then
+ op_byte(char_info(f)(c)) := (op_byte(char_info(f)(c))) - lig_tag;
+ end;
+ end;
+end;
+
+function init_font_base(v: integer): integer;
+@z
+
+@x [1253] - tagcode
+ ef_code_base: set_ef_code(f, p, cur_val);
+@y
+ ef_code_base: set_ef_code(f, p, cur_val);
+ tag_code: set_tag_code(f, p, cur_val);
+@z
+
+@x [1254] - tagcode
+primitive("efcode",assign_font_int,ef_code_base);
+@!@:ef_code_}{\.{\\efcode} primitive@>
+@y
+primitive("efcode",assign_font_int,ef_code_base);
+@!@:ef_code_}{\.{\\efcode} primitive@>
+primitive("tagcode",assign_font_int,tag_code);
+@!@:tag_code_}{\.{\\tagcode} primitive@>
+@z
+
+@x [1255]
+ef_code_base: print_esc("efcode");
+@y
+ef_code_base: print_esc("efcode");
+tag_code: print_esc("tagcode");
+@z
diff --git a/Build/source/texk/web2c/pdftexdir/pdftexextra.in b/Build/source/texk/web2c/pdftexdir/pdftexextra.in
new file mode 100644
index 00000000000..cd81871bec9
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/pdftexextra.in
@@ -0,0 +1,40 @@
+/*
+Copyright (c) 1996-2004 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX 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.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: pdftexextra.in,v 1.4 2004/08/26 18:14:18 olaf Exp $
+*/
+
+/* pdftexextra.in: banner etc. for pdfTeX.
+
+ This is included by pdfTeX, from ../etexextra.c
+ (generated from ../lib/texmfmp.c).
+*/
+
+#define BANNER "This is pdfTeX, Version 3.141592-PDFTEX-VERSION"
+#define COPYRIGHT_HOLDER "Han The Thanh"
+#define AUTHOR NULL
+#define PROGRAM_HELP PDFTEXHELP
+#define BUG_ADDRESS "pdftex@tug.org"
+#define DUMP_VAR TEXformatdefault
+#define DUMP_LENGTH_VAR formatdefaultlength
+#define DUMP_OPTION "fmt"
+#define DUMP_EXT ".fmt"
+#define INPUT_FORMAT kpse_tex_format
+#define INI_PROGRAM "pdfinitex"
+#define VIR_PROGRAM "pdfvirtex"
diff --git a/Build/source/texk/web2c/pdftexdir/pdftexlib.mk b/Build/source/texk/web2c/pdftexdir/pdftexlib.mk
new file mode 100644
index 00000000000..5b3f745385c
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/pdftexlib.mk
@@ -0,0 +1,76 @@
+## pdftexlib.mk - Makefile fragment for libraries used by pdf[ex]tex.
+# Public domain.
+
+# The pdf*tex programs depend on a number of libraries.
+# Include dependencies to get the built if we don't do make
+# from the top-level directory.
+
+Makefile: pdftexdir/pdftexlib.mk
+
+# libz
+
+ZLIBDIR=../../libs/zlib
+ZLIBSRCDIR=$(srcdir)/$(ZLIBDIR)
+ZLIBDEP = @ZLIBDEP@
+LDZLIB = @LDZLIB@
+
+$(ZLIBDIR)/libz.a: $(ZLIBSRCDIR)
+ cd $(ZLIBDIR) && $(MAKE) $(common_makeargs) libz.a
+
+
+# libpng
+
+LIBPNGDIR=../../libs/libpng
+LIBPNGSRCDIR=$(srcdir)/$(LIBPNGDIR)
+LIBPNGDEP = @LIBPNGDEP@
+LDLIBPNG = @LDLIBPNG@
+
+$(LIBPNGDIR)/libpng.a: $(LIBPNGSRCDIR)/*.c
+ cd $(LIBPNGDIR) && $(MAKE) $(common_makeargs) libpng.a
+
+
+# libxpdf
+
+LIBXPDFDIR=../../libs/xpdf
+LIBXPDFSRCDIR=$(srcdir)/$(LIBXPDFDIR)
+LIBXPDFDEP = @LIBXPDFDEP@
+LDLIBXPDF = @LDLIBXPDF@
+
+$(LIBXPDFDIR)/fofi/libfofi.a: $(LIBXPDFSRCDIR)/fofi/*.cc \
+ $(LIBXPDFSRCDIR)/fofi/*.h
+ cd $(LIBXPDFDIR)/fofi; $(MAKE) $(common_makeargs) libfofi.a
+$(LIBXPDFDIR)/goo/libGoo.a: $(LIBXPDFSRCDIR)/goo/*.cc \
+ $(LIBXPDFSRCDIR)/goo/*.c $(LIBXPDFSRCDIR)/goo/*.h
+ cd $(LIBXPDFDIR)/goo; $(MAKE) $(common_makeargs) libGoo.a
+$(LIBXPDFDIR)/xpdf/libxpdf.a: $(LIBXPDFSRCDIR)/xpdf/*.cc \
+ $(LIBXPDFSRCDIR)/xpdf/*.h
+ cd $(LIBXPDFDIR)/xpdf; $(MAKE) $(common_makeargs) libxpdf.a
+
+
+# md5
+
+LIBMD5DIR=../../libs/md5
+LIBMD5SRCDIR=$(srcdir)/$(LIBMD5DIR)
+LIBMD5DEP=$(LIBMD5DIR)/md5.o
+
+$(LIBMD5DEP): $(LIBMD5SRCDIR)/md5.c $(LIBMD5SRCDIR)/md5.h
+clean:: md5lib-clean
+md5lib-clean:
+ rm -f $(LIBMD5DEP)
+
+
+# libpdf itself
+pdflib = pdftexdir/libpdf.a
+pdflib_sources = $(srcdir)/pdftexdir/*.c $(srcdir)/pdftexdir/*.cc \
+ $(srcdir)/pdftexdir/*.h
+
+pdftexdir/libpdf.a: $(pdflib_sources) pdftexdir/pdftexextra.h
+ cd pdftexdir && $(MAKE) $(common_makeargs) libpdf.a
+
+
+# Convenience variables.
+
+pdftexlibs = $(pdflib) $(LDLIBPNG) $(LDZLIB) $(LDLIBXPDF) $(LIBMD5DEP)
+pdftexlibsdep = $(pdflib) $(LIBPNGDEP) $(ZLIBDEP) $(LIBXPDFDEP) $(LIBMD5DEP)
+
+## end of pdftexlib.mk - Makefile fragment for libraries used by pdf[ex]tex.
diff --git a/Build/source/texk/web2c/pdftexdir/pdftoepdf.cc b/Build/source/texk/web2c/pdftexdir/pdftoepdf.cc
new file mode 100644
index 00000000000..ef52a356763
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/pdftoepdf.cc
@@ -0,0 +1,1072 @@
+/*
+Copyright 1996-2004 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX 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.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/pdftoepdf.cc#53 $
+*/
+
+#include <stdlib.h>
+#include <math.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <aconf.h>
+#include <GString.h>
+#include <gmem.h>
+#include <gfile.h>
+#include <config.h>
+#include "Object.h"
+#include "Stream.h"
+#include "Array.h"
+#include "Dict.h"
+#include "XRef.h"
+#include "Catalog.h"
+#include "Link.h"
+#include "Page.h"
+#include "GfxFont.h"
+#include "PDFDoc.h"
+#include "GlobalParams.h"
+#include "Error.h"
+
+#include "epdf.h"
+
+static const char perforce_id[] =
+ "$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/pdftoepdf.cc#53 $";
+
+/* we avoid reading all necessary kpathsea headers, but we need xstrdup */
+#ifdef __cplusplus
+extern "C" {
+ extern KPSEDLL char *xstrdup (const char *);
+}
+#else
+ extern KPSEDLL char *xstrdup (const char *);
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+// FIXME: This definition is a duplicate from ../pdftexcoerce.h, which is
+// not usable here because of different macro definitions.
+extern integer pdflastpdfboxspec ;
+}
+#endif
+
+/*
+ * Used flags below:
+ * PDFTEX_COPY_PAGEGROUP
+ * if pdfTeX should copy a page group (a new feature in pdf1.4 for
+ * transparency) of an included file. The current support for this is
+ * most likely broken. pdfTeX will at least give a warning if this flag
+ * is not set. Surprisingly Acrobat and Jaws display files without a
+ * page group correctly, so it might be safe to not set the flag.
+ * See also PDFTEX_COPY_PAGEGROUP_NOFAIL
+ * PDFTEX_COPY_PAGEGROUP_NOFAIL
+ * if set to false pdfTeX will treat a page group in an included file as
+ * an error and abort gracefully. This is only evaluated if
+ * PDFTEX_COPY_PAGEGROUP is set.
+ */
+
+// FIXME: These definitions are duplicates from pdftexd.h
+/* #define PDF_PDF_BOX_SPEC_MEDIA 0 */
+/* #define PDF_PDF_BOX_SPEC_CROP 1 */
+/* #define PDF_PDF_BOX_SPEC_BLEED 2 */
+/* #define PDF_PDF_BOX_SPEC_TRIM 3 */
+/* #define PDF_PDF_BOX_SPEC_ART 4 */
+#define pdfpdfboxspecmedia ( 0 )
+#define pdfpdfboxspeccrop ( 1 )
+#define pdfpdfboxspecbleed ( 2 )
+#define pdfpdfboxspectrim ( 3 )
+#define pdfpdfboxspecart ( 4 )
+
+// The prefix for the PDF keys special to pdfTeX
+// This has been registered with Adobe by Hans Hagen
+#define pdfkeyprefix "PTEX"
+
+// PdfObject encapsulates the xpdf Object type, and properly
+// frees its resources on destruction.
+// Use obj-> to access members of the Object, and
+// &obj to get a pointer to the object.
+// It is no longer necessary to call Object::free explicitely.
+
+class PdfObject {
+public:
+ PdfObject() { /* nothing */ }
+ ~PdfObject() { iObject.free(); }
+ Object* operator->() { return &iObject; }
+ Object* operator&() { return &iObject; }
+private: // no copying or assigning
+ PdfObject(const PdfObject &);
+ void operator=(const PdfObject &);
+public:
+ Object iObject;
+};
+
+// when copying the Resources of the selected page, all objects are copied
+// recusively top-down. Indirect objects however are not fetched during
+// copying, but get a new object number from pdftex and then will be
+// appended into a linked list. Duplicates are checked and removed from the
+// list of indirect objects during appending.
+
+enum InObjType {
+ objFont,
+ objFontDesc,
+ objOther
+};
+
+struct InObj {
+ Ref ref; // ref in original PDF
+ InObjType type; // object type
+ InObj *next; // next entry in list of indirect objects
+ integer num; // new object number in output PDF
+ fm_entry * fontmap; // pointer to font map entry
+ integer enc_objnum; // Encoding for objFont
+ int written; // has it been written to output PDF?
+};
+
+struct UsedEncoding {
+ integer enc_objnum;
+ GfxFont *font;
+ UsedEncoding *next;
+};
+
+static InObj *inObjList;
+static UsedEncoding *encodingList;
+static GBool isInit = gFalse;
+
+// --------------------------------------------------------------------
+// Maintain list of open embedded PDF files
+// --------------------------------------------------------------------
+
+struct PdfDocument {
+ char *file_name;
+ PDFDoc *doc;
+ XRef *xref;
+ InObj *inObjList;
+ int occurences; // number of references to the document; the doc can be
+ // deleted when this is negative
+ PdfDocument *next;
+};
+
+static PdfDocument *pdfDocuments = 0;
+
+static XRef *xref = 0;
+
+// Returns pointer to PdfDocument record for PDF file.
+// Creates a new record if it doesn't exist yet.
+// xref is made current for the document.
+
+static PdfDocument *find_add_document(char *file_name)
+{
+ PdfDocument *p = pdfDocuments;
+ while (p && strcmp(p->file_name, file_name) != 0)
+ p = p->next;
+ if (p) {
+ xref = p->xref;
+ (p->occurences)++;
+#ifdef DEBUG
+ fprintf(stderr, "\nIncrementing %s (%d)\n", p->file_name, p->occurences);
+#endif
+ return p;
+ }
+ p = new PdfDocument;
+ p->file_name = xstrdup(file_name);
+ p->xref = xref = 0;
+ p->occurences = 0;
+#ifdef DEBUG
+ fprintf(stderr, "\nCreating %s (%d)\n", p->file_name, p->occurences);
+#endif
+ GString *docName = new GString(p->file_name);
+ p->doc = new PDFDoc(docName); // takes ownership of docName
+ if (!p->doc->isOk() || !p->doc->okToPrint()) {
+ pdftex_fail("xpdf: reading PDF image failed");
+ }
+ p->inObjList = 0;
+ p->next = pdfDocuments;
+ pdfDocuments = p;
+ return p;
+}
+
+// Deallocate a PdfDocument with all its resources
+static void delete_document(PdfDocument *pdf_doc)
+{
+ PdfDocument **p = &pdfDocuments;
+ while (*p && *p != pdf_doc)
+ p = &((*p)->next);
+ // should not happen:
+ if (!*p)
+ return;
+ // unlink from list
+ *p = pdf_doc->next;
+ // free pdf_doc's resources
+ InObj *r, *n;
+ for (r = pdf_doc->inObjList; r != 0; r = n) {
+ n = r->next;
+ delete r;
+ }
+ xref = pdf_doc->xref;
+ delete pdf_doc->doc;
+ xfree(pdf_doc->file_name);
+ delete pdf_doc;
+}
+
+// Replacement for
+// Object *initDict(Dict *dict1){ initObj(objDict); dict = dict1; return this; }
+static void initDictFromDict (PdfObject &obj, Dict *dict)
+{
+ obj->initDict(xref);
+ for (int i = 0,
+ l = dict->getLength();
+ i < l;
+ i++) {
+ Object obj1;
+ obj->dictAdd(copyString(dict->getKey(i)), dict->getValNF(i, &obj1));
+ }
+}
+
+// --------------------------------------------------------------------
+
+static int addEncoding(GfxFont *gfont)
+{
+ UsedEncoding *n;
+ n = new UsedEncoding;
+ n->next = encodingList;
+ encodingList = n;
+ n->font = gfont;
+ n->enc_objnum = pdfnewobjnum();
+ return n->enc_objnum;
+}
+
+#define addFont(ref, fontmap, enc_objnum) \
+ addInObj(objFont, ref, fontmap, enc_objnum)
+
+#define addFontDesc(ref, fontmap) \
+ addInObj(objFontDesc, ref, fontmap, 0)
+
+#define addOther(ref) \
+ addInObj(objOther, ref, 0, 0)
+
+static int addInObj(InObjType type, Ref ref, fm_entry *f, integer e)
+{
+ InObj *p, *q, *n = new InObj;
+ if (ref.num == 0)
+ pdftex_fail("pdf inclusion: invalid reference");
+ n->ref = ref;
+ n->type = type;
+ n->next = 0;
+ n->fontmap = f;
+ n->enc_objnum = e;
+ n->written = 0;
+ if (inObjList == 0)
+ inObjList = n;
+ else {
+ for (p = inObjList; p != 0; p = p->next) {
+ if (p->ref.num == ref.num && p->ref.gen == ref.gen) {
+ delete n;
+ return p->num;
+ }
+ q = p;
+ }
+ // it is important to add new objects at the end of the list,
+ // because new objects are being added while the list is being
+ // written out.
+ q->next = n;
+ }
+ n->num = pdfnewobjnum();
+ return n->num;
+}
+
+static void copyObject(Object *);
+
+static void copyName(char *s)
+{
+ pdf_puts("/");
+ for (; *s != 0; s++) {
+ if (isdigit(*s) || isupper(*s) || islower(*s) || *s == '_' ||
+ *s == '.' || *s == '-' )
+ pdfout(*s);
+ else
+ pdf_printf("#%.2X", *s & 0xFF);
+ }
+}
+
+static void copyDictEntry(Object *obj, int i)
+{
+ PdfObject obj1;
+ copyName(obj->dictGetKey(i));
+ pdf_puts(" ");
+ obj->dictGetValNF(i, &obj1);
+ copyObject(&obj1);
+ pdf_puts("\n");
+}
+
+static void copyDict(Object *obj)
+{
+ int i, l;
+ if (!obj->isDict())
+ pdftex_fail("pdf inclusion: invalid dict type <%s>",
+ obj->getTypeName());
+ for (i = 0, l = obj->dictGetLength(); i < l; ++i)
+ copyDictEntry(obj, i);
+}
+
+static void copyFontDict(Object *obj, InObj *r)
+{
+ int i, l;
+ char *key;
+ if (!obj->isDict())
+ pdftex_fail("pdf inclusion: invalid dict type <%s>",
+ obj->getTypeName());
+ pdf_puts("<<\n");
+ if (r->type == objFont) { // Font dict
+ for (i = 0, l = obj->dictGetLength(); i < l; ++i) {
+ key = obj->dictGetKey(i);
+ if (strcmp("BaseFont", key) == 0 ||
+ strcmp("Encoding", key) == 0)
+ continue; // skip original values
+ copyDictEntry(obj, i);
+ }
+ // write new BaseFont and Encoding
+ pdf_printf("/BaseFont %i 0 R\n", (int)get_fontname(r->fontmap));
+ pdf_printf("/Encoding %i 0 R\n", (int)r->enc_objnum);
+ }
+ else { // FontDescriptor dict
+ for (i = 0, l = obj->dictGetLength(); i < l; ++i) {
+ key = obj->dictGetKey(i);
+ if (strcmp("FontName", key) == 0 ||
+ strncmp("FontFile", key, strlen("FontFile")) == 0)
+ continue; // ignore original FontFile/FontName
+ if (strcmp("CharSet", key) == 0)
+ continue; // ignore CharSet
+ copyDictEntry(obj, i);
+ }
+ // write new FontName and FontFile
+ pdf_printf("/FontName %i 0 R\n", (int)get_fontname(r->fontmap));
+ pdf_printf("/FontFile %i 0 R\n", (int)get_fontfile(r->fontmap));
+ }
+ pdf_puts(">>");
+}
+
+static void copyStream(Stream *str)
+{
+ int c;
+ str->reset();
+ while ((c = str->getChar()) != EOF)
+ pdfout(c);
+}
+
+static void copyProcSet(Object *obj)
+{
+ int i, l;
+ PdfObject procset;
+ if (!obj->isArray())
+ pdftex_fail("pdf inclusion: invalid ProcSet array type <%s>",
+ obj->getTypeName());
+ pdf_puts("/ProcSet [ ");
+ for (i = 0, l = obj->arrayGetLength(); i < l; ++i) {
+ obj->arrayGetNF(i, &procset);
+ if (!procset->isName())
+ pdftex_fail("pdf inclusion: invalid ProcSet entry type <%s>",
+ procset->getTypeName());
+ copyName(procset->getName());
+ pdf_puts(" ");
+ }
+ pdf_puts("]\n");
+}
+
+static void copyFont(char *tag, Object *fontRef)
+{
+ PdfObject fontdict, subtype, basefont, fontdescRef, fontdesc, charset, fontfile;
+ GfxFont *gfont;
+ fm_entry *fontmap;
+ // Check whether the font has already been embedded before analysing it.
+ InObj *p;
+ Ref ref = fontRef->getRef();
+ for (p = inObjList; p; p = p->next) {
+ if (p->ref.num == ref.num && p->ref.gen == ref.gen) {
+ copyName(tag);
+ pdf_printf(" %d 0 R ", p->num);
+ return;
+ }
+ }
+ /* only handle included Type1 fonts; anything else will be copied */
+ if (fontRef->fetch(xref, &fontdict) &&
+ fontdict->isDict() &&
+ fontdict->dictLookup("Subtype", &subtype) &&
+ subtype->isName() &&
+ fontdict->dictLookup("BaseFont", &basefont) &&
+ basefont->isName() &&
+ fontdict->dictLookupNF("FontDescriptor", &fontdescRef) &&
+ fontdescRef->isRef() &&
+ fontdescRef->fetch(xref, &fontdesc) &&
+ fontdesc->isDict() &&
+ fontdesc->dictLookupNF("FontDescriptor", &fontdescRef) &&
+ ((strcmp(subtype->getName(), "Type1") == 0 &&
+ fontdesc->dictLookup("FontFile", &fontfile)) ||
+ (strcmp(subtype->getName(), "Type1C") == 0 &&
+ fontdesc->dictLookup("FontFile3", &fontfile))) &&
+ fontfile->isStream()
+ ) {
+ fontmap = lookup_fontmap(basefont->getName());
+ if (fontmap != NULL) {
+ if (fontdesc->dictLookup("CharSet", &charset) &&
+ charset->isString() && is_subsetable(fontmap))
+ mark_glyphs(fontmap, charset->getString()->getCString());
+ else
+ embed_whole_font(fontmap);
+ addFontDesc(fontdescRef->getRef(), fontmap);
+ copyName(tag);
+ gfont = GfxFont::makeFont(xref, tag, fontRef->getRef(),
+ fontdict->getDict());
+ pdf_printf(" %d 0 R ", addFont(fontRef->getRef(), fontmap,
+ addEncoding(gfont)));
+ return;
+ }
+ }
+ copyName(tag);
+ pdf_puts(" ");
+ copyObject(fontRef);
+}
+
+static void copyFontResources(Object *obj)
+{
+ PdfObject fontRef;
+ int i, l;
+ if (!obj->isDict())
+ pdftex_fail("pdf inclusion: invalid font resources dict type <%s>",
+ obj->getTypeName());
+ pdf_puts("/Font << ");
+ for (i = 0, l = obj->dictGetLength(); i < l; ++i) {
+ obj->dictGetValNF(i, &fontRef);
+ if (fontRef->isRef())
+ copyFont(obj->dictGetKey(i), &fontRef);
+ else
+ pdftex_fail("pdf inclusion: invalid font in reference type <%s>",
+ fontRef->getTypeName());
+ }
+ pdf_puts(">>\n");
+}
+
+static void copyOtherResources(Object *obj, char *key)
+{
+ /* copies all other resources (write_epdf handles Fonts and ProcSets),
+ * but gives a warning if an object is not a dictionary.
+ */
+ if (!obj->isDict())
+ //FIXME: Write the message only to the log file
+ pdftex_warn("pdf inclusion: invalid other resource which is no dict"
+ " (key '%s', type <%s>); copying it anyway.",
+ key,
+ obj->getTypeName());
+ copyName(key);
+ pdf_puts(" ");
+ copyObject(obj);
+}
+
+/* converts double to string; very small and very large numbers are NOT
+ * converted to scientific notation.
+ * n must be a number or real confirming to the implementation limits of PDF as
+ * specified in appendix C.1 of the pdf ref.
+ * These are:
+ * maximum value of ints is +2^32
+ * maximum value of reals is +2^15
+ * smalles values of reals is 1/(2^16)
+ */
+static char *
+convertNumToPDF(double n)
+{
+ static const int precision = 6;
+ static const int fact = (int) 1E6; /* must be 10^precision */
+ static const double epsilon = 0.5E-6; /* 2epsilon must be 10^-precision */
+ static char buf[64];
+ // handle very small values: return 0
+ if (fabs(n) < epsilon) {buf[0] = '0'; buf[1] = '\0';}
+ else {
+ char ints[64];
+ int bindex = 0, sindex = 0;
+ int ival, fval;
+ // handle the sign part if n is negative
+ if (n < 0) {
+ buf[bindex++] = '-';
+ n = -n;
+ }
+ n += epsilon; // for rounding
+ // handle the integer part, simply with sprintf
+ ival = (int)floor(n);
+ n -= ival;
+ sprintf(ints, "%d", ival);
+ while (ints[sindex] != 0) buf[bindex++] = ints[sindex++];
+ // handle the fractional part up to 'precision' digits
+ fval = (int)floor(n*fact);
+ if (fval) {
+ // set a dot
+ buf[bindex++] = '.';
+ sindex = bindex + precision;
+ buf[sindex--] = '\0';
+ // fill up trailing zeros with the string terminator NULL
+ while (((fval % 10) == 0) && (sindex >= bindex)) {
+ buf[sindex--] = '\0';
+ fval /= 10;
+ }
+ // fill up the fractional part back to front
+ while (sindex >= bindex) {
+ buf[sindex--] = (fval % 10) + '0';
+ fval /= 10;
+ }
+ } else buf[bindex++] = 0;
+ }
+ return (char *)buf;
+}
+
+static void copyObject(Object *obj)
+{
+ PdfObject obj1;
+ int i, l, c;
+ Ref ref;
+ char *p;
+ GString *s;
+ if (obj->isBool()) {
+ pdf_printf("%s", obj->getBool() ? "true" : "false");
+ }
+ else if (obj->isInt()) {
+ pdf_printf("%i", obj->getInt());
+ }
+ else if (obj->isReal()) {
+ pdf_printf("%s", convertNumToPDF(obj->getReal()));
+ }
+ else if (obj->isNum()) {
+ pdf_printf("%s", convertNumToPDF(obj->getNum()));
+ }
+ else if (obj->isString()) {
+ s = obj->getString();
+ p = s->getCString();
+ l = s->getLength();
+ if (strlen(p) == (unsigned int)l) {
+ pdf_puts("(");
+ for (; *p != 0; p++) {
+ c = (unsigned char)*p;
+ if (c == '(' || c == ')' || c == '\\')
+ pdf_printf("\\%c", c);
+ else if (c < 0x20 || c > 0x7F)
+ pdf_printf("\\%03o", c);
+ else
+ pdfout(c);
+ }
+ pdf_puts(")");
+ }
+ else {
+ pdf_puts("<");
+ for (i = 0; i < l; i++) {
+ c = s->getChar(i) & 0xFF;
+ pdf_printf("%.2x", c);
+ }
+ pdf_puts(">");
+ }
+ }
+ else if (obj->isName()) {
+ copyName(obj->getName());
+ }
+ else if (obj->isNull()) {
+ pdf_puts("null");
+ }
+ else if (obj->isArray()) {
+ pdf_puts("[");
+ for (i = 0, l = obj->arrayGetLength(); i < l; ++i) {
+ obj->arrayGetNF(i, &obj1);
+ if (!obj1->isName())
+ pdf_puts(" ");
+ copyObject(&obj1);
+ }
+ pdf_puts("]");
+ }
+ else if (obj->isDict()) {
+ pdf_puts("<<\n");
+ copyDict(obj);
+ pdf_puts(">>");
+ }
+ else if (obj->isStream()) {
+ initDictFromDict (obj1, obj->streamGetDict());
+ obj->streamGetDict()->incRef();
+ pdf_puts("<<\n");
+ copyDict(&obj1);
+ pdf_puts(">>\n");
+ pdf_puts("stream\n");
+ copyStream(obj->getStream()->getBaseStream());
+ pdf_puts("endstream");
+ }
+ else if (obj->isRef()) {
+ ref = obj->getRef();
+ if (ref.num == 0) {
+ pdftex_warn("pdf inclusion: reference to invalid object was replaced by <null>");
+ pdf_puts("null");
+ }
+ else
+ pdf_printf("%d 0 R", addOther(ref));
+ }
+ else {
+ pdftex_fail("pdf inclusion: type <%s> cannot be copied",
+ obj->getTypeName());
+ }
+}
+
+static void writeRefs()
+{
+ InObj *r;
+ for (r = inObjList; r != 0; r = r->next) {
+ if (!r->written) {
+ Object obj1;
+ r->written = 1;
+ zpdfbeginobj(r->num);
+ xref->fetch(r->ref.num, r->ref.gen, &obj1);
+ if (r->type == objFont || r->type == objFontDesc)
+ copyFontDict(&obj1, r);
+ else
+ copyObject(&obj1);
+ pdf_puts("\n");
+ pdfendobj();
+ obj1.free();
+ }
+ }
+}
+
+static void writeEncodings()
+{
+ UsedEncoding *r, *n;
+ char *glyphNames[MAX_CHAR_CODE + 1], *s;
+ int i;
+ for (r = encodingList; r != 0; r = r->next) {
+ for (i = 0; i <= MAX_CHAR_CODE; i++) {
+ if (r->font->isCIDFont()) {
+ pdftex_warn("pdf inclusion: CID font included, encoding maybe wrong");
+ }
+ if ((s = ((Gfx8BitFont *)r->font)->getCharName(i)) != 0)
+ glyphNames[i] = s;
+ else
+ glyphNames[i] = notdef;
+ }
+ write_enc(glyphNames, NULL, r->enc_objnum);
+ }
+ for (r = encodingList; r != 0; r = n) {
+ n = r->next;
+ delete r->font;
+ delete r;
+ }
+}
+
+/* Reads various information about the pdf and sets it up for later inclusion.
+ * This will fail if the pdf version of the pdf is higher than
+ * minor_pdf_version_wanted or page_name is given and can not be found.
+ * It makes no sense to give page_name _and_ page_num.
+ * Returns the page number.
+ */
+integer
+read_pdf_info(char *image_name, char *page_name, integer page_num,
+ integer minor_pdf_version_wanted, integer always_use_pdf_pagebox,
+ integer pdf_inclusion_errorlevel)
+{
+ PdfDocument *pdf_doc;
+ Page *page;
+ int rotate;
+ PDFRectangle *pagebox;
+ float pdf_version_found, pdf_version_wanted;
+ // initialize
+ if (!isInit) {
+ globalParams = new GlobalParams();
+ globalParams->setErrQuiet(gFalse);
+ isInit = gTrue;
+ }
+ // open PDF file
+ pdf_doc = find_add_document(image_name);
+ epdf_doc = (void *) pdf_doc;
+#ifdef DEBUG
+ fprintf(stderr, "\nReading information on %s\n", pdf_doc->file_name);
+#endif
+ // check pdf version
+ // this works only for pdf 1.x -- but since any versions of pdf newer
+ // than 1.x will not be backwards compatible to pdf 1.x, pdfTeX will
+ // then have to changed drastically anyway.
+ pdf_version_found = pdf_doc->doc->getPDFVersion();
+ pdf_version_wanted = 1 + (minor_pdf_version_wanted * 0.1);
+ if (pdf_version_found > pdf_version_wanted) {
+ char msg[] = "pdf inclusion: found pdf version <%.1f>, but at most version <%.1f> allowed";
+ if (pdf_inclusion_errorlevel > 0) {
+ pdftex_fail(msg, pdf_version_found, pdf_version_wanted);
+ } else {
+ pdftex_warn(msg, pdf_version_found, pdf_version_wanted);
+ }
+ }
+ epdf_num_pages = pdf_doc->doc->getCatalog()->getNumPages();
+ if (page_name) {
+ // get page by name
+ GString name(page_name);
+ LinkDest *link = pdf_doc->doc->findDest(&name);
+ if (link == 0 || !link->isOk())
+ pdftex_fail("pdf inclusion: invalid destination <%s>",
+ page_name);
+ Ref ref = link->getPageRef();
+ page_num = pdf_doc->doc->getCatalog()->findPage(ref.num, ref.gen);
+ if (page_num == 0)
+ pdftex_fail("pdf inclusion: destination is not a page <%s>",
+ page_name);
+ delete link;
+ } else {
+ // get page by number
+ if (page_num <= 0 || page_num > epdf_num_pages)
+ pdftex_fail("pdf inclusion: required page does not exist <%i>",
+ epdf_num_pages);
+ }
+ // get the required page
+ page = pdf_doc->doc->getCatalog()->getPage(page_num);
+
+ // get the pagebox (media, crop...) to use.
+ // always_use_pdf_pagebox can set in the config file to override the
+ // setting through pdfximage.
+ if (always_use_pdf_pagebox < 1) {
+ switch (pdflastpdfboxspec) {
+ case pdfpdfboxspeccrop:
+ pagebox = page->getCropBox();
+ break;
+
+ case pdfpdfboxspecbleed:
+ pagebox = page->getBleedBox();
+ break;
+
+ case pdfpdfboxspectrim:
+ pagebox = page->getTrimBox();
+ break;
+
+ case pdfpdfboxspecart:
+ pagebox = page->getArtBox();
+ break;
+
+ default:
+ pagebox = page->getMediaBox();
+ }
+ }
+ else {
+ switch (always_use_pdf_pagebox) {
+ case 1 :
+ pagebox = page->getMediaBox();
+ break;
+ case 2 :
+ pagebox = page->getCropBox();
+ break;
+ case 3 :
+ pagebox = page->getBleedBox();
+ break;
+ case 4 :
+ pagebox = page->getTrimBox();
+ break;
+ default : // 5 and larger
+ pagebox = page->getArtBox();
+ }
+ }
+#ifdef DEBUG
+ fprintf(stderr,
+ "\npagebox->x1: %.8f, pagebox->x2: %.8f, pagebox->y1: %.8f, pagebox->y2: %.8f\n",
+ pagebox->x1, pagebox->x2, pagebox->y1, pagebox->y2);
+#endif
+ epdf_width = pagebox->x2 - pagebox->x1;
+ epdf_height = pagebox->y2 - pagebox->y1;
+ epdf_orig_x = pagebox->x1;
+ epdf_orig_y = pagebox->y1;
+
+ rotate = page->getRotate();
+ // handle page rotation and adjust dimens as needed
+ if (rotate != 0) {
+ if (rotate % 90 == 0) {
+ // handle only the simple case: multiple of 90s.
+ // these are the only values allowed according to the
+ // reference (v1.3, p.78).
+ // 180 needs no special treatment here
+ register float f;
+ switch (rotate) {
+ case 90: f = epdf_height; epdf_height = epdf_width; epdf_width = f; break;
+ case 270: f = epdf_height; epdf_height = epdf_width; epdf_width = f; break;
+ }
+ }
+ }
+ pdf_doc->xref = pdf_doc->doc->getXRef();
+ return page_num;
+}
+
+/* writes the current epf_doc.
+ * Here the included pdf is copied, so most errors that can happen during pdf
+ * inclusion will arise here.
+ */
+void
+write_epdf(void)
+{
+ Page *page;
+ PdfObject contents, obj1, obj2;
+ PdfObject group, metadata, pieceinfo, separationInfo;
+ Object info;
+ char *key;
+ int i, l;
+ int rotate;
+ double scale[6] = {0, 0, 0, 0, 0, 0};
+ bool writematrix = false;
+ PdfDocument *pdf_doc = (PdfDocument *) epdf_doc;
+ (pdf_doc->occurences)--;
+#ifdef DEBUG
+ fprintf(stderr, "\nDecrementing %s (%d)\n", pdf_doc->file_name, pdf_doc->occurences);
+#endif
+ xref = pdf_doc->xref;
+ inObjList = pdf_doc->inObjList;
+ encodingList = 0;
+ page = pdf_doc->doc->getCatalog()->getPage(epdf_selected_page);
+ rotate = page->getRotate();
+ PDFRectangle *pagebox;
+ // write the Page header
+ pdf_puts("/Type /XObject\n");
+ pdf_puts("/Subtype /Form\n");
+ pdf_puts("/FormType 1\n");
+
+ // write additional information
+ pdf_printf("/%s.FileName (%s)\n", pdfkeyprefix,
+ convertStringToPDFString(pdf_doc->file_name,
+ strlen(pdf_doc->file_name)));
+ pdf_printf("/%s.PageNumber %i\n", pdfkeyprefix, epdf_selected_page);
+ pdf_doc->doc->getDocInfoNF(&info);
+ if (info.isRef()) {
+ // the info dict must be indirect (pdf ref p.61)
+ pdf_printf("/%s.InfoDict ", pdfkeyprefix);
+ pdf_printf("%d 0 R \n", addOther(info.getRef()));
+ }
+
+ // get the pagebox (media, crop...) to use.
+ // epdf_always_use_pdf_pagebox is a copy of always_use_pdf_pagebox which
+ // can set in the config file to override the setting through pdfximage.
+ if (epdf_always_use_pdf_pagebox < 1) {
+ switch (epdf_page_box) {
+ case pdfpdfboxspeccrop:
+ pagebox = page->getCropBox();
+ break;
+
+ case pdfpdfboxspecbleed:
+ pagebox = page->getBleedBox();
+ break;
+
+ case pdfpdfboxspectrim:
+ pagebox = page->getTrimBox();
+ break;
+
+ case pdfpdfboxspecart:
+ pagebox = page->getArtBox();
+ break;
+
+ default:
+ pagebox = page->getMediaBox();
+ }
+ }
+ else {
+ switch (epdf_always_use_pdf_pagebox) {
+ case 1 :
+ pagebox = page->getMediaBox();
+ break;
+ case 2 :
+ pagebox = page->getCropBox();
+ break;
+ case 3 :
+ pagebox = page->getBleedBox();
+ break;
+ case 4 :
+ pagebox = page->getTrimBox();
+ break;
+ default : // 5 and larger
+ pagebox = page->getArtBox();
+ }
+ }
+#ifdef DEBUG
+ fprintf(stderr,
+ "\npagebox->x1: %.8f, pagebox->x2: %.8f, pagebox->y1: %.8f, pagebox->y2: %.8f\n",
+ pagebox->x1, pagebox->x2, pagebox->y1, pagebox->y2);
+#endif
+
+ // handle page rotation
+ if (rotate != 0) {
+ if (rotate % 90 == 0) {
+ // this handles only the simple case: multiple of 90s but these
+ // are the only values allowed according to the reference
+ // (v1.3, p.78).
+ // the image is rotated around its center.
+ // the /Rotate key is clockwise while the matrix is
+ // counterclockwise :-%
+ tex_printf (", page is rotated %d degrees", rotate);
+ switch (rotate) {
+ case 90: scale[1] = -1; scale[2] = 1; scale[4] = pagebox->x1 - pagebox->y1; scale[5] = pagebox->y1 + pagebox->x2; writematrix = true; break;
+ case 180: scale[0] = scale[3] = -1; scale[4] = pagebox->x1 + pagebox->x2; scale[5] = pagebox->y1 + pagebox->y2; writematrix = true; break; // width and height are exchanged
+ case 270: scale[1] = 1; scale[2] = -1; scale[4] = pagebox->x1 + pagebox->y2; scale[5] = pagebox->y1 - pagebox->x1; writematrix = true; break;
+ }
+ if (writematrix) { // The matrix is only written if the image is rotated.
+ pdf_printf("/Matrix [%.8f %.8f %.8f %.8f %.8f %.8f]\n",
+ scale[0],
+ scale[1],
+ scale[2],
+ scale[3],
+ scale[4],
+ scale[5]);
+ }
+ }
+ }
+
+ pdf_printf("/BBox [%.8f %.8f %.8f %.8f]\n",
+ pagebox->x1,
+ pagebox->y1,
+ pagebox->x2,
+ pagebox->y2);
+
+ // write the page Group if it's there
+ if (page->getGroup() != NULL) {
+#if PDFTEX_COPY_PAGEGROUP
+# if PDFTEX_COPY_PAGEGROUP_NOFAIL
+ // FIXME: This will most likely produce incorrect PDFs :-(
+ initDictFromDict(group, page->getGroup());
+ if (group->dictGetLength() > 0) {
+ pdf_puts("/Group ");
+ copyObject (&group);
+ pdf_puts("\n");
+ }
+# else
+ // FIXME: currently we don't know how to handle Page Groups so we abort gracefully :-(
+ pdftex_fail("pdf inclusion: Page Group detected which pdfTeX can't handle. Sorry.");
+# endif
+#else
+ // FIXME: currently we don't know how to handle Page Groups so we at least give a warning :-(
+ pdftex_warn("pdf inclusion: Page Group detected which pdfTeX can't handle. Ignoring it.");
+#endif
+ }
+
+ // write the page Metadata if it's there
+ if (page->getMetadata() != NULL) {
+ metadata->initStream(page->getMetadata());
+ pdf_puts("/Metadata ");
+ copyObject (&metadata);
+ pdf_puts("\n");
+ }
+
+ // write the page PieceInfo if it's there
+ if (page->getPieceInfo() != NULL) {
+ initDictFromDict (pieceinfo, page->getPieceInfo());
+ if (pieceinfo->dictGetLength() > 0) {
+ pdf_puts("/PieceInfo ");
+ copyObject (&pieceinfo);
+ pdf_puts("\n");
+ }
+ }
+
+ // write the page SeparationInfo if it's there
+ if (page->getSeparationInfo() != NULL) {
+ initDictFromDict (separationInfo, page->getSeparationInfo());
+ if (separationInfo->dictGetLength() > 0) {
+ pdf_puts("/SeparationInfo ");
+ copyObject (&separationInfo);
+ pdf_puts("\n");
+ }
+ }
+
+ // write the Resources dictionary
+ if (page->getResourceDict() == NULL) {
+ // Resources can be missing (files without them have been spotted
+ // in the wild). This violates the pdf spec, which claims they are
+ // required, but all RIPs accept them.
+ // We "replace" them with empty Resources.
+ pdftex_warn("pdf inclusion: no /Resources detected. Replacing with empty /Resources.");
+ pdf_puts("/Resources <<>>\n");
+ }
+ else {
+ initDictFromDict (obj1, page->getResourceDict());
+ page->getResourceDict()->incRef();
+ if (!obj1->isDict())
+ pdftex_fail("pdf inclusion: invalid resources dict type <%s>",
+ obj1->getTypeName());
+ pdf_puts("/Resources <<\n");
+ for (i = 0, l = obj1->dictGetLength(); i < l; ++i) {
+ obj1->dictGetVal(i, &obj2);
+ key = obj1->dictGetKey(i);
+ if (strcmp("Font", key) == 0)
+ copyFontResources(&obj2);
+ else if (strcmp("ProcSet", key) == 0)
+ copyProcSet(&obj2);
+ else
+ copyOtherResources(&obj2, key);
+ }
+ pdf_puts(">>\n");
+ }
+ // write the page contents
+ page->getContents(&contents);
+ if (contents->isStream()) {
+ initDictFromDict (obj1, contents->streamGetDict());
+ contents->streamGetDict()->incRef();
+ copyDict(&obj1);
+ pdf_puts(">>\nstream\n");
+ copyStream(contents->getStream()->getBaseStream());
+ pdf_puts("endstream\n");
+ pdfendobj();
+ }
+ else if (contents->isArray()) {
+ pdfbeginstream();
+ for (i = 0, l = contents->arrayGetLength(); i < l; ++i) {
+ Object contentsobj;
+ copyStream((contents->arrayGet(i, &contentsobj))->getStream());
+ contentsobj.free();
+ }
+ pdfendstream();
+ }
+ else {// the contents are optional, but we need to include an empty stream
+ pdfbeginstream();
+ pdfendstream();
+ }
+ // write out all indirect objects
+ writeRefs();
+ // write out all used encodings (and delete list)
+ writeEncodings();
+ // save object list, xref
+ pdf_doc->inObjList = inObjList;
+ pdf_doc->xref = xref;
+}
+
+// Called when an image has been written and it's resources in image_tab are
+// freed and it's not referenced anymore.
+void
+epdf_delete()
+{
+ PdfDocument *pdf_doc = (PdfDocument *) epdf_doc;
+ xref = pdf_doc->xref;
+ if (pdf_doc->occurences < 0) {
+#ifdef DEBUG
+ fprintf(stderr, "\nDeleting %s\n", pdf_doc->file_name);
+#endif
+ delete_document(pdf_doc);
+ }
+}
+
+// Called when PDF embedding system is finalized.
+// Now deallocate all remaining PdfDocuments.
+void epdf_check_mem()
+{
+ if (isInit) {
+ PdfDocument *p, *n;
+ for (p = pdfDocuments; p; p = n) {
+ n = p->next;
+ delete_document(p);
+ }
+ // see above for globalParams
+ delete globalParams;
+ }
+}
+// vi:ts=4:tw=79:expandtab:ai:
diff --git a/Build/source/texk/web2c/pdftexdir/pdftosrc.cc b/Build/source/texk/web2c/pdftexdir/pdftosrc.cc
new file mode 100644
index 00000000000..ec83aca7b94
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/pdftosrc.cc
@@ -0,0 +1,130 @@
+/*
+Copyright (c) 1996-2002 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX 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.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/pdftosrc.cc#10 $
+*/
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <aconf.h>
+#include <GString.h>
+#include <gmem.h>
+#include <gfile.h>
+#include "Object.h"
+#include "Stream.h"
+#include "Array.h"
+#include "Dict.h"
+#include "XRef.h"
+#include "Catalog.h"
+#include "Page.h"
+#include "GfxFont.h"
+#include "PDFDoc.h"
+#include "GlobalParams.h"
+#include "Error.h"
+
+static XRef *xref = 0;
+
+int main(int argc, char *argv[])
+{
+ char *p, buf[1024];
+ PDFDoc *doc;
+ GString *fileName;
+ Stream *s;
+ Object srcStream, srcName, catalogDict;
+ FILE *outfile;
+ char *outname;
+ int objnum = 0, objgen = 0;
+ int c;
+ fprintf(stderr, "pdftosrc version %s\n", xpdfVersion);
+ if (argc < 2) {
+ fprintf(stderr, "Usage: pdftosrc <PDF-file> [<stream-object-number>]\n");
+ exit(1);
+ }
+ fileName = new GString(argv[1]);
+ globalParams = new GlobalParams();
+ doc = new PDFDoc(fileName);
+ if (!doc->isOk()) {
+ fprintf(stderr, "Invalid PDF file\n");
+ exit(1);
+ }
+ if (argc >= 3) {
+ objnum = atoi(argv[2]);
+ if (argc >= 4)
+ objgen = atoi(argv[3]);
+ }
+ xref = doc->getXRef();
+ catalogDict.initNull();
+ xref->getCatalog(&catalogDict);
+ if (!catalogDict.isDict("Catalog")) {
+ fprintf(stderr, "No Catalog found\n");
+ exit(1);
+ }
+ srcStream.initNull();
+ if (objnum == 0) {
+ catalogDict.dictLookup("SourceObject", &srcStream);
+ if (!srcStream.isStream("SourceFile")) {
+ fprintf(stderr, "No SourceObject found\n");
+ exit(1);
+ }
+ srcName.initNull();
+ srcStream.getStream()->getDict()->lookup("SourceName", &srcName);
+ if (!srcName.isString()) {
+ fprintf(stderr, "No SourceName found\n");
+ exit(1);
+ }
+ outname = srcName.getString()->getCString();
+ // We cannot free srcName, as objname shares its string.
+ // srcName.free();
+ }
+ else {
+ xref->fetch(objnum, objgen, &srcStream);
+ if (!srcStream.isStream()) {
+ fprintf(stderr, "Not a Stream object\n");
+ exit(1);
+ }
+ sprintf(buf, "%s", fileName->getCString());
+ if ((p = strrchr(buf, '.')) == 0)
+ p = strchr(buf, 0);
+ if (objgen == 0)
+ sprintf(p, ".%i", objnum);
+ else
+ sprintf(p, ".%i+%i", objnum, objgen);
+ outname = buf;
+ }
+ if (!(outfile = fopen(outname, "wb"))) {
+ fprintf(stderr, "Cannot open file \"%s\" for writing\n", outname);
+ exit(1);
+ }
+ s = srcStream.getStream();
+ s->reset();
+ while ((c = s->getChar()) != EOF)
+ fputc(c, outfile);
+ if (objnum == 0)
+ fprintf(stderr, "Source file extracted to %s\n", outname);
+ else
+ fprintf(stderr, "Stream object extracted to %s\n", outname);
+ fclose(outfile);
+ catalogDict.free();
+ srcStream.free();
+ delete doc;
+ delete globalParams;
+}
diff --git a/Build/source/texk/web2c/pdftexdir/pdftosrc.rc b/Build/source/texk/web2c/pdftexdir/pdftosrc.rc
new file mode 100644
index 00000000000..6929fbade24
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/pdftosrc.rc
@@ -0,0 +1,35 @@
+/* pdftosrc.rc: pdftosrc resources -*- C++ -*-
+
+ Copyright (C) 1996-2003 Fabrice Popineau <fabrice.popineau@supelec.fr>
+
+ This file is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ This file is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this file; if not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
+
+#include <texlive-version.h>
+
+#define VER_FILEVERSION TEXLIVE_MAJOR_VERSION,TEXLIVE_MINOR_VERSION,TEXLIVE_BETA_NUMBER,TEXLIVE_ALPHA_NUMBER
+#define VER_FILEVERSION_STR TEXLIVE_PRODUCTVERSION_STR " pdftosrc 2.01"
+
+#define VER_INTERNALNAME_STR "pdftosrc"
+#define VER_ORIGINALFILENAME_STR "pdftosrc.exe"
+
+#define VER_FILEDESCRIPTION_STR "PDF Source Extractor"
+
+#define VER_COMPANYNAME_STR ""
+#define VER_LEGALCOPYRIGHT_STR ""
+
+#include <texlive.version>
+
+/* pdftosrc.rc ends here */
diff --git a/Build/source/texk/web2c/pdftexdir/pkin.c b/Build/source/texk/web2c/pdftexdir/pkin.c
new file mode 100644
index 00000000000..3bece2124ad
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/pkin.c
@@ -0,0 +1,427 @@
+/*
+Copyright (c) 1996-2002 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX 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.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/pkin.c#4 $
+*/
+
+/*
+ * NAME
+ * pkin.c - implementation of readchar()
+ * DESCRIPTION
+ * This implementation of readchar() uses parts of the program dvips
+ * written by Tomas Rokicki--the inventor of the pkformat--(loadfont.c,
+ * download.c and unpack.c). Dvips in turn is derived from pktype.
+ * Pktype(TeX) is described in debt in ``The PKtype processor'',
+ * which is available as pktype.weave as part of the METAFONTware.
+ * What was needed to implement readchar() is rearranged in pkfile.c to
+ * get more modularity in the style of MODULA2.
+ * BUGFIXES
+ * May 1997: Eric Delaunay <delaunay@lix.polytechnique.fr> reports a
+ * problem with huge fonts (greater than 1008 DPI). The code for
+ * handling PK characters in `extended format' was wrongly derived
+ * from dvips. Made some minor improvements regarding error handling.
+ * REDESIGN
+ * Piet Tutelaers
+ * rcpt@urc.tue.nl
+ *
+ * Modified for use with pdftex by Han The Thanh <thanh@fi.muni.cz>.
+ */
+
+#include "ptexlib.h"
+
+/*
+ * Now we have some routines to get stuff from the pk file. pkbyte returns
+ * the next byte from the pk file.
+ */
+
+
+/*
+static FILE *pkfile ;
+*/
+
+extern FILE *t3_file;
+#define pkfile t3_file
+
+static shalfword pkbyte(void)
+{
+ register shalfword i ;
+
+ if ((i=xgetc(pkfile))==EOF)
+ pdftex_fail("unexpected eof in pk file") ;
+ return(i) ;
+}
+
+static integer pkduo(void)
+{
+ register integer i ;
+
+ i = pkbyte() ;
+ if (i > 127)
+ i -= 256 ;
+ i = i * 256 + pkbyte() ;
+ return(i) ;
+}
+
+static integer pktrio(void)
+{
+ register integer i ;
+
+ i = pkbyte() ;
+ if (i > 127)
+ i -= 256 ;
+ i = i * 256 + pkbyte() ;
+ i = i * 256 + pkbyte() ;
+ return(i) ;
+}
+
+static integer pkquad(void)
+{
+ register integer i ;
+
+ i = pkbyte() ;
+ if (i > 127)
+ i -= 256 ;
+ i = i * 256 + pkbyte() ;
+ i = i * 256 + pkbyte() ;
+ i = i * 256 + pkbyte() ;
+ return(i) ;
+}
+
+/*
+ * The next part is devoted to unpacking the character data.
+ */
+
+/*
+ * We need procedures to get a nybble, bit, and packed word from the
+ * packed data structure.
+ */
+
+static halfword inputbyte, flagbyte ;
+static halfword bitweight ;
+static halfword dynf ;
+static halfword repeatcount ;
+
+static shalfword getnyb(void)
+{ halfword temp;
+ if ( bitweight == 0 )
+ { bitweight = 16 ;
+ inputbyte = pkbyte();
+ temp = inputbyte >> 4 ;
+ } else {
+ bitweight = 0 ;
+ temp = inputbyte & 15 ;
+ }
+ return(temp);
+}
+
+static boolean getbit(void)
+{
+ bitweight >>= 1 ;
+ if ( bitweight == 0 )
+ { inputbyte = pkbyte();
+ bitweight = 128 ;
+ }
+ return(inputbyte & bitweight) ;
+}
+
+static halfword (*realfunc)(void) ;
+long pk_remainder ;
+static halfword handlehuge(halfword i, halfword k);
+
+static halfword pkpackednum(void) {
+register halfword i, j ;
+ i = getnyb () ;
+ if ( i == 0 )
+ { do { j = getnyb () ;
+ i++ ;
+ } while ( ! ( j != 0 ) ) ;
+ if ( i > 3 ) {
+/*
+ * Damn, we got a huge count! We *fake* it by giving an artificially
+ * large repeat count.
+ */
+ return(handlehuge(i, j)) ;
+ } else {
+ while ( i > 0 )
+ { j = j * 16 + getnyb () ;
+ i-- ;
+ }
+ return ( j - 15 + ( 13 - dynf ) * 16 + dynf ) ;
+ }
+ }
+ else if ( i <= dynf ) return ( i ) ;
+ else if ( i < 14 ) return ( ( i - dynf - 1 ) * 16 + getnyb () + dynf + 1
+ ) ;
+ else
+ { if ( i == 14 ) repeatcount = pkpackednum () ;
+ else repeatcount = 1 ;
+#ifdef DEBUG
+ printf("[%d]", repeatcount);
+#endif
+ return ( (*realfunc)() ) ;
+ }
+ }
+
+static halfword rest(void)
+{
+ halfword i ;
+
+ if (pk_remainder < 0) {
+ pk_remainder = - pk_remainder ;
+ return ( 0 ) ;
+ } else if (pk_remainder > 0) {
+ if (pk_remainder > 4000) {
+ pk_remainder = 4000 - pk_remainder ;
+ return ( 4000 ) ;
+ } else {
+ i = pk_remainder ;
+ pk_remainder = 0 ;
+ realfunc = pkpackednum ;
+ return ( i ) ;
+ }
+ } else {
+ pdftex_fail("shouldn't happen") ;
+ return 0; /*NOTREACHED*/
+ }
+}
+
+static halfword handlehuge(halfword i, halfword k)
+{
+ register long j = k ;
+
+ while (i) {
+ j = (j << 4L) + getnyb() ;
+ i-- ;
+ }
+ pk_remainder = j - 15 + ( 13 - dynf ) * 16 + dynf ;
+ realfunc = rest ;
+ return ( rest() ) ;
+}
+
+/*
+ * And now we have our unpacking routine.
+ */
+
+static halfword gpower[17] = { 0, 1, 3, 7, 15, 31, 63, 127,
+ 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535 } ;
+
+static void unpack(chardesc *cd)
+{
+ register integer i, j ;
+ register halfword word, wordweight ;
+ halfword *raster;
+ shalfword rowsleft ;
+ boolean turnon ;
+ shalfword hbit ;
+ halfword count ;
+ shalfword wordwidth ;
+
+ wordwidth = (cd->cwidth + 15) / 16 ;
+ i = 2 * cd->cheight * (long)wordwidth ;
+ if (i <= 0)
+ i = 2 ;
+ if (i > cd->rastersize) {
+ xfree(cd->raster);
+ cd->rastersize = i;
+ cd->raster = xtalloc(cd->rastersize, halfword);
+ }
+ raster = cd->raster;
+ realfunc = pkpackednum ;
+ dynf = flagbyte / 16 ;
+ turnon = flagbyte & 8 ;
+ if ( dynf == 14 )
+ { bitweight = 0 ;
+ for ( i = 1 ; i <= cd->cheight ; i ++ )
+ { word = 0 ;
+ wordweight = 32768 ;
+ for ( j = 1 ; j <= cd->cwidth ; j ++ )
+ { if ( getbit () ) word += wordweight ;
+ wordweight >>= 1 ;
+ if ( wordweight == 0 )
+ { *raster++ = word ;
+ word = 0 ;
+ wordweight = 32768 ;
+ }
+ }
+ if ( wordweight != 32768 )
+ *raster++ = word ;
+ }
+ } else {
+ rowsleft = cd->cheight ;
+ hbit = cd->cwidth ;
+ repeatcount = 0 ;
+ wordweight = 16 ;
+ word = 0 ;
+ bitweight = 0 ;
+ while ( rowsleft > 0 )
+ { count = (*realfunc)() ;
+#ifdef DEBUG
+ if (turnon) printf("(%d) ",count);
+ else printf("%d ",count);
+#endif
+ while ( count != 0 )
+ { if ( ( count < wordweight ) && ( count < hbit ) )
+ { if ( turnon ) word += gpower [ wordweight ] - gpower
+ [ wordweight - count ] ;
+ hbit -= count ;
+ wordweight -= count ;
+ count = 0 ;
+ }
+ else if ( ( count >= hbit ) && ( hbit <= wordweight ) )
+ { if ( turnon )
+ word += gpower [ wordweight ] - gpower
+ [ wordweight - hbit ] ;
+ *raster++ = word ;
+ for ( i = 1 ; i <= repeatcount ; i ++ ) {
+ for ( j = 1 ; j <= wordwidth ; j ++ ) {
+ *raster = *(raster - wordwidth) ;
+ raster++ ;
+ }
+ }
+ rowsleft -= repeatcount + 1 ;
+ repeatcount = 0 ;
+ word = 0 ;
+ wordweight = 16 ;
+ count -= hbit ;
+ hbit = cd->cwidth ;
+ }
+ else
+ { if ( turnon ) word += gpower [ wordweight ] ;
+ *raster++ = word ;
+ word = 0 ;
+ count -= wordweight ;
+ hbit -= wordweight ;
+ wordweight = 16 ;
+ }
+ }
+ turnon = ! turnon ;
+ }
+ if ( ( rowsleft != 0 ) || ( (integer)hbit != cd->cwidth ) )
+ pdftex_fail("error while unpacking; more bits than required");
+ }
+}
+
+/*
+ * readchar(): the main routine
+ * Reads the character definition of character `c' into `cd' if available,
+ * return FALSE (0) otherwise.
+ */
+
+/*
+ * readchar(): the main routine
+ * check pk preamble if necessary,
+ * read the next character definition into `cd',
+ * return EOF if no character definition is available
+ */
+
+int readchar(boolean check_preamble, chardesc *cd)
+{
+ register shalfword i ;
+ register integer k ;
+ register integer length=0 ;
+
+/*
+ * Check the preamble of the pkfile
+ */
+ if (check_preamble) {
+ if (pkbyte()!=247)
+ pdftex_fail("bad pk file, expected pre") ;
+ if (pkbyte()!=89)
+ pdftex_fail("bad version of pk file") ;
+ for(i=pkbyte(); i>0; i--) /* creator of pkfile */
+ (void)pkbyte() ;
+ (void)pkquad(); /* design size */
+ k = pkquad() ; /* checksum */
+ k = pkquad() ; /* hppp */
+ k = pkquad() ; /* vppp */
+ }
+/*
+ * Now we skip to the desired character definition
+ */
+ while ((flagbyte=pkbyte())!=245) {
+ if (flagbyte < 240) {
+ switch (flagbyte & 7) {
+case 0: case 1: case 2: case 3:
+ length = (flagbyte & 7) * 256 + pkbyte() - 3;
+ cd->charcode = pkbyte() ;
+ (void) pktrio() ; /* TFMwidth */
+ cd->xescape = pkbyte() ; /* pixel width */
+ cd->cwidth = pkbyte() ;
+ cd->cheight = pkbyte() ;
+ cd->xoff = pkbyte() ;
+ cd->yoff = pkbyte() ;
+ if (cd->xoff > 127)
+ cd->xoff -= 256 ;
+ if (cd->yoff > 127)
+ cd->yoff -= 256 ;
+ break ;
+case 4: case 5: case 6:
+ length = (flagbyte & 3) * 65536L + pkbyte() * 256L ;
+ length = length + pkbyte() - 4L ;
+ cd->charcode = pkbyte() ;
+ (void) pktrio() ; /* TFMwidth */
+ cd->xescape = pkduo() ; /* pixelwidth */
+ cd->cwidth = pkduo() ;
+ cd->cheight = pkduo() ;
+ cd->xoff = pkduo() ;
+ cd->yoff = pkduo() ;
+ break ;
+case 7:
+ length = pkquad() - 9L;
+ cd->charcode = pkquad();
+ (void) pkquad() ; /* TFMwidth */
+ cd->xescape = pkquad(); /* pixelwidth */
+ k = pkquad() ;
+ cd->cwidth = pkquad();
+ cd->cheight = pkquad();
+ cd->xoff = pkquad();
+ cd->yoff = pkquad();
+ }
+ if (length <= 0)
+ pdftex_fail("packet length (%i) too small", (int)length) ;
+ unpack(cd);
+ return 1;
+ } else {
+ k = 0 ;
+ switch (flagbyte) {
+case 243:
+ k = pkbyte() ;
+ if (k > 127)
+ k -= 256 ;
+case 242:
+ k = k * 256 + pkbyte() ;
+case 241:
+ k = k * 256 + pkbyte() ;
+case 240:
+ k = k * 256 + pkbyte() ;
+ while (k-- > 0)
+ i = pkbyte() ;
+ break ;
+case 244:
+ k = pkquad() ;
+ break ;
+case 246:
+ break ;
+default:
+ pdftex_fail("unexpected command (%i)", (int)flagbyte) ;
+ }
+ }
+ }
+ return 0; /* character not found */
+}
diff --git a/Build/source/texk/web2c/pdftexdir/ptexlib.h b/Build/source/texk/web2c/pdftexdir/ptexlib.h
new file mode 100644
index 00000000000..90159001e39
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/ptexlib.h
@@ -0,0 +1,219 @@
+/*
+Copyright (c) 1996-2002 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX 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.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/ptexlib.h#26 $
+*/
+
+#ifndef PDFTEXLIB
+#define PDFTEXLIB
+
+/* WEB2C macros and prototypes */
+#if !defined(PDFTEXCOERCE) && !defined(PDFETEXCOERCE)
+#ifdef pdfTeX
+#undef pdfTeX /* to avoid warning about redefining pdfTeX in pdftexd.h */
+#endif /* pdfTeX */
+#define EXTERN extern
+#include "pdftexd.h"
+#endif
+
+/* pdftexlib macros */
+#include "ptexmac.h"
+
+/* pdftexlib type declarations */
+typedef struct {
+ const char *pdfname;
+ const char *t1name;
+ float value;
+ boolean valid;
+} key_entry;
+
+typedef struct {
+ boolean loaded; /* the encoding has been loaded? */
+ char *name; /* encoding file name */
+ integer objnum; /* object number */
+ char **glyph_names;
+} enc_entry;
+
+typedef struct {
+ char *tfm_name; /* TFM file name */
+ char *ps_name; /* PostScript name */
+ integer flags; /* font flags */
+ char *ff_name; /* font file name */
+ char *subset_tag; /* pseudoUniqueTag for subsetted font */
+ enc_entry *encoding; /* pointer to corresponding encoding */
+ internalfontnumber tfm_num; /* number of the TFM refering this entry */
+ unsigned short type; /* font type (T1/TTF/...) */
+ short slant; /* SlantFont */
+ short extend; /* ExtendFont */
+ integer ff_objnum; /* FontFile object number */
+ integer fn_objnum; /* FontName/BaseName object number */
+ integer fd_objnum; /* FontDescriptor object number */
+ char *charset; /* string containing used glyphs */
+ boolean all_glyphs; /* embed all glyphs? */
+ unsigned short links; /* link flags from tfm_tree and ps_tree */
+ short tfm_avail; /* flags whether a tfm is available */
+} fm_entry;
+
+typedef struct {
+ char *ff_name; /* base name of font file */
+ char *ff_path; /* full path to font file */
+} ff_entry;
+
+typedef short shalfword ;
+typedef struct {
+ integer charcode,
+ cwidth,
+ cheight,
+ xoff,
+ yoff,
+ xescape,
+ rastersize;
+ halfword *raster;
+} chardesc;
+
+/* pdftexlib variable declarations */
+extern boolean fontfile_found;
+extern boolean is_otf_font;
+extern boolean true_dimen;
+extern boolean write_ttf_glyph_names;
+extern char **t1_glyph_names, *t1_builtin_glyph_names[];
+extern char *cur_file_name;
+extern const char notdef[];
+extern fm_entry *fm_cur;
+extern integer t1_length1, t1_length2, t1_length3;
+extern integer ttf_length;
+extern internalfontnumber tex_font;
+extern key_entry font_keys[];
+extern strnumber last_tex_string;
+extern size_t last_ptr_index;
+extern char fontname_buf[];
+
+/* pdftexlib function prototypes */
+
+/* epdf.c */
+extern integer get_fontfile_num(int);
+extern integer get_fontname_num(int);
+extern void epdf_free(void);
+
+/* mapfile.c */
+extern char *mk_basename(char *);
+extern char *mk_exname(char *, int);
+extern fm_entry * lookup_fontmap(char *);
+extern boolean hasfmentry(internalfontnumber);
+extern internalfontnumber tfmoffm(fmentryptr);
+extern void checkextfm(strnumber, integer);
+extern void fm_free(void);
+extern void fm_read_info(void);
+extern ff_entry * check_ff_exist(fm_entry *);
+extern void pdfmapfile(integer);
+extern void pdfmapline(integer);
+
+/* papersiz.c */
+extern integer myatodim(char **);
+extern integer myatol(char **);
+
+/* pkin.c */
+extern int readchar(boolean, chardesc *);
+
+/* utils.c */
+extern boolean str_eq_cstr(strnumber, char *);
+extern char *makecstring(integer);
+extern int xfflush(FILE *);
+extern int xgetc(FILE *);
+extern int xputc(int, FILE *);
+extern scaled extxnoverd(scaled, scaled, scaled);
+extern size_t xfwrite(void *, size_t size, size_t nmemb, FILE *);
+extern strnumber getresnameprefix(void);
+extern strnumber maketexstring(const char *);
+extern integer fb_offset(void);
+extern void fb_flush(void);
+extern void fb_putchar(eightbits b);
+extern void fb_seek(integer);
+extern void libpdffinish(void);
+extern char *makecfilename(strnumber s);
+extern void make_subset_tag(fm_entry *, char **);
+extern void pdf_printf(const char *,...);
+extern void pdf_puts(const char *);
+extern void pdftex_fail(const char *,...);
+extern void pdftex_warn(const char *,...);
+extern void setjobid(int, int, int, int, int, int);
+extern void tex_printf(const char *, ...);
+extern void writestreamlength(integer, integer);
+extern char *convertStringToPDFString(char *in, int len);
+extern void printID(strnumber);
+
+/* vfpacket.c */
+extern eightbits packetbyte(void);
+extern integer newvfpacket(internalfontnumber);
+extern void poppacketstate(void);
+extern void pushpacketstate(void);
+extern void startpacket(internalfontnumber, integer);
+extern void storepacket(integer, integer, integer);
+extern void vf_free(void);
+
+/* writeenc.c */
+extern boolean indexed_enc(fm_entry *);
+extern enc_entry *add_enc(char *);
+extern void enc_free(void);
+extern void read_enc(enc_entry *);
+extern void write_enc(char **, enc_entry *, integer);
+
+/* writefont.c */
+extern void dopdffont(integer, internalfontnumber);
+
+/* writeimg.c */
+extern boolean checkimageb(integer);
+extern boolean checkimagec(integer);
+extern boolean checkimagei(integer);
+extern boolean ispdfimage(integer);
+extern integer epdforigx(integer);
+extern integer epdforigy(integer);
+extern integer imageheight(integer);
+extern integer imagepages(integer);
+extern integer imagewidth(integer);
+extern integer imagexres(integer);
+extern integer imageyres(integer);
+extern integer readimage(strnumber, integer, strnumber, integer, integer, integer, integer);
+extern void deleteimage(integer);
+extern void img_free(void) ;
+extern void updateimageprocset(integer);
+extern void writeimage(integer);
+
+/* writet1.c */
+extern boolean t1_subset(char *, char *, unsigned char *);
+extern void load_enc(char *, char **);
+extern void writet1(void);
+extern void t1_free(void);
+
+/* writet3.c */
+extern void writet3(int, internalfontnumber);
+extern scaled getpkcharwidth(internalfontnumber, scaled);
+
+/* writettf.c */
+extern void writettf(void);
+extern void writeotf(void);
+
+/* writezip.c */
+extern void writezip(boolean);
+
+/* avlstuff.c */
+extern void avlputobj(integer, integer);
+extern integer avlfindobj(integer, integer, integer);
+
+#endif /* PDFTEXLIB */
diff --git a/Build/source/texk/web2c/pdftexdir/ptexmac.h b/Build/source/texk/web2c/pdftexdir/ptexmac.h
new file mode 100644
index 00000000000..ed6ebe7d9be
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/ptexmac.h
@@ -0,0 +1,196 @@
+/*
+Copyright (c) 1996-2004 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX 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.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/ptexmac.h#18 $
+*/
+
+#ifndef PDFTEXMAC
+#define PDFTEXMAC
+
+/* Not all systems define it. */
+#ifndef M_PI
+#define M_PI 3.14159265358979323846 /* pi */
+#define M_PI_2 1.5707963267948966192E0 /*Hex 2^ 0 * 1.921FB54442D18 */
+#define M_PI_4 7.8539816339744830962E-1 /*Hex 2^-1 * 1.921FB54442D18 */
+#endif
+
+#ifdef WIN32
+// Why relying on gmalloc() ???
+#define gmalloc(n) xmalloc(n)
+#define gfree(p) free(p)
+#define inline __inline
+#define srandom(n) srand(n)
+#define random() rand()
+#endif
+
+/* Pascal WEB macros */
+#define maxinteger 0x7FFFFFFF
+#define maxdimen 0x3FFFFFFF
+
+#define objinfo(n) objtab[n].int0
+
+#define pdfroom(n) do { \
+ if (pdfbufsize < n) \
+ pdftex_fail("PDF output buffer overflowed"); \
+ if (pdfptr + n > pdfbufsize) \
+ pdfflush(); \
+} while (0)
+
+#define pdfout(c) do { \
+ if (pdfptr > pdfbufsize) \
+ pdfflush(); \
+ pdfbuf[pdfptr++] = c; \
+} while (0)
+
+#define pdfoffset() (pdfgone + pdfptr)
+#define pdfinitfont(f) {tmpf = f; pdfcreatefontobj();}
+
+#define MAX_CHAR_CODE 255
+
+#define PRINTF_BUF_SIZE 1024
+#define MAX_CSTRING_LEN 1024
+#define MAX_PSTRING_LEN 1024
+#define SMALL_BUF_SIZE 256
+#define SMALL_ARRAY_SIZE 256
+#define FONTNAME_BUF_SIZE 128 /* a PDF name can be maximum 127 chars long */
+
+#define check_buf(size, buf_size) \
+ if ((size) > (buf_size)) \
+ pdftex_fail("buffer overflow", (buf_size))
+
+#define append_char_to_buf(c, p, buf, buf_size) do { \
+ if (c == 9) \
+ c = 32; \
+ if (c == 13 || c == EOF) \
+ c = 10; \
+ if (c != ' ' || (p > buf && p[-1] != 32)) { \
+ check_buf(p - buf + 1, (buf_size)); \
+ *p++ = c; \
+ } \
+} while (0)
+
+#define append_eol(p, buf, buf_size) do { \
+ check_buf(p - buf + 2, (buf_size)); \
+ if (p - buf > 1 && p[-1] != 10) \
+ *p++ = 10; \
+ if (p - buf > 2 && p[-2] == 32) { \
+ p[-2] = 10; \
+ p--; \
+ } \
+ *p = 0; \
+} while (0)
+
+#define remove_eol(p, buf) do { \
+ p = strend(buf) - 1; \
+ if (*p == 10) \
+ *p = 0; \
+} while (0)
+
+#define skip(p, c) if (*p == c) p++
+
+#define alloc_array(T, n, s) do { \
+ if (T##_array == NULL) { \
+ T##_limit = (s); \
+ if ((n) > T##_limit) \
+ T##_limit = (n); \
+ T##_array = xtalloc(T##_limit, T##_entry); \
+ T##_ptr = T##_array; \
+ } \
+ else if (T##_ptr - T##_array + (n) > T##_limit) { \
+ last_ptr_index = T##_ptr - T##_array; \
+ T##_limit *= 2; \
+ if (T##_ptr - T##_array + (n) > T##_limit) \
+ T##_limit = T##_ptr - T##_array + (n); \
+ xretalloc(T##_array, T##_limit, T##_entry); \
+ T##_ptr = T##_array + last_ptr_index; \
+ } \
+} while (0)
+
+#define is_cfg_comment(c) \
+ (c == 10 || c == '*' || c == '#' || c == ';' || c == '%')
+
+#define define_array(T) \
+T##_entry *T##_ptr, *T##_array = NULL; \
+size_t T##_limit
+
+#define xfree(p) do { if (p != NULL) free(p); p = NULL; } while (0)
+#define strend(s) strchr(s, 0)
+#define xtalloc XTALLOC
+#define xretalloc XRETALLOC
+
+#define ASCENT_CODE 0
+#define CAPHEIGHT_CODE 1
+#define DESCENT_CODE 2
+#define FONTNAME_CODE 3
+#define ITALIC_ANGLE_CODE 4
+#define STEMV_CODE 5
+#define XHEIGHT_CODE 6
+#define FONTBBOX1_CODE 7
+#define FONTBBOX2_CODE 8
+#define FONTBBOX3_CODE 9
+#define FONTBBOX4_CODE 10
+#define MAX_KEY_CODE (FONTBBOX1_CODE + 1)
+#define FONT_KEYS_NUM (FONTBBOX4_CODE + 1)
+
+#define F_INCLUDED 0x01
+#define F_SUBSETTED 0x02
+#define F_TRUETYPE 0x04
+#define F_BASEFONT 0x08
+
+#define set_included(fm) ((fm)->type |= F_INCLUDED)
+#define set_subsetted(fm) ((fm)->type |= F_SUBSETTED)
+#define set_truetype(fm) ((fm)->type |= F_TRUETYPE)
+#define set_basefont(fm) ((fm)->type |= F_BASEFONT)
+
+#define unset_included(fm) ((fm)->type &= ~F_INCLUDED)
+#define unset_subsetted(fm) ((fm)->type &= ~F_SUBSETTED)
+#define unset_truetype(fm) ((fm)->type &= ~F_TRUETYPE)
+#define unset_basefont(fm) ((fm)->type &= ~F_BASEFONT)
+
+#define unset_fontfile(fm) xfree((fm)->ff_name)
+
+#define is_included(fm) ((fm)->type & F_INCLUDED)
+#define is_subsetted(fm) ((fm)->type & F_SUBSETTED)
+#define is_truetype(fm) ((fm)->type & F_TRUETYPE)
+#define is_basefont(fm) ((fm)->type & F_BASEFONT)
+#define no_font_desc(fm) (is_basefont(fm) && !is_included(fm))
+
+#define fm_slant(fm) (fm)->slant
+#define fm_extend(fm) (fm)->extend
+#define fm_fontfile(fm) (fm)->ff_name
+
+#define is_reencoded(fm) ((fm)->encoding != NULL)
+#define is_fontfile(fm) (fm_fontfile(fm) != NULL)
+#define is_t1fontfile(fm) (is_fontfile(fm) && !is_truetype(fm))
+
+#define LINK_TFM 0x01
+#define LINK_PS 0x02
+#define set_tfmlink(fm) ((fm)->links |= LINK_TFM)
+#define set_pslink(fm) ((fm)->links |= LINK_PS)
+#define unset_tfmlink(fm) ((fm)->links &= ~LINK_TFM)
+#define unset_pslink(fm) ((fm)->links &= ~LINK_PS)
+#define has_tfmlink(fm) ((fm)->links & LINK_TFM)
+#define has_pslink(fm) ((fm)->links & LINK_PS)
+
+
+#define set_cur_file_name(s) \
+ cur_file_name = s; \
+ packfilename(maketexstring(cur_file_name), getnullstr(), getnullstr())
+
+#endif /* PDFTEXMAC */
diff --git a/Build/source/texk/web2c/pdftexdir/randoms.ch b/Build/source/texk/web2c/pdftexdir/randoms.ch
new file mode 100644
index 00000000000..2268143406d
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/randoms.ch
@@ -0,0 +1,569 @@
+% randoms.ch
+% Copyright (c) 2005 Han Th\^e\llap{\raise 0.5ex\hbox{\'{}}} Th\`anh, <thanh@pdftex.org>
+%
+% This file is part of pdfTeX.
+%
+% pdfTeX 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.
+%
+% pdfTeX is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with pdfTeX; if not, write to the Free Software
+% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+%
+% $Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/pdftex.ch#163 $
+%
+% This is a WEB change file for pseudo-random numbers in pdftex 1.30 and above.
+%
+% There are four new primitives:
+%
+% \pdfuniformdeviate <count>
+% Generates a uniformly distributed random integer value
+% between 0 (inclusive) and <count> (exclusive).
+% This primitive expands to a list of tokens.
+%
+% \pdfnormaldeviate
+% Expands to a random integer value with a mean of 0 and a
+% unit of 65536.
+% This primitive expands to a list of tokens.
+%
+% \pdfrandomseed
+% You can use \the\pdfrandomseed to query the current seed value,
+% so you can e.g. the value to the log file.
+%
+% The initial value of the seed is derived from the system time,
+% and is not more than 1,000,999,999 (this ensures that the value
+% can be used with commands like \count).
+%
+% \pdfsetrandomseed <count>
+% This sets the random seed to a specific value, allowing you
+% to re-play sequences of semi-randoms at a later moment.
+%
+% Most of the actual code is taken from metapost, and originally
+% written by Knuth, for Metafont. Glue to make it work in TeX is
+% by me. If you find an error, it is bound to be in my code,
+% not Knuth's :-)
+%
+% Taco Hoekwater (taco@metatex.org), june 27, 2005. No restrictions.
+
+@x
+@* \[8] Packed data.
+@y
+@* \[7b] Random numbers.
+
+\font\tenlogo=logo10 % font used for the METAFONT logo
+\def\MP{{\tenlogo META}\-{\tenlogo POST}}
+
+This section is (almost) straight from MetaPost. I had to change
+the types (use |integer| instead of |fraction|), but that should
+not have any influence on the actual calculations (the original
+comments refer to quantities like |fraction_four| ($2^{30}$), and
+that is the same as the numeric representation of |maxdimen|).
+
+I've copied the low-level variables and routines that are needed, but
+only those (e.g. |m_log|), not the accompanying ones like |m_exp|. Most
+of the following low-level numeric routines are only needed within the
+calculation of |norm_rand|. I've been forced to rename |make_fraction|
+to |make_frac| because TeX already has a routine by that name with
+a wholly different function (it creates a |fraction_noad| for math
+typesetting) -- Taco
+
+And now let's complete our collection of numeric utility routines
+by considering random number generation.
+\MP\ generates pseudo-random numbers with the additive scheme recommended
+in Section 3.6 of {\sl The Art of Computer Programming}; however, the
+results are random fractions between 0 and |fraction_one-1|, inclusive.
+
+There's an auxiliary array |randoms| that contains 55 pseudo-random
+fractions. Using the recurrence $x_n=(x_{n-55}-x_{n-31})\bmod 2^{28}$,
+we generate batches of 55 new $x_n$'s at a time by calling |new_randoms|.
+The global variable |j_random| tells which element has most recently
+been consumed.
+
+@<Glob...@>=
+@!randoms:array[0..54] of integer; {the last 55 random values generated}
+@!j_random:0..54; {the number of unused |randoms|}
+@!random_seed:scaled; {the default random seed}
+
+@ A small bit of metafont is needed.
+
+@d fraction_half==@'1000000000 {$2^{27}$, represents 0.50000000}
+@d fraction_one==@'2000000000 {$2^{28}$, represents 1.00000000}
+@d fraction_four==@'10000000000 {$2^{30}$, represents 4.00000000}
+@d el_gordo == @'17777777777 {$2^{31}-1$, the largest value that \MP\ likes}
+@d halfp(#)==(#) div 2
+@d double(#) == #:=#+# {multiply a variable by two}
+
+@ The |make_frac| routine produces the |fraction| equivalent of
+|p/q|, given integers |p| and~|q|; it computes the integer
+$f=\lfloor2^{28}p/q+{1\over2}\rfloor$, when $p$ and $q$ are
+positive. If |p| and |q| are both of the same scaled type |t|,
+the ``type relation'' |make_frac(t,t)=fraction| is valid;
+and it's also possible to use the subroutine ``backwards,'' using
+the relation |make_frac(t,fraction)=t| between scaled types.
+
+If the result would have magnitude $2^{31}$ or more, |make_frac|
+sets |arith_error:=true|. Most of \MP's internal computations have
+been designed to avoid this sort of error.
+
+If this subroutine were programmed in assembly language on a typical
+machine, we could simply compute |(@t$2^{28}$@>*p)div q|, since a
+double-precision product can often be input to a fixed-point division
+instruction. But when we are restricted to \PASCAL\ arithmetic it
+is necessary either to resort to multiple-precision maneuvering
+or to use a simple but slow iteration. The multiple-precision technique
+would be about three times faster than the code adopted here, but it
+would be comparatively long and tricky, involving about sixteen
+additional multiplications and divisions.
+
+This operation is part of \MP's ``inner loop''; indeed, it will
+consume nearly 10\pct! of the running time (exclusive of input and output)
+if the code below is left unchanged. A machine-dependent recoding
+will therefore make \MP\ run faster. The present implementation
+is highly portable, but slow; it avoids multiplication and division
+except in the initial stage. System wizards should be careful to
+replace it with a routine that is guaranteed to produce identical
+results in all cases.
+@^system dependencies@>
+
+As noted below, a few more routines should also be replaced by machine-dependent
+code, for efficiency. But when a procedure is not part of the ``inner loop,''
+such changes aren't advisable; simplicity and robustness are
+preferable to trickery, unless the cost is too high.
+@^inner loop@>
+
+@p function make_frac(@!p,@!q:integer):integer;
+var @!f:integer; {the fraction bits, with a leading 1 bit}
+@!n:integer; {the integer part of $\vert p/q\vert$}
+@!negative:boolean; {should the result be negated?}
+@!be_careful:integer; {disables certain compiler optimizations}
+begin if p>=0 then negative:=false
+else begin negate(p); negative:=true;
+ end;
+if q<=0 then
+ begin debug if q=0 then confusion("/");@;@+gubed@;@/
+@:this can't happen /}{\quad \./@>
+ negate(q); negative:=not negative;
+ end;
+n:=p div q; p:=p mod q;
+if n>=8 then
+ begin arith_error:=true;
+ if negative then make_frac:=-el_gordo@+else make_frac:=el_gordo;
+ end
+else begin n:=(n-1)*fraction_one;
+ @<Compute $f=\lfloor 2^{28}(1+p/q)+{1\over2}\rfloor$@>;
+ if negative then make_frac:=-(f+n)@+else make_frac:=f+n;
+ end;
+end;
+
+@ The |repeat| loop here preserves the following invariant relations
+between |f|, |p|, and~|q|:
+(i)~|0<=p<q|; (ii)~$fq+p=2^k(q+p_0)$, where $k$ is an integer and
+$p_0$ is the original value of~$p$.
+
+Notice that the computation specifies
+|(p-q)+p| instead of |(p+p)-q|, because the latter could overflow.
+Let us hope that optimizing compilers do not miss this point; a
+special variable |be_careful| is used to emphasize the necessary
+order of computation. Optimizing compilers should keep |be_careful|
+in a register, not store it in memory.
+@^inner loop@>
+
+@<Compute $f=\lfloor 2^{28}(1+p/q)+{1\over2}\rfloor$@>=
+f:=1;
+repeat be_careful:=p-q; p:=be_careful+p;
+if p>=0 then f:=f+f+1
+else begin double(f); p:=p+q;
+ end;
+until f>=fraction_one;
+be_careful:=p-q;
+if be_careful+p>=0 then incr(f)
+
+@
+
+@p function take_frac(@!q:integer;@!f:integer):integer;
+var @!p:integer; {the fraction so far}
+@!negative:boolean; {should the result be negated?}
+@!n:integer; {additional multiple of $q$}
+@!be_careful:integer; {disables certain compiler optimizations}
+begin @<Reduce to the case that |f>=0| and |q>0|@>;
+if f<fraction_one then n:=0
+else begin n:=f div fraction_one; f:=f mod fraction_one;
+ if q<=el_gordo div n then n:=n*q
+ else begin arith_error:=true; n:=el_gordo;
+ end;
+ end;
+f:=f+fraction_one;
+@<Compute $p=\lfloor qf/2^{28}+{1\over2}\rfloor-q$@>;
+be_careful:=n-el_gordo;
+if be_careful+p>0 then
+ begin arith_error:=true; n:=el_gordo-p;
+ end;
+if negative then take_frac:=-(n+p)
+else take_frac:=n+p;
+end;
+
+@ @<Reduce to the case that |f>=0| and |q>0|@>=
+if f>=0 then negative:=false
+else begin negate(f); negative:=true;
+ end;
+if q<0 then
+ begin negate(q); negative:=not negative;
+ end;
+
+@ The invariant relations in this case are (i)~$\lfloor(qf+p)/2^k\rfloor
+=\lfloor qf_0/2^{28}+{1\over2}\rfloor$, where $k$ is an integer and
+$f_0$ is the original value of~$f$; (ii)~$2^k\L f<2^{k+1}$.
+@^inner loop@>
+
+@<Compute $p=\lfloor qf/2^{28}+{1\over2}\rfloor-q$@>=
+p:=fraction_half; {that's $2^{27}$; the invariants hold now with $k=28$}
+if q<fraction_four then
+ repeat if odd(f) then p:=halfp(p+q)@+else p:=halfp(p);
+ f:=halfp(f);
+ until f=1
+else repeat if odd(f) then p:=p+halfp(q-p)@+else p:=halfp(p);
+ f:=halfp(f);
+ until f=1
+
+@ The subroutines for logarithm and exponential involve two tables.
+The first is simple: |two_to_the[k]| equals $2^k$. The second involves
+a bit more calculation, which the author claims to have done correctly:
+|spec_log[k]| is $2^{27}$ times $\ln\bigl(1/(1-2^{-k})\bigr)=
+2^{-k}+{1\over2}2^{-2k}+{1\over3}2^{-3k}+\cdots\,$, rounded to the
+nearest integer.
+
+@<Glob...@>=
+@!two_to_the:array[0..30] of integer; {powers of two}
+@!spec_log:array[1..28] of integer; {special logarithms}
+
+
+@ @<Set init...@>=
+two_to_the[0]:=1;
+for k:=1 to 30 do two_to_the[k]:=2*two_to_the[k-1];
+spec_log[1]:=93032640;
+spec_log[2]:=38612034;
+spec_log[3]:=17922280;
+spec_log[4]:=8662214;
+spec_log[5]:=4261238;
+spec_log[6]:=2113709;
+spec_log[7]:=1052693;
+spec_log[8]:=525315;
+spec_log[9]:=262400;
+spec_log[10]:=131136;
+spec_log[11]:=65552;
+spec_log[12]:=32772;
+spec_log[13]:=16385;
+for k:=14 to 27 do spec_log[k]:=two_to_the[27-k];
+spec_log[28]:=1;
+
+@
+
+@p function m_log(@!x:integer):integer;
+var @!y,@!z:integer; {auxiliary registers}
+@!k:integer; {iteration counter}
+begin if x<=0 then @<Handle non-positive logarithm@>
+else begin y:=1302456956+4-100; {$14\times2^{27}\ln2\approx1302456956.421063$}
+ z:=27595+6553600; {and $2^{16}\times .421063\approx 27595$}
+ while x<fraction_four do
+ begin double(x); y:=y-93032639; z:=z-48782;
+ end; {$2^{27}\ln2\approx 93032639.74436163$
+ and $2^{16}\times.74436163\approx 48782$}
+ y:=y+(z div unity); k:=2;
+ while x>fraction_four+4 do
+ @<Increase |k| until |x| can be multiplied by a
+ factor of $2^{-k}$, and adjust $y$ accordingly@>;
+ m_log:=y div 8;
+ end;
+end;
+
+@ @<Increase |k| until |x| can...@>=
+begin z:=((x-1) div two_to_the[k])+1; {$z=\lceil x/2^k\rceil$}
+while x<fraction_four+z do
+ begin z:=halfp(z+1); k:=k+1;
+ end;
+y:=y+spec_log[k]; x:=x-z;
+end
+
+@ @<Handle non-positive logarithm@>=
+begin print_err("Logarithm of ");
+@.Logarithm...replaced by 0@>
+print_scaled(x); print(" has been replaced by 0");
+help2("Since I don't take logs of non-positive numbers,")@/
+ ("I'm zeroing this one. Proceed, with fingers crossed.");
+error; m_log:=0;
+end
+
+@ The following somewhat different subroutine tests rigorously if $ab$ is
+greater than, equal to, or less than~$cd$,
+given integers $(a,b,c,d)$. In most cases a quick decision is reached.
+The result is $+1$, 0, or~$-1$ in the three respective cases.
+
+@d return_sign(#)==begin ab_vs_cd:=#; return;
+ end
+
+@p function ab_vs_cd(@!a,b,c,d:integer):integer;
+label exit;
+var @!q,@!r:integer; {temporary registers}
+begin @<Reduce to the case that |a,c>=0|, |b,d>0|@>;
+loop@+ begin q := a div d; r := c div b;
+ if q<>r then
+ if q>r then return_sign(1)@+else return_sign(-1);
+ q := a mod d; r := c mod b;
+ if r=0 then
+ if q=0 then return_sign(0)@+else return_sign(1);
+ if q=0 then return_sign(-1);
+ a:=b; b:=q; c:=d; d:=r;
+ end; {now |a>d>0| and |c>b>0|}
+exit:end;
+
+@ @<Reduce to the case that |a...@>=
+if a<0 then
+ begin negate(a); negate(b);
+ end;
+if c<0 then
+ begin negate(c); negate(d);
+ end;
+if d<=0 then
+ begin if b>=0 then
+ if ((a=0)or(b=0))and((c=0)or(d=0)) then return_sign(0)
+ else return_sign(1);
+ if d=0 then
+ if a=0 then return_sign(0)@+else return_sign(-1);
+ q:=a; a:=c; c:=q; q:=-b; b:=-d; d:=q;
+ end
+else if b<=0 then
+ begin if b<0 then if a>0 then return_sign(-1);
+ if c=0 then return_sign(0) else return_sign(-1);
+ end
+
+@ To consume a random integer, the program below will say `|next_random|'
+and then it will fetch |randoms[j_random]|.
+
+@d next_random==if j_random=0 then new_randoms
+ else decr(j_random)
+
+@p procedure new_randoms;
+var @!k:0..54; {index into |randoms|}
+@!x:integer; {accumulator}
+begin for k:=0 to 23 do
+ begin x:=randoms[k]-randoms[k+31];
+ if x<0 then x:=x+fraction_one;
+ randoms[k]:=x;
+ end;
+for k:=24 to 54 do
+ begin x:=randoms[k]-randoms[k-24];
+ if x<0 then x:=x+fraction_one;
+ randoms[k]:=x;
+ end;
+j_random:=54;
+end;
+
+@ To initialize the |randoms| table, we call the following routine.
+
+@p procedure init_randoms(@!seed:integer);
+var @!j,@!jj,@!k:integer; {more or less random integers}
+@!i:0..54; {index into |randoms|}
+begin j:=abs(seed);
+while j>=fraction_one do j:=halfp(j);
+k:=1;
+for i:=0 to 54 do
+ begin jj:=k; k:=j-k; j:=jj;
+ if k<0 then k:=k+fraction_one;
+ randoms[(i*21)mod 55]:=j;
+ end;
+new_randoms; new_randoms; new_randoms; {``warm up'' the array}
+end;
+
+@ To produce a uniform random number in the range |0<=u<x| or |0>=u>x|
+or |0=u=x|, given a |scaled| value~|x|, we proceed as shown here.
+
+Note that the call of |take_frac| will produce the values 0 and~|x|
+with about half the probability that it will produce any other particular
+values between 0 and~|x|, because it rounds its answers.
+
+@p function unif_rand(@!x:integer):integer;
+var @!y:integer; {trial value}
+begin next_random; y:=take_frac(abs(x),randoms[j_random]);
+if y=abs(x) then unif_rand:=0
+else if x>0 then unif_rand:=y
+else unif_rand:=-y;
+end;
+
+@ Finally, a normal deviate with mean zero and unit standard deviation
+can readily be obtained with the ratio method (Algorithm 3.4.1R in
+{\sl The Art of Computer Programming\/}).
+
+@p function norm_rand:integer;
+var @!x,@!u,@!l:integer; {what the book would call $2^{16}X$, $2^{28}U$,
+ and $-2^{24}\ln U$}
+begin repeat
+ repeat next_random;
+ x:=take_frac(112429,randoms[j_random]-fraction_half);
+ {$2^{16}\sqrt{8/e}\approx 112428.82793$}
+ next_random; u:=randoms[j_random];
+ until abs(x)<u;
+x:=make_frac(x,u);
+l:=139548960-m_log(u); {$2^{24}\cdot12\ln2\approx139548959.6165$}
+until ab_vs_cd(1024,l,x,x)>=0;
+norm_rand:=x;
+end;
+
+@* \[8] Packed data.
+@z
+
+@x l.388
+@d pdftex_last_item_codes = pdftex_first_rint_code + 11 {end of \pdfTeX's command codes}
+@y
+@d random_seed_code = pdftex_first_rint_code + 12 {code for \.{\\pdfrandomseed}}
+@d pdftex_last_item_codes = pdftex_first_rint_code + 12 {end of \pdfTeX's command codes}
+@z
+
+@x l.417
+primitive("pdfelapsedtime",last_item,elapsed_time_code);
+@!@:elapsed_time_}{\.{\\pdfelapsedtime} primitive@>
+@y
+primitive("pdfelapsedtime",last_item,elapsed_time_code);
+@!@:elapsed_time_}{\.{\\pdfelapsedtime} primitive@>
+primitive("pdfrandomseed",last_item,random_seed_code);
+@!@:random_seed_}{\.{\\pdfrandomseed} primitive@>
+@z
+
+@x l.434
+ elapsed_time_code: print_esc("pdfelapsedtime");
+@y
+ elapsed_time_code: print_esc("pdfelapsedtime");
+ random_seed_code: print_esc("pdfrandomseed");
+@z
+
+@x l.461
+ elapsed_time_code: cur_val := get_microinterval;
+@y
+ elapsed_time_code: cur_val := get_microinterval;
+ random_seed_code: cur_val := random_seed;
+@z
+
+@x
+@d pdftex_convert_codes = pdftex_first_expand_code + 21 {end of \pdfTeX's command codes}
+@y
+@d uniform_deviate_code = pdftex_first_expand_code + 21 {end of \pdfTeX's command codes}
+@d normal_deviate_code = pdftex_first_expand_code + 22 {end of \pdfTeX's command codes}
+@d pdftex_convert_codes = pdftex_first_expand_code + 23 {end of \pdfTeX's command codes}
+@z
+
+@x
+primitive("jobname",convert,job_name_code);@/
+@y
+primitive("pdfuniformdeviate",convert,uniform_deviate_code);@/
+@!@:uniform_deviate_}{\.{\\pdfuniformdeviate} primitive@>
+primitive("pdfnormaldeviate",convert,normal_deviate_code);@/
+@!@:normal_deviate_}{\.{\\pdfnormaldeviate} primitive@>
+primitive("jobname",convert,job_name_code);@/
+@z
+
+@x
+ othercases print_esc("jobname")
+@y
+ uniform_deviate_code: print_esc("pdfuniformdeviate");
+ normal_deviate_code: print_esc("pdfnormaldeviate");
+ othercases print_esc("jobname")
+@z
+
+@x
+pdf_strcmp_code:
+ begin
+ save_scanner_status := scanner_status;
+ save_warning_index := warning_index;
+ save_def_ref := def_ref;
+ compare_strings;
+ def_ref := save_def_ref;
+ warning_index := save_warning_index;
+ scanner_status := save_scanner_status;
+ end;
+job_name_code: if job_name=0 then open_log_file;
+@y
+pdf_strcmp_code:
+ begin
+ save_scanner_status := scanner_status;
+ save_warning_index := warning_index;
+ save_def_ref := def_ref;
+ compare_strings;
+ def_ref := save_def_ref;
+ warning_index := save_warning_index;
+ scanner_status := save_scanner_status;
+ end;
+job_name_code: if job_name=0 then open_log_file;
+uniform_deviate_code: scan_int;
+normal_deviate_code: do_nothing;
+@z
+
+@x
+job_name_code: print(job_name);
+@y
+uniform_deviate_code: print_int(unif_rand(cur_val));
+normal_deviate_code: print_int(norm_rand);
+job_name_code: print(job_name);
+@z
+
+
+@x
+@<Compute the magic offset@>;
+@y
+random_seed :=(microseconds*1000)+(epochseconds mod 1000000);@/
+init_randoms(random_seed);@/
+@<Compute the magic offset@>;
+@z
+
+@x l. 4562
+@d pdftex_last_extension_code == pdftex_first_extension_code + 25
+@y
+@d set_random_seed_code == pdftex_first_extension_code + 26
+@d pdftex_last_extension_code == pdftex_first_extension_code + 26
+@z
+
+@x l.4625
+primitive("pdfresettimer",extension,reset_timer_code);@/
+@!@:reset_timer_}{\.{\\pdfresettimer} primitive@>
+@y
+primitive("pdfresettimer",extension,reset_timer_code);@/
+@!@:reset_timer_}{\.{\\pdfresettimer} primitive@>
+primitive("pdfsetrandomseed",extension,set_random_seed_code);@/
+@!@:set_random_seed_code}{\.{\\pdfsetrandomseed} primitive@>
+@z
+
+@x
+ reset_timer_code: print_esc("pdfresettimer");
+@y
+ reset_timer_code: print_esc("pdfresettimer");
+ set_random_seed_code: print_esc("pdfsetrandomseed");
+@z
+
+@x
+reset_timer_code: @<Implement \.{\\pdfresettimer}@>;
+@y
+reset_timer_code: @<Implement \.{\\pdfresettimer}@>;
+set_random_seed_code: @<Implement \.{\\pdfsetrandomseed}@>;
+@z
+
+@x
+@ @<Implement \.{\\pdfresettimer}@>=
+@y
+@ Negative random seed values are silently converted to positive ones
+
+@<Implement \.{\\pdfsetrandomseed}@>=
+begin
+ scan_int;
+ if cur_val<0 then negate(cur_val);
+ random_seed := cur_val;
+ init_randoms(random_seed);
+end
+
+@ @<Implement \.{\\pdfresettimer}@>=
+@z
+
diff --git a/Build/source/texk/web2c/pdftexdir/tex.ch0 b/Build/source/texk/web2c/pdftexdir/tex.ch0
new file mode 100644
index 00000000000..f3c0b93fa80
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/tex.ch0
@@ -0,0 +1,42 @@
+%
+% Copyright (c) 1996-2002 Han The Thanh, <thanh@pdftex.org>
+%
+% This file is part of pdfTeX.
+%
+% pdfTeX 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.
+%
+% pdfTeX is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with pdfTeX; if not, write to the Free Software
+% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+%
+% $Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/tex.ch0#10 $
+%
+% Change file to assist in creating the web2c-specific change file.
+% This one comes first, resolves inconsistencies between the generated
+% pdftex.web and tex.ch
+
+@x [1.2] l.188
+@d TeX_banner=='This is TeX, Version 3.141592' {printed when \TeX\ starts}
+@#
+@d banner==pdfTeX_banner
+@y
+@d banner=='This is TeX, Version 3.141592' {printed when \TeX\ starts}
+@z
+
+@x [17.236] l.4960 - first web2c, then pdfTeX additional integer parameters
+@d tex_int_pars=55 {total number of \TeX's integer parameters}
+@#
+@d pdftex_first_integer_code = tex_int_pars {base for \pdfTeX's integer parameters}
+@y
+@d int_pars=55 {total number of integer parameters}
+@#
+@d pdftex_first_integer_code = tex_int_pars {base for \pdfTeX's integer parameters}
+@z
diff --git a/Build/source/texk/web2c/pdftexdir/tex.ch1 b/Build/source/texk/web2c/pdftexdir/tex.ch1
new file mode 100644
index 00000000000..172e2a6668b
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/tex.ch1
@@ -0,0 +1,39 @@
+%
+% Copyright (c) 1996-2002 Han The Thanh, <thanh@pdftex.org>
+%
+% This file is part of pdfTeX.
+%
+% pdfTeX 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.
+%
+% pdfTeX is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with pdfTeX; if not, write to the Free Software
+% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+%
+% $Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/tex.ch1#11 $
+%
+% Change file to assist in creating the web2c-specific change file.
+% This one resolves inconsistencies between tex.ch and tex.pch.
+
+@x [1] m.2 l.188 - banner
+@d banner==TeX_banner
+@d banner_k==TeX_banner_k
+@y
+@d banner==pdfTeX_banner
+@d banner_k==pdfTeX_banner_k
+@z
+
+@x [17.236] l.4960 - first web2c, then pdfTeX additional integer parameters
+@d int_pars=web2c_int_pars {total number of integer parameters}
+@#
+@d pdftex_first_integer_code = tex_int_pars {base for \pdfTeX's integer parameters}
+@y
+@d pdftex_first_integer_code = web2c_int_pars {base for \pdfTeX's integer parameters}
+@z
diff --git a/Build/source/texk/web2c/pdftexdir/tex.pch b/Build/source/texk/web2c/pdftexdir/tex.pch
new file mode 100644
index 00000000000..ca78e387dd5
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/tex.pch
@@ -0,0 +1,355 @@
+% Copyright (c) 1996-2005 Han Th\^e\llap{\raise 0.5ex\hbox{\'{}}} Th\`anh, <thanh@pdftex.org>
+%
+% Note: This file, pdftexdir/tex.pch, contains the web2c changes for the
+% pdfTeX specific part of pdftex.web (defined in pdftexdir/pdftex.ch)
+% and is used as follows to construct the web2c change file for pdfTeX:
+%
+% pdftexdir/tex.ch0 )
+% + )
+% tex.ch )
+% + ) => tie -c ... => pdftex.ch
+% pdftexdir/tex.ch1 )
+% + )
+% pdftexdir/tex.pch )
+%
+% In addition, this file is used to construct the web2c change file
+% for pdfeTeX:
+%
+% pdfetexdir/tex.ch0 )
+% + )
+% tex.ch )
+% + )
+% etexdir/tex.ch1 )
+% + ) => tie -c ... => pdfetex.ch
+% etexdir/tex.ech )
+% + )
+% pdfetexdir/tex.ch1 )
+% + )
+% pdftexdir/tex.pch )
+%
+% where the four (small) files pdf{,e}texdir/tex.ch[01] take care
+% of interferences between web2c, e-Tex, pdfTeX changes.
+% Consequently, changes in all these files have to be coordinated.
+
+% This file is part of pdfTeX.
+%
+% pdfTeX 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.
+%
+% pdfTeX is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with pdfTeX; if not, write to the Free Software
+% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+%
+% $Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/tex.pch#26 $
+% Change file containing web2c-specific or system-dependent changes to
+% pdftex
+
+@x [1] m.2 l.188 - Web2C: extensions imply we're not pdfTeX
+@d pdfTeX_banner=='This is pdfTeX, Version 3.141592',pdftex_version_string
+@y
+@d pdfTeX_banner_k=='This is pdfTeXk, Version 3.141592',pdftex_version_string
+@d pdfTeX_banner=='This is pdfTeX, Version 3.141592',pdftex_version_string
+@z
+
+@x (MLTeX)
+ begin i := char_tag(char_info(f)(c));
+@y
+ begin i := char_tag(orig_char_info(f)(c));
+@z
+
+@x (MLTeX)
+@d is_valid_char(#)==((font_bc[f] <= #) and (# <= font_ec[f]) and
+ char_exists(char_info(f)(#)))
+@y
+@d is_valid_char(#)==((font_bc[f] <= #) and (# <= font_ec[f]) and
+ char_exists(orig_char_info(f)(#)))
+@z
+
+@x (MLTeX)
+function get_charwidth(f: internal_font_number; c: eight_bits): scaled;
+begin
+ if is_valid_char(c) then
+ get_charwidth := char_width(f)(char_info(f)(c))
+ else
+ get_charwidth := 0;
+end;
+
+function get_charheight(f: internal_font_number; c: eight_bits): scaled;
+begin
+ if is_valid_char(c) then
+ get_charheight := char_height(f)(height_depth(char_info(f)(c)))
+ else
+ get_charheight := 0;
+end;
+
+function get_chardepth(f: internal_font_number; c: eight_bits): scaled;
+begin
+ if is_valid_char(c) then
+ get_chardepth := char_depth(f)(height_depth(char_info(f)(c)))
+ else
+ get_chardepth := 0;
+end;
+@y
+function get_charwidth(f: internal_font_number; c: eight_bits): scaled;
+begin
+ if is_valid_char(c) then
+ get_charwidth := char_width(f)(orig_char_info(f)(c))
+ else
+ get_charwidth := 0;
+end;
+
+function get_charheight(f: internal_font_number; c: eight_bits): scaled;
+begin
+ if is_valid_char(c) then
+ get_charheight := char_height(f)(height_depth(orig_char_info(f)(c)))
+ else
+ get_charheight := 0;
+end;
+
+function get_chardepth(f: internal_font_number; c: eight_bits): scaled;
+begin
+ if is_valid_char(c) then
+ get_chardepth := char_depth(f)(height_depth(orig_char_info(f)(c)))
+ else
+ get_chardepth := 0;
+end;
+@z
+
+@x (MLTeX)
+label reswitch, move_past, fin_rule, next_p;
+@y
+label reswitch, move_past, fin_rule, next_p, found, continue;
+@z
+
+@x (MLTeX)
+ if is_valid_char(c) then
+ output_one_char(c)
+ else
+ char_warning(f, c);
+ cur_h:=cur_h+char_width(f)(char_info(f)(c));
+@y
+ if is_valid_char(c) then begin
+ output_one_char(c);
+ cur_h:=cur_h+char_width(f)(char_info(f)(c));
+ goto continue;
+ end;
+ if mltex_enabled_p then
+ @<(\pdfTeX) Output a substitution, |goto continue| if not possible@>;
+continue:
+@z
+
+@x
+@ The |pdf_vlist_out| routine is similar to |pdf_hlist_out|, but a bit simpler.
+@y
+@ @<(\pdfTeX) Output a substitution, |goto continue| if not possible@>=
+ begin
+ @<Get substitution information, check it, goto |found|
+ if all is ok, otherwise goto |continue|@>;
+found: @<Print character substition tracing log@>;
+ @<(\pdfTeX) Rebuild character using substitution information@>;
+ end
+
+@ @<(\pdfTeX) Rebuild character using substitution information@>=
+ base_x_height:=x_height(f);
+ base_slant:=slant(f)/float_constant(65536);
+@^real division@>
+ accent_slant:=base_slant; {slant of accent character font}
+ base_width:=char_width(f)(ib_c);
+ base_height:=char_height(f)(height_depth(ib_c));
+ accent_width:=char_width(f)(ia_c);
+ accent_height:=char_height(f)(height_depth(ia_c));
+ @/{compute necessary horizontal shift (don't forget slant)}@/
+ delta:=round((base_width-accent_width)/float_constant(2)+
+ base_height*base_slant-base_x_height*accent_slant);
+@^real multiplication@>
+@^real addition@>
+ @/{1. For centering/horizontal shifting insert a kern node.}@/
+ cur_h:=cur_h+delta;
+ @/{2. Then insert the accent character possibly shifted up or down.}@/
+ if ((base_height<>base_x_height) and (accent_height>0)) then
+ begin {the accent must be shifted up or down}
+ cur_v:=base_line+(base_x_height-base_height);
+ output_one_char(accent_c);
+ cur_v:=base_line;
+ end
+ else begin
+ output_one_char(accent_c);
+ end;
+ cur_h:=cur_h+accent_width;
+ @/{3. For centering/horizontal shifting insert another kern node.}@/
+ cur_h:=cur_h+(-accent_width-delta);
+ @/{4. Output the base character.}@/
+ output_one_char(base_c);
+ cur_h:=cur_h+base_width;
+
+@ The |pdf_vlist_out| routine is similar to |pdf_hlist_out|, but a bit simpler.
+@z
+
+@x [49.1259]
+ begin if s>0 then
+ begin if s=font_size[f] then goto common_ending;
+ end
+ else if font_size[f]=xn_over_d(font_dsize[f],-s,1000) then
+ goto common_ending;
+ end
+@y
+ begin
+ if pdf_font_step[f] = 0 then begin
+ if s>0 then
+ begin if s=font_size[f] then goto common_ending;
+ end
+ else if font_size[f]=xn_over_d(font_dsize[f],-s,1000) then
+ goto common_ending;
+ end
+ end
+@z
+
+@x (WEB2C!)
+param_base:=xmalloc_array(integer, font_max);
+
+undump_things(font_check[null_font], font_ptr+1-null_font);
+@y
+param_base:=xmalloc_array(integer, font_max);
+
+pdf_char_used:=xmalloc_array(char_used_array, font_max);
+pdf_char_map:=xmalloc_array(char_map_array, font_max);
+pdf_font_size:=xmalloc_array(scaled, font_max);
+pdf_font_num:=xmalloc_array(integer, font_max);
+pdf_font_map:=xmalloc_array(fm_entry_ptr, font_max);
+pdf_font_type:=xmalloc_array(eight_bits, font_max);
+pdf_font_attr:=xmalloc_array(str_number, font_max);
+pdf_font_blink:=xmalloc_array(internal_font_number, font_max);
+pdf_font_elink:=xmalloc_array(internal_font_number, font_max);
+pdf_font_stretch:=xmalloc_array(integer, font_max);
+pdf_font_shrink:=xmalloc_array(integer, font_max);
+pdf_font_step:=xmalloc_array(integer, font_max);
+pdf_font_expand_ratio:=xmalloc_array(integer, font_max);
+pdf_font_auto_expand:=xmalloc_array(boolean, font_max);
+pdf_font_lp_base:=xmalloc_array(integer, font_max);
+pdf_font_rp_base:=xmalloc_array(integer, font_max);
+pdf_font_ef_base:=xmalloc_array(integer, font_max);
+vf_packet_base:=xmalloc_array(integer, font_max);
+vf_default_font:=xmalloc_array(internal_font_number, font_max);
+vf_local_font_num:=xmalloc_array(internal_font_number, font_max);
+vf_e_fnts:=xmalloc_array(integer, font_max);
+vf_i_fnts:=xmalloc_array(internal_font_number, font_max);
+
+for font_k := font_base to font_max do begin
+ for k := 0 to 31 do begin
+ pdf_char_used[font_k, k] := 0;
+ pdf_char_map[font_k, k] := k;
+ end;
+ pdf_char_map[font_k, 32] := 32;
+ pdf_font_size[font_k] := 0;
+ pdf_font_num[font_k] := 0;
+ pdf_font_map[font_k] := 0;
+ pdf_font_type[font_k] := new_font_type;
+ pdf_font_attr[font_k] := "";
+ pdf_font_blink[font_k] := null_font;
+ pdf_font_elink[font_k] := null_font;
+ pdf_font_stretch[font_k] := null_font;
+ pdf_font_shrink[font_k] := null_font;
+ pdf_font_step[font_k] := 0;
+ pdf_font_expand_ratio[font_k] := 0;
+ pdf_font_auto_expand[font_k] := false;
+ pdf_font_lp_base[font_k] := 0;
+ pdf_font_rp_base[font_k] := 0;
+ pdf_font_ef_base[font_k] := 0;
+end;
+
+make_pdftex_banner;
+undump_things(font_check[null_font], font_ptr+1-null_font);
+@z
+
+@x [51.1]
+ setup_bound_var (0)('hash_extra')(hash_extra);
+
+@y
+ setup_bound_var (0)('hash_extra')(hash_extra);
+ setup_bound_var (65536)('obj_tab_size')(obj_tab_size);
+ setup_bound_var (20000)('dest_names_size')(dest_names_size);
+@z
+
+@x [51.2]
+ const_chk (hash_extra);
+ if error_line > ssup_error_line then error_line := ssup_error_line;
+@y
+ const_chk (hash_extra);
+ const_chk (obj_tab_size);
+ const_chk (pdf_mem_size);
+ const_chk (dest_names_size);
+ if error_line > ssup_error_line then error_line := ssup_error_line;
+@z
+
+@x [51.3]
+ hyph_link :=xmalloc_array (hyph_pointer, hyph_size);
+@y
+ hyph_link :=xmalloc_array (hyph_pointer, hyph_size);
+ obj_tab:=xmalloc_array (obj_entry, obj_tab_size);
+ pdf_mem:=xmalloc_array (integer, inf_pdf_mem_size); {will grow dynamically}
+ dest_names:=xmalloc_array (dest_name_entry, dest_names_size);
+@z
+
+@x (WEB2C!)
+ param_base:=xmalloc_array(integer, font_max);
+
+ font_ptr:=null_font; fmem_ptr:=7;
+@y
+param_base:=xmalloc_array(integer, font_max);
+
+pdf_char_used:=xmalloc_array(char_used_array,font_max);
+pdf_char_map:=xmalloc_array(char_map_array,font_max);
+pdf_font_size:=xmalloc_array(scaled,font_max);
+pdf_font_num:=xmalloc_array(integer,font_max);
+pdf_font_map:=xmalloc_array(fm_entry_ptr,font_max);
+pdf_font_type:=xmalloc_array(eight_bits,font_max);
+pdf_font_attr:=xmalloc_array(str_number,font_max);
+pdf_font_blink:=xmalloc_array(internal_font_number,font_max);
+pdf_font_elink:=xmalloc_array(internal_font_number,font_max);
+pdf_font_stretch:=xmalloc_array(integer,font_max);
+pdf_font_shrink:=xmalloc_array(integer,font_max);
+pdf_font_step:=xmalloc_array(integer,font_max);
+pdf_font_expand_ratio:=xmalloc_array(integer,font_max);
+pdf_font_auto_expand:=xmalloc_array(boolean,font_max);
+pdf_font_lp_base:=xmalloc_array(integer,font_max);
+pdf_font_rp_base:=xmalloc_array(integer,font_max);
+pdf_font_ef_base:=xmalloc_array(integer,font_max);
+vf_packet_base:=xmalloc_array(integer,font_max);
+vf_default_font:=xmalloc_array(internal_font_number,font_max);
+vf_local_font_num:=xmalloc_array(internal_font_number,font_max);
+vf_e_fnts:=xmalloc_array(integer,font_max);
+vf_i_fnts:=xmalloc_array(internal_font_number,font_max);
+
+for font_k := font_base to font_max do begin
+ for k := 0 to 31 do begin
+ pdf_char_used[font_k, k] := 0;
+ pdf_char_map[font_k, k] := k;
+ end;
+ pdf_char_map[font_k, 32] := 32;
+ pdf_font_size[font_k] := 0;
+ pdf_font_num[font_k] := 0;
+ pdf_font_map[font_k] := 0;
+ pdf_font_type[font_k] := new_font_type;
+ pdf_font_attr[font_k] := "";
+ pdf_font_blink[font_k] := null_font;
+ pdf_font_elink[font_k] := null_font;
+ pdf_font_stretch[font_k] := null_font;
+ pdf_font_shrink[font_k] := null_font;
+ pdf_font_step[font_k] := 0;
+ pdf_font_expand_ratio[font_k] := 0;
+ pdf_font_auto_expand[font_k] := false;
+ pdf_font_lp_base[font_k] := 0;
+ pdf_font_rp_base[font_k] := 0;
+ pdf_font_ef_base[font_k] := 0;
+end;
+
+font_ptr:=null_font; fmem_ptr:=7;
+make_pdftex_banner;
+@z
diff --git a/Build/source/texk/web2c/pdftexdir/ttf2afm.c b/Build/source/texk/web2c/pdftexdir/ttf2afm.c
new file mode 100644
index 00000000000..d3aa7051339
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/ttf2afm.c
@@ -0,0 +1,998 @@
+/*
+Copyright (c) 1996-2005 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX 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.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/ttf2afm.c#21 $
+*/
+
+/*
+#include <kpathsea/c-auto.h>
+#include <kpathsea/c-fopen.h>
+#include <kpathsea/c-limits.h>
+#include <kpathsea/c-memstr.h>
+#include <kpathsea/c-proto.h>
+#include <kpathsea/c-std.h>
+#include <kpathsea/c-unistd.h>
+#include <kpathsea/c-vararg.h>
+#include <kpathsea/getopt.h>
+*/
+#include <kpathsea/kpathsea.h>
+#include <time.h>
+#include <libgen.h>
+#include <pdftexdir/ptexmac.h>
+#include <pdftexdir/writettf.h>
+
+static const char perforce_id[] =
+ "$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/ttf2afm.c#21 $";
+
+/* constants used for print_glyph */
+#define AS_NAME 0
+#define AS_INDEX 1
+#define AS_UNICODE 2
+
+#define VERSION "1.0"
+
+#define enc_getchar() xgetc(encfile)
+#define enc_eof() feof(encfile)
+#define pdftex_fail ttf_fail
+
+#define print_str(S) if (S != NULL) fprintf(outfile, #S " %s\n", S)
+#define print_dimen(N) if (N != 0) fprintf(outfile, #N " %i\n", (int)get_ttf_funit(N))
+
+#define get_ttf_funit(n) \
+ (n < 0 ? -((-n/upem)*1000 + ((-n%upem)*1000)/upem) :\
+ ((n/upem)*1000 + ((n%upem)*1000)/upem))
+
+typedef struct _unicode_entry {
+ TTF_USHORT code;
+ struct _unicode_entry *next;
+} unicode_entry;
+
+typedef struct {
+ TTF_ULONG wx;
+ const char *name;
+ TTF_USHORT index;
+ TTF_LONG bbox[4];
+ TTF_LONG offset;
+ char found;
+ unicode_entry *unicode_list;
+} mtx_entry;
+
+typedef struct _kern_entry {
+ TTF_FWORD value;
+ TTF_USHORT adjacent;
+ struct _kern_entry *next;
+} kern_entry;
+
+
+char *FontName = NULL;
+char *FullName = NULL;
+char *FamilyName = NULL;
+char *Notice = NULL;
+char *Version = NULL;
+char *Weight = NULL;
+TTF_LONG ItalicAngle = 0;
+TTF_LONG IsFixedPitch = 0;
+TTF_LONG FontBBox1 = 0;
+TTF_LONG FontBBox2 = 0;
+TTF_LONG FontBBox3 = 0;
+TTF_LONG FontBBox4 = 0;
+TTF_LONG UnderlinePosition = 0;
+TTF_LONG UnderlineThickness = 0;
+TTF_LONG CapHeight = 0;
+TTF_LONG XHeight = 0;
+TTF_LONG Ascender = 0;
+TTF_LONG Descender = 0;
+
+char *cur_file_name = NULL;
+char *bname = NULL;
+FILE *fontfile, *encfile, *outfile = NULL;
+char enc_line[ENC_BUF_SIZE];
+int print_glyph = AS_NAME; /* print glyph as names by default*/
+int print_cmap = 0;
+int use_ext_enc = 0; /* use external encoding? */
+int select_unicode = 1; /* use the first unicode mapping by default */
+int printing_enc = 0; /* set to 1 while printing encodings */
+
+
+TTF_USHORT upem;
+TTF_USHORT ntabs;
+int nhmtx;
+int post_format;
+int loca_format;
+int nglyphs;
+int nkernpairs = 0;
+int names_count = 0;
+char *ps_glyphs_buf = NULL;
+dirtab_entry *dir_tab;
+mtx_entry *mtx_tab;
+kern_entry *kern_tab;
+char *enc_names[MAX_CHAR_CODE + 1];
+
+cmap_entry *cmap_tab;
+TTF_USHORT ncmapsubtabs;
+long cmap_offset;
+
+TTF_USHORT unicode_map[0xFFFF];
+
+#include "macnames.c"
+
+void ttf_fail(char *fmt,...)
+{
+ va_list args;
+ va_start(args, fmt);
+ fprintf(stderr, "\nError: ttf2afm");
+ if (cur_file_name)
+ fprintf(stderr, " (file %s)", cur_file_name);
+ fprintf(stderr, ": ");
+ vfprintf(stderr, fmt, args);
+ fprintf(stderr, "\n");
+ va_end(args);
+ exit(-1);
+}
+
+void ttf_warn(char *fmt,...)
+{
+ va_list args;
+ va_start(args, fmt);
+ fprintf(stderr, "\nWarning: ttf2afm");
+ if (cur_file_name)
+ fprintf(stderr, " (file %s)", cur_file_name);
+ fprintf(stderr, ": ");
+ vfprintf(stderr, fmt, args);
+ fprintf(stderr, "\n");
+ va_end(args);
+}
+
+int xgetc(FILE *stream)
+{
+ int c = getc(stream);
+ if (c < 0 && c != EOF)
+ ttf_fail("getc() failed");
+ return c;
+}
+
+long ttf_getnum(int s)
+{
+ long i = 0;
+ int c;
+ while (s > 0) {
+ if ((c = xgetc(fontfile)) < 0)
+ ttf_fail("unexpected EOF");
+ i = (i << 8) + c;
+ s--;
+ }
+ return i;
+}
+
+dirtab_entry *name_lookup(char *s)
+{
+ dirtab_entry *p;
+ for (p = dir_tab; p - dir_tab < ntabs; p++)
+ if (strncmp(p->tag, s, 4) == 0)
+ break;
+ if (p - dir_tab == ntabs)
+ p = NULL;
+ return p;
+}
+
+void ttf_seek_tab(char *name, TTF_LONG offset)
+{
+ dirtab_entry *p = name_lookup(name);
+ if (p == NULL)
+ ttf_fail("can't find table `%s'", name);
+ if (fseek(fontfile, p->offset + offset, SEEK_SET) < 0)
+ ttf_fail("fseek() failed while reading `%s' table", name);
+}
+
+void ttf_seek_off(char *name, TTF_LONG offset)
+{
+ if (fseek(fontfile, offset, SEEK_SET) < 0)
+ ttf_fail("fseek() failed while reading `%s' table", name);
+}
+
+void store_kern_value(TTF_USHORT i, TTF_USHORT j, TTF_FWORD v)
+{
+ kern_entry *pk;
+ for (pk = kern_tab + i; pk->next != NULL; pk = pk->next);
+ pk->next = xtalloc(1, kern_entry);
+ pk = pk->next;
+ pk->next = NULL;
+ pk->adjacent = j;
+ pk->value = v;
+}
+
+TTF_FWORD get_kern_value(TTF_USHORT i, TTF_USHORT j)
+{
+ kern_entry *pk;
+ for (pk = kern_tab + i; pk->next != NULL; pk = pk->next)
+ if (pk->adjacent == j)
+ return pk->value;
+ return 0;
+}
+
+void free_tabs()
+{
+ int i;
+ kern_entry *p, *q, *r;
+ unicode_entry *u, *v;
+ mtx_entry *pm;
+ xfree(ps_glyphs_buf);
+ xfree(dir_tab);
+ xfree(cmap_tab);
+ for (pm = mtx_tab; pm - mtx_tab < nglyphs; pm++)
+ if (pm->unicode_list != NULL) {
+ for (u = pm->unicode_list; u != NULL; u = v) {
+ v = u->next;
+ xfree(u);
+ }
+ }
+ xfree(mtx_tab);
+ for (i = 0; i <= MAX_CHAR_CODE; i++)
+ if (enc_names[i] != notdef)
+ free(enc_names[i]);
+ if (kern_tab == NULL)
+ return;
+ for (p = kern_tab; p - kern_tab < nglyphs; p++)
+ if (p->next != NULL) {
+ for (q = p->next; q != NULL; q = r) {
+ r = q->next;
+ xfree(q);
+ }
+ }
+ xfree(kern_tab);
+}
+
+void enc_getline()
+{
+ char *p;
+ int c;
+restart:
+ if (enc_eof())
+ ttf_fail("unexpected end of file");
+ p = enc_line;
+ do {
+ c = enc_getchar();
+ append_char_to_buf(c, p, enc_line, ENC_BUF_SIZE);
+ } while (c != 10);
+ append_eol(p, enc_line, ENC_BUF_SIZE);
+ if (p - enc_line <= 2 || *enc_line == '%')
+ goto restart;
+}
+
+void read_encoding(char *encname)
+{
+ char buf[ENC_BUF_SIZE], *q, *r;
+ int i;
+ cur_file_name = encname;
+ if ((encfile = kpse_open_file(encname, kpse_enc_format)) == NULL)
+ ttf_fail("can't open encoding file for reading");
+ enc_getline();
+ if (*enc_line != '/' || (r = strchr(enc_line, '[')) == 0)
+ ttf_fail("invalid encoding vector: name or `[' missing:\n%s", enc_line);
+ for (i = 0; i <= MAX_CHAR_CODE; i++)
+ enc_names[i] = (char*) notdef;
+ if (r[1] == 32)
+ r += 2;
+ else
+ r++;
+ for (;;) {
+ while (*r == '/') {
+ for (q = buf, r++; *r != ' ' && *r != 10 && *r != ']' && *r != '/'; *q++ = *r++);
+ *q = 0;
+ if (*r == ' ')
+ r++;
+ if (strcmp(buf, notdef) != 0)
+ enc_names[names_count] = xstrdup(buf);
+ if (names_count++ > MAX_CHAR_CODE)
+ ttf_fail("encoding vector contains more than %i names",
+ (int)(MAX_CHAR_CODE + 1));
+ }
+ if (*r != 10 && *r != '%')
+ if (strncmp(r, "] def", strlen("] def")) == 0)
+ goto done;
+ else
+ ttf_fail("invalid encoding vector: a name or `] def' expected:\n%s", enc_line);
+ enc_getline();
+ r = enc_line;
+ }
+done:
+ xfclose(encfile, cur_file_name);
+ if (names_count != MAX_CHAR_CODE + 1)
+ ttf_warn("encoding vector contains only %i names (expected %i)",
+ names_count, MAX_CHAR_CODE + 1);
+}
+
+void append_unicode(long glyph_index, TTF_USHORT code)
+{
+ mtx_entry *m;
+ unicode_entry *u, *v;
+ assert(glyph_index >= 0 && glyph_index < nglyphs);
+ u = xtalloc(1, unicode_entry), *v;
+ m = mtx_tab + glyph_index;
+ u->next = NULL;
+ u->code = code;
+ if (m->unicode_list == NULL)
+ m->unicode_list = u;
+ else {
+ for (v = m->unicode_list; v->next != NULL; v = v->next);
+ v->next = u;
+ }
+}
+
+void read_cmap()
+{
+ cmap_entry *e;
+ seg_entry *seg_tab, *s;
+ TTF_USHORT *glyphId, format, segCount;
+ long int n, i, j, k, first_code, length, last_sep, index;
+ int unicode_map_count = 0;
+ ttf_seek_tab("cmap", TTF_USHORT_SIZE); /* skip the table vesrion number (=0) */
+ ncmapsubtabs = get_ushort();
+ cmap_offset = xftell(fontfile, cur_file_name) - 2*TTF_USHORT_SIZE;
+ cmap_tab = xtalloc(ncmapsubtabs, cmap_entry);
+ for (e = cmap_tab; e - cmap_tab < ncmapsubtabs; e++) {
+ e->platform_id = get_ushort();
+ e->encoding_id = get_ushort();
+ e->offset = get_ulong();
+ }
+ for (i = 0; i < 0xFFFF; ++i)
+ unicode_map[i] = NOGLYPH_ASSIGNED_YET;
+ for (e = cmap_tab; e - cmap_tab < ncmapsubtabs; e++) {
+ ttf_seek_off("cmap", cmap_offset + e->offset);
+ format = get_ushort();
+ if (is_unicode_mapping(e) && format == 4) {
+ ++unicode_map_count;
+ if (unicode_map_count == select_unicode)
+ goto read_unicode_mapping;
+ }
+ continue;
+read_unicode_mapping:
+ length = get_ushort(); /* length of subtable */
+ get_ushort(); /* skip the version number */
+ segCount = get_ushort()/2;
+ get_ushort(); /* skip searchRange */
+ get_ushort(); /* skip entrySelector */
+ get_ushort(); /* skip rangeShift */
+ seg_tab = xtalloc(segCount, seg_entry);
+ for (s = seg_tab; s - seg_tab < segCount; s++)
+ s->endCode = get_ushort();
+ get_ushort(); /* skip reversedPad */
+ for (s = seg_tab; s - seg_tab < segCount; s++)
+ s->startCode = get_ushort();
+ for (s = seg_tab; s - seg_tab < segCount; s++)
+ s->idDelta = get_ushort();
+ for (s = seg_tab; s - seg_tab < segCount; s++)
+ s->idRangeOffset = get_ushort();
+ length -= 8*TTF_USHORT_SIZE + 4*segCount*TTF_USHORT_SIZE;
+ n = length/TTF_USHORT_SIZE; /* number of glyphID's */
+ glyphId = xtalloc(n, TTF_USHORT);
+ for (i = 0; i < n; i++)
+ glyphId[i] = get_ushort();
+ for (s = seg_tab; s - seg_tab < segCount; s++) {
+ for (i = s->startCode; i <= s->endCode; i++) {
+ if (i == 0xFFFF)
+ break;
+ if (s->idRangeOffset != 0xFFFF) {
+ if (s->idRangeOffset == 0)
+ index = (s->idDelta + i) & 0xFFFF;
+ else {
+ k = (i - s->startCode) + s->idRangeOffset/2 +
+ (s - seg_tab) - segCount ;
+ assert(k >= 0 && k < n);
+ index = glyphId[k];
+ if (index != 0)
+ index = (index + s->idDelta) & 0xFFFF;
+ }
+ if (index < 0 || index >= nglyphs)
+ ttf_fail("cmap: glyph index out of range [0..%i)", nglyphs);
+ if (unicode_map[i] != NOGLYPH_ASSIGNED_YET)
+ ttf_fail("cmap: unicode %.4X is mapped to multiple glyphs", i);
+ if (unicode_map[i] == 0)
+ ttf_warn("unicode %.4X is mapped to glyph 0", i);
+ unicode_map[i] = index;
+ append_unicode(index, i);
+ }
+ }
+ }
+ xfree(seg_tab);
+ xfree(glyphId);
+ break;
+ }
+ if (e - cmap_tab == ncmapsubtabs)
+ ttf_fail("Invalid argument `-m %i': out of range [1..%i]",
+ select_unicode, unicode_map_count);
+}
+
+void read_font()
+{
+ long i, j, k, l, n, m, platform_id, encoding_id;
+ TTF_FWORD kern_value;
+ char buf[1024], *p;
+ dirtab_entry *pd;
+ kern_entry *pk;
+ mtx_entry *pm;
+ ttf_skip(TTF_FIXED_SIZE);
+ ntabs = get_ushort();
+ ttf_skip(3*TTF_USHORT_SIZE);
+ dir_tab = xtalloc(ntabs, dirtab_entry);
+ for (pd = dir_tab; pd - dir_tab < ntabs; pd++) {
+ pd->tag[0] = get_char();
+ pd->tag[1] = get_char();
+ pd->tag[2] = get_char();
+ pd->tag[3] = get_char();
+ ttf_skip(TTF_ULONG_SIZE);
+ pd->offset = get_ulong();
+ pd->length = get_ulong();
+ }
+ ttf_seek_tab("head", 2*TTF_FIXED_SIZE + 2*TTF_ULONG_SIZE + TTF_USHORT_SIZE);
+ upem = get_ushort();
+ ttf_skip(16);
+ FontBBox1 = get_fword();
+ FontBBox2 = get_fword();
+ FontBBox3 = get_fword();
+ FontBBox4 = get_fword();
+ ttf_skip(TTF_USHORT_SIZE);
+ ttf_skip(TTF_USHORT_SIZE + TTF_SHORT_SIZE);
+ loca_format = get_short();
+ ttf_seek_tab("maxp", TTF_FIXED_SIZE);
+ nglyphs = get_ushort();
+ mtx_tab = xtalloc(nglyphs + 1, mtx_entry);
+ for (pm = mtx_tab; pm - mtx_tab < nglyphs + 1; pm++) {
+ pm->name = NULL; /* notdef */
+ pm->found = 0;
+ pm->unicode_list = NULL;
+ }
+ ttf_seek_tab("hhea", TTF_FIXED_SIZE);
+ Ascender = get_fword();
+ Descender = get_fword();
+ ttf_skip(TTF_FWORD_SIZE + TTF_UFWORD_SIZE + 3*TTF_FWORD_SIZE + 8*TTF_SHORT_SIZE);
+ nhmtx = get_ushort();
+ ttf_seek_tab("hmtx", 0);
+ for (pm = mtx_tab; pm - mtx_tab < nhmtx; pm++) {
+ pm->wx = get_ufword();
+ ttf_skip(TTF_FWORD_SIZE);
+ }
+ i = pm[-1].wx;
+ for (; pm - mtx_tab < nglyphs; pm++)
+ pm->wx = i;
+ ttf_seek_tab("post", 0);
+ post_format = get_fixed();
+ ItalicAngle = get_fixed();
+ UnderlinePosition = get_fword();
+ UnderlineThickness = get_fword();
+ IsFixedPitch = get_ulong();
+ ttf_skip(4*TTF_ULONG_SIZE);
+ switch (post_format) {
+ case 0x00010000:
+ for (pm = mtx_tab; pm - mtx_tab < NMACGLYPHS; pm++)
+ pm->name = mac_glyph_names[pm - mtx_tab];
+ break;
+ case 0x00020000:
+ l = get_ushort(); /* some fonts have this value different from nglyphs */
+ for (pm = mtx_tab; pm - mtx_tab < l; pm++)
+ pm->index = get_ushort();
+ if ((pd = name_lookup("post")) == NULL)
+ ttf_fail("can't find table `post'");
+ n = pd->length - (xftell(fontfile, cur_file_name) - pd->offset);
+ ps_glyphs_buf = xtalloc(n + 1, char);
+ for (m = 0, p = ps_glyphs_buf; p - ps_glyphs_buf < n;) {
+ for (i = get_byte(); i > 0; i--)
+ *p++ = get_char();
+ *p++ = 0;
+ m++;
+ }
+ for (pm = mtx_tab; pm - mtx_tab < l; pm++) {
+ if (pm->index < NMACGLYPHS)
+ pm->name = mac_glyph_names[pm->index];
+ else {
+ k = pm->index - NMACGLYPHS;
+ if (k < m) {
+ for (p = ps_glyphs_buf; k > 0; k--)
+ p = (char *)strend(p) + 1;
+ pm->name = p;
+ }
+ else {
+ pm->name = NULL; /* index out of valid range, fix name to notdef */
+ }
+ }
+ }
+ break;
+ case 0x00030000:
+ if (print_glyph == AS_NAME) {
+ ttf_warn("no names available in `post' table, print glyph names as indices");
+ print_glyph = AS_INDEX;
+ }
+ break;
+ default:
+ ttf_fail("unsupported format (%.8X) of `post' table", post_format);
+ }
+ ttf_seek_tab("loca", 0);
+ for (pm = mtx_tab; pm - mtx_tab < nglyphs + 1; pm++)
+ pm->offset = (loca_format == 1 ? get_ulong() : get_ushort() << 1);
+ if ((pd = name_lookup("glyf")) == NULL)
+ ttf_fail("can't find table `glyf'");
+ for (n = pd->offset, pm = mtx_tab; pm - mtx_tab < nglyphs; pm++) {
+ ttf_seek_off("glyf", n + pm->offset);
+ ttf_skip(TTF_SHORT_SIZE);
+ pm->bbox[0] = get_fword();
+ pm->bbox[1] = get_fword();
+ pm->bbox[2] = get_fword();
+ pm->bbox[3] = get_fword();
+ }
+
+ ttf_seek_tab("name", 0);
+ i = ftell(fontfile);
+ get_ushort(); /* skip Format selector (=0) */
+ n = get_ushort(); /* number of name records */
+ j = get_ushort() + i; /* start of string storage */
+ i += 3*TTF_USHORT_SIZE; /* update the current offset */
+ while (n-- > 0) {
+ ttf_seek_off("name", i);
+ platform_id = get_ushort();
+ encoding_id = get_ushort();
+ get_ushort(); /* skip language_id */
+ k = get_ushort(); /* name_id */
+ l = get_ushort(); /* string length */
+ if ((platform_id == 1 && encoding_id == 0) &&
+ (k == 0 || k == 1 || k == 4 || k == 5 ||
+ k == 6)) {
+ ttf_seek_off("name", j + get_ushort());
+ for (p = buf; l-- > 0; p++)
+ *p = get_char();
+ *p++ = 0;
+ p = xstrdup(buf);
+ switch (k) {
+ case 0: Notice = p; break;
+ case 1: FamilyName = p; break;
+ case 4: FullName = p; break;
+ case 5: Version = p; break;
+ case 6: FontName = p; break;
+ }
+ if (Notice != NULL && FamilyName != NULL &&
+ FullName != NULL && FontName != NULL &&
+ Version != NULL)
+ break;
+ }
+ i += 6*TTF_USHORT_SIZE;
+ }
+ if ((pd = name_lookup("PCLT")) != NULL) {
+ ttf_seek_off("PCLT", pd->offset + TTF_FIXED_SIZE + TTF_ULONG_SIZE + TTF_USHORT_SIZE);
+ XHeight = get_ushort();
+ if (XHeight > FontBBox4) {
+ ttf_warn("XHeight is too big (%i)\n"
+ "This is likely a font bug, so I discarded this parameter.",
+ (int)get_ttf_funit(XHeight));
+ XHeight = 0;
+ }
+ ttf_skip(2*TTF_USHORT_SIZE);
+ CapHeight = get_ushort();
+ if (CapHeight > FontBBox4) {
+ ttf_warn("CapHeight is too big (%i)\n"
+ "This is likely a font bug, so I discarded this parameter.",
+ (int)get_ttf_funit(CapHeight));
+ CapHeight = 0;
+ }
+ }
+ if ((pd = name_lookup("OS/2")) != NULL) {
+ ttf_seek_off("OS/2", pd->offset + TTF_USHORT_SIZE + TTF_SHORT_SIZE);
+ switch (get_ushort()) {
+ case 100: Weight = xstrdup("Thin"); break;
+ case 200: Weight = xstrdup("ExtraLight"); break;
+ case 300: Weight = xstrdup("Light"); break;
+ case 400: Weight = xstrdup("Normal"); break;
+ case 500: Weight = xstrdup("Medium"); break;
+ case 600: Weight = xstrdup("SemiBold"); break;
+ case 700: Weight = xstrdup("Bold"); break;
+ case 800: Weight = xstrdup("ExtraBold"); break;
+ case 900: Weight = xstrdup("Black"); break;
+ }
+ }
+ read_cmap();
+ if ((pd = name_lookup("kern")) == NULL)
+ return;
+ kern_tab = xtalloc(nglyphs, kern_entry);
+ for (pk = kern_tab; pk - kern_tab < nglyphs; pk++) {
+ pk->next = NULL;
+ pk->value = 0;
+ }
+ ttf_seek_off("kern", pd->offset + TTF_USHORT_SIZE);
+ for (n = get_ushort(); n > 0; n--) {
+ ttf_skip(2*TTF_USHORT_SIZE);
+ k = get_ushort();
+ if (!(k & 1) || (k & 2) || (k & 4))
+ return;
+ if (k >> 8 != 0) {
+ ttf_warn("warning: only format 0 supported of `kern' \
+ subtables, others are ignored\n");
+ continue;
+ }
+ k = get_ushort();
+ ttf_skip(3*TTF_USHORT_SIZE);
+ while (k-- > 0) {
+ i = get_ushort();
+ j = get_ushort();
+ kern_value = get_fword();
+ if (kern_value != 0) {
+ store_kern_value(i, j, kern_value);
+ nkernpairs++;
+ }
+ }
+ }
+}
+
+int null_glyph(const char *s)
+{
+ return (s == NULL || s == notdef);
+ /*
+ strcmp(s, ".null") == 0 ||
+ strcmp(s, ".notdef") == 0 ||
+ strcmp(s, "CR") == 0 ||
+ strcmp(s, "nonmarkingreturn") == 0
+ */
+}
+
+void print_glyph_name(FILE *f, long glyph_index, int convention)
+{
+ unicode_entry *u;
+ static char buf[1024];
+ const char *n;
+ assert(glyph_index >= 0 && glyph_index < nglyphs);
+ n = mtx_tab[glyph_index].name;
+ if (printing_enc && (n == notdef || glyph_index == 0)) {
+ fputs(notdef, f);
+ return;
+ }
+ switch (convention) {
+ case AS_NAME:
+ if (!null_glyph(n))
+ fprintf(f, "%s", mtx_tab[glyph_index].name);
+ else if (n == notdef && glyph_index == 0)
+ fputs(notdef, f);
+ else
+ fprintf(f, "%s%li", GLYPH_PREFIX_INDEX, glyph_index);
+ break;
+ case AS_INDEX:
+ fprintf(f, "%s%li", GLYPH_PREFIX_INDEX, glyph_index);
+ break;
+ case AS_UNICODE:
+ u = mtx_tab[glyph_index].unicode_list;
+ if (glyph_index == 0 || u == NULL)
+ fprintf(f, "%s%li", GLYPH_PREFIX_INDEX, glyph_index);
+ else {
+ fprintf(f, "%s%.4X", GLYPH_PREFIX_UNICODE, u->code);
+ if (u->next != NULL) {
+ *buf = 0;
+ for (; u != NULL; u = u->next) {
+ assert(strlen(buf) + strlen(GLYPH_PREFIX_UNICODE) + 4 < sizeof(buf));
+ sprintf(strend(buf), "%s%.4X ", GLYPH_PREFIX_UNICODE, u->code);
+ }
+ ttf_warn("glyph %li have multiple encodings: %s",
+ glyph_index, buf);
+ }
+ }
+ break;
+ }
+}
+
+void print_char_metric(FILE *f, int charcode, long glyph_index)
+{
+ assert(glyph_index >= 0 && glyph_index < nglyphs);
+ fprintf(f, "C %i ; WX %i ; N ", (int) charcode,
+ (int)get_ttf_funit(mtx_tab[glyph_index].wx));
+ print_glyph_name(f, glyph_index, print_glyph);
+ fprintf(f, " ; B %i %i %i %i ;\n",
+ (int)get_ttf_funit(mtx_tab[glyph_index].bbox[0]),
+ (int)get_ttf_funit(mtx_tab[glyph_index].bbox[1]),
+ (int)get_ttf_funit(mtx_tab[glyph_index].bbox[2]),
+ (int)get_ttf_funit(mtx_tab[glyph_index].bbox[3]));
+}
+
+void print_afm(char *date, char *fontname)
+{
+ int i, ncharmetrics;
+ mtx_entry *pm;
+ short mtx_index[MAX_CHAR_CODE + 1], *idx;
+ unsigned int index;
+ char **pe;
+ kern_entry *pk, *qk;
+ unicode_entry *u;
+ char buf[20];
+ fputs("StartFontMetrics 2.0\n", outfile);
+ fprintf(outfile, "Comment Converted at %s by ttf2afm from font file `%s'\n", date, fontname);
+ print_str(FontName);
+ print_str(FullName);
+ print_str(FamilyName);
+ print_str(Weight);
+ fprintf(outfile, "ItalicAngle %i", (int)(ItalicAngle/0x10000));
+ if (ItalicAngle%0x10000 > 0)
+ fprintf(outfile, ".%i", (int)((ItalicAngle%0x10000)*1000)/0x10000);
+ fputs("\n", outfile);
+ fprintf(outfile, "IsFixedPitch %s\n", IsFixedPitch ? "true" : "false");
+ fprintf(outfile, "FontBBox %i %i %i %i\n",
+ (int)get_ttf_funit(FontBBox1),
+ (int)get_ttf_funit(FontBBox2),
+ (int)get_ttf_funit(FontBBox3),
+ (int)get_ttf_funit(FontBBox4));
+ print_dimen(UnderlinePosition);
+ print_dimen(UnderlineThickness);
+ print_str(Version);
+ print_str(Notice);
+ fputs("EncodingScheme FontSpecific\n", outfile);
+ print_dimen(CapHeight);
+ print_dimen(XHeight);
+ print_dimen(Ascender);
+ print_dimen(Descender);
+ ncharmetrics = nglyphs;
+ if (use_ext_enc == 0) { /* external encoding vector not given */
+ fprintf(outfile, "StartCharMetrics %u\n", ncharmetrics);
+ for (pm = mtx_tab; pm - mtx_tab < nglyphs; pm++) {
+ pm->found = 1;
+ print_char_metric(outfile, -1, pm - mtx_tab);
+ }
+ }
+ else { /* external encoding vector given */
+ for (idx = mtx_index; idx - mtx_index <= MAX_CHAR_CODE; *idx++ = 0);
+ for (pe = enc_names; pe - enc_names < names_count; pe++) {
+ if (*pe == notdef)
+ continue;
+ /* scan form `uniABCD' */
+ if (sscanf(*pe, GLYPH_PREFIX_UNICODE "%X", &index) == 1) {
+ if (unicode_map[index] != NOGLYPH_ASSIGNED_YET) {
+ pm = mtx_tab + unicode_map[index];
+ pm->found = 1;
+ }
+ else
+ ttf_warn("`unicode %s%.4X' is not mapped to any glyph",
+ GLYPH_PREFIX_UNICODE, index);
+ continue;
+ }
+ /* scan form `index123' */
+ if (sscanf(*pe, GLYPH_PREFIX_INDEX "%u", &index) == 1) {
+ if (index >= nglyphs)
+ ttf_fail("`%s' out of valid range [0..%i)",
+ *pe, nglyphs);
+ pm = mtx_tab + index;
+ pm->found = 1;
+ continue;
+ }
+ for (pm = mtx_tab; pm - mtx_tab < nglyphs; pm++)
+ if (pm->name != NULL && strcmp(*pe, pm->name) == 0)
+ break;
+ if (pm - mtx_tab < nglyphs) {
+ mtx_index[pe - enc_names] = pm - mtx_tab;
+ pm->found = 1;
+ continue;
+ }
+ else
+ ttf_warn("glyph `%s' not found", *pe);
+ }
+ fprintf(outfile, "StartCharMetrics %u\n", ncharmetrics);
+ for (idx = mtx_index; idx - mtx_index <= MAX_CHAR_CODE; idx++) {
+ if (*idx != 0 && mtx_tab[*idx].found == 1)
+ print_char_metric(outfile, idx - mtx_index, *idx);
+ }
+ for (pm = mtx_tab; pm - mtx_tab < nglyphs; pm++) {
+ if (pm->found == 0)
+ print_char_metric(outfile, -1, pm - mtx_tab);
+ }
+ }
+end_metrics:
+ fputs("EndCharMetrics\n", outfile);
+ if (nkernpairs == 0)
+ goto end_kerns;
+ fprintf(outfile, "StartKernData\nStartKernPairs %i\n", nkernpairs);
+ for (pk = kern_tab; pk - kern_tab < nglyphs; pk++)
+ for (qk = pk; qk != NULL; qk = qk->next)
+ if (qk->value != 0) {
+ fputs("KPX ", outfile);
+ print_glyph_name(outfile, pk - kern_tab, print_glyph);
+ fputs(" ", outfile);
+ print_glyph_name(outfile, qk->adjacent, print_glyph);
+ fprintf(outfile, " %i\n", get_ttf_funit(qk->value));
+ }
+ fputs("EndKernPairs\nEndKernData\n", outfile);
+end_kerns:
+ fputs("EndFontMetrics\n", outfile);
+}
+
+void print_encoding(char *fontname)
+{
+ long int i, k, first_code, length, last_sep;
+ FILE *file;
+ TTF_USHORT format;
+ char *enc_name, *end_enc_name;
+ cmap_entry *e;
+ const char *n;
+ printing_enc = 1;
+ enc_name = xtalloc(strlen(bname) + 20, char);
+ strcpy(enc_name, bname);
+ end_enc_name = strend(enc_name);
+ for (e = cmap_tab; e - cmap_tab < ncmapsubtabs; e++) {
+ ttf_seek_off("cmap", cmap_offset + e->offset);
+ format = get_ushort();
+ if (format != 0 && format != 4 && format != 6) {
+ ttf_warn("format %i of encoding subtable unsupported", (int)format);
+ continue;
+ }
+ sprintf(end_enc_name, ".e%i%i",
+ (int)e->platform_id, (int)e->encoding_id);
+ if ((file = xfopen(enc_name, FOPEN_W_MODE)) == NULL)
+ ttf_fail("cannot open file for writing (%s)\n", enc_name);
+ fprintf(file, "%% Encoding table from font file %s\n", fontname);
+ fprintf(file, "%% Platform ID %i", (int)e->platform_id);
+ switch (e->platform_id) {
+ case 0: fprintf(file, " (Apple Unicode)"); break;
+ case 1: fprintf(file, " (Macintosh)"); break;
+ case 2: fprintf(file, " (ISO)"); break;
+ case 3: fprintf(file, " (Microsoft)"); break;
+ }
+ fprintf(file, "\n");
+ fprintf(file, "%% Encoding ID %i", (int)e->encoding_id);
+ if (e->platform_id == 1 && e->encoding_id == 0)
+ fprintf(file, " (Roman)");
+ if (e->platform_id == 3)
+ switch (e->encoding_id) {
+ case 0: fprintf(file, " (Symbol)"); break;
+ case 1: fprintf(file, " (Unicode)"); break;
+ }
+ fprintf(file, "\n");
+ fprintf(file, "%% Format %i", (int)(format));
+ switch (format) {
+ case 0: fprintf(file, " (byte encoding table)"); break;
+ case 4: fprintf(file, " (segment mapping to delta values)"); break;
+ case 6: fprintf(file, " (trimmed table mapping)"); break;
+ }
+ fprintf(file, "\n");
+ fprintf(file, "/Encoding%i [\n", (int)(e - cmap_tab + 1));
+ switch (format) {
+ case 0:
+ get_ushort(); /* skip length */
+ get_ushort(); /* skip version number */
+ for (i = 0; i <= MAX_CHAR_CODE; i++) {
+ fputs("/", file);
+ print_glyph_name(file, get_byte(), print_glyph);
+ fputs("\n", file);
+ }
+ break;
+ case 4:
+ for (i = 0; i < nglyphs; ++i) {
+ fprintf(file, "%% Glyph %li -> ", i);
+ print_glyph_name(file, i, AS_UNICODE);
+ fputs("\n", file);
+ }
+ break;
+ case 6:
+ get_ushort(); /* skip table length */
+ get_ushort(); /* skip version number */
+ first_code = get_ushort(); /* first character code */
+ for (i = 0; i < first_code; ++i)
+ fprintf(file, "/%s\n", notdef);
+ length = get_ushort(); /* number of character codes */
+ for (i = first_code; i < first_code + length; i++) {
+ k = get_ushort();
+ if (i > MAX_CHAR_CODE)
+ fputs("% ", file);
+ fputs("/", file);
+ print_glyph_name(file, k, print_glyph);
+ fputs("\n", file);
+ }
+ for (i = first_code + length; i <= MAX_CHAR_CODE; i++)
+ fprintf(file, "/%s\n", notdef);
+ break;
+ default:
+ ttf_warn("format %i of encoding subtable unsupported", (int)format);
+ }
+ fprintf(file, "] def\n");
+ }
+ xfree(enc_name);
+}
+
+void usage()
+{
+ cur_file_name = NULL;
+ fprintf(stderr,
+ "Usage: ttf2afm [-i|-u|-c|-v] [-e enc] [-o filename] [-m NUM] fontfile\n"
+ " -i: force printing glyph names in form 'index123'\n"
+ " -u: force printing glyph names in form 'uniABCD'\n"
+ " -c: print encoding tables to `basename.e<platformID><encodingID>'\n"
+ " -v: print version\n"
+ " -e enc: encode the AFM output using encoding vector from `enc'\n"
+ " -o filename: write output to file `filename' instead of stdout\n"
+ " -m NUM: select unicode mapping (default = 1, ie the first)\n"
+ " fontfile: the TrueType fontfile\n"
+ "\nPlease send bug reports or feature requests to <pdftex@tug.org>\n"
+ );
+ _exit(-1);
+}
+
+int main(int argc, char **argv)
+{
+ char date[128], *s;
+ time_t t = time(&t);
+ int c;
+ kpse_set_progname(argv[0]);
+ kpse_init_prog("ttf2afm", 0, 0, 0) ;
+ while ((c = getopt(argc, argv, "iucve:o:m:")) != -1)
+ switch (c) {
+ case 'i':
+ print_glyph = AS_INDEX;
+ break;
+ case 'u':
+ print_glyph = AS_UNICODE;
+ break;
+ case 'c':
+ print_cmap = 1;
+ break;
+ case 'e':
+ cur_file_name = optarg;
+ read_encoding(cur_file_name);
+ use_ext_enc = 1;
+ break;
+ case 'o':
+ cur_file_name = optarg;
+ outfile = xfopen(cur_file_name, FOPEN_W_MODE);
+ if (outfile == NULL)
+ ttf_fail("cannot open file for writing");
+ break;
+ case 'm':
+ select_unicode = atoi(optarg);
+ break;
+ case 'v':
+ fprintf(stderr,
+ "ttf2afm version " VERSION "\n"
+ "Copyright (C) 1997-2005 Han The Thanh.\n"
+ "There is NO warranty. Redistribution of this software is\n"
+ "covered by the terms of both the pdfTeX copyright and\n"
+ "the GNU General Public License.\n"
+ "For more information about these matters, see the files\n"
+ "named COPYING and the pdfTeX source.\n"
+ "Primary author of ttf2afm: Han The Thanh.\n"
+ );
+ _exit(0);
+ default:
+ usage();
+ }
+ if (argc - optind != 1)
+ usage();
+ sprintf(date, "%s\n", ctime(&t));
+ *(char *)strchr(date, '\n') = 0;
+ cur_file_name = argv[optind];
+ if (print_cmap) {
+ bname = strdup(xbasename(cur_file_name));
+ if ((s = rindex(bname, '.')) != NULL)
+ *s = 0;
+ }
+ if ((fontfile = kpse_open_file(cur_file_name, kpse_truetype_format)) == NULL)
+ ttf_fail("can't open font file for reading");
+ read_font();
+ if (outfile == NULL)
+ outfile = stdout;
+ print_afm(date, cur_file_name);
+ if (print_cmap)
+ print_encoding(cur_file_name);
+ xfree(FontName);
+ xfree(FullName);
+ xfree(FamilyName);
+ xfree(Notice);
+ xfree(Version);
+ xfree(Weight);
+ free_tabs();
+ xfclose(fontfile, cur_file_name);
+ return 0;
+}
diff --git a/Build/source/texk/web2c/pdftexdir/ttf2afm.rc b/Build/source/texk/web2c/pdftexdir/ttf2afm.rc
new file mode 100644
index 00000000000..a63881df7d1
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/ttf2afm.rc
@@ -0,0 +1,35 @@
+/* ttf2afm.rc: ttf2afm -*- C++ -*-
+
+ Copyright (C) 1996-2003 Fabrice Popineau <fabrice.popineau@supelec.fr>
+
+ This file is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ This file is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this file; if not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
+
+#include <texlive-version.h>
+
+#define VER_FILEVERSION TEXLIVE_MAJOR_VERSION,TEXLIVE_MINOR_VERSION,TEXLIVE_BETA_NUMBER,TEXLIVE_ALPHA_NUMBER
+#define VER_FILEVERSION_STR TEXLIVE_PRODUCTVERSION_STR " ttf2afm 1.10a"
+
+#define VER_INTERNALNAME_STR "ttf2afm"
+#define VER_ORIGINALFILENAME_STR "ttf2afm.exe"
+
+#define VER_FILEDESCRIPTION_STR "TTF-to-AFM Converter"
+
+#define VER_COMPANYNAME_STR ""
+#define VER_LEGALCOPYRIGHT_STR "Copyright (c) 1996-2002 Han The Thanh, <thanh@pdftex.org>"
+
+#include "texlive.version"
+
+/* ttf2afm.rc ends here */
diff --git a/Build/source/texk/web2c/pdftexdir/utils.c b/Build/source/texk/web2c/pdftexdir/utils.c
new file mode 100644
index 00000000000..c1be283ba2e
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/utils.c
@@ -0,0 +1,1129 @@
+/*
+Copyright (c) 1996-2005 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX 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.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/utils.c#25 $
+*/
+
+#include "sys/types.h"
+#include "regex.h"
+#include "ptexlib.h"
+#include "zlib.h"
+#include "md5.h"
+#include <kpathsea/c-vararg.h>
+#include <kpathsea/c-proto.h>
+#include <kpathsea/c-stat.h>
+#include <kpathsea/c-fopen.h>
+#include <time.h>
+
+static const char perforce_id[] =
+ "$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/utils.c#25 $";
+
+char *cur_file_name = NULL;
+strnumber last_tex_string;
+static char print_buf[PRINTF_BUF_SIZE];
+static char *jobname_cstr = NULL;
+static char *job_id_string = NULL;
+extern string ptexbanner; /* from web2c/lib/texmfmp.c */
+extern string versionstring; /* from web2c/lib/version.c */
+extern KPSEDLL string kpathsea_version_string; /* from kpathsea/version.c */
+
+size_t last_ptr_index; /* for use with alloc_array */
+
+/* define fb_ptr, fb_array & fb_limit */
+typedef char fb_entry;
+define_array(fb);
+
+/* define char_ptr, char_array & char_limit */
+typedef char char_entry;
+define_array(char);
+
+integer fb_offset(void)
+{
+ return fb_ptr - fb_array;
+}
+
+void fb_seek(integer offset)
+{
+ fb_ptr = fb_array + offset;
+}
+
+void fb_putchar(eightbits b)
+{
+ alloc_array(fb, 1, SMALL_ARRAY_SIZE);
+ *fb_ptr++ = b;
+}
+
+void fb_flush(void)
+{
+ fb_entry *p;
+ integer n;
+ for (p = fb_array; p < fb_ptr;) {
+ n = pdfbufsize - pdfptr;
+ if (fb_ptr - p < n)
+ n = fb_ptr - p;
+ memcpy(pdfbuf + pdfptr, p, (unsigned)n);
+ pdfptr += n;
+ if (pdfptr == pdfbufsize)
+ pdfflush();
+ p += n;
+ }
+ fb_ptr = fb_array;
+}
+
+static void fnstr_append(const char *s)
+{
+ int l = strlen(s) + 1;
+ alloc_array(char, l, SMALL_ARRAY_SIZE);
+ strcat(char_ptr, s);
+ char_ptr = strend(char_ptr);
+}
+
+void make_subset_tag(fm_entry *fm_cur, char **glyph_names)
+{
+ char tag[7];
+ unsigned long crc;
+ int i, l = strlen(job_id_string) + 1;
+ alloc_array(char, l, SMALL_ARRAY_SIZE);
+ strcpy(char_array, job_id_string);
+ char_ptr = strend(char_array);
+ if (fm_cur->tfm_name != NULL) {
+ fnstr_append(" TFM name: ");
+ fnstr_append(fm_cur->tfm_name);
+ }
+ fnstr_append(" PS name: ");
+ if (font_keys[FONTNAME_CODE].valid)
+ fnstr_append(fontname_buf);
+ else if (fm_cur->ps_name != NULL)
+ fnstr_append(fm_cur->ps_name);
+ fnstr_append(" Encoding: ");
+ if (fm_cur->encoding != NULL && (fm_cur->encoding)->name != NULL)
+ fnstr_append((fm_cur->encoding)->name);
+ else
+ fnstr_append("built-in");
+ fnstr_append(" CharSet: ");
+ assert(glyph_names != NULL);
+ for (i = 0; i <= MAX_CHAR_CODE; i++)
+ if (pdfcharmarked(tex_font, i) && glyph_names[i] != notdef) {
+ fnstr_append(" /");
+ fnstr_append(glyph_names[i]);
+ }
+ if (fm_cur->charset != NULL) {
+ fnstr_append(" Extra CharSet: ");
+ fnstr_append(fm_cur->charset);
+ }
+ crc = crc32(0L, Z_NULL, 0);
+ crc = crc32(crc, (Bytef*)char_array, strlen(char_array));
+ /* we need to fit a 32-bit number into a string of 6 uppercase chars long;
+ * there are 26 uppercase chars ==> each char represents a number in range
+ * 0..25. The maximal number that can be represented by the tag is
+ * 26^6 - 1, which is a number between 2^28 and 2^29. Thus the bits 29..31
+ * of the CRC must be dropped out.
+ */
+ for (i = 0; i < 6; i++) {
+ tag[i] = 'A' + crc % 26;
+ crc /= 26;
+ }
+ tag[6] = 0;
+ fm_cur->subset_tag = xstrdup(tag);
+}
+
+void pdf_puts(const char *s)
+{
+ pdfroom(strlen(s) + 1);
+ while (*s)
+ pdfbuf[pdfptr++] = *s++;
+}
+
+void pdf_printf(const char *fmt,...)
+{
+ va_list args;
+ va_start(args, fmt);
+ vsprintf(print_buf, fmt, args);
+ pdf_puts(print_buf);
+ va_end(args);
+}
+
+strnumber maketexstring(const char *s)
+{
+ int l;
+ if (s == NULL || *s == 0)
+ return getnullstr();
+ l = strlen(s);
+ check_buf(poolptr + l, poolsize);
+ while (l-- > 0)
+ strpool[poolptr++] = *s++;
+ last_tex_string = makestring();
+ return last_tex_string;
+}
+
+void tex_printf(const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ vsprintf(print_buf, fmt, args);
+ print(maketexstring(print_buf));
+ flushstr(last_tex_string);
+ xfflush(stdout);
+ va_end(args);
+}
+
+/* Helper for pdftex_fail. */
+static void safe_print(const char *str)
+{
+ const char *c;
+ for (c = str; *c; ++c)
+ print(*c);
+}
+
+/* pdftex_fail may be called when a buffer overflow has happened/is
+ happening, therefore may not call mktexstring. However, with the
+ current implementation it appears that error messages are misleading,
+ possibly because pool overflows are detected too late. */
+void pdftex_fail(const char *fmt,...)
+{
+ va_list args;
+ va_start(args, fmt);
+ println();
+ safe_print("Error: ");
+ safe_print(program_invocation_name);
+ if (cur_file_name) {
+ safe_print(" (file ");
+ safe_print(cur_file_name);
+ safe_print(")");
+ }
+ safe_print(": ");
+ vsprintf(print_buf, fmt, args);
+ safe_print(print_buf);
+ va_end(args);
+ println();
+ safe_print(" ==> Fatal error occurred, the output PDF file is not finished!");
+ println();
+ exit(-1);
+}
+
+void pdftex_warn(const char *fmt,...)
+{
+ va_list args;
+ va_start(args, fmt);
+ println();
+ tex_printf("Warning: %s", program_invocation_name);
+ if (cur_file_name)
+ tex_printf(" (file %s)", cur_file_name);
+ tex_printf(": ");
+ vsprintf(print_buf, fmt, args);
+ print(maketexstring(print_buf));
+ flushstr(last_tex_string);
+ va_end(args);
+ println();
+}
+
+char *makecstring(integer s)
+{
+ static char cstrbuf[MAX_CSTRING_LEN];
+ char *p = cstrbuf;
+ int i, l = strstart[s + 1] - strstart[s];
+ check_buf(l + 1, MAX_CSTRING_LEN);
+ for (i = 0; i < l; i++)
+ *p++ = strpool[i + strstart[s]];
+ *p = 0;
+ return cstrbuf;
+}
+
+/*
+boolean str_eq_cstr(strnumber n, char *s)
+{
+ int l;
+ if (s == NULL || n == 0)
+ return false;
+ l = strstart[n];
+ while (*s && l < strstart[n + 1] && *s == strpool[l])
+ l++, s++;
+ return !*s && l == strstart[n + 1];
+}
+*/
+
+void setjobid(int year, int month, int day, int time, int pdftexversion, int pdftexrevision)
+{
+ char *name_string, *format_string, *s;
+
+ if (job_id_string != NULL)
+ return;
+
+ name_string = xstrdup(makecstring(jobname));
+ format_string = xstrdup(makecstring(formatident));
+ s = xtalloc(SMALL_BUF_SIZE +
+ strlen(name_string) +
+ strlen(format_string) +
+ strlen(ptexbanner) +
+ strlen(versionstring) +
+ strlen(kpathsea_version_string), char);
+ /* The Web2c version string starts with a space. */
+ sprintf(s, "%.4d/%.2d/%.2d %.2d:%.2d %s %s %s%s %s",
+ year, month, day, time/60, time%60,
+ name_string, format_string, ptexbanner,
+ versionstring, kpathsea_version_string);
+ job_id_string = xstrdup(s);
+ xfree(s);
+ xfree(name_string);
+ xfree(format_string);
+}
+
+void makepdftexbanner(void)
+{
+ static boolean pdftexbanner_init = false;
+ char *s;
+
+ if (pdftexbanner_init)
+ return;
+
+ s = xtalloc(SMALL_BUF_SIZE +
+ strlen(ptexbanner) +
+ strlen(versionstring) +
+ strlen(kpathsea_version_string), char);
+ /* The Web2c version string starts with a space. */
+ sprintf(s, "%s%s %s", ptexbanner, versionstring, kpathsea_version_string);
+ pdftexbanner = maketexstring(s);
+ xfree(s);
+ pdftexbanner_init = true;
+}
+
+strnumber getresnameprefix(void)
+{
+/* static char name_str[] = */
+/* "!\"$&'*+,-.0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\\" */
+/* "^_`abcdefghijklmnopqrstuvwxyz|~"; */
+ static char name_str[] =
+"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+ char prefix[7]; /* make a tag of 6 chars long */
+ unsigned long crc;
+ int i, base = strlen(name_str);
+ crc = crc32(0L, Z_NULL, 0);
+ crc = crc32(crc, (Bytef*)job_id_string, strlen(job_id_string));
+ for (i = 0; i < 6; i++) {
+ prefix[i] = name_str[crc % base];
+ crc /= base;
+ }
+ prefix[6] = 0;
+ return maketexstring(prefix);
+}
+
+size_t xfwrite(void *ptr, size_t size, size_t nmemb, FILE *stream)
+{
+ if (fwrite(ptr, size, nmemb, stream) != nmemb)
+ pdftex_fail("fwrite() failed");
+ return nmemb;
+}
+
+int xfflush(FILE *stream)
+{
+ if (fflush(stream) != 0)
+ pdftex_fail("fflush() failed");
+ return 0;
+}
+
+int xgetc(FILE *stream)
+{
+ int c = getc(stream);
+ if (c < 0 && c != EOF)
+ pdftex_fail("getc() failed");
+ return c;
+}
+
+int xputc(int c, FILE *stream)
+{
+ int i = putc(c, stream);
+ if (i < 0)
+ pdftex_fail("putc() failed");
+ return i;
+}
+
+void writestreamlength(integer length, integer offset)
+{
+ integer save_offset;
+ if (jobname_cstr == NULL)
+ jobname_cstr = xstrdup(makecstring(jobname));
+ save_offset = xftell(pdffile, jobname_cstr);
+ xfseek(pdffile, offset, SEEK_SET, jobname_cstr);
+ fprintf(pdffile, "%li", (long int)length);
+ xfseek(pdffile, pdfoffset(), SEEK_SET, jobname_cstr);
+}
+
+scaled extxnoverd(scaled x, scaled n, scaled d)
+{
+ double r = (((double)x)*((double)n))/((double)d);
+ if (r > 0)
+ r += 0.5;
+ else
+ r -= 0.5;
+ if (r >= (double)maxinteger || r <= -(double)maxinteger)
+ pdftex_warn("arithmetic: number too big");
+ return r;
+}
+
+void libpdffinish()
+{
+ xfree(fb_array);
+ xfree(char_array);
+ xfree(job_id_string);
+ fm_free();
+ t1_free();
+ enc_free();
+ img_free();
+ vf_free();
+ epdf_free();
+}
+
+/* Converts any string given in in in an allowed PDF string which can be
+ * handled by printf et.al.: \ is escaped to \\, parenthesis are escaped and
+ * control characters are octal encoded.
+ * This assumes that the string does not contain any already escaped
+ * characters!
+ */
+char *convertStringToPDFString (char *in, int len)
+{
+ static char pstrbuf[MAX_PSTRING_LEN];
+ char *out = pstrbuf;
+ int i, j;
+ char buf[5];
+ j = 0;
+ for (i = 0; i < len; i++) {
+ check_buf(j + sizeof(buf), MAX_PSTRING_LEN);
+ if (((unsigned char)in[i] < '!') || ((unsigned char)in[i] > '~')){
+ /* convert control characters into oct */
+ sprintf (buf, "\\%03o", (unsigned int)(unsigned char)in[i]);
+ out[j++] = buf[0];
+ out[j++] = buf[1];
+ out[j++] = buf[2];
+ out[j++] = buf[3];
+ }
+ else if ((in[i] == '(') || (in[i] == ')')) {
+ /* escape paranthesis */
+ out[j++] = '\\';
+ out[j++] = in[i];
+ }
+ else if (in[i] == '\\') {
+ /* escape backslash */
+ out[j++] = '\\';
+ out[j++] = '\\';
+ }
+ else {
+ /* copy char :-) */
+ out[j++] = in[i];
+ }
+ }
+ out[j] = '\0';
+ return pstrbuf;
+}
+
+
+/* Converts any string given in in in an allowed PDF string which can be
+ * handled by printf et.al.: \ is escaped to \\, parenthesis are escaped and
+ * control characters are octal encoded.
+ * This assumes that the string does not contain any already escaped
+ * characters!
+ *
+ * See escapename for parameter description.
+ */
+void escapestring(poolpointer in)
+{
+ poolpointer out = poolptr;
+ unsigned char ch;
+ while (in < out) {
+ if (poolptr + 4 >= poolsize) {
+ poolptr = poolsize;
+ /* error by str_toks that calls str_room(1) */
+ return;
+ }
+
+ ch = (unsigned char)strpool[in++];
+
+ if ((ch < '!') || (ch > '~')) {
+ /* convert control characters into oct */
+ sprintf (&strpool[poolptr], "\\%.3o", (unsigned int)ch);
+ poolptr += 4;
+ continue;
+ }
+ if ((ch == '(') || (ch == ')') || (ch == '\\')) {
+ /* escape parenthesis and backslash */
+ strpool[poolptr++] = '\\';
+ }
+ /* copy char :-) */
+ strpool[poolptr++] = ch;
+ }
+}
+
+
+/* Convert any given string in a PDF name using escaping mechanism
+ of PDF 1.2. The result does not include the leading slash.
+
+ PDF specification 1.6, section 3.2.6 "Name Objects" explains:
+ <blockquote>
+ Beginning with PDF 1.2, any character except null (character code 0) may
+ be included in a name by writing its 2-digit hexadecimal code, preceded
+ by the number sign character (#); see implementation notes 3 and 4 in
+ Appendix H. This syntax is required to represent any of the delimiter or
+ white-space characters or the number sign character itself; it is
+ recommended but not required for characters whose codes are outside the
+ range 33 (!) to 126 (~).
+ </blockquote>
+ The following table shows the conversion that are done by this
+ function:
+ code result reason
+ -----------------------------------
+ 0 ignored not allowed
+ 1..32 escaped must for white-space:
+ 9 (tab), 10 (lf), 12 (ff), 13 (cr), 32 (space)
+ recommended for the other control characters
+ 35 escaped escape char "#"
+ 37 escaped delimiter "%"
+ 40..41 escaped delimiters "(" and ")"
+ 47 escaped delimiter "/"
+ 60 escaped delimiter "<"
+ 62 escaped delimiter ">"
+ 91 escaped delimiter "["
+ 93 escaped delimiter "]"
+ 123 escaped delimiter "{"
+ 125 escaped delimiter "}"
+ 127..255 escaped recommended
+ else copy regular characters
+
+ Parameter "in" is a pointer into the string pool where
+ the input string is located. The output string is written
+ as temporary string right after the input string.
+ Thus at the begin of the procedure the global variable
+ "poolptr" points to the start of the output string and
+ after the end when the procedure returns.
+*/
+void escapename(poolpointer in)
+{
+ poolpointer out = poolptr;
+ unsigned char ch;
+
+ while (in < out) {
+ if (poolptr + 3 >= poolsize) {
+ poolptr = poolsize;
+ /* error by str_toks that calls str_room(1) */
+ return;
+ }
+
+ ch = (unsigned char)strpool[in++];
+
+ if ((ch >= 1 && ch <= 32) || ch >= 127) {
+ /* escape */
+ sprintf(&strpool[poolptr], "#%.2X", (unsigned int)ch);
+ poolptr += 3;
+ continue;
+ }
+ switch (ch) {
+ case 0:
+ /* ignore */
+ break;
+ case 35:
+ case 37:
+ case 40:
+ case 41:
+ case 47:
+ case 60:
+ case 62:
+ case 91:
+ case 93:
+ case 123:
+ case 125:
+ /* escape */
+ sprintf(&strpool[poolptr], "#%.2X", (unsigned int)ch);
+ poolptr += 3;
+ break;
+ default:
+ /* copy */
+ strpool[poolptr++] = ch;
+ }
+ }
+}
+
+/* Convert any given string in a PDF hexadecimal string. The
+ result does not include the angle brackets.
+
+ This procedure uses uppercase hexadecimal letters.
+
+ See escapename for description of parameters.
+*/
+void escapehex(poolpointer in)
+{
+ poolpointer out = poolptr;
+ unsigned char ch;
+
+ while (in < out) {
+ if (poolptr + 2 >= poolsize) {
+ poolptr = poolsize;
+ /* error by str_toks that calls str_room(1) */
+ return;
+ }
+
+ ch = (unsigned char)strpool[in++];
+
+ sprintf(&strpool[poolptr], "%.2X", (unsigned int)ch);
+ poolptr += 2;
+ }
+}
+
+/* Unescape any given hexadecimal string.
+
+ Last hex digit can be omitted, it is replaced by zero, see
+ PDF specification.
+
+ Invalid digits are silently ignored.
+
+ See escapename for description of parameters.
+*/
+void unescapehex(poolpointer in)
+{
+ poolpointer out = poolptr;
+ unsigned char ch, a;
+ boolean first = true;
+
+ while (in < out) {
+ if (poolptr + 1 >= poolsize) {
+ poolptr = poolsize;
+ /* error by str_toks that calls str_room(1) */
+ return;
+ }
+
+ ch = (unsigned char)strpool[in++];
+
+ if ((ch >= '0') && (ch <= '9')) {
+ ch -= '0';
+ }
+ else if ((ch >= 'A') && (ch <= 'F')) {
+ ch -= 'A' - 10;
+ }
+ else if ((ch >= 'a') && (ch <= 'f')) {
+ ch -= 'a' - 10;
+ }
+ else {
+ continue; /* ignore wrong character */
+ }
+
+ if (first) {
+ a = ch << 4;
+ first = false;
+ continue;
+ }
+
+ strpool[poolptr++] = a + ch;
+ first = true;
+ }
+ if (!first) { /* last hex digit is omitted */
+ strpool[poolptr++] = ch << 4;
+ }
+}
+
+
+/* Converts any string given in in in an allowed PDF string which is
+ * hexadecimal encoded;
+ * sizeof(out) should be at least lin*2+1.
+ */
+void convertStringToHexString (char *in, char *out, int lin)
+{
+ int i, j;
+ char buf[3];
+ j = 0;
+ for (i = 0; i < lin; i++) {
+ sprintf (buf, "%02X", (unsigned int)(unsigned char)in[i]);
+ out[j++] = buf[0];
+ out[j++] = buf[1];
+ }
+ out[j] = '\0';
+}
+
+/* Compute the ID string as per PDF1.4 9.3:
+ <blockquote>
+ File identifers are defined by the optional ID entry in a PDF file's
+ trailer dictionary (see Section 3.4.4, "File Trailer"; see also
+ implementation note 105 in Appendix H). The value of this entry is an
+ array of two strings. The first string is a permanent identifier based
+ on the contents of the file at the time it was originally created, and
+ does not change when the file is incrementally updated. The second
+ string is a changing identifier based on the file's contents at the
+ time it was last updated. When a file is first written, both
+ identifiers are set to the same value. If both identifiers match when a
+ file reference is resolved, it is very likely that the correct file has
+ been found; if only the first identifier matches, then a different
+ version of the correct file has been found.
+ To help ensure the uniqueness of file identifiers, it is recommend
+ that they be computed using a message digest algorithm such as MD5
+ (described in Internet RFC 1321, The MD5 Message-Digest Algorithm; see
+ the Bibliography), using the following information (see implementation
+ note 106 in Appendix H):
+ - The current time
+ - A string representation of the file's location, usually a pathname
+ - The size of the file in bytes
+ - The values of all entries in the file's document information
+ dictionary (see Section 9.2.1, Document Information Dictionary )
+ </blockquote>
+ This stipulates only that the two IDs must be identical when the file is
+ created and that they should be reasonably unique. Since it's difficult
+ to get the file size at this point in the execution of pdfTeX and
+ scanning the info dict is also difficult, we start with a simpler
+ implementation using just the first two items.
+ */
+void printID (strnumber filename)
+{
+ time_t t;
+ size_t size;
+ char time_str[32];
+ md5_state_t state;
+ md5_byte_t digest[16];
+ char id[64];
+ char *file_name;
+ char pwd[4096];
+ /* start md5 */
+ md5_init(&state);
+ /* get the time */
+ t = time(NULL);
+ size = strftime (time_str, sizeof(time_str), "%Y%m%dT%H%M%SZ", gmtime(&t));
+ md5_append(&state, (const md5_byte_t *)time_str, size);
+ /* get the file name */
+ if (getcwd(pwd, sizeof(pwd)) == NULL)
+ pdftex_fail("getcwd() failed (path too long?)");
+ file_name = makecstring(filename);
+ md5_append(&state, (const md5_byte_t *)pwd, strlen(pwd));
+ md5_append(&state, (const md5_byte_t *)"/", 1);
+ md5_append(&state, (const md5_byte_t *)file_name, strlen(file_name));
+ /* finish md5 */
+ md5_finish(&state, digest);
+ /* write the IDs */
+ convertStringToHexString ((char*)digest, id, 16);
+ pdf_printf("/ID [<%s> <%s>]", id, id);
+}
+
+/* Print the /CreationDate entry.
+
+ PDF Reference, third edition says about the expected date format:
+ <blockquote>
+ 3.8.2 Dates
+
+ PDF defines a standard date format, which closely follows that of
+ the international standard ASN.1 (Abstract Syntax Notation One),
+ defined in ISO/IEC 8824 (see the Bibliography). A date is a string
+ of the form
+
+ (D:YYYYMMDDHHmmSSOHH'mm')
+
+ where
+
+ YYYY is the year
+ MM is the month
+ DD is the day (01-31)
+ HH is the hour (00-23)
+ mm is the minute (00-59)
+ SS is the second (00-59)
+ O is the relationship of local time to Universal Time (UT),
+ denoted by one of the characters +, -, or Z (see below)
+ HH followed by ' is the absolute value of the offset from UT
+ in hours (00-23)
+ mm followed by ' is the absolute value of the offset from UT
+ in minutes (00-59)
+
+ The apostrophe character (') after HH and mm is part of the syntax.
+ All fields after the year are optional. (The prefix D:, although also
+ optional, is strongly recommended.) The default values for MM and DD
+ are both 01; all other numerical fields default to zero values. A plus
+ sign (+) as the value of the O field signifies that local time is
+ later than UT, a minus sign (-) that local time is earlier than UT,
+ and the letter Z that local time is equal to UT. If no UT information
+ is specified, the relationship of the specified time to UT is
+ considered to be unknown. Whether or not the time zone is known, the
+ rest of the date should be specified in local time.
+
+ For example, December 23, 1998, at 7:52 PM, U.S. Pacific Standard
+ Time, is represented by the string
+
+ D:199812231952-08'00'
+ </blockquote>
+
+ The main difficulty is get the time zone offset. strftime() does this in ISO
+ C99 (e.g. newer glibc) with %z, but we have to work with other systems (e.g.
+ Solaris 2.5).
+*/
+
+time_t start_time = 0;
+#define TIME_STR_SIZE 30
+char start_time_str[TIME_STR_SIZE];
+char time_str[TIME_STR_SIZE];
+ /* minimum size for time_str is 24: "D:YYYYmmddHHMMSS+HH'MM'" */
+
+void makepdftime(time_t t, char *time_str)
+{
+
+ struct tm lt, gmt;
+ size_t size;
+ int off, off_hours, off_mins;
+
+ /* get the time */
+ lt = *localtime(&t);
+ size = strftime(time_str, TIME_STR_SIZE, "D:%Y%m%d%H%M%S", &lt);
+ /* expected format: "YYYYmmddHHMMSS" */
+ if (size == 0) {
+ /* unexpected, contents of time_str is undefined */
+ time_str[0] = '\0';
+ return;
+ }
+
+ /* correction for seconds: %S can be in range 00..61,
+ the PDF reference expects 00..59,
+ therefore we map "60" and "61" to "59" */
+ if (time_str[14] == '6') {
+ time_str[14] = '5';
+ time_str[15] = '9';
+ time_str[16] = '\0'; /* for safety */
+ }
+
+ /* get the time zone offset */
+ gmt = *gmtime(&t);
+
+ /* this calculation method was found in exim's tod.c */
+ off = 60*(lt.tm_hour - gmt.tm_hour) + lt.tm_min - gmt.tm_min;
+ if (lt.tm_year != gmt.tm_year) {
+ off += (lt.tm_year > gmt.tm_year) ? 1440 : -1440;
+ }
+ else if (lt.tm_yday != gmt.tm_yday) {
+ off += (lt.tm_yday > gmt.tm_yday) ? 1440 : -1440;
+ }
+
+ if (off == 0) {
+ time_str[size++] = 'Z';
+ time_str[size] = 0;
+ }
+ else {
+ off_hours = off/60;
+ off_mins = abs(off - off_hours*60);
+ sprintf(&time_str[size], "%+03i'%02d'", off_hours, off_mins);
+ }
+}
+
+void initstarttime() {
+ if (start_time == 0) {
+ start_time = time((time_t *) NULL);
+ makepdftime(start_time, start_time_str);
+ }
+}
+
+void printcreationdate() {
+ initstarttime();
+ pdf_printf("/CreationDate (%s)\n", start_time_str);
+}
+
+void getcreationdate()
+{
+ /* put creation date on top of string pool and update poolptr */
+ poolpointer out = poolptr;
+ unsigned char ch;
+ int len = strlen(start_time_str);
+
+ initstarttime();
+
+ if (poolptr + len >= poolsize) {
+ poolptr = poolsize;
+ /* error by str_toks that calls str_room(1) */
+ return;
+ }
+
+ memcpy(&strpool[poolptr], start_time_str, len);
+ poolptr += len;
+}
+
+void getfilemoddate(strnumber s) {
+ struct stat file_data;
+
+ char *file_name = kpse_find_tex(makecfilename(s));
+ if (file_name == NULL) {
+ return; /* empty string */
+ }
+
+ /* get file status */
+ if (stat(file_name, &file_data) == 0) {
+ int len;
+
+ makepdftime(file_data.st_mtime, time_str);
+ len = strlen(time_str);
+ if (poolptr + len >= poolsize) {
+ poolptr = poolsize;
+ /* error by str_toks that calls str_room(1) */
+ }
+ else {
+ memcpy(&strpool[poolptr], time_str, len);
+ poolptr += len;
+ }
+ }
+ /* else { errno contains error code } */
+
+ xfree(file_name);
+}
+
+void getfilesize(strnumber s) {
+ struct stat file_data;
+
+ char *file_name = kpse_find_tex(makecfilename(s));
+ if (file_name == NULL) {
+ return; /* empty string */
+ }
+
+ /* get file status */
+ if (stat(file_name, &file_data) == 0) {
+ int len;
+ char buf[20];
+
+ /* st_size has type off_t */
+ sprintf(buf, "%lu", (long unsigned int)file_data.st_size);
+ len = strlen(buf);
+ if (poolptr + len >= poolsize) {
+ poolptr = poolsize;
+ /* error by str_toks that calls str_room(1) */
+ }
+ else {
+ memcpy(&strpool[poolptr], buf, len);
+ poolptr += len;
+ }
+ }
+ /* else { errno contains error code } */
+
+ xfree(file_name);
+}
+
+#define DIGEST_SIZE 16
+#define FILE_BUF_SIZE 1024
+
+void getmd5sum(strnumber s, boolean file) {
+ md5_state_t state;
+ md5_byte_t digest[DIGEST_SIZE];
+ char outbuf[2 * DIGEST_SIZE + 1];
+ int len = 2 * DIGEST_SIZE;
+
+ if (file) {
+ char file_buf[FILE_BUF_SIZE];
+ int read = 0;
+ FILE *f;
+
+ char *file_name = kpse_find_tex(makecfilename(s));
+ if (file_name == NULL) {
+ return; /* empty string */
+ }
+ /* in case of error the empty string is returned,
+ no need for xfopen that aborts on error.
+ */
+ f = fopen(file_name, FOPEN_RBIN_MODE);
+ if (f == NULL) {
+ xfree(file_name);
+ return;
+ }
+ md5_init(&state);
+ while ((read = fread(&file_buf, sizeof(char),
+ FILE_BUF_SIZE, f)) > 0) {
+ md5_append(&state, (const md5_byte_t *)file_buf, read);
+ }
+ md5_finish(&state, digest);
+ fclose(f);
+
+ xfree(file_name);
+ }
+ else {
+ /* s contains the data */
+ md5_init(&state);
+ md5_append(&state,
+ (const md5_byte_t *)&strpool[strstart[s]],
+ strstart[s + 1] - strstart[s]);
+ md5_finish(&state, digest);
+ }
+
+ if (poolptr + len >= poolsize) {
+ /* error by str_toks that calls str_room(1) */
+ return;
+ }
+ convertStringToHexString((char*)digest, outbuf, DIGEST_SIZE);
+ memcpy(&strpool[poolptr], outbuf, len);
+ poolptr += len;
+}
+
+void getfiledump(strnumber s, int offset, int length) {
+ FILE *f;
+ int read;
+ poolpointer data_ptr;
+ poolpointer data_end;
+ char *file_name;
+
+ if (length == 0) {
+ /* empty result string */
+ return;
+ }
+
+ if (poolptr + 2 * length + 1 >= poolsize) {
+ /* no place for result */
+ poolptr = poolsize;
+ /* error by str_toks that calls str_room(1) */
+ return;
+ }
+
+ file_name = kpse_find_tex(makecfilename(s));
+ if (file_name == NULL) {
+ return; /* empty string */
+ }
+
+ /* read file data */
+ f = fopen(file_name, FOPEN_RBIN_MODE);
+ if (f == NULL) {
+ xfree(file_name);
+ return;
+ }
+ if (fseek(f, (long)offset, SEEK_SET) != 0) {
+ xfree(file_name);
+ return;
+ }
+ /* there is enough space in the string pool, the read
+ data are put in the upper half of the result, thus
+ the conversion to hex can be done without overwriting
+ unconverted bytes. Be aware that sprintf also appends
+ a nul byte at the end. */
+ data_ptr = poolptr + length;
+ read = fread(&strpool[data_ptr],
+ sizeof(char), length, f);
+ fclose(f);
+
+ /* convert to hex */
+ data_end = data_ptr + read;
+ for (; data_ptr < data_end; data_ptr++) {
+ sprintf(&strpool[poolptr], "%.2X",
+ (unsigned int)strpool[data_ptr]);
+ poolptr += 2;
+ }
+ xfree(file_name);
+}
+
+#define DEFAULT_SUB_MATCH_COUNT 10
+int sub_match_count = DEFAULT_SUB_MATCH_COUNT;
+regmatch_t *pmatch = NULL;
+char *match_string = NULL;
+
+void matchstrings(strnumber s, strnumber t, int subcount, boolean icase) {
+ regex_t preg;
+ int cflags = REG_EXTENDED;
+ int eflags = 0;
+ int ret;
+ char *str;
+
+ if (icase) {
+ cflags |= REG_ICASE;
+ }
+
+ if (poolptr + 10 >= poolsize) {
+ poolptr = poolsize;
+ return;
+ }
+
+ str = makecstring(s);
+ ret = regcomp(&preg, str, cflags);
+ if (ret != 0) {
+ int size = regerror(ret, &preg, NULL, 0);
+ str = xtalloc(size, char);
+ regerror(ret, &preg, str, size);
+ pdftex_warn("%s%s", "\\pdfmatch: ", str);
+ xfree(str);
+ strpool[poolptr++] = '-';
+ strpool[poolptr++] = '1';
+ }
+ else {
+ str = makecstring(t);
+ sub_match_count = ((subcount < 0) ?
+ DEFAULT_SUB_MATCH_COUNT : subcount);
+ xfree(pmatch);
+ if (sub_match_count > 0) {
+ pmatch = xtalloc(sub_match_count, regmatch_t);
+ }
+ ret = regexec(&preg, str, sub_match_count, pmatch, eflags);
+ xfree(match_string);
+ match_string = xstrdup(str);
+ if (ret == 0) {
+ strpool[poolptr++] = '1';
+ }
+ else { /* REG_NOMATCH */
+ strpool[poolptr++] = '0';
+ }
+ }
+
+ regfree(&preg);
+}
+
+void getmatch(int i) {
+ int size = 0;
+ int len = 0;
+
+ boolean found = i < sub_match_count
+ && match_string != NULL
+ && pmatch[i].rm_so >= 0
+ && i >= 0;
+
+ if (found) {
+ len = pmatch[i].rm_eo - pmatch[i].rm_so;
+ size = 20 + len;
+ /* 20: place for integer number and '->' */
+ }
+ else {
+ size = 4;
+ }
+
+ if (poolptr + size >= poolsize) {
+ poolptr = poolsize;
+ return;
+ }
+
+ if (found) {
+ sprintf(&strpool[poolptr], "%d", pmatch[i].rm_so);
+ poolptr += strlen(&strpool[poolptr]);
+ strpool[poolptr++] = '-';
+ strpool[poolptr++] = '>';
+ memcpy(&strpool[poolptr], &match_string[pmatch[i].rm_so], len);
+ poolptr += len;
+ return;
+ }
+
+ strpool[poolptr++] = '-';
+ strpool[poolptr++] = '1';
+ strpool[poolptr++] = '-';
+ strpool[poolptr++] = '>';
+}
+
+
+/* makecfilename
+ input/ouput same as makecstring:
+ input: string number
+ output: C string with quotes removed.
+*/
+char *makecfilename(strnumber s) {
+ char *name = makecstring(s);
+ char *p = name;
+ char *q = name;
+
+ while (*p) {
+ if (*p != '"')
+ *q++ = *p;
+ p++;
+ }
+ *q = '\0';
+ fprintf(stderr, " %s\n", name);
+ return name;
+}
diff --git a/Build/source/texk/web2c/pdftexdir/vadjust.ch b/Build/source/texk/web2c/pdftexdir/vadjust.ch
new file mode 100644
index 00000000000..09887ea01a8
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/vadjust.ch
@@ -0,0 +1,273 @@
+% WEB change file containing vadjust extension for pdfTeX
+%
+% Copyright (c) 1996-2004 Han Th\^e\llap{\raise 0.5ex\hbox{\'{}}} Th\`anh, <thanh@pdftex.org>
+%
+% This file is part of pdfTeX.
+%
+% pdfTeX 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.
+%
+% pdfTeX is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with pdfTeX; if not, write to the Free Software
+% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+%
+% $Id: vadjust.ch,v 1.2 2004/08/01 12:12:23 olaf Exp $
+
+@x [142] - pre-vadjust
+@d adjust_node=5 {|type| of an adjust node}
+@y
+@d adjust_node=5 {|type| of an adjust node}
+@d adjust_pre == subtype {pre-adjustment?}
+@#{|append_list| is used to append a list to |tail|}
+@d append_list(#) == begin link(tail) := link(#); append_list_end
+@d append_list_end(#) == tail := #; end
+
+@z
+
+@x [162] - pre-vadjust
+@d backup_head==mem_top-13 {head of token list built by |scan_keyword|}
+@d hi_mem_stat_min==mem_top-13 {smallest statically allocated word in
+ the one-word |mem|}
+@d hi_mem_stat_usage=14 {the number of one-word nodes always present}
+@y
+@d backup_head==mem_top-13 {head of token list built by |scan_keyword|}
+@d pre_adjust_head==mem_top-14 {head of pre-adjustment list returned by |hpack|}
+@d hi_mem_stat_min==mem_top-14 {smallest statically allocated word in
+ the one-word |mem|}
+@d hi_mem_stat_usage=15 {the number of one-word nodes always present}
+@z
+
+@x [197] - pre-vadjust
+begin print_esc("vadjust"); node_list_display(adjust_ptr(p)); {recursive call}
+@y
+begin print_esc("vadjust"); if adjust_pre(p) <> 0 then print(" pre ");
+node_list_display(adjust_ptr(p)); {recursive call}
+@z
+
+@x [649] - pre-vadjust
+if adjust_tail<>null then link(adjust_tail):=null;
+@y
+if adjust_tail<>null then link(adjust_tail):=null;
+if pre_adjust_tail<>null then link(pre_adjust_tail):=null;
+@z
+
+@x [655] - pre-vadjust
+@<Transfer node |p| to the adjustment list@>=
+begin while link(q)<>p do q:=link(q);
+if type(p)=adjust_node then
+ begin link(adjust_tail):=adjust_ptr(p);
+ while link(adjust_tail)<>null do adjust_tail:=link(adjust_tail);
+ p:=link(p); free_node(link(q),small_node_size);
+ end
+@y
+@<Glob...@>=
+@!pre_adjust_tail: pointer;
+
+@ @<Set init...@>=
+pre_adjust_tail := null;
+
+@ Materials in \.{\\vadjust} used with \.{pre} keyword will be appended to
+|pre_adjust_tail| instead of |adjust_tail|.
+
+@d update_adjust_list(#) == begin
+ link(#) := adjust_ptr(p);
+ while link(#) <> null do
+ # := link(#);
+end
+
+@<Transfer node |p| to the adjustment list@>=
+begin while link(q)<>p do q:=link(q);
+ if type(p) = adjust_node then begin
+ if adjust_pre(p) <> 0 then
+ update_adjust_list(pre_adjust_tail)
+ else
+ update_adjust_list(adjust_tail);
+ p := link(p); free_node(link(q), small_node_size);
+ end
+@z
+
+@x [770] - pre-vadjust
+@d align_stack_node_size=5 {number of |mem| words to save alignment states}
+@y
+@d align_stack_node_size=6 {number of |mem| words to save alignment states}
+@z
+
+@x [770] - pre-vadjust
+@!cur_head,@!cur_tail:pointer; {adjustment list pointers}
+@y
+@!cur_head,@!cur_tail:pointer; {adjustment list pointers}
+@!cur_pre_head,@!cur_pre_tail:pointer; {pre-adjustment list pointers}
+@z
+
+@x [771] - pre-vadjust
+cur_head:=null; cur_tail:=null;
+@y
+cur_head:=null; cur_tail:=null;
+cur_pre_head:=null; cur_pre_tail:=null;
+@z
+
+@x [772] - pre-vadjust
+info(p+4):=cur_head; link(p+4):=cur_tail;
+@y
+info(p+4):=cur_head; link(p+4):=cur_tail;
+info(p+5):=cur_pre_head; link(p+5):=cur_pre_tail;
+@z
+
+@x [771] - pre-vadjust
+cur_tail:=link(p+4); cur_head:=info(p+4);
+@y
+cur_tail:=link(p+4); cur_head:=info(p+4);
+cur_pre_tail:=link(p+5); cur_pre_head:=info(p+5);
+@z
+
+@x [786] - pre-vadjust
+cur_align:=link(preamble); cur_tail:=cur_head; init_span(cur_align);
+@y
+cur_align:=link(preamble); cur_tail:=cur_head; cur_pre_tail:=cur_pre_head;
+init_span(cur_align);
+@z
+
+@x [791] - pre-vadjust
+ begin adjust_tail:=cur_tail; u:=hpack(link(head),natural); w:=width(u);
+ cur_tail:=adjust_tail; adjust_tail:=null;
+ end
+@y
+ begin adjust_tail:=cur_tail; pre_adjust_tail:=cur_pre_tail;
+ u:=hpack(link(head),natural); w:=width(u);
+ cur_tail:=adjust_tail; adjust_tail:=null;
+ cur_pre_tail:=pre_adjust_tail; pre_adjust_tail:=null;
+ end
+@z
+
+@x [799] - pre-vadjust
+ pop_nest; append_to_vlist(p);
+ if cur_head<>cur_tail then
+ begin link(tail):=link(cur_head); tail:=cur_tail;
+ end;
+@y
+ pop_nest;
+ if cur_pre_head <> cur_pre_tail then
+ append_list(cur_pre_head)(cur_pre_tail);
+ append_to_vlist(p);
+ if cur_head <> cur_tail then
+ append_list(cur_head)(cur_tail);
+@z
+
+@x [888] - pre-vadjust
+append_to_vlist(just_box);
+if adjust_head<>adjust_tail then
+ begin link(tail):=link(adjust_head); tail:=adjust_tail;
+ end;
+adjust_tail:=null
+@y
+if pre_adjust_head <> pre_adjust_tail then
+ append_list(pre_adjust_head)(pre_adjust_tail);
+pre_adjust_tail := null;
+append_to_vlist(just_box);
+if adjust_head <> adjust_tail then
+ append_list(adjust_head)(adjust_tail);
+adjust_tail := null
+@z
+
+@x
+adjust_tail:=adjust_head;
+@y
+adjust_tail:=adjust_head;
+pre_adjust_tail := pre_adjust_head;
+@z
+
+@x [1076] - pre-vadjust
+ begin append_to_vlist(cur_box);
+ if adjust_tail<>null then
+ begin if adjust_head<>adjust_tail then
+ begin link(tail):=link(adjust_head); tail:=adjust_tail;
+ end;
+ adjust_tail:=null;
+ end;
+@y
+ begin
+ if pre_adjust_tail <> null then begin
+ if pre_adjust_head <> pre_adjust_tail then
+ append_list(pre_adjust_head)(pre_adjust_tail);
+ pre_adjust_tail := null;
+ end;
+ append_to_vlist(cur_box);
+ if adjust_tail <> null then begin
+ if adjust_head <> adjust_tail then
+ append_list(adjust_head)(adjust_tail);
+ adjust_tail := null;
+ end;
+@z
+
+@x [1085] - pre-vadjust
+adjusted_hbox_group: begin adjust_tail:=adjust_head; package(0);
+@y
+adjusted_hbox_group: begin adjust_tail:=adjust_head;
+ pre_adjust_tail:=pre_adjust_head; package(0);
+@z
+
+@x [1099] - pre-vadjust
+saved(0):=cur_val; incr(save_ptr);
+new_save_level(insert_group); scan_left_brace; normal_paragraph;
+push_nest; mode:=-vmode; prev_depth:=ignore_depth;
+end;
+@y
+saved(0) := cur_val;
+if (cur_cmd = vadjust) and scan_keyword("pre") then
+ saved(1) := 1
+else
+ saved(1) := 0;
+save_ptr := save_ptr + 2;
+new_save_level(insert_group); scan_left_brace; normal_paragraph;
+push_nest; mode:=-vmode; prev_depth:=ignore_depth;
+end;
+@z
+
+@x [1100] - pre-vadjust
+ d:=split_max_depth; f:=floating_penalty; unsave; decr(save_ptr);
+@y
+ d:=split_max_depth; f:=floating_penalty; unsave; save_ptr := save_ptr - 2;
+@z
+
+@x [1100] - pre-vadjust
+ subtype(tail):=0; {the |subtype| is not used}
+@y
+ adjust_pre(tail) := saved(1); {the |subtype| is used for |adjust_pre|}
+@z
+
+@x [1198] - pre-vadjust
+@!t:pointer; {tail of adjustment list}
+@y
+@!t:pointer; {tail of adjustment list}
+@!pre_t:pointer; {tail of pre-adjustment list}
+@z
+
+@x [1199] - pre-vadjust
+adjust_tail:=adjust_head; b:=hpack(p,natural); p:=list_ptr(b);
+t:=adjust_tail; adjust_tail:=null;@/
+@y
+adjust_tail:=adjust_head; pre_adjust_tail:=pre_adjust_head;
+b:=hpack(p,natural); p:=list_ptr(b);
+t:=adjust_tail; adjust_tail:=null;@/
+pre_t:=pre_adjust_tail; pre_adjust_tail:=null;@/
+@z
+
+@x [1205] - pre-vadjust
+if t<>adjust_head then {migrating material comes after equation number}
+ begin link(tail):=link(adjust_head); tail:=t;
+ end;
+@y
+if t<>adjust_head then {migrating material comes after equation number}
+ begin link(tail):=link(adjust_head); tail:=t;
+ end;
+if pre_t<>pre_adjust_head then
+ begin link(tail):=link(pre_adjust_head); tail:=pre_t;
+ end;
+@z
diff --git a/Build/source/texk/web2c/pdftexdir/vfpacket.c b/Build/source/texk/web2c/pdftexdir/vfpacket.c
new file mode 100644
index 00000000000..1f8f86b8d82
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/vfpacket.c
@@ -0,0 +1,116 @@
+/*
+Copyright (c) 1996-2002 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX 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.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/vfpacket.c#7 $
+*/
+
+#include "ptexlib.h"
+
+typedef struct {
+ internalfontnumber font;
+ char *dataptr;
+ int len;
+} packet_entry;
+
+/* define packet_ptr, packet_array & packet_limit */
+define_array(packet);
+
+typedef struct {
+ char **data;
+ int *len;
+ internalfontnumber font;
+} vf_entry;
+
+/* define vf_ptr, vf_array & vf_limit */
+define_array(vf);
+
+static char *packet_data_ptr;
+
+integer newvfpacket(internalfontnumber f)
+{
+ int i,
+ n = fontec[f] - fontbc[f] + 1;
+ alloc_array(vf, 1, SMALL_ARRAY_SIZE);
+ vf_ptr->len = xtalloc(n, int);
+ vf_ptr->data = xtalloc(n, char *);
+ for (i = 0; i < n; i++) {
+ vf_ptr->data[i] = NULL;
+ vf_ptr->len[i] = 0;
+ }
+ vf_ptr->font = f;
+ return vf_ptr++ - vf_array;
+}
+
+void storepacket(integer f, integer c, integer s)
+{
+ int l = strstart[s + 1] - strstart[s];
+ vf_array[vfpacketbase[f]].len[c - fontbc[f]] = l;
+ vf_array[vfpacketbase[f]].data[c - fontbc[f]] = xtalloc(l, char);
+ memcpy((void *)vf_array[vfpacketbase[f]].data[c - fontbc[f]],
+ (void *)(strpool + strstart[s]), (unsigned)l);
+}
+
+void pushpacketstate()
+{
+ alloc_array(packet, 1, SMALL_ARRAY_SIZE);
+ packet_ptr->font = f;
+ packet_ptr->dataptr = packet_data_ptr;
+ packet_ptr->len = vfpacketlength;
+ packet_ptr++;
+}
+
+void poppacketstate()
+{
+ if (packet_ptr == packet_array)
+ pdftex_fail("packet stack empty, impossible to pop");
+ packet_ptr--;
+ f = packet_ptr->font;
+ packet_data_ptr = packet_ptr->dataptr;
+ vfpacketlength = packet_ptr->len;
+}
+
+void startpacket(internalfontnumber f, integer c)
+{
+ packet_data_ptr = vf_array[vfpacketbase[f]].data[c - fontbc[f]];
+ vfpacketlength = vf_array[vfpacketbase[f]].len[c - fontbc[f]];
+}
+
+eightbits packetbyte()
+{
+ vfpacketlength--;
+ return *packet_data_ptr++;
+}
+
+void vf_free(void)
+{
+ vf_entry *v;
+ int n;
+ char **p;
+ if (vf_array != NULL) {
+ for (v = vf_array; v < vf_ptr; v++) {
+ xfree(v->len);
+ n = fontec[v->font] - fontec[v->font] + 1;
+ for (p = v->data; p - v->data < n ; p++)
+ xfree(*p);
+ xfree(v->data);
+ }
+ xfree(vf_array);
+ }
+ xfree(packet_array);
+}
diff --git a/Build/source/texk/web2c/pdftexdir/win32.mak b/Build/source/texk/web2c/pdftexdir/win32.mak
new file mode 100644
index 00000000000..1a0e5ba3a45
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/win32.mak
@@ -0,0 +1,71 @@
+################################################################################
+#
+# Makefile : Web2C / pdftexdir
+# Author : Fabrice Popineau <Fabrice.Popineau@supelec.fr>
+# Platform : Win32, Microsoft VC++ 6.0, depends upon fpTeX 0.5 sources
+# Time-stamp: <04/03/13 13:12:08 popineau>
+#
+################################################################################
+root_srcdir = ..\..\..
+!ifdef DEVELOPMENT
+INCLUDE=$(INCLUDE);$(root_srcdir)\texk.development
+!else
+INCLUDE=$(INCLUDE);$(root_srcdir)\texk
+!endif
+
+
+USE_XPDF = 1
+USE_ZLIB = 1
+USE_PNG = 1
+USE_JPEG = 1
+USE_TEX = 1
+USE_MD5 = 1
+USE_GNUW32 = 1
+USE_KPATHSEA = 1
+
+!include <msvc/common.mak>
+
+DEFS = -I.. -I$(top_srcdir) $(DEFS) -DMAKE_TEX_DLL -DHAVE_CONFIG_H -DpdfeTeX
+
+objects = $(objdir)\avl.obj $(objdir)\avlstuff.obj $(objdir)\epdf.obj \
+ $(objdir)\mapfile.obj \
+ $(objdir)\utils.obj $(objdir)\vfpacket.obj \
+ $(objdir)\pkin.obj $(objdir)\writefont.obj $(objdir)\writet1.obj \
+ $(objdir)\writet3.obj $(objdir)\writezip.obj $(objdir)\writeenc.obj \
+ $(objdir)\writettf.obj $(objdir)\writejpg.obj $(objdir)\writepng.obj \
+ $(objdir)\writeimg.obj \
+ $(objdir)\pdftoepdf.obj
+
+default: all
+
+all: $(objdir) libpdftoepdf $(objdir)\libpdf.lib
+
+$(objdir)\libpdf.lib: $(objdir) $(objects) $(md5lib)
+ $(archive) $(objects) $(md5lib)
+
+libpdftoepdf: $(objdir) $(objdir)\libpdftoepdf.lib
+
+$(objdir)\libpdftoepdf.lib: $(objdir)\pdftoepdf.obj $(xpdflib)
+ $(archive) $(objdir)\pdftoepdf.obj $(xpdflib)
+
+$(objdir)\pdftoepdf.obj: pdftoepdf.cc # $(xpdf)
+
+ptexlib.h: ..\pdftexd.h
+
+..\pdftexd.h:
+ -@echo $(verbose) & ( \
+ pushd .. & $(make) pdftexd.h & popd \
+ )
+
+!include <msvc/config.mak>
+!include <msvc/install.mak>
+
+!include <msvc/clean.mak>
+!include <msvc/rdepend.mak>
+
+!include "./depend.mak"
+
+#
+# Local Variables:
+# mode: makefile
+# End:
diff --git a/Build/source/texk/web2c/pdftexdir/writeenc.c b/Build/source/texk/web2c/pdftexdir/writeenc.c
new file mode 100644
index 00000000000..7963403ec7e
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/writeenc.c
@@ -0,0 +1,145 @@
+/*
+Copyright (c) 1996-2005 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX 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.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/writeenc.c#13 $
+
+source code indentation by "indent -kr -nut"
+*/
+
+#include "ptexlib.h"
+#include "avlstuff.h"
+
+static const char perforce_id[] =
+ "$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/writeenc.c#13 $";
+
+void read_enc(enc_entry * e)
+{
+ assert(e != NULL);
+ if (e->loaded)
+ return;
+ load_enc(e->name, e->glyph_names);
+ e->loaded = true;
+}
+
+/* write_enc is used to write either external encoding (given in map file) or
+ * internal encoding (read from the font file); when glyph_names is NULL
+ * the 2nd argument is a pointer to the encoding entry; otherwise the 3rd is
+ * the object number of the Encoding object
+ */
+void write_enc(char **glyph_names, enc_entry * e, integer eobjnum)
+{
+ boolean is_notdef;
+ int i;
+ char **g;
+ if (glyph_names == NULL) {
+ assert(e != NULL);
+ if (e->objnum != 0) /* the encoding has been written already */
+ return;
+ pdfnewdict(0, 0);
+ e->objnum = objptr;
+ g = e->glyph_names;
+ } else {
+ pdfbegindict(eobjnum);
+ g = glyph_names;
+ }
+ pdf_printf("/Type /Encoding\n/Differences [ 0 /%s", g[0]);
+ is_notdef = (g[0] == notdef);
+ for (i = 1; i <= MAX_CHAR_CODE; i++) {
+ if (g[i] == notdef) {
+ if (!is_notdef) {
+ pdf_printf(" %i/%s", i, notdef);
+ is_notdef = true;
+ }
+ } else {
+ if (is_notdef) {
+ pdf_printf(" %i", i);
+ is_notdef = false;
+ }
+ pdf_printf("/%s", g[i]);
+ }
+ }
+ pdf_puts("]\n");
+ pdfenddict();
+}
+
+/**********************************************************************/
+/* All encoding entries go into AVL tree for fast search by name. */
+
+struct avl_table *enc_tree = NULL;
+
+/* AVL sort enc_entry into enc_tree by name */
+
+static int comp_enc_entry(const void *pa, const void *pb, void *p)
+{
+ return strcmp(((const enc_entry *) pa)->name,
+ ((const enc_entry *) pb)->name);
+}
+
+enc_entry *add_enc(char *s)
+{
+ int i;
+ enc_entry tmp, *p;
+ void **aa;
+
+ assert(s != NULL);
+ if (enc_tree == NULL) {
+ enc_tree = avl_create(comp_enc_entry, NULL, &avl_xallocator);
+ assert(enc_tree != NULL);
+ }
+ tmp.name = s;
+ p = (enc_entry *) avl_find(enc_tree, &tmp);
+ if (p != NULL) /* encoding already registered */
+ return p;
+ p = xtalloc(1, enc_entry);
+ p->loaded = false;
+ p->name = xstrdup(s);
+ p->objnum = 0;
+ p->glyph_names = xtalloc(MAX_CHAR_CODE + 1, char *);
+ for (i = 0; i <= MAX_CHAR_CODE; i++)
+ p->glyph_names[i] = (char *) notdef;
+ aa = avl_probe(enc_tree, p);
+ assert(aa != NULL);
+ return p;
+}
+
+/**********************************************************************/
+/* cleaning up... */
+
+static void destroy_enc_entry(void *pa, void *pb)
+{
+ enc_entry *p;
+ int i;
+
+ p = (enc_entry *) pa;
+ xfree(p->name);
+ if (p->glyph_names != NULL)
+ for (i = 0; i <= MAX_CHAR_CODE; i++)
+ if (p->glyph_names[i] != notdef)
+ xfree(p->glyph_names[i]);
+ xfree(p->glyph_names);
+ xfree(p);
+}
+
+void enc_free()
+{
+ if (enc_tree != NULL)
+ avl_destroy(enc_tree, destroy_enc_entry);
+}
+
+/**********************************************************************/
diff --git a/Build/source/texk/web2c/pdftexdir/writefont.c b/Build/source/texk/web2c/pdftexdir/writefont.c
new file mode 100644
index 00000000000..abb0074bde0
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/writefont.c
@@ -0,0 +1,318 @@
+/*
+Copyright (c) 1996-2002 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX 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.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/writefont.c#15 $
+*/
+
+#include "ptexlib.h"
+
+static const char perforce_id[] =
+ "$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/writefont.c#15 $";
+
+key_entry font_keys[FONT_KEYS_NUM] = {
+ {"Ascent", "Ascender", 0, false},
+ {"CapHeight", "CapHeight", 0, false},
+ {"Descent", "Descender", 0, false},
+ {"FontName", "FontName", 0, false},
+ {"ItalicAngle", "ItalicAngle", 0, false},
+ {"StemV", "StdVW", 0, false},
+ {"XHeight", "XHeight", 0, false},
+ {"FontBBox", "FontBBox", 0, false},
+ {"", "", 0, false},
+ {"", "", 0, false},
+ {"", "", 0, false}
+};
+
+internalfontnumber tex_font;
+boolean fontfile_found;
+boolean is_otf_font;
+boolean write_ttf_glyph_names;
+char fontname_buf[FONTNAME_BUF_SIZE];
+
+static int first_char, last_char;
+static integer char_widths[MAX_CHAR_CODE + 1];
+static boolean write_fontfile_only;
+static int char_widths_objnum,
+ encoding_objnum;
+static char **cur_glyph_names;
+
+static void print_key(integer code, integer v)
+{
+ pdf_printf("/%s ", font_keys[code].pdfname);
+ if (font_keys[code].valid)
+ pdf_printf("%i", (int)font_keys[code].value);
+ else
+ pdf_printf("%i", (int)dividescaled(v, pdffontsize[tex_font], 3));
+ pdf_puts("\n");
+}
+
+static void print_italic_angle()
+{
+ pdf_printf("/%s ", font_keys[ITALIC_ANGLE_CODE].pdfname);
+ if (font_keys[ITALIC_ANGLE_CODE].valid)
+ pdf_printf("%g", font_keys[ITALIC_ANGLE_CODE].value);
+ else
+ pdf_printf("%g", -atan(getslant(tex_font)/65536.0)*(180/M_PI));
+ pdf_puts("\n");
+}
+
+static integer getstemv(void)
+{
+ return getcharwidth(tex_font, '.')/3;
+}
+
+static void getbbox(void)
+{
+ font_keys[FONTBBOX1_CODE].value = 0;
+ font_keys[FONTBBOX2_CODE].value =
+ dividescaled(-getchardepth(tex_font, 'y'), pdffontsize[tex_font], 3);
+ font_keys[FONTBBOX3_CODE].value =
+ dividescaled(getquad(tex_font), pdffontsize[tex_font], 3);
+ font_keys[FONTBBOX4_CODE].value =
+ dividescaled(getcharheight(tex_font, 'H'), pdffontsize[tex_font], 3);
+}
+
+static void get_char_widths(void)
+{
+ int i;
+ for (i = 0; i <= MAX_CHAR_CODE; i++) {
+ if (i < fontbc[tex_font] || i > fontec[tex_font])
+ char_widths[i] = 0;
+ else
+ char_widths[i] = getcharwidth(tex_font, i);
+ }
+ for (i = fontbc[tex_font]; i <= 32; i++)
+ char_widths[pdfcharmap[tex_font][i]] = char_widths[i];
+ for (i = fontbc[tex_font]; i <= MAX_CHAR_CODE; i++)
+ if (pdfcharmarked(tex_font, i))
+ break;
+ first_char = i;
+ for (i = MAX_CHAR_CODE; i > first_char; i--)
+ if (pdfcharmarked(tex_font, i))
+ break;
+ last_char = i;
+ if ((first_char > last_char) ||
+ (first_char == last_char && !pdfcharmarked(tex_font, first_char))) {
+ write_fontfile_only = true; /* the font is used in PDF images only */
+ return;
+ }
+ for (i = first_char; i <= last_char; i++)
+ if (pdfcharmarked(tex_font, i))
+ char_widths[i] = dividescaled(char_widths[i],
+ pdffontsize[tex_font], 3);
+ else
+ char_widths[i] = 0;
+}
+
+static void write_char_widths(void)
+{
+ int i;
+ pdfbeginobj(char_widths_objnum);
+ pdf_puts("[");
+ for (i = first_char; i <= last_char; i++)
+ pdf_printf("%i ", char_widths[i]);
+ pdf_puts("]\n");
+ pdfendobj();
+}
+
+static void write_fontname(boolean as_reference)
+{
+ if (as_reference && fm_cur->fn_objnum != 0) {
+ pdf_printf("%i 0 R\n", (int)fm_cur->fn_objnum);
+ return;
+ }
+ pdf_puts("/");
+ if (fm_cur->subset_tag != NULL)
+ pdf_printf("%s+", fm_cur->subset_tag);
+ if (font_keys[FONTNAME_CODE].valid)
+ pdf_printf("%s", fontname_buf);
+ else if (fm_cur->ps_name != NULL)
+ pdf_printf("%s", fm_cur->ps_name);
+ else
+ pdf_printf("%s", fm_cur->tfm_name);
+ pdf_puts("\n");
+}
+
+static void write_fontobj(integer font_objnum)
+{
+ pdfbegindict(font_objnum);
+ pdf_puts("/Type /Font\n");
+ pdf_printf("/Subtype /%s\n", is_truetype(fm_cur) ? "TrueType" : "Type1");
+ if (encoding_objnum != 0)
+ pdf_printf("/Encoding %i 0 R\n", (int)encoding_objnum);
+ if (pdffontattr[tex_font] != getnullstr()) {
+ pdfprint(pdffontattr[tex_font]);
+ pdf_puts("\n");
+ }
+ if (no_font_desc(fm_cur)) {
+ pdf_printf("/BaseFont /%s\n", fm_cur->ps_name);
+ pdfenddict();
+ return;
+ }
+ char_widths_objnum = pdfnewobjnum();
+ pdf_printf("/FirstChar %i\n/LastChar %i\n/Widths %i 0 R\n",
+ first_char, last_char, char_widths_objnum);
+ pdf_printf("/BaseFont ");
+ write_fontname(true);
+ if (fm_cur->fd_objnum == 0)
+ fm_cur->fd_objnum = pdfnewobjnum();
+ pdf_printf("/FontDescriptor %i 0 R\n", fm_cur->fd_objnum);
+ pdfenddict();
+}
+
+static void write_fontfile(void)
+{
+ int i;
+ for (i = 0; i < FONT_KEYS_NUM; i++)
+ font_keys[i].valid = false;
+ fontfile_found = false;
+ is_otf_font = false;
+ if (is_truetype(fm_cur))
+ writettf();
+ else
+ writet1();
+ if (!fontfile_found || !is_included(fm_cur))
+ return;
+ if (fm_cur->ff_objnum == 0)
+ pdftex_fail("font file object number for `%s' not initialized",
+ fm_cur->tfm_name);
+ pdfbegindict(fm_cur->ff_objnum); /* font file stream */
+ if (is_truetype(fm_cur))
+ pdf_printf("/Length1 %i\n", (int)ttf_length);
+ else if (is_otf_font)
+ pdf_printf("/Subtype /Type1C\n");
+ else
+ pdf_printf("/Length1 %i\n/Length2 %i\n/Length3 %i\n",
+ (int)t1_length1, (int)t1_length2, (int)t1_length3);
+ pdfbeginstream();
+ fb_flush();
+ pdfendstream();
+}
+
+static void write_fontdescriptor(void)
+{
+ int i;
+ pdfbegindict(fm_cur->fd_objnum); /* font descriptor */
+ print_key(ASCENT_CODE, getcharheight(tex_font, 'h'));
+ print_key(CAPHEIGHT_CODE, getcharheight(tex_font, 'H'));
+ print_key(DESCENT_CODE, -getchardepth(tex_font, 'y'));
+ pdf_printf("/FontName ");
+ write_fontname(true);
+ print_italic_angle();
+ print_key(STEMV_CODE, getstemv());
+ print_key(XHEIGHT_CODE, getxheight(tex_font));
+ if (!font_keys[FONTBBOX1_CODE].valid) {
+ getbbox();
+ }
+ pdf_printf("/%s [%i %i %i %i]\n",
+ font_keys[FONTBBOX1_CODE].pdfname,
+ (int)font_keys[FONTBBOX1_CODE].value,
+ (int)font_keys[FONTBBOX2_CODE].value,
+ (int)font_keys[FONTBBOX3_CODE].value,
+ (int)font_keys[FONTBBOX4_CODE].value);
+ if (!fontfile_found && fm_cur->flags == 4)
+ pdf_puts("/Flags 34\n"); /* assumes a roman sans serif font */
+ else
+ pdf_printf("/Flags %i\n", (int)fm_cur->flags);
+ if (is_included(fm_cur) && fontfile_found) {
+ if (is_subsetted(fm_cur) && !is_truetype(fm_cur)) {
+ cur_glyph_names = t1_glyph_names;
+ pdf_puts("/CharSet (");
+ for (i = 0; i <= MAX_CHAR_CODE; i++)
+ if (pdfcharmarked(tex_font, i) && cur_glyph_names[i] != notdef)
+ pdf_printf("/%s", cur_glyph_names[i]);
+ pdf_puts(")\n");
+ }
+ if (is_truetype(fm_cur))
+ pdf_printf("/FontFile2 %i 0 R\n", fm_cur->ff_objnum);
+ else if (is_otf_font)
+ pdf_printf("/FontFile3 %i 0 R\n", fm_cur->ff_objnum);
+ else
+ pdf_printf("/FontFile %i 0 R\n", fm_cur->ff_objnum);
+ }
+ pdfenddict();
+}
+
+void dopdffont(integer font_objnum, internalfontnumber f)
+{
+ int i;
+ tex_font = f;
+ cur_glyph_names = NULL;
+ encoding_objnum = 0;
+ write_ttf_glyph_names = false;
+ write_fontfile_only = false;
+ if (pdffontmap[tex_font] == NULL)
+ pdftex_fail("pdffontmap not initialized for font %s",
+ makecstring(fontname[tex_font]));
+ if (hasfmentry(tex_font))
+ fm_cur = (fm_entry *) pdffontmap[tex_font];
+ else
+ fm_cur = NULL;
+ if (fm_cur == NULL || (fm_cur->ps_name == NULL && fm_cur->ff_name == NULL)) {
+ writet3(font_objnum, tex_font);
+ return;
+ }
+
+ get_char_widths(); /* update char widths; also check whether this font is
+ used in embedded PDF only; if so then set
+ write_fontfile_only to true */
+
+ if (!write_fontfile_only) { /* encoding vector needed */
+ if ((is_reencoded(fm_cur))) {
+ read_enc(fm_cur->encoding);
+ if (!is_truetype(fm_cur)) {
+ write_enc(NULL, fm_cur->encoding, 0);
+ encoding_objnum = (fm_cur->encoding)->objnum;
+ }
+ else
+ write_ttf_glyph_names = true;
+ }
+ else if (is_fontfile(fm_cur) && !is_truetype(fm_cur)) {
+ encoding_objnum = pdfnewobjnum();
+ }
+ }
+ if (is_included(fm_cur))
+ write_fontfile();
+ if (fm_cur->fn_objnum != 0) {
+ pdfbeginobj(fm_cur->fn_objnum);
+ write_fontname(false);
+ pdfendobj();
+ }
+ if (!write_fontfile_only)
+ write_fontobj(font_objnum);
+ if (no_font_desc(fm_cur))
+ return;
+ if (!write_fontfile_only) {
+ write_fontdescriptor();
+ write_char_widths();
+ }
+ if (cur_glyph_names == t1_builtin_glyph_names) {
+ if (!write_fontfile_only) {
+ for (i = 0; i <= MAX_CHAR_CODE; i++)
+ if (!pdfcharmarked(tex_font, i) && cur_glyph_names[i] != notdef) {
+ xfree(cur_glyph_names[i]);
+ cur_glyph_names[i] = (char*) notdef;
+ }
+ write_enc(cur_glyph_names, NULL, encoding_objnum);
+ }
+ for (i = 0; i <= MAX_CHAR_CODE; i++)
+ if (cur_glyph_names[i] != notdef)
+ xfree(cur_glyph_names[i]);
+ }
+}
diff --git a/Build/source/texk/web2c/pdftexdir/writeimg.c b/Build/source/texk/web2c/pdftexdir/writeimg.c
new file mode 100644
index 00000000000..397e5fba7e0
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/writeimg.c
@@ -0,0 +1,354 @@
+/*
+Copyright (c) 1996-2002, 2005 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX 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.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/writeimg.c#18 $
+*/
+
+#include "ptexlib.h"
+#include "image.h"
+#include <kpathsea/c-auto.h>
+#include <kpathsea/c-memstr.h>
+
+static const char perforce_id[] =
+ "$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/writeimg.c#18 $";
+
+#define bp2int(p) round(p*(onehundredbp/100.0))
+
+/* define image_ptr, image_array & image_limit */
+define_array(image);
+
+float epdf_width;
+float epdf_height;
+float epdf_orig_x;
+float epdf_orig_y;
+integer epdf_selected_page;
+integer epdf_num_pages;
+integer epdf_page_box;
+integer epdf_always_use_pdf_pagebox;
+void *epdf_doc;
+
+static integer new_image_entry(void)
+{
+ alloc_array(image, 1, SMALL_BUF_SIZE);
+ image_ptr->image_type = IMAGE_TYPE_NONE;
+ image_ptr->color_type = 0;
+ image_ptr->num_pages = 0;
+ image_ptr->x_res = 0;
+ image_ptr->y_res = 0;
+ image_ptr->width = 0;
+ image_ptr->height = 0;
+ image_ptr->colorspace_ref = 0;
+ return image_ptr++ - image_array;
+}
+
+integer imagecolor(integer img)
+{
+ return img_color(img);
+}
+
+integer imagewidth(integer img)
+{
+ return img_width(img);
+}
+
+integer imageheight(integer img)
+{
+ return img_height(img);
+}
+
+integer imagexres(integer img)
+{
+ return img_xres(img);
+}
+
+integer imageyres(integer img)
+{
+ return img_yres(img);
+}
+
+boolean ispdfimage(integer img)
+{
+ return img_type(img) == IMAGE_TYPE_PDF;
+}
+
+boolean checkimageb(integer procset)
+{
+ return procset & IMAGE_COLOR_B;
+}
+
+boolean checkimagec(integer procset)
+{
+ return procset & IMAGE_COLOR_C;
+}
+
+boolean checkimagei(integer procset)
+{
+ return procset & IMAGE_COLOR_I;
+}
+
+void updateimageprocset(integer img)
+{
+ pdfimageprocset |= img_color(img);
+}
+
+integer epdforigx(integer img)
+{
+ return pdf_ptr(img)->orig_x;
+}
+
+integer epdforigy(integer img)
+{
+ return pdf_ptr(img)->orig_y;
+}
+
+integer imagepages(integer img)
+{
+ return img_pages(img);
+}
+
+integer imagecolordepth(integer img)
+{
+ switch (img_type(img)) {
+ case IMAGE_TYPE_PNG:
+ return png_info(img)->bit_depth;
+ case IMAGE_TYPE_JPG:
+ return jpg_ptr(img)->bits_per_component;
+ case IMAGE_TYPE_PDF:
+ return 0;
+ default:
+ pdftex_fail("unknown type of image");
+ }
+}
+
+/*
+ Patch ImageTypeDetection 2003/02/08 by Heiko Oberdiek.
+
+ Function "readimage" performs some basic initializations.
+ Then it looks at the file extension to determine the
+ image type and calls specific code/functions.
+ The main disadvantage is that standard file extensions
+ have to be used, otherwise pdfTeX is not able to detect
+ the correct image type.
+
+ The patch now looks at the file header first regardless of
+ the file extension. This is implemented in function
+ "checktypebyheader". If this check fails, the traditional
+ test of standard file extension is tried, done in function
+ "checktypebyextension".
+
+ Magic headers:
+
+ * "PNG (Portable Network Graphics) Specification", Version 1.2
+ (http://www.libpng.org/pub/png):
+
+ | 3.1. PNG file signature
+ |
+ | The first eight bytes of a PNG file always contain the following
+ | (decimal) values:
+ |
+ | 137 80 78 71 13 10 26 10
+
+ Translation to C: "\x89PNG\r\n\x1A\n"
+
+ * "JPEG File Interchange Format", Version 1.02:
+
+ | o you can identify a JFIF file by looking for the following
+ | sequence: X'FF', SOI X'FF', APP0, <2 bytes to be skipped>,
+ | "JFIF", X'00'.
+
+ Function "checktypebyheader" only looks at the first two bytes:
+ "\xFF\xD8"
+
+ * "PDF Reference", third edition:
+ * The first line should contain "%PDF-1.0" until "%PDF-1.4"
+ (section 3.4.1 "File Header").
+ * The "implementation notes" say:
+
+ | 3.4.1, File Header
+ | 12. Acrobat viewers require only that the header appear
+ | somewhere within the first 1024 bytes of the file.
+ | 13. Acrobat viewers will also accept a header of the form
+ | %!PS-Adobe-N.n PDF-M.m
+
+ The check in function "checktypebyheader" only implements
+ the first issue. The implementation notes are not considered.
+ Therefore files with garbage at start of file must have the
+ standard extension.
+
+ Functions "checktypebyheader" and "checktypebyextension":
+ img_type(img) is set to IMAGE_TYPE_NONE by new_image_entry().
+ Both functions tries to detect a type and set img_type(img).
+ Thus a value other than IMAGE_TYPE_NONE indicates that a
+ type is found.
+*/
+
+#define HEADER_JPG "\xFF\xD8"
+#define HEADER_PNG "\x89PNG\r\n\x1A\n"
+#define HEADER_PDF "%PDF-1."
+#define MAX_HEADER (sizeof(HEADER_PNG)-1)
+static void checktypebyheader(integer img)
+{
+ int i;
+ FILE *file = NULL;
+ char header[MAX_HEADER];
+
+ if (img_type(img) != IMAGE_TYPE_NONE) /* nothing to do */
+ return;
+
+ /* read the header */
+ file = xfopen(img_name(img), FOPEN_RBIN_MODE);
+ for (i=0; i<MAX_HEADER; i++) {
+ header[i] = xgetc(file);
+ if (feof(file))
+ pdftex_fail("reading image file failed");
+ }
+ xfclose(file, img_name(img));
+
+ /* tests */
+ if (strncmp(header, HEADER_JPG, sizeof(HEADER_JPG)-1) == 0)
+ img_type(img) = IMAGE_TYPE_JPG;
+ else if (strncmp(header, HEADER_PNG, sizeof(HEADER_PNG)-1) == 0)
+ img_type(img) = IMAGE_TYPE_PNG;
+ else if (strncmp(header, HEADER_PDF, sizeof(HEADER_PDF)-1) == 0)
+ img_type(img) = IMAGE_TYPE_PDF;
+}
+
+static void checktypebyextension(integer img)
+{
+ char *image_suffix;
+
+ if (img_type(img) != IMAGE_TYPE_NONE) /* nothing to do */
+ return;
+ /* tests */
+ if ((image_suffix = strrchr(cur_file_name, '.')) == 0)
+ img_type(img) = IMAGE_TYPE_NONE;
+ else if (strcasecmp(image_suffix, ".pdf") == 0)
+ img_type(img) = IMAGE_TYPE_PDF;
+ else if (strcasecmp(image_suffix, ".png") == 0)
+ img_type(img) = IMAGE_TYPE_PNG;
+ else if (strcasecmp(image_suffix, ".jpg") == 0 ||
+ strcasecmp(image_suffix, ".jpeg") == 0)
+ img_type(img) = IMAGE_TYPE_JPG;
+}
+
+integer readimage(strnumber s, integer page_num, strnumber page_name, integer colorspace,
+ integer pdfversion, integer pdfforcepagebox,
+ integer pdfinclusionerrorlevel)
+{
+ char *dest = NULL;
+ integer img = new_image_entry();
+ img_colorspace_ref(img) = colorspace;
+
+ /* need to allocate new string as makecstring's buffer is
+ already used by cur_file_name */
+ if (page_name != 0)
+ dest = xstrdup(makecstring(page_name));
+ cur_file_name = makecfilename(s);
+ img_name(img) = kpse_find_file(cur_file_name, kpse_tex_format, true);
+ if (img_name(img) == NULL)
+ pdftex_fail("cannot find image file");
+ /* kpse_find_file perhaps changed the file name */
+ cur_file_name = img_name(img);
+ /* type checks */
+ checktypebyheader(img);
+ checktypebyextension(img);
+ /* read image */
+ switch (img_type(img)) {
+ case IMAGE_TYPE_PDF:
+ pdf_ptr(img) = xtalloc(1, pdf_image_struct);
+ pdf_ptr(img)->page_box = pdflastpdfboxspec;
+ pdf_ptr(img)->always_use_pdfpagebox = pdfforcepagebox;
+ page_num = read_pdf_info(img_name(img), dest, page_num,
+ pdfversion, pdfforcepagebox,
+ pdfinclusionerrorlevel);
+ img_width(img) = bp2int(epdf_width);
+ img_height(img) = bp2int(epdf_height);
+ img_pages(img) = epdf_num_pages;
+ pdf_ptr(img)->orig_x = bp2int(epdf_orig_x);
+ pdf_ptr(img)->orig_y = bp2int(epdf_orig_y);
+ pdf_ptr(img)->selected_page = page_num;
+ pdf_ptr(img)->doc = epdf_doc;
+ break;
+ case IMAGE_TYPE_PNG:
+ img_pages(img) = 1;
+ read_png_info(img);
+ break;
+ case IMAGE_TYPE_JPG:
+ jpg_ptr(img) = xtalloc(1, JPG_IMAGE_INFO);
+ img_pages(img) = 1;
+ read_jpg_info(img);
+ break;
+ default:
+ pdftex_fail("unknown type of image");
+ }
+ xfree(dest);
+ cur_file_name = NULL;
+ return img;
+}
+
+void writeimage(integer img)
+{
+ cur_file_name = img_name(img);
+ tex_printf(" <%s", img_name(img));
+ switch (img_type(img)) {
+ case IMAGE_TYPE_PNG:
+ write_png(img);
+ break;
+ case IMAGE_TYPE_JPG:
+ write_jpg(img);
+ break;
+ case IMAGE_TYPE_PDF:
+ epdf_doc = pdf_ptr(img)->doc;
+ epdf_selected_page = pdf_ptr(img)->selected_page;
+ epdf_page_box = pdf_ptr(img)->page_box;
+ epdf_always_use_pdf_pagebox = pdf_ptr(img)->always_use_pdfpagebox;
+ write_epdf();
+ break;
+ default:
+ pdftex_fail("unknown type of image");
+ }
+ tex_printf(">");
+ cur_file_name = NULL;
+}
+
+void deleteimage(integer img)
+{
+ switch (img_type(img)) {
+ case IMAGE_TYPE_PDF:
+ epdf_doc = pdf_ptr(img)->doc;
+ epdf_delete();
+ break;
+ case IMAGE_TYPE_PNG:
+ xfclose(png_ptr(img)->io_ptr, cur_file_name);
+ png_destroy_read_struct(&(png_ptr(img)), &(png_info(img)), NULL);
+ break;
+ case IMAGE_TYPE_JPG:
+ xfclose(jpg_ptr(img)->file, cur_file_name);
+ break;
+ default:
+ pdftex_fail("unknown type of image");
+ }
+ xfree(img_name(img));
+ return;
+}
+
+void img_free()
+{
+ xfree(image_array);
+}
diff --git a/Build/source/texk/web2c/pdftexdir/writejpg.c b/Build/source/texk/web2c/pdftexdir/writejpg.c
new file mode 100644
index 00000000000..1b01737e4e5
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/writejpg.c
@@ -0,0 +1,227 @@
+/*
+Copyright (c) 1996-2002 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX 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.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/writejpg.c#10 $
+*/
+
+#include "ptexlib.h"
+#include "image.h"
+
+#define JPG_GRAY 1 /* Gray color space, use /DeviceGray */
+#define JPG_RGB 3 /* RGB color space, use /DeviceRGB */
+#define JPG_CMYK 4 /* CMYK color space, use /DeviceCMYK */
+
+typedef enum { /* JPEG marker codes */
+ M_SOF0 = 0xc0, /* baseline DCT */
+ M_SOF1 = 0xc1, /* extended sequential DCT */
+ M_SOF2 = 0xc2, /* progressive DCT */
+ M_SOF3 = 0xc3, /* lossless (sequential) */
+
+ M_SOF5 = 0xc5, /* differential sequential DCT */
+ M_SOF6 = 0xc6, /* differential progressive DCT */
+ M_SOF7 = 0xc7, /* differential lossless */
+
+ M_JPG = 0xc8, /* JPEG extensions */
+ M_SOF9 = 0xc9, /* extended sequential DCT */
+ M_SOF10 = 0xca, /* progressive DCT */
+ M_SOF11 = 0xcb, /* lossless (sequential) */
+
+ M_SOF13 = 0xcd, /* differential sequential DCT */
+ M_SOF14 = 0xce, /* differential progressive DCT */
+ M_SOF15 = 0xcf, /* differential lossless */
+
+ M_DHT = 0xc4, /* define Huffman tables */
+
+ M_DAC = 0xcc, /* define arithmetic conditioning table */
+
+ M_RST0 = 0xd0, /* restart */
+ M_RST1 = 0xd1, /* restart */
+ M_RST2 = 0xd2, /* restart */
+ M_RST3 = 0xd3, /* restart */
+ M_RST4 = 0xd4, /* restart */
+ M_RST5 = 0xd5, /* restart */
+ M_RST6 = 0xd6, /* restart */
+ M_RST7 = 0xd7, /* restart */
+
+ M_SOI = 0xd8, /* start of image */
+ M_EOI = 0xd9, /* end of image */
+ M_SOS = 0xda, /* start of scan */
+ M_DQT = 0xdb, /* define quantization tables */
+ M_DNL = 0xdc, /* define number of lines */
+ M_DRI = 0xdd, /* define restart interval */
+ M_DHP = 0xde, /* define hierarchical progression */
+ M_EXP = 0xdf, /* expand reference image(s) */
+
+ M_APP0 = 0xe0, /* application marker, used for JFIF */
+ M_APP1 = 0xe1, /* application marker */
+ M_APP2 = 0xe2, /* application marker */
+ M_APP3 = 0xe3, /* application marker */
+ M_APP4 = 0xe4, /* application marker */
+ M_APP5 = 0xe5, /* application marker */
+ M_APP6 = 0xe6, /* application marker */
+ M_APP7 = 0xe7, /* application marker */
+ M_APP8 = 0xe8, /* application marker */
+ M_APP9 = 0xe9, /* application marker */
+ M_APP10 = 0xea, /* application marker */
+ M_APP11 = 0xeb, /* application marker */
+ M_APP12 = 0xec, /* application marker */
+ M_APP13 = 0xed, /* application marker */
+ M_APP14 = 0xee, /* application marker, used by Adobe */
+ M_APP15 = 0xef, /* application marker */
+
+ M_JPG0 = 0xf0, /* reserved for JPEG extensions */
+ M_JPG13 = 0xfd, /* reserved for JPEG extensions */
+ M_COM = 0xfe, /* comment */
+
+ M_TEM = 0x01, /* temporary use */
+
+ M_ERROR = 0x100 /* dummy marker, internal use only */
+} JPEG_MARKER;
+
+static JPG_UINT16 read2bytes(FILE *f)
+{
+ int c = xgetc(f);
+ return (c << 8) + xgetc(f);
+}
+
+void read_jpg_info(integer img)
+{
+ int i;
+ char jpg_id[]="JFIF";
+ int units=0;
+ img_xres(img)=img_yres(img)=0;
+ jpg_ptr(img)->file = xfopen(img_name(img), FOPEN_RBIN_MODE);
+ xfseek(jpg_ptr(img)->file,0,SEEK_END,cur_file_name);
+ jpg_ptr(img)->length=xftell(jpg_ptr(img)->file,cur_file_name);
+ xfseek(jpg_ptr(img)->file,0,SEEK_SET,cur_file_name);
+ if(read2bytes(jpg_ptr(img)->file)!=0xFFD8)
+ pdftex_fail("reading JPEG image failed");
+
+ if(read2bytes(jpg_ptr(img)->file)==0xFFE0) { /* JFIF APP0 */
+ (void)read2bytes(jpg_ptr(img)->file);
+ for(i=0;i<5;i++) if(xgetc(jpg_ptr(img)->file)!=jpg_id[i])
+ pdftex_fail("reading JPEG image failed");
+ (void)read2bytes(jpg_ptr(img)->file);
+ units=xgetc(jpg_ptr(img)->file);
+ img_xres(img)=read2bytes(jpg_ptr(img)->file);
+ img_yres(img)=read2bytes(jpg_ptr(img)->file);
+ switch(units) {
+ case 1: break; /* pixels per inch */
+ case 2: img_xres(img)*=2.54; img_yres(img)*=2.54;
+ break; /* pixels per cm */
+ default:img_xres(img)=img_yres(img)=0; break;
+ }
+ }
+
+ xfseek(jpg_ptr(img)->file,0,SEEK_SET,cur_file_name);
+ while(1) {
+ if(feof(jpg_ptr(img)->file) || fgetc(jpg_ptr(img)->file)!=0xFF)
+ pdftex_fail("reading JPEG image failed");
+ switch(xgetc(jpg_ptr(img)->file)) {
+ case M_SOF5:
+ case M_SOF6:
+ case M_SOF7:
+ case M_SOF9:
+ case M_SOF10:
+ case M_SOF11:
+ case M_SOF13:
+ case M_SOF14:
+ case M_SOF15:
+ pdftex_fail("unsupported type of compression");
+ case M_SOF2:
+ if (fixedpdfminorversion <= 2)
+ pdftex_fail("cannot use progressive DCT with PDF-1.2");
+ case M_SOF0:
+ case M_SOF1:
+ case M_SOF3:
+ (void)read2bytes(jpg_ptr(img)->file); /* read segment length */
+ jpg_ptr(img)->bits_per_component = xgetc(jpg_ptr(img)->file);
+ img_height(img) = read2bytes(jpg_ptr(img)->file);
+ img_width(img) = read2bytes(jpg_ptr(img)->file);
+ jpg_ptr(img)->color_space = xgetc(jpg_ptr(img)->file);
+ xfseek(jpg_ptr(img)->file,0,SEEK_SET,cur_file_name);
+ switch (jpg_ptr(img)->color_space) {
+ case JPG_GRAY:
+ img_color(img) = IMAGE_COLOR_B;
+ break;
+ case JPG_RGB:
+ img_color(img) = IMAGE_COLOR_C;
+ break;
+ case JPG_CMYK:
+ img_color(img) = IMAGE_COLOR_C;
+ break;
+ default:
+ pdftex_fail("Unsupported color space %i",
+ (int)jpg_ptr(img)->color_space);
+ }
+ return;
+ case M_SOI: /* ignore markers without parameters */
+ case M_EOI:
+ case M_TEM:
+ case M_RST0:
+ case M_RST1:
+ case M_RST2:
+ case M_RST3:
+ case M_RST4:
+ case M_RST5:
+ case M_RST6:
+ case M_RST7:
+ break;
+ default: /* skip variable length markers */
+ xfseek(jpg_ptr(img)->file,read2bytes(jpg_ptr(img)->file)-2,SEEK_CUR,cur_file_name);
+ break;
+ }
+ }
+}
+
+void write_jpg(integer img)
+{
+ long unsigned l;
+ FILE *f;
+ pdf_puts("/Type /XObject\n/Subtype /Image\n");
+ pdf_printf("/Width %i\n/Height %i\n/BitsPerComponent %i\n/Length %i\n",
+ img_width(img),
+ img_height(img),
+ (int)jpg_ptr(img)->bits_per_component,
+ (int)jpg_ptr(img)->length);
+ pdf_puts("/ColorSpace ");
+ if (img_colorspace_ref(img) != 0) {
+ pdf_printf("%i 0 R\n", (int)img_colorspace_ref(img));
+ }
+ else {
+ switch (jpg_ptr(img)->color_space) {
+ case JPG_GRAY:
+ pdf_puts("/DeviceGray\n");
+ break;
+ case JPG_RGB:
+ pdf_puts("/DeviceRGB\n");
+ break;
+ case JPG_CMYK:
+ pdf_puts("/DeviceCMYK\n/Decode [1 0 1 0 1 0 1 0]\n");
+ break;
+ default:
+ pdftex_fail("Unsupported color space %i",
+ (int)jpg_ptr(img)->color_space);
+ }
+ }
+ pdf_puts("/Filter /DCTDecode\n>>\nstream\n");
+ for (l = jpg_ptr(img)->length, f = jpg_ptr(img)->file; l > 0; l--)
+ pdfout(xgetc(f));
+ pdf_puts("endstream\nendobj\n");
+}
diff --git a/Build/source/texk/web2c/pdftexdir/writepng.c b/Build/source/texk/web2c/pdftexdir/writepng.c
new file mode 100644
index 00000000000..30340c9e08e
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/writepng.c
@@ -0,0 +1,593 @@
+/*
+Copyright (c) 1996-2004 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX 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.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/writepng.c#8 $
+*/
+
+#include "ptexlib.h"
+#include "image.h"
+
+
+
+static const char perforce_id[] =
+ "$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/writepng.c#8 $";
+
+
+void read_png_info(integer img)
+{
+ double gamma;
+ FILE *png_file = xfopen(img_name(img), FOPEN_RBIN_MODE);
+
+ if ((png_ptr(img) = png_create_read_struct(PNG_LIBPNG_VER_STRING,
+ NULL, NULL, NULL)) == NULL)
+ pdftex_fail("libpng: png_create_read_struct() failed");
+ if ((png_info(img) = png_create_info_struct(png_ptr(img))) == NULL)
+ pdftex_fail("libpng: png_create_info_struct() failed");
+ if (setjmp(png_ptr(img)->jmpbuf))
+ pdftex_fail("libpng: internal error");
+ png_init_io(png_ptr(img), png_file);
+ png_read_info(png_ptr(img), png_info(img));
+ /* simple transparency support */
+ if (png_get_valid(png_ptr(img), png_info(img), PNG_INFO_tRNS)) {
+ png_set_tRNS_to_alpha(png_ptr(img));
+ }
+ /* alpha channel support */
+ if (fixedpdfminorversion < 4 && png_ptr(img)->color_type | PNG_COLOR_MASK_ALPHA)
+ png_set_strip_alpha(png_ptr(img));
+ /* 16bit depth support */
+ if (fixedpdfminorversion < 5)
+ fixedimagehicolor = 0;
+ if (png_info(img)->bit_depth == 16 && !fixedimagehicolor)
+ png_set_strip_16(png_ptr(img));
+ /* gamma support */
+ if (fixedimageapplygamma) {
+ if(png_get_gAMA(png_ptr(img), png_info(img), &gamma))
+ png_set_gamma(png_ptr(img), (fixedgamma / 1000.0), gamma);
+ else
+ png_set_gamma(png_ptr(img), (fixedgamma / 1000.0), (1000.0/ fixedimagegamma ));
+ }
+ /* reset structure */
+ png_read_update_info(png_ptr(img), png_info(img));
+ /* resolution support */
+ img_width(img) = png_info(img)->width;
+ img_height(img) = png_info(img)->height;
+ if (png_info(img)->valid & PNG_INFO_pHYs) {
+ img_xres(img) =
+ round(0.0254*png_get_x_pixels_per_meter(png_ptr(img), png_info(img)));
+ img_yres(img) =
+ round(0.0254*png_get_y_pixels_per_meter(png_ptr(img), png_info(img)));
+ }
+ switch (png_info(img)->color_type) {
+ case PNG_COLOR_TYPE_PALETTE:
+ img_color(img) = IMAGE_COLOR_C | IMAGE_COLOR_I;
+ break;
+ case PNG_COLOR_TYPE_GRAY:
+ case PNG_COLOR_TYPE_GRAY_ALPHA:
+ img_color(img) = IMAGE_COLOR_B;
+ break;
+ case PNG_COLOR_TYPE_RGB:
+ case PNG_COLOR_TYPE_RGB_ALPHA:
+ img_color(img) = IMAGE_COLOR_C;
+ break;
+ default:
+ pdftex_fail("unsupported type of color_type <%i>", png_info(img)->color_type);
+ }
+}
+
+
+#define write_gray_pixel_16(r) \
+ if (j % 4 == 0||j % 4 == 1) pdfbuf[pdfptr++] = *r++; \
+ else smask[smask_ptr++] = *r++
+
+#define write_gray_pixel_8(r) \
+ if (j % 2 == 0) pdfbuf[pdfptr++] = *r++; \
+ else smask[smask_ptr++] = *r++
+
+
+#define write_rgb_pixel_16(r) \
+ if (!(j % 8 == 6||j % 8 == 7)) pdfbuf[pdfptr++] = *r++; \
+ else smask[smask_ptr++] = *r++
+
+#define write_rgb_pixel_8(r) \
+ if (j % 4 != 3) pdfbuf[pdfptr++] = *r++; \
+ else smask[smask_ptr++] = *r++
+
+#define write_simple_pixel(r) pdfbuf[pdfptr++] = *r++
+
+
+#define write_noninterlaced(outmac) \
+ for (i = 0; i < (int)png_info(img)->height; i++) { \
+ png_read_row(png_ptr(img), row, NULL); \
+ r = row; \
+ k = png_info(img)->rowbytes; \
+ while(k > 0) { \
+ l = (k > pdfbufsize)? pdfbufsize : k; \
+ pdfroom(l); \
+ for (j = 0; j < l; j++) { \
+ outmac; \
+ } \
+ k -= l; \
+ } \
+ }
+
+#define write_interlaced(outmac) \
+ for (i = 0; i < (int)png_info(img)->height; i++) { \
+ row = rows[i]; \
+ k = png_info(img)->rowbytes; \
+ while(k > 0) { \
+ l = (k > pdfbufsize)? pdfbufsize : k; \
+ pdfroom(l); \
+ for (j = 0; j < l; j++) { \
+ outmac; \
+ } \
+ k -= l; \
+ } \
+ xfree(rows[i]); \
+ }
+
+
+void write_png_palette (integer img)
+{
+ int i, j, k, l;
+ png_bytep row, r, *rows;
+ integer palette_objnum = 0;
+ pdfcreateobj(0, 0);
+ palette_objnum = objptr;
+ if (img_colorspace_ref(img) != 0) {
+ pdf_printf("%i 0 R\n", (int)img_colorspace_ref(img));
+ }
+ else {
+ pdf_printf("[/Indexed /DeviceRGB %i %i 0 R]\n",
+ (int)(png_info(img)->num_palette - 1),
+ (int)palette_objnum);
+ }
+ pdfbeginstream();
+ if (png_info(img)->interlace_type == PNG_INTERLACE_NONE) {
+ row = xtalloc(png_info(img)->rowbytes, png_byte);
+ write_noninterlaced(write_simple_pixel(r));
+ xfree(row);
+ } else {
+ if (png_info(img)->height*png_info(img)->rowbytes >= 10240000L)
+ pdftex_warn("large interlaced PNG might cause out of memory (use non-interlaced PNG to fix this)");
+ rows = xtalloc(png_info(img)->height, png_bytep);
+ for (i = 0; i < png_info(img)->height; i++)
+ rows[i] = xtalloc(png_info(img)->rowbytes, png_byte);
+ png_read_image(png_ptr(img), rows);
+ write_interlaced(write_simple_pixel(row));
+ xfree(rows);
+ }
+ pdfendstream();
+ if (palette_objnum > 0) {
+ pdfbegindict(palette_objnum);
+ pdfbeginstream();
+ for (i = 0; i < png_info(img)->num_palette; i++) {
+ pdfroom(3);
+ pdfbuf[pdfptr++] = png_info(img)->palette[i].red;
+ pdfbuf[pdfptr++] = png_info(img)->palette[i].green;
+ pdfbuf[pdfptr++] = png_info(img)->palette[i].blue;
+ }
+ pdfendstream();
+ }
+}
+
+void write_png_gray (integer img)
+{
+ int i, j, k, l;
+ png_bytep row, r, *rows;
+ if (img_colorspace_ref(img) != 0) {
+ pdf_printf("%i 0 R\n", (int)img_colorspace_ref(img));
+ }
+ else {
+ pdf_puts("/DeviceGray\n");
+ }
+ pdfbeginstream();
+ if (png_info(img)->interlace_type == PNG_INTERLACE_NONE) {
+ row = xtalloc(png_info(img)->rowbytes, png_byte);
+ write_noninterlaced(write_simple_pixel(r));
+ xfree(row);
+ } else {
+ if (png_info(img)->height*png_info(img)->rowbytes >= 10240000L)
+ pdftex_warn("large interlaced PNG might cause out of memory (use non-interlaced PNG to fix this)");
+ rows = xtalloc(png_info(img)->height, png_bytep);
+ for (i = 0; i < png_info(img)->height; i++)
+ rows[i] = xtalloc(png_info(img)->rowbytes, png_byte);
+ png_read_image(png_ptr(img), rows);
+ write_interlaced(write_simple_pixel(row));
+ xfree(rows);
+ }
+ pdfendstream();
+}
+
+
+
+void write_png_gray_alpha (integer img)
+{
+ int i, j, k, l;
+ png_bytep row, r, *rows;
+ integer smask_objnum = 0;
+ png_bytep smask;
+ integer smask_ptr = 0;
+ integer smask_size = 0;
+ int bitdepth;
+ if (img_colorspace_ref(img) != 0) {
+ pdf_printf("%i 0 R\n", (int)img_colorspace_ref(img));
+ }
+ else {
+ pdf_puts("/DeviceGray\n");
+ }
+ pdfcreateobj(0, 0);
+ smask_objnum = objptr;
+ pdf_printf("/SMask %i 0 R\n",
+ (int)smask_objnum);
+ smask_size = (png_info(img)->rowbytes/2)*png_info(img)->height;
+ smask = xtalloc(smask_size, png_byte);
+ pdfbeginstream();
+ if (png_info(img)->interlace_type == PNG_INTERLACE_NONE) {
+ row = xtalloc(png_info(img)->rowbytes, png_byte);
+ if ((png_info(img)->bit_depth == 16) && fixedimagehicolor) {
+ write_noninterlaced(write_gray_pixel_16(r));
+ } else {
+ write_noninterlaced(write_gray_pixel_8(r));
+ }
+ xfree(row);
+ } else {
+ if (png_info(img)->height*png_info(img)->rowbytes >= 10240000L)
+ pdftex_warn("large interlaced PNG might cause out of memory (use non-interlaced PNG to fix this)");
+ rows = xtalloc(png_info(img)->height, png_bytep);
+ for (i = 0; i < png_info(img)->height; i++)
+ rows[i] = xtalloc(png_info(img)->rowbytes, png_byte);
+ png_read_image(png_ptr(img), rows);
+ if ((png_info(img)->bit_depth == 16) && fixedimagehicolor) {
+ write_interlaced(write_gray_pixel_16(row));
+ } else {
+ write_interlaced(write_gray_pixel_8(row));
+ }
+ xfree(rows);
+ }
+ pdfendstream();
+ pdfflush();
+ /* now write the Smask object */
+ if (smask_objnum > 0) {
+ bitdepth = (int)png_info(img)->bit_depth;
+ pdfbegindict(smask_objnum);
+ pdf_puts("/Type /XObject\n/Subtype /Image\n");
+ pdf_printf("/Width %i\n/Height %i\n/BitsPerComponent %i\n",
+ (int)png_info(img)->width,
+ (int)png_info(img)->height,
+ (bitdepth == 16 ? 8 : bitdepth));
+ pdf_puts("/ColorSpace /DeviceGray\n");
+ pdfbeginstream();
+ for (i = 0; i <smask_size; i++) {
+ if (i % 8 == 0)
+ pdfroom(8);
+ pdfbuf[pdfptr++] = smask[i];
+ if (bitdepth == 16)
+ i++;
+ }
+ xfree(smask);
+ pdfendstream();
+ }
+}
+
+void write_png_rgb (integer img)
+{
+ int i, j, k, l;
+ png_bytep row, r, *rows;
+ if (img_colorspace_ref(img) != 0) {
+ pdf_printf("%i 0 R\n", (int)img_colorspace_ref(img));
+ }
+ else {
+ pdf_puts("/DeviceRGB\n");
+ }
+ pdfbeginstream();
+ if (png_info(img)->interlace_type == PNG_INTERLACE_NONE) {
+ row = xtalloc(png_info(img)->rowbytes, png_byte);
+ write_noninterlaced(write_simple_pixel(r));
+ xfree(row);
+ } else {
+ if (png_info(img)->height*png_info(img)->rowbytes >= 10240000L)
+ pdftex_warn("large interlaced PNG might cause out of memory (use non-interlaced PNG to fix this)");
+ rows = xtalloc(png_info(img)->height, png_bytep);
+ for (i = 0; i < png_info(img)->height; i++)
+ rows[i] = xtalloc(png_info(img)->rowbytes, png_byte);
+ png_read_image(png_ptr(img), rows);
+ write_interlaced(write_simple_pixel(row));
+ xfree(rows);
+ }
+ pdfendstream();
+}
+
+void write_png_rgb_alpha (integer img)
+{
+ int i, j, k, l;
+ png_bytep row, r, *rows;
+ integer smask_objnum = 0;
+ png_bytep smask;
+ integer smask_ptr = 0;
+ integer smask_size = 0;
+ int bitdepth;
+ if (img_colorspace_ref(img) != 0) {
+ pdf_printf("%i 0 R\n", (int)img_colorspace_ref(img));
+ }
+ else {
+ pdf_puts("/DeviceRGB\n");
+ }
+ pdfcreateobj(0, 0);
+ smask_objnum = objptr;
+ pdf_printf("/SMask %i 0 R\n",
+ (int)smask_objnum);
+ smask_size = (png_info(img)->rowbytes/2)*png_info(img)->height;
+ smask = xtalloc(smask_size, png_byte);
+ pdfbeginstream();
+ if (png_info(img)->interlace_type == PNG_INTERLACE_NONE) {
+ row = xtalloc(png_info(img)->rowbytes, png_byte);
+ if ((png_info(img)->bit_depth == 16) && fixedimagehicolor) {
+ write_noninterlaced(write_rgb_pixel_16(r));
+ } else {
+ write_noninterlaced(write_rgb_pixel_8(r));
+ }
+ xfree(row);
+ } else {
+ if (png_info(img)->height*png_info(img)->rowbytes >= 10240000L)
+ pdftex_warn("large interlaced PNG might cause out of memory (use non-interlaced PNG to fix this)");
+ rows = xtalloc(png_info(img)->height, png_bytep);
+ for (i = 0; i < png_info(img)->height; i++)
+ rows[i] = xtalloc(png_info(img)->rowbytes, png_byte);
+ png_read_image(png_ptr(img), rows);
+ if ((png_info(img)->bit_depth == 16) && fixedimagehicolor) {
+ write_interlaced(write_rgb_pixel_16(row));
+ } else {
+ write_interlaced(write_rgb_pixel_8(row));
+ }
+ xfree(rows);
+ }
+ pdfendstream();
+ pdfflush();
+ /* now write the Smask object */
+ if (smask_objnum > 0) {
+ bitdepth = (int)png_info(img)->bit_depth;
+ pdfbegindict(smask_objnum);
+ pdf_puts("/Type /XObject\n/Subtype /Image\n");
+ pdf_printf("/Width %i\n/Height %i\n/BitsPerComponent %i\n",
+ (int)png_info(img)->width,
+ (int)png_info(img)->height,
+ (bitdepth == 16 ? 8 : bitdepth));
+ pdf_puts("/ColorSpace /DeviceGray\n");
+ pdfbeginstream();
+ for (i = 0; i <smask_size; i++) {
+ if (i % 8 == 0)
+ pdfroom(8);
+ pdfbuf[pdfptr++] = smask[i];
+ if (bitdepth == 16)
+ i++;
+ }
+ xfree(smask);
+ pdfendstream();
+ }
+}
+
+
+/**********************************************************************/
+/*
+ *
+ * The |copy_png| function is from Hartmut Henkel. The goal is to use
+ * pdf's native FlateDecode support if that is possible.
+ *
+ * Only a subset of the png files allows this, but when possible it
+ * greatly improves inclusion speed.
+ *
+ */
+
+/* Code cheerfully gleaned from Thomas Merz' PDFlib, file p_png.c "SPNG - Simple PNG" */
+
+static int spng_getint(FILE * fp)
+{
+ unsigned char buf[4];
+ if (fread(buf, 1, 4, fp) != 4)
+ pdftex_fail("writepng: reading chunk type failed");
+ return (((((int) buf[0] << 8) + buf[1]) << 8) + buf[2] << 8) + buf[3];
+}
+
+#define SPNG_CHUNK_IDAT 0x49444154
+#define SPNG_CHUNK_IEND 0x49454E44
+
+void copy_png(integer img)
+{
+ FILE *fp = png_ptr(img)->io_ptr;
+ int i, len, type, streamlength = 0;
+ boolean endflag = false;
+ int idat = 0; /* flag to check continuous IDAT chunks sequence */
+ /* 1st pass to find overall stream /Length */
+ if (fseek(fp, 8, SEEK_SET) != 0)
+ pdftex_fail("writepng: fseek in PNG file failed");
+ do {
+ len = spng_getint(fp);
+ type = spng_getint(fp);
+ switch (type) {
+ case SPNG_CHUNK_IEND:
+ endflag = true;
+ break;
+ case SPNG_CHUNK_IDAT:
+ streamlength += len;
+ default:
+ if (fseek(fp, len + 4, SEEK_CUR) != 0)
+ pdftex_fail("writepng: fseek in PNG file failed");
+ }
+ } while (endflag == false);
+ pdf_printf("/Length %d\n", streamlength);
+ pdf_printf("/Filter /FlateDecode\n");
+ pdf_printf("/DecodeParms << ");
+ pdf_printf("/Colors %d ", png_info(img)->color_type == 2 ? 3 : 1);
+ pdf_printf("/Columns %d ", (int) png_info(img)->width);
+ pdf_printf("/BitsPerComponent %i ", (int) png_info(img)->bit_depth);
+ pdf_printf("/Predictor %d ", 10); /* actual predictor defined on line basis */
+ pdf_printf(">>\n>>\nstream\n");
+ /* 2nd pass to copy data */
+ endflag = false;
+ if (fseek(fp, 8, SEEK_SET) != 0)
+ pdftex_fail("writepng: fseek in PNG file failed");
+ do {
+ len = spng_getint(fp);
+ type = spng_getint(fp);
+ switch (type) {
+ case SPNG_CHUNK_IDAT: /* do copy */
+ if (idat == 2)
+ pdftex_fail("writepng: IDAT chunk sequence broken");
+ idat = 1;
+ while (len > 0) {
+ i = (len > pdfbufsize) ? pdfbufsize : len;
+ pdfroom(i);
+ fread(&pdfbuf[pdfptr], 1, i, fp);
+ pdfptr += i;
+ len -= i;
+ }
+ if (fseek(fp, 4, SEEK_CUR) != 0)
+ pdftex_fail("writepng: fseek in PNG file failed");
+ break;
+ case SPNG_CHUNK_IEND: /* done */
+ pdf_puts("\nendstream\nendobj\n");
+ endflag = true;
+ break;
+ default:
+ if (idat == 1)
+ idat = 2;
+ if (fseek(fp, len + 4, SEEK_CUR) != 0)
+ pdftex_fail("writepng: fseek in PNG file failed");
+ }
+ } while (endflag == false);
+}
+
+void write_png (integer img)
+{
+
+ double gamma, checked_gamma;
+ int i;
+ integer palette_objnum = 0;
+ if (fixedpdfminorversion < 5)
+ fixedimagehicolor = 0;
+
+ pdf_puts("/Type /XObject\n/Subtype /Image\n");
+ pdf_printf("/Width %i\n/Height %i\n/BitsPerComponent %i\n",
+ (int)png_info(img)->width,
+ (int)png_info(img)->height,
+ (int)png_info(img)->bit_depth);
+ pdf_puts("/ColorSpace ");
+ checked_gamma = 1.0;
+ if (fixedimageapplygamma) {
+ if(png_get_gAMA(png_ptr(img), png_info(img), &gamma)) {
+ checked_gamma = (fixedgamma / 1000.0) * gamma;
+ } else {
+ checked_gamma = (fixedgamma / 1000.0) * (1000.0/ fixedimagegamma );
+ }
+ }
+ /* the switching between |png_info| and |png_ptr| queries has been trial and error.
+ */
+ if (fixedpdfminorversion > 1
+ && png_info(img)->interlace_type == PNG_INTERLACE_NONE
+ && (png_ptr(img)->transformations == 0 ||
+ png_ptr(img)->transformations == 0x2000 ) /* gamma */
+ && !(png_ptr(img)->color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
+ png_ptr(img)->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ && (fixedimagehicolor || (png_ptr(img)->bit_depth <= 8))
+ && (checked_gamma <= 1.01 && checked_gamma > 0.99)
+ )
+ {
+ if (img_colorspace_ref(img) != 0) {
+ pdf_printf("%i 0 R\n", (int)img_colorspace_ref(img));
+ }
+ else {
+ switch (png_info(img)->color_type) {
+ case PNG_COLOR_TYPE_PALETTE:
+ pdfcreateobj(0, 0);
+ palette_objnum = objptr;
+ pdf_printf("[/Indexed /DeviceRGB %i %i 0 R]\n",
+ (int) (png_info(img)->num_palette - 1),
+ (int) palette_objnum);
+ break;
+ case PNG_COLOR_TYPE_GRAY:
+ pdf_puts("/DeviceGray\n");
+ break;
+ default: /* RGB */
+ pdf_puts("/DeviceRGB\n");
+ };
+ }
+ tex_printf(" (PNG copy)");
+ copy_png(img);
+ if (palette_objnum > 0) {
+ pdfbegindict(palette_objnum);
+ pdfbeginstream();
+ for (i = 0; i < png_info(img)->num_palette; i++) {
+ pdfroom(3);
+ pdfbuf[pdfptr++] = png_info(img)->palette[i].red;
+ pdfbuf[pdfptr++] = png_info(img)->palette[i].green;
+ pdfbuf[pdfptr++] = png_info(img)->palette[i].blue;
+ }
+ pdfendstream();
+ }
+ } else {
+ if (0) {
+ tex_printf(" PNG copy skipped because: ");
+ if(fixedimageapplygamma &&
+ (checked_gamma > 1.01 || checked_gamma < 0.99))
+ tex_printf("gamma delta=%lf ", checked_gamma);
+ if (png_ptr(img)->transformations != PNG_TRANSFORM_IDENTITY)
+ tex_printf("transform=%d",png_ptr(img)->transformations);
+ if ((png_info(img)->color_type != PNG_COLOR_TYPE_GRAY) &&
+ (png_info(img)->color_type != PNG_COLOR_TYPE_RGB) &&
+ (png_info(img)->color_type != PNG_COLOR_TYPE_PALETTE))
+ tex_printf("colortype ");
+ if (fixedpdfminorversion <= 1)
+ tex_printf("version=%d ",fixedpdfminorversion);
+ if (png_info(img)->interlace_type != PNG_INTERLACE_NONE)
+ tex_printf("interlaced ");
+ if (png_info(img)->bit_depth > 8)
+ tex_printf("bitdepth=%d ",png_info(img)->bit_depth);
+ if (png_get_valid(png_ptr(img), png_info(img), PNG_INFO_tRNS))
+ tex_printf("simple transparancy ");
+ }
+ switch (png_info(img)->color_type) {
+ case PNG_COLOR_TYPE_PALETTE:
+ write_png_palette(img);
+ break;
+ case PNG_COLOR_TYPE_GRAY:
+ write_png_gray(img);
+ break;
+ case PNG_COLOR_TYPE_GRAY_ALPHA:
+ if (fixedpdfminorversion >=4)
+ write_png_gray_alpha(img);
+ else
+ write_png_gray(img);
+ break;
+ case PNG_COLOR_TYPE_RGB:
+ write_png_rgb(img);
+ break;
+ case PNG_COLOR_TYPE_RGB_ALPHA:
+ if (fixedpdfminorversion >=4)
+ write_png_rgb_alpha(img);
+ else
+ write_png_rgb(img);
+ break;
+ default:
+ pdftex_fail("unsupported type of color_type <%i>", png_info(img)->color_type);
+ }
+ }
+ pdfflush();
+}
+
+
diff --git a/Build/source/texk/web2c/pdftexdir/writet1.c b/Build/source/texk/web2c/pdftexdir/writet1.c
new file mode 100644
index 00000000000..08704286524
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/writet1.c
@@ -0,0 +1,1780 @@
+/*
+Copyright (c) 1996-2005 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX 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.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/writet1.c#25 $
+*/
+
+static const char perforce_id[] =
+ "$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/writet1.c#25 $";
+
+#ifdef pdfTeX /* writet1 used with pdfTeX */
+#include "ptexlib.h"
+#define t1_log(s) tex_printf(s)
+#define t1_open() \
+ open_input(&t1_file, kpse_type1_format, FOPEN_RBIN_MODE)
+#define enc_open() \
+ open_input(&enc_file, kpse_enc_format, FOPEN_RBIN_MODE)
+#define external_enc() (fm_cur->encoding)->glyph_names
+#define full_file_name() (char*)nameoffile + 1
+#define get_length1() t1_length1 = t1_offset() - t1_save_offset
+#define get_length2() t1_length2 = t1_offset() - t1_save_offset
+#define get_length3() t1_length3 = t1_offset() - t1_save_offset
+#define is_used_char(c) pdfcharmarked(tex_font, c)
+#define t1_putchar fb_putchar
+#define t1_offset fb_offset
+#define out_eexec_char t1_putchar
+#define save_offset() t1_save_offset = t1_offset()
+#define end_last_eexec_line() \
+ t1_eexec_encrypt = false
+#define t1_char(c) c
+#define embed_all_glyphs(tex_font) fm_cur->all_glyphs
+#define extra_charset() fm_cur->charset
+#define update_subset_tag() \
+ strncpy(fb_array + t1_fontname_offset, fm_cur->subset_tag, 6)
+
+integer t1_length1, t1_length2, t1_length3;
+static integer t1_save_offset;
+static integer t1_fontname_offset;
+extern char *fb_array;
+
+#else /* writet1 used with dvips */
+#include "dvips.h"
+#include "ptexmac.h"
+#undef fm_extend
+#define fm_extend(f) 0
+#undef fm_slant
+#define fm_slant(f) 0
+#undef is_reencoded
+#define is_reencoded(f) (cur_enc_name != NULL)
+#undef is_subsetted
+#define is_subsetted(f) true
+#undef is_included
+#define is_included(f) true
+#undef set_cur_file_name
+#define set_cur_file_name(s) cur_file_name = s
+#define t1_open() \
+ ((t1_file = search(headerpath, cur_file_name, FOPEN_RBIN_MODE)) != NULL)
+#define enc_open() \
+ ((enc_file = search(encpath, cur_file_name, FOPEN_RBIN_MODE)) != NULL)
+#define external_enc() ext_glyph_names
+#define full_file_name() cur_file_name
+#define get_length1()
+#define get_length2()
+#define get_length3()
+#define is_used_char(c) (grid[c] == 1)
+#define out_eexec_char t1_outhex
+#define save_offset()
+#define end_last_eexec_line() \
+ hexline_length = HEXLINE_WIDTH; \
+ end_hexline(); \
+ t1_eexec_encrypt = false
+#define t1_log(s)
+#define t1_scan_only()
+#define t1_include()
+#define t1_putchar(c) fputc(c, bitfile)
+#define t1_scan_keys()
+#define embed_all_glyphs(tex_font) false
+#undef pdfmovechars
+#ifdef SHIFTLOWCHARS
+extern char errbuf[];
+extern Boolean shiftlowchars;
+#define pdfmovechars shiftlowchars
+#define t1_char(c) T1Char(c)
+#else /* SHIFTLOWCHARS */
+#define t1_char(c) c
+#define pdfmovechars 0
+#endif /* SHIFTLOWCHARS */
+#define extra_charset() dvips_extra_charset
+#define make_subset_tag(a, b)
+#define update_subset_tag()
+
+static char *dvips_extra_charset ;
+extern FILE *bitfile ;
+extern FILE *search();
+static char *cur_file_name;
+static char *cur_enc_name;
+static unsigned char *grid;
+static char *ext_glyph_names[MAX_CHAR_CODE + 1];
+static char print_buf[PRINTF_BUF_SIZE];
+static int hexline_length;
+static char notdef[] = ".notdef";
+static size_t last_ptr_index;
+#endif /* pdfTeX */
+
+#include <kpathsea/c-vararg.h>
+#include <kpathsea/c-proto.h>
+
+#define t1_getchar() getc(t1_file)
+#define t1_ungetchar(c) ungetc(c, t1_file)
+#define t1_eof() feof(t1_file)
+#define t1_close() xfclose(t1_file, cur_file_name)
+
+#define enc_getchar() getc(enc_file)
+#define enc_eof() feof(enc_file)
+#define enc_close() xfclose(enc_file, cur_file_name)
+
+#define valid_code(c) (c >= 0 && c <= MAX_CHAR_CODE)
+
+static const char *standard_glyph_names[MAX_CHAR_CODE + 1] = {
+notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+notdef, notdef, notdef, notdef, 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", notdef, notdef, notdef, notdef, notdef, notdef,
+notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+notdef, "exclamdown", "cent", "sterling", "fraction", "yen", "florin",
+"section", "currency", "quotesingle", "quotedblleft", "guillemotleft",
+"guilsinglleft", "guilsinglright", "fi", "fl", notdef, "endash", "dagger",
+"daggerdbl", "periodcentered", notdef, "paragraph", "bullet",
+"quotesinglbase", "quotedblbase", "quotedblright", "guillemotright",
+"ellipsis", "perthousand", notdef, "questiondown", notdef, "grave", "acute",
+"circumflex", "tilde", "macron", "breve", "dotaccent", "dieresis", notdef,
+"ring", "cedilla", notdef, "hungarumlaut", "ogonek", "caron", "emdash",
+notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+notdef, notdef, notdef, notdef, notdef, notdef, notdef, "AE", notdef,
+"ordfeminine", notdef, notdef, notdef, notdef, "Lslash", "Oslash", "OE",
+"ordmasculine", notdef, notdef, notdef, notdef, notdef, "ae", notdef, notdef,
+notdef, "dotlessi", notdef, notdef, "lslash", "oslash", "oe", "germandbls",
+notdef, notdef, notdef, notdef
+};
+
+static char charstringname[] = "/CharStrings";
+
+char **t1_glyph_names;
+char *t1_builtin_glyph_names[MAX_CHAR_CODE + 1];
+static boolean read_encoding_only;
+static int t1_encoding;
+
+#define T1_BUF_SIZE 0x10
+#define ENC_BUF_SIZE 0x1000
+
+#define ENC_STANDARD 0
+#define ENC_BUILTIN 1
+
+#define CS_HSTEM 1
+#define CS_VSTEM 3
+#define CS_VMOVETO 4
+#define CS_RLINETO 5
+#define CS_HLINETO 6
+#define CS_VLINETO 7
+#define CS_RRCURVETO 8
+#define CS_CLOSEPATH 9
+#define CS_CALLSUBR 10
+#define CS_RETURN 11
+#define CS_ESCAPE 12
+#define CS_HSBW 13
+#define CS_ENDCHAR 14
+#define CS_RMOVETO 21
+#define CS_HMOVETO 22
+#define CS_VHCURVETO 30
+#define CS_HVCURVETO 31
+#define CS_1BYTE_MAX (CS_HVCURVETO + 1)
+
+#define CS_DOTSECTION CS_1BYTE_MAX + 0
+#define CS_VSTEM3 CS_1BYTE_MAX + 1
+#define CS_HSTEM3 CS_1BYTE_MAX + 2
+#define CS_SEAC CS_1BYTE_MAX + 6
+#define CS_SBW CS_1BYTE_MAX + 7
+#define CS_DIV CS_1BYTE_MAX + 12
+#define CS_CALLOTHERSUBR CS_1BYTE_MAX + 16
+#define CS_POP CS_1BYTE_MAX + 17
+#define CS_SETCURRENTPOINT CS_1BYTE_MAX + 33
+#define CS_2BYTE_MAX (CS_SETCURRENTPOINT + 1)
+#define CS_MAX CS_2BYTE_MAX
+
+typedef unsigned char byte;
+
+typedef struct {
+ byte nargs; /* number of arguments */
+ boolean bottom; /* take arguments from bottom of stack? */
+ boolean clear; /* clear stack? */
+ boolean valid;
+} cc_entry; /* CharString Command */
+
+typedef struct {
+ char *name; /* glyph name (or notdef for Subrs entry) */
+ byte *data;
+ unsigned short len; /* length of the whole string */
+ unsigned short cslen; /* length of the encoded part of the string */
+ boolean used;
+ boolean valid;
+} cs_entry;
+
+static unsigned short t1_dr, t1_er;
+static const unsigned short t1_c1 = 52845, t1_c2 = 22719;
+static unsigned short t1_cslen;
+static short t1_lenIV;
+static char enc_line[ENC_BUF_SIZE];
+
+/* define t1_line_ptr, t1_line_array & t1_line_limit */
+typedef char t1_line_entry;
+define_array(t1_line);
+
+/* define t1_buf_ptr, t1_buf_array & t1_buf_limit */
+typedef char t1_buf_entry;
+define_array(t1_buf);
+
+static int cs_start;
+
+static cs_entry *cs_tab, *cs_ptr, *cs_notdef;
+static char *cs_dict_start, *cs_dict_end;
+static int cs_count, cs_size, cs_size_pos;
+
+static cs_entry *subr_tab;
+static char *subr_array_start, *subr_array_end;
+static int subr_max, subr_size, subr_size_pos;
+
+/* This list contains the begin/end tokens commonly used in the */
+/* /Subrs array of a Type 1 font. */
+static const char *cs_token_pairs_list[][2] = {
+ {" RD", "NP"},
+ {" -|", "|"},
+ {" RD", "noaccess put"},
+ {" -|", "noaccess put"},
+ {NULL, NULL}
+};
+static const char **cs_token_pair;
+
+static boolean t1_pfa, t1_cs, t1_scan, t1_eexec_encrypt, t1_synthetic;
+static int t1_in_eexec; /* 0 before eexec-encrypted, 1 during, 2 after */
+static long t1_block_length;
+static int last_hexbyte;
+static FILE *t1_file;
+static FILE *enc_file;
+
+#define str_prefix(s1, s2) (strncmp(s1, s2, strlen(s2)) == 0)
+#define t1_prefix(s) str_prefix(t1_line_array, s)
+#define t1_buf_prefix(s) str_prefix(t1_buf_array, s)
+#define t1_suffix(s) str_suffix(t1_line_array, t1_line_ptr, s)
+#define t1_buf_suffix(s) str_suffix(t1_buf_array, t1_buf_ptr, s)
+#define t1_charstrings() strstr(t1_line_array, charstringname)
+#define t1_subrs() t1_prefix("/Subrs")
+#define t1_end_eexec() t1_suffix("mark currentfile closefile")
+#define t1_cleartomark() t1_prefix("cleartomark")
+
+#ifndef pdfTeX
+static void pdftex_fail(char *fmt,...)
+{
+ va_list args;
+ va_start(args, fmt);
+ fputs("\nError: module writet1", stderr);
+ if (cur_file_name)
+ fprintf(stderr, " (file %s)", cur_file_name);
+ fputs(": ", stderr);
+ vsprintf(print_buf, fmt, args);
+ fputs(print_buf, stderr);
+ fputs("\n ==> Fatal error occurred, the output PS file is not finished!\n", stderr);
+ va_end(args);
+ exit(-1);
+}
+
+static void pdftex_warn(char *fmt,...)
+{
+ va_list args;
+ va_start(args, fmt);
+ fputs("\nWarning: module writet1 of dvips", stderr);
+ if (cur_file_name)
+ fprintf(stderr, " (file %s)", cur_file_name);
+ fputs(": ", stderr);
+ vsprintf(print_buf, fmt, args);
+ fputs(print_buf, stderr);
+ fputs("\n", stderr);
+ va_end(args);
+}
+
+#define HEXLINE_WIDTH 64
+
+static void end_hexline()
+{
+ if (hexline_length == HEXLINE_WIDTH) {
+ fputs("\n", bitfile);
+ hexline_length = 0;
+ }
+}
+
+static void t1_outhex(byte b)
+{
+ static char *hexdigits = "0123456789ABCDEF";
+ t1_putchar(hexdigits[b/16]);
+ t1_putchar(hexdigits[b%16]);
+ hexline_length += 2;
+ end_hexline();
+}
+#endif /* pdfTeX */
+
+
+static void enc_getline(void)
+{
+ char *p;
+ int c;
+restart:
+ if (enc_eof())
+ pdftex_fail("unexpected end of file");
+ p = enc_line;
+ do {
+ c = enc_getchar();
+ append_char_to_buf(c, p, enc_line, ENC_BUF_SIZE);
+ } while (c != 10);
+ append_eol(p, enc_line, ENC_BUF_SIZE);
+ if (p - enc_line < 2 || *enc_line == '%')
+ goto restart;
+}
+
+void load_enc(char *enc_name, char **glyph_names)
+{
+ char buf[ENC_BUF_SIZE], *p, *r;
+ int names_count;
+ set_cur_file_name(enc_name);
+ if (!enc_open()) {
+ pdftex_warn("cannot open encoding file for reading");
+ cur_file_name = NULL;
+ return;
+ }
+ t1_log("{");
+ t1_log(cur_file_name = full_file_name());
+ enc_getline();
+ if (*enc_line != '/' || (r = strchr(enc_line, '[')) == NULL) {
+ remove_eol(r, enc_line);
+ pdftex_fail("invalid encoding vector (a name or `[' missing): `%s'", enc_line);
+ }
+ names_count = 0;
+ r++; /* skip '[' */
+ skip(r, ' ');
+ for (;;) {
+ while (*r == '/') {
+ for (p = buf, r++; *r != ' ' && *r != 10 && *r != ']' && *r != '/'; *p++ = *r++);
+ *p = 0;
+ skip(r, ' ');
+ if (names_count > MAX_CHAR_CODE)
+ pdftex_fail("encoding vector contains more than %i names",
+ (int)(MAX_CHAR_CODE + 1));
+ if (strcmp(buf, notdef) != 0)
+ glyph_names[names_count] = xstrdup(buf);
+ names_count++;
+ }
+ if (*r != 10 && *r != '%') {
+ if (strncmp(r, "] def", strlen("] def")) == 0)
+ goto done;
+ else {
+ remove_eol(r, enc_line);
+ pdftex_fail("invalid encoding vector: a name or `] def' expected: `%s'", enc_line);
+ }
+ }
+ enc_getline();
+ r = enc_line;
+ }
+done:
+ enc_close();
+ t1_log("}");
+ cur_file_name = NULL;
+}
+
+static void t1_check_pfa(void)
+{
+ int c = t1_getchar();
+ if (c != 128)
+ t1_pfa = true;
+ else
+ t1_pfa = false;
+ t1_ungetchar(c);
+}
+
+static int t1_getbyte(void)
+{
+ int c = t1_getchar();
+ if (t1_pfa)
+ return c;
+ if (t1_block_length == 0) {
+ if (c != 128)
+ pdftex_fail("invalid marker");
+ c = t1_getchar();
+ if (c == 3) {
+ while (!t1_eof())
+ t1_getchar();
+ return EOF;
+ }
+ t1_block_length = t1_getchar() & 0xff;
+ t1_block_length |= (t1_getchar() & 0xff) << 8;
+ t1_block_length |= (t1_getchar() & 0xff) << 16;
+ t1_block_length |= (t1_getchar() & 0xff) << 24;
+ c = t1_getchar();
+ }
+ t1_block_length--;
+ return c;
+}
+
+static int hexval(int c)
+{
+ if (c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+ else if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ else if (c >= '0' && c <= '9')
+ return c - '0';
+ else
+ return -1;
+}
+
+static byte edecrypt(byte cipher)
+{
+ byte plain;
+ if (t1_pfa) {
+ while (cipher == 10 || cipher == 13)
+ cipher = t1_getbyte();
+ last_hexbyte = cipher = (hexval(cipher) << 4) + hexval(t1_getbyte());
+ }
+ plain = (cipher^(t1_dr >> 8));
+ t1_dr = (cipher + t1_dr)*t1_c1 + t1_c2;
+ return plain;
+}
+
+static byte cdecrypt(byte cipher, unsigned short *cr)
+{
+ byte plain = (cipher^(*cr >> 8));
+ *cr = (cipher + *cr)*t1_c1 + t1_c2;
+ return plain;
+}
+
+static byte eencrypt(byte plain)
+{
+ byte cipher = (plain^(t1_er >> 8));
+ t1_er = (cipher + t1_er)*t1_c1 + t1_c2;
+ return cipher;
+}
+
+static byte cencrypt(byte plain, unsigned short *cr)
+{
+ byte cipher = (plain^(*cr >> 8));
+ *cr = (cipher + *cr)*t1_c1 + t1_c2;
+ return cipher;
+}
+
+static char *eol(char *s)
+{
+ char *p = strend(s);
+ if (p - s > 1 && p[-1] != 10) {
+ *p++ = 10;
+ *p = 0;
+ }
+ return p;
+}
+
+static float t1_scan_num(char *p, char **r)
+{
+ float f;
+ skip(p, ' ');
+ if (sscanf(p, "%g", &f) != 1) {
+ remove_eol(p, t1_line_array);
+ pdftex_fail("a number expected: `%s'", t1_line_array);
+ }
+ if (r != NULL) {
+ for (; isdigit(*p) || *p == '.' ||
+ *p == 'e' || *p == 'E' || *p == '+' || *p == '-'; p++);
+ *r = p;
+ }
+ return f;
+}
+
+static boolean str_suffix(const char *begin_buf, const char *end_buf,
+ const char *s)
+{
+ const char *s1 = end_buf - 1,
+ *s2 = strend(s) - 1;
+ if (*s1 == 10)
+ s1--;
+ while (s1 >= begin_buf && s2 >= s) {
+ if (*s1-- != *s2--)
+ return false;
+ }
+ return s2 < s;
+}
+
+static void t1_getline(void)
+{
+ int c, l, eexec_scan;
+ char *p;
+ static const char eexec_str[] = "currentfile eexec";
+ static int eexec_len = 17; /* strlen(eexec_str) */
+restart:
+ if (t1_eof())
+ pdftex_fail("unexpected end of file");
+ t1_line_ptr = t1_line_array;
+ alloc_array(t1_line, 1, T1_BUF_SIZE);
+ t1_cslen = 0;
+ eexec_scan = 0;
+ c = t1_getbyte();
+ if (c == EOF)
+ goto exit;
+ while (!t1_eof()) {
+ if (t1_in_eexec == 1)
+ c = edecrypt(c);
+ alloc_array(t1_line, 1, T1_BUF_SIZE);
+ append_char_to_buf(c, t1_line_ptr, t1_line_array, t1_line_limit);
+ if (t1_in_eexec == 0 && eexec_scan >= 0 && eexec_scan < eexec_len) {
+ if (t1_line_array[eexec_scan] == eexec_str[eexec_scan])
+ eexec_scan++;
+ else
+ eexec_scan = -1;
+ }
+ if (c == 10 || (t1_pfa && eexec_scan == eexec_len && c == 32))
+ break;
+ if (t1_cs && t1_cslen == 0 && (t1_line_ptr - t1_line_array > 4) &&
+ (t1_suffix(" RD ") || t1_suffix(" -| "))) {
+ p = t1_line_ptr - 5;
+ while (*p != ' ')
+ p--;
+ t1_cslen = l = t1_scan_num(p + 1, 0);
+ cs_start = t1_line_ptr - t1_line_array; /* cs_start is an index now */
+ alloc_array(t1_line, l, T1_BUF_SIZE);
+ while (l-- > 0)
+ *t1_line_ptr++ = edecrypt(t1_getbyte());
+ }
+ c = t1_getbyte();
+ }
+ alloc_array(t1_line, 2, T1_BUF_SIZE); /* append_eol can append 2 chars */
+ append_eol(t1_line_ptr, t1_line_array, t1_line_limit);
+ if (t1_line_ptr - t1_line_array < 2)
+ goto restart;
+ if (eexec_scan == eexec_len)
+ t1_in_eexec = 1;
+exit:
+ /* ensure that t1_buf_array has as much room as t1_line_array */
+ t1_buf_ptr = t1_buf_array;
+ alloc_array(t1_buf, t1_line_limit, t1_line_limit);
+}
+
+static void t1_putline(void)
+{
+ char *p = t1_line_array;
+ if (t1_line_ptr - t1_line_array <= 1)
+ return;
+ if (t1_eexec_encrypt) {
+ while (p < t1_line_ptr)
+ out_eexec_char(eencrypt(*p++));
+ }
+ else
+ while (p < t1_line_ptr)
+ t1_putchar(*p++);
+}
+
+static void t1_puts(const char *s)
+{
+ if (s != t1_line_array)
+ strcpy(t1_line_array, s);
+ t1_line_ptr = strend(t1_line_array);
+ t1_putline();
+}
+
+static void t1_printf(const char *fmt,...)
+{
+ va_list args;
+ va_start(args, fmt);
+ vsprintf(t1_line_array, fmt, args);
+ t1_puts(t1_line_array);
+ va_end(args);
+}
+
+static void t1_init_params(const char *open_name_prefix)
+{
+ t1_log(open_name_prefix);
+ t1_log(cur_file_name);
+ t1_lenIV = 4;
+ t1_dr = 55665;
+ t1_er = 55665;
+ t1_in_eexec = 0;
+ t1_cs = false;
+ t1_scan = true;
+ t1_synthetic = false;
+ t1_eexec_encrypt = false;
+ t1_block_length = 0;
+ t1_check_pfa();
+}
+
+static void t1_close_font_file(const char *close_name_suffix)
+{
+ t1_log(close_name_suffix);
+ t1_close();
+ cur_file_name = NULL;
+}
+
+static void t1_check_block_len(boolean decrypt)
+{
+ int l, c;
+ if (t1_block_length == 0)
+ return;
+ c = t1_getbyte();
+ if (decrypt)
+ c = edecrypt(c);
+ l = t1_block_length;
+ if (!(l == 0 && (c == 10 || c == 13))) {
+ pdftex_warn("%i bytes more than expected were ignored", l + 1);
+ while (l-- > 0)
+ t1_getbyte();
+ }
+}
+
+static void t1_start_eexec(void)
+{
+ int i;
+ if (is_included(fm_cur)) {
+ get_length1();
+ save_offset();
+ }
+ if (!t1_pfa)
+ t1_check_block_len(false);
+ for (t1_line_ptr = t1_line_array, i = 0; i < 4; i++) {
+ edecrypt(t1_getbyte());
+ *t1_line_ptr++ = 0;
+ }
+ t1_eexec_encrypt = true;
+ if (is_included(fm_cur))
+ t1_putline(); /* to put the first four bytes */
+}
+
+static void t1_stop_eexec(void)
+{
+ int c;
+ if (is_included(fm_cur)) {
+ get_length2();
+ save_offset();
+ }
+ end_last_eexec_line();
+ if (!t1_pfa)
+ t1_check_block_len(true);
+ else {
+ c = edecrypt(t1_getbyte());
+ if (!(c == 10 || c == 13)) {
+ if (last_hexbyte == 0)
+ t1_puts("00");
+ else
+ pdftex_warn("unexpected data after eexec");
+ }
+ }
+ t1_cs = false;
+ t1_in_eexec = 2;
+}
+
+#ifdef pdfTeX
+static void t1_modify_fm(void)
+{
+ /*
+ * font matrix is given as six numbers a0..a5, which stands for the matrix
+ *
+ * a0 a1 0
+ * M = a2 a3 0
+ * a4 a5 1
+ *
+ * ExtendFont is given as
+ *
+ * e 0 0
+ * E = 0 1 0
+ * 0 0 1
+ *
+ * SlantFont is given as
+ *
+ * 1 0 0
+ * S = s 1 0
+ * 0 0 1
+ *
+ * and the final transformation is
+ *
+ * e*a0 e*a1 0
+ * F = E.S.M = s*e*a0+a2 s*e*a1+a3 0
+ * a4 a5 1
+ */
+ float e, s, a[6], b[6];
+ int i, c;
+ char *p, *q, *r;
+ if ((p = strchr(t1_line_array, '[')) == 0)
+ if ((p = strchr(t1_line_array, '{')) == 0) {
+ remove_eol(p, t1_line_array);
+ pdftex_fail("FontMatrix: an array expected: `%s'", t1_line_array);
+ }
+ c = *p++; /* save the character '[' resp. '{' */
+ strncpy(t1_buf_array, t1_line_array, (unsigned)(p - t1_line_array));
+ r = t1_buf_array + (p - t1_line_array);
+ for (i = 0; i < 6; i++) {
+ a[i] = t1_scan_num(p, &q);
+ p = q;
+ }
+ if (fm_extend(fm_cur) != 0)
+ e = fm_extend(fm_cur)*1E-3;
+ else
+ e = 1;
+ s = fm_slant(fm_cur)*1E-3;
+ b[0] = e*a[0];
+ b[1] = e*a[1];
+ b[2] = s*e*a[0] + a[2];
+ b[3] = s*e*a[1] + a[3];
+ b[4] = a[4];
+ b[5] = a[5];
+ for (i = 0; i < 6; i++) {
+ sprintf(r, "%g ", b[i]);
+ r = strend(r);
+ }
+ if (c == '[') {
+ while (*p != ']' && *p != 0)
+ p++;
+ }
+ else {
+ while (*p != '}' && *p != 0)
+ p++;
+ }
+ if (*p == 0) {
+ remove_eol(p, t1_line_array);
+ pdftex_fail("FontMatrix: cannot find the corresponding character to '%c': `%s'", c, t1_line_array);
+ }
+ strcpy(r, p);
+ strcpy(t1_line_array, t1_buf_array);
+ t1_line_ptr = eol(t1_line_array);
+}
+
+static void t1_modify_italic(void)
+{
+ float a;
+ char *p, *r;
+ if (fm_slant(fm_cur) == 0)
+ return;
+ p = strchr(t1_line_array, ' ');
+ strncpy(t1_buf_array, t1_line_array, (unsigned)(p - t1_line_array + 1));
+ a = t1_scan_num(p + 1, &r);
+ a -= atan(fm_slant(fm_cur)*1E-3)*(180/M_PI);
+ sprintf(t1_buf_array + (p - t1_line_array + 1), "%g", a);
+ strcpy(strend(t1_buf_array), r);
+ strcpy(t1_line_array, t1_buf_array);
+ t1_line_ptr = eol(t1_line_array);
+ font_keys[ITALIC_ANGLE_CODE].value = round(a);
+ font_keys[ITALIC_ANGLE_CODE].valid = true;
+}
+
+static void t1_scan_keys(void)
+{
+ int i, k;
+ char *p, *q, *r;
+ key_entry *key;
+ if (fm_extend(fm_cur) != 0 || fm_slant(fm_cur) != 0) {
+ if (t1_prefix("/FontMatrix")) {
+ t1_modify_fm();
+ return;
+ }
+ if (t1_prefix("/ItalicAngle")) {
+ t1_modify_italic();
+ return;
+ }
+ }
+ if (t1_prefix("/FontType")) {
+ p = t1_line_array + strlen("FontType") + 1;
+ if ((i = t1_scan_num(p, 0)) != 1)
+ pdftex_fail("Type%d fonts unsupported by pdfTeX", i);
+ return;
+ }
+ for (key = font_keys; key - font_keys < MAX_KEY_CODE; key++)
+ if (strncmp(t1_line_array + 1, key->t1name, strlen(key->t1name)) == 0)
+ break;
+ if (key - font_keys == MAX_KEY_CODE)
+ return;
+ key->valid = true;
+ p = t1_line_array + strlen(key->t1name) + 1;
+ skip(p, ' ');
+ if ((k = key - font_keys) == FONTNAME_CODE) {
+ if (*p != '/') {
+ remove_eol(p, t1_line_array);
+ pdftex_fail("a name expected: `%s'", t1_line_array);
+ }
+ r = ++p; /* skip the slash */
+ for (q = t1_buf_array; *p != ' ' && *p != 10; *q++ = *p++);
+ *q = 0;
+ if (fm_slant(fm_cur) != 0) {
+ sprintf(q, "-Slant_%i", (int)fm_slant(fm_cur));
+ q = strend(q);
+ }
+ if (fm_extend(fm_cur) != 0) {
+ sprintf(q, "-Extend_%i", (int)fm_extend(fm_cur));
+ }
+ strncpy(fontname_buf, t1_buf_array, FONTNAME_BUF_SIZE);
+ /* at this moment we cannot call make_subset_tag() yet, as the encoding
+ * is not read; thus we mark the offset of the subset tag and write it
+ * later */
+ if (is_included(fm_cur) && is_subsetted(fm_cur)) {
+ t1_fontname_offset = t1_offset() + (r - t1_line_array);
+ strcpy(t1_buf_array, p);
+ sprintf(r, "ABCDEF+%s%s", fontname_buf, t1_buf_array);
+ t1_line_ptr = eol(r);
+ }
+ return;
+ }
+ if ((k == STEMV_CODE || k == FONTBBOX1_CODE) &&
+ (*p == '[' || *p == '{'))
+ p++;
+ if (k == FONTBBOX1_CODE) {
+ for (i = 0; i < 4; i++) {
+ key[i].value = t1_scan_num(p, &r);
+ p = r;
+ }
+ return;
+ }
+ key->value = t1_scan_num(p, 0);
+}
+
+#endif /* pdfTeX */
+
+static void t1_scan_param(void)
+{
+ static const char *lenIV = "/lenIV";
+ if (!t1_scan || *t1_line_array != '/')
+ return;
+ if (t1_prefix(lenIV)) {
+ t1_lenIV = t1_scan_num(t1_line_array + strlen(lenIV), 0);
+ return;
+ }
+ t1_scan_keys();
+}
+
+static void copy_glyph_names(char **glyph_names, int a, int b)
+{
+ if (glyph_names[b] != notdef) {
+ free(glyph_names[b]);
+ glyph_names[b] = (char*) notdef;
+ }
+ if (glyph_names[a] != notdef) {
+ glyph_names[b] = xstrdup(glyph_names[a]);
+ }
+}
+
+static void t1_builtin_enc(void)
+{
+ int i, a, b, c, counter = 0;
+ char *r, *p;
+ /*
+ * At this moment "/Encoding" is the prefix of t1_line_array
+ */
+ if (t1_suffix("def")) { /* predefined encoding */
+ sscanf(t1_line_array + strlen("/Encoding"), "%256s", t1_buf_array);
+ if (strcmp(t1_buf_array, "StandardEncoding") == 0) {
+ for (i = 0; i <= MAX_CHAR_CODE; i++)
+ if (standard_glyph_names[i] == notdef)
+ t1_builtin_glyph_names[i] = (char*) notdef;
+ else
+ t1_builtin_glyph_names[i] = xstrdup(standard_glyph_names[i]);
+ t1_encoding = ENC_STANDARD;
+ }
+ else
+ pdftex_fail("cannot subset font (unknown predefined encoding `%s')",
+ t1_buf_array);
+ return;
+ } else
+ t1_encoding = ENC_BUILTIN;
+ /*
+ * At this moment "/Encoding" is the prefix of t1_line_array, and the encoding is
+ * not a predefined encoding
+ *
+ * We have two possible forms of Encoding vector. The first case is
+ *
+ * /Encoding [/a /b /c...] readonly def
+ *
+ * and the second case can look like
+ *
+ * /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for
+ * dup 0 /x put
+ * dup 1 /y put
+ * ...
+ * readonly def
+ */
+ for (i = 0; i <= MAX_CHAR_CODE; i++)
+ t1_builtin_glyph_names[i] = (char*) notdef;
+ if (t1_prefix("/Encoding [") || t1_prefix("/Encoding[")) { /* the first case */
+ r = strchr(t1_line_array, '[') + 1;
+ skip(r, ' ');
+ for(;;) {
+ while (*r == '/') {
+ for (p = t1_buf_array, r++;
+ *r != 32 && *r != 10 && *r != ']' && *r != '/';
+ *p++ = *r++);
+ *p = 0;
+ skip(r, ' ');
+ if (counter > MAX_CHAR_CODE)
+ pdftex_fail("encoding vector contains more than %i names",
+ (int)(MAX_CHAR_CODE + 1));
+ if (strcmp(t1_buf_array, notdef) != 0)
+ t1_builtin_glyph_names[counter] = xstrdup(t1_buf_array);
+ counter++;
+ }
+ if (*r != 10 && *r != '%') {
+ if (str_prefix(r, "] def") || str_prefix(r, "] readonly def"))
+ break;
+ else {
+ remove_eol(r, t1_line_array);
+ pdftex_fail("a name or `] def' or `] readonly def' expected: `%s'",
+ t1_line_array);
+ }
+ }
+ t1_getline();
+ r = t1_line_array;
+ }
+ }
+ else { /* the second case */
+ p = strchr(t1_line_array, 10);
+ for (;;) {
+ if (*p == 10) {
+ t1_getline();
+ p = t1_line_array;
+ }
+ /*
+ check for `dup <index> <glyph> put'
+ */
+ if (sscanf(p, "dup %i%256s put", &i, t1_buf_array) == 2 &&
+ *t1_buf_array == '/' && valid_code(i)) {
+ if (strcmp(t1_buf_array + 1, notdef) != 0)
+ t1_builtin_glyph_names[i] = xstrdup(t1_buf_array + 1);
+ p = strstr(p, " put") + strlen(" put");
+ skip(p, ' ');
+ }
+ /*
+ check for `dup dup <to> exch <from> get put'
+ */
+ else if (sscanf(p, "dup dup %i exch %i get put", &b, &a) == 2 &&
+ valid_code(a) && valid_code(b)) {
+ copy_glyph_names(t1_builtin_glyph_names, a, b);
+ p = strstr(p, " get put") + strlen(" get put");
+ skip(p, ' ');
+ }
+ /*
+ check for `dup dup <from> <size> getinterval <to> exch putinterval'
+ */
+ else if (sscanf(p, "dup dup %i %i getinterval %i exch putinterval",
+ &a, &c, &b) == 3 &&
+ valid_code(a) && valid_code(b) && valid_code(c)) {
+ for (i = 0; i < c; i++)
+ copy_glyph_names(t1_builtin_glyph_names, a + i, b + i);
+ p = strstr(p, " putinterval") + strlen(" putinterval");
+ skip(p, ' ');
+ }
+ /*
+ check for `def' or `readonly def'
+ */
+ else if ((p == t1_line_array || (p > t1_line_array && p[-1] == ' ')) &&
+ strcmp(p, "def\n") == 0)
+ return;
+ /*
+ skip an unrecognizable word
+ */
+ else {
+ while (*p != ' ' && *p != 10)
+ p++;
+ skip(p, ' ');
+ }
+ }
+ }
+}
+
+static void t1_check_end(void)
+{
+ if (t1_eof())
+ return;
+ t1_getline();
+ if (t1_prefix("{restore}"))
+ t1_putline();
+}
+
+#ifdef pdfTeX
+static boolean t1_open_fontfile(const char *open_name_prefix)
+{
+ char *ex_ffname = NULL;
+ ff_entry *ff;
+ ff = check_ff_exist(fm_cur);
+ if (ff->ff_path != NULL)
+ t1_file = xfopen(cur_file_name = ff->ff_path, FOPEN_RBIN_MODE);
+ else {
+ set_cur_file_name(fm_cur->ff_name);
+ pdftex_warn("cannot open Type 1 font file for reading");
+ return false;
+ }
+ t1_init_params(open_name_prefix);
+ fontfile_found = true;
+ return true;
+}
+
+static void t1_scan_only(void)
+{
+ do {
+ t1_getline();
+ t1_scan_param();
+ } while (t1_in_eexec == 0);
+ t1_start_eexec();
+ do {
+ t1_getline();
+ t1_scan_param();
+ } while (!(t1_charstrings() || t1_subrs()));
+}
+
+static void t1_include(void)
+{
+ do {
+ t1_getline();
+ t1_scan_param();
+ t1_putline();
+ } while (t1_in_eexec == 0);
+ t1_start_eexec();
+ do {
+ t1_getline();
+ t1_scan_param();
+ t1_putline();
+ } while (!(t1_charstrings() || t1_subrs()));
+ t1_cs = true;
+ do {
+ t1_getline();
+ t1_putline();
+ } while (!t1_end_eexec());
+ t1_stop_eexec();
+ do {
+ t1_getline();
+ t1_putline();
+ } while (!t1_cleartomark());
+ t1_check_end(); /* write "{restore}if" if found */
+ get_length3();
+}
+
+#else /* not pdfTeX */
+static boolean t1_open_fontfile(char *open_name_prefix)
+{
+ if (!t1_open()) {
+ (void)sprintf(errbuf, "! Couldn't find font file %s", cur_file_name);
+ error(errbuf);
+ }
+ t1_init_params(open_name_prefix);
+ return true;
+}
+#endif /* pdfTeX */
+
+#define check_subr(subr) \
+ if (subr >= subr_size || subr < 0) \
+ pdftex_fail("Subrs array: entry index out of range (%i)", subr);
+
+static const char **check_cs_token_pair()
+{
+ const char **p = (const char**) cs_token_pairs_list;
+ for (; p[0] != NULL; ++p)
+ if (t1_buf_prefix(p[0]) && t1_buf_suffix(p[1]))
+ return p;
+ return NULL;
+}
+
+static void cs_store(boolean is_subr)
+{
+ char *p;
+ cs_entry *ptr;
+ int subr;
+ for (p = t1_line_array, t1_buf_ptr = t1_buf_array; *p != ' '; *t1_buf_ptr++ = *p++);
+ *t1_buf_ptr = 0;
+ if (is_subr) {
+ subr = t1_scan_num(p + 1, 0);
+ check_subr(subr);
+ ptr = subr_tab + subr;
+ }
+ else {
+ ptr = cs_ptr++;
+ if (cs_ptr - cs_tab > cs_size)
+ pdftex_fail("CharStrings dict: more entries than dict size (%i)", cs_size);
+ if (strcmp(t1_buf_array + 1, notdef) == 0) /* skip the slash */
+ ptr->name = (char*) notdef;
+ else
+ ptr->name = xstrdup(t1_buf_array + 1);
+ }
+ /* copy " RD " + cs data to t1_buf_array */
+ memcpy(t1_buf_array, t1_line_array + cs_start - 4, (unsigned)(t1_cslen + 4));
+ /* copy the end of cs data to t1_buf_array */
+ for (p = t1_line_array + cs_start + t1_cslen, t1_buf_ptr = t1_buf_array + t1_cslen + 4;
+ *p != 10; *t1_buf_ptr++ = *p++);
+ *t1_buf_ptr++ = 10;
+ if (is_subr && cs_token_pair == NULL)
+ cs_token_pair = check_cs_token_pair();
+ ptr->len = t1_buf_ptr - t1_buf_array;
+ ptr->cslen = t1_cslen;
+ ptr->data = xtalloc(ptr->len, byte);
+ memcpy(ptr->data, t1_buf_array, ptr->len);
+ ptr->valid = true;
+}
+
+#define store_subr() cs_store(true)
+#define store_cs() cs_store(false)
+
+#define CC_STACK_SIZE 24
+
+static integer cc_stack[CC_STACK_SIZE], *stack_ptr = cc_stack;
+static cc_entry cc_tab[CS_MAX];
+static boolean is_cc_init = false;
+
+
+#define cc_pop(N) \
+ if (stack_ptr - cc_stack < (N)) \
+ stack_error(N); \
+ stack_ptr -= N
+
+#define stack_error(N) { \
+ pdftex_warn("CharString: invalid access (%i) to stack (%i entries)", \
+ N, stack_ptr - cc_stack); \
+ goto cs_error; \
+}
+
+/*
+static integer cc_get(integer index)
+{
+ if (index < 0) {
+ if (stack_ptr + index < cc_stack )
+ stack_error(stack_ptr - cc_stack + index);
+ return *(stack_ptr + index);
+ }
+ else {
+ if (cc_stack + index >= stack_ptr)
+ stack_error(index);
+ return cc_stack[index];
+ }
+}
+*/
+
+#define cc_get(N) ((N) < 0 ? *(stack_ptr + (N)) : *(cc_stack + (N)))
+
+#define cc_push(V) *stack_ptr++ = V
+#define cc_clear() stack_ptr = cc_stack
+
+#define set_cc(N, B, A, C) \
+ cc_tab[N].nargs = A; \
+ cc_tab[N].bottom = B; \
+ cc_tab[N].clear = C; \
+ cc_tab[N].valid = true
+
+static void cc_init(void)
+{
+ int i;
+ if (is_cc_init)
+ return;
+ for (i = 0; i < CS_MAX; i++)
+ cc_tab[i].valid = false;
+ set_cc(CS_HSTEM, true, 2, true);
+ set_cc(CS_VSTEM, true, 2, true);
+ set_cc(CS_VMOVETO, true, 1, true);
+ set_cc(CS_RLINETO, true, 2, true);
+ set_cc(CS_HLINETO, true, 1, true);
+ set_cc(CS_VLINETO, true, 1, true);
+ set_cc(CS_RRCURVETO, true, 6, true);
+ set_cc(CS_CLOSEPATH, false, 0, true);
+ set_cc(CS_CALLSUBR, false, 1, false);
+ set_cc(CS_RETURN, false, 0, false);
+ /*
+ set_cc(CS_ESCAPE, false, 0, false);
+ */
+ set_cc(CS_HSBW, true, 2, true);
+ set_cc(CS_ENDCHAR, false, 0, true);
+ set_cc(CS_RMOVETO, true, 2, true);
+ set_cc(CS_HMOVETO, true, 1, true);
+ set_cc(CS_VHCURVETO, true, 4, true);
+ set_cc(CS_HVCURVETO, true, 4, true);
+ set_cc(CS_DOTSECTION, false, 0, true);
+ set_cc(CS_VSTEM3, true, 6, true);
+ set_cc(CS_HSTEM3, true, 6, true);
+ set_cc(CS_SEAC, true, 5, true);
+ set_cc(CS_SBW, true, 4, true);
+ set_cc(CS_DIV, false, 2, false);
+ set_cc(CS_CALLOTHERSUBR, false, 0, false);
+ set_cc(CS_POP, false, 0, false);
+ set_cc(CS_SETCURRENTPOINT, true, 2, true);
+ is_cc_init = true;
+}
+
+#define cs_getchar() cdecrypt(*data++, &cr)
+
+#define mark_subr(n) cs_mark(0, n)
+#define mark_cs(s) cs_mark(s, 0)
+
+static void cs_warn(const char *cs_name, int subr, const char *fmt,...)
+{
+ char buf[SMALL_BUF_SIZE];
+ va_list args;
+ va_start(args, fmt);
+ vsprintf(buf, fmt, args);
+ va_end(args);
+ if (cs_name == NULL)
+ pdftex_warn("Subr (%i): %s", (int)subr, buf);
+ else
+ pdftex_warn("CharString (/%s): %s", cs_name, buf);
+}
+
+static void cs_mark(const char *cs_name, int subr)
+{
+ byte *data;
+ int i, b, cs_len;
+ integer a, a1, a2;
+ unsigned short cr;
+ static integer lastargOtherSubr3 = 3; /* the argument of last call to
+ OtherSubrs[3] */
+ cs_entry *ptr;
+ cc_entry *cc;
+ if (cs_name == NULL) {
+ check_subr(subr);
+ ptr = subr_tab + subr;
+ if (!ptr->valid)
+ return;
+ }
+ else {
+ if (cs_notdef != NULL &&
+ (cs_name == notdef || strcmp(cs_name, notdef) == 0))
+ ptr = cs_notdef;
+ else {
+ for (ptr = cs_tab; ptr < cs_ptr; ptr++)
+ if (strcmp(ptr->name, cs_name) == 0)
+ break;
+ if (ptr == cs_ptr) {
+ pdftex_warn("glyph `%s' undefined", cs_name);
+ return;
+ }
+ if (ptr->name == notdef)
+ cs_notdef = ptr;
+ }
+ }
+ /* only marked CharString entries and invalid entries can be skipped;
+ valid marked subrs must be parsed to keep the stack in sync */
+ if (!ptr->valid || (ptr->used && cs_name != NULL))
+ return;
+ ptr->used = true;
+ cr = 4330;
+ cs_len = ptr->cslen;
+ data = ptr->data + 4;
+ for (i = 0; i < t1_lenIV; i++, cs_len--)
+ cs_getchar();
+ while (cs_len > 0) {
+ --cs_len;
+ b = cs_getchar();
+ if (b >= 32) {
+ if (b <= 246)
+ a = b - 139;
+ else if (b <= 250) {
+ --cs_len;
+ a = ((b - 247) << 8) + 108 + cs_getchar();
+ }
+ else if (b <= 254) {
+ --cs_len;
+ a = -((b - 251) << 8) - 108 - cs_getchar();
+ }
+ else {
+ cs_len -= 4;
+ a = (cs_getchar() & 0xff) << 24;
+ a |= (cs_getchar() & 0xff) << 16;
+ a |= (cs_getchar() & 0xff) << 8;
+ a |= (cs_getchar() & 0xff) << 0;
+ if (sizeof(integer) > 4 && (a & 0x80000000))
+ a |= ~0x7FFFFFFF;
+ }
+ cc_push(a);
+ }
+ else {
+ if (b == CS_ESCAPE) {
+ b = cs_getchar() + CS_1BYTE_MAX;
+ cs_len--;
+ }
+ if (b >= CS_MAX) {
+ cs_warn(cs_name, subr, "command value out of range: %i", (int)b);
+ goto cs_error;
+ }
+ cc = cc_tab + b;
+ if (!cc->valid) {
+ cs_warn(cs_name, subr, "command not valid: %i", (int)b);
+ goto cs_error;
+ }
+ if (cc->bottom) {
+ if (stack_ptr - cc_stack < cc->nargs)
+ cs_warn(cs_name, subr,
+ "less arguments on stack (%i) than required (%i)",
+ (int)(stack_ptr - cc_stack), (int)cc->nargs);
+ else if (stack_ptr - cc_stack > cc->nargs)
+ cs_warn(cs_name, subr,
+ "more arguments on stack (%i) than required (%i)",
+ (int)(stack_ptr - cc_stack), (int)cc->nargs);
+ }
+ switch (cc - cc_tab) {
+ case CS_CALLSUBR:
+ a1 = cc_get(-1);
+ cc_pop(1);
+ mark_subr(a1);
+ if (!subr_tab[a1].valid) {
+ cs_warn(cs_name, subr,
+ "cannot call subr (%i)", (int)a1);
+ goto cs_error;
+ }
+ break;
+ case CS_DIV:
+ cc_pop(2);
+ cc_push(0);
+ break;
+ case CS_CALLOTHERSUBR:
+ if (cc_get(-1) == 3)
+ lastargOtherSubr3 = cc_get(-3);
+ a1 = cc_get(-2) + 2;
+ cc_pop(a1);
+ break;
+ case CS_POP:
+ cc_push(lastargOtherSubr3);
+ /* the only case when we care about the value being pushed onto
+ stack is when POP follows CALLOTHERSUBR (changing hints by
+ OtherSubrs[3])
+ */
+ break;
+ case CS_SEAC:
+ a1 = cc_get(3);
+ a2 = cc_get(4);
+ cc_clear();
+ mark_cs(standard_glyph_names[a1]);
+ mark_cs(standard_glyph_names[a2]);
+ break;
+ default:
+ if (cc->clear)
+ cc_clear();
+ }
+ }
+ }
+ return;
+cs_error: /* an error occured during parsing */
+ cc_clear();
+ ptr->valid = false;
+ ptr->used = false;
+}
+
+static void t1_subset_ascii_part(void)
+{
+ int i, j;
+ t1_getline();
+ while (!t1_prefix("/Encoding")) {
+ t1_scan_param();
+ t1_putline();
+ t1_getline();
+ }
+ t1_builtin_enc();
+ if (is_reencoded(fm_cur))
+ t1_glyph_names = external_enc();
+ else
+ t1_glyph_names = t1_builtin_glyph_names;
+ if (is_included(fm_cur) && is_subsetted(fm_cur)) {
+ make_subset_tag(fm_cur, t1_glyph_names);
+ update_subset_tag();
+ }
+ if (t1_encoding == ENC_STANDARD)
+ t1_puts("/Encoding StandardEncoding def\n");
+ else {
+ t1_puts("/Encoding 256 array\n0 1 255 {1 index exch /.notdef put} for\n");
+ for (i = 0, j = 0; i <= MAX_CHAR_CODE; i++) {
+ if (is_used_char(i) && t1_glyph_names[i] != notdef) {
+ j++;
+ t1_printf("dup %i /%s put\n", (int)t1_char(i), t1_glyph_names[i]);
+ }
+ }
+ /* We didn't mark anything for the Encoding array. */
+ /* We add "dup 0 /.notdef put" for compatibility */
+ /* with Acrobat 5.0. */
+ if (j == 0)
+ t1_puts("dup 0 /.notdef put\n");
+ t1_puts("readonly def\n");
+ }
+ do {
+ t1_getline();
+ t1_scan_param();
+ if (!t1_prefix("/UniqueID")) /* ignore UniqueID for subsetted fonts */
+ t1_putline();
+ } while (t1_in_eexec == 0);
+}
+
+#define t1_subr_flush() t1_flush_cs(true)
+#define t1_cs_flush() t1_flush_cs(false)
+
+static void t1_flush_cs(boolean);
+
+static void cs_init(void)
+{
+ cs_ptr = cs_tab = NULL;
+ cs_dict_start = cs_dict_end = NULL;
+ cs_count = cs_size = cs_size_pos = 0;
+ cs_token_pair = NULL;
+ subr_tab = NULL;
+ subr_array_start = subr_array_end = NULL;
+ subr_max = subr_size = subr_size_pos = 0;
+}
+
+static void init_cs_entry(cs_entry *cs)
+{
+ cs->data = NULL;
+ cs->name = NULL;
+ cs->len = 0;
+ cs->cslen = 0;
+ cs->used = false;
+ cs->valid = false;
+}
+
+static void t1_mark_glyphs(void);
+
+static void t1_read_subrs(void)
+{
+ int i, s;
+ cs_entry *ptr;
+ t1_getline();
+ while (!(t1_charstrings() || t1_subrs())) {
+ t1_scan_param();
+ t1_putline();
+ t1_getline();
+ }
+found:
+ t1_cs = true;
+ t1_scan = false;
+ if (!t1_subrs())
+ return;
+ subr_size_pos = strlen("/Subrs") + 1;
+ /* subr_size_pos points to the number indicating dict size after "/Subrs" */
+ subr_size = t1_scan_num(t1_line_array + subr_size_pos, 0);
+ if (subr_size == 0) {
+ while (!t1_charstrings())
+ t1_getline();
+ return;
+ }
+ subr_tab = xtalloc(subr_size, cs_entry);
+ for (ptr = subr_tab; ptr - subr_tab < subr_size; ptr++)
+ init_cs_entry(ptr);
+ subr_array_start = xstrdup(t1_line_array);
+ t1_getline();
+ while (t1_cslen) {
+ store_subr();
+ t1_getline();
+ }
+ /* mark the first four entries without parsing */
+ for (i = 0; i < subr_size && i < 4; i++)
+ subr_tab[i].used = true;
+ /* the end of the Subrs array might have more than one line so we need to
+ concatnate them to subr_array_end. Unfortunately some fonts don't have
+ the Subrs array followed by the CharStrings dict immediately (synthetic
+ fonts). If we cannot find CharStrings in next POST_SUBRS_SCAN lines then
+ we will treat the font as synthetic and ignore everything until next
+ Subrs is found
+ */
+#define POST_SUBRS_SCAN 5
+ s = 0;
+ *t1_buf_array = 0;
+ for (i = 0; i < POST_SUBRS_SCAN; i++) {
+ if (t1_charstrings())
+ break;
+ s += t1_line_ptr - t1_line_array;
+ alloc_array(t1_buf, s, T1_BUF_SIZE);
+ strcat(t1_buf_array, t1_line_array);
+ t1_getline();
+ }
+ subr_array_end = xstrdup(t1_buf_array);
+ if (i == POST_SUBRS_SCAN) { /* CharStrings not found;
+ suppose synthetic font */
+ for (ptr = subr_tab; ptr - subr_tab < subr_size; ptr++)
+ if (ptr->valid)
+ xfree(ptr->data);
+ xfree(subr_tab);
+ xfree(subr_array_start);
+ xfree(subr_array_end);
+ cs_init();
+ t1_cs = false;
+ t1_synthetic = true;
+ while (!(t1_charstrings() || t1_subrs()))
+ t1_getline();
+ goto found;
+ }
+}
+
+static void t1_flush_cs(boolean is_subr)
+{
+ char *p;
+ byte *r, *return_cs = NULL;
+ cs_entry *tab, *end_tab, *ptr;
+ char *start_line, *line_end;
+ int count, size_pos;
+ unsigned short cr, cs_len;
+ if (is_subr) {
+ start_line = subr_array_start;
+ line_end = subr_array_end;
+ size_pos = subr_size_pos;
+ tab = subr_tab;
+ count = subr_max + 1;
+ end_tab = subr_tab + count;
+ }
+ else {
+ start_line = cs_dict_start;
+ line_end = cs_dict_end;
+ size_pos = cs_size_pos;
+ tab = cs_tab;
+ end_tab = cs_ptr;
+ count = cs_count;
+ }
+ t1_line_ptr = t1_line_array;
+ for (p = start_line; p - start_line < size_pos;)
+ *t1_line_ptr++ = *p++;
+ while (isdigit(*p))
+ p++;
+ sprintf(t1_line_ptr, "%u", count);
+ strcat(t1_line_ptr, p);
+ t1_line_ptr = eol(t1_line_array);
+ t1_putline();
+
+ /* create return_cs to replace unsused subr's */
+ if (is_subr) {
+ cr = 4330;
+ cs_len = 0;
+ return_cs = xtalloc(t1_lenIV + 1, byte);
+ if (t1_lenIV > 0) {
+ for (cs_len = 0, r = return_cs; cs_len < t1_lenIV; cs_len++, r++)
+ *r = cencrypt(0x00, &cr);
+ *r = cencrypt(CS_RETURN, &cr);
+ }
+ else {
+ *return_cs = CS_RETURN;
+ }
+ cs_len++;
+ }
+
+ for (ptr = tab; ptr < end_tab; ptr++) {
+ if (ptr->used) {
+ if (is_subr)
+ sprintf(t1_line_array, "dup %u %u", ptr - tab, ptr->cslen);
+ else
+ sprintf(t1_line_array, "/%s %u", ptr->name, ptr->cslen);
+ p = strend(t1_line_array);
+ memcpy(p, ptr->data, ptr->len);
+ t1_line_ptr = p + ptr->len;
+ t1_putline();
+ }
+ else {
+ /* replace unsused subr's by return_cs */
+ if (is_subr) {
+ sprintf(t1_line_array, "dup %u %u%s ", ptr - tab, cs_len,
+ cs_token_pair[0]);
+ p = strend(t1_line_array);
+ memcpy(p, return_cs, cs_len);
+ t1_line_ptr = p + cs_len;
+ t1_putline();
+ sprintf(t1_line_array, " %s", cs_token_pair[1]);
+ t1_line_ptr = eol(t1_line_array);
+ t1_putline();
+ }
+ }
+ xfree(ptr->data);
+ if (ptr->name != notdef)
+ xfree(ptr->name);
+ }
+ sprintf(t1_line_array, "%s", line_end);
+ t1_line_ptr = eol(t1_line_array);
+ t1_putline();
+ if (is_subr)
+ xfree(return_cs);
+ xfree(tab);
+ xfree(start_line);
+ xfree(line_end);
+}
+
+static void t1_mark_glyphs(void)
+{
+ int i;
+ char *charset = extra_charset();
+ char *g, *s, *r;
+ cs_entry *ptr;
+ if (t1_synthetic || embed_all_glyphs(tex_font)) { /* mark everything */
+ if (cs_tab != NULL)
+ for (ptr = cs_tab; ptr < cs_ptr; ptr++)
+ if (ptr->valid)
+ ptr->used = true;
+ if (subr_tab != NULL) {
+ for (ptr = subr_tab; ptr - subr_tab < subr_size; ptr++)
+ if (ptr->valid)
+ ptr->used = true;
+ subr_max = subr_size - 1;
+ }
+ return;
+ }
+ mark_cs(notdef);
+ for (i = 0; i <= MAX_CHAR_CODE; i++)
+ if (is_used_char(i)) {
+ if (t1_glyph_names[i] == notdef)
+ pdftex_warn("character %i is mapped to %s", i, notdef);
+ else
+ mark_cs(t1_glyph_names[i]);
+ }
+ if (charset == NULL)
+ goto set_subr_max;
+ g = s = charset + 1; /* skip the first '/' */
+ r = strend(g);
+ while (g < r) {
+ while (*s != '/' && s < r)
+ s++;
+ *s = 0; /* terminate g by rewriting '/' to 0 */
+ mark_cs(g);
+ g = s + 1;
+ }
+set_subr_max:
+ if (subr_tab != NULL)
+ for (subr_max = -1, ptr = subr_tab; ptr - subr_tab < subr_size; ptr++)
+ if (ptr->used && ptr - subr_tab > subr_max)
+ subr_max = ptr - subr_tab;
+}
+
+static void t1_subset_charstrings(void)
+{
+ cs_entry *ptr;
+ cs_size_pos = strstr(t1_line_array, charstringname) + strlen(charstringname)
+ - t1_line_array + 1;
+ /* cs_size_pos points to the number indicating
+ dict size after "/CharStrings" */
+ cs_size = t1_scan_num(t1_line_array + cs_size_pos, 0);
+ cs_ptr = cs_tab = xtalloc(cs_size, cs_entry);
+ for (ptr = cs_tab; ptr - cs_tab < cs_size; ptr++)
+ init_cs_entry(ptr);
+ cs_notdef = NULL;
+ cs_dict_start = xstrdup(t1_line_array);
+ t1_getline();
+ while (t1_cslen) {
+ store_cs();
+ t1_getline();
+ }
+ cs_dict_end = xstrdup(t1_line_array);
+ t1_mark_glyphs();
+ if (subr_tab != NULL) {
+ if (cs_token_pair == NULL)
+ pdftex_fail("This Type 1 font uses mismatched subroutine begin/end token pairs.");
+ t1_subr_flush();
+ }
+ for (cs_count = 0, ptr = cs_tab; ptr < cs_ptr; ptr++)
+ if (ptr->used)
+ cs_count++;
+ t1_cs_flush();
+}
+
+static void t1_subset_end(void)
+{
+ if (t1_synthetic) { /* copy to "dup /FontName get exch definefont pop" */
+ while (!strstr(t1_line_array, "definefont")) {
+ t1_getline();
+ t1_putline();
+ }
+ while (!t1_end_eexec())
+ t1_getline(); /* ignore the rest */
+ t1_putline(); /* write "mark currentfile closefile" */
+ }
+ else while (!t1_end_eexec()) { /* copy to "mark currentfile closefile" */
+ t1_getline();
+ t1_putline();
+ }
+ t1_stop_eexec();
+ while (!t1_cleartomark()) {
+ t1_getline();
+ t1_putline();
+ }
+ if (!t1_synthetic) /* don't check "{restore}if" for synthetic fonts */
+ t1_check_end(); /* write "{restore}if" if found */
+ get_length3();
+}
+
+void writet1(void)
+{
+ read_encoding_only = false;
+#ifdef pdfTeX
+ t1_save_offset = 0;
+ if (strcasecmp(strend(fm_fontfile(fm_cur)) - 4, ".otf") == 0) {
+ if (!is_included(fm_cur) || is_subsetted(fm_cur))
+ pdftex_fail("OTF fonts must be included entirely");
+ writeotf();
+ is_otf_font = true;
+ return;
+ }
+#endif
+ if (!is_included(fm_cur)) { /* scan parameters from font file */
+ if (!t1_open_fontfile("{"))
+ return;
+ t1_scan_only();
+ t1_close_font_file("}");
+ return;
+ }
+ if (!is_subsetted(fm_cur)) { /* include entire font */
+ if (!t1_open_fontfile("<<"))
+ return;
+ t1_include();
+ t1_close_font_file(">>");
+ return;
+ }
+ /* partial downloading */
+ if (!t1_open_fontfile("<"))
+ return;
+ t1_subset_ascii_part();
+ t1_start_eexec();
+ cc_init();
+ cs_init();
+ t1_read_subrs();
+ t1_subset_charstrings();
+ t1_subset_end();
+ t1_close_font_file(">");
+}
+
+void t1_free()
+{
+ xfree(t1_line_array);
+ xfree(t1_buf_array);
+}
+
+#ifndef pdfTeX
+boolean t1_subset(char *fontfile, char *encfile, unsigned char *g)
+{
+ int i;
+ cur_enc_name = encfile;
+ for (i = 0; i <= MAX_CHAR_CODE; i++)
+ ext_glyph_names[i] = (char*) notdef;
+ if (cur_enc_name != NULL)
+ load_enc(cur_enc_name, ext_glyph_names);
+ grid = g;
+ cur_file_name = fontfile;
+ hexline_length = 0;
+ writet1();
+ for (i = 0; i <= MAX_CHAR_CODE; i++)
+ if (ext_glyph_names[i] != notdef)
+ free(ext_glyph_names[i]);
+ return 1 ; /* note: there *is* no unsuccessful return */
+}
+
+boolean t1_subset_2(char *fontfile, unsigned char *g, char *extraGlyphs)
+{
+ int i;
+ for (i = 0; i <= MAX_CHAR_CODE; i++)
+ ext_glyph_names[i] = (char*) notdef;
+ grid = g;
+ cur_file_name = fontfile;
+ hexline_length = 0;
+ dvips_extra_charset = extraGlyphs ;
+ writet1();
+ for (i = 0; i <= MAX_CHAR_CODE; i++)
+ if (ext_glyph_names[i] != notdef)
+ free(ext_glyph_names[i]);
+ return 1 ; /* note: there *is* no unsuccessful return */
+}
+#endif /* not pdfTeX */
diff --git a/Build/source/texk/web2c/pdftexdir/writet3.c b/Build/source/texk/web2c/pdftexdir/writet3.c
new file mode 100644
index 00000000000..fa9c09bc3d1
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/writet3.c
@@ -0,0 +1,389 @@
+/*
+Copyright (c) 1996-2002 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX 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.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/writet3.c#9 $
+*/
+
+#include "ptexlib.h"
+#include <kpathsea/tex-glyph.h>
+#include <kpathsea/magstep.h>
+
+#define T3_BUF_SIZE 1024
+
+static const char perforce_id[] =
+ "$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/writet3.c#9 $";
+
+/* define t3_line_ptr, t3_line_array & t3_line_limit */
+typedef char t3_line_entry;
+define_array(t3_line);
+
+FILE *t3_file;
+static boolean t3_image_used;
+
+static integer t3_char_procs[MAX_CHAR_CODE + 1];
+static float t3_char_widths[MAX_CHAR_CODE + 1];
+static int t3_glyph_num;
+static float t3_font_scale;
+static integer t3_b0, t3_b1, t3_b2, t3_b3;
+static boolean is_pk_font;
+
+#define t3_open() \
+ open_input(&t3_file, kpse_miscfonts_format, FOPEN_RBIN_MODE)
+#define t3_close() xfclose(t3_file, cur_file_name)
+#define t3_getchar() xgetc(t3_file)
+#define t3_eof() feof(t3_file)
+#define t3_prefix(s) (!strncmp(t3_line_array, s, strlen(s)))
+#define t3_putchar(c) pdfout(c)
+
+#define t3_check_eof() \
+ if (t3_eof()) \
+ pdftex_fail("unexpected end of file");
+
+static void t3_getline(void)
+{
+ int c;
+restart:
+ t3_line_ptr = t3_line_array;
+ c = t3_getchar();
+ while (!t3_eof()) {
+ alloc_array(t3_line, 1, T3_BUF_SIZE);
+ append_char_to_buf(c, t3_line_ptr, t3_line_array, t3_line_limit);
+ if (c == 10)
+ break;
+ c = t3_getchar();
+ }
+ alloc_array(t3_line, 2, T3_BUF_SIZE);
+ append_eol(t3_line_ptr, t3_line_array, T3_BUF_SIZE);
+ if (t3_line_ptr - t3_line_array < 2 || *t3_line_array == '%') {
+ if (!t3_eof())
+ goto restart;
+ }
+}
+
+static void t3_putline(void)
+{
+ char *p = t3_line_array;
+ while (p < t3_line_ptr)
+ t3_putchar(*p++);
+}
+
+static void update_bbox(integer llx, integer lly, integer urx, integer ury, boolean is_first_glyph)
+{
+ if (is_first_glyph) {
+ t3_b0 = llx;
+ t3_b1 = lly;
+ t3_b2 = urx;
+ t3_b3 = ury;
+ }
+ else {
+ if (llx < t3_b0)
+ t3_b0 = llx;
+ if (lly < t3_b1)
+ t3_b1 = lly;
+ if (urx > t3_b2)
+ t3_b2 = urx;
+ if (ury > t3_b3)
+ t3_b3 = ury;
+ }
+}
+
+static void t3_write_glyph(internalfontnumber f)
+{
+ static char t3_begin_glyph_str[] = "\\pdfglyph";
+ static char t3_end_glyph_str[] = "\\endglyph";
+ int glyph_index;
+ int width, height, depth, llx, lly, urx, ury;
+ char *p;
+ t3_getline();
+ if (t3_prefix(t3_begin_glyph_str)) {
+ if (sscanf(t3_line_array + strlen(t3_begin_glyph_str) + 1,
+ "%i %i %i %i %i %i %i %i =", &glyph_index,
+ &width, &height, &depth, &llx, &lly, &urx, &ury) != 8) {
+ remove_eol(p, t3_line_array);
+ pdftex_warn("invalid glyph preamble: `%s'", t3_line_array);
+ return;
+ }
+ if (glyph_index < fontbc[f] || glyph_index > fontec[f])
+ return;
+ }
+ else
+ return;
+ if (!pdfcharmarked(f, glyph_index)) {
+ while (!t3_prefix(t3_end_glyph_str)) {
+ t3_check_eof();
+ t3_getline();
+ }
+ return;
+ }
+ update_bbox(llx, lly, urx, ury, t3_glyph_num == 0);
+ t3_glyph_num++;
+ pdfnewdict(0, 0);
+ t3_char_procs[glyph_index] = objptr;
+ if (width == 0)
+ t3_char_widths[glyph_index] =
+ (getcharwidth(f, glyph_index)/t3_font_scale) / pdffontsize[f];
+ else
+ t3_char_widths[glyph_index] = width;
+ pdfbeginstream();
+ t3_getline();
+ pdf_printf("%i 0 %i %i %i %i d1\nq\n",
+ (int)t3_char_widths[glyph_index], (int)llx,
+ (int)lly, (int)urx, (int)ury);
+ while (!t3_prefix(t3_end_glyph_str)) {
+ t3_check_eof();
+ if (t3_prefix("BI"))
+ t3_image_used = true;
+ t3_putline();
+ t3_getline();
+ }
+ pdf_puts("Q\n");
+ pdfendstream();
+}
+
+static integer get_pk_font_scale(internalfontnumber f)
+{
+ return
+ dividescaled(pkscalefactor,
+ dividescaled(pdffontsize[f], onehundredbp, fixeddecimaldigits + 2),
+ 0);
+}
+
+static integer pk_char_width(internalfontnumber f, scaled w)
+{
+ return
+ dividescaled(dividescaled(w, pdffontsize[f], 7),
+ get_pk_font_scale(f), 0);
+}
+
+scaled getpkcharwidth(internalfontnumber f, scaled w)
+{
+ return (get_pk_font_scale(f)/100000.0)*
+ (pk_char_width(f, w)/100.0)*
+ pdffontsize[f];
+}
+
+static boolean writepk(internalfontnumber f)
+{
+ kpse_glyph_file_type font_ret;
+ integer llx, lly, urx, ury;
+ integer cw, rw, i, j;
+ halfword *row;
+ char *name;
+ chardesc cd;
+ boolean is_null_glyph, check_preamble;
+ integer dpi;
+ int e;
+ dpi = kpse_magstep_fix(
+ round(fixedpkresolution*(((float)pdffontsize[f])/fontdsize[f])),
+ fixedpkresolution, NULL);
+ cur_file_name = makecstring(fontname[f]);
+ name = kpse_find_pk(cur_file_name, (unsigned)dpi, &font_ret);
+ if (name == NULL ||
+ !FILESTRCASEEQ(cur_file_name, font_ret.name) ||
+ !kpse_bitmap_tolerance((float)font_ret.dpi, (float)dpi)) {
+ pdftex_warn("Font %s at %i not found", cur_file_name, (int)dpi);
+ cur_file_name = NULL;
+ return false;
+ }
+ t3_file = xfopen(name, FOPEN_RBIN_MODE);
+ t3_image_used = true;
+ is_pk_font = true;
+ tex_printf(" <%s", (char *)name);
+ cd.rastersize = 256;
+ cd.raster = xtalloc(cd.rastersize, halfword);
+ check_preamble = true;
+ while (readchar(check_preamble, &cd) != 0) {
+ check_preamble = false;
+ if (!pdfcharmarked(f, cd.charcode))
+ continue;
+ t3_char_widths[cd.charcode] =
+ pk_char_width(f, getcharwidth(f, cd.charcode));
+ if (cd.cwidth < 1 || cd.cheight < 1) {
+ cd.xescape = cd.cwidth = round(t3_char_widths[cd.charcode]/100.0);
+ cd.cheight = 1;
+ cd.xoff = 0;
+ cd.yoff = 0;
+ is_null_glyph = true;
+ }
+ else
+ is_null_glyph = false;
+ llx = -cd.xoff;
+ lly = cd.yoff - cd.cheight + 1;
+ urx = cd.cwidth + llx + 1;
+ ury = cd.cheight + lly;
+ update_bbox(llx, lly, urx, ury, t3_glyph_num == 0);
+ t3_glyph_num++;
+ pdfnewdict(0, 0);
+ t3_char_procs[cd.charcode] = objptr;
+ pdfbeginstream();
+ pdfprintreal(t3_char_widths[cd.charcode], 2);
+ pdf_printf(" 0 %i %i %i %i d1\n",
+ (int)llx, (int)lly, (int)urx, (int)ury);
+ if (is_null_glyph)
+ goto end_stream;
+ pdf_printf("q\n%i 0 0 %i %i %i cm\nBI\n", (int)cd.cwidth,
+ (int)cd.cheight, (int)llx, (int)lly);
+ pdf_printf("/W %i\n/H %i\n",
+ (int)cd.cwidth, (int)cd.cheight);
+ pdf_puts("/IM true\n/BPC 1\n/D [1 0]\nID ");
+ cw = (cd.cwidth + 7)/8;
+ rw = (cd.cwidth + 15)/16;
+ row = cd.raster;
+ for (i = 0; i < cd.cheight; i++) {
+ for (j = 0; j < rw - 1; j++) {
+ pdfout(*row/256);
+ pdfout(*row%256);
+ row++;
+ }
+ pdfout(*row/256);
+ if (2*rw == cw)
+ pdfout(*row%256);
+ row++;
+ }
+ pdf_puts("\nEI\nQ\n");
+end_stream:
+ pdfendstream();
+ }
+ xfree(cd.raster);
+ cur_file_name = NULL;
+ return true;
+}
+
+void writet3(int objnum, internalfontnumber f)
+{
+ static char t3_font_scale_str[] = "\\pdffontscale";
+ int i, e;
+ int first_char, last_char;
+ integer pk_font_scale;
+ boolean is_notdef;
+ t3_glyph_num = 0;
+ t3_image_used = false;
+ for (i = 0; i <= MAX_CHAR_CODE; i++) {
+ t3_char_procs[i] = 0;
+ t3_char_widths[i] = 0;
+ }
+ packfilename(fontname[f], getnullstr(), maketexstring(".pgc"));
+ cur_file_name = makecstring(makenamestring());
+ is_pk_font = false;
+ if (!t3_open()) {
+ if (writepk(f))
+ goto write_font_dict;
+ else {
+ cur_file_name = NULL;
+ return;
+ }
+ }
+ tex_printf("<%s", nameoffile + 1);
+ t3_getline();
+ if (!t3_prefix(t3_font_scale_str) ||
+ sscanf(t3_line_array + strlen(t3_font_scale_str) + 1, "%g", &t3_font_scale) < 1 ||
+ t3_font_scale <= 0 || t3_font_scale > 1000 ) {
+ pdftex_warn("missing or invalid font scale");
+ t3_close();
+ cur_file_name = NULL;
+ return;
+ }
+ while (!t3_eof())
+ t3_write_glyph(f);
+write_font_dict:
+ for (i = fontbc[f]; i <= fontec[f]; i++)
+ if (pdfcharmarked(f, i))
+ break;
+ first_char = i;
+ for (i = fontec[f]; i > first_char; i--)
+ if (pdfcharmarked(f, i))
+ break;
+ last_char = i;
+ pdfbegindict(objnum); /* Type 3 font dictionary */
+ pdf_puts("/Type /Font\n/Subtype /Type3\n");
+ pdf_printf("/Name /F%i\n", (int)f);
+ if (pdffontattr[f] != getnullstr()) {
+ pdfprint(pdffontattr[f]);
+ pdf_puts("\n");
+ }
+ if (is_pk_font) {
+ pk_font_scale = get_pk_font_scale(f);
+ pdf_puts("/FontMatrix [");
+ pdfprintreal(pk_font_scale, 5);
+ pdf_puts(" 0 0 ");
+ pdfprintreal(pk_font_scale, 5);
+ pdf_puts(" 0 0]\n") ;
+ }
+ else
+ pdf_printf("/FontMatrix [%g 0 0 %g 0 0]\n",
+ (double)t3_font_scale, (double)t3_font_scale);
+ pdf_printf("/%s [ %i %i %i %i ]\n",
+ font_keys[FONTBBOX1_CODE].pdfname,
+ (int)t3_b0, (int)t3_b1,
+ (int)t3_b2, (int)t3_b3);
+ pdf_printf("/Resources << /ProcSet [ /PDF %s] >>\n",
+ t3_image_used ? "/ImageB " : "");
+ pdf_printf("/FirstChar %i\n/LastChar %i\n", first_char, last_char);
+ pdf_printf("/Widths %i 0 R\n/Encoding %i 0 R\n/CharProcs %i 0 R\n",
+ (int)(objptr + 1), (int)(objptr + 2),
+ (int)(objptr + 3));
+ pdfenddict();
+ pdfnewobj(0, 0); /* chars width array */
+ pdf_puts("[");
+ if (is_pk_font)
+ for (i = first_char; i <= last_char; i++) {
+ pdfprintreal(t3_char_widths[i], 2);
+ pdf_puts(" ");
+ }
+ else
+ for (i = first_char; i <= last_char; i++)
+ pdf_printf("%i ", (int)t3_char_widths[i]);
+ pdf_puts("]\n");
+ pdfendobj();
+ pdfnewdict(0, 0); /* encoding dictionary */
+ pdf_printf("/Type /Encoding\n/Differences [%i", first_char);
+ if (t3_char_procs[first_char] == 0) {
+ pdf_printf("/%s", notdef);
+ is_notdef = true;
+ }
+ else {
+ pdf_printf("/a%i", first_char);
+ is_notdef = false;
+ }
+ for (i = first_char + 1; i <= last_char; i++) {
+ if (t3_char_procs[i] == 0) {
+ if (!is_notdef) {
+ pdf_printf(" %i/%s", i, notdef);
+ is_notdef = true;
+ }
+ }
+ else {
+ if (is_notdef) {
+ pdf_printf(" %i", i);
+ is_notdef = false;
+ }
+ pdf_printf("/a%i", i);
+ }
+ }
+ pdf_puts("]\n");
+ pdfenddict();
+ pdfnewdict(0, 0); /* CharProcs dictionary */
+ for (i = first_char; i <= last_char; i++)
+ if (t3_char_procs[i] != 0)
+ pdf_printf("/a%i %i 0 R\n", (int)i, (int)t3_char_procs[i]);
+ pdfenddict();
+ t3_close();
+ tex_printf(">");
+ cur_file_name = NULL;
+}
diff --git a/Build/source/texk/web2c/pdftexdir/writettf.c b/Build/source/texk/web2c/pdftexdir/writettf.c
new file mode 100644
index 00000000000..e2d0d1641d6
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/writettf.c
@@ -0,0 +1,1257 @@
+/*
+Copyright (c) 1996-2002 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX 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.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/writettf.c#16 $
+*/
+
+#include "ptexlib.h"
+#include "writettf.h"
+
+static const char perforce_id[] =
+ "$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/writettf.c#16 $";
+
+#define DEFAULT_NTABS 14
+#define NEW_CMAP_SIZE 2
+
+#define ttf_putchar fb_putchar
+#define ttf_offset fb_offset
+#define ttf_seek_outbuf fb_seek
+
+#define INFILE ttf_file
+
+#define ttf_open() \
+ open_input(&ttf_file, kpse_truetype_format, FOPEN_RBIN_MODE)
+#define ttf_close() xfclose(ttf_file, cur_file_name)
+#define ttf_getchar() xgetc(ttf_file)
+#define ttf_eof() feof(ttf_file)
+
+typedef struct {
+ TTF_LONG offset;
+ TTF_LONG newoffset;
+ TTF_UFWORD advWidth;
+ TTF_FWORD lsb;
+ char *name; /* name of glyph */
+ TTF_SHORT newindex; /* new index of glyph in output file */
+ TTF_USHORT name_index; /* index of name as read from font file */
+} glyph_entry;
+
+typedef struct {
+ char *name; /* name of glyph */
+ short newindex; /* new index of glyph in output file */
+} ttfenc_entry;
+
+typedef struct {
+ TTF_USHORT platform_id;
+ TTF_USHORT encoding_id;
+ TTF_USHORT language_id;
+ TTF_USHORT name_id;
+ TTF_USHORT length;
+ TTF_USHORT offset;
+ TTF_USHORT new_offset;
+ TTF_USHORT new_length;
+} name_record;
+
+static TTF_USHORT ntabs;
+static TTF_USHORT upem;
+static TTF_FIXED post_format;
+static TTF_SHORT loca_format;
+static TTF_ULONG last_glyf_offset;
+static TTF_USHORT glyphs_count;
+static TTF_USHORT new_glyphs_count;
+static TTF_USHORT nhmtxs;
+static TTF_USHORT new_ntabs;
+
+static glyph_entry *glyph_tab;
+static short *glyph_index;
+static cmap_entry *cmap_tab, new_cmap_tab[NEW_CMAP_SIZE];
+static name_record *name_tab;
+static int name_record_num;
+static char *name_buf;
+static int name_buf_size;
+static dirtab_entry *dir_tab;
+static char *glyph_name_buf;
+static TTF_ULONG checksum;
+static TTF_ULONG tab_length;
+static TTF_ULONG tmp_ulong;
+static TTF_ULONG checkSumAdjustment_offset;
+static FILE *ttf_file;
+static ttfenc_entry ttfenc_tab[MAX_CHAR_CODE + 1];
+
+static TTF_USHORT unicode_map[0xFFFF];
+
+
+integer ttf_length;
+
+#include "macnames.c"
+
+extern char *fb_array;
+
+static const char *newtabnames[] = {
+ "OS/2",
+ "PCLT",
+ "cmap",
+ "cvt ",
+ "fpgm",
+ "glyf",
+ "head",
+ "hhea",
+ "hmtx",
+ "loca",
+ "maxp",
+ "name",
+ "post",
+ "prep"
+};
+
+static unsigned char ttf_addchksm(unsigned char b)
+{
+ tmp_ulong = (tmp_ulong << 8) + b;
+ tab_length++;
+ if (tab_length % 4 == 0) {
+ checksum += tmp_ulong;
+ tmp_ulong = 0;
+ }
+ return b;
+}
+
+static TTF_ULONG ttf_getchksm(void)
+{
+ while (tab_length % 4 != 0)
+ ttf_putchar(ttf_addchksm(0)); /* ttf_addchksm updates tab_length */
+ return checksum;
+}
+
+static long ttf_putnum(int s, long n)
+{
+ long i = n;
+ char buf[TTF_LONG_SIZE + 1], *p = buf;
+ while (s-- > 0) {
+ *p++ = i & 0xFF;
+ i >>= 8;
+ }
+ p--;
+ while (p >= buf)
+ ttf_putchar(ttf_addchksm(*p--));
+ return n;
+}
+
+static long ttf_getnum(int s)
+{
+ long i = 0;
+ int c;
+ while (s > 0) {
+ if ((c = ttf_getchar()) < 0)
+ pdftex_fail("unexpected EOF");
+ i = (i << 8) + c;
+ s--;
+ }
+ return i;
+}
+
+static long ttf_funit(long n)
+{
+ if (n < 0)
+ return -((-n/upem)*1000 + ((-n%upem)*1000)/upem);
+ else
+ return (n/upem)*1000 + ((n%upem)*1000)/upem;
+}
+
+static void ttf_ncopy(int n)
+{
+ while (n-- > 0)
+ copy_byte();
+}
+
+static dirtab_entry *ttf_name_lookup(const char *s, boolean required)
+{
+ dirtab_entry *tab;
+ for (tab = dir_tab; tab - dir_tab < ntabs; tab++)
+ if (strncmp(tab->tag, s, 4) == 0)
+ break;
+ if (tab - dir_tab == ntabs) {
+ if (required)
+ pdftex_fail("can't find table `%s'", s);
+ else
+ tab = NULL;
+ }
+ return tab;
+}
+
+static dirtab_entry *ttf_seek_tab(const char *name, TTF_LONG offset)
+{
+ dirtab_entry *tab = ttf_name_lookup(name, true);
+ xfseek(INFILE, tab->offset + offset, SEEK_SET, cur_file_name);
+ return tab;
+}
+
+static void ttf_seek_off(TTF_LONG offset)
+{
+ xfseek(INFILE, offset, SEEK_SET, cur_file_name);
+}
+
+static void ttf_copy_encoding(void)
+{
+ int i;
+ char **glyph_names = (fm_cur->encoding)->glyph_names;
+ ttfenc_entry *e = ttfenc_tab;
+ pdfmarkchar(tex_font, 'a'); /* workaround for a bug of AcroReader 4.0 */
+ for (i = 0; i <= MAX_CHAR_CODE; i++, e++) {
+ if (pdfcharmarked(tex_font, i))
+ e->name = glyph_names[i];
+ else
+ e->name = (char*) notdef;
+ }
+}
+
+#define ttf_append_byte(B)\
+do {\
+ if (name_tab[i].platform_id == 3)\
+ *q++ = 0;\
+ *q++ = B;\
+} while (0)
+
+static void ttf_read_name(void)
+{
+ int i, j;
+ dirtab_entry *tab = ttf_seek_tab("name", TTF_USHORT_SIZE);
+ char *p;
+ name_record_num = get_ushort();
+ name_tab = xtalloc(name_record_num, name_record);
+ name_buf_size = tab->length -
+ (3*TTF_USHORT_SIZE + name_record_num*6*TTF_USHORT_SIZE);
+ name_buf = xtalloc(name_buf_size, char);
+ ttf_skip(TTF_USHORT_SIZE);
+ for (i = 0; i < name_record_num; i++) {
+ name_tab[i].platform_id = get_ushort();
+ name_tab[i].encoding_id = get_ushort();
+ name_tab[i].language_id = get_ushort();
+ name_tab[i].name_id = get_ushort();
+ name_tab[i].length = get_ushort();
+ name_tab[i].offset = get_ushort();
+ }
+ for (p = name_buf; p - name_buf < name_buf_size; p++)
+ *p = get_char();
+ /* look for PS font name */
+ for (i = 0; i < name_record_num; i++) {
+ if (name_tab[i].platform_id == 1 &&
+ name_tab[i].encoding_id == 0 &&
+ name_tab[i].name_id == 6) {
+ strncpy(fontname_buf, name_buf + name_tab[i].offset, name_tab[i].length);
+ fontname_buf[name_tab[i].length] = 0;
+ font_keys[FONTNAME_CODE].valid = true;
+ break;
+ }
+ }
+ if (!font_keys[FONTNAME_CODE].valid) {
+ for (i = 0; i < name_record_num; i++) {
+ if (name_tab[i].platform_id == 3 &&
+ (name_tab[i].encoding_id == 0 ||
+ name_tab[i].encoding_id == 1) &&
+ name_tab[i].name_id == 6) {
+ for (j = 0, p = fontname_buf; j < name_tab[i].length; j += 2)
+ *p++ = name_buf[name_tab[i].offset + j + 1];
+ *p = 0;
+ font_keys[FONTNAME_CODE].valid = true;
+ break;
+ }
+ }
+ }
+}
+
+static void ttf_read_mapx(void)
+{
+ int i;
+ glyph_entry *glyph;
+ ttf_seek_tab("maxp", TTF_FIXED_SIZE);
+ glyph_tab = xtalloc(1 + (glyphs_count = get_ushort()), glyph_entry);
+ for (glyph = glyph_tab; glyph - glyph_tab < glyphs_count; glyph++) {
+ glyph->newindex = -1;
+ glyph->newoffset = 0;
+ glyph->name_index = 0;
+ glyph->name = (char*) notdef;
+ }
+ glyph_index = xtalloc(glyphs_count, short);
+ glyph_index[0] = 0; /* index of ".notdef" glyph */
+ glyph_index[1] = 1; /* index of ".null" glyph */
+}
+
+static void ttf_read_head(void)
+{
+ ttf_seek_tab("head", 2*TTF_FIXED_SIZE + 2*TTF_ULONG_SIZE + TTF_USHORT_SIZE);
+ upem = get_ushort();
+ ttf_skip(16);
+ font_keys[FONTBBOX1_CODE].value = ttf_funit(get_fword());
+ font_keys[FONTBBOX2_CODE].value = ttf_funit(get_fword());
+ font_keys[FONTBBOX3_CODE].value = ttf_funit(get_fword());
+ font_keys[FONTBBOX4_CODE].value = ttf_funit(get_fword());
+ font_keys[FONTBBOX1_CODE].valid = true;
+ font_keys[FONTBBOX2_CODE].valid = true;
+ font_keys[FONTBBOX3_CODE].valid = true;
+ font_keys[FONTBBOX4_CODE].valid = true;
+ ttf_skip(2*TTF_USHORT_SIZE + TTF_SHORT_SIZE);
+ loca_format = get_short();
+}
+
+static void ttf_read_hhea(void)
+{
+ ttf_seek_tab("hhea", TTF_FIXED_SIZE);
+ font_keys[ASCENT_CODE].value = ttf_funit(get_fword());
+ font_keys[DESCENT_CODE].value = ttf_funit(get_fword());
+ font_keys[ASCENT_CODE].valid = true;
+ font_keys[DESCENT_CODE].valid = true;
+ ttf_skip(TTF_FWORD_SIZE + TTF_UFWORD_SIZE + 3*TTF_FWORD_SIZE + 8*TTF_SHORT_SIZE);
+ nhmtxs = get_ushort();
+}
+
+static void ttf_read_pclt(void)
+{
+ if (ttf_name_lookup("PCLT", false) == NULL)
+ return;
+ ttf_seek_tab("PCLT", TTF_FIXED_SIZE + TTF_ULONG_SIZE + TTF_USHORT_SIZE);
+ font_keys[XHEIGHT_CODE].value = ttf_funit(get_ushort());
+ ttf_skip(2*TTF_USHORT_SIZE);
+ font_keys[CAPHEIGHT_CODE].value = ttf_funit(get_ushort());
+ font_keys[XHEIGHT_CODE].valid = true;
+ font_keys[CAPHEIGHT_CODE].valid = true;
+}
+
+static void ttf_read_hmtx(void)
+{
+ glyph_entry *glyph;
+ TTF_UFWORD last_advWidth;
+ ttf_seek_tab("hmtx", 0);
+ for (glyph = glyph_tab; glyph - glyph_tab < nhmtxs; glyph++) {
+ glyph->advWidth = get_ufword();
+ glyph->lsb = get_ufword();
+ }
+ if (nhmtxs < glyphs_count) {
+ last_advWidth = glyph[-1].advWidth;
+ for (;glyph - glyph_tab < glyphs_count; glyph++) {
+ glyph->advWidth = last_advWidth;
+ glyph->lsb = get_ufword();
+ }
+ }
+}
+
+static void ttf_read_post(void)
+{
+ int k, nnames;
+ long length;
+ long int_part, frac_part;
+ int sign = 1;
+ TTF_FIXED italic_angle;
+ char *p;
+ glyph_entry *glyph;
+ dirtab_entry *tab = ttf_seek_tab("post", 0);
+ post_format = get_fixed();
+ italic_angle = get_fixed();
+ int_part = italic_angle >> 16;
+ if (int_part > 0x7FFF) { /* a negative number */
+ int_part = 0x10000 - int_part;
+ sign = -1;
+ }
+ frac_part = italic_angle % 0x10000;
+ font_keys[ITALIC_ANGLE_CODE].value = sign*(int_part + frac_part*1.0/0x10000);
+ font_keys[ITALIC_ANGLE_CODE].valid = true;
+ if (glyph_tab == NULL)
+ return; /* being called from writeotf() */
+ ttf_skip(2*TTF_FWORD_SIZE + 5*TTF_ULONG_SIZE);
+ switch (post_format) {
+ case 0x10000:
+ for (glyph = glyph_tab; glyph - glyph_tab < NMACGLYPHS; glyph++) {
+ glyph->name = (char*)mac_glyph_names[glyph - glyph_tab];
+ glyph->name_index = glyph - glyph_tab;
+ }
+ break;
+ case 0x20000:
+ nnames = get_ushort(); /* some fonts have this value different from nglyphs */
+ for (glyph = glyph_tab; glyph - glyph_tab < nnames; glyph++)
+ glyph->name_index = get_ushort();
+ length = tab->length - (xftell(INFILE, cur_file_name) - tab->offset);
+ glyph_name_buf = xtalloc(length, char);
+ for (p = glyph_name_buf; p - glyph_name_buf < length;) {
+ for (k = get_byte(); k > 0; k--)
+ *p++ = get_char();
+ *p++ = 0;
+ }
+ for (glyph = glyph_tab; glyph - glyph_tab < nnames; glyph++) {
+ if (glyph->name_index < NMACGLYPHS)
+ glyph->name = (char*)mac_glyph_names[glyph->name_index];
+ else {
+ p = glyph_name_buf;
+ k = glyph->name_index - NMACGLYPHS;
+ for (; k > 0; k--)
+ p = strend(p) + 1;
+ glyph->name = p;
+ }
+ }
+ break;
+ case 0x00030000:
+ for (glyph = glyph_tab; glyph - glyph_tab < NMACGLYPHS; glyph++) {
+ glyph->name_index = glyph - glyph_tab;
+ }
+ break;
+ default:
+ pdftex_fail("unsupported format (%.8X) of `post' table", (unsigned int) post_format);
+ }
+}
+
+static void ttf_read_loca(void)
+{
+ glyph_entry *glyph;
+ ttf_seek_tab("loca", 0);
+ if (loca_format != 0)
+ for (glyph = glyph_tab; glyph - glyph_tab < glyphs_count + 1; glyph++)
+ glyph->offset = get_ulong();
+ else
+ for (glyph = glyph_tab; glyph - glyph_tab < glyphs_count + 1; glyph++)
+ glyph->offset = get_ushort() << 1;
+}
+
+static void ttf_read_tabdir()
+{
+ int i;
+ dirtab_entry *tab;
+/* if ((version= get_fixed()) != 0x00010000) */
+/* pdftex_fail("unsupport version 0x%.8X; can handle only version 1.0", (int)version); */
+ ttf_skip(TTF_FIXED_SIZE); /* ignore the sfnt number */
+ dir_tab = xtalloc(ntabs = get_ushort(), dirtab_entry);
+ ttf_skip(3*TTF_USHORT_SIZE);
+ for (tab = dir_tab; tab - dir_tab < ntabs; tab++) {
+ for (i = 0; i < 4; i++)
+ tab->tag[i] = get_char();
+ tab->checksum = get_ulong();
+ tab->offset = get_ulong();
+ tab->length = get_ulong();
+ }
+}
+
+static void ttf_read_cmap(void)
+{
+ cmap_entry *e;
+ seg_entry *seg_tab, *s;
+ TTF_USHORT *glyphId, format, segCount;
+ TTF_USHORT ncmapsubtabs;
+ long cmap_offset;
+ long int n, i, j, k, first_code, length, last_sep, index;
+ int unicode_map_count = 0;
+ int select_unicode = 1; /* may be changed later if needed */
+ ttf_seek_tab("cmap", TTF_USHORT_SIZE); /* skip the table vesrion number (=0) */
+ ncmapsubtabs = get_ushort();
+ cmap_offset = xftell(INFILE, cur_file_name) - 2*TTF_USHORT_SIZE;
+ cmap_tab = xtalloc(ncmapsubtabs, cmap_entry);
+ for (e = cmap_tab; e - cmap_tab < ncmapsubtabs; e++) {
+ e->platform_id = get_ushort();
+ e->encoding_id = get_ushort();
+ e->offset = get_ulong();
+ }
+ for (i = 0; i < 0xFFFF; ++i)
+ unicode_map[i] = NOGLYPH_ASSIGNED_YET;
+ for (e = cmap_tab; e - cmap_tab < ncmapsubtabs; e++) {
+ ttf_seek_off(cmap_offset + e->offset);
+ format = get_ushort();
+ if (is_unicode_mapping(e) && format == 4) {
+ ++unicode_map_count;
+ if (unicode_map_count == select_unicode)
+ goto read_unicode_mapping;
+ }
+ continue;
+read_unicode_mapping:
+ length = get_ushort(); /* length of subtable */
+ get_ushort(); /* skip the version number */
+ segCount = get_ushort()/2;
+ get_ushort(); /* skip searchRange */
+ get_ushort(); /* skip entrySelector */
+ get_ushort(); /* skip rangeShift */
+ seg_tab = xtalloc(segCount, seg_entry);
+ for (s = seg_tab; s - seg_tab < segCount; s++)
+ s->endCode = get_ushort();
+ get_ushort(); /* skip reversedPad */
+ for (s = seg_tab; s - seg_tab < segCount; s++)
+ s->startCode = get_ushort();
+ for (s = seg_tab; s - seg_tab < segCount; s++)
+ s->idDelta = get_ushort();
+ for (s = seg_tab; s - seg_tab < segCount; s++)
+ s->idRangeOffset = get_ushort();
+ length -= 8*TTF_USHORT_SIZE + 4*segCount*TTF_USHORT_SIZE;
+ n = length/TTF_USHORT_SIZE; /* number of glyphID's */
+ glyphId = xtalloc(n, TTF_USHORT);
+ for (i = 0; i < n; i++)
+ glyphId[i] = get_ushort();
+ for (s = seg_tab; s - seg_tab < segCount; s++) {
+ for (i = s->startCode; i <= s->endCode; i++) {
+ if (i == 0xFFFF)
+ break;
+ if (s->idRangeOffset != 0xFFFF) {
+ if (s->idRangeOffset == 0)
+ index = (s->idDelta + i) & 0xFFFF;
+ else {
+ k = (i - s->startCode) + s->idRangeOffset/2 +
+ (s - seg_tab) - segCount ;
+ assert(k >= 0 && k < n);
+ index = glyphId[k];
+ if (index != 0)
+ index = (index + s->idDelta) & 0xFFFF;
+ }
+ if (index >= glyphs_count)
+ pdftex_fail("cmap: glyph index %i out of range [0..%i)",
+ index, glyphs_count);
+ if (unicode_map[i] != NOGLYPH_ASSIGNED_YET)
+ pdftex_warn("cmap: multiple glyphs are mapped to unicode %.4X, "
+ "only %i will be used (glyph %i being ignored)",
+ i, unicode_map[i], index);
+ else
+ unicode_map[i] = index;
+ }
+ }
+ }
+ xfree(seg_tab);
+ xfree(glyphId);
+ break;
+ }
+ if (e - cmap_tab == ncmapsubtabs)
+ pdftex_fail("Invalid argument `-m %i': out of range [1..%i]",
+ select_unicode, unicode_map_count);
+ xfree(cmap_tab);
+}
+
+static void ttf_read_font(void)
+{
+ ttf_read_tabdir();
+ if (ttf_name_lookup("PCLT", false) == NULL)
+ new_ntabs--;
+ if (ttf_name_lookup("fpgm", false) == NULL)
+ new_ntabs--;
+ if (ttf_name_lookup("cvt ", false) == NULL)
+ new_ntabs--;
+ if (ttf_name_lookup("prep", false) == NULL)
+ new_ntabs--;
+ ttf_read_mapx();
+ ttf_read_head();
+ ttf_read_hhea();
+ ttf_read_pclt();
+ ttf_read_hmtx();
+ ttf_read_post();
+ ttf_read_loca();
+ ttf_read_name();
+ ttf_read_cmap();
+}
+
+static void ttf_reset_chksm(dirtab_entry *tab)
+{
+ checksum = 0;
+ tab_length = 0;
+ tmp_ulong = 0;
+ tab->offset = ttf_offset();
+ if (tab->offset % 4 != 0)
+ pdftex_warn("offset of `%4.4s' is not a multiple of 4", tab->tag);
+}
+
+
+static void ttf_set_chksm(dirtab_entry *tab)
+{
+ tab->length = ttf_offset() - tab->offset;
+ tab->checksum = ttf_getchksm();
+}
+
+static void ttf_copytab(const char *name)
+{
+ long i;
+ dirtab_entry *tab = ttf_seek_tab(name, 0);
+ ttf_reset_chksm(tab);
+ for (i = tab->length; i > 0; i--)
+ copy_char();
+ ttf_set_chksm(tab);
+}
+
+#define BYTE_ENCODING_LENGTH \
+ ((MAX_CHAR_CODE + 1)*TTF_BYTE_SIZE + 3*TTF_USHORT_SIZE)
+
+static void ttf_byte_encoding(void)
+{
+ ttfenc_entry *e;
+ put_ushort(0); /* format number (0: byte encoding table) */
+ put_ushort(BYTE_ENCODING_LENGTH); /* length of table */
+ put_ushort(0); /* version number */
+ for (e = ttfenc_tab; e - ttfenc_tab <= MAX_CHAR_CODE; e++)
+ if (e->newindex < 256) {
+ put_byte(e->newindex);
+ }
+ else {
+ if (e->name != notdef)
+ pdftex_warn("glyph `%s' has been mapped to `%s' in `ttf_byte_encoding' cmap table",
+ e->name, notdef);
+ put_byte(0); /* notdef */
+ }
+}
+
+#define TRIMMED_TABLE_MAP_LENGTH (TTF_USHORT_SIZE*(5 + (MAX_CHAR_CODE + 1)))
+
+static void ttf_trimmed_table_map(void)
+{
+ ttfenc_entry *e;
+ put_ushort(6); /* format number (6): trimmed table mapping */
+ put_ushort(TRIMMED_TABLE_MAP_LENGTH);
+ put_ushort(0); /* version number (0) */
+ put_ushort(0); /* first character code */
+ put_ushort(MAX_CHAR_CODE + 1); /* number of character code in table */
+ for (e = ttfenc_tab; e - ttfenc_tab <= MAX_CHAR_CODE; e++)
+ put_ushort(e->newindex);
+}
+
+#define SEG_MAP_DELTA_LENGTH ((16 + (MAX_CHAR_CODE + 1))*TTF_USHORT_SIZE)
+
+static void ttf_seg_map_delta(void)
+{
+ ttfenc_entry *e;
+ put_ushort(4); /* format number (4: segment mapping to delta values) */
+ put_ushort(SEG_MAP_DELTA_LENGTH);
+ put_ushort(0); /* version number */
+ put_ushort(4); /* 2*segCount */
+ put_ushort(4); /* searchRange */
+ put_ushort(1); /* entrySelector */
+ put_ushort(0); /* rangeShift */
+ put_ushort(0xF0FF); /* endCount[0] */
+ put_ushort(0xFFFF); /* endCount[1] */
+ put_ushort(0); /* reversedPad */
+ put_ushort(0xF000); /* startCount[0] */
+ put_ushort(0xFFFF); /* startCount[1] */
+ put_ushort(0); /* idDelta[0] */
+ put_ushort(1); /* idDelta[1] */
+ put_ushort(2*TTF_USHORT_SIZE); /* idRangeOffset[0] */
+ put_ushort(0); /* idRangeOffset[1] */
+ for (e = ttfenc_tab; e - ttfenc_tab <= MAX_CHAR_CODE; e++)
+ put_ushort(e->newindex);
+}
+
+#define CMAP_ENTRY_LENGTH (2*TTF_USHORT_SIZE + TTF_ULONG_SIZE)
+
+static void ttf_select_cmap(void)
+{
+ assert(sizeof(new_cmap_tab) <= NEW_CMAP_SIZE*sizeof(cmap_entry));
+ new_cmap_tab[0].platform_id = 1; /* Macintosh */
+ new_cmap_tab[0].encoding_id = 0; /* Symbol; ignore code page */
+ new_cmap_tab[0].format = new_glyphs_count < 256 ? 0 /* byte encoding */
+ : 6; /* trimmed table mapping */
+ new_cmap_tab[1].platform_id = 3; /* Microsoft */
+ new_cmap_tab[1].encoding_id = 0; /* Symbol; ignore code page */
+ new_cmap_tab[1].format = 4; /* segment mapping to delta */
+}
+
+static void ttf_write_cmap(void)
+{
+ cmap_entry *ce;
+ long offset;
+ dirtab_entry *tab = ttf_name_lookup("cmap", true);
+ ttf_select_cmap();
+ ttf_reset_chksm(tab);
+ put_ushort(0); /* table version number (0) */
+ put_ushort(NEW_CMAP_SIZE); /* number of encoding tables */
+ offset = 2*TTF_USHORT_SIZE + NEW_CMAP_SIZE*CMAP_ENTRY_LENGTH;
+ for (ce = new_cmap_tab; ce - new_cmap_tab < NEW_CMAP_SIZE; ce++) {
+ ce->offset = offset;
+ switch (ce->format) {
+ case 0:
+ offset += BYTE_ENCODING_LENGTH;
+ break;
+ case 4:
+ offset += SEG_MAP_DELTA_LENGTH;
+ break;
+ case 6:
+ offset += TRIMMED_TABLE_MAP_LENGTH;
+ break;
+ default:
+ pdftex_fail("invalid format (it should not have happened)");
+ }
+ put_ushort(ce->platform_id);
+ put_ushort(ce->encoding_id);
+ put_ulong(ce->offset);
+ }
+ for (ce = new_cmap_tab; ce - new_cmap_tab < NEW_CMAP_SIZE; ce++) {
+ switch (ce->format) {
+ case 0:
+ ttf_byte_encoding();
+ break;
+ case 4:
+ ttf_seg_map_delta();
+ break;
+ case 6:
+ ttf_trimmed_table_map();
+ break;
+ }
+ }
+ ttf_set_chksm(tab);
+}
+
+static int prepend_subset_tags(int index, char *p)
+{
+ boolean is_unicode = (name_tab[index].platform_id == 3);
+ int i;
+ assert(index > 0 && index < name_record_num && fm_cur->subset_tag != NULL);
+ if (is_unicode) {
+ for (i = 0; i < 6; ++i) {
+ *p++ = 0;
+ *p++ = fm_cur->subset_tag[i];
+ }
+ *p++ = 0;
+ *p++ = '+';
+ return 14;
+ } else {
+ strncpy(p, fm_cur->subset_tag, 6);
+ p += 6;
+ *p++ = '+';
+ return 7;
+ }
+}
+
+
+static void ttf_write_name(void)
+{
+ int i, l;
+ char *p;
+ int new_name_buf_size;
+ char *new_name_buf;
+ name_record *n;
+ dirtab_entry *tab = ttf_name_lookup("name", true);
+ if (is_subsetted(fm_cur)) {
+ l = 0;
+ for (i = 0; i < name_record_num; i++)
+ l += name_tab[i].length + 14; /* maximum lengh of new stogare area */
+ new_name_buf = xtalloc(l, char);
+ /* additional space for subset tags */
+ p = new_name_buf;
+ for (i = 0; i < name_record_num; i++) {
+ n = name_tab + i;
+ n->new_offset = p - new_name_buf;
+ if ((n->name_id == 1 || n->name_id == 3 ||
+ n->name_id == 4 || n->name_id == 6) &&
+ ((n->platform_id == 1 && n->encoding_id == 0) ||
+ (n->platform_id == 3 && n->encoding_id == 0) ||
+ (n->platform_id == 3 && n->encoding_id == 1)))
+ {
+ l = prepend_subset_tags(i, p);
+ p += l;
+ }
+ else
+ l = 0;
+ memcpy(p, name_buf + n->offset, n->length);
+ p += n->length;
+ n->new_length = n->length + l;
+ }
+ new_name_buf_size = p - new_name_buf;
+ }
+ else {
+ new_name_buf = name_buf;
+ new_name_buf_size = name_buf_size;
+ }
+ ttf_reset_chksm(tab);
+ put_ushort(0); /* Format selector */
+ put_ushort(name_record_num);
+ put_ushort(3*TTF_USHORT_SIZE + name_record_num*6*TTF_USHORT_SIZE);
+ for (i = 0; i < name_record_num; i++) {
+ put_ushort(name_tab[i].platform_id);
+ put_ushort(name_tab[i].encoding_id);
+ put_ushort(name_tab[i].language_id);
+ put_ushort(name_tab[i].name_id);
+ put_ushort(name_tab[i].new_length);
+ put_ushort(name_tab[i].new_offset);
+ }
+ for (p = new_name_buf; p - new_name_buf < new_name_buf_size; p++)
+ put_char(*p);
+ ttf_set_chksm(tab);
+ if (new_name_buf != name_buf)
+ xfree(new_name_buf);
+}
+
+static void ttf_write_dirtab(void)
+{
+ dirtab_entry *tab;
+ TTF_ULONG i, k;
+ char *p;
+ integer save_offset = ttf_offset();
+ ttf_seek_outbuf(TABDIR_OFF);
+ if (is_subsetted(fm_cur)) {
+ for (i = 0; i < DEFAULT_NTABS; i++) {
+ tab = ttf_name_lookup(newtabnames[i], false);
+ if (tab == NULL)
+ continue;
+ for (k = 0; k < 4; k++)
+ put_char(tab->tag[k]);
+ put_ulong(tab->checksum);
+ put_ulong(tab->offset);
+ put_ulong(tab->length);
+ }
+ }
+ else {
+ for (tab = dir_tab; tab - dir_tab < ntabs; tab++) {
+ for (k = 0; k < 4; k++)
+ put_char(tab->tag[k]);
+ put_ulong(tab->checksum);
+ put_ulong(tab->offset);
+ put_ulong(tab->length);
+ }
+ }
+ /* adjust checkSumAdjustment */
+ tmp_ulong = 0;
+ checksum = 0;
+ for (p = fb_array, i = 0; i < save_offset;) {
+ tmp_ulong = (tmp_ulong << 8) + *p++;
+ i++;
+ if (i % 4 == 0) {
+ checksum += tmp_ulong;
+ tmp_ulong = 0;
+ }
+ }
+ if (i % 4 != 0) {
+ pdftex_warn("font length is not a multiple of 4 (%li)", i);
+ checksum <<= 8*(4 - i % 4);
+ }
+ k = 0xB1B0AFBA - checksum;
+ ttf_seek_outbuf(checkSumAdjustment_offset);
+ put_ulong(k);
+ ttf_seek_outbuf(save_offset);
+}
+
+static void ttf_write_glyf(void)
+{
+ short *id, k;
+ TTF_USHORT idx;
+ TTF_USHORT flags;
+ dirtab_entry *tab = ttf_name_lookup("glyf", true);
+ long glyf_offset = tab->offset;
+ long new_glyf_offset = ttf_offset();
+ ttf_reset_chksm(tab);
+ for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) {
+ glyph_tab[*id].newoffset = ttf_offset() - new_glyf_offset;
+ if (glyph_tab[*id].offset != glyph_tab[*id + 1].offset) {
+ ttf_seek_off(glyf_offset + glyph_tab[*id].offset);
+ k = copy_short();
+ ttf_ncopy(4*TTF_FWORD_SIZE);
+ if (k < 0) {
+ do {
+ flags = copy_ushort();
+ idx = get_ushort();
+ if (glyph_tab[idx].newindex < 0) {
+ glyph_tab[idx].newindex = new_glyphs_count;
+ glyph_index[new_glyphs_count++] = idx;
+ /*
+ N.B.: Here we change `new_glyphs_count',
+ which appears in the condition of the `for' loop
+ */
+ }
+ put_ushort(glyph_tab[idx].newindex);
+ if (flags & ARG_1_AND_2_ARE_WORDS)
+ ttf_ncopy(2*TTF_SHORT_SIZE);
+ else
+ ttf_ncopy(TTF_USHORT_SIZE);
+ if (flags & WE_HAVE_A_SCALE)
+ ttf_ncopy(TTF_F2DOT14_SIZE);
+ else if (flags & WE_HAVE_AN_X_AND_Y_SCALE)
+ ttf_ncopy(2*TTF_F2DOT14_SIZE);
+ else if (flags & WE_HAVE_A_TWO_BY_TWO)
+ ttf_ncopy(4*TTF_F2DOT14_SIZE);
+ } while (flags & MORE_COMPONENTS);
+ if (flags & WE_HAVE_INSTRUCTIONS)
+ ttf_ncopy(copy_ushort());
+ }
+ else
+ ttf_ncopy(glyph_tab[*id + 1].offset - glyph_tab[*id].offset -
+ TTF_USHORT_SIZE - 4*TTF_FWORD_SIZE);
+ }
+ }
+ last_glyf_offset = ttf_offset() - new_glyf_offset;
+ ttf_set_chksm(tab);
+}
+
+static void ttf_reindex_glyphs(void)
+{
+ ttfenc_entry *e;
+ glyph_entry *glyph;
+ unsigned int index;
+ /*
+ * reindexing glyphs: we append index of used glyphs to `glyph_index'
+ * while going through `ttfenc_tab'. After appending a new entry to
+ * `glyph_index' we set field `newindex' of corresponding entries in both
+ * `glyph_tab' and `ttfenc_tab' to the newly created index
+ *
+ */
+ for (e = ttfenc_tab; e - ttfenc_tab <= MAX_CHAR_CODE; e++) {
+ e->newindex = 0; /* index of ".notdef" glyph */
+ if (e->name == notdef)
+ continue;
+ /* scan form `index123' */
+ if (sscanf(e->name, GLYPH_PREFIX_INDEX "%i", &index) == 1) {
+ if (index >= glyphs_count) {
+ pdftex_warn("`%s' out of valid range [0..%i)",
+ e->name, glyphs_count);
+ continue;
+ }
+ glyph = glyph_tab + index;
+ goto append_new_glyph;
+ }
+ /* scan form `uniABCD' */
+ if (sscanf(e->name, GLYPH_PREFIX_UNICODE "%X", &index) == 1) {
+ assert(index <= 0xFFFF);
+ if (unicode_map[index] != NOGLYPH_ASSIGNED_YET) {
+ if (unicode_map[index] >= glyphs_count) {
+ pdftex_warn("`%s' is mapped to index %i which is out of valid range [0..%i)",
+ e->name, unicode_map[index], glyphs_count);
+ continue;
+ }
+ glyph = glyph_tab + unicode_map[index];
+ goto append_new_glyph;
+ }
+ else {
+ pdftex_warn("`unicode %s%.4X' is not mapped to any glyph",
+ GLYPH_PREFIX_UNICODE, index);
+ continue;
+ }
+ }
+ /* look up by name */
+ for (glyph = glyph_tab; glyph - glyph_tab < glyphs_count; glyph++)
+ if (glyph->name != notdef && strcmp(glyph->name, e->name) == 0)
+ break;
+ if (!(glyph - glyph_tab < glyphs_count)) {
+ pdftex_warn("glyph `%s' not found", e->name);
+ continue;
+ }
+append_new_glyph:
+ assert(glyph - glyph_tab < glyphs_count);
+ if (glyph->newindex < 0) {
+ glyph_index[new_glyphs_count] = glyph - glyph_tab;
+ glyph->newindex = new_glyphs_count;
+ new_glyphs_count++;
+ }
+ e->newindex = glyph->newindex;
+ }
+}
+
+static void ttf_write_head()
+{
+ dirtab_entry *tab;
+ tab = ttf_seek_tab("head", 0);
+ ttf_reset_chksm(tab);
+ ttf_ncopy(2*TTF_FIXED_SIZE);
+ checkSumAdjustment_offset = ttf_offset();
+ put_ulong(0);
+ ttf_skip(TTF_ULONG_SIZE); /* skip checkSumAdjustment */
+ ttf_ncopy(TTF_ULONG_SIZE + 2*TTF_USHORT_SIZE + 16 +
+ 4*TTF_FWORD_SIZE + 2*TTF_USHORT_SIZE + TTF_SHORT_SIZE);
+ if (is_subsetted(fm_cur)) {
+ put_short(loca_format);
+ put_short(0);
+ }
+ else
+ ttf_ncopy(2*TTF_SHORT_SIZE);
+ ttf_set_chksm(tab);
+}
+
+static void ttf_write_hhea(void)
+{
+ dirtab_entry *tab;
+ tab = ttf_seek_tab("hhea", 0);
+ ttf_reset_chksm(tab);
+ ttf_ncopy(TTF_FIXED_SIZE + 3*TTF_FWORD_SIZE + TTF_UFWORD_SIZE + 3*TTF_FWORD_SIZE + 8*TTF_SHORT_SIZE);
+ put_ushort(new_glyphs_count);
+ ttf_set_chksm(tab);
+}
+
+static void ttf_write_htmx(void)
+{
+ short *id;
+ dirtab_entry *tab = ttf_seek_tab("hmtx", 0);
+ ttf_reset_chksm(tab);
+ for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) {
+ put_ufword(glyph_tab[*id].advWidth);
+ put_ufword(glyph_tab[*id].lsb);
+ }
+ ttf_set_chksm(tab);
+}
+
+static void ttf_write_loca(void)
+{
+ short *id;
+ dirtab_entry *tab = ttf_seek_tab("loca", 0);
+ ttf_reset_chksm(tab);
+ loca_format = 0;
+ if (last_glyf_offset >= 0x00020000 || (last_glyf_offset & 1))
+ loca_format = 1;
+ else
+ for (id = glyph_index; id - glyph_index < new_glyphs_count; id++)
+ if (glyph_tab[*id].newoffset & 1) {
+ loca_format = 1;
+ break;
+ }
+ if (loca_format != 0) {
+ for (id = glyph_index; id - glyph_index < new_glyphs_count; id++)
+ put_ulong(glyph_tab[*id].newoffset);
+ put_ulong(last_glyf_offset);
+ }
+ else {
+ for (id = glyph_index; id - glyph_index < new_glyphs_count; id++)
+ put_ushort(glyph_tab[*id].newoffset/2);
+ put_ushort(last_glyf_offset/2);
+ }
+ ttf_set_chksm(tab);
+}
+
+static void ttf_write_mapx(void)
+{
+ dirtab_entry *tab = ttf_seek_tab("maxp", TTF_FIXED_SIZE + TTF_USHORT_SIZE);
+ ttf_reset_chksm(tab);
+ put_fixed(0x00010000);
+ put_ushort(new_glyphs_count);
+ ttf_ncopy(13*TTF_USHORT_SIZE);
+ ttf_set_chksm(tab);
+}
+
+static void ttf_write_OS2(void)
+{
+ dirtab_entry *tab = ttf_seek_tab("OS/2", 0);
+ TTF_USHORT version;
+ ttf_reset_chksm(tab);
+ version = get_ushort();
+ if (version != 0x0000 && version != 0x0001 && version != 0x0002)
+ pdftex_fail("unknown verssion of OS/2 table (%.4X)", version);
+ put_ushort(0x0001); /* fix version to 1*/
+ ttf_ncopy(2*TTF_USHORT_SIZE + 13*TTF_SHORT_SIZE + 10*TTF_BYTE_SIZE);
+ ttf_skip(4*TTF_ULONG_SIZE); /* ulUnicodeRange 1--4 */
+ put_ulong(0x00000003); /* Basic Latin + Latin-1 Supplement (0x0000--0x00FF) */
+ put_ulong(0x10000000); /* Private Use (0xE000--0xF8FF) */
+ put_ulong(0x00000000);
+ put_ulong(0x00000000);
+ ttf_ncopy(4*TTF_CHAR_SIZE + TTF_USHORT_SIZE); /* achVendID + fsSelection */
+ ttf_skip(2*TTF_USHORT_SIZE);
+ put_ushort(0x0000); /* usFirstCharIndex */
+ put_ushort(0xF0FF); /* usLastCharIndex */
+ ttf_ncopy(5*TTF_USHORT_SIZE);
+ /* for version 0 the OS/2 table ends here, the rest is for version 1 */
+ put_ulong(0x80000000); /* Symbol Character Set---don't use any code page */
+ put_ulong(0x00000000);
+ ttf_set_chksm(tab);
+}
+
+static boolean unsafe_name(char *s)
+{
+ const char **p;
+ for (p = ambiguous_names; *p != NULL; p++)
+ if (strcmp(s, *p) == 0)
+ return true;
+ return false;
+}
+
+static void ttf_write_post(void)
+{
+ dirtab_entry *tab = ttf_seek_tab("post", TTF_FIXED_SIZE);
+ glyph_entry *glyph;
+ char *s;
+ short *id;
+ int l;
+ ttf_reset_chksm(tab);
+ if (!write_ttf_glyph_names || post_format == 0x00030000) {
+ put_fixed(0x00030000);
+ ttf_ncopy(TTF_FIXED_SIZE + 2*TTF_FWORD_SIZE + 5*TTF_ULONG_SIZE);
+ }
+ else {
+ put_fixed(0x00020000);
+ ttf_ncopy(TTF_FIXED_SIZE + 2*TTF_FWORD_SIZE + 5*TTF_ULONG_SIZE);
+ put_ushort(new_glyphs_count);
+ k = 0;
+ for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) {
+ glyph = glyph_tab + *id;
+ if (glyph->name_index >= NMACGLYPHS || unsafe_name(glyph->name))
+ glyph->name_index = NMACGLYPHS + k++;
+ put_ushort(glyph->name_index);
+ }
+ for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) {
+ glyph = glyph_tab + *id;
+ if (glyph->name_index >= NMACGLYPHS) {
+ s = glyph->name;
+ l = strlen(s);
+ put_byte(l);
+ while (l-- > 0)
+ put_char(*s++);
+ }
+ }
+ }
+ ttf_set_chksm(tab);
+}
+
+static void ttf_init_font(int n)
+{
+ int i, k;
+ for (i = 1, k = 0; i <= n; i <<= 1, k++);
+ put_fixed(0x00010000); /* font version */
+ put_ushort(n); /* number of tables */
+ put_ushort(i << 3); /* search range */
+ put_ushort(k - 1); /* entry selector */
+ put_ushort((n<<4) - (i<<3)); /* range shift */
+ ttf_seek_outbuf(TABDIR_OFF + n*4*TTF_ULONG_SIZE);
+}
+
+static void ttf_subset_font(void)
+{
+ ttf_init_font(new_ntabs);
+ if (ttf_name_lookup("PCLT", false) != NULL)
+ ttf_copytab("PCLT");
+ if (ttf_name_lookup("fpgm", false) != NULL)
+ ttf_copytab("fpgm");
+ if (ttf_name_lookup("cvt ", false) != NULL)
+ ttf_copytab("cvt ");
+ if (ttf_name_lookup("prep", false) != NULL)
+ ttf_copytab("prep");
+ ttf_reindex_glyphs();
+ ttf_write_glyf();
+ ttf_write_loca();
+ ttf_write_OS2();
+ ttf_write_head();
+ ttf_write_hhea();
+ ttf_write_htmx();
+ ttf_write_mapx();
+ ttf_write_name();
+ ttf_write_post();
+ ttf_write_cmap();
+ ttf_write_dirtab();
+}
+
+static void ttf_copy_font(void)
+{
+ dirtab_entry *tab;
+ ttf_init_font(ntabs);
+ for (tab = dir_tab; tab - dir_tab < ntabs; tab++) {
+ if (strncmp(tab->tag, "head", 4) == 0)
+ ttf_write_head();
+ else
+ ttf_copytab(tab->tag);
+ }
+ ttf_write_dirtab();
+}
+
+void writettf()
+{
+ set_cur_file_name(fm_cur->ff_name);
+ if (is_subsetted(fm_cur) && !(is_reencoded(fm_cur))) {
+ pdftex_warn("encoding vector required for TrueType font subsetting");
+ cur_file_name = NULL;
+ return;
+ }
+ if (!ttf_open()) {
+ pdftex_fail("cannot open TrueType font file for reading");
+ }
+ cur_file_name = (char*)nameoffile + 1;
+ if (!is_included(fm_cur))
+ tex_printf("{%s", cur_file_name);
+ else if (is_subsetted(fm_cur))
+ tex_printf("<%s", cur_file_name);
+ else
+ tex_printf("<<%s", cur_file_name);
+ fontfile_found = true;
+ new_glyphs_count = 2;
+ new_ntabs = DEFAULT_NTABS;
+ dir_tab = NULL;
+ glyph_tab = NULL;
+ glyph_index = NULL;
+ glyph_name_buf = NULL;
+ name_tab = NULL;
+ name_buf = NULL;
+ ttf_read_font();
+ if (is_included(fm_cur)) {
+ pdfsaveoffset = pdfoffset();
+ pdfflush();
+ if (is_subsetted(fm_cur)) {
+ ttf_copy_encoding();
+ make_subset_tag(fm_cur, fm_cur->encoding->glyph_names);
+ ttf_subset_font();
+ }
+ else
+ ttf_copy_font();
+ ttf_length = ttf_offset();
+ }
+ xfree(dir_tab);
+ xfree(glyph_tab);
+ xfree(glyph_index);
+ xfree(glyph_name_buf);
+ xfree(name_tab);
+ xfree(name_buf);
+ ttf_close();
+ if (!is_included(fm_cur))
+ tex_printf("}");
+ else if (is_subsetted(fm_cur))
+ tex_printf(">");
+ else
+ tex_printf(">>");
+ cur_file_name = NULL;
+}
+
+void writeotf()
+{
+ dirtab_entry *tab;
+ long i;
+ set_cur_file_name(fm_cur->ff_name);
+ if (!open_input(&ttf_file, kpse_type1_format, FOPEN_RBIN_MODE)) {
+ pdftex_fail("cannot open OpenType font file for reading");
+ }
+ cur_file_name = (char*)nameoffile + 1;
+ tex_printf("<<%s", cur_file_name);
+ fontfile_found = true;
+ dir_tab = NULL;
+ glyph_tab = NULL;
+ ttf_read_tabdir();
+ /* read font parameters */
+ if (ttf_name_lookup("head", false) != NULL)
+ ttf_read_head();
+ if (ttf_name_lookup("hhea", false) != NULL)
+ ttf_read_hhea();
+ if (ttf_name_lookup("PCLT", false) != NULL)
+ ttf_read_pclt();
+ if (ttf_name_lookup("post", false) != NULL)
+ ttf_read_post();
+ /* copy font file */
+ tab = ttf_seek_tab("CFF ", 0);
+ for (i = tab->length; i > 0; i--)
+ copy_char();
+ xfree(dir_tab);
+ ttf_close();
+ tex_printf(">>");
+ cur_file_name = NULL;
+}
+
+/*
+ To calculate the checkSum for the 'head' table which itself includes the
+ checkSumAdjustment entry for the entire font, do the following:
+
+ * Set the checkSumAdjustment to 0.
+ * Calculate the checksum for all the tables including the 'head' table
+ and enter that value into the table directory.
+ * Calculate the checksum for the entire font.
+ * Subtract that value from the hex value B1B0AFBA.
+ * Store the result in checkSumAdjustment.
+
+ The checkSum for the 'head table which includes the checkSumAdjustment
+ entry for the entire font is now incorrect. That is not a problem. Do not
+ change it. An application attempting to verify that the 'head' table has
+ not changed should calculate the checkSum for that table by not including
+ the checkSumAdjustment value, and compare the result with the entry in the
+ table directory.
+
+ The table directory also includes the offset of the associated tagged
+ table from the beginning of the font file and the length of that table.
+
+
+ */
diff --git a/Build/source/texk/web2c/pdftexdir/writettf.h b/Build/source/texk/web2c/pdftexdir/writettf.h
new file mode 100644
index 00000000000..eca53cdfe30
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/writettf.h
@@ -0,0 +1,130 @@
+/*
+Copyright (c) 1996-2002 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX 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.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/writettf.h#1 $
+*/
+
+typedef signed char TTF_CHAR;
+typedef unsigned char TTF_BYTE;
+typedef signed short TTF_SHORT;
+typedef unsigned short TTF_USHORT;
+typedef signed long TTF_LONG;
+typedef unsigned long TTF_ULONG;
+typedef unsigned long TTF_FIXED;
+typedef unsigned short TTF_FUNIT;
+typedef signed short TTF_FWORD;
+typedef unsigned short TTF_UFWORD;
+typedef unsigned short TTF_F2DOT14;
+
+#define TTF_CHAR_SIZE 1
+#define TTF_BYTE_SIZE 1
+#define TTF_SHORT_SIZE 2
+#define TTF_USHORT_SIZE 2
+#define TTF_LONG_SIZE 4
+#define TTF_ULONG_SIZE 4
+#define TTF_FIXED_SIZE 4
+#define TTF_FWORD_SIZE 2
+#define TTF_UFWORD_SIZE 2
+#define TTF_F2DOT14_SIZE 2
+
+#define ARG_1_AND_2_ARE_WORDS (1<<0)
+#define ARGS_ARE_XY_VALUES (1<<1)
+#define ROUND_XY_TO_GRID (1<<2)
+#define WE_HAVE_A_SCALE (1<<3)
+#define RESERVED (1<<4)
+#define MORE_COMPONENTS (1<<5)
+#define WE_HAVE_AN_X_AND_Y_SCALE (1<<6)
+#define WE_HAVE_A_TWO_BY_TWO (1<<7)
+#define WE_HAVE_INSTRUCTIONS (1<<8)
+#define USE_MY_METRICS (1<<9)
+
+#define get_type(t) ((t)ttf_getnum(t##_SIZE))
+#define ttf_skip(n) ttf_getnum(n)
+
+#define get_byte() get_type(TTF_BYTE)
+#define get_char() get_type(TTF_CHAR)
+#define get_ushort() get_type(TTF_USHORT)
+#define get_short() get_type(TTF_SHORT)
+#define get_ulong() get_type(TTF_ULONG)
+#define get_long() get_type(TTF_LONG)
+#define get_fixed() get_type(TTF_FIXED)
+#define get_funit() get_type(TTF_FUNIT)
+#define get_fword() get_type(TTF_FWORD)
+#define get_ufword() get_type(TTF_UFWORD)
+#define get_f2dot14() get_type(TTF_F2DOT14)
+
+#define put_num(t,n) ((t)ttf_putnum(t##_SIZE, n))
+
+#define put_char(n) put_num(TTF_CHAR, n)
+#define put_byte(n) put_num(TTF_BYTE, n)
+#define put_short(n) put_num(TTF_SHORT, n)
+#define put_ushort(n) put_num(TTF_USHORT, n)
+#define put_long(n) put_num(TTF_LONG, n)
+#define put_ulong(n) put_num(TTF_ULONG, n)
+#define put_fixed(n) put_num(TTF_FIXED, n)
+#define put_funit(n) put_num(TTF_FUNIT, n)
+#define put_fword(n) put_num(TTF_FWORD, n)
+#define put_ufword(n) put_num(TTF_UFWORD, n)
+#define put_f2dot14(n) put_num(TTF_F2DOT14, n)
+
+#define copy_byte() put_byte(get_byte())
+#define copy_char() put_char(get_char())
+#define copy_ushort() put_ushort(get_ushort())
+#define copy_short() put_short(get_short())
+#define copy_ulong() put_ulong(get_ulong())
+#define copy_long() put_long(get_long())
+#define copy_fixed() put_fixed(get_fixed())
+#define copy_funit() put_funit(get_funit())
+#define copy_fword() put_fword(get_fword())
+#define copy_ufword() put_ufword(get_ufword())
+#define copy_f2dot14() put_f2dot14(get_f2dot14())
+
+#define is_unicode_mapping(e) \
+ (e->platform_id == 0 || (e->platform_id == 3 || e->encoding_id == 1))
+
+
+#define NMACGLYPHS 258
+#define TABDIR_OFF 12
+#define ENC_BUF_SIZE 1024
+
+#define GLYPH_PREFIX_INDEX "index"
+#define GLYPH_PREFIX_UNICODE "uni"
+
+#define NOGLYPH_ASSIGNED_YET 0xFFFF /* indicating that no glyph is assigned to
+ an unicode */
+typedef struct {
+ char tag[4];
+ TTF_ULONG checksum;
+ TTF_ULONG offset;
+ TTF_ULONG length;
+} dirtab_entry;
+
+typedef struct {
+ TTF_USHORT platform_id;
+ TTF_USHORT encoding_id;
+ TTF_ULONG offset;
+ TTF_USHORT format;
+} cmap_entry;
+
+typedef struct {
+ TTF_USHORT endCode;
+ TTF_USHORT startCode;
+ TTF_USHORT idDelta;
+ TTF_USHORT idRangeOffset;
+} seg_entry;
diff --git a/Build/source/texk/web2c/pdftexdir/writezip.c b/Build/source/texk/web2c/pdftexdir/writezip.c
new file mode 100644
index 00000000000..3669397617c
--- /dev/null
+++ b/Build/source/texk/web2c/pdftexdir/writezip.c
@@ -0,0 +1,82 @@
+/*
+Copyright (c) 1996-2002 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX 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.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/writezip.c#7 $
+*/
+
+#include "ptexlib.h"
+#include "zlib.h"
+
+static const char perforce_id[] =
+ "$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/writezip.c#7 $";
+
+#define ZIP_BUF_SIZE 32768
+
+#define check_err(f, fn) \
+ if (f != Z_OK) \
+ pdftex_fail("zlib: %s() failed", fn)
+
+
+static char zipbuf[ZIP_BUF_SIZE];
+static z_stream c_stream; /* compression stream */
+
+void writezip(boolean finish)
+{
+ int err;
+
+ if (!getpdfcompresslevel()) {
+ if (pdfptr) {
+ pdfgone += xfwrite(pdfbuf, 1, pdfptr, pdffile);
+ pdfstreamlength += pdfptr;
+ }
+ return;
+ }
+
+ cur_file_name = NULL;
+ if (pdfstreamlength == 0) {
+ c_stream.zalloc = (alloc_func)0;
+ c_stream.zfree = (free_func)0;
+ c_stream.opaque = (voidpf)0;
+ check_err(deflateInit(&c_stream, getpdfcompresslevel()), "deflateInit");
+ c_stream.next_out = (Bytef*)zipbuf;
+ c_stream.avail_out = ZIP_BUF_SIZE;
+ }
+ c_stream.next_in = pdfbuf;
+ c_stream.avail_in = pdfptr;
+ for(;;) {
+ if (c_stream.avail_out == 0) {
+ pdfgone += xfwrite(zipbuf, 1, ZIP_BUF_SIZE, pdffile);
+ c_stream.next_out = (Bytef*)zipbuf;
+ c_stream.avail_out = ZIP_BUF_SIZE;
+ }
+ err = deflate(&c_stream, finish ? Z_FINISH : Z_NO_FLUSH);
+ if (finish && err == Z_STREAM_END)
+ break;
+ check_err(err, "deflate");
+ if (!finish && c_stream.avail_in == 0)
+ break;
+ }
+ if (finish) {
+ if (c_stream.avail_out < ZIP_BUF_SIZE) /* at least one byte has been output */
+ pdfgone += xfwrite(zipbuf, 1, ZIP_BUF_SIZE - c_stream.avail_out, pdffile);
+ check_err(deflateEnd(&c_stream), "deflateEnd");
+ xfflush(pdffile);
+ }
+ pdfstreamlength = c_stream.total_out;
+}