From fa5d18c2f98ae3bca364f3c19804bd42f8305512 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Sun, 8 May 2016 22:44:34 +0000 Subject: context git-svn-id: svn://tug.org/texlive/trunk@40962 c570f23f-e606-0410-a88d-b1316a301751 --- .../context/documents/general/manuals/luatex.pdf | Bin 991216 -> 994575 bytes .../doc/context/scripts/mkiv/context.html | 3 +- .../doc/context/scripts/mkiv/context.man | 5 +- .../doc/context/scripts/mkiv/context.xml | 5 +- .../doc/context/scripts/mkiv/mtx-context.html | 3 +- .../doc/context/scripts/mkiv/mtx-context.man | 5 +- .../doc/context/scripts/mkiv/mtx-context.xml | 5 +- .../sources/general/manuals/luatex/luatex-lua.tex | 86 +- .../general/manuals/luatex/luatex-style.tex | 4 +- .../sources/general/manuals/luatex/luatex.tex | 2 + Master/texmf-dist/doc/man/man1/context.1 | 5 +- Master/texmf-dist/doc/man/man1/context.man1.pdf | Bin 21431 -> 22864 bytes Master/texmf-dist/doc/man/man1/luatools.man1.pdf | Bin 18421 -> 18421 bytes Master/texmf-dist/doc/man/man1/mtx-babel.man1.pdf | Bin 16108 -> 16108 bytes Master/texmf-dist/doc/man/man1/mtx-base.man1.pdf | Bin 18441 -> 18441 bytes Master/texmf-dist/doc/man/man1/mtx-bibtex.man1.pdf | Bin 14827 -> 14827 bytes Master/texmf-dist/doc/man/man1/mtx-cache.man1.pdf | Bin 15820 -> 15820 bytes Master/texmf-dist/doc/man/man1/mtx-chars.man1.pdf | Bin 15813 -> 15813 bytes Master/texmf-dist/doc/man/man1/mtx-check.man1.pdf | Bin 15975 -> 15975 bytes Master/texmf-dist/doc/man/man1/mtx-colors.man1.pdf | Bin 14800 -> 14800 bytes Master/texmf-dist/doc/man/man1/mtx-context.1 | 5 +- .../texmf-dist/doc/man/man1/mtx-context.man1.pdf | Bin 21431 -> 22864 bytes Master/texmf-dist/doc/man/man1/mtx-epub.man1.pdf | Bin 16489 -> 16489 bytes Master/texmf-dist/doc/man/man1/mtx-fcd.man1.pdf | Bin 16754 -> 16754 bytes Master/texmf-dist/doc/man/man1/mtx-flac.man1.pdf | Bin 15723 -> 15723 bytes Master/texmf-dist/doc/man/man1/mtx-fonts.man1.pdf | Bin 18052 -> 18052 bytes Master/texmf-dist/doc/man/man1/mtx-grep.man1.pdf | Bin 15660 -> 15660 bytes .../texmf-dist/doc/man/man1/mtx-interface.man1.pdf | Bin 17357 -> 17357 bytes .../texmf-dist/doc/man/man1/mtx-metapost.man1.pdf | Bin 15741 -> 15741 bytes .../texmf-dist/doc/man/man1/mtx-metatex.man1.pdf | Bin 15253 -> 15253 bytes .../texmf-dist/doc/man/man1/mtx-modules.man1.pdf | Bin 16073 -> 16073 bytes .../texmf-dist/doc/man/man1/mtx-package.man1.pdf | Bin 15725 -> 15725 bytes .../texmf-dist/doc/man/man1/mtx-patterns.man1.pdf | Bin 16861 -> 16861 bytes Master/texmf-dist/doc/man/man1/mtx-pdf.man1.pdf | Bin 16029 -> 16029 bytes Master/texmf-dist/doc/man/man1/mtx-plain.man1.pdf | Bin 15788 -> 15788 bytes .../texmf-dist/doc/man/man1/mtx-profile.man1.pdf | Bin 16365 -> 16365 bytes Master/texmf-dist/doc/man/man1/mtx-rsync.man1.pdf | Bin 15783 -> 15783 bytes Master/texmf-dist/doc/man/man1/mtx-scite.man1.pdf | Bin 15878 -> 15878 bytes Master/texmf-dist/doc/man/man1/mtx-server.man1.pdf | Bin 16014 -> 16014 bytes .../texmf-dist/doc/man/man1/mtx-texworks.man1.pdf | Bin 15331 -> 15331 bytes Master/texmf-dist/doc/man/man1/mtx-timing.man1.pdf | Bin 15477 -> 15477 bytes Master/texmf-dist/doc/man/man1/mtx-tools.man1.pdf | Bin 16727 -> 16727 bytes .../texmf-dist/doc/man/man1/mtx-unicode.man1.pdf | Bin 15225 -> 15225 bytes Master/texmf-dist/doc/man/man1/mtx-unzip.man1.pdf | Bin 15640 -> 15640 bytes Master/texmf-dist/doc/man/man1/mtx-update.man1.pdf | Bin 17604 -> 17604 bytes Master/texmf-dist/doc/man/man1/mtx-watch.man1.pdf | Bin 16561 -> 16561 bytes .../texmf-dist/doc/man/man1/mtx-youless.man1.pdf | Bin 16126 -> 16126 bytes Master/texmf-dist/doc/man/man1/mtxrun.man1.pdf | Bin 20513 -> 20513 bytes Master/texmf-dist/doc/man/man1/texexec.man1.pdf | Bin 17189 -> 17189 bytes Master/texmf-dist/doc/man/man1/texmfstart.man1.pdf | Bin 20513 -> 20513 bytes .../texmf-dist/scripts/context/lua/mtx-context.lua | 101 +- .../texmf-dist/scripts/context/lua/mtx-context.xml | 5 +- .../texmf-dist/scripts/context/lua/mtx-modules.lua | 2 +- .../scripts/context/lua/mtx-patterns.lua | 14 +- .../texmf-dist/scripts/context/lua/mtx-plain.lua | 20 +- .../tex/context/base/context-version.pdf | Bin 4249 -> 4253 bytes .../texmf-dist/tex/context/base/mkiv/back-pdf.lua | 11 + .../texmf-dist/tex/context/base/mkiv/char-ini.lua | 12 +- .../texmf-dist/tex/context/base/mkiv/cont-new.mkiv | 2 +- .../tex/context/base/mkiv/context-todo.tex | 9 +- .../texmf-dist/tex/context/base/mkiv/context.mkiv | 2 +- .../texmf-dist/tex/context/base/mkiv/core-con.lua | 43 +- .../texmf-dist/tex/context/base/mkiv/core-con.mkiv | 4 +- .../texmf-dist/tex/context/base/mkiv/core-ctx.lua | 24 +- .../texmf-dist/tex/context/base/mkiv/font-chk.lua | 13 +- .../texmf-dist/tex/context/base/mkiv/font-enh.lua | 16 +- .../texmf-dist/tex/context/base/mkiv/font-ext.lua | 89 +- .../texmf-dist/tex/context/base/mkiv/font-fbk.lua | 12 +- .../texmf-dist/tex/context/base/mkiv/font-gbn.lua | 20 +- .../texmf-dist/tex/context/base/mkiv/font-gds.lua | 34 +- .../texmf-dist/tex/context/base/mkiv/font-lib.mkvi | 9 +- .../texmf-dist/tex/context/base/mkiv/font-one.lua | 1220 +++++ .../texmf-dist/tex/context/base/mkiv/font-otc.lua | 27 +- .../texmf-dist/tex/context/base/mkiv/font-otj.lua | 30 +- .../texmf-dist/tex/context/base/mkiv/font-otl.lua | 8 +- .../texmf-dist/tex/context/base/mkiv/font-oto.lua | 2 + .../texmf-dist/tex/context/base/mkiv/font-ots.lua | 3 + .../texmf-dist/tex/context/base/mkiv/lang-def.mkiv | 2 +- .../texmf-dist/tex/context/base/mkiv/lang-ini.lua | 8 +- .../texmf-dist/tex/context/base/mkiv/lang-ini.mkiv | 2 +- .../texmf-dist/tex/context/base/mkiv/lpdf-ini.lua | 21 +- .../texmf-dist/tex/context/base/mkiv/lpdf-xmp.lua | 88 +- .../texmf-dist/tex/context/base/mkiv/luat-cnf.lua | 1 + .../texmf-dist/tex/context/base/mkiv/m-oldotf.mkiv | 1 + .../texmf-dist/tex/context/base/mkiv/meta-ini.mkiv | 4 + .../texmf-dist/tex/context/base/mkiv/mult-sys.mkiv | 2 +- .../texmf-dist/tex/context/base/mkiv/node-fnt.lua | 15 +- .../tex/context/base/mkiv/status-files.pdf | Bin 9119 -> 9257 bytes .../tex/context/base/mkiv/status-lua.pdf | Bin 268089 -> 268124 bytes .../texmf-dist/tex/context/base/mkiv/typo-tal.lua | 8 +- .../texmf-dist/tex/context/base/mkiv/typo-wrp.mkiv | 1 + .../tex/context/fonts/mkiv/type-imp-lato.mkiv | 90 +- .../tex/context/interface/mkiv/i-context.pdf | Bin 820458 -> 820451 bytes .../tex/context/interface/mkiv/i-readme.pdf | Bin 60792 -> 60791 bytes .../tex/context/modules/mkiv/m-scite.mkiv | 39 +- .../modules/mkiv/s-languages-hyphenation.lua | 157 +- .../modules/mkiv/s-languages-hyphenation.mkiv | 35 +- .../tex/context/modules/mkiv/s-mod-01.mkiv | 3 +- .../texmf-dist/tex/context/modules/mkiv/x-ldx.lua | 89 +- .../texmf-dist/tex/context/modules/mkiv/x-ldx.mkiv | 52 +- .../generic/context/luatex/luatex-fonts-merged.lua | 5236 ++++++++++---------- .../tex/generic/context/luatex/luatex-fonts.lua | 7 +- 102 files changed, 4692 insertions(+), 3029 deletions(-) create mode 100644 Master/texmf-dist/tex/context/base/mkiv/font-one.lua (limited to 'Master') diff --git a/Master/texmf-dist/doc/context/documents/general/manuals/luatex.pdf b/Master/texmf-dist/doc/context/documents/general/manuals/luatex.pdf index 61ff94bfba6..a63c4d9179a 100644 Binary files a/Master/texmf-dist/doc/context/documents/general/manuals/luatex.pdf and b/Master/texmf-dist/doc/context/documents/general/manuals/luatex.pdf differ diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/context.html b/Master/texmf-dist/doc/context/scripts/mkiv/context.html index 3161eac7250..5fbf49d2b93 100644 --- a/Master/texmf-dist/doc/context/scripts/mkiv/context.html +++ b/Master/texmf-dist/doc/context/scripts/mkiv/context.html @@ -82,7 +82,8 @@ --batchmoderun without stopping and do not show messages on the console --nonstopmoderun without stopping --synctexrun with synctex enabled (optional value: zipped, unzipped, 1, -1) - --nodatesomit runtime dates in pdf file + --nodatesomit runtime dates in pdf file (optional value: a number (this 1970 offset time) or string "YYYY-MM-DD HH:MM") + --nocompressionforcefully turns off compression in the backend --traileridalternative trailer id (or constant one) --generategenerate file database etc. (as luatools does) diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/context.man b/Master/texmf-dist/doc/context/scripts/mkiv/context.man index f1c552832c2..c8359e9e814 100644 --- a/Master/texmf-dist/doc/context/scripts/mkiv/context.man +++ b/Master/texmf-dist/doc/context/scripts/mkiv/context.man @@ -114,7 +114,10 @@ run without stopping run with synctex enabled (optional value: zipped, unzipped, 1, -1) .TP .B --nodates -omit runtime dates in pdf file +omit runtime dates in pdf file (optional value: a number (this 1970 offset time) or string "YYYY-MM-DD HH:MM") +.TP +.B --nocompression +forcefully turns off compression in the backend .TP .B --trailerid alternative trailer id (or constant one) diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/context.xml b/Master/texmf-dist/doc/context/scripts/mkiv/context.xml index f5a67424165..2ba7ee59e07 100644 --- a/Master/texmf-dist/doc/context/scripts/mkiv/context.xml +++ b/Master/texmf-dist/doc/context/scripts/mkiv/context.xml @@ -129,7 +129,10 @@ run with synctex enabled (optional value: zipped, unzipped, 1, -1) - omit runtime dates in pdf file + omit runtime dates in pdf file (optional value: a number (this 1970 offset time) or string "YYYY-MM-DD HH:MM") + + + forcefully turns off compression in the backend alternative trailer id (or constant one) diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-context.html b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-context.html index 3161eac7250..5fbf49d2b93 100644 --- a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-context.html +++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-context.html @@ -82,7 +82,8 @@ --batchmoderun without stopping and do not show messages on the console --nonstopmoderun without stopping --synctexrun with synctex enabled (optional value: zipped, unzipped, 1, -1) - --nodatesomit runtime dates in pdf file + --nodatesomit runtime dates in pdf file (optional value: a number (this 1970 offset time) or string "YYYY-MM-DD HH:MM") + --nocompressionforcefully turns off compression in the backend --traileridalternative trailer id (or constant one) --generategenerate file database etc. (as luatools does) diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-context.man b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-context.man index f1c552832c2..c8359e9e814 100644 --- a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-context.man +++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-context.man @@ -114,7 +114,10 @@ run without stopping run with synctex enabled (optional value: zipped, unzipped, 1, -1) .TP .B --nodates -omit runtime dates in pdf file +omit runtime dates in pdf file (optional value: a number (this 1970 offset time) or string "YYYY-MM-DD HH:MM") +.TP +.B --nocompression +forcefully turns off compression in the backend .TP .B --trailerid alternative trailer id (or constant one) diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-context.xml b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-context.xml index f5a67424165..2ba7ee59e07 100644 --- a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-context.xml +++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-context.xml @@ -129,7 +129,10 @@ run with synctex enabled (optional value: zipped, unzipped, 1, -1) - omit runtime dates in pdf file + omit runtime dates in pdf file (optional value: a number (this 1970 offset time) or string "YYYY-MM-DD HH:MM") + + + forcefully turns off compression in the backend alternative trailer id (or constant one) diff --git a/Master/texmf-dist/doc/context/sources/general/manuals/luatex/luatex-lua.tex b/Master/texmf-dist/doc/context/sources/general/manuals/luatex/luatex-lua.tex index 79c4e08ed6b..0960f803206 100644 --- a/Master/texmf-dist/doc/context/sources/general/manuals/luatex/luatex-lua.tex +++ b/Master/texmf-dist/doc/context/sources/general/manuals/luatex/luatex-lua.tex @@ -56,44 +56,32 @@ similar fashion as the other \TEX\ engines. Some options are accepted but have n consequence. The following command|-|line options are understood: \starttabulate[|lT|p|] +\NC --credits \NC display credits and exit \NC \NR +\NC --debug-format \NC enable format debugging \NC \NR +\NC --draftmode \NC switch on draft mode i.e.\ generate no output in \PDF\ mode \NC \NR +\NC --[no-]file-line-error \NC disable/enable \type {file:line:error} style messages \NC \NR +\NC --[no-]file-line-error-style \NC aliases of \type {--[no-]file-line-error} \NC \NR \NC --fmt=FORMAT \NC load the format file \type {FORMAT} \NC\NR -\NC --lua=FILE \NC load and execute a \LUA\ initialization script\NC\NR -\NC --safer \NC disable easily exploitable \LUA\ commands \NC\NR -\NC --nosocket \NC disable the \LUA\ socket library \NC\NR +\NC --halt-on-error \NC stop processing at the first error\NC \NR \NC --help \NC display help and exit \NC\NR \NC --ini \NC be \type {iniluatex}, for dumping formats \NC\NR -\NC --interaction=STRING \NC set interaction mode: \type {batchmode}, \type {nonstopmode}, - \type {scrollmode} or \type {errorstopmode} \NC \NR -\NC --halt-on-error \NC stop processing at the first error\NC \NR -\NC --kpathsea-debug=NUMBER \NC set path searching debugging flags according to - the bits of \type {NUMBER} \NC \NR +\NC --interaction=STRING \NC set interaction mode: \type {batchmode}, \type {nonstopmode}, \type {scrollmode} or \type {errorstopmode} \NC \NR +\NC --jobname=STRING \NC set the job name to \type {STRING} \NC \NR +\NC --kpathsea-debug=NUMBER \NC set path searching debugging flags according to the bits of \type {NUMBER} \NC \NR +\NC --lua=FILE \NC load and execute a \LUA\ initialization script \NC\NR +\NC --[no-]mktex=FMT \NC disable/enable \type {mktexFMT} generation with \type {FMT} is \type {tex} or \type {tfm} \NC \NR +\NC --nosocket \NC disable the \LUA\ socket library \NC\NR +\NC --output-comment=STRING \NC use \type {STRING} for \DVI\ file comment instead of date (no effect for \PDF) \NC \NR +\NC --output-directory=DIR \NC use \type {DIR} as the directory to write files to \NC \NR +\NC --output-format=FORMAT \NC use \type {FORMAT} for job output; \type {FORMAT} is \type {dvi} or \type {pdf} \NC \NR \NC --progname=STRING \NC set the program name to \type {STRING} \NC \NR -\NC --version \NC display version and exit \NC \NR -\NC --credits \NC display credits and exit \NC \NR \NC --recorder \NC enable filename recorder \NC \NR -\NC --output-comment=STRING \NC use \type {STRING} for \DVI\ file comment - instead of date (no effect for \PDF) \NC \NR -\NC --output-directory=DIR \NC use \type {DIR} as the directory to write - files to \NC \NR -\NC --draftmode \NC switch on draft mode i.e.\ generate no - output in \PDF\ mode \NC \NR -\NC --output-format=FORMAT \NC use \type {FORMAT} for job output; \type - {FORMAT} is \type {dvi} or \type {pdf} \NC - \NR +\NC --safer \NC disable easily exploitable \LUA\ commands \NC\NR \NC --[no-]shell-escape \NC disable/enable system calls \NC \NR -\NC --enable-write18 \NC enable system calls \NC \NR -\NC --disable-write18 \NC disable system calls \NC \NR -\NC --shell-restricted \NC restrict system calls to a list of commands - given in \type {texmf.cnf} \NC \NR -\NC --debug-format \NC enable format debugging \NC \NR -\NC --[no-]file-line-error \NC disable/enable \type {file:line:error} style - messages \NC \NR -\NC --[no-]file-line-error-style \NC aliases of \type {--[no-]file-line-error} \NC \NR -\NC --jobname=STRING \NC set the job name to \type {STRING} \NC \NR -\NC --[no-]mktex=FMT \NC disable/enable \type {mktexFMT} generation - with \type {FMT} is \type {tex} or \type - {tfm} \NC \NR +\NC --shell-restricted \NC restrict system calls to a list of commands given in \type {texmf.cnf} \NC \NR \NC --synctex=NUMBER \NC enable \type {synctex} \NC \NR +\NC --utc \NC use utc times when applicable \NC \NR +\NC --version \NC display version and exit \NC \NR \stoptabulate Some of the traditional flags are just ignored: \type {--etex}, \type @@ -543,6 +531,42 @@ At some point (this also depends on distributions) \LUATEX\ might have these libraries loaded on demand. For this reason you can best use \type {require} to make sure they are loaded. +\section{Testing} + +For development reasons you can influence the used startup date and time. This can +be done in two ways. + +\startitemize[n] + +\startitem + By setting the environmment variable \type {SOURCE_DATE_EPOCH}. This will + influence the \TEX\ parameters \type {time} and \type {date}, the random seed, + the \PDF\ timestamp and the \PDF\ id that is derived from the time as well. This + variable is consulted when the \KPSE\ library is enabled. Resolving is + delegated to this library. +\stopitem + +\startitem + By setting the \type {start_time} variable in the \type {texconfig} table; as + with other variables we use the internal name there. For compatibility + reasons we also honour a \type {SOURCE_DATE_EPOCH} entry. It should be noted + that there are no such variables in other engines and this method is only + relevant in case the while setup happens in \LUA. +\stopitem + +\stopitemize + +When Universal Time is needed, you can pass the flag \type {utc} to the engine. This +property also works when the date and time are set by \LUATEX\ itself. It has a +complementary entry \type {use_utc_time} in the \type {texconfig} table. + +{\em To some extend a cleaner solution would be to have a flag that disables all +variable data in one go (like filenames and so) but we just follow the method +implemented in \PDFTEX\ where primitives are used to influence other properties.} + +{\em In \CONTEXT\ we provide the command line argument \type {--nodates} that +does bit more disabling of dates.} + \stopchapter \stopcomponent diff --git a/Master/texmf-dist/doc/context/sources/general/manuals/luatex/luatex-style.tex b/Master/texmf-dist/doc/context/sources/general/manuals/luatex/luatex-style.tex index b07190e2141..26688abaf26 100644 --- a/Master/texmf-dist/doc/context/sources/general/manuals/luatex/luatex-style.tex +++ b/Master/texmf-dist/doc/context/sources/general/manuals/luatex/luatex-style.tex @@ -198,7 +198,7 @@ withpen pencircle scaled (p/2) withcolor (luaorbitfactor * luaholecolor) ; fill fullcircle scaled r shifted (d+1/8,d+1/8) - rotated luaextraangle + rotated - luaextraangle withcolor luaplanetcolor ; fill fullcircle scaled r shifted (d-1/8,d-1/8) withcolor luaholecolor ; @@ -228,7 +228,7 @@ \startuseMPgraphic{luanumber} % luaextraangle := \luaextraangle; - luaextraangle := if (LastPageNumber == 0) : 0 else : RealPageNumber * 360 / LastPageNumber fi; + luaextraangle := if (LastPageNumber == 0) : 0 else : (RealPageNumber / LastPageNumber) * 360 fi; luaorbitfactor := 0.25 ; picture p ; p := lualogo ; setbounds p to boundingbox fullcircle ; diff --git a/Master/texmf-dist/doc/context/sources/general/manuals/luatex/luatex.tex b/Master/texmf-dist/doc/context/sources/general/manuals/luatex/luatex.tex index a9524246b9c..59a969396ad 100644 --- a/Master/texmf-dist/doc/context/sources/general/manuals/luatex/luatex.tex +++ b/Master/texmf-dist/doc/context/sources/general/manuals/luatex/luatex.tex @@ -3,6 +3,8 @@ % \tex vs \type vs \syntax vs. \luatex % \em \it \/ +% "context --nodates --nocompression luatex" can be used for comparison runs + \environment luatex-style \environment luatex-logos diff --git a/Master/texmf-dist/doc/man/man1/context.1 b/Master/texmf-dist/doc/man/man1/context.1 index f1c552832c2..c8359e9e814 100644 --- a/Master/texmf-dist/doc/man/man1/context.1 +++ b/Master/texmf-dist/doc/man/man1/context.1 @@ -114,7 +114,10 @@ run without stopping run with synctex enabled (optional value: zipped, unzipped, 1, -1) .TP .B --nodates -omit runtime dates in pdf file +omit runtime dates in pdf file (optional value: a number (this 1970 offset time) or string "YYYY-MM-DD HH:MM") +.TP +.B --nocompression +forcefully turns off compression in the backend .TP .B --trailerid alternative trailer id (or constant one) diff --git a/Master/texmf-dist/doc/man/man1/context.man1.pdf b/Master/texmf-dist/doc/man/man1/context.man1.pdf index 8b55d3b8450..330457cdb3e 100644 Binary files a/Master/texmf-dist/doc/man/man1/context.man1.pdf and b/Master/texmf-dist/doc/man/man1/context.man1.pdf differ diff --git a/Master/texmf-dist/doc/man/man1/luatools.man1.pdf b/Master/texmf-dist/doc/man/man1/luatools.man1.pdf index 555aa6e9fdd..bb2a438fed5 100644 Binary files a/Master/texmf-dist/doc/man/man1/luatools.man1.pdf and b/Master/texmf-dist/doc/man/man1/luatools.man1.pdf differ diff --git a/Master/texmf-dist/doc/man/man1/mtx-babel.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-babel.man1.pdf index 925edb45144..cda6d55813b 100644 Binary files a/Master/texmf-dist/doc/man/man1/mtx-babel.man1.pdf and b/Master/texmf-dist/doc/man/man1/mtx-babel.man1.pdf differ diff --git a/Master/texmf-dist/doc/man/man1/mtx-base.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-base.man1.pdf index fe3da288143..09730255a6a 100644 Binary files a/Master/texmf-dist/doc/man/man1/mtx-base.man1.pdf and b/Master/texmf-dist/doc/man/man1/mtx-base.man1.pdf differ diff --git a/Master/texmf-dist/doc/man/man1/mtx-bibtex.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-bibtex.man1.pdf index 6acf134e382..ed66f7de5b2 100644 Binary files a/Master/texmf-dist/doc/man/man1/mtx-bibtex.man1.pdf and b/Master/texmf-dist/doc/man/man1/mtx-bibtex.man1.pdf differ diff --git a/Master/texmf-dist/doc/man/man1/mtx-cache.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-cache.man1.pdf index 2663105cd2c..f5b4e09e9e9 100644 Binary files a/Master/texmf-dist/doc/man/man1/mtx-cache.man1.pdf and b/Master/texmf-dist/doc/man/man1/mtx-cache.man1.pdf differ diff --git a/Master/texmf-dist/doc/man/man1/mtx-chars.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-chars.man1.pdf index 3f8d910b927..cf2342ec732 100644 Binary files a/Master/texmf-dist/doc/man/man1/mtx-chars.man1.pdf and b/Master/texmf-dist/doc/man/man1/mtx-chars.man1.pdf differ diff --git a/Master/texmf-dist/doc/man/man1/mtx-check.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-check.man1.pdf index e9960a4b828..38a96667663 100644 Binary files a/Master/texmf-dist/doc/man/man1/mtx-check.man1.pdf and b/Master/texmf-dist/doc/man/man1/mtx-check.man1.pdf differ diff --git a/Master/texmf-dist/doc/man/man1/mtx-colors.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-colors.man1.pdf index c2632cf9520..e0ba6973f94 100644 Binary files a/Master/texmf-dist/doc/man/man1/mtx-colors.man1.pdf and b/Master/texmf-dist/doc/man/man1/mtx-colors.man1.pdf differ diff --git a/Master/texmf-dist/doc/man/man1/mtx-context.1 b/Master/texmf-dist/doc/man/man1/mtx-context.1 index f1c552832c2..c8359e9e814 100644 --- a/Master/texmf-dist/doc/man/man1/mtx-context.1 +++ b/Master/texmf-dist/doc/man/man1/mtx-context.1 @@ -114,7 +114,10 @@ run without stopping run with synctex enabled (optional value: zipped, unzipped, 1, -1) .TP .B --nodates -omit runtime dates in pdf file +omit runtime dates in pdf file (optional value: a number (this 1970 offset time) or string "YYYY-MM-DD HH:MM") +.TP +.B --nocompression +forcefully turns off compression in the backend .TP .B --trailerid alternative trailer id (or constant one) diff --git a/Master/texmf-dist/doc/man/man1/mtx-context.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-context.man1.pdf index fd0d9bf5320..20257a84455 100644 Binary files a/Master/texmf-dist/doc/man/man1/mtx-context.man1.pdf and b/Master/texmf-dist/doc/man/man1/mtx-context.man1.pdf differ diff --git a/Master/texmf-dist/doc/man/man1/mtx-epub.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-epub.man1.pdf index 4d9c3d67bf9..bb04d96ebae 100644 Binary files a/Master/texmf-dist/doc/man/man1/mtx-epub.man1.pdf and b/Master/texmf-dist/doc/man/man1/mtx-epub.man1.pdf differ diff --git a/Master/texmf-dist/doc/man/man1/mtx-fcd.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-fcd.man1.pdf index 8acdd359c9f..8b4b90110bf 100644 Binary files a/Master/texmf-dist/doc/man/man1/mtx-fcd.man1.pdf and b/Master/texmf-dist/doc/man/man1/mtx-fcd.man1.pdf differ diff --git a/Master/texmf-dist/doc/man/man1/mtx-flac.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-flac.man1.pdf index 4f8af798f47..c37efcc5c20 100644 Binary files a/Master/texmf-dist/doc/man/man1/mtx-flac.man1.pdf and b/Master/texmf-dist/doc/man/man1/mtx-flac.man1.pdf differ diff --git a/Master/texmf-dist/doc/man/man1/mtx-fonts.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-fonts.man1.pdf index f6631df5d22..7550f0510ac 100644 Binary files a/Master/texmf-dist/doc/man/man1/mtx-fonts.man1.pdf and b/Master/texmf-dist/doc/man/man1/mtx-fonts.man1.pdf differ diff --git a/Master/texmf-dist/doc/man/man1/mtx-grep.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-grep.man1.pdf index a7857783b1f..e48b3bb735d 100644 Binary files a/Master/texmf-dist/doc/man/man1/mtx-grep.man1.pdf and b/Master/texmf-dist/doc/man/man1/mtx-grep.man1.pdf differ diff --git a/Master/texmf-dist/doc/man/man1/mtx-interface.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-interface.man1.pdf index 322dc73e0dc..b8ecec8dd72 100644 Binary files a/Master/texmf-dist/doc/man/man1/mtx-interface.man1.pdf and b/Master/texmf-dist/doc/man/man1/mtx-interface.man1.pdf differ diff --git a/Master/texmf-dist/doc/man/man1/mtx-metapost.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-metapost.man1.pdf index a4d4384c861..92d704cf0f0 100644 Binary files a/Master/texmf-dist/doc/man/man1/mtx-metapost.man1.pdf and b/Master/texmf-dist/doc/man/man1/mtx-metapost.man1.pdf differ diff --git a/Master/texmf-dist/doc/man/man1/mtx-metatex.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-metatex.man1.pdf index 6bad04b47fa..7d98a917252 100644 Binary files a/Master/texmf-dist/doc/man/man1/mtx-metatex.man1.pdf and b/Master/texmf-dist/doc/man/man1/mtx-metatex.man1.pdf differ diff --git a/Master/texmf-dist/doc/man/man1/mtx-modules.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-modules.man1.pdf index 238b5a4868d..2444f6f9ec8 100644 Binary files a/Master/texmf-dist/doc/man/man1/mtx-modules.man1.pdf and b/Master/texmf-dist/doc/man/man1/mtx-modules.man1.pdf differ diff --git a/Master/texmf-dist/doc/man/man1/mtx-package.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-package.man1.pdf index 3aadd949ff4..386f5d87cce 100644 Binary files a/Master/texmf-dist/doc/man/man1/mtx-package.man1.pdf and b/Master/texmf-dist/doc/man/man1/mtx-package.man1.pdf differ diff --git a/Master/texmf-dist/doc/man/man1/mtx-patterns.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-patterns.man1.pdf index 56495124b59..67b43f5579e 100644 Binary files a/Master/texmf-dist/doc/man/man1/mtx-patterns.man1.pdf and b/Master/texmf-dist/doc/man/man1/mtx-patterns.man1.pdf differ diff --git a/Master/texmf-dist/doc/man/man1/mtx-pdf.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-pdf.man1.pdf index dfcde8f9212..52bc0b7833d 100644 Binary files a/Master/texmf-dist/doc/man/man1/mtx-pdf.man1.pdf and b/Master/texmf-dist/doc/man/man1/mtx-pdf.man1.pdf differ diff --git a/Master/texmf-dist/doc/man/man1/mtx-plain.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-plain.man1.pdf index cedeb695676..cd2a8dc2140 100644 Binary files a/Master/texmf-dist/doc/man/man1/mtx-plain.man1.pdf and b/Master/texmf-dist/doc/man/man1/mtx-plain.man1.pdf differ diff --git a/Master/texmf-dist/doc/man/man1/mtx-profile.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-profile.man1.pdf index 9b76caf93f7..8b4c2563bc7 100644 Binary files a/Master/texmf-dist/doc/man/man1/mtx-profile.man1.pdf and b/Master/texmf-dist/doc/man/man1/mtx-profile.man1.pdf differ diff --git a/Master/texmf-dist/doc/man/man1/mtx-rsync.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-rsync.man1.pdf index 0dcdf7a59fa..cf483074bd1 100644 Binary files a/Master/texmf-dist/doc/man/man1/mtx-rsync.man1.pdf and b/Master/texmf-dist/doc/man/man1/mtx-rsync.man1.pdf differ diff --git a/Master/texmf-dist/doc/man/man1/mtx-scite.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-scite.man1.pdf index 5e840687194..d6b0e6336dd 100644 Binary files a/Master/texmf-dist/doc/man/man1/mtx-scite.man1.pdf and b/Master/texmf-dist/doc/man/man1/mtx-scite.man1.pdf differ diff --git a/Master/texmf-dist/doc/man/man1/mtx-server.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-server.man1.pdf index f4a6f81344c..a47749dc144 100644 Binary files a/Master/texmf-dist/doc/man/man1/mtx-server.man1.pdf and b/Master/texmf-dist/doc/man/man1/mtx-server.man1.pdf differ diff --git a/Master/texmf-dist/doc/man/man1/mtx-texworks.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-texworks.man1.pdf index d6773f729b8..ec0a7d2510f 100644 Binary files a/Master/texmf-dist/doc/man/man1/mtx-texworks.man1.pdf and b/Master/texmf-dist/doc/man/man1/mtx-texworks.man1.pdf differ diff --git a/Master/texmf-dist/doc/man/man1/mtx-timing.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-timing.man1.pdf index 0e80b3e2e6c..96db03d52ad 100644 Binary files a/Master/texmf-dist/doc/man/man1/mtx-timing.man1.pdf and b/Master/texmf-dist/doc/man/man1/mtx-timing.man1.pdf differ diff --git a/Master/texmf-dist/doc/man/man1/mtx-tools.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-tools.man1.pdf index ceda98ad9cf..64e6ff2e83c 100644 Binary files a/Master/texmf-dist/doc/man/man1/mtx-tools.man1.pdf and b/Master/texmf-dist/doc/man/man1/mtx-tools.man1.pdf differ diff --git a/Master/texmf-dist/doc/man/man1/mtx-unicode.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-unicode.man1.pdf index 5a44bbf52f1..5f3d9590476 100644 Binary files a/Master/texmf-dist/doc/man/man1/mtx-unicode.man1.pdf and b/Master/texmf-dist/doc/man/man1/mtx-unicode.man1.pdf differ diff --git a/Master/texmf-dist/doc/man/man1/mtx-unzip.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-unzip.man1.pdf index 809296431fe..5ecac0d4567 100644 Binary files a/Master/texmf-dist/doc/man/man1/mtx-unzip.man1.pdf and b/Master/texmf-dist/doc/man/man1/mtx-unzip.man1.pdf differ diff --git a/Master/texmf-dist/doc/man/man1/mtx-update.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-update.man1.pdf index 20dc51ad0a1..a8562216b50 100644 Binary files a/Master/texmf-dist/doc/man/man1/mtx-update.man1.pdf and b/Master/texmf-dist/doc/man/man1/mtx-update.man1.pdf differ diff --git a/Master/texmf-dist/doc/man/man1/mtx-watch.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-watch.man1.pdf index bf6b95ab742..652104769fb 100644 Binary files a/Master/texmf-dist/doc/man/man1/mtx-watch.man1.pdf and b/Master/texmf-dist/doc/man/man1/mtx-watch.man1.pdf differ diff --git a/Master/texmf-dist/doc/man/man1/mtx-youless.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-youless.man1.pdf index 73bba720403..4b7c368bc92 100644 Binary files a/Master/texmf-dist/doc/man/man1/mtx-youless.man1.pdf and b/Master/texmf-dist/doc/man/man1/mtx-youless.man1.pdf differ diff --git a/Master/texmf-dist/doc/man/man1/mtxrun.man1.pdf b/Master/texmf-dist/doc/man/man1/mtxrun.man1.pdf index 8327365e190..a4fd9e33301 100644 Binary files a/Master/texmf-dist/doc/man/man1/mtxrun.man1.pdf and b/Master/texmf-dist/doc/man/man1/mtxrun.man1.pdf differ diff --git a/Master/texmf-dist/doc/man/man1/texexec.man1.pdf b/Master/texmf-dist/doc/man/man1/texexec.man1.pdf index 137e3870006..f5860580eb5 100644 Binary files a/Master/texmf-dist/doc/man/man1/texexec.man1.pdf and b/Master/texmf-dist/doc/man/man1/texexec.man1.pdf differ diff --git a/Master/texmf-dist/doc/man/man1/texmfstart.man1.pdf b/Master/texmf-dist/doc/man/man1/texmfstart.man1.pdf index 9a1555972b7..0966e08b0a6 100644 Binary files a/Master/texmf-dist/doc/man/man1/texmfstart.man1.pdf and b/Master/texmf-dist/doc/man/man1/texmfstart.man1.pdf differ diff --git a/Master/texmf-dist/scripts/context/lua/mtx-context.lua b/Master/texmf-dist/scripts/context/lua/mtx-context.lua index dce9170ccbc..a5f01cebc1f 100644 --- a/Master/texmf-dist/scripts/context/lua/mtx-context.lua +++ b/Master/texmf-dist/scripts/context/lua/mtx-context.lua @@ -572,29 +572,30 @@ function scripts.context.run(ctxdata,filename) return end -- - local a_mkii = getargument("mkii") or getargument("pdftex") or getargument("xetex") - local a_purge = getargument("purge") - local a_purgeall = getargument("purgeall") - local a_purgeresult = getargument("purgeresult") - local a_global = getargument("global") - local a_timing = getargument("timing") - local a_profile = getargument("profile") - local a_batchmode = getargument("batchmode") - local a_nonstopmode = getargument("nonstopmode") - local a_scollmode = getargument("scrollmode") - local a_once = getargument("once") - local a_synctex = getargument("synctex") - local a_backend = getargument("backend") - local a_arrange = getargument("arrange") - local a_noarrange = getargument("noarrange") - local a_jiton = getargument("jiton") - local a_jithash = getargument("jithash") - local a_texformat = getargument("texformat") - local a_keeptuc = getargument("keeptuc") - local a_keeplog = getargument("keeplog") - local a_export = getargument("export") - local a_nodates = getargument("nodates") - local a_trailerid = getargument("trailerid") + local a_mkii = getargument("mkii") or getargument("pdftex") or getargument("xetex") + local a_purge = getargument("purge") + local a_purgeall = getargument("purgeall") + local a_purgeresult = getargument("purgeresult") + local a_global = getargument("global") + local a_timing = getargument("timing") + local a_profile = getargument("profile") + local a_batchmode = getargument("batchmode") + local a_nonstopmode = getargument("nonstopmode") + local a_scollmode = getargument("scrollmode") + local a_once = getargument("once") + local a_synctex = getargument("synctex") + local a_backend = getargument("backend") + local a_arrange = getargument("arrange") + local a_noarrange = getargument("noarrange") + local a_jiton = getargument("jiton") + local a_jithash = getargument("jithash") + local a_texformat = getargument("texformat") + local a_keeptuc = getargument("keeptuc") + local a_keeplog = getargument("keeplog") + local a_export = getargument("export") + local a_nodates = getargument("nodates") + local a_trailerid = getargument("trailerid") + local a_nocompression = getargument("nocompression") -- the following flag is not officially supported because i cannot forsee -- side effects (so no bug reports please) .. we provide --sandbox that @@ -707,21 +708,23 @@ function scripts.context.run(ctxdata,filename) scripts.context.make(formatname) end -- - local oldhash = multipass_hashfiles(jobname) - local newhash = { } - local maxnofruns = once and 1 or multipass_nofruns + local oldhash = multipass_hashfiles(jobname) + local newhash = { } + local maxnofruns = once and 1 or multipass_nofruns + local fulljobname = validstring(filename) -- local c_flags = { - directives = directives, -- gets passed via mtxrun - trackers = trackers, -- gets passed via mtxrun - experiments = experiments, -- gets passed via mtxrun + directives = directives, -- gets passed via mtxrun + trackers = trackers, -- gets passed via mtxrun + experiments = experiments, -- gets passed via mtxrun -- - result = validstring(resultname), - input = validstring(getargument("input") or filename), -- alternative input - fulljobname = validstring(filename), - files = concat(files,","), - ctx = validstring(ctxname), - export = a_export and true or nil, + result = validstring(resultname), + input = validstring(getargument("input") or filename), -- alternative input + fulljobname = fulljobname, + files = concat(files,","), + ctx = validstring(ctxname), + export = a_export and true or nil, + nocompression = a_nocompression and true or nil, } -- for k, v in next, environment.arguments do @@ -758,7 +761,7 @@ function scripts.context.run(ctxdata,filename) local directives = { } -- if a_nodates then - directives[#directives+1] = "backend.nodates" + directives[#directives+1] = format("backend.date=%s",type(a_nodates) == "string" and a_nodates or " no") end -- if a_trailerid then @@ -848,9 +851,9 @@ function scripts.context.run(ctxdata,filename) end -- if a_purge then - scripts.context.purge_job(jobname) + scripts.context.purge_job(jobname,false,false,fulljobname) elseif a_purgeall then - scripts.context.purge_job(jobname,true) + scripts.context.purge_job(jobname,true,false,fulljobname) end -- if resultname then @@ -864,11 +867,13 @@ function scripts.context.run(ctxdata,filename) report("result renamed to: %s",newbase) end -- - if purge then - scripts.context.purge_job(resultname) - elseif purgeall then - scripts.context.purge_job(resultname,true) - end + -- -- needs checking + -- + -- if a_purge then + -- scripts.context.purge_job(resultname) + -- elseif a_purgeall then + -- scripts.context.purge_job(resultname,true) + -- end -- local pdfview = getargument("autopdf") if pdfview then @@ -1243,6 +1248,9 @@ local temporary_runfiles = { "aux", "blg", -- bibtex } +local temporary_suffixes = { + "prep", -- context preprocessed +} local synctex_runfiles = { "synctex", "synctex.gz", -- synctex } @@ -1271,7 +1279,7 @@ local function purge_file(dfile,cfile) end end -function scripts.context.purge_job(jobname,all,mkiitoo) +function scripts.context.purge_job(jobname,all,mkiitoo,fulljobname) if jobname and jobname ~= "" then jobname = filebasename(jobname) local filebase = removesuffix(jobname) @@ -1285,6 +1293,11 @@ function scripts.context.purge_job(jobname,all,mkiitoo) for i=1,#temporary_runfiles do deleted[#deleted+1] = purge_file(fileaddsuffix(filebase,temporary_runfiles[i])) end + if fulljobname and fulljobname ~= jobname then + for i=1,#temporary_suffixes do + deleted[#deleted+1] = purge_file(fileaddsuffix(fulljobname,temporary_suffixes[i],true)) + end + end if not environment.argument("synctex") then -- special case: not deleted when --synctex is given, but what if given in preamble for i=1,#synctex_runfiles do diff --git a/Master/texmf-dist/scripts/context/lua/mtx-context.xml b/Master/texmf-dist/scripts/context/lua/mtx-context.xml index f5a67424165..2ba7ee59e07 100644 --- a/Master/texmf-dist/scripts/context/lua/mtx-context.xml +++ b/Master/texmf-dist/scripts/context/lua/mtx-context.xml @@ -129,7 +129,10 @@ run with synctex enabled (optional value: zipped, unzipped, 1, -1) - omit runtime dates in pdf file + omit runtime dates in pdf file (optional value: a number (this 1970 offset time) or string "YYYY-MM-DD HH:MM") + + + forcefully turns off compression in the backend alternative trailer id (or constant one) diff --git a/Master/texmf-dist/scripts/context/lua/mtx-modules.lua b/Master/texmf-dist/scripts/context/lua/mtx-modules.lua index f4003c1db12..572e6a304ce 100644 --- a/Master/texmf-dist/scripts/context/lua/mtx-modules.lua +++ b/Master/texmf-dist/scripts/context/lua/mtx-modules.lua @@ -58,7 +58,7 @@ local report = application.report -- \stoptypen -- -- Macro definitions specific to the documentation are not surrounded by --- start-stop commands. The suffix specificaction can be overruled at runtime, +-- start-stop commands. The suffix specification can be overruled at runtime, -- but defaults to the file extension. This specification can be used for language -- depended verbatim typesetting. -- diff --git a/Master/texmf-dist/scripts/context/lua/mtx-patterns.lua b/Master/texmf-dist/scripts/context/lua/mtx-patterns.lua index 716fed281bc..b3f5f5bb144 100644 --- a/Master/texmf-dist/scripts/context/lua/mtx-patterns.lua +++ b/Master/texmf-dist/scripts/context/lua/mtx-patterns.lua @@ -441,13 +441,13 @@ function scripts.patterns.save(destination,mnemonic,name,patternsnew,hyphenation if nofpatternsnew > 0 then local data = concat(patternsnew," ") patterndata = { - n = nofpatternsnew, - compression = compression, - length = #data, - data = compression and zlib.compress(data,9) or data, - characters = concat(table.sortedkeys(pusednew),""), - minhyphenmin = 1, -- determined by pattern author - minhyphenmax = 1, -- determined by pattern author + n = nofpatternsnew, + compression = compression, + length = #data, + data = compression and zlib.compress(data,9) or data, + characters = concat(table.sortedkeys(pusednew),""), + lefthyphenmin = 1, -- determined by pattern author + righthyphenmax = 1, -- determined by pattern author } else patterndata = { diff --git a/Master/texmf-dist/scripts/context/lua/mtx-plain.lua b/Master/texmf-dist/scripts/context/lua/mtx-plain.lua index 949b57952f5..347f63f1d0a 100644 --- a/Master/texmf-dist/scripts/context/lua/mtx-plain.lua +++ b/Master/texmf-dist/scripts/context/lua/mtx-plain.lua @@ -12,6 +12,8 @@ if not modules then modules = { } end modules ['mtx-plain'] = { -- instead of kpse here, just like with the font database code (as that -- one also works with kpse runtime) +local format = string.format + local helpinfo = [[ @@ -46,14 +48,18 @@ local report = application.report scripts = scripts or { } scripts.plain = scripts.plain or { } +local passed_options = table.tohash { + "utc" +} + local function execute(...) - local command = string.format(...) + local command = format(...) report("running command %a\n",command) return os.execute(command) end local function resultof(...) - local command = string.format(...) + local command = format(...) report("running command %a",command) local result = os.resultof(command) or "" result = string.gsub(result,"[\n\r]+","") @@ -72,7 +78,7 @@ function scripts.plain.make(texengine,texformat) report("using path expansion %a",fmtpathspec) else report("no valid path reported, trying alternative") --- fmtpathspec = resultof("kpsewhich --show-path=fmt --engine=%s",texengine) + -- fmtpathspec = resultof("kpsewhich --show-path=fmt --engine=%s",texengine) if fmtpathspec ~= "" then report("using path expansion %a",fmtpathspec) else @@ -108,7 +114,13 @@ end function scripts.plain.run(texengine,texformat,filename) local t = { } for k, v in next, environment.arguments do - t[#t+1] = string.format("--mtx:%s=%s",k,v) + local m = passed_options[k] and "" or "mtx:" + if type(v) == "string" and v ~= "" then + v = format("--%s%s=%s",m,k,v) + elseif v then + v = format("--%s%s",m,k) + end + t[#t+1] = v end execute('%s --fmt=%s %s "%s"',texengine,file.removesuffix(texformat),table.concat(t," "),filename) end diff --git a/Master/texmf-dist/tex/context/base/context-version.pdf b/Master/texmf-dist/tex/context/base/context-version.pdf index a1a04de92c1..fbb5c71c981 100644 Binary files a/Master/texmf-dist/tex/context/base/context-version.pdf and b/Master/texmf-dist/tex/context/base/context-version.pdf differ diff --git a/Master/texmf-dist/tex/context/base/mkiv/back-pdf.lua b/Master/texmf-dist/tex/context/base/mkiv/back-pdf.lua index 0821abb2895..323f1d57fcf 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/back-pdf.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/back-pdf.lua @@ -25,6 +25,8 @@ local scankeyword = scanners.keyword local scanners = interfaces.scanners local implement = interfaces.implement +local report = logs.reporter("backend") + local outputfilename function codeinjections.getoutputfilename() @@ -145,6 +147,15 @@ scanners.pdfstartmirroring = function() context(pdfsetmatrix(-1,0,0,1)) end +if environment.arguments.nocompression then + pdf.setcompresslevel(0) + pdf.setobjcompresslevel(0) + function pdf.setcompresslevel() + -- blocked from now on + end + pdf.setobjcompresslevel = pdf.setcompresslevel +end + scanners.pdfstopmirroring = scanners.pdfstartmirroring -- todo, change the above to implement too -- diff --git a/Master/texmf-dist/tex/context/base/mkiv/char-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/char-ini.lua index ad53cae8f34..63328a177a3 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/char-ini.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/char-ini.lua @@ -1083,8 +1083,8 @@ if not characters.lhash then lhash[utfchar(k)] = utfchar(l) elseif #l == 2 then lhash[utfchar(k)] = utfchar(l[1]) .. utfchar(l[2]) - else - inspect(v) + -- else + -- inspect(v) end else local u = v.uccode @@ -1094,8 +1094,8 @@ if not characters.lhash then uhash[utfchar(k)] = utfchar(u) elseif #u == 2 then uhash[utfchar(k)] = utfchar(u[1]) .. utfchar(u[2]) - else - inspect(v) + -- else + -- inspect(v) end end end @@ -1105,8 +1105,8 @@ if not characters.lhash then shash[utfchar(k)] = utfchar(s) elseif #s == 2 then shash[utfchar(k)] = utfchar(s[1]) .. utfchar(s[2]) - else - inspect(v) + -- else + -- inspect(v) end end -- end diff --git a/Master/texmf-dist/tex/context/base/mkiv/cont-new.mkiv b/Master/texmf-dist/tex/context/base/mkiv/cont-new.mkiv index 3e5ff1ffc1f..1b0ec7432ea 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/cont-new.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/cont-new.mkiv @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2016.05.01 09:52} +\newcontextversion{2016.05.08 17:30} %D This file is loaded at runtime, thereby providing an excellent place for %D hacks, patches, extensions and new features. diff --git a/Master/texmf-dist/tex/context/base/mkiv/context-todo.tex b/Master/texmf-dist/tex/context/base/mkiv/context-todo.tex index 0674ad9fbda..66889c4d37c 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/context-todo.tex +++ b/Master/texmf-dist/tex/context/base/mkiv/context-todo.tex @@ -18,6 +18,13 @@ \startitem add \type {--output-filename} for \PDF\ filename \stopitem + \startitem + more consistent \type {lang_variables} and \type {tex_language} in \type + {texlang.w} and also store the \type {*mins} + \stopitem + \startitem + get rid of \type {temp} node in hyphenator i.e. postpone to when needed + \stopitem \stopitemize \subsubject{\CONTEXT} @@ -33,7 +40,7 @@ play with box attributes \stopitem \startitem - check consistency between foonotes and running text (main color, + check consistency between footnotes and running text (main color, styles, properties) \stopitem \startitem diff --git a/Master/texmf-dist/tex/context/base/mkiv/context.mkiv b/Master/texmf-dist/tex/context/base/mkiv/context.mkiv index 7ec285ed137..c66b2856a33 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/context.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/context.mkiv @@ -39,7 +39,7 @@ %D up and the dependencies are more consistent. \edef\contextformat {\jobname} -\edef\contextversion{2016.05.01 09:52} +\edef\contextversion{2016.05.08 17:30} \edef\contextkind {beta} %D For those who want to use this: diff --git a/Master/texmf-dist/tex/context/base/mkiv/core-con.lua b/Master/texmf-dist/tex/context/base/mkiv/core-con.lua index bfe5357a6ec..6913ac569a2 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/core-con.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/core-con.lua @@ -19,8 +19,9 @@ slower but look nicer this way.

local floor, date, time, concat = math.floor, os.date, os.time, table.concat local lower, upper, rep, match, gsub = string.lower, string.upper, string.rep, string.match, string.gsub local utfchar, utfbyte = utf.char, utf.byte -local tonumber, tostring = tonumber, tostring -local P, C, Cs, lpegmatch = lpeg.P, lpeg.C, lpeg.Cs, lpeg.match +local tonumber, tostring, type, rawset = tonumber, tostring, type, rawset +local P, S, R, Cc, Cf, Cg, Ct, Cs, C = lpeg.P, lpeg.S, lpeg.R, lpeg.Cc, lpeg.Cf, lpeg.Cg, lpeg.Ct, lpeg.Cs, lpeg.C +local lpegmatch = lpeg.match local context = context local commands = commands @@ -33,6 +34,8 @@ local formatters = string.formatters local variables = interfaces.variables local constants = interfaces.constants +local texset = tex.set + converters = converters or { } local converters = converters @@ -1355,3 +1358,39 @@ implement { actions = { formatters["U+%05X"], context }, arguments = "integer" } + +local n = lpeg.R("09")^1 / tonumber + +local p = Cf( Ct("") + * Cg(Cc("year") * (n )) * P("-")^-1 + * Cg(Cc("month") * (n + Cc( 1))) * P("-")^-1 + * Cg(Cc("day") * (n + Cc( 1))) * lpeg.patterns.whitespace^-1 + * Cg(Cc("hour") * (n + Cc( 0))) * P(":")^-1 + * Cg(Cc("min") * (n + Cc( 0))) + , rawset) + +function converters.totime(s) + if not s then + return + elseif type(s) == "table" then + return s + elseif type(s) == "string" then + return lpegmatch(p,s) + end + local n = tonumber(s) + if n and n >= 0 then + return date("*t",n) + end +end + +function converters.settime(t) + if type(t) ~= "table" then + t = converters.totime(t) + end + if t then + texset("year", t.year or 1000) + texset("month", t.month or 1) + texset("day", t.day or 1) + texset("time", (t.hour or 0) * 60 + (t.min or 0)) + end +end diff --git a/Master/texmf-dist/tex/context/base/mkiv/core-con.mkiv b/Master/texmf-dist/tex/context/base/mkiv/core-con.mkiv index 1f6dc54d5e6..8565a30965b 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/core-con.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/core-con.mkiv @@ -250,8 +250,8 @@ \newcount\normalweekday - \def\dayoftheweek #1#2#3{\clf_weekdayname\numexpr#1\relax\numexpr#2\relax,\numexpr#3\relax} % name -\unexpanded\def\getdayoftheweek#1#2#3{\normalweekday\clf_weekday\numexpr#1\relax\numexpr#2\relax,\numexpr#3\relax\relax} % number + \def\dayoftheweek #1#2#3{\clf_weekdayname\numexpr#1\relax\numexpr#2\relax\numexpr#3\relax} % name +\unexpanded\def\getdayoftheweek#1#2#3{\normalweekday\clf_weekday\numexpr#1\relax\numexpr#2\relax\numexpr#3\relax\relax} % number %D Using this macro in %D diff --git a/Master/texmf-dist/tex/context/base/mkiv/core-ctx.lua b/Master/texmf-dist/tex/context/base/mkiv/core-ctx.lua index c20691cd7be..1f22402e65b 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/core-ctx.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/core-ctx.lua @@ -37,6 +37,7 @@ local gsub, find, match, validstring = string.gsub, string.find, string.match, s local concat = table.concat local xmltext = xml.text +local report_jobfile = logs.reporter("system","jobfile") local report_prepfiles = logs.reporter("system","prepfiles") local commands = commands @@ -94,6 +95,8 @@ end function ctxrunner.load(ctxname) + report_jobfile("processing %a",ctxname) + local xmldata = xml.load(ctxname) local jobname = tex.jobname -- todo @@ -138,7 +141,7 @@ function ctxrunner.load(ctxname) end for e in xml.collected(xmldata,"ctx:message") do - report_prepfiles("ctx comment: %s", xmltext(e)) + report_jobfile("ctx comment: %s", xmltext(e)) end for r, d, k in xml.elements(xmldata,"ctx:value[@name='job']") do @@ -192,17 +195,21 @@ function ctxrunner.load(ctxname) pattern =justtext(xml.tostring(pattern)) if preprocessor and preprocessor ~= "" and pattern and pattern ~= "" then local noftreatments = #treatments + 1 - local findpattern = string.topattern(pattern) + local findpattern = string.topattern(pattern) local preprocessors = utilities.parsers.settings_to_array(preprocessor) treatments[noftreatments] = { pattern = findpattern, preprocessors = preprocessors, } - report_prepfiles("step %s, pattern %a, preprocessor: %a",noftreatments,findpattern,preprocessors) + report_jobfile("step %s, pattern %a, preprocessor: %a",noftreatments,findpattern,preprocessors) end end end + if #treatments == 0 then + report_jobfile("no treatments needed") + end + local function needstreatment(oldfile) for i=1,#treatments do local treatment = treatments[i] @@ -215,6 +222,8 @@ function ctxrunner.load(ctxname) local preparefile = #treatments > 0 and function(prepfiles,filename) + filename = file.collapsepath(filename) + local treatment = needstreatment(filename) local oldfile = filename local newfile = false @@ -244,9 +253,12 @@ function ctxrunner.load(ctxname) end end end + oldname = file.collapsepath(oldname) + newname = file.collapsepath(newname) if not newfile then newfile = filename - elseif file.needsupdating(filename,newfile) then + report_prepfiles("%a is not converted to %a",filename,newfile) + elseif not lfs.isfile(newfile) or file.needsupdating(filename,newfile) then for i=1,#runners do report_prepfiles("step %i: %s",i,runners[i]) end @@ -258,6 +270,8 @@ function ctxrunner.load(ctxname) -- if result > 0 then -- report_prepfiles("error, return code: %s",result) -- end + logs.newline() + logs.newline() end if lfs.isfile(newfile) then file.syncmtimes(filename,newfile) @@ -268,6 +282,8 @@ function ctxrunner.load(ctxname) end elseif lfs.isfile(newfile) then report_prepfiles("%a is already converted to %a",filename,newfile) + else + report_prepfiles("unknown error when converting %a to %a",filename,newfile) end else newfile = filename diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-chk.lua b/Master/texmf-dist/tex/context/base/mkiv/font-chk.lua index 5b1ad992070..15291052fe3 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-chk.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-chk.lua @@ -437,7 +437,7 @@ local function adddummysymbols(tfmdata,...) -- end end -registerotffeature { +local dummies_specification = { name = "dummies", description = "dummy symbols", default = true, @@ -447,15 +447,8 @@ registerotffeature { } } -registerafmfeature { - name = "dummies", - description = "dummy symbols", - default = true, - manipulators = { - base = adddummysymbols, - node = adddummysymbols, - } -} +registerotffeature(dummies_specification) +registerafmfeature(dummies_specification) -- callback.register("char_exists",function(f,c) -- to slow anyway as called often so we should flag in tfmdata -- return true diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-enh.lua b/Master/texmf-dist/tex/context/base/mkiv/font-enh.lua index 3439a434ab4..f3209f5ee10 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-enh.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-enh.lua @@ -173,7 +173,7 @@ local function initializeunicoding(tfmdata) end end -registerafmfeature { +local unicoding_specification = { name = "unicoding", description = "adapt unicode table", initializers = { @@ -186,15 +186,5 @@ registerafmfeature { -- } } -registerotffeature { - name = "unicoding", - description = "adapt unicode table", - initializers = { - base = initializeunicoding, - node = initializeunicoding, - }, - -- manipulators = { - -- base = finalizeunicoding, - -- node = finalizeunicoding, - -- } -} +registerotffeature(unicoding_specification) +registerafmfeature(unicoding_specification) diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-ext.lua b/Master/texmf-dist/tex/context/base/mkiv/font-ext.lua index 79144aa70e3..189a588f146 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-ext.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-ext.lua @@ -149,7 +149,7 @@ local function initializeexpansion(tfmdata,value) end end -registerotffeature { +local expansion_specification = { name = "expansion", description = "apply hz optimization", initializers = { @@ -158,14 +158,8 @@ registerotffeature { } } -registerafmfeature { - name = "expansion", - description = "apply hz optimization", - initializers = { - base = initializeexpansion, - node = initializeexpansion, - } -} +registerotffeature(expansion_specification) +registerafmfeature(expansion_specification) fonts.goodies.register("expansions", function(...) return fonts.goodies.report("expansions", trace_expansion, ...) end) @@ -466,7 +460,7 @@ local function initializeprotrusion(tfmdata,value) end end -registerotffeature { +local protrusion_specification = { name = "protrusion", description = "l/r margin character protrusion", initializers = { @@ -475,14 +469,8 @@ registerotffeature { } } -registerafmfeature { - name = "protrusion", - description = "shift characters into the left and or right margin", - initializers = { - base = initializeprotrusion, - node = initializeprotrusion, - } -} +registerotffeature(protrusion_specification) +registerafmfeature(protrusion_specification) fonts.goodies.register("protrusions", function(...) return fonts.goodies.report("protrusions", trace_protrusion, ...) end) @@ -534,7 +522,7 @@ local function initializeitlc(tfmdata,value) -- hm, always value end end -registerotffeature { +local italic_specification = { name = "itlc", description = "italic correction", initializers = { @@ -543,20 +531,14 @@ registerotffeature { } } -registerafmfeature { - name = "itlc", - description = "italic correction", - initializers = { - base = initializeitlc, - node = initializeitlc, - } -} +registerotffeature(italic_specification) +registerafmfeature(italic_specification) local function initializetextitalics(tfmdata,value) -- yes no delay tfmdata.properties.textitalics = toboolean(value) end -registerotffeature { +local textitalics_specification = { name = "textitalics", description = "use alternative text italic correction", initializers = { @@ -565,20 +547,14 @@ registerotffeature { } } -registerafmfeature { - name = "textitalics", - description = "use alternative text italic correction", - initializers = { - base = initializetextitalics, - node = initializetextitalics, - } -} +registerotffeature(textitalics_specification) +registerafmfeature(textitalics_specification) local function initializemathitalics(tfmdata,value) -- yes no delay tfmdata.properties.mathitalics = toboolean(value) end -registerotffeature { +local mathitalics_specification = { name = "mathitalics", description = "use alternative math italic correction", initializers = { @@ -587,14 +563,8 @@ registerotffeature { } } -registerafmfeature { - name = "mathitalics", - description = "use alternative math italic correction", - initializers = { - base = initializemathitalics, - node = initializemathitalics, - } -} +registerotffeature(mathitalics_specification) +registerafmfeature(mathitalics_specification) -- slanting @@ -610,7 +580,7 @@ local function initializeslant(tfmdata,value) tfmdata.parameters.slantfactor = value end -registerotffeature { +local slant_specification = { name = "slant", description = "slant glyphs", initializers = { @@ -619,14 +589,8 @@ registerotffeature { } } -registerafmfeature { - name = "slant", - description = "slant glyphs", - initializers = { - base = initializeslant, - node = initializeslant, - } -} +registerotffeature(slant_specification) +registerafmfeature(slant_specification) local function initializeextend(tfmdata,value) value = tonumber(value) @@ -640,7 +604,7 @@ local function initializeextend(tfmdata,value) tfmdata.parameters.extendfactor = value end -registerotffeature { +local extend_specification = { name = "extend", description = "scale glyphs horizontally", initializers = { @@ -649,14 +613,8 @@ registerotffeature { } } -registerafmfeature { - name = "extend", - description = "scale glyphs horizontally", - initializers = { - base = initializeextend, - node = initializeextend, - } -} +registerotffeature(extend_specification) +registerafmfeature(extend_specification) -- For Wolfgang Schuster: -- @@ -745,7 +703,7 @@ local function manipulatedimensions(tfmdata,key,value) end end -registerotffeature { +local dimensions_specification = { name = "dimensions", description = "force dimensions", manipulators = { @@ -754,6 +712,9 @@ registerotffeature { } } +registerotffeature(dimensions_specification) +registerafmfeature(dimensions_specification) + -- for zhichu chen (see mailing list archive): we might add a few more variants -- in due time -- diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-fbk.lua b/Master/texmf-dist/tex/context/base/mkiv/font-fbk.lua index 9ef0706d235..3734e8071bf 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-fbk.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-fbk.lua @@ -251,7 +251,7 @@ local function composecharacters(tfmdata) end end -registerotffeature { +local compose_specification = { name = "compose", description = "additional composed characters", manipulators = { @@ -260,14 +260,8 @@ registerotffeature { } } -registerafmfeature { - name = "compose", - description = "additional composed characters", - manipulators = { - base = composecharacters, - node = composecharacters, - } -} +registerotffeature(compose_specification) +registerafmfeature(compose_specification) vf.helpers.composecharacters = composecharacters diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-gbn.lua b/Master/texmf-dist/tex/context/base/mkiv/font-gbn.lua index daa072b4bc2..a02406b756f 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-gbn.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-gbn.lua @@ -126,17 +126,19 @@ function nodes.handlers.nodepass(head) local variant = hash[getchar(p)] if variant then setchar(p,variant) - if not redundant then - redundant = { n } - else - redundant[#redundant+1] = n - end end end end + -- per generic user request we always remove selectors + if not redundant then + redundant = { n } + else + redundant[#redundant+1] = n + end end end end + local nofbasefonts = #basefonts if redundant then for i=1,#redundant do local r = redundant[i] @@ -147,8 +149,8 @@ function nodes.handlers.nodepass(head) else setlink(p,n) end - if b > 0 then - for i=1,b do + if nofbasefonts > 0 then + for i=1,nofbasefonts do local bi = basefonts[i] if r == bi[1] then bi[1] = n @@ -192,8 +194,8 @@ function nodes.handlers.nodepass(head) end end end - if basemodepass and #basefonts > 0 then - for i=1,#basefonts do + if basemodepass and nofbasefonts > 0 then + for i=1,nofbasefonts do local range = basefonts[i] local start = range[1] local stop = range[2] diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-gds.lua b/Master/texmf-dist/tex/context/base/mkiv/font-gds.lua index 23bbad42f63..52bb9c98352 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-gds.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-gds.lua @@ -465,9 +465,9 @@ local function setextensions(tfmdata) end end --- installation (collected to keep the overview) -- also for type 1 +-- installation -registerotffeature { +local goodies_specification = { name = "goodies", description = "goodies on top of built in features", initializers = { @@ -477,6 +477,12 @@ registerotffeature { } } +registerotffeature(goodies_specification) +registerafmfeature(goodies_specification) +registertfmfeature(goodies_specification) + +-- maybe more of the following could be for type one too + registerotffeature { name = "extrafeatures", description = "extra features", @@ -527,30 +533,6 @@ registerotffeature { } } --- afm - -registerafmfeature { - name = "goodies", - description = "goodies on top of built in features", - initializers = { - position = 1, - base = setgoodies, - node = setgoodies, - } -} - --- tfm - -registertfmfeature { - name = "goodies", - description = "goodies on top of built in features", - initializers = { - position = 1, - base = setgoodies, - node = setgoodies, - } -} - -- experiment, we have to load the definitions immediately as they precede -- the definition so they need to be initialized in the typescript diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-lib.mkvi b/Master/texmf-dist/tex/context/base/mkiv/font-lib.mkvi index 7bb042a5943..90de409d138 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-lib.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/font-lib.mkvi @@ -36,9 +36,6 @@ \registerctxluafile{font-tfm}{1.001} -\registerctxluafile{font-afm}{1.001} -\registerctxluafile{font-afk}{1.001} - \registerctxluafile{font-hsh}{1.001} % hashes used by context \registerctxluafile{font-nod}{1.001} @@ -58,6 +55,12 @@ \registerctxluafile{font-oth}{1.001} \registerctxluafile{font-osd}{1.001} +% we use otf code for type one + +\registerctxluafile{font-one}{1.001} +%registerctxluafile{font-afm}{1.001} +\registerctxluafile{font-afk}{1.001} + % so far \registerctxluafile{font-pat}{1.001} % patchers diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-one.lua b/Master/texmf-dist/tex/context/base/mkiv/font-one.lua new file mode 100644 index 00000000000..3602fd4650a --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/font-one.lua @@ -0,0 +1,1220 @@ +if not modules then modules = { } end modules ['font-one'] = { + version = 1.001, + comment = "companion to font-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +--[[ldx-- +

Some code may look a bit obscure but this has to do with the fact that we also use +this code for testing and much code evolved in the transition from to + to .

+ +

The following code still has traces of intermediate font support where we handles +font encodings. Eventually font encoding went away but we kept some code around in +other modules.

+ +

This version implements a node mode approach so that users can also more easily +add features.

+--ldx]]-- + +local fonts, logs, trackers, containers, resolvers = fonts, logs, trackers, containers, resolvers + +local next, type, tonumber = next, type, tonumber +local match, gmatch, lower, gsub, strip, find = string.match, string.gmatch, string.lower, string.gsub, string.strip, string.find +local char, byte, sub = string.char, string.byte, string.sub +local abs = math.abs +local bxor, rshift = bit32.bxor, bit32.rshift +local P, S, R, Cmt, C, Ct, Cs, lpegmatch, patterns = lpeg.P, lpeg.S, lpeg.R, lpeg.Cmt, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.match, lpeg.patterns +local derivetable = table.derive + +local trace_features = false trackers.register("afm.features", function(v) trace_features = v end) +local trace_indexing = false trackers.register("afm.indexing", function(v) trace_indexing = v end) +local trace_loading = false trackers.register("afm.loading", function(v) trace_loading = v end) +local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end) + +local report_afm = logs.reporter("fonts","afm loading") + +local setmetatableindex = table.setmetatableindex + +local findbinfile = resolvers.findbinfile + +local definers = fonts.definers +local readers = fonts.readers +local constructors = fonts.constructors + +local afm = constructors.newhandler("afm") +local pfb = constructors.newhandler("pfb") +local otf = fonts.handlers.otf + +local otfreaders = otf.readers +local otfenhancers = otf.enhancers + +local afmfeatures = constructors.newfeatures("afm") +local registerafmfeature = afmfeatures.register + +afm.version = 1.505 -- incrementing this number one up will force a re-cache +afm.cache = containers.define("fonts", "afm", afm.version, true) +afm.autoprefixed = true -- this will become false some day (catches texnansi-blabla.*) + +afm.helpdata = { } -- set later on so no local for this +afm.syncspace = true -- when true, nicer stretch values + +local overloads = fonts.mappings.overloads + +local applyruntimefixes = fonts.treatments and fonts.treatments.applyfixes + +--[[ldx-- +

We start with the basic reader which we give a name similar to the +built in and reader.

+--ldx]]-- + +--~ Comment FONTIDENTIFIER LMMATHSYMBOLS10 +--~ Comment CODINGSCHEME TEX MATH SYMBOLS +--~ Comment DESIGNSIZE 10.0 pt +--~ Comment CHECKSUM O 4261307036 +--~ Comment SPACE 0 plus 0 minus 0 +--~ Comment QUAD 1000 +--~ Comment EXTRASPACE 0 +--~ Comment NUM 676.508 393.732 443.731 +--~ Comment DENOM 685.951 344.841 +--~ Comment SUP 412.892 362.892 288.889 +--~ Comment SUB 150 247.217 +--~ Comment SUPDROP 386.108 +--~ Comment SUBDROP 50 +--~ Comment DELIM 2390 1010 +--~ Comment AXISHEIGHT 250 + +local comment = P("Comment") +local spacing = patterns.spacer -- S(" \t")^1 +local lineend = patterns.newline -- S("\n\r") +local words = C((1 - lineend)^1) +local number = C((R("09") + S("."))^1) / tonumber * spacing^0 +local data = lpeg.Carg(1) + +local pattern = ( -- needs testing ... not used anyway as we no longer need math afm's + comment * spacing * + ( + data * ( + ("CODINGSCHEME" * spacing * words ) / function(fd,a) end + + ("DESIGNSIZE" * spacing * number * words ) / function(fd,a) fd[ 1] = a end + + ("CHECKSUM" * spacing * number * words ) / function(fd,a) fd[ 2] = a end + + ("SPACE" * spacing * number * "plus" * number * "minus" * number) / function(fd,a,b,c) fd[ 3], fd[ 4], fd[ 5] = a, b, c end + + ("QUAD" * spacing * number ) / function(fd,a) fd[ 6] = a end + + ("EXTRASPACE" * spacing * number ) / function(fd,a) fd[ 7] = a end + + ("NUM" * spacing * number * number * number ) / function(fd,a,b,c) fd[ 8], fd[ 9], fd[10] = a, b, c end + + ("DENOM" * spacing * number * number ) / function(fd,a,b ) fd[11], fd[12] = a, b end + + ("SUP" * spacing * number * number * number ) / function(fd,a,b,c) fd[13], fd[14], fd[15] = a, b, c end + + ("SUB" * spacing * number * number ) / function(fd,a,b) fd[16], fd[17] = a, b end + + ("SUPDROP" * spacing * number ) / function(fd,a) fd[18] = a end + + ("SUBDROP" * spacing * number ) / function(fd,a) fd[19] = a end + + ("DELIM" * spacing * number * number ) / function(fd,a,b) fd[20], fd[21] = a, b end + + ("AXISHEIGHT" * spacing * number ) / function(fd,a) fd[22] = a end + ) + + (1-lineend)^0 + ) + + (1-comment)^1 +)^0 + +local function scan_comment(str) + local fd = { } + lpegmatch(pattern,str,1,fd) + return fd +end + +-- On a rainy day I will rewrite this in lpeg ... or we can use the (slower) fontloader +-- as in now supports afm/pfb loading but it's not too bad to have different methods +-- for testing approaches. + +local keys = { } + +function keys.FontName (data,line) data.metadata.fontname = strip (line) -- get rid of spaces + data.metadata.fullname = strip (line) end +function keys.ItalicAngle (data,line) data.metadata.italicangle = tonumber (line) end +function keys.IsFixedPitch(data,line) data.metadata.monospaced = toboolean(line,true) end +function keys.CharWidth (data,line) data.metadata.charwidth = tonumber (line) end +function keys.XHeight (data,line) data.metadata.xheight = tonumber (line) end +function keys.Descender (data,line) data.metadata.descender = tonumber (line) end +function keys.Ascender (data,line) data.metadata.ascender = tonumber (line) end +function keys.Comment (data,line) + -- Comment DesignSize 12 (pts) + -- Comment TFM designsize: 12 (in points) + line = lower(line) + local designsize = match(line,"designsize[^%d]*(%d+)") + if designsize then data.metadata.designsize = tonumber(designsize) end +end + +local function get_charmetrics(data,charmetrics,vector) + local characters = data.characters + local chr, ind = { }, 0 + for k, v in gmatch(charmetrics,"([%a]+) +(.-) *;") do + if k == 'C' then + v = tonumber(v) + if v < 0 then + ind = ind + 1 -- ? + else + ind = v + end + chr = { + index = ind + } + elseif k == 'WX' then + chr.width = tonumber(v) + elseif k == 'N' then + characters[v] = chr + elseif k == 'B' then + local llx, lly, urx, ury = match(v,"^ *(.-) +(.-) +(.-) +(.-)$") + chr.boundingbox = { tonumber(llx), tonumber(lly), tonumber(urx), tonumber(ury) } + elseif k == 'L' then + local plus, becomes = match(v,"^(.-) +(.-)$") + local ligatures = chr.ligatures + if ligatures then + ligatures[plus] = becomes + else + chr.ligatures = { [plus] = becomes } + end + end + end +end + +local function get_kernpairs(data,kernpairs) + local characters = data.characters + for one, two, value in gmatch(kernpairs,"KPX +(.-) +(.-) +(.-)\n") do + local chr = characters[one] + if chr then + local kerns = chr.kerns + if kerns then + kerns[two] = tonumber(value) + else + chr.kerns = { [two] = tonumber(value) } + end + end + end +end + +local function get_variables(data,fontmetrics) + for key, rest in gmatch(fontmetrics,"(%a+) *(.-)[\n\r]") do + local keyhandler = keys[key] + if keyhandler then + keyhandler(data,rest) + end + end +end + +-- new (unfinished) pfb loader but i see no differences between +-- old and new (one bad vector with old) + +local get_indexes + +do + + local n, m + + local progress = function(str,position,name,size) + local forward = position + tonumber(size) + 3 + 2 + n = n + 1 + if n >= m then + return #str, name + elseif forward < #str then + return forward, name + else + return #str, name + end + end + + local initialize = function(str,position,size) + n = 0 + m = tonumber(size) + return position + 1 + end + + local charstrings = P("/CharStrings") + local name = P("/") * C((R("az")+R("AZ")+R("09")+S("-_."))^1) + local size = C(R("09")^1) + local spaces = P(" ")^1 + + local p_filternames = Ct ( + (1-charstrings)^0 * charstrings * spaces * Cmt(size,initialize) + * (Cmt(name * P(" ")^1 * C(R("09")^1), progress) + P(1))^1 + ) + + -- if one of first 4 not 0-9A-F then binary else hex + + local decrypt + + do + + local r, c1, c2, n = 0, 0, 0, 0 + + local function step(c) + local cipher = byte(c) + local plain = bxor(cipher,rshift(r,8)) + r = ((cipher + r) * c1 + c2) % 65536 + return char(plain) + end + + decrypt = function(binary) + r, c1, c2, n = 55665, 52845, 22719, 4 + binary = gsub(binary,".",step) + return sub(binary,n+1) + end + + -- local pattern = Cs((P(1) / step)^1) + -- + -- decrypt = function(binary) + -- r, c1, c2, n = 55665, 52845, 22719, 4 + -- binary = lpegmatch(pattern,binary) + -- return sub(binary,n+1) + -- end + + end + + local function loadpfbvector(filename) + -- for the moment limited to encoding only + + local data = io.loaddata(resolvers.findfile(filename)) + + if not find(data,"!PS%-AdobeFont%-") then + print("no font",filename) + return + end + + if not data then + print("no data",filename) + return + end + + local ascii, binary = match(data,"(.*)eexec%s+......(.*)") + + if not binary then + print("no binary",filename) + return + end + + binary = decrypt(binary,4) + + local vector = lpegmatch(p_filternames,binary) + + vector[0] = table.remove(vector,1) + + if not vector then + print("no vector",filename) + return + end + + return vector + + end + + get_indexes = function(data,pfbname) + local vector = loadpfbvector(pfbname) + if vector then + local characters = data.characters + if trace_loading then + report_afm("getting index data from %a",pfbname) + end + for index=1,#vector do + local name = vector[index] + local char = characters[name] + if char then + if trace_indexing then + report_afm("glyph %a has index %a",name,index) + end + char.index = index + end + end + end + end + +end + +local function readafm(filename) + local ok, afmblob, size = resolvers.loadbinfile(filename) -- has logging + if ok and afmblob then + local data = { + resources = { + filename = resolvers.unresolve(filename), + version = afm.version, + creator = "context mkiv", + }, + properties = { + hasitalics = false, + }, + goodies = { + }, + metadata = { + filename = file.removesuffix(file.basename(filename)) + }, + characters = { + -- a temporary store + }, + descriptions = { + -- the final store + }, + } + afmblob = gsub(afmblob,"StartCharMetrics(.-)EndCharMetrics", function(charmetrics) + if trace_loading then + report_afm("loading char metrics") + end + get_charmetrics(data,charmetrics,vector) + return "" + end) + afmblob = gsub(afmblob,"StartKernPairs(.-)EndKernPairs", function(kernpairs) + if trace_loading then + report_afm("loading kern pairs") + end + get_kernpairs(data,kernpairs) + return "" + end) + afmblob = gsub(afmblob,"StartFontMetrics%s+([%d%.]+)(.-)EndFontMetrics", function(version,fontmetrics) + if trace_loading then + report_afm("loading variables") + end + data.afmversion = version + get_variables(data,fontmetrics) + data.fontdimens = scan_comment(fontmetrics) -- todo: all lpeg, no time now + return "" + end) + return data + else + if trace_loading then + report_afm("no valid afm file %a",filename) + end + return nil + end +end + +--[[ldx-- +

We cache files. Caching is taken care of in the loader. We cheat a bit by adding +ligatures and kern information to the afm derived data. That way we can set them faster +when defining a font.

+ +

We still keep the loading two phased: first we load the data in a traditional +fashion and later we transform it to sequences.

+--ldx]]-- + +local addkerns, unify, normalize, fixnames, addligatures, addtexligatures + +function afm.load(filename) + filename = resolvers.findfile(filename,'afm') or "" + if filename ~= "" and not fonts.names.ignoredfile(filename) then + local name = file.removesuffix(file.basename(filename)) + local data = containers.read(afm.cache,name) + local attr = lfs.attributes(filename) + local size, time = attr.size or 0, attr.modification or 0 + -- + local pfbfile = file.replacesuffix(name,"pfb") + local pfbname = resolvers.findfile(pfbfile,"pfb") or "" + if pfbname == "" then + pfbname = resolvers.findfile(file.basename(pfbfile),"pfb") or "" + end + local pfbsize, pfbtime = 0, 0 + if pfbname ~= "" then + local attr = lfs.attributes(pfbname) + pfbsize = attr.size or 0 + pfbtime = attr.modification or 0 + end + if not data or data.size ~= size or data.time ~= time or data.pfbsize ~= pfbsize or data.pfbtime ~= pfbtime then + report_afm("reading %a",filename) + data = readafm(filename) + if data then + if pfbname ~= "" then + data.resources.filename = resolvers.unresolve(pfbname) + get_indexes(data,pfbname) + elseif trace_loading then + report_afm("no pfb file for %a",filename) + -- data.resources.filename = "unset" -- better than loading the afm file + end + -- we now have all the data loaded + if trace_loading then + report_afm("unifying %a",filename) + end + unify(data,filename) + if trace_loading then + report_afm("add ligatures") -- there can be missing ones + end + addligatures(data) + if trace_loading then + report_afm("add extra kerns") + end + addkerns(data) + if trace_loading then + report_afm("normalizing") + end + normalize(data) + if trace_loading then + report_afm("fixing names") + end + fixnames(data) + if trace_loading then + report_afm("add tounicode data") + end + -- otfreaders.addunicodetable(data) -- only when not done yet + fonts.mappings.addtounicode(data,filename) + -- otfreaders.extend(data) + otfreaders.pack(data) + data.size = size + data.time = time + data.pfbsize = pfbsize + data.pfbtime = pfbtime + report_afm("saving %a in cache",name) + -- data.resources.unicodes = nil -- consistent with otf but here we save not much + data = containers.write(afm.cache, name, data) + data = containers.read(afm.cache,name) + end + end + if data then + -- constructors.addcoreunicodes(unicodes) + otfreaders.unpack(data) + otfreaders.expand(data) -- inline tables + otfreaders.addunicodetable(data) -- only when not done yet + otfenhancers.apply(data,filename,data) + if applyruntimefixes then + applyruntimefixes(filename,data) + end + end + return data + else + return nil + end +end + +local uparser = fonts.mappings.makenameparser() + +unify = function(data, filename) + local unicodevector = fonts.encodings.agl.unicodes -- loaded runtime in context + local unicodes = { } + local names = { } + local private = constructors.privateoffset + local descriptions = data.descriptions + for name, blob in next, data.characters do + local code = unicodevector[name] -- or characters.name_to_unicode[name] + if not code then + code = lpegmatch(uparser,name) + if not code then + code = private + private = private + 1 + report_afm("assigning private slot %U for unknown glyph name %a",code,name) + end + end + local index = blob.index + unicodes[name] = code + names[name] = index + blob.name = name + descriptions[code] = { + boundingbox = blob.boundingbox, + width = blob.width, + kerns = blob.kerns, + index = index, + name = name, + } + end + for unicode, description in next, descriptions do + local kerns = description.kerns + if kerns then + local krn = { } + for name, kern in next, kerns do + local unicode = unicodes[name] + if unicode then + krn[unicode] = kern + else + -- print(unicode,name) + end + end + description.kerns = krn + end + end + data.characters = nil + local resources = data.resources + local filename = resources.filename or file.removesuffix(file.basename(filename)) + resources.filename = resolvers.unresolve(filename) -- no shortcut + resources.unicodes = unicodes -- name to unicode + resources.marks = { } -- todo + -- resources.names = names -- name to index + resources.private = private +end + +local everywhere = { ["*"] = { ["*"] = true } } -- or: { ["*"] = { "*" } } +local noflags = { false, false, false, false } + +normalize = function(data) + local ligatures = setmetatableindex("table") + local kerns = setmetatableindex("table") + local extrakerns = setmetatableindex("table") + for u, c in next, data.descriptions do + local l = c.ligatures + local k = c.kerns + local e = c.extrakerns + if l then + ligatures[u] = l + for u, v in next, l do + l[u] = { ligature = v } + end + c.ligatures = nil + end + if k then + kerns[u] = k + for u, v in next, k do + k[u] = v -- { v, 0 } + end + c.kerns = nil + end + if e then + extrakerns[u] = e + for u, v in next, e do + e[u] = v -- { v, 0 } + end + c.extrakerns = nil + end + end + local features = { + gpos = { }, + gsub = { }, + } + local sequences = { + -- only filled ones + } + if next(ligatures) then + features.gsub.liga = everywhere + data.properties.hasligatures = true + sequences[#sequences+1] = { + features = { + liga = everywhere, + }, + flags = noflags, + name = "s_s_0", + nofsteps = 1, + order = { "liga" }, + type = "gsub_ligature", + steps = { + { + coverage = ligatures, + }, + }, + } + end + if next(kerns) then + features.gpos.kern = everywhere + data.properties.haskerns = true + sequences[#sequences+1] = { + features = { + kern = everywhere, + }, + flags = noflags, + name = "p_s_0", + nofsteps = 1, + order = { "kern" }, + type = "gpos_pair", + steps = { + { + format = "kern", + coverage = kerns, + }, + }, + } + end + if next(extrakerns) then + features.gpos.extrakerns = everywhere + data.properties.haskerns = true + sequences[#sequences+1] = { + features = { + extrakerns = everywhere, + }, + flags = noflags, + name = "p_s_1", + nofsteps = 1, + order = { "extrakerns" }, + type = "gpos_pair", + steps = { + { + format = "kern", + coverage = extrakerns, + }, + }, + } + end + -- todo: compress kerns + data.resources.features = features + data.resources.sequences = sequences +end + +fixnames = function(data) + for k, v in next, data.descriptions do + local n = v.name + local r = overloads[n] + if r then + local name = r.name + if trace_indexing then + report_afm("renaming characters %a to %a",n,name) + end + v.name = name + v.unicode = r.unicode + end + end +end + +--[[ldx-- +

These helpers extend the basic table with extra ligatures, texligatures +and extra kerns. This saves quite some lookups later.

+--ldx]]-- + +local addthem = function(rawdata,ligatures) + if ligatures then + local descriptions = rawdata.descriptions + local resources = rawdata.resources + local unicodes = resources.unicodes + -- local names = resources.names + for ligname, ligdata in next, ligatures do + local one = descriptions[unicodes[ligname]] + if one then + for _, pair in next, ligdata do + local two, three = unicodes[pair[1]], unicodes[pair[2]] + if two and three then + local ol = one.ligatures + if ol then + if not ol[two] then + ol[two] = three + end + else + one.ligatures = { [two] = three } + end + end + end + end + end + end +end + +addligatures = function(rawdata) addthem(rawdata,afm.helpdata.ligatures ) end +addtexligatures = function(rawdata) addthem(rawdata,afm.helpdata.texligatures) end + +--[[ldx-- +

We keep the extra kerns in separate kerning tables so that we can use +them selectively.

+--ldx]]-- + +-- This is rather old code (from the beginning when we had only tfm). If +-- we unify the afm data (now we have names all over the place) then +-- we can use shcodes but there will be many more looping then. But we +-- could get rid of the tables in char-cmp then. Als, in the generic version +-- we don't use the character database. (Ok, we can have a context specific +-- variant). + +addkerns = function(rawdata) -- using shcodes is not robust here + local descriptions = rawdata.descriptions + local resources = rawdata.resources + local unicodes = resources.unicodes + local function do_it_left(what) + if what then + for unicode, description in next, descriptions do + local kerns = description.kerns + if kerns then + local extrakerns + for complex, simple in next, what do + complex = unicodes[complex] + simple = unicodes[simple] + if complex and simple then + local ks = kerns[simple] + if ks and not kerns[complex] then + if extrakerns then + extrakerns[complex] = ks + else + extrakerns = { [complex] = ks } + end + end + end + end + if extrakerns then + description.extrakerns = extrakerns + end + end + end + end + end + local function do_it_copy(what) + if what then + for complex, simple in next, what do + complex = unicodes[complex] + simple = unicodes[simple] + if complex and simple then + local complexdescription = descriptions[complex] + if complexdescription then -- optional + local simpledescription = descriptions[complex] + if simpledescription then + local extrakerns + local kerns = simpledescription.kerns + if kerns then + for unicode, kern in next, kerns do + if extrakerns then + extrakerns[unicode] = kern + else + extrakerns = { [unicode] = kern } + end + end + end + local extrakerns = simpledescription.extrakerns + if extrakerns then + for unicode, kern in next, extrakerns do + if extrakerns then + extrakerns[unicode] = kern + else + extrakerns = { [unicode] = kern } + end + end + end + if extrakerns then + complexdescription.extrakerns = extrakerns + end + end + end + end + end + end + end + -- add complex with values of simplified when present + do_it_left(afm.helpdata.leftkerned) + do_it_left(afm.helpdata.bothkerned) + -- copy kerns from simple char to complex char unless set + do_it_copy(afm.helpdata.bothkerned) + do_it_copy(afm.helpdata.rightkerned) +end + +--[[ldx-- +

The copying routine looks messy (and is indeed a bit messy).

+--ldx]]-- + +local function adddimensions(data) -- we need to normalize afm to otf i.e. indexed table instead of name + if data then + for unicode, description in next, data.descriptions do + local bb = description.boundingbox + if bb then + local ht, dp = bb[4], -bb[2] + if ht == 0 or ht < 0 then + -- no need to set it and no negative heights, nil == 0 + else + description.height = ht + end + if dp == 0 or dp < 0 then + -- no negative depths and no negative depths, nil == 0 + else + description.depth = dp + end + end + end + end +end + +local function copytotfm(data) + if data and data.descriptions then + local metadata = data.metadata + local resources = data.resources + local properties = derivetable(data.properties) + local descriptions = derivetable(data.descriptions) + local goodies = derivetable(data.goodies) + local characters = { } + local parameters = { } + local unicodes = resources.unicodes + -- + for unicode, description in next, data.descriptions do -- use parent table + characters[unicode] = { } + end + -- + local filename = constructors.checkedfilename(resources) + local fontname = metadata.fontname or metadata.fullname + local fullname = metadata.fullname or metadata.fontname + local endash = 0x0020 -- space + local emdash = 0x2014 + local spacer = "space" + local spaceunits = 500 + -- + local monospaced = metadata.monospaced + local charwidth = metadata.charwidth + local italicangle = metadata.italicangle + local charxheight = metadata.xheight and metadata.xheight > 0 and metadata.xheight + properties.monospaced = monospaced + parameters.italicangle = italicangle + parameters.charwidth = charwidth + parameters.charxheight = charxheight + -- same as otf + if properties.monospaced then + if descriptions[endash] then + spaceunits, spacer = descriptions[endash].width, "space" + end + if not spaceunits and descriptions[emdash] then + spaceunits, spacer = descriptions[emdash].width, "emdash" + end + if not spaceunits and charwidth then + spaceunits, spacer = charwidth, "charwidth" + end + else + if descriptions[endash] then + spaceunits, spacer = descriptions[endash].width, "space" + end + if not spaceunits and charwidth then + spaceunits, spacer = charwidth, "charwidth" + end + end + spaceunits = tonumber(spaceunits) + if spaceunits < 200 then + -- todo: warning + end + -- + parameters.slant = 0 + parameters.space = spaceunits + parameters.space_stretch = 500 + parameters.space_shrink = 333 + parameters.x_height = 400 + parameters.quad = 1000 + -- + if italicangle and italicangle ~= 0 then + parameters.italicangle = italicangle + parameters.italicfactor = math.cos(math.rad(90+italicangle)) + parameters.slant = - math.tan(italicangle*math.pi/180) + end + if monospaced then + parameters.space_stretch = 0 + parameters.space_shrink = 0 + elseif afm.syncspace then + parameters.space_stretch = spaceunits/2 + parameters.space_shrink = spaceunits/3 + end + parameters.extra_space = parameters.space_shrink + if charxheight then + parameters.x_height = charxheight + else + -- same as otf + local x = 0x0078 -- x + if x then + local x = descriptions[x] + if x then + parameters.x_height = x.height + end + end + -- + end + local fd = data.fontdimens + if fd and fd[8] and fd[9] and fd[10] then -- math + for k,v in next, fd do + parameters[k] = v + end + end + -- + parameters.designsize = (metadata.designsize or 10)*65536 + parameters.ascender = abs(metadata.ascender or 0) + parameters.descender = abs(metadata.descender or 0) + parameters.units = 1000 + -- + properties.spacer = spacer + properties.encodingbytes = 2 + properties.format = fonts.formats[filename] or "type1" + properties.filename = filename + properties.fontname = fontname + properties.fullname = fullname + properties.psname = fullname + properties.name = filename or fullname or fontname + -- + if next(characters) then + return { + characters = characters, + descriptions = descriptions, + parameters = parameters, + resources = resources, + properties = properties, + goodies = goodies, + } + end + end + return nil +end + +--[[ldx-- +

Originally we had features kind of hard coded for +files but since I expect to support more font formats, I decided +to treat this fontformat like any other and handle features in a +more configurable way.

+--ldx]]-- + +function afm.setfeatures(tfmdata,features) + local okay = constructors.initializefeatures("afm",tfmdata,features,trace_features,report_afm) + if okay then + return constructors.collectprocessors("afm",tfmdata,features,trace_features,report_afm) + else + return { } -- will become false + end +end + +local function addtables(data) + local resources = data.resources + local lookuptags = resources.lookuptags + local unicodes = resources.unicodes + if not lookuptags then + lookuptags = { } + resources.lookuptags = lookuptags + end + setmetatableindex(lookuptags,function(t,k) + local v = type(k) == "number" and ("lookup " .. k) or k + t[k] = v + return v + end) + if not unicodes then + unicodes = { } + resources.unicodes = unicodes + setmetatableindex(unicodes,function(t,k) + setmetatableindex(unicodes,nil) + for u, d in next, data.descriptions do + local n = d.name + if n then + t[n] = u + end + end + return rawget(t,k) + end) + end + constructors.addcoreunicodes(unicodes) -- do we really need this? +end + +local function afmtotfm(specification) + local afmname = specification.filename or specification.name + if specification.forced == "afm" or specification.format == "afm" then -- move this one up + if trace_loading then + report_afm("forcing afm format for %a",afmname) + end + else + local tfmname = findbinfile(afmname,"ofm") or "" + if tfmname ~= "" then + if trace_loading then + report_afm("fallback from afm to tfm for %a",afmname) + end + return -- just that + end + end + if afmname ~= "" then + -- weird, isn't this already done then? + local features = constructors.checkedfeatures("afm",specification.features.normal) + specification.features.normal = features + constructors.hashinstance(specification,true) -- also weird here + -- + specification = definers.resolve(specification) -- new, was forgotten + local cache_id = specification.hash + local tfmdata = containers.read(constructors.cache, cache_id) -- cache with features applied + if not tfmdata then + local rawdata = afm.load(afmname) + if rawdata and next(rawdata) then + addtables(rawdata) + adddimensions(rawdata) + tfmdata = copytotfm(rawdata) + if tfmdata and next(tfmdata) then + local shared = tfmdata.shared + if not shared then + shared = { } + tfmdata.shared = shared + end + shared.rawdata = rawdata + shared.dynamics = { } + tfmdata.changed = { } + shared.features = features + shared.processes = afm.setfeatures(tfmdata,features) + end + elseif trace_loading then + report_afm("no (valid) afm file found with name %a",afmname) + end + tfmdata = containers.write(constructors.cache,cache_id,tfmdata) + end + return tfmdata + end +end + +--[[ldx-- +

As soon as we could intercept the reader, I implemented an + reader. Since traditional could use +fonts with companions, the following method also could handle +those cases, but now that we can handle directly we no longer +need this features.

+--ldx]]-- + +local function read_from_afm(specification) + local tfmdata = afmtotfm(specification) + if tfmdata then + tfmdata.properties.name = specification.name + tfmdata = constructors.scale(tfmdata, specification) + local allfeatures = tfmdata.shared.features or specification.features.normal + constructors.applymanipulators("afm",tfmdata,allfeatures,trace_features,report_afm) + fonts.loggers.register(tfmdata,'afm',specification) + end + return tfmdata +end + +--[[ldx-- +

Here comes the implementation of a few features. We only implement +those that make sense for this format.

+--ldx]]-- + +local function prepareligatures(tfmdata,ligatures,value) + if value then + local descriptions = tfmdata.descriptions + local hasligatures = false + for unicode, character in next, tfmdata.characters do + local description = descriptions[unicode] + local dligatures = description.ligatures + if dligatures then + local cligatures = character.ligatures + if not cligatures then + cligatures = { } + character.ligatures = cligatures + end + for unicode, ligature in next, dligatures do + cligatures[unicode] = { + char = ligature, + type = 0 + } + end + hasligatures = true + end + end + tfmdata.properties.hasligatures = hasligatures + end +end + +local function preparekerns(tfmdata,kerns,value) + if value then + local rawdata = tfmdata.shared.rawdata + local resources = rawdata.resources + local unicodes = resources.unicodes + local descriptions = tfmdata.descriptions + local haskerns = false + for u, chr in next, tfmdata.characters do + local d = descriptions[u] + local newkerns = d[kerns] + if newkerns then + local kerns = chr.kerns + if not kerns then + kerns = { } + chr.kerns = kerns + end + for k,v in next, newkerns do + local uk = unicodes[k] + if uk then + kerns[uk] = v + end + end + haskerns = true + end + end + tfmdata.properties.haskerns = haskerns + end +end + +local list = { + -- [0x0022] = 0x201D, + [0x0027] = 0x2019, + -- [0x0060] = 0x2018, +} + +local function texreplacements(tfmdata,value) + local descriptions = tfmdata.descriptions + local characters = tfmdata.characters + for k, v in next, list do + characters [k] = characters [v] -- we forget about kerns + descriptions[k] = descriptions[v] -- we forget about kerns + end +end + +-- local function ligatures (tfmdata,value) prepareligatures(tfmdata,'ligatures', value) end +-- local function texligatures(tfmdata,value) prepareligatures(tfmdata,'texligatures',value) end +-- local function kerns (tfmdata,value) preparekerns (tfmdata,'kerns', value) end +local function extrakerns (tfmdata,value) preparekerns (tfmdata,'extrakerns', value) end + +local function setmode(tfmdata,value) + if value then + tfmdata.properties.mode = lower(value) + end +end + +registerafmfeature { + name = "mode", + description = "mode", + initializers = { + base = setmode, + node = setmode, + } +} + +registerafmfeature { + name = "features", + description = "features", + default = true, + initializers = { + node = otf.nodemodeinitializer, + base = otf.basemodeinitializer, + }, + processors = { + node = otf.featuresprocessor, + } +} + +-- readers + +local check_tfm = readers.check_tfm + +fonts.formats.afm = "type1" +fonts.formats.pfb = "type1" + +local function check_afm(specification,fullname) + local foundname = findbinfile(fullname, 'afm') or "" -- just to be sure + if foundname == "" then + foundname = fonts.names.getfilename(fullname,"afm") or "" + end + if foundname == "" and afm.autoprefixed then + local encoding, shortname = match(fullname,"^(.-)%-(.*)$") -- context: encoding-name.* + if encoding and shortname and fonts.encodings.known[encoding] then + shortname = findbinfile(shortname,'afm') or "" -- just to be sure + if shortname ~= "" then + foundname = shortname + if trace_defining then + report_afm("stripping encoding prefix from filename %a",afmname) + end + end + end + end + if foundname ~= "" then + specification.filename = foundname + specification.format = "afm" + return read_from_afm(specification) + end +end + +function readers.afm(specification,method) + local fullname, tfmdata = specification.filename or "", nil + if fullname == "" then + local forced = specification.forced or "" + if forced ~= "" then + tfmdata = check_afm(specification,specification.name .. "." .. forced) + end + if not tfmdata then + method = method or definers.method or "afm or tfm" + if method == "tfm" then + tfmdata = check_tfm(specification,specification.name) + elseif method == "afm" then + tfmdata = check_afm(specification,specification.name) + elseif method == "tfm or afm" then + tfmdata = check_tfm(specification,specification.name) or check_afm(specification,specification.name) + else -- method == "afm or tfm" or method == "" then + tfmdata = check_afm(specification,specification.name) or check_tfm(specification,specification.name) + end + end + else + tfmdata = check_afm(specification,fullname) + end + return tfmdata +end + +function readers.pfb(specification,method) -- only called when forced + local original = specification.specification + if trace_defining then + report_afm("using afm reader for %a",original) + end + specification.specification = gsub(original,"%.pfb",".afm") + specification.forced = "afm" + return readers.afm(specification,method) +end diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-otc.lua b/Master/texmf-dist/tex/context/base/mkiv/font-otc.lua index 871b6f13c97..be9ba86604b 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-otc.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-otc.lua @@ -61,8 +61,6 @@ local function addfeature(data,feature,specifications) end -- feature has to be unique but the name entry wins eventually - -- todo alse gpos - local fontfeatures = resources.features or everywhere local unicodes = resources.unicodes local splitter = lpeg.splitter(" ",unicodes) @@ -529,6 +527,7 @@ end otf.enhancers.addfeature = addfeature local extrafeatures = { } +local knownfeatures = { } function otf.addfeature(name,specification) if type(name) == "table" then @@ -536,16 +535,31 @@ function otf.addfeature(name,specification) name = specification.name end if type(name) == "string" then - extrafeatures[name] = specification + local slot = knownfeatures[name] + if slot then + -- we overload one + else + slot = #extrafeatures + 1 + knownfeatures[name] = slot + end + specification.name = name -- to be sure + extrafeatures[slot] = specification end end +-- for feature, specification in next, extrafeatures do +-- addfeature(data,feature,specification) +-- end + local function enhance(data,filename,raw) - for feature, specification in next, extrafeatures do - addfeature(data,feature,specification) + for slot=1,#extrafeatures do + local specification = extrafeatures[slot] + addfeature(data,specification.name,specification) end end +-- otf.enhancers.enhance = enhance + otf.enhancers.register("check extra features",enhance) -- tlig -- @@ -574,6 +588,7 @@ local tlig_specification = { otf.addfeature("tlig",tlig_specification) registerotffeature { + -- this makes it a known feature (in tables) name = 'tlig', description = 'tex ligatures', } @@ -598,6 +613,7 @@ local trep_specification = { otf.addfeature("trep",trep_specification) registerotffeature { + -- this makes it a known feature (in tables) name = 'trep', description = 'tex replacements', } @@ -699,6 +715,7 @@ local anum_specification = { otf.addfeature("anum",anum_specification) -- todo: only when there is already an arab script feature registerotffeature { + -- this makes it a known feature (in tables) name = 'anum', description = 'arabic digits', } diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-otj.lua b/Master/texmf-dist/tex/context/base/mkiv/font-otj.lua index 6ff80d88df8..b65a9db6627 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-otj.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-otj.lua @@ -1255,11 +1255,11 @@ local function inject_everything(head,where) insert_node_after(pre,n,newkern(rightkern)) done = true end - end - if hasmarks then - local pm = i.markbasenode - if pm then - processmark(pm,current,i) + if hasmarks then + local pm = i.markbasenode + if pm then + processmark(pm,current,i) + end end end end @@ -1287,11 +1287,11 @@ local function inject_everything(head,where) insert_node_after(post,n,newkern(rightkern)) done = true end - end - if hasmarks then - local pm = i.markbasenode - if pm then - processmark(pm,current,i) + if hasmarks then + local pm = i.markbasenode + if pm then + processmark(pm,current,i) + end end end end @@ -1319,11 +1319,11 @@ local function inject_everything(head,where) insert_node_after(replace,n,newkern(rightkern)) done = true end - end - if hasmarks then - local pm = i.markbasenode - if pm then - processmark(pm,current,i) + if hasmarks then + local pm = i.markbasenode + if pm then + processmark(pm,current,i) + end end end end diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-otl.lua b/Master/texmf-dist/tex/context/base/mkiv/font-otl.lua index f7b6eb5ae5f..01342a9be6e 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-otl.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-otl.lua @@ -101,6 +101,12 @@ registerdirective("fonts.otf.loader.forcenotdef", function(v) forcenotdef = -- end -- end +-- Enhancers are used to apply fixes and extensions to fonts. For instance, we use them +-- to implement tlig and trep features. They are not neccessarily bound to opentype +-- fonts but can also apply to type one fonts, given that they obey the structure of an +-- opentype font. They are not to be confused with format specific features but maybe +-- some are so generic that they might eventually move to this mechanism. + local ordered_enhancers = { "check extra features", } @@ -302,7 +308,7 @@ function otf.load(filename,sub,featurefile) -- second argument (format) is gone -- enhancers.apply(data,filename,data) -- - constructors.addcoreunicodes(unicodes) + -- constructors.addcoreunicodes(data.resources.unicodes) -- still needed ? -- if applyruntimefixes then applyruntimefixes(filename,data) diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-oto.lua b/Master/texmf-dist/tex/context/base/mkiv/font-oto.lua index b7ee717c949..23beba7876d 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-oto.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-oto.lua @@ -450,3 +450,5 @@ registerotffeature { base = featuresinitializer, } } + +otf.basemodeinitializer = featuresinitializer diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-ots.lua b/Master/texmf-dist/tex/context/base/mkiv/font-ots.lua index 21225c2274f..c173de2be5a 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-ots.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-ots.lua @@ -3652,6 +3652,9 @@ registerotffeature { } } +otf.nodemodeinitializer = featuresinitializer +otf.featuresprocessor = featuresprocessor + -- This can be used for extra handlers, but should be used with care! otf.handlers = handlers -- used in devanagari diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-def.mkiv b/Master/texmf-dist/tex/context/base/mkiv/lang-def.mkiv index e4906096e0e..5e40a33b030 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lang-def.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/lang-def.mkiv @@ -341,7 +341,7 @@ \c!rightquotation=\upperrightdoubleninequote, \c!date={\v!year,.,\space,\v!month,\space,\v!day,.}] -\installlanguage [\s!finish] [\s!fi] +\installlanguage [\s!finnish] [\s!fi] \installlanguage [\s!hungarian] [\s!hu] % Altaic Languages: Uigur, Uzbek, Azeri/Azerbaijani, Chuvash, diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/lang-ini.lua index eb7e32b89f3..00fdb3f0973 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lang-ini.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/lang-ini.lua @@ -40,8 +40,8 @@ local prehyphenchar = lang.prehyphenchar -- global per language local posthyphenchar = lang.posthyphenchar -- global per language local preexhyphenchar = lang.preexhyphenchar -- global per language local postexhyphenchar = lang.postexhyphenchar -- global per language -local lefthyphenmin = lang.lefthyphenmin -local righthyphenmin = lang.righthyphenmin +----- lefthyphenmin = lang.lefthyphenmin +----- righthyphenmin = lang.righthyphenmin local sethjcode = lang.sethjcode local uccodes = characters.uccodes @@ -344,8 +344,8 @@ function languages.prehyphenchar (what) return prehyphenchar (tolang(what)) function languages.posthyphenchar (what) return posthyphenchar (tolang(what)) end function languages.preexhyphenchar (what) return preexhyphenchar (tolang(what)) end function languages.postexhyphenchar(what) return postexhyphenchar(tolang(what)) end -function languages.lefthyphenmin (what) return lefthyphenmin (tolang(what)) end -function languages.righthyphenmin (what) return righthyphenmin (tolang(what)) end +-------- languages.lefthyphenmin (what) return lefthyphenmin (tolang(what)) end +-------- languages.righthyphenmin (what) return righthyphenmin (tolang(what)) end -- e['implementer']= 'imple{m}{-}{-}menter' -- e['manual'] = 'man{}{}{}' diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/lang-ini.mkiv index 8ff41b28792..214ce8ca38a 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lang-ini.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/lang-ini.mkiv @@ -518,7 +518,7 @@ \let\dohyphens\relax -\unexpanded\def\lang_basics_synchronize_min_max +\unexpanded\def\lang_basics_synchronize_min_max % maybe store this at the lua end {% these values are stored along with glyph nodes \lefthyphenmin \numexpr0\languageparameter\s!lefthyphenmin +\hyphenminoffset\relax \righthyphenmin\numexpr0\languageparameter\s!righthyphenmin+\hyphenminoffset\relax diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-ini.lua index 2149f4729a4..f0b919d4ee0 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lpdf-ini.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-ini.lua @@ -1059,13 +1059,30 @@ do return timestamp end + function lpdf.settime(n) + if n then + n = converters.totime(n) + if n then + converters.settime(n) + timestamp = os.date("%Y-%m-%dT%X",os.time(n)) .. os.timezone(true) + end + end + return timestamp + end + + lpdf.settime(tonumber(resolvers.variable("start_time")) or tonumber(resolvers.variable("SOURCE_DATE_EPOCH"))) -- bah + function lpdf.pdftimestamp(str) local Y, M, D, h, m, s, Zs, Zh, Zm = match(str,"^(%d%d%d%d)%-(%d%d)%-(%d%d)T(%d%d):(%d%d):(%d%d)([%+%-])(%d%d):(%d%d)$") return Y and format("D:%s%s%s%s%s%s%s%s'%s'",Y,M,D,h,m,s,Zs,Zh,Zm) end - function lpdf.id() - return format("%s.%s",tex.jobname,timestamp) + function lpdf.id(nodate) + if nodate then + return tex.jobname + else + return format("%s.%s",tex.jobname,timestamp) + end end end diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-xmp.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-xmp.lua index b8170319c11..c8b86d38464 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lpdf-xmp.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-xmp.lua @@ -41,7 +41,7 @@ local mapping = { ["ConTeXt.Time"] = { "date", "rdf:Description/pdfx:ConTeXt.Time" }, ["ConTeXt.Url"] = { "context", "rdf:Description/pdfx:ConTeXt.Url" }, ["ConTeXt.Version"] = { "context", "rdf:Description/pdfx:ConTeXt.Version" }, - ["ID"] = { "date", "rdf:Description/pdfx:ID" }, -- has date + ["ID"] = { "id", "rdf:Description/pdfx:ID" }, -- has date ["PTEX.Fullbanner"] = { "metadata","rdf:Description/pdfx:PTEX.Fullbanner" }, -- Adobe PDF schema ["Keywords"] = { "metadata","rdf:Description/pdf:Keywords" }, @@ -60,8 +60,8 @@ local mapping = { ["ModDate"] = { "date", "rdf:Description/xmp:ModDate" }, -- dummy ["ModifyDate"] = { "date", "rdf:Description/xmp:ModifyDate" }, -- XMP Media Management schema - ["DocumentID"] = { "date", "rdf:Description/xmpMM:DocumentID" }, -- uuid - ["InstanceID"] = { "date", "rdf:Description/xmpMM:InstanceID" }, -- uuid + ["DocumentID"] = { "id", "rdf:Description/xmpMM:DocumentID" }, -- uuid + ["InstanceID"] = { "id", "rdf:Description/xmpMM:InstanceID" }, -- uuid ["RenditionClass"] = { "pdf", "rdf:Description/xmpMM:RenditionClass" }, -- PDF/X-4 ["VersionID"] = { "pdf", "rdf:Description/xmpMM:VersionID" }, -- PDF/X-4 -- additional entries @@ -105,32 +105,66 @@ local included = table.setmetatableindex( { return true end) -directives.register("backend.nodates", function(v) - included.date = not v +function lpdf.settrailerid(v) if v then - report_info("no date/time information will be added to the PDF file") - end -end) - -directives.register("backend.trailerid", function(v) - if v then - if toboolean(v) or v == "" then + local b = toboolean(v) or v == "" + if b then v = "This file is processed by ConTeXt and LuaTeX." else v = tostring(v) end local h = md5.HEX(v) - report_info("using hashed trailer id %a (%a)",v,h) + if b then + report_info("using frozen trailer id") + else + report_info("using hashed trailer id %a (%a)",v,h) + end pdf.settrailerid(format("[<%s> <%s>]",h,h)) end -end) +end + +function lpdf.setdates(v) + local t = type(v) + if t == "number" or t == "string" then + t = converters.totime(v) + if t then + included.date = true + included.id = "fake" + report_info("forced date/time information %a will be used",lpdf.settime(t)) + lpdf.settrailerid(false) + return + end + end + v = toboolean(v) + included.date = v + if v then + included.id = true + else + report_info("no date/time but fake id information will be added") + lpdf.settrailerid(true) + included.id = "fake" + -- maybe: lpdf.settime(231631200) -- 1975-05-05 % first entry of knuth about tex mentioned in DT + end +end + +function lpdf.id() -- overload of ini + local banner = tex.jobname + if included.date then + return format("%s.%s",banner,lpdf.timestamp()) + else + return banner + end +end + +directives.register("backend.trailerid", lpdf.settrailerid) +directives.register("backend.date", lpdf.setdates) local function permitdetail(what) local m = mapping[what] if m then return included[m[1]] and m[2] else - return included[what] + return included[what] and true or false end end @@ -214,22 +248,34 @@ end -- flushing -local t = { } for i=1,24 do t[i] = random() end +local function randomstring(n) + local t = { } + for i=1,n do + t[i] = char(96 + random(26)) + end + return concat(t) +end + +randomstring(26) -- kind of initializes and kicks off random local function flushxmpinfo() commands.pushrandomseed() commands.setrandomseed(os.time()) - local t = { } for i=1,24 do t[i] = char(96 + random(26)) end - local packetid = concat(t) - - local documentid = format("uuid:%s",os.uuid()) - local instanceid = format("uuid:%s",os.uuid()) + local packetid = "no unique packet id here" -- 24 chars + local documentid = "no unique document id here" + local instanceid = "no unique instance id here" local producer = format("LuaTeX-%0.2f.%s",status.luatex_version/100,status.luatex_revision) local creator = "LuaTeX + ConTeXt MkIV" local time = lpdf.timestamp() local fullbanner = status.banner + if included.id ~= "fake" then + packetid = randomstring(24) + documentid = "uuid:%s" .. os.uuid() + instanceid = "uuid:%s" .. os.uuid() + end + pdfaddxmpinfo("DocumentID", documentid) pdfaddxmpinfo("InstanceID", instanceid) pdfaddxmpinfo("Producer", producer) diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-cnf.lua b/Master/texmf-dist/tex/context/base/mkiv/luat-cnf.lua index 83622ef5399..9d37df7bb10 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/luat-cnf.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/luat-cnf.lua @@ -42,6 +42,7 @@ luatex = luatex or { } texconfig.kpse_init = false texconfig.shell_escape = 't' +---------.start_time = tonumber(os.getenv("SOURCE_DATE_EPOCH")) -- not used in context -- as soon as possible diff --git a/Master/texmf-dist/tex/context/base/mkiv/m-oldotf.mkiv b/Master/texmf-dist/tex/context/base/mkiv/m-oldotf.mkiv index c7c468d93ec..313f9f48459 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/m-oldotf.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/m-oldotf.mkiv @@ -25,6 +25,7 @@ "font-otc", "font-oth", "font-odv", + "font-one", "font-map", "font-fbk", "font-gds", diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/meta-ini.mkiv index 9f53aea69f6..d0fff83dfd6 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/meta-ini.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/meta-ini.mkiv @@ -486,6 +486,10 @@ \startMPextensions string contextversion; contextversion:="\contextversion"; % expanded + minute:=\the\normaltime mod 60; + hour:=\the\normaltime div 60; + year:=\the\normalyear; + month:=\the\normalmonth; \stopMPextensions %D \macros diff --git a/Master/texmf-dist/tex/context/base/mkiv/mult-sys.mkiv b/Master/texmf-dist/tex/context/base/mkiv/mult-sys.mkiv index 01a1674dced..88e956d66e9 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/mult-sys.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/mult-sys.mkiv @@ -48,7 +48,7 @@ \definesystemconstant {danish} \definesystemconstant {da} \definesystemconstant {dutch} \definesystemconstant {nl} \definesystemconstant {english} \definesystemconstant {en} -\definesystemconstant {finish} \definesystemconstant {fi} +\definesystemconstant {finnish} \definesystemconstant {fi} \definesystemconstant {french} \definesystemconstant {fr} \definesystemconstant {german} \definesystemconstant {de} \definesystemconstant {hungarian} \definesystemconstant {hu} diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-fnt.lua b/Master/texmf-dist/tex/context/base/mkiv/node-fnt.lua index 7f0d239979a..e77280c372e 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/node-fnt.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/node-fnt.lua @@ -17,9 +17,12 @@ local trace_characters = false trackers.register("nodes.characters", function( local trace_fontrun = false trackers.register("nodes.fontrun", function(v) trace_fontrun = v end) local trace_variants = false trackers.register("nodes.variants", function(v) trace_variants = v end) -local force_discrun = true directives.register("nodes.discrun", function(v) force_discrun = v end) -local force_boundaryrun = true directives.register("nodes.boundaryrun", function(v) force_boundaryrun = v end) -local force_basepass = true directives.register("nodes.basepass", function(v) force_basepass = v end) +-- bad namespace for directives + +local force_discrun = true directives.register("nodes.discrun", function(v) force_discrun = v end) +local force_boundaryrun = true directives.register("nodes.boundaryrun", function(v) force_boundaryrun = v end) +local force_basepass = true directives.register("nodes.basepass", function(v) force_basepass = v end) +local keep_redundant = false directives.register("nodes.keepredundant",function(v) keep_redundant = v end) local report_fonts = logs.reporter("fonts","processing") @@ -271,6 +274,12 @@ function handlers.characters(head) end end end + elseif keep_redundant then + -- go on, can be used for tracing + elseif not redundant then + redundant = { n } + else + redundant[#redundant+1] = n end end end diff --git a/Master/texmf-dist/tex/context/base/mkiv/status-files.pdf b/Master/texmf-dist/tex/context/base/mkiv/status-files.pdf index 5d4c84ce108..6ea8ed23fd9 100644 Binary files a/Master/texmf-dist/tex/context/base/mkiv/status-files.pdf and b/Master/texmf-dist/tex/context/base/mkiv/status-files.pdf differ diff --git a/Master/texmf-dist/tex/context/base/mkiv/status-lua.pdf b/Master/texmf-dist/tex/context/base/mkiv/status-lua.pdf index 84aba5a7fd9..cb96b7185ed 100644 Binary files a/Master/texmf-dist/tex/context/base/mkiv/status-lua.pdf and b/Master/texmf-dist/tex/context/base/mkiv/status-lua.pdf differ diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-tal.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-tal.lua index a67cd0a4b47..21c6794c47a 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-tal.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-tal.lua @@ -200,10 +200,10 @@ function characteralign.handler(originalhead,where) while current do local char, id = isglyph(current) if char then - local font = getfont(current) - -- local unicode = unicodes[font][char] - local unicode = fontcharacters[font][char].unicode or char -- ignore tables - if not unicode then + local font = getfont(current) + local data = fontcharacters[font][char] + local unicode = data and data.unicode or char -- ignore tables + if not unicode then -- type(unicode) ~= "number" -- no unicode so forget about it elseif unicode == separator then c = current diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-wrp.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-wrp.mkiv index 4b18785bd33..08134905021 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-wrp.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-wrp.mkiv @@ -44,6 +44,7 @@ \spac_crlf_placeholder \ifcase\raggedstatus\hfil\or\or\or\hfil\fi \break + \hskip\zeropoint % new so that the next word also hyphenates \ignorespaces} \unexpanded\def\spac_crlf_placeholder diff --git a/Master/texmf-dist/tex/context/fonts/mkiv/type-imp-lato.mkiv b/Master/texmf-dist/tex/context/fonts/mkiv/type-imp-lato.mkiv index 11a386b3f7d..4a0dbeb36f1 100644 --- a/Master/texmf-dist/tex/context/fonts/mkiv/type-imp-lato.mkiv +++ b/Master/texmf-dist/tex/context/fonts/mkiv/type-imp-lato.mkiv @@ -1,6 +1,6 @@ %D \module %D [ file=type-imp-lato, -%D version=2014.05.02, +%D version=2016.05.07, %D title=\CONTEXT\ Typescript Macros, %D subtitle=Lato fonts, %D author=Hans Hagen, @@ -11,11 +11,24 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -% hai : hair / lta : italic -% lig : light / lta : italic -% reg : regular / lta : italic -% bol : bold / lta : italic -% bla : black / lta : italic +% Lato-Black.ttf +% Lato-BlackItalic.ttf +% Lato-Bold.ttf +% Lato-BoldItalic.ttf +% Lato-Hairline.ttf +% Lato-HairlineItalic.ttf +% Lato-Heavy.ttf +% Lato-HeavyItalic.ttf +% Lato-Italic.ttf +% Lato-Light.ttf +% Lato-LightItalic.ttf +% Lato-Medium.ttf +% Lato-MediumItalic.ttf +% Lato-Regular.ttf +% Lato-Semibold.ttf +% Lato-SemiboldItalic.ttf +% Lato-Thin.ttf +% Lato-ThinItalic.ttf \loadtypescriptfile[dejavu] \loadtypescriptfile[xits] @@ -24,29 +37,68 @@ \starttypescript [\s!sans] [lato] [\s!name] \setups[\s!font:\s!fallback:\s!sans] - \definefontsynonym [\s!Sans] [\s!file:lato-reg] [\s!features=\s!default] - \definefontsynonym [\s!SansBold] [\s!file:lato-bol] [\s!features=\s!default] - \definefontsynonym [\s!SansItalic] [\s!file:lato-regita] [\s!features=\s!default] - \definefontsynonym [\s!SansBoldItalic] [\s!file:lato-bollta] [\s!features=\s!default] + \definefontsynonym [\s!Sans] [\s!file:lato-regular] [\s!features=\s!default] + \definefontsynonym [\s!SansBold] [\s!file:lato-bold] [\s!features=\s!default] + \definefontsynonym [\s!SansItalic] [\s!file:lato-italic] [\s!features=\s!default] + \definefontsynonym [\s!SansBoldItalic] [\s!file:lato-bolditalic] [\s!features=\s!default] \stoptypescript \starttypescript [\s!sans] [lato-light] [\s!name] \setups[\s!font:\s!fallback:\s!sans] - \definefontsynonym [\s!Sans] [\s!file:lato-lig] [\s!features=\s!default] - \definefontsynonym [\s!SansBold] [\s!file:lato-reg] [\s!features=\s!default] - \definefontsynonym [\s!SansItalic] [\s!file:lato-liglta] [\s!features=\s!default] - \definefontsynonym [\s!SansBoldItalic] [\s!file:lato-regita] [\s!features=\s!default] + \definefontsynonym [\s!Sans] [\s!file:lato-light] [\s!features=\s!default] + \definefontsynonym [\s!SansBold] [\s!file:lato-regular] [\s!features=\s!default] + \definefontsynonym [\s!SansItalic] [\s!file:lato-lightitalic] [\s!features=\s!default] + \definefontsynonym [\s!SansBoldItalic] [\s!file:lato-italic] [\s!features=\s!default] \stoptypescript \starttypescript [\s!sans] [lato-dark] [\s!name] \setups[\s!font:\s!fallback:\s!sans] - \definefontsynonym [\s!Sans] [\s!file:lato-bol] [\s!features=\s!default] - \definefontsynonym [\s!SansBold] [\s!file:lato-bla] [\s!features=\s!default] - \definefontsynonym [\s!SansItalic] [\s!file:lato-bollta] [\s!features=\s!default] - \definefontsynonym [\s!SansBoldItalic] [\s!file:lato-blalta] [\s!features=\s!default] + \definefontsynonym [\s!Sans] [\s!file:lato-bold] [\s!features=\s!default] + \definefontsynonym [\s!SansBold] [\s!file:lato-heavy] [\s!features=\s!default] + \definefontsynonym [\s!SansItalic] [\s!file:lato-bolditalic] [\s!features=\s!default] + \definefontsynonym [\s!SansBoldItalic] [\s!file:lato-heavyitalic] [\s!features=\s!default] + \stoptypescript + + \starttypescript [\s!sans] [lato-black] [\s!name] + \setups[\s!font:\s!fallback:\s!sans] + \definefontsynonym [\s!Sans] [\s!file:lato-heavy] [\s!features=\s!default] + \definefontsynonym [\s!SansBold] [\s!file:lato-black] [\s!features=\s!default] + \definefontsynonym [\s!SansItalic] [\s!file:lato-heavyitalic] [\s!features=\s!default] + \definefontsynonym [\s!SansBoldItalic] [\s!file:lato-blackitalic] [\s!features=\s!default] \stoptypescript - \starttypescript[lato,lato-light,lato-dark] + \starttypescript [\s!sans] [lato-hairline] [\s!name] + \setups[\s!font:\s!fallback:\s!sans] + \definefontsynonym [\s!Sans] [\s!file:lato-hairline] [\s!features=\s!default] + \definefontsynonym [\s!SansBold] [\s!file:lato-regular] [\s!features=\s!default] + \definefontsynonym [\s!SansItalic] [\s!file:lato-hairlineitalic] [\s!features=\s!default] + \definefontsynonym [\s!SansBoldItalic] [\s!file:lato-italic] [\s!features=\s!default] + \stoptypescript + + \starttypescript [\s!sans] [lato-thin] [\s!name] + \setups[\s!font:\s!fallback:\s!sans] + \definefontsynonym [\s!Sans] [\s!file:lato-thin] [\s!features=\s!default] + \definefontsynonym [\s!SansBold] [\s!file:lato-regular] [\s!features=\s!default] + \definefontsynonym [\s!SansItalic] [\s!file:lato-thinitalic] [\s!features=\s!default] + \definefontsynonym [\s!SansBoldItalic] [\s!file:lato-italic] [\s!features=\s!default] + \stoptypescript + + \starttypescript [\s!sans] [lato-medium] [\s!name] + \setups[\s!font:\s!fallback:\s!sans] + \definefontsynonym [\s!Sans] [\s!file:lato-medium] [\s!features=\s!default] + \definefontsynonym [\s!SansBold] [\s!file:lato-bold] [\s!features=\s!default] + \definefontsynonym [\s!SansItalic] [\s!file:lato-mediumitalic] [\s!features=\s!default] + \definefontsynonym [\s!SansBoldItalic] [\s!file:lato-bolditalic] [\s!features=\s!default] + \stoptypescript + + \starttypescript [\s!sans] [lato-semibold] [\s!name] + \setups[\s!font:\s!fallback:\s!sans] + \definefontsynonym [\s!Sans] [\s!file:lato-regular] [\s!features=\s!default] + \definefontsynonym [\s!SansBold] [\s!file:lato-semibold] [\s!features=\s!default] + \definefontsynonym [\s!SansItalic] [\s!file:lato-italic] [\s!features=\s!default] + \definefontsynonym [\s!SansBoldItalic] [\s!file:lato-semibolditalic] [\s!features=\s!default] + \stoptypescript + \starttypescript[lato,lato-light,lato-dark,lato-black,lato-hairline,lato-thin,lato-medium,lato-semibold] \definetypeface [\typescriptone] [\s!ss] [\s!sans] [\typescriptone] [\s!default] \definetypeface [\typescriptone] [\s!rm] [\s!serif] [dejavu] [\s!default] \definetypeface [\typescriptone] [\s!tt] [\s!mono] [dejavu] [\s!default] diff --git a/Master/texmf-dist/tex/context/interface/mkiv/i-context.pdf b/Master/texmf-dist/tex/context/interface/mkiv/i-context.pdf index 6d0041d258d..f83e7b524c1 100644 Binary files a/Master/texmf-dist/tex/context/interface/mkiv/i-context.pdf and b/Master/texmf-dist/tex/context/interface/mkiv/i-context.pdf differ diff --git a/Master/texmf-dist/tex/context/interface/mkiv/i-readme.pdf b/Master/texmf-dist/tex/context/interface/mkiv/i-readme.pdf index 4d61ab7a800..0c981cc83b5 100644 Binary files a/Master/texmf-dist/tex/context/interface/mkiv/i-readme.pdf and b/Master/texmf-dist/tex/context/interface/mkiv/i-readme.pdf differ diff --git a/Master/texmf-dist/tex/context/modules/mkiv/m-scite.mkiv b/Master/texmf-dist/tex/context/modules/mkiv/m-scite.mkiv index 71f31becef3..e033235c313 100644 --- a/Master/texmf-dist/tex/context/modules/mkiv/m-scite.mkiv +++ b/Master/texmf-dist/tex/context/modules/mkiv/m-scite.mkiv @@ -165,8 +165,29 @@ function scite.installcommands() context(exportcolors()) end +local p = lpeg.P("\\slxS ")^1 + +local function indent(str) + local l = string.split(str,"\n") + for i=1,#l do + local s = l[i] + if #s > 0 then + local n = lpegmatch(p,s) + if n then + n = (n-1)/6 + else + n = 0 + end + l[i] = formatters["\\slxb{%s}%s\\slxe"](n,s) + end + end + return concat(l,"\n") +end + local function lexdata(data,lexname) - buffers.assign("lex",exportstyled(scite.loadedlexers[lexname],data or "")) + local styled = exportstyled(scite.loadedlexers[lexname],data or "") + styled = indent(styled) + buffers.assign("lex",styled) end scite.lexdata = lexdata @@ -187,9 +208,21 @@ end \unprotect +\unexpanded\def\buff_scite_slxb#1% + {%\begingroup + \hangindent\dimexpr\numexpr#1+1\relax\emwidth\relax + \hangafter \numexpr\numexpr#1+1\relax} + +\unexpanded\def\buff_scite_slxe + {\par + }%\endgroup} + \unexpanded\def\installscitecommands {\ctxlua{buffers.scite.installcommands()}% - \let\installscitecommands\relax} + \let\installscitecommands\relax + \def\slxS{\fixedspace\allowbreak}% + \let\slxb\buff_scite_slxb + \let\slxe\buff_scite_slxe} \unexpanded\def\startscite {\begingroup @@ -212,6 +245,7 @@ end \installscitecommands \tt \dontcomplain + \raggedright \startcontextcode \startlines \getbuffer[lex]% @@ -232,6 +266,7 @@ end \installscitecommands \tt \dontcomplain + \raggedright \setcatcodetable\ctxcatcodes % needed in xml \startlines \getbuffer[lex]% diff --git a/Master/texmf-dist/tex/context/modules/mkiv/s-languages-hyphenation.lua b/Master/texmf-dist/tex/context/modules/mkiv/s-languages-hyphenation.lua index c5a4f91f1e9..971ca3d8f3c 100644 --- a/Master/texmf-dist/tex/context/modules/mkiv/s-languages-hyphenation.lua +++ b/Master/texmf-dist/tex/context/modules/mkiv/s-languages-hyphenation.lua @@ -11,111 +11,194 @@ moduledata.languages.hyphenation = moduledata.languages.hyphenation or { } local a_colormodel = attributes.private('colormodel') +local tex = tex +local context = context + local nodecodes = nodes.nodecodes -local nodepool = nodes.pool +local nuts = nodes.nuts +local nodepool = nuts.pool + local disc_code = nodecodes.disc local glyph_code = nodecodes.glyph + local emwidths = fonts.hashes.emwidths local exheights = fonts.hashes.exheights + local newkern = nodepool.kern local newrule = nodepool.rule local newglue = nodepool.glue -local insert_node_after = node.insert_after -local traverse_by_id = node.traverse_id -local hyphenate = languages.hyphenators.handler -- lang.hyphenate -local find_tail = node.tail -local remove_node = nodes.remove +local insert_node_after = nuts.insert_after +local traverse_by_id = nuts.traverse_id + +local tonut = nodes.tonut +local tonode = nodes.tonode +local getid = nuts.getid +local getnext = nuts.getnext +local getdisc = nuts.getdisc +local getattr = nuts.getattr +local getfont = nuts.getfont +local getfield = nuts.getfield +local setlink = nuts.setlink +local setdisc = nuts.setdisc +local setfield = nuts.setfield +local free_node = nuts.free local tracers = nodes.tracers local colortracers = tracers and tracers.colors local setnodecolor = colortracers.set +-- maybe this will become code code + +local states = table.setmetatableindex(function(t,k) + return { + lefthyphenmin = tex.lefthyphenmin, + righthyphenmin = tex.righthyphenmin, + hyphenationmin = tex.hyphenationmin, + prehyphenchar = tex.prehyphenchar, + posthyphenchar = tex.posthyphenchar, + } +end) + +interfaces.implement { + name = "storelanguagestate", + actions = function() + states[tex.language] = { + lefthyphenmin = tex.lefthyphenmin, + righthyphenmin = tex.righthyphenmin, + hyphenationmin = tex.hyphenationmin, + prehyphenchar = tex.prehyphenchar, + posthyphenchar = tex.posthyphenchar, + } + end +} + +function moduledata.languages.getstate(l) + return states[l] -- code +end + +-- end + local function identify(head,marked) - local current, prev = head, nil + local current = tonut(head) + local prev = nil while current do - local id = current.id - local next = current.next + local id = getid(current) + local next = getnext(current) if id == disc_code then - if prev and next then -- and next.id == glyph_code then -- catch other usage of disc + if prev and next then -- asume glyphs marked[#marked+1] = prev + local pre, post, replace, pre_tail, post_tail, replace_tail = getdisc(current,true) + if replace then + setlink(prev,replace) + setlink(replace_tail,next) + setdisc(pre,post,nil) + prev = tail + else + setlink(prev,next) + end + free_node(current) end elseif id == glyph_code then prev = current + else + prev = nil end current = next end end -local function strip(head,marked) +local function mark(head,marked,w,h,d,how) + head = tonut(head) for i=1,#marked do - local prev = marked[i] - remove_node(head,prev.next,true) + local current = marked[i] + local font = getfont(current) + local em = emwidths[font] + local ex = exheights[font] + local width = w*em + local rule = newrule(width,h*ex,d*ex) + head, current = insert_node_after(head,current,newkern(-width/2)) + head, current = insert_node_after(head,current,rule) + head, current = insert_node_after(head,current,newkern(-width/2)) + head, current = insert_node_after(head,current,newglue(0)) + setnodecolor(rule,how) -- ,getattr(current,a_colormodel)) end end -local function mark(head,marked,w,h,d,how) - for i=1,#marked do - local prev = marked[i] - local font = prev.font - local em = emwidths[font] - local ex = exheights[font] - local width = w*em - local rule = newrule(width,h*ex,d*ex) - head, prev = insert_node_after(head,prev,newkern(-width/2)) - head, prev = insert_node_after(head,prev,rule) - head, prev = insert_node_after(head,prev,newkern(-width/2)) - head, prev = insert_node_after(head,prev,newglue(0)) - setnodecolor(rule,how,prev[a_colormodel]) +local function getlanguage(head,l,left,right) + local t = { } + for n in traverse_by_id(glyph_code,tonut(head)) do + t[n] = { + getfield(n,"lang"), + getfield(n,"left"), + getfield(n,"right"), + } end end -local langs, tags, noflanguages = { }, { }, 0 - -local colorbytag = false +local langs = { } +local tags = { } +local noflanguages = 0 +local colorbytag = false function moduledata.languages.hyphenation.showhyphens(head) if noflanguages > 0 then local marked = { } + local cached = { } + -- somehow assigning -1 fails + for n in traverse_by_id(glyph_code,tonut(head)) do + cached[n] = { + getfield(n,"lang"), + getfield(n,"left"), + getfield(n,"right") + } + end for i=1,noflanguages do local m = { } local l = langs[i] + local s = states[l] marked[i] = m - for n in traverse_by_id(glyph_code,head) do - n.lang = l + local lmin = s.lefthyphenmin + local rmin = s.righthyphenmin + for n in next, cached do + setfield(n,"lang",l) + setfield(n,"left",lmin) + setfield(n,"right",rmin) end languages.hyphenators.methods.original(head) identify(head,m) - strip(head,m) end for i=noflanguages,1,-1 do local l = noflanguages - i + 1 mark(head,marked[i],1/16,l/2,l/4,"hyphenation:"..(colorbytag and tags[i] or i)) end + for n, d in next, cached do + setfield(n,"lang",d[1]) + setfield(n,"left",d[2]) + setfield(n,"right",d[3]) + end return head, true else return head, false end end -local savedlanguage - function moduledata.languages.hyphenation.startcomparepatterns(list) if list and list ~= "" then tags = utilities.parsers.settings_to_array(list) end - savedlanguage = tex.language - tex.language = 0 noflanguages = #tags + context.begingroup() for i=1,noflanguages do langs[i] = tags[i] and languages.getnumber(tags[i]) + context.language{tags[i]} end + context.endgroup() nodes.tasks.enableaction("processors","moduledata.languages.hyphenation.showhyphens") end function moduledata.languages.hyphenation.stopcomparepatterns() noflanguages = 0 - tex.language = savedlanguage or tex.language nodes.tasks.disableaction("processors","moduledata.languages.hyphenation.showhyphens") end diff --git a/Master/texmf-dist/tex/context/modules/mkiv/s-languages-hyphenation.mkiv b/Master/texmf-dist/tex/context/modules/mkiv/s-languages-hyphenation.mkiv index 6662dbf2f32..9ff5720a04f 100644 --- a/Master/texmf-dist/tex/context/modules/mkiv/s-languages-hyphenation.mkiv +++ b/Master/texmf-dist/tex/context/modules/mkiv/s-languages-hyphenation.mkiv @@ -34,6 +34,12 @@ \ctxlua{moduledata.languages.hyphenation.stopcomparepatterns()}% \endgroup} +\appendtoks + \clf_storelanguagestate % global +\to \everylanguage + +\clf_storelanguagestate % initialize + \installmodulecommandluasingle \showcomparepatternslegend {moduledata.languages.hyphenation.showcomparelegend} \protect @@ -42,11 +48,13 @@ \definecolor[hyphenation:2] [g=.8] \definecolor[hyphenation:3] [b=.8] \definecolor[hyphenation:4] [r=.4,g=.4] +\definecolor[hyphenation:5] [r=.4,b=.4] \definecolor[hyphenation:en] [hyphenation:1] \definecolor[hyphenation:de] [hyphenation:2] \definecolor[hyphenation:nl] [hyphenation:3] \definecolor[hyphenation:fr] [hyphenation:4] +\definecolor[hyphenation:sl] [hyphenation:5] \stopmodule @@ -56,10 +64,33 @@ \starttext -\def|#1|{-} + \startcomparepatterns[en,sl] + {For Mojca Miklavec} + {For Mojca Miklavec} + \stopcomparepatterns + + \startcomparepatterns[en] + {For Mojca Miklavec} + {For Mojca Miklavec} + \stopcomparepatterns + + \startcomparepatterns[sl] + {For Mojca Miklavec} + {For Mojca Miklavec} + \stopcomparepatterns + + \startcomparepatterns[en,sl] + {For Mojca Miklavec}\crlf + {For Mojca Miklavec}\crlf + {\de For Mojca Miklavec}\crlf + {For Mojca Miklavec}\crlf + {\fr For Mojca Miklavec} + \stopcomparepatterns + + \page \startsubject{Normal text} - \input tufte + \input tufte \stopsubject \startsubject{Compare hyphenation points of \showcomparepatternslegend[en,de]} diff --git a/Master/texmf-dist/tex/context/modules/mkiv/s-mod-01.mkiv b/Master/texmf-dist/tex/context/modules/mkiv/s-mod-01.mkiv index 6946bef691c..f1c8d425806 100644 --- a/Master/texmf-dist/tex/context/modules/mkiv/s-mod-01.mkiv +++ b/Master/texmf-dist/tex/context/modules/mkiv/s-mod-01.mkiv @@ -278,13 +278,14 @@ \setuplayout [\c!backspace=3.5cm, + \c!cutspace=2cm, \c!leftmargin=1.75cm, \c!rightmargin=0cm, \c!margindistance=.5cm, \c!leftedgedistance=.25cm, \c!rightedgedistance=.5cm, \c!edge=1.5cm, - \c!width=15.55333cm, % 13.998cm at 9pt => 15.55333 at 10pt + \c!width=middle, \c!topspace=2cm, \c!header=1.25cm, \c!footer=1.25cm, diff --git a/Master/texmf-dist/tex/context/modules/mkiv/x-ldx.lua b/Master/texmf-dist/tex/context/modules/mkiv/x-ldx.lua index 31cbebf1392..e88c4c79772 100644 --- a/Master/texmf-dist/tex/context/modules/mkiv/x-ldx.lua +++ b/Master/texmf-dist/tex/context/modules/mkiv/x-ldx.lua @@ -19,13 +19,13 @@ with . I will rewrite this using lpeg. On the other hand, we cannot expect proper and for educational purposed the syntax might be wrong. + +Todo: use the scite parser. --ldx]]-- --- there is a nice parser on from http://lua-users.org/wiki/LpegRecipes (by --- Patrick Donnelly) but lua crashes when I apply functions to some of the --- matches +local banner = "version 1.0.1 - 2007+ - PRAGMA ADE / CONTEXT" -banner = "version 1.0.1 - 2007+ - PRAGMA ADE / CONTEXT" +local report = logs.reporter("x-ldx") --[[ This script needs a few libraries. Instead of merging the code here @@ -226,6 +226,8 @@ and by calculating the indentation we also avoid space troubles. It also makes it possible to change the indentation afterwards. --ldx]]-- +local newmethod = true + function ldx.as_xml(data) -- ldx: not needed local t, cmode = { }, false t[#t+1] = "\n" @@ -233,38 +235,44 @@ function ldx.as_xml(data) -- ldx: not needed for k=1,#data do local v = data[k] if v.code and not emptystring(v.code) then - t[#t+1] = "\n\n" - local split = splitstring(v.code,"\n") - for k=1,#split do -- make this faster - local v = split[k] - local a, b = find(v,"^(%s+)") - if v then v = gsub(v,"[\n\r ]+$","") end - if a and b then - v = sub(v,b+1,#v) - if cmode then - t[#t+1] = "" .. v .. "\n" - else - t[#t+1] = "" .. v .. "\n" - end - elseif emptystring(v) then - if cmode then - t[#t+1] = "\n" + if newmethod then + t[#t+1] = "\n\n" + else + t[#t+1] = "\n\n" + local split = splitstring(v.code,"\n") + for k=1,#split do -- make this faster + local v = split[k] + local a, b = find(v,"^(%s+)") + if v then v = gsub(v,"[\n\r ]+$","") end + if a and b then + v = sub(v,b+1,#v) + if cmode then + t[#t+1] = "" .. v .. "\n" + else + t[#t+1] = "" .. v .. "\n" + end + elseif emptystring(v) then + if cmode then + t[#t+1] = "\n" + else + t[#t+1] = "\n" + end + elseif find(v,"^%-%-%[%[") then + t[#t+1] = "" .. v .. "\n" + cmode= true + elseif find(v,"^%]%]%-%-") then + t[#t+1] = "" .. v .. "\n" + cmode= false + elseif cmode then + t[#t+1] = "" .. v .. "\n" else - t[#t+1] = "\n" + t[#t+1] = "" .. v .. "\n" end - elseif find(v,"^%-%-%[%[") then - t[#t+1] = "" .. v .. "\n" - cmode= true - elseif find(v,"^%]%]%-%-") then - t[#t+1] = "" .. v .. "\n" - cmode= false - elseif cmode then - t[#t+1] = "" .. v .. "\n" - else - t[#t+1] = "" .. v .. "\n" end + t[#t+1] = "\n" end - t[#t+1] = "\n" elseif v.comment then t[#t+1] = "\n\n" .. v.comment .. "\n\n" else @@ -288,20 +296,25 @@ The next function wraps it all in one call: --ldx]]-- function ldx.convert(luaname,ldxname) - if not file.is_readable(luaname) then - luaname = luaname .. ".lua" + if not lfs.isfile(luaname) then + file.addsuffix(luaname,"lua") end - if file.is_readable(luaname) then + if lfs.isfile(luaname) then if not ldxname then ldxname = file.replacesuffix(luaname,"ldx") end + report("converting file %a to %a",luaname,ldxname) local data = ldx.load(luaname) if data then - ldx.enhance(data) +-- ldx.enhance(data) if ldxname ~= luaname then ldx.save(ldxname,data) end + else + report("invalid file %a",luaname) end + else + report("unknown file %a",luaname) end end @@ -336,6 +349,6 @@ The main conversion call is: if environment.files and environment.files[1] then ldx.convert(environment.files[1],environment.files[2]) +else + report("no file given") end - ---~ exit(1) diff --git a/Master/texmf-dist/tex/context/modules/mkiv/x-ldx.mkiv b/Master/texmf-dist/tex/context/modules/mkiv/x-ldx.mkiv index 0156f2c5569..06163a594bb 100644 --- a/Master/texmf-dist/tex/context/modules/mkiv/x-ldx.mkiv +++ b/Master/texmf-dist/tex/context/modules/mkiv/x-ldx.mkiv @@ -93,7 +93,23 @@ \startxmlsetups ldx:code \startpacked \xmlflush{#1}\relax - \stoppacked + \scitepacked +\stopxmlsetups + +\startluacode + function xml.finalizers.tex.cdatatobuffer(c,name) + buffers.assign(name,xml.cdata(c[1])) + end +\stopluacode + +\startxmlsetups ldx:luacode + \blank + \begingroup + \switchtobodyfont[dejavu-condensed] + \xmlfilter{#1}{./cdatatobuffer('name')} + \scitebuffer[lua][name] + \endgroup + \blank \stopxmlsetups \startxmlsetups ldx:lines @@ -150,26 +166,22 @@ % code -> cd % comment -> tx (text) -\definetypeface[mainfacenormal] [ss][sans] [iwona] [default] -\definetypeface[mainfacenormal] [rm][serif][palatino] [default] -\definetypeface[mainfacenormal] [tt][mono] [modern] [default][rscale=1] % 1.1 -\definetypeface[mainfacenormal] [mm][math] [iwona] [default][encoding=default] - -\definetypeface[mainfacemedium] [ss][sans] [iwona-medium][default] -\definetypeface[mainfacenormal] [rm][serif][palatino] [default] -\definetypeface[mainfacemedium] [tt][mono] [modern] [default][rscale=1] % 1.1 -\definetypeface[mainfacemedium] [mm][math] [iwona-medium][default][encoding=default] +\usemodule[scite] -\definetypeface[mainfacenarrowtt][tt][mono] [modern-cond] [default][rscale=1] % 1.1 +\switchtobodyfont + [dejavu-condensed,10pt] % preload \setupbodyfont - [mainfacenormal,11pt] + [dejavu,10pt] % main font + +\mainlanguage + [en] \setupwhitespace [big] -\defineregister[function][functions] -\defineregister[variable][variables] +\defineregister[function] +\defineregister[variable] \definehead[source][subject] \definehead[extra] [subsubject] @@ -190,7 +202,15 @@ \setuplayout [width=middle, height=middle, - backspace=2cm, - topspace=2cm] + footer=0pt, + header=1.5cm, + backspace=1.5cm, + topspace=1.5cm] + +\doifmode {nocolor} { + + \setupcolors + [conversion=always] +} \endinput diff --git a/Master/texmf-dist/tex/generic/context/luatex/luatex-fonts-merged.lua b/Master/texmf-dist/tex/generic/context/luatex/luatex-fonts-merged.lua index 5f35deddf86..3e6f1d138dc 100644 --- a/Master/texmf-dist/tex/generic/context/luatex/luatex-fonts-merged.lua +++ b/Master/texmf-dist/tex/generic/context/luatex/luatex-fonts-merged.lua @@ -1,6 +1,6 @@ -- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua -- parent file : c:/data/develop/context/sources/luatex-fonts.lua --- merge date : 05/01/16 09:52:32 +-- merge date : 05/08/16 17:30:49 do -- begin closure to overcome local limits and interference @@ -6973,51 +6973,61 @@ end -- closure do -- begin closure to overcome local limits and interference -if not modules then modules={} end modules ['font-afm']={ +if not modules then modules={} end modules ['font-oti']={ version=1.001, comment="companion to font-ini.mkiv", author="Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright="PRAGMA ADE / ConTeXt Development Team", license="see context related readme files" } -local fonts,logs,trackers,containers,resolvers=fonts,logs,trackers,containers,resolvers -local next,type,tonumber=next,type,tonumber -local match,gmatch,lower,gsub,strip,find=string.match,string.gmatch,string.lower,string.gsub,string.strip,string.find -local char,byte,sub=string.char,string.byte,string.sub -local abs=math.abs -local bxor,rshift=bit32.bxor,bit32.rshift -local P,S,R,Cmt,C,Ct,Cs,lpegmatch,patterns=lpeg.P,lpeg.S,lpeg.R,lpeg.Cmt,lpeg.C,lpeg.Ct,lpeg.Cs,lpeg.match,lpeg.patterns -local derivetable=table.derive -local trace_features=false trackers.register("afm.features",function(v) trace_features=v end) -local trace_indexing=false trackers.register("afm.indexing",function(v) trace_indexing=v end) -local trace_loading=false trackers.register("afm.loading",function(v) trace_loading=v end) -local trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end) -local report_afm=logs.reporter("fonts","afm loading") -local setmetatableindex=table.setmetatableindex -local findbinfile=resolvers.findbinfile -local definers=fonts.definers -local readers=fonts.readers +local lower=string.lower +local fonts=fonts local constructors=fonts.constructors -local afm=constructors.newhandler("afm") -local pfb=constructors.newhandler("pfb") -local afmfeatures=constructors.newfeatures("afm") -local registerafmfeature=afmfeatures.register -afm.version=1.501 -afm.cache=containers.define("fonts","afm",afm.version,true) -afm.autoprefixed=true -afm.helpdata={} -afm.syncspace=true -afm.addligatures=true -afm.addtexligatures=true -afm.addkerns=true -local overloads=fonts.mappings.overloads -local applyruntimefixes=fonts.treatments and fonts.treatments.applyfixes +local otf=constructors.newhandler("otf") +local otffeatures=constructors.newfeatures("otf") +local registerotffeature=otffeatures.register +local otftables=otf.tables or {} +otf.tables=otftables +local allocate=utilities.storage.allocate +registerotffeature { + name="features", + description="initialization of feature handler", + default=true, +} local function setmode(tfmdata,value) if value then tfmdata.properties.mode=lower(value) end end -registerafmfeature { +local function setlanguage(tfmdata,value) + if value then + local cleanvalue=lower(value) + local languages=otftables and otftables.languages + local properties=tfmdata.properties + if not languages then + properties.language=cleanvalue + elseif languages[value] then + properties.language=cleanvalue + else + properties.language="dflt" + end + end +end +local function setscript(tfmdata,value) + if value then + local cleanvalue=lower(value) + local scripts=otftables and otftables.scripts + local properties=tfmdata.properties + if not scripts then + properties.script=cleanvalue + elseif scripts[value] then + properties.script=cleanvalue + else + properties.script="dflt" + end + end +end +registerotffeature { name="mode", description="mode", initializers={ @@ -7025,1217 +7035,76 @@ registerafmfeature { node=setmode, } } -local comment=P("Comment") -local spacing=patterns.spacer -local lineend=patterns.newline -local words=C((1-lineend)^1) -local number=C((R("09")+S("."))^1)/tonumber*spacing^0 -local data=lpeg.Carg(1) -local pattern=( - comment*spacing*( - data*( - ("CODINGSCHEME"*spacing*words )/function(fd,a) end+("DESIGNSIZE"*spacing*number*words )/function(fd,a) fd[ 1]=a end+("CHECKSUM"*spacing*number*words )/function(fd,a) fd[ 2]=a end+("SPACE"*spacing*number*"plus"*number*"minus"*number)/function(fd,a,b,c) fd[ 3],fd[ 4],fd[ 5]=a,b,c end+("QUAD"*spacing*number )/function(fd,a) fd[ 6]=a end+("EXTRASPACE"*spacing*number )/function(fd,a) fd[ 7]=a end+("NUM"*spacing*number*number*number )/function(fd,a,b,c) fd[ 8],fd[ 9],fd[10]=a,b,c end+("DENOM"*spacing*number*number )/function(fd,a,b ) fd[11],fd[12]=a,b end+("SUP"*spacing*number*number*number )/function(fd,a,b,c) fd[13],fd[14],fd[15]=a,b,c end+("SUB"*spacing*number*number )/function(fd,a,b) fd[16],fd[17]=a,b end+("SUPDROP"*spacing*number )/function(fd,a) fd[18]=a end+("SUBDROP"*spacing*number )/function(fd,a) fd[19]=a end+("DELIM"*spacing*number*number )/function(fd,a,b) fd[20],fd[21]=a,b end+("AXISHEIGHT"*spacing*number )/function(fd,a) fd[22]=a end - )+(1-lineend)^0 - )+(1-comment)^1 -)^0 -local function scan_comment(str) - local fd={} - lpegmatch(pattern,str,1,fd) - return fd -end -local keys={} -function keys.FontName (data,line) data.metadata.fontname=strip (line) - data.metadata.fullname=strip (line) end -function keys.ItalicAngle (data,line) data.metadata.italicangle=tonumber (line) end -function keys.IsFixedPitch(data,line) data.metadata.monospaced=toboolean(line,true) end -function keys.CharWidth (data,line) data.metadata.charwidth=tonumber (line) end -function keys.XHeight (data,line) data.metadata.xheight=tonumber (line) end -function keys.Descender (data,line) data.metadata.descender=tonumber (line) end -function keys.Ascender (data,line) data.metadata.ascender=tonumber (line) end -function keys.Comment (data,line) - line=lower(line) - local designsize=match(line,"designsize[^%d]*(%d+)") - if designsize then data.metadata.designsize=tonumber(designsize) end -end -local function get_charmetrics(data,charmetrics,vector) - local characters=data.characters - local chr,ind={},0 - for k,v in gmatch(charmetrics,"([%a]+) +(.-) *;") do - if k=='C' then - v=tonumber(v) - if v<0 then - ind=ind+1 +registerotffeature { + name="language", + description="language", + initializers={ + base=setlanguage, + node=setlanguage, + } +} +registerotffeature { + name="script", + description="script", + initializers={ + base=setscript, + node=setscript, + } +} +otftables.featuretypes=allocate { + gpos_single="position", + gpos_pair="position", + gpos_cursive="position", + gpos_mark2base="position", + gpos_mark2ligature="position", + gpos_mark2mark="position", + gpos_context="position", + gpos_contextchain="position", + gsub_single="substitution", + gsub_multiple="substitution", + gsub_alternate="substitution", + gsub_ligature="substitution", + gsub_context="substitution", + gsub_contextchain="substitution", + gsub_reversecontextchain="substitution", + gsub_reversesub="substitution", +} +function otffeatures.checkeddefaultscript(featuretype,autoscript,scripts) + if featuretype=="position" then + local default=scripts.dflt + if default then + if autoscript=="position" or autoscript==true then + return default else - ind=v + report_otf("script feature %s not applied, enable default positioning") end - chr={ - index=ind - } - elseif k=='WX' then - chr.width=tonumber(v) - elseif k=='N' then - characters[v]=chr - elseif k=='B' then - local llx,lly,urx,ury=match(v,"^ *(.-) +(.-) +(.-) +(.-)$") - chr.boundingbox={ tonumber(llx),tonumber(lly),tonumber(urx),tonumber(ury) } - elseif k=='L' then - local plus,becomes=match(v,"^(.-) +(.-)$") - local ligatures=chr.ligatures - if ligatures then - ligatures[plus]=becomes - else - chr.ligatures={ [plus]=becomes } + else + end + elseif featuretype=="substitution" then + local default=scripts.dflt + if default then + if autoscript=="substitution" or autoscript==true then + return default end end end end -local function get_kernpairs(data,kernpairs) - local characters=data.characters - for one,two,value in gmatch(kernpairs,"KPX +(.-) +(.-) +(.-)\n") do - local chr=characters[one] - if chr then - local kerns=chr.kerns - if kerns then - kerns[two]=tonumber(value) +function otffeatures.checkeddefaultlanguage(featuretype,autolanguage,languages) + if featuretype=="position" then + local default=languages.dflt + if default then + if autolanguage=="position" or autolanguage==true then + return default else - chr.kerns={ [two]=tonumber(value) } + report_otf("language feature %s not applied, enable default positioning") end + else end - end -end -local function get_variables(data,fontmetrics) - for key,rest in gmatch(fontmetrics,"(%a+) *(.-)[\n\r]") do - local keyhandler=keys[key] - if keyhandler then - keyhandler(data,rest) - end - end -end -local get_indexes -do - local fontloader=fontloader - local get_indexes_old=false - if fontloader then - local font_to_table=fontloader.to_table - local open_font=fontloader.open - local close_font=fontloader.close - get_indexes_old=function(data,pfbname) - local pfbblob=open_font(pfbname) - if pfbblob then - local characters=data.characters - local pfbdata=font_to_table(pfbblob) - if pfbdata then - local glyphs=pfbdata.glyphs - if glyphs then - if trace_loading then - report_afm("getting index data from %a",pfbname) - end - for index,glyph in next,glyphs do - local name=glyph.name - if name then - local char=characters[name] - if char then - if trace_indexing then - report_afm("glyph %a has index %a",name,index) - end - char.index=index - end - end - end - elseif trace_loading then - report_afm("no glyph data in pfb file %a",pfbname) - end - elseif trace_loading then - report_afm("no data in pfb file %a",pfbname) - end - close_font(pfbblob) - elseif trace_loading then - report_afm("invalid pfb file %a",pfbname) - end - end - end - local n,m - local progress=function(str,position,name,size) - local forward=position+tonumber(size)+3+2 - n=n+1 - if n>=m then - return #str,name - elseif forward<#str then - return forward,name - else - return #str,name - end - end - local initialize=function(str,position,size) - n=0 - m=tonumber(size) - return position+1 - end - local charstrings=P("/CharStrings") - local name=P("/")*C((R("az")+R("AZ")+R("09")+S("-_."))^1) - local size=C(R("09")^1) - local spaces=P(" ")^1 - local p_filternames=Ct ( - (1-charstrings)^0*charstrings*spaces*Cmt(size,initialize)*(Cmt(name*P(" ")^1*C(R("09")^1),progress)+P(1))^1 - ) - local decrypt - do - local r,c1,c2,n=0,0,0,0 - local function step(c) - local cipher=byte(c) - local plain=bxor(cipher,rshift(r,8)) - r=((cipher+r)*c1+c2)%65536 - return char(plain) - end - decrypt=function(binary) - r,c1,c2,n=55665,52845,22719,4 - binary=gsub(binary,".",step) - return sub(binary,n+1) - end - end - local function loadpfbvector(filename) - local data=io.loaddata(resolvers.findfile(filename)) - if not find(data,"!PS%-AdobeFont%-") then - print("no font",filename) - return - end - if not data then - print("no data",filename) - return - end - local ascii,binary=match(data,"(.*)eexec%s+......(.*)") - if not binary then - print("no binary",filename) - return - end - binary=decrypt(binary,4) - local vector=lpegmatch(p_filternames,binary) - vector[0]=table.remove(vector,1) - if not vector then - print("no vector",filename) - return - end - return vector - end - get_indexes=function(data,pfbname) - local vector=loadpfbvector(pfbname) - if vector then - local characters=data.characters - if trace_loading then - report_afm("getting index data from %a",pfbname) - end - for index=1,#vector do - local name=vector[index] - local char=characters[name] - if char then - if trace_indexing then - report_afm("glyph %a has index %a",name,index) - end - char.index=index - end - end - end - end - if get_indexes_old then - afm.use_new_indexer=true - get_indexes_new=get_indexes - get_indexes=function(data,pfbname) - if afm.use_new_indexer then - return get_indexes_new(data,pfbname) - else - return get_indexes_old(data,pfbname) - end - end - end -end -local function readafm(filename) - local ok,afmblob,size=resolvers.loadbinfile(filename) - if ok and afmblob then - local data={ - resources={ - filename=resolvers.unresolve(filename), - version=afm.version, - creator="context mkiv", - }, - properties={ - hasitalics=false, - }, - goodies={}, - metadata={ - filename=file.removesuffix(file.basename(filename)) - }, - characters={ - }, - descriptions={ - }, - } - afmblob=gsub(afmblob,"StartCharMetrics(.-)EndCharMetrics",function(charmetrics) - if trace_loading then - report_afm("loading char metrics") - end - get_charmetrics(data,charmetrics,vector) - return "" - end) - afmblob=gsub(afmblob,"StartKernPairs(.-)EndKernPairs",function(kernpairs) - if trace_loading then - report_afm("loading kern pairs") - end - get_kernpairs(data,kernpairs) - return "" - end) - afmblob=gsub(afmblob,"StartFontMetrics%s+([%d%.]+)(.-)EndFontMetrics",function(version,fontmetrics) - if trace_loading then - report_afm("loading variables") - end - data.afmversion=version - get_variables(data,fontmetrics) - data.fontdimens=scan_comment(fontmetrics) - return "" - end) - return data - else - if trace_loading then - report_afm("no valid afm file %a",filename) - end - return nil - end -end -local addkerns,addligatures,addtexligatures,unify,normalize,fixnames -function afm.load(filename) - filename=resolvers.findfile(filename,'afm') or "" - if filename~="" and not fonts.names.ignoredfile(filename) then - local name=file.removesuffix(file.basename(filename)) - local data=containers.read(afm.cache,name) - local attr=lfs.attributes(filename) - local size,time=attr.size or 0,attr.modification or 0 - local pfbfile=file.replacesuffix(name,"pfb") - local pfbname=resolvers.findfile(pfbfile,"pfb") or "" - if pfbname=="" then - pfbname=resolvers.findfile(file.basename(pfbfile),"pfb") or "" - end - local pfbsize,pfbtime=0,0 - if pfbname~="" then - local attr=lfs.attributes(pfbname) - pfbsize=attr.size or 0 - pfbtime=attr.modification or 0 - end - if not data or data.size~=size or data.time~=time or data.pfbsize~=pfbsize or data.pfbtime~=pfbtime then - report_afm("reading %a",filename) - data=readafm(filename) - if data then - if pfbname~="" then - data.resources.filename=resolvers.unresolve(pfbname) - get_indexes(data,pfbname) - elseif trace_loading then - report_afm("no pfb file for %a",filename) - end - report_afm("unifying %a",filename) - unify(data,filename) - if afm.addligatures then - report_afm("add ligatures") - addligatures(data) - end - if afm.addtexligatures then - report_afm("add tex ligatures") - addtexligatures(data) - end - if afm.addkerns then - report_afm("add extra kerns") - addkerns(data) - end - normalize(data) - fixnames(data) - report_afm("add tounicode data") - fonts.mappings.addtounicode(data,filename) - data.size=size - data.time=time - data.pfbsize=pfbsize - data.pfbtime=pfbtime - report_afm("saving %a in cache",name) - data.resources.unicodes=nil - data=containers.write(afm.cache,name,data) - data=containers.read(afm.cache,name) - end - if applyruntimefixes and data then - applyruntimefixes(filename,data) - end - end - return data - else - return nil - end -end -local uparser=fonts.mappings.makenameparser() -unify=function(data,filename) - local unicodevector=fonts.encodings.agl.unicodes - local unicodes={} - local names={} - local private=constructors.privateoffset - local descriptions=data.descriptions - for name,blob in next,data.characters do - local code=unicodevector[name] - if not code then - code=lpegmatch(uparser,name) - if not code then - code=private - private=private+1 - report_afm("assigning private slot %U for unknown glyph name %a",code,name) - end - end - local index=blob.index - unicodes[name]=code - names[name]=index - blob.name=name - descriptions[code]={ - boundingbox=blob.boundingbox, - width=blob.width, - kerns=blob.kerns, - index=index, - name=name, - } - end - for unicode,description in next,descriptions do - local kerns=description.kerns - if kerns then - local krn={} - for name,kern in next,kerns do - local unicode=unicodes[name] - if unicode then - krn[unicode]=kern - else - end - end - description.kerns=krn - end - end - data.characters=nil - local resources=data.resources - local filename=resources.filename or file.removesuffix(file.basename(filename)) - resources.filename=resolvers.unresolve(filename) - resources.unicodes=unicodes - resources.marks={} - resources.private=private -end -local everywhere={ ["*"]={ ["*"]=true } } -local noflags={ false,false,false,false } -afm.experimental_normalize=false -normalize=function(data) - if type(afm.experimental_normalize)=="function" then - afm.experimental_normalize(data) - end -end -fixnames=function(data) - for k,v in next,data.descriptions do - local n=v.name - local r=overloads[n] - if r then - local name=r.name - if trace_indexing then - report_afm("renaming characters %a to %a",n,name) - end - v.name=name - v.unicode=r.unicode - end - end -end -local addthem=function(rawdata,ligatures) - if ligatures then - local descriptions=rawdata.descriptions - local resources=rawdata.resources - local unicodes=resources.unicodes - for ligname,ligdata in next,ligatures do - local one=descriptions[unicodes[ligname]] - if one then - for _,pair in next,ligdata do - local two,three=unicodes[pair[1]],unicodes[pair[2]] - if two and three then - local ol=one.ligatures - if ol then - if not ol[two] then - ol[two]=three - end - else - one.ligatures={ [two]=three } - end - end - end - end - end - end -end -addligatures=function(rawdata) addthem(rawdata,afm.helpdata.ligatures ) end -addtexligatures=function(rawdata) addthem(rawdata,afm.helpdata.texligatures) end -addkerns=function(rawdata) - local descriptions=rawdata.descriptions - local resources=rawdata.resources - local unicodes=resources.unicodes - local function do_it_left(what) - if what then - for unicode,description in next,descriptions do - local kerns=description.kerns - if kerns then - local extrakerns - for complex,simple in next,what do - complex=unicodes[complex] - simple=unicodes[simple] - if complex and simple then - local ks=kerns[simple] - if ks and not kerns[complex] then - if extrakerns then - extrakerns[complex]=ks - else - extrakerns={ [complex]=ks } - end - end - end - end - if extrakerns then - description.extrakerns=extrakerns - end - end - end - end - end - local function do_it_copy(what) - if what then - for complex,simple in next,what do - complex=unicodes[complex] - simple=unicodes[simple] - if complex and simple then - local complexdescription=descriptions[complex] - if complexdescription then - local simpledescription=descriptions[complex] - if simpledescription then - local extrakerns - local kerns=simpledescription.kerns - if kerns then - for unicode,kern in next,kerns do - if extrakerns then - extrakerns[unicode]=kern - else - extrakerns={ [unicode]=kern } - end - end - end - local extrakerns=simpledescription.extrakerns - if extrakerns then - for unicode,kern in next,extrakerns do - if extrakerns then - extrakerns[unicode]=kern - else - extrakerns={ [unicode]=kern } - end - end - end - if extrakerns then - complexdescription.extrakerns=extrakerns - end - end - end - end - end - end - end - do_it_left(afm.helpdata.leftkerned) - do_it_left(afm.helpdata.bothkerned) - do_it_copy(afm.helpdata.bothkerned) - do_it_copy(afm.helpdata.rightkerned) -end -local function adddimensions(data) - if data then - for unicode,description in next,data.descriptions do - local bb=description.boundingbox - if bb then - local ht,dp=bb[4],-bb[2] - if ht==0 or ht<0 then - else - description.height=ht - end - if dp==0 or dp<0 then - else - description.depth=dp - end - end - end - end -end -local function copytotfm(data) - if data and data.descriptions then - local metadata=data.metadata - local resources=data.resources - local properties=derivetable(data.properties) - local descriptions=derivetable(data.descriptions) - local goodies=derivetable(data.goodies) - local characters={} - local parameters={} - local unicodes=resources.unicodes - for unicode,description in next,data.descriptions do - characters[unicode]={} - end - local filename=constructors.checkedfilename(resources) - local fontname=metadata.fontname or metadata.fullname - local fullname=metadata.fullname or metadata.fontname - local endash=0x0020 - local emdash=0x2014 - local spacer="space" - local spaceunits=500 - local monospaced=metadata.monospaced - local charwidth=metadata.charwidth - local italicangle=metadata.italicangle - local charxheight=metadata.xheight and metadata.xheight>0 and metadata.xheight - properties.monospaced=monospaced - parameters.italicangle=italicangle - parameters.charwidth=charwidth - parameters.charxheight=charxheight - if properties.monospaced then - if descriptions[endash] then - spaceunits,spacer=descriptions[endash].width,"space" - end - if not spaceunits and descriptions[emdash] then - spaceunits,spacer=descriptions[emdash].width,"emdash" - end - if not spaceunits and charwidth then - spaceunits,spacer=charwidth,"charwidth" - end - else - if descriptions[endash] then - spaceunits,spacer=descriptions[endash].width,"space" - end - if not spaceunits and charwidth then - spaceunits,spacer=charwidth,"charwidth" - end - end - spaceunits=tonumber(spaceunits) - if spaceunits<200 then - end - parameters.slant=0 - parameters.space=spaceunits - parameters.space_stretch=500 - parameters.space_shrink=333 - parameters.x_height=400 - parameters.quad=1000 - if italicangle and italicangle~=0 then - parameters.italicangle=italicangle - parameters.italicfactor=math.cos(math.rad(90+italicangle)) - parameters.slant=- math.tan(italicangle*math.pi/180) - end - if monospaced then - parameters.space_stretch=0 - parameters.space_shrink=0 - elseif afm.syncspace then - parameters.space_stretch=spaceunits/2 - parameters.space_shrink=spaceunits/3 - end - parameters.extra_space=parameters.space_shrink - if charxheight then - parameters.x_height=charxheight - else - local x=0x0078 - if x then - local x=descriptions[x] - if x then - parameters.x_height=x.height - end - end - end - local fd=data.fontdimens - if fd and fd[8] and fd[9] and fd[10] then - for k,v in next,fd do - parameters[k]=v - end - end - parameters.designsize=(metadata.designsize or 10)*65536 - parameters.ascender=abs(metadata.ascender or 0) - parameters.descender=abs(metadata.descender or 0) - parameters.units=1000 - properties.spacer=spacer - properties.encodingbytes=2 - properties.format=fonts.formats[filename] or "type1" - properties.filename=filename - properties.fontname=fontname - properties.fullname=fullname - properties.psname=fullname - properties.name=filename or fullname or fontname - if next(characters) then - return { - characters=characters, - descriptions=descriptions, - parameters=parameters, - resources=resources, - properties=properties, - goodies=goodies, - } - end - end - return nil -end -function afm.setfeatures(tfmdata,features) - local okay=constructors.initializefeatures("afm",tfmdata,features,trace_features,report_afm) - if okay then - return constructors.collectprocessors("afm",tfmdata,features,trace_features,report_afm) - else - return {} - end -end -local function addtables(data) - local resources=data.resources - local lookuptags=resources.lookuptags - local unicodes=resources.unicodes - if not lookuptags then - lookuptags={} - resources.lookuptags=lookuptags - end - setmetatableindex(lookuptags,function(t,k) - local v=type(k)=="number" and ("lookup "..k) or k - t[k]=v - return v - end) - if not unicodes then - unicodes={} - resources.unicodes=unicodes - setmetatableindex(unicodes,function(t,k) - setmetatableindex(unicodes,nil) - for u,d in next,data.descriptions do - local n=d.name - if n then - t[n]=u - end - end - return rawget(t,k) - end) - end - constructors.addcoreunicodes(unicodes) -end -local function afmtotfm(specification) - local afmname=specification.filename or specification.name - if specification.forced=="afm" or specification.format=="afm" then - if trace_loading then - report_afm("forcing afm format for %a",afmname) - end - else - local tfmname=findbinfile(afmname,"ofm") or "" - if tfmname~="" then - if trace_loading then - report_afm("fallback from afm to tfm for %a",afmname) - end - return - end - end - if afmname~="" then - local features=constructors.checkedfeatures("afm",specification.features.normal) - specification.features.normal=features - constructors.hashinstance(specification,true) - specification=definers.resolve(specification) - local cache_id=specification.hash - local tfmdata=containers.read(constructors.cache,cache_id) - if not tfmdata then - local rawdata=afm.load(afmname) - if rawdata and next(rawdata) then - addtables(rawdata) - adddimensions(rawdata) - tfmdata=copytotfm(rawdata) - if tfmdata and next(tfmdata) then - local shared=tfmdata.shared - if not shared then - shared={} - tfmdata.shared=shared - end - shared.rawdata=rawdata - shared.features=features - shared.processes=afm.setfeatures(tfmdata,features) - end - elseif trace_loading then - report_afm("no (valid) afm file found with name %a",afmname) - end - tfmdata=containers.write(constructors.cache,cache_id,tfmdata) - end - return tfmdata - end -end -local function read_from_afm(specification) - local tfmdata=afmtotfm(specification) - if tfmdata then - tfmdata.properties.name=specification.name - tfmdata=constructors.scale(tfmdata,specification) - local allfeatures=tfmdata.shared.features or specification.features.normal - constructors.applymanipulators("afm",tfmdata,allfeatures,trace_features,report_afm) - fonts.loggers.register(tfmdata,'afm',specification) - end - return tfmdata -end -local function prepareligatures(tfmdata,ligatures,value) - if value then - local descriptions=tfmdata.descriptions - local hasligatures=false - for unicode,character in next,tfmdata.characters do - local description=descriptions[unicode] - local dligatures=description.ligatures - if dligatures then - local cligatures=character.ligatures - if not cligatures then - cligatures={} - character.ligatures=cligatures - end - for unicode,ligature in next,dligatures do - cligatures[unicode]={ - char=ligature, - type=0 - } - end - hasligatures=true - end - end - tfmdata.properties.hasligatures=hasligatures - end -end -local function preparekerns(tfmdata,kerns,value) - if value then - local rawdata=tfmdata.shared.rawdata - local resources=rawdata.resources - local unicodes=resources.unicodes - local descriptions=tfmdata.descriptions - local haskerns=false - for u,chr in next,tfmdata.characters do - local d=descriptions[u] - local newkerns=d[kerns] - if newkerns then - local kerns=chr.kerns - if not kerns then - kerns={} - chr.kerns=kerns - end - for k,v in next,newkerns do - local uk=unicodes[k] - if uk then - kerns[uk]=v - end - end - haskerns=true - end - end - tfmdata.properties.haskerns=haskerns - end -end -local list={ - [0x0027]=0x2019, -} -local function texreplacements(tfmdata,value) - local descriptions=tfmdata.descriptions - local characters=tfmdata.characters - for k,v in next,list do - characters [k]=characters [v] - descriptions[k]=descriptions[v] - end -end -local function ligatures (tfmdata,value) prepareligatures(tfmdata,'ligatures',value) end -local function texligatures(tfmdata,value) prepareligatures(tfmdata,'texligatures',value) end -local function kerns (tfmdata,value) preparekerns (tfmdata,'kerns',value) end -local function extrakerns (tfmdata,value) preparekerns (tfmdata,'extrakerns',value) end -registerafmfeature { - name="liga", - description="traditional ligatures", - initializers={ - base=ligatures, - node=ligatures, - } -} -registerafmfeature { - name="kern", - description="intercharacter kerning", - initializers={ - base=kerns, - node=kerns, - } -} -registerafmfeature { - name="extrakerns", - description="additional intercharacter kerning", - initializers={ - base=extrakerns, - node=extrakerns, - } -} -registerafmfeature { - name='tlig', - description='tex ligatures', - initializers={ - base=texligatures, - node=texligatures, - } -} -registerafmfeature { - name='trep', - description='tex replacements', - initializers={ - base=texreplacements, - node=texreplacements, - } -} -local check_tfm=readers.check_tfm -fonts.formats.afm="type1" -fonts.formats.pfb="type1" -local function check_afm(specification,fullname) - local foundname=findbinfile(fullname,'afm') or "" - if foundname=="" then - foundname=fonts.names.getfilename(fullname,"afm") or "" - end - if foundname=="" and afm.autoprefixed then - local encoding,shortname=match(fullname,"^(.-)%-(.*)$") - if encoding and shortname and fonts.encodings.known[encoding] then - shortname=findbinfile(shortname,'afm') or "" - if shortname~="" then - foundname=shortname - if trace_defining then - report_afm("stripping encoding prefix from filename %a",afmname) - end - end - end - end - if foundname~="" then - specification.filename=foundname - specification.format="afm" - return read_from_afm(specification) - end -end -function readers.afm(specification,method) - local fullname,tfmdata=specification.filename or "",nil - if fullname=="" then - local forced=specification.forced or "" - if forced~="" then - tfmdata=check_afm(specification,specification.name.."."..forced) - end - if not tfmdata then - method=method or definers.method or "afm or tfm" - if method=="tfm" then - tfmdata=check_tfm(specification,specification.name) - elseif method=="afm" then - tfmdata=check_afm(specification,specification.name) - elseif method=="tfm or afm" then - tfmdata=check_tfm(specification,specification.name) or check_afm(specification,specification.name) - else - tfmdata=check_afm(specification,specification.name) or check_tfm(specification,specification.name) - end - end - else - tfmdata=check_afm(specification,fullname) - end - return tfmdata -end -function readers.pfb(specification,method) - local original=specification.specification - if trace_defining then - report_afm("using afm reader for %a",original) - end - specification.specification=gsub(original,"%.pfb",".afm") - specification.forced="afm" - return readers.afm(specification,method) -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['font-afk']={ - version=1.001, - comment="companion to font-afm.lua", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files", - dataonly=true, -} -local allocate=utilities.storage.allocate -fonts.handlers.afm.helpdata={ - ligatures=allocate { - ['f']={ - { 'f','ff' }, - { 'i','fi' }, - { 'l','fl' }, - }, - ['ff']={ - { 'i','ffi' } - }, - ['fi']={ - { 'i','fii' } - }, - ['fl']={ - { 'i','fli' } - }, - ['s']={ - { 't','st' } - }, - ['i']={ - { 'j','ij' } - }, - }, - texligatures=allocate { - ['quoteleft']={ - { 'quoteleft','quotedblleft' } - }, - ['quoteright']={ - { 'quoteright','quotedblright' } - }, - ['hyphen']={ - { 'hyphen','endash' } - }, - ['endash']={ - { 'hyphen','emdash' } - } - }, - leftkerned=allocate { - AEligature="A",aeligature="a", - OEligature="O",oeligature="o", - IJligature="I",ijligature="i", - AE="A",ae="a", - OE="O",oe="o", - IJ="I",ij="i", - Ssharp="S",ssharp="s", - }, - rightkerned=allocate { - AEligature="E",aeligature="e", - OEligature="E",oeligature="e", - IJligature="J",ijligature="j", - AE="E",ae="e", - OE="E",oe="e", - IJ="J",ij="j", - Ssharp="S",ssharp="s", - }, - bothkerned=allocate { - Acircumflex="A",acircumflex="a", - Ccircumflex="C",ccircumflex="c", - Ecircumflex="E",ecircumflex="e", - Gcircumflex="G",gcircumflex="g", - Hcircumflex="H",hcircumflex="h", - Icircumflex="I",icircumflex="i", - Jcircumflex="J",jcircumflex="j", - Ocircumflex="O",ocircumflex="o", - Scircumflex="S",scircumflex="s", - Ucircumflex="U",ucircumflex="u", - Wcircumflex="W",wcircumflex="w", - Ycircumflex="Y",ycircumflex="y", - Agrave="A",agrave="a", - Egrave="E",egrave="e", - Igrave="I",igrave="i", - Ograve="O",ograve="o", - Ugrave="U",ugrave="u", - Ygrave="Y",ygrave="y", - Atilde="A",atilde="a", - Itilde="I",itilde="i", - Otilde="O",otilde="o", - Utilde="U",utilde="u", - Ntilde="N",ntilde="n", - Adiaeresis="A",adiaeresis="a",Adieresis="A",adieresis="a", - Ediaeresis="E",ediaeresis="e",Edieresis="E",edieresis="e", - Idiaeresis="I",idiaeresis="i",Idieresis="I",idieresis="i", - Odiaeresis="O",odiaeresis="o",Odieresis="O",odieresis="o", - Udiaeresis="U",udiaeresis="u",Udieresis="U",udieresis="u", - Ydiaeresis="Y",ydiaeresis="y",Ydieresis="Y",ydieresis="y", - Aacute="A",aacute="a", - Cacute="C",cacute="c", - Eacute="E",eacute="e", - Iacute="I",iacute="i", - Lacute="L",lacute="l", - Nacute="N",nacute="n", - Oacute="O",oacute="o", - Racute="R",racute="r", - Sacute="S",sacute="s", - Uacute="U",uacute="u", - Yacute="Y",yacute="y", - Zacute="Z",zacute="z", - Dstroke="D",dstroke="d", - Hstroke="H",hstroke="h", - Tstroke="T",tstroke="t", - Cdotaccent="C",cdotaccent="c", - Edotaccent="E",edotaccent="e", - Gdotaccent="G",gdotaccent="g", - Idotaccent="I",idotaccent="i", - Zdotaccent="Z",zdotaccent="z", - Amacron="A",amacron="a", - Emacron="E",emacron="e", - Imacron="I",imacron="i", - Omacron="O",omacron="o", - Umacron="U",umacron="u", - Ccedilla="C",ccedilla="c", - Kcedilla="K",kcedilla="k", - Lcedilla="L",lcedilla="l", - Ncedilla="N",ncedilla="n", - Rcedilla="R",rcedilla="r", - Scedilla="S",scedilla="s", - Tcedilla="T",tcedilla="t", - Ohungarumlaut="O",ohungarumlaut="o", - Uhungarumlaut="U",uhungarumlaut="u", - Aogonek="A",aogonek="a", - Eogonek="E",eogonek="e", - Iogonek="I",iogonek="i", - Uogonek="U",uogonek="u", - Aring="A",aring="a", - Uring="U",uring="u", - Abreve="A",abreve="a", - Ebreve="E",ebreve="e", - Gbreve="G",gbreve="g", - Ibreve="I",ibreve="i", - Obreve="O",obreve="o", - Ubreve="U",ubreve="u", - Ccaron="C",ccaron="c", - Dcaron="D",dcaron="d", - Ecaron="E",ecaron="e", - Lcaron="L",lcaron="l", - Ncaron="N",ncaron="n", - Rcaron="R",rcaron="r", - Scaron="S",scaron="s", - Tcaron="T",tcaron="t", - Zcaron="Z",zcaron="z", - dotlessI="I",dotlessi="i", - dotlessJ="J",dotlessj="j", - AEligature="AE",aeligature="ae",AE="AE",ae="ae", - OEligature="OE",oeligature="oe",OE="OE",oe="oe", - IJligature="IJ",ijligature="ij",IJ="IJ",ij="ij", - Lstroke="L",lstroke="l",Lslash="L",lslash="l", - Ostroke="O",ostroke="o",Oslash="O",oslash="o", - Ssharp="SS",ssharp="ss", - Aumlaut="A",aumlaut="a", - Eumlaut="E",eumlaut="e", - Iumlaut="I",iumlaut="i", - Oumlaut="O",oumlaut="o", - Uumlaut="U",uumlaut="u", - } -} - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['font-oti']={ - version=1.001, - comment="companion to font-ini.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local lower=string.lower -local fonts=fonts -local constructors=fonts.constructors -local otf=constructors.newhandler("otf") -local otffeatures=constructors.newfeatures("otf") -local registerotffeature=otffeatures.register -local otftables=otf.tables or {} -otf.tables=otftables -local allocate=utilities.storage.allocate -registerotffeature { - name="features", - description="initialization of feature handler", - default=true, -} -local function setmode(tfmdata,value) - if value then - tfmdata.properties.mode=lower(value) - end -end -local function setlanguage(tfmdata,value) - if value then - local cleanvalue=lower(value) - local languages=otftables and otftables.languages - local properties=tfmdata.properties - if not languages then - properties.language=cleanvalue - elseif languages[value] then - properties.language=cleanvalue - else - properties.language="dflt" - end - end -end -local function setscript(tfmdata,value) - if value then - local cleanvalue=lower(value) - local scripts=otftables and otftables.scripts - local properties=tfmdata.properties - if not scripts then - properties.script=cleanvalue - elseif scripts[value] then - properties.script=cleanvalue - else - properties.script="dflt" - end - end -end -registerotffeature { - name="mode", - description="mode", - initializers={ - base=setmode, - node=setmode, - } -} -registerotffeature { - name="language", - description="language", - initializers={ - base=setlanguage, - node=setlanguage, - } -} -registerotffeature { - name="script", - description="script", - initializers={ - base=setscript, - node=setscript, - } -} -otftables.featuretypes=allocate { - gpos_single="position", - gpos_pair="position", - gpos_cursive="position", - gpos_mark2base="position", - gpos_mark2ligature="position", - gpos_mark2mark="position", - gpos_context="position", - gpos_contextchain="position", - gsub_single="substitution", - gsub_multiple="substitution", - gsub_alternate="substitution", - gsub_ligature="substitution", - gsub_context="substitution", - gsub_contextchain="substitution", - gsub_reversecontextchain="substitution", - gsub_reversesub="substitution", -} -function otffeatures.checkeddefaultscript(featuretype,autoscript,scripts) - if featuretype=="position" then - local default=scripts.dflt - if default then - if autoscript=="position" or autoscript==true then - return default - else - report_otf("script feature %s not applied, enable default positioning") - end - else - end - elseif featuretype=="substitution" then - local default=scripts.dflt - if default then - if autoscript=="substitution" or autoscript==true then - return default - end - end - end -end -function otffeatures.checkeddefaultlanguage(featuretype,autolanguage,languages) - if featuretype=="position" then - local default=languages.dflt - if default then - if autolanguage=="position" or autolanguage==true then - return default - else - report_otf("language feature %s not applied, enable default positioning") - end - else - end - elseif featuretype=="substitution" then - local default=languages.dflt - if default then - if autolanguage=="substitution" or autolanguage==true then - return default + elseif featuretype=="substitution" then + local default=languages.dflt + if default then + if autolanguage=="substitution" or autolanguage==true then + return default end end end @@ -15827,7 +14696,6 @@ function otf.load(filename,sub,featurefile) otfreaders.expand(data) otfreaders.addunicodetable(data) enhancers.apply(data,filename,data) - constructors.addcoreunicodes(unicodes) if applyruntimefixes then applyruntimefixes(filename,data) end @@ -16658,6 +15526,7 @@ registerotffeature { base=featuresinitializer, } } +otf.basemodeinitializer=featuresinitializer end -- closure @@ -17713,11 +16582,11 @@ local function inject_everything(head,where) insert_node_after(pre,n,newkern(rightkern)) done=true end - end - if hasmarks then - local pm=i.markbasenode - if pm then - processmark(pm,current,i) + if hasmarks then + local pm=i.markbasenode + if pm then + processmark(pm,current,i) + end end end end @@ -17743,11 +16612,11 @@ local function inject_everything(head,where) insert_node_after(post,n,newkern(rightkern)) done=true end - end - if hasmarks then - local pm=i.markbasenode - if pm then - processmark(pm,current,i) + if hasmarks then + local pm=i.markbasenode + if pm then + processmark(pm,current,i) + end end end end @@ -17773,11 +16642,11 @@ local function inject_everything(head,where) insert_node_after(replace,n,newkern(rightkern)) done=true end - end - if hasmarks then - local pm=i.markbasenode - if pm then - processmark(pm,current,i) + if hasmarks then + local pm=i.markbasenode + if pm then + processmark(pm,current,i) + end end end end @@ -21284,6 +20153,8 @@ registerotffeature { node=featuresprocessor, } } +otf.nodemodeinitializer=featuresinitializer +otf.featuresprocessor=featuresprocessor otf.handlers=handlers local setspacekerns=nodes.injections.setspacekerns if not setspacekerns then os.exit() end function otf.handlers.trigger_space_kerns(head,start,dataset,sequence,_,_,_,_,font,attr) @@ -21826,1556 +20697,2710 @@ local function initializedevanagi(tfmdata) end end end - if valid[kind] then - for i=1,nofsteps do - local step=steps[i] - local coverage=step.coverage - if coverage then - local reph=false - if step.osdstep then - for k,v in next,ra do - local r=coverage[k] - if r then - local h=false - for k,v in next,halant do - local h=r[k] - if h then - reph=h.ligature or false - break - end - end - if reph then - break - end - end - end - else - end - seqsubset[#seqsubset+1]={ kind,coverage,reph } - end + if valid[kind] then + for i=1,nofsteps do + local step=steps[i] + local coverage=step.coverage + if coverage then + local reph=false + if step.osdstep then + for k,v in next,ra do + local r=coverage[k] + if r then + local h=false + for k,v in next,halant do + local h=r[k] + if h then + reph=h.ligature or false + break + end + end + if reph then + break + end + end + end + else + end + seqsubset[#seqsubset+1]={ kind,coverage,reph } + end + end + end + if kind=="pref" then + local sequence=dataset[3] + local steps=sequence.steps + local nofsteps=sequence.nofsteps + for i=1,nofsteps do + local step=steps[i] + local coverage=step.coverage + if coverage then + for k,v in next,halant do + local h=coverage[k] + if h then + local found=false + for k,v in next,h do + found=v and v.ligature + if found then + pre_base_reordering_consonants[k]=found + break + end + end + if found then + break + end + end + end + end + end + end + end + if script=="deva" then + sharedfeatures["dv04"]=true + elseif script=="dev2" then + sharedfeatures["dv01"]=true + sharedfeatures["dv02"]=true + sharedfeatures["dv03"]=true + sharedfeatures["dv04"]=true + elseif script=="mlym" then + sharedfeatures["pstf"]=true + elseif script=="mlm2" then + sharedfeatures["pstf"]=true + sharedfeatures["pref"]=true + sharedfeatures["dv03"]=true + gsubfeatures ["dv03"]=dev2_defaults + insert(sequences,insertindex,sequence_reorder_pre_base_reordering_consonants) + end + end + end +end +registerotffeature { + name="devanagari", + description="inject additional features", + default=true, + initializers={ + node=initializedevanagi, + }, +} +local function deva_initialize(font,attr) + local tfmdata=fontdata[font] + local datasets=otf.dataset(tfmdata,font,attr) + local devanagaridata=datasets.devanagari + if not devanagaridata then + devanagaridata={ + reph=false, + vattu=false, + blwfcache={}, + } + datasets.devanagari=devanagaridata + local resources=tfmdata.resources + local devanagari=resources.devanagari + for s=1,#datasets do + local dataset=datasets[s] + if dataset and dataset[1] then + local kind=dataset[4] + if kind=="rphf" then + devanagaridata.reph=true + elseif kind=="blwf" then + devanagaridata.vattu=true + devanagaridata.blwfcache=devanagari.blwfcache + end + end + end + end + return devanagaridata.reph,devanagaridata.vattu,devanagaridata.blwfcache +end +local function deva_reorder(head,start,stop,font,attr,nbspaces) + local reph,vattu,blwfcache=deva_initialize(font,attr) + local current=start + local n=getnext(start) + local base=nil + local firstcons=nil + local lastcons=nil + local basefound=false + if reph and ra[getchar(start)] and halant[getchar(n)] then + if n==stop then + return head,stop,nbspaces + end + if getchar(getnext(n))==c_zwj then + current=start + else + current=getnext(n) + setprop(start,a_state,s_rphf) + end + end + if getchar(current)==c_nbsp then + if current==stop then + stop=getprev(stop) + head=remove_node(head,current) + free_node(current) + return head,stop,nbspaces + else + nbspaces=nbspaces+1 + base=current + firstcons=current + lastcons=current + current=getnext(current) + if current~=stop then + if nukta[getchar(current)] then + current=getnext(current) + end + if getchar(current)==c_zwj then + if current~=stop then + local next=getnext(current) + if next~=stop and halant[getchar(next)] then + current=next + next=getnext(current) + local tmp=next and getnext(next) or nil + local changestop=next==stop + local tempcurrent=copy_node(next) + copyinjection(tempcurrent,next) + local nextcurrent=copy_node(current) + copyinjection(nextcurrent,current) + setlink(tempcurrent,nextcurrent) + setprop(tempcurrent,a_state,s_blwf) + tempcurrent=processcharacters(tempcurrent,font) + setprop(tempcurrent,a_state,unsetvalue) + if getchar(next)==getchar(tempcurrent) then + flush_list(tempcurrent) + local n=copy_node(current) + copyinjection(n,current) + setchar(current,dotted_circle) + head=insert_node_after(head,current,n) + else + setchar(current,getchar(tempcurrent)) + local freenode=getnext(current) + setlink(current,tmp) + free_node(freenode) + flush_list(tempcurrent) + if changestop then + stop=current + end + end + end + end + end + end + end + end + while not basefound do + local char=getchar(current) + if consonant[char] then + setprop(current,a_state,s_half) + if not firstcons then + firstcons=current + end + lastcons=current + if not base then + base=current + elseif blwfcache[char] then + setprop(current,a_state,s_blwf) + else + base=current + end + end + basefound=current==stop + current=getnext(current) + end + if base~=lastcons then + local np=base + local n=getnext(base) + local ch=getchar(n) + if nukta[ch] then + np=n + n=getnext(n) + ch=getchar(n) + end + if halant[ch] then + if lastcons~=stop then + local ln=getnext(lastcons) + if nukta[getchar(ln)] then + lastcons=ln + end + end + local nn=getnext(n) + local ln=getnext(lastcons) + setlink(np,nn) + setnext(lastcons,n) + if ln then + setprev(ln,n) + end + setnext(n,ln) + setprev(n,lastcons) + if lastcons==stop then + stop=n + end + end + end + n=getnext(start) + if n~=stop and ra[getchar(start)] and halant[getchar(n)] and not zw_char[getchar(getnext(n))] then + local matra=base + if base~=stop then + local next=getnext(base) + if dependent_vowel[getchar(next)] then + matra=next + end + end + local sp=getprev(start) + local nn=getnext(n) + local mn=getnext(matra) + setlink(sp,nn) + setlink(matra,start) + setlink(n,mn) + if head==start then + head=nn + end + start=nn + if matra==stop then + stop=n + end + end + local current=start + while current~=stop do + local next=getnext(current) + if next~=stop and halant[getchar(next)] and getchar(getnext(next))==c_zwnj then + setprop(current,a_state,unsetvalue) + end + current=next + end + if base~=stop and getprop(base,a_state) then + local next=getnext(base) + if halant[getchar(next)] and not (next~=stop and getchar(getnext(next))==c_zwj) then + setprop(base,a_state,unsetvalue) + end + end + local current,allreordered,moved=start,false,{ [base]=true } + local a,b,p,bn=base,base,base,getnext(base) + if base~=stop and nukta[getchar(bn)] then + a,b,p=bn,bn,bn + end + while not allreordered do + local c=current + local n=getnext(current) + local l=nil + if c~=stop then + local ch=getchar(n) + if nukta[ch] then + c=n + n=getnext(n) + ch=getchar(n) + end + if c~=stop then + if halant[ch] then + c=n + n=getnext(n) + ch=getchar(n) + end + while c~=stop and dependent_vowel[ch] do + c=n + n=getnext(n) + ch=getchar(n) + end + if c~=stop then + if vowel_modifier[ch] then + c=n + n=getnext(n) + ch=getchar(n) + end + if c~=stop and stress_tone_mark[ch] then + c=n + n=getnext(n) end end - if kind=="pref" then - local sequence=dataset[3] - local steps=sequence.steps - local nofsteps=sequence.nofsteps - for i=1,nofsteps do - local step=steps[i] - local coverage=step.coverage - if coverage then - for k,v in next,halant do - local h=coverage[k] - if h then - local found=false - for k,v in next,h do - found=v and v.ligature - if found then - pre_base_reordering_consonants[k]=found - break - end - end - if found then - break - end - end + end + end + local bp=getprev(firstcons) + local cn=getnext(current) + local last=getnext(c) + while cn~=last do + if pre_mark[getchar(cn)] then + if bp then + setnext(bp,cn) + end + local prev,next=getboth(cn) + if next then + setprev(next,prev) + end + setnext(prev,next) + if cn==stop then + stop=prev + end + setprev(cn,bp) + setlink(cn,firstcons) + if firstcons==start then + if head==start then + head=cn + end + start=cn + end + break + end + cn=getnext(cn) + end + allreordered=c==stop + current=getnext(c) + end + if reph or vattu then + local current,cns=start,nil + while current~=stop do + local c=current + local n=getnext(current) + if ra[getchar(current)] and halant[getchar(n)] then + c=n + n=getnext(n) + local b,bn=base,base + while bn~=stop do + local next=getnext(bn) + if dependent_vowel[getchar(next)] then + b=next + end + bn=next + end + if getprop(current,a_state)==s_rphf then + if b~=current then + if current==start then + if head==start then + head=n end + start=n + end + if b==stop then + stop=c end + local prev=getprev(current) + setlink(prev,n) + local next=getnext(b) + setlink(c,next) + setlink(b,current) + end + elseif cns and getnext(cns)~=current then + local cp=getprev(current) + local cnsn=getnext(cns) + setlink(cp,n) + setlink(cns,current) + setlink(c,cnsn) + if c==stop then + stop=cp + break + end + current=getprev(n) + end + else + local char=getchar(current) + if consonant[char] then + cns=current + local next=getnext(cns) + if halant[getchar(next)] then + cns=next + end + elseif char==c_nbsp then + nbspaces=nbspaces+1 + cns=current + local next=getnext(cns) + if halant[getchar(next)] then + cns=next end end end - if script=="deva" then - sharedfeatures["dv04"]=true - elseif script=="dev2" then - sharedfeatures["dv01"]=true - sharedfeatures["dv02"]=true - sharedfeatures["dv03"]=true - sharedfeatures["dv04"]=true - elseif script=="mlym" then - sharedfeatures["pstf"]=true - elseif script=="mlm2" then - sharedfeatures["pstf"]=true - sharedfeatures["pref"]=true - sharedfeatures["dv03"]=true - gsubfeatures ["dv03"]=dev2_defaults - insert(sequences,insertindex,sequence_reorder_pre_base_reordering_consonants) - end + current=getnext(current) end end + if getchar(base)==c_nbsp then + nbspaces=nbspaces-1 + head=remove_node(head,base) + free_node(base) + end + return head,stop,nbspaces end -registerotffeature { - name="devanagari", - description="inject additional features", - default=true, - initializers={ - node=initializedevanagi, - }, -} -local function deva_initialize(font,attr) - local tfmdata=fontdata[font] - local datasets=otf.dataset(tfmdata,font,attr) - local devanagaridata=datasets.devanagari - if not devanagaridata then - devanagaridata={ - reph=false, - vattu=false, - blwfcache={}, - } - datasets.devanagari=devanagaridata - local resources=tfmdata.resources - local devanagari=resources.devanagari - for s=1,#datasets do - local dataset=datasets[s] - if dataset and dataset[1] then - local kind=dataset[4] - if kind=="rphf" then - devanagaridata.reph=true - elseif kind=="blwf" then - devanagaridata.vattu=true - devanagaridata.blwfcache=devanagari.blwfcache +function handlers.devanagari_reorder_matras(head,start) + local current=start + local startfont=getfont(start) + local startattr=getprop(start,a_syllabe) + while current do + local char=ischar(current,startfont) + local next=getnext(current) + if char and getprop(current,a_syllabe)==startattr then + if halant[char] and not getprop(current,a_state) then + if next then + local char=ischar(next,startfont) + if char and zw_char[char] and getprop(next,a_syllabe)==startattr then + current=next + next=getnext(current) + end end + local startnext=getnext(start) + head=remove_node(head,start) + setlink(start,next) + setlink(current,start) + start=startnext + break end end + current=next end - return devanagaridata.reph,devanagaridata.vattu,devanagaridata.blwfcache + return head,start,true end -local function deva_reorder(head,start,stop,font,attr,nbspaces) - local reph,vattu,blwfcache=deva_initialize(font,attr) - local current=start - local n=getnext(start) - local base=nil - local firstcons=nil - local lastcons=nil - local basefound=false - if reph and ra[getchar(start)] and halant[getchar(n)] then - if n==stop then - return head,stop,nbspaces - end - if getchar(getnext(n))==c_zwj then - current=start +function handlers.devanagari_reorder_reph(head,start) + local current=getnext(start) + local startnext=nil + local startprev=nil + local startfont=getfont(start) + local startattr=getprop(start,a_syllabe) + while current do + local char=ischar(current,font) + if char and getprop(current,a_syllabe)==startattr then + if halant[char] and not getprop(current,a_state) then + local next=getnext(current) + if next then + local nextchar=ischar(next,font) + if nextchar and zw_char[nextchar] and getprop(next,a_syllabe)==startattr then + current=next + next=getnext(current) + end + end + startnext=getnext(start) + head=remove_node(head,start) + setlink(start,next) + setlink(current,start) + start=startnext + startattr=getprop(start,a_syllabe) + break + end + current=getnext(current) else - current=getnext(n) - setprop(start,a_state,s_rphf) + break end end - if getchar(current)==c_nbsp then - if current==stop then - stop=getprev(stop) - head=remove_node(head,current) - free_node(current) - return head,stop,nbspaces - else - nbspaces=nbspaces+1 - base=current - firstcons=current - lastcons=current - current=getnext(current) - if current~=stop then - if nukta[getchar(current)] then - current=getnext(current) + if not startnext then + current=getnext(start) + while current do + local char=ischar(current,font) + if char and getprop(current,a_syllabe)==startattr then + if getprop(current,a_state)==s_pstf then + startnext=getnext(start) + head=remove_node(head,start) + local prev=getprev(current) + setlink(prev,start) + setlink(start,current) + start=startnext + startattr=getprop(start,a_syllabe) + break end - if getchar(current)==c_zwj then - if current~=stop then - local next=getnext(current) - if next~=stop and halant[getchar(next)] then - current=next - next=getnext(current) - local tmp=next and getnext(next) or nil - local changestop=next==stop - local tempcurrent=copy_node(next) - copyinjection(tempcurrent,next) - local nextcurrent=copy_node(current) - copyinjection(nextcurrent,current) - setlink(tempcurrent,nextcurrent) - setprop(tempcurrent,a_state,s_blwf) - tempcurrent=processcharacters(tempcurrent,font) - setprop(tempcurrent,a_state,unsetvalue) - if getchar(next)==getchar(tempcurrent) then - flush_list(tempcurrent) - local n=copy_node(current) - copyinjection(n,current) - setchar(current,dotted_circle) - head=insert_node_after(head,current,n) - else - setchar(current,getchar(tempcurrent)) - local freenode=getnext(current) - setlink(current,tmp) - free_node(freenode) - flush_list(tempcurrent) - if changestop then - stop=current - end - end + current=getnext(current) + else + break + end + end + end + if not startnext then + current=getnext(start) + local c=nil + while current do + local char=ischar(current,font) + if char and getprop(current,a_syllabe)==startattr then + if not c and mark_above_below_post[char] and reorder_class[char]~="after subscript" then + c=current + end + current=getnext(current) + else + break + end + end + if c then + startnext=getnext(start) + head=remove_node(head,start) + local prev=getprev(c) + setlink(prev,start) + setlink(start,c) + start=startnext + startattr=getprop(start,a_syllabe) + end + end + if not startnext then + current=start + local next=getnext(current) + while next do + local nextchar=ischar(next,font) + if nextchar and getprop(next,a_syllabe)==startattr then + current=next + next=getnext(current) + else + break + end + end + if start~=current then + startnext=getnext(start) + head=remove_node(head,start) + local next=getnext(current) + setlink(start,next) + setlink(current,"next",start) + start=startnext + end + end + return head,start,true +end +function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start) + local current=start + local startnext=nil + local startprev=nil + local startfont=getfont(start) + local startattr=getprop(start,a_syllabe) + while current do + local char=ischar(current,font) + if char and getprop(current,a_syllabe)==startattr then + local next=getnext(current) + if halant[char] and not getprop(current,a_state) then + if next then + local nextchar=ischar(next,font) + if nextchar and getprop(next,a_syllabe)==startattr then + if nextchar==c_zwnj or nextchar==c_zwj then + current=next + next=getnext(current) end end end + startnext=getnext(start) + removenode(start,start) + setlink(start,next) + setlink(current,start) + start=startnext + break end + current=next + else + break end end - while not basefound do - local char=getchar(current) - if consonant[char] then - setprop(current,a_state,s_half) - if not firstcons then - firstcons=current - end - lastcons=current - if not base then - base=current - elseif blwfcache[char] then - setprop(current,a_state,s_blwf) - else - base=current - end - end - basefound=current==stop - current=getnext(current) - end - if base~=lastcons then - local np=base - local n=getnext(base) - local ch=getchar(n) - if nukta[ch] then - np=n - n=getnext(n) - ch=getchar(n) - end - if halant[ch] then - if lastcons~=stop then - local ln=getnext(lastcons) - if nukta[getchar(ln)] then - lastcons=ln + if not startnext then + current=getnext(start) + startattr=getprop(start,a_syllabe) + while current do + local char=ischar(current,font) + if char and getprop(current,a_syllabe)==startattr then + if not consonant[char] and getprop(current,a_state) then + startnext=getnext(start) + removenode(start,start) + local prev=getprev(current) + setlink(start,prev) + setlink(start,current) + start=startnext + break end - end - local nn=getnext(n) - local ln=getnext(lastcons) - setlink(np,nn) - setnext(lastcons,n) - if ln then - setprev(ln,n) - end - setnext(n,ln) - setprev(n,lastcons) - if lastcons==stop then - stop=n + current=getnext(current) + else + break end end end - n=getnext(start) - if n~=stop and ra[getchar(start)] and halant[getchar(n)] and not zw_char[getchar(getnext(n))] then - local matra=base - if base~=stop then - local next=getnext(base) - if dependent_vowel[getchar(next)] then - matra=next - end - end - local sp=getprev(start) - local nn=getnext(n) - local mn=getnext(matra) - setlink(sp,nn) - setlink(matra,start) - setlink(n,mn) - if head==start then - head=nn - end - start=nn - if matra==stop then - stop=n + return head,start,true +end +function handlers.devanagari_remove_joiners(head,start,kind,lookupname,replacement) + local stop=getnext(start) + local font=getfont(start) + local last=start + while stop do + local char=ischar(stop,font) + if char and (char==c_zwnj or char==c_zwj) then + last=stop + stop=getnext(stop) + else + break end end - local current=start - while current~=stop do - local next=getnext(current) - if next~=stop and halant[getchar(next)] and getchar(getnext(next))==c_zwnj then - setprop(current,a_state,unsetvalue) - end - current=next + local prev=getprev(start) + if stop then + setnext(last) + setlink(prev,stop) + elseif prev then + setnext(prev) end - if base~=stop and getprop(base,a_state) then - local next=getnext(base) - if halant[getchar(next)] and not (next~=stop and getchar(getnext(next))==c_zwj) then - setprop(base,a_state,unsetvalue) - end + if head==start then + head=stop end - local current,allreordered,moved=start,false,{ [base]=true } - local a,b,p,bn=base,base,base,getnext(base) - if base~=stop and nukta[getchar(bn)] then - a,b,p=bn,bn,bn + flush_list(start) + return head,stop,true +end +local function dev2_initialize(font,attr) + local devanagari=fontdata[font].resources.devanagari + if devanagari then + return devanagari.seqsubset or {},devanagari.reorderreph or {} + else + return {},{} end - while not allreordered do - local c=current - local n=getnext(current) - local l=nil - if c~=stop then - local ch=getchar(n) - if nukta[ch] then - c=n - n=getnext(n) - ch=getchar(n) - end - if c~=stop then - if halant[ch] then - c=n - n=getnext(n) - ch=getchar(n) +end +local function dev2_reorder(head,start,stop,font,attr,nbspaces) + local seqsubset,reorderreph=dev2_initialize(font,attr) + local reph=false + local halfpos=nil + local basepos=nil + local subpos=nil + local postpos=nil + local locl={} + for i=1,#seqsubset do + local subset=seqsubset[i] + local kind=subset[1] + local lookupcache=subset[2] + if kind=="rphf" then + for k,v in next,ra do + local r=lookupcache[k] + if r then + for k,v in next,halant do + local h=r[k] + if h then + reph=h.ligature or false + break + end + end + if reph then + break + end end - while c~=stop and dependent_vowel[ch] do - c=n - n=getnext(n) - ch=getchar(n) + end + local current=start + local last=getnext(stop) + while current~=last do + if current~=stop then + local c=locl[current] or getchar(current) + local found=lookupcache[c] + if found then + local next=getnext(current) + local n=locl[next] or getchar(next) + if found[n] then + local afternext=next~=stop and getnext(next) + if afternext and zw_char[getchar(afternext)] then + current=next + current=getnext(current) + elseif current==start then + setprop(current,a_state,s_rphf) + current=next + else + current=next + end + end + end end - if c~=stop then - if vowel_modifier[ch] then - c=n - n=getnext(n) - ch=getchar(n) + current=getnext(current) + end + elseif kind=="pref" then + local current=start + local last=getnext(stop) + while current~=last do + if current~=stop then + local c=locl[current] or getchar(current) + local found=lookupcache[c] + if found then + local next=getnext(current) + local n=locl[next] or getchar(next) + if found[n] then + setprop(current,a_state,s_pref) + setprop(next,a_state,s_pref) + current=next + end end - if c~=stop and stress_tone_mark[ch] then - c=n - n=getnext(n) + end + current=getnext(current) + end + elseif kind=="half" then + local current=start + local last=getnext(stop) + while current~=last do + if current~=stop then + local c=locl[current] or getchar(current) + local found=lookupcache[c] + if found then + local next=getnext(current) + local n=locl[next] or getchar(next) + if found[n] then + if next~=stop and getchar(getnext(next))==c_zwnj then + current=next + else + setprop(current,a_state,s_half) + if not halfpos then + halfpos=current + end + end + current=getnext(current) + end end end + current=getnext(current) end - end - local bp=getprev(firstcons) - local cn=getnext(current) - local last=getnext(c) - while cn~=last do - if pre_mark[getchar(cn)] then - if bp then - setnext(bp,cn) - end - local prev,next=getboth(cn) - if next then - setprev(next,prev) - end - setnext(prev,next) - if cn==stop then - stop=prev + elseif kind=="blwf" then + local current=start + local last=getnext(stop) + while current~=last do + if current~=stop then + local c=locl[current] or getchar(current) + local found=lookupcache[c] + if found then + local next=getnext(current) + local n=locl[next] or getchar(next) + if found[n] then + setprop(current,a_state,s_blwf) + setprop(next,a_state,s_blwf) + current=next + subpos=current + end + end end - setprev(cn,bp) - setlink(cn,firstcons) - if firstcons==start then - if head==start then - head=cn + current=getnext(current) + end + elseif kind=="pstf" then + local current=start + local last=getnext(stop) + while current~=last do + if current~=stop then + local c=locl[current] or getchar(current) + local found=lookupcache[c] + if found then + local next=getnext(current) + local n=locl[next] or getchar(next) + if found[n] then + setprop(current,a_state,s_pstf) + setprop(next,a_state,s_pstf) + current=next + postpos=current + end end - start=cn end - break + current=getnext(current) end - cn=getnext(cn) end - allreordered=c==stop - current=getnext(c) end - if reph or vattu then - local current,cns=start,nil - while current~=stop do - local c=current - local n=getnext(current) - if ra[getchar(current)] and halant[getchar(n)] then - c=n - n=getnext(n) - local b,bn=base,base - while bn~=stop do - local next=getnext(bn) - if dependent_vowel[getchar(next)] then - b=next - end - bn=next + reorderreph.coverage={ [reph]=true } + local current,base,firstcons=start,nil,nil + if getprop(start,a_state)==s_rphf then + current=getnext(getnext(start)) + end + if current~=getnext(stop) and getchar(current)==c_nbsp then + if current==stop then + stop=getprev(stop) + head=remove_node(head,current) + free_node(current) + return head,stop,nbspaces + else + nbspaces=nbspaces+1 + base=current + current=getnext(current) + if current~=stop then + local char=getchar(current) + if nukta[char] then + current=getnext(current) + char=getchar(current) end - if getprop(current,a_state)==s_rphf then - if b~=current then - if current==start then - if head==start then - head=n + if char==c_zwj then + local next=getnext(current) + if current~=stop and next~=stop and halant[getchar(next)] then + current=next + next=getnext(current) + local tmp=getnext(next) + local changestop=next==stop + setnext(next,nil) + setprop(current,a_state,s_pref) + current=processcharacters(current,font) + setprop(current,a_state,s_blwf) + current=processcharacters(current,font) + setprop(current,a_state,s_pstf) + current=processcharacters(current,font) + setprop(current,a_state,unsetvalue) + if halant[getchar(current)] then + setnext(getnext(current),tmp) + local nc=copy_node(current) + copyinjection(nc,current) + setchar(current,dotted_circle) + head=insert_node_after(head,current,nc) + else + setnext(current,tmp) + if changestop then + stop=current end - start=n - end - if b==stop then - stop=c end - local prev=getprev(current) - setlink(prev,n) - local next=getnext(b) - setlink(c,next) - setlink(b,current) - end - elseif cns and getnext(cns)~=current then - local cp=getprev(current) - local cnsn=getnext(cns) - setlink(cp,n) - setlink(cns,current) - setlink(c,cnsn) - if c==stop then - stop=cp - break end - current=getprev(n) end - else - local char=getchar(current) - if consonant[char] then - cns=current - local next=getnext(cns) - if halant[getchar(next)] then - cns=next + end + end + else + local last=getnext(stop) + while current~=last do + local next=getnext(current) + if consonant[getchar(current)] then + if not (current~=stop and next~=stop and halant[getchar(next)] and getchar(getnext(next))==c_zwj) then + if not firstcons then + firstcons=current end - elseif char==c_nbsp then - nbspaces=nbspaces+1 - cns=current - local next=getnext(cns) - if halant[getchar(next)] then - cns=next + local a=getprop(current,a_state) + if not (a==s_pref or a==s_blwf or a==s_pstf) then + base=current end end end - current=getnext(current) + current=next + end + if not base then + base=firstcons end end - if getchar(base)==c_nbsp then - nbspaces=nbspaces-1 - head=remove_node(head,base) - free_node(base) + if not base then + if getprop(start,a_state)==s_rphf then + setprop(start,a_state,unsetvalue) + end + return head,stop,nbspaces + else + if getprop(base,a_state) then + setprop(base,a_state,unsetvalue) + end + basepos=base end - return head,stop,nbspaces -end -function handlers.devanagari_reorder_matras(head,start) - local current=start - local startfont=getfont(start) - local startattr=getprop(start,a_syllabe) - while current do - local char=ischar(current,startfont) - local next=getnext(current) - if char and getprop(current,a_syllabe)==startattr then - if halant[char] and not getprop(current,a_state) then - if next then - local char=ischar(next,startfont) - if char and zw_char[char] and getprop(next,a_syllabe)==startattr then - current=next - next=getnext(current) + if not halfpos then + halfpos=base + end + if not subpos then + subpos=base + end + if not postpos then + postpos=subpos or base + end + local moved={} + local current=start + local last=getnext(stop) + while current~=last do + local char,target,cn=locl[current] or getchar(current),nil,getnext(current) + local tpm=twopart_mark[char] + if tpm then + local extra=copy_node(current) + copyinjection(extra,current) + char=tpm[1] + setchar(current,char) + setchar(extra,tpm[2]) + head=insert_node_after(head,current,extra) + end + if not moved[current] and dependent_vowel[char] then + if pre_mark[char] then + moved[current]=true + local prev,next=getboth(current) + setlink(prev,next) + if current==stop then + stop=getprev(current) + end + if halfpos==start then + if head==start then + head=current end + start=current end - local startnext=getnext(start) - head=remove_node(head,start) - setlink(start,next) - setlink(current,start) - start=startnext - break + local prev=getprev(halfpos) + setlink(prev,current) + setlink(current,halfpos) + halfpos=current + elseif above_mark[char] then + target=basepos + if subpos==basepos then + subpos=current + end + if postpos==basepos then + postpos=current + end + basepos=current + elseif below_mark[char] then + target=subpos + if postpos==subpos then + postpos=current + end + subpos=current + elseif post_mark[char] then + target=postpos + postpos=current end - end - current=next - end - return head,start,true -end -function handlers.devanagari_reorder_reph(head,start) - local current=getnext(start) - local startnext=nil - local startprev=nil - local startfont=getfont(start) - local startattr=getprop(start,a_syllabe) - while current do - local char=ischar(current,font) - if char and getprop(current,a_syllabe)==startattr then - if halant[char] and not getprop(current,a_state) then - local next=getnext(current) - if next then - local nextchar=ischar(next,font) - if nextchar and zw_char[nextchar] and getprop(next,a_syllabe)==startattr then - current=next - next=getnext(current) + if mark_above_below_post[char] then + local prev=getprev(current) + if prev~=target then + local next=getnext(current) + setlink(next,prev) + if current==stop then + stop=prev end + local next=getnext(target) + setlink(current,next) + setlink(target,current) end - startnext=getnext(start) - head=remove_node(head,start) - setlink(start,next) - setlink(current,start) - start=startnext - startattr=getprop(start,a_syllabe) - break end - current=getnext(current) - else - break end + current=cn end - if not startnext then - current=getnext(start) - while current do - local char=ischar(current,font) - if char and getprop(current,a_syllabe)==startattr then - if getprop(current,a_state)==s_pstf then - startnext=getnext(start) - head=remove_node(head,start) - local prev=getprev(current) - setlink(prev,start) - setlink(start,current) - start=startnext - startattr=getprop(start,a_syllabe) - break - end - current=getnext(current) - else - break + local current,c=start,nil + while current~=stop do + local char=getchar(current) + if halant[char] or stress_tone_mark[char] then + if not c then + c=current end + else + c=nil end - end - if not startnext then - current=getnext(start) - local c=nil - while current do - local char=ischar(current,font) - if char and getprop(current,a_syllabe)==startattr then - if not c and mark_above_below_post[char] and reorder_class[char]~="after subscript" then - c=current - end - current=getnext(current) - else - break + local next=getnext(current) + if c and nukta[getchar(next)] then + if head==c then + head=next + end + if stop==next then + stop=current end - end - if c then - startnext=getnext(start) - head=remove_node(head,start) local prev=getprev(c) - setlink(prev,start) - setlink(start,c) - start=startnext - startattr=getprop(start,a_syllabe) - end - end - if not startnext then - current=start - local next=getnext(current) - while next do - local nextchar=ischar(next,font) - if nextchar and getprop(next,a_syllabe)==startattr then - current=next - next=getnext(current) - else - break + setlink(next,prev) + local nextnext=getnext(next) + setnext(current,nextnext) + local nextnextnext=getnext(nextnext) + if nextnextnext then + setprev(nextnextnext,current) end + setlink(nextnext,c) end - if start~=current then - startnext=getnext(start) - head=remove_node(head,start) - local next=getnext(current) - setlink(start,next) - setlink(current,"next",start) - start=startnext - end + if stop==current then break end + current=getnext(current) end - return head,start,true + if getchar(base)==c_nbsp then + nbspaces=nbspaces-1 + head=remove_node(head,base) + free_node(base) + end + return head,stop,nbspaces end -function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start) - local current=start - local startnext=nil - local startprev=nil - local startfont=getfont(start) - local startattr=getprop(start,a_syllabe) - while current do - local char=ischar(current,font) - if char and getprop(current,a_syllabe)==startattr then - local next=getnext(current) - if halant[char] and not getprop(current,a_state) then - if next then - local nextchar=ischar(next,font) - if nextchar and getprop(next,a_syllabe)==startattr then - if nextchar==c_zwnj or nextchar==c_zwj then - current=next - next=getnext(current) +local separator={} +imerge(separator,consonant) +imerge(separator,independent_vowel) +imerge(separator,dependent_vowel) +imerge(separator,vowel_modifier) +imerge(separator,stress_tone_mark) +for k,v in next,nukta do separator[k]=true end +for k,v in next,halant do separator[k]=true end +local function analyze_next_chars_one(c,font,variant) + local n=getnext(c) + if not n then + return c + end + if variant==1 then + local v=ischar(n,font) + if v and nukta[v] then + n=getnext(n) + if n then + v=ischar(n,font) + end + end + if n and v then + local nn=getnext(n) + if nn then + local vv=ischar(nn,font) + if vv then + local nnn=getnext(nn) + if nnn then + local vvv=ischar(nnn,font) + if vvv then + if vv==c_zwj and consonant[vvv] then + c=nnn + elseif (vv==c_zwnj or vv==c_zwj) and halant[vvv] then + local nnnn=getnext(nnn) + if nnnn then + local vvvv=ischar(nnnn) + if vvvv and consonant[vvvv] then + c=nnnn + end + end + end end end end - startnext=getnext(start) - removenode(start,start) - setlink(start,next) - setlink(current,start) - start=startnext - break end - current=next - else - break end - end - if not startnext then - current=getnext(start) - startattr=getprop(start,a_syllabe) - while current do - local char=ischar(current,font) - if char and getprop(current,a_syllabe)==startattr then - if not consonant[char] and getprop(current,a_state) then - startnext=getnext(start) - removenode(start,start) - local prev=getprev(current) - setlink(start,prev) - setlink(start,current) - start=startnext - break + elseif variant==2 then + local v=ischar(n,font) + if v and nukta[v] then + c=n + end + n=getnext(c) + if n then + v=ischar(n,font) + if v then + local nn=getnext(n) + if nn then + local vv=ischar(nn,font) + if vv and zw_char[vv] then + n=nn + v=vv + nn=getnext(nn) + vv=nn and ischar(nn,font) + end + if vv and halant[v] and consonant[vv] then + c=nn + end end - current=getnext(current) - else - break end end end - return head,start,true -end -function handlers.devanagari_remove_joiners(head,start,kind,lookupname,replacement) - local stop=getnext(start) - local font=getfont(start) - local last=start - while stop do - local char=ischar(stop,font) - if char and (char==c_zwnj or char==c_zwj) then - last=stop - stop=getnext(stop) - else - break + local n=getnext(c) + if not n then + return c + end + local v=ischar(n,font) + if not v then + return c + end + if dependent_vowel[v] then + c=getnext(c) + n=getnext(c) + if not n then + return c + end + v=ischar(n,font) + if not v then + return c end end - local prev=getprev(start) - if stop then - setnext(last) - setlink(prev,stop) - elseif prev then - setnext(prev) + if nukta[v] then + c=getnext(c) + n=getnext(c) + if not n then + return c + end + v=ischar(n,font) + if not v then + return c + end end - if head==start then - head=stop + if halant[v] then + c=getnext(c) + n=getnext(c) + if not n then + return c + end + v=ischar(n,font) + if not v then + return c + end end - flush_list(start) - return head,stop,true -end -local function dev2_initialize(font,attr) - local devanagari=fontdata[font].resources.devanagari - if devanagari then - return devanagari.seqsubset or {},devanagari.reorderreph or {} + if vowel_modifier[v] then + c=getnext(c) + n=getnext(c) + if not n then + return c + end + v=ischar(n,font) + if not v then + return c + end + end + if stress_tone_mark[v] then + c=getnext(c) + n=getnext(c) + if not n then + return c + end + v=ischar(n,font) + if not v then + return c + end + end + if stress_tone_mark[v] then + return n else - return {},{} + return c end end -local function dev2_reorder(head,start,stop,font,attr,nbspaces) - local seqsubset,reorderreph=dev2_initialize(font,attr) - local reph=false - local halfpos=nil - local basepos=nil - local subpos=nil - local postpos=nil - local locl={} - for i=1,#seqsubset do - local subset=seqsubset[i] - local kind=subset[1] - local lookupcache=subset[2] - if kind=="rphf" then - for k,v in next,ra do - local r=lookupcache[k] - if r then - for k,v in next,halant do - local h=r[k] - if h then - reph=h.ligature or false - break - end - end - if reph then - break - end - end - end - local current=start - local last=getnext(stop) - while current~=last do - if current~=stop then - local c=locl[current] or getchar(current) - local found=lookupcache[c] - if found then - local next=getnext(current) - local n=locl[next] or getchar(next) - if found[n] then - local afternext=next~=stop and getnext(next) - if afternext and zw_char[getchar(afternext)] then - current=next - current=getnext(current) - elseif current==start then - setprop(current,a_state,s_rphf) - current=next - else - current=next - end - end - end - end - current=getnext(current) - end - elseif kind=="pref" then - local current=start - local last=getnext(stop) - while current~=last do - if current~=stop then - local c=locl[current] or getchar(current) - local found=lookupcache[c] - if found then - local next=getnext(current) - local n=locl[next] or getchar(next) - if found[n] then - setprop(current,a_state,s_pref) - setprop(next,a_state,s_pref) - current=next - end - end - end - current=getnext(current) - end - elseif kind=="half" then - local current=start - local last=getnext(stop) - while current~=last do - if current~=stop then - local c=locl[current] or getchar(current) - local found=lookupcache[c] - if found then - local next=getnext(current) - local n=locl[next] or getchar(next) - if found[n] then - if next~=stop and getchar(getnext(next))==c_zwnj then - current=next - else - setprop(current,a_state,s_half) - if not halfpos then - halfpos=current - end - end - current=getnext(current) - end - end - end - current=getnext(current) - end - elseif kind=="blwf" then - local current=start - local last=getnext(stop) - while current~=last do - if current~=stop then - local c=locl[current] or getchar(current) - local found=lookupcache[c] - if found then - local next=getnext(current) - local n=locl[next] or getchar(next) - if found[n] then - setprop(current,a_state,s_blwf) - setprop(next,a_state,s_blwf) - current=next - subpos=current +local function analyze_next_chars_two(c,font) + local n=getnext(c) + if not n then + return c + end + local v=ischar(n,font) + if v and nukta[v] then + c=n + end + n=c + while true do + local nn=getnext(n) + if nn then + local vv=ischar(nn,font) + if vv then + if halant[vv] then + n=nn + local nnn=getnext(nn) + if nnn then + local vvv=ischar(nnn,font) + if vvv and zw_char[vvv] then + n=nnn end end - end - current=getnext(current) - end - elseif kind=="pstf" then - local current=start - local last=getnext(stop) - while current~=last do - if current~=stop then - local c=locl[current] or getchar(current) - local found=lookupcache[c] - if found then - local next=getnext(current) - local n=locl[next] or getchar(next) - if found[n] then - setprop(current,a_state,s_pstf) - setprop(next,a_state,s_pstf) - current=next - postpos=current + elseif vv==c_zwnj or vv==c_zwj then + local nnn=getnext(nn) + if nnn then + local vvv=ischar(nnn,font) + if vvv and halant[vvv] then + n=nnn end end + else + break end - current=getnext(current) - end - end - end - reorderreph.coverage={ [reph]=true } - local current,base,firstcons=start,nil,nil - if getprop(start,a_state)==s_rphf then - current=getnext(getnext(start)) - end - if current~=getnext(stop) and getchar(current)==c_nbsp then - if current==stop then - stop=getprev(stop) - head=remove_node(head,current) - free_node(current) - return head,stop,nbspaces - else - nbspaces=nbspaces+1 - base=current - current=getnext(current) - if current~=stop then - local char=getchar(current) - if nukta[char] then - current=getnext(current) - char=getchar(current) - end - if char==c_zwj then - local next=getnext(current) - if current~=stop and next~=stop and halant[getchar(next)] then - current=next - next=getnext(current) - local tmp=getnext(next) - local changestop=next==stop - setnext(next,nil) - setprop(current,a_state,s_pref) - current=processcharacters(current,font) - setprop(current,a_state,s_blwf) - current=processcharacters(current,font) - setprop(current,a_state,s_pstf) - current=processcharacters(current,font) - setprop(current,a_state,unsetvalue) - if halant[getchar(current)] then - setnext(getnext(current),tmp) - local nc=copy_node(current) - copyinjection(nc,current) - setchar(current,dotted_circle) - head=insert_node_after(head,current,nc) - else - setnext(current,tmp) - if changestop then - stop=current + local nn=getnext(n) + if nn then + local vv=ischar(nn,font) + if vv and consonant[vv] then + n=nn + local nnn=getnext(nn) + if nnn then + local vvv=ischar(nnn,font) + if vvv and nukta[vvv] then + n=nnn end end + c=n + else + break end + else + break end + else + break end - end - else - local last=getnext(stop) - while current~=last do - local next=getnext(current) - if consonant[getchar(current)] then - if not (current~=stop and next~=stop and halant[getchar(next)] and getchar(getnext(next))==c_zwj) then - if not firstcons then - firstcons=current - end - local a=getprop(current,a_state) - if not (a==s_pref or a==s_blwf or a==s_pstf) then - base=current - end - end - end - current=next - end - if not base then - base=firstcons + else + break end end - if not base then - if getprop(start,a_state)==s_rphf then - setprop(start,a_state,unsetvalue) - end - return head,stop,nbspaces - else - if getprop(base,a_state) then - setprop(base,a_state,unsetvalue) - end - basepos=base + if not c then + return end - if not halfpos then - halfpos=base + local n=getnext(c) + if not n then + return c end - if not subpos then - subpos=base + local v=ischar(n,font) + if not v then + return c end - if not postpos then - postpos=subpos or base + if v==c_anudatta then + c=n + n=getnext(c) + if not n then + return c + end + v=ischar(n,font) + if not v then + return c + end end - local moved={} - local current=start - local last=getnext(stop) - while current~=last do - local char,target,cn=locl[current] or getchar(current),nil,getnext(current) - local tpm=twopart_mark[char] - if tpm then - local extra=copy_node(current) - copyinjection(extra,current) - char=tpm[1] - setchar(current,char) - setchar(extra,tpm[2]) - head=insert_node_after(head,current,extra) + if halant[v] then + c=n + n=getnext(c) + if not n then + return c end - if not moved[current] and dependent_vowel[char] then - if pre_mark[char] then - moved[current]=true - local prev,next=getboth(current) - setlink(prev,next) - if current==stop then - stop=getprev(current) - end - if halfpos==start then - if head==start then - head=current - end - start=current - end - local prev=getprev(halfpos) - setlink(prev,current) - setlink(current,halfpos) - halfpos=current - elseif above_mark[char] then - target=basepos - if subpos==basepos then - subpos=current - end - if postpos==basepos then - postpos=current - end - basepos=current - elseif below_mark[char] then - target=subpos - if postpos==subpos then - postpos=current - end - subpos=current - elseif post_mark[char] then - target=postpos - postpos=current + v=ischar(n,font) + if not v then + return c + end + if v==c_zwnj or v==c_zwj then + c=n + n=getnext(c) + if not n then + return c end - if mark_above_below_post[char] then - local prev=getprev(current) - if prev~=target then - local next=getnext(current) - setlink(next,prev) - if current==stop then - stop=prev - end - local next=getnext(target) - setlink(current,next) - setlink(target,current) - end + v=ischar(n,font) + if not v then + return c end end - current=cn - end - local current,c=start,nil - while current~=stop do - local char=getchar(current) - if halant[char] or stress_tone_mark[char] then - if not c then - c=current + else + if dependent_vowel[v] then + c=n + n=getnext(c) + if not n then + return c + end + v=ischar(n,font) + if not v then + return c end - else - c=nil end - local next=getnext(current) - if c and nukta[getchar(next)] then - if head==c then - head=next + if nukta[v] then + c=n + n=getnext(c) + if not n then + return c end - if stop==next then - stop=current + v=ischar(n,font) + if not v then + return c end - local prev=getprev(c) - setlink(next,prev) - local nextnext=getnext(next) - setnext(current,nextnext) - local nextnextnext=getnext(nextnext) - if nextnextnext then - setprev(nextnextnext,current) + end + if halant[v] then + c=n + n=getnext(c) + if not n then + return c + end + v=ischar(n,font) + if not v then + return c end - setlink(nextnext,c) end - if stop==current then break end - current=getnext(current) end - if getchar(base)==c_nbsp then - nbspaces=nbspaces-1 - head=remove_node(head,base) - free_node(base) + if vowel_modifier[v] then + c=n + n=getnext(c) + if not n then + return c + end + v=ischar(n,font) + if not v then + return c + end end - return head,stop,nbspaces -end -local separator={} -imerge(separator,consonant) -imerge(separator,independent_vowel) -imerge(separator,dependent_vowel) -imerge(separator,vowel_modifier) -imerge(separator,stress_tone_mark) -for k,v in next,nukta do separator[k]=true end -for k,v in next,halant do separator[k]=true end -local function analyze_next_chars_one(c,font,variant) - local n=getnext(c) - if not n then + if stress_tone_mark[v] then + c=n + n=getnext(c) + if not n then + return c + end + v=ischar(n,font) + if not v then + return c + end + end + if stress_tone_mark[v] then + return n + else return c end - if variant==1 then - local v=ischar(n,font) - if v and nukta[v] then - n=getnext(n) - if n then - v=ischar(n,font) +end +local function inject_syntax_error(head,current,mark) + local signal=copy_node(current) + copyinjection(signal,current) + if mark==pre_mark then + setchar(signal,dotted_circle) + else + setchar(current,dotted_circle) + end + return insert_node_after(head,current,signal) +end +function methods.deva(head,font,attr) + head=tonut(head) + local current=head + local start=true + local done=false + local nbspaces=0 + while current do + local char=ischar(current,font) + if char then + done=true + local syllablestart=current + local syllableend=nil + local c=current + local n=getnext(c) + local first=char + if n and ra[first] then + local second=ischar(n,font) + if second and halant[second] then + local n=getnext(n) + if n then + local third=ischar(n,font) + if third then + c=n + first=third + end + end + end end - end - if n and v then - local nn=getnext(n) - if nn then - local vv=ischar(nn,font) - if vv then - local nnn=getnext(nn) - if nnn then - local vvv=ischar(nnn,font) - if vvv then - if vv==c_zwj and consonant[vvv] then - c=nnn - elseif (vv==c_zwnj or vv==c_zwj) and halant[vvv] then - local nnnn=getnext(nnn) - if nnnn then - local vvvv=ischar(nnnn) - if vvvv and consonant[vvvv] then - c=nnnn - end + local standalone=first==c_nbsp + if standalone then + local prev=getprev(current) + if prev then + local prevchar=ischar(prev,font) + if not prevchar then + elseif not separator[prevchar] then + else + standalone=false + end + else + end + end + if standalone then + local syllableend=analyze_next_chars_one(c,font,2) + current=getnext(syllableend) + if syllablestart~=syllableend then + head,current,nbspaces=deva_reorder(head,syllablestart,syllableend,font,attr,nbspaces) + current=getnext(current) + end + else + if consonant[char] then + local prevc=true + while prevc do + prevc=false + local n=getnext(current) + if not n then + break + end + local v=ischar(n,font) + if not v then + break + end + if nukta[v] then + n=getnext(n) + if not n then + break + end + v=ischar(n,font) + if not v then + break + end + end + if halant[v] then + n=getnext(n) + if not n then + break + end + v=ischar(n,font) + if not v then + break + end + if v==c_zwnj or v==c_zwj then + n=getnext(n) + if not n then + break + end + v=ischar(n,font) + if not v then + break end end + if consonant[v] then + prevc=true + current=n + end end end - end - end - end - elseif variant==2 then - local v=ischar(n,font) - if v and nukta[v] then - c=n - end - n=getnext(c) - if n then - v=ischar(n,font) - if v then - local nn=getnext(n) - if nn then - local vv=ischar(nn,font) - if vv and zw_char[vv] then - n=nn - v=vv - nn=getnext(nn) - vv=nn and ischar(nn,font) + local n=getnext(current) + if n then + local v=ischar(n,font) + if v and nukta[v] then + current=n + n=getnext(current) + end + end + syllableend=current + current=n + if current then + local v=ischar(current,font) + if not v then + elseif halant[v] then + local n=getnext(current) + if n then + local v=ischar(n,font) + if v and zw_char[v] then + syllableend=n + current=getnext(n) + else + syllableend=current + current=n + end + else + syllableend=current + current=n + end + else + if dependent_vowel[v] then + syllableend=current + current=getnext(current) + v=ischar(current,font) + end + if v and vowel_modifier[v] then + syllableend=current + current=getnext(current) + v=ischar(current,font) + end + if v and stress_tone_mark[v] then + syllableend=current + current=getnext(current) + end + end + end + if syllablestart~=syllableend then + head,current,nbspaces=deva_reorder(head,syllablestart,syllableend,font,attr,nbspaces) + current=getnext(current) + end + elseif independent_vowel[char] then + syllableend=current + current=getnext(current) + if current then + local v=ischar(current,font) + if v then + if vowel_modifier[v] then + syllableend=current + current=getnext(current) + v=ischar(current,font) + end + if v and stress_tone_mark[v] then + syllableend=current + current=getnext(current) + end + end end - if vv and halant[v] and consonant[vv] then - c=nn + else + local mark=mark_four[char] + if mark then + head,current=inject_syntax_error(head,current,mark) end + current=getnext(current) end end + else + current=getnext(current) end + start=false end - local n=getnext(c) - if not n then - return c - end - local v=ischar(n,font) - if not v then - return c - end - if dependent_vowel[v] then - c=getnext(c) - n=getnext(c) - if not n then - return c - end - v=ischar(n,font) - if not v then - return c - end - end - if nukta[v] then - c=getnext(c) - n=getnext(c) - if not n then - return c - end - v=ischar(n,font) - if not v then - return c - end + if nbspaces>0 then + head=replace_all_nbsp(head) end - if halant[v] then - c=getnext(c) - n=getnext(c) - if not n then - return c + head=tonode(head) + return head,done +end +function methods.dev2(head,font,attr) + head=tonut(head) + local current=head + local start=true + local done=false + local syllabe=0 + local nbspaces=0 + while current do + local syllablestart=nil + local syllableend=nil + local char=ischar(current,font) + if char then + done=true + syllablestart=current + local c=current + local n=getnext(current) + if n and ra[char] then + local nextchar=ischar(n,font) + if nextchar and halant[nextchar] then + local n=getnext(n) + if n then + local nextnextchar=ischar(n,font) + if nextnextchar then + c=n + char=nextnextchar + end + end + end + end + if independent_vowel[char] then + current=analyze_next_chars_one(c,font,1) + syllableend=current + else + local standalone=char==c_nbsp + if standalone then + nbspaces=nbspaces+1 + local p=getprev(current) + if not p then + elseif ischar(p,font) then + elseif not separator[getchar(p)] then + else + standalone=false + end + end + if standalone then + current=analyze_next_chars_one(c,font,2) + syllableend=current + elseif consonant[getchar(current)] then + current=analyze_next_chars_two(current,font) + syllableend=current + end + end end - v=ischar(n,font) - if not v then - return c + if syllableend then + syllabe=syllabe+1 + local c=syllablestart + local n=getnext(syllableend) + while c~=n do + setprop(c,a_syllabe,syllabe) + c=getnext(c) + end end - end - if vowel_modifier[v] then - c=getnext(c) - n=getnext(c) - if not n then - return c + if syllableend and syllablestart~=syllableend then + head,current,nbspaces=dev2_reorder(head,syllablestart,syllableend,font,attr,nbspaces) end - v=ischar(n,font) - if not v then - return c + if not syllableend then + local char=ischar(current,font) + if char and not getprop(current,a_state) then + local mark=mark_four[char] + if mark then + head,current=inject_syntax_error(head,current,mark) + end + end end + start=false + current=getnext(current) end - if stress_tone_mark[v] then - c=getnext(c) - n=getnext(c) - if not n then - return c - end - v=ischar(n,font) - if not v then - return c - end + if nbspaces>0 then + head=replace_all_nbsp(head) end - if stress_tone_mark[v] then - return n - else - return c + head=tonode(head) + return head,done +end +methods.mlym=methods.deva +methods.mlm2=methods.dev2 + +end -- closure + +do -- begin closure to overcome local limits and interference + +if not modules then modules={} end modules ['font-one']={ + version=1.001, + comment="companion to font-ini.mkiv", + author="Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright="PRAGMA ADE / ConTeXt Development Team", + license="see context related readme files" +} +local fonts,logs,trackers,containers,resolvers=fonts,logs,trackers,containers,resolvers +local next,type,tonumber=next,type,tonumber +local match,gmatch,lower,gsub,strip,find=string.match,string.gmatch,string.lower,string.gsub,string.strip,string.find +local char,byte,sub=string.char,string.byte,string.sub +local abs=math.abs +local bxor,rshift=bit32.bxor,bit32.rshift +local P,S,R,Cmt,C,Ct,Cs,lpegmatch,patterns=lpeg.P,lpeg.S,lpeg.R,lpeg.Cmt,lpeg.C,lpeg.Ct,lpeg.Cs,lpeg.match,lpeg.patterns +local derivetable=table.derive +local trace_features=false trackers.register("afm.features",function(v) trace_features=v end) +local trace_indexing=false trackers.register("afm.indexing",function(v) trace_indexing=v end) +local trace_loading=false trackers.register("afm.loading",function(v) trace_loading=v end) +local trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end) +local report_afm=logs.reporter("fonts","afm loading") +local setmetatableindex=table.setmetatableindex +local findbinfile=resolvers.findbinfile +local definers=fonts.definers +local readers=fonts.readers +local constructors=fonts.constructors +local afm=constructors.newhandler("afm") +local pfb=constructors.newhandler("pfb") +local otf=fonts.handlers.otf +local otfreaders=otf.readers +local otfenhancers=otf.enhancers +local afmfeatures=constructors.newfeatures("afm") +local registerafmfeature=afmfeatures.register +afm.version=1.505 +afm.cache=containers.define("fonts","afm",afm.version,true) +afm.autoprefixed=true +afm.helpdata={} +afm.syncspace=true +local overloads=fonts.mappings.overloads +local applyruntimefixes=fonts.treatments and fonts.treatments.applyfixes +local comment=P("Comment") +local spacing=patterns.spacer +local lineend=patterns.newline +local words=C((1-lineend)^1) +local number=C((R("09")+S("."))^1)/tonumber*spacing^0 +local data=lpeg.Carg(1) +local pattern=( + comment*spacing*( + data*( + ("CODINGSCHEME"*spacing*words )/function(fd,a) end+("DESIGNSIZE"*spacing*number*words )/function(fd,a) fd[ 1]=a end+("CHECKSUM"*spacing*number*words )/function(fd,a) fd[ 2]=a end+("SPACE"*spacing*number*"plus"*number*"minus"*number)/function(fd,a,b,c) fd[ 3],fd[ 4],fd[ 5]=a,b,c end+("QUAD"*spacing*number )/function(fd,a) fd[ 6]=a end+("EXTRASPACE"*spacing*number )/function(fd,a) fd[ 7]=a end+("NUM"*spacing*number*number*number )/function(fd,a,b,c) fd[ 8],fd[ 9],fd[10]=a,b,c end+("DENOM"*spacing*number*number )/function(fd,a,b ) fd[11],fd[12]=a,b end+("SUP"*spacing*number*number*number )/function(fd,a,b,c) fd[13],fd[14],fd[15]=a,b,c end+("SUB"*spacing*number*number )/function(fd,a,b) fd[16],fd[17]=a,b end+("SUPDROP"*spacing*number )/function(fd,a) fd[18]=a end+("SUBDROP"*spacing*number )/function(fd,a) fd[19]=a end+("DELIM"*spacing*number*number )/function(fd,a,b) fd[20],fd[21]=a,b end+("AXISHEIGHT"*spacing*number )/function(fd,a) fd[22]=a end + )+(1-lineend)^0 + )+(1-comment)^1 +)^0 +local function scan_comment(str) + local fd={} + lpegmatch(pattern,str,1,fd) + return fd +end +local keys={} +function keys.FontName (data,line) data.metadata.fontname=strip (line) + data.metadata.fullname=strip (line) end +function keys.ItalicAngle (data,line) data.metadata.italicangle=tonumber (line) end +function keys.IsFixedPitch(data,line) data.metadata.monospaced=toboolean(line,true) end +function keys.CharWidth (data,line) data.metadata.charwidth=tonumber (line) end +function keys.XHeight (data,line) data.metadata.xheight=tonumber (line) end +function keys.Descender (data,line) data.metadata.descender=tonumber (line) end +function keys.Ascender (data,line) data.metadata.ascender=tonumber (line) end +function keys.Comment (data,line) + line=lower(line) + local designsize=match(line,"designsize[^%d]*(%d+)") + if designsize then data.metadata.designsize=tonumber(designsize) end +end +local function get_charmetrics(data,charmetrics,vector) + local characters=data.characters + local chr,ind={},0 + for k,v in gmatch(charmetrics,"([%a]+) +(.-) *;") do + if k=='C' then + v=tonumber(v) + if v<0 then + ind=ind+1 + else + ind=v + end + chr={ + index=ind + } + elseif k=='WX' then + chr.width=tonumber(v) + elseif k=='N' then + characters[v]=chr + elseif k=='B' then + local llx,lly,urx,ury=match(v,"^ *(.-) +(.-) +(.-) +(.-)$") + chr.boundingbox={ tonumber(llx),tonumber(lly),tonumber(urx),tonumber(ury) } + elseif k=='L' then + local plus,becomes=match(v,"^(.-) +(.-)$") + local ligatures=chr.ligatures + if ligatures then + ligatures[plus]=becomes + else + chr.ligatures={ [plus]=becomes } + end + end end end -local function analyze_next_chars_two(c,font) - local n=getnext(c) - if not n then - return c - end - local v=ischar(n,font) - if v and nukta[v] then - c=n - end - n=c - while true do - local nn=getnext(n) - if nn then - local vv=ischar(nn,font) - if vv then - if halant[vv] then - n=nn - local nnn=getnext(nn) - if nnn then - local vvv=ischar(nnn,font) - if vvv and zw_char[vvv] then - n=nnn - end - end - elseif vv==c_zwnj or vv==c_zwj then - local nnn=getnext(nn) - if nnn then - local vvv=ischar(nnn,font) - if vvv and halant[vvv] then - n=nnn - end - end - else - break - end - local nn=getnext(n) - if nn then - local vv=ischar(nn,font) - if vv and consonant[vv] then - n=nn - local nnn=getnext(nn) - if nnn then - local vvv=ischar(nnn,font) - if vvv and nukta[vvv] then - n=nnn - end - end - c=n - else - break - end - else - break - end +local function get_kernpairs(data,kernpairs) + local characters=data.characters + for one,two,value in gmatch(kernpairs,"KPX +(.-) +(.-) +(.-)\n") do + local chr=characters[one] + if chr then + local kerns=chr.kerns + if kerns then + kerns[two]=tonumber(value) else - break + chr.kerns={ [two]=tonumber(value) } end - else - break end end - if not c then - return +end +local function get_variables(data,fontmetrics) + for key,rest in gmatch(fontmetrics,"(%a+) *(.-)[\n\r]") do + local keyhandler=keys[key] + if keyhandler then + keyhandler(data,rest) + end end - local n=getnext(c) - if not n then - return c +end +local get_indexes +do + local n,m + local progress=function(str,position,name,size) + local forward=position+tonumber(size)+3+2 + n=n+1 + if n>=m then + return #str,name + elseif forward<#str then + return forward,name + else + return #str,name + end end - local v=ischar(n,font) - if not v then - return c + local initialize=function(str,position,size) + n=0 + m=tonumber(size) + return position+1 end - if v==c_anudatta then - c=n - n=getnext(c) - if not n then - return c + local charstrings=P("/CharStrings") + local name=P("/")*C((R("az")+R("AZ")+R("09")+S("-_."))^1) + local size=C(R("09")^1) + local spaces=P(" ")^1 + local p_filternames=Ct ( + (1-charstrings)^0*charstrings*spaces*Cmt(size,initialize)*(Cmt(name*P(" ")^1*C(R("09")^1),progress)+P(1))^1 + ) + local decrypt + do + local r,c1,c2,n=0,0,0,0 + local function step(c) + local cipher=byte(c) + local plain=bxor(cipher,rshift(r,8)) + r=((cipher+r)*c1+c2)%65536 + return char(plain) end - v=ischar(n,font) - if not v then - return c + decrypt=function(binary) + r,c1,c2,n=55665,52845,22719,4 + binary=gsub(binary,".",step) + return sub(binary,n+1) end end - if halant[v] then - c=n - n=getnext(c) - if not n then - return c + local function loadpfbvector(filename) + local data=io.loaddata(resolvers.findfile(filename)) + if not find(data,"!PS%-AdobeFont%-") then + print("no font",filename) + return end - v=ischar(n,font) - if not v then - return c + if not data then + print("no data",filename) + return end - if v==c_zwnj or v==c_zwj then - c=n - n=getnext(c) - if not n then - return c - end - v=ischar(n,font) - if not v then - return c - end + local ascii,binary=match(data,"(.*)eexec%s+......(.*)") + if not binary then + print("no binary",filename) + return end - else - if dependent_vowel[v] then - c=n - n=getnext(c) - if not n then - return c - end - v=ischar(n,font) - if not v then - return c - end + binary=decrypt(binary,4) + local vector=lpegmatch(p_filternames,binary) + vector[0]=table.remove(vector,1) + if not vector then + print("no vector",filename) + return end - if nukta[v] then - c=n - n=getnext(c) - if not n then - return c + return vector + end + get_indexes=function(data,pfbname) + local vector=loadpfbvector(pfbname) + if vector then + local characters=data.characters + if trace_loading then + report_afm("getting index data from %a",pfbname) end - v=ischar(n,font) - if not v then - return c + for index=1,#vector do + local name=vector[index] + local char=characters[name] + if char then + if trace_indexing then + report_afm("glyph %a has index %a",name,index) + end + char.index=index + end end end - if halant[v] then - c=n - n=getnext(c) - if not n then - return c + end +end +local function readafm(filename) + local ok,afmblob,size=resolvers.loadbinfile(filename) + if ok and afmblob then + local data={ + resources={ + filename=resolvers.unresolve(filename), + version=afm.version, + creator="context mkiv", + }, + properties={ + hasitalics=false, + }, + goodies={}, + metadata={ + filename=file.removesuffix(file.basename(filename)) + }, + characters={ + }, + descriptions={ + }, + } + afmblob=gsub(afmblob,"StartCharMetrics(.-)EndCharMetrics",function(charmetrics) + if trace_loading then + report_afm("loading char metrics") end - v=ischar(n,font) - if not v then - return c + get_charmetrics(data,charmetrics,vector) + return "" + end) + afmblob=gsub(afmblob,"StartKernPairs(.-)EndKernPairs",function(kernpairs) + if trace_loading then + report_afm("loading kern pairs") + end + get_kernpairs(data,kernpairs) + return "" + end) + afmblob=gsub(afmblob,"StartFontMetrics%s+([%d%.]+)(.-)EndFontMetrics",function(version,fontmetrics) + if trace_loading then + report_afm("loading variables") end + data.afmversion=version + get_variables(data,fontmetrics) + data.fontdimens=scan_comment(fontmetrics) + return "" + end) + return data + else + if trace_loading then + report_afm("no valid afm file %a",filename) end + return nil end - if vowel_modifier[v] then - c=n - n=getnext(c) - if not n then - return c +end +local addkerns,unify,normalize,fixnames,addligatures,addtexligatures +function afm.load(filename) + filename=resolvers.findfile(filename,'afm') or "" + if filename~="" and not fonts.names.ignoredfile(filename) then + local name=file.removesuffix(file.basename(filename)) + local data=containers.read(afm.cache,name) + local attr=lfs.attributes(filename) + local size,time=attr.size or 0,attr.modification or 0 + local pfbfile=file.replacesuffix(name,"pfb") + local pfbname=resolvers.findfile(pfbfile,"pfb") or "" + if pfbname=="" then + pfbname=resolvers.findfile(file.basename(pfbfile),"pfb") or "" end - v=ischar(n,font) - if not v then - return c + local pfbsize,pfbtime=0,0 + if pfbname~="" then + local attr=lfs.attributes(pfbname) + pfbsize=attr.size or 0 + pfbtime=attr.modification or 0 end - end - if stress_tone_mark[v] then - c=n - n=getnext(c) - if not n then - return c + if not data or data.size~=size or data.time~=time or data.pfbsize~=pfbsize or data.pfbtime~=pfbtime then + report_afm("reading %a",filename) + data=readafm(filename) + if data then + if pfbname~="" then + data.resources.filename=resolvers.unresolve(pfbname) + get_indexes(data,pfbname) + elseif trace_loading then + report_afm("no pfb file for %a",filename) + end + if trace_loading then + report_afm("unifying %a",filename) + end + unify(data,filename) + if trace_loading then + report_afm("add ligatures") + end + addligatures(data) + if trace_loading then + report_afm("add extra kerns") + end + addkerns(data) + if trace_loading then + report_afm("normalizing") + end + normalize(data) + if trace_loading then + report_afm("fixing names") + end + fixnames(data) + if trace_loading then + report_afm("add tounicode data") + end + fonts.mappings.addtounicode(data,filename) + otfreaders.pack(data) + data.size=size + data.time=time + data.pfbsize=pfbsize + data.pfbtime=pfbtime + report_afm("saving %a in cache",name) + data=containers.write(afm.cache,name,data) + data=containers.read(afm.cache,name) + end end - v=ischar(n,font) - if not v then - return c + if data then + otfreaders.unpack(data) + otfreaders.expand(data) + otfreaders.addunicodetable(data) + otfenhancers.apply(data,filename,data) + if applyruntimefixes then + applyruntimefixes(filename,data) + end end - end - if stress_tone_mark[v] then - return n - else - return c - end -end -local function inject_syntax_error(head,current,mark) - local signal=copy_node(current) - copyinjection(signal,current) - if mark==pre_mark then - setchar(signal,dotted_circle) + return data else - setchar(current,dotted_circle) + return nil end - return insert_node_after(head,current,signal) end -function methods.deva(head,font,attr) - head=tonut(head) - local current=head - local start=true - local done=false - local nbspaces=0 - while current do - local char=ischar(current,font) - if char then - done=true - local syllablestart=current - local syllableend=nil - local c=current - local n=getnext(c) - local first=char - if n and ra[first] then - local second=ischar(n,font) - if second and halant[second] then - local n=getnext(n) - if n then - local third=ischar(n,font) - if third then - c=n - first=third - end - end - end +local uparser=fonts.mappings.makenameparser() +unify=function(data,filename) + local unicodevector=fonts.encodings.agl.unicodes + local unicodes={} + local names={} + local private=constructors.privateoffset + local descriptions=data.descriptions + for name,blob in next,data.characters do + local code=unicodevector[name] + if not code then + code=lpegmatch(uparser,name) + if not code then + code=private + private=private+1 + report_afm("assigning private slot %U for unknown glyph name %a",code,name) end - local standalone=first==c_nbsp - if standalone then - local prev=getprev(current) - if prev then - local prevchar=ischar(prev,font) - if not prevchar then - elseif not separator[prevchar] then - else - standalone=false - end + end + local index=blob.index + unicodes[name]=code + names[name]=index + blob.name=name + descriptions[code]={ + boundingbox=blob.boundingbox, + width=blob.width, + kerns=blob.kerns, + index=index, + name=name, + } + end + for unicode,description in next,descriptions do + local kerns=description.kerns + if kerns then + local krn={} + for name,kern in next,kerns do + local unicode=unicodes[name] + if unicode then + krn[unicode]=kern else end end - if standalone then - local syllableend=analyze_next_chars_one(c,font,2) - current=getnext(syllableend) - if syllablestart~=syllableend then - head,current,nbspaces=deva_reorder(head,syllablestart,syllableend,font,attr,nbspaces) - current=getnext(current) - end - else - if consonant[char] then - local prevc=true - while prevc do - prevc=false - local n=getnext(current) - if not n then - break - end - local v=ischar(n,font) - if not v then - break - end - if nukta[v] then - n=getnext(n) - if not n then - break - end - v=ischar(n,font) - if not v then - break - end - end - if halant[v] then - n=getnext(n) - if not n then - break - end - v=ischar(n,font) - if not v then - break - end - if v==c_zwnj or v==c_zwj then - n=getnext(n) - if not n then - break - end - v=ischar(n,font) - if not v then - break - end - end - if consonant[v] then - prevc=true - current=n + description.kerns=krn + end + end + data.characters=nil + local resources=data.resources + local filename=resources.filename or file.removesuffix(file.basename(filename)) + resources.filename=resolvers.unresolve(filename) + resources.unicodes=unicodes + resources.marks={} + resources.private=private +end +local everywhere={ ["*"]={ ["*"]=true } } +local noflags={ false,false,false,false } +normalize=function(data) + local ligatures=setmetatableindex("table") + local kerns=setmetatableindex("table") + local extrakerns=setmetatableindex("table") + for u,c in next,data.descriptions do + local l=c.ligatures + local k=c.kerns + local e=c.extrakerns + if l then + ligatures[u]=l + for u,v in next,l do + l[u]={ ligature=v } + end + c.ligatures=nil + end + if k then + kerns[u]=k + for u,v in next,k do + k[u]=v + end + c.kerns=nil + end + if e then + extrakerns[u]=e + for u,v in next,e do + e[u]=v + end + c.extrakerns=nil + end + end + local features={ + gpos={}, + gsub={}, + } + local sequences={ + } + if next(ligatures) then + features.gsub.liga=everywhere + data.properties.hasligatures=true + sequences[#sequences+1]={ + features={ + liga=everywhere, + }, + flags=noflags, + name="s_s_0", + nofsteps=1, + order={ "liga" }, + type="gsub_ligature", + steps={ + { + coverage=ligatures, + }, + }, + } + end + if next(kerns) then + features.gpos.kern=everywhere + data.properties.haskerns=true + sequences[#sequences+1]={ + features={ + kern=everywhere, + }, + flags=noflags, + name="p_s_0", + nofsteps=1, + order={ "kern" }, + type="gpos_pair", + steps={ + { + format="kern", + coverage=kerns, + }, + }, + } + end + if next(extrakerns) then + features.gpos.extrakerns=everywhere + data.properties.haskerns=true + sequences[#sequences+1]={ + features={ + extrakerns=everywhere, + }, + flags=noflags, + name="p_s_1", + nofsteps=1, + order={ "extrakerns" }, + type="gpos_pair", + steps={ + { + format="kern", + coverage=extrakerns, + }, + }, + } + end + data.resources.features=features + data.resources.sequences=sequences +end +fixnames=function(data) + for k,v in next,data.descriptions do + local n=v.name + local r=overloads[n] + if r then + local name=r.name + if trace_indexing then + report_afm("renaming characters %a to %a",n,name) + end + v.name=name + v.unicode=r.unicode + end + end +end +local addthem=function(rawdata,ligatures) + if ligatures then + local descriptions=rawdata.descriptions + local resources=rawdata.resources + local unicodes=resources.unicodes + for ligname,ligdata in next,ligatures do + local one=descriptions[unicodes[ligname]] + if one then + for _,pair in next,ligdata do + local two,three=unicodes[pair[1]],unicodes[pair[2]] + if two and three then + local ol=one.ligatures + if ol then + if not ol[two] then + ol[two]=three end + else + one.ligatures={ [two]=three } end end - local n=getnext(current) - if n then - local v=ischar(n,font) - if v and nukta[v] then - current=n - n=getnext(current) - end - end - syllableend=current - current=n - if current then - local v=ischar(current,font) - if not v then - elseif halant[v] then - local n=getnext(current) - if n then - local v=ischar(n,font) - if v and zw_char[v] then - syllableend=n - current=getnext(n) + end + end + end + end +end +addligatures=function(rawdata) addthem(rawdata,afm.helpdata.ligatures ) end +addtexligatures=function(rawdata) addthem(rawdata,afm.helpdata.texligatures) end +addkerns=function(rawdata) + local descriptions=rawdata.descriptions + local resources=rawdata.resources + local unicodes=resources.unicodes + local function do_it_left(what) + if what then + for unicode,description in next,descriptions do + local kerns=description.kerns + if kerns then + local extrakerns + for complex,simple in next,what do + complex=unicodes[complex] + simple=unicodes[simple] + if complex and simple then + local ks=kerns[simple] + if ks and not kerns[complex] then + if extrakerns then + extrakerns[complex]=ks else - syllableend=current - current=n + extrakerns={ [complex]=ks } end - else - syllableend=current - current=n - end - else - if dependent_vowel[v] then - syllableend=current - current=getnext(current) - v=ischar(current,font) - end - if v and vowel_modifier[v] then - syllableend=current - current=getnext(current) - v=ischar(current,font) - end - if v and stress_tone_mark[v] then - syllableend=current - current=getnext(current) end end end - if syllablestart~=syllableend then - head,current,nbspaces=deva_reorder(head,syllablestart,syllableend,font,attr,nbspaces) - current=getnext(current) + if extrakerns then + description.extrakerns=extrakerns end - elseif independent_vowel[char] then - syllableend=current - current=getnext(current) - if current then - local v=ischar(current,font) - if v then - if vowel_modifier[v] then - syllableend=current - current=getnext(current) - v=ischar(current,font) + end + end + end + end + local function do_it_copy(what) + if what then + for complex,simple in next,what do + complex=unicodes[complex] + simple=unicodes[simple] + if complex and simple then + local complexdescription=descriptions[complex] + if complexdescription then + local simpledescription=descriptions[complex] + if simpledescription then + local extrakerns + local kerns=simpledescription.kerns + if kerns then + for unicode,kern in next,kerns do + if extrakerns then + extrakerns[unicode]=kern + else + extrakerns={ [unicode]=kern } + end + end end - if v and stress_tone_mark[v] then - syllableend=current - current=getnext(current) + local extrakerns=simpledescription.extrakerns + if extrakerns then + for unicode,kern in next,extrakerns do + if extrakerns then + extrakerns[unicode]=kern + else + extrakerns={ [unicode]=kern } + end + end + end + if extrakerns then + complexdescription.extrakerns=extrakerns end end end + end + end + end + end + do_it_left(afm.helpdata.leftkerned) + do_it_left(afm.helpdata.bothkerned) + do_it_copy(afm.helpdata.bothkerned) + do_it_copy(afm.helpdata.rightkerned) +end +local function adddimensions(data) + if data then + for unicode,description in next,data.descriptions do + local bb=description.boundingbox + if bb then + local ht,dp=bb[4],-bb[2] + if ht==0 or ht<0 then else - local mark=mark_four[char] - if mark then - head,current=inject_syntax_error(head,current,mark) - end - current=getnext(current) + description.height=ht + end + if dp==0 or dp<0 then + else + description.depth=dp + end + end + end + end +end +local function copytotfm(data) + if data and data.descriptions then + local metadata=data.metadata + local resources=data.resources + local properties=derivetable(data.properties) + local descriptions=derivetable(data.descriptions) + local goodies=derivetable(data.goodies) + local characters={} + local parameters={} + local unicodes=resources.unicodes + for unicode,description in next,data.descriptions do + characters[unicode]={} + end + local filename=constructors.checkedfilename(resources) + local fontname=metadata.fontname or metadata.fullname + local fullname=metadata.fullname or metadata.fontname + local endash=0x0020 + local emdash=0x2014 + local spacer="space" + local spaceunits=500 + local monospaced=metadata.monospaced + local charwidth=metadata.charwidth + local italicangle=metadata.italicangle + local charxheight=metadata.xheight and metadata.xheight>0 and metadata.xheight + properties.monospaced=monospaced + parameters.italicangle=italicangle + parameters.charwidth=charwidth + parameters.charxheight=charxheight + if properties.monospaced then + if descriptions[endash] then + spaceunits,spacer=descriptions[endash].width,"space" + end + if not spaceunits and descriptions[emdash] then + spaceunits,spacer=descriptions[emdash].width,"emdash" + end + if not spaceunits and charwidth then + spaceunits,spacer=charwidth,"charwidth" + end + else + if descriptions[endash] then + spaceunits,spacer=descriptions[endash].width,"space" + end + if not spaceunits and charwidth then + spaceunits,spacer=charwidth,"charwidth" + end + end + spaceunits=tonumber(spaceunits) + if spaceunits<200 then + end + parameters.slant=0 + parameters.space=spaceunits + parameters.space_stretch=500 + parameters.space_shrink=333 + parameters.x_height=400 + parameters.quad=1000 + if italicangle and italicangle~=0 then + parameters.italicangle=italicangle + parameters.italicfactor=math.cos(math.rad(90+italicangle)) + parameters.slant=- math.tan(italicangle*math.pi/180) + end + if monospaced then + parameters.space_stretch=0 + parameters.space_shrink=0 + elseif afm.syncspace then + parameters.space_stretch=spaceunits/2 + parameters.space_shrink=spaceunits/3 + end + parameters.extra_space=parameters.space_shrink + if charxheight then + parameters.x_height=charxheight + else + local x=0x0078 + if x then + local x=descriptions[x] + if x then + parameters.x_height=x.height end end - else - current=getnext(current) end - start=false + local fd=data.fontdimens + if fd and fd[8] and fd[9] and fd[10] then + for k,v in next,fd do + parameters[k]=v + end + end + parameters.designsize=(metadata.designsize or 10)*65536 + parameters.ascender=abs(metadata.ascender or 0) + parameters.descender=abs(metadata.descender or 0) + parameters.units=1000 + properties.spacer=spacer + properties.encodingbytes=2 + properties.format=fonts.formats[filename] or "type1" + properties.filename=filename + properties.fontname=fontname + properties.fullname=fullname + properties.psname=fullname + properties.name=filename or fullname or fontname + if next(characters) then + return { + characters=characters, + descriptions=descriptions, + parameters=parameters, + resources=resources, + properties=properties, + goodies=goodies, + } + end end - if nbspaces>0 then - head=replace_all_nbsp(head) + return nil +end +function afm.setfeatures(tfmdata,features) + local okay=constructors.initializefeatures("afm",tfmdata,features,trace_features,report_afm) + if okay then + return constructors.collectprocessors("afm",tfmdata,features,trace_features,report_afm) + else + return {} end - head=tonode(head) - return head,done end -function methods.dev2(head,font,attr) - head=tonut(head) - local current=head - local start=true - local done=false - local syllabe=0 - local nbspaces=0 - while current do - local syllablestart=nil - local syllableend=nil - local char=ischar(current,font) - if char then - done=true - syllablestart=current - local c=current - local n=getnext(current) - if n and ra[char] then - local nextchar=ischar(n,font) - if nextchar and halant[nextchar] then - local n=getnext(n) - if n then - local nextnextchar=ischar(n,font) - if nextnextchar then - c=n - char=nextnextchar - end +local function addtables(data) + local resources=data.resources + local lookuptags=resources.lookuptags + local unicodes=resources.unicodes + if not lookuptags then + lookuptags={} + resources.lookuptags=lookuptags + end + setmetatableindex(lookuptags,function(t,k) + local v=type(k)=="number" and ("lookup "..k) or k + t[k]=v + return v + end) + if not unicodes then + unicodes={} + resources.unicodes=unicodes + setmetatableindex(unicodes,function(t,k) + setmetatableindex(unicodes,nil) + for u,d in next,data.descriptions do + local n=d.name + if n then + t[n]=u + end + end + return rawget(t,k) + end) + end + constructors.addcoreunicodes(unicodes) +end +local function afmtotfm(specification) + local afmname=specification.filename or specification.name + if specification.forced=="afm" or specification.format=="afm" then + if trace_loading then + report_afm("forcing afm format for %a",afmname) + end + else + local tfmname=findbinfile(afmname,"ofm") or "" + if tfmname~="" then + if trace_loading then + report_afm("fallback from afm to tfm for %a",afmname) + end + return + end + end + if afmname~="" then + local features=constructors.checkedfeatures("afm",specification.features.normal) + specification.features.normal=features + constructors.hashinstance(specification,true) + specification=definers.resolve(specification) + local cache_id=specification.hash + local tfmdata=containers.read(constructors.cache,cache_id) + if not tfmdata then + local rawdata=afm.load(afmname) + if rawdata and next(rawdata) then + addtables(rawdata) + adddimensions(rawdata) + tfmdata=copytotfm(rawdata) + if tfmdata and next(tfmdata) then + local shared=tfmdata.shared + if not shared then + shared={} + tfmdata.shared=shared end + shared.rawdata=rawdata + shared.dynamics={} + tfmdata.changed={} + shared.features=features + shared.processes=afm.setfeatures(tfmdata,features) end + elseif trace_loading then + report_afm("no (valid) afm file found with name %a",afmname) end - if independent_vowel[char] then - current=analyze_next_chars_one(c,font,1) - syllableend=current - else - local standalone=char==c_nbsp - if standalone then - nbspaces=nbspaces+1 - local p=getprev(current) - if not p then - elseif ischar(p,font) then - elseif not separator[getchar(p)] then - else - standalone=false + tfmdata=containers.write(constructors.cache,cache_id,tfmdata) + end + return tfmdata + end +end +local function read_from_afm(specification) + local tfmdata=afmtotfm(specification) + if tfmdata then + tfmdata.properties.name=specification.name + tfmdata=constructors.scale(tfmdata,specification) + local allfeatures=tfmdata.shared.features or specification.features.normal + constructors.applymanipulators("afm",tfmdata,allfeatures,trace_features,report_afm) + fonts.loggers.register(tfmdata,'afm',specification) + end + return tfmdata +end +local function prepareligatures(tfmdata,ligatures,value) + if value then + local descriptions=tfmdata.descriptions + local hasligatures=false + for unicode,character in next,tfmdata.characters do + local description=descriptions[unicode] + local dligatures=description.ligatures + if dligatures then + local cligatures=character.ligatures + if not cligatures then + cligatures={} + character.ligatures=cligatures + end + for unicode,ligature in next,dligatures do + cligatures[unicode]={ + char=ligature, + type=0 + } + end + hasligatures=true + end + end + tfmdata.properties.hasligatures=hasligatures + end +end +local function preparekerns(tfmdata,kerns,value) + if value then + local rawdata=tfmdata.shared.rawdata + local resources=rawdata.resources + local unicodes=resources.unicodes + local descriptions=tfmdata.descriptions + local haskerns=false + for u,chr in next,tfmdata.characters do + local d=descriptions[u] + local newkerns=d[kerns] + if newkerns then + local kerns=chr.kerns + if not kerns then + kerns={} + chr.kerns=kerns + end + for k,v in next,newkerns do + local uk=unicodes[k] + if uk then + kerns[uk]=v end end - if standalone then - current=analyze_next_chars_one(c,font,2) - syllableend=current - elseif consonant[getchar(current)] then - current=analyze_next_chars_two(current,font) - syllableend=current + haskerns=true + end + end + tfmdata.properties.haskerns=haskerns + end +end +local list={ + [0x0027]=0x2019, +} +local function texreplacements(tfmdata,value) + local descriptions=tfmdata.descriptions + local characters=tfmdata.characters + for k,v in next,list do + characters [k]=characters [v] + descriptions[k]=descriptions[v] + end +end +local function extrakerns (tfmdata,value) preparekerns (tfmdata,'extrakerns',value) end +local function setmode(tfmdata,value) + if value then + tfmdata.properties.mode=lower(value) + end +end +registerafmfeature { + name="mode", + description="mode", + initializers={ + base=setmode, + node=setmode, + } +} +registerafmfeature { + name="features", + description="features", + default=true, + initializers={ + node=otf.nodemodeinitializer, + base=otf.basemodeinitializer, + }, + processors={ + node=otf.featuresprocessor, + } +} +local check_tfm=readers.check_tfm +fonts.formats.afm="type1" +fonts.formats.pfb="type1" +local function check_afm(specification,fullname) + local foundname=findbinfile(fullname,'afm') or "" + if foundname=="" then + foundname=fonts.names.getfilename(fullname,"afm") or "" + end + if foundname=="" and afm.autoprefixed then + local encoding,shortname=match(fullname,"^(.-)%-(.*)$") + if encoding and shortname and fonts.encodings.known[encoding] then + shortname=findbinfile(shortname,'afm') or "" + if shortname~="" then + foundname=shortname + if trace_defining then + report_afm("stripping encoding prefix from filename %a",afmname) end end end - if syllableend then - syllabe=syllabe+1 - local c=syllablestart - local n=getnext(syllableend) - while c~=n do - setprop(c,a_syllabe,syllabe) - c=getnext(c) - end - end - if syllableend and syllablestart~=syllableend then - head,current,nbspaces=dev2_reorder(head,syllablestart,syllableend,font,attr,nbspaces) + end + if foundname~="" then + specification.filename=foundname + specification.format="afm" + return read_from_afm(specification) + end +end +function readers.afm(specification,method) + local fullname,tfmdata=specification.filename or "",nil + if fullname=="" then + local forced=specification.forced or "" + if forced~="" then + tfmdata=check_afm(specification,specification.name.."."..forced) end - if not syllableend then - local char=ischar(current,font) - if char and not getprop(current,a_state) then - local mark=mark_four[char] - if mark then - head,current=inject_syntax_error(head,current,mark) - end + if not tfmdata then + method=method or definers.method or "afm or tfm" + if method=="tfm" then + tfmdata=check_tfm(specification,specification.name) + elseif method=="afm" then + tfmdata=check_afm(specification,specification.name) + elseif method=="tfm or afm" then + tfmdata=check_tfm(specification,specification.name) or check_afm(specification,specification.name) + else + tfmdata=check_afm(specification,specification.name) or check_tfm(specification,specification.name) end end - start=false - current=getnext(current) + else + tfmdata=check_afm(specification,fullname) end - if nbspaces>0 then - head=replace_all_nbsp(head) + return tfmdata +end +function readers.pfb(specification,method) + local original=specification.specification + if trace_defining then + report_afm("using afm reader for %a",original) end - head=tonode(head) - return head,done + specification.specification=gsub(original,"%.pfb",".afm") + specification.forced="afm" + return readers.afm(specification,method) end -methods.mlym=methods.deva -methods.mlm2=methods.dev2 + +end -- closure + +do -- begin closure to overcome local limits and interference + +if not modules then modules={} end modules ['font-afk']={ + version=1.001, + comment="companion to font-afm.lua", + author="Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright="PRAGMA ADE / ConTeXt Development Team", + license="see context related readme files", + dataonly=true, +} +local allocate=utilities.storage.allocate +fonts.handlers.afm.helpdata={ + ligatures=allocate { + ['f']={ + { 'f','ff' }, + { 'i','fi' }, + { 'l','fl' }, + }, + ['ff']={ + { 'i','ffi' } + }, + ['fi']={ + { 'i','fii' } + }, + ['fl']={ + { 'i','fli' } + }, + ['s']={ + { 't','st' } + }, + ['i']={ + { 'j','ij' } + }, + }, + texligatures=allocate { + ['quoteleft']={ + { 'quoteleft','quotedblleft' } + }, + ['quoteright']={ + { 'quoteright','quotedblright' } + }, + ['hyphen']={ + { 'hyphen','endash' } + }, + ['endash']={ + { 'hyphen','emdash' } + } + }, + leftkerned=allocate { + AEligature="A",aeligature="a", + OEligature="O",oeligature="o", + IJligature="I",ijligature="i", + AE="A",ae="a", + OE="O",oe="o", + IJ="I",ij="i", + Ssharp="S",ssharp="s", + }, + rightkerned=allocate { + AEligature="E",aeligature="e", + OEligature="E",oeligature="e", + IJligature="J",ijligature="j", + AE="E",ae="e", + OE="E",oe="e", + IJ="J",ij="j", + Ssharp="S",ssharp="s", + }, + bothkerned=allocate { + Acircumflex="A",acircumflex="a", + Ccircumflex="C",ccircumflex="c", + Ecircumflex="E",ecircumflex="e", + Gcircumflex="G",gcircumflex="g", + Hcircumflex="H",hcircumflex="h", + Icircumflex="I",icircumflex="i", + Jcircumflex="J",jcircumflex="j", + Ocircumflex="O",ocircumflex="o", + Scircumflex="S",scircumflex="s", + Ucircumflex="U",ucircumflex="u", + Wcircumflex="W",wcircumflex="w", + Ycircumflex="Y",ycircumflex="y", + Agrave="A",agrave="a", + Egrave="E",egrave="e", + Igrave="I",igrave="i", + Ograve="O",ograve="o", + Ugrave="U",ugrave="u", + Ygrave="Y",ygrave="y", + Atilde="A",atilde="a", + Itilde="I",itilde="i", + Otilde="O",otilde="o", + Utilde="U",utilde="u", + Ntilde="N",ntilde="n", + Adiaeresis="A",adiaeresis="a",Adieresis="A",adieresis="a", + Ediaeresis="E",ediaeresis="e",Edieresis="E",edieresis="e", + Idiaeresis="I",idiaeresis="i",Idieresis="I",idieresis="i", + Odiaeresis="O",odiaeresis="o",Odieresis="O",odieresis="o", + Udiaeresis="U",udiaeresis="u",Udieresis="U",udieresis="u", + Ydiaeresis="Y",ydiaeresis="y",Ydieresis="Y",ydieresis="y", + Aacute="A",aacute="a", + Cacute="C",cacute="c", + Eacute="E",eacute="e", + Iacute="I",iacute="i", + Lacute="L",lacute="l", + Nacute="N",nacute="n", + Oacute="O",oacute="o", + Racute="R",racute="r", + Sacute="S",sacute="s", + Uacute="U",uacute="u", + Yacute="Y",yacute="y", + Zacute="Z",zacute="z", + Dstroke="D",dstroke="d", + Hstroke="H",hstroke="h", + Tstroke="T",tstroke="t", + Cdotaccent="C",cdotaccent="c", + Edotaccent="E",edotaccent="e", + Gdotaccent="G",gdotaccent="g", + Idotaccent="I",idotaccent="i", + Zdotaccent="Z",zdotaccent="z", + Amacron="A",amacron="a", + Emacron="E",emacron="e", + Imacron="I",imacron="i", + Omacron="O",omacron="o", + Umacron="U",umacron="u", + Ccedilla="C",ccedilla="c", + Kcedilla="K",kcedilla="k", + Lcedilla="L",lcedilla="l", + Ncedilla="N",ncedilla="n", + Rcedilla="R",rcedilla="r", + Scedilla="S",scedilla="s", + Tcedilla="T",tcedilla="t", + Ohungarumlaut="O",ohungarumlaut="o", + Uhungarumlaut="U",uhungarumlaut="u", + Aogonek="A",aogonek="a", + Eogonek="E",eogonek="e", + Iogonek="I",iogonek="i", + Uogonek="U",uogonek="u", + Aring="A",aring="a", + Uring="U",uring="u", + Abreve="A",abreve="a", + Ebreve="E",ebreve="e", + Gbreve="G",gbreve="g", + Ibreve="I",ibreve="i", + Obreve="O",obreve="o", + Ubreve="U",ubreve="u", + Ccaron="C",ccaron="c", + Dcaron="D",dcaron="d", + Ecaron="E",ecaron="e", + Lcaron="L",lcaron="l", + Ncaron="N",ncaron="n", + Rcaron="R",rcaron="r", + Scaron="S",scaron="s", + Tcaron="T",tcaron="t", + Zcaron="Z",zcaron="z", + dotlessI="I",dotlessi="i", + dotlessJ="J",dotlessj="j", + AEligature="AE",aeligature="ae",AE="AE",ae="ae", + OEligature="OE",oeligature="oe",OE="OE",oe="oe", + IJligature="IJ",ijligature="ij",IJ="IJ",ij="ij", + Lstroke="L",lstroke="l",Lslash="L",lslash="l", + Ostroke="O",ostroke="o",Oslash="O",oslash="o", + Ssharp="SS",ssharp="ss", + Aumlaut="A",aumlaut="a", + Eumlaut="E",eumlaut="e", + Iumlaut="I",iumlaut="i", + Oumlaut="O",oumlaut="o", + Uumlaut="U",uumlaut="u", + } +} end -- closure @@ -24164,17 +24189,18 @@ function nodes.handlers.nodepass(head) local variant=hash[getchar(p)] if variant then setchar(p,variant) - if not redundant then - redundant={ n } - else - redundant[#redundant+1]=n - end end end end + if not redundant then + redundant={ n } + else + redundant[#redundant+1]=n + end end end end + local nofbasefonts=#basefonts if redundant then for i=1,#redundant do local r=redundant[i] @@ -24185,8 +24211,8 @@ function nodes.handlers.nodepass(head) else setlink(p,n) end - if b>0 then - for i=1,b do + if nofbasefonts>0 then + for i=1,nofbasefonts do local bi=basefonts[i] if r==bi[1] then bi[1]=n @@ -24230,8 +24256,8 @@ function nodes.handlers.nodepass(head) end end end - if basemodepass and #basefonts>0 then - for i=1,#basefonts do + if basemodepass and nofbasefonts>0 then + for i=1,nofbasefonts do local range=basefonts[i] local start=range[1] local stop=range[2] diff --git a/Master/texmf-dist/tex/generic/context/luatex/luatex-fonts.lua b/Master/texmf-dist/tex/generic/context/luatex/luatex-fonts.lua index e1ec3764ec3..1d2f2037fea 100644 --- a/Master/texmf-dist/tex/generic/context/luatex/luatex-fonts.lua +++ b/Master/texmf-dist/tex/generic/context/luatex/luatex-fonts.lua @@ -230,8 +230,6 @@ if non_generic_context.luatex_fonts.skip_loading ~= true then loadmodule('luatex-fonts-syn.lua') loadmodule('font-tfm.lua') - loadmodule('font-afm.lua') - loadmodule('font-afk.lua') loadmodule('font-oti.lua') -- These are the old loader and processing modules. These use the built-in font loader and @@ -260,6 +258,11 @@ if non_generic_context.luatex_fonts.skip_loading ~= true then loadmodule('font-ots.lua') loadmodule('font-osd.lua') + -- type one code + + loadmodule('font-one.lua') -- was font-afm.lua + loadmodule('font-afk.lua') + -- common code loadmodule('font-lua.lua') -- cgit v1.2.3