From 0b5550c241229764120d133af80a0cbab5937ddd Mon Sep 17 00:00:00 2001 From: Martin Schröder Date: Mon, 24 Mar 2008 15:47:15 +0000 Subject: First step of importing luatex (up to r1121) git-svn-id: svn://tug.org/texlive/trunk@7124 c570f23f-e606-0410-a88d-b1316a301751 --- Build/source/texk/web2c/Makefile.in | 9 +- Build/source/texk/web2c/luatexdir/.indent.pro | 12 + Build/source/texk/web2c/luatexdir/ChangeLog | 69 + Build/source/texk/web2c/luatexdir/Makefile.in | 141 + Build/source/texk/web2c/luatexdir/NEWS | 537 + Build/source/texk/web2c/luatexdir/README | 87 + Build/source/texk/web2c/luatexdir/avl.c | 893 + Build/source/texk/web2c/luatexdir/avl.h | 115 + Build/source/texk/web2c/luatexdir/avlstuff.c | 180 + Build/source/texk/web2c/luatexdir/avlstuff.h | 29 + Build/source/texk/web2c/luatexdir/change-files.txt | 35 + Build/source/texk/web2c/luatexdir/depend.mk | 2874 ++ Build/source/texk/web2c/luatexdir/font/.indent.pro | 12 + Build/source/texk/web2c/luatexdir/font/dofont.c | 183 + Build/source/texk/web2c/luatexdir/font/luafont.c | 1733 + Build/source/texk/web2c/luatexdir/font/macnames.c | 312 + Build/source/texk/web2c/luatexdir/font/mapfile.c | 967 + Build/source/texk/web2c/luatexdir/font/pkin.c | 439 + Build/source/texk/web2c/luatexdir/font/sfnt.c | 647 + Build/source/texk/web2c/luatexdir/font/sfnt.h | 197 + Build/source/texk/web2c/luatexdir/font/subfont.c | 264 + Build/source/texk/web2c/luatexdir/font/subfont.txt | 74 + Build/source/texk/web2c/luatexdir/font/texfont.c | 1094 + Build/source/texk/web2c/luatexdir/font/texfont.h | 524 + Build/source/texk/web2c/luatexdir/font/tfmofm.c | 1005 + Build/source/texk/web2c/luatexdir/font/tounicode.c | 604 + Build/source/texk/web2c/luatexdir/font/tt_glyf.c | 658 + Build/source/texk/web2c/luatexdir/font/tt_glyf.h | 60 + Build/source/texk/web2c/luatexdir/font/tt_table.c | 483 + Build/source/texk/web2c/luatexdir/font/tt_table.h | 193 + Build/source/texk/web2c/luatexdir/font/vfovf.c | 1349 + Build/source/texk/web2c/luatexdir/font/vfpacket.c | 377 + Build/source/texk/web2c/luatexdir/font/writecff.c | 3381 ++ Build/source/texk/web2c/luatexdir/font/writecff.h | 349 + Build/source/texk/web2c/luatexdir/font/writeenc.c | 183 + Build/source/texk/web2c/luatexdir/font/writefont.c | 885 + Build/source/texk/web2c/luatexdir/font/writet1.c | 1768 + Build/source/texk/web2c/luatexdir/font/writet3.c | 348 + Build/source/texk/web2c/luatexdir/font/writettf.c | 1509 + Build/source/texk/web2c/luatexdir/font/writettf.h | 172 + .../source/texk/web2c/luatexdir/font/writetype0.c | 124 + .../source/texk/web2c/luatexdir/font/writetype2.c | 422 + Build/source/texk/web2c/luatexdir/hyphen.h | 60 + .../source/texk/web2c/luatexdir/image/.indent.pro | 12 + Build/source/texk/web2c/luatexdir/image/epdf.c | 107 + Build/source/texk/web2c/luatexdir/image/epdf.h | 125 + Build/source/texk/web2c/luatexdir/image/image.h | 223 + .../source/texk/web2c/luatexdir/image/pdftoepdf.cc | 1008 + Build/source/texk/web2c/luatexdir/image/writeimg.c | 677 + .../source/texk/web2c/luatexdir/image/writejbig2.c | 749 + .../source/texk/web2c/luatexdir/image/writejbig2.h | 151 + Build/source/texk/web2c/luatexdir/image/writejpg.c | 277 + Build/source/texk/web2c/luatexdir/image/writepng.c | 635 + Build/source/texk/web2c/luatexdir/lang/hnjalloc.c | 72 + Build/source/texk/web2c/luatexdir/lang/hnjalloc.h | 46 + Build/source/texk/web2c/luatexdir/lang/hyphen.c | 830 + Build/source/texk/web2c/luatexdir/lang/texlang.c | 825 + Build/source/texk/web2c/luatexdir/lua/.indent.pro | 12 + .../source/texk/web2c/luatexdir/lua/lcallbacklib.c | 463 + Build/source/texk/web2c/luatexdir/lua/lfontlib.c | 213 + Build/source/texk/web2c/luatexdir/lua/limglib.c | 714 + Build/source/texk/web2c/luatexdir/lua/lkpselib.c | 272 + Build/source/texk/web2c/luatexdir/lua/llanglib.c | 219 + Build/source/texk/web2c/luatexdir/lua/llualib.c | 229 + Build/source/texk/web2c/luatexdir/lua/lmplib.c | 1251 + Build/source/texk/web2c/luatexdir/lua/lnodelib.c | 1967 + Build/source/texk/web2c/luatexdir/lua/loslibext.c | 627 + Build/source/texk/web2c/luatexdir/lua/lpdflib.c | 127 + Build/source/texk/web2c/luatexdir/lua/lstatslib.c | 211 + Build/source/texk/web2c/luatexdir/lua/ltexiolib.c | 117 + Build/source/texk/web2c/luatexdir/lua/ltexlib.c | 820 + Build/source/texk/web2c/luatexdir/lua/ltokenlib.c | 263 + Build/source/texk/web2c/luatexdir/lua/luainit.c | 520 + Build/source/texk/web2c/luatexdir/lua/luanode.c | 200 + Build/source/texk/web2c/luatexdir/lua/luastuff.c | 310 + Build/source/texk/web2c/luatexdir/lua/luatex.c | 343 + Build/source/texk/web2c/luatexdir/lua/luatoken.c | 548 + Build/source/texk/web2c/luatexdir/lua/mp.w | 26173 ++++++++++++++ Build/source/texk/web2c/luatexdir/lua/psout.w | 5697 +++ Build/source/texk/web2c/luatexdir/lua/texluac.c | 199 + Build/source/texk/web2c/luatexdir/luatangle.ch | 492 + Build/source/texk/web2c/luatexdir/luatangle.web | 3328 ++ Build/source/texk/web2c/luatexdir/luatex-api.h | 104 + Build/source/texk/web2c/luatexdir/luatex.ch | 2623 ++ Build/source/texk/web2c/luatexdir/luatex.defines | 560 + Build/source/texk/web2c/luatexdir/luatex.h | 173 + Build/source/texk/web2c/luatexdir/luatex.mk | 170 + Build/source/texk/web2c/luatexdir/luatex.web | 35760 +++++++++++++++++++ Build/source/texk/web2c/luatexdir/luatexextra.in | 42 + Build/source/texk/web2c/luatexdir/luatexlib.mk | 214 + Build/source/texk/web2c/luatexdir/macnames.c | 312 + Build/source/texk/web2c/luatexdir/makecpool.c | 60 + Build/source/texk/web2c/luatexdir/managed-sa.c | 245 + Build/source/texk/web2c/luatexdir/managed-sa.h | 74 + Build/source/texk/web2c/luatexdir/mathcodes.c | 191 + Build/source/texk/web2c/luatexdir/nodes.h | 648 + Build/source/texk/web2c/luatexdir/pdftosrc.1 | 219 + Build/source/texk/web2c/luatexdir/pdftosrc.cc | 178 + Build/source/texk/web2c/luatexdir/pdftosrc.rc | 35 + Build/source/texk/web2c/luatexdir/ptexlib.h | 615 + Build/source/texk/web2c/luatexdir/ptexmac.h | 236 + Build/source/texk/web2c/luatexdir/svnversion.h | 3 + Build/source/texk/web2c/luatexdir/tex/linebreak.c | 2095 ++ .../texk/web2c/luatexdir/tex/postlinebreak.c | 512 + Build/source/texk/web2c/luatexdir/tex/texnodes.c | 1694 + Build/source/texk/web2c/luatexdir/tex/texpdf.c | 169 + Build/source/texk/web2c/luatexdir/tex/textoken.c | 753 + Build/source/texk/web2c/luatexdir/textcodes.c | 278 + Build/source/texk/web2c/luatexdir/tokens.h | 68 + Build/source/texk/web2c/luatexdir/ttf2afm.c | 1053 + Build/source/texk/web2c/luatexdir/ttf2afm.rc | 35 + Build/source/texk/web2c/luatexdir/utils.c | 1798 + Build/source/texk/web2c/luatexdir/writezip.c | 98 + Build/source/texk/web2c/web2c/coerce.h | 5 + Build/source/texk/web2c/web2c/splitup.c | 7 +- 115 files changed, 127432 insertions(+), 4 deletions(-) create mode 100644 Build/source/texk/web2c/luatexdir/.indent.pro create mode 100644 Build/source/texk/web2c/luatexdir/ChangeLog create mode 100644 Build/source/texk/web2c/luatexdir/Makefile.in create mode 100644 Build/source/texk/web2c/luatexdir/NEWS create mode 100644 Build/source/texk/web2c/luatexdir/README create mode 100644 Build/source/texk/web2c/luatexdir/avl.c create mode 100644 Build/source/texk/web2c/luatexdir/avl.h create mode 100644 Build/source/texk/web2c/luatexdir/avlstuff.c create mode 100644 Build/source/texk/web2c/luatexdir/avlstuff.h create mode 100644 Build/source/texk/web2c/luatexdir/change-files.txt create mode 100644 Build/source/texk/web2c/luatexdir/depend.mk create mode 100644 Build/source/texk/web2c/luatexdir/font/.indent.pro create mode 100644 Build/source/texk/web2c/luatexdir/font/dofont.c create mode 100644 Build/source/texk/web2c/luatexdir/font/luafont.c create mode 100644 Build/source/texk/web2c/luatexdir/font/macnames.c create mode 100644 Build/source/texk/web2c/luatexdir/font/mapfile.c create mode 100644 Build/source/texk/web2c/luatexdir/font/pkin.c create mode 100644 Build/source/texk/web2c/luatexdir/font/sfnt.c create mode 100644 Build/source/texk/web2c/luatexdir/font/sfnt.h create mode 100644 Build/source/texk/web2c/luatexdir/font/subfont.c create mode 100644 Build/source/texk/web2c/luatexdir/font/subfont.txt create mode 100644 Build/source/texk/web2c/luatexdir/font/texfont.c create mode 100644 Build/source/texk/web2c/luatexdir/font/texfont.h create mode 100644 Build/source/texk/web2c/luatexdir/font/tfmofm.c create mode 100644 Build/source/texk/web2c/luatexdir/font/tounicode.c create mode 100644 Build/source/texk/web2c/luatexdir/font/tt_glyf.c create mode 100644 Build/source/texk/web2c/luatexdir/font/tt_glyf.h create mode 100644 Build/source/texk/web2c/luatexdir/font/tt_table.c create mode 100644 Build/source/texk/web2c/luatexdir/font/tt_table.h create mode 100644 Build/source/texk/web2c/luatexdir/font/vfovf.c create mode 100644 Build/source/texk/web2c/luatexdir/font/vfpacket.c create mode 100644 Build/source/texk/web2c/luatexdir/font/writecff.c create mode 100644 Build/source/texk/web2c/luatexdir/font/writecff.h create mode 100644 Build/source/texk/web2c/luatexdir/font/writeenc.c create mode 100644 Build/source/texk/web2c/luatexdir/font/writefont.c create mode 100644 Build/source/texk/web2c/luatexdir/font/writet1.c create mode 100644 Build/source/texk/web2c/luatexdir/font/writet3.c create mode 100644 Build/source/texk/web2c/luatexdir/font/writettf.c create mode 100644 Build/source/texk/web2c/luatexdir/font/writettf.h create mode 100644 Build/source/texk/web2c/luatexdir/font/writetype0.c create mode 100644 Build/source/texk/web2c/luatexdir/font/writetype2.c create mode 100644 Build/source/texk/web2c/luatexdir/hyphen.h create mode 100644 Build/source/texk/web2c/luatexdir/image/.indent.pro create mode 100644 Build/source/texk/web2c/luatexdir/image/epdf.c create mode 100644 Build/source/texk/web2c/luatexdir/image/epdf.h create mode 100644 Build/source/texk/web2c/luatexdir/image/image.h create mode 100644 Build/source/texk/web2c/luatexdir/image/pdftoepdf.cc create mode 100644 Build/source/texk/web2c/luatexdir/image/writeimg.c create mode 100644 Build/source/texk/web2c/luatexdir/image/writejbig2.c create mode 100644 Build/source/texk/web2c/luatexdir/image/writejbig2.h create mode 100644 Build/source/texk/web2c/luatexdir/image/writejpg.c create mode 100644 Build/source/texk/web2c/luatexdir/image/writepng.c create mode 100644 Build/source/texk/web2c/luatexdir/lang/hnjalloc.c create mode 100644 Build/source/texk/web2c/luatexdir/lang/hnjalloc.h create mode 100644 Build/source/texk/web2c/luatexdir/lang/hyphen.c create mode 100644 Build/source/texk/web2c/luatexdir/lang/texlang.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/.indent.pro create mode 100644 Build/source/texk/web2c/luatexdir/lua/lcallbacklib.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/lfontlib.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/limglib.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/lkpselib.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/llanglib.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/llualib.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/lmplib.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/lnodelib.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/loslibext.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/lpdflib.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/lstatslib.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/ltexiolib.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/ltexlib.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/ltokenlib.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/luainit.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/luanode.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/luastuff.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/luatex.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/luatoken.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/mp.w create mode 100644 Build/source/texk/web2c/luatexdir/lua/psout.w create mode 100644 Build/source/texk/web2c/luatexdir/lua/texluac.c create mode 100644 Build/source/texk/web2c/luatexdir/luatangle.ch create mode 100644 Build/source/texk/web2c/luatexdir/luatangle.web create mode 100644 Build/source/texk/web2c/luatexdir/luatex-api.h create mode 100644 Build/source/texk/web2c/luatexdir/luatex.ch create mode 100644 Build/source/texk/web2c/luatexdir/luatex.defines create mode 100644 Build/source/texk/web2c/luatexdir/luatex.h create mode 100644 Build/source/texk/web2c/luatexdir/luatex.mk create mode 100644 Build/source/texk/web2c/luatexdir/luatex.web create mode 100644 Build/source/texk/web2c/luatexdir/luatexextra.in create mode 100644 Build/source/texk/web2c/luatexdir/luatexlib.mk create mode 100644 Build/source/texk/web2c/luatexdir/macnames.c create mode 100644 Build/source/texk/web2c/luatexdir/makecpool.c create mode 100644 Build/source/texk/web2c/luatexdir/managed-sa.c create mode 100644 Build/source/texk/web2c/luatexdir/managed-sa.h create mode 100644 Build/source/texk/web2c/luatexdir/mathcodes.c create mode 100644 Build/source/texk/web2c/luatexdir/nodes.h create mode 100644 Build/source/texk/web2c/luatexdir/pdftosrc.1 create mode 100644 Build/source/texk/web2c/luatexdir/pdftosrc.cc create mode 100644 Build/source/texk/web2c/luatexdir/pdftosrc.rc create mode 100644 Build/source/texk/web2c/luatexdir/ptexlib.h create mode 100644 Build/source/texk/web2c/luatexdir/ptexmac.h create mode 100644 Build/source/texk/web2c/luatexdir/svnversion.h create mode 100644 Build/source/texk/web2c/luatexdir/tex/linebreak.c create mode 100644 Build/source/texk/web2c/luatexdir/tex/postlinebreak.c create mode 100644 Build/source/texk/web2c/luatexdir/tex/texnodes.c create mode 100644 Build/source/texk/web2c/luatexdir/tex/texpdf.c create mode 100644 Build/source/texk/web2c/luatexdir/tex/textoken.c create mode 100644 Build/source/texk/web2c/luatexdir/textcodes.c create mode 100644 Build/source/texk/web2c/luatexdir/tokens.h create mode 100644 Build/source/texk/web2c/luatexdir/ttf2afm.c create mode 100644 Build/source/texk/web2c/luatexdir/ttf2afm.rc create mode 100644 Build/source/texk/web2c/luatexdir/utils.c create mode 100644 Build/source/texk/web2c/luatexdir/writezip.c (limited to 'Build/source/texk/web2c') diff --git a/Build/source/texk/web2c/Makefile.in b/Build/source/texk/web2c/Makefile.in index 0ec24cdef95..bd687a9ac8f 100644 --- a/Build/source/texk/web2c/Makefile.in +++ b/Build/source/texk/web2c/Makefile.in @@ -1,4 +1,4 @@ -# $Id: //depot/Build/source.development/TeX/texk/web2c/Makefile.in#66 $ +# $Id$ # @configure_input@ # Makefile for web2c --kb@mail.tug.org. Public domain. version = @WEB2CVERSION@ @@ -555,6 +555,7 @@ trip-clean: # # Helper makefile fragment for pdf*tex. kpse_include pdftexdir/pdftexlib.mk +#LUATEXkpse_include pdftexdir/luatexlib.mk # # Makefile fragments: kpse_include etexdir/etex.mk @@ -562,6 +563,7 @@ kpse_include omegadir/omega.mk kpse_include alephdir/aleph.mk kpse_include pdftexdir/pdftex.mk kpse_include xetexdir/xetex.mk +#LUATEXkpse_include luatexdir/luatex.mk # # non-engine programs. @@ -575,7 +577,8 @@ programs = bibtex ctangle ctie cweave dvicopy dvitomp dvitype gftodvi gftopk \ engines = $(tex) $(etex) $(mf) $(mfn) $(metapost) \ $(omega) $(aleph) \ $(pdftex) $(pdfetex) \ - $(xetex) + $(xetex) #LUATEX\ +#LUATEX $(luatex) programs: $(programs) $(engines) $(mpware_programs) \ $(omegafonts_programs) $(otps_programs) $(pdftosrc) @@ -1125,7 +1128,7 @@ installcheck: # # Cleaning. -all_subdirs = doc lib man $(mpware) web2c window $(omegafonts) $(otps) $(pdftexdir) $(mpostdir) +all_subdirs = doc lib man $(mpware) web2c window $(omegafonts) $(otps) $(pdftexdir) $(mpostdir) #LUATEX $(luatexdir) # Having a multiple-target rule with the subdir loop fails because of # the dependencies introduced by clean.mk. Yet, we want the diff --git a/Build/source/texk/web2c/luatexdir/.indent.pro b/Build/source/texk/web2c/luatexdir/.indent.pro new file mode 100644 index 00000000000..e9e690f1ba8 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/.indent.pro @@ -0,0 +1,12 @@ +/* $Id$ */ +--k-and-r-style +--blank-lines-after-procedures +--line-length 80 +--procnames-start-lines +--no-space-after-function-call-names +--dont-break-procedure-type +--space-after-cast +/* this does not work in indent 2.2.6 :-( */ +--no-tabs +/* this is new in indent 2.2.9 */ +--preprocessor-indentation 2 diff --git a/Build/source/texk/web2c/luatexdir/ChangeLog b/Build/source/texk/web2c/luatexdir/ChangeLog new file mode 100644 index 00000000000..d6004e43700 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/ChangeLog @@ -0,0 +1,69 @@ +2004-08-21 Peter Breitenlohner + + * pdfetex.ch2: Adapted to e-TeX version 2.2. + +2004-08-26 Olaf Weber + + * pdfetexextra.in: File was renamed from pdftexextra.h; the + current pdfTeX and e-TeX versions are substituted from + ../pdftexdir/pdftex.version and ../etexdir/etex.version. Variant + of code supplied by Peter Breitenlohner . + + * pdfetex.mk: Added rule to insert pdfTeX and e-TeX versions into + pdfetexextra.h. Variant of code supplied by Peter Breitenlohner + . + +2004-08-25 Olaf Weber + + * pdfetex.mk: vadjust.ch moved from pdfxtexdir to pdftexdir. + +2004-08-17 Olaf Weber + + * pdfetex.mk: Resurrected etex.fix, there is again a need to + include late-breaking changes. + +2004-07-29 Peter Breitenlohner + + * pdfetex.ch[12]: Somewhat rearrange handling of kern and math + nodes in order to reduce interference between eTeX and pdfTeX + change files. + + * pdfetex.ch1 (hlist_out): Keep full mixed direction typesetting + code. + +2004-07-25 Peter Breitenlohner + + * pdfetex.ch[12]: Reorganize additional command codes for convert + and last_item in order to reduce interference between eTeX and + pdfTeX change files. + +2004-07-23 Peter Breitenlohner + + * pdfetex.ch[12], tex.ch[01]: Reorganize handling of banner + string in order to reduce interference between eTeX, pdfTeX, + and web2c change files. + +2004-07-22 Peter Breitenlohner + + * pdfetex.ch[12]: Removed unused token types for pdfTeX's + additional token list parameters. + +2004-07-19 Peter Breitenlohner + + * pdfetex.ch[12], tex.ch0: Reorganize handling of additional + token list and integer parameters and e-TeX's additional + penalties in order to reduce interference between eTeX, pdfTeX, + and web2c change files. + + * pdfetex.mk (pdfetex.ch): Remove tex.ch2 from build rules. + + * tex.ch2: Removed. + +2004-07-17 Peter Breitenlohner + + * pdfetex.mk: Rewrite build rules for pdfetex.{web,ch}, + remove etex.{ch0,ch1,fix}, tex.ch2, and several non-dependencies. + + * pdfetex.ch2: Adapt to eTeX changes. + + * ChangeLog: New file. diff --git a/Build/source/texk/web2c/luatexdir/Makefile.in b/Build/source/texk/web2c/luatexdir/Makefile.in new file mode 100644 index 00000000000..a959a42d56b --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/Makefile.in @@ -0,0 +1,141 @@ +# Makefile for libpdf - te@dbs.uni-hannover.de +# $Id$ + +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@ -I$(LIBOBSDCOMPATDIR) -I$(LIBOBSDCOMPATDIR)/.. -I$(LIBOBSDCOMPATFSRCDIR) -I$(LIBOBSDCOMPATFSRCDIR)/.. -I$(LIBPNGSRCDIR) -I$(ZLIBSRCDIR) +CXX = @CXX@ + +CTANGLE = ../ctangle + +.SUFFIXES: .cc .o +.cc.o: + $(CXX) $(ALL_CXXFLAGS) -c $< -o $@ + +# 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) + +LIBOBSDCOMPATDIR=../../../libs/obsdcompat +LIBOBSDCOMPATFSRCDIR=$(srcdir)/$(LIBOBSDCOMPATDIR) + +XCPPFLAGS=-I.. -I$(srcdir)/.. -I../.. -I$(srcdir)/../.. -I$(LIBMD5DIR) \ + -I$(LIBMD5SRCDIR) @LIBPNGCPPFLAGS@ @ZLIBCPPFLAGS@ \ + -I$(LIBXPDFDIR) -I$(LIBXPDFDIR)/.. -I$(LIBXPDFSRCDIR) -I$(LIBXPDFSRCDIR)/.. \ + -I$(LIBOBSDCOMPATDIR) -I$(LIBOBSDCOMPATDIR)/.. -I$(LIBOBSDCOMPATFSRCDIR) \ + -I$(LIBOBSDCOMPATFSRCDIR)/.. -DpdfTeX + + +OBJS = \ +avl.o \ +avlstuff.o \ +font/mapfile.o \ +font/pkin.o \ +font/subfont.o \ +font/tounicode.o \ +font/vfpacket.o \ +font/writeenc.o \ +font/writefont.o \ +font/writet1.o \ +font/writet3.o \ +font/writettf.o \ +font/writetype0.o \ +font/writetype2.o \ +font/writecff.o \ +font/tt_glyf.o \ +font/tt_table.o \ +font/sfnt.o \ +font/texfont.o \ +font/tfmofm.o \ +font/vfovf.o \ +font/luafont.o \ +font/dofont.o \ +image/epdf.o \ +image/pdftoepdf.o \ +image/writeimg.o \ +image/writejbig2.o \ +image/writejpg.o \ +image/writepng.o \ +lua/loslibext.o \ +lua/lcallbacklib.o \ +lua/lkpselib.o \ +lua/llualib.o \ +lua/lnodelib.o \ +lua/lpdflib.o \ +lua/lstatslib.o \ +lua/ltexiolib.o \ +lua/ltexlib.o \ +lua/ltokenlib.o \ +lua/lfontlib.o \ +lua/texluac.o \ +lua/luainit.o \ +lua/luastuff.o \ +lua/luatex.o \ +lua/luatoken.o \ +lua/luanode.o \ +lua/llanglib.o \ +lua/limglib.o \ +lua/mp.o \ +lua/psout.o \ +lua/lmplib.o \ +lang/hnjalloc.o \ +lang/hyphen.o \ +lang/texlang.o \ +tex/linebreak.o \ +tex/postlinebreak.o \ +tex/texnodes.o \ +tex/textoken.o \ +tex/texpdf.o \ +managed-sa.o \ +mathcodes.o \ +textcodes.o \ +utils.o \ +writezip.o + +all: libpdf.a makecpool + +libpdf.a: lua/mp.c lua/psout.c $(OBJS) + rm -f $@ + $(AR) $(ARFLAGS) $@ $(OBJS) + $(RANLIB) $@ + +lua/mp.c: lua/mp.w + $(CTANGLE) $(srcdir)/lua/mp.w - lua/mp.c + +lua/psout.c: lua/psout.w + $(CTANGLE) $(srcdir)/lua/psout.w - lua/psout.c + +makecpool: makecpool.o + $(link_command) makecpool.o + +kpse_include ../make/clean.mk + +clean:: + rm -f libpdf.a ttf2afm pdftosrc + +depend: + rm -f $(OBJS) $(srcdir)/depend.mk + for a in $(OBJS); do \ + env XXCFLAGS="-MM -MT \$$@" XCFLAGS="-MM -MT \$$@" $(MAKE) -k $$a; \ + touch $$a; \ + grep -a -v "^$(CC)\|$(CXX)\|$(AR)\|make\|klibtool" $$a | \ + sed 's: [^ ]*/\.\./libs/[^ ]*::g' >> $(srcdir)/depend.mk; \ + done; \ + rm -f $(OBJS) + +kpse_include luatexdir/depend.mk diff --git a/Build/source/texk/web2c/luatexdir/NEWS b/Build/source/texk/web2c/luatexdir/NEWS new file mode 100644 index 00000000000..626b5c95a0b --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/NEWS @@ -0,0 +1,537 @@ +--------------------------------------------------------------- +pdfTeX 3.141592-1.40.0-beta-20060811 was released on 2006-08-11 +--------------------------------------------------------------- +- renamed primitives: + \primitive -> \pdfprimitive + \ifprimitive -> \ifpdfprimitive + \ifabsdim -> \ifpdfabsdim + \ifabsnum -> \ifpdfabsnum +- new version of \primitive/\ifprimitive (but see above) +- new dimen: \pdfpxdimen +- support for jbig2 files +- new library: obsdcompat, which has improved string functions and allows the + use of __attribute__ +- update libpng to 1.2.12 +- added JFIF detection patch to writejpg.c (was bug 548) +- bugfix: truetype OS/2 v3 fonts (594) +- bugfix: file with only \immediate\pdfobj stream results in garbage (505) +- bugfix: invalid pdf created if font name contains space (509) + +--------------------------------------------------------------- +pdfTeX 3.141592-1.40.0-beta-20060725 was released on 2006-07-25 +--------------------------------------------------------------- +- added patches by Christian Schenk forwarded by Hartmut +- added patch 421 (popen) from Taco +- added lots of (void) to writettf* and ttf2afm to silence the compiler +- removed some unused variables from tounicode.c +- add new code by Thanh (patch 580) +- added security patch for xpdf :-( +- added JFIF detection patch to writejpg.c (bug 548) + +--------------------------------------------------------------- +pdfTeX 3.141592-1.40.0-beta-20060213 was released on 2006-02-13 +--------------------------------------------------------------- +- pdftex.web has been improved a bit +- new patch: + - 473 \ifabsnum and \ifabsdim +- the manual has been updated a bit and is again included + +--------------------------------------------------------------- +pdfTeX 3.141592-1.40.0-beta-20060125 was released on 2006-01-25 +--------------------------------------------------------------- +- pdfTeX now includes pdfeTeX, i.e. there is no way to make a binary without + eTeX support. Also the sources of TeX, eTeX and pdfTeX have been merged into + one file pdftex.web +- most pdfTeX change files are gone; only one file (pdftex.ch) remains. +- improved patches: + - 393 Ensure newline before endstream + +--------------------------------------------------------------- +pdfTeX 3.141592-1.40.0-beta-20060117 was released on 2006-01-17 +--------------------------------------------------------------- +- pdfTeX is now pdfeTeX, i.e. there is no way to make a binary without eTeX + support. Also the sources of TeX, eTeX and pdfTeX have been merged into one + file pdfetex.web +- strip trailing zeros in fractions of reals written +- removed patch 467 \ifindef +- improved logging of objstreams + +---------------------------------------------------------------- +pdfTeX 3.141592-1.40.0-alpha-20060111 was released on 2006-01-11 +---------------------------------------------------------------- +- new patches: + - 466 \primitive and \ifprimitive + - 467 \ifinedef +- improved patches: + - 393 Ensure newline before endstream +- pdfTeX now sets /ModDate and /Trapped by default (the values can be + overridden with /pdfinfo) +- more fixes to remove warnings from -Wall + +---------------------------------------------------------------- +pdfTeX 3.141592-1.40.0-alpha-20060106 was released on 2006-01-06 +---------------------------------------------------------------- +- many small fixes to remove warnings from -Wall +- removed some unused variables +- really fix bug 444 +- add some GCC extensions and use *nprintf instead of *printf where possible +- fixed a unicode bug in ttf2afm + +---------------------------------------------------------------- +pdfTeX 3.141592-1.40.0-alpha-20051226 was released on 2005-12-26 +---------------------------------------------------------------- +- improved patches: + - 453 Object Streams for PDF-1.5 + - take PK resolution from "pk_dpi" parameter in texmf.cnf, if it has not + been set by the format file or by the user + - 432 Rules in a PDF qQ group +- some fixes for Thanhs patch +- some improvements from -Wall +- .indent.pro for indent + +---------------------------------------------------------------- +pdfTeX 3.141592-1.40.0-alpha-20051221 was released on 2005-12-21 +---------------------------------------------------------------- +- has a large patch from Thanh +- pdflastlink has been fixed +- remove generated pdf in case of fatal error + +---------------------------------------------------------------- +pdfTeX 3.141592-1.40.0-alpha-20051208 was released on 2005-12-08 +---------------------------------------------------------------- +- improved patches: + - 386 grow obj_tab and dest_names arrays dynamically + - 453 Object Streams for PDF-1.5 + - take PK resolution from "pk_dpi" parameter in texmf.cnf, if it has not + been set by the format file or by the user +- write out PDF statistics later to make them correct +- makefile target pdfetex-all.pdf for a huge file + +---------------------------------------------------------------- +pdfTeX 3.141592-1.40.0-alpha-20051205 was released on 2005-12-05 +---------------------------------------------------------------- +- has these patches: + - 386 grow obj_tab and dest_names arrays dynamically + - 416 new primitive pdflastlink + - 427 Character positioning patch + - 432 Rules in a PDF qQ group + - 434 Remove queued map item handling + - 438 \pdfsavepos in DVI mode + - 443 512 zeros in Type1 fonts not copied anymore + - 447 Don't write /Encoding for non-reencoded fonts + - 453 Object Streams for PDF-1.5 + - take PK resolution from "pk_dpi" parameter in texmf.cnf, if it has not + been set by the format file or by the user + +------------------------------------------------- +pdfTeX 3.141592-1.30.6 was released on 2006-02-16 +------------------------------------------------- +- bugfix: updated xpdf to 3.01pl2 + +------------------------------------------------- +pdfTeX 3.141592-1.30.5 was released on 2005-12-04 +------------------------------------------------- +- bugfix: \pdfximage prints the file name twice (bug 441) +- bugfix: buffer overflow with \pdfmatch (bug 444) +- bugfix: updated xpdf to 3.01pl1 + +------------------------------------------------- +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 generates a uniformly distributed random + integer value between 0 (inclusive) and (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 sets the random seed to a specific value. + - \pdfnoligatures\f disables ligatures for the loaded font \f. + - Escaping strings: + - \pdfescapestring{} escapes the string so that it can be used as + PDF string. + - \pdfescapename{} escapes the string so that it can be used as PDF + name. + - \pdfescapehex{} converts the string to uppercase hexadecimal + representation. + - \pdfunescapehex{} reverses the effect of \pdfescapehex + - \pdfcreationdate expands to the date string that pdfTeX uses in the info + dict as default. + - \pdffilemoddate{} expands to the modification date of in the + same format as \pdfcreationdate (PDF date format). + - \pdffilesize{} expands to the size of as string. + - \pdfmdfivesum{} or \pdfmdfivesum file {} calculates the md5 + sum (of a string or a file) and converts it to uppercase hexadecimal format + (same as \pdfescapehex). + - \pdffiledump [offset ] [length ] + Expands to a hex dump of the file given in , 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 , which expands to the number in the + corresponding form XObject name. + - \leftmarginkern and \rightmarginkern tell the + margin kern at the left and right side of the horizontal list stored in box + . + - \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 }] {}{} + 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 + 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: + "->" + The position "-1" with an empty string indicates that this entry is not + set. + - \pdfstrcmp{}{} compares two strings and returns the strings "0" if + equals , "-1" if is less than , "1" if is greater than + +- 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) + -> +- 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: + --> [count ] + See http://www.ntg.nl/pipermail/ntg-pdftex/2003-June/000165.html +- The syntax of \pdfobj has been extended: + \pdfobj (h, v, m) + --> reserveobjnum + | [useobjnum ] [] [stream []] + --> + | + 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 and 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 [] (h, v, m) + --> [] [] [] [] + --> 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 , 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$ +// vim: tw=79:ts=2:expandtab:autoindent diff --git a/Build/source/texk/web2c/luatexdir/README b/Build/source/texk/web2c/luatexdir/README new file mode 100644 index 00000000000..f1e142f1b25 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/README @@ -0,0 +1,87 @@ +pdfTeX +====== + +README for version 3.14159-1.40.0-beta-20060811 +=============================================== + +This directory contains the version 1.40.0-alpha-20060811 of pdfTeX, an +extended version of eTeX 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. + +pdfTeX is based on the original eTeX 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-2006 Han The Thanh, + +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, Ralf Utermann, 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$ +// vim: tw=75 diff --git a/Build/source/texk/web2c/luatexdir/avl.c b/Build/source/texk/web2c/luatexdir/avl.c new file mode 100644 index 00000000000..a25239e8d93 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/avl.c @@ -0,0 +1,893 @@ +/* Produced by texiweb from libavl.w. */ + +/* libavl - library for manipulation of binary trees. + Copyright (C) 1998-2002, 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 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 on the Internet, or + write to Ben Pfaff, Stanford University, Computer Science Dept., 353 + Serra Mall, Stanford CA 94305, USA. +*/ + +#include +#include +#include +#include +#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; +} + +/* Destroys |new| with |avl_destroy (new, destroy)|, + first setting right links of nodes in |stack| within |new| + to null pointers to avoid touching uninitialized data. */ +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 + +/* 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/luatexdir/avl.h b/Build/source/texk/web2c/luatexdir/avl.h new file mode 100644 index 00000000000..b9f9e3c01a9 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/avl.h @@ -0,0 +1,115 @@ +/* Produced by texiweb from libavl.w. */ + +/* libavl - library for manipulation of binary trees. + Copyright (C) 1998-2002, 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 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 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 + +/* 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 *); + +#endif /* avl.h */ diff --git a/Build/source/texk/web2c/luatexdir/avlstuff.c b/Build/source/texk/web2c/luatexdir/avlstuff.c new file mode 100644 index 00000000000..74fcf6b8eda --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/avlstuff.c @@ -0,0 +1,180 @@ +/* +Copyright (c) 2004-2005 Han The Thanh, + +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$ + +*/ + +#include "ptexlib.h" +#include +#include +#include "avl.h" + +static struct avl_table *PdfObjTree[pdf_objtype_max + 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 +}; + +/**********************************************************************/ +/* general AVL comparison functions */ + +int comp_int_entry(const void *pa, const void *pb, void *p) +{ + cmp_return(*(const int *) pa, *(const int *) pb); + return 0; +} + +int comp_string_entry(const void *pa, const void *pb, void *p) +{ + return strcmp((const char *) pa, (const char *) pb); +} + +/**********************************************************************/ +/* One AVL tree for each obj_type 0...pdfobjtypemax */ + + +typedef struct oentry_ { + integer int0; + integer objptr; +} oentry; + +/* AVL sort oentry 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 oentry *) pa)->int0; + b = ((const oentry *) pb)->int0; + if (a < 0 && b < 0) { /* string comparison */ + if (a <= 2097152 && b <= 2097152) { + a+=2097152; + b+=2097152; + as = str_start[-a]; + ae = str_start[-a + 1]; /* start of next string in pool */ + bs = str_start[-b]; + be = str_start[-b + 1]; + al = ae - as; + bl = be - bs; + if (al < bl) /* compare first by string length */ + return -1; + if (al > bl) + return 1; + for (; as < ae; as++, bs++) { + if (str_pool[as] < str_pool[bs]) + return -1; + if (str_pool[as] > str_pool[bs]) + return 1; + } + } else { + pdftex_fail("avlstuff.c: compare_items() for single characters: NI"); + } + } else { /* integer comparison */ + if (a < b) + return -1; + if (a > b) + return 1; + } + return 0; +} + +void avl_put_obj(integer objptr, integer t) +{ + static void **pp; + static oentry *oe; + + 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"); + } + oe = xtalloc(1, oentry); + oe->int0 = obj_tab[objptr].int0; + oe->objptr = objptr; /* allows to relocate objtab */ + pp = avl_probe(PdfObjTree[t], oe); + if (pp == NULL) + pdftex_fail("avlstuff.c: avl_probe() out of memory in insertion"); +} + + +/* replacement for linear search pascal function "find_obj()" */ + +integer avl_find_obj(integer t, integer i, integer byname) +{ + static oentry *p; + static oentry tmp; + + if (byname > 0) + tmp.int0 = -i; + else + tmp.int0 = i; + if (PdfObjTree[t] == NULL) + return 0; + p = (oentry *) avl_find(PdfObjTree[t], &tmp); + if (p == NULL) + return 0; + return p->objptr; +} + +/**********************************************************************/ + +struct avl_table *mf_tree = NULL; + +typedef struct { + char *tfm_name; + internalfontnumber fontnum; +} mf_entry; + +/**********************************************************************/ +/* cleaning up... */ + +static void destroy_oentry(void *pa, void *pb) +{ + oentry *p = (oentry *) pa; + xfree(p); +} + +void PdfObjTree_free() +{ + int i; + + for (i = 0; i <= pdf_objtype_max; i++) { + if (PdfObjTree[i] != NULL) + avl_destroy(PdfObjTree[i], destroy_oentry); + } +} + +/**********************************************************************/ diff --git a/Build/source/texk/web2c/luatexdir/avlstuff.h b/Build/source/texk/web2c/luatexdir/avlstuff.h new file mode 100644 index 00000000000..e5a4de894d2 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/avlstuff.h @@ -0,0 +1,29 @@ +/* +Copyright (c) 2004 Han The Thanh, + +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$ + +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/luatexdir/change-files.txt b/Build/source/texk/web2c/luatexdir/change-files.txt new file mode 100644 index 00000000000..c6a3387f41d --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/change-files.txt @@ -0,0 +1,35 @@ +How change files are applied for pdftex/pdfetex? + +============================= pdftex ============================= + +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: + 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/pdftex.ch: + + % 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) + +Output: + pdftex.ch (not pdftexdir/pdftex.ch): + additional & system-dependent changes diff --git a/Build/source/texk/web2c/luatexdir/depend.mk b/Build/source/texk/web2c/luatexdir/depend.mk new file mode 100644 index 00000000000..8d1bf394648 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/depend.mk @@ -0,0 +1,2874 @@ +avl.o: ../../../../src/texk/web2c/luatexdir/avl.c \ + ../../../../src/texk/web2c/luatexdir/avl.h +avlstuff.o: ../../../../src/texk/web2c/luatexdir/avlstuff.c \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h +font/mapfile.o: ../../../../src/texk/web2c/luatexdir/font/mapfile.c \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h \ + ../../../../src/texk/web2c/luatexdir/luatex-api.h \ + \ + \ + +font/pkin.o: ../../../../src/texk/web2c/luatexdir/font/pkin.c \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h +font/subfont.o: ../../../../src/texk/web2c/luatexdir/font/subfont.c \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h +font/tounicode.o: ../../../../src/texk/web2c/luatexdir/font/tounicode.c \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h +font/vfpacket.o: ../../../../src/texk/web2c/luatexdir/font/vfpacket.c \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h +font/writeenc.o: ../../../../src/texk/web2c/luatexdir/font/writeenc.c \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h +font/writefont.o: ../../../../src/texk/web2c/luatexdir/font/writefont.c \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h +font/writet1.o: ../../../../src/texk/web2c/luatexdir/font/writet1.c \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h \ + ../../../../src/texk/web2c/luatexdir/luatex-api.h \ + \ + \ + +font/writet3.o: ../../../../src/texk/web2c/luatexdir/font/writet3.c \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-glyph.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/magstep.h +font/writettf.o: ../../../../src/texk/web2c/luatexdir/font/writettf.c \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h \ + ../../../../src/texk/web2c/luatexdir/font/writettf.h \ + ../../../../src/texk/web2c/luatexdir/font/macnames.c +font/writetype0.o: \ + ../../../../src/texk/web2c/luatexdir/font/writetype0.c \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h \ + ../../../../src/texk/web2c/luatexdir/font/writettf.h \ + ../../../../src/texk/web2c/luatexdir/font/writecff.h +font/writetype2.o: \ + ../../../../src/texk/web2c/luatexdir/font/writetype2.c \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h \ + ../../../../src/texk/web2c/luatexdir/font/writettf.h \ + ../../../../src/texk/web2c/luatexdir/font/writecff.h \ + ../../../../src/texk/web2c/luatexdir/font/sfnt.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/font/tt_glyf.h +font/writecff.o: ../../../../src/texk/web2c/luatexdir/font/writecff.c \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h \ + ../../../../src/texk/web2c/luatexdir/font/writecff.h +font/tt_glyf.o: ../../../../src/texk/web2c/luatexdir/font/tt_glyf.c \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h \ + ../../../../src/texk/web2c/luatexdir/font/sfnt.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/font/tt_table.h \ + ../../../../src/texk/web2c/luatexdir/font/tt_glyf.h +font/tt_table.o: ../../../../src/texk/web2c/luatexdir/font/tt_table.c \ + ../../../../src/texk/web2c/luatexdir/font/sfnt.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/font/tt_table.h +font/sfnt.o: ../../../../src/texk/web2c/luatexdir/font/sfnt.c \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/font/sfnt.h +font/texfont.o: ../../../../src/texk/web2c/luatexdir/font/texfont.c \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h \ + ../../../../src/texk/web2c/luatexdir/luatex-api.h \ + \ + \ + +font/tfmofm.o: ../../../../src/texk/web2c/luatexdir/font/tfmofm.c \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h \ + ../../../../src/texk/web2c/luatexdir/luatex-api.h \ + \ + \ + +font/vfovf.o: ../../../../src/texk/web2c/luatexdir/font/vfovf.c \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h \ + ../../../../src/texk/web2c/luatexdir/luatex-api.h \ + \ + \ + +font/luafont.o: ../../../../src/texk/web2c/luatexdir/font/luafont.c \ + ../../../../src/texk/web2c/luatexdir/luatex-api.h \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h +font/dofont.o: ../../../../src/texk/web2c/luatexdir/font/dofont.c \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h \ + ../../../../src/texk/web2c/luatexdir/luatex-api.h \ + \ + \ + +image/epdf.o: ../../../../src/texk/web2c/luatexdir/image/epdf.c \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h +image/pdftoepdf.o: \ + ../../../../src/texk/web2c/luatexdir/image/pdftoepdf.cc \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/image/epdf.h \ + ../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../web2c/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../web2c/luatexdir/ptexmac.h \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + +image/writeimg.o: ../../../../src/texk/web2c/luatexdir/image/writeimg.c \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + +image/writejbig2.o: \ + ../../../../src/texk/web2c/luatexdir/image/writejbig2.c \ + ../../../../src/texk/web2c/luatexdir/image/writejbig2.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h +image/writejpg.o: ../../../../src/texk/web2c/luatexdir/image/writejpg.c \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h +image/writepng.o: ../../../../src/texk/web2c/luatexdir/image/writepng.c \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h +lua/loslibext.o: ../../../../src/texk/web2c/luatexdir/lua/loslibext.c \ + ../../../../src/texk/web2c/luatexdir/luatex-api.h \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h +lua/lcallbacklib.o: \ + ../../../../src/texk/web2c/luatexdir/lua/lcallbacklib.c \ + ../../../../src/texk/web2c/luatexdir/luatex-api.h \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h +lua/lkpselib.o: ../../../../src/texk/web2c/luatexdir/lua/lkpselib.c \ + ../../../../src/texk/web2c/luatexdir/luatex-api.h \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/expand.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-glyph.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/readable.h +lua/llualib.o: ../../../../src/texk/web2c/luatexdir/lua/llualib.c \ + ../../../../src/texk/web2c/luatexdir/luatex-api.h \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h +lua/lnodelib.o: ../../../../src/texk/web2c/luatexdir/lua/lnodelib.c \ + ../../../../src/texk/web2c/luatexdir/luatex-api.h \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h +lua/lpdflib.o: ../../../../src/texk/web2c/luatexdir/lua/lpdflib.c \ + ../../../../src/texk/web2c/luatexdir/luatex-api.h \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h +lua/lstatslib.o: ../../../../src/texk/web2c/luatexdir/lua/lstatslib.c \ + ../../../../src/texk/web2c/luatexdir/luatex-api.h \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h +lua/ltexiolib.o: ../../../../src/texk/web2c/luatexdir/lua/ltexiolib.c \ + ../../../../src/texk/web2c/luatexdir/luatex-api.h \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h +lua/ltexlib.o: ../../../../src/texk/web2c/luatexdir/lua/ltexlib.c \ + ../../../../src/texk/web2c/luatexdir/luatex-api.h \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h +lua/ltokenlib.o: ../../../../src/texk/web2c/luatexdir/lua/ltokenlib.c \ + ../../../../src/texk/web2c/luatexdir/luatex-api.h \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h +lua/lfontlib.o: ../../../../src/texk/web2c/luatexdir/lua/lfontlib.c \ + ../../../../src/texk/web2c/luatexdir/luatex-api.h \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h +lua/texluac.o: ../../../../src/texk/web2c/luatexdir/lua/texluac.c \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + +lua/luainit.o: ../../../../src/texk/web2c/luatexdir/lua/luainit.c \ + ../../../../src/texk/web2c/luatexdir/luatex-api.h \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h ../luatexdir/luatexextra.h +lua/luastuff.o: ../../../../src/texk/web2c/luatexdir/lua/luastuff.c \ + ../../../../src/texk/web2c/luatexdir/luatex-api.h \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h +lua/luatex.o: ../../../../src/texk/web2c/luatexdir/lua/luatex.c \ + ../../../../src/texk/web2c/luatexdir/luatex-api.h \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h \ + +lua/luatoken.o: ../../../../src/texk/web2c/luatexdir/lua/luatoken.c \ + ../../../../src/texk/web2c/luatexdir/luatex-api.h \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h \ + ../../../../src/texk/web2c/luatexdir/tokens.h +lua/luanode.o: ../../../../src/texk/web2c/luatexdir/lua/luanode.c \ + ../../../../src/texk/web2c/luatexdir/luatex-api.h \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h +lua/llanglib.o: ../../../../src/texk/web2c/luatexdir/lua/llanglib.c \ + ../../../../src/texk/web2c/luatexdir/luatex-api.h \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h +lua/limglib.o: ../../../../src/texk/web2c/luatexdir/lua/limglib.c \ + \ + \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h \ + ../../../../src/texk/web2c/luatexdir/lua/../image/image.h +lang/hnjalloc.o: ../../../../src/texk/web2c/luatexdir/lang/hnjalloc.c +lang/hyphen.o: ../../../../src/texk/web2c/luatexdir/lang/hyphen.c \ + ../../../../src/texk/web2c/luatexdir/lang/hnjalloc.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h +lang/texlang.o: ../../../../src/texk/web2c/luatexdir/lang/texlang.c \ + ../../../../src/texk/web2c/luatexdir/luatex-api.h \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h +tex/linebreak.o: ../../../../src/texk/web2c/luatexdir/tex/linebreak.c \ + ../../../../src/texk/web2c/luatexdir/luatex-api.h \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h +tex/postlinebreak.o: \ + ../../../../src/texk/web2c/luatexdir/tex/postlinebreak.c \ + ../../../../src/texk/web2c/luatexdir/luatex-api.h \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h +tex/texnodes.o: ../../../../src/texk/web2c/luatexdir/tex/texnodes.c \ + ../../../../src/texk/web2c/luatexdir/luatex-api.h \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h +tex/textoken.o: ../../../../src/texk/web2c/luatexdir/tex/textoken.c \ + ../../../../src/texk/web2c/luatexdir/luatex-api.h \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h \ + ../../../../src/texk/web2c/luatexdir/tokens.h +tex/texpdf.o: ../../../../src/texk/web2c/luatexdir/tex/texpdf.c \ + ../../../../src/texk/web2c/luatexdir/luatex-api.h \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h +managed-sa.o: ../../../../src/texk/web2c/luatexdir/managed-sa.c \ + ../../../../src/texk/web2c/luatexdir/luatex-api.h \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h \ + ../../../../src/texk/web2c/luatexdir/managed-sa.h +mathcodes.o: ../../../../src/texk/web2c/luatexdir/mathcodes.c \ + ../../../../src/texk/web2c/luatexdir/luatex-api.h \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h \ + ../../../../src/texk/web2c/luatexdir/managed-sa.h +textcodes.o: ../../../../src/texk/web2c/luatexdir/textcodes.c \ + ../../../../src/texk/web2c/luatexdir/luatex-api.h \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h \ + ../../../../src/texk/web2c/luatexdir/managed-sa.h +utils.o: ../../../../src/texk/web2c/luatexdir/utils.c \ + \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-stat.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + \ + \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h \ + ../../../../src/texk/web2c/luatexdir/svnversion.h \ + \ + +writezip.o: ../../../../src/texk/web2c/luatexdir/writezip.c \ + ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmp.h \ + ../../../../src/texk/web2c/luatexdir/../cpascal.h \ + ../../../../src/texk/web2c/luatexdir/../config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \ + ../../web2c/c-auto.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \ + ../../../../src/texk/web2c/luatexdir/../help.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \ + ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \ + ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \ + ../../../../src/texk/web2c/luatexdir/ptexmac.h \ + ../../../../src/texk/web2c/luatexdir/avlstuff.h \ + ../../../../src/texk/web2c/luatexdir/avl.h \ + ../../../../src/texk/web2c/luatexdir/image/image.h \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../../../src/texk/web2c/luatexdir/font/texfont.h \ + ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \ + ../../../../src/texk/web2c/luatexdir/hyphen.h \ + ../../../../src/texk/web2c/luatexdir/nodes.h \ + diff --git a/Build/source/texk/web2c/luatexdir/font/.indent.pro b/Build/source/texk/web2c/luatexdir/font/.indent.pro new file mode 100644 index 00000000000..e9e690f1ba8 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/font/.indent.pro @@ -0,0 +1,12 @@ +/* $Id$ */ +--k-and-r-style +--blank-lines-after-procedures +--line-length 80 +--procnames-start-lines +--no-space-after-function-call-names +--dont-break-procedure-type +--space-after-cast +/* this does not work in indent 2.2.6 :-( */ +--no-tabs +/* this is new in indent 2.2.9 */ +--preprocessor-indentation 2 diff --git a/Build/source/texk/web2c/luatexdir/font/dofont.c b/Build/source/texk/web2c/luatexdir/font/dofont.c new file mode 100644 index 00000000000..fbe44c29ba9 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/font/dofont.c @@ -0,0 +1,183 @@ +/* +Copyright (c) 1996-2006 Taco Hoekwater + +This file is part of LuaTeX. + +LuaTeX 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. + +LuaTeX 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 LuaTeX; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +$Id: dofont.c 1013 2008-02-14 00:09:02Z oneiros $ +*/ + +#include "ptexlib.h" + +#include "luatex-api.h" + +#define TIMERS 0 + +#if TIMERS +#include +#endif + + +/* a bit more interfacing is needed for proper error reporting */ + +static char * +font_error_message (pointer u, char *nom, scaled s) { + char *str = xmalloc(256); + char *c = makecstring(zget_cs_text(u)); + char *extra = "metric data not found or bad"; + if (s>=0 ) { + snprintf(str,255,"Font \\%s=%s at %gpt not loadable: %s", c, nom, (double)s/65536, extra); + } else if (s!=-1000) { + snprintf(str,255,"Font \\%s=%s scaled %d not loadable: %s", c, nom, (int)(-s), extra); + } else { + snprintf(str,255,"Font \\%s=%s not loadable: %s", c, nom, extra); + } + return str; +} + +static int +do_define_font (integer f, char *cnom, char *caire, scaled s, integer natural_dir) { + + boolean res; /* was the callback successful? */ + integer callback_id; + char *cnam; +#if TIMERS + struct timeval tva; + struct timeval tvb; + double tvdiff; +#endif + int r; + res = 0; + + callback_id=callback_defined(define_font_callback); + if (callback_id>0) { + if (caire == NULL || strlen(caire)==0) { + cnam = xstrdup(cnom); + } else { + cnam = xmalloc(strlen(cnom)+strlen(caire)+2); + sprintf(cnam,"%s/%s",caire,cnom); + } +#if TIMERS + gettimeofday(&tva,NULL); +#endif + callback_id = run_and_save_callback(callback_id,"Sdd->",cnam,s,f); +#if TIMERS + gettimeofday(&tvb,NULL); + tvdiff = tvb.tv_sec*1000000.0; + tvdiff += (double)tvb.tv_usec; + tvdiff -= (tva.tv_sec*1000000.0); + tvdiff -= (double)tva.tv_usec; + tvdiff /= 1000000; + fprintf(stdout,"\ncallback('define_font',%s,%i): %f seconds\n", cnam,f,tvdiff); +#endif + free(cnam); + if (callback_id>0) { /* success */ + luaL_checkstack(Luas[0],1,"out of stack space"); + lua_rawgeti(Luas[0],LUA_REGISTRYINDEX, callback_id); + if (lua_istable(Luas[0],-1)) { +#if TIMERS + gettimeofday(&tva,NULL); +#endif + res = font_from_lua(Luas[0],f); + destroy_saved_callback (callback_id); +#if TIMERS + gettimeofday(&tvb,NULL); + tvdiff = tvb.tv_sec*1000000.0; + tvdiff += (double)tvb.tv_usec; + tvdiff -= (tva.tv_sec*1000000.0); + tvdiff -= (double)tva.tv_usec; + tvdiff /= 1000000; + fprintf(stdout,"font_from_lua(%s,%i): %f seconds\n", font_name(f),f,tvdiff); +#endif + lua_pop(Luas[0],1); + } else if (lua_isnumber(Luas[0],-1)) { + r = lua_tonumber(Luas[0],-1); + destroy_saved_callback (callback_id); + delete_font(f); + lua_pop(Luas[0],1); + return r; + } else { + lua_pop(Luas[0],1); + delete_font(f); + return 0; + } + } + } else { + res = read_tfm_info(f,cnom,caire,s); + if (res) { + set_hyphen_char(f,get_default_hyphen_char()); + set_skew_char(f,get_default_skew_char()); + } + } + if (res) { + do_vf(f); + set_font_natural_dir(f,natural_dir); + return f; + } else { + delete_font(f); + return 0; + } + +} + +int +read_font_info(pointer u, strnumber nom, strnumber aire, scaled s, + integer natural_dir) { + integer f; + char *cnom, *caire = NULL; + char *msg; + cnom = xstrdup(makecstring(nom)); + if (aire != 0) + caire = xstrdup(makecstring(aire)); + + f = new_font(); + if ((f = do_define_font(f, cnom,caire,s,natural_dir))) { + if (caire != NULL) free(caire); + free(cnom); + return f; + } else { + char *help[] = {"I wasn't able to read the size data for this font,", + "so I will ignore the font specification.", + "[Wizards can fix TFM files using TFtoPL/PLtoTF.]", + "You might try inserting a different font spec;", + "e.g., type `I\font='.", + NULL } ; + if(!get_suppress_fontnotfound_error()) { + msg = font_error_message(u, cnom, s); + tex_error(msg,help); + free(msg); + } + if (caire != NULL) free(caire); + free(cnom); + return 0; + } +} + +/* TODO This function is a placeholder. There can easily appears holes in + the |font_tables| array, and we could attempt to reuse those +*/ + +int +find_font_id (char *nom, char *aire, scaled s) { + integer f; + f = new_font(); + if ((f = do_define_font(f, nom, aire,s,-1))) { + return f; + } else { + return 0; + } +} + diff --git a/Build/source/texk/web2c/luatexdir/font/luafont.c b/Build/source/texk/web2c/luatexdir/font/luafont.c new file mode 100644 index 00000000000..be32e39de9f --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/font/luafont.c @@ -0,0 +1,1733 @@ + +#include "luatex-api.h" +#include + +#include "nodes.h" + +#define noVERBOSE + +#define SAVE_REF 1 + +char *font_type_strings[] = {"unknown","virtual","real", NULL}; +char *font_format_strings[] = {"unknown","type1","type3","truetype", "opentype", NULL}; +char *font_embedding_strings[] = {"unknown","no","subset", "full", NULL}; +char *ligature_type_strings[] = {"=:", "=:|", "|=:", "|=:|", "", "=:|>", "|=:>", "|=:|>", "", "", "", "|=:|>>", NULL }; + +void +font_char_to_lua (lua_State *L, internalfontnumber f, charinfo *co) { + int i; + liginfo *l; + kerninfo *ki; + + lua_createtable(L,0,10); + + lua_pushstring(L,"width"); + lua_pushnumber(L,get_charinfo_width(co)); + lua_rawset(L,-3); + + lua_pushstring(L,"height"); + lua_pushnumber(L,get_charinfo_height(co)); + lua_rawset(L,-3); + + lua_pushstring(L,"depth"); + lua_pushnumber(L,get_charinfo_depth(co)); + lua_rawset(L,-3); + + lua_pushstring(L,"italic"); + lua_pushnumber(L,get_charinfo_italic(co)); + lua_rawset(L,-3); + + if (get_charinfo_ef(co)!=0) { + lua_pushstring(L,"expansion_factor"); + lua_pushnumber(L,get_charinfo_ef(co)); + lua_rawset(L,-3); + } + + if (get_charinfo_lp(co)!=0) { + lua_pushstring(L,"left_protruding"); + lua_pushnumber(L,get_charinfo_lp(co)); + lua_rawset(L,-3); + } + + if (get_charinfo_lp(co)!=0) { + lua_pushstring(L,"right_protruding"); + lua_pushnumber(L,get_charinfo_rp(co)); + lua_rawset(L,-3); + } + + + if (font_encodingbytes(f) == 2 ) { + lua_pushstring(L,"index"); + lua_pushnumber(L,get_charinfo_index(co)); + lua_rawset(L,-3); + } + + if (get_charinfo_name(co)!=NULL) { + lua_pushstring(L,"name"); + lua_pushstring(L,get_charinfo_name(co)); + lua_rawset(L,-3); + } + + if (get_charinfo_tounicode(co)!=NULL) { + lua_pushstring(L,"tounicode"); + lua_pushstring(L,get_charinfo_tounicode(co)); + lua_rawset(L,-3); + } + + if (get_charinfo_tag(co) == list_tag) { + lua_pushstring(L,"next"); + lua_pushnumber(L,get_charinfo_remainder(co)); + lua_rawset(L,-3); + } + + lua_pushstring(L,"used"); + lua_pushboolean(L,(get_charinfo_used(co) ? true : false)); + lua_rawset(L,-3); + + if (get_charinfo_tag(co) == ext_tag) { + lua_pushstring(L,"extensible"); + lua_createtable(L,0,4); + lua_pushnumber(L,get_charinfo_extensible(co,EXT_TOP)); + lua_setfield(L,-2,"top"); + lua_pushnumber(L,get_charinfo_extensible(co,EXT_BOT)); + lua_setfield(L,-2,"bot"); + lua_pushnumber(L,get_charinfo_extensible(co,EXT_MID)); + lua_setfield(L,-2,"mid"); + lua_pushnumber(L,get_charinfo_extensible(co,EXT_REP)); + lua_setfield(L,-2,"rep"); + lua_rawset(L,-3); + } + ki = get_charinfo_kerns(co); + if (ki != NULL) { + lua_pushstring(L,"kerns"); + lua_createtable(L,10,1); + for (i=0;!kern_end(ki[i]);i++) { + if (kern_char(ki[i]) == right_boundarychar) { + lua_pushstring(L,"right_boundary"); + } else { + lua_pushnumber(L,kern_char(ki[i])); + } + lua_pushnumber(L,kern_kern(ki[i])); + lua_rawset(L,-3); + } + lua_rawset(L,-3); + } + l = get_charinfo_ligatures(co); + if (l!=NULL) { + lua_pushstring(L,"ligatures"); + lua_createtable(L,10,1); + for (i=0;!lig_end(l[i]);i++) { + if (lig_char(l[i]) == right_boundarychar) { + lua_pushstring(L,"right_boundary"); + } else { + lua_pushnumber(L,lig_char(l[i])); + } + lua_createtable(L,0,2); + lua_pushstring(L,"type"); + lua_pushnumber(L,lig_type(l[i])); + lua_rawset(L,-3); + lua_pushstring(L,"char"); + lua_pushnumber(L,lig_replacement(l[i])); + lua_rawset(L,-3); + lua_rawset(L,-3); + } + lua_rawset(L,-3); + } +} + +static void +write_lua_parameters (lua_State *L, int f) { + int k; + lua_newtable(L); + for (k=1;k<=font_params(f);k++) { + lua_pushnumber(L,font_param(f,k)); + switch (k) { + case slant_code: lua_setfield(L,-2,"slant"); break; + case space_code: lua_setfield(L,-2,"space"); break; + case space_stretch_code: lua_setfield(L,-2,"space_stretch"); break; + case space_shrink_code: lua_setfield(L,-2,"space_shrink"); break; + case x_height_code: lua_setfield(L,-2,"x_height"); break; + case quad_code: lua_setfield(L,-2,"quad"); break; + case extra_space_code: lua_setfield(L,-2,"extra_space"); break; + default: + lua_rawseti(L,-2,k); + } + } + lua_setfield(L,-2,"parameters"); +} + + +int +font_to_lua (lua_State *L, int f) { + int k; + charinfo *co; + if (font_cache_id(f)) { + /* fetch the table from the registry if it was + saved there by font_from_lua() */ + lua_rawgeti(L,LUA_REGISTRYINDEX,font_cache_id(f)); + /* fontdimens can be changed from tex code */ + write_lua_parameters(L,f); + return 1; + } + + lua_newtable(L); + lua_pushstring(L,font_name(f)); + lua_setfield(L,-2,"name"); + if(font_area(f)!=NULL) { + lua_pushstring(L,font_area(f)); + lua_setfield(L,-2,"area"); + } + if(font_filename(f)!=NULL) { + lua_pushstring(L,font_filename(f)); + lua_setfield(L,-2,"filename"); + } + if(font_fullname(f)!=NULL) { + lua_pushstring(L,font_fullname(f)); + lua_setfield(L,-2,"fullname"); + } + if(font_encodingname(f)!=NULL) { + lua_pushstring(L,font_encodingname(f)); + lua_setfield(L,-2,"encodingname"); + } + + lua_pushboolean(L,(font_used(f) ? true : false)); + lua_setfield(L,-2,"used"); + + + lua_pushstring(L,font_type_strings[font_type(f)]); + lua_setfield(L,-2,"type"); + lua_pushstring(L,font_format_strings[font_format(f)]); + lua_setfield(L,-2,"format"); + lua_pushstring(L,font_embedding_strings[font_embedding(f)]); + lua_setfield(L,-2,"embedding"); + + lua_pushnumber(L,font_size(f)); + lua_setfield(L,-2,"size"); + lua_pushnumber(L,font_dsize(f)); + lua_setfield(L,-2,"designsize"); + lua_pushnumber(L,font_checksum(f)); + lua_setfield(L,-2,"checksum"); + lua_pushnumber(L,font_slant(f)); + lua_setfield(L,-2,"slant"); + lua_pushnumber(L,font_extend(f)); + lua_setfield(L,-2,"extend"); + lua_pushnumber(L,font_natural_dir(f)); + lua_setfield(L,-2,"direction"); + lua_pushnumber(L,font_encodingbytes(f)); + lua_setfield(L,-2,"encodingbytes"); + lua_pushnumber(L,font_tounicode(f)); + lua_setfield(L,-2,"tounicode"); + + /* pdf parameters */ + /* skip the first four for now, that are very much interal */ + /* + if (pdf_font_size(f) != 0) { + lua_pushnumber(L,pdf_font_size(f)); + lua_setfield(L,-2,"pdf_size"); + } + if (pdf_font_num(f) != 0) { + lua_pushnumber(L,pdf_font_num(f)); + lua_setfield(L,-2,"pdf_num"); + } + if (pdf_font_blink(f) != 0) { + lua_pushnumber(L,pdf_font_blink(f)); + lua_setfield(L,-2,"pdf_blink"); + } + if (pdf_font_elink(f) != 0) { + lua_pushnumber(L,pdf_font_elink(f)); + lua_setfield(L,-2,"pdf_elink"); + } + */ + /* the next one is read only */ + if (pdf_font_expand_ratio(f) != 0) { + lua_pushnumber(L,pdf_font_expand_ratio(f)); + lua_setfield(L,-2,"expand_ratio"); + } + if (pdf_font_shrink(f) != 0) { + lua_pushnumber(L,pdf_font_shrink(f)); + lua_setfield(L,-2,"shrink"); + } + if (pdf_font_stretch(f) != 0) { + lua_pushnumber(L,pdf_font_stretch(f)); + lua_setfield(L,-2,"stretch"); + } + if (pdf_font_step(f) != 0) { + lua_pushnumber(L,pdf_font_step(f)); + lua_setfield(L,-2,"step"); + } + if (pdf_font_auto_expand(f) != 0) { + lua_pushboolean(L,pdf_font_auto_expand(f)); + lua_setfield(L,-2,"auto_expand"); + } + if (pdf_font_attr(f) != 0) { + lua_pushstring(L,makecstring(pdf_font_attr(f))); + lua_setfield(L,-2,"attributes"); + } + + /* params */ + write_lua_parameters(L,f); + + /* chars */ + lua_createtable(L,font_tables[f]->charinfo_size,0); /* all characters */ + + if (has_left_boundary(f)) { + co = get_charinfo(f,left_boundarychar); + font_char_to_lua(L,f,co); + lua_setfield(L,-2,"left_boundary"); + } + if (has_right_boundary(f)) { + co = get_charinfo(f,right_boundarychar); + font_char_to_lua(L,f,co); + lua_setfield(L,-2,"right_boundary"); + } + + for (k=font_bc(f);k<=font_ec(f);k++) { + if (char_exists(f,k)) { + lua_pushnumber(L,k); + co = get_charinfo(f,k); + font_char_to_lua(L,f,co); + lua_rawset(L,-3); + } + } + lua_setfield(L,-2,"characters"); + return 1; +} + +static int +count_hash_items (lua_State *L, int name_index){ + int n = -1; + lua_rawgeti(L,LUA_REGISTRYINDEX,name_index); + lua_rawget(L,-2); + if (!lua_isnil(L,-1)) { + if (lua_istable(L,-1)) { + n = 0; + /* now find the number */ + lua_pushnil(L); /* first key */ + while (lua_next(L, -2) != 0) { + n++; + lua_pop(L,1); + } + } + } + lua_pop(L,1); + return n; +} + +#define streq(a,b) (strcmp(a,b)==0) + +#define append_packet(k) { cpackets[np++] = k; } + +#define do_store_four(l) { \ + append_packet((l&0xFF000000)>>24); \ + append_packet((l&0x00FF0000)>>16); \ + append_packet((l&0x0000FF00)>>8); \ + append_packet((l&0x000000FF)); } + +/* +*/ + +#define lua_roundnumber(a,b) (int)floor((double)lua_tonumber(L,-1)+0.5) + +static int +numeric_field (lua_State *L, char *name, int dflt) { + int i = dflt; + lua_pushstring(L,name); + lua_rawget(L,-2); + if (lua_isnumber(L,-1)) { + i = lua_roundnumber(L,-1); + } + lua_pop(L,1); + return i; +} + +static int +n_numeric_field (lua_State *L, int name_index, int dflt) { + register int i = dflt; + lua_rawgeti(L,LUA_REGISTRYINDEX, name_index); /* fetch the stringptr */ + lua_rawget(L,-2); + if (lua_type(L,-1)==LUA_TNUMBER) { + i = lua_roundnumber(L,-1); + } + lua_pop(L,1); + return i; +} + + +static int +enum_field (lua_State *L, char *name, int dflt, char **values) { + int k; + char *s; + int i = dflt; + lua_pushstring(L,name); + lua_rawget(L,-2); + if (lua_isnumber(L,-1)) { + i = lua_tonumber(L,-1); + } else if (lua_isstring(L,-1)) { + s = (char *)lua_tostring(L,-1); + k = 0; + while (values[k] != NULL) { + if (strcmp(values[k],s) == 0) { + i = k; + break; + } + k++; + } + } + lua_pop(L,1); + return i; +} + +static int +boolean_field (lua_State *L, char *name, int dflt) { + int i = dflt; + lua_pushstring(L,name); + lua_rawget(L,-2); + if (lua_isboolean(L,-1)) { + i = lua_toboolean(L,-1); + } + lua_pop(L,1); + return i; +} + +static int +n_boolean_field (lua_State *L, int name_index, int dflt) { + int i = dflt; + lua_rawgeti(L,LUA_REGISTRYINDEX, name_index); /* fetch the stringptr */ + lua_rawget(L,-2); + if (lua_isboolean(L,-1)) { + i = lua_toboolean(L,-1); + } + lua_pop(L,1); + return i; +} + + +static char * +string_field (lua_State *L, char *name, char *dflt) { + char *i; + lua_pushstring(L,name); + lua_rawget(L,-2); + if (lua_isstring(L,-1)) { + i = xstrdup(lua_tostring(L,-1)); + } else if (dflt==NULL) { + i = NULL; + } else { + i = xstrdup(dflt); + } + lua_pop(L,1); + return i; +} + +static char * +n_string_field (lua_State *L, int name_index, char *dflt) { + char *i; + lua_rawgeti(L,LUA_REGISTRYINDEX, name_index); /* fetch the stringptr */ + lua_rawget(L,-2); + if (lua_isstring(L,-1)) { + i = xstrdup(lua_tostring(L,-1)); + } else if (dflt==NULL) { + i = NULL; + } else { + i = xstrdup(dflt); + } + lua_pop(L,1); + return i; +} + +#define init_luaS_index(a) do { \ + lua_pushliteral(L,#a); \ + luaS_##a##_ptr = (char *)lua_tostring(L,-1); \ + luaS_##a##_index = luaL_ref (L,LUA_REGISTRYINDEX); \ + } while (0) + +#define make_luaS_index(a) \ + static int luaS_##a##_index = 0; \ + static char * luaS_##a##_ptr = NULL + +#define luaS_index(a) luaS_##a##_index + +#define luaS_ptr_eq(a,b) (a==luaS_##b##_ptr) + +make_luaS_index(width); +make_luaS_index(height); +make_luaS_index(depth); +make_luaS_index(italic); +make_luaS_index(index); +make_luaS_index(left_protruding); +make_luaS_index(right_protruding); +make_luaS_index(expansion_factor); +make_luaS_index(top); +make_luaS_index(bot); +make_luaS_index(rep); +make_luaS_index(mid); +make_luaS_index(next); +make_luaS_index(used); +make_luaS_index(name); +make_luaS_index(tounicode); +make_luaS_index(font); +make_luaS_index(char); +make_luaS_index(slot); +make_luaS_index(comment); +make_luaS_index(push); +make_luaS_index(pop); +make_luaS_index(rule); +make_luaS_index(right); +make_luaS_index(node); +make_luaS_index(down); +make_luaS_index(special); +make_luaS_index(slant); +make_luaS_index(space); +make_luaS_index(space_stretch); +make_luaS_index(space_shrink); +make_luaS_index(x_height); +make_luaS_index(quad); +make_luaS_index(extra_space); +make_luaS_index(left_boundary); +make_luaS_index(right_boundary); +make_luaS_index(kerns); +make_luaS_index(ligatures); +make_luaS_index(fonts); + +void init_font_string_pointers (lua_State *L) { + init_luaS_index(width); + init_luaS_index(height); + init_luaS_index(depth); + init_luaS_index(italic); + init_luaS_index(index); + init_luaS_index(left_protruding); + init_luaS_index(right_protruding); + init_luaS_index(expansion_factor); + init_luaS_index(top); + init_luaS_index(bot); + init_luaS_index(rep); + init_luaS_index(mid); + init_luaS_index(next); + init_luaS_index(used); + init_luaS_index(name); + init_luaS_index(tounicode); + init_luaS_index(font); + init_luaS_index(char); + init_luaS_index(slot); + init_luaS_index(comment); + init_luaS_index(push); + init_luaS_index(pop); + init_luaS_index(rule); + init_luaS_index(right); + init_luaS_index(node); + init_luaS_index(down); + init_luaS_index(special); + + init_luaS_index(slant); + init_luaS_index(space); + init_luaS_index(space_stretch); + init_luaS_index(space_shrink); + init_luaS_index(x_height); + init_luaS_index(quad); + init_luaS_index(extra_space); + + init_luaS_index(left_boundary); + init_luaS_index(right_boundary); + init_luaS_index(kerns); + init_luaS_index(ligatures); + init_luaS_index(fonts); +} + +static int +count_char_packet_bytes (lua_State *L) { + register int i; + register int l = 0; + int ff = 0; + for (i=1;i<=lua_objlen(L,-1);i++) { + lua_rawgeti(L,-1,i); + if (lua_istable(L,-1)) { + lua_rawgeti(L,-1,1); + if (lua_isstring(L,-1)) { + char *s = (char *)lua_tostring(L,-1); + if (luaS_ptr_eq(s,font)) { l+= 5; ff =1; } + else if (luaS_ptr_eq(s,char)) { if (ff==0) { l+=5; } l += 5; ff = 1; } + else if (luaS_ptr_eq(s,slot)) { l += 10; ff = 1;} + else if (luaS_ptr_eq(s,comment)) { ; } + else if (luaS_ptr_eq(s,push) || + luaS_ptr_eq(s,pop)) { l++; } + else if (luaS_ptr_eq(s,rule)) { l+=9; } + else if (luaS_ptr_eq(s,right) || + luaS_ptr_eq(s,node) || + luaS_ptr_eq(s,down)) { l+=5; } + else if (luaS_ptr_eq(s,special)) { + size_t len; + lua_rawgeti(L,-2,2); + (void)lua_tolstring(L,-1,&len); + lua_pop(L,1); + if (len>0) { l = l + 5 + len; } + } + else { fprintf(stdout,"unknown packet command %s!\n",s); } + } else { + fprintf(stdout,"no packet command!\n"); + } + lua_pop(L,1); /* command name */ + } + lua_pop(L,1); /* item */ + } + return l; +} + + + +scaled +sp_to_dvi (halfword sp, halfword atsize) { + double result, mult; + mult = (double)(atsize>>16); + result = (sp << 4); + return floor (result/mult ); +} + + +static void +read_char_packets (lua_State *L, integer *l_fonts, charinfo *co, int atsize) { + int i, n, m; + size_t l; + int cmd; + char *s; + real_eight_bits *cpackets; + int ff = 0; + int np = 0; + int max_f = 0; + int pc = count_char_packet_bytes (L); + if (pc<=0) + return; + assert(l_fonts != NULL); + assert(l_fonts[1] != 0); + while (l_fonts[(max_f+1)]!=0) + max_f++; + + cpackets = xmalloc(pc+1); + for (i=1;i<=lua_objlen(L,-1);i++) { + lua_rawgeti(L,-1,i); + if (lua_istable(L,-1)) { + /* fetch the command code */ + lua_rawgeti(L,-1,1); + if (lua_isstring(L,-1)) { + s = (char *)lua_tostring(L,-1); + cmd = 0; + if (luaS_ptr_eq(s,font)) { + cmd = packet_font_code; + } else if (luaS_ptr_eq(s,char)) { + cmd = packet_char_code; + if (ff==0) { + append_packet(packet_font_code); + ff = l_fonts[1]; + do_store_four(ff); + } + } else if (luaS_ptr_eq(s,slot)) { + cmd = packet_nop_code; + lua_rawgeti(L,-2,2); n = lua_tointeger(L,-1); + ff = (n>max_f ? l_fonts[1] : l_fonts[n]); + lua_rawgeti(L,-3,3); n = lua_tointeger(L,-1); + lua_pop(L,2); + append_packet(packet_font_code); + do_store_four(ff); + append_packet(packet_char_code); + do_store_four(n); + } + else if (luaS_ptr_eq(s,comment)) { cmd = packet_nop_code; } + else if (luaS_ptr_eq(s,node)) { cmd = packet_node_code; } + else if (luaS_ptr_eq(s,push)) { cmd = packet_push_code; } + else if (luaS_ptr_eq(s,pop)) { cmd = packet_pop_code; } + else if (luaS_ptr_eq(s,rule)) { cmd = packet_rule_code; } + else if (luaS_ptr_eq(s,right)) { cmd = packet_right_code; } + else if (luaS_ptr_eq(s,down)) { cmd = packet_down_code; } + else if (luaS_ptr_eq(s,special)) { cmd = packet_special_code; } + + switch(cmd) { + case packet_push_code: + case packet_pop_code: + append_packet(cmd); + break; + case packet_font_code: + append_packet(cmd); + lua_rawgeti(L,-2,2); + n = lua_tointeger(L,-1); + ff = (n>max_f ? l_fonts[1] : l_fonts[n]); + do_store_four(ff); + lua_pop(L,1); + break; + case packet_node_code: + append_packet(cmd); + lua_rawgeti(L,-2,2); + n = copy_node_list(nodelist_from_lua(L)); + do_store_four(n); + lua_pop(L,1); + break; + case packet_char_code: + append_packet(cmd); + lua_rawgeti(L,-2,2); + n = lua_tointeger(L,-1); + do_store_four(n); + lua_pop(L,1); + break; + case packet_right_code: + case packet_down_code: + append_packet(cmd); + lua_rawgeti(L,-2,2); + n = lua_tointeger(L,-1); + do_store_four(sp_to_dvi(n,atsize)); + lua_pop(L,1); + break; + case packet_rule_code: + append_packet(cmd); + lua_rawgeti(L,-2,2); + n = lua_tointeger(L,-1); + do_store_four(sp_to_dvi(n,atsize)); + lua_rawgeti(L,-3,3); + n = lua_tointeger(L,-1); + do_store_four(sp_to_dvi(n,atsize)); + lua_pop(L,2); + break; + case packet_special_code: + append_packet(cmd); + lua_rawgeti(L,-2,2); + s = (char *)lua_tolstring(L,-1,&l); + if (l>0) { + do_store_four(l); + m = (int)l; + while(m>0) { + n = *s++; + m--; + append_packet(n); + } + } + lua_pop(L,1); + break; + case packet_nop_code: + break; + default: + fprintf(stdout,"Unknown char packet code %s (char %d in font %s)\n",s,(int)c,font_name(f)); + } + } + lua_pop(L,1); /* command code */ + } else { + fprintf(stdout,"Found a `commands' item that is not a table (char %d in font %s)\n",(int)c,font_name(f)); + } + lua_pop(L,1); /* command table */ + } + append_packet(packet_end_code); + set_charinfo_packets(co,cpackets); + return; +} + + +static void +read_lua_cidinfo (lua_State *L, int f) { + int i; + char *s; + lua_getfield(L,-1,"cidinfo"); + if (lua_istable(L,-1)) { + i = numeric_field(L,"version",0); + set_font_cidversion(f,i); + i = numeric_field(L,"supplement",0); + set_font_cidsupplement(f,i); + s = string_field(L,"registry","Adobe"); /* Adobe-Identity-0 */ + set_font_cidregistry(f,s); + s = string_field(L,"ordering","Identity"); + set_font_cidordering(f,s); + } + lua_pop(L,1); +} + + +static void +read_lua_parameters (lua_State *L, int f) { + int i, n; + char *s; + lua_getfield(L,-1,"parameters"); + if (lua_istable(L,-1)) { + /* the number of parameters is the max(IntegerKeys(L)),7) */ + n = 7; + lua_pushnil(L); /* first key */ + while (lua_next(L, -2) != 0) { + if (lua_isnumber(L,-2)) { + i = lua_tonumber(L,-2); + if (i > n) n = i; + } + lua_pop(L,1); /* pop value */ + } + if (n>7) set_font_params(f,n); + /* sometimes it is handy to have all integer keys */ + for (i=1;i<=7;i++) { + lua_rawgeti(L,-1,i); + if (lua_isnumber(L,-1)) { + n = lua_roundnumber(L,-1); + set_font_param(f,i, n); + } + lua_pop(L,1); + } + lua_pushnil(L); /* first key */ + while (lua_next(L, -2) != 0) { + if (lua_isnumber(L,-2)) { + i = lua_tointeger(L,-2); + if (i>=8) { + n = (lua_isnumber(L,-1) ? lua_roundnumber(L,-1) : 0); + set_font_param(f,i, n); + } + } else if (lua_isstring(L,-2)) { + s = (char *)lua_tostring(L,-2); + n = (lua_isnumber(L,-1) ? lua_roundnumber(L,-1) : 0); + if (luaS_ptr_eq(s,slant)) { set_font_param(f,slant_code,n); } + else if (luaS_ptr_eq(s,space)) { set_font_param(f,space_code,n); } + else if (luaS_ptr_eq(s,space_stretch)) { set_font_param(f,space_stretch_code,n); } + else if (luaS_ptr_eq(s,space_shrink)) { set_font_param(f,space_shrink_code,n); } + else if (luaS_ptr_eq(s,x_height)) { set_font_param(f,x_height_code,n); } + else if (luaS_ptr_eq(s,quad)) { set_font_param(f,quad_code,n); } + else if (luaS_ptr_eq(s,extra_space)) { set_font_param(f,extra_space_code,n); } + } + lua_pop(L,1); + } + } + lua_pop(L,1); + +} + +void +font_char_from_lua (lua_State *L, internal_font_number f, integer i, integer *l_fonts) { + int k,r,t; + charinfo *co; + kerninfo *ckerns; + liginfo *cligs; + scaled j; + char *s; + int nl = 0; /* number of ligature table items */ + int nk = 0; /* number of kern table items */ + int ctr = 0; + int atsize = font_size(f); + if (lua_istable(L,-1)) { + co = get_charinfo(f,i); + set_charinfo_tag (co,0); + j = n_numeric_field(L,luaS_width_index,0); set_charinfo_width (co,j); + j = n_numeric_field(L,luaS_height_index,0); set_charinfo_height (co,j); + j = n_numeric_field(L,luaS_depth_index,0); set_charinfo_depth (co,j); + j = n_numeric_field(L,luaS_italic_index,0); set_charinfo_italic (co,j); + j = n_numeric_field(L,luaS_index_index,0); set_charinfo_index(co,j); + j = n_numeric_field(L,luaS_expansion_factor_index,0); set_charinfo_ef(co,j); + j = n_numeric_field(L,luaS_left_protruding_index,0); set_charinfo_lp(co,j); + j = n_numeric_field(L,luaS_right_protruding_index,0); set_charinfo_rp(co,j); + k = n_boolean_field(L,luaS_used_index,0); set_charinfo_used(co,k); + s = n_string_field (L,luaS_name_index,NULL); set_charinfo_name(co,s); + s = n_string_field (L,luaS_tounicode_index,NULL); set_charinfo_tounicode(co,s); + k = n_numeric_field(L,luaS_next_index,-1); + if (k>=0) { + set_charinfo_tag (co,list_tag); + set_charinfo_remainder (co,k); + } + lua_getfield(L,-1,"extensible"); + if (lua_istable(L,-1)){ + int top, bot,mid, rep; + top = n_numeric_field(L,luaS_top_index,0); + bot = n_numeric_field(L,luaS_bot_index,0); + mid = n_numeric_field(L,luaS_mid_index,0); + rep = n_numeric_field(L,luaS_rep_index,0); + if (top != 0 || bot != 0 || mid != 0 || rep != 0) { + set_charinfo_tag (co,ext_tag); + set_charinfo_extensible (co,top,bot,mid,rep); + } else { + pdftex_warn("lua-loaded font %s char [%d] has an invalid extensible field!",font_name(f),(int)i); + } + } + lua_pop(L,1); + + nk = count_hash_items(L,luaS_index(kerns)); + if (nk>0) { + ckerns = xcalloc((nk+1),sizeof(kerninfo)); + lua_rawgeti(L,LUA_REGISTRYINDEX,luaS_index(kerns)); + lua_rawget(L,-2); + if (lua_istable(L,-1)) { /* there are kerns */ + ctr = 0; + lua_pushnil(L); + while (lua_next(L, -2) != 0) { + k = non_boundarychar; + if (lua_isnumber(L,-2)) { + k = lua_tonumber(L,-2); /* adjacent char */ + if (k<0) + k = non_boundarychar; + } else if (lua_isstring(L,-2)) { + s = (char *)lua_tostring(L,-2); + if (luaS_ptr_eq(s,right_boundary)) { + k = right_boundarychar; + if (!has_right_boundary(f)) + set_right_boundary(f,get_charinfo(f,right_boundarychar)); + } + } + j = lua_roundnumber(L,-1); /* movement */ + if (k!=non_boundarychar) { + set_kern_item(ckerns[ctr],k,j); + ctr++; + } else { + pdftex_warn("lua-loaded font %s char [%d] has an invalid kern field!",font_name(f),(int)i); + } + lua_pop(L,1); + } + /* guard against empty tables */ + if (ctr>0) { + set_kern_item(ckerns[ctr],end_kern,0); + set_charinfo_kerns(co,ckerns); + } else { + pdftex_warn("lua-loaded font %s char [%d] has an invalid kerns field!",font_name(f),(int)i); + } + } + lua_pop(L,1); + } + + /* packet commands */ + lua_getfield(L,-1,"commands"); + if (lua_istable(L,-1)){ + lua_pushnil(L); /* first key */ + if (lua_next(L, -2) != 0) { + lua_pop(L,2); + read_char_packets(L,(integer *)l_fonts,co,atsize); + } + } + lua_pop(L,1); + + /* ligatures */ + nl = count_hash_items(L,luaS_index(ligatures)); + + if (nl>0) { + cligs = xcalloc((nl+1),sizeof(liginfo)); + lua_rawgeti(L,LUA_REGISTRYINDEX,luaS_index(ligatures)); + lua_rawget(L,-2); + if (lua_istable(L,-1)){/* do ligs */ + ctr = 0; + lua_pushnil(L); + while (lua_next(L, -2) != 0) { + k = non_boundarychar; + if (lua_isnumber(L,-2)) { + k = lua_tonumber(L,-2); /* adjacent char */ + if (k<0) { + k = non_boundarychar; + } + } else if (lua_isstring(L,-2)) { + s = (char *)lua_tostring(L,-2); + if (luaS_ptr_eq(s,right_boundary)) { + k = right_boundarychar; + if (!has_right_boundary(f)) + set_right_boundary(f,get_charinfo(f,right_boundarychar)); + } + } + r = -1; + if (lua_istable(L,-1)) { + r = n_numeric_field(L,luaS_char_index,-1); /* ligature */ + } + if (r != -1 && k != non_boundarychar) { + t = enum_field(L,"type",0,ligature_type_strings); + set_ligature_item(cligs[ctr],(t*2)+1,k,r); + ctr++; + } else { + pdftex_warn("lua-loaded font %s char [%d] has an invalid ligature field!",font_name(f),(int)i); + } + lua_pop(L,1); /* iterator value */ + } + /* guard against empty tables */ + if (ctr>0) { + set_ligature_item(cligs[ctr],0,end_ligature,0); + set_charinfo_ligatures(co,cligs); + } else { + pdftex_warn("lua-loaded font %s char [%d] has an invalid ligatures field!",font_name(f),(int)i); + } + } + lua_pop(L,1); /* ligatures table */ + } + } +} + + + +/* The caller has to fix the state of the lua stack when there is an error! */ + + +int +font_from_lua (lua_State *L, int f) { + int i,n,r,t; + int s_top; /* lua stack top */ + int bc; /* first char index */ + int ec; /* last char index */ + char *s; + integer *l_fonts = NULL; + /* the table is at stack index -1 */ + + if (luaS_width_index==0) + init_font_string_pointers(L); + + s = string_field(L,"area",""); set_font_area(f,s); + s = string_field(L,"filename",NULL); set_font_filename(f,s); + s = string_field(L,"encodingname",NULL); set_font_encodingname(f,s); + + s = string_field(L,"name",NULL); set_font_name(f,s); + s = string_field(L,"fullname",font_name(f)); set_font_fullname(f,s); + + if (s==NULL) { + pdftex_fail("lua-loaded font [%d] has no name!",f); + return false; + } + + i = numeric_field(L,"designsize",655360); set_font_dsize(f,i); + i = numeric_field(L,"size",font_dsize(f)); set_font_size(f,i); + i = numeric_field(L,"checksum",0); set_font_checksum(f,i); + i = numeric_field(L,"direction",0); set_font_natural_dir(f,i); + i = numeric_field(L,"encodingbytes",0); set_font_encodingbytes(f,i); + i = numeric_field(L,"tounicode",0); set_font_tounicode(f,i); + + i = numeric_field(L,"extend",0); + if (i<-2000) i = -2000; if (i>2000) i = 2000; if (i==1000) i = 0; + set_font_extend(f,i); + i = numeric_field(L,"slant",0); + if (i<-1000) i = -1000; if (i>1000) i = 1000; + set_font_slant(f,i); + + i = numeric_field(L,"hyphenchar",get_default_hyphen_char()); set_hyphen_char(f,i); + i = numeric_field(L,"skewchar",get_default_skew_char()); set_skew_char(f,i); + i = boolean_field(L,"used",0); set_font_used(f,i); + + s = string_field (L,"attributes",NULL); + if (s!=NULL && strlen(s)>0) { + i = maketexstring(s); + set_pdf_font_attr(f,i); + } + + i = enum_field(L,"type", unknown_font_type,font_type_strings); set_font_type(f,i); + i = enum_field(L,"format", unknown_format, font_format_strings); set_font_format(f,i); + i = enum_field(L,"embedding",unknown_embedding,font_embedding_strings); set_font_embedding(f,i); + if (font_encodingbytes(f)==0 && + (font_format(f)==opentype_format || font_format(f)==truetype_format)) { + set_font_encodingbytes(f,2); + } + + /* now fetch the base fonts, if needed */ + n = count_hash_items(L,luaS_index(fonts)); + if (n>0) { + l_fonts = xmalloc((n+2)*sizeof(integer)); + memset (l_fonts,0,(n+2)*sizeof(integer)); + lua_rawgeti(L,LUA_REGISTRYINDEX,luaS_index(fonts)); + lua_rawget(L,-2); + for (i=1;i<=n;i++) { + lua_rawgeti(L,-1,i); + if (lua_istable(L,-1)) { + lua_getfield(L,-1,"id"); + if (lua_isnumber(L,-1)) { + l_fonts[i] = lua_tonumber(L,-1); + lua_pop(L,2); /* pop id and entry */ + continue; + } + lua_pop(L,1); /* pop id */ + }; + s = NULL; + if (lua_istable(L,-1)) { + lua_getfield(L,-1,"name"); + if (lua_isstring(L,-1)) { + s = (char *)lua_tostring(L,-1); + } + lua_pop(L,1); /* pop name */ + } + if (s!= NULL) { + lua_getfield(L,-1,"size"); + t = (lua_isnumber(L,-1) ? lua_roundnumber(L,-1) : -1000); + lua_pop(L,1); + + /* TODO: the stack is messed up, otherwise this + * explicit resizing would not be needed + */ + s_top = lua_gettop(L); + l_fonts[i] = find_font_id(s,"",t); + lua_settop(L,s_top); + } else { + pdftex_fail("Invalid local font in font %s!\n", font_name(f)); + } + lua_pop(L,1); /* pop list entry */ + } + lua_pop(L,1); /* pop list entry */ + } else { + if(font_type(f) == virtual_font_type) { + pdftex_fail("Invalid local fonts in font %s!\n", font_name(f)); + } else { + l_fonts = xmalloc(3*sizeof(integer)); + l_fonts[0] = 0; + l_fonts[1] = f; + l_fonts[2] = 0; + } + } + + /* parameters */ + read_lua_parameters(L,f); + read_lua_cidinfo(L,f); + + /* characters */ + lua_getfield(L,-1,"characters"); + if (lua_istable(L,-1)) { + /* find the array size values */ + ec = 0; bc = -1; + lua_pushnil(L); /* first key */ + while (lua_next(L, -2) != 0) { + if (lua_isnumber(L,-2)) { + i = lua_tointeger(L,-2); + if (i>=0) { + if (lua_istable(L,-1)) { + if (i>ec) ec = i; + if (bc<0) bc = i; + if (bc>=0 && i=0) { + font_char_from_lua(L,f, i, l_fonts); + } + } else if (lua_isstring(L,-2)) { + s = (char *)lua_tostring(L,-2); + if (luaS_ptr_eq(s,left_boundary)) { + font_char_from_lua(L,f, left_boundarychar, l_fonts); + } else if (luaS_ptr_eq(s,right_boundary)) { + font_char_from_lua(L,f, right_boundarychar, l_fonts); + } + } + lua_pop(L, 1); + } + lua_pop(L, 1); + + /* handle font expansion last: the |copy_font| routine is called eventually, + and that needs to know |bc| and |ec|. */ + if (font_type(f)!=virtual_font_type) { + int fstep = numeric_field(L,"step",0); + if (fstep<0) fstep = 0; + if (fstep>100) fstep = 100; + if (fstep!=0) { + int fshrink = numeric_field(L,"shrink",0); + int fstretch = numeric_field(L,"stretch",0); + int fexpand = boolean_field(L,"auto_expand",0); + if (fshrink<0) fshrink = 0; + if (fshrink>500) fshrink = 500; + fshrink -= (fshrink % fstep); + if (fshrink<0) fshrink = 0; + if (fstretch<0) fstretch = 0; + if (fstretch>1000) fstretch = 1000; + fstretch -= (fstretch % fstep); + if (fstretch<0) fstretch = 0; + set_expand_params(f, fexpand, fstretch, fshrink, fstep, 0); + } + } + + } else { /* jikes, no characters */ + pdftex_warn("lua-loaded font [%d] (%s) has no characters!",f, font_name(f)); + } + +#if SAVE_REF + r = luaL_ref(Luas[0],LUA_REGISTRYINDEX); /* pops the table */ + set_font_cache_id(f,r); +#else + lua_pop(Luas[0],1); +#endif + } else { /* jikes, no characters */ + pdftex_warn("lua-loaded font [%d] (%s) has no character table!",f, font_name(f)); + } + + if (l_fonts!=NULL) + free(l_fonts); + return true; +} + +/* ==================================================================== + * + * L I G A T U R I N G + * + * ==================================================================== */ + + +#define assert_disc(a) \ + assert(pre_break(a)!=null); /* expect head_node */ \ + assert(type(pre_break(a))==nesting_node); \ + assert((vlink_pre_break(a)==null && tlink_pre_break(a)==null) || tail_of_list(vlink_pre_break(a))==tlink_pre_break(a)); \ + assert(post_break(a)!=null); /* expect head_node */ \ + assert(type(post_break(a))==nesting_node); \ + assert((vlink_post_break(a)==null && tlink_post_break(a)==null) || tail_of_list(vlink_post_break(a))==tlink_post_break(a)); \ + assert(no_break(a)!=null); /* expect head_node */ \ + assert(type(no_break(a))==nesting_node); \ + assert((vlink_no_break(a)==null && tlink_no_break(a)==null) || tail_of_list(vlink_no_break(a))==tlink_no_break(a)); + +static void +nesting_append (halfword nest, halfword newn) { + halfword tail = tlink(nest); + assert(alink(nest)==null); + assert(vlink(newn)==null); + assert(alink(newn)==null); + if (tail==null) { + assert(vlink(nest)==null); + couple_nodes(nest,newn); + } else { + assert(vlink(tail)==null); + assert(tail_of_list(vlink(nest))==tail); + couple_nodes(tail,newn); + } + tlink(nest) = newn; +} + + +static void +nesting_prepend (halfword nest, halfword newn) { + halfword head = vlink(nest); + assert(alink(nest)==null); + assert(vlink(newn)==null); + assert(alink(newn)==null); + couple_nodes(nest,newn); + if (head==null) { + assert(tlink(nest)==null); + tlink(nest) = newn; + } else { + assert(alink(head)==nest); + assert(tail_of_list(head)==tlink(nest)); + couple_nodes(newn,head); + } +} + + +static int +test_ligature( liginfo *lig, halfword left, halfword right ) { + if (type(left)!=glyph_node) + return 0; + assert(type(right)==glyph_node); + if (font(left)!=font(right)) return 0; + if (is_ghost(left) || is_ghost(right)) return 0; + *lig = get_ligature(font(left),character(left),character(right)); + if (is_valid_ligature(*lig)) { + return 1; + } + return 0; +} + + +static int +try_ligature(halfword *frst, halfword fwd) { + halfword cur = *frst; + liginfo lig; + if (test_ligature(&lig,cur,fwd)) { + int move_after = (lig_type(lig) & 0x0C)>>2; + int keep_right = ((lig_type(lig) & 0x01) != 0); + int keep_left = ((lig_type(lig) & 0x02) != 0); + halfword newgl = raw_glyph_node(); + font(newgl) = font(cur); + character(newgl) = lig_replacement(lig); + set_is_ligature(newgl); + + /* below might not be correct in contrived border case. + * but we use it only for debugging, so ... */ + if (character(cur)<0) { + set_is_leftboundary(newgl); + } + if (character(fwd)<0) { + set_is_rightboundary(newgl); + } + if (character(cur)<0) { + if (character(fwd)<0) { + build_attribute_list(newgl); + } else { + add_node_attr_ref(node_attr(fwd)); + node_attr(newgl) = node_attr(fwd); + } + } else { + add_node_attr_ref(node_attr(cur)); + node_attr(newgl) = node_attr(cur); + } + + /* TODO/FIXME if this ligature is consists of another ligature + * we should add it's lig_ptr to the new glyphs lig_ptr (and + * cleanup the no longer needed node) LOW PRIORITY */ + /* left side */ + if (keep_left) { + halfword new_first = copy_node(cur); + lig_ptr(newgl) = new_first; + couple_nodes(cur,newgl); + if (move_after) { + move_after--; + cur = newgl; + } + } else { + halfword prev = alink(cur); + uncouple_node(cur); + lig_ptr(newgl) = cur; + assert(prev!=null); + couple_nodes(prev,newgl); + cur = newgl; /* as cur has disappeared */ + } + /* right side */ + if (keep_right) { + halfword new_second = copy_node(fwd); + /* correct, because we _know_ lig_ptr points to _one_ node */ + couple_nodes(lig_ptr(newgl),new_second); + couple_nodes(newgl,fwd); + if (move_after) { + move_after--; + cur = fwd; + } + } else { + halfword next = vlink(fwd); + uncouple_node(fwd); + /* correct, because we _know_ lig_ptr points to _one_ node */ + couple_nodes(lig_ptr(newgl),fwd); + if (next!=null) {couple_nodes(newgl,next);} + } + + /* check and return */ + /* assert(move_after==0);*/ + *frst = cur; + return 1; + } + return 0; +} + + +/* there shouldn't be any ligatures here - we only add them at the end of + * xxx_break in a DISC-1 - DISC-2 situation and we stop processing DISC-1 + * (we continue with DISC-1's post_ and no_break */ +static halfword +handle_lig_nest(halfword root, halfword cur) { + if (cur==null) return root; + while (vlink(cur)!=null) { + halfword fwd = vlink(cur); + if (type(cur)==glyph_node && type(fwd)==glyph_node && + font(cur)==font(fwd) && try_ligature(&cur,fwd)) continue; + cur = vlink(cur); + assert(vlink(alink(cur))==cur); + } + tlink(root) = cur; + return root; +} + + +static halfword +handle_lig_word(halfword cur) { + halfword right=null; + + if (type(cur)==whatsit_node && subtype(cur)==cancel_boundary_node) { + halfword prev= alink(cur); + halfword fwd = vlink(cur); +/* uncouple_node(cur); */ /* not needed, it is freed */ + flush_node(cur); + if (fwd==null) { + vlink(prev) = fwd; + return prev; + } + couple_nodes(prev,fwd); + if (type(fwd)!=glyph_node) return prev; + cur = fwd; + } else if (has_left_boundary(font(cur))) { + halfword prev= alink(cur); + halfword p = new_glyph(font(cur),left_boundarychar); + couple_nodes(prev,p); + couple_nodes(p,cur); + cur = p; + } + if (has_right_boundary(font(cur))) { + right = new_glyph(font(cur),right_boundarychar); + } + + while (1) { + /* A glyph followed by ... */ + if (type(cur)==glyph_node) { + halfword fwd = vlink(cur); + if (fwd==null) { /* last character of paragraph */ + if (right==null) break; + couple_nodes(cur,right); + right = null; + continue; + } + assert(alink(fwd)==cur); + if (type(fwd)==glyph_node) { /* GLYPH - GLYPH */ + if (font(cur)!=font(fwd)) break; + if (try_ligature(&cur,fwd)) continue; + } else if (type(fwd)==disc_node) { /* GLYPH - DISC */ + + /* if a{bx}{}{y} and a+b=>B convert to {Bx}{}{ay} */ + halfword pre = vlink_pre_break(fwd); + halfword nob = vlink_no_break(fwd); + liginfo lig; + assert_disc(fwd); + /* Check on: a{b?}{?}{?} and a+b=>B : {B?}{?}{a?}*/ + /* Check on: a{?}{?}{b?} and a+b=>B : {a?}{?}{B?} */ + if ( (pre!=null && type(pre)==glyph_node && test_ligature(&lig,cur,pre)) + || (nob!=null && type(nob)==glyph_node && test_ligature(&lig,cur,nob))) { + /* move cur from before disc, to skipped part */ + halfword prev = alink(cur); + assert(vlink(prev)==cur); + uncouple_node(cur); + couple_nodes(prev,fwd); + nesting_prepend(no_break(fwd),cur); + /* now ligature the pre_break */ + nesting_prepend(pre_break(fwd),copy_node(cur)); + /* As we have removed cur, we need to start again ... */ + cur = prev; + } + /* Check on: a{?}{?}{}b and a+b=>B : {a?}{?b}{B}*/ + halfword next = vlink(fwd); + if (nob==null && next != null && type(next)==glyph_node + && test_ligature(&lig,cur,next)) { + /* move cur from before disc to no_break part */ + halfword prev = alink(cur); + assert(alink(next)==fwd); + assert(vlink(prev)==cur); + uncouple_node(cur); + couple_nodes(prev,fwd); + couple_nodes(no_break(fwd),cur); /* we _know_ it's empty */ + /* now copy cur the pre_break */ + nesting_prepend(pre_break(fwd),copy_node(cur)); + /* move next from after disc to no_break part */ + halfword tail = vlink(next); + uncouple_node(next); + try_couple_nodes(fwd,tail); + couple_nodes(cur,next); /* we _know_ this works */ + tlink(no_break(fwd)) = next; /* and make sure the list is correct */ + /* now copy next to the post_break */ + nesting_append(post_break(fwd),copy_node(next)); + /* As we have removed cur, we need to start again ... */ + cur = prev; + } + /* we are finished with the pre_break */ + handle_lig_nest(pre_break(fwd),vlink_pre_break(fwd)); + } else if (type(fwd)==whatsit_node && subtype(fwd)==cancel_boundary_node) { + halfword next = vlink(fwd); + try_couple_nodes(cur,next); + flush_node(fwd); + if (right!=null) { + flush_node(right); /* Shame, didn't need it */ + /* right = null; */ /* no need, we're going to leave the loop anyway */ + } + break; + } else { /* fwd is something unknown */ + if (right==null) break; + couple_nodes(cur,right); + couple_nodes(right,fwd); + right = null; + continue; + } + /* A discretionary followed by ... */ + } else if (type(cur)==disc_node) { + assert_disc(cur); + /* If {?}{x}{?} or {?}{?}{y} then ... */ + if (vlink_no_break(cur)!=null || vlink_post_break(cur)!=null) { + halfword fwd; + halfword lists[511]; /* max 8 levels */ + + int i, max_depth=0; + lists[max_depth++] = handle_lig_nest(post_break(cur),vlink_post_break(cur)); + lists[max_depth++] = handle_lig_nest(no_break(cur),vlink_no_break(cur)); + while (1) { + if ((fwd = vlink(cur))==null) return cur; + if ( type(fwd)==glyph_node) { + for (i=0; i0) { + tail = run_lua_ligkern_callback(head,tail,callback_id); + if (tail==null) tail = tail_of_list(head); + } else { + tail = handle_ligaturing(head,tail); + } + + callback_id = callback_defined(kerning_callback); + if (callback_id>0) { + tail = run_lua_ligkern_callback(head,tail,callback_id); + if (tail==null) tail = tail_of_list(head); + } else { + halfword nest = new_node(nesting_node,1); + halfword cur = vlink(head); + halfword aft = vlink(tail); + couple_nodes(nest,cur); + tlink(nest)=tail; + vlink(tail)=null; + do_handle_kerning(nest,null,null); + couple_nodes(head,vlink(nest)); + tail = tlink(nest); + try_couple_nodes(tail,aft); + flush_node(nest); + } + return tail; +} + diff --git a/Build/source/texk/web2c/luatexdir/font/macnames.c b/Build/source/texk/web2c/luatexdir/font/macnames.c new file mode 100644 index 00000000000..941f087ef56 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/font/macnames.c @@ -0,0 +1,312 @@ +/* +Copyright (c) 1996-2002 Han The Thanh, + +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: macnames.c 1013 2008-02-14 00:09:02Z oneiros $ +*/ + +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/luatexdir/font/mapfile.c b/Build/source/texk/web2c/luatexdir/font/mapfile.c new file mode 100644 index 00000000000..1c444e5c1d4 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/font/mapfile.c @@ -0,0 +1,967 @@ +/* +Copyright (c) 1996-2006 Han The Thanh, + +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: mapfile.c 1013 2008-02-14 00:09:02Z oneiros $ + +*/ + +#include +#include "ptexlib.h" +#include +#include +#include +#include "luatex-api.h" + +#define FM_BUF_SIZE 1024 + +static FILE *fm_file; + +static unsigned char *fm_buffer = NULL; +static integer fm_size = 0; +static integer fm_curbyte = 0; + +#define fm_open() \ + open_input (&fm_file, kpse_fontmap_format, FOPEN_RBIN_MODE) +#define fm_read_file() \ + readbinfile(fm_file,&fm_buffer,&fm_size) +#define fm_close() xfclose(fm_file, cur_file_name) +#define fm_getchar() fm_buffer[fm_curbyte++] +#define fm_eof() (fm_curbyte>=fm_size) + +typedef enum { FM_DUPIGNORE, FM_REPLACE, FM_DELETE } updatemode; +typedef enum { MAPFILE, MAPLINE } maptype; + +typedef struct mitem { + updatemode mode; /* FM_DUPIGNORE or FM_REPLACE or FM_DELETE */ + maptype type; /* map file or map line */ + char *line; /* pointer to map file name or map line */ + int lineno; /* line number in map file */ +} mapitem; +mapitem *mitem = NULL; + +static const char nontfm[] = ""; + +#define read_field(r, q, buf) do { \ + q = buf; \ + while (*r != ' ' && *r != '<' && *r != '"' && *r != '\0') \ + *q++ = *r++; \ + *q = '\0'; \ + skip (r, ' '); \ +} while (0) + +#define set_field(F) do { \ + if (q > buf) \ + fm->F = xstrdup(buf); \ + if (*r == '\0') \ + goto done; \ +} while (0) + +fm_entry *new_fm_entry(void) +{ + fm_entry *fm; + fm = xtalloc(1, fm_entry); + fm->tfm_name = NULL; + fm->sfd_name = NULL; + fm->ps_name = NULL; + fm->fd_flags = 4; + fm->ff_name = NULL; + fm->encname = NULL; + fm->type = 0; + fm->slant = 0; + fm->extend = 0; + fm->links = 0; + fm->pid = -1; + fm->eid = -1; + fm->subfont = NULL; + fm->in_use = false; + return fm; +} + +void delete_fm_entry(fm_entry * fm) +{ + xfree(fm->tfm_name); + xfree(fm->sfd_name); + xfree(fm->ps_name); + xfree(fm->ff_name); + 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; +} + +/**********************************************************************/ + +struct avl_table *tfm_tree = NULL; +struct avl_table *ps_tree = NULL; +struct avl_table *ff_tree = NULL; +struct avl_table *encname_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); +} + +/* 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) +{ + int i; + const fm_entry *p1 = (const fm_entry *) pa, *p2 = (const fm_entry *) pb; + assert(p1->ps_name != NULL && p2->ps_name != NULL); + if ((i = strcmp(p1->ps_name, p2->ps_name))) + return i; + cmp_return(p1->slant, p2->slant); + cmp_return(p1->extend, p2->extend); + 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 () +{ + assert(tfm_tree == NULL); + tfm_tree = avl_create(comp_fm_entry_tfm, NULL, &avl_xallocator); + assert(tfm_tree != NULL); + assert(ps_tree == NULL); + ps_tree = avl_create(comp_fm_entry_ps, NULL, &avl_xallocator); + assert(ps_tree != NULL); + assert(ff_tree == NULL); + ff_tree = avl_create(comp_ff_entry, NULL, &avl_xallocator); + assert(ff_tree != NULL); + assert(encname_tree == NULL); + encname_tree = avl_create(comp_string_entry, NULL, &avl_xallocator); + assert(encname_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. +*/ + +int avl_do_entry(fm_entry * fm, int mode) +{ + fm_entry *p; + void *a; + void **aa; + + /* handle tfm_name link */ + + if (strcmp(fm->tfm_name, nontfm)) { + p = (fm_entry *) avl_find(tfm_tree, fm); + if (p != NULL) { + switch (mode) { + case FM_DUPIGNORE: + pdftex_warn + ("fontmap entry for `%s' already exists, duplicates ignored", + fm->tfm_name); + goto exit; + break; + case FM_REPLACE: + case FM_DELETE: + if (p->in_use) { + pdftex_warn + ("fontmap entry for `%s' has been used, replace/delete not allowed", + fm->tfm_name); + goto exit; + } + a = avl_delete(tfm_tree, p); + assert(a != NULL); + unset_tfmlink(p); + if (!has_pslink(p)) + delete_fm_entry(p); + break; + default: + assert(0); + } + } + if (mode != FM_DELETE) { + aa = avl_probe(tfm_tree, fm); + assert(aa != NULL); + set_tfmlink(fm); + } + } + + /* handle ps_name link */ + + if (fm->ps_name != NULL) { + p = (fm_entry *) avl_find(ps_tree, fm); + if (p != NULL) { + switch (mode) { + case FM_DUPIGNORE: + goto exit; + break; + case FM_REPLACE: + case FM_DELETE: + if (p->in_use) + goto exit; + a = avl_delete(ps_tree, p); + assert(a != NULL); + unset_pslink(p); + if (!has_tfmlink(p)) + delete_fm_entry(p); + break; + default: + assert(0); + } + } + if (mode != FM_DELETE && is_t1fontfile(fm) && is_included(fm)) { + aa = avl_probe(ps_tree, fm); + assert(aa != NULL); + set_pslink(fm); + } + } + exit: + if (!has_tfmlink(fm) && !has_pslink(fm)) /* e. g. after FM_DELETE */ + return 1; /* deallocation of fm_entry structure required */ + else + return 0; +} + +/* add the encoding name to an AVL tree. this has nothing to do with writeenc.c */ + +char *add_encname(char *s) +{ + char *p; + void **aa; + assert(s != NULL); + assert(encname_tree != NULL); + if ((p = (char *) avl_find(encname_tree, s)) == NULL) { /* encoding name not yet registered */ + p = xstrdup(s); + aa = avl_probe(encname_tree, p); + assert(aa != NULL); + } + return p; +} + +/**********************************************************************/ +/* consistency check for map entry, with warn flag */ + +int check_fm_entry(fm_entry * fm, boolean warn) +{ + int a = 0; + assert(fm != NULL); + + if (is_fontfile(fm) && !is_included(fm)) { + if (warn) + pdftex_warn + ("ambiguous entry for `%s': font file present but not included, " + "will be treated as font file not present", fm->tfm_name); + xfree(fm->ff_name); + /* do not set variable |a| as this entry will be still accepted */ + } + + /* if both ps_name and font file are missing, drop this entry */ + if (fm->ps_name == NULL && !is_fontfile(fm)) { + if (warn) + pdftex_warn + ("invalid entry for `%s': both ps_name and font file missing", + fm->tfm_name); + a += 1; + } + + /* TrueType fonts cannot be reencoded without subsetting */ + 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 += 2; + } + + /* SlantFont and ExtendFont can be used only with Type1 fonts */ + if ((fm->slant != 0 || fm->extend != 0) + && !(is_t1fontfile(fm) && is_included(fm))) { + if (warn) + pdftex_warn + ("invalid entry for `%s': SlantFont/ExtendFont can be used only with embedded Type1 fonts", + fm->tfm_name); + a += 4; + } + + /* the value of SlantFont and ExtendFont must be reasonable */ + 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 += 8; + } + 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 += 16; + } + + /* subfonts must be used with subsetted non-reencoded TrueType fonts */ + if (fm->pid != -1 && + !(is_truetype(fm) && is_subsetted(fm) && !is_reencoded(fm))) { + if (warn) + pdftex_warn + ("invalid entry for `%s': PidEid can be used only with subsetted non-reencoded TrueType fonts", + fm->tfm_name); + a += 32; + } + + return a; +} + +/**********************************************************************/ +/* returns true if s is one of the 14 std. font names; speed-trimmed. */ + +boolean check_std_t1font(char *s) +{ + static const char *std_t1font_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 + }; + const size_t n = strlen(s); + int 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(std_t1font_names[k], s)) + return true; + return false; +}; + +/**********************************************************************/ + +static void fm_scan_line() +{ + int a, b, c, j, u = 0, v = 0; + float d; + fm_entry *fm; + char fm_line[FM_BUF_SIZE], buf[FM_BUF_SIZE]; + char *p, *q, *r, *s; + switch (mitem->type) { + case MAPFILE: + p = fm_line; + do { + c = fm_getchar(); + append_char_to_buf(c, p, fm_line, FM_BUF_SIZE); + } + while (c != 10 && !fm_eof()); + *(--p) = '\0'; + r = fm_line; + break; + case MAPLINE: + r = mitem->line; /* work on string from makecstring() */ + break; + default: + assert(0); + } + if (*r == '\0' || is_cfg_comment(*r)) + return; + fm = new_fm_entry(); + read_field(r, q, buf); + set_field(tfm_name); + if (!isdigit(*r)) { /* 2nd field ps_name may not start with a digit */ + read_field(r, q, buf); + set_field(ps_name); + } + if (isdigit(*r)) { /* font descriptor /Flags given? */ + for (s = r; isdigit(*s); s++); + if (*s == ' ' || *s == '"' || *s == '<' || *s == '\0') { /* not e. g. 8r.enc */ + fm->fd_flags = atoi(r); + while (isdigit(*r)) + r++; + } + } + while (1) { /* loop through "specials", encoding, font file */ + skip(r, ' '); + switch (*r) { + case '\0': + 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 (str_prefix(s, "SlantFont")) { + 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 (str_prefix(s, "ExtendFont")) { + 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 != '\0'; 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 != '\0'; 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; + case 'P': /* handle cases for subfonts like 'PidEid=3,1' */ + if (sscanf(r, "PidEid=%i, %i %n", &a, &b, &c) >= 2) { + fm->pid = a; + fm->eid = b; + r += c; + 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->encname = add_encname(buf); + u = v = 0; /* u, v used if intervening blank: "<< foo" */ + } else if (strlen(buf) > 0) { /* file name given */ + /* font file, formats: + * subsetting: ' no subsetting */ + } + set_field(ff_name); + u = v = 0; + } else { + u = a; + v = b; + } + } + } + done: + if (fm->ps_name != NULL && check_std_t1font(fm->ps_name)) + set_std_t1font(fm); + if (is_fontfile(fm)) { + if (strcasecmp(strend(fm_fontfile(fm)) - 4, ".ttf") == 0) + set_truetype(fm); + else if (strcasecmp(strend(fm_fontfile(fm)) - 4, ".otf") == 0) + set_opentype(fm); + else + set_type1(fm); + } else + set_type1(fm); /* assume a builtin font is Type1 */ + 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 (handle_subfont_fm(fm, mitem->mode)) /* is this a subfont? */ + return; + if (avl_do_entry(fm, mitem->mode) == 0) /* if success */ + return; + bad_line: + delete_fm_entry(fm); +} + +/**********************************************************************/ + +void fm_read_info () +{ + int callback_id; + int file_opened = 0; + char *ftemp = NULL; + if (tfm_tree == NULL) + create_avl_trees (); + if (mitem->line == NULL) /* nothing to do */ + return; + mitem->lineno = 1; + switch (mitem->type) { + case MAPFILE: + set_cur_file_name (mitem->line); + if (fm_buffer!=NULL) { + xfree(fm_buffer); + fm_buffer=NULL; + } + fm_curbyte=0; + fm_size=0; + callback_id=callback_defined(find_map_file_callback); + if (callback_id>0) { + if(run_callback(callback_id,"S->S",(char *)(nameoffile+1),&ftemp)) { + if(ftemp!=NULL&&strlen(ftemp)) { + free(nameoffile); + namelength = strlen(ftemp); + nameoffile = xmalloc(namelength+2); + strcpy((char *)(nameoffile+1),ftemp); + free(ftemp); + } + } + } + callback_id=callback_defined(read_map_file_callback); + if (callback_id>0) { + if(run_callback(callback_id,"S->bSd",(char *)(nameoffile+1), + &file_opened, &fm_buffer,&fm_size)) { + if(file_opened) { + if (fm_size>0) { + cur_file_name = (char *) nameoffile + 1; + if (tracefilenames) + tex_printf ("{%s", cur_file_name); + while (!fm_eof ()) { + fm_scan_line (); + mitem->lineno++; + } + if (tracefilenames) + tex_printf ("}"); + fm_file = NULL; + } + } else { + pdftex_warn ("cannot open font map file"); + } + } else { + pdftex_warn ("cannot open font map file"); + } + } else { + if (!fm_open ()) { + pdftex_warn ("cannot open font map file"); + } else { + fm_read_file(); + cur_file_name = (char *) nameoffile + 1; + tex_printf ("{%s", cur_file_name); + while (!fm_eof ()) { + fm_scan_line (); + mitem->lineno++; + } + fm_close (); + tex_printf ("}"); + fm_file = NULL; + } + } + break; + case MAPLINE: + cur_file_name = NULL; /* makes pdftex_warn() shorter */ + fm_scan_line (); + break; + default: + assert (0); + } + mitem->line = NULL; /* done with this line */ + cur_file_name = NULL; + return; +} + +/**********************************************************************/ + +static fm_entry_ptr fmlookup(internalfontnumber f) +{ + char *tfm; + fm_entry *fm; + fm_entry tmp; + if (tfm_tree == NULL) + fm_read_info(); /* only to read default map file */ + tfm = font_name(f); + assert(strcmp(tfm, nontfm)); + + /* Look up for full [+-] */ + tmp.tfm_name = tfm; + fm = (fm_entry *) avl_find(tfm_tree, &tmp); + if (fm != NULL) { + fm->in_use = true; + return (fm_entry_ptr) fm; + } + return (fm_entry_ptr) dummy_fm_entry(); +} + +boolean hasfmentry(internalfontnumber f) +{ + if (font_map(f) == NULL) + set_font_map(f, (fm_entry_ptr) fmlookup(f)); + assert(font_map(f) != NULL); + return font_map(f) != (fm_entry_ptr) dummy_fm_entry(); +} + +/* check whether a map entry is valid for font replacement */ + +static boolean fm_valid_for_font_replacement(fm_entry * fm) +{ + ff_entry *ff; + + assert(fm != NULL); + assert(is_fontfile(fm)); /* ps_tree should contain only entries with font file */ + assert(is_type1(fm)); /* ps_tree should contain only Type1 entries */ + + ff = check_ff_exist(fm->ff_name, false); + assert(ff != NULL); + if (ff->ff_path == NULL) /* ...there is no font file available */ + return false; + return true; /* all tests passed */ +} + +/**********************************************************************/ +/* + * lookup fontmap by ps_name; + * used for Type1 font replacement when embedding of PDF files + */ + +fm_entry *lookup_fontmap(char *ps_name) +{ + fm_entry *fm, *fm2, tmp; + char *a, *b, *c, *d, *e, *s; + int i, sl, ex; + struct avl_traverser t, t2; + if (tfm_tree == NULL) + fm_read_info(); /* only to read default map file */ + assert(ps_name != NULL); + s = ps_name; + if (strlen(ps_name) > 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 = ps_name; + } + + /* + * Scan -Slant_ and -Extend_ font name extensions; + * three valid formats: + * -Slant_ + * -Slant_-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'; /* ps_name string ends before "-Slant_" */ + } else { + if (e != b) { /* only if 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'; /* ps_name 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'; /* ps_name string ends before "-Extend_" */ + } + } + } + tmp.ps_name = s; + + fm = (fm_entry *) avl_t_find(&t, ps_tree, &tmp); + if (fm == NULL) + return NULL; /* no entry found */ + + /* at this point we know there is at least one fm_entry with given ps_name; + * we test all such entries and return the first one that is valid for font + * replacement */ + + t2 = t; + fm2 = (fm_entry *) avl_t_prev(&t2); + + /* search forward */ + do { + if (fm_valid_for_font_replacement(fm)) + return fm; + fm = (fm_entry *) avl_t_next(&t); + } while (fm != NULL && comp_fm_entry_ps(fm, &tmp, NULL) == 0); + + /* search backward */ + while (fm2 != NULL && comp_fm_entry_ps(fm2, &tmp, NULL) == 0) { + if (fm_valid_for_font_replacement(fm2)) + return fm2; + fm2 = (fm_entry *) avl_t_prev(&t2); + } + + return NULL; +} + +/**********************************************************************/ +/* + * Process map file given by its name or map line contents. Items not + * beginning with [+-=] flush default map file, if it has not yet been + * read. Leading blanks and blanks immediately following [+-=] are + * ignored. + */ + +void process_map_item(char *s, int type) +{ + char *p; + int mode; + if (*s == ' ') + s++; /* ignore leading blank */ + 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; /* like +, but also: */ + mitem->line = NULL; /* flush default map file name */ + } + if (*s == ' ') + s++; /* ignore blank after [+-=] */ + p = s; /* map item starts here */ + switch (type) { + case MAPFILE: /* remove blank at end */ + while (*p != '\0' && *p != ' ') + p++; + *p = '\0'; + break; + case MAPLINE: /* blank at end allowed */ + break; + default: + assert(0); + } + if (mitem->line != NULL) /* read default map file first */ + fm_read_info(); + if (*s != '\0') { /* only if real item to process */ + mitem->mode = mode; + mitem->type = type; + mitem->line = s; + fm_read_info(); + } +} + +void pdfmapfile(integer t) +{ + process_map_item(makecstring(tokens_to_string(t)), MAPFILE); + flush_str(last_tokens_string); +} + +void pdfmapline(integer t) +{ + process_map_item(makecstring(tokens_to_string(t)), MAPLINE); + flush_str(last_tokens_string); +} + +void pdf_init_map_file(string map_name) +{ + assert(mitem == NULL); + mitem = xtalloc(1, mapitem); + mitem->mode = FM_DUPIGNORE; + mitem->type = MAPFILE; + mitem->line = xstrdup(map_name); +} + + +/**********************************************************************/ +/* + * Early check whether a font file exists. 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(char *ff_name, boolean is_tt) +{ + ff_entry *ff; + ff_entry tmp; + void **aa; + int callback_id; + char *filepath=NULL; + + assert(ff_name != NULL); + tmp.ff_name = 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(ff_name); + if (is_tt) { + callback_id=callback_defined(find_truetype_file_callback); + if (callback_id>0) { + run_callback(callback_id,"S->S",ff_name,&filepath); + if (filepath && strlen(filepath)==0) + filepath=NULL; + ff->ff_path = filepath; + } else { + ff->ff_path = kpse_find_file (ff_name, kpse_truetype_format, 0); + } + } + else { + callback_id=callback_defined(find_type1_file_callback); + if (callback_id>0) { + run_callback(callback_id,"S->S",ff_name,&filepath); + if (filepath && strlen(filepath)==0) + filepath=NULL; + ff->ff_path = filepath; + } else { + ff->ff_path = kpse_find_file (ff_name, kpse_type1_format, 0); + } + } + aa = avl_probe(ff_tree, ff); + assert(aa != NULL); + } + return ff; +} + +/**********************************************************************/ +/* 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); + tfm_tree = NULL; + } + if (ps_tree != NULL) { + avl_destroy(ps_tree, destroy_fm_entry_ps); + ps_tree = NULL; + } + if (ff_tree != NULL) { + avl_destroy(ff_tree, destroy_ff_entry); + ff_tree = NULL; + } +} + +/**********************************************************************/ +/* end of mapfile.c */ diff --git a/Build/source/texk/web2c/luatexdir/font/pkin.c b/Build/source/texk/web2c/luatexdir/font/pkin.c new file mode 100644 index 00000000000..5067d6dbd66 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/font/pkin.c @@ -0,0 +1,439 @@ +/* +Copyright (c) 1996-2002 Han The Thanh, + +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: pkin.c 1013 2008-02-14 00:09:02Z oneiros $ +*/ + +/* + * 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 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 . + */ + +#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]", (int) 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) ", (int) count); + else + printf("%d ", (int) 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/luatexdir/font/sfnt.c b/Build/source/texk/web2c/luatexdir/font/sfnt.c new file mode 100644 index 00000000000..95453a531a0 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/font/sfnt.c @@ -0,0 +1,647 @@ +/* $Header: /home/cvsroot/dvipdfmx/src/sfnt.c,v 1.12 2004/09/11 14:50:29 hirata Exp $ + + This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. + + Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata, + the dvipdfmx project team + + 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. +*/ + +/* Based on dvipdfmx-0.13.2c */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H_ */ + +#include + +#ifndef pdfTeX +#include "system.h" + +#include "error.h" +#include "mem.h" +#include "mfileio.h" +#else +extern void pdftex_fail (const char *fmt, ...); /* utils.c */ +#endif + +#include "sfnt.h" + +#ifdef XETEX +UNSIGNED_BYTE +ft_unsigned_byte(sfnt* f) +{ + unsigned char byte; + unsigned long length = 1; + + if (FT_Load_Sfnt_Table(f->ft_face, 0, f->loc, &byte, &length) != 0) + TT_ERROR("sfnt: Freetype failure..."); + f->loc += 1; + + return byte; +} + +SIGNED_BYTE +ft_signed_byte(sfnt* f) +{ + int b = ft_unsigned_byte(f); + if (b >= 0x80) + b -= 0x100; + return (SIGNED_BYTE)b; +} + +UNSIGNED_PAIR +ft_unsigned_pair(sfnt* f) +{ + unsigned char buf[2]; + unsigned long length = 2; + + if (FT_Load_Sfnt_Table(f->ft_face, 0, f->loc, buf, &length) != 0) + TT_ERROR("sfnt: Freetype failure..."); + f->loc += 2; + + return (UNSIGNED_PAIR)((unsigned)buf[0] << 8) + buf[1]; +} + +SIGNED_PAIR +ft_signed_pair(sfnt* f) +{ + int p = ft_unsigned_pair(f); + if (p >= 0x8000U) + p -= 0x10000U; + + return (SIGNED_PAIR)p; +} + +UNSIGNED_QUAD +ft_unsigned_quad(sfnt* f) +{ + unsigned char buf[4]; + unsigned long length = 4; + + if (FT_Load_Sfnt_Table(f->ft_face, 0, f->loc, buf, &length) != 0) + TT_ERROR("sfnt: Freetype failure..."); + f->loc += 4; + + return ((unsigned long)buf[0] << 24) + ((unsigned long)buf[1] << 16) + + ((unsigned long)buf[2] << 8) + (unsigned long)buf[3]; +} + +unsigned long +ft_read(unsigned char* buf, unsigned long len, sfnt* f) +{ + unsigned long length = len; + if (FT_Load_Sfnt_Table(f->ft_face, 0, f->loc, buf, &length) != 0) + TT_ERROR("sfnt: Freetype failure..."); + f->loc += len; + + return length; +} +#endif + + +/* + * type: + * `true' (0x74727565): TrueType (Mac) + * `typ1' (0x74797031) (Mac): PostScript font housed in a sfnt wrapper + * 0x00010000: TrueType (Win)/OpenType + * `OTTO': PostScript CFF font with OpenType wrapper + * `ttcf': TrueType Collection +*/ +#define SFNT_TRUETYPE 0x00010000UL +#define SFNT_MAC_TRUE 0x74727565UL +#define SFNT_OPENTYPE 0x00010000UL +#define SFNT_POSTSCRIPT 0x4f54544fUL +#define SFNT_TTC 0x74746366UL + +#ifdef XETEX +sfnt * +sfnt_open (FT_Face face, int accept_types) +{ + sfnt *sfont; + ULONG type; + + if (!face || !FT_IS_SFNT(face)) + return NULL; + + sfont = NEW(1, sfnt); + sfont->ft_face = face; + sfont->loc = 0; + sfont->type = 0; + + type = sfnt_get_ulong(sfont); + + if (type == SFNT_TRUETYPE || type == SFNT_MAC_TRUE) { + sfont->type = SFNT_TYPE_TRUETYPE; + } else if (type == SFNT_OPENTYPE) { + sfont->type = SFNT_TYPE_OPENTYPE; + } else if (type == SFNT_POSTSCRIPT) { + sfont->type = SFNT_TYPE_POSTSCRIPT; + } else if (type == SFNT_TTC) { + sfont->type = SFNT_TYPE_TTC; + } + + if ((sfont->type & accept_types) == 0) { + RELEASE(sfont); + return NULL; + } + + sfont->loc = 0; + + sfont->directory = NULL; + + return sfont; +} +#else /* not XETEX */ +#ifdef pdfTeX +sfnt * +sfnt_open (unsigned char *buffer, integer buflen) +{ + sfnt *sfont; + ULONG type; + + sfont = xmalloc(sizeof(sfnt)); + sfont->loc = 0; + sfont->buffer = buffer; + sfont->buflen = buflen; + + type = sfnt_get_ulong(sfont); + + if (type == SFNT_TRUETYPE || type == SFNT_MAC_TRUE) { + sfont->type = SFNT_TYPE_TRUETYPE; + } else if (type == SFNT_OPENTYPE) { + sfont->type = SFNT_TYPE_OPENTYPE; + } else if (type == SFNT_POSTSCRIPT) { + sfont->type = SFNT_TYPE_POSTSCRIPT; + } else if (type == SFNT_TTC) { + sfont->type = SFNT_TYPE_TTC; + } + + sfont->loc=0; + sfont->directory = NULL; + return sfont; +} +#else +sfnt * +sfnt_open (FILE *fp) +{ + sfnt *sfont; + ULONG type; + + ASSERT(fp); + + rewind(fp); + + sfont = NEW(1, sfnt); + + sfont->stream = fp; + + type = sfnt_get_ulong(sfont); + + if (type == SFNT_TRUETYPE || type == SFNT_MAC_TRUE) { + sfont->type = SFNT_TYPE_TRUETYPE; + } else if (type == SFNT_OPENTYPE) { + sfont->type = SFNT_TYPE_OPENTYPE; + } else if (type == SFNT_POSTSCRIPT) { + sfont->type = SFNT_TYPE_POSTSCRIPT; + } else if (type == SFNT_TTC) { + sfont->type = SFNT_TYPE_TTC; + } + + rewind(sfont->stream); + + sfont->directory = NULL; + + return sfont; +} +#endif +#endif + +static void +release_directory (struct sfnt_table_directory *td) +{ + long i; + + if (td) { + if (td->tables) { + for (i = 0; i < td->num_tables; i++) { + if (td->tables[i].data) + RELEASE(td->tables[i].data); + } + RELEASE(td->tables); + } + if (td->flags) + RELEASE(td->flags); + RELEASE(td); + } + + return; +} + +void +sfnt_close (sfnt *sfont) +{ + + if (sfont) { + if (sfont->directory) + release_directory(sfont->directory); + RELEASE(sfont); + } + + return; +} + +int +put_big_endian (void *s, LONG q, int n) +{ + int i; + char *p; + + p = (char *) s; + for (i = n - 1; i >= 0; i--) { + p[i] = (char) (q & 0xff); + q >>= 8; + } + + return n; +} + +/* Convert four-byte number to big endianess + * in a machine independent way. + */ +static void +convert_tag (char *tag, unsigned long u_tag) +{ + int i; + + for (i = 3; i >= 0; i--) { + tag[i] = (char) (u_tag % 256); + u_tag /= 256; + } + + return; +} + +/* + * Computes the max power of 2 <= n + */ +static unsigned +max2floor (unsigned n) +{ + int val = 1; + + while (n > 1) { + n /= 2; + val *= 2; + } + + return val; +} + +/* + * Computes the log2 of the max power of 2 <= n + */ +static unsigned +log2floor (unsigned n) +{ + unsigned val = 0; + + while (n > 1) { + n /= 2; + val++; + } + + return val; +} + +static ULONG +sfnt_calc_checksum(void *data, ULONG length) +{ + ULONG chksum = 0; + BYTE *p, *endptr; + int count = 0; + + p = (BYTE *) data; + endptr = p + length; + while (p < endptr) { + chksum += (p[0] << (8 * ( 3 - count))); + count = ((count + 1) & 3); + p++; + } + + return chksum; +} + +static int +find_table_index (struct sfnt_table_directory *td, const char *tag) +{ + int idx; + + if (!td) + return -1; + + for (idx = 0; idx < td->num_tables; idx++) { + if (!memcmp(td->tables[idx].tag, tag, 4)) + return idx; + } + + return -1; +} + +void +sfnt_set_table (sfnt *sfont, const char *tag, void *data, ULONG length) +{ + struct sfnt_table_directory *td; + int idx; + + ASSERT(sfont); + + td = sfont->directory; + idx = find_table_index(td, tag); + + if (idx < 0) { + idx = td->num_tables; + td->num_tables++; + td->tables = RENEW(td->tables, td->num_tables, struct sfnt_table); + memcpy(td->tables[idx].tag, tag, 4); + } + + td->tables[idx].check_sum = sfnt_calc_checksum(data, length); + td->tables[idx].offset = 0L; + td->tables[idx].length = length; + td->tables[idx].data = data; + + return; +} + +ULONG +sfnt_find_table_len (sfnt *sfont, const char *tag) +{ + ULONG length; + struct sfnt_table_directory *td; + int idx; + + ASSERT(sfont && tag); + + td = sfont->directory; + idx = find_table_index(td, tag); + if (idx < 0) + length = 0; + else { + length = td->tables[idx].length; + } + + return length; +} + +ULONG +sfnt_find_table_pos (sfnt *sfont, const char *tag) +{ + ULONG offset; + struct sfnt_table_directory *td; + int idx; + + ASSERT(sfont && tag); + + td = sfont->directory; + idx = find_table_index(td, tag); + if (idx < 0) + offset = 0; + else { + offset = td->tables[idx].offset; + } + + return offset; +} + +ULONG +sfnt_locate_table (sfnt *sfont, const char *tag) +{ + ULONG offset; + + ASSERT(sfont && tag); + + offset = sfnt_find_table_pos(sfont, tag); + if (offset == 0) + TT_ERROR("sfnt: table not found..."); + + sfnt_seek_set(sfont, offset); + + return offset; +} + +int +sfnt_read_table_directory (sfnt *sfont, ULONG offset) +{ + struct sfnt_table_directory *td; + unsigned long i, u_tag; + + ASSERT(sfont); + + if (sfont->directory) + release_directory(sfont->directory); + sfont->directory = td = NEW (1, struct sfnt_table_directory); + +#ifdef XETEX + ASSERT(sfont->ft_face); +#elif defined(pdfTeX) + ASSERT(sfont->buffer); +#else + ASSERT(sfont->stream); +#endif + + sfnt_seek_set(sfont, offset); + + td->version = sfnt_get_ulong(sfont); + td->num_tables = sfnt_get_ushort(sfont); + td->search_range = sfnt_get_ushort(sfont); + td->entry_selector = sfnt_get_ushort(sfont); + td->range_shift = sfnt_get_ushort(sfont); + + td->flags = NEW(td->num_tables, char); + td->tables = NEW(td->num_tables, struct sfnt_table); + + for (i = 0; i < td->num_tables; i++) { + u_tag = sfnt_get_ulong(sfont); + + convert_tag(td->tables[i].tag, u_tag); + td->tables[i].check_sum = sfnt_get_ulong(sfont); + td->tables[i].offset = sfnt_get_ulong(sfont); + td->tables[i].length = sfnt_get_ulong(sfont); + td->tables[i].data = NULL; + + td->flags[i] = 0; + } + + td->num_kept_tables = 0; + + return 0; +} + +int +sfnt_require_table (sfnt *sfont, const char *tag, int must_exist) +{ + struct sfnt_table_directory *td; + int idx; + + ASSERT(sfont && sfont->directory); + + td = sfont->directory; + idx = find_table_index(td, tag); + if (idx < 0) { + if (must_exist) + return -1; + } else { + td->flags[idx] |= SFNT_TABLE_REQUIRED; + td->num_kept_tables++; + } + + return 0; +} + +#ifndef pdfTeX +#include "pdfobj.h" +#endif + +/* + * o All tables begin on four byte boundries, and pad any remaining space + * between tables with zeros + * + * o Entries in the Table Directory must be sorted in ascending order by tag + * + * o The head table contains checksum of the whole font file. + * To compute: first set it to 0, sum the entire font as ULONG, + * then store 0xB1B0AFBA - sum. + */ + +#ifdef pdfTeX +extern pdf_obj *pdf_new_stream(void); +extern void pdf_add_stream(pdf_obj *, unsigned char *, long); +extern void pdf_release_obj(pdf_obj *); +#undef MIN +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define STREAM_COMPRESS +#endif + +static unsigned char wbuf[1024], padbytes[4] = {0, 0, 0, 0}; + +pdf_obj * +sfnt_create_FontFile_stream (sfnt *sfont) +{ + pdf_obj *stream; +#ifndef pdfTeX + pdf_obj *stream_dict; +#endif + struct sfnt_table_directory *td; + long offset, nb_read, length; + int i, sr; + char *p; + + ASSERT(sfont && sfont->directory); + + stream = pdf_new_stream(STREAM_COMPRESS); + + td = sfont->directory; + + /* Header */ + p = (char *) wbuf; + p += sfnt_put_ulong (p, td->version); + p += sfnt_put_ushort(p, td->num_kept_tables); + sr = max2floor(td->num_kept_tables) * 16; + p += sfnt_put_ushort(p, sr); + p += sfnt_put_ushort(p, log2floor(td->num_kept_tables)); + p += sfnt_put_ushort(p, td->num_kept_tables * 16 - sr); + + pdf_add_stream(stream, wbuf, 12); + + /* + * Compute start of actual tables (after headers). + */ + offset = 12 + 16 * td->num_kept_tables; + for (i = 0; i < td->num_tables; i++) { + /* This table must exist in FontFile */ + if (td->flags[i] & SFNT_TABLE_REQUIRED) { + if ((offset % 4) != 0) { + offset += 4 - (offset % 4); + } + + p = (char *) wbuf; + memcpy(p, td->tables[i].tag, 4); + p += 4; + p += sfnt_put_ulong(p, td->tables[i].check_sum); + p += sfnt_put_ulong(p, offset); + p += sfnt_put_ulong(p, td->tables[i].length); + pdf_add_stream(stream, wbuf, 16); + + offset += td->tables[i].length; + } + } + + offset = 12 + 16 * td->num_kept_tables; + for (i = 0; i < td->num_tables; i++) { + if (td->flags[i] & SFNT_TABLE_REQUIRED) { + if ((offset % 4) != 0) { + length = 4 - (offset % 4); + pdf_add_stream(stream, padbytes, length); + offset += length; + } + if (!td->tables[i].data) { +#ifdef XETEX + if (!sfont->ft_face) +#elif defined(pdfTeX) + if (!sfont->buffer) +#else + if (!sfont->stream) +#endif + { + pdf_release_obj(stream); + TT_ERROR("Font file not opened or already closed..."); + return NULL; + } + + length = td->tables[i].length; + sfnt_seek_set(sfont, td->tables[i].offset); + while (length > 0) { + nb_read = sfnt_read(wbuf, MIN(length, 1024), sfont); + if (nb_read < 0) { + pdf_release_obj(stream); + TT_ERROR("Reading file failed..."); + return NULL; + } else if (nb_read > 0) { + pdf_add_stream(stream, wbuf, nb_read); + } + length -= nb_read; + } + } else { + pdf_add_stream(stream, + (unsigned char *)td->tables[i].data, + td->tables[i].length); + RELEASE(td->tables[i].data); + td->tables[i].data = NULL; + } + /* Set offset for next table */ + offset += td->tables[i].length; + } + } + +#ifndef pdfTeX + stream_dict = pdf_stream_dict(stream); + pdf_add_dict(stream_dict, + pdf_new_name("Length1"), + pdf_new_number(offset)); +#endif + return stream; +} diff --git a/Build/source/texk/web2c/luatexdir/font/sfnt.h b/Build/source/texk/web2c/luatexdir/font/sfnt.h new file mode 100644 index 00000000000..8db54dd9c39 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/font/sfnt.h @@ -0,0 +1,197 @@ +/* $Header: /home/cvsroot/dvipdfmx/src/sfnt.h,v 1.9 2004/09/11 14:50:29 hirata Exp $ + + This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. + + Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata, + the dvipdfmx project team + + 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. +*/ + +#ifndef _SFNT_H_ +#define _SFNT_H_ + +#if HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H_ */ + +#ifndef pdfTeX +#include "mfileio.h" +#include "numbers.h" +#include "pdfobj.h" +#endif + +#ifdef XETEX +#include "ft2build.h" +#include FT_FREETYPE_H +#include FT_TRUETYPE_TABLES_H +#endif + +/* Data Types as described in Apple's TTRefMan */ +typedef unsigned char BYTE; +typedef signed char ICHAR; +typedef unsigned short USHORT; +typedef signed short SHORT; +typedef unsigned long ULONG; +typedef signed long LONG; +typedef unsigned long Fixed; /* 16.16-bit signed fixed-point number */ +typedef short FWord; +typedef unsigned short uFWord; +typedef short F2Dot14; /* 16-bit signed fixed number with the low + 14 bits representing fraction. */ + +struct sfnt_table +{ + /* table header */ + char tag[4]; + ULONG check_sum; + ULONG offset; + ULONG length; + char *data; /* table data */ +}; + +#define SFNT_TABLE_REQUIRED (1 << 0) + +struct sfnt_table_directory +{ + ULONG version; /* Fixed for Win */ + USHORT num_tables; + USHORT search_range; + USHORT entry_selector; + USHORT range_shift; + USHORT num_kept_tables; /* number of kept tables */ + char *flags; /* keep or omit */ + struct sfnt_table *tables; +}; + +/* sfnt resource */ +#define SFNT_TYPE_TRUETYPE (1 << 0) +#define SFNT_TYPE_OPENTYPE (1 << 1) +#define SFNT_TYPE_POSTSCRIPT (1 << 2) +#define SFNT_TYPE_TTC (1 << 4) + +typedef struct +{ + int type; + struct sfnt_table_directory *directory; +#ifdef XETEX + FT_Face ft_face; + long loc; +#elif defined(pdfTeX) + BYTE *buffer; + long buflen; + long loc; +#else + FILE *stream; +#endif +} sfnt; + +/* Convert sfnt "fixed" type to double */ +#define fixed(a) ((double)((a)%0x10000L)/(double)(0x10000L) + \ + (a)/0x10000L - (((a)/0x10000L > 0x7fffL) ? 0x10000L : 0)) + +#ifdef XETEX +UNSIGNED_BYTE ft_unsigned_byte(sfnt* f); +SIGNED_BYTE ft_signed_byte(sfnt* f); +UNSIGNED_PAIR ft_unsigned_pair(sfnt* f); +SIGNED_PAIR ft_signed_pair(sfnt* f); +UNSIGNED_QUAD ft_unsigned_quad(sfnt* f); +unsigned long ft_read(unsigned char* buf, unsigned long len, sfnt* f); + +#define sfnt_get_byte(s) ((BYTE) ft_unsigned_byte(s)) +#define sfnt_get_char(s) ((ICHAR) ft_signed_byte (s)) +#define sfnt_get_ushort(s) ((USHORT) ft_unsigned_pair(s)) +#define sfnt_get_short(s) ((SHORT) ft_signed_pair (s)) +#define sfnt_get_ulong(s) ((ULONG) ft_unsigned_quad(s)) +#define sfnt_get_long(s) ((LONG) ft_signed_quad (s)) + +#define sfnt_seek_set(s,o) (s)->loc = (o) +#define sfnt_read(b,l,s) ft_read((b), (l), (s)) +#elif defined(pdfTeX) +BYTE get_unsigned_byte(sfnt* f); +ICHAR get_signed_byte(sfnt* f); +USHORT get_unsigned_pair(sfnt* f); +SHORT get_signed_pair(sfnt* f); +ULONG get_unsigned_quad(sfnt* f); +int do_sfnt_read (unsigned char *dest, int len, sfnt *f); + +#define sfnt_get_byte(s) ((BYTE) get_unsigned_byte(s)) +#define sfnt_get_char(s) ((ICHAR) get_signed_byte (s)) +#define sfnt_get_ushort(s) ((USHORT) get_unsigned_pair(s)) +#define sfnt_get_short(s) ((SHORT) get_signed_pair (s)) +#define sfnt_get_ulong(s) ((ULONG) get_unsigned_quad(s)) +#define sfnt_get_long(s) ((LONG) get_signed_quad (s)) + +#define sfnt_seek_set(s,o) (s)->loc = (o) +#define sfnt_read(b,l,s) do_sfnt_read((b), (l), (s)) +#else +/* get_***_*** from numbers.h */ +#define sfnt_get_byte(s) ((BYTE) get_unsigned_byte((s)->stream)) +#define sfnt_get_char(s) ((ICHAR) get_signed_byte ((s)->stream)) +#define sfnt_get_ushort(s) ((USHORT) get_unsigned_pair((s)->stream)) +#define sfnt_get_short(s) ((SHORT) get_signed_pair ((s)->stream)) +#define sfnt_get_ulong(s) ((ULONG) get_unsigned_quad((s)->stream)) +#define sfnt_get_long(s) ((LONG) get_signed_quad ((s)->stream)) + +#define sfnt_seek_set(s,o) seek_absolute((s)->stream, (o)) +#define sfnt_read(b,l,s) fread((b), 1, (l), (s)->stream) +#endif + +extern int put_big_endian (void *s, LONG q, int n); + +#define sfnt_put_ushort(s,v) put_big_endian((s), v, 2); +#define sfnt_put_short(s,v) put_big_endian((s), v, 2); +#define sfnt_put_ulong(s,v) put_big_endian((s), v, 4); +#define sfnt_put_long(s,v) put_big_endian((s), v, 4); + +#ifdef XETEX +extern sfnt *sfnt_open (FT_Face face, int accept_types); +#elif defined(pdfTeX) +extern sfnt *sfnt_open (unsigned char *buffer, integer buflen); +#else +extern sfnt *sfnt_open (FILE *fp); +#endif +extern void sfnt_close (sfnt *sfont); + +/* table directory */ +extern int sfnt_read_table_directory (sfnt *sfont, ULONG offset); +extern ULONG sfnt_find_table_len (sfnt *sfont, const char *tag); +extern ULONG sfnt_find_table_pos (sfnt *sfont, const char *tag); +extern ULONG sfnt_locate_table (sfnt *sfont, const char *tag); + +extern void sfnt_set_table (sfnt *sfont, + const char *tag, void *data, ULONG length); +extern int sfnt_require_table (sfnt *sfont, const char *tag, int must_exist); + +#ifdef pdfTeX +typedef struct +{ + ULONG length; + BYTE *data; +} pdf_obj; + +#define ASSERT(a) assert(a) +#define RELEASE(a) free(a) +#define NEW(a,b) xmalloc((a)*sizeof(b)) +#define RENEW(a,b,c) xrealloc(a, ((b)*sizeof(c))) +#define TT_ERROR pdftex_fail +#define WARN printf + + +#endif + +extern pdf_obj *sfnt_create_FontFile_stream (sfnt *sfont); + +#endif /* _SFNT_H_ */ diff --git a/Build/source/texk/web2c/luatexdir/font/subfont.c b/Build/source/texk/web2c/luatexdir/font/subfont.c new file mode 100644 index 00000000000..836985c10fd --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/font/subfont.c @@ -0,0 +1,264 @@ +/* +Copyright (c) 2005-2006 Han The Thanh, + +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 +*/ + +#include "ptexlib.h" +#include + +static struct avl_table *sfd_tree = NULL; + +static unsigned char *sfd_buffer = NULL; +static integer sfd_size = 0; +static integer sfd_curbyte = 0; + +#define SFD_BUF_SIZE SMALL_BUF_SIZE + +#define sfd_close() xfclose(sfd_file, cur_file_name) +#define sfd_open() open_input(&sfd_file, kpse_sfd_format, FOPEN_RBIN_MODE) + +#define sfd_read_file() readbinfile(sfd_file,&sfd_buffer,&sfd_size) +#define sfd_getchar() sfd_buffer[sfd_curbyte++] +#define sfd_eof() (sfd_curbyte>sfd_size) + + +static FILE *sfd_file; +static char sfd_line[SFD_BUF_SIZE]; + +static subfont_entry *new_subfont_entry (void) +{ + int i; + subfont_entry *subfont; + subfont = xtalloc (1, subfont_entry); + subfont->infix = NULL; + for (i = 0; i < 256; ++i) + subfont->charcodes[i] = -1; /* unassigned */ + subfont->next = NULL; + return subfont; +} + +static sfd_entry *new_sfd_entry (void) +{ + sfd_entry *sfd; + sfd = xtalloc (1, sfd_entry); + sfd->name = NULL; + sfd->subfont = NULL; + return sfd; +} + +static void destroy_sfd_entry (void *pa, void *pb) +{ + subfont_entry *p, *q; + sfd_entry *sfd; + sfd = (sfd_entry *) pa; + p = sfd->subfont; + while (p != NULL) { + q = p->next; + xfree (p->infix); + xfree (p); + p = q; + } + xfree (sfd->name); +} + +static int comp_sfd_entry (const void *pa, const void *pb, void *p) +{ + return strcmp (((const sfd_entry *) pa)->name, + ((const sfd_entry *) pb)->name); +} + +void sfd_free (void) +{ + if (sfd_tree != NULL) + avl_destroy (sfd_tree, destroy_sfd_entry); +} + +static void sfd_getline (boolean expect_eof) +{ + char *p; + int c; + restart: + if (sfd_eof ()) { + if (expect_eof) + return; + else + pdftex_fail ("unexpected end of file"); + } + p = sfd_line; + do { + c = sfd_getchar (); + append_char_to_buf (c, p, sfd_line, SFD_BUF_SIZE); + } while (c != 10 && !sfd_eof()); + append_eol (p, sfd_line, SFD_BUF_SIZE); + if (p - sfd_line < 2 || *sfd_line == '#') + goto restart; +} + +static sfd_entry *read_sfd (char *sfd_name) +{ + void **aa; + sfd_entry *sfd, tmp_sfd; + subfont_entry *sf; + char *ftemp = NULL; + char buf[SMALL_BUF_SIZE], *p; + long int i, j, k; + int n; + int callback_id=0; + int file_opened=0; + /* check whether this sfd has been read */ + tmp_sfd.name = sfd_name; + if (sfd_tree == NULL) { + sfd_tree = avl_create (comp_sfd_entry, NULL, &avl_xallocator); + assert (sfd_tree != NULL); + } + sfd = (sfd_entry *) avl_find (sfd_tree, &tmp_sfd); + if (sfd != NULL) + return sfd; + set_cur_file_name (sfd_name); + if (sfd_buffer!=NULL) { + xfree(sfd_buffer); + sfd_buffer=NULL; + } + sfd_curbyte=0; + sfd_size=0; + + callback_id=callback_defined(find_sfd_file_callback); + if (callback_id>0) { + if(run_callback(callback_id,"S->S",cur_file_name,&ftemp)) { + if(ftemp!=NULL&&strlen(ftemp)) { + if (cur_file_name) + free(cur_file_name); + cur_file_name = xstrdup(ftemp); + free(ftemp); + } + } + } + callback_id=callback_defined(read_sfd_file_callback); + if (callback_id>0) { + if(! (run_callback(callback_id,"S->bSd",cur_file_name, + &file_opened, &sfd_buffer,&sfd_size) && + file_opened && + sfd_size>0 ) ) { + pdftex_warn ("cannot open SFD file for reading"); + cur_file_name = NULL; + return NULL; + } + sfd_read_file(); + sfd_close(); + } + tex_printf ("{"); + tex_printf (cur_file_name); + sfd = new_sfd_entry (); + sfd->name = xstrdup (sfd_name); + while (!sfd_eof ()) { + sfd_getline (true); + if (*sfd_line == 10) /* empty line indicating eof */ + break; + sf = new_subfont_entry (); + sf->next = sfd->subfont; + sfd->subfont = sf; + sscanf (sfd_line, "%s %n", buf, &n); + sf->infix = xstrdup (buf); + p = sfd_line + n; /* skip to the next word */ + k = 0; + read_ranges: + for (;;) { + if (*p == '\\') { /* continue on next line */ + sfd_getline (false); + p = sfd_line; + goto read_ranges; + } else if (*p == 0) /* end of subfont */ + break; + if (sscanf (p, " %li %n", &i, &n) == 0) + pdftex_fail ("invalid token:\n%s", p); + p += n; + if (*p == ':') { /* offset */ + k = i; + p++; + } else if (*p == '_') { /* range */ + if (sscanf (p + 1, " %li %n", &j, &n) == 0) + pdftex_fail ("invalid token:\n%s", p); + if (i > j || k + (j - i) > 255) + pdftex_fail ("invalid range:\n%s", p); + while (i <= j) + sf->charcodes[k++] = i++; + p += n + 1; + } else /* codepoint */ + sf->charcodes[k++] = i; + } + } + tex_printf ("}"); + aa = avl_probe (sfd_tree, sfd); + assert (aa != NULL); + return sfd; +} + +boolean handle_subfont_fm (fm_entry * fm, int mode) +{ + size_t l; + char *p, *q, *r; + sfd_entry *sfd; + subfont_entry *sf; + fm_entry *fm2; + char buf[SMALL_BUF_SIZE]; + assert (fm->tfm_name != NULL); + p = fm->tfm_name; + q = strchr (p, '@'); /* search for the first '@' */ + if (q == NULL) + return false; + r = strchr (q + 1, '@'); /* search for the second '@' */ + if (r == NULL) + return false; + if (q <= p || r <= q + 1 /* prefix or sfd name is empty */ + || r - p != strlen (p) - 1) /* or the second '@' is not the last char yet */ + return false; + l = r - (q + 1); /* length of sfd name */ + strncpy (buf, q + 1, l); + buf[l] = 0; + check_buf(strlen(buf) + 4, SMALL_BUF_SIZE); + strcat (buf, ".sfd"); + sfd = read_sfd (buf); + if (sfd == NULL) + return false; + /* at this point we know fm is a subfont */ + set_subfont (fm); + xfree (fm->ps_name); + fm->ps_name = NULL; + /* set default values for PidEid */ + if (fm->pid == -1) { + fm->pid = 3; + fm->eid = 1; + } + l = q - p; /* length of base tfm name (prefix) */ + for (sf = sfd->subfont; sf != NULL; sf = sf->next) { + strncpy (buf, p, l); + buf[l] = 0; + strcat (buf, sf->infix); + fm2 = new_fm_entry (); + fm2->tfm_name = xstrdup (buf); + fm2->ff_name = xstrdup (fm->ff_name); + fm2->type = fm->type; + fm2->pid = fm->pid; + fm2->eid = fm->eid; + fm2->subfont = sf; + if (avl_do_entry (fm2, mode) != 0) /* try to insert the entry */ + delete_fm_entry (fm2); /* delete it if failed */ + } + delete_fm_entry (fm); + return true; +} diff --git a/Build/source/texk/web2c/luatexdir/font/subfont.txt b/Build/source/texk/web2c/luatexdir/font/subfont.txt new file mode 100644 index 00000000000..9fe053cbb9c --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/font/subfont.txt @@ -0,0 +1,74 @@ +map entry: + +cyberb@Unicode@ => look at Unicode.sfd => find the mapping => charcode + => PidEid=3,1 => glyphs + +eg cyberb01 => subfont 01 in Unicode.sfd => charcodes + +Infix can be anything, thus the question: given a tfm name, how to find out +whether this is a subfont? + +It is safe to limit the infix to be composed from hexadecimal digits only? + +If so, one possibility is: + +(1) +while last-char-of-tfmname is a hexdigit do + remove the last char from tfmname + do a lookup for the tfmname + if found an entry with subfont flag then + break +enddo + +(2) +Or, when a map entry with subfont flag is scanned, let pdftex create all +the relevant entries. Which may be a safer and faster solution (but wastes more +memory) + + +Let's do (2), as infix can be any word. + + + +Implementation: + +- let's have a map entry: + +cyberb@Unicode@ long[256] + - added those subfont to an AVL tree + - create map entries for cyberb01--cyberbff, each has a pointer to the + corresponding sfd mapping entry + +- extended attributes for map entry: + - Pid + - Eid + - sfd_map + +- sfd_mapping: + - name: sfd name, eg "Unicode" + - infix, eg "01" + - mapping: long[256] + +- how to find out whether a sfd has been loaded: + - lookup for any entry with the given sfd name + +- functions: + - load_sfd + - lookup_subfont + - extend reading map entries + +- when writting ttf: + - if re-encoded --> process like in case of type1 fonts + - if PidEid is being used: + - read cmap tables: store (ttfname, pid, eid) + - search for used chars + - use sfd to find the charcodes + - look into cmap to diff --git a/Build/source/texk/web2c/luatexdir/font/texfont.c b/Build/source/texk/web2c/luatexdir/font/texfont.c new file mode 100644 index 00000000000..150c2cba769 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/font/texfont.c @@ -0,0 +1,1094 @@ +/* + Copyright (c) 1996-2006 Taco Hoekwater + + This file is part of LuaTeX. + + LuaTeX 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. + + LuaTeX 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 LuaTeX; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + $Id: texfont.c 1013 2008-02-14 00:09:02Z oneiros $ */ + +/* Main font API implementation for the pascal parts */ + +/* stuff to watch out for: + * + * - Knuth had a 'null_character' that was used when a character could + * not be found by the fetch() routine, to signal an error. This has + * been deleted, but it may mean that the output of luatex is + * incompatible with TeX after fetch() has detected an error condition. + * + * - Knuth also had a font_glue() optimization. I've removed that + * because it was a bit of dirty programming and it also was + * problematic if 0 != null. + */ + +#include "ptexlib.h" +#include "luatex-api.h" + +#define proper_char_index(c) (c<=font_ec(f) && c>=font_bc(f)) +#define dxfree(a,b) { xfree(a); a = b ; } +#define do_realloc(a,b,d) a = xrealloc(a,(b)*sizeof(d)) + +texfont **font_tables = NULL; + +static integer font_arr_max = 0; +static integer font_id_maxval = 0; + +static void grow_font_table (integer id) { + int j; + if (id>=font_arr_max) { + font_bytes += (font_arr_max-id+8)*sizeof(texfont *); + font_tables = xrealloc(font_tables,(id+8)*sizeof(texfont *)); + j = 8; + while (j--) { + font_tables[id+j] = NULL; + } + font_arr_max = id+8; + } +} + +integer +new_font_id (void) { + int i; + for (i=0;i=font_arr_max) + grow_font_table (i); + if (i>font_id_maxval) + font_id_maxval = i; + return i; +} + +integer +max_font_id (void) { + return font_id_maxval; +} + +void +set_max_font_id (integer i) { + font_id_maxval = i; +} + +integer +new_font (void) { + int k; + int id; + charinfo *ci; + id = new_font_id(); + font_bytes += sizeof(texfont); + /* most stuff is zero */ + font_tables[id] = xcalloc(1,sizeof(texfont)); + font_tables[id]->_font_name = NULL; + font_tables[id]->_font_area = NULL; + font_tables[id]->_font_filename = NULL; + font_tables[id]->_font_fullname = NULL; + font_tables[id]->_font_encodingname = NULL; + font_tables[id]->_font_cidregistry = NULL; + font_tables[id]->_font_cidordering = NULL; + font_tables[id]->_left_boundary = NULL; + font_tables[id]->_right_boundary = NULL; + font_tables[id]->_param_base = NULL; + + set_font_bc(id, 1); /* ec = 0 */ + set_hyphen_char(id,'-'); + set_skew_char(id,-1); + + /* allocate eight values including 0 */ + set_font_params(id,7); + for (k=0;k<=7;k++) { + set_font_param(id,k,0); + } + /* character info zero is reserved for notdef */ + font_tables[id]->characters = new_sa_tree(1, 0); /* stack size 1, default item value 0 */ + + ci = xcalloc(1,sizeof(charinfo)); + set_charinfo_name(ci,xstrdup(".notdef")); + font_tables[id]->charinfo = ci; + font_tables[id]->charinfo_cache = NULL; + + return id; +} + +#define Charinfo_count(a) font_tables[a]->charinfo_count +#define Charinfo_size(a) font_tables[a]->charinfo_size +#define Characters(a) font_tables[a]->characters + +charinfo * +get_charinfo (internal_font_number f, integer c) { + sa_tree_item glyph; + charinfo *ci; + if (proper_char_index(c)) { + glyph = get_sa_item(Characters(f), c); + if (!glyph) { + /* this could be optimized using controlled growth */ + font_bytes += sizeof(charinfo); + glyph = ++font_tables[f]->charinfo_count; + do_realloc(font_tables[f]->charinfo, (glyph+1), charinfo); + memset (&(font_tables[f]->charinfo[glyph]),0,sizeof(charinfo)); + font_tables[f]->charinfo[glyph].ef = 1000; /* init */ + font_tables[f]->charinfo_size = glyph; + set_sa_item(font_tables[f]->characters, c, glyph, 1); /* 1= global */ + } + return &(font_tables[f]->charinfo[glyph]); + } else if (c == left_boundarychar) { + if (left_boundary(f)==NULL) { + ci = xcalloc(1,sizeof(charinfo)); + font_bytes += sizeof(charinfo); + set_left_boundary(f,ci); + } + return left_boundary(f); + } else if (c == right_boundarychar) { + if (right_boundary(f)==NULL) { + ci = xcalloc(1,sizeof(charinfo)); + font_bytes += sizeof(charinfo); + set_right_boundary(f,ci); + } + return right_boundary(f); + } + return &(font_tables[f]->charinfo[0]); +} + +void +set_charinfo (internal_font_number f, integer c, charinfo *ci) { + sa_tree_item glyph; + if (proper_char_index(c)) { + glyph = get_sa_item(Characters(f), c); + if (glyph) { + font_tables[f]->charinfo[glyph] = *ci; + } else { + pdftex_fail("font: %s","character insertion failed"); + } + } else if (c == left_boundarychar) { + set_left_boundary(f,ci); + } else if (c == right_boundarychar) { + set_right_boundary(f,ci); + } +} + + + +charinfo * +copy_charinfo (charinfo *ci) { + int x; + kerninfo *kern; + liginfo *lig; + real_eight_bits *packet; + charinfo *co = NULL; + if (ci==NULL) + return NULL; + co = xmalloc(sizeof(charinfo)); + memcpy(co,ci,sizeof(charinfo)); + set_charinfo_used(co,false); + co->name = NULL; + co->tounicode = NULL; + co->packets = NULL; + co->ligatures = NULL; + co->kerns = NULL; + co->extensible = NULL; + if (ci->name!=NULL) { + co->name = xstrdup(ci->name); + } + if (ci->tounicode!=NULL) { + co->tounicode = xstrdup(ci->tounicode); + } + /* kerns */ + if ((kern = get_charinfo_kerns(ci)) != NULL) { + x = 0; + while (!kern_end(kern[x])) { x++; } x++; + co->kerns = xmalloc (x*sizeof(kerninfo)); + memcpy(co->kerns,ci->kerns,(x*sizeof(kerninfo))); + } + /* ligs */ + if ((lig = get_charinfo_ligatures(ci)) != NULL) { + x = 0; + while (!lig_end(lig[x])) { x++; } x++; + co->ligatures = xmalloc (x*sizeof(liginfo)); + memcpy(co->ligatures,ci->ligatures,(x*sizeof(liginfo))); + } + /* packets */ + if ((packet = get_charinfo_packets(ci)) != NULL) { + x = vf_packet_bytes(ci); + co->packets = xmalloc (x); + memcpy(co->packets,ci->packets,x); + } + if (get_charinfo_tag(ci)==ext_tag) { + int top, bot, rep, mid; + top = get_charinfo_extensible(ci,EXT_TOP); + bot = get_charinfo_extensible(ci,EXT_BOT); + mid = get_charinfo_extensible(ci,EXT_MID); + rep = get_charinfo_extensible(ci,EXT_REP); + set_charinfo_extensible(co,top,bot,mid,rep); + } + return co; +} + +#if 0 +int +find_charinfo_id (internal_font_number f, integer c) { + register int g=0; + if (font_tables[f]->charinfo_cache==NULL) { + int i = (font_ec(f)+1)*sizeof(int); + font_tables[f]->charinfo_cache = xmalloc(i); + memset(font_tables[f]->charinfo_cache,0,i); + } else { + g = font_tables[f]->charinfo_cache[c]; + } + if (g==0) { + g = get_sa_item(font_tables[f]->characters, c); + font_tables[f]->charinfo_cache[c] = g; + } + return g; +} +#else +#define find_charinfo_id(f,c) get_sa_item(font_tables[f]->characters,c) +#endif + + +charinfo * +char_info (internal_font_number f, integer c) { + if (f>font_id_maxval) + return 0; + if (proper_char_index(c)) { + register int glyph = find_charinfo_id(f,c); + return &(font_tables[f]->charinfo[glyph]); + } else if (c == left_boundarychar && left_boundary(f)!=NULL) { + return left_boundary(f); + } else if (c == right_boundarychar && right_boundary(f)!=NULL) { + return right_boundary(f); + } + return &(font_tables[f]->charinfo[0]); +} + +charinfo_short +char_info_short (internal_font_number f, integer c) { + charinfo_short s; + charinfo *i; + i = char_info(f,c); + s.ci_wd = i->width; + s.ci_dp = i->depth; + s.ci_ht = i->height; + return s; +} + +integer +char_exists (internal_font_number f, integer c) { + if (f>font_id_maxval) + return 0; + if (proper_char_index(c)) { + return find_charinfo_id(f,c); + } else if ((c == left_boundarychar) && has_left_boundary(f)) { + return 1; + } else if ((c == right_boundarychar) && has_right_boundary(f)) { + return 1; + } + return 0; +} + +int +lua_char_exists_callback (internal_font_number f, integer c) { + integer callback_id ; + lua_State *L = Luas[0]; + int ret=0; + callback_id = callback_defined(char_exists_callback); + if (callback_id!=0) { + lua_rawgeti(L,LUA_REGISTRYINDEX,callback_callbacks_id); + lua_rawgeti(L,-1, callback_id); + if (!lua_isfunction(L,-1)) { + lua_pop(L,2); + return 0; + } + lua_pushnumber(L,f); + lua_pushnumber(L,c); + if (lua_pcall(L,2,1,0) != 0) { /* two args, 1 result */ + fprintf(stdout,"error: %s\n",lua_tostring(L,-1)); + lua_pop(L,2); + error(); + } else { + ret = lua_toboolean(L,-1); + } + } + return ret; +} + + +void set_charinfo_width (charinfo *ci, scaled val) { ci->width = val; } +void set_charinfo_height (charinfo *ci, scaled val) { ci->height = val; } +void set_charinfo_depth (charinfo *ci, scaled val) { ci->depth = val; } +void set_charinfo_italic (charinfo *ci, scaled val) { ci->italic = val; } +void set_charinfo_tag (charinfo *ci, scaled val) { ci->tag = val; } +void set_charinfo_remainder (charinfo *ci, scaled val) { ci->remainder = val; } +void set_charinfo_used (charinfo *ci, scaled val) { ci->used = val; } +void set_charinfo_index (charinfo *ci, scaled val) { ci->index = val; } +void set_charinfo_name (charinfo *ci, char *val) { dxfree(ci->name,val); } +void set_charinfo_tounicode (charinfo *ci, char *val) { dxfree(ci->tounicode,val); } +void set_charinfo_ligatures (charinfo *ci, liginfo *val) { dxfree(ci->ligatures,val); } +void set_charinfo_kerns (charinfo *ci, kerninfo *val) { dxfree(ci->kerns,val); } +void set_charinfo_packets (charinfo *ci, real_eight_bits *val){ dxfree(ci->packets,val); } +void set_charinfo_ef (charinfo *ci, scaled val) { ci->ef = val; } +void set_charinfo_lp (charinfo *ci, scaled val) { ci->lp = val; } +void set_charinfo_rp (charinfo *ci, scaled val) { ci->rp = val; } + + + +void set_charinfo_extensible (charinfo *ci, int top, int bot, int mid, int rep) { + if (top == 0 && bot == 0 && mid == 0 && rep == 0) { + if (ci->extensible != NULL) { + free(ci->extensible); + ci->extensible = NULL; + } + } else { + if (ci->extensible == NULL) { + ci->extensible = xmalloc(4*sizeof(integer)); + } + ci->extensible[EXT_TOP] = top; + ci->extensible[EXT_BOT] = bot; + ci->extensible[EXT_MID] = mid; + ci->extensible[EXT_REP] = rep; + } +} + +scaled get_charinfo_width (charinfo *ci) { return ci->width; } +scaled get_charinfo_height (charinfo *ci) { return ci->height; } +scaled get_charinfo_depth (charinfo *ci) { return ci->depth; } +scaled get_charinfo_italic (charinfo *ci) { return ci->italic; } +char get_charinfo_tag (charinfo *ci) { return ci->tag; } +integer get_charinfo_remainder (charinfo *ci) { return ci->remainder; } +char get_charinfo_used (charinfo *ci) { return ci->used; } +integer get_charinfo_index (charinfo *ci) { return ci->index; } +char *get_charinfo_name (charinfo *ci) { return ci->name; } +char *get_charinfo_tounicode (charinfo *ci) { return ci->tounicode; } +liginfo *get_charinfo_ligatures (charinfo *ci) { return ci->ligatures; } +kerninfo *get_charinfo_kerns (charinfo *ci) { return ci->kerns; } +real_eight_bits *get_charinfo_packets (charinfo *ci) { return ci->packets; } +integer get_charinfo_ef (charinfo *ci) { return ci->ef; } +integer get_charinfo_rp (charinfo *ci) { return ci->rp; } +integer get_charinfo_lp (charinfo *ci) { return ci->lp; } + +integer get_charinfo_extensible (charinfo *ci, int whch) { + int w = 0; + if (ci->extensible != NULL) + w = ci->extensible[whch]; + return w; +} + +integer ext_top (internal_font_number f, integer c) { + charinfo *ci = char_info(f,c); + integer w = get_charinfo_extensible(ci,EXT_TOP); + /* fprintf(stdout,"top of char 0x%4x in font %s: %i\n",c,font_name(f),w);*/ + return w; +} + +integer ext_bot (internal_font_number f, integer c) { + charinfo *ci = char_info(f,c); + integer w = get_charinfo_extensible(ci,EXT_BOT); + /*fprintf(stdout,"bot of char 0x%4x in font %s: %i\n",c,font_name(f),w);*/ + return w; +} +integer ext_mid (internal_font_number f, integer c) { + charinfo *ci = char_info(f,c); + integer w = get_charinfo_extensible(ci,EXT_MID); + /*fprintf(stdout,"mid of char 0x%4x in font %s: %i\n",c,font_name(f),w);*/ + return w; +} +integer ext_rep (internal_font_number f, integer c) { + charinfo *ci = char_info(f,c); + integer w = get_charinfo_extensible(ci,EXT_REP); + /*fprintf(stdout,"rep of char 0x%4x in font %s: %i\n",c,font_name(f),w);*/ + return w; +} + +scaled char_width (internal_font_number f, integer c) { + charinfo *ci = char_info(f,c); + scaled w = get_charinfo_width(ci); + /*fprintf(stdout,"width of char 0x%x in font %s: %i\n",c,font_name(f),w);*/ + return w; +} + +scaled char_depth (internal_font_number f, integer c) { + charinfo *ci = char_info(f,c); + scaled w = get_charinfo_depth(ci); + /*fprintf(stdout,"depth of char 0x%x in font %s: %i\n",c,font_name(f),w);*/ + return w; +} + +scaled char_height (internal_font_number f, integer c) { + charinfo *ci = char_info(f,c); + scaled w = get_charinfo_height(ci); + /*fprintf(stdout,"height of char 0x%x in font %s: %i\n",c,font_name(f),w);*/ + return w; +} + +scaled char_italic (internal_font_number f, integer c) { + charinfo *ci = char_info(f,c); + return get_charinfo_italic(ci); +} + +integer char_remainder (internal_font_number f, integer c) { + charinfo *ci = char_info(f,c); + return get_charinfo_remainder(ci); +} + +char char_tag (internal_font_number f, integer c) { + charinfo *ci = char_info(f,c); + return get_charinfo_tag(ci); +} + +char char_used (internal_font_number f, integer c) { + charinfo *ci = char_info(f,c); + return get_charinfo_used(ci); +} + +char *char_name (internal_font_number f, integer c) { + charinfo *ci = char_info(f,c); + return get_charinfo_name(ci); +} + +integer char_index (internal_font_number f, integer c) { + charinfo *ci = char_info(f,c); + return get_charinfo_index(ci); +} + +liginfo * char_ligatures (internal_font_number f, integer c) { + charinfo *ci = char_info(f,c); + return get_charinfo_ligatures(ci); +} + +kerninfo * char_kerns (internal_font_number f, integer c) { + charinfo *ci = char_info(f,c); + return get_charinfo_kerns(ci); +} + +real_eight_bits * char_packets (internal_font_number f, integer c) { + charinfo *ci = char_info(f,c); + return get_charinfo_packets(ci); +} + + +void +set_font_params(internal_font_number f, int b) { + int i; + i = font_params(f); + if (i!=b) { + font_bytes += (b-font_params(f))*sizeof(scaled); + do_realloc(param_base(f), (b+1), integer); + font_params(f) = b; + if (b>i) { + while (i_font_name = NULL; + font_tables[k]->_font_filename = NULL; + font_tables[k]->_font_fullname = NULL; + font_tables[k]->_font_encodingname = NULL; + font_tables[k]->_font_area = NULL; + font_tables[k]->_font_cidregistry = NULL; + font_tables[k]->_font_cidordering = NULL; + font_tables[k]->_left_boundary = NULL; + font_tables[k]->_right_boundary = NULL; + + set_font_name(k,xstrdup(font_name(f))); + if (font_filename(f)!= NULL) + set_font_filename(k,xstrdup(font_filename(f))); + if (font_fullname(f)!= NULL) + set_font_fullname(k,xstrdup(font_fullname(f))); + if (font_encodingname(f)!= NULL) + set_font_encodingname(k,xstrdup(font_encodingname(f))); + if (font_area(f)!= NULL) + set_font_area(k,xstrdup(font_area(f))); + if (font_cidregistry(f)!= NULL) + set_font_cidregistry(k,xstrdup(font_cidregistry(f))); + if (font_cidordering(f)!= NULL) + set_font_cidordering(k,xstrdup(font_cidordering(f))); + + i = sizeof(*param_base(f))*font_params(f); + font_bytes += i; + param_base(k) = xmalloc (i); + memcpy(param_base(k),param_base(f), i); + + i = sizeof(charinfo)*(Charinfo_size(f)+1); + font_bytes += i; + font_tables[k]->charinfo = xmalloc(i); + memset(font_tables[k]->charinfo,0,i); + for(i=0;i<=Charinfo_size(k);i++) { + ci = copy_charinfo(&font_tables[f]->charinfo[i]); + font_tables[k]->charinfo[i] = *ci; + } + + if (left_boundary(f)!= NULL ) { + ci = copy_charinfo(left_boundary(f)); + set_charinfo(k,left_boundarychar,ci); + } + + if (right_boundary(f)!= NULL ) { + ci = copy_charinfo(right_boundary(f)); + set_charinfo(k,right_boundarychar,ci); + } + return k; +} + +void delete_font (integer f) { + int i; + charinfo *co; + assert(f>0); + if (font_tables[f]!=NULL) { + set_font_name(f,NULL); + set_font_filename(f,NULL); + set_font_fullname(f,NULL); + set_font_encodingname(f,NULL); + set_font_area(f,NULL); + set_font_cidregistry(f,NULL); + set_font_cidordering(f,NULL); + set_left_boundary(f,NULL); + set_right_boundary(f,NULL); + + for(i=font_bc(f); i<=font_ec(f); i++) { + if (char_exists(f,i)) { + co = char_info(f,i); + set_charinfo_name(co,NULL); + set_charinfo_tounicode(co,NULL); + set_charinfo_packets(co,NULL); + set_charinfo_ligatures(co,NULL); + set_charinfo_kerns(co,NULL); + set_charinfo_extensible(co,0,0,0,0); + } + } + /* free .notdef */ + set_charinfo_name(font_tables[f]->charinfo+0,NULL); + free(font_tables[f]->charinfo); + destroy_sa_tree(font_tables[f]->characters); + + free(param_base(f)); + free(font_tables[f]); + font_tables[f] = NULL; + + if (font_id_maxval==f) { + font_id_maxval--; + } + } +} + +void +create_null_font (void) { + int i = new_font(); + assert(i==0); + set_font_name(i,xstrdup("nullfont")); + set_font_area(i,xstrdup("")); + set_font_touched(i,1); +} + +boolean +is_valid_font (integer id) { + int ret=0; + if (id>=0 && id<=font_id_maxval && font_tables[id]!=NULL) + ret=1; + return ret; +} + +/* return 1 == identical */ +boolean +cmp_font_name (integer id, strnumber t) { + char *tid , *tt; + if (!is_valid_font(id)) + return 0; + tt = makecstring(t); + tid = font_name(id); + if (tt == NULL && tid == NULL) + return 1; + if (tt == NULL || tid == NULL || strcmp(tid,tt)!=0) + return 0; + return 1; +} + +boolean +cmp_font_area (integer id, strnumber t) { + char *tt = NULL; + char *tid = font_area(id); + if (t == 0) { + if (tid == NULL || strlen(tid)==0) + return 1; + else + return 0; + } + tt = makecstring(t); + if ((tt == NULL || strlen(tt)==0) && (tid == NULL || strlen(tid)==0)) + return 1; + if (tt == NULL || strcmp(tid,tt)!=0) + return 0; + return 1; +} + + +static boolean +same_font_name (integer id, integer t) { + int ret = 0; + if (font_name(t) == NULL || + font_name(id) == NULL || + strcmp(font_name(t),font_name(id))!=0) { + ; + } else { + ret =1 ; + } + return ret; +} + +boolean +font_shareable (internal_font_number f, internal_font_number k) { + int ret = 0; + if (font_cidregistry(f) == NULL) { + if ( hasfmentry ( k ) + && ( font_map ( k ) == font_map ( f ) ) + && ( same_font_name ( k , f ) + || + ( pdf_font_auto_expand (f) + && ( pdf_font_blink (f) != 0 ) /* 0 = nullfont */ + && same_font_name ( k , pdf_font_blink (f) ) ) ) ) { + ret = 1; + } + } else { + if ((font_filename(k) != NULL && font_filename(f) != NULL && + strcmp(font_filename(k),font_filename(f)) == 0) + || + ( pdf_font_auto_expand (f) + && ( pdf_font_blink (f) != 0 ) /* 0 = nullfont */ + && same_font_name ( k , pdf_font_blink (f) ) ) ) { + ret = 1; + } + } + return ret; +} + +integer +test_no_ligatures (internal_font_number f) { + integer c; + for (c=font_bc(f);c<=font_ec(f);c++) { + if (has_lig(f,c)) /* char_exists(f,c) */ + return 0; + } + return 1; +} + +integer +get_tag_code (internal_font_number f, integer c) { + small_number i; + if (char_exists(f,c)) { + i = char_tag(f,c); + if (i==lig_tag) return 1; + else if (i==list_tag) return 2; + else if (i==ext_tag) return 4; + else return 0; + } + return -1; +} + +integer +get_lp_code (internal_font_number f, integer c) { + charinfo *ci = char_info(f,c); + return get_charinfo_lp(ci); +} + +integer +get_rp_code (internal_font_number f, integer c) { + charinfo *ci = char_info(f,c); + return get_charinfo_rp(ci); +} + +integer +get_ef_code (internal_font_number f, integer c) { + charinfo *ci = char_info(f,c); + return get_charinfo_ef(ci); +} + +void +set_tag_code (internal_font_number f, integer c, integer i) { + integer fixedi; + charinfo * co; + if (char_exists(f,c)) { + /* abs(fix_int(i-7,0)) */ + fixedi = - (i<-7 ? -7 : (i>0 ? 0 : i )) ; + co = char_info(f,c); + if (fixedi >= 4) { + if (char_tag(f,c) == ext_tag) + set_charinfo_tag(co,(char_tag(f,c)- ext_tag)); + fixedi = fixedi - 4; + } + if (fixedi >= 2) { + if (char_tag(f,c) == list_tag) + set_charinfo_tag(co,(char_tag(f,c)- list_tag)); + fixedi = fixedi - 2; + }; + if (fixedi >= 1) { + if (has_lig(f,c)) + set_charinfo_ligatures(co,NULL); + if (has_kern(f,c)) + set_charinfo_kerns(co,NULL); + } + } +} + + +void +set_lp_code(internal_font_number f, integer c, integer i) { + charinfo * co; + if (char_exists(f,c)) { + co = char_info(f,c); + set_charinfo_lp(co,i); + } +} + +void +set_rp_code(internal_font_number f, integer c, integer i) { + charinfo * co; + if (char_exists(f,c)) { + co = char_info(f,c); + set_charinfo_rp(co,i); + } +} + +void +set_ef_code(internal_font_number f, integer c, integer i) { + charinfo * co; + if (char_exists(f,c)) { + co = char_info(f,c); + set_charinfo_ef(co,i); + } +} + +void +set_no_ligatures (internal_font_number f) { + integer c; + charinfo * co; + + if (font_tables[f]->ligatures_disabled) + return; + + co = char_info(f,left_boundarychar); + set_charinfo_ligatures(co,NULL); + co = char_info(f,right_boundarychar); /* this is weird */ + set_charinfo_ligatures(co,NULL); + for (c=0;ccharinfo_count;c++) { + co = font_tables[f]->charinfo+c; + set_charinfo_ligatures(co,NULL); + } + font_tables[f]->ligatures_disabled =1; +} + +liginfo +get_ligature (internal_font_number f, integer lc, integer rc) { + liginfo t, u; + charinfo * co; + t.lig = 0; + t.type = 0; + t.adj = 0; + if (lc == non_boundarychar || rc == non_boundarychar || (!has_lig(f,lc)) ) + return t; + k = 0; + co = char_info(f,lc); + while (1) { + u = charinfo_ligature(co,k); + if (lig_end(u)) + break; + if (lig_char(u) == rc) { + if (lig_disabled(u)) { + return t; + } else { + return u; + } + } + k++; + } + return t; +} + + +scaled +get_kern(internal_font_number f, integer lc, integer rc) +{ + integer k; + kerninfo u; + charinfo * co; + if (lc == non_boundarychar || rc == non_boundarychar || (!has_kern(f,lc)) ) + return 0; + k = 0; + co = char_info(f,lc); + while (1) { + u = charinfo_kern(co,k); + if (kern_end(u)) + break; + if (kern_char(u) == rc) { + if (kern_disabled(u)) + return 0; + else + return kern_kern(u); + } + k++; + } + return 0; +} + + +/* dumping and undumping fonts */ + +#define dump_string(a) \ + if (a!=NULL) { \ + x = strlen(a)+1; \ + dump_int(x); dump_things(*a, x); \ + } else { \ + x = 0; dump_int(x); \ + } + +void +dump_charinfo (int f , int c) { + charinfo *co; + int x; + liginfo *lig; + kerninfo *kern; + + dump_int(c); + co = char_info(f,c); + set_charinfo_used(co,0); + dump_int(get_charinfo_width(co)); + dump_int(get_charinfo_height(co)); + dump_int(get_charinfo_depth(co)); + dump_int(get_charinfo_italic(co)); + dump_int(get_charinfo_tag(co)); + dump_int(get_charinfo_ef(co)); + dump_int(get_charinfo_rp(co)); + dump_int(get_charinfo_lp(co)); + dump_int(get_charinfo_remainder(co)); + dump_int(get_charinfo_used(co)); + dump_int(get_charinfo_index(co)); + dump_string(get_charinfo_name(co)); + dump_string(get_charinfo_tounicode(co)); + + /* ligatures */ + x = 0; + if ((lig = get_charinfo_ligatures(co)) != NULL) { + while (!lig_end(lig[x])) { x++; } + x++; + dump_int(x); dump_things(*lig, x); + } else { + dump_int(x); + } + /* kerns */ + x = 0; + if ((kern = get_charinfo_kerns(co)) != NULL) { + while (!kern_end(kern[x])) { x++; } + x++; + dump_int(x); dump_things(*kern, x); + } else { + dump_int(x); + } + /* packets */ + x= vf_packet_bytes(co); + dump_int(x); + if (x>0) { + dump_things(*get_charinfo_packets(co), x); + } + + if (get_charinfo_tag(co)==ext_tag) { + x = get_charinfo_extensible(co,EXT_TOP); dump_int(x); + x = get_charinfo_extensible(co,EXT_BOT); dump_int(x); + x = get_charinfo_extensible(co,EXT_MID); dump_int(x); + x = get_charinfo_extensible(co,EXT_REP); dump_int(x); + } +} + +void +dump_font (int f) { + int i,x; + + set_font_used(f,0); + font_tables[f]->charinfo_cache = NULL; + dump_things(*(font_tables[f]), 1); + dump_string(font_name(f)); + dump_string(font_area(f)); + dump_string(font_filename(f)); + dump_string(font_fullname(f)); + dump_string(font_encodingname(f)); + dump_string(font_cidregistry(f)); + dump_string(font_cidordering(f)); + + dump_things(*param_base(f),(font_params(f)+1)); + + if (has_left_boundary(f)) { + dump_int(1); dump_charinfo(f,left_boundarychar); + } else { + dump_int(0); + } + if (has_right_boundary(f)) { + dump_int(1); dump_charinfo(f,right_boundarychar); + } else { + dump_int(0); + } + + for(i=font_bc(f); i<=font_ec(f); i++) { + if (char_exists(f,i)) { + dump_charinfo(f,i); + } + } +} + +int +undump_charinfo (int f) { + charinfo *co; + int x,i; + char *s = NULL; + liginfo *lig = NULL; + kerninfo *kern = NULL; + real_eight_bits *packet = NULL; + int top = 0, bot = 0, mid = 0, rep = 0; + + undump_int(i); + co = get_charinfo(f,i); + undump_int(x); set_charinfo_width(co,x); + undump_int(x); set_charinfo_height(co,x); + undump_int(x); set_charinfo_depth(co,x); + undump_int(x); set_charinfo_italic(co,x); + undump_int(x); set_charinfo_tag(co,x); + undump_int(x); set_charinfo_ef(co,x); + undump_int(x); set_charinfo_rp(co,x); + undump_int(x); set_charinfo_lp(co,x); + undump_int(x); set_charinfo_remainder(co,x); + undump_int(x); set_charinfo_used(co,x); + undump_int(x); set_charinfo_index(co,x); + + /* name */ + undump_int (x); + if (x>0) { + font_bytes += x; + s = xmalloc(x); + undump_things(*s,x); + } + set_charinfo_name(co,s); + + /* tounicode */ + undump_int (x); + if (x>0) { + font_bytes += x; + s = xmalloc(x); + undump_things(*s,x); + } + set_charinfo_tounicode(co,s); + + /* ligatures */ + undump_int (x); + if (x>0) { + font_bytes += x*sizeof(liginfo); + lig = xmalloc(x*sizeof(liginfo)); + undump_things(*lig,x); + } + set_charinfo_ligatures(co,lig); + + /* kerns */ + undump_int (x); + if (x>0) { + font_bytes += x*sizeof(kerninfo); + kern = xmalloc(x*sizeof(kerninfo)); + undump_things(*kern,x); + } + set_charinfo_kerns(co,kern); + + /* packets */ + undump_int (x); + if (x>0) { + font_bytes += x; + packet = xmalloc(x); + undump_things(*packet,x); + } + set_charinfo_packets(co,packet); + + if (get_charinfo_tag(co)==ext_tag) { + undump_int(top); + undump_int(bot); + undump_int(mid); + undump_int(rep); + set_charinfo_extensible(co,top,bot,mid,rep); + } + return i; +} + +#define undump_font_string(a) undump_int (x); \ + if (x>0) { \ + font_bytes += x; \ + s = xmalloc(x); undump_things(*s,x); \ + a(f,s); } + + +void +undump_font(int f) +{ + int x, i; + texfont *tt; + charinfo *ci; + char *s; + grow_font_table (f); + font_tables[f] = NULL; + font_bytes += sizeof(texfont); + tt = xmalloc(sizeof(texfont)); + undump_things(*tt,1); + font_tables[f] = tt; + + undump_font_string(set_font_name); + undump_font_string(set_font_area); + undump_font_string(set_font_filename); + undump_font_string(set_font_fullname); + undump_font_string(set_font_encodingname); + undump_font_string(set_font_cidregistry); + undump_font_string(set_font_cidordering); + + i = sizeof(*param_base(f))*(font_params(f)+1); + font_bytes += i; + param_base(f) = xmalloc (i); + undump_things(*param_base(f), (font_params(f)+1)); + + font_tables[f]->_left_boundary = NULL; + undump_int(x); + if (x) { i = undump_charinfo(f); } /* left boundary */ + + font_tables[f]->_right_boundary = NULL; + undump_int(x); + if (x) { i = undump_charinfo(f); } /* right boundary */ + + + font_tables[f]->characters = new_sa_tree(1, 0); /* stack size 1, default item value 0 */ + ci = xcalloc(1,sizeof(charinfo)); + set_charinfo_name(ci,xstrdup(".notdef")); + font_tables[f]->charinfo = ci; + + i = font_bc(f); + while(i + + This file is part of LuaTeX. + + LuaTeX 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. + + LuaTeX 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 LuaTeX; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + $Id: texfont.h 1117 2008-03-21 15:26:12Z hhenkel $ */ + +/* Here we have the interface to LuaTeX's font system, as seen from the + main pascal program. There is a companion list in luatex.defines to + keep web2c happy */ + +/* this file is read at the end of ptexlib.h, which is called for at + the end of luatexcoerce.h, as well as from the C sources +*/ + +#ifndef TEXFONT_H +#define TEXFONT_H 1 + +#include "luatexdir/managed-sa.h" + +#define pointer halfword + +typedef struct liginfo { + integer adj; + integer lig; + char type; +} liginfo; + +typedef struct kerninfo { + integer adj; + scaled sc; +} kerninfo; + +typedef struct charinfo { + char *name; /* postscript character name */ + liginfo *ligatures; /* ligature items */ + kerninfo *kerns; /* kern items */ + real_eight_bits *packets; /* virtual commands. */ + integer *extensible; /* extensible recipe (if any) */ + unsigned short index; /* CID index */ + integer remainder; /* spare value for odd items, could be union-ed with extensible */ + scaled width; /* width */ + scaled height; /* height */ + scaled depth; /* depth */ + scaled italic; /* italic correction */ + integer ef; /* font expansion factor */ + integer lp; /* left protruding factor */ + integer rp; /* right protruding factor */ + char tag ; /* list / ext taginfo */ + char used ; /* char is typeset ? */ + char *tounicode; /* unicode equivalent */ +} charinfo; + + +/* this is for speed reasons, it is called from the web source + when more than two of the traditional four char values are needed + at the same time. the structure |charinfo_short| is defined in + web */ + +#ifndef luaTeX +typedef struct charinfo_short { + scaled ci_wd; /* width */ + scaled ci_ht; /* height */ + scaled ci_dp; /* depth */ +} charinfo_short; +#endif + + +extern charinfo_short char_info_short (internal_font_number f, integer c); + + + +typedef struct texfont { + integer _font_size ; + integer _font_dsize ; + char * _font_name ; + char * _font_area ; + char * _font_filename ; + char * _font_fullname ; + char * _font_encodingname ; + char * _font_cidregistry ; + char * _font_cidordering ; + integer _font_cidversion ; + integer _font_cidsupplement ; + + integer _font_ec ; + integer _font_checksum ; /* internal information */ + char _font_used ; /* internal information */ + char _font_touched ; /* internal information */ + integer _font_cache_id ; /* internal information */ + char _font_encodingbytes ; /* 1 or 2 bytes */ + integer _font_slant ; /* a slant in ppt */ + integer _font_extend ; /* an extension in ppt, or 0 */ + char _font_tounicode ; /* 1 if info is present */ + fm_entry_ptr _font_map; + integer _font_type; + integer _font_format; + integer _font_embedding; + integer _font_bc ; + integer _hyphen_char ; + integer _skew_char ; + integer _font_natural_dir; + + charinfo *_left_boundary; + charinfo *_right_boundary; + + integer _font_params; + scaled *_param_base; + + sa_tree characters; + integer charinfo_count; + integer charinfo_size; + charinfo *charinfo; + int *charinfo_cache; + integer ligatures_disabled; + + integer _pdf_font_num; /* maps to a PDF resource ID */ + scaled _pdf_font_size; /* maps to a PDF font size */ + internal_font_number _pdf_font_blink; /* link to base font for expanded fonts */ + internal_font_number _pdf_font_elink; /* link to expanded fonts for base font */ + integer _pdf_font_expand_ratio; /* expansion ratio of a particular font */ + internal_font_number _pdf_font_shrink; /* font at limit of shrinking */ + internal_font_number _pdf_font_stretch; /* font at limit of stretching */ + integer _pdf_font_step; /* amount of one step of expansion */ + boolean _pdf_font_auto_expand; /* this font is auto-expanded? */ + str_number _pdf_font_attr; /* pointer to additional attributes */ +} texfont; + +typedef enum { + unknown_font_type=0, /* new font (has not been used yet) */ + virtual_font_type, /* virtual font */ + real_font_type, /* real font */ +} font_types; + +typedef enum { + unknown_format=0, + type1_format, + type3_format, + truetype_format, + opentype_format, +} font_formats; + +typedef enum { + unknown_embedding=0, + no_embedding, + subset_embedding, + full_embedding, +} font_embedding_option; + +extern char *font_type_strings[]; +extern char *font_format_strings[]; +extern char *font_embedding_strings[]; + + +#define font_checksum(a) font_tables[a]->_font_checksum +#define set_font_checksum(a,b) font_checksum(a) = b + +#define font_check_0(a) ((font_tables[a]->_font_checksum&0xFF000000)>>24) +#define font_check_1(a) ((font_tables[a]->_font_checksum&0x00FF0000)>>16) +#define font_check_2(a) ((font_tables[a]->_font_checksum&0x0000FF00)>>8) +#define font_check_3(a) (font_tables[a]->_font_checksum&0x000000FF) + +#define font_size(a) font_tables[a]->_font_size +#define set_font_size(a,b) font_size(a) = b +#define font_dsize(a) font_tables[a]->_font_dsize +#define set_font_dsize(a,b) font_dsize(a) = b + +#define font_name(a) font_tables[a]->_font_name +#define get_font_name(a) (unsigned char *)font_name(a) +#define set_font_name(f,b) font_name(f) = b +#define tex_font_name(a) maketexstring(font_name(a)) + +boolean cmp_font_name (integer, strnumber); + +#define font_area(a) font_tables[a]->_font_area +#define get_font_area(a) (unsigned char *)font_area(a) +#define set_font_area(f,b) font_area(f) = b +#define tex_font_area(a) maketexstring(font_area(a)) + +boolean cmp_font_area (integer, strnumber); + +#define font_reassign(a,b) { if (a!=NULL) free(a); a = b; } + +#define font_filename(a) font_tables[a]->_font_filename +#define set_font_filename(f,b) font_reassign(font_filename(f),b) + +#define font_fullname(a) font_tables[a]->_font_fullname +#define set_font_fullname(f,b) font_reassign(font_fullname(f),b) + +#define font_encodingname(a) font_tables[a]->_font_encodingname +#define set_font_encodingname(f,b) font_reassign(font_encodingname(f),b) + +boolean font_shareable(internal_font_number,internal_font_number); + +#define cmp_font_filename(a,b) (!(font_filename(a)!=NULL || font_filename(b)!=NULL || \ + strcmp(font_filename(a),font_filename(b)))) +#define cmp_font_fullname(a,b) (!(font_fullname(a)!=NULL || font_fullname(b)!=NULL || \ + strcmp(font_fullname(a),font_fullname(b)))) +#define cmp_font_encodingname(a,b) (!(font_encoding(a)!=NULL || font_encodingname(b)!=NULL || \ + strcmp(font_encodingname(a),font_encodingname(b)))) + +#define font_bc(a) font_tables[a]->_font_bc +#define set_font_bc(f,b) font_bc(f) = b + +#define font_ec(a) font_tables[a]->_font_ec +#define set_font_ec(f,b) font_ec(f) = b + +#define font_used(a) (font_tables[a]!=NULL && font_tables[a]->_font_used) +#define set_font_used(a,b) font_tables[a]->_font_used = b + +#define font_touched(a) font_tables[a]->_font_touched +#define set_font_touched(a,b) font_touched(a) = b + +#define font_type(a) font_tables[a]->_font_type +#define set_font_type(a,b) { /* fprintf(stdout,"set font type of %s to %i: %s\n",font_name(a),b,__FILE__); */ \ + font_type(a) = b; } + +#define font_format(a) font_tables[a]->_font_format +#define font_format_name(a) font_format_strings[font_tables[a]->_font_format] +#define set_font_format(a,b) font_format(a) = b + +#define font_embedding(a) font_tables[a]->_font_embedding +#define set_font_embedding(a,b) font_embedding(a) = b + +#define font_cidversion(a) font_tables[a]->_font_cidversion +#define set_font_cidversion(a,b) font_cidversion(a) = b + +#define font_cidsupplement(a) font_tables[a]->_font_cidsupplement +#define set_font_cidsupplement(a,b) font_cidsupplement(a) = b + +#define font_cidordering(a) font_tables[a]->_font_cidordering +#define set_font_cidordering(f,b) font_reassign(font_cidordering(f),b) + +#define font_cidregistry(a) font_tables[a]->_font_cidregistry +#define set_font_cidregistry(f,b) font_reassign(font_cidregistry(f),b) + +#define font_map(a) font_tables[a]->_font_map +#define set_font_map(a,b) font_map(a) = b + +#define font_cache_id(a) font_tables[a]->_font_cache_id +#define set_font_cache_id(a,b) font_cache_id(a) = b + +#define font_encodingbytes(a) font_tables[a]->_font_encodingbytes +#define set_font_encodingbytes(a,b) font_encodingbytes(a) = b + +#define font_slant(a) font_tables[a]->_font_slant +#define set_font_slant(a,b) font_slant(a) = b + +#define font_extend(a) font_tables[a]->_font_extend +#define set_font_extend(a,b) font_extend(a) = b + +#define font_tounicode(a) font_tables[a]->_font_tounicode +#define set_font_tounicode(a,b) font_tounicode(a) = b + +#define hyphen_char(a) font_tables[a]->_hyphen_char +#define set_hyphen_char(a,b) hyphen_char(a) = b + +#define skew_char(a) font_tables[a]->_skew_char +#define set_skew_char(a,b) skew_char(a) = b + +#define font_natural_dir(a) font_tables[a]->_font_natural_dir +#define set_font_natural_dir(a,b) font_natural_dir(a) = b + +#define pdf_font_size(a) font_tables[a]->_pdf_font_size +#define set_pdf_font_size(a,b) pdf_font_size(a) = b + +#define pdf_font_num(a) font_tables[a]->_pdf_font_num +#define set_pdf_font_num(a,b) pdf_font_num(a) = b + +#define pdf_font_blink(a) font_tables[a]->_pdf_font_blink +#define set_pdf_font_blink(a,b) pdf_font_blink(a) = b + +#define pdf_font_elink(a) font_tables[a]->_pdf_font_elink +#define set_pdf_font_elink(a,b) pdf_font_elink(a) = b + +#define pdf_font_expand_ratio(a) font_tables[a]->_pdf_font_expand_ratio +#define set_pdf_font_expand_ratio(a,b) pdf_font_expand_ratio(a) = b + +#define pdf_font_shrink(a) font_tables[a]->_pdf_font_shrink +#define set_pdf_font_shrink(a,b) pdf_font_shrink(a) = b + +#define pdf_font_stretch(a) font_tables[a]->_pdf_font_stretch +#define set_pdf_font_stretch(a,b) pdf_font_stretch(a) = b + +#define pdf_font_step(a) font_tables[a]->_pdf_font_step +#define set_pdf_font_step(a,b) pdf_font_step(a) = b + +#define pdf_font_auto_expand(a) font_tables[a]->_pdf_font_auto_expand +#define set_pdf_font_auto_expand(a,b) pdf_font_auto_expand(a) = b + +#define pdf_font_attr(a) font_tables[a]->_pdf_font_attr +#define set_pdf_font_attr(a,b) pdf_font_attr(a) = b + + +#define left_boundarychar -1 +#define right_boundarychar -2 +#define non_boundarychar -3 + +#define left_boundary(a) font_tables[a]->_left_boundary +#define has_left_boundary(a) (left_boundary(a)!=NULL) +#define set_left_boundary(a,b) font_reassign(left_boundary(a),b) + +#define right_boundary(a) font_tables[a]->_right_boundary +#define has_right_boundary(a) (right_boundary(a)!=NULL) +#define set_right_boundary(a,b) font_reassign(right_boundary(a),b) + +#define font_bchar(a) (right_boundary(a)!=NULL ? right_boundarychar : non_boundarychar) + +/* font parameters */ + +#define font_params(a) font_tables[a]->_font_params +#define param_base(a) font_tables[a]->_param_base +#define font_param(a,b) font_tables[a]->_param_base[b] + +extern void set_font_params(internal_font_number f, int b); + +#define set_font_param(f,n,b) \ + { if (font_params(f)kerns[c] + +#define kern_char(b) (b).adj +#define kern_kern(b) (b).sc +#define kern_end(b) ((b).adj == end_kern) +#define kern_disabled(b) ((b).adj > end_kern) + +/* character ligatures */ + +#define end_ligature 0x7FFFFF /* otherchar value meaning "stop" */ +#define ignored_ligature 0x800000 /* otherchar value meaning "disabled" */ + +#define charinfo_ligature(b,c) b->ligatures[c] + +#define is_valid_ligature(a) ((a).type!=0) +#define lig_type(a) ((a).type>>1) +#define lig_char(a) (a).adj +#define lig_replacement(a) (a).lig +#define lig_end(a) (lig_char(a) == end_ligature) +#define lig_disabled(a) (lig_char(a) > end_ligature) + +#define no_tag 0 /* vanilla character */ +#define lig_tag 1 /* character has a ligature/kerning program */ +#define list_tag 2 /* character has a successor in a charlist */ +#define ext_tag 3 /* character is extensible */ + +extern scaled char_height (internal_font_number f, integer c); +extern scaled char_width (internal_font_number f, integer c); +extern scaled char_depth (internal_font_number f, integer c); +extern scaled char_italic (internal_font_number f, integer c); + +extern liginfo * char_ligatures (internal_font_number f, integer c); +extern kerninfo * char_kerns (internal_font_number f, integer c); +extern real_eight_bits * char_packets (internal_font_number f, integer c); + +#define has_lig(f,b) (char_exists(f,b) &&( char_ligatures(f,b) != NULL)) +#define has_kern(f,b) (char_exists(f,b) && (char_kerns(f,b) != NULL)) +#define has_packet(f,b) (char_exists(f,b) && (char_packets(f,b) != NULL)) + +extern integer char_remainder (internal_font_number f, integer c); +extern char char_tag (internal_font_number f, integer c); +extern char char_used (internal_font_number f, integer c); +extern char * char_name (internal_font_number f, integer c); +extern integer char_index (internal_font_number f, integer c); + +scaled get_kern(internalfontnumber f, integer lc, integer rc); +liginfo get_ligature(internalfontnumber f, integer lc, integer rc); + +#define EXT_TOP 0 +#define EXT_BOT 1 +#define EXT_MID 2 +#define EXT_REP 3 + +extern texfont **font_tables; + +integer new_font (void) ; +integer copy_font (integer id) ; +integer scale_font (integer id, integer atsize) ; +integer max_font_id (void); +void set_max_font_id (integer id); +integer new_font_id (void); +void create_null_font (void); +void delete_font(integer id); +boolean is_valid_font (integer id); + +void dump_font (int font_number); +void undump_font (int font_number); + +integer test_no_ligatures (internal_font_number f) ; +void set_no_ligatures (internal_font_number f) ; + +extern integer get_tag_code (internal_font_number f, integer c); +extern integer get_lp_code (internal_font_number f, integer c); +extern integer get_rp_code (internal_font_number f, integer c); +extern integer get_ef_code (internal_font_number f, integer c); + +extern void set_tag_code (internal_font_number f, integer c, integer i) ; +extern void set_lp_code(internal_font_number f, integer c, integer i) ; +extern void set_rp_code(internal_font_number f, integer c, integer i) ; +extern void set_ef_code(internal_font_number f, integer c, integer i) ; + +int read_tfm_info(internal_font_number f, char *nom, char *aire, scaled s); + + +/* from dofont.c */ + +extern int read_font_info (pointer u, strnumber nom, strnumber aire, scaled s, integer ndir); +extern int find_font_id (char *nom, char *aire, scaled s); + +/* for and from vfpacket.c */ + +#define scan_special 3 /* look into special text */ /* this is a hack */ + +typedef enum { packet_char_code, + packet_font_code, + packet_pop_code, + packet_push_code, + packet_special_code, + packet_right_code, + packet_down_code, + packet_rule_code, + packet_node_code, + packet_nop_code, + packet_end_code } packet_command_codes; + +extern scaled sqxfw (scaled sq, integer fw); + +extern void do_vf_packet (internal_font_number vf_f, integer c); +extern int vf_packet_bytes (charinfo *co); + +#endif diff --git a/Build/source/texk/web2c/luatexdir/font/tfmofm.c b/Build/source/texk/web2c/luatexdir/font/tfmofm.c new file mode 100644 index 00000000000..db82f94deba --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/font/tfmofm.c @@ -0,0 +1,1005 @@ +/* +Copyright (c) 1996-2006 Taco Hoekwater + +This file is part of LuaTeX. + +LuaTeX 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. + +LuaTeX 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 LuaTeX; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +$Id: tfmofm.c 1013 2008-02-14 00:09:02Z oneiros $ +*/ + +#include "ptexlib.h" + +#include "luatex-api.h" + +/* Here are some macros that help process ligatures and kerns */ + +#define lig_kern_start(f,c) char_remainder(f,c) +#define stop_flag 128 /* value indicating `\.{STOP}' in a lig/kern program */ +#define kern_flag 128 /* op code for a kern step */ + +#define skip_byte(z) lig_kerns[z].b0 +#define next_char(z) lig_kerns[z].b1 +#define op_byte(z) lig_kerns[z].b2 +#define rem_byte(z) lig_kerns[z].b3 +#define lig_kern_restart(c) (256*op_byte(c)+rem_byte(c)) + +/* + +The information in a \.{TFM} file appears in a sequence of 8-bit bytes. +Since the number of bytes is always a multiple of 4, we could +also regard the file as a sequence of 32-bit words, but \TeX\ uses the +byte interpretation. The format of \.{TFM} files was designed by +Lyle Ramshaw in 1980. The intent is to convey a lot of different kinds +@^Ramshaw, Lyle Harold@> +of information in a compact but useful form. + +$\Omega$ is capable of reading not only \.{TFM} files, but also +\.{OFM} files, which can describe fonts with up to 65536 characters +and with huge lig/kern tables. These fonts will often be virtual +fonts built up from real fonts with 256 characters, but $\Omega$ +is not aware of this. + +The documentation below describes \.{TFM} files, with slight additions +to show where \.{OFM} files differ. + */ +/* +@ The first 24 bytes (6 words) of a \.{TFM} file contain twelve 16-bit +integers that give the lengths of the various subsequent portions +of the file. These twelve integers are, in order: +$$\vbox{\halign{\hfil#&$\null=\null$#\hfil\cr +|lf|&length of the entire file, in words;\cr +|lh|&length of the header data, in words;\cr +|bc|&smallest character code in the font;\cr +|ec|&largest character code in the font;\cr +|nw|&number of words in the width table;\cr +|nh|&number of words in the height table;\cr +|nd|&number of words in the depth table;\cr +|ni|&number of words in the italic correction table;\cr +|nl|&number of words in the lig/kern table;\cr +|nk|&number of words in the kern table;\cr +|ne|&number of words in the extensible character table;\cr +|np|&number of font parameter words.\cr}}$$ +They are all nonnegative and less than $2^{15}$. We must have |bc-1<=ec<=255|, +and +$$\hbox{|lf=6+lh+(ec-bc+1)+nw+nh+nd+ni+nl+nk+ne+np|.}$$ +Note that a \.{TFM} font may contain as many as 256 characters +(if |bc=0| and |ec=255|), and as few as 0 characters (if |bc=ec+1|). + +Incidentally, when two or more 8-bit bytes are combined to form an integer of +16 or more bits, the most significant bytes appear first in the file. +This is called BigEndian order. +@!@^BigEndian order@> + +The first 52 bytes (13 words) of an \.{OFM} file contains thirteen +32-bit integers that give the lengths of the various subsequent +portions of the file. The first word is 0 (future versions of +\.{OFM} files could have different values; what is important is that +the first two bytes be 0 to differentiate \.{TFM} and \.{OFM} files). +The next twelve integers are as above, all nonegative and less +than~$2^{31}$. We must have |bc-1<=ec<=65535|, and +$$\hbox{|lf=13+lh+2*(ec-bc+1)+nw+nh+nd+ni+nl+nk+ne+np|.}$$ +Note that an \.{OFM} font may contain as many as 65536 characters +(if |bc=0| and |ec=65535|), and as few as 0 characters (if |bc=ec+1|). + +@ The rest of the \.{TFM} file may be regarded as a sequence of ten data +arrays having the informal specification +$$\def\arr$[#1]#2${\&{array} $[#1]$ \&{of} #2} +\vbox{\halign{\hfil\\{#}&$\,:\,$\arr#\hfil\cr +header&|[0..lh-1]@t\\{stuff}@>|\cr +char\_info&|[bc..ec]char_info_word|\cr +width&|[0..nw-1]fix_word|\cr +height&|[0..nh-1]fix_word|\cr +depth&|[0..nd-1]fix_word|\cr +italic&|[0..ni-1]fix_word|\cr +lig\_kern&|[0..nl-1]lig_kern_command|\cr +kern&|[0..nk-1]fix_word|\cr +exten&|[0..ne-1]extensible_recipe|\cr +param&|[1..np]fix_word|\cr}}$$ +The most important data type used here is a |@!fix_word|, which is +a 32-bit representation of a binary fraction. A |fix_word| is a signed +quantity, with the two's complement of the entire word used to represent +negation. Of the 32 bits in a |fix_word|, exactly 12 are to the left of the +binary point; thus, the largest |fix_word| value is $2048-2^{-20}$, and +the smallest is $-2048$. We will see below, however, that all but two of +the |fix_word| values must lie between $-16$ and $+16$. + +@ The first data array is a block of header information, which contains +general facts about the font. The header must contain at least two words, +|header[0]| and |header[1]|, whose meaning is explained below. +Additional header information of use to other software routines might +also be included, but \TeX82 does not need to know about such details. +For example, 16 more words of header information are in use at the Xerox +Palo Alto Research Center; the first ten specify the character coding +scheme used (e.g., `\.{XEROX text}' or `\.{TeX math symbols}'), the next five +give the font identifier (e.g., `\.{HELVETICA}' or `\.{CMSY}'), and the +last gives the ``face byte.'' The program that converts \.{DVI} files +to Xerox printing format gets this information by looking at the \.{TFM} +file, which it needs to read anyway because of other information that +is not explicitly repeated in \.{DVI}~format. + +\yskip\hang|header[0]| is a 32-bit check sum that \TeX\ will copy into +the \.{DVI} output file. Later on when the \.{DVI} file is printed, +possibly on another computer, the actual font that gets used is supposed +to have a check sum that agrees with the one in the \.{TFM} file used by +\TeX. In this way, users will be warned about potential incompatibilities. +(However, if the check sum is zero in either the font file or the \.{TFM} +file, no check is made.) The actual relation between this check sum and +the rest of the \.{TFM} file is not important; the check sum is simply an +identification number with the property that incompatible fonts almost +always have distinct check sums. +@^check sum@> + +\yskip\hang|header[1]| is a |fix_word| containing the design size of +the font, in units of \TeX\ points. This number must be at least 1.0; it is +fairly arbitrary, but usually the design size is 10.0 for a ``10 point'' +font, i.e., a font that was designed to look best at a 10-point size, +whatever that really means. When a \TeX\ user asks for a font +`\.{at} $\delta$ \.{pt}', the effect is to override the design size +and replace it by $\delta$, and to multiply the $x$ and~$y$ coordinates +of the points in the font image by a factor of $\delta$ divided by the +design size. {\sl All other dimensions in the\/ \.{TFM} file are +|fix_word|\kern-1pt\ numbers in design-size units}, with the exception of +|param[1]| (which denotes the slant ratio). Thus, for example, the value +of |param[6]|, which defines the \.{em} unit, is often the |fix_word| value +$2^{20}=1.0$, since many fonts have a design size equal to one em. +The other dimensions must be less than 16 design-size units in absolute +value; thus, |header[1]| and |param[1]| are the only |fix_word| +entries in the whole \.{TFM} file whose first byte might be something +besides 0 or 255. + +@ Next comes the |char_info| array, which contains one |@!char_info_word| +per character. Each word in this part of a \.{TFM} file contains six fields +packed into four bytes as follows. + +\yskip\hang first byte: |@!width_index| (8 bits)\par +\hang second byte: |@!height_index| (4 bits) times 16, plus |@!depth_index| + (4~bits)\par +\hang third byte: |@!italic_index| (6 bits) times 4, plus |@!tag| + (2~bits)\par +\hang fourth byte: |@!remainder| (8 bits)\par +\yskip\noindent +The actual width of a character is \\{width}|[width_index]|, in design-size +units; this is a device for compressing information, since many characters +have the same width. Since it is quite common for many characters +to have the same height, depth, or italic correction, the \.{TFM} format +imposes a limit of 16 different heights, 16 different depths, and +64 different italic corrections. + +For \.{OFM} files, two words (eight bytes) are used. +The arrangement is as follows. + +\yskip\hang first and second bytes: |@!width_index| (16 bits)\par +\hang third byte: |@!height_index| (8 bits)\par +\hang fourth byte: |@!depth_index| (8~bits)\par +\hang fifth and sixth bytes: +|@!italic_index| (14 bits) times 4, plus |@!tag| (2~bits)\par +\hang seventh and eighth bytes: |@!remainder| (16 bits)\par +\yskip\noindent +Therefore the \.{OFM} format imposes a limit of 256 different heights, +256 different depths, and 16384 different italic corrections. + +@!@^italic correction@> +The italic correction of a character has two different uses. +(a)~In ordinary text, the italic correction is added to the width only if +the \TeX\ user specifies `\.{\\/}' after the character. +(b)~In math formulas, the italic correction is always added to the width, +except with respect to the positioning of subscripts. + +Incidentally, the relation $\\{width}[0]=\\{height}[0]=\\{depth}[0]= +\\{italic}[0]=0$ should always hold, so that an index of zero implies a +value of zero. The |width_index| should never be zero unless the +character does not exist in the font, since a character is valid if and +only if it lies between |bc| and |ec| and has a nonzero |width_index|. +*/ + + /* +@ \TeX\ checks the information of a \.{TFM} file for validity as the +file is being read in, so that no further checks will be needed when +typesetting is going on. The somewhat tedious subroutine that does this +is called |read_font_info|. It has four parameters: the user font +identifier~|u|, the file name and area strings |nom| and |aire|, and the +``at'' size~|s|. If |s|~is negative, it's the negative of a scale factor +to be applied to the design size; |s=-1000| is the normal case. +Otherwise |s| will be substituted for the design size; in this +case, |s| must be positive and less than $2048\rm\,pt$ +(i.e., it must be less than $2^{27}$ when considered as an integer). + +The subroutine opens and closes a global file variable called |tfm_file|. +It returns the value of the internal font number that was just loaded. +If an error is detected, an error message is issued and no font +information is stored; |null_font| is returned in this case. + +@d bad_tfm=11 {label for |read_font_info|} +@d abort==goto bad_tfm {do this when the \.{TFM} data is wrong} + +*/ + +/* +The |tag| field in a |char_info_word| has four values that explain how to +interpret the |remainder| field. + +\yskip\hangg|tag=0| (|no_tag|) means that |remainder| is unused.\par +\hangg|tag=1| (|lig_tag|) means that this character has a ligature/kerning +program starting at position |remainder| in the |lig_kern| array.\par +\hangg|tag=2| (|list_tag|) means that this character is part of a chain of +characters of ascending sizes, and not the largest in the chain. The +|remainder| field gives the character code of the next larger character.\par +\hangg|tag=3| (|ext_tag|) means that this character code represents an +extensible character, i.e., a character that is built up of smaller pieces +so that it can be made arbitrarily large. The pieces are specified in +|@!exten[remainder]|.\par +\yskip\noindent +Characters with |tag=2| and |tag=3| are treated as characters with |tag=0| +unless they are used in special circumstances in math formulas. For example, +the \.{\\sum} operation looks for a |list_tag|, and the \.{\\left} +operation looks for both |list_tag| and |ext_tag|. +*/ + +/* The |lig_kern| array contains instructions in a simple programming language +that explains what to do for special letter pairs. Each word in this array, +in a \.{TFM} file, is a |@!lig_kern_command| of four bytes. + +\yskip\hang first byte: |skip_byte|, indicates that this is the final program + step if the byte is 128 or more, otherwise the next step is obtained by + skipping this number of intervening steps.\par +\hang second byte: |next_char|, ``if |next_char| follows the current character, + then perform the operation and stop, otherwise continue.''\par +\hang third byte: |op_byte|, indicates a ligature step if less than~128, + a kern step otherwise.\par +\hang fourth byte: |remainder|.\par +\yskip\noindent +In an \.{OFM} file, eight bytes are used, two bytes for each field. + +In a kern step, an +additional space equal to |kern[256*(op_byte-128)+remainder]| is inserted +between the current character and |next_char|. This amount is +often negative, so that the characters are brought closer together +by kerning; but it might be positive. + +There are eight kinds of ligature steps, having |op_byte| codes $4a+2b+c$ where +$0\le a\le b+c$ and $0\le b,c\le1$. The character whose code is +|remainder| is inserted between the current character and |next_char|; +then the current character is deleted if $b=0$, and |next_char| is +deleted if $c=0$; then we pass over $a$~characters to reach the next +current character (which may have a ligature/kerning program of its own). + +If the very first instruction of the |lig_kern| array has |skip_byte=255|, +the |next_char| byte is the so-called right boundary character of this font; +the value of |next_char| need not lie between |bc| and~|ec|. +If the very last instruction of the |lig_kern| array has |skip_byte=255|, +there is a special ligature/kerning program for a left boundary character, +beginning at location |256*op_byte+remainder|. +The interpretation is that \TeX\ puts implicit boundary characters +before and after each consecutive string of characters from the same font. +These implicit characters do not appear in the output, but they can affect +ligatures and kerning. + +If the very first instruction of a character's |lig_kern| program has +|skip_byte>128|, the program actually begins in location +|256*op_byte+remainder|. This feature allows access to large |lig_kern| +arrays, because the first instruction must otherwise +appear in a location |<=255| in a \.{TFM} file, |<=65535| in an \.{OFM} file. + +Any instruction with |skip_byte>128| in the |lig_kern| array must satisfy +the condition +$$\hbox{|256*op_byte+remainder=0|, unless $M$ is absent; +in the latter case we can have $TR^kB$ for both even and odd values of~|k|. +The width of the extensible character is the width of $R$; and the +height-plus-depth is the sum of the individual height-plus-depths of the +components used, since the pieces are butted together in a vertical list. +*/ + +/* +The final portion of a \.{TFM} file is the |param| array, which is another +sequence of |fix_word| values. + +\yskip\hang|param[1]=slant| is the amount of italic slant, which is used +to help position accents. For example, |slant=.25| means that when you go +up one unit, you also go .25 units to the right. The |slant| is a pure +number; it's the only |fix_word| other than the design size itself that is +not scaled by the design size. + +\hang|param[2]=space| is the normal spacing between words in text. +Note that character |" "| in the font need not have anything to do with +blank spaces. + +\hang|param[3]=space_stretch| is the amount of glue stretching between words. + +\hang|param[4]=space_shrink| is the amount of glue shrinking between words. + +\hang|param[5]=x_height| is the size of one ex in the font; it is also +the height of letters for which accents don't have to be raised or lowered. + +\hang|param[6]=quad| is the size of one em in the font. + +\hang|param[7]=extra_space| is the amount added to |param[2]| at the +ends of sentences. + +\yskip\noindent +If fewer than seven parameters are present, \TeX\ sets the missing parameters +to zero. Fonts used for math symbols are required to have +additional parameter information, which is explained later. +*/ + +/* + There are programs called \.{TFtoPL} and \.{PLtoTF} that convert + between the \.{TFM} format and a symbolic property-list format + that can be easily edited. These programs contain extensive + diagnostic information, so \TeX\ does not have to bother giving + precise details about why it rejects a particular \.{TFM} file. + +*/ + +#define tfm_abort { font_tables[f]->_font_name = NULL; \ + font_tables[f]->_font_area = NULL; \ + xfree(tfm_buffer); xfree(kerns); \ + xfree(widths); xfree(heights); xfree(depths); \ + xfree(italics); xfree(extens); xfree(lig_kerns); \ + xfree(xligs); xfree(xkerns); \ + return 0; } + +#define tfm_success { xfree(tfm_buffer); xfree(kerns); \ + xfree(widths); xfree(heights); xfree(depths); \ + xfree(italics); xfree(extens); xfree(lig_kerns); \ + xfree(xligs); xfree(xkerns); return 1; } + + +int +open_tfm_file(char *nom, char *aire, unsigned char **tfm_buf, integer *tfm_siz) { + boolean res; /* was the callback successful? */ + boolean opened; /* was |tfm_file| successfully opened?*/ + integer callback_id; + FILE *tfm_file; + /* packfilename(nom,aire,getnullstr()); */ + if(nameoffile != NULL) + xfree(nameoffile); + nameoffile = malloc(strlen(nom)+2); + strcpy(stringcast(nameoffile+1),nom); + namelength = strlen(nom); + callback_id=callback_defined(read_font_file_callback); + if (callback_id>0) { + res = run_callback(callback_id,"S->bSd",stringcast(nameoffile+1), + &opened, tfm_buf, tfm_siz); + if (res && opened && (*tfm_siz>0)) { + return 1; + } + if (!opened) + return -1; + } else { + if (ofm_open_in(tfm_file)) { + res = read_tfm_file(tfm_file,tfm_buf,tfm_siz); + b_close(tfm_file); + if (res) { + return 1; + } + } else { + return -1; + } + } + return 0; +} + + +/* + Note: A malformed \.{TFM} file might be shorter than it claims to be; + thus |eof(tfm_file)| might be true when |read_font_info| refers to + |tfm_file^| or when it says |get(tfm_file)|. If such circumstances + cause system error messages, you will have to defeat them somehow, + for example by defining |fget| to be `\ignorespaces|begin get(tfm_file);| + |if eof(tfm_file) then abort; end|\unskip'. + @^system dependencies@> +*/ + +#define fget tfm_byte++ +#define fbyte tfm_buffer[tfm_byte] + +#define read_sixteen(a) \ + { a=tfm_buffer[tfm_byte++]; \ + if (a>127) { tfm_abort; } \ + a=(a*256)+tfm_buffer[tfm_byte]; } + +#define read_sixteen_unsigned(a) \ + { a=tfm_buffer[tfm_byte++]; \ + a=(a*256)+tfm_buffer[tfm_byte]; } + +#define read_thirtytwo(a) \ + { a=tfm_buffer[++tfm_byte]; \ + if (a>127) { tfm_abort; } \ + a=(a*256)+tfm_buffer[++tfm_byte]; \ + a=(a*256)+tfm_buffer[++tfm_byte]; \ + a=(a*256)+tfm_buffer[++tfm_byte]; } + +#define store_four_bytes(z) \ + { a=tfm_buffer[++tfm_byte]; \ + a=(a*256)+tfm_buffer[++tfm_byte]; \ + a=(a*256)+tfm_buffer[++tfm_byte]; \ + a=(a*256)+tfm_buffer[++tfm_byte]; \ + z = a; } + +#define store_char_info(z) \ + { if (font_level!=-1) { \ + fget; read_sixteen_unsigned(a); \ + ci._width_index=a; \ + fget; read_sixteen_unsigned(b); \ + ci._height_index=b>>8; \ + ci._depth_index=b%256; \ + fget; read_sixteen_unsigned(c); \ + ci._italic_index=c>>8; \ + ci._tag=c%4; \ + fget; read_sixteen_unsigned(d); \ + ci._remainder=d; \ + } else { \ + a=tfm_buffer[++tfm_byte]; \ + ci._width_index=a; \ + b=tfm_buffer[++tfm_byte]; \ + ci._height_index=b>>4; \ + ci._depth_index=b%16; \ + c=tfm_buffer[++tfm_byte]; \ + ci._italic_index=c>>2; \ + ci._tag=c%4; \ + d=tfm_buffer[++tfm_byte]; \ + ci._remainder=d; \ + } } + +#define read_four_quarters(q) \ + { if (font_level!=-1) { \ + fget; read_sixteen_unsigned(a); q.b0=a; \ + fget; read_sixteen_unsigned(b); q.b1=b; \ + fget; read_sixteen_unsigned(c); q.b2=c; \ + fget; read_sixteen_unsigned(d); q.b3=d; \ + } else { \ + a=tfm_buffer[++tfm_byte]; q.b0=a; \ + b=tfm_buffer[++tfm_byte]; q.b1=b; \ + c=tfm_buffer[++tfm_byte]; q.b2=c; \ + d=tfm_buffer[++tfm_byte]; q.b3=d; \ + } } + +#define check_byte_range(z) { if ((zec)) tfm_abort ; } + + +/* A |fix_word| whose four bytes are $(a,b,c,d)$ from left to right represents + the number + $$x=\left\{\vcenter{\halign{$#$,\hfil\qquad&if $#$\hfil\cr + b\cdot2^{-4}+c\cdot2^{-12}+d\cdot2^{-20}&a=0;\cr + -16+b\cdot2^{-4}+c\cdot2^{-12}+d\cdot2^{-20}&a=255.\cr}}\right.$$ + (No other choices of |a| are allowed, since the magnitude of a number in + design-size units must be less than 16.) We want to multiply this + quantity by the integer~|z|, which is known to be less than $2^{27}$. + If $|z|<2^{23}$, the individual multiplications $b\cdot z$, + $c\cdot z$, $d\cdot z$ cannot overflow; otherwise we will divide |z| by 2, + 4, 8, or 16, to obtain a multiplier less than $2^{23}$, and we can + compensate for this later. If |z| has thereby been replaced by + $|z|^\prime=|z|/2^e$, let $\beta=2^{4-e}$; we shall compute + $$\lfloor(b+c\cdot2^{-8}+d\cdot2^{-16})\,z^\prime/\beta\rfloor$$ + if $a=0$, or the same quantity minus $\alpha=2^{4+e}z^\prime$ if $a=255$. + This calculation must be done exactly, in order to guarantee portability + of \TeX\ between computers. +*/ + +#define store_scaled(zz) \ + { fget; a=fbyte; fget; b=fbyte; \ + fget; c=fbyte; fget; d=fbyte; \ + sw=(((((d*z)>>8)+(c*z))>>8)+(b*z)) / beta; \ + if (a==0) { zz=sw; } else if (a==255) { zz=sw-alpha; } else tfm_abort; \ + } + +#define check_existence(z) \ + { check_byte_range(z); \ + if (!char_exists(f,z)) tfm_abort; \ + } + +typedef struct tfmcharacterinfo { + integer _kern_index; + integer _lig_index; + integer _width_index; + integer _height_index; + integer _depth_index; + integer _italic_index; + integer _remainder; + unsigned char _tag ; +} tfmcharacterinfo; + +extern charinfo *copy_charinfo(charinfo *ci); + +int +read_tfm_info(internalfontnumber f, char *cnom, char *caire, scaled s) { + integer k; /* index into |font_info| */ + halfword lf,lh,bc,ec,nw,nh,nd,ni,nl,nk,ne,np,slh; /* sizes of subfiles */ + scaled *widths, *heights, *depths, *italics, *kerns; + halfword font_dir; + integer a,b,c,d; /* byte variables */ + integer i; /* counter */ + integer font_level,header_length; + integer nco,ncw,npc,nlw,neew; + tfmcharacterinfo ci; + charinfo *co; + four_quarters qw; + four_quarters *lig_kerns, *extens; + scaled sw; /* accumulators */ + integer bch_label; /* left boundary start location, or infinity */ + int bchar; /* :0..too_big_char; */ /* right boundary character, or |too_big_char| */ + integer first_two; + scaled z; /* the design size or the ``at'' size */ + integer alpha; + char beta; /* :1..16*/ + integer *xligs, *xkerns; /* aux. for ligkern processing */ + liginfo *cligs; + kerninfo *ckerns; + int fligs, fkerns; + char *tmpnam; + integer tfm_byte = 0; /* index into |tfm_buffer| */ + integer saved_tfm_byte = 0; /* saved index into |tfm_buffer| */ + unsigned char *tfm_buffer = NULL; /* byte buffer for tfm files */ + integer tfm_size = 0; /* total size of the tfm file */ + + widths=NULL; + heights=NULL; + depths = NULL; + italics = NULL; + kerns = NULL; + lig_kerns = NULL; + extens = NULL; + xkerns = NULL; + ckerns = NULL; + xligs = NULL; + cligs = NULL; + + font_dir = 0; + + memset(&ci,0,sizeof(tfmcharacterinfo)); + + if(open_tfm_file(cnom,caire,&tfm_buffer,&tfm_size)!=1) + tfm_abort; + + /* cnom can be an absolute filename, xbasename() fixes that. */ + + tmpnam=strdup(xbasename(cnom)); + if (strcmp(tmpnam+strlen(tmpnam)-4,".tfm")==0) { + *(tmpnam+strlen(tmpnam)-4) =0; + } + set_font_name(f,tmpnam); + set_font_area(f,xstrdup(caire)); /* perhaps it leaks, but it doesnt crash */ + + /* @; */ + nco=0; ncw=0; npc=0; + read_sixteen(first_two); + if (first_two!=0) { + font_level=-1; + lf=first_two; + fget; read_sixteen(lh); + fget; read_sixteen(bc); + fget; read_sixteen(ec); + if ((bc>ec+1)||(ec>255)) tfm_abort; + if (bc>255) { /* |bc=256| and |ec=255| */ + bc=1; ec=0; + }; + fget; read_sixteen(nw); + fget; read_sixteen(nh); + fget; read_sixteen(nd); + fget; read_sixteen(ni); + fget; read_sixteen(nl); + fget; read_sixteen(nk); + fget; read_sixteen(ne); + fget; read_sixteen(np); + header_length=6; + ncw=(ec-bc+1); + nlw=nl; + neew=ne; + } else { + fget; read_sixteen(font_level); + if (font_level!=0) tfm_abort; + read_thirtytwo(lf); + read_thirtytwo(lh); + read_thirtytwo(bc); + read_thirtytwo(ec); + if ((bc>ec+1)||(ec>65535)) tfm_abort; + if (bc>65535) { /* |bc=65536| and |ec=65535| */ + bc=1; ec=0; + }; + read_thirtytwo(nw); + read_thirtytwo(nh); + read_thirtytwo(nd); + read_thirtytwo(ni); + read_thirtytwo(nl); + read_thirtytwo(nk); + read_thirtytwo(ne); + read_thirtytwo(np); + read_thirtytwo(font_dir); /* junk */ + nlw=2*nl; + neew=2*ne; + header_length=14; + ncw=2*(ec-bc+1); + }; + if (lf!=(header_length+lh+ncw+nw+nh+nd+ni+nlw+nk+neew+np)) tfm_abort; + + /* @; */ + + set_font_natural_dir(f,font_dir); + set_font_bc(f,bc); + set_font_ec(f,ec); + + /* read the arrays first */ + widths = xmalloc(nw*sizeof(scaled)); + heights = xmalloc(nh*sizeof(scaled)); + depths = xmalloc(nd*sizeof(scaled)); + italics = xmalloc(ni*sizeof(scaled)); + extens = xmalloc(ne*sizeof(four_quarters)); + lig_kerns = xmalloc(nl*sizeof(four_quarters)); + kerns = xmalloc(nk*sizeof(scaled)); + + /* @; */ + + /* Only the first two words of the header are needed by \TeX82. */ + slh = lh; + if (lh<2) + tfm_abort; + store_four_bytes(font_checksum(f)); + fget; read_sixteen(z); /* this rejects a negative design size */ + fget; z=z*256+fbyte; fget; z=(z*16)+(fbyte>>4); + if (z2) { + fget;fget;fget;fget; + lh--; /* ignore the rest of the header */ + }; + + /* read the arrays before the character info */ + + set_font_dsize(f,z); + if (s!=-1000) { + z = (s>=0 ? s : xn_over_d(z,-s,1000)); + } + set_font_size(f,z); + + if (np>7) + set_font_params(f,np); + + saved_tfm_byte = tfm_byte; + tfm_byte = (header_length+slh+ncw)*4 - 1; + + /* @; */ + + alpha=16; + while (z>=040000000) { + z=z>>1; alpha=alpha+alpha; + }; + beta=256/alpha; alpha=alpha*z; + + /* @; */ + + for (k=0;k; */ + + bch_label=nl; /* infinity*/ + bchar=65536; + if (nl>0) { + for (k=0;k128) { + if (256*c+d>=nl) tfm_abort; + if (a==255 && k==0) bchar=b; + } else { + /* if (b!=bchar) check_existence(b); */ + if (c<128) { + /* check_existence(d); */ /* check ligature */ + } else if (256*(c-128)+d>=nk) { + tfm_abort; /* check kern */ + } + if ((a<128) && (k-0+a+1>=nl)) tfm_abort; + }; + }; + if (a==255) bch_label=256*c+d; + }; + + /* the actual kerns */ + for (k=0;k; */ + for (k=0;k; */ + + if (np>7) { + set_font_params(f,np); + } + for (k=1;k<=np;k++) { + if (k==1) { /* the |slant| parameter is a pure number */ + fget; sw=fbyte; + if (sw>127) sw=sw-256; + fget; sw=sw*256+fbyte; + fget; sw=sw*256+fbyte; + fget; sw=(sw*16)+(fbyte>>4); + set_font_param(f,k,sw); + } else { + store_scaled(font_param(f,k)); + } + } + + /* + We check to see that the \.{TFM} file doesn't end prematurely; but + no error message is given for files having more than |lf| words. + */ + + if (tfm_byte stop_flag) + k = lig_kern_restart(k); + */ + while (1) { + if (skip_byte(k) <= stop_flag) { + if(op_byte(k) >= kern_flag) { /* kern */ + fkerns++; + } else { /* lig */ + fligs++; + } + } + if (skip_byte(k) == 0) { + k++; + } else { + if (skip_byte(k) >= stop_flag) + break; + k += skip_byte(k) + 1; + } + } + } + if (fkerns >0 || fligs > 0) { + if (fligs>0) cligs = xcalloc((fligs+1),sizeof(liginfo)); + if (fkerns>0) ckerns = xcalloc((fkerns+1),sizeof(kerninfo)); + fligs = 0; + fkerns = 0; + k = bch_label; + /* + if (skip_byte(k) > stop_flag) + k = lig_kern_restart(k); + */ + while (1) { + if (skip_byte(k) <= stop_flag) { + if(op_byte(k) >= kern_flag) { /* kern */ + set_kern_item(ckerns[fkerns],next_char(k),kerns[256*(op_byte(k)-128)+rem_byte(k)]); + fkerns++; + } else { /* lig */ + set_ligature_item(cligs[fligs],(op_byte(k)*2+1),next_char(k),rem_byte(k)); + fligs++; + } + } + if (skip_byte(k) == 0) { + k++; + } else { + if (skip_byte(k) >= stop_flag) + break; + k += skip_byte(k) + 1; + } + } + if (fkerns>0 || fligs>0){ + co = get_charinfo(f,left_boundarychar); + if (fkerns>0) { + set_kern_item(ckerns[fkerns],end_kern,0); + fkerns++; + set_charinfo_kerns(co,ckerns); + } + if (fligs>0){ + set_ligature_item(cligs[fligs],0,end_ligature,0); + fligs++; + set_charinfo_ligatures(co,cligs); + } + set_charinfo_remainder(co,0); + } + } + + /* @; */ + for (k=bc;k<=ec;k++) { + store_char_info(k); + if (ci._width_index==0) + continue; + if (ci._width_index>=nw||ci._height_index>=nh|| + ci._depth_index>=nd||ci._italic_index>=ni) tfm_abort; + d = ci._remainder; + switch (ci._tag) { + case lig_tag: if (d>=nl) tfm_abort; break; + case ext_tag: if (d>=ne) tfm_abort; break; + case list_tag: + /* We want to make sure that there is no cycle of characters linked together + by |list_tag| entries, since such a cycle would get \TeX\ into an endless + loop. If such a cycle exists, the routine here detects it when processing + the largest character code in the cycle. + */ + check_byte_range(d); + while (d stop_flag) + k = lig_kern_restart(k); + /* now k is the start index */ + while (1) { + if (skip_byte(k) <= stop_flag) { + if(op_byte(k) >= kern_flag) { /* kern */ + xkerns[i]++; + if (next_char(k) == bchar) + xkerns[i]++; + } else { /* lig */ + xligs[i]++; + if (next_char(k) == bchar) + xligs[i]++; + } + } + if (skip_byte(k) == 0) { + k++; + } else { + if (skip_byte(k) >= stop_flag) + break; + k += skip_byte(k) + 1; + } + } + } + } + + cligs = NULL; + ckerns = NULL; + + for (i=bc;i<=ec;i++) { + fligs = 0; + fkerns = 0; + if (char_tag(f,i) == lig_tag) { + k = lig_kern_start(f,i); + if (skip_byte(k) > stop_flag) + k = lig_kern_restart(k); + /* now k is the start index */ + if (xligs[i]>0) cligs = xcalloc((xligs[i]+1),sizeof(liginfo)); + if (xkerns[i]>0) ckerns = xcalloc((xkerns[i]+1),sizeof(kerninfo)); + while (1) { + if (skip_byte(k) <= stop_flag) { + if(op_byte(k) >= kern_flag) { /* kern */ + if (next_char(k) == bchar) { + set_kern_item(ckerns[fkerns],right_boundarychar,kerns[256*(op_byte(k)-128)+rem_byte(k)]); + fkerns++; + } + set_kern_item(ckerns[fkerns],next_char(k),kerns[256*(op_byte(k)-128)+rem_byte(k)]); + fkerns++; + } else { /* lig */ + if (next_char(k) == bchar) { + set_ligature_item(cligs[fligs],(op_byte(k)*2+1),right_boundarychar,rem_byte(k)); + fligs++; + } + set_ligature_item(cligs[fligs],(op_byte(k)*2+1),next_char(k),rem_byte(k)); + fligs++; + } + } + if (skip_byte(k) == 0) { + k++; + } else { + if (skip_byte(k) >= stop_flag) + break; + k += skip_byte(k) + 1; + } + } + if (fkerns>0 || fligs>0){ + co = get_charinfo(f,i); + if (fkerns>0) { + set_kern_item(ckerns[fkerns],end_kern,0); + fkerns++; + set_charinfo_kerns(co,ckerns); + } + if (fligs>0){ + set_ligature_item(cligs[fligs],0,end_ligature,0); + fligs++; + set_charinfo_ligatures(co,cligs); + } + set_charinfo_remainder(co,0); + } + } + } + + + /* @ */ + + /* Now to wrap it up, we have checked all the necessary things about the \.{TFM} + file, and all we need to do is put the finishing touches on the data for + the new font. + */ + + if (bchar!= 65536) { + co = copy_charinfo(char_info(f,bchar)); + set_right_boundary(f,co); + } + + tfm_success; +} + diff --git a/Build/source/texk/web2c/luatexdir/font/tounicode.c b/Build/source/texk/web2c/luatexdir/font/tounicode.c new file mode 100644 index 00000000000..ff86a8512e2 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/font/tounicode.c @@ -0,0 +1,604 @@ +/* +Copyright (c) 2006 Han The Thanh, + +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 +*/ + +#include "ptexlib.h" + +#define isXdigit(c) (isdigit(c) || ('A' <= (c) && (c) <= 'F')) +#define UNI_UNDEF -1 +#define UNI_STRING -2 /* string allocated by def_tounicode() */ +#define UNI_EXTRA_STRING -3 /* string allocated by set_glyph_unicode() */ + +static struct avl_table *glyph_unicode_tree = NULL; + +static int comp_glyph_unicode_entry(const void *pa, const void *pb, void *p) +{ + return strcmp(((const glyph_unicode_entry *) pa)->name, + ((const glyph_unicode_entry *) pb)->name); +} + +static glyph_unicode_entry *new_glyph_unicode_entry(void) +{ + glyph_unicode_entry *e; + e = xtalloc(1, glyph_unicode_entry); + e->name = NULL; + e->code = UNI_UNDEF; + e->unicode_seq = NULL; + return e; +} + +static void destroy_glyph_unicode_entry(void *pa, void *pb) +{ + glyph_unicode_entry *e = (glyph_unicode_entry *) pa; + xfree(e->name); + if (e->code == UNI_STRING) { + assert(e->unicode_seq != NULL); + xfree(e->unicode_seq); + } +} + +void glyph_unicode_free(void) +{ + if (glyph_unicode_tree != NULL) + avl_destroy(glyph_unicode_tree, destroy_glyph_unicode_entry); +} + +void def_tounicode(strnumber glyph, strnumber unistr) +{ + char buf[SMALL_BUF_SIZE], *p; + char buf2[SMALL_BUF_SIZE], *q; + int valid_unistr; /* 0: invalid; 1: unicode value; 2: string */ + int i, l; + glyph_unicode_entry *gu, t; + void **aa; + + p = makecstring(glyph); + assert(strlen(p) < SMALL_BUF_SIZE); + strcpy(buf, p); /* copy the result to buf before next call of makecstring() */ + p = makecstring(unistr); + while (*p == ' ') + p++; /* ignore leading spaces */ + l = strlen(p); + while (l > 0 && p[l - 1] == ' ') + l--; /* ignore traling spaces */ + valid_unistr = 1; /* a unicode value is the most common case */ + for (i = 0; i < l; i++) { + if (p[i] == ' ') + valid_unistr = 2; /* if a space occurs we treat this entry as a string */ + else if (!isXdigit(p[i])) { + valid_unistr = 0; + break; + } + } + if (l == 0 || valid_unistr == 0 || strlen(buf) == 0 + || strcmp(buf, notdef) == 0) { + pdftex_warn("ToUnicode: invalid parameter(s): `%s' => `%s'", buf, p); + return; + } + if (glyph_unicode_tree == NULL) { + glyph_unicode_tree = + avl_create(comp_glyph_unicode_entry, NULL, &avl_xallocator); + assert(glyph_unicode_tree != NULL); + } + t.name = buf; + /* allow overriding existing entries */ + if ((gu = (glyph_unicode_entry *) avl_find(glyph_unicode_tree, &t)) != NULL) { + if (gu->code == UNI_STRING) { + assert(gu->unicode_seq != NULL); + xfree(gu->unicode_seq); + } + } else { /* make new entry */ + gu = new_glyph_unicode_entry(); + gu->name = xstrdup(buf); + } + if (valid_unistr == 2) { /* a string with space(s) */ + /* copy p to buf2, ignoring spaces */ + for (q = buf2; *p != 0; p++) + if (*p != ' ') + *q++ = *p; + *q = 0; + gu->code = UNI_STRING; + gu->unicode_seq = xstrdup(buf2); + } else { + i = sscanf(p, "%lX", &(gu->code)); + assert(i == 1); + } + aa = avl_probe(glyph_unicode_tree, gu); + assert(aa != NULL); +} + + +static long check_unicode_value(char *s, boolean multiple_value) +{ + int l = strlen(s); + int i; + long code; + + if (l == 0) + return UNI_UNDEF; + if (multiple_value && l % 4 != 0) + return UNI_UNDEF; + if (!multiple_value && !(4 <= l && l <= 6)) + return UNI_UNDEF; + + for (i = 0; i < l; i++) { + if (!isXdigit(s[i])) + return UNI_UNDEF; + if (multiple_value) { + if (i % 4 == 3) { + if (sscanf(s + i - 3, "%4lX", &code) != 1) + return UNI_UNDEF; + if (!((0x0000 <= code && code <= 0xD7FF) || + (0xE000 <= code && code <= 0xFFFF))) + return UNI_UNDEF; + } + } else { /* single value */ + if (i == l - 1) { + if (sscanf(s, "%lX", &code) != 1) + return UNI_UNDEF; + if (!((0x0000 <= code && code <= 0xD7FF) || + (0xE000 <= code && code <= 0x10FFFF))) + return UNI_UNDEF; + } + } + } + return code; +} + +static char *utf16be_str(long code) +{ + static char buf[SMALL_BUF_SIZE]; + long v; + unsigned vh, vl; + + assert(code >= 0); + + if (code <= 0xFFFF) + sprintf(buf, "%04lX", code); + else { + v = code - 0x10000; + vh = v / 0x400 + 0xD800; + vl = v % 0x400 + 0xDC00; + sprintf(buf, "%04X%04X", vh, vl); + } + return buf; +} + + +/* this function set proper values to *gp based on s; in case it returns + * gp->code == UNI_EXTRA_STRING then the caller is responsible for freeing + * gp->unicode_seq too */ +static void set_glyph_unicode(char *s, glyph_unicode_entry * gp) +{ + char buf[SMALL_BUF_SIZE], buf2[SMALL_BUF_SIZE], *p; + long code; + boolean last_component; + glyph_unicode_entry tmp, *ptmp; + + /* skip dummy entries */ + if (s == NULL || s == notdef) + return; + + /* strip everything after the first dot */ + p = strchr(s, '.'); + if (p != NULL) { + *buf = 0; + strncat(buf, s, p - s); + s = buf; + } + + if (strlen(s) == 0) + return; + + /* check for case of multiple components separated by '_' */ + p = strchr(s, '_'); + if (p != NULL) { + assert(strlen(s) < sizeof(buf)); + if (s != buf) { + strcpy(buf, s); + p = strchr(buf, '_'); + s = buf; + } + *buf2 = 0; + last_component = false; + for (;;) { + *p = 0; + tmp.code = UNI_UNDEF; + set_glyph_unicode(s, &tmp); + switch (tmp.code) { + case UNI_UNDEF: /* not found, do nothing */ + break; + case UNI_STRING: /* s matched an entry with string value in the database */ + assert(tmp.unicode_seq != NULL); + assert(strlen(buf2) + strlen(tmp.unicode_seq) < sizeof(buf2)); + strcat(buf2, tmp.unicode_seq); + break; + case UNI_EXTRA_STRING: /* s is a multiple value of form "uniXXXX" */ + assert(strlen(buf2) + strlen(tmp.unicode_seq) < sizeof(buf2)); + strcat(buf2, tmp.unicode_seq); + xfree(tmp.unicode_seq); + break; + default: /* s matched an entry with numeric value in the + database, or a value derived from "uXXXX" */ + assert(tmp.code >= 0); + strcat(buf2, utf16be_str(tmp.code)); + } + if (last_component) + break; + s = p + 1; + p = strchr(s, '_'); + if (p == NULL) { + p = strend(s); + last_component = true; + } + } + gp->code = UNI_EXTRA_STRING; + gp->unicode_seq = xstrdup(buf2); + return; + } + + /* lookup for glyph name in the database */ + tmp.name = s; + tmp.code = UNI_UNDEF; + ptmp = (glyph_unicode_entry *) avl_find(glyph_unicode_tree, &tmp); + if (ptmp != NULL) { + gp->code = ptmp->code; + gp->unicode_seq = ptmp->unicode_seq; + return; + } + + /* check for case of "uniXXXX" (multiple 4-hex-digit values allowed) */ + if (str_prefix(s, "uni")) { + p = s + strlen("uni"); + code = check_unicode_value(p, true); + if (code != UNI_UNDEF) { + if (strlen(p) == 4) /* single value */ + gp->code = code; + else { /* multiple value */ + gp->code = UNI_EXTRA_STRING; + gp->unicode_seq = xstrdup(p); + } + } + return; /* since the last case cannot happen */ + } + + /* check for case of "uXXXX" (single value up to 6 hex digits) */ + if (str_prefix(s, "u")) { + p = s + strlen("u"); + code = check_unicode_value(p, false); + if (code != UNI_UNDEF) { + assert(code >= 0); + gp->code = code; + } + } +} + +static void set_cid_glyph_unicode(long index, glyph_unicode_entry * gp, + internal_font_number f) { + char *s; + if (font_tounicode(f)) { + if ((s = get_charinfo_tounicode(char_info(f,index)))!=NULL) { + gp->code = UNI_EXTRA_STRING; + gp->unicode_seq = xstrdup(s); + } + } else { + gp->code = index; /* fallback */ + } +} + + +integer write_tounicode(char **glyph_names, char *name) +{ + char buf[SMALL_BUF_SIZE], *p; + static char builtin_suffix[] = "-builtin"; + short range_size[257]; + glyph_unicode_entry gtab[257]; + integer objnum; + int i, j; + int bfchar_count, bfrange_count, subrange_count; + assert(strlen(name) + strlen(builtin_suffix) < SMALL_BUF_SIZE); + if (glyph_unicode_tree == NULL) { + pdftex_warn("no GlyphToUnicode entry has been inserted yet!"); + fixed_gen_tounicode = 0; + return 0; + } + strcpy(buf, name); + if ((p = strrchr(buf, '.')) != NULL && strcmp(p, ".enc") == 0) + *p = 0; /* strip ".enc" from encoding name */ + else + strcat(buf, builtin_suffix); /* ".enc" not present, this is a builtin + encoding so the name is eg "cmr10-builtin" */ + objnum = pdf_new_objnum(); + pdf_begin_dict(objnum, 0); + pdf_begin_stream(); + pdf_printf("%%!PS-Adobe-3.0 Resource-CMap\n" + "%%%%DocumentNeededResources: ProcSet (CIDInit)\n" + "%%%%IncludeResource: ProcSet (CIDInit)\n" + "%%%%BeginResource: CMap (TeX-%s-0)\n" + "%%%%Title: (TeX-%s-0 TeX %s 0)\n" + "%%%%Version: 1.000\n" + "%%%%EndComments\n" + "/CIDInit /ProcSet findresource begin\n" + "12 dict begin\n" + "begincmap\n" + "/CIDSystemInfo\n" + "<< /Registry (TeX)\n" + "/Ordering (%s)\n" + "/Supplement 0\n" + ">> def\n" + "/CMapName /TeX-%s-0 def\n" + "/CMapType 2 def\n" + "1 begincodespacerange\n" + "<00> \n" "endcodespacerange\n", buf, buf, buf, buf, buf); + + /* set gtab */ + for (i = 0; i < 256; ++i) { + gtab[i].code = UNI_UNDEF; + set_glyph_unicode(glyph_names[i], >ab[i]); + } + gtab[256].code = UNI_UNDEF; + + /* set range_size */ + for (i = 0; i < 256;) { + if (gtab[i].code == UNI_STRING || gtab[i].code == UNI_EXTRA_STRING) { + range_size[i] = 1; /* single entry */ + i++; + } else if (gtab[i].code == UNI_UNDEF) { + range_size[i] = 0; /* no entry */ + i++; + } else { /* gtab[i].code >= 0 */ + j = i; + while (i < 256 && gtab[i + 1].code >= 0 && + gtab[i].code + 1 == gtab[i + 1].code) + i++; + /* at this point i is the last entry of the subrange */ + i++; /* move i to the next entry */ + range_size[j] = i - j; + } + } + + /* calculate bfrange_count and bfchar_count */ + bfrange_count = 0; + bfchar_count = 0; + for (i = 0; i < 256;) { + if (range_size[i] == 1) { + bfchar_count++; + i++; + } else if (range_size[i] > 1) { + bfrange_count++; + i += range_size[i]; + } else + i++; + } + + /* write out bfrange */ + i = 0; + write_bfrange: + if (bfrange_count > 100) + subrange_count = 100; + else + subrange_count = bfrange_count; + bfrange_count -= subrange_count; + pdf_printf("%i beginbfrange\n", subrange_count); + for (j = 0; j < subrange_count; j++) { + while (range_size[i] <= 1 && i < 256) + i++; + assert(i < 256); + pdf_printf("<%02X> <%02X> <%s>\n", i, i + range_size[i] - 1, + utf16be_str(gtab[i].code)); + i += range_size[i]; + } + pdf_printf("endbfrange\n"); + if (bfrange_count > 0) + goto write_bfrange; + + /* write out bfchar */ + i = 0; + write_bfchar: + if (bfchar_count > 100) + subrange_count = 100; + else + subrange_count = bfchar_count; + bfchar_count -= subrange_count; + pdf_printf("%i beginbfchar\n", subrange_count); + for (j = 0; j < subrange_count; j++) { + while (i < 256) { + if (range_size[i] > 1) + i += range_size[i]; + else if (range_size[i] == 0) + i++; + else /* range_size[i] == 1 */ + break; + } + assert(i < 256 && gtab[i].code != UNI_UNDEF); + if (gtab[i].code == UNI_STRING || gtab[i].code == UNI_EXTRA_STRING) { + assert(gtab[i].unicode_seq != NULL); + pdf_printf("<%02X> <%s>\n", i, gtab[i].unicode_seq); + } else + pdf_printf("<%02X> <%s>\n", i, utf16be_str(gtab[i].code)); + i++; + } + pdf_printf("endbfchar\n"); + if (bfchar_count > 0) + goto write_bfchar; + + /* free strings allocated by set_glyph_unicode() */ + for (i = 0; i < 256; ++i) { + if (gtab[i].code == UNI_EXTRA_STRING) + xfree(gtab[i].unicode_seq); + } + + pdf_printf("endcmap\n" + "CMapName currentdict /CMap defineresource pop\n" + "end\n" "end\n" "%%%%EndResource\n" "%%%%EOF\n"); + pdf_end_stream(); + return objnum; +} + +integer write_cid_tounicode(fo_entry * fo, internalfontnumber f) { + + int range_size[65537]; + glyph_unicode_entry gtab[65537]; + integer objnum; + int i, j, k; + int bfchar_count, bfrange_count, subrange_count; + char *buf; + + assert(fo->fd->fontname); + buf = xmalloc(strlen(fo->fd->fontname)+8); + sprintf(buf,"%s-%s",(fo->fd->subset_tag!=NULL ? fo->fd->subset_tag : "UCS"), + fo->fd->fontname); + + objnum = pdf_new_objnum(); + pdf_begin_dict(objnum, 0); + pdf_begin_stream(); + pdf_printf("%%!PS-Adobe-3.0 Resource-CMap\n" + "%%%%DocumentNeededResources: ProcSet (CIDInit)\n" + "%%%%IncludeResource: ProcSet (CIDInit)\n" + "%%%%BeginResource: CMap (TeX-%s-0)\n" + "%%%%Title: (TeX-%s-0 TeX %s 0)\n" + "%%%%Version: 1.000\n" + "%%%%EndComments\n" + "/CIDInit /ProcSet findresource begin\n" + "12 dict begin\n" + "begincmap\n" + "/CIDSystemInfo\n" + "<< /Registry (TeX)\n" + "/Ordering (%s)\n" + "/Supplement 0\n" + ">> def\n" + "/CMapName /TeX-Identity-%s def\n" + "/CMapType 2 def\n" + "1 begincodespacerange\n" + "<0000> \n" + "endcodespacerange\n", buf, buf, buf, buf, buf); + xfree(buf); + /* set up gtab */ + for (i = 0; i < 65537; ++i) { + gtab[i].code = UNI_UNDEF; + } + for (k = 1; k <= max_font_id(); k++) { + if (k == f || -f == pdf_font_num(k)) { + for (i = font_bc(k); i <= font_ec(k); i++) { + if (char_exists(k,i) && char_used(k,i)) { + j = char_index(k,i); + if (gtab[j].code == UNI_UNDEF) { + set_cid_glyph_unicode(i, >ab[j], f); + } + } + } + } + } + + /* set range_size */ + for (i = 0; i < 65536;) { + if (gtab[i].code == UNI_STRING || gtab[i].code == UNI_EXTRA_STRING) { + range_size[i] = 1; /* single entry */ + i++; + } else if (gtab[i].code == UNI_UNDEF) { + range_size[i] = 0; /* no entry */ + i++; + } else { /* gtab[i].code >= 0 */ + j = i; + while (i < 65536 && gtab[i + 1].code >= 0 && + gtab[i].code + 1 == gtab[i + 1].code) + i++; + /* at this point i is the last entry of the subrange */ + i++; /* move i to the next entry */ + range_size[j] = i - j; + } + } + + /* calculate bfrange_count and bfchar_count */ + bfrange_count = 0; + bfchar_count = 0; + for (i = 0; i < 65536;) { + if (range_size[i] == 1) { + bfchar_count++; + i++; + } else if (range_size[i] > 1) { + bfrange_count++; + i += range_size[i]; + } else + i++; + } + + /* write out bfrange */ + i = 0; + write_bfrange: + if (bfrange_count > 100) + subrange_count = 100; + else + subrange_count = bfrange_count; + bfrange_count -= subrange_count; + pdf_printf("%i beginbfrange\n", subrange_count); + for (j = 0; j < subrange_count; j++) { + while (range_size[i] <= 1 && i < 65536) + i++; + assert(i < 65536); + pdf_printf("<%04X> <%04X> <%s>\n", i, i + range_size[i] - 1, + utf16be_str(gtab[i].code)); + i += range_size[i]; + } + pdf_printf("endbfrange\n"); + if (bfrange_count > 0) + goto write_bfrange; + + /* write out bfchar */ + i = 0; + write_bfchar: + if (bfchar_count > 100) + subrange_count = 100; + else + subrange_count = bfchar_count; + bfchar_count -= subrange_count; + pdf_printf("%i beginbfchar\n", subrange_count); + for (j = 0; j < subrange_count; j++) { + while (i < 65536) { + if (range_size[i] > 1) + i += range_size[i]; + else if (range_size[i] == 0) + i++; + else /* range_size[i] == 1 */ + break; + } + assert(i < 65536 && gtab[i].code != UNI_UNDEF); + if (gtab[i].code == UNI_STRING || gtab[i].code == UNI_EXTRA_STRING) { + assert(gtab[i].unicode_seq != NULL); + pdf_printf("<%04X> <%s>\n", i, gtab[i].unicode_seq); + } else + pdf_printf("<%04X> <%s>\n", i, utf16be_str(gtab[i].code)); + i++; + } + pdf_printf("endbfchar\n"); + if (bfchar_count > 0) + goto write_bfchar; + + /* free strings allocated by set_glyph_unicode() */ + for (i = 0; i < 65536; ++i) { + if (gtab[i].code == UNI_EXTRA_STRING) + xfree(gtab[i].unicode_seq); + } + + pdf_printf("endcmap\n" + "CMapName currentdict /CMap defineresource pop\n" + "end\n" "end\n" "%%%%EndResource\n" "%%%%EOF\n"); + pdf_end_stream(); + return objnum; +} diff --git a/Build/source/texk/web2c/luatexdir/font/tt_glyf.c b/Build/source/texk/web2c/luatexdir/font/tt_glyf.c new file mode 100644 index 00000000000..bf21e58c49a --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/font/tt_glyf.c @@ -0,0 +1,658 @@ +/* $Header: /home/cvsroot/dvipdfmx/src/tt_glyf.c,v 1.2 2005/06/09 14:31:11 hirata Exp $ + + This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. + + Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata, + the dvipdfmx project team + + 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. +*/ + +/* + * Subsetting glyf, updating loca, hmtx, ... + * + */ + +#include "ptexlib.h" + +#include "sfnt.h" +#include "tt_table.h" +#include "tt_glyf.h" + +#define NUM_GLYPH_LIMIT 65534 +#define TABLE_DATA_ALLOC_SIZE 40960 +#define GLYPH_ARRAY_ALLOC_SIZE 256 + +static USHORT +find_empty_slot (struct tt_glyphs *g) +{ + USHORT gid; + + ASSERT(g); + + for (gid = 0; gid < NUM_GLYPH_LIMIT; gid++) { + if (!(g->used_slot[gid/8] & (1 << (7 - (gid % 8))))) + break; + } + if (gid == NUM_GLYPH_LIMIT) + TT_ERROR("No empty glyph slot available."); + + return gid; +} + +USHORT +tt_find_glyph (struct tt_glyphs *g, USHORT gid) +{ + USHORT idx, new_gid = 0; + + ASSERT(g); + + for (idx = 0; idx < g->num_glyphs; idx++) { + if (gid == g->gd[idx].ogid) { + new_gid = g->gd[idx].gid; + break; + } + } + + return new_gid; +} + +USHORT +tt_get_index (struct tt_glyphs *g, USHORT gid) +{ + USHORT idx; + + ASSERT(g); + + for (idx = 0; idx < g->num_glyphs; idx++) { + if (gid == g->gd[idx].gid) + break; + } + if (idx == g->num_glyphs) + idx = 0; + + return idx; +} + +USHORT +tt_add_glyph (struct tt_glyphs *g, USHORT gid, USHORT new_gid) +{ + ASSERT(g); + + if (g->used_slot[new_gid/8] & (1 << (7 - (new_gid % 8)))) { + WARN("Slot %u already used.", new_gid); + } else { + if (g->num_glyphs+1 >= NUM_GLYPH_LIMIT) + TT_ERROR("Too many glyphs."); + + if (g->num_glyphs >= g->max_glyphs) { + g->max_glyphs += GLYPH_ARRAY_ALLOC_SIZE; + g->gd = RENEW(g->gd, g->max_glyphs, struct tt_glyph_desc); + } + g->gd[g->num_glyphs].gid = new_gid; + g->gd[g->num_glyphs].ogid = gid; + g->gd[g->num_glyphs].length = 0; + g->gd[g->num_glyphs].data = NULL; + g->used_slot[new_gid/8] |= (1 << (7 - (new_gid % 8))); + g->num_glyphs += 1; + } + + if (new_gid > g->last_gid) { + g->last_gid = new_gid; + } + + return new_gid; +} + +/* + * Initialization + */ +struct tt_glyphs * +tt_build_init (void) +{ + struct tt_glyphs *g; + + g = NEW(1, struct tt_glyphs); + + g->num_glyphs = 0; + g->max_glyphs = 0; + g->last_gid = 0; + g->emsize = 1; + g->default_advh = 0; + g->default_tsb = 0; + g->gd = NULL; + g->used_slot = NEW(8192, unsigned char); + memset(g->used_slot, 0, 8192); + tt_add_glyph(g, 0, 0); + + return g; +} + +void +tt_build_finish (struct tt_glyphs *g) +{ + if (g) { + if (g->gd) { + USHORT idx; + for (idx = 0; idx < g->num_glyphs; idx++) { + if (g->gd[idx].data) + RELEASE(g->gd[idx].data); + } + RELEASE(g->gd); + } + if (g->used_slot) + RELEASE(g->used_slot); + RELEASE(g); + } +} + +static int +glyf_cmp (const void *v1, const void *v2) +{ + int cmp = 0; + struct tt_glyph_desc *sv1, *sv2; + + sv1 = (struct tt_glyph_desc *) v1; + sv2 = (struct tt_glyph_desc *) v2; + + if (sv1->gid == sv2->gid) + cmp = 0; + else if (sv1->gid < sv2->gid) + cmp = -1; + else + cmp = 1; + + return cmp; +} + +/* + * TrueType outline data. + */ +#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_COMPONENT (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) + +int +tt_build_tables (sfnt *sfont, struct tt_glyphs *g) +{ + char *hmtx_table_data = NULL, *loca_table_data = NULL; + char *glyf_table_data = NULL; + ULONG hmtx_table_size, loca_table_size, glyf_table_size; + /* some information available from other TrueType table */ + struct tt_head_table *head = NULL; + struct tt_hhea_table *hhea = NULL; + struct tt_maxp_table *maxp = NULL; + struct tt_longMetrics *hmtx, *vmtx = NULL; + struct tt_os2__table *os2; + /* temp */ + ULONG *location, offset; + long i; + USHORT *w_stat; /* Estimate most frequently appeared width */ + + ASSERT(g); + + if (sfont->type != SFNT_TYPE_TRUETYPE && + sfont->type != SFNT_TYPE_TTC) + TT_ERROR("Invalid font type"); + + if (g->num_glyphs > NUM_GLYPH_LIMIT) + TT_ERROR("Too many glyphs."); + + /* + * Read head, hhea, maxp, loca: + * + * unitsPerEm --> head + * numHMetrics --> hhea + * indexToLocFormat --> head + * numGlyphs --> maxp + */ + head = tt_read_head_table(sfont); + hhea = tt_read_hhea_table(sfont); + maxp = tt_read_maxp_table(sfont); + + if (hhea->metricDataFormat != 0) + TT_ERROR("Unknown metricDataFormat."); + + g->emsize = head->unitsPerEm; + + sfnt_locate_table(sfont, "hmtx"); + hmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, hhea->numberOfHMetrics); + + os2 = tt_read_os2__table(sfont); + if (os2) { + g->default_advh = os2->sTypoAscender - os2->sTypoDescender; + g->default_tsb = g->default_advh - os2->sTypoAscender; + } + + if (sfnt_find_table_pos(sfont, "vmtx") > 0) { + struct tt_vhea_table *vhea; + vhea = tt_read_vhea_table(sfont); + sfnt_locate_table(sfont, "vmtx"); + vmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, vhea->numOfLongVerMetrics); + RELEASE(vhea); + } else { + vmtx = NULL; + } + + sfnt_locate_table(sfont, "loca"); + location = NEW(maxp->numGlyphs + 1, ULONG); + if (head->indexToLocFormat == 0) { + for (i = 0; i <= maxp->numGlyphs; i++) + location[i] = 2*((ULONG) sfnt_get_ushort(sfont)); + } else if (head->indexToLocFormat == 1) { + for (i = 0; i <= maxp->numGlyphs; i++) + location[i] = sfnt_get_ulong(sfont); + } else { + TT_ERROR("Unknown IndexToLocFormat."); + } + + w_stat = NEW(g->emsize+2, USHORT); + memset(w_stat, 0, sizeof(USHORT)*(g->emsize+2)); + /* + * Read glyf table. + */ + offset = sfnt_locate_table(sfont, "glyf"); + /* + * The num_glyphs may grow when composite glyph is found. + * A component of glyph refered by a composite glyph is appended + * to used_glyphs if it is not already registered in used_glyphs. + * Glyph programs of composite glyphs are modified so that it + * correctly refer to new gid of their components. + */ + for (i = 0; i < NUM_GLYPH_LIMIT; i++) { + USHORT gid; /* old gid */ + ULONG loc, len; + BYTE *p, *endptr; + SHORT number_of_contours; + + if (i >= g->num_glyphs) /* finished */ + break; + + gid = g->gd[i].ogid; + if (gid >= maxp->numGlyphs) + TT_ERROR("Invalid glyph index (gid %u)", gid); + + loc = location[gid]; + len = location[gid+1] - loc; + g->gd[i].advw = hmtx[gid].advance; + g->gd[i].lsb = hmtx[gid].sideBearing; + if (vmtx) { + g->gd[i].advh = vmtx[gid].advance; + g->gd[i].tsb = vmtx[gid].sideBearing; + } else { + g->gd[i].advh = g->default_advh; + g->gd[i].tsb = g->default_tsb; + } + g->gd[i].length = len; + g->gd[i].data = NULL; + if (g->gd[i].advw <= g->emsize) { + w_stat[g->gd[i].advw] += 1; + } else { + w_stat[g->emsize+1] += 1; /* larger than em */ + } + + if (len == 0) { /* Does not contains any data. */ + continue; + } else if (len < 10) { + TT_ERROR("Invalid TrueType glyph data (gid %u).", gid); + } + + g->gd[i].data = p = NEW(len, BYTE); + endptr = p + len; + + sfnt_seek_set(sfont, offset+loc); + number_of_contours = sfnt_get_short(sfont); + p += sfnt_put_short(p, number_of_contours); + + /* BoundingBox: FWord x 4 */ + g->gd[i].llx = sfnt_get_short(sfont); + g->gd[i].lly = sfnt_get_short(sfont); + g->gd[i].urx = sfnt_get_short(sfont); + g->gd[i].ury = sfnt_get_short(sfont); + /* _FIXME_ */ +#if 1 + if (!vmtx) /* vertOriginY == sTypeAscender */ + g->gd[i].tsb = g->default_advh - g->default_tsb - g->gd[i].ury; +#endif + p += sfnt_put_short(p, g->gd[i].llx); + p += sfnt_put_short(p, g->gd[i].lly); + p += sfnt_put_short(p, g->gd[i].urx); + p += sfnt_put_short(p, g->gd[i].ury); + + /* Read evrything else. */ + sfnt_read(p, len - 10, sfont); + /* + * Fix GIDs of composite glyphs. + */ + if (number_of_contours < 0) { + USHORT flags, cgid, new_gid; /* flag, gid of a component */ + do { + if (p >= endptr) + TT_ERROR("Invalid TrueType glyph data (gid %u): %u bytes", gid, (unsigned int)len); + /* + * Flags and gid of component glyph are both USHORT. + */ + flags = ((*p) << 8)| *(p+1); + p += 2; + cgid = ((*p) << 8)| *(p+1); + if (cgid >= maxp->numGlyphs) { + TT_ERROR("Invalid gid (%u > %u) in composite glyph %u.", cgid, maxp->numGlyphs, gid); + } + new_gid = tt_find_glyph(g, cgid); + if (new_gid == 0) { + new_gid = tt_add_glyph(g, cgid, find_empty_slot(g)); + } + p += sfnt_put_ushort(p, new_gid); + /* + * Just skip remaining part. + */ + p += (flags & ARG_1_AND_2_ARE_WORDS) ? 4 : 2; + if (flags & WE_HAVE_A_SCALE) /* F2Dot14 */ + p += 2; + else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) /* F2Dot14 x 2 */ + p += 4; + else if (flags & WE_HAVE_A_TWO_BY_TWO) /* F2Dot14 x 4 */ + p += 8; + } while (flags & MORE_COMPONENT); + /* + * TrueType instructions comes here: + * length_of_instruction (ushort) + * instruction (byte * length_of_instruction) + */ + } + } + RELEASE(location); + RELEASE(hmtx); + if (vmtx) + RELEASE(vmtx); + + { + int max_count = -1; + + g->dw = g->gd[0].advw; + for (i = 0; i < g->emsize + 1; i++) { + if (w_stat[i] > max_count) { + max_count = w_stat[i]; + g->dw = i; + } + } + } + RELEASE(w_stat); + + qsort(g->gd, g->num_glyphs, sizeof(struct tt_glyph_desc), glyf_cmp); + { + USHORT prev, last_advw; + char *p, *q; + int padlen, num_hm_known; + + glyf_table_size = 0UL; + num_hm_known = 0; + last_advw = g->gd[g->num_glyphs - 1].advw; + for (i = g->num_glyphs - 1; i >= 0; i--) { + padlen = (g->gd[i].length % 4) ? (4 - (g->gd[i].length % 4)) : 0; + glyf_table_size += g->gd[i].length + padlen; + if (!num_hm_known && last_advw != g->gd[i].advw) { + hhea->numberOfHMetrics = g->gd[i].gid + 2; + num_hm_known = 1; + } + } + /* All advance widths are same. */ + if (!num_hm_known) { + hhea->numberOfHMetrics = 1; + } + hmtx_table_size = hhea->numberOfHMetrics * 2 + (g->last_gid + 1) * 2; + + /* + * Choosing short format does not always give good result + * when compressed. Sometimes increases size. + */ + if (glyf_table_size < 0x20000UL) { + head->indexToLocFormat = 0; + loca_table_size = (g->last_gid + 2)*2; + } else { + head->indexToLocFormat = 1; + loca_table_size = (g->last_gid + 2)*4; + } + + hmtx_table_data = p = NEW(hmtx_table_size, char); + loca_table_data = q = NEW(loca_table_size, char); + glyf_table_data = NEW(glyf_table_size, char); + + offset = 0UL; prev = 0; + for (i = 0; i < g->num_glyphs; i++) { + long gap, j; + gap = (long) g->gd[i].gid - prev - 1; + for (j = 1; j <= gap; j++) { + if (prev + j == hhea->numberOfHMetrics - 1) { + p += sfnt_put_ushort(p, last_advw); + } else if (prev + j < hhea->numberOfHMetrics) { + p += sfnt_put_ushort(p, 0); + } + p += sfnt_put_short (p, 0); + if (head->indexToLocFormat == 0) { + q += sfnt_put_ushort(q, (USHORT) (offset/2)); + } else { + q += sfnt_put_ulong(q, offset); + } + } + padlen = (g->gd[i].length % 4) ? (4 - (g->gd[i].length % 4)) : 0; + if (g->gd[i].gid < hhea->numberOfHMetrics) { + p += sfnt_put_ushort(p, g->gd[i].advw); + } + p += sfnt_put_short (p, g->gd[i].lsb); + if (head->indexToLocFormat == 0) { + q += sfnt_put_ushort(q, (USHORT) (offset/2)); + } else { + q += sfnt_put_ulong(q, offset); + } + memset(glyf_table_data + offset, 0, g->gd[i].length + padlen); + memcpy(glyf_table_data + offset, g->gd[i].data, g->gd[i].length); + offset += g->gd[i].length + padlen; + prev = g->gd[i].gid; + /* free data here since it consume much memory */ + RELEASE(g->gd[i].data); + g->gd[i].length = 0; g->gd[i].data = NULL; + } + if (head->indexToLocFormat == 0) { + q += sfnt_put_ushort(q, (USHORT) (offset/2)); + } else { + q += sfnt_put_ulong(q, offset); + } + + sfnt_set_table(sfont, "hmtx", (char *) hmtx_table_data, hmtx_table_size); + sfnt_set_table(sfont, "loca", (char *) loca_table_data, loca_table_size); + sfnt_set_table(sfont, "glyf", (char *) glyf_table_data, glyf_table_size); + } + + head->checkSumAdjustment = 0; + maxp->numGlyphs = g->last_gid + 1; + + /* TODO */ + sfnt_set_table(sfont, "maxp", tt_pack_maxp_table(maxp), TT_MAXP_TABLE_SIZE); + sfnt_set_table(sfont, "hhea", tt_pack_hhea_table(hhea), TT_HHEA_TABLE_SIZE); + sfnt_set_table(sfont, "head", tt_pack_head_table(head), TT_HEAD_TABLE_SIZE); + RELEASE(maxp); + RELEASE(hhea); + RELEASE(head); + if (os2) + RELEASE(os2); + + return 0; +} + +int +tt_get_metrics (sfnt *sfont, struct tt_glyphs *g) +{ + struct tt_head_table *head = NULL; + struct tt_hhea_table *hhea = NULL; + struct tt_maxp_table *maxp = NULL; + struct tt_longMetrics *hmtx, *vmtx = NULL; + struct tt_os2__table *os2; + /* temp */ + ULONG *location, offset; + long i; + USHORT *w_stat; + + ASSERT(g); + + if (sfont == NULL || +#ifdef XETEX + sfont->ft_face == NULL +#elif defined(pdfTeX) + sfont->buffer == NULL +#else + sfont->stream == NULL +#endif + ) + TT_ERROR("File not opened."); + + if (sfont->type != SFNT_TYPE_TRUETYPE && + sfont->type != SFNT_TYPE_TTC) + TT_ERROR("Invalid font type"); + + /* + * Read head, hhea, maxp, loca: + * + * unitsPerEm --> head + * numHMetrics --> hhea + * indexToLocFormat --> head + * numGlyphs --> maxp + */ + head = tt_read_head_table(sfont); + hhea = tt_read_hhea_table(sfont); + maxp = tt_read_maxp_table(sfont); + + if (hhea->metricDataFormat != 0) + TT_ERROR("Unknown metricDataFormat."); + + g->emsize = head->unitsPerEm; + + sfnt_locate_table(sfont, "hmtx"); + hmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, hhea->numberOfHMetrics); + + os2 = tt_read_os2__table(sfont); + g->default_advh = os2->sTypoAscender - os2->sTypoDescender; + g->default_tsb = g->default_advh - os2->sTypoAscender; + + if (sfnt_find_table_pos(sfont, "vmtx") > 0) { + struct tt_vhea_table *vhea; + vhea = tt_read_vhea_table(sfont); + sfnt_locate_table(sfont, "vmtx"); + vmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, vhea->numOfLongVerMetrics); + RELEASE(vhea); + } else { + vmtx = NULL; + } + + sfnt_locate_table(sfont, "loca"); + location = NEW(maxp->numGlyphs + 1, ULONG); + if (head->indexToLocFormat == 0) { + for (i = 0; i <= maxp->numGlyphs; i++) + location[i] = 2*((ULONG) sfnt_get_ushort(sfont)); + } else if (head->indexToLocFormat == 1) { + for (i = 0; i <= maxp->numGlyphs; i++) + location[i] = sfnt_get_ulong(sfont); + } else { + TT_ERROR("Unknown IndexToLocFormat."); + } + + w_stat = NEW(g->emsize+2, USHORT); + memset(w_stat, 0, sizeof(USHORT)*(g->emsize+2)); + /* + * Read glyf table. + */ + offset = sfnt_locate_table(sfont, "glyf"); + for (i = 0; i < g->num_glyphs; i++) { + USHORT gid; /* old gid */ + ULONG loc, len; + SHORT number_of_contours; + + gid = g->gd[i].ogid; + if (gid >= maxp->numGlyphs) + TT_ERROR("Invalid glyph index (gid %u)", gid); + + loc = location[gid]; + len = location[gid+1] - loc; + g->gd[i].advw = hmtx[gid].advance; + g->gd[i].lsb = hmtx[gid].sideBearing; + if (vmtx) { + g->gd[i].advh = vmtx[gid].advance; + g->gd[i].tsb = vmtx[gid].sideBearing; + } else { + g->gd[i].advh = g->default_advh; + g->gd[i].tsb = g->default_tsb; + } + g->gd[i].length = len; + g->gd[i].data = NULL; + + if (g->gd[i].advw <= g->emsize) { + w_stat[g->gd[i].advw] += 1; + } else { + w_stat[g->emsize+1] += 1; /* larger than em */ + } + + if (len == 0) { /* Does not contains any data. */ + continue; + } else if (len < 10) { + TT_ERROR("Invalid TrueType glyph data (gid %u).", gid); + } + + sfnt_seek_set(sfont, offset+loc); + number_of_contours = sfnt_get_short(sfont); + + /* BoundingBox: FWord x 4 */ + g->gd[i].llx = sfnt_get_short(sfont); + g->gd[i].lly = sfnt_get_short(sfont); + g->gd[i].urx = sfnt_get_short(sfont); + g->gd[i].ury = sfnt_get_short(sfont); + /* _FIXME_ */ +#if 1 + if (!vmtx) /* vertOriginY == sTypeAscender */ + g->gd[i].tsb = g->default_advh - g->default_tsb - g->gd[i].ury; +#endif + } + RELEASE(location); + RELEASE(hmtx); + RELEASE(maxp); + RELEASE(hhea); + RELEASE(head); + RELEASE(os2); + + if (vmtx) + RELEASE(vmtx); + + { + int max_count = -1; + + g->dw = g->gd[0].advw; + for (i = 0; i < g->emsize + 1; i++) { + if (w_stat[i] > max_count) { + max_count = w_stat[i]; + g->dw = i; + } + } + } + RELEASE(w_stat); + + + return 0; +} diff --git a/Build/source/texk/web2c/luatexdir/font/tt_glyf.h b/Build/source/texk/web2c/luatexdir/font/tt_glyf.h new file mode 100644 index 00000000000..cf33af6733f --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/font/tt_glyf.h @@ -0,0 +1,60 @@ +/* $Header: /home/cvsroot/dvipdfmx/src/tt_glyf.h,v 1.1 2004/09/11 14:50:29 hirata Exp $ + + This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. + + Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata, + the dvipdfmx project team + + 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. +*/ + +#ifndef _TT_GLYF_H_ +#define _TT_GLYF_H_ + +struct tt_glyph_desc +{ + USHORT gid; + USHORT ogid; /* GID in original font */ + USHORT advw, advh; + SHORT lsb, tsb; + SHORT llx, lly, urx, ury; + ULONG length; + BYTE *data; +}; + +struct tt_glyphs +{ + USHORT num_glyphs; + USHORT max_glyphs; + USHORT last_gid; + USHORT emsize; + USHORT dw; /* optimal value for DW */ + USHORT default_advh; /* default value */ + SHORT default_tsb; /* default value */ + struct tt_glyph_desc *gd; + unsigned char *used_slot; +}; + +extern struct tt_glyphs *tt_build_init (void); +extern void tt_build_finish (struct tt_glyphs *g); + +extern USHORT tt_add_glyph (struct tt_glyphs *g, USHORT gid, USHORT new_gid); +extern USHORT tt_get_index (struct tt_glyphs *g, USHORT gid); +extern USHORT tt_find_glyph (struct tt_glyphs *g, USHORT gid); + +extern int tt_build_tables (sfnt *sfont, struct tt_glyphs *g); +extern int tt_get_metrics (sfnt *sfont, struct tt_glyphs *g); + +#endif /* _TT_GLYF_H_ */ diff --git a/Build/source/texk/web2c/luatexdir/font/tt_table.c b/Build/source/texk/web2c/luatexdir/font/tt_table.c new file mode 100644 index 00000000000..4f82552d9df --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/font/tt_table.c @@ -0,0 +1,483 @@ +/* $Header: /home/cvsroot/dvipdfmx/src/tt_table.c,v 1.7 2004/09/11 14:50:29 hirata Exp $ + + This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. + + Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata, + the dvipdfmx project team + + 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. +*/ + +#include + +#ifndef pdfTeX +#include "system.h" +#include "error.h" +#include "mem.h" +#include "mfileio.h" +#else +extern void pdftex_fail (const char *fmt, ...); /* utils.c */ +#endif + +#include "sfnt.h" +#include "tt_table.h" + +/* + tables contains information refered by other tables + maxp->numGlyphs, etc --> loca, etc + hhea->numberOfHMetrics --> hmtx + head->indexToLocFormat --> loca + head->glyphDataFormat --> glyf +*/ + +char *tt_pack_head_table (struct tt_head_table *table) +{ + int i; + char *p, *data; + + if (table == NULL) + TT_ERROR("passed NULL pointer\n"); + + p = data = NEW(TT_HEAD_TABLE_SIZE, char); + p += sfnt_put_ulong(p, table->version); + p += sfnt_put_ulong(p, table->fontRevision); + p += sfnt_put_ulong(p, table->checkSumAdjustment); + p += sfnt_put_ulong(p, table->magicNumber); + p += sfnt_put_ushort(p, table->flags); + p += sfnt_put_ushort(p, table->unitsPerEm); + for (i=0; i<8; i++) { + *(p++) = (table->created)[i]; + } + for (i=0; i<8; i++) { + *(p++) = (table->modified)[i]; + } + p += sfnt_put_short(p, table->xMin); + p += sfnt_put_short(p, table->yMin); + p += sfnt_put_short(p, table->xMax); + p += sfnt_put_short(p, table->yMax); + p += sfnt_put_ushort(p, table->macStyle); + p += sfnt_put_ushort(p, table->lowestRecPPEM); + p += sfnt_put_short(p, table->fontDirectionHint); + p += sfnt_put_short(p, table->indexToLocFormat); + p += sfnt_put_short(p, table->glyphDataFormat); + + return data; +} + +struct tt_head_table *tt_read_head_table (sfnt *sfont) +{ + int i; + struct tt_head_table *table = NULL; + + table = NEW(1, struct tt_head_table); + + sfnt_locate_table(sfont, "head"); + + table->version = sfnt_get_ulong(sfont); + table->fontRevision = sfnt_get_ulong(sfont); + table->checkSumAdjustment = sfnt_get_ulong(sfont); + table->magicNumber = sfnt_get_ulong(sfont); + table->flags = sfnt_get_ushort(sfont); + table->unitsPerEm = sfnt_get_ushort(sfont); + for (i=0; i<8; i++) { + (table->created)[i] = sfnt_get_byte (sfont); + } + for (i=0; i<8; i++) { + (table->modified)[i] = sfnt_get_byte (sfont); + } + table->xMin = sfnt_get_short(sfont); + table->yMin = sfnt_get_short(sfont); + table->xMax = sfnt_get_short(sfont); + table->yMax = sfnt_get_short(sfont); + table->macStyle = sfnt_get_short(sfont); + table->lowestRecPPEM = sfnt_get_short(sfont); + table->fontDirectionHint = sfnt_get_short(sfont); + table->indexToLocFormat = sfnt_get_short(sfont); + table->glyphDataFormat = sfnt_get_short(sfont); + + return table; +} + +char *tt_pack_maxp_table (struct tt_maxp_table *table) +{ + char *p, *data; + + p = data = NEW(TT_MAXP_TABLE_SIZE, char); + p += sfnt_put_ulong(p, table->version); + p += sfnt_put_ushort(p, table->numGlyphs); + p += sfnt_put_ushort(p, table->maxPoints); + p += sfnt_put_ushort(p, table->maxContours); + p += sfnt_put_ushort(p, table->maxComponentPoints); + p += sfnt_put_ushort(p, table->maxComponentContours); + p += sfnt_put_ushort(p, table->maxZones); + p += sfnt_put_ushort(p, table->maxTwilightPoints); + p += sfnt_put_ushort(p, table->maxStorage); + p += sfnt_put_ushort(p, table->maxFunctionDefs); + p += sfnt_put_ushort(p, table->maxInstructionDefs); + p += sfnt_put_ushort(p, table->maxStackElements); + p += sfnt_put_ushort(p, table->maxSizeOfInstructions); + p += sfnt_put_ushort(p, table->maxComponentElements); + p += sfnt_put_ushort(p, table->maxComponentDepth); + + return data; +} + +struct tt_maxp_table *tt_read_maxp_table (sfnt *sfont) +{ + struct tt_maxp_table *table = NULL; + + table = NEW(1, struct tt_maxp_table); + + sfnt_locate_table(sfont, "maxp"); + table->version = sfnt_get_ulong(sfont); + table->numGlyphs = sfnt_get_ushort(sfont); + table->maxPoints = sfnt_get_ushort(sfont); + table->maxContours = sfnt_get_ushort(sfont); + table->maxComponentPoints = sfnt_get_ushort(sfont); + table->maxComponentContours = sfnt_get_ushort(sfont); + table->maxZones = sfnt_get_ushort(sfont); + table->maxTwilightPoints = sfnt_get_ushort(sfont); + table->maxStorage = sfnt_get_ushort(sfont); + table->maxFunctionDefs = sfnt_get_ushort(sfont); + table->maxInstructionDefs = sfnt_get_ushort(sfont); + table->maxStackElements = sfnt_get_ushort(sfont); + table->maxSizeOfInstructions = sfnt_get_ushort(sfont); + table->maxComponentElements = sfnt_get_ushort(sfont); + table->maxComponentDepth = sfnt_get_ushort(sfont); + + return table; +} + +char *tt_pack_hhea_table (struct tt_hhea_table *table) +{ + int i; + char *p, *data; + + p = data = NEW(TT_HHEA_TABLE_SIZE, char); + p += sfnt_put_ulong(p, table->version); + p += sfnt_put_short(p, table->Ascender); + p += sfnt_put_short(p, table->Descender); + p += sfnt_put_short(p, table->LineGap); + p += sfnt_put_ushort(p, table->advanceWidthMax); + p += sfnt_put_short(p, table->minLeftSideBearing); + p += sfnt_put_short(p, table->minRightSideBearing); + p += sfnt_put_short(p, table->xMaxExtent); + p += sfnt_put_short(p, table->caretSlopeRise); + p += sfnt_put_short(p, table->caretSlopeRun); + for (i = 0; i < 5; i++) { + p += sfnt_put_short(p, table->reserved[i]); + } + p += sfnt_put_short(p, table->metricDataFormat); + p += sfnt_put_ushort(p, table->numberOfHMetrics); + + return data; +} + +struct tt_hhea_table * +tt_read_hhea_table (sfnt *sfont) +{ + int i; + struct tt_hhea_table *table = NULL; + + table = NEW(1, struct tt_hhea_table); + + sfnt_locate_table(sfont, "hhea"); + table->version = sfnt_get_ulong(sfont); + table->Ascender = sfnt_get_short (sfont); + table->Descender = sfnt_get_short(sfont); + table->LineGap = sfnt_get_short(sfont); + table->advanceWidthMax = sfnt_get_ushort(sfont); + table->minLeftSideBearing = sfnt_get_short(sfont); + table->minRightSideBearing = sfnt_get_short(sfont); + table->xMaxExtent = sfnt_get_short(sfont); + table->caretSlopeRise = sfnt_get_short(sfont); + table->caretSlopeRun = sfnt_get_short(sfont); + for(i = 0; i < 5; i++) { + table->reserved[i] = sfnt_get_short(sfont); + } + table->metricDataFormat = sfnt_get_short(sfont); + if (table->metricDataFormat != 0) + TT_ERROR("unknown metricDaraFormat"); + table->numberOfHMetrics = sfnt_get_ushort(sfont); + + return table; +} + +/* vhea */ +char * +tt_pack_vhea_table (struct tt_vhea_table *table) +{ + int i; + char *p, *data; + + p = data = NEW(TT_VHEA_TABLE_SIZE, char); + p += sfnt_put_ulong(p, table->version); + p += sfnt_put_short(p, table->vertTypoAscender); + p += sfnt_put_short(p, table->vertTypoDescender); + p += sfnt_put_short(p, table->vertTypoLineGap); + p += sfnt_put_short(p, table->advanceHeightMax); /* ushort ? */ + p += sfnt_put_short(p, table->minTopSideBearing); + p += sfnt_put_short(p, table->minBottomSideBearing); + p += sfnt_put_short(p, table->yMaxExtent); + p += sfnt_put_short(p, table->caretSlopeRise); + p += sfnt_put_short(p, table->caretSlopeRun); + p += sfnt_put_short(p, table->caretOffset); + for(i = 0; i < 5; i++) { + p += sfnt_put_short(p, table->reserved[i]); + } + p += sfnt_put_ushort(p, table->numOfLongVerMetrics); + + return data; +} + +struct tt_vhea_table *tt_read_vhea_table (sfnt *sfont) +{ + int i; + struct tt_vhea_table *table = NULL; + + table = NEW(1, struct tt_vhea_table); + + sfnt_locate_table(sfont, "vhea"); + table->version = sfnt_get_ulong(sfont); + table->vertTypoAscender = sfnt_get_short (sfont); + table->vertTypoDescender = sfnt_get_short(sfont); + table->vertTypoLineGap = sfnt_get_short(sfont); + table->advanceHeightMax = sfnt_get_short(sfont); /* ushort ? */ + table->minTopSideBearing = sfnt_get_short(sfont); + table->minBottomSideBearing = sfnt_get_short(sfont); + table->yMaxExtent = sfnt_get_short(sfont); + table->caretSlopeRise = sfnt_get_short(sfont); + table->caretSlopeRun = sfnt_get_short(sfont); + table->caretOffset = sfnt_get_short(sfont); + for(i=0;i<5;i++) { + (table->reserved)[i] = sfnt_get_short(sfont); + } + table->numOfLongVerMetrics = sfnt_get_ushort(sfont); + + return table; +} + + +struct tt_VORG_table * +tt_read_VORG_table (sfnt *sfont) +{ + struct tt_VORG_table *vorg; + ULONG offset; + USHORT i; + + offset = sfnt_find_table_pos(sfont, "VORG"); + + if (offset > 0) { + vorg = NEW(1, struct tt_VORG_table); + + sfnt_locate_table(sfont, "VORG"); + if (sfnt_get_ushort(sfont) != 1 || + sfnt_get_ushort(sfont) != 0) + TT_ERROR("Unsupported VORG version."); + + vorg->defaultVertOriginY = sfnt_get_short(sfont); + vorg->numVertOriginYMetrics = sfnt_get_ushort(sfont); + vorg->vertOriginYMetrics = NEW(vorg->numVertOriginYMetrics, + struct tt_vertOriginYMetrics); + /* + * The vertOriginYMetrics array must be sorted in increasing + * glyphIndex order. + */ + for (i = 0; + i < vorg->numVertOriginYMetrics; i++) { + vorg->vertOriginYMetrics[i].glyphIndex = sfnt_get_ushort(sfont); + vorg->vertOriginYMetrics[i].vertOriginY = sfnt_get_short(sfont); + } + } else { + vorg = NULL; + } + + return vorg; +} + +/* + * hmtx and vmtx + * + * Reading/writing hmtx and vmtx depend on other tables, maxp and hhea/vhea. + */ + +struct tt_longMetrics * +tt_read_longMetrics (sfnt *sfont, USHORT numGlyphs, USHORT numLongMetrics) +{ + struct tt_longMetrics *m; + USHORT gid, last_adv = 0; + + m = NEW(numGlyphs, struct tt_longMetrics); + for (gid = 0; gid < numGlyphs; gid++) { + if (gid < numLongMetrics) + last_adv = sfnt_get_ushort(sfont); + m[gid].sideBearing = sfnt_get_short(sfont); + m[gid].advance = last_adv; + } + + return m; +} + +/* OS/2 table */ +/* this table may not exist */ +struct tt_os2__table * +tt_read_os2__table (sfnt *sfont) +{ + struct tt_os2__table *table = NULL; + int i; + + if (sfnt_find_table_pos(sfont, "OS/2") == 0) + return NULL; + + sfnt_locate_table(sfont, "OS/2"); + + table = NEW(1, struct tt_os2__table); + + table->version = sfnt_get_ushort(sfont); + table->xAvgCharWidth = sfnt_get_short(sfont); + table->usWeightClass = sfnt_get_ushort(sfont); + table->usWidthClass = sfnt_get_ushort(sfont); + table->fsType = sfnt_get_short(sfont); + table->ySubscriptXSize = sfnt_get_short(sfont); + table->ySubscriptYSize = sfnt_get_short(sfont); + table->ySubscriptXOffset = sfnt_get_short(sfont); + table->ySubscriptYOffset = sfnt_get_short(sfont); + table->ySuperscriptXSize = sfnt_get_short(sfont); + table->ySuperscriptYSize = sfnt_get_short(sfont); + table->ySuperscriptXOffset = sfnt_get_short(sfont); + table->ySuperscriptYOffset = sfnt_get_short(sfont); + table->yStrikeoutSize = sfnt_get_short(sfont); + table->yStrikeoutPosition = sfnt_get_short(sfont); + table->sFamilyClass = sfnt_get_short(sfont); + for (i = 0; i < 10; i++) { + table->panose[i] = sfnt_get_byte(sfont); + } + table->ulUnicodeRange1 = sfnt_get_ulong(sfont); + table->ulUnicodeRange2 = sfnt_get_ulong(sfont); + table->ulUnicodeRange3 = sfnt_get_ulong(sfont); + table->ulUnicodeRange4 = sfnt_get_ulong(sfont); + for (i = 0; i < 4; i++) { + table->achVendID[i] = sfnt_get_char(sfont); + } + table->fsSelection = sfnt_get_ushort(sfont); + table->usFirstCharIndex = sfnt_get_ushort(sfont); + table->usLastCharIndex = sfnt_get_ushort(sfont); + table->sTypoAscender = sfnt_get_short(sfont); + table->sTypoDescender = sfnt_get_short(sfont); + table->sTypoLineGap = sfnt_get_short(sfont); + table->usWinAscent = sfnt_get_ushort(sfont); + table->usWinDescent = sfnt_get_ushort(sfont); + table->ulCodePageRange1 = sfnt_get_ulong(sfont); + table->ulCodePageRange2 = sfnt_get_ulong(sfont); + if (table->version == 0x0002) { + table->sxHeight = sfnt_get_short(sfont); + table->sCapHeight = sfnt_get_short(sfont); + table->usDefaultChar = sfnt_get_ushort(sfont); + table->usBreakChar = sfnt_get_ushort(sfont); + table->usMaxContext = sfnt_get_ushort(sfont); + } + + return table; +} + +USHORT +tt_get_name (sfnt *sfont, char *dest, USHORT destlen, + USHORT plat_id, USHORT enco_id, + USHORT lang_id, USHORT name_id) +{ + USHORT length = 0; + USHORT num_names, string_offset; + ULONG name_offset; + int i; + + name_offset = sfnt_locate_table (sfont, "name"); + + if (sfnt_get_ushort(sfont)) + TT_ERROR ("Expecting zero"); + + num_names = sfnt_get_ushort(sfont); + string_offset = sfnt_get_ushort(sfont); + for (i=0;i destlen - 1) { + fprintf(stderr, "\n** Notice: Name string too long. Truncating **\n"); + length = destlen - 1; + } + sfnt_seek_set (sfont, name_offset+string_offset+offset); + sfnt_read((unsigned char*)dest, length, sfont); + dest[length] = '\0'; + break; + } + } + if (i == num_names) { + length = 0; + } + + return length; +} + +USHORT +tt_get_ps_fontname (sfnt *sfont, char *dest, USHORT destlen) +{ + USHORT namelen = 0; + +#ifdef XETEX + + const char* name = FT_Get_Postscript_Name(sfont->ft_face); + namelen = strlen(name); + if (namelen > destlen - 1) { + strncpy(dest, name, destlen - 1); + dest[destlen] = 0; + } + else + strcpy(dest, name); + +#else + + /* First try Mac-Roman PS name and then Win-Unicode PS name */ + if ((namelen = tt_get_name(sfont, dest, destlen, 1, 0, 0, 6)) != 0 || + (namelen = tt_get_name(sfont, dest, destlen, 3, 1, 0x409u, 6)) != 0 || + (namelen = tt_get_name(sfont, dest, destlen, 3, 5, 0x412u, 6)) != 0) + return namelen; + + fprintf(stderr, "\n** Warning: No valid PostScript name available **\n"); + /* + Wrokaround for some bad TTfonts: + Language ID value 0xffffu for `accept any language ID' + */ + if ((namelen = tt_get_name(sfont, dest, destlen, 1, 0, 0xffffu, 6)) == 0) { + /* + Finally falling back to Mac Roman name field. + Warning: Some bad Japanese TTfonts using SJIS encoded string in the + Mac Roman name field. + */ + namelen = tt_get_name(sfont, dest, destlen, 1, 0, 0, 1); + } + +#endif + + return namelen; +} diff --git a/Build/source/texk/web2c/luatexdir/font/tt_table.h b/Build/source/texk/web2c/luatexdir/font/tt_table.h new file mode 100644 index 00000000000..ffb2c5b8f45 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/font/tt_table.h @@ -0,0 +1,193 @@ +/* $Header: /home/cvsroot/dvipdfmx/src/tt_table.h,v 1.6 2004/09/11 14:50:29 hirata Exp $ + + This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. + + Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata, + the dvipdfmx project team + + 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. +*/ + +#ifndef _TT_TABLE_H_ +#define _TT_TABLE_H_ + +#include "sfnt.h" + +#define TT_HEAD_TABLE_SIZE 54UL +#define TT_MAXP_TABLE_SIZE 32UL +#define TT_HHEA_TABLE_SIZE 36UL +#define TT_VHEA_TABLE_SIZE 36UL + +struct tt_head_table +{ + Fixed version; + Fixed fontRevision; + ULONG checkSumAdjustment; + ULONG magicNumber; + USHORT flags; + USHORT unitsPerEm; + BYTE created[8]; + BYTE modified[8]; + FWord xMin, yMin, xMax, yMax; + USHORT macStyle; + USHORT lowestRecPPEM; + SHORT fontDirectionHint; + SHORT indexToLocFormat; + SHORT glyphDataFormat; +}; + +struct tt_hhea_table +{ + Fixed version; + FWord Ascender; + FWord Descender; + FWord LineGap; + uFWord advanceWidthMax; + FWord minLeftSideBearing; + FWord minRightSideBearing; + FWord xMaxExtent; + SHORT caretSlopeRise; + SHORT caretSlopeRun; + SHORT reserved[5]; /* set to 0 */ + SHORT metricDataFormat; + USHORT numberOfHMetrics; +}; + +struct tt_vhea_table +{ + Fixed version; + SHORT vertTypoAscender; /* v.1.1 name */ + SHORT vertTypoDescender; /* v.1.1 name */ + SHORT vertTypoLineGap; /* v.1.1 name */ + SHORT advanceHeightMax; + SHORT minTopSideBearing; + SHORT minBottomSideBearing; + SHORT yMaxExtent; + SHORT caretSlopeRise; + SHORT caretSlopeRun; + SHORT caretOffset; + SHORT reserved[5]; /* set to 0 */ + USHORT numOfLongVerMetrics; +}; + +struct tt_maxp_table +{ + Fixed version; + USHORT numGlyphs; + USHORT maxPoints; + USHORT maxContours; + USHORT maxComponentPoints; + USHORT maxComponentContours; + USHORT maxZones; + USHORT maxTwilightPoints; + USHORT maxStorage; + USHORT maxFunctionDefs; + USHORT maxInstructionDefs; + USHORT maxStackElements; + USHORT maxSizeOfInstructions; + USHORT maxComponentElements; + USHORT maxComponentDepth; +}; + +struct tt_os2__table +{ + USHORT version; /* 0x0001 or 0x0002 */ + SHORT xAvgCharWidth; + USHORT usWeightClass; + USHORT usWidthClass; + SHORT fsType; /* if (faType & 0x08) editable_embedding */ + SHORT ySubscriptXSize; + SHORT ySubscriptYSize; + SHORT ySubscriptXOffset; + SHORT ySubscriptYOffset; + SHORT ySuperscriptXSize; + SHORT ySuperscriptYSize; + SHORT ySuperscriptXOffset; + SHORT ySuperscriptYOffset; + SHORT yStrikeoutSize; + SHORT yStrikeoutPosition; + SHORT sFamilyClass; + BYTE panose[10]; + ULONG ulUnicodeRange1; + ULONG ulUnicodeRange2; + ULONG ulUnicodeRange3; + ULONG ulUnicodeRange4; + ICHAR achVendID[4]; + USHORT fsSelection; + USHORT usFirstCharIndex; + USHORT usLastCharIndex; + SHORT sTypoAscender; /* TTF spec. from MS is wrong */ + SHORT sTypoDescender; /* TTF spec. from MS is wrong */ + SHORT sTypoLineGap; /* TTF spec. from MS is wrong */ + USHORT usWinAscent; + USHORT usWinDescent; + ULONG ulCodePageRange1; + ULONG ulCodePageRange2; + /* version 0x0002 */ + SHORT sxHeight; + SHORT sCapHeight; + USHORT usDefaultChar; + USHORT usBreakChar; + USHORT usMaxContext; +}; + +struct tt_vertOriginYMetrics { + USHORT glyphIndex; + SHORT vertOriginY; +}; + +struct tt_VORG_table { + SHORT defaultVertOriginY; + USHORT numVertOriginYMetrics; + struct tt_vertOriginYMetrics *vertOriginYMetrics; +}; + +/* hmtx and vmtx */ +struct tt_longMetrics +{ + USHORT advance; + SHORT sideBearing; +}; + + +/* head, hhea, maxp */ +extern char *tt_pack_head_table (struct tt_head_table *table); +extern struct tt_head_table *tt_read_head_table (sfnt *sfont); +extern char *tt_pack_hhea_table (struct tt_hhea_table *table); +extern struct tt_hhea_table *tt_read_hhea_table (sfnt *sfont); +extern char *tt_pack_maxp_table (struct tt_maxp_table *table); +extern struct tt_maxp_table *tt_read_maxp_table (sfnt *sfont); + +/* vhea */ +extern char *tt_pack_vhea_table (struct tt_vhea_table *table); +extern struct tt_vhea_table *tt_read_vhea_table (sfnt *sfont); + +/* VORG */ +extern struct tt_VORG_table *tt_read_VORG_table (sfnt *sfont); + +/* hmtx and vmtx */ +extern struct tt_longMetrics *tt_read_longMetrics (sfnt *sfont, + USHORT numGlyphs, USHORT numLongMetrics); + +/* OS/2 table */ +extern struct tt_os2__table *tt_read_os2__table (sfnt *sfont); + +/* name table */ +extern USHORT tt_get_name (sfnt *sfont, char *dest, USHORT destlen, + USHORT plat_id, USHORT enco_id, + USHORT lang_id, USHORT name_id); +extern USHORT tt_get_ps_fontname (sfnt *sfont, char *dest, USHORT destlen); + +#endif /* _TT_TABLE_H_ */ diff --git a/Build/source/texk/web2c/luatexdir/font/vfovf.c b/Build/source/texk/web2c/luatexdir/font/vfovf.c new file mode 100644 index 00000000000..0f23cb07b94 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/font/vfovf.c @@ -0,0 +1,1349 @@ +/* +Copyright (c) 1996-2006 Taco Hoekwater + +This file is part of LuaTeX. + +LuaTeX 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. + +LuaTeX 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 LuaTeX; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +$Id: vfovf.c 1022 2008-02-14 11:49:30Z taco $ +*/ + +#include "ptexlib.h" + +#include "luatex-api.h" + +/* this is a hack! */ +#define font_max 5000 + +#define set_char_0 0 /* typeset character 0 and move right */ +#define set1 128 /* typeset a character and move right */ +#define set2 129 /* typeset a character and move right */ +#define set3 130 /* typeset a character and move right */ +#define set4 131 /* typeset a character and move right */ +#define set_rule 132 /* typeset a rule and move right */ +#define put1 133 /* typeset a character without moving */ +#define put2 134 /* typeset a character without moving */ +#define put3 135 /* typeset a character without moving */ +#define put4 136 /* typeset a character without moving */ +#define put_rule 137 /* typeset a rule */ +#define nop 138 /* no operation */ +#define bop 139 /* beginning of page */ +#define eop 140 /* ending of page */ +#define push 141 /* save the current positions */ +#define pop 142 /* restore previous positions */ +#define right1 143 /* move right */ +#define right2 144 /* move right */ +#define right3 145 /* move right */ +#define right4 146 /* move right, 4 bytes */ +#define w0 147 /* move right by |w| */ +#define w1 148 /* move right and set |w| */ +#define w2 149 /* move right and set |w| */ +#define w3 150 /* move right and set |w| */ +#define w4 151 /* move right and set |w| */ +#define x0 152 /* move right by |x| */ +#define x1 153 /* move right and set |x| */ +#define x2 154 /* move right and set |x| */ +#define x3 155 /* move right and set |x| */ +#define x4 156 /* move right and set |x| */ +#define down1 157 /* move down */ +#define down2 158 /* move down */ +#define down3 159 /* move down */ +#define down4 160 /* move down, 4 bytes */ +#define y0 161 /* move down by |y| */ +#define y1 162 /* move down and set |y| */ +#define y2 163 /* move down and set |y| */ +#define y3 164 /* move down and set |y| */ +#define y4 165 /* move down and set |y| */ +#define z0 166 /* move down by |z| */ +#define z1 167 /* move down and set |z| */ +#define z2 168 /* move down and set |z| */ +#define z3 169 /* move down and set |z| */ +#define z4 170 /* move down and set |z| */ +#define fnt_num_0 171 /* set current font to 0 */ +#define fnt1 235 /* set current font */ +#define fnt2 236 /* set current font */ +#define fnt3 237 /* set current font */ +#define fnt4 238 /* set current font */ +#define xxx1 239 /* extension to DVI primitives */ +#define xxx2 240 /* extension to DVI primitives */ +#define xxx3 241 /* extension to DVI primitives */ +#define xxx4 242 /* potentially long extension to DVI primitives */ +#define fnt_def1 243 /* define the meaning of a font number */ +#define pre 247 /* preamble */ +#define post 248 /* postamble beginning */ +#define post_post 249 /* postamble ending */ +#define yyy1 250 /* PDF literal text */ +#define yyy2 251 /* PDF literal text */ +#define yyy3 252 /* PDF literal text */ +#define yyy4 253 /* PDF literal text */ + +#define null_font 0 + +#define long_char 242 /* \.{VF} command for general character packet */ +#define vf_id 202 /* identifies \.{VF} files */ + +/* go out \.{VF} processing with an error message */ +#define bad_vf(a) { xfree(vf_buffer); print_nlp(); \ + print_string("Error in processing VF font ("); \ + print_string(font_name(f)); \ + print_string(".vf): "); \ + print_string(a); \ + print_string(", virtual font will be ignored"); \ + print_ln(); return; } + +#define lua_bad_vf(a) { xfree(vf_buffer); \ + lua_settop(L,s_top); \ + lua_pushnil(L); \ + lua_pushstring(L,a); \ + return 2; } + +#define tmp_b0 tmp_w.qqqq.b0 +#define tmp_b1 tmp_w.qqqq.b1 +#define tmp_b2 tmp_w.qqqq.b2 +#define tmp_b3 tmp_w.qqqq.b3 +#define tmp_int tmp_w.cint + +#define vf_stack_size 100 /* \.{DVI} files shouldn't |push| beyond this depth */ + +typedef unsigned char vf_stack_index ; /* an index into the stack */ + +typedef struct vf_stack_record { + scaled stack_w, stack_x, stack_y, stack_z; +} vf_stack_record; + +boolean auto_expand_vf(internal_font_number f); /* forward */ + +/* get a byte from\.{VF} file */ + +#define vf_byte(a) { real_eight_bits vf_tmp_b; \ + if (vf_cur>=vf_size) { \ + pdftex_fail("unexpected eof on virtual font"); \ + } \ + vf_tmp_b = vf_buffer[vf_cur++] ; a = vf_tmp_b; } + + +#define vf_replace_z() { \ + vf_alpha=16; \ + while (vf_z>=040000000) { \ + vf_z= vf_z / 2; \ + vf_alpha += vf_alpha; \ + } \ + vf_beta=256 / vf_alpha; \ + vf_alpha=vf_alpha*vf_z; } + +/* read |k| bytes as an integer from \.{VF} file */ + +#define vf_read(k,l) { integer itmp = 0, dtmp = k, jtmp = 0; \ + while (dtmp > 0) { \ + vf_byte(jtmp); \ + if ((dtmp==k) && jtmp>127) \ + jtmp = jtmp - 256; \ + itmp = itmp*256 + jtmp; \ + decr(dtmp); \ + } \ + l = itmp; } + +#define vf_read_u(k,l) { unsigned int dtmp=k, itmp = 0, jtmp = 0; \ + while (dtmp-- > 0) { \ + vf_byte(jtmp); \ + itmp = itmp*256 + jtmp; \ + } \ + l = itmp; } + +void +pdf_check_vf_cur_val (void) { + internal_font_number f; + f = cur_val; + if (font_type(f) == virtual_font_type) + pdf_error("font", "command cannot be used with virtual font"); +} + +static void +vf_local_font_warning(internal_font_number f, internal_font_number k, char *s, integer a, integer b) { + print_nlp(); + print_string(s); + print_string(" in local font "); + print_string(font_name(k)); + print_string(" ("); + print_int(b); + print_string(" != "); + print_int(a); + print_string(") in virtual font "); + print_string(font_name(f)); + print_string(".vf ignored."); +} + + +/* process a local font in \.{VF} file */ + +internal_font_number +vf_def_font(internal_font_number f,unsigned char *vf_buffer, integer *vf_cr) { + internal_font_number k; + str_number s; + scaled ds,fs; + four_quarters cs; + memory_word tmp_w; /* accumulator */ + integer junk; + unsigned long checksum; + cs.b0 = vf_buffer[(*vf_cr)]; + cs.b1 = vf_buffer[(*vf_cr)+1]; + cs.b2 = vf_buffer[(*vf_cr)+2]; + cs.b3 = vf_buffer[(*vf_cr)+3]; (*vf_cr)+=4; + checksum = cs.b0*256*256*256 + cs.b1*256*256 + cs.b2*256 + cs.b3; + k = vf_buffer[(*vf_cr)] ; (*vf_cr)++; + if (k>127) k-=256; + k = k*256+ vf_buffer[(*vf_cr)] ; (*vf_cr)++; + k = k*256+ vf_buffer[(*vf_cr)] ; (*vf_cr)++; + k = k*256+ vf_buffer[(*vf_cr)] ; (*vf_cr)++; + + fs = sqxfw(k, font_size(f)); + + k = vf_buffer[(*vf_cr)] ; (*vf_cr)++; + if (k>127) k-=256; + k = k*256+ vf_buffer[(*vf_cr)] ; (*vf_cr)++; + k = k*256+ vf_buffer[(*vf_cr)] ; (*vf_cr)++; + k = k*256+ vf_buffer[(*vf_cr)] ; (*vf_cr)++; + + ds = k / 16; + + + tmp_b0 = vf_buffer[(*vf_cr)] ; (*vf_cr)++; + tmp_b1 = vf_buffer[(*vf_cr)] ; (*vf_cr)++; + while (tmp_b0 > 0) { + tmp_b0--; + (*vf_cr)++; /* skip the font path */ + } + string_room(tmp_b1); + while (tmp_b1 > 0) { + tmp_b1--; + junk = vf_buffer[(*vf_cr)] ; (*vf_cr)++; + append_pool_char(junk); + } + s = make_string(); + k = tfm_lookup(s, fs); + if (k == null_font) + k = read_font_info(get_nullcs(), s, get_nullstr(), fs, -1); + if (k != null_font) { + if (checksum!=0 && font_checksum(k)!=0 && checksum!= font_checksum(k)) + vf_local_font_warning(f, k, "checksum mismatch",checksum,font_checksum(k)); + if (ds != font_dsize(k)) + vf_local_font_warning(f, k, "design size mismatch",ds,font_dsize(k)); + } + if (pdf_font_expand_ratio(f) != 0) + set_expand_params(k, pdf_font_auto_expand(f), + pdf_font_expand_ratio(pdf_font_stretch(f)), + -pdf_font_expand_ratio(pdf_font_shrink(f)), + pdf_font_step(f), pdf_font_expand_ratio(f)); + return k; +} + + +int +open_vf_file (char *fn, unsigned char **vbuffer, integer *vsize) { + boolean res; /* was the callback successful? */ + integer callback_id; + boolean file_read; /* was |vf_file| successfully read? */ + FILE *vf_file; + char *fnam = NULL; + + + + + namelength = strlen(fn); + nameoffile = xmalloc(namelength+2); + strcpy((char *)(nameoffile+1),fn); + + callback_id=callback_defined(find_vf_file_callback); + if (callback_id>0) { + res = run_callback(callback_id,"S->S",fn, &fnam); + if (res && (fnam!=NULL) && (strlen(fnam)>0)) { + /* @; */ + free(nameoffile); + namelength = strlen(fnam); + nameoffile = xmalloc(namelength+2); + strcpy((char *)(nameoffile+1),fnam); + } else { + return 0; + } + } + callback_id=callback_defined(read_vf_file_callback); + if (callback_id>0) { + file_read = false; + res = run_callback(callback_id,"S->bSd",stringcast(nameoffile+1), + &file_read, vbuffer,vsize); + if (res && file_read && (*vsize>0)) { + return 1; + } + if (!file_read) + return 0; /* -1 */ + } else { + if (ovf_b_open_in(vf_file) || vf_b_open_in(vf_file)) { + res = read_vf_file(vf_file,vbuffer,vsize); + b_close(vf_file); + if (res) { + return 1; + } + } else { + return 0; /* -1 */ + } + } + return 0; +} + + +/* + @ The |do_vf| procedure attempts to read the \.{VF} file for a font, and sets + |font_type()| to |real_font_type| if the \.{VF} file could not be found + or loaded, otherwise sets |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|. +*/ + +#define append_packet(k) vpackets[vf_np++] = k + +/* life is easier if all internal font commands are fnt4 and + all character commands are set4 or put4 */ + +#define append_fnt_set(k) { \ + assert(k>0) ; \ + append_packet(packet_font_code); \ + append_four(k); } + +#define append_four(k) { \ + append_packet((k&0xFF000000)>>24); \ + append_packet((k&0x00FF0000)>>16); \ + append_packet((k&0x0000FF00)>>8); \ + append_packet((k&0x000000FF)); } + +/* some of these things happen twice, adding a define is simplest */ + +#define test_checksum() { vf_byte(tmp_b0); vf_byte(tmp_b1); \ + vf_byte(tmp_b2); vf_byte(tmp_b3); \ + if (((tmp_b0 != 0) || (tmp_b1 != 0) || (tmp_b2 != 0) || (tmp_b3 != 0)) && \ + ((font_check_0(f) != 0) || (font_check_1(f) != 0) || \ + (font_check_2(f) != 0) || (font_check_3(f) != 0)) && \ + ((tmp_b0 != font_check_0(f)) || (tmp_b1 != font_check_1(f)) || \ + (tmp_b2 != font_check_2(f)) || (tmp_b3 != font_check_3(f)))) { \ + print_nlp(); \ + print_string("checksum mismatch in font "); \ + print_string(font_name(f)); \ + print_string(".vf ignored "); } } + +#define test_dsize() { int read_tmp; vf_read(4,read_tmp); \ + if ((read_tmp / 16) != font_dsize(f)) { \ + print_nlp(); \ + print_string("design size mismatch in font "); \ + print_string(font_name(f)); \ + print_string(".vf ignored"); \ + } } + + +int count_packet_bytes (real_eight_bits *vf_buf, int cur_bute, int count) { + int k = 0; + int ff = 0; + int acc = 0; + unsigned int cmd = 0; + unsigned int d = 0; + while (k= set_char_0) && (cmd < set1)) { + if (ff==0) { ff = 1; acc+=5; } + acc+=5; + } else if ((fnt_num_0 <= cmd) && (cmd <= fnt_num_0 + 63)) { + ff = 1; + acc+=5; + } else { + switch (cmd) { + case fnt1: acc+=5; k+=1; ff=1 ; break; + case fnt2: acc+=5; k+=2; ff=1 ; break; + case fnt3: acc+=5; k+=3; ff=1 ; break; + case fnt4: acc+=5; k+=4; ff=1 ; break; + case set_rule: acc+=9; k+=8; break; + case put_rule: acc+=11; k+=8; break; + case set1: acc+=5; k+=1; if (ff==0) { ff = 1; acc+=5; } break; + case set2: acc+=5; k+=2; if (ff==0) { ff = 1; acc+=5; } break; + case set3: acc+=5; k+=3; if (ff==0) { ff = 1; acc+=5; } break; + case set4: acc+=5; k+=4; if (ff==0) { ff = 1; acc+=5; } break; + case put1: acc+=7; k+=1; if (ff==0) { ff = 1; acc+=5; } break; + case put2: acc+=7; k+=2; if (ff==0) { ff = 1; acc+=5; } break; + case put3: acc+=7; k+=3; if (ff==0) { ff = 1; acc+=5; } break; + case put4: acc+=7; k+=4; if (ff==0) { ff = 1; acc+=5; } break; + case right1: acc+=5; k+=1; break; + case right2: acc+=5; k+=2; break; + case right3: acc+=5; k+=3; break; + case right4: acc+=5; k+=4; break; + case w1: acc+=5; k+=1; break; + case w2: acc+=5; k+=2; break; + case w3: acc+=5; k+=3; break; + case w4: acc+=5; k+=4; break; + case x1: acc+=5; k+=1; break; + case x2: acc+=5; k+=2; break; + case x3: acc+=5; k+=3; break; + case x4: acc+=5; k+=4; break; + case down1: acc+=5; k+=1; break; + case down2: acc+=5; k+=2; break; + case down3: acc+=5; k+=3; break; + case down4: acc+=5; k+=4; break; + case y1: acc+=5; k+=1; break; + case y2: acc+=5; k+=2; break; + case y3: acc+=5; k+=3; break; + case y4: acc+=5; k+=4; break; + case z1: acc+=5; k+=1; break; + case z2: acc+=5; k+=2; break; + case z3: acc+=5; k+=3; break; + case z4: acc+=5; k+=4; break; + case xxx1: + d = vf_buf[cur_bute+k]; k++; + k += d; acc += 5 + d; + break; + case xxx2: + d = vf_buf[cur_bute+k]; k++; + d = d*256 + vf_buf[cur_bute+k]; k++; + k += d; acc += 5 + d; + break; + case xxx3: + d = vf_buf[cur_bute+k]; k++; + d = d*256 + vf_buf[cur_bute+k]; k++; + d = d*256 + vf_buf[cur_bute+k]; k++; + k += d; acc += 5 + d; + break; + case xxx4: + d = vf_buf[cur_bute+k]; k++; + d = d*256 + vf_buf[cur_bute+k]; k++; + d = d*256 + vf_buf[cur_bute+k]; k++; + d = d*256 + vf_buf[cur_bute+k]; k++; + k += d; acc += 5 + d; + break; + case w0: acc+=5; break; + case x0: acc+=5; break; + case y0: acc+=5; break; + case z0: acc+=5; break; + case nop: break; + case push: acc+=1; break; + case pop: acc+=1; break; + } + } + } + return (acc+1); +} + +void +do_vf(internal_font_number f) { + integer k, n, i; + unsigned cmd; + scaled x,y,w,z,h,v; + integer cc, cmd_length, packet_length; + charinfo *co; + scaled tfm_width; + integer save_cur_byte; + vf_stack_index stack_level; + integer vf_z; /* multiplier */ + integer vf_alpha; /* correction for negative values */ + char vf_beta; /* divisor */ + integer vf_np; + real_eight_bits *vpackets; + memory_word tmp_w; /* accumulator */ + vf_stack_record vf_stack[256]; + integer junk; + unsigned char *vf_buffer; + integer vf_size; + integer vf_cur; + integer *vf_local_fnts = NULL; /* external font ids */ + integer *vf_real_fnts = NULL; /* internal font ids */ + unsigned vf_nf = 0; /* local font counter */ + + if (font_type(f)!= unknown_font_type) + return; + set_font_type(f,real_font_type); + if (auto_expand_vf(f)) + return; /* auto-expanded virtual font */ + stack_level = 0; + /* @; */ + vf_cur=0; vf_buffer=NULL; vf_size=0; + if (!open_vf_file(font_name(f), &vf_buffer, &vf_size)) + return; + /* @;@/ */ + set_font_type(f,virtual_font_type); + vf_byte(k); + if (k != pre) + bad_vf("PRE command expected"); + vf_byte(k); + if (k != vf_id) + bad_vf("wrong id byte"); + vf_byte(cmd_length); + for (k = 1;k<= cmd_length;k++) + vf_byte(junk); + test_checksum(); + test_dsize(); + /* update_terminal;*/ + vf_z = font_size(f); + vf_replace_z(); + /* @;@/ */ + /* scan forward to find the number of internal fonts */ + vf_nf = 0; + save_cur_byte = vf_cur; + vf_byte(cmd); + while ((cmd >= fnt_def1) && (cmd <= (fnt_def1 + 3))) { + vf_read((cmd - fnt_def1 + 1),junk); + vf_read(4,junk); + vf_read(4,junk); + vf_read(4,junk); + vf_byte(k); + vf_byte(junk); + k += junk; + while (k-- > 0) { vf_byte(junk); } + incr(vf_nf); + vf_byte(cmd); + } + vf_cur = save_cur_byte; + vf_byte(cmd); + /* malloc and fill the local font arrays */ + if (vf_nf>0) { + i = vf_nf*sizeof(integer); + vf_local_fnts= xmalloc(i); + memset(vf_local_fnts,0,i); + vf_real_fnts= xmalloc(i); + memset(vf_real_fnts,0,i); + vf_nf = 0; + while ((cmd >= fnt_def1) && (cmd <= (fnt_def1 + 3))) { + vf_read_u((cmd - fnt_def1 + 1),vf_local_fnts[vf_nf]); + vf_real_fnts[vf_nf] = vf_def_font(f, vf_buffer, &vf_cur); + incr(vf_nf); + vf_byte(cmd); + } + } + + + while (cmd <= long_char) { + /* @;@/ */ + vf_np = 0; + if (cmd == long_char) { + vf_read_u(4,packet_length); + vf_read_u(4,cc); + if (!char_exists(f,cc)) { + bad_vf("invalid character code"); + } + vf_read(4,k); + tfm_width = sqxfw(k, font_size(f)); + } else { + packet_length = cmd; + vf_byte(cc); + if (!char_exists(f,cc)) { + bad_vf("invalid character code"); + } + vf_read(3,k); + tfm_width = sqxfw(k, font_size(f)); + } + if (packet_length < 0) + bad_vf("negative packet length"); + if (tfm_width != char_width(f,cc)) { + /* precisely 'one off' errors are rampant */ + if (abs(tfm_width - char_width(f,cc))>1) { + print_nlp(); + print_string("character width mismatch in font "); + print_string(font_name(f)); + print_string(".vf ignored"); + } + } + k = count_packet_bytes(vf_buffer,vf_cur,packet_length); + vpackets = xmalloc(k+1); + co = get_charinfo(f,cc); + k = 0; + w = 0; x = 0; y = 0; z = 0; + while (packet_length > 0) { + vf_byte(cmd); + decr(packet_length); + + if ((cmd >= set_char_0) && (cmd < set1)) { + if (k == 0) { + k = vf_real_fnts[0]; + append_fnt_set(k); + } + append_packet(packet_char_code); + append_four(cmd); + cmd_length = 0; + cmd = nop; + + } else if (((fnt_num_0 <= cmd) && (cmd <= fnt_num_0 + 63)) || + ((fnt1 <= cmd) && (cmd <= fnt1 + 3))) { + if (cmd >= fnt1) { + vf_read_u((cmd - fnt1 + 1),k); + packet_length -= (cmd - fnt1 + 1); + } else { + k = cmd - fnt_num_0; + } + + /* change from local to external font id */ + n = 0; + while ((n < vf_nf) && (vf_local_fnts[n] != k)) + n++; + if (n==vf_nf) + bad_vf("undefined local font"); + + k = vf_real_fnts[n]; + append_fnt_set(k); + cmd_length = 0; + cmd = nop; + } else { + switch (cmd) { + case set_rule: + vf_read(4,h); vf_read(4,v); + append_packet(packet_rule_code); + append_four(h); + append_four(v); + packet_length -= 8; + break; + case put_rule: + vf_read(4,h); vf_read(4,v); + append_packet(packet_push_code); + append_packet(packet_rule_code); + append_four(h); + append_four(v); + append_packet(packet_pop_code); + packet_length -= 8; + break; + case set1: + case set2: + case set3: + case set4: + if (k == 0) { + k = vf_real_fnts[0]; + append_fnt_set(k); + } + vf_read_u((cmd - set1 + 1),i); + append_packet(packet_char_code); + append_four(i); + packet_length -= (cmd - set1 + 1); + break; + case put1: + case put2: + case put3: + case put4: + if (k == 0) { + k = vf_real_fnts[0]; + append_fnt_set(k); + } + vf_read_u((cmd - put1 + 1),i); + append_packet(packet_push_code); + append_packet(packet_char_code); + append_four(i); + append_packet(packet_pop_code); + packet_length -= (cmd - put1 + 1); + break; + case right1: + case right2: + case right3: + case right4: + vf_read((cmd - right1 + 1),i); + append_packet(packet_right_code); + append_four(i); + packet_length -= (cmd - right1 + 1); + break; + case w1: + case w2: + case w3: + case w4: + vf_read((cmd - w1 + 1),w); + append_packet(packet_right_code); + append_four(w); + packet_length -= (cmd - w1 + 1); + break; + case x1: + case x2: + case x3: + case x4: + vf_read((cmd - x1 + 1),x); + append_packet(packet_right_code); + append_four(x); + packet_length -= (cmd - x1 + 1); + break; + case down1: + case down2: + case down3: + case down4: + vf_read((cmd - down1 + 1),i); + append_packet(packet_down_code); + append_four(i); + packet_length -= (cmd - down1 + 1); + break; + case y1: + case y2: + case y3: + case y4: + vf_read((cmd - y1 + 1),y); + append_packet(packet_down_code); + append_four(y); + packet_length -= (cmd - y1 + 1); + break; + case z1: + case z2: + case z3: + case z4: + vf_read((cmd - z1 + 1),z); + append_packet(packet_down_code); + append_four(z); + packet_length -= (cmd - z1 + 1); + break; + case xxx1: + case xxx2: + case xxx3: + case xxx4: + vf_read_u((cmd - xxx1 + 1),cmd_length); + packet_length -= (cmd - xxx1 + 1); + if (cmd_length <= 0) + bad_vf("special of negative length"); + packet_length -= cmd_length; + + append_packet(packet_special_code); + append_four(cmd_length); + while (cmd_length > 0) { + cmd_length--; + vf_byte(i); + append_packet(i); + } + append_packet(0); + break; + case w0: + append_packet(packet_right_code); + append_four(w); + break; + case x0: + append_packet(packet_right_code); + append_four(x); + break; + case y0: + append_packet(packet_down_code); + append_four(y); + break; + case z0: + append_packet(packet_down_code); + append_four(z); + break; + case nop: + break; + case push: + if (stack_level == vf_stack_size) { + overflow_string("virtual font stack size", vf_stack_size); + } else { + vf_stack[stack_level].stack_w = w; + vf_stack[stack_level].stack_x = x; + vf_stack[stack_level].stack_y = y; + vf_stack[stack_level].stack_z = z; + incr(stack_level); + append_packet(packet_push_code); + } + break; + case pop: + if (stack_level == 0) { + bad_vf("more POPs than PUSHs in character"); + } else { + decr(stack_level); + w = vf_stack[stack_level].stack_w; + x = vf_stack[stack_level].stack_x; + y = vf_stack[stack_level].stack_y; + z = vf_stack[stack_level].stack_z; + append_packet(packet_pop_code); + } + break; + default: + bad_vf("improver DVI command"); + } + } + } + /* signal end of packet */ + append_packet(packet_end_code); + + if (stack_level != 0) + bad_vf("more PUSHs than POPs in character packet"); + if (packet_length != 0) + bad_vf("invalid packet length or DVI command in packet"); + /* @; */ + set_charinfo_packets(co,vpackets); + vf_byte(cmd); + } + if (cmd != post) + bad_vf("POST command expected"); + + xfree(vf_buffer); +} + +#define make_command0(N,K) { \ + lua_newtable(L); \ + lua_pushstring(L, N); \ + lua_rawseti(L,-2, 1); \ + lua_rawseti(L,-2, K); \ + K++; } + +#define make_command1(N,V,K) { \ + lua_newtable(L); \ + lua_pushstring(L, N); \ + lua_rawseti(L,-2, 1); \ + lua_pushnumber(L, V); \ + lua_rawseti(L,-2, 2); \ + lua_rawseti(L,-2, K); \ + K++; } + +#define make_command2(N,V,W,K) { \ + lua_newtable(L); \ + lua_pushstring(L, N); \ + lua_rawseti(L,-2, 1); \ + lua_pushnumber(L, V); \ + lua_rawseti(L,-2, 2); \ + lua_pushnumber(L, W); \ + lua_rawseti(L,-2, 3); \ + lua_rawseti(L,-2, K); \ + K++; } + +#define make_commands(N,S,V,K) { \ + lua_newtable(L); \ + lua_pushstring(L, N); \ + lua_rawseti(L,-2, 1); \ + lua_pushlstring(L, S, V); \ + lua_rawseti(L,-2, 2); \ + lua_rawseti(L,-2, K); \ + K++; } + + +int +make_vf_table(lua_State *L, char *cnom, scaled atsize) { + integer cmd, k, i; + integer cc, cmd_length, packet_length; + scaled tfm_width; + vf_stack_index stack_level; + integer vf_z; /* multiplier */ + integer vf_alpha; /* correction for negative values */ + char vf_beta; /* divisor */ + char *s; + scaled h,v; + scaled w, x, y, z; + integer s_top; /* lua stack */ + integer vf_nf ; /* local font counter */ + scaled ds,fs; + four_quarters cs; + memory_word tmp_w; /* accumulator */ + vf_stack_record vf_stack[256]; + unsigned char *vf_buffer; + integer vf_size; + integer vf_cur; + + + stack_level = 0; + /* @; */ + vf_cur=0; vf_buffer=NULL; vf_size=0; + if (!open_vf_file(cnom, &vf_buffer, &vf_size)) { + lua_pushnil(L); + return 1; + } + + /* start by creating a table */ + s_top = lua_gettop(L); + lua_newtable(L); + + /* @;@/ */ + vf_byte(k); + if (k != pre) + lua_bad_vf("PRE command expected"); + vf_byte(k); + if (k != vf_id) + lua_bad_vf("wrong id byte"); + vf_byte(cmd_length); + + s = xmalloc(cmd_length); + for (k = 1;k<= cmd_length;k++) + vf_byte(s[(k-1)]); + + lua_pushlstring(L,s,cmd_length); + free(s); + lua_setfield(L,-2,"header"); + + vf_byte(cs.b0); vf_byte(cs.b1); vf_byte(cs.b2); vf_byte(cs.b3); + lua_pushnumber(L, (unsigned long)(cs.b0<<24)+(cs.b1<<16)+(cs.b2<<8)+cs.b3 ); + lua_setfield(L,-2,"checksum"); + + vf_read(4,k); + ds = k /16; + lua_pushinteger(L,ds); + lua_setfield(L,-2,"designsize"); + + + lua_pushstring(L,cnom); + lua_setfield(L,-2,"name"); + + lua_pushinteger(L,atsize); + lua_setfield(L,-2,"size"); + + + /* update_terminal;*/ + vf_z = atsize; + vf_replace_z(); + /* @;@/ */ + vf_byte(cmd); + lua_newtable(L); + + i = 1; + while ((cmd >= fnt_def1) && (cmd <= fnt_def1 + 3)) { + + lua_newtable(L); + vf_read_u((cmd - fnt_def1 + 1),vf_nf); + vf_nf++; + /* checksum */ + vf_byte(cs.b0); vf_byte(cs.b1); vf_byte(cs.b2); vf_byte(cs.b3); + + vf_read(4,k); + fs = sqxfw(k, atsize); + lua_pushstring(L,"size"); + lua_pushnumber(L,fs); + lua_rawset(L,-3); + + vf_read(4,k); + ds = k / 16; /* dsize, not used */ + + vf_byte(tmp_b0); + vf_byte(tmp_b1); + while (tmp_b0 > 0) { tmp_b0--; vf_byte(k); } /* skip the font path */ + + s = xmalloc(tmp_b1+1); k = 0; + while (tmp_b1-- > 0) + vf_byte(s[k++]); + s[k]=0; + lua_pushstring(L,"name"); + lua_pushstring(L,xstrdup(s)); + free(s); + lua_rawset(L,-3); + + lua_rawseti(L,-2,vf_nf); + i++; + vf_byte(cmd); + } + + if (i>1) { + lua_setfield(L,-2,"fonts"); + } else { + lua_pop(L,1); + } + + lua_newtable(L); /* 'characters' */ + while (cmd <= long_char) { + /* @;@/ */ + if (cmd == long_char) { + vf_read_u(4,packet_length); + vf_read_u(4,cc); + vf_read(4,tfm_width); + } else { + packet_length = cmd; + vf_byte(cc); + vf_read(3,tfm_width); + } + if (packet_length < 0) + lua_bad_vf("negative packet length"); + + lua_newtable(L); /* for this character */ + + lua_pushnumber(L,tfm_width); + lua_setfield(L,-2,"width"); + + lua_newtable(L); /* for 'commands' */ + + k = 1; vf_nf = 0; + w = 0; x = 0; y = 0; z = 0; + while (packet_length > 0) { + vf_byte(cmd); + decr(packet_length); + + if ((cmd >= set_char_0) && (cmd < set1)) { + if (vf_nf == 0) { + vf_nf = 1; + make_command1("font",vf_nf,k); + } + make_command1("char",cmd,k); + + } else if (((fnt_num_0 <= cmd) && (cmd <= fnt_num_0 + 63)) || + ((fnt1 <= cmd) && (cmd <= fnt1 + 3))) { + if (cmd >= fnt1) { + vf_read_u((cmd - fnt1 + 1),vf_nf); vf_nf++; + packet_length -= (cmd - fnt1 + 1); + } else { + vf_nf = cmd - fnt_num_0 + 1; + } + make_command1("font",vf_nf,k); + } else { + switch (cmd) { + case set_rule: + vf_read(4,h); vf_read(4,v); + make_command2("rule",sqxfw(h,atsize),sqxfw(v,atsize),k); + packet_length -= 8; + break; + case put_rule: + vf_read(4,h); vf_read(4,v); + make_command0("push",k); + make_command2("rule",sqxfw(h,atsize),sqxfw(v,atsize),k); + make_command0("pop",k); + packet_length -= 8; + break; + case set1: + case set2: + case set3: + case set4: + if (vf_nf == 0) { + vf_nf = 1; + make_command1("font",vf_nf,k); + } + vf_read_u((cmd - set1 + 1),i); + make_command1("char",i,k); + packet_length -= (cmd - set1 + 1); + break; + case put1: + case put2: + case put3: + case put4: + if (vf_nf == 0) { + vf_nf = 1; + make_command1("font",vf_nf,k); + } + vf_read_u((cmd - put1 + 1),i); + make_command0("push",k); + make_command1("char",i,k); + make_command0("pop",k); + packet_length -= (cmd - put1 + 1); + break; + case right1: + case right2: + case right3: + case right4: + vf_read((cmd - right1 + 1),i); + make_command1("right",sqxfw(i,atsize),k); + packet_length -= (cmd - right1 + 1); + break; + case w1: + case w2: + case w3: + case w4: + vf_read((cmd - w1 + 1),w); + make_command1("right",sqxfw(w,atsize),k); + packet_length -= (cmd - w1 + 1); + break; + case x1: + case x2: + case x3: + case x4: + vf_read((cmd - x1 + 1),x); + make_command1("right",sqxfw(x,atsize),k); + packet_length -= (cmd - x1 + 1); + break; + case down1: + case down2: + case down3: + case down4: + vf_read((cmd - down1 + 1),i); + make_command1("down",sqxfw(i,atsize),k); + packet_length -= (cmd - down1 + 1); + break; + case y1: + case y2: + case y3: + case y4: + vf_read((cmd - y1 + 1),y); + make_command1("down",sqxfw(y,atsize),k); + packet_length -= (cmd - y1 + 1); + break; + case z1: + case z2: + case z3: + case z4: + vf_read((cmd - z1 + 1),z); + make_command1("down",sqxfw(z,atsize),k); + packet_length -= (cmd - z1 + 1); + break; + case xxx1: + case xxx2: + case xxx3: + case xxx4: + vf_read_u((cmd - xxx1 + 1),cmd_length); + packet_length -= (cmd - xxx1 + 1); + if (cmd_length <= 0) + lua_bad_vf("special of negative length"); + packet_length -= cmd_length; + + s = xmalloc(cmd_length+1); i = 0; + while (cmd_length > 0) { + cmd_length--; + vf_byte(s[i]); + i++; + } + s[i]=0; + make_commands("special",strdup(s),i,k); + free(s); + break; + case w0: + make_command1("right",sqxfw(w,atsize),k); + break; + case x0: + make_command1("right",sqxfw(x,atsize),k); + break; + case y0: + make_command1("down",sqxfw(y,atsize),k); + break; + case z0: + make_command1("down",sqxfw(z,atsize),k); + break; + case nop: + break; + case push: + if (stack_level == vf_stack_size) { + overflow_string("virtual font stack size", vf_stack_size); + } else { + vf_stack[stack_level].stack_w = w; + vf_stack[stack_level].stack_x = x; + vf_stack[stack_level].stack_y = y; + vf_stack[stack_level].stack_z = z; + incr(stack_level); + make_command0("push",k); + } + break; + case pop: + if (stack_level == 0) { + lua_bad_vf("more POPs than PUSHs in character"); + } else { + decr(stack_level); + w = vf_stack[stack_level].stack_w; + x = vf_stack[stack_level].stack_x; + y = vf_stack[stack_level].stack_y; + z = vf_stack[stack_level].stack_z; + make_command0("pop",k); + } + break; + default: + lua_bad_vf("improver DVI command"); + } + } + } + /* signal end of packet */ + lua_setfield(L,-2,"commands"); + + if (stack_level != 0) + lua_bad_vf("more PUSHs than POPs in character packet"); + if (packet_length != 0) + lua_bad_vf("invalid packet length or DVI command in packet"); + + lua_rawseti(L,-2,cc); + + vf_byte(cmd); + } + lua_setfield(L,-2,"characters"); + + if (cmd != post) + lua_bad_vf("POST command expected"); + xfree(vf_buffer); + return 1; +} + + +extern void replace_packet_fonts(internal_font_number f, integer *old_fontid, integer *new_fontid, int count) ; +extern integer *packet_local_fonts(internal_font_number f, integer *num); +extern internal_font_number auto_expand_font (internal_font_number f, integer e) ; + + +/* This function is called from |do_vf|, and fixes up the virtual data + inside an auto-expanded virtual font */ + +boolean +auto_expand_vf(internal_font_number f) { + + internal_font_number bf; + integer e, k; + integer *vf_old_fonts, *vf_new_fonts; + integer num = 0; + + if ((! pdf_font_auto_expand(f)) || (pdf_font_blink(f) == null_font)) + return false ; /* not an auto-expanded font */ + bf = pdf_font_blink(f); + + if (font_type(bf) != virtual_font_type) + return false; /* not a virtual font */ + + e = pdf_font_expand_ratio(f); + + vf_old_fonts = packet_local_fonts(bf,&num); + if (num>0) { + vf_new_fonts = xmalloc(num*sizeof(integer)); + for (k=0;k 0) { + print_char('+'); + } + print_int(e); + selector=old_setting; + return make_string(); +} + + +internal_font_number +auto_expand_font (internal_font_number f, integer e) { + internal_font_number k; + kerninfo *krn; + charinfo *co, *ci; + char *fn; + integer i; + scaled w; + k = copy_font(f); + i = strlen(font_name(f))+12; + fn = xmalloc(i); + snprintf(fn,i,"%s%s%d",font_name(f),(e>0 ? "+" : ""), (int)e); + set_font_name(k,fn); + for (i = font_bc(k);i<=font_ec(k);i++) { + if (char_exists(k,i)) { + co = get_charinfo(k,i); + w = round_xn_over_d(char_width(f,i), 1000 + e, 1000); + set_charinfo_width (co, w); + w = round_xn_over_d(char_italic(f,i), 1000 + e, 1000); + set_charinfo_italic(co, w); + krn = get_charinfo_kerns(co); + if (krn != NULL) { + while (!kern_end((*krn))) { + kern_kern(*krn) = round_xn_over_d(kern_kern(*krn), 1000 + e, 1000); + krn++; + } + } + } + } + return k; +} + +void +vf_expand_local_fonts(internal_font_number f) { + internal_font_number lf; + integer k, num; + integer *vf_old_fonts; + pdfassert(font_type(f) == virtual_font_type); + num = 0; + vf_old_fonts = packet_local_fonts(f,&num); + if (num>0) { + for (k = 0;k 0) { + sprintf(new_font_name,"%s+%ils",font_name(k),(int)e); + } else { + /* minus from %i */ + sprintf(new_font_name,"%s%ils",font_name(k),(int)e); + } + set_font_name(k, new_font_name); + + /* create the corresponding virtual font */ + set_font_type(k,virtual_font_type); + + vf_z = font_size(f); + vf_replace_z(); + w = round_xn_over_d(quad(f), e, 2000); + if (w > 0) { + tmp_b0 = 0; + } else { + tmp_b0 = 255; + w = vf_alpha + w; + } + r = w*vf_beta; + tmp_b1 = r / vf_z; + r = r % vf_z; + if (r == 0) { + tmp_b2 = 0; + } else { + r = r * 256; + tmp_b2 = r / vf_z; + r = r % vf_z; + } + if (r == 0) { + tmp_b3 = 0; + } else { + r = r * 256; + tmp_b3 = r / vf_z; + } + /* + vf_packet_base[k] = new_vf_packet(k); + + for (c=font_bc(k);c<=font_ec(k);c++) { + string_room(17); + append_fnt_set(f); + append_packet(right1 + 3); + append_packet(tmp_b0); + append_packet(tmp_b1); + append_packet(tmp_b2); + append_packet(tmp_b3); + + append_packet(set1); + append_packet(c); + + append_packet(right1 + 3); + append_packet(tmp_b0); + append_packet(tmp_b1); + append_packet(tmp_b2); + append_packet(tmp_b3); + s = make_string(); + store_packet(k, c, s); + flush_str(s); + } +*/ + return k; +} + + diff --git a/Build/source/texk/web2c/luatexdir/font/vfpacket.c b/Build/source/texk/web2c/luatexdir/font/vfpacket.c new file mode 100644 index 00000000000..4d8445f2227 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/font/vfpacket.c @@ -0,0 +1,377 @@ +/* +Copyright (c) 1996-2002 Han The Thanh, + +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: vfpacket.c 1013 2008-02-14 00:09:02Z oneiros $ +*/ + +#include "ptexlib.h" + +/* + 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 |packet_cur_s| and should + not exceed |packet_max_recursion|. +*/ + +#define packet_max_recursion 100 + +typedef unsigned char packet_stack_index ; /* an index into the stack */ + +typedef struct packet_stack_record { + scaled stack_h; + scaled stack_v; +} packet_stack_record; + + +static packet_stack_index packet_cur_s = 0; /* current recursion level */ +static packet_stack_record packet_stack [packet_max_recursion]; +static packet_stack_index packet_stack_ptr = 0; /* pointer into |packet_stack| */ + + +/* Some macros for processing character packets. */ + +#define do_packet_byte() vf_packets[cur_packet_byte++] + +#define packet_number(fw) { \ + fw = do_packet_byte(); \ + fw = fw*256 + do_packet_byte(); \ + fw = fw*256 + do_packet_byte(); \ + fw = fw*256 + do_packet_byte(); } + +#define packet_scaled(a,fs) { integer fw; \ + fw = do_packet_byte(); \ + if (fw>127) fw = fw - 256; \ + fw = fw*256 + do_packet_byte(); \ + fw = fw*256 + do_packet_byte(); \ + fw = fw*256 + do_packet_byte(); \ + a = sqxfw(fw, fs); } + + +/* count the number of bytes in a command packet */ +int +vf_packet_bytes (charinfo *co) { + real_eight_bits *vf_packets; + integer cur_packet_byte; + unsigned k; + int cmd; + + vf_packets = get_charinfo_packets(co); + if (vf_packets == NULL) { + return 0; + } + cur_packet_byte = 0; + while ((cmd = vf_packets[cur_packet_byte]) != packet_end_code) { + cur_packet_byte++; + switch (cmd) { + case packet_char_code: + case packet_font_code: + case packet_right_code: + case packet_down_code: + case packet_node_code: + cur_packet_byte += 4; + break; + case packet_push_code: + case packet_pop_code: + break; + case packet_rule_code: + cur_packet_byte += 8; + break; + case packet_special_code: + packet_number(k); /* +4 */ + cur_packet_byte += k; + break; + case packet_nop_code: + break; + default: + pdf_error("vf", "invalid DVI command"); + } + }; + return (cur_packet_byte +1); +} + + +/* typeset the \.{DVI} commands in the + character packet for character |c| in current font |f| */ + +char *packet_command_names[] = { + "char", "font","pop", "push", "special", + "right","down","rule","node", "nop","end", NULL}; + + +void +do_vf_packet (internal_font_number vf_f, integer c) { + internal_font_number lf; + charinfo *co; + scaled save_cur_h, save_cur_v; + real_eight_bits *vf_packets; + integer cur_packet_byte; + integer cmd, fs_f; + scaled i; + unsigned k; + str_number s; + + packet_cur_s++; + if (packet_cur_s >= packet_max_recursion) + overflow_string("max level recursion of virtual fonts", packet_max_recursion); + save_cur_v = cur_v; + save_cur_h = cur_h; + + lf = 0; /* for -Wall */ + co = get_charinfo(vf_f,c); + vf_packets = get_charinfo_packets(co); + if (vf_packets == NULL) { + packet_cur_s--; + return ; + } + cur_packet_byte = 0; + fs_f = font_size(vf_f); + while ((cmd = vf_packets[cur_packet_byte]) != packet_end_code) { + cur_packet_byte++; + /* + if (cmd>packet_end_code) { + fprintf(stdout, "do_vf_packet(%i,%i) command code = illegal \n", vf_f,c); + } else { + fprintf(stdout, "do_vf_packet(%i,%i) command code = %s\n",vf_f, c, packet_command_names[cmd]); + } + */ + switch (cmd) { + case packet_font_code: + packet_number(lf); + break; + case packet_push_code: + packet_stack[packet_stack_ptr].stack_h = cur_h; + packet_stack[packet_stack_ptr].stack_v = cur_v; + packet_stack_ptr++; + break; + case packet_pop_code: + packet_stack_ptr--; + cur_h = packet_stack[packet_stack_ptr].stack_h; + cur_v = packet_stack[packet_stack_ptr].stack_v; + break; + case packet_char_code: + packet_number(k); + if (!char_exists(lf,k)) { + char_warning(lf, k); + } else { + output_one_char(lf, k); + } + cur_h = cur_h + char_width(lf,k); + break; + case packet_rule_code: + packet_scaled(rule_ht,fs_f); + packet_scaled(rule_wd,fs_f); + if ((rule_wd > 0) && (rule_ht > 0)) { + pdf_set_rule(cur_h, cur_v, rule_wd, rule_ht); + cur_h = cur_h + rule_wd; + } + break; + case packet_right_code: + packet_scaled(i,fs_f); + cur_h = cur_h + i; + break; + case packet_down_code: + packet_scaled(i,fs_f); + cur_v = cur_v + i; + break; + case packet_special_code: + packet_number(k); + string_room(k); + while (k > 0) { + k--; + append_pool_char(do_packet_byte()); + } + s = make_string(); + literal(s, scan_special, false); + flush_str(s); + break; + case packet_node_code: + packet_number(k); + temp_ptr = k; + pdf_hlist_out(); + break; + case packet_nop_code: + break; + default: + pdf_error("vf", "invalid DVI command"); + } + }; + cur_h = save_cur_h; + cur_v = save_cur_v; + packet_cur_s--; +} + + +integer *packet_local_fonts(internal_font_number f, integer *num) { + int c, cmd, cur_packet_byte, lf, k,l, i; + integer localfonts[256] = {0}; + integer *lfs; + charinfo *co; + + real_eight_bits *vf_packets; + k = 0; + for (c = font_bc(f);c <= font_ec(f);c++) { + if (char_exists(f,c)) { + co = get_charinfo(f,c); + vf_packets = get_charinfo_packets(co); + if (vf_packets == NULL) + continue; + cur_packet_byte = 0; + while ((cmd = vf_packets[cur_packet_byte]) != packet_end_code) { + cur_packet_byte++; + switch (cmd) { + case packet_font_code: + packet_number(lf); + for (l=0;l 0) + (void)do_packet_byte(); + break; + default: + pdf_error("vf", "invalid DVI command"); + } + } + } + } + *num = k; + if (k>0) { + lfs = xmalloc (k*sizeof(integer)); + memcpy(lfs,localfonts,k*sizeof(integer)); + return lfs; + } + return NULL; +} + + +void +replace_packet_fonts(internal_font_number f, integer *old_fontid, integer *new_fontid, int count) { + int c, cmd, cur_packet_byte, lf, k,l; + charinfo *co; + real_eight_bits *vf_packets; + + k = 0; + for (c = font_bc(f);c <= font_ec(f);c++) { + if (char_exists(f,c)) { + co = get_charinfo(f,c); + vf_packets = get_charinfo_packets(co); + if (vf_packets == NULL) + continue; + cur_packet_byte = 0; + while ((cmd = vf_packets[cur_packet_byte]) != packet_end_code) { + cur_packet_byte++; + switch (cmd) { + case packet_font_code: + packet_number(lf); + for (l=0;l>24; + vf_packets[(cur_packet_byte-3)] = (k&0x00FF0000)>>16; + vf_packets[(cur_packet_byte-2)] = (k&0x0000FF00)>>8; + vf_packets[(cur_packet_byte-1)] = (k&0x000000FF); + } + break; + case packet_push_code: + case packet_pop_code: + case packet_nop_code: + break; + case packet_char_code: + case packet_right_code: + case packet_down_code: + case packet_node_code: + cur_packet_byte+=4; + break; + case packet_rule_code: + cur_packet_byte+=8; + break; + case packet_special_code: + packet_number(k); + while (k-- > 0) + (void)do_packet_byte(); + break; + default: + pdf_error("vf", "invalid DVI command"); + } + } + } + } +} + +/* this function was copied/borrowed/stolen from dvipdfm code */ + +scaled sqxfw (scaled sq, integer fw) +{ + int sign = 1; + unsigned long a, b, c, d, ad, bd, bc, ac; + unsigned long e, f, g, h, i, j, k; + unsigned long result; + /* Make positive. */ + if (sq < 0) { + sign = -sign; + sq = -sq; + } + if (fw < 0) { + sign = -sign; + fw = -fw; + } + a = ((unsigned long) sq) >> 16u; + b = ((unsigned long) sq) & 0xffffu; + c = ((unsigned long) fw) >> 16u; + d = ((unsigned long) fw) & 0xffffu; + ad = a*d; bd = b*d; bc = b*c; ac = a*c; + e = bd >> 16u; + f = ad >> 16u; + g = ad & 0xffffu; + h = bc >> 16u; + i = bc & 0xffffu; + j = ac >> 16u; + k = ac & 0xffffu; + result = (e+g+i + (1<<3)) >> 4u; /* 1<<3 is for rounding */ + result += (f+h+k) << 12u; + result += j << 28u; + return (sign>0)?result:-result; +} diff --git a/Build/source/texk/web2c/luatexdir/font/writecff.c b/Build/source/texk/web2c/luatexdir/font/writecff.c new file mode 100644 index 00000000000..69c35c6950e --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/font/writecff.c @@ -0,0 +1,3381 @@ +/* +Copyright (c) 2007 Taco Hoekwater, taco@luatex.org + +This file is part of luaTeX. + +luaTeX 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. + +luaTeX 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 luaTeX; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +$Id: writecff.c 1021 2008-02-14 10:24:34Z taco $ +*/ + +#include "ptexlib.h" + +#include "writecff.h" + +#define get_offset(s,n) get_unsigned(s, (n)) +#define get_card8(a) a->stream[a->offset++] +#define get_card16(a) get_unsigned(a,2) + +#undef b0 +#undef b1 +#undef b2 +#undef b3 + +#define WORK_BUFFER_SIZE 1024 + +static char work_buffer[WORK_BUFFER_SIZE]; + +static unsigned long get_unsigned (cff_font *cff, int n) +{ + unsigned long v = 0; + while (n-- > 0) + v = v*256 + get_card8(cff); + return v; +} + +#define CFF_ERROR pdftex_fail +#define WARN pdftex_warn + + +const char *const cff_stdstr[CFF_STDSTR_MAX] = { + ".notdef", "space", "exclam", "quotedbl", "numbersign", + "dollar", "percent", "ampersand", "quoteright", "parenleft", + "parenright", "asterisk", "plus", "comma", "hyphen", + "period", "slash", "zero", "one", "two", + "three", "four", "five", "six", "seven", + "eight", "nine", "colon", "semicolon", "less", + "equal", "greater", "question", "at", "A", + "B", "C", "D", "E", "F", + "G", "H", "I", "J", "K", + "L", "M", "N", "O", "P", + "Q", "R", "S", "T", "U", + "V", "W", "X", "Y", "Z", + "bracketleft", "backslash", "bracketright", "asciicircum", "underscore", + "quoteleft", "a", "b", "c", "d", + "e", "f", "g", "h", "i", + "j", "k", "l", "m", "n", + "o", "p", "q", "r", "s", + "t", "u", "v", "w", "x", + "y", "z", "braceleft", "bar", "braceright", + "asciitilde", "exclamdown", "cent", "sterling", "fraction", + "yen", "florin", "section", "currency", "quotesingle", + "quotedblleft", "guillemotleft", "guilsinglleft", "guilsinglright", "fi", + "fl", "endash", "dagger", "daggerdbl", "periodcentered", + "paragraph", "bullet", "quotesinglbase", "quotedblbase", "quotedblright", + "guillemotright", "ellipsis", "perthousand", "questiondown", "grave", + "acute", "circumflex", "tilde", "macron", "breve", + "dotaccent", "dieresis", "ring", "cedilla", "hungarumlaut", + "ogonek", "caron", "emdash", "AE", "ordfeminine", + "Lslash", "Oslash", "OE", "ordmasculine", "ae", + "dotlessi", "lslash", "oslash", "oe", "germandbls", + "onesuperior", "logicalnot", "mu", "trademark", "Eth", + "onehalf", "plusminus", "Thorn", "onequarter", "divide", + "brokenbar", "degree", "thorn", "threequarters", "twosuperior", + "registered", "minus", "eth", "multiply", "threesuperior", + "copyright", "Aacute", "Acircumflex", "Adieresis", "Agrave", + "Aring", "Atilde", "Ccedilla", "Eacute", "Ecircumflex", + "Edieresis", "Egrave", "Iacute", "Icircumflex", "Idieresis", + "Igrave", "Ntilde", "Oacute", "Ocircumflex", "Odieresis", + "Ograve", "Otilde", "Scaron", "Uacute", "Ucircumflex", + "Udieresis", "Ugrave", "Yacute", "Ydieresis", "Zcaron", + "aacute", "acircumflex", "adieresis", "agrave", "aring", + "atilde", "ccedilla", "eacute", "ecircumflex", "edieresis", + "egrave", "iacute", "icircumflex", "idieresis", "igrave", + "ntilde", "oacute", "ocircumflex", "odieresis", "ograve", + "otilde", "scaron", "uacute", "ucircumflex", "udieresis", + "ugrave", "yacute", "ydieresis", "zcaron", "exclamsmall", + "Hungarumlautsmall", "dollaroldstyle", "dollarsuperior", "ampersandsmall", "Acutesmall", + "parenleftsuperior", "parenrightsuperior", "twodotenleader", "onedotenleader", "zerooldstyle", + "oneoldstyle", "twooldstyle", "threeoldstyle", "fouroldstyle", "fiveoldstyle", + "sixoldstyle", "sevenoldstyle", "eightoldstyle", "nineoldstyle", "commasuperior", + "threequartersemdash", "periodsuperior", "questionsmall", "asuperior", "bsuperior", + "centsuperior", "dsuperior", "esuperior", "isuperior", "lsuperior", + "msuperior", "nsuperior", "osuperior", "rsuperior", "ssuperior", + "tsuperior", "ff", "ffi", "ffl", "parenleftinferior", + "parenrightinferior", "Circumflexsmall", "hyphensuperior", "Gravesmall", "Asmall", + "Bsmall", "Csmall", "Dsmall", "Esmall", "Fsmall", + "Gsmall", "Hsmall", "Ismall", "Jsmall", "Ksmall", + "Lsmall", "Msmall", "Nsmall", "Osmall", "Psmall", + "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall", + "Vsmall", "Wsmall", "Xsmall", "Ysmall", "Zsmall", + "colonmonetary", "onefitted", "rupiah", "Tildesmall", "exclamdownsmall", + "centoldstyle", "Lslashsmall", "Scaronsmall", "Zcaronsmall", "Dieresissmall", + "Brevesmall", "Caronsmall", "Dotaccentsmall", "Macronsmall", "figuredash", + "hypheninferior", "Ogoneksmall", "Ringsmall", "Cedillasmall", "questiondownsmall", + "oneeighth", "threeeighths", "fiveeighths", "seveneighths", "onethird", + "twothirds", "zerosuperior", "foursuperior", "fivesuperior", "sixsuperior", + "sevensuperior", "eightsuperior", "ninesuperior", "zeroinferior", "oneinferior", + "twoinferior", "threeinferior", "fourinferior", "fiveinferior", "sixinferior", + "seveninferior", "eightinferior", "nineinferior", "centinferior", "dollarinferior", + "periodinferior", "commainferior", "Agravesmall", "Aacutesmall", "Acircumflexsmall", + "Atildesmall", "Adieresissmall", "Aringsmall", "AEsmall", "Ccedillasmall", + "Egravesmall", "Eacutesmall", "Ecircumflexsmall", "Edieresissmall", "Igravesmall", + "Iacutesmall", "Icircumflexsmall", "Idieresissmall", "Ethsmall", "Ntildesmall", + "Ogravesmall", "Oacutesmall", "Ocircumflexsmall", "Otildesmall", "Odieresissmall", + "OEsmall", "Oslashsmall", "Ugravesmall", "Uacutesmall", "Ucircumflexsmall", + "Udieresissmall", "Yacutesmall", "Thornsmall", "Ydieresissmall", + "001.000", "001.001", "001.002", "001.003", + "Black", "Bold", "Book", "Light", "Medium", "Regular", "Roman", "Semibold" +}; + + +/* Only read header part but not body */ +cff_index * +cff_get_index_header (cff_font *cff) +{ + cff_index *idx; + card16 i, count; + + idx = xcalloc(1, sizeof(cff_index)); + + idx->count = count = get_card16(cff); + if (count > 0) { + idx->offsize = get_card8(cff); + if (idx->offsize < 1 || idx->offsize > 4) + CFF_ERROR("invalid offsize data"); + + idx->offset = xcalloc(count+1, sizeof(l_offset)); + for (i=0;ioffset)[i] = get_offset(cff, idx->offsize); + } + + if (idx->offset[0] != 1) + CFF_ERROR("cff_get_index(): invalid index data"); + + idx->data = NULL; + } else { + idx->offsize = 0; + idx->offset = NULL; + idx->data = NULL; + } + + return idx; +} + + + +cff_index * +cff_get_index (cff_font *cff) +{ + cff_index *idx; + card16 i, count; + long length; + + idx = xcalloc(1,sizeof(cff_index)); + + idx->count = count = get_card16(cff); + if (count > 0) { + idx->offsize = get_card8(cff); + if (idx->offsize < 1 || idx->offsize > 4) + CFF_ERROR("invalid offsize data"); + + idx->offset = xcalloc((count + 1),sizeof(l_offset)); + for (i = 0 ; i < count + 1; i++) { + idx->offset[i] = get_offset(cff, idx->offsize); + } + + if (idx->offset[0] != 1) + CFF_ERROR("Invalid CFF Index offset data"); + + length = idx->offset[count] - idx->offset[0]; + + idx->data = xcalloc(length,sizeof(card8)); + memcpy(idx->data,&cff->stream[cff->offset],length); + cff->offset += length; + + } else { + idx->offsize = 0; + idx->offset = NULL; + idx->data = NULL; + } + return idx; +} + + +long +cff_pack_index (cff_index *idx, card8 *dest, long destlen) +{ + long len = 0; + unsigned long datalen; + card16 i; + + if (idx->count < 1) { + if (destlen < 2) + CFF_ERROR("Not enough space available..."); + memset(dest, 0, 2); + return 2; + } + + len = cff_index_size(idx); + datalen = idx->offset[idx->count] - 1; + + if (destlen < len) + CFF_ERROR("Not enough space available..."); + + *(dest++) = (idx->count >> 8) & 0xff; + *(dest++) = idx->count & 0xff; + + if (datalen < 0xffUL) { + idx->offsize = 1; + *(dest++) = 1; + for (i = 0; i <= idx->count; i++) { + *(dest++) = (card8) (idx->offset[i] & 0xff); + } + } else if (datalen < 0xffffUL) { + idx->offsize = 2; + *(dest++) = 2; + for (i = 0; i <= idx->count; i++) { + *(dest++) = (card8) ((idx->offset[i] >> 8) & 0xff); + *(dest++) = (card8) ( idx->offset[i] & 0xff); + } + } else if (datalen < 0xffffffUL) { + idx->offsize = 3; + *(dest++) = 3; + for (i = 0; i <= idx->count; i++) { + *(dest++) = (card8)((idx->offset[i] >> 16) & 0xff); + *(dest++) = (card8)((idx->offset[i] >> 8) & 0xff); + *(dest++) = (card8)(idx->offset[i] & 0xff); + } + } else { + idx->offsize = 4; + *(dest++) = 4; + for (i = 0; i <= idx->count; i++) { + *(dest++) = (card8)((idx->offset[i] >> 24) & 0xff); + *(dest++) = (card8)((idx->offset[i] >> 16) & 0xff); + *(dest++) = (card8)((idx->offset[i] >> 8) & 0xff); + *(dest++) = (card8)(idx->offset[i] & 0xff); + } + } + + memmove(dest, idx->data, idx->offset[idx->count] - 1); + + return len; +} + +long +cff_index_size (cff_index *idx) +{ + if (idx->count > 0) { + l_offset datalen; + + datalen = idx->offset[idx->count] - 1; + if (datalen < 0xffUL) { + idx->offsize = 1; + } else if (datalen < 0xffffUL) { + idx->offsize = 2; + } else if (datalen < 0xffffffUL) { + idx->offsize = 3; + } else { + idx->offsize = 4; + } + return (3 + (idx->offsize)*(idx->count + 1) + datalen); + } else { + return 2; + } +} + +cff_index *cff_new_index (card16 count) +{ + cff_index *idx; + + idx = xcalloc(1, sizeof(cff_index)); + idx->count = count; + idx->offsize = 0; + + if (count > 0) { + idx->offset = xcalloc(count + 1, sizeof(l_offset)); + (idx->offset)[0] = 1; + } else { + idx->offset = NULL; + } + idx->data = NULL; + + return idx; +} + + +void cff_release_index (cff_index *idx) +{ + if (idx) { + xfree(idx->data); + xfree(idx->offset); + xfree(idx); + } +} + +void cff_release_dict (cff_dict *dict) +{ + if (dict) { + if (dict->entries) { + int i; + for (i=0;icount;i++) { + xfree((dict->entries)[i].values); + } + xfree(dict->entries); + } + xfree(dict); + } +} + + +void cff_release_encoding (cff_encoding *encoding) +{ + if (encoding) { + switch (encoding->format & (~0x80)) { + case 0: xfree(encoding->data.codes); break; + case 1: xfree(encoding->data.range1); break; + default: CFF_ERROR("Unknown Encoding format."); + } + if (encoding->format & 0x80) + xfree(encoding->supp); + xfree(encoding); + } +} + +void +cff_release_charsets (cff_charsets *charset) +{ + if (charset) { + switch (charset->format) { + case 0: xfree(charset->data.glyphs); break; + case 1: xfree(charset->data.range1); break; + case 2: xfree(charset->data.range2); break; + default: break; + } + xfree(charset); + } +} + +void cff_release_fdselect (cff_fdselect *fdselect) +{ + if (fdselect) { + if (fdselect->format == 0) { xfree(fdselect->data.fds); } + else if (fdselect->format == 3) { xfree(fdselect->data.ranges); } + xfree(fdselect); + } +} + + +void +cff_close (cff_font *cff) +{ + card16 i; + + if (cff) { + if (cff->fontname) xfree(cff->fontname); + if (cff->name) cff_release_index(cff->name); + if (cff->topdict) cff_release_dict(cff->topdict); + if (cff->string) cff_release_index(cff->string); + if (cff->gsubr) cff_release_index(cff->gsubr); + if (cff->encoding) cff_release_encoding(cff->encoding); + if (cff->charsets) cff_release_charsets(cff->charsets); + if (cff->fdselect) cff_release_fdselect(cff->fdselect); + if (cff->cstrings) cff_release_index(cff->cstrings); + if (cff->fdarray) { + for (i=0;inum_fds;i++) { + if (cff->fdarray[i]) cff_release_dict(cff->fdarray[i]); + } + xfree(cff->fdarray); + } + if (cff->private) { + for (i=0;inum_fds;i++) { + if (cff->private[i]) cff_release_dict(cff->private[i]); + } + xfree(cff->private); + } + if (cff->subrs) { + for (i=0;inum_fds;i++) { + if (cff->subrs[i]) cff_release_index(cff->subrs[i]); + } + xfree(cff->subrs); + } + if (cff->_string) + cff_release_index(cff->_string); + xfree(cff); + } + + return; +} + +char * +cff_get_name (cff_font *cff) +{ + char *fontname; + l_offset len; + cff_index *idx; + + idx = cff->name; + len = idx->offset[cff->index + 1] - idx->offset[cff->index]; + fontname = xmalloc((len + 1)*sizeof(char)); + memcpy(fontname, idx->data + idx->offset[cff->index] - 1, len); + fontname[len] = '\0'; + + return fontname; +} + + +long +cff_set_name (cff_font *cff, char *name) +{ + cff_index *idx; + + if (strlen(name) > 127) + CFF_ERROR("FontName string length too large..."); + + if (cff->name) + cff_release_index(cff->name); + + cff->name = idx = xcalloc(1, sizeof(cff_index)); + idx->count = 1; + idx->offsize = 1; + idx->offset = xmalloc(2*sizeof(l_offset)); + (idx->offset)[0] = 1; + (idx->offset)[1] = strlen(name) + 1; + idx->data = xcalloc(strlen(name), sizeof(card8)); + memmove(idx->data, name, strlen(name)); /* no trailing '\0' */ + + return 5 + strlen(name); +} + +long +cff_put_header (cff_font *cff, card8 *dest, long destlen) +{ + if (destlen < 4) + CFF_ERROR("Not enough space available..."); + + *(dest++) = cff->header_major; + *(dest++) = cff->header_minor; + *(dest++) = 4; /* Additional data in between header and + * Name INDEX ignored. + */ + /* We will set all offset (0) to four-byte integer. */ + *(dest++) = 4; + cff->header_offsize = 4; + + return 4; +} + +#define CFF_PARSE_OK 0 +#define CFF_CFF_ERROR_PARSE_CFF_ERROR -1 +#define CFF_CFF_ERROR_STACK_OVERFLOW -2 +#define CFF_CFF_ERROR_STACK_UNDERFLOW -3 +#define CFF_CFF_ERROR_STACK_RANGECHECK -4 + +#define DICT_ENTRY_MAX 16 + +cff_dict *cff_new_dict (void) +{ + cff_dict *dict; + + dict = xcalloc(1, sizeof(cff_dict)); + dict->max = DICT_ENTRY_MAX; + dict->count = 0; + dict->entries = xcalloc(dict->max, sizeof(cff_dict_entry)); + return dict; +} + +/* + * Operand stack: + * only numbers are stored (as double) + * + * Operand types: + * + * number : double (integer or real) + * boolean: stored as a number + * SID : stored as a number + * array : array of numbers + * delta : array of numbers + */ + +#define CFF_DICT_STACK_LIMIT 64 +static int stack_top = 0; +static double arg_stack[CFF_DICT_STACK_LIMIT]; + +/* + * CFF DICT encoding: + * TODO: default values + */ + +#define CFF_LAST_DICT_OP1 22 +#define CFF_LAST_DICT_OP2 39 +#define CFF_LAST_DICT_OP (CFF_LAST_DICT_OP1 + CFF_LAST_DICT_OP2) + +static struct { + const char *opname; + int argtype; +} dict_operator[CFF_LAST_DICT_OP] = { + {"version", CFF_TYPE_SID}, + {"Notice", CFF_TYPE_SID}, + {"FullName", CFF_TYPE_SID}, + {"FamilyName", CFF_TYPE_SID}, + {"Weight", CFF_TYPE_SID}, + {"FontBBox", CFF_TYPE_ARRAY}, + {"BlueValues", CFF_TYPE_DELTA}, + {"OtherBlues", CFF_TYPE_DELTA}, + {"FamilyBlues", CFF_TYPE_DELTA}, + {"FamilyOtherBlues", CFF_TYPE_DELTA}, + {"StdHW", CFF_TYPE_NUMBER}, + {"StdVW", CFF_TYPE_NUMBER}, + {NULL, -1}, /* first byte of two-byte operator */ + /* Top */ + {"UniqueID", CFF_TYPE_NUMBER}, + {"XUID", CFF_TYPE_ARRAY}, + {"charset", CFF_TYPE_OFFSET}, + {"Encoding", CFF_TYPE_OFFSET}, + {"CharStrings", CFF_TYPE_OFFSET}, + {"Private", CFF_TYPE_SZOFF}, /* two numbers (size and offset) */ + /* Private */ + {"Subrs", CFF_TYPE_OFFSET}, + {"defaultWidthX", CFF_TYPE_NUMBER}, + {"nominalWidthX", CFF_TYPE_NUMBER}, + /* Operator 2 */ + {"Copyright", CFF_TYPE_SID}, + {"IsFixedPitch", CFF_TYPE_BOOLEAN}, + {"ItalicAngle", CFF_TYPE_NUMBER}, + {"UnderlinePosition", CFF_TYPE_NUMBER}, + {"UnderlineThickness", CFF_TYPE_NUMBER}, + {"PaintType", CFF_TYPE_NUMBER}, + {"CharstringType", CFF_TYPE_NUMBER}, + {"FontMatrix", CFF_TYPE_ARRAY}, + {"StrokeWidth", CFF_TYPE_NUMBER}, + {"BlueScale", CFF_TYPE_NUMBER}, + {"BlueShift", CFF_TYPE_NUMBER}, + {"BlueFuzz", CFF_TYPE_NUMBER}, + {"StemSnapH", CFF_TYPE_DELTA}, + {"StemSnapV", CFF_TYPE_DELTA}, + {"ForceBold", CFF_TYPE_BOOLEAN}, + {NULL, -1}, + {NULL, -1}, + {"LanguageGroup", CFF_TYPE_NUMBER}, + {"ExpansionFactor", CFF_TYPE_NUMBER}, + {"InitialRandomSeed", CFF_TYPE_NUMBER}, + {"SyntheticBase", CFF_TYPE_NUMBER}, + {"PostScript", CFF_TYPE_SID}, + {"BaseFontName", CFF_TYPE_SID}, + {"BaseFontBlend", CFF_TYPE_DELTA}, /* MMaster ? */ + {NULL, -1}, + {NULL, -1}, + {NULL, -1}, + {NULL, -1}, + {NULL, -1}, + {NULL, -1}, + /* CID-Keyed font */ + {"ROS", CFF_TYPE_ROS}, /* SID SID number */ + {"CIDFontVersion", CFF_TYPE_NUMBER}, + {"CIDFontRevision", CFF_TYPE_NUMBER}, + {"CIDFontType", CFF_TYPE_NUMBER}, + {"CIDCount", CFF_TYPE_NUMBER}, + {"UIDBase", CFF_TYPE_NUMBER}, + {"FDArray", CFF_TYPE_OFFSET}, + {"FDSelect", CFF_TYPE_OFFSET}, + {"FontName", CFF_TYPE_SID}, +}; + +/* Parse DICT data */ +static double get_integer (card8 **data, card8 *endptr, int *status) +{ + long result = 0; + card8 b0, b1, b2; + + b0 = *(*data)++; + if (b0 == 28 && *data < endptr - 2) { /* shortint */ + b1 = *(*data)++; + b2 = *(*data)++; + result = b1*256+b2; + if (result > 0x7fffL) + result -= 0x10000L; + } else if (b0 == 29 && *data < endptr - 4) { /* longint */ + int i; + result = *(*data)++; + if (result > 0x7f) + result -= 0x100; + for (i=0;i<3;i++) { + result = result*256+(**data); + *data += 1; + } + } else if (b0 >= 32 && b0 <= 246) { /* int (1) */ + result = b0 - 139; + } else if (b0 >= 247 && b0 <= 250) { /* int (2) */ + b1 = *(*data)++; + result = (b0-247)*256+b1+108; + } else if (b0 >= 251 && b0 <= 254) { + b1 = *(*data)++; + result = -(b0-251)*256-b1-108; + } else { + *status = CFF_CFF_ERROR_PARSE_CFF_ERROR; + } + + return (double) result; +} + +/* Simply uses strtod */ +static double get_real(card8 **data, card8 *endptr, int *status) +{ + double result = 0.0; + int nibble = 0, pos = 0; + int len = 0, fail = 0; + + if (**data != 30 || *data >= endptr -1) { + *status = CFF_CFF_ERROR_PARSE_CFF_ERROR; + return 0.0; + } + + *data += 1; /* skip first byte (30) */ + + pos = 0; + while ((! fail) && len < WORK_BUFFER_SIZE - 2 && *data < endptr) { + /* get nibble */ + if (pos % 2) { + nibble = **data & 0x0f; + *data += 1; + } else { + nibble = (**data >> 4) & 0x0f; + } + if (nibble >= 0x00 && nibble <= 0x09) { + work_buffer[len++] = nibble + '0'; + } else if (nibble == 0x0a) { /* . */ + work_buffer[len++] = '.'; + } else if (nibble == 0x0b || nibble == 0x0c) { /* E, E- */ + work_buffer[len++] = 'e'; + if (nibble == 0x0c) + work_buffer[len++] = '-'; + } else if (nibble == 0x0e) { /* `-' */ + work_buffer[len++] = '-'; + } else if (nibble == 0x0d) { /* skip */ + /* do nothing */ + } else if (nibble == 0x0f) { /* end */ + work_buffer[len++] = '\0'; + if (((pos % 2) == 0) && (**data != 0xff)) { + fail = 1; + } + break; + } else { /* invalid */ + fail = 1; + } + pos++; + } + + /* returned values */ + if (fail || nibble != 0x0f) { + *status = CFF_CFF_ERROR_PARSE_CFF_ERROR; + } else { + char *s; + result = strtod(work_buffer, &s); + if (*s != 0 || errno == ERANGE) { + *status = CFF_CFF_ERROR_PARSE_CFF_ERROR; + } + } + + return result; +} + +/* operators */ +static void add_dict (cff_dict *dict, + card8 **data, card8 *endptr, int *status) +{ + int id, argtype; + + id = **data; + if (id == 0x0c) { + *data += 1; + if (*data >= endptr || + (id = **data + CFF_LAST_DICT_OP1) >= CFF_LAST_DICT_OP) { + *status = CFF_CFF_ERROR_PARSE_CFF_ERROR; + return; + } + } else if (id >= CFF_LAST_DICT_OP1) { + *status = CFF_CFF_ERROR_PARSE_CFF_ERROR; + return; + } + + argtype = dict_operator[id].argtype; + if (dict_operator[id].opname == NULL || argtype < 0) { + *status = CFF_CFF_ERROR_PARSE_CFF_ERROR; + return; + } else if (stack_top < 1) { + *status = CFF_CFF_ERROR_STACK_UNDERFLOW; + return; + } + + if (dict->count >= dict->max) { + dict->max += DICT_ENTRY_MAX; + /* not zeroed! */ + dict->entries = xrealloc(dict->entries, dict->max*sizeof(cff_dict_entry)); + } + + (dict->entries)[dict->count].id = id; + (dict->entries)[dict->count].key = (char *) dict_operator[id].opname; + if (argtype == CFF_TYPE_NUMBER || + argtype == CFF_TYPE_BOOLEAN || + argtype == CFF_TYPE_SID || + argtype == CFF_TYPE_OFFSET) { + stack_top--; + (dict->entries)[dict->count].count = 1; + (dict->entries)[dict->count].values = xcalloc(1, sizeof(double)); + (dict->entries)[dict->count].values[0] = arg_stack[stack_top]; + } else { + (dict->entries)[dict->count].count = stack_top; + (dict->entries)[dict->count].values = xcalloc(stack_top, sizeof(double)); + while (stack_top > 0) { + stack_top--; + (dict->entries)[dict->count].values[stack_top] = arg_stack[stack_top]; + } + } + + dict->count += 1; + *data += 1; + + return; +} + +/* + * All operands are treated as number or array of numbers. + * Private: two numbers, size and offset + * ROS : three numbers, SID, SID, and a number + */ +cff_dict *cff_dict_unpack (card8 *data, card8 *endptr) +{ + cff_dict *dict; + int status = CFF_PARSE_OK; + + stack_top = 0; + + dict = cff_new_dict(); + while (data < endptr && status == CFF_PARSE_OK) { + if (*data < 22) { /* operator */ + add_dict(dict, &data, endptr, &status); + } else if (*data == 30) { /* real - First byte of a sequence (variable) */ + if (stack_top < CFF_DICT_STACK_LIMIT) { + arg_stack[stack_top] = get_real(&data, endptr, &status); + stack_top++; + } else { + status = CFF_CFF_ERROR_STACK_OVERFLOW; + } + } else if (*data == 255 || (*data >= 22 && *data <= 27)) { /* reserved */ + data++; + } else { /* everything else are integer */ + if (stack_top < CFF_DICT_STACK_LIMIT) { + arg_stack[stack_top] = get_integer(&data, endptr, &status); + stack_top++; + } else { + status = CFF_CFF_ERROR_STACK_OVERFLOW; + } + } + } + + if (status != CFF_PARSE_OK) { + pdftex_fail("Parsing CFF DICT failed. (error=%d)", status); + } else if (stack_top != 0) { + WARN("Garbage in CFF DICT data."); + stack_top = 0; + } + + return dict; +} + + +int cff_dict_known (cff_dict *dict, const char *key) +{ + int i; + + for (i = 0; i < dict->count; i++) { + if (key && strcmp(key, (dict->entries)[i].key) == 0 + && (dict->entries)[i].count > 0) + return 1; + } + + return 0; +} + +double cff_dict_get (cff_dict *dict, const char *key, int idx) +{ + double value = 0.0; + int i; + + assert(key && dict); + + for (i = 0; i < dict->count; i++) { + if (strcmp(key, (dict->entries)[i].key) == 0) { + if ((dict->entries)[i].count > idx) + value = (dict->entries)[i].values[idx]; + else + pdftex_fail("Invalid index number."); + break; + } + } + + if (i == dict->count) + pdftex_fail("DICT entry \"%s\" not found.", key); + + return value; +} + +card8 cff_fdselect_lookup (cff_font *cff, card16 gid) +{ + card8 fd = 0xff; + cff_fdselect *fdsel; + + if (cff->fdselect == NULL) + CFF_ERROR("in cff_fdselect_lookup(): FDSelect not available"); + + fdsel = cff->fdselect; + + if (gid >= cff->num_glyphs) + CFF_ERROR("in cff_fdselect_lookup(): Invalid glyph index"); + + switch (fdsel->format) { + case 0: + fd = fdsel->data.fds[gid]; + break; + case 3: + { + if (gid == 0) { + fd = (fdsel->data).ranges[0].fd; + } else { + card16 i; + for (i=1;i<(fdsel->num_entries);i++) { + if (gid < (fdsel->data).ranges[i].first) + break; + } + fd = (fdsel->data).ranges[i-1].fd; + } + } + break; + default: + CFF_ERROR("in cff_fdselect_lookup(): Invalid FDSelect format"); + break; + } + + if (fd >= cff->num_fds) + CFF_ERROR("in cff_fdselect_lookup(): Invalid Font DICT index"); + + return fd; +} + +long cff_read_subrs (cff_font *cff) +{ + long len = 0; + long offset; + int i; + + + if ((cff->flag & FONTTYPE_CIDFONT) && cff->fdselect == NULL) { + cff_read_fdselect(cff); + } + + if ((cff->flag & FONTTYPE_CIDFONT) && cff->fdarray == NULL) { + cff_read_fdarray(cff); + } + + if (cff->private == NULL) + cff_read_private(cff); + + if (cff->gsubr == NULL) { + cff->offset = cff->gsubr_offset; + cff->gsubr = cff_get_index(cff); + } + + cff->subrs = xcalloc(cff->num_fds, sizeof(cff_index *)); + if (cff->flag & FONTTYPE_CIDFONT) { + for (i=0;inum_fds;i++) { + if (cff->private[i] == NULL || + !cff_dict_known(cff->private[i], "Subrs")) { + (cff->subrs)[i] = NULL; + } else { + offset = (long) cff_dict_get(cff->fdarray[i], "Private", 1); + offset += (long) cff_dict_get(cff->private[i], "Subrs", 0); + cff->offset = offset; + (cff->subrs)[i] = cff_get_index(cff); + len += cff_index_size((cff->subrs)[i]); + } + } + } else { + if (cff->private[0] == NULL || + !cff_dict_known(cff->private[0], "Subrs")) { + (cff->subrs)[0] = NULL; + } else { + offset = (long) cff_dict_get(cff->topdict, "Private", 1); + offset += (long) cff_dict_get(cff->private[0], "Subrs", 0); + cff->offset = offset; + (cff->subrs)[0] = cff_get_index(cff); + len += cff_index_size((cff->subrs)[0]); + } + } + + return len; +} + + +long cff_read_fdarray (cff_font *cff) +{ + long len = 0; + cff_index *idx; + long offset, size; + card16 i; + + if (cff->topdict == NULL) + CFF_ERROR("in cff_read_fdarray(): Top DICT not found"); + + if (!(cff->flag & FONTTYPE_CIDFONT)) + return 0; + + /* must exist */ + offset = (long) cff_dict_get(cff->topdict, "FDArray", 0); + cff->offset = offset; + idx = cff_get_index(cff); + cff->num_fds = (card8)idx->count; + cff->fdarray = xcalloc(idx->count, sizeof(cff_dict *)); + for (i=0;icount;i++) { + card8 *data = idx->data + (idx->offset)[i] - 1; + size = (idx->offset)[i+1] - (idx->offset)[i]; + if (size > 0) { + (cff->fdarray)[i] = cff_dict_unpack(data, data+size); + } else { + (cff->fdarray)[i] = NULL; + } + } + len = cff_index_size(idx); + cff_release_index(idx); + + return len; +} + + +long cff_read_private (cff_font *cff) +{ + long len = 0; + card8 *data; + long offset, size; + + if (cff->flag & FONTTYPE_CIDFONT) { + int i; + + if (cff->fdarray == NULL) + cff_read_fdarray(cff); + + cff->private = xcalloc(cff->num_fds, sizeof(cff_dict *)); + for (i=0;inum_fds;i++) { + if (cff->fdarray[i] != NULL && + cff_dict_known(cff->fdarray[i], "Private") && + (size = (long) cff_dict_get(cff->fdarray[i], "Private", 0)) + > 0) { + offset = (long) cff_dict_get(cff->fdarray[i], "Private", 1); + cff->offset = offset; + data = xcalloc(size, sizeof(card8)); + memcpy(data,&cff->stream[cff->offset],size); + cff->offset = size; + (cff->private)[i] = cff_dict_unpack(data, data+size); + xfree(data); + len += size; + } else { + (cff->private)[i] = NULL; + } + } + } else { + cff->num_fds = 1; + cff->private = xcalloc(1, sizeof(cff_dict *)); + if (cff_dict_known(cff->topdict, "Private") && + (size = (long) cff_dict_get(cff->topdict, "Private", 0)) > 0) { + offset = (long) cff_dict_get(cff->topdict, "Private", 1); + cff->offset = offset; + data = xcalloc(size, sizeof(card8)); + memcpy(data,&cff->stream[cff->offset],size); + cff->offset = size; + cff->private[0] = cff_dict_unpack(data, data+size); + xfree(data); + len += size; + } else { + (cff->private)[0] = NULL; + len = 0; + } + } + + return len; +} + + +cff_font *read_cff (unsigned char *buf,long buflength, int n) +{ + cff_font *cff; + cff_index *idx; + long offset ; + + + cff = xcalloc(1,sizeof(cff_font)); + + cff->stream = buf; + cff->stream_size = buflength; + cff->index = n; + + cff->header_major = get_card8(cff); + cff->header_minor = get_card8(cff); + cff->header_hdr_size = get_card8(cff); + cff->header_offsize = get_card8(cff); + if (cff->header_offsize < 1 || cff->header_offsize > 4) { + WARN("invalid offsize data"); + cff_close(cff); + return NULL; + } + if (cff->header_major > 1) { + pdftex_warn("CFF major version %u not supported.",cff->header_major); + cff_close(cff); + return NULL; + } + cff->offset = cff->header_hdr_size; + + /* Name INDEX */ + idx = cff_get_index(cff); + if (n > idx->count - 1) { + pdftex_warn("Invalid CFF fontset index number."); + cff_close(cff); + return NULL; + } + + cff->name = idx; + + cff->fontname = cff_get_name(cff); + + /* Top DICT INDEX */ + idx = cff_get_index(cff); + if (n > idx->count - 1) { + WARN("CFF Top DICT not exist..."); + cff_close(cff); + return NULL; + } + cff->topdict = cff_dict_unpack(idx->data + idx->offset[n] - 1, + idx->data + idx->offset[n + 1] - 1); + if (!cff->topdict) { + WARN("Parsing CFF Top DICT data failed..."); + cff_close(cff); + return NULL; + } + cff_release_index(idx); + + if (cff_dict_known(cff->topdict, "CharstringType") && + cff_dict_get(cff->topdict, "CharstringType", 0) != 2) { + WARN("Only Type 2 Charstrings supported..."); + cff_close(cff); + return NULL; + } + + if (cff_dict_known(cff->topdict, "SyntheticBase")) { + WARN("CFF Synthetic font not supported."); + cff_close(cff); + return NULL; + } + + /* String INDEX */ + cff->string = cff_get_index(cff); + + /* offset to GSubr */ + cff->gsubr_offset = cff->offset; + + /* Number of glyphs */ + offset = (long) cff_dict_get(cff->topdict, "CharStrings", 0); + cff->offset = offset; + cff->num_glyphs = get_card16(cff); + + /* Check for font type */ + if (cff_dict_known(cff->topdict, "ROS")) { + cff->flag |= FONTTYPE_CIDFONT; + } else { + cff->flag |= FONTTYPE_FONT; + } + + /* Check for encoding */ + if (cff_dict_known(cff->topdict, "Encoding")) { + offset = (long) cff_dict_get(cff->topdict, "Encoding", 0); + if (offset == 0) { /* predefined */ + cff->flag |= ENCODING_STANDARD; + } else if (offset == 1) { + cff->flag |= ENCODING_EXPERT; + } + } else { + cff->flag |= ENCODING_STANDARD; + } + + cff->offset = cff->gsubr_offset; /* seek back to GSubr */ + + return cff; +} + +/* write a cff for opentype */ + + + +/* Pack DICT data */ +static long pack_integer (card8 *dest, long destlen, long value) +{ + long len = 0; + + if (value >= -107 && value <= 107) { + if (destlen < 1) + CFF_ERROR("Buffer overflow."); + dest[0] = (value + 139) & 0xff; + len = 1; + } else if (value >= 108 && value <= 1131) { + if (destlen < 2) + CFF_ERROR("Buffer overflow."); + value = 0xf700u + value - 108; + dest[0] = (value >> 8) & 0xff; + dest[1] = value & 0xff; + len = 2; + } else if (value >= -1131 && value <= -108) { + if (destlen < 2) + CFF_ERROR("Buffer overflow."); + value = 0xfb00u - value - 108; + dest[0] = (value >> 8) & 0xff; + dest[1] = value & 0xff; + len = 2; + } else if (value >= -32768 && value <= 32767) { /* shortint */ + if (destlen < 3) + CFF_ERROR("Buffer overflow."); + dest[0] = 28; + dest[1] = (value >> 8) & 0xff; + dest[2] = value & 0xff; + len = 3; + } else { /* longint */ + if (destlen < 5) + CFF_ERROR("Buffer overflow."); + dest[0] = 29; + dest[1] = (value >> 24) & 0xff; + dest[2] = (value >> 16) & 0xff; + dest[3] = (value >> 8) & 0xff; + dest[4] = value & 0xff; + len = 5; + } + return len; +} + +static long pack_real (card8 *dest, long destlen, double value) +{ + long e; + int i = 0, pos = 2; +#define CFF_REAL_MAX_LEN 17 + + if (destlen < 2) + CFF_ERROR("Buffer overflow."); + + dest[0] = 30; + + if (value == 0.0) { + dest[1] = 0x0f; + return 2; + } + + if (value < 0.0) { + dest[1] = 0xe0; + value *= -1.0; + pos++; + } + + e = 0; + if (value >= 10.0) { + while (value >= 10.0) { + value /= 10.0; + e++; + } + } else if (value < 1.0) { + while (value < 1.0) { + value *= 10.0; + e--; + } + } + + sprintf(work_buffer, "%1.14g", value); + for (i=0;i= '0' && work_buffer[i] <= '9') { + ch = work_buffer[i] - '0'; + } else { + CFF_ERROR("Invalid character."); + } + + if (destlen < pos/2 + 1) + CFF_ERROR("Buffer overflow."); + + if (pos % 2) { + dest[pos/2] += ch; + } else { + dest[pos/2] = (ch << 4); + } + pos++; + } + + if (e > 0) { + if (pos % 2) { + dest[pos/2] += 0x0b; + } else { + if (destlen < pos/2 + 1) + CFF_ERROR("Buffer overflow."); + dest[pos/2] = 0xb0; + } + pos++; + } else if (e < 0) { + if (pos % 2) { + dest[pos/2] += 0x0c; + } else { + if (destlen < pos/2 + 1) + CFF_ERROR("Buffer overflow."); + dest[pos/2] = 0xc0; + } + e *= -1; + pos++; + } + + if (e != 0) { + sprintf(work_buffer, "%ld", e); + for (i=0;i= '0' && work_buffer[i] <= '9') { + ch = work_buffer[i] - '0'; + } else { + CFF_ERROR("Invalid character."); + } + + if (destlen < pos/2 + 1) + CFF_ERROR("Buffer overflow."); + + if (pos % 2) { + dest[pos/2] += ch; + } else { + dest[pos/2] = (ch << 4); + } + pos++; + } + } + + if (pos % 2) { + dest[pos/2] += 0x0f; + pos++; + } else { + if (destlen < pos/2 + 1) + CFF_ERROR("Buffer overflow."); + dest[pos/2] = 0xff; + pos += 2; + } + + return pos/2; +} + +static long cff_dict_put_number (double value, + card8 *dest, long destlen, + int type) +{ + long len = 0; + double nearint; + + nearint = floor(value+0.5); + /* set offset to longint */ + if (type == CFF_TYPE_OFFSET) { + long lvalue; + + lvalue = (long) value; + if (destlen < 5) + CFF_ERROR("Buffer overflow."); + dest[0] = 29; + dest[1] = (lvalue >> 24) & 0xff; + dest[2] = (lvalue >> 16) & 0xff; + dest[3] = (lvalue >> 8) & 0xff; + dest[4] = lvalue & 0xff; + len = 5; + } else if (value > CFF_INT_MAX || value < CFF_INT_MIN || + (fabs(value - nearint) > 1.0e-5)) { /* real */ + len = pack_real(dest, destlen, value); + } else { /* integer */ + len = pack_integer(dest, destlen, (long) nearint); + } + + return len; +} + +static long +put_dict_entry (cff_dict_entry *de, + card8 *dest, long destlen) +{ + long len = 0; + int i, type, id; + + if (de->count > 0) { + id = de->id; + if (dict_operator[id].argtype == CFF_TYPE_OFFSET || + dict_operator[id].argtype == CFF_TYPE_SZOFF) { + type = CFF_TYPE_OFFSET; + } else { + type = CFF_TYPE_NUMBER; + } + for (i = 0; i < de->count; i++) { + len += cff_dict_put_number(de->values[i], + dest+len, + destlen-len, type); + } + if (id >= 0 && id < CFF_LAST_DICT_OP1) { + if (len + 1 > destlen) + CFF_ERROR("Buffer overflow."); + dest[len++] = id; + } else if (id >= 0 && id < CFF_LAST_DICT_OP) { + if (len + 2 > destlen) + CFF_ERROR("in cff_dict_pack(): Buffer overflow"); + dest[len++] = 12; + dest[len++] = id - CFF_LAST_DICT_OP1; + } else { + CFF_ERROR("Invalid CFF DICT operator ID."); + } + } + + return len; +} + +long cff_dict_pack (cff_dict *dict, card8 *dest, long destlen) +{ + long len = 0; + int i; + + for (i = 0; i < dict->count; i++) { + if (!strcmp(dict->entries[i].key, "ROS")) { + len += put_dict_entry(&dict->entries[i], dest, destlen); + break; + } + } + for (i = 0; i < dict->count; i++) { + if (strcmp(dict->entries[i].key, "ROS")) { + len += put_dict_entry(&dict->entries[i], dest+len, destlen-len); + } + } + + return len; +} + + +void cff_dict_add (cff_dict *dict, const char *key, int count) +{ + int id, i; + + for (id=0;idcount;i++) { + if ((dict->entries)[i].id == id) { + if ((dict->entries)[i].count != count) + CFF_ERROR("Inconsistent DICT argument number."); + return; + } + } + + if (dict->count + 1 >= dict->max) { + dict->max += 8; + dict->entries = xrealloc(dict->entries, (dict->max)*sizeof(cff_dict_entry)); + } + + (dict->entries)[dict->count].id = id; + (dict->entries)[dict->count].key = (char *) dict_operator[id].opname; + (dict->entries)[dict->count].count = count; + if (count > 0) { + (dict->entries)[dict->count].values = xcalloc(count, sizeof(double)); + memset((dict->entries)[dict->count].values, + 0, sizeof(double)*count); + } else { + (dict->entries)[dict->count].values = NULL; + } + dict->count += 1; + + return; +} + + +void cff_dict_remove (cff_dict *dict, const char *key) +{ + int i; + for (i = 0; i < dict->count; i++) { + if (key && strcmp(key, (dict->entries)[i].key) == 0) { + (dict->entries)[i].count = 0; + if ((dict->entries)[i].values) + xfree((dict->entries)[i].values); + (dict->entries)[i].values = NULL; + } + } +} + +void cff_dict_set (cff_dict *dict, const char *key, int idx, double value) +{ + int i; + + assert(dict && key); + + for (i = 0 ; i < dict->count; i++) { + if (strcmp(key, (dict->entries)[i].key) == 0) { + if ((dict->entries)[i].count > idx) + (dict->entries)[i].values[idx] = value; + else + CFF_ERROR("Invalid index number."); + break; + } + } + + if (i == dict->count) + pdftex_fail("DICT entry \"%s\" not found.", key); +} + + +/* Strings */ +char *cff_get_string (cff_font *cff, s_SID id) +{ + char *result = NULL; + long len; + + if (id < CFF_STDSTR_MAX) { + len = strlen(cff_stdstr[id]); + result = xcalloc(len+1, sizeof(char)); + memcpy(result, cff_stdstr[id], len); + result[len] = '\0'; + } else if (cff && cff->string) { + cff_index *strings = cff->string; + id -= CFF_STDSTR_MAX; + if (id < strings->count) { + len = (strings->offset)[id+1] - (strings->offset)[id]; + result = xcalloc(len + 1, sizeof(char)); + memmove(result, strings->data + (strings->offset)[id] - 1, len); + result[len] = '\0'; + } + } + + return result; +} + +long cff_get_sid (cff_font *cff, char *str) +{ + card16 i; + + if (!cff || !str) + return -1; + + /* I search String INDEX first. */ + if (cff && cff->string) { + cff_index *idx = cff->string; + for (i = 0; i < idx->count; i++) { + if (strlen(str) == (idx->offset)[i+1] - (idx->offset)[i] && + !memcmp(str, (idx->data)+(idx->offset)[i]-1, strlen(str))) + return (i + CFF_STDSTR_MAX); + } + } + + for (i = 0; i < CFF_STDSTR_MAX; i++) { + if (!strcmp(str, cff_stdstr[i])) + return i; + } + + return -1; +} + + +void cff_update_string (cff_font *cff) +{ + if (cff == NULL) + CFF_ERROR("CFF font not opened."); + + if (cff->string) + cff_release_index(cff->string); + cff->string = cff->_string; + cff->_string = NULL; +} + + +s_SID cff_add_string (cff_font *cff, char *str) +{ + card16 idx; + cff_index *strings; + l_offset offset, size; + + if (cff == NULL) + CFF_ERROR("CFF font not opened."); + + if (cff->_string == NULL) + cff->_string = cff_new_index(0); + strings = cff->_string; + + for (idx = 0; idx < strings->count; idx++) { + size = strings->offset[idx+1] - strings->offset[idx]; + offset = strings->offset[idx]; + if (size == strlen(str) && + !memcmp(strings->data+offset-1, str, strlen(str))) + return (idx + CFF_STDSTR_MAX); + } + + for (idx = 0; idx < CFF_STDSTR_MAX; idx++) { + if (cff_stdstr[idx] && + !strcmp(cff_stdstr[idx], str)) + return idx; + } + offset = (strings->count > 0) ? strings->offset[strings->count] : 1; + strings->offset = xrealloc(strings->offset, (strings->count+2)*sizeof(l_offset)); + if (strings->count == 0) + strings->offset[0] = 1; + idx = strings->count; + strings->count += 1; + strings->offset[strings->count] = offset + strlen(str); + strings->data = xrealloc(strings->data, (offset+strlen(str)-1)*sizeof(card8)); + memcpy(strings->data+offset-1, str, strlen(str)); + + return (idx + CFF_STDSTR_MAX); +} + + +void cff_dict_update (cff_dict *dict, cff_font *cff) +{ + int i; + + for (i = 0;i < dict->count; i++) { + if ((dict->entries)[i].count > 0) { + char *str; + int id; + + id = (dict->entries)[i].id; + + if (dict_operator[id].argtype == CFF_TYPE_SID) { + str = cff_get_string(cff, (dict->entries)[i].values[0]); + (dict->entries)[i].values[0] = cff_add_string(cff, str); + xfree(str); + } else if (dict_operator[id].argtype == CFF_TYPE_ROS) { + str = cff_get_string(cff, (dict->entries)[i].values[0]); + (dict->entries)[i].values[0] = cff_add_string(cff, str); + xfree(str); + str = cff_get_string(cff, (dict->entries)[i].values[1]); + (dict->entries)[i].values[1] = cff_add_string(cff, str); + xfree(str); + } + + } + } +} + +/* charsets */ + +long cff_read_charsets (cff_font *cff) +{ + cff_charsets *charset; + long offset, length; + card16 count, i; + + if (cff->topdict == NULL) + CFF_ERROR("Top DICT not available"); + + if (!cff_dict_known(cff->topdict, "charset")) { + cff->flag |= CHARSETS_ISOADOBE; + cff->charsets = NULL; + return 0; + } + + offset = (long) cff_dict_get(cff->topdict, "charset", 0); + + if (offset == 0) { /* predefined */ + cff->flag |= CHARSETS_ISOADOBE; + cff->charsets = NULL; + return 0; + } else if (offset == 1) { + cff->flag |= CHARSETS_EXPERT; + cff->charsets = NULL; + return 0; + } else if (offset == 2) { + cff->flag |= CHARSETS_EXPSUB; + cff->charsets = NULL; + return 0; + } + + cff->offset = offset; + cff->charsets = charset = xcalloc(1, sizeof(cff_charsets)); + charset->format = get_card8(cff); + charset->num_entries = 0; + + count = cff->num_glyphs - 1; + length = 1; + + /* Not sure. Not well documented. */ + switch (charset->format) { + case 0: + charset->num_entries = cff->num_glyphs - 1; /* no .notdef */ + charset->data.glyphs = xcalloc(charset->num_entries, sizeof(s_SID)); + length += (charset->num_entries) * 2; + for (i=0;i<(charset->num_entries);i++) { + charset->data.glyphs[i] = get_card16(cff); + } + count = 0; + break; + case 1: + { + cff_range1 *ranges = NULL; + while (count > 0 && charset->num_entries < cff->num_glyphs) { + ranges = xrealloc(ranges, (charset->num_entries + 1)*sizeof(cff_range1)); + ranges[charset->num_entries].first = get_card16(cff); + ranges[charset->num_entries].n_left = get_card8(cff); + count -= ranges[charset->num_entries].n_left + 1; /* no-overrap */ + charset->num_entries += 1; + charset->data.range1 = ranges; + } + length += (charset->num_entries) * 3; + } + break; + case 2: + { + cff_range2 *ranges = NULL; + while (count > 0 && charset->num_entries < cff->num_glyphs) { + ranges = xrealloc(ranges, (charset->num_entries + 1)*sizeof(cff_range2)); + ranges[charset->num_entries].first = get_card16(cff); + ranges[charset->num_entries].n_left = get_card16(cff); + count -= ranges[charset->num_entries].n_left + 1; /* non-overrapping */ + charset->num_entries += 1; + } + charset->data.range2 = ranges; + length += (charset->num_entries) * 4; + } + break; + default: + xfree(charset); + CFF_ERROR("Unknown Charset format"); + break; + } + + if (count > 0) + CFF_ERROR("Charset data possibly broken"); + + return length; +} + +long cff_pack_charsets (cff_font *cff, card8 *dest, long destlen) +{ + long len = 0; + card16 i; + cff_charsets *charset; + + if (cff->flag & HAVE_STANDARD_CHARSETS || cff->charsets == NULL) + return 0; + + if (destlen < 1) + CFF_ERROR("in cff_pack_charsets(): Buffer overflow"); + + charset = cff->charsets; + + dest[len++] = charset->format; + switch (charset->format) { + case 0: + if (destlen < len + (charset->num_entries)*2) + CFF_ERROR("in cff_pack_charsets(): Buffer overflow"); + for (i=0;i<(charset->num_entries);i++) { + s_SID sid = (charset->data).glyphs[i]; /* or CID */ + dest[len++] = (sid >> 8) & 0xff; + dest[len++] = sid & 0xff; + } + break; + case 1: + { + if (destlen < len + (charset->num_entries)*3) + CFF_ERROR("in cff_pack_charsets(): Buffer overflow"); + for (i=0;i<(charset->num_entries);i++) { + dest[len++] = ((charset->data).range1[i].first >> 8) & 0xff; + dest[len++] = (charset->data).range1[i].first & 0xff; + dest[len++] = (charset->data).range1[i].n_left; + } + } + break; + case 2: + { + if (destlen < len + (charset->num_entries)*4) + CFF_ERROR("in cff_pack_charsets(): Buffer overflow"); + for (i=0;i<(charset->num_entries);i++) { + dest[len++] = ((charset->data).range2[i].first >> 8) & 0xff; + dest[len++] = (charset->data).range2[i].first & 0xff; + dest[len++] = ((charset->data).range2[i].n_left >> 8) & 0xff; + dest[len++] = (charset->data).range2[i].n_left & 0xff; + } + } + break; + default: + CFF_ERROR("Unknown Charset format"); + break; + } + + return len; +} + + + +/* + * Type 2 Charstring support: + * Decode and encode Type 2 charstring + * + * All local/global subroutine calls in a given charstring is replace by the + * content of subroutine charstrings. We do this because some PostScript RIP + * may have problems with sparse subroutine array. Workaround for this is to + * re-order subroutine array so that no gap appears in the subroutine array, + * or put dummy charstrings that contains only `return' in the gap. However, + * re-ordering of subroutine is rather difficult for Type 2 charstrings due + * to the bias which depends on the total number of subroutines. Replacing + * callgsubr/callsubr calls with the content of the corresponding subroutine + * charstring may be more efficient than putting dummy subroutines in the + * case of subsetted font. Adobe distiller seems doing same thing. + * + * And also note that subroutine numbers within subroutines can depend on the + * content of operand stack as follows: + * + * ... l m callsubr << subr #(m+bias): n add callsubr >> ... + * + * I've not implemented the `random' operator which generates a pseudo-random + * number in the range (0, 1] and push them into argument stack. + * How pseudo-random sequences are generated is not documented in the Type 2 + * charstring spec.. + */ + + +#define CS_TYPE2_DEBUG_STR "Type2 Charstring Parser" +#define CS_TYPE2_DEBUG 5 + +/* decoder/encoder status codes */ +#define CS_BUFFER_CFF_ERROR -3 +#define CS_STACK_CFF_ERROR -2 +#define CS_PARSE_CFF_ERROR -1 +#define CS_PARSE_OK 0 +#define CS_PARSE_END 1 +#define CS_SUBR_RETURN 2 +#define CS_CHAR_END 3 + +static int status = CS_PARSE_CFF_ERROR; + +#define DST_NEED(a,b) {if ((a) < (b)) { status = CS_BUFFER_CFF_ERROR ; return ; }} +#define SRC_NEED(a,b) {if ((a) < (b)) { status = CS_PARSE_CFF_ERROR ; return ; }} +#define NEED(a,b) {if ((a) < (b)) { status = CS_STACK_CFF_ERROR ; return ; }} + +/* hintmask and cntrmask need number of stem zones */ +static int num_stems = 0; +static int phase = 0; + +/* subroutine nesting */ +static int cs2_nest = 0; + +/* advance width */ +static int have_width = 0; +static double width = 0.0; + +/* + * Standard Encoding Accented Characters: + * Optional four arguments for endchar. See, CFF spec., p.35. + * This is obsolete feature and is no longer supported. + */ +#if 0 +/* adx ady bchar achar endchar */ +static double seac[4] = {0.0, 0.0, 0.0, 0.0}; +#endif + +/* Operand stack and Transient array */ +static int cs2_stack_top = 0; +static double cs2_arg_stack[CS_ARG_STACK_MAX]; +static double trn_array[CS_TRANS_ARRAY_MAX]; + +/* + * Type 2 CharString encoding + */ + +/* + * 1-byte CharString operaotrs: + * cs_escape is first byte of two-byte operator + */ + +/* RESERVED 0 */ +#define cs_hstem 1 +/* RESERVED 2 */ +#define cs_vstem 3 +#define cs_vmoveto 4 +#define cs_rlineto 5 +#define cs_hlineto 6 +#define cs_vlineto 7 +#define cs_rrcurveto 8 +/* cs_closepath 9 : TYPE1 */ +#define cs_callsubr 10 +#define cs_return 11 +#define cs_escape 12 +/* cs_hsbw 13 : TYPE1 */ +#define cs_endchar 14 +/* RESERVED 15 */ +/* RESERVED 16 */ +/* RESERVED 17 */ +#define cs_hstemhm 18 +#define cs_hintmask 19 +#define cs_cntrmask 20 +#define cs_rmoveto 21 +#define cs_hmoveto 22 +#define cs_vstemhm 23 +#define cs_rcurveline 24 +#define cs_rlinecurve 25 +#define cs_vvcurveto 26 +#define cs_hhcurveto 27 +/* SHORTINT 28 : first byte of shortint*/ +#define cs_callgsubr 29 +#define cs_vhcurveto 30 +#define cs_hvcurveto 31 + +/* + * 2-byte CharString operaotrs: + * "dotsection" is obsoleted in Type 2 charstring. + */ + +#define cs_dotsection 0 +/* cs_vstem3 1 : TYPE1 */ +/* cs_hstem3 2 : TYPE1 */ +#define cs_and 3 +#define cs_or 4 +#define cs_not 5 +/* cs_seac 6 : TYPE1 */ +/* cs_sbw 7 : TYPE1 */ +/* RESERVED 8 */ +#define cs_abs 9 +#define cs_add 10 +#define cs_sub 11 +#define cs_div 12 +/* RESERVED 13 */ +#define cs_neg 14 +#define cs_eq 15 +/* cs_callothersubr 16 : TYPE1 */ +/* cs_pop 17 : TYPE1 */ +#define cs_drop 18 +/* RESERVED 19 */ +#define cs_put 20 +#define cs_get 21 +#define cs_ifelse 22 +#define cs_random 23 +#define cs_mul 24 +/* RESERVED 25 */ +#define cs_sqrt 26 +#define cs_dup 27 +#define cs_exch 28 +#define cs_index 29 +#define cs_roll 30 +/* cs_setcurrentpoint 31 : TYPE1 */ +/* RESERVED 32 */ +/* RESERVED 33 */ +#define cs_hflex 34 +#define cs_flex 35 +#define cs_hflex1 36 +#define cs_flex1 37 + +/* + * clear_stack() put all operands sotred in operand stack to dest. + */ +static void +clear_stack (card8 **dest, card8 *limit) +{ + int i; + + for (i = 0; i < cs2_stack_top; i++) { + double value; + long ivalue; + value = cs2_arg_stack[i]; + /* Nearest integer value */ + ivalue = (long) floor(value+0.5); + if (value >= 0x8000L || value <= (-0x8000L - 1)) { + /* + * This number cannot be represented as a single operand. + * We must use `a b mul ...' or `a c div' to represent large values. + */ + CFF_ERROR("Argument value too large. (This is bug)"); + } else if (fabs(value - ivalue) > 3.0e-5) { + /* 16.16-bit signed fixed value */ + DST_NEED(limit, *dest + 5); + *(*dest)++ = 255; + ivalue = (long) floor(value); /* mantissa */ + *(*dest)++ = (ivalue >> 8) & 0xff; + *(*dest)++ = ivalue & 0xff; + ivalue = (long)((value - ivalue) * 0x10000l); /* fraction */ + *(*dest)++ = (ivalue >> 8) & 0xff; + *(*dest)++ = ivalue & 0xff; + /* Everything else are integers. */ + } else if (ivalue >= -107 && ivalue <= 107) { + DST_NEED(limit, *dest + 1); + *(*dest)++ = ivalue + 139; + } else if (ivalue >= 108 && ivalue <= 1131) { + DST_NEED(limit, *dest + 2); + ivalue = 0xf700u + ivalue - 108; + *(*dest)++ = (ivalue >> 8) & 0xff; + *(*dest)++ = ivalue & 0xff; + } else if (ivalue >= -1131 && ivalue <= -108) { + DST_NEED(limit, *dest + 2); + ivalue = 0xfb00u - ivalue - 108; + *(*dest)++ = (ivalue >> 8) & 0xff; + *(*dest)++ = ivalue & 0xff; + } else if (ivalue >= -32768 && ivalue <= 32767) { /* shortint */ + DST_NEED(limit, *dest + 3); + *(*dest)++ = 28; + *(*dest)++ = (ivalue >> 8) & 0xff; + *(*dest)++ = (ivalue) & 0xff; + } else { /* Shouldn't come here */ + CFF_ERROR("Unexpected error."); + } + } + + cs2_stack_top = 0; /* clear stack */ + + return; +} + +/* + * Single byte operators: + * Path construction, Operator for finishing a path, Hint operators. + * + * phase: + * 0: inital state + * 1: hint declaration, first stack-clearing operator appeared + * 2: in path construction + */ + +static void +do_operator1 (card8 **dest, card8 *limit, card8 **data, card8 *endptr) +{ + card8 op = **data; + + *data += 1; + + switch (op) { + case cs_hstemhm: + case cs_vstemhm: + /* charstring may have hintmask if above operator have seen */ + case cs_hstem: + case cs_vstem: + if (phase == 0 && (cs2_stack_top % 2)) { + have_width = 1; + width = cs2_arg_stack[0]; + } + num_stems += cs2_stack_top/2; + clear_stack(dest, limit); + DST_NEED(limit, *dest + 1); + *(*dest)++ = op; + phase = 1; + break; + case cs_hintmask: + case cs_cntrmask: + if (phase < 2) { + if (phase == 0 && (cs2_stack_top % 2)) { + have_width = 1; + width = cs2_arg_stack[0]; + } + num_stems += cs2_stack_top/2; + } + clear_stack(dest, limit); + DST_NEED(limit, *dest + 1); + *(*dest)++ = op; + if (num_stems > 0) { + int masklen = (num_stems + 7) / 8; + DST_NEED(limit, *dest + masklen); + SRC_NEED(endptr, *data + masklen); + memmove(*dest, *data, masklen); + *data += masklen; + *dest += masklen; + } + phase = 2; + break; + case cs_rmoveto: + if (phase == 0 && (cs2_stack_top % 2)) { + have_width = 1; + width = cs2_arg_stack[0]; + } + clear_stack(dest, limit); + DST_NEED(limit, *dest + 1); + *(*dest)++ = op; + phase = 2; + break; + case cs_hmoveto: + case cs_vmoveto: + if (phase == 0 && (cs2_stack_top % 2) == 0) { + have_width = 1; + width = cs2_arg_stack[0]; + } + clear_stack(dest, limit); + DST_NEED(limit, *dest + 1); + *(*dest)++ = op; + phase = 2; + break; + case cs_endchar: + if (cs2_stack_top == 1) { + have_width = 1; + width = cs2_arg_stack[0]; + clear_stack(dest, limit); + } else if (cs2_stack_top == 4 || cs2_stack_top == 5) { + WARN("\"seac\" character deprecated in Type 2 charstring."); + status = CS_PARSE_CFF_ERROR; + return; + } else if (cs2_stack_top > 0) { + WARN("Operand stack not empty."); + } + DST_NEED(limit, *dest + 1); + *(*dest)++ = op; + status = CS_CHAR_END; + break; + /* above oprators are candidate for first stack-clearing operator */ + case cs_rlineto: + case cs_hlineto: + case cs_vlineto: + case cs_rrcurveto: + case cs_rcurveline: + case cs_rlinecurve: + case cs_vvcurveto: + case cs_hhcurveto: + case cs_vhcurveto: + case cs_hvcurveto: + if (phase < 2) { + WARN("Broken Type 2 charstring."); + status = CS_PARSE_CFF_ERROR; + return; + } + clear_stack(dest, limit); + DST_NEED(limit, *dest + 1); + *(*dest)++ = op; + break; + /* all operotors above are stack-clearing operator */ + /* no output */ + case cs_return: + case cs_callgsubr: + case cs_callsubr: + CFF_ERROR("Unexpected call(g)subr/return"); + break; + default: + /* no-op ? */ + WARN("%s: Unknown charstring operator: 0x%02x", CS_TYPE2_DEBUG_STR, op); + status = CS_PARSE_CFF_ERROR; + break; + } + + return; +} + +/* + * Double byte operators: + * Flex, arithmetic, conditional, and storage operators. + * + * Following operators are not supported: + * random: How random ? + */ +static void +do_operator2 (card8 **dest, card8 *limit, card8 **data, card8 *endptr) +{ + card8 op; + + *data += 1; + + SRC_NEED(endptr, *data + 1); + + op = **data; + *data += 1; + + switch(op) { + case cs_dotsection: /* deprecated */ + WARN("Operator \"dotsection\" deprecated in Type 2 charstring."); + status = CS_PARSE_CFF_ERROR; + return; + break; + case cs_hflex: + case cs_flex: + case cs_hflex1: + case cs_flex1: + if (phase < 2) { + WARN("%s: Broken Type 2 charstring.", CS_TYPE2_DEBUG_STR); + status = CS_PARSE_CFF_ERROR; + return; + } + clear_stack(dest, limit); + DST_NEED(limit, *dest + 2); + *(*dest)++ = cs_escape; + *(*dest)++ = op; + break; + /* all operator above are stack-clearing */ + /* no output */ + case cs_and: + NEED(cs2_stack_top, 2); + cs2_stack_top--; + if (cs2_arg_stack[cs2_stack_top] && cs2_arg_stack[cs2_stack_top-1]) { + cs2_arg_stack[cs2_stack_top-1] = 1.0; + } else { + cs2_arg_stack[cs2_stack_top-1] = 0.0; + } + break; + case cs_or: + NEED(cs2_stack_top, 2); + cs2_stack_top--; + if (cs2_arg_stack[cs2_stack_top] || cs2_arg_stack[cs2_stack_top-1]) { + cs2_arg_stack[cs2_stack_top-1] = 1.0; + } else { + cs2_arg_stack[cs2_stack_top-1] = 0.0; + } + break; + case cs_not: + NEED(cs2_stack_top, 1); + if (cs2_arg_stack[cs2_stack_top-1]) { + cs2_arg_stack[cs2_stack_top-1] = 0.0; + } else { + cs2_arg_stack[cs2_stack_top-1] = 1.0; + } + break; + case cs_abs: + NEED(cs2_stack_top, 1); + cs2_arg_stack[cs2_stack_top-1] = fabs(cs2_arg_stack[cs2_stack_top-1]); + break; + case cs_add: + NEED(cs2_stack_top, 2); + cs2_arg_stack[cs2_stack_top-2] += cs2_arg_stack[cs2_stack_top-1]; + cs2_stack_top--; + break; + case cs_sub: + NEED(cs2_stack_top, 2); + cs2_arg_stack[cs2_stack_top-2] -= cs2_arg_stack[cs2_stack_top-1]; + cs2_stack_top--; + break; + case cs_div: /* doesn't check overflow */ + NEED(cs2_stack_top, 2); + cs2_arg_stack[cs2_stack_top-2] /= cs2_arg_stack[cs2_stack_top-1]; + cs2_stack_top--; + break; + case cs_neg: + NEED(cs2_stack_top, 1); + cs2_arg_stack[cs2_stack_top-1] *= -1.0; + break; + case cs_eq: + NEED(cs2_stack_top, 2); + cs2_stack_top--; + if (cs2_arg_stack[cs2_stack_top] == cs2_arg_stack[cs2_stack_top-1]) { + cs2_arg_stack[cs2_stack_top-1] = 1.0; + } else { + cs2_arg_stack[cs2_stack_top-1] = 0.0; + } + break; + case cs_drop: + NEED(cs2_stack_top, 1); + cs2_stack_top--; + break; + case cs_put: + NEED(cs2_stack_top, 2); + { + int idx = (int)cs2_arg_stack[--cs2_stack_top]; + NEED(CS_TRANS_ARRAY_MAX, idx); + trn_array[idx] = cs2_arg_stack[--cs2_stack_top]; + } + break; + case cs_get: + NEED(cs2_stack_top, 1); + { + int idx = (int)cs2_arg_stack[cs2_stack_top-1]; + NEED(CS_TRANS_ARRAY_MAX, idx); + cs2_arg_stack[cs2_stack_top-1] = trn_array[idx]; + } + break; + case cs_ifelse: + NEED(cs2_stack_top, 4); + cs2_stack_top -= 3; + if (cs2_arg_stack[cs2_stack_top+1] > cs2_arg_stack[cs2_stack_top+2]) { + cs2_arg_stack[cs2_stack_top-1] = cs2_arg_stack[cs2_stack_top]; + } + break; + case cs_mul: + NEED(cs2_stack_top, 2); + cs2_arg_stack[cs2_stack_top-2] = cs2_arg_stack[cs2_stack_top-2] * cs2_arg_stack[cs2_stack_top-1]; + cs2_stack_top--; + break; + case cs_sqrt: + NEED(cs2_stack_top, 1); + cs2_arg_stack[cs2_stack_top-1] = sqrt(cs2_arg_stack[cs2_stack_top-1]); + break; + case cs_dup: + NEED(cs2_stack_top, 1); + NEED(CS_ARG_STACK_MAX, cs2_stack_top+1); + cs2_arg_stack[cs2_stack_top] = cs2_arg_stack[cs2_stack_top-1]; + cs2_stack_top++; + break; + case cs_exch: + NEED(cs2_stack_top, 2); + { + double save = cs2_arg_stack[cs2_stack_top-2]; + cs2_arg_stack[cs2_stack_top-2] = cs2_arg_stack[cs2_stack_top-1]; + cs2_arg_stack[cs2_stack_top-1] = save; + } + break; + case cs_index: + NEED(cs2_stack_top, 2); /* need two arguments at least */ + { + int idx = (int)cs2_arg_stack[cs2_stack_top-1]; + if (idx < 0) { + cs2_arg_stack[cs2_stack_top-1] = cs2_arg_stack[cs2_stack_top-2]; + } else { + NEED(cs2_stack_top, idx+2); + cs2_arg_stack[cs2_stack_top-1] = cs2_arg_stack[cs2_stack_top-idx-2]; + } + } + break; + case cs_roll: + NEED(cs2_stack_top, 2); + { + int N, J; + J = (int)cs2_arg_stack[--cs2_stack_top]; + N = (int)cs2_arg_stack[--cs2_stack_top]; + NEED(cs2_stack_top, N); + if (J > 0) { + J = J % N; + while (J-- > 0) { + double save = cs2_arg_stack[cs2_stack_top-1]; + int i = cs2_stack_top - 1; + while (i > cs2_stack_top-N) { + cs2_arg_stack[i] = cs2_arg_stack[i-1]; + i--; + } + cs2_arg_stack[i] = save; + } + } else { + J = (-J) % N; + while (J-- > 0) { + double save = cs2_arg_stack[cs2_stack_top-N]; + int i = cs2_stack_top - N; + while (i < cs2_stack_top-1) { + cs2_arg_stack[i] = cs2_arg_stack[i+1]; + i++; + } + cs2_arg_stack[i] = save; + } + } + } + break; + case cs_random: + WARN("%s: Charstring operator \"random\" found.", CS_TYPE2_DEBUG_STR); + NEED(CS_ARG_STACK_MAX, cs2_stack_top+1); + cs2_arg_stack[cs2_stack_top++] = 1.0; + break; + default: + /* no-op ? */ + WARN("%s: Unknown charstring operator: 0x0c%02x", CS_TYPE2_DEBUG_STR, op); + status = CS_PARSE_CFF_ERROR; + break; + } + + return; +} + +/* + * integer: + * exactly the same as the DICT encoding (except 29) + */ +static void +cs2_get_integer (card8 **data, card8 *endptr) +{ + long result = 0; + card8 b0 = **data, b1, b2; + + *data += 1; + + if (b0 == 28) { /* shortint */ + SRC_NEED(endptr, *data + 2); + b1 = **data; + b2 = *(*data+1); + result = b1*256+b2; + if (result > 0x7fff) + result -= 0x10000L; + *data += 2; + } else if (b0 >= 32 && b0 <= 246) { /* int (1) */ + result = b0 - 139; + } else if (b0 >= 247 && b0 <= 250) { /* int (2) */ + SRC_NEED(endptr, *data + 1); + b1 = **data; + result = (b0-247)*256+b1+108; + *data += 1; + } else if (b0 >= 251 && b0 <= 254) { + SRC_NEED(endptr, *data + 1); + b1 = **data; + result = -(b0-251)*256-b1-108; + *data += 1; + } else { + status = CS_PARSE_CFF_ERROR; + return; + } + + NEED(CS_ARG_STACK_MAX, cs2_stack_top+1); + cs2_arg_stack[cs2_stack_top++] = (double) result; + + return; +} + +/* + * Signed 16.16-bits fixed number for Type 2 charstring encoding + */ +static void +get_fixed (card8 **data, card8 *endptr) +{ + long ivalue; + double rvalue; + + *data += 1; + + SRC_NEED(endptr, *data + 4); + + ivalue = *(*data) * 0x100 + *(*data+1); + rvalue = (ivalue > 0x7fffL) ? (ivalue - 0x10000L) : ivalue; + ivalue = *(*data+2) * 0x100 + *(*data+3); + rvalue += ((double) ivalue) / 0x10000L; + + NEED(CS_ARG_STACK_MAX, cs2_stack_top+1); + cs2_arg_stack[cs2_stack_top++] = rvalue; + *data += 4; + + return; +} + +/* + * Subroutines: + * The bias for subroutine number is introduced in type 2 charstrings. + * + * subr: set to a pointer to the subroutine charstring. + * len: set to the length of subroutine charstring. + * subr_idx: CFF INDEX data that contains subroutines. + * id: biased subroutine number. + */ +static void +get_subr (card8 **subr, long *len, cff_index *subr_idx, long id) +{ + card16 count; + + if (subr_idx == NULL) + CFF_ERROR("%s: Subroutine called but no subroutine found.", CS_TYPE2_DEBUG_STR); + + count = subr_idx->count; + + /* Adding bias number */ + if (count < 1240) { + id += 107; + } else if (count < 33900) { + id += 1131; + } else { + id += 32768; + } + + if (id > count) + CFF_ERROR("%s: Invalid Subr index: %ld (max=%u)", CS_TYPE2_DEBUG_STR, id, count); + + *len = (subr_idx->offset)[id + 1] - (subr_idx->offset)[id]; + *subr = subr_idx->data + (subr_idx->offset)[id] - 1; + + return; +} + +/* + * NOTE: + * The Type 2 interpretation of a number encoded in five-bytes (those with + * an initial byte value of 255) differs from how it is interpreted in the + * Type 1 format. + */ + +static void +do_charstring (card8 **dest, card8 *limit, + card8 **data, card8 *endptr, + cff_index *gsubr_idx, cff_index *subr_idx) +{ + card8 b0 = 0, *subr; + long len; + + if (cs2_nest > CS_SUBR_NEST_MAX) + CFF_ERROR("%s: Subroutine nested too deeply.", CS_TYPE2_DEBUG_STR); + + cs2_nest++; + + while (*data < endptr && status == CS_PARSE_OK) { + b0 = **data; + if (b0 == 255) { /* 16-bit.16-bit fixed signed number */ + get_fixed(data, endptr); + } else if (b0 == cs_return) { + status = CS_SUBR_RETURN; + } else if (b0 == cs_callgsubr) { + if (cs2_stack_top < 1) { + status = CS_STACK_CFF_ERROR; + } else { + cs2_stack_top--; + get_subr(&subr, &len, gsubr_idx, (long) cs2_arg_stack[cs2_stack_top]); + if (*dest + len > limit) + CFF_ERROR("%s: Possible buffer overflow.", CS_TYPE2_DEBUG_STR); + do_charstring(dest, limit, &subr, subr + len, + gsubr_idx, subr_idx); + *data += 1; + } + } else if (b0 == cs_callsubr) { + if (cs2_stack_top < 1) { + status = CS_STACK_CFF_ERROR; + } else { + cs2_stack_top--; + get_subr(&subr, &len, subr_idx, (long) cs2_arg_stack[cs2_stack_top]); + if (limit < *dest + len) + CFF_ERROR("%s: Possible buffer overflow.", CS_TYPE2_DEBUG_STR); + do_charstring(dest, limit, &subr, subr + len, + gsubr_idx, subr_idx); + *data += 1; + } + } else if (b0 == cs_escape) { + do_operator2(dest, limit, data, endptr); + } else if (b0 < 32 && b0 != 28) { /* 19, 20 need mask */ + do_operator1(dest, limit, data, endptr); + } else if ((b0 <= 22 && b0 >= 27) || b0 == 31) { /* reserved */ + status = CS_PARSE_CFF_ERROR; /* not an error ? */ + } else { /* integer */ + cs2_get_integer(data, endptr); + } + } + + if (status == CS_SUBR_RETURN) { + status = CS_PARSE_OK; + } else if (status == CS_CHAR_END && *data < endptr) { + WARN("%s: Garbage after endchar.", CS_TYPE2_DEBUG_STR); + } else if (status < CS_PARSE_OK) { /* error */ + CFF_ERROR("%s: Parsing charstring failed: (status=%d, stack=%d)", + CS_TYPE2_DEBUG_STR, status, cs2_stack_top); + } + + cs2_nest--; + + return; +} + +static void +cs_parse_init (void) +{ + status = CS_PARSE_OK; + cs2_nest = 0; + phase = 0; + num_stems = 0; + cs2_stack_top = 0; +} + +/* + * Not just copying... + */ +long +cs_copy_charstring (card8 *dst, long dstlen, + card8 *src, long srclen, + cff_index *gsubr, cff_index *subr, + double default_width, double nominal_width, cs_ginfo *ginfo) +{ + card8 *save = dst; + + cs_parse_init(); + + width = 0.0; + have_width = 0; + + /* expand call(g)subrs */ + do_charstring(&dst, dst + dstlen, &src, src + srclen, gsubr, subr); + + if (ginfo) { + ginfo->flags = 0; /* not used */ + if (have_width) { + ginfo->wx = nominal_width + width; + } else { + ginfo->wx = default_width; + } + } + + return (long)(dst - save); +} + +/* encodings */ + +/* + * Encoding and Charset + * + * Encoding and Charset arrays always begin with GID = 1. + */ +long cff_read_encoding (cff_font *cff) +{ + cff_encoding *encoding; + long offset, length; + card8 i; + + if (cff->topdict == NULL) { + CFF_ERROR("Top DICT data not found"); + } + + if (!cff_dict_known(cff->topdict, "Encoding")) { + cff->flag |= ENCODING_STANDARD; + cff->encoding = NULL; + return 0; + } + + offset = (long) cff_dict_get(cff->topdict, "Encoding", 0); + if (offset == 0) { /* predefined */ + cff->flag |= ENCODING_STANDARD; + cff->encoding = NULL; + return 0; + } else if (offset == 1) { + cff->flag |= ENCODING_EXPERT; + cff->encoding = NULL; + return 0; + } + + cff->offset= offset; + cff->encoding = encoding = xcalloc(1, sizeof(cff_encoding)); + encoding->format = get_card8(cff); + length = 1; + + switch (encoding->format & (~0x80)) { + case 0: + encoding->num_entries = get_card8(cff); + (encoding->data).codes = xcalloc(encoding->num_entries, sizeof(card8)); + for (i=0;i<(encoding->num_entries);i++) { + (encoding->data).codes[i] = get_card8(cff); + } + length += encoding->num_entries + 1; + break; + case 1: + { + cff_range1 *ranges; + encoding->num_entries = get_card8(cff); + encoding->data.range1 = ranges + = xcalloc(encoding->num_entries, sizeof(cff_range1)); + for (i=0;i<(encoding->num_entries);i++) { + ranges[i].first = get_card8(cff); + ranges[i].n_left = get_card8(cff); + } + length += (encoding->num_entries) * 2 + 1; + } + break; + default: + xfree(encoding); + CFF_ERROR("Unknown Encoding format"); + break; + } + + /* Supplementary data */ + if ((encoding->format) & 0x80) { + cff_map *map; + encoding->num_supps = get_card8(cff); + encoding->supp = map = xcalloc(encoding->num_supps, sizeof(cff_map)); + for (i=0;i<(encoding->num_supps);i++) { + map[i].code = get_card8(cff); + map[i].glyph = get_card16(cff); /* SID */ + } + length += (encoding->num_supps) * 3 + 1; + } else { + encoding->num_supps = 0; + encoding->supp = NULL; + } + + return length; +} + +long cff_pack_encoding (cff_font *cff, card8 *dest, long destlen) +{ + long len = 0; + cff_encoding *encoding; + card16 i; + + if (cff->flag & HAVE_STANDARD_ENCODING || cff->encoding == NULL) + return 0; + + if (destlen < 2) + CFF_ERROR("in cff_pack_encoding(): Buffer overflow"); + + encoding = cff->encoding; + + dest[len++] = encoding->format; + dest[len++] = encoding->num_entries; + switch (encoding->format & (~0x80)) { + case 0: + if (destlen < len + encoding->num_entries) + CFF_ERROR("in cff_pack_encoding(): Buffer overflow"); + for (i=0;i<(encoding->num_entries);i++) { + dest[len++] = (encoding->data).codes[i]; + } + break; + case 1: + { + if (destlen < len + (encoding->num_entries)*2) + CFF_ERROR("in cff_pack_encoding(): Buffer overflow"); + for (i=0;i<(encoding->num_entries);i++) { + dest[len++] = (encoding->data).range1[i].first & 0xff; + dest[len++] = (encoding->data).range1[i].n_left; + } + } + break; + default: + CFF_ERROR("Unknown Encoding format"); + break; + } + + if ((encoding->format) & 0x80) { + if (destlen < len + (encoding->num_supps)*3 + 1) + CFF_ERROR("in cff_pack_encoding(): Buffer overflow"); + dest[len++] = encoding->num_supps; + for (i=0;i<(encoding->num_supps);i++) { + dest[len++] = (encoding->supp)[i].code; + dest[len++] = ((encoding->supp)[i].glyph >> 8) & 0xff; + dest[len++] = (encoding->supp)[i].glyph & 0xff; + } + } + + return len; +} + +/* CID-Keyed font specific */ +long cff_read_fdselect (cff_font *cff) +{ + cff_fdselect *fdsel; + long offset, length; + card16 i; + + if (cff->topdict == NULL) + CFF_ERROR("Top DICT not available"); + + if (!(cff->flag & FONTTYPE_CIDFONT)) + return 0; + + offset = (long) cff_dict_get(cff->topdict, "FDSelect", 0); + cff->offset = offset; + cff->fdselect = fdsel = xcalloc(1, sizeof(cff_fdselect)); + fdsel->format = get_card8(cff); + + length = 1; + + switch (fdsel->format) { + case 0: + fdsel->num_entries = cff->num_glyphs; + (fdsel->data).fds = xcalloc(fdsel->num_entries, sizeof(card8)); + for (i=0;i<(fdsel->num_entries);i++) { + (fdsel->data).fds[i] = get_card8(cff); + } + length += fdsel->num_entries; + break; + case 3: + { + cff_range3 *ranges; + fdsel->num_entries = get_card16(cff); + fdsel->data.ranges = ranges = xcalloc(fdsel->num_entries, sizeof(cff_range3)); + for (i=0;i<(fdsel->num_entries);i++) { + ranges[i].first = get_card16(cff); + ranges[i].fd = get_card8(cff); + } + if (ranges[0].first != 0) + CFF_ERROR("Range not starting with 0."); + if (cff->num_glyphs != get_card16(cff)) + CFF_ERROR("Sentinel value mismatched with number of glyphs."); + length += (fdsel->num_entries) * 3 + 4; + } + break; + default: + xfree(fdsel); + CFF_ERROR("Unknown FDSelect format."); + break; + } + + return length; +} + + +long cff_pack_fdselect (cff_font *cff, card8 *dest, long destlen) +{ + cff_fdselect *fdsel; + long len = 0; + card16 i; + + if (cff->fdselect == NULL) + return 0; + + if (destlen < 1) + CFF_ERROR("in cff_pack_fdselect(): Buffur overflow"); + + fdsel = cff->fdselect; + + dest[len++] = fdsel->format; + switch (fdsel->format) { + case 0: + if (fdsel->num_entries != cff->num_glyphs) + CFF_ERROR("in cff_pack_fdselect(): Invalid data"); + if (destlen < len + fdsel->num_entries) + CFF_ERROR("in cff_pack_fdselect(): Buffer overflow"); + for (i=0;inum_entries;i++) { + dest[len++] = (fdsel->data).fds[i]; + } + break; + case 3: + { + if (destlen < len + 2) + CFF_ERROR("in cff_pack_fdselect(): Buffer overflow"); + len += 2; + for (i=0;i<(fdsel->num_entries);i++) { + if (destlen < len + 3) + CFF_ERROR("in cff_pack_fdselect(): Buffer overflow"); + dest[len++] = ((fdsel->data).ranges[i].first >> 8) & 0xff; + dest[len++] = (fdsel->data).ranges[i].first & 0xff; + dest[len++] = (fdsel->data).ranges[i].fd; + } + if (destlen < len + 2) + CFF_ERROR("in cff_pack_fdselect(): Buffer overflow"); + dest[len++] = (cff->num_glyphs >> 8) & 0xff; + dest[len++] = cff->num_glyphs & 0xff; + dest[1] = ((len/3 - 1) >> 8) & 0xff; + dest[2] = (len/3 - 1) & 0xff; + } + break; + default: + CFF_ERROR("Unknown FDSelect format."); + break; + } + + return len; +} + + + +/* + * Create an instance of embeddable font. + */ +static void +write_fontfile (cff_font *cffont, char *fullname) +{ + cff_index *topdict, *fdarray, *private; + unsigned char *dest; + long destlen = 0, i, size; + long offset, topdict_offset, fdarray_offset; + + /* DICT sizes (offset set to long int) */ + topdict = cff_new_index(1); + fdarray = cff_new_index(cffont->num_fds); + private = cff_new_index(cffont->num_fds); + + cff_dict_remove(cffont->topdict, "UniqueID"); + cff_dict_remove(cffont->topdict, "XUID"); + cff_dict_remove(cffont->topdict, "Private"); /* some bad font may have */ + cff_dict_remove(cffont->topdict, "Encoding"); /* some bad font may have */ + + topdict->offset[1] = cff_dict_pack(cffont->topdict, + (card8 *) work_buffer, + WORK_BUFFER_SIZE) + 1; + for (i = 0;i < cffont->num_fds; i++) { + size = 0; + if (cffont->private && cffont->private[i]) { + size = cff_dict_pack(cffont->private[i], + (card8 *) work_buffer, WORK_BUFFER_SIZE); + if (size < 1) { /* Private had contained only Subr */ + cff_dict_remove(cffont->fdarray[i], "Private"); + } + } + (private->offset)[i+1] = (private->offset)[i] + size; + (fdarray->offset)[i+1] = (fdarray->offset)[i] + + cff_dict_pack(cffont->fdarray[i], + (card8 *) work_buffer, WORK_BUFFER_SIZE); + } + + destlen = 4; /* header size */ + destlen += cff_set_name(cffont, fullname); + destlen += cff_index_size(topdict); + destlen += cff_index_size(cffont->string); + destlen += cff_index_size(cffont->gsubr); + destlen += (cffont->charsets->num_entries) * 2 + 1; /* charset format 0 */ + destlen += (cffont->fdselect->num_entries) * 3 + 5; /* fdselect format 3 */ + destlen += cff_index_size(cffont->cstrings); + destlen += cff_index_size(fdarray); + destlen += private->offset[private->count] - 1; /* Private is not INDEX */ + + dest = xcalloc(destlen, sizeof(card8)); + + offset = 0; + /* Header */ + offset += cff_put_header(cffont, dest + offset, destlen - offset); + /* Name */ + offset += cff_pack_index(cffont->name, dest + offset, destlen - offset); + /* Top DICT */ + topdict_offset = offset; + offset += cff_index_size(topdict); + /* Strings */ + offset += cff_pack_index(cffont->string, dest + offset, destlen - offset); + /* Global Subrs */ + offset += cff_pack_index(cffont->gsubr, dest + offset, destlen - offset); + + /* charset */ + cff_dict_set(cffont->topdict, "charset", 0, offset); + offset += cff_pack_charsets(cffont, dest + offset, destlen - offset); + + /* FDSelect */ + cff_dict_set(cffont->topdict, "FDSelect", 0, offset); + offset += cff_pack_fdselect(cffont, dest + offset, destlen - offset); + + /* CharStrings */ + cff_dict_set(cffont->topdict, "CharStrings", 0, offset); + offset += cff_pack_index(cffont->cstrings, + dest + offset, cff_index_size(cffont->cstrings)); + cff_release_index(cffont->cstrings); + cffont->cstrings = NULL; /* Charstrings cosumes huge memory */ + + /* FDArray and Private */ + cff_dict_set(cffont->topdict, "FDArray", 0, offset); + fdarray_offset = offset; + offset += cff_index_size(fdarray); + + fdarray->data = xcalloc(fdarray->offset[fdarray->count] - 1, sizeof(card8)); + for (i = 0; i < cffont->num_fds; i++) { + size = private->offset[i+1] - private->offset[i]; + if (cffont->private[i] && size > 0) { + cff_dict_pack(cffont->private[i], dest + offset, size); + cff_dict_set(cffont->fdarray[i], "Private", 0, size); + cff_dict_set(cffont->fdarray[i], "Private", 1, offset); + } + cff_dict_pack(cffont->fdarray[i], + fdarray->data + (fdarray->offset)[i] - 1, + fdarray->offset[fdarray->count] - 1); + offset += size; + } + + cff_pack_index(fdarray, dest + fdarray_offset, cff_index_size(fdarray)); + cff_release_index(fdarray); + cff_release_index(private); + + /* Finally Top DICT */ + topdict->data = xcalloc(topdict->offset[topdict->count] - 1, sizeof(card8)); + cff_dict_pack(cffont->topdict, + topdict->data, topdict->offset[topdict->count] - 1); + cff_pack_index(topdict, dest + topdict_offset, cff_index_size(topdict)); + cff_release_index(topdict); + + for (i = 0; i < offset; i++) + fb_putchar (dest[i]); + + /*fprintf(stdout," (%i/%i)",offset,cffont->stream_size);*/ + xfree(dest); + return ; +} + + +/* if the CFF data was converted from an old type1 font, then the .notdef + glyph may not be at id 0, so in that case |uglytype1fix| is nonzero */ + +void write_cff(cff_font *cffont, fd_entry *fd, int uglytype1fix) { + cff_index *charstrings, *cs_idx; + + long charstring_len, max_len; + long size, offset = 0; + + card8 *data; + card16 num_glyphs, cs_count, code, gid, last_cid; + + double nominal_width, default_width; + + char *fullname; + + glw_entry *glyph, *found; + struct avl_traverser t; + + + + + fullname = xcalloc(8+strlen(fd->fontname),1); + sprintf(fullname,"%s+%s",fd->subset_tag,fd->fontname); + + /* finish parsing the CFF */ + cff_read_private(cffont); + cff_read_subrs (cffont); + + /* + * Widths + */ + if (cffont->private[0] && + cff_dict_known(cffont->private[0], "defaultWidthX")) { + default_width = (double) cff_dict_get(cffont->private[0], "defaultWidthX", 0); + } else { + default_width = CFF_DEFAULTWIDTHX_DEFAULT; + } + if (cffont->private[0] && + cff_dict_known(cffont->private[0], "nominalWidthX")) { + nominal_width = (double) cff_dict_get(cffont->private[0], "nominalWidthX", 0); + } else { + nominal_width = CFF_NOMINALWIDTHX_DEFAULT; + } + + num_glyphs = 0; + last_cid = 0; + glyph = xtalloc(1,glw_entry); + + /* insert notdef */ + glyph->id = uglytype1fix; + if (avl_find(fd->gl_tree, glyph)==NULL) { + /*fprintf(stderr,"seeding .notdef at %i\n",uglytype1fix);*/ + avl_insert(fd->gl_tree, glyph); + glyph = xtalloc(1,glw_entry); + } + + + avl_t_init(&t, fd->gl_tree); + for (found = (glw_entry *) avl_t_first(&t, fd->gl_tree); + found != NULL; + found = (glw_entry *) avl_t_next(&t)) { + if (found->id > last_cid) + last_cid = found->id; + num_glyphs++; + } + + { + cff_fdselect *fdselect; + + fdselect = xcalloc(1, sizeof(cff_fdselect)); + fdselect->format = 3; + fdselect->num_entries = 1; + fdselect->data.ranges = xcalloc(1, sizeof(cff_range3)); + fdselect->data.ranges[0].first = 0; + fdselect->data.ranges[0].fd = 0; + cffont->fdselect = fdselect; + } + + { + cff_charsets *charset; + + charset = xcalloc(1, sizeof(cff_charsets)); + charset->format = 0; + charset->num_entries = num_glyphs-1; + charset->data.glyphs = xcalloc(num_glyphs, sizeof(s_SID)); + + gid = 0; + + avl_t_init(&t, fd->gl_tree); + for (found = (glw_entry *) avl_t_first(&t, fd->gl_tree); + found != NULL; + found = (glw_entry *) avl_t_next(&t)) { + if(found->id!=0) { + charset->data.glyphs[gid] = found->id; + gid++; + } + } + cffont->charsets = charset; + } + + cff_dict_add(cffont->topdict, "CIDCount", 1); + cff_dict_set(cffont->topdict, "CIDCount", 0, last_cid + 1); + + cffont->fdarray = xcalloc(1, sizeof(cff_dict *)); + cffont->fdarray[0] = cff_new_dict(); + cff_dict_add(cffont->fdarray[0], "FontName", 1); + cff_dict_set(cffont->fdarray[0], "FontName", 0, + (double) cff_add_string(cffont, fullname)); /* FIXME: Skip XXXXXX+ */ + cff_dict_add(cffont->fdarray[0], "Private", 2); + cff_dict_set(cffont->fdarray[0], "Private", 0, 0.0); + cff_dict_set(cffont->fdarray[0], "Private", 0, 0.0); + /* FDArray - index offset, not known yet */ + cff_dict_add(cffont->topdict, "FDArray", 1); + cff_dict_set(cffont->topdict, "FDArray", 0, 0.0); + /* FDSelect - offset, not known yet */ + cff_dict_add(cffont->topdict, "FDSelect", 1); + cff_dict_set(cffont->topdict, "FDSelect", 0, 0.0); + + cff_dict_remove(cffont->topdict, "UniqueID"); + cff_dict_remove(cffont->topdict, "XUID"); + cff_dict_remove(cffont->topdict, "Private"); + cff_dict_remove(cffont->topdict, "Encoding"); + + cffont->offset = cff_dict_get(cffont->topdict, "CharStrings", 0); + cs_idx = cff_get_index_header(cffont); + + offset = cffont->offset; + cs_count = cs_idx->count; + if (cs_count < 2) { + CFF_ERROR("No valid charstring data found."); + } + + /* build the new charstrings entry */ + charstrings = cff_new_index(cs_count+1); + max_len = 2 * CS_STR_LEN_MAX; + charstrings->data = xcalloc(max_len, sizeof(card8)); + charstring_len = 0; + + gid = 0; + data = xcalloc(CS_STR_LEN_MAX, sizeof(card8)); + + for (code=0; code < cs_count; code++) { + glyph->id = code; + if ((avl_find(fd->gl_tree,glyph) != NULL)) { + size = cs_idx->offset[code+1] - cs_idx->offset[code]; + + if (size > CS_STR_LEN_MAX) { + pdftex_fail("Charstring too long: gid=%u, %ld bytes", code, size); + } + if (charstring_len + CS_STR_LEN_MAX >= max_len) { + max_len = charstring_len + 2 * CS_STR_LEN_MAX; + charstrings->data = xrealloc(charstrings->data, max_len*sizeof(card8)); + } + (charstrings->offset)[gid] = charstring_len + 1; + cffont->offset= offset + (cs_idx->offset)[code] - 1; + memcpy(data,&cffont->stream[cffont->offset],size); + charstring_len += cs_copy_charstring(charstrings->data + charstring_len, + max_len - charstring_len, + data, size, + cffont->gsubr, (cffont->subrs)[0], + default_width, nominal_width, NULL); + gid++; + } + } + + /* this happens if the internal metrics do not agree with the actual disk font */ + if (gid < num_glyphs) { + WARN("embedded subset is smaller than expected: %d instead of %d glyphs.", gid, num_glyphs); + num_glyphs = gid; + } + + xfree(data); + cff_release_index(cs_idx); + + (charstrings->offset)[num_glyphs] = charstring_len + 1; + charstrings->count = num_glyphs; + cffont->num_glyphs = num_glyphs; + cffont->cstrings = charstrings; + + /* + * We don't use subroutines at all. + */ + if (cffont->gsubr) + cff_release_index(cffont->gsubr); + cffont->gsubr = cff_new_index(0); + + if (cffont->subrs && cffont->subrs[0]) + cff_release_index(cffont->subrs[0]); + cffont->subrs[0] = NULL; + + if (cffont->private && (cffont->private)[0]) { + cff_dict_remove((cffont->private)[0], "Subrs"); /* no Subrs */ + } + + cff_add_string(cffont, (char *)"Adobe"); + cff_add_string(cffont, (char *)"Identity"); + + cff_dict_update(cffont->topdict, cffont); + cff_dict_update(cffont->private[0], cffont); + cff_update_string(cffont); + + /* CFF code need to be rewrote... */ + cff_dict_add(cffont->topdict, "ROS", 3); + cff_dict_set(cffont->topdict, "ROS", 0, + (double) cff_get_sid(cffont, (char *)"Adobe")); + cff_dict_set(cffont->topdict, "ROS", 1, + (double) cff_get_sid(cffont, (char *)"Identity")); + cff_dict_set(cffont->topdict, "ROS", 2, 0.0); + + write_fontfile(cffont,fullname); + xfree(fullname); + cff_close (cffont); + +} + +#define ERROR(a) { perror(a); return 0; } + +/* Input : SID or CID (16-bit unsigned int) + * Output: glyph index + */ +card16 +cff_charsets_lookup (cff_font *cff, card16 cid) +{ + card16 gid = 0; + cff_charsets *charset; + card16 i; + + if (cff->flag & (CHARSETS_ISOADOBE|CHARSETS_EXPERT|CHARSETS_EXPSUB)) { + ERROR("Predefined CFF charsets not supported yet"); + } else if (cff->charsets == NULL) { + ERROR("Charsets data not available"); + } + + if (cid == 0) { + return 0; /* GID 0 (.notdef) */ + } + + charset = cff->charsets; + + gid = 0; + switch (charset->format) { + case 0: + for (i = 0; i num_entries; i++) { + if (cid == charset->data.glyphs[i]) { + gid = i + 1; + return gid; + } + } + break; + case 1: + for (i = 0; i < charset->num_entries; i++) { + if (cid >= charset->data.range1[i].first && + cid <= charset->data.range1[i].first + charset->data.range1[i].n_left) { + gid += cid - charset->data.range1[i].first + 1; + return gid; + } + gid += charset->data.range1[i].n_left + 1; + } + break; + case 2: + for (i = 0; i < charset->num_entries; i++) { + if (cid >= charset->data.range2[i].first && + cid <= charset->data.range2[i].first + charset->data.range2[i].n_left) { + gid += cid - charset->data.range2[i].first + 1; + return gid; + } + gid += charset->data.range2[i].n_left + 1; + } + break; + default: + ERROR("Unknown Charset format"); + } + + return 0; /* not found */ +} + + +#define is_cidfont(a) ((a)->flag & FONTTYPE_CIDFONT) +#define CID_MAX 65535 + +void write_cid_cff(cff_font *cffont, fd_entry *fd, int uglytype1fix) { + cff_index *charstrings, *cs_idx; + + long charstring_len, max_len; + long size, offset = 0; + + card8 *data; + card16 num_glyphs, cs_count, gid, last_cid; + + + int fdsel, prev_fd, cid_count, cid; + char *fullname; + + glw_entry *glyph; + + unsigned char *CIDToGIDMap = NULL; + + cff_fdselect *fdselect = NULL; + cff_charsets *charset = NULL; + + + if (!is_cidfont(cffont)) { + perror("Not a CIDfont."); + return; + } + + fullname = xcalloc(8+strlen(fd->fontname),1); + sprintf(fullname,"%s+%s",fd->subset_tag,fd->fontname); + + /* finish parsing the CFF */ + + if (cff_dict_known(cffont->topdict, "CIDCount")) { + cid_count = (card16) cff_dict_get(cffont->topdict, "CIDCount", 0); + } else { + cid_count = CFF_CIDCOUNT_DEFAULT; + } + cff_read_charsets(cffont); + CIDToGIDMap = xmalloc((2*cid_count) * sizeof(unsigned char)); + memset(CIDToGIDMap, 0, 2*cid_count); + + + glyph = xtalloc(1,glw_entry); + /* insert notdef */ + glyph->id = uglytype1fix; + if (avl_find(fd->gl_tree, glyph)==NULL) { + avl_insert(fd->gl_tree, glyph); + glyph = xtalloc(1,glw_entry); + } + + cid = 0; last_cid = 0; num_glyphs = 0; + for (cid = 0; cid <= CID_MAX; cid++) { + glyph->id = cid; + if (avl_find(fd->gl_tree,glyph) != NULL) { + gid = cff_charsets_lookup(cffont, cid); + CIDToGIDMap[2*cid] = (gid >> 8) & 0xff; + CIDToGIDMap[2*cid+1] = gid & 0xff; + last_cid = cid; + num_glyphs++; + } + } + + cff_read_fdselect(cffont); + cff_read_fdarray(cffont); + cff_read_private(cffont); + + cff_read_subrs (cffont); + + + cffont->offset = cff_dict_get(cffont->topdict, "CharStrings", 0); + cs_idx = cff_get_index_header(cffont); + + offset = cffont->offset; + cs_count = cs_idx->count; + if (cs_count < 2) { + CFF_ERROR("No valid charstring data found."); + } + + charset = xcalloc(1, sizeof(cff_charsets)); + charset->format = 0; + charset->num_entries = 0; + charset->data.glyphs = xcalloc(num_glyphs, sizeof(s_SID)); + + fdselect = xcalloc(1, sizeof(cff_fdselect)); + fdselect->format = 3; + fdselect->num_entries = 0; + fdselect->data.ranges = xcalloc(num_glyphs, sizeof(cff_range3)); + + charstrings = cff_new_index(cs_count+1); + max_len = 2 * CS_STR_LEN_MAX; + charstrings->data = xcalloc(max_len, sizeof(card8)); + charstring_len = 0; + + prev_fd = -1; gid = 0; + data = xcalloc(CS_STR_LEN_MAX, sizeof(card8)); + for (cid=0; cid <= last_cid; cid++) { + unsigned short gid_org; + + glyph->id = cid; + if (avl_find(fd->gl_tree,glyph) == NULL) + continue; + + gid_org = (CIDToGIDMap[2*cid] << 8)|(CIDToGIDMap[2*cid+1]); + size = cs_idx->offset[gid_org+1] - cs_idx->offset[gid_org]; + if (size > CS_STR_LEN_MAX) { + pdftex_fail("Charstring too long: gid=%u, %ld bytes", cid, size); + } + if (charstring_len + CS_STR_LEN_MAX >= max_len) { + max_len = charstring_len + 2 * CS_STR_LEN_MAX; + charstrings->data = xrealloc(charstrings->data, max_len*sizeof(card8)); + } + (charstrings->offset)[gid] = charstring_len + 1; + cffont->offset= offset + (cs_idx->offset)[gid_org] - 1; + memcpy(data,&cffont->stream[cffont->offset],size); + fdsel = cff_fdselect_lookup(cffont, gid_org); + charstring_len += cs_copy_charstring(charstrings->data + charstring_len, + max_len - charstring_len, + data, size, + cffont->gsubr, (cffont->subrs)[fdsel], + 0, 0, NULL); + + if (cid>0 && gid_org > 0) { + charset->data.glyphs[charset->num_entries] = cid; + charset->num_entries += 1; + } + if (fdsel != prev_fd) { + fdselect->data.ranges[fdselect->num_entries].first = gid; + fdselect->data.ranges[fdselect->num_entries].fd = fdsel; + fdselect->num_entries += 1; + prev_fd = fdsel; + } + gid++; + } + + if (gid != num_glyphs) + CFF_ERROR("Unexpected error: %i != %i", gid, num_glyphs); + xfree(data); + cff_release_index(cs_idx); + + xfree(CIDToGIDMap); + + (charstrings->offset)[num_glyphs] = charstring_len + 1; + charstrings->count = num_glyphs; + cffont->num_glyphs = num_glyphs; + cffont->cstrings = charstrings; + + cff_release_charsets(cffont->charsets); + cffont->charsets = charset; + cff_release_fdselect(cffont->fdselect); + cffont->fdselect = fdselect; + + /* + * We don't use subroutines at all. + */ + if (cffont->gsubr) + cff_release_index(cffont->gsubr); + cffont->gsubr = cff_new_index(0); + + for (fdsel = 0; fdsel < cffont->num_fds; fdsel++) { + if (cffont->subrs && cffont->subrs[fdsel]) { + cff_release_index(cffont->subrs[fdsel]); + cffont->subrs[fdsel] = NULL; + } + if (cffont->private && (cffont->private)[fdsel]) { + cff_dict_remove((cffont->private)[fdsel], "Subrs"); /* no Subrs */ + } + } + + write_fontfile(cffont,fullname); + xfree(fullname); + cff_close (cffont); + +} + + +/* here is a sneaky trick: fontforge knows how to convert Type1 to CFF, so + * I have defined a utility function in luafflib.c that does exactly that. + * If it works out ok, I will clean up this code. + */ + +extern int ff_createcff (char *, unsigned char **, integer *); + +void writetype1w (fd_entry *fd) { + cff_font *cff; + int i; + FILE *fp; + ff_entry *ff; + unsigned char *tfm_buffer = NULL; + integer tfm_size = 0; + int notdefpos = 0; + + ff = check_ff_exist(fd->fm->ff_name, 0); + + fp = fopen (ff->ff_path, "rb"); + cur_file_name = ff->ff_path; + + if (!fp) { + fprintf(stderr,"Type1: Could not open Type1 font: %s", cur_file_name); + uexit(1); + } + fclose(fp); + + if (tracefilenames) { + if (is_subsetted(fd->fm)) + tex_printf ("<%s", cur_file_name); + else + tex_printf ("<<%s", cur_file_name); + } + + notdefpos = ff_createcff(ff->ff_path,&tfm_buffer,&tfm_size); + + if (tfm_size>0) { + cff = read_cff(tfm_buffer,tfm_size,0); + if (cff != NULL) { + write_cff(cff,fd,notdefpos); + } else { + for (i = 0; i < tfm_size ; i++) + fb_putchar (tfm_buffer[i]); + } + fd->ff_found = 1; + } else { + fprintf(stderr,"Type1: Could not understand Type1 font: %s", cur_file_name); + uexit(1); + } + if (tracefilenames) { + if (is_subsetted (fd->fm)) + tex_printf (">"); + else + tex_printf (">>"); + } + cur_file_name = NULL; +} + + diff --git a/Build/source/texk/web2c/luatexdir/font/writecff.h b/Build/source/texk/web2c/luatexdir/font/writecff.h new file mode 100644 index 00000000000..8cb93024f7a --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/font/writecff.h @@ -0,0 +1,349 @@ +/* $Header: /home/cvsroot/dvipdfmx/src/cff_limits.h,v 1.3 2002/10/30 02:27:05 chofchof Exp $ + + This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. + + Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata, + the dvipdfmx project team + + 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. +*/ + +#ifndef _CFF_LIMITS_H_ +#define _CFF_LIMITS_H_ + +#include + +#define CFF_INT_MAX 0x7fffffff +#define CFF_INT_MIN (-0x7fffffff - 1) + +#if (LONG_MAX < CFF_INT_MAX || LONG_MIN > CFF_INT_MIN) +#error "CFF support won't work on this system." +#endif + +#define CFF_SID_MAX 64999 +#define CFF_STDSTR_MAX 391 + +/* Type 2 Charstring */ +#define CS_NUM_SUBR_MAX 65536 +#define CS_STR_LEN_MAX 65536 +#define CS_STEM_ZONE_MAX 96 +#define CS_ARG_STACK_MAX 48 +#define CS_TRANS_ARRAY_MAX 32 +#define CS_SUBR_NEST_MAX 10 + +#endif /* _CFF_LIMITS_H_ */ + +#ifndef _CFF_TYPES_H_ +#define _CFF_TYPES_H_ + +/* CFF Data Types */ + +#define CFF_TYPE_UNKNOWN 0 +#define CFF_TYPE_INTEGER (1 << 0) +#define CFF_TYPE_REAL (1 << 1) +#define CFF_TYPE_NUMBER (CFF_TYPE_INTEGER|CFF_TYPE_REAL) +#define CFF_TYPE_BOOLEAN (1 << 2) +#define CFF_TYPE_SID (1 << 3) +#define CFF_TYPE_ARRAY (1 << 4) +#define CFF_TYPE_DELTA (1 << 5) + +/* SID SID number */ +#define CFF_TYPE_ROS (1 << 6) +/* offset(0) */ +#define CFF_TYPE_OFFSET (1 << 7) +/* size offset(0) */ +#define CFF_TYPE_SZOFF (1 << 8) + +typedef unsigned char card8; /* 1-byte unsigned number */ +typedef unsigned short card16; /* 2-byte unsigned number */ +typedef unsigned char c_offsize; /* 1-byte unsigned number specifies the size + of an Offset field or fields, range 1-4 */ +typedef unsigned long l_offset; /* 1, 2, 3, or 4-byte offset */ +typedef unsigned short s_SID; /* 2-byte string identifier */ + +typedef unsigned long l_size; + +typedef struct { + card16 count; /* number of objects stored in INDEX */ + c_offsize offsize; /* Offset array element size, 1-4 */ + l_offset *offset; /* Offset array, count + 1 offsets */ + card8 *data; /* Object data */ +} cff_index; + + +/* Dictionary */ +typedef struct { + int id; /* encoded data value (as card8 or card16) */ + char *key; /* opname */ + int count; /* number of values */ + double *values; /* values */ +} cff_dict_entry; + +typedef struct { + int max; + int count; + cff_dict_entry *entries; +} cff_dict; + +/* Encoding, Charset and FDSelect */ +typedef struct +{ + s_SID first; /* SID or CID, or card8 for Encoding */ + card8 n_left; /* no. of remaining gids/codes in this range */ +} cff_range1; + +typedef struct +{ + s_SID first; /* SID or CID (card16) */ + card16 n_left; /* card16-version of range1 */ +} cff_range2; + +typedef struct +{ + card8 code; + s_SID glyph; +} cff_map; + +typedef struct +{ + card8 format; /* if (format & 0x80) then have supplement */ + card8 num_entries; /* number of entries */ + union { + card8 *codes; /* format 0 */ + cff_range1 *range1; /* format 1 */ + } data; + card8 num_supps; /* number of supplementary data */ + cff_map *supp; /* supplement */ +} cff_encoding; + +typedef struct +{ + card8 format; + card16 num_entries; + union { + s_SID *glyphs; /* format 0 */ + cff_range1 *range1; /* format 1 */ + cff_range2 *range2; /* format 2 */ + } data; +} cff_charsets; + +/* CID-Keyed font specific */ +typedef struct +{ + card16 first; + card8 fd; +} cff_range3; + +typedef struct +{ + card8 format; + card16 num_entries; /* number of glyphs/ranges */ + union { + card8 *fds; /* format 0 */ + cff_range3 *ranges; /* format 3 */ + } data; + /* card16 sentinel; */ /* format 3 only, must be equals to num_glyphs */ +} cff_fdselect; + +#endif /* _CFF_TYPES_H_ */ + +#ifndef _CFF_STDSTR_H_ +#define _CFF_STDSTR_H_ + +#define CFF_STDSTR_MAX 391 + +extern const char *const cff_stdstr[]; +#endif /* _CFF_STDSTR_H_ */ + +#ifndef _CFF_H_ +#define _CFF_H_ + +/*#include "mfileio.h"*/ + +/* Flag */ +#define FONTTYPE_CIDFONT (1 << 0) +#define FONTTYPE_FONT (1 << 1) +#define FONTTYPE_MMASTER (1 << 2) + +#define ENCODING_STANDARD (1 << 3) +#define ENCODING_EXPERT (1 << 4) + +#define CHARSETS_ISOADOBE (1 << 5) +#define CHARSETS_EXPERT (1 << 6) +#define CHARSETS_EXPSUB (1 << 7) + +#define HAVE_STANDARD_ENCODING (ENCODING_STANDARD|ENCODING_EXPERT) +#define HAVE_STANDARD_CHARSETS \ + (CHARSETS_ISOADOBE|CHARSETS_EXPERT|CHARSETS_EXPSUB) + +#define CFF_STRING_NOTDEF 65535 + +typedef struct +{ + char *fontname; /* FontName */ + + /* - CFF structure - */ + + card8 header_major; /* major version */ + card8 header_minor; /* minor version */ + card8 header_hdr_size; /* Header size (bytes) */ + c_offsize header_offsize; /* Absolute offset (0) size */ + + cff_index *name; /* Name INDEX */ + cff_dict *topdict; /* Top DICT (single) */ + cff_index *string; /* String INDEX */ + cff_index *gsubr; /* Global Subr INDEX */ + cff_encoding *encoding; /* Encodings */ + cff_charsets *charsets; /* Charsets */ + cff_fdselect *fdselect; /* FDSelect, CIDFont only */ + cff_index *cstrings; /* CharStrings */ + cff_dict **fdarray; /* CIDFont only */ + cff_dict **private; /* per-Font DICT */ + cff_index **subrs; /* Local Subr INDEX, per-Private DICT */ + + /* -- extra data -- */ + l_offset gsubr_offset; + card16 num_glyphs; /* number of glyphs (CharString INDEX count) */ + card8 num_fds; /* number of Font DICT */ + + /* Updated String INDEX. + * Please fix this. We should separate input and output. + */ + cff_index *_string; + + unsigned char *stream; + l_offset offset; + l_offset stream_size; + + int index; /* CFF fontset index */ + int flag; /* Flag: see above */ +} cff_font; + +extern cff_font *cff_open(unsigned char *stream, long stream_size, int n); +extern void cff_close (cff_font *cff); + +#define cff_seek_set(c, p) seek_absolute (((c)->stream), ((c)->offset) + (p)); + +/* CFF Header */ +extern long cff_put_header (cff_font *cff, card8 *dest, long destlen); + +/* CFF INDEX */ +extern cff_index *cff_get_index (cff_font *cff); +extern cff_index *cff_get_index_header (cff_font *cff); +extern void cff_release_index (cff_index *idx); +extern cff_index *cff_new_index (card16 count); +extern long cff_index_size (cff_index *idx); +extern long cff_pack_index (cff_index *idx, card8 *dest, long destlen); + +/* Name INDEX */ +extern char *cff_get_name (cff_font *cff); +extern long cff_set_name (cff_font *cff, char *name); + +/* Global and Local Subrs INDEX */ +extern long cff_read_subrs (cff_font *cff); + +/* Encoding */ +extern long cff_read_encoding (cff_font *cff); +extern long cff_pack_encoding (cff_font *cff, card8 *dest, long destlen); +extern card16 cff_encoding_lookup (cff_font *cff, card8 code); +extern void cff_release_encoding (cff_encoding *encoding); + +/* Charsets */ +extern long cff_read_charsets (cff_font *cff); +extern long cff_pack_charsets (cff_font *cff, card8 *dest, long destlen); + +/* Returns GID of PS name "glyph" */ +extern card16 cff_glyph_lookup (cff_font *cff, const char *glyph); +/* Returns GID of glyph with SID/CID "cid" */ +extern card16 cff_charsets_lookup (cff_font *cff, card16 cid); +extern void cff_release_charsets (cff_charsets *charset); +/* Returns SID or CID */ +extern card16 cff_charsets_lookup_inverse (cff_font *cff, card16 gid); + +/* FDSelect */ +extern long cff_read_fdselect (cff_font *cff); +extern long cff_pack_fdselect (cff_font *cff, card8 *dest, long destlen); +extern card8 cff_fdselect_lookup (cff_font *cff, card16 gid); +extern void cff_release_fdselect (cff_fdselect *fdselect); + +/* Font DICT(s) */ +extern long cff_read_fdarray (cff_font *cff); + +/* Private DICT(s) */ +extern long cff_read_private (cff_font *cff); + +/* String */ +extern int cff_match_string (cff_font *cff, const char *str, s_SID sid); +extern char *cff_get_string (cff_font *cff, s_SID id); +extern long cff_get_sid (cff_font *cff, char *str); +extern s_SID cff_add_string (cff_font *cff, char *str); +extern void cff_update_string (cff_font *cff); + +#define cff_is_stdstr(s) (cff_get_sid(NULL, (s)) >= 0) + +#endif /* _CFF_H_ */ + +#ifndef _CFF_DICT_H_ +#define _CFF_DICT_H_ + +#define CFF_CIDCOUNT_DEFAULT 8720 +#define CFF_NOMINALWIDTHX_DEFAULT 0.0 +#define CFF_DEFAULTWIDTHX_DEFAULT 0.0 + +extern cff_dict *cff_new_dict (void); +extern void cff_release_dict (cff_dict *dict); + +extern void cff_dict_set (cff_dict *dict, const char *key, int idx, double value); +extern double cff_dict_get (cff_dict *dict, const char *key, int idx); +extern void cff_dict_add (cff_dict *dict, const char *key, int count); +extern void cff_dict_remove (cff_dict *dict, const char *key); +extern int cff_dict_known (cff_dict *dict, const char *key); + +/* decode/encode DICT */ +extern cff_dict *cff_dict_unpack (card8 *data, card8 *endptr); +extern long cff_dict_pack (cff_dict *dict, card8 *dest, long destlen); + +extern void cff_dict_update (cff_dict *dict, cff_font *cff); + +#endif /* _CFF_DICT_H_ */ + +#ifndef _CS_TYPE2_H_ +#define _CS_TYPE2_H_ + +typedef struct { + int flags; /* unused in Type 2 charstring */ + double wx, wy; + struct { + double llx, lly, urx, ury; + } bbox; + struct { + double asb, adx, ady; + card8 bchar, achar; + } seac; /* unused in Type 2 charstring */ +} cs_ginfo; + +extern long cs_copy_charstring (card8 *dest, long destlen, + card8 *src, long srclen, + cff_index *gsubr, cff_index *subr, + double default_width, double nominal_width, cs_ginfo *ginfo); +#endif /* _CS_TYPE2_H_ */ + +#define cff_is_cidfont(a) (a->flag & FONTTYPE_CIDFONT) +#define cff_understandable(a) (a->header_major==1) + +extern cff_font *read_cff(unsigned char *buf,long buflength, int subf); + +extern void write_cff(cff_font *cff, fd_entry *fd, int hack); +extern void write_cid_cff(cff_font *cffont, fd_entry *fd, int uglytype1fix) ; diff --git a/Build/source/texk/web2c/luatexdir/font/writeenc.c b/Build/source/texk/web2c/luatexdir/font/writeenc.c new file mode 100644 index 00000000000..feaf1407d1e --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/font/writeenc.c @@ -0,0 +1,183 @@ +/* +Copyright (c) 1996-2005 Han The Thanh, + +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: writeenc.c 1013 2008-02-14 00:09:02Z oneiros $ +*/ + +#include "ptexlib.h" + +/**********************************************************************/ +/* All encoding entries go into AVL tree for fast search by name. */ + +struct avl_table *fe_tree = NULL; + +/* AVL sort fe_entry into fe_tree by name */ + +static int comp_fe_entry(const void *pa, const void *pb, void *p) +{ + return strcmp(((const fe_entry *) pa)->name, ((const fe_entry *) pb)->name); +} + +fe_entry *new_fe_entry() +{ + fe_entry *fe; + fe = xtalloc(1, fe_entry); + fe->name = NULL; + fe->fe_objnum = 0; + fe->glyph_names = NULL; /* encoding file not yet read in */ + fe->tx_tree = NULL; + return fe; +} + +fe_entry *lookup_fe_entry(char *s) +{ + fe_entry fe; + assert(s != NULL); + fe.name = s; + if (fe_tree == NULL) { + fe_tree = avl_create(comp_fe_entry, NULL, &avl_xallocator); + assert(fe_tree != NULL); + } + return (fe_entry *) avl_find(fe_tree, &fe); +} + +void register_fe_entry(fe_entry * fe) +{ + void **aa; + if (fe_tree == NULL) { + fe_tree = avl_create(comp_fe_entry, NULL, &avl_xallocator); + assert(fe_tree != NULL); + } + assert(fe != NULL); + assert(fe->name != NULL); + assert(lookup_fe_entry(fe->name) == NULL); /* encoding not yet registered */ + aa = avl_probe(fe_tree, fe); + assert(aa != NULL); +} + +fe_entry *get_fe_entry(char *s) +{ + fe_entry *fe; + char **gl; + if ((fe = lookup_fe_entry(s)) == NULL && (gl = load_enc_file(s)) != NULL) { + fe = new_fe_entry(); + fe->name = s; + fe->glyph_names = gl; + register_fe_entry(fe); + } + return fe; +} + +/**********************************************************************/ + +void epdf_write_enc(char **glyph_names, integer fe_objnum) +{ + int i, i_old; + assert(glyph_names != NULL); + assert(fe_objnum != 0); + pdf_begin_dict(fe_objnum, 1); + pdf_puts("/Type /Encoding\n"); + pdf_printf("/Differences ["); + for (i = 0, i_old = -2; i < 256; i++) + if (glyph_names[i] != notdef) { + if (i == i_old + 1) /* no gap */ + pdf_printf("/%s", glyph_names[i]); + else { + if (i_old == -2) + pdf_printf("%i/%s", i, glyph_names[i]); + else + pdf_printf(" %i/%s", i, glyph_names[i]); + } + i_old = i; + } + pdf_puts("]\n"); + pdf_end_dict(); +} + +void write_enc(char **glyph_names, struct avl_table *tx_tree, integer fe_objnum) +{ + int i_old, *p; + struct avl_traverser t; + assert(glyph_names != NULL); + assert(tx_tree != NULL); + assert(fe_objnum != 0); + pdf_begin_dict(fe_objnum, 1); + pdf_puts("/Type /Encoding\n"); + pdf_printf("/Differences ["); + avl_t_init(&t, tx_tree); + for (i_old = -2, p = (int *) avl_t_first(&t, tx_tree); p != NULL; + p = (int *) avl_t_next(&t)) { + if (*p == i_old + 1) /* no gap */ + pdf_printf("/%s", glyph_names[*p]); + else { + if (i_old == -2) + pdf_printf("%i/%s", *p, glyph_names[*p]); + else + pdf_printf(" %i/%s", *p, glyph_names[*p]); + } + i_old = *p; + } + pdf_puts("]\n"); + pdf_end_dict(); +} + +void write_fontencoding(fe_entry * fe) +{ + assert(fe != NULL); + write_enc(fe->glyph_names, fe->tx_tree, fe->fe_objnum); +} + +void write_fontencodings() +{ + fe_entry *fe; + struct avl_traverser t; + if (fe_tree == NULL) + return; + avl_t_init(&t, fe_tree); + for (fe = (fe_entry *) avl_t_first(&t, fe_tree); fe != NULL; + fe = (fe_entry *) avl_t_next(&t)) + if (fe->fe_objnum != 0) + write_fontencoding(fe); +} + +/**********************************************************************/ +/* cleaning up... */ + +static void destroy_fe_entry(void *pa, void *pb) +{ + fe_entry *p; + int i; + p = (fe_entry *) pa; + xfree(p->name); + if (p->glyph_names != NULL) + for (i = 0; i < 256; i++) + if (p->glyph_names[i] != notdef) + xfree(p->glyph_names[i]); + xfree(p->glyph_names); + xfree(p); +} + +void enc_free() +{ + if (fe_tree != NULL) + avl_destroy(fe_tree, destroy_fe_entry); + fe_tree = NULL; +} + +/**********************************************************************/ diff --git a/Build/source/texk/web2c/luatexdir/font/writefont.c b/Build/source/texk/web2c/luatexdir/font/writefont.c new file mode 100644 index 00000000000..05257746889 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/font/writefont.c @@ -0,0 +1,885 @@ +/* +Copyright (c) 1996-2006 Han The Thanh, + +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: writefont.c 1112 2008-03-20 14:46:32Z taco $ +*/ + +#include "ptexlib.h" + +extern void writetype0 (fd_entry * fd) ; +extern void writetype2 (fd_entry * fd) ; +extern unsigned long cidtogid_obj; + +#ifdef DO_TYPE1C +extern void writet1c(fd_entry * fd); /* in writecff.c */ +#endif + +extern void writet1w (fd_entry * fd); /* in writecff.c */ +extern void writetype1w (fd_entry * fd); +extern integer write_cid_tounicode(fo_entry * fo, internalfontnumber f); /* in tounicode.c */ + + +void write_cid_fontdictionary(fo_entry * fo, internalfontnumber f); +void create_cid_fontdictionary(fm_entry * fm, integer font_objnum, internalfontnumber f); + +/**********************************************************************/ + +struct avl_table *fo_tree = NULL; /* tree of font dictionaries */ +struct avl_table *fd_tree = NULL; /* tree of font descriptor objects */ + +static int comp_fo_entry(const void *pa, const void *pb, void *p) +{ + return strcmp(((const fo_entry *) pa)->fm->tfm_name, + ((const fo_entry *) pb)->fm->tfm_name); +} + +static int comp_fd_entry(const void *pa, const void *pb, void *p) +{ + int i; + const fd_entry *p1 = (const fd_entry *) pa, *p2 = (const fd_entry *) pb; + assert(p1->fm != NULL && is_fontfile(p1->fm) && + p2->fm != NULL && is_fontfile(p2->fm)); + if ((i = strcmp(p1->fm->ff_name, p2->fm->ff_name)) != 0) + return i; + cmp_return(p1->fm->slant, p2->fm->slant); + cmp_return(p1->fm->extend, p2->fm->extend); + return 0; +} + +/**********************************************************************/ +/* initialize data structure for /Type /Font */ + +fo_entry *new_fo_entry(void) +{ + fo_entry *fo; + fo = xtalloc(1, fo_entry); + fo->fo_objnum = 0; + fo->tex_font = 0; + fo->fm = NULL; + fo->fd = NULL; + fo->fe = NULL; + fo->cw_objnum = 0; + fo->first_char = 1; + fo->last_char = 0; + fo->tx_tree = NULL; + fo->tounicode_objnum = 0; + return fo; +} + +/* initialize data structure for /Type /FontDescriptor */ + +fd_entry *new_fd_entry(void) +{ + fd_entry *fd; + int i; + fd = xtalloc(1, fd_entry); + fd->fd_objnum = 0; + fd->fontname = NULL; + fd->subset_tag = NULL; + fd->ff_found = false; + fd->ff_objnum = 0; + fd->fn_objnum = 0; + fd->all_glyphs = false; + fd->write_ttf_glyph_names = false; + for (i = 0; i < INT_KEYS_NUM; i++) { + fd->font_dim[i].val = 0; + fd->font_dim[i].set = false; + } + fd->fe = NULL; + fd->builtin_glyph_names = NULL; + fd->fm = NULL; + fd->tx_tree = NULL; + fd->gl_tree = NULL; + return fd; +} + +/**********************************************************************/ +/* + * Only fallback values of font metrics are taken from the TFM info + * of f by preset_fontmetrics(). During reading of the font file, + * these values are replaced by metrics from the font, if available. + */ + +static void preset_fontmetrics(fd_entry * fd, internalfontnumber f) +{ + int i; + fd->font_dim[ITALIC_ANGLE_CODE].val = + divide_scaled(-atan(get_slant(f) / 65536.0) * (180 / M_PI), + pdf_font_size(f), 3); + fd->font_dim[ASCENT_CODE].val = + divide_scaled(char_height(f, 'h'), pdf_font_size(f), 3); + fd->font_dim[CAPHEIGHT_CODE].val = + divide_scaled(char_height(f, 'H'), pdf_font_size(f), 3); + i = -divide_scaled(char_depth(f, 'y'), pdf_font_size(f), 3); + fd->font_dim[DESCENT_CODE].val = i < 0 ? i : 0; + fd->font_dim[STEMV_CODE].val = + divide_scaled(char_width(f, '.') / 3, pdf_font_size(f), 3); + fd->font_dim[XHEIGHT_CODE].val = + divide_scaled(get_x_height(f), pdf_font_size(f), 3); + fd->font_dim[FONTBBOX1_CODE].val = 0; + fd->font_dim[FONTBBOX2_CODE].val = fd->font_dim[DESCENT_CODE].val; + fd->font_dim[FONTBBOX3_CODE].val = + divide_scaled(get_quad(f), pdf_font_size(f), 3); + fd->font_dim[FONTBBOX4_CODE].val = + fd->font_dim[CAPHEIGHT_CODE].val > fd->font_dim[ASCENT_CODE].val ? + fd->font_dim[CAPHEIGHT_CODE].val : fd->font_dim[ASCENT_CODE].val; + for (i = 0; i < INT_KEYS_NUM; i++) + fd->font_dim[i].set = true; +} + +static void write_fontmetrics(fd_entry * fd) +{ + int i; + if (fd->font_dim[FONTBBOX1_CODE].set && fd->font_dim[FONTBBOX2_CODE].set + && fd->font_dim[FONTBBOX3_CODE].set && fd->font_dim[FONTBBOX4_CODE].set) + pdf_printf("/%s [%i %i %i %i]\n", font_key[FONTBBOX1_CODE].pdfname, + (int) fd->font_dim[FONTBBOX1_CODE].val, + (int) fd->font_dim[FONTBBOX2_CODE].val, + (int) fd->font_dim[FONTBBOX3_CODE].val, + (int) fd->font_dim[FONTBBOX4_CODE].val); + for (i = 0; i < GEN_KEY_NUM; i++) + if (fd->font_dim[i].set) + pdf_printf("/%s %i\n", font_key[i].pdfname, fd->font_dim[i].val); +} + +/**********************************************************************/ + +static void preset_fontname(fo_entry * fo) +{ + if (fo->fm->ps_name != NULL) + fo->fd->fontname = xstrdup(fo->fm->ps_name); /* just fallback */ + else + fo->fd->fontname = xstrdup(fo->fm->tfm_name); +} + +static void write_fontname(fd_entry * fd, char *key) +{ + assert(fd->fontname != NULL); + pdf_puts("/"); + if (key != NULL) + pdf_printf("%s /", key); + if (fd->subset_tag != NULL) + pdf_printf("%s+", fd->subset_tag); + pdf_printf("%s\n", fd->fontname); +} + +static void write_fontname_object(fd_entry * fd) +{ + assert(fd->fn_objnum != 0); + pdf_begin_obj(fd->fn_objnum, 1); + write_fontname(fd, NULL); + pdf_end_obj(); +} + +/**********************************************************************/ + +fd_entry *lookup_fd_entry(char *s, integer slant, integer extend) +{ + fd_entry fd; + fm_entry fm; + assert(s != NULL); + fm.ff_name = s; + fm.slant = slant; + fm.extend = extend; + fd.fm = &fm; + if (fd_tree == NULL) { + fd_tree = avl_create(comp_fd_entry, NULL, &avl_xallocator); + assert(fd_tree != NULL); + } + return (fd_entry *) avl_find(fd_tree, &fd); +} + +fd_entry *lookup_fontdescriptor(fo_entry * fo) +{ + assert(fo != NULL); + assert(fo->fm != NULL); + assert(is_fontfile(fo->fm)); + return lookup_fd_entry(fo->fm->ff_name, fo->fm->slant, fo->fm->extend); +} + +void register_fd_entry(fd_entry * fd) +{ + void **aa; + if (fd_tree == NULL) { + fd_tree = avl_create(comp_fd_entry, NULL, &avl_xallocator); + assert(fd_tree != NULL); + } + assert(fd != NULL && fd->fm != NULL && is_fontfile(fd->fm)); + assert(lookup_fd_entry(fd->fm->ff_name, fd->fm->slant, fd->fm->extend) == NULL); /* font descriptor not yet registered */ + aa = avl_probe(fd_tree, fd); + assert(aa != NULL); +} + +void create_fontdescriptor(fo_entry * fo, internalfontnumber f) +{ + assert(fo != NULL); + assert(fo->fm != NULL); + assert(fo->fd == NULL); + fo->fd = new_fd_entry(); + preset_fontname(fo); + preset_fontmetrics(fo->fd, f); + fo->fd->fe = fo->fe; /* encoding needed by TrueType writing */ + fo->fd->fm = fo->fm; /* map entry needed by TrueType writing */ + fo->fd->gl_tree = avl_create(comp_string_entry, NULL, &avl_xallocator); + assert(fo->fd->gl_tree != NULL); +} + +/**********************************************************************/ +/* + * For all used characters of TeX font f, get corresponding glyph names + * from external reencoding (.enc) file and collect these in the glyph + * tree gl_tree of font descriptor fd referenced by font dictionary fo. + */ + +void mark_reenc_glyphs(fo_entry * fo, internalfontnumber f) +{ + int i; + char **g; + void **aa; + assert(fo->fe != NULL); + if (is_subsetted(fo->fm)) { + assert(is_included(fo->fm)); + /* mark glyphs from TeX (externally reencoded characters) */ + g = fo->fe->glyph_names; + for (i = fo->first_char; i <= fo->last_char; i++) { + if (pdf_char_marked(f, i) && g[i] != notdef + && (char *) avl_find(fo->fd->gl_tree, g[i]) == NULL) { + aa = avl_probe(fo->fd->gl_tree, xstrdup(g[i])); + assert(aa != NULL); + } + } + } +} + +/* + * Function mark_chars() has 2 uses: + * 1. Mark characters as chars on TeX level. + * 2. Mark encoding pairs used by TeX to optimize encoding vector. + */ + +struct avl_table *mark_chars(fo_entry * fo, struct avl_table *tx_tree, + internalfontnumber f) +{ + int i, *j; + void **aa; + if (tx_tree == NULL) { + tx_tree = avl_create(comp_int_entry, NULL, &avl_xallocator); + assert(tx_tree != NULL); + } + for (i = fo->first_char; i <= fo->last_char; i++) { + if (pdf_char_marked(f, i) && (int *) avl_find(tx_tree, &i) == NULL) { + j = xtalloc(1, int); + *j = i; + aa = avl_probe(tx_tree, j); + assert(aa != NULL); + } + } + return tx_tree; +} + +/**********************************************************************/ + +void get_char_range(fo_entry * fo, internalfontnumber f) +{ + int i; + assert(fo != NULL); + for (i = font_bc(f); i <= font_ec(f); i++) /* search for first_char and last_char */ + if (pdf_char_marked(f, i)) + break; + fo->first_char = i; + for (i = font_ec(f); i >= font_bc(f); i--) + if (pdf_char_marked(f, i)) + break; + fo->last_char = i; + if ((fo->first_char > fo->last_char) + || !pdf_char_marked(f, fo->first_char)) { /* no character used from this font */ + fo->last_char = 0; + fo->first_char = fo->last_char + 1; + } +} + +static void write_charwidth_array(fo_entry * fo, internalfontnumber f) +{ + int i, j, *ip, *fip, width; + struct avl_traverser t; + assert(fo->tx_tree != NULL); + assert(fo->cw_objnum == 0); + fo->cw_objnum = pdf_new_objnum(); + pdf_begin_obj(fo->cw_objnum, 1); + avl_t_init(&t, fo->tx_tree); + fip = (int *) avl_t_first(&t, fo->tx_tree); + assert(fip != NULL); + pdf_puts("["); + for (ip = fip, j = *ip; ip != NULL; ip = (int *) avl_t_next(&t)) { + if (ip != fip) + pdf_puts(" "); + i = *ip; + while (j < i - 1) { + pdf_puts("0 "); + j++; + } + j = i; + width = divide_scaled(char_width(f, i), pdf_font_size(f), 4); + pdf_printf("%i", (int) width / 10); /* see adv_char_width() in pdftex.web */ + if ((width = width % 10) != 0) + pdf_printf(".%i", width); + } + pdf_puts("]\n"); + pdf_end_obj(); +} + +/**********************************************************************/ +/* + * Remark: Font objects from embedded PDF files are never registered + * into fo_tree; they are individually written out. + */ + +fo_entry *lookup_fo_entry(char *s) +{ + fo_entry fo; + fm_entry fm; + assert(s != NULL); + fm.tfm_name = s; + fo.fm = &fm; + if (fo_tree == NULL) { + fo_tree = avl_create(comp_fo_entry, NULL, &avl_xallocator); + assert(fo_tree != NULL); + } + return (fo_entry *) avl_find(fo_tree, &fo); +} + +void register_fo_entry(fo_entry * fo) +{ + void **aa; + if (fo_tree == NULL) { + fo_tree = avl_create(comp_fo_entry, NULL, &avl_xallocator); + assert(fo_tree != NULL); + } + assert(fo != NULL); + assert(fo->fm != NULL); + assert(fo->fm->tfm_name != NULL); + assert (lookup_fo_entry(fo->fm->tfm_name) == NULL) ; + aa = avl_probe(fo_tree, fo); + assert(aa != NULL); +} + +/**********************************************************************/ + +static void write_fontfile(fd_entry * fd) +{ + assert(is_included(fd->fm)); + if (is_cidkeyed(fd->fm)) { + if (is_opentype(fd->fm)) + writetype0(fd); + else if (is_truetype(fd->fm)) + writetype2(fd); + else if (is_type1(fd->fm)) + writetype1w(fd); + else + assert(0); + } else { + if (is_type1(fd->fm)) +#ifdef DO_TYPE1C + writet1c(fd); +#else + writet1(fd); +#endif + else if (is_truetype(fd->fm)) + writettf(fd); + else if (is_opentype(fd->fm)) + writeotf(fd); + else + assert(0); + } + if (!fd->ff_found) + return; + assert(fd->ff_objnum == 0); + fd->ff_objnum = pdf_new_objnum(); + pdf_begin_dict(fd->ff_objnum, 0); /* font file stream */ + if (is_cidkeyed(fd->fm)) { + /* No subtype is used for TrueType-based OpenType fonts */ + if (is_opentype(fd->fm) || is_type1(fd->fm)) + pdf_puts("/Subtype /CIDFontType0C\n"); + /* else + pdf_puts("/Subtype /OpenType\n");*/ + } else { + if (is_type1(fd->fm)) + pdf_printf("/Length1 %i\n/Length2 %i\n/Length3 %i\n", + (int) t1_length1, (int) t1_length2, (int) t1_length3); + else if (is_truetype(fd->fm)) + pdf_printf("/Length1 %i\n", (int) ttf_length); + else if (is_opentype(fd->fm)) + pdf_puts("/Subtype /Type1C\n"); + else + assert(0); + } + pdf_begin_stream(); + fb_flush(); + pdf_end_stream(); +} + +/**********************************************************************/ + +static void write_fontdescriptor(fd_entry * fd) +{ + char *glyph; + struct avl_traverser t; + assert(fd != NULL && fd->fm != NULL); + + if (is_fontfile(fd->fm)) + write_fontfile(fd); /* this will set fd->ff_found if font file is found */ + if (fd->fn_objnum != 0) + write_fontname_object(fd); + if (fd->fd_objnum == 0) + fd->fd_objnum = pdf_new_objnum(); + pdf_begin_dict(fd->fd_objnum, 1); + pdf_puts("/Type /FontDescriptor\n"); + write_fontname(fd, "FontName"); + if (!fd->ff_found && fd->fm->fd_flags == 4) + pdf_puts("/Flags 34\n"); /* assumes a roman sans serif font */ + else + pdf_printf("/Flags %i\n", (int) fd->fm->fd_flags); + write_fontmetrics(fd); + if (is_cidkeyed(fd->fm)) { + if (is_type1(fd->fm)) + pdf_printf("/FontFile3 %i 0 R\n", (int) fd->ff_objnum); + else if (is_truetype(fd->fm)) + pdf_printf("/FontFile2 %i 0 R\n", (int) fd->ff_objnum); + else if (is_opentype(fd->fm)) + pdf_printf("/FontFile3 %i 0 R\n", (int) fd->ff_objnum); + else + assert(0); + } else { + if (fd->ff_found) { + if (is_subsetted(fd->fm) && is_type1(fd->fm)) { + /* /CharSet is optional; names may appear in any order */ + assert(fd->gl_tree != NULL); + avl_t_init(&t, fd->gl_tree); + pdf_puts("/CharSet ("); + for (glyph = (char *) avl_t_first(&t, fd->gl_tree); glyph != NULL; + glyph = (char *) avl_t_next(&t)) + pdf_printf("/%s", glyph); + pdf_puts(")\n"); + } + if (is_type1(fd->fm)) + pdf_printf("/FontFile %i 0 R\n", (int) fd->ff_objnum); + else if (is_truetype(fd->fm)) + pdf_printf("/FontFile2 %i 0 R\n", (int) fd->ff_objnum); + else if (is_opentype(fd->fm)) + pdf_printf("/FontFile3 %i 0 R\n", (int) fd->ff_objnum); + else + assert(0); + } + } + /* TODO: Optional keys for CID fonts. + + The most interesting ones are + /Style << /Panose <12-byte string>>> + and + /CIDSET + the latter can be used in subsets, to give the included CIDs + as a bitmap on the whole list. + */ + pdf_end_dict(); +} + +void write_fontdescriptors() +{ + fd_entry *fd; + struct avl_traverser t; + if (fd_tree == NULL) + return; + avl_t_init(&t, fd_tree); + for (fd = (fd_entry *) avl_t_first(&t, fd_tree); fd != NULL; + fd = (fd_entry *) avl_t_next(&t)) + write_fontdescriptor(fd); +} + +/**********************************************************************/ + +void write_fontdictionary(fo_entry * fo) +{ + assert(fo != NULL); + assert(fo->fm != NULL); + assert(fo->fo_objnum != 0); /* reserved as pdf_font_num(f) in pdftex.web */ + + /* write ToUnicode entry if needed */ + if (fixed_gen_tounicode > 0 && fo->fd != NULL) { + if (fo->fe != NULL) { + fo->tounicode_objnum = + write_tounicode(fo->fe->glyph_names, fo->fe->name); + } else if (is_type1(fo->fm)) { + assert(fo->fd->builtin_glyph_names != NULL); + fo->tounicode_objnum = + write_tounicode(fo->fd->builtin_glyph_names, fo->fm->tfm_name); + } + } + + pdf_begin_dict(fo->fo_objnum, 1); + pdf_puts("/Type /Font\n"); + pdf_puts("/Subtype /"); + if (is_type1(fo->fm)) +#ifdef DO_TYPE1C + pdf_printf("%s\n", "Type1C"); +#else + pdf_printf("%s\n", "Type1"); +#endif + else if (is_truetype(fo->fm)) + pdf_printf("%s\n", "TrueType"); + else if (is_opentype(fo->fm)) + pdf_printf("%s\n", "Type1"); + else + assert(0); + assert(fo->fd != NULL && fo->fd->fd_objnum != 0); + write_fontname(fo->fd, "BaseFont"); + pdf_printf("/FontDescriptor %i 0 R\n", (int) fo->fd->fd_objnum); + assert(fo->cw_objnum != 0); + pdf_printf("/FirstChar %i\n/LastChar %i\n/Widths %i 0 R\n", + (int) fo->first_char, (int) fo->last_char, + (int) fo->cw_objnum); + if ((is_type1(fo->fm) || is_opentype(fo->fm)) && fo->fe != NULL && fo->fe->fe_objnum != 0) + pdf_printf("/Encoding %i 0 R\n", (int) fo->fe->fe_objnum); + if (fo->tounicode_objnum != 0) + pdf_printf("/ToUnicode %i 0 R\n", (int) fo->tounicode_objnum); + if (pdf_font_attr(fo->tex_font) != get_nullstr()) { + pdf_print(pdf_font_attr(fo->tex_font)); + pdf_puts("\n"); + } + pdf_end_dict(); +} + +void write_fontdictionaries() +{ + fo_entry *fo; + struct avl_traverser t; + if (fo_tree == NULL) + return; + avl_t_init(&t, fo_tree); + for (fo = (fo_entry *) avl_t_first(&t, fo_tree); fo != NULL; + fo = (fo_entry *) avl_t_next(&t)) + write_fontdictionary(fo); +} + +/**********************************************************************/ +/* + * Final flush of all font related stuff by call from + * @= in pdftex.web. + */ + +void write_fontstuff() +{ + write_fontdescriptors(); + write_fontencodings(); /* see writeenc.c */ + write_fontdictionaries(); +} + +/**********************************************************************/ + +void create_fontdictionary(fm_entry * fm, integer font_objnum, + internalfontnumber f) +{ + fo_entry *fo = new_fo_entry(); + get_char_range(fo, f); /* set fo->first_char and fo->last_char from f */ + assert(fo->last_char >= fo->first_char); + fo->fm = fm; + fo->fo_objnum = font_objnum; + fo->tex_font = f; + if (is_reencoded(fo->fm)) { /* at least the map entry tells so */ + fo->fe = get_fe_entry(fo->fm->encname); /* returns NULL if .enc file couldn't be opened */ + if (fo->fe != NULL && (is_type1(fo->fm) || is_opentype(fo->fm))) { + if (fo->fe->fe_objnum == 0) + fo->fe->fe_objnum = pdf_new_objnum(); /* then it will be written out */ + /* mark encoding pairs used by TeX to optimize encoding vector */ + fo->fe->tx_tree = mark_chars(fo, fo->fe->tx_tree, f); + } + } + fo->tx_tree = mark_chars(fo, fo->tx_tree, f); /* for write_charwidth_array() */ + write_charwidth_array(fo, f); + if (!is_builtin(fo->fm)) { + if (is_type1(fo->fm)) { + if ((fo->fd = lookup_fontdescriptor(fo)) == NULL) { + create_fontdescriptor(fo, f); + register_fd_entry(fo->fd); + } + } else + create_fontdescriptor(fo, f); + if (fo->fe != NULL) { + mark_reenc_glyphs(fo, f); + if (!is_type1(fo->fm)) { + /* mark reencoded characters as chars on TeX level */ + assert(fo->fd->tx_tree == NULL); + fo->fd->tx_tree = mark_chars(fo, fo->fd->tx_tree, f); + if (is_truetype(fo->fm)) + fo->fd->write_ttf_glyph_names = true; + } + } else + /* mark non-reencoded characters as chars on TeX level */ + fo->fd->tx_tree = mark_chars(fo, fo->fd->tx_tree, f); + if (!is_type1(fo->fm)) + write_fontdescriptor(fo->fd); + } else { + /* builtin fonts still need the /Widths array and /FontDescriptor + * (to avoid error 'font FOO contains bad /BBox') + */ + create_fontdescriptor(fo, f); + write_fontdescriptor(fo->fd); + if (!is_std_t1font(fo->fm)) + pdftex_warn("font `%s' is not a standard font; " + "I suppose it is available to your PDF viewer then", + fo->fm->ps_name); + } + if (is_type1(fo->fm)) + register_fo_entry(fo); + else + write_fontdictionary(fo); +} + +/**********************************************************************/ + + +void do_pdf_font(integer font_objnum, internalfontnumber f) +{ + fm_entry *fm; + /* This is not 100% true: CID is actually needed whenever (and + * only) there are more than 256 separate glyphs used. But for + * now, just assume the user knows what he is doing; + */ + if (font_encodingbytes(f)==2) { + /* Create a virtual font map entry, as this is needed by the + * rest of the font inclusion mechanism. + */ + fm = new_fm_entry(); + fm->tfm_name = font_name(f); /* or whatever, not a real tfm */ + fm->ff_name = font_filename(f); /* the actual file */ + fm->encname = font_encodingname(f); /* for the CIDSystemInfo */ + fm->ps_name = font_fullname(f); /* the true name */ + fm->slant = font_slant(f); /* slant factor */ + fm->extend = font_extend(f); /* extension factor */ + fm->fd_flags = 4; /* can perhaps be done better */ + fm->in_use = true; + + switch (font_format(f)) { + case opentype_format: set_opentype(fm); break; + case truetype_format: set_truetype(fm); break; + case type1_format: set_type1(fm); break; + default: + pdftex_fail("writefont.c: The file format (%s) for font `%s' is incompatible with wide characters\n", + font_format_name(f),font_name(f)); + } + /* This makes "unknown" default to subsetted inclusion */ + if (font_embedding(f)!=no_embedding) { + set_included(fm); + if (font_embedding(f)!=full_embedding) { + set_subsetted(fm); + } + } + set_cidkeyed(fm); + create_cid_fontdictionary(fm, font_objnum, f); + + } else { + fm = hasfmentry(f) ? (fm_entry *) font_map(f) : NULL; + if (fm == NULL || (fm->ps_name == NULL && fm->ff_name == NULL)) + writet3(font_objnum, f); + else + create_fontdictionary(fm, font_objnum, f); + } +} + +/**********************************************************************/ + + +/* + The glyph width is included in |glw_entry|, because that width + depends on the value it has in the font where it is actually + typeset from, not the font that is the 'owner' of the fd entry. + + TODO: It is possible that the user messes with the metric width, + but handling that properly would require access to the 'hmtx' table + at this point in the program. +*/ + +int comp_glw_entry(const void *pa, const void *pb, void *p) +{ + unsigned short i, j; + i = (*(glw_entry *)pa).id; + j = (*(glw_entry *)pb).id; + cmp_return(i,j); + return 0; +} + +void create_cid_fontdescriptor(fo_entry * fo, internalfontnumber f) +{ + assert(fo != NULL); + assert(fo->fm != NULL); + assert(fo->fd == NULL); + fo->fd = new_fd_entry(); + preset_fontname(fo); + preset_fontmetrics(fo->fd, f); + fo->fd->fe = fo->fe; /* encoding needed by TrueType writing */ + fo->fd->fm = fo->fm; /* map entry needed by TrueType writing */ + fo->fd->gl_tree = avl_create(comp_glw_entry, NULL, &avl_xallocator); + assert(fo->fd->gl_tree != NULL); +} + +/* + The values |font_bc()| and |font_ec()| are potentially large + character ids, but the strings that are written out use CID + indexes, and those are limited to 16-bit values. +*/ + +static void mark_cid_subset_glyphs(fo_entry *fo, internal_font_number f) +{ + int i, k; + glw_entry *j; + void *aa; + for (k = 1; k <= max_font_id(); k++) { + if ( k == f || -f == pdf_font_num(k)) { + for (i = font_bc(k); i <= font_ec(k); i++) { + if (char_exists(k,i) && char_used(k,i)) { + j = xtalloc(1,glw_entry); + j->id = char_index(k,i); + j->wd = divide_scaled_n(char_width(k, i), pdf_font_size(k), 10000.0); + if ((glw_entry *)avl_find(fo->fd->gl_tree,j) == NULL) { + aa = avl_probe(fo->fd->gl_tree, j); + assert(aa != NULL); + } + } + } + } + } +} + +/* + It is possible to compress the widths array even better, by using the + alternate 'range' syntax and possibly even using /DW to set + a default value. + + There is a some optimization here already: glyphs that are + not used do not appear in the widths array at all. + + We have to make sure that we do not output an (incorrect!) + width for a character that exists in the font, but is not used + in typesetting. An enormous negative width is used as sentinel value +*/ + + +static void write_cid_charwidth_array(fo_entry * fo) +{ + int i, j; + glw_entry *glyph; + struct avl_traverser t; + + assert(fo->cw_objnum == 0); + fo->cw_objnum = pdf_new_objnum(); + pdf_begin_obj(fo->cw_objnum, 1); + avl_t_init(&t, fo->fd->gl_tree); + glyph = (glw_entry *) avl_t_first(&t, fo->fd->gl_tree); + assert(glyph != NULL); + i = glyph->id; + pdf_printf("[ %i [", i); + for (; glyph != NULL; glyph = (glw_entry *) avl_t_next(&t)) { + j = glyph->wd; + if (glyph->id>(i+1)) { + pdf_printf("] %i [", glyph->id); + j = glyph->wd; + } + if (glyph->id==(i+1)) + pdf_puts(" "); + pdf_printf("%i", (j/10)); + if ((j % 10) != 0) + pdf_printf(".%i", (j % 10)); + i = glyph->id; + } + pdf_puts("]]\n"); + pdf_end_obj(); +} + + +void create_cid_fontdictionary(fm_entry * fm, integer font_objnum, + internalfontnumber f) +{ + fo_entry *fo = new_fo_entry(); + get_char_range(fo, f); /* set fo->first_char and fo->last_char from f */ + assert(fo->last_char >= fo->first_char); + fo->fm = fm; + fo->fo_objnum = font_objnum; + fo->tex_font = f; + create_cid_fontdescriptor (fo, f); + mark_cid_subset_glyphs (fo,f); + if (is_subsetted(fo->fm)) { + /* + this is a bit sneaky. |make_subset_tag()| actually expects the glyph tree + to contain strings instead of |glw_entry| items. However, all calculations + are done using explicit typecasts, so it works out ok. + */ + make_subset_tag(fo->fd); + } + write_cid_charwidth_array(fo); + write_fontdescriptor(fo->fd); + + write_cid_fontdictionary(fo,f); +} + +void write_cid_fontdictionary(fo_entry * fo, internalfontnumber f) +{ + int i; + + fo->tounicode_objnum = write_cid_tounicode(fo,f); + + pdf_begin_dict(fo->fo_objnum, 1); + pdf_puts("/Type /Font\n"); + pdf_puts("/Subtype /Type0\n"); + pdf_puts("/Encoding /Identity-H\n"); + write_fontname(fo->fd, "BaseFont"); + i = pdf_new_objnum(); + pdf_printf("/DescendantFonts [%i 0 R]\n", i); + /* todo: the ToUnicode CMap */ + if (fo->tounicode_objnum != 0) + pdf_printf("/ToUnicode %i 0 R\n", (int) fo->tounicode_objnum); + + pdf_end_dict(); + + pdf_begin_dict(i, 1); + pdf_puts("/Type /Font\n"); + if (is_opentype(fo->fm) || is_type1(fo->fm)) { + pdf_puts("/Subtype /CIDFontType0\n"); + } else { + pdf_puts("/Subtype /CIDFontType2\n"); + pdf_printf("/CIDToGIDMap /Identity\n"); + } + write_fontname(fo->fd, "BaseFont"); + pdf_printf("/FontDescriptor %i 0 R\n", (int) fo->fd->fd_objnum); + pdf_printf("/W %i 0 R\n",(int) fo->cw_objnum); + pdf_printf("/CIDSystemInfo <<\n"); + pdf_printf("/Registry (%s)\n", (font_cidregistry(f)? font_cidregistry(f): "Adobe")); + pdf_printf("/Ordering (%s)\n",(font_cidordering(f)? font_cidordering(f) : "Identity")) ; + pdf_printf("/Supplement %u\n",(unsigned int)font_cidsupplement(f)); + pdf_printf(">>\n"); + + /* I doubt there is anything useful that could be written here */ + /* + if (pdf_font_attr(fo->tex_font) != get_nullstr()) { + pdf_print(pdf_font_attr(fo->tex_font)); + pdf_puts("\n"); + } + */ + pdf_end_dict(); + +} + diff --git a/Build/source/texk/web2c/luatexdir/font/writet1.c b/Build/source/texk/web2c/luatexdir/font/writet1.c new file mode 100644 index 00000000000..376135dc8be --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/font/writet1.c @@ -0,0 +1,1768 @@ +/* +Copyright (c) 1996-2006 Han The Thanh, + +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 $ + +*/ + +# include "ptexlib.h" +# include +# include +# include +# include "luatex-api.h" + +# define t1_log(s) if(tracefilenames) tex_printf(s) +# 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 = fixedcontent? t1_offset() - t1_save_offset : 0 +# define save_offset() t1_save_offset = t1_offset() + +# define t1_putchar fb_putchar +# define t1_offset fb_offset +# define out_eexec_char t1_putchar + +# 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) +# define fixedcontent false + +integer t1_length1, t1_length2, t1_length3; +static integer t1_save_offset; +static integer t1_fontname_offset; +extern char *fb_array; + +static unsigned char *t1_buffer = NULL; +static integer t1_size = 0; +static integer t1_curbyte = 0; + +#define t1_read_file() \ + readbinfile(t1_file,&t1_buffer,&t1_size) +#define t1_close() xfclose(t1_file,cur_file_name) +#define t1_getchar() t1_buffer[t1_curbyte++] +#define t1_ungetchar(c) t1_curbyte-- +#define t1_eof() (t1_curbyte>t1_size) + +#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") + +static unsigned char *enc_buffer = NULL; +static integer enc_size = 0; +static integer enc_curbyte = 0; + +#define enc_open() \ + open_input(&enc_file, kpse_enc_format, FOPEN_RBIN_MODE) +#define enc_read_file() \ + readbinfile(enc_file,&enc_buffer,&enc_size) +#define enc_close() xfclose(enc_file,cur_file_name) +#define enc_getchar() enc_buffer[enc_curbyte++] +#define enc_eof() (enc_curbyte>enc_size) + +#define valid_code(c) (c >= 0 && c < 256) +#define fixedcontent false + +static const char *standard_glyph_names[256] = { + /* 0x00 */ + notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, + notdef, notdef, notdef, notdef, notdef, notdef, notdef, + /* 0x10 */ + notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, + notdef, notdef, notdef, notdef, notdef, notdef, notdef, + /* 0x20 */ + "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", + "ampersand", "quoteright", "parenleft", "parenright", "asterisk", + "plus", "comma", "hyphen", "period", "slash", + /* 0x30 */ + "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", + "nine", "colon", "semicolon", "less", "equal", "greater", "question", + /* 0x40 */ + "at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", + "O", + /* 0x50 */ + "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft", + "backslash", "bracketright", "asciicircum", "underscore", + /* 0x60 */ + "quoteleft", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", + "m", "n", "o", + /* 0x70 */ + "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", + "braceright", "asciitilde", notdef, + /* 0x80 */ + notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, + notdef, notdef, notdef, notdef, notdef, notdef, notdef, + /* 0x90 */ + notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, + notdef, notdef, notdef, notdef, notdef, notdef, notdef, + /* 0xa0 */ + notdef, "exclamdown", "cent", "sterling", "fraction", "yen", "florin", + "section", "currency", "quotesingle", "quotedblleft", "guillemotleft", + "guilsinglleft", "guilsinglright", "fi", "fl", + /* 0xb0 */ + notdef, "endash", "dagger", "daggerdbl", "periodcentered", notdef, + "paragraph", "bullet", "quotesinglbase", "quotedblbase", + "quotedblright", "guillemotright", "ellipsis", "perthousand", notdef, + "questiondown", + /* 0xc0 */ + notdef, "grave", "acute", "circumflex", "tilde", "macron", "breve", + "dotaccent", "dieresis", notdef, + "ring", "cedilla", notdef, "hungarumlaut", "ogonek", "caron", + /* 0xd0 */ + "emdash", notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, + notdef, notdef, notdef, notdef, notdef, notdef, notdef, + /* 0xe0 */ + notdef, "AE", notdef, "ordfeminine", notdef, notdef, notdef, notdef, + "Lslash", "Oslash", "OE", "ordmasculine", notdef, notdef, notdef, + notdef, + /* 0xf0 */ + notdef, "ae", notdef, notdef, notdef, "dotlessi", notdef, notdef, "lslash", + "oslash", "oe", "germandbls", notdef, notdef, notdef, notdef +}; + + +integer t1_length1, t1_length2, t1_length3; +static integer t1_save_offset; +static integer t1_fontname_offset; +extern char *fb_array; +static fd_entry *fd_cur; + +static char charstringname[] = "/CharStrings"; + +enum { ENC_STANDARD, ENC_BUILTIN } t1_encoding; + +#define T1_BUF_SIZE 0x10 +#define ENC_BUF_SIZE 0x1000 + +#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_counter, 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; + +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 && !enc_eof()); + append_eol (p, enc_line, ENC_BUF_SIZE); + if (p - enc_line < 2 || *enc_line == '%') + goto restart; +} + +/* read encoding from .enc file, return glyph_names array, or pdffail() */ + +char **load_enc_file(char *enc_name) +{ + int callback_id = 0; + int file_opened = 0; + char *ftemp = NULL; + char buf[ENC_BUF_SIZE], *p, *r; + int i, names_count; + char **glyph_names; + char *tempname ; + set_cur_file_name (enc_name); + callback_id=callback_defined(find_enc_file_callback); + if (callback_id>0) { + if(run_callback(callback_id,"S->S",(char *)(nameoffile+1),&ftemp)) { + if(ftemp!=NULL&&strlen(ftemp)) { + free(nameoffile); + namelength = strlen(ftemp); + nameoffile = xmalloc(namelength+2); + strcpy((char *)(nameoffile+1),ftemp); + free(ftemp); + } else { + return NULL; + } + } + } + callback_id=callback_defined(read_enc_file_callback); + enc_curbyte=0; + enc_size=0; + if (callback_id>0) { + if(run_callback(callback_id,"S->bSd",(char *)(nameoffile+1), + &file_opened, &enc_buffer,&enc_size)) { + if((!file_opened) || enc_size==0) { + pdftex_warn ("cannot open encoding file for reading"); + cur_file_name = NULL; + return NULL; + } + } + } else { + if (!enc_open ()) { + pdftex_warn ("cannot open encoding file for reading"); + cur_file_name = NULL; + return NULL; + } + enc_read_file(); + enc_close(); + } + glyph_names = xtalloc(256, char *); + for (i = 0; i < 256; i++) + glyph_names[i] = (char *) notdef; + t1_log ("{"); + + tempname = xmalloc(namelength+2); + strcpy(tempname,(char *)(nameoffile+1)); + set_cur_file_name (tempname); + t1_log (cur_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 > 256) + pdftex_fail ("encoding vector contains more than 256 names"); + 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: + t1_log ("}"); + cur_file_name = NULL; + return glyph_names; +} + +void free_glyph_names(char **glyph_names) +{ + int i; + assert(glyph_names != NULL); + for (i = 0; i < 256; i++) + if (glyph_names[i] != notdef) + xfree(glyph_names[i]); + xfree(glyph_names); +} + + +static void t1_check_pfa (void) +{ + const int c = t1_getchar (); + t1_pfa = (c != 128) ? true : 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 ()) + (void)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) +{ + const byte plain = (cipher ^ (*cr >> 8)); + *cr = (cipher + *cr) * t1_c1 + t1_c2; + return plain; +} + +static byte eencrypt (byte plain) +{ + const 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) +{ + const 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) + t1_putchar (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 (); +} + +__attribute__ ((format (printf, 1, 2))) +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); + 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; + assert(is_included(fd_cur->fm)); + 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; + t1_putline (); /* to put the first four bytes */ +} + +static void t1_stop_eexec (void) +{ + int c; + assert(is_included(fd_cur->fm)); + get_length2 (); + save_offset (); + t1_eexec_encrypt = false; + 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; +} + +/* macros for various transforms; currently only slant and extend are used */ + +# define do_xshift(x,a) {x[4]+=a;} +# define do_yshift(x,a) {x[5]+=a;} +# define do_xscale(x,a) {x[0]*=a; x[2]*=a; x[4]*=a;} +# define do_yscale(x,a) {x[1]*=a; x[3]*=a; x[5]*=a;} +# define do_extend(x,a) {do_xscale(x,a);} +# define do_scale(x,a) {do_xscale(x,a); do_yscale(x,a);} +# define do_slant(x,a) {x[0]+=x[1]*(a); x[2]+=x[3]*(a); x[4]+=x[5]*(a);} +# define do_shear(x,a) {x[1]+=x[0]*(a); x[3]+=x[2]*(a); x[5]+=x[4]*(a);} +# define do_rotate(x,a) \ + {float t, u=cos(a), v=sin(a); \ + t =x[0]*u+x[1]*-v; \ + x[1] =x[0]*v+x[1]* u; x[0]=t; \ + t =x[2]*u+x[3]*-v; \ + x[3] =x[2]*v+x[3]* u; x[2]=t; \ + t =x[4]*u+x[5]*-v; \ + x[5] =x[4]*v+x[5]* u; x[4]=t;} + +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 + * + * The slant transform must be done _before_ the extend transform + * for compatibility! + */ + float a[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, (size_t) (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_slant(fd_cur->fm) != 0) + do_slant(a, fm_slant(fd_cur->fm) * 1E-3); + if (fm_extend(fd_cur->fm) != 0) + do_extend(a, fm_extend(fd_cur->fm) * 1E-3); + for (i = 0; i < 6; i++) { + sprintf (r, "%g ", a[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(fd_cur->fm) == 0) + return; + p = strchr (t1_line_array, ' '); + strncpy (t1_buf_array, t1_line_array, (size_t) (p - t1_line_array + 1)); + a = t1_scan_num (p + 1, &r); + a -= atan (fm_slant(fd_cur->fm) * 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); + fd_cur->font_dim[ITALIC_ANGLE_CODE].val = round(a); + fd_cur->font_dim[ITALIC_ANGLE_CODE].set = true; +} + +static void t1_scan_keys (void) +{ + int i, k; + char *p, *q, *r; + key_entry *key; + if (fm_extend(fd_cur->fm) != 0 || fm_slant(fd_cur->fm) != 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 = (key_entry *) font_key; key - font_key < FONT_KEYS_NUM; key++) { + if (key->t1name[0] != '\0' && + str_prefix(t1_line_array + 1, key->t1name)) + break; + } + if (key - font_key == FONT_KEYS_NUM) + return; + p = t1_line_array + strlen (key->t1name) + 1; + skip (p, ' '); + if ((k = key - font_key) == 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(fd_cur->fm) != 0) { + sprintf(q, "-Slant_%i", (int) fm_slant(fd_cur->fm)); + q = strend (q); + } + if (fm_extend(fd_cur->fm) != 0) { + sprintf(q, "-Extend_%i", (int) fm_extend(fd_cur->fm)); + } + xfree(fd_cur->fontname); + fd_cur->fontname = xstrdup(t1_buf_array); + /* 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_subsetted(fd_cur->fm)) { + assert(is_included(fd_cur->fm)); + t1_fontname_offset = t1_offset () + (r - t1_line_array); + strcpy (t1_buf_array, p); + sprintf(r, "ABCDEF+%s%s", fd_cur->fontname, 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++, k++) { + fd_cur->font_dim[k].val = t1_scan_num(p, &r); + fd_cur->font_dim[k].set = true; + p = r; + } + return; + } + fd_cur->font_dim[k].val = t1_scan_num(p, 0); + fd_cur->font_dim[k].set = true; +} + +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) { + xfree (glyph_names[b]); + glyph_names[b] = (char *) notdef; + } + if (glyph_names[a] != notdef) { + glyph_names[b] = xstrdup (glyph_names[a]); + } +} + +/* read encoding from Type1 font file, return glyph_names array, or pdffail() */ + +char **t1_builtin_enc(void) +{ + int i, a, b, c, counter = 0; + char *r, *p, **glyph_names; + /* At this moment "/Encoding" is the prefix of t1_line_array */ + glyph_names = xtalloc(256, char *); + for (i = 0; i < 256; i++) + glyph_names[i] = (char *) notdef; + if (t1_suffix("def")) { /* predefined encoding */ + sscanf(t1_line_array + strlen("/Encoding"), "%256s", t1_buf_array); + if (strcmp(t1_buf_array, "StandardEncoding") == 0) { + t1_encoding = ENC_STANDARD; + for (i = 0; i < 256; i++) { + if (standard_glyph_names[i] != notdef) + glyph_names[i] = xstrdup(standard_glyph_names[i]); + } + return glyph_names; + } else + pdftex_fail + ("cannot subset font (unknown predefined encoding `%s')", + t1_buf_array); + } + /* 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 + */ + t1_encoding = ENC_BUILTIN; + 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 > 255) + pdftex_fail("encoding vector contains more than 256 names"); + if (strcmp(t1_buf_array, notdef) != 0) + 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 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) + glyph_names[i] = xstrdup(t1_buf_array + 1); + p = strstr(p, " put") + strlen(" put"); + skip(p, ' '); + } + /* + check for `dup dup exch 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(glyph_names, a, b); + p = strstr(p, " get put") + strlen(" get put"); + skip(p, ' '); + } + /* + check for `dup dup getinterval 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(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 glyph_names; + /* + skip an unrecognizable word + */ + else { + while (*p != ' ' && *p != 10) + p++; + skip(p, ' '); + } + } + } + return glyph_names; +} + + +static void t1_check_end (void) +{ + if (t1_eof ()) + return; + t1_getline (); + if (t1_prefix ("{restore}")) + t1_putline (); +} + +static boolean t1_open_fontfile (const char *open_name_prefix) +{ + int callback_id = 0; + int file_opened = 0; + char *ftemp = NULL; + ff_entry *ff; + ff = check_ff_exist(fd_cur->fm->ff_name, is_truetype(fd_cur->fm)); + t1_curbyte = 0; + t1_size = 0; + if (ff->ff_path != NULL) { + callback_id=callback_defined(find_type1_file_callback); + if (callback_id>0) { + if(run_callback(callback_id,"S->S",ff->ff_path,&ftemp)) { + if(ftemp!=NULL&&strlen(ftemp)) { + strcpy(ff->ff_path,ftemp); + } + } + } + callback_id=callback_defined(read_type1_file_callback); + if (callback_id>0) { + if(run_callback(callback_id,"S->bSd",ff->ff_path, + &file_opened, &t1_buffer,&t1_size) + && file_opened && t1_size>0) { + cur_file_name = ff->ff_path; + } else { + set_cur_file_name (fd_cur->fm->ff_name); + pdftex_warn ("cannot open Type 1 font file for reading"); + return false; + } + } else { + t1_file = xfopen (cur_file_name = ff->ff_path, FOPEN_RBIN_MODE); + t1_read_file(); + t1_close(); + } + } + else { + set_cur_file_name (fd_cur->fm->ff_name); + pdftex_warn ("cannot open Type 1 font file for reading"); + return false; + } + t1_init_params (open_name_prefix); + return true; +} + +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 (); + if (fixedcontent) { /* copy 512 zeros (not needed for PDF) */ + do { + t1_getline (); + t1_putline (); + } + while (!t1_cleartomark ()); + t1_check_end (); /* write "{restore}if" if found */ + } + get_length3 (); +} + +#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)", \ + (int) N, (int)(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) + +__attribute__ ((format (printf, 3, 4))) +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; +} + +/**********************************************************************/ +/* AVL search tree for glyph code by glyph name */ + +static int comp_t1_glyphs(const void *pa, const void *pb, void *p) +{ + return strcmp(*((const char **) pa), *((const char **) pb)); +} + +struct avl_table *create_t1_glyph_tree(char **glyph_names) +{ + int i; + void **aa; + static struct avl_table *gl_tree; + gl_tree = avl_create(comp_t1_glyphs, NULL, &avl_xallocator); + assert(gl_tree != NULL); + for (i = 0; i < 256; i++) { + if (glyph_names[i] != notdef && + (char **) avl_find(gl_tree, &glyph_names[i]) == NULL) { + /* no strdup here, just point to the glyph_names array members */ + aa = avl_probe(gl_tree, &glyph_names[i]); + assert(aa != NULL); + } + } + return gl_tree; +} + +void destroy_t1_glyph_tree(struct avl_table *gl_tree) +{ + assert(gl_tree != NULL); + avl_destroy(gl_tree, NULL); +} + +/**********************************************************************/ + +static void t1_subset_ascii_part(void) +{ + int j, *p; + char *glyph, **gg, **glyph_names; + struct avl_table *gl_tree; + struct avl_traverser t; + void **aa; + assert(fd_cur != NULL); + assert(fd_cur->gl_tree != NULL); + t1_getline(); + while (!t1_prefix("/Encoding")) { + t1_scan_param(); + t1_putline(); + t1_getline(); + } + glyph_names = t1_builtin_enc(); + fd_cur->builtin_glyph_names = glyph_names; + if (is_subsetted(fd_cur->fm)) { + assert(is_included(fd_cur->fm)); + if (fd_cur->tx_tree != NULL) { + /* take over collected non-reencoded characters from TeX */ + avl_t_init(&t, fd_cur->tx_tree); + for (p = (int *) avl_t_first(&t, fd_cur->tx_tree); p != NULL; + p = (int *) avl_t_next(&t)) { + if ((char *) avl_find(fd_cur->gl_tree, glyph_names[*p]) == NULL) { + glyph = xstrdup(glyph_names[*p]); + aa = avl_probe(fd_cur->gl_tree, glyph); + assert(aa != NULL); + } + } + } + make_subset_tag(fd_cur); + assert(t1_fontname_offset != 0); + strncpy(fb_array + t1_fontname_offset, fd_cur->subset_tag, 6); + } + /* now really all glyphs needed from this font are in the fd_cur->gl_tree */ + 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"); + gl_tree = create_t1_glyph_tree(glyph_names); + avl_t_init(&t, fd_cur->gl_tree); + j = 0; + for (glyph = (char *) avl_t_first(&t, fd_cur->gl_tree); glyph != NULL; + glyph = (char *) avl_t_next(&t)) { + if ((gg = (char **) avl_find(gl_tree, &glyph)) != NULL) { + t1_printf("dup %i /%s put\n", (int) (gg - glyph_names), *gg); + j++; + } + } + destroy_t1_glyph_tree(gl_tree); + if (j == 0) + /* We didn't mark anything for the Encoding array. */ + /* We add "dup 0 /.notdef put" for compatibility */ + /* with Acrobat 5.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); +} + + +static void cs_init (void) +{ + cs_ptr = cs_tab = NULL; + cs_dict_start = cs_dict_end = NULL; + cs_counter = 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_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; + } +} + +#define t1_subr_flush() t1_flush_cs(true) +#define t1_cs_flush() t1_flush_cs(false) + +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_counter; + } + 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 (); + + cs_len = 0; /* for -Wall */ + /* 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 %li %u", (long int)(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 %li %u%s ", (long int)(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) +{ + char *glyph; + struct avl_traverser t; + cs_entry *ptr; + if (t1_synthetic || fd_cur->all_glyphs) { /* 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); + avl_t_init(&t, fd_cur->gl_tree); + for (glyph = (char *) avl_t_first(&t, fd_cur->gl_tree); glyph != NULL; + glyph = (char *) avl_t_next(&t)) { + mark_cs(glyph); + } + 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_counter = 0, ptr = cs_tab; ptr < cs_ptr; ptr++) + if (ptr->used) + cs_counter++; + 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 (); + if (fixedcontent) { /* copy 512 zeros (not needed for PDF) */ + 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(fd_entry * fd) +{ + fd_cur = fd; /* fd_cur is global inside writet1.c */ + assert(fd_cur->fm != NULL); + assert(is_type1(fd->fm)); + assert(is_included(fd->fm)); + + t1_save_offset = 0; + if (!is_subsetted(fd_cur->fm)) { /* include entire font */ + if (!(fd->ff_found = t1_open_fontfile("<<"))) + return; + t1_include (); + t1_close_font_file (">>"); + return; + } + /* partial downloading */ + if (!(fd->ff_found = 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); +} + diff --git a/Build/source/texk/web2c/luatexdir/font/writet3.c b/Build/source/texk/web2c/luatexdir/font/writet3.c new file mode 100644 index 00000000000..42827d1b124 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/font/writet3.c @@ -0,0 +1,348 @@ +/* +Copyright (c) 1996-2006 Han The Thanh, + +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: writet3.c 1013 2008-02-14 00:09:02Z oneiros $ +*/ + +#include "ptexlib.h" +#include +#include +#include + +#define T3_BUF_SIZE 1024 + +typedef char t3_line_entry; +define_array (t3_line); + +FILE *t3_file; +static boolean t3_image_used; + +static integer t3_char_procs[256]; +static float t3_char_widths[256]; +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; + +static unsigned char *t3_buffer = NULL; +static integer t3_size = 0; +static integer t3_curbyte = 0; + + +#define t3_open() \ + open_input(&t3_file, kpse_miscfonts_format, FOPEN_RBIN_MODE) +#define t3_read_file() readbinfile(t3_file,&t3_buffer,&t3_size) +#define t3_close() xfclose(t3_file, cur_file_name) +#define t3_getchar() t3_buffer[t3_curbyte++] +#define t3_eof() (t3_curbyte>t3_size) + +#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 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 integer get_pk_font_scale (internalfontnumber f) +{ + return + divide_scaled (pk_scale_factor, + divide_scaled (pdf_font_size(f), one_hundred_bp, + fixed_decimal_digits + 2), 0); +} + +static integer pk_char_width (internalfontnumber f, scaled w) +{ + return + divide_scaled (divide_scaled (w, pdf_font_size(f), 7), + get_pk_font_scale (f), 0); +} + +scaled get_pk_char_width (internalfontnumber f, scaled w) +{ + return (get_pk_font_scale (f) / 100000.0) * + (pk_char_width (f, w) / 100.0) * pdf_font_size(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; + char *ftemp = NULL; + chardesc cd; + boolean is_null_glyph, check_preamble; + integer dpi; + int callback_id=0; + int file_opened=0; + int mallocsize=0; + if (t3_buffer!=NULL) { + xfree(t3_buffer); + t3_buffer=NULL; + } + t3_curbyte=0; + t3_size=0; + + callback_id=callback_defined(find_pk_file_callback); + + if (callback_id>0) { + dpi = round (fixed_pk_resolution * + (((float) pdf_font_size(f)) / font_dsize(f))); + /* .dpi/.pk */ + cur_file_name = font_name(f); + mallocsize = strlen(cur_file_name)+24+9; + name = xmalloc(mallocsize); + snprintf(name,mallocsize,"%ddpi/%s.%dpk",(int)fixed_pk_resolution,cur_file_name,(int)dpi); + if(run_callback(callback_id,"S->S",name,&ftemp)) { + if(ftemp!=NULL&&strlen(ftemp)) { + free(name); + name = xstrdup(ftemp); + free(ftemp); + } + } + } else { + dpi = + kpse_magstep_fix (round + (fixed_pk_resolution * + (((float) pdf_font_size(f)) / font_dsize(f))), + fixed_pk_resolution, NULL); + cur_file_name = font_name(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; + } + } + callback_id=callback_defined(read_pk_file_callback); + if (callback_id>0) { + if(! ( run_callback(callback_id,"S->bSd",name, &file_opened, &t3_buffer,&t3_size) && + file_opened && + t3_size>0 ) ) { + pdftex_warn ("Font %s at %i not found", cur_file_name, (int)dpi); + cur_file_name = NULL; + return false; + } + } else { + t3_file = xfopen (name, FOPEN_RBIN_MODE); + t3_read_file(); + t3_close(); + } + t3_image_used = true; + is_pk_font = true; + if (tracefilenames) + 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 (!pdf_char_marked (f, cd.charcode)) + continue; + t3_char_widths[cd.charcode] = + pk_char_width (f, get_charwidth (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++; + pdf_new_dict (0, 0, 0); + t3_char_procs[cd.charcode] = obj_ptr; + pdf_begin_stream (); + pdf_print_real (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: + pdf_end_stream (); + } + xfree (cd.raster); + cur_file_name = NULL; + return true; +} + +void writet3 (int objnum, internalfontnumber f) +{ + + int i; + integer wptr, eptr, cptr; + int first_char, last_char; + integer pk_font_scale; + boolean is_notdef; + + + t3_glyph_num = 0; + t3_image_used = false; + for (i = 0; i < 256; i++) { + t3_char_procs[i] = 0; + t3_char_widths[i] = 0; + } + pack_file_name (tex_font_name(f), get_nullstr (), maketexlstring (".pgc",4)); + cur_file_name = makecstring (make_name_string ()); + is_pk_font = false; + + if (t3_buffer!=NULL) { + xfree(t3_buffer); + t3_buffer=NULL; + } + t3_curbyte=0; + t3_size=0; + if (!writepk (f)) { + cur_file_name = NULL; + return; + } + for (i = font_bc(f); i <= font_ec(f); i++) + if (pdf_char_marked (f, i)) + break; + first_char = i; + for (i = font_ec(f); i > first_char; i--) + if (pdf_char_marked (f, i)) + break; + last_char = i; + pdf_begin_dict (objnum, 1); /* Type 3 font dictionary */ + pdf_puts ("/Type /Font\n/Subtype /Type3\n"); + pdf_printf ("/Name /F%i\n", (int) f); + if (pdf_font_attr(f) != get_nullstr ()) { + pdf_print (pdf_font_attr(f)); + pdf_puts ("\n"); + } + if (is_pk_font) { + pk_font_scale = get_pk_font_scale (f); + pdf_puts ("/FontMatrix ["); + pdf_print_real (pk_font_scale, 5); + pdf_puts (" 0 0 "); + pdf_print_real (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_key[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); + wptr = pdf_new_objnum (); + eptr = pdf_new_objnum (); + cptr = pdf_new_objnum (); + pdf_printf ("/Widths %i 0 R\n/Encoding %i 0 R\n/CharProcs %i 0 R\n", + (int)wptr, (int)eptr, (int)cptr); + pdf_end_dict (); + pdf_begin_obj (wptr, 1); /* chars width array */ + pdf_puts ("["); + if (is_pk_font) + for (i = first_char; i <= last_char; i++) { + pdf_print_real (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"); + pdf_end_obj (); + pdf_begin_dict (eptr, 1); /* 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"); + pdf_end_dict (); + pdf_begin_dict (cptr, 1); /* 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]); + pdf_end_dict (); + if (tracefilenames) + tex_printf (">"); + cur_file_name = NULL; +} diff --git a/Build/source/texk/web2c/luatexdir/font/writettf.c b/Build/source/texk/web2c/luatexdir/font/writettf.c new file mode 100644 index 00000000000..2a92706a0de --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/font/writettf.c @@ -0,0 +1,1509 @@ +/* +Copyright (c) 1996-2006 Han The Thanh, + +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: writettf.c 1013 2008-02-14 00:09:02Z oneiros $ +*/ + +#include "ptexlib.h" +#include "writettf.h" +#include + +#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*/ + +unsigned char *ttf_buffer = NULL; +integer ttf_size = 0; +integer ttf_curbyte = 0; + +typedef struct { + char *name; /* name of glyph */ + long code; /* charcode in case of subfonts */ + 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; + +typedef struct { + char *ttf_name; + TTF_USHORT pid; + TTF_USHORT eid; + short *table; +} ttf_cmap_entry; + +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; + +glyph_entry *glyph_tab; +dirtab_entry *dir_tab; + +static long *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 char *glyph_name_buf; +static TTF_ULONG checksum; +static TTF_ULONG tab_length; +static TTF_ULONG tmp_ulong; +static TTF_ULONG checkSumAdjustment_offset; +FILE *ttf_file; +static ttfenc_entry ttfenc_tab[256]; + +fd_entry *fd_cur; /* pointer to the current font descriptor */ + +static struct avl_table *ttf_cmap_tree = NULL; + +integer ttf_length; + +#include "macnames.c" + +extern char *fb_array; +extern char charsetstr[]; + +static const char *newtabnames[] = { + "OS/2", + "PCLT", + "cmap", + "cvt ", + "fpgm", + "glyf", + "head", + "hhea", + "hmtx", + "loca", + "maxp", + "name", + "post", + "prep" +}; + +ttf_cmap_entry *new_ttf_cmap_entry (void) +{ + ttf_cmap_entry *e; + e = xtalloc (1, ttf_cmap_entry); + e->ttf_name = NULL; + e->table = NULL; + return e; +} + +static void destroy_ttf_cmap_entry (void *pa, void *pb) +{ + ttf_cmap_entry *p; + p = (ttf_cmap_entry *) pa; + xfree (p->ttf_name); + xfree (p->table); + xfree (p); +} + +void ttf_free (void) +{ + if (ttf_cmap_tree != NULL) + avl_destroy (ttf_cmap_tree, destroy_ttf_cmap_entry); +} + +static int comp_ttf_cmap_entry (const void *pa, const void *pb, void *p) +{ + const ttf_cmap_entry *p1 = (const ttf_cmap_entry *) pa, + *p2 = (const ttf_cmap_entry *) pb; + int i; + assert (p1->ttf_name != NULL && p2->ttf_name != NULL); + if ((i = strcmp (p1->ttf_name, p2->ttf_name)) != 0) + return i; + cmp_return (p1->pid, p2->pid); + cmp_return (p1->eid, p2->eid); + return 0; +} + +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; +} + +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; +} + +long ttf_getnum (int s) +{ + long i = 0; + int c; + while (s > 0) { + if (ttf_eof()) + pdftex_fail ("unexpected EOF"); + c = ttf_getchar (); + 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 (); +} + +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; +} + +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);*/ + ttf_curbyte = tab->offset + offset; + return tab; +} + +static void ttf_seek_off (TTF_LONG offset) +{ + ttf_curbyte = offset; + //xfseek (INFILE, offset, SEEK_SET, cur_file_name); +} + +static void ttf_copy_encoding(void) +{ + int i, *q; + void **aa; + char **glyph_names; + long *charcodes; + static char buf[SMALL_BUF_SIZE]; + struct avl_traverser t; + ttfenc_entry *e = ttfenc_tab; + + assert(fd_cur->tx_tree != NULL); /* this must be set in create_fontdictionary */ + + if (fd_cur->fe != NULL) { + glyph_names = fd_cur->fe->glyph_names; + assert(glyph_names != NULL); + + for (i = 0; i < 256; i++) + ttfenc_tab[i].name = (char *) notdef; + + /* a workaround for a bug of AcroReader 4.0 */ + if (strcmp(glyph_names[97], "a") == 0) { + q = xtalloc(1, int); + *q = 'a'; + aa = avl_probe(fd_cur->tx_tree, q); + assert(aa != NULL); + } + /* end of workaround */ + + /* take over collected characters from TeX, reencode them */ + avl_t_init(&t, fd_cur->tx_tree); + for (q = (int *) avl_t_first(&t, fd_cur->tx_tree); q != NULL; + q = (int *) avl_t_next(&t)) { + assert(*q >= 0 && *q < 256); + ttfenc_tab[*q].name = glyph_names[*q]; + } + make_subset_tag(fd_cur); + } else if (is_subfont(fd_cur->fm)) { + charcodes = fd_cur->fm->subfont->charcodes; + assert(charcodes != NULL); + + for (i = 0; i < 256; i++) + ttfenc_tab[i].code = -1; + + /* take over collected characters from TeX */ + avl_t_init(&t, fd_cur->tx_tree); + for (q = (int *) avl_t_first(&t, fd_cur->tx_tree); q != NULL; + q = (int *) avl_t_next(&t)) { + assert(*q >= 0 && *q < 256); + e = ttfenc_tab + *q; + e->code = charcodes[*q]; + if (e->code == -1) + pdftex_warn("character %i is not mapped to any charcode", *q); + else { + assert(e->code < 0x10000); + sprintf(buf, "/c%4.4X", (int) e->code); + aa = avl_probe(fd_cur->gl_tree, xstrdup(buf)); + assert(aa != NULL); + } + } + make_subset_tag(fd_cur); + } else + assert(0); +} + +#define ttf_append_byte(B)\ +do {\ + if (name_tab[i].platform_id == 3)\ + *q++ = 0;\ + *q++ = B;\ +} while (0) + +static char *strip_spaces_and_delims(char *s, int l) +{ + static char buf[SMALL_BUF_SIZE]; + char *p = buf; + int i; + + assert(l >= 0 && l < (int) sizeof(buf)); + + for (i = 0; i < l; s++, i++) { + if (*s == '(' || *s == ')' || *s == '<' || *s == '>' || + *s == '[' || *s == ']' || *s == '{' || *s == '}' || + *s == '/' || *s == '%' || isspace(*s)) + continue; + *p++ = *s; + } + *p = 0; + return buf; +} + +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) { + xfree(fd_cur->fontname); + fd_cur->fontname = + xstrdup(strip_spaces_and_delims(name_buf + name_tab[i].offset, + name_tab[i].length)); + fd_cur->font_dim[FONTNAME_CODE].set = true; + break; + } + } + if (!fd_cur->font_dim[FONTNAME_CODE].set) { + 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 = fd_cur->fontname; j < name_tab[i].length; + j += 2) + *p++ = name_buf[name_tab[i].offset + j + 1]; + *p = 0; + fd_cur->font_dim[FONTNAME_CODE].set = true; + break; + } + } + } +} + +static void ttf_read_mapx (void) +{ + 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, long); + glyph_index[0] = 0; /* index of ".notdef" glyph */ + glyph_index[1] = 1; /* index of ".null" glyph */ +} + +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); + fd_cur->font_dim[FONTBBOX1_CODE].val = ttf_funit(get_fword()); + fd_cur->font_dim[FONTBBOX2_CODE].val = ttf_funit(get_fword()); + fd_cur->font_dim[FONTBBOX3_CODE].val = ttf_funit(get_fword()); + fd_cur->font_dim[FONTBBOX4_CODE].val = ttf_funit(get_fword()); + fd_cur->font_dim[FONTBBOX1_CODE].set = true; + fd_cur->font_dim[FONTBBOX2_CODE].set = true; + fd_cur->font_dim[FONTBBOX3_CODE].set = true; + fd_cur->font_dim[FONTBBOX4_CODE].set = true; + ttf_skip (2 * TTF_USHORT_SIZE + TTF_SHORT_SIZE); + loca_format = get_short (); +} + +void ttf_read_hhea (void) +{ + ttf_seek_tab ("hhea", TTF_FIXED_SIZE); + fd_cur->font_dim[ASCENT_CODE].val = ttf_funit(get_fword()); + fd_cur->font_dim[DESCENT_CODE].val = ttf_funit(get_fword()); + fd_cur->font_dim[ASCENT_CODE].set = true; + fd_cur->font_dim[DESCENT_CODE].set = true; + ttf_skip (TTF_FWORD_SIZE + TTF_UFWORD_SIZE + 3 * TTF_FWORD_SIZE + + 8 * TTF_SHORT_SIZE); + nhmtxs = get_ushort (); +} + +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); + fd_cur->font_dim[XHEIGHT_CODE].val = ttf_funit(get_ushort()); + ttf_skip(2 * TTF_USHORT_SIZE); + fd_cur->font_dim[CAPHEIGHT_CODE].val = ttf_funit(get_ushort()); + fd_cur->font_dim[XHEIGHT_CODE].set = true; + fd_cur->font_dim[CAPHEIGHT_CODE].set = 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 (); + } + } +} + +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; + const 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; + fd_cur->font_dim[ITALIC_ANGLE_CODE].val = + sign * (int_part + frac_part * 1.0 / 0x10000); + fd_cur->font_dim[ITALIC_ANGLE_CODE].set = 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);*/ + length = tab->length - (ttf_curbyte - 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; +} + +void ttf_read_tabdir (void) +{ + int i; + dirtab_entry *tab; + 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 ttf_cmap_entry *ttf_read_cmap (char *ttf_name, int pid, int eid, + boolean warn) +{ + seg_entry *seg_tab, *s; + TTF_USHORT *glyphId, format, segCount; + TTF_USHORT ncmapsubtabs, tmp_pid, tmp_eid; + TTF_ULONG cmap_offset, tmp_offset; + long n, i, k, length, index; + ttf_cmap_entry tmp_e, *p; + void **aa; + + /* loop up in ttf_cmap_tree first, return if found */ + tmp_e.ttf_name = ttf_name; + tmp_e.pid = pid; + tmp_e.eid = eid; + if (ttf_cmap_tree == NULL) { + ttf_cmap_tree = avl_create (comp_ttf_cmap_entry, NULL, &avl_xallocator); + assert (ttf_cmap_tree != NULL); + } + p = (ttf_cmap_entry *) avl_find (ttf_cmap_tree, &tmp_e); + if (p != NULL) + return p; + + /* not found, have to read it */ + 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_offset = ttf_curbyte - 2 * TTF_USHORT_SIZE; + cmap_tab = xtalloc (ncmapsubtabs, cmap_entry); + for (i = 0; i < ncmapsubtabs; ++i) { + tmp_pid = get_ushort (); + tmp_eid = get_ushort (); + tmp_offset = get_ulong (); + if (tmp_pid == pid && tmp_eid == eid) { + ttf_seek_off (cmap_offset + tmp_offset); + format = get_ushort (); + if (format == 4) + goto read_cmap_format_4; + else { + if (warn) + pdftex_warn ("cmap format %i unsupported", format); + return NULL; + } + } + } + if (warn) + pdftex_warn ("cannot find cmap subtable for (pid,eid) = (%i, %i)", + pid, eid); + return NULL; + read_cmap_format_4: + /* initialize the new entry */ + p = new_ttf_cmap_entry (); + p->ttf_name = xstrdup (ttf_name); + p->pid = pid; + p->eid = eid; + p->table = xtalloc (0x10000, short); + for (i = 0; i < 0x10000; ++i) + p->table[i] = -1; /* unassigned yet */ + + /* read the subtable */ + length = get_ushort (); /* length of subtable */ + (void) get_ushort (); /* skip the version number */ + segCount = get_ushort () / 2; + (void) get_ushort (); /* skip searchRange */ + (void) get_ushort (); /* skip entrySelector */ + (void) get_ushort (); /* skip rangeShift */ + seg_tab = xtalloc (segCount, seg_entry); + for (s = seg_tab; s - seg_tab < segCount; s++) + s->endCode = get_ushort (); + (void) 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 %li out of range [0..%i)", + index, glyphs_count); + if (p->table[i] != -1) + pdftex_warn + ("cmap: multiple glyphs are mapped to unicode %.4lX, " + "only %i will be used (glyph %li being ignored)", i, + p->table[i], index); + else + p->table[i] = index; + } + } + } + xfree (seg_tab); + xfree (glyphId); + aa = avl_probe (ttf_cmap_tree, p); + assert (aa != NULL); + return p; +} + +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 (); +} + +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 \ + ((256)*TTF_BYTE_SIZE + 3*TTF_USHORT_SIZE) + +static void ttf_byte_encoding (void) +{ + ttfenc_entry *e; + (void) put_ushort (0); /* format number (0: byte encoding table) */ + (void) put_ushort (BYTE_ENCODING_LENGTH); /* length of table */ + (void) put_ushort (0); /* version number */ + for (e = ttfenc_tab; e - ttfenc_tab < 256; 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 + (256))) + +static void ttf_trimmed_table_map (void) +{ + ttfenc_entry *e; + (void) put_ushort (6); /* format number (6): trimmed table mapping */ + (void) put_ushort (TRIMMED_TABLE_MAP_LENGTH); + (void) put_ushort (0); /* version number (0) */ + (void) put_ushort (0); /* first character code */ + (void) put_ushort (256); /* number of character code in table */ + for (e = ttfenc_tab; e - ttfenc_tab < 256; e++) + (void) put_ushort (e->newindex); +} + +#define SEG_MAP_DELTA_LENGTH ((16 + (256))*TTF_USHORT_SIZE) + +static void ttf_seg_map_delta (void) +{ + ttfenc_entry *e; + (void) put_ushort (4); /* format number (4: segment mapping to delta values) */ + (void) put_ushort (SEG_MAP_DELTA_LENGTH); + (void) put_ushort (0); /* version number */ + (void) put_ushort (4); /* 2*segCount */ + (void) put_ushort (4); /* searchRange */ + (void) put_ushort (1); /* entrySelector */ + (void) put_ushort (0); /* rangeShift */ + (void) put_ushort (0xF0FF); /* endCount[0] */ + (void) put_ushort (0xFFFF); /* endCount[1] */ + (void) put_ushort (0); /* reversedPad */ + (void) put_ushort (0xF000); /* startCount[0] */ + (void) put_ushort (0xFFFF); /* startCount[1] */ + (void) put_ushort (0); /* idDelta[0] */ + (void) put_ushort (1); /* idDelta[1] */ + (void) put_ushort (2 * TTF_USHORT_SIZE); /* idRangeOffset[0] */ + (void) put_ushort (0); /* idRangeOffset[1] */ + for (e = ttfenc_tab; e - ttfenc_tab < 256; e++) + (void) 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); + (void) put_ushort (0); /* table version number (0) */ + (void) 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)"); + } + (void) put_ushort (ce->platform_id); + (void) 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) +{ + const boolean is_unicode = (name_tab[index].platform_id == 3); + int i; + assert (index > 0 && index < name_record_num && fd_cur->subset_tag != NULL); + if (is_unicode) { + for (i = 0; i < 6; ++i) { + *p++ = 0; + *p++ = fd_cur->subset_tag[i]; + } + *p++ = 0; + *p++ = '+'; + return 14; + } else { + strncpy (p, fd_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 (fd_cur->fm)) { + 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); + (void) put_ushort (0); /* Format selector */ + (void) put_ushort (name_record_num); + (void) put_ushort (3 * TTF_USHORT_SIZE + + name_record_num * 6 * TTF_USHORT_SIZE); + for (i = 0; i < name_record_num; i++) { + (void) put_ushort (name_tab[i].platform_id); + (void) put_ushort (name_tab[i].encoding_id); + (void) put_ushort (name_tab[i].language_id); + (void) put_ushort (name_tab[i].name_id); + (void) put_ushort (name_tab[i].new_length); + (void) 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; + const integer save_offset = ttf_offset (); + ttf_seek_outbuf (TABDIR_OFF); + if (is_subsetted (fd_cur->fm)) { + 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 < (unsigned) 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) +{ + long *id, k; + TTF_USHORT idx; + TTF_USHORT flags; + dirtab_entry *tab = ttf_name_lookup ("glyf", true); + const long glyf_offset = tab->offset; + const 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 + */ + } + (void) 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; + int index; + short *t; + ttf_cmap_entry *cmap = NULL; + boolean cmap_not_found = false; + + /* + * 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 < 256; e++) { + e->newindex = 0; /* index of ".notdef" glyph */ + + /* handle case of subfonts first */ + if (is_subfont(fd_cur->fm)) { + if (e->code == -1) + continue; + assert(fd_cur->fm->pid != -1 && fd_cur->fm->eid != -1); + if (cmap == NULL && !cmap_not_found) { + cmap = + ttf_read_cmap(fd_cur->fm->ff_name, fd_cur->fm->pid, + fd_cur->fm->eid, true); + if (cmap == NULL) + cmap_not_found = true; + } + if (cmap == NULL) + continue; + t = cmap->table; + assert(t != NULL && e->code < 0x10000); + if (t[e->code] < 0) { + pdftex_warn + ("subfont %s: wrong mapping: character %li --> 0x%4.4lX --> .notdef", + fd_cur->fm->tfm_name, (long) (e - ttfenc_tab), e->code); + continue; + } + assert(t[e->code] >= 0 && t[e->code] < glyphs_count); /* t has been read from ttf */ + glyph = glyph_tab + t[e->code]; + goto append_new_glyph; + } + + /* handle case of reencoded fonts */ + 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) { + if (cmap == NULL && !cmap_not_found) { + /* need to read the unicode mapping, ie (pid,eid) = (3,1) or (0,3) */ + cmap = ttf_read_cmap(fd_cur->fm->ff_name, 3, 1, false); + if (cmap == NULL) + cmap = ttf_read_cmap(fd_cur->fm->ff_name, 0, 3, false); + if (cmap == NULL) { + pdftex_warn + ("no unicode mapping found, all `uniXXXX' names will be ignored"); + cmap_not_found = true; /* once only */ + } + } + if (cmap == NULL) + continue; + t = cmap->table; + assert(t != NULL); + if (t[index] != -1) { + if (t[index] >= glyphs_count) { + pdftex_warn + ("`%s' is mapped to index %i which is out of valid range [0..%i)", + e->name, t[index], glyphs_count); + continue; + } + glyph = glyph_tab + t[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 && glyph - glyph_tab < glyphs_count); + if (glyph->newindex < 0) { + glyph_index[new_glyphs_count] = (short) (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(fd_cur->fm)) { + (void) put_short (loca_format); + (void) 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); + (void) put_ushort (new_glyphs_count); + ttf_set_chksm (tab); +} + +static void ttf_write_htmx (void) +{ + long *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) +{ + long *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++) + (void) put_ushort (glyph_tab[*id].newoffset / 2); + (void) 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); + (void) 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 > 3) + pdftex_fail ("unknown version of OS/2 table (%.4X)", version); + (void) 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); + (void) put_ushort (0x0000); /* usFirstCharIndex */ + (void) 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; + long *id; + int l; + ttf_reset_chksm (tab); + if (!fd_cur->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); + (void) 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++; + (void) 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 */ + (void) put_ushort (n); /* number of tables */ + (void) put_ushort (i << 3); /* search range */ + (void) put_ushort (k - 1); /* entry selector */ + (void) 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(fd_entry * fd) +{ + int callback_id; + int file_opened = 0; + char *ftemp = NULL; + fd_cur = fd; /* fd_cur is global inside writettf.c */ + assert(fd_cur->fm != NULL); + assert(is_truetype(fd_cur->fm)); + assert(is_included(fd_cur->fm)); + + set_cur_file_name(fd_cur->fm->ff_name); + + if (is_subsetted(fd_cur->fm) && (fd_cur->fe == NULL) + && !is_subfont(fd_cur->fm)) { + pdftex_warn ("Subset TrueType must be a reencoded or a subfont"); + cur_file_name = NULL; + return; + } + ttf_curbyte=0; + ttf_size=0; + callback_id=callback_defined(find_truetype_file_callback); + if (callback_id>0) { + if(run_callback(callback_id,"S->S",(char *)(nameoffile+1),&ftemp)) { + if(ftemp!=NULL&&strlen(ftemp)) { + free(nameoffile); + namelength = strlen(ftemp); + nameoffile = xmalloc(namelength+2); + strcpy((char *)(nameoffile+1),ftemp); + free(ftemp); + } + } + } + + callback_id=callback_defined(read_truetype_file_callback); + if (callback_id>0) { + if(run_callback(callback_id,"S->bSd",(char *)(nameoffile+1), + &file_opened, &ttf_buffer,&ttf_size) && + file_opened && ttf_size>0) { + } else { + pdftex_fail ("cannot open TrueType font file for reading"); + } + } else { + if (!ttf_open ()) { + pdftex_fail ("cannot open TrueType font file for reading"); + } + ttf_read_file(); + ttf_close(); + } + cur_file_name = (char *) nameoffile + 1; + if (tracefilenames) { + if (is_subsetted(fd_cur->fm)) + tex_printf ("<%s", cur_file_name); + else + tex_printf ("<<%s", cur_file_name); + } + fd_cur->ff_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 (); + + pdf_save_offset = pdfoffset (); + pdf_flush (); + + if (is_subsetted(fd_cur->fm)) { + ttf_copy_encoding (); + 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); + if (tracefilenames) { + if (is_subsetted (fd_cur->fm)) + tex_printf (">"); + else + tex_printf (">>"); + } + cur_file_name = NULL; +} + +void do_writeotf(fd_entry * fd) +{ + long i; + dirtab_entry *tab; + dir_tab = NULL; + glyph_tab = NULL; + if (tracefilenames) + tex_printf ("<<%s", cur_file_name); + 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 ();*/ + if (tracefilenames) + tex_printf (">>"); +} + +void writeotf (fd_entry * fd) { + int callback_id; + int file_opened = 0; + char *ftemp = NULL; + + + fd_cur = fd; /* fd_cur is global inside writettf.c */ + assert(fd_cur->fm != NULL); + assert(is_opentype(fd_cur->fm)); + assert(is_included(fd_cur->fm)); + + set_cur_file_name(fd_cur->fm->ff_name); + ttf_curbyte=0; + ttf_size=0; + callback_id=callback_defined(find_opentype_file_callback); + if (callback_id>0) { + if(run_callback(callback_id,"S->S",(char *)(nameoffile+1),&ftemp)) { + if(ftemp!=NULL&&strlen(ftemp)) { + free(nameoffile); + namelength = strlen(ftemp); + nameoffile = xmalloc(namelength+2); + strcpy((char *)(nameoffile+1),ftemp); + free(ftemp); + } + } + } + callback_id=callback_defined(read_opentype_file_callback); + if (callback_id>0) { + if(run_callback(callback_id,"S->bSd",(char *)(nameoffile+1), + &file_opened, &ttf_buffer,&ttf_size) && + file_opened && ttf_size>0) { + } else { + pdftex_fail ("cannot open OpenType font file for reading"); + } + } else { + if (!otf_open ()) { + pdftex_fail ("cannot open OpenType font file for reading"); + } + ttf_read_file(); + ttf_close(); + } + + cur_file_name = (char *) nameoffile + 1; + fd_cur->ff_found = true; + do_writeotf(fd); + 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/luatexdir/font/writettf.h b/Build/source/texk/web2c/luatexdir/font/writettf.h new file mode 100644 index 00000000000..ecfaa2c37e3 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/font/writettf.h @@ -0,0 +1,172 @@ +/* +Copyright (c) 1996-2006 Han The Thanh, + +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: writettf.h 1013 2008-02-14 00:09:02Z oneiros $ +*/ + +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) (void)put_num(TTF_CHAR, n) +#define put_byte(n) (void)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) (void)put_num(TTF_ULONG, n) +#define put_fixed(n) (void)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) (void)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" + +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; + +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; + +/* some functions and variables are used by writetype0.c */ + +extern fd_entry *fd_cur; /* pointer to the current font descriptor */ +extern unsigned char *ttf_buffer; +extern integer ttf_size; +extern integer ttf_curbyte; +extern glyph_entry *glyph_tab; +extern dirtab_entry *dir_tab; +extern dirtab_entry *ttf_name_lookup (const char *s, boolean required); +extern dirtab_entry *ttf_seek_tab (const char *name, TTF_LONG offset); + +extern void ttf_read_tabdir (void); +extern void ttf_read_head (void); +extern void ttf_read_hhea (void); +extern void ttf_read_pclt (void); +extern void ttf_read_post (void); + +extern FILE *ttf_file; + +#define ttf_open() \ + open_input(&ttf_file, kpse_truetype_format, FOPEN_RBIN_MODE) +#define otf_open() \ + open_input(&ttf_file, kpse_opentype_format, FOPEN_RBIN_MODE) +#define ttf_read_file() \ + readbinfile(ttf_file,&ttf_buffer,&ttf_size) +#define ttf_close() xfclose(ttf_file,cur_file_name) +#define ttf_getchar() ttf_buffer[ttf_curbyte++] +#define ttf_eof() (ttf_curbyte>ttf_size) + +extern long ttf_putnum (int s, long n); +extern long ttf_getnum (int s); + + diff --git a/Build/source/texk/web2c/luatexdir/font/writetype0.c b/Build/source/texk/web2c/luatexdir/font/writetype0.c new file mode 100644 index 00000000000..0f9eecaac7c --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/font/writetype0.c @@ -0,0 +1,124 @@ +/* +Copyright (c) 2007 Taco Hoekwater, taco@luatex.org + +This file is part of luaTeX. + +luaTeX 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. + +luaTeX 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 luaTeX; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +$Id: writetype0.c 1013 2008-02-14 00:09:02Z oneiros $ +*/ + +#include "ptexlib.h" + +#include "writettf.h" + +#include "writecff.h" + +void writetype0 (fd_entry * fd) { + int callback_id; + int file_opened = 0; + char *ftemp = NULL; + long i; + dirtab_entry *tab; + cff_font *cff; + + dir_tab = NULL; + glyph_tab = NULL; + + fd_cur = fd; /* fd_cur is global inside writettf.c */ + assert(fd_cur->fm != NULL); + assert(is_opentype(fd_cur->fm)); + assert(is_included(fd_cur->fm)); + + set_cur_file_name(fd_cur->fm->ff_name); + ttf_curbyte=0; + ttf_size=0; + callback_id=callback_defined(find_opentype_file_callback); + if (callback_id>0) { + if(run_callback(callback_id,"S->S",(char *)(nameoffile+1),&ftemp)) { + if(ftemp!=NULL&&strlen(ftemp)) { + free(nameoffile); + namelength = strlen(ftemp); + nameoffile = xmalloc(namelength+2); + strcpy((char *)(nameoffile+1),ftemp); + free(ftemp); + } + } + } + callback_id=callback_defined(read_opentype_file_callback); + if (callback_id>0) { + if(run_callback(callback_id,"S->bSd",(char *)(nameoffile+1), + &file_opened, &ttf_buffer,&ttf_size) && + file_opened && ttf_size>0) { + } else { + pdftex_fail ("cannot open OpenType font file for reading"); + } + } else { + if (!otf_open ()) { + pdftex_fail ("cannot open OpenType font file for reading"); + } + ttf_read_file(); + ttf_close(); + } + + cur_file_name = (char *) nameoffile + 1; + fd_cur->ff_found = true; + + if (tracefilenames) { + if (is_subsetted(fd_cur->fm)) + tex_printf ("<%s", cur_file_name); + else + tex_printf ("<<%s", cur_file_name); + } + 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); + + /* TODO the next 0 is a subfont index */ + cff = read_cff(ttf_buffer+ttf_curbyte,tab->length,0); + if (cff != NULL) { + if (cff_is_cidfont(cff)) { + write_cid_cff(cff,fd_cur,0); + /* + for (i = tab->length; i > 0; i--) + fb_putchar (ttf_getnum(1)); + */ + } else { + write_cff(cff,fd_cur,0); + } + } else { + /* not understood, just do a copy */ + for (i = tab->length; i > 0; i--) + fb_putchar (ttf_getnum(1)); + } + xfree (dir_tab); + if (tracefilenames) { + if (is_subsetted (fd_cur->fm)) + tex_printf (">"); + else + tex_printf (">>"); + } + cur_file_name = NULL; +} diff --git a/Build/source/texk/web2c/luatexdir/font/writetype2.c b/Build/source/texk/web2c/luatexdir/font/writetype2.c new file mode 100644 index 00000000000..649c350b707 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/font/writetype2.c @@ -0,0 +1,422 @@ + +/* +Copyright (c) 2007 Taco Hoekwater, taco@luatex.org + +This file is part of luaTeX. + +luaTeX 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. + +luaTeX 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 luaTeX; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +$Id: writetype2.c 1013 2008-02-14 00:09:02Z oneiros $ +*/ + +#include "ptexlib.h" +#include "writettf.h" +#include "writecff.h" + +#include "sfnt.h" +#include "tt_glyf.h" + +/* forward*/ +void make_tt_subset (fd_entry * fd,unsigned char *buffer, integer buflen) ; + +unsigned long cidtogid_obj = 0; + +/* low-level helpers */ + +#define test_loc(l) \ + if ((f->loc+l)>f->buflen) { \ + fprintf (stderr,"File ended prematurely\n"); \ + uexit(1); \ + } + + +BYTE get_unsigned_byte(sfnt* f) { + test_loc(1); + return (BYTE)f->buffer[(f->loc++)]; +}; + +ICHAR get_signed_byte(sfnt* f) { + test_loc(1); + return (ICHAR)f->buffer[(f->loc++)]; +}; + +USHORT get_unsigned_pair(sfnt* f){ + USHORT l; + test_loc(2); + l = f->buffer[(f->loc++)]; + l = l*0x100 + f->buffer[(f->loc++)]; + return l; +}; + +SHORT get_signed_pair(sfnt* f){ + long l; + test_loc(2); + l = f->buffer[(f->loc++)]; + if (l>0x80) l -= 0x100; + l = l*0x100 + f->buffer[(f->loc++)]; + return l; +}; + +ULONG get_unsigned_quad(sfnt* f){ + ULONG l; + test_loc(4); + l = f->buffer[(f->loc++)]; + l = l*0x100 + f->buffer[(f->loc++)]; + l = l*0x100 + f->buffer[(f->loc++)]; + l = l*0x100 + f->buffer[(f->loc++)]; + return l; +}; + +int do_sfnt_read (unsigned char *dest, int len, sfnt *f) { + int i; + test_loc(len); + for (i=0;ibuffer[f->loc+i]; + } + f->loc += len; + return len; +}; + +pdf_obj *pdf_new_stream(void) { + pdf_obj *stream = xmalloc(sizeof(pdf_obj)) ; + stream->length =0; + stream->data=NULL; + return stream; +}; + +void pdf_add_stream(pdf_obj *stream, unsigned char *buf, long len) { + int i; + assert (stream!=NULL); + if (stream->data==NULL) { + stream->data = xmalloc(len); + } else { + stream->data = xrealloc(stream->data,len+stream->length); + } + for (i=0;idata+stream->length+i)=*(buf+i); + } + stream->length+=len; +}; + +void pdf_release_obj(pdf_obj *stream) { + if (stream!=NULL) { + if (stream->data!=NULL) { + xfree(stream->data); + } + xfree(stream); + } +}; + + +void +writetype2 (fd_entry * fd) { + int callback_id; + int file_opened = 0; + char *ftemp = NULL; + + glyph_tab = NULL; + + fd_cur = fd; /* fd_cur is global inside writettf.c */ + assert(fd_cur->fm != NULL); + assert(is_truetype(fd_cur->fm)); + + if (!is_subsetted(fd_cur->fm)) { + writettf(fd); + return; + } + + assert(is_included(fd_cur->fm)); + + set_cur_file_name(fd_cur->fm->ff_name); + ttf_curbyte=0; + ttf_size=0; + callback_id=callback_defined(find_opentype_file_callback); + if (callback_id>0) { + if(run_callback(callback_id,"S->S",(char *)(nameoffile+1),&ftemp)) { + if(ftemp!=NULL&&strlen(ftemp)) { + free(nameoffile); + namelength = strlen(ftemp); + nameoffile = xmalloc(namelength+2); + strcpy((char *)(nameoffile+1),ftemp); + free(ftemp); + } + } + } + callback_id=callback_defined(read_opentype_file_callback); + if (callback_id>0) { + if(run_callback(callback_id,"S->bSd",(char *)(nameoffile+1), + &file_opened, &ttf_buffer,&ttf_size) && + file_opened && ttf_size>0) { + } else { + pdftex_fail ("cannot open OpenType font file for reading"); + } + } else { + if (!otf_open ()) { + pdftex_fail ("cannot open OpenType font file for reading"); + } + ttf_read_file(); + ttf_close(); + } + + cur_file_name = (char *) nameoffile + 1; + fd_cur->ff_found = true; + + if (tracefilenames) { + if (is_subsetted(fd_cur->fm)) + tex_printf ("<%s", cur_file_name); + else + tex_printf ("<<%s", cur_file_name); + } + + /* here is the real work */ + + make_tt_subset(fd,ttf_buffer,ttf_size); + + /*xfree (dir_tab);*/ + if (tracefilenames) { + if (is_subsetted (fd_cur->fm)) + tex_printf (">"); + else + tex_printf (">>"); + } + cur_file_name = NULL; +} + +/* + * PDF viewer applications use following tables (CIDFontType 2) + * + * head, hhea, loca, maxp, glyf, hmtx, fpgm, cvt_, prep + * + * - from PDF Ref. v.1.3, 2nd ed. + * + * The fpgm, cvt_, and prep tables appears only when TrueType instructions + * requires them. Those tables must be preserved if they exist. + * We use must_exist flag to indicate `preserve it if present' + * and to make sure not to cause an error when it does not exist. + * + * post and name table must exist in ordinary TrueType font file, + * but when a TrueType font is converted to CIDFontType 2 font, those tables + * are no longer required. + * + * The OS/2 table (required for TrueType font for Windows and OS/2) contains + * liscencing information, but PDF viewers seems not using them. + * + * The 'name' table added. See comments in ttf.c. + */ + +static struct +{ + const char *name; + int must_exist; +} required_table[] = { + {"OS/2", 0}, {"head", 1}, {"hhea", 1}, {"loca", 1}, {"maxp", 1}, + {"name", 1}, {"glyf", 1}, {"hmtx", 1}, {"fpgm", 0}, {"cvt ", 0}, + {"prep", 0}, {NULL, 0} +}; + + +unsigned long ttc_read_offset (sfnt *sfont, int ttc_idx) +{ + long version; + unsigned long offset = 0; + unsigned long num_dirs = 0; + + sfnt_seek_set (sfont, 4); /* skip version tag */ + + version = sfnt_get_ulong(sfont); + num_dirs = sfnt_get_ulong(sfont); + if (ttc_idx < 0 || ttc_idx > num_dirs - 1) { + fprintf(stderr,"Invalid TTC index number\n"); + uexit(1); + } + + sfnt_seek_set (sfont, 12 + ttc_idx * 4); + offset = sfnt_get_ulong (sfont); + + return offset; +} + +extern int ff_get_ttc_index(char *ffname, char*psname); + +void make_tt_subset (fd_entry * fd,unsigned char *buffer, integer buflen) { + + long i, cid; + unsigned int last_cid; + glw_entry *glyph, *found; + struct avl_traverser t; + unsigned char *cidtogidmap ; + unsigned short num_glyphs, gid; + struct tt_glyphs *glyphs; + char *used_chars; + sfnt *sfont; + pdf_obj *fontfile; + int verbose = 0, error = 0; + + cidtogidmap = NULL; + + sfont = sfnt_open(buffer, buflen); + + if (sfont->type == SFNT_TYPE_TTC) { + i = ff_get_ttc_index(fd->fm->ff_name,fd->fm->ps_name); + error = sfnt_read_table_directory(sfont, ttc_read_offset(sfont, i)); + } else { + error = sfnt_read_table_directory(sfont, 0); + } + + if (error < 0) { + fprintf(stderr,"Could not parse the ttf directory.\n"); + uexit(1); + } + + glyphs = tt_build_init(); + + last_cid = 0; + num_glyphs = 1; /* .notdef */ + + glyph = xtalloc(1,glw_entry); + + avl_t_init(&t, fd->gl_tree); + for (found = (glw_entry *) avl_t_first(&t, fd->gl_tree); + found != NULL; + found = (glw_entry *) avl_t_next(&t)) { + if (found->id > last_cid) + last_cid = found->id; + } + +#ifndef NO_GHOSTSCRIPT_BUG + cidtogidmap = NULL; +#else + cidtogidmap = xmalloc(((last_cid + 1) * 2) * sizeof(unsigned char)); + memset(cidtogidmap, 0, (last_cid + 1) * 2); +#endif + + /* fill used_chars */ + used_chars = xmalloc((last_cid + 1) * sizeof(char)); + memset(used_chars, 0, (last_cid + 1)); + avl_t_init(&t, fd->gl_tree); + for (found = (glw_entry *) avl_t_first(&t, fd->gl_tree); + found != NULL; + found = (glw_entry *) avl_t_next(&t)) { + used_chars[found->id] = 1; + } + + /* + * Map CIDs to GIDs. + */ + + num_glyphs = 1; /* .notdef */ + for (cid = 1; cid <= last_cid; cid++) { + if (used_chars[cid]==0) + continue; + gid = cid; + + +#ifndef NO_GHOSTSCRIPT_BUG + gid = tt_add_glyph(glyphs, gid, cid); +#else + gid = tt_add_glyph(glyphs, gid, num_glyphs); + cidtogidmap[2*cid ] = gid >> 8; + cidtogidmap[2*cid+1] = gid & 0xff; +#endif /* !NO_GHOSTSCRIPT_BUG */ + + num_glyphs++; + } + + if (num_glyphs==1) { + fprintf(stderr,"No glyphs in subset?.\n"); + uexit(1); + } + + if (tt_build_tables(sfont, glyphs) < 0) { + fprintf(stderr,"Could not parse the ttf buffer.\n"); + uexit(1); + } + + if (verbose > 1) { + fprintf(stdout,"[%u glyphs (Max CID: %u)]", glyphs->num_glyphs, last_cid); + } + + tt_build_finish(glyphs); + + /* Create font file */ + + for (i = 0; required_table[i].name; i++) { + if (sfnt_require_table(sfont, + required_table[i].name, + required_table[i].must_exist) < 0) { + fprintf(stderr,"Some required TrueType table does not exist."); + uexit(1); + } + } + + fontfile = sfnt_create_FontFile_stream(sfont); + + if (verbose > 1) { + fprintf(stdout,"[%ld bytes]", fontfile->length); + } + + /* squeeze in the cidgidmap */ + if (cidtogidmap!=NULL) { + cidtogid_obj = pdf_new_objnum(); + pdf_begin_dict(cidtogid_obj, 0); + pdf_printf("/Length %i\n",((last_cid + 1) * 2)); + pdf_end_dict(); + pdf_printf("stream\n"); + pdfroom ((last_cid + 1) * 2); + for (i = 0; i<((last_cid + 1) * 2); i++ ) { + pdf_buf[pdf_ptr++] = cidtogidmap[i]; + } + pdf_printf("\nendstream\n"); + } + + /* the tff subset */ + for (i = 0; ilength; i++ ) + fb_putchar (fontfile->data[i]); + + + /* other stuff that needs fixing: */ + + /* + * DW, W, DW2, and W2 + */ + /* + if (opt_flags & CIDFONT_FORCE_FIXEDPITCH) { + pdf_add_dict(font->fontdict, + pdf_new_name("DW"), pdf_new_number(1000.0)); + } else { + add_TTCIDHMetrics(font->fontdict, glyphs, used_chars, cidtogidmap, last_cid); + if (v_used_chars) + add_TTCIDVMetrics(font->fontdict, glyphs, used_chars, cidtogidmap, last_cid); + } + */ + + /* + * CIDSet + */ + /* + { + pdf_obj *cidset; + + cidset = pdf_new_stream(STREAM_COMPRESS); + pdf_add_stream(cidset, used_chars, last_cid/8 + 1); + pdf_add_dict(font->descriptor, + pdf_new_name("CIDSet"), + pdf_ref_obj(cidset)); + pdf_release_obj(cidset); + } + */ + + return; +} diff --git a/Build/source/texk/web2c/luatexdir/hyphen.h b/Build/source/texk/web2c/luatexdir/hyphen.h new file mode 100644 index 00000000000..f665c7605b9 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/hyphen.h @@ -0,0 +1,60 @@ +/* LibHnj is dual licensed under LGPL and MPL. Boilerplate for both + * licenses follows. + */ + +/* LibHnj - a library for high quality hyphenation and justification + * Copyright (C) 1998 Raph Levien, (C) 2001 ALTLinux, Moscow + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307 USA. +*/ + +/* + * The contents of this file are subject to the Mozilla Public License + * Version 1.0 (the "MPL"); you may not use this file except in + * compliance with the MPL. You may obtain a copy of the MPL at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the MPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL + * for the specific language governing rights and limitations under the + * MPL. + * + */ +#ifndef __HYPHEN_H__ +#define __HYPHEN_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +typedef struct _HyphenDict HyphenDict; + +#include "ptexlib.h" +#include "nodes.h" + +HyphenDict* hnj_hyphen_new(); +void hnj_hyphen_load(HyphenDict*dict, const unsigned char *fn); +void hnj_hyphen_free (HyphenDict *dict); +void hnj_hyphen_clear (HyphenDict *dict); +void hnj_hyphen_hyphenate (HyphenDict *dict, halfword first, halfword last, int size, halfword left, halfword right, lang_variables*lan); +unsigned char* hnj_serialize(HyphenDict*); +void hnj_free_serialize(unsigned char*); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __HYPHEN_H__ */ diff --git a/Build/source/texk/web2c/luatexdir/image/.indent.pro b/Build/source/texk/web2c/luatexdir/image/.indent.pro new file mode 100644 index 00000000000..e9e690f1ba8 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/image/.indent.pro @@ -0,0 +1,12 @@ +/* $Id$ */ +--k-and-r-style +--blank-lines-after-procedures +--line-length 80 +--procnames-start-lines +--no-space-after-function-call-names +--dont-break-procedure-type +--space-after-cast +/* this does not work in indent 2.2.6 :-( */ +--no-tabs +/* this is new in indent 2.2.9 */ +--preprocessor-indentation 2 diff --git a/Build/source/texk/web2c/luatexdir/image/epdf.c b/Build/source/texk/web2c/luatexdir/image/epdf.c new file mode 100644 index 00000000000..071181f17bd --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/image/epdf.c @@ -0,0 +1,107 @@ +/* +Copyright (c) 1996-2002 Han The Thanh, + +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: epdf.c 1012 2008-02-14 00:00:57Z oneiros $ +*/ + +#include "ptexlib.h" + + +#include +#include +#include + +extern void epdf_check_mem(void); +extern void register_fd_entry(fd_entry *); + + +int is_subsetable(fm_entry * fm) +{ + assert(is_included(fm)); + return is_subsetted(fm); +} + +fd_entry *epdf_create_fontdescriptor(fm_entry * fm) +{ + fd_entry *fd; + if ((fd = lookup_fd_entry(fm->ff_name, fm->slant, fm->extend)) == NULL) { + fm->in_use = true; + fd = new_fd_entry(); + fd->fm = fm; + register_fd_entry(fd); + fd->fd_objnum = pdf_new_objnum(); + assert(fm->ps_name != NULL); + fd->fontname = xstrdup(fm->ps_name); /* just fallback */ + /* preset_fontmetrics (fo->fd, f); */ + fd->gl_tree = avl_create(comp_string_entry, NULL, &avl_xallocator); + assert(fd->gl_tree != NULL); + } + return fd; +} + +integer get_fd_objnum(fd_entry * fd) +{ + assert(fd->fd_objnum != 0); + return fd->fd_objnum; +} + +integer get_fn_objnum(fd_entry * fd) +{ + if (fd->fn_objnum == 0) + fd->fn_objnum = pdf_new_objnum(); + return fd->fn_objnum; +} + +/*********************************************************************** + * Mark glyphs used by embedded PDF file: + * 1. build fontdescriptor, if not yet existing + * 2. mark glyphs directly there + * + * Input charset from xpdf is a string of glyph names including + * leading slashes, but without blanks between them, like: /a/b/c +***********************************************************************/ + +void epdf_mark_glyphs(fd_entry * fd, char *charset) +{ + char *p, *q, *s; + char *glyph; + void **aa; + if (charset == NULL) + return; + assert(fd != NULL); + for (s = charset + 1, q = charset + strlen(charset); s < q; s = p + 1) { + for (p = s; *p != '\0' && *p != '/'; p++); + *p = '\0'; + if ((char *) avl_find(fd->gl_tree, s) == NULL) { + glyph = xstrdup(s); + aa = avl_probe(fd->gl_tree, glyph); + assert(aa != NULL); + } + } +} + +void embed_whole_font(fd_entry * fd) +{ + fd->all_glyphs = true; +} + +void epdf_free(void) +{ + epdf_check_mem(); +} diff --git a/Build/source/texk/web2c/luatexdir/image/epdf.h b/Build/source/texk/web2c/luatexdir/image/epdf.h new file mode 100644 index 00000000000..2359d53d3db --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/image/epdf.h @@ -0,0 +1,125 @@ +/* +Copyright (c) 1996-2006 Han The Thanh, + +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: epdf.h 1031 2008-02-14 23:03:20Z hhenkel $ +*/ + +extern "C" { + +#include + + extern char *xstrdup(const char *); + +/* the following code is extremly ugly but needed for including web2c/config.h */ + +#include /* 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 /* define SIZEOF_LONG */ +#include /* define type integer */ + +#include +#include "openbsd-compat.h" +#include "image.h" + +/* #-define pdfbufsize pdfbufmax */ + + extern integer epdf_page_box; + extern void *epdf_xref; + + extern integer pdf_box_spec_media; + extern integer pdf_box_spec_crop; + extern integer pdf_box_spec_bleed; + extern integer pdf_box_spec_trim; + extern integer pdf_box_spec_art; + + extern integer pdf_stream_length; + extern integer pdf_ptr; + extern integer pool_ptr; + typedef unsigned char eight_bits; + extern eight_bits *pdf_buf; + extern integer pdf_buf_size; + extern integer pdf_os_mode; + extern eight_bits pdf_last_byte; + + extern char notdef[]; + + extern integer fixed_replace_font; + + extern int is_subsetable(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 pdf_new_objnum(void); + extern void read_pdf_info(image_dict *, integer, integer); + extern void embed_whole_font(struct fd_entry *); + extern void epdf_check_mem(void); + extern void epdf_delete(image_dict *); + extern void epdf_free(void); + __attribute__ ((format(printf, 1, 2))) + extern void pdf_printf(const char *fmt, ...); + extern void pdf_puts(const char *); + extern void pdf_begin_stream(void); + extern void pdf_end_obj(void); + extern void pdf_end_stream(void); + extern void pdf_flush(void); + __attribute__ ((noreturn, format(printf, 1, 2))) + extern void pdftex_fail(const char *fmt, ...); + __attribute__ ((format(printf, 1, 2))) + extern void pdftex_warn(const char *fmt, ...); + __attribute__ ((format(printf, 1, 2))) + extern void tex_printf(const char *, ...); + extern void write_epdf(image_dict *); + extern void zpdf_begin_dict(integer, bool); + extern void zpdf_begin_obj(integer, bool); + extern void zpdf_create_obj(integer, integer); + extern void zpdf_new_dict(integer, integer, bool); + extern void zpdf_os_get_os_buf(integer); + +/* epdf.c */ + extern void epdf_mark_glyphs(struct fd_entry *, char *); + extern struct fd_entry *epdf_create_fontdescriptor(struct fm_entry *); + extern int get_fd_objnum(struct fd_entry *); + extern int get_fn_objnum(struct fd_entry *); + +/* write_enc.c */ + extern void epdf_write_enc(char **, integer); + +/* write_enc.c */ + extern pdf_img_struct *new_pdf_img_struct(void); + +/* utils.c */ + extern char *convertStringToPDFString(char *in, int len); + extern char *stripzeros(char *a); + +/* 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/luatexdir/image/image.h b/Build/source/texk/web2c/luatexdir/image/image.h new file mode 100644 index 00000000000..cf7d4f0dd88 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/image/image.h @@ -0,0 +1,223 @@ +/* +Copyright (c) 1996-2002 Han The Thanh, + +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: image.h 1100 2008-03-09 13:40:48Z hhenkel $ +*/ + +#ifndef IMAGE_H +# define IMAGE_H + +# include <../libpng/png.h> + +# define JPG_UINT16 unsigned int +# define JPG_UINT32 unsigned long +# define JPG_UINT8 unsigned char + +# define IMAGE_COLOR_B 1 +# define IMAGE_COLOR_C 2 +# define IMAGE_COLOR_I 4 + +extern integer zround(double); /* from zround.c */ +# define bp2int(p) zround(p * (one_hundred_bp / 100.0)) + +# define TYPE_IMG "image" +# define TYPE_IMG_DICT "image-dict" + +# define scaled integer + +/**********************************************************************/ + +typedef struct { + float width; + float height; + float orig_x; + float orig_y; + void *doc; +} pdf_img_struct; + +typedef struct { + png_structp png_ptr; + png_infop info_ptr; +} png_img_struct; + +typedef struct { + int color_space; /* used color space. See JPG_ constants */ + JPG_UINT32 length; /* length of file/data */ +} jpg_img_struct; + +typedef struct { /* currently unused */ +} jb2_img_struct; + +typedef enum { DICT_NEW, /* fresh dictionary */ + DICT_FILESCANNED, /* image file scanned */ + DICT_REFERED, /* pdf_refximage_node in node list --> read-only dict */ + DICT_OUTIMG, /* /Im* appears in pagestream */ + DICT_SCHEDULED, /* image dict scheduled for writing */ + DICT_WRITTEN /* image dict written to file */ +} dict_state; + +typedef enum { IMAGE_TYPE_NONE, IMAGE_TYPE_PDF, IMAGE_TYPE_PNG, IMAGE_TYPE_JPG, + IMAGE_TYPE_JBIG2, IMAGE_TYPE_SENTINEL +} imgtype_e; + +typedef enum { IMG_KEEPOPEN, IMG_CLOSEINBETWEEN } img_readtype_e; + +typedef enum { PDF_BOX_SPEC_NONE, PDF_BOX_SPEC_MEDIA, PDF_BOX_SPEC_CROP, + PDF_BOX_SPEC_BLEED, PDF_BOX_SPEC_TRIM, PDF_BOX_SPEC_ART, + PDF_BOX_SPEC_SENTINEL +} pdfboxspec_e; + +/**********************************************************************/ + +typedef struct { + integer objnum; + integer index; /* /Im1, /Im2, ... */ + integer x_size; /* dimensions in pixel counts as in JPG/PNG/JBIG2 file */ + integer y_size; + integer x_res; /* pixel resolution as in JPG/PNG/JBIG2 file */ + integer y_res; + integer colorspace; /* number of /ColorSpace object */ + integer total_pages; + integer page_num; /* requested page (by number) */ + char *pagename; /* requested page (by name) */ + char *filename; /* requested raw file name */ + char *filepath; /* full file path after kpathsea */ + char *attr; /* additional image dict entries */ + FILE *file; + imgtype_e image_type; + int color_space; /* used color space. See JPG_ constants */ + int color_depth; /* color depth */ + pdfboxspec_e page_box_spec; /* PDF page box spec.: media/crop/bleed/trim/art */ + dict_state state; + union { + pdf_img_struct *pdf; + png_img_struct *png; + jpg_img_struct *jpg; + jb2_img_struct *jb2; + } img_struct; +} image_dict; + +# define img_objnum(N) ((N)->objnum) +# define img_index(N) ((N)->index) +# define img_xsize(N) ((N)->x_size) +# define img_ysize(N) ((N)->y_size) +# define img_xres(N) ((N)->x_res) +# define img_yres(N) ((N)->y_res) +# define img_colorspace(N) ((N)->colorspace) +# define img_totalpages(N) ((N)->total_pages) +# define img_pagenum(N) ((N)->page_num) +# define img_pagename(N) ((N)->pagename) +# define img_filename(N) ((N)->filename) +# define img_filepath(N) ((N)->filepath) +# define img_attr(N) ((N)->attr) +# define img_file(N) ((N)->file) +# define img_type(N) ((N)->image_type) +# define img_color(N) ((N)->color_space) +# define img_colordepth(N) ((N)->color_depth) +# define img_pagebox(N) ((N)->page_box_spec) +# define img_state(N) ((N)->state) + +# define img_pdf_ptr(N) ((N)->img_struct.pdf) +# define img_pdf_width(N) ((N)->img_struct.pdf->width) +# define img_pdf_height(N) ((N)->img_struct.pdf->height) +# define img_pdf_orig_x(N) ((N)->img_struct.pdf->orig_x) +# define img_pdf_orig_y(N) ((N)->img_struct.pdf->orig_y) +# define img_pdf_doc(N) ((N)->img_struct.pdf->doc) + +# define img_png_ptr(N) ((N)->img_struct.png) +# define img_png_png_ptr(N) ((N)->img_struct.png->png_ptr) +# define img_png_info_ptr(N) ((N)->img_struct.png->info_ptr) + +# define img_jpg_ptr(N) ((N)->img_struct.jpg) +# define img_jpg_color(N) ((N)->img_struct.jpg->color_space) + +# define img_jb2_ptr(N) ((N)->img_struct.jb2) + +/**********************************************************************/ + +typedef struct { + integer width; /* requested/actual TeX dimensions */ + integer height; + integer depth; + integer transform; + integer flags; + image_dict *dict; + int dict_ref; /* luaL_ref() reference */ +} image; + +# define img_width(N) ((N)->width) +# define img_height(N) ((N)->height) +# define img_depth(N) ((N)->depth) +# define img_transform(N) ((N)->transform) +# define img_flags(N) ((N)->flags) +# define img_dict(N) ((N)->dict) +# define img_dictref(N) ((N)->dict_ref) + +# define F_FLAG_SCALED 0x01 +# define F_FLAG_REFERED 0x02 + +# define img_flags(N) ((N)->flags) +# define img_set_scaled(N) (img_flags(N) |= F_FLAG_SCALED) +# define img_set_refered(N) (img_flags(N) |= F_FLAG_REFERED) +# define img_unset_scaled(N) (img_flags(N) &= ~F_FLAG_SCALED) +# define img_unset_refered(N) (img_flags(N) &= ~F_FLAG_REFERED) +# define img_is_scaled(N) ((img_flags(N) & F_FLAG_SCALED) != 0) +# define img_is_refered(N) ((img_flags(N) & F_FLAG_REFERED) != 0) + +# define set_wd_running(N) (img_width(N) = null_flag) +# define set_ht_running(N) (img_height(N) = null_flag) +# define set_dp_running(N) (img_depth(N) = null_flag) +# define is_wd_running(N) (img_width(N) == null_flag) +# define is_ht_running(N) (img_height(N) == null_flag) +# define is_dp_running(N) (img_depth(N) == null_flag) + +/**********************************************************************/ + +/* writeimg.c */ + +image *new_image(); +image_dict *new_image_dict(); +void init_image(image *); +void init_image_dict(image_dict *); +void scale_img(image *); +integer img_to_array(image *); +void delete_image(image *); +void free_image_dict(image_dict * p); +void read_img(image_dict *, integer, integer); + +/* writepng.c */ + +# ifndef boolean /* TODO: from where to get the original definition? */ +# define boolean int +# endif + +void read_png_info(image_dict *, img_readtype_e); +void read_jpg_info(image_dict *, img_readtype_e); +void read_jbig2_info(image_dict *); +void read_pdf_info(image_dict *, integer, integer); +void write_img(image_dict *); +void write_png(image_dict *); +void write_jpg(image_dict *); +void write_jbig2(image_dict *); +void write_epdf(image_dict *); + +/* pdftoepdf.cc */ + +void epdf_delete(image_dict * idict); + +#endif diff --git a/Build/source/texk/web2c/luatexdir/image/pdftoepdf.cc b/Build/source/texk/web2c/luatexdir/image/pdftoepdf.cc new file mode 100644 index 00000000000..c5270eb58bd --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/image/pdftoepdf.cc @@ -0,0 +1,1008 @@ +/* +Copyright 1996-2006 Han The Thanh, + +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: pdftoepdf.cc 1058 2008-02-19 21:13:58Z hhenkel $ +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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" + +#define one_hundred_bp 6578176 /* 7227 * 65536 / 72 */ + +// This file is mostly C and not very much C++; it's just used to interface +// the functions of xpdf, which happens to be written in C++. + +// Used flags below: +// PDFTEX_COPY_PAGEGROUP +// If pdfTeX should copy a page group (a new feature in PDF 1.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. + +// The prefix "PTEX" for the PDF keys is 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 + fd_entry *fd; // pointer to /FontDescriptor object structure + 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, "\npdfTeX Debug: Incrementing %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, "\npdfTeX Debug: Creating %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 = pdf_new_objnum(); + return n->enc_objnum; +} + +#define addFont(ref, fd, enc_objnum) \ + addInObj(objFont, ref, fd, enc_objnum) + +// addFontDesc is only used to avoid writing the original FontDescriptor +// from the PDF file. + +#define addFontDesc(ref, fd) \ + addInObj(objFontDesc, ref, fd, 0) + +#define addOther(ref) \ + addInObj(objOther, ref, 0, 0) + +static int addInObj(InObjType type, Ref ref, fd_entry * fd, 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->fd = fd; + 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; + } + if (type == objFontDesc) + n->num = get_fd_objnum(fd); + else + n->num = pdf_new_objnum(); + 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"); + assert(r->type == objFont); // FontDescriptor is in fd_tree + for (i = 0, l = obj->dictGetLength(); i < l; ++i) { + key = obj->dictGetKey(i); + if (strncmp("FontDescriptor", key, strlen("FontDescriptor")) == 0 + || strncmp("BaseFont", key, strlen("BaseFont")) == 0 + || strncmp("Encoding", key, strlen("Encoding")) == 0) + continue; // skip original values + copyDictEntry(obj, i); + } + // write new FontDescriptor, BaseFont, and Encoding + pdf_printf("/FontDescriptor %d 0 R\n", (int) get_fd_objnum(r->fd)); + pdf_printf("/BaseFont %d 0 R\n", (int) get_fn_objnum(r->fd)); + pdf_printf("/Encoding %d 0 R\n", (int) r->enc_objnum); + pdf_puts(">>"); +} + +static void copyStream(Stream * str) +{ + int c; + str->reset(); + while ((c = str->getChar()) != EOF) + pdfout(c); + pdf_last_byte = pdf_buf[pdf_ptr - 1]; +} + +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"); +} + +#define REPLACE_TYPE1C true + +static void copyFont(char *tag, Object * fontRef) +{ + PdfObject fontdict, subtype, basefont, fontdescRef, fontdesc, charset, + fontfile, ffsubtype; + GfxFont *gfont; + fd_entry *fd; + 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 ", (int) p->num); + return; + } + } + // Only handle included Type1 (and Type1C) fonts; anything else will be copied. + // Type1C fonts are replaced by Type1 fonts, if REPLACE_TYPE1C is true. + if (fixed_replace_font && fontRef->fetch(xref, &fontdict)->isDict() + && fontdict->dictLookup("Subtype", &subtype)->isName() + && !strcmp(subtype->getName(), "Type1") + && fontdict->dictLookup("BaseFont", &basefont)->isName() + && fontdict->dictLookupNF("FontDescriptor", &fontdescRef)->isRef() + && fontdescRef->fetch(xref, &fontdesc)->isDict() + && (fontdesc->dictLookup("FontFile", &fontfile)->isStream() + || (REPLACE_TYPE1C + && fontdesc->dictLookup("FontFile3", &fontfile)->isStream() + && fontfile->streamGetDict()->lookup("Subtype", + &ffsubtype)->isName() + && !strcmp(ffsubtype->getName(), "Type1C"))) + && (fontmap = lookup_fontmap(basefont->getName())) != NULL) { + fd = epdf_create_fontdescriptor(fontmap); + if (fontdesc->dictLookup("CharSet", &charset) && + charset->isString() && is_subsetable(fontmap)) + epdf_mark_glyphs(fd, charset->getString()->getCString()); + else + embed_whole_font(fd); + addFontDesc(fontdescRef->getRef(), fd); + copyName(tag); + gfont = GfxFont::makeFont(xref, tag, fontRef->getRef(), + fontdict->getDict()); + pdf_printf(" %d 0 R ", addFont(fontRef->getRef(), fd, + addEncoding(gfont))); + } else { + 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); +} + +// Function onverts double to string; very small and very large numbers +// are NOT converted to scientific notation. +// n must be a number or real conforming 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()); + if (pdf_last_byte != '\n') + pdf_puts("\n"); + pdf_puts("endstream"); // can't simply write pdf_end_stream() + } else if (obj->isRef()) { + ref = obj->getRef(); + if (ref.num == 0) { + pdftex_warn + ("PDF inclusion: reference to invalid object was replaced by "); + 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; + xref->fetch(r->ref.num, r->ref.gen, &obj1); + if (r->type == objFont) { + assert(!obj1.isStream()); + zpdf_begin_obj(r->num, 2); // \pdfobjcompresslevel = 2 is for this + copyFontDict(&obj1, r); + pdf_puts("\n"); + pdf_end_obj(); + } else if (r->type != objFontDesc) { // /FontDescriptor is written via write_fontdescriptor() + if (obj1.isStream()) + zpdf_begin_obj(r->num, 0); + else + zpdf_begin_obj(r->num, 2); // \pdfobjcompresslevel = 2 is for this + copyObject(&obj1); + pdf_puts("\n"); + pdf_end_obj(); + } + obj1.free(); + } + } +} + +static void writeEncodings() +{ + UsedEncoding *r, *n; + char *glyphNames[256], *s; + int i; + for (r = encodingList; r != 0; r = r->next) { + for (i = 0; i < 256; 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; + } + epdf_write_enc(glyphNames, r->enc_objnum); + } + for (r = encodingList; r != 0; r = n) { + n = r->next; + delete r->font; + delete r; + } +} + +// get the pagebox according to the pagebox_spec + +static PDFRectangle *get_pagebox(Page * page, integer pagebox_spec) +{ + if (pagebox_spec == pdf_box_spec_media) + return page->getMediaBox(); + else if (pagebox_spec == pdf_box_spec_crop) + return page->getCropBox(); + else if (pagebox_spec == pdf_box_spec_bleed) + return page->getBleedBox(); + else if (pagebox_spec == pdf_box_spec_trim) + return page->getTrimBox(); + else if (pagebox_spec == pdf_box_spec_art) + return page->getArtBox(); + else + pdftex_fail("PDF inclusion: unknown value of pagebox spec (%i)", + (int) pagebox_spec); + return page->getMediaBox(); // to make the compiler happy +} + + +// 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. + +void +read_pdf_info(image_dict * idict, integer minor_pdf_version_wanted, + integer pdf_inclusion_errorlevel) +{ + PdfDocument *pdf_doc; + Page *page; + int rotate; + PDFRectangle *pagebox; + float pdf_version_found, pdf_version_wanted; + assert(idict != NULL); + assert(img_type(idict) == IMAGE_TYPE_PDF); + assert(img_pdf_ptr(idict) == NULL); + img_pdf_ptr(idict) = new_pdf_img_struct(); + // initialize + if (!isInit) { + globalParams = new GlobalParams(); + globalParams->setErrQuiet(gFalse); + isInit = gTrue; + } + // open PDF file + pdf_doc = find_add_document(img_filepath(idict)); + img_pdf_doc(idict) = pdf_doc; + + // 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); + } + } + img_totalpages(idict) = pdf_doc->doc->getCatalog()->getNumPages(); + if (img_pagename(idict)) { + // get page by name + GString name(img_pagename(idict)); + LinkDest *link = pdf_doc->doc->findDest(&name); + if (link == 0 || !link->isOk()) + pdftex_fail("PDF inclusion: invalid destination <%s>", + img_pagename(idict)); + Ref ref = link->getPageRef(); + img_pagenum(idict) = + pdf_doc->doc->getCatalog()->findPage(ref.num, ref.gen); + if (img_pagenum(idict) == 0) + pdftex_fail("PDF inclusion: destination is not a page <%s>", + img_pagename(idict)); + delete link; + } else { + // get page by number + if (img_pagenum(idict) <= 0 + || img_pagenum(idict) > img_totalpages(idict)) + pdftex_fail("PDF inclusion: required page <%i> does not exist", + (int) img_pagenum(idict)); + } + // get the required page + page = pdf_doc->doc->getCatalog()->getPage(img_pagenum(idict)); + + // get the pagebox (media, crop...) to use. + pagebox = get_pagebox(page, img_pagebox(idict)); + if (pagebox->x2 > pagebox->x1) { + img_pdf_orig_x(idict) = pagebox->x1; + img_pdf_width(idict) = pagebox->x2 - pagebox->x1; + } else { + img_pdf_orig_x(idict) = pagebox->x2; + img_pdf_width(idict) = pagebox->x1 - pagebox->x2; + } + if (pagebox->y2 > pagebox->y1) { + img_pdf_orig_y(idict) = pagebox->y1; + img_pdf_height(idict) = pagebox->y2 - pagebox->y1; + } else { + img_pdf_orig_y(idict) = pagebox->y2; + img_pdf_height(idict) = pagebox->y1 - pagebox->y2; + } + + 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 = img_pdf_height(idict); + img_pdf_height(idict) = img_pdf_width(idict); + img_pdf_width(idict) = f; + break; + case 270: + f = img_pdf_height(idict); + img_pdf_height(idict) = img_pdf_width(idict); + img_pdf_width(idict) = f; + break; + } + } + } + pdf_doc->xref = pdf_doc->doc->getXRef(); + img_xsize(idict) = bp2int(img_pdf_width(idict)); + img_ysize(idict) = bp2int(img_pdf_height(idict)); +} + +// 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(image_dict * idict) +{ + Page *page; + PdfObject contents, obj1, obj2; + PdfObject group, metadata, pieceinfo, separationInfo; + Object info; + char *key; + char s[256]; + int i, l; + int rotate; + double scale[6] = { 0, 0, 0, 0, 0, 0 }; + bool writematrix = false; + PdfDocument *pdf_doc = (PdfDocument *) img_pdf_doc(idict); + (pdf_doc->occurences)--; +#ifdef DEBUG + fprintf(stderr, "\npdfTeX Debug: Decrementing %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(img_pagenum(idict)); + rotate = page->getRotate(); + PDFRectangle *pagebox; + // write the Page header + pdf_puts("/Type /XObject\n/Subtype /Form\n"); + if (img_attr(idict) != NULL && strlen(img_attr(idict)) > 0) + pdf_printf("%s\n", img_attr(idict)); + 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, (int) img_pagenum(idict)); + 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. + pagebox = get_pagebox(page, img_pagebox(idict)); + + // 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. + sprintf(s, "/Matrix [%.8f %.8f %.8f %.8f %.8f %.8f]\n", + scale[0], + scale[1], scale[2], scale[3], scale[4], scale[5]); + pdf_printf(stripzeros(s)); + } + } + } + + sprintf(s, "/BBox [%.8f %.8f %.8f %.8f]\n", + pagebox->x1, pagebox->y1, pagebox->x2, pagebox->y2); + pdf_printf(stripzeros(s)); + + // 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 Ref., which claims they are + // required, but all RIPs accept them. + // We "replace" them with empty /Resources, although in form xobjects + // /Resources are not required. + 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_end_stream(); + } else if (contents->isArray()) { + pdf_begin_stream(); + for (i = 0, l = contents->arrayGetLength(); i < l; ++i) { + Object contentsobj; + copyStream((contents->arrayGet(i, &contentsobj))->getStream()); + contentsobj.free(); + } + pdf_end_stream(); + } else { // the contents are optional, but we need to include an empty stream + pdf_begin_stream(); + pdf_end_stream(); + } + // 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(image_dict * idict) +{ + PdfDocument *pdf_doc = (PdfDocument *) img_pdf_doc(idict); + xref = pdf_doc->xref; + if (pdf_doc->occurences < 0) { +#ifdef DEBUG + fprintf(stderr, "\npdfTeX Debug: Deleting %s\n", pdf_doc->file_name); +#endif + delete_document(pdf_doc); + } + img_pdf_doc(idict) = NULL; +} + +// 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; + } +} diff --git a/Build/source/texk/web2c/luatexdir/image/writeimg.c b/Build/source/texk/web2c/luatexdir/image/writeimg.c new file mode 100644 index 00000000000..66eb459bc0c --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/image/writeimg.c @@ -0,0 +1,677 @@ +/* +Copyright (c) 1996-2002, 2005 Han The Thanh, + +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: writeimg.c 1119 2008-03-22 11:27:02Z hhenkel $ +*/ + +#include +#include "ptexlib.h" +#include +#include + +#include "image.h" + +#include <../lua51/lua.h> +#include <../lua51/lauxlib.h> + +extern void pdf_print_real(integer m, integer d); + +#define obj_aux(A) obj_tab[(A)].int4 + +/**********************************************************************/ +/* + 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 + "check_type_by_header". If this check fails, the traditional + test of standard file extension is tried, done in function + "check_type_by_extension". + + 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 "check_type_by_header" only looks at the first two bytes: + "\xFF\xD8" + + * ISO/IEC JTC 1/SC 29/WG 1 + (ITU-T SG8) + Coding of Still Pictures + Title: 14492 FCD + Source: JBIG Committee + Project: JTC 1.29.10 + Status: Final Committee Draft + + | D.4.1, ID string + | + | This is an 8-byte sequence containing 0x97 0x4A 0x42 0x32 0x0D 0x0A + | 0x1A 0x0A. + + * "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 "check_type_by_header" 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 "check_type_by_header" and "check_type_by_extension": + img_type(img) is set to IMAGE_TYPE_NONE by new_image_dict(). + Both functions try to detect a type and set img_type(img). + Thus a value other than IMAGE_TYPE_NONE indicates that a + type has been found. +*/ + +#define HEADER_JPG "\xFF\xD8" +#define HEADER_PNG "\x89PNG\r\n\x1A\n" +#define HEADER_JBIG2 "\x97\x4A\x42\x32\x0D\x0A\x1A\x0A" +#define HEADER_PDF "%PDF-1." +#define MAX_HEADER (sizeof(HEADER_PNG)-1) + +static void check_type_by_header(image_dict * idict) +{ + int i; + FILE *file = NULL; + char header[MAX_HEADER]; + + assert(idict != NULL); + if (img_type(idict) != IMAGE_TYPE_NONE) /* nothing to do */ + return; + /* read the header */ + file = xfopen(img_filepath(idict), FOPEN_RBIN_MODE); + for (i = 0; (unsigned) i < MAX_HEADER; i++) { + header[i] = xgetc(file); + if (feof(file)) + pdftex_fail("reading image file failed"); + } + xfclose(file, img_filepath(idict)); + /* tests */ + if (strncmp(header, HEADER_JPG, sizeof(HEADER_JPG) - 1) == 0) + img_type(idict) = IMAGE_TYPE_JPG; + else if (strncmp(header, HEADER_PNG, sizeof(HEADER_PNG) - 1) == 0) + img_type(idict) = IMAGE_TYPE_PNG; + else if (strncmp(header, HEADER_JBIG2, sizeof(HEADER_JBIG2) - 1) == 0) + img_type(idict) = IMAGE_TYPE_JBIG2; + else if (strncmp(header, HEADER_PDF, sizeof(HEADER_PDF) - 1) == 0) + img_type(idict) = IMAGE_TYPE_PDF; +} + +static void check_type_by_extension(image_dict * idict) +{ + char *image_suffix; + + assert(idict != NULL); + if (img_type(idict) != IMAGE_TYPE_NONE) /* nothing to do */ + return; + /* tests */ + if ((image_suffix = strrchr(img_filename(idict), '.')) == 0) + img_type(idict) = IMAGE_TYPE_NONE; + else if (strcasecmp(image_suffix, ".png") == 0) + img_type(idict) = IMAGE_TYPE_PNG; + else if (strcasecmp(image_suffix, ".jpg") == 0 || + strcasecmp(image_suffix, ".jpeg") == 0) + img_type(idict) = IMAGE_TYPE_JPG; + else if (strcasecmp(image_suffix, ".jbig2") == 0 || + strcasecmp(image_suffix, ".jb2") == 0) + img_type(idict) = IMAGE_TYPE_JBIG2; + else if (strcasecmp(image_suffix, ".pdf") == 0) + img_type(idict) = IMAGE_TYPE_PDF; +} + +/**********************************************************************/ + +pdf_img_struct *new_pdf_img_struct() +{ + pdf_img_struct *p; + p = xtalloc(1, pdf_img_struct); + p->width = 0; + p->height = 0; + p->orig_x = 0; + p->orig_y = 0; + p->doc = NULL; + return p; +} + +void init_image(image * p) +{ + assert(p != NULL); + set_wd_running(p); + set_ht_running(p); + set_dp_running(p); + img_transform(p) = 0; + img_flags(p) = 0; + img_unset_refered(p); /* wd/ht/dp may be modified */ + img_unset_scaled(p); + img_dict(p) = NULL; + img_dictref(p) = LUA_NOREF; +} + +image *new_image() +{ + image *p = xtalloc(1, image); + init_image(p); + return p; +} + +void init_image_dict(image_dict * p) +{ + assert(p != NULL); + img_objnum(p) = 0; + img_index(p) = 0; + img_xsize(p) = 0; + img_ysize(p) = 0; + img_xres(p) = 0; + img_yres(p) = 0; + img_colorspace(p) = 0; + img_totalpages(p) = 0; + img_pagenum(p) = 1; + img_pagename(p) = NULL; + img_filename(p) = NULL; + img_filepath(p) = NULL; + img_attr(p) = NULL; + img_file(p) = NULL; + img_type(p) = IMAGE_TYPE_NONE; + img_color(p) = 0; + img_colordepth(p) = 0; + img_pagebox(p) = PDF_BOX_SPEC_MEDIA; + img_state(p) = DICT_NEW; + img_pdf_ptr(p) = NULL; /* union */ +} + +image_dict *new_image_dict() +{ + image_dict *p = xtalloc(1, image_dict); + init_image_dict(p); + return p; +} + +void free_dict_strings(image_dict * p) +{ + if (img_filename(p) != NULL) + xfree(img_filename(p)); + img_filename(p) = NULL; + if (img_filepath(p) != NULL) + xfree(img_filepath(p)); + img_filepath(p) = NULL; + if (img_attr(p) != NULL) + xfree(img_attr(p)); + img_attr(p) = NULL; + if (img_pagename(p) != NULL) + xfree(img_pagename(p)); + img_pagename(p) = NULL; +} + +void free_image_dict(image_dict * p) +{ + free_dict_strings(p); + if (img_type(p) == IMAGE_TYPE_PDF) + epdf_delete(p); + assert(img_file(p) == NULL); + xfree(p); +} + +/**********************************************************************/ + +void pdf_print_resname_prefix() +{ + if (pdf_resname_prefix != 0) + pdf_printf(makecstring(pdf_resname_prefix)); +} + +void read_img(image_dict * idict, integer pdf_minor_version, + integer pdf_inclusion_errorlevel) +{ + char *filepath; + int callback_id; + assert(idict != NULL); + if (img_filename(idict) == NULL) + pdftex_fail("image file name missing"); + callback_id = callback_defined(find_image_file_callback); + if (img_filepath(idict) == NULL) { + if (callback_id > 0 + && run_callback(callback_id, "S->S", img_filename(idict), + &filepath)) { + if (filepath && (strlen(filepath) > 0)) + img_filepath(idict) = strdup(filepath); + } else + img_filepath(idict) = + kpse_find_file(img_filename(idict), kpse_tex_format, true); + } + if (img_filepath(idict) == NULL) + pdftex_fail("cannot find image file"); + /* type checks */ + check_type_by_header(idict); + check_type_by_extension(idict); + /* read image */ + switch (img_type(idict)) { + case IMAGE_TYPE_PDF: + read_pdf_info(idict, pdf_minor_version, pdf_inclusion_errorlevel); + break; + case IMAGE_TYPE_PNG: + read_png_info(idict, IMG_CLOSEINBETWEEN); + break; + case IMAGE_TYPE_JPG: + read_jpg_info(idict, IMG_CLOSEINBETWEEN); + break; + case IMAGE_TYPE_JBIG2: + if (pdf_minor_version < 4) { + pdftex_fail + ("JBIG2 images only possible with at least PDF 1.4; you are generating PDF 1.%i", + (int) pdf_minor_version); + } + read_jbig2_info(idict); + break; + default: + pdftex_fail("internal error: unknown image type"); + } + cur_file_name = NULL; + if (img_state(idict) < DICT_FILESCANNED) + img_state(idict) = DICT_FILESCANNED; +} + +void scale_img(image * img) +{ + integer x, y, xr, yr; /* size and resolution of image */ + scaled w, h; /* indeed size corresponds to image resolution */ + integer default_res; + assert(img != NULL); + image_dict *idict = img_dict(img); + assert(idict != NULL); + x = img_xsize(idict); /* dimensions, resolutions from image file */ + y = img_ysize(idict); + xr = img_xres(idict); + yr = img_yres(idict); + if ((img_transform(img) & 1) == 1) { + int tmp = x; + x = y; + y = tmp; + tmp = xr; + xr = yr; + yr = tmp; + } + if (xr > 65535 || yr > 65535) { + xr = 0; + yr = 0; + pdftex_warn("ext1: too large image resolution ignored"); + } + if (x <= 0 || y <= 0 || xr < 0 || yr < 0) + pdftex_fail("ext1: invalid image dimensions"); + if (img_type(idict) == IMAGE_TYPE_PDF) { + w = x; + h = y; + } else { + default_res = fix_int(get_pdf_image_resolution(), 0, 65535); + if (default_res > 0 && (xr == 0 || yr == 0)) { + xr = default_res; + yr = default_res; + } + if (is_wd_running(img) && is_ht_running(img)) { + if (xr > 0 && yr > 0) { + w = ext_xn_over_d(one_hundred_inch, x, 100 * xr); + h = ext_xn_over_d(one_hundred_inch, y, 100 * yr); + } else { + w = ext_xn_over_d(one_hundred_inch, x, 7200); + h = ext_xn_over_d(one_hundred_inch, y, 7200); + } + } + } + if (is_wd_running(img) && is_ht_running(img) && is_dp_running(img)) { + img_width(img) = w; + img_height(img) = h; + img_depth(img) = 0; + } else if (is_wd_running(img)) { + /* image depth or height is explicitly specified */ + if (is_ht_running(img)) { + /* image depth is explicitly specified */ + img_width(img) = ext_xn_over_d(h, x, y); + img_height(img) = h - img_depth(img); + } else if (is_dp_running(img)) { + /* image height is explicitly specified */ + img_width(img) = ext_xn_over_d(img_height(img), x, y); + img_depth(img) = 0; + } else { + /* both image depth and height are explicitly specified */ + img_width(img) = + ext_xn_over_d(img_height(img) + img_depth(img), x, y); + } + } else { + /* image width is explicitly specified */ + if (is_ht_running(img) && is_dp_running(img)) { + /* both image depth and height are not specified */ + img_height(img) = ext_xn_over_d(img_width(img), y, x); + img_depth(img) = 0; + } + /* image depth is explicitly specified */ + else if (is_ht_running(img)) { + img_height(img) = + ext_xn_over_d(img_width(img), y, x) - img_depth(img); + } + /* image height is explicitly specified */ + else if (is_dp_running(img)) { + img_depth(img) = 0; + } + /* else both image depth and height are explicitly specified */ + } + img_set_scaled(img); +} + +void out_img(image * img, scaled hpos, scaled vpos) +{ + float a[7]; /* transformation matrix (todo: indices should be reduced!) */ + int r; /* number of digits after the decimal point */ + assert(img != 0); + image_dict *idict = img_dict(img); + assert(idict != 0); + scaled wd = img_width(img); + scaled ht = img_height(img); + scaled dp = img_depth(img); + if (img_type(idict) == IMAGE_TYPE_PDF) { + a[1] = wd * 1.0e6 / img_xsize(idict); + a[2] = 0; + a[3] = 0; + a[4] = (ht + dp) * 1.0e6 / img_ysize(idict); + a[5] = hpos - + (float) wd *bp2int(img_pdf_orig_x(idict)) / img_xsize(idict); + a[6] = vpos - + (float) ht *bp2int(img_pdf_orig_y(idict)) / img_ysize(idict); + r = 6; + } else { + a[1] = wd * 1.0e6 / one_hundred_bp; + a[2] = 0; + a[3] = 0; + a[4] = (ht + dp) * 1.0e6 / one_hundred_bp; + a[5] = hpos; + a[6] = vpos; + r = 4; + } + if ((img_transform(img) & 1) == 1) { + if (ht == -dp) + pdftex_fail("image transform: division by zero (height == -depth)"); + if (wd == 0) + pdftex_fail("image transform: division by zero (width == 0)"); + } + switch (img_transform(img) & 7) { + case 0: /* unrotated */ + break; + case 1: /* rot. 90 deg. (counterclockwise) */ + a[2] = a[1] * (ht + dp) / wd; + a[1] = 0; + a[3] = -a[4] * wd / (ht + dp); + a[4] = 0; + a[5] += wd; + break; + case 2: /* rot. 180 deg. */ + a[1] = -a[1]; + a[4] = -a[4]; + a[5] += wd; + a[6] += ht + dp; + break; + case 3: /* rot. 270 deg. */ + a[2] = -a[1] * (ht + dp) / wd; + a[1] = 0; + a[3] = a[4] * wd / (ht + dp); + a[4] = 0; + a[6] += ht + dp; + break; + case 4: /* mirrored, unrotated */ + a[1] = -a[1]; + a[5] += wd; + break; + case 5: /* mirrored, then rot. 90 deg. */ + a[2] = -a[1] * (ht + dp) / wd; + a[1] = 0; + a[3] = -a[4] * wd / (ht + dp); + a[4] = 0; + a[5] += wd; + a[6] += ht + dp; + break; + case 6: /* mirrored, then rot. 180 deg. */ + a[4] = -a[4]; + a[6] += ht + dp; + break; + case 7: /* mirrored, then rot. 270 deg. */ + a[2] = a[1] * (ht + dp) / wd; + a[1] = 0; + a[3] = a[4] * wd / (ht + dp); + a[4] = 0; + break; + default: + assert(0); + } + pdf_end_text(); + pdf_printf("q\n"); + pdf_print_real((integer) a[1], r); + pdfout(' '); + pdf_print_real((integer) a[2], r); + pdfout(' '); + pdf_print_real((integer) a[3], r); + pdfout(' '); + pdf_print_real((integer) a[4], r); + pdfout(' '); + pdf_print_bp((integer) a[5]); + pdfout(' '); + pdf_print_bp((integer) a[6]); + pdf_printf(" cm\n/Im"); + pdf_print_int(img_index(idict)); + pdf_print_resname_prefix(); + pdf_printf(" Do\nQ\n"); + if (img_state(idict) < DICT_OUTIMG) + img_state(idict) = DICT_OUTIMG; +} + +void write_img(image_dict * idict) +{ + assert(idict != NULL); + if (img_state(idict) < DICT_WRITTEN) { + if (tracefilenames) + tex_printf(" <%s", img_filepath(idict)); + switch (img_type(idict)) { + case IMAGE_TYPE_PNG: + write_png(idict); + break; + case IMAGE_TYPE_JPG: + write_jpg(idict); + break; + case IMAGE_TYPE_JBIG2: + write_jbig2(idict); + break; + case IMAGE_TYPE_PDF: + write_epdf(idict); + break; + default: + pdftex_fail("internal error: unknown image type"); + } + if (tracefilenames) + tex_printf(">"); + } + if (img_state(idict) < DICT_WRITTEN) + img_state(idict) = DICT_WRITTEN; +} + +/**********************************************************************/ + +typedef image *img_entry; +/* define img_ptr, img_array, & img_limit */ +define_array(img); /* array of pointers to image structures */ + +integer img_to_array(image * img) +{ + assert(img != NULL); + alloc_array(img, 1, SMALL_BUF_SIZE); + *img_ptr = img; + return img_ptr++ - img_array; /* now img is read-only */ +} + +/**********************************************************************/ +/* stuff to be accessible from TeX */ + +integer read_image(integer objnum, integer index, strnumber filename, + integer page_num, + strnumber attr, + strnumber page_name, + integer colorspace, integer page_box, + integer pdf_minor_version, integer pdf_inclusion_errorlevel) +{ + integer ref; + image *a = new_image(); + ref = img_to_array(a); + image_dict *idict = img_dict(a) = new_image_dict(); + assert(idict != NULL); + img_objnum(idict) = objnum; + img_index(idict) = index; + /* img_xsize, img_ysize, img_xres, img_yres set by read_img() */ + img_colorspace(idict) = colorspace; + img_pagenum(idict) = page_num; + /* img_totalpages set by read_img() */ + if (page_name != 0) + img_pagename(idict) = xstrdup(makecstring(page_name)); + cur_file_name = makecfilename(filename); + assert(cur_file_name != NULL); + img_filename(idict) = xstrdup(cur_file_name); + if (attr != 0) + img_attr(idict) = xstrdup(makecstring(attr)); + img_pagebox(idict) = page_box; + read_img(idict, pdf_minor_version, pdf_inclusion_errorlevel); + img_unset_scaled(a); + img_set_refered(a); + return ref; +} + +void set_image_dimensions(integer ref, integer wd, integer ht, integer dp) +{ + image *a = img_array[ref]; + img_width(a) = wd; + img_height(a) = ht; + img_depth(a) = dp; +} + +void scale_image(integer ref) +{ + scale_img(img_array[ref]); +} + +void out_image(integer ref, scaled hpos, scaled vpos) +{ + image *a = img_array[ref]; + out_img(a, hpos, vpos); +} + +void write_image(integer ref) +{ + write_img(img_dict(img_array[ref])); +} + +integer image_pages(integer ref) +{ + return img_totalpages(img_dict(img_array[ref])); +} + +integer image_colordepth(integer ref) +{ + return img_colordepth(img_dict(img_array[ref])); +} + +integer epdf_orig_x(integer ref) +{ + return bp2int(img_pdf_orig_x(img_dict(img_array[ref]))); +} + +integer epdf_orig_y(integer ref) +{ + return bp2int(img_pdf_orig_y(img_dict(img_array[ref]))); +} + +integer image_objnum(integer ref) +{ + return img_objnum(img_dict(img_array[ref])); +} + +integer image_index(integer ref) +{ + return img_index(img_dict(img_array[ref])); +} + +integer image_width(integer ref) +{ + return img_width(img_array[ref]); +} + +integer image_height(integer ref) +{ + return img_height(img_array[ref]); +} + +integer image_depth(integer ref) +{ + return img_depth(img_array[ref]); +} + +void update_image_procset(integer ref) +{ + pdf_image_procset |= img_color(img_dict(img_array[ref])); +} + +/**********************************************************************/ + +boolean check_image_b(integer procset) +{ + return procset & IMAGE_COLOR_B; +} + +boolean check_image_c(integer procset) +{ + return procset & IMAGE_COLOR_C; +} + +boolean check_image_i(integer procset) +{ + return procset & IMAGE_COLOR_I; +} diff --git a/Build/source/texk/web2c/luatexdir/image/writejbig2.c b/Build/source/texk/web2c/luatexdir/image/writejbig2.c new file mode 100644 index 00000000000..d50ed88c485 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/image/writejbig2.c @@ -0,0 +1,749 @@ +/*********************************************************************** +Copyright (c) 2002-2006 Han The Thanh, + +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 + +This is experimental JBIG2 image support to pdfTeX. JBIG2 image decoding +is part of Adobe PDF-1.4, and requires Acroread 5.0 or later. + +References +========== + +* 14492 FCD: Information technology -- coded representation of picture +and audio information -- lossy/lossless coding of bi-level images / +JBIG committee, 1999 July 16. This JBIG2 Working Draft is available from +http://www.jpeg.org/public/fcd14492.pdf. The references in the C-code +correspond to the sections of this document. + +* PDF Reference, 5th edition, version 1.6, 1985--2005 Adobe Systems +Incorporated. Available online: + +http://partners.adobe.com/public/developer/en/pdf/PDFReference16.pdf + +News +==== + +31 May 2006: no need to wait for endoffileflag in sequential access +organization. + +10 May 2006: ygetc() for some catching of broken JBIG2 files; modify to +accept Example 3.4 from PDFRef 5th ed. with short end-of-file segment. + +09 May 2006: pages_maketree() and segments_maketree() by AVL tree, +some cleaning up. + +06 May 2006: File list replaced by AVL tree; new_fileinfo(), +new_pageinfo(). + +04 May 2006: Updated for pdftex-1.40-beta-20060213. + +08 Jan. 2003: Added flushjbig2page0objects() function. Now at the end +of the pdfTeX run all pending page0 objects are written out. + +08 Jan. 2003: Release on private webpage. + +04 Jan. 2003: Completely rewritten. Now with some data structures. +Rudimentary local file and image bookkeeping. Multiple image inclusion +from one JBIG2 file. Only required page0 segments are marked for +inclusion. + +13 Nov. 2002: pdfcrypting removed. + +08 Dec. 2002: bug in page 0 stream writing repaired. +Strategy for multiple page inclusion from same JBIG2 file: When writing +1st image, create fresh PDF object for page 0, and include any page +0 segments from complete file (even if these segments are not needed +for image). When writing next image, check by filename comparison if +PDF object for page 0 of this JBIG2 file has already been written. This +can only remember the file name for the direct predecessor JBIG2 image +(but images of other types might come inbetween). If such page 0 PDF +object exists, reference it. Else create fresh one. + +09 Dec. 2002: JBIG2 seg. page numbers > 0 are now set to 1, see PDF Ref. + +$Id: writejbig2.c 1027 2008-02-14 21:01:03Z hhenkel $ +***********************************************************************/ + +#include "writejbig2.h" +#undef DEBUG + +/**********************************************************************/ + +struct avl_table *file_tree = NULL; + +static int comp_file_entry(const void *pa, const void *pb, void *p) +{ + return strcmp(((const FILEINFO *) pa)->filepath, + ((const FILEINFO *) pb)->filepath); +} + +static int comp_page_entry(const void *pa, const void *pb, void *p) +{ + return ((const PAGEINFO *) pa)->pagenum - ((const PAGEINFO *) pb)->pagenum; +} + +static int comp_segment_entry(const void *pa, const void *pb, void *p) +{ + return ((const SEGINFO *) pa)->segnum - ((const SEGINFO *) pb)->segnum; +} + +/**********************************************************************/ + +int ygetc(FILE * stream) +{ + int c = getc(stream); + if (c < 0) { + if (c == EOF) + pdftex_fail("getc() failed; premature end of JBIG2 image file"); + else + pdftex_fail("getc() failed (can't happen)"); + } + return c; +} + +/**********************************************************************/ + +FILEINFO *new_fileinfo() +{ + FILEINFO *fip; + fip = xtalloc(1, FILEINFO); + fip->file = NULL; + fip->filepath = NULL; + fip->filesize = 0; + initlinkedlist(&(fip->pages)); + initlinkedlist(&(fip->page0)); + fip->filehdrflags = 0; + fip->sequentialaccess = false; + fip->numofpages = 0; + fip->streamstart = 0; + fip->pdfpage0objnum = 0; + fip->phase = INITIAL; + return fip; +} + +PAGEINFO *new_pageinfo() +{ + PAGEINFO *pip; + pip = xtalloc(1, PAGEINFO); + initlinkedlist(&(pip->segments)); + pip->pagenum = 0; + pip->width = 0; + pip->height = 0; + pip->xres = 0; + pip->yres = 0; + pip->pagesegmentflags = 0; + pip->stripinginfo = 0; + pip->stripedheight = 0; + return pip; +} + +void init_seginfo(SEGINFO * sip) +{ + sip->segnum = 0; + sip->isrefered = false; + sip->refers = false; + sip->seghdrflags = 0; + sip->pageassocsizeflag = false; + sip->reftosegcount = 0; + sip->countofrefered = 0; + sip->fieldlen = 0; + sip->segnumwidth = 0; + sip->segpage = 0; + sip->segdatalen = 0; + sip->hdrstart = 0; + sip->hdrend = 0; + sip->datastart = 0; + sip->dataend = 0; + sip->endofstripeflag = false; + sip->endofpageflag = false; + sip->pageinfoflag = false; + sip->endoffileflag = false; +} + +/**********************************************************************/ + +void initlinkedlist(LIST * lp) +{ + lp->first = NULL; + lp->last = NULL; + lp->tree = NULL; +} + +LIST *litem_append(LIST * lp) +{ + LITEM *ip; + ip = xtalloc(1, LITEM); + if (lp->first == NULL) { + lp->first = ip; + ip->prev = NULL; + } else { + lp->last->next = ip; + ip->prev = lp->last; + } + lp->last = ip; + ip->next = NULL; + ip->d = NULL; + return lp; +} + +/**********************************************************************/ + +void pages_maketree(LIST * plp) +{ + LITEM *ip; + void **aa; + assert(plp->tree == NULL); + plp->tree = avl_create(comp_page_entry, NULL, &avl_xallocator); + assert(plp->tree != NULL); + for (ip = plp->first; ip != NULL; ip = ip->next) { + aa = avl_probe(plp->tree, (PAGEINFO *) ip->d); + assert(aa != NULL); + } +} + +void segments_maketree(LIST * slp) +{ + LITEM *ip; + void **aa; + assert(slp->tree == NULL); + slp->tree = avl_create(comp_segment_entry, NULL, &avl_xallocator); + assert(slp->tree != NULL); + for (ip = slp->first; ip != NULL; ip = ip->next) { + aa = avl_probe(slp->tree, (SEGINFO *) ip->d); + assert(aa != NULL); + } +} + +/**********************************************************************/ + +PAGEINFO *find_pageinfo(LIST * plp, unsigned long pagenum) +{ + PAGEINFO tmp; + tmp.pagenum = pagenum; + assert(plp->tree != NULL); + return (PAGEINFO *) avl_find(plp->tree, &tmp); +} + +SEGINFO *find_seginfo(LIST * slp, unsigned long segnum) +{ + SEGINFO tmp; + tmp.segnum = segnum; + assert(slp->tree != NULL); + return (SEGINFO *) avl_find(slp->tree, &tmp); +} + +/**********************************************************************/ + +unsigned int read2bytes(FILE * f) +{ + unsigned int c = ygetc(f); + return (c << 8) + ygetc(f); +} + +unsigned long read4bytes(FILE * f) +{ + unsigned int l = read2bytes(f); + return (l << 16) + read2bytes(f); +} + +/**********************************************************************/ + +unsigned long getstreamlen(LITEM * slip, boolean refer) +{ + SEGINFO *sip; + unsigned long len = 0; + for (; slip != NULL; slip = slip->next) { + sip = slip->d; + if (refer || sip->isrefered) + len += sip->hdrend - sip->hdrstart + sip->dataend - sip->datastart; + } + return len; +} + +/**********************************************************************/ + +void readfilehdr(FILEINFO * fip) +{ + unsigned int i; + /* Annex D.4 File header syntax */ + /* Annex D.4.1 ID string */ + unsigned char jbig2_id[] = { 0x97, 'J', 'B', '2', 0x0d, 0x0a, 0x1a, 0x0a }; + xfseek(fip->file, 0, SEEK_SET, fip->filepath); + for (i = 0; i < 8; i++) + if (ygetc(fip->file) != jbig2_id[i]) + pdftex_fail + ("readfilehdr(): reading JBIG2 image file failed: ID string missing"); + /* Annex D.4.2 File header flags */ + fip->filehdrflags = ygetc(fip->file); + fip->sequentialaccess = (fip->filehdrflags & 0x01) ? true : false; + if (fip->sequentialaccess) { /* Annex D.1 vs. Annex D.2 */ + xfseek(fip->file, 0, SEEK_END, fip->filepath); + fip->filesize = xftell(fip->file, fip->filepath); + xfseek(fip->file, 9, SEEK_SET, fip->filepath); + } + /* Annex D.4.3 Number of pages */ + if (!(fip->filehdrflags >> 1) & 0x01) /* known number of pages */ + fip->numofpages = read4bytes(fip->file); + /* --- at end of file header --- */ +} + +/**********************************************************************/ +/* for first reading of file; return value tells if header been read */ + +boolean readseghdr(FILEINFO * fip, SEGINFO * sip) +{ + unsigned int i; + sip->hdrstart = xftell(fip->file, fip->filepath); + if (fip->sequentialaccess && sip->hdrstart == fip->filesize) + return false; /* no endoffileflag is ok for sequentialaccess */ +#ifdef DEBUG + printf("\nhdrstart %d\n", sip->hdrstart); +#endif + /* 7.2.2 Segment number */ + sip->segnum = read4bytes(fip->file); +#ifdef DEBUG + printf(" segnum %d\n", sip->segnum); +#endif + /* 7.2.3 Segment header flags */ + sip->seghdrflags = ygetc(fip->file); +#ifdef DEBUG + printf(" hdrflags %d\n", sip->seghdrflags & 0x3f); +#endif + checkseghdrflags(sip); + if (fip->sequentialaccess && sip->endoffileflag) /* accept shorter segment, */ + return true; /* makes it compliant with Example 3.4 of PDFRef. 5th ed. */ + sip->pageassocsizeflag = ((sip->seghdrflags >> 6) & 0x01) ? true : false; + /* 7.2.4 Referred-to segment count and retention flags */ + sip->reftosegcount = (unsigned int) ygetc(fip->file); + sip->countofrefered = sip->reftosegcount >> 5; + if (sip->countofrefered < 5) + sip->fieldlen = 1; + else { + sip->fieldlen = 5 + sip->countofrefered / 8; + xfseek(fip->file, sip->fieldlen - 1, SEEK_CUR, fip->filepath); + } + /* 7.2.5 Referred-to segment numbers */ + if (sip->segnum <= 256) + sip->segnumwidth = 1; + else if (sip->segnum <= 65536) + sip->segnumwidth = 2; + else + sip->segnumwidth = 4; + for (i = 0; i < sip->countofrefered; i++) { + switch (sip->segnumwidth) { + case 1: + (void) ygetc(fip->file); + break; + case 2: + (void) read2bytes(fip->file); + break; + case 4: + (void) read4bytes(fip->file); + break; + } + } + /* 7.2.6 Segment page association */ + if (sip->pageassocsizeflag) + sip->segpage = read4bytes(fip->file); + else + sip->segpage = ygetc(fip->file); + /* 7.2.7 Segment data length */ + sip->segdatalen = read4bytes(fip->file); + sip->hdrend = xftell(fip->file, fip->filepath); + /* ---- at end of segment header ---- */ + return true; +} + +/**********************************************************************/ +/* for writing, marks refered page0 segments, sets segpage > 0 to 1 */ + +void writeseghdr(FILEINFO * fip, SEGINFO * sip) +{ + unsigned int i; + unsigned long referedseg = 0; + /* 7.2.2 Segment number */ + /* 7.2.3 Segment header flags */ + /* 7.2.4 Referred-to segment count and retention flags */ + for (i = 0; i < 5 + sip->fieldlen; i++) + pdfout(ygetc(fip->file)); + /* 7.2.5 Referred-to segment numbers */ + for (i = 0; i < sip->countofrefered; i++) { + switch (sip->segnumwidth) { + case 1: + referedseg = ygetc(fip->file); + pdfout(referedseg); + break; + case 2: + referedseg = read2bytes(fip->file); + pdfout((referedseg >> 8) & 0xff); + pdfout(referedseg & 0xff); + break; + case 4: + referedseg = read4bytes(fip->file); + pdfout((referedseg >> 24) & 0xff); + pdfout((referedseg >> 16) & 0xff); + pdfout((referedseg >> 8) & 0xff); + pdfout(referedseg & 0xff); + break; + } + if (fip->page0.last != NULL && !sip->refers) + markpage0seg(fip, referedseg); + } + if (sip->countofrefered > 0) + sip->refers = true; + /* 7.2.6 Segment page association */ + if (sip->pageassocsizeflag) + for (i = 0; i < 3; i++) { + (void) ygetc(fip->file); + pdfout(0); + } + (void) ygetc(fip->file); + pdfout((sip->segpage > 0) ? 1 : 0); + /* 7.2.7 Segment data length */ + for (i = 0; i < 4; i++) + pdfout(ygetc(fip->file)); + /* ---- at end of segment header ---- */ +} + +/**********************************************************************/ +/* for recursive marking of refered page0 segments */ + +void checkseghdr(FILEINFO * fip, SEGINFO * sip) +{ + unsigned int i; + unsigned long referedseg = 0; + /* 7.2.2 Segment number */ + /* 7.2.3 Segment header flags */ + /* 7.2.4 Referred-to segment count and retention flags */ + xfseek(fip->file, 5 + sip->fieldlen, SEEK_CUR, fip->filepath); + /* 7.2.5 Referred-to segment numbers */ + for (i = 0; i < sip->countofrefered; i++) { + switch (sip->segnumwidth) { + case 1: + referedseg = ygetc(fip->file); + break; + case 2: + referedseg = read2bytes(fip->file); + break; + case 4: + referedseg = read4bytes(fip->file); + break; + } + if (!sip->refers) + markpage0seg(fip, referedseg); + } + if (sip->countofrefered > 0) + sip->refers = true; + /* 7.2.6 Segment page association */ + /* 7.2.7 Segment data length */ + if (sip->pageassocsizeflag) + xfseek(fip->file, 8, SEEK_CUR, fip->filepath); + else + xfseek(fip->file, 5, SEEK_CUR, fip->filepath); + /* ---- at end of segment header ---- */ +} + +/**********************************************************************/ + +void checkseghdrflags(SEGINFO * sip) +{ + sip->endofstripeflag = false; + sip->endofpageflag = false; + sip->pageinfoflag = false; + sip->endoffileflag = false; + /* 7.3 Segment types */ + switch (sip->seghdrflags & 0x3f) { + case M_SymbolDictionary: + case M_IntermediateTextRegion: + case M_ImmediateTextRegion: + case M_ImmediateLosslessTextRegion: + case M_PatternDictionary: + case M_IntermediateHalftoneRegion: + case M_ImmediateHalftoneRegion: + case M_ImmediateLosslessHalftoneRegion: + case M_IntermediateGenericRegion: + case M_ImmediateGenericRegion: + case M_ImmediateLosslessGenericRegion: + case M_IntermediateGenericRefinementRegion: + case M_ImmediateGenericRefinementRegion: + case M_ImmediateLosslessGenericRefinementRegion: + break; + case M_PageInformation: + sip->pageinfoflag = true; + break; + case M_EndOfPage: + sip->endofpageflag = true; + break; + case M_EndOfStripe: + sip->endofstripeflag = true; + break; + case M_EndOfFile: + sip->endoffileflag = true; + break; + case M_Profiles: + case M_Tables: + case M_Extension: + break; + default: + pdftex_fail + ("checkseghdrflags(): unknown segment type in JBIG2 image file"); + break; + } +} + +/**********************************************************************/ + +void markpage0seg(FILEINFO * fip, unsigned long referedseg) +{ + PAGEINFO *pip; + SEGINFO *sip; + pip = fip->page0.first->d; + sip = find_seginfo(&(pip->segments), referedseg); + if (sip != NULL) { + if (!sip->refers && sip->countofrefered > 0) + checkseghdr(fip, sip); + sip->isrefered = true; + } +} + +/**********************************************************************/ + +unsigned long findstreamstart(FILEINFO * fip) +{ + SEGINFO tmp; + assert(!fip->sequentialaccess); /* D.2 Random-access organisation */ + do /* find random-access stream start */ + (void) readseghdr(fip, &tmp); + while (!tmp.endoffileflag); + fip->streamstart = tmp.hdrend; + readfilehdr(fip); + return fip->streamstart; +} + +/**********************************************************************/ + +void rd_jbig2_info(FILEINFO * fip) +{ + unsigned long seekdist = 0; /* for sequential-access only */ + unsigned long streampos = 0; /* for random-access only */ + unsigned long currentpage = 0; + boolean sipavail = false; + PAGEINFO *pip; + SEGINFO *sip = NULL; + LIST *plp, *slp; + fip->file = xfopen(fip->filepath, FOPEN_RBIN_MODE); + readfilehdr(fip); + if (!fip->sequentialaccess) /* D.2 Random-access organisation */ + streampos = findstreamstart(fip); + while (true) { /* loop over segments */ + if (!sipavail) { + sip = xtalloc(1, SEGINFO); + sipavail = true; + } + init_seginfo(sip); + if (!readseghdr(fip, sip) || sip->endoffileflag) + break; + if (sip->segpage > 0) { + if (sip->segpage > currentpage) { + plp = litem_append(&(fip->pages)); + plp->last->d = new_pageinfo(); + currentpage = sip->segpage; + } + pip = fip->pages.last->d; + } else { + if (fip->page0.last == NULL) { + plp = litem_append(&(fip->page0)); + plp->last->d = new_pageinfo(); + } + pip = fip->page0.last->d; + } + if (!sip->endofpageflag) { + slp = litem_append(&(pip->segments)); + slp->last->d = sip; + sipavail = false; + } + if (!fip->sequentialaccess) + sip->datastart = streampos; + else + sip->datastart = sip->hdrend; + sip->dataend = sip->datastart + sip->segdatalen; + if (!fip->sequentialaccess + && (sip->pageinfoflag || sip->endofstripeflag)) + xfseek(fip->file, sip->datastart, SEEK_SET, fip->filepath); + seekdist = sip->segdatalen; + /* 7.4.8 Page information segment syntax */ + if (sip->pageinfoflag) { + pip->pagenum = sip->segpage; + pip->width = read4bytes(fip->file); + pip->height = read4bytes(fip->file); + pip->xres = read4bytes(fip->file); + pip->yres = read4bytes(fip->file); + pip->pagesegmentflags = ygetc(fip->file); + /* 7.4.8.6 Page striping information */ + pip->stripinginfo = read2bytes(fip->file); + seekdist -= 19; + } + if (sip->endofstripeflag) { + pip->stripedheight = read4bytes(fip->file); + seekdist -= 4; + } + if (!fip->sequentialaccess + && (sip->pageinfoflag || sip->endofstripeflag)) + xfseek(fip->file, sip->hdrend, SEEK_SET, fip->filepath); + if (!fip->sequentialaccess) + streampos += sip->segdatalen; + if (fip->sequentialaccess) + xfseek(fip->file, seekdist, SEEK_CUR, fip->filepath); + if (sip->endofpageflag && currentpage && (pip->stripinginfo >> 15)) + pip->height = pip->stripedheight; + } + fip->phase = HAVEINFO; + if (sipavail) + xfree(sip); + xfclose(fip->file, fip->filepath); +} + +/**********************************************************************/ + +void wr_jbig2(FILEINFO * fip, unsigned long page) +{ + LITEM *slip; + PAGEINFO *pip; + SEGINFO *sip; + unsigned long i; + if (page > 0) { + pip = find_pageinfo(&(fip->pages), page); + assert(pip != NULL); + pdf_puts("/Type /XObject\n/Subtype /Image\n"); + pdf_printf("/Width %i\n", pip->width); + pdf_printf("/Height %i\n", pip->height); + pdf_puts("/ColorSpace /DeviceGray\n"); + pdf_puts("/BitsPerComponent 1\n"); + pdf_printf("/Length %lu\n", getstreamlen(pip->segments.first, true)); + pdf_puts("/Filter [/JBIG2Decode]\n"); + if (fip->page0.last != NULL) { + if (fip->pdfpage0objnum == 0) { + pdf_create_obj(0, 0); + fip->pdfpage0objnum = obj_ptr; + } + pdf_printf("/DecodeParms [<< /JBIG2Globals %lu 0 R >>]\n", + fip->pdfpage0objnum); + } + } else { + pip = find_pageinfo(&(fip->page0), page); + assert(pip != NULL); + pdf_begin_dict(fip->pdfpage0objnum, 0); + pdf_printf("/Length %lu\n", getstreamlen(pip->segments.first, false)); + } + pdf_puts(">>\n"); + pdf_puts("stream\n"); + fip->file = xfopen(fip->filepath, FOPEN_RBIN_MODE); + for (slip = pip->segments.first; slip != NULL; slip = slip->next) { /* loop over page segments */ + sip = slip->d; + if (sip->isrefered || page > 0) { + xfseek(fip->file, sip->hdrstart, SEEK_SET, fip->filepath); + /* mark refered-to page 0 segments, change segpages > 1 to 1 */ + writeseghdr(fip, sip); + xfseek(fip->file, sip->datastart, SEEK_SET, fip->filepath); + for (i = sip->datastart; i < sip->dataend; i++) + pdfout(ygetc(fip->file)); + } + } + pdf_end_stream(); + xfclose(fip->file, fip->filepath); +} + +/**********************************************************************/ + +void read_jbig2_info(image_dict * idict) +{ + FILEINFO *fip, tmp; + PAGEINFO *pip; + void **aa; + assert(idict != NULL); + img_type(idict) = IMAGE_TYPE_JBIG2; + if (img_pagenum(idict) < 1) + pdftex_fail + ("read_jbig2_info(): page %d not in JBIG2 image file; page must be > 0", + (int) img_pagenum(idict)); + if (file_tree == NULL) { + file_tree = avl_create(comp_file_entry, NULL, &avl_xallocator); + assert(file_tree != NULL); + } + tmp.filepath = img_filepath(idict); + fip = (FILEINFO *) avl_find(file_tree, &tmp); + if (fip == NULL) { + fip = new_fileinfo(); + fip->filepath = xstrdup(img_filepath(idict)); + aa = avl_probe(file_tree, fip); + assert(aa != NULL); + } + if (fip->phase == INITIAL) { + rd_jbig2_info(fip); + pages_maketree(&(fip->pages)); + if (fip->page0.last != NULL) { + pages_maketree(&(fip->page0)); + pip = fip->page0.first->d; + segments_maketree(&(pip->segments)); + } + } + pip = find_pageinfo(&(fip->pages), img_pagenum(idict)); + if (pip == NULL) + pdftex_fail("read_jbig2_info(): page %d not found in JBIG2 image file", + (int) img_pagenum(idict)); + img_xsize(idict) = pip->width; + img_ysize(idict) = pip->height; + img_xres(idict) = (int) (pip->xres * 0.0254 + 0.5); + img_yres(idict) = (int) (pip->yres * 0.0254 + 0.5); + img_colordepth(idict) = 1; +} + +/**********************************************************************/ + +void write_jbig2(image_dict * idict) +{ + FILEINFO *fip, tmp; + PAGEINFO *pip; + assert(idict != NULL); + assert(file_tree != NULL); + tmp.filepath = img_filepath(idict); + fip = (FILEINFO *) avl_find(file_tree, &tmp); + assert(fip != NULL); + assert(fip->phase == HAVEINFO); /* don't write before rd_jbig2_info() call */ + pip = find_pageinfo(&(fip->pages), img_pagenum(idict)); + assert(pip != NULL); + wr_jbig2(fip, pip->pagenum); + img_file(idict) = NULL; +} + +/**********************************************************************/ + +void flush_jbig2_page0_objects() +{ + FILEINFO *fip; + struct avl_traverser t; + if (file_tree != NULL) { + avl_t_init(&t, file_tree); + for (fip = avl_t_first(&t, file_tree); fip != NULL; + fip = avl_t_next(&t)) { + if (fip->page0.last != NULL) + wr_jbig2(fip, 0); + } + } +} + +/**********************************************************************/ diff --git a/Build/source/texk/web2c/luatexdir/image/writejbig2.h b/Build/source/texk/web2c/luatexdir/image/writejbig2.h new file mode 100644 index 00000000000..c1bec32d859 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/image/writejbig2.h @@ -0,0 +1,151 @@ +/*********************************************************************** +Copyright (c) 2002-2006 Han The Thanh, + +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 + +This is experimental JBIG2 image support to pdfTeX. JBIG2 image decoding +is part of Adobe PDF-1.4, and requires Acroread 5.0 or later. + +$Id: writejbig2.h 1012 2008-02-14 00:00:57Z oneiros $ +***********************************************************************/ + +#include +#include +#include +#include "ptexlib.h" +#include "ptexmac.h" +#include "image.h" + +/* 7.3 Segment types */ +#define M_SymbolDictionary 0 +#define M_IntermediateTextRegion 4 +#define M_ImmediateTextRegion 6 +#define M_ImmediateLosslessTextRegion 7 +#define M_PatternDictionary 16 +#define M_IntermediateHalftoneRegion 20 +#define M_ImmediateHalftoneRegion 22 +#define M_ImmediateLosslessHalftoneRegion 23 +#define M_IntermediateGenericRegion 36 +#define M_ImmediateGenericRegion 38 +#define M_ImmediateLosslessGenericRegion 39 +#define M_IntermediateGenericRefinementRegion 40 +#define M_ImmediateGenericRefinementRegion 42 +#define M_ImmediateLosslessGenericRefinementRegion 43 +#define M_PageInformation 48 +#define M_EndOfPage 49 +#define M_EndOfStripe 50 +#define M_EndOfFile 51 +#define M_Profiles 52 +#define M_Tables 53 +#define M_Extension 62 + +/**********************************************************************/ + +typedef enum { INITIAL, HAVEINFO, WRITEPDF } PHASE; + +typedef struct _LITEM { + struct _LITEM *prev; + struct _LITEM *next; + void *d; /* data */ +} LITEM; + +typedef struct _LIST { + LITEM *first; + LITEM *last; + struct avl_table *tree; +} LIST; + +typedef struct _SEGINFO { + unsigned long segnum; + boolean isrefered; + boolean refers; + unsigned int seghdrflags; /* set by readseghdr() */ + boolean pageassocsizeflag; /* set by readseghdr() */ + unsigned int reftosegcount; /* set by readseghdr() */ + unsigned int countofrefered; /* set by readseghdr() */ + unsigned int fieldlen; /* set by readseghdr() */ + unsigned int segnumwidth; /* set by readseghdr() */ + long segpage; /* set by readseghdr() */ + unsigned long segdatalen; /* set by readseghdr() */ + unsigned long hdrstart; /* set by readseghdr() */ + unsigned long hdrend; /* set by readseghdr() */ + unsigned long datastart; + unsigned long dataend; + boolean endofstripeflag; /* set by checkseghdrflags() */ + boolean endofpageflag; /* set by checkseghdrflags() */ + boolean pageinfoflag; /* set by checkseghdrflags() */ + boolean endoffileflag; /* set by checkseghdrflags() */ +} SEGINFO; + +typedef struct _PAGEINFO { + LIST segments; /* segments associated with page */ + unsigned long pagenum; + unsigned int width; + unsigned int height; + unsigned int xres; + unsigned int yres; + unsigned int pagesegmentflags; + unsigned int stripinginfo; + unsigned int stripedheight; +} PAGEINFO; + +typedef struct _FILEINFO { + FILE *file; + char *filepath; + long filesize; + LIST pages; /* not including page0 */ + LIST page0; + unsigned int filehdrflags; /* set by readfilehdr() */ + boolean sequentialaccess; /* set by readfilehdr() */ + unsigned long numofpages; /* set by readfilehdr() */ + unsigned long streamstart; /* set by get_jbig2_info() */ + unsigned long pdfpage0objnum; + PHASE phase; +} FILEINFO; + +/**********************************************************************/ + +static int comp_file_entry(const void *, const void *, void *); +static int comp_page_entry(const void *, const void *, void *); +static int comp_segment_entry(const void *, const void *, void *); +int ygetc(FILE *); +FILEINFO *new_fileinfo(); +PAGEINFO *new_pageinfo(); +void initseginfo(SEGINFO *); +void initlinkedlist(LIST *); +LIST *litem_append(LIST *); +void pages_maketree(LIST *); +void segments_maketree(LIST *); +PAGEINFO *find_pageinfo(LIST *, unsigned long); +SEGINFO *find_seginfo(LIST *, unsigned long); +unsigned int read2bytes(FILE *); +unsigned long read4bytes(FILE *); +unsigned long getstreamlen(LITEM *, boolean); +void readfilehdr(FILEINFO *); +boolean readseghdr(FILEINFO *, SEGINFO *); +void writeseghdr(FILEINFO *, SEGINFO *); +void checkseghdr(FILEINFO *, SEGINFO *); +void checkseghdrflags(SEGINFO * sip); +void markpage0seg(FILEINFO *, unsigned long); +unsigned long findstreamstart(FILEINFO *); +void rd_jbig2_info(FILEINFO *); +void wr_jbig2(FILEINFO *, unsigned long); +void read_jbig2_info(image_dict *); +void write_jbig2(image_dict *); +void flushjbig2page0objects(); + +/**********************************************************************/ diff --git a/Build/source/texk/web2c/luatexdir/image/writejpg.c b/Build/source/texk/web2c/luatexdir/image/writejpg.c new file mode 100644 index 00000000000..422c29470fb --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/image/writejpg.c @@ -0,0 +1,277 @@ +/* +Copyright (c) 1996-2006 Han The Thanh, + +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: writejpg.c 1100 2008-03-09 13:40:48Z hhenkel $ +*/ + +#include +#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 close_and_cleanup_jpg(image_dict * idict) +{ + assert(idict != NULL); + assert(img_file(idict) != NULL); + assert(img_filepath(idict) != NULL); + xfclose(img_file(idict), img_filepath(idict)); + img_file(idict) = NULL; + assert(img_jpg_ptr(idict) != NULL); + xfree(img_jpg_ptr(idict)); + img_jpg_ptr(idict) = NULL; +} + +void read_jpg_info(image_dict * idict, img_readtype_e readtype) +{ + int i, units = 0; + unsigned char jpg_id[] = "JFIF"; + assert(idict != NULL); + assert(img_type(idict) == IMAGE_TYPE_JPG); + img_totalpages(idict) = 1; + img_pagenum(idict) = 1; + img_xres(idict) = img_yres(idict) = 0; + assert(img_file(idict) == NULL); + img_file(idict) = xfopen(img_filepath(idict), FOPEN_RBIN_MODE); + assert(img_jpg_ptr(idict) == NULL); + img_jpg_ptr(idict) = xtalloc(1, jpg_img_struct); + xfseek(img_file(idict), 0, SEEK_END, img_filepath(idict)); + img_jpg_ptr(idict)->length = xftell(img_file(idict), img_filepath(idict)); + xfseek(img_file(idict), 0, SEEK_SET, img_filepath(idict)); + if (read2bytes(img_file(idict)) != 0xFFD8) + pdftex_fail("reading JPEG image failed (no JPEG header found)"); + /* currently only true JFIF files allow extracting img_xres and img_yres */ + if (read2bytes(img_file(idict)) == 0xFFE0) { /* check for JFIF */ + (void) read2bytes(img_file(idict)); + for (i = 0; i < 5; i++) { + if (xgetc(img_file(idict)) != jpg_id[i]) + break; + } + if (i == 5) { /* it's JFIF */ + read2bytes(img_file(idict)); + units = xgetc(img_file(idict)); + img_xres(idict) = read2bytes(img_file(idict)); + img_yres(idict) = read2bytes(img_file(idict)); + switch (units) { + case 1: + break; /* pixels per inch */ + case 2: + img_xres(idict) *= 2.54; + img_yres(idict) *= 2.54; + break; /* pixels per cm */ + default: + img_xres(idict) = img_yres(idict) = 0; + break; + } + } + } + xfseek(img_file(idict), 0, SEEK_SET, img_filepath(idict)); + while (1) { + if (feof(img_file(idict))) + pdftex_fail("reading JPEG image failed (premature file end)"); + if (fgetc(img_file(idict)) != 0xFF) + pdftex_fail("reading JPEG image failed (no marker found)"); + switch (xgetc(img_file(idict))) { + 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 (fixed_pdf_minor_version <= 2) + pdftex_fail("cannot use progressive DCT with PDF-1.2"); + case M_SOF0: + case M_SOF1: + case M_SOF3: + (void) read2bytes(img_file(idict)); /* read segment length */ + img_colordepth(idict) = xgetc(img_file(idict)); + img_ysize(idict) = read2bytes(img_file(idict)); + img_xsize(idict) = read2bytes(img_file(idict)); + img_jpg_color(idict) = xgetc(img_file(idict)); + xfseek(img_file(idict), 0, SEEK_SET, img_filepath(idict)); + switch (img_jpg_color(idict)) { + case JPG_GRAY: + img_color(idict) = IMAGE_COLOR_B; + break; + case JPG_RGB: + img_color(idict) = IMAGE_COLOR_C; + break; + case JPG_CMYK: + img_color(idict) = IMAGE_COLOR_C; + break; + default: + pdftex_fail("Unsupported color space %i", + (int) img_jpg_color(idict)); + } + if (readtype == IMG_CLOSEINBETWEEN) + close_and_cleanup_jpg(idict); + 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(img_file(idict), read2bytes(img_file(idict)) - 2, + SEEK_CUR, img_filepath(idict)); + break; + } + } + assert(0); +} + +static void reopen_jpg(image_dict * idict) +{ + integer width, height, xres, yres; + width = img_xsize(idict); + height = img_ysize(idict); + xres = img_xres(idict); + yres = img_yres(idict); + read_jpg_info(idict, IMG_KEEPOPEN); + if (width != img_xsize(idict) || height != img_ysize(idict) + || xres != img_xres(idict) || yres != img_yres(idict)) + pdftex_fail("writejpg: image dimensions have changed"); +} + +void write_jpg(image_dict * idict) +{ + long unsigned l; + FILE *f; + assert(idict != NULL); + if (img_file(idict) == NULL) + reopen_jpg(idict); + assert(img_jpg_ptr(idict) != NULL); + pdf_puts("/Type /XObject\n/Subtype /Image\n"); + if (img_attr(idict) != NULL && strlen(img_attr(idict)) > 0) + pdf_printf("%s\n", img_attr(idict)); + pdf_printf("/Width %i\n/Height %i\n/BitsPerComponent %i\n/Length %i\n", + (int) img_xsize(idict), + (int) img_ysize(idict), + (int) img_colordepth(idict), (int) img_jpg_ptr(idict)->length); + pdf_puts("/ColorSpace "); + if (img_colorspace(idict) != 0) { + pdf_printf("%i 0 R\n", (int) img_colorspace(idict)); + } else { + switch (img_jpg_color(idict)) { + 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) img_jpg_color(idict)); + } + } + pdf_puts("/Filter /DCTDecode\n>>\nstream\n"); + for (l = img_jpg_ptr(idict)->length, f = img_file(idict); l > 0; l--) + pdfout(xgetc(f)); + pdf_end_stream(); + close_and_cleanup_jpg(idict); +} diff --git a/Build/source/texk/web2c/luatexdir/image/writepng.c b/Build/source/texk/web2c/luatexdir/image/writepng.c new file mode 100644 index 00000000000..7f1269d9943 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/image/writepng.c @@ -0,0 +1,635 @@ +/* +Copyright (c) 1996-2004 Han The Thanh, + +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: writepng.c 1101 2008-03-09 16:12:15Z hhenkel $ +*/ + +#include +#include "ptexlib.h" +#include "image.h" + +void close_and_cleanup_png(image_dict * idict) +{ + assert(idict != NULL); + assert(img_file(idict) != NULL); + assert(img_filepath(idict) != NULL); + xfclose(img_file(idict), img_filepath(idict)); + img_file(idict) = NULL; + assert(img_png_ptr(idict) != NULL); + png_destroy_read_struct(&(img_png_png_ptr(idict)), + &(img_png_info_ptr(idict)), NULL); + xfree(img_png_ptr(idict)); + img_png_ptr(idict) = NULL; +} + +void read_png_info(image_dict * idict, img_readtype_e readtype) +{ + double gamma; + png_structp png_p; + png_infop info_p; + assert(idict != NULL); + assert(img_type(idict) == IMAGE_TYPE_PNG); + img_totalpages(idict) = 1; + img_pagenum(idict) = 1; + img_xres(idict) = img_yres(idict) = 0; + assert(img_file(idict) == NULL); + img_file(idict) = xfopen(img_filepath(idict), FOPEN_RBIN_MODE); + assert(img_png_ptr(idict) == NULL); + img_png_ptr(idict) = xtalloc(1, png_img_struct); + if ((png_p = png_create_read_struct(PNG_LIBPNG_VER_STRING, + NULL, NULL, NULL)) == NULL) + pdftex_fail("libpng: png_create_read_struct() failed"); + img_png_png_ptr(idict) = png_p; + if ((info_p = png_create_info_struct(png_p)) == NULL) + pdftex_fail("libpng: png_create_info_struct() failed"); + img_png_info_ptr(idict) = info_p; + if (setjmp(png_p->jmpbuf)) + pdftex_fail("libpng: internal error"); + png_init_io(png_p, img_file(idict)); + png_read_info(png_p, info_p); + /* simple transparency support */ + if (png_get_valid(png_p, info_p, PNG_INFO_tRNS)) { + png_set_tRNS_to_alpha(png_p); + } + /* alpha channel support */ + if (fixed_pdf_minor_version < 4 && png_p->color_type | PNG_COLOR_MASK_ALPHA) + png_set_strip_alpha(png_p); + /* 16bit depth support */ + if (fixed_pdf_minor_version < 5) + fixed_image_hicolor = 0; + if (info_p->bit_depth == 16 && !fixed_image_hicolor) + png_set_strip_16(png_p); + /* gamma support */ + if (fixed_image_apply_gamma) { + if (png_get_gAMA(png_p, info_p, &gamma)) + png_set_gamma(png_p, (fixed_gamma / 1000.0), gamma); + else + png_set_gamma(png_p, (fixed_gamma / 1000.0), + (1000.0 / fixed_image_gamma)); + } + /* reset structure */ + png_read_update_info(png_p, info_p); + /* resolution support */ + img_xsize(idict) = info_p->width; + img_ysize(idict) = info_p->height; + if (info_p->valid & PNG_INFO_pHYs) { + img_xres(idict) = + round(0.0254 * png_get_x_pixels_per_meter(png_p, info_p)); + img_yres(idict) = + round(0.0254 * png_get_y_pixels_per_meter(png_p, info_p)); + } + switch (info_p->color_type) { + case PNG_COLOR_TYPE_PALETTE: + img_color(idict) = IMAGE_COLOR_C | IMAGE_COLOR_I; + break; + case PNG_COLOR_TYPE_GRAY: + case PNG_COLOR_TYPE_GRAY_ALPHA: + img_color(idict) = IMAGE_COLOR_B; + break; + case PNG_COLOR_TYPE_RGB: + case PNG_COLOR_TYPE_RGB_ALPHA: + img_color(idict) = IMAGE_COLOR_C; + break; + default: + pdftex_fail("unsupported type of color_type <%i>", info_p->color_type); + } + img_colordepth(idict) = info_p->bit_depth; + if (readtype == IMG_CLOSEINBETWEEN) + close_and_cleanup_png(idict); +} + +#define write_gray_pixel_16(r) \ + if (j % 4 == 0||j % 4 == 1) pdf_buf[pdf_ptr++] = *r++; \ + else smask[smask_ptr++] = *r++ + +#define write_gray_pixel_8(r) \ + if (j % 2 == 0) pdf_buf[pdf_ptr++] = *r++; \ + else smask[smask_ptr++] = *r++ + + +#define write_rgb_pixel_16(r) \ + if (!(j % 8 == 6||j % 8 == 7)) pdf_buf[pdf_ptr++] = *r++; \ + else smask[smask_ptr++] = *r++ + +#define write_rgb_pixel_8(r) \ + if (j % 4 != 3) pdf_buf[pdf_ptr++] = *r++; \ + else smask[smask_ptr++] = *r++ + +#define write_simple_pixel(r) pdf_buf[pdf_ptr++] = *r++ + +#define write_noninterlaced(outmac) \ + for (i = 0; (unsigned) i < (int)info_p->height; i++) { \ + png_read_row(png_p, row, NULL); \ + r = row; \ + k = info_p->rowbytes; \ + while(k > 0) { \ + l = (k > pdf_buf_size)? pdf_buf_size : k; \ + pdfroom(l); \ + for (j = 0; j < l; j++) { \ + outmac; \ + } \ + k -= l; \ + } \ + } + +#define write_interlaced(outmac) \ + for (i = 0; (unsigned) i < (int)info_p->height; i++) { \ + row = rows[i]; \ + k = info_p->rowbytes; \ + while(k > 0) { \ + l = (k > pdf_buf_size)? pdf_buf_size : k;\ + pdfroom(l); \ + for (j = 0; j < l; j++) { \ + outmac; \ + } \ + k -= l; \ + } \ + xfree(rows[i]); \ + } + +void write_png_palette(image_dict * idict) +{ + int i, j, k, l; + png_structp png_p = img_png_png_ptr(idict); + png_infop info_p = img_png_info_ptr(idict); + png_bytep row, r, *rows; + integer palette_objnum = 0; + if (img_colorspace(idict) != 0) { + pdf_printf("%i 0 R\n", (int) img_colorspace(idict)); + } else { + pdf_create_obj(0, 0); + palette_objnum = obj_ptr; + pdf_printf("[/Indexed /DeviceRGB %i %i 0 R]\n", + (int) (info_p->num_palette - 1), (int) palette_objnum); + } + pdf_begin_stream(); + if (info_p->interlace_type == PNG_INTERLACE_NONE) { + row = xtalloc(info_p->rowbytes, png_byte); + write_noninterlaced(write_simple_pixel(r)); + xfree(row); + } else { + if (info_p->height * info_p->rowbytes >= 10240000L) + pdftex_warn + ("large interlaced PNG might cause out of memory (use non-interlaced PNG to fix this)"); + rows = xtalloc(info_p->height, png_bytep); + for (i = 0; (unsigned) i < info_p->height; i++) + rows[i] = xtalloc(info_p->rowbytes, png_byte); + png_read_image(png_p, rows); + write_interlaced(write_simple_pixel(row)); + xfree(rows); + } + pdf_end_stream(); + if (palette_objnum > 0) { + pdf_begin_dict(palette_objnum, 0); + pdf_begin_stream(); + for (i = 0; (unsigned) i < info_p->num_palette; i++) { + pdfroom(3); + pdf_buf[pdf_ptr++] = info_p->palette[i].red; + pdf_buf[pdf_ptr++] = info_p->palette[i].green; + pdf_buf[pdf_ptr++] = info_p->palette[i].blue; + } + pdf_end_stream(); + } +} + +void write_png_gray(image_dict * idict) +{ + int i, j, k, l; + png_structp png_p = img_png_png_ptr(idict); + png_infop info_p = img_png_info_ptr(idict); + png_bytep row, r, *rows; + if (img_colorspace(idict) != 0) { + pdf_printf("%i 0 R\n", (int) img_colorspace(idict)); + } else { + pdf_puts("/DeviceGray\n"); + } + pdf_begin_stream(); + if (info_p->interlace_type == PNG_INTERLACE_NONE) { + row = xtalloc(info_p->rowbytes, png_byte); + write_noninterlaced(write_simple_pixel(r)); + xfree(row); + } else { + if (info_p->height * info_p->rowbytes >= 10240000L) + pdftex_warn + ("large interlaced PNG might cause out of memory (use non-interlaced PNG to fix this)"); + rows = xtalloc(info_p->height, png_bytep); + for (i = 0; (unsigned) i < info_p->height; i++) + rows[i] = xtalloc(info_p->rowbytes, png_byte); + png_read_image(png_p, rows); + write_interlaced(write_simple_pixel(row)); + xfree(rows); + } + pdf_end_stream(); +} + +void write_png_gray_alpha(image_dict * idict) +{ + int i, j, k, l; + png_structp png_p = img_png_png_ptr(idict); + png_infop info_p = img_png_info_ptr(idict); + 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(idict) != 0) { + pdf_printf("%i 0 R\n", (int) img_colorspace(idict)); + } else { + pdf_puts("/DeviceGray\n"); + } + pdf_create_obj(0, 0); + smask_objnum = obj_ptr; + pdf_printf("/SMask %i 0 R\n", (int) smask_objnum); + smask_size = (info_p->rowbytes / 2) * info_p->height; + smask = xtalloc(smask_size, png_byte); + pdf_begin_stream(); + if (info_p->interlace_type == PNG_INTERLACE_NONE) { + row = xtalloc(info_p->rowbytes, png_byte); + if ((info_p->bit_depth == 16) && fixed_image_hicolor) { + write_noninterlaced(write_gray_pixel_16(r)); + } else { + write_noninterlaced(write_gray_pixel_8(r)); + } + xfree(row); + } else { + if (info_p->height * info_p->rowbytes >= 10240000L) + pdftex_warn + ("large interlaced PNG might cause out of memory (use non-interlaced PNG to fix this)"); + rows = xtalloc(info_p->height, png_bytep); + for (i = 0; (unsigned) i < info_p->height; i++) + rows[i] = xtalloc(info_p->rowbytes, png_byte); + png_read_image(png_p, rows); + if ((info_p->bit_depth == 16) && fixed_image_hicolor) { + write_interlaced(write_gray_pixel_16(row)); + } else { + write_interlaced(write_gray_pixel_8(row)); + } + xfree(rows); + } + pdf_end_stream(); + pdf_flush(); + /* now write the Smask object */ + bitdepth = (int) info_p->bit_depth; + pdf_begin_dict(smask_objnum, 0); + pdf_puts("/Type /XObject\n/Subtype /Image\n"); + if (img_attr(idict) != NULL && strlen(img_attr(idict)) > 0) + pdf_printf("%s\n", img_attr(idict)); + pdf_printf("/Width %i\n/Height %i\n/BitsPerComponent %i\n", + (int) info_p->width, + (int) info_p->height, (bitdepth == 16 ? 8 : bitdepth)); + pdf_puts("/ColorSpace /DeviceGray\n"); + pdf_begin_stream(); + for (i = 0; i < smask_size; i++) { + if (i % 8 == 0) + pdfroom(8); + pdf_buf[pdf_ptr++] = smask[i]; + if (bitdepth == 16) + i++; + } + pdf_end_stream(); + xfree(smask); +} + +void write_png_rgb(image_dict * idict) +{ + int i, j, k, l; + png_structp png_p = img_png_png_ptr(idict); + png_infop info_p = img_png_info_ptr(idict); + png_bytep row, r, *rows; + if (img_colorspace(idict) != 0) { + pdf_printf("%i 0 R\n", (int) img_colorspace(idict)); + } else { + pdf_puts("/DeviceRGB\n"); + } + pdf_begin_stream(); + if (info_p->interlace_type == PNG_INTERLACE_NONE) { + row = xtalloc(info_p->rowbytes, png_byte); + write_noninterlaced(write_simple_pixel(r)); + xfree(row); + } else { + if (info_p->height * info_p->rowbytes >= 10240000L) + pdftex_warn + ("large interlaced PNG might cause out of memory (use non-interlaced PNG to fix this)"); + rows = xtalloc(info_p->height, png_bytep); + for (i = 0; (unsigned) i < info_p->height; i++) + rows[i] = xtalloc(info_p->rowbytes, png_byte); + png_read_image(png_p, rows); + write_interlaced(write_simple_pixel(row)); + xfree(rows); + } + pdf_end_stream(); +} + +void write_png_rgb_alpha(image_dict * idict) +{ + int i, j, k, l; + png_structp png_p = img_png_png_ptr(idict); + png_infop info_p = img_png_info_ptr(idict); + 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(idict) != 0) { + pdf_printf("%i 0 R\n", (int) img_colorspace(idict)); + } else { + pdf_puts("/DeviceRGB\n"); + } + pdf_create_obj(0, 0); + smask_objnum = obj_ptr; + pdf_printf("/SMask %i 0 R\n", (int) smask_objnum); + smask_size = (info_p->rowbytes / 2) * info_p->height; + smask = xtalloc(smask_size, png_byte); + pdf_begin_stream(); + if (info_p->interlace_type == PNG_INTERLACE_NONE) { + row = xtalloc(info_p->rowbytes, png_byte); + if ((info_p->bit_depth == 16) && fixed_image_hicolor) { + write_noninterlaced(write_rgb_pixel_16(r)); + } else { + write_noninterlaced(write_rgb_pixel_8(r)); + } + xfree(row); + } else { + if (info_p->height * info_p->rowbytes >= 10240000L) + pdftex_warn + ("large interlaced PNG might cause out of memory (use non-interlaced PNG to fix this)"); + rows = xtalloc(info_p->height, png_bytep); + for (i = 0; (unsigned) i < info_p->height; i++) + rows[i] = xtalloc(info_p->rowbytes, png_byte); + png_read_image(png_p, rows); + if ((info_p->bit_depth == 16) && fixed_image_hicolor) { + write_interlaced(write_rgb_pixel_16(row)); + } else { + write_interlaced(write_rgb_pixel_8(row)); + } + xfree(rows); + } + pdf_end_stream(); + pdf_flush(); + /* now write the Smask object */ + if (smask_objnum > 0) { + bitdepth = (int) info_p->bit_depth; + pdf_begin_dict(smask_objnum, 0); + pdf_puts("/Type /XObject\n/Subtype /Image\n"); + if (img_attr(idict) != NULL) + pdf_printf("%s\n", img_attr(idict)); + pdf_printf("/Width %i\n/Height %i\n/BitsPerComponent %i\n", + (int) info_p->width, + (int) info_p->height, (bitdepth == 16 ? 8 : bitdepth)); + pdf_puts("/ColorSpace /DeviceGray\n"); + pdf_begin_stream(); + for (i = 0; i < smask_size; i++) { + if (i % 8 == 0) + pdfroom(8); + pdf_buf[pdf_ptr++] = smask[i]; + if (bitdepth == 16) + i++; + } + xfree(smask); + pdf_end_stream(); + } +} + +/**********************************************************************/ +/* + * 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(image_dict * idict) +{ + assert(idict != NULL); + png_structp png_p = img_png_png_ptr(idict); + png_infop info_p = img_png_info_ptr(idict); + FILE *fp = (FILE *) png_p->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 ", info_p->color_type == 2 ? 3 : 1); + pdf_printf("/Columns %d ", (int) info_p->width); + pdf_printf("/BitsPerComponent %i ", (int) info_p->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 > pdf_buf_size) ? pdf_buf_size : len; + pdfroom(i); + fread(&pdf_buf[pdf_ptr], 1, i, fp); + pdf_ptr += 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_end_stream(); + 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 reopen_png(image_dict * idict) +{ + integer width, height, xres, yres; + width = img_xsize(idict); /* do consistency check */ + height = img_ysize(idict); + xres = img_xres(idict); + yres = img_yres(idict); + read_png_info(idict, IMG_KEEPOPEN); + if (width != img_xsize(idict) || height != img_ysize(idict) + || xres != img_xres(idict) || yres != img_yres(idict)) + pdftex_fail("writepng: image dimensions have changed"); +} + +void write_png(image_dict * idict) +{ + double gamma, checked_gamma; + int i; + integer palette_objnum = 0; + assert(idict != NULL); + if (img_file(idict) == NULL) + reopen_png(idict); + assert(img_png_ptr(idict) != NULL); + png_structp png_p = img_png_png_ptr(idict); + png_infop info_p = img_png_info_ptr(idict); + if (fixed_pdf_minor_version < 5) + fixed_image_hicolor = 0; + pdf_puts("/Type /XObject\n/Subtype /Image\n"); + if (img_attr(idict) != NULL && strlen(img_attr(idict)) > 0) + pdf_printf("%s\n", img_attr(idict)); + pdf_printf("/Width %i\n/Height %i\n/BitsPerComponent %i\n", + (int) info_p->width, + (int) info_p->height, (int) info_p->bit_depth); + pdf_puts("/ColorSpace "); + checked_gamma = 1.0; + if (fixed_image_apply_gamma) { + if (png_get_gAMA(png_p, info_p, &gamma)) { + checked_gamma = (fixed_gamma / 1000.0) * gamma; + } else { + checked_gamma = + (fixed_gamma / 1000.0) * (1000.0 / fixed_image_gamma); + } + } + /* the switching between |info_p| and |png_p| queries has been trial and error. + */ + if (fixed_pdf_minor_version > 1 && info_p->interlace_type == PNG_INTERLACE_NONE && (png_p->transformations == 0 || png_p->transformations == 0x2000) /* gamma */ + &&!(png_p->color_type == PNG_COLOR_TYPE_GRAY_ALPHA || + png_p->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + && (fixed_image_hicolor || (png_p->bit_depth <= 8)) + && (checked_gamma <= 1.01 && checked_gamma > 0.99) + ) { + if (img_colorspace(idict) != 0) { + pdf_printf("%i 0 R\n", (int) img_colorspace(idict)); + } else { + switch (info_p->color_type) { + case PNG_COLOR_TYPE_PALETTE: + pdf_create_obj(0, 0); + palette_objnum = obj_ptr; + pdf_printf("[/Indexed /DeviceRGB %i %i 0 R]\n", + (int) (info_p->num_palette - 1), + (int) palette_objnum); + break; + case PNG_COLOR_TYPE_GRAY: + pdf_puts("/DeviceGray\n"); + break; + default: /* RGB */ + pdf_puts("/DeviceRGB\n"); + }; + } + if (tracefilenames) + tex_printf(" (PNG copy)"); + copy_png(idict); + if (palette_objnum > 0) { + pdf_begin_dict(palette_objnum, 0); + pdf_begin_stream(); + for (i = 0; (unsigned) i < info_p->num_palette; i++) { + pdfroom(3); + pdf_buf[pdf_ptr++] = info_p->palette[i].red; + pdf_buf[pdf_ptr++] = info_p->palette[i].green; + pdf_buf[pdf_ptr++] = info_p->palette[i].blue; + } + pdf_end_stream(); + } + } else { + if (0) { + tex_printf(" PNG copy skipped because: "); + if (fixed_image_apply_gamma && + (checked_gamma > 1.01 || checked_gamma < 0.99)) + tex_printf("gamma delta=%lf ", checked_gamma); + if (png_p->transformations != PNG_TRANSFORM_IDENTITY) + tex_printf("transform=%lu", (long) png_p->transformations); + if ((info_p->color_type != PNG_COLOR_TYPE_GRAY) + && (info_p->color_type != PNG_COLOR_TYPE_RGB) + && (info_p->color_type != PNG_COLOR_TYPE_PALETTE)) + tex_printf("colortype "); + if (fixed_pdf_minor_version <= 1) + tex_printf("version=%d ", (int) fixed_pdf_minor_version); + if (info_p->interlace_type != PNG_INTERLACE_NONE) + tex_printf("interlaced "); + if (info_p->bit_depth > 8) + tex_printf("bitdepth=%d ", info_p->bit_depth); + if (png_get_valid(png_p, info_p, PNG_INFO_tRNS)) + tex_printf("simple transparancy "); + } + switch (info_p->color_type) { + case PNG_COLOR_TYPE_PALETTE: + write_png_palette(idict); + break; + case PNG_COLOR_TYPE_GRAY: + write_png_gray(idict); + break; + case PNG_COLOR_TYPE_GRAY_ALPHA: + if (fixed_pdf_minor_version >= 4) + write_png_gray_alpha(idict); + else + write_png_gray(idict); + break; + case PNG_COLOR_TYPE_RGB: + write_png_rgb(idict); + break; + case PNG_COLOR_TYPE_RGB_ALPHA: + if (fixed_pdf_minor_version >= 4) + write_png_rgb_alpha(idict); + else + write_png_rgb(idict); + break; + default: + pdftex_fail("unsupported type of color_type <%i>", + info_p->color_type); + } + } + pdf_flush(); + close_and_cleanup_png(idict); +} diff --git a/Build/source/texk/web2c/luatexdir/lang/hnjalloc.c b/Build/source/texk/web2c/luatexdir/lang/hnjalloc.c new file mode 100644 index 00000000000..59d62e2aabb --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lang/hnjalloc.c @@ -0,0 +1,72 @@ +/* LibHnj is dual licensed under LGPL and MPL. Boilerplate for both + * licenses follows. + */ + +/* LibHnj - a library for high quality hyphenation and justification + * Copyright (C) 1998 Raph Levien, (C) 2001 ALTLinux, Moscow + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307 USA. +*/ + +/* + * The contents of this file are subject to the Mozilla Public License + * Version 1.0 (the "MPL"); you may not use this file except in + * compliance with the MPL. You may obtain a copy of the MPL at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the MPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL + * for the specific language governing rights and limitations under the + * MPL. + * + */ +/* wrappers for malloc */ + +#include +#include + +void * +hnj_malloc (int size) +{ + void *p; + + p = malloc (size); + if (p == NULL) + { + fprintf (stderr, "can't allocate %d bytes\n", size); + exit (1); + } + return p; +} + +void * +hnj_realloc (void *p, int size) +{ + p = realloc (p, size); + if (p == NULL) + { + fprintf (stderr, "can't allocate %d bytes\n", size); + exit (1); + } + return p; +} + +void +hnj_free (void *p) +{ + free (p); +} + diff --git a/Build/source/texk/web2c/luatexdir/lang/hnjalloc.h b/Build/source/texk/web2c/luatexdir/lang/hnjalloc.h new file mode 100644 index 00000000000..db82fb9c758 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lang/hnjalloc.h @@ -0,0 +1,46 @@ +/* LibHnj is dual licensed under LGPL and MPL. Boilerplate for both + * licenses follows. + */ + +/* LibHnj - a library for high quality hyphenation and justification + * Copyright (C) 1998 Raph Levien + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307 USA. +*/ + +/* + * The contents of this file are subject to the Mozilla Public License + * Version 1.0 (the "MPL"); you may not use this file except in + * compliance with the MPL. You may obtain a copy of the MPL at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the MPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL + * for the specific language governing rights and limitations under the + * MPL. + * + */ +/* wrappers for malloc */ + +void * +hnj_malloc (int size); + +void * +hnj_realloc (void *p, int size); + +void +hnj_free (void *p); + diff --git a/Build/source/texk/web2c/luatexdir/lang/hyphen.c b/Build/source/texk/web2c/luatexdir/lang/hyphen.c new file mode 100644 index 00000000000..140cde8d768 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lang/hyphen.c @@ -0,0 +1,830 @@ +/* Libhnj is dual licensed under LGPL and MPL. Boilerplate for both + * licenses follows. + */ + +/* LibHnj - a library for high quality hyphenation and justification + * Copyright (C) 1998 Raph Levien, + * (C) 2001 ALTLinux, Moscow (http://www.alt-linux.org), + * (C) 2001 Peter Novodvorsky (nidd@cs.msu.su) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307 USA. +*/ + +/* + * The contents of this file are subject to the Mozilla Public License + * Version 1.0 (the "MPL"); you may not use this file except in + * compliance with the MPL. You may obtain a copy of the MPL at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the MPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL + * for the specific language governing rights and limitations under the + * MPL. + * + */ +#include /* for NULL, malloc */ +#include /* for fprintf */ +#include /* for strdup */ +#include /* for malloc used by substring inclusion*/ + +#define MAXPATHS 40960 + +#ifdef UNX +#include /* for exit */ +#endif + +#include + +/*#define VERBOSE*/ + +#include "hnjalloc.h" +#include "hyphen.h" + +/* SHOULD BE MOVED TO SEPARATE LIBRARY */ +static unsigned char * hnj_strdup( + const unsigned char *s +) { + unsigned char *new; + int l; + + l = strlen ((char*)s); + new = hnj_malloc (l + 1); + memcpy (new, s, l); + new[l] = 0; + return new; +} + +static int is_utf8_follow( + unsigned char c +) { + if (c>=0x80 && c<0xC0) return 1; + return 0; +} + +/* -------------------------------------------------------------------- + * + * Type definitions + * + * -------------------------------------------------------------------- + */ + +/* a little bit of a hash table implementation. This simply maps strings + to state numbers */ + +typedef struct _HashTab HashTab; +typedef struct _HashEntry HashEntry; +typedef struct _HashIter HashIter; +typedef union _HashVal HashVal; + +/* A cheap, but effective, hack. */ +#define HASH_SIZE 31627 + +struct _HashTab { + HashEntry *entries[HASH_SIZE]; +}; + +union _HashVal { + int state; + char* hyppat; +}; + +struct _HashEntry { + HashEntry *next; + unsigned char *key; + HashVal u; +}; + +struct _HashIter { + HashEntry** e; + HashEntry* cur; + int ndx; +}; + +/* State machine */ +typedef struct _HyphenState HyphenState; +typedef struct _HyphenTrans HyphenTrans; +#define MAX_CHARS 256 +#define MAX_NAME 20 + +struct _HyphenDict { + int num_states; + int pat_length; + char cset[MAX_NAME]; + HyphenState *states; + HashTab *patterns; + HashTab *merged; + HashTab *state_num; +}; + +struct _HyphenState { + char *match; + /*char *repl;*/ + /*signed char replindex;*/ + /*signed char replcut;*/ + int fallback_state; + int num_trans; + HyphenTrans *trans; +}; + +struct _HyphenTrans { + int uni_ch; + int new_state; +}; + + +/* Combine two right-aligned number patterns, 04000 + 020 becomes 04020*/ +static char *combine( + char *expr, + const char *subexpr +) { + int l1 = strlen(expr); + int l2 = strlen(subexpr); + int off = l1-l2; + int j; + /* this works also for utf8 sequences because the substring is identical + * to the last substring-length bytes of expr except for the (single byte) + * hyphenation encoders + */ + for (j=0; je = h->entries; + i->cur = NULL; + i->ndx = -1; + return i; +} + + +int nextHashStealPattern( + HashIter*i, + unsigned char**word, + char **pattern +) { + while (i->cur==NULL) { + if (i->ndx >= HASH_SIZE-1) return 0; + i->cur = i->e[++i->ndx]; + } + *word = i->cur->key; + *pattern = i->cur->u.hyppat; + i->cur->u.hyppat = NULL; + i->cur = i->cur->next; + return 1; +} + + +int nextHash( + HashIter*i, + unsigned char**word +) { + while (i->cur==NULL) { + if (i->ndx >= HASH_SIZE-1) return 0; + i->cur = i->e[++i->ndx]; + } + *word = i->cur->key; + i->cur = i->cur->next; + return 1; +} + + +int eachHash( + HashIter*i, + unsigned char**word, + char**pattern +) { + while (i->cur==NULL) { + if (i->ndx >= HASH_SIZE-1) return 0; + i->cur = i->e[++i->ndx]; + } + *word = i->cur->key; + *pattern = i->cur->u.hyppat; + i->cur = i->cur->next; + return 1; +} + + +void delete_HashIter( + HashIter*i +) { + hnj_free(i); +} + + +/* a char* hash function from ASU - adapted from Gtk+ */ +static unsigned int hnj_string_hash ( + const unsigned char *s +) { + const unsigned char *p; + unsigned int h=0, g; + + for (p = s; *p != '\0'; p += 1) { + h = ( h << 4 ) + *p; + if ( ( g = h & 0xf0000000 ) ) { + h = h ^ (g >> 24); + h = h ^ g; + } + } + return h /* % M */; +} + + +/* assumes that key is not already present! */ +static void state_insert( + HashTab *hashtab, + unsigned char *key, + int state +) { + int i; + HashEntry *e; + + i = hnj_string_hash (key) % HASH_SIZE; + e = hnj_malloc (sizeof(HashEntry)); + e->next = hashtab->entries[i]; + e->key = key; + e->u.state = state; + hashtab->entries[i] = e; +} + + +/* assumes that key is not already present! */ +static void hyppat_insert( + HashTab *hashtab, + unsigned char *key, + char* hyppat +) { + int i; + HashEntry *e; + + i = hnj_string_hash (key) % HASH_SIZE; + for (e = hashtab->entries[i]; e; e=e->next) { + if (strcmp((char*)e->key,(char*)key)==0) { + if (e->u.hyppat) hnj_free(e->u.hyppat); + e->u.hyppat = hyppat; + hnj_free(key); + return; + } + } + e = hnj_malloc (sizeof(HashEntry)); + e->next = hashtab->entries[i]; + e->key = key; + e->u.hyppat = hyppat; + hashtab->entries[i] = e; +} + + +/* return state if found, otherwise -1 */ +static int state_lookup( + HashTab *hashtab, + const unsigned char *key +) { + int i; + HashEntry *e; + + i = hnj_string_hash (key) % HASH_SIZE; + for (e = hashtab->entries[i]; e; e = e->next) { + if (!strcmp ((char*)key, (char*)e->key)) { + return e->u.state; + } + } + return -1; +} + + +/* return state if found, otherwise -1 */ +static char* hyppat_lookup( + HashTab *hashtab, + const unsigned char *chars, + int l +) { + int i; + HashEntry *e; + unsigned char key[128]; /* should be ample*/ + strncpy((char*)key,(char*)chars,l); key[l]=0; + i = hnj_string_hash (key) % HASH_SIZE; + for (e = hashtab->entries[i]; e; e = e->next) { + if (!strcmp ((char*)key, (char*)e->key)) { + return e->u.hyppat; + } + } + return NULL; +} + + +/* Get the state number, allocating a new state if necessary. */ +static int hnj_get_state( + HyphenDict *dict, + const unsigned char *string, + int *state_num +) { + *state_num = state_lookup(dict->state_num, string); + + if (*state_num >= 0) + return *state_num; + + state_insert(dict->state_num, hnj_strdup(string), dict->num_states); + /* predicate is true if dict->num_states is a power of two */ + if (!(dict->num_states & (dict->num_states - 1))) { + dict->states = hnj_realloc( + dict->states, + (dict->num_states << 1) * sizeof(HyphenState)); + } + dict->states[dict->num_states].match = NULL; + dict->states[dict->num_states].fallback_state = -1; + dict->states[dict->num_states].num_trans = 0; + dict->states[dict->num_states].trans = NULL; + return dict->num_states++; +} + + +/* add a transition from state1 to state2 through ch - assumes that the + transition does not already exist */ +static void hnj_add_trans( + HyphenDict *dict, + int state1, + int state2, + int uni_ch +) { + int num_trans; + /* TH: this test was a bit too strict, it is quite normal for old + patterns to have chars in the range 0-31 or 127-159 (inclusive). + To ease the transition, let's only disallow NUL for now + (this is probably a requirement of the code anyway). + */ + if (uni_ch==0) { + fprintf(stderr,"Character out of bounds: u%04x \n",uni_ch); + exit(1); + } + num_trans = dict->states[state1].num_trans; + if (num_trans == 0) { + dict->states[state1].trans = hnj_malloc(sizeof(HyphenTrans)); + } else if (!(num_trans & (num_trans - 1))) { + dict->states[state1].trans = hnj_realloc( + dict->states[state1].trans, + (num_trans << 1) * sizeof(HyphenTrans)); + } + dict->states[state1].trans[num_trans].uni_ch = uni_ch; + dict->states[state1].trans[num_trans].new_state = state2; + dict->states[state1].num_trans++; +} + + +#ifdef VERBOSE + +static unsigned char *get_state_str( + int state +) { + int i; + HashEntry *e; + + for (i = 0; i < HASH_SIZE; i++) + for (e = global->entries[i]; e; e = e->next) + if (e->u.state == state) + return e->key; + return NULL; +} +#endif + + +/* I've changed the semantics a bit here: hnj_hyphen_load used to + operate on a file, but now the argument is a string buffer. + */ + +static const unsigned char* next_pattern( + size_t* length, + const unsigned char **buf +) { + const unsigned char *rover = *buf; + while (*rover && isspace(*rover)) rover++; + const unsigned char *here = rover; + while (*rover) { + if (isspace(*rover)) { + *length = rover-here; + *buf = rover; + return here; + } + rover++; + } + *length = rover-here; + *buf = rover; + return *length ? here : NULL; /* zero sensed */ +} + +static void init_hash( + HashTab**h +) { + if (*h) return; + int i; + *h = hnj_malloc(sizeof(HashTab)); + for (i = 0; i < HASH_SIZE; i++) (*h)->entries[i] = NULL; +} + + +static void clear_state_hash( + HashTab**h +) { + if (*h==NULL) return; + int i; + for (i = 0; i < HASH_SIZE; i++) { + HashEntry *e, *next; + for (e = (*h)->entries[i]; e; e = next) { + next = e->next; + hnj_free (e->key); + hnj_free (e); + } + } + hnj_free(*h); + *h=NULL; +} + + +static void clear_hyppat_hash( + HashTab**h +) { + if (*h==NULL) return; + int i; + for (i = 0; i < HASH_SIZE; i++) { + HashEntry *e, *next; + for (e = (*h)->entries[i]; e; e = next) { + next = e->next; + hnj_free(e->key); + if (e->u.hyppat) hnj_free(e->u.hyppat); + hnj_free(e); + } + } + hnj_free(*h); + *h=NULL; +} + + +static void init_dict( + HyphenDict* dict +) { + dict->num_states = 1; + dict->pat_length = 0; + dict->states = hnj_malloc (sizeof(HyphenState)); + dict->states[0].match = NULL; + dict->states[0].fallback_state = -1; + dict->states[0].num_trans = 0; + dict->states[0].trans = NULL; + dict->patterns = NULL; + dict->merged = NULL; + dict->state_num = NULL; + init_hash(&dict->patterns); +} + + +static void clear_dict( + HyphenDict* dict +) { + int state_num; + for (state_num = 0; state_num < dict->num_states; state_num++) { + HyphenState *hstate = &dict->states[state_num]; + if (hstate->match) hnj_free (hstate->match); + if (hstate->trans) hnj_free (hstate->trans); + } + hnj_free (dict->states); + clear_hyppat_hash(&dict->patterns); + clear_hyppat_hash(&dict->merged); + clear_state_hash(&dict->state_num); +} + + + +HyphenDict* hnj_hyphen_new() { + HyphenDict* dict = hnj_malloc (sizeof(HyphenDict)); + init_dict(dict); + return dict; +} + + +void hnj_hyphen_clear( + HyphenDict* dict +) { + clear_dict(dict); + init_dict(dict); +} + + +void hnj_hyphen_free( + HyphenDict *dict +) { + clear_dict(dict); + hnj_free(dict); +} + +unsigned char* hnj_serialize( + HyphenDict* dict +) { + HashIter *v; + unsigned char* word; + char* pattern; + unsigned char* buf = hnj_malloc(dict->pat_length); + unsigned char* cur = buf; + v = new_HashIter(dict->patterns); + while (eachHash(v,&word,&pattern)) { + int i=0, e=0; + while(word[e+i]) { + if (pattern[i]!='0') *cur++ = (unsigned char) pattern[i]; + *cur++ = word[e+i++]; + while (is_utf8_follow(word[e+i])) *cur++ = word[i+e++]; + } + if (pattern[i]!='0') *cur++ = (unsigned char) pattern[i]; + *cur++ = ' '; + } + delete_HashIter(v); + *cur = 0; + return buf; +} + + +void hnj_free_serialize( + unsigned char* c +) { + hnj_free(c); +} + + +/* hyphenation pattern: + * signed bytes + * 0 indicates end (actually any negative number) + * : prio(1+),startpos,length,len1,[replace],len2,[replace] + * most basic example is: + * p n 0 0 0 + * for a hyphenation point between characters + */ + + +void hnj_hyphen_load( + HyphenDict* dict, + const unsigned char *f +) { + int state_num, last_state; + int i, j = 0; + int ch; + int found; + HashEntry *e; + HashIter *v; + unsigned char* word; + char* pattern; + size_t l = 0; + + + /***************************************/ + + const unsigned char* format; + const unsigned char* begin = f; + while((format = next_pattern(&l,&f))!=NULL) { + int i,j,e; + /* + printf("%s\n",format); + char* repl = strnchr(format, '/',l); + int replindex = 0; + int replcut = 0; + if (repl) { + int clen = l-(repl-format); + l = repl-format; + char * index = strnchr(repl + 1, ',',clen); + if (index) { + char * index2 = strnchr(index + 1, ',',clen-(index-repl)); + if (index2) { + replindex = (signed char) atoi(index + 1) - 1; + replcut = (signed char) atoi(index2 + 1); + } + } else { + hnj_strchomp(repl + 1); + replindex = 0; + replcut = strlen(buf); + } + repl = hnj_strdup(repl + 1); + } + */ + for (i=0,j=0,e=0; i='0'&&format[i]<='9') j++; + if (is_utf8_follow(format[i])) e++; + } + /* l-e => number of _characters_ not _bytes_*/ + /* l-e-j => number of pattern characters*/ + unsigned char *pat = (unsigned char*) malloc(1+l-j); + char *org = ( char*) malloc(2+l-e-j); + /* remove hyphenation encoders (digits) from pat*/ + org[0] = '0'; + for (i=0,j=0,e=0; i'9') { + pat[e+j++] = c; + org[j] = '0'; + } else { + org[j] = c; + } + } + pat[e+j] = 0; + org[j+1] = 0; + hyppat_insert(dict->patterns,pat,org); + } + dict->pat_length += (f-begin)+2; /* 2 for spurious spaces*/ + init_hash(&dict->merged); + v = new_HashIter(dict->patterns); + while (nextHash(v,&word)) { + int wordsize = strlen((char*)word); + int j,l; + for (l=1; l<=wordsize; l++) { + if (is_utf8_follow(word[l])) continue; /* Do not clip an utf8 sequence*/ + for (j=1; j<=l; j++) { + int i = l-j; + if (is_utf8_follow(word[i])) continue; /* Do not start halfway an utf8 sequence*/ + char *subpat_pat; + if ((subpat_pat = hyppat_lookup(dict->patterns,word+i,j))!=NULL) { + char* newpat_pat; + if ((newpat_pat = hyppat_lookup(dict->merged,word,l))==NULL) { + unsigned char *newword=(unsigned char*)malloc(l+1); + strncpy((char*)newword, (char*)word,l); newword[l]=0; + int e=0; + for (i=0; imerged,newword,combine(neworg,subpat_pat)); + } else { + combine(newpat_pat,subpat_pat); + } + } + } + } + } + delete_HashIter(v); + + init_hash(&dict->state_num); + state_insert(dict->state_num, hnj_strdup((unsigned char*)""), 0); + v = new_HashIter(dict->merged); + while (nextHashStealPattern(v,&word,&pattern)) { + static unsigned char mask[] = {0x3F,0x1F,0xF,0x7}; + int j = strlen((char*)word); +#ifdef VERBOSE + printf ("word %s pattern %s, j = %d\n", word, pattern, j); +#endif + state_num = hnj_get_state( dict, word, &found ); + dict->states[state_num].match = pattern; + + /* now, put in the prefix transitions */ + while (found < 0) { + j--; + last_state = state_num; + ch = word[j]; + if (ch>=0x80) { + int i=1; + while (is_utf8_follow(word[j-i])) i++; + ch = word[j-i] & mask[i]; + int m = j-i; + while (i--) { + ch = (ch<<6)+(0x3F & word[j-i]); + } + j = m; + } + word[j] = '\0'; + state_num = hnj_get_state (dict, word, &found); + hnj_add_trans (dict, state_num, last_state, ch); + } + } + delete_HashIter(v); + clear_hyppat_hash(&dict->merged); + + /***************************************/ + + /* put in the fallback states */ + for (i = 0; i < HASH_SIZE; i++) { + for (e = dict->state_num->entries[i]; e; e = e->next) { + /* do not do state==0 otherwise things get confused*/ + if (e->u.state) { + for (j = 1; 1; j++) { + state_num = state_lookup(dict->state_num, e->key + j); + if (state_num >= 0) break; + } + dict->states[e->u.state].fallback_state = state_num; + } + } + } +#ifdef VERBOSE + for (i = 0; i < HASH_SIZE; i++) { + for (e = dict->state_num->entries[i]; e; e = e->next) { + printf ("%d string %s state %d, fallback=%d\n", i, e->key, e->u.state, + dict->states[e->u.state].fallback_state); + for (j = 0; j < dict->states[e->u.state].num_trans; j++) { + printf (" u%4x->%d\n", (int)dict->states[e->u.state].trans[j].uni_ch, + dict->states[e->u.state].trans[j].new_state); + } + } + } +#endif + clear_state_hash(&dict->state_num); +} + + +void hnj_hyphen_hyphenate( + HyphenDict *dict, + halfword first, + halfword last, + int length, + halfword left, + halfword right, + lang_variables *lan +) { + /* +2 for dots at each end, +1 for points /outside/ characters*/ + int ext_word_len = length+2; + int hyphen_len = ext_word_len+1; + /*char *hyphens = hnj_malloc((hyphen_len*2)+1); */ /* LATER */ + char *hyphens = hnj_malloc(hyphen_len+1); + + /* Add a '.' to beginning and end to facilitate matching*/ + set_vlink(begin_point,first); + set_vlink(end_point,get_vlink(last)); + set_vlink(last,end_point); + + int char_num; + for (char_num = 0; char_num < hyphen_len; char_num++) { + /* hyphens[char_num*2] = '0'; */ /* LATER */ + /* hyphens[char_num*2+1] = '0'; */ /* LATER */ + hyphens[char_num] = '0'; + } + /*hyphens[hyphen_len*2] = 0; */ /* LATER */ + hyphens[hyphen_len] = 0; + + /* now, run the finite state machine */ + int state = 0; + halfword here; + for (char_num=0, here=begin_point; here!=end_point; here=get_vlink(here)) { + + int ch = get_character(here); + + while (state!=-1) { + /* printf("%*s%s%c",char_num-strlen(get_state_str(state)),"",get_state_str(state),(char)ch);*/ + HyphenState *hstate = &dict->states[state]; + int k; + for (k = 0; k < hstate->num_trans; k++) { + if (hstate->trans[k].uni_ch == ch) { + state = hstate->trans[k].new_state; + /* printf(" state %d\n",state);*/ + char *match = dict->states[state].match; + if (match) { + /* +2 because: + * 1 string length is one bigger than offset + * 1 hyphenation starts before first character + */ + int offset = char_num + 2 - strlen (match); + /* printf ("%*s%s\n", offset,"", match);*/ + int m; + for (m = 0; match[m]; m++) { + if (hyphens[offset+m] < match[m]) hyphens[offset+m] = match[m]; + } + } + goto try_next_letter; + } + } + state = hstate->fallback_state; + /* printf (" back to %d\n", state);*/ + } + /* nothing worked, let's go to the next character*/ + state = 0; +try_next_letter: ; + char_num++; + } + + /* restore the correct pointers*/ + set_vlink(last,get_vlink(end_point)); + + /* pattern is ^.^w^o^r^d^.^ word_len=4, ext_word_len=6, hyphens=7 + * check ^ ^ ^ so drop first two and stop after word_len-1 + */ + for (here=first,char_num=2; here!=left; here=get_vlink(here)) char_num++; + for (; here!=right; here=get_vlink(here)) { + if (hyphens[char_num] & 1) + here = insert_syllable_discretionary(here, lan); + char_num++; + } + hnj_free(hyphens); +} diff --git a/Build/source/texk/web2c/luatexdir/lang/texlang.c b/Build/source/texk/web2c/luatexdir/lang/texlang.c new file mode 100644 index 00000000000..12390ae2fcf --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lang/texlang.c @@ -0,0 +1,825 @@ +/* +Copyright (c) 2007 Taco Hoekwater + +This file is part of luatex. + +luatex 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. + +luatex 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 luatex; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +This is texlang.c +*/ + +#include "luatex-api.h" +#include + +#include + +#include "nodes.h" +#include "hyphen.h" + +/* functions from the fontforge unicode library */ + +extern unsigned int *utf82u_strcpy(unsigned int *ubuf,const char *utf8buf); +extern unsigned int u_strlen(unsigned int *ubuf); +extern char *utf8_idpb(char *w,unsigned int i); + +#define noVERBOSE + +#define MAX_TEX_LANGUAGES 32767 + +static struct tex_language *tex_languages[MAX_TEX_LANGUAGES] = {NULL}; +static int next_lang_id = 0; + +struct tex_language * +new_language (void) { + struct tex_language* lang; + if (next_lang_idid = next_lang_id++; + lang->exceptions = 0; + lang->patterns = NULL; + lang->pre_hyphen_char = '-'; + lang->post_hyphen_char = 0; + return lang; + } else { + return NULL; + } +} + +struct tex_language * +get_language (int n) { + if (n>=0 && n<=MAX_TEX_LANGUAGES ) { + if (tex_languages[n]!=NULL) { + return tex_languages[n]; + } else { + return new_language(); + } + } else { + return NULL; + } +} + +void +set_pre_hyphen_char (integer n, integer v) { + struct tex_language *l = get_language((int)n); + l->pre_hyphen_char = (int)v; +} + +void +set_post_hyphen_char (integer n, integer v) { + struct tex_language *l = get_language((int)n); + l->post_hyphen_char = (int)v; +} + +integer +get_pre_hyphen_char (integer n) { + struct tex_language *l = get_language((int)n); + return (integer)l->pre_hyphen_char; +} + +integer +get_post_hyphen_char (integer n) { + struct tex_language *l = get_language((int)n); + return (integer)l->post_hyphen_char; +} + +void +load_patterns (struct tex_language *lang, unsigned char *buffer) { + if (lang==NULL) + return; + if (lang->patterns==NULL) { + lang->patterns = hnj_hyphen_new(); + } + hnj_hyphen_load (lang->patterns,buffer); +} + +void +clear_patterns (struct tex_language *lang) { + if (lang==NULL) + return; + if (lang->patterns!=NULL) { + hnj_hyphen_clear(lang->patterns); + } +} + +void +load_tex_patterns(int curlang, halfword head) { + char *s = tokenlist_to_cstring (head,1, NULL); + load_patterns(get_language(curlang),(unsigned char *)s); +} + + +#define STORE_CHAR(x) { word[w] = x ; if (wexceptions==0) { + lua_newtable(L); + lang->exceptions = luaL_ref(L,LUA_REGISTRYINDEX); + } + lua_rawgeti(L, LUA_REGISTRYINDEX, lang->exceptions); + s = (char *)buffer; + while (*s) { + while (isspace(*s)) s++; + if (*s) { + value = s; + s = clean_hyphenation(s, &cleaned); + if (cleaned!=NULL) { + if ((s-value)>0) { + lua_pushstring(L,cleaned); + lua_pushlstring(L,value,(s-value)); + lua_rawset(L,-3); + } + free(cleaned); + } else { +#ifdef VERBOSE + fprintf(stderr,"skipping invalid hyphenation exception: %s\n",value); +#endif + } + } + } +} + +void +clear_hyphenation (struct tex_language *lang) { + if (lang==NULL) + return; + if (lang->exceptions!=0) { + luaL_unref(Luas[0],LUA_REGISTRYINDEX,lang->exceptions); + lang->exceptions = 0; + } +} + + +void +load_tex_hyphenation(int curlang, halfword head) { + char *s = tokenlist_to_cstring (head,1, NULL); + load_hyphenation(get_language(curlang),(unsigned char *)s); +} + +/* TODO: clean this up. The delete_attribute_ref() statements are not very + nice, but needed. Also, in the post-break, it would be nicer to get the + attribute list from vlink(n). No rush, as it is currently not used much. */ + +halfword insert_discretionary ( halfword t, halfword pre, halfword post, halfword replace) { + halfword g, n; + n = new_node(disc_node,syllable_disc); + try_couple_nodes(n,vlink(t)); + couple_nodes(t,n); + for (g=pre;g!=null;g=vlink(g)) { + font(g)=font(replace); + if (node_attr(t)!=null) { + delete_attribute_ref(node_attr(g)); + node_attr(g) = node_attr(t); + attr_list_ref(node_attr(t)) += 1; + } + } + for (g=post;g!=null;g =vlink(g)) { + font(g)=font(replace); + if (node_attr(t)!=null) { + delete_attribute_ref(node_attr(g)); + node_attr(g) = node_attr(t); + attr_list_ref(node_attr(t)) += 1; + } + } + for (g=replace;g!=null;g =vlink(g)) { + if (node_attr(t)!=null) { + delete_attribute_ref(node_attr(g)); + node_attr(g) = node_attr(t); + attr_list_ref(node_attr(t)) += 1; + } + } + if (node_attr(t)!=null) { + delete_attribute_ref(node_attr(vlink(t))); + node_attr(vlink(t)) = node_attr(t); + attr_list_ref(node_attr(t)) += 1; + } + t = vlink(t); + set_disc_field(pre_break(t),pre); + set_disc_field(post_break(t),post); + set_disc_field(no_break(t),replace); + return t; +} + +halfword +insert_syllable_discretionary ( halfword t, lang_variables *lan) { + halfword g, n; + n = new_node(disc_node,syllable_disc); + couple_nodes(n,vlink(t)); + couple_nodes(t,n); + delete_attribute_ref(node_attr(n)); + if (node_attr(t)!=null) { + node_attr(n) = node_attr(t); + attr_list_ref(node_attr(t))++ ; + } else { + node_attr(n) = null; + } + if (lan->pre_hyphen_char >0) { + g = raw_glyph_node(); + set_to_character(g); + character(g)=lan->pre_hyphen_char; + font(g)=font(t); + lang_data(g)=lang_data(t); + if (node_attr(t)!=null) { + node_attr(g) = node_attr(t); + attr_list_ref(node_attr(t)) ++; + } + set_disc_field(pre_break(n),g); + } + + if (lan->post_hyphen_char >0) { + t = vlink(n); + g = raw_glyph_node(); + set_to_character(g); + character(g)=lan->post_hyphen_char; + font(g)=font(t); + lang_data(g)=lang_data(t); + if (node_attr(t)!=null) { + node_attr(g) = node_attr(t); + attr_list_ref(node_attr(t)) += 1; + } + set_disc_field(post_break(n),g); + } + return n; +} + +halfword insert_word_discretionary ( halfword t, lang_variables *lan) { + halfword pre = null, pos = null; + if (lan->pre_hyphen_char >0) pre = insert_character ( null, lan->pre_hyphen_char); + if (lan->post_hyphen_char>0) pos = insert_character ( null, lan->post_hyphen_char); + return insert_discretionary ( t, pre, pos, null); +} + +halfword insert_complex_discretionary ( halfword t, lang_variables *lan, + halfword pre, halfword pos, halfword replace) { + return insert_discretionary ( t, pre, pos, replace); +} + + +halfword insert_character ( halfword t, int c) { + halfword p; + p=new_node(glyph_node,0); + set_to_character(p); + character(p)=c; + if (t!=null) { + couple_nodes(t,p); + } + return p; +} + + +void +set_disc_field (halfword f, halfword t) { + if (t!=null) { + couple_nodes(f,t); + tlink(f) = tail_of_list(t); + } +} + + + +char *hyphenation_exception(int exceptions, char *w) { + char *ret = NULL; + lua_State *L = Luas[0]; + lua_checkstack(L,2); + lua_rawgeti(L,LUA_REGISTRYINDEX,exceptions); + if (lua_istable(L,-1)) { /* ?? */ + lua_pushstring(L,w); /* word table */ + lua_rawget(L,-2); + if (lua_isstring(L,-1)) { + ret = xstrdup((char *)lua_tostring(L,-1)); + } + lua_pop(L,2); + } else { + lua_pop(L,1); + } + return ret; +} + + +char *exception_strings(struct tex_language *lang) { + char *value; + int size = 0, current =0; + size_t l =0; + char *ret = NULL; + lua_State *L = Luas[0]; + if (lang->exceptions==0) + return NULL; + lua_checkstack(L,2); + lua_rawgeti(L,LUA_REGISTRYINDEX,lang->exceptions); + if (lua_istable(L,-1)) { + /* iterate and join */ + lua_pushnil(L); /* first key */ + while (lua_next(L,-2) != 0) { + value = (char *)lua_tolstring(L, -1, &l); + if (current + 2 + l > size ) { + ret = xrealloc(ret, (1.2*size)+current+l+1024); + size = (1.2*size)+current+l+1024; + } + *(ret+current) = ' '; + strcpy(ret+current+1,value); + current += l+1; + lua_pop(L, 1); + } + } + return ret; +} + + +/* the sequence from |wordstart| to |r| can contain only normal characters */ +/* it could be faster to modify a halfword pointer and return an integer */ + +halfword find_exception_part(int *j, int *uword, int len) { + halfword g = null, gg = null; + register int i = *j; + i++; /* this puts uword[i] on the '{' */ + while (i0) { + halfword q = t; + replace = vlink(q); + while(repl>0 && q!=null) { + q=vlink(q); + if (type(q)==glyph_node) { + repl--; + } + } + try_couple_nodes(t,vlink(q)); + vlink(q)=null; + } + t = insert_discretionary(t,gg,hh,replace); + } else { + t = vlink(t); + } + } +} + +/* This is a documentation section from the pascal web file. It is not +true any more, but I do not have time right now to rewrite it -- Taco + +When the line-breaking routine is unable to find a feasible sequence of +breakpoints, it makes a second pass over the paragraph, attempting to +hyphenate the hyphenatable words. The goal of hyphenation is to insert +discretionary material into the paragraph so that there are more +potential places to break. + +The general rules for hyphenation are somewhat complex and technical, +because we want to be able to hyphenate words that are preceded or +followed by punctuation marks, and because we want the rules to work +for languages other than English. We also must contend with the fact +that hyphens might radically alter the ligature and kerning structure +of a word. + +A sequence of characters will be considered for hyphenation only if it +belongs to a ``potentially hyphenatable part'' of the current paragraph. +This is a sequence of nodes $p_0p_1\ldots p_m$ where $p_0$ is a glue node, +$p_1\ldots p_{m-1}$ are either character or ligature or whatsit or +implicit kern nodes, and $p_m$ is a glue or penalty or insertion or adjust +or mark or whatsit or explicit kern node. (Therefore hyphenation is +disabled by boxes, math formulas, and discretionary nodes already inserted +by the user.) The ligature nodes among $p_1\ldots p_{m-1}$ are effectively +expanded into the original non-ligature characters; the kern nodes and +whatsits are ignored. Each character |c| is now classified as either a +nonletter (if |lc_code(c)=0|), a lowercase letter (if +|lc_code(c)=c|), or an uppercase letter (otherwise); an uppercase letter +is treated as if it were |lc_code(c)| for purposes of hyphenation. The +characters generated by $p_1\ldots p_{m-1}$ may begin with nonletters; let +$c_1$ be the first letter that is not in the middle of a ligature. Whatsit +nodes preceding $c_1$ are ignored; a whatsit found after $c_1$ will be the +terminating node $p_m$. All characters that do not have the same font as +$c_1$ will be treated as nonletters. The |hyphen_char| for that font +must be between 0 and 255, otherwise hyphenation will not be attempted. +\TeX\ looks ahead for as many consecutive letters $c_1\ldots c_n$ as +possible; however, |n| must be less than 64, so a character that would +otherwise be $c_{64}$ is effectively not a letter. Furthermore $c_n$ must +not be in the middle of a ligature. In this way we obtain a string of +letters $c_1\ldots c_n$ that are generated by nodes $p_a\ldots p_b$, where +|1<=a<=b+1<=m|. If |n>=l_hyf+r_hyf|, this string qualifies for hyphenation; +however, |uc_hyph| must be positive, if $c_1$ is uppercase. + +The hyphenation process takes place in three stages. First, the candidate +sequence $c_1\ldots c_n$ is found; then potential positions for hyphens +are determined by referring to hyphenation tables; and finally, the nodes +$p_a\ldots p_b$ are replaced by a new sequence of nodes that includes the +discretionary breaks found. + +Fortunately, we do not have to do all this calculation very often, because +of the way it has been taken out of \TeX's inner loop. For example, when +the second edition of the author's 700-page book {\sl Seminumerical +Algorithms} was typeset by \TeX, only about 1.2 hyphenations needed to be +@^Knuth, Donald Ervin@> +tried per paragraph, since the line breaking algorithm needed to use two +passes on only about 5 per cent of the paragraphs. + + +When a word been set up to contain a candidate for hyphenation, +\TeX\ first looks to see if it is in the user's exception dictionary. If not, +hyphens are inserted based on patterns that appear within the given word, +using an algorithm due to Frank~M. Liang. +@^Liang, Franklin Mark@> +*/ + +/* + * This is incompatible with TEX because the first word of a paragraph + * can be hyphenated, but most european users seem to agree that + * prohibiting hyphenation there was not a the best idea ever. + */ + +halfword find_next_wordstart(halfword r) { + register int l; + register int start_ok = 1; + int mathlevel = 1; + while (r!=null) { + switch (type(r)) { + case glue_node: + start_ok = 1; + break; + case math_node: + while (mathlevel>0 ){ + r = vlink(r); + if (r==null) + return r; + if (type(r)==math_node) { + if (subtype(r)==before) { + mathlevel++; + } else { + mathlevel--; + } + } + } + break; + case glyph_node: + if (start_ok && + is_simple_character(r) && + (l = get_lc_code(character(r)))>0 && + (char_uchyph(r) || l == character(r))) + return r; + /* fall through */ + default: + start_ok = 0; + break; + } + r = vlink(r); + } + return r; +} + +int valid_wordend( halfword s) { + register halfword r = s; + register int clang = char_lang(s); + if (r==null) + return 1; + while ((r!=null) && + ((type(r)==glyph_node && is_simple_character(r) && clang == char_lang(r)) || + (type(r)==kern_node && subtype(r)==normal))) { + r = vlink(r); + } + if (r==null || + (type(r)==glyph_node && is_simple_character(r) && clang != char_lang(r)) || + type(r)==glue_node || + type(r)==whatsit_node || + type(r)==ins_node || + type(r)==adjust_node || + type(r)==penalty_node || + (type(r)==kern_node && subtype(r)==explicit)) + return 1; + return 0; +} + +void +hnj_hyphenation (halfword head, halfword tail) { + int lchar, i; + struct tex_language* lang; + lang_variables langdata; + char utf8word[(4*MAX_WORD_LEN)+1] = {0}; + int wordlen = 0; + char *hy = utf8word; + char *replacement = NULL; + halfword s, r = head, wordstart = null, save_tail = null, left = null, right = null; + + /* this first movement assures two things: + * a) that we won't waste lots of time on something that has been + * handled already (in that case, none of the glyphs match |simple_character|). + * b) that the first word can be hyphenated. if the movement was + * not explicit, then the indentation at the start of a paragraph + * list would make find_next_wordstart() look too far ahead. + */ + + while (r!=null && (type(r)!=glyph_node || !is_simple_character(r))) + r =vlink(r); + /* this will make |r| a glyph node with subtype_character */ + r = find_next_wordstart(r); + if (r==null) + return; + + assert (tail!=null); + save_tail = vlink(tail); + s = new_penalty(0); + couple_nodes(tail, s); + + while (r!=null) { /* could be while(1), but let's be paranoid */ + wordstart = r; + assert (is_simple_character(wordstart)); + int clang = char_lang(wordstart); + int lhmin = char_lhmin(wordstart); + int rhmin = char_rhmin(wordstart); + langdata.pre_hyphen_char = get_pre_hyphen_char(clang); + langdata.post_hyphen_char = get_post_hyphen_char(clang); + while (r!=null && + type(r)==glyph_node && + is_simple_character(r) && + clang == char_lang(r) && + (lchar = get_lc_code(character(r)))>0) { + wordlen++; + hy = utf8_idpb(hy,character(r)); + /* this should not be needed any more */ + /*if (vlink(r)!=null) alink(vlink(r))=r;*/ + r = vlink(r); + } + if (valid_wordend(r) && wordlen>=lhmin+rhmin && (lang=tex_languages[clang])!=NULL) { + *hy=0; + if (lang->exceptions!=0 && + (replacement = hyphenation_exception(lang->exceptions,utf8word))!=NULL) { +#ifdef VERBOSE + fprintf(stderr,"replacing %s (c=%d) by %s\n",utf8word,clang,replacement); +#endif + do_exception(wordstart,r,replacement); + free(replacement); + } else if (lang->patterns!=NULL) { + + left = wordstart; + for (i=lhmin;i>1;i--) { + left = vlink(left); + while (!is_simple_character(left)) + left = vlink(left); + } + right = r; + for (i=rhmin;i>0;i--) { + right = alink(right); + while (!is_simple_character(right)) + right = alink(right); + } + +#ifdef VERBOSE + fprintf(stderr,"hyphenate %s (c=%d,l=%d,r=%d) from %c to %c\n",utf8word, + clang,lhmin,rhmin, + character(left), character(right)); +#endif + (void)hnj_hyphen_hyphenate(lang->patterns,wordstart,r,wordlen,left,right, &langdata); + } + } + wordlen = 0; + hy = utf8word; + if (r==null) + break; + r = find_next_wordstart(r); + } + flush_node(vlink(tail)); + vlink(tail) = save_tail; +} + + +void +new_hyphenation (halfword head, halfword tail) { + register int callback_id = 0; + if (head==null || vlink(head)==null) + return; + fix_node_list (head); /* TODO: use couple_nodes() in append_tail()!*/ + callback_id = callback_defined(hyphenate_callback); + if (callback_id>0) { + lua_State *L = Luas[0]; + lua_rawgeti(L,LUA_REGISTRYINDEX,callback_callbacks_id); + lua_rawgeti(L,-1, callback_id); + if (!lua_isfunction(L,-1)) { + lua_pop(L,2); + return; + } + nodelist_to_lua(L,head); + nodelist_to_lua(L,tail); + if (lua_pcall(L,2,0,0) != 0) { + fprintf(stdout,"error: %s\n",lua_tostring(L,-1)); + lua_pop(L,2); + lua_error(L); + return; + } + lua_pop(L,1); + } else { + hnj_hyphenation(head,tail); + } +} + +/* dumping and undumping fonts */ + +#define dump_string(a) \ + if (a!=NULL) { \ + x = strlen(a)+1; \ + dump_int(x); dump_things(*a, x); \ + } else { \ + x = 0; dump_int(x); \ + } + + +void dump_one_language (int i) { + char *s = NULL; + unsigned x = 0; + struct tex_language *lang; + lang = tex_languages[i]; + dump_int(lang->id); + dump_int(lang->pre_hyphen_char); + dump_int(lang->post_hyphen_char); + if (lang->patterns!=NULL) { + s = (char *)hnj_serialize(lang->patterns); + } + dump_string(s); + if (s!=NULL) { + free(s); + s = NULL; + } + if (lang->exceptions!=0) + s = exception_strings(lang); + dump_string(s); + if (s!=NULL) { + free(s); + } + free (lang); +} + +void dump_language_data (void) { + int i; + dump_int(next_lang_id); + for (i=0;iid = x; + undump_int(x); lang->pre_hyphen_char = x; + undump_int(x); lang->post_hyphen_char = x; + /* patterns */ + undump_int (x); + if (x>0) { + s = xmalloc(x); + undump_things(*s,x); + load_patterns(lang,(unsigned char *)s); + free(s); + } + /* exceptions */ + undump_int (x); + if (x>0) { + s = xmalloc(x); + undump_things(*s,x); + load_hyphenation(lang,(unsigned char *)s); + free(s); + } +} + +void undump_language_data (void) { + int i; + unsigned x, numlangs; + undump_int(numlangs); + for (i=0;i + +extern int do_run_callback (int special, char *values, va_list vl); + +int callback_set[total_callbacks] = {0}; + +static const char *const callbacknames[] = { + "", /* empty on purpose */ + "find_write_file", + "find_output_file", + "find_image_file", + "find_format_file", + "find_read_file", "open_read_file", + "find_ocp_file", "read_ocp_file", + "find_vf_file", "read_vf_file", + "find_data_file", "read_data_file", + "find_font_file", "read_font_file", + "find_map_file", "read_map_file", + "find_enc_file", "read_enc_file", + "find_type1_file", "read_type1_file", + "find_truetype_file", "read_truetype_file", + "find_opentype_file", "read_opentype_file", + "find_sfd_file", "read_sfd_file", + "find_pk_file", "read_pk_file", + "show_error_hook", + "process_input_buffer", + "start_page_number", "stop_page_number", + "start_run", "stop_run", + "define_font", + "token_filter", + "pre_output_filter", + "buildpage_filter", + "hpack_filter", "vpack_filter", + "char_exists", + "hyphenate", + "ligaturing", + "kerning", + "pre_linebreak_filter", + "linebreak_filter", + "post_linebreak_filter", + NULL }; + +int callback_callbacks_id = 0; + +void +get_lua_boolean (char *table, char *name, boolean *target) { + int stacktop; + stacktop = lua_gettop(Luas[0]); + luaL_checkstack(Luas[0],2,"out of stack space"); + lua_getglobal(Luas[0],table); + if (lua_istable(Luas[0],-1)) { + lua_getfield(Luas[0],-1,name); + if (lua_isboolean(Luas[0],-1)) { + *target = (lua_toboolean(Luas[0],-1)); + } else if (lua_isnumber(Luas[0],-1)) { + *target = (lua_tonumber(Luas[0],-1)==0 ? 0 : 1); + } + } + lua_settop(Luas[0],stacktop); + return; +} + +void +get_saved_lua_boolean (int r, char *name, boolean *target) { + int stacktop; + stacktop = lua_gettop(Luas[0]); + luaL_checkstack(Luas[0],2,"out of stack space"); + lua_rawgeti(Luas[0],LUA_REGISTRYINDEX,r); + if (lua_istable(Luas[0],-1)) { + lua_getfield(Luas[0],-1,name); + if (lua_isboolean(Luas[0],-1)) { + *target = lua_toboolean(Luas[0],-1); + } else if (lua_isnumber(Luas[0],-1)) { + *target = (lua_tonumber(Luas[0],-1)==0 ? 0 : 1); + } + } + lua_settop(Luas[0],stacktop); + return; +} + +void +get_lua_number (char *table, char *name, integer *target) { + int stacktop; + stacktop = lua_gettop(Luas[0]); + luaL_checkstack(Luas[0],2,"out of stack space"); + lua_getglobal(Luas[0],table); + if (lua_istable(Luas[0],-1)) { + lua_getfield(Luas[0],-1,name); + if (lua_isnumber(Luas[0],-1)) { + *target = lua_tonumber(Luas[0],-1); + } + } + lua_settop(Luas[0],stacktop); + return; +} + +void +get_saved_lua_number (int r, char *name, integer *target) { + int stacktop; + stacktop = lua_gettop(Luas[0]); + luaL_checkstack(Luas[0],2,"out of stack space"); + lua_rawgeti(Luas[0],LUA_REGISTRYINDEX,r); + if (lua_istable(Luas[0],-1)) { + lua_getfield(Luas[0],-1,name); + if (lua_isnumber(Luas[0],-1)) { + *target = lua_tonumber(Luas[0],-1); + } + } + lua_settop(Luas[0],stacktop); + return; +} + + +void +get_lua_string (char *table, char *name, char **target) { + int stacktop; + stacktop = lua_gettop(Luas[0]); + luaL_checkstack(Luas[0],2,"out of stack space"); + lua_getglobal(Luas[0],table); + if (lua_istable(Luas[0],-1)) { + lua_getfield(Luas[0],-1,name); + if (lua_isstring(Luas[0],-1)) { + *target = (char *)lua_tostring(Luas[0],-1); + } + } + lua_settop(Luas[0],stacktop); + return; +} + +void +get_saved_lua_string (int r, char *name, char **target) { + int stacktop; + stacktop = lua_gettop(Luas[0]); + luaL_checkstack(Luas[0],2,"out of stack space"); + lua_rawgeti(Luas[0],LUA_REGISTRYINDEX,r); + if (lua_istable(Luas[0],-1)) { + lua_getfield(Luas[0],-1,name); + if (lua_isstring(Luas[0],-1)) { + *target = (char *)lua_tostring(Luas[0],-1); + } + } + lua_settop(Luas[0],stacktop); + return; +} + + +#define CALLBACK_BOOLEAN 'b' +#define CALLBACK_INTEGER 'd' +#define CALLBACK_LINE 'l' +#define CALLBACK_STRNUMBER 's' +#define CALLBACK_STRING 'S' +#define CALLBACK_CHARNUM 'c' + +int +run_saved_callback (int r, char *name, char *values, ...) { + va_list args; + int ret = 0; + lua_State *L = Luas[0]; + int stacktop = lua_gettop(L); + va_start(args,values); + luaL_checkstack(L,2,"out of stack space"); + lua_rawgeti(L,LUA_REGISTRYINDEX,r); + lua_pushstring(L,name); + lua_rawget(L,-2); + if (lua_isfunction(L,-1)) { + ret = do_run_callback(2,values,args); + } + va_end(args); + lua_settop(L,stacktop); + return ret; +} + + +int +run_and_save_callback (int i, char *values, ...) { + va_list args; + int ret = 0; + lua_State *L = Luas[0]; + int stacktop = lua_gettop(L); + va_start(args,values); + luaL_checkstack(L,2,"out of stack space"); + lua_rawgeti(L,LUA_REGISTRYINDEX,callback_callbacks_id); + lua_rawgeti(L,-1,i); + if (lua_isfunction(L,-1)) { + ret = do_run_callback(1,values,args); + } + va_end(args); + if (ret>0) { + ret = luaL_ref(L,LUA_REGISTRYINDEX); + } + lua_settop(L,stacktop); + return ret; +} + + +int +run_callback (int i, char *values, ...) { + va_list args; + int ret = 0; + lua_State *L = Luas[0]; + int stacktop = lua_gettop(L); + va_start(args,values); + luaL_checkstack(L,2,"out of stack space"); + lua_rawgeti(L,LUA_REGISTRYINDEX,callback_callbacks_id); + lua_rawgeti(L,-1, i); + if (lua_isfunction(L,-1)) { + ret = do_run_callback(0,values,args); + } + va_end(args); + lua_settop(L,stacktop); + return ret; +} + +int +do_run_callback (int special, char *values, va_list vl) { + int ret, len; + int narg,nres; + char *s; + char cs; + int *bufloc; + char *ss = NULL; + int retval = 0; + lua_State *L = Luas[0]; + if (special==2) { /* copy the enclosing table */ + luaL_checkstack(L,1,"out of stack space"); + lua_pushvalue(L,-2); + } + for (narg = 0; *values; narg++) { + luaL_checkstack(L,1,"out of stack space"); + switch (*values++) { + case CALLBACK_CHARNUM: /* an ascii char! */ + cs = (char)va_arg(vl, int); + lua_pushlstring(L,&cs, 1); + break; + case CALLBACK_STRING: /* C string */ + s = va_arg(vl, char *); + lua_pushstring(L, s); + break; + case CALLBACK_INTEGER: /* int */ + lua_pushnumber(L, va_arg(vl, int)); + break; + case CALLBACK_STRNUMBER: /* TeX string */ + s = makeclstring(va_arg(vl, int),&len); + lua_pushlstring(L, s,len); + break; + case CALLBACK_BOOLEAN: /* boolean */ + lua_pushboolean(L, va_arg(vl, int)); + break; + case CALLBACK_LINE: /* a buffer section, with implied start */ + lua_pushlstring(L, (char *)(buffer+first), va_arg(vl, int)); + break; + case '-': + narg--; + break; + case '>': + goto ENDARGS; + default : + ; + } + } + ENDARGS: + nres = strlen(values); + if (special==1) { + nres++; + } + if (special==2) { + narg++; + } + if(lua_pcall(L,narg,nres,0) != 0) { + /* Can't be more precise here, could be called before + * TeX initialization is complete + */ + fprintf(stderr,"This went wrong: %s\n",lua_tostring(L,-1)); + error(); + return 0; + }; + if (nres==0) { + return 1; + } + nres = -nres; + while (*values) { + switch (*values++) { + case CALLBACK_BOOLEAN: + if (!lua_isboolean(L,nres)) { + fprintf(stderr,"Expected a boolean, not: %s\n", lua_typename(L,lua_type(L,nres))); + goto EXIT; + } + int b = lua_toboolean(L,nres); + *va_arg(vl, boolean *) = (boolean)b; + break; + case CALLBACK_INTEGER: + if (!lua_isnumber(L,nres)) { + fprintf(stderr,"Expected a number, not: %s\n", lua_typename(L,lua_type(L,nres))); + goto EXIT; + } + b = lua_tonumber(L,nres); + *va_arg(vl, int *) = b; + break; + case CALLBACK_LINE: /* TeX line */ + if (!lua_isstring(L,nres)) { + if (!lua_isnil(L,nres)) + fprintf(stderr,"Expected a string for (l), not: %s\n", + lua_typename(L,lua_type(L,nres))); + goto EXIT; + } + s = (char *)lua_tolstring(L,nres, (size_t *)&len); + if (s!=NULL) { /* |len| can be zero */ + bufloc = va_arg(vl, int *); + ret = *bufloc; + check_buffer_overflow (ret+len); + while (len--) { + buffer[(*bufloc)++] = *s++; + } + while ((*bufloc)-1>ret && buffer[(*bufloc)-1] == ' ') + (*bufloc)--; + } else { + bufloc = 0; + } + break; + case CALLBACK_STRNUMBER: /* TeX string */ + if (!lua_isstring(L,nres)) { + if (!lua_isnil(L,nres)) { + fprintf(stderr,"Expected a string for (s), not: %s\n", + lua_typename(L,lua_type(L,nres))); + goto EXIT; + } + } + s = (char *)lua_tolstring(L,nres,(size_t *)&len); + if (s==NULL) /* |len| can be zero */ + *va_arg(vl, int *) = 0; + else { + *va_arg(vl, int *) = maketexlstring(s,len); + } + break; + case CALLBACK_STRING: /* C string aka buffer */ + if (!lua_isstring(L,nres)) { + if (!lua_isnil(L,nres)) { + fprintf(stderr,"Expected a string for (S), not: %s\n", + lua_typename(L,lua_type(L,nres))); + goto EXIT; + } + } + s = (char *)lua_tolstring(L,nres,(size_t *)&len); + + if (s==NULL) /* |len| can be zero */ + *va_arg(vl, int *) = 0; + else { + ss = xmalloc(len+1); + (void)memcpy(ss,s,(len+1)); + *va_arg(vl, char **) = ss; + } + break; + default: + fprintf(stdout,"invalid return value type"); + goto EXIT; + } + nres++; + } + retval = 1; + EXIT: + return retval; +} + +void +destroy_saved_callback (int i) { + luaL_unref(Luas[0],LUA_REGISTRYINDEX,i); +} + +static int callback_register (lua_State *L) { + int cb; + char *s; + if (!lua_isstring(L,1) || + ((!lua_isfunction(L,2)) && !lua_isnil(L,2))) { + lua_pushnil(L); + lua_pushstring(L,"Invalid arguments to callback.register."); + return 2; + } + s = (char *)lua_tostring(L,1); + for(cb=0;cb +#include "nodes.h" + +/* this function is in vfovf.c for the moment */ +extern int make_vf_table(lua_State *L, char *name, scaled s); + +static int +font_read_tfm (lua_State *L) { + internalfontnumber f; + scaled s; + int k; + char *cnom; + if(lua_isstring(L, 1)) { + cnom = (char *)lua_tostring(L, 1); + if(lua_isnumber(L, 2)) { + s = (integer)lua_tonumber(L,2); + if (strlen(cnom)) { + f = new_font(); + if (read_tfm_info(f, cnom, "", s)) { + k = font_to_lua(L,f); + delete_font(f); + return k; + } else { + delete_font(f); + lua_pushstring(L, "font loading failed"); + lua_error(L); + } + } else { + lua_pushstring(L, "expected tfm name as first argument"); + lua_error(L); + } + } else { + lua_pushstring(L, "expected an integer size as second argument"); + lua_error(L); + } + } else { + lua_pushstring(L, "expected tfm name as first argument"); + lua_error(L); + } + return 2; /* not reached */ +} + + +static int +font_read_vf (lua_State *L) { + scaled s; + char *cnom; + if(lua_isstring(L, 1)) { + cnom = (char *)lua_tostring(L, 1); + if (strlen(cnom)) { + if(lua_isnumber(L, 2)) { + s = lua_tonumber(L,2); + return make_vf_table(L,cnom,s); + } else { + lua_pushstring(L, "expected an integer size as second argument"); + lua_error(L); + return 2; + } + } + } + lua_pushstring(L, "expected vf name as first argument"); + lua_error(L); + return 2; /* not reached */ +} + +static int +tex_current_font (lua_State *L) { + int i; + i = (int)luaL_optinteger(L,1,0); + if (i>0) { + if (is_valid_font(i)) { + zset_cur_font(i); + return 0; + } else { + lua_pushstring(L, "expected a valid font id"); + lua_error(L); + return 2; /* not reached */ + } + } else { + lua_pushnumber(L,get_cur_font()); + return 1; + } +} + +static int +tex_max_font (lua_State *L) { + lua_pushnumber(L,max_font_id()); + return 1; +} + + +static int +tex_each_font_next (lua_State *L) { + int i,m; /* id */ + m = lua_tonumber(L,1); + i = lua_tonumber(L,2); + i++; + while(i<=m && !is_valid_font(i)) + i++; + if (i>m) { + lua_pushnil(L); + return 1; + } else { + lua_pushnumber(L, i); + font_to_lua (L, i); + return 2; + } +} + +static int +tex_each_font (lua_State *L) { + lua_pushcclosure(L, tex_each_font_next, 0); + lua_pushnumber(L, max_font_id()); + lua_pushnumber(L, 0); + return 3; +} + +static int +frozenfont (lua_State *L) { + int i; + i = (int)luaL_checkinteger(L,1); + if (i) { + if (is_valid_font(i)) { + if (font_touched(i) || font_used(i)) { + lua_pushboolean(L,1); + } else { + lua_pushboolean(L,0); + } + } else { + lua_pushnil(L); + } + return 1; + } else { + lua_pushstring(L, "expected an integer argument"); + lua_error(L); + } + return 0; /* not reached */ +} + + +static int +setfont (lua_State *L) { + int i; + i = (int)luaL_checkinteger(L,-2); + if (i) { + luaL_checktype(L,-1,LUA_TTABLE); + if (is_valid_font(i)) { + if (! (font_touched(i) || font_used(i))) { + font_from_lua (L,i) ; + } else { + lua_pushstring(L, "that font has been accessed already, changing it is forbidden"); + lua_error(L); + } + } else { + lua_pushstring(L, "that integer id is not a valid font"); + lua_error(L); + } + } + return 0; +} + + +static int +deffont (lua_State *L) { + int i; + luaL_checktype(L,-1,LUA_TTABLE); + + i = new_font(); + if(font_from_lua (L,i)) { + lua_pushnumber(L,i); + return 1; + } else { + lua_pop(L,1); /* pop the broken table */ + delete_font(i); + lua_pushstring(L, "font creation failed"); + lua_error(L); + } + return 0; /* not reached */ +} + +static int +getfont (lua_State *L) { + int i; + i = (int)luaL_checkinteger(L,-1); + if (i && is_valid_font(i) && font_to_lua (L, i)) + return 1; + lua_pushnil(L); + return 1; +} + + +static const struct luaL_reg fontlib [] = { + {"read_tfm", font_read_tfm}, + {"read_vf", font_read_vf}, + {"current", tex_current_font}, + {"max", tex_max_font}, + {"each", tex_each_font}, + {"getfont", getfont}, + {"setfont", setfont}, + {"define", deffont}, + {"frozen", frozenfont}, + {NULL, NULL} /* sentinel */ +}; + +int luaopen_font (lua_State *L) +{ + luaL_register(L, "font", fontlib); + make_table(L,"fonts","getfont","setfont"); + return 1; +} diff --git a/Build/source/texk/web2c/luatexdir/lua/limglib.c b/Build/source/texk/web2c/luatexdir/lua/limglib.c new file mode 100644 index 00000000000..fd75e49799a --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/limglib.c @@ -0,0 +1,714 @@ +/* $Id: limglib.c 1098 2008-03-09 10:28:19Z hhenkel $ */ + +#include +#include +#include +#include <../lua51/lua.h> +#include <../lua51/lauxlib.h> +#include +#include "../image/image.h" +#include "../luatex-api.h" + +/**********************************************************************/ + +#ifdef DEBUG +static void stackDump(lua_State * L, char *s) +{ + int i; + int top = lua_gettop(L); + printf("\n=== stackDump <%s>: ", s); + for (i = 1; i <= top; i++) { /* repeat for each level */ + int t = lua_type(L, i); + printf("%d: ", i); + switch (t) { + case LUA_TSTRING: /* strings */ + printf("`%s'", lua_tostring(L, i)); + break; + case LUA_TBOOLEAN: /* booleans */ + printf(lua_toboolean(L, i) ? "true" : "false"); + break; + case LUA_TNUMBER: /* numbers */ + printf("%g", lua_tonumber(L, i)); + break; + default: /* other values */ + printf("%s", lua_typename(L, t)); + break; + } + printf(" "); /* put a separator */ + } + printf("\n"); +} +#endif + +/**********************************************************************/ + +typedef enum { P__ZERO, P_ATTR, P_COLORDEPTH, P_COLORSPACE, P_DEPTH, P_FILENAME, + P_FILEPATH, P_HEIGHT, P_IMAGETYPE, P_INDEX, P_OBJNUM, P_PAGE, P_PAGEBOX, + P_TOTALPAGES, P_TRANSFORM, P_WIDTH, P_XRES, P_XSIZE, P_YRES, P_YSIZE, + P__SENTINEL +} parm_idx; + +typedef struct { + const char *name; /* parameter name */ + parm_idx idx; /* index within img_parms array */ +} parm_struct; + +parm_struct img_parms[] = { + {NULL, P__ZERO}, /* dummy; lua indices run from 1 */ + {"attr", P_ATTR}, + {"colordepth", P_COLORDEPTH}, + {"colorspace", P_COLORSPACE}, + {"depth", P_DEPTH}, + {"filename", P_FILENAME}, + {"filepath", P_FILEPATH}, + {"height", P_HEIGHT}, + {"imagetype", P_IMAGETYPE}, + {"index", P_INDEX}, + {"objnum", P_OBJNUM}, + {"page", P_PAGE}, + {"pagebox", P_PAGEBOX}, + {"pages", P_TOTALPAGES}, + {"transform", P_TRANSFORM}, + {"width", P_WIDTH}, + {"xres", P_XRES}, + {"xsize", P_XSIZE}, + {"yres", P_YRES}, + {"ysize", P_YSIZE}, + {NULL, P__SENTINEL} +}; + +#define imgtype_max 4 +const char *imgtype_s[] = { "none", "pdf", "png", "jpg", "jbig2", NULL }; + +#define pagebox_max 5 +const char *pdfboxspec_s[] = + { "none", "media", "crop", "bleed", "trim", "art", NULL }; + +/**********************************************************************/ + +static void image_to_lua(lua_State * L, image * a) +{ /* key user ... */ + int i, j; + image_dict *d = img_dict(a); + assert(d != NULL); + lua_pushvalue(L, -1); /* k k u ... */ + lua_gettable(L, LUA_ENVIRONINDEX); /* i? k u ... */ + if (!lua_isnumber(L, -1)) /* !i k u ... */ + luaL_error(L, "image_to_lua not a valid image key: %s", + lua_tostring(L, -2)); + i = lua_tointeger(L, -1); /* i k u ... */ + lua_pop(L, 2); /* u ... */ + switch (i) { + case P_WIDTH: + if (is_wd_running(a)) + lua_pushnil(L); + else + lua_pushinteger(L, img_width(a)); + break; + case P_HEIGHT: + if (is_ht_running(a)) + lua_pushnil(L); + else + lua_pushinteger(L, img_height(a)); + break; + case P_DEPTH: + if (is_dp_running(a)) + lua_pushnil(L); + else + lua_pushinteger(L, img_depth(a)); + break; + case P_TRANSFORM: + lua_pushinteger(L, img_transform(a)); + break; + /* now follow all image_dict entries */ + case P_FILENAME: + if (img_filename(d) == NULL || strlen(img_filename(d)) == 0) + lua_pushnil(L); + else + lua_pushstring(L, img_filename(d)); + break; + case P_FILEPATH: + if (img_filepath(d) == NULL || strlen(img_filepath(d)) == 0) + lua_pushnil(L); + else + lua_pushstring(L, img_filepath(d)); + break; + case P_ATTR: + if (img_attr(d) == NULL || strlen(img_attr(d)) == 0) + lua_pushnil(L); + else + lua_pushstring(L, img_attr(d)); + break; + case P_PAGE: + if (img_pagename(d) != NULL && strlen(img_pagename(d)) != 0) + lua_pushstring(L, img_pagename(d)); + else + lua_pushinteger(L, img_pagenum(d)); + break; + case P_TOTALPAGES: + lua_pushinteger(L, img_totalpages(d)); + break; + case P_XSIZE: + lua_pushinteger(L, img_xsize(d)); + break; + case P_YSIZE: + lua_pushinteger(L, img_ysize(d)); + break; + case P_XRES: + lua_pushinteger(L, img_xres(d)); + break; + case P_YRES: + lua_pushinteger(L, img_yres(d)); + break; + case P_COLORSPACE: + if (img_colorspace(d) == 0) + lua_pushnil(L); + else + lua_pushinteger(L, img_colorspace(d)); + break; + case P_COLORDEPTH: + if (img_colordepth(d) == 0) + lua_pushnil(L); + else + lua_pushinteger(L, img_colordepth(d)); + break; + case P_IMAGETYPE: + j = img_type(d); + if (j >= 0 && j <= imgtype_max) { + if (j == IMAGE_TYPE_NONE) + lua_pushnil(L); + else + lua_pushstring(L, imgtype_s[j]); + } else + assert(0); + break; + case P_PAGEBOX: + j = img_pagebox(d); + if (j >= 0 && j <= pagebox_max) { + if (j == PDF_BOX_SPEC_NONE) + lua_pushnil(L); + else + lua_pushstring(L, pdfboxspec_s[j]); + } else + assert(0); + break; + case P_OBJNUM: + if (img_objnum(d) == 0) + lua_pushnil(L); + else + lua_pushinteger(L, img_objnum(d)); + break; + case P_INDEX: + if (img_index(d) == 0) + lua_pushnil(L); + else + lua_pushinteger(L, img_index(d)); + break; + default: + assert(0); + } /* v u ... */ +} + +static void lua_to_image(lua_State * L, image * a) +{ /* value key table ... */ + int i; + image_dict *d = img_dict(a); + assert(d != NULL); + lua_pushvalue(L, -2); /* k v k t ... */ + lua_gettable(L, LUA_ENVIRONINDEX); /* i? v k t ... */ + if (!lua_isnumber(L, -1)) /* !i v k t ... */ + luaL_error(L, "lua_to_image not a valid image key: %s", + lua_tostring(L, -3)); + i = lua_tointeger(L, -1); /* i v k t ... */ + lua_pop(L, 1); /* v k t ... */ + switch (i) { + case P_WIDTH: + if (img_is_refered(a)) + luaL_error(L, "image.width is now read-only"); + if (lua_isnil(L, -1)) + set_wd_running(a); + else if (lua_type(L, -1) == LUA_TNUMBER) + img_width(a) = lua_tointeger(L, -1); + else if (lua_type(L, -1) == LUA_TSTRING) + img_width(a) = dimen_to_number(L, (char *) lua_tostring(L, -1)); + else + luaL_error(L, + "image.width needs integer or nil value or dimension string"); + img_unset_scaled(a); + break; + case P_HEIGHT: + if (img_is_refered(a)) + luaL_error(L, "image.height is now read-only"); + if (lua_isnil(L, -1)) + set_ht_running(a); + else if (lua_type(L, -1) == LUA_TNUMBER) + img_height(a) = lua_tointeger(L, -1); + else if (lua_type(L, -1) == LUA_TSTRING) + img_height(a) = dimen_to_number(L, (char *) lua_tostring(L, -1)); + else + luaL_error(L, + "image.height needs integer or nil value or dimension string"); + img_unset_scaled(a); + break; + case P_DEPTH: + if (img_is_refered(a)) + luaL_error(L, "image.depth is now read-only"); + if (lua_isnil(L, -1)) + set_dp_running(a); + else if (lua_type(L, -1) == LUA_TNUMBER) + img_depth(a) = lua_tointeger(L, -1); + else if (lua_type(L, -1) == LUA_TSTRING) + img_depth(a) = dimen_to_number(L, (char *) lua_tostring(L, -1)); + else + luaL_error(L, + "image.depth needs integer or nil value or dimension string"); + img_unset_scaled(a); + break; + case P_TRANSFORM: + if (img_is_refered(a)) + luaL_error(L, "image.transform is now read-only"); + if (lua_isnumber(L, -1)) + img_transform(a) = lua_tointeger(L, -1); + else + luaL_error(L, "image.transform needs integer value"); + img_unset_scaled(a); + break; + /* now follow all image_dict entries */ + case P_FILENAME: + if (img_state(d) >= DICT_FILESCANNED) + luaL_error(L, "image.filename is now read-only"); + if (lua_isstring(L, -1)) { + if (img_filename(d) != NULL) + xfree(img_filename(d)); + img_filename(d) = xstrdup(lua_tostring(L, -1)); + } else + luaL_error(L, "image.filename needs string value"); + break; + case P_ATTR: + if (img_state(d) >= DICT_FILESCANNED) + luaL_error(L, "image.attr is now read-only"); + if (lua_isstring(L, -1) || lua_isnil(L, -1)) { + if (img_attr(d) != NULL) + xfree(img_attr(d)); + if (lua_isstring(L, -1)) + img_attr(d) = xstrdup(lua_tostring(L, -1)); + } else + luaL_error(L, "image.attr needs string or nil value"); + break; + case P_PAGE: + if (img_state(d) >= DICT_FILESCANNED) + luaL_error(L, "image.page is now read-only"); + if (lua_type(L, -1) == LUA_TSTRING) { + if (img_pagename(d) != NULL) + xfree(img_pagename(d)); + img_pagename(d) = xstrdup(lua_tostring(L, -1)); + img_pagenum(d) = 0; + } else if (lua_type(L, -1) == LUA_TNUMBER) { + img_pagenum(d) = lua_tointeger(L, -1); + if (img_pagename(d) != NULL) + xfree(img_pagename(d)); + img_pagename(d) = NULL; + } else + luaL_error(L, "image.page needs integer or string value"); + break; + case P_COLORSPACE: + if (img_state(d) >= DICT_FILESCANNED) + luaL_error(L, "image.colorspace is now read-only"); + if (lua_isnil(L, -1)) + img_colorspace(d) = 0; + else if (lua_isnumber(L, -1)) + img_colorspace(d) = lua_tointeger(L, -1); + else + luaL_error(L, "image.colorspace needs integer or nil value"); + break; + case P_PAGEBOX: + if (img_state(d) >= DICT_FILESCANNED) + luaL_error(L, "image.pagebox is now read-only"); + if (lua_isnil(L, -1)) + img_pagebox(d) = PDF_BOX_SPEC_NONE; + else if (lua_isstring(L, -1)) + img_pagebox(d) = luaL_checkoption(L, -1, "none", pdfboxspec_s); + else + luaL_error(L, "image.pagebox needs string or nil value"); + break; + case P_FILEPATH: + case P_TOTALPAGES: + case P_XSIZE: + case P_YSIZE: + case P_XRES: + case P_YRES: + case P_IMAGETYPE: + case P_OBJNUM: + case P_INDEX: + case P_COLORDEPTH: + luaL_error(L, "image.%s is a read-only variable", img_parms[i].name); + break; + default: + assert(0); + } /* v k t ... */ +} + +/**********************************************************************/ + +void fix_image_size(lua_State * L, image * a) +{ + if (!img_is_scaled(a) || is_wd_running(a) || is_ht_running(a) + || is_dp_running(a)) { + if (img_is_refered(a)) + luaL_error(L, "image is read-only"); + scale_img(a); + } +} + +void copy_image(lua_State * L, lua_Number scale) +{ + image *a, **aa, *b, **bb; + if (lua_gettop(L) != 1) + luaL_error(L, "img.copy() needs exactly 1 argument"); + aa = (image **) luaL_checkudata(L, 1, TYPE_IMG); /* a */ + lua_pop(L, 1); /* - */ + a = *aa; + bb = (image **) lua_newuserdata(L, sizeof(image *)); /* b */ + luaL_getmetatable(L, TYPE_IMG); /* m b */ + lua_setmetatable(L, -2); /* b */ + b = *bb = new_image(); + if (!is_wd_running(a)) + img_width(b) = zround(img_width(a) * scale); + if (!is_ht_running(a)) + img_height(b) = zround(img_height(a) * scale); + if (!is_dp_running(a)) + img_depth(b) = zround(img_depth(a) * scale); + img_transform(b) = img_transform(a); + img_dict(b) = img_dict(a); + if (img_dictref(a) != LUA_NOREF) { + lua_rawgeti(L, LUA_GLOBALSINDEX, img_dictref(a)); /* ad b */ + img_dictref(b) = luaL_ref(L, LUA_GLOBALSINDEX); /* b */ + } else + assert(img_state(img_dict(a)) >= DICT_REFERED); +} + +/**********************************************************************/ + +static int l_new_image(lua_State * L) +{ + image *a, **aa; + if (lua_gettop(L) > 1) + luaL_error(L, "img.new() needs maximum 1 argument"); + if (lua_gettop(L) == 1 && !lua_istable(L, 1)) + luaL_error(L, "img.new() needs table as optional argument"); /* (t) */ + aa = (image **) lua_newuserdata(L, sizeof(image *)); /* i (t) */ + luaL_getmetatable(L, TYPE_IMG); /* m i (t) */ + lua_setmetatable(L, -2); /* i (t) */ + a = *aa = new_image(); + image_dict **add = (image_dict **) lua_newuserdata(L, sizeof(image_dict *)); /* ad i (t) */ + luaL_getmetatable(L, TYPE_IMG_DICT); /* m ad i (t) */ + lua_setmetatable(L, -2); /* ad i (t) */ + img_dict(a) = *add = new_image_dict(); + img_dictref(a) = luaL_ref(L, LUA_GLOBALSINDEX); /* i (t) */ + if (lua_gettop(L) != 1) { /* i t, else just i */ + lua_insert(L, -2); /* t i */ + lua_pushnil(L); /* n t i (1st key for iterator) */ + while (lua_next(L, -2) != 0) { /* v k t i */ + lua_to_image(L, a); /* v k t i */ + lua_pop(L, 1); /* k t i */ + } /* t i */ + lua_pop(L, 1); /* i */ + } /* i */ + return 1; /* i */ +} + +static int l_copy_image(lua_State * L) +{ + if (lua_gettop(L) != 1) + luaL_error(L, "img.copy() needs exactly 1 argument"); + if (lua_istable(L, 1)) + l_new_image(L); /* image --- if everything worked well */ + else + copy_image(L, 1.0); /* image */ + return 1; /* image */ +} + +static int l_scan_image(lua_State * L) +{ + image *a, **aa; + if (lua_gettop(L) != 1) + luaL_error(L, "img.scan() needs exactly 1 argument"); + if (lua_istable(L, 1)) + l_new_image(L); /* image --- if everything worked well */ + aa = (image **) luaL_checkudata(L, 1, TYPE_IMG); /* image */ + a = *aa; + image_dict *ad = img_dict(a); + if (img_state(ad) == DICT_NEW) { + read_img(ad, get_pdf_minor_version(), get_pdf_inclusion_errorlevel()); + img_unset_scaled(a); + } + fix_image_size(L, a); + return 1; /* image */ +} + +/* these should go into some header file... */ +#define obj_type_ximage 8 +#define obj_aux(a) obj_tab[a].int4 /* auxiliary pointer */ +#define obj_data_ptr obj_aux /* pointer to |pdf_mem| */ + +static halfword img_to_node(image * a, integer ref) +{ + image_dict *ad = img_dict(a); + assert(ad != NULL); + assert(img_objnum(ad) != 0); + halfword n = new_node(whatsit_node, pdf_refximage_node); + pdf_ximage_ref(n) = ref; + pdf_width(n) = img_width(a); + pdf_height(n) = img_height(a); + pdf_depth(n) = img_depth(a); + return n; +} + +typedef enum { WR_WRITE, WR_IMMEDIATEWRITE, WR_NODE } wrtype_e; +const char *wrtype_s[] = + { "img.write()", "img.immediatewrite()", "img.node()" }; + +extern void lua_nodelib_push_fast(lua_State * L, halfword n); + +static void write_image_or_node(lua_State * L, wrtype_e writetype) +{ + image *a, **aa; + halfword n; + if (lua_gettop(L) != 1) + luaL_error(L, "%s needs exactly 1 argument", wrtype_s[writetype]); + if (lua_istable(L, 1)) + l_new_image(L); /* image --- if everything worked well */ + aa = (image **) luaL_checkudata(L, 1, TYPE_IMG); /* image */ + a = *aa; + image_dict *ad = img_dict(a); + assert(ad != NULL); + if (img_state(ad) == DICT_NEW) { + read_img(ad, get_pdf_minor_version(), get_pdf_inclusion_errorlevel()); + img_unset_scaled(a); + } + fix_image_size(L, a); + check_pdfoutput(maketexstring(wrtype_s[writetype]), true); + flush_str(last_tex_string); + integer ref = img_to_array(a); + if (img_objnum(ad) == 0) { /* not strictly needed here, could be delayed until out_image() */ + pdf_ximage_count++; + pdf_create_obj(obj_type_ximage, pdf_ximage_count); + img_objnum(ad) = obj_ptr; + img_index(ad) = pdf_ximage_count; + obj_data_ptr(obj_ptr) = ref; + } + switch (writetype) { + case WR_WRITE: + n = img_to_node(a, ref); + new_tail_append(n); + break; /* image */ + case WR_IMMEDIATEWRITE: + check_pdfminorversion(); /* does initialization stuff */ + pdf_begin_dict(img_objnum(ad), 0); + write_img(ad); + break; /* image */ + case WR_NODE: /* image */ + lua_pop(L, 1); /* - */ + n = img_to_node(a, ref); + lua_nodelib_push_fast(L, n); + break; /* node */ + default: + assert(0); + } + if (img_state(ad) < DICT_REFERED) + img_state(ad) = DICT_REFERED; + img_set_refered(a); /* now image may not be freed by gc */ +} + +static int l_write_image(lua_State * L) +{ + write_image_or_node(L, WR_WRITE); + return 1; /* image */ +} + +static int l_immediatewrite_image(lua_State * L) +{ + write_image_or_node(L, WR_IMMEDIATEWRITE); + return 1; /* image */ +} + +static int l_image_node(lua_State * L) +{ + write_image_or_node(L, WR_NODE); + return 1; /* node */ +} + +static int l_image_keys(lua_State * L) +{ + parm_struct *p = img_parms + 1; + if (lua_gettop(L) != 0) + luaL_error(L, "img.keys() goes without argument"); + lua_newtable(L); /* t */ + for (; p->name != NULL; p++) { + lua_pushinteger(L, (int) p->idx); /* k t */ + lua_pushstring(L, p->name); /* v k t */ + lua_settable(L, -3); /* t */ + } + return 1; +} + +static int l_image_types(lua_State * L) +{ + int i; + char **p; + if (lua_gettop(L) != 0) + luaL_error(L, "img.types() goes without argument"); + lua_newtable(L); /* t */ + for (i = 1, p = (char **) (imgtype_s + 1); *p != NULL; p++, i++) { + lua_pushinteger(L, (int) i); /* k t */ + lua_pushstring(L, *p); /* v k t */ + lua_settable(L, -3); /* t */ + } + return 1; +} + +static int l_image_boxes(lua_State * L) +{ + int i; + char **p; + if (lua_gettop(L) != 0) + luaL_error(L, "img.boxes() goes without argument"); + lua_newtable(L); /* t */ + for (i = 1, p = (char **) (pdfboxspec_s + 1); *p != NULL; p++, i++) { + lua_pushinteger(L, (int) i); /* k t */ + lua_pushstring(L, *p); /* v k t */ + lua_settable(L, -3); /* t */ + } + return 1; +} + +static const struct luaL_Reg imglib[] = { + {"new", l_new_image}, + {"copy", l_copy_image}, + {"scan", l_scan_image}, + {"write", l_write_image}, + {"immediatewrite", l_immediatewrite_image}, + {"node", l_image_node}, + {"keys", l_image_keys}, + {"types", l_image_types}, + {"boxes", l_image_boxes}, + {NULL, NULL} /* sentinel */ +}; + +/**********************************************************************/ +/* Metamethods for image */ + +static int m_img_get(lua_State * L) +{ + image **aa = (image **) luaL_checkudata(L, 1, TYPE_IMG); /* k u */ + image_to_lua(L, *aa); /* v u */ + return 1; +} + +static int m_img_set(lua_State * L) +{ + image **aa = (image **) luaL_checkudata(L, 1, TYPE_IMG); /* value key user */ + lua_to_image(L, *aa); /* v k u */ + return 0; +} + +static int m_img_mul(lua_State * L) +{ + image **aa; + lua_Number scale; + if (lua_isnumber(L, 1)) { /* u? n */ + aa = (image **) luaL_checkudata(L, 2, TYPE_IMG); /* u n */ + lua_insert(L, -2); /* n a */ + } else if (lua_isnumber(L, 2)) { /* n u? */ + aa = (image **) luaL_checkudata(L, 1, TYPE_IMG); /* n a */ + } /* n a */ + scale = lua_tonumber(L, 2); /* n a */ + lua_pop(L, 1); /* a */ + copy_image(L, scale); /* b */ + return 1; +} + +static int m_img_print(lua_State * L) +{ + image **aa = (image **) luaL_checkudata(L, 1, TYPE_IMG); + image_dict *d = img_dict(*aa); + if (img_pagename(d) != NULL && strlen(img_pagename(d)) != 0) + lua_pushfstring(L, "", + img_filename(d), img_pagename(d)); + else + lua_pushfstring(L, "", img_filename(d), + img_pagenum(d)); + return 1; +} + +static int m_img_gc(lua_State * L) +{ + image *a, **aa; + aa = (image **) luaL_checkudata(L, 1, TYPE_IMG); + a = *aa; +#ifdef DEBUG + printf("\n===== IMG GC ===== a=%d ad=%d\n", a, img_dict(a)); +#endif + luaL_unref(L, LUA_GLOBALSINDEX, img_dictref(a)); + if (!img_is_refered(a)) + xfree(a); + return 0; +} + +static const struct luaL_Reg img_m[] = { + {"__index", m_img_get}, + {"__newindex", m_img_set}, + {"__mul", m_img_mul}, + {"__tostring", m_img_print}, + {"__gc", m_img_gc}, /* finalizer */ + {NULL, NULL} /* sentinel */ +}; + +/**********************************************************************/ +/* Metamethods for image_dict */ + +static int m_img_dict_gc(lua_State * L) +{ + image_dict *ad, **add; + add = (image_dict **) luaL_checkudata(L, 1, TYPE_IMG_DICT); + ad = *add; +#ifdef DEBUG + printf("\n===== IMG_DICT GC FREE ===== ad=%d\n", ad); +#endif + if (img_state(ad) < DICT_REFERED) + free_image_dict(ad); + return 0; +} + +static const struct luaL_Reg img_dict_m[] = { + {"__gc", m_img_dict_gc}, /* finalizer */ + {NULL, NULL} /* sentinel */ +}; + +/**********************************************************************/ + +void preset_environment(lua_State * L, parm_struct * p) +{ + int i; + lua_newtable(L); /* t */ + for (i = 1, ++p; p->name != NULL; i++, p++) { + assert(i == (int) p->idx); + lua_pushstring(L, p->name); /* k t */ + lua_pushinteger(L, (int) p->idx); /* v k t */ + lua_settable(L, -3); /* t */ + } + lua_replace(L, LUA_ENVIRONINDEX); /* - */ +} + +int luaopen_img(lua_State * L) +{ + preset_environment(L, img_parms); + luaL_newmetatable(L, TYPE_IMG); + luaL_register(L, NULL, img_m); + luaL_newmetatable(L, TYPE_IMG_DICT); + luaL_register(L, NULL, img_dict_m); + luaL_register(L, "img", imglib); + return 1; +} + +/**********************************************************************/ diff --git a/Build/source/texk/web2c/luatexdir/lua/lkpselib.c b/Build/source/texk/web2c/luatexdir/lua/lkpselib.c new file mode 100644 index 00000000000..5ec4dfed869 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/lkpselib.c @@ -0,0 +1,272 @@ +/* $Id: lkpselib.c 1061 2008-02-20 09:51:04Z taco $ */ + +#include "luatex-api.h" +#include +#include +#include +#include +#include + +static const int filetypes[] = { + kpse_gf_format, + kpse_pk_format, + kpse_any_glyph_format, + kpse_tfm_format, + kpse_afm_format, + kpse_base_format, + kpse_bib_format, + kpse_bst_format, + kpse_cnf_format, + kpse_db_format, + kpse_fmt_format, + kpse_fontmap_format, + kpse_mem_format, + kpse_mf_format, + kpse_mfpool_format, + kpse_mft_format, + kpse_mp_format, + kpse_mppool_format, + kpse_mpsupport_format, + kpse_ocp_format, + kpse_ofm_format, + kpse_opl_format, + kpse_otp_format, + kpse_ovf_format, + kpse_ovp_format, + kpse_pict_format, + kpse_tex_format, + kpse_texdoc_format, + kpse_texpool_format, + kpse_texsource_format, + kpse_tex_ps_header_format, + kpse_troff_font_format, + kpse_type1_format, + kpse_vf_format, + kpse_dvips_config_format, + kpse_ist_format, + kpse_truetype_format, + kpse_type42_format, + kpse_web2c_format, + kpse_program_text_format, + kpse_program_binary_format, + kpse_miscfonts_format, + kpse_web_format, + kpse_cweb_format, + kpse_enc_format, + kpse_cmap_format, + kpse_sfd_format, + kpse_opentype_format, + kpse_pdftex_config_format, + kpse_lig_format, + kpse_texmfscripts_format }; + +static const char *const filetypenames[] = { + "gf", + "pk", + "bitmap font", + "tfm", + "afm", + "base", + "bib", + "bst", + "cnf", + "ls-R", + "fmt", + "map", + "mem", + "mf", + "mfpool", + "mft", + "mp", + "mppool", + "MetaPost support", + "ocp", + "ofm", + "opl", + "otp", + "ovf", + "ovp", + "graphic/figure", + "tex", + "TeX system documentation", + "texpool", + "TeX system sources", + "PostScript header", + "Troff fonts", + "type1 fonts", + "vf", + "dvips config", + "ist", + "truetype fonts", + "type42 fonts", + "web2c files", + "other text files", + "other binary files", + "misc fonts", + "web", + "cweb", + "enc files", + "cmap files", + "subfont definition files", + "opentype fonts", + "pdftex config", + "lig files", + "texmfscripts", + NULL }; + +/* set to 1 by the |program_name| function */ + +int program_name_set = 0; + +#define TEST_PROGRAM_NAME_SET do { \ + if (! program_name_set) { \ + lua_pushstring(L, "Please call kpse.set_program_name() before using the library"); \ + return lua_error(L); \ + } \ + } while (0) + +static int find_file (lua_State *L) { + int i; + char *st; + int ftype = kpse_tex_format; + int mexist = 0; + TEST_PROGRAM_NAME_SET; + if (!lua_isstring(L,1)) { + lua_pushstring(L, "not a file name"); + lua_error(L); + } + st = (char *)lua_tostring(L,1); + i = lua_gettop(L); + while (i>1) { + if (lua_isboolean (L,i)) { + mexist = lua_toboolean (L,i); + } else if (lua_isnumber (L,i)) { + mexist = lua_tonumber (L,i) ; + } else if (lua_isstring(L,i)) { + int op = luaL_checkoption(L, i, NULL, filetypenames); + ftype = filetypes[op]; + } + i--; + } + if (ftype==kpse_pk_format || + ftype==kpse_gf_format || + ftype==kpse_any_glyph_format) { + /* ret.format, ret.name, ret.dpi */ + kpse_glyph_file_type ret; + lua_pushstring(L, kpse_find_glyph (st,mexist, ftype, &ret)); + } else { + if (mexist>0) + mexist = 1; + if (mexist<0) + mexist = 0; + lua_pushstring(L, kpse_find_file (st,ftype,mexist)); + } + return 1; +} + +static int show_path (lua_State *L) { + int op = luaL_checkoption(L, -1, "tex", filetypenames); + int user_format = filetypes[op]; + TEST_PROGRAM_NAME_SET; + if (!kpse_format_info[user_format].type) /* needed if arg was numeric */ + kpse_init_format (user_format); + lua_pushstring (L, kpse_format_info[user_format].path); + return 1; +} + + +static int expand_path (lua_State *L) { + const char *st = luaL_checkstring(L,1); + TEST_PROGRAM_NAME_SET; + lua_pushstring(L, kpse_path_expand(st)); + return 1; +} + +static int expand_braces (lua_State *L) { + const char *st = luaL_checkstring(L,1); + TEST_PROGRAM_NAME_SET; + lua_pushstring(L, kpse_brace_expand(st)); + return 1; +} + +static int expand_var (lua_State *L) { + const char *st = luaL_checkstring(L,1); + TEST_PROGRAM_NAME_SET; + lua_pushstring(L, kpse_var_expand(st)); + return 1; +} + +static int var_value (lua_State *L) { + const char *st = luaL_checkstring(L,1); + TEST_PROGRAM_NAME_SET; + lua_pushstring(L, kpse_var_value(st)); + return 1; +} + +/* Engine support is a bit of a problem, because we do not want + * to interfere with the normal format discovery of |luatex|. + * Current approach: run |os.setenv()| if you have to. + */ + +extern int luainit; + +static int set_program_name (lua_State *L) { + const char *exe_name = luaL_checkstring(L,1); + const char *prog_name = luaL_optstring(L,2,exe_name); + if (! program_name_set) { + kpse_set_program_name(exe_name, prog_name); + program_name_set = 1; + } else { + kpse_reset_program_name(prog_name); + } + /* fix up the texconfig entry */ + lua_checkstack(L,3); + lua_getglobal(L,"texconfig"); + if (lua_istable(L,-1)) { + lua_pushstring(L,"kpse_init"); + lua_pushboolean(L,0); + lua_rawset(L,-3); + } + lua_pop(L,1); + return 0; +} + +static int init_prog (lua_State *L) { + const char *prefix = luaL_checkstring(L,1); + unsigned dpi = luaL_checkinteger(L,2); + const char *mode = luaL_checkstring(L,3); + const char *fallback = luaL_optstring(L,4,NULL); + TEST_PROGRAM_NAME_SET; + kpse_init_prog(prefix,dpi,mode,fallback); + return 0; +} + +static int readable_file (lua_State *L) { + const char *name = luaL_checkstring(L,1); + TEST_PROGRAM_NAME_SET; + lua_pushstring(L,(char *)kpse_readable_file (name)); + return 1; +} + + +static const struct luaL_reg kpselib [] = { + {"set_program_name", set_program_name}, + {"init_prog", init_prog}, + {"readable_file", readable_file}, + {"find_file", find_file}, + {"expand_path", expand_path}, + {"expand_var", expand_var}, + {"expand_braces",expand_braces}, + {"var_value",var_value}, + {"show_path",show_path}, + {NULL, NULL} /* sentinel */ +}; + + +int +luaopen_kpse (lua_State *L) +{ + luaL_register(L,"kpse",kpselib); + return 1; +} + diff --git a/Build/source/texk/web2c/luatexdir/lua/llanglib.c b/Build/source/texk/web2c/luatexdir/lua/llanglib.c new file mode 100644 index 00000000000..63e8c45dec8 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/llanglib.c @@ -0,0 +1,219 @@ +/* +Copyright (c) 2007 Taco Hoekwater + +This file is part of luatex. + +luatex 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. + +luatex 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 luatex; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +This is llanglib.c +*/ + +#include "luatex-api.h" +#include + +#include "nodes.h" + +#define LANG_METATABLE "luatex.lang" + +#define check_islang(L,b) (struct tex_language **)luaL_checkudata(L,b,LANG_METATABLE) + +static int +lang_new (lua_State *L) { + struct tex_language **lang; + if (lua_gettop(L)==0) { + lang = lua_newuserdata(L, sizeof(struct tex_language *)); + *lang = new_language(); + if (!*lang) { + lua_pushstring(L,"lang.new(): no room for a new language"); + return lua_error(L); + } + } else { + lang = lua_newuserdata(L, sizeof(struct tex_language *)); + *lang = get_language(lua_tonumber(L,1)); + } + luaL_getmetatable(L,LANG_METATABLE); + lua_setmetatable(L,-2); + return 1; +} + +static int +lang_id (lua_State *L) { + struct tex_language **lang_ptr; + lang_ptr = check_islang(L,1); + lua_pushnumber(L,(*lang_ptr)->id); + return 1; +} + +static int +lang_patterns (lua_State *L) { + struct tex_language **lang_ptr; + lang_ptr = check_islang(L,1); + if (lua_gettop(L)!=1) { + if (!lua_isstring(L,2)) { + lua_pushstring(L,"lang.patterns(): argument should be a string"); + return lua_error(L); + } + load_patterns(*lang_ptr, (unsigned char *)lua_tostring(L,2)); + return 0; + } else { + if ((*lang_ptr)->patterns!=NULL) { + lua_pushstring(L,(char *)hnj_serialize((*lang_ptr)->patterns)); + } else { + lua_pushnil(L); + } + return 1; + } +} + +static int +lang_clear_patterns (lua_State *L) { + struct tex_language **lang_ptr; + lang_ptr = check_islang(L,1); + clear_patterns(*lang_ptr); + return 0; +} + + +static int +lang_hyphenation (lua_State *L) { + struct tex_language **lang_ptr; + lang_ptr = check_islang(L,1); + if (lua_gettop(L)!=1) { + if(!lua_isstring(L,2)) { + lua_pushstring(L,"lang.hyphenation(): argument should be a string"); + return lua_error(L); + } + load_hyphenation(*lang_ptr,(unsigned char *)lua_tostring(L,2)); + return 0; + } else { + if ((*lang_ptr)->exceptions!=0) { + lua_pushstring(L,exception_strings(*lang_ptr)); + } else { + lua_pushnil(L); + } + return 1; + } +} + +static int +lang_pre_hyphen_char (lua_State *L) { + struct tex_language **lang_ptr; + lang_ptr = check_islang(L,1); + if (lua_gettop(L)!=1) { + if(!lua_isnumber(L,2)) { + lua_pushstring(L,"lang.prehyphenchar(): argument should be a character number"); + return lua_error(L); + } + (*lang_ptr)->pre_hyphen_char = lua_tonumber(L,2); + return 0; + } else { + lua_pushnumber(L,(*lang_ptr)->pre_hyphen_char); + return 1; + } +} + +static int +lang_post_hyphen_char (lua_State *L) { + struct tex_language **lang_ptr; + lang_ptr = check_islang(L,1); + if (lua_gettop(L)!=1) { + if(!lua_isnumber(L,2)) { + lua_pushstring(L,"lang.posthyphenchar(): argument should be a character number"); + return lua_error(L); + } + (*lang_ptr)->post_hyphen_char = lua_tonumber(L,2); + return 0; + } else { + lua_pushnumber(L,(*lang_ptr)->post_hyphen_char); + return 1; + } +} + +static int +lang_clear_hyphenation (lua_State *L) { + struct tex_language **lang_ptr; + lang_ptr = check_islang(L,1); + clear_hyphenation(*lang_ptr); + return 0; +} + + +static int +do_lang_clean (lua_State *L) { + char *cleaned; + if (!lua_isstring(L,1)) { + lua_pushstring(L,"lang.clean(): argument should be a string"); + return lua_error(L); + } + (void)clean_hyphenation((char *)lua_tostring(L,1),&cleaned); + lua_pushstring(L,cleaned); + return 1; +} + +static int +do_lang_hyphenate (lua_State *L) { + halfword *h,*t; + h = check_isnode(L,1); + if (lua_isuserdata(L,2)) { + t = check_isnode(L,2); + lua_pop(L,1); + } else { + t = h; + while (vlink(*t)!=null) + *t = vlink(*t); + } + hnj_hyphenation(*h,*t); + lua_pushboolean(L,1); + return 1; +} + + +static const struct luaL_reg langlib_d [] = { + {"clear_patterns", lang_clear_patterns}, + {"clear_hyphenation", lang_clear_hyphenation}, + {"patterns", lang_patterns}, + {"hyphenation", lang_hyphenation}, + {"prehyphenchar", lang_pre_hyphen_char}, + {"posthyphenchar", lang_post_hyphen_char}, + {"id", lang_id}, + {NULL, NULL} /* sentinel */ +}; + + +static const struct luaL_reg langlib[] = { + {"clear_patterns", lang_clear_patterns}, + {"clear_hyphenation", lang_clear_hyphenation}, + {"patterns", lang_patterns}, + {"hyphenation", lang_hyphenation}, + {"prehyphenchar", lang_pre_hyphen_char}, + {"posthyphenchar", lang_post_hyphen_char}, + {"id", lang_id}, + {"clean", do_lang_clean}, + {"hyphenate", do_lang_hyphenate}, + {"new", lang_new}, + {NULL, NULL} /* sentinel */ +}; + + +int +luaopen_lang (lua_State *L) { + luaL_newmetatable(L,LANG_METATABLE); + lua_pushvalue(L, -1); /* push metatable */ + lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ + luaL_register(L, NULL, langlib_d); /* dict methods */ + luaL_register(L, "lang", langlib); + return 1; +} + diff --git a/Build/source/texk/web2c/luatexdir/lua/llualib.c b/Build/source/texk/web2c/luatexdir/lua/llualib.c new file mode 100644 index 00000000000..0d13500a9b7 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/llualib.c @@ -0,0 +1,229 @@ + +/* $Id: llualib.c 1013 2008-02-14 00:09:02Z oneiros $ */ + +#include "luatex-api.h" +#include + +#define LOAD_BUF_SIZE 256 +#define UINT_MAX32 0xFFFFFFFF + +typedef struct { + unsigned char* buf; + int size; + int done; + int alloc; +} bytecode; + +static bytecode *lua_bytecode_registers = NULL; + +int luabytecode_max = -1; +unsigned int luabytecode_bytes = 0; + +void dump_luac_registers (void) { + int k,n; + bytecode b; + dump_int(luabytecode_max); + if (lua_bytecode_registers != NULL) { + n = 0; + for (k=0;k<=luabytecode_max;k++) { + if (lua_bytecode_registers[k].size != 0) + n++; + } + dump_int(n); + for (k=0;k<=luabytecode_max;k++) { + b = lua_bytecode_registers[k]; + if (b.size != 0) { + dump_int(k); + dump_int(b.size); + do_zdump ((char *)b.buf,1,(b.size), DUMP_FILE); + } + } + } +} + +void undump_luac_registers (void) { + int k,n; + unsigned int i; + bytecode b; + undump_int(luabytecode_max); + if (luabytecode_max>=0) { + i = (luabytecode_max+1); + if ((int)(UINT_MAX32/sizeof(bytecode)+1)<=i) { + lua_fatal_error("Corrupt format file"); + } + lua_bytecode_registers = xmalloc(i*sizeof(bytecode)); + luabytecode_bytes = i*sizeof(bytecode); + for (i=0;i<=luabytecode_max;i++) { + lua_bytecode_registers[i].done = 0; + lua_bytecode_registers[i].size = 0; + lua_bytecode_registers[i].buf = NULL; + } + undump_int(n); + for (i=0;isize + size > buf->alloc) { + buf->buf = xrealloc(buf->buf,buf->alloc+size+LOAD_BUF_SIZE); + buf->alloc = buf->alloc+size+LOAD_BUF_SIZE; + } + memcpy(buf->buf+buf->size, b, size); + buf->size += size; + luabytecode_bytes += size; + return 0; +} + +const char* reader(lua_State* L, void* ud, size_t* size) { + bytecode* buf = (bytecode*)ud; + if (buf->done == buf->size) { + *size = 0; + buf->done = 0; + return NULL; + } + *size = buf->size; + buf->done = buf->size; + return (const char*)buf->buf; +} + +int get_bytecode (lua_State *L) { + int k; + k = (int)luaL_checkinteger(L,-1); + if (k<0) { + lua_pushnil(L); + } else if (!bytecode_register_shadow_get(L,k)) { + if (k<=luabytecode_max && lua_bytecode_registers[k].buf != NULL) { + if(lua_load(L,reader,(void *)(lua_bytecode_registers+k),"bytecode")) { + lua_error(L); + lua_pushnil(L); + } else { + lua_pushvalue(L,-1); + bytecode_register_shadow_set(L,k); + } + } else { + lua_pushnil(L); + } + } + return 1; +} + +int set_bytecode (lua_State *L) { + int k, ltype; + unsigned int i; + k = (int)luaL_checkinteger(L,-2); + i = k+1; + if ((int)(UINT_MAX32/sizeof(bytecode)+1)luabytecode_max) { + i = sizeof(bytecode)*(k+1); + lua_bytecode_registers = xrealloc(lua_bytecode_registers,i); + if (luabytecode_max==-1) { + luabytecode_bytes += sizeof(bytecode)*(k+1); + } else { + luabytecode_bytes += sizeof(bytecode)*(k+1-luabytecode_max); + } + for (i=(luabytecode_max+1);i<=k;i++) { + lua_bytecode_registers[i].buf=NULL; + lua_bytecode_registers[i].size=0; + lua_bytecode_registers[i].done=0; + } + luabytecode_max = k; + } + if (lua_bytecode_registers[k].buf != NULL) { + xfree(lua_bytecode_registers[k].buf); + luabytecode_bytes -= lua_bytecode_registers[k].size; + lua_bytecode_registers[k].buf = NULL; + lua_bytecode_registers[k].size=0; + lua_bytecode_registers[k].done=0; + lua_pushnil(L); + bytecode_register_shadow_set(L,k); + } + if (ltype == LUA_TFUNCTION) { + lua_bytecode_registers[k].buf=xmalloc(LOAD_BUF_SIZE); + lua_bytecode_registers[k].alloc = LOAD_BUF_SIZE; + memset(lua_bytecode_registers[k].buf, 0, LOAD_BUF_SIZE); + lua_dump(L,writer,(void *)(lua_bytecode_registers+k)); + } + lua_pop(L,1); + return 0; +} + +static const struct luaL_reg lualib [] = { + {"getbytecode", get_bytecode}, + {"setbytecode", set_bytecode}, + {NULL, NULL} /* sentinel */ +}; + +int luaopen_lua (lua_State *L, int n, char *fname) +{ + luaL_register(L, "lua", lualib); + make_table(L,"bytecode","getbytecode","setbytecode"); + lua_newtable(L); + lua_setfield(L, LUA_REGISTRYINDEX, "bytecode_shadow"); + lua_pushinteger(L, n); + lua_setfield(L, -2, "id"); + lua_pushstring(L, "0.1"); + lua_setfield(L, -2, "version"); + if (fname == NULL) { + lua_pushnil(L); + } else { + lua_pushstring(L, fname); + } + lua_setfield(L, -2, "startupfile"); + return 1; +} + diff --git a/Build/source/texk/web2c/luatexdir/lua/lmplib.c b/Build/source/texk/web2c/luatexdir/lua/lmplib.c new file mode 100644 index 00000000000..a194f9a55d8 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/lmplib.c @@ -0,0 +1,1251 @@ +/* $Id$ */ + +#include +#include +#include + +#ifndef pdfTeX +#include +#include +#include +#else +#include <../lua51/lua.h> +#include <../lua51/lauxlib.h> +#include <../lua51/lualib.h> +#endif + +#include "mplib.h" +#include "mpmp.h" +#include "mppsout.h" /* for mp_edge_object */ + +#define MPLIB_METATABLE "MPlib" +#define MPLIB_FIG_METATABLE "MPlib.fig" +#define MPLIB_GR_METATABLE "MPlib.gr" + +#define mplib_init_S(a) do { \ + lua_pushliteral(L,#a); \ + mplib_##a##_ptr = (char *)lua_tostring(L,-1); \ + mplib_##a##_index = luaL_ref (L,LUA_REGISTRYINDEX); \ + } while (0) + +#define mplib_push_S(a) do { \ + lua_rawgeti(L,LUA_REGISTRYINDEX,mplib_##a##_index); \ + } while (0) + +#define mplib_is_S(a,i) (mplib_##a##_ptr==(char *)lua_tostring(L,i)) + +#define mplib_make_S(a) \ + static int mplib_##a##_index = 0; \ + static char *mplib_##a##_ptr = NULL + +static int mplib_type_Ses[mp_special_code+1] = {0}; /* [0] is not used */ + +mplib_make_S(fill); +mplib_make_S(outline); +mplib_make_S(text); +mplib_make_S(special); +mplib_make_S(start_bounds); +mplib_make_S(stop_bounds); +mplib_make_S(start_clip); +mplib_make_S(stop_clip); + +mplib_make_S(left_type); +mplib_make_S(right_type); +mplib_make_S(x_coord); +mplib_make_S(y_coord); +mplib_make_S(left_x); +mplib_make_S(left_y); +mplib_make_S(right_x); +mplib_make_S(right_y); + +mplib_make_S(color); +mplib_make_S(dash); +mplib_make_S(depth); +mplib_make_S(dsize); +mplib_make_S(font); +mplib_make_S(height); +mplib_make_S(htap); +mplib_make_S(linecap); +mplib_make_S(linejoin); +mplib_make_S(miterlimit); +mplib_make_S(path); +mplib_make_S(pen); +mplib_make_S(postscript); +mplib_make_S(prescript); +mplib_make_S(transform); +mplib_make_S(type); +mplib_make_S(width); + +void mplib_init_Ses(lua_State *L) { + mplib_init_S(fill); + mplib_init_S(outline); + mplib_init_S(text); + mplib_init_S(start_bounds); + mplib_init_S(stop_bounds); + mplib_init_S(start_clip); + mplib_init_S(stop_clip); + mplib_init_S(special); + + mplib_type_Ses[mp_fill_code] = mplib_fill_index; + mplib_type_Ses[mp_stroked_code] = mplib_outline_index; + mplib_type_Ses[mp_text_code] = mplib_text_index; + mplib_type_Ses[mp_start_bounds_code] = mplib_start_bounds_index; + mplib_type_Ses[mp_stop_bounds_code] = mplib_stop_bounds_index; + mplib_type_Ses[mp_start_clip_code] = mplib_start_clip_index; + mplib_type_Ses[mp_stop_clip_code] = mplib_stop_clip_index; + mplib_type_Ses[mp_special_code] = mplib_special_index; + + mplib_init_S(left_type); + mplib_init_S(right_type); + mplib_init_S(x_coord); + mplib_init_S(y_coord); + mplib_init_S(left_x); + mplib_init_S(left_y); + mplib_init_S(right_x); + mplib_init_S(right_y); + + mplib_init_S(color); + mplib_init_S(dash); + mplib_init_S(depth); + mplib_init_S(dsize); + mplib_init_S(font); + mplib_init_S(height); + mplib_init_S(htap); + mplib_init_S(linecap); + mplib_init_S(linejoin); + mplib_init_S(miterlimit); + mplib_init_S(path); + mplib_init_S(pen); + mplib_init_S(postscript); + mplib_init_S(prescript); + mplib_init_S(transform); + mplib_init_S(type); + mplib_init_S(width); +} + + + + +#define xfree(A) if ((A)!=NULL) { free((A)); A = NULL; } + +#define is_mp(L,b) (MP *)luaL_checkudata(L,b,MPLIB_METATABLE) +#define is_fig(L,b) (struct mp_edge_object **)luaL_checkudata(L,b,MPLIB_FIG_METATABLE) +#define is_gr_object(L,b) (struct mp_graphic_object **)luaL_checkudata(L,b,MPLIB_GR_METATABLE) + +/* Enumeration string arrays */ + +static const char *interaction_options[] = + { "unknown","batch","nonstop","scroll","errorstop", NULL}; + +static const char *mplib_filetype_names[] = + {"term", "error", "mp", "log", "ps", "mem", "tfm", "map", "pfb", "enc", NULL}; + +/* only "endpoint" and "explicit" actually happen in paths, + as well as "open" in elliptical pens */ + +static const char *knot_type_enum[] = + { "endpoint", "explicit", "given", "curl", "open", "end_cycle" }; + +/* object fields */ + +static const char *fill_fields[] = + { "type", "path", "htap", "pen", "color", "linejoin", "miterlimit", + "prescript", "postscript", NULL }; + +static const char *stroked_fields[] = + { "type", "path", "pen", "color", "linejoin", "miterlimit", "linecap", "dash", + "prescript", "postscript", NULL }; + +static const char *text_fields[] = + { "type", "text", "dsize", "font", "color", "width", "height", "depth", "transform", + "prescript", "postscript", NULL }; + +static const char *special_fields[] = + { "type", "prescript", NULL }; + +static const char *start_bounds_fields[] = + { "type", "path", NULL }; + +static const char *start_clip_fields[] = + { "type", "path", NULL }; + +static const char *stop_bounds_fields[] = + { "type", NULL }; + +static const char *stop_clip_fields[] = + { "type", NULL }; + +static const char *no_fields[] = + { NULL }; + +typedef enum { + P_ERROR_LINE, P_HALF_LINE, P_MAX_LINE, P_MAIN_MEMORY, + P_HASH_SIZE, P_HASH_PRIME, P_PARAM_SIZE, P_IN_OPEN, P_RANDOM_SEED, + P_INTERACTION, P_INI_VERSION, P_TROFF_MODE, P_PRINT_NAMES, P_MEM_NAME, + P_JOB_NAME, P_FIND_FILE, P__SENTINEL +} mplib_parm_idx; + +typedef struct { + const char *name; /* parameter name */ + mplib_parm_idx idx; /* parameter index */ +} mplib_parm_struct; + +static mplib_parm_struct mplib_parms[] = { + {"error_line", P_ERROR_LINE }, + {"half_error_line", P_HALF_LINE }, + {"max_print_line", P_MAX_LINE }, + {"main_memory", P_MAIN_MEMORY }, + {"hash_size", P_HASH_SIZE }, + {"hash_prime", P_HASH_PRIME }, + {"param_size", P_PARAM_SIZE }, + {"max_in_open", P_IN_OPEN }, + {"random_seed", P_RANDOM_SEED }, + {"interaction", P_INTERACTION }, + {"ini_version", P_INI_VERSION }, + {"troff_mode", P_TROFF_MODE }, + {"print_found_names", P_PRINT_NAMES }, + {"mem_name", P_MEM_NAME }, + {"job_name", P_JOB_NAME }, + {"find_file", P_FIND_FILE }, + {NULL, P__SENTINEL } +}; + +typedef struct _FILE_ITEM { + FILE *f; +} _FILE_ITEM ; + +typedef struct _FILE_ITEM File; + +#define make_stream_buf(A) char *A; size_t A##_size; size_t A##_used + +#define free_stream_buf(A) xfree(mplib_data->A); mplib_data->A##_size = 0; mplib_data->A##_used = 0 + +typedef struct _MPLIB_INSTANCE_DATA { + void *term_file_ptr; + void *err_file_ptr; + void *log_file_ptr; + void *ps_file_ptr; + make_stream_buf(term_out); + make_stream_buf(error_out); + make_stream_buf(log_out); + make_stream_buf(ps_out); + char *input_data; + char *input_data_ptr; + size_t input_data_len; + struct mp_edge_object *edges ; + lua_State *LL; +} _MPLIB_INSTANCE_DATA; + +typedef struct _MPLIB_INSTANCE_DATA mplib_instance; + +static mplib_instance *mplib_get_data (MP mp) { + return (mplib_instance *)mp->userdata; +} + +static mplib_instance *mplib_make_data (void) { + mplib_instance *mplib_data = malloc(sizeof(mplib_instance)); + memset(mplib_data,0,sizeof(mplib_instance)); + return mplib_data ; +} + + +/* Start by defining all the callback routines for the library + * except |run_make_mpx| and |run_editor|. + */ + + +char *mplib_find_file (MP mp, const char *fname, const char *fmode, int ftype) { + mplib_instance *mplib_data = mplib_get_data(mp); + lua_State *L = mplib_data->LL; + lua_checkstack(L,4); + lua_getfield(L,LUA_REGISTRYINDEX,"mplib_file_finder"); + if (lua_isfunction(L,-1)) { + char *s = NULL, *x = NULL; + lua_pushstring(L, fname); + lua_pushstring(L, fmode); + if (ftype >= mp_filetype_text) { + lua_pushnumber(L, ftype-mp_filetype_text); + } else { + lua_pushstring(L, mplib_filetype_names[ftype]); + } + if(lua_pcall(L,3,1,0) != 0) { + fprintf(stdout,"Error in mp.find_file: %s\n", (char *)lua_tostring(L,-1)); + return NULL; + } + x = (char *)lua_tostring(L,-1); + if (x!=NULL) + s = strdup(x); + lua_pop(L,1); /* pop the string */ + return s; + } else { + lua_pop(L,1); + } + if (fmode[0] != 'r' || (! access (fname,R_OK)) || ftype) { + return strdup(fname); + } + return NULL; +} + +static int +mplib_find_file_function (lua_State *L) { + if (! (lua_isfunction(L,-1)|| lua_isnil(L,-1) )) { + return 1; /* error */ + } + lua_pushstring(L, "mplib_file_finder"); + lua_pushvalue(L,-2); + lua_rawset(L,LUA_REGISTRYINDEX); + return 0; +} + +void *mplib_open_file(MP mp, const char *fname, const char *fmode, int ftype) { + File *ff = malloc(sizeof (File)); + if (ff) { + mplib_instance *mplib_data = mplib_get_data(mp); + ff->f = NULL; + if (ftype==mp_filetype_terminal) { + if (fmode[0] == 'r') { + ff->f = stdin; + } else { + xfree(mplib_data->term_file_ptr); + ff->f = malloc(1); + mplib_data->term_file_ptr = ff->f; + } + } else if (ftype==mp_filetype_error) { + xfree(mplib_data->err_file_ptr); + ff->f = malloc(1); + mplib_data->err_file_ptr = ff->f; + } else if (ftype == mp_filetype_log) { + xfree(mplib_data->log_file_ptr); + ff->f = malloc(1); + mplib_data->log_file_ptr = ff->f; + } else if (ftype == mp_filetype_postscript) { + xfree(mplib_data->ps_file_ptr); + ff->f = malloc(1); + mplib_data->ps_file_ptr = ff->f; + } else { + char realmode[3]; + char *f = mplib_find_file(mp, fname,fmode,ftype); + if (f==NULL) + return NULL; + realmode[0] = *fmode; + realmode[1] = 'b'; + realmode[2] = 0; + ff->f = fopen(f, realmode); + if ((fmode[0] == 'r') && (ff->f == NULL)) { + free(ff); + return NULL; + } + } + return ff; + } + return NULL; +} + +static int +mplib_get_char (void *f, mplib_instance *mplib_data) { + int c; + if (f==stdin && mplib_data->input_data != NULL) { + if (mplib_data->input_data_len==0) { + if (mplib_data->input_data_ptr!=NULL) + mplib_data->input_data_ptr = NULL; + else + mplib_data->input_data = NULL; + c = EOF; + } else { + mplib_data->input_data_len--; + c = *(mplib_data->input_data_ptr)++; + } + } else { + c = fgetc(f); + } + return c; +} + +static void +mplib_unget_char (void *f, mplib_instance *mplib_data, int c) { + if (f==stdin && mplib_data->input_data_ptr != NULL) { + mplib_data->input_data_len++; + mplib_data->input_data_ptr--; + } else { + ungetc(c,f); + } +} + + +char *mplib_read_ascii_file (MP mp, void *ff, size_t *size) { + char *s = NULL; + if (ff!=NULL) { + int c; + size_t len = 0, lim = 128; + mplib_instance *mplib_data = mplib_get_data(mp); + FILE *f = ((File *)ff)->f; + if (f==NULL) + return NULL; + *size = 0; + c = mplib_get_char(f,mplib_data); + if (c==EOF) + return NULL; + s = malloc(lim); + if (s==NULL) return NULL; + while (c!=EOF && c!='\n' && c!='\r') { + if (len==lim) { + s =realloc(s, (lim+(lim>>2))); + if (s==NULL) return NULL; + lim+=(lim>>2); + } + s[len++] = c; + c = mplib_get_char(f,mplib_data); + } + if (c=='\r') { + c = mplib_get_char(f,mplib_data); + if (c!=EOF && c!='\n') + mplib_unget_char(f,mplib_data,c); + } + s[len] = 0; + *size = len; + } + return s; +} + +#define APPEND_STRING(a,b) do { \ + if ((mplib_data->a##_used+strlen(b))>=mplib_data->a##_size) { \ + mplib_data->a##_size += 256+(mplib_data->a##_size)/5+strlen(b); \ + mplib_data->a = realloc(mplib_data->a,mplib_data->a##_size); \ + } \ + (void)strcpy(mplib_data->a+mplib_data->a##_used,b); \ + mplib_data->a##_used += strlen(b); \ + } while (0) + +void mplib_write_ascii_file (MP mp, void *ff, const char *s) { + if (ff!=NULL) { + void *f = ((File *)ff)->f; + mplib_instance *mplib_data = mplib_get_data(mp); + if (f!=NULL) { + if (f==mplib_data->term_file_ptr) { + APPEND_STRING(term_out,s); + } else if (f==mplib_data->err_file_ptr) { + APPEND_STRING(error_out,s); + } else if (f==mplib_data->log_file_ptr) { + APPEND_STRING(log_out,s); + } else if (f==mplib_data->ps_file_ptr) { + APPEND_STRING(ps_out,s); + } else { + fprintf((FILE *)f,s); + } + } + } +} + +void mplib_read_binary_file (MP mp, void *ff, void **data, size_t *size) { + (void)mp; + if (ff!=NULL) { + size_t len = 0; + FILE *f = ((File *)ff)->f; + if (f!=NULL) + len = fread(*data,1,*size,f); + *size = len; + } +} + +void mplib_write_binary_file (MP mp, void *ff, void *s, size_t size) { + (void)mp; + if (ff!=NULL) { + FILE *f = ((File *)ff)->f; + if (f!=NULL) + fwrite(s,size,1,f); + } +} + + +void mplib_close_file (MP mp, void *ff) { + if (ff!=NULL) { + mplib_instance *mplib_data = mplib_get_data(mp); + void *f = ((File *)ff)->f; + if (f != NULL && f != mplib_data->term_file_ptr && f != mplib_data->err_file_ptr + && f != mplib_data->log_file_ptr && f != mplib_data->ps_file_ptr) { + fclose(f); + } + free(ff); + } +} + +int mplib_eof_file (MP mp, void *ff) { + if (ff!=NULL) { + mplib_instance *mplib_data = mplib_get_data(mp); + FILE *f = ((File *)ff)->f; + if (f==NULL) + return 1; + if (f==stdin && mplib_data->input_data != NULL) { + return (mplib_data->input_data_len==0); + } + return feof(f); + } + return 1; +} + +void mplib_flush_file (MP mp, void *ff) { + (void)mp; + (void)ff; + return ; +} + +#define APPEND_TO_EDGES(a) do { \ + if (mplib_data->edges==NULL) { \ + mplib_data->edges = hh; \ + } else { \ + struct mp_edge_object *p = mplib_data->edges; \ + while (p->_next!=NULL) { p = p->_next; } \ + p->_next = hh; \ + } \ +} while (0) + +void mplib_shipout_backend (MP mp, int h) { + struct mp_edge_object *hh = mp_gr_export(mp, h); + if (hh) { + mplib_instance *mplib_data = mplib_get_data(mp); + APPEND_TO_EDGES(hh); + } +} + + +static void +mplib_setup_file_ops(struct MP_options * options) { + options->find_file = mplib_find_file; + options->open_file = mplib_open_file; + options->close_file = mplib_close_file; + options->eof_file = mplib_eof_file; + options->flush_file = mplib_flush_file; + options->write_ascii_file = mplib_write_ascii_file; + options->read_ascii_file = mplib_read_ascii_file; + options->write_binary_file = mplib_write_binary_file; + options->read_binary_file = mplib_read_binary_file; + options->shipout_backend = mplib_shipout_backend; +} + +static int +mplib_new (lua_State *L) { + MP *mp_ptr; + mp_ptr = lua_newuserdata(L, sizeof(MP *)); + if (mp_ptr) { + int i; + mplib_instance *mplib_data; + struct MP_options * options; /* instance options */ + options = mp_options(); + mplib_setup_file_ops(options); + mplib_data = mplib_make_data(); + mplib_data->LL = L; + options->userdata = (void *)mplib_data; + options->noninteractive = 1; /* required ! */ + options->print_found_names = 0; + if (lua_type(L,1)==LUA_TTABLE) { + for (i=0;mplib_parms[i].name!=NULL;i++) { + lua_getfield(L,1,mplib_parms[i].name); + if (lua_isnil(L,-1)) { + lua_pop(L,1); + continue; /* skip unset */ + } + switch(mplib_parms[i].idx) { + case P_ERROR_LINE: + options->error_line = lua_tointeger(L,-1); + break; + case P_HALF_LINE: + options->half_error_line = lua_tointeger(L,-1); + break; + case P_MAX_LINE: + options->max_print_line = lua_tointeger(L,-1); + break; + case P_MAIN_MEMORY: + options->main_memory = lua_tointeger(L,-1); + break; + case P_HASH_SIZE: + options->hash_size = lua_tointeger(L,-1); + break; + case P_HASH_PRIME: + options->hash_prime = lua_tointeger(L,-1); + break; + case P_PARAM_SIZE: + options->param_size = lua_tointeger(L,-1); + break; + case P_IN_OPEN: + options->max_in_open = lua_tointeger(L,-1); + break; + case P_RANDOM_SEED: + options->random_seed = lua_tointeger(L,-1); + break; + case P_INTERACTION: + options->interaction = luaL_checkoption(L,-1,"errorstopmode", interaction_options); + break; + case P_INI_VERSION: + options->ini_version = lua_toboolean(L,-1); + break; + case P_TROFF_MODE: + options->troff_mode = lua_toboolean(L,-1); + break; + case P_PRINT_NAMES: + options->print_found_names = lua_toboolean(L,-1); + break; + /* + case P_COMMAND_LINE: + options->command_line = strdup((char *)lua_tostring(L,-1)); + break; + */ + case P_MEM_NAME: + options->mem_name = strdup((char *)lua_tostring(L,-1)); + break; + case P_JOB_NAME: + options->job_name = strdup((char *)lua_tostring(L,-1)); + break; + case P_FIND_FILE: + if(mplib_find_file_function(L)) { /* error here */ + fprintf(stdout,"Invalid arguments to mp.new({find_file=...})\n"); + } + break; + default: + break; + } + lua_pop(L,1); + } + } + *mp_ptr = mp_new(options); + xfree(options->command_line); + xfree(options->mem_name); + xfree(options->job_name); + free(options); + if (*mp_ptr) { + luaL_getmetatable(L,MPLIB_METATABLE); + lua_setmetatable(L,-2); + return 1; + } + } + lua_pushnil(L); + return 1; +} + +static int +mplib_collect (lua_State *L) { + MP *mp_ptr = is_mp(L,1); + xfree(*mp_ptr); + return 0; +} + +static int +mplib_tostring (lua_State *L) { + MP *mp_ptr = is_mp(L,1); + if (*mp_ptr!=NULL) { + lua_pushfstring(L,"",*mp_ptr); + return 1; + } + return 0; +} + +static int +mplib_wrapresults(lua_State *L, mplib_instance *mplib_data, int h) { + lua_checkstack(L,5); + lua_newtable(L); + if (mplib_data->term_out != NULL) { + lua_pushstring(L,mplib_data->term_out); + lua_setfield(L,-2,"term"); + free_stream_buf(term_out); + } + if (mplib_data->error_out != NULL) { + lua_pushstring(L,mplib_data->error_out); + lua_setfield(L,-2,"error"); + free_stream_buf(error_out); + } + if (mplib_data->log_out != NULL ) { + lua_pushstring(L,mplib_data->log_out); + lua_setfield(L,-2,"log"); + free_stream_buf(log_out); + } + if (mplib_data->edges != NULL ) { + struct mp_edge_object **v; + struct mp_edge_object *p = mplib_data->edges; + int i = 1; + lua_newtable(L); + while (p!=NULL) { + v = lua_newuserdata (L, sizeof(struct mp_edge_object *)); + *v = p; + luaL_getmetatable(L,MPLIB_FIG_METATABLE); + lua_setmetatable(L,-2); + lua_rawseti(L,-2,i); i++; + p = p->_next; + } + lua_setfield(L,-2,"fig"); + mplib_data->edges = NULL; + } + lua_pushnumber(L,h); + lua_setfield(L,-2,"status"); + return 1; +} + +static int +mplib_execute (lua_State *L) { + MP *mp_ptr = is_mp(L,1); + if (*mp_ptr!=NULL && lua_isstring(L,2)) { + int h; + mplib_instance *mplib_data = mplib_get_data(*mp_ptr); + mplib_data->input_data = (char *)lua_tolstring(L,2, &(mplib_data->input_data_len)); + mplib_data->input_data_ptr = mplib_data->input_data; + if ((*mp_ptr)->run_state==0) { + h = mp_initialize(*mp_ptr); + } + h = mp_execute(*mp_ptr); + if (mplib_data->input_data_len!=0) { + mplib_data->input_data = NULL; + mplib_data->input_data_ptr = NULL; + mplib_data->input_data_len=0; + } + return mplib_wrapresults(L, mplib_data, h); + } else { + lua_pushnil(L); + } + return 1; +} + +static int +mplib_finish (lua_State *L) { + MP *mp_ptr = is_mp(L,1); + if (*mp_ptr!=NULL) { + mplib_instance *mplib_data = mplib_get_data(*mp_ptr); + int h = mp_finish(*mp_ptr); + return mplib_wrapresults(L, mplib_data, h); + } else { + lua_pushnil(L); + } + return 1; +} + +static int +mplib_statistics (lua_State *L) { + MP *mp_ptr = is_mp(L,1); + if (*mp_ptr!=NULL) { + lua_newtable(L); + lua_pushnumber(L, mp_memory_usage (*mp_ptr)); + lua_setfield(L,-2,"main_memory"); + lua_pushnumber(L, mp_hash_usage (*mp_ptr)); + lua_setfield(L,-2,"hash_size"); + lua_pushnumber(L, mp_param_usage (*mp_ptr)); + lua_setfield(L,-2,"param_size"); + lua_pushnumber(L, mp_open_usage (*mp_ptr)); + lua_setfield(L,-2,"max_in_open"); + } else { + lua_pushnil(L); + } + return 1; +} + + +/* figure methods */ + +static int +mplib_fig_collect (lua_State *L) { + struct mp_edge_object **hh = is_fig(L,1); + if (*hh!=NULL) { + mp_gr_toss_objects (*hh); + *hh=NULL; + } + return 0; +} + +static int +mplib_fig_body (lua_State *L) { + int i = 1; + struct mp_graphic_object **v; + struct mp_graphic_object *p; + struct mp_edge_object **hh = is_fig(L,1); + lua_newtable(L); + p = (*hh)->body; + while (p!=NULL) { + v = lua_newuserdata (L, sizeof(struct mp_graphic_object *)); + *v = p; + luaL_getmetatable(L,MPLIB_GR_METATABLE); + lua_setmetatable(L,-2); + lua_rawseti(L,-2,i); i++; + p = p->_link_field; + } + (*hh)->body = NULL; /* prevent double free */ + return 1; +} + +static int +mplib_fig_copy_body (lua_State *L) { + int i = 1; + struct mp_graphic_object **v; + struct mp_graphic_object *p; + struct mp_edge_object **hh = is_fig(L,1); + lua_newtable(L); + p = (*hh)->body; + while (p!=NULL) { + v = lua_newuserdata (L, sizeof(struct mp_graphic_object *)); + *v = mp_gr_copy_object((*hh)->_parent,p); + luaL_getmetatable(L,MPLIB_GR_METATABLE); + lua_setmetatable(L,-2); + lua_rawseti(L,-2,i); i++; + p = p->_link_field; + } + return 1; +} + + +static int +mplib_fig_tostring (lua_State *L) { + struct mp_edge_object **hh = is_fig(L,1); + lua_pushfstring(L,"
",*hh); + return 1; +} + + + +static int +mp_wrapped_shipout (struct mp_edge_object *hh, int prologues, int procset) { + MP mp = hh->_parent; + if (setjmp(mp->jump_buf)) { + return 0; + } + mp_gr_ship_out(hh,prologues,procset); + return 1; +} + +static int +mplib_fig_postscript (lua_State *L) { + struct mp_edge_object **hh = is_fig(L,1); + int prologues = luaL_optnumber(L,2,-1); + int procset = luaL_optnumber(L,3,-1); + mplib_instance *mplib_data = mplib_get_data((*hh)->_parent); + if (mplib_data->ps_out == NULL) { + if (mp_wrapped_shipout(*hh,prologues, procset)) { + if (mplib_data->ps_out!=NULL ) { + lua_pushstring(L, mplib_data->ps_out); + free_stream_buf(ps_out); + } else { + lua_pushnil(L); + } + return 1; + } else { + lua_pushnil(L); + lua_pushstring(L,mplib_data->log_out); + xfree(mplib_data->ps_out); + return 2; + } + } + lua_pushnil(L); + return 1; +} + +static int +mplib_fig_filename (lua_State *L) { + struct mp_edge_object **hh = is_fig(L,1); + if (*hh!= NULL) { + char *s = (*hh)->_filename; + lua_pushstring(L,s); + } else { + lua_pushnil(L); + } + return 1; +} + + +static int +mplib_fig_bb (lua_State *L) { + struct mp_edge_object **hh = is_fig(L,1); + lua_newtable(L); + lua_pushnumber(L, (double)(*hh)->_minx/65536.0); + lua_rawseti(L,-2,1); + lua_pushnumber(L, (double)(*hh)->_miny/65536.0); + lua_rawseti(L,-2,2); + lua_pushnumber(L, (double)(*hh)->_maxx/65536.0); + lua_rawseti(L,-2,3); + lua_pushnumber(L, (double)(*hh)->_maxy/65536.0); + lua_rawseti(L,-2,4); + return 1; +} + +/* object methods */ + +static int +mplib_gr_collect (lua_State *L) { + struct mp_graphic_object **hh = is_gr_object(L,1); + if (*hh!=NULL) { + mp_gr_toss_object(*hh); + *hh=NULL; + } + return 0; +} + +static int +mplib_gr_tostring (lua_State *L) { + struct mp_graphic_object **hh = is_gr_object(L,1); + lua_pushfstring(L,"",*hh); + return 1; +} + + +static int +mplib_gr_fields (lua_State *L) { + const char **fields; + const char *f; + int i = 1; + struct mp_graphic_object **hh = is_gr_object(L,1); + if (*hh) { + switch ((*hh)->_type_field) { + case mp_fill_code: fields = fill_fields; break; + case mp_stroked_code: fields = stroked_fields; break; + case mp_text_code: fields = text_fields; break; + case mp_special_code: fields = special_fields; break; + case mp_start_clip_code: fields = start_clip_fields; break; + case mp_start_bounds_code: fields = start_bounds_fields; break; + case mp_stop_clip_code: fields = stop_clip_fields; break; + case mp_stop_bounds_code: fields = stop_bounds_fields; break; + default: fields = no_fields; + } + lua_newtable(L); + for (f = *fields; f != NULL; f++) { + lua_pushstring(L,f); + lua_rawseti(L,-2,i); i++; + } + } else { + lua_pushnil(L); + } + return 1; +} + + +#define mplib_push_number(L,x) lua_pushnumber(L,(lua_Number)(x)/65536.0) + +#define MPLIB_PATH 0 +#define MPLIB_PEN 1 + +static void +mplib_push_path (lua_State *L, struct mp_knot *h, int is_pen) { + struct mp_knot *p; /* for scanning the path */ + int i=1; + p=h; + if (p!=NULL) { + lua_newtable(L); + do { + lua_createtable(L,0,6); + if (!is_pen) { + if (p->left_type_field != mp_explicit) { + mplib_push_S(left_type); + lua_pushstring(L,knot_type_enum[p->left_type_field]); + lua_rawset(L,-3); + } + if (p->right_type_field != mp_explicit) { + mplib_push_S(right_type); + lua_pushstring(L,knot_type_enum[p->right_type_field]); + lua_rawset(L,-3); + } + } + mplib_push_S(x_coord); + mplib_push_number(L,p->x_coord_field); + lua_rawset(L,-3); + mplib_push_S(y_coord); + mplib_push_number(L,p->y_coord_field); + lua_rawset(L,-3); + mplib_push_S(left_x); + mplib_push_number(L,p->left_x_field); + lua_rawset(L,-3); + mplib_push_S(left_y); + mplib_push_number(L,p->left_y_field); + lua_rawset(L,-3); + mplib_push_S(right_x); + mplib_push_number(L,p->right_x_field); + lua_rawset(L,-3); + mplib_push_S(right_y); + mplib_push_number(L,p->right_y_field); + lua_rawset(L,-3); + lua_rawseti(L,-2,i); i++; + if ( p->right_type_field==mp_endpoint ) { + return; + } + p=p->next_field; + } while (p!=h) ; + } else { + lua_pushnil(L); + } +} + +#define set_color_objects(pq) \ + object_color_model = pq->color_model_field; \ + object_color_a = pq->color_field._a_val; \ + object_color_b = pq->color_field._b_val; \ + object_color_c = pq->color_field._c_val; \ + object_color_d = pq->color_field._d_val; + + +static void +mplib_push_color (lua_State *L, struct mp_graphic_object *p ) { + int object_color_model; + int object_color_a, object_color_b, object_color_c, object_color_d ; + if (p!=NULL) { + if (p->_type_field == mp_fill_code) { + mp_fill_object *h = (mp_fill_object *)p; + set_color_objects(h); + } else if (p->_type_field == mp_stroked_code) { + mp_stroked_object *h = (mp_stroked_object *)p; + set_color_objects(h); + } else { + mp_text_object *h = (mp_text_object *)p; + set_color_objects(h); + } + lua_newtable(L); + if (object_color_model >= mp_grey_model) { + mplib_push_number(L,object_color_a); + lua_rawseti(L,-2,1); + if (object_color_model >= mp_rgb_model) { + mplib_push_number(L,object_color_b); + lua_rawseti(L,-2,2); + mplib_push_number(L,object_color_c); + lua_rawseti(L,-2,3); + if (object_color_model == mp_cmyk_model) { + mplib_push_number(L,object_color_d); + lua_rawseti(L,-2,4); + } + } + } + } else { + lua_pushnil(L); + } +} + +/* the dash scale is not exported, the field has no external value */ +static void +mplib_push_dash (lua_State *L, struct mp_stroked_object *h ) { + mp_dash_object *d; + if (h!=NULL && h->dash_p_field != NULL) { + d = h->dash_p_field; + lua_newtable(L); + mplib_push_number(L,d->offset_field); + lua_setfield(L,-2,"offset"); + if (d->array_field!=NULL ) { + int i = 0; + lua_newtable(L); + while (*(d->array_field+i) != -1) { + mplib_push_number(L, *(d->array_field+1)); + i++; + lua_rawseti(L,-2,i); + } + lua_setfield(L,-2,"dashes"); + } + } else { + lua_pushnil(L); + } +} + +static void +mplib_push_transform (lua_State *L, struct mp_text_object *h ) { + int i = 1; + if (h!=NULL) { + lua_createtable(L,6,0); + mplib_push_number(L,h->tx_field); + lua_rawseti(L,-2,i); i++; + mplib_push_number(L,h->ty_field); + lua_rawseti(L,-2,i); i++; + mplib_push_number(L,h->txx_field); + lua_rawseti(L,-2,i); i++; + mplib_push_number(L,h->tyx_field); + lua_rawseti(L,-2,i); i++; + mplib_push_number(L,h->txy_field); + lua_rawseti(L,-2,i); i++; + mplib_push_number(L,h->tyy_field); + lua_rawseti(L,-2,i); i++; + } else { + lua_pushnil(L); + } +} + +#define FIELD(A) (mplib_is_S(A,2)) + +static void +mplib_fill_field (lua_State *L, struct mp_fill_object *h) { + if (FIELD(path)) { + mplib_push_path(L, h->path_p_field, MPLIB_PATH); + } else if (FIELD(htap)) { + mplib_push_path(L, h->htap_p_field, MPLIB_PATH); + } else if (FIELD(pen)) { + mplib_push_path(L, h->pen_p_field, MPLIB_PEN); + } else if (FIELD(color)) { + mplib_push_color(L,(mp_graphic_object *)h); + } else if (FIELD(linejoin)) { + lua_pushnumber(L,h->ljoin_field); + } else if (FIELD(miterlimit)) { + mplib_push_number(L,h->miterlim_field); + } else if (FIELD(prescript)) { + lua_pushstring(L,h->pre_script_field); + } else if (FIELD(postscript)) { + lua_pushstring(L,h->post_script_field); + } else { + lua_pushnil(L); + } +} + +static void +mplib_stroked_field (lua_State *L, struct mp_stroked_object *h) { + if (FIELD(path)) { + mplib_push_path(L, h->path_p_field, MPLIB_PATH); + } else if (FIELD(pen)) { + mplib_push_path(L, h->pen_p_field, MPLIB_PEN); + } else if (FIELD(color)) { + mplib_push_color(L, (mp_graphic_object *)h); + } else if (FIELD(dash)) { + mplib_push_dash(L,h); + } else if (FIELD(linecap)) { + lua_pushnumber(L,h->lcap_field); + } else if (FIELD(linejoin)) { + lua_pushnumber(L,h->ljoin_field); + } else if (FIELD(miterlimit)) { + mplib_push_number(L,h->miterlim_field); + } else if (FIELD(prescript)) { + lua_pushstring(L,h->pre_script_field); + } else if (FIELD(postscript)) { + lua_pushstring(L,h->post_script_field); + } else { + lua_pushnil(L); + } +} + +static void +mplib_text_field (lua_State *L, struct mp_text_object *h) { + if (FIELD(text)) { + lua_pushstring(L,h->text_p_field); + } else if (FIELD(dsize)) { + mplib_push_number(L,(h->font_dsize_field/16)); + } else if (FIELD(font)) { + lua_pushstring(L,h->font_name_field); + } else if (FIELD(color)) { + mplib_push_color(L,(mp_graphic_object *)h); + } else if (FIELD(width)) { + mplib_push_number(L,h->width_field); + } else if (FIELD(height)) { + mplib_push_number(L,h->height_field); + } else if (FIELD(depth)) { + mplib_push_number(L,h->depth_field); + } else if (FIELD(transform)) { + mplib_push_transform(L,h); + } else if (FIELD(prescript)) { + lua_pushstring(L,h->pre_script_field); + } else if (FIELD(postscript)) { + lua_pushstring(L,h->post_script_field); + } else { + lua_pushnil(L); + } +} + +static void +mplib_special_field (lua_State *L, struct mp_special_object *h) { + if (FIELD(prescript)) { + lua_pushstring(L,h->pre_script_field); + } else { + lua_pushnil(L); + } +} + +static void +mplib_start_bounds_field (lua_State *L, struct mp_bounds_object *h) { + if (FIELD(path)) { + mplib_push_path(L,h->path_p_field, MPLIB_PATH); + } else { + lua_pushnil(L); + } +} + +static void +mplib_start_clip_field (lua_State *L, struct mp_clip_object *h) { + if (FIELD(path)) { + mplib_push_path(L,h->path_p_field, MPLIB_PATH); + } else { + lua_pushnil(L); + } +} + +static int +mplib_gr_index (lua_State *L) { + struct mp_graphic_object **hh = is_gr_object(L,1); + if (*hh) { + struct mp_graphic_object *h = *hh; + if (mplib_is_S(type,2)) { + lua_rawgeti(L,LUA_REGISTRYINDEX,mplib_type_Ses[h->_type_field]); + } else { + switch (h->_type_field) { + case mp_fill_code: mplib_fill_field(L,(mp_fill_object *)h); break; + case mp_stroked_code: mplib_stroked_field(L,(mp_stroked_object *)h); break; + case mp_text_code: mplib_text_field(L,(mp_text_object *)h); break; + case mp_special_code: mplib_special_field(L,(mp_special_object *)h); break; + case mp_start_clip_code: mplib_start_clip_field(L,(mp_clip_object *)h); break; + case mp_start_bounds_code: mplib_start_bounds_field(L,(mp_bounds_object *)h); break; + /* case mp_stop_clip_code: */ + /* case mp_stop_bounds_code: */ + default: lua_pushnil(L); + } + } + } else { + lua_pushnil(L); + } + return 1; +} + + +static const struct luaL_reg mplib_meta[] = { + {"__gc", mplib_collect}, + {"__tostring", mplib_tostring}, + {NULL, NULL} /* sentinel */ +}; + +static const struct luaL_reg mplib_fig_meta[] = { + {"__gc", mplib_fig_collect }, + {"__tostring", mplib_fig_tostring }, + {"objects", mplib_fig_body }, + {"copy_objects", mplib_fig_copy_body }, + {"filename", mplib_fig_filename }, + {"postscript", mplib_fig_postscript }, + {"boundingbox", mplib_fig_bb }, + {NULL, NULL} /* sentinel */ +}; + +static const struct luaL_reg mplib_gr_meta[] = { + {"__gc", mplib_gr_collect }, + {"__tostring", mplib_gr_tostring }, + {"__index", mplib_gr_index }, + {"fields", mplib_gr_fields }, + {NULL, NULL} /* sentinel */ +}; + + +static const struct luaL_reg mplib_d [] = { + {"execute", mplib_execute }, + {"finish", mplib_finish }, + {"statistics", mplib_statistics }, + {NULL, NULL} /* sentinel */ +}; + + +static const struct luaL_reg mplib_m[] = { + {"new", mplib_new}, + {NULL, NULL} /* sentinel */ +}; + + +int +luaopen_mp (lua_State *L) { + mplib_init_Ses(L); + luaL_newmetatable(L,MPLIB_GR_METATABLE); + lua_pushvalue(L, -1); /* push metatable */ + lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ + luaL_register(L, NULL, mplib_gr_meta); /* object meta methods */ + lua_pop(L,1); + + luaL_newmetatable(L,MPLIB_FIG_METATABLE); + lua_pushvalue(L, -1); /* push metatable */ + lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ + luaL_register(L, NULL, mplib_fig_meta); /* figure meta methods */ + lua_pop(L,1); + + luaL_newmetatable(L,MPLIB_METATABLE); + lua_pushvalue(L, -1); /* push metatable */ + lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ + luaL_register(L, NULL, mplib_meta); /* meta methods */ + luaL_register(L, NULL, mplib_d); /* dict methods */ + luaL_register(L, "mplib", mplib_m); /* module functions */ + return 1; +} + diff --git a/Build/source/texk/web2c/luatexdir/lua/lnodelib.c b/Build/source/texk/web2c/luatexdir/lua/lnodelib.c new file mode 100644 index 00000000000..de269d5d9c8 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/lnodelib.c @@ -0,0 +1,1967 @@ +/* $Id: lnodelib.c 1056 2008-02-19 15:42:17Z taco $ */ + +#include "luatex-api.h" +#include + +#include "nodes.h" + +#define init_luaS_index(a) do { \ + lua_pushliteral(L,#a); \ + luaS_##a##_ptr = (char *)lua_tostring(L,-1); \ + luaS_##a##_index = luaL_ref (L,LUA_REGISTRYINDEX); \ + } while (0) + +#define make_luaS_index(a) \ + static int luaS_##a##_index = 0; \ + static char * luaS_##a##_ptr = NULL + +#define luaS_index(a) luaS_##a##_index + +#define luaS_ptr_eq(a,b) (a==luaS_##b##_ptr) + +#define NODE_METATABLE "luatex_node" + +make_luaS_index(luatex_node); + +halfword *check_isnode (lua_State *L, int ud) { + register halfword *p = lua_touserdata(L, ud); + if (p != NULL) { + if (lua_getmetatable(L, ud)) { + lua_rawgeti(L,LUA_REGISTRYINDEX,luaS_index(luatex_node)); + lua_gettable(L, LUA_REGISTRYINDEX); + if (lua_rawequal(L, -1, -2)) { + lua_pop(L, 2); + return p; + } + } + } + luaL_typerror(L, ud, NODE_METATABLE); + return NULL; +} + +/* This routine finds the numerical value of a string (or number) at + lua stack index |n|. If it is not a valid node type, returns -1 */ + +static +int do_get_node_type_id (lua_State *L, int n, node_info *data) { + register int j; + if (lua_type(L,n)==LUA_TSTRING) { + char *s = (char *)lua_tostring(L,n); + for (j=0;data[j].id!=-1;j++) { + if (strcmp(s,data[j].name)==0) + return j; + } + } else if (lua_type(L,n)==LUA_TNUMBER) { + register int i = lua_tointeger(L,n); + if (data[i].id==i) + return i; + for (j=0;data[j].id!=-1;j++) { + if (data[j].id==i) + return j; + } + } + return -1; +} + +#define get_node_type_id(L,n) do_get_node_type_id(L,n,node_data) +#define get_node_subtype_id(L,n) do_get_node_type_id(L,n,whatsit_node_data) + +static +int get_valid_node_type_id (lua_State *L, int n) { + int i = get_node_type_id(L,n); + if (i==-1) { + if (lua_type(L,n)==LUA_TSTRING) { + lua_pushfstring(L, "Invalid node type id: %s",(char *)lua_tostring(L,n)); + } else { + lua_pushfstring(L, "Invalid node type id: %d",(int)lua_tonumber(L,n)); + } + return lua_error(L); + } + return i; +} + +static +int get_valid_node_subtype_id (lua_State *L, int n) { + int i = get_node_subtype_id(L,n); + if (i==-1) { + if (lua_type(L,n)==LUA_TSTRING) { + lua_pushfstring(L, "Invalid whatsit node id: %s",(char *)lua_tostring(L,n)); + } else { + lua_pushfstring(L, "Invalid whatsit node id: %d",(int)lua_tonumber(L,n)); + } + return lua_error(L); + } + return i; +} + + + +/* Creates a userdata object for a number found at the stack top, + if it is representing a node (i.e. an pointer into |varmem|). + It replaces the stack entry with the new userdata, or pushes + |nil| if the number is |null|, or if the index is definately out of + range. This test could be improved. +*/ + +void +lua_nodelib_push(lua_State *L) { + halfword n; + halfword *a; + n = -1; + if (lua_isnumber(L,-1)) { + n = lua_tointeger(L,-1); + } + lua_pop(L,1); + if ((n==null) || (n<0) || (n>var_mem_max)) { + lua_pushnil(L); + } else { + a = lua_newuserdata(L, sizeof(halfword)); + *a = n; + lua_rawgeti(L,LUA_REGISTRYINDEX,luaS_index(luatex_node)); + lua_gettable(L, LUA_REGISTRYINDEX); + lua_setmetatable(L,-2); + } + return; +} + +void +lua_nodelib_push_fast(lua_State *L, halfword n) { + halfword *a; + a = lua_newuserdata(L, sizeof(halfword)); + *a = n; + lua_rawgeti(L,LUA_REGISTRYINDEX,luaS_index(luatex_node)); + lua_gettable(L, LUA_REGISTRYINDEX); + lua_setmetatable(L,-2); + return; +} + + +/* converts type strings to type ids */ + +static int +lua_nodelib_id (lua_State *L) { + integer i = get_node_type_id(L,1); + if (i>=0) { + lua_pushnumber(L,i); + } else { + lua_pushnil(L); + } + return 1; +} + + +static int +lua_nodelib_subtype (lua_State *L) { + integer i = get_node_subtype_id(L,1); + if (i>=0) { + lua_pushnumber(L,i); + } else { + lua_pushnil(L); + } + return 1; +} + +/* converts id numbers to type names */ + +static int +lua_nodelib_type (lua_State *L) { + integer i = get_node_type_id(L,1); + if (i>=0) { + lua_pushstring(L,node_data[i].name); + } else { + lua_pushnil(L); + } + return 1; +} + + +/* allocate a new node */ + +static int +lua_nodelib_new(lua_State *L) { + int i,j; + halfword n = null; + i = get_valid_node_type_id(L,1); + + if (i==whatsit_node) { + j = -1; + if (lua_gettop(L)>1) { j = get_valid_node_subtype_id(L,2); } + if (j<0) { + lua_pushstring(L, "Creating a whatsit requires the subtype number as a second argument"); + lua_error(L); + } + } else { + j = 0; + if (lua_gettop(L)>1) { j = lua_tointeger(L,2); } + } + n = new_node(i,j); + lua_nodelib_push_fast(L,n); + return 1; +} + + +/* Free a node. + This function returns the 'next' node, because that may be helpful */ + +static int +lua_nodelib_free(lua_State *L) { + halfword *n; + halfword p; + if (lua_gettop(L)<1) { + lua_pushnil(L); + return 1; + } else if(lua_isnil(L,1)) { + return 1; /* the nil itself */ + } + n = check_isnode(L,1); + p = vlink(*n); + flush_node(*n); + lua_pushnumber(L,p); + lua_nodelib_push(L); + return 1; +} + +/* Free a node list */ + +static int +lua_nodelib_flush_list(lua_State *L) { + halfword *n_ptr; + if ((lua_gettop(L)<1) || lua_isnil(L,1)) + return 0; + n_ptr = check_isnode(L,1); + flush_node_list(*n_ptr); + return 0; +} + +/* find prev, and fix backlinks */ + +#define set_t_to_prev(head,current) \ + t = head; \ + while (vlink(t)!=current && t != null) { \ + if (vlink(t)!=null) \ + alink(vlink(t)) = t; \ + t = vlink(t); \ + } + +/* remove a node from a list */ + + +static int +lua_nodelib_remove (lua_State *L) { + halfword head, current, t; + if (lua_gettop(L)<2) { + lua_pushstring(L,"Not enough arguments for node.remove()"); + lua_error(L); + } + head = *(check_isnode(L,1)); + if (lua_isnil(L,2)) { + return 2; /* the arguments, as they are */ + } + current = *(check_isnode(L,2)); + + if (head == current) { + if (alink(head)!=null && vlink(current)!=null) { + alink(vlink(current)) = alink(head); + } + head = vlink(current); + current = head; + } else { /* head != current */ + t = alink(current); + if (t==null || vlink(t)!=current) { + set_t_to_prev(head,current); + if (t==null) { /* error! */ + lua_pushstring(L,"Attempt to node.remove() a non-existing node"); + lua_error(L); + } + } + /* t is now the previous node */ + vlink(t) = vlink(current); + if (vlink(current)!=null) { + alink(vlink(current)) = t; + } + current = vlink(current); + } + lua_pushnumber(L,head); + lua_nodelib_push(L); + lua_pushnumber(L,current); + lua_nodelib_push(L); + return 2; +} + +/* Insert a node in a list */ + +static int +lua_nodelib_insert_before (lua_State *L) { + halfword head, current, n, t; + if (lua_gettop(L)<3) { + lua_pushstring(L,"Not enough arguments for node.insert_before()"); + lua_error(L); + } + if (lua_isnil(L,3)) { + lua_pop(L,1); + return 2; + } else { + n = *(check_isnode(L,3)); + } + if (lua_isnil(L,1)) { /* no head */ + vlink(n) = null; + alink(n) = null; + lua_nodelib_push_fast(L,n); + lua_pushvalue(L,-1); + return 2; + } else { + head = *(check_isnode(L,1)); + } + if (lua_isnil(L,2)) { + current = tail_of_list(head); + } else { + current = *(check_isnode(L,2)); + } + t = alink(current); + if (t==null || vlink(t)!=current) { + set_t_to_prev(head,current); + if (t==null) { /* error! */ + lua_pushstring(L,"Attempt to node.insert_before() a non-existing node"); + lua_error(L); + } + } + couple_nodes(t,n); + couple_nodes(n,current); + if (head==current) { + lua_nodelib_push_fast(L,n); + } else { + lua_nodelib_push_fast(L,head); + } + lua_nodelib_push_fast(L,n); + return 2; +} + + +static int +lua_nodelib_insert_after (lua_State *L) { + halfword head, current, n; + if (lua_gettop(L)<3) { + lua_pushstring(L,"Not enough arguments for node.insert_after()"); + lua_error(L); + } + if (lua_isnil(L,3)) { + lua_pop(L,1); + return 2; + } else { + n = *(check_isnode(L,3)); + } + if (lua_isnil(L,1)) { /* no head */ + vlink(n) = null; + alink(n) = null; + lua_nodelib_push_fast(L,n); + lua_pushvalue(L,-1); + return 2; + } else { + head = *(check_isnode(L,1)); + } + if (lua_isnil(L,2)) { + current = head; + while (vlink(current)!=null) + current = vlink(current); + } else { + current = *(check_isnode(L,2)); + } + try_couple_nodes(n,vlink(current)); + couple_nodes(current, n); + + lua_pop(L,2); + lua_nodelib_push_fast(L,n); + return 2; +} + + +/* Copy a node list */ + +static int +lua_nodelib_copy_list (lua_State *L) { + halfword *n; + halfword m; + if (lua_isnil(L,1)) + return 1; /* the nil itself */ + n = check_isnode(L,1); + m = copy_node_list(*n); + lua_nodelib_push_fast(L,m); + return 1; +} + +/* (Deep) copy a node */ + +static int +lua_nodelib_copy(lua_State *L) { + halfword *n; + halfword m; + if (lua_isnil(L,1)) + return 1; /* the nil itself */ + n = check_isnode(L,1); + m = copy_node(*n); + lua_nodelib_push_fast(L,m); + return 1; +} + +/* output (write) a node to tex's processor */ + +static int +lua_nodelib_append(lua_State *L) { + halfword *n; + halfword m; + int i, j; + j = lua_gettop(L); + for (i=1;i<=j;i++) { + n = check_isnode(L,i); + m = copy_node_list(*n); + new_tail_append(m); + while (vlink(m)!= null) { + m = vlink(m); + new_tail_append(m); + } + } + return 0; +} + +static int +lua_nodelib_last_node(lua_State *L) { + halfword m; + m = pop_tail(); + lua_pushnumber(L,m); + lua_nodelib_push(L); + return 1; +} + + + +/* build a hbox */ + +static int +lua_nodelib_hpack(lua_State *L) { + halfword n, p; + char *s; + integer w = 0; + int m = 1; + n = *(check_isnode(L,1)); + if (lua_gettop(L)>1) { + w = lua_tointeger(L,2); + if (lua_gettop(L)>2 && lua_type(L,3)==LUA_TSTRING) { + s = (char *)lua_tostring(L,3); + if (strcmp(s,"additional")==0) { + m = 1; + } else { + m = lua_tonumber(L,3); + } + } + } + p = hpack(n,w,m); + lua_nodelib_push_fast(L,p); + return 1; +} + +/* This function is similar to |get_node_type_id|, for field + identifiers. It has to do some more work, because not all + identifiers are valid for all types of nodes. +*/ + +/* this inlining is an optimisation trick. it would be even faster to + compare string pointers on the lua stack, but that would require a + lot of code reworking that I don't have time for right now. +*/ + + +make_luaS_index(id); +make_luaS_index(next); +make_luaS_index(char); +make_luaS_index(font); +make_luaS_index(attr); +make_luaS_index(prev); +make_luaS_index(lang); +make_luaS_index(subtype); +make_luaS_index(left); +make_luaS_index(right); +make_luaS_index(uchyph); +make_luaS_index(components); +make_luaS_index(xoffset); +make_luaS_index(yoffset); + + +void initialize_luaS_indexes(lua_State *L) { + init_luaS_index(id); + init_luaS_index(next); + init_luaS_index(char); + init_luaS_index(font); + init_luaS_index(attr); + init_luaS_index(prev); + init_luaS_index(lang); + init_luaS_index(subtype); + init_luaS_index(left); + init_luaS_index(right); + init_luaS_index(uchyph); + init_luaS_index(components); + init_luaS_index(xoffset); + init_luaS_index(yoffset); +} + +static int +get_node_field_id (lua_State *L, int n, int node ) { + register int t = type(node); + register char *s = (char *)lua_tostring(L,n); + if (luaS_ptr_eq(s,next)) { return 0; } + else if (luaS_ptr_eq(s,id)) { return 1; } + else if (luaS_ptr_eq(s,attr) && + nodetype_has_attributes(t)) { return 3 ; } + else if (t==glyph_node) { + if (luaS_ptr_eq(s,subtype)) { return 2; } + else if (luaS_ptr_eq(s,font)) { return 5; } + else if (luaS_ptr_eq(s,char)) { return 4; } + else if (luaS_ptr_eq(s,prev)) { return -1; } + else if (luaS_ptr_eq(s,lang)) { return 6; } + else if (luaS_ptr_eq(s,left)) { return 7; } + else if (luaS_ptr_eq(s,right)) { return 8; } + else if (luaS_ptr_eq(s,uchyph)) { return 9; } + else if (luaS_ptr_eq(s,components)) { return 10; } + else if (luaS_ptr_eq(s,xoffset)) { return 11; } + else if (luaS_ptr_eq(s,yoffset)) { return 12; } + } + else if (luaS_ptr_eq(s,prev)) { return -1; } + else if (luaS_ptr_eq(s,subtype)) { return 2; } + else { + int j; + char **fields = node_data[t].fields; + if (t==whatsit_node) + fields = whatsit_node_data[subtype(node)].fields; + for (j=0;fields[j]!=NULL;j++) { + if (strcmp(s,fields[j])==0) { + return j+3; + } + } + } + return -2; +} + + +static int +get_valid_node_field_id (lua_State *L, int n, int node ) { + int i = get_node_field_id(L,n,node); + if (i==-2) { + char *s = (char *)lua_tostring(L,n); + lua_pushfstring(L, "Invalid field id %s for node type %s (%d)" , s, node_data[type(node)].name,subtype(node)); + lua_error(L); + } + return i; +} + +static int +lua_nodelib_has_field (lua_State *L) { + int i= -2; + if (!lua_isnil(L,1)) { + i = get_node_field_id(L,2,*(check_isnode(L,1))); + } + lua_pushboolean(L,(i!=-2)); + return 1; +} + + +/* fetch the list of valid node types */ + +static int +do_lua_nodelib_types (lua_State *L, node_info *data) { + int i; + lua_newtable(L); + for (i=0;data[i].id!=-1;i++) { + lua_pushstring(L,data[i].name); + lua_rawseti(L,-2,data[i].id); + } + return 1; +} + +static int +lua_nodelib_types (lua_State *L) { + return do_lua_nodelib_types (L, node_data); +} + +static int +lua_nodelib_whatsits (lua_State *L) { + return do_lua_nodelib_types (L, whatsit_node_data); +} + + +/* fetch the list of valid fields */ + +static int +lua_nodelib_fields (lua_State *L) { + int i = -1; + char ** fields; + int t = get_valid_node_type_id(L,1); + if (t==whatsit_node ) { + t = get_valid_node_subtype_id(L,2); + fields = whatsit_node_data[t].fields; + } else { + fields = node_data[t].fields; + } + lua_checkstack(L,2); + lua_newtable(L); + lua_pushstring(L,"next"); + lua_rawseti(L,-2,0); + lua_pushstring(L,"id"); + lua_rawseti(L,-2,1); + lua_pushstring(L,"subtype"); + lua_rawseti(L,-2,2); + if (fields!=NULL) { + lua_pushstring(L,"prev"); + lua_rawseti(L,-2,-1); + for (i=0;fields[i]!=NULL;i++) { + lua_pushstring(L,fields[i]); + lua_rawseti(L,-2,(i+3)); + } + } + return 1; +} + +/* find the end of a list */ + +static int +lua_nodelib_tail (lua_State *L) { + halfword *n; + halfword t; + if (lua_isnil(L,1)) + return 1; /* the nil itself */ + n = check_isnode(L,1); + t=*n; + if (t==null) + return 1; /* the old userdata */ + alink(t) = null; + while (vlink(t)!=null) { + alink(vlink(t)) = t; + t = vlink(t); + } + lua_nodelib_push_fast(L,t); + return 1; +} + +/* a few utility functions for attribute stuff */ + +static int +lua_nodelib_has_attribute (lua_State *L) { + halfword *n; + int i, val ; + if (lua_isnil(L,1)) + return 1; /* the nil itself */ + n = check_isnode(L,1); + i = lua_tointeger(L,2); + val = luaL_optinteger(L,3,-1); + if((val = has_attribute(*n,i,val))>=0) { + lua_pushnumber(L,val); + } else { + lua_pushnil(L); + } + return 1; +} + +static int +lua_nodelib_set_attribute (lua_State *L) { + halfword *n; + int i, val; + if (lua_gettop(L)==3) { + i = lua_tointeger(L,2); + val = lua_tointeger(L,3); + n = check_isnode(L,1); + if (val<0) { + (void)unset_attribute(*n,i,val); + } else { + set_attribute(*n,i,val); + } + } else { + lua_pushstring(L,"incorrect number of arguments"); + lua_error(L); + } + return 0; +} + + +static int +lua_nodelib_unset_attribute (lua_State *L) { + halfword *n; + int i, val, ret; + if (lua_gettop(L)<=3) { + i = luaL_checknumber(L,2); + val = luaL_optnumber(L,3,-1); + n = check_isnode(L,1); + ret = unset_attribute(*n,i,val); + if(ret>=0) { + lua_pushnumber(L,ret); + } else { + lua_pushnil(L); + } + return 1; + } else { + lua_pushstring(L,"incorrect number of arguments"); + return lua_error(L); + } +} + + +/* iteration */ + +static int nodelib_aux_nil (lua_State *L) { + lua_pushnil(L); + return 1; +} + +static int +nodelib_aux_next_filtered (lua_State *L) { + register halfword t; /* traverser */ + register int i = lua_tointeger(L,lua_upvalueindex(1)); + if (lua_isnil(L,2)) { /* first call */ + t = *check_isnode(L,1); + } else { + t = *check_isnode(L,2); + t = vlink(t); + } + while (t!=null && type(t)!=i) { t = vlink(t); } + if (t==null) { + lua_pushnil(L); + } else { + lua_nodelib_push_fast(L,t); + } + return 1; +} + + +static int +lua_nodelib_traverse_filtered (lua_State *L) { + halfword n; + if (lua_isnil(L,2)) { + lua_pushcclosure(L, nodelib_aux_nil, 0); + return 1; + } + n = *(check_isnode(L,2)); + lua_pop(L,1); /* the node, integer remains */ + lua_pushcclosure(L, nodelib_aux_next_filtered, 1); + lua_nodelib_push_fast(L,n); + lua_pushnil(L); + return 3; +} + +static int +nodelib_aux_next (lua_State *L) { + register halfword t; /* traverser */ + if (lua_isnil(L,2)) { /* first call */ + t = *check_isnode(L,1); + } else { + t = *check_isnode(L,2); + t = vlink(t); + } + if (t==null) { + lua_pushnil(L); + } else { + lua_nodelib_push_fast(L,t); + } + return 1; +} + +static int +lua_nodelib_traverse (lua_State *L) { + halfword n; + if (lua_isnil(L,1)) { + lua_pushcclosure(L, nodelib_aux_nil, 0); + return 1; + } + n = *(check_isnode(L,1)); + lua_pushcclosure(L, nodelib_aux_next, 0); + lua_nodelib_push_fast(L,n); + lua_pushnil(L); + return 3; +; +} + + + +static int +do_lua_nodelib_count (lua_State *L, halfword match, int i, halfword first) { + int count = 0; + int t = first; + while (t!=match) { + if (i<0 || type(t)==i) { count++; } + t = vlink(t); + } + lua_pushnumber(L,count); + return 1; +} + +static int lua_nodelib_length (lua_State *L) { + halfword n; + halfword m = null; + if (lua_isnil(L,1)) { + lua_pushnumber(L,0); + return 1; + } + n = *(check_isnode(L,1)); + if (lua_gettop(L)==2) { + m = *(check_isnode(L,2)); + } + return do_lua_nodelib_count(L,m,-1,n); +} + + +static int lua_nodelib_count (lua_State *L) { + halfword n; + halfword m = null; + int i = -1; + i = lua_tointeger(L,1); + if (lua_isnil(L,2)) { + lua_pushnumber(L,0); + return 1; + } + n = *(check_isnode(L,2)); + if (lua_gettop(L)==3) + m = *(check_isnode(L,3)); + return do_lua_nodelib_count(L,m,i,n); +} + +/* fetching a field from a node */ + +#define nodelib_pushlist(L,n) { lua_pushnumber(L,n); lua_nodelib_push(L); } +#define nodelib_pushattr(L,n) { lua_pushnumber(L,n); lua_nodelib_push(L); } +#define nodelib_pushspec(L,n) { lua_pushnumber(L,n); lua_nodelib_push(L); } +#define nodelib_pushaction(L,n) { lua_pushnumber(L,n); lua_nodelib_push(L); } +#define nodelib_pushstring(L,n) { lua_pushstring(L,makecstring(n)); } + +static void +lua_nodelib_getfield_whatsit (lua_State *L, int n, int field) { + if (field==2) { + lua_pushnumber(L,subtype(n)); + } else { + switch (subtype(n)) { + case open_node: + switch (field) { + case 4: lua_pushnumber(L,write_stream(n)); break; + case 5: nodelib_pushstring(L,open_name(n)); break; + case 6: nodelib_pushstring(L,open_area(n)); break; + case 7: nodelib_pushstring(L,open_ext(n)); break; + default: lua_pushnil(L); + } + break; + case write_node: + switch (field) { + case 4: lua_pushnumber(L,write_stream(n)); break; + case 5: tokenlist_to_lua(L,write_tokens(n)); break; + default: lua_pushnil(L); + } + break; + case close_node: + switch (field) { + case 4: lua_pushnumber(L,write_stream(n)); break; + default: lua_pushnil(L); + } + break; + case special_node: + switch (field) { + case 4: tokenlist_to_luastring(L,write_tokens(n)); break; + default: lua_pushnil(L); + } + break; + case local_par_node: + switch (field) { + case 4: lua_pushnumber(L,local_pen_inter(n)); break; + case 5: lua_pushnumber(L,local_pen_broken(n)); break; + case 6: lua_pushnumber(L,local_par_dir(n)); break; + case 7: nodelib_pushlist(L,local_box_left(n)); break; + case 8: lua_pushnumber(L,local_box_left_width(n)); break; + case 9: nodelib_pushlist(L,local_box_right(n)); break; + case 10: lua_pushnumber(L,local_box_right_width(n)); break; + default: lua_pushnil(L); + } + break; + case dir_node: + switch (field) { + case 4: lua_pushnumber(L,dir_dir(n)); break; + case 5: lua_pushnumber(L,dir_level(n)); break; + case 6: lua_pushnumber(L,dir_dvi_ptr(n)); break; + case 7: lua_pushnumber(L,dir_dvi_h(n)); break; + default: lua_pushnil(L); + } + break; + case pdf_literal_node: + switch (field) { + case 4: lua_pushnumber(L,pdf_literal_mode(n)); break; + case 5: tokenlist_to_luastring(L,pdf_literal_data(n)); break; + default: lua_pushnil(L); + } + break; + case pdf_refobj_node: + switch (field) { + case 4: lua_pushnumber(L,pdf_obj_objnum(n)); break; + default: lua_pushnil(L); + } + break; + case pdf_refxform_node: + switch (field) { + case 4: lua_pushnumber(L,pdf_width(n)); break; + case 5: lua_pushnumber(L,pdf_height(n)); break; + case 6: lua_pushnumber(L,pdf_depth(n)); break; + case 7: lua_pushnumber(L,pdf_xform_objnum(n)); break; + default: lua_pushnil(L); + } + break; + case pdf_refximage_node: + switch (field) { + case 4: lua_pushnumber(L,pdf_width(n)); break; + case 5: lua_pushnumber(L,pdf_height(n)); break; + case 6: lua_pushnumber(L,pdf_depth(n)); break; + case 7: lua_pushnumber(L,pdf_ximage_objnum(n)); break; + default: lua_pushnil(L); + } + break; + case pdf_annot_node: + switch (field) { + case 4: lua_pushnumber(L,pdf_width(n)); break; + case 5: lua_pushnumber(L,pdf_height(n)); break; + case 6: lua_pushnumber(L,pdf_depth(n)); break; + case 7: lua_pushnumber(L,pdf_annot_objnum(n)); break; + case 8: tokenlist_to_luastring(L,pdf_annot_data(n)); break; + default: lua_pushnil(L); + } + break; + case pdf_start_link_node: + switch (field) { + case 4: lua_pushnumber(L,pdf_width(n)); break; + case 5: lua_pushnumber(L,pdf_height(n)); break; + case 6: lua_pushnumber(L,pdf_depth(n)); break; + case 7: lua_pushnumber(L,pdf_link_objnum(n)); break; + case 8: tokenlist_to_luastring(L,pdf_link_attr(n)); break; + case 9: nodelib_pushaction(L,pdf_link_action(n)); break; + default: lua_pushnil(L); + } + break; + case pdf_dest_node: + switch (field) { + case 4: lua_pushnumber(L,pdf_width(n)); break; + case 5: lua_pushnumber(L,pdf_height(n)); break; + case 6: lua_pushnumber(L,pdf_depth(n)); break; + case 7: lua_pushnumber(L,pdf_dest_named_id(n)); break; + case 8: if (pdf_dest_named_id(n) == 1) + tokenlist_to_luastring(L,pdf_dest_id(n)); + else + lua_pushnumber(L,pdf_dest_id(n)); break; + case 9: lua_pushnumber(L,pdf_dest_type(n)); break; + case 10: lua_pushnumber(L,pdf_dest_xyz_zoom(n)); break; + case 11: lua_pushnumber(L,pdf_dest_objnum(n)); break; + default: lua_pushnil(L); + } + break; + case pdf_thread_node: + case pdf_start_thread_node: + switch (field) { + case 4: lua_pushnumber(L,pdf_width(n)); break; + case 5: lua_pushnumber(L,pdf_height(n)); break; + case 6: lua_pushnumber(L,pdf_depth(n)); break; + case 7: lua_pushnumber(L,pdf_thread_named_id(n)); break; + case 8: if (pdf_thread_named_id(n) == 1) + tokenlist_to_luastring(L,pdf_thread_id(n)); + else + lua_pushnumber(L,pdf_thread_id(n)); break; + case 9: tokenlist_to_luastring(L,pdf_thread_attr(n)); break; + default: lua_pushnil(L); + } + break; + case late_lua_node: + switch (field) { + case 4: lua_pushnumber(L,late_lua_reg(n)); break; + case 5: tokenlist_to_luastring(L,late_lua_data(n)); break; + default: lua_pushnil(L); + } + break; + case close_lua_node: + switch (field) { + case 4: lua_pushnumber(L,late_lua_reg(n)); break; + default: lua_pushnil(L); + } + break; + case pdf_colorstack_node: + switch (field) { + case 4: lua_pushnumber(L,pdf_colorstack_stack(n)); break; + case 5: lua_pushnumber(L,pdf_colorstack_cmd(n)); break; + case 6: tokenlist_to_luastring(L,pdf_colorstack_data(n)); break; + default: lua_pushnil(L); + } + break; + case pdf_setmatrix_node: + switch (field) { + case 4: tokenlist_to_luastring(L,pdf_setmatrix_data(n)); break; + default: lua_pushnil(L); + } + break; + case user_defined_node: + switch (field) { + case 4: lua_pushnumber(L,user_node_id(n)); break; + case 5: lua_pushnumber(L,user_node_type(n)); break; + case 6: + switch (user_node_type(n)) { + case 'a': nodelib_pushlist(L,user_node_value(n)); break; + case 'd': lua_pushnumber(L,user_node_value(n)); break; + case 'n': nodelib_pushlist(L,user_node_value(n)); break; + case 's': nodelib_pushstring(L,user_node_value(n)); break; + case 't': tokenlist_to_lua(L,user_node_value(n)); break; + default: lua_pushnumber(L,user_node_value(n)); break; + } break; + default: lua_pushnil(L); + } + break; + default: + lua_pushnil(L); + break; + } + } +} + + +static int +lua_nodelib_getfield (lua_State *L) { + halfword *n_ptr, n; + int field; + if (lua_isnil(L,1)) + return 1; /* a nil */ + n_ptr = check_isnode(L,1); + n = *n_ptr; + field = get_valid_node_field_id(L,2, n); + + if (field<-1) + return 0; + if (field==0) { + lua_pushnumber(L,vlink(n)); + lua_nodelib_push(L); + } else if (field==1) { + lua_pushnumber(L,type(n)); + } else if (field==-1) { + lua_pushnumber(L,alink(n)); + lua_nodelib_push(L); + } else if (field==3 && nodetype_has_attributes(type(n))) { + nodelib_pushattr(L,node_attr(n)); + } else { + switch (type(n)) { + case hlist_node: + case vlist_node: + switch (field) { + case 2: lua_pushnumber(L,subtype(n)); break; + case 4: lua_pushnumber(L,width(n)); break; + case 5: lua_pushnumber(L,depth(n)); break; + case 6: lua_pushnumber(L,height(n)); break; + case 7: lua_pushnumber(L,box_dir(n)); break; + case 8: lua_pushnumber(L,shift_amount(n)); break; + case 9: lua_pushnumber(L,glue_order(n)); break; + case 10: lua_pushnumber(L,glue_sign(n)); break; + case 11: lua_pushnumber(L,(double)glue_set(n)); break; + case 12: nodelib_pushlist(L,list_ptr(n)); break; + default: lua_pushnil(L); + } + break; + case unset_node: + switch (field) { + case 2: lua_pushnumber(L,0); break; + case 4: lua_pushnumber(L,width(n)); break; + case 5: lua_pushnumber(L,depth(n)); break; + case 6: lua_pushnumber(L,height(n)); break; + case 7: lua_pushnumber(L,box_dir(n)); break; + case 8: lua_pushnumber(L,glue_shrink(n)); break; + case 9: lua_pushnumber(L,glue_order(n)); break; + case 10: lua_pushnumber(L,glue_sign(n)); break; + case 11: lua_pushnumber(L,glue_stretch(n)); break; + case 12: lua_pushnumber(L,span_count(n)); break; + case 13: nodelib_pushlist(L,list_ptr(n)); break; + default: lua_pushnil(L); + } + break; + case rule_node: + switch (field) { + case 2: lua_pushnumber(L,0); break; + case 4: lua_pushnumber(L,width(n)); break; + case 5: lua_pushnumber(L,depth(n)); break; + case 6: lua_pushnumber(L,height(n)); break; + case 7: lua_pushnumber(L,rule_dir(n)); break; + default: lua_pushnil(L); + } + break; + case ins_node: + switch (field) { + case 2: lua_pushnumber(L,subtype(n)); break; + case 4: lua_pushnumber(L,float_cost(n)); break; + case 5: lua_pushnumber(L,depth(n)); break; + case 6: lua_pushnumber(L,height(n)); break; + case 7: nodelib_pushspec(L,split_top_ptr(n)); break; + case 8: nodelib_pushlist(L,ins_ptr(n)); break; + default: lua_pushnil(L); + } + break; + case mark_node: + switch (field) { + case 2: lua_pushnumber(L,subtype(n)); break; + case 4: lua_pushnumber(L,mark_class(n)); break; + case 5: tokenlist_to_lua(L,mark_ptr(n)); break; + default: lua_pushnil(L); + } + break; + case adjust_node: + switch (field) { + case 2: lua_pushnumber(L,subtype(n)); break; + case 4: nodelib_pushlist(L,adjust_ptr(n)); break; + default: lua_pushnil(L); + } + break; + case disc_node: + switch (field) { + case 2: lua_pushnumber(L,subtype(n)); break; + case 4: nodelib_pushlist(L,vlink(pre_break(n))); break; + case 5: nodelib_pushlist(L,vlink(post_break(n))); break; + case 6: nodelib_pushlist(L,vlink(no_break(n))); break; + default: lua_pushnil(L); + } + break; + case math_node: + switch (field) { + case 2: lua_pushnumber(L,subtype(n)); break; + case 4: lua_pushnumber(L,surround(n)); break; + default: lua_pushnil(L); + } + break; + case glue_node: + switch (field) { + case 2: lua_pushnumber(L,subtype(n)); break; + case 4: nodelib_pushspec(L,glue_ptr(n)); break; + case 5: nodelib_pushlist(L,leader_ptr(n)); break; + default: lua_pushnil(L); + } + break; + case glue_spec_node: + switch (field) { + case 2: lua_pushnumber(L,0); break; + case 3: lua_pushnumber(L,width(n)); break; + case 4: lua_pushnumber(L,stretch(n)); break; + case 5: lua_pushnumber(L,shrink(n)); break; + case 6: lua_pushnumber(L,stretch_order(n)); break; + case 7: lua_pushnumber(L,shrink_order(n)); break; + case 8: lua_pushnumber(L,glue_ref_count(n)); break; + default: lua_pushnil(L); + } + break; + case kern_node: + switch (field) { + case 2: lua_pushnumber(L,subtype(n)); break; + case 4: lua_pushnumber(L,width(n)); break; + default: lua_pushnil(L); + } + break; + case penalty_node: + switch (field) { + case 2: lua_pushnumber(L,0); break; + case 4: lua_pushnumber(L,penalty(n)); break; + default: lua_pushnil(L); + } + break; + case glyph_node: + switch (field) { + case 2: lua_pushnumber(L,subtype(n)); break; + case 4: lua_pushnumber(L,character(n)); break; + case 5: lua_pushnumber(L,font(n)); break; + case 6: lua_pushnumber(L,char_lang(n)); break; + case 7: lua_pushnumber(L,char_lhmin(n)); break; + case 8: lua_pushnumber(L,char_rhmin(n)); break; + case 9: lua_pushnumber(L,char_uchyph(n)); break; + case 10: nodelib_pushlist(L,lig_ptr(n)); break; + case 11: lua_pushnumber(L,x_displace(n)); break; + case 12: lua_pushnumber(L,y_displace(n)); break; + default: lua_pushnil(L); + } + break; + case inserting_node: + switch (field) { + case 2: lua_pushnumber(L,subtype(n)); break; + case 3: nodelib_pushlist(L,last_ins_ptr(n)); break; + case 4: nodelib_pushlist(L,best_ins_ptr(n)); break; + default: lua_pushnil(L); + } + break; + case split_up_node: + switch (field) { + case 2: lua_pushnumber(L,subtype(n)); break; + case 3: nodelib_pushlist(L,last_ins_ptr(n)); break; + case 4: nodelib_pushlist(L,best_ins_ptr(n)); break; + case 5: nodelib_pushlist(L,broken_ptr(n)); break; + case 6: nodelib_pushlist(L,broken_ins(n)); break; + default: lua_pushnil(L); + } + break; + case margin_kern_node : + switch (field) { + case 2: lua_pushnumber(L,subtype(n)); break; + case 3: lua_pushnumber(L,width(n)); break; + case 4: nodelib_pushlist(L,margin_char(n)); break; + default: lua_pushnil(L); + } + break; + case action_node: + switch (field) { + case 2: lua_pushnil(L); /* dummy subtype */ break; + case 3: lua_pushnumber(L,pdf_action_type(n)); break; + case 4: lua_pushnumber(L,pdf_action_named_id(n)); break; + case 5: if (pdf_action_named_id(n)==1) { + tokenlist_to_luastring(L,pdf_action_id(n)); + } else { + lua_pushnumber(L,pdf_action_id(n)); + } break; + case 6: tokenlist_to_luastring(L,pdf_action_file(n)); break; + case 7: lua_pushnumber(L,pdf_action_new_window(n)); break; + case 8: tokenlist_to_luastring(L,pdf_action_tokens(n));break; + case 9: lua_pushnumber(L,pdf_action_refcount(n)); break; + default: lua_pushnil(L); + } + break; + case attribute_list_node : + switch (field) { + case 2: lua_pushnumber(L,0); break; + default: lua_pushnil(L); + } + break; + case attribute_node : + switch (field) { + case 2: lua_pushnumber(L,0); break; + case 3: lua_pushnumber(L,attribute_id(n)); break; + case 4: lua_pushnumber(L,attribute_value(n)); break; + default: lua_pushnil(L); + } + break; + case whatsit_node: + lua_nodelib_getfield_whatsit(L,n,field); + break; + default: + lua_pushnil(L); + break; + } + } + return 1; +} + + +static int nodelib_getlist(lua_State *L, int n) { + halfword *m; + if (lua_isuserdata(L,n)) { + m = check_isnode(L,n); + return *m; + } else { + return null ; + } +} + +#define nodelib_getspec nodelib_getlist +#define nodelib_getaction nodelib_getlist + + +static str_number +nodelib_getstring(lua_State *L, int a) { + size_t k; + char *s=(char *)lua_tolstring(L,a, &k); + return maketexlstring(s,k); +} + +#define nodelib_gettoks(L,a) tokenlist_from_lua(L) + +static void nodelib_setattr (lua_State *L, int stackindex, halfword n) { + halfword p; + p = nodelib_getlist(L,stackindex); + if (node_attr(n) != p) { + if (node_attr(n)!=null) + delete_attribute_ref(node_attr(n)); + node_attr(n) = p; + attr_list_ref(p)++; + } +} + +static int nodelib_cantset (lua_State *L, int field, int n) { + lua_pushfstring(L,"You cannot set field %d in a node of type %s", + field, node_data[type(n)].name); + lua_error(L); + return 0; +} + +static int +lua_nodelib_setfield_whatsit(lua_State *L, int n, int field) { + switch (subtype(n)) { + case open_node: + switch (field) { + case 4: write_stream(n) = lua_tointeger(L,3); break; + case 5: open_name(n) = nodelib_getstring(L,3); break; + case 6: open_area(n) = nodelib_getstring(L,3); break; + case 7: open_ext(n) = nodelib_getstring(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case write_node: + switch (field) { + case 4: write_stream(n) = lua_tointeger(L,3); break; + case 5: write_tokens(n) = nodelib_gettoks(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case close_node: + switch (field) { + case 4: write_stream(n) = lua_tointeger(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case special_node: + switch (field) { + case 4: write_tokens(n) = nodelib_gettoks(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case local_par_node: + switch (field) { + case 4: local_pen_inter(n) = lua_tointeger(L,3); break; + case 5: local_pen_broken(n) = lua_tointeger(L,3); break; + case 6: local_par_dir(n) = lua_tointeger(L,3); break; + case 7: local_box_left(n) = nodelib_getlist(L,3); break; + case 8: local_box_left_width(n) = lua_tointeger(L,3); break; + case 9: local_box_right(n) = nodelib_getlist(L,3); break; + case 10: local_box_right_width(n) = lua_tointeger(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case dir_node: + switch (field) { + case 4: dir_dir(n) = lua_tointeger(L,3); break; + case 5: dir_level(n) = lua_tointeger(L,3); break; + case 6: dir_dvi_ptr(n) = lua_tointeger(L,3); break; + case 7: dir_dvi_h(n) = lua_tointeger(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case pdf_literal_node: + switch (field) { + case 4: pdf_literal_mode(n) = lua_tointeger(L,3); break; + case 5: pdf_literal_data(n) = nodelib_gettoks(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case pdf_refobj_node: + switch (field) { + case 4: pdf_obj_objnum(n) = lua_tointeger(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case pdf_refxform_node: + switch (field) { + case 4: pdf_width(n) = lua_tointeger(L,3); break; + case 5: pdf_height(n) = lua_tointeger(L,3); break; + case 6: pdf_depth(n) = lua_tointeger(L,3); break; + case 7: pdf_xform_objnum(n) = lua_tointeger(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case pdf_refximage_node: + switch (field) { + case 4: pdf_width(n) = lua_tointeger(L,3); break; + case 5: pdf_height(n) = lua_tointeger(L,3); break; + case 6: pdf_depth(n) = lua_tointeger(L,3); break; + case 7: pdf_ximage_objnum(n) = lua_tointeger(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case pdf_annot_node: + switch (field) { + case 4: pdf_width(n) = lua_tointeger(L,3); break; + case 5: pdf_height(n) = lua_tointeger(L,3); break; + case 6: pdf_depth(n) = lua_tointeger(L,3); break; + case 7: pdf_annot_objnum(n) = lua_tointeger(L,3); break; + case 8: pdf_annot_data(n) = nodelib_getstring(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case pdf_start_link_node: + switch (field) { + case 4: pdf_width(n) = lua_tointeger(L,3); break; + case 5: pdf_height(n) = lua_tointeger(L,3); break; + case 6: pdf_depth(n) = lua_tointeger(L,3); break; + case 7: pdf_link_objnum(n) = lua_tointeger(L,3); break; + case 8: pdf_link_attr(n) = nodelib_getstring(L,3); break; + case 9: pdf_link_action(n) = nodelib_getaction(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case pdf_end_link_node: + switch (field) { + default: return nodelib_cantset(L,field,n); + } + break; + case pdf_dest_node: + switch (field) { + case 4: pdf_width(n) = lua_tointeger(L,3); break; + case 5: pdf_height(n) = lua_tointeger(L,3); break; + case 6: pdf_depth(n) = lua_tointeger(L,3); break; + case 7: pdf_dest_named_id(n) = lua_tointeger(L,3); break; + case 8: if (pdf_dest_named_id(n)==1) + pdf_dest_id(n) = nodelib_gettoks(L,3); + else + pdf_dest_id(n) = lua_tointeger(L,3); break; + case 9: pdf_dest_type(n) = lua_tointeger(L,3); break; + case 10: pdf_dest_xyz_zoom(n) = lua_tointeger(L,3); break; + case 11: pdf_dest_objnum(n) = lua_tointeger(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case pdf_thread_node: + case pdf_start_thread_node: + switch (field) { + case 4: pdf_width(n) = lua_tointeger(L,3); break; + case 5: pdf_height(n) = lua_tointeger(L,3); break; + case 6: pdf_depth(n) = lua_tointeger(L,3); break; + case 7: pdf_thread_named_id(n) = lua_tointeger(L,3); break; + case 8: if (pdf_thread_named_id(n)==1) + pdf_thread_id(n) = nodelib_gettoks(L,3); + else + pdf_thread_id(n) = lua_tointeger(L,3); break; + case 9: pdf_thread_attr(n) = nodelib_gettoks(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case pdf_end_thread_node: + case pdf_save_pos_node: + return nodelib_cantset(L,field,n); + break; + case late_lua_node: + switch (field) { + case 4: late_lua_reg(n) = lua_tointeger(L,3); break; + case 5: late_lua_data(n) = nodelib_gettoks(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case close_lua_node: + switch (field) { + case 4: late_lua_reg(n) = lua_tointeger(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case pdf_colorstack_node: + switch (field) { + case 4: pdf_colorstack_stack(n) = lua_tointeger(L,3); break; + case 5: pdf_colorstack_cmd(n) = lua_tointeger(L,3); break; + case 6: pdf_colorstack_data(n) = nodelib_gettoks(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case pdf_setmatrix_node: + switch (field) { + case 4: pdf_setmatrix_data(n) = nodelib_gettoks(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case pdf_save_node: + case pdf_restore_node: + case cancel_boundary_node: + return nodelib_cantset(L,field,n); + break; + case user_defined_node: + switch (field) { + case 4: user_node_id(n) = lua_tointeger(L,3); break; + case 5: user_node_type(n) = lua_tointeger(L,3); break; + case 6: + switch(user_node_type(n)) { + case 'a': user_node_value(n) = nodelib_getlist(L,3); break; + case 'd': user_node_value(n) = lua_tointeger(L,3); break; + case 'n': user_node_value(n) = nodelib_getlist(L,3); break; + case 's': user_node_value(n) = nodelib_getstring(L,3); break; + case 't': user_node_value(n) = nodelib_gettoks(L,3); break; + default: user_node_value(n) = lua_tointeger(L,3); break; + } break; + default: return nodelib_cantset(L,field,n); + } + break; + default: + /* do nothing */ + break; + } + return 0; +} + +static int +lua_nodelib_setfield (lua_State *L) { + register halfword n; + register int field; + n = *check_isnode(L,1); + field = get_valid_node_field_id(L,2,n); + if (field<-1) + return 0; + if (field==0) { + vlink(n) = nodelib_getlist(L,3); + } else if (field==-1) { + alink(n) = nodelib_getlist(L,3); + } else if (field==3 && nodetype_has_attributes(type(n))) { + nodelib_setattr(L,3,n); + } else if (type(n)==glyph_node) { + switch (field) { + case 2: subtype(n) = lua_tointeger(L,3); break; + case 4: character(n) = lua_tointeger(L,3); break; + case 5: font(n) = lua_tointeger(L,3); break; + case 6: set_char_lang(n,lua_tointeger(L,3)); break; + case 7: set_char_lhmin(n,lua_tointeger(L,3)); break; + case 8: set_char_rhmin(n,lua_tointeger(L,3)); break; + case 9: set_char_uchyph(n,lua_tointeger(L,3)); break; + case 10: lig_ptr(n) = nodelib_getlist(L,3); break; + case 11: x_displace(n) = lua_tointeger(L,3); break; + case 12: y_displace(n) = lua_tointeger(L,3); break; + default: return nodelib_cantset(L,field,n); + } + } else { + switch (type(n)) { + case hlist_node: + case vlist_node: + switch (field) { + case 2: subtype(n) = lua_tointeger(L,3); break; + case 4: width(n) = lua_tointeger(L,3); break; + case 5: depth(n) = lua_tointeger(L,3); break; + case 6: height(n) = lua_tointeger(L,3); break; + case 7: box_dir(n) = lua_tointeger(L,3); break; + case 8: shift_amount(n) = lua_tointeger(L,3); break; + case 9: glue_order(n) = lua_tointeger(L,3); break; + case 10: glue_sign(n) = lua_tointeger(L,3); break; + case 11: glue_set(n) = (double)lua_tonumber(L,3); break; + case 12: list_ptr(n) = nodelib_getlist(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case unset_node: + switch (field) { + case 2: /* dummy subtype */ break; + case 4: width(n) = lua_tointeger(L,3); break; + case 5: depth(n) = lua_tointeger(L,3); break; + case 6: height(n) = lua_tointeger(L,3); break; + case 7: box_dir(n) = lua_tointeger(L,3); break; + case 8: glue_shrink(n) = lua_tointeger(L,3); break; + case 9: glue_order(n) = lua_tointeger(L,3); break; + case 10: glue_sign(n) = lua_tointeger(L,3); break; + case 11: glue_stretch(n) = lua_tointeger(L,3); break; + case 12: span_count(n) = lua_tointeger(L,3); break; + case 13: list_ptr(n) = nodelib_getlist(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case rule_node: + switch (field) { + case 2: /* dummy subtype */ break; + case 4: width(n) = lua_tointeger(L,3); break; + case 5: depth(n) = lua_tointeger(L,3); break; + case 6: height(n) = lua_tointeger(L,3); break; + case 7: rule_dir(n) = lua_tointeger(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case ins_node: + switch (field) { + case 2: subtype(n) = lua_tointeger(L,3); break; + case 4: float_cost(n) = lua_tointeger(L,3); break; + case 5: depth(n) = lua_tointeger(L,3); break; + case 6: height(n) = lua_tointeger(L,3); break; + case 7: split_top_ptr(n) = nodelib_getspec(L,3); break; + case 8: ins_ptr(n) = nodelib_getlist(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case mark_node: + switch (field) { + case 2: subtype(n) = lua_tointeger(L,3); break; + case 4: mark_class(n) = lua_tointeger(L,3); break; + case 5: mark_ptr(n) = nodelib_gettoks(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case adjust_node: + switch (field) { + case 2: subtype(n) = lua_tointeger(L,3); break; + case 4: adjust_ptr(n) = nodelib_getlist(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case disc_node: + switch (field) { + case 2: subtype(n) = lua_tointeger(L,3); break; + case 4: set_disc_field(pre_break(n),nodelib_getlist(L,3)); break; + case 5: set_disc_field(post_break(n),nodelib_getlist(L,3)); break; + case 6: set_disc_field(no_break(n),nodelib_getlist(L,3)); break; + default: return nodelib_cantset(L,field,n); + } + break; + case math_node: + switch (field) { + case 2: subtype(n) = lua_tointeger(L,3); break; + case 4: surround(n) = lua_tointeger(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case glue_node: + switch (field) { + case 2: subtype(n) = lua_tointeger(L,3); break; + case 4: glue_ptr(n) = nodelib_getspec(L,3); break; + case 5: leader_ptr(n) = nodelib_getlist(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case glue_spec_node: + switch (field) { + case 2: /* dummy subtype */ break; + case 3: width(n) = lua_tointeger(L,3); break; + case 4: stretch(n) = lua_tointeger(L,3); break; + case 5: shrink(n) = lua_tointeger(L,3); break; + case 6: stretch_order(n) = lua_tointeger(L,3); break; + case 7: shrink_order(n) = lua_tointeger(L,3); break; + case 8: glue_ref_count(n) = lua_tointeger(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case kern_node: + switch (field) { + case 2: subtype(n) = lua_tointeger(L,3); break; + case 4: width(n) = lua_tointeger(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case penalty_node: + switch (field) { + case 2: /* dummy subtype */ break; + case 4: penalty(n) = lua_tointeger(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case action_node: + switch (field) { + case 2: /* dummy subtype */ break; + case 3: pdf_action_type(n) = lua_tointeger(L,3); break; + case 4: pdf_action_named_id(n) = lua_tointeger(L,3); break; + case 5: if (pdf_action_named_id(n)==1) { + pdf_action_id(n) = nodelib_gettoks(L,3); + } else { + pdf_action_id(n) = lua_tointeger(L,3); + } break; + case 6: pdf_action_file(n) = nodelib_gettoks(L,3); break; + case 7: pdf_action_new_window(n) = lua_tointeger(L,3); break; + case 8: pdf_action_tokens(n) = nodelib_gettoks(L,3); break; + case 9: pdf_action_refcount(n) = lua_tointeger(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case margin_kern_node: + switch (field) { + case 2: subtype(n) = lua_tointeger(L,3); break; + case 3: width(n) = lua_tointeger(L,3); break; + case 4: margin_char(n) = nodelib_getlist(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case inserting_node: + switch (field) { + case 2: subtype(n) = lua_tointeger(L,3); break; + case 3: last_ins_ptr(n) = nodelib_getlist(L,3); break; + case 4: best_ins_ptr(n) = nodelib_getlist(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case split_up_node: + switch (field) { + case 2: subtype(n) = lua_tointeger(L,3); break; + case 3: last_ins_ptr(n) = nodelib_getlist(L,3); break; + case 4: best_ins_ptr(n) = nodelib_getlist(L,3); break; + case 5: broken_ptr(n) = nodelib_getlist(L,3); break; + case 6: broken_ins(n) = nodelib_getlist(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case attribute_list_node: + switch (field) { + case 2: /* dummy subtype */ break; + default: return nodelib_cantset(L,field,n); + } + break; + case attribute_node: + switch (field) { + case 2: /* dummy subtype */ break; + case 3: attribute_id(n) = lua_tointeger(L,3); break; + case 4: attribute_value(n) = lua_tointeger(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case whatsit_node: + lua_nodelib_setfield_whatsit(L,n,field); + break; + default: + /* do nothing */ + break; + } + } + return 0; +} + +static int +lua_nodelib_print (lua_State *L) { + char *msg; + char a[7] = {' ',' ',' ', 'n', 'i', 'l', 0}; + char v[7] = {' ',' ',' ', 'n', 'i', 'l', 0}; + halfword *n; + n = check_isnode(L,1); + msg = xmalloc(256); + if (alink(*n)!=null) + snprintf(a,7,"%6d",(int)alink(*n)); + if (vlink(*n)!=null) + snprintf(v,7,"%6d",(int)vlink(*n)); + snprintf(msg,255," %s : %s %d>", a, (int)*n, v, node_data[type(*n)].name, subtype(*n)); + lua_pushstring(L,msg); + free(msg); + return 1; +} + + +static int +lua_nodelib_equal (lua_State *L) { + halfword n, m; + n = *(check_isnode(L,1)); + m = *(check_isnode(L,2)); + lua_pushboolean(L,(n==m)); + return 1; +} + +static int +font_tex_ligaturing (lua_State *L) { + /* on the stack are two nodes and a direction */ + halfword tmp_head; + halfword *h; + halfword t =null; + if (lua_gettop(L)<1) { + lua_pushnil(L); + lua_pushboolean(L,0); + return 2; + } + h = check_isnode(L,1); + if (lua_gettop(L)>1) { + t = *(check_isnode(L,2)); + } + tmp_head = new_node(nesting_node,1); + couple_nodes(tmp_head,*h); + tlink(tmp_head)=t; + t = handle_ligaturing(tmp_head,t); + lua_pushnumber(L,vlink(tmp_head)); + flush_node(tmp_head); + lua_nodelib_push(L); + lua_pushnumber(L,t); + lua_nodelib_push(L); + lua_pushboolean(L,1); + return 3; +} + +static int +font_tex_kerning (lua_State *L) { + /* on the stack are two nodes and a direction */ + + halfword tmp_head; + halfword *h; + halfword t =null; + if (lua_gettop(L)<1) { + lua_pushnil(L); + lua_pushboolean(L,0); + return 2; + } + h = check_isnode(L,1); + if (lua_gettop(L)>1) { + t = *(check_isnode(L,2)); + } + tmp_head = new_node(nesting_node,1); + couple_nodes(tmp_head,*h); + tlink(tmp_head)=t; + t = handle_kerning(tmp_head,t); + lua_pushnumber(L,vlink(tmp_head)); + flush_node(tmp_head); + lua_nodelib_push(L); + lua_pushnumber(L,t); + lua_nodelib_push(L); + lua_pushboolean(L,1); + return 3; +} + +static int +lua_nodelib_protect_glyphs (lua_State *L) { + int t = 0; + halfword head = *(check_isnode(L,1)); + while (head!=null) { + if (type(head)==glyph_node) { + register int s = subtype(head); + if (s<256) { + t = 1; + subtype(head) = ((s&0xFE) << 8); + } + } + head = vlink(head); + } + lua_pushboolean(L,t); + lua_pushvalue(L,1); + return 2; +} + +static int +lua_nodelib_unprotect_glyphs (lua_State *L) { + int t = 0; + halfword head = *(check_isnode(L,1)); + while (head!=null) { + if (type(head)==glyph_node) { + register int s = subtype(head); + if (s>=256) { + t = 1; + subtype(head) = (s >> 8); + } + } + head = vlink(head); + } + lua_pushboolean(L,t); + lua_pushvalue(L,1); + return 2; +} + + +static int +lua_nodelib_first_character (lua_State *L) { + /* on the stack are two nodes and a direction */ + halfword h, savetail = null, t = null; + if (lua_gettop(L)<1) { + lua_pushnil(L); + lua_pushboolean(L,0); + return 2; + } + h = *(check_isnode(L,1)); + if (lua_gettop(L)>1) { + t = *(check_isnode(L,2)); + savetail = vlink(t); + vlink(t) = null; + } + while (h!=null && !is_simple_character(h)) { + h = vlink(h); + } + if (savetail!=null) { vlink(t) = savetail; } + lua_pushnumber(L,h); + lua_nodelib_push(L); + lua_pushboolean(L,(h==null? 0 : 1)); + return 2; +} + + +/* this is too simplistic, but it helps Hans to get going */ + +halfword +do_ligature_n (halfword prev, halfword stop, halfword lig) { + vlink(lig) = vlink(stop); + vlink(stop) = null; + lig_ptr(lig) = vlink(prev); + vlink(prev) = lig; + return lig; +} + + + +/* node.do_ligature_n(node prev, node last, node lig) */ +static int +lua_nodelib_do_ligature_n (lua_State *L) { + halfword n, m, o, p, tmp_head; + n = *(check_isnode(L,1)); + m = *(check_isnode(L,2)); + o = *(check_isnode(L,3)); + if (alink(n)==null || vlink(alink(n))!=n) { + tmp_head = new_node(temp_node,0); + couple_nodes(tmp_head,n); + p = do_ligature_n(tmp_head,m,o); + flush_node(tmp_head); + } else { + p = do_ligature_n(alink(n),m,o); + } + lua_pushnumber(L,p); + lua_nodelib_push(L); + return 1; +} + +extern halfword list_node_mem_usage (void) ; + +static int +lua_nodelib_usedlist (lua_State *L) { + lua_pushnumber(L,list_node_mem_usage()); + lua_nodelib_push(L); + return 1; +} + + +static const struct luaL_reg nodelib_f [] = { + {"id", lua_nodelib_id}, + {"subtype", lua_nodelib_subtype}, + {"type", lua_nodelib_type}, + {"new", lua_nodelib_new}, + {"length", lua_nodelib_length}, + {"count", lua_nodelib_count}, + {"traverse", lua_nodelib_traverse}, + {"traverse_id", lua_nodelib_traverse_filtered}, + {"slide", lua_nodelib_tail}, + {"types", lua_nodelib_types}, + {"whatsits", lua_nodelib_whatsits}, + {"fields", lua_nodelib_fields}, + {"has_field", lua_nodelib_has_field}, + {"free", lua_nodelib_free}, + {"flush_list", lua_nodelib_flush_list}, + {"remove", lua_nodelib_remove}, + {"insert_before", lua_nodelib_insert_before}, + {"insert_after", lua_nodelib_insert_after}, + {"write", lua_nodelib_append}, + {"last_node", lua_nodelib_last_node}, + {"copy", lua_nodelib_copy}, + {"copy_list", lua_nodelib_copy_list}, + {"hpack", lua_nodelib_hpack}, + {"has_attribute", lua_nodelib_has_attribute}, + {"set_attribute", lua_nodelib_set_attribute}, + {"unset_attribute", lua_nodelib_unset_attribute}, + {"do_ligature_n", lua_nodelib_do_ligature_n}, + {"ligaturing", font_tex_ligaturing}, + {"kerning", font_tex_kerning}, + {"first_character", lua_nodelib_first_character}, + {"usedlist", lua_nodelib_usedlist}, + {"protect_glyphs", lua_nodelib_protect_glyphs}, + {"unprotect_glyphs", lua_nodelib_unprotect_glyphs}, + {NULL, NULL} /* sentinel */ +}; + +static const struct luaL_reg nodelib_m [] = { + {"__index", lua_nodelib_getfield}, + {"__newindex", lua_nodelib_setfield}, + {"__tostring", lua_nodelib_print}, + {"__eq", lua_nodelib_equal}, + {NULL, NULL} /* sentinel */ +}; + + + +int +luaopen_node (lua_State *L) +{ + luaL_newmetatable(L,NODE_METATABLE); + luaL_register(L, NULL, nodelib_m); + luaL_register(L, "node", nodelib_f); + init_luaS_index(luatex_node); + initialize_luaS_indexes(L); + return 1; +} + +void +nodelist_to_lua (lua_State *L, int n) { + lua_pushnumber(L,n); + lua_nodelib_push(L); +} + +int +nodelist_from_lua (lua_State *L) { + halfword *n; + if (lua_isnil(L,-1)) + return null; + n = check_isnode(L,-1); + return *n; +} + diff --git a/Build/source/texk/web2c/luatexdir/lua/loslibext.c b/Build/source/texk/web2c/luatexdir/lua/loslibext.c new file mode 100644 index 00000000000..003b031f627 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/loslibext.c @@ -0,0 +1,627 @@ +/* $Id: loslibext.c 1066 2008-02-23 10:52:51Z taco $ */ + +#include "luatex-api.h" +#include + +#include +#include +#include + +/* An attempt to figure out the basic platform, does not + care about niceties like version numbers yet, + and ignores platforms where luatex is unlikely to + successfully compile without major prorting effort + (amiga|mac|os2|vms) */ + +#if defined(_WIN32) || defined(WIN32) || defined(__NT__) +#define OS_PLATTYPE "windows" +#define OS_PLATNAME "windows" +#elif defined(__GO32__) || defined(__DJGPP__) || defined(__DOS__) +#define OS_PLATTYPE "msdos" +#define OS_PLATNAME "msdos" +#else /* assume everything else is unix-y */ +#define OS_PLATTYPE "unix" +/* this is just a first guess */ +#if defined(__BSD__) + #define OS_PLATNAME "bsd" +#elif defined(__SYSV__) + #define OS_PLATNAME "sysv" +#else + #define OS_PLATNAME "generic" +#endif +/* attempt to be more precise */ +#if defined(__LINUX__) || defined (__linux) + #undef OS_PLATNAME + #define OS_PLATNAME "linux" +#elif defined(__FREEBSD__) || defined(__FreeBSD) + #undef OS_PLATNAME + #define OS_PLATNAME "freebsd" +#elif defined(__OPENBSD__) || defined(__OpenBSD) + #undef OS_PLATNAME + #define OS_PLATNAME "openbsd" +#elif defined(__SOLARIS__) + #undef OS_PLATNAME + #define OS_PLATNAME "solaris" +#elif defined(__SUNOS__) || defined(__SUN__) || defined(sun) + #undef OS_PLATNAME + #define OS_PLATNAME "sunos" +#elif defined(HPUX) || defined(__hpux) + #undef OS_PLATNAME + #define OS_PLATNAME "hpux" +#elif defined(__sgi) + #undef OS_PLATNAME + #define OS_PLATNAME "irix" +#elif defined(__MACH__) && defined(__APPLE__) + #undef OS_PLATNAME + #define OS_PLATNAME "macosx" +#endif +#endif + + + + + +/* there could be more platforms that don't have these two, + * but win32 and sunos are for sure. + * gettimeofday() for win32 is using an alternative definition + */ + +#if (! defined(WIN32)) && (! defined(__SUNOS__)) +#include /* gettimeofday() */ +#include /* times() */ +#include +#endif + +/* set this to one for spawn instead of exec on windows */ + +#define DONT_REALLY_EXIT 1 + +#ifdef WIN32 +#include +#define spawn_command(a,b,c) _spawnvpe(_P_WAIT,(const char *)a,(const char* const*)b,(const char* const*)c) +#if DONT_REALLY_EXIT +#define exec_command(a,b,c) exit(spawn_command((a),(b),(c))) +#else +#define exec_command(a,b,c) _execvpe((const char *)a,(const char* const*)b,(const char* const*)c) +#endif +#else +#include +#define DEFAULT_PATH "/bin:/usr/bin:." + +static int +exec_command(const char *file, char *const *argv, char *const *envp) +{ + char path[PATH_MAX]; + const char *searchpath, *esp; + size_t prefixlen, filelen, totallen; + + if (strchr(file, '/')) /* Specific path */ + return execve(file, argv, envp); + + filelen = strlen(file); + + searchpath = getenv("PATH"); + if (!searchpath) + searchpath = DEFAULT_PATH; + + errno = ENOENT; /* Default errno, if execve() doesn't change it */ + + do { + esp = strchr(searchpath, ':'); + if (esp) + prefixlen = esp - searchpath; + else + prefixlen = strlen(searchpath); + + if (prefixlen == 0 || searchpath[prefixlen - 1] == '/') { + totallen = prefixlen + filelen; + if (totallen >= PATH_MAX) + continue; + memcpy(path, searchpath, prefixlen); + memcpy(path + prefixlen, file, filelen); + } else { + totallen = prefixlen + filelen + 1; + if (totallen >= PATH_MAX) + continue; + memcpy(path, searchpath, prefixlen); + path[prefixlen] = '/'; + memcpy(path + prefixlen + 1, file, filelen); + } + path[totallen] = '\0'; + + execve(path, argv, envp); + if (errno == E2BIG || errno == ENOEXEC || + errno == ENOMEM || errno == ETXTBSY) + break; /* Report this as an error, no more search */ + + searchpath = esp + 1; + } while (esp); + + return -1; +} + +/* + It is not possible to mimic |spawnve()| completely. The main problem is + that the |fork|--|waitpid| combination cannot really do identical error + reporting to the parent process, because it has to pass all the possible + error conditions as well as the actual process return status through a + single 8-bit value. + + The current implementation tries to give back meaningful results for |execve()| + errors in the child, for the cases that could also be returned by |spawnve()|, + and for |ETXTBSY|, because that can be triggered by our path searching routine. + + This implementation does not differentiate abnormal status conditions reported + by |waitpid()|, but will simply return a single error indication value. + + For all this, hyjacking a bunch of numbers in the range 1...255 is needed. + The chance of collisions is hopefully diminished by using a rather random + range in the 8-bit section. +*/ + +#define INVALID_RET_E2BIG 143 +#define INVALID_RET_ENOENT 144 +#define INVALID_RET_ENOEXEC 145 +#define INVALID_RET_ENOMEM 146 +#define INVALID_RET_ETXTBSY 147 +#define INVALID_RET_UNKNOWN 148 +#define INVALID_RET_INTR 149 + +static int +spawn_command(const char *file, char *const *argv, char *const *envp) +{ + pid_t pid, wait_pid; + int status; + pid = fork(); + if (pid<0) { + return -1; /* fork failed */ + } + if (pid>0) { /* parent */ + status = 0; + wait_pid = waitpid (pid, &status,0); + if (wait_pid == pid) { + if (WIFEXITED(status)) + return WEXITSTATUS(status); + else + return INVALID_RET_INTR; + } else { + return -1; /* some waitpid error */ + } + } else { + int f; + /* somewhat random upper limit. ignore errors on purpose */ + for (f = 0; f<256; f++) + (void)fsync(f); + + if (exec_command(file, argv, envp)) { + /* let's hope no-one uses these values */ + switch (errno) { + case E2BIG: exit(INVALID_RET_E2BIG); + case ETXTBSY: exit(INVALID_RET_ETXTBSY); + case ENOENT: exit(INVALID_RET_ENOENT); + case ENOEXEC: exit(INVALID_RET_ENOEXEC); + case ENOMEM: exit(INVALID_RET_ENOMEM); + default: exit(INVALID_RET_UNKNOWN); + } + return -1; + } + } +} + +#endif + +extern char **environ; + +static char ** +do_split_command(char *maincmd) +{ + char *piece, *start_piece; + char *cmd; + char **cmdline = NULL; + unsigned int i, j; + int ret = 0; + int in_string = 0; + int quoted = 0; + if (strlen(maincmd) == 0) + return NULL; + /* allocate the array of options first. it will probably be + be a little bit too big, but better too much than to little */ + j=2; + for (i = 0; i < strlen(maincmd); i++) { if (maincmd[i]==' ') j++; } + cmdline = malloc(sizeof(char *) * j); + for (i = 0; i < j; i++) { cmdline[i] = NULL; } + cmd = maincmd; + i = 0; + while (cmd[i] == ' ') i++; /* skip leading spaces */ + start_piece = malloc(strlen(cmd)+1); /* a buffer */ + piece = start_piece; + for (; i <= strlen(maincmd); i++) { + if (cmd[i]=='\\' && + (cmd[i+1] == '\\' || cmd[i+1] == '\'' || cmd[i+1] == '"')) { + quoted =1; + continue; + } + if (in_string && cmd[i] == in_string && !quoted) { + in_string = 0; + continue; + } + if ((cmd[i] == '"' || cmd[i] == '\'')&& !quoted) { + in_string = cmd[i]; + continue; + } + if ((in_string==0 && cmd[i] == ' ') || cmd[i]==0) { + *piece = 0; + cmdline[ret++] = xstrdup(start_piece); + piece = start_piece; + while (i < strlen(maincmd) && cmd[(i + 1)] == ' ') + i++; + continue; + } + *piece++ = cmd[i]; + quoted=0; + } + xfree(start_piece); + return cmdline; +} + +static char ** +do_flatten_command(lua_State *L, char **runcmd) { + unsigned int i, j ; + char *s; + char **cmdline = NULL; + *runcmd = NULL; + + for (j = 1;;j++) { + lua_rawgeti(L,-1,j); + if (lua_isnil(L,-1)) { + lua_pop(L,1); + break; + } + lua_pop(L,1); + } + if (j == 1) + return NULL; + cmdline = malloc(sizeof(char *) * (j+1)); + for (i = 1; i <= j; i++) { + cmdline[i] = NULL; + lua_rawgeti(L,-1,i); + if (lua_isnil(L,-1) || (s=(char *)lua_tostring(L,-1))==NULL) { + lua_pop(L,1); + if (i==1) { + xfree(cmdline) ; + return NULL; + } else { + break; + } + } else { + lua_pop(L,1); + cmdline[(i-1)] = xstrdup(s); + } + } + cmdline[i] = NULL; + + lua_rawgeti(L,-1,0); + if (lua_isnil(L,-1) || (s=(char *)lua_tostring(L,-1))==NULL) { + *runcmd = cmdline[0]; + } else { + *runcmd = xstrdup(s); + } + lua_pop(L,1); + + return cmdline; +} + + +static int os_exec (lua_State *L) { + char * maincmd, * runcmd; + char ** cmdline = NULL; + + if (lua_gettop(L)!=1) { + lua_pushnil(L); + lua_pushliteral(L,"invalid arguments passed"); + return 2; + } + if (lua_type(L,1)==LUA_TSTRING) { + maincmd = (char *)lua_tostring(L, 1); + cmdline = do_split_command(maincmd); + runcmd = cmdline[0]; + } else if (lua_type(L,1)==LUA_TTABLE) { + cmdline = do_flatten_command(L, & runcmd); + } + if (cmdline!=NULL) { +#if defined(WIN32) && DONT_REALLY_EXIT + exec_command(runcmd, cmdline, environ); +#else + if (exec_command(runcmd, cmdline, environ)==-1) { + lua_pushnil(L); + lua_pushfstring(L,"%s: %s",runcmd, strerror(errno)); + lua_pushnumber(L, errno); + return 3; + } +#endif + } + lua_pushnil(L); + lua_pushliteral(L,"invalid command line passed"); + return 2; +} + +#define do_error_return(A,B) do { \ + lua_pushnil(L); \ + lua_pushfstring(L,"%s: %s",runcmd,(A)); \ + lua_pushnumber(L, B); \ + return 3; \ + } while (0) + +static int os_spawn (lua_State *L) { + char * maincmd, * runcmd; + char ** cmdline = NULL; + int i; + + if (lua_gettop(L)!=1) { + lua_pushnil(L); + lua_pushliteral(L,"invalid arguments passed"); + return 2; + } + if (lua_type(L,1)==LUA_TSTRING) { + maincmd = (char *)lua_tostring(L, 1); + cmdline = do_split_command(maincmd); + runcmd = cmdline[0]; + } else if (lua_type(L,1)==LUA_TTABLE) { + cmdline = do_flatten_command(L, &runcmd); + } + if (cmdline!=NULL) { + i = spawn_command(runcmd, cmdline, environ); + if (i==0) { + lua_pushnumber(L, i); + return 1; + } else if (i==-1) { + /* this branch covers WIN32 as well as fork() and waitpid() errors */ + do_error_return(strerror(errno),errno); +#ifndef WIN32 + } else if (i==INVALID_RET_E2BIG) { do_error_return(strerror(E2BIG),i); + } else if (i==INVALID_RET_ENOENT) { do_error_return(strerror(ENOENT),i); + } else if (i==INVALID_RET_ENOEXEC) { do_error_return(strerror(ENOEXEC),i); + } else if (i==INVALID_RET_ENOMEM) { do_error_return(strerror(ENOMEM),i); + } else if (i==INVALID_RET_ETXTBSY) { do_error_return(strerror(ETXTBSY),i); + } else if (i==INVALID_RET_UNKNOWN) { do_error_return("execution failed",i); + } else if (i==INVALID_RET_INTR) { do_error_return("execution interrupted",i); +#endif + } else { + lua_pushnumber(L, i); + return 1; + } + } + lua_pushnil(L); + lua_pushliteral(L,"invalid command line passed"); + return 2; +} + +/* Hans wants to set env values */ + +static int os_setenv (lua_State *L) { + char *value, *key, *val; + key = (char *)luaL_optstring(L, 1, NULL); + val = (char *)luaL_optstring(L, 2, NULL); + if (key) { + if (val) { + value = xmalloc(strlen(key)+strlen(val)+2); + sprintf(value,"%s=%s",key,val); + if (putenv(value)) { + return luaL_error(L, "unable to change environment"); + } + } else { +#if defined(WIN32) || defined(__sun__) + value = xmalloc(strlen(key)+2); + sprintf(value,"%s=",key); + if (putenv(value)) { + return luaL_error(L, "unable to change environment"); + } +#else + (void)unsetenv(key); +#endif + } + } + lua_pushboolean (L, 1); + return 1; +} + + +void find_env (lua_State *L){ + char *envitem, *envitem_orig; + char *envkey; + char **envpointer; + envpointer = environ; + lua_getglobal(L,"os"); + if (envpointer!=NULL && lua_istable(L,-1)) { + luaL_checkstack(L,2,"out of stack space"); + lua_pushstring(L,"env"); + lua_newtable(L); + while (*envpointer) { + /* TODO: perhaps a memory leak here */ + luaL_checkstack(L,2,"out of stack space"); + envitem = xstrdup(*envpointer); + envitem_orig = envitem; + envkey=envitem; + while (*envitem != '=') { + envitem++; + } + *envitem=0; + envitem++; + lua_pushstring(L,envkey); + lua_pushstring(L,envitem); + lua_rawset(L,-3); + envpointer++; + free(envitem_orig); + } + lua_rawset(L,-3); + } + lua_pop(L,1); +} + +static int ex_sleep(lua_State *L) +{ + lua_Number interval = luaL_checknumber(L, 1); + lua_Number units = luaL_optnumber(L, 2, 1); +#ifdef WIN32 + Sleep(1e3 * interval / units); +#else /* assumes posix or bsd */ + usleep(1e6 * interval / units); +#endif + return 0; +} + +#if (! defined (WIN32)) && (! defined (__SUNOS__)) +static int os_times (lua_State *L) { + struct tms r; + (void)times(&r); + lua_newtable(L); + lua_pushnumber(L, ((lua_Number)(r.tms_utime))/(lua_Number)sysconf(_SC_CLK_TCK)); + lua_setfield(L,-2,"utime"); + lua_pushnumber(L, ((lua_Number)(r.tms_stime))/(lua_Number)sysconf(_SC_CLK_TCK)); + lua_setfield(L,-2,"stime"); + lua_pushnumber(L, ((lua_Number)(r.tms_cutime))/(lua_Number)sysconf(_SC_CLK_TCK)); + lua_setfield(L,-2,"cutime"); + lua_pushnumber(L, ((lua_Number)(r.tms_cstime))/(lua_Number)sysconf(_SC_CLK_TCK)); + lua_setfield(L,-2,"cstime"); + return 1; +} +#endif + +#if ! defined (__SUNOS__) + +#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) + #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64 +#else + #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL +#endif + +static int os_gettimeofday (lua_State *L) { + double v; +#ifndef WIN32 + struct timeval tv; + gettimeofday(&tv, NULL); + v = (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0; +#else + FILETIME ft; + unsigned __int64 tmpres = 0; + + GetSystemTimeAsFileTime(&ft); + + tmpres |= ft.dwHighDateTime; + tmpres <<= 32; + tmpres |= ft.dwLowDateTime; + tmpres /= 10; + tmpres -= DELTA_EPOCH_IN_MICROSECS; /*converting file time to unix epoch*/ + v = (double)tmpres / 1000000.0; +#endif + lua_pushnumber(L, v); + return 1; +} +#endif + +static const char repl[] = "0123456789abcdefghijklmnopqrstuvwxyz"; + +static int dirs_made = 0; + +#define MAXTRIES 36*36*36 + +char * +do_mkdtemp (char *tmpl) +{ + int count ; + int value ; + char *xes = &tmpl[strlen (tmpl) - 6]; + /* this is not really all that random, but it will do */ + if (dirs_made==0) { + srand(time(NULL)); + } + value = rand(); + for (count = 0; count < MAXTRIES; value += 8413, ++count) { + int v = value; + xes[0] = repl[v % 36]; v /= 36; + xes[1] = repl[v % 36]; v /= 36; + xes[2] = repl[v % 36]; v /= 36; + xes[3] = repl[v % 36]; v /= 36; + xes[4] = repl[v % 36]; v /= 36; + xes[5] = repl[v % 36]; + if (mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR) >= 0) { + dirs_made++; + return tmpl; + } else if (errno != EEXIST) { + return NULL; + } + } + return NULL; +} + +static int os_tmpdir (lua_State *L) { + char *s, *tempdir; + char *tmp = (char *)luaL_optstring(L, 1, "luatex.XXXXXX"); + if (tmp==NULL || + strlen(tmp)<6 || + (strcmp(tmp+strlen(tmp)-6,"XXXXXX") != 0)) { + lua_pushnil(L); + lua_pushstring(L, "Invalid argument to os.tmpdir()"); + return 2; + } else { + tempdir = xstrdup(tmp); + } +#ifdef HAVE_MKDTEMP + s = mkdtemp(tempdir); +#else + s = do_mkdtemp(tempdir); +#endif + if (s==NULL) { + int en = errno; /* calls to Lua API may change this value */ + lua_pushnil(L); + lua_pushfstring(L, "%s", strerror(en)); + return 2; + } else { + lua_pushstring(L,s); + return 1; + } +} + + +void +open_oslibext (lua_State *L, int safer_option) { + + find_env(L); + + lua_getglobal(L,"os"); + lua_pushcfunction(L, ex_sleep); + lua_setfield(L,-2,"sleep"); + lua_getglobal(L,"os"); + lua_pushliteral(L, OS_PLATTYPE); + lua_setfield(L,-2,"type"); + lua_getglobal(L,"os"); + lua_pushliteral(L, OS_PLATNAME); + lua_setfield(L,-2,"name"); +#if (! defined (WIN32)) && (! defined (__SUNOS__)) + lua_getglobal(L,"os"); + lua_pushcfunction(L, os_times); + lua_setfield(L,-2,"times"); +#endif +#if ! defined (__SUNOS__) + lua_getglobal(L,"os"); + lua_pushcfunction(L, os_gettimeofday); + lua_setfield(L,-2,"gettimeofday"); +#endif + if (!safer_option) { + lua_getglobal(L,"os"); + lua_pushcfunction(L, os_setenv); + lua_setfield(L,-2,"setenv"); + lua_getglobal(L,"os"); + lua_pushcfunction(L, os_exec); + lua_setfield(L,-2,"exec"); + lua_getglobal(L,"os"); + lua_pushcfunction(L, os_spawn); + lua_setfield(L,-2,"spawn"); + lua_getglobal(L,"os"); + lua_pushcfunction(L, os_tmpdir); + lua_setfield(L,-2,"tmpdir"); + + } + + +} diff --git a/Build/source/texk/web2c/luatexdir/lua/lpdflib.c b/Build/source/texk/web2c/luatexdir/lua/lpdflib.c new file mode 100644 index 00000000000..9cf847c84c8 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/lpdflib.c @@ -0,0 +1,127 @@ +/* $Id: lpdflib.c 1013 2008-02-14 00:09:02Z oneiros $ */ + +#include "luatex-api.h" +#include + + +static int +findcurv (lua_State *L) { + int j; + j = get_cur_v(); + lua_pushnumber(L, j); + return 1; +} + +static int +findcurh (lua_State *L) { + int j; + j = get_cur_h(); + lua_pushnumber(L, j); + return 1; +} + + +typedef enum { set_origin, direct_page, direct_always } pdf_lit_mode; + +int luapdfprint(lua_State * L) +{ + int n; + unsigned i, len; + const char *outputstr, *st; + pdf_lit_mode literal_mode; + n = lua_gettop(L); + if (!lua_isstring(L, -1)) { + lua_pushstring(L, "no string to print"); + lua_error(L); + } + literal_mode = set_origin; + if (n == 2) { + if (!lua_isstring(L, -2)) { + lua_pushstring(L, "invalid argument for print literal mode"); + lua_error(L); + } else { + outputstr = (char *) lua_tostring(L, -2); + if (strcmp(outputstr, "direct") == 0) + literal_mode = direct_always; + else if (strcmp(outputstr, "page") == 0) + literal_mode = direct_page; + else { + lua_pushstring(L, + "invalid argument for print literal mode"); + lua_error(L); + } + } + } else { + if (n != 1) { + lua_pushstring(L, "invalid number of arguments"); + lua_error(L); + } + } + switch (literal_mode) { + case (set_origin): + pdf_end_text(); + pdf_set_origin(cur_h, cur_v); + break; + case (direct_page): + pdf_end_text(); + break; + case (direct_always): + pdf_end_string_nl(); + break; + default: + assert(0); + } + st = lua_tolstring(L, n,&len); + for (i = 0; i < len; i++) { + if (i%16 == 0) + pdfroom(16); + pdf_buf[pdf_ptr++] = st[i]; + } + return 0; +} + +static int +getpdf (lua_State *L) { + char *st; + if (lua_isstring(L,2)) { + st = (char *)lua_tostring(L,2); + if (st && *st) { + if (*st == 'h') + return findcurh(L); + else if (*st == 'v') + return findcurv(L); + } + } + lua_pushnil(L); + return 1; +} + +static int +setpdf (lua_State *L) { + return (L==NULL ? 0 : 0); /* for -Wall */ +} + +static const struct luaL_reg pdflib[] = { + {"print", luapdfprint}, + {NULL, NULL} /* sentinel */ +}; + + +int +luaopen_pdf (lua_State *L) { + luaL_register(L, "pdf", pdflib); + /* build meta table */ + luaL_newmetatable(L,"pdf_meta"); + lua_pushstring(L, "__index"); + lua_pushcfunction(L, getpdf); + /* do these later, NYI */ + if (0) { + lua_settable(L, -3); + lua_pushstring(L, "__newindex"); + lua_pushcfunction(L, setpdf); + } + lua_settable(L, -3); + lua_setmetatable(L,-2); /* meta to itself */ + return 1; +} + diff --git a/Build/source/texk/web2c/luatexdir/lua/lstatslib.c b/Build/source/texk/web2c/luatexdir/lua/lstatslib.c new file mode 100644 index 00000000000..025e851e775 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/lstatslib.c @@ -0,0 +1,211 @@ +/* $Id: lstatslib.c 1013 2008-02-14 00:09:02Z oneiros $ */ + +#include "luatex-api.h" +#include + +typedef struct statistic { + const char *name; + char type; + void *value; +} statistic ; + +extern char *ptexbanner; +/* extern string getcurrentfilenamestring; */ + +typedef char * (*charfunc)(void); +typedef integer (*intfunc)(void); + +char *getbanner (void) { + return ptexbanner; +} + +/* hack, I really should implement the makecstring */ +char *getfilename (void) { + integer t; + t = get_current_name(); + if (t>(1<<21)) + return makecstring(t); + else + return xstrdup (""); +} + +char *getlasterror (void) { + return makecstring(last_error); +} + + +extern int luabytecode_max; +extern int luabytecode_bytes; +extern int luastate_max; +extern int luastate_bytes; + +static struct statistic stats[] = { + { "pdf_gone", 'g', &pdf_gone }, + { "pdf_ptr", 'g', &pdf_ptr }, + { "dvi_gone", 'g', &dvi_offset }, + { "dvi_ptr", 'g', &dvi_ptr }, + { "total_pages", 'g', &total_pages }, + { "output_file_name", 's', &output_file_name }, + { "log_name", 's', &texmf_log_name }, /* weird */ + { "banner", 'S', &getbanner }, + { "pdftex_banner", 's', &pdftex_banner }, + /* + * mem stat + */ + { "var_used", 'g', &var_used }, + { "dyn_used", 'g', &dyn_used }, + /* + * traditional tex stats + */ + { "str_ptr", 'g', &str_ptr }, + { "init_str_ptr", 'g', &init_str_ptr }, + { "max_strings", 'g', &max_strings }, + { "pool_ptr", 'g', &pool_ptr }, + { "init_pool_ptr", 'g', &init_pool_ptr }, + { "pool_size", 'g', &pool_size }, + { "var_mem_max", 'g', &var_mem_max }, + { "node_mem_usage", 'S', &sprint_node_mem_usage }, + { "fix_mem_max", 'g', &fix_mem_max }, + { "fix_mem_min", 'g', &fix_mem_min }, + { "fix_mem_end", 'g', &fix_mem_end }, + { "cs_count", 'g', &cs_count }, + { "hash_size", 'G', &get_hash_size }, + { "hash_extra", 'g', &hash_extra }, + { "font_ptr", 'G', &max_font_id }, + { "max_in_stack", 'g', &max_in_stack }, + { "max_nest_stack", 'g', &max_nest_stack }, + { "max_param_stack", 'g', &max_param_stack }, + { "max_buf_stack", 'g', &max_buf_stack }, + { "max_save_stack", 'g', &max_save_stack }, + { "stack_size", 'g', &stack_size }, + { "nest_size", 'g', &nest_size }, + { "param_size", 'g', ¶m_size }, + { "buf_size", 'g', &buf_size }, + { "save_size", 'g', &save_size }, + /* pdf stats */ + { "obj_ptr", 'g', &obj_ptr }, + { "obj_tab_size", 'g', &obj_tab_size }, + { "pdf_os_cntr", 'g', &pdf_os_cntr }, + { "pdf_os_objidx", 'g', &pdf_os_objidx }, + { "pdf_dest_names_ptr", 'g', &pdf_dest_names_ptr }, + { "dest_names_size", 'g', &dest_names_size }, + { "pdf_mem_ptr", 'g', &pdf_mem_ptr }, + { "pdf_mem_size", 'g', &pdf_mem_size }, + + { "largest_used_mark", 'g', &biggest_used_mark }, + + { "filename", 'S', &getfilename }, + { "inputid", 'G', &get_current_name }, + { "linenumber", 'g', &line }, + { "lasterrorstring", 'S', &getlasterror }, + + { "luabytecodes", 'g', &luabytecode_max }, + { "luabytecode_bytes", 'g', &luabytecode_bytes }, + { "luastates", 'g', &luastate_max }, + { "luastate_bytes", 'g', &luastate_bytes }, + + { "output_active", 'b', &output_active }, + + { NULL, 0 , 0 } }; + + +static int stats_name_to_id (char *name) { + int i; + for (i=0; stats[i].name!=NULL; i++) { + if (strcmp(stats[i].name, name) == 0) + return i; + } + return 0; +} + +static int do_getstat (lua_State *L,int i) { + int t; + char *st; + charfunc f; + intfunc g; + int str; + t = stats[i].type; + switch(t) { + case 'S': + f = stats[i].value; + st = f(); + lua_pushstring(L,st); + break; + case 's': + str = *(integer *)(stats[i].value); + if (str) { + lua_pushstring(L,makecstring(str)); + } else { + lua_pushnil(L); + } + break; + case 'G': + g = stats[i].value; + lua_pushnumber(L,g()); + break; + case 'g': + lua_pushnumber(L,*(integer *)(stats[i].value)); + break; + case 'B': + g = stats[i].value; + lua_pushboolean(L,g()); + break; + case 'b': + lua_pushboolean(L,*(integer *)(stats[i].value)); + break; + default: + lua_pushnil(L); + } + return 1; +} + +static int getstats (lua_State *L) { + char *st; + int i; + if (lua_isstring(L,-1)) { + st = (char *)lua_tostring(L,-1); + i = stats_name_to_id(st); + if (i>0) { + return do_getstat(L,i); + } + } + return 0; +} + +static int setstats (lua_State *L) { + return 0; +} + +static int statslist (lua_State *L) { + int i; + luaL_checkstack(L,1,"out of stack space"); + lua_newtable(L); + for (i=0; stats[i].name!=NULL; i++) { + luaL_checkstack(L,2,"out of stack space"); + lua_pushstring(L,stats[i].name); + do_getstat(L,i); + lua_rawset(L,-3); + } + return 1; +} + + + +static const struct luaL_reg statslib [] = { + {"list",statslist}, + {NULL, NULL} /* sentinel */ +}; + +int luaopen_stats (lua_State *L) +{ + luaL_register(L, "status", statslib); + luaL_newmetatable(L,"stats_meta"); + lua_pushstring(L, "__index"); + lua_pushcfunction(L, getstats); + lua_settable(L, -3); + lua_pushstring(L, "__newindex"); + lua_pushcfunction(L, setstats); + lua_settable(L, -3); + lua_setmetatable(L,-2); /* meta to itself */ + return 1; +} diff --git a/Build/source/texk/web2c/luatexdir/lua/ltexiolib.c b/Build/source/texk/web2c/luatexdir/lua/ltexiolib.c new file mode 100644 index 00000000000..a61409b2943 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/ltexiolib.c @@ -0,0 +1,117 @@ +/* $Id: ltexiolib.c 1013 2008-02-14 00:09:02Z oneiros $ */ + +#include "luatex-api.h" +#include + +typedef void (*texio_printer) (strnumber s); + +static char *loggable_info = NULL; + +static int +do_texio_print (lua_State *L, texio_printer printfunction) { + strnumber texs,u; + char *s; + char save_selector; + int n,i; + size_t k; + u = 0; + n = lua_gettop(L); + if (n==0 || !lua_isstring(L, -1)) { + lua_pushstring(L, "no string to print"); + lua_error(L); + } + save_selector = selector; + i = 1; + if (n>1) { + s=(char *)lua_tostring(L, 1); + if (strcmp(s,"log") == 0) { i++; selector = log_only; } + else if (strcmp(s,"term") == 0) { i++; selector = term_only; } + else if (strcmp(s,"term and log") == 0) { i++; selector = term_and_log; } + } + if (selector!=log_only && selector!=term_only && selector != term_and_log) { + normalize_selector(); /* sets selector */ + } + /* just in case there is a string in progress */ + if (str_start[str_ptr-0x200000]1) { + s=(char *)lua_tostring(L, 1); + if (strcmp(s,"log") == 0) { i++; l = 1; } + else if (strcmp(s,"term") == 0) { i++; l = 2; } + else if (strcmp(s,"term and log") == 0) { i++; l = 3; } + } + for (;i<=n;i++) { + if(lua_isstring(L, i)) { + s = (char *)lua_tostring(L, i); + if (l==2||l==3) + fprintf(stdout,"%s%s", extra, s); + if (l==1||l==3) { + if (loggable_info==NULL) { + loggable_info = strdup(s); + } else { + char *v = concat3 (loggable_info,extra,s); + free(loggable_info); + loggable_info = v; + } + } + } + } +} + +static int +texio_print (lua_State *L) { + if (ready_already!=314159 || pool_ptr==0 || job_name==0) { + do_texio_ini_print(L,""); + return 0; + } + return do_texio_print(L,zprint); +} + +static int +texio_printnl (lua_State *L) { + if (ready_already!=314159 || pool_ptr==0 || job_name==0) { + do_texio_ini_print(L,"\n"); + return 0; + } + return do_texio_print(L,zprint_nl); +} + +/* at the point this function is called, the selector is log_only */ +void flush_loggable_info (void) { + if (loggable_info!=NULL) { + fprintf(log_file,"%s\n",loggable_info); + free(loggable_info); + loggable_info=NULL; + } +} + + +static const struct luaL_reg texiolib [] = { + {"write", texio_print}, + {"write_nl", texio_printnl}, + {NULL, NULL} /* sentinel */ +}; + +int +luaopen_texio (lua_State *L) { + luaL_register(L,"texio",texiolib); + return 1; +} diff --git a/Build/source/texk/web2c/luatexdir/lua/ltexlib.c b/Build/source/texk/web2c/luatexdir/lua/ltexlib.c new file mode 100644 index 00000000000..f2258010136 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/ltexlib.c @@ -0,0 +1,820 @@ +/* $Id: ltexlib.c 1087 2008-03-07 23:52:35Z hhenkel $ */ + +#include "luatex-api.h" +#include +#include "nodes.h" + +typedef struct { + char *text; + unsigned int tsize; + void *next; + unsigned char partial; + int cattable; +} rope; + +typedef struct { + rope *head; + rope *tail; + char complete; /* currently still writing ? */ +} spindle; + +#define PARTIAL_LINE 1 +#define FULL_LINE 0 + +#define NO_CAT_TABLE -2 +#define DEFAULT_CAT_TABLE -1 + +#define write_spindle spindles[spindle_index] +#define read_spindle spindles[(spindle_index-1)] + +static int spindle_size = 0; +static spindle *spindles = NULL; +static int spindle_index = 0; + + +static int +do_luacprint (lua_State * L, int partial, int deftable) { + int i, n; + size_t tsize; + char *st, *sttemp; + rope *rn; + int cattable = deftable; + int startstrings = 1; + n = lua_gettop(L); + if (cattable != NO_CAT_TABLE) { + if (lua_type(L,1)==LUA_TNUMBER && n>1) { + cattable = lua_tonumber(L, 1); + startstrings = 2; + } + } + for (i = startstrings; i <= n; i++) { + if (!lua_isstring(L, i)) { + lua_pushstring(L, "no string to print"); + lua_error(L); + } + sttemp = (char *)lua_tolstring(L, i,&tsize); + st = xmalloc((tsize+1)); + memcpy(st,sttemp,(tsize+1)); + if (st) { + /* fprintf(stderr,"W[%d]:=%s\n",spindle_index,st);*/ + luacstrings++; + rn = (rope *)xmalloc(sizeof(rope)); /* valgrind says we leak here */ + rn->text = st; + rn->tsize = tsize; + rn->partial = partial; + rn->cattable = cattable; + rn->next = NULL; + if (write_spindle.head == NULL) { + assert(write_spindle.tail == NULL); + write_spindle.head = rn; + } else { + write_spindle.tail->next = rn; + } + write_spindle.tail = rn; + write_spindle.complete = 0; + } + } + return 0; +} + +int luacwrite(lua_State * L) { + return do_luacprint(L,FULL_LINE,NO_CAT_TABLE); +} + +int luacprint(lua_State * L) { + return do_luacprint(L,FULL_LINE,DEFAULT_CAT_TABLE); +} + +int luacsprint(lua_State * L) { + return do_luacprint(L,PARTIAL_LINE,DEFAULT_CAT_TABLE); +} + +int +luacstring_detokenized (void) { + return (read_spindle.tail->cattable == NO_CAT_TABLE); +} + +int +luacstring_defaultcattable (void) { + return (read_spindle.tail->cattable == DEFAULT_CAT_TABLE); +} + +integer +luacstring_cattable (void) { + return (integer)read_spindle.tail->cattable; +} + +int +luacstring_simple (void) { + return (read_spindle.tail->partial == PARTIAL_LINE); +} + +int +luacstring_penultimate (void) { + return (read_spindle.tail->next == NULL); +} + +int +luacstring_input (void) { + char *st; + int ret; + rope *t = read_spindle.head; + if (!read_spindle.complete) { + read_spindle.complete =1; + read_spindle.tail = NULL; + } + if (t == NULL) { + if(read_spindle.tail != NULL) + free(read_spindle.tail); + read_spindle.tail = NULL; + return 0; + } + if (t->text != NULL) { + st = t->text; + /* put that thing in the buffer */ + last = first; + ret = last; + check_buffer_overflow (last + t->tsize); + while (t->tsize-->0) + buffer[last++] = *st++; + if (!t->partial) { + while (last-1>ret && buffer[last-1] == ' ') + last--; + } + free (t->text); + t->text = NULL; + } + if (read_spindle.tail != NULL) { /* not a one-liner */ + free(read_spindle.tail); + } + read_spindle.tail = t; + read_spindle.head = t->next; + return 1; +} + +/* open for reading, and make a new one for writing */ +void +luacstring_start (int n) { + spindle_index++; + if(spindle_size == spindle_index) { /* add a new one */ + spindles = xrealloc(spindles,sizeof(spindle)*(spindle_size+1)); + spindles[spindle_index].head = NULL; + spindles[spindle_index].tail = NULL; + spindles[spindle_index].complete = 0; + spindle_size++; + } +} + +/* close for reading */ + +void +luacstring_close (int n) { + rope *next, *t; + next = read_spindle.head; + while (next != NULL) { + if (next->text != NULL) + free(next->text); + t = next; + next = next->next; + free(t); + } + read_spindle.head = NULL; + if(read_spindle.tail != NULL) + free(read_spindle.tail); + read_spindle.tail = NULL; + read_spindle.complete = 0; + spindle_index--; +} + +/* local (static) versions */ + +#define width_offset 1 +#define depth_offset 2 +#define height_offset 3 + +#define check_index_range(j) \ + if (j<0 || j > 65535) { \ + lua_pushstring(L, "incorrect index value"); \ + lua_error(L); } + + +int dimen_to_number (lua_State *L,char *s){ + double v; + char *d; + int j; + v = strtod(s,&d); + if (strcmp (d,"in") == 0) { j = (int)(((v*7227)/100) *65536); } + else if (strcmp (d,"pc") == 0) { j = (int)((v*12) *65536); } + else if (strcmp (d,"cm") == 0) { j = (int)(((v*7227)/254) *65536); } + else if (strcmp (d,"mm") == 0) { j = (int)(((v*7227)/2540) *65536); } + else if (strcmp (d,"bp") == 0) { j = (int)(((v*7227)/7200) *65536); } + else if (strcmp (d,"dd") == 0) { j = (int)(((v*1238)/1157) *65536); } + else if (strcmp (d,"cc") == 0) { j = (int)(((v*14856)/1157) *65536); } + else if (strcmp (d,"nd") == 0) { j = (int)(((v*21681)/20320)*65536); } + else if (strcmp (d,"nc") == 0) { j = (int)(((v*65043)/5080) *65536); } + else if (strcmp (d,"pt") == 0) { j = (int)(v *65536); } + else if (strcmp (d,"sp") == 0) { j = (int)(v); } + else { + lua_pushstring(L, "unknown dimension specifier"); + lua_error(L); + j = 0; + } + return j; +} + +int setdimen (lua_State *L) { + int i,j; + size_t k; + int cur_cs; + int texstr; + char *s; + i = lua_gettop(L); + j = 0; + /* find the value*/ + if (!lua_isnumber(L,i)) + if (lua_isstring(L,i)) { + j = dimen_to_number(L,(char *)lua_tostring(L,i)); + } else { + lua_pushstring(L, "unsupported value type"); + lua_error(L); + } + else + j = (int)lua_tonumber(L,i); + /* find the index*/ + if (lua_type(L,i-1)==LUA_TSTRING) { + s = (char *)lua_tolstring(L,i-1, &k); + texstr = maketexlstring(s,k); + cur_cs = string_lookup(texstr); + flush_str(texstr); + k = zget_equiv(cur_cs)-get_scaled_base(); + } else { + k = (int)luaL_checkinteger(L,i-1); + } + check_index_range(k); + if(set_tex_dimen_register(k,j)) { + lua_pushstring(L, "incorrect value"); + lua_error(L); + } + return 0; +} + +int getdimen (lua_State *L) { + int i,j; + size_t k; + int cur_cs; + int texstr; + char *s; + i = lua_gettop(L); + if (lua_type(L,i)==LUA_TSTRING) { + s = (char *)lua_tolstring(L,i, &k); + texstr = maketexlstring(s,k); + cur_cs = string_lookup(texstr); + flush_str(texstr); + if (is_undefined_cs(cur_cs)) { + lua_pushnil(L); + return 1; + } + k = zget_equiv(cur_cs)-get_scaled_base(); + } else { + k = (int)luaL_checkinteger(L,i); + } + check_index_range(k); + j = get_tex_dimen_register(k); + lua_pushnumber(L, j); + return 1; +} + +int setcount (lua_State *L) { + int i,j; + size_t k; + int cur_cs; + int texstr; + char *s; + i = lua_gettop(L); + j = (int)luaL_checkinteger(L,i); + if (lua_type(L,i-1)==LUA_TSTRING) { + s = (char *)lua_tolstring(L,i-1,&k); + texstr = maketexlstring(s,k); + cur_cs = string_lookup(texstr); + flush_str(texstr); + k = zget_equiv(cur_cs)-get_count_base(); + } else { + k = (int)luaL_checkinteger(L,i-1); + } + check_index_range(k); + if (set_tex_count_register(k,j)) { + lua_pushstring(L, "incorrect value"); + lua_error(L); + } + return 0; +} + +int getcount (lua_State *L) { + int i, j; + size_t k; + int cur_cs; + int texstr; + char *s; + i = lua_gettop(L); + if (lua_type(L,i)==LUA_TSTRING) { + s = (char *)lua_tolstring(L,i, &k); + texstr = maketexlstring(s,k); + cur_cs = string_lookup(texstr); + flush_str(texstr); + if (is_undefined_cs(cur_cs)) { + lua_pushnil(L); + return 1; + } + k = zget_equiv(cur_cs)-get_count_base(); + } else { + k = (int)luaL_checkinteger(L,i); + } + check_index_range(k); + j = get_tex_count_register(k); + lua_pushnumber(L, j); + return 1; +} + + +int setattribute (lua_State *L) { + int i,j; + size_t k; + int cur_cs; + int texstr; + char *s; + i = lua_gettop(L); + j = (int)luaL_checkinteger(L,i); + if (lua_type(L,i-1)==LUA_TSTRING) { + s = (char *)lua_tolstring(L,i-1, &k); + texstr = maketexlstring(s,k); + cur_cs = string_lookup(texstr); + flush_str(texstr); + k = zget_equiv(cur_cs)-get_attribute_base(); + } else { + k = (int)luaL_checkinteger(L,i-1); + } + check_index_range(k); + if (set_tex_attribute_register(k,j)) { + lua_pushstring(L, "incorrect value"); + lua_error(L); + } + return 0; +} + +int getattribute (lua_State *L) { + int i, j; + size_t k; + int cur_cs; + int texstr; + char *s; + i = lua_gettop(L); + if (lua_type(L,i)==LUA_TSTRING) { + s = (char *)lua_tolstring(L,i, &k); + texstr = maketexlstring(s,k); + cur_cs = string_lookup(texstr); + flush_str(texstr); + if (is_undefined_cs(cur_cs)) { + lua_pushnil(L); + return 1; + } + k = zget_equiv(cur_cs)-get_attribute_base(); + } else { + k = (int)luaL_checkinteger(L,i); + } + check_index_range(k); + j = get_tex_attribute_register(k); + lua_pushnumber(L, j); + return 1; +} + +int settoks (lua_State *L) { + int i,j; + size_t k,len; + int cur_cs; + int texstr; + char *s, *st; + i = lua_gettop(L); + if (!lua_isstring(L,i)) { + lua_pushstring(L, "unsupported value type"); + lua_error(L); + } + st = (char *)lua_tolstring(L,i,&len); + + if (lua_type(L,i-1)==LUA_TSTRING) { + s = (char *)lua_tolstring(L,i-1, &k); + texstr = maketexlstring(s,k); + cur_cs = string_lookup(texstr); + flush_str(texstr); + k = zget_equiv(cur_cs)-get_toks_base(); + } else { + k = (int)luaL_checkinteger(L,i-1); + } + check_index_range(k); + j = maketexlstring(st,len); + + if(zset_tex_toks_register(k,j)) { + flush_str(j); + lua_pushstring(L, "incorrect value"); + lua_error(L); + } + return 0; +} + +int gettoks (lua_State *L) { + int i; + size_t k; + strnumber t; + int cur_cs; + int texstr; + char *s; + i = lua_gettop(L); + if (lua_type(L,i)==LUA_TSTRING) { + s = (char *)lua_tolstring(L,i, &k); + texstr = maketexlstring(s,k); + cur_cs = string_lookup(texstr); + flush_str(texstr); + if (is_undefined_cs(cur_cs)) { + lua_pushnil(L); + return 1; + } + k = zget_equiv(cur_cs)-get_toks_base(); + } else { + k = (int)luaL_checkinteger(L,i); + } + + check_index_range(k); + t = get_tex_toks_register(k); + lua_pushstring(L, makecstring(t)); + flush_str(t); + return 1; +} + +int getbox (lua_State *L) { + int k, t; + k = (int)luaL_checkinteger(L,-1); + check_index_range(k); + t = get_tex_box_register(k); + nodelist_to_lua(L,t); + return 1; +} + +int setbox (lua_State *L) { + int i,j,k; + + + + k = (int)luaL_checkinteger(L,-2); + check_index_range(k); + i = get_tex_box_register(k); + if (lua_isboolean(L,-1)) { + j = lua_toboolean(L,-1); + if (j==0) + j = null; + else + return 0; + } else { + j = nodelist_from_lua(L); + } + if(set_tex_box_register(k,j)) { + lua_pushstring(L, "incorrect value"); + lua_error(L); + } + return 0; +} + + +static int getboxdim (lua_State *L, int whichdim) { + int i, j; + i = lua_gettop(L); + j = (int)lua_tonumber(L,(i)); + lua_settop(L,(i-2)); /* table at -1 */ + if (j<0 || j > 65535) { + lua_pushstring(L, "incorrect index"); + lua_error(L); + } + switch (whichdim) { + case width_offset: + lua_pushnumber(L, get_tex_box_width(j)); + break; + case height_offset: + lua_pushnumber(L, get_tex_box_height(j)); + break; + case depth_offset: + lua_pushnumber(L, get_tex_box_depth(j)); + } + return 1; +} + +int getboxwd (lua_State *L) { + return getboxdim (L, width_offset); +} + +int getboxht (lua_State *L) { + return getboxdim (L, height_offset); +} + +int getboxdp (lua_State *L) { + return getboxdim (L, depth_offset); +} + +static int setboxdim (lua_State *L, int whichdim) { + int i,j,k,err; + i = lua_gettop(L); + if (!lua_isnumber(L,i)) { + j = dimen_to_number(L,(char *)lua_tostring(L,i)); + } else { + j = (int)lua_tonumber(L,i); + } + k = (int)lua_tonumber(L,(i-1)); + lua_settop(L,(i-3)); /* table at -2 */ + if (k<0 || k > 65535) { + lua_pushstring(L, "incorrect index"); + lua_error(L); + } + err = 0; + switch (whichdim) { + case width_offset: + err = set_tex_box_width(k,j); + break; + case height_offset: + err = set_tex_box_height(k,j); + break; + case depth_offset: + err = set_tex_box_depth(k,j); + } + if (err) { + lua_pushstring(L, "not a box"); + lua_error(L); + } + return 0; +} + +int setboxwd (lua_State *L) { + return setboxdim(L,width_offset); +} + +int setboxht (lua_State *L) { + return setboxdim(L,height_offset); +} + +int setboxdp (lua_State *L) { + return setboxdim(L,depth_offset); +} + +int settex (lua_State *L) { + char *st; + int i,j,texstr; + size_t k; + int cur_cs, cur_cmd; + j = 0; + i = lua_gettop(L); + if (lua_isstring(L,(i-1))) { + st = (char *)lua_tolstring(L,(i-1), &k); + texstr = maketexlstring(st,k); + if (zis_primitive(texstr)) { + cur_cs = string_lookup(texstr); + flush_str(texstr); + cur_cmd = zget_eq_type(cur_cs); + if (is_int_assign(cur_cmd)) { + if (lua_isnumber(L,i)) { + assign_internal_int(zget_equiv(cur_cs),lua_tonumber(L,i)); + } else { + lua_pushstring(L, "unsupported value type"); + lua_error(L); + } + } else if (is_dim_assign(cur_cmd)) { + if (!lua_isnumber(L,i)) + if (lua_isstring(L,i)) { + j = dimen_to_number(L,(char *)lua_tostring(L,i)); + } else { + lua_pushstring(L, "unsupported value type"); + lua_error(L); + } + else + j = (int)lua_tonumber(L,i); + assign_internal_dim(zget_equiv(cur_cs),j); + } else { + lua_pushstring(L, "unsupported tex internal assignment"); + lua_error(L); + } + } else { + lua_rawset(L,(i-2)); + } + } else { + lua_rawset(L,(i-2)); + } + return 0; +} + +char * +get_something_internal (int cur_cmd, int cur_code) { + int texstr; + char *str; + int save_cur_val,save_cur_val_level; + save_cur_val = cur_val; + save_cur_val_level = cur_val_level; + zscan_something_simple(cur_cmd,cur_code); + texstr = the_scanned_result(); + cur_val = save_cur_val; + cur_val_level = save_cur_val_level; + str = makecstring(texstr); + flush_str(texstr); + return str; +} + +char * +get_convert (int cur_code) { + int texstr; + char *str = NULL; + texstr = the_convert_string(cur_code); + if (texstr) { + str = makecstring(texstr); + flush_str(texstr); + } + return str; +} + + +int +gettex (lua_State *L) { + char *st; + int i,texstr; + size_t k; + char *str; + int cur_cs, cur_cmd, cur_code; + i = lua_gettop(L); + if (lua_isstring(L,i)) { + st = (char *)lua_tolstring(L,i, &k); + texstr = maketexlstring(st,k); + cur_cs = zprim_lookup(texstr); + flush_str(texstr); + if (cur_cs) { + cur_cmd = zget_prim_eq_type(cur_cs); + cur_code = zget_prim_equiv(cur_cs); + if (is_convert(cur_cmd)) + str = get_convert(cur_code); + else + str = get_something_internal(cur_cmd,cur_code); + if (str) + lua_pushstring(L,str); + else + lua_pushnil(L); + return 1; + } else { + lua_rawget(L,(i-1)); + return 1; + } + } else { + lua_rawget(L,(i-1)); + return 1; + } + return 0; /* not reached */ +} + + +int +getlist (lua_State *L) { + char *str; + if (lua_isstring(L,2)) { + str = (char *)lua_tostring(L,2); + if (strcmp(str,"page_ins_head")==0) { + lua_pushnumber(L,page_ins_head); lua_nodelib_push(L); + } else if (strcmp(str,"contrib_head")==0) { + lua_pushnumber(L,contrib_head); lua_nodelib_push(L); + } else if (strcmp(str,"page_head")==0) { + lua_pushnumber(L,page_head); lua_nodelib_push(L); + } else if (strcmp(str,"temp_head")==0) { + lua_pushnumber(L,temp_head); lua_nodelib_push(L); + } else if (strcmp(str,"hold_head")==0) { + lua_pushnumber(L,hold_head); lua_nodelib_push(L); + } else if (strcmp(str,"adjust_head")==0) { + lua_pushnumber(L,adjust_head); lua_nodelib_push(L); + } else if (strcmp(str,"pre_adjust_head")==0) { + lua_pushnumber(L,pre_adjust_head); lua_nodelib_push(L); + } else if (strcmp(str,"align_head")==0) { + lua_pushnumber(L,align_head); lua_nodelib_push(L); + } else { + lua_pushnil(L); + } + } else { + lua_pushnil(L); + } + return 1; +} + +int +setlist (lua_State *L) { + return 0; +} + +#define infinity 2147483647 + +static int +do_integer_error(double m) { + char *help[] = {"I can only go up to 2147483647='17777777777=""7FFFFFFF,", + "so I'm using that number instead of yours.", + NULL } ; + tex_error("Number too big",help); + return (m>0.0 ? infinity : -infinity); +} + + +static int +tex_roundnumber (lua_State *L) { + double m = lua_tonumber(L, 1)+0.5; + if (abs(m)>(double)infinity) + lua_pushnumber(L,do_integer_error(m)); + else + lua_pushnumber(L,floor(m)); + return 1; +} + +static int +tex_scaletable (lua_State *L) { + double delta = luaL_checknumber(L, 2); + if (lua_istable(L,1)) { + lua_newtable(L); /* the new table is at index 3 */ + lua_pushnil(L); + while (lua_next(L,1)!= 0 ) { /* numeric value */ + lua_pushvalue(L,-2); + lua_insert(L,-2); + if (lua_isnumber(L,-1)) { + double m = lua_tonumber(L,-1)*delta + 0.5; + lua_pop(L,1); + if (abs(m)>(double)infinity) + lua_pushnumber(L,do_integer_error(m)); + else + lua_pushnumber(L,floor(m)); + } + lua_rawset(L,3); + } + } else if (lua_isnumber(L,1)) { + double m = lua_tonumber(L,1)*delta + 0.5; + if (abs(m)>(double)infinity) + lua_pushnumber(L,do_integer_error(m)); + else + lua_pushnumber(L,floor(m)); + } else { + lua_pushnil(L); + } + return 1; +} + +static const struct luaL_reg texlib [] = { + {"write", luacwrite}, + {"print", luacprint}, + {"sprint", luacsprint}, + {"setdimen", setdimen}, + {"getdimen", getdimen}, + {"setattribute", setattribute}, + {"getattribute", getattribute}, + {"setcount", setcount}, + {"getcount", getcount}, + {"settoks", settoks}, + {"gettoks", gettoks}, + {"setbox", setbox}, + {"getbox", getbox}, + {"setlist", setlist}, + {"getlist", getlist}, + {"setboxwd", setboxwd}, + {"getboxwd", getboxwd}, + {"setboxht", setboxht}, + {"getboxht", getboxht}, + {"setboxdp", setboxdp}, + {"getboxdp", getboxdp}, + {"round", tex_roundnumber}, + {"scale", tex_scaletable}, + {NULL, NULL} /* sentinel */ +}; + +int luaopen_tex (lua_State *L) +{ + luaL_register(L, "tex", texlib); + make_table(L,"attribute","getattribute","setattribute"); + make_table(L,"dimen","getdimen","setdimen"); + make_table(L,"count","getcount","setcount"); + make_table(L,"toks","gettoks","settoks"); + make_table(L,"box","getbox","setbox"); + make_table(L,"lists","getlist","setlist"); + make_table(L,"wd","getboxwd","setboxwd"); + make_table(L,"ht","getboxht","setboxht"); + make_table(L,"dp","getboxdp","setboxdp"); + /* make the meta entries */ + /* fetch it back */ + luaL_newmetatable(L,"tex_meta"); + lua_pushstring(L, "__index"); + lua_pushcfunction(L, gettex); + lua_settable(L, -3); + lua_pushstring(L, "__newindex"); + lua_pushcfunction(L, settex); + lua_settable(L, -3); + lua_setmetatable(L,-2); /* meta to itself */ + /* initialize the I/O stack: */ + spindles = xmalloc(sizeof(spindle)); + spindle_index = 0; + spindles[0].head = NULL; + spindles[0].tail = NULL; + spindle_size = 1; + return 1; +} + diff --git a/Build/source/texk/web2c/luatexdir/lua/ltokenlib.c b/Build/source/texk/web2c/luatexdir/lua/ltokenlib.c new file mode 100644 index 00000000000..582779623cf --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/ltokenlib.c @@ -0,0 +1,263 @@ +/* $Id: ltokenlib.c 1013 2008-02-14 00:09:02Z oneiros $ */ + +#include "luatex-api.h" +#include + + +extern int get_command_id (char *); + +static int max_command = 0; +static int hash_base = 0; +static int active_base = 0; +static int null_cs = 0; + +#define protected_token 0x1C00001 + +#define is_valid_token(L,i) (lua_istable(L,i) && lua_objlen(L,i)==3) +#define get_token_cmd(L,i) lua_rawgeti(L,i,1) +#define get_token_chr(L,i) lua_rawgeti(L,i,2) +#define get_token_cs(L,i) lua_rawgeti(L,i,3) + +static int +test_expandable (lua_State *L) { + integer cmd = -1; + if (is_valid_token(L,-1)) { + get_token_cmd(L,-1); + if (lua_isnumber(L,-1)) { + cmd = lua_tointeger(L,-1); + } else if (lua_isstring(L,-1)) { + cmd = get_command_id((char *)lua_tostring(L,-1)); + } + if (cmd>max_command) { + lua_pushboolean(L,1); + } else { + lua_pushboolean(L,0); + } + } else { + lua_pushnil(L); + } + return 1; +} + + +static int +test_protected (lua_State *L) { + integer chr = -1; + if (is_valid_token(L,-1)) { + get_token_chr(L,-1); + if (lua_isnumber(L,-1)) { + chr = lua_tointeger(L,-1); + } else if (lua_isstring(L,-1)) { + chr = get_command_id((char *)lua_tostring(L,-1)); + } + if (fixmem[fixmem[chr].hhrh].hhlh==protected_token) { + lua_pushboolean(L,1); + } else { + lua_pushboolean(L,0); + } + } else { + lua_pushnil(L); + } + return 1; +} + +static int +test_activechar (lua_State *L) { + integer cmd = -1; + if (is_valid_token(L,-1)) { + get_token_chr(L,-1); + if (lua_isnumber(L,-1)) { + cmd = lua_tointeger(L,-1); + } + if (cmd>0 && cmd==protected_token) { + lua_pushboolean(L,1); + } else { + lua_pushboolean(L,0); + } + } else { + lua_pushnil(L); + } + return 1; +} + + +static int +run_get_command_name (lua_State *L) { + int cs; + if (is_valid_token(L,-1)) { + get_token_cmd(L,-1); + if (lua_isnumber(L,-1)) { + cs = lua_tointeger(L,-1); + lua_pushstring(L,command_names[cs].cmd_name); + } else { + lua_pushstring(L,""); + } + } else { + lua_pushnil(L); + } + return 1; +} + +static int +run_get_csname_name (lua_State *L) { + int cs,cmd,n; + char *s; + + if (is_valid_token(L,-1)) { + get_token_cmd(L,-1); + if (lua_isnumber(L,-1)) { + cmd = lua_tointeger(L,-1); + } + lua_pop(L,1); + cs = 0; + get_token_cs(L,-1); + if (lua_isnumber(L,-1)) { + cs = lua_tointeger(L,-1); + } + lua_pop(L,1); + + if (cs != 0 && (n = zget_cs_text(cs)) && n>=0) { + s = makecstring(n); + lua_pushstring(L,s); + } else { + lua_pushstring(L,""); + } + } else { + lua_pushnil(L); + } + return 1; +} + +static int +run_get_command_id (lua_State *L) { + int cs = -1; + if (lua_isstring(L,-1)) { + cs = get_command_id((char *)lua_tostring(L,-1)); + } + lua_pushnumber(L,cs); + return 1; +} + + +static int +run_get_csname_id (lua_State *L) { + int texstr; + char *s; + size_t k,cs = 0; + if (lua_isstring(L,-1)) { + s = (char *)lua_tolstring(L,-1, &k); + texstr = maketexlstring(s,k); + cs = string_lookup(texstr); + flush_str(texstr); + } + lua_pushnumber(L,cs); + return 1; +} + + +void +make_token_table (lua_State *L, int cmd, int chr, int cs) { + lua_createtable(L,3,0); + lua_pushnumber(L,cmd); + lua_rawseti(L,-2,1); + lua_pushnumber(L,chr); + lua_rawseti(L,-2,2); + lua_pushnumber(L,cs); + lua_rawseti(L,-2,3); +} + +static int +run_get_next (lua_State *L) { + int save_nncs; + save_nncs = no_new_control_sequence; + no_new_control_sequence = 0; + get_next(); + no_new_control_sequence = save_nncs; + make_token_table(L,cur_cmd,cur_chr,cur_cs); + return 1; +} + +static int +run_expand (lua_State *L) { + expand(); + return 0; +} + + +static int +run_lookup (lua_State *L) { + char *s; + size_t l; + str_number t; + integer cs,cmd,chr; + int save_nncs; + if (lua_isstring(L,-1)) { + s = (char *)lua_tolstring(L,-1,&l); + if (l>0) { + save_nncs = no_new_control_sequence; + no_new_control_sequence = true; + cs = id_lookup((last+1),l); /* cleans up the lookup buffer */ + t = maketexlstring(s,l); + cs = string_lookup(t); + flush_str(t); + cmd = zget_eq_type(cs); + chr = zget_equiv(cs); + make_token_table(L,cmd,chr,cs); + no_new_control_sequence = save_nncs; + return 1; + } + } + lua_newtable(L); + return 1; +} + +static int +run_build (lua_State *L) { + integer cmd,chr,cs; + if (lua_isnumber(L,1)) { + cs =0; + chr = lua_tointeger(L,1); + cmd = luaL_optinteger(L,2,zget_char_cat_code(chr)); + if (cmd==0 || cmd == 9 || cmd == 14 || cmd == 15) { + fprintf(stdout, "\n\nluatex error: not a good token.\nCatcode %i can not be returned, so I replaced it by 12 (other)",(int)cmd); + error(); + cmd=12; + } + if (cmd == 13) { + cs=chr+active_base; + cmd=zget_eq_type(cs); + chr=zget_equiv(cs); + } + make_token_table(L,cmd,chr,cs); + return 1; + } else { + return run_lookup(L); + } +} + + +static const struct luaL_reg tokenlib [] = { + {"get_next", run_get_next}, + {"expand", run_expand}, + {"lookup", run_lookup}, + {"create", run_build}, + {"is_expandable",test_expandable}, + {"is_activechar",test_activechar}, + {"is_protected", test_protected}, + {"csname_id", run_get_csname_id}, + {"csname_name", run_get_csname_name}, + {"command_name", run_get_command_name}, + {"command_id", run_get_command_id}, + {NULL, NULL} /* sentinel */ +}; + +int luaopen_token (lua_State *L) +{ + luaL_register(L, "token", tokenlib); + max_command = get_max_command(); + hash_base = get_hash_base(); + active_base = get_active_base(); + null_cs = get_nullcs(); + return 1; +} + diff --git a/Build/source/texk/web2c/luatexdir/lua/luainit.c b/Build/source/texk/web2c/luatexdir/lua/luainit.c new file mode 100644 index 00000000000..c76b676c0f4 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/luainit.c @@ -0,0 +1,520 @@ +#include + +#include "luatex-api.h" +#include + +#include + +#ifndef program_invocation_name +/* char *program_invocation_name = NULL; */ +#endif + +extern void parse_src_specials_option (char *n) ; + +const_string LUATEX_IHELP[] = { + "Usage: luatex --lua=FILE [OPTION]... [TEXNAME[.tex]] [COMMANDS]", + " or: luatex --lua=FILE [OPTION]... \\FIRST-LINE", + " or: luatex --lua=FILE [OPTION]... &FMT ARGS", + " Run luaTeX on TEXNAME, usually creating TEXNAME.pdf.", + " Any remaining COMMANDS are processed as luatex input, after TEXNAME is read.", + "", + " Alternatively, if the first non-option argument begins with a backslash,", + " interpret all non-option arguments as a line of luatex input.", + "", + " Alternatively, if the first non-option argument begins with a &, the", + " next word is taken as the FMT to read, overriding all else. Any", + " remaining arguments are processed as above.", + "", + " If no arguments or options are specified, prompt for input.", + "", + " --lua=FILE the lua initialization file", + " --safer disable some easily exploitable lua commands", + " --fmt=FORMAT load the format file FORMAT", + " --ini be initex, for dumping formats", + " --help display this help and exit", + " --version output version information and exit", + "", + " Alternate behaviour models can be obtained by special switches", + "", + " --luaonly run a lua file, then exit", + " --luaconly byte-compile a lua file, then exit", + NULL +}; + +static void +prepare_cmdline(lua_State * L, char **argv, int argc, int zero_offset) +{ + int i; + luaL_checkstack(L, argc + 3, "too many arguments to script"); + lua_createtable(L, 0, 0); + for (i = 0; i < argc; i++) { + lua_pushstring(L, argv[i]); + lua_rawseti(L, -2, (i-zero_offset)); + } + lua_setglobal(L, "arg"); + return; +} + +extern string dump_name; +extern const_string c_job_name; +extern boolean srcspecialsoption; +extern char *last_source_name; +extern int last_lineno; + +string input_name = NULL; + +static string user_progname = NULL; + +extern char *ptexbanner; +extern int program_name_set; /* in lkpselib.c */ + +/* for topenin() */ +extern char **argv; +extern int argc; + +char *startup_filename = NULL; +int lua_only = 0; +int lua_offset = 0; + +int safer_option = 0; + +/* Reading the options. */ + +/* Test whether getopt found an option ``A''. + Assumes the option index is in the variable `option_index', and the + option table in a variable `long_options'. */ +#define ARGUMENT_IS(a) STREQ (long_options[option_index].name, a) + +/* SunOS cc can't initialize automatic structs, so make this static. */ +static struct option long_options[] + = { { "fmt", 1, 0, 0}, + { "lua", 1, 0, 0}, + { "luaonly", 0, 0, 0}, + { "safer", 0, &safer_option, 1}, + { "help", 0, 0, 0 }, + { "ini", 0, &ini_version, 1 }, + { "interaction", 1, 0, 0 }, + { "halt-on-error", 0, &haltonerrorp, 1 }, + { "kpathsea-debug", 1, 0, 0 }, + { "progname", 1, 0, 0 }, + { "version", 0, 0, 0 }, + { "recorder", 0, &recorder_enabled, 1 }, + { "etex", 0, 0, 0 }, + { "output-comment", 1, 0, 0 }, + { "output-directory", 1, 0, 0 }, + { "draftmode", 0, 0, 0 }, + { "output-format", 1, 0, 0 }, + { "shell-escape", 0, &shellenabledp, 1 }, + { "no-shell-escape", 0, &shellenabledp, -1 }, + { "debug-format", 0, &debug_format_file, 1 }, + { "src-specials", 2, 0, 0 }, + { "file-line-error-style", 0, &filelineerrorstylep, 1 }, + { "no-file-line-error-style", 0, &filelineerrorstylep, -1 }, + /* Shorter option names for the above. */ + { "file-line-error", 0, &filelineerrorstylep, 1 }, + { "no-file-line-error", 0, &filelineerrorstylep, -1 }, + { "jobname", 1, 0, 0 }, + { "parse-first-line", 0, &parsefirstlinep, 1 }, + { "no-parse-first-line", 0, &parsefirstlinep, -1 }, + { "translate-file", 1, 0, 0 }, + { "default-translate-file", 1, 0, 0 }, + { "8bit", 0, 0, 0 }, + { "mktex", 1, 0, 0 }, + { "no-mktex", 1, 0, 0 }, +{0, 0, 0, 0} +}; + +static void +parse_options(int argc, char **argv) +{ + int g; /* `getopt' return code. */ + int option_index; + char *firstfile = NULL; + opterr = 0; /* dont whine */ + for (;;) { + g = getopt_long_only(argc, argv, "+", long_options, &option_index); + + if (g == -1) /* End of arguments, exit the loop. */ + break; + if (g == '?') /* Unknown option. */ + continue; + + assert(g == 0); /* We have no short option names. */ + + if (ARGUMENT_IS("luaonly")) { + lua_only = 1; + lua_offset = optind; + luainit = 1 ; + } else if (ARGUMENT_IS("lua")) { + startup_filename = optarg; + lua_offset = (optind-1); + luainit = 1 ; + + } else if (ARGUMENT_IS ("kpathsea-debug")) { + kpathsea_debug |= atoi (optarg); + + } else if (ARGUMENT_IS("progname")) { + user_progname = optarg; + + } else if (ARGUMENT_IS ("jobname")) { + c_job_name = optarg; + + } else if (ARGUMENT_IS("fmt")) { + dump_name = optarg; + + } else if (ARGUMENT_IS ("output-directory")) { + output_directory = optarg; + + } else if (ARGUMENT_IS ("output-comment")) { + unsigned len = strlen (optarg); + if (len < 256) { + output_comment = optarg; + } else { + WARNING2 ("Comment truncated to 255 characters from %d. (%s)", + len, optarg); + output_comment = (string)xmalloc (256); + strncpy (output_comment, optarg, 255); + output_comment[255] = 0; + } + + } else if (ARGUMENT_IS ("src-specials")) { + last_source_name = xstrdup(""); + /* Option `--src" without any value means `auto' mode. */ + if (optarg == NULL) { + insertsrcspecialeverypar = true; + insertsrcspecialauto = true; + srcspecialsoption = true; + srcspecialsp = true; + } else { + parse_src_specials_option(optarg); + } + + } else if (ARGUMENT_IS ("output-format")) { + pdf_output_option = 1; + if (strcmp(optarg, "dvi") == 0) { + pdf_output_value = 0; + } else if (strcmp(optarg, "pdf") == 0) { + pdf_output_value = 2; + } else { + WARNING1 ("Ignoring unknown value `%s' for --output-format", optarg); + pdf_output_option = 0; + } + + } else if (ARGUMENT_IS ("draftmode")) { + pdf_draftmode_option = 1; + pdf_draftmode_value = 1; + + } else if (ARGUMENT_IS ("mktex")) { + kpse_maketex_option (optarg, true); + + } else if (ARGUMENT_IS ("no-mktex")) { + kpse_maketex_option (optarg, false); + + } else if (ARGUMENT_IS ("interaction")) { + /* These numbers match @d's in *.ch */ + if (STREQ (optarg, "batchmode")) { + interactionoption = 0; + } else if (STREQ (optarg, "nonstopmode")) { + interactionoption = 1; + } else if (STREQ (optarg, "scrollmode")) { + interactionoption = 2; + } else if (STREQ (optarg, "errorstopmode")) { + interactionoption = 3; + } else { + WARNING1 ("Ignoring unknown argument `%s' to --interaction", optarg); + } + + } else if (ARGUMENT_IS("help")) { + usagehelp(LUATEX_IHELP, BUG_ADDRESS); + + } else if (ARGUMENT_IS("version")) { + char *versions; + initversionstring(&versions); + print_version_banner(); + + puts( +"\n\nLuaTeX merges and builds upon (parts of) the code from these projects:\n\n" +"tex by Donald Knuth\n" +"etex by Peter Breitenlohner, Phil Taylor and friends\n" +"omega by John Plaice and Yannis Haralambous\n" +"aleph by Giuseppe Bilotta\n" +"pdftex by Han The Thanh and friends\n" +"kpathsea by Karl Berry, Olaf Weber and others\n" +"lua by Roberto Ierusalimschy, Waldemar Celes,\n" +" Luiz Henrique de Figueiredo\n" +"metapost by John Hobby, Taco Hoekwater and friends.\n" +"xpdf by Derek Noonberg (partial)\n" +"fontforge by George Williams (partial)\n\n" +"Some extensions to lua and additional lua libraries are used, as well as\n" +"libraries for graphic inclusion. More details can be found in the source.\n" +"Code development was sponsored by a grant from Colorado State University\n" +"via the 'oriental tex' project, the TeX User Groups, and donations.\n\n" +"The LuaTeX team is Hans Hagen, Hartmut Henkel, Taco Hoekwater.\n\n" +"There is NO warranty. Redistribution of this software is covered by\n" +"the terms of the GNU General Public License, version 2. For more\n" +"information about these matters, see the file named COPYING and\n" +"the LuaTeX source.\n\n" +"Copyright 2008 Taco Hoekwater, the LuaTeX Team.\n"); + + puts(versions); + uexit(0); + } + } + /* attempt to find dump_name */ + if (argv[optind] && argv[optind][0] == '&') { + dump_name = strdup(argv[optind] + 1); + } else if (argv[optind] && argv[optind][0] != '\\') { + if (argv[optind][0] == '*') { + input_name = strdup(argv[optind] + 1); + } else { + firstfile = strdup(argv[optind]); + if (lua_only) { + startup_filename = firstfile; + } else { + if ((strstr(firstfile,".lua") == firstfile+strlen(firstfile)-4) || + (strstr(firstfile,".luc") == firstfile+strlen(firstfile)-4) || + (strstr(firstfile,".LUA") == firstfile+strlen(firstfile)-4) || + (strstr(firstfile,".LUC") == firstfile+strlen(firstfile)-4) || + (strstr(argv[0],"luatexlua") != NULL) || + (strstr(argv[0],"texlua") != NULL)) { + startup_filename = firstfile; + lua_only = 1; + lua_offset = optind; + luainit = 1 ; + } else { + input_name = firstfile; + } + } + } + } else { + if ((strstr(argv[0],"luatexlua") != NULL)|| + (strstr(argv[0],"texlua") != NULL)) { + lua_only = 1; + luainit = 1 ; + } + } +} + +/* test for readability */ +#define is_readable(a) (stat(a,&finfo)==0) && S_ISREG(finfo.st_mode) && \ + (f=fopen(a,"r")) != NULL && !fclose(f) + +char * +find_filename(char *name, char *envkey) +{ + struct stat finfo; + char *dirname = NULL; + char *filename = NULL; + FILE *f; + if (is_readable(name)) { + return name; + } else { + dirname = getenv(envkey); + if ((dirname != NULL) && strlen(dirname)) { + dirname = strdup(getenv(envkey)); + if (*(dirname + strlen(dirname) - 1) == '/') { + *(dirname + strlen(dirname) - 1) = 0; + } + filename = xmalloc(strlen(dirname) + strlen(name) + 2); + filename = concat3(dirname, "/", name); + if (is_readable(filename)) { + xfree(dirname); + return filename; + } + xfree(filename); + } + } + return NULL; +} + + +void +init_kpse (void) { + + if (!user_progname) { + user_progname = dump_name; + } else if (!dump_name) { + dump_name = user_progname; + } + if (!user_progname) { + if (ini_version) { + user_progname = input_name; + } else { + if(!startup_filename) { + if (!dump_name) { + dump_name = strdup(argv[0]); + user_progname = dump_name; + } + } + } + } + if (!user_progname) { + fprintf(stdout, + "kpathsea mode needs a --progname or --fmt switch\n"); + exit(1); + } + kpse_set_program_name(argv[0], user_progname); + program_name_set=1; +} + +void +fix_dumpname (void) { + int dist; + if (dump_name) { + /* adjust array for Pascal and provide extension, if needed */ + dist = strlen(dump_name) - strlen(DUMP_EXT); + if (strstr(dump_name, DUMP_EXT) == dump_name + dist) + DUMP_VAR = concat(" ", dump_name); + else + DUMP_VAR = concat3(" ", dump_name, DUMP_EXT); + DUMP_LENGTH_VAR = strlen(DUMP_VAR + 1); + } else { + /* For dump_name to be NULL is a bug. */ + if (!ini_version) + abort(); + } +} + +void +lua_initialize(int ac, char **av) +{ + + char *given_file = NULL; + int kpse_init; + int tex_table_id; + int pdf_table_id; + int token_table_id; + int node_table_id; + /* Save to pass along to topenin. */ + argc = ac; + argv = av; + + ptexbanner = BANNER; + program_invocation_name = argv[0]; + + /* be 'luac' */ + if (argc>1 && + (STREQ(argv[0],"texluac") || + STREQ(argv[1],"--luaconly") || + STREQ(argv[1],"--luac"))) { + exit(luac_main(ac,av)); + } + + /* Must be initialized before options are parsed. */ + interactionoption = 4; + dump_name = NULL; + /* parse commandline */ + parse_options(ac, av); + + /* make sure that the locale is 'sane' (for lua) */ + putenv("LC_CTYPE=C"); + putenv("LC_COLLATE=C"); + putenv("LC_NUMERIC=C"); + + /* this is sometimes needed */ + putenv("engine=luatex"); + + luainterpreter(0); + + prepare_cmdline(Luas[0], argv, argc, lua_offset); /* collect arguments */ + + if (startup_filename != NULL) { + given_file = xstrdup(startup_filename); + startup_filename = find_filename(startup_filename, "LUATEXDIR"); + } + /* now run the file */ + if (startup_filename != NULL) { + /* hide the 'tex' and 'pdf' table */ + tex_table_id = hide_lua_table(Luas[0], "tex"); + token_table_id = hide_lua_table(Luas[0], "token"); + node_table_id = hide_lua_table(Luas[0], "node"); + pdf_table_id = hide_lua_table(Luas[0], "pdf"); + + if (luaL_loadfile(Luas[0], startup_filename)) { + fprintf(stdout, "%s\n",lua_tostring(Luas[0], -1)); + exit(1); + } + if (lua_pcall(Luas[0], 0, 0, 0)) { + fprintf(stdout, "%s\n",lua_tostring(Luas[0], -1)); + exit(1); + } + /* no filename? quit now! */ + if (!input_name) { + get_lua_string("texconfig", "jobname", &input_name); + } + if (!dump_name) { + get_lua_string("texconfig", "formatname", &dump_name); + } + if ((lua_only) || ((!input_name) && (!dump_name))) { + exit(0); + } + /* unhide the 'tex' and 'pdf' table */ + unhide_lua_table(Luas[0], "tex", tex_table_id); + unhide_lua_table(Luas[0], "pdf", pdf_table_id); + unhide_lua_table(Luas[0], "token", token_table_id); + unhide_lua_table(Luas[0], "node", node_table_id); + + /* kpse_init */ + kpse_init = -1; + get_lua_boolean("texconfig", "kpse_init", &kpse_init); + + if (kpse_init != 0) { + init_kpse(); + } + /* prohibit_file_trace (boolean) */ + tracefilenames = 1; + get_lua_boolean("texconfig", "trace_file_names", &tracefilenames); + + /* src_special_xx */ + insertsrcspecialauto = insertsrcspecialeverypar = + insertsrcspecialeveryparend = insertsrcspecialeverycr = + insertsrcspecialeverymath = insertsrcspecialeveryhbox = + insertsrcspecialeveryvbox = insertsrcspecialeverydisplay = + false; + get_lua_boolean("texconfig", "src_special_auto", + &insertsrcspecialauto); + get_lua_boolean("texconfig", "src_special_everypar", + &insertsrcspecialeverypar); + get_lua_boolean("texconfig", "src_special_everyparend", + &insertsrcspecialeveryparend); + get_lua_boolean("texconfig", "src_special_everycr", + &insertsrcspecialeverycr); + get_lua_boolean("texconfig", "src_special_everymath", + &insertsrcspecialeverymath); + get_lua_boolean("texconfig", "src_special_everyhbox", + &insertsrcspecialeveryhbox); + get_lua_boolean("texconfig", "src_special_everyvbox", + &insertsrcspecialeveryvbox); + get_lua_boolean("texconfig", "src_special_everydisplay", + &insertsrcspecialeverydisplay); + + srcspecialsp = insertsrcspecialauto | insertsrcspecialeverypar | + insertsrcspecialeveryparend | insertsrcspecialeverycr | + insertsrcspecialeverymath | insertsrcspecialeveryhbox | + insertsrcspecialeveryvbox | insertsrcspecialeverydisplay; + + /* file_line_error */ + filelineerrorstylep = false; + get_lua_boolean("texconfig", "file_line_error", + &filelineerrorstylep); + + /* halt_on_error */ + haltonerrorp = false; + get_lua_boolean("texconfig", "halt_on_error", &haltonerrorp); + + fix_dumpname(); + } else { + if (luainit) { + if (given_file) { + fprintf(stdout, "%s file %s not found\n", (lua_only ? "Script" : "Configuration"), given_file); + } else { + fprintf(stdout, "No %s file given\n", (lua_only ? "script" : "configuration")); + } + exit(1); + } else { + /* init */ + init_kpse(); + fix_dumpname(); + } + } +} diff --git a/Build/source/texk/web2c/luatexdir/lua/luanode.c b/Build/source/texk/web2c/luatexdir/lua/luanode.c new file mode 100644 index 00000000000..17c8e7be8e2 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/luanode.c @@ -0,0 +1,200 @@ +/* $Id: luanode.c 1013 2008-02-14 00:09:02Z oneiros $ */ + +#include "luatex-api.h" +#include +#include "nodes.h" + +#undef link /* defined by cpascal.h */ +#define info(a) fixmem[(a)].hhlh +#define link(a) fixmem[(a)].hhrh + + +static char *group_code_names[] = { + "", + "simple", + "hbox", + "adjusted_hbox", + "vbox", + "vtop", + "align", + "no_align", + "output", + "math", + "disc", + "insert", + "vcenter", + "math_choice", + "semi_simple", + "math_shift", + "math_left", + "local_box" , + "split_off", + "split_keep", + "preamble", + "align_set", + "fin_row"}; + +char *pack_type_name[] = { "exactly", "additional"}; + + +void +lua_node_filter_s (int filterid, char *extrainfo, halfword head_node, halfword *tail_node) { + halfword ret; + int a; + lua_State *L = Luas[0]; + int callback_id = callback_defined(filterid); + if (head_node==null || vlink(head_node)==null || callback_id==0) + return; + lua_rawgeti(L,LUA_REGISTRYINDEX,callback_callbacks_id); + lua_rawgeti(L,-1, callback_id); + if (!lua_isfunction(L,-1)) { + lua_pop(L,2); + return; + } + nodelist_to_lua(L,vlink(head_node)); /* arg 1 */ + lua_pushstring(L,extrainfo); /* arg 2 */ + if (lua_pcall(L,2,1,0) != 0) { /* no arg, 1 result */ + fprintf(stdout,"error: %s\n",lua_tostring(L,-1)); + lua_pop(L,2); + error(); + return; + } + if (lua_isboolean(L,-1)) { + if (lua_toboolean(L,-1)!=1) { + flush_node_list(vlink(head_node)); + vlink(head_node) = null; + } + } else { + a = nodelist_from_lua(L); + vlink(head_node)= a; + } + lua_pop(L,2); /* result and callback container table */ + if (fix_node_lists) + fix_node_list(head_node); + ret = vlink(head_node); + if (ret!=null) { + while (vlink(ret)!=null) + ret=vlink(ret); + *tail_node=ret; + } else { + *tail_node=head_node; + } + return ; +} + +void +lua_node_filter (int filterid, int extrainfo, halfword head_node, halfword *tail_node) { + lua_node_filter_s(filterid, group_code_names[extrainfo], head_node, tail_node); + return ; +} + + + +halfword +lua_hpack_filter (halfword head_node, scaled size, int pack_type, int extrainfo) { + halfword ret; + lua_State *L = Luas[0]; + int callback_id = callback_defined(hpack_filter_callback); + if (head_node==null || callback_id == 0) + return head_node; + lua_rawgeti(L,LUA_REGISTRYINDEX,callback_callbacks_id); + lua_rawgeti(L,-1, callback_id); + if (!lua_isfunction(L,-1)) { + lua_pop(L,2); + return head_node; + } + + nodelist_to_lua(L,head_node); + lua_pushstring(L,group_code_names[extrainfo]); + lua_pushnumber(L,size); + lua_pushstring(L,pack_type_name[pack_type]); + if (lua_pcall(L,4,1,0) != 0) { /* no arg, 1 result */ + fprintf(stdout,"error: %s\n",lua_tostring(L,-1)); + lua_pop(L,2); + error(); + return head_node; + } + ret = head_node; + if (lua_isboolean(L,-1)) { + if (lua_toboolean(L,-1)!=1) { + flush_node_list(head_node); + ret = null; + } + } else { + ret = nodelist_from_lua(L); + } + lua_pop(L,2); /* result and callback container table */ + /* lua_gc(L,LUA_GCSTEP, LUA_GC_STEP_SIZE);*/ + if (fix_node_lists) + fix_node_list(ret); + return ret; +} + +halfword +lua_vpack_filter (halfword head_node, scaled size, int pack_type, scaled maxd, int extrainfo) { + halfword ret; + integer callback_id ; + lua_State *L = Luas[0]; + if (head_node==null) + return head_node; + if (strcmp("output",group_code_names[extrainfo])==0) { + callback_id = callback_defined(pre_output_filter_callback); + } else { + callback_id = callback_defined(vpack_filter_callback); + } + if (callback_id==0) { + return head_node; + } + lua_rawgeti(L,LUA_REGISTRYINDEX,callback_callbacks_id); + lua_rawgeti(L,-1, callback_id); + if (!lua_isfunction(L,-1)) { + lua_pop(L,2); + return head_node; + } + nodelist_to_lua(L,head_node); + lua_pushstring(L,group_code_names[extrainfo]); + lua_pushnumber(L,size); + lua_pushstring(L,pack_type_name[pack_type]); + lua_pushnumber(L,maxd); + if (lua_pcall(L,5,1,0) != 0) { /* no arg, 1 result */ + fprintf(stdout,"error: %s\n",lua_tostring(L,-1)); + lua_pop(L,2); + error(); + return head_node; + } + ret = head_node; + if (lua_isboolean(L,-1)) { + if (lua_toboolean(L,-1)!=1) { + flush_node_list(head_node); + ret = null; + } + } else { + ret = nodelist_from_lua(L); + } + lua_pop(L,2); /* result and callback container table */ + /* lua_gc(L,LUA_GCSTEP, LUA_GC_STEP_SIZE);*/ + if (fix_node_lists) + fix_node_list(ret); + return ret; +} + + +/* This is a quick hack to fix etex's \lastnodetype now that + * there are many more visible node types. TODO: check the + * eTeX manual for the expected return values. + */ + +int +visible_last_node_type (int n) { + int i = type(n); + if ((i!=math_node) && (i<=unset_node)) + return i+1; + if (i==glyph_node) + return -1; + if (i==whatsit_node && subtype(n)==local_par_node) + return -1; + if (i==255) + return -1 ; /* this is not right, probably dir nodes! */ + return last_known_node +1 ; +} + diff --git a/Build/source/texk/web2c/luatexdir/lua/luastuff.c b/Build/source/texk/web2c/luatexdir/lua/luastuff.c new file mode 100644 index 00000000000..f48bfdb0171 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/luastuff.c @@ -0,0 +1,310 @@ +/* $Id: luastuff.c 1079 2008-03-05 15:34:41Z taco $ */ + +#include "luatex-api.h" +#include + +lua_State *Luas[65536]; + +extern char *startup_filename; +extern int safer_option; + +int luastate_max = 0; +int luastate_bytes = 0; + +void +make_table (lua_State *L, char *tab, char *getfunc, char *setfunc) { + /* make the table */ /* [{}] */ + lua_pushstring(L,tab); /* [{},"dimen"] */ + lua_newtable(L); /* [{},"dimen",{}] */ + lua_settable(L, -3); /* [{}] */ + /* fetch it back */ + lua_pushstring(L,tab); /* [{},"dimen"] */ + lua_gettable(L, -2); /* [{},{}] */ + /* make the meta entries */ + luaL_newmetatable(L,tab); /* [{},{},{}] */ + lua_pushstring(L, "__index"); /* [{},{},{},"__index"] */ + lua_pushstring(L, getfunc); /* [{},{},{},"__index","getdimen"] */ + lua_gettable(L, -5); /* [{},{},{},"__index",] */ + lua_settable(L, -3); /* [{},{},{}] */ + lua_pushstring(L, "__newindex");/* [{},{},{},"__newindex"] */ + lua_pushstring(L, setfunc); /* [{},{},{},"__newindex","setdimen"] */ + lua_gettable(L, -5); /* [{},{},{},"__newindex",] */ + lua_settable(L, -3); /* [{},{},{}] */ + lua_setmetatable(L,-2); /* [{},{}] : assign the metatable */ + lua_pop(L,1); /* [{}] : clean the stack */ +} + +static +const char *getS(lua_State * L, void *ud, size_t * size) { + LoadS *ls = (LoadS *) ud; + (void) L; + if (ls->size == 0) + return NULL; + *size = ls->size; + ls->size = 0; + return ls->s; +} + +void *my_luaalloc (void *ud, void *ptr, size_t osize, size_t nsize) { + void *ret = NULL; + if (nsize == 0) + free(ptr); + else + ret = realloc(ptr, nsize); + luastate_bytes += (nsize-osize); + return ret; +} + +static int my_luapanic (lua_State *L) { + (void)L; /* to avoid warnings */ + fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n", + lua_tostring(L, -1)); + return 0; +} + + +void +luainterpreter (int n) { + lua_State *L; + L = lua_newstate(my_luaalloc, NULL); + if (L==NULL) { + fprintf(stderr,"Can't create a new Lua state (%d).",n); + return; + } + lua_atpanic(L, &my_luapanic); + + luastate_max++; + luaL_openlibs(L); + + open_oslibext(L,safer_option); + + lua_getglobal(L,"package"); + lua_pushstring(L,""); + lua_setfield(L,-2,"cpath"); + lua_pop(L,1); /* pop the table */ + + /*luaopen_unicode(L);*/ + lua_pushcfunction(L, luaopen_unicode); + lua_pushstring(L, "unicode"); + lua_call(L, 1, 0); + + /*luaopen_zip(L);*/ + lua_pushcfunction(L, luaopen_zip); + lua_pushstring(L, "zip"); + lua_call(L, 1, 0); + + /*luaopen_lpeg(L);*/ + lua_pushcfunction(L, luaopen_lpeg); + lua_pushstring(L, "lpeg"); + lua_call(L, 1, 0); + + /*luaopen_md5(L);*/ + lua_pushcfunction(L, luaopen_md5); + lua_pushstring(L, "md5"); + lua_call(L, 1, 0); + + /*luaopen_lfs(L);*/ + lua_pushcfunction(L, luaopen_lfs); + lua_pushstring(L, "lfs"); + lua_call(L, 1, 0); + + /* zlib. slightly odd calling convention */ + luaopen_zlib(L); + lua_setglobal(L,"zlib"); + luaopen_gzip(L); + /* fontforge */ + luaopen_ff(L); + + luaopen_pdf(L); + luaopen_tex(L); + luaopen_token(L); + luaopen_node(L); + luaopen_texio(L); + luaopen_kpse(L); + if (n==0) { + luaopen_callback(L); + lua_createtable(L, 0, 0); + lua_setglobal(L, "texconfig"); + } + luaopen_lua(L,n,startup_filename); + luaopen_stats(L); + luaopen_font(L); + luaopen_lang(L); + + /* luaopen_img(L); */ + lua_pushcfunction(L, luaopen_img); + lua_pushstring(L, "img"); + lua_call(L, 1, 0); + + luaopen_mp(L); + + if (safer_option) { + /* disable some stuff if --safer */ + (void)hide_lua_value(L, "os","execute"); + (void)hide_lua_value(L, "os","rename"); + (void)hide_lua_value(L, "os","remove"); + (void)hide_lua_value(L, "io","popen"); + /* make io.open only read files */ + luaL_checkstack(L,2,"out of stack space"); + lua_getglobal(L,"io"); + lua_getfield(L,-1,"open_ro"); + lua_setfield(L,-2,"open"); + (void)hide_lua_value(L, "io","tmpfile"); + (void)hide_lua_value(L, "io","output"); + (void)hide_lua_value(L, "lfs","chdir"); + (void)hide_lua_value(L, "lfs","lock"); + (void)hide_lua_value(L, "lfs","touch"); + (void)hide_lua_value(L, "lfs","rmdir"); + (void)hide_lua_value(L, "lfs","mkdir"); + } + Luas[n] = L; +} + +int hide_lua_table(lua_State *L, char *name) { + int r=0; + lua_getglobal(L,name); + if(lua_istable(L,-1)) { + r = luaL_ref(L,LUA_REGISTRYINDEX); + lua_pushnil(L); + lua_setglobal(L,name); + } + return r; +} + +void unhide_lua_table(lua_State *L, char *name, int r) { + lua_rawgeti(L,LUA_REGISTRYINDEX,r); + lua_setglobal(L,name); + luaL_unref(L,LUA_REGISTRYINDEX,r); +} + +int hide_lua_value(lua_State *L, char *name, char *item) { + int r=0; + lua_getglobal(L,name); + if(lua_istable(L,-1)) { + lua_getfield(L,-1,item); + r = luaL_ref(L,LUA_REGISTRYINDEX); + lua_pushnil(L); + lua_setfield(L,-2,item); + } + return r; +} + +void unhide_lua_value(lua_State *L, char *name, char *item, int r) { + lua_getglobal(L,name); + if(lua_istable(L,-1)) { + lua_rawgeti(L,LUA_REGISTRYINDEX,r); + lua_setfield(L,-2,item); + luaL_unref(L,LUA_REGISTRYINDEX,r); + } +} + + +void +luacall(int n, int s) { + LoadS ls; + int i ; + char lua_id[12]; + if (Luas[n] == NULL) { + luainterpreter(n); + } + luatex_load_init(s,&ls); + if (ls.size>0) { + snprintf((char *)lua_id,12,"luas[%d]",n); + i = lua_load(Luas[n], getS, &ls, lua_id); + if (i != 0) { + Luas[n] = luatex_error(Luas[n],(i == LUA_ERRSYNTAX ? 0 : 1)); + } else { + i = lua_pcall(Luas[n], 0, 0, 0); + if (i != 0) { + Luas[n] = luatex_error(Luas[n],(i == LUA_ERRRUN ? 0 : 1)); + } + } + } +} + +void +luatokencall(int n, int p) { + LoadS ls; + int i, l; + char *s=NULL; + char lua_id[12]; + if (Luas[n] == NULL) { + luainterpreter(n); + } + l = 0; + s = tokenlist_to_cstring(p,1,&l); + ls.s = s; + ls.size = l; + if (ls.size>0) { + snprintf((char *)lua_id,12,"luas[%d]",n); + i = lua_load(Luas[n], getS, &ls, lua_id); + xfree(s); + if (i != 0) { + Luas[n] = luatex_error(Luas[n],(i == LUA_ERRSYNTAX ? 0 : 1)); + } else { + i = lua_pcall(Luas[n], 0, 0, 0); + if (i != 0) { + Luas[n] = luatex_error(Luas[n],(i == LUA_ERRRUN ? 0 : 1)); + } + } + } +} + + + +void +closelua(int n) { + if (n!=0 && Luas[n] != NULL) { + lua_close(Luas[n]); + luastate_max--; + Luas[n] = NULL; + } +} + + +void +luatex_load_init (int s, LoadS *ls) { + ls->s = (const char *)&(str_pool[str_start[s]]); + ls->size = str_start[s + 1] - str_start[s]; +} + +lua_State * +luatex_error (lua_State * L, int is_fatal) { + + size_t len; + char *err; + strnumber s; + const char *luaerr = lua_tolstring(L, -1,&len); + err = (char *)xmalloc(len+1); + len = snprintf(err,(len+1),"%s",luaerr); + if (is_fatal>0) { + /* Normally a memory error from lua. + The pool may overflow during the maketexlstring(), but we + are crashing anyway so we may as well abort on the pool size */ + s = maketexlstring(err, len); + lua_fatal_error(s); + /* never reached */ + xfree (err); + lua_close(L); + luastate_max--; + return (lua_State *)NULL; + } else { + /* Here, the pool could be full already, but we can possibly escape from that + * condition, since the lua chunk that caused the error is the current string. + */ + s = str_ptr-0x200000; + /* fprintf(stderr,"poolinfo: %d: %d,%d out of %d\n",s,pool_ptr,str_start[(s-1)],pool_size);*/ + pool_ptr = str_start[(s-1)]; + str_start[s] = pool_ptr; + if (pool_ptr+len>=pool_size) { + lua_norm_error(' '); + } else { + s = maketexlstring(err,len); + lua_norm_error(s); + flush_str(s); + } + xfree (err); + return L; + } +} + diff --git a/Build/source/texk/web2c/luatexdir/lua/luatex.c b/Build/source/texk/web2c/luatexdir/lua/luatex.c new file mode 100644 index 00000000000..5172ca24292 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/luatex.c @@ -0,0 +1,343 @@ +/* $Id: luatex.c 1013 2008-02-14 00:09:02Z oneiros $ */ + +#include "luatex-api.h" +#include +#include + +/* do this aleph stuff here, for now */ + +void +b_test_in(void) +{ + string fname = kpse_find_file ((char *)(nameoffile + 1), + kpse_program_binary_format, true); + + if (fname) { + libcfree(nameoffile); + nameoffile = xmalloc(2+strlen(fname)); + namelength = strlen(fname); + strcpy((char *)nameoffile+1, fname); + } + else { + libcfree(nameoffile); + nameoffile = xmalloc(2); + namelength = 0; + nameoffile[0] = 0; + nameoffile[1] = 0; + } +} + + +int **ocp_tables; +static int ocp_entries = 0; + +void +allocate_ocp_table P2C(int, ocp_number, int, ocp_size) +{ + int i; + if (ocp_entries==0) { + ocp_tables = (int **) xmalloc(256*sizeof(int**)); + ocp_entries=256; + } else if ((ocp_number==256)&&(ocp_entries==256)) { + ocp_tables = xrealloc(ocp_tables, 65536); + ocp_entries=65536; + } + ocp_tables[ocp_number] = + (int *) xmalloc((1+ocp_size)*sizeof(int)); + ocp_tables[ocp_number][0] = ocp_size; + for (i=1; i<=ocp_size; i++) { + ocp_tables[ocp_number][i] = 0; + } +} + +void +dump_ocp_table P1C(int, ocp_number) +{ + dump_things(ocp_tables[ocp_number][0], ocp_tables[ocp_number][0]+1); +} + +void +undump_ocp_table P1C(int, ocp_number) +{ + int sizeword; + if (ocp_entries==0) { + ocp_tables = (int **) xmalloc(256*sizeof(int**)); + ocp_entries=256; + } else if ((ocp_number==256)&&(ocp_entries==256)) { + ocp_tables = xrealloc(ocp_tables, 65536); + ocp_entries=65536; + } + undump_things(sizeword,1); + ocp_tables[ocp_number] = + (int *) xmalloc((1+sizeword)*sizeof(int)); + ocp_tables[ocp_number][0] = sizeword; + undump_things(ocp_tables[ocp_number][1], sizeword); +} + + +void +run_external_ocp P1C(string, external_ocp_name) +{ + char *in_file_name; + char *out_file_name; + FILE *in_file; + FILE *out_file; + char command_line[400]; + int i; + unsigned c; + int c_in; +#ifdef WIN32 + char *tempenv; + +#define null_string(s) ((s == NULL) || (*s == '\0')) + + tempenv = getenv("TMPDIR"); + if (null_string(tempenv)) + tempenv = getenv("TEMP"); + if (null_string(tempenv)) + tempenv = getenv("TMP"); + if (null_string(tempenv)) + tempenv = "c:/tmp"; /* "/tmp" is not good if we are on a CD-ROM */ + in_file_name = concat(tempenv, "/__aleph__in__XXXXXX"); + mktemp(in_file_name); +#else + in_file_name = strdup("/tmp/__aleph__in__XXXXXX"); + mkstemp(in_file_name); +#endif /* WIN32 */ + + in_file = fopen(in_file_name, FOPEN_WBIN_MODE); + + for (i=1; i<=otp_input_end; i++) { + c = otp_input_buf[i]; + if (c>0xffff) { + fprintf(stderr, "Aleph does not currently support 31-bit chars\n"); + exit(1); + } + if (c>0x4000000) { + fputc(0xfc | ((c>>30) & 0x1), in_file); + fputc(0x80 | ((c>>24) & 0x3f), in_file); + fputc(0x80 | ((c>>18) & 0x3f), in_file); + fputc(0x80 | ((c>>12) & 0x3f), in_file); + fputc(0x80 | ((c>>6) & 0x3f), in_file); + fputc(0x80 | (c & 0x3f), in_file); + } else if (c>0x200000) { + fputc(0xf8 | ((c>>24) & 0x3), in_file); + fputc(0x80 | ((c>>18) & 0x3f), in_file); + fputc(0x80 | ((c>>12) & 0x3f), in_file); + fputc(0x80 | ((c>>6) & 0x3f), in_file); + fputc(0x80 | (c & 0x3f), in_file); + } else if (c>0x10000) { + fputc(0xf0 | ((c>>18) & 0x7), in_file); + fputc(0x80 | ((c>>12) & 0x3f), in_file); + fputc(0x80 | ((c>>6) & 0x3f), in_file); + fputc(0x80 | (c & 0x3f), in_file); + } else if (c>0x800) { + fputc(0xe0 | ((c>>12) & 0xf), in_file); + fputc(0x80 | ((c>>6) & 0x3f), in_file); + fputc(0x80 | (c & 0x3f), in_file); + } else if (c>0x80) { + fputc(0xc0 | ((c>>6) & 0x1f), in_file); + fputc(0x80 | (c & 0x3f), in_file); + } else { + fputc(c & 0x7f, in_file); + } + } + fclose(in_file); + +#define advance_cin if ((c_in = fgetc(out_file)) == -1) { \ + fprintf(stderr, "File contains bad char\n"); \ + goto end_of_while; \ + } + +#ifdef WIN32 + out_file_name = concat(tempenv, "/__aleph__out__XXXXXX"); + mktemp(out_file_name); +#else + out_file_name = strdup("/tmp/__aleph__out__XXXXXX"); + mkstemp(out_file_name); +#endif + + sprintf(command_line, "%s <%s >%s\n", + external_ocp_name+1, in_file_name, out_file_name); + system(command_line); + out_file = fopen(out_file_name, FOPEN_RBIN_MODE); + otp_output_end = 0; + otp_output_buf[otp_output_end] = 0; + while ((c_in = fgetc(out_file)) != -1) { + if (c_in>=0xfc) { + c = (c_in & 0x1) << 30; + {advance_cin} + c |= (c_in & 0x3f) << 24; + {advance_cin} + c |= (c_in & 0x3f) << 18; + {advance_cin} + c |= (c_in & 0x3f) << 12; + {advance_cin} + c |= (c_in & 0x3f) << 6; + {advance_cin} + c |= c_in & 0x3f; + } else if (c_in>=0xf8) { + c = (c_in & 0x3) << 24; + {advance_cin} + c |= (c_in & 0x3f) << 18; + {advance_cin} + c |= (c_in & 0x3f) << 12; + {advance_cin} + c |= (c_in & 0x3f) << 6; + {advance_cin} + c |= c_in & 0x3f; + } else if (c_in>=0xf0) { + c = (c_in & 0x7) << 18; + {advance_cin} + c |= (c_in & 0x3f) << 12; + {advance_cin} + c |= (c_in & 0x3f) << 6; + {advance_cin} + c |= c_in & 0x3f; + } else if (c_in>=0xe0) { + c = (c_in & 0xf) << 12; + {advance_cin} + c |= (c_in & 0x3f) << 6; + {advance_cin} + c |= c_in & 0x3f; + } else if (c_in>=0x80) { + c = (c_in & 0x1f) << 6; + {advance_cin} + c |= c_in & 0x3f; + } else { + c = c_in & 0x7f; + } + otp_output_buf[++otp_output_end] = c; + } + +end_of_while: + remove(in_file_name); + remove(out_file_name); +} + +/* Read and write dump files through zlib */ + +/* Earlier versions recast *f from FILE * to gzFile, but there is + * no guarantee that these have the same size, so a static variable + * is needed. + */ + +static gzFile gz_fmtfile = NULL; + +void +do_zdump (char *p, int item_size, int nitems, FILE *out_file) +{ + int err; + if (nitems==0) + return; + if (gzwrite (gz_fmtfile,(void *)p, item_size*nitems) != item_size*nitems) + { + fprintf (stderr, "! Could not write %d %d-byte item(s): %s.\n", + nitems, item_size, gzerror(gz_fmtfile,&err)); + uexit (1); + } +} + +void +do_zundump (char *p, int item_size, int nitems, FILE *in_file) +{ + int err; + if (nitems==0) + return; + if (gzread (gz_fmtfile,(void *)p, item_size*nitems) <= 0) + { + fprintf (stderr, "Could not undump %d %d-byte item(s): %s.\n", + nitems, item_size, gzerror(gz_fmtfile,&err)); + uexit (1); + } +} + +#define COMPRESSION "R3" + +boolean +zopen_w_input (FILE **f, int format, const_string fopen_mode) { + int callbackid; + int res; + char *fnam; + callbackid = callback_defined(find_format_file_callback); + if (callbackid>0) { + res = run_callback(callbackid,"S->S",(nameoffile+1),&fnam); + if (res && fnam && strlen(fnam)>0) { + xfree (nameoffile); + nameoffile = xmalloc (strlen(fnam)+2); + memcpy((nameoffile+1),fnam,strlen(fnam)); + *(nameoffile+strlen(fnam)+1)=0; + *f = xfopen(fnam,fopen_mode); + if (*f == NULL) { + return 0; + } + } else { + return 0; + } + } else { + res = open_input(f,format,fopen_mode); + } + if (res) { + gz_fmtfile = gzdopen(fileno(*f),"rb" COMPRESSION); + } + return res; +} + +boolean +zopen_w_output (FILE **f, const_string fopen_mode) { + int res = 1; + if (luainit) { + *f = fopen((nameoffile+1),fopen_mode); + if (*f == NULL) { + return 0; + } + } else { + res = open_output(f,fopen_mode); + } + if (res) { + gz_fmtfile = gzdopen(fileno(*f),"wb" COMPRESSION); + } + return res; +} + +void +zwclose (FILE *f) { + gzclose(gz_fmtfile); +} + +/* create the dvi or pdf file */ + +int +open_outfile(FILE **f, char *name, char *mode) { + FILE *res; + res = fopen(name,mode); + if (res != NULL) { + *f = res; + return 1; + } + return 0; +} + + +/* the caller sets tfm_buffer=NULL and tfm_size=0 */ + +int +readbinfile (FILE *f, unsigned char **tfm_buffer, integer *tfm_size) { + void *buf; + int size; + if (fseek(f, 0, SEEK_END)==0) { + size = ftell(f); + if (size>0) { + buf = xmalloc(size); + if(fseek(f, 0, SEEK_SET)==0) { + if(fread((void *)buf,size,1,f)==1) { + *tfm_buffer=(unsigned char *)buf; + *tfm_size=(integer)size; + return 1; + } + } + } + } /* seek failed, or zero-sized file */ + return 0; +} + diff --git a/Build/source/texk/web2c/luatexdir/lua/luatoken.c b/Build/source/texk/web2c/luatexdir/lua/luatoken.c new file mode 100644 index 00000000000..23d9ca82150 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/luatoken.c @@ -0,0 +1,548 @@ +/* $Id: luatoken.c 1013 2008-02-14 00:09:02Z oneiros $ */ + +#include "luatex-api.h" +#include + +#include "tokens.h" + +command_item command_names[] = + { { "relax", 0, NULL }, + { "left_brace", 0 , NULL }, + { "right_brace", 0 , NULL }, + { "math_shift", 0 , NULL }, + { "tab_mark", 0 , NULL }, + { "car_ret", 0 , NULL }, + { "mac_param", 0 , NULL }, + { "sup_mark", 0 , NULL }, + { "sub_mark", 0 , NULL }, + { "endv", 0 , NULL }, + { "spacer", 0 , NULL }, + { "letter", 0 , NULL }, + { "other_char", 0 , NULL }, + { "par_end", 0 , NULL }, + { "stop", 0 , NULL }, + { "delim_num", 0 , NULL }, + { "char_num", 0 , NULL }, + { "math_char_num", 0 , NULL }, + { "mark", 0 , NULL }, + { "xray", 0 , NULL }, + { "make_box", 0 , NULL }, + { "hmove", 0 , NULL }, + { "vmove", 0 , NULL }, + { "un_hbox", 0 , NULL }, + { "un_vbox", 0 , NULL }, + { "remove_item", 0 , NULL }, + { "hskip", 0 , NULL }, + { "vskip", 0 , NULL }, + { "mskip", 0 , NULL }, + { "kern", 0 , NULL }, + { "mkern", 0 , NULL }, + { "leader_ship", 0 , NULL }, + { "halign", 0 , NULL }, + { "valign", 0 , NULL }, + { "no_align", 0 , NULL }, + { "vrule", 0 , NULL }, + { "hrule", 0 , NULL }, + { "insert", 0 , NULL }, + { "vadjust", 0 , NULL }, + { "ignore_spaces", 0 , NULL }, + { "after_assignment", 0 , NULL }, + { "after_group", 0 , NULL }, + { "break_penalty", 0 , NULL }, + { "start_par", 0 , NULL }, + { "ital_corr", 0 , NULL }, + { "accent", 0 , NULL }, + { "math_accent", 0 , NULL }, + { "discretionary", 0 , NULL }, + { "eq_no", 0 , NULL }, + { "left_right", 0 , NULL }, + { "math_comp", 0 , NULL }, + { "limit_switch", 0 , NULL }, + { "above", 0 , NULL }, + { "math_style", 0 , NULL }, + { "math_choice", 0 , NULL }, + { "non_script", 0 , NULL }, + { "vcenter", 0 , NULL }, + { "case_shift", 0 , NULL }, + { "message", 0 , NULL }, + { "extension", 0 , NULL }, + { "in_stream", 0 , NULL }, + { "begin_group", 0 , NULL }, + { "end_group", 0 , NULL }, + { "omit", 0 , NULL }, + { "ex_space", 0 , NULL }, + { "no_boundary", 0 , NULL }, + { "radical", 0 , NULL }, + { "end_cs_name", 0 , NULL }, + { "char_ghost", 0 , NULL }, + { "assign_local_box", 0 , NULL }, + { "char_given", 0 , NULL }, + { "math_given", 0 , NULL }, + { "omath_given", 0 , NULL }, + { "last_item", 0 , NULL }, + { "toks_register", 0 , NULL }, + { "assign_toks", 0, NULL }, + { "assign_int", 0, NULL }, + { "assign_dimen", 0 , NULL }, + { "assign_glue", 0 ,NULL }, + { "assign_mu_glue", 0 , NULL }, + { "assign_font_dimen", 0 , NULL }, + { "assign_font_int", 0 , NULL }, + { "set_aux", 0 , NULL }, + { "set_prev_graf", 0 , NULL }, + { "set_page_dimen", 0 , NULL }, + { "set_page_int", 0 , NULL }, + { "set_box_dimen", 0 , NULL }, + { "set_shape", 0, NULL }, + { "def_code", 0 , NULL }, + { "extdef_code", 0 , NULL }, + { "def_family", 0 , NULL }, + { "set_font", 0 , NULL }, + { "def_font", 0 , NULL }, + { "register", 0 , NULL }, + { "assign_box_dir", 0 , NULL }, + { "assign_dir", 0 , NULL }, + { "advance", 0 , NULL }, + { "multiply", 0 , NULL }, + { "divide", 0 , NULL }, + { "prefix", 0 , NULL }, + { "let", 0 , NULL }, /* 100 */ + { "shorthand_def", 0 , NULL }, + { "read_to_cs", 0 , NULL }, + { "def", 0 , NULL }, + { "set_box", 0 , NULL }, + { "hyph_data", 0 , NULL }, + { "set_interaction", 0 , NULL }, + { "letterspace_font", 0 , NULL }, + { "set_ocp", 0 , NULL }, + { "def_ocp", 0 , NULL }, + { "set_ocp_list", 0 , NULL }, /* 110 */ + { "def_ocp_list", 0 , NULL }, + { "clear_ocp_lists", 0 , NULL }, + { "push_ocp_list", 0 , NULL }, + { "pop_ocp_list", 0 , NULL }, + { "ocp_list_op", 0 , NULL }, + { "ocp_trace_level", 0 , NULL}, + { "undefined_cs", 0 , NULL }, + { "expand_after", 0 , NULL }, + { "no_expand", 0 , NULL }, + { "input", 0 , NULL }, /* 120 */ + { "if_test", 0 , NULL }, + { "fi_or_else", 0 , NULL }, + { "cs_name", 0 , NULL }, + { "convert", 0 , NULL }, + { "the", 0 , NULL }, + { "top_bot_mark", 0 , NULL }, + { "call", 0 , NULL }, + { "long_call", 0 , NULL }, + { "outer_call", 0 , NULL }, + { "long_outer_call", 0 , NULL }, /* 130 */ + { "end_template", 0 , NULL }, + { "dont_expand", 0, NULL }, + { "glue_ref", 0 , NULL }, + { "shape_ref", 0 , NULL }, + { "box_ref", 0 , NULL }, + { "data", 0 , NULL }, + { NULL, 0, NULL } }; + + +int get_command_id (char *s) { + int i; + int cmd = -1; + for (i=0;command_names[i].cmd_name != NULL;i++) { + if (strcmp(s,command_names[i].cmd_name) == 0) + break; + } + if (command_names[i].cmd_name!=NULL) { + cmd = i; + } + return cmd; +} + +static int +get_cur_cmd (lua_State *L) { + int r = 0; + cur_cs = 0; + int len = lua_objlen(L,-1); + if (len==3 || len==2) { + r = 1; + lua_rawgeti(L,-1,1); + cur_cmd = lua_tointeger(L,-1); + lua_rawgeti(L,-2,2); + cur_chr = lua_tointeger(L,-1); + if (len==3) { + lua_rawgeti(L,-3,3); + cur_cs = lua_tointeger(L,-1); + } + lua_pop(L,len); + if (cur_cs==0) + cur_tok=(cur_cmd*string_offset)+cur_chr; + else + cur_tok=cs_token_flag+cur_cs; + } + return r; +} + + +static int +token_from_lua (lua_State *L) { + int cmd,chr; + int cs = 0; + int len = lua_objlen(L,-1); + if (len==3 || len==2) { + lua_rawgeti(L,-1,1); + cmd = lua_tointeger(L,-1); + lua_rawgeti(L,-2,2); + chr = lua_tointeger(L,-1); + if (len==3) { + lua_rawgeti(L,-3,3); + cs = lua_tointeger(L,-1); + } + lua_pop(L,len); + if (cs==0) { + return (cmd*string_offset)+chr; + } else { + return cs_token_flag+cs; + } + } + return -1; +} + +static int +get_cur_cs (lua_State *L) { + char *s; + unsigned j; + size_t l; + integer cs; + int save_nncs; + int ret; + ret = 0; + cur_cs = 0; + lua_getfield(L,-1,"name"); + if (lua_isstring(L,-1)) { + s = (char *)lua_tolstring(L,-1,&l); + if (l>0) { + if (last+l>buf_size) + check_buffer_overflow(last+l); + for (j=0;jalloci) { \ + ret = xrealloc(ret,alloci+64); \ + alloci = alloci + 64; } \ + ret[i++] = a; } + +#define Print_char(a) append_i_byte(a) + +#define Print_uchar(s) { \ + if (s<=0x7F) { \ + Print_char(s); \ + } else if (s<=0x7FF) { \ + Print_char(0xC0 + (s / 0x40)); \ + Print_char(0x80 + (s % 0x40)); \ + } else if (s<=0xFFFF) { \ + Print_char(0xE0 + (s / 0x1000)); \ + Print_char(0x80 + ((s % 0x1000) / 0x40)); \ + Print_char(0x80 + ((s % 0x1000) % 0x40)); \ + } else if (s>=0x10FF00) { \ + Print_char(s-0x10FF00); \ + } else { \ + Print_char(0xF0 + (s / 0x40000)); \ + Print_char(0x80 + ((s % 0x40000) / 0x1000)); \ + Print_char(0x80 + (((s % 0x40000) % 0x1000) / 0x40)); \ + Print_char(0x80 + (((s % 0x40000) % 0x1000) % 0x40)); \ + } } + + +#define Print_esc(b) { if (e>0 && e=0xF0))|| \ + ((length(a)==3)&&(str_pool[str_start_macro(a)]>=0xE0))|| \ + ((length(a)==2)&&(str_pool[str_start_macro(a)]>=0xC0)) + +#define is_cat_letter(a) \ + (get_char_cat_code(pool_to_unichar(str_start_macro(a))) == 11) + +static int active_base = 0; +static int hash_base = 0; +static int eqtb_size = 0; +static int null_cs = 0; +static int undefined_control_sequence; + +char * +tokenlist_to_cstring ( int p , int inhibit_par, int *siz) { + integer m, c ; + integer q; + char *s; + int e; + char *ret=NULL; + int match_chr = '#'; + int n = '0'; + int alloci = 0; + int i = 0; + if (p==null || link(p)==null) { + if (siz!=NULL) + *siz = 0; + return NULL; + } + p = link(p); /* skip refcount */ + if (active_base==0) { + active_base = get_active_base(); + hash_base = get_hash_base(); + null_cs = get_nullcs(); + eqtb_size = get_eqtb_size(); + undefined_control_sequence = get_undefined_control_sequence(); + } + e = get_escape_char(); + while ( p != null ) { + if (p < fix_mem_min || p > fix_mem_end ) { + Print_esc ("CLOBBERED.") ; + break; + } + if (info(p)>=cs_token_flag) { + if ( ! (inhibit_par && info(p)==par_token) ) { + q = info(p) - cs_token_flag; + if (q=undefined_control_sequence)&&((q<=eqtb_size))||(q>eqtb_size+hash_extra)) { + Print_esc("IMPOSSIBLE."); + } else if ((zget_cs_text(q)<0)||(zget_cs_text(q)>=str_ptr)) { + Print_esc("NONEXISTENT."); + } else { + Print_uchar (e); + s = makecstring(zget_cs_text(q)); + while (*s) { Print_char(*s); s++; } + if ((! single_letter(zget_cs_text(q))) || is_cat_letter(zget_cs_text(q))) { + Print_char(' '); + } + } + } + } else { + m=info(p) / string_offset; + c=info(p) % string_offset; + if ( info(p) < 0 ) { + Print_esc ( "BAD.") ; + } else { + switch ( m ) { + case 6 : /* falls through */ + Print_uchar ( c ) ; + case 1 : + case 2 : + case 3 : + case 4 : + case 7 : + case 8 : + case 10 : + case 11 : + case 12 : + Print_uchar ( c ) ; + break ; + case 5 : + Print_uchar ( match_chr ) ; + if ( c <= 9 ) { + Print_char ( c + '0') ; + } else { + Print_char ( '!' ) ; + return NULL; + } + break ; + case 13 : + match_chr = c ; + Print_uchar ( c ) ; + incr ( n ) ; + Print_char ( n ) ; + if ( n > '9' ) + return NULL; + break ; + case 14 : + if ( c == 0 ) { + Print_char ('-'); + Print_char ('>') ; + } + break ; + default: + Print_esc ( "BAD.") ; + break ; + } + } + } + p = link(p); + } + ret[i]=0; + if (siz!=NULL) + *siz = i; + return ret; +} + + +void +tokenlist_to_lua(lua_State *L, int p) { + int cmd,chr,cs; + int v; + int i = 1; + v = p; + while (v!=null && v < fix_mem_end) { i++; v = link(v); } + i = 1; + lua_createtable(L,i,0); + while (p!=null&& p < fix_mem_end) { + if (info(p)>=cs_token_flag) { + cs=info(p)-cs_token_flag; + cmd = zget_eq_type(cs); + chr = zget_equiv(cs); + make_token_table(L,cmd,chr,cs); + } else { + cmd=info(p) / string_offset; + chr=info(p) % string_offset; + make_token_table(L,cmd,chr,0); + } + lua_rawseti(L,-2,i++); + p = link(p); + } +} + + +void +tokenlist_to_luastring(lua_State *L, int p) { + int l; + char *s; + s = tokenlist_to_cstring(p,1,&l); + lua_pushlstring(L,s,l); +} + + +int +tokenlist_from_lua(lua_State *L) { + char *s; + int tok,i; + size_t j; + halfword p,q,r; + r = get_avail(); + info(r)=0; /* ref count */ + link(r)=null; + p = r; + if (lua_istable(L,-1)) { + j = lua_objlen(L,-1); + if (j>0) { + for (i=1;i<=j;i++) { + lua_rawgeti(L,-1,i); + tok = token_from_lua(L); + if (tok>=0) { + store_new_token(tok); + } + lua_pop(L,1); + }; + } + return r; + } else if (lua_isstring(L,-1)) { + s = (char *)lua_tolstring(L,-1,&j); + for (i=0;i0) { + for (i=1;i<=j;i++) { + lua_rawgeti(L,-1,i); + if (get_cur_cmd(L) || get_cur_cs(L)) { + store_new_token(cur_tok); + } + lua_pop(L,1); + } + } + if (p!=r) { + p = link(r); + free_avail(r); + begin_token_list(p, inserted); + cur_input.nofilter_field=true; + get_next(); + lua_pop(L,1); + break; + } else { + fprintf(stdout,"error: illegal or empty token list returned\n"); + lua_pop(L,2); + error(); + return; + } + } else { + lua_pop(L,1); + if (get_cur_cmd(L) || get_cur_cs(L)) { + lua_pop(L,1); + break; + } else { + lua_pop(L,2); + continue; + } + } + } else { + lua_pop(L,1); + continue; + } + } + lua_pop(L,1); /* callback container */ + return; +} + diff --git a/Build/source/texk/web2c/luatexdir/lua/mp.w b/Build/source/texk/web2c/luatexdir/lua/mp.w new file mode 100644 index 00000000000..a459cc48fe1 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/mp.w @@ -0,0 +1,26173 @@ +% $Id: mp.web,v 1.8 2005/08/24 10:54:02 taco Exp $ +% MetaPost, by John Hobby. Public domain. + +% Much of this program was copied with permission from MF.web Version 1.9 +% It interprets a language very similar to D.E. Knuth's METAFONT, but with +% changes designed to make it more suitable for PostScript output. + +% TeX is a trademark of the American Mathematical Society. +% METAFONT is a trademark of Addison-Wesley Publishing Company. +% PostScript is a trademark of Adobe Systems Incorporated. + +% Here is TeX material that gets inserted after \input webmac +\def\hang{\hangindent 3em\noindent\ignorespaces} +\def\textindent#1{\hangindent2.5em\noindent\hbox to2.5em{\hss#1 }\ignorespaces} +\def\ps{PostScript} +\def\psqrt#1{\sqrt{\mathstrut#1}} +\def\k{_{k+1}} +\def\pct!{{\char`\%}} % percent sign in ordinary text +\font\tenlogo=logo10 % font used for the METAFONT logo +\font\logos=logosl10 +\def\MF{{\tenlogo META}\-{\tenlogo FONT}} +\def\MP{{\tenlogo META}\-{\tenlogo POST}} +\def\[#1]{\ignorespaces} % left over from pascal web +\def\<#1>{$\langle#1\rangle$} +\def\section{\mathhexbox278} +\let\swap=\leftrightarrow +\def\round{\mathop{\rm round}\nolimits} +\mathchardef\vb="026A % synonym for `\|' + +\def\(#1){} % this is used to make section names sort themselves better +\def\9#1{} % this is used for sort keys in the index via @@:sort key}{entry@@> +\def\title{MetaPost} +\pdfoutput=1 +\pageno=3 + +@* \[1] Introduction. + +This is \MP, a graphics-language processor based on D. E. Knuth's \MF. + +The main purpose of the following program is to explain the algorithms of \MP\ +as clearly as possible. However, the program has been written so that it +can be tuned to run efficiently in a wide variety of operating environments +by making comparatively few changes. Such flexibility is possible because +the documentation that follows is written in the \.{WEB} language, which is +at a higher level than C. + +A large piece of software like \MP\ has inherent complexity that cannot +be reduced below a certain level of difficulty, although each individual +part is fairly simple by itself. The \.{WEB} language is intended to make +the algorithms as readable as possible, by reflecting the way the +individual program pieces fit together and by providing the +cross-references that connect different parts. Detailed comments about +what is going on, and about why things were done in certain ways, have +been liberally sprinkled throughout the program. These comments explain +features of the implementation, but they rarely attempt to explain the +\MP\ language itself, since the reader is supposed to be familiar with +{\sl The {\logos METAFONT\/}book} as well as the manual +@.WEB@> +@:METAFONTbook}{\sl The {\logos METAFONT\/}book@> +{\sl A User's Manual for MetaPost}, Computing Science Technical Report 162, +AT\AM T Bell Laboratories. + +@ The present implementation is a preliminary version, but the possibilities +for new features are limited by the desire to remain as nearly compatible +with \MF\ as possible. + +On the other hand, the \.{WEB} description can be extended without changing +the core of the program, and it has been designed so that such +extensions are not extremely difficult to make. +The |banner| string defined here should be changed whenever \MP\ +undergoes any modifications, so that it will be clear which version of +\MP\ might be the guilty party when a problem arises. +@^extensions to \MP@> +@^system dependencies@> + +@d banner "This is MetaPost, Version 1.003" /* printed when \MP\ starts */ +@d metapost_version "1.003" +@d mplib_version "0.30" +@d version_string " (Cweb version 0.30)" + +@d true 1 +@d false 0 + +@ The external library header for \MP\ is |mplib.h|. It contains a +few typedefs and the header defintions for the externally used +fuctions. + +The most important of the typedefs is the definition of the structure +|MP_options|, that acts as a small, configurable front-end to the fairly +large |MP_instance| structure. + +@(mplib.h@>= +typedef struct MP_instance * MP; +@ +typedef struct MP_options { + @