summaryrefslogtreecommitdiff
path: root/tex/context
diff options
context:
space:
mode:
authorHans Hagen <pragma@wxs.nl>2018-04-13 15:51:39 +0200
committerContext Git Mirror Bot <phg42.2a@gmail.com>2018-04-13 15:51:39 +0200
commit25fcad7435f56cdce2658336909f4da6a65589c0 (patch)
treec23d5d04a7e86c7ddc2ebeca06d3de63ebdc806e /tex/context
parent1e5d7f41ddede5e6400a2a7762032823d3545df4 (diff)
downloadcontext-25fcad7435f56cdce2658336909f4da6a65589c0.tar.gz
2018-04-13 15:02:00
Diffstat (limited to 'tex/context')
-rw-r--r--tex/context/base/mkii/cont-new.mkii2
-rw-r--r--tex/context/base/mkii/context.mkii2
-rw-r--r--tex/context/base/mkii/mult-nl.mkii7
-rw-r--r--tex/context/base/mkiv/anch-bck.mkvi4
-rw-r--r--tex/context/base/mkiv/back-exp.lua14
-rw-r--r--tex/context/base/mkiv/buff-ini.mkiv24
-rw-r--r--tex/context/base/mkiv/catc-ini.mkiv161
-rw-r--r--tex/context/base/mkiv/char-act.mkiv36
-rw-r--r--tex/context/base/mkiv/cldf-ini.lua8
-rw-r--r--tex/context/base/mkiv/cont-new.mkiv2
-rw-r--r--tex/context/base/mkiv/context.mkiv4
-rw-r--r--tex/context/base/mkiv/font-cft.lua10
-rw-r--r--tex/context/base/mkiv/font-chk.lua39
-rw-r--r--tex/context/base/mkiv/font-col.lua31
-rw-r--r--tex/context/base/mkiv/font-con.lua64
-rw-r--r--tex/context/base/mkiv/font-ctx.lua347
-rw-r--r--tex/context/base/mkiv/font-def.lua1
-rw-r--r--tex/context/base/mkiv/font-dsp.lua34
-rw-r--r--tex/context/base/mkiv/font-enh.lua16
-rw-r--r--tex/context/base/mkiv/font-ext.lua1856
-rw-r--r--tex/context/base/mkiv/font-fbk.lua260
-rw-r--r--tex/context/base/mkiv/font-fea.mkvi10
-rw-r--r--tex/context/base/mkiv/font-imp-dimensions.lua113
-rw-r--r--tex/context/base/mkiv/font-imp-effects.lua397
-rw-r--r--tex/context/base/mkiv/font-imp-italics.lua147
-rw-r--r--tex/context/base/mkiv/font-imp-ligatures.lua136
-rw-r--r--tex/context/base/mkiv/font-imp-math.lua79
-rw-r--r--tex/context/base/mkiv/font-imp-notused.lua166
-rw-r--r--tex/context/base/mkiv/font-imp-properties.lua128
-rw-r--r--tex/context/base/mkiv/font-imp-quality.lua477
-rw-r--r--tex/context/base/mkiv/font-imp-reorder.lua172
-rw-r--r--tex/context/base/mkiv/font-imp-tex.lua144
-rw-r--r--tex/context/base/mkiv/font-imp-tracing.lua171
-rw-r--r--tex/context/base/mkiv/font-imp-unicode.lua80
-rw-r--r--tex/context/base/mkiv/font-ini.mkvi10
-rw-r--r--tex/context/base/mkiv/font-lib.mkvi21
-rw-r--r--tex/context/base/mkiv/font-map.lua105
-rw-r--r--tex/context/base/mkiv/font-mat.mkvi30
-rw-r--r--tex/context/base/mkiv/font-nod.lua13
-rw-r--r--tex/context/base/mkiv/font-ocl.lua59
-rw-r--r--tex/context/base/mkiv/font-otc.lua299
-rw-r--r--tex/context/base/mkiv/font-otj.lua4
-rw-r--r--tex/context/base/mkiv/font-ott.lua22
-rw-r--r--tex/context/base/mkiv/font-pre.mkiv30
-rw-r--r--tex/context/base/mkiv/font-prv.lua74
-rw-r--r--tex/context/base/mkiv/font-shp.lua10
-rw-r--r--tex/context/base/mkiv/font-tfm.lua5
-rw-r--r--tex/context/base/mkiv/font-vfc.lua98
-rw-r--r--tex/context/base/mkiv/font-vir.lua8
-rw-r--r--tex/context/base/mkiv/l-file.lua38
-rw-r--r--tex/context/base/mkiv/l-lpeg.lua31
-rw-r--r--tex/context/base/mkiv/l-os.lua35
-rw-r--r--tex/context/base/mkiv/l-table.lua16
-rw-r--r--tex/context/base/mkiv/lang-ini.mkiv7
-rw-r--r--tex/context/base/mkiv/lang-lab.mkiv12
-rw-r--r--tex/context/base/mkiv/lpdf-ano.lua84
-rw-r--r--tex/context/base/mkiv/lpdf-tag.lua8
-rw-r--r--tex/context/base/mkiv/luat-cod.lua15
-rw-r--r--tex/context/base/mkiv/lxml-css.lua135
-rw-r--r--tex/context/base/mkiv/lxml-lpt.lua4
-rw-r--r--tex/context/base/mkiv/lxml-tex.lua6
-rw-r--r--tex/context/base/mkiv/math-ext.lua25
-rw-r--r--tex/context/base/mkiv/math-fbk.lua161
-rw-r--r--tex/context/base/mkiv/math-ini.mkiv39
-rw-r--r--tex/context/base/mkiv/math-noa.lua31
-rw-r--r--tex/context/base/mkiv/math-tag.lua3
-rw-r--r--tex/context/base/mkiv/math-vfu.lua266
-rw-r--r--tex/context/base/mkiv/meta-blb.lua305
-rw-r--r--tex/context/base/mkiv/meta-blb.mkiv50
-rw-r--r--tex/context/base/mkiv/meta-imp-txt.mkiv54
-rw-r--r--tex/context/base/mkiv/mlib-lua.lua61
-rw-r--r--tex/context/base/mkiv/mlib-pdf.lua3
-rw-r--r--tex/context/base/mkiv/mlib-pps.lua37
-rw-r--r--tex/context/base/mkiv/mult-low.lua4
-rw-r--r--tex/context/base/mkiv/mult-prm.lua2
-rw-r--r--tex/context/base/mkiv/node-aux.lua12
-rw-r--r--tex/context/base/mkiv/node-met.lua22
-rw-r--r--tex/context/base/mkiv/node-nut.lua30
-rw-r--r--tex/context/base/mkiv/node-shp.lua3
-rw-r--r--tex/context/base/mkiv/node-tra.lua6
-rw-r--r--tex/context/base/mkiv/publ-ini.lua4
-rw-r--r--tex/context/base/mkiv/spac-ver.lua9
-rw-r--r--tex/context/base/mkiv/status-files.pdfbin26044 -> 26098 bytes
-rw-r--r--tex/context/base/mkiv/status-lua.pdfbin255106 -> 256761 bytes
-rw-r--r--tex/context/base/mkiv/strc-doc.mkiv10
-rw-r--r--tex/context/base/mkiv/strc-mar.lua3
-rw-r--r--tex/context/base/mkiv/strc-num.mkiv8
-rw-r--r--tex/context/base/mkiv/strc-ref.lua36
-rw-r--r--tex/context/base/mkiv/strc-ref.mkvi422
-rw-r--r--tex/context/base/mkiv/supp-box.lua7
-rw-r--r--tex/context/base/mkiv/supp-box.mkiv5
-rw-r--r--tex/context/base/mkiv/syst-aux.mkiv57
-rw-r--r--tex/context/base/mkiv/syst-ini.mkiv394
-rw-r--r--tex/context/base/mkiv/trac-inf.lua21
-rw-r--r--tex/context/base/mkiv/trac-log.lua52
-rw-r--r--tex/context/base/mkiv/trac-vis.lua3
-rw-r--r--tex/context/base/mkiv/trac-vis.mkiv5
-rw-r--r--tex/context/base/mkiv/util-lua.lua4
-rw-r--r--tex/context/base/mkiv/util-prs.lua25
-rw-r--r--tex/context/base/mkiv/util-sto.lua10
-rw-r--r--tex/context/fonts/mkiv/type-imp-cambria.mkiv11
-rw-r--r--tex/context/fonts/mkiv/type-imp-dejavu.mkiv5
-rw-r--r--tex/context/fonts/mkiv/type-imp-latinmodern.mkiv4
-rw-r--r--tex/context/fonts/mkiv/type-imp-modernlatin.mkiv56
-rw-r--r--tex/context/fonts/mkiv/type-imp-texgyre.mkiv17
-rw-r--r--tex/context/interface/mkii/keys-nl.xml7
-rw-r--r--tex/context/interface/mkiv/context-en.xml80
-rw-r--r--tex/context/interface/mkiv/i-context.pdfbin846253 -> 847282 bytes
-rw-r--r--tex/context/interface/mkiv/i-fonts.xml24
-rw-r--r--tex/context/interface/mkiv/i-readme.pdfbin61030 -> 61034 bytes
-rw-r--r--tex/context/interface/mkiv/i-visualizer.xml6
-rw-r--r--tex/context/interface/mkiv/i-xml.xml28
112 files changed, 5115 insertions, 3633 deletions
diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii
index d8599af1a..734fea0b7 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{2018.04.03 22:22}
+\newcontextversion{2018.04.13 14:53}
%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 31663439f..22b2f44c9 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{2018.04.03 22:22}
+\edef\contextversion{2018.04.13 14:53}
%D For those who want to use this:
diff --git a/tex/context/base/mkii/mult-nl.mkii b/tex/context/base/mkii/mult-nl.mkii
index ba7c5a42c..be6df5d07 100644
--- a/tex/context/base/mkii/mult-nl.mkii
+++ b/tex/context/base/mkii/mult-nl.mkii
@@ -185,6 +185,7 @@
\setinterfacevariable{extremestretch}{extremestretch}
\setinterfacevariable{fact}{gegeven}
\setinterfacevariable{february}{februari}
+\setinterfacevariable{field}{veld}
\setinterfacevariable{figure}{figuur}
\setinterfacevariable{figures}{figuren}
\setinterfacevariable{file}{file}
@@ -794,7 +795,7 @@
\setinterfaceconstant{family}{soort}
\setinterfaceconstant{features}{features}
\setinterfaceconstant{fences}{fences}
-\setinterfaceconstant{field}{field}
+\setinterfaceconstant{field}{veld}
\setinterfaceconstant{fieldbackgroundcolor}{veldachtergrondkleur}
\setinterfaceconstant{fieldframecolor}{veldkaderkleur}
\setinterfaceconstant{fieldlayer}{veldlaag}
@@ -849,6 +850,7 @@
\setinterfaceconstant{headerstate}{hoofdstatus}
\setinterfaceconstant{headlabel}{koplabel}
\setinterfaceconstant{headnumber}{kopnummer}
+\setinterfaceconstant{headseparator}{kopscheider}
\setinterfaceconstant{headstyle}{kopletter}
\setinterfaceconstant{height}{hoogte}
\setinterfaceconstant{hfactor}{hfactor}
@@ -1075,6 +1077,7 @@
\setinterfaceconstant{preview}{preview}
\setinterfaceconstant{previous}{vorige}
\setinterfaceconstant{previousnumber}{vorigenummer}
+\setinterfaceconstant{print}{print}
\setinterfaceconstant{printable}{printbaar}
\setinterfaceconstant{process}{proces}
\setinterfaceconstant{profile}{profile}
@@ -1160,8 +1163,10 @@
\setinterfaceconstant{sidemethod}{zijmethode}
\setinterfaceconstant{sidespaceafter}{zijnawit}
\setinterfaceconstant{sidespacebefore}{zijvoorwit}
+\setinterfaceconstant{sidespaceinbetween}{zijtussenwit}
\setinterfaceconstant{sidethreshold}{sidethreshold}
\setinterfaceconstant{sign}{teken}
+\setinterfaceconstant{simplecommand}{simpelcommando}
\setinterfaceconstant{size}{formaat}
\setinterfaceconstant{slantedfeatures}{slantedfeatures}
\setinterfaceconstant{slantedfont}{slantedfont}
diff --git a/tex/context/base/mkiv/anch-bck.mkvi b/tex/context/base/mkiv/anch-bck.mkvi
index 348ea0ad1..911b1bca2 100644
--- a/tex/context/base/mkiv/anch-bck.mkvi
+++ b/tex/context/base/mkiv/anch-bck.mkvi
@@ -474,13 +474,13 @@
\strc_floats_mark_as_free
\plustwo
\d_page_sides_leftskip
- \d_strc_floats_margin
+ \d_page_sides_margin
\d_page_sides_topskip
\d_page_sides_bottomskip
\or % rightside
\strc_floats_mark_as_free
\plusthree
- \d_strc_floats_margin
+ \d_page_sides_margin
\d_page_sides_rightskip
\d_page_sides_topskip
\d_page_sides_bottomskip
diff --git a/tex/context/base/mkiv/back-exp.lua b/tex/context/base/mkiv/back-exp.lua
index b18679fa2..26efe6aad 100644
--- a/tex/context/base/mkiv/back-exp.lua
+++ b/tex/context/base/mkiv/back-exp.lua
@@ -118,6 +118,7 @@ local tonut = nuts.tonut
local getnext = nuts.getnext
local getsubtype = nuts.getsubtype
local getfont = nuts.getfont
+local getchar = nuts.getchar
local getdisc = nuts.getdisc
local getcomponents = nuts.getcomponents
local getlist = nuts.getlist
@@ -167,7 +168,7 @@ local currentparagraph = nil
local noftextblocks = 0
-local hyphencode = 0xAD
+----- hyphencode = 0xAD
local hyphen = utfchar(0xAD) -- todo: also emdash etc
local tagsplitter = structurestags.patterns.splitter
----- colonsplitter = lpeg.splitat(":")
@@ -2748,9 +2749,12 @@ end
local function collectresults(head,list,pat,pap) -- is last used (we also have currentattribute)
local p
- for n in traverse_nodes(head) do
- local c, id = isglyph(n) -- 14: image, 8: literal (mp)
- if c then
+-- for n in traverse_nodes(head) do
+-- local c, id = isglyph(n) -- 14: image, 8: literal (mp)
+-- if c then
+ for n, id in traverse_nodes(head) do
+ if id == glyph_code then
+ local c = getchar(n)
local at = getattr(n,a_tagged) or pat
if not at then
-- we need to tag the pagebody stuff as being valid skippable
@@ -2855,7 +2859,7 @@ local function collectresults(head,list,pat,pap) -- is last used (we also have c
elseif id == disc_code then -- probably too late
local pre, post, replace = getdisc(n)
if keephyphens then
- if pre and not getnext(pre) and isglyph(pre) == hyphencode then
+ if pre and not getnext(pre) and isglyph(pre) == 0xAD then -- hyphencode then
nofcurrentcontent = nofcurrentcontent + 1
currentcontent[nofcurrentcontent] = hyphen
end
diff --git a/tex/context/base/mkiv/buff-ini.mkiv b/tex/context/base/mkiv/buff-ini.mkiv
index 1a5ce4591..6baf752cd 100644
--- a/tex/context/base/mkiv/buff-ini.mkiv
+++ b/tex/context/base/mkiv/buff-ini.mkiv
@@ -274,28 +274,4 @@
\def\getbufferdata[#1]{\buff_get_stored_indeed{#1}}
-%D This is a weird one, moved from cont-new. Do we really need it? If not
-%D it will go away.
-
-\bgroup \permitcircumflexescape
-
-\obeylines % don't remove %'s !
-
-\gdef\collapsedspace#1%
- {\ifx#1^^M%
- \expandafter\collapsedspace
- \else
- \space
- \expandafter#1%
- \fi}
-
-\unexpanded\gdef\collapsespaces
- {\prependtoksonce\relax\to\everyeof%
- \ignorelines%
- \ignoretabs%
- \let\obeyedspace\collapsedspace%
- \obeyspaces}
-
-\egroup
-
\protect \endinput
diff --git a/tex/context/base/mkiv/catc-ini.mkiv b/tex/context/base/mkiv/catc-ini.mkiv
index 471e4d1c8..215ec14e1 100644
--- a/tex/context/base/mkiv/catc-ini.mkiv
+++ b/tex/context/base/mkiv/catc-ini.mkiv
@@ -23,58 +23,110 @@
%D \MKII\ file. There is some overlap in code with \MKII\ but we take that
%D for granted. Also, in \MKIV\ less active characters are used.
-\setnewconstant\escapecatcode 0
-\setnewconstant\begingroupcatcode 1
-\setnewconstant\endgroupcatcode 2
-\setnewconstant\mathshiftcatcode 3
-\setnewconstant\alignmentcatcode 4
-\setnewconstant\endoflinecatcode 5
-\setnewconstant\parametercatcode 6
-\setnewconstant\superscriptcatcode 7
-\setnewconstant\subscriptcatcode 8
-\setnewconstant\ignorecatcode 9
-\setnewconstant\spacecatcode 10
-\setnewconstant\lettercatcode 11
-\setnewconstant\othercatcode 12 % finally obsolete: \let\other \othercatcode
-\setnewconstant\activecatcode 13 % finally obsolete: \let\active\activecatcode
-\setnewconstant\commentcatcode 14
-\setnewconstant\invalidcatcode 15
-
-\setnewconstant\tabasciicode 9
-\setnewconstant\newlineasciicode 10 % don't confuse this one with \endoflineasciicode
-\setnewconstant\formfeedasciicode 12
-\setnewconstant\endoflineasciicode 13 % somewhat messy but this can be the active \par
-\setnewconstant\endoffileasciicode 26
-\setnewconstant\spaceasciicode 32
-\setnewconstant\exclamationmarkasciicode 33 % ! used in namespace protection
-\setnewconstant\doublequoteasciicode 34 % "
-\setnewconstant\hashasciicode 35
-\setnewconstant\dollarasciicode 36
-\setnewconstant\commentasciicode 37
-\setnewconstant\ampersandasciicode 38
-\setnewconstant\singlequoteasciicode 39 % '
-\setnewconstant\primeasciicode 39 % '
-\setnewconstant\hyphenasciicode 45
-\setnewconstant\forwardslashasciicode 47 % /
-\setnewconstant\colonasciicode 58
-\setnewconstant\lessthanasciicode 60 % < used as alternative verbatim {
-\setnewconstant\morethanasciicode 62 % > used as alternative verbatim }
-\setnewconstant\questionmarkasciicode 63 % ? used in namespace protection
-\setnewconstant\atsignasciicode 64 % @ used in namespace protection
-\setnewconstant\backslashasciicode 92 % `\\
-\setnewconstant\circumflexasciicode 94
-\setnewconstant\underscoreasciicode 95
-\setnewconstant\leftbraceasciicode 123 % `\{
-\setnewconstant\barasciicode 124 % `\|
-\setnewconstant\rightbraceasciicode 125 % `\}
-\setnewconstant\tildeasciicode 126 % `\~
-\setnewconstant\delasciicode 127
+% \normalprotected\def\setnewconstantfromchar#1%
+% {\expandafter\ifdefined\expandafter#1\expandafter
+% \let\expandafter#1\expandafter\undefined\expandafter\fi\expandafter
+% \newcount\expandafter#1\expandafter#1\the#1\relax}
+%
+% \normalprotected\def\setnewconstantfromchar#1%
+% {\begingroup
+% \scratchcounter#1%
+% \edef\!!stringa{\meaning#1}%
+% \chardef#1\scratchcounter
+% \edef\!!stringb{\meaning#1}%
+% \normalexpanded{\endgroup
+% \ifx\!!stringa\!!stringb
+% \let#1\noexpand\undefined
+% \newcount#1%
+% \fi
+% #1\the\scratchcounter\relax}}
+%
+% \normalprotected\def\setnewconstantfromchar#1%
+% {\begingroup
+% \edef\!!stringa{\meaning#1}%
+% \expandafter\chardef\expandafter#1\the#1%
+% \edef\!!stringb{\meaning#1}%
+% \normalexpanded{\endgroup
+% \ifx\!!stringa\!!stringb
+% \let#1\noexpand\undefined
+% \newcount#1%
+% \fi
+% #1\the#1\relax}}
+%
+% \normalprotected\def\setnewconstantfromchar#1%
+% {\scratchcounter#1\let#1\undefined\newcount#1#1\scratchcounter}
+
+\def\promote#1{\scratchcounter#1\let#1\undefined\newcount#1#1\scratchcounter}
+
+\promote\escapecatcode
+\promote\begingroupcatcode
+\promote\endgroupcatcode
+\promote\mathshiftcatcode
+\promote\alignmentcatcode
+\promote\endoflinecatcode
+\promote\parametercatcode
+\promote\superscriptcatcode
+\promote\subscriptcatcode
+\promote\ignorecatcode
+\promote\spacecatcode
+\promote\lettercatcode
+\promote\othercatcode
+\promote\activecatcode
+\promote\commentcatcode
+\promote\invalidcatcode
+
+\promote\tabasciicode
+\promote\newlineasciicode
+\promote\formfeedasciicode
+\promote\endoflineasciicode
+\promote\endoffileasciicode
+\promote\spaceasciicode
+\promote\exclamationmarkasciicode
+\promote\doublequoteasciicode
+\promote\hashasciicode
+\promote\dollarasciicode
+\promote\commentasciicode
+\promote\ampersandasciicode
+\promote\singlequoteasciicode
+\promote\primeasciicode
+\promote\hyphenasciicode
+\promote\forwardslashasciicode
+\promote\colonasciicode
+\promote\lessthanasciicode
+\promote\morethanasciicode
+\promote\questionmarkasciicode
+\promote\atsignasciicode
+\promote\backslashasciicode
+\promote\circumflexasciicode
+\promote\underscoreasciicode
+\promote\leftbraceasciicode
+\promote\barasciicode
+\promote\rightbraceasciicode
+\promote\tildeasciicode
+\promote\delasciicode
+
+\let\promote\undefined
+
+% \begingroup
+%
+% \catcode\tabasciicode \activecatcode
+% \catcode\formfeedasciicode \activecatcode
+% \catcode\endoflineasciicode\activecatcode
+%
+% \letcharcode\tabasciicode \relax
+% \letcharcode\newlineasciicode \relax
+% \letcharcode\formfeedasciicode \relax
+% \letcharcode\endoflineasciicode\relax
+%
+% \xdef\activetabtoken {\Uchar\tabasciicode } % \gdef\activetabtoken {^^I}
+% \xdef\outputnewlinechar {\Uchar\newlineasciicode } % \gdef\outputnewlinechar {^^J}
+% \xdef\activeformfeedtoken {\Uchar\formfeedasciicode } % \gdef\activeformfeedtoken {^^L}
+% \xdef\activeendoflinetoken{\Uchar\endoflineasciicode} % \gdef\activeendoflinetoken{^^M}
+%
+% \endgroup
\begingroup
- \catcode \tabasciicode \activecatcode \gdef\activetabtoken {^^I}
- \gdef\outputnewlinechar {^^J}
- \catcode \formfeedasciicode \activecatcode \gdef\activeformfeedtoken {^^L}
- \catcode \endoflineasciicode \activecatcode \gdef\activeendoflinetoken{^^M}
+ \letcharcode\newlineasciicode\relax \xdef\outputnewlinechar{\Uchar\newlineasciicode}
\endgroup
% \endlinechar = \endoflineasciicode % appended to input lines
@@ -82,10 +134,17 @@
% rather special and used in writing to file: \let\par\outputnewlinechar
+% \normalprotected\def\initializenewlinechar % operating system dependent
+% {\begingroup
+% \newlinechar\newlineasciicode
+% \xdef\outputnewlinechar{^^J}%
+% \endgroup}
+
\normalprotected\def\initializenewlinechar % operating system dependent
{\begingroup
+ \letcharcode\newlineasciicode\relax
\newlinechar\newlineasciicode
- \xdef\outputnewlinechar{^^J}%
+ \xdef\outputnewlinechar{\Uchar\newlineasciicode}%
\endgroup}
%D We predefine some prefixes ahead of syst-aux and mult-sys.
diff --git a/tex/context/base/mkiv/char-act.mkiv b/tex/context/base/mkiv/char-act.mkiv
index 7d7268c8b..6b2ca51e2 100644
--- a/tex/context/base/mkiv/char-act.mkiv
+++ b/tex/context/base/mkiv/char-act.mkiv
@@ -44,11 +44,14 @@
\unexpanded\def\controlspace{\hbox{\asciispacechar}} % rather tex, we need the unicode value
\unexpanded\def\normalspaces{\catcode\spaceasciicode\spacecatcode}
-\bgroup
- \catcode\spaceasciicode\activecatcode
- \unexpanded\gdef\obeyspaces{\catcode\spaceasciicode\activecatcode\def {\obeyedspace}}
- \unexpanded\gdef\setcontrolspaces{\catcode\spaceasciicode\activecatcode\def {\controlspace}}
-\egroup
+% \bgroup
+% \catcode\spaceasciicode\activecatcode
+% \unexpanded\gdef\obeyspaces {\catcode\spaceasciicode\activecatcode\def {\obeyedspace }}
+% \unexpanded\gdef\setcontrolspaces{\catcode\spaceasciicode\activecatcode\def {\controlspace}}
+% \egroup
+
+\unexpanded\def\obeyspaces {\catcode\spaceasciicode\activecatcode\letcharcode\spaceasciicode\obeyedspace }
+\unexpanded\def\setcontrolspaces{\catcode\spaceasciicode\activecatcode\letcharcode\spaceasciicode\controlspace}
%D \macros
%D {obeytabs, obeylines, obeypages,ignoretabs, ignorelines, ignorepages}
@@ -59,17 +62,28 @@
%D \NEWPAGE\ character locally, we redefine the meaning of
%D this (often already) active character.
-\expandafter\def\activeformfeedtoken{\par}
+% \expandafter\def\activeformfeedtoken{\par}
+
+\letcharcode\formfeedasciicode\par
%D The following indirect definitions enable us to implement
%D all kind of \type{\obeyed} handlers.
-\unexpanded\def\obeytabs {\catcode\tabasciicode \activecatcode\expandafter\def\activetabtoken {\obeyedtab }}
-\unexpanded\def\obeylines {\catcode\endoflineasciicode\activecatcode\expandafter\def\activeendoflinetoken{\obeyedline}}
-\unexpanded\def\obeypages {\catcode\formfeedasciicode \activecatcode\expandafter\def\activeformfeedtoken {\obeyedpage}}
+% \unexpanded\def\obeytabs {\catcode\tabasciicode \activecatcode\expandafter\def\activetabtoken {\obeyedtab }}
+% \unexpanded\def\obeylines {\catcode\endoflineasciicode\activecatcode\expandafter\def\activeendoflinetoken{\obeyedline}}
+% \unexpanded\def\obeypages {\catcode\formfeedasciicode \activecatcode\expandafter\def\activeformfeedtoken {\obeyedpage}}
+
+% \unexpanded\def\ignoretabs {\catcode\tabasciicode \activecatcode\expandafter\def\activetabtoken {\obeyedspace}}
+% \unexpanded\def\ignorelines{\catcode\endoflineasciicode\activecatcode\expandafter\def\activeendoflinetoken{\obeyedspace}}
+% \unexpanded\def\ignorepages{\catcode\formfeedasciicode \ignorecatcode}
+% \unexpanded\def\ignoreeofs {\catcode\endoffileasciicode\ignorecatcode}
+
+\unexpanded\def\obeytabs {\catcode\tabasciicode \activecatcode\letcharcode\tabasciicode \obeyedtab }
+\unexpanded\def\obeylines {\catcode\endoflineasciicode\activecatcode\letcharcode\endoflineasciicode\obeyedline}
+\unexpanded\def\obeypages {\catcode\formfeedasciicode \activecatcode\letcharcode\formfeedasciicode \obeyedpage}
-\unexpanded\def\ignoretabs {\catcode\tabasciicode \activecatcode\expandafter\def\activetabtoken {\obeyedspace}}
-\unexpanded\def\ignorelines{\catcode\endoflineasciicode\activecatcode\expandafter\def\activeendoflinetoken{\obeyedspace}}
+\unexpanded\def\ignoretabs {\catcode\tabasciicode \activecatcode\letcharcode\tabasciicode \obeyedspace}
+\unexpanded\def\ignorelines{\catcode\endoflineasciicode\activecatcode\letcharcode\endoflineasciicode\obeyedspace}
\unexpanded\def\ignorepages{\catcode\formfeedasciicode \ignorecatcode}
\unexpanded\def\ignoreeofs {\catcode\endoffileasciicode\ignorecatcode}
diff --git a/tex/context/base/mkiv/cldf-ini.lua b/tex/context/base/mkiv/cldf-ini.lua
index 8cd6408d3..86dec0209 100644
--- a/tex/context/base/mkiv/cldf-ini.lua
+++ b/tex/context/base/mkiv/cldf-ini.lua
@@ -690,7 +690,7 @@ local function writer(parent,command,...) -- already optimized before call
-- for i=1,#t do
-- local ti = t[i]
for i=1,select("#",...) do
- local ti = (select(i,...))
+ local ti = select(i,...)
if direct then
local typ = type(ti)
if typ == "string" or typ == "number" then
@@ -798,7 +798,7 @@ end
-- local function prtwriter(command,...) -- already optimized before call
-- flush(prtcatcodes,command)
-- for i=1,select("#",...) do
--- local ti = (select(i,...))
+-- local ti = select(i,...)
-- if ti == nil then
-- -- nothing
-- elseif ti == "" then
@@ -1179,7 +1179,7 @@ do
-- snippets
for i=1,select("#",...) do
nofcollected = nofcollected + 1
- collected[nofcollected] = (select(i,...))
+ collected[nofcollected] = select(i,...)
end
end
@@ -1187,7 +1187,7 @@ do
-- -- lines
-- for i=1,select("#",...) do
-- n = n + 1
- -- t[n] = (select(i,...))
+ -- t[n] = select(i,...)
-- n = n + 1
-- t[n] = "\r"
-- end
diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv
index acb618a43..61c9a1493 100644
--- a/tex/context/base/mkiv/cont-new.mkiv
+++ b/tex/context/base/mkiv/cont-new.mkiv
@@ -11,7 +11,7 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\newcontextversion{2018.04.03 22:22}
+\newcontextversion{2018.04.13 14:53}
%D This file is loaded at runtime, thereby providing an excellent place for
%D hacks, patches, extensions and new features.
diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv
index 7795c5a17..00fd83ea8 100644
--- a/tex/context/base/mkiv/context.mkiv
+++ b/tex/context/base/mkiv/context.mkiv
@@ -42,7 +42,7 @@
%D has to match \type {YYYY.MM.DD HH:MM} format.
\edef\contextformat {\jobname}
-\edef\contextversion{2018.04.03 22:22}
+\edef\contextversion{2018.04.13 14:53}
\edef\contextkind {beta}
%D For those who want to use this:
@@ -568,8 +568,10 @@
\loadmarkfile{mlib-pdf}
\loadmarkfile{mlib-pps}
\loadmarkfile{meta-pdf}
+\loadmarkfile{meta-blb}
\loadmarkfile{grph-epd}
+
\loadmarkfile{cont-run} % the main runner (used in cont-yes.mkiv)
\setupcurrentlanguage[\defaultlanguagetag]
diff --git a/tex/context/base/mkiv/font-cft.lua b/tex/context/base/mkiv/font-cft.lua
index 83227ca4a..2e1610f17 100644
--- a/tex/context/base/mkiv/font-cft.lua
+++ b/tex/context/base/mkiv/font-cft.lua
@@ -248,6 +248,16 @@ do
mathitalics = t_boolean,
textitalics = t_boolean,
finalized = t_boolean,
+ effect = {
+ effect = t_cardinal,
+ width = t_float,
+ factor = t_float,
+ hfactor = t_float,
+ vfactor = t_float,
+ wdelta = t_float,
+ hdelta = t_float,
+ ddelta = t_float,
+ }
},
parameters = {
mathsize = t_cardinal,
diff --git a/tex/context/base/mkiv/font-chk.lua b/tex/context/base/mkiv/font-chk.lua
index 3613432c1..4e7bf939b 100644
--- a/tex/context/base/mkiv/font-chk.lua
+++ b/tex/context/base/mkiv/font-chk.lua
@@ -196,7 +196,10 @@ local variants = allocate {
{ tag = "yellow", r = .6, g = .6, b = 0 },
}
-local pdf_blob = "pdf: q %.6F 0 0 %.6F 0 0 cm %s %s %s rg %s %s %s RG 10 M 1 j 1 J 0.05 w %s Q"
+-- bah .. low level pdf ... should be a rule or plugged in
+
+----- pdf_blob = "pdf: q %.6F 0 0 %.6F 0 0 cm %s %s %s rg %s %s %s RG 10 M 1 j 1 J 0.05 w %s Q"
+local pdf_blob = "q %.6F 0 0 %.6F 0 0 cm %s %s %s rg %s %s %s RG 10 M 1 j 1 J 0.05 w %s Q"
local cache = { } -- saves some tables but not that impressive
@@ -235,8 +238,8 @@ local function addmissingsymbols(tfmdata) -- we can have an alternative with rul
width = size*fake.width,
height = size*fake.height,
depth = size*fake.depth,
- -- bah .. low level pdf ... should be a rule or plugged in
- commands = { { "special", formatters[pdf_blob](scale,scale,r,g,b,r,g,b,fake.code) } }
+ -- commands = { { "special", formatters[pdf_blob](scale,scale,r,g,b,r,g,b,fake.code) } }
+ commands = { { "pdf", formatters[pdf_blob](scale,scale,r,g,b,r,g,b,fake.code) } }
}
cache[hash] = char
end
@@ -390,7 +393,6 @@ checkers.getmissing = getmissing
do
local reported = true
- local tracked = false
callback.register("glyph_not_found",function(font,char)
if font > 0 then
@@ -408,7 +410,6 @@ do
trackers.register("fonts.missing", function(v)
if v then
enableaction("processors","fonts.checkers.missing")
- tracked = true
else
disableaction("processors","fonts.checkers.missing")
end
@@ -419,27 +420,25 @@ do
end)
logs.registerfinalactions(function()
--- if tracked then
- local collected, details = getmissing()
- if next(collected) then
+ local collected, details = getmissing()
+ if next(collected) then
+ for filename, list in sortedhash(details) do
+ logs.startfilelogging(report,"missing characters",filename)
+ for u, v in sortedhash(list) do
+ report("%4i %U %c %s",v,u,u,chardata[u].description)
+ end
+ logs.stopfilelogging()
+ end
+ if logs.loggingerrors() then
for filename, list in sortedhash(details) do
- logs.startfilelogging(report,"missing characters",filename)
+ logs.starterrorlogging(report,"missing characters",filename)
for u, v in sortedhash(list) do
report("%4i %U %c %s",v,u,u,chardata[u].description)
end
- logs.stopfilelogging()
- end
- if logs.loggingerrors() then
- for filename, list in sortedhash(details) do
- logs.starterrorlogging(report,"missing characters",filename)
- for u, v in sortedhash(list) do
- report("%4i %U %c %s",v,u,u,chardata[u].description)
- end
- logs.stoperrorlogging()
- end
+ logs.stoperrorlogging()
end
end
--- end
+ end
end)
end
diff --git a/tex/context/base/mkiv/font-col.lua b/tex/context/base/mkiv/font-col.lua
index 7bbaf31cb..8aad4d7d5 100644
--- a/tex/context/base/mkiv/font-col.lua
+++ b/tex/context/base/mkiv/font-col.lua
@@ -47,22 +47,22 @@ collections.definitions = definitions
local vectors = collections.vectors or { }
collections.vectors = vectors
-local fonthashes = fonts.hashes
-local fonthelpers = fonts.helpers
-
-local fontdata = fonthashes.identifiers
-local fontquads = fonthashes.quads
-local chardata = fonthashes.characters
-local propdata = fonthashes.properties
-
-local addprivate = fonthelpers.addprivate
-local hasprivate = fonthelpers.hasprivate
+local helpers = fonts.helpers
+local charcommand = helpers.commands.char
+local rightcommand = helpers.commands.right
+local addprivate = helpers.addprivate
+local hasprivate = helpers.hasprivate
+local fontpatternhassize = helpers.fontpatternhassize
+
+local hashes = fonts.hashes
+local fontdata = hashes.identifiers
+local fontquads = hashes.quads
+local chardata = hashes.characters
+local propdata = hashes.properties
local currentfont = font.current
local addcharacters = font.addcharacters
-local fontpatternhassize = fonts.helpers.fontpatternhassize
-
local implement = interfaces.implement
local list = { }
@@ -284,13 +284,16 @@ local function monoslot(font,char,parent,factor)
local width = factor * fontquads[parent]
local character = characters[char]
if character then
+ -- runtime patching of the font (can only be new characters)
+ -- instead of messing with existing dimensions
local data = {
+ -- no features so a simple copy
width = width,
height = character.height,
depth = character.depth,
commands = {
- { "right", (width - character.width or 0)/2 },
- { "slot", 0, char }
+ rightcommand[(width - character.width or 0)/2],
+ charcommand[char],
}
}
local u = addprivate(tfmdata, privatename, data)
diff --git a/tex/context/base/mkiv/font-con.lua b/tex/context/base/mkiv/font-con.lua
index add646da1..73e9ffe22 100644
--- a/tex/context/base/mkiv/font-con.lua
+++ b/tex/context/base/mkiv/font-con.lua
@@ -98,6 +98,24 @@ function constructors.getprivate(tfmdata)
return private
end
+function constructors.setmathparameter(tfmdata,name,value)
+ local m = tfmdata.mathparameters
+ local c = tfmdata.MathConstants
+ if m then
+ m[name] = value
+ end
+ if c and c ~= m then
+ c[name] = value
+ end
+end
+
+function constructors.getmathparameter(tfmdata,name)
+ local p = tfmdata.mathparameters or tfmdata.MathConstants
+ if p then
+ return p[name]
+ end
+end
+
--[[ldx--
<p>Beware, the boundingbox is passed as reference so we may not overwrite it
in the process; numbers are of course copies. Here 65536 equals 1pt. (Due to
@@ -477,20 +495,28 @@ function constructors.scale(tfmdata,specification)
target.shrink = expansion.shrink
target.step = expansion.step
end
+ -- slanting
+ local slantfactor = parameters.slantfactor or 0
+ if slantfactor ~= 0 then
+ target.slant = slantfactor * 1000
+ else
+ target.slant = 0
+ end
-- widening
local extendfactor = parameters.extendfactor or 0
if extendfactor ~= 0 and extendfactor ~= 1 then
hdelta = hdelta * extendfactor
- target.extend = extendfactor * 1000 -- extent ?
+ target.extend = extendfactor * 1000
else
target.extend = 1000 -- extent ?
end
- -- slanting
- local slantfactor = parameters.slantfactor or 0
- if slantfactor ~= 0 then
- target.slant = slantfactor * 1000
+ -- squeezing
+ local squeezefactor = parameters.squeezefactor or 0
+ if squeezefactor ~= 0 and squeezefactor ~= 1 then
+ vdelta = vdelta * squeezefactor
+ target.squeeze = squeezefactor * 1000
else
- target.slant = 0
+ target.squeeze = 1000 -- extent ?
end
-- effects
local mode = parameters.mode or 0
@@ -499,7 +525,7 @@ function constructors.scale(tfmdata,specification)
end
local width = parameters.width or 0
if width ~= 0 then
- target.width = width
+ target.width = width * delta * 1000 / 655360
end
--
targetparameters.factor = delta
@@ -947,12 +973,16 @@ function constructors.finalize(tfmdata)
parameters.width = 0
end
--
+ if not parameters.slantfactor then
+ parameters.slantfactor = tfmdata.slant or 0
+ end
+ --
if not parameters.extendfactor then
parameters.extendfactor = tfmdata.extend or 0
end
--
- if not parameters.slantfactor then
- parameters.slantfactor = tfmdata.slant or 0
+ if not parameters.squeezefactor then
+ parameters.squeezefactor = tfmdata.squeeze or 0
end
--
local designsize = parameters.designsize
@@ -1043,8 +1073,9 @@ function constructors.finalize(tfmdata)
tfmdata.stretch = nil
tfmdata.shrink = nil
tfmdata.step = nil
- tfmdata.extend = nil
tfmdata.slant = nil
+ tfmdata.extend = nil
+ tfmdata.squeeze = nil
tfmdata.mode = nil
tfmdata.width = nil
tfmdata.units = nil
@@ -1097,7 +1128,18 @@ hashmethods.normal = function(list)
-- no need to add to hash (maybe we need a skip list)
else
n = n + 1
- s[n] = k .. '=' .. tostring(v)
+ if type(v) == "table" then
+ -- table.sequenced
+ local t = { }
+ local m = 0
+ for k, v in next, v do
+ m = m + 1
+ t[m] = k .. '=' .. tostring(v)
+ end
+ s[n] = k .. '={' .. concat(t,",") .. "}"
+ else
+ s[n] = k .. '=' .. tostring(v)
+ end
end
end
if n > 0 then
diff --git a/tex/context/base/mkiv/font-ctx.lua b/tex/context/base/mkiv/font-ctx.lua
index 87885f64f..68191143b 100644
--- a/tex/context/base/mkiv/font-ctx.lua
+++ b/tex/context/base/mkiv/font-ctx.lua
@@ -12,21 +12,23 @@ if not modules then modules = { } end modules ['font-ctx'] = {
-- Todo: make a proper 'next id' mechanism (register etc) or wait till 'true'
-- in virtual fonts indices is implemented.
-local context, commands = context, commands
+local tostring, next, type, rawget, tonumber = tostring, next, type, rawget, tonumber
local format, gmatch, match, find, lower, upper, gsub, byte, topattern = string.format, string.gmatch, string.match, string.find, string.lower, string.upper, string.gsub, string.byte, string.topattern
local concat, serialize, sort, fastcopy, mergedtable = table.concat, table.serialize, table.sort, table.fastcopy, table.merged
local sortedhash, sortedkeys, sequenced = table.sortedhash, table.sortedkeys, table.sequenced
-local settings_to_hash, hash_to_string, settings_to_array = utilities.parsers.settings_to_hash, utilities.parsers.hash_to_string, utilities.parsers.settings_to_array
+local parsers = utilities.parsers
+local settings_to_hash, settings_to_hash_colon_too, hash_to_string, settings_to_array = parsers.settings_to_hash, parsers.settings_to_hash_colon_too, parsers.hash_to_string, parsers.settings_to_array
local formatcolumns = utilities.formatters.formatcolumns
local mergehashes = utilities.parsers.mergehashes
local formatters = string.formatters
local basename = file.basename
-local tostring, next, type, rawget, tonumber = tostring, next, type, rawget, tonumber
local utfchar, utfbyte = utf.char, utf.byte
local round = math.round
+local context, commands = context, commands
+
local P, S, C, Cc, Cf, Cg, Ct, lpegmatch = lpeg.P, lpeg.S, lpeg.C, lpeg.Cc, lpeg.Cf, lpeg.Cg, lpeg.Ct, lpeg.match
local trace_features = false trackers.register("fonts.features", function(v) trace_features = v end)
@@ -66,6 +68,8 @@ local hashes = fonts.hashes
local currentfont = font.current
local definefont = font.define
+local getprivateslot = helpers.getprivateslot
+
local cleanname = names.cleanname
local encodings = fonts.encodings
@@ -472,36 +476,40 @@ registerotffeature {
-- },
-- }
-local beforecopyingcharacters = sequencers.new {
- name = "beforecopyingcharacters",
- arguments = "target,original",
-}
+do
+
+ local beforecopyingcharacters = sequencers.new {
+ name = "beforecopyingcharacters",
+ arguments = "target,original",
+ }
-appendgroup(beforecopyingcharacters,"before") -- user
-appendgroup(beforecopyingcharacters,"system") -- private
-appendgroup(beforecopyingcharacters,"after" ) -- user
+ appendgroup(beforecopyingcharacters,"before") -- user
+ appendgroup(beforecopyingcharacters,"system") -- private
+ appendgroup(beforecopyingcharacters,"after" ) -- user
-function constructors.beforecopyingcharacters(original,target)
- local runner = beforecopyingcharacters.runner
- if runner then
- runner(original,target)
+ function constructors.beforecopyingcharacters(original,target)
+ local runner = beforecopyingcharacters.runner
+ if runner then
+ runner(original,target)
+ end
end
-end
-local aftercopyingcharacters = sequencers.new {
- name = "aftercopyingcharacters",
- arguments = "target,original",
-}
+ local aftercopyingcharacters = sequencers.new {
+ name = "aftercopyingcharacters",
+ arguments = "target,original",
+ }
-appendgroup(aftercopyingcharacters,"before") -- user
-appendgroup(aftercopyingcharacters,"system") -- private
-appendgroup(aftercopyingcharacters,"after" ) -- user
+ appendgroup(aftercopyingcharacters,"before") -- user
+ appendgroup(aftercopyingcharacters,"system") -- private
+ appendgroup(aftercopyingcharacters,"after" ) -- user
-function constructors.aftercopyingcharacters(original,target)
- local runner = aftercopyingcharacters.runner
- if runner then
- runner(original,target)
+ function constructors.aftercopyingcharacters(original,target)
+ local runner = aftercopyingcharacters.runner
+ if runner then
+ runner(original,target)
+ end
end
+
end
--[[ldx--
@@ -575,6 +583,15 @@ local function presetcontext(name,parent,features) -- will go to con and shared
features = { }
elseif type(features) == "string" then
features = normalize_features(settings_to_hash(features))
+ for key, value in next, features do
+ if type(value) == "string" and find(value,"=") then
+ local t = settings_to_hash(value)
+ if next(t) then
+-- features[key] = sequenced(normalize_features(t),",")
+ features[key] = t -- sequenced(normalize_features(t),",")
+ end
+ end
+ end
else
features = normalize_features(features)
end
@@ -584,8 +601,8 @@ local function presetcontext(name,parent,features) -- will go to con and shared
local s = setups[p]
if s then
for k, v in next, s do
--- no, as then we cannot overload: e.g. math,mathextra
--- reverted, so we only take from parent when not set
+ -- no, as then we cannot overload: e.g. math,mathextra
+ -- reverted, so we only take from parent when not set
if features[k] == nil then
features[k] = v
end
@@ -1299,7 +1316,6 @@ do -- else too many locals
local busy = false
scanners.definefont_two = function()
-
local global = scanboolean() -- \ifx\fontclass\empty\s!false\else\s!true\fi
local cs = scanstring () -- {#csname}%
local str = scanstring () -- \somefontfile
@@ -1411,6 +1427,7 @@ do -- else too many locals
specification.fallbacks = fontfallbacks
end
end
+ --
local tfmdata = definers.read(specification,size) -- id not yet known (size in spec?)
--
local lastfontid = 0
@@ -2397,9 +2414,12 @@ do
return f and (f.gpos[n] or f.gsub[n])
end
+ local ctx_doifelse = commands.doifelse
+ local ctx_doif = commands.doif
+
implement {
name = "doifelsecurrentfonthasfeature",
- actions = { constructors.currentfonthasfeature, commands.doifelse },
+ actions = { constructors.currentfonthasfeature, ctx_doifelse },
arguments = "string"
}
@@ -2443,10 +2463,23 @@ do
implement {
name = "definefontfeature",
arguments = "3 strings",
- actions = presetcontext
+ actions = presetcontext,
+ }
+
+ implement {
+ name = "doifelsefontfeature",
+ arguments = "string",
+ actions = function(name) ctx_doifelse(contextnumber(name) > 1) end,
}
implement {
+ name = "doifunknownfontfeature",
+ arguments = "string",
+ actions = function(name) ctx_doif(contextnumber(name) == 0) end,
+ }
+
+
+ implement {
name = "adaptfontfeature",
arguments = "2 strings",
actions = adaptcontext
@@ -2708,9 +2741,13 @@ implement {
arguments = "string",
}
-local list = storage.shared.bodyfontsizes or { }
+local sharedstorage = storage.shared
+
+local list = sharedstorage.bodyfontsizes or { }
+local unknown = sharedstorage.unknownbodyfontsizes or { }
-storage.shared.bodyfontsizes = list
+sharedstorage.bodyfontsizes = list
+sharedstorage.unknownbodyfontsizes = unknown
implement {
name = "registerbodyfontsize",
@@ -2720,6 +2757,17 @@ implement {
end
}
+interfaces.implement {
+ name = "registerunknownbodysize",
+ arguments = "string",
+ actions = function(size)
+ if not unknown[size] then
+ interfaces.showmessage("fonts",14,size)
+ end
+ unknown[size] = true
+ end,
+}
+
implement {
name = "getbodyfontsizes",
arguments = "string",
@@ -2873,6 +2921,12 @@ end
-- for the font manual
+statistics.register("body font sizes", function()
+ if next(unknown) then
+ return formatters["defined: % t, undefined: % t"](sortedkeys(list),sortedkeys(unknown))
+ end
+end)
+
statistics.register("used fonts",function()
if trace_usage then
local filename = file.nameonly(environment.jobname) .. "-fonts-usage.lua"
@@ -3018,79 +3072,178 @@ end
-- for the moment here (and not in font-con.lua):
-local identical = table.identical
-local copy = table.copy
-local fontdata = fonts.hashes.identifiers
-local addcharacters = font.addcharacters
-
--- This helper is mostly meant to add last-resort (virtual) characters
--- or runtime generated fonts (so we forget about features and such). It
--- will probably take a while before it get used.
-
-local trace_adding = false
-local report_adding = logs.reporter("fonts","add characters")
-
-trackers.register("fonts.addcharacters",function(v) trace_adding = v end)
-
-if addcharacters then
-
- function fonts.constructors.addcharacters(id,list)
- local newchar = list.characters
- if newchar then
- local data = fontdata[id]
- local newfont = list.fonts
- local oldchar = data.characters
- local oldfont = data.fonts
- addcharacters(id, {
- characters = newchar,
- fonts = newfont,
- nomath = not data.properties.hasmath,
- })
- -- this is just for tracing, as the assignment only uses the fonts list
- -- and doesn't store it otherwise
- if newfont then
- if oldfont then
- local oldn = #oldfont
- local newn = #newfont
- for n=1,newn do
- local ok = false
- local nf = newfont[n]
- for o=1,oldn do
- if identical(nf,oldfont[o]) then
- ok = true
- break
+do
+
+ local identical = table.identical
+ local copy = table.copy
+ local fontdata = fonts.hashes.identifiers
+ local addcharacters = font.addcharacters
+
+ -- This helper is mostly meant to add last-resort (virtual) characters
+ -- or runtime generated fonts (so we forget about features and such). It
+ -- will probably take a while before it get used.
+
+ local trace_adding = false
+ local report_adding = logs.reporter("fonts","add characters")
+
+ trackers.register("fonts.addcharacters",function(v) trace_adding = v end)
+
+ if addcharacters then
+
+ function fonts.constructors.addcharacters(id,list)
+ local newchar = list.characters
+ if newchar then
+ local data = fontdata[id]
+ local newfont = list.fonts
+ local oldchar = data.characters
+ local oldfont = data.fonts
+ addcharacters(id, {
+ characters = newchar,
+ fonts = newfont,
+ nomath = not data.properties.hasmath,
+ })
+ -- this is just for tracing, as the assignment only uses the fonts list
+ -- and doesn't store it otherwise
+ if newfont then
+ if oldfont then
+ local oldn = #oldfont
+ local newn = #newfont
+ for n=1,newn do
+ local ok = false
+ local nf = newfont[n]
+ for o=1,oldn do
+ if identical(nf,oldfont[o]) then
+ ok = true
+ break
+ end
+ end
+ if not ok then
+ oldn = oldn + 1
+ oldfont[oldn] = newfont[i]
end
end
- if not ok then
- oldn = oldn + 1
- oldfont[oldn] = newfont[i]
- end
+ else
+ data.fonts = newfont
end
- else
- data.fonts = newfont
end
- end
- -- this is because we need to know what goes on and also might
- -- want to access character data
- for u, c in next, newchar do
- if trace_adding then
- report_adding("adding character %U to font %!font:name!",u,id)
+ -- this is because we need to know what goes on and also might
+ -- want to access character data
+ for u, c in next, newchar do
+ if trace_adding then
+ report_adding("adding character %U to font %!font:name!",u,id)
+ end
+ oldchar[u] = c
end
- oldchar[u] = c
end
end
- end
-else
- function fonts.constructors.addcharacters(id,list)
- report_adding("adding characters to %!font:name! is not yet supported",id)
+ else
+ function fonts.constructors.addcharacters(id,list)
+ report_adding("adding characters to %!font:name! is not yet supported",id)
+ end
end
+
+ implement {
+ name = "addfontpath",
+ arguments = "string",
+ actions = function(list)
+ names.addruntimepath(settings_to_array(list))
+ end
+ }
+
end
-implement {
- name = "addfontpath",
- arguments = "string",
- actions = function(list)
- names.addruntimepath(settings_to_array(list))
+-- moved here
+
+do
+
+ local family_font = node.family_font
+ local new_glyph = nodes.pool.glyph
+ local fontproperties = fonts.hashes.properties
+
+ local function getprivateslot(id,name)
+ if not name then
+ name = id
+ id = currentfont()
+ end
+ local properties = fontproperties[id]
+ local privates = properties and properties.privates
+ return privates and privates[name]
end
-}
+
+ local function getprivatenode(tfmdata,name)
+ if type(tfmdata) == "number" then
+ tfmdata = fontdata[tfmdata]
+ end
+ local properties = tfmdata.properties
+ local font = properties.id
+ local slot = getprivateslot(font,name)
+ if slot then
+ -- todo: set current attribibutes
+ local char = tfmdata.characters[slot]
+ local tonode = char.tonode
+ if tonode then
+ return tonode(font,char)
+ else
+ return new_glyph(font,slot)
+ end
+ end
+ end
+
+ local function getprivatecharornode(tfmdata,name)
+ if type(tfmdata) == "number" then
+ tfmdata = fontdata[tfmdata]
+ end
+ local properties = tfmdata.properties
+ local font = properties.id
+ local slot = getprivateslot(font,name)
+ if slot then
+ -- todo: set current attributes
+ local char = tfmdata.characters[slot]
+ local tonode = char.tonode
+ if tonode then
+ return "node", tonode(tfmdata,char)
+ else
+ return "char", slot
+ end
+ end
+ end
+
+ helpers.getprivateslot = getprivateslot
+ helpers.getprivatenode = getprivatenode
+ helpers.getprivatecharornode = getprivatecharornode
+
+ implement {
+ name = "getprivatechar",
+ arguments = "string",
+ actions = function(name)
+ local p = getprivateslot(name)
+ if p then
+ context(utfchar(p))
+ end
+ end
+ }
+
+ implement {
+ name = "getprivatemathchar",
+ arguments = "string",
+ actions = function(name)
+ local p = getprivateslot(family_font(0),name)
+ if p then
+ context(utfchar(p))
+ end
+ end
+ }
+
+ implement {
+ name = "getprivateslot",
+ arguments = "string",
+ actions = function(name)
+ local p = getprivateslot(name)
+ if p then
+ context(p)
+ end
+ end
+ }
+
+end
diff --git a/tex/context/base/mkiv/font-def.lua b/tex/context/base/mkiv/font-def.lua
index 97d25f180..732ce401f 100644
--- a/tex/context/base/mkiv/font-def.lua
+++ b/tex/context/base/mkiv/font-def.lua
@@ -377,6 +377,7 @@ function definers.loadfont(specification)
-- todo: also hash by instance / factors
local tfmdata = loadedfonts[hash] -- hashes by size !
if not tfmdata then
+ -- normally context will not end up here often (if so there is an issue somewhere)
local forced = specification.forced or ""
if forced ~= "" then
local reader = readers[lower(forced)] -- normally forced is already lowered
diff --git a/tex/context/base/mkiv/font-dsp.lua b/tex/context/base/mkiv/font-dsp.lua
index 02e5a7df6..77b2b7ff0 100644
--- a/tex/context/base/mkiv/font-dsp.lua
+++ b/tex/context/base/mkiv/font-dsp.lua
@@ -68,7 +68,7 @@ local reversed = table.reversed
local sort = table.sort
local insert = table.insert
local round = math.round
-local lpegmatch = lpeg.match
+local settings_to_hash_colon_too = table.settings_to_hash_colon_too
local setmetatableindex = table.setmetatableindex
local formatters = string.formatters
@@ -300,30 +300,16 @@ end)
-- wght:400,wdth:100,ital:1
--- local names = table.setmetatableindex ( {
--- weight = "wght",
--- width = "wdth",
--- italic = "ital",
--- }, "self")
-
--- todo: spaces in name but not before :
-
-local pattern = lpeg.Cf (
- lpeg.Ct("") *
- lpeg.Cg (
- --(lpeg.R("az")^1/names) * lpeg.S(" :") *
- lpeg.C((lpeg.R("az","09")+lpeg.P(" "))^1) * lpeg.S(" :=") *
- (lpeg.patterns.number/tonumber) * lpeg.S(" ,")^0
- )^1, rawset
-)
+local function axistofactors(str)
+ local t = settings_to_hash_colon_too(str)
+ for k, v in next, t do
+ t[k] = tonumber(v) or v -- this also normalizes numbers itself
+ end
+ return t
+end
local hash = table.setmetatableindex(function(t,k)
- local v = lpegmatch(pattern,k)
- local t = { }
- for k, v in sortedhash(v) do
- t[#t+1] = k .. "=" .. v
- end
- v = concat(t,",")
+ local v = sequenced(axistofactors(k),",")
t[k] = v
return v
end)
@@ -341,7 +327,7 @@ function helpers.normalizedaxis(str)
end
local function axistofactors(str)
- return lpegmatch(pattern,str)
+ return settings_to_hash_colon_too(str)
end
-- contradicting spec ... (signs) so i'll check it and fix it once we have
diff --git a/tex/context/base/mkiv/font-enh.lua b/tex/context/base/mkiv/font-enh.lua
index b1fcd9be8..9ec116d47 100644
--- a/tex/context/base/mkiv/font-enh.lua
+++ b/tex/context/base/mkiv/font-enh.lua
@@ -115,7 +115,7 @@ local registerotffeature = otffeatures.register
----- tosixteen = fonts.mappings.tounicode16
-local function initializeunicoding(tfmdata)
+local function initialize(tfmdata)
local goodies = tfmdata.goodies
local newcoding = nil
for i=1,#goodies do
@@ -165,18 +165,14 @@ local function initializeunicoding(tfmdata)
end
end
-local unicoding_specification = {
+local specification = {
name = "unicoding",
description = "adapt unicode table",
initializers = {
- base = initializeunicoding,
- node = initializeunicoding,
+ base = initialize,
+ node = initialize,
},
- -- manipulators = {
- -- base = finalizeunicoding,
- -- node = finalizeunicoding,
- -- }
}
-registerotffeature(unicoding_specification)
-registerafmfeature(unicoding_specification)
+registerotffeature(specification)
+registerafmfeature(specification)
diff --git a/tex/context/base/mkiv/font-ext.lua b/tex/context/base/mkiv/font-ext.lua
deleted file mode 100644
index d873dccd4..000000000
--- a/tex/context/base/mkiv/font-ext.lua
+++ /dev/null
@@ -1,1856 +0,0 @@
-if not modules then modules = { } end modules ['font-ext'] = {
- version = 1.001,
- comment = "companion to font-ini.mkiv and hand-ini.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local next, type, tonumber = next, type, tonumber
-local byte, find, formatters = string.byte, string.find, string.formatters
-local utfchar = utf.char
-local sortedhash, sortedkeys, sort = table.sortedhash, table.sortedkeys, table.sort
-
-local context = context
-local fonts = fonts
-local utilities = utilities
-
-local trace_protrusion = false trackers.register("fonts.protrusion", function(v) trace_protrusion = v end)
-local trace_expansion = false trackers.register("fonts.expansion", function(v) trace_expansion = v end)
-
-local report_expansions = logs.reporter("fonts","expansions")
-local report_protrusions = logs.reporter("fonts","protrusions")
-
---[[ldx--
-<p>When we implement functions that deal with features, most of them
-will depend of the font format. Here we define the few that are kind
-of neutral.</p>
---ldx]]--
-
-local handlers = fonts.handlers
-local hashes = fonts.hashes
-local otf = handlers.otf
-local afm = handlers.afm
-
-local registerotffeature = otf.features.register
-local registerafmfeature = afm.features.register
-
-local fontdata = hashes.identifiers
-local fontproperties = hashes.properties
-
-local constructors = fonts.constructors
-local getprivate = constructors.getprivate
-
-local allocate = utilities.storage.allocate
-local settings_to_array = utilities.parsers.settings_to_array
-local settings_to_hash = utilities.parsers.settings_to_hash
-local getparameters = utilities.parsers.getparameters
-local gettexdimen = tex.getdimen
-local family_font = node.family_font
-
-local setmetatableindex = table.setmetatableindex
-
-local implement = interfaces.implement
-local variables = interfaces.variables
-
-
-local v_background = variables.background
-local v_frame = variables.frame
-local v_empty = variables.empty
-local v_none = variables.none
-
--- -- -- -- -- --
--- shared
--- -- -- -- -- --
-
-local function get_class_and_vector(tfmdata,value,where) -- "expansions"
- local g_where = tfmdata.goodies and tfmdata.goodies[where]
- local f_where = fonts[where]
- local g_classes = g_where and g_where.classes
- local f_classes = f_where and f_where.classes
- local class = (g_classes and g_classes[value]) or (f_classes and f_classes[value])
- if class then
- local class_vector = class.vector
- local g_vectors = g_where and g_where.vectors
- local f_vectors = f_where and f_where.vectors
- local vector = (g_vectors and g_vectors[class_vector]) or (f_vectors and f_vectors[class_vector])
- return class, vector
- end
-end
-
--- -- -- -- -- --
--- expansion (hz)
--- -- -- -- -- --
-
-local expansions = fonts.expansions or allocate()
-
-fonts.expansions = expansions
-
-local classes = expansions.classes or allocate()
-local vectors = expansions.vectors or allocate()
-
-expansions.classes = classes
-expansions.vectors = vectors
-
--- beware, pdftex itself uses percentages * 10
---
--- todo: get rid of byte() here
-
-classes.preset = { stretch = 2, shrink = 2, step = .5, factor = 1 }
-
-classes['quality'] = {
- stretch = 2, shrink = 2, step = .5, vector = 'default', factor = 1
-}
-
-vectors['default'] = {
- [byte('A')] = 0.5, [byte('B')] = 0.7, [byte('C')] = 0.7, [byte('D')] = 0.5, [byte('E')] = 0.7,
- [byte('F')] = 0.7, [byte('G')] = 0.5, [byte('H')] = 0.7, [byte('K')] = 0.7, [byte('M')] = 0.7,
- [byte('N')] = 0.7, [byte('O')] = 0.5, [byte('P')] = 0.7, [byte('Q')] = 0.5, [byte('R')] = 0.7,
- [byte('S')] = 0.7, [byte('U')] = 0.7, [byte('W')] = 0.7, [byte('Z')] = 0.7,
- [byte('a')] = 0.7, [byte('b')] = 0.7, [byte('c')] = 0.7, [byte('d')] = 0.7, [byte('e')] = 0.7,
- [byte('g')] = 0.7, [byte('h')] = 0.7, [byte('k')] = 0.7, [byte('m')] = 0.7, [byte('n')] = 0.7,
- [byte('o')] = 0.7, [byte('p')] = 0.7, [byte('q')] = 0.7, [byte('s')] = 0.7, [byte('u')] = 0.7,
- [byte('w')] = 0.7, [byte('z')] = 0.7,
- [byte('2')] = 0.7, [byte('3')] = 0.7, [byte('6')] = 0.7, [byte('8')] = 0.7, [byte('9')] = 0.7,
-}
-
-vectors['quality'] = vectors['default'] -- metatable ?
-
-local function initializeexpansion(tfmdata,value)
- if value then
- local class, vector = get_class_and_vector(tfmdata,value,"expansions")
- if class then
- if vector then
- local stretch = class.stretch or 0
- local shrink = class.shrink or 0
- local step = class.step or 0
- local factor = class.factor or 1
- if trace_expansion then
- report_expansions("setting class %a, vector %a, factor %a, stretch %a, shrink %a, step %a",
- value,class.vector,factor,stretch,shrink,step)
- end
- tfmdata.parameters.expansion = {
- stretch = 10 * stretch,
- shrink = 10 * shrink,
- step = 10 * step,
- factor = factor,
- }
- local data = characters and characters.data
- for i, chr in next, tfmdata.characters do
- local v = vector[i]
- if data and not v then -- we could move the data test outside (needed for plain)
- local d = data[i]
- if d then
- local s = d.shcode
- if not s then
- -- sorry
- elseif type(s) == "table" then
- v = ((vector[s[1]] or 0) + (vector[s[#s]] or 0)) / 2
- else
- v = vector[s] or 0
- end
- end
- end
- if v and v ~= 0 then
- chr.expansion_factor = v*factor
- else -- can be option
- chr.expansion_factor = factor
- end
- end
- elseif trace_expansion then
- report_expansions("unknown vector %a in class %a",class.vector,value)
- end
- elseif trace_expansion then
- report_expansions("unknown class %a",value)
- end
- end
-end
-
-local expansion_specification = {
- name = "expansion",
- description = "apply hz optimization",
- initializers = {
- base = initializeexpansion,
- node = initializeexpansion,
- }
-}
-
-registerotffeature(expansion_specification)
-registerafmfeature(expansion_specification)
-
-fonts.goodies.register("expansions", function(...) return fonts.goodies.report("expansions", trace_expansion, ...) end)
-
-implement {
- name = "setupfontexpansion",
- arguments = "2 strings",
- actions = function(class,settings) getparameters(classes,class,'preset',settings) end
-}
-
--- -- -- -- -- --
--- protrusion
--- -- -- -- -- --
-
-fonts.protrusions = allocate()
-local protrusions = fonts.protrusions
-
-protrusions.classes = allocate()
-protrusions.vectors = allocate()
-
-local classes = protrusions.classes
-local vectors = protrusions.vectors
-
--- the values need to be revisioned
-
-classes.preset = { factor = 1, left = 1, right = 1 }
-
-classes['pure'] = {
- vector = 'pure', factor = 1
-}
-classes['punctuation'] = {
- vector = 'punctuation', factor = 1
-}
-classes['alpha'] = {
- vector = 'alpha', factor = 1
-}
-classes['quality'] = {
- vector = 'quality', factor = 1
-}
-
-vectors['pure'] = {
-
- [0x002C] = { 0, 1 }, -- comma
- [0x002E] = { 0, 1 }, -- period
- [0x003A] = { 0, 1 }, -- colon
- [0x003B] = { 0, 1 }, -- semicolon
- [0x002D] = { 0, 1 }, -- hyphen
- [0x00AD] = { 0, 1 }, -- also hyphen
- [0x2013] = { 0, 0.50 }, -- endash
- [0x2014] = { 0, 0.33 }, -- emdash
- [0x3001] = { 0, 1 }, -- ideographic comma 、
- [0x3002] = { 0, 1 }, -- ideographic full stop 。
- [0x060C] = { 0, 1 }, -- arabic comma ،
- [0x061B] = { 0, 1 }, -- arabic semicolon ؛
- [0x06D4] = { 0, 1 }, -- arabic full stop ۔
-
-}
-
-vectors['punctuation'] = {
-
- [0x003F] = { 0, 0.20 }, -- ?
- [0x00BF] = { 0, 0.20 }, -- ¿
- [0x0021] = { 0, 0.20 }, -- !
- [0x00A1] = { 0, 0.20 }, -- ¡
- [0x0028] = { 0.05, 0 }, -- (
- [0x0029] = { 0, 0.05 }, -- )
- [0x005B] = { 0.05, 0 }, -- [
- [0x005D] = { 0, 0.05 }, -- ]
- [0x002C] = { 0, 0.70 }, -- comma
- [0x002E] = { 0, 0.70 }, -- period
- [0x003A] = { 0, 0.50 }, -- colon
- [0x003B] = { 0, 0.50 }, -- semicolon
- [0x002D] = { 0, 0.70 }, -- hyphen
- [0x00AD] = { 0, 0.70 }, -- also hyphen
- [0x2013] = { 0, 0.30 }, -- endash
- [0x2014] = { 0, 0.20 }, -- emdash
- [0x060C] = { 0, 0.70 }, -- arabic comma
- [0x061B] = { 0, 0.50 }, -- arabic semicolon
- [0x06D4] = { 0, 0.70 }, -- arabic full stop
- [0x061F] = { 0, 0.20 }, -- ؟
-
- -- todo: left and right quotes: .5 double, .7 single
-
- [0x2039] = { 0.70, 0.70 }, -- left single guillemet ‹
- [0x203A] = { 0.70, 0.70 }, -- right single guillemet ›
- [0x00AB] = { 0.50, 0.50 }, -- left guillemet «
- [0x00BB] = { 0.50, 0.50 }, -- right guillemet »
-
- [0x2018] = { 0.70, 0.70 }, -- left single quotation mark ‘
- [0x2019] = { 0, 0.70 }, -- right single quotation mark ’
- [0x201A] = { 0.70, 0 }, -- single low-9 quotation mark ,
- [0x201B] = { 0.70, 0 }, -- single high-reversed-9 quotation mark ‛
- [0x201C] = { 0.50, 0.50 }, -- left double quotation mark “
- [0x201D] = { 0, 0.50 }, -- right double quotation mark ”
- [0x201E] = { 0.50, 0 }, -- double low-9 quotation mark „
- [0x201F] = { 0.50, 0 }, -- double high-reversed-9 quotation mark ‟
-
-}
-
-vectors['alpha'] = {
-
- [byte("A")] = { .05, .05 },
- [byte("F")] = { 0, .05 },
- [byte("J")] = { .05, 0 },
- [byte("K")] = { 0, .05 },
- [byte("L")] = { 0, .05 },
- [byte("T")] = { .05, .05 },
- [byte("V")] = { .05, .05 },
- [byte("W")] = { .05, .05 },
- [byte("X")] = { .05, .05 },
- [byte("Y")] = { .05, .05 },
-
- [byte("k")] = { 0, .05 },
- [byte("r")] = { 0, .05 },
- [byte("t")] = { 0, .05 },
- [byte("v")] = { .05, .05 },
- [byte("w")] = { .05, .05 },
- [byte("x")] = { .05, .05 },
- [byte("y")] = { .05, .05 },
-
-}
-
-vectors['quality'] = table.merged(
- vectors['punctuation'],
- vectors['alpha']
-)
-
--- As this is experimental code, users should not depend on it. The implications are still
--- discussed on the ConTeXt Dev List and we're not sure yet what exactly the spec is (the
--- next code is tested with a gyre font patched by / fea file made by Khaled Hosny). The
--- double trick should not be needed it proper hanging punctuation is used in which case
--- values < 1 can be used.
---
--- preferred (in context, usine vectors):
---
--- \definefontfeature[whatever][default][mode=node,protrusion=quality]
---
--- using lfbd and rtbd, with possibibility to enable only one side :
---
--- \definefontfeature[whocares][default][mode=node,protrusion=yes, opbd=yes,script=latn]
--- \definefontfeature[whocares][default][mode=node,protrusion=right,opbd=yes,script=latn]
---
--- idem, using multiplier
---
--- \definefontfeature[whocares][default][mode=node,protrusion=2,opbd=yes,script=latn]
--- \definefontfeature[whocares][default][mode=node,protrusion=double,opbd=yes,script=latn]
---
--- idem, using named feature file (less frozen):
---
--- \definefontfeature[whocares][default][mode=node,protrusion=2,opbd=yes,script=latn,featurefile=texgyrepagella-regularxx.fea]
-
-classes['double'] = { -- for testing opbd
- factor = 2, left = 1, right = 1,
-}
-
-local function map_opbd_onto_protrusion(tfmdata,value,opbd)
- local characters = tfmdata.characters
- local descriptions = tfmdata.descriptions
- local properties = tfmdata.properties
- local resources = tfmdata.resources
- local rawdata = tfmdata.shared.rawdata
- local lookuphash = rawdata.lookuphash
- local lookuptags = resources.lookuptags
- local script = properties.script
- local language = properties.language
- local done, factor, left, right = false, 1, 1, 1
- local class = classes[value]
- if class then
- factor = class.factor or 1
- left = class.left or 1
- right = class.right or 1
- else
- factor = tonumber(value) or 1
- end
- if opbd ~= "right" then
- local validlookups, lookuplist = otf.collectlookups(rawdata,"lfbd",script,language)
- if validlookups then
- for i=1,#lookuplist do
- local lookup = lookuplist[i]
- local steps = lookup.steps
- if steps then
- if trace_protrusion then
- report_protrusions("setting left using lfbd")
- end
- for i=1,#steps do
- local step = steps[i]
- local coverage = step.coverage
- if coverage then
- for k, v in next, coverage do
- -- local p = - v[3] / descriptions[k].width-- or 1 ~= 0 too but the same
- local p = - (v[1] / 1000) * factor * left
- characters[k].left_protruding = p
- if trace_protrusion then
- report_protrusions("lfbd -> %C -> %p",k,p)
- end
- end
- end
- end
- done = true
- end
- end
- end
- end
- if opbd ~= "left" then
- local validlookups, lookuplist = otf.collectlookups(rawdata,"rtbd",script,language)
- if validlookups then
- for i=1,#lookuplist do
- local lookup = lookuplist[i]
- local steps = lookup.steps
- if steps then
- if trace_protrusion then
- report_protrusions("setting right using rtbd")
- end
- for i=1,#steps do
- local step = steps[i]
- local coverage = step.coverage
- if coverage then
- for k, v in next, coverage do
- -- local p = v[3] / descriptions[k].width -- or 3
- local p = (v[1] / 1000) * factor * right
- characters[k].right_protruding = p
- if trace_protrusion then
- report_protrusions("rtbd -> %C -> %p",k,p)
- end
- end
- end
- end
- end
- done = true
- end
- end
- end
-end
-
--- The opbd test is just there because it was discussed on the context development list. However,
--- the mentioned fxlbi.otf font only has some kerns for digits. So, consider this feature not supported
--- till we have a proper test font.
-
-local function initializeprotrusion(tfmdata,value)
- if value then
- local opbd = tfmdata.shared.features.opbd
- if opbd then
- -- possible values: left right both yes no (experimental)
- map_opbd_onto_protrusion(tfmdata,value,opbd)
- else
- local class, vector = get_class_and_vector(tfmdata,value,"protrusions")
- if class then
- if vector then
- local factor = class.factor or 1
- local left = class.left or 1
- local right = class.right or 1
- if trace_protrusion then
- report_protrusions("setting class %a, vector %a, factor %a, left %a, right %a",
- value,class.vector,factor,left,right)
- end
- local data = characters.data
- local emwidth = tfmdata.parameters.quad
- tfmdata.parameters.protrusion = {
- factor = factor,
- left = left,
- right = right,
- }
- for i, chr in next, tfmdata.characters do
- local v, pl, pr = vector[i], nil, nil
- if v then
- pl, pr = v[1], v[2]
- else
- local d = data[i]
- if d then
- local s = d.shcode
- if not s then
- -- sorry
- elseif type(s) == "table" then
- local vl, vr = vector[s[1]], vector[s[#s]]
- if vl then pl = vl[1] end
- if vr then pr = vr[2] end
- else
- v = vector[s]
- if v then
- pl, pr = v[1], v[2]
- end
- end
- end
- end
- if pl and pl ~= 0 then
- chr.left_protruding = left *pl*factor
- end
- if pr and pr ~= 0 then
- chr.right_protruding = right*pr*factor
- end
- end
- elseif trace_protrusion then
- report_protrusions("unknown vector %a in class %a",class.vector,value)
- end
- elseif trace_protrusion then
- report_protrusions("unknown class %a",value)
- end
- end
- end
-end
-
-local protrusion_specification = {
- name = "protrusion",
- description = "l/r margin character protrusion",
- initializers = {
- base = initializeprotrusion,
- node = initializeprotrusion,
- }
-}
-
-registerotffeature(protrusion_specification)
-registerafmfeature(protrusion_specification)
-
-fonts.goodies.register("protrusions", function(...) return fonts.goodies.report("protrusions", trace_protrusion, ...) end)
-
-implement {
- name = "setupfontprotrusion",
- arguments = "2 strings",
- actions = function(class,settings) getparameters(classes,class,'preset',settings) end
-}
-
--- -- --
-
-local function initializenostackmath(tfmdata,value)
- tfmdata.properties.nostackmath = value and true
-end
-
-registerotffeature {
- name = "nostackmath",
- description = "disable math stacking mechanism",
- initializers = {
- base = initializenostackmath,
- node = initializenostackmath,
- }
-}
-
-local function initializerealdimensions(tfmdata,value)
- tfmdata.properties.realdimensions = value and true
-end
-
-registerotffeature {
- name = "realdimensions",
- description = "accept negative dimenions",
- initializers = {
- base = initializerealdimensions,
- node = initializerealdimensions,
- }
-}
-
-local function initializeitlc(tfmdata,value) -- hm, always value
- if value then
- -- the magic 40 and it formula come from Dohyun Kim but we might need another guess
- local parameters = tfmdata.parameters
- local italicangle = parameters.italicangle
- if italicangle and italicangle ~= 0 then
- local properties = tfmdata.properties
- local factor = tonumber(value) or 1
- properties.hasitalics = true
- properties.autoitalicamount = factor * (parameters.uwidth or 40)/2
- end
- end
-end
-
-local italic_specification = {
- name = "itlc",
- description = "italic correction",
- initializers = {
- base = initializeitlc,
- node = initializeitlc,
- }
-}
-
-registerotffeature(italic_specification)
-registerafmfeature(italic_specification)
-
-local function initializetextitalics(tfmdata,value) -- yes no delay
- tfmdata.properties.textitalics = toboolean(value)
-end
-
-local textitalics_specification = {
- name = "textitalics",
- description = "use alternative text italic correction",
- initializers = {
- base = initializetextitalics,
- node = initializetextitalics,
- }
-}
-
-registerotffeature(textitalics_specification)
-registerafmfeature(textitalics_specification)
-
--- local function initializemathitalics(tfmdata,value) -- yes no delay
--- tfmdata.properties.mathitalics = toboolean(value)
--- end
---
--- local mathitalics_specification = {
--- name = "mathitalics",
--- description = "use alternative math italic correction",
--- initializers = {
--- base = initializemathitalics,
--- node = initializemathitalics,
--- }
--- }
-
--- registerotffeature(mathitalics_specification)
--- registerafmfeature(mathitalics_specification)
-
--- slanting
-
-local function initializeslant(tfmdata,value)
- value = tonumber(value)
- if not value then
- value = 0
- elseif value > 1 then
- value = 1
- elseif value < -1 then
- value = -1
- end
- tfmdata.parameters.slantfactor = value
-end
-
-local slant_specification = {
- name = "slant",
- description = "slant glyphs",
- initializers = {
- base = initializeslant,
- node = initializeslant,
- }
-}
-
-registerotffeature(slant_specification)
-registerafmfeature(slant_specification)
-
-local function initializeextend(tfmdata,value)
- value = tonumber(value)
- if not value then
- value = 0
- elseif value > 10 then
- value = 10
- elseif value < -10 then
- value = -10
- end
- tfmdata.parameters.extendfactor = value
-end
-
-local extend_specification = {
- name = "extend",
- description = "scale glyphs horizontally",
- initializers = {
- base = initializeextend,
- node = initializeextend,
- }
-}
-
-registerotffeature(extend_specification)
-registerafmfeature(extend_specification)
-
--- For Wolfgang Schuster:
---
--- \definefontfeature[thisway][default][script=hang,language=zhs,dimensions={2,2,2}]
--- \definedfont[file:kozminpr6nregular*thisway]
---
--- For the moment we don't mess with the descriptions.
-
-local function manipulatedimensions(tfmdata,key,value)
- if type(value) == "string" and value ~= "" then
- local characters = tfmdata.characters
- local parameters = tfmdata.parameters
- local emwidth = parameters.quad
- local exheight = parameters.xheight
- local newwidth = false
- local newheight = false
- local newdepth = false
- if value == "strut" then
- newheight = gettexdimen("strutht")
- newdepth = gettexdimen("strutdp")
- elseif value == "mono" then
- newwidth = emwidth
- else
- local spec = settings_to_array(value)
- newwidth = tonumber(spec[1])
- newheight = tonumber(spec[2])
- newdepth = tonumber(spec[3])
- if newwidth then newwidth = newwidth * emwidth end
- if newheight then newheight = newheight * exheight end
- if newdepth then newdepth = newdepth * exheight end
- end
- if newwidth or newheight or newdepth then
- local additions = { }
- for unicode, old_c in next, characters do
- local oldwidth = old_c.width
- local oldheight = old_c.height
- local olddepth = old_c.depth
- local width = newwidth or oldwidth or 0
- local height = newheight or oldheight or 0
- local depth = newdepth or olddepth or 0
- if oldwidth ~= width or oldheight ~= height or olddepth ~= depth then
- local private = getprivate(tfmdata)
- local newslot = { "slot", 1, private } -- { "slot", 0, private }
- local new_c
- local commands = oldwidth ~= width and {
- { "right", (width - oldwidth) / 2 },
- newslot,
- } or {
- newslot,
- }
- if height > 0 then
- if depth > 0 then
- new_c = {
- width = width,
- height = height,
- depth = depth,
- commands = commands,
- }
- else
- new_c = {
- width = width,
- height = height,
- commands = commands,
- }
- end
- else
- if depth > 0 then
- new_c = {
- width = width,
- depth = depth,
- commands = commands,
- }
- else
- new_c = {
- width = width,
- commands = commands,
- }
- end
- end
- setmetatableindex(new_c,old_c)
- characters[unicode] = new_c
- additions[private] = old_c
- end
- end
- for k, v in next, additions do
- characters[k] = v
- end
- -- elseif height > 0 and depth > 0 then
- -- for unicode, old_c in next, characters do
- -- old_c.height = height
- -- old_c.depth = depth
- -- end
- -- elseif height > 0 then
- -- for unicode, old_c in next, characters do
- -- old_c.height = height
- -- end
- -- elseif depth > 0 then
- -- for unicode, old_c in next, characters do
- -- old_c.depth = depth
- -- end
- end
- end
-end
-
-local dimensions_specification = {
- name = "dimensions",
- description = "force dimensions",
- manipulators = {
- base = manipulatedimensions,
- node = manipulatedimensions,
- }
-}
-
-registerotffeature(dimensions_specification)
-registerafmfeature(dimensions_specification)
-
---------------------------------------------------------------------------------------------------------------
-
--- local function fakemonospace(tfmdata)
--- local resources = tfmdata.resources
--- local gposfeatures = resources.features.gpos
--- local characters = tfmdata.characters
--- local descriptions = tfmdata.descriptions
--- local sequences = resources.sequences
--- local coverage = { }
--- local units = tfmdata.shared.rawdata.metadata.units
--- for k, v in next, characters do
--- local w = descriptions[k].width
--- local d = units - w
--- coverage[k] = { -d/2, 0, units, 0 }
--- end
--- local f = { dflt = { dflt = true } }
--- local s = #sequences + 1
--- local t = {
--- features = { fakemono = f },
--- flags = { false, false, false, false },
--- index = s,
--- name = "p_s_" .. s,
--- nofsteps = 1,
--- order = { "fakemono" },
--- skiphash = false,
--- type = "gpos_single",
--- steps = {
--- {
--- format = "single",
--- coverage = coverage,
--- }
--- }
--- }
--- gposfeatures["fakemono"] = f
--- sequences[s] = t
--- end
---
--- fonts.constructors.features.otf.register {
--- name = "fakemono",
--- description = "fake monospaced",
--- initializers = {
--- node = fakemonospace,
--- },
--- }
-
---------------------------------------------------------------------------------------------------------------
-
--- for zhichu chen (see mailing list archive): we might add a few more variants
--- in due time
---
--- \definefontfeature[boxed][default][boundingbox=yes] % paleblue
---
--- maybe:
---
--- \definecolor[DummyColor][s=.75,t=.5,a=1] {\DummyColor test} \nopdfcompression
---
--- local gray = { "pdf", "origin", "/Tr1 gs .75 g" }
--- local black = { "pdf", "origin", "/Tr0 gs 0 g" }
-
-
--- boundingbox={yes|background|frame|empty|<color>}
-
-local push = { "push" }
-local pop = { "pop" }
-
------ gray = { "pdf", "origin", ".75 g .75 G" }
------ black = { "pdf", "origin", "0 g 0 G" }
------ gray = { "pdf", ".75 g" }
------ black = { "pdf", "0 g" }
-
--- local bp = number.dimenfactors.bp
---
--- local downcache = setmetatableindex(function(t,d)
--- local v = { "down", d }
--- t[d] = v
--- return v
--- end)
---
--- local backcache = setmetatableindex(function(t,h)
--- local h = h * bp
--- local v = setmetatableindex(function(t,w)
--- -- local v = { "rule", h, w }
--- local v = { "pdf", "origin", formatters["0 0 %.6F %.6F re F"](w*bp,h) }
--- t[w] = v
--- return v
--- end)
--- t[h] = v
--- return v
--- end)
---
--- local forecache = setmetatableindex(function(t,h)
--- local h = h * bp
--- local v = setmetatableindex(function(t,w)
--- local v = { "pdf", "origin", formatters["%.6F w 0 0 %.6F %.6F re S"](0.25*65536*bp,w*bp,h) }
--- t[w] = v
--- return v
--- end)
--- t[h] = v
--- return v
--- end)
-
-local bp = number.dimenfactors.bp
-local r = 16384 * bp -- 65536 // 4
-
-local backcache = setmetatableindex(function(t,h)
- local h = h * bp
- local v = setmetatableindex(function(t,d)
- local d = d * bp
- local v = setmetatableindex(function(t,w)
- local v = { "pdf", "origin", formatters["%.6F w 0 %.6F %.6F %.6F re f"](r,-d,w*bp,h+d) }
- t[w] = v
- return v
- end)
- t[d] = v
- return v
- end)
- t[h] = v
- return v
-end)
-
-local forecache = setmetatableindex(function(t,h)
- local h = h * bp
- local v = setmetatableindex(function(t,d)
- local d = d * bp
- local v = setmetatableindex(function(t,w)
- -- the frame goes through the boundingbox
- -- local v = { "pdf", "origin", formatters["[] 0 d 0 J %.6F w %.6F %.6F %.6F re S"](r,-d,w*bp,h+d) }
- local v = { "pdf", "origin", formatters["[] 0 d 0 J %.6F w %.6F %.6F %.6F %.6F re S"](r,r/2,-d+r/2,w*bp-r,h+d-r) }
- t[w] = v
- return v
- end)
- t[d] = v
- return v
- end)
- t[h] = v
- return v
-end)
-
-local startcolor = nil
-local stopcolor = nil
-
-local function showboundingbox(tfmdata,key,value)
- if value then
- if not backcolors then
- local vfspecials = backends.pdf.tables.vfspecials
- startcolor = vfspecials.startcolor
- stopcolor = vfspecials.stopcolor
- end
- local characters = tfmdata.characters
- local additions = { }
- local rulecache = backcache
- local showchar = true
- local color = "palegray"
- if type(value) == "string" then
- value = settings_to_array(value)
- for i=1,#value do
- local v = value[i]
- if v == v_frame then
- rulecache = forecache
- elseif v == v_background then
- rulecache = backcache
- elseif v == v_empty then
- showchar = false
- elseif v == v_none then
- color = nil
- else
- color = v
- end
- end
- end
- local gray = color and startcolor(color) or nil
- local black = gray and stopcolor or nil
- for unicode, old_c in next, characters do
- local private = getprivate(tfmdata)
- local width = old_c.width or 0
- local height = old_c.height or 0
- local depth = old_c.depth or 0
- local char = showchar and { "slot", 1, private } or nil -- { "slot", 0, private }
- -- local new_c
- -- if depth == 0 then
- -- new_c = {
- -- width = width,
- -- height = height,
- -- commands = {
- -- push,
- -- gray,
- -- rulecache[height][width],
- -- black,
- -- pop,
- -- char,
- -- }
- -- }
- -- else
- -- new_c = {
- -- width = width,
- -- height = height,
- -- depth = depth,
- -- commands = {
- -- push,
- -- downcache[depth],
- -- gray,
- -- rulecache[height+depth][width],
- -- black,
- -- pop,
- -- char,
- -- }
- -- }
- -- end
- local rule = rulecache[height][depth][width]
- local new_c = {
- width = width,
- height = height,
- depth = depth,
- commands = gray and {
- -- push,
- gray,
- rule,
- black,
- -- pop,
- char,
- } or {
- rule,
- char,
- }
- }
- setmetatableindex(new_c,old_c)
- characters[unicode] = new_c
- additions[private] = old_c
- end
- for k, v in next, additions do
- characters[k] = v
- end
- end
-end
-
-registerotffeature {
- name = "boundingbox",
- description = "show boundingbox",
- manipulators = {
- base = showboundingbox,
- node = showboundingbox,
- }
-}
-
--- -- for notosans but not general
---
--- do
---
--- local v_local = interfaces and interfaces.variables and interfaces.variables["local"] or "local"
---
--- local utfbyte = utf.byte
---
--- local function initialize(tfmdata,key,value)
--- local characters = tfmdata.characters
--- local parameters = tfmdata.parameters
--- local oldchar = 32
--- local newchar = 32
--- if value == "locl" or value == v_local then
--- newchar = fonts.handlers.otf.getsubstitution(tfmdata,oldchar,"locl",true) or oldchar
--- elseif value == true then
--- -- use normal space
--- elseif value then
--- newchar = utfbyte(value)
--- else
--- return
--- end
--- local newchar = newchar and characters[newchar]
--- local newspace = newchar and newchar.width
--- if newspace > 0 then
--- parameters.space = newspace
--- parameters.space_stretch = newspace/2
--- parameters.space_shrink = newspace/3
--- parameters.extra_space = parameters.space_shrink
--- end
--- end
---
--- registerotffeature {
--- name = 'space', -- true|false|locl|character
--- description = 'space settings',
--- manipulators = {
--- base = initialize,
--- node = initialize,
--- }
--- }
---
--- end
-
-do
-
- local P, lpegpatterns, lpegmatch = lpeg.P, lpeg.patterns, lpeg.match
-
- local amount, stretch, shrink, extra
-
- local factor = lpegpatterns.unsigned
- local space = lpegpatterns.space
- local pattern = (
- (factor / function(n) amount = tonumber(n) or amount end)
- + (P("+") + P("plus" )) * space^0 * (factor / function(n) stretch = tonumber(n) or stretch end)
- + (P("-") + P("minus")) * space^0 * (factor / function(n) shrink = tonumber(n) or shrink end)
- + ( P("extra")) * space^0 * (factor / function(n) extra = tonumber(n) or extra end)
- + space^1
- )^1
-
- local function initialize(tfmdata,key,value)
- local characters = tfmdata.characters
- local parameters = tfmdata.parameters
- if type(value) == "string" then
- local emwidth = parameters.quad
- amount, stretch, shrink, extra = 0, 0, 0, false
- lpegmatch(pattern,value)
- if not extra then
- if shrink ~= 0 then
- extra = shrink
- elseif stretch ~= 0 then
- extra = stretch
- else
- extra = amount
- end
- end
- parameters.space = amount * emwidth
- parameters.space_stretch = stretch * emwidth
- parameters.space_shrink = shrink * emwidth
- parameters.extra_space = extra * emwidth
- end
- end
-
- -- 1.1 + 1.2 - 1.3 minus 1.4 plus 1.1 extra 1.4 -- last one wins
-
- registerotffeature {
- name = "spacing",
- description = "space settings",
- manipulators = {
- base = initialize,
- node = initialize,
- }
- }
-
-end
-
--- -- historic stuff, move from font-ota (handled differently, typo-rep)
---
--- local delete_node = nodes.delete
--- local fontdata = fonts.hashes.identifiers
---
--- local nodecodes = nodes.nodecodes
--- local glyph_code = nodecodes.glyph
---
--- local strippables = allocate()
--- fonts.strippables = strippables
---
--- strippables.joiners = table.tohash {
--- 0x200C, -- zwnj
--- 0x200D, -- zwj
--- }
---
--- strippables.all = table.tohash {
--- 0x000AD, 0x017B4, 0x017B5, 0x0200B, 0x0200C, 0x0200D, 0x0200E, 0x0200F, 0x0202A, 0x0202B,
--- 0x0202C, 0x0202D, 0x0202E, 0x02060, 0x02061, 0x02062, 0x02063, 0x0206A, 0x0206B, 0x0206C,
--- 0x0206D, 0x0206E, 0x0206F, 0x0FEFF, 0x1D173, 0x1D174, 0x1D175, 0x1D176, 0x1D177, 0x1D178,
--- 0x1D179, 0x1D17A, 0xE0001, 0xE0020, 0xE0021, 0xE0022, 0xE0023, 0xE0024, 0xE0025, 0xE0026,
--- 0xE0027, 0xE0028, 0xE0029, 0xE002A, 0xE002B, 0xE002C, 0xE002D, 0xE002E, 0xE002F, 0xE0030,
--- 0xE0031, 0xE0032, 0xE0033, 0xE0034, 0xE0035, 0xE0036, 0xE0037, 0xE0038, 0xE0039, 0xE003A,
--- 0xE003B, 0xE003C, 0xE003D, 0xE003E, 0xE003F, 0xE0040, 0xE0041, 0xE0042, 0xE0043, 0xE0044,
--- 0xE0045, 0xE0046, 0xE0047, 0xE0048, 0xE0049, 0xE004A, 0xE004B, 0xE004C, 0xE004D, 0xE004E,
--- 0xE004F, 0xE0050, 0xE0051, 0xE0052, 0xE0053, 0xE0054, 0xE0055, 0xE0056, 0xE0057, 0xE0058,
--- 0xE0059, 0xE005A, 0xE005B, 0xE005C, 0xE005D, 0xE005E, 0xE005F, 0xE0060, 0xE0061, 0xE0062,
--- 0xE0063, 0xE0064, 0xE0065, 0xE0066, 0xE0067, 0xE0068, 0xE0069, 0xE006A, 0xE006B, 0xE006C,
--- 0xE006D, 0xE006E, 0xE006F, 0xE0070, 0xE0071, 0xE0072, 0xE0073, 0xE0074, 0xE0075, 0xE0076,
--- 0xE0077, 0xE0078, 0xE0079, 0xE007A, 0xE007B, 0xE007C, 0xE007D, 0xE007E, 0xE007F,
--- }
---
--- strippables[true] = strippables.joiners
---
--- local function processformatters(head,font)
--- local subset = fontdata[font].shared.features.formatters
--- local vector = subset and strippables[subset]
--- if vector then
--- local current, done = head, false
--- while current do
--- if current.id == glyph_code and current.subtype<256 and current.font == font then
--- local char = current.char
--- if vector[char] then
--- head, current = delete_node(head,current)
--- done = true
--- else
--- current = current.next
--- end
--- else
--- current = current.next
--- end
--- end
--- return head, done
--- else
--- return head, false
--- end
--- end
---
--- registerotffeature {
--- name = "formatters",
--- description = "hide formatting characters",
--- methods = {
--- base = processformatters,
--- node = processformatters,
--- }
--- }
-
--- not to be used! experimental code, only needed when testing
-
-local is_letter = characters.is_letter
-local always = true
-
-local function collapseitalics(tfmdata,key,value)
- local threshold = value == true and 100 or tonumber(value)
- if threshold and threshold > 0 then
- if threshold > 100 then
- threshold = 100
- end
- for unicode, data in next, tfmdata.characters do
- if always or is_letter[unicode] or is_letter[data.unicode] then
- local italic = data.italic
- if italic and italic ~= 0 then
- local width = data.width
- if width and width ~= 0 then
- local delta = threshold * italic / 100
- data.width = width + delta
- data.italic = italic - delta
- end
- end
- end
- end
- end
-end
-
-local dimensions_specification = {
- name = "collapseitalics",
- description = "collapse italics",
- manipulators = {
- base = collapseitalics,
- node = collapseitalics,
- }
-}
-
-registerotffeature(dimensions_specification)
-registerafmfeature(dimensions_specification)
-
--- a handy helper (might change or be moved to another namespace)
-
-local nodepool = nodes.pool
-local new_glyph = nodepool.glyph
-
-local helpers = fonts.helpers
-local currentfont = font.current
-
-local currentprivate = 0xE000
-local maximumprivate = 0xEFFF
-
--- if we run out of space we can think of another range but by sharing we can
--- use these privates for mechanisms like alignments-on-character and such
-
-local sharedprivates = setmetatableindex(function(t,k)
- v = currentprivate
- if currentprivate < maximumprivate then
- currentprivate = currentprivate + 1
- else
- -- reuse last slot, todo: warning
- end
- t[k] = v
- return v
-end)
-
-function helpers.addprivate(tfmdata,name,characterdata)
- local properties = tfmdata.properties
- local characters = tfmdata.characters
- local privates = properties.privates
- if not privates then
- privates = { }
- properties.privates = privates
- end
- if not name then
- name = formatters["anonymous_private_0x%05X"](currentprivate)
- end
- local usedprivate = sharedprivates[name]
- privates[name] = usedprivate
- characters[usedprivate] = characterdata
- return usedprivate
-end
-
-local function getprivateslot(id,name)
- if not name then
- name = id
- id = currentfont()
- end
- local properties = fontproperties[id]
- local privates = properties and properties.privates
- return privates and privates[name]
-end
-
-local function getprivatenode(tfmdata,name)
- if type(tfmdata) == "number" then
- tfmdata = fontdata[tfmdata]
- end
- local properties = tfmdata.properties
- local font = properties.id
- local slot = getprivateslot(font,name)
- if slot then
- -- todo: set current attribibutes
- local char = tfmdata.characters[slot]
- local tonode = char.tonode
- if tonode then
- return tonode(font,char)
- else
- return new_glyph(font,slot)
- end
- end
-end
-
-local function getprivatecharornode(tfmdata,name)
- if type(tfmdata) == "number" then
- tfmdata = fontdata[tfmdata]
- end
- local properties = tfmdata.properties
- local font = properties.id
- local slot = getprivateslot(font,name)
- if slot then
- -- todo: set current attributes
- local char = tfmdata.characters[slot]
- local tonode = char.tonode
- if tonode then
- return "node", tonode(tfmdata,char)
- else
- return "char", slot
- end
- end
-end
-
-helpers.getprivateslot = getprivateslot
-helpers.getprivatenode = getprivatenode
-helpers.getprivatecharornode = getprivatecharornode
-
-function helpers.getprivates(tfmdata)
- if type(tfmdata) == "number" then
- tfmdata = fontdata[tfmdata]
- end
- local properties = tfmdata.properties
- return properties and properties.privates
-end
-
-function helpers.hasprivate(tfmdata,name)
- if type(tfmdata) == "number" then
- tfmdata = fontdata[tfmdata]
- end
- local properties = tfmdata.properties
- local privates = properties and properties.privates
- return privates and privates[name] or false
-end
-
--- relatively new:
-
-do
-
- local extraprivates = { }
-
- function fonts.helpers.addextraprivate(name,f)
- extraprivates[#extraprivates+1] = { name, f }
- end
-
- local function addextraprivates(tfmdata)
- for i=1,#extraprivates do
- local e = extraprivates[i]
- local c = e[2](tfmdata)
- if c then
- fonts.helpers.addprivate(tfmdata, e[1], c)
- end
- end
- end
-
- constructors.newfeatures.otf.register {
- name = "extraprivates",
- description = "extra privates",
- default = true,
- manipulators = {
- base = addextraprivates,
- node = addextraprivates,
- }
- }
-
-end
-
-implement {
- name = "getprivatechar",
- arguments = "string",
- actions = function(name)
- local p = getprivateslot(name)
- if p then
- context(utfchar(p))
- end
- end
-}
-
-implement {
- name = "getprivatemathchar",
- arguments = "string",
- actions = function(name)
- local p = getprivateslot(family_font(0),name)
- if p then
- context(utfchar(p))
- end
- end
-}
-
-implement {
- name = "getprivateslot",
- arguments = "string",
- actions = function(name)
- local p = getprivateslot(name)
- if p then
- context(p)
- end
- end
-}
-
--- requested for latex but not supported unless really needed in context:
---
--- registerotffeature {
--- name = "ignoremathconstants",
--- description = "ignore math constants table",
--- initializers = {
--- base = function(tfmdata,value)
--- if value then
--- tfmdata.mathparameters = nil
--- end
--- end
--- }
--- }
-
--- tfmdata.properties.mathnolimitsmode = tonumber(value) or 0
-
-do
-
- local splitter = lpeg.splitat(",",tonumber)
- local lpegmatch = lpeg.match
-
- local function initialize(tfmdata,value)
- local mathparameters = tfmdata.mathparameters
- if mathparameters then
- local sup, sub
- if type(value) == "string" then
- sup, sub = lpegmatch(splitter,value)
- if not sup then
- sub, sup = 0, 0
- elseif not sub then
- sub, sup = sup, 0
- end
- elseif type(value) == "number" then
- sup, sub = 0, value
- end
- mathparameters.NoLimitSupFactor = sup
- mathparameters.NoLimitSubFactor = sub
- end
- end
-
- registerotffeature {
- name = "mathnolimitsmode",
- description = "influence nolimits placement",
- initializers = {
- base = initialize,
- node = initialize,
- }
- }
-
-end
-
-do
-
- local function initialize(tfmdata,value)
- local properties = tfmdata.properties
- if properties then
- properties.identity = value == "vertical" and "vertical" or "horizontal"
- end
- end
-
- registerotffeature {
- name = "identity",
- description = "set font identity",
- initializers = {
- base = initialize,
- node = initialize,
- }
- }
-
- local function initialize(tfmdata,value)
- local properties = tfmdata.properties
- if properties then
- properties.writingmode = value == "vertical" and "vertical" or "horizontal"
- end
- end
-
- registerotffeature {
- name = "writingmode",
- description = "set font direction",
- initializers = {
- base = initialize,
- node = initialize,
- }
- }
-
-end
-
-do -- another hack for a crappy font
-
- local function additalictowidth(tfmdata,key,value)
- local characters = tfmdata.characters
- local additions = { }
- for unicode, old_c in next, characters do
- -- maybe check for math
- local oldwidth = old_c.width
- local olditalic = old_c.italic
- if olditalic and olditalic ~= 0 then
- local private = getprivate(tfmdata)
- local new_c = {
- width = oldwidth + olditalic,
- height = old_c.height,
- depth = old_c.depth,
- commands = {
- -- { "slot", 1, private },
- -- { "slot", 0, private },
- { "char", private },
- { "right", olditalic },
- },
- }
- setmetatableindex(new_c,old_c)
- characters[unicode] = new_c
- additions[private] = old_c
- end
- end
- for k, v in next, additions do
- characters[k] = v
- end
- end
-
- registerotffeature {
- name = "italicwidths",
- description = "add italic to width",
- manipulators = {
- base = additalictowidth,
- -- node = additalictowidth, -- only makes sense for math
- }
- }
-
-end
-
-do
-
- local tounicode = fonts.mappings.tounicode
-
- local function check(tfmdata,key,value)
- if value == "ligatures" then
- local private = fonts.constructors and fonts.constructors.privateoffset or 0xF0000
- local collected = fonts.handlers.otf.readers.getcomponents(tfmdata.shared.rawdata)
- if collected and next(collected)then
- for unicode, char in next, tfmdata.characters do
- if true then -- if unicode >= private or (unicode >= 0xE000 and unicode <= 0xF8FF) then
- local u = collected[unicode]
- if u then
- 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
- u = u[1]
- end
- char.unicode = u
- char.tounicode = tounicode(u)
- end
- end
- end
- end
- end
- end
- end
-
- -- forceunicodes=ligatures : aggressive lig resolving (e.g. for emoji)
- --
- -- kind of like: \enabletrackers[fonts.mapping.forceligatures]
-
- registerotffeature {
- name = "forceunicodes",
- description = "forceunicodes",
- manipulators = {
- base = check,
- node = check,
- }
- }
-
-end
-
-do
-
- -- This is a rather special test-only feature that I added for the sake of testing
- -- Idris's husayni. We wanted to know if uniscribe obeys the order of lookups in a
- -- font, in spite of what the description of handling arabic suggests. And indeed,
- -- mixed-in lookups of other features (like all these ss* in husayni) are handled
- -- the same in context as in uniscribe. If one sets reorderlookups=arab then we sort
- -- according to the "assumed" order so e.g. the ss* move to after the standard
- -- features. The observed difference in rendering is an indication that uniscribe is
- -- quite faithful to the font (while e.g. tests with the hb plugin demonstrate some
- -- interference, apart from some hard coded init etc expectations). Anyway, it means
- -- that we're okay with the (generic) node processor. A pitfall is that in context
- -- we can actually control more, so we can trigger an analyze pass with e.g.
- -- dflt/dflt while the libraries depend on the script settings for that. Uniscribe
- -- probably also parses the string and when seeing arabic will follow a different
- -- code path, although it seems to treat all features equal.
-
- local trace_reorder = trackers.register("fonts.reorderlookups",function(v) trace_reorder = v end)
- local report_reorder = logs.reporter("fonts","reorder")
-
- local vectors = { }
-
- vectors.arab = {
- gsub = {
- ccmp = 1,
- isol = 2,
- fina = 3,
- medi = 4,
- init = 5,
- rlig = 6,
- rclt = 7,
- calt = 8,
- liga = 9,
- dlig = 10,
- cswh = 11,
- mset = 12,
- },
- gpos = {
- curs = 1,
- kern = 2,
- mark = 3,
- mkmk = 4,
- },
- }
-
- function otf.reorderlookups(tfmdata,vector)
- local order = vectors[vector]
- if not order then
- return
- end
- local oldsequences = tfmdata.resources.sequences
- if oldsequences then
- local sequences = { }
- for i=1,#oldsequences do
- sequences[i] = oldsequences[i]
- end
- for i=1,#sequences do
- local s = sequences[i]
- local features = s.features
- local kind = s.type
- local index = s.index
- if features then
- local when
- local what
- for feature in sortedhash(features) do
- if not what then
- what = find(kind,"^gsub") and "gsub" or "gpos"
- end
- local newwhen = order[what][feature]
- if not newwhen then
- -- skip
- elseif not when then
- when = newwhen
- elseif newwhen < when then
- when = newwhen
- end
- end
- s.ondex = s.index
- s.index = i
- s.what = what == "gsub" and 1 or 2
- s.when = when or 99
- else
- s.ondex = s.index
- s.index = i
- s.what = 1
- s.when = 99
- end
- end
- sort(sequences,function(a,b)
- local what_a = a.what
- local what_b = b.what
- if what_a ~= what_b then
- return a.index < b.index
- end
- local when_a = a.when
- local when_b = b.when
- if when_a == when_b then
- return a.index < b.index
- else
- return when_a < when_b
- end
- end)
- local swapped = 0
- for i=1,#sequences do
- local sequence = sequences[i]
- local features = sequence.features
- if features then
- local index = sequence.index
- if index ~= i then
- swapped = swapped + 1
- end
- if trace_reorder then
- if swapped == 1 then
- report_reorder()
- report_reorder("start swapping lookups in font %!font:name!",tfmdata)
- report_reorder()
- report_reorder("gsub order: % t",table.swapped(order.gsub))
- report_reorder("gpos order: % t",table.swapped(order.gpos))
- report_reorder()
- end
- report_reorder("%03i : lookup %03i, type %s, sorted %2i, moved %s, % t",
- i,index,sequence.what == 1 and "gsub" or "gpos",sequence.when or 99,
- (index > i and "-") or (index < i and "+") or "=",sortedkeys(features))
- end
- end
- sequence.what = nil
- sequence.when = nil
- sequence.index = sequence.ondex
- end
- if swapped > 0 then
- if trace_reorder then
- report_reorder()
- report_reorder("stop swapping lookups, %i lookups swapped",swapped)
- report_reorder()
- end
--- tfmdata.resources.sequences = sequences
- tfmdata.shared.reorderedsequences = sequences
- end
- end
- end
-
- -- maybe delay till ra is filled
-
- local function reorderlookups(tfmdata,key,value)
- if value then
- otf.reorderlookups(tfmdata,value)
- end
- end
-
- registerotffeature {
- name = "reorderlookups",
- description = "reorder lookups",
- manipulators = {
- base = reorderlookups,
- node = reorderlookups,
- }
- }
-
-end
-
--- maybe useful
-
-local function initializeoutline(tfmdata,value)
- value = tonumber(value)
- if not value then
- value = 0
- else
- value = tonumber(value) or 0
- end
- if value then
- value = value * 1000
- end
- tfmdata.parameters.mode = 1
- tfmdata.parameters.width = value
-end
-
-local outline_specification = {
- name = "outline",
- description = "outline glyphs",
- initializers = {
- base = initializeoutline,
- node = initializeoutline,
- }
-}
-
-registerotffeature(outline_specification)
-registerafmfeature(outline_specification)
-
--- definitely ugly
-
-local report_effect = logs.reporter("fonts","effect")
-local trace_effect = false
-
-trackers.register("fonts.effect", function(v) trace_effect = v end)
-
-local effects = {
- inner = 0,
- normal = 0,
- outer = 1,
- outline = 1,
- both = 2,
- hidden = 3,
-}
-
-local function initializeeffect(tfmdata,value)
- local spec
- if type(value) == "number" then
- spec = { width = value }
- else
- spec = settings_to_hash(value)
- end
- local effect = spec.effect or "both"
- local width = tonumber(spec.width) or 0
- local mode = effects[effect]
- if not mode then
- report_effect("invalid effect %a",effect)
- elseif width == 0 and mode == 0 then
- report_effect("invalid width %a for effect %a",width,effect)
- else
- local parameters = tfmdata.parameters
- local properties = tfmdata.properties
- parameters.mode = mode
- parameters.width = width * 1000
- local factor = tonumber(spec.factor) or 0
- local hfactor = tonumber(spec.vfactor) or factor
- local vfactor = tonumber(spec.hfactor) or factor
- local delta = tonumber(spec.delta) or 1
- local wdelta = tonumber(spec.wdelta) or delta
- local hdelta = tonumber(spec.hdelta) or delta
- local ddelta = tonumber(spec.ddelta) or hdelta
- properties.effect = {
- effect = effect,
- width = width,
- factor = factor,
- hfactor = hfactor,
- vfactor = vfactor,
- wdelta = wdelta,
- hdelta = hdelta,
- ddelta = ddelta,
- }
- end
-end
-
-local function manipulateeffect(tfmdata)
- local effect = tfmdata.properties.effect
- if effect then
- local characters = tfmdata.characters
- local parameters = tfmdata.parameters
- local multiplier = effect.width * 100
- local wdelta = effect.wdelta * parameters.hfactor * multiplier
- local hdelta = effect.hdelta * parameters.vfactor * multiplier
- local ddelta = effect.ddelta * parameters.vfactor * multiplier
- local hshift = wdelta / 2
- local factor = (1 + effect.factor) * parameters.factor
- local hfactor = (1 + effect.hfactor) * parameters.hfactor
- local vfactor = (1 + effect.vfactor) * parameters.vfactor
- for unicode, old_c in next, characters do
- local oldwidth = old_c.width
- local oldheight = old_c.height
- local olddepth = old_c.depth
- if oldwidth and oldwidth > 0 then
- old_c.width = oldwidth + wdelta
- old_c.commands = {
- { "right", hshift },
- { "char", unicode },
- }
- end
- if oldheight and oldheight > 0 then
- old_c.height = oldheight + hdelta
- end
- if olddepth and olddepth > 0 then
- old_c.depth = olddepth + ddelta
- end
- end
- parameters.factor = factor
- parameters.hfactor = hfactor
- parameters.vfactor = vfactor
- if trace_effect then
- report_effect("applying effect")
- report_effect(" effect : %s", effect.effect)
- report_effect(" width : %s => %s", effect.width, multiplier)
- report_effect(" factor : %s => %s", effect.factor, factor )
- report_effect(" hfactor : %s => %s", effect.hfactor,hfactor)
- report_effect(" vfactor : %s => %s", effect.vfactor,vfactor)
- report_effect(" wdelta : %s => %s", effect.wdelta, wdelta)
- report_effect(" hdelta : %s => %s", effect.hdelta, hdelta)
- report_effect(" ddelta : %s => %s", effect.ddelta, ddelta)
- end
- end
-end
-
-local effect_specification = {
- name = "effect",
- description = "apply effects to glyphs",
- initializers = {
- base = initializeeffect,
- node = initializeeffect,
- },
- manipulators = {
- base = manipulateeffect,
- node = manipulateeffect,
- },
-}
-
-registerotffeature(effect_specification)
-registerafmfeature(effect_specification)
diff --git a/tex/context/base/mkiv/font-fbk.lua b/tex/context/base/mkiv/font-fbk.lua
index 79ebc3f25..cf500d0ce 100644
--- a/tex/context/base/mkiv/font-fbk.lua
+++ b/tex/context/base/mkiv/font-fbk.lua
@@ -14,38 +14,38 @@ local next = next
<p>This is very experimental code!</p>
--ldx]]--
-local trace_combining_visualize = false trackers.register("fonts.composing.visualize", function(v) trace_combining_visualize = v end)
-local trace_combining_define = false trackers.register("fonts.composing.define", function(v) trace_combining_define = v end)
+local trace_visualize = false trackers.register("fonts.composing.visualize", function(v) trace_visualize = v end)
+local trace_define = false trackers.register("fonts.composing.define", function(v) trace_define = v end)
-trackers.register("fonts.combining", "fonts.composing.define") -- for old times sake (and manuals)
-trackers.register("fonts.combining.all", "fonts.composing.*") -- for old times sake (and manuals)
-
-local report_combining = logs.reporter("fonts","combining")
-
-local force_combining = false -- just for demo purposes (see mk)
+local report = logs.reporter("fonts","combining")
local allocate = utilities.storage.allocate
local fonts = fonts
local handlers = fonts.handlers
local constructors = fonts.constructors
+local helpers = fonts.helpers
local otf = handlers.otf
local afm = handlers.afm
local registerotffeature = otf.features.register
local registerafmfeature = afm.features.register
+local addotffeature = otf.addfeature
+
local unicodecharacters = characters.data
local unicodefallbacks = characters.fallbacks
-local vf = handlers.vf
-local commands = vf.combiner.commands
-local push = vf.predefined.push
-local pop = vf.predefined.pop
+local vfcommands = helpers.commands
+local charcommand = vfcommands.char
+local rightcommand = vfcommands.right
+local downcommand = vfcommands.down
+local upcommand = vfcommands.up
+local push = vfcommands.push
+local pop = vfcommands.pop
-local force_composed = false
-local cache = { } -- we could make these weak
-local fraction = 0.15 -- 30 units for lucida
+local force_combining = false -- just for demo purposes (see mk)
+local fraction = 0.15 -- 30 units for lucida
-- todo: we also need to update the feature hashes ... i'll do that when i'm in the mood
-- and/or when i need it
@@ -65,15 +65,15 @@ local function composecharacters(tfmdata)
local italicfactor = parameters.italicfactor or 0
local vfspecials = backends.tables.vfspecials --brr
local red, green, blue, black
- if trace_combining_visualize then
+ if trace_visualize then
red = vfspecials.startcolor("red")
green = vfspecials.startcolor("green")
blue = vfspecials.startcolor("blue")
black = vfspecials.stopcolor
end
local compose = fonts.goodies.getcompositions(tfmdata)
- if compose and trace_combining_visualize then
- report_combining("using compose information from goodies file")
+ if compose and trace_visualize then
+ report("using compose information from goodies file")
end
local done = false
for i, c in next, unicodecharacters do -- loop over all characters ... not that efficient but a specials hash takes memory
@@ -105,24 +105,12 @@ local function composecharacters(tfmdata)
acc = unicodefallbacks[acc]
charsacc = acc and characters[acc]
end
- local chr_t = cache[chr]
- if not chr_t then
- -- chr_t = { "slot", 1, chr }
- -- chr_t = { "slot", 0, chr }
- chr_t = { "char", chr }
- cache[chr] = chr_t
- end
+ local chr_t = charcommand[chr]
if charsacc then
- if trace_combining_define then
- report_combining("composed %C, base %C, accent %C",i,chr,acc)
- end
- local acc_t = cache[acc]
- if not acc_t then
- -- acc_t = { "slot", 1, acc }
- -- acc_t = { "slot", 0, acc }
- acc_t = { "char", acc }
- cache[acc] = acc_t
+ if trace_define then
+ report("composed %C, base %C, accent %C",i,chr,acc)
end
+ local acc_t = charcommand[acc]
local cb = descriptions[chr].boundingbox
local ab = descriptions[acc].boundingbox
-- todo: adapt height
@@ -148,26 +136,30 @@ local function composecharacters(tfmdata)
local ay = a_anchor.y or 0
local dx = cx - ax
local dy = cy - ay
- if trace_combining_define then
- report_combining("building %C from %C and %C",i,chr,acc)
- report_combining(" boundingbox:")
- report_combining(" chr: %3i %3i %3i %3i",unpack(cb))
- report_combining(" acc: %3i %3i %3i %3i",unpack(ab))
- report_combining(" anchors:")
- report_combining(" chr: %3i %3i",cx,cy)
- report_combining(" acc: %3i %3i",ax,ay)
- report_combining(" delta:")
- report_combining(" %s: %3i %3i",i_anchored,dx,dy)
+ if trace_define then
+ report("building %C from %C and %C",i,chr,acc)
+ report(" boundingbox:")
+ report(" chr: %3i %3i %3i %3i",unpack(cb))
+ report(" acc: %3i %3i %3i %3i",unpack(ab))
+ report(" anchors:")
+ report(" chr: %3i %3i",cx,cy)
+ report(" acc: %3i %3i",ax,ay)
+ report(" delta:")
+ report(" %s: %3i %3i",i_anchored,dx,dy)
end
- if trace_combining_visualize then
- t.commands = { push, {"right", scale*dx}, {"down",-scale*dy}, green, acc_t, black, pop, chr_t }
- -- t.commands = {
- -- push, {"right", scale*cx}, {"down", -scale*cy}, red, {"rule",10000,10000,10000}, pop,
- -- push, {"right", scale*ax}, {"down", -scale*ay}, blue, {"rule",10000,10000,10000}, pop,
- -- push, {"right", scale*dx}, {"down", -scale*dy}, green, acc_t, black, pop, chr_t
- -- }
+ local right = rightcommand[scale*dx]
+ local down = upcommand[scale*dy]
+ if trace_visualize then
+ t.commands = {
+ push, right, down,
+ green, acc_t, black,
+ pop, chr_t,
+ }
else
- t.commands = { push, {"right", scale*dx}, {"down",-scale*dy}, acc_t, pop, chr_t }
+ t.commands = {
+ push, right, down,
+ acc_t, pop, chr_t,
+ }
end
done = true
end
@@ -179,10 +171,17 @@ local function composecharacters(tfmdata)
local dx = (c_urx - a_urx - a_llx + c_llx)/2
local dd = (c_urx - c_llx)*italicfactor
if a_ury < 0 then
- if trace_combining_visualize then
- t.commands = { push, {"right", dx-dd}, red, acc_t, black, pop, chr_t }
+ local right = rightcommand[dx-dd]
+ if trace_visualize then
+ t.commands = {
+ push, right, red, acc_t,
+ black, pop, chr_t,
+ }
else
- t.commands = { push, {"right", dx-dd}, acc_t, pop, chr_t }
+ t.commands = {
+ push, right, acc_t, pop,
+ chr_t,
+ }
end
elseif c_ury > a_lly then -- messy test
local dy
@@ -214,27 +213,46 @@ local function composecharacters(tfmdata)
else
dy = - deltaxheight + extraxheight
end
- if trace_combining_visualize then
- t.commands = { push, { "right", dx+dd }, { "down", dy }, green, acc_t, black, pop, chr_t }
+ local right = rightcommand[dx+dd]
+ local down = downcommand[dy]
+ if trace_visualize then
+ t.commands = {
+ push, right, down, green,
+ acc_t, black, pop, chr_t,
+ }
else
- t.commands = { push, { "right", dx+dd }, { "down", dy }, acc_t, pop, chr_t }
+ t.commands = {
+ push, right, down, acc_t,
+ pop, chr_t,
+ }
end
else
- if trace_combining_visualize then
- t.commands = { push, { "right", dx+dd }, blue, acc_t, black, pop, chr_t }
+ local right = rightcommand[dx+dd]
+ if trace_visualize then
+ t.commands = {
+ push, right, blue, acc_t,
+ black, pop, chr_t,
+ }
else
- t.commands = { push, { "right", dx+dd }, acc_t, pop, chr_t }
+ t.commands = {
+ push, right, acc_t, pop,
+ chr_t,
+ }
end
end
end
else
- t.commands = { chr_t } -- else index mess
+ t.commands = {
+ chr_t, -- else index mess
+ }
end
else
- if trace_combining_define then
- report_combining("%C becomes simplified %C",i,chr)
+ if trace_define then
+ report("%C becomes simplified %C",i,chr)
end
- t.commands = { chr_t } -- else index mess
+ t.commands = {
+ chr_t, -- else index mess
+ }
end
done = true
characters[i] = t
@@ -254,7 +272,7 @@ local function composecharacters(tfmdata)
end
end
-local compose_specification = {
+local specification = {
name = "compose",
description = "additional composed characters",
manipulators = {
@@ -263,75 +281,71 @@ local compose_specification = {
}
}
-registerotffeature(compose_specification)
-registerafmfeature(compose_specification)
+registerotffeature(specification)
+registerafmfeature(specification)
-vf.helpers.composecharacters = composecharacters
+addotffeature {
+ name = "char-ligatures",
+ type = "ligature",
+ data = characters.splits.char,
+ order = { "char-ligatures" },
+ prepend = true,
+}
--- This installs the builder into the regular virtual font builder,
--- which only makes sense as demo.
+addotffeature {
+ name = "compat-ligatures",
+ type = "ligature",
+ data = characters.splits.compat,
+ order = { "compat-ligatures" },
+ prepend = true,
+}
-commands["compose.trace.enable"] = function()
- trace_combining_visualize = true
-end
+registerotffeature {
+ name = 'char-ligatures',
+ description = 'unicode char specials to ligatures',
+}
-commands["compose.trace.disable"] = function()
- trace_combining_visualize = false
-end
+registerotffeature {
+ name = 'compat-ligatures',
+ description = 'unicode compat specials to ligatures',
+}
-commands["compose.force.enable"] = function()
- force_combining = true
-end
+do
-commands["compose.force.disable"] = function()
- force_combining = false
-end
+ -- This installs the builder into the regular virtual font builder,
+ -- which only makes sense as demo.
-commands["compose.trace.set"] = function(g,v)
- if v[2] == nil then
- trace_combining_visualize = true
- else
- trace_combining_visualize = v[2]
- end
-end
-
-commands["compose.apply"] = function(g,v)
- composecharacters(g)
-end
+ local vf = handlers.vf
+ local commands = vf.combiner.commands
--- vf builder
+ vf.helpers.composecharacters = composecharacters
--- { "pdf", "origin", "q " .. s .. " 0 0 " .. s .. " 0 0 cm" },
--- { "pdf", "origin", "q 1 0 0 1 " .. -w .. " " .. -h .. " cm" },
--- { "pdf", "origin", "/Fm\XX\space Do" },
--- { "pdf", "origin", "Q" },
--- { "pdf", "origin", "Q" },
+ commands["compose.trace.enable"] = function()
+ trace_visualize = true
+ end
--- new and experimental
+ commands["compose.trace.disable"] = function()
+ trace_visualize = false
+ end
-local everywhere = { ["*"] = { ["*"] = true } } -- or: { ["*"] = { "*" } }
-local noflags = { }
+ commands["compose.force.enable"] = function()
+ force_combining = true
+ end
-local char_specification = {
- type = "ligature",
- features = everywhere,
- data = characters.splits.char,
- order = { "char-ligatures" },
- flags = noflags,
- prepend = true,
-}
+ commands["compose.force.disable"] = function()
+ force_combining = false
+ end
-local compat_specification = {
- type = "ligature",
- features = everywhere,
- data = characters.splits.compat,
- order = { "compat-ligatures" },
- flags = noflags,
- prepend = true,
-}
+ commands["compose.trace.set"] = function(g,v)
+ if v[2] == nil then
+ trace_visualize = true
+ else
+ trace_visualize = v[2]
+ end
+ end
-otf.addfeature("char-ligatures", char_specification) -- xlig (extra)
-otf.addfeature("compat-ligatures",compat_specification) -- plig (pseudo)
+ commands["compose.apply"] = function(g,v)
+ composecharacters(g)
+ end
-registerotffeature { name = 'char-ligatures', description = 'unicode char specials to ligatures' }
-registerotffeature { name = 'compat-ligatures', description = 'unicode compat specials to ligatures' }
+end
diff --git a/tex/context/base/mkiv/font-fea.mkvi b/tex/context/base/mkiv/font-fea.mkvi
index 5f65543ab..4a5356090 100644
--- a/tex/context/base/mkiv/font-fea.mkvi
+++ b/tex/context/base/mkiv/font-fea.mkvi
@@ -368,11 +368,19 @@
% \doifelsecurrentfonthasfeature{crap}{YES}{NO}
% \doifelsecurrentfonthasfeature{kern}{YES}{NO}
-\def\doifelsecurrentfonthasfeature#feature%
+\def\doifelsecurrentfonthasfeature#feature% expandable
{\clf_doifelsecurrentfonthasfeature{#feature}}
\let\doifcurrentfonthasfeatureelse\doifelsecurrentfonthasfeature
+\def\doifelsefontfeature#feature% expandable
+ {\clf_doifelsefontfeature{#feature}}
+
+\let\doiffontfeatureelse\doifelsefontfeature
+
+\def\doifunknownfontfeature#feature% expandable
+ {\clf_doifunknownfontfeature{#feature}}
+
% new:
\clf_registerlanguagefeatures
diff --git a/tex/context/base/mkiv/font-imp-dimensions.lua b/tex/context/base/mkiv/font-imp-dimensions.lua
new file mode 100644
index 000000000..e658ef7bb
--- /dev/null
+++ b/tex/context/base/mkiv/font-imp-dimensions.lua
@@ -0,0 +1,113 @@
+if not modules then modules = { } end modules ['font-imp-dimensions'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv and hand-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local next, type, tonumber = next, type, tonumber
+
+local fonts = fonts
+local utilities = utilities
+
+local helpers = fonts.helpers
+local prependcommands = helpers.prependcommands
+local charcommand = helpers.commands.char
+local rightcommand = helpers.commands.right
+
+local handlers = fonts.handlers
+local otf = handlers.otf
+local afm = handlers.afm
+
+local registerotffeature = otf.features.register
+local registerafmfeature = afm.features.register
+
+local settings_to_array = utilities.parsers.settings_to_array
+local gettexdimen = tex.getdimen
+
+-- For Wolfgang Schuster:
+--
+-- \definefontfeature[thisway][default][script=hang,language=zhs,dimensions={2,2,2}]
+-- \definedfont[file:kozminpr6nregular*thisway]
+
+local function initialize(tfmdata,key,value)
+ if type(value) == "string" and value ~= "" then
+ local characters = tfmdata.characters
+ local parameters = tfmdata.parameters
+ local emwidth = parameters.quad
+ local exheight = parameters.xheight
+ local newwidth = false
+ local newheight = false
+ local newdepth = false
+ if value == "strut" then
+ newheight = gettexdimen("strutht")
+ newdepth = gettexdimen("strutdp")
+ elseif value == "mono" then
+ newwidth = emwidth
+ else
+ local spec = settings_to_array(value)
+ newwidth = tonumber(spec[1])
+ newheight = tonumber(spec[2])
+ newdepth = tonumber(spec[3])
+ if newwidth then newwidth = newwidth * emwidth end
+ if newheight then newheight = newheight * exheight end
+ if newdepth then newdepth = newdepth * exheight end
+ end
+ if newwidth or newheight or newdepth then
+ for unicode, character in next, characters do
+ local oldwidth = character.width
+ local oldheight = character.height
+ local olddepth = character.depth
+ local width = newwidth or oldwidth or 0
+ local height = newheight or oldheight or 0
+ local depth = newdepth or olddepth or 0
+ if oldwidth ~= width or oldheight ~= height or olddepth ~= depth then
+ character.width = width
+ character.height = height
+ character.depth = depth
+ if oldwidth ~= width then
+ local commands = character.commands
+ local hshift = rightcommand[(width - oldwidth) / 2]
+ if commands then
+ character.commands = prependcommands (
+ commands,
+ hshift
+ )
+ else
+ character.commands = {
+ hshift,
+ charcommand[unicode],
+ }
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+local specification = {
+ name = "dimensions",
+ description = "force dimensions",
+ manipulators = {
+ base = initialize,
+ node = initialize,
+ }
+}
+
+registerotffeature(specification)
+registerafmfeature(specification)
+
+local function initialize(tfmdata,value)
+ tfmdata.properties.realdimensions = value and true
+end
+
+registerotffeature {
+ name = "realdimensions",
+ description = "accept negative dimenions",
+ initializers = {
+ base = initialize,
+ node = initialize,
+ }
+}
diff --git a/tex/context/base/mkiv/font-imp-effects.lua b/tex/context/base/mkiv/font-imp-effects.lua
new file mode 100644
index 000000000..a5e04500c
--- /dev/null
+++ b/tex/context/base/mkiv/font-imp-effects.lua
@@ -0,0 +1,397 @@
+if not modules then modules = { } end modules ['font-imp-effects'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv and hand-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo: pickup from goodies: if type(effect) then ...
+
+local next, type, tonumber = next, type, tonumber
+local is_boolean = string.is_boolean
+
+local fonts = fonts
+
+local handlers = fonts.handlers
+local registerotffeature = handlers.otf.features.register
+local registerafmfeature = handlers.afm.features.register
+
+local settings_to_hash = utilities.parsers.settings_to_hash_colon_too
+
+local helpers = fonts.helpers
+local prependcommands = helpers.prependcommands
+local charcommand = helpers.commands.char
+local rightcommand = helpers.commands.right
+local upcommand = helpers.commands.up
+local dummycommand = helpers.commands.dummy
+
+----- constructors = fonts.constructors
+----- getmathparameter = constructors.getmathparameter
+----- setmathparameter = constructors.setmathparameter
+
+local report_effect = logs.reporter("fonts","effect")
+local report_slant = logs.reporter("fonts","slant")
+local report_extend = logs.reporter("fonts","extend")
+local report_squeeze = logs.reporter("fonts","squeeze")
+
+local trace = false
+
+trackers.register("fonts.effect", function(v) trace = v end)
+trackers.register("fonts.slant", function(v) trace = v end)
+trackers.register("fonts.extend", function(v) trace = v end)
+trackers.register("fonts.squeeze",function(v) trace = v end)
+
+local function initializeslant(tfmdata,value)
+ value = tonumber(value)
+ if not value then
+ value = 0
+ elseif value > 1 then
+ value = 1
+ elseif value < -1 then
+ value = -1
+ end
+ if trace then
+ report_slant("applying %0.3f",value)
+ end
+ tfmdata.parameters.slantfactor = value
+end
+
+local specification = {
+ name = "slant",
+ description = "slant glyphs",
+ initializers = {
+ base = initializeslant,
+ node = initializeslant,
+ }
+}
+
+registerotffeature(specification)
+registerafmfeature(specification)
+
+local function initializeextend(tfmdata,value)
+ value = tonumber(value)
+ if not value then
+ value = 0
+ elseif value > 10 then
+ value = 10
+ elseif value < -10 then
+ value = -10
+ end
+ if trace then
+ report_extend("applying %0.3f",value)
+ end
+ tfmdata.parameters.extendfactor = value
+end
+
+local specification = {
+ name = "extend",
+ description = "scale glyphs horizontally",
+ initializers = {
+ base = initializeextend,
+ node = initializeextend,
+ }
+}
+
+registerotffeature(specification)
+registerafmfeature(specification)
+
+local function initializesqueeze(tfmdata,value)
+ value = tonumber(value)
+ if not value then
+ value = 0
+ elseif value > 10 then
+ value = 10
+ elseif value < -10 then
+ value = -10
+ end
+ if trace then
+ report_squeeze("applying %0.3f",value)
+ end
+ tfmdata.parameters.squeezefactor = value
+end
+
+local specification = {
+ name = "squeeze",
+ description = "scale glyphs vertically",
+ initializers = {
+ base = initializesqueeze,
+ node = initializesqueeze,
+ }
+}
+
+registerotffeature(specification)
+registerafmfeature(specification)
+
+local effects = {
+ inner = 0,
+ normal = 0,
+ outer = 1,
+ outline = 1,
+ both = 2,
+ hidden = 3,
+}
+
+local function initializeeffect(tfmdata,value)
+ local spec
+ if type(value) == "number" then
+ spec = { width = value }
+ else
+ spec = settings_to_hash(value)
+ end
+ local effect = spec.effect or "both"
+ local width = tonumber(spec.width) or 0
+ local mode = effects[effect]
+ if not mode then
+ report_effect("invalid effect %a",effect)
+ elseif width == 0 and mode == 0 then
+ report_effect("invalid width %a for effect %a",width,effect)
+ else
+ local parameters = tfmdata.parameters
+ local properties = tfmdata.properties
+ parameters.mode = mode
+ parameters.width = width * 1000
+ if is_boolean(spec.auto) == true then
+ local squeeze = 1 - width/20
+ local average = (1 - squeeze) * width * 100
+ spec.squeeze = squeeze
+ spec.extend = 1 + width/2
+ spec.wdelta = average
+ spec.hdelta = average/2
+ spec.ddelta = average/2
+ spec.vshift = average/2
+ end
+ local factor = tonumber(spec.factor) or 0
+ local hfactor = tonumber(spec.hfactor) or factor
+ local vfactor = tonumber(spec.vfactor) or factor
+ local delta = tonumber(spec.delta) or 1
+ local wdelta = tonumber(spec.wdelta) or delta
+ local hdelta = tonumber(spec.hdelta) or delta
+ local ddelta = tonumber(spec.ddelta) or hdelta
+ local vshift = tonumber(spec.vshift) or 0
+ local slant = spec.slant
+ local extend = spec.extend
+ local squeeze = spec.squeeze
+ if slant then
+ initializeslant(tfmdata,slant)
+ end
+ if extend then
+ initializeextend(tfmdata,extend)
+ end
+ if squeeze then
+ initializesqueeze(tfmdata,squeeze)
+ end
+ properties.effect = {
+ effect = effect,
+ width = width,
+ factor = factor,
+ hfactor = hfactor,
+ vfactor = vfactor,
+ wdelta = wdelta,
+ hdelta = hdelta,
+ ddelta = ddelta,
+ vshift = vshift,
+ slant = tfmdata.parameters.slantfactor,
+ extend = tfmdata.parameters.extendfactor,
+ squeeze = tfmdata.parameters.squeezefactor,
+ }
+ end
+end
+
+local rules = {
+ "RadicalRuleThickness",
+ "OverbarRuleThickness",
+ "FractionRuleThickness",
+ "UnderbarRuleThickness",
+}
+
+-- local commands = char.commands
+-- if commands then
+-- local command = commands[1]
+-- if command and command[1] == "right" then
+-- commands[1] = rightcommand[command[2]-snap]
+-- end
+-- end
+
+local function setmathparameters(tfmdata,characters,mathparameters,dx,dy,squeeze)
+ if delta ~= 0 then
+ for i=1,#rules do
+ local name = rules[i]
+ local value = mathparameters[name]
+ if value then
+ mathparameters[name] = (squeeze or 1) * (value + dx)
+ end
+ end
+ end
+end
+
+local function setmathcharacters(tfmdata,characters,mathparameters,dx,dy,squeeze,wdelta,hdelta,ddelta)
+
+ local function wdpatch(char)
+ if wsnap ~= 0 then
+ char.width = char.width + wdelta/2
+ end
+ end
+
+ local function htpatch(char)
+ if hsnap ~= 0 then
+ local height = char.height
+ if height then
+ char.height = char.height + 2 * dy
+ end
+ end
+ end
+
+ local character = characters[0x221A]
+
+ if character then
+ local char = character
+ local next = character.next
+ wdpatch(char)
+ htpatch(char)
+ while next do
+ char = characters[next]
+ wdpatch(char)
+ htpatch(char)
+ next = char.next
+ end
+ if char then
+ local v = char.vert_variants
+ if v then
+ local top = v[#v]
+ if top then
+ htpatch(characters[top.glyph])
+ end
+ end
+ end
+ end
+end
+
+local function manipulateeffect(tfmdata)
+ local effect = tfmdata.properties.effect
+ if effect then
+ local characters = tfmdata.characters
+ local parameters = tfmdata.parameters
+ local mathparameters = tfmdata.mathparameters
+ local multiplier = effect.width * 100
+ local factor = parameters.factor
+ local hfactor = parameters.hfactor
+ local vfactor = parameters.vfactor
+ local wdelta = effect.wdelta * hfactor * multiplier
+ local hdelta = effect.hdelta * vfactor * multiplier
+ local ddelta = effect.ddelta * vfactor * multiplier
+ local vshift = effect.vshift * vfactor * multiplier
+ local squeeze = effect.squeeze
+ local hshift = wdelta -- / 2
+ local dx = multiplier * vfactor
+ local dy = vshift
+ local factor = (1 + effect.factor) * factor
+ local hfactor = (1 + effect.hfactor) * hfactor
+ local vfactor = (1 + effect.vfactor) * vfactor
+ local vshift = vshift ~= 0 and upcommand[vshift] or false
+ for unicode, character in next, characters do
+ local oldwidth = character.width
+ local oldheight = character.height
+ local olddepth = character.depth
+ if oldwidth and oldwidth > 0 then
+ character.width = oldwidth + wdelta
+ local commands = character.commands
+ local hshift = rightcommand[hshift]
+ if vshift then
+ if commands then
+ prependcommands ( commands,
+ hshift,
+ vshift
+ )
+ else
+ character.commands = {
+ hshift,
+ vshift,
+ charcommand[unicode]
+ }
+ end
+ else
+ if commands then
+ prependcommands ( commands,
+ hshift
+ )
+ else
+ character.commands = {
+ hshift,
+ charcommand[unicode]
+ }
+ end
+ end
+ end
+ if oldheight and oldheight > 0 then
+ character.height = oldheight + hdelta
+ end
+ if olddepth and olddepth > 0 then
+ character.depth = olddepth + ddelta
+ end
+ end
+ if mathparameters then
+ setmathparameters(tfmdata,characters,mathparameters,dx,dy,squeeze)
+ setmathcharacters(tfmdata,characters,mathparameters,dx,dy,squeeze,wdelta,hdelta,ddelta)
+ end
+ parameters.factor = factor
+ parameters.hfactor = hfactor
+ parameters.vfactor = vfactor
+ if trace then
+ report_effect("applying")
+ report_effect(" effect : %s", effect.effect)
+ report_effect(" width : %s => %s", effect.width, multiplier)
+ report_effect(" factor : %s => %s", effect.factor, factor )
+ report_effect(" hfactor : %s => %s", effect.hfactor,hfactor)
+ report_effect(" vfactor : %s => %s", effect.vfactor,vfactor)
+ report_effect(" wdelta : %s => %s", effect.wdelta, wdelta)
+ report_effect(" hdelta : %s => %s", effect.hdelta, hdelta)
+ report_effect(" ddelta : %s => %s", effect.ddelta, ddelta)
+ end
+ end
+end
+
+local specification = {
+ name = "effect",
+ description = "apply effects to glyphs",
+ initializers = {
+ base = initializeeffect,
+ node = initializeeffect,
+ },
+ manipulators = {
+ base = manipulateeffect,
+ node = manipulateeffect,
+ },
+}
+
+registerotffeature(specification)
+registerafmfeature(specification)
+
+local function initializeoutline(tfmdata,value)
+ value = tonumber(value)
+ if not value then
+ value = 0
+ else
+ value = tonumber(value) or 0
+ end
+ local parameters = tfmdata.parameters
+ local properties = tfmdata.properties
+ parameters.mode = effects.outline
+ parameters.width = value * 1000
+ properties.effect = {
+ effect = effect,
+ width = width,
+ }
+end
+
+local specification = {
+ name = "outline",
+ description = "outline glyphs",
+ initializers = {
+ base = initializeoutline,
+ node = initializeoutline,
+ }
+}
+
+registerotffeature(specification)
+registerafmfeature(specification)
diff --git a/tex/context/base/mkiv/font-imp-italics.lua b/tex/context/base/mkiv/font-imp-italics.lua
new file mode 100644
index 000000000..aace899c5
--- /dev/null
+++ b/tex/context/base/mkiv/font-imp-italics.lua
@@ -0,0 +1,147 @@
+if not modules then modules = { } end modules ['font-imp-italics'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv and hand-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local next = next
+
+local fonts = fonts
+local handlers = fonts.handlers
+local registerotffeature = handlers.otf.features.register
+local registerafmfeature = handlers.afm.features.register
+
+local function initialize(tfmdata,key,value)
+ for unicode, character in next, tfmdata.characters do
+ local olditalic = character.italic
+ if olditalic and olditalic ~= 0 then
+ character.width = character.width + olditalic
+ character.italic = 0
+ end
+ end
+end
+
+local specification = {
+ name = "italicwidths",
+ description = "add italic to width",
+ manipulators = {
+ base = initialize,
+ node = initialize, -- only makes sense for math
+ }
+}
+
+registerotffeature(specification)
+registerafmfeature(specification)
+
+local function initialize(tfmdata,value) -- hm, always value
+ if value then
+ -- the magic 40 and it formula come from Dohyun Kim but we might need another guess
+ local parameters = tfmdata.parameters
+ local italicangle = parameters.italicangle
+ if italicangle and italicangle ~= 0 then
+ local properties = tfmdata.properties
+ local factor = tonumber(value) or 1
+ properties.hasitalics = true
+ properties.autoitalicamount = factor * (parameters.uwidth or 40)/2
+ end
+ end
+end
+
+local specification = {
+ name = "itlc",
+ description = "italic correction",
+ initializers = {
+ base = initialize,
+ node = initialize,
+ }
+}
+
+registerotffeature(specification)
+registerafmfeature(specification)
+
+if context then
+
+ local function initialize(tfmdata,value) -- yes no delay
+ tfmdata.properties.textitalics = toboolean(value)
+ end
+
+ local specification = {
+ name = "textitalics",
+ description = "use alternative text italic correction",
+ initializers = {
+ base = initialize,
+ node = initialize,
+ }
+ }
+
+ registerotffeature(specification)
+ registerafmfeature(specification)
+
+end
+
+-- no longer used
+
+if context then
+
+ -- local function initializemathitalics(tfmdata,value) -- yes no delay
+ -- tfmdata.properties.mathitalics = toboolean(value)
+ -- end
+ --
+ -- local specification = {
+ -- name = "mathitalics",
+ -- description = "use alternative math italic correction",
+ -- initializers = {
+ -- base = initializemathitalics,
+ -- node = initializemathitalics,
+ -- }
+ -- }
+ --
+ -- registerotffeature(specification)
+ -- registerafmfeature(specification)
+
+end
+
+-- -- also not used, only when testing
+
+if context then
+
+ local letter = characters.is_letter
+ local always = true
+
+ local function collapseitalics(tfmdata,key,value)
+ local threshold = value == true and 100 or tonumber(value)
+ if threshold and threshold > 0 then
+ if threshold > 100 then
+ threshold = 100
+ end
+ for unicode, data in next, tfmdata.characters do
+ if always or letter[unicode] or letter[data.unicode] then
+ local italic = data.italic
+ if italic and italic ~= 0 then
+ local width = data.width
+ if width and width ~= 0 then
+ local delta = threshold * italic / 100
+ data.width = width + delta
+ data.italic = italic - delta
+ end
+ end
+ end
+ end
+ end
+ end
+
+ local dimensions_specification = {
+ name = "collapseitalics",
+ description = "collapse italics",
+ manipulators = {
+ base = collapseitalics,
+ node = collapseitalics,
+ }
+ }
+
+ registerotffeature(dimensions_specification)
+ registerafmfeature(dimensions_specification)
+
+end
diff --git a/tex/context/base/mkiv/font-imp-ligatures.lua b/tex/context/base/mkiv/font-imp-ligatures.lua
new file mode 100644
index 000000000..091eb5d4b
--- /dev/null
+++ b/tex/context/base/mkiv/font-imp-ligatures.lua
@@ -0,0 +1,136 @@
+if not modules then modules = { } end modules ['font-imp-ligatures'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local lpegmatch = lpeg.match
+local utfsplit = utf.split
+local settings_to_array = utilities.parsers.settings_to_array
+
+local fonts = fonts
+local otf = fonts.handlers.otf
+local registerotffeature = otf.features.register
+local addotffeature = otf.addfeature
+
+-- This is a quick and dirty hack.
+
+local lookups = { }
+local protect = { }
+local revert = { }
+local zwjchar = 0x200C
+local zwj = { zwjchar }
+
+addotffeature {
+ name = "blockligatures",
+ type = "chainsubstitution",
+ nocheck = true, -- because there is no 0x200C in the font
+ prepend = true, -- make sure we do it early
+ future = true, -- avoid nilling due to no steps yet
+ lookups = {
+ {
+ type = "multiple",
+ data = lookups,
+ },
+ },
+ data = {
+ rules = protect,
+ }
+}
+
+addotffeature {
+ name = "blockligatures",
+ type = "chainsubstitution",
+ nocheck = true, -- because there is no 0x200C in the font
+ append = true, -- this is done late
+ overload = false, -- we don't want to overload the previous definition
+ lookups = {
+ {
+ type = "ligature",
+ data = lookups,
+ },
+ },
+ data = {
+ rules = revert,
+ }
+}
+
+registerotffeature {
+ name = 'blockligatures',
+ description = 'block certain ligatures',
+}
+
+local splitter = lpeg.splitat(":")
+
+local function blockligatures(str)
+
+ local t = settings_to_array(str)
+
+ for i=1,#t do
+ local ti = t[i]
+ local before, current, after = lpegmatch(splitter,ti)
+ if current and after then -- before is returned when no match
+ -- experimental joke
+ if before then
+ before = utfsplit(before)
+ for i=1,#before do
+ before[i] = { before[i] }
+ end
+ end
+ if current then
+ current = utfsplit(current)
+ end
+ if after then
+ after = utfsplit(after)
+ for i=1,#after do
+ after[i] = { after[i] }
+ end
+ end
+ else
+ before = nil
+ current = utfsplit(ti)
+ after = nil
+ end
+ if #current > 1 then
+ local one = current[1]
+ local two = current[2]
+ lookups[one] = { one, zwjchar }
+ local one = { one }
+ local two = { two }
+ local new = #protect + 1
+ protect[new] = {
+ before = before,
+ current = { one, two },
+ after = after,
+ lookups = { 1 }, -- not shared !
+ }
+ revert[new] = {
+ -- before = before,
+ current = { one, zwj },
+ -- after = { two, unpack(after) },
+ after = { two },
+ lookups = { 1 }, -- not shared !
+ }
+ end
+ end
+end
+
+-- blockligatures("\0\0")
+
+otf.helpers.blockligatures = blockligatures
+
+-- blockligatures("fi,ff")
+-- blockligatures("fl")
+-- blockligatures("u:fl:age")
+
+if context then
+
+ interfaces.implement {
+ name = "blockligatures",
+ arguments = "string",
+ actions = blockligatures,
+ }
+
+end
diff --git a/tex/context/base/mkiv/font-imp-math.lua b/tex/context/base/mkiv/font-imp-math.lua
new file mode 100644
index 000000000..3a82c2a9e
--- /dev/null
+++ b/tex/context/base/mkiv/font-imp-math.lua
@@ -0,0 +1,79 @@
+if not modules then modules = { } end modules ['font-imp-math'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv and hand-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local next, type, tonumber = next, type, tonumber
+
+local fonts = fonts
+local helpers = fonts.helpers
+local registerotffeature = fonts.handlers.otf.features.register
+
+local setmetatableindex = table.setmetatableindex
+
+-- requested for latex but not supported unless really needed in context:
+--
+-- registerotffeature {
+-- name = "ignoremathconstants",
+-- description = "ignore math constants table",
+-- initializers = {
+-- base = function(tfmdata,value)
+-- if value then
+-- tfmdata.mathparameters = nil
+-- end
+-- end
+-- }
+-- }
+
+-- tfmdata.properties.mathnolimitsmode = tonumber(value) or 0
+
+local splitter = lpeg.splitat(",",tonumber)
+local lpegmatch = lpeg.match
+
+local function initialize(tfmdata,value)
+ local mathparameters = tfmdata.mathparameters
+ if mathparameters then
+ local sup, sub
+ if type(value) == "string" then
+ sup, sub = lpegmatch(splitter,value)
+ if not sup then
+ sub, sup = 0, 0
+ elseif not sub then
+ sub, sup = sup, 0
+ end
+ elseif type(value) == "number" then
+ sup, sub = 0, value
+ end
+ if sup then
+ mathparameters.NoLimitSupFactor = sup
+ end
+ if sub then
+ mathparameters.NoLimitSubFactor = sub
+ end
+ end
+end
+
+registerotffeature {
+ name = "mathnolimitsmode",
+ description = "influence nolimits placement",
+ initializers = {
+ base = initialize,
+ node = initialize,
+ }
+}
+
+local function initialize(tfmdata,value)
+ tfmdata.properties.nostackmath = value and true
+end
+
+registerotffeature {
+ name = "nostackmath",
+ description = "disable math stacking mechanism",
+ initializers = {
+ base = initialize,
+ node = initialize,
+ }
+}
diff --git a/tex/context/base/mkiv/font-imp-notused.lua b/tex/context/base/mkiv/font-imp-notused.lua
new file mode 100644
index 000000000..1c78db7aa
--- /dev/null
+++ b/tex/context/base/mkiv/font-imp-notused.lua
@@ -0,0 +1,166 @@
+if not modules then modules = { } end modules ['font-imp-notused'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv and hand-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- local next = next
+-- local utfbyte = utf.byte
+--
+-- local fonts = fonts
+--
+-- local handlers = fonts.handlers
+-- local otf = handlers.otf
+-- local afm = handlers.afm
+--
+-- local registerotffeature = otf.features.register
+-- local registerafmfeature = afm.features.register
+
+-- local function initialize(tfmdata)
+-- local resources = tfmdata.resources
+-- local gposfeatures = resources.features.gpos
+-- local characters = tfmdata.characters
+-- local descriptions = tfmdata.descriptions
+-- local sequences = resources.sequences
+-- local coverage = { }
+-- local units = tfmdata.shared.rawdata.metadata.units
+-- for k, v in next, characters do
+-- local w = descriptions[k].width
+-- local d = units - w
+-- coverage[k] = { -d/2, 0, units, 0 }
+-- end
+-- local f = { dflt = { dflt = true } }
+-- local s = #sequences + 1
+-- local t = {
+-- features = { fakemono = f },
+-- flags = { false, false, false, false },
+-- index = s,
+-- name = "p_s_" .. s,
+-- nofsteps = 1,
+-- order = { "fakemono" },
+-- skiphash = false,
+-- type = "gpos_single",
+-- steps = {
+-- {
+-- format = "single",
+-- coverage = coverage,
+-- }
+-- }
+-- }
+-- gposfeatures["fakemono"] = f
+-- sequences[s] = t
+-- end
+--
+-- registerotffeature {
+-- name = "fakemono",
+-- description = "fake monospaced",
+-- initializers = {
+-- node = initialize,
+-- },
+-- }
+
+-- -- for notosans but not general
+--
+-- local v_local = interfaces and interfaces.variables and interfaces.variables["local"] or "local"
+--
+-- local function initialize(tfmdata,key,value)
+-- local characters = tfmdata.characters
+-- local parameters = tfmdata.parameters
+-- local oldchar = 32
+-- local newchar = 32
+-- if value == "locl" or value == v_local then
+-- newchar = fonts.handlers.otf.getsubstitution(tfmdata,oldchar,"locl",true) or oldchar
+-- elseif value == true then
+-- -- use normal space
+-- elseif value then
+-- newchar = utfbyte(value)
+-- else
+-- return
+-- end
+-- local newchar = newchar and characters[newchar]
+-- local newspace = newchar and newchar.width
+-- if newspace > 0 then
+-- parameters.space = newspace
+-- parameters.space_stretch = newspace/2
+-- parameters.space_shrink = newspace/3
+-- parameters.extra_space = parameters.space_shrink
+-- end
+-- end
+--
+-- registerotffeature {
+-- name = 'space', -- true|false|locl|character
+-- description = 'space settings',
+-- manipulators = {
+-- base = initialize,
+-- node = initialize,
+-- }
+-- }
+
+-- -- historic stuff, move from font-ota (handled differently, typo-rep)
+--
+-- local delete_node = nodes.delete
+-- local fontdata = fonts.hashes.identifiers
+--
+-- local nodecodes = nodes.nodecodes
+-- local glyph_code = nodecodes.glyph
+--
+-- local strippables = allocate()
+-- fonts.strippables = strippables
+--
+-- strippables.joiners = table.tohash {
+-- 0x200C, -- zwnj
+-- 0x200D, -- zwj
+-- }
+--
+-- strippables.all = table.tohash {
+-- 0x000AD, 0x017B4, 0x017B5, 0x0200B, 0x0200C, 0x0200D, 0x0200E, 0x0200F, 0x0202A, 0x0202B,
+-- 0x0202C, 0x0202D, 0x0202E, 0x02060, 0x02061, 0x02062, 0x02063, 0x0206A, 0x0206B, 0x0206C,
+-- 0x0206D, 0x0206E, 0x0206F, 0x0FEFF, 0x1D173, 0x1D174, 0x1D175, 0x1D176, 0x1D177, 0x1D178,
+-- 0x1D179, 0x1D17A, 0xE0001, 0xE0020, 0xE0021, 0xE0022, 0xE0023, 0xE0024, 0xE0025, 0xE0026,
+-- 0xE0027, 0xE0028, 0xE0029, 0xE002A, 0xE002B, 0xE002C, 0xE002D, 0xE002E, 0xE002F, 0xE0030,
+-- 0xE0031, 0xE0032, 0xE0033, 0xE0034, 0xE0035, 0xE0036, 0xE0037, 0xE0038, 0xE0039, 0xE003A,
+-- 0xE003B, 0xE003C, 0xE003D, 0xE003E, 0xE003F, 0xE0040, 0xE0041, 0xE0042, 0xE0043, 0xE0044,
+-- 0xE0045, 0xE0046, 0xE0047, 0xE0048, 0xE0049, 0xE004A, 0xE004B, 0xE004C, 0xE004D, 0xE004E,
+-- 0xE004F, 0xE0050, 0xE0051, 0xE0052, 0xE0053, 0xE0054, 0xE0055, 0xE0056, 0xE0057, 0xE0058,
+-- 0xE0059, 0xE005A, 0xE005B, 0xE005C, 0xE005D, 0xE005E, 0xE005F, 0xE0060, 0xE0061, 0xE0062,
+-- 0xE0063, 0xE0064, 0xE0065, 0xE0066, 0xE0067, 0xE0068, 0xE0069, 0xE006A, 0xE006B, 0xE006C,
+-- 0xE006D, 0xE006E, 0xE006F, 0xE0070, 0xE0071, 0xE0072, 0xE0073, 0xE0074, 0xE0075, 0xE0076,
+-- 0xE0077, 0xE0078, 0xE0079, 0xE007A, 0xE007B, 0xE007C, 0xE007D, 0xE007E, 0xE007F,
+-- }
+--
+-- strippables[true] = strippables.joiners
+--
+-- local function processformatters(head,font)
+-- local subset = fontdata[font].shared.features.formatters
+-- local vector = subset and strippables[subset]
+-- if vector then
+-- local current, done = head, false
+-- while current do
+-- if current.id == glyph_code and current.subtype<256 and current.font == font then
+-- local char = current.char
+-- if vector[char] then
+-- head, current = delete_node(head,current)
+-- done = true
+-- else
+-- current = current.next
+-- end
+-- else
+-- current = current.next
+-- end
+-- end
+-- return head, done
+-- else
+-- return head, false
+-- end
+-- end
+--
+-- registerotffeature {
+-- name = "formatters",
+-- description = "hide formatting characters",
+-- methods = {
+-- base = processformatters,
+-- node = processformatters,
+-- }
+-- }
diff --git a/tex/context/base/mkiv/font-imp-properties.lua b/tex/context/base/mkiv/font-imp-properties.lua
new file mode 100644
index 000000000..8cd22af69
--- /dev/null
+++ b/tex/context/base/mkiv/font-imp-properties.lua
@@ -0,0 +1,128 @@
+if not modules then modules = { } end modules ['font-imp-properties'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv and hand-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local next, type, tonumber, select = next, type, tonumber, select
+local byte, find, formatters = string.byte, string.find, string.formatters
+local utfchar = utf.char
+local sortedhash, sortedkeys, sort = table.sortedhash, table.sortedkeys, table.sort
+local insert = table.insert
+
+local context = context
+local fonts = fonts
+local utilities = utilities
+
+local helpers = fonts.helpers
+
+local handlers = fonts.handlers
+local hashes = fonts.hashes
+local otf = handlers.otf
+local afm = handlers.afm
+
+local registerotffeature = otf.features.register
+local registerafmfeature = afm.features.register
+
+local fontdata = hashes.identifiers
+local fontproperties = hashes.properties
+
+local constructors = fonts.constructors
+local getprivate = constructors.getprivate
+
+local allocate = utilities.storage.allocate
+local family_font = node.family_font
+
+local setmetatableindex = table.setmetatableindex
+
+local implement = interfaces.implement
+
+do
+
+ local P, lpegpatterns, lpegmatch = lpeg.P, lpeg.patterns, lpeg.match
+
+ local amount, stretch, shrink, extra
+
+ local factor = lpegpatterns.unsigned
+ local space = lpegpatterns.space
+ local pattern = (
+ (factor / function(n) amount = tonumber(n) or amount end)
+ + (P("+") + P("plus" )) * space^0 * (factor / function(n) stretch = tonumber(n) or stretch end)
+ + (P("-") + P("minus")) * space^0 * (factor / function(n) shrink = tonumber(n) or shrink end)
+ + ( P("extra")) * space^0 * (factor / function(n) extra = tonumber(n) or extra end)
+ + space^1
+ )^1
+
+ local function initialize(tfmdata,key,value)
+ local characters = tfmdata.characters
+ local parameters = tfmdata.parameters
+ if type(value) == "string" then
+ local emwidth = parameters.quad
+ amount, stretch, shrink, extra = 0, 0, 0, false
+ lpegmatch(pattern,value)
+ if not extra then
+ if shrink ~= 0 then
+ extra = shrink
+ elseif stretch ~= 0 then
+ extra = stretch
+ else
+ extra = amount
+ end
+ end
+ parameters.space = amount * emwidth
+ parameters.space_stretch = stretch * emwidth
+ parameters.space_shrink = shrink * emwidth
+ parameters.extra_space = extra * emwidth
+ end
+ end
+
+ -- 1.1 + 1.2 - 1.3 minus 1.4 plus 1.1 extra 1.4 -- last one wins
+
+ registerotffeature {
+ name = "spacing",
+ description = "space settings",
+ manipulators = {
+ base = initialize,
+ node = initialize,
+ }
+ }
+
+end
+
+do
+
+ local function initialize(tfmdata,value)
+ local properties = tfmdata.properties
+ if properties then
+ properties.identity = value == "vertical" and "vertical" or "horizontal"
+ end
+ end
+
+ registerotffeature {
+ name = "identity",
+ description = "set font identity",
+ initializers = {
+ base = initialize,
+ node = initialize,
+ }
+ }
+
+ local function initialize(tfmdata,value)
+ local properties = tfmdata.properties
+ if properties then
+ properties.writingmode = value == "vertical" and "vertical" or "horizontal"
+ end
+ end
+
+ registerotffeature {
+ name = "writingmode",
+ description = "set font direction",
+ initializers = {
+ base = initialize,
+ node = initialize,
+ }
+ }
+
+end
diff --git a/tex/context/base/mkiv/font-imp-quality.lua b/tex/context/base/mkiv/font-imp-quality.lua
new file mode 100644
index 000000000..dc063f28a
--- /dev/null
+++ b/tex/context/base/mkiv/font-imp-quality.lua
@@ -0,0 +1,477 @@
+if not modules then modules = { } end modules ['font-imp-quality'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv and hand-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local next, type, tonumber = next, type, tonumber
+local byte = string.byte
+local insert = table.insert
+
+local fonts = fonts
+local utilities = utilities
+
+local handlers = fonts.handlers
+local otf = handlers.otf
+local afm = handlers.afm
+local registerotffeature = otf.features.register
+local registerafmfeature = afm.features.register
+
+local allocate = utilities.storage.allocate
+local getparameters = utilities.parsers.getparameters
+
+local implement = interfaces and interfaces.implement
+
+local trace_protrusion = false trackers.register("fonts.protrusion", function(v) trace_protrusion = v end)
+local trace_expansion = false trackers.register("fonts.expansion", function(v) trace_expansion = v end)
+
+local report_expansions = logs.reporter("fonts","expansions")
+local report_protrusions = logs.reporter("fonts","protrusions")
+
+-- -- -- -- -- --
+-- shared
+-- -- -- -- -- --
+
+local function get_class_and_vector(tfmdata,value,where) -- "expansions"
+ local g_where = tfmdata.goodies and tfmdata.goodies[where]
+ local f_where = fonts[where]
+ local g_classes = g_where and g_where.classes
+ local f_classes = f_where and f_where.classes
+ local class = (g_classes and g_classes[value]) or (f_classes and f_classes[value])
+ if class then
+ local class_vector = class.vector
+ local g_vectors = g_where and g_where.vectors
+ local f_vectors = f_where and f_where.vectors
+ local vector = (g_vectors and g_vectors[class_vector]) or (f_vectors and f_vectors[class_vector])
+ return class, vector
+ end
+end
+
+-- -- -- -- -- --
+-- expansion (hz)
+-- -- -- -- -- --
+
+local expansions = fonts.expansions or allocate()
+
+fonts.expansions = expansions
+
+local classes = expansions.classes or allocate()
+local vectors = expansions.vectors or allocate()
+
+expansions.classes = classes
+expansions.vectors = vectors
+
+-- beware, pdftex itself uses percentages * 10
+--
+-- todo: get rid of byte() here
+
+classes.preset = { stretch = 2, shrink = 2, step = .5, factor = 1 }
+
+classes['quality'] = {
+ stretch = 2, shrink = 2, step = .5, vector = 'default', factor = 1
+}
+
+vectors['default'] = {
+ [byte('A')] = 0.5, [byte('B')] = 0.7, [byte('C')] = 0.7, [byte('D')] = 0.5, [byte('E')] = 0.7,
+ [byte('F')] = 0.7, [byte('G')] = 0.5, [byte('H')] = 0.7, [byte('K')] = 0.7, [byte('M')] = 0.7,
+ [byte('N')] = 0.7, [byte('O')] = 0.5, [byte('P')] = 0.7, [byte('Q')] = 0.5, [byte('R')] = 0.7,
+ [byte('S')] = 0.7, [byte('U')] = 0.7, [byte('W')] = 0.7, [byte('Z')] = 0.7,
+ [byte('a')] = 0.7, [byte('b')] = 0.7, [byte('c')] = 0.7, [byte('d')] = 0.7, [byte('e')] = 0.7,
+ [byte('g')] = 0.7, [byte('h')] = 0.7, [byte('k')] = 0.7, [byte('m')] = 0.7, [byte('n')] = 0.7,
+ [byte('o')] = 0.7, [byte('p')] = 0.7, [byte('q')] = 0.7, [byte('s')] = 0.7, [byte('u')] = 0.7,
+ [byte('w')] = 0.7, [byte('z')] = 0.7,
+ [byte('2')] = 0.7, [byte('3')] = 0.7, [byte('6')] = 0.7, [byte('8')] = 0.7, [byte('9')] = 0.7,
+}
+
+vectors['quality'] = vectors['default'] -- metatable ?
+
+local function initialize(tfmdata,value)
+ if value then
+ local class, vector = get_class_and_vector(tfmdata,value,"expansions")
+ if class then
+ if vector then
+ local stretch = class.stretch or 0
+ local shrink = class.shrink or 0
+ local step = class.step or 0
+ local factor = class.factor or 1
+ if trace_expansion then
+ report_expansions("setting class %a, vector %a, factor %a, stretch %a, shrink %a, step %a",
+ value,class.vector,factor,stretch,shrink,step)
+ end
+ tfmdata.parameters.expansion = {
+ stretch = 10 * stretch,
+ shrink = 10 * shrink,
+ step = 10 * step,
+ factor = factor,
+ }
+ local data = characters and characters.data
+ for i, chr in next, tfmdata.characters do
+ local v = vector[i]
+ if data and not v then -- we could move the data test outside (needed for plain)
+ local d = data[i]
+ if d then
+ local s = d.shcode
+ if not s then
+ -- sorry
+ elseif type(s) == "table" then
+ v = ((vector[s[1]] or 0) + (vector[s[#s]] or 0)) / 2
+ else
+ v = vector[s] or 0
+ end
+ end
+ end
+ if v and v ~= 0 then
+ chr.expansion_factor = v*factor
+ else -- can be option
+ chr.expansion_factor = factor
+ end
+ end
+ elseif trace_expansion then
+ report_expansions("unknown vector %a in class %a",class.vector,value)
+ end
+ elseif trace_expansion then
+ report_expansions("unknown class %a",value)
+ end
+ end
+end
+
+local specification = {
+ name = "expansion",
+ description = "apply hz optimization",
+ initializers = {
+ base = initialize,
+ node = initialize,
+ }
+}
+
+registerotffeature(specification)
+registerafmfeature(specification)
+
+fonts.goodies.register("expansions", function(...) return fonts.goodies.report("expansions", trace_expansion, ...) end)
+
+if context then
+
+ implement {
+ name = "setupfontexpansion",
+ arguments = "2 strings",
+ actions = function(class,settings) getparameters(classes,class,'preset',settings) end
+ }
+
+end
+
+-- -- -- -- -- --
+-- protrusion
+-- -- -- -- -- --
+
+fonts.protrusions = allocate()
+local protrusions = fonts.protrusions
+
+protrusions.classes = allocate()
+protrusions.vectors = allocate()
+
+local classes = protrusions.classes
+local vectors = protrusions.vectors
+
+-- the values need to be revisioned
+
+classes.preset = { factor = 1, left = 1, right = 1 }
+
+classes['pure'] = {
+ vector = 'pure', factor = 1
+}
+classes['punctuation'] = {
+ vector = 'punctuation', factor = 1
+}
+classes['alpha'] = {
+ vector = 'alpha', factor = 1
+}
+classes['quality'] = {
+ vector = 'quality', factor = 1
+}
+
+vectors['pure'] = {
+
+ [0x002C] = { 0, 1 }, -- comma
+ [0x002E] = { 0, 1 }, -- period
+ [0x003A] = { 0, 1 }, -- colon
+ [0x003B] = { 0, 1 }, -- semicolon
+ [0x002D] = { 0, 1 }, -- hyphen
+ [0x00AD] = { 0, 1 }, -- also hyphen
+ [0x2013] = { 0, 0.50 }, -- endash
+ [0x2014] = { 0, 0.33 }, -- emdash
+ [0x3001] = { 0, 1 }, -- ideographic comma 、
+ [0x3002] = { 0, 1 }, -- ideographic full stop 。
+ [0x060C] = { 0, 1 }, -- arabic comma ،
+ [0x061B] = { 0, 1 }, -- arabic semicolon ؛
+ [0x06D4] = { 0, 1 }, -- arabic full stop ۔
+
+}
+
+vectors['punctuation'] = {
+
+ [0x003F] = { 0, 0.20 }, -- ?
+ [0x00BF] = { 0, 0.20 }, -- ¿
+ [0x0021] = { 0, 0.20 }, -- !
+ [0x00A1] = { 0, 0.20 }, -- ¡
+ [0x0028] = { 0.05, 0 }, -- (
+ [0x0029] = { 0, 0.05 }, -- )
+ [0x005B] = { 0.05, 0 }, -- [
+ [0x005D] = { 0, 0.05 }, -- ]
+ [0x002C] = { 0, 0.70 }, -- comma
+ [0x002E] = { 0, 0.70 }, -- period
+ [0x003A] = { 0, 0.50 }, -- colon
+ [0x003B] = { 0, 0.50 }, -- semicolon
+ [0x002D] = { 0, 0.70 }, -- hyphen
+ [0x00AD] = { 0, 0.70 }, -- also hyphen
+ [0x2013] = { 0, 0.30 }, -- endash
+ [0x2014] = { 0, 0.20 }, -- emdash
+ [0x060C] = { 0, 0.70 }, -- arabic comma
+ [0x061B] = { 0, 0.50 }, -- arabic semicolon
+ [0x06D4] = { 0, 0.70 }, -- arabic full stop
+ [0x061F] = { 0, 0.20 }, -- ؟
+
+ -- todo: left and right quotes: .5 double, .7 single
+
+ [0x2039] = { 0.70, 0.70 }, -- left single guillemet ‹
+ [0x203A] = { 0.70, 0.70 }, -- right single guillemet ›
+ [0x00AB] = { 0.50, 0.50 }, -- left guillemet «
+ [0x00BB] = { 0.50, 0.50 }, -- right guillemet »
+
+ [0x2018] = { 0.70, 0.70 }, -- left single quotation mark ‘
+ [0x2019] = { 0, 0.70 }, -- right single quotation mark ’
+ [0x201A] = { 0.70, 0 }, -- single low-9 quotation mark ,
+ [0x201B] = { 0.70, 0 }, -- single high-reversed-9 quotation mark ‛
+ [0x201C] = { 0.50, 0.50 }, -- left double quotation mark “
+ [0x201D] = { 0, 0.50 }, -- right double quotation mark ”
+ [0x201E] = { 0.50, 0 }, -- double low-9 quotation mark „
+ [0x201F] = { 0.50, 0 }, -- double high-reversed-9 quotation mark ‟
+
+}
+
+vectors['alpha'] = {
+
+ [byte("A")] = { .05, .05 },
+ [byte("F")] = { 0, .05 },
+ [byte("J")] = { .05, 0 },
+ [byte("K")] = { 0, .05 },
+ [byte("L")] = { 0, .05 },
+ [byte("T")] = { .05, .05 },
+ [byte("V")] = { .05, .05 },
+ [byte("W")] = { .05, .05 },
+ [byte("X")] = { .05, .05 },
+ [byte("Y")] = { .05, .05 },
+
+ [byte("k")] = { 0, .05 },
+ [byte("r")] = { 0, .05 },
+ [byte("t")] = { 0, .05 },
+ [byte("v")] = { .05, .05 },
+ [byte("w")] = { .05, .05 },
+ [byte("x")] = { .05, .05 },
+ [byte("y")] = { .05, .05 },
+
+}
+
+vectors['quality'] = table.merged(
+ vectors['punctuation'],
+ vectors['alpha']
+)
+
+-- As this is experimental code, users should not depend on it. The implications are still
+-- discussed on the ConTeXt Dev List and we're not sure yet what exactly the spec is (the
+-- next code is tested with a gyre font patched by / fea file made by Khaled Hosny). The
+-- double trick should not be needed it proper hanging punctuation is used in which case
+-- values < 1 can be used.
+--
+-- preferred (in context, usine vectors):
+--
+-- \definefontfeature[whatever][default][mode=node,protrusion=quality]
+--
+-- using lfbd and rtbd, with possibibility to enable only one side :
+--
+-- \definefontfeature[whocares][default][mode=node,protrusion=yes, opbd=yes,script=latn]
+-- \definefontfeature[whocares][default][mode=node,protrusion=right,opbd=yes,script=latn]
+--
+-- idem, using multiplier
+--
+-- \definefontfeature[whocares][default][mode=node,protrusion=2,opbd=yes,script=latn]
+-- \definefontfeature[whocares][default][mode=node,protrusion=double,opbd=yes,script=latn]
+--
+-- idem, using named feature file (less frozen):
+--
+-- \definefontfeature[whocares][default][mode=node,protrusion=2,opbd=yes,script=latn,featurefile=texgyrepagella-regularxx.fea]
+
+classes['double'] = { -- for testing opbd
+ factor = 2, left = 1, right = 1,
+}
+
+local function map_opbd_onto_protrusion(tfmdata,value,opbd)
+ local characters = tfmdata.characters
+ local descriptions = tfmdata.descriptions
+ local properties = tfmdata.properties
+ local resources = tfmdata.resources
+ local rawdata = tfmdata.shared.rawdata
+ local lookuphash = rawdata.lookuphash
+ local lookuptags = resources.lookuptags
+ local script = properties.script
+ local language = properties.language
+ local done, factor, left, right = false, 1, 1, 1
+ local class = classes[value]
+ if class then
+ factor = class.factor or 1
+ left = class.left or 1
+ right = class.right or 1
+ else
+ factor = tonumber(value) or 1
+ end
+ if opbd ~= "right" then
+ local validlookups, lookuplist = otf.collectlookups(rawdata,"lfbd",script,language)
+ if validlookups then
+ for i=1,#lookuplist do
+ local lookup = lookuplist[i]
+ local steps = lookup.steps
+ if steps then
+ if trace_protrusion then
+ report_protrusions("setting left using lfbd")
+ end
+ for i=1,#steps do
+ local step = steps[i]
+ local coverage = step.coverage
+ if coverage then
+ for k, v in next, coverage do
+ -- local p = - v[3] / descriptions[k].width-- or 1 ~= 0 too but the same
+ local p = - (v[1] / 1000) * factor * left
+ characters[k].left_protruding = p
+ if trace_protrusion then
+ report_protrusions("lfbd -> %C -> %p",k,p)
+ end
+ end
+ end
+ end
+ done = true
+ end
+ end
+ end
+ end
+ if opbd ~= "left" then
+ local validlookups, lookuplist = otf.collectlookups(rawdata,"rtbd",script,language)
+ if validlookups then
+ for i=1,#lookuplist do
+ local lookup = lookuplist[i]
+ local steps = lookup.steps
+ if steps then
+ if trace_protrusion then
+ report_protrusions("setting right using rtbd")
+ end
+ for i=1,#steps do
+ local step = steps[i]
+ local coverage = step.coverage
+ if coverage then
+ for k, v in next, coverage do
+ -- local p = v[3] / descriptions[k].width -- or 3
+ local p = (v[1] / 1000) * factor * right
+ characters[k].right_protruding = p
+ if trace_protrusion then
+ report_protrusions("rtbd -> %C -> %p",k,p)
+ end
+ end
+ end
+ end
+ end
+ done = true
+ end
+ end
+ end
+end
+
+-- The opbd test is just there because it was discussed on the context development list. However,
+-- the mentioned fxlbi.otf font only has some kerns for digits. So, consider this feature not supported
+-- till we have a proper test font.
+
+local function initialize(tfmdata,value)
+ if value then
+ local opbd = tfmdata.shared.features.opbd
+ if opbd then
+ -- possible values: left right both yes no (experimental)
+ map_opbd_onto_protrusion(tfmdata,value,opbd)
+ else
+ local class, vector = get_class_and_vector(tfmdata,value,"protrusions")
+ if class then
+ if vector then
+ local factor = class.factor or 1
+ local left = class.left or 1
+ local right = class.right or 1
+ if trace_protrusion then
+ report_protrusions("setting class %a, vector %a, factor %a, left %a, right %a",
+ value,class.vector,factor,left,right)
+ end
+ local data = characters.data
+ local emwidth = tfmdata.parameters.quad
+ tfmdata.parameters.protrusion = {
+ factor = factor,
+ left = left,
+ right = right,
+ }
+ for i, chr in next, tfmdata.characters do
+ local v, pl, pr = vector[i], nil, nil
+ if v then
+ pl, pr = v[1], v[2]
+ else
+ local d = data[i]
+ if d then
+ local s = d.shcode
+ if not s then
+ -- sorry
+ elseif type(s) == "table" then
+ local vl, vr = vector[s[1]], vector[s[#s]]
+ if vl then pl = vl[1] end
+ if vr then pr = vr[2] end
+ else
+ v = vector[s]
+ if v then
+ pl, pr = v[1], v[2]
+ end
+ end
+ end
+ end
+ if pl and pl ~= 0 then
+ chr.left_protruding = left *pl*factor
+ end
+ if pr and pr ~= 0 then
+ chr.right_protruding = right*pr*factor
+ end
+ end
+ elseif trace_protrusion then
+ report_protrusions("unknown vector %a in class %a",class.vector,value)
+ end
+ elseif trace_protrusion then
+ report_protrusions("unknown class %a",value)
+ end
+ end
+ end
+end
+
+local specification = {
+ name = "protrusion",
+ description = "l/r margin character protrusion",
+ initializers = {
+ base = initialize,
+ node = initialize,
+ }
+}
+
+registerotffeature(specification)
+registerafmfeature(specification)
+
+fonts.goodies.register("protrusions", function(...) return fonts.goodies.report("protrusions", trace_protrusion, ...) end)
+
+if context then
+
+ implement {
+ name = "setupfontprotrusion",
+ arguments = "2 strings",
+ actions = function(class,settings) getparameters(classes,class,'preset',settings) end
+ }
+
+end
diff --git a/tex/context/base/mkiv/font-imp-reorder.lua b/tex/context/base/mkiv/font-imp-reorder.lua
new file mode 100644
index 000000000..250aa47c6
--- /dev/null
+++ b/tex/context/base/mkiv/font-imp-reorder.lua
@@ -0,0 +1,172 @@
+if not modules then modules = { } end modules ['font-imp-reorder'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv and hand-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local next = next
+local find = string.find
+local sortedhash, sortedkeys, sort = table.sortedhash, table.sortedkeys, table.sort
+
+local fonts = fonts
+local otf = fonts.handlers.otf
+local registerotffeature = otf.features.register
+
+-- This is a rather special test-only feature that I added for the sake of testing
+-- Idris's husayni. We wanted to know if uniscribe obeys the order of lookups in a
+-- font, in spite of what the description of handling arabic suggests. And indeed,
+-- mixed-in lookups of other features (like all these ss* in husayni) are handled
+-- the same in context as in uniscribe. If one sets reorderlookups=arab then we sort
+-- according to the "assumed" order so e.g. the ss* move to after the standard
+-- features. The observed difference in rendering is an indication that uniscribe is
+-- quite faithful to the font (while e.g. tests with the hb plugin demonstrate some
+-- interference, apart from some hard coded init etc expectations). Anyway, it means
+-- that we're okay with the (generic) node processor. A pitfall is that in context
+-- we can actually control more, so we can trigger an analyze pass with e.g.
+-- dflt/dflt while the libraries depend on the script settings for that. Uniscribe
+-- probably also parses the string and when seeing arabic will follow a different
+-- code path, although it seems to treat all features equal.
+
+local trace_reorder = trackers.register("fonts.reorderlookups",function(v) trace_reorder = v end)
+local report_reorder = logs.reporter("fonts","reorder")
+
+local vectors = { }
+
+vectors.arab = {
+ gsub = {
+ ccmp = 1,
+ isol = 2,
+ fina = 3,
+ medi = 4,
+ init = 5,
+ rlig = 6,
+ rclt = 7,
+ calt = 8,
+ liga = 9,
+ dlig = 10,
+ cswh = 11,
+ mset = 12,
+ },
+ gpos = {
+ curs = 1,
+ kern = 2,
+ mark = 3,
+ mkmk = 4,
+ },
+}
+
+local function compare(a,b)
+ local what_a = a.what
+ local what_b = b.what
+ if what_a ~= what_b then
+ return a.index < b.index
+ end
+ local when_a = a.when
+ local when_b = b.when
+ if when_a == when_b then
+ return a.index < b.index
+ else
+ return when_a < when_b
+ end
+end
+
+function otf.reorderlookups(tfmdata,vector)
+ local order = vectors[vector]
+ if not order then
+ return
+ end
+ local oldsequences = tfmdata.resources.sequences
+ if oldsequences then
+ local sequences = { }
+ for i=1,#oldsequences do
+ sequences[i] = oldsequences[i]
+ end
+ for i=1,#sequences do
+ local s = sequences[i]
+ local features = s.features
+ local kind = s.type
+ local index = s.index
+ if features then
+ local when
+ local what
+ for feature in sortedhash(features) do
+ if not what then
+ what = find(kind,"^gsub") and "gsub" or "gpos"
+ end
+ local newwhen = order[what][feature]
+ if not newwhen then
+ -- skip
+ elseif not when then
+ when = newwhen
+ elseif newwhen < when then
+ when = newwhen
+ end
+ end
+ s.ondex = s.index
+ s.index = i
+ s.what = what == "gsub" and 1 or 2
+ s.when = when or 99
+ else
+ s.ondex = s.index
+ s.index = i
+ s.what = 1
+ s.when = 99
+ end
+ end
+ sort(sequences,compare)
+ local swapped = 0
+ for i=1,#sequences do
+ local sequence = sequences[i]
+ local features = sequence.features
+ if features then
+ local index = sequence.index
+ if index ~= i then
+ swapped = swapped + 1
+ end
+ if trace_reorder then
+ if swapped == 1 then
+ report_reorder()
+ report_reorder("start swapping lookups in font %!font:name!",tfmdata)
+ report_reorder()
+ report_reorder("gsub order: % t",table.swapped(order.gsub))
+ report_reorder("gpos order: % t",table.swapped(order.gpos))
+ report_reorder()
+ end
+ report_reorder("%03i : lookup %03i, type %s, sorted %2i, moved %s, % t",
+ i,index,sequence.what == 1 and "gsub" or "gpos",sequence.when or 99,
+ (index > i and "-") or (index < i and "+") or "=",sortedkeys(features))
+ end
+ end
+ sequence.what = nil
+ sequence.when = nil
+ sequence.index = sequence.ondex
+ end
+ if swapped > 0 then
+ if trace_reorder then
+ report_reorder()
+ report_reorder("stop swapping lookups, %i lookups swapped",swapped)
+ report_reorder()
+ end
+ tfmdata.shared.reorderedsequences = sequences
+ end
+ end
+end
+
+-- maybe delay till ra is filled
+
+local function initialize(tfmdata,key,value)
+ if value then
+ otf.reorderlookups(tfmdata,value)
+ end
+end
+
+registerotffeature {
+ name = "reorderlookups",
+ description = "reorder lookups",
+ manipulators = {
+ base = initialize,
+ node = initialize,
+ }
+}
diff --git a/tex/context/base/mkiv/font-imp-tex.lua b/tex/context/base/mkiv/font-imp-tex.lua
new file mode 100644
index 000000000..b4b9a7b69
--- /dev/null
+++ b/tex/context/base/mkiv/font-imp-tex.lua
@@ -0,0 +1,144 @@
+if not modules then modules = { } end modules ['font-imp-tex'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local next = next
+
+local fonts = fonts
+local otf = fonts.handlers.otf
+local registerotffeature = otf.features.register
+local addotffeature = otf.addfeature
+
+-- tlig (we need numbers for some fonts so ...)
+
+local specification = {
+ type = "ligature",
+ order = { "tlig" },
+ prepend = true,
+ data = {
+ -- endash = "hyphen hyphen",
+ -- emdash = "hyphen hyphen hyphen",
+ [0x2013] = { 0x002D, 0x002D },
+ [0x2014] = { 0x002D, 0x002D, 0x002D },
+ -- quotedblleft = "quoteleft quoteleft",
+ -- quotedblright = "quoteright quoteright",
+ -- quotedblleft = "grave grave",
+ -- quotedblright = "quotesingle quotesingle",
+ -- quotedblbase = "comma comma",
+ },
+}
+
+addotffeature("tlig",specification)
+
+registerotffeature {
+ -- this makes it a known feature (in tables)
+ name = "tlig",
+ description = "tex ligatures",
+}
+
+-- trep
+
+local specification = {
+ type = "substitution",
+ order = { "trep" },
+ prepend = true,
+ data = {
+ -- [0x0022] = 0x201D,
+ [0x0027] = 0x2019,
+ -- [0x0060] = 0x2018,
+ },
+}
+
+addotffeature("trep",specification)
+
+registerotffeature {
+ -- this makes it a known feature (in tables)
+ name = "trep",
+ description = "tex replacements",
+}
+
+-- some day this will be moved to font-imp-scripts.lua
+
+-- anum
+
+local anum_arabic = {
+ [0x0030] = 0x0660,
+ [0x0031] = 0x0661,
+ [0x0032] = 0x0662,
+ [0x0033] = 0x0663,
+ [0x0034] = 0x0664,
+ [0x0035] = 0x0665,
+ [0x0036] = 0x0666,
+ [0x0037] = 0x0667,
+ [0x0038] = 0x0668,
+ [0x0039] = 0x0669,
+}
+
+local anum_persian = {
+ [0x0030] = 0x06F0,
+ [0x0031] = 0x06F1,
+ [0x0032] = 0x06F2,
+ [0x0033] = 0x06F3,
+ [0x0034] = 0x06F4,
+ [0x0035] = 0x06F5,
+ [0x0036] = 0x06F6,
+ [0x0037] = 0x06F7,
+ [0x0038] = 0x06F8,
+ [0x0039] = 0x06F9,
+}
+
+local function valid(data)
+ local features = data.resources.features
+ if features then
+ for k, v in next, features do
+ for k, v in next, v do
+ if v.arab then
+ return true
+ end
+ end
+ end
+ end
+end
+
+local specification = {
+ {
+ type = "substitution",
+ features = { arab = { urd = true, dflt = true } },
+ order = { "anum" },
+ data = anum_arabic,
+ valid = valid,
+ },
+ {
+ type = "substitution",
+ features = { arab = { urd = true } },
+ order = { "anum" },
+ data = anum_persian,
+ valid = valid,
+ },
+}
+
+addotffeature("anum",specification)
+
+registerotffeature {
+ -- this makes it a known feature (in tables)
+ name = "anum",
+ description = "arabic digits",
+}
+
+-- -- example:
+--
+-- fonts.handlers.otf.addfeature {
+-- name = "hangulfix",
+-- type = "substitution",
+-- features = { ["hang"] = { ["*"] = true } },
+-- data = {
+-- [0x1160] = 0x119E,
+-- },
+-- order = { "hangulfix" },
+-- flags = { },
+-- prepend = true,
+-- })
diff --git a/tex/context/base/mkiv/font-imp-tracing.lua b/tex/context/base/mkiv/font-imp-tracing.lua
new file mode 100644
index 000000000..e6de494df
--- /dev/null
+++ b/tex/context/base/mkiv/font-imp-tracing.lua
@@ -0,0 +1,171 @@
+if not modules then modules = { } end modules ['font-imp-tracing'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv and hand-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local next, type = next, type
+local formatters = string.formatters
+
+local fonts = fonts
+
+local handlers = fonts.handlers
+local registerotffeature = handlers.otf.features.register
+local registerafmfeature = handlers.afm.features.register
+
+local settings_to_array = utilities.parsers.settings_to_array
+local setmetatableindex = table.setmetatableindex
+
+local helpers = fonts.helpers
+local prependcommands = helpers.prependcommands
+local charcommand = helpers.commands.char
+
+local variables = interfaces.variables
+
+local v_background = variables.background
+local v_frame = variables.frame
+local v_empty = variables.empty
+local v_none = variables.none
+
+-- for zhichu chen (see mailing list archive): we might add a few more variants
+-- in due time
+--
+-- \definefontfeature[boxed][default][boundingbox=yes] % paleblue
+--
+-- maybe:
+--
+-- \definecolor[DummyColor][s=.75,t=.5,a=1] {\DummyColor test} \nopdfcompression
+--
+-- local gray = { "pdf", "origin", "/Tr1 gs .75 g" }
+-- local black = { "pdf", "origin", "/Tr0 gs 0 g" }
+
+-- boundingbox={yes|background|frame|empty|<color>}
+
+local bp = number.dimenfactors.bp
+local r = 16384 * bp -- 65536 // 4
+local f_1 = formatters["%.6F w 0 %.6F %.6F %.6F re f"]
+local f_2 = formatters["[] 0 d 0 J %.6F w %.6F %.6F %.6F %.6F re S"]
+
+local backcache = setmetatableindex(function(t,h)
+ local h = h * bp
+ local v = setmetatableindex(function(t,d)
+ local d = d * bp
+ local v = setmetatableindex(function(t,w)
+ local v = { "pdf", "origin", f_1(r,-d,w*bp,h+d) }
+ t[w] = v
+ return v
+ end)
+ t[d] = v
+ return v
+ end)
+ t[h] = v
+ return v
+end)
+
+local forecache = setmetatableindex(function(t,h)
+ local h = h * bp
+ local v = setmetatableindex(function(t,d)
+ local d = d * bp
+ local v = setmetatableindex(function(t,w)
+ -- the frame goes through the boundingbox
+ local v = { "pdf", "origin", f_2(r,r/2,-d+r/2,w*bp-r,h+d-r) }
+ t[w] = v
+ return v
+ end)
+ t[d] = v
+ return v
+ end)
+ t[h] = v
+ return v
+end)
+
+local startcolor = nil
+local stopcolor = nil
+
+local function initialize(tfmdata,key,value)
+ if value then
+ if not backcolors then
+ local vfspecials = backends.pdf.tables.vfspecials
+ startcolor = vfspecials.startcolor
+ stopcolor = vfspecials.stopcolor
+ end
+ local characters = tfmdata.characters
+ local rulecache = backcache
+ local showchar = true
+ local color = "palegray"
+ if type(value) == "string" then
+ value = settings_to_array(value)
+ for i=1,#value do
+ local v = value[i]
+ if v == v_frame then
+ rulecache = forecache
+ elseif v == v_background then
+ rulecache = backcache
+ elseif v == v_empty then
+ showchar = false
+ elseif v == v_none then
+ color = nil
+ else
+ color = v
+ end
+ end
+ end
+ local gray = color and startcolor(color) or nil
+ local black = gray and stopcolor or nil
+ for unicode, character in next, characters do
+ local width = character.width or 0
+ local height = character.height or 0
+ local depth = character.depth or 0
+ local rule = rulecache[height][depth][width]
+ if showchar then
+ local commands = character.commands
+ if commands then
+ if gray then
+ character.commands = prependcommands (
+ commands, gray, rule, black
+ )
+ else
+ character.commands = prependcommands (
+ commands, rule
+ )
+ end
+ else
+ local char = charcommand[unicode]
+ if gray then
+ character.commands = {
+ gray, rule, black, char
+ }
+ else
+ character.commands = {
+ rule, char
+ }
+ end
+ end
+ else
+ if gray then
+ character.commands = {
+ gray, rule, black
+ }
+ else
+ character.commands = {
+ rule
+ }
+ end
+ end
+ end
+ end
+end
+
+local specification = {
+ name = "boundingbox",
+ description = "show boundingbox",
+ manipulators = {
+ base = initialize,
+ node = initialize,
+ }
+}
+
+registerotffeature(specification)
+registerafmfeature(specification)
diff --git a/tex/context/base/mkiv/font-imp-unicode.lua b/tex/context/base/mkiv/font-imp-unicode.lua
new file mode 100644
index 000000000..9e1e3465e
--- /dev/null
+++ b/tex/context/base/mkiv/font-imp-unicode.lua
@@ -0,0 +1,80 @@
+if not modules then modules = { } end modules ['font-imp-unicode'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv and hand-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local next = next
+
+local fonts = fonts
+local helpers = fonts.helpers
+local constructors = fonts.constructors
+local registerotffeature = fonts.handlers.otf.features.register
+
+local extraprivates = helpers.extraprivates
+local addprivate = helpers.addprivate
+
+local function initialize(tfmdata)
+ for i=1,#extraprivates do
+ local e = extraprivates[i]
+ local c = e[2](tfmdata)
+ if c then
+ addprivate(tfmdata, e[1], c)
+ end
+ end
+end
+
+constructors.newfeatures.otf.register {
+ name = "extraprivates",
+ description = "extra privates",
+ default = true,
+ manipulators = {
+ base = initialize,
+ node = initialize,
+ }
+}
+
+local tounicode = fonts.mappings.tounicode
+
+local function initialize(tfmdata,key,value)
+ if value == "ligatures" then
+ local private = fonts.constructors and fonts.constructors.privateoffset or 0xF0000
+ local collected = fonts.handlers.otf.readers.getcomponents(tfmdata.shared.rawdata)
+ if collected and next(collected)then
+ for unicode, char in next, tfmdata.characters do
+ local u = collected[unicode]
+ if u then
+ 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
+ u = u[1]
+ end
+ char.unicode = u
+ char.tounicode = tounicode(u)
+ end
+ end
+ end
+ end
+ end
+end
+
+-- forceunicodes=ligatures : aggressive lig resolving (e.g. for emoji)
+--
+-- kind of like: \enabletrackers[fonts.mapping.forceligatures]
+
+registerotffeature {
+ name = "forceunicodes",
+ description = "forceunicodes",
+ manipulators = {
+ base = initialize,
+ node = initialize,
+ }
+}
diff --git a/tex/context/base/mkiv/font-ini.mkvi b/tex/context/base/mkiv/font-ini.mkvi
index 693182919..f81d751f3 100644
--- a/tex/context/base/mkiv/font-ini.mkvi
+++ b/tex/context/base/mkiv/font-ini.mkvi
@@ -1727,7 +1727,8 @@
\font_helpers_process_style_list{\font_helpers_define_unknown_check_definitions{#body}}%
\ifconditional\c_font_defining_state
\ifconditional\c_font_defining_environment_state\else
- \showmessage\m!fonts{14}{#body}% main
+ %\showmessage\m!fonts{14}{#body}% main
+ \clf_registerunknownbodysize{#body}%
\fi
\setfalse\c_font_defining_state
\font_helpers_register_fontbody{#body}%
@@ -1741,13 +1742,6 @@
\fi
\fi}
-% \def\font_helpers_define_unknown_check_sizes#body#relativesize%
-% {\ifcsname\??fontenvironments\s!default#relativesize\endcsname % fontclass ?
-% % how \lastnamedcs here
-% \expandafter\normalizebodyfontsize\csname\??fontenvironments#body#relativesize\endcsname{\csname\??fontenvironments\s!default#relativesize\endcsname\dimexpr#body\relax}%
-% \settrue\c_font_defining_state
-% \fi}
-
\def\font_helpers_define_unknown_check_sizes#body#relativesize%
{\ifcsname\??fontenvironments\s!default#relativesize\endcsname % fontclass ?
\expandafter\normalizebodyfontsize\csname\??fontenvironments#body#relativesize\endcsname{\csname\??fontenvironments\s!default#relativesize\endcsname\dimexpr#body\relax}%
diff --git a/tex/context/base/mkiv/font-lib.mkvi b/tex/context/base/mkiv/font-lib.mkvi
index 24ab68781..7f8601f4e 100644
--- a/tex/context/base/mkiv/font-lib.mkvi
+++ b/tex/context/base/mkiv/font-lib.mkvi
@@ -26,12 +26,17 @@
% the otf font loader:
+% helpers
+
+
\registerctxluafile{font-otr}{optimize} % opentype fontloader
\registerctxluafile{font-web}{} % opentype fontloader
\registerctxluafile{font-cff}{optimize} % quadratic outlines
\registerctxluafile{font-ttf}{optimize} % cubic outlines
\registerctxluafile{font-dsp}{optimize} % ... for this one
\registerctxluafile{font-hsh}{} % hashes used by context
+\registerctxluafile{font-vfc}{}
+\registerctxluafile{font-prv}{} % needs hashes
\registerctxluafile{font-nod}{}
\registerctxluafile{font-oti}{} % otf initialization
\registerctxluafile{font-ott}{} % otf tables (first)
@@ -87,7 +92,21 @@
\registerctxluafile{font-def}{}
\registerctxluafile{font-ctx}{} % after def as it overloads
-\registerctxluafile{font-ext}{}
+% extensions, order matters
+
+\registerctxluafile{font-imp-ligatures}{}
+\registerctxluafile{font-imp-tex}{}
+\registerctxluafile{font-imp-reorder}{}
+\registerctxluafile{font-imp-properties}{}
+\registerctxluafile{font-imp-unicode}{}
+\registerctxluafile{font-imp-math}{}
+\registerctxluafile{font-imp-notused}{}
+\registerctxluafile{font-imp-effects}{}
+\registerctxluafile{font-imp-quality}{}
+\registerctxluafile{font-imp-italics}{}
+\registerctxluafile{font-imp-dimensions}{}
+\registerctxluafile{font-imp-tracing}{} % comes last!
+
\registerctxluafile{font-fbk}{}
\registerctxluafile{font-aux}{}
diff --git a/tex/context/base/mkiv/font-map.lua b/tex/context/base/mkiv/font-map.lua
index 66cf2db39..b44e20ede 100644
--- a/tex/context/base/mkiv/font-map.lua
+++ b/tex/context/base/mkiv/font-map.lua
@@ -168,55 +168,84 @@ local function tounicode16sequence(unicodes)
return concat(t)
end
-local function tounicode(unicode)
- if type(unicode) == "table" then
- local t = { }
- for l=1,#unicode do
- local u = unicode[l]
- if u < 0xD7FF or (u > 0xDFFF and u <= 0xFFFF) then
- t[l] = f_single(u)
- else
- u = u - 0x10000
- t[l] = f_double(rshift(u,10)+0xD800,u%1024+0xDC00)
- end
- end
- return concat(t)
- else
- if unicode < 0xD7FF or (unicode > 0xDFFF and unicode <= 0xFFFF) then
- return f_single(unicode)
- else
- unicode = unicode - 0x10000
- return f_double(rshift(unicode,10)+0xD800,unicode%1024+0xDC00)
- end
- end
-end
-
--- no real gain on runs
-
--- local hash = table.setmetatableindex(function(t,u)
--- local v
--- if u < 0xD7FF or (u > 0xDFFF and u <= 0xFFFF) then
--- v = f_single(u)
+-- local function tounicode(unicode)
+-- if type(unicode) == "table" then
+-- local t = { }
+-- for l=1,#unicode do
+-- local u = unicode[l]
+-- if u < 0xD7FF or (u > 0xDFFF and u <= 0xFFFF) then
+-- t[l] = f_single(u)
+-- else
+-- u = u - 0x10000
+-- t[l] = f_double(rshift(u,10)+0xD800,u%1024+0xDC00)
+-- end
+-- end
+-- return concat(t)
-- else
--- u = u - 0x10000
--- v = f_double(rshift(u,10)+0xD800,u%1024+0xDC00)
+-- if unicode < 0xD7FF or (unicode > 0xDFFF and unicode <= 0xFFFF) then
+-- return f_single(unicode)
+-- else
+-- unicode = unicode - 0x10000
+-- return f_double(rshift(unicode,10)+0xD800,unicode%1024+0xDC00)
+-- end
-- end
--- t[u] = v
--- return v
--- end)
---
--- local function tounicode(unicode,name)
+-- end
+
+local unknown = f_single(0xFFFD)
+
+-- local function tounicode(unicode)
-- if type(unicode) == "table" then
-- local t = { }
-- for l=1,#unicode do
--- t[l] = hash[unicode[l]]
+-- t[l] = tounicode(unicode[l])
-- end
-- return concat(t)
+-- elseif unicode >= 0x00E000 and unicode <= 0x00F8FF then
+-- return unknown
+-- elseif unicode >= 0x0F0000 and unicode <= 0x0FFFFF then
+-- return unknown
+-- elseif unicode >= 0x100000 and unicode <= 0x10FFFF then
+-- return unknown
+-- elseif unicode < 0xD7FF or (unicode > 0xDFFF and unicode <= 0xFFFF) then
+-- return f_single(unicode)
-- else
--- return hash[unicode]
+-- unicode = unicode - 0x10000
+-- return f_double(rshift(unicode,10)+0xD800,unicode%1024+0xDC00)
-- end
-- end
+local hash = table.setmetatableindex(function(t,k)
+ local v
+ if k >= 0x00E000 and k <= 0x00F8FF then
+ v = unknown
+ elseif k >= 0x0F0000 and k <= 0x0FFFFF then
+ v = unknown
+ elseif k >= 0x100000 and k <= 0x10FFFF then
+ v = unknown
+ elseif k < 0xD7FF or (k > 0xDFFF and k <= 0xFFFF) then
+ v = f_single(k)
+ else
+ v = k - 0x10000
+ v = f_double(rshift(k,10)+0xD800,k%1024+0xDC00)
+ end
+ t[k] = v
+ return v
+end)
+
+table.makeweak(hash)
+
+local function tounicode(unicode,name)
+ if type(unicode) == "table" then
+ local t = { }
+ for l=1,#unicode do
+ t[l] = hash[unicode[l]]
+ end
+ return concat(t)
+ else
+ return hash[unicode]
+ end
+end
+
local function fromunicode16(str)
if #str == 4 then
return tonumber(str,16)
diff --git a/tex/context/base/mkiv/font-mat.mkvi b/tex/context/base/mkiv/font-mat.mkvi
index 0134f3fe6..64810d327 100644
--- a/tex/context/base/mkiv/font-mat.mkvi
+++ b/tex/context/base/mkiv/font-mat.mkvi
@@ -263,12 +263,12 @@
\fi}
\def\font_helpers_bidirectional_mathstrategy_nop_changed
- {\textfont \c_font_fam_mr_rl\textfont \c_font_fam_mr
- \scriptfont \c_font_fam_mr_rl\scriptfont \c_font_fam_mr
- \scriptscriptfont\c_font_fam_mr_rl\scriptscriptfont\c_font_fam_mr
- \textfont \c_font_fam_mr_lr\textfont \c_font_fam_mr
+ {\textfont \c_font_fam_mr_lr\textfont \c_font_fam_mr
\scriptfont \c_font_fam_mr_lr\scriptfont \c_font_fam_mr
- \scriptscriptfont\c_font_fam_mr_lr\scriptscriptfont\c_font_fam_mr}
+ \scriptscriptfont\c_font_fam_mr_lr\scriptscriptfont\c_font_fam_mr
+ \textfont \c_font_fam_mr_rl\textfont \c_font_fam_mr
+ \scriptfont \c_font_fam_mr_rl\scriptfont \c_font_fam_mr
+ \scriptscriptfont\c_font_fam_mr_rl\scriptscriptfont\c_font_fam_mr}
\appendtoks
\ifconditional\c_font_bidirectional_mathstrategy
@@ -313,12 +313,12 @@
{\textfont \c_font_fam_mb \textfont \c_font_fam_mr
\scriptfont \c_font_fam_mb \scriptfont \c_font_fam_mr
\scriptscriptfont\c_font_fam_mb \scriptscriptfont\c_font_fam_mr
- \textfont \c_font_fam_mb_rl\textfont \c_font_fam_mr_rl
- \scriptfont \c_font_fam_mb_rl\scriptfont \c_font_fam_mr_rl
- \scriptscriptfont\c_font_fam_mb_rl\scriptscriptfont\c_font_fam_mr_rl
\textfont \c_font_fam_mb_lr\textfont \c_font_fam_mr_lr
\scriptfont \c_font_fam_mb_lr\scriptfont \c_font_fam_mr_lr
- \scriptscriptfont\c_font_fam_mb_lr\scriptscriptfont\c_font_fam_mr_lr}
+ \scriptscriptfont\c_font_fam_mb_lr\scriptscriptfont\c_font_fam_mr_lr
+ \textfont \c_font_fam_mb_rl\textfont \c_font_fam_mr_rl
+ \scriptfont \c_font_fam_mb_rl\scriptfont \c_font_fam_mr_rl
+ \scriptscriptfont\c_font_fam_mb_rl\scriptscriptfont\c_font_fam_mr_rl}
\def\font_helpers_apply_complete_bold_mathstrategy
{\ifconditional\c_font_complete_bold_mathstrategy
@@ -425,13 +425,16 @@
\ifdefined\mathdefault \else \let\mathdefault\relax \fi
+\newconditional\c_math_bold
+
\unexpanded\def\mr % math regular
{\ifmmode
\font_helpers_synchronize_math_family_mr
\else
\font_helpers_set_current_font_alternative\s!mr
\fi
- \mathdefault}
+ \mathdefault
+ \setfalse\c_math_bold}
\unexpanded\def\mb % math bold
{\ifmmode
@@ -439,12 +442,17 @@
\else
\font_helpers_set_current_font_alternative\s!mb
\fi
- \mathdefault}
+ \mathdefault
+ \settrue\c_math_bold}
\appendtoks
\font_helpers_synchronize_math_family % auto bold
\to \everymathematics
+\appendtoks
+ \ifconditional\c_math_bold\mb\fi
+\to \everymathematics
+
%D \macros
%D {bigmath,nobigmath}
%D
diff --git a/tex/context/base/mkiv/font-nod.lua b/tex/context/base/mkiv/font-nod.lua
index 2670a924b..cdceb98a2 100644
--- a/tex/context/base/mkiv/font-nod.lua
+++ b/tex/context/base/mkiv/font-nod.lua
@@ -79,7 +79,6 @@ local copy_node_list = nuts.copy_list
local hpack_node_list = nuts.hpack
local flush_node_list = nuts.flush_list
local traverse_nodes = nuts.traverse
------ traverse_id = nuts.traverse_id
local protect_glyphs = nuts.protect_glyphs
local nodepool = nuts.pool
@@ -392,8 +391,7 @@ function step_tracers.codes(i,command,space)
if w then
context.startcolor(colors[what])
context("%s:",what)
- for c in traverse_nodes(w) do
- local id = getid(c)
+ for c, id in traverse_nodes(w) do
if id == glyph_code then
showchar(c)
else
@@ -501,9 +499,12 @@ local threshold = 65536 -- 1pt
local function toutf(list,result,nofresult,stopcriterium,nostrip)
if list then
- for n in traverse_nodes(tonut(list)) do
- local c, id = isglyph(n)
- if c then
+-- for n in traverse_nodes(tonut(list)) do
+-- local c, id = isglyph(n)
+-- if c then
+ for n, id in traverse_nodes(tonut(list)) do
+ if id == glyph_code then
+ local c = getchar(n)
local components = getcomponents(n)
if components then
result, nofresult = toutf(components,result,nofresult,false,true)
diff --git a/tex/context/base/mkiv/font-ocl.lua b/tex/context/base/mkiv/font-ocl.lua
index b17cf991d..7dfcd129e 100644
--- a/tex/context/base/mkiv/font-ocl.lua
+++ b/tex/context/base/mkiv/font-ocl.lua
@@ -13,13 +13,20 @@ local round, max = math.round, math.round
local sortedkeys, sortedhash = table.sortedkeys, table.sortedhash
local setmetatableindex = table.setmetatableindex
-local formatters = string.formatters
-local tounicode = fonts.mappings.tounicode
+local formatters = string.formatters
+local tounicode = fonts.mappings.tounicode
-local otf = fonts.handlers.otf
+local helpers = fonts.helpers
-local f_color = formatters["%.3f %.3f %.3f rg"]
-local f_gray = formatters["%.3f g"]
+local charcommand = helpers.commands.char
+local rightcommand = helpers.commands.right
+local leftcommand = helpers.commands.left
+local downcommand = helpers.commands.down
+
+local otf = fonts.handlers.otf
+
+local f_color = formatters["%.3f %.3f %.3f rg"]
+local f_gray = formatters["%.3f g"]
if context then
@@ -136,7 +143,7 @@ end
-- -- only shows the first glyph in acrobat and nothing more. No problem with other
-- -- renderers.
--
--- local function initializecolr(tfmdata,kind,value) -- hm, always value
+-- local function initialize(tfmdata,kind,value) -- hm, always value
-- if value then
-- local resources = tfmdata.resources
-- local palettes = resources.colorpalettes
@@ -161,11 +168,6 @@ end
-- tfmdata.fonts = {
-- { id = 0 }
-- }
--- local widths = setmetatableindex(function(t,k)
--- local v = { "right", -k }
--- t[k] = v
--- return v
--- end)
-- --
-- local getactualtext = otf.getactualtext
-- local default = colorvalues[#colorvalues]
@@ -173,12 +175,6 @@ end
-- local actualb = { "pdf", "page", b } -- saves tables
-- local actuale = { "pdf", "page", e } -- saves tables
-- --
--- local cache = setmetatableindex(function(t,k)
--- local v = { "char", k } -- could he a weak shared hash
--- t[k] = v
--- return v
--- end)
--- --
-- for unicode, character in next, characters do
-- local description = descriptions[unicode]
-- if description then
@@ -187,7 +183,7 @@ end
-- local u = description.unicode or characters[unicode].unicode
-- local w = character.width or 0
-- local s = #colorlist
--- local goback = w ~= 0 and widths[w] or nil -- needs checking: are widths the same
+-- local goback = w ~= 0 and leftcommand[w] or nil -- needs checking: are widths the same
-- local t = {
-- start,
-- not u and actualb or { "pdf", "page", (getactualtext(tounicode(u))) }
@@ -202,7 +198,7 @@ end
-- n = n + 1 t[n] = v
-- l = v
-- end
--- n = n + 1 t[n] = cache[entry.slot]
+-- n = n + 1 t[n] = charcommand[entry.slot]
-- if s > 1 and i < s and goback then
-- n = n + 1 t[n] = goback
-- end
@@ -221,7 +217,7 @@ end
-- -- Here we have no color change in BT .. ET and more q Q pairs but even then acrobat
-- -- fails displaying the overlays correctly. Other renderers do it right.
-local function initializecolr(tfmdata,kind,value) -- hm, always value
+local function initialize(tfmdata,kind,value) -- hm, always value
if value then
local resources = tfmdata.resources
local palettes = resources.colorpalettes
@@ -246,11 +242,6 @@ local function initializecolr(tfmdata,kind,value) -- hm, always value
tfmdata.fonts = {
{ id = 0 }
}
- local widths = setmetatableindex(function(t,k)
- local v = { "right", -k }
- t[k] = v
- return v
- end)
--
local getactualtext = otf.getactualtext
local default = colorvalues[#colorvalues]
@@ -258,12 +249,6 @@ local function initializecolr(tfmdata,kind,value) -- hm, always value
local actualb = { "pdf", "page", b } -- saves tables
local actuale = { "pdf", "page", e } -- saves tables
--
- local cache = setmetatableindex(function(t,k)
- local v = { "char", k } -- could he a weak shared hash
- t[k] = v
- return v
- end)
- --
for unicode, character in next, characters do
local description = descriptions[unicode]
if description then
@@ -272,7 +257,7 @@ local function initializecolr(tfmdata,kind,value) -- hm, always value
local u = description.unicode or characters[unicode].unicode
local w = character.width or 0
local s = #colorlist
- local goback = w ~= 0 and widths[w] or nil -- needs checking: are widths the same
+ local goback = w ~= 0 and leftcommand[w] or nil -- needs checking: are widths the same
local t = {
start, -- really needed
not u and actualb or { "pdf", "page", (getactualtext(tounicode(u))) }
@@ -292,7 +277,7 @@ local function initializecolr(tfmdata,kind,value) -- hm, always value
n = n + 1 t[n] = v
l = v
end
- n = n + 1 t[n] = cache[entry.slot]
+ n = n + 1 t[n] = charcommand[entry.slot]
if s > 1 and i < s and goback then
n = n + 1 t[n] = goback
end
@@ -314,8 +299,8 @@ fonts.handlers.otf.features.register {
name = "colr",
description = "color glyphs",
manipulators = {
- base = initializecolr,
- node = initializecolr,
+ base = initialize,
+ node = initialize,
}
}
@@ -436,8 +421,8 @@ local function pdftovirtual(tfmdata,pdfshapes,kind) -- kind = sbix|svg
local dp = character.depth or 0
character.commands = {
not unicode and actualb or { "pdf", "page", (getactualtext(unicode)) },
- { "down", dp + dy * hfactor },
- { "right", dx * hfactor },
+ downcommand[dp + dy * hfactor],
+ rightcommand[dx * hfactor],
-- setcode and { "lua", setcode } or nop,
{ "image", { filename = name, width = wd, height = ht, depth = dp } },
-- nilcode and { "lua", nilcode } or nop,
diff --git a/tex/context/base/mkiv/font-otc.lua b/tex/context/base/mkiv/font-otc.lua
index 2bad62d60..fb8bf7c66 100644
--- a/tex/context/base/mkiv/font-otc.lua
+++ b/tex/context/base/mkiv/font-otc.lua
@@ -6,11 +6,10 @@ if not modules then modules = { } end modules ['font-otc'] = {
license = "see context related readme files"
}
-local format, insert, sortedkeys, tohash = string.format, table.insert, table.sortedkeys, table.tohash
+local insert, sortedkeys, sortedhash, tohash = table.insert, table.sortedkeys, table.sortedhash, table.tohash
local type, next = type, next
local lpegmatch = lpeg.match
-local utfbyte, utflen, utfsplit = utf.byte, utf.len, utf.split
-local match = string.match
+local utfbyte, utflen = utf.byte, utf.len
local sortedhash = table.sortedhash
-- we assume that the other otf stuff is loaded already
@@ -813,177 +812,6 @@ otf.enhancers.enhance = enhance
otf.enhancers.register("check extra features",enhance)
--- tlig --
-
-local tlig = { -- we need numbers for some fonts so ...
- -- endash = "hyphen hyphen",
- -- emdash = "hyphen hyphen hyphen",
- [0x2013] = { 0x002D, 0x002D },
- [0x2014] = { 0x002D, 0x002D, 0x002D },
- -- quotedblleft = "quoteleft quoteleft",
- -- quotedblright = "quoteright quoteright",
- -- quotedblleft = "grave grave",
- -- quotedblright = "quotesingle quotesingle",
- -- quotedblbase = "comma comma",
-}
-
-local tlig_specification = {
- type = "ligature",
- features = everywhere,
- data = tlig,
- order = { "tlig" },
- flags = noflags,
- prepend = true,
-}
-
-otf.addfeature("tlig",tlig_specification)
-
-registerotffeature {
- -- this makes it a known feature (in tables)
- name = 'tlig',
- description = 'tex ligatures',
-}
-
--- trep
-
-local trep = {
- -- [0x0022] = 0x201D,
- [0x0027] = 0x2019,
- -- [0x0060] = 0x2018,
-}
-
-local trep_specification = {
- type = "substitution",
- features = everywhere,
- data = trep,
- order = { "trep" },
- flags = noflags,
- prepend = true,
-}
-
-otf.addfeature("trep",trep_specification)
-
-registerotffeature {
- -- this makes it a known feature (in tables)
- name = 'trep',
- description = 'tex replacements',
-}
-
--- -- tcom (obsolete, was already not set for a while)
-
--- if characters.combined then
---
--- local tcom = { }
---
--- local function initialize()
--- characters.initialize()
--- for first, seconds in next, characters.combined do
--- for second, combination in next, seconds do
--- tcom[combination] = { first, second }
--- end
--- end
--- -- return false
--- end
---
--- local tcom_specification = {
--- type = "ligature",
--- features = everywhere,
--- data = tcom,
--- order = { "tcom" },
--- flags = noflags,
--- initialize = initialize,
--- }
---
--- otf.addfeature("tcom",tcom_specification)
---
--- registerotffeature {
--- name = 'tcom',
--- description = 'tex combinations',
--- }
---
--- end
-
--- anum
-
-local anum_arabic = {
- [0x0030] = 0x0660,
- [0x0031] = 0x0661,
- [0x0032] = 0x0662,
- [0x0033] = 0x0663,
- [0x0034] = 0x0664,
- [0x0035] = 0x0665,
- [0x0036] = 0x0666,
- [0x0037] = 0x0667,
- [0x0038] = 0x0668,
- [0x0039] = 0x0669,
-}
-
-local anum_persian = {
- [0x0030] = 0x06F0,
- [0x0031] = 0x06F1,
- [0x0032] = 0x06F2,
- [0x0033] = 0x06F3,
- [0x0034] = 0x06F4,
- [0x0035] = 0x06F5,
- [0x0036] = 0x06F6,
- [0x0037] = 0x06F7,
- [0x0038] = 0x06F8,
- [0x0039] = 0x06F9,
-}
-
-local function valid(data)
- local features = data.resources.features
- if features then
- for k, v in next, features do
- for k, v in next, v do
- if v.arab then
- return true
- end
- end
- end
- end
-end
-
-local anum_specification = {
- {
- type = "substitution",
- features = { arab = { urd = true, dflt = true } },
- order = { "anum" },
- data = anum_arabic,
- flags = noflags, -- { },
- valid = valid,
- },
- {
- type = "substitution",
- features = { arab = { urd = true } },
- order = { "anum" },
- data = anum_persian,
- flags = noflags, -- { },
- valid = valid,
- },
-}
-
-otf.addfeature("anum",anum_specification) -- todo: only when there is already an arab script feature
-
-registerotffeature {
- -- this makes it a known feature (in tables)
- name = 'anum',
- description = 'arabic digits',
-}
-
--- maybe:
-
--- fonts.handlers.otf.addfeature("hangulfix",{
--- type = "substitution",
--- features = { ["hang"] = { ["*"] = true } },
--- data = {
--- [0x1160] = 0x119E,
--- },
--- order = { "hangulfix" },
--- flags = { },
--- prepend = true,
--- })
-
-- fonts.handlers.otf.features.register {
-- name = 'hangulfix',
-- description = 'fixes for hangul',
@@ -1028,126 +856,3 @@ registerotffeature {
-- a = { b = -500 },
-- }
-- }
-
--- This is a quick and dirty hack.
-
-local lookups = { }
-local protect = { }
-local revert = { }
-local zwjchar = 0x200C
-local zwj = { zwjchar }
-
-otf.addfeature {
- name = "blockligatures",
- type = "chainsubstitution",
- nocheck = true, -- because there is no 0x200C in the font
- prepend = true, -- make sure we do it early
- future = true, -- avoid nilling due to no steps yet
- lookups = {
- {
- type = "multiple",
- data = lookups,
- },
- },
- data = {
- rules = protect,
- }
-}
-
-otf.addfeature {
- name = "blockligatures",
- type = "chainsubstitution",
- nocheck = true, -- because there is no 0x200C in the font
- append = true, -- this is done late
- overload = false, -- we don't want to overload the previous definition
- lookups = {
- {
- type = "ligature",
- data = lookups,
- },
- },
- data = {
- rules = revert,
- }
-}
-
-registerotffeature {
- name = 'blockligatures',
- description = 'block certain ligatures',
-}
-
-local settings_to_array = utilities.parsers and utilities.parsers.settings_to_array
- or function(s) return string.split(s,",") end -- for generic
-
-local splitter = lpeg.splitat(":")
-
-local function blockligatures(str)
-
- local t = settings_to_array(str)
-
- for i=1,#t do
- local ti = t[i]
- local before, current, after = lpegmatch(splitter,ti)
- if current and after then -- before is returned when no match
- -- experimental joke
- if before then
- before = utfsplit(before)
- for i=1,#before do
- before[i] = { before[i] }
- end
- end
- if current then
- current = utfsplit(current)
- end
- if after then
- after = utfsplit(after)
- for i=1,#after do
- after[i] = { after[i] }
- end
- end
- else
- before = nil
- current = utfsplit(ti)
- after = nil
- end
- if #current > 1 then
- local one = current[1]
- local two = current[2]
- lookups[one] = { one, zwjchar }
- local one = { one }
- local two = { two }
- local new = #protect + 1
- protect[new] = {
- before = before,
- current = { one, two },
- after = after,
- lookups = { 1 }, -- not shared !
- }
- revert[new] = {
- -- before = before,
- current = { one, zwj },
- -- after = { two, unpack(after) },
- after = { two },
- lookups = { 1 }, -- not shared !
- }
- end
- end
-end
-
--- blockligatures("\0\0")
-
-otf.helpers.blockligatures = blockligatures
-
--- blockligatures("fi,ff")
--- blockligatures("fl")
--- blockligatures("u:fl:age")
-
-if context then
-
- interfaces.implement {
- name = "blockligatures",
- arguments = "string",
- actions = blockligatures,
- }
-
-end
diff --git a/tex/context/base/mkiv/font-otj.lua b/tex/context/base/mkiv/font-otj.lua
index 9037939df..45a3acb7d 100644
--- a/tex/context/base/mkiv/font-otj.lua
+++ b/tex/context/base/mkiv/font-otj.lua
@@ -128,6 +128,10 @@ do if not fontkern then -- generic
return n
end
+end end
+
+do if not italickern then -- generic
+
local thekern = nuts.new("kern",3) -- italiccorrection
local setkern = nuts.setkern
local copy_node = nuts.copy_node
diff --git a/tex/context/base/mkiv/font-ott.lua b/tex/context/base/mkiv/font-ott.lua
index 59d92f40d..c9e2836d8 100644
--- a/tex/context/base/mkiv/font-ott.lua
+++ b/tex/context/base/mkiv/font-ott.lua
@@ -8,7 +8,8 @@ if not modules then modules = { } end modules ["font-ott"] = {
}
local type, next, tonumber, tostring, rawget, rawset = type, next, tonumber, tostring, rawget, rawset
-local gsub, lower, format, match = string.gsub, string.lower, string.format, string.match
+local gsub, lower, format, match, gmatch, find = string.gsub, string.lower, string.format, string.match, string.gmatch, string.find
+local sequenced = table.sequenced
local is_boolean = string.is_boolean
local setmetatableindex = table.setmetatableindex
@@ -1098,9 +1099,9 @@ function otffeatures.normalize(features)
h.script = rawget(verbosescripts,v) or (scripts[v] and v) or "dflt" -- auto adds
elseif k == "axis" then
h[k] = normalizedaxis(value)
-if not callbacks.supported.glyph_stream_provider then
- h.variableshapes = true -- for the moment
-end
+ if not callbacks.supported.glyph_stream_provider then
+ h.variableshapes = true -- for the moment
+ end
else
local uk = usedfeatures[key]
local uv = uk[value]
@@ -1113,10 +1114,23 @@ end
elseif type(value) == "string" then
local b = is_boolean(value)
if type(b) == "nil" then
+ -- we do this elsewhere
+ --
+ -- if find(value,"=") then
+ -- local t = { }
+ -- for k, v in gmatch(value,"([^%s,=]+)%s*=%s*([^%s,=]+)") do
+ -- t[k] = tonumber(v) or v
+ -- end
+ -- if next(t) then
+ -- value = sequenced(t,",")
+ -- end
+ -- end
uv = lower(value)
else
uv = b
end
+ elseif type(value) == "table" then
+ uv = sequenced(t,",")
else
uv = value
end
diff --git a/tex/context/base/mkiv/font-pre.mkiv b/tex/context/base/mkiv/font-pre.mkiv
index b49bc560e..01e580ac5 100644
--- a/tex/context/base/mkiv/font-pre.mkiv
+++ b/tex/context/base/mkiv/font-pre.mkiv
@@ -452,9 +452,37 @@
[slanted]
[slant=.2]
+% \definefontfeature
+% [boldened]
+% [extend=1.2]
+
+%D Neat:
+
+% By eye:
+%
+% \definefontfeature[boldened-10][effect={width=0.10,delta=1.0,hdelta=0.500,ddelta=0.150,vshift=0.125,extend=1.025,squeeze=0.99250}]
+% \definefontfeature[boldened-15][effect={width=0.15,delta=1.0,hdelta=0.500,ddelta=0.150,vshift=0.250,extend=1.050,squeeze=0.98750}]
+% \definefontfeature[boldened-20][effect={width=0.20,delta=1.0,hdelta=0.500,ddelta=0.150,vshift=0.375,extend=1.075,squeeze=0.98125}]
+% \definefontfeature[boldened-30][effect={width=0.30,delta=1.0,hdelta=0.500,ddelta=0.150,vshift=0.500,extend=1.100,squeeze=0.97500}]
+%
+% By calculation:
+%
+% \definefontfeature[boldened-10][effect={width=0.10,delta=1.0,hdelta=0.02500,ddelta=0.02500,vshift=0.02500,extend=1.050,squeeze=0.99500}]
+% \definefontfeature[boldened-15][effect={width=0.15,delta=1.0,hdelta=0.05625,ddelta=0.05625,vshift=0.05625,extend=1.075,squeeze=0.99250}]
+% \definefontfeature[boldened-20][effect={width=0.20,delta=1.0,hdelta=0.10000,ddelta=0.10000,vshift=0.10000,extend=1.100,squeeze=0.99000}]
+% \definefontfeature[boldened-30][effect={width=0.30,delta=1.0,hdelta=0.22500,ddelta=0.22500,vshift=0.22500,extend=1.150,squeeze=0.98500}]
+%
+% So we can do this:
+
+\definefontfeature[boldened-10][effect={width=0.10,auto=yes}]
+\definefontfeature[boldened-15][effect={width=0.15,auto=yes}]
+\definefontfeature[boldened-20][effect={width=0.20,auto=yes}]
+\definefontfeature[boldened-25][effect={width=0.25,auto=yes}]
+\definefontfeature[boldened-30][effect={width=0.30,auto=yes}]
+
\definefontfeature
[boldened]
- [extend=1.2]
+ [boldened-30]
%D Emoji:
diff --git a/tex/context/base/mkiv/font-prv.lua b/tex/context/base/mkiv/font-prv.lua
new file mode 100644
index 000000000..fef1f3618
--- /dev/null
+++ b/tex/context/base/mkiv/font-prv.lua
@@ -0,0 +1,74 @@
+if not modules then modules = { } end modules ['font-prv'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv and hand-ini.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 fonts = fonts
+local helpers = fonts.helpers
+local fontdata = fonts.hashes.identifiers
+
+local setmetatableindex = table.setmetatableindex
+
+local currentprivate = 0xE000
+local maximumprivate = 0xEFFF
+
+local extraprivates = { }
+helpers.extraprivates = extraprivates
+
+function fonts.helpers.addextraprivate(name,f)
+ extraprivates[#extraprivates+1] = { name, f }
+end
+
+-- if we run out of space we can think of another range but by sharing we can
+-- use these privates for mechanisms like alignments-on-character and such
+
+local sharedprivates = setmetatableindex(function(t,k)
+ v = currentprivate
+ if currentprivate < maximumprivate then
+ currentprivate = currentprivate + 1
+ else
+ -- reuse last slot, todo: warning
+ end
+ t[k] = v
+ return v
+end)
+
+function helpers.addprivate(tfmdata,name,characterdata)
+ local properties = tfmdata.properties
+ local characters = tfmdata.characters
+ local privates = properties.privates
+ if not privates then
+ privates = { }
+ properties.privates = privates
+ end
+ if not name then
+ name = formatters["anonymous_private_0x%05X"](currentprivate)
+ end
+ local usedprivate = sharedprivates[name]
+ privates[name] = usedprivate
+ characters[usedprivate] = characterdata
+ return usedprivate
+end
+
+function helpers.getprivates(tfmdata)
+ if type(tfmdata) == "number" then
+ tfmdata = fontdata[tfmdata]
+ end
+ local properties = tfmdata.properties
+ return properties and properties.privates
+end
+
+function helpers.hasprivate(tfmdata,name)
+ if type(tfmdata) == "number" then
+ tfmdata = fontdata[tfmdata]
+ end
+ local properties = tfmdata.properties
+ local privates = properties and properties.privates
+ return privates and privates[name] or false
+end
diff --git a/tex/context/base/mkiv/font-shp.lua b/tex/context/base/mkiv/font-shp.lua
index 75a12ac82..79c015a63 100644
--- a/tex/context/base/mkiv/font-shp.lua
+++ b/tex/context/base/mkiv/font-shp.lua
@@ -338,7 +338,7 @@ local function segmentstopdf(segments,factor,bt,et)
end
end
-local function addvariableshapes(tfmdata,key,value)
+local function initialize(tfmdata,key,value)
if value then
local shapes = otf.loadoutlinedata(tfmdata)
if not shapes then
@@ -354,7 +354,9 @@ local function addvariableshapes(tfmdata,key,value)
local factor = hfactor / 65536
local getactualtext = otf.getactualtext
for unicode, char in next, characters do
- if not char.commands then
+ if char.commands then
+ -- can't happen as we're doing this before other messing around
+ else
local shape = glyphs[char.index]
if shape then
local segments = shape.segments
@@ -375,8 +377,8 @@ otf.features.register {
name = "variableshapes", -- enforced for now
description = "variable shapes",
manipulators = {
- base = addvariableshapes,
- node = addvariableshapes,
+ base = initialize,
+ node = initialize,
}
}
diff --git a/tex/context/base/mkiv/font-tfm.lua b/tex/context/base/mkiv/font-tfm.lua
index 0059e6296..9f78f2c0a 100644
--- a/tex/context/base/mkiv/font-tfm.lua
+++ b/tex/context/base/mkiv/font-tfm.lua
@@ -21,6 +21,7 @@ local setmetatableindex = table.setmetatableindex
local fonts = fonts
local handlers = fonts.handlers
+local helpers = fonts.helpers
local readers = fonts.readers
local constructors = fonts.constructors
local encodings = fonts.encodings
@@ -39,6 +40,8 @@ local registertfmfeature = tfmfeatures.register
local tfmenhancers = constructors.enhancers.tfm
local registertfmenhancer = tfmenhancers.register
+local charcommand = helpers.commands.char
+
constructors.resolvevirtualtoo = false -- wil be set in font-ctx.lua
fonts.formats.tfm = "type1" -- we need to have at least a value here
@@ -465,7 +468,7 @@ do
if backmap then
original.index = backmap[name]
else -- probably bitmap
- original.commands = { parentfont, { "char", index } }
+ original.commands = { parentfont, charcommand[index] } -- or "slot"
original.oindex = index
end
done[name] = true
diff --git a/tex/context/base/mkiv/font-vfc.lua b/tex/context/base/mkiv/font-vfc.lua
new file mode 100644
index 000000000..cac225de6
--- /dev/null
+++ b/tex/context/base/mkiv/font-vfc.lua
@@ -0,0 +1,98 @@
+if not modules then modules = { } end modules ['font-vfc'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv and hand-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local select = select
+local insert = table.insert
+
+local fonts = fonts
+local helpers = fonts.helpers
+
+local setmetatableindex = table.setmetatableindex
+local makeweak = table.makeweak
+
+-- Helpers dealing with virtual fonts: beware, these are final values so
+-- don't change the content of tables gotten this way!
+
+local push = { "push" }
+local pop = { "pop" }
+local dummy = { "comment" }
+
+function helpers.prependcommands(commands,...)
+ insert(commands,1,push)
+ for i=select("#",...),1,-1 do
+ local s = select(i,...)
+ if s then
+ insert(commands,1,s)
+ end
+ end
+ insert(commands,pop)
+ return commands
+end
+
+function helpers.appendcommands(commands,...)
+ insert(commands,1,push)
+ insert(commands,pop)
+ for i=1,select("#",...) do
+ local s = select(i,...)
+ if s then
+ insert(commands,s)
+ end
+ end
+ return commands
+end
+
+-- todo: maybe weak
+-- todo: maybe indirect so that we can't change them
+
+local char = setmetatableindex(function(t,k)
+ local v = { "char", k }
+ t[k] = v
+ return v
+end)
+
+local right = setmetatableindex(function(t,k)
+ local v = { "right", k }
+ t[k] = v
+ return v
+end)
+
+local left = setmetatableindex(function(t,k)
+ local v = { "right", -k }
+ t[k] = v
+ return v
+end)
+
+local down = setmetatableindex(function(t,k)
+ local v = { "down", k }
+ t[k] = v
+ return v
+end)
+
+local up = setmetatableindex(function(t,k)
+ local v = { "down", -k }
+ t[k] = v
+ return v
+end)
+
+-- makeweak(char)
+-- makeweak(right)
+-- makeweak(left)
+-- makeweak(up)
+-- makeweak(down)
+
+helpers.commands = utilities.storage.allocate {
+ char = char,
+ right = right,
+ left = left,
+ down = down,
+ up = up,
+ push = push,
+ pop = pop,
+ dummy = dummy,
+}
+
diff --git a/tex/context/base/mkiv/font-vir.lua b/tex/context/base/mkiv/font-vir.lua
index 03ad7fc85..d65136245 100644
--- a/tex/context/base/mkiv/font-vir.lua
+++ b/tex/context/base/mkiv/font-vir.lua
@@ -14,7 +14,7 @@ if not modules then modules = { } end modules ['font-vir'] = {
--
-- vf.rule vf.special vf.right vf.push vf.down vf.char vf.node vf.fontid vf.pop vf.image vf.nop
-local next = next
+local next, setmetatable, getmetatable = next, setmetatable, getmetatable
local allocate = utilities.storage.allocate
local setmetatableindex = table.setmetatableindex
@@ -66,11 +66,7 @@ local combinations = { }
local combiner = { }
local whatever = allocate()
local helpers = allocate()
-local predefined = allocate {
- dummy = { "comment" },
- push = { "push" },
- pop = { "pop" },
-}
+local predefined = fonts.helpers.commands
methods.variants = variants -- todo .. wrong namespace
vf.combinations = combinations
diff --git a/tex/context/base/mkiv/l-file.lua b/tex/context/base/mkiv/l-file.lua
index 5fec0040f..46b6847d3 100644
--- a/tex/context/base/mkiv/l-file.lua
+++ b/tex/context/base/mkiv/l-file.lua
@@ -69,35 +69,34 @@ local lpegmatch = lpeg.match
local getcurrentdir, attributes = lfs.currentdir, lfs.attributes
local checkedsplit = string.checkedsplit
--- local patterns = file.patterns or { }
--- file.patterns = patterns
-
local P, R, S, C, Cs, Cp, Cc, Ct = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Cp, lpeg.Cc, lpeg.Ct
-- better this way:
-local tricky = S("/\\") * P(-1)
+----- tricky = S("/\\") * P(-1)
local attributes = lfs.attributes
-if sandbox then
- sandbox.redefine(lfs.isfile,"lfs.isfile")
- sandbox.redefine(lfs.isdir, "lfs.isdir")
-end
-
function lfs.isdir(name)
- if lpegmatch(tricky,name) then
- return attributes(name,"mode") == "directory"
- else
- return attributes(name.."/.","mode") == "directory"
- end
+ -- if not lpegmatch(tricky,name) then
+ -- name = name .. "/."
+ -- end
+ return attributes(name,"mode") == "directory"
end
function lfs.isfile(name)
- return attributes(name,"mode") == "file"
+ local a = attributes(name,"mode")
+ return a == "file" or a == "link" or nil
end
function lfs.isfound(name)
- return attributes(name,"mode") == "file" and name or nil
+ local a = attributes(name,"mode")
+ return (a == "file" or a == "link") and name or nil
+end
+
+if sandbox then
+ sandbox.redefine(lfs.isfile,"lfs.isfile")
+ sandbox.redefine(lfs.isdir, "lfs.isdir")
+ sandbox.redefine(lfs.isfound, "lfs.isfound")
end
local colon = P(":")
@@ -725,3 +724,10 @@ function file.withinbase(path) -- don't go beyond root
return true
end
+-- not used in context but was in luatex once:
+
+local symlinkattributes = lfs.symlinkattributes
+
+function lfs.readlink(name)
+ return symlinkattributes(name,"target") or nil
+end
diff --git a/tex/context/base/mkiv/l-lpeg.lua b/tex/context/base/mkiv/l-lpeg.lua
index a7ebd567d..e3d0ff9c3 100644
--- a/tex/context/base/mkiv/l-lpeg.lua
+++ b/tex/context/base/mkiv/l-lpeg.lua
@@ -944,7 +944,7 @@ local function make2(t,rest) -- only ascii
return p
end
-function lpeg.utfchartabletopattern(list,insensitive) -- goes to util-lpg
+local function utfchartabletopattern(list,insensitive) -- goes to util-lpg
local tree = { }
local n = #list
if n == 0 then
@@ -1022,6 +1022,16 @@ function lpeg.utfchartabletopattern(list,insensitive) -- goes to util-lpg
return (insensitive and make2 or make1)(tree)
end
+lpeg.utfchartabletopattern = utfchartabletopattern
+
+function lpeg.utfreplacer(list,insensitive)
+ local pattern = Cs((utfchartabletopattern(list,insensitive)/list + utf8character)^0)
+ return function(str)
+ return lpegmatch(pattern,str) or str
+ end
+end
+
+
-- local t = { "start", "stoep", "staart", "paard" }
-- local p = lpeg.Cs((lpeg.utfchartabletopattern(t)/string.upper + 1)^1)
@@ -1209,3 +1219,22 @@ end
-- local h = "ADFE0345"
-- local b = lpegmatch(patterns.hextobytes,h)
-- print(h,b,string.tohex(b),string.toHEX(b))
+
+local patterns = { } -- can be made weak
+
+local function containsws(what)
+ local p = patterns[what]
+ if not p then
+ local p1 = P(what) * (whitespace + P(-1)) * Cc(true)
+ local p2 = whitespace * P(p1)
+ p = P(p1) + P(1-p2)^0 * p2 + Cc(false)
+ patterns[what] = p
+ end
+ return p
+end
+
+lpeg.containsws = containsws
+
+function string.containsws(str,what)
+ return lpegmatch(patterns[what] or containsws(what),str)
+end
diff --git a/tex/context/base/mkiv/l-os.lua b/tex/context/base/mkiv/l-os.lua
index 9b54c9840..bf13baaa6 100644
--- a/tex/context/base/mkiv/l-os.lua
+++ b/tex/context/base/mkiv/l-os.lua
@@ -156,7 +156,7 @@ end
local launchers = {
windows = "start %s",
macosx = "open %s",
- unix = "$BROWSER %s &> /dev/null &",
+ unix = "xdg-open %s &> /dev/null &",
}
function os.launch(str)
@@ -234,10 +234,12 @@ elseif os.type == "windows" then
-- PROCESSOR_ARCHITECTURE : binary platform
-- PROCESSOR_ARCHITEW6432 : OS platform
+ -- mswin-64 is now win64
+
function resolvers.platform(t,k)
- local platform, architecture = "", os.getenv("PROCESSOR_ARCHITECTURE") or ""
+ local architecture = os.getenv("PROCESSOR_ARCHITECTURE") or ""
+ local platform = ""
if find(architecture,"AMD64",1,true) then
- -- platform = "mswin-64"
platform = "win64"
else
platform = "mswin"
@@ -251,13 +253,17 @@ elseif name == "linux" then
function resolvers.platform(t,k)
-- we sometimes have HOSTTYPE set so let's check that first
- local platform, architecture = "", os.getenv("HOSTTYPE") or resultof("uname -m") or ""
- if find(architecture,"x86_64",1,true) then
- platform = "linux-64"
+ local architecture = os.getenv("HOSTTYPE") or resultof("uname -m") or ""
+ local platform = os.getenv("MTX_PLATFORM")
+ local musl = find(os.selfdir or "","linuxmusl")
+ if platform ~= "" then
+ -- we're done
+ elseif find(architecture,"x86_64",1,true) then
+ platform = musl and "linuxmusl" or "linux-64"
elseif find(architecture,"ppc",1,true) then
platform = "linux-ppc"
else
- platform = "linux"
+ platform = musl and "linuxmusl" or "linux"
end
os.setenv("MTX_PLATFORM",platform)
os.platform = platform
@@ -277,11 +283,13 @@ elseif name == "macosx" then
]]--
function resolvers.platform(t,k)
- -- local platform, architecture = "", os.getenv("HOSTTYPE") or ""
+ -- local platform = ""
+ -- local architecture = os.getenv("HOSTTYPE") or ""
-- if architecture == "" then
-- architecture = resultof("echo $HOSTTYPE") or ""
-- end
- local platform, architecture = "", resultof("echo $HOSTTYPE") or ""
+ local architecture = resultof("echo $HOSTTYPE") or ""
+ local platform = ""
if architecture == "" then
-- print("\nI have no clue what kind of OSX you're running so let's assume an 32 bit intel.\n")
platform = "osx-intel"
@@ -300,7 +308,8 @@ elseif name == "macosx" then
elseif name == "sunos" then
function resolvers.platform(t,k)
- local platform, architecture = "", resultof("uname -m") or ""
+ local architecture = resultof("uname -m") or ""
+ local platform = ""
if find(architecture,"sparc",1,true) then
platform = "solaris-sparc"
else -- if architecture == 'i86pc'
@@ -314,7 +323,8 @@ elseif name == "sunos" then
elseif name == "freebsd" then
function resolvers.platform(t,k)
- local platform, architecture = "", resultof("uname -m") or ""
+ local architecture = resultof("uname -m") or ""
+ local platform = ""
if find(architecture,"amd64",1,true) then
platform = "freebsd-amd64"
else
@@ -329,7 +339,8 @@ elseif name == "kfreebsd" then
function resolvers.platform(t,k)
-- we sometimes have HOSTTYPE set so let's check that first
- local platform, architecture = "", os.getenv("HOSTTYPE") or resultof("uname -m") or ""
+ local architecture = os.getenv("HOSTTYPE") or resultof("uname -m") or ""
+ local platform = ""
if find(architecture,"x86_64",1,true) then
platform = "kfreebsd-amd64"
else
diff --git a/tex/context/base/mkiv/l-table.lua b/tex/context/base/mkiv/l-table.lua
index 5cd65dd67..788d1511f 100644
--- a/tex/context/base/mkiv/l-table.lua
+++ b/tex/context/base/mkiv/l-table.lua
@@ -1236,7 +1236,7 @@ function table.reverse(t) -- check with 5.3 ?
end
end
-function table.sequenced(t,sep,simple) -- hash only
+local function sequenced(t,sep,simple)
if not t then
return ""
end
@@ -1257,17 +1257,27 @@ function table.sequenced(t,sep,simple) -- hash only
s[n] = k
elseif v and v~= "" then
n = n + 1
- s[n] = k .. "=" .. tostring(v)
+ if type(v) == "table" then
+ s[n] = k .. "={" .. sequenced(v,sep,simple) .. "}"
+ else
+ s[n] = k .. "=" .. tostring(v)
+ end
end
else
n = n + 1
- s[n] = k .. "=" .. tostring(v)
+ if type(v) == "table" then
+ s[n] = k .. "={" .. sequenced(v,sep,simple) .. "}"
+ else
+ s[n] = k .. "=" .. tostring(v)
+ end
end
end
end
return concat(s,sep or " | ")
end
+table.sequenced = sequenced
+
function table.print(t,...)
if type(t) ~= "table" then
print(tostring(t))
diff --git a/tex/context/base/mkiv/lang-ini.mkiv b/tex/context/base/mkiv/lang-ini.mkiv
index 7c83ae38f..9c7b5641b 100644
--- a/tex/context/base/mkiv/lang-ini.mkiv
+++ b/tex/context/base/mkiv/lang-ini.mkiv
@@ -548,7 +548,12 @@
% this will move to core-spa !
\appendtoks
- \doifelse{\languageparameter\c!spacing}\v!broad\nonfrenchspacing\frenchspacing
+ \edef\p_spacing{\languageparameter\c!spacing}%
+ \ifx\p_spacing\v!broad
+ \nonfrenchspacing
+ \else
+ \frenchspacing
+ \fi
\to \everylanguage
% \mainlanguage[nl] \setuplanguage[nl][lefthyphen=,righthyphen=?]
diff --git a/tex/context/base/mkiv/lang-lab.mkiv b/tex/context/base/mkiv/lang-lab.mkiv
index 73637753d..9d73d96e5 100644
--- a/tex/context/base/mkiv/lang-lab.mkiv
+++ b/tex/context/base/mkiv/lang-lab.mkiv
@@ -277,10 +277,16 @@
\def\lang_labels_text_prefix_copy_pair[#1=#2]%
{\lang_labels_text_prefix_copy_pair_indeed{#1}[#2,,]}
+% \def\lang_labels_text_prefix_copy_pair_indeed#1[#2,#3]%
+% {\expandafter\let
+% \csname\??label\currenttextprefixclass:\currenttextprefixtag:#1\expandafter\endcsname
+% \csname\??label\currenttextprefixclass:\currenttextprefixtag:#2\endcsname}
+%
+% this delays the aliasing so that we can switch maillanguage in between
+
\def\lang_labels_text_prefix_copy_pair_indeed#1[#2,#3]%
- {\expandafter\let
- \csname\??label\currenttextprefixclass:\currenttextprefixtag:#1\expandafter\endcsname
- \csname\??label\currenttextprefixclass:\currenttextprefixtag:#2\endcsname}
+ {\expandafter\edef\csname\??label\currenttextprefixclass:#1\endcsname
+ {{\noexpand\csname\??label\currenttextprefixclass:\noexpand\reallanguagetag\noexpand\currentmainlanguage:#2\endcsname}{}}}
\definelabelclass [head] [0] % titles
\definelabelclass [label] [0] % texts
diff --git a/tex/context/base/mkiv/lpdf-ano.lua b/tex/context/base/mkiv/lpdf-ano.lua
index 01f015b72..eba4d6060 100644
--- a/tex/context/base/mkiv/lpdf-ano.lua
+++ b/tex/context/base/mkiv/lpdf-ano.lua
@@ -106,6 +106,31 @@ local pdf_fit = pdfconstant("Fit")
local pdf_named = pdfconstant("Named")
local autoprefix = "#"
+local usedautoprefixes = { }
+
+local function registerautoprefix(name)
+ local internal = autoprefix .. name
+ if usedautoprefixes[internal] == nil then
+ usedautoprefixes[internal] = false
+ end
+ return internal
+end
+
+local function useautoprefix(name)
+ local internal = autoprefix .. name
+ usedautoprefixes[internal] = true
+end
+
+local function checkautoprefixes(destinations)
+ for k, v in next, usedautoprefixes do
+ if not v then
+ if trace_destinations then
+ report_destinations("flushing unused autoprefix %a",k)
+ end
+ destinations[k] = nil
+ end
+ end
+end
-- Bah, I hate this kind of features .. anyway, as we have delayed resolving we
-- only support a document-wide setup and it has to be set before the first one
@@ -193,11 +218,15 @@ local defaultdestination = pdfarray { 0, pdf_fit }
-- fit is default (see lpdf-nod)
local destinations = { } -- to be used soon
+local reported = setmetatableindex("table")
local function pdfregisterdestination(name,reference)
local d = destinations[name]
if d then
- report_destinations("ignoring duplicate destination %a with reference %a",name,reference)
+ if not reported[name][reference] then
+ report_destinations("ignoring duplicate destination %a with reference %a",name,reference)
+ reported[name][reference] = true
+ end
else
destinations[name] = reference
end
@@ -222,6 +251,7 @@ end)
local function pdfnametree(destinations)
local slices = { }
+ checkautoprefixes(destinations)
local sorted = table.sortedkeys(destinations)
local size = #sorted
@@ -292,7 +322,6 @@ end
local function pdfdestinationspecification()
if next(destinations) then -- safeguard
local r = pdfnametree(destinations)
- -- pdfaddtocatalog("Dests",r)
pdfaddtonames("Dests",r)
if not log_destinations then
destinations = nil
@@ -459,7 +488,7 @@ function nodeinjections.destination(width,height,depth,names,view)
elseif type(name) == "number" then
local used = usedinternals[name]
usedviews[name] = view
- names[n] = autoprefix .. name
+ names[n] = registerautoprefix(name)
doview = true
else
usedviews[name] = view
@@ -479,10 +508,9 @@ function nodeinjections.destination(width,height,depth,names,view)
local used = usedinternals[name]
if used and used ~= defaultview then
usedviews[name] = view
- names[n] = autoprefix .. name
+ names[n] = registerautoprefix(name)
doview = true
else
- -- names[n] = autoprefix .. name
names[n] = false
end
end
@@ -504,7 +532,7 @@ local function pdflinkpage(page)
end
local function pdflinkinternal(internal,page)
- local method = references.innermethod
+ -- local method = references.innermethod
if internal then
flaginternals[internal] = true -- for bookmarks and so
local used = usedinternals[internal]
@@ -512,7 +540,7 @@ local function pdflinkinternal(internal,page)
return pagereferences[page]
else
if type(internal) ~= "string" then
- internal = autoprefix .. internal
+ internal = useautoprefix(internal)
end
return pdfdictionary {
S = pdf_goto,
@@ -872,16 +900,21 @@ end
runners["special operation"] = runners["special"]
runners["special operation with arguments"] = runners["special"]
+local reported = { }
+
function specials.internal(var,actions) -- better resolve in strc-ref
- local i = tonumber(var.operation)
+ local o = var.operation
+ local i = o and tonumber(o)
local v = i and references.internals[i]
- if not v then
- -- error
- report_references("no internal reference %a",i or "<unset>")
- else
- flaginternals[i] = true
+ if v then
+ flaginternals[i] = true -- also done in pdflinkinternal
return pdflinkinternal(i,v.references.realpage)
end
+ local v = i or o or "<unset>"
+ if not reported[v] then
+ report_references("no internal reference %a",v)
+ reported[v] = true
+ end
end
-- realpage already resolved
@@ -946,19 +979,18 @@ end
-- sections
--- function specials.section(var,actions)
--- local sectionname = var.operation
--- local destination = var.arguments
--- local internal = structures.sections.internalreference(sectionname,destination)
--- if internal then
--- var.special = "internal"
--- var.operation = internal
--- var.arguments = nil
--- specials.internal(var,actions)
--- end
--- end
-
-specials.section = specials.internal -- specials.section just need to have a value as it's checked
+function specials.section(var,actions)
+ -- a bit duplicate
+ local sectionname = var.arguments
+ local destination = var.operation
+ local internal = structures.sections.internalreference(sectionname,destination)
+ if internal then
+ var.special = "internal"
+ var.operation = internal
+ var.arguments = nil
+ return specials.internal(var,actions)
+ end
+end
-- todo, do this in references namespace ordered instead (this is an experiment)
diff --git a/tex/context/base/mkiv/lpdf-tag.lua b/tex/context/base/mkiv/lpdf-tag.lua
index f4ecfc8a6..dc7d038fe 100644
--- a/tex/context/base/mkiv/lpdf-tag.lua
+++ b/tex/context/base/mkiv/lpdf-tag.lua
@@ -324,11 +324,10 @@ function nodeinjections.addtags(head)
local last = nil
local ranges = { }
local range = nil
- local head = tonut(head)
+ local head = tonut(head)
local function collectranges(head,list)
- for n in traverse_nodes(head) do
- local id = getid(n)
+ for n, id in traverse_nodes(head) do
if id == glyph_code then
-- maybe also disc
local at = getattr(n,a_tagged)
@@ -472,8 +471,7 @@ end
-- local last, ranges, range = nil, { }, nil
--
-- local function collectranges(head,list)
--- for n in traverse_nodes(head) do
--- local id = getid(n) -- 14: image, 8: literal (mp)
+-- for n, id in traverse_nodes(head) do
-- if id == glyph_code then
-- local at = getattr(n,a_tagged)
-- if not at then
diff --git a/tex/context/base/mkiv/luat-cod.lua b/tex/context/base/mkiv/luat-cod.lua
index 91bb7c2e1..94006d52c 100644
--- a/tex/context/base/mkiv/luat-cod.lua
+++ b/tex/context/base/mkiv/luat-cod.lua
@@ -187,6 +187,21 @@ end
-- a kpse error when disabled. This is an engine issue that will
-- be sorted out in due time.
+if not lfs.isfile then
+
+ local attributes = lfs.attributes
+
+ function lfs.isdir(name)
+ return attributes(name,"mode") == "directory"
+ end
+
+ function lfs.isfile(name)
+ local a = attributes(name,"mode")
+ return a == "file" or a == "link" or nil
+ end
+
+end
+
local isfile = lfs.isfile
local function source_file(name)
diff --git a/tex/context/base/mkiv/lxml-css.lua b/tex/context/base/mkiv/lxml-css.lua
index 1787c53df..8d6c42409 100644
--- a/tex/context/base/mkiv/lxml-css.lua
+++ b/tex/context/base/mkiv/lxml-css.lua
@@ -6,7 +6,7 @@ if not modules then modules = { } end modules ['lxml-css'] = {
license = "see context related readme files"
}
-local tonumber, rawset, type = tonumber, rawset, type
+local tonumber, rawset, type, select = tonumber, rawset, type, select
local lower, format, find, gmatch = string.lower, string.format, string.find, string.gmatch
local topattern, is_empty = string.topattern, string.is_empty
local P, S, C, R, Cb, Cg, Carg, Ct, Cc, Cf, Cs = lpeg.P, lpeg.S, lpeg.C, lpeg.R, lpeg.Cb, lpeg.Cg, lpeg.Carg, lpeg.Ct, lpeg.Cc, lpeg.Cf, lpeg.Cs
@@ -118,24 +118,33 @@ css.padding = padding
-- print(padding("0",pixel,hsize,exheight,emwidth))
--- local currentfont = font.current
--- local texget = tex.get
--- local hashes = fonts.hashes
--- local quads = hashes.quads
--- local xheights = hashes.xheights
---
--- local function padding(str)
--- local font = currentfont()
--- local exheight = xheights[font]
--- local emwidth = quads[font]
--- local hsize = texget("hsize")/100
--- local pixel = emwidth/100
--- return padding(str,pixel,hsize,exheight,emwidth)
--- end
---
--- function css.simplepadding(str)
--- context("%ssp",padding(str,pixel,hsize,exheight,emwidth))
--- end
+local context = context
+
+if context then
+
+ local currentfont = font.current
+ local texget = tex.get
+ local hashes = fonts.hashes
+ local quads = hashes.quads
+ local xheights = hashes.xheights
+
+ local function todimension(str)
+ local font = currentfont()
+ local exheight = xheights[font]
+ local emwidth = quads[font]
+ local hsize = texget("hsize")/100
+ local pixel = emwidth/100
+ return dimension(str,pixel,hsize,exheight,emwidth)
+ end
+
+ css.todimension = todimension
+
+ function context.cssdimension(str)
+ -- context("%ssp",todimension(str))
+ context(todimension(str) .. "sp")
+ end
+
+end
local pattern = Cf( Ct("") * (
Cg(
@@ -993,3 +1002,91 @@ interfaces.implement {
actions = css.mappedstylevalue,
arguments = "3 strings",
}
+
+-- more (for mm)
+
+local containsws = string.containsws
+local classsplitter = lpeg.tsplitat(whitespace^1)
+
+function xml.functions.classes(e,class) -- cache
+ if class then
+ local at = e.at
+ local data = at[class] or at.class
+ if data then
+ return lpegmatch(classsplitter,data) or { }
+ end
+ end
+ return { }
+end
+
+-- function xml.functions.hasclass(e,class,name)
+-- if class then
+-- local at = e.at
+-- local data = at[class] or at.class
+-- if data then
+-- return data == name or containsws(data,name)
+-- end
+-- end
+-- return false
+-- end
+--
+-- function xml.expressions.hasclass(attribute,name)
+-- if attribute then
+-- return attribute == name or containsws(attribute,name)
+-- end
+-- return false
+-- end
+
+function xml.functions.hasclass(e,class,name,more,...)
+ if class and name then
+ local at = e.at
+ local data = at[class] or at.class
+ if not data or data == "" then
+ return false
+ end
+ if data == name or data == more then
+ return true
+ end
+ if containsws(data,name) then
+ return true
+ end
+ if not more then
+ return false
+ end
+ if containsws(data,more) then
+ return true
+ end
+ for i=1,select("#",...) do
+ if containsws(data,select(i,...)) then
+ return true
+ end
+ end
+ end
+ return false
+end
+
+function xml.expressions.hasclass(data,name,more,...)
+ if data then
+ if not data or data == "" then
+ return false
+ end
+ if data == name or data == more then
+ return true
+ end
+ if containsws(data,name) then
+ return true
+ end
+ if not more then
+ return false
+ end
+ if containsws(data,more) then
+ return true
+ end
+ for i=1,select("#",...) do
+ if containsws(data,select(i,...)) then
+ return true
+ end
+ end
+ end
+ return false
+end
diff --git a/tex/context/base/mkiv/lxml-lpt.lua b/tex/context/base/mkiv/lxml-lpt.lua
index bb6fb4568..9cccac120 100644
--- a/tex/context/base/mkiv/lxml-lpt.lua
+++ b/tex/context/base/mkiv/lxml-lpt.lua
@@ -1592,8 +1592,8 @@ end
-- local w = lpeg.patterns.whitespace
-- local p = w^0 * lpeg.Cf(lpeg.Ct("") * lpeg.Cg(lpeg.C((1-w)^1) * lpeg.Cc(true) * w^0)^1,rawset)
--- function xml.functions.classes(e) -- cache
--- local class = e.at.class
+-- function xml.functions.classes(e,class) -- cache
+-- class = class and e.at[class] or e.at.class
-- if class then
-- return lpegmatch(p,class)
-- else
diff --git a/tex/context/base/mkiv/lxml-tex.lua b/tex/context/base/mkiv/lxml-tex.lua
index b8280ba9c..eed3b123a 100644
--- a/tex/context/base/mkiv/lxml-tex.lua
+++ b/tex/context/base/mkiv/lxml-tex.lua
@@ -1997,7 +1997,7 @@ do
implement {
name = "xmldoifatt",
arguments = "3 strings",
- actions = function(id,l,v)
+ actions = function(id,k,v)
local e = getid(id)
ctx_doif(e and e.at[k] == v or false)
end
@@ -2006,7 +2006,7 @@ do
implement {
name = "xmldoifnotatt",
arguments = "3 strings",
- actions = function(id,l,v)
+ actions = function(id,k,v)
local e = getid(id)
ctx_doifnot(e and e.at[k] == v or false)
end
@@ -2015,7 +2015,7 @@ do
implement {
name = "xmldoifelseatt",
arguments = "3 strings",
- actions = function(id,l,v)
+ actions = function(id,k,v)
local e = getid(id)
ctx_doifelse(e and e.at[k] == v or false)
end
diff --git a/tex/context/base/mkiv/math-ext.lua b/tex/context/base/mkiv/math-ext.lua
index a4b865713..15a93d62e 100644
--- a/tex/context/base/mkiv/math-ext.lua
+++ b/tex/context/base/mkiv/math-ext.lua
@@ -7,22 +7,23 @@ if not modules then modules = { } end modules ['math-ext'] = {
}
local rawget = rawget
-
-local trace_virtual = false trackers.register("math.virtual", function(v) trace_virtual = v end)
-
local basename = file.basename
+local sortedhash = table.sortedhash
+
+local mathematics = mathematics
+local extras = mathematics.extras or { }
+mathematics.extras = extras
-local mathematics = mathematics
-local characters = characters
+local characters = characters
+local chardata = characters.data
+local mathpairs = characters.mathpairs
-local report_math = logs.reporter("mathematics")
+local trace_virtual = false
+local report_math = logs.reporter("mathematics")
-mathematics.extras = mathematics.extras or { }
-local extras = mathematics.extras
+trackers.register("math.virtual", function(v) trace_virtual = v end)
-local mathplus = { }
-local chardata = characters.data
-local mathpairs = characters.mathpairs
+local mathplus = { }
-- todo: store them and skip storage if already stored
-- todo: make a char-ctx.lua (or is this already side effect of save in format)
@@ -47,7 +48,7 @@ function extras.copy(target,original)
local characters = target.characters
local properties = target.properties
local parameters = target.parameters
- for unicode in table.sortedhash(mathplus) do
+ for unicode in sortedhash(mathplus) do
local extradesc = chardata[unicode]
local nextinsize = extradesc.nextinsize
if nextinsize then
diff --git a/tex/context/base/mkiv/math-fbk.lua b/tex/context/base/mkiv/math-fbk.lua
index 7aa8c437f..0d8fda7d4 100644
--- a/tex/context/base/mkiv/math-fbk.lua
+++ b/tex/context/base/mkiv/math-fbk.lua
@@ -20,10 +20,22 @@ local sortedhash = table.sortedhash
local fallbacks = { }
mathematics.fallbacks = fallbacks
+local helpers = fonts.helpers
+local prependcommands = helpers.prependcommands
+local charcommand = helpers.commands.char
+local leftcommand = helpers.commands.left
+local rightcommand = helpers.commands.right
+local upcommand = helpers.commands.up
+local downcommand = helpers.commands.down
+local dummycommand = helpers.commands.dummy
+local popcommand = helpers.commands.pop
+local pushcommand = helpers.commands.push
+
local virtualcharacters = { }
-local identifiers = fonts.hashes.identifiers
-local lastmathids = fonts.hashes.lastmathids
+local hashes = fonts.hashes
+local identifiers = hashes.identifiers
+local lastmathids = hashes.lastmathids
-- we need a trick (todo): if we define scriptscript, script and text in
-- that order we could use their id's .. i.e. we could always add a font
@@ -151,22 +163,21 @@ local function reference(index,char)
if index then
return { "slot", index, char }
else
- return { "char", char }
+ return charcommand[char]
end
end
-local function raised(data,down)
- local replacement = data.replacement
- local character = data.scriptdata.characters[replacement]
+local function raised(data,replacement,down)
+ local character = data.scriptdata.characters[replacement]
if character then
+ local size = data.size
return {
width = character.width,
height = character.height,
depth = character.depth,
commands = {
- { "down", down and data.size/4 or -data.size/2 }, -- maybe exheight
+ down and downcommand[size/4] or upcommand[size/2],
reference(data.scriptindex,replacement)
- -- { "slot", data.scriptindex or 0, char } -- hm, data.mathrelation.scriptindex
}
}
end
@@ -177,33 +188,18 @@ end
-- virtualcharacters[0x208A] = 0x2212
-- virtualcharacters[0x208B] = 0x002B
-virtualcharacters[0x207A] = function(data)
- data.replacement = 0x002B
- return raised(data)
-end
-
-virtualcharacters[0x207B] = function(data)
- data.replacement = 0x2212
- return raised(data)
-end
-
-virtualcharacters[0x208A] = function(data)
- data.replacement = 0x002B
- return raised(data,true)
-end
-
-virtualcharacters[0x208B] = function(data)
- data.replacement = 0x2212
- return raised(data,true)
-end
+virtualcharacters[0x207A] = function(data) return raised(data,0x002B) end
+virtualcharacters[0x207B] = function(data) return raised(data,0x2212) end
+virtualcharacters[0x208A] = function(data) return raised(data,0x002B,true) end
+virtualcharacters[0x208B] = function(data) return raised(data,0x2212,true) end
-- local function repeated(data,char,n,fraction)
-- local character = data.characters[char]
-- if character then
-- local width = character.width
-- local delta = width - character.italic -- width * fraction
--- local c = { "char", char }
--- local r = { "right", right }
+-- local c = charcommand[char]
+-- local r = rightcommand[right]
-- local commands = { }
-- for i=1,n-1 do
-- width = width + delta
@@ -234,14 +230,9 @@ addextra(0xFE350) -- MATHEMATICAL DOUBLE ARROW LEFT END
addextra(0xFE351) -- MATHEMATICAL DOUBLE ARROW MIDDLE PART
addextra(0xFE352) -- MATHEMATICAL DOUBLE ARROW RIGHT END
-local push = { "push" }
-local pop = { "pop" }
-local leftarrow = { "char", 0x2190 }
-local relbar = { "char", 0x2212 }
-local rightarrow = { "char", 0x2192 }
--- local leftarrow = { "slot", 0, 0x2190 }
--- local relbar = { "slot", 0, 0x2212 }
--- local rightarrow = { "slot", 0, 0x2192 }
+local leftarrow = charcommand[0x2190]
+local relbar = charcommand[0x2212]
+local rightarrow = charcommand[0x2192]
virtualcharacters[0xFE350] = function(data)
-- return combined(data,0x2190,0x2212) -- leftarrow relbar
@@ -254,11 +245,11 @@ virtualcharacters[0xFE350] = function(data)
height = size,
depth = size,
commands = {
- push,
- { "down", size/2 },
+ pushcommand,
+ downcommand[size/2],
leftarrow,
- pop,
- { "down", -size/2 },
+ popcommand,
+ upcommand[size/2],
relbar,
}
}
@@ -275,11 +266,11 @@ virtualcharacters[0xFE351] = function(data)
height = size,
depth = size,
commands = {
- push,
- { "down", size/2 },
+ pushcommand,
+ downcommand[size/2],
relbar,
- pop,
- { "down", -size/2 },
+ popcommand,
+ upcommand[size/2],
relbar,
}
}
@@ -297,12 +288,12 @@ virtualcharacters[0xFE352] = function(data)
height = size,
depth = size,
commands = {
- push,
- { "down", size/2 },
+ pushcommand,
+ downcommand[size/2],
relbar,
- pop,
- { "right", chartwo.width - charone.width },
- { "down", -size/2 },
+ popcommand,
+ rightcommand[chartwo.width - charone.width],
+ upcommand[size/2],
rightarrow,
}
}
@@ -325,10 +316,11 @@ local function accent_to_extensible(target,newchr,original,oldchr,height,depth,s
height = height or 0
depth = depth or 0
end
- local correction = swap and { "down", (olddata.height or 0) - height } or { "down", olddata.height + (offset or 0)}
+ local correction = swap and
+ downcommand[(olddata.height or 0) - height]
+ or downcommand[olddata.height + (offset or 0)]
local newdata = {
- commands = { correction, { "slot", 1, oldchr } },
- -- commands = { correction, { "slot", 0, oldchr } },
+ commands = { correction, charcommand[oldchr] },
width = olddata.width,
height = height,
depth = depth,
@@ -340,14 +332,12 @@ local function accent_to_extensible(target,newchr,original,oldchr,height,depth,s
local oldnextdata = characters[nextglyph]
if oldnextdata then
local newnextdata = {
- commands = { correction, { "slot", 1, nextglyph } },
- -- commands = { correction, { "slot", 0, nextglyph } },
+ commands = { correction, charcommand[nextglyph] },
width = oldnextdata.width,
height = height,
depth = depth,
}
--- local newnextglyph = addprivate(target,formatters["M-N-%H"](nextglyph),newnextdata)
- local newnextglyph = addprivate(target,nil,newnextdata)
+ local newnextglyph = addprivate(target,formatters["M-N-%H"](nextglyph),newnextdata)
newdata.next = newnextglyph
local nextnextglyph = oldnextdata.next
if nextnextglyph == nextglyph then
@@ -372,14 +362,12 @@ local function accent_to_extensible(target,newchr,original,oldchr,height,depth,s
local olddata = characters[oldglyph]
if olddata then
local newdata = {
- commands = { correction, { "slot", 1, oldglyph } },
- -- commands = { correction, { "slot", 0, oldglyph } },
+ commands = { correction, charcommand[oldglyph] },
width = olddata.width,
height = height,
depth = depth,
}
--- hvi.glyph = addprivate(target,formatters["M-H-%H"](oldglyph),newdata)
- hvi.glyph = addprivate(target,nil,newdata)
+ hvi.glyph = addprivate(target,formatters["M-H-%H"](oldglyph),newdata)
else
report_fallbacks("error in fallback: no valid horiz_variants, slot %X, index %i",oldglyph,i)
end
@@ -394,14 +382,14 @@ end
virtualcharacters[0x203E] = function(data)
local target = data.target
local height, depth = 0, 0
--- local mathparameters = target.mathparameters
--- if mathparameters then
--- height = mathparameters.OverbarVerticalGap
--- depth = mathparameters.UnderbarVerticalGap
--- else
+ -- local mathparameters = target.mathparameters
+ -- if mathparameters then
+ -- height = mathparameters.OverbarVerticalGap
+ -- depth = mathparameters.UnderbarVerticalGap
+ -- else
height = target.parameters.xheight/4
depth = height
--- end
+ -- end
return accent_to_extensible(target,0x203E,data.original,0x0305,height,depth,nil,nil,0x203E)
end
@@ -431,7 +419,7 @@ local function spacefraction(data,fraction)
local width = fraction * data.target.parameters.space
return {
width = width,
- commands = { { "right", width } }
+ commands = { rightcommand[width] }
}
end
@@ -439,7 +427,7 @@ local function charfraction(data,char)
local width = data.target.characters[char].width
return {
width = width,
- commands = { { "right", width } }
+ commands = { rightcommand[width] }
}
end
@@ -447,7 +435,7 @@ local function quadfraction(data,fraction)
local width = fraction * data.target.parameters.quad
return {
width = width,
- commands = { { "right", width } }
+ commands = { rightcommand[width] }
}
end
@@ -527,9 +515,8 @@ local function smashed(data,unicode,optional)
local shift = oldchar.height - height
local newchar = {
commands = {
- { "down", shift },
- { "slot", 0, unicode },
--- { "char", unicode },
+ downcommand[shift],
+ charcommand[unicode],
},
height = height,
width = oldchar.width,
@@ -607,11 +594,11 @@ local function actuarian(data)
width = basewidth + 4 * linewidth,
unicode = 0x20E7,
commands = {
- { "right", 2 * linewidth },
- { "down", - baseheight - 3 * linewidth },
+ rightcommand[2 * linewidth],
+ downcommand[- baseheight - 3 * linewidth],
{ "rule", linewidth, basewidth + 4 * linewidth },
- { "right", -linewidth },
- { "down", baseheight + 4 * linewidth },
+ leftcommand[linewidth],
+ downcommand[baseheight + 4 * linewidth],
{ "rule", baseheight + 5 * linewidth, linewidth },
},
}
@@ -629,11 +616,11 @@ local function equals(data,unicode,snippet,advance,n) -- mathpair needs them
unicode = unicode,
width = n*basechar.width + (n-1)*advance,
commands = {
- { "char", snippet },
- { "right", advance },
- { "char", snippet },
- n > 2 and { "right", advance } or nil,
- n > 2 and { "char", snippet } or nil,
+ charcommand[snippet],
+ rightcommand[advance],
+ charcommand[snippet],
+ n > 2 and rightcommand[advance] or nil,
+ n > 2 and charcommand[snippet] or nil,
},
}
end
@@ -657,11 +644,11 @@ virtualcharacters[0x2980] = function(data) return equals(data,0x2980,0x007C,-1/8
-- height = height, -- we cheat (no time now)
-- depth = depth, -- we cheat (no time now)
-- commands = {
--- { "down", - height/2 }, -- sort of works
--- { "char", 0x003D },
--- { "right", -width },
--- { "down", height }, -- sort of works
--- { "char", 0x003D },
+-- upcommand[height/2], -- sort of works
+-- charcommand[0x003D],
+-- leftcommand[width],
+-- downcommand[height], -- sort of works
+-- charcommand[0x003D],
-- },
-- }
-- end
diff --git a/tex/context/base/mkiv/math-ini.mkiv b/tex/context/base/mkiv/math-ini.mkiv
index 17d900d74..9dfc317dd 100644
--- a/tex/context/base/mkiv/math-ini.mkiv
+++ b/tex/context/base/mkiv/math-ini.mkiv
@@ -1273,9 +1273,13 @@
%D Memory saver:
+\def\math_basics_check_compact
+ {\doifelse{\mathematicsparameter\c!compact}\v!yes
+ \enabledirectives\disabledirectives[math.virtual.optional]}
+
\appendtoks
\ifx\currentmathematics\empty
- \doifelse{\mathematicsparameter\c!compact}\v!yes\enabledirectives\disabledirectives[math.virtual.optional]%
+ \math_basics_check_compact % less tracing
\fi
\to \everysetupmathematics
@@ -1311,18 +1315,31 @@
%D \HL
%D \stoptabulate
+% We will use proper constants when we go numbers instead of XXX.
+
\newconditional\c_math_right_to_left
+\installcorenamespace{mathaligndirection}
+
+\setvalue{\??mathaligndirection r2l}{\settrue\c_math_right_to_left}
+\setvalue{\??mathaligndirection\v!righttoleft}{\settrue\c_math_right_to_left}
+
\appendtoks
- \doifelse{\mathematicsparameter\c!align}{r2l}\settrue\setfalse\c_math_right_to_left
+ \ifcsname\??mathaligndirection\mathematicsparameter\c!align\endcsname
+ \lastnamedcs
+ \else
+ \setfalse\c_math_right_to_left
+ \fi
\to \everyswitchmathematics
\unexpanded\def\math_basics_synchronize_direction
{\mathdir T\ifconditional\c_math_right_to_left R\else L\fi T}
+% Not \everymathematics as it comes too late and I'm not in the mood for a mixed mode
+% kludge now (should be a property of beginmath nodes and passed to callbacks).
+
\appendtoks
\math_basics_synchronize_direction
-%to \everymathematics % comes too late and I'm not in the mood for a mixed mode kludge now (should be a property of beginmath nodes and passed to callbacks)
\to \everyswitchmathematics
% experimental (needed for an article)
@@ -1337,11 +1354,6 @@
\letvalue{\??mathbidi\v!yes}\math_bidi_enable
\letvalue{\??mathbidi\v!no }\math_bidi_disable
-% \appendtoks
-% \edef\p_bidi{\mathematicsparameter\c!bidi}%
-% \csname\??mathbidi\ifcsname\??mathbidi\p_bidi\endcsname\p_bidi\else\v!no\fi\endcsname
-% \to \everysetupmathematics
-
\appendtoks
\edef\p_bidi{\mathematicsparameter\c!bidi}% still needed ?
\ifcsname\??mathbidi\p_bidi\endcsname\lastnamedcs\else\math_bidi_disable\fi
@@ -2468,10 +2480,13 @@
% I need to decide:
%
-%mathscriptboxmode\zerocount % no kerning
-%mathscriptboxmode\plusone % lists
-\mathscriptboxmode\plustwo % lists and boxes
-%mathscriptboxmode\plusthree % lists and boxes with \boundary=1 (also for testing and demo)
+%mathscriptboxmode \zerocount % no kerning
+%mathscriptboxmode \plusone % lists
+\mathscriptboxmode \plustwo % lists and boxes
+\mathscriptcharmode\plusone % lists and boxes
+%mathscriptboxmode \plusthree % lists and boxes with \boundary=1 (also for testing and demo)
+
+\mathrulethicknessmode\plusone
\unexpanded\def\mathtext {\mathortext{\math_text_choice_font\relax}\hbox}
\unexpanded\def\mathword {\mathortext{\math_text_choice_word\relax}\hbox}
diff --git a/tex/context/base/mkiv/math-noa.lua b/tex/context/base/mkiv/math-noa.lua
index 529837cfa..20f77411e 100644
--- a/tex/context/base/mkiv/math-noa.lua
+++ b/tex/context/base/mkiv/math-noa.lua
@@ -101,6 +101,7 @@ local setfam = nuts.setfam
local setsubtype = nuts.setsubtype
local setattr = nuts.setattr
local setattrlist = nuts.setattrlist
+local setwidth = nuts.setwidth
local getfield = nuts.getfield
local getnext = nuts.getnext
@@ -211,6 +212,7 @@ local right_fence_code = fencecodes.right
-- local sf = setfield local st = setmetatableindex("number") setfield = function(n,f,v) st[f] = st[f] + 1 sf(n,f,v) end mathematics.SETFIELD = st
local function process(start,what,n,parent)
+
if n then
n = n + 1
else
@@ -456,6 +458,34 @@ do
"pseudobold",
}
+ families[math_fraction] = function(pointer,what,n,parent)
+ local a = getattr(pointer,a_mathfamily)
+ if a and a >= 0 then
+ if a > 0 then
+ setattr(pointer,a_mathfamily,0)
+ if a > 5 then
+ a = a - 3
+ end
+ end
+ setfam(pointer,a)
+ end
+ processnested(pointer,families,n+1)
+ end
+
+ families[math_noad] = function(pointer,what,n,parent)
+ local a = getattr(pointer,a_mathfamily)
+ if a and a >= 0 then
+ if a > 0 then
+ setattr(pointer,a_mathfamily,0)
+ if a > 5 then
+ a = a - 3
+ end
+ end
+ setfam(pointer,a)
+ end
+ processnested(pointer,families,n+1)
+ end
+
families[math_char] = function(pointer)
if getfam(pointer) == 0 then
local a = getattr(pointer,a_mathfamily)
@@ -501,7 +531,6 @@ do
end
end
end
-
families[math_delim] = function(pointer)
if getfield(pointer,"small_fam") == 0 then
local a = getattr(pointer,a_mathfamily)
diff --git a/tex/context/base/mkiv/math-tag.lua b/tex/context/base/mkiv/math-tag.lua
index d1ed90d38..9837dec35 100644
--- a/tex/context/base/mkiv/math-tag.lua
+++ b/tex/context/base/mkiv/math-tag.lua
@@ -287,8 +287,7 @@ else
local cache = { } -- we can have nested unboxed mess so best local to runner
local keep = nil
-- local keep = { } -- win case we might need to move keep outside
- for n in traverse_nodes(list) do
- local id = getid(n)
+ for n, id in traverse_nodes(list) do
local mth = id == math_code and getsubtype(n)
if mth == 0 then
-- insert(keep,text)
diff --git a/tex/context/base/mkiv/math-vfu.lua b/tex/context/base/mkiv/math-vfu.lua
index 4767ffa90..338a4bef7 100644
--- a/tex/context/base/mkiv/math-vfu.lua
+++ b/tex/context/base/mkiv/math-vfu.lua
@@ -46,9 +46,18 @@ fonts.encodings.math = mathencodings -- better is then: fonts.encodings.vecto
local vfmath = allocate()
fonts.handlers.vf.math = vfmath
+local helpers = fonts.helpers
+local vfcommands = helpers.commands
+local rightcommand = vfcommands.right
+local leftcommand = vfcommands.left
+local downcommand = vfcommands.down
+local upcommand = vfcommands.up
+local push = vfcommands.push
+local pop = vfcommands.pop
+
local shared = { }
--- local push, pop, back = { "push" }, { "pop" }, { "slot", 1, 0x2215 }
+-- local back = { "slot", 1, 0x2215 }
--
-- local function negate(main,characters,id,size,unicode,basecode)
-- if not characters[unicode] then
@@ -64,8 +73,8 @@ local shared = { }
-- commands = {
-- { "slot", 1, basecode },
-- push,
--- { "down", ht/5},
--- { "right", - wd/2},
+-- downcommand[ht/5],
+-- leftcommand[wd/2],
-- back,
-- push,
-- }
@@ -139,107 +148,96 @@ local function parent(main,characters,id,size,unicode,first,rule,last)
end
end
-local push, pop, step = { "push" }, { "pop" }, 0.2 -- 0.1 is nicer but gives larger files
+local step = 0.2 -- 0.1 is nicer but gives larger files
local function make(main,characters,id,size,n,m)
local old = 0xFF000 + n
- local c = characters[old]
+ local c = characters[old]
if c then
- local upslot, dnslot, uprule, dnrule = 0xFF100 + n, 0xFF200 + n, 0xFF300 + m, 0xFF400 + m
- local xu = main.parameters.x_height + 0.3*size
- local xd = 0.3*size
- local w, h, d = c.width, c.height, c.depth
+ local upslot = 0xFF100 + n
+ local dnslot = 0xFF200 + n
+ local uprule = 0xFF300 + m
+ local dnrule = 0xFF400 + m
+ local xu = main.parameters.x_height + 0.3*size
+ local xd = 0.3*size
+ local w = c.width
+ local h = c.height
+ local d = c.depth
local thickness = h - d
local rulewidth = step*size -- we could use an overlap
- local slot = { "slot", id, old }
- local rule = { "rule", thickness, rulewidth }
- local up = { "down", -xu }
- local dn = { "down", xd }
- local ht, dp = xu + 3*thickness, 0
+ local slot = { "slot", id, old }
+ local rule = { "rule", thickness, rulewidth }
+ local up = upcommand[xu]
+ local dn = downcommand[xd]
+ local ht = xu + 3*thickness
+ local dp = 0
if not characters[uprule] then
- characters[uprule] = { width = rulewidth, height = ht, depth = dp, commands = { push, up, rule, pop } }
+ characters[uprule] = {
+ width = rulewidth,
+ height = ht,
+ depth = dp,
+ commands = { push, up, rule, pop },
+ }
end
- characters[upslot] = { width = w, height = ht, depth = dp, commands = { push, up, slot, pop } }
- local ht, dp = 0, xd + 3*thickness
+ characters[upslot] = {
+ width = w,
+ height = ht,
+ depth = dp,
+ commands = { push, up, slot, pop },
+ }
+ local ht = 0
+ local dp = xd + 3*thickness
if not characters[dnrule] then
- characters[dnrule] = { width = rulewidth, height = ht, depth = dp, commands = { push, dn, rule, pop } }
+ characters[dnrule] = {
+ width = rulewidth,
+ height = ht,
+ depth = dp,
+ commands = { push, dn, rule, pop }
+ }
end
- characters[dnslot] = { width = w, height = ht, depth = dp, commands = { push, dn, slot, pop } }
+ characters[dnslot] = {
+ width = w,
+ height = ht,
+ depth = dp,
+ commands = { push, dn, slot, pop },
+ }
end
end
local function clipped(main,characters,id,size,unicode,original) -- push/pop needed?
local minus = characters[original]
if minus then
- local mu = size/18
- local step = 3*mu
+ local mu = size/18
+ local step = 3*mu
local width = minus.width
if width > step then
width = width - step
- step = step / 2
+ step = step / 2
else
width = width / 2
- step = width
+ step = width
end
characters[unicode] = {
width = width,
height = minus.height,
depth = minus.depth,
- commands = { push, { "right", -step }, { "slot", id, original }, pop }
+ commands = {
+ push,
+ leftcommand[step],
+ { "slot", id, original },
+ pop,
+ }
}
end
end
--- fails: pdf:page: pdf:direct: ... some funny displacement
-
--- this does not yet work ... { "scale", 2, 0, 0, 3 } .. commented code
---
--- this does not work ... no interpretation going on here
---
--- local nodeinjections = backends.nodeinjections
--- { "node", nodeinjections.save() },
--- { "node", nodeinjections.transform(.7,0,0,.7) },
--- commands[#commands+1] = { "node", nodeinjections.restore() }
-
--- local done = { }
---
--- local function raise(main,characters,id,size,unicode,private,n,id_of_smaller) -- this is a real fake mess
--- local raised = characters[private]
--- if raised then
--- if not done[unicode] then
--- report_virtual("temporary too large %U due to issues in luatex backend",unicode)
--- done[unicode] = true
--- end
--- local up = 0.85 * main.parameters.x_height
--- local slot = { "slot", id, private }
--- local commands = {
--- push,
--- { "down", - up },
--- -- { "scale", .7, 0, 0, .7 },
--- slot,
--- }
--- for i=2,n do
--- commands[#commands+1] = slot
--- end
--- commands[#commands+1] = pop
--- characters[unicode] = {
--- width = .7 * n * raised.width,
--- height = .7 * (raised.height + up),
--- depth = .7 * (raised.depth - up),
--- commands = commands,
--- }
--- end
--- end
-
local function raise(main,characters,id,size,unicode,private,n,id_of_smaller) -- this is a real fake mess
local raised = fonts.hashes.characters[main.fonts[id_of_smaller].id][private] -- characters[private]
if raised then
- local up = 0.85 * main.parameters.x_height
+ local up = 0.85 * main.parameters.x_height
local slot = { "slot", id_of_smaller, private }
local commands = {
- push,
- { "down", - up },
- slot,
+ push, upcommand[up], slot,
}
for i=2,n do
commands[#commands+1] = slot
@@ -258,65 +256,85 @@ end
local function dots(main,characters,id,size,unicode)
local c = characters[0x002E]
if c then
- local w, h, d = c.width, c.height, c.depth
- local mu = size/18
- local right3mu = { "right", 3*mu }
- local right1mu = { "right", 1*mu }
- local up1size = { "down", -.1*size }
- local up4size = { "down", -.4*size }
- local up7size = { "down", -.7*size }
- local right2muw = { "right", 2*mu + w }
- local slot = { "slot", id, 0x002E }
+ local w = c.width
+ local h = c.height
+ local d = c.depth
+ local mu = size/18
+ local right3mu = rightcommand[3*mu]
+ local right1mu = rightcommand[1*mu]
+ local up1size = upcommand[.1*size]
+ local up4size = upcommand[.4*size]
+ local up7size = upcommand[.7*size]
+ local right2muw = rightcommand[2*mu + w]
+ local slot = { "slot", id, 0x002E }
if unicode == 0x22EF then
local c = characters[0x022C5]
if c then
- local w, h, d = c.width, c.height, c.depth
- local slot = { "slot", id, 0x022C5 }
+ local width = c.width
+ local height = c.height
+ local depth = c.depth
+ local slot = { "slot", id, 0x022C5 }
characters[unicode] = {
- width = 3*w + 2*3*mu, height = h, depth = d,
- commands = { push, slot, right3mu, slot, right3mu, slot, pop }
+ width = 3*width + 2*3*mu,
+ height = height,
+ depth = depth,
+ commands = {
+ push, slot, right3mu, slot, right3mu, slot, pop,
+ }
}
end
elseif unicode == 0x22EE then
-- weird height !
characters[unicode] = {
- width = w, height = h+(1.4)*size, depth = 0,
- commands = { push, push, slot, pop, up4size, push, slot, pop, up4size, slot, pop }
+ width = w,
+ height = h+(1.4)*size,
+ depth = 0,
+ commands = {
+ push, push, slot, pop, up4size, push, slot, pop, up4size, slot, pop,
+ }
}
elseif unicode == 0x22F1 then
characters[unicode] = {
- width = 3*w + 6*size/18, height = 1.5*size, depth = 0,
+ width = 3*w + 6*size/18,
+ height = 1.5*size,
+ depth = 0,
commands = {
push,
- right1mu,
- push, up7size, slot, pop,
- right2muw,
- push, up4size, slot, pop,
- right2muw,
- push, up1size, slot, pop,
- right1mu,
+ right1mu,
+ push, up7size, slot, pop,
+ right2muw,
+ push, up4size, slot, pop,
+ right2muw,
+ push, up1size, slot, pop,
+ right1mu,
pop
}
}
elseif unicode == 0x22F0 then
characters[unicode] = {
- width = 3*w + 6*size/18, height = 1.5*size, depth = 0,
+ width = 3*w + 6*size/18,
+ height = 1.5*size,
+ depth = 0,
commands = {
push,
- right1mu,
- push, up1size, slot, pop,
- right2muw,
- push, up4size, slot, pop,
- right2muw,
- push, up7size, slot, pop,
- right1mu,
+ right1mu,
+ push, up1size, slot, pop,
+ right2muw,
+ push, up4size, slot, pop,
+ right2muw,
+ push, up7size, slot, pop,
+ right1mu,
pop
}
}
else
characters[unicode] = {
- width = 3*w + 2*3*mu, height = h, depth = d,
- commands = { push, slot, right3mu, slot, right3mu, slot, pop }
+ width = 3*w + 2*3*mu,
+ height = h,
+ depth = d,
+ commands = {
+ push, slot, right3mu, slot, right3mu, slot, pop,
+ }
}
end
end
@@ -331,21 +349,23 @@ local function vertbar(main,characters,id,size,parent,scale,unicode)
width = cp.width,
height = cp.height + sc,
depth = cp.depth + sc,
+ next = cp.next, -- can be extensible
commands = {
- push, { "down", -sc }, pc, pop,
- push, { "down", sc }, pc, pop,
+ push, upcommand [sc], pc, pop,
+ push, downcommand[sc], pc, pop,
pc,
},
- next = cp.next -- can be extensible
}
cp.next = unicode
end
end
local function jointwo(main,characters,id,size,unicode,u1,d12,u2,what)
- local c1, c2 = characters[u1], characters[u2]
+ local c1 = characters[u1]
+ local c2 = characters[u2]
if c1 and c2 then
- local w1, w2 = c1.width, c2.width
+ local w1 = c1.width
+ local w2 = c2.width
local mu = size/18
characters[unicode] = {
width = w1 + w2 - d12 * mu,
@@ -353,7 +373,7 @@ local function jointwo(main,characters,id,size,unicode,u1,d12,u2,what)
depth = max(c1.depth or 0, c2.depth or 0),
commands = {
{ "slot", id, u1 },
- { "right", -d12*mu } ,
+ leftcommand[d12*mu],
{ "slot", id, u2 },
},
}
@@ -361,19 +381,23 @@ local function jointwo(main,characters,id,size,unicode,u1,d12,u2,what)
end
local function jointhree(main,characters,id,size,unicode,u1,d12,u2,d23,u3)
- local c1, c2, c3 = characters[u1], characters[u2], characters[u3]
+ local c1 = characters[u1]
+ local c2 = characters[u2]
+ local c3 = characters[u3]
if c1 and c2 and c3 then
- local w1, w2, w3 = c1.width, c2.width, c3.width
+ local w1 = c1.width
+ local w2 = c2.width
+ local w3 = c3.width
local mu = size/18
characters[unicode] = {
width = w1 + w2 + w3 - d12*mu - d23*mu,
height = max(c1.height or 0, c2.height or 0, c3.height or 0),
- depth = max(c1.depth or 0, c2.depth or 0, c3.depth or 0),
+ depth = max(c1.depth or 0, c2.depth or 0, c3.depth or 0),
commands = {
{ "slot", id, u1 },
- { "right", - d12*mu } ,
+ leftcommand[d12*mu],
{ "slot", id, u2 },
- { "right", - d23*mu },
+ leftcommand[d23*mu],
{ "slot", id, u3 },
}
}
@@ -383,9 +407,8 @@ end
local function stack(main,characters,id,size,unicode,u1,d12,u2)
local c1, c2 = characters[u1], characters[u2]
if c1 and c2 then
- local w1, w2 = c1.width, c2.width
- local h1, h2 = c1.height, c2.height
- local d1, d2 = c1.depth, c2.depth
+ local w1, h1, d1 = c1.width, c1.height, c1.depth
+ local w2, h2, d2 = c2.width, c2.height, c2.depth
local mu = size/18
characters[unicode] = {
width = w1,
@@ -393,8 +416,8 @@ local function stack(main,characters,id,size,unicode,u1,d12,u2)
depth = d1,
commands = {
{ "slot", id, u1 },
- { "right", - w1/2 - w2/2 } ,
- { "down", -h1 + d2 -d12*mu } ,
+ leftcommand[w1/2 + w2/2],
+ downcommand[-h1 + d2 -d12*mu],
{ "slot", id, u2 },
}
}
@@ -407,15 +430,13 @@ local function repeated(main,characters,id,size,unicode,u,n,private,fraction) --
local width = c.width
local italic = fraction*width -- c.italic or 0 -- larger ones have funny italics
local tc = { "slot", id, u }
- local tr = { "right", -italic } -- see hack elsewhere
+ local tr = leftcommand[italic] -- see hack elsewhere
local commands = { }
for i=1,n-1 do
commands[#commands+1] = tc
commands[#commands+1] = tr
end
commands[#commands+1] = tc
--- inspect(c)
--- inspect(commands)
local next = c.next
if next then
repeated(main,characters,id,size,private,next,n,private+1,fraction)
@@ -623,7 +644,6 @@ local function copy_glyph(main,target,original,unicode,slot)
}
local newnextglyph = addprivate(main,formatters["M-N-%H"](nextglyph),newnextdata)
newdata.next = newnextglyph
--- report_virtual("copied next: %X",newdata.next)
local nextnextglyph = oldnextdata.next
if nextnextglyph == nextglyph then
break
@@ -649,7 +669,6 @@ local function copy_glyph(main,target,original,unicode,slot)
commands = { { "slot", slot, oldglyph } },
}
hvi.glyph = addprivate(main,formatters["M-H-%H"](oldglyph),newdata)
--- report_virtual("copied h variant: %X at index %i",hvi.glyph,i)
end
end
local vv = olddata.vert_variants
@@ -668,7 +687,6 @@ local function copy_glyph(main,target,original,unicode,slot)
commands = { { "slot", slot, oldglyph } },
}
vvi.glyph = addprivate(main,formatters["M-V-%H"](oldglyph),newdata)
--- report_virtual("copied v variant: %X at index %i",vvi.glyph,i)
end
end
return newdata
diff --git a/tex/context/base/mkiv/meta-blb.lua b/tex/context/base/mkiv/meta-blb.lua
new file mode 100644
index 000000000..202c2850b
--- /dev/null
+++ b/tex/context/base/mkiv/meta-blb.lua
@@ -0,0 +1,305 @@
+if not modules then modules = { } end modules ['meta-blb'] = {
+ version = 1.001,
+ comment = "companion to mlib-ctx.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+-- This could be integrated in other modules but for me it also serves
+-- as an example of usign the plugin mechanism.
+
+local tonumber = tonumber
+
+local setmetatableindex = table.setmetatableindex
+local insert, remove = table.insert, table.remove
+
+local topoints = number.topoints
+local mpprint = mp.print
+local mpinteger = mp.integer
+local mppoints = mp.points
+local mptriplet = mp.triplet
+local mptripletpoints = mp.tripletpoints
+
+local texsetbox = tex.setbox
+local toutf = nodes.toutf
+local hpack_nodes = nodes.hpack
+
+local trace = false
+local report = logs.reporter("metapost","blobs")
+
+trackers.register("metapost.blobs", function(v) trace = v end)
+
+-- We start with a text that comes from an analyze stage and can end up with
+-- one or more results. For practical reasons we store the blobs in one array
+-- and work with ranges.
+
+local allblobs = { }
+
+local function newcategory(t,k)
+ if trace then
+ report("new category %a",k)
+ end
+ local v = {
+ name = k,
+ text = "",
+ blobs = { },
+ }
+ t[k] = v
+ return v
+end
+
+local texblobs = setmetatableindex(newcategory)
+
+local function blob_raw_reset(category)
+ -- we need to keep the allblobs
+ if category then
+ if trace then
+ report("reset category %a",category)
+ end
+ texblobs[category] = nil
+ else
+ if trace then
+ report("reset all")
+ end
+ texblobs = setmetatableindex(newcategory)
+ end
+end
+
+local function blob_raw_dimensions(i)
+ local blob = allblobs[i]
+ if blob then
+ return blob.width, blob.height, blob.depth
+ else
+ return 0, 0, 0
+ end
+end
+
+local function blob_raw_content(i)
+ return allblobs[i]
+end
+
+local function blob_raw_toutf(i)
+ return toutf(allblobs[i])
+end
+
+local function blob_raw_wipe(i)
+ allblobs[i] = false
+end
+
+mp.blob_raw_dimensions = blob_raw_dimensions
+mp.blob_raw_content = blob_raw_content
+mp.blob_raw_reset = blob_raw_reset
+mp.blob_raw_wipe = blob_raw_wipe
+mp.blob_raw_toutf = blob_raw_toutf
+
+function mp.blob_new(category,text)
+ if trace then
+ report("category %a, text %a",category,text)
+ end
+ texblobs[category].text = text
+end
+
+function mp.blob_add(category,blob)
+ local tb = texblobs[category].blobs
+ local tn = #allblobs + 1
+ blob = hpack_nodes(blob)
+ allblobs[tn] = blob
+ tb[#tb+1] = tn
+ if trace then
+ report("category %a, blob %a set, content %a",category,tn,blob_raw_toutf(tn))
+ end
+end
+
+function mp.blob_width(category,i)
+ local index = texblobs[category].blobs[i]
+ local blob = allblobs[index]
+ if blob then
+ mppoints(blob.width or 0)
+ else
+ mpinteger(0)
+ end
+end
+
+function mp.blob_size(category,i)
+ mpprint(#texblobs[category].blobs or 0)
+end
+
+function mp.blob_index(category,i)
+ mpprint(texblobs[category].blobs[i] or 0)
+end
+
+function mp.blob_dimensions(category,i)
+ local index = texblobs[category].blobs[i]
+ local blob = allblobs[index]
+ if blob then
+ mptripletpoints(blob.width,blob.height,blob.depth)
+ else
+ mptriplet(0,0,0)
+ end
+end
+
+local f_f = string.formatters["%F"]
+local sxsy = metapost.sxsy
+local cm = metapost.cm
+
+local function injectblob(object,blob)
+ local sx, rx, ry, sy, tx, ty = cm(object)
+ local wd, ht, dp = blob_raw_dimensions(blob)
+ if wd then
+ object.path = false
+ object.color = false
+ object.grouped = true
+ object.istext = true
+ return function()
+ if trace then
+ report("injecting blob %a, width %p, heigth %p, depth %p, text %a",blob,wd,ht,dp,blob_raw_toutf(blob))
+ end
+ context.MPLIBgetblobscaledcm(blob,
+ f_f(sx), f_f(rx), f_f(ry),
+ f_f(sy), f_f(tx), f_f(ty),
+ sxsy(wd,ht,dp))
+ end
+ end
+end
+
+mp.blob_inject = injectblob
+
+local function getblob(box,blob)
+ texsetbox(box,blob_raw_content(blob))
+ blob_raw_wipe(blob)
+end
+
+interfaces.implement {
+ name = "mpgetblob",
+ actions = getblob,
+ arguments = { "integer", "integer" },
+}
+
+-- the plug:
+
+local function reset()
+ blob_raw_reset()
+end
+
+local function analyze(object,prescript)
+ -- nothing
+end
+
+local function process(object,prescript,before,after)
+ if prescript.tb_stage == "inject" then
+ local tb_blob = tonumber(prescript.tb_blob)
+ if tb_blob then
+ before[#before+1] = injectblob(object,tb_blob)
+ end
+ end
+end
+
+metapost.installplugin(reset,analyze,process)
+
+-- Here follows an example of usage of the above: a more modern
+-- version of followokens (in meta-imp-txt.mkiv).
+
+local nodecodes = nodes.nodecodes
+local kerncodes = nodes.kerncodes
+
+local glue_code = nodecodes.glue
+local kern_code = nodecodes.kern
+local c_userkern = kerncodes.userkern
+local c_fontkern = kerncodes.fontkern
+local c_italickern = kerncodes.italickern
+local a_fontkern = attributes.private("fontkern")
+
+local takebox = tex.takebox
+local flatten_list = node.flatten_discretionaries
+local remove_node = nodes.remove
+local flush_node = nodes.flush
+
+local addblob = mp.blob_add
+local newblob = mp.blob_new
+
+local visible_code = {
+ [nodecodes.glyph] = true,
+ [nodecodes.glue] = true,
+ [nodecodes.hlist] = true,
+ [nodecodes.vlist] = true,
+ [nodecodes.rule] = true,
+}
+
+local function initialize(category,box)
+ local wrap = takebox(box)
+ if wrap then
+ local head = wrap.list
+ local tail = nil
+ local temp = nil
+ if head then
+ local n = { }
+ local s = 0
+ head = flatten_list(head)
+ local current = head
+ while current do
+ local id = current.id
+ if visible_code[id] then
+ head, current, tail = remove_node(head,current)
+ s = s + 1
+ n[s] = tail
+ elseif id == kern_code then
+ local subtype = current.subtype
+ if subtype == c_fontkern or subtype == italickern then -- or current[a_fontkern]
+ head, current, temp = remove_node(head,current)
+ tail.next = temp
+ temp.prev = tail
+ tail = temp
+ else
+ head, current, temp = remove_node(head,current)
+ s = s + 1
+ n[s] = temp
+ end
+ elseif id == glue_code then
+ head, current, temp = remove_node(head,current)
+ s = s + 1
+ n[s] = temp
+ else
+ current = current.next
+ end
+ end
+ for i=1,s do
+ n[i] = addblob(category,n[i])
+ end
+ wrap.list = head
+ end
+ flush_node(wrap)
+ end
+end
+
+interfaces.implement {
+ name = "MPLIBconvertfollowtext",
+ arguments = { "integer","integer" },
+ actions = initialize,
+}
+
+local function reset()
+ -- nothing
+end
+
+local function analyze(object,prescript)
+ if prescript.ft_stage == "trial" then
+ local ft_category = tonumber(prescript.ft_category)
+ if ft_category then
+ newblob(ft_category,object.postscript) -- only for tracing
+ context.MPLIBfollowtext(ft_category,object.postscript)
+ metapost.getjobdata().multipass = true
+ end
+ end
+end
+
+local function process(object,prescript,before,after)
+ if prescript.ft_stage == "final" then
+ object.path = false
+ object.color = false
+ object.grouped = true
+ object.istext = true
+ end
+end
+
+metapost.installplugin(reset,analyze,process)
diff --git a/tex/context/base/mkiv/meta-blb.mkiv b/tex/context/base/mkiv/meta-blb.mkiv
new file mode 100644
index 000000000..78e2dde3e
--- /dev/null
+++ b/tex/context/base/mkiv/meta-blb.mkiv
@@ -0,0 +1,50 @@
+%D \module
+%D [ file=meta-blb,
+%D version=2018.04.12,
+%D title=\METAPOST\ Graphics,
+%D subtitle=Blobs,
+%D author=Hans Hagen,
+%D date=\ currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{MetaPost Graphics / Blobs}
+
+\registerctxluafile{meta-blb}{}
+
+\unprotect
+
+\unexpanded\def\MPLIBgetblobscaledcm#1#2#3#4#5#6#7#8#9%
+ {\clf_mpgetblob\MPtextbox#1\relax
+ \setbox\MPbox\hpack\bgroup
+ \dotransformnextbox{#2}{#3}{#4}{#5}{#6}{#7}%
+ \vpack to \zeropoint\bgroup
+ \vss
+ \hpack to \zeropoint \bgroup
+ % \fastsxsy{#8}{#9}{\raise\dp\MPtextbox\box\MPtextbox}%
+ \fastsxsy{#8}{#9}{\box\MPtextbox}%
+ \hss
+ \egroup
+ \egroup
+ \egroup
+ \smashbox\MPbox
+ \box\MPbox}
+
+%D An example of usage:
+
+\definefontfeature[followtext][liga=no]
+
+\unexpanded\def\MPLIBfollowtext#1#2%
+ {\begingroup
+ \scratchcounter#1\relax
+ \setbox\scratchbox\hbox{\addff{followtext}#2}%
+ \clf_MPLIBconvertfollowtext\scratchcounter\scratchbox
+ \endgroup}
+
+% \def\reversedtext#1%
+% {\cldcontext{table.concat(table.reverse(utf.totable(\!!bs#1\!!es)))}}
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/meta-imp-txt.mkiv b/tex/context/base/mkiv/meta-imp-txt.mkiv
index e9660b3a7..34e36ae54 100644
--- a/tex/context/base/mkiv/meta-imp-txt.mkiv
+++ b/tex/context/base/mkiv/meta-imp-txt.mkiv
@@ -203,6 +203,7 @@
\startluacode
local nodecodes = nodes.nodecodes
+ local kerncodes = nodes.kerncodes
local visible_code = {
[nodecodes.glyph] = true,
@@ -212,54 +213,39 @@
[nodecodes.rule] = true,
}
- local disc_code = nodecodes.disc
- local kern_code = nodecodes.kern
-
- local c_userkern = nodes.kerncodes.userkern
+ local kern_code = nodecodes.kern
+ local c_userkern = kerncodes.userkern
local a_fontkern = attributes.private("fontkern")
local n = nil
local s = 0
function mp.follow_reset()
- r = nil
+ n = nil
s = 0
end
function mp.follow_initialize(b)
- if not r then
- local l = tex.takebox(b).list
- n = { }
- s = 0
- while l do
- local c = l
- l = l.next
- local id = c.id
- if visible_code[id] then
- s = s + 1
- n[s] = c
- c.prev = nil
- c.next = nil
- elseif id == kern_code then
- if c.subtype == c_userkern and not c[a_fontkern] then
+ if not n then
+ local head = tex.takebox(b).list
+ if head then
+ n = { }
+ s = 0
+ head = node.flatten_discretionaries(head)
+ local current = head
+ while current do
+ local id = current.id
+ if visible_code[id] then
s = s + 1
- n[s] = c
- c.prev = nil
- else
- n[s].next = c
- c.prev = n[s]
- end
- c.next = nil
- elseif id == disc_code then
- local r = c.replace
- while r do
+ head, current, n[s] = nodes.remove(head,current)
+ elseif id == kern_code and current.subtype == c_userkern and not current[a_fontkern] then
s = s + 1
- n[s] = r
- r = r.next
- r.prev = nil
- r.next = nil
+ head, current, n[s] = nodes.remove(head,current)
+ else
+ current = current.next
end
end
+ nodes.flush_list(head)
end
end
end
diff --git a/tex/context/base/mkiv/mlib-lua.lua b/tex/context/base/mkiv/mlib-lua.lua
index 19e731b85..d934e6472 100644
--- a/tex/context/base/mkiv/mlib-lua.lua
+++ b/tex/context/base/mkiv/mlib-lua.lua
@@ -62,11 +62,16 @@ end
local f_code = formatters["%s return mp._f_()"]
-local f_numeric = formatters["%.16f"]
-local f_integer = formatters["%i"]
-local f_pair = formatters["(%.16f,%.16f)"]
-local f_triplet = formatters["(%.16f,%.16f,%.16f)"]
-local f_quadruple = formatters["(%.16f,%.16f,%.16f,%.16f)"]
+local f_numeric = formatters["%.16f"]
+local f_integer = formatters["%i"]
+local f_pair = formatters["(%.16f,%.16f)"]
+local f_triplet = formatters["(%.16f,%.16f,%.16f)"]
+local f_quadruple = formatters["(%.16f,%.16f,%.16f,%.16f)"]
+
+local f_points = formatters["%p"]
+local f_pair_pt = formatters["(%p,%p)"]
+local f_triplet_pt = formatters["(%p,%p,%p)"]
+local f_quadruple_pt = formatters["(%p,%p,%p,%p)"]
local function mpprint(...) -- we can optimize for n=1
for i=1,select("#",...) do
@@ -156,6 +161,11 @@ function mp.integer(i)
buffer[n] = i or "0"
end
+function mp.points(i)
+ n = n + 1
+ buffer[n] = i and f_points(i) or "0pt"
+end
+
function mp.pair(x,y)
n = n + 1
if type(x) == "table" then
@@ -165,6 +175,15 @@ function mp.pair(x,y)
end
end
+function mp.pairpoints(x,y)
+ n = n + 1
+ if type(x) == "table" then
+ buffer[n] = f_pair_pt(x[1],x[2])
+ else
+ buffer[n] = f_pair_pt(x,y)
+ end
+end
+
function mp.triplet(x,y,z)
n = n + 1
if type(x) == "table" then
@@ -174,6 +193,15 @@ function mp.triplet(x,y,z)
end
end
+function mp.tripletpoints(x,y,z)
+ n = n + 1
+ if type(x) == "table" then
+ buffer[n] = f_triplet_pt(x[1],x[2],x[3])
+ else
+ buffer[n] = f_triplet_pt(x,y,z)
+ end
+end
+
function mp.quadruple(w,x,y,z)
n = n + 1
if type(w) == "table" then
@@ -183,7 +211,16 @@ function mp.quadruple(w,x,y,z)
end
end
-function mp.path(t,connector,cycle)
+function mp.quadruplepoints(w,x,y,z)
+ n = n + 1
+ if type(w) == "table" then
+ buffer[n] = f_quadruple_pt(w[1],w[2],w[3],w[4])
+ else
+ buffer[n] = f_quadruple_pt(w,x,y,z)
+ end
+end
+
+local function mppath(f,t,connector,cycle)
if type(t) == "table" then
local tn = #t
if tn > 0 then
@@ -194,11 +231,11 @@ function mp.path(t,connector,cycle)
connector = "--"
end
local ti = t[1]
- n = n + 1 ; buffer[n] = f_pair(ti[1],ti[2])
+ n = n + 1 ; buffer[n] = f(ti[1],ti[2])
for i=2,tn do
local ti = t[i]
n = n + 1 ; buffer[n] = connector
- n = n + 1 ; buffer[n] = f_pair(ti[1],ti[2])
+ n = n + 1 ; buffer[n] = f(ti[1],ti[2])
end
if cycle then
n = n + 1 ; buffer[n] = connector
@@ -208,6 +245,14 @@ function mp.path(t,connector,cycle)
end
end
+function mp.path(...)
+ mppath(f_pair,...)
+end
+
+function mp.pathpoints(...)
+ mppath(f_pair_pt,...)
+end
+
function mp.size(t)
n = n + 1
buffer[n] = type(t) == "table" and f_numeric(#t) or "0"
diff --git a/tex/context/base/mkiv/mlib-pdf.lua b/tex/context/base/mkiv/mlib-pdf.lua
index 75f810fb3..453d00aef 100644
--- a/tex/context/base/mkiv/mlib-pdf.lua
+++ b/tex/context/base/mkiv/mlib-pdf.lua
@@ -430,7 +430,7 @@ function metapost.flush(result,flusher,askedfig)
startfigure(properties.number,llx,lly,urx,ury,"begin",figure)
result[#result+1] = "q"
if objects then
- resetplugins(result) -- we should move the colorinitializer here
+-- resetplugins(result) -- we should move the colorinitializer here
local savedpath = nil
local savedhtap = nil
for o=1,#objects do
@@ -640,6 +640,7 @@ function metapost.flush(result,flusher,askedfig)
end
end
metapost.comment = nocomment
+ resetplugins(result) -- we should move the colorinitializer here
end
end
end
diff --git a/tex/context/base/mkiv/mlib-pps.lua b/tex/context/base/mkiv/mlib-pps.lua
index bb5ce31e5..1a6aa5e86 100644
--- a/tex/context/base/mkiv/mlib-pps.lua
+++ b/tex/context/base/mkiv/mlib-pps.lua
@@ -541,6 +541,8 @@ local function sxsy(wd,ht,dp) -- helper for text
return (wd ~= 0 and factor/wd) or 0, (hd ~= 0 and factor/hd) or 0
end
+metapost.sxsy = sxsy
+
-- for stock mp we need to declare the booleans first
local no_first_run = "boolean mfun_first_run ; mfun_first_run := false ;"
@@ -906,14 +908,7 @@ end
function metapost.resetplugins(t) -- intialize plugins, before figure
if top.plugmode then
-
outercolormodel = colors.currentmodel() -- currently overloads the one set at the tex end
-
- -- plugins can have been added
- resetter = resetteractions.runner
- analyzer = analyzeractions.runner
- processor = processoractions.runner
- -- let's apply one runner
resetter(t)
end
end
@@ -967,6 +962,8 @@ local function cm(object)
return 1, 0, 0, 1, 0, 0 -- weird case
end
+metapost.cm = cm
+
-- color
local function cl_reset(t)
@@ -1591,7 +1588,6 @@ function mp.get_outline_text(index) -- maybe we need a more private namespace
mp.print(outlinetexts[index] or "draw origin;")
end
-
-- definitions
appendaction(resetteractions, "system",ot_reset)
@@ -1616,17 +1612,20 @@ appendaction(processoractions,"system",tr_process) -- last, as color can be rese
appendaction(processoractions,"system",la_process)
--- function metapost.installplugin(reset,analyze,process)
--- if reset then
--- appendaction(resetteractions,"system",reset)
--- end
--- if analyze then
--- appendaction(analyzeractions,"system",analyze)
--- end
--- if process then
--- appendaction(processoractions,"system",process)
--- end
--- end
+function metapost.installplugin(reset,analyze,process)
+ if reset then
+ appendaction(resetteractions,"system",reset)
+ end
+ if analyze then
+ appendaction(analyzeractions,"system",analyze)
+ end
+ if process then
+ appendaction(processoractions,"system",process)
+ end
+ resetter = resetteractions .runner
+ analyzer = analyzeractions .runner
+ processor = processoractions.runner
+end
-- we're nice and set them already
diff --git a/tex/context/base/mkiv/mult-low.lua b/tex/context/base/mkiv/mult-low.lua
index 0acba3b87..be5e90889 100644
--- a/tex/context/base/mkiv/mult-low.lua
+++ b/tex/context/base/mkiv/mult-low.lua
@@ -197,8 +197,8 @@ return {
--
"hglue", "vglue", "hfillneg", "vfillneg", "hfilllneg", "vfilllneg",
--
- "ruledhss", "ruledhfil", "ruledhfill", "ruledhfilneg", "ruledhfillneg", "normalhfillneg",
- "ruledvss", "ruledvfil", "ruledvfill", "ruledvfilneg", "ruledvfillneg", "normalvfillneg",
+ "ruledhss", "ruledhfil", "ruledhfill", "ruledhfilll", "ruledhfilneg", "ruledhfillneg", "normalhfillneg", "normalhfilllneg",
+ "ruledvss", "ruledvfil", "ruledvfill", "ruledvfilll", "ruledvfilneg", "ruledvfillneg", "normalvfillneg", "normalvfilllneg",
"ruledhbox", "ruledvbox", "ruledvtop", "ruledvcenter", "ruledmbox",
"ruledhpack", "ruledvpack", "ruledtpack",
"ruledhskip", "ruledvskip", "ruledkern", "ruledmskip", "ruledmkern",
diff --git a/tex/context/base/mkiv/mult-prm.lua b/tex/context/base/mkiv/mult-prm.lua
index 1cd5f5810..53c30d7ed 100644
--- a/tex/context/base/mkiv/mult-prm.lua
+++ b/tex/context/base/mkiv/mult-prm.lua
@@ -298,7 +298,9 @@ return {
"mathrulesfam",
"mathrulesmode",
"mathscriptsmode",
+ "mathscriptcharmode",
"mathscriptboxmode",
+ "mathrulethicknessmode",
"mathstyle",
"mathsurroundmode",
"mathsurroundskip",
diff --git a/tex/context/base/mkiv/node-aux.lua b/tex/context/base/mkiv/node-aux.lua
index 84567068b..5e85ead1c 100644
--- a/tex/context/base/mkiv/node-aux.lua
+++ b/tex/context/base/mkiv/node-aux.lua
@@ -154,9 +154,8 @@ function nodes.repackhlist(list,...)
end
local function set_attributes(head,attr,value)
- for n in traverse_nodes(head) do
+ for n, id in traverse_nodes(head) do
setattr(n,attr,value)
- local id = getid(n)
if id == hlist_node or id == vlist_node then
set_attributes(getlist(n),attr,value)
end
@@ -164,11 +163,10 @@ local function set_attributes(head,attr,value)
end
local function set_unset_attributes(head,attr,value)
- for n in traverse_nodes(head) do
+ for n, id in traverse_nodes(head) do
if not getattr(n,attr) then
setattr(n,attr,value)
end
- local id = getid(n)
if id == hlist_code or id == vlist_code then
set_unset_attributes(getlist(n),attr,value)
end
@@ -176,9 +174,8 @@ local function set_unset_attributes(head,attr,value)
end
local function unset_attributes(head,attr)
- for n in traverse_nodes(head) do
+ for n, id in traverse_nodes(head) do
setattr(n,attr,unsetvalue)
- local id = getid(n)
if id == hlist_code or id == vlist_code then
unset_attributes(getlist(n),attr)
end
@@ -431,8 +428,7 @@ nodes.link = function(list,currentfont,currentattr,head,tail)
end
local function locate(start,wantedid,wantedsubtype)
- for n in traverse_nodes(start) do
- local id = getid(n)
+ for n, id in traverse_nodes(start) do
if id == wantedid then
if not wantedsubtype or getsubtype(n) == wantedsubtype then
return n
diff --git a/tex/context/base/mkiv/node-met.lua b/tex/context/base/mkiv/node-met.lua
index 12a9256bc..4141c8b66 100644
--- a/tex/context/base/mkiv/node-met.lua
+++ b/tex/context/base/mkiv/node-met.lua
@@ -62,6 +62,26 @@ end
-- statistics.tracefunction(node, "node", "getfield","setfield")
-- statistics.tracefunction(node.direct,"node.direct","getfield","setfield")
+if LUATEXFUNCTIONALITY < 6695 then
+
+ local getnext = node.getnext
+ local getid = node.getid
+
+ local function iterate(h,n)
+ if n then
+ local n = getnext(n)
+ return n, getid(n)
+ elseif h then
+ return h, getid(h), getnext(h)
+ end
+ end
+
+ function node.traverse(h)
+ return iterate, h
+ end
+
+end
+
-- We start with some helpers and provide all relevant basic functions in the
-- node namespace as well.
@@ -163,7 +183,7 @@ local n_setlink = node.setlink or -- always
-- not that fast but not used often anyway
local h = nil
for i=1,select("#",...) do
- local n = (select(i,...))
+ local n = select(i,...)
if not n then
-- go on
elseif h then
diff --git a/tex/context/base/mkiv/node-nut.lua b/tex/context/base/mkiv/node-nut.lua
index 3e9a08b48..302ece4bf 100644
--- a/tex/context/base/mkiv/node-nut.lua
+++ b/tex/context/base/mkiv/node-nut.lua
@@ -143,16 +143,6 @@ nodes.tonut = tonut
-- helpers
-if not direct.getfam then -- LUATEXVERSION < 1.070
-
- local getfield = direct.getfield
- local setfield = direct.setfield
-
- direct.getfam = function(n) return getfield(n,"small_fam") end
- direct.setfam = function(n,f) setfield(n,"small_fam",f) end
-
-end
-
if not direct.getdirection then
local getdir = direct.getdir
@@ -184,6 +174,26 @@ if not direct.getdirection then
end
+if LUATEXFUNCTIONALITY < 6695 then
+
+ local getnext = direct.getnext
+ local getid = direct.getid
+
+ local function iterate(h,n)
+ if n then
+ local n = getnext(n)
+ return n, getid(n)
+ elseif h then
+ return h, getid(h), getnext(h)
+ end
+ end
+
+ function direct.traverse(h)
+ return iterate, h
+ end
+
+end
+
local nuts = nodes.nuts
nuts.tostring = direct.tostring
diff --git a/tex/context/base/mkiv/node-shp.lua b/tex/context/base/mkiv/node-shp.lua
index 2e7a3529a..2c20d9567 100644
--- a/tex/context/base/mkiv/node-shp.lua
+++ b/tex/context/base/mkiv/node-shp.lua
@@ -192,8 +192,7 @@ local function count(head,data,subcategory)
-- no components, pre, post, replace .. can maybe an option .. but
-- we use this for optimization so it makes sense to look the the
-- main node only
- for n in traverse_nodes(tonut(head)) do
- local id = getid(n)
+ for n, id in traverse_nodes(tonut(head)) do
local dn = data[nodecodes[id]] -- we could use id and then later convert to nodecodes
dn[subcategory] = dn[subcategory] + 1
if id == hlist_code or id == vlist_code then
diff --git a/tex/context/base/mkiv/node-tra.lua b/tex/context/base/mkiv/node-tra.lua
index f12599866..a2e5a7653 100644
--- a/tex/context/base/mkiv/node-tra.lua
+++ b/tex/context/base/mkiv/node-tra.lua
@@ -198,8 +198,7 @@ function nodes.idstostring(head,tail)
local t = { }
local last_id = nil
local last_n = 0
- for n in traverse_nodes(head,tail) do -- hm, does not stop at tail
- local id = getid(n)
+ for n, id in traverse_nodes(head,tail) do -- hm, does not stop at tail
if id == whatsit_code then
id = whatcodes[getsubtype(n)]
else
@@ -354,8 +353,7 @@ local what = { [0] = "unknown", "line", "box", "indent", "row", "cell" }
local function showboxes(n,symbol,depth)
depth = depth or 0
symbol = symbol or "."
- for n in traverse_nodes(tonut(n)) do
- local id = getid(n)
+ for n, id in traverse_nodes(tonut(n)) do
if id == hlist_code or id == vlist_code then
local s = getsubtype(n)
report_nodes(rep(symbol,depth) .. what[s] or s)
diff --git a/tex/context/base/mkiv/publ-ini.lua b/tex/context/base/mkiv/publ-ini.lua
index 8497b190f..9dfeda168 100644
--- a/tex/context/base/mkiv/publ-ini.lua
+++ b/tex/context/base/mkiv/publ-ini.lua
@@ -2325,13 +2325,13 @@ do
implement {
name = "btxflushlistentry",
- arguments = "2 strings",
+ arguments = { "string", "integer" },
actions = lists.flushentry,
}
implement {
name = "btxflushlisttag",
- arguments = "2 strings",
+ arguments = { "string", "integer" },
actions = lists.flushtag,
}
diff --git a/tex/context/base/mkiv/spac-ver.lua b/tex/context/base/mkiv/spac-ver.lua
index 969a195e1..8f2136f95 100644
--- a/tex/context/base/mkiv/spac-ver.lua
+++ b/tex/context/base/mkiv/spac-ver.lua
@@ -290,8 +290,7 @@ local function validvbox(parentid,list)
end
end
local done = nil
- for n in traverse_nodes(list) do
- local id = getid(n)
+ for n, id in traverse_nodes(list) do
if id == vlist_code or id == hlist_code then
if done then
return nil
@@ -326,8 +325,7 @@ local function already_done(parentid,list,a_snapmethod) -- todo: done when only
return false
end
end
- for n in traverse_nodes(list) do
- local id = getid(n)
+ for n, id in traverse_nodes(list) do
if id == hlist_code or id == vlist_code then
-- local a = getattr(n,a_snapmethod)
-- if not a then
@@ -1917,8 +1915,7 @@ do
local flush = false
stackhack = true -- todo: only when grid snapping once enabled
-- todo: fast check if head = tail
- for n in traverse_nodes(newhead) do -- we could just look for glue nodes
- local id = getid(n)
+ for n, id in traverse_nodes(newhead) do -- we could just look for glue nodes
if id ~= glue_code then
flush = true
else
diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf
index 452af8333..d3b0db503 100644
--- a/tex/context/base/mkiv/status-files.pdf
+++ b/tex/context/base/mkiv/status-files.pdf
Binary files differ
diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf
index c4928ecb0..87aefae39 100644
--- a/tex/context/base/mkiv/status-lua.pdf
+++ b/tex/context/base/mkiv/status-lua.pdf
Binary files differ
diff --git a/tex/context/base/mkiv/strc-doc.mkiv b/tex/context/base/mkiv/strc-doc.mkiv
index 805525487..3b4b656d3 100644
--- a/tex/context/base/mkiv/strc-doc.mkiv
+++ b/tex/context/base/mkiv/strc-doc.mkiv
@@ -29,4 +29,14 @@
\xdef\currentstructureattribute {\the\lastdestinationattribute}%
\xdef\currentstructuresynchronize{\strc_lists_inject_enhance{#1}{\the\locationcount}}}
+\unexpanded\def\setstructurecomponentsynchronization#1% todo: use ctxcontext
+ {\clf_setinternalreference
+ prefix {\currentstructurecomponentreferenceprefix}%
+ reference {\currentstructurecomponentreference}
+ internal \locationcount
+ view {\interactionparameter\c!focus}%
+ \relax
+ \xdef\currentstructurecomponentattribute {\the\lastdestinationattribute}%
+ \xdef\currentstructurecomponentsynchronize{\strc_lists_inject_enhance{#1}{\the\locationcount}}}
+
\protect \endinput
diff --git a/tex/context/base/mkiv/strc-mar.lua b/tex/context/base/mkiv/strc-mar.lua
index 24a7fd491..a2cbc2ab2 100644
--- a/tex/context/base/mkiv/strc-mar.lua
+++ b/tex/context/base/mkiv/strc-mar.lua
@@ -116,8 +116,7 @@ end
-- identify range
local function sweep(head,first,last)
- for n in traverse(head) do
- local id = getid(n)
+ for n, id in traverse(head) do
if id == glyph_code then
local a = getattr(n,a_marks)
if not a then
diff --git a/tex/context/base/mkiv/strc-num.mkiv b/tex/context/base/mkiv/strc-num.mkiv
index be35e7671..cca66a6f5 100644
--- a/tex/context/base/mkiv/strc-num.mkiv
+++ b/tex/context/base/mkiv/strc-num.mkiv
@@ -669,11 +669,9 @@
%}
\relax
\xdef\m_strc_counters_last_registered_index{\the\scratchcounter}%
- \clf_setinternalreference
- internal \locationcount
- \relax
- \xdef\m_strc_counters_last_registered_attribute {\the\lastdestinationattribute}%
- \xdef\m_strc_counters_last_registered_synchronize{\strc_lists_inject_enhance{\m_strc_counters_last_registered_index}{\the\locationcount}}}
+ \setstructurecomponentsynchronization\m_strc_counters_last_registered_index
+ \glet\m_strc_counters_last_registered_attribute \currentstructurecomponentattribute
+ \glet\m_strc_counters_last_registered_synchronize\currentstructurecomponentsynchronize}
\let\m_strc_counters_last_registered_index \relax
\let\m_strc_counters_last_registered_attribute \relax
diff --git a/tex/context/base/mkiv/strc-ref.lua b/tex/context/base/mkiv/strc-ref.lua
index f20d93161..02971c3f9 100644
--- a/tex/context/base/mkiv/strc-ref.lua
+++ b/tex/context/base/mkiv/strc-ref.lua
@@ -137,6 +137,7 @@ storage.register("structures/references/defined", references.defined, "structure
local initializers = { }
local finalizers = { }
+local somefound = false -- so we don't report missing when we have a fresh start
function references.registerinitializer(func) -- we could use a token register instead
initializers[#initializers+1] = func
@@ -162,6 +163,7 @@ local function initializer() -- can we use a tobesaved as metatable for collecte
end
end
end
+ somefound = next(collected)
end
local function finalizer()
@@ -370,6 +372,8 @@ implement {
arguments = "2 strings",
}
+local reported = setmetatableindex("table")
+
function references.set(data)
local references = data.references
local reference = references.reference
@@ -388,10 +392,16 @@ function references.set(data)
if ref == "" then
-- skip
elseif check_duplicates and pd[ref] then
- if prefix and prefix ~= "" then
- report_references("redundant reference %a in namespace %a",ref,prefix)
- else
- report_references("redundant reference %a",ref)
+ if not prefix then
+ prefix = ""
+ end
+ if not reported[prefix][ref] then
+ if prefix ~= "" then
+ report_references("redundant reference %a in namespace %a",ref,prefix)
+ else
+ report_references("redundant reference %a",ref)
+ end
+ reported[prefix][ref] = true
end
else
n = n + 1
@@ -1004,9 +1014,9 @@ local function loadexternalreferences(name,utilitydata)
local pages = struc.pages.collected -- pagenumber data
-- a bit weird one, as we don't have the externals in the collected
for prefix, set in next, external do
-if prefix == "" then
- prefix = name -- this can clash!
-end
+ if prefix == "" then
+ prefix = name -- this can clash!
+ end
for reference, data in next, set do
if trace_importing then
report_importing("registering %a reference, kind %a, name %a, prefix %a, reference %a",
@@ -1034,9 +1044,9 @@ end
if kind and realpage then
references.pagedata = pages[realpage]
local prefix = references.prefix or ""
-if prefix == "" then
- prefix = name -- this can clash!
-end
+ if prefix == "" then
+ prefix = name -- this can clash!
+ end
local target = external[prefix]
if not target then
target = { }
@@ -1847,7 +1857,9 @@ function references.valid(prefix,reference,specification)
local str = f_valid(prefix,reference)
local u = unknowns[str]
if not u then
- interfaces.showmessage("references",1,str) -- 1 = unknown, 4 = illegal
+ if somefound then
+ interfaces.showmessage("references",1,str) -- 1 = unknown, 4 = illegal
+ end
unknowns[str] = 1
nofunknowns = nofunknowns + 1
else
@@ -1987,7 +1999,7 @@ local function setinternalreference(specification)
-- ugly .. later we decide to ignore it when we have a real one
-- but for testing we might want to see them all
if internal then
- if innermethod ~= v_name then -- so page and auto
+ if innermethod ~= v_name then -- innermethod == v_auto
-- we don't want too many #1 #2 #3 etc
tn = tn + 1
t[tn] = internal -- when number it's internal
diff --git a/tex/context/base/mkiv/strc-ref.mkvi b/tex/context/base/mkiv/strc-ref.mkvi
index d0752407c..6d0e369b1 100644
--- a/tex/context/base/mkiv/strc-ref.mkvi
+++ b/tex/context/base/mkiv/strc-ref.mkvi
@@ -45,19 +45,18 @@
% \definespecial\dosetexecuteJScode
% ...
-%D This module deals with referencing. In \CONTEXT\ referencing is one of
-%D the core features, although at a first glance probably nobody will
-%D notice. This is good, because referencing should be as hidden as possible.
+%D This module deals with referencing. In \CONTEXT\ referencing is one of the core
+%D features, although at a first glance probably nobody will notice. This is good,
+%D because referencing should be as hidden as possible.
%D
-%D Before we start implementing functionality we provide a way to set
-%D up this mechanism.
+%D Before we start implementing functionality we provide a way to set up this
+%D mechanism.
%D
%D \showsetup{setupreferencing}
%D
-%D In interactive documents verbose references don't always
-%D make sense (what is a page number in an unnumbered
-%D document). By setting the \type{interaction} variable, one
-%D can influences the way interactive references are set.
+%D In interactive documents verbose references don't always make sense (what is a
+%D page number in an unnumbered document). By setting the \type{interaction}
+%D variable, one can influences the way interactive references are set.
\let\referenceprefix\empty
@@ -122,9 +121,8 @@
\dosetdirectpagereference\m_strc_references_asked
\fi}
-%D Actually there is not much difference between a text and a
-%D full reference, but it's the concept that counts. The low
-%D level implementation is:
+%D Actually there is not much difference between a text and a full reference, but
+%D it's the concept that counts. The low level implementation is:
\newcount\lastreferenceattribute
\newcount\lastdestinationattribute
@@ -134,8 +132,8 @@
\let\dofinishreference\strc_references_finish % used at lua end
-% This is somewhat tricky: we want to keep the reference with the following word but
-% that word should also hyphenate. We need to find a better way.
+%D This is somewhat tricky: we want to keep the reference with the following word but
+%D that word should also hyphenate. We need to find a better way.
% 0 = nothing
% 1 = bind to following word
@@ -502,34 +500,31 @@
%D \macros
%D {everyreference}
%D
-%D For rather tricky purposes, one can assign sanitizing
-%D macros to \type{\everyreference} (no longer that relevant).
+%D For rather tricky purposes, one can assign sanitizing macros to \type
+%D {\everyreference} (no longer that relevant).
\newevery \everyreference \relax
-%D This is really needed, since for instance Polish has a
-%D different alphabet and needs accented entries in registers.
+%D This is really needed, since for instance Polish has a different alphabet and
+%D needs accented entries in registers.
\appendtoks
\cleanupfeatures
\to \everyreference
-%D We did not yet discuss prefixing. Especially in interactive
-%D documents, it's not always easy to keep track of duplicate
-%D references. The prefix mechanism, which we will describe
-%D later on, solves this problem. By (automatically) adding a
-%D prefix one keeps references local, but the global ones in
-%D view. To enable this feature, we explictly split the prefix
-%D from the reference.
+%D We did not yet discuss prefixing. Especially in interactive documents, it's not
+%D always easy to keep track of duplicate references. The prefix mechanism, which we
+%D will describe later on, solves this problem. By (automatically) adding a prefix
+%D one keeps references local, but the global ones in view. To enable this feature,
+%D we explictly split the prefix from the reference.
\let\referenceprefix\empty
-%D For a long time the only way to access an external file was
-%D to use the file prefix (\type {somefile::}. However, when
-%D you split up a document, redefining the references may be
-%D such a pain, that another approach is feasible. By setting
-%D the \type {autofile} variable to \type {yes} or \type
-%D {page}, you can access the reference directly.
+%D For a long time the only way to access an external file was to use the file
+%D prefix (\type {somefile::}. However, when you split up a document, redefining the
+%D references may be such a pain, that another approach is feasible. By setting the
+%D \type {autofile} variable to \type {yes} or \type {page}, you can access the
+%D reference directly.
%D
%D \starttabulate[||||]
%D \NC filename::tag \NC page(filename::pnum) \NC tag \NC\NR
@@ -540,9 +535,9 @@
\unexpanded\def\usereferences[#filename]{} % obsolete
-%D As mentioned we will also use the cross reference mechanism
-%D for navigational purposes. The main reason for this is that
-%D we want to treat both categories alike:
+%D As mentioned we will also use the cross reference mechanism for navigational
+%D purposes. The main reason for this is that we want to treat both categories
+%D alike:
%D
%D \starttyping
%D \goto{go back}[PreviousJump]
@@ -553,15 +548,13 @@
%D \type{colofon page} reference is, apart from hyperlinking, a
%D rather normal reference.
%D
-%D We already saw that cross refences are written to and read
-%D from a file. The pure navigational ones don't need to be
-%D written to file, but both for fast processing and
-%D transparant integration, they are saved internally as a sort
-%D of reference. We can easily distinguish such system
-%D references from real cross reference ones by their tag.
+%D We already saw that cross refences are written to and read from a file. The pure
+%D navigational ones don't need to be written to file, but both for fast processing
+%D and transparant integration, they are saved internally as a sort of reference. We
+%D can easily distinguish such system references from real cross reference ones by
+%D their tag.
%D
-%D We also use the odd/even characteristic to determine the
-%D page state.
+%D We also use the odd/even characteristic to determine the page state.
\let\currentrealreference \empty
\let\currentpagereference \empty
@@ -576,11 +569,10 @@
%
% 0 = no page ref, 1=same page, 2=before, 3=after
-%D Cross references appear as numbers (figure~1.1, chapter~2)
-%D or pagenumbers (page~2, page 3--2), and are called with
-%D \type{\in} and \type{\at}. In interactive documents we also
-%D have \type{\goto}, \type{\button} and alike. These are more
-%D versatile and look like:
+%D Cross references appear as numbers (figure~1.1, chapter~2) or pagenumbers
+%D (page~2, page 3--2), and are called with \type {\in} and \type {\at}. In
+%D interactive documents we also have \type {\goto}, \type {\button} and alike.
+%D These are more versatile and look like:
%D
%D \starttyping
%D \goto[reference]
@@ -592,23 +584,19 @@
%D \goto[action{argument}]
%D \stoptyping
%D
-%D The first one is a normal reference, the second and third
-%D are references to a file or \URL. The brace delimited
-%D references for instance refer to a \JAVASCRIPT. The last
-%D example shows that we can pass arguments to the actions.
+%D The first one is a normal reference, the second and third are references to a
+%D file or \URL. The brace delimited references for instance refer to a \JAVASCRIPT.
+%D The last example shows that we can pass arguments to the actions.
%D
-%D Now we've come to the testing step. As we can see below,
-%D this macro does bit more than testing: it also resolves
-%D the reference. This means that whenever we test for the
-%D existance of a reference at an outer level, we have all the
-%D relevant properties of that reference avaliable inside the
-%D true branche~(\type{#2}).
+%D Now we've come to the testing step. As we can see below, this macro does bit more
+%D than testing: it also resolves the reference. This means that whenever we test
+%D for the existance of a reference at an outer level, we have all the relevant
+%D properties of that reference avaliable inside the true branche~(\type {#2}).
%D
-%D The prefix has to do with localizing references. When a
-%D prefix is set, looking for a reference comes to looking for
-%D the prefixed one, and when not found, looking for the non
-%D prefixed one. Consider for instance the prefix set to
-%D \type{sidetrack}.
+%D The prefix has to do with localizing references. When a prefix is set, looking
+%D for a reference comes to looking for the prefixed one, and when not found,
+%D looking for the non prefixed one. Consider for instance the prefix set to \type
+%D {sidetrack}.
%D
%D \starttyping
%D \pagereference[important]
@@ -625,17 +613,15 @@
%D ...{sidetrack}{important}...
%D \stoptyping
%D
-%D Now when we call for \type{unimportant}, we will indeed get
-%D the pagenumber associated to this reference. But when we
-%D call for \type{important}, while the prefix is still set, we
-%D will get the pagenumber bound to the prefixed one.
+%D Now when we call for \type{unimportant}, we will indeed get the pagenumber
+%D associated to this reference. But when we call for \type{important}, while the
+%D prefix is still set, we will get the pagenumber bound to the prefixed one.
%D
%D {\em Some day, when processing time and memory are no longer
%D performance factors, we will introduce multi||level
%D prefixes.}
%D
-%D Before we start analyzing, I introduce a general
-%D definition macro. Consider:
+%D Before we start analyzing, I introduce a general definition macro. Consider:
%D
%D \starttyping
%D \goto{do}[JS(My_Script{"test",123}),titlepage]
@@ -652,8 +638,7 @@
%D
%D \showsetup{definereference}
%D
-%D We can trace references by setting the next switch to
-%D true.
+%D We can trace references by setting the next switch to true.
\unexpanded\def\definereference
{\dodoubleempty\strc_references_define_reference}
@@ -673,23 +658,22 @@
%D \goto{somewhere}[JS(somescript),nextpage,JS(anotherscript)]
%D \stoptyping
%D
-%D Actually supporting chains is up to the special driver. Here
-%D we only provide the hooks.
+%D Actually supporting chains is up to the special driver. Here we only provide the
+%D hooks.
%D \macros
%D {highlighthyperlinks}
%D
-%D The next switch can be used to make user hyperlinks are
-%D not highlighted when clicked on.
+%D The next switch can be used to make user hyperlinks are not highlighted when
+%D clicked on.
\newconditional\highlighthyperlinks \settrue\highlighthyperlinks
%D \macros
%D {gotonewwindow}
%D
-%D To make the {\em goto previous jump} feature more
-%D convenient when using more than one file, it makes sense
-%D to force the viewer to open a new window for each file
+%D To make the {\em goto previous jump} feature more convenient when using more than
+%D one file, it makes sense to force the viewer to open a new window for each file
%D opened.
\newconditional\gotonewwindow \setfalse\gotonewwindow
@@ -708,13 +692,11 @@
\let\doifreferencefoundelse \doifelsereferencefound
-%D The tester only splits the reference in components but does
-%D not look into them. The following macro does a preroll and
-%D determines for instance the current real reference pagenumber.
-%D The \type {\currentrealreference} macro does the same so unless
-%D one wants to use the pagestate the next macro seldom needs to
-%D be called.
-
+%D The tester only splits the reference in components but does not look into them.
+%D The following macro does a preroll and determines for instance the current real
+%D reference pagenumber. The \type {\currentrealreference} macro does the same so
+%D unless one wants to use the pagestate the next macro seldom needs to be called.
+%D
%D The inner case is simple. Only two cases have to be taken
%D care of:
%D
@@ -723,8 +705,8 @@
%D \goto{some text}[prefix:reference]
%D \stoptyping
%D
-%D References to other files however are treated strict or
-%D tolerant, depending on their loading and availability:
+%D References to other files however are treated strict or tolerant, depending on
+%D their loading and availability:
%D
%D \starttyping
%D \useexternaldocument[somefile][filename][a nice description]
@@ -734,72 +716,61 @@
%D \goto{unchecked reference}[anotherfile::reference]
%D \stoptyping
%D
-%D An unknown reference is reported on the screen, in the log
-%D file and, when enabled, in the left margin of the text.
+%D An unknown reference is reported on the screen, in the log file and, when
+%D enabled, in the left margin of the text.
\let\unknownreference\gobbleoneargument
-%D When a reference is not found, we typeset a placeholder
-%D (two glyphs are often enough to represent the reference
-%D text).
+%D When a reference is not found, we typeset a placeholder (two glyphs are often
+%D enough to represent the reference text).
\def\dummyreference{{\tttf ??}}
\def\emptyreference{{\tttf !!}}
-%D To prevent repetitive messages concerning a reference
-%D being defined, we set such an unknown reference to an empty
-%D one after the first encounter.
-
-%D Apart from cross references supplied by the user, \CONTEXT\
-%D generates cross references itself. Most of them are not
-%D saved as a reference, but stored with their source, for
-%D instance a list or an index entry. Such automatically
-%D generated, for the user invisible, references are called
-%D {\em internal references}. The user supplied ones are
-%D labeled as {\em external references}.
-%D
-%D A second important characteristic is that when we want to
-%D support different backends (viewers), we need to support
-%D named destinations as well as page numbers. I invite readers
-%D to take a glance at the special driver modules to understand
-%D the fine points of this. As a result we will deal with {\em
-%D locations} as well as {\em real page numbers}. We explictly
-%D call this pagenumber a real one, because it is independant
-%D of the page numbering scheme used in the document.
-%D
-%D One of the reasons for \CONTEXT\ being the first \TEX\ base
-%D macropackage to support sophisticated interactive \PDF\
-%D files, lays in the mere fact that real page numbers are
-%D available in most two pass data, like references, list data
-%D and index entries.
-%D
-%D We will speak of \type{thisis...} when we are marking a
-%D location, and \type{goto...} when we point to such a
-%D location. The latter one can be seen as a hyperlink to the
-%D former one. In the next macros one we use constructs like:
+%D To prevent repetitive messages concerning a reference being defined, we set such
+%D an unknown reference to an empty one after the first encounter.
+%D
+%D Apart from cross references supplied by the user, \CONTEXT\ generates cross
+%D references itself. Most of them are not saved as a reference, but stored with
+%D their source, for instance a list or an index entry. Such automatically
+%D generated, for the user invisible, references are called {\em internal
+%D references}. The user supplied ones are labeled as {\em external references}.
+%D
+%D A second important characteristic is that when we want to support different
+%D backends (viewers), we need to support named destinations as well as page
+%D numbers. I invite readers to take a glance at the special driver modules to
+%D understand the fine points of this. As a result we will deal with {\em locations}
+%D as well as {\em real page numbers}. We explictly call this pagenumber a real one,
+%D because it is independant of the page numbering scheme used in the document.
+%D
+%D One of the reasons for \CONTEXT\ being the first \TEX\ base macropackage to
+%D support sophisticated interactive \PDF\ files, lays in the mere fact that real
+%D page numbers are available in most two pass data, like references, list data and
+%D index entries.
+%D
+%D We will speak of \type {thisis...} when we are marking a location, and
+%D \type {goto...} when we point to such a location. The latter one can be seen as a
+%D hyperlink to the former one. In the next macros one we use constructs like:
%D
%D \starttyping
%D \dostart...
%D \dostop...
%D \stoptyping
%D
-%D Such macros are used to invoke the relevant specials from
-%D the special driver modules (see \type{spec-ini}). The flag
-%D \type{\iflocation} signals if we're in interactive mode.
+%D The flag \type {\iflocation} signals if we're in interactive mode.
\ifdefined\buttonheight \else \newdimen\buttonheight \fi
\ifdefined\buttonwidth \else \newdimen\buttonwidth \fi
-%D Internal references can best be set using the next few
-%D macros. Setting such references to unique values is
-%D completely up to the macros that call them.
+%D Internal references can best be set using the next few macros. Setting such
+%D references to unique values is completely up to the macros that call them.
%D
%D \starttyping
%D \thisissomeinternal{tag}{identifier}
%D \gotosomeinternal {tag}{identifier}{pagenumber}{text}
%D \stoptyping
-
-%D We could do this in lua ...
+%D
+%D We could do this in \LUA\ \unknown
\newif \iflocation
\newcount\locationcount
@@ -845,12 +816,10 @@
\def\gotonextinternal#text#target%
{\directgoto{#text}[internal(#target)]}
-%D In this module we define three system references: one for
-%D handling navigational, viewer specific, commands, another
-%D for jumping to special pages, like the first or last one,
-%D and a third reference for linking tree like lists, like
-%D tables of contents. The latter two adapt themselves to the
-%D current state.
+%D In this module we define three system references: one for handling navigational,
+%D viewer specific, commands, another for jumping to special pages, like the first
+%D or last one, and a third reference for linking tree like lists, like tables of
+%D contents. The latter two adapt themselves to the current state.
%D
%D An example of an action is:
%D
@@ -863,11 +832,10 @@
%D \starttyping
%D \goto{some text}[\v!action(PreviousJump]
%D \stoptyping
-
-%D One can also activate an automatic prefix mechanism. By
-%D setting the \type{\prefix} variable to \type{+}, the prefix
-%D is incremented, when set to \type{-} or empty, the prefix is
-%D reset. Other values become the prefix.
+%D
+%D One can also activate an automatic prefix mechanism. By setting the
+%D \type {\prefix} variable to \type {+}, the prefix is incremented, when set to
+%D \type {-} or empty, the prefix is reset. Other values become the prefix.
\newcount\prefixcounter
@@ -892,13 +860,6 @@
\unexpanded\def\setupglobalreferenceprefix[#prefix]%
{\xdef\referenceprefix{#prefix}}
-% \unexpanded\def\pushreferenceprefix#prefix%
-% {\pushmacro\referenceprefix
-% \xdef\referenceprefix{#prefix}} % global
-
-% \unexpanded\def\popreferenceprefix
-% {\popmacro\referenceprefix}
-
\unexpanded\def\globalpushreferenceprefix#prefix%
{\xdef\referenceprefix{\clf_pushreferenceprefix{#prefix}}}
@@ -935,16 +896,14 @@
\setupreferenceprefix[\referencingparameter\c!prefix]
\to \everysetupreferencing
-%D We can typeset a reference using \type{\in}, \type{\at} and
-%D \type{\about} and goto specific locations using
-%D \type{\goto}. The last one does not make that much sense in
-%D a paper document. To complicate things, \PLAIN\ \TEX\ also
-%D implements an \type {\in} but fortunately that one only
-%D makes sense in math mode.
+%D We can typeset a reference using \type {\in}, \type {\at} and \type {\about} and
+%D goto specific locations using \type {\goto}. The last one does not make that much
+%D sense in a paper document. To complicate things, \PLAIN\ \TEX\ also implements an
+%D \type {\in} but fortunately that one only makes sense in math mode.
%D
-%D Typesetting the reference is a bit more complicated than one
-%D would at first sight expect. This is due to the fact that we
-%D distinguish three (five) alternative calls:
+%D Typesetting the reference is a bit more complicated than one would at first sight
+%D expect. This is due to the fact that we distinguish three (five) alternative
+%D calls:
%D
%D \placefigure
%D [here][three calls]
@@ -971,25 +930,11 @@
%D \getbuffer
%D \stoplines
%D
-%D The dual \type{{}} results in a split reference. In a
-%D document meant for paper, one is tempted to use the last
-%D (most straightforward) alternative. When a document is also
-%D meant voor electronic distribution, the former alternatives
-%D have preference, because everything between the \type{\in}
-%D and~\type{[} becomes active (and when asked for, typeset
-%D in a different color and typeface).
-
-% \unexpanded\def\in {\mathortext\donormalmathin \strc_references_in}
-% \unexpanded\def\at {\mathortext\donormalmathat \strc_references_at}
-% \unexpanded\def\about{\mathortext\donormalmathabout\strc_references_about}
-% \unexpanded\def\from {\mathortext\donormalmathfrom \strc_references_from}
-% \unexpanded\def\over {\mathortext\donormalmathover \strc_references_about}
-
-% \definecommand in {\strc_references_in}
-% \definecommand at {\strc_references_at}
-% \definecommand about {\strc_references_about}
-% \definecommand from {\strc_references_from}
-% \definecommand over {\strc_references_about} % needed here, else math problems
+%D The dual \type {{}} results in a split reference. In a document meant for paper,
+%D one is tempted to use the last (most straightforward) alternative. When a
+%D document is also meant voor electronic distribution, the former alternatives have
+%D preference, because everything between the \type {\in} and~\type {[} becomes
+%D active (and when asked for, typeset in a different color and typeface).
\appendtoks
\ifdefined\in \let\normalmathin \in \unexpanded\def\in {\mathortext\normalmathin \strc_references_in } \else \let\in \strc_references_in \fi
@@ -1009,8 +954,7 @@
\def\currentreferencedefault {\clf_filterreference{default}}
\def\currentreferencerealpage{\clf_filterreference{realpage}}
-%D The most straightforward way of retrieving references is
-%D using \type{\ref}.
+%D The most straightforward way of retrieving references is using \type {\ref}.
\unexpanded\def\getreference % checking, unexpanded
{\dodoubleargument\strc_references_get_reference}
@@ -1040,12 +984,11 @@
\referencingparameter\c!right
\endgroup}
-%D The previously discussed setup macro lets us specify the
-%D representation of references. A symbol reference does not
-%D show the specific data, like the number of a figure, but
-%D shows one of: \hbox {$^\goforwardcharacter$
-%D $^\gobackwardcharacter$ $^\gonowherecharacter$}, depending
-%D on the direction to go.
+%D The previously discussed setup macro lets us specify the representation of
+%D references. A symbol reference does not show the specific data, like the number
+%D of a figure, but shows one of: \hbox {$^\goforwardcharacter$
+%D $^\gobackwardcharacter$ $^\gonowherecharacter$}, depending on the direction to
+%D go.
%D
%D \starttyping
%D ... \somewhere{backward text}{forward text}[someref] ...
@@ -1242,15 +1185,6 @@
\setvalue{\??referencinginteraction\v!symbol}%
{\referencesymbol}
-% \def\referencesequence
-% {\csname\??referencinginteraction
-% \ifcsname\??referencinginteraction\referencingparameter\c!interaction\endcsname
-% \referencingparameter\c!interaction
-% \else
-% \v!all
-% \fi
-% \endcsname}
-
\def\referencesequence
{\ifcsname\??referencinginteraction\referencingparameter\c!interaction\endcsname
\expandafter\lastnamedcs
@@ -1311,9 +1245,8 @@
%D \macros
%D {definereferenceformat}
%D
-%D The next few macros were made for for David Arnold and Taco
-%D Hoekwater. They can be used for predefining reference
-%D texts, and thereby stimulate efficiency.
+%D The next few macros were made for for David Arnold and Taco Hoekwater. They can
+%D be used for predefining reference texts, and thereby stimulate efficiency.
%D
%D \starttyping
%D \definereferenceformat[informula] [left=(,right=),text=formula]
@@ -1328,11 +1261,11 @@
%D the \informulas [b] \andformula [for:c]
%D \stoptyping
%D
-%D Instead of a text, one can specify a label, which should
-%D be defined with \type {\setuplabeltext}.
+%D Instead of a text, one can specify a label, which should be defined with \type
+%D {\setuplabeltext}.
%D
-%D Watch out: the second argument is somewhat special and mostly
-%D meant for a suffix to a number:
+%D Watch out: the second argument is somewhat special and mostly meant for a suffix
+%D to a number:
%D
%D \startbuffer
%D \definereferenceformat [intesta] [left=(,right=),text=Whatever~]
@@ -1437,21 +1370,18 @@
%
% \definereferenceformat[hellup][text=Hellup ,setups=referenceformat:numberplustext]
-%D In interactive documents going to a specific location is not
-%D bound to cross references. The \type{\goto} commands can be
-%D used to let users access another part of the document. In
-%D this respect, interactive tables of contents and registers
-%D can be considered goto's. Because in fact a \type{\goto} is
-%D just a reference without reference specific data, the
-%D previous macros are implemented using the goto
-%D functionality.
+%D In interactive documents going to a specific location is not bound to cross
+%D references. The \type {\goto} commands can be used to let users access another
+%D part of the document. In this respect, interactive tables of contents and
+%D registers can be considered goto's. Because in fact a \type {\goto} is just a
+%D reference without reference specific data, the previous macros are implemented
+%D using the goto functionality.
%D
%D \showsetup{goto}
%D
-%D One important characteristic is that the first argument of
-%D \type{\goto} (and therefore \type{\at} and \type{\in} is
-%D split at spaces. This means that, although hyphenation is
-%D prevented, long references can cross line endings.
+%D One important characteristic is that the first argument of \type {\goto} (and
+%D therefore \type {\at} and \type {\in} is split at spaces. This means that,
+%D although hyphenation is prevented, long references can cross line endings.
% \starttext
% \setupinteraction[state=start]
@@ -1744,17 +1674,15 @@
{\box\scratchbox}%
\endgroup}
-%D An reference to another document can be specified as a file
-%D or as an \URL. Both are handled by the same mechanism and
-%D can be issued by saying something like:
+%D An reference to another document can be specified as a file or as an \URL. Both
+%D are handled by the same mechanism and can be issued by saying something like:
%D
%D \starttyping
%D \goto[dictionary::the letter a]
%D \stoptyping
%D
-%D One can imagine that many references to such a dictionary
-%D are made, so in most cases such a document reference in an
-%D indirect one.
+%D One can imagine that many references to such a dictionary are made, so in most
+%D cases such a document reference in an indirect one.
%D
%D \showsetup{useexternaldocument}
%D
@@ -1766,8 +1694,8 @@
%D [The Famous English Dictionary]
%D \stoptyping
%D
-%D The next macro implements these relations, and also take
-%D care of loading the document specific references.
+%D The next macro implements these relations, and also take care of loading the
+%D document specific references.
%D
%D The \URL\ alternative takes four arguments:
%D
@@ -1789,9 +1717,8 @@
%D \useURL [id] [url]
%D \stoptyping
%D
-%D This time we don't load the references when no file is
-%D specified. This is logical when one keeps in mind that a
-%D valid \URL\ can also be a mail address.
+%D This time we don't load the references when no file is specified. This is logical
+%D when one keeps in mind that a valid \URL\ can also be a mail address.
\unexpanded\def\useurl {\doquadrupleempty\strc_references_use_url } % so that they can be used in expanded arguments
\unexpanded\def\usefile{\dotripleargument\strc_references_use_file} % so that they can be used in expanded arguments
@@ -1814,8 +1741,7 @@
%D \macros
%D {url,setupurl}
%D
-%D We also have: \type{\url} for directly calling the
-%D description. So we can say:
+%D We also have: \type {\url} for directly calling the description. So we can say:
%D
%D \starttyping
%D \useURL [one] [http://www.test.nl]
@@ -1843,8 +1769,8 @@
\hyphenatedurl{\clf_geturl{#label}}%
\endgroup}
-%D This macro is hooked into a support macro, and thereby
-%D \URL's break ok, according to the setting of a switch,
+%D This macro is hooked into a support macro, and thereby \URL's break ok, according
+%D to the setting of a switch,
%D
%D \startbuffer
%D \useURL
@@ -1858,9 +1784,8 @@
%D
%D \getbuffer
-%D When defining the external source of information, one can
-%D also specify a suitable name (the last argument). This name
-%D can be called upon with:
+%D When defining the external source of information, one can also specify a suitable
+%D name (the last argument). This name can be called upon with:
%D
%D \showsetup{from}
%D
@@ -1895,9 +1820,8 @@
%D \goto{some text}[identifier::location]
%D \stoptyping
-%D A special case of references are those to programs. These,
-%D very system dependant references are implemented by abusing
-%D some of the previous macros.
+%D A special case of references are those to programs. These, very system dependant
+%D references are implemented by abusing some of the previous macros.
%D
%D \showsetup{setupprograms}
%D \showsetup{defineprogram}
@@ -1925,8 +1849,7 @@
\clf_getprogram{#name}%
\endgroup}
-%D As we can see, we directly use the special reference
-%D mechanism, which means that
+%D As we can see, we directly use the special reference mechanism, which means that
%D
%D \starttyping
%D \goto{some text}[program(name{args})]
@@ -1934,11 +1857,10 @@
%D
%D is valid.
-%D The next macro provides access to the actual pagenumbers.
-%D When documenting and sanitizing the original reference
-%D macros, I decided to keep the present meaning as well as to
-%D make this meaning available as a special reference method.
-%D So now one can use:
+%D The next macro provides access to the actual pagenumbers. When documenting and
+%D sanitizing the original reference macros, I decided to keep the present meaning
+%D as well as to make this meaning available as a special reference method. So now
+%D one can use:
%D
%D \starttyping
%D \gotopage{some text}[location]
@@ -1967,8 +1889,7 @@
\def\gotopage#text[#target]%
{\goto{#text}[\v!page(#target)]}
-%D The previous definitions are somewhat obsolete so we don't
-%D use it here.
+%D The previous definitions are somewhat obsolete so we don't use it here.
%D We can cross link documents by using:
%D
@@ -1980,16 +1901,14 @@
%D \coupledocument[print][somefile][chapter,section]
%D \stoptyping
%D
-%D After which when applicable, we have available the
-%D references:
+%D After which when applicable, we have available the references:
%D
%D \starttyping
%D \goto{print version}[print::chapter]
%D \stoptyping
%D
-%D and alike. The title placement definition macros have a
-%D key \type{file}, which is interpreted as the file to jump
-%D to, that is, when one clicks on the title.
+%D and alike. The title placement definition macros have a key \type {file}, which
+%D is interpreted as the file to jump to, that is, when one clicks on the title.
\def\coupledocument
{\doquadrupleempty\strc_references_couple_document}
@@ -2002,8 +1921,8 @@
%D \macros
%D {dotextprefix}
%D
-%D In previous macros we used \type {\dotextprefix} to
-%D generate a space between a label and a number.
+%D In previous macros we used \type {\dotextprefix} to generate a space between
+%D a label and a number.
%D
%D \starttyping
%D \dotextprefix{text}
@@ -2026,9 +1945,8 @@
\fi
\endgroup}
-%D In the next settings we see some variables that were not
-%D used here and that concern the way the pagenumbers refered
-%D to are typeset.
+%D In the next settings we see some variables that were not used here and that
+%D concern the way the pagenumbers refered to are typeset.
\setupreferencing
[\c!state=\v!start,
diff --git a/tex/context/base/mkiv/supp-box.lua b/tex/context/base/mkiv/supp-box.lua
index 40047167c..3ea16dcf8 100644
--- a/tex/context/base/mkiv/supp-box.lua
+++ b/tex/context/base/mkiv/supp-box.lua
@@ -55,6 +55,7 @@ local setdisc = nuts.setdisc
local setwidth = nuts.setwidth
local setheight = nuts.setheight
local setdepth = nuts.setdepth
+local setshift = nuts.setshift
local flush_node = nuts.flush_node
local flush_list = nuts.flush_list
@@ -601,4 +602,10 @@ do
end
}
+ interfaces.implement {
+ name = "shiftbox",
+ arguments = { "integer", "dimension" },
+ actions = function(n,d) setshift(getbox(n),d) end,
+ }
+
end
diff --git a/tex/context/base/mkiv/supp-box.mkiv b/tex/context/base/mkiv/supp-box.mkiv
index fb9cbdf5d..5fc34ba74 100644
--- a/tex/context/base/mkiv/supp-box.mkiv
+++ b/tex/context/base/mkiv/supp-box.mkiv
@@ -2974,6 +2974,11 @@
% \unexpanded\def\tightvbox{\dowithnextbox{\dp\nextbox\zeropoint\box\nextbox}\vbox}
% \unexpanded\def\tightvtop{\dowithnextbox{\ht\nextbox\zeropoint\box\nextbox}\vtop}
+%D This one keeps dimensions and sets the shift field (and so it's more for testing
+%D than for real usage):
+
+\unexpanded\def\shiftbox{\clf_shiftbox}
+
\protect \endinput
% a bit of test code:
diff --git a/tex/context/base/mkiv/syst-aux.mkiv b/tex/context/base/mkiv/syst-aux.mkiv
index 77f947753..ee5761af0 100644
--- a/tex/context/base/mkiv/syst-aux.mkiv
+++ b/tex/context/base/mkiv/syst-aux.mkiv
@@ -491,8 +491,6 @@
%D \type {\def} comes into action. This way the space after \type {\:} becomes a
%D delimiter of the longer named \type {\reinspectnextcharacter}.
-% try: \expandafter\def\firstofoneargument{\syst_helpers_reinspect_next_character} {...}
-
\let\next\:
\def\:{\let\blankspace= } \:
@@ -514,6 +512,31 @@
\let\:\next
+%D This is much nicer and works too:
+
+% \def\firstofoneargument#1{#1}
+%
+% \expandafter\let\firstofoneargument{\blankspace= }
+%
+% \expandafter\def\firstofoneargument{\syst_helpers_reinspect_next_character
+% } {\let\if_next_blank_space_token\iftrue
+% \futurelet\nexttoken\syst_helpers_inspect_next_character}
+%
+% \expandafter\def\firstofoneargument{\syst_helpers_reinspect_next_optional_character
+% } {\let\if_next_blank_space_token\iftrue
+% \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+%
+% \expandafter\def\firstofoneargument{\syst_helpers_reinspect_next_bgroup_character
+% } {\let\if_next_blank_space_token\iftrue
+% \futurelet\nexttoken\syst_helpers_inspect_next_bgroup_character}
+%
+% \expandafter\def\firstofoneargument{\syst_helpers_reinspect_next_parenthesis_character
+% } {\let\if_next_blank_space_token\iftrue
+% \futurelet\nexttoken\syst_helpers_inspect_next_parenthesis_character}
+%
+% \expandafter\def\firstofoneargument{\syst_helpers_ignore_spacing_blankspace
+% } {\futurelet\nexttoken\syst_helpers_ignore_spacing}
+
%D \macros
%D {setvalue,setgvalue,setevalue,setxvalue,
%D letvalue,letgvalue,getvalue,resetvalue,
@@ -3183,17 +3206,25 @@
%D Apart from the prefixes, a few more \type{\expandafters}
%D are needed:
-\unexpanded\def\newif#1%
- {\privatescratchcounter\escapechar
- \escapechar\minusone
- \expandafter\expandafter\expandafter
- \redoglobal\expandafter\expandafter\expandafter
- \edef\@if#1{true}{\let\noexpand#1\noexpand\iftrue}%
- \expandafter\expandafter\expandafter
- \redoglobal\expandafter\expandafter\expandafter
- \edef\@if#1{false}{\let\noexpand#1\noexpand\iffalse}%
- \dodoglobal\@if#1{false}%
- \escapechar\privatescratchcounter}
+% \unexpanded\def\newif#1% uses the original plain \@if
+% {\privatescratchcounter\escapechar
+% \escapechar\minusone
+% \expandafter\expandafter\expandafter
+% \redoglobal\expandafter\expandafter\expandafter
+% \edef\@if#1{true}{\let\noexpand#1\noexpand\iftrue}%
+% \expandafter\expandafter\expandafter
+% \redoglobal\expandafter\expandafter\expandafter
+% \edef\@if#1{false}{\let\noexpand#1\noexpand\iffalse}%
+% \dodoglobal\@if#1{false}%
+% \escapechar\privatescratchcounter}
+
+\normalprotected\def\newif#1% see syst-ini.mkiv
+ {\let\new_if_saved\newif
+ \let\newif\new_if_check
+ \expandafter\redoglobal\expandafter\def\csname\expandafter\newif\csstring#1true\endcsname {\let#1\iftrue }%
+ \expandafter\redoglobal\expandafter\def\csname\expandafter\newif\csstring#1false\endcsname{\let#1\iffalse}%
+ \dodoglobal\csname\expandafter\newif\csstring#1false\endcsname
+ \let\newif\new_if_saved}
%D Also new:
diff --git a/tex/context/base/mkiv/syst-ini.mkiv b/tex/context/base/mkiv/syst-ini.mkiv
index 4b5cc616b..c27b832bb 100644
--- a/tex/context/base/mkiv/syst-ini.mkiv
+++ b/tex/context/base/mkiv/syst-ini.mkiv
@@ -19,51 +19,85 @@
%D Characters can have special states, that can be triggered by setting their
%D category coded. Some are preset, others are to be set as soon as possible,
%D otherwise we cannot define any useful macros.
-
-%catcode`\^^@ = 9 % ascii null is ignored
-%catcode`\\ = 0 % backslash is TeX escape character
-
-\catcode`\{ = 1 % left brace is begin-group character
-\catcode`\} = 2 % right brace is end-group character
-\catcode`\$ = 3 % dollar sign is math shift
-\catcode`\& = 4 % ampersand is alignment tab
-\catcode`\# = 6 % hash mark is macro parameter character
-\catcode`\^ = 7 % circumflex and uparrow are for superscripts
-\catcode`\_ = 8 % underline and downarrow are for subscripts
-\catcode`\^^I = 10 % ascii tab is a blank space
-
-%catcode`\^^M = 5 % ascii return is end-line
-%catcode`\% = 14 % percent sign is comment character
-%catcode`\ = 10 % ascii space is blank space
-%catcode`\^^? = 15 % ascii delete is invalid
-
-\catcode`\~ = 13 % tilde is active
-\catcode`\^^L = 13 % ascii form-feed
-
-%catcode`\A = 11
-%.......
-%catcode`\Z = 11
-
-%catcode`\a = 11
-%.......
-%catcode`\z = 11
-
-\def ^^L{\par}
-\def\^^M{\ } % control <return> = control <space>
-\def\^^I{\ } % same for <tab>
-
-%D In \CONTEXT, we simply ignore end||of||file tokens:
-
-\catcode`\^^Z=9
+%D
+%D First we define a bunch of constants. Normally we would \type {\setconstant}
+%D but we're prestine and have no macros defined yet. Abstraction also makes it
+%D possible to avoid the \type {^^} in the input.
+
+\chardef\escapecatcode 0
+\chardef\begingroupcatcode 1
+\chardef\endgroupcatcode 2
+\chardef\mathshiftcatcode 3
+\chardef\alignmentcatcode 4
+\chardef\endoflinecatcode 5
+\chardef\parametercatcode 6
+\chardef\superscriptcatcode 7
+\chardef\subscriptcatcode 8
+\chardef\ignorecatcode 9
+\chardef\spacecatcode 10
+\chardef\lettercatcode 11
+\chardef\othercatcode 12 % finally obsolete: \let\other \othercatcode
+\chardef\activecatcode 13 % finally obsolete: \let\active\activecatcode
+\chardef\commentcatcode 14
+\chardef\invalidcatcode 15
+
+%chardef\zeroasciicode 0
+\chardef\tabasciicode 9
+\chardef\newlineasciicode 10 % don't confuse this one with \endoflineasciicode
+\chardef\formfeedasciicode 12
+\chardef\endoflineasciicode 13 % somewhat messy but this can be the active \par
+\chardef\endoffileasciicode 26
+\chardef\spaceasciicode 32
+\chardef\exclamationmarkasciicode 33 % ! used in namespace protection
+\chardef\doublequoteasciicode 34 % "
+\chardef\hashasciicode 35
+\chardef\dollarasciicode 36
+\chardef\commentasciicode 37
+\chardef\ampersandasciicode 38
+\chardef\singlequoteasciicode 39 % '
+\chardef\primeasciicode 39 % '
+\chardef\hyphenasciicode 45
+\chardef\forwardslashasciicode 47 % /
+\chardef\colonasciicode 58
+\chardef\lessthanasciicode 60 % < used as alternative verbatim {
+\chardef\morethanasciicode 62 % > used as alternative verbatim }
+\chardef\questionmarkasciicode 63 % ? used in namespace protection
+\chardef\atsignasciicode 64 % @ used in namespace protection
+\chardef\backslashasciicode 92 % `\\
+\chardef\circumflexasciicode 94
+\chardef\underscoreasciicode 95
+\chardef\leftbraceasciicode 123 % `\{
+\chardef\barasciicode 124 % `\|
+\chardef\rightbraceasciicode 125 % `\}
+\chardef\tildeasciicode 126 % `\~
+\chardef\delasciicode 127
+
+%catcode\zeroasciicode \ignorecatcode % `\^^@ ascii null is ignored
+\catcode\tabasciicode \spacecatcode % `\^^I ascii tab is a blank space
+\catcode\formfeedasciicode \activecatcode % `\^^L ascii form-feed (active, set later)
+%catcode\endoflineasciicode \endoflinecatcode % `\^^M ascii return is end-line
+\catcode\endoffileasciicode \ignorecatcode % `\^^Z endoffile (ignored in ConTeXt)
+%catcode\spaceasciicode \spacecatcode % `\ ascii space is blank space
+\catcode\hashasciicode \parametercatcode % `\# hash mark is macro parameter character
+\catcode\dollarasciicode \mathshiftcatcode % `\$ dollar sign is math shift
+%catcode\commentasciicode \commentcatcode % `\% percent sign is comment character
+\catcode\ampersandasciicode \alignmentcatcode % `\& ampersand is alignment tab
+%catcode\backslashasciicode \escapecatcode % `\\ backslash is TeX escape character
+\catcode\circumflexasciicode \superscriptcatcode % `\^ circumflex and uparrow are for superscripts
+\catcode\underscoreasciicode \subscriptcatcode % `\_ underline and downarrow are for subscripts
+\catcode\leftbraceasciicode \begingroupcatcode % `\{ left brace is begin-group character
+\catcode\rightbraceasciicode \endgroupcatcode % `\} right brace is end-group character
+\catcode\tildeasciicode \activecatcode % `\~ tilde is active
+%catcode\delasciicode \invalidcatcode % `\^^? ascii delete is invalid
%D It makes sense to know what engine we're running so let's try to deduce it.
-\chardef\unknownengine = 0
-\chardef\pdftexengine = 1
-\chardef\xetexengine = 2
-\chardef\luatexengine = 3
+\chardef\unknownengine 0
+\chardef\pdftexengine 1
+\chardef\xetexengine 2
+\chardef\luatexengine 3
-\chardef\statuswrite = 128
+\chardef\statuswrite 128
\ifx\directlua\undefined
\ifx\XeTeXversion\undefined
@@ -83,7 +117,7 @@
% for historic reasons we keep some mkii code around
\else
\immediate\write\statuswrite{>>>}
- \immediate\write\statuswrite{>>> only luatex is supported}
+ \immediate\write\statuswrite{>>> only LuaTeX is supported}
\immediate\write\statuswrite{>>>}
\let\dump\relax
\expandafter\end
@@ -108,6 +142,17 @@
tex.enableprimitives("normal",luatexprimitives)
}
+\def\space{ }
+\def\empty{}
+
+\letcharcode \formfeedasciicode \par % \def ^^L{\par} formfeed
+\letcharcode \tildeasciicode \ % tilde
+\letcharcode \spaceasciicode \space % space
+
+\expandafter\def\csname\Uchar\tabasciicode \endcsname {\ } % \def\^^I{\ } tab
+\expandafter\def\csname\Uchar\formfeedasciicode \endcsname {\par} % \def\^^L{\par} formfeed
+\expandafter\def\csname\Uchar\endoflineasciicode\endcsname {\ } % \def\^^M{\ } return
+
%D \ETEX\ has a not so handy way of telling you the version number, i.e. the revision
%D number has a period in it:
@@ -120,15 +165,15 @@
\def\unprotect
{\edef\protect
- {\catcode`@=\the\catcode`@\relax
- \catcode`?=\the\catcode`?\relax
- \catcode`!=\the\catcode`!\relax
- \catcode`_=\the\catcode`_\relax
+ {\catcode\atsignasciicode \the\catcode\atsignasciicode \relax
+ \catcode\exclamationmarkasciicode\the\catcode\exclamationmarkasciicode\relax
+ \catcode\questionmarkasciicode \the\catcode\questionmarkasciicode \relax
+ \catcode\underscoreasciicode \the\catcode\underscoreasciicode \relax
\let\protect\relax}%
- \catcode`@=11
- \catcode`?=11
- \catcode`!=11
- \catcode`_=11 }
+ \catcode\atsignasciicode \lettercatcode
+ \catcode\exclamationmarkasciicode\lettercatcode
+ \catcode\questionmarkasciicode \lettercatcode
+ \catcode\underscoreasciicode \lettercatcode}
\let\protect\relax
@@ -212,10 +257,10 @@
% A few traditional allocations (these might go):
-\countdef \count@ = 255 % hm, used in \newif .. todo: replace it there
-\dimendef \dimen@ = 0
-\dimendef \dimen@i = 1 % global only
-\dimendef \dimen@ii = 2
+\countdef \count@ 255 % hm, used in \newif .. todo: replace it there
+\dimendef \dimen@ 0
+\dimendef \dimen@i 1 % global only
+\dimendef \dimen@ii 2
%D So, effectively we start allocating from 256 and upwards. The inserts sit in the
%D range 128 upto 254. Page numbers use the counters 0 upto 9 and the pagebox is
@@ -258,8 +303,7 @@
% %D The next definitions are really needed (in \CONTEXT):
-%newlinechar=10 \def\outputnewlinechar{\rawcharacter{10}}
-\newlinechar=10 \edef\outputnewlinechar{^^J}
+\newlinechar\newlineasciicode \edef\outputnewlinechar{\Uchar\newlineasciicode} % {^^J}
%D One reason to start high with allocation is that it permits us to allocate
%D consecutive ranges more easily, for instance if for \MPLIB\ we want to allocate a
@@ -395,19 +439,19 @@
%D More allocations:
-\newskip \zeroskip \zeroskip = 0pt plus 0pt minus 0pt
-\newdimen \zeropoint \zeropoint = 0pt
-\newdimen \onepoint \onepoint = 1pt
-\newdimen \halfapoint \halfapoint = 0.5pt
-\newdimen \maxdimen \maxdimen = 16383.99999pt
-\newcount \maxcount \maxcount = 2147483647
-\newdimen \onebasepoint \onebasepoint = 1bp
-\newdimen \scaledpoint \scaledpoint = 1sp
-\newdimen \thousandpoint \thousandpoint = 1000pt
-\newmuskip\zeromuskip \zeromuskip = 0mu
-\newmuskip\onemuskip \onemuskip = 1mu
+\newskip \zeroskip \zeroskip 0pt plus 0pt minus 0pt
+\newdimen \zeropoint \zeropoint 0pt
+\newdimen \onepoint \onepoint 1pt
+\newdimen \halfapoint \halfapoint 0.5pt
+\newdimen \maxdimen \maxdimen 16383.99999pt
+\newcount \maxcount \maxcount 2147483647
+\newdimen \onebasepoint \onebasepoint 1bp
+\newdimen \scaledpoint \scaledpoint 1sp
+\newdimen \thousandpoint \thousandpoint 1000pt
+\newmuskip\zeromuskip \zeromuskip 0mu
+\newmuskip\onemuskip \onemuskip 1mu
-\newmuskip\muquad \muquad = 18mu
+\newmuskip\muquad \muquad 18mu
\let\points \onepoint
\let\halfpoint\halfapoint
@@ -416,32 +460,32 @@
%D And even more: (todo: countdefs 60+)
-%newcount \minusone \minusone = -1
-\newcount \minustwo \minustwo = -2
-%chardef \zerocount = 0
-%chardef \plusone = 1
-\chardef \plustwo = 2
-\chardef \plusthree = 3
-\chardef \plusfour = 4
-\chardef \plusfive = 5
-\chardef \plussix = 6
-\chardef \plusseven = 7
-\chardef \pluseight = 8
-\chardef \plusnine = 9
-\chardef \plusten = 10
-\chardef \plussixteen = 16
-\chardef \plushundred = 100
-\chardef \plustwohundred = 200
-\chardef \pluscxxvii = 127
-\chardef \pluscxxviii = 128
-\chardef \pluscclv = 255
-\chardef \pluscclvi = 256
-\chardef \plusthousand = 1000
-\chardef \plustenthousand = 10000
-\chardef \plustwentythousand = 20000
-\chardef \medcard = 32768
-\chardef \maxcard = 65536 % pdftex has less mathchars
-\chardef \maxcardminusone = 65535
+%newcount \minusone \minusone -1
+\newcount \minustwo \minustwo -2
+%chardef \zerocount 0
+%chardef \plusone 1
+\chardef \plustwo 2
+\chardef \plusthree 3
+\chardef \plusfour 4
+\chardef \plusfive 5
+\chardef \plussix 6
+\chardef \plusseven 7
+\chardef \pluseight 8
+\chardef \plusnine 9
+\chardef \plusten 10
+\chardef \plussixteen 16
+\chardef \plushundred 100
+\chardef \plustwohundred 200
+\chardef \pluscxxvii 127
+\chardef \pluscxxviii 128
+\chardef \pluscclv 255
+\chardef \pluscclvi 256
+\chardef \plusthousand 1000
+\chardef \plustenthousand 10000
+\chardef \plustwentythousand 20000
+\chardef \medcard 32768
+\chardef \maxcard 65536 % pdftex has less mathchars
+\chardef \maxcardminusone 65535
%D \macros
%D {doubleexpandafter,tripleexpandafter,expanded,startexpanded}
@@ -506,21 +550,47 @@
%D creates \type {\footrue}, \type {\foofalse} to go with \type {\iffoo}.
%D \stopnarrower
-\normalprotected\def\newif#1%
- {\count@\escapechar
- \escapechar\minusone
- \expandafter\expandafter\expandafter\def\@if #1{true}{\let#1\iftrue }%
- \expandafter\expandafter\expandafter\def\@if#1{false}{\let#1\iffalse}%
- \@if#1{false}% the condition starts out false
- \escapechar\count@}
-
-\def\@if#1#2%
- {\csname\expandafter\if@\string#1#2\endcsname}
+% \normalprotected\def\newif#1%
+% {\count@\escapechar
+% \escapechar\minusone
+% \expandafter\expandafter\expandafter\def\new_if #1{true}{\let#1\iftrue }%
+% \expandafter\expandafter\expandafter\def\new_if#1{false}{\let#1\iffalse}%
+% \new_if#1{false}% the condition starts out false
+% \escapechar\count@}
+%
+% \def\new_if#1#2%
+% {\csname\expandafter\if@\string#1#2\endcsname}
+%
+% \bgroup % `if' is required
+% \uccode`1=`i \uccode`2=`f \uppercase{\gdef\if@12{}}
+% \egroup
-\bgroup % `if' is required
+% We use \csstring so there is no need to push/pop escapechar.
+% We use different names so that we get a better error message.
+%
+% \normalprotected\def\newif#1%
+% {\let\new_if_saved\newif
+% \let\newif\new_if_check
+% \expandafter\expandafter\expandafter\def\new_if_cs #1{true}{\let#1\iftrue }%
+% \expandafter\expandafter\expandafter\def\new_if_cs#1{false}{\let#1\iffalse}%
+% \new_if_cs#1{false}%
+% \let\newif\new_if_saved}
+%
+% \normalprotected\def\new_if_cs#1#2%
+% {\csname\expandafter\newif\csstring#1#2\endcsname}
+%
+% We wrap all into one macro:
- \uccode`1=`i \uccode`2=`f \uppercase{\gdef\if@12{}}
+\normalprotected\def\newif#1%
+ {\let\new_if_saved\newif
+ \let\newif\new_if_check
+ \expandafter\def\csname\expandafter\newif\csstring#1true\endcsname {\let#1\iftrue }%
+ \expandafter\def\csname\expandafter\newif\csstring#1false\endcsname{\let#1\iffalse}%
+ \csname\expandafter\newif\csstring#1false\endcsname
+ \let\newif\new_if_saved}
+\bgroup
+ \normalexpanded{\gdef\noexpand\new_if_check\string i\string f{}}
\egroup
%D Let's test this one:
@@ -540,26 +610,6 @@
\normalprotected\def\uedef{\normalprotected\edef}
\normalprotected\def\uxdef{\normalprotected\xdef}
-%D The catcode constants will be redefined in later catcode related modules
-%D but they can be used in the same way.
-
-\chardef\escapecatcode = 0
-\chardef\begingroupcatcode = 1
-\chardef\endgroupcatcode = 2
-\chardef\mathshiftcatcode = 3
-\chardef\alignmentcatcode = 4
-\chardef\endoflinecatcode = 5
-\chardef\parametercatcode = 6
-\chardef\superscriptcatcode = 7
-\chardef\subscriptcatcode = 8
-\chardef\ignorecatcode = 9
-\chardef\spacecatcode = 10
-\chardef\lettercatcode = 11
-\chardef\othercatcode = 12
-\chardef\activecatcode = 13
-\chardef\commentcatcode = 14
-\chardef\invalidcatcode = 15
-
%D For a while we keep the following, as systems like tikz need it. Best
%D not use that one \CONTEXT.
@@ -872,28 +922,28 @@
\let\endgraf\par
\let\endline\cr
-\def\space{ }
-\def\empty{}
-
\normalprotected\def\null{\hpack{}}
%D The following two might be overloaded later on but some modules need then
%D earlier. These functionality is reflected in the name and will not change.
-\bgroup
- \catcode`\^^M=\activecatcode%
- \gdef\obeylines{\catcode`\^^M\activecatcode \let^^M\par}%
- \global\let^^M\par%
-\egroup
-
-\bgroup
- \gdef\obeyspaces{\catcode`\ \activecatcode}%
- \obeyspaces\global\let =\space%
-\egroup
+% \bgroup
+% \catcode`\^^M=\activecatcode%
+% \gdef\obeylines{\catcode`\^^M\activecatcode \let^^M\par}%
+% \global\let^^M\par%
+% \egroup
+%
+% \bgroup
+% \gdef\obeyspaces{\catcode`\ \activecatcode}%
+% \obeyspaces\global\let =\space%
+% \egroup
-%D A constant:
+\def\obeylines {\catcode\endoflineasciicode\activecatcode\letcharcode\endoflineasciicode\par}
+\def\obeyspaces{\catcode\spaceasciicode \activecatcode\letcharcode\spaceasciicode \space}
-\let\endoflinetoken=^^M
+% %D A constant:
+%
+% \let\endoflinetoken=^^M
%D Also needed might be a simple loop structure and we borrow plain \TEX's one
%D as it is often expected to be present and it is about the fastest you can
@@ -980,30 +1030,30 @@
% module after which the official interfaces have to be used. This is needed for
% modules not made by ctx developers.
-\normalprotected\def\pdfliteral {\pdfextension literal }
-\normalprotected\def\pdfcolorstack {\pdfextension colorstack }
-\normalprotected\def\pdfsetmatrix {\pdfextension setmatrix }
-\normalprotected\def\pdfsave {\pdfextension save\relax}
-\normalprotected\def\pdfrestore {\pdfextension restore\relax}
-\normalprotected\def\pdfobj {\pdfextension obj }
-\normalprotected\def\pdfrefobj {\pdfextension refobj }
-\normalprotected\def\pdfannot {\pdfextension annot }
-\normalprotected\def\pdfstartlink {\pdfextension startlink }
-\normalprotected\def\pdfendlink {\pdfextension endlink\relax}
-\normalprotected\def\pdfoutline {\pdfextension outline }
-\normalprotected\def\pdfdest {\pdfextension dest }
-\normalprotected\def\pdfthread {\pdfextension thread }
-\normalprotected\def\pdfstartthread {\pdfextension startthread }
-\normalprotected\def\pdfendthread {\pdfextension endthread\relax}
-\normalprotected\def\pdfinfo {\pdfextension info }
-\normalprotected\def\pdfcatalog {\pdfextension catalog }
-\normalprotected\def\pdfnames {\pdfextension names }
-\normalprotected\def\pdfincludechars {\pdfextension includechars }
-\normalprotected\def\pdffontattr {\pdfextension fontattr }
-\normalprotected\def\pdfmapfile {\pdfextension mapfile }
-\normalprotected\def\pdfmapline {\pdfextension mapline }
-\normalprotected\def\pdftrailer {\pdfextension trailer }
-\normalprotected\def\pdfglyphtounicode {\pdfextension glyphtounicode }
+\normalprotected\def\pdfliteral {\pdfextension literal }
+\normalprotected\def\pdfcolorstack {\pdfextension colorstack }
+\normalprotected\def\pdfsetmatrix {\pdfextension setmatrix }
+\normalprotected\def\pdfsave {\pdfextension save\relax}
+\normalprotected\def\pdfrestore {\pdfextension restore\relax}
+\normalprotected\def\pdfobj {\pdfextension obj }
+\normalprotected\def\pdfrefobj {\pdfextension refobj }
+\normalprotected\def\pdfannot {\pdfextension annot }
+\normalprotected\def\pdfstartlink {\pdfextension startlink }
+\normalprotected\def\pdfendlink {\pdfextension endlink\relax}
+\normalprotected\def\pdfoutline {\pdfextension outline }
+\normalprotected\def\pdfdest {\pdfextension dest }
+\normalprotected\def\pdfthread {\pdfextension thread }
+\normalprotected\def\pdfstartthread {\pdfextension startthread }
+\normalprotected\def\pdfendthread {\pdfextension endthread\relax}
+\normalprotected\def\pdfinfo {\pdfextension info }
+\normalprotected\def\pdfcatalog {\pdfextension catalog }
+\normalprotected\def\pdfnames {\pdfextension names }
+\normalprotected\def\pdfincludechars {\pdfextension includechars }
+\normalprotected\def\pdffontattr {\pdfextension fontattr }
+\normalprotected\def\pdfmapfile {\pdfextension mapfile }
+\normalprotected\def\pdfmapline {\pdfextension mapline }
+\normalprotected\def\pdftrailer {\pdfextension trailer }
+\normalprotected\def\pdfglyphtounicode {\pdfextension glyphtounicode }
% \chardef\pdfnofullbanner = 1
% \chardef\pdfnofilename = 2
@@ -1188,12 +1238,14 @@
\ifdefined\protrusionboundary \else \let\protrusionboundary\boundary \fi
\ifdefined\wordboundary \else \let\wordboundary \noboundary \fi
-\ifdefined\mathrulesfam \else \newcount\mathrulesfam \fi
-\ifdefined\mathrulesmode \else \newcount\mathrulesmode \fi
-\ifdefined\mathsurroundmode \else \newcount\mathsurroundmode \fi
-\ifdefined\mathitalicsmode \else \newcount\mathitalicsmode \fi
-\ifdefined\mathdelimitersmode \else \newcount\mathdelimitersmode \fi
-\ifdefined\mathscriptboxmode \else \newcount\mathscriptboxmode \fi
+\ifdefined\mathrulesfam \else \newcount\mathrulesfam \fi
+\ifdefined\mathrulesmode \else \newcount\mathrulesmode \fi
+\ifdefined\mathsurroundmode \else \newcount\mathsurroundmode \fi
+\ifdefined\mathitalicsmode \else \newcount\mathitalicsmode \fi
+\ifdefined\mathdelimitersmode \else \newcount\mathdelimitersmode \fi
+\ifdefined\mathscriptboxmode \else \newcount\mathscriptboxmode \fi
+\ifdefined\mathscriptcharmode \else \newcount\mathscriptcharmode \fi
+\ifdefined\mathrulethicknessmode \else \newcount\mathrulethicknessmode \fi
\ifdefined\hyphenpenaltymode \else \newcount\hyphenpenaltymode \fi
\ifdefined\automatichyphenpenalty \else \newcount\automatichyphenpenalty \fi
diff --git a/tex/context/base/mkiv/trac-inf.lua b/tex/context/base/mkiv/trac-inf.lua
index 439e8b2dc..51893d585 100644
--- a/tex/context/base/mkiv/trac-inf.lua
+++ b/tex/context/base/mkiv/trac-inf.lua
@@ -123,6 +123,24 @@ local function elapsed(instance)
end
end
+local function currenttime(instance)
+ if type(instance) == "number" then
+ return instance
+ else
+ local timer = timers[instance or "notimer"]
+ local it = timer.timing
+ if it > 1 then
+ -- whatever
+ else
+ local starttime = timer.starttime
+ if starttime and starttime > 0 then
+ return seconds(timer.loadtime + ticks() - starttime)
+ end
+ end
+ return 0
+ end
+end
+
local function elapsedtime(instance)
return format("%0.3f",elapsed(instance))
end
@@ -141,6 +159,7 @@ statistics.hastiming = hastiming
statistics.resettiming = resettiming
statistics.starttiming = starttiming
statistics.stoptiming = stoptiming
+statistics.currenttime = currenttime
statistics.elapsed = elapsed
statistics.elapsedtime = elapsedtime
statistics.elapsedindeed = elapsedindeed
@@ -229,7 +248,7 @@ end
function statistics.runtime()
stoptiming(statistics)
- -- stoptiming(statistics) -- somehow we can start the timer twice, but where
+ -- stoptiming(statistics) -- somehow we can start the timer twice, but where
return statistics.formatruntime(elapsedtime(statistics))
end
diff --git a/tex/context/base/mkiv/trac-log.lua b/tex/context/base/mkiv/trac-log.lua
index 1471bd4c7..297d053ab 100644
--- a/tex/context/base/mkiv/trac-log.lua
+++ b/tex/context/base/mkiv/trac-log.lua
@@ -758,7 +758,7 @@ if tex then
local report = logs.reporter("pages") -- not needed but saves checking when we grep for it
local texgetcount = tex and tex.getcount
- local real, user, sub
+ local real, user, sub = 0, 0, 0
function logs.start_page_number()
real = texgetcount("realpageno")
@@ -766,47 +766,35 @@ if tex then
sub = texgetcount("subpageno")
end
- local timing = false
- local starttime = nil
- local lasttime = nil
+ local timing = false
+ local lasttime = nil
trackers.register("pages.timing", function(v) -- only for myself (diagnostics)
- starttime = os.clock() -- todo: use other timer
- timing = true
+ timing = ""
end)
function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average
if timing then
- local elapsed, average
- local stoptime = os.clock()
+ local elapsed = statistics.currenttime(statistics)
+ local average, page
if not lasttime or real < 2 then
- elapsed = stoptime
- average = stoptime
- starttime = stoptime
+ average = elapsed
+ page = elapsed
else
- elapsed = stoptime - lasttime
- average = (stoptime - starttime) / (real - 1)
- end
- lasttime = stoptime
- if real <= 0 then
- report("flushing page, time %0.04f / %0.04f",elapsed,average)
- elseif user <= 0 then
- report("flushing realpage %s, time %0.04f / %0.04f",real,elapsed,average)
- elseif sub <= 0 then
- report("flushing realpage %s, userpage %s, time %0.04f / %0.04f",real,user,elapsed,average)
- else
- report("flushing realpage %s, userpage %s, subpage %s, time %0.04f / %0.04f",real,user,sub,elapsed,average)
+ average = elapsed / (real - 1)
+ page = elapsed - lasttime
end
+ lasttime = elapsed
+ timing = formatters[", total %0.03f, page %0.03f, average %0.03f"](elapsed,page,average)
+ end
+ if real <= 0 then
+ report("flushing page%s",timing)
+ elseif user <= 0 then
+ report("flushing realpage %s%s",real,timing)
+ elseif sub <= 0 then
+ report("flushing realpage %s, userpage %s%s",real,user,timing)
else
- if real <= 0 then
- report("flushing page")
- elseif user <= 0 then
- report("flushing realpage %s",real)
- elseif sub <= 0 then
- report("flushing realpage %s, userpage %s",real,user)
- else
- report("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
- end
+ report("flushing realpage %s, userpage %s, subpage %s%s",real,user,sub,timing)
end
logs.flush()
end
diff --git a/tex/context/base/mkiv/trac-vis.lua b/tex/context/base/mkiv/trac-vis.lua
index 0e37752db..91ee1cf7d 100644
--- a/tex/context/base/mkiv/trac-vis.lua
+++ b/tex/context/base/mkiv/trac-vis.lua
@@ -1433,8 +1433,7 @@ do
}
local function markfonts(list)
- for n in traverse_nodes(list) do
- local id = getid(n)
+ for n, id in traverse_nodes(list) do
if id == glyph_code then
local font = getfont(n)
local okay = used[font]
diff --git a/tex/context/base/mkiv/trac-vis.mkiv b/tex/context/base/mkiv/trac-vis.mkiv
index a6a3fa5a2..b7e506faf 100644
--- a/tex/context/base/mkiv/trac-vis.mkiv
+++ b/tex/context/base/mkiv/trac-vis.mkiv
@@ -122,6 +122,11 @@
\unexpanded\def\showfontitalics
{\clf_setvisual{italic}}
+\unexpanded\def\showglyphdata
+ {\showglyphs
+ \showfontkerns
+ \showfontitalics}
+
\unexpanded\def\showfontexpansion
{\clf_setvisual{expansion}}
diff --git a/tex/context/base/mkiv/util-lua.lua b/tex/context/base/mkiv/util-lua.lua
index b7de11936..7c5e1bf2a 100644
--- a/tex/context/base/mkiv/util-lua.lua
+++ b/tex/context/base/mkiv/util-lua.lua
@@ -198,12 +198,12 @@ function luautilities.checkmemory(previous,threshold,trace) -- threshold in MB
collectgarbage("collect")
local afterwards = collectgarbage("count")
if trace or tracememory then
- report_mem("previous %i MB, current %i MB, delta %i MB, threshold %i MB, afterwards %i MB",
+ report_mem("previous %r MB, current %r MB, delta %r MB, threshold %r MB, afterwards %r MB",
previous/1024,current/1024,delta/1024,threshold,afterwards)
end
return afterwards
elseif trace or tracememory then
- report_mem("previous %i MB, current %i MB, delta %i MB, threshold %i MB",
+ report_mem("previous %r MB, current %r MB, delta %r MB, threshold %r MB",
previous/1024,current/1024,delta/1024,threshold)
end
end
diff --git a/tex/context/base/mkiv/util-prs.lua b/tex/context/base/mkiv/util-prs.lua
index 48d59a9f3..891f1096a 100644
--- a/tex/context/base/mkiv/util-prs.lua
+++ b/tex/context/base/mkiv/util-prs.lua
@@ -31,6 +31,7 @@ utilities.parsers.hashes = hashes
local digit = R("09")
local space = P(' ')
local equal = P("=")
+local colon = P(":")
local comma = P(",")
local lbrace = P("{")
local rbrace = P("}")
@@ -72,11 +73,13 @@ lpegpatterns.nested = nestedbraces -- no capture
lpegpatterns.argument = argument -- argument after e.g. =
lpegpatterns.content = content -- rest after e.g =
-local value = P(lbrace * C((nobrace + nestedbraces)^0) * rbrace) + C((nestedbraces + (1-comma))^0)
+local value = lbrace * C((nobrace + nestedbraces)^0) * rbrace
+ + C((nestedbraces + (1-comma))^0)
local key = C((1-equal-comma)^1)
local pattern_a = (space+comma)^0 * (key * equal * value + key * C(""))
local pattern_c = (space+comma)^0 * (key * equal * value)
+local pattern_d = (space+comma)^0 * (key * (equal+colon) * value + key * C(""))
local key = C((1-space-equal-comma)^1)
local pattern_b = spaces * comma^0 * spaces * (key * ((spaces * equal * spaces * value) + C("")))
@@ -92,10 +95,12 @@ end
local pattern_a_s = (pattern_a/set)^1
local pattern_b_s = (pattern_b/set)^1
local pattern_c_s = (pattern_c/set)^1
+local pattern_d_s = (pattern_d/set)^1
patterns.settings_to_hash_a = pattern_a_s
patterns.settings_to_hash_b = pattern_b_s
patterns.settings_to_hash_c = pattern_c_s
+patterns.settings_to_hash_d = pattern_d_s
function parsers.make_settings_to_hash_pattern(set,how)
if how == "strict" then
@@ -126,6 +131,18 @@ function parsers.settings_to_hash(str,existing)
end
end
+function parsers.settings_to_hash_colon_too(str)
+ if not str or str == "" then
+ return { }
+ elseif type(str) == "table" then
+ return str
+ else
+ hash = { }
+ lpegmatch(pattern_d_s,str)
+ return hash
+ end
+end
+
function parsers.settings_to_hash_tolerant(str,existing)
if not str or str == "" then
return { }
@@ -165,7 +182,7 @@ function parsers.settings_to_hash_strict(str,existing)
end
local separator = comma * space^0
-local value = P(lbrace * C((nobrace + nestedbraces)^0) * rbrace)
+local value = lbrace * C((nobrace + nestedbraces)^0) * rbrace
+ C((nestedbraces + (1-comma))^0)
local pattern = spaces * Ct(value*(separator*value)^0)
@@ -210,7 +227,7 @@ function parsers.settings_to_numbers(str)
return str
end
-local value = P(lbrace * C((nobrace + nestedbraces)^0) * rbrace)
+local value = lbrace * C((nobrace + nestedbraces)^0) * rbrace
+ C((nestedbraces + nestedbrackets + nestedparents + (1-comma))^0)
local pattern = spaces * Ct(value*(separator*value)^0)
@@ -242,7 +259,7 @@ function parsers.groupedsplitat(symbol,withaction)
if not pattern then
local symbols = S(symbol)
local separator = space^0 * symbols * space^0
- local value = P(lbrace * C((nobrace + nestedbraces)^0) * rbrace)
+ local value = lbrace * C((nobrace + nestedbraces)^0) * rbrace
+ C((nestedbraces + (1-(space^0*(symbols+P(-1)))))^0)
if withaction then
local withvalue = Carg(1) * value / function(f,s) return f(s) end
diff --git a/tex/context/base/mkiv/util-sto.lua b/tex/context/base/mkiv/util-sto.lua
index 5b6915eaf..0da685e9f 100644
--- a/tex/context/base/mkiv/util-sto.lua
+++ b/tex/context/base/mkiv/util-sto.lua
@@ -196,6 +196,16 @@ function table.getmetatablekey(t,key,value)
return m and m[key]
end
+function table.makeweak(t)
+ local m = getmetatable(t)
+ if m then
+ m.__mode = "v"
+ else
+ setmetatable(t,{ __mode = "v" })
+ end
+ return t
+end
+
-- Problem: we have no __next (which is ok as it would probably slow down lua) so
-- we cannot loop over the keys.
diff --git a/tex/context/fonts/mkiv/type-imp-cambria.mkiv b/tex/context/fonts/mkiv/type-imp-cambria.mkiv
index f5679fd92..06781a8d0 100644
--- a/tex/context/fonts/mkiv/type-imp-cambria.mkiv
+++ b/tex/context/fonts/mkiv/type-imp-cambria.mkiv
@@ -20,6 +20,8 @@
% microsoft: cambria.ttc cambriab.ttf cambriai.ttf cambriaz.ttf
% ascender : cambmath.ttf cambria.ttf cambriab.ttf cambriai.ttf cambriaz.ttf
+ \doifunknownfontfeature {cambria-math-bold} {\definefontfeature[cambria-math-bold][boldened]}
+
\starttypescript [\s!math,\s!serif] [cambria,cambria-x,cambria-y]
% whatever matches
\definefontsynonym [CambriaMath] [\s!name:cambriamath]
@@ -42,15 +44,18 @@
\starttypescript [\s!math] [cambria,cambria-m,cambria-a] [\s!name]
\loadfontgoodies[cambria-math]
- \definefontsynonym [\s!MathRoman] [CambriaMath] [\s!features={\s!math\mathsizesuffix,mathextra},\s!goodies=cambria-math]
+ \definefontsynonym [\s!MathRoman] [CambriaMath] [\s!features={\s!math\mathsizesuffix,mathextra},\s!goodies=cambria-math]
+ \definefontsynonym [\s!MathRomanBold] [CambriaMath] [\s!features={\s!math\mathsizesuffix,cambria-math-bold,mathextra},\s!goodies=cambria-math]
\stoptypescript
\starttypescript [\s!math] [cambria-x] [\s!name]
\loadfontgoodies[cambria-math]
- \definefontsynonym [\s!MathRoman] [CambriaMath] [\s!features={\s!math,mathextra},\s!goodies=cambria-math]
+ \definefontsynonym [\s!MathRoman] [CambriaMath] [\s!features={\s!math,mathextra},\s!goodies=cambria-math]
+ \definefontsynonym [\s!MathRomanBold] [CambriaMath] [\s!features={\s!math,cambria-math-bold,mathextra},\s!goodies=cambria-math]
\stoptypescript
\starttypescript [\s!math] [cambria-y] [\s!name]
\loadfontgoodies[cambria-math]
- \definefontsynonym [\s!MathRoman] [CambriaMath] [\s!features={\s!math-nostack\mathsizesuffix,mathextra},\s!goodies=cambria-math]
+ \definefontsynonym [\s!MathRoman] [CambriaMath] [\s!features={\s!math-nostack\mathsizesuffix,mathextra},\s!goodies=cambria-math]
+ \definefontsynonym [\s!MathRomanBold] [CambriaMath] [\s!features={\s!math-nostack\mathsizesuffix,cambria-math-bold,mathextra},\s!goodies=cambria-math]
\stoptypescript
\starttypescript [\s!serif] [cambria,cambria-m,cambria-a] [\s!name]
diff --git a/tex/context/fonts/mkiv/type-imp-dejavu.mkiv b/tex/context/fonts/mkiv/type-imp-dejavu.mkiv
index 582d8a764..3af9d2d17 100644
--- a/tex/context/fonts/mkiv/type-imp-dejavu.mkiv
+++ b/tex/context/fonts/mkiv/type-imp-dejavu.mkiv
@@ -15,6 +15,8 @@
\starttypescriptcollection[dejavu]
+ \doifunknownfontfeature {dejavu-math-bold} {\definefontfeature[dejavu-math-bold][boldened]}
+
\starttypescript [\s!serif] [dejavu] [\s!name]
\setups[\s!font:\s!fallback:\s!serif]
\definefontsynonym [\s!Serif] [\s!name:dejavuserif] [\s!features=\s!default,\s!fallbacks=\s!Serif]
@@ -41,7 +43,8 @@
\starttypescript [\s!math][dejavu][\s!name]
\loadfontgoodies[dejavu-math]
- \definefontsynonym[\s!MathRoman][file:texgyredejavu-math][\s!features={\s!math\mathsizesuffix,mathextra},\s!goodies=dejavu-math]
+ \definefontsynonym[\s!MathRoman] [file:texgyredejavu-math][\s!features={\s!math\mathsizesuffix,mathextra},\s!goodies=dejavu-math]
+ \definefontsynonym[\s!MathRomanBold][file:texgyredejavu-math][\s!features={\s!math\mathsizesuffix,dejavu-math-bold,mathextra},\s!goodies=schola-math]
\stoptypescript
\starttypescript[dejavu]
diff --git a/tex/context/fonts/mkiv/type-imp-latinmodern.mkiv b/tex/context/fonts/mkiv/type-imp-latinmodern.mkiv
index 63f74027b..cc9559d8b 100644
--- a/tex/context/fonts/mkiv/type-imp-latinmodern.mkiv
+++ b/tex/context/fonts/mkiv/type-imp-latinmodern.mkiv
@@ -28,6 +28,8 @@
\starttypescriptcollection[latinmodern]
+ \doifunknownfontfeature {lm-math-bold} {\definefontfeature[lm-math-bold][boldened]}
+
\starttypescript [\s!serif] [simple] [\s!name]
\definefontsynonym [\s!Simple] [\s!file:lmmonoproplt10-regular] [\s!features=\s!default]
\stoptypescript
@@ -180,7 +182,7 @@
\starttypescript [\s!math] [modern,latin-modern]
\loadfontgoodies[lm]
\definefontsynonym [LMMathRoman-Regular] [\v!file:latinmodern-math-regular.otf] [\s!features={\s!math\mathsizesuffix,lm-math,mathextra},\s!goodies=lm]
- \definefontsynonym [LMMathRoman-Bold] [\v!file:latinmodern-math-regular.otf] [\s!features={\s!math\mathsizesuffix,lm-math,mathextra},\s!goodies=lm]
+ \definefontsynonym [LMMathRoman-Bold] [\v!file:latinmodern-math-regular.otf] [\s!features={\s!math\mathsizesuffix,lm-math-bold,lm-math,mathextra},\s!goodies=lm]
\stoptypescript
\starttypescript [modern-designsize-virtual]
diff --git a/tex/context/fonts/mkiv/type-imp-modernlatin.mkiv b/tex/context/fonts/mkiv/type-imp-modernlatin.mkiv
index a3f4762f1..2494d1af2 100644
--- a/tex/context/fonts/mkiv/type-imp-modernlatin.mkiv
+++ b/tex/context/fonts/mkiv/type-imp-modernlatin.mkiv
@@ -13,50 +13,52 @@
\starttypescriptcollection[modernlatin]
- \definefontfeature[lm-rm-regular][effect={width=0.15,delta=1.00}]
- \definefontfeature[lm-rm-bold] [effect={width=0.30,delta=1.00}]
- \definefontfeature[lm-ss-regular][effect={width=0.10,delta=1.00}]
- \definefontfeature[lm-ss-bold] [effect={width=0.20,delta=1.00}]
- \definefontfeature[lm-tt-regular][effect={width=0.20,delta=1.00}]
- \definefontfeature[lm-tt-bold] [effect={width=0.30,delta=1.00}]
+ \doifunknownfontfeature {lm-serif-regular} {\definefontfeature[lm-serif-regular][boldened-15]}
+ \doifunknownfontfeature {lm-serif-bold} {\definefontfeature[lm-serif-bold] [boldened-30]}
+ \doifunknownfontfeature {lm-sans-regular} {\definefontfeature[lm-sans-regular] [boldened-10]}
+ \doifunknownfontfeature {lm-sans-bold} {\definefontfeature[lm-sans-bold] [boldened-20]}
+ \doifunknownfontfeature {lm-mono-regular} {\definefontfeature[lm-mono-regular] [boldened-20]}
+ \doifunknownfontfeature {lm-mono-bold} {\definefontfeature[lm-mono-bold] [boldened-30]}
+ \doifunknownfontfeature {lm-math-regular} {\definefontfeature[lm-math-regular] [boldened-15]}
+ \doifunknownfontfeature {lm-math-bold} {\definefontfeature[lm-math-bold] [boldened-30]}
\starttypescript [\s!serif] [modern-latin]
% \loadfontgoodies[lm]
- \definefontsynonym [Serif] [\s!file:lmroman10-regular] [\s!features={\s!default,lm-rm-regular}]
- \definefontsynonym [SerifItalic] [\s!file:lmroman10-italic] [\s!features={\s!default,lm-rm-regular}]
- \definefontsynonym [SerifSlanted] [\s!file:lmromanslant10-regular] [\s!features={\s!default,lm-rm-regular}]
- \definefontsynonym [SerifBold] [\s!file:lmroman10-regular] [\s!features={\s!default,lm-rm-bold}]
- \definefontsynonym [SerifBoldItalic] [\s!file:lmroman10-italic] [\s!features={\s!default,lm-rm-bold}]
- \definefontsynonym [SerifBoldSlanted][\s!file:lmromanslant10-regular] [\s!features={\s!default,lm-rm-bold}]
+ \definefontsynonym [Serif] [\s!file:lmroman10-regular] [\s!features={\s!default,lm-serif-regular}]
+ \definefontsynonym [SerifItalic] [\s!file:lmroman10-italic] [\s!features={\s!default,lm-serif-regular}]
+ \definefontsynonym [SerifSlanted] [\s!file:lmromanslant10-regular] [\s!features={\s!default,lm-serif-regular}]
+ \definefontsynonym [SerifBold] [\s!file:lmroman10-regular] [\s!features={\s!default,lm-serif-bold}]
+ \definefontsynonym [SerifBoldItalic] [\s!file:lmroman10-italic] [\s!features={\s!default,lm-serif-bold}]
+ \definefontsynonym [SerifBoldSlanted][\s!file:lmromanslant10-regular] [\s!features={\s!default,lm-serif-bold}]
\stoptypescript
\starttypescript [\s!sans] [modern-latin]
% \loadfontgoodies[lm]
- \definefontsynonym [Sans] [\s!file:lmsans10-regular] [\s!features={\s!default,lm-ss-regular}]
- \definefontsynonym [SansItalic] [\s!file:lmsans10-oblique] [\s!features={\s!default,lm-ss-regular}]
- \definefontsynonym [SansSlanted] [\s!file:lmsans10-oblique] [\s!features={\s!default,lm-ss-regular}]
- \definefontsynonym [SansBold] [\s!file:lmsans10-regular] [\s!features={\s!default,lm-ss-bold}]
- \definefontsynonym [SansBoldItalic] [\s!file:lmsans10-oblique] [\s!features={\s!default,lm-ss-bold}]
- \definefontsynonym [SansBoldSlanted][\s!file:lmsans10-oblique] [\s!features={\s!default,lm-ss-bold}]
+ \definefontsynonym [Sans] [\s!file:lmsans10-regular] [\s!features={\s!default,lm-sans-regular}]
+ \definefontsynonym [SansItalic] [\s!file:lmsans10-oblique] [\s!features={\s!default,lm-sans-regular}]
+ \definefontsynonym [SansSlanted] [\s!file:lmsans10-oblique] [\s!features={\s!default,lm-sans-regular}]
+ \definefontsynonym [SansBold] [\s!file:lmsans10-regular] [\s!features={\s!default,lm-sans-bold}]
+ \definefontsynonym [SansBoldItalic] [\s!file:lmsans10-oblique] [\s!features={\s!default,lm-sans-bold}]
+ \definefontsynonym [SansBoldSlanted][\s!file:lmsans10-oblique] [\s!features={\s!default,lm-sans-bold}]
\stoptypescript
\starttypescript [\s!mono] [modern-latin]
% \loadfontgoodies[lm]
- \definefontsynonym [Mono] [\s!file:lmmono10-regular] [\s!features={\s!default,lm-tt-regular}]
- \definefontsynonym [MonoItalic] [\s!file:lmmono10-italic] [\s!features={\s!default,lm-tt-regular}]
- \definefontsynonym [MonoSlanted] [\s!file:lmmonoslant10-regular] [\s!features={\s!default,lm-tt-regular}]
- \definefontsynonym [MonoBold] [\s!file:lmmono10-regular] [\s!features={\s!default,lm-tt-bold}]
- \definefontsynonym [MonoBoldItalic] [\s!file:lmmono10-italic] [\s!features={\s!default,lm-tt-bold}]
- \definefontsynonym [MonoBoldSlanted][\s!file:lmmonoslant10-regular] [\s!features={\s!default,lm-tt-bold}]
+ \definefontsynonym [Mono] [\s!file:lmmono10-regular] [\s!features={\s!default,lm-mono-regular}]
+ \definefontsynonym [MonoItalic] [\s!file:lmmono10-italic] [\s!features={\s!default,lm-mono-regular}]
+ \definefontsynonym [MonoSlanted] [\s!file:lmmonoslant10-regular] [\s!features={\s!default,lm-mono-regular}]
+ \definefontsynonym [MonoBold] [\s!file:lmmono10-regular] [\s!features={\s!default,lm-mono-bold}]
+ \definefontsynonym [MonoBoldItalic] [\s!file:lmmono10-italic] [\s!features={\s!default,lm-mono-bold}]
+ \definefontsynonym [MonoBoldSlanted][\s!file:lmmonoslant10-regular] [\s!features={\s!default,lm-mono-bold}]
\stoptypescript
\starttypescript [\s!math] [modern-latin]
\loadfontgoodies[lm]
- \definefontsynonym [LMMathRoman-Regular] [\v!file:latinmodern-math-regular.otf] [\s!features={\s!math\mathsizesuffix,lm-math,mathextra},\s!goodies=lm]
- \definefontsynonym [LMMathRoman-Bold] [\v!file:latinmodern-math-regular.otf] [\s!features={\s!math\mathsizesuffix,lm-math,mathextra},\s!goodies=lm]
+ \definefontsynonym [MathRoman] [\v!file:latinmodern-math-regular.otf] [\s!features={\s!math\mathsizesuffix,lm-math,lm-math-regular,mathextra},\s!goodies=lm]
+ \definefontsynonym [MathRomanBold] [\v!file:latinmodern-math-regular.otf] [\s!features={\s!math\mathsizesuffix,lm-math,lm-math-bold,mathextra},\s!goodies=lm]
\stoptypescript
- \starttypescript [modern-latin]
+ \starttypescript [modern-latin,modernlatin]
\definetypeface [\typescriptone] [\s!rm] [\s!serif] [modern-latin] [\s!default]
\definetypeface [\typescriptone] [\s!ss] [\s!sans] [modern-latin] [\s!default]
\definetypeface [\typescriptone] [\s!tt] [\s!mono] [modern-latin] [\s!default]
diff --git a/tex/context/fonts/mkiv/type-imp-texgyre.mkiv b/tex/context/fonts/mkiv/type-imp-texgyre.mkiv
index 2bec4c2a8..583da77c1 100644
--- a/tex/context/fonts/mkiv/type-imp-texgyre.mkiv
+++ b/tex/context/fonts/mkiv/type-imp-texgyre.mkiv
@@ -20,6 +20,11 @@
\starttypescriptcollection[texgyre]
+ \doifunknownfontfeature {pagella-math-bold} {\definefontfeature[pagella-math-bold][boldened]}
+ \doifunknownfontfeature {schola-math-bold} {\definefontfeature[schola-math-bold] [boldened]}
+ \doifunknownfontfeature {bonum-math-bold} {\definefontfeature[bonum-math-bold] [boldened]}
+ \doifunknownfontfeature {termes-math-bold} {\definefontfeature[termes-math-bold] [boldened]}
+
\definetypescriptprefix [f:pagella] [pagella]
\definetypescriptprefix [f:termes] [termes]
\definetypescriptprefix [f:heros] [heros]
@@ -242,7 +247,8 @@
\starttypescript [\s!math][times,termes][\s!all]
% \loadfontgoodies[texgyre]
% \definefontsynonym[\s!MathRoman][file:texgyre-termes-math-regular.otf][\s!features={\s!math\mathsizesuffix,mathextra},\s!goodies=texgyre]
- \definefontsynonym[\s!MathRoman][file:texgyretermes-math.otf][\s!features={\s!math\mathsizesuffix,mathextra},\s!goodies=termes-math]
+ \definefontsynonym[\s!MathRoman] [file:texgyretermes-math.otf][\s!features={\s!math\mathsizesuffix,mathextra},\s!goodies=termes-math]
+ \definefontsynonym[\s!MathRomanBold][file:texgyretermes-math.otf][\s!features={\s!math\mathsizesuffix,termes-math-bold,mathextra},\s!goodies=schola-math]
\stoptypescript
\stoptypescriptcollection
@@ -270,7 +276,8 @@
\starttypescript [\s!math][palatino,pagella][\s!all]
% \loadfontgoodies[texgyre]
% \definefontsynonym[\s!MathRoman][file:texgyre-pagella-math-regular.otf][\s!features={\s!math\mathsizesuffix,mathextra},\s!goodies=texgyre]
- \definefontsynonym[\s!MathRoman][file:texgyrepagella-math.otf][\s!features={\s!math\mathsizesuffix,mathextra},\s!goodies=pagella-math]
+ \definefontsynonym[\s!MathRoman] [file:texgyrepagella-math.otf][\s!features={\s!math\mathsizesuffix,mathextra},\s!goodies=pagella-math]
+ \definefontsynonym[\s!MathRomanBold][file:texgyrepagella-math.otf][\s!features={\s!math\mathsizesuffix,pagella-math-bold,mathextra},\s!goodies=schola-math]
\stoptypescript
\stoptypescriptcollection
@@ -282,7 +289,8 @@
\starttypescript [\s!math][bookman,bonum][\s!all]
% \loadfontgoodies[texgyre]
% \definefontsynonym[\s!MathRoman][file:texgyre-bonum-math-regular.otf][\s!features={\s!math\mathsizesuffix,mathextra},\s!goodies=texgyre]
- \definefontsynonym[\s!MathRoman][file:texgyrebonum-math.otf][\s!features={\s!math\mathsizesuffix,mathextra},\s!goodies=bonum-math]
+ \definefontsynonym[\s!MathRoman] [file:texgyrebonum-math.otf][\s!features={\s!math\mathsizesuffix,mathextra},\s!goodies=bonum-math]
+ \definefontsynonym[\s!MathRomanBold][file:texgyrebonum-math.otf][\s!features={\s!math\mathsizesuffix,bonum-math-bold,mathextra},\s!goodies=schola-math]
\stoptypescript
\stoptypescriptcollection
@@ -292,7 +300,8 @@
\starttypescript [\s!math][schoolbook,schola][\s!all]
% \loadfontgoodies[texgyre]
% \definefontsynonym[\s!MathRoman][file:texgyre-schola-math-regular.otf][\s!features={\s!math\mathsizesuffix,mathextra},\s!goodies=texgyre]
- \definefontsynonym[\s!MathRoman][file:texgyreschola-math.otf][\s!features={\s!math\mathsizesuffix,mathextra},\s!goodies=schola-math]
+ \definefontsynonym[\s!MathRoman] [file:texgyreschola-math.otf][\s!features={\s!math\mathsizesuffix,mathextra},\s!goodies=schola-math]
+ \definefontsynonym[\s!MathRomanBold][file:texgyreschola-math.otf][\s!features={\s!math\mathsizesuffix,schola-math-bold,mathextra},\s!goodies=schola-math]
\stoptypescript
\stoptypescriptcollection
diff --git a/tex/context/interface/mkii/keys-nl.xml b/tex/context/interface/mkii/keys-nl.xml
index 212685d44..f493e096f 100644
--- a/tex/context/interface/mkii/keys-nl.xml
+++ b/tex/context/interface/mkii/keys-nl.xml
@@ -188,6 +188,7 @@
<cd:variable name='extremestretch' value='extremestretch'/>
<cd:variable name='fact' value='gegeven'/>
<cd:variable name='february' value='februari'/>
+ <cd:variable name='field' value='veld'/>
<cd:variable name='figure' value='figuur'/>
<cd:variable name='figures' value='figuren'/>
<cd:variable name='file' value='file'/>
@@ -800,7 +801,7 @@
<cd:constant name='family' value='soort'/>
<cd:constant name='features' value='features'/>
<cd:constant name='fences' value='fences'/>
- <cd:constant name='field' value='field'/>
+ <cd:constant name='field' value='veld'/>
<cd:constant name='fieldbackgroundcolor' value='veldachtergrondkleur'/>
<cd:constant name='fieldframecolor' value='veldkaderkleur'/>
<cd:constant name='fieldlayer' value='veldlaag'/>
@@ -855,6 +856,7 @@
<cd:constant name='headerstate' value='hoofdstatus'/>
<cd:constant name='headlabel' value='koplabel'/>
<cd:constant name='headnumber' value='kopnummer'/>
+ <cd:constant name='headseparator' value='kopscheider'/>
<cd:constant name='headstyle' value='kopletter'/>
<cd:constant name='height' value='hoogte'/>
<cd:constant name='hfactor' value='hfactor'/>
@@ -1081,6 +1083,7 @@
<cd:constant name='preview' value='preview'/>
<cd:constant name='previous' value='vorige'/>
<cd:constant name='previousnumber' value='vorigenummer'/>
+ <cd:constant name='print' value='print'/>
<cd:constant name='printable' value='printbaar'/>
<cd:constant name='process' value='proces'/>
<cd:constant name='profile' value='profile'/>
@@ -1166,8 +1169,10 @@
<cd:constant name='sidemethod' value='zijmethode'/>
<cd:constant name='sidespaceafter' value='zijnawit'/>
<cd:constant name='sidespacebefore' value='zijvoorwit'/>
+ <cd:constant name='sidespaceinbetween' value='zijtussenwit'/>
<cd:constant name='sidethreshold' value='sidethreshold'/>
<cd:constant name='sign' value='teken'/>
+ <cd:constant name='simplecommand' value='simpelcommando'/>
<cd:constant name='size' value='formaat'/>
<cd:constant name='slantedfeatures' value='slantedfeatures'/>
<cd:constant name='slantedfont' value='slantedfont'/>
diff --git a/tex/context/interface/mkiv/context-en.xml b/tex/context/interface/mkiv/context-en.xml
index 4cfb3c7fe..8d0ae0644 100644
--- a/tex/context/interface/mkiv/context-en.xml
+++ b/tex/context/interface/mkiv/context-en.xml
@@ -11575,6 +11575,45 @@
</cd:keywords>
</cd:arguments>
</cd:command>
+ <cd:command category="fonts conditional" file="font-fea.mkvi" level="system" name="doifelsefontfeature">
+ <cd:arguments>
+ <cd:keywords delimiters="braces">
+ <cd:constant type="cd:name"/>
+ </cd:keywords>
+ <cd:keywords delimiters="braces">
+ <cd:constant type="cd:true"/>
+ </cd:keywords>
+ <cd:keywords delimiters="braces">
+ <cd:constant type="cd:false"/>
+ </cd:keywords>
+ </cd:arguments>
+ </cd:command>
+ <cd:command category="fonts conditional" file="font-fea.mkvi" level="system" name="doiffontfeatureelse">
+ <cd:arguments>
+ <cd:keywords delimiters="braces">
+ <cd:constant type="cd:name"/>
+ </cd:keywords>
+ <cd:keywords delimiters="braces">
+ <cd:constant type="cd:true"/>
+ </cd:keywords>
+ <cd:keywords delimiters="braces">
+ <cd:constant type="cd:false"/>
+ </cd:keywords>
+ </cd:arguments>
+ </cd:command>
+ <cd:command category="fonts conditional" file="font-fea.mkvi" level="system" name="doifunknownfontfeature">
+ <cd:arguments>
+ <cd:keywords delimiters="braces">
+ <cd:constant type="cd:name"/>
+ </cd:keywords>
+ <cd:keywords delimiters="braces">
+ <cd:constant type="cd:true"/>
+ </cd:keywords>
+ <cd:keywords delimiters="braces">
+ <cd:constant type="cd:false"/>
+ </cd:keywords>
+ </cd:arguments>
+ </cd:command>
<cd:command category="fonts" file="font-fea.mkvi" level="system" name="doaddfeature">
<cd:arguments>
<cd:keywords delimiters="braces" list="yes">
@@ -44449,6 +44488,8 @@
<cd:command file="trc-vis.mkiv" level="document" name="showglyphs"/>
<cd:command file="trc-vis.mkiv" level="document" name="showfontkerns"/>
<cd:command file="trc-vis.mkiv" level="document" name="showfontitalics"/>
+ <cd:command file="trc-vis.mkiv" level="document" name="showglyphdata"/>
+ <cd:command file="trc-vis.mkiv" level="document" name="showfontexpansion"/>
<cd:command file="trc-vis.mkiv" level="system" name="setvisualizerfont">
<cd:arguments>
<cd:keywords optional="yes">
@@ -45671,6 +45712,45 @@
</cd:keywords>
</cd:arguments>
</cd:command>
+ <cd:command category="xml" file="lxml-ini.mkiv" level="style" name="xmldoifatt">
+ <cd:arguments>
+ <cd:keywords delimiters="braces">
+ <cd:constant type="cd:node"/>
+ </cd:keywords>
+ <cd:string/>
+ <cd:string/>
+ <cd:keywords delimiters="braces">
+ <cd:constant type="cd:true"/>
+ </cd:keywords>
+ </cd:arguments>
+ </cd:command>
+ <cd:command category="xml" file="lxml-ini.mkiv" level="style" name="xmldoifnotatt">
+ <cd:arguments>
+ <cd:keywords delimiters="braces">
+ <cd:constant type="cd:node"/>
+ </cd:keywords>
+ <cd:string/>
+ <cd:string/>
+ <cd:keywords delimiters="braces">
+ <cd:constant type="cd:true"/>
+ </cd:keywords>
+ </cd:arguments>
+ </cd:command>
+ <cd:command category="xml" file="lxml-ini.mkiv" level="style" name="xmldoifelseatt">
+ <cd:arguments>
+ <cd:keywords delimiters="braces">
+ <cd:constant type="cd:node"/>
+ </cd:keywords>
+ <cd:string/>
+ <cd:string/>
+ <cd:keywords delimiters="braces">
+ <cd:constant type="cd:true"/>
+ </cd:keywords>
+ <cd:keywords delimiters="braces">
+ <cd:constant type="cd:false"/>
+ </cd:keywords>
+ </cd:arguments>
+ </cd:command>
<cd:command category="xml" file="lxml-ini.mkiv" level="style" name="xmldoifselfempty">
<cd:arguments>
<cd:keywords delimiters="braces">
diff --git a/tex/context/interface/mkiv/i-context.pdf b/tex/context/interface/mkiv/i-context.pdf
index 4ef3011df..16cba5392 100644
--- a/tex/context/interface/mkiv/i-context.pdf
+++ b/tex/context/interface/mkiv/i-context.pdf
Binary files differ
diff --git a/tex/context/interface/mkiv/i-fonts.xml b/tex/context/interface/mkiv/i-fonts.xml
index 1e6e169a4..9735f8935 100644
--- a/tex/context/interface/mkiv/i-fonts.xml
+++ b/tex/context/interface/mkiv/i-fonts.xml
@@ -421,7 +421,6 @@
<cd:resolve name="argument-false"/>
</cd:arguments>
</cd:command>
-
<cd:command name="doifcurrentfonthasfeatureelse" level="system" category="fonts conditional" file="font-fea.mkvi">
<cd:arguments>
<cd:resolve name="argument-name"/>
@@ -430,6 +429,29 @@
</cd:arguments>
</cd:command>
+ <cd:command name="doifelsefontfeature" level="system" category="fonts conditional" file="font-fea.mkvi">
+ <cd:arguments>
+ <cd:resolve name="argument-name"/>
+ <cd:resolve name="argument-true"/>
+ <cd:resolve name="argument-false"/>
+ </cd:arguments>
+ </cd:command>
+ <cd:command name="doiffontfeatureelse" level="system" category="fonts conditional" file="font-fea.mkvi">
+ <cd:arguments>
+ <cd:resolve name="argument-name"/>
+ <cd:resolve name="argument-true"/>
+ <cd:resolve name="argument-false"/>
+ </cd:arguments>
+ </cd:command>
+
+ <cd:command name="doifunknownfontfeature" level="system" category="fonts conditional" file="font-fea.mkvi">
+ <cd:arguments>
+ <cd:resolve name="argument-name"/>
+ <cd:resolve name="argument-true"/>
+ <cd:resolve name="argument-false"/>
+ </cd:arguments>
+ </cd:command>
+
<cd:command name="doaddfeature" level="system" category="fonts" file="font-fea.mkvi">
<cd:arguments>
<cd:resolve name="argument-name-list"/>
diff --git a/tex/context/interface/mkiv/i-readme.pdf b/tex/context/interface/mkiv/i-readme.pdf
index d8b9f44d9..539507938 100644
--- a/tex/context/interface/mkiv/i-readme.pdf
+++ b/tex/context/interface/mkiv/i-readme.pdf
Binary files differ
diff --git a/tex/context/interface/mkiv/i-visualizer.xml b/tex/context/interface/mkiv/i-visualizer.xml
index daaad28cd..cf9d22e22 100644
--- a/tex/context/interface/mkiv/i-visualizer.xml
+++ b/tex/context/interface/mkiv/i-visualizer.xml
@@ -148,6 +148,10 @@
<cd:command name="showfontitalics" level="document" file="trc-vis.mkiv"/>
+ <cd:command name="showglyphdata" level="document" file="trc-vis.mkiv"/>
+
+ <cd:command name="showfontexpansion" level="document" file="trc-vis.mkiv"/>
+
<cd:command name="setvisualizerfont" level="system" file="trc-vis.mkiv">
<cd:arguments>
<cd:resolve name="keyword-font-optional"/>
@@ -156,4 +160,4 @@
<cd:command name="resetvisualizers" level="system" file="trc-vis.mkiv"/>
-</cd:interface> \ No newline at end of file
+</cd:interface>
diff --git a/tex/context/interface/mkiv/i-xml.xml b/tex/context/interface/mkiv/i-xml.xml
index d09913f7c..1786e1bf6 100644
--- a/tex/context/interface/mkiv/i-xml.xml
+++ b/tex/context/interface/mkiv/i-xml.xml
@@ -664,6 +664,34 @@
</cd:arguments>
</cd:command>
+ <cd:command name="xmldoifatt" level="style" category="xml" file="lxml-ini.mkiv">
+ <cd:arguments>
+ <cd:resolve name="argument-node"/>
+ <cd:string/>
+ <cd:string/>
+ <cd:resolve name="argument-true"/>
+ </cd:arguments>
+ </cd:command>
+
+ <cd:command name="xmldoifnotatt" level="style" category="xml" file="lxml-ini.mkiv">
+ <cd:arguments>
+ <cd:resolve name="argument-node"/>
+ <cd:string/>
+ <cd:string/>
+ <cd:resolve name="argument-true"/>
+ </cd:arguments>
+ </cd:command>
+
+ <cd:command name="xmldoifelseatt" level="style" category="xml" file="lxml-ini.mkiv">
+ <cd:arguments>
+ <cd:resolve name="argument-node"/>
+ <cd:string/>
+ <cd:string/>
+ <cd:resolve name="argument-true"/>
+ <cd:resolve name="argument-false"/>
+ </cd:arguments>
+ </cd:command>
+
<cd:command name="xmldoifselfempty" level="style" category="xml" file="lxml-ini.mkiv">
<cd:arguments>
<cd:resolve name="argument-node"/>