diff options
author | Hans Hagen <pragma@wxs.nl> | 2023-02-14 18:21:35 +0100 |
---|---|---|
committer | Context Git Mirror Bot <phg@phi-gamma.net> | 2023-02-14 18:21:35 +0100 |
commit | cd404631d7079a9af603d173eb015f026731aa01 (patch) | |
tree | 588c6c8e860bb26955999dfc8be67eb78cc7ff7f /tex | |
parent | d643b65f7ab840157f538914b07f8d3cddf94bec (diff) | |
download | context-cd404631d7079a9af603d173eb015f026731aa01.tar.gz |
2023-02-14 17:44:00
Diffstat (limited to 'tex')
57 files changed, 6525 insertions, 728 deletions
diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii index c61c97d8a..736e64033 100644 --- a/tex/context/base/mkii/cont-new.mkii +++ b/tex/context/base/mkii/cont-new.mkii @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2023.02.07 19:02} +\newcontextversion{2023.02.14 17:41} %D This file is loaded at runtime, thereby providing an %D excellent place for hacks, patches, extensions and new diff --git a/tex/context/base/mkii/context.mkii b/tex/context/base/mkii/context.mkii index b62aa3a85..3337f07f0 100644 --- a/tex/context/base/mkii/context.mkii +++ b/tex/context/base/mkii/context.mkii @@ -20,7 +20,7 @@ %D your styles an modules. \edef\contextformat {\jobname} -\edef\contextversion{2023.02.07 19:02} +\edef\contextversion{2023.02.14 17:41} %D For those who want to use this: diff --git a/tex/context/base/mkiv/buff-ini.lua b/tex/context/base/mkiv/buff-ini.lua index 9af76f72e..f23344eda 100644 --- a/tex/context/base/mkiv/buff-ini.lua +++ b/tex/context/base/mkiv/buff-ini.lua @@ -816,7 +816,7 @@ local function getbuffermkvi(name) -- rather direct ! ctx_viafile(resolvers.macros.preprocessed(getcontent(name)),formatters["buffer.%s.mkiv"](validstring(name,"noname"))) end -local function gettexbuffer(name) +local function getbuffertex(name) local buffer = name and cache[name] if buffer and buffer.data ~= "" then ctx_pushcatcodetable() @@ -831,15 +831,15 @@ local function gettexbuffer(name) end end -buffers.get = getbuffer -buffers.getmkiv = getbuffermkiv -buffers.gettexbuffer = gettexbuffer -buffers.run = runbuffer +buffers.get = getbuffer +buffers.getmkvi = getbuffermkvi +buffers.gettex = getbuffertex +buffers.run = runbuffer implement { name = "getbufferctxlua", actions = loadcontent, arguments = "string" } implement { name = "getbuffer", actions = getbuffer, arguments = "string" } implement { name = "getbuffermkvi", actions = getbuffermkvi, arguments = "string" } -implement { name = "gettexbuffer", actions = gettexbuffer, arguments = "string" } +implement { name = "getbuffertex", actions = getbuffertex, arguments = "string" } interfaces.implement { name = "getbuffercontent", diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv index d524240e6..b525836df 100644 --- a/tex/context/base/mkiv/cont-new.mkiv +++ b/tex/context/base/mkiv/cont-new.mkiv @@ -13,7 +13,7 @@ % \normalend % uncomment this to get the real base runtime -\newcontextversion{2023.02.07 19:02} +\newcontextversion{2023.02.14 17:41} %D This file is loaded at runtime, thereby providing an excellent place for hacks, %D patches, extensions and new features. There can be local overloads in cont-loc diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv index 1e3ce084e..a5e343291 100644 --- a/tex/context/base/mkiv/context.mkiv +++ b/tex/context/base/mkiv/context.mkiv @@ -49,7 +49,7 @@ %D {YYYY.MM.DD HH:MM} format. \edef\contextformat {\jobname} -\edef\contextversion{2023.02.07 19:02} +\edef\contextversion{2023.02.14 17:41} %D Kind of special: diff --git a/tex/context/base/mkiv/regi-ini.lua b/tex/context/base/mkiv/regi-ini.lua index 8d4f2bfd5..2a3b2caaf 100644 --- a/tex/context/base/mkiv/regi-ini.lua +++ b/tex/context/base/mkiv/regi-ini.lua @@ -16,7 +16,6 @@ runtime.</p> local commands, context = commands, context - local tostring = tostring local utfchar = utf.char local P, Cs, Cc, lpegmatch = lpeg.P, lpeg.Cs, lpeg.Cc, lpeg.match diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf Binary files differindex cf4d8480a..70fe4d224 100644 --- a/tex/context/base/mkiv/status-files.pdf +++ b/tex/context/base/mkiv/status-files.pdf diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf Binary files differindex 258228978..9540ac450 100644 --- a/tex/context/base/mkiv/status-lua.pdf +++ b/tex/context/base/mkiv/status-lua.pdf diff --git a/tex/context/base/mkiv/tabl-xtb.mkvi b/tex/context/base/mkiv/tabl-xtb.mkvi index 3f3ef4be3..c340efdfa 100644 --- a/tex/context/base/mkiv/tabl-xtb.mkvi +++ b/tex/context/base/mkiv/tabl-xtb.mkvi @@ -267,7 +267,7 @@ }% else whitespace mess \def\tabl_x_get_buffer - {\clf_gettexbuffer{\tabl_x_current_buffer}} + {\clf_getbuffertex{\tabl_x_current_buffer}} \let\tabl_x_start_row_yes \relax \let\tabl_x_start_row_nop \relax diff --git a/tex/context/base/mkxl/back-imp-lua.mkxl b/tex/context/base/mkxl/back-imp-lua.mkxl index db26657ef..641123842 100644 --- a/tex/context/base/mkxl/back-imp-lua.mkxl +++ b/tex/context/base/mkxl/back-imp-lua.mkxl @@ -11,6 +11,6 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\registerctxluafile{back-imp-lua}{autosuffix,optimize} +\registerctxluafile{back-imp-lua}{autosuffix} \endinput diff --git a/tex/context/base/mkxl/back-imp-mps.mkxl b/tex/context/base/mkxl/back-imp-mps.mkxl index 45dde7e36..bda053706 100644 --- a/tex/context/base/mkxl/back-imp-mps.mkxl +++ b/tex/context/base/mkxl/back-imp-mps.mkxl @@ -11,6 +11,6 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\registerctxluafile{back-imp-mps}{autosuffix,optimize} +\registerctxluafile{back-imp-mps}{autosuffix} \endinput diff --git a/tex/context/base/mkxl/buff-ini.lmt b/tex/context/base/mkxl/buff-ini.lmt index 1d4722531..9f5535638 100644 --- a/tex/context/base/mkxl/buff-ini.lmt +++ b/tex/context/base/mkxl/buff-ini.lmt @@ -88,12 +88,19 @@ local buffers = buffers local cache = { } local function erase(name) - cache[name] = nil + if not name or name == "" then + cache[""] = false -- nil + else + local list = settings_to_array(name) + for i=1,#list do + cache[list[i]] = false -- nil + end + end end local assign do - -- Ther eis no gain in an immediate concatenating lpeg + -- There is no gain in an immediate concatenating lpeg local action = whitespace^0 * C(P("+")^1 + P("*")) * whitespace^0 local equal = whitespace^0 * patterns.equal * whitespace^0 @@ -708,12 +715,17 @@ local function runbuffer(name,encapsulate,runnername,suffixes) end local f_getbuffer = formatters["buffer.%s"] +local defaultlist = { "" } local function getbuffer(name) - local str = getcontent(name) - if str ~= "" then - -- characters.showstring(str) - ctx_viafile(str,f_getbuffer(validstring(name,"noname"))) + local list = name and name ~= "" and settings_to_array(name) or defaultlist + for i=1,#list do + local buf = list[i] + local str = getcontent(buf) + if str ~= "" then + -- characters.showstring(str) + ctx_viafile(str,f_getbuffer(validstring(buf,"noname"))) + end end end @@ -721,7 +733,7 @@ local function getbuffermkvi(name) -- rather direct ! ctx_viafile(resolvers.macros.preprocessed(getcontent(name)),formatters["buffer.%s.mkiv"](validstring(name,"noname"))) end -local function gettexbuffer(name) +local function getbuffertex(name) local buffer = name and cache[name] if buffer and buffer.data ~= "" then ctx_pushcatcodetable() @@ -736,15 +748,16 @@ local function gettexbuffer(name) end end -buffers.get = getbuffer -buffers.getmkiv = getbuffermkiv -buffers.gettexbuffer = gettexbuffer -buffers.run = runbuffer +buffers.get = getbuffer +buffers.getmkvi = getbuffermkvi +buffers.gettex = getbuffertex +buffers.getctxlua = loadcontent +buffers.run = runbuffer -implement { name = "getbufferctxlua", actions = loadcontent, arguments = "string" } -implement { name = "getbuffer", actions = getbuffer, arguments = "string" } -implement { name = "getbuffermkvi", actions = getbuffermkvi, arguments = "string" } -implement { name = "gettexbuffer", actions = gettexbuffer, arguments = "string" } +implement { name = "getbufferctxlua", actions = loadcontent, arguments = "argument" } +implement { name = "getbuffer", actions = getbuffer, arguments = "argument" } +implement { name = "getbuffermkvi", actions = getbuffermkvi, arguments = "argument" } +implement { name = "getbuffertex", actions = getbuffertex, arguments = "argument" } interfaces.implement { name = "getbuffercontent", diff --git a/tex/context/base/mkxl/buff-ini.mkxl b/tex/context/base/mkxl/buff-ini.mkxl index d192a01ea..0bc4d665f 100644 --- a/tex/context/base/mkxl/buff-ini.mkxl +++ b/tex/context/base/mkxl/buff-ini.mkxl @@ -107,9 +107,9 @@ \permanent\tolerant\protected\def\setbuffer[#1]#:#2\endbuffer % seldom used so we just pass #2 {\clf_assignbuffer{#1}{\detokenize{#2}}\catcodetable\relax} -% beware, never adapt the global buffer settings, actually we might introduce +% Beware, never adapt the global buffer settings, actually we might introduce % a broken parent chain for this purpose but on the other hand it's not that -% different from framed cum suis +% different from framed cum suis. \installcorenamespace{buffer} @@ -143,35 +143,40 @@ \permanent\def\thebuffernumber #1{\namedbufferparameter{#1}\c!number} \permanent\def\thedefinedbuffer#1{def-\namedbufferparameter{#1}\c!number} -\permanent\tolerant\protected\def\getbuffer[#1]% [name] +\permanent\def\getbufferdata[#1]% expandable + {\clf_getbuffer{#1}} + +\permanent\tolerant\protected\def\getbuffer[#1]% [namelist] {\namedbufferparameter\empty\c!before\relax - \doifelsenothing{#1} - {\buff_get_stored_indeed\empty} - {\processcommalist[#1]\buff_get_stored_indeed}% + \clf_getbuffer{#1}% \namedbufferparameter\empty\c!after\relax} \protected\def\buff_get_stored#1#2% {\namedbufferparameter{#1}\c!before\relax - \buff_get_stored_indeed{#2}% + \clf_getbuffer{#2}% \namedbufferparameter{#1}\c!after\relax} -\protected\def\buff_get_stored_indeed#1% - {\clf_getbuffer{#1}} +\aliased\let\rawbuffer\clf_getbuffer % expandable \permanent\protected\def\getdefinedbuffer[#1]% {\buff_get_stored{#1}{\thedefinedbuffer{#1}}}% -\permanent\tolerant\protected\def\inlinebuffer[#1]% [name] - {\doifelsenothing{#1} - {\buff_get_stored_inline_indeed\empty} - {\processcommalist[#1]\buff_get_stored_inline_indeed}} +% We had this: +% +% \permanent\tolerant\protected\def\inlinebuffer[#1]% [name] +% {\doifelsenothing{#1} +% {\buff_get_stored_inline_indeed\empty} +% {\processcommalist[#1]\buff_get_stored_inline_indeed}} +% +% \protected\def\buff_get_stored_inline_indeed#1% +% {\ignorespaces\clf_getbuffer{#1}\removeunwantedspaces} +% +% but it makes no sense to ignore spaces in between and we now do the +% list at the \LUA\ end anyway: -\protected\def\buff_get_stored_inline_indeed#1% +\permanent\tolerant\protected\def\inlinebuffer[#1]% [name] {\ignorespaces\clf_getbuffer{#1}\removeunwantedspaces} -\permanent\def\rawbuffer#1% expandable - {\clf_getbuffer{#1}} - \definebuffer [\v!hiding] @@ -180,20 +185,14 @@ [\c!before=, \c!after=] -\permanent\protected\protected\def\processTEXbuffer[#1]% keep case, maybe also lower - {\pushcatcodetable - \catcodetable\ctxcatcodes % \setcatcodetable - \buff_get_stored_indeed{#1}% - \popcatcodetable} - -% only mkiv: -% -% \startbuffer[x] -% x -% \stopbuffer -% -% \savebuffer[x] [temp] % gets name: jobname-temp.tmp -% \savebufferinfile[x][temp.log] % gets name: temp.log +%D \starttyping +%D \startbuffer[x] +%D x y z +%D \stopbuffer +%D +%D \savebuffer[x] [temp] % gets name: jobname-temp.tmp +%D \savebufferinfile[x][temp.log] % gets name: temp.log +%D \stoptyping \installcorenamespace{savebuffer} \installcorenamespace{savebuffercounter} @@ -242,6 +241,9 @@ %D \stoptext %D \stoptyping +% We can keep the counter at the lua end and explicitly reset it when we +% save. + \appendtoks \ifcsname\e!stop\currentsavebuffer\endcsname\else \definebuffer[\currentsavebuffer]% @@ -272,8 +274,15 @@ % % \ctxluabuffer[what] \ctxluabuffer -\permanent\tolerant\protected\def\ctxluabuffer[#1]{\clf_getbufferctxlua{#1}} % todo: use public implementor -\permanent\tolerant\protected\def\mkvibuffer [#1]{\clf_getbuffermkvi {#1}} % todo: use public implementor +\permanent\tolerant\protected\def\processTEXbuffer[#1]#;#=% keep case, maybe also lower + {\pushcatcodetable + \catcodetable\ctxcatcodes % \setcatcodetable + \clf_getbuffer{#1#2}% + \popcatcodetable} + +\permanent\tolerant\protected\def\ctxluabuffer[#1]#;#={\clf_getbufferctxlua{#1#2}} % todo: use public implementor +\permanent\tolerant\protected\def\mkvibuffer [#1]#;#={\clf_getbuffermkvi {#1#2}} % todo: use public implementor +\permanent\tolerant\protected\def\texbuffer [#1]#;#={\clf_getbuffertex {#1#2}} % todo: use public implementor % maybe still used elsewhere @@ -281,10 +290,6 @@ \aliased\let\dostartbuffer\grabbufferdata % for old times sake, this will go away -% new (expandable): - -\permanent\def\getbufferdata[#1]{\buff_get_stored_indeed{#1}} - % low level helper (for math manual): % \showboxinbuffer{temp}<boxnumber><detail> % defined in lua, detail cf \shownodedetails 0|1|2 diff --git a/tex/context/base/mkxl/buff-ver.mkxl b/tex/context/base/mkxl/buff-ver.mkxl index 461807162..8c42694a3 100644 --- a/tex/context/base/mkxl/buff-ver.mkxl +++ b/tex/context/base/mkxl/buff-ver.mkxl @@ -31,7 +31,6 @@ \installcorenamespace{typinglines} \installcorenamespace{typingspace} -\installcorenamespace{typingblank} % needs checking ... used? \newtoks\everyinitializeverbatim @@ -58,14 +57,6 @@ \defcsname\??typingspace\v!fixed \endcsname{\enforced\let\obeyedspace\specialfixedspace} \defcsname\??typingspace\v!character \endcsname{\enforced\chardef\obeyedspace\spaceasciicode} -\defcsname\??typingblank\v!standard \endcsname{\s_spac_whitespace_parskip} -\defcsname\??typingblank\v!small \endcsname{\smallskipamount} -\defcsname\??typingblank\v!medium \endcsname{\medskipamount} -\defcsname\??typingblank\v!big \endcsname{\bigskipamount} -\defcsname\??typingblank\v!halfline \endcsname{.5\baselineskip} -\defcsname\??typingblank\v!line \endcsname{\baselineskip} -\defcsname\??typingblank\v!none \endcsname{\zeropoint} - \protected\def\buff_verbatim_obey_hyphens {} @@ -109,12 +100,10 @@ \def\buff_verbatim_initialize_typing_one {\usebodyfontparameter\typingparameter - \scratchskip\typingparameter\c!oddmargin\relax - \ifzeropt\scratchskip \else + \ifzerodim\typingparameter\c!oddmargin\else \let\buff_verbatim_set_line_margin\buff_verbatim_set_line_margin_indeed \fi - \scratchskip\typingparameter\c!evenmargin\relax - \ifzeropt\scratchskip \else + \ifzerodim\typingparameter\c!evenmargin\else \let\buff_verbatim_set_line_margin\buff_verbatim_set_line_margin_indeed \fi \ifrelax\buff_verbatim_set_line_margin @@ -289,8 +278,8 @@ \futureexpand\bgroup\buff_verbatim_type_a\buff_verbatim_type_one} \def\buff_verbatim_type_one - {\catcode`<=\othercatcode % old precaution - \catcode`>=\othercatcode % old precaution + {\catcode\lessthanasciicode\othercatcode % old precaution + \catcode\morethanasciicode\othercatcode % old precaution \futureexpandis<\buff_verbatim_type_b\buff_verbatim_type_c} \def\buff_verbatim_type_three @@ -461,10 +450,10 @@ \futureexpandis[\buff_verbatim_typing_start_yes\buff_verbatim_typing_start_nop} \def\buff_verbatim_typing_start_yes[#1]% - {\ifcondition\validassignment{#1}% + {\ifhastok={#1}% \setupcurrenttyping[#1]% - \else - \doif\v!continue{#1}{\lettypingparameter\c!continue\v!yes}% + \orelse\ifcstok{#1}\v!continue + \lettypingparameter\c!continue\v!yes \fi \typingparameter\c!before\relax % moved down \startpacked[\v!blank]% % moved down diff --git a/tex/context/base/mkxl/cont-new.mkxl b/tex/context/base/mkxl/cont-new.mkxl index 9a267bc5f..667b2bc6d 100644 --- a/tex/context/base/mkxl/cont-new.mkxl +++ b/tex/context/base/mkxl/cont-new.mkxl @@ -13,7 +13,7 @@ % \normalend % uncomment this to get the real base runtime -\newcontextversion{2023.02.07 19:02} +\newcontextversion{2023.02.14 17:41} %D This file is loaded at runtime, thereby providing an excellent place for hacks, %D patches, extensions and new features. There can be local overloads in cont-loc diff --git a/tex/context/base/mkxl/context.mkxl b/tex/context/base/mkxl/context.mkxl index 143c67ffb..b0539ce74 100644 --- a/tex/context/base/mkxl/context.mkxl +++ b/tex/context/base/mkxl/context.mkxl @@ -29,7 +29,7 @@ %D {YYYY.MM.DD HH:MM} format. \immutable\edef\contextformat {\jobname} -\immutable\edef\contextversion{2023.02.07 19:02} +\immutable\edef\contextversion{2023.02.14 17:41} %overloadmode 1 % check frozen / warning %overloadmode 2 % check frozen / error @@ -642,8 +642,16 @@ \errorstopmode \dump \endinput -% These lua files are (still) shared with mkiv amd some are large and -% rather generic. However there are some that can be improved in lmtx. +% Some lua files are (still) shared with mkiv amd some are large and rather +% generic. However there are some that can be improved in lmtx. At some point +% we will definitely freeze mkiv and then use lmt files for futher development +% of lmtx. We also no longer use the macro feature to replace 5.3 compatible +% function calls by native 5.4 features as lmt files assume 5.4 anyway. This +% makes format generation a little faster (not that it's that slow). It might \ +% take a while before we dealt with all of them because I'll also clean them +% up a bit when doing. +% +% % luat-bas.mkxl l-macro-imp-optimize % this will go away % c:/data/develop/context/sources/attr-eff.lua % c:/data/develop/context/sources/attr-mkr.lua @@ -689,6 +697,8 @@ % c:/data/develop/context/sources/core-dat.lua % c:/data/develop/context/sources/core-two.lua +% data... + % c:/data/develop/context/sources/file-ini.lua % c:/data/develop/context/sources/file-lib.lua % c:/data/develop/context/sources/file-res.lua @@ -697,14 +707,11 @@ % c:/data/develop/context/sources/font-afk.lua % c:/data/develop/context/sources/font-agl.lua % c:/data/develop/context/sources/font-aux.lua -% c:/data/develop/context/sources/font-cff.lua % c:/data/develop/context/sources/font-cid.lua % c:/data/develop/context/sources/font-enc.lua % c:/data/develop/context/sources/font-log.lua % c:/data/develop/context/sources/font-lua.lua % not realy used, more a demo -% c:/data/develop/context/sources/font-map.lua % c:/data/develop/context/sources/font-nod.lua % some trace helpers -% c:/data/develop/context/sources/font-onr.lua % type one afm/pfb % c:/data/develop/context/sources/font-osd.lua % c:/data/develop/context/sources/font-otc.lua % c:/data/develop/context/sources/font-oth.lua @@ -720,7 +727,6 @@ % c:/data/develop/context/sources/font-sol.lua % c:/data/develop/context/sources/font-syn.lua % identification code % c:/data/develop/context/sources/font-trt.lua -% c:/data/develop/context/sources/font-ttf.lua % c:/data/develop/context/sources/font-web.lua % proof of concept, never used % c:/data/develop/context/sources/font-imp-combining.lua % shared, like typescript @@ -753,8 +759,6 @@ % c:/data/develop/context/sources/lang-txt.lua % these are data files % c:/data/develop/context/sources/lang-wrd.lua -% c:/data/develop/context/sources/libs-ini.lua % will become lmt - % c:/data/develop/context/sources/luat-exe.lua % c:/data/develop/context/sources/luat-iop.lua % c:/data/develop/context/sources/luat-mac.lua % will become lmt @@ -790,7 +794,7 @@ % c:/data/develop/context/sources/phys-dim.lua -% c:/data/develop/context/sources/publ-aut.lua +% c:/data/develop/context/sources/publ-aut.lua % shared % c:/data/develop/context/sources/publ-dat.lua % c:/data/develop/context/sources/publ-fnd.lua % c:/data/develop/context/sources/publ-inc.lua @@ -802,8 +806,6 @@ % c:/data/develop/context/sources/publ-tra.lua % c:/data/develop/context/sources/publ-usr.lua -% c:/data/develop/context/sources/regi-ini.lua - % c:/data/develop/context/sources/scrn-but.lua % c:/data/develop/context/sources/scrn-fld.lua % c:/data/develop/context/sources/scrn-hlp.lua @@ -838,13 +840,11 @@ % c:/data/develop/context/sources/trac-par.lua % c:/data/develop/context/sources/trac-tex.lua -% c:/data/develop/context/sources/typo-cln.lua +% c:/data/develop/context/sources/typo-cln.lua -- wrong name for what it does % c:/data/develop/context/sources/typo-dha.lua % c:/data/develop/context/sources/typo-fkr.lua % c:/data/develop/context/sources/typo-inj.lua -% c:/data/develop/context/sources/typo-lan.lua % c:/data/develop/context/sources/typo-man.lua -% c:/data/develop/context/sources/typo-pnc.lua % c:/data/develop/context/sources/typo-prc.lua % c:/data/develop/context/sources/typo-rep.lua diff --git a/tex/context/base/mkxl/data-vir.lmt b/tex/context/base/mkxl/data-vir.lmt new file mode 100644 index 000000000..b78211fc9 --- /dev/null +++ b/tex/context/base/mkxl/data-vir.lmt @@ -0,0 +1,104 @@ +if not modules then modules = { } end modules ['data-vir'] = { + version = 1.001, + comment = "companion to luat-lib.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local type = type +local formatters = string.formatters + +local trace_virtual = false +local report_virtual = logs.reporter("resolvers","virtual") + +trackers.register("resolvers.locating", function(v) trace_virtual = v end) +trackers.register("resolvers.virtual", function(v) trace_virtual = v end) + +local resolvers = resolvers +local savers = resolvers.savers +local cleaners = resolvers.cleaners + +local data = { } +local n = 0 -- hm, number can be query +local f_virtual_n = formatters["virtual://%s.%s"] +local f_virtual_y = formatters["virtual://%s-%s.%s"] + +function savers.virtual(specification,content,suffix) + n = n + 1 -- one number for all namespaces + local path = type(specification) == "table" and specification.path or specification + if type(path) ~= "string" or path == "" then + path = "virtualfile" + end + local filename = suffix and f_virtual_y(path,n,suffix) or f_virtual_n(path,n) + if trace_virtual then + report_virtual("saver: file %a saved",filename) + end + data[filename] = content + return filename +end + +function cleaners.virtual(filename) + data[filename] = nil +end + +local finders = resolvers.finders +local notfound = finders.notfound + +function finders.virtual(specification) + local original = specification.original + local d = data[original] + if d then + if trace_virtual then + report_virtual("finder: file %a found",original) + end + return original + else + if trace_virtual then + report_virtual("finder: unknown file %a",original) + end + return notfound() + end +end + +local openers = resolvers.openers +local notfound = openers.notfound +local textopener = openers.helpers.textopener + +function openers.virtual(specification) + local original = specification.original + local d = data[original] + if d then + if trace_virtual then + report_virtual("opener: file %a opened",original) + end + data[original] = nil -- when we comment this we can have error messages + -- With utf-8 we signal that no regime is to be applied! + -- characters.showstring(d) + return textopener("virtual",original,d,"utf-8") + else + if trace_virtual then + report_virtual("opener: file %a not found",original) + end + return notfound() + end +end + +local loaders = resolvers.loaders +local notfound = loaders.notfound + +function loaders.virtual(specification) + local original = specification.original + local d = data[original] + if d then + if trace_virtual then + report_virtual("loader: file %a loaded",original) + end + data[original] = nil + return true, d, #d + end + if trace_virtual then + report_virtual("loader: file %a not loaded",original) + end + return notfound() +end diff --git a/tex/context/base/mkxl/file-ini.mklx b/tex/context/base/mkxl/file-ini.mklx index 106536eea..7c4645a9a 100644 --- a/tex/context/base/mkxl/file-ini.mklx +++ b/tex/context/base/mkxl/file-ini.mklx @@ -99,11 +99,11 @@ \the\everystartreadingfile \pushcatcodetable % saveguard \setcatcodetable\ctxcatcodes - \clf_pushregime}% temporarily this way + \pushregime}% temporarily this way \permanent\protected\def\stopreadingfile - {\popcatcodetable % saveguard - \clf_popregime % temporarily this way + {\popcatcodetable % saveguard + \popregime % temporarily this way \the\everystopreadingfile \global\advanceby\readingfilelevel\minusone} diff --git a/tex/context/base/mkxl/font-cff.lmt b/tex/context/base/mkxl/font-cff.lmt new file mode 100644 index 000000000..dc5f98382 --- /dev/null +++ b/tex/context/base/mkxl/font-cff.lmt @@ -0,0 +1,2788 @@ +if not modules then modules = { } end modules ['font-cff'] = { + version = 1.001, + optimize = true, + 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" +} + +-- todo: option.outlines +-- todo: option.boundingbox +-- per charstring (less memory) + +-- This is a heavy one as it is a rather packed format. We don't need al the information +-- now but we might need it later (who know what magic we can do with metapost). So at +-- some point this might become a module. We just follow Adobe Technical Notes #5176 and +-- #5177. In case of doubt I looked in the fontforge code that comes with LuaTeX but +-- it's not the easiest source to read (and doesn't cover cff2). + +-- For now we save the segments in a list of segments with the operator last in an entry +-- because that reflects the original. But it might make more sense to use a single array +-- per segment. For pdf a simple concat works ok, but for other purposes a operator first +-- flush is nicer. +-- +-- In retrospect I could have looked into the backend code of LuaTeX but it never +-- occurred to me that parsing charstrings was needed there (which has to to +-- with merging subroutines and flattening, not so much with calculations.) On +-- the other hand, we can now feed back cff2 stuff. + +local next, type, tonumber, rawget = next, type, tonumber, rawget +local byte, char, gmatch, sub = string.byte, string.char, string.gmatch, string.sub +local concat, insert, remove, unpack = table.concat, table.insert, table.remove, table.unpack +local floor, abs, round, ceil, min, max = math.floor, math.abs, math.round, math.ceil, math.min, math.max +local P, C, R, S, C, Cs, Ct = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Ct +local lpegmatch = lpeg.match +local formatters = string.formatters +local bytetable = string.bytetable +----- rshift, band, extract = bit32.rshift, bit32.band, bit32.extract + +local readers = fonts.handlers.otf.readers +local streamreader = readers.streamreader + +local readstring = streamreader.readstring +local readbyte = streamreader.readcardinal1 -- 8-bit unsigned integer +local readushort = streamreader.readcardinal2 -- 16-bit unsigned integer +local readuint = streamreader.readcardinal3 -- 24-bit unsigned integer +local readulong = streamreader.readcardinal4 -- 32-bit unsigned integer +local setposition = streamreader.setposition +local getposition = streamreader.getposition +local readbytetable = streamreader.readbytetable + +directives.register("fonts.streamreader",function() + + streamreader = utilities.streams + + readstring = streamreader.readstring + readbyte = streamreader.readcardinal1 + readushort = streamreader.readcardinal2 + readuint = streamreader.readcardinal3 + readulong = streamreader.readcardinal4 + setposition = streamreader.setposition + getposition = streamreader.getposition + readbytetable = streamreader.readbytetable + +end) + +local setmetatableindex = table.setmetatableindex + +local trace_charstrings = false trackers.register("fonts.cff.charstrings",function(v) trace_charstrings = v end) +local report = logs.reporter("otf reader","cff") + +local parsedictionaries +local parsecharstring +local parsecharstrings +local resetcharstrings +local parseprivates +local startparsing +local stopparsing + +local defaultstrings = { [0] = -- taken from ff + ".notdef", "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", + "ampersand", "quoteright", "parenleft", "parenright", "asterisk", "plus", + "comma", "hyphen", "period", "slash", "zero", "one", "two", "three", "four", + "five", "six", "seven", "eight", "nine", "colon", "semicolon", "less", + "equal", "greater", "question", "at", "A", "B", "C", "D", "E", "F", "G", "H", + "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", + "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", + "underscore", "quoteleft", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", + "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", + "z", "braceleft", "bar", "braceright", "asciitilde", "exclamdown", "cent", + "sterling", "fraction", "yen", "florin", "section", "currency", + "quotesingle", "quotedblleft", "guillemotleft", "guilsinglleft", + "guilsinglright", "fi", "fl", "endash", "dagger", "daggerdbl", + "periodcentered", "paragraph", "bullet", "quotesinglbase", "quotedblbase", + "quotedblright", "guillemotright", "ellipsis", "perthousand", "questiondown", + "grave", "acute", "circumflex", "tilde", "macron", "breve", "dotaccent", + "dieresis", "ring", "cedilla", "hungarumlaut", "ogonek", "caron", "emdash", + "AE", "ordfeminine", "Lslash", "Oslash", "OE", "ordmasculine", "ae", + "dotlessi", "lslash", "oslash", "oe", "germandbls", "onesuperior", + "logicalnot", "mu", "trademark", "Eth", "onehalf", "plusminus", "Thorn", + "onequarter", "divide", "brokenbar", "degree", "thorn", "threequarters", + "twosuperior", "registered", "minus", "eth", "multiply", "threesuperior", + "copyright", "Aacute", "Acircumflex", "Adieresis", "Agrave", "Aring", + "Atilde", "Ccedilla", "Eacute", "Ecircumflex", "Edieresis", "Egrave", + "Iacute", "Icircumflex", "Idieresis", "Igrave", "Ntilde", "Oacute", + "Ocircumflex", "Odieresis", "Ograve", "Otilde", "Scaron", "Uacute", + "Ucircumflex", "Udieresis", "Ugrave", "Yacute", "Ydieresis", "Zcaron", + "aacute", "acircumflex", "adieresis", "agrave", "aring", "atilde", + "ccedilla", "eacute", "ecircumflex", "edieresis", "egrave", "iacute", + "icircumflex", "idieresis", "igrave", "ntilde", "oacute", "ocircumflex", + "odieresis", "ograve", "otilde", "scaron", "uacute", "ucircumflex", + "udieresis", "ugrave", "yacute", "ydieresis", "zcaron", "exclamsmall", + "Hungarumlautsmall", "dollaroldstyle", "dollarsuperior", "ampersandsmall", + "Acutesmall", "parenleftsuperior", "parenrightsuperior", "twodotenleader", + "onedotenleader", "zerooldstyle", "oneoldstyle", "twooldstyle", + "threeoldstyle", "fouroldstyle", "fiveoldstyle", "sixoldstyle", + "sevenoldstyle", "eightoldstyle", "nineoldstyle", "commasuperior", + "threequartersemdash", "periodsuperior", "questionsmall", "asuperior", + "bsuperior", "centsuperior", "dsuperior", "esuperior", "isuperior", + "lsuperior", "msuperior", "nsuperior", "osuperior", "rsuperior", "ssuperior", + "tsuperior", "ff", "ffi", "ffl", "parenleftinferior", "parenrightinferior", + "Circumflexsmall", "hyphensuperior", "Gravesmall", "Asmall", "Bsmall", + "Csmall", "Dsmall", "Esmall", "Fsmall", "Gsmall", "Hsmall", "Ismall", + "Jsmall", "Ksmall", "Lsmall", "Msmall", "Nsmall", "Osmall", "Psmall", + "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall", "Vsmall", "Wsmall", + "Xsmall", "Ysmall", "Zsmall", "colonmonetary", "onefitted", "rupiah", + "Tildesmall", "exclamdownsmall", "centoldstyle", "Lslashsmall", + "Scaronsmall", "Zcaronsmall", "Dieresissmall", "Brevesmall", "Caronsmall", + "Dotaccentsmall", "Macronsmall", "figuredash", "hypheninferior", + "Ogoneksmall", "Ringsmall", "Cedillasmall", "questiondownsmall", "oneeighth", + "threeeighths", "fiveeighths", "seveneighths", "onethird", "twothirds", + "zerosuperior", "foursuperior", "fivesuperior", "sixsuperior", + "sevensuperior", "eightsuperior", "ninesuperior", "zeroinferior", + "oneinferior", "twoinferior", "threeinferior", "fourinferior", + "fiveinferior", "sixinferior", "seveninferior", "eightinferior", + "nineinferior", "centinferior", "dollarinferior", "periodinferior", + "commainferior", "Agravesmall", "Aacutesmall", "Acircumflexsmall", + "Atildesmall", "Adieresissmall", "Aringsmall", "AEsmall", "Ccedillasmall", + "Egravesmall", "Eacutesmall", "Ecircumflexsmall", "Edieresissmall", + "Igravesmall", "Iacutesmall", "Icircumflexsmall", "Idieresissmall", + "Ethsmall", "Ntildesmall", "Ogravesmall", "Oacutesmall", "Ocircumflexsmall", + "Otildesmall", "Odieresissmall", "OEsmall", "Oslashsmall", "Ugravesmall", + "Uacutesmall", "Ucircumflexsmall", "Udieresissmall", "Yacutesmall", + "Thornsmall", "Ydieresissmall", "001.000", "001.001", "001.002", "001.003", + "Black", "Bold", "Book", "Light", "Medium", "Regular", "Roman", "Semibold", +} + +local standardnames = { [0] = -- needed for seac + false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, + "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", + "ampersand", "quoteright", "parenleft", "parenright", "asterisk", "plus", + "comma", "hyphen", "period", "slash", "zero", "one", "two", "three", "four", + "five", "six", "seven", "eight", "nine", "colon", "semicolon", "less", + "equal", "greater", "question", "at", "A", "B", "C", "D", "E", "F", "G", "H", + "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", + "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", + "underscore", "quoteleft", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", + "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", + "z", "braceleft", "bar", "braceright", "asciitilde", false, false, false, + false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, "exclamdown", + "cent", "sterling", "fraction", "yen", "florin", "section", "currency", + "quotesingle", "quotedblleft", "guillemotleft", "guilsinglleft", + "guilsinglright", "fi", "fl", false, "endash", "dagger", "daggerdbl", + "periodcentered", false, "paragraph", "bullet", "quotesinglbase", + "quotedblbase", "quotedblright", "guillemotright", "ellipsis", "perthousand", + false, "questiondown", false, "grave", "acute", "circumflex", "tilde", + "macron", "breve", "dotaccent", "dieresis", false, "ring", "cedilla", false, + "hungarumlaut", "ogonek", "caron", "emdash", false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, + false, "AE", false, "ordfeminine", false, false, false, false, "Lslash", + "Oslash", "OE", "ordmasculine", false, false, false, false, false, "ae", + false, false, false, "dotlessi", false, false, "lslash", "oslash", "oe", + "germandbls", false, false, false, false +} + +local cffreaders = { + readbyte, + readushort, + readuint, + readulong, +} + +directives.register("fonts.streamreader",function() + cffreaders = { + readbyte, + readushort, + readuint, + readulong, + } +end) + +-- The header contains information about its own size. + +local function readheader(f) + local offset = getposition(f) + local major = readbyte(f) + local header = { + offset = offset, + major = major, + minor = readbyte(f), + size = readbyte(f), -- headersize + } + if major == 1 then + header.dsize = readbyte(f) -- list of dict offsets + elseif major == 2 then + header.dsize = readushort(f) -- topdict size + else + -- I'm probably no longer around by then and we use AI's to + -- handle this kind of stuff, if we typeset documents at all. + end + setposition(f,offset+header.size) + return header +end + +-- The indexes all look the same, so we share a loader. We could pass a handler +-- and run over the array but why bother, we only have a few uses. + +local function readlengths(f,longcount) + local count = longcount and readulong(f) or readushort(f) + if count == 0 then + return { } + end + local osize = readbyte(f) + local read = cffreaders[osize] + if not read then + report("bad offset size: %i",osize) + return { } + end + local lengths = { } + local previous = read(f) + for i=1,count do + local offset = read(f) + local length = offset - previous + if length < 0 then + report("bad offset: %i",length) + length = 0 + end + lengths[i] = length + previous = offset + end + return lengths +end + +-- There can be subfonts so names is an array. However, in our case it's always +-- one font. The same is true for the top dictionaries. Watch how we only load +-- the dictionary string as for interpretation we need to have the strings loaded +-- as well. + +local function readfontnames(f) + local names = readlengths(f) + for i=1,#names do + names[i] = readstring(f,names[i]) + end + return names +end + +local function readtopdictionaries(f) + local dictionaries = readlengths(f) + for i=1,#dictionaries do + dictionaries[i] = readstring(f,dictionaries[i]) + end + return dictionaries +end + +-- Strings are added to a list of standard strings so we start the font specific +-- one with an offset. Strings are shared so we have one table. + +local function readstrings(f) + local lengths = readlengths(f) + local strings = setmetatableindex({ }, defaultstrings) + local index = #defaultstrings + for i=1,#lengths do + index = index + 1 + strings[index] = readstring(f,lengths[i]) + end + return strings +end + +-- Parsing the dictionaries is delayed till we have the strings loaded. The parser +-- is stack based so the operands come before the operator (like in postscript). + +-- local function delta(t) +-- local n = #t +-- if n > 1 then +-- local p = t[1] +-- for i=2,n do +-- local c = t[i] +-- t[i] = c + p +-- p = c +-- end +-- end +-- end + +do + + -- We use a closure so that we don't need to pass too much around. For cff2 we can + -- at some point use a simple version as there is less. + + local stack = { } + local top = 0 + local result = { } + local strings = { } + + local p_single = + P("\00") / function() + result.version = strings[stack[top]] or "unset" + top = 0 + end + + P("\01") / function() + result.notice = strings[stack[top]] or "unset" + top = 0 + end + + P("\02") / function() + result.fullname = strings[stack[top]] or "unset" + top = 0 + end + + P("\03") / function() + result.familyname = strings[stack[top]] or "unset" + top = 0 + end + + P("\04") / function() + result.weight = strings[stack[top]] or "unset" + top = 0 + end + + P("\05") / function() + result.fontbbox = { unpack(stack,1,4) } + top = 0 + end + + P("\06") / function() + result.bluevalues = { unpack(stack,1,top) } + top = 0 + end + + P("\07") / function() + result.otherblues = { unpack(stack,1,top) } + top = 0 + end + + P("\08") / function() + result.familyblues = { unpack(stack,1,top) } + top = 0 + end + + P("\09") / function() + result.familyotherblues = { unpack(stack,1,top) } + top = 0 + end + + P("\10") / function() + result.stdhw = stack[top] + top = 0 + end + + P("\11") / function() + result.stdvw = stack[top] + top = 0 + end + + P("\13") / function() + result.uniqueid = stack[top] + top = 0 + end + + P("\14") / function() + result.xuid = concat(stack,"",1,top) + top = 0 + end + + P("\15") / function() + result.charset = stack[top] + top = 0 + end + + P("\16") / function() + result.encoding = stack[top] + top = 0 + end + + P("\17") / function() -- valid cff2 + result.charstrings = stack[top] + top = 0 + end + + P("\18") / function() + result.private = { + size = stack[top-1], + offset = stack[top], + } + top = 0 + end + + P("\19") / function() + result.subroutines = stack[top] + top = 0 -- new, forgotten ? + end + + P("\20") / function() + result.defaultwidthx = stack[top] + top = 0 -- new, forgotten ? + end + + P("\21") / function() + result.nominalwidthx = stack[top] + top = 0 -- new, forgotten ? + end + -- + P("\22") / function() -- reserved + -- end + -- + P("\23") / function() -- reserved + -- end + + P("\24") / function() -- new in cff2 + result.vstore = stack[top] + top = 0 + end + + P("\25") / function() -- new in cff2 + result.maxstack = stack[top] + top = 0 + end + -- + P("\26") / function() -- reserved + -- end + -- + P("\27") / function() -- reserved + -- end + + local p_double = P("\12") * ( + P("\00") / function() + result.copyright = stack[top] + top = 0 + end + + P("\01") / function() + result.monospaced = stack[top] == 1 and true or false -- isfixedpitch + top = 0 + end + + P("\02") / function() + result.italicangle = stack[top] + top = 0 + end + + P("\03") / function() + result.underlineposition = stack[top] + top = 0 + end + + P("\04") / function() + result.underlinethickness = stack[top] + top = 0 + end + + P("\05") / function() + result.painttype = stack[top] + top = 0 + end + + P("\06") / function() + result.charstringtype = stack[top] + top = 0 + end + + P("\07") / function() -- valid cff2 + result.fontmatrix = { unpack(stack,1,6) } + top = 0 + end + + P("\08") / function() + result.strokewidth = stack[top] + top = 0 + end + + P("\09") / function() + result.bluescale = stack[top] + top = 0 + end + + P("\10") / function() + result.blueshift = stack[top] + top = 0 + end + + P("\11") / function() + result.bluefuzz = stack[top] + top = 0 + end + + P("\12") / function() + result.stemsnaph = { unpack(stack,1,top) } + top = 0 + end + + P("\13") / function() + result.stemsnapv = { unpack(stack,1,top) } + top = 0 + end + + P("\20") / function() + result.syntheticbase = stack[top] + top = 0 + end + + P("\21") / function() + result.postscript = strings[stack[top]] or "unset" + top = 0 + end + + P("\22") / function() + result.basefontname = strings[stack[top]] or "unset" + top = 0 + end + + P("\21") / function() + result.basefontblend = stack[top] + top = 0 + end + + P("\30") / function() + result.cid.registry = strings[stack[top-2]] or "unset" + result.cid.ordering = strings[stack[top-1]] or "unset" + result.cid.supplement = stack[top] + top = 0 + end + + P("\31") / function() + result.cid.fontversion = stack[top] + top = 0 + end + + P("\32") / function() + result.cid.fontrevision= stack[top] + top = 0 + end + + P("\33") / function() + result.cid.fonttype = stack[top] + top = 0 + end + + P("\34") / function() + result.cid.count = stack[top] + top = 0 + end + + P("\35") / function() + result.cid.uidbase = stack[top] + top = 0 + end + + P("\36") / function() -- valid cff2 + result.cid.fdarray = stack[top] + top = 0 + end + + P("\37") / function() -- valid cff2 + result.cid.fdselect = stack[top] + top = 0 + end + + P("\38") / function() + result.cid.fontname = strings[stack[top]] or "unset" + top = 0 + end + ) + + -- Some lpeg fun ... a first variant split the byte and made a new string but + -- the second variant is much faster. Not that it matters much as we don't see + -- such numbers often. + + local remap_1 = { + ["\x00"] = "00", ["\x01"] = "01", ["\x02"] = "02", ["\x03"] = "03", ["\x04"] = "04", ["\x05"] = "05", ["\x06"] = "06", ["\x07"] = "07", ["\x08"] = "08", ["\x09"] = "09", ["\x0A"] = "0.", ["\x0B"] = "0E", ["\x0C"] = "0E-", ["\x0D"] = "0", ["\x0E"] = "0-", ["\x0F"] = "0", + ["\x10"] = "10", ["\x11"] = "11", ["\x12"] = "12", ["\x13"] = "13", ["\x14"] = "14", ["\x15"] = "15", ["\x16"] = "16", ["\x17"] = "17", ["\x18"] = "18", ["\x19"] = "19", ["\x1A"] = "1.", ["\x1B"] = "1E", ["\x1C"] = "1E-", ["\x1D"] = "1", ["\x1E"] = "1-", ["\x1F"] = "1", + ["\x20"] = "20", ["\x21"] = "21", ["\x22"] = "22", ["\x23"] = "23", ["\x24"] = "24", ["\x25"] = "25", ["\x26"] = "26", ["\x27"] = "27", ["\x28"] = "28", ["\x29"] = "29", ["\x2A"] = "2.", ["\x2B"] = "2E", ["\x2C"] = "2E-", ["\x2D"] = "2", ["\x2E"] = "2-", ["\x2F"] = "2", + ["\x30"] = "30", ["\x31"] = "31", ["\x32"] = "32", ["\x33"] = "33", ["\x34"] = "34", ["\x35"] = "35", ["\x36"] = "36", ["\x37"] = "37", ["\x38"] = "38", ["\x39"] = "39", ["\x3A"] = "3.", ["\x3B"] = "3E", ["\x3C"] = "3E-", ["\x3D"] = "3", ["\x3E"] = "3-", ["\x3F"] = "3", + ["\x40"] = "40", ["\x41"] = "41", ["\x42"] = "42", ["\x43"] = "43", ["\x44"] = "44", ["\x45"] = "45", ["\x46"] = "46", ["\x47"] = "47", ["\x48"] = "48", ["\x49"] = "49", ["\x4A"] = "4.", ["\x4B"] = "4E", ["\x4C"] = "4E-", ["\x4D"] = "4", ["\x4E"] = "4-", ["\x4F"] = "4", + ["\x50"] = "50", ["\x51"] = "51", ["\x52"] = "52", ["\x53"] = "53", ["\x54"] = "54", ["\x55"] = "55", ["\x56"] = "56", ["\x57"] = "57", ["\x58"] = "58", ["\x59"] = "59", ["\x5A"] = "5.", ["\x5B"] = "5E", ["\x5C"] = "5E-", ["\x5D"] = "5", ["\x5E"] = "5-", ["\x5F"] = "5", + ["\x60"] = "60", ["\x61"] = "61", ["\x62"] = "62", ["\x63"] = "63", ["\x64"] = "64", ["\x65"] = "65", ["\x66"] = "66", ["\x67"] = "67", ["\x68"] = "68", ["\x69"] = "69", ["\x6A"] = "6.", ["\x6B"] = "6E", ["\x6C"] = "6E-", ["\x6D"] = "6", ["\x6E"] = "6-", ["\x6F"] = "6", + ["\x70"] = "70", ["\x71"] = "71", ["\x72"] = "72", ["\x73"] = "73", ["\x74"] = "74", ["\x75"] = "75", ["\x76"] = "76", ["\x77"] = "77", ["\x78"] = "78", ["\x79"] = "79", ["\x7A"] = "7.", ["\x7B"] = "7E", ["\x7C"] = "7E-", ["\x7D"] = "7", ["\x7E"] = "7-", ["\x7F"] = "7", + ["\x80"] = "80", ["\x81"] = "81", ["\x82"] = "82", ["\x83"] = "83", ["\x84"] = "84", ["\x85"] = "85", ["\x86"] = "86", ["\x87"] = "87", ["\x88"] = "88", ["\x89"] = "89", ["\x8A"] = "8.", ["\x8B"] = "8E", ["\x8C"] = "8E-", ["\x8D"] = "8", ["\x8E"] = "8-", ["\x8F"] = "8", + ["\x90"] = "90", ["\x91"] = "91", ["\x92"] = "92", ["\x93"] = "93", ["\x94"] = "94", ["\x95"] = "95", ["\x96"] = "96", ["\x97"] = "97", ["\x98"] = "98", ["\x99"] = "99", ["\x9A"] = "9.", ["\x9B"] = "9E", ["\x9C"] = "9E-", ["\x9D"] = "9", ["\x9E"] = "9-", ["\x9F"] = "9", + ["\xA0"] = ".0", ["\xA1"] = ".1", ["\xA2"] = ".2", ["\xA3"] = ".3", ["\xA4"] = ".4", ["\xA5"] = ".5", ["\xA6"] = ".6", ["\xA7"] = ".7", ["\xA8"] = ".8", ["\xA9"] = ".9", ["\xAA"] = "..", ["\xAB"] = ".E", ["\xAC"] = ".E-", ["\xAD"] = ".", ["\xAE"] = ".-", ["\xAF"] = ".", + ["\xB0"] = "E0", ["\xB1"] = "E1", ["\xB2"] = "E2", ["\xB3"] = "E3", ["\xB4"] = "E4", ["\xB5"] = "E5", ["\xB6"] = "E6", ["\xB7"] = "E7", ["\xB8"] = "E8", ["\xB9"] = "E9", ["\xBA"] = "E.", ["\xBB"] = "EE", ["\xBC"] = "EE-", ["\xBD"] = "E", ["\xBE"] = "E-", ["\xBF"] = "E", + ["\xC0"] = "E-0", ["\xC1"] = "E-1", ["\xC2"] = "E-2", ["\xC3"] = "E-3", ["\xC4"] = "E-4", ["\xC5"] = "E-5", ["\xC6"] = "E-6", ["\xC7"] = "E-7", ["\xC8"] = "E-8", ["\xC9"] = "E-9", ["\xCA"] = "E-.", ["\xCB"] = "E-E", ["\xCC"] = "E-E-", ["\xCD"] = "E-", ["\xCE"] = "E--", ["\xCF"] = "E-", + ["\xD0"] = "-0", ["\xD1"] = "-1", ["\xD2"] = "-2", ["\xD3"] = "-3", ["\xD4"] = "-4", ["\xD5"] = "-5", ["\xD6"] = "-6", ["\xD7"] = "-7", ["\xD8"] = "-8", ["\xD9"] = "-9", ["\xDA"] = "-.", ["\xDB"] = "-E", ["\xDC"] = "-E-", ["\xDD"] = "-", ["\xDE"] = "--", ["\xDF"] = "-", + } + local remap_2 = { + ["\x0F"] = "0", ["\x1F"] = "1", ["\x2F"] = "2", ["\x3F"] = "3", ["\x4F"] = "4", + ["\x5F"] = "5", ["\x6F"] = "6", ["\x7F"] = "7", ["\x8F"] = "8", ["\x9F"] = "9", + } + + local p_last_1 = S("\x0F\x1F\x2F\x3F\x4F\x5F\x6F\x7F\x8F\x9F\xAF\xBF") + local p_last_2 = R("\xF0\xFF") + + -- tricky, we don't want to append last + + -- local p_nibbles = P("\30") * Cs(((1-p_last)/remap)^0 * (P(1)/remap)) / function(n) + local p_nibbles = P("\30") * Cs(((1-(p_last_1+p_last_2))/remap_1)^0 * (p_last_1/remap_2 + p_last_2/"")) / function(n) + -- 0-9=digit a=. b=E c=E- d=reserved e=- f=finish + top = top + 1 + stack[top] = tonumber(n) or 0 + end + + local p_byte = C(R("\32\246")) / function(b0) + -- -107 .. +107 + top = top + 1 + stack[top] = byte(b0) - 139 + end + + local p_positive = C(R("\247\250")) * C(1) / function(b0,b1) + -- +108 .. +1131 + top = top + 1 + stack[top] = (byte(b0)-247)*256 + byte(b1) + 108 + end + + local p_negative = C(R("\251\254")) * C(1) / function(b0,b1) + -- -1131 .. -108 + top = top + 1 + stack[top] = -(byte(b0)-251)*256 - byte(b1) - 108 + end + + -- local p_float = P("\255") * C(1) * C(1) * C(1) * C(1) / function(b0,b1,b2,b3) + -- top = top + 1 + -- stack[top] = 0 + -- end + + local p_short = P("\28") * C(1) * C(1) / function(b1,b2) + -- -32768 .. +32767 : b1<<8 | b2 + top = top + 1 + local n = 0x100 * byte(b1) + byte(b2) + if n >= 0x8000 then + stack[top] = n - 0xFFFF - 1 + else + stack[top] = n + end + end + + local p_long = P("\29") * C(1) * C(1) * C(1) * C(1) / function(b1,b2,b3,b4) + -- -2^31 .. +2^31-1 : b1<<24 | b2<<16 | b3<<8 | b4 + top = top + 1 + local n = 0x1000000 * byte(b1) + 0x10000 * byte(b2) + 0x100 * byte(b3) + byte(b4) + if n >= 0x8000000 then + stack[top] = n - 0xFFFFFFFF - 1 + else + stack[top] = n + end + end + + local p_unsupported = P(1) / function(detail) + top = 0 + end + + local p_dictionary = ( + p_byte + + p_positive + + p_negative + + p_short + + p_long + + p_nibbles + + p_single + + p_double + -- + p_float + + p_unsupported + )^1 + + parsedictionaries = function(data,dictionaries,version) + stack = { } + strings = data.strings + if trace_charstrings then + report("charstring format %a",version) + end + for i=1,#dictionaries do + top = 0 + result = version == "cff" and { + monospaced = false, + italicangle = 0, + underlineposition = -100, + underlinethickness = 50, + painttype = 0, + charstringtype = 2, + fontmatrix = { 0.001, 0, 0, 0.001, 0, 0 }, + fontbbox = { 0, 0, 0, 0 }, + strokewidth = 0, + charset = 0, + encoding = 0, + cid = { + fontversion = 0, + fontrevision = 0, + fonttype = 0, + count = 8720, + } + } or { + charstringtype = 2, + charset = 0, + vstore = 0, + cid = { + -- nothing yet + }, + } + lpegmatch(p_dictionary,dictionaries[i]) + dictionaries[i] = result + end + -- + result = { } + top = 0 + stack = { } + end + + parseprivates = function(data,dictionaries) + stack = { } + strings = data.strings + for i=1,#dictionaries do + local private = dictionaries[i].private + if private and private.data then + top = 0 + result = { + forcebold = false, + languagegroup = 0, + expansionfactor = 0.06, + initialrandomseed = 0, + subroutines = 0, + defaultwidthx = 0, + nominalwidthx = 0, + cid = { + -- actually an error + }, + } + lpegmatch(p_dictionary,private.data) + private.data = result + end + end + result = { } + top = 0 + stack = { } + end + + -- All bezier curves have 6 points with successive pairs relative to + -- the previous pair. Some can be left out and are then copied or zero + -- (optimization). + -- + -- We are not really interested in all the details of a glyph because we + -- only need to calculate the boundingbox. So, todo: a quick no result but + -- calculate only variant. + -- + -- The conversion is straightforward and the specification os clear once + -- you understand that the x and y needs to be updates each step. It's also + -- quite easy to test because in mp a shape will look bad when a few variables + -- are swapped. But still there might be bugs down here because not all + -- variants are seen in a font so far. We are less compact that the ff code + -- because there quite some variants are done in one helper with a lot of + -- testing for states. + + local x = 0 + local y = 0 + local width = false + local lsb = 0 + local result = { } + local r = 0 + local stems = 0 + local globalbias = 0 + local localbias = 0 + local nominalwidth = 0 + local defaultwidth = 0 + local charset = false + local globals = false + local locals = false + local depth = 1 + local xmin = 0 + local xmax = 0 + local ymin = 0 + local ymax = 0 + local checked = false + local keepcurve = false + local version = 2 + local regions = false + local nofregions = 0 + local region = false + local factors = false + local axis = false + local vsindex = 0 + local justpass = false + local seacs = { } + local procidx = nil + + local function showstate(where,i,n) + if i then + local j = i + n - 1 + report("%w%-10s : [%s] step",depth*2+2,where,concat(stack," ",i,j <= top and j or top)) + else + report("%w%-10s : [%s] n=%i",depth*2,where,concat(stack," ",1,top),top) + end + end + + local function showvalue(where,value,showstack) + if showstack then + report("%w%-10s : %s : [%s] n=%i",depth*2,where,tostring(value),concat(stack," ",1,top),top) + else + report("%w%-10s : %s",depth*2,where,tostring(value)) + end + end + + -- All these indirect calls make this run slower but it's cleaner this way + -- and we cache the result. As we moved the boundingbox code inline we gain + -- some back. I inlined some of then and a bit speed can be gained by more + -- inlining but not that much. + + -- Maybe have several action tables: + -- + -- keep curve / checked + -- keep curve / not checked + -- checked + -- not checked + + local function xymoveto() + if keepcurve then + r = r + 1 + result[r] = { x, y, "m" } + end + if checked then + if x > xmax then xmax = x elseif x < xmin then xmin = x end + if y > ymax then ymax = y elseif y < ymin then ymin = y end + else + xmin = x + ymin = y + xmax = x + ymax = y + checked = true + end + end + + local function xmoveto() -- slight speedup + if keepcurve then + r = r + 1 + result[r] = { x, y, "m" } + end + if not checked then + xmin = x + ymin = y + xmax = x + ymax = y + checked = true + elseif x > xmax then + xmax = x + elseif x < xmin then + xmin = x + end + end + + local function ymoveto() -- slight speedup + if keepcurve then + r = r + 1 + result[r] = { x, y, "m" } + end + if not checked then + xmin = x + ymin = y + xmax = x + ymax = y + checked = true + elseif y > ymax then + ymax = y + elseif y < ymin then + ymin = y + end + end + + local function moveto() + if trace_charstrings then + showstate("moveto") + end + top = 0 -- forgotten + xymoveto() + end + + local function xylineto() -- we could inline, no blend + if keepcurve then + r = r + 1 + result[r] = { x, y, "l" } + end + if checked then + if x > xmax then xmax = x elseif x < xmin then xmin = x end + if y > ymax then ymax = y elseif y < ymin then ymin = y end + else + xmin = x + ymin = y + xmax = x + ymax = y + checked = true + end + end + + local function xlineto() -- slight speedup + if keepcurve then + r = r + 1 + result[r] = { x, y, "l" } + end + if not checked then + xmin = x + ymin = y + xmax = x + ymax = y + checked = true + elseif x > xmax then + xmax = x + elseif x < xmin then + xmin = x + end + end + + local function ylineto() -- slight speedup + if keepcurve then + r = r + 1 + result[r] = { x, y, "l" } + end + if not checked then + xmin = x + ymin = y + xmax = x + ymax = y + checked = true + elseif y > ymax then + ymax = y + elseif y < ymin then + ymin = y + end + end + + local function xycurveto(x1,y1,x2,y2,x3,y3,i,n) -- called local so no blend here + if trace_charstrings then + showstate("curveto",i,n) + end + if keepcurve then + r = r + 1 + result[r] = { x1, y1, x2, y2, x3, y3, "c" } + end + if checked then + if x1 > xmax then xmax = x1 elseif x1 < xmin then xmin = x1 end + if y1 > ymax then ymax = y1 elseif y1 < ymin then ymin = y1 end + else + xmin = x1 + ymin = y1 + xmax = x1 + ymax = y1 + checked = true + end + if x2 > xmax then xmax = x2 elseif x2 < xmin then xmin = x2 end + if y2 > ymax then ymax = y2 elseif y2 < ymin then ymin = y2 end + if x3 > xmax then xmax = x3 elseif x3 < xmin then xmin = x3 end + if y3 > ymax then ymax = y3 elseif y3 < ymin then ymin = y3 end + end + + local function rmoveto() + if not width then + if top > 2 then + width = stack[1] + if trace_charstrings then + showvalue("backtrack width",width) + end + else + width = true + end + end + if trace_charstrings then + showstate("rmoveto") + end + x = x + stack[top-1] -- dx1 + y = y + stack[top] -- dy1 + top = 0 + xymoveto() + end + + local function hmoveto() + if not width then + if top > 1 then + width = stack[1] + if trace_charstrings then + showvalue("backtrack width",width) + end + else + width = true + end + end + if trace_charstrings then + showstate("hmoveto") + end + x = x + stack[top] -- dx1 + top = 0 + xmoveto() + end + + local function vmoveto() + if not width then + if top > 1 then + width = stack[1] + if trace_charstrings then + showvalue("backtrack width",width) + end + else + width = true + end + end + if trace_charstrings then + showstate("vmoveto") + end + y = y + stack[top] -- dy1 + top = 0 + ymoveto() + end + + local function rlineto() + if trace_charstrings then + showstate("rlineto") + end + for i=1,top,2 do + x = x + stack[i] -- dxa + y = y + stack[i+1] -- dya + xylineto() + end + top = 0 + end + + local function hlineto() -- x (y,x)+ | (x,y)+ + if trace_charstrings then + showstate("hlineto") + end + if top == 1 then + x = x + stack[1] + xlineto() + else + local swap = true + for i=1,top do + if swap then + x = x + stack[i] + xlineto() + swap = false + else + y = y + stack[i] + ylineto() + swap = true + end + end + end + top = 0 + end + + local function vlineto() -- y (x,y)+ | (y,x)+ + if trace_charstrings then + showstate("vlineto") + end + if top == 1 then + y = y + stack[1] + ylineto() + else + local swap = false + for i=1,top do + if swap then + x = x + stack[i] + xlineto() + swap = false + else + y = y + stack[i] + ylineto() + swap = true + end + end + end + top = 0 + end + + local function rrcurveto() + if trace_charstrings then + showstate("rrcurveto") + end +if top == 6 then + local ax = x + stack[1] -- dxa + local ay = y + stack[2] -- dya + local bx = ax + stack[3] -- dxb + local by = ay + stack[4] -- dyb + x = bx + stack[5] -- dxc + y = by + stack[6] -- dyc + xycurveto(ax,ay,bx,by,x,y,1,6) +else +-- print("rr",top==6,top) + for i=1,top,6 do + local ax = x + stack[i] -- dxa + local ay = y + stack[i+1] -- dya + local bx = ax + stack[i+2] -- dxb + local by = ay + stack[i+3] -- dyb + x = bx + stack[i+4] -- dxc + y = by + stack[i+5] -- dyc + xycurveto(ax,ay,bx,by,x,y,i,6) + end +end + top = 0 + end + + local function hhcurveto() + if trace_charstrings then + showstate("hhcurveto") + end + local s = 1 + if top % 2 ~= 0 then + y = y + stack[1] -- dy1 + s = 2 + end +if top == 4 then + local ax = x + stack[1] -- dxa + local ay = y + local bx = ax + stack[2] -- dxb + local by = ay + stack[3] -- dyb + x = bx + stack[4] -- dxc + y = by + xycurveto(ax,ay,bx,by,x,y,1,4) +else + for i=s,top,4 do + local ax = x + stack[i] -- dxa + local ay = y + local bx = ax + stack[i+1] -- dxb + local by = ay + stack[i+2] -- dyb + x = bx + stack[i+3] -- dxc + y = by + xycurveto(ax,ay,bx,by,x,y,i,4) + end +end + top = 0 + end + + local function vvcurveto() + if trace_charstrings then + showstate("vvcurveto") + end + local s = 1 + local d = 0 + if top % 2 ~= 0 then + d = stack[1] -- dx1 + s = 2 + end +if top == 4 then + local ax = x + d + local ay = y + stack[1] -- dya + local bx = ax + stack[2] -- dxb + local by = ay + stack[3] -- dyb + x = bx + y = by + stack[4] -- dyc + xycurveto(ax,ay,bx,by,x,y,1,4) + d = 0 +else + for i=s,top,4 do + local ax = x + d + local ay = y + stack[i] -- dya + local bx = ax + stack[i+1] -- dxb + local by = ay + stack[i+2] -- dyb + x = bx + y = by + stack[i+3] -- dyc + xycurveto(ax,ay,bx,by,x,y,i,4) + d = 0 + end +end + top = 0 + end + + local function xxcurveto(swap) + local last = top % 4 ~= 0 and stack[top] + if last then + top = top - 1 + end +if top == 4 then + local ax, ay, bx, by + if swap then + ax = x + stack[1] + ay = y + bx = ax + stack[2] + by = ay + stack[3] + y = by + stack[4] + if last then + x = bx + last + else + x = bx + end + else + ax = x + ay = y + stack[1] + bx = ax + stack[2] + by = ay + stack[3] + x = bx + stack[4] + if last then + y = by + last + else + y = by + end + end + xycurveto(ax,ay,bx,by,x,y,1 ,4) +else + for i=1,top,4 do + local ax, ay, bx, by + if swap then + ax = x + stack[i] + ay = y + bx = ax + stack[i+1] + by = ay + stack[i+2] + y = by + stack[i+3] + if last and i+3 == top then + x = bx + last + else + x = bx + end + swap = false + else + ax = x + ay = y + stack[i] + bx = ax + stack[i+1] + by = ay + stack[i+2] + x = bx + stack[i+3] + if last and i+3 == top then + y = by + last + else + y = by + end + swap = true + end + xycurveto(ax,ay,bx,by,x,y,i,4) + end +end + top = 0 + end + + local function hvcurveto() + if trace_charstrings then + showstate("hvcurveto") + end + xxcurveto(true) + end + + local function vhcurveto() + if trace_charstrings then + showstate("vhcurveto") + end + xxcurveto(false) + end + + local function rcurveline() + if trace_charstrings then + showstate("rcurveline") + end + for i=1,top-2,6 do + local ax = x + stack[i] -- dxa + local ay = y + stack[i+1] -- dya + local bx = ax + stack[i+2] -- dxb + local by = ay + stack[i+3] -- dyb + x = bx + stack[i+4] -- dxc + y = by + stack[i+5] -- dyc + xycurveto(ax,ay,bx,by,x,y,i,6) + end + x = x + stack[top-1] -- dxc + y = y + stack[top] -- dyc + xylineto() + top = 0 + end + + local function rlinecurve() + if trace_charstrings then + showstate("rlinecurve") + end + if top > 6 then + for i=1,top-6,2 do + x = x + stack[i] + y = y + stack[i+1] + xylineto() + end + end + local ax = x + stack[top-5] + local ay = y + stack[top-4] + local bx = ax + stack[top-3] + local by = ay + stack[top-2] + x = bx + stack[top-1] + y = by + stack[top] + xycurveto(ax,ay,bx,by,x,y) + top = 0 + end + + -- flex is not yet tested! no loop + + local function flex() -- fd not used + if trace_charstrings then + showstate("flex") + end + local ax = x + stack[1] -- dx1 + local ay = y + stack[2] -- dy1 + local bx = ax + stack[3] -- dx2 + local by = ay + stack[4] -- dy2 + local cx = bx + stack[5] -- dx3 + local cy = by + stack[6] -- dy3 + xycurveto(ax,ay,bx,by,cx,cy) + local dx = cx + stack[7] -- dx4 + local dy = cy + stack[8] -- dy4 + local ex = dx + stack[9] -- dx5 + local ey = dy + stack[10] -- dy5 + x = ex + stack[11] -- dx6 + y = ey + stack[12] -- dy6 + xycurveto(dx,dy,ex,ey,x,y) + top = 0 + end + + local function hflex() + if trace_charstrings then + showstate("hflex") + end + local ax = x + stack[1] -- dx1 + local ay = y + local bx = ax + stack[2] -- dx2 + local by = ay + stack[3] -- dy2 + local cx = bx + stack[4] -- dx3 + local cy = by + xycurveto(ax,ay,bx,by,cx,cy) + local dx = cx + stack[5] -- dx4 + local dy = by + local ex = dx + stack[6] -- dx5 + local ey = y + x = ex + stack[7] -- dx6 + xycurveto(dx,dy,ex,ey,x,y) + top = 0 + end + + local function hflex1() + if trace_charstrings then + showstate("hflex1") + end + local ax = x + stack[1] -- dx1 + local ay = y + stack[2] -- dy1 + local bx = ax + stack[3] -- dx2 + local by = ay + stack[4] -- dy2 + local cx = bx + stack[5] -- dx3 + local cy = by + xycurveto(ax,ay,bx,by,cx,cy) + local dx = cx + stack[6] -- dx4 + local dy = by + local ex = dx + stack[7] -- dx5 + local ey = dy + stack[8] -- dy5 + x = ex + stack[9] -- dx6 + xycurveto(dx,dy,ex,ey,x,y) + top = 0 + end + + local function flex1() + if trace_charstrings then + showstate("flex1") + end + local ax = x + stack[1] --dx1 + local ay = y + stack[2] --dy1 + local bx = ax + stack[3] --dx2 + local by = ay + stack[4] --dy2 + local cx = bx + stack[5] --dx3 + local cy = by + stack[6] --dy3 + xycurveto(ax,ay,bx,by,cx,cy) + local dx = cx + stack[7] --dx4 + local dy = cy + stack[8] --dy4 + local ex = dx + stack[9] --dx5 + local ey = dy + stack[10] --dy5 + if abs(ex - x) > abs(ey - y) then -- spec: abs(dx) > abs(dy) + x = ex + stack[11] + else + y = ey + stack[11] + end + xycurveto(dx,dy,ex,ey,x,y) + top = 0 + end + + local function getstem() + if top == 0 then + -- bad + elseif top % 2 ~= 0 then + if width then + remove(stack,1) + else + width = remove(stack,1) + if trace_charstrings then + showvalue("width",width) + end + end + top = top - 1 + end + if trace_charstrings then + showstate("stem") + end + stems = stems + (top // 2) + top = 0 + end + + local function getmask() + if top == 0 then + -- bad + elseif top % 2 ~= 0 then + if width then + remove(stack,1) + else + width = remove(stack,1) + if trace_charstrings then + showvalue("width",width) + end + end + top = top - 1 + end + if trace_charstrings then + showstate(operator == 19 and "hintmark" or "cntrmask") + end + stems = stems + (top // 2) + top = 0 + if stems == 0 then + -- forget about it + elseif stems <= 8 then + return 1 + else + return (stems + 7) // 8 + end + end + + local function unsupported(t) + if trace_charstrings then + showstate("unsupported " .. t) + end + top = 0 + end + + local function unsupportedsub(t) + if trace_charstrings then + showstate("unsupported sub " .. t) + end + top = 0 + end + + -- type 1 (not used in type 2) + + local function getstem3() + if trace_charstrings then + showstate("stem3") + end + top = 0 + end + + local function divide() + if version == "cff" then + local d = stack[top] + top = top - 1 + stack[top] = stack[top] / d + end + end + + local function closepath() + if version == "cff" then + if trace_charstrings then + showstate("closepath") + end + end + top = 0 + end + + local function hsbw() + if version == "cff" then + if trace_charstrings then + showstate("hsbw") + end + lsb = stack[top-1] or 0 + width = stack[top] + end + top = 0 + end + + local function sbw() + if version == "cff" then + if trace_charstrings then + showstate("sbw") + end + lsb = stack[top-3] + width = stack[top-1] + end + top = 0 + end + + -- asb adx ady bchar achar seac (accented characters) + + local function seac() + if version == "cff" then + if trace_charstrings then + showstate("seac") + end + end + top = 0 + end + + -- These are probably used for special cases i.e. call out to the + -- postscript interpreter (p 61 of the spec as well as chapter 8). + -- + -- This needs checking (I have to ask Taco next time we meet.) + + local popped = 3 + local hints = 3 + + -- arg1 ... argn n othersubr# <callothersubr> (on postscript stack) + + local function callothersubr() + if version == "cff" then + if trace_charstrings then + showstate("callothersubr") + end + if stack[top] == hints then + popped = stack[top-2] + else + popped = 3 + end + local t = stack[top-1] + if t then + top = top - (t + 2) + if top < 0 then + top = 0 + end + else + top = 0 + end + else + top = 0 + end + end + + -- <pop> number (from postscript stack) + + local function pop() + if version == "cff" then + if trace_charstrings then + showstate("pop") + end + top = top + 1 + stack[top] = popped + else + top = 0 + end + end + + local function setcurrentpoint() + if version == "cff" then + if trace_charstrings then + showstate("setcurrentpoint (unsupported)") + end + x = x + stack[top-1] + y = y + stack[top] + end + top = 0 + end + + -- So far for unsupported postscript. Now some cff2 magic. As I still need + -- to wrap my head around the rather complex variable font specification + -- with regions and axis, the following approach kind of works but is more + -- some trial and error trick. It's still not clear how much of the complex + -- truetype description applies to cff. Once there are fonts out there we'll + -- get there. (Marcel and friends did some tests with recent cff2 fonts so + -- the code has been adapted accordingly.) + + local reginit = false + + local function updateregions(n) -- n + 1 + if regions then + local current = regions[n+1] or regions[1] + nofregions = #current + if axis and n ~= reginit then + factors = { } + for i=1,nofregions do + local region = current[i] + local s = 1 + for j=1,#axis do + local f = axis[j] + local r = region[j] + local start = r.start + local peak = r.peak + local stop = r.stop + if start > peak or peak > stop then + -- * 1 + elseif start < 0 and stop > 0 and peak ~= 0 then + -- * 1 + elseif peak == 0 then + -- * 1 + elseif f < start or f > stop then + -- * 0 + s = 0 + break + elseif f < peak then + s = s * (f - start) / (peak - start) + elseif f > peak then + s = s * (stop - f) / (stop - peak) + else + -- * 1 + end + end + factors[i] = s + end + end + end + reginit = n + end + + local function setvsindex() + local vsindex = stack[top] + if trace_charstrings then + showstate(formatters["vsindex %i"](vsindex)) + end + updateregions(vsindex) + top = top - 1 + end + + local function blend() + local n = stack[top] + top = top - 1 + if axis then + -- x (r1x,r2x,r3x) + -- (x,y) (r1x,r2x,r3x) (r1y,r2y,r3y) + if trace_charstrings then + local t = top - nofregions * n + local m = t - n + for i=1,n do + local k = m + i + local d = m + n + (i-1)*nofregions + local old = stack[k] + local new = old + for r=1,nofregions do + new = new + stack[d+r] * factors[r] + end + stack[k] = new + showstate(formatters["blend %i of %i: %s -> %s"](i,n,old,new)) + end + top = t + elseif n == 1 then + top = top - nofregions + local v = stack[top] + for r=1,nofregions do + v = v + stack[top+r] * factors[r] + end + stack[top] = v + else + top = top - nofregions * n + local d = top + local k = top - n + for i=1,n do + k = k + 1 + local v = stack[k] + for r=1,nofregions do + v = v + stack[d+r] * factors[r] + end + stack[k] = v + d = d + nofregions + end + end + else + top = top - nofregions * n + end + end + + -- Bah, we cannot use a fast lpeg because a hint has an unknown size and a + -- runtime capture cannot handle that well. + + local actions = { [0] = + unsupported, -- 0 + getstem, -- 1 -- hstem + unsupported, -- 2 + getstem, -- 3 -- vstem + vmoveto, -- 4 + rlineto, -- 5 + hlineto, -- 6 + vlineto, -- 7 + rrcurveto, -- 8 + unsupported, -- 9 -- closepath + unsupported, -- 10 -- calllocal, + unsupported, -- 11 -- callreturn, + unsupported, -- 12 -- elsewhere + hsbw, -- 13 -- hsbw (type 1 cff) + unsupported, -- 14 -- endchar, + setvsindex, -- 15 -- cff2 + blend, -- 16 -- cff2 + unsupported, -- 17 + getstem, -- 18 -- hstemhm + getmask, -- 19 -- hintmask + getmask, -- 20 -- cntrmask + rmoveto, -- 21 + hmoveto, -- 22 + getstem, -- 23 -- vstemhm + rcurveline, -- 24 + rlinecurve, -- 25 + vvcurveto, -- 26 + hhcurveto, -- 27 + unsupported, -- 28 -- elsewhere + unsupported, -- 29 -- elsewhere + vhcurveto, -- 30 + hvcurveto, -- 31 + } + + local reverse = { [0] = + "unsupported", + "getstem", + "unsupported", + "getstem", + "vmoveto", + "rlineto", + "hlineto", + "vlineto", + "rrcurveto", + "unsupported", + "unsupported", + "unsupported", + "unsupported", + "hsbw", + "unsupported", + "setvsindex", + "blend", + "unsupported", + "getstem", + "getmask", + "getmask", + "rmoveto", + "hmoveto", + "getstem", + "rcurveline", + "rlinecurve", + "vvcurveto", + "hhcurveto", + "unsupported", + "unsupported", + "vhcurveto", + "hvcurveto", + } + + local subactions = { + -- cff 1 + [000] = dotsection, + [001] = getstem3, + [002] = getstem3, + [006] = seac, + [007] = sbw, + [012] = divide, + [016] = callothersubr, + [017] = pop, + [033] = setcurrentpoint, + -- cff 2 + [034] = hflex, + [035] = flex, + [036] = hflex1, + [037] = flex1, + } + + local chars = setmetatableindex(function (t,k) + local v = char(k) + t[k] = v + return v + end) + + local c_endchar = chars[14] + + -- todo: round in blend + + local encode = { } + local typeone = false + + -- this eventually can become a helper + + setmetatableindex(encode,function(t,i) + for i=-2048,-1130 do + -- t[i] = char(28,band(rshift(i,8),0xFF),band(i,0xFF)) + t[i] = char(28,(i >> 8) & 0xFF,i & 0xFF) + end + for i=-1131,-108 do + local v = 0xFB00 - i - 108 + -- t[i] = char(band(rshift(v,8),0xFF),band(v,0xFF)) + t[i] = char((v >> 8) & 0xFF,v & 0xFF) + end + for i=-107,107 do + t[i] = chars[i + 139] + end + for i=108,1131 do + local v = 0xF700 + i - 108 + -- t[i] = char(extract(v,8,8),extract(v,0,8)) + t[i] = char((v >> 8) & 0xFF,v & 0xFF) + end + for i=1132,2048 do + -- t[i] = char(28,band(rshift(i,8),0xFF),band(i,0xFF)) + t[i] = char(28,(i >> 8) & 0xFF,i & 0xFF) + end + setmetatableindex(encode,function(t,k) + -- as we're cff2 we write 16.16-bit signed fixed value + local r = round(k) + local v = rawget(t,r) + if v then + return v + end + local v1 = floor(k) + local v2 = floor((k - v1) * 0x10000) + -- return char(255,extract(v1,8,8),extract(v1,0,8),extract(v2,8,8),extract(v2,0,8)) + return char(255,(v1 >> 8) & 0xFF,v1 & 0xFF,(v2 >> 8) & 0xFF,v2 & 0xFF) + end) + return t[i] + end) + + readers.cffencoder = encode + + local function p_setvsindex() + local vsindex = stack[top] + updateregions(vsindex) + top = top - 1 + end + + local function p_blend() + -- leaves n values on stack + local n = stack[top] + top = top - 1 + if not axis then + -- fatal error + elseif n == 1 then + top = top - nofregions + local v = stack[top] + for r=1,nofregions do + v = v + stack[top+r] * factors[r] + end + stack[top] = round(v) + else + top = top - nofregions * n + local d = top + local k = top - n + for i=1,n do + k = k + 1 + local v = stack[k] + for r=1,nofregions do + v = v + stack[d+r] * factors[r] + end + stack[k] = round(v) + d = d + nofregions + end + end + end + + local function p_getstem() + local n = 0 + if top % 2 ~= 0 then + n = 1 + end + if top > n then + stems = stems + ((top - n) // 2) + end + end + + local function p_getmask() + local n = 0 + if top % 2 ~= 0 then + n = 1 + end + if top > n then + stems = stems + ((top - n) // 2) + end + if stems == 0 then + return 0 + elseif stems <= 8 then + return 1 + else + return (stems + 7) // 8 + end + end + + -- end of experiment + + local process + + local function call(scope,list,bias) -- ,process) + depth = depth + 1 + if top == 0 then + showstate(formatters["unknown %s call %s, case %s"](scope,"?",1)) + top = 0 + else + local index = stack[top] + bias + top = top - 1 + if trace_charstrings then + showvalue(scope,index,true) + end + local tab = list[index] + if tab then + process(tab) + else + showstate(formatters["unknown %s call %s, case %s"](scope,index,2)) + top = 0 + end + end + depth = depth - 1 + end + + -- precompiling and reuse is much slower than redoing the calls + + process = function(tab) + local i = 1 + local n = #tab + while i <= n do + local t = tab[i] + if t >= 32 then + top = top + 1 + if t <= 246 then + -- -107 .. +107 + stack[top] = t - 139 + i = i + 1 + elseif t <= 250 then + -- +108 .. +1131 + -- stack[top] = (t-247)*256 + tab[i+1] + 108 + -- stack[top] = t*256 - 247*256 + tab[i+1] + 108 + stack[top] = t*256 - 63124 + tab[i+1] + i = i + 2 + elseif t <= 254 then + -- -1131 .. -108 + -- stack[top] = -(t-251)*256 - tab[i+1] - 108 + -- stack[top] = -t*256 + 251*256 - tab[i+1] - 108 + stack[top] = -t*256 + 64148 - tab[i+1] + i = i + 2 + elseif typeone then + local n = 0x1000000 * tab[i+1] + 0x10000 * tab[i+2] + 0x100 * tab[i+3] + tab[i+4] + if n >= 0x8000000 then + n = n - 0xFFFFFFFF - 1 + end + stack[top] = n + i = i + 5 + else + local n1 = 0x100 * tab[i+1] + tab[i+2] + local n2 = 0x100 * tab[i+3] + tab[i+4] + if n1 >= 0x8000 then + n1 = n1 - 0x10000 + end + stack[top] = n1 + n2/0xFFFF + i = i + 5 + end + elseif t == 28 then + -- -32768 .. +32767 : b1<<8 | b2 + top = top + 1 + local n = 0x100 * tab[i+1] + tab[i+2] + if n >= 0x8000 then + -- stack[top] = n - 0xFFFF - 1 + stack[top] = n - 0x10000 + else + stack[top] = n + end + i = i + 3 + elseif t == 11 then -- not in cff2 + if trace_charstrings then + showstate("return") + end + return + elseif t == 10 then + call("local",locals,localbias) -- ,process) + i = i + 1 + elseif t == 14 then -- not in cff2 + if width then + -- okay + elseif top > 0 then + width = stack[1] + if trace_charstrings then + showvalue("width",width) + end + else + width = true + end + if trace_charstrings then + showstate("endchar") + end + return + elseif t == 29 then + call("global",globals,globalbias) -- ,process) + i = i + 1 + elseif t == 12 then + i = i + 1 + local t = tab[i] + if justpass then + if t >= 34 and t <= 37 then -- flexes + for i=1,top do + r = r + 1 ; result[r] = encode[stack[i]] + end + r = r + 1 ; result[r] = chars[12] + r = r + 1 ; result[r] = chars[t] + top = 0 + elseif t == 6 then + seacs[procidx] = { + asb = stack[1], + adx = stack[2], + ady = stack[3], + base = stack[4], + accent = stack[5], + width = width, + lsb = lsb, + } + top = 0 + else + local a = subactions[t] + if a then + a(t) + else + top = 0 + end + end + else + local a = subactions[t] + if a then + a(t) + else + if trace_charstrings then + showvalue("<subaction>",t) + end + top = 0 + end + end + i = i + 1 + elseif justpass then + -- todo: local a = passactions + if t == 15 then + p_setvsindex() + i = i + 1 + elseif t == 16 then + local s = p_blend() or 0 + i = i + s + 1 + -- cff 1: (when cff2 strip them) + elseif t == 1 or t == 3 or t == 18 or operation == 23 then + p_getstem() -- at the start + if version == "cff" then +-- if true then + if top > 0 then + for i=1,top do + r = r + 1 ; result[r] = encode[stack[i]] + end + top = 0 + end + r = r + 1 ; result[r] = chars[t] + else + top = 0 + end + i = i + 1 + -- cff 1: (when cff2 strip them) + elseif t == 19 or t == 20 then + local s = p_getmask() or 0 -- after the stems +-- if version == "cff" then + if true then + if top > 0 then + for i=1,top do + r = r + 1 ; result[r] = encode[stack[i]] + end + top = 0 + end + r = r + 1 ; result[r] = chars[t] + for j=1,s do + i = i + 1 + r = r + 1 ; result[r] = chars[tab[i]] + end + else + i = i + s + top = 0 + end + i = i + 1 + -- cff 1: closepath + elseif t == 9 then + top = 0 + i = i + 1 + elseif t == 13 then + hsbw() +-- if version == "cff" then + if true then + -- we do a moveto over lsb + r = r + 1 ; result[r] = encode[lsb] + r = r + 1 ; result[r] = chars[22] + else + -- lsb is supposed to be zero + end + i = i + 1 + else + if trace_charstrings then + showstate(reverse[t] or "<action>") + end + if top > 0 then + -- if t == 8 and top > 42 then + if t == 8 and top > 48 then + -- let's assume this only happens for rrcurveto .. the other ones would need some more + -- complex handling (cff2 stuff) + -- + -- dx1 dy1 (dx1+dx2) (dy1+dy2) (dx1+dx2+dx3) (dy1+dy2+dy3) rcurveto. + local n = 0 + for i=1,top do + -- if n == 42 then + if n == 48 then +-- local zero = encode[0] +-- local res3 = result[r-3] +-- local res2 = result[r-2] +-- local res1 = result[r-1] +-- local res0 = result[r] +-- result[r-3] = zero +-- result[r-2] = zero + r = r + 1 ; result[r] = chars[t] +-- r = r + 1 ; result[r] = zero +-- r = r + 1 ; result[r] = zero +-- r = r + 1 ; result[r] = res3 +-- r = r + 1 ; result[r] = res2 +-- r = r + 1 ; result[r] = res1 +-- r = r + 1 ; result[r] = res0 + n = 1 + else + n = n + 1 + end + r = r + 1 ; result[r] = encode[stack[i]] + end + else + for i=1,top do + r = r + 1 ; result[r] = encode[stack[i]] + end + end + top = 0 + end + r = r + 1 ; result[r] = chars[t] + i = i + 1 + end + else + local a = actions[t] + if a then + local s = a(t) + if s then + i = i + s + 1 + else + i = i + 1 + end + else + if trace_charstrings then + showstate(reverse[t] or "<action>") + end + top = 0 + i = i + 1 + end + end + end + end + + -- local function calculatebounds(segments,x,y) + -- local nofsegments = #segments + -- if nofsegments == 0 then + -- return { x, y, x, y } + -- else + -- local xmin = 10000 + -- local xmax = -10000 + -- local ymin = 10000 + -- local ymax = -10000 + -- if x < xmin then xmin = x end + -- if x > xmax then xmax = x end + -- if y < ymin then ymin = y end + -- if y > ymax then ymax = y end + -- -- we now have a reasonable start so we could + -- -- simplify the next checks + -- for i=1,nofsegments do + -- local s = segments[i] + -- local x = s[1] + -- local y = s[2] + -- if x < xmin then xmin = x end + -- if x > xmax then xmax = x end + -- if y < ymin then ymin = y end + -- if y > ymax then ymax = y end + -- if s[#s] == "c" then -- "curveto" + -- local x = s[3] + -- local y = s[4] + -- if x < xmin then xmin = x elseif x > xmax then xmax = x end + -- if y < ymin then ymin = y elseif y > ymax then ymax = y end + -- local x = s[5] + -- local y = s[6] + -- if x < xmin then xmin = x elseif x > xmax then xmax = x end + -- if y < ymin then ymin = y elseif y > ymax then ymax = y end + -- end + -- end + -- return { round(xmin), round(ymin), round(xmax), round(ymax) } -- doesn't make ceil more sense + -- end + -- end + + local function setbias(globals,locals,nobias) + if nobias then + return 0, 0 + else + local g = #globals + local l = #locals + return + ((g < 1240 and 107) or (g < 33900 and 1131) or 32768) + 1, + ((l < 1240 and 107) or (l < 33900 and 1131) or 32768) + 1 + end + end + + local function processshape(glyphs,tab,index,hack) + + if not tab then + glyphs[index] = { + boundingbox = { 0, 0, 0, 0 }, + width = 0, + name = charset and charset[index] or nil, + } + return + end + + tab = bytetable(tab) + + x = 0 + y = 0 + width = false + lsb = 0 + r = 0 + top = 0 + stems = 0 + result = { } -- we could reuse it when only boundingbox calculations are needed + popped = 3 + procidx = index + + xmin = 0 + xmax = 0 + ymin = 0 + ymax = 0 + checked = false + if trace_charstrings then + report("glyph: %i",index) + report("data : % t",tab) + end + + if regions then + updateregions(vsindex) + end + + process(tab) + if hack then + return x, y + end + + local boundingbox = { + round(xmin), + round(ymin), + round(xmax), + round(ymax), + } + + if width == true or width == false then + width = defaultwidth + else + width = nominalwidth + width + end + + local glyph = glyphs[index] -- can be autodefined in otr + if justpass then + r = r + 1 + result[r] = c_endchar + local stream = concat(result) +result = nil + -- if trace_charstrings then + -- report("vdata: %s",stream) + -- end + if glyph then + glyph.stream = stream + glyph.width = width + else + glyphs[index] = { stream = stream, width = width } + end + elseif glyph then + glyph.segments = keepcurve ~= false and result or nil + glyph.boundingbox = boundingbox + if not glyph.width then + glyph.width = width + end + if charset and not glyph.name then + glyph.name = charset[index] + end + -- glyph.sidebearing = 0 -- todo + elseif keepcurve then + glyphs[index] = { + segments = result, + boundingbox = boundingbox, + width = width, + name = charset and charset[index] or nil, + -- sidebearing = 0, + } +result = nil + else + glyphs[index] = { + boundingbox = boundingbox, + width = width, + name = charset and charset[index] or nil, + } + end + if trace_charstrings then + report("width : %s",tostring(width)) + report("boundingbox: % t",boundingbox) + end + + end + + startparsing = function(fontdata,data,streams) + reginit = false + axis = false + regions = data.regions + justpass = streams == true + popped = 3 + seacs = { } + if regions then + -- this was: + -- regions = { regions } -- needs checking + -- and is now (MFC): + regions = { } + local deltas = data.deltas + for i = 1, #deltas do + regions[i] = deltas[i].regions + end + axis = data.factors or false + end + end + + stopparsing = function(fontdata,data) + stack = { } + glyphs = false + result = { } + top = 0 + locals = false + globals = false + strings = false + popped = 3 + seacs = { } + end + + local function setwidths(private) + if not private then + return 0, 0 + end + local privatedata = private.data + if not privatedata then + return 0, 0 + end + return privatedata.nominalwidthx or 0, privatedata.defaultwidthx or 0 + end + + parsecharstrings = function(fontdata,data,glphs,doshapes,tversion,streams,nobias,istypeone) + + local dictionary = data.dictionaries[1] + local charstrings = dictionary.charstrings + + keepcurve = doshapes + version = tversion + typeone = istypeone or false + strings = data.strings + globals = data.routines or { } + locals = dictionary.subroutines or { } + charset = dictionary.charset + vsindex = dictionary.vsindex or 0 + + local glyphs = glphs or { } + + globalbias, localbias = setbias(globals,locals,nobias) + nominalwidth, defaultwidth = setwidths(dictionary.private) + + if charstrings then + startparsing(fontdata,data,streams) + for index=1,#charstrings do + processshape(glyphs,charstrings[index],index-1) + end + if justpass and next(seacs) then + -- old type 1 stuff ... seacs + local charset = data.dictionaries[1].charset + if charset then + local lookup = table.swapped(charset) + for index, v in next, seacs do + local bindex = lookup[standardnames[v.base]] + local aindex = lookup[standardnames[v.accent]] + local bglyph = bindex and glyphs[bindex] + local aglyph = aindex and glyphs[aindex] + if bglyph and aglyph then + -- this is a real ugly hack but we seldom enter this branch (e.g. old lbr) + local jp = justpass + justpass = false + local x, y = processshape(glyphs,charstrings[bindex+1],bindex,true) + justpass = jp + -- + local base = bglyph.stream + local accent = aglyph.stream + local moveto = encode[-x-v.asb+v.adx] .. chars[22] + .. encode[-y +v.ady] .. chars[ 4] + -- prune an endchar + base = sub(base,1,#base-1) + -- combine them + glyphs[index].stream = base .. moveto .. accent + end + end + end + end + stopparsing(fontdata,data) + else + report("no charstrings") + end + return glyphs + end + + parsecharstring = function(fontdata,data,dictionary,tab,glphs,index,doshapes,tversion,streams) + + keepcurve = doshapes + version = tversion + strings = data.strings + globals = data.routines or { } + locals = dictionary.subroutines or { } + charset = false + vsindex = dictionary.vsindex or 0 + + local glyphs = glphs or { } + + justpass = streams == true + seacs = { } + + globalbias, localbias = setbias(globals,locals,nobias) + nominalwidth, defaultwidth = setwidths(dictionary.private) + + processshape(glyphs,tab,index-1) + + return glyphs[index] + end + +end + +local function readglobals(f,data,version) + local routines = readlengths(f,version == "cff2") + for i=1,#routines do + routines[i] = readbytetable(f,routines[i]) + end + data.routines = routines +end + +local function readencodings(f,data) + data.encodings = { } +end + +local function readcharsets(f,data,dictionary) + local header = data.header + local strings = data.strings + local nofglyphs = data.nofglyphs + local charsetoffset = dictionary.charset + if charsetoffset and charsetoffset ~= 0 then + setposition(f,header.offset+charsetoffset) + local format = readbyte(f) + local charset = { [0] = ".notdef" } + dictionary.charset = charset + if format == 0 then + for i=1,nofglyphs do + charset[i] = strings[readushort(f)] + end + elseif format == 1 or format == 2 then + local readcount = format == 1 and readbyte or readushort + local i = 1 + while i <= nofglyphs do + local sid = readushort(f) + local n = readcount(f) + for s=sid,sid+n do + charset[i] = strings[s] + i = i + 1 + if i > nofglyphs then + break + end + end + end + else + report("cff parser: unsupported charset format %a",format) + end + else + dictionary.nocharset = true + dictionary.charset = nil + end +end + +local function readprivates(f,data) + local header = data.header + local dictionaries = data.dictionaries + local private = dictionaries[1].private + if private then + setposition(f,header.offset+private.offset) + private.data = readstring(f,private.size) + end +end + +local function readlocals(f,data,dictionary,version) + local header = data.header + local private = dictionary.private + if private then + local subroutineoffset = private.data.subroutines + if subroutineoffset ~= 0 then + setposition(f,header.offset+private.offset+subroutineoffset) + local subroutines = readlengths(f,version == "cff2") + for i=1,#subroutines do + subroutines[i] = readbytetable(f,subroutines[i]) + end + dictionary.subroutines = subroutines + private.data.subroutines = nil + else + dictionary.subroutines = { } + end + else + dictionary.subroutines = { } + end +end + +-- These charstrings are little programs and described in: Technical Note #5177. A truetype +-- font has only one dictionary. + +local function readcharstrings(f,data,version) + local header = data.header + local dictionaries = data.dictionaries + local dictionary = dictionaries[1] + local stringtype = dictionary.charstringtype + local offset = dictionary.charstrings + if type(offset) ~= "number" then + -- weird + elseif stringtype == 2 then + setposition(f,header.offset+offset) + -- could be a metatable .. delayed loading + local charstrings = readlengths(f,version=="cff2") + local nofglyphs = #charstrings + for i=1,nofglyphs do + charstrings[i] = readstring(f,charstrings[i]) + end + data.nofglyphs = nofglyphs + dictionary.charstrings = charstrings + else + report("unsupported charstr type %i",stringtype) + data.nofglyphs = 0 + dictionary.charstrings = { } + end +end + +-- cid (maybe do this stepwise so less mem) -- share with above + +local function readcidprivates(f,data) + local header = data.header + local dictionaries = data.dictionaries[1].cid.dictionaries + for i=1,#dictionaries do + local dictionary = dictionaries[i] + local private = dictionary.private + if private then + setposition(f,header.offset+private.offset) + private.data = readstring(f,private.size) + end + end + parseprivates(data,dictionaries) +end + +readers.parsecharstrings = parsecharstrings -- used in font-onr.lua (type 1) + +local function readnoselect(f,fontdata,data,glyphs,doshapes,version,streams) + local dictionaries = data.dictionaries + local dictionary = dictionaries[1] + local cid = not dictionary.private and dictionary.cid + readglobals(f,data,version) + readcharstrings(f,data,version) + if version == "cff2" then + dictionary.charset = nil + else + readencodings(f,data) + readcharsets(f,data,dictionary) + end + if cid then + local fdarray = cid.fdarray + if fdarray then + setposition(f,data.header.offset + fdarray) + local dictionaries = readlengths(f,version=="cff2") + local nofdictionaries = #dictionaries + if nofdictionaries > 0 then + for i=1,nofdictionaries do + dictionaries[i] = readstring(f,dictionaries[i]) + end + parsedictionaries(data,dictionaries) + dictionary.private = dictionaries[1].private + if nofdictionaries > 1 then + report("ignoring dictionaries > 1 in cid font") + end + end + end + end + readprivates(f,data) + parseprivates(data,data.dictionaries) + readlocals(f,data,dictionary,version) + startparsing(fontdata,data,streams) + parsecharstrings(fontdata,data,glyphs,doshapes,version,streams,false) + stopparsing(fontdata,data) +end + +local function readfdselect(f,fontdata,data,glyphs,doshapes,version,streams) + local header = data.header + local dictionaries = data.dictionaries + local dictionary = dictionaries[1] + local cid = dictionary.cid + local cidselect = cid and cid.fdselect + readglobals(f,data,version) + readcharstrings(f,data,version) + if version ~= "cff2" then + readencodings(f,data) + end + local charstrings = dictionary.charstrings + local fdindex = { } + local nofglyphs = data.nofglyphs + local maxindex = -1 + setposition(f,header.offset+cidselect) + local format = readbyte(f) + if format == 1 then + for i=0,nofglyphs do -- notdef included (needs checking) + local index = readbyte(f) + fdindex[i] = index + if index > maxindex then + maxindex = index + end + end + elseif format == 3 then + local nofranges = readushort(f) + local first = readushort(f) + local index = readbyte(f) + while true do + local last = readushort(f) + if index > maxindex then + maxindex = index + end + for i=first,last do + fdindex[i] = index + end + if last >= nofglyphs then + break + else + first = last + 1 + index = readbyte(f) + end + end + else + report("unsupported fd index format %i",format) + end + -- hm, always + if maxindex >= 0 then + local cidarray = cid.fdarray + if cidarray then + setposition(f,header.offset+cidarray) + local dictionaries = readlengths(f,version == "cff2") + if #dictionaries > 0 then + for i=1,#dictionaries do + dictionaries[i] = readstring(f,dictionaries[i]) + end + parsedictionaries(data,dictionaries) + cid.dictionaries = dictionaries + readcidprivates(f,data) + for i=1,#dictionaries do + readlocals(f,data,dictionaries[i],version) + end + startparsing(fontdata,data,streams) + for i=1,#charstrings do + local dictionary = dictionaries[fdindex[i]+1] + if dictionary then + parsecharstring(fontdata,data,dictionary,charstrings[i],glyphs,i,doshapes,version,streams) + else + -- report("no dictionary for %a : %a => %a",version,i,fdindex[i]+1) + end + -- charstrings[i] = false + end + stopparsing(fontdata,data) + else + report("no cid dictionaries") + end + else + report("no cid array") + end + end +end + +local gotodatatable = readers.helpers.gotodatatable + +local function cleanup(data,dictionaries) + -- for i=1,#dictionaries do + -- local d = dictionaries[i] + -- d.subroutines = nil + -- end + -- data.strings = nil + -- if data then + -- data.charstrings = nil + -- data.routines = nil + -- end +end + +function readers.cff(f,fontdata,specification) + local tableoffset = gotodatatable(f,fontdata,"cff",specification.details or specification.glyphs) + if tableoffset then + local header = readheader(f) + if header.major ~= 1 then + report("only version %s is supported for table %a",1,"cff") + return + end + local glyphs = fontdata.glyphs + local names = readfontnames(f) + local dictionaries = readtopdictionaries(f) + local strings = readstrings(f) + local data = { + header = header, + names = names, + dictionaries = dictionaries, + strings = strings, + nofglyphs = fontdata.nofglyphs, + } + -- + parsedictionaries(data,dictionaries,"cff") + -- + local dic = dictionaries[1] + local cid = dic.cid + -- + local cffinfo = { + familyname = dic.familyname, + fullname = dic.fullname, + boundingbox = dic.boundingbox, + weight = dic.weight, + italicangle = dic.italicangle, + underlineposition = dic.underlineposition, + underlinethickness = dic.underlinethickness, + defaultwidth = dic.defaultwidthx, + nominalwidth = dic.nominalwidthx, + monospaced = dic.monospaced, + } + fontdata.cidinfo = cid and { + registry = cid.registry, + ordering = cid.ordering, + supplement = cid.supplement, + } + fontdata.cffinfo = cffinfo + -- + local all = specification.shapes or specification.streams or false + if specification.glyphs or all then + if cid and cid.fdselect then + readfdselect(f,fontdata,data,glyphs,all,"cff",specification.streams) + else + readnoselect(f,fontdata,data,glyphs,all,"cff",specification.streams) + end + end + local private = dic.private + if private then + local data = private.data + if type(data) == "table" then + cffinfo.defaultwidth = data.defaultwidthx or cffinfo.defaultwidth + cffinfo.nominalwidth = data.nominalwidthx or cffinfo.nominalwidth + cffinfo.bluevalues = data.bluevalues + cffinfo.otherblues = data.otherblues + cffinfo.familyblues = data.familyblues + cffinfo.familyotherblues = data.familyotherblues + cffinfo.bluescale = data.bluescale + cffinfo.blueshift = data.blueshift + cffinfo.bluefuzz = data.bluefuzz + cffinfo.stdhw = data.stdhw + cffinfo.stdvw = data.stdvw + cffinfo.stemsnaph = data.stemsnaph + cffinfo.stemsnapv = data.stemsnapv + end + end + cleanup(data,dictionaries) + end +end + +function readers.cff2(f,fontdata,specification) + local tableoffset = gotodatatable(f,fontdata,"cff2",specification.glyphs) + if tableoffset then + local header = readheader(f) + if header.major ~= 2 then + report("only version %s is supported for table %a",2,"cff2") + return + end + local glyphs = fontdata.glyphs + local dictionaries = { readstring(f,header.dsize) } + local data = { + header = header, + dictionaries = dictionaries, + nofglyphs = fontdata.nofglyphs, + } + -- + parsedictionaries(data,dictionaries,"cff2") + -- + local offset = dictionaries[1].vstore + if offset > 0 then + local storeoffset = dictionaries[1].vstore + data.header.offset + 2 -- cff has a preceding size field + local regions, deltas = readers.helpers.readvariationdata(f,storeoffset,factors) + -- + data.regions = regions + data.deltas = deltas + else + data.regions = { } + data.deltas = { } + end + data.factors = specification.factors + -- + local cid = data.dictionaries[1].cid + local all = specification.shapes or specification.streams or false + if cid and cid.fdselect then + readfdselect(f,fontdata,data,glyphs,all,"cff2",specification.streams) + else + readnoselect(f,fontdata,data,glyphs,all,"cff2",specification.streams) + end + cleanup(data,dictionaries) + end +end + +-- temporary helper needed for checking backend patches + +-- function readers.cffcheck(filename) +-- local f = io.open(filename,"rb") +-- if f then +-- local fontdata = { +-- glyphs = { }, +-- } +-- local header = readheader(f) +-- if header.major ~= 1 then +-- report("only version %s is supported for table %a",1,"cff") +-- return +-- end +-- local names = readfontnames(f) +-- local dictionaries = readtopdictionaries(f) +-- local strings = readstrings(f) +-- local glyphs = { } +-- local data = { +-- header = header, +-- names = names, +-- dictionaries = dictionaries, +-- strings = strings, +-- glyphs = glyphs, +-- nofglyphs = 0, +-- } +-- -- +-- parsedictionaries(data,dictionaries,"cff") +-- -- +-- local cid = data.dictionaries[1].cid +-- if cid and cid.fdselect then +-- readfdselect(f,fontdata,data,glyphs,false) +-- else +-- readnoselect(f,fontdata,data,glyphs,false) +-- end +-- return data +-- end +-- end diff --git a/tex/context/base/mkxl/font-dsp.lmt b/tex/context/base/mkxl/font-dsp.lmt index 1b54bf463..a1bf6f641 100644 --- a/tex/context/base/mkxl/font-dsp.lmt +++ b/tex/context/base/mkxl/font-dsp.lmt @@ -56,11 +56,6 @@ if not modules then modules = { } end modules ['font-dsp'] = { -- less code. After all there are often not that many demanding features. local next, type, tonumber = next, type, tonumber -local band = bit32.band -local extract = bit32.extract -local bor = bit32.bor -local lshift = bit32.lshift -local rshift = bit32.rshift local gsub = string.gsub local lower = string.lower local sub = string.sub @@ -298,7 +293,7 @@ local lookupnames = { -- local lookupstate = setmetatableindex(function(t,k) -- local v = { } -- for kk, vv in next, lookupbits do --- if band(k,kk) ~= 0 then +-- if (k & kk) ~= 0 then -- v[vv] = true -- end -- end @@ -308,10 +303,10 @@ local lookupnames = { local lookupflags = setmetatableindex(function(t,k) local v = { - band(k,0x0008) ~= 0 and true or false, -- ignoremarks - band(k,0x0004) ~= 0 and true or false, -- ignoreligatures - band(k,0x0002) ~= 0 and true or false, -- ignorebaseglyphs - band(k,0x0001) ~= 0 and true or false, -- r2l + (k & 0x0008) ~= 0 and true or false, -- ignoremarks + (k & 0x0004) ~= 0 and true or false, -- ignoreligatures + (k & 0x0002) ~= 0 and true or false, -- ignorebaseglyphs + (k & 0x0001) ~= 0 and true or false, -- r2l } t[k] = v return v @@ -751,16 +746,17 @@ local function readposition(f,format,mainoffset,getdelta) -- .... -- end -- - local x = band(format,0x1) ~= 0 and readshort(f) or 0 -- x placement - local y = band(format,0x2) ~= 0 and readshort(f) or 0 -- y placement - local h = band(format,0x4) ~= 0 and readshort(f) or 0 -- h advance - local v = band(format,0x8) ~= 0 and readshort(f) or 0 -- v advance + local x = (format & 0x1) ~= 0 and readshort(f) or 0 -- x placement + local y = (format & 0x2) ~= 0 and readshort(f) or 0 -- y placement + local h = (format & 0x4) ~= 0 and readshort(f) or 0 -- h advance + local v = (format & 0x8) ~= 0 and readshort(f) or 0 -- v advance if format >= 0x10 then - local X = band(format,0x10) ~= 0 and skipshort(f) or 0 - local Y = band(format,0x20) ~= 0 and skipshort(f) or 0 - local H = band(format,0x40) ~= 0 and skipshort(f) or 0 - local V = band(format,0x80) ~= 0 and skipshort(f) or 0 - local s = skips[extract(format,4,4)] + local X = (format & 0x10) ~= 0 and skipshort(f) or 0 + local Y = (format & 0x20) ~= 0 and skipshort(f) or 0 + local H = (format & 0x40) ~= 0 and skipshort(f) or 0 + local V = (format & 0x80) ~= 0 and skipshort(f) or 0 + -- local s = skips[extract(format,4,4)] + local s = skips[(format >> 4) & 0xF] if s > 0 then skipshort(f,s) end @@ -2159,11 +2155,12 @@ do subtables[j] = offset + readushort(f) -- we can probably put lookupoffset here end -- which one wins? - local markclass = band(flagbits,0x0010) ~= 0 -- usemarkfilteringset + local markclass = (flagbits & 0x0010) ~= 0 -- usemarkfilteringset if markclass then markclass = readushort(f) -- + 1 end - local markset = rshift(flagbits,8) + -- local markset = rshift(flagbits,8) + local markset = (flagbits >> 8) & 0xFFFFFFFF if markset > 0 then markclass = markset -- + 1 end @@ -2607,7 +2604,8 @@ do local length = readushort(f) local coverage = readushort(f) -- bit 8-15 of coverage: format 0 or 2 - local format = rshift(coverage,8) -- is this ok + -- local format = rshift(coverage,8) -- is this ok + local format = (coverage >> 8) & 0xFFFFFFFF -- is this ok if format == 0 then local nofpairs = readushort(f) local searchrange = readushort(f) @@ -3051,7 +3049,7 @@ local function readmathvariants(f,fontdata,offset) advance = readushort(f), } local flags = readushort(f) - if band(flags,0x0001) ~= 0 then + if (flags & 0x0001) ~= 0 then p.extender = 1 -- true end parts[i] = p @@ -4533,16 +4531,19 @@ local function calculate(f,fontdata,specification,offset,field,regions,deltas,no setposition(f,offset) local format = readushort(f) -- todo: check local mapcount = readushort(f) - local entrysize = rshift(band(format,0x0030),4) + 1 - local nofinnerbits = band(format,0x000F) + 1 -- n of inner bits - local innermask = lshift(1,nofinnerbits) - 1 + -- local entrysize = rshift(band(format,0x0030),4) + 1 + local entrysize = (((format & 0x0030) >> 4) & 0xFFFFFFFF) + 1 + local nofinnerbits = (format & 0x000F) + 1 -- n of inner bits + -- local innermask = lshift(1,nofinnerbits) - 1 + local innermask = (1 << nofinnerbits) - 1 local readcardinal = read_cardinal[entrysize] -- 1 upto 4 bytes local innerindex = { } -- size is mapcount local outerindex = { } -- size is mapcount for i=0,mapcount-1 do local mapdata = readcardinal(f) - outerindex[i] = rshift(mapdata,nofinnerbits) - innerindex[i] = band(mapdata,innermask) + -- outerindex[i] = rshift(mapdata,nofinnerbits) + outerindex[i] = (mapdata >> nofinnerbits) & 0xFFFFFFFF + innerindex[i] = (mapdata & innermask) end -- use last entry when no match i setvariabledata(fontdata,"hvarwidths",true) diff --git a/tex/context/base/mkxl/font-lib.mklx b/tex/context/base/mkxl/font-lib.mklx index cf6b51102..6caf1daf8 100644 --- a/tex/context/base/mkxl/font-lib.mklx +++ b/tex/context/base/mkxl/font-lib.mklx @@ -35,30 +35,29 @@ \registerctxluafile{font-fmp}{autosuffix} \registerctxluafile{font-agl}{} % if needed we can comment this and delay loading \registerctxluafile{font-cid}{} % cid maps -\registerctxluafile{font-map}{optimize} +\registerctxluafile{font-map}{} % helpers -\registerctxluafile{font-otr}{optimize} % opentype fontloader +\registerctxluafile{font-otr}{} % opentype fontloader \registerctxluafile{font-web}{} % opentype fontloader -\registerctxluafile{font-cff}{optimize} % quadratic outlines -\registerctxluafile{font-ttf}{optimize} % cubic outlines -\registerctxluafile{font-dsp}{autosuffix,optimize} +\registerctxluafile{font-cff}{autosuffix} % quadratic outlines +\registerctxluafile{font-ttf}{autosuffix} % cubic outlines +\registerctxluafile{font-dsp}{autosuffix} \registerctxluafile{font-hsh}{autosuffix} % hashes used by context \registerctxluafile{font-vfc}{autosuffix} \registerctxluafile{font-prv}{} % needs hashes \registerctxluafile{font-vir}{} -\registerctxluafile{font-nod}{optimize} +\registerctxluafile{font-nod}{} \registerctxluafile{font-oti}{} % otf initialization \registerctxluafile{font-ott}{} % otf tables (first) \registerctxluafile{font-otl}{autosuffix} \registerctxluafile{font-oto}{} -\registerctxluafile{font-otj}{autosuffix,optimize} +\registerctxluafile{font-otj}{autosuffix} \registerctxluafile{font-oup}{} \registerctxluafile{font-ota}{autosuffix} -%registerctxluafile{font-ots-pre-scale}{autosuffix,optimize} -\registerctxluafile{font-ots}{autosuffix,optimize} -\registerctxluafile{font-otd}{autosuffix,optimize} +\registerctxluafile{font-ots}{autosuffix} +\registerctxluafile{font-otd}{autosuffix} \registerctxluafile{font-otc}{} \registerctxluafile{font-oth}{} % \doifelsefileexists{font-osd-new.lmt}{ @@ -71,15 +70,15 @@ % we use otf code for type one -\registerctxluafile{font-onr}{autosuffix,optimize} -\registerctxluafile{font-one}{autosuffix,optimize} +\registerctxluafile{font-onr}{autosuffix} +\registerctxluafile{font-one}{autosuffix} \registerctxluafile{font-afk}{} \registerctxluafile{font-txt}{autosuffix} % tfm -\registerctxluafile{font-tpk}{autosuffix,optimize} +\registerctxluafile{font-tpk}{autosuffix} \registerctxluafile{font-tfm}{autosuffix} % name database diff --git a/tex/context/base/mkxl/font-map.lmt b/tex/context/base/mkxl/font-map.lmt new file mode 100644 index 000000000..be1321384 --- /dev/null +++ b/tex/context/base/mkxl/font-map.lmt @@ -0,0 +1,518 @@ +if not modules then modules = { } end modules ['font-map'] = { + version = 1.001, + optimize = true, + 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 tonumber, next, type = tonumber, next, type + +local match, format, find, concat, gsub, lower = string.match, string.format, string.find, table.concat, string.gsub, string.lower +local P, R, S, C, Ct, Cc, lpegmatch = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.match +local formatters = string.formatters +local sortedhash, sortedkeys = table.sortedhash, table.sortedkeys + +local trace_loading = false trackers.register("fonts.loading", function(v) trace_loading = v end) +local trace_mapping = false trackers.register("fonts.mapping", function(v) trace_mapping = v end) + +local report_fonts = logs.reporter("fonts","loading") -- not otf only + +-- force_ligatures was true for a while so that these emoji's with bad names work too + +local force_ligatures = false directives.register("fonts.mapping.forceligatures",function(v) force_ligatures = v end) + +local fonts = fonts or { } +local mappings = fonts.mappings or { } +fonts.mappings = mappings + +local allocate = utilities.storage.allocate + +local hex = R("AF","af","09") +local hexfour = (hex*hex*hex^-2) / function(s) return tonumber(s,16) end +local hexsix = (hex*hex*hex^-4) / function(s) return tonumber(s,16) end +local dec = (R("09")^1) / tonumber +local period = P(".") +local unicode = (P("uni") + P("UNI")) * (hexfour * (period + P(-1)) * Cc(false) + Ct(hexfour^1) * Cc(true)) -- base planes +local ucode = (P("u") + P("U") ) * (hexsix * (period + P(-1)) * Cc(false) + Ct(hexsix ^1) * Cc(true)) -- extended +local index = P("index") * dec * Cc(false) + +local parser = unicode + ucode + index +local parsers = { } + +local function makenameparser(str) + if not str or str == "" then + return parser + else + local p = parsers[str] + if not p then + p = P(str) * period * dec * Cc(false) + parsers[str] = p + end + return p + end +end + +local f_single = formatters["%04X"] +local f_double = formatters["%04X%04X"] +local s_unknown = "FFFD" + +local function tounicode16(unicode) + if unicode < 0xD7FF or (unicode > 0xDFFF and unicode <= 0xFFFF) then + return f_single(unicode) + elseif unicode >= 0x00E000 and unicode <= 0x00F8FF then + return s_unknown + elseif unicode >= 0x0F0000 and unicode <= 0x0FFFFF then + return s_unknown + elseif unicode >= 0x100000 and unicode <= 0x10FFFF then + return s_unknown + elseif unicode >= 0x00D800 and unicode <= 0x00DFFF then + return s_unknown + else + unicode = unicode - 0x10000 + return f_double((k//0x400)+0xD800,unicode%0x400+0xDC00) + end +end + +local function tounicode16sequence(unicodes) + local t = { } + for l=1,#unicodes do + local u = unicodes[l] + if u < 0xD7FF or (u > 0xDFFF and u <= 0xFFFF) then + t[l] = f_single(u) + elseif unicode >= 0x00E000 and unicode <= 0x00F8FF then + t[l] = s_unknown + elseif unicode >= 0x0F0000 and unicode <= 0x0FFFFF then + t[l] = s_unknown + elseif unicode >= 0x100000 and unicode <= 0x10FFFF then + t[l] = s_unknown + -- elseif unicode >= 0x00D800 and unicode <= 0x00DFFF then + elseif unicode >= 0x00D7FF and unicode <= 0x00DFFF then + t[l] = s_unknown + else + u = u - 0x10000 + t[l] = f_double((k//0x400)+0xD800,u%0x400+0xDC00) + end + end + return concat(t) +end + + +local hash = { } +local conc = { } + +table.setmetatableindex(hash,function(t,k) + local v + if k < 0xD7FF or (k > 0xDFFF and k <= 0xFFFF) then + v = f_single(k) + else + local k = k - 0x10000 + v = f_double((k//0x400)+0xD800,k%0x400+0xDC00) + end + t[k] = v + return v +end) + +local function tounicode(k) + if type(k) == "table" then + local n = #k + for l=1,n do + conc[l] = hash[k[l]] + end + return concat(conc,"",1,n) + elseif k >= 0x00E000 and k <= 0x00F8FF then + return s_unknown + elseif k >= 0x0F0000 and k <= 0x0FFFFF then + return s_unknown + elseif k >= 0x100000 and k <= 0x10FFFF then + return s_unknown + -- elseif k >= 0x00D800 and k <= 0x00DFFF then + elseif k >= 0x00D7FF and k <= 0x00DFFF then + return s_unknown + else + return hash[k] + end +end + +local function fromunicode16(str) + if #str == 4 then + return tonumber(str,16) + else + local l, r = match(str,"(....)(....)") + return 0x10000 + (tonumber(l,16)-0xD800)*0x400 + tonumber(r,16) - 0xDC00 + end +end + +-- Slightly slower: +-- +-- local p = C(4) * (C(4)^-1) / function(l,r) +-- if r then +-- return (tonumber(l,16))*0x400 + tonumber(r,16) - 0xDC00 +-- else +-- return tonumber(l,16) +-- end +-- end +-- +-- local function fromunicode16(str) +-- return lpegmatch(p,str) +-- end + +mappings.makenameparser = makenameparser +mappings.tounicode = tounicode +mappings.tounicode16 = tounicode16 +mappings.tounicode16sequence = tounicode16sequence +mappings.fromunicode16 = fromunicode16 + +-- mozilla emoji has bad lig names: name = gsub(name,"(u[a-f0-9_]+)%-([a-f0-9_]+)","%1_%2") + +local ligseparator = P("_") +local varseparator = P(".") +local namesplitter = Ct(C((1 - ligseparator - varseparator)^1) * (ligseparator * C((1 - ligseparator - varseparator)^1))^0) + +-- maybe: ff fi fl ffi ffl => f_f f_i f_l f_f_i f_f_l + +-- local function test(name) +-- local split = lpegmatch(namesplitter,name) +-- print(string.formatters["%s: [% t]"](name,split)) +-- end + +-- test("i.f_") +-- test("this") +-- test("this.that") +-- test("japan1.123") +-- test("such_so_more") +-- test("such_so_more.that") + +-- to be completed .. for fonts that use unicodes for ligatures which +-- is a actually a bad thing and should be avoided in the first place + +do + + local overloads = { + IJ = { name = "I_J", unicode = { 0x49, 0x4A }, mess = 0x0132 }, + ij = { name = "i_j", unicode = { 0x69, 0x6A }, mess = 0x0133 }, + ff = { name = "f_f", unicode = { 0x66, 0x66 }, mess = 0xFB00 }, + fi = { name = "f_i", unicode = { 0x66, 0x69 }, mess = 0xFB01 }, + fl = { name = "f_l", unicode = { 0x66, 0x6C }, mess = 0xFB02 }, + ffi = { name = "f_f_i", unicode = { 0x66, 0x66, 0x69 }, mess = 0xFB03 }, + ffl = { name = "f_f_l", unicode = { 0x66, 0x66, 0x6C }, mess = 0xFB04 }, + fj = { name = "f_j", unicode = { 0x66, 0x6A } }, + fk = { name = "f_k", unicode = { 0x66, 0x6B } }, + + -- endash = { name = "endash", unicode = 0x2013, mess = 0x2013 }, + -- emdash = { name = "emdash", unicode = 0x2014, mess = 0x2014 }, + } + + local o = allocate { } + + for k, v in next, overloads do + local name = v.name + local mess = v.mess + if name then + o[name] = v + end + if mess then + o[mess] = v + end + o[k] = v + end + + mappings.overloads = o + +end + +function mappings.addtounicode(data,filename,checklookups,forceligatures) + local resources = data.resources + local unicodes = resources.unicodes + if not unicodes then + if trace_mapping then + report_fonts("no unicode list, quitting tounicode for %a",filename) + end + return + end + local properties = data.properties + local descriptions = data.descriptions + local overloads = mappings.overloads + -- we need to move this code + unicodes['space'] = unicodes['space'] or 32 + unicodes['hyphen'] = unicodes['hyphen'] or 45 + unicodes['zwj'] = unicodes['zwj'] or 0x200D + unicodes['zwnj'] = unicodes['zwnj'] or 0x200C + -- + local private = fonts.constructors and fonts.constructors.privateoffset or 0xF0000 -- 0x10FFFF + local unicodevector = fonts.encodings.agl.unicodes or { } -- loaded runtime in context + local contextvector = fonts.encodings.agl.ctxcodes or { } -- loaded runtime in context + local missing = { } + local nofmissing = 0 + local oparser = nil + local cidnames = nil + local cidcodes = nil + local cidinfo = properties.cidinfo + local usedmap = cidinfo and fonts.cid.getmap(cidinfo) + local uparser = makenameparser() -- hm, every time? + if usedmap then + oparser = usedmap and makenameparser(cidinfo.ordering) + cidnames = usedmap.names + cidcodes = usedmap.unicodes + end + local ns = 0 + local nl = 0 + -- + -- in order to avoid differences between runs due to hash randomization we + -- run over a sorted list + -- + local dlist = sortedkeys(descriptions) + -- + -- for du, glyph in next, descriptions do + for i=1,#dlist do + local du = dlist[i] + local glyph = descriptions[du] + local name = glyph.name + if name then + local overload = overloads[name] or overloads[du] + if overload then + -- get rid of weird ligatures + -- glyph.name = overload.name + glyph.unicode = overload.unicode + else + local gu = glyph.unicode -- can already be set (number or table) + if not gu or gu == -1 or du >= private or (du >= 0xE000 and du <= 0xF8FF) or du == 0xFFFE or du == 0xFFFF then + local unicode = unicodevector[name] or contextvector[name] + if unicode then + glyph.unicode = unicode + ns = ns + 1 + end + -- cidmap heuristics, beware, there is no guarantee for a match unless + -- the chain resolves + if (not unicode) and usedmap then + local foundindex = lpegmatch(oparser,name) + if foundindex then + unicode = cidcodes[foundindex] -- name to number + if unicode then + glyph.unicode = unicode + ns = ns + 1 + else + local reference = cidnames[foundindex] -- number to name + if reference then + local foundindex = lpegmatch(oparser,reference) + if foundindex then + unicode = cidcodes[foundindex] + if unicode then + glyph.unicode = unicode + ns = ns + 1 + end + end + if not unicode or unicode == "" then + local foundcodes, multiple = lpegmatch(uparser,reference) + if foundcodes then + glyph.unicode = foundcodes + if multiple then + nl = nl + 1 + unicode = true + else + ns = ns + 1 + unicode = foundcodes + end + end + end + end + end + end + end + -- a.whatever or a_b_c.whatever or a_b_c (no numbers) a.b_ + -- + -- It is not trivial to find a solution that suits all fonts. We tried several alternatives + -- and this one seems to work reasonable also with fonts that use less standardized naming + -- schemes. The extra private test is tested by KE and seems to work okay with non-typical + -- fonts as well. + -- + if not unicode or unicode == "" then + local split = lpegmatch(namesplitter,name) + local nsplit = split and #split or 0 -- add if + if nsplit == 0 then + -- skip + elseif nsplit == 1 then + local base = split[1] + local u = unicodes[base] or unicodevector[base] or contextvector[name] + if not u then + -- skip + elseif type(u) == "table" then + -- unlikely + if u[1] < private then + unicode = u + glyph.unicode = unicode + end + elseif u < private then + unicode = u + glyph.unicode = unicode + end + else + local t = { } + local n = 0 + for l=1,nsplit do + local base = split[l] + local u = unicodes[base] or unicodevector[base] or contextvector[name] + if not u then + break + elseif type(u) == "table" then + if u[1] >= private then + break + end + n = n + 1 + t[n] = u[1] + else + if u >= private then + break + end + n = n + 1 + t[n] = u + end + end + if n > 0 then + if n == 1 then + unicode = t[1] + else + unicode = t + end + glyph.unicode = unicode + end + end + nl = nl + 1 + end + -- last resort (we might need to catch private here as well) + if not unicode or unicode == "" then + local foundcodes, multiple = lpegmatch(uparser,name) + if foundcodes then + glyph.unicode = foundcodes + if multiple then + nl = nl + 1 + unicode = true + else + ns = ns + 1 + unicode = foundcodes + end + end + end + -- check using substitutes and alternates + local r = overloads[unicode] + if r then + unicode = r.unicode + glyph.unicode = unicode + end + -- + if not unicode then + missing[du] = true + nofmissing = nofmissing + 1 + end + else + -- maybe a message or so + end + end + else + local overload = overloads[du] + if overload then + glyph.unicode = overload.unicode + elseif not glyph.unicode then + missing[du] = true + nofmissing = nofmissing + 1 + end + end + end + if type(checklookups) == "function" then + checklookups(data,missing,nofmissing) + end + + local unicoded = 0 + local collected = fonts.handlers.otf.readers.getcomponents(data) -- neglectable overhead + + local function resolve(glyph,u) + local n = #u + for i=1,n do + if u[i] > private then + n = 0 + break + end + end + if n > 0 then + if n > 1 then + glyph.unicode = u + else + glyph.unicode = u[1] + end + unicoded = unicoded + 1 + end + end + + if not collected then + -- move on + elseif forceligatures or force_ligatures then + for i=1,#dlist do + local du = dlist[i] + if du >= private or (du >= 0xE000 and du <= 0xF8FF) then + local u = collected[du] -- always tables + if u then + resolve(descriptions[du],u) + end + end + end + else + for i=1,#dlist do + local du = dlist[i] + if du >= private or (du >= 0xE000 and du <= 0xF8FF) then + local glyph = descriptions[du] + if glyph.class == "ligature" and not glyph.unicode then + local u = collected[du] -- always tables + if u then + resolve(glyph,u) + end + end + end + end + end + + if trace_mapping and unicoded > 0 then + report_fonts("%n ligature tounicode mappings deduced from gsub ligature features",unicoded) + end + if trace_mapping then + -- for unic, glyph in sortedhash(descriptions) do + for i=1,#dlist do + local du = dlist[i] + local glyph = descriptions[du] + local name = glyph.name or "-" + local index = glyph.index or 0 + local unicode = glyph.unicode + if unicode then + if type(unicode) == "table" then + local unicodes = { } + for i=1,#unicode do + unicodes[i] = formatters("%U",unicode[i]) + end + report_fonts("internal slot %U, name %a, unicode %U, tounicode % t",index,name,du,unicodes) + else + report_fonts("internal slot %U, name %a, unicode %U, tounicode %U",index,name,du,unicode) + end + else + report_fonts("internal slot %U, name %a, unicode %U",index,name,du) + end + end + end + if trace_loading and (ns > 0 or nl > 0) then + report_fonts("%s tounicode entries added, ligatures %s",nl+ns,ns) + end +end + +-- local parser = makenameparser("Japan1") +-- local parser = makenameparser() +-- local function test(str) +-- local b, a = lpegmatch(parser,str) +-- print((a and table.serialize(b)) or b) +-- end +-- test("a.sc") +-- test("a") +-- test("uni1234") +-- test("uni1234.xx") +-- test("uni12349876") +-- test("u123400987600") +-- test("index1234") +-- test("Japan1.123") diff --git a/tex/context/base/mkxl/font-onr.lmt b/tex/context/base/mkxl/font-onr.lmt index 2c18f6e89..d28c247df 100644 --- a/tex/context/base/mkxl/font-onr.lmt +++ b/tex/context/base/mkxl/font-onr.lmt @@ -26,7 +26,7 @@ local next, type, tonumber, rawset = next, type, tonumber, rawset local match, lower, gsub, strip, find = string.match, 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 +----- bxor, rshift = bit32.bxor, bit32.rshift local P, S, R, V, Cmt, C, Ct, Cs, Carg, Cf, Cg, Cc = lpeg.P, lpeg.S, lpeg.R, lpeg.V, lpeg.Cmt, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg, lpeg.Cf, lpeg.Cg, lpeg.Cc local lpegmatch, patterns = lpeg.match, lpeg.patterns @@ -68,8 +68,10 @@ do local function step(c) local cipher = byte(c) - local plain = bxor(cipher,rshift(r,8)) - r = ((cipher + r) * c1 + c2) % 65536 + -- local plain = bxor(cipher,rshift(r,8)) + local plain = (cipher ~ ((r >> 8) & 0xFFFFFFFF)) + -- r = ((cipher + r) * c1 + c2) % 65536 + r = ((cipher + r) * c1 + c2) % 0x10000 return char(plain) end diff --git a/tex/context/base/mkxl/font-tpk.lmt b/tex/context/base/mkxl/font-tpk.lmt index d265433c5..fc6789402 100644 --- a/tex/context/base/mkxl/font-tpk.lmt +++ b/tex/context/base/mkxl/font-tpk.lmt @@ -13,8 +13,8 @@ if not modules then modules = { } end modules ['font-tpk'] = { -- luatex. All do things a bit more luaish and errors are of course mine. local next = next -local extract, band, lshift, rshift = bit32.extract, bit32.band, bit32.lshift, bit32.rshift -local idiv = number.idiv +----- extract, band, lshift, rshift = bit32.extract, bit32.band, bit32.lshift, bit32.rshift +----- idiv = number.idiv local char = string.char local concat, insert, remove, copy = table.concat, table.insert, table.remove, table.copy local tobitstring = number.tobitstring @@ -67,20 +67,22 @@ do if bitweight == 0 then bitweight = 16 inputbyte = readbyte(s) - return extract(inputbyte,4,4) + -- return extract(inputbyte,4,4) + return (inputbyte >> 4) & 0xF else bitweight = 0 - return band(inputbyte,15) + return inputbyte & 15 end end local function getbit() -- can be inlined - bitweight = rshift(bitweight,1) + -- bitweight = rshift(bitweight,1) + bitweight = (bitweight >> 1) & 0xFFFFFFFF if bitweight == 0 then -- actually we can check for 1 inputbyte = readbyte(s) bitweight = 128 end - return band(inputbyte,bitweight) + return inputbyte & bitweight end local function pkpackednum() @@ -130,8 +132,8 @@ do local function handlehuge(i,j) while i ~= 0 do - j = lshift(j,4) + getnyb() - -- j = extract(j,8,4) + getnyb() + -- j = lshift(j,4) + getnyb() + j = ((j << 4) & 0xFFFFFFFF) + getnyb() i = i - 1 end remainder = j - 15 + (13 - dynf) * 16 + dynf @@ -153,14 +155,14 @@ do local ysize = glyph.ysize local word = 0 local wordweight = 0 - local wordwidth = idiv(xsize + 15,16) + local wordwidth = (xsize + 15) // 16 local rowsleft = 0 - local turnon = band(flagbyte,8) == 8 and true or false + local turnon = (flagbyte & 8) == 8 and true or false local hbit = 0 local count = 0 -- realfunc = pkpackednum - dynf = idiv(flagbyte,16) + dynf = flagbyte // 16 -- if dynf == 14 then bitweight = 0 @@ -171,7 +173,8 @@ do if getbit() ~= 0 then word = word + wordweight end - wordweight = rshift(wordweight,1) + -- wordweight = rshift(wordweight,1) + wordweight = (wordweight >> 1) & 0xFFFFFFFF if wordweight == 0 then r = r + 1 raster[r] = word @@ -247,8 +250,8 @@ do local rr = { } local r = 0 local s = 0 - local cw = idiv(xsize+ 7, 8) - local rw = idiv(xsize+15,16) + local cw = (xsize+ 7) // 8 + local rw = (xsize+15) // 16 local extra = 2 * rw == cw local b for y=1,ysize do @@ -261,7 +264,8 @@ do if extra then r = r + 1 ; rr[r] = tobitstring(b,16,16) else - r = r + 1 ; rr[r] = tobitstring(extract(b,8+(8-cw),cw),cw,cw) + -- r = r + 1 ; rr[r] = tobitstring(extract(b,8+(8-cw),cw),cw,cw) + r = r + 1 ; rr[r] = tobitstring((b >> (8+(8-cw))) &~ (-1 << cw),cw,cw) end result[y] = concat(rr) end @@ -304,20 +308,23 @@ Q]] ] local result = { } local r = 0 local s = 0 - local cw = idiv(xsize+ 7, 8) - local rw = idiv(xsize+15,16) + local cw = (xsize+ 7) // 8 + local rw = (xsize+15) // 16 local extra = 2 * rw == cw local b for y=1,ysize do for x=1,rw-1 do s = s + 1 ; b = stream[s] - r = r + 1 ; result[r] = char(extract(b,8,8),extract(b,0,8)) + -- r = r + 1 ; result[r] = char(extract(b,8,8),extract(b,0,8)) + r = r + 1 ; result[r] = char((b >> 8) & 0xFF,b & 0xFF) end s = s + 1 ; b = stream[s] if extra then - r = r + 1 ; result[r] = char(extract(b,8,8),extract(b,0,8)) + -- r = r + 1 ; result[r] = char(extract(b,8,8),extract(b,0,8)) + r = r + 1 ; result[r] = char((b >> 8) & 0xFF,b & 0xFF) else - r = r + 1 ; result[r] = char(extract(b,8,8)) + -- r = r + 1 ; result[r] = char(extract(b,8,8)) + r = r + 1 ; result[r] = char((b >> 8) & 0xFF) end end return template(width,llx,lly,urx,ury,xdpi,ydpi,llx,lly,xsize,ysize,result), width @@ -346,10 +353,10 @@ Q]] ] while true do local flagbyte = readcardinal1(s) if flagbyte < 240 then - local c = band(flagbyte,7) + local c = flagbyte & 7 local length, index, width, pixels, xsize, ysize, xoffset, yoffset if c >= 0 and c <= 3 then - length = band(flagbyte,7) * 256 + readcardinal1(s) - 3 + length = (flagbyte & 7) * 256 + readcardinal1(s) - 3 index = readcardinal1(s) width = readinteger3(s) pixels = readcardinal1(s) @@ -364,7 +371,7 @@ Q]] ] yoffset = yoffset - 256 end elseif c >= 4 and c <= 6 then - length = band(flagbyte,3) * 65536 + readcardinal1(s) * 256 + readcardinal1(s) - 4 + length = (flagbyte & 3) * 65536 + readcardinal1(s) * 256 + readcardinal1(s) - 4 index = readcardinal1(s) width = readinteger3(s) pixels = readcardinal2(s) @@ -587,8 +594,9 @@ do end local checksum = readcardinal4(s) local designsize = readcardinal2(s) - designsize = designsize * 256 + readcardinal1(s) - designsize = designsize * 16 + rshift(readcardinal1(s),4) + designsize = designsize * 256 + readcardinal1(s) + -- designsize = designsize * 16 + rshift(readcardinal1(s),4) + designsize = designsize * 16 + (readcardinal1(s) >> 4) if designsize < 0xFFFF then return someerror("weird designsize") end @@ -596,15 +604,17 @@ do local alpha = 16 local z = designsize while z >= 040000000 do - z = rshift(z,1) + -- z = rshift(z,1) + z = (z >> 1) & 0xFFFFFFFF alpha = alpha + alpha end - local beta = idiv(256,alpha) + local beta = 256 // alpha alpha = alpha * z -- local function readscaled() local a, b, c, d = readbytes(s,4) - local n = idiv(rshift(rshift(d*z,8)+c*z,8)+b*z,beta) + -- local n = idiv(rshift(rshift(d*z,8)+c*z,8)+b*z,beta) + local n = (((((((d * z) >> 8) & 0xFFFFFFFF) + c * z) >> 8) & 0xFFFFFFFF) + b * z) // beta if a == 0 then return n elseif a == 255 then @@ -619,7 +629,8 @@ do if a > 127 then a = a - 256 end - return a * 0xFFFFF + b * 0xFFF + c * 0xF + rshift(d,4) + -- return a * 0xFFFFF + b * 0xFFF + c * 0xF + rshift(d,4) + return a * 0xFFFFF + b * 0xFFF + c * 0xF + ((d >> 4) & 0xFFFFFFFF) end -- while lh > 2 do -- can be one-liner @@ -775,11 +786,15 @@ do else width = readcardinal1(s) height = readcardinal1(s) - depth = extract(height,0,4) - height = extract(height,4,4) + -- depth = extract(height,0,4) + depth = height & 0xF + -- height = extract(height,4,4) + height = (height >> 4) & 0xF italic = readcardinal1(s) - tag = extract(italic,0,2) - italic = extract(italic,2,6) + -- tag = extract(italic,0,2) + tag = italic & 0x03 + -- italic = extract(italic,2,6) + italic = (italic >> 2) & 0xFF remainder = readcardinal1(s) end if width == 0 then @@ -964,7 +979,7 @@ do local function scaled2() local a, b = readbytes(s,2) - local sw = idiv(b*z,beta) + local sw = (b*z) // beta if a == 0 then return sw elseif a == 255 then @@ -976,7 +991,8 @@ do local function scaled3() local a, b, c = readbytes(s,3) - local sw = idiv(rshift(c*z,8)+b*z,beta) + -- local sw = idiv(rshift(c*z,8)+b*z,beta) + local sw = ((((c * z) >> 8) & 0xFFFFFFFF) + b * z) // beta if a == 0 then return sw elseif a == 255 then @@ -988,7 +1004,8 @@ do local function scaled4() local a, b, c, d = readbytes(s,4) - local sw = idiv( rshift(rshift(d*z,8)+(c*z),8)+b*z,beta) + -- local sw = idiv( rshift(rshift(d*z,8)+(c*z),8)+b*z,beta) + local sw = (((((d * z) >> 8) & 0xFFFFFFFF + (c * z)) >> 8) & 0xFFFFFFFF + b * z) // beta if a == 0 then return sw elseif a == 255 then @@ -1162,17 +1179,18 @@ do end local header = readstring(s,readcardinal1(s)) local checksum = readcardinal4(s) - local designsize = idiv(readcardinal4(s),16) + local designsize = readcardinal4(s) // 16 local fonts = data and data.fonts or { } local glyphs = data and data.glyphs or { } -- alpha = 16 z = designsize while z >= 040000000 do - z = rshift(z,1) + -- z = rshift(z,1) + z = (z >> 1) & 0xFFFFFFFF alpha = alpha + alpha end - beta = idiv(256,alpha) + beta = 256 // alpha alpha = alpha * z -- cmd = readcardinal1(s) @@ -1191,7 +1209,7 @@ do end local checksum = skipbytes(s,4) local size = scaled4() - local designsize = idiv(readcardinal4(s),16) + local designsize = readcardinal4(s) // 16 local pathlen = readcardinal1(s) local namelen = readcardinal1(s) local path = readstring(s,pathlen) @@ -1267,7 +1285,7 @@ do local vffile = resolvers.findbinfile(vfname,"ovf") if tfmfile and tfmfile ~= "" then if size < 0 then - size = idiv(65536 * -size,100) + size = (65536 * -size) // 100 end local data = readers.loadtfm(tfmfile) if data.error then diff --git a/tex/context/base/mkxl/font-ttf.lmt b/tex/context/base/mkxl/font-ttf.lmt new file mode 100644 index 000000000..fa0e3c494 --- /dev/null +++ b/tex/context/base/mkxl/font-ttf.lmt @@ -0,0 +1,1496 @@ +if not modules then modules = { } end modules ['font-ttf'] = { + version = 1.001, + optimize = true, + 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" +} + +-- This version is different from previous in the sense that we no longer store +-- contours but keep points and contours (endpoints) separate for a while +-- because later on we need to apply deltas and that is easier on a list of +-- points. + +-- The code is a bit messy. I looked at the ff code but it's messy too. It has +-- to do with the fact that we need to look at points on the curve and control +-- points in between. This also means that we start at point 2 and have to look +-- at point 1 when we're at the end. We still use a ps like storage with the +-- operator last in an entry. It's typical code that evolves stepwise till a +-- point of no comprehension. + +-- For deltas we need a rather complex loop over points that can have holes and +-- be less than nofpoints and even can have duplicates and also the x and y value +-- lists can be shorter than etc. I need fonts in order to complete this simply +-- because I need to visualize in order to understand (what the standard tries +-- to explain). + +-- 0 point then none applied +-- 1 points then applied to all +-- otherwise inferred deltas using nearest +-- if no lower point then use highest referenced point +-- if no higher point then use lowest referenced point +-- factor = (target-left)/(right-left) +-- delta = (1-factor)*left + factor * right + +local next, type, unpack = next, type, unpack +----- band, rshift = bit32.band, bit32.rshift +local sqrt, round, abs, min, max = math.sqrt, math.round, math.abs, math.min, math.max +local char, rep = string.char, string.rep +local concat = table.concat +local setmetatableindex = table.setmetatableindex + +local report = logs.reporter("otf reader","ttf") + +local trace_deltas = false + +local readers = fonts.handlers.otf.readers +local streamreader = readers.streamreader + +local setposition = streamreader.setposition +local getposition = streamreader.getposition +local skipbytes = streamreader.skip +local readbyte = streamreader.readcardinal1 -- 8-bit unsigned integer +local readushort = streamreader.readcardinal2 -- 16-bit unsigned integer +local readulong = streamreader.readcardinal4 -- 24-bit unsigned integer +local readchar = streamreader.readinteger1 -- 8-bit signed integer +local readshort = streamreader.readinteger2 -- 16-bit signed integer +local read2dot14 = streamreader.read2dot14 -- 16-bit signed fixed number with the low 14 bits of fraction (2.14) (F2DOT14) +local readinteger = streamreader.readinteger1 +local readcardinaltable = streamreader.readcardinaltable +local readintegertable = streamreader.readintegertable + +directives.register("fonts.streamreader",function() + + streamreader = utilities.streams + + setposition = streamreader.setposition + getposition = streamreader.getposition + skipbytes = streamreader.skip + readbyte = streamreader.readcardinal1 + readushort = streamreader.readcardinal2 + readulong = streamreader.readcardinal4 + readchar = streamreader.readinteger1 + readshort = streamreader.readinteger2 + read2dot14 = streamreader.read2dot14 + readinteger = streamreader.readinteger1 + readcardinaltable = streamreader.readcardinaltable + readintegertable = streamreader.readintegertable + +end) + +local short = 2 +local ushort = 2 +local ulong = 4 + +local helpers = readers.helpers +local gotodatatable = helpers.gotodatatable + +local function mergecomposites(glyphs,shapes) + + -- todo : deltas + + local function merge(index,shape,components) + local contours = { } + local points = { } + local nofcontours = 0 + local nofpoints = 0 + local offset = 0 + local deltas = shape.deltas + for i=1,#components do + local component = components[i] + local subindex = component.index + local subshape = shapes[subindex] + local subcontours = subshape.contours + local subpoints = subshape.points + if not subcontours then + local subcomponents = subshape.components + if subcomponents then + subcontours, subpoints = merge(subindex,subshape,subcomponents) + end + end + if subpoints then + local matrix = component.matrix + local xscale = matrix[1] + local xrotate = matrix[2] + local yrotate = matrix[3] + local yscale = matrix[4] + local xoffset = matrix[5] + local yoffset = matrix[6] + local count = #subpoints + if xscale == 1 and yscale == 1 and xrotate == 0 and yrotate == 0 then + for i=1,count do + local p = subpoints[i] + nofpoints = nofpoints + 1 + points[nofpoints] = { + p[1] + xoffset, + p[2] + yoffset, + p[3] + } + end + else + for i=1,count do + local p = subpoints[i] + local x = p[1] + local y = p[2] + nofpoints = nofpoints + 1 + points[nofpoints] = { + -- unifractur : u n + -- seguiemj : 0x270E 0x2710 + xscale * x + xrotate * y + xoffset, + yscale * y + yrotate * x + yoffset, +-- xscale * x + yrotate * y + xoffset, +-- xrotate * x + yscale * y + yoffset, + p[3] + } + end + end + local subcount = #subcontours + if subcount == 1 then + nofcontours = nofcontours + 1 + contours[nofcontours] = offset + subcontours[1] + else + for i=1,#subcontours do + nofcontours = nofcontours + 1 + contours[nofcontours] = offset + subcontours[i] + end + end + offset = offset + count + else + report("missing contours composite %s, component %s of %s, glyph %s",index,i,#components,subindex) + end + end + shape.points = points -- todo : phantom points + shape.contours = contours + shape.components = nil + return contours, points + end + + for index=0,#glyphs do + local shape = shapes[index] + if shape then + local components = shape.components + if components then + merge(index,shape,components) + end + end + end + +end + +local function readnothing(f) + return { + type = "nothing", + } +end + +-- begin of converter + +local function curveto(m_x,m_y,l_x,l_y,r_x,r_y) -- todo: inline this + return + l_x + 2/3 *(m_x-l_x), l_y + 2/3 *(m_y-l_y), + r_x + 2/3 *(m_x-r_x), r_y + 2/3 *(m_y-r_y), + r_x, r_y, "c" +end + +-- We could omit the operator which saves some 10%: +-- +-- #2=lineto #4=quadratic #6=cubic #3=moveto (with "m") +-- +-- This is tricky ... something to do with phantom points .. however, the hvar +-- and vvar tables should take care of the width .. the test font doesn't have +-- those so here we go then (we need a flag for hvar). +-- +-- h-advance left-side-bearing v-advance top-side-bearing +-- +-- We had two loops (going backward) but can do it in one loop .. but maybe we +-- should only accept fonts with proper hvar tables. + +-- dowidth is kind of hack ... fonts are not always ok wrt these extra points + +local xv = { } -- we share this cache +local yv = { } -- we share this cache + +local function applyaxis(glyph,shape,deltas,dowidth) + local points = shape.points + if points then + local nofpoints = #points + local dw = 0 + local dl = 0 + for i=1,#deltas do + local deltaset = deltas[i] + local xvalues = deltaset.xvalues + local yvalues = deltaset.yvalues + if xvalues and yvalues then + local dpoints = deltaset.points + local factor = deltaset.factor + if dpoints then + local cnt = #dpoints + if dowidth then + cnt = cnt - 4 + end + if cnt > 0 then + -- Not the most efficient solution but we seldom do this. We + -- actually need to avoid the extra points here but I'll deal + -- with that when needed. + local contours = shape.contours + local nofcontours = #contours + local first = 1 + local firstindex = 1 + for contour=1,nofcontours do + local last = contours[contour] + if last >= first then + local lastindex = cnt + if firstindex < cnt then + for currentindex=firstindex,cnt do + local found = dpoints[currentindex] + if found <= first then + firstindex = currentindex + end + if found == last then + lastindex = currentindex + break + elseif found > last then + -- \definefontfeature[book][default][axis={weight=800}] + -- \definefont[testfont][file:Commissioner-vf-test.ttf*book] + -- \testfont EΘÄΞ + while lastindex > 1 and dpoints[lastindex] > last do + lastindex = lastindex - 1 + end + -- + break + end + end + end + -- print("unicode: ",glyph.unicode or "?") + -- print("contour: ",first,contour,last) + -- print("index : ",firstindex,lastindex,cnt) + -- print("points : ",dpoints[firstindex],dpoints[lastindex]) + local function find(i) + local prv = lastindex + for j=firstindex,lastindex do + local nxt = dpoints[j] -- we could save this lookup when we return it + if nxt == i then + return false, j, false + elseif nxt > i then + return prv, false, j + end + prv = j + end + return prv, false, firstindex + end + -- We need the first and last points untouched so we first + -- collect data. + for point=first,last do + local d1, d2, d3 = find(point) + local p2 = points[point] + if d2 then + xv[point] = xvalues[d2] + yv[point] = yvalues[d2] + else + local n1 = dpoints[d1] + local n3 = dpoints[d3] + -- Some day I need to figure out these extra points but + -- I'll wait till the standard is more clear and fonts + -- become better (ntg-context: fraunces.ttf > abcdef). + if n1 > nofpoints then + n1 = nofpoints + end + if n3 > nofpoints then + n3 = nofpoints + end + -- + local p1 = points[n1] + local p3 = points[n3] + local p1x = p1[1] + local p2x = p2[1] + local p3x = p3[1] + local p1y = p1[2] + local p2y = p2[2] + local p3y = p3[2] + local x1 = xvalues[d1] + local y1 = yvalues[d1] + local x3 = xvalues[d3] + local y3 = yvalues[d3] + -- + local fx + local fy + -- + if p1x == p3x then + if x1 == x3 then + fx = x1 + else + fx = 0 + end + elseif p2x <= min(p1x,p3x) then + if p1x < p3x then + fx = x1 + else + fx = x3 + end + elseif p2x >= max(p1x,p3x) then + if p1x > p3x then + fx = x1 + else + fx = x3 + end + else + fx = (p2x - p1x)/(p3x - p1x) +-- fx = round(fx) + fx = (1 - fx) * x1 + fx * x3 + end + -- + if p1y == p3y then + if y1 == y3 then + fy = y1 + else + fy = 0 + end + elseif p2y <= min(p1y,p3y) then + if p1y < p3y then + fy = y1 + else + fy = y3 + end + elseif p2y >= max(p1y,p3y) then + if p1y > p3y then + fy = y1 + else + fy = y3 + end + else + fy = (p2y - p1y)/(p3y - p1y) +-- fy = round(fy) + fy = (1 - fy) * y1 + fy * y3 + end + -- -- maybe: + -- if p1y ~= p3y then + -- fy = (p2y - p1y)/(p3y - p1y) + -- fy = (1 - fy) * y1 + fy * y3 + -- elseif abs(p1y-p2y) < abs(p3y-p2y) then + -- fy = y1 + -- else + -- fy = y3 + -- end + -- + xv[point] = fx + yv[point] = fy + end + end + if lastindex < cnt then + firstindex = lastindex + 1 + end + end + first = last + 1 + end + + for i=1,nofpoints do + local pi = points[i] + local fx = xv[i] + local fy = yv[i] + if fx ~= 0 then + pi[1] = pi[1] + factor * fx + end + if fy ~= 0 then + pi[2] = pi[2] + factor * fy + end + end + else + report("bad deltapoint data, maybe a missing hvar table") + end + else + for i=1,nofpoints do + local p = points[i] + local x = xvalues[i] + if x then + local y = yvalues[i] + if x ~= 0 then + p[1] = p[1] + factor * x + end + if y ~= 0 then + p[2] = p[2] + factor * y + end + else + break + end + end + end + if dowidth then + local h = nofpoints + 2 -- weird, the example font seems to have left first + local l = nofpoints + 1 + ----- v = nofpoints + 3 + ----- t = nofpoints + 4 + local x = xvalues[h] + if x then + dw = dw + factor * x + end + local x = xvalues[l] + if x then + dl = dl + factor * x + end + end + end + end + -- for i=1,nofpoints do + -- local p = points[i] + -- p[1] = round(p[1]) + -- p[2] = round(p[2]) + -- end + if dowidth then + local width = glyph.width or 0 + -- local lsb = glyph.lsb or 0 + glyph.width = width + dw - dl + end + else + report("no points for glyph %a",glyph.name) + end +end + +-- round or not ? + +-- local quadratic = true -- both methods work, todo: install a directive +local quadratic = false + +local function contours2outlines_normal(glyphs,shapes) -- maybe accept the bbox overhead +-- for index=1,#glyphs do + for index=0,#glyphs-1 do + local shape = shapes[index] + if shape then + local glyph = glyphs[index] + local contours = shape.contours + local points = shape.points + if contours then + local nofcontours = #contours + local segments = { } + local nofsegments = 0 + glyph.segments = segments + if nofcontours > 0 then + local px = 0 + local py = 0 + local first = 1 + for i=1,nofcontours do + local last = contours[i] + if last >= first then + local first_pt = points[first] + local first_on = first_pt[3] + -- todo no new tables but reuse lineto and quadratic + if first == last then + first_pt[3] = "m" -- "moveto" + nofsegments = nofsegments + 1 + segments[nofsegments] = first_pt + else -- maybe also treat n == 2 special + local first_on = first_pt[3] + local last_pt = points[last] + local last_on = last_pt[3] + local start = 1 + local control_pt = false + if first_on then + start = 2 + else + if last_on then + first_pt = last_pt + else + first_pt = { (first_pt[1]+last_pt[1])/2, (first_pt[2]+last_pt[2])/2, false } + end + control_pt = first_pt + end + local x = first_pt[1] + local y = first_pt[2] + if not done then + xmin = x + ymin = y + xmax = x + ymax = y + done = true + end + nofsegments = nofsegments + 1 + segments[nofsegments] = { x, y, "m" } -- "moveto" + if not quadratic then + px = x + py = y + end + local previous_pt = first_pt + for i=first,last do + local current_pt = points[i] + local current_on = current_pt[3] + local previous_on = previous_pt[3] + if previous_on then + if current_on then + -- both normal points + local x, y = current_pt[1], current_pt[2] + nofsegments = nofsegments + 1 + segments[nofsegments] = { x, y, "l" } -- "lineto" + if not quadratic then + px, py = x, y + end + else + control_pt = current_pt + end + elseif current_on then + local x1 = control_pt[1] + local y1 = control_pt[2] + local x2 = current_pt[1] + local y2 = current_pt[2] + nofsegments = nofsegments + 1 + if quadratic then + segments[nofsegments] = { x1, y1, x2, y2, "q" } -- "quadraticto" + else + x1, y1, x2, y2, px, py = curveto(x1, y1, px, py, x2, y2) + segments[nofsegments] = { x1, y1, x2, y2, px, py, "c" } -- "curveto" + end + control_pt = false + else + local x2 = (previous_pt[1]+current_pt[1])/2 + local y2 = (previous_pt[2]+current_pt[2])/2 + local x1 = control_pt[1] + local y1 = control_pt[2] + nofsegments = nofsegments + 1 + if quadratic then + segments[nofsegments] = { x1, y1, x2, y2, "q" } -- "quadraticto" + else + x1, y1, x2, y2, px, py = curveto(x1, y1, px, py, x2, y2) + segments[nofsegments] = { x1, y1, x2, y2, px, py, "c" } -- "curveto" + end + control_pt = current_pt + end + previous_pt = current_pt + end + if first_pt == last_pt then + -- we're already done, probably a simple curve + else + nofsegments = nofsegments + 1 + local x2 = first_pt[1] + local y2 = first_pt[2] + if not control_pt then + segments[nofsegments] = { x2, y2, "l" } -- "lineto" + elseif quadratic then + local x1 = control_pt[1] + local y1 = control_pt[2] + segments[nofsegments] = { x1, y1, x2, y2, "q" } -- "quadraticto" + else + local x1 = control_pt[1] + local y1 = control_pt[2] + x1, y1, x2, y2, px, py = curveto(x1, y1, px, py, x2, y2) + segments[nofsegments] = { x1, y1, x2, y2, px, py, "c" } -- "curveto" + -- px, py = x2, y2 + end + end + end + end + first = last + 1 + end + end + end + end + end +end + +local function contours2outlines_shaped(glyphs,shapes,keepcurve) +-- for index=1,#glyphs do + for index=0,#glyphs-1 do + local shape = shapes[index] + if shape then + local glyph = glyphs[index] + local contours = shape.contours + local points = shape.points + if contours then + local nofcontours = #contours + local segments = keepcurve and { } or nil + local nofsegments = 0 + if keepcurve then + glyph.segments = segments + end + if nofcontours > 0 then + local xmin, ymin, xmax, ymax, done = 0, 0, 0, 0, false + local px, py = 0, 0 -- we could use these in calculations which saves a copy + local first = 1 + for i=1,nofcontours do + local last = contours[i] + if last >= first then + local first_pt = points[first] + local first_on = first_pt[3] + -- todo no new tables but reuse lineto and quadratic + if first == last then + -- this can influence the boundingbox + if keepcurve then + first_pt[3] = "m" -- "moveto" + nofsegments = nofsegments + 1 + segments[nofsegments] = first_pt + end + else -- maybe also treat n == 2 special + local first_on = first_pt[3] + local last_pt = points[last] + local last_on = last_pt[3] + local start = 1 + local control_pt = false + if first_on then + start = 2 + else + if last_on then + first_pt = last_pt + else + first_pt = { (first_pt[1]+last_pt[1])/2, (first_pt[2]+last_pt[2])/2, false } + end + control_pt = first_pt + end + local x = first_pt[1] + local y = first_pt[2] + if not done then + xmin, ymin, xmax, ymax = x, y, x, y + done = true + else + if x < xmin then xmin = x elseif x > xmax then xmax = x end + if y < ymin then ymin = y elseif y > ymax then ymax = y end + end + if keepcurve then + nofsegments = nofsegments + 1 + segments[nofsegments] = { x, y, "m" } -- "moveto" + end + if not quadratic then + px = x + py = y + end + local previous_pt = first_pt + for i=first,last do + local current_pt = points[i] + local current_on = current_pt[3] + local previous_on = previous_pt[3] + if previous_on then + if current_on then + -- both normal points + local x = current_pt[1] + local y = current_pt[2] + if x < xmin then xmin = x elseif x > xmax then xmax = x end + if y < ymin then ymin = y elseif y > ymax then ymax = y end + if keepcurve then + nofsegments = nofsegments + 1 + segments[nofsegments] = { x, y, "l" } -- "lineto" + end + if not quadratic then + px = x + py = y + end + else + control_pt = current_pt + end + elseif current_on then + local x1 = control_pt[1] + local y1 = control_pt[2] + local x2 = current_pt[1] + local y2 = current_pt[2] + if quadratic then + if x1 < xmin then xmin = x1 elseif x1 > xmax then xmax = x1 end + if y1 < ymin then ymin = y1 elseif y1 > ymax then ymax = y1 end + if keepcurve then + nofsegments = nofsegments + 1 + segments[nofsegments] = { x1, y1, x2, y2, "q" } -- "quadraticto" + end + else + x1, y1, x2, y2, px, py = curveto(x1, y1, px, py, x2, y2) + if x1 < xmin then xmin = x1 elseif x1 > xmax then xmax = x1 end + if y1 < ymin then ymin = y1 elseif y1 > ymax then ymax = y1 end + if x2 < xmin then xmin = x2 elseif x2 > xmax then xmax = x2 end + if y2 < ymin then ymin = y2 elseif y2 > ymax then ymax = y2 end + if px < xmin then xmin = px elseif px > xmax then xmax = px end + if py < ymin then ymin = py elseif py > ymax then ymax = py end + if keepcurve then + nofsegments = nofsegments + 1 + segments[nofsegments] = { x1, y1, x2, y2, px, py, "c" } -- "curveto" + end + end + control_pt = false + else + local x2 = (previous_pt[1]+current_pt[1])/2 + local y2 = (previous_pt[2]+current_pt[2])/2 + local x1 = control_pt[1] + local y1 = control_pt[2] + if quadratic then + if x1 < xmin then xmin = x1 elseif x1 > xmax then xmax = x1 end + if y1 < ymin then ymin = y1 elseif y1 > ymax then ymax = y1 end + if keepcurve then + nofsegments = nofsegments + 1 + segments[nofsegments] = { x1, y1, x2, y2, "q" } -- "quadraticto" + end + else + x1, y1, x2, y2, px, py = curveto(x1, y1, px, py, x2, y2) + if x1 < xmin then xmin = x1 elseif x1 > xmax then xmax = x1 end + if y1 < ymin then ymin = y1 elseif y1 > ymax then ymax = y1 end + if x2 < xmin then xmin = x2 elseif x2 > xmax then xmax = x2 end + if y2 < ymin then ymin = y2 elseif y2 > ymax then ymax = y2 end + if px < xmin then xmin = px elseif px > xmax then xmax = px end + if py < ymin then ymin = py elseif py > ymax then ymax = py end + if keepcurve then + nofsegments = nofsegments + 1 + segments[nofsegments] = { x1, y1, x2, y2, px, py, "c" } -- "curveto" + end + end + control_pt = current_pt + end + previous_pt = current_pt + end + if first_pt == last_pt then + -- we're already done, probably a simple curve + elseif not control_pt then + if keepcurve then + nofsegments = nofsegments + 1 + segments[nofsegments] = { first_pt[1], first_pt[2], "l" } -- "lineto" + end + else + local x1 = control_pt[1] + local y1 = control_pt[2] + local x2 = first_pt[1] + local y2 = first_pt[2] + if x1 < xmin then xmin = x1 elseif x1 > xmax then xmax = x1 end + if y1 < ymin then ymin = y1 elseif y1 > ymax then ymax = y1 end + if quadratic then + if keepcurve then + nofsegments = nofsegments + 1 + segments[nofsegments] = { x1, y1, x2, y2, "q" } -- "quadraticto" + end + else + x1, y1, x2, y2, px, py = curveto(x1, y1, px, py, x2, y2) + if x2 < xmin then xmin = x2 elseif x2 > xmax then xmax = x2 end + if y2 < ymin then ymin = y2 elseif y2 > ymax then ymax = y2 end + if px < xmin then xmin = px elseif px > xmax then xmax = px end + if py < ymin then ymin = py elseif py > ymax then ymax = py end + if keepcurve then + nofsegments = nofsegments + 1 + segments[nofsegments] = { x1, y1, x2, y2, px, py, "c" } -- "curveto" + end + -- px, py = x2, y2 + end + end + end + end + first = last + 1 + end + -- See readers.hvar where we set the delta lsb as well as the adapted + -- width. At this point we do know the boundingbox's llx. The xmax is + -- not that relevant. It needs more testing! + -- + xmin = glyph.boundingbox[1] + -- + local dlsb = glyph.dlsb + if dlsb then + xmin = xmin + dlsb + glyph.dlsb = nil -- save space + end + -- + glyph.boundingbox = { round(xmin), round(ymin), round(xmax), round(ymax) } + end + end + end + end +end + +-- optimize for zero + +local c_zero = char(0) +local s_zero = char(0,0) + +-- local shorthash = setmetatableindex(function(t,k) +-- -- t[k] = char(band(rshift(k,8),0xFF),band(k,0xFF)) return t[k] +-- t[k] = char((k >> 8) & 0xFF,k & 0xFF) return t[k] +-- end) + +local function toushort(n) + -- return char(band(rshift(n,8),0xFF),band(n,0xFF)) + return char((n >> 8) & 0xFF,n & 0xFF) + -- return shorthash[n] +end + +local function toshort(n) + if n < 0 then + n = n + 0x10000 + end + -- return char(band(rshift(n,8),0xFF),band(n,0xFF)) + return char((n >> 8) & 0xFF,n & 0xFF) + -- return shorthash[n] +end + +-- todo: we can reuse result, xpoints and ypoints + +local chars = setmetatableindex(function(t,k) + for i=0,255 do local v = char(i) t[i] = v end return t[k] +end) + +local function repackpoints(glyphs,shapes) + local noboundingbox = { 0, 0, 0, 0 } + local result = { } -- reused + local xpoints = { } -- reused + local ypoints = { } -- reused + for index=0,#glyphs do + local shape = shapes[index] + if shape then + local r = 0 + local glyph = glyphs[index] + local contours = shape.contours + local nofcontours = contours and #contours or 0 + local boundingbox = glyph.boundingbox or noboundingbox + r = r + 1 result[r] = toshort(nofcontours) + r = r + 1 result[r] = toshort(boundingbox[1]) -- xmin + r = r + 1 result[r] = toshort(boundingbox[2]) -- ymin + r = r + 1 result[r] = toshort(boundingbox[3]) -- xmax + r = r + 1 result[r] = toshort(boundingbox[4]) -- ymax + if nofcontours > 0 then + for i=1,nofcontours do + r = r + 1 result[r] = toshort(contours[i]-1) + end + r = r + 1 result[r] = s_zero -- no instructions + local points = shape.points + local currentx = 0 + local currenty = 0 + -- local xpoints = { } + -- local ypoints = { } + local x = 0 + local y = 0 + local lastflag = nil + local nofflags = 0 + for i=1,#points do + local pt = points[i] + local px = pt[1] + local py = pt[2] + local fl = pt[3] and 0x01 or 0x00 + if px == currentx then + fl = fl + 0x10 + else + local dx = round(px - currentx) + x = x + 1 + if dx < -255 or dx > 255 then + xpoints[x] = toshort(dx) + elseif dx < 0 then + fl = fl + 0x02 + -- xpoints[x] = char(-dx) + xpoints[x] = chars[-dx] + elseif dx > 0 then + fl = fl + 0x12 + -- xpoints[x] = char(dx) + xpoints[x] = chars[dx] + else + fl = fl + 0x02 + xpoints[x] = c_zero + end + end + if py == currenty then + fl = fl + 0x20 + else + local dy = round(py - currenty) + y = y + 1 + if dy < -255 or dy > 255 then + ypoints[y] = toshort(dy) + elseif dy < 0 then + fl = fl + 0x04 + -- ypoints[y] = char(-dy) + ypoints[y] = chars[-dy] + elseif dy > 0 then + fl = fl + 0x24 + -- ypoints[y] = char(dy) + ypoints[y] = chars[dy] + else + fl = fl + 0x04 + ypoints[y] = c_zero + end + end + currentx = px + currenty = py + if lastflag == fl then + if nofflags == 255 then + -- This happens in koeieletters! + lastflag = lastflag + 0x08 + r = r + 1 result[r] = char(lastflag,nofflags-1) + nofflags = 1 + lastflag = fl + else + nofflags = nofflags + 1 + end + else -- if > 255 + if nofflags == 1 then + -- r = r + 1 result[r] = char(lastflag) + r = r + 1 result[r] = chars[lastflag] + elseif nofflags == 2 then + r = r + 1 result[r] = char(lastflag,lastflag) + elseif nofflags > 2 then + lastflag = lastflag + 0x08 + r = r + 1 result[r] = char(lastflag,nofflags-1) + end + nofflags = 1 + lastflag = fl + end + end + if nofflags == 1 then + -- r = r + 1 result[r] = char(lastflag) + r = r + 1 result[r] = chars[lastflag] + elseif nofflags == 2 then + r = r + 1 result[r] = char(lastflag,lastflag) + elseif nofflags > 2 then + lastflag = lastflag + 0x08 + r = r + 1 result[r] = char(lastflag,nofflags-1) + end + -- r = r + 1 result[r] = concat(xpoints) + -- r = r + 1 result[r] = concat(ypoints) + r = r + 1 result[r] = concat(xpoints,"",1,x) + r = r + 1 result[r] = concat(ypoints,"",1,y) + end + -- can be helper or delegated to user + local stream = concat(result,"",1,r) + local length = #stream + local padding = ((length+3) // 4) * 4 - length + if padding > 0 then + -- stream = stream .. rep("\0",padding) -- can be a repeater + if padding == 1 then + padding = "\0" + elseif padding == 2 then + padding = "\0\0" + else + padding = "\0\0\0" + end + padding = stream .. padding + end + glyph.stream = stream + end + end +end + +-- end of converter + +local flags = { } + +local function readglyph(f,nofcontours) -- read deltas here, saves space + local points = { } + -- local instructions = { } + local contours = { } -- readintegertable(f,nofcontours,short) + for i=1,nofcontours do + contours[i] = readshort(f) + 1 + end + local nofpoints = contours[nofcontours] + local nofinstructions = readushort(f) + skipbytes(f,nofinstructions) + -- because flags can repeat we don't know the amount ... in fact this is + -- not that efficient (small files but more mem) + local i = 1 + while i <= nofpoints do + local flag = readbyte(f) + flags[i] = flag + if (flag & 0x08) ~= 0 then + local n = readbyte(f) + if n == 1 then + i = i + 1 + flags[i] = flag + else + for j=1,n do + i = i + 1 + flags[i] = flag + end + end + end + i = i + 1 + end + -- first come the x coordinates, and next the y coordinates and they + -- can be repeated + local x = 0 + for i=1,nofpoints do + local flag = flags[i] + -- local short = (flag & 0x02) ~= 0 + -- local same = (flag & 0x10) ~= 0 + if (flag & 0x02) ~= 0 then + if (flag & 0x10) ~= 0 then + x = x + readbyte(f) + else + x = x - readbyte(f) + end + elseif (flag & 0x10) ~= 0 then + -- copy + else + x = x + readshort(f) + end + points[i] = { x, 0, (flag & 0x01) ~= 0 } + end + local y = 0 + for i=1,nofpoints do + local flag = flags[i] + -- local short = (flag & 0x04) ~= 0 + -- local same = (flag & 0x20) ~= 0 + if (flag & 0x04) ~= 0 then + if (flag & 0x20) ~= 0 then + y = y + readbyte(f) + else + y = y - readbyte(f) + end + elseif (flag & 0x20) ~= 0 then + -- copy + else + y = y + readshort(f) + end + points[i][2] = y + end + return { + type = "glyph", + points = points, + contours = contours, + nofpoints = nofpoints, + } +end + +local function readcomposite(f) + local components = { } + local nofcomponents = 0 + local instructions = false + while true do + local flags = readushort(f) + local index = readushort(f) + ----- f_words = (flags & 0x0001) ~= 0 + local f_xyarg = (flags & 0x0002) ~= 0 + ----- f_round = (flags & 0x0006) ~= 0 -- 2 + 4 + ----- f_scale = (flags & 0x0008) ~= 0 + ----- f_reserved = (flags & 0x0010) ~= 0 + ----- f_more = (flags & 0x0020) ~= 0 + ----- f_xyscale = (flags & 0x0040) ~= 0 + ----- f_matrix = (flags & 0x0080) ~= 0 + ----- f_instruct = (flags & 0x0100) ~= 0 + ----- f_usemine = (flags & 0x0200) ~= 0 + ----- f_overlap = (flags & 0x0400) ~= 0 + local f_offset = (flags & 0x0800) ~= 0 + ----- f_uoffset = (flags & 0x1000) ~= 0 + local xscale = 1 + local xrotate = 0 + local yrotate = 0 + local yscale = 1 + local xoffset = 0 + local yoffset = 0 + local base = false + local reference = false + if f_xyarg then + if (flags & 0x0001) ~= 0 then -- f_words + xoffset = readshort(f) + yoffset = readshort(f) + else + xoffset = readchar(f) -- signed byte, stupid name + yoffset = readchar(f) -- signed byte, stupid name + end + else + if (flags & 0x0001) ~= 0 then -- f_words + base = readshort(f) + reference = readshort(f) + else + base = readchar(f) -- signed byte, stupid name + reference = readchar(f) -- signed byte, stupid name + end + end + if (flags & 0x0008) ~= 0 then -- f_scale + xscale = read2dot14(f) + yscale = xscale + if f_xyarg and f_offset then + xoffset = xoffset * xscale + yoffset = yoffset * yscale + end + elseif (flags & 0x0040) ~= 0 then -- f_xyscale + xscale = read2dot14(f) + yscale = read2dot14(f) + if f_xyarg and f_offset then + xoffset = xoffset * xscale + yoffset = yoffset * yscale + end + elseif (flags & 0x0080) ~= 0 then -- f_matrix + xscale = read2dot14(f) -- xxpart + xrotate = read2dot14(f) -- yxpart + yrotate = read2dot14(f) -- xypart + yscale = read2dot14(f) -- yypart + if f_xyarg and f_offset then + xoffset = xoffset * sqrt(xscale ^2 + yrotate^2) -- was xrotate + yoffset = yoffset * sqrt(xrotate^2 + yscale ^2) -- was yrotate + end + end + nofcomponents = nofcomponents + 1 + components[nofcomponents] = { + index = index, + usemine = (flags & 0x0200) ~= 0, -- f_usemine + round = (flags & 0x0006) ~= 0, -- f_round, + base = base, + reference = reference, + matrix = { xscale, xrotate, yrotate, yscale, xoffset, yoffset }, + } + if (flags & 0x0100) ~= 0 then + instructions = true + end + if (flags & 0x0020) == 0 then -- f_more + break + end + end + return { + type = "composite", + components = components, + } +end + +-- function readers.cff(f,offset,glyphs,doshapes) -- false == no shapes (nil or true otherwise) + +-- The glyf table depends on the loca table. We have one entry to much +-- in the locations table (the last one is a dummy) because we need to +-- calculate the size of a glyph blob from the delta, although we not +-- need it in our usage (yet). We can remove the locations table when +-- we're done (todo: cleanup finalizer). + +function readers.loca(f,fontdata,specification) + if specification.glyphs then + local datatable = fontdata.tables.loca + if datatable then + -- locations are relative to the glypdata table (glyf) + local offset = fontdata.tables.glyf.offset + local format = fontdata.fontheader.indextolocformat + local profile = fontdata.maximumprofile + local nofglyphs = profile and profile.nofglyphs + local locations = { } + setposition(f,datatable.offset) + if format == 1 then + if not nofglyphs then + nofglyphs = (datatable.length // 4) - 1 + end + for i=0,nofglyphs do + locations[i] = offset + readulong(f) + end + fontdata.nofglyphs = nofglyphs + else + if not nofglyphs then + nofglyphs = (datatable.length // 2) - 1 + end + for i=0,nofglyphs do + locations[i] = offset + readushort(f) * 2 + end + end + fontdata.nofglyphs = nofglyphs + fontdata.locations = locations + end + end +end + +function readers.glyf(f,fontdata,specification) -- part goes to cff module + local tableoffset = gotodatatable(f,fontdata,"glyf",specification.glyphs) + if tableoffset then + local locations = fontdata.locations + if locations then + local glyphs = fontdata.glyphs + local nofglyphs = fontdata.nofglyphs + local filesize = fontdata.filesize + local nothing = { 0, 0, 0, 0 } + local shapes = { } + local loadshapes = specification.shapes or specification.instance or specification.streams + for index=0,nofglyphs-1 do + local location = locations[index] + local length = locations[index+1] - location + if location >= filesize then + report("discarding %s glyphs due to glyph location bug",nofglyphs-index+1) + fontdata.nofglyphs = index - 1 + fontdata.badfont = true + break + elseif length > 0 then + setposition(f,location) + local nofcontours = readshort(f) + glyphs[index].boundingbox = { + readshort(f), -- xmin + readshort(f), -- ymin + readshort(f), -- xmax + readshort(f), -- ymax + } + if not loadshapes then + -- save space + elseif nofcontours == 0 then + shapes[index] = readnothing(f) + elseif nofcontours > 0 then + shapes[index] = readglyph(f,nofcontours) + else + shapes[index] = readcomposite(f,nofcontours) + end + else + if loadshapes then + shapes[index] = readnothing(f) + end + glyphs[index].boundingbox = nothing + end + end + if loadshapes then + if readers.gvar then + readers.gvar(f,fontdata,specification,glyphs,shapes) + end + mergecomposites(glyphs,shapes) + if specification.instance then + if specification.streams then + repackpoints(glyphs,shapes) + else + contours2outlines_shaped(glyphs,shapes,specification.shapes) + end + elseif specification.shapes then + if specification.streams then + repackpoints(glyphs,shapes) + else + contours2outlines_normal(glyphs,shapes) + end + elseif specification.streams then + repackpoints(glyphs,shapes) + end + end + end + end +end + +-- gvar is a bit crazy format and one can really wonder if the bit-jugling obscurity +-- is still needed in these days .. cff is much nicer with these blends while the ttf +-- coding variant looks quite horrible + +local function readtuplerecord(f,nofaxis) + local record = { } + for i=1,nofaxis do + record[i] = read2dot14(f) + end + return record +end + +-- (1) the first is a real point the rest deltas +-- (2) points can be present more than once (multiple deltas then) + +local function readpoints(f) + local count = readbyte(f) + if count == 0 then + -- second byte not used, deltas for all point numbers + return nil, 0 -- todo + else + if count < 128 then + -- no second byte, use count + elseif (count & 0x80) ~= 0 then + count = (count & 0x7F) * 256 + readbyte(f) + else + -- bad news + end + local points = { } + local p = 0 + local n = 1 -- indices + while p < count do + local control = readbyte(f) + local runreader = (control & 0x80) ~= 0 and readushort or readbyte + local runlength = (control & 0x7F) + for i=1,runlength+1 do + n = n + runreader(f) + p = p + 1 + points[p] = n + end + end + return points, p + end +end + +local function readdeltas(f,nofpoints) + local deltas = { } + local p = 0 + while nofpoints > 0 do + local control = readbyte(f) + if control then + local allzero = (control & 0x80) ~= 0 + local runlength = (control & 0x3F) + 1 + if allzero then + for i=1,runlength do + p = p + 1 + deltas[p] = 0 + end + else + local runreader = (control & 0x40) ~= 0 and readshort or readinteger + for i=1,runlength do + p = p + 1 + deltas[p] = runreader(f) + end + end + nofpoints = nofpoints - runlength + else + -- it happens + break + end + end + -- saves space + if p > 0 then + return deltas + else + -- forget about all zeros + end +end + +function readers.gvar(f,fontdata,specification,glyphdata,shapedata) + -- this is one of the messiest tables + local instance = specification.instance + if not instance then + return + end + local factors = specification.factors + if not factors then + return + end + local tableoffset = gotodatatable(f,fontdata,"gvar",specification.variable or specification.shapes) + if tableoffset then + local version = readulong(f) -- 1.0 + local nofaxis = readushort(f) + local noftuples = readushort(f) + local tupleoffset = tableoffset + readulong(f) + local nofglyphs = readushort(f) + local flags = readushort(f) + local dataoffset = tableoffset + readulong(f) + local data = { } + local tuples = { } + local glyphdata = fontdata.glyphs + local dowidth = not fontdata.variabledata.hvarwidths + -- there is one more offset (so that one can calculate the size i suppose) + -- so we could test for overflows but we simply assume sane font files + if (flags & 0x0001) ~= 0 then + for i=1,nofglyphs+1 do + data[i] = dataoffset + readulong(f) + end + else + for i=1,nofglyphs+1 do + data[i] = dataoffset + 2*readushort(f) + end + end + -- + if noftuples > 0 then + setposition(f,tupleoffset) + for i=1,noftuples do + tuples[i] = readtuplerecord(f,nofaxis) + end + end + local nextoffset = false + local startoffset = data[1] + for i=1,nofglyphs do -- hm one more cf spec + nextoffset = data[i+1] + local glyph = glyphdata[i-1] + local name = trace_deltas and glyph.name + if startoffset == nextoffset then + if name then + report("no deltas for glyph %a",name) + end + else + local shape = shapedata[i-1] -- todo 0 + if not shape then + if name then + report("no shape for glyph %a",name) + end + else + lastoffset = startoffset + setposition(f,startoffset) + local flags = readushort(f) + local count = (flags & 0x0FFF) + local offset = startoffset + readushort(f) -- to serialized + local deltas = { } + local allpoints = (shape.nofpoints or 0) -- + 1 + local shared = false + local nofshared = 0 + if (flags & 0x8000) ~= 0 then -- has shared points + -- go to the packed stream (get them once) + local current = getposition(f) + setposition(f,offset) + shared, nofshared = readpoints(f) + offset = getposition(f) + setposition(f,current) + -- and back to the table + end + for j=1,count do + local size = readushort(f) -- check + local flags = readushort(f) + local index = (flags & 0x0FFF) + local haspeak = (flags & 0x8000) ~= 0 + local intermediate = (flags & 0x4000) ~= 0 + local private = (flags & 0x2000) ~= 0 + local peak = nil + local start = nil + local stop = nil + local xvalues = nil + local yvalues = nil + local points = shared -- we default to shared + local nofpoints = nofshared -- we default to shared + -- local advance = 4 + if haspeak then + peak = readtuplerecord(f,nofaxis) + -- advance = advance + 2*nofaxis + else + if index+1 > #tuples then + report("error, bad tuple index",index) + end + peak = tuples[index+1] -- hm, needs checking, only peak? + end + if intermediate then + start = readtuplerecord(f,nofaxis) + stop = readtuplerecord(f,nofaxis) + -- advance = advance + 4*nofaxis + end + -- get the deltas + if size > 0 then + local current = getposition(f) + -- goto the packed stream + setposition(f,offset) + if private then + points, nofpoints = readpoints(f) + end -- else + if nofpoints == 0 then + nofpoints = allpoints + 4 + end + if nofpoints > 0 then + -- a nice test is to do only one + xvalues = readdeltas(f,nofpoints) + yvalues = readdeltas(f,nofpoints) + end + -- resync offset + offset = offset + size + -- back to the table + setposition(f,current) + end + if not xvalues and not yvalues then + points = nil + end + local s = 1 + for i=1,nofaxis do + local f = factors[i] + local peak = peak and peak [i] or 0 + -- local start = start and start[i] or 0 + -- local stop = stop and stop [i] or 0 + local start = start and start[i] or (peak < 0 and peak or 0) + local stop = stop and stop [i] or (peak > 0 and peak or 0) -- or 1 ? +-- local stop = stop and stop [i] or (peak > 0 and peak or 1) -- or 1 ? + -- do we really need these tests ... can't we assume sane values + if start > peak or peak > stop then + -- * 1 + elseif start < 0 and stop > 0 and peak ~= 0 then + -- * 1 + elseif peak == 0 then + -- * 1 + elseif f < start or f > stop then + -- * 0 + s = 0 + break + elseif f < peak then + s = s * (f - start) / (peak - start) + elseif f > peak then + s = s * (stop - f) / (stop - peak) + else + -- * 1 + end + end + if s == 0 then + if name then + report("no deltas applied for glyph %a",name) + end + else + deltas[#deltas+1] = { + factor = s, + points = points, + xvalues = xvalues, + yvalues = yvalues, + } + end + end + if shape.type == "glyph" then + applyaxis(glyph,shape,deltas,dowidth) + else + -- todo: args_are_xy_values mess .. i have to be really bored + -- and motivated to deal with it + shape.deltas = deltas + end + end + end + startoffset = nextoffset + end + end +end diff --git a/tex/context/base/mkxl/libs-ini.lmt b/tex/context/base/mkxl/libs-ini.lmt new file mode 100644 index 000000000..4ce0e8e50 --- /dev/null +++ b/tex/context/base/mkxl/libs-ini.lmt @@ -0,0 +1,206 @@ +if not modules then modules = { } end modules ['libs-ini'] = { + version = 1.001, + comment = "companion to luat-lib.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- This is a loader for optional libraries in luametatex with context lmtx. It's +-- kind of experimental. We also use a different locator than in mkiv because we +-- don't support loading lua libraries and swiglibs any more. Of course one can try +-- the regular lua loaders but we just assume that a user then knows what (s)he is +-- doing. At some point this variant will divert more from the original loader +-- file 'libs-ini.lua'. + +local type, unpack = type, unpack +local find = string.find + +-- here we implement the resolver + +local nameonly = file.nameonly +local joinfile = file.join +local addsuffix = file.addsuffix +local qualifiedpath = file.is_qualified_path + +local isfile = lfs.isfile + +local findfile = resolvers.findfile +local expandpaths = resolvers.expandedpathlistfromvariable + +local report = logs.reporter("resolvers","libraries") +local trace = false +local silent = false + +trackers.register("resolvers.lib", function(v) trace = v end) +trackers.register("resolvers.lib.silent", function(v) silent = v end) + +local function findlib(required) -- todo: cache + local suffix = os.libsuffix or "so" + if not qualifiedpath(required) then + local list = directives.value("system.librarynames" ) + local only = nameonly(required) + if type(list) == "table" then + list = list[only] + if type(list) ~= "table" then + list = { only } + end + else + list = { only } + end + if trace then + report("using lookup list for library %a: % | t",only,list) + end + for i=1,#list do + local name = list[i] + local found = findfile(name,"lib") + if not found or found == "" then + found = findfile(addsuffix(name,suffix),"lib") + end + if found and found ~= "" then + if trace then + report("library %a resolved via %a path to %a",name,"tds lib",found) + end + return found + end + end + if expandpaths then + local list = expandpaths("PATH") + local base = addsuffix(only,suffix) + for i=1,#list do + local full = joinfile(list[i],base) + local found = isfile(full) and full + if found and found ~= "" then + if trace then + report("library %a resolved via %a path to %a",full,"system",found) + end + return found + end + end + end + elseif isfile(addsuffix(required,suffix)) then + if trace then + report("library with qualified name %a %sfound",required,"") + end + return required + else + if trace then + report("library with qualified name %a %sfound",required,"not ") + end + end + return false +end + +local foundlibraries = table.setmetatableindex(function(t,k) + local v = findlib(k) + t[k] = v + return v +end) + +function resolvers.findlib(required) + return foundlibraries[required] +end + +-- here we implement the loader + +local libraries = { } +resolvers.libraries = libraries + +local report = logs.reporter("optional") + +if optional then optional.loaded = { } end + +function libraries.validoptional(name) + local thelib = optional and optional[name] + if not thelib then + -- forget about it, no message here + elseif thelib.initialize then + return thelib + else + report("invalid optional library %a",libname) + end +end + +function libraries.optionalloaded(name,libnames) + local thelib = optional and optional[name] + if not thelib then + report("no optional %a library found",name) + else + local thelib_initialize = thelib.initialize + if not thelib_initialize then + report("invalid optional library %a",name) + else + if type(libnames) == "string" then + libnames = { libnames } + end + if type(libnames) == "table" then + for i=1,#libnames do + local libname = libnames[i] + local filename = foundlibraries[libname] + if filename and filename ~= "" then + libnames[i] = filename + else + report("unable to locate library %a",libname) + return + end + end + local initialized = thelib_initialize(unpack(libnames)) + if not initialized then + report("unable to initialize library '% + t'",libnames) + elseif not silent then + report("using library '% + t'",libnames) + end + return initialized + end + end + end +end + +-- local patterns = { +-- "libs-imp-%s.mkxl", +-- "libs-imp-%s.mklx", +-- } +-- +-- local function action(name,foundname) +-- -- could be one command +-- context.startreadingfile() +-- context.input(foundname) +-- context.stopreadingfile() +-- end +-- +-- interfaces.implement { +-- name = "uselibrary", +-- arguments = "string" +-- actions = function(name) +-- resolvers.uselibrary { +-- category = "color definition", +-- name = name, +-- patterns = patterns, +-- action = action, +-- onlyonce = true, +-- } +-- end +-- } + +-- We overload the standard 'require' function. Because we're in LuaMetaTeX we are +-- more likely to find 'lmt' files when we deal with the TeX and MetaPost part but +-- user files likely have the 'lua' suffix. + +do + + local dofile = dofile + local savedrequire = require + + function require(name,version) + if find(name,"%.lua$") or find(name,"%.lmt$") then + local m = dofile(findfile(name)) + if m then + package.loaded[name] = m + return m + end + else + return savedrequire(name) + end + end + +end diff --git a/tex/context/base/mkxl/libs-ini.mkxl b/tex/context/base/mkxl/libs-ini.mkxl index ef24536bf..bc1fe92e0 100644 --- a/tex/context/base/mkxl/libs-ini.mkxl +++ b/tex/context/base/mkxl/libs-ini.mkxl @@ -11,12 +11,12 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\registerctxluafile{libs-ini}{} % shared with mkiv +\registerctxluafile{libs-ini}{autosuffix} % These are used by the graphic converters: -\registerctxluafile{libs-imp-curl}{autosuffix} -\registerctxluafile{libs-imp-ghostscript}{autosuffix} +\registerctxluafile{libs-imp-curl} {autosuffix} +\registerctxluafile{libs-imp-ghostscript} {autosuffix} \registerctxluafile{libs-imp-graphicsmagick}{autosuffix} % These are loaded on demand: diff --git a/tex/context/base/mkxl/luat-lib.mkxl b/tex/context/base/mkxl/luat-lib.mkxl index 7ad29e29e..cb161cafa 100644 --- a/tex/context/base/mkxl/luat-lib.mkxl +++ b/tex/context/base/mkxl/luat-lib.mkxl @@ -61,7 +61,7 @@ \registerctxluafile{data-pre}{} % after data-res \registerctxluafile{data-bin}{} % before data-tex \registerctxluafile{data-tex}{} % after data-pre -\registerctxluafile{data-vir}{} +\registerctxluafile{data-vir}{autosuffix} \registerctxluafile{data-zip}{} \registerctxluafile{data-dec}{} \registerctxluafile{data-tar}{} diff --git a/tex/context/base/mkxl/math-act.lmt b/tex/context/base/mkxl/math-act.lmt index faa0d2ae5..19a43ce87 100644 --- a/tex/context/base/mkxl/math-act.lmt +++ b/tex/context/base/mkxl/math-act.lmt @@ -321,7 +321,7 @@ mathtweaks.subsets = { p = { 0x1D45D }, dotless = { 0x00049, 0x0004A, 0x00131, 0x00237, 0x1D6A4, 0x1D6A5 }, integrals = { 0x0222B, 0x0222C, 0x0222D, 0x0222E, 0x0222F, 0x02230, 0x02231, 0x02232, 0x02233, 0x02A0B, 0x02A0C, 0x02A0D, 0x02A0E, 0x02A0F, 0x02A10, 0x02A11, 0x02A12, 0x02A13, 0x02A14, 0x02A15, 0x02A16, 0x02A17, 0x02A18, 0x02A19, 0x02A1A, 0x02A1B, 0x02A1C, 0x02320, 0x02321 }, - horizontalfences = { 0x023B4, 0x023B5, 0x023DC, 0x023DD, 0x023DE, 0x023DF, 0x023E0, 0x023E1 }, -- not really used + horizontalfences = { 0x0203E, 0x023B4, 0x023B5, 0x023DC, 0x023DD, 0x023DE, 0x023DF, 0x023E0, 0x023E1 }, -- not really used } local function getalso(target,original) @@ -1844,7 +1844,8 @@ do parts = { { advance = width, ["end"] = step, glyph = 0x203E, start = 0 }, { advance = width, ["end"] = 0, glyph = 0x203E, start = step, extender = 1 }, - } + }, + partsorientation = "horizontal", } -- characters[0x0332] = characters[0x203E] @@ -1872,7 +1873,8 @@ do { advance = thickness, glyph = tpiece, ["end"] = 0, start = half }, { advance = width, glyph = 0x203E, ["end"] = step, start = step, extender = 1 }, { advance = thickness, glyph = tpiece, ["end"] = half, start = 0 }, - } + }, + partsorientation = "horizontal", } end if not characters[0x23B5] then @@ -1893,7 +1895,8 @@ do { advance = thickness, glyph = bpiece, ["end"] = 0, start = half }, { advance = width, glyph = 0x203E, ["end"] = step, start = step, extender = 1 }, { advance = thickness, glyph = bpiece, ["end"] = half, start = 0 }, - } + }, + partsorientation = "horizontal", } end -- @@ -1932,7 +1935,8 @@ do end if chardata and (force or overloads[unicode] == false or not chardata.parts) then if not list then - chardata.parts = nil -- when we test + -- chardata.parts = nil -- when we test + chardata.parts = { { glyph = unicode } } else local overload = overloads[unicode] local parts = { } @@ -2030,6 +2034,7 @@ do [0x21CB] = centered, -- leftrightharpoons [0x21CC] = centered, -- rightleftharpoons [0x21C4] = centered, -- rightoverleftarrow + [0x21C6] = centered, -- leftoverrightarrow [0x21A6] = centered, -- mapsto -- [0x203E] = { slackslack, { left = slack, right = slack, extensible = true } }, -- bar diff --git a/tex/context/base/mkxl/math-rad.mklx b/tex/context/base/mkxl/math-rad.mklx index 645d32740..cb3cdb0a8 100644 --- a/tex/context/base/mkxl/math-rad.mklx +++ b/tex/context/base/mkxl/math-rad.mklx @@ -26,7 +26,7 @@ % \def\rootradical{\Uroot 0 "221A } % can be done in char-def % \def\surdradical{\Uradical 0 "221A } % can be done in char-def -\protected\def\sqrt{\doifelsenextoptionalcs\rootwithdegree\rootwithoutdegree} % will be redefined +% \protected\def\sqrt{\doifelsenextoptionalcs\rootwithdegree\rootwithoutdegree} % will be redefined % \permanent\protected\def\styledrootradical#1#2% so that \text works ok ... \rootradical behaves somewhat weird % {\normalexpanded{\math_radical_common @@ -39,8 +39,8 @@ % \permanent\protected\def\styledrootradical#1#2% so that \text works ok ... \rootradical behaves somewhat weird % {\Uroot style \normalmathstyle "0 "221A {#1}{#2}} -\permanent\protected\def\rootwithdegree[#1]{\math_radical_common{#1}} -\permanent\protected\def\rootwithoutdegree {\math_radical_common {}} +% \permanent\protected\def\rootwithdegree[#1]{\math_radical_common{#1}} +% \permanent\protected\def\rootwithoutdegree {\math_radical_common {}} %D Even older stuff: @@ -79,6 +79,20 @@ %D $ \sqrt[3]{5} \RR\sqrt[3]{5} \sqrt[3]{5} $\par %D $ \sqrt[3]{5} {\RR\sqrt[3]{5}} \sqrt[3]{5} $\par %D \stoptyping +%D +%D And: +%D +%D \starttyping +%D \definemathradical[lsqrt][strut=yes] +%D \definemathradical[msqrt][strut=math] +%D \definemathradical[xsqrt][height=3ex,depth=2ex] +%D +%D $\sqrt[strut=no][3]{y}$ +%D $\sqrt[strut=no,n=5]{y}$ +%D $\sqrt[strut=no,n=5][6]{y}$ +%D $\sqrt[strut=math]{y}$ +%D $\sqrt[3]{y}$ +%D \stoptyping \installcorenamespace{mathradical} \installcorenamespace{mathradicalalternative} @@ -117,9 +131,14 @@ \tolerant\protected\def\math_radical_handle#tag#*[#settings]#*[#degree]#:#body% {\begingroup \edef\currentmathradical{#tag}% - \ifparameter#degree\or - \edef\currentmathradicaldegree{#degree}% + \ifhastok={#settings}% + \lettonothing\currentmathradicaldegree \setupcurrentmathradical[#settings]% + \ifparameter#degree\or + \edef\currentmathradicaldegree{#degree}% + \else + \edef\currentmathradicaldegree{\mathradicalparameter\c!n}% + \fi \else \edef\currentmathradicaldegree{#settings}% \fi @@ -253,7 +272,12 @@ \fi \endgroup} -\definemathradical[sqrt][mp=minifun::math:radical:default] +\pushoverloadmode + +\definemathradical[root][mp=minifun::math:radical:default] +\definemathradical[sqrt][root] + +\popoverloadmode % \setupmathradical[sqrt][alternative=normal,color=darkblue] % \setupmathradical[sqrt][alternative=mp,color=darkgreen] diff --git a/tex/context/base/mkxl/math-stc.mklx b/tex/context/base/mkxl/math-stc.mklx index 952fba6c6..5922fb116 100644 --- a/tex/context/base/mkxl/math-stc.mklx +++ b/tex/context/base/mkxl/math-stc.mklx @@ -98,19 +98,30 @@ \fi \hss}} -\def\math_stackers_regular - {\mathstylehbox{\usemathstackerscolorparameter\c!color - \hskip\d_math_stackers_offset_l - \Umathaccent\zerocount\zerocount\scratchunicode - {\hskip\dimexpr\scratchwidth-\d_math_stackers_offset_l-\d_math_stackers_offset_r}% - \hskip\d_math_stackers_offset_r - }} +% \def\math_stackers_regular +% {\mathstylehbox{\usemathstackerscolorparameter\c!color +% \hskip\d_math_stackers_offset_l +% \Umathaccent\zerocount\zerocount\scratchunicode +% {\hskip\dimexpr\scratchwidth-\d_math_stackers_offset_l-\d_math_stackers_offset_r}% +% \hskip\d_math_stackers_offset_r +% }} + +% \def\math_stackers_stretch % we don't have that one yet +% {\mathstylehbox{\usemathstackerscolorparameter\c!color +% \hskip\d_math_stackers_offset_l +% \Umathaccent\zerocount\zerocount\scratchunicode +% {\hskip\dimexpr\hsize-\d_math_stackers_offset_l-\d_math_stackers_offset_r}% +% \hskip\d_math_stackers_offset_r +% }} -\def\math_stackers_stretch % we don't have that one yet +\def\math_stackers_regular {\mathstylehbox{\usemathstackerscolorparameter\c!color \hskip\d_math_stackers_offset_l - \Umathaccent\zerocount\zerocount\scratchunicode - {\hskip\dimexpr\hsize-\d_math_stackers_offset_l-\d_math_stackers_offset_r}% + \Uhextensible + middle + width \dimexpr\scratchwidth-\d_math_stackers_offset_l-\d_math_stackers_offset_r\relax + \zerocount\scratchunicode + \relax \hskip\d_math_stackers_offset_r }} @@ -410,6 +421,9 @@ \setbox\scratchboxthree\csname\??mathstackersalternative\p_alternative\endcsname \dostoptagged \fi + \ifdim\wd\scratchboxthree>\scratchwidth + \scratchwidth\wd\scratchboxthree + \fi % \ifdim\wd\scratchboxone<\scratchwidth \setbox\scratchboxone\hpack to \scratchwidth{\hss\unhbox\scratchboxone\hss}% unhboxing makes leaders work @@ -1192,8 +1206,6 @@ \definemathextensible [\v!chemistry] [crightoverleftarrow] ["21C4] \definemathextensible [\v!chemistry] [cleftoverrightarrow] ["21C6] -% for the moment: - \def\math_stackers_hacked_fill#1#2#3% {\mathematics {\begingroup @@ -1203,35 +1215,37 @@ \thinmuskip \zeromuskip \tinymuskip \zeromuskip \pettymuskip \zeromuskip - #1% - \mkern-7\onemuskip - \cleaders\mathstylehbox{\mkern-2\onemuskip#2\mkern-2\onemuskip}\hfill - \mkern-7\onemuskip - #3% + \ifrelax#1% + \cleaders\mathstylehbox{#2}\hfill + \else + #1% + \mkern-7\onemuskip + \cleaders\mathstylehbox{\mkern-2\onemuskip#2\mkern-2\onemuskip}\hfill + \mkern-7\onemuskip + #3% + \fi \endgroup}} -% These will become characters defined in math-act. - -\immutable\protected\def\rightarrowfill {\math_stackers_hacked_fill \relbar \relbar \rightarrow} -\immutable\protected\def\leftarrowfill {\math_stackers_hacked_fill \leftarrow \relbar \relbar } -\immutable\protected\def\rightoverleftarrowfill{\math_stackers_hacked_fill \ctxdoublearrowfillleftend\ctxdoublearrowfillmiddlepart\ctxdoublearrowfillrightend} -\immutable\protected\def\leftoverrightarrowfill{\math_stackers_hacked_fill \ctxdoublearrowfillrightend\ctxdoublearrowfillmiddlepart\ctxdoublearrowfillleftend} -\immutable\protected\def\equalfill {\math_stackers_hacked_fill \Relbar \Relbar \Relbar} -\immutable\protected\def\Rightarrowfill {\math_stackers_hacked_fill \Relbar \Relbar \Rightarrow} -\immutable\protected\def\Leftarrowfill {\math_stackers_hacked_fill \Leftarrow \Relbar \Relbar} -\immutable\protected\def\Leftrightarrowfill {\math_stackers_hacked_fill \Leftarrow \Relbar \Rightarrow} -\immutable\protected\def\leftrightarrowfill {\math_stackers_hacked_fill \leftarrow \relbar \rightarrow} -\immutable\protected\def\mapstofill {\math_stackers_hacked_fill{\mapstochar\relbar} \relbar \rightarrow} -\immutable\protected\def\twoheadrightarrowfill {\math_stackers_hacked_fill \relbar \relbar \twoheadrightarrow} -\immutable\protected\def\twoheadleftarrowfill {\math_stackers_hacked_fill \twoheadleftarrow \relbar \relbar} -\immutable\protected\def\rightharpoondownfill {\math_stackers_hacked_fill \relbar \relbar \rightharpoondown} -\immutable\protected\def\rightharpoonupfill {\math_stackers_hacked_fill \relbar \relbar \rightharpoonup} -\immutable\protected\def\leftharpoondownfill {\math_stackers_hacked_fill \leftharpoondown \relbar \relbar} -\immutable\protected\def\leftharpoonupfill {\math_stackers_hacked_fill \leftharpoonup \relbar \relbar} -\immutable\protected\def\hookleftfill {\math_stackers_hacked_fill \leftarrow \relbar {\relbar\joinrel\rhook}} -\immutable\protected\def\hookrightfill {\math_stackers_hacked_fill{\lhook\joinrel\relbar} \relbar \rightarrow} -\immutable\protected\def\relfill {\math_stackers_hacked_fill \relbar \relbar \relbar} -\immutable\protected\def\triplerelfill {\math_stackers_hacked_fill \equiv \equiv \equiv} +\immutable\protected\def\rightarrowfill {\math_stackers_hacked_fill \relbar \relbar \rightarrow} +\immutable\protected\def\leftarrowfill {\math_stackers_hacked_fill \leftarrow \relbar \relbar} +\immutable\protected\def\rightoverleftarrowfill{\math_stackers_hacked_fill \relax \crightoverleftarrow \relax} +\immutable\protected\def\leftoverrightarrowfill{\math_stackers_hacked_fill \relax \cleftoverrightarrow \relax} +\immutable\protected\def\equalfill {\math_stackers_hacked_fill \Relbar \Relbar \Relbar} +\immutable\protected\def\Rightarrowfill {\math_stackers_hacked_fill \Relbar \Relbar \Rightarrow} +\immutable\protected\def\Leftarrowfill {\math_stackers_hacked_fill \Leftarrow \Relbar \Relbar} +\immutable\protected\def\Leftrightarrowfill {\math_stackers_hacked_fill \Leftarrow \Relbar \Rightarrow} +\immutable\protected\def\leftrightarrowfill {\math_stackers_hacked_fill \leftarrow \relbar \rightarrow} +\immutable\protected\def\mapstofill {\math_stackers_hacked_fill{\mapstochar\relbar} \relbar \rightarrow} +\immutable\protected\def\twoheadrightarrowfill {\math_stackers_hacked_fill \relbar \relbar \twoheadrightarrow} +\immutable\protected\def\twoheadleftarrowfill {\math_stackers_hacked_fill \twoheadleftarrow \relbar \relbar} +\immutable\protected\def\rightharpoondownfill {\math_stackers_hacked_fill \relbar \relbar \rightharpoondown} +\immutable\protected\def\rightharpoonupfill {\math_stackers_hacked_fill \relbar \relbar \rightharpoonup} +\immutable\protected\def\leftharpoondownfill {\math_stackers_hacked_fill \leftharpoondown \relbar \relbar} +\immutable\protected\def\leftharpoonupfill {\math_stackers_hacked_fill \leftharpoonup \relbar \relbar} +\immutable\protected\def\hookleftfill {\math_stackers_hacked_fill \leftarrow \relbar {\relbar\joinrel\rhook}} +\immutable\protected\def\hookrightfill {\math_stackers_hacked_fill{\lhook\joinrel\relbar}\relbar \rightarrow} +\immutable\protected\def\relfill {\math_stackers_hacked_fill \relbar \relbar \relbar} +\immutable\protected\def\triplerelfill {\math_stackers_hacked_fill \equiv \equiv \equiv} %D For the moment (needs checking): diff --git a/tex/context/base/mkxl/math-ttv.lmt b/tex/context/base/mkxl/math-ttv.lmt index 06e934dcd..e33a23478 100644 --- a/tex/context/base/mkxl/math-ttv.lmt +++ b/tex/context/base/mkxl/math-ttv.lmt @@ -152,6 +152,11 @@ mathencodings["tex-mr-missing"] = { [0x02236] = 0x3A, -- colon } +mathencodings["tex-ex-braces"] = { + [0x0007B] = 0x7B, -- {, braceleftbig + [0x0007D] = 0x7D, -- }, bracerightbig +} + mathencodings["tex-mi"] = { [0x1D6E4] = 0x00, -- Gamma [0x1D6E5] = 0x01, -- Delta @@ -463,275 +468,275 @@ mathencodings["tex-sy"] = { [0xFE325] = 0x30, -- prime 0x02032 } --- The names in masm10.enc can be trusted best and are shown in the first --- column, while in the second column we show the tex/ams names. As usual --- it costs hours to figure out such a table. - -mathencodings["tex-ma"] = { - [0x022A1] = 0x00, -- squaredot \boxdot - [0x0229E] = 0x01, -- squareplus \boxplus - [0x022A0] = 0x02, -- squaremultiply \boxtimes - [0x025A1] = 0x03, -- square \square \Box - [0x025A0] = 0x04, -- squaresolid \blacksquare - [0x025AA] = 0x05, -- squaresmallsolid \centerdot - [0x022C4] = 0x06, -- diamond \Diamond \lozenge - [0x02666] = 0x07, -- diamondsolid \blacklozenge - [0x021BB] = 0x08, -- clockwise \circlearrowright - [0x021BA] = 0x09, -- anticlockwise \circlearrowleft - [0x021CC] = 0x0A, -- harpoonleftright \rightleftharpoons - [0x021CB] = 0x0B, -- harpoonrightleft \leftrightharpoons - [0x0229F] = 0x0C, -- squareminus \boxminus - [0x022A9] = 0x0D, -- forces \Vdash - [0x022AA] = 0x0E, -- forcesbar \Vvdash - [0x022A8] = 0x0F, -- satisfies \vDash - [0x021A0] = 0x10, -- dblarrowheadright \twoheadrightarrow - [0x0219E] = 0x11, -- dblarrowheadleft \twoheadleftarrow - [0x021C7] = 0x12, -- dblarrowleft \leftleftarrows - [0x021C9] = 0x13, -- dblarrowright \rightrightarrows - [0x021C8] = 0x14, -- dblarrowup \upuparrows - [0x021CA] = 0x15, -- dblarrowdwn \downdownarrows - [0x021BE] = 0x16, -- harpoonupright \upharpoonright \restriction - [0x021C2] = 0x17, -- harpoondownright \downharpoonright - [0x021BF] = 0x18, -- harpoonupleft \upharpoonleft - [0x021C3] = 0x19, -- harpoondownleft \downharpoonleft - [0x021A3] = 0x1A, -- arrowtailright \rightarrowtail - [0x021A2] = 0x1B, -- arrowtailleft \leftarrowtail - [0x021C6] = 0x1C, -- arrowparrleftright \leftrightarrows --- [0x021C5] = 0x00, -- \updownarrows (missing in lm) - [0x021C4] = 0x1D, -- arrowparrrightleft \rightleftarrows - [0x021B0] = 0x1E, -- shiftleft \Lsh - [0x021B1] = 0x1F, -- shiftright \Rsh - [0x021DD] = 0x20, -- squiggleright \leadsto \rightsquigarrow - [0x021AD] = 0x21, -- squiggleleftright \leftrightsquigarrow - [0x021AB] = 0x22, -- curlyleft \looparrowleft - [0x021AC] = 0x23, -- curlyright \looparrowright - [0x02257] = 0x24, -- circleequal \circeq - [0x0227F] = 0x25, -- followsorequal \succsim - [0x02273] = 0x26, -- greaterorsimilar \gtrsim - [0x02A86] = 0x27, -- greaterorapproxeql \gtrapprox - [0x022B8] = 0x28, -- multimap \multimap - [0x02234] = 0x29, -- therefore \therefore - [0x02235] = 0x2A, -- because \because - [0x02251] = 0x2B, -- equalsdots \Doteq \doteqdot - [0x0225C] = 0x2C, -- defines \triangleq - [0x0227E] = 0x2D, -- precedesorequal \precsim - [0x02272] = 0x2E, -- lessorsimilar \lesssim - [0x02A85] = 0x2F, -- lessorapproxeql \lessapprox - [0x02A95] = 0x30, -- equalorless \eqslantless - [0x02A96] = 0x31, -- equalorgreater \eqslantgtr - [0x022DE] = 0x32, -- equalorprecedes \curlyeqprec - [0x022DF] = 0x33, -- equalorfollows \curlyeqsucc - [0x0227C] = 0x34, -- precedesorcurly \preccurlyeq - [0x02266] = 0x35, -- lessdblequal \leqq - [0x02A7D] = 0x36, -- lessorequalslant \leqslant - [0x02276] = 0x37, -- lessorgreater \lessgtr - [0x02035] = 0x38, -- primereverse \backprime - -- [0x0] = 0x39, -- axisshort \dabar - [0x02253] = 0x3A, -- equaldotrightleft \risingdotseq - [0x02252] = 0x3B, -- equaldotleftright \fallingdotseq - [0x0227D] = 0x3C, -- followsorcurly \succcurlyeq - [0x02267] = 0x3D, -- greaterdblequal \geqq - [0x02A7E] = 0x3E, -- greaterorequalslant \geqslant - [0x02277] = 0x3F, -- greaterorless \gtrless - [0x0228F] = 0x40, -- squareimage \sqsubset - [0x02290] = 0x41, -- squareoriginal \sqsupset - -- wrong: see ** - -- [0x022B3] = 0x42, -- triangleright \rhd \vartriangleright - -- [0x022B2] = 0x43, -- triangleleft \lhd \vartriangleleft - -- cf lm - [0x022B5] = 0x44, -- trianglerightequal \unrhd \trianglerighteq - [0x022B4] = 0x45, -- triangleleftequal \unlhd \trianglelefteq - -- - [0x02605] = 0x46, -- star \bigstar - [0x0226C] = 0x47, -- between \between - [0x025BC] = 0x48, -- triangledownsld \blacktriangledown - [0x025B6] = 0x49, -- trianglerightsld \blacktriangleright - [0x025C0] = 0x4A, -- triangleleftsld \blacktriangleleft - -- [0x0] = 0x4B, -- arrowaxisright - -- [0x0] = 0x4C, -- arrowaxisleft - [0x025B2] = 0x4D, -- triangle \triangleup \vartriangle - [0x025B2] = 0x4E, -- trianglesolid \blacktriangle - [0x025BD] = 0x4F, -- triangleinv \triangledown - [0x02256] = 0x50, -- ringinequal \eqcirc - [0x022DA] = 0x51, -- lessequalgreater \lesseqgtr - [0x022DB] = 0x52, -- greaterlessequal \gtreqless - [0x02A8B] = 0x53, -- lessdbleqlgreater \lesseqqgtr - [0x02A8C] = 0x54, -- greaterdbleqlless \gtreqqless - [0x000A5] = 0x55, -- Yen \yen - [0x021DB] = 0x56, -- arrowtripleright \Rrightarrow - [0x021DA] = 0x57, -- arrowtripleleft \Lleftarrow - [0x02713] = 0x58, -- check \checkmark - [0x022BB] = 0x59, -- orunderscore \veebar - [0x022BC] = 0x5A, -- nand \barwedge - [0x02306] = 0x5B, -- perpcorrespond \doublebarwedge - [0x02220] = 0x5C, -- angle \angle - [0x02221] = 0x5D, -- measuredangle \measuredangle - [0x02222] = 0x5E, -- sphericalangle \sphericalangle - -- [0x0] = 0x5F, -- proportional \varpropto - -- [0x0] = 0x60, -- smile \smallsmile - -- [0x0] = 0x61, -- frown \smallfrown - [0x022D0] = 0x62, -- subsetdbl \Subset - [0x022D1] = 0x63, -- supersetdbl \Supset - [0x022D3] = 0x64, -- uniondbl \doublecup \Cup - [0x022D2] = 0x65, -- intersectiondbl \doublecap \Cap - [0x022CF] = 0x66, -- uprise \curlywedge - [0x022CE] = 0x67, -- downfall \curlyvee - [0x022CB] = 0x68, -- multiopenleft \leftthreetimes - [0x022CC] = 0x69, -- multiopenright \rightthreetimes - [0x02AC5] = 0x6A, -- subsetdblequal \subseteqq - [0x02AC6] = 0x6B, -- supersetdblequal \supseteqq - [0x0224F] = 0x6C, -- difference \bumpeq - [0x0224E] = 0x6D, -- geomequivalent \Bumpeq - [0x022D8] = 0x6E, -- muchless \lll \llless - [0x022D9] = 0x6F, -- muchgreater \ggg \gggtr - [0x0231C] = 0x70, -- rightanglenw \ulcorner - [0x0231D] = 0x71, -- rightanglene \urcorner - [0x024C7] = 0x72, -- circleR \circledR - [0x024C8] = 0x73, -- circleS \circledS - [0x022D4] = 0x74, -- fork \pitchfork - [0x02214] = 0x75, -- dotplus \dotplus - [0x0223D] = 0x76, -- revsimilar \backsim - [0x022CD] = 0x77, -- revasymptequal \backsimeq -- AM: Check this! I mapped it to simeq. - [0x0231E] = 0x78, -- rightanglesw \llcorner - [0x0231F] = 0x79, -- rightanglese \lrcorner - [0x02720] = 0x7A, -- maltesecross \maltese - [0x02201] = 0x7B, -- complement \complement - [0x022BA] = 0x7C, -- intercal \intercal - [0x0229A] = 0x7D, -- circlering \circledcirc - [0x0229B] = 0x7E, -- circleasterisk \circledast - [0x0229D] = 0x7F, -- circleminus \circleddash -} - -mathencodings["tex-mb"] = { - -- [0x0] = 0x00, -- lessornotequal \lvertneqq - -- [0x0] = 0x01, -- greaterornotequal \gvertneqq - [0x02270] = 0x02, -- notlessequal \nleq - [0x02271] = 0x03, -- notgreaterequal \ngeq - [0x0226E] = 0x04, -- notless \nless - [0x0226F] = 0x05, -- notgreater \ngtr - [0x02280] = 0x06, -- notprecedes \nprec - [0x02281] = 0x07, -- notfollows \nsucc - [0x02268] = 0x08, -- lessornotdbleql \lneqq - [0x02269] = 0x09, -- greaterornotdbleql \gneqq - -- [0x0] = 0x0A, -- notlessorslnteql \nleqslant - -- [0x0] = 0x0B, -- notgreaterorslnteql \ngeqslant - [0x02A87] = 0x0C, -- lessnotequal \lneq - [0x02A88] = 0x0D, -- greaternotequal \gneq - -- [0x0] = 0x0E, -- notprecedesoreql \npreceq - -- [0x0] = 0x0F, -- notfollowsoreql \nsucceq - [0x022E8] = 0x10, -- precedeornoteqvlnt \precnsim - [0x022E9] = 0x11, -- followornoteqvlnt \succnsim - [0x022E6] = 0x12, -- lessornotsimilar \lnsim - [0x022E7] = 0x13, -- greaterornotsimilar \gnsim - -- [0x0] = 0x14, -- notlessdblequal \nleqq - -- [0x0] = 0x15, -- notgreaterdblequal \ngeqq - [0x02AB5] = 0x16, -- precedenotslnteql \precneqq - [0x02AB6] = 0x17, -- follownotslnteql \succneqq - [0x02AB9] = 0x18, -- precedenotdbleqv \precnapprox - [0x02ABA] = 0x19, -- follownotdbleqv \succnapprox - [0x02A89] = 0x1A, -- lessnotdblequal \lnapprox - [0x02A8A] = 0x1B, -- greaternotdblequal \gnapprox - [0x02241] = 0x1C, -- notsimilar \nsim - [0x02247] = 0x1D, -- notapproxequal \ncong - -- [0x0] = 0x1E, -- upslope \diagup - -- [0x0] = 0x1F, -- downslope \diagdown - -- [0x0] = 0x20, -- notsubsetoreql \varsubsetneq - -- [0x0] = 0x21, -- notsupersetoreql \varsupsetneq - -- [0x0] = 0x22, -- notsubsetordbleql \nsubseteqq - -- [0x0] = 0x23, -- notsupersetordbleql \nsupseteqq - [0x02ACB] = 0x24, -- subsetornotdbleql \subsetneqq - [0x02ACC] = 0x25, -- supersetornotdbleql \supsetneqq - -- [0x0] = 0x26, -- subsetornoteql \varsubsetneqq - -- [0x0] = 0x27, -- supersetornoteql \varsupsetneqq - [0x0228A] = 0x28, -- subsetnoteql \subsetneq - [0x0228B] = 0x29, -- supersetnoteql \supsetneq - [0x02288] = 0x2A, -- notsubseteql \nsubseteq - [0x02289] = 0x2B, -- notsuperseteql \nsupseteq - [0x02226] = 0x2C, -- notparallel \nparallel - [0x02224] = 0x2D, -- notbar \nmid \ndivides - -- [0x0] = 0x2E, -- notshortbar \nshortmid - -- [0x0] = 0x2F, -- notshortparallel \nshortparallel - [0x022AC] = 0x30, -- notturnstile \nvdash - [0x022AE] = 0x31, -- notforces \nVdash - [0x022AD] = 0x32, -- notsatisfies \nvDash - [0x022AF] = 0x33, -- notforcesextra \nVDash - [0x022ED] = 0x34, -- nottriangeqlright \ntrianglerighteq - [0x022EC] = 0x35, -- nottriangeqlleft \ntrianglelefteq - [0x022EA] = 0x36, -- nottriangleleft \ntriangleleft - [0x022EB] = 0x37, -- nottriangleright \ntriangleright - [0x0219A] = 0x38, -- notarrowleft \nleftarrow - [0x0219B] = 0x39, -- notarrowright \nrightarrow - [0x021CD] = 0x3A, -- notdblarrowleft \nLeftarrow - [0x021CF] = 0x3B, -- notdblarrowright \nRightarrow - [0x021CE] = 0x3C, -- notdblarrowboth \nLeftrightarrow - [0x021AE] = 0x3D, -- notarrowboth \nleftrightarrow - [0x022C7] = 0x3E, -- dividemultiply \divideontimes - [0x02300] = 0x3F, -- diametersign \varnothing - [0x02204] = 0x40, -- notexistential \nexists - [0x1D538] = 0x41, -- A (blackboard A) - [0x1D539] = 0x42, -- B - [0x02102] = 0x43, -- C - [0x1D53B] = 0x44, -- D - [0x1D53C] = 0x45, -- E - [0x1D53D] = 0x46, -- F - [0x1D53E] = 0x47, -- G - [0x0210D] = 0x48, -- H - [0x1D540] = 0x49, -- I - [0x1D541] = 0x4A, -- J - [0x1D542] = 0x4B, -- K - [0x1D543] = 0x4C, -- L - [0x1D544] = 0x4D, -- M - [0x02115] = 0x4E, -- N - [0x1D546] = 0x4F, -- O - [0x02119] = 0x50, -- P - [0x0211A] = 0x51, -- Q - [0x0211D] = 0x52, -- R - [0x1D54A] = 0x53, -- S - [0x1D54B] = 0x54, -- T - [0x1D54C] = 0x55, -- U - [0x1D54D] = 0x56, -- V - [0x1D54E] = 0x57, -- W - [0x1D54F] = 0x58, -- X - [0x1D550] = 0x59, -- Y - [0x02124] = 0x5A, -- Z (blackboard Z) - [0x02132] = 0x60, -- finv \Finv - [0x02141] = 0x61, -- fmir \Game - -- [0x0] = 0x62, tildewide - -- [0x0] = 0x63, tildewider - -- [0x0] = 0x64, Finv - -- [0x0] = 0x65, Gmir - [0x02127] = 0x66, -- Omegainv \mho - [0x000F0] = 0x67, -- eth \eth - [0x02242] = 0x68, -- equalorsimilar \eqsim - [0x02136] = 0x69, -- beth \beth - [0x02137] = 0x6A, -- gimel \gimel - [0x02138] = 0x6B, -- daleth \daleth - [0x022D6] = 0x6C, -- lessdot \lessdot - [0x022D7] = 0x6D, -- greaterdot \gtrdot - [0x022C9] = 0x6E, -- multicloseleft \ltimes - [0x022CA] = 0x6F, -- multicloseright \rtimes - -- [0x0] = 0x70, -- barshort \shortmid - -- [0x0] = 0x71, -- parallelshort \shortparallel - -- [0x02216] = 0x72, -- integerdivide \smallsetminus (2216 already part of tex-sy - -- [0x0] = 0x73, -- similar \thicksim - -- [0x0] = 0x74, -- approxequal \thickapprox - [0x0224A] = 0x75, -- approxorequal \approxeq - [0x02AB8] = 0x76, -- followsorequal \succapprox - [0x02AB7] = 0x77, -- precedesorequal \precapprox - [0x021B6] = 0x78, -- archleftdown \curvearrowleft - [0x021B7] = 0x79, -- archrightdown \curvearrowright - [0x003DC] = 0x7A, -- Digamma \digamma - [0x003F0] = 0x7B, -- kappa \varkappa - [0x1D55C] = 0x7C, -- k \Bbbk (blackboard k) - [0x0210F] = 0x7D, -- planckover2pi \hslash % 0x7D - [0x00127] = 0x7E, -- planckover2pi1 \hbar % 0x7E - [0x003F6] = 0x7F, -- epsiloninv \backepsilon -} - -mathencodings["tex-mc"] = { - -- this file has no tfm so it gets mapped in the private space - [0xFE324] = "mapsfromchar", -} +-- -- The names in masm10.enc can be trusted best and are shown in the first +-- -- column, while in the second column we show the tex/ams names. As usual +-- -- it costs hours to figure out such a table. +-- +-- mathencodings["tex-ma"] = { +-- [0x022A1] = 0x00, -- squaredot \boxdot +-- [0x0229E] = 0x01, -- squareplus \boxplus +-- [0x022A0] = 0x02, -- squaremultiply \boxtimes +-- [0x025A1] = 0x03, -- square \square \Box +-- [0x025A0] = 0x04, -- squaresolid \blacksquare +-- [0x025AA] = 0x05, -- squaresmallsolid \centerdot +-- [0x022C4] = 0x06, -- diamond \Diamond \lozenge +-- [0x02666] = 0x07, -- diamondsolid \blacklozenge +-- [0x021BB] = 0x08, -- clockwise \circlearrowright +-- [0x021BA] = 0x09, -- anticlockwise \circlearrowleft +-- [0x021CC] = 0x0A, -- harpoonleftright \rightleftharpoons +-- [0x021CB] = 0x0B, -- harpoonrightleft \leftrightharpoons +-- [0x0229F] = 0x0C, -- squareminus \boxminus +-- [0x022A9] = 0x0D, -- forces \Vdash +-- [0x022AA] = 0x0E, -- forcesbar \Vvdash +-- [0x022A8] = 0x0F, -- satisfies \vDash +-- [0x021A0] = 0x10, -- dblarrowheadright \twoheadrightarrow +-- [0x0219E] = 0x11, -- dblarrowheadleft \twoheadleftarrow +-- [0x021C7] = 0x12, -- dblarrowleft \leftleftarrows +-- [0x021C9] = 0x13, -- dblarrowright \rightrightarrows +-- [0x021C8] = 0x14, -- dblarrowup \upuparrows +-- [0x021CA] = 0x15, -- dblarrowdwn \downdownarrows +-- [0x021BE] = 0x16, -- harpoonupright \upharpoonright \restriction +-- [0x021C2] = 0x17, -- harpoondownright \downharpoonright +-- [0x021BF] = 0x18, -- harpoonupleft \upharpoonleft +-- [0x021C3] = 0x19, -- harpoondownleft \downharpoonleft +-- [0x021A3] = 0x1A, -- arrowtailright \rightarrowtail +-- [0x021A2] = 0x1B, -- arrowtailleft \leftarrowtail +-- [0x021C6] = 0x1C, -- arrowparrleftright \leftrightarrows +-- -- [0x021C5] = 0x00, -- \updownarrows (missing in lm) +-- [0x021C4] = 0x1D, -- arrowparrrightleft \rightleftarrows +-- [0x021B0] = 0x1E, -- shiftleft \Lsh +-- [0x021B1] = 0x1F, -- shiftright \Rsh +-- [0x021DD] = 0x20, -- squiggleright \leadsto \rightsquigarrow +-- [0x021AD] = 0x21, -- squiggleleftright \leftrightsquigarrow +-- [0x021AB] = 0x22, -- curlyleft \looparrowleft +-- [0x021AC] = 0x23, -- curlyright \looparrowright +-- [0x02257] = 0x24, -- circleequal \circeq +-- [0x0227F] = 0x25, -- followsorequal \succsim +-- [0x02273] = 0x26, -- greaterorsimilar \gtrsim +-- [0x02A86] = 0x27, -- greaterorapproxeql \gtrapprox +-- [0x022B8] = 0x28, -- multimap \multimap +-- [0x02234] = 0x29, -- therefore \therefore +-- [0x02235] = 0x2A, -- because \because +-- [0x02251] = 0x2B, -- equalsdots \Doteq \doteqdot +-- [0x0225C] = 0x2C, -- defines \triangleq +-- [0x0227E] = 0x2D, -- precedesorequal \precsim +-- [0x02272] = 0x2E, -- lessorsimilar \lesssim +-- [0x02A85] = 0x2F, -- lessorapproxeql \lessapprox +-- [0x02A95] = 0x30, -- equalorless \eqslantless +-- [0x02A96] = 0x31, -- equalorgreater \eqslantgtr +-- [0x022DE] = 0x32, -- equalorprecedes \curlyeqprec +-- [0x022DF] = 0x33, -- equalorfollows \curlyeqsucc +-- [0x0227C] = 0x34, -- precedesorcurly \preccurlyeq +-- [0x02266] = 0x35, -- lessdblequal \leqq +-- [0x02A7D] = 0x36, -- lessorequalslant \leqslant +-- [0x02276] = 0x37, -- lessorgreater \lessgtr +-- [0x02035] = 0x38, -- primereverse \backprime +-- -- [0x0] = 0x39, -- axisshort \dabar +-- [0x02253] = 0x3A, -- equaldotrightleft \risingdotseq +-- [0x02252] = 0x3B, -- equaldotleftright \fallingdotseq +-- [0x0227D] = 0x3C, -- followsorcurly \succcurlyeq +-- [0x02267] = 0x3D, -- greaterdblequal \geqq +-- [0x02A7E] = 0x3E, -- greaterorequalslant \geqslant +-- [0x02277] = 0x3F, -- greaterorless \gtrless +-- [0x0228F] = 0x40, -- squareimage \sqsubset +-- [0x02290] = 0x41, -- squareoriginal \sqsupset +-- -- wrong: see ** +-- -- [0x022B3] = 0x42, -- triangleright \rhd \vartriangleright +-- -- [0x022B2] = 0x43, -- triangleleft \lhd \vartriangleleft +-- -- cf lm +-- [0x022B5] = 0x44, -- trianglerightequal \unrhd \trianglerighteq +-- [0x022B4] = 0x45, -- triangleleftequal \unlhd \trianglelefteq +-- -- +-- [0x02605] = 0x46, -- star \bigstar +-- [0x0226C] = 0x47, -- between \between +-- [0x025BC] = 0x48, -- triangledownsld \blacktriangledown +-- [0x025B6] = 0x49, -- trianglerightsld \blacktriangleright +-- [0x025C0] = 0x4A, -- triangleleftsld \blacktriangleleft +-- -- [0x0] = 0x4B, -- arrowaxisright +-- -- [0x0] = 0x4C, -- arrowaxisleft +-- [0x025B2] = 0x4D, -- triangle \triangleup \vartriangle +-- [0x025B2] = 0x4E, -- trianglesolid \blacktriangle +-- [0x025BD] = 0x4F, -- triangleinv \triangledown +-- [0x02256] = 0x50, -- ringinequal \eqcirc +-- [0x022DA] = 0x51, -- lessequalgreater \lesseqgtr +-- [0x022DB] = 0x52, -- greaterlessequal \gtreqless +-- [0x02A8B] = 0x53, -- lessdbleqlgreater \lesseqqgtr +-- [0x02A8C] = 0x54, -- greaterdbleqlless \gtreqqless +-- [0x000A5] = 0x55, -- Yen \yen +-- [0x021DB] = 0x56, -- arrowtripleright \Rrightarrow +-- [0x021DA] = 0x57, -- arrowtripleleft \Lleftarrow +-- [0x02713] = 0x58, -- check \checkmark +-- [0x022BB] = 0x59, -- orunderscore \veebar +-- [0x022BC] = 0x5A, -- nand \barwedge +-- [0x02306] = 0x5B, -- perpcorrespond \doublebarwedge +-- [0x02220] = 0x5C, -- angle \angle +-- [0x02221] = 0x5D, -- measuredangle \measuredangle +-- [0x02222] = 0x5E, -- sphericalangle \sphericalangle +-- -- [0x0] = 0x5F, -- proportional \varpropto +-- -- [0x0] = 0x60, -- smile \smallsmile +-- -- [0x0] = 0x61, -- frown \smallfrown +-- [0x022D0] = 0x62, -- subsetdbl \Subset +-- [0x022D1] = 0x63, -- supersetdbl \Supset +-- [0x022D3] = 0x64, -- uniondbl \doublecup \Cup +-- [0x022D2] = 0x65, -- intersectiondbl \doublecap \Cap +-- [0x022CF] = 0x66, -- uprise \curlywedge +-- [0x022CE] = 0x67, -- downfall \curlyvee +-- [0x022CB] = 0x68, -- multiopenleft \leftthreetimes +-- [0x022CC] = 0x69, -- multiopenright \rightthreetimes +-- [0x02AC5] = 0x6A, -- subsetdblequal \subseteqq +-- [0x02AC6] = 0x6B, -- supersetdblequal \supseteqq +-- [0x0224F] = 0x6C, -- difference \bumpeq +-- [0x0224E] = 0x6D, -- geomequivalent \Bumpeq +-- [0x022D8] = 0x6E, -- muchless \lll \llless +-- [0x022D9] = 0x6F, -- muchgreater \ggg \gggtr +-- [0x0231C] = 0x70, -- rightanglenw \ulcorner +-- [0x0231D] = 0x71, -- rightanglene \urcorner +-- [0x024C7] = 0x72, -- circleR \circledR +-- [0x024C8] = 0x73, -- circleS \circledS +-- [0x022D4] = 0x74, -- fork \pitchfork +-- [0x02214] = 0x75, -- dotplus \dotplus +-- [0x0223D] = 0x76, -- revsimilar \backsim +-- [0x022CD] = 0x77, -- revasymptequal \backsimeq -- AM: Check this! I mapped it to simeq. +-- [0x0231E] = 0x78, -- rightanglesw \llcorner +-- [0x0231F] = 0x79, -- rightanglese \lrcorner +-- [0x02720] = 0x7A, -- maltesecross \maltese +-- [0x02201] = 0x7B, -- complement \complement +-- [0x022BA] = 0x7C, -- intercal \intercal +-- [0x0229A] = 0x7D, -- circlering \circledcirc +-- [0x0229B] = 0x7E, -- circleasterisk \circledast +-- [0x0229D] = 0x7F, -- circleminus \circleddash +-- } +-- +-- mathencodings["tex-mb"] = { +-- -- [0x0] = 0x00, -- lessornotequal \lvertneqq +-- -- [0x0] = 0x01, -- greaterornotequal \gvertneqq +-- [0x02270] = 0x02, -- notlessequal \nleq +-- [0x02271] = 0x03, -- notgreaterequal \ngeq +-- [0x0226E] = 0x04, -- notless \nless +-- [0x0226F] = 0x05, -- notgreater \ngtr +-- [0x02280] = 0x06, -- notprecedes \nprec +-- [0x02281] = 0x07, -- notfollows \nsucc +-- [0x02268] = 0x08, -- lessornotdbleql \lneqq +-- [0x02269] = 0x09, -- greaterornotdbleql \gneqq +-- -- [0x0] = 0x0A, -- notlessorslnteql \nleqslant +-- -- [0x0] = 0x0B, -- notgreaterorslnteql \ngeqslant +-- [0x02A87] = 0x0C, -- lessnotequal \lneq +-- [0x02A88] = 0x0D, -- greaternotequal \gneq +-- -- [0x0] = 0x0E, -- notprecedesoreql \npreceq +-- -- [0x0] = 0x0F, -- notfollowsoreql \nsucceq +-- [0x022E8] = 0x10, -- precedeornoteqvlnt \precnsim +-- [0x022E9] = 0x11, -- followornoteqvlnt \succnsim +-- [0x022E6] = 0x12, -- lessornotsimilar \lnsim +-- [0x022E7] = 0x13, -- greaterornotsimilar \gnsim +-- -- [0x0] = 0x14, -- notlessdblequal \nleqq +-- -- [0x0] = 0x15, -- notgreaterdblequal \ngeqq +-- [0x02AB5] = 0x16, -- precedenotslnteql \precneqq +-- [0x02AB6] = 0x17, -- follownotslnteql \succneqq +-- [0x02AB9] = 0x18, -- precedenotdbleqv \precnapprox +-- [0x02ABA] = 0x19, -- follownotdbleqv \succnapprox +-- [0x02A89] = 0x1A, -- lessnotdblequal \lnapprox +-- [0x02A8A] = 0x1B, -- greaternotdblequal \gnapprox +-- [0x02241] = 0x1C, -- notsimilar \nsim +-- [0x02247] = 0x1D, -- notapproxequal \ncong +-- -- [0x0] = 0x1E, -- upslope \diagup +-- -- [0x0] = 0x1F, -- downslope \diagdown +-- -- [0x0] = 0x20, -- notsubsetoreql \varsubsetneq +-- -- [0x0] = 0x21, -- notsupersetoreql \varsupsetneq +-- -- [0x0] = 0x22, -- notsubsetordbleql \nsubseteqq +-- -- [0x0] = 0x23, -- notsupersetordbleql \nsupseteqq +-- [0x02ACB] = 0x24, -- subsetornotdbleql \subsetneqq +-- [0x02ACC] = 0x25, -- supersetornotdbleql \supsetneqq +-- -- [0x0] = 0x26, -- subsetornoteql \varsubsetneqq +-- -- [0x0] = 0x27, -- supersetornoteql \varsupsetneqq +-- [0x0228A] = 0x28, -- subsetnoteql \subsetneq +-- [0x0228B] = 0x29, -- supersetnoteql \supsetneq +-- [0x02288] = 0x2A, -- notsubseteql \nsubseteq +-- [0x02289] = 0x2B, -- notsuperseteql \nsupseteq +-- [0x02226] = 0x2C, -- notparallel \nparallel +-- [0x02224] = 0x2D, -- notbar \nmid \ndivides +-- -- [0x0] = 0x2E, -- notshortbar \nshortmid +-- -- [0x0] = 0x2F, -- notshortparallel \nshortparallel +-- [0x022AC] = 0x30, -- notturnstile \nvdash +-- [0x022AE] = 0x31, -- notforces \nVdash +-- [0x022AD] = 0x32, -- notsatisfies \nvDash +-- [0x022AF] = 0x33, -- notforcesextra \nVDash +-- [0x022ED] = 0x34, -- nottriangeqlright \ntrianglerighteq +-- [0x022EC] = 0x35, -- nottriangeqlleft \ntrianglelefteq +-- [0x022EA] = 0x36, -- nottriangleleft \ntriangleleft +-- [0x022EB] = 0x37, -- nottriangleright \ntriangleright +-- [0x0219A] = 0x38, -- notarrowleft \nleftarrow +-- [0x0219B] = 0x39, -- notarrowright \nrightarrow +-- [0x021CD] = 0x3A, -- notdblarrowleft \nLeftarrow +-- [0x021CF] = 0x3B, -- notdblarrowright \nRightarrow +-- [0x021CE] = 0x3C, -- notdblarrowboth \nLeftrightarrow +-- [0x021AE] = 0x3D, -- notarrowboth \nleftrightarrow +-- [0x022C7] = 0x3E, -- dividemultiply \divideontimes +-- [0x02300] = 0x3F, -- diametersign \varnothing +-- [0x02204] = 0x40, -- notexistential \nexists +-- [0x1D538] = 0x41, -- A (blackboard A) +-- [0x1D539] = 0x42, -- B +-- [0x02102] = 0x43, -- C +-- [0x1D53B] = 0x44, -- D +-- [0x1D53C] = 0x45, -- E +-- [0x1D53D] = 0x46, -- F +-- [0x1D53E] = 0x47, -- G +-- [0x0210D] = 0x48, -- H +-- [0x1D540] = 0x49, -- I +-- [0x1D541] = 0x4A, -- J +-- [0x1D542] = 0x4B, -- K +-- [0x1D543] = 0x4C, -- L +-- [0x1D544] = 0x4D, -- M +-- [0x02115] = 0x4E, -- N +-- [0x1D546] = 0x4F, -- O +-- [0x02119] = 0x50, -- P +-- [0x0211A] = 0x51, -- Q +-- [0x0211D] = 0x52, -- R +-- [0x1D54A] = 0x53, -- S +-- [0x1D54B] = 0x54, -- T +-- [0x1D54C] = 0x55, -- U +-- [0x1D54D] = 0x56, -- V +-- [0x1D54E] = 0x57, -- W +-- [0x1D54F] = 0x58, -- X +-- [0x1D550] = 0x59, -- Y +-- [0x02124] = 0x5A, -- Z (blackboard Z) +-- [0x02132] = 0x60, -- finv \Finv +-- [0x02141] = 0x61, -- fmir \Game +-- -- [0x0] = 0x62, tildewide +-- -- [0x0] = 0x63, tildewider +-- -- [0x0] = 0x64, Finv +-- -- [0x0] = 0x65, Gmir +-- [0x02127] = 0x66, -- Omegainv \mho +-- [0x000F0] = 0x67, -- eth \eth +-- [0x02242] = 0x68, -- equalorsimilar \eqsim +-- [0x02136] = 0x69, -- beth \beth +-- [0x02137] = 0x6A, -- gimel \gimel +-- [0x02138] = 0x6B, -- daleth \daleth +-- [0x022D6] = 0x6C, -- lessdot \lessdot +-- [0x022D7] = 0x6D, -- greaterdot \gtrdot +-- [0x022C9] = 0x6E, -- multicloseleft \ltimes +-- [0x022CA] = 0x6F, -- multicloseright \rtimes +-- -- [0x0] = 0x70, -- barshort \shortmid +-- -- [0x0] = 0x71, -- parallelshort \shortparallel +-- -- [0x02216] = 0x72, -- integerdivide \smallsetminus (2216 already part of tex-sy +-- -- [0x0] = 0x73, -- similar \thicksim +-- -- [0x0] = 0x74, -- approxequal \thickapprox +-- [0x0224A] = 0x75, -- approxorequal \approxeq +-- [0x02AB8] = 0x76, -- followsorequal \succapprox +-- [0x02AB7] = 0x77, -- precedesorequal \precapprox +-- [0x021B6] = 0x78, -- archleftdown \curvearrowleft +-- [0x021B7] = 0x79, -- archrightdown \curvearrowright +-- [0x003DC] = 0x7A, -- Digamma \digamma +-- [0x003F0] = 0x7B, -- kappa \varkappa +-- [0x1D55C] = 0x7C, -- k \Bbbk (blackboard k) +-- [0x0210F] = 0x7D, -- planckover2pi \hslash % 0x7D +-- [0x00127] = 0x7E, -- planckover2pi1 \hbar % 0x7E +-- [0x003F6] = 0x7F, -- epsiloninv \backepsilon +-- } +-- +-- mathencodings["tex-mc"] = { +-- -- this file has no tfm so it gets mapped in the private space +-- [0xFE324] = "mapsfromchar", +-- } mathencodings["tex-fraktur"] = { -- [0x1D504] = 0x41, -- A (fraktur A) diff --git a/tex/context/base/mkxl/math-vfu.lmt b/tex/context/base/mkxl/math-vfu.lmt index 53988036c..bdd5de103 100644 --- a/tex/context/base/mkxl/math-vfu.lmt +++ b/tex/context/base/mkxl/math-vfu.lmt @@ -936,9 +936,12 @@ function vfmath.define(specification,set,goodies) local skewchar = ss.skewchar local backmap = ss.backmap local badones = ss.badones + local ignore = ss.ignore local done = { } local extras = { } - if not backmap then + if backmap == false then + -- backmap = { } + elseif not backmap then backmap = { } for unicode, character in next, fc do backmap[character.order or character.index or unicode] = unicode @@ -969,11 +972,16 @@ function vfmath.define(specification,set,goodies) rv[unicode] = true end else - local u = mathematics.gaps[unicode] or unicode - local t = virtualize(s,uni,fci,skewchar,tonumber(badones and badones[fci.name or ""]),mathparameters,u,fp) - done[uni] = t - characters[unicode] = t - fci.unicode = u + local name = fci.name or "" + if ignore and ignore[name] then + -- get rid of ugly slanted antykwa { } + else + local u = mathematics.gaps[unicode] or unicode + local t = virtualize(s,uni,fci,skewchar,tonumber(badones and badones[name]),mathparameters,u,fp) + done[uni] = t + characters[unicode] = t + fci.unicode = u + end end end if isextension then diff --git a/tex/context/base/mkxl/node-bck.mkxl b/tex/context/base/mkxl/node-bck.mkxl index 357180710..4ee2b0fa9 100644 --- a/tex/context/base/mkxl/node-bck.mkxl +++ b/tex/context/base/mkxl/node-bck.mkxl @@ -19,7 +19,7 @@ \unprotect -\registerctxluafile{node-bck}{autosuffix,optimize} +\registerctxluafile{node-bck}{autosuffix} % \backgroundvbox[green] {\input tufte } \par % \backgroundvbox[blue] {\input ward } \par diff --git a/tex/context/base/mkxl/node-fin.mkxl b/tex/context/base/mkxl/node-fin.mkxl index c0ad58f7d..aef7eea58 100644 --- a/tex/context/base/mkxl/node-fin.mkxl +++ b/tex/context/base/mkxl/node-fin.mkxl @@ -15,8 +15,8 @@ \unprotect -\registerctxluafile{node-shp}{autosuffix,optimize} -\registerctxluafile{node-fin}{autosuffix,optimize} +\registerctxluafile{node-shp}{autosuffix} +\registerctxluafile{node-fin}{autosuffix} \permanent\protected\def\finalizeobjectbox #1{\clf_finalizebox#1\relax} \permanent\protected\def\finalizeshipoutbox#1{\clf_finalizebox#1\relax} diff --git a/tex/context/base/mkxl/node-rul.mkxl b/tex/context/base/mkxl/node-rul.mkxl index 5253c8008..04c0e0dc3 100644 --- a/tex/context/base/mkxl/node-rul.mkxl +++ b/tex/context/base/mkxl/node-rul.mkxl @@ -85,7 +85,7 @@ \mutable\lettonothing\m_rule_option \mutable\lettonothing\m_rule_color -\registerctxluafile{node-rul}{autosuffix,optimize} +\registerctxluafile{node-rul}{autosuffix} \installcorenamespace{bar} \installcorenamespace{barstack} diff --git a/tex/context/base/mkxl/pack-rul.mkxl b/tex/context/base/mkxl/pack-rul.mkxl index 9c25cbf05..36b4fc7b0 100644 --- a/tex/context/base/mkxl/pack-rul.mkxl +++ b/tex/context/base/mkxl/pack-rul.mkxl @@ -25,7 +25,7 @@ \newdimension\framedmaxwidth \newdimension\framedaveragewidth -\registerctxluafile{pack-rul}{autosuffix,optimize} +\registerctxluafile{pack-rul}{autosuffix} \unprotect diff --git a/tex/context/base/mkxl/regi-ini.lmt b/tex/context/base/mkxl/regi-ini.lmt new file mode 100644 index 000000000..c0cd4f1c8 --- /dev/null +++ b/tex/context/base/mkxl/regi-ini.lmt @@ -0,0 +1,367 @@ +if not modules then modules = { } end modules ['regi-ini'] = { + version = 1.001, + comment = "companion to regi-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +--[[ldx-- +<p>Regimes take care of converting the input characters into +<l n='utf'/> sequences. The conversion tables are loaded at +runtime.</p> +--ldx]]-- + +local tostring = tostring +local utfchar = utf.char +local P, Cs, Cc, lpegmatch = lpeg.P, lpeg.Cs, lpeg.Cc, lpeg.match +local char, gsub, format, gmatch, byte, match, lower = string.char, string.gsub, string.format, string.gmatch, string.byte, string.match, string.lower +local next = next +local insert, remove, fastcopy = table.insert, table.remove, table.fastcopy +local concat = table.concat +local totable = string.totable + +local allocate = utilities.storage.allocate +local sequencers = utilities.sequencers +local textlineactions = resolvers.openers.helpers.textlineactions +local setmetatableindex = table.setmetatableindex + +-- We will hook regime handling code into the input methods. + +local trace_translating = false trackers.register("regimes.translating", function(v) trace_translating = v end) + +local report_loading = logs.reporter("regimes","loading") +local report_translating = logs.reporter("regimes","translating") + +regimes = regimes or { } +local regimes = regimes + +local mapping = allocate { + utf = false +} + +local backmapping = allocate { +} + +-- regimes.mapping = mapping + +local synonyms = { -- backward compatibility list + + ["windows-1250"] = "cp1250", + ["windows-1251"] = "cp1251", + ["windows-1252"] = "cp1252", + ["windows-1253"] = "cp1253", + ["windows-1254"] = "cp1254", + ["windows-1255"] = "cp1255", + ["windows-1256"] = "cp1256", + ["windows-1257"] = "cp1257", + ["windows-1258"] = "cp1258", + + ["il1"] = "8859-1", + ["il2"] = "8859-2", + ["il3"] = "8859-3", + ["il4"] = "8859-4", + ["il5"] = "8859-9", + ["il6"] = "8859-10", + ["il7"] = "8859-13", + ["il8"] = "8859-14", + ["il9"] = "8859-15", + ["il10"] = "8859-16", + + ["iso-8859-1"] = "8859-1", + ["iso-8859-2"] = "8859-2", + ["iso-8859-3"] = "8859-3", + ["iso-8859-4"] = "8859-4", + ["iso-8859-9"] = "8859-9", + ["iso-8859-10"] = "8859-10", + ["iso-8859-13"] = "8859-13", + ["iso-8859-14"] = "8859-14", + ["iso-8859-15"] = "8859-15", + ["iso-8859-16"] = "8859-16", + + ["latin1"] = "8859-1", + ["latin2"] = "8859-2", + ["latin3"] = "8859-3", + ["latin4"] = "8859-4", + ["latin5"] = "8859-9", + ["latin6"] = "8859-10", + ["latin7"] = "8859-13", + ["latin8"] = "8859-14", + ["latin9"] = "8859-15", + ["latin10"] = "8859-16", + + ["utf-8"] = "utf", + ["utf8"] = "utf", + [""] = "utf", + + ["windows"] = "cp1252", + + ["pdf"] = "pdfdoc", + + ["437"] = "ibm", +} + +local currentregime = "utf" + +local function loadregime(mapping,regime) + regime = lower(tostring(regime)) + regime = synonyms[regime] or synonyms["windows-"..regime] or regime + local name = resolvers.findfile(format("regi-%s.lua",regime)) or "" + local data = name ~= "" and dofile(name) + if data then + vector = { } + for eightbit, unicode in next, data do + vector[char(eightbit)] = utfchar(unicode) + end + report_loading("vector %a is loaded",regime) + else + vector = false + report_loading("vector %a is unknown",regime) + end + mapping[regime] = vector + return vector +end + +local function loadreverse(t,k) + local t = { } + local m = mapping[k] + if m then + for k, v in next, m do + t[v] = k + end + end + backmapping[k] = t + return t +end + +setmetatableindex(mapping, loadregime) +setmetatableindex(backmapping,loadreverse) + +regimes.mapping = mapping +regimes.backmapping = backmapping + +local function fromregime(regime,line) + if line and #line > 0 then + -- local map = mapping[regime and synonyms[regime] or regime or currentregime] + local map = mapping[regime or currentregime] + if map then + line = gsub(line,".",map) + end + end + return line +end + +local cache = { } -- if really needed we can copy vectors and hash defaults + +setmetatableindex(cache, function(t,k) + local v = { remappers = { } } + t[k] = v + return v +end) + +local function toregime(vector,str,default) -- toregime('8859-1',"abcde Ä","?") + local d = default or "?" + local c = cache[vector].remappers + local r = c[d] + if not r then + local t = fastcopy(backmapping[vector]) + -- r = utf.remapper(t) -- not good for defaults here + local pattern = Cs((lpeg.utfchartabletopattern(t)/t + lpeg.patterns.utf8character/d + P(1)/d)^0) + r = function(str) + if not str or str == "" then + return "" + else + return lpegmatch(pattern,str) + end + end + c[d] = r + end + return r(str) +end + +local function disable() + currentregime = "utf" + sequencers.disableaction(textlineactions,"regimes.process") + return currentregime +end + +local function enable(regime) + regime = synonyms[regime] or regime + if mapping[regime] == false then + disable() + else + currentregime = regime + sequencers.enableaction(textlineactions,"regimes.process") + end + return currentregime +end + +regimes.toregime = toregime +regimes.fromregime = fromregime +regimes.translate = function(str,regime) return fromregime(regime,str) end +regimes.enable = enable +regimes.disable = disable + +-- The following function can be used when we want to make sure that utf gets passed +-- unharmed. This is needed for modules. + +local level = 0 + +function regimes.process(str,filename,currentline,noflines,coding) + if level == 0 and coding ~= "utf-8" then + str = fromregime(currentregime,str) + if trace_translating then + report_translating("utf: %s",str) + end + end + return str +end + +local function push() + level = level + 1 + if trace_translating then + report_translating("pushing level %s",level) + end +end + +local function pop() + if level > 0 then + if trace_translating then + report_translating("popping level %s",level) + end + level = level - 1 + end +end + +regimes.push = push +regimes.pop = pop + +function regimes.list() + local name = resolvers.findfile(format("regi-ini.lua",regime)) or "" + local okay = { } + if name then + local list = dir.glob(file.join(file.dirname(name),"regi-*.lua")) + for i=1,#list do + local name = list[i] + if name ~= "regi-ini.lua" then + okay[#okay+1] = match(name,"regi%-(.-)%.lua") + end + table.sort(okay) + end + end + return okay +end + +sequencers.prependaction(textlineactions,"system","regimes.process") +sequencers.disableaction(textlineactions,"regimes.process") + +-- Next we provide some hacks. Unfortunately we run into crappy encoded (read: +-- mixed) encoded xml files that have these ë ä ö ü sequences instead of ë ä ö ü +-- etc. + +local patterns = { } + +function regimes.cleanup(regime,str) + if not str or str == "" then + return str + end + local p = patterns[regime] + if p == nil then + regime = regime and synonyms[regime] or regime or currentregime + local vector = regime ~= "utf" and regime ~= "utf-8" and mapping[regime] + if vector then + local mapping = { } + for k, v in next, vector do + local split = totable(v) + for i=1,#split do + split[i] = utfchar(byte(split[i])) + end + split = concat(split) + if v ~= split then + mapping[split] = v + end + end + p = Cs((lpeg.utfchartabletopattern(mapping)/mapping+P(1))^0) + else + p = false + end + patterns[regime] = p + end + return p and lpegmatch(p,str) or str +end + +-- local old = [[test ë ä ö ü crap]] +-- local new = regimes.cleanup("cp1252",old) +-- report_translating("%s -> %s",old,new) +-- local old = "Pozn" .. char(0xE1) .. "mky" +-- local new = fromregime("cp1250",old) +-- report_translating("%s -> %s",old,new) + +-- interface (might move to regi-tex.lua) + +if interfaces then + + local implement = interfaces.implement + local setmacro = interfaces.setmacro + + implement { + name = "enableregime", + public = true, + protected = true, + arguments = "optional", + actions = function(regime) setmacro("currentregime",enable(regime)) end + } + + implement { + name = "disableregime", + public = true, + protected = true, + actions = function() setmacro("currentregime",disable()) end + } + + implement { + name = "pushregime", + public = true, + protected = true, + actions = push + } + + implement { + name = "popregime", + public = true, + protected = true, + actions = pop + } + + local stack = { } + + implement { + name = "startregime", + public = true, + protected = true, + arguments = "optional", + actions = function(regime) + insert(stack,currentregime) + if trace_translating then + report_translating("start using %a",regime) + end + setmacro("currentregime",enable(regime)) + end + } + + implement { + name = "stopregime", + public = true, + protected = true, + actions = function() + if #stack > 0 then + local regime = remove(stack) + if trace_translating then + report_translating("stop using %a",regime) + end + setmacro("currentregime",enable(regime)) + end + end + } + +end diff --git a/tex/context/base/mkxl/regi-ini.mkxl b/tex/context/base/mkxl/regi-ini.mkxl index 8ba7edc42..da5bdf081 100644 --- a/tex/context/base/mkxl/regi-ini.mkxl +++ b/tex/context/base/mkxl/regi-ini.mkxl @@ -11,13 +11,14 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\registerctxluafile{regi-ini}{} +\registerctxluafile{regi-ini}{autosuffix} \unprotect %D \macros %D {enableregime,disableregime, %D startregime,stopregime, +%D pushregime, popregime, %D currentregime} %D %D Beware, the enable and disable commands are global switches, so best use the @@ -25,13 +26,15 @@ \mutable\lettonothing\currentregime -\permanent\protected\def\enableregime[#1]{\clf_enableregime{#1}} -\permanent\protected\def\disableregime {\clf_disableregime} -\permanent\protected\def\startregime [#1]{\clf_startregime{#1}} -\permanent\protected\def\stopregime {\clf_stopregime} - -% only for diagnostics: - -% \def\codepagename#1{\cldcontext{os.tocodepage("#1")}} +%D These are defined at the \LUA\ end: +%D +%D \starttyping +%D \enableregime[#1] +%D \disableregime +%D \startregime [#1] +%D \stopregime +%D \pushregime +%D \popregime +%D \stoptyping \protect \endinput diff --git a/tex/context/base/mkxl/spac-ali.mkxl b/tex/context/base/mkxl/spac-ali.mkxl index c7d2fb657..f5b0e2fb8 100644 --- a/tex/context/base/mkxl/spac-ali.mkxl +++ b/tex/context/base/mkxl/spac-ali.mkxl @@ -19,7 +19,7 @@ %D variants. Starting at the last day of 2011 both methods are merged into one and %D caching has been added, which makes switching twice as fast. -\registerctxluafile{spac-ali}{autosuffix,optimize} +\registerctxluafile{spac-ali}{autosuffix} % Used once so ... replace it or use if more frequently ... diff --git a/tex/context/base/mkxl/spac-chr.mkxl b/tex/context/base/mkxl/spac-chr.mkxl index 346bc2183..ef63b2b82 100644 --- a/tex/context/base/mkxl/spac-chr.mkxl +++ b/tex/context/base/mkxl/spac-chr.mkxl @@ -15,7 +15,7 @@ \unprotect -\registerctxluafile{spac-chr}{autosuffix,optimize} +\registerctxluafile{spac-chr}{autosuffix} \definesystemattribute[characters][public] diff --git a/tex/context/base/mkxl/spac-hor.mkxl b/tex/context/base/mkxl/spac-hor.mkxl index 017a94d5b..3c4fd1eb4 100644 --- a/tex/context/base/mkxl/spac-hor.mkxl +++ b/tex/context/base/mkxl/spac-hor.mkxl @@ -400,13 +400,19 @@ % test test\fsp. test % beats frenchspacing +% \permanent\protected\def\fsp#1% fixed space puncuation +% {\begingroup +% \ifchknum`#1\or +% \sfcode`#1\plusthousand +% \fi +% #1% +% \endgroup} + \permanent\protected\def\fsp#1% fixed space puncuation - {\begingroup + {#1% \ifchknum`#1\or - \sfcode`#1\plusthousand - \fi - #1% - \endgroup} + \spacefactor\plusthousand + \fi} %D Here's a tweak .. if needed one can configure it in the configuration %D so that initialization happens more efficient. diff --git a/tex/context/base/mkxl/spac-ver.mkxl b/tex/context/base/mkxl/spac-ver.mkxl index 807ecfcd3..640d493b9 100644 --- a/tex/context/base/mkxl/spac-ver.mkxl +++ b/tex/context/base/mkxl/spac-ver.mkxl @@ -20,7 +20,7 @@ \newdimen \bodyfontstrutdepth \newgluespec\globalbodyfontlineheight % why a skip -\newdimen \globalbodyfontstrutheight +\newdimen \globalbodyfontstrutheight \newdimen \globalbodyfontstrutdepth \newgluespec \s_spac_vspacing_predefined @@ -31,7 +31,7 @@ % \overloaded\let\strutdp \undefined \newdimen\strutdp % \overloaded\let\struthtdp\undefined \newdimen\struthtdp -\registerctxluafile{spac-ver}{autosuffix,optimize} +\registerctxluafile{spac-ver}{autosuffix} % todo: use usernodes ? diff --git a/tex/context/base/mkxl/strc-flt.mklx b/tex/context/base/mkxl/strc-flt.mklx index 1f2aeaae5..55b825fe1 100644 --- a/tex/context/base/mkxl/strc-flt.mklx +++ b/tex/context/base/mkxl/strc-flt.mklx @@ -527,6 +527,53 @@ \fi \fi} +\def\strc_floats_apply_caption_command + {\setbox\b_strc_floats_caption\hbox\bgroup + %\unless\ifcstok{\floatcaptionparameter\c!command}\emptytoks + \floatcaptionparameter\c!command{\box\b_strc_floats_caption}% + %\orunless\ifcstok{\floatcaptionparameter\c!deeptextcommand}\emptytoks + % \floatcaptionparameter\c!deeptextcommand{\unvbox\b_strc_floats_caption}% + %\else + % \box\b_strc_floats_caption + %\fi + \egroup} + +%D Some trickery (example by MS): +%D +%D \starttyping +%D \defineframed +%D [MyCaptionFramed] +%D [align={lohi,flushleft}, +%D width=fit, +%D frame=off, +%D strut=no, +%D topframe=on, +%D loffset=1em, +%D toffset=0.25\lineheight] +%D +%D \starttexdefinition protected MyCaption #1 +%D \MyCaptionFramed { +%D % we ignore #1 as we want to unpack +%D \unvbox\floatcaptionbox +%D } +%D \stoptexdefinition +%D +%D \definefloat[pagefloat][pagefloats][graphic] +%D +%D \setupfloat +%D [pagefloat] +%D [default={page,header,footer}] +%D +%D \setupcaption +%D [pagefloat] +%D [location={top,inner}, +%D align=inner, +%D command=\MyCaption, +%D spaceinbetween=nowhite] +%D \stoptyping + +\permanent\protected\def\floatcaptionbox{\b_strc_floats_caption} + %D We can do this ... %D %D \starttyping @@ -1683,8 +1730,7 @@ % todo: installable maken, variant/method=auto vs macro \strc_floats_prepare_page_caption %\page_backgrounds_add_local_to_box\b_strc_floats_content - \setbox\b_strc_floats_caption\hbox % text - {\floatcaptionparameter\c!command{\box\b_strc_floats_caption}}% + \strc_floats_apply_caption_command \strc_floats_set_caption_dimensions\b_strc_floats_caption %\moveboxontogrid\b_strc_floats_caption{\floatcaptionparameter\c!grid}\d_strc_floats_caption_height %\page_backgrounds_add_local_to_box\b_strc_floats_caption @@ -2355,7 +2401,7 @@ \else \strc_floats_check_caption_content \strc_floats_prepare_side_caption - \setbox\b_strc_floats_caption\hbox{\floatcaptionparameter\c!command{\box\b_strc_floats_caption}}% \hpack ? + \strc_floats_apply_caption_command %\moveboxontogrid\b_strc_floats_caption{\floatcaptionparameter\c!grid}\d_strc_floats_caption_height %\page_backgrounds_add_local_to_box\b_strc_floats_caption \strc_floats_build_side_box diff --git a/tex/context/base/mkxl/strc-lst.lmt b/tex/context/base/mkxl/strc-lst.lmt index 67e06520c..703e580d7 100644 --- a/tex/context/base/mkxl/strc-lst.lmt +++ b/tex/context/base/mkxl/strc-lst.lmt @@ -853,17 +853,46 @@ filters[v_component] = function(specification) return result end +-- filters[v_product] = function(specification) +-- local reference = specification.reference +-- if reference and reference ~= "" then +-- -- local utilitydata = job.loadother(reference,true) +-- local fullname = file.replacesuffix(reference,"tuc") +-- if lfs.isfile(fullname) then +-- local utilitydata = job.loadother(fullname) +-- if utilitydata then +-- local collected = utilitydata.structures.lists.collected or { } +-- setmetatableindex(collected,{ external = reference }) +-- return collected +-- end +-- end +-- end +-- return { } +-- end + filters[v_product] = function(specification) local reference = specification.reference if reference and reference ~= "" then --- local utilitydata = job.loadother(reference,true) + -- local utilitydata = job.loadother(reference,true) local fullname = file.replacesuffix(reference,"tuc") if lfs.isfile(fullname) then local utilitydata = job.loadother(fullname) if utilitydata then local collected = utilitydata.structures.lists.collected or { } setmetatableindex(collected,{ external = reference }) - return collected + local result = { } + local nofresult = 0 + local all = specification.all + local names = specification.names + for i=1,#collected do + local v = collected[i] + local m = v.metadata + if m and names[m.name] or all then + nofresult = nofresult + 1 + result[nofresult] = v + end + end + return result end end end diff --git a/tex/context/base/mkxl/strc-ref.mklx b/tex/context/base/mkxl/strc-ref.mklx index de8cd29e1..e7073b36d 100644 --- a/tex/context/base/mkxl/strc-ref.mklx +++ b/tex/context/base/mkxl/strc-ref.mklx @@ -37,7 +37,7 @@ \registerctxluafile{strc-rsc}{autosuffix} \registerctxluafile{strc-ref}{autosuffix} -\registerctxluafile{node-ref}{autosuffix,optimize} +\registerctxluafile{node-ref}{autosuffix} \unprotect diff --git a/tex/context/base/mkxl/supp-box.mkxl b/tex/context/base/mkxl/supp-box.mkxl index 802815416..710a4892e 100644 --- a/tex/context/base/mkxl/supp-box.mkxl +++ b/tex/context/base/mkxl/supp-box.mkxl @@ -34,7 +34,7 @@ \newdimension\lastnaturalboxht \newdimension\lastnaturalboxdp -\registerctxluafile{supp-box}{autosuffix,optimize} +\registerctxluafile{supp-box}{autosuffix} % \fixupboxesmode\plusone % gone: is now the default diff --git a/tex/context/base/mkxl/tabl-xtb.mklx b/tex/context/base/mkxl/tabl-xtb.mklx index 84755cc1c..f7121dc58 100644 --- a/tex/context/base/mkxl/tabl-xtb.mklx +++ b/tex/context/base/mkxl/tabl-xtb.mklx @@ -252,7 +252,7 @@ }% else whitespace mess \def\tabl_x_get_buffer - {\clf_gettexbuffer{\tabl_x_current_buffer}} + {\clf_getbuffertex{\tabl_x_current_buffer}} \let\tabl_x_start_row_yes \relax \let\tabl_x_start_row_nop \relax diff --git a/tex/context/base/mkxl/type-set.mkxl b/tex/context/base/mkxl/type-set.mkxl index 2425d8538..5b83f287e 100644 --- a/tex/context/base/mkxl/type-set.mkxl +++ b/tex/context/base/mkxl/type-set.mkxl @@ -176,8 +176,8 @@ \definefilesynonym [type-imp-kurier-medium.mkiv] [type-imp-kurier.mkiv] \definefilesynonym [type-imp-kurier-heavy.mkiv] [type-imp-kurier.mkiv] -\definefilesynonym [type-imp-antykwa-torunska-light.mkiv] [type-imp-antykwa.mkiv] -\definefilesynonym [type-imp-antykwa-torunska-cond.mkiv] [type-imp-antykwa.mkiv] -\definefilesynonym [type-imp-antykwa-torunska-lightcond.mkiv] [type-imp-antykwa.mkiv] +\definefilesynonym [type-imp-antykwa-light.mkiv] [type-imp-antykwa.mkiv] +\definefilesynonym [type-imp-antykwa-cond.mkiv] [type-imp-antykwa.mkiv] +\definefilesynonym [type-imp-antykwa-lightcond.mkiv] [type-imp-antykwa.mkiv] \protect \endinput diff --git a/tex/context/base/mkxl/typo-lan.lmt b/tex/context/base/mkxl/typo-lan.lmt new file mode 100644 index 000000000..21aead80c --- /dev/null +++ b/tex/context/base/mkxl/typo-lan.lmt @@ -0,0 +1,89 @@ +if not modules then modules = { } end modules ['typo-lan'] = { + version = 1.001, + comment = "companion to typo-lan.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local type, next = type, next + +local currentfont = font.current +local setmetatableindex = table.setmetatableindex +local utfbyte = utf.byte + +local hashes = fonts.hashes +local fontdata = hashes.characters +local emwidths = hashes.emwidths + +local frequencies = languages.frequencies or { } +languages.frequencies = frequencies + +local frequencydata = { } +local frequencyfile = string.formatters["lang-frq-%s.lua"] +local frequencycache = { } + +setmetatableindex(frequencydata, function(t,language) + local fullname = resolvers.findfile(frequencyfile(language)) + local v = fullname ~= "" and dofile(fullname) + if not v or not v.frequencies then + v = t.en + end + t[language] = v + return v +end) + +setmetatableindex(frequencycache, function(t,language) + local dataset = frequencydata[language] + local frequencies = dataset.frequencies + if not frequencies then + return t.en + end + local v = { } + setmetatableindex(v, function(t,font) + local average = emwidths[font] / 2 + if frequencies then + local characters = fontdata[font] + local sum, tot = 0, 0 + for k, v in next, frequencies do + local character = characters[k] -- characters[type(k) == "number" and k or utfbyte(k)] + tot = tot + v + sum = sum + v * (character and character.width or average) + end + average = sum / tot -- widths + end + t[font] = average + return average + end) + t[language] = v + return v +end) + +function frequencies.getdata(language) + return frequencydata[language] +end + +function frequencies.averagecharwidth(language,font) + return frequencycache[language or "en"][font or currentfont()] +end + +-- Just because we can, we also have a setter ... + +local dimension_value = tokens.values.dimension +local scanstring = tokens.scanners.string +local scandimension = tokens.scanners.dimension + +interfaces.implement { + name = "languagecharwidth", + public = true, + usage = "value", + actions = function(what) + local language = scanstring() + local font = currentfont() + if what == "value" then + return dimension_value, frequencycache[language][font] or 0 + else + frequencycache[language][font] = scandimension(false,false,true) + end + end, +} diff --git a/tex/context/base/mkxl/typo-lan.mkxl b/tex/context/base/mkxl/typo-lan.mkxl index 9d137f5a5..7fc2a7b46 100644 --- a/tex/context/base/mkxl/typo-lan.mkxl +++ b/tex/context/base/mkxl/typo-lan.mkxl @@ -15,10 +15,10 @@ \unprotect -\registerctxluafile{typo-lan}{} +\registerctxluafile{typo-lan}{autosuffix} %D \macros -%D {averagecharwidth, charwidthlanguage} +%D {languagecharwidth, averagecharwidth, charwidthlanguage} %D %D This is a more \MKIV-ish variant of lang-frq.mkiv. The methods are gone as one %D doesn't need the tables for them. The main macro is \type {\averagecharwidth} @@ -26,39 +26,41 @@ %D %D I finally decided to reimplement this as I needed it for a manual (which is often %D a reason for such a rewrite). With some inspiring Porcupine Tree in the -%D background it's not the worst thing to do. +%D background it's not the worst thing to do. The \LMTX\ variant is a bit more +%D flexible as it can also set, not that someone will notice. \mutable\def\charwidthlanguage{\currentmainlanguage} -\permanent\def\averagecharwidth {\dimexpr\clf_averagecharwidth{\charwidthlanguage}\scaledpoint\relax} -\permanent\def\languagecharwidth#1{\dimexpr\clf_averagecharwidth{#1}\scaledpoint\relax} - -\protect - -\continueifinputfile{typo-lan.mkiv} - -\setuplayout[backspace=4cm] - -\showframe - -\starttext - -\startbuffer - -\mainlanguage[en] \hsize65\averagecharwidth \normalexpanded{\inleft{\the\hsize}} \input ward \par -\mainlanguage[de] \hsize65\averagecharwidth \normalexpanded{\inleft{\the\hsize}} \input ward \par -\mainlanguage[nl] \hsize65\averagecharwidth \normalexpanded{\inleft{\the\hsize}} \input ward \par - -\stopbuffer - -\getbuffer \blank - -\switchtobodyfont[pagella] - -\getbuffer \blank - -\switchtobodyfont[tt,8pt] - -\getbuffer - -\stoptext +% \languagecharwidth{language} is defined at the lua end + +\permanent\def\averagecharwidth{\languagecharwidth{\charwidthlanguage}} + +\protect \endinput + +% \setuplayout[backspace=4cm] +% +% \showframe +% +% \starttext +% +% \startbuffer +% +% \mainlanguage[en] \hsize65\averagecharwidth \normalexpanded{\inleft{\the\hsize}} \input ward \par +% \mainlanguage[de] \hsize65\averagecharwidth \normalexpanded{\inleft{\the\hsize}} \input ward \par +% \mainlanguage[nl] \hsize65\averagecharwidth \normalexpanded{\inleft{\the\hsize}} \input ward \par +% +% \languagecharwidth{de}=\languagecharwidth{en} +% +% \stopbuffer +% +% \getbuffer \blank +% +% \switchtobodyfont[pagella] +% +% \getbuffer \blank +% +% \switchtobodyfont[tt,8pt] +% +% \getbuffer +% +% \stoptext diff --git a/tex/context/base/mkxl/typo-pnc.lmt b/tex/context/base/mkxl/typo-pnc.lmt new file mode 100644 index 000000000..090cbb5b6 --- /dev/null +++ b/tex/context/base/mkxl/typo-pnc.lmt @@ -0,0 +1,170 @@ +if not modules then modules = { } end modules ['typo-pnc'] = { + version = 1.001, + comment = "companion to typo-pnc.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local nodes = nodes +local fonts = fonts + +local enableaction = nodes.tasks.enableaction + +local nuts = nodes.nuts +local tonut = nodes.tonut + +local nodecodes = nodes.nodecodes +local gluecodes = nodes.gluecodes +local glyph_code = nodecodes.glyph +local glue_code = nodecodes.glue +local spaceskip_code = gluecodes.spaceskip + +local new_kern = nuts.pool.kern +local insertafter = nuts.insertafter + +local nextglyph = nuts.traversers.glyph + +local getchar = nuts.getchar +local getfont = nuts.getfont +local getboth = nuts.getboth +local getnext = nuts.getnext +local getattr = nuts.getattr +local getid = nuts.getid +local getsubtype = nuts.getsubtype +local getwidth = nuts.getwidth +local setwidth = nuts.setwidth +local findattribute = nuts.findattribute + +local glyph_code = nodes.nodecodes.glyph + +local parameters = fonts.hashes.parameters +local categories = characters.categories + +local texsetattribute = tex.setattribute +local unsetvalue = attributes.unsetvalue + +local period = 0x2E +local factor = 0.5 + +-- alternative: tex.getlccode and tex.getuccode + +typesetters = typesetters or { } +local typesetters = typesetters + +local periodkerns = typesetters.periodkerns or { } +typesetters.periodkerns = periodkerns + +local report = logs.reporter("period kerns") +local trace = false + +trackers.register("typesetters.periodkerns",function(v) trace = v end) + +periodkerns.mapping = periodkerns.mapping or { } +periodkerns.factors = periodkerns.factors or { } +local a_periodkern = attributes.private("periodkern") + +storage.register("typesetters/periodkerns/mapping", periodkerns.mapping, "typesetters.periodkerns.mapping") +storage.register("typesetters/periodkerns/factors", periodkerns.factors, "typesetters.periodkerns.factors") + +local mapping = periodkerns.mapping +local factors = periodkerns.factors + +function periodkerns.handler(head) + local _, start = findattribute(head,a_periodkern,glyph_code) + if start then + for current, char, font in nextglyph, start do + if char == period then + local a = getattr(current,a_periodkern) + if a then + local factor = mapping[a] + if factor then + local prev, next = getboth(current) + if prev and next and getid(prev) == glyph_code and getid(next) == glyph_code then + local pchar = getchar(prev) + local pcode = categories[pchar] + if pcode == "lu" or pcode == "ll" then + local nchar = getchar(next) + local ncode = categories[nchar] + if ncode == "lu" or ncode == "ll" then + local next2 = getnext(next) + if next2 and getid(next2) == glyph_code and getchar(next2) == period then + -- A.B. + local fontspace, inserted + if factor ~= 0 then + fontspace = parameters[getfont(current)].space -- can be sped up + inserted = factor * fontspace + insertafter(head,current,new_kern(inserted)) + if trace then + report("inserting space at %C . [%p] %C .",pchar,inserted,nchar) + end + end + local next3 = getnext(next2) + if next3 and getid(next3) == glue_code and getsubtype(next3) == spaceskip_code then + local width = getwidth(next3) + local space = fontspace or parameters[getfont(current)].space -- can be sped up + if width > space then -- space + extraspace + local next4 = getnext(next3) + if next4 and getid(next4) == glyph_code then + local fchar = getchar(next4) + if categories[fchar] ~= "lu" then + -- A.B.<glue>X + if trace then + if inserted then + report("reverting space at %C . [%p] %C . [%p->%p] %C",pchar,inserted,nchar,width,space,fchar) + else + report("reverting space at %C . %C . [%p->%p] %C",pchar,nchar,width,space,fchar) + end + end + setwidth(next3,space) + else + if trace then + if inserted then + report("keeping space at %C . [%p] %C . [%p] %C",pchar,inserted,nchar,width,fchar) + else + report("keeping space at %C . %C . [%p] %C",pchar,nchar,width,fchar) + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + return head +end + +local enabled = false + +function periodkerns.set(factor) + factor = tonumber(factor) or 0 + if not enabled then + enableaction("processors","typesetters.periodkerns.handler") + enabled = true + end + local a = factors[factor] + if not a then + a = #mapping + 1 + factors[factors], mapping[a] = a, factor + end + factor = a + texsetattribute(a_periodkern,factor) + return factor +end + +-- interface + +interfaces.implement { + name = "setperiodkerning", + actions = periodkerns.set, + arguments = "string" +} + + diff --git a/tex/context/base/mkxl/typo-pnc.mkxl b/tex/context/base/mkxl/typo-pnc.mkxl index b5b1a17d6..aceab2685 100644 --- a/tex/context/base/mkxl/typo-pnc.mkxl +++ b/tex/context/base/mkxl/typo-pnc.mkxl @@ -19,7 +19,7 @@ % with "foo e.g.\ bar" so let's see if we can automate that and at the same time % inject spaces between the snippets. It gets boring writing this kind of code. -\registerctxluafile{typo-pnc}{} +\registerctxluafile{typo-pnc}{autosuffix} \definesystemattribute[periodkern][public,global] diff --git a/tex/context/fonts/mkiv/antykwa-math.lfg b/tex/context/fonts/mkiv/antykwa-math.lfg index fe259e909..3c34d7af0 100644 --- a/tex/context/fonts/mkiv/antykwa-math.lfg +++ b/tex/context/fonts/mkiv/antykwa-math.lfg @@ -19,6 +19,12 @@ local badones = { coproductdisplay = .25, } +local uglyones = { + braceleft = true, + braceright = true, +} + + return { name = "antykwa-math", version = "1.00", @@ -42,7 +48,8 @@ return { { name = "mi-anttri.tfm", vector = "tex-it", skewchar=0x7F }, { name = "mi-anttbi.tfm", vector = "tex-bi", skewchar=0x7F }, { name = "rm-anttb.tfm", vector = "tex-bf", skewchar=0x7F }, - { name = "sy-anttrz.tfm", vector = "tex-sy", skewchar=0x30, parameters = true }, + { name = "sy-anttrz.tfm", vector = "tex-sy", skewchar=0x30, parameters = true, ignore = uglyones }, + { name = "file:AntykwaTorunska-Regular", vector = "tex-ex-braces", backmap = false }, { name = "ex-anttr.tfm", vector = "tex-ex", extension = true, badones = badones }, }, ["antykwa-light-math"] = { @@ -53,7 +60,8 @@ return { { name = "mi-anttli.tfm", vector = "tex-it", skewchar=0x7F }, { name = "mi-anttri.tfm", vector = "tex-bi", skewchar=0x7F }, { name = "rm-anttr.tfm", vector = "tex-bf", skewchar=0x7F }, - { name = "sy-anttlz.tfm", vector = "tex-sy", skewchar=0x30, parameters = true }, + { name = "sy-anttlz.tfm", vector = "tex-sy", skewchar=0x30, parameters = true, ignore = uglyones }, + { name = "file:AntykwaTorunskaLight-Regular", vector = "tex-ex-braces", backmap = false }, { name = "ex-anttl.tfm", vector = "tex-ex", extension = true, badones = badones }, }, ["antykwa-cond-math"] = { @@ -64,7 +72,8 @@ return { { name = "mi-anttcri.tfm", vector = "tex-it", skewchar=0x7F }, { name = "mi-anttcbi.tfm", vector = "tex-bi", skewchar=0x7F }, { name = "rm-anttcb.tfm", vector = "tex-bf", skewchar=0x7F }, - { name = "sy-anttcrz.tfm", vector = "tex-sy", skewchar=0x30, parameters = true }, + { name = "sy-anttcrz.tfm", vector = "tex-sy", skewchar=0x30, parameters = true, ignore = uglyones }, + { name = "file:AntykwaTorunskaCond-Regular", vector = "tex-ex-braces", backmap = false }, { name = "ex-anttcr.tfm", vector = "tex-ex", extension = true, badones = badones }, }, ["antykwa-lightcond-math"] = { @@ -75,7 +84,8 @@ return { { name = "mi-anttcli.tfm", vector = "tex-it", skewchar=0x7F }, { name = "mi-anttcri.tfm", vector = "tex-bi", skewchar=0x7F }, { name = "rm-anttcr.tfm", vector = "tex-bf", skewchar=0x7F }, - { name = "sy-anttclz.tfm", vector = "tex-sy", skewchar=0x30, parameters = true }, + { name = "sy-anttclz.tfm", vector = "tex-sy", skewchar=0x30, parameters = true, ignore = uglyones }, + { name = "file:AntykwaTorunskaCondLight-Regular", vector = "tex-ex-braces", backmap = false }, { name = "ex-anttcl.tfm", vector = "tex-ex", extension = true, badones = badones }, } } diff --git a/tex/context/fonts/mkiv/bonum-math.lfg b/tex/context/fonts/mkiv/bonum-math.lfg index e3fd4119d..56262eb32 100644 --- a/tex/context/fonts/mkiv/bonum-math.lfg +++ b/tex/context/fonts/mkiv/bonum-math.lfg @@ -139,6 +139,16 @@ return { ["0x221A.parts.bottom"] = { location = "left", hfactor = .1, vfactor = 1.15 }, } }, + { + tweak = "dimensions", + list = { + -- [0x007D] = { topright = -0.05, bottomright = -0.05 }, -- right brace variants + ["0x7C"] = { width = 1.4, xoffset=0.2 }, -- vertical bar + -- ["0x7C.variants.*"] = { width = 1, extend = 2.4 }, -- vertical bar + -- ["0x7C.parts.top"] = { , }, -- vertical bar + -- ["0x7C.parts.bottom"] = { bottomright = -0.15 }, -- vertical bar + }, + }, { tweak = "fixaccents", @@ -277,7 +287,7 @@ return { }, { tweak = "addbars", - advance = 0.275, + advance = 0.475, }, { tweak = "addactuarian", diff --git a/tex/context/fonts/mkiv/type-imp-antykwa.mkiv b/tex/context/fonts/mkiv/type-imp-antykwa.mkiv index 15a2f39b6..6ad747307 100644 --- a/tex/context/fonts/mkiv/type-imp-antykwa.mkiv +++ b/tex/context/fonts/mkiv/type-imp-antykwa.mkiv @@ -34,7 +34,7 @@ \definefontsynonym [AntykwaTorunska-Light] [\s!file:AntykwaTorunskaLight-Regular] [\s!features=\s!default] \definefontsynonym [AntykwaTorunska-LightItalic] [\s!file:AntykwaTorunskaLight-Italic] [\s!features=\s!default] \definefontsynonym [AntykwaTorunska-Medium] [\s!file:AntykwaTorunskaMed-Regular] [\s!features=\s!default] - \definefontsynonym [AntykwaTorunska-MedItalic] [\s!file:AntykwaTorunskaMed-Italic] [\s!features=\s!default] + \definefontsynonym [AntykwaTorunska-MediumItalic] [\s!file:AntykwaTorunskaMed-Italic] [\s!features=\s!default] \definefontsynonym [AntykwaTorunska-CondRegular] [\s!file:AntykwaTorunskaCond-Regular] [\s!features=\s!default] \definefontsynonym [AntykwaTorunska-CondItalic] [\s!file:AntykwaTorunskaCond-Italic] [\s!features=\s!default] \definefontsynonym [AntykwaTorunska-CondBold] [\s!file:AntykwaTorunskaCond-Bold] [\s!features=\s!default] @@ -42,24 +42,7 @@ \definefontsynonym [AntykwaTorunska-CondLight] [\s!file:AntykwaTorunskaCondLight-Regular] [\s!features=\s!default] \definefontsynonym [AntykwaTorunska-CondLightItalic] [\s!file:AntykwaTorunskaCondLight-Italic] [\s!features=\s!default] \definefontsynonym [AntykwaTorunska-CondMedium] [\s!file:AntykwaTorunskaCondMed-Regular] [\s!features=\s!default] - \definefontsynonym [AntykwaTorunska-CondMedItalic] [\s!file:AntykwaTorunskaCondMed-Italic] [\s!features=\s!default] - - \definefontsynonym [AntykwaTorunska-Cap] [\s!file:AntykwaTorunska-Regular] [\s!features=\s!smallcaps] - \definefontsynonym [AntykwaTorunska-ItalicCap] [\s!file:AntykwaTorunska-Italic] [\s!features=\s!smallcaps] - \definefontsynonym [AntykwaTorunska-BoldCap] [\s!file:AntykwaTorunska-Bold] [\s!features=\s!smallcaps] - \definefontsynonym [AntykwaTorunska-BoldItalicCap] [\s!file:AntykwaTorunska-BoldItalic] [\s!features=\s!smallcaps] - \definefontsynonym [AntykwaTorunska-LightCap] [\s!file:AntykwaTorunskaLight-Regular] [\s!features=\s!smallcaps] - \definefontsynonym [AntykwaTorunska-LightItalicCap] [\s!file:AntykwaTorunskaLight-Italic] [\s!features=\s!smallcaps] - \definefontsynonym [AntykwaTorunska-MediumCap] [\s!file:AntykwaTorunskaMed-Regular] [\s!features=\s!smallcaps] - \definefontsynonym [AntykwaTorunska-MedItalicCap] [\s!file:AntykwaTorunskaMed-Italic] [\s!features=\s!smallcaps] - \definefontsynonym [AntykwaTorunska-CondCap] [\s!file:AntykwaTorunskaCond-Regular] [\s!features=\s!smallcaps] - \definefontsynonym [AntykwaTorunska-CondItalicCap] [\s!file:AntykwaTorunskaCond-Italic] [\s!features=\s!smallcaps] - \definefontsynonym [AntykwaTorunska-CondBoldCap] [\s!file:AntykwaTorunskaCond-Bold] [\s!features=\s!smallcaps] - \definefontsynonym [AntykwaTorunska-CondBoldItalicCap] [\s!file:AntykwaTorunskaCond-BoldItalic] [\s!features=\s!smallcaps] - \definefontsynonym [AntykwaTorunska-CondLightCap] [\s!file:AntykwaTorunskaCondLight-Regular] [\s!features=\s!smallcaps] - \definefontsynonym [AntykwaTorunska-CondLightItalicCap][\s!file:AntykwaTorunskaCondLight-Italic] [\s!features=\s!smallcaps] - \definefontsynonym [AntykwaTorunska-CondMediumCap] [\s!file:AntykwaTorunskaCondMed-Regular] [\s!features=\s!smallcaps] - \definefontsynonym [AntykwaTorunska-CondMedItalicCap] [\s!file:AntykwaTorunskaCondMed-Italic] [\s!features=\s!smallcaps] + \definefontsynonym [AntykwaTorunska-CondMediumItalic] [\s!file:AntykwaTorunskaCondMed-Italic] [\s!features=\s!default] \stoptypescript \starttypescript [\s!math][antykwa,antykwa-torunska][\s!all] @@ -89,7 +72,6 @@ \definefontsynonym [\s!SerifSlanted] [AntykwaTorunska-Italic] \definefontsynonym [\s!SerifBoldItalic] [AntykwaTorunska-BoldItalic] \definefontsynonym [\s!SerifBoldSlanted] [AntykwaTorunska-BoldItalic] - \definefontsynonym [\s!SerifCaps] [AntykwaTorunska-Cap] \stoptypescript \starttypescript [\s!serif] [antykwa-light,antykwa-torunska-light] [\s!name] @@ -97,9 +79,8 @@ \definefontsynonym [\s!SerifBold] [AntykwaTorunska-Medium] \definefontsynonym [\s!SerifItalic] [AntykwaTorunska-LightItalic] \definefontsynonym [\s!SerifSlanted] [AntykwaTorunska-LightItalic] - \definefontsynonym [\s!SerifBoldItalic] [AntykwaTorunska-MedItalic] - \definefontsynonym [\s!SerifBoldSlanted] [AntykwaTorunska-MedItalic] - \definefontsynonym [\s!SerifCaps] [AntykwaTorunska-LightCap] + \definefontsynonym [\s!SerifBoldItalic] [AntykwaTorunska-MediumItalic] + \definefontsynonym [\s!SerifBoldSlanted] [AntykwaTorunska-MediumItalic] \stoptypescript \starttypescript [\s!serif] [antykwa-cond,antykwa-torunska-cond] [\s!name] @@ -109,7 +90,6 @@ \definefontsynonym [\s!SerifSlanted] [AntykwaTorunska-CondItalic] \definefontsynonym [\s!SerifBoldItalic] [AntykwaTorunska-CondBoldItalic] \definefontsynonym [\s!SerifBoldSlanted] [AntykwaTorunska-CondBoldItalic] - \definefontsynonym [\s!SerifCaps] [AntykwaTorunska-CondCap] \stoptypescript \starttypescript [\s!serif] [antykwa-lightcond,antykwa-torunska-lightcond] [\s!name] @@ -117,117 +97,8 @@ \definefontsynonym [\s!SerifBold] [AntykwaTorunska-CondMedium] \definefontsynonym [\s!SerifItalic] [AntykwaTorunska-CondLightItalic] \definefontsynonym [\s!SerifSlanted] [AntykwaTorunska-CondLightItalic] - \definefontsynonym [\s!SerifBoldItalic] [AntykwaTorunska-CondMedItalic] - \definefontsynonym [\s!SerifBoldSlanted] [AntykwaTorunska-CondMedItalic] - \definefontsynonym [\s!SerifCaps] [AntykwaTorunska-CondLightCap] - \stoptypescript - - \starttypescript [\s!serif] [antykwa,antykwa-torunska] [\s!name] - \definefontsynonym [SerifRegular] [Serif] - \definefontsynonym [SerifRegularCaps] [AntykwaTorunska-Cap] - \definefontsynonym [SerifBoldCaps] [AntykwaTorunska-BoldCap] - \definefontsynonym [SerifItalicCaps] [AntykwaTorunska-ItalicCap] - \definefontsynonym [SerifSlantedCaps] [AntykwaTorunska-ItalicCap] - \definefontsynonym [SerifBoldItalicCaps] [AntykwaTorunska-BoldItalicCap] - \definefontsynonym [SerifBoldSlantedCaps] [AntykwaTorunska-BoldItalicCap] - \definefontsynonym [SerifCapsCaps] [AntykwaTorunska-Cap] - - \definefontsynonym [SerifRegularLight] [AntykwaTorunska-Light] - \definefontsynonym [SerifBoldLight] [AntykwaTorunska-Medium] - \definefontsynonym [SerifItalicLight] [AntykwaTorunska-LightItalic] - \definefontsynonym [SerifSlantedLight] [AntykwaTorunska-LightItalic] - \definefontsynonym [SerifBoldItalicLight] [AntykwaTorunska-MedItalic] - \definefontsynonym [SerifBoldSlantedLight] [AntykwaTorunska-MedItalic] - \definefontsynonym [SerifCapsLight] [AntykwaTorunska-LightCap] - - \definefontsynonym [SerifRegularCond] [AntykwaTorunska-CondRegular] - \definefontsynonym [SerifBoldCond] [AntykwaTorunska-CondBold] - \definefontsynonym [SerifItalicCond] [AntykwaTorunska-CondItalic] - \definefontsynonym [SerifSlantedCond] [AntykwaTorunska-CondItalic] - \definefontsynonym [SerifBoldItalicCond] [AntykwaTorunska-CondBoldItalic] - \definefontsynonym [SerifBoldSlantedCond] [AntykwaTorunska-CondBoldItalic] - \definefontsynonym [SerifCapsCond] [AntykwaTorunska-CondCap] - \stoptypescript - - \starttypescript [\s!serif] [antykwa-light,antykwa-torunska-light] [\s!name] - \definefontsynonym [SerifRegular] [Serif] - \definefontsynonym [SerifRegularCaps] [AntykwaTorunska-LightCap] - \definefontsynonym [SerifBoldCaps] [AntykwaTorunska-MediumCap] - \definefontsynonym [SerifItalicCaps] [AntykwaTorunska-LightItalicCap] - \definefontsynonym [SerifSlantedCaps] [AntykwaTorunska-LightItalicCap] - \definefontsynonym [SerifBoldItalicCaps] [AntykwaTorunska-MedItalicCap] - \definefontsynonym [SerifBoldSlantedCaps] [AntykwaTorunska-MedItalicCap] - \definefontsynonym [SerifCapsCaps] [AntykwaTorunska-LightCap] - - \definefontsynonym [SerifRegularDark] [AntykwaTorunska-Regular] - \definefontsynonym [SerifBoldDark] [AntykwaTorunska-Bold] - \definefontsynonym [SerifItalicDark] [AntykwaTorunska-Italic] - \definefontsynonym [SerifSlantedDark] [AntykwaTorunska-Italic] - \definefontsynonym [SerifBoldItalicDark] [AntykwaTorunska-BoldItalic] - \definefontsynonym [SerifBoldSlantedDark] [AntykwaTorunska-BoldItalic] - \definefontsynonym [SerifCapsDark] [AntykwaTorunska-Cap] - - \definefontsynonym [SerifRegularCond] [AntykwaTorunska-CondLight] - \definefontsynonym [SerifBoldCond] [AntykwaTorunska-CondMedium] - \definefontsynonym [SerifItalicCond] [AntykwaTorunska-CondLightItalic] - \definefontsynonym [SerifSlantedCond] [AntykwaTorunska-CondLightItalic] - \definefontsynonym [SerifBoldItalicCond] [AntykwaTorunska-CondMedItalic] - \definefontsynonym [SerifBoldSlantedCond] [AntykwaTorunska-CondMedItalic] - \definefontsynonym [SerifCapsCond] [AntykwaTorunska-CondLightCap] - \stoptypescript - - \starttypescript [\s!serif] [antykwa-cond,antykwa-torunska-cond] [\s!name] - \definefontsynonym [SerifRegular] [Serif] - \definefontsynonym [SerifRegularCaps] [AntykwaTorunska-CondCap] - \definefontsynonym [SerifBoldCaps] [AntykwaTorunska-CondBoldCap] - \definefontsynonym [SerifItalicCaps] [AntykwaTorunska-CondItalicCap] - \definefontsynonym [SerifSlantedCaps] [AntykwaTorunska-CondItalicCap] - \definefontsynonym [SerifBoldItalicCaps] [AntykwaTorunska-CondBoldItalicCap] - \definefontsynonym [SerifBoldSlantedCaps] [AntykwaTorunska-CondBoldItalicCap] - \definefontsynonym [SerifCapsCaps] [AntykwaTorunska-CondCap] - - \definefontsynonym [SerifRegularLight] [AntykwaTorunska-CondLight] - \definefontsynonym [SerifBoldLight] [AntykwaTorunska-CondMedium] - \definefontsynonym [SerifItalicLight] [AntykwaTorunska-CondLightItalic] - \definefontsynonym [SerifSlantedLight] [AntykwaTorunska-CondLightItalic] - \definefontsynonym [SerifBoldItalicLight] [AntykwaTorunska-CondMedItalic] - \definefontsynonym [SerifBoldSlantedLight] [AntykwaTorunska-CondMedItalic] - \definefontsynonym [SerifCapsLight] [AntykwaTorunska-CondLightCap] - - \definefontsynonym [SerifRegularExp] [AntykwaTorunska-Regular] - \definefontsynonym [SerifBoldExp] [AntykwaTorunska-Bold] - \definefontsynonym [SerifItalicExp] [AntykwaTorunska-Italic] - \definefontsynonym [SerifSlantedExp] [AntykwaTorunska-Italic] - \definefontsynonym [SerifBoldItalicExp] [AntykwaTorunska-BoldItalic] - \definefontsynonym [SerifBoldSlantedExp] [AntykwaTorunska-BoldItalic] - \definefontsynonym [SerifCapsExp] [AntykwaTorunska-Cap] - \stoptypescript - - \starttypescript [\s!serif] [antykwa-lightcond,antykwa-torunska-lightcond] [\s!name] - \definefontsynonym [SerifRegular] [Serif] - \definefontsynonym [SerifRegularCaps] [AntykwaTorunska-CondLightCap] - \definefontsynonym [SerifBoldCaps] [AntykwaTorunska-CondMediumCap] - \definefontsynonym [SerifItalicCaps] [AntykwaTorunska-CondLightItalicCap] - \definefontsynonym [SerifSlantedCaps] [AntykwaTorunska-CondLightItalicCap] - \definefontsynonym [SerifBoldItalicCaps] [AntykwaTorunska-CondMedItalicCap] - \definefontsynonym [SerifBoldSlantedCaps] [AntykwaTorunska-CondMedItalicCap] - \definefontsynonym [SerifCapsCaps] [AntykwaTorunska-CondLightCap] - - \definefontsynonym [SerifRegularDark] [AntykwaTorunska-CondRegular] - \definefontsynonym [SerifBoldDark] [AntykwaTorunska-CondBold] - \definefontsynonym [SerifItalicDark] [AntykwaTorunska-CondItalic] - \definefontsynonym [SerifSlantedDark] [AntykwaTorunska-CondItalic] - \definefontsynonym [SerifBoldItalicDark] [AntykwaTorunska-CondBoldItalic] - \definefontsynonym [SerifBoldSlantedDark] [AntykwaTorunska-CondBoldItalic] - \definefontsynonym [SerifCapsDark] [AntykwaTorunska-CondCap] - - \definefontsynonym [SerifRegularExp] [AntykwaTorunska-Light] - \definefontsynonym [SerifBoldExp] [AntykwaTorunska-Medium] - \definefontsynonym [SerifItalicExp] [AntykwaTorunska-LightItalic] - \definefontsynonym [SerifSlantedExp] [AntykwaTorunska-LightItalic] - \definefontsynonym [SerifBoldItalicExp] [AntykwaTorunska-MedItalic] - \definefontsynonym [SerifBoldSlantedExp] [AntykwaTorunska-MedItalic] - \definefontsynonym [SerifCapsExp] [AntykwaTorunska-LightCap] + \definefontsynonym [\s!SerifBoldItalic] [AntykwaTorunska-CondMediumItalic] + \definefontsynonym [\s!SerifBoldSlanted] [AntykwaTorunska-CondMediumItalic] \stoptypescript \stoptypescriptcollection diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index 9618051bd..aaf99ed45 100644 --- a/tex/generic/context/luatex/luatex-fonts-merged.lua +++ b/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 : 2023-02-07 19:02 +-- merge date : 2023-02-14 17:41 do -- begin closure to overcome local limits and interference |