summaryrefslogtreecommitdiff
path: root/tex
diff options
context:
space:
mode:
Diffstat (limited to 'tex')
-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-pe.mkii1
-rw-r--r--tex/context/base/mkiv/cont-new.mkiv2
-rw-r--r--tex/context/base/mkiv/context.mkiv2
-rw-r--r--tex/context/base/mkiv/font-imp-properties.lua8
-rw-r--r--tex/context/base/mkiv/lpdf-ini.lua3
-rw-r--r--tex/context/base/mkiv/mult-prm.lua6
-rw-r--r--tex/context/base/mkiv/status-files.pdfbin24755 -> 24730 bytes
-rw-r--r--tex/context/base/mkiv/status-lua.pdfbin257166 -> 257156 bytes
-rw-r--r--tex/context/base/mkxl/blob-ini.mkxl2
-rw-r--r--tex/context/base/mkxl/cont-new.mkxl2
-rw-r--r--tex/context/base/mkxl/context.mkxl2
-rw-r--r--tex/context/base/mkxl/font-chk.lmt4
-rw-r--r--tex/context/base/mkxl/font-con.lmt94
-rw-r--r--tex/context/base/mkxl/font-ctx.lmt16
-rw-r--r--tex/context/base/mkxl/font-hsh.lmt397
-rw-r--r--tex/context/base/mkxl/font-imp-quality.lmt583
-rw-r--r--tex/context/base/mkxl/font-imp-tracing.lmt10
-rw-r--r--tex/context/base/mkxl/font-ini.mklx14
-rw-r--r--tex/context/base/mkxl/font-lib.mklx36
-rw-r--r--tex/context/base/mkxl/font-one.lmt847
-rw-r--r--tex/context/base/mkxl/font-otl.lmt889
-rw-r--r--tex/context/base/mkxl/font-tfm.lmt666
-rw-r--r--tex/context/base/mkxl/font-tpk.lmt1304
-rw-r--r--tex/context/base/mkxl/lang-dis.lmt2
-rw-r--r--tex/context/base/mkxl/lang-hyp.lmt2
-rw-r--r--tex/context/base/mkxl/math-act.lmt18
-rw-r--r--tex/context/base/mkxl/math-dim.lmt249
-rw-r--r--tex/context/base/mkxl/math-fbk.lmt10
-rw-r--r--tex/context/base/mkxl/math-ini.lmt2
-rw-r--r--tex/context/base/mkxl/math-ini.mkxl2
-rw-r--r--tex/context/base/mkxl/math-noa.lmt60
-rw-r--r--tex/context/base/mkxl/math-tag.lmt50
-rw-r--r--tex/context/base/mkxl/math-vfu.lmt107
-rw-r--r--tex/context/base/mkxl/node-aux.lmt6
-rw-r--r--tex/context/base/mkxl/node-pro.lmt7
-rw-r--r--tex/context/base/mkxl/node-rul.lmt11
-rw-r--r--tex/context/base/mkxl/node-ser.lmt8
-rw-r--r--tex/context/base/mkxl/node-typ.lmt135
-rw-r--r--tex/context/base/mkxl/page-ini.lmt4
-rw-r--r--tex/context/base/mkxl/scrn-ref.lmt57
-rw-r--r--tex/context/base/mkxl/scrn-ref.mklx2
-rw-r--r--tex/context/base/mkxl/scrp-ini.lmt4
-rw-r--r--tex/context/base/mkxl/spac-chr.lmt4
-rw-r--r--tex/context/base/mkxl/spac-prf.lmt4
-rw-r--r--tex/context/base/mkxl/spac-ver.lmt30
-rw-r--r--tex/context/base/mkxl/supp-box.lmt4
-rw-r--r--tex/context/base/mkxl/trac-jus.lmt122
-rw-r--r--tex/context/base/mkxl/trac-jus.mkxl2
-rw-r--r--tex/context/base/mkxl/typo-adj.lmt8
-rw-r--r--tex/context/base/mkxl/typo-bld.lmt8
-rw-r--r--tex/context/base/mkxl/typo-krn.lmt10
-rw-r--r--tex/context/base/mkxl/typo-mar.lmt6
-rw-r--r--tex/context/base/mkxl/typo-par.mkxl2
-rw-r--r--tex/context/fonts/mkiv/type-imp-adobegaramond.mkiv42
-rw-r--r--tex/context/fonts/mkiv/type-imp-ebgaramond.mkiv4
-rw-r--r--tex/context/interface/mkii/keys-pe.xml1
-rw-r--r--tex/context/modules/mkiv/s-math-characters.lua22
-rw-r--r--tex/generic/context/luatex/luatex-fonts-merged.lua2
60 files changed, 5605 insertions, 294 deletions
diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii
index 5536dd894..876eacdfc 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{2021.11.30 19:43}
+\newcontextversion{2021.12.03 15:17}
%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 9f51621bf..48af7f8e3 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{2021.11.30 19:43}
+\edef\contextversion{2021.12.03 15:17}
%D For those who want to use this:
diff --git a/tex/context/base/mkii/mult-pe.mkii b/tex/context/base/mkii/mult-pe.mkii
index 410fa7590..290da95f2 100644
--- a/tex/context/base/mkii/mult-pe.mkii
+++ b/tex/context/base/mkii/mult-pe.mkii
@@ -1282,6 +1282,7 @@
\setinterfaceconstant{tab}{تب}
\setinterfaceconstant{text}{متن}
\setinterfaceconstant{textalign}{textalign}
+\setinterfaceconstant{textalternative}{textalternative}
\setinterfaceconstant{textcolor}{رنگ‌متن}
\setinterfaceconstant{textcommand}{فرمان‌متن}
\setinterfaceconstant{textdistance}{فاصله‌متن}
diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv
index 529d7448d..92172d354 100644
--- a/tex/context/base/mkiv/cont-new.mkiv
+++ b/tex/context/base/mkiv/cont-new.mkiv
@@ -13,7 +13,7 @@
% \normalend % uncomment this to get the real base runtime
-\newcontextversion{2021.11.30 19:43}
+\newcontextversion{2021.12.03 15:17}
%D This file is loaded at runtime, thereby providing an excellent place for hacks,
%D patches, extensions and new features. There can be local overloads in cont-loc
diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv
index 956425aa6..fa300cafd 100644
--- a/tex/context/base/mkiv/context.mkiv
+++ b/tex/context/base/mkiv/context.mkiv
@@ -49,7 +49,7 @@
%D {YYYY.MM.DD HH:MM} format.
\edef\contextformat {\jobname}
-\edef\contextversion{2021.11.30 19:43}
+\edef\contextversion{2021.12.03 15:17}
%D Kind of special:
diff --git a/tex/context/base/mkiv/font-imp-properties.lua b/tex/context/base/mkiv/font-imp-properties.lua
index 21b55aeb2..5405737a5 100644
--- a/tex/context/base/mkiv/font-imp-properties.lua
+++ b/tex/context/base/mkiv/font-imp-properties.lua
@@ -72,10 +72,10 @@ do
extra = amount
end
end
- parameters.space = amount * emwidth
- parameters.space_stretch = stretch * emwidth
- parameters.space_shrink = shrink * emwidth
- parameters.extra_space = extra * emwidth
+ parameters.space = amount * emwidth
+ parameters.spacestretch = stretch * emwidth
+ parameters.spaceshrink = shrink * emwidth
+ parameters.extraspace = extra * emwidth
end
end
diff --git a/tex/context/base/mkiv/lpdf-ini.lua b/tex/context/base/mkiv/lpdf-ini.lua
index 1098ef8fa..07e9c8df8 100644
--- a/tex/context/base/mkiv/lpdf-ini.lua
+++ b/tex/context/base/mkiv/lpdf-ini.lua
@@ -1410,7 +1410,8 @@ do
return timestamp
end
- lpdf.settime(tonumber(resolvers.variable("start_time")) or tonumber(resolvers.variable("SOURCE_DATE_EPOCH"))) -- bah
+ -- lpdf.settime(tonumber(resolvers.variable("starttime")) or tonumber(resolvers.variable("SOURCE_DATE_EPOCH"))) -- bah
+ lpdf.settime(tonumber(resolvers.variable("starttime")))
function lpdf.pdftimestamp(str)
local t = type(str)
diff --git a/tex/context/base/mkiv/mult-prm.lua b/tex/context/base/mkiv/mult-prm.lua
index 2c0d9d41b..87c52de04 100644
--- a/tex/context/base/mkiv/mult-prm.lua
+++ b/tex/context/base/mkiv/mult-prm.lua
@@ -301,6 +301,8 @@ return {
"crampedscriptstyle",
"crampedtextstyle",
"csstring",
+ "currentloopiterator",
+ "currentloopnesting",
"currentmarks",
"defcsname",
"dimensiondef",
@@ -320,6 +322,7 @@ return {
"expandafterspaces",
"expandcstoken",
"expanded",
+ "expandedloop",
"expandtoken",
"explicitdiscretionary",
"explicithyphenpenalty",
@@ -434,6 +437,7 @@ return {
"localbrokenpenalty",
"localcontrol",
"localcontrolled",
+ "localcontrolledloop",
"localinterlinepenalty",
"localleftbox",
"localleftboxbox",
@@ -507,6 +511,7 @@ return {
"protrudechars",
"protrusionboundary",
"pxdimen",
+ "quitloop",
"quitvmode",
"retokenized",
"rightmarginkern",
@@ -539,6 +544,7 @@ return {
"tracingmarks",
"tracingmath",
"undent",
+ "unexpandedloop",
"unletfrozen",
"unletprotected",
"untraced",
diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf
index 2cd4adcf2..41707d50a 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 9c5a72289..40471b66f 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/mkxl/blob-ini.mkxl b/tex/context/base/mkxl/blob-ini.mkxl
index 1dcd55972..2e27ab20e 100644
--- a/tex/context/base/mkxl/blob-ini.mkxl
+++ b/tex/context/base/mkxl/blob-ini.mkxl
@@ -18,7 +18,7 @@
%D down the road (close to version 1.00 of \LUATEX). Typesetting in
%D pure \LUA\ sometimes makes sense.
-\registerctxluafile{node-typ}{} % experimental
+\registerctxluafile{node-typ}{autosuffix} % experimental
\registerctxluafile{blob-ini}{autosuffix}
\unprotect
diff --git a/tex/context/base/mkxl/cont-new.mkxl b/tex/context/base/mkxl/cont-new.mkxl
index 3bfffe608..95430abf6 100644
--- a/tex/context/base/mkxl/cont-new.mkxl
+++ b/tex/context/base/mkxl/cont-new.mkxl
@@ -13,7 +13,7 @@
% \normalend % uncomment this to get the real base runtime
-\newcontextversion{2021.11.30 19:43}
+\newcontextversion{2021.12.03 15:17}
%D This file is loaded at runtime, thereby providing an excellent place for hacks,
%D patches, extensions and new features. There can be local overloads in cont-loc
diff --git a/tex/context/base/mkxl/context.mkxl b/tex/context/base/mkxl/context.mkxl
index 854c65e98..914f4bfd9 100644
--- a/tex/context/base/mkxl/context.mkxl
+++ b/tex/context/base/mkxl/context.mkxl
@@ -29,7 +29,7 @@
%D {YYYY.MM.DD HH:MM} format.
\immutable\edef\contextformat {\jobname}
-\immutable\edef\contextversion{2021.11.30 19:43}
+\immutable\edef\contextversion{2021.12.03 15:17}
%overloadmode 1 % check frozen / warning
%overloadmode 2 % check frozen / error
diff --git a/tex/context/base/mkxl/font-chk.lmt b/tex/context/base/mkxl/font-chk.lmt
index 967431423..008b9bb41 100644
--- a/tex/context/base/mkxl/font-chk.lmt
+++ b/tex/context/base/mkxl/font-chk.lmt
@@ -379,13 +379,13 @@ local function expandglyph(characters,index,done)
if n then
d.next = expandglyph(characters,n,done)
end
- local h = d.horiz_variants
+ local h = d.hvariants
if h then
for i=1,#h do
h[i].glyph = expandglyph(characters,h[i].glyph,done)
end
end
- local v = d.vert_variants
+ local v = d.vvariants
if v then
for i=1,#v do
v[i].glyph = expandglyph(characters,v[i].glyph,done)
diff --git a/tex/context/base/mkxl/font-con.lmt b/tex/context/base/mkxl/font-con.lmt
index b452f5a12..3310242a8 100644
--- a/tex/context/base/mkxl/font-con.lmt
+++ b/tex/context/base/mkxl/font-con.lmt
@@ -161,17 +161,17 @@ function constructors.trytosharefont(target,tfmdata)
end
local synonyms = {
- exheight = "x_height",
- xheight = "x_height",
- ex = "x_height",
+ exheight = "xheight",
+ xheight = "xheight",
+ ex = "xheight",
emwidth = "quad",
em = "quad",
- spacestretch = "space_stretch",
- stretch = "space_stretch",
- spaceshrink = "space_shrink",
- shrink = "space_shrink",
- extraspace = "extra_space",
- xspace = "extra_space",
+ spacestretch = "spacestretch",
+ stretch = "spacestretch",
+ spaceshrink = "spaceshrink",
+ shrink = "spaceshrink",
+ extraspace = "extraspace",
+ xspace = "extraspace",
slantperpoint = "slant",
}
@@ -188,9 +188,9 @@ function constructors.enhanceparameters(parameters)
if k == "spacing" then
return {
width = t.space,
- stretch = t.space_stretch,
- shrink = t.space_shrink,
- extra = t.extra_space,
+ stretch = t.spacestretch,
+ shrink = t.spaceshrink,
+ extra = t.extraspace,
}
end
return mt and mt[k] or nil
@@ -205,9 +205,9 @@ function constructors.enhanceparameters(parameters)
elseif k == "spacing" then
if type(v) == "table" then
rawset(t,"space",v.width or 0)
- rawset(t,"space_stretch",v.stretch or 0)
- rawset(t,"space_shrink",v.shrink or 0)
- rawset(t,"extra_space",v.extra or 0)
+ rawset(t,"spacestretch",v.stretch or 0)
+ rawset(t,"spaceshrink",v.shrink or 0)
+ rawset(t,"extraspace",v.extra or 0)
end
else
rawset(t,k,v)
@@ -437,21 +437,21 @@ function constructors.scale(tfmdata,specification)
--
target.postprocessors = tfmdata.postprocessors
--
- local targetslant = (parameters.slant or parameters[1] or 0) * factors.pt -- per point
- local targetspace = (parameters.space or parameters[2] or 0) * hdelta
- local targetspace_stretch = (parameters.space_stretch or parameters[3] or 0) * hdelta
- local targetspace_shrink = (parameters.space_shrink or parameters[4] or 0) * hdelta
- local targetx_height = (parameters.x_height or parameters[5] or 0) * vdelta
- local targetquad = (parameters.quad or parameters[6] or 0) * hdelta
- local targetextra_space = (parameters.extra_space or parameters[7] or 0) * hdelta
- --
- targetparameters.slant = targetslant -- slantperpoint
- targetparameters.space = targetspace
- targetparameters.space_stretch = targetspace_stretch
- targetparameters.space_shrink = targetspace_shrink
- targetparameters.x_height = targetx_height
- targetparameters.quad = targetquad
- targetparameters.extra_space = targetextra_space
+ local targetslant = (parameters.slant or parameters[1] or 0) * factors.pt -- per point
+ local targetspace = (parameters.space or parameters[2] or 0) * hdelta
+ local targetspacestretch = (parameters.spacestretch or parameters[3] or 0) * hdelta
+ local targetspaceshrink = (parameters.spaceshrink or parameters[4] or 0) * hdelta
+ local targetxheight = (parameters.xheight or parameters[5] or 0) * vdelta
+ local targetquad = (parameters.quad or parameters[6] or 0) * hdelta
+ local targetextraspace = (parameters.extraspace or parameters[7] or 0) * hdelta
+ --
+ targetparameters.slant = targetslant -- slantperpoint
+ targetparameters.space = targetspace
+ targetparameters.spacestretch = targetspacestretch
+ targetparameters.spaceshrink = targetspaceshrink
+ targetparameters.xheight = targetxheight
+ targetparameters.quad = targetquad
+ targetparameters.extraspace = targetextraspace
--
local hshift = parameters.hshift
if hshift then
@@ -653,17 +653,17 @@ function constructors.scale(tfmdata,specification)
end
if hasquality then
-- we could move these calculations elsewhere (saves calculations)
- local ve = character.expansion_factor
+ local ve = character.expansion
if ve then
- chr.expansion_factor = ve*1000 -- expansionfactor, hm, can happen elsewhere
+ chr.expansion = ve*1000 -- expansionfactor, hm, can happen elsewhere
end
- local vl = character.left_protruding
+ local vl = character.leftprotrusion
if vl then
- chr.left_protruding = width*vl
+ chr.leftprotrusion = width*vl
end
- local vr = character.right_protruding
+ local vr = character.rightprotrusion
if vr then
- chr.right_protruding = width*vr
+ chr.rightprotrusion = width*vr
end
end
--
@@ -674,7 +674,7 @@ function constructors.scale(tfmdata,specification)
if vn then
chr.next = vn
else
- local vv = character.vert_variants
+ local vv = character.vvariants
if vv then
local t = { }
for i=1,#vv do
@@ -690,9 +690,9 @@ function constructors.scale(tfmdata,specification)
["glyph"] = vvi["glyph"],
}
end
- chr.vert_variants = t
+ chr.vvariants = t
else
- local hv = character.horiz_variants
+ local hv = character.hvariants
if hv then
local t = { }
for i=1,#hv do
@@ -708,18 +708,18 @@ function constructors.scale(tfmdata,specification)
["glyph"] = hvi["glyph"],
}
end
- chr.horiz_variants = t
+ chr.hvariants = t
end
end
-- todo also check mathitalics (or that one can go away)
end
- local vi = character.vert_italic
+ local vi = character.vitalic
if vi and vi ~= 0 then
- chr.vert_italic = vi*hdelta
+ chr.vitalic = vi*hdelta
end
local va = character.accent
if va then
- chr.top_accent = vdelta*va
+ chr.topaccent = vdelta*va
end
if stackmath then
local mk = character.mathkerns
@@ -729,10 +729,10 @@ function constructors.scale(tfmdata,specification)
local br = mk.bottomright
local bl = mk.bottomleft
chr.mathkern = { -- singular -> should be patched in luatex !
- top_right = tr and mathkerns(tr,vdelta) or nil,
- top_left = tl and mathkerns(tl,vdelta) or nil,
- bottom_right = br and mathkerns(br,vdelta) or nil,
- bottom_left = bl and mathkerns(bl,vdelta) or nil,
+ topright = tr and mathkerns(tr,vdelta) or nil,
+ topleft = tl and mathkerns(tl,vdelta) or nil,
+ bottomright = br and mathkerns(br,vdelta) or nil,
+ bottomleft = bl and mathkerns(bl,vdelta) or nil,
}
end
end
diff --git a/tex/context/base/mkxl/font-ctx.lmt b/tex/context/base/mkxl/font-ctx.lmt
index ed8c22f58..05cad84f0 100644
--- a/tex/context/base/mkxl/font-ctx.lmt
+++ b/tex/context/base/mkxl/font-ctx.lmt
@@ -303,14 +303,14 @@ function definers.resetnullfont()
-- resetting is needed because tikz misuses nullfont
local parameters = fonts.nulldata.parameters
--
- parameters.slant = 0 -- 1
- parameters.space = 0 -- 2
- parameters.space_stretch = 0 -- 3
- parameters.space_shrink = 0 -- 4
- parameters.x_height = 0 -- 5
- parameters.quad = 0 -- 6
- parameters.extra_space = 0 -- 7
- parameters.designsize = 655360
+ parameters.slant = 0 -- 1
+ parameters.space = 0 -- 2
+ parameters.spacestretch = 0 -- 3
+ parameters.spaceshrink = 0 -- 4
+ parameters.xheight = 0 -- 5
+ parameters.quad = 0 -- 6
+ parameters.extraspace = 0 -- 7
+ parameters.designsize = 655360
--
constructors.enhanceparameters(parameters) -- official copies for us
--
diff --git a/tex/context/base/mkxl/font-hsh.lmt b/tex/context/base/mkxl/font-hsh.lmt
new file mode 100644
index 000000000..594f47332
--- /dev/null
+++ b/tex/context/base/mkxl/font-hsh.lmt
@@ -0,0 +1,397 @@
+if not modules then modules = { } end modules ['font-hsh'] = {
+ 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 rawget = rawget
+
+local setmetatableindex = table.setmetatableindex
+local currentfont = font and font.current -- used in the web service
+local allocate = utilities.storage.allocate
+
+local fonts = fonts
+local hashes = fonts.hashes or allocate()
+fonts.hashes = hashes
+
+-- todo: autoallocate ... just create on the fly .. use constructors.keys (problem: plurals)
+
+local identifiers = hashes.identifiers or allocate()
+local characters = hashes.characters or allocate() -- chardata
+local descriptions = hashes.descriptions or allocate()
+local parameters = hashes.parameters or allocate()
+local mathparameters = hashes.mathparameters or allocate()
+local properties = hashes.properties or allocate()
+local resources = hashes.resources or allocate()
+local spacings = hashes.spacings or allocate()
+local spaces = hashes.spaces or allocate()
+local quads = hashes.quads or allocate() -- maybe also spacedata
+local xheights = hashes.xheights or allocate()
+local csnames = hashes.csnames or allocate() -- namedata
+local features = hashes.features or allocate()
+local marks = hashes.marks or allocate()
+local classes = hashes.classes or allocate()
+local italics = hashes.italics or allocate()
+local lastmathids = hashes.lastmathids or allocate()
+local dynamics = hashes.dynamics or allocate()
+local unicodes = hashes.unicodes or allocate()
+local unislots = hashes.unislots or allocate()
+local originals = hashes.originals or allocate()
+local modes = hashes.modes or allocate()
+local variants = hashes.variants or allocate()
+
+hashes.characters = characters
+hashes.descriptions = descriptions
+hashes.parameters = parameters
+hashes.mathparameters = mathparameters
+hashes.properties = properties
+hashes.resources = resources
+hashes.spacings = spacings
+hashes.spaces = spaces
+hashes.quads = quads hashes.emwidths = quads
+hashes.xheights = xheights hashes.exheights = xheights
+hashes.csnames = csnames
+hashes.features = features
+hashes.marks = marks
+hashes.classes = classes
+hashes.italics = italics
+hashes.lastmathids = lastmathids
+hashes.dynamics = dynamics
+hashes.unicodes = unicodes
+hashes.unislots = unislots
+hashes.originals = originals
+hashes.modes = modes
+hashes.variants = variants
+
+local nodepool = nodes and nodes.pool
+local dummyglyph = nodepool and nodepool.register(nodepool.glyph())
+
+local nulldata = allocate {
+ name = "nullfont",
+ characters = { },
+ descriptions = { },
+ properties = {
+ designsize = 786432, -- really ? maybe move to 655360 instead
+ },
+ parameters = { -- lmromanregular @ 12pt
+ slantperpoint = 0,
+ spacing = {
+ width = 256377,
+ stretch = 128188,
+ shrink = 85459,
+ extra = 85459,
+ },
+ quad = 786432,
+ size = 786432,
+ slant = 0, -- 1
+ space = 256377, -- 2
+ spacestretch = 128188, -- 3
+ spaceshrink = 85459, -- 4
+ xheight = 338952, -- 5
+ quad = 786432, -- 6
+ extraspace = 85459, -- 7
+ },
+}
+
+fonts.nulldata = nulldata
+
+fonts.constructors.enhanceparameters(nulldata.parameters) -- official copies for us
+
+setmetatableindex(identifiers, function(t,k)
+ return k == true and identifiers[currentfont()] or nulldata
+end)
+
+if font then
+
+ -- to be used
+
+ local define = font.define
+ local setfont = font.setfont
+ local frozen = font.frozen
+
+ function fonts.reserveid(fontdata)
+ return define(fontdata or nulldata)
+ end
+
+ function fonts.enhanceid(id,fontdata)
+ if not frozen(id) then
+ setfont(id,fontdata)
+ end
+ end
+
+end
+
+setmetatableindex(characters, function(t,k)
+ if k == true then
+ return characters[currentfont()]
+ else
+ local characters = identifiers[k].characters
+ t[k] = characters
+ return characters
+ end
+end)
+
+setmetatableindex(descriptions, function(t,k)
+ if k == true then
+ return descriptions[currentfont()]
+ else
+ local descriptions = identifiers[k].descriptions
+ t[k] = descriptions
+ return descriptions
+ end
+end)
+
+setmetatableindex(parameters, function(t,k)
+ if k == true then
+ return parameters[currentfont()]
+ else
+ local parameters = identifiers[k].parameters
+ t[k] = parameters
+ return parameters
+ end
+end)
+
+setmetatableindex(mathparameters, function(t,k)
+ if k == true then
+ return mathparameters[currentfont()]
+ else
+ local mathparameters = identifiers[k].mathparameters
+ t[k] = mathparameters
+ return mathparameters
+ end
+end)
+
+setmetatableindex(properties, function(t,k)
+ if k == true then
+ return properties[currentfont()]
+ else
+ local properties = identifiers[k].properties
+ t[k] = properties
+ return properties
+ end
+end)
+
+setmetatableindex(resources, function(t,k)
+ if k == true then
+ return resources[currentfont()]
+ else
+ local shared = identifiers[k].shared
+ local rawdata = shared and shared.rawdata
+ local resources = rawdata and rawdata.resources
+ t[k] = resources or false -- better than resolving each time
+ return resources
+ end
+end)
+
+setmetatableindex(features, function(t,k)
+ if k == true then
+ return features[currentfont()]
+ else
+ local shared = identifiers[k].shared
+ local features = shared and shared.features or { }
+ t[k] = features
+ return features
+ end
+end)
+
+local nospacing = {
+ width = 0,
+ stretch = 0,
+ shrink = 0,
+ extra = 0,
+}
+
+setmetatableindex(spacings, function(t,k)
+ if k == true then
+ return spacings[currentfont()]
+ else
+ local parameters = parameters[k]
+ local spacing = parameters and parameters.spacing or nospacing
+ t[k] = spacing
+ return spacing
+ end
+end)
+
+setmetatableindex(spaces, function(t,k)
+ if k == true then
+ return spaces[currentfont()]
+ else
+ local space = spacings[k].width
+ t[k] = space
+ return space
+ end
+end)
+
+setmetatableindex(marks, function(t,k)
+ if k == true then
+ return marks[currentfont()]
+ else
+ local resources = identifiers[k].resources or { }
+ local marks = resources.marks or { }
+ t[k] = marks
+ return marks
+ end
+end)
+
+setmetatableindex(classes, function(t,k)
+ if k == true then
+ return classes[currentfont()]
+ else
+ local resources = identifiers[k].resources or { }
+ local classes = resources.classes or { }
+ t[k] = classes
+ return classes
+ end
+end)
+
+setmetatableindex(quads, function(t,k)
+ if k == true then
+ return quads[currentfont()]
+ else
+ local parameters = rawget(parameters,k)
+ local quad
+ if parameters then
+ quad = parameters.quad
+ elseif dummyglyph then
+ dummyglyph.font = k
+ dummyglyph.char = 0x2014 -- emdash
+ quad = dummyglyph.width -- dirty trick
+ end
+ if not quad or quad == 0 then
+ quad = 655360 -- lm 10pt
+ end
+ t[k] = quad
+ return quad
+ end
+end)
+
+setmetatableindex(xheights, function(t,k)
+ if k == true then
+ return xheights[currentfont()]
+ else
+ local parameters = rawget(parameters,k)
+ local xheight
+ if parameters then
+ xheight = parameters.xheight
+ elseif dummyglyph then
+ dummyglyph.font = k
+ dummyglyph.char = 0x78 -- x
+ xheight = dummyglyph.height -- dirty trick
+ end
+ if not xheight or xheight == 0 then
+ xheight = 282460 -- lm 10pt
+ end
+ t[k] = xheight
+ return xheight
+ end
+end)
+
+setmetatableindex(italics, function(t,k) -- is test !
+ if k == true then
+ return italics[currentfont()]
+ else
+ local properties = identifiers[k].properties
+ local hasitalics = properties and properties.hasitalics
+ if hasitalics then
+ hasitalics = characters[k] -- convenient return
+ else
+ hasitalics = false
+ end
+ t[k] = hasitalics
+ return hasitalics
+ end
+end)
+
+setmetatableindex(dynamics, function(t,k)
+ if k == true then
+ return dynamics[currentfont()]
+ else
+ local shared = identifiers[k].shared
+ local dynamics = shared and shared.dynamics or false
+ t[k] = dynamics
+ return dynamics
+ end
+end)
+
+setmetatableindex(unicodes, function(t,k) -- always a unicode
+ if k == true then
+ return unicodes[currentfont()]
+ else
+ local resources = resources[k]
+ local unicodes = resources and resources.unicodes or { }
+ t[k] = unicodes
+ return unicodes
+ end
+end)
+
+setmetatableindex(originals, function(t,k) -- always a unicode
+ if k == true then
+ return originals[currentfont()]
+ else
+ local resolved = { }
+ setmetatableindex(resolved,function(t,name)
+ local u = unicodes[k][name]
+ local d = u and descriptions[k][u]
+ local v = d and d.unicode or u or 0 -- so we return notdef (at least for the moment)
+ t[name] = u
+ return v
+ end)
+ t[k] = resolved
+ return resolved
+ end
+end)
+
+setmetatableindex(unislots, function(t,k)
+ if k == true then
+ return unislots[currentfont()]
+ else
+ local characters = identifiers[k].characters
+ local resolved = setmetatableindex(function(t,k)
+ local c = characters[k]
+ local v = c and c.unicode or 0xFFFD
+ t[k] = v
+ return v -- can be a table !
+ end)
+ t[k] = resolved
+ return resolved
+ end
+end)
+
+setmetatableindex(modes, function(t,k)
+ if k == true then
+ return modes[currentfont()]
+ else
+ local mode = properties[k].mode or "base"
+ t[k] = mode
+ return mode
+ end
+end)
+
+setmetatableindex(variants, function(t,k)
+ if k == true then
+ return variants[currentfont()]
+ else
+ local resources = resources[k]
+ if resources then
+ local variants = resources.variants
+ if variants and next(variants) then
+ t[k] = variants
+ return variants
+ end
+ end
+ t[k] = false
+ return false
+ end
+end)
+
+if font then
+
+ function font.getfont(id)
+ return identifiers[id]
+ end
+
+end
+
+-- font.setfont = currentfont -- bah, no native 'setfont' as name
diff --git a/tex/context/base/mkxl/font-imp-quality.lmt b/tex/context/base/mkxl/font-imp-quality.lmt
new file mode 100644
index 000000000..93ec1b653
--- /dev/null
+++ b/tex/context/base/mkxl/font-imp-quality.lmt
@@ -0,0 +1,583 @@
+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"
+}
+
+if not context then return end
+
+local next, type, tonumber = next, type, tonumber
+
+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
+
+classes.preset = {
+ stretch = 2,
+ shrink = 2,
+ step = .5,
+ factor = 1,
+}
+
+classes['quality'] = {
+ stretch = 2,
+ shrink = 2,
+ step = .5,
+ vector = 'default',
+ factor = 1,
+}
+
+vectors['default'] = {
+ [0x0041] = 0.5, -- A
+ [0x0042] = 0.7, -- B
+ [0x0043] = 0.7, -- C
+ [0x0044] = 0.5, -- D
+ [0x0045] = 0.7, -- E
+ [0x0046] = 0.7, -- F
+ [0x0047] = 0.5, -- G
+ [0x0048] = 0.7, -- H
+ [0x004B] = 0.7, -- K
+ [0x004D] = 0.7, -- M
+ [0x004E] = 0.7, -- N
+ [0x004F] = 0.5, -- O
+ [0x0050] = 0.7, -- P
+ [0x0051] = 0.5, -- Q
+ [0x0052] = 0.7, -- R
+ [0x0053] = 0.7, -- S
+ [0x0055] = 0.7, -- U
+ [0x0057] = 0.7, -- W
+ [0x005A] = 0.7, -- Z
+ [0x0061] = 0.7, -- a
+ [0x0062] = 0.7, -- b
+ [0x0063] = 0.7, -- c
+ [0x0064] = 0.7, -- d
+ [0x0065] = 0.7, -- e
+ [0x0067] = 0.7, -- g
+ [0x0068] = 0.7, -- h
+ [0x006B] = 0.7, -- k
+ [0x006D] = 0.7, -- m
+ [0x006E] = 0.7, -- n
+ [0x006F] = 0.7, -- o
+ [0x0070] = 0.7, -- p
+ [0x0071] = 0.7, -- q
+ [0x0073] = 0.7, -- s
+ [0x0075] = 0.7, -- u
+ [0x0077] = 0.7, -- w
+ [0x007A] = 0.7, -- z
+ [0x0032] = 0.7, -- 2
+ [0x0033] = 0.7, -- 3
+ [0x0036] = 0.7, -- 6
+ [0x0038] = 0.7, -- 8
+ [0x0039] = 0.7, -- 9
+}
+
+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 = v*factor
+ else -- can be option
+ chr.expansion = 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)
+
+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.20, 0 }, -- ¿
+ [0x0021] = { 0, 0.20 }, -- !
+ [0x00A1] = { 0.20, 0, }, -- ¡
+ [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'] = {
+
+ [0x0041] = { .05, .05 }, -- A
+ [0x0046] = { 0, .05 }, -- F
+ [0x004A] = { .05, 0 }, -- J
+ [0x004B] = { 0, .05 }, -- K
+ [0x004C] = { 0, .05 }, -- L
+ [0x0054] = { .05, .05 }, -- T
+ [0x0056] = { .05, .05 }, -- V
+ [0x0057] = { .05, .05 }, -- W
+ [0x0058] = { .05, .05 }, -- X
+ [0x0059] = { .05, .05 }, -- Y
+
+ [0x006B] = { 0, .05 }, -- k
+ [0x0072] = { 0, .05 }, -- r
+ [0x0074] = { 0, .05 }, -- t
+ [0x0076] = { .05, .05 }, -- v
+ [0x0077] = { .05, .05 }, -- w
+ [0x0078] = { .05, .05 }, -- x
+ [0x0079] = { .05, .05 }, -- y
+
+}
+
+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 parameters = tfmdata.parameters
+ 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 units = parameters.units
+ 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
+ local lfactor = left * factor
+ local rfactor = right * factor
+ if trace_protrusion then
+ report_protrusions("left factor %0.3F, right factor %0.3F",lfactor,rfactor)
+ end
+ tfmdata.parameters.protrusion = {
+ factor = factor,
+ left = left,
+ right = right,
+ }
+ 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
+ if v == true then
+ -- zero
+ else
+ local w = descriptions[k].width
+ local d = - v[1]
+ if w == 0 or d == 0 then
+ -- ignored
+ else
+ local p = lfactor * d/units
+ characters[k].leftprotrusion = p
+ if trace_protrusion then
+ report_protrusions("lfbd -> %0.3F %C",p,k)
+ end
+ end
+ 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
+ if v == true then
+ -- zero
+ else
+ local w = descriptions[k].width
+ local d = - v[3]
+ if w == 0 or d == 0 then
+ -- ignored
+ else
+ local p = rfactor * d/units
+ characters[k].rightprotrusion = p
+ if trace_protrusion then
+ report_protrusions("rtbd -> %0.3F %C",p,k)
+ end
+ end
+ 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 lfactor = left * factor
+ local rfactor = right * factor
+ if trace_protrusion then
+ report_protrusions("left factor %0.3F, right factor %0.3F",lfactor,rfactor)
+ end
+ tfmdata.parameters.protrusion = {
+ factor = factor,
+ left = left,
+ right = right,
+ }
+ for i, chr in next, tfmdata.characters do
+ local v = vector[i]
+ local pl = nil
+ local pr = nil
+ if v then
+ pl = v[1]
+ pr = 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 = vector[s[1]]
+ local vr = 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 = v[1]
+ pr = v[2]
+ end
+ end
+ end
+ end
+ if pl and pl ~= 0 then
+ local p = pl * lfactor
+ chr.leftprotrusion = p
+ if trace_protrusion then
+ report_protrusions("left -> %0.3F %C ",p,i)
+ end
+ end
+ if pr and pr ~= 0 then
+ local p = pr * rfactor
+ chr.rightprotrusion = p
+ if trace_protrusion then
+ report_protrusions("right -> %0.3F %C",p,i)
+ end
+ 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)
+
+implement {
+ name = "setupfontprotrusion",
+ arguments = "2 strings",
+ actions = function(class,settings) getparameters(classes,class,'preset',settings) end
+}
+
+local function initialize(tfmdata,value)
+ local properties = tfmdata.properties
+ local parameters = tfmdata.parameters
+ if properties then
+ value = tonumber(value)
+ if value then
+ if value < 0 then
+ value = 0
+ elseif value > 10 then
+ report_expansions("threshold for %a @ %p limited to 10 pct",properties.fontname,parameters.size)
+ value = 10
+ end
+ if value > 5 then
+ report_expansions("threshold for %a @ %p exceeds 5 pct",properties.fontname,parameters.size)
+ end
+ end
+ properties.threshold = value or nil -- nil enforces default
+ end
+end
+
+local specification = {
+ name = "threshold",
+ description = "threshold for quality features",
+ initializers = {
+ base = initialize,
+ node = initialize,
+ }
+}
+
+registerotffeature(specification)
+registerafmfeature(specification)
diff --git a/tex/context/base/mkxl/font-imp-tracing.lmt b/tex/context/base/mkxl/font-imp-tracing.lmt
index 9f842b522..2187b9497 100644
--- a/tex/context/base/mkxl/font-imp-tracing.lmt
+++ b/tex/context/base/mkxl/font-imp-tracing.lmt
@@ -186,7 +186,7 @@ local function initialize(tfmdata,key,value)
local tlcolor = { "startcolor", "trace:4" } -- y / dy
for unicode, character in next, characters do
local mathkern = character.mathkern
- local italic = character.vert_italic or character.italic
+ local italic = character.vitalic or character.italic
if mathkern or (italic and italic ~= 0) then
local width = character.width or 0
local height = character.height or 0
@@ -202,10 +202,10 @@ local function initialize(tfmdata,key,value)
count = count + 1 list[count] = black
end
if mathkern then
- local br = mathkern.bottom_right
- local tr = mathkern.top_right
- local bl = mathkern.bottom_left
- local tl = mathkern.top_left
+ local br = mathkern.bottomright
+ local tr = mathkern.topright
+ local bl = mathkern.bottomleft
+ local tl = mathkern.topleft
if br then
local done = false
for i=1,#br do
diff --git a/tex/context/base/mkxl/font-ini.mklx b/tex/context/base/mkxl/font-ini.mklx
index db90bc79c..6a926bcbd 100644
--- a/tex/context/base/mkxl/font-ini.mklx
+++ b/tex/context/base/mkxl/font-ini.mklx
@@ -703,6 +703,8 @@
\mutable\let\lastrawfontcall \relax
\mutable\let\lastglobalrawfontcall\relax
+\immutable\dimensiondef\d_font_default_size 10pt
+
\protected\def\font_helpers_low_level_define
{\ifconditional\c_font_compact
\expandafter\font_helpers_low_level_define_compact
@@ -733,8 +735,10 @@
\fi
%
\ifcase\scaledfontmode\relax
- % none, avoid the designsize if possible
- \d_font_scaled_font_size-\plusthousand\scaledpoint
+ % mkiv, fails with glyphscale:
+ % \d_font_scaled_font_size-\plusthousand\scaledpoint
+ % so we just assume
+ \d_font_scaled_font_size\d_font_default_size
\or
% at
\d_font_scaled_font_size\somefontsize
@@ -830,8 +834,10 @@
\fi
%
\ifcase\scaledfontmode\relax
- % none, avoid the designsize if possible
- \d_font_scaled_font_size-\plusthousand\scaledpoint
+ % mkiv, fails with glyphscale:
+ % \d_font_scaled_font_size-\plusthousand\scaledpoint
+ % so we just assume
+ \d_font_scaled_font_size\d_font_default_size
\or
% at
\d_font_scaled_font_size\somefontsize
diff --git a/tex/context/base/mkxl/font-lib.mklx b/tex/context/base/mkxl/font-lib.mklx
index e8c5ad246..2f20214e7 100644
--- a/tex/context/base/mkxl/font-lib.mklx
+++ b/tex/context/base/mkxl/font-lib.mklx
@@ -21,30 +21,30 @@
%registerctxluafile{font-cft}{}
\registerctxluafile{font-enc}{}
\registerctxluafile{font-fmp}{autosuffix}
-\registerctxluafile{font-agl}{} % if needed we can comment this and delay loading
-\registerctxluafile{font-cid}{} % cid maps
+\registerctxluafile{font-agl}{} % if needed we can comment this and delay loading
+\registerctxluafile{font-cid}{} % cid maps
\registerctxluafile{font-map}{optimize}
% 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-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}{autosuffix} % hashes used by context
\registerctxluafile{font-vir}{}
\registerctxluafile{font-vfc}{autosuffix}
-\registerctxluafile{font-prv}{} % needs hashes
+\registerctxluafile{font-prv}{} % needs hashes
\registerctxluafile{font-nod}{optimize}
-\registerctxluafile{font-oti}{} % otf initialization
-\registerctxluafile{font-ott}{} % otf tables (first)
-\registerctxluafile{font-otl}{}
+\registerctxluafile{font-oti}{} % otf initialization
+\registerctxluafile{font-ott}{} % otf tables (first)
+\registerctxluafile{font-otl}{autosuffix}
\registerctxluafile{font-oto}{}
\registerctxluafile{font-otj}{autosuffix,optimize}
\registerctxluafile{font-oup}{}
\registerctxluafile{font-ota}{autosuffix}
-% \registerctxluafile{font-ots-pre-scale}{autosuffix,optimize}
+%registerctxluafile{font-ots-pre-scale}{autosuffix,optimize}
\registerctxluafile{font-ots}{autosuffix,optimize}
\registerctxluafile{font-otd}{autosuffix,optimize}
\registerctxluafile{font-otc}{}
@@ -56,15 +56,15 @@
% we use otf code for type one
\registerctxluafile{font-onr}{optimize}
-\registerctxluafile{font-one}{optimize}
+\registerctxluafile{font-one}{autosuffix,optimize}
\registerctxluafile{font-afk}{}
\registerctxluafile{font-txt}{autosuffix}
% tfm
-\registerctxluafile{font-tpk}{optimize}
-\registerctxluafile{font-tfm}{}
+\registerctxluafile{font-tpk}{autosuffix,optimize}
+\registerctxluafile{font-tfm}{autosuffix}
% name database
@@ -100,13 +100,13 @@
\registerctxluafile{font-imp-ligatures}{}
\registerctxluafile{font-imp-tex}{}
\registerctxluafile{font-imp-reorder}{}
-\registerctxluafile{font-imp-properties}{}
+\registerctxluafile{font-imp-properties}{autosuffix}
\registerctxluafile{font-imp-unicode}{}
\registerctxluafile{font-imp-text}{autosuffix}
\registerctxluafile{font-imp-math}{autosuffix}
\registerctxluafile{font-imp-notused}{}
\registerctxluafile{font-imp-effects}{autosuffix}
-\registerctxluafile{font-imp-quality}{}
+\registerctxluafile{font-imp-quality}{autosuffix}
\registerctxluafile{font-imp-italics}{}
\registerctxluafile{font-imp-dimensions}{}
\registerctxluafile{font-imp-spacekerns}{}
diff --git a/tex/context/base/mkxl/font-one.lmt b/tex/context/base/mkxl/font-one.lmt
new file mode 100644
index 000000000..453f61192
--- /dev/null
+++ b/tex/context/base/mkxl/font-one.lmt
@@ -0,0 +1,847 @@
+if not modules then modules = { } end modules ['font-one'] = {
+ version = 1.001,
+ optimize = true,
+ comment = "companion to font-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--[[ldx--
+<p>Some code may look a bit obscure but this has to do with the fact that we also use
+this code for testing and much code evolved in the transition from <l n='tfm'/> to
+<l n='afm'/> to <l n='otf'/>.</p>
+
+<p>The following code still has traces of intermediate font support where we handles
+font encodings. Eventually font encoding went away but we kept some code around in
+other modules.</p>
+
+<p>This version implements a node mode approach so that users can also more easily
+add features.</p>
+--ldx]]--
+
+local fonts, logs, trackers, containers, resolvers = fonts, logs, trackers, containers, resolvers
+
+local next, type, tonumber, rawget = next, type, tonumber, rawget
+local match, gsub = string.match, string.gsub
+local abs = math.abs
+local P, S, R, Cmt, C, Ct, Cs, Carg = lpeg.P, lpeg.S, lpeg.R, lpeg.Cmt, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg
+local lpegmatch, patterns = lpeg.match, lpeg.patterns
+local sortedhash = table.sortedhash
+
+local trace_features = false trackers.register("afm.features", function(v) trace_features = v end)
+local trace_indexing = false trackers.register("afm.indexing", function(v) trace_indexing = v end)
+local trace_loading = false trackers.register("afm.loading", function(v) trace_loading = v end)
+local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end)
+
+local report_afm = logs.reporter("fonts","afm loading")
+
+local setmetatableindex = table.setmetatableindex
+local derivetable = table.derive
+
+local findbinfile = resolvers.findbinfile
+
+local privateoffset = fonts.constructors and fonts.constructors.privateoffset or 0xF0000 -- 0x10FFFF
+
+local definers = fonts.definers
+local readers = fonts.readers
+local constructors = fonts.constructors
+
+local afm = constructors.handlers.afm
+local pfb = constructors.handlers.pfb
+local otf = fonts.handlers.otf
+
+local otfreaders = otf.readers
+local otfenhancers = otf.enhancers
+
+local afmfeatures = constructors.features.afm
+local registerafmfeature = afmfeatures.register
+
+local afmenhancers = constructors.enhancers.afm
+local registerafmenhancer = afmenhancers.register
+
+afm.version = 1.513 -- incrementing this number one up will force a re-cache
+afm.cache = containers.define("fonts", "one", afm.version, true)
+afm.autoprefixed = true -- this will become false some day (catches texnansi-blabla.*)
+
+afm.helpdata = { } -- set later on so no local for this
+afm.syncspace = true -- when true, nicer stretch values
+
+local overloads = fonts.mappings.overloads
+
+local applyruntimefixes = fonts.treatments and fonts.treatments.applyfixes
+
+--[[ldx--
+<p>We cache files. Caching is taken care of in the loader. We cheat a bit by adding
+ligatures and kern information to the afm derived data. That way we can set them faster
+when defining a font.</p>
+
+<p>We still keep the loading two phased: first we load the data in a traditional
+fashion and later we transform it to sequences. Then we apply some methods also
+used in opentype fonts (like <t>tlig</t>).</p>
+--ldx]]--
+
+function afm.load(filename)
+ filename = resolvers.findfile(filename,'afm') or ""
+ if filename ~= "" and not fonts.names.ignoredfile(filename) then
+ local name = file.removesuffix(file.basename(filename))
+ local data = containers.read(afm.cache,name)
+ local attr = lfs.attributes(filename)
+ local size = attr and attr.size or 0
+ local time = attr and attr.modification or 0
+ --
+ local pfbfile = file.replacesuffix(name,"pfb")
+ local pfbname = resolvers.findfile(pfbfile,"pfb") or ""
+ if pfbname == "" then
+ pfbname = resolvers.findfile(file.basename(pfbfile),"pfb") or ""
+ end
+ local pfbsize = 0
+ local pfbtime = 0
+ if pfbname ~= "" then
+ local attr = lfs.attributes(pfbname)
+ pfbsize = attr.size or 0
+ pfbtime = attr.modification or 0
+ end
+ if not data or data.size ~= size or data.time ~= time or data.pfbsize ~= pfbsize or data.pfbtime ~= pfbtime then
+ report_afm("reading %a",filename)
+ data = afm.readers.loadfont(filename,pfbname)
+ if data then
+ afmenhancers.apply(data,filename)
+ -- otfreaders.addunicodetable(data) -- only when not done yet
+ fonts.mappings.addtounicode(data,filename)
+ otfreaders.stripredundant(data)
+ -- otfreaders.extend(data)
+ otfreaders.pack(data)
+ data.size = size
+ data.time = time
+ data.pfbsize = pfbsize
+ data.pfbtime = pfbtime
+ report_afm("saving %a in cache",name)
+ -- data.resources.unicodes = nil -- consistent with otf but here we save not much
+ data = containers.write(afm.cache, name, data)
+ data = containers.read(afm.cache,name)
+ end
+ end
+ if data then
+ -- constructors.addcoreunicodes(unicodes)
+ otfreaders.unpack(data)
+ otfreaders.expand(data) -- inline tables
+ otfreaders.addunicodetable(data) -- only when not done yet
+ otfenhancers.apply(data,filename,data)
+ if applyruntimefixes then
+ applyruntimefixes(filename,data)
+ end
+ end
+ return data
+ end
+end
+
+-- we run a more advanced analyzer later on anyway
+
+local uparser = fonts.mappings.makenameparser() -- each time
+
+local function enhance_unify_names(data, filename)
+ local unicodevector = fonts.encodings.agl.unicodes -- loaded runtime in context
+ local unicodes = { }
+ local names = { }
+ local private = data.private or privateoffset
+ local descriptions = data.descriptions
+ for name, blob in sortedhash(data.characters) do -- sorting is nicer for privates
+ local code = unicodevector[name] -- or characters.name_to_unicode[name]
+ if not code then
+ code = lpegmatch(uparser,name)
+ if type(code) ~= "number" then
+ code = private
+ private = private + 1
+ report_afm("assigning private slot %U for unknown glyph name %a",code,name)
+ end
+ end
+ local index = blob.index
+ unicodes[name] = code
+ names[name] = index
+ blob.name = name
+ descriptions[code] = {
+ boundingbox = blob.boundingbox,
+ width = blob.width,
+ kerns = blob.kerns,
+ index = index,
+ name = name,
+ }
+ end
+ for unicode, description in next, descriptions do
+ local kerns = description.kerns
+ if kerns then
+ local krn = { }
+ for name, kern in next, kerns do
+ local unicode = unicodes[name]
+ if unicode then
+ krn[unicode] = kern
+ else
+ -- print(unicode,name)
+ end
+ end
+ description.kerns = krn
+ end
+ end
+ data.characters = nil
+ data.private = private
+ local resources = data.resources
+ local filename = resources.filename or file.removesuffix(file.basename(filename))
+ resources.filename = resolvers.unresolve(filename) -- no shortcut
+ resources.unicodes = unicodes -- name to unicode
+ resources.marks = { } -- todo
+ -- resources.names = names -- name to index
+end
+
+local everywhere = { ["*"] = { ["*"] = true } } -- or: { ["*"] = { "*" } }
+local noflags = { false, false, false, false }
+
+local function enhance_normalize_features(data)
+ local ligatures = setmetatableindex("table")
+ local kerns = setmetatableindex("table")
+ local extrakerns = setmetatableindex("table")
+ for u, c in next, data.descriptions do
+ local l = c.ligatures
+ local k = c.kerns
+ local e = c.extrakerns
+ if l then
+ ligatures[u] = l
+ for u, v in next, l do
+ l[u] = { ligature = v }
+ end
+ c.ligatures = nil
+ end
+ if k then
+ kerns[u] = k
+ for u, v in next, k do
+ k[u] = v -- { v, 0 }
+ end
+ c.kerns = nil
+ end
+ if e then
+ extrakerns[u] = e
+ for u, v in next, e do
+ e[u] = v -- { v, 0 }
+ end
+ c.extrakerns = nil
+ end
+ end
+ local features = {
+ gpos = { },
+ gsub = { },
+ }
+ local sequences = {
+ -- only filled ones
+ }
+ if next(ligatures) then
+ features.gsub.liga = everywhere
+ data.properties.hasligatures = true
+ sequences[#sequences+1] = {
+ features = {
+ liga = everywhere,
+ },
+ flags = noflags,
+ name = "s_s_0",
+ nofsteps = 1,
+ order = { "liga" },
+ type = "gsub_ligature",
+ steps = {
+ {
+ coverage = ligatures,
+ },
+ },
+ }
+ end
+ if next(kerns) then
+ features.gpos.kern = everywhere
+ data.properties.haskerns = true
+ sequences[#sequences+1] = {
+ features = {
+ kern = everywhere,
+ },
+ flags = noflags,
+ name = "p_s_0",
+ nofsteps = 1,
+ order = { "kern" },
+ type = "gpos_pair",
+ steps = {
+ {
+ format = "kern",
+ coverage = kerns,
+ },
+ },
+ }
+ end
+ if next(extrakerns) then
+ features.gpos.extrakerns = everywhere
+ data.properties.haskerns = true
+ sequences[#sequences+1] = {
+ features = {
+ extrakerns = everywhere,
+ },
+ flags = noflags,
+ name = "p_s_1",
+ nofsteps = 1,
+ order = { "extrakerns" },
+ type = "gpos_pair",
+ steps = {
+ {
+ format = "kern",
+ coverage = extrakerns,
+ },
+ },
+ }
+ end
+ -- todo: compress kerns
+ data.resources.features = features
+ data.resources.sequences = sequences
+end
+
+local function enhance_fix_names(data)
+ for k, v in next, data.descriptions do
+ local n = v.name
+ local r = overloads[n]
+ if r then
+ local name = r.name
+ if trace_indexing then
+ report_afm("renaming characters %a to %a",n,name)
+ end
+ v.name = name
+ v.unicode = r.unicode
+ end
+ end
+end
+
+--[[ldx--
+<p>These helpers extend the basic table with extra ligatures, texligatures
+and extra kerns. This saves quite some lookups later.</p>
+--ldx]]--
+
+local addthem = function(rawdata,ligatures)
+ if ligatures then
+ local descriptions = rawdata.descriptions
+ local resources = rawdata.resources
+ local unicodes = resources.unicodes
+ -- local names = resources.names
+ for ligname, ligdata in next, ligatures do
+ local one = descriptions[unicodes[ligname]]
+ if one then
+ for _, pair in next, ligdata do
+ local two = unicodes[pair[1]]
+ local three = unicodes[pair[2]]
+ if two and three then
+ local ol = one.ligatures
+ if ol then
+ if not ol[two] then
+ ol[two] = three
+ end
+ else
+ one.ligatures = { [two] = three }
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+local function enhance_add_ligatures(rawdata)
+ addthem(rawdata,afm.helpdata.ligatures)
+end
+
+--[[ldx--
+<p>We keep the extra kerns in separate kerning tables so that we can use
+them selectively.</p>
+--ldx]]--
+
+-- This is rather old code (from the beginning when we had only tfm). If
+-- we unify the afm data (now we have names all over the place) then
+-- we can use shcodes but there will be many more looping then. But we
+-- could get rid of the tables in char-cmp then. Als, in the generic version
+-- we don't use the character database. (Ok, we can have a context specific
+-- variant).
+
+local function enhance_add_extra_kerns(rawdata) -- using shcodes is not robust here
+ local descriptions = rawdata.descriptions
+ local resources = rawdata.resources
+ local unicodes = resources.unicodes
+ local function do_it_left(what)
+ if what then
+ for unicode, description in next, descriptions do
+ local kerns = description.kerns
+ if kerns then
+ local extrakerns
+ for complex, simple in next, what do
+ complex = unicodes[complex]
+ simple = unicodes[simple]
+ if complex and simple then
+ local ks = kerns[simple]
+ if ks and not kerns[complex] then
+ if extrakerns then
+ extrakerns[complex] = ks
+ else
+ extrakerns = { [complex] = ks }
+ end
+ end
+ end
+ end
+ if extrakerns then
+ description.extrakerns = extrakerns
+ end
+ end
+ end
+ end
+ end
+ local function do_it_copy(what)
+ if what then
+ for complex, simple in next, what do
+ complex = unicodes[complex]
+ simple = unicodes[simple]
+ if complex and simple then
+ local complexdescription = descriptions[complex]
+ if complexdescription then -- optional
+ local simpledescription = descriptions[complex]
+ if simpledescription then
+ local extrakerns
+ local kerns = simpledescription.kerns
+ if kerns then
+ for unicode, kern in next, kerns do
+ if extrakerns then
+ extrakerns[unicode] = kern
+ else
+ extrakerns = { [unicode] = kern }
+ end
+ end
+ end
+ local extrakerns = simpledescription.extrakerns
+ if extrakerns then
+ for unicode, kern in next, extrakerns do
+ if extrakerns then
+ extrakerns[unicode] = kern
+ else
+ extrakerns = { [unicode] = kern }
+ end
+ end
+ end
+ if extrakerns then
+ complexdescription.extrakerns = extrakerns
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ -- add complex with values of simplified when present
+ do_it_left(afm.helpdata.leftkerned)
+ do_it_left(afm.helpdata.bothkerned)
+ -- copy kerns from simple char to complex char unless set
+ do_it_copy(afm.helpdata.bothkerned)
+ do_it_copy(afm.helpdata.rightkerned)
+end
+
+--[[ldx--
+<p>The copying routine looks messy (and is indeed a bit messy).</p>
+--ldx]]--
+
+local function adddimensions(data) -- we need to normalize afm to otf i.e. indexed table instead of name
+ if data then
+ for unicode, description in next, data.descriptions do
+ local bb = description.boundingbox
+ if bb then
+ local ht = bb[4]
+ local dp = -bb[2]
+ if ht == 0 or ht < 0 then
+ -- no need to set it and no negative heights, nil == 0
+ else
+ description.height = ht
+ end
+ if dp == 0 or dp < 0 then
+ -- no negative depths and no negative depths, nil == 0
+ else
+ description.depth = dp
+ end
+ end
+ end
+ end
+end
+
+local function copytotfm(data)
+ if data and data.descriptions then
+ local metadata = data.metadata
+ local resources = data.resources
+ local properties = derivetable(data.properties)
+ local descriptions = derivetable(data.descriptions)
+ local goodies = derivetable(data.goodies)
+ local characters = { }
+ local parameters = { }
+ local unicodes = resources.unicodes
+ --
+ for unicode, description in next, data.descriptions do -- use parent table
+ characters[unicode] = { }
+ end
+ --
+ local filename = constructors.checkedfilename(resources)
+ local fontname = metadata.fontname or metadata.fullname
+ local fullname = metadata.fullname or metadata.fontname
+ local endash = 0x2013
+ local emdash = 0x2014
+ local space = 0x0020 -- space
+ local spacer = "space"
+ local spaceunits = 500
+ --
+ local monospaced = metadata.monospaced
+ local charwidth = metadata.charwidth
+ local italicangle = metadata.italicangle
+ local charxheight = metadata.xheight and metadata.xheight > 0 and metadata.xheight
+ properties.monospaced = monospaced
+ parameters.italicangle = italicangle
+ parameters.charwidth = charwidth
+ parameters.charxheight = charxheight
+ -- nearly the same as otf, catches
+ local d_endash = descriptions[endash]
+ local d_emdash = descriptions[emdash]
+ local d_space = descriptions[space]
+ if not d_space or d_space == 0 then
+ d_space = d_endash
+ end
+ if d_space then
+ spaceunits, spacer = d_space.width or 0, "space"
+ end
+ if properties.monospaced then
+ if spaceunits == 0 and d_emdash then
+ spaceunits, spacer = d_emdash.width or 0, "emdash"
+ end
+ else
+ if spaceunits == 0 and d_endash then
+ spaceunits, spacer = d_emdash.width or 0, "endash"
+ end
+ end
+ if spaceunits == 0 and charwidth then
+ spaceunits, spacer = charwidth or 0, "charwidth"
+ end
+ if spaceunits == 0 then
+ spaceunits = tonumber(spaceunits) or 500
+ end
+ if spaceunits == 0 then
+ spaceunits = 500
+ end
+ --
+ parameters.slant = 0
+ parameters.space = spaceunits
+ parameters.spacestretch = 500
+ parameters.spaceshrink = 333
+ parameters.xheight = 400
+ parameters.quad = 1000
+ --
+ if italicangle and italicangle ~= 0 then
+ parameters.italicangle = italicangle
+ parameters.italicfactor = math.cos(math.rad(90+italicangle))
+ parameters.slant = - math.tan(italicangle*math.pi/180)
+ end
+ if monospaced then
+ parameters.spacestretch = 0
+ parameters.spaceshrink = 0
+ elseif afm.syncspace then
+ parameters.spacestretch = spaceunits/2
+ parameters.spaceshrink = spaceunits/3
+ end
+ parameters.extraspace = parameters.spaceshrink
+ if charxheight then
+ parameters.xheight = charxheight
+ else
+ -- same as otf
+ local x = 0x0078 -- x
+ if x then
+ local x = descriptions[x]
+ if x then
+ parameters.xheight = x.height
+ end
+ end
+ --
+ end
+ --
+ if metadata.sup then
+ local dummy = { 0, 0, 0 }
+ parameters[ 1] = metadata.designsize or 0
+ parameters[ 2] = metadata.checksum or 0
+ parameters[ 3],
+ parameters[ 4],
+ parameters[ 5] = unpack(metadata.space or dummy)
+ parameters[ 6] = metadata.quad or 0
+ parameters[ 7] = metadata.extraspace or 0
+ parameters[ 8],
+ parameters[ 9],
+ parameters[10] = unpack(metadata.num or dummy)
+ parameters[11],
+ parameters[12] = unpack(metadata.denom or dummy)
+ parameters[13],
+ parameters[14],
+ parameters[15] = unpack(metadata.sup or dummy)
+ parameters[16],
+ parameters[17] = unpack(metadata.sub or dummy)
+ parameters[18] = metadata.supdrop or 0
+ parameters[19] = metadata.subdrop or 0
+ parameters[20],
+ parameters[21] = unpack(metadata.delim or dummy)
+ parameters[22] = metadata.axisheight or 0
+ end
+ --
+ parameters.designsize = (metadata.designsize or 10)*65536
+ parameters.ascender = abs(metadata.ascender or 0)
+ parameters.descender = abs(metadata.descender or 0)
+ parameters.units = 1000
+ --
+ properties.spacer = spacer
+ properties.format = fonts.formats[filename] or "type1"
+ properties.filename = filename
+ properties.fontname = fontname
+ properties.fullname = fullname
+ properties.psname = fullname
+ properties.name = filename or fullname or fontname
+ properties.private = properties.private or data.private or privateoffset
+ --
+if not CONTEXTLMTXMODE or CONTEXTLMTXMODE == 0 then
+ properties.encodingbytes = 2
+end
+ --
+ if next(characters) then
+ return {
+ characters = characters,
+ descriptions = descriptions,
+ parameters = parameters,
+ resources = resources,
+ properties = properties,
+ goodies = goodies,
+ }
+ end
+ end
+ return nil
+end
+
+--[[ldx--
+<p>Originally we had features kind of hard coded for <l n='afm'/> files but since I
+expect to support more font formats, I decided to treat this fontformat like any
+other and handle features in a more configurable way.</p>
+--ldx]]--
+
+function afm.setfeatures(tfmdata,features)
+ local okay = constructors.initializefeatures("afm",tfmdata,features,trace_features,report_afm)
+ if okay then
+ return constructors.collectprocessors("afm",tfmdata,features,trace_features,report_afm)
+ else
+ return { } -- will become false
+ end
+end
+
+local function addtables(data)
+ local resources = data.resources
+ local lookuptags = resources.lookuptags
+ local unicodes = resources.unicodes
+ if not lookuptags then
+ lookuptags = { }
+ resources.lookuptags = lookuptags
+ end
+ setmetatableindex(lookuptags,function(t,k)
+ local v = type(k) == "number" and ("lookup " .. k) or k
+ t[k] = v
+ return v
+ end)
+ if not unicodes then
+ unicodes = { }
+ resources.unicodes = unicodes
+ setmetatableindex(unicodes,function(t,k)
+ setmetatableindex(unicodes,nil)
+ for u, d in next, data.descriptions do
+ local n = d.name
+ if n then
+ t[n] = u
+ end
+ end
+ return rawget(t,k)
+ end)
+ end
+ constructors.addcoreunicodes(unicodes) -- do we really need this?
+end
+
+local function afmtotfm(specification)
+ local afmname = specification.filename or specification.name
+ if specification.forced == "afm" or specification.format == "afm" then -- move this one up
+ if trace_loading then
+ report_afm("forcing afm format for %a",afmname)
+ end
+ else
+ local tfmname = findbinfile(afmname,"ofm") or ""
+ if tfmname ~= "" then
+ if trace_loading then
+ report_afm("fallback from afm to tfm for %a",afmname)
+ end
+ return -- just that
+ end
+ end
+ if afmname ~= "" then
+ -- weird, isn't this already done then?
+ local features = constructors.checkedfeatures("afm",specification.features.normal)
+ specification.features.normal = features
+ constructors.hashinstance(specification,true) -- also weird here
+ --
+ specification = definers.resolve(specification) -- new, was forgotten
+ local cache_id = specification.hash
+ local tfmdata = containers.read(constructors.cache, cache_id) -- cache with features applied
+ if not tfmdata then
+ local rawdata = afm.load(afmname)
+ if rawdata and next(rawdata) then
+ addtables(rawdata)
+ adddimensions(rawdata)
+ tfmdata = copytotfm(rawdata)
+ if tfmdata and next(tfmdata) then
+ local shared = tfmdata.shared
+ if not shared then
+ shared = { }
+ tfmdata.shared = shared
+ end
+ shared.rawdata = rawdata
+ shared.dynamics = { }
+ tfmdata.changed = { }
+ shared.features = features
+ shared.processes = afm.setfeatures(tfmdata,features)
+ end
+ elseif trace_loading then
+ report_afm("no (valid) afm file found with name %a",afmname)
+ end
+ tfmdata = containers.write(constructors.cache,cache_id,tfmdata)
+ end
+ return tfmdata
+ end
+end
+
+--[[ldx--
+<p>As soon as we could intercept the <l n='tfm'/> reader, I implemented an
+<l n='afm'/> reader. Since traditional <l n='pdftex'/> could use <l n='opentype'/>
+fonts with <l n='afm'/> companions, the following method also could handle
+those cases, but now that we can handle <l n='opentype'/> directly we no longer
+need this features.</p>
+--ldx]]--
+
+local function read_from_afm(specification)
+ local tfmdata = afmtotfm(specification)
+ if tfmdata then
+ tfmdata.properties.name = specification.name
+ tfmdata.properties.id = specification.id
+ tfmdata = constructors.scale(tfmdata, specification)
+ local allfeatures = tfmdata.shared.features or specification.features.normal
+ constructors.applymanipulators("afm",tfmdata,allfeatures,trace_features,report_afm)
+ fonts.loggers.register(tfmdata,'afm',specification)
+ end
+ return tfmdata
+end
+
+--[[ldx--
+<p>We have the usual two modes and related features initializers and processors.</p>
+--ldx]]--
+
+registerafmfeature {
+ name = "mode",
+ description = "mode",
+ initializers = {
+ base = otf.modeinitializer,
+ node = otf.modeinitializer,
+ }
+}
+
+registerafmfeature {
+ name = "features",
+ description = "features",
+ default = true,
+ initializers = {
+ node = otf.nodemodeinitializer,
+ base = otf.basemodeinitializer,
+ },
+ processors = {
+ node = otf.featuresprocessor,
+ }
+}
+
+-- readers
+
+fonts.formats.afm = "type1"
+fonts.formats.pfb = "type1"
+
+local function check_afm(specification,fullname)
+ local foundname = findbinfile(fullname, 'afm') or "" -- just to be sure
+ if foundname == "" then
+ foundname = fonts.names.getfilename(fullname,"afm") or ""
+ end
+ if fullname and foundname == "" and afm.autoprefixed then
+ local encoding, shortname = match(fullname,"^(.-)%-(.*)$") -- context: encoding-name.*
+ if encoding and shortname and fonts.encodings.known[encoding] then
+ shortname = findbinfile(shortname,'afm') or "" -- just to be sure
+ if shortname ~= "" then
+ foundname = shortname
+ if trace_defining then
+ report_afm("stripping encoding prefix from filename %a",afmname)
+ end
+ end
+ end
+ end
+ if foundname ~= "" then
+ specification.filename = foundname
+ specification.format = "afm"
+ return read_from_afm(specification)
+ end
+end
+
+function readers.afm(specification,method)
+ local fullname = specification.filename or ""
+ local tfmdata = nil
+ if fullname == "" then
+ local forced = specification.forced or ""
+ if forced ~= "" then
+ tfmdata = check_afm(specification,specification.name .. "." .. forced)
+ end
+ if not tfmdata then
+ local check_tfm = readers.check_tfm
+ method = (check_tfm and (method or definers.method or "afm or tfm")) or "afm"
+ if method == "tfm" then
+ tfmdata = check_tfm(specification,specification.name)
+ elseif method == "afm" then
+ tfmdata = check_afm(specification,specification.name)
+ elseif method == "tfm or afm" then
+ tfmdata = check_tfm(specification,specification.name) or check_afm(specification,specification.name)
+ else -- method == "afm or tfm" or method == "" then
+ tfmdata = check_afm(specification,specification.name) or check_tfm(specification,specification.name)
+ end
+ end
+ else
+ tfmdata = check_afm(specification,fullname)
+ end
+ return tfmdata
+end
+
+function readers.pfb(specification,method) -- only called when forced
+ local original = specification.specification
+ if trace_defining then
+ report_afm("using afm reader for %a",original)
+ end
+ specification.forced = "afm"
+ local function swap(name)
+ local value = specification[swap]
+ if value then
+ specification[swap] = gsub("%.pfb",".afm",1)
+ end
+ end
+ swap("filename")
+ swap("fullname")
+ swap("forcedname")
+ swap("specification")
+ return readers.afm(specification,method)
+end
+
+-- now we register them
+
+registerafmenhancer("unify names", enhance_unify_names)
+registerafmenhancer("add ligatures", enhance_add_ligatures)
+registerafmenhancer("add extra kerns", enhance_add_extra_kerns)
+registerafmenhancer("normalize features", enhance_normalize_features)
+registerafmenhancer("check extra features", otfenhancers.enhance)
+registerafmenhancer("fix names", enhance_fix_names)
diff --git a/tex/context/base/mkxl/font-otl.lmt b/tex/context/base/mkxl/font-otl.lmt
new file mode 100644
index 000000000..f493bc327
--- /dev/null
+++ b/tex/context/base/mkxl/font-otl.lmt
@@ -0,0 +1,889 @@
+if not modules then modules = { } end modules ['font-otl'] = {
+ 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",
+}
+
+-- After some experimenting with an alternative loader (one that is needed for
+-- getting outlines in mp) I decided not to be compatible with the old (built-in)
+-- one. The approach used in font-otn is as follows: we load the font in a compact
+-- format but still very compatible with the ff data structures. From there we
+-- create hashes to access the data efficiently. The implementation of feature
+-- processing is mostly based on looking at the data as organized in the glyphs and
+-- lookups as well as the specification. Keeping the lookup data in the glyphs is
+-- very instructive and handy for tracing. On the other hand hashing is what brings
+-- speed. So, the in the new approach (the old one will stay around too) we no
+-- longer keep data in the glyphs which saves us a (what in retrospect looks a bit
+-- like) a reconstruction step. It also means that the data format of the cached
+-- files changes. What method is used depends on that format. There is no fundamental
+-- change in processing, and not even in data organation. Most has to do with
+-- loading and storage.
+
+-- todo: less tounicodes
+
+local lower = string.lower
+local type, next, tonumber, tostring, unpack = type, next, tonumber, tostring, unpack
+local abs = math.abs
+local derivetable, sortedhash = table.derive, table.sortedhash
+local formatters = string.formatters
+
+local setmetatableindex = table.setmetatableindex
+local allocate = utilities.storage.allocate
+local registertracker = trackers.register
+local registerdirective = directives.register
+local starttiming = statistics.starttiming
+local stoptiming = statistics.stoptiming
+local elapsedtime = statistics.elapsedtime
+local findbinfile = resolvers.findbinfile
+
+----- trace_private = false registertracker("otf.private", function(v) trace_private = v end)
+----- trace_subfonts = false registertracker("otf.subfonts", function(v) trace_subfonts = v end)
+local trace_loading = false registertracker("otf.loading", function(v) trace_loading = v end)
+local trace_features = false registertracker("otf.features", function(v) trace_features = v end)
+----- trace_dynamics = false registertracker("otf.dynamics", function(v) trace_dynamics = v end)
+----- trace_sequences = false registertracker("otf.sequences", function(v) trace_sequences = v end)
+----- trace_markwidth = false registertracker("otf.markwidth", function(v) trace_markwidth = v end)
+local trace_defining = false registertracker("fonts.defining", function(v) trace_defining = v end)
+
+local report_otf = logs.reporter("fonts","otf loading")
+
+local fonts = fonts
+local otf = fonts.handlers.otf
+
+otf.version = 3.119 -- beware: also sync font-mis.lua and in mtx-fonts
+otf.cache = containers.define("fonts", "otl", otf.version, true)
+otf.svgcache = containers.define("fonts", "svg", otf.version, true)
+otf.pngcache = containers.define("fonts", "png", otf.version, true)
+otf.pdfcache = containers.define("fonts", "pdf", otf.version, true)
+otf.mpscache = containers.define("fonts", "mps", otf.version, true)
+
+otf.svgenabled = false
+otf.pngenabled = false
+
+local otfreaders = otf.readers
+
+local hashes = fonts.hashes
+local definers = fonts.definers
+local readers = fonts.readers
+local constructors = fonts.constructors
+
+local otffeatures = constructors.features.otf
+local registerotffeature = otffeatures.register
+
+local otfenhancers = constructors.enhancers.otf
+local registerotfenhancer = otfenhancers.register
+
+local forceload = false
+local cleanup = 0 -- mk: 0=885M 1=765M 2=735M (regular run 730M)
+local syncspace = true
+local forcenotdef = false
+
+local privateoffset = fonts.constructors and fonts.constructors.privateoffset or 0xF0000 -- 0x10FFFF
+
+local applyruntimefixes = fonts.treatments and fonts.treatments.applyfixes
+
+local wildcard = "*"
+local default = "dflt"
+
+local formats = fonts.formats
+
+formats.otf = "opentype"
+formats.ttf = "truetype"
+formats.ttc = "truetype"
+
+registerdirective("fonts.otf.loader.cleanup", function(v) cleanup = tonumber(v) or (v and 1) or 0 end)
+registerdirective("fonts.otf.loader.force", function(v) forceload = v end)
+registerdirective("fonts.otf.loader.syncspace", function(v) syncspace = v end)
+registerdirective("fonts.otf.loader.forcenotdef", function(v) forcenotdef = v end)
+
+-- otfenhancers.patch("before","migrate metadata","cambria",function() end)
+
+registerotfenhancer("check extra features", function() end) -- placeholder
+
+-- Kai has memory problems on osx so here is an experiment (I only tested on windows as
+-- my test mac is old and gets no updates and is therefore rather useless.):
+
+local checkmemory = utilities.lua and utilities.lua.checkmemory
+local threshold = 100 -- MB
+local tracememory = false
+
+registertracker("fonts.otf.loader.memory",function(v) tracememory = v end)
+
+if not checkmemory then -- we need a generic plug (this code might move):
+
+ local collectgarbage = collectgarbage
+
+ checkmemory = function(previous,threshold) -- threshold in MB
+ local current = collectgarbage("count")
+ if previous then
+ local checked = (threshold or 64)*1024
+ if current - previous > checked then
+ collectgarbage("collect")
+ current = collectgarbage("count")
+ end
+ end
+ return current
+ end
+
+end
+
+function otf.load(filename,sub,instance)
+ local base = file.basename(file.removesuffix(filename))
+ local name = file.removesuffix(base) -- already no suffix
+ local attr = lfs.attributes(filename)
+ local size = attr and attr.size or 0
+ local time = attr and attr.modification or 0
+ -- sub can be number of string
+ if sub == "" then
+ sub = false
+ end
+ local hash = name
+ if sub then
+ hash = hash .. "-" .. sub
+ end
+ if instance then
+ hash = hash .. "-" .. instance
+ end
+ hash = containers.cleanname(hash)
+ local data = containers.read(otf.cache,hash)
+ local reload = not data or data.size ~= size or data.time ~= time or data.tableversion ~= otfreaders.tableversion
+ if forceload then
+ report_otf("forced reload of %a due to hard coded flag",filename)
+ reload = true
+ end
+ if reload then
+ report_otf("loading %a, hash %a",filename,hash)
+ --
+ starttiming(otfreaders,true)
+ data = otfreaders.loadfont(filename,sub or 1,instance) -- we can pass the number instead (if it comes from a name search)
+ if data then
+ -- todo: make this a plugin
+ local used = checkmemory()
+ local resources = data.resources
+ local svgshapes = resources.svgshapes
+ local pngshapes = resources.pngshapes
+ if cleanup == 0 then
+ checkmemory(used,threshold,tracememory)
+ end
+ if svgshapes then
+ resources.svgshapes = nil
+ if otf.svgenabled then
+ local timestamp = os.date()
+ -- work in progress ... a bit boring to do
+ containers.write(otf.svgcache,hash, {
+ svgshapes = svgshapes,
+ timestamp = timestamp,
+ })
+ data.properties.svg = {
+ hash = hash,
+ timestamp = timestamp,
+ }
+ end
+ if cleanup > 1 then
+ collectgarbage("collect")
+ else
+ checkmemory(used,threshold,tracememory)
+ end
+ end
+ if pngshapes then
+ resources.pngshapes = nil
+ if otf.pngenabled then
+ local timestamp = os.date()
+ -- work in progress ... a bit boring to do
+ containers.write(otf.pngcache,hash, {
+ pngshapes = pngshapes,
+ timestamp = timestamp,
+ })
+ data.properties.png = {
+ hash = hash,
+ timestamp = timestamp,
+ }
+ end
+ if cleanup > 1 then
+ collectgarbage("collect")
+ else
+ checkmemory(used,threshold,tracememory)
+ end
+ end
+ --
+ otfreaders.compact(data)
+ if cleanup == 0 then
+ checkmemory(used,threshold,tracememory)
+ end
+ otfreaders.rehash(data,"unicodes")
+ otfreaders.addunicodetable(data)
+ otfreaders.extend(data)
+ if cleanup == 0 then
+ checkmemory(used,threshold,tracememory)
+ end
+ if context then
+ otfreaders.condense(data)
+ end
+ otfreaders.pack(data)
+ report_otf("loading done")
+ report_otf("saving %a in cache",filename)
+ data = containers.write(otf.cache, hash, data)
+ if cleanup > 1 then
+ collectgarbage("collect")
+ else
+ checkmemory(used,threshold,tracememory)
+ end
+ stoptiming(otfreaders)
+ if elapsedtime then
+ report_otf("loading, optimizing, packing and caching time %s", elapsedtime(otfreaders))
+ end
+ if cleanup > 3 then
+ collectgarbage("collect")
+ else
+ checkmemory(used,threshold,tracememory)
+ end
+ data = containers.read(otf.cache,hash) -- this frees the old table and load the sparse one
+ if cleanup > 2 then
+ collectgarbage("collect")
+ else
+ checkmemory(used,threshold,tracememory)
+ end
+ else
+ stoptiming(otfreaders)
+ data = nil
+ report_otf("loading failed due to read error")
+ end
+ end
+ if data then
+ if trace_defining then
+ report_otf("loading from cache using hash %a",hash)
+ end
+ --
+ otfreaders.unpack(data)
+ otfreaders.expand(data) -- inline tables
+ otfreaders.addunicodetable(data) -- only when not done yet
+ --
+ otfenhancers.apply(data,filename,data) -- in context one can also use treatments
+ --
+ -- constructors.addcoreunicodes(data.resources.unicodes) -- still needed ?
+ --
+ if applyruntimefixes then
+ applyruntimefixes(filename,data) -- e.g. see treatments.lfg
+ end
+ --
+ data.metadata.math = data.resources.mathconstants
+ --
+ -- delayed tables (experiment)
+ --
+ local classes = data.resources.classes
+ if not classes then
+ local descriptions = data.descriptions
+ classes = setmetatableindex(function(t,k)
+ local d = descriptions[k]
+ local v = (d and d.class or "base") or false
+ t[k] = v
+ return v
+ end)
+ data.resources.classes = classes
+ end
+ --
+ end
+
+ return data
+end
+
+-- modes: node, base, none
+
+function otf.setfeatures(tfmdata,features)
+ local okay = constructors.initializefeatures("otf",tfmdata,features,trace_features,report_otf)
+ if okay then
+ return constructors.collectprocessors("otf",tfmdata,features,trace_features,report_otf)
+ else
+ return { } -- will become false
+ end
+end
+
+-- the first version made a top/mid/not extensible table, now we just
+-- pass on the variants data and deal with it in the tfm scaler (there
+-- is no longer an extensible table anyway)
+--
+-- we cannot share descriptions as virtual fonts might extend them (ok,
+-- we could use a cache with a hash
+--
+-- we already assign an empty table to characters as we can add for
+-- instance protruding info and loop over characters; one is not supposed
+-- to change descriptions and if one does so one should make a copy!
+
+local function copytotfm(data,cache_id)
+ if data then
+ local metadata = data.metadata
+ local properties = derivetable(data.properties)
+ local descriptions = derivetable(data.descriptions)
+ local goodies = derivetable(data.goodies)
+ local characters = { } -- newtable if we knwo how many
+ local parameters = { }
+ local mathparameters = { }
+ --
+ local resources = data.resources
+ local unicodes = resources.unicodes
+ local spaceunits = 500
+ local spacer = "space"
+ local designsize = metadata.designsize or 100
+ local minsize = metadata.minsize or designsize
+ local maxsize = metadata.maxsize or designsize
+ local mathspecs = metadata.math
+ --
+ if designsize == 0 then
+ designsize = 100
+ minsize = 100
+ maxsize = 100
+ end
+ if mathspecs then
+ for name, value in next, mathspecs do
+ mathparameters[name] = value
+ end
+ end
+ for unicode in next, data.descriptions do -- use parent table
+ characters[unicode] = { }
+ end
+ if mathspecs then
+ for unicode, character in next, characters do
+ local d = descriptions[unicode] -- we could use parent table here
+ local m = d.math
+ if m then
+ -- watch out: luatex uses hvariants for the parts
+ --
+ local italic = m.italic
+ local vitalic = m.vitalic
+ --
+ local variants = m.hvariants
+ local parts = m.hparts
+ if variants then
+ local c = character
+ for i=1,#variants do
+ -- local un = variants[i].glyph
+ local un = variants[i]
+ c.next = un
+ c = characters[un]
+ end -- c is now last in chain
+ c.hvariants = parts
+ elseif parts then
+ character.hvariants = parts
+ italic = m.hitalic
+ end
+ --
+ local variants = m.vvariants
+ local parts = m.vparts
+ if variants then
+ local c = character
+ for i=1,#variants do
+ -- local un = variants[i].glyph
+ local un = variants[i]
+ c.next = un
+ c = characters[un]
+ end -- c is now last in chain
+ c.vvariants = parts
+ elseif parts then
+ character.vvariants = parts
+ end
+ --
+ if italic and italic ~= 0 then
+ character.italic = italic
+ end
+ --
+ if vitalic and vitalic ~= 0 then
+ character.vitalic = vitalic
+ end
+ --
+ local accent = m.accent -- taccent?
+ if accent then
+ character.accent = accent
+ end
+ --
+ local kerns = m.kerns
+ if kerns then
+ character.mathkerns = kerns
+ end
+ end
+ end
+ end
+ -- we need a runtime lookup because of running from cdrom or zip, brrr (shouldn't
+ -- we use the basename then?)
+ local filename = constructors.checkedfilename(resources)
+ local fontname = metadata.fontname
+ local fullname = metadata.fullname or fontname
+ local psname = fontname or fullname
+ local subfont = metadata.subfontindex
+ local units = metadata.units or 1000
+ --
+ if units == 0 then -- catch bugs in fonts
+ units = 1000 -- maybe 2000 when ttf
+ metadata.units = 1000
+ report_otf("changing %a units to %a",0,units)
+ end
+ --
+ local monospaced = metadata.monospaced
+ local charwidth = metadata.averagewidth -- or unset
+ local charxheight = metadata.xheight -- or unset
+ local italicangle = metadata.italicangle
+ local hasitalics = metadata.hasitalics
+ properties.monospaced = monospaced
+ properties.hasitalics = hasitalics
+ parameters.italicangle = italicangle
+ parameters.charwidth = charwidth
+ parameters.charxheight = charxheight
+ --
+ local space = 0x0020
+ local emdash = 0x2014
+ if monospaced then
+ if descriptions[space] then
+ spaceunits, spacer = descriptions[space].width, "space"
+ end
+ if not spaceunits and descriptions[emdash] then
+ spaceunits, spacer = descriptions[emdash].width, "emdash"
+ end
+ if not spaceunits and charwidth then
+ spaceunits, spacer = charwidth, "charwidth"
+ end
+ else
+ if descriptions[space] then
+ spaceunits, spacer = descriptions[space].width, "space"
+ end
+ if not spaceunits and descriptions[emdash] then
+ spaceunits, spacer = descriptions[emdash].width/2, "emdash/2"
+ end
+ if not spaceunits and charwidth then
+ spaceunits, spacer = charwidth, "charwidth"
+ end
+ end
+ spaceunits = tonumber(spaceunits) or units/2
+ --
+ parameters.slant = 0
+ parameters.space = spaceunits -- 3.333 (cmr10)
+ parameters.spacestretch = 1*units/2 -- 500 -- 1.666 (cmr10)
+ parameters.spaceshrink = 1*units/3 -- 333 -- 1.111 (cmr10)
+ parameters.xheight = 2*units/5 -- 400
+ parameters.quad = units -- 1000
+ if spaceunits < 2*units/5 then
+ -- todo: warning
+ end
+ if italicangle and italicangle ~= 0 then
+ parameters.italicangle = italicangle
+ parameters.italicfactor = math.cos(math.rad(90+italicangle))
+ parameters.slant = - math.tan(italicangle*math.pi/180)
+ end
+ if monospaced then
+ parameters.spacestretch = 0
+ parameters.spaceshrink = 0
+ elseif syncspace then --
+ parameters.spacestretch = spaceunits/2
+ parameters.spaceshrink = spaceunits/3
+ end
+ parameters.extraspace = parameters.spaceshrink -- 1.111 (cmr10)
+ if charxheight then
+ parameters.xheight = charxheight
+ else
+ local x = 0x0078
+ if x then
+ local x = descriptions[x]
+ if x then
+ parameters.xheight = x.height
+ end
+ end
+ end
+ --
+ parameters.designsize = (designsize/10)*65536
+ parameters.minsize = (minsize /10)*65536
+ parameters.maxsize = (maxsize /10)*65536
+ parameters.ascender = abs(metadata.ascender or 0)
+ parameters.descender = abs(metadata.descender or 0)
+ parameters.units = units
+ parameters.vheight = metadata.defaultvheight
+ --
+ properties.space = spacer
+ properties.format = data.format or formats.otf
+ properties.filename = filename
+ properties.fontname = fontname
+ properties.fullname = fullname
+ properties.psname = psname
+ properties.name = filename or fullname
+ properties.subfont = subfont
+ --
+if not CONTEXTLMTXMODE or CONTEXTLMTXMODE == 0 then
+ --
+ properties.encodingbytes = 2
+elseif CONTEXTLMTXMODE then
+ local duplicates = resources and resources.duplicates
+ if duplicates then
+ local maxindex = data.nofglyphs or metadata.nofglyphs
+ if maxindex then
+ for u, d in sortedhash(duplicates) do
+ local du = descriptions[u]
+ if du then
+ for uu in sortedhash(d) do
+ maxindex = maxindex + 1
+ descriptions[uu].dupindex = du.index
+ descriptions[uu].index = maxindex
+ end
+ else
+ -- report_otf("no %U in font %a, duplicates ignored",u,filename)
+ end
+ end
+ end
+ end
+ --
+end
+ --
+ -- properties.name = specification.name
+ -- properties.sub = specification.sub
+ --
+ properties.private = properties.private or data.private or privateoffset
+ --
+ return {
+ characters = characters,
+ descriptions = descriptions,
+ parameters = parameters,
+ mathparameters = mathparameters,
+ resources = resources,
+ properties = properties,
+ goodies = goodies,
+ }
+ end
+end
+
+-- These woff files are a kind of joke in a tex environment because one can simply convert
+-- them to ttf/otf and use them as such (after all, we cache them too). The successor format
+-- woff2 is more complex so there we can as well call an external converter which in the end
+-- makes this code kind of obsolete before it's even used. Although ... it might become a
+-- more general conversion plug in.
+
+local converters = {
+ woff = {
+ cachename = "webfonts",
+ action = otf.readers.woff2otf,
+ }
+}
+
+-- We can get differences between daylight saving etc ... but it makes no sense to
+-- mess with trickery .. so be it when you use a different binary.
+
+local function checkconversion(specification)
+ local filename = specification.filename
+ local converter = converters[lower(file.suffix(filename))]
+ if converter then
+ local base = file.basename(filename)
+ local name = file.removesuffix(base)
+ local attr = lfs.attributes(filename)
+ local size = attr and attr.size or 0
+ local time = attr and attr.modification or 0
+ if size > 0 then
+ local cleanname = containers.cleanname(name)
+ local cachename = caches.setfirstwritablefile(cleanname,converter.cachename)
+ if not io.exists(cachename) or (time ~= lfs.attributes(cachename).modification) then
+ report_otf("caching font %a in %a",filename,cachename)
+ converter.action(filename,cachename) -- todo infoonly
+ lfs.touch(cachename,time,time)
+ end
+ specification.filename = cachename
+ end
+ end
+end
+
+local function otftotfm(specification)
+ local cache_id = specification.hash
+ local tfmdata = containers.read(constructors.cache,cache_id)
+ if not tfmdata then
+
+ checkconversion(specification) -- for the moment here
+
+ local name = specification.name
+ local sub = specification.sub
+ local subindex = specification.subindex
+ local filename = specification.filename
+ local features = specification.features.normal
+ local instance = specification.instance or (features and features.axis)
+ local rawdata = otf.load(filename,sub,instance)
+ if rawdata and next(rawdata) then
+ local descriptions = rawdata.descriptions
+ rawdata.lookuphash = { } -- to be done
+ tfmdata = copytotfm(rawdata,cache_id)
+ if tfmdata and next(tfmdata) then
+ -- at this moment no characters are assigned yet, only empty slots
+ local features = constructors.checkedfeatures("otf",features)
+ local shared = tfmdata.shared
+ if not shared then
+ shared = { }
+ tfmdata.shared = shared
+ end
+ shared.rawdata = rawdata
+ -- shared.features = features -- default
+ shared.dynamics = { }
+ -- shared.processes = { }
+ tfmdata.changed = { }
+ shared.features = features
+ shared.processes = otf.setfeatures(tfmdata,features)
+ end
+ end
+ containers.write(constructors.cache,cache_id,tfmdata)
+ end
+ return tfmdata
+end
+
+local function read_from_otf(specification)
+ local tfmdata = otftotfm(specification)
+ if tfmdata then
+ -- this late ? .. needs checking
+ tfmdata.properties.name = specification.name
+ tfmdata.properties.sub = specification.sub
+ tfmdata.properties.id = specification.id
+ --
+ tfmdata = constructors.scale(tfmdata,specification)
+ local allfeatures = tfmdata.shared.features or specification.features.normal
+ constructors.applymanipulators("otf",tfmdata,allfeatures,trace_features,report_otf)
+ constructors.setname(tfmdata,specification) -- only otf?
+ fonts.loggers.register(tfmdata,file.suffix(specification.filename),specification)
+ end
+ return tfmdata
+end
+
+local function checkmathsize(tfmdata,mathsize)
+ local mathdata = tfmdata.shared.rawdata.metadata.math
+ local mathsize = tonumber(mathsize)
+ if mathdata then -- we cannot use mathparameters as luatex will complain
+ local parameters = tfmdata.parameters
+ parameters.scriptpercentage = mathdata.ScriptPercentScaleDown
+ parameters.scriptscriptpercentage = mathdata.ScriptScriptPercentScaleDown
+ parameters.mathsize = mathsize -- only when a number !
+ end
+end
+
+registerotffeature {
+ name = "mathsize",
+ description = "apply mathsize specified in the font",
+ initializers = {
+ base = checkmathsize,
+ node = checkmathsize,
+ }
+}
+
+-- readers
+
+function otf.collectlookups(rawdata,kind,script,language)
+ if not kind then
+ return
+ end
+ if not script then
+ script = default
+ end
+ if not language then
+ language = default
+ end
+ local lookupcache = rawdata.lookupcache
+ if not lookupcache then
+ lookupcache = { }
+ rawdata.lookupcache = lookupcache
+ end
+ local kindlookup = lookupcache[kind]
+ if not kindlookup then
+ kindlookup = { }
+ lookupcache[kind] = kindlookup
+ end
+ local scriptlookup = kindlookup[script]
+ if not scriptlookup then
+ scriptlookup = { }
+ kindlookup[script] = scriptlookup
+ end
+ local languagelookup = scriptlookup[language]
+ if not languagelookup then
+ local sequences = rawdata.resources.sequences
+ local featuremap = { }
+ local featurelist = { }
+ if sequences then
+ for s=1,#sequences do
+ local sequence = sequences[s]
+ local features = sequence.features
+ if features then
+ features = features[kind]
+ if features then
+ -- features = features[script] or features[default] or features[wildcard]
+ features = features[script] or features[wildcard]
+ if features then
+ -- features = features[language] or features[default] or features[wildcard]
+ features = features[language] or features[wildcard]
+ if features then
+ if not featuremap[sequence] then
+ featuremap[sequence] = true
+ featurelist[#featurelist+1] = sequence
+ end
+ end
+ end
+ end
+ end
+ end
+ if #featurelist == 0 then
+ featuremap, featurelist = false, false
+ end
+ else
+ featuremap, featurelist = false, false
+ end
+ languagelookup = { featuremap, featurelist }
+ scriptlookup[language] = languagelookup
+ end
+ return unpack(languagelookup)
+end
+
+-- moved from font-oth.lua, todo: also afm
+
+local function getgsub(tfmdata,k,kind,value)
+ local shared = tfmdata.shared
+ local rawdata = shared and shared.rawdata
+ if rawdata then
+ local sequences = rawdata.resources.sequences
+ if sequences then
+ local properties = tfmdata.properties
+ local validlookups, lookuplist = otf.collectlookups(rawdata,kind,properties.script,properties.language)
+ if validlookups then
+ -- local choice = tonumber(value) or 1 -- no random here (yet)
+ for i=1,#lookuplist do
+ local lookup = lookuplist[i]
+ local steps = lookup.steps
+ local nofsteps = lookup.nofsteps
+ for i=1,nofsteps do
+ local coverage = steps[i].coverage
+ if coverage then
+ local found = coverage[k]
+ if found then
+ return found, lookup.type
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+otf.getgsub = getgsub -- returns value, gsub_kind
+
+function otf.getsubstitution(tfmdata,k,kind,value)
+ local found, kind = getgsub(tfmdata,k,kind,value)
+ if not found then
+ --
+ elseif kind == "gsub_single" then
+ return found
+ elseif kind == "gsub_alternate" then
+ local choice = tonumber(value) or 1 -- no random here (yet)
+ return found[choice] or found[1] or k
+ end
+ return k
+end
+
+otf.getalternate = otf.getsubstitution
+
+function otf.getmultiple(tfmdata,k,kind)
+ local found, kind = getgsub(tfmdata,k,kind)
+ if found and kind == "gsub_multiple" then
+ return found
+ end
+ return { k }
+end
+
+function otf.getkern(tfmdata,left,right,kind)
+ local kerns = getgsub(tfmdata,left,kind or "kern",true) -- for now we use getsub
+ if kerns then
+ local found = kerns[right]
+ local kind = type(found)
+ if kind == "table" then
+ found = found[1][3] -- can be more clever
+ elseif kind ~= "number" then
+ found = false
+ end
+ if found then
+ return found * tfmdata.parameters.factor
+ end
+ end
+ return 0
+end
+
+local function check_otf(forced,specification,suffix)
+ local name = specification.name
+ if forced then
+ name = specification.forcedname -- messy
+ end
+ local fullname = findbinfile(name,suffix) or ""
+ if fullname == "" then
+ fullname = fonts.names.getfilename(name,suffix) or ""
+ end
+ if fullname ~= "" and not fonts.names.ignoredfile(fullname) then
+ specification.filename = fullname
+ return read_from_otf(specification)
+ end
+end
+
+local function opentypereader(specification,suffix)
+ local forced = specification.forced or ""
+ if formats[forced] then
+ return check_otf(true,specification,forced)
+ else
+ return check_otf(false,specification,suffix)
+ end
+end
+
+readers.opentype = opentypereader -- kind of useless and obsolete
+
+function readers.otf(specification) return opentypereader(specification,"otf") end
+function readers.ttf(specification) return opentypereader(specification,"ttf") end
+function readers.ttc(specification) return opentypereader(specification,"ttf") end
+
+function readers.woff(specification)
+ checkconversion(specification)
+ opentypereader(specification,"")
+end
+
+-- this will be overloaded
+
+function otf.scriptandlanguage(tfmdata,attr)
+ local properties = tfmdata.properties
+ return properties.script or "dflt", properties.language or "dflt"
+end
+
+-- a little bit of abstraction
+
+local function justset(coverage,unicode,replacement)
+ coverage[unicode] = replacement
+end
+
+otf.coverup = {
+ stepkey = "steps",
+ actions = {
+ chainsubstitution = justset,
+ chainposition = justset,
+ substitution = justset,
+ alternate = justset,
+ multiple = justset,
+ kern = justset,
+ pair = justset,
+ single = justset,
+ ligature = function(coverage,unicode,ligature)
+ local first = ligature[1]
+ local tree = coverage[first]
+ if not tree then
+ tree = { }
+ coverage[first] = tree
+ end
+ for i=2,#ligature do
+ local l = ligature[i]
+ local t = tree[l]
+ if not t then
+ t = { }
+ tree[l] = t
+ end
+ tree = t
+ end
+ tree.ligature = unicode
+ end,
+ },
+ register = function(coverage,featuretype,format)
+ return {
+ format = format,
+ coverage = coverage,
+ }
+ end
+}
diff --git a/tex/context/base/mkxl/font-tfm.lmt b/tex/context/base/mkxl/font-tfm.lmt
new file mode 100644
index 000000000..dcb76ba80
--- /dev/null
+++ b/tex/context/base/mkxl/font-tfm.lmt
@@ -0,0 +1,666 @@
+if not modules then modules = { } end modules ['font-tfm'] = {
+ 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"
+}
+
+if not context then return end -- use luatex-fonts-tfm.lua instead
+
+local next, type = next, type
+local match, format = string.match, string.format
+local concat, sortedhash = table.concat, table.sortedhash
+local idiv = number.idiv
+
+local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end)
+local trace_features = false trackers.register("tfm.features", function(v) trace_features = v end)
+
+local report_defining = logs.reporter("fonts","defining")
+local report_tfm = logs.reporter("fonts","tfm loading")
+
+local findbinfile = resolvers.findbinfile
+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
+
+local tfm = constructors.handlers.tfm
+tfm.version = 1.000
+tfm.maxnestingdepth = 5
+tfm.maxnestingsize = 65536*1024
+
+local otf = fonts.handlers.otf
+local otfenhancers = otf.enhancers
+
+local tfmfeatures = constructors.features.tfm
+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
+fonts.formats.ofm = "type1" -- we need to have at least a value here
+
+--[[ldx--
+<p>The next function encapsulates the standard <l n='tfm'/> loader as
+supplied by <l n='luatex'/>.</p>
+--ldx]]--
+
+-- this might change: not scaling and then apply features and do scaling in the
+-- usual way with dummy descriptions but on the other hand .. we no longer use
+-- tfm so why bother
+
+-- ofm directive blocks local path search unless set; btw, in context we
+-- don't support ofm files anyway as this format is obsolete
+
+-- we need to deal with nested virtual fonts, but because we load in the
+-- frontend we also need to make sure we don't nest too deep (esp when sizes
+-- get large)
+--
+-- (VTITLE Example of a recursion)
+-- (MAPFONT D 0 (FONTNAME recurse)(FONTAT D 2))
+-- (CHARACTER C A (CHARWD D 1)(CHARHT D 1)(MAP (SETRULE D 1 D 1)))
+-- (CHARACTER C B (CHARWD D 2)(CHARHT D 2)(MAP (SETCHAR C A)))
+-- (CHARACTER C C (CHARWD D 4)(CHARHT D 4)(MAP (SETCHAR C B)))
+--
+-- we added the same checks as below to the luatex engine
+
+function tfm.setfeatures(tfmdata,features)
+ local okay = constructors.initializefeatures("tfm",tfmdata,features,trace_features,report_tfm)
+ if okay then
+ return constructors.collectprocessors("tfm",tfmdata,features,trace_features,report_tfm)
+ else
+ return { } -- will become false
+ end
+end
+
+local depth = { } -- table.setmetatableindex("number")
+
+-- Normally we just load the tfm data and go on. However there was some demand for
+-- loading good old tfm /pfb files where afm files were lacking and even enc files
+-- of dubious quality so we now support loading such (often messy) setups too.
+--
+-- Because such fonts also use (ugly) tweaks achieve some purpose (like swapping
+-- accents) we need to delay the unicoding actions till after the features have been
+-- applied.
+--
+-- It must be noted that in ConTeXt we don't expect this to be used at all. Here is
+-- example:
+--
+-- tfm metrics + pfb vector for index + pfb file for shapes
+--
+-- \font\foo=file:csr10.tfm:reencode=auto;mode=node;liga=yes;kern=yes
+--
+-- tfm metrics + pfb vector for index + enc file for tfm mapping + pfb file for shapes
+--
+-- \font\foo=file:csr10.tfm:reencode=csr.enc;mode=node;liga=yes;kern=yes
+--
+-- tfm metrics + enc file for mapping to tfm + bitmaps shapes
+--
+-- \font\foo=file:csr10.tfm:reencode=csr.enc;bitmap=yes;mode=node;liga=yes;kern=yes
+--
+-- One can add features:
+--
+-- fonts.handlers.otf.addfeature {
+-- name = "czechdqcheat",
+-- type = "substitution",
+-- data = {
+-- quotedblright = "csquotedblright",
+-- },
+-- }
+--
+-- So "czechdqcheat=yes" is then a valid feature. And yes, it's a cheat.
+
+local loadtfmvf = tfm.readers.loadtfmvf
+
+local function read_from_tfm(specification)
+ local filename = specification.filename
+ local size = specification.size
+ depth[filename] = (depth[filename] or 0) + 1
+ if trace_defining then
+ report_defining("loading tfm file %a at size %s",filename,size)
+ end
+ local tfmdata = loadtfmvf(filename,size)
+ if tfmdata then
+
+ local features = specification.features and specification.features.normal or { }
+ local features = constructors.checkedfeatures("tfm",features)
+ specification.features.normal = features
+
+ -- If reencode returns a new table, we assume that we're doing something
+ -- special. An 'auto' reencode picks up its vector from the pfb file.
+
+ local getmapentry = fonts.mappings.getentry
+
+ if getmapentry and not features.reencode then
+ -- This can happen multiple times but not that often so we don't
+ -- optimize this.
+ local encoding, pfbfile, encfile = getmapentry(filename)
+ if encoding and pfbfile then
+ features.reencode = encfile
+ features.pfbfile = pfbfile
+ end
+ end
+ local newtfmdata = (depth[filename] == 1) and tfm.reencode(tfmdata,specification)
+ if newtfmdata then
+ tfmdata = newtfmdata
+ end
+
+ local resources = tfmdata.resources or { }
+ local properties = tfmdata.properties or { }
+ local parameters = tfmdata.parameters or { }
+ local shared = tfmdata.shared or { }
+ --
+ shared.features = features
+ shared.resources = resources
+ --
+ properties.id = specification.id
+ properties.name = tfmdata.name -- todo: fallback
+ properties.fontname = tfmdata.fontname -- todo: fallback
+ properties.psname = tfmdata.psname -- todo: fallback
+ properties.fullname = tfmdata.fullname -- todo: fallback
+ properties.filename = specification.filename -- todo: fallback
+ properties.format = tfmdata.format or fonts.formats.tfm -- better than nothing
+ properties.usedbitmap = tfmdata.usedbitmap
+ --
+ if getmapentry and newtfmdata then
+ properties.filename = features.pfbfile
+ end
+ --
+ tfmdata.properties = properties
+ tfmdata.resources = resources
+ tfmdata.parameters = parameters
+ tfmdata.shared = shared
+ --
+ shared.rawdata = { resources = resources }
+ shared.features = features
+ --
+ -- The next branch is only entered when we have a proper encoded file i.e.
+ -- unicodes and such. It really nakes no sense to do feature juggling when
+ -- we have no names and unicodes.
+ --
+ if newtfmdata then
+ --
+ -- Some opentype processing assumes these to be present:
+ --
+ if not resources.marks then
+ resources.marks = { }
+ end
+ if not resources.sequences then
+ resources.sequences = { }
+ end
+ if not resources.features then
+ resources.features = {
+ gsub = { },
+ gpos = { },
+ }
+ end
+ if not tfmdata.changed then
+ tfmdata.changed = { }
+ end
+ if not tfmdata.descriptions then
+ tfmdata.descriptions = tfmdata.characters
+ end
+ --
+ -- It might be handy to have this:
+ --
+ otf.readers.addunicodetable(tfmdata)
+ --
+ -- We make a pseudo opentype font, e.g. kerns and ligatures etc:
+ --
+ tfmenhancers.apply(tfmdata,filename)
+ --
+ -- Now user stuff can kick in.
+ --
+ constructors.applymanipulators("tfm",tfmdata,features,trace_features,report_tfm)
+ --
+ -- As that can also mess with names and such, we are now ready for finalizing
+ -- the unicode information. This is a different order that for instance type one
+ -- (afm) files. First we try to deduce unicodes from already present information.
+ --
+ otf.readers.unifymissing(tfmdata)
+ --
+ -- Next we fill in the gaps, based on names from teh agl. Probably not much will
+ -- happen here.
+ --
+ fonts.mappings.addtounicode(tfmdata,filename)
+ --
+ -- The tounicode data is passed to the backend that constructs the vectors for us.
+ --
+if not CONTEXTLMTXMODE or CONTEXTLMTXMODE == 0 then
+ tfmdata.tounicode = 1
+end
+ local tounicode = fonts.mappings.tounicode
+ for unicode, v in next, tfmdata.characters do
+ local u = v.unicode
+ if u then
+ v.tounicode = tounicode(u)
+ end
+ end
+ --
+ -- However, when we use a bitmap font those vectors can't be constructed because
+ -- that information is not carried with those fonts (there is no name info, nor
+ -- proper index info, nor unicodes at that end). So, we provide it ourselves.
+ --
+ if tfmdata.usedbitmap then
+ tfm.addtounicode(tfmdata)
+ end
+ end
+ --
+ shared.processes = next(features) and tfm.setfeatures(tfmdata,features) or nil
+ --
+ if size < 0 then
+ size = idiv(65536 * -size,100)
+ end
+
+ parameters.factor = 1 -- already scaled
+ parameters.units = 1000 -- just in case
+ parameters.size = size
+ parameters.slant = parameters.slant or parameters[1] or 0
+ parameters.space = parameters.space or parameters[2] or 0
+ parameters.spacestretch = parameters.spacestretch or parameters[3] or 0
+ parameters.spaceshrink = parameters.spaceshrink or parameters[4] or 0
+ parameters.xheight = parameters.xheight or parameters[5] or 0
+ parameters.quad = parameters.quad or parameters[6] or 0
+ parameters.extraspace = parameters.extraspace or parameters[7] or 0
+ --
+ constructors.enhanceparameters(parameters) -- official copies for us
+ --
+ properties.private = properties.private or tfmdata.private or privateoffset
+ --
+ if newtfmdata then
+ --
+ -- We do nothing as we assume flat tfm files. It would become real messy
+ -- otherwise and I don't have something for testing on my system anyway.
+ --
+ else
+ -- already loaded
+ local fonts = tfmdata.fonts
+ if fonts then
+ for i=1,#fonts do
+ local font = fonts[i]
+ local id = font.id
+ if not id then
+ local name = font.name
+ local size = font.size
+ if name and size then
+ local data, id = constructors.readanddefine(name,size)
+ if id then
+ font.id = id
+ font.name = nil
+ font.size = nil
+ end
+ end
+ end
+ end
+ end
+ end
+ --
+ properties.haskerns = true
+ properties.hasligatures = true
+ properties.hasitalics = true
+ resources.unicodes = { }
+ resources.lookuptags = { }
+ --
+ depth[filename] = depth[filename] - 1
+ --
+ return tfmdata
+ else
+ depth[filename] = depth[filename] - 1
+ end
+end
+
+local function check_tfm(specification,fullname) -- we could split up like afm/otf
+ local foundname = findbinfile(fullname, 'tfm') or ""
+ if foundname == "" then
+ foundname = findbinfile(fullname, 'ofm') or "" -- not needed in context
+ end
+ if foundname == "" then
+ foundname = fonts.names.getfilename(fullname,"tfm") or ""
+ end
+ if foundname ~= "" then
+ specification.filename = foundname
+ specification.format = "ofm"
+ return read_from_tfm(specification)
+ elseif trace_defining then
+ report_defining("loading tfm with name %a fails",specification.name)
+ end
+end
+
+readers.check_tfm = check_tfm
+
+function readers.tfm(specification)
+ local fullname = specification.filename or ""
+ if fullname == "" then
+ local forced = specification.forced or ""
+ if forced ~= "" then
+ fullname = specification.name .. "." .. forced
+ else
+ fullname = specification.name
+ end
+ end
+ return check_tfm(specification,fullname)
+end
+
+readers.ofm = readers.tfm
+
+-- The reencoding acts upon the 'reencode' feature which can have values 'auto' or
+-- an enc file. You can also specify a 'pfbfile' feature (but it defaults to the
+-- tfm filename) and a 'bitmap' feature. When no enc file is givven (auto) we will
+-- get the vectors from the pfb file.
+
+do
+
+ local outfiles = { }
+
+ local tfmcache = table.setmetatableindex(function(t,tfmdata)
+ local id = font.define(tfmdata)
+ t[tfmdata] = id
+ return id
+ end)
+
+ local encdone = table.setmetatableindex("table")
+
+ function tfm.reencode(tfmdata,specification)
+
+ local features = specification.features
+
+ if not features then
+ return
+ end
+
+ local features = features.normal
+
+ if not features then
+ return
+ end
+
+ local tfmfile = file.basename(tfmdata.name)
+ local encfile = features.reencode -- or features.enc
+ local pfbfile = features.pfbfile -- or features.pfb
+ local bitmap = features.bitmap -- or features.pk
+
+ if not encfile then
+ return
+ end
+
+ local pfbfile = pfbfile or outfiles[tfmfile]
+
+ if pfbfile == nil then
+ if bitmap then
+ pfbfile = false
+ elseif type(pfbfile) ~= "string" then
+ pfbfile = tfmfile
+ end
+ if type(pfbfile) == "string" then
+ pfbfile = file.addsuffix(pfbfile,"pfb")
+ -- pdf.mapline(tfmfile .. "<" .. pfbfile)
+ report_tfm("using type1 shapes from %a for %a",pfbfile,tfmfile)
+ else
+ report_tfm("using bitmap shapes for %a",tfmfile)
+ pfbfile = false -- use bitmap
+ end
+ outfiles[tfmfile] = pfbfile
+ end
+
+ local encoding = false
+ local vector = false
+ if type(pfbfile) == "string" then
+ local pfb = constructors.handlers.pfb
+ if pfb and pfb.loadvector then
+ local v, e = pfb.loadvector(pfbfile)
+ if v then
+ vector = v
+ end
+ if e then
+ encoding = e
+ end
+ end
+ end
+ if type(encfile) == "string" and encfile ~= "auto" then
+ encoding = fonts.encodings.load(file.addsuffix(encfile,"enc"))
+ if encoding then
+ encoding = encoding.vector
+ end
+ end
+ if not encoding then
+ report_tfm("bad encoding for %a, quitting",tfmfile)
+ return
+ end
+
+ local unicoding = fonts.encodings.agl and fonts.encodings.agl.unicodes
+ local virtualid = tfmcache[tfmdata]
+ local tfmdata = table.copy(tfmdata) -- good enough for small fonts
+ local characters = { }
+ local originals = tfmdata.characters
+ local indices = { }
+ local parentfont = { "font", 1 } -- can be zero (self referencing)
+ local private = tfmdata.privateoffset or constructors.privateoffset
+ local reported = encdone[tfmfile][encfile] -- bah, encdone for tfm or pfb ?
+ -- create characters table
+
+ -- vector : pfbindex -> name
+ -- encoding : tfmindex -> name
+
+ -- we store the order also because some tex encodings (see math-vfu) needs
+ -- that for remapping with non standard glyphs names cq. lack of unicode
+ -- slot information
+
+ for k, v in next, originals do
+ v.order = k
+ end
+
+ local backmap = vector and table.swapped(vector)
+ local done = { } -- prevent duplicate
+ for tfmindex, name in sortedhash(encoding) do -- predictable order
+ local original = originals[tfmindex]
+ if original then
+ local unicode = unicoding[name]
+ if unicode then
+ original.unicode = unicode
+ else
+ unicode = private
+ private = private + 1
+ if trace_defining and not reported then
+ report_tfm("glyph %a in font %a with encoding %a gets unicode %U",name,tfmfile,encfile,unicode)
+ end
+ end
+ characters[unicode] = original
+ indices[tfmindex] = unicode
+ original.name = name -- so one can lookup weird names
+ if backmap then
+ original.index = backmap[name] -- the pfb index
+ else -- probably bitmap
+ original.commands = { parentfont, charcommand[tfmindex] } -- or "slot"
+ original.oindex = tfmindex
+ end
+ done[name] = true
+ elseif not done[name] then
+ report_tfm("bad index %a in font %a with name %a",tfmindex,tfmfile,name)
+ end
+ end
+
+ encdone[tfmfile][encfile] = true
+
+ -- redo kerns and ligatures
+
+ for k, v in next, characters do
+ local kerns = v.kerns
+ if kerns then
+ local t = { }
+ for k, v in next, kerns do
+ local i = indices[k]
+ if i then
+ t[i] = v
+ end
+ end
+ v.kerns = next(t) and t or nil
+ end
+ local ligatures = v.ligatures
+ if ligatures then
+ local t = { }
+ for k, v in next, ligatures do
+ local i = indices[k]
+ if i then
+ t[i] = v
+ v.char = indices[v.char]
+ end
+ end
+ v.ligatures = next(t) and t or nil
+ end
+ end
+
+ -- wrap up
+
+ tfmdata.fonts = { { id = virtualid } }
+ tfmdata.characters = characters
+ tfmdata.fullname = tfmdata.fullname or tfmdata.name
+ tfmdata.psname = file.nameonly(pfbfile or tfmdata.name)
+ tfmdata.filename = pfbfile
+ -- tfmdata.format = bitmap and "type3" or "type1"
+ tfmdata.format = "type1"
+if not CONTEXTLMTXMODE or CONTEXTLMTXMODE == 0 then
+ tfmdata.encodingbytes = 2
+ tfmdata.tounicode = 1
+ tfmdata.embedding = "subset"
+end
+ tfmdata.usedbitmap = bitmap and virtualid
+ tfmdata.private = private
+
+ return tfmdata
+ end
+
+end
+
+-- Now we implement the regular features handlers. We need to convert the
+-- tfm specific structures to opentype structures. In basemode they are
+-- converted back so that is a bit of a waste but it's fast enough.
+
+do
+
+ local everywhere = { ["*"] = { ["*"] = true } } -- or: { ["*"] = { "*" } }
+ local noflags = { false, false, false, false }
+
+ local function enhance_normalize_features(data)
+ local ligatures = setmetatableindex("table")
+ local kerns = setmetatableindex("table")
+ local characters = data.characters
+ for u, c in next, characters do
+ local l = c.ligatures
+ local k = c.kerns
+ if l then
+ ligatures[u] = l
+ for u, v in next, l do
+ l[u] = { ligature = v.char }
+ end
+ c.ligatures = nil
+ end
+ if k then
+ kerns[u] = k
+ for u, v in next, k do
+ k[u] = v -- { v, 0 }
+ end
+ c.kerns = nil
+ end
+ end
+
+ for u, l in next, ligatures do
+ for k, v in next, l do
+ local vl = v.ligature
+ local dl = ligatures[vl]
+ if dl then
+ for kk, vv in next, dl do
+ v[kk] = vv -- table.copy(vv)
+ end
+ end
+ end
+ end
+
+ local features = {
+ gpos = { },
+ gsub = { },
+ }
+ local sequences = {
+ -- only filled ones
+ }
+ if next(ligatures) then
+ features.gsub.liga = everywhere
+ data.properties.hasligatures = true
+ sequences[#sequences+1] = {
+ features = {
+ liga = everywhere,
+ },
+ flags = noflags,
+ name = "s_s_0",
+ nofsteps = 1,
+ order = { "liga" },
+ type = "gsub_ligature",
+ steps = {
+ {
+ coverage = ligatures,
+ },
+ },
+ }
+ end
+ if next(kerns) then
+ features.gpos.kern = everywhere
+ data.properties.haskerns = true
+ sequences[#sequences+1] = {
+ features = {
+ kern = everywhere,
+ },
+ flags = noflags,
+ name = "p_s_0",
+ nofsteps = 1,
+ order = { "kern" },
+ type = "gpos_pair",
+ steps = {
+ {
+ format = "kern",
+ coverage = kerns,
+ },
+ },
+ }
+ end
+ data.resources.features = features
+ data.resources.sequences = sequences
+ data.shared.resources = data.shared.resources or resources
+ end
+
+ registertfmenhancer("normalize features", enhance_normalize_features)
+ registertfmenhancer("check extra features", otfenhancers.enhance)
+
+end
+
+-- As with type one (afm) loading, we just use the opentype ones:
+
+registertfmfeature {
+ name = "mode",
+ description = "mode",
+ initializers = {
+ base = otf.modeinitializer,
+ node = otf.modeinitializer,
+ }
+}
+
+registertfmfeature {
+ name = "features",
+ description = "features",
+ default = true,
+ initializers = {
+ base = otf.basemodeinitializer,
+ node = otf.nodemodeinitializer,
+ },
+ processors = {
+ node = otf.featuresprocessor,
+ }
+}
diff --git a/tex/context/base/mkxl/font-tpk.lmt b/tex/context/base/mkxl/font-tpk.lmt
new file mode 100644
index 000000000..d216bc257
--- /dev/null
+++ b/tex/context/base/mkxl/font-tpk.lmt
@@ -0,0 +1,1304 @@
+if not modules then modules = { } end modules ['font-tpk'] = {
+ version = 1.001,
+ optimize = true,
+ comment = "companion to font-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- The bitmap loader is more or less derived from the luatex version (taco)
+-- which is derived from pdftex (thanh) who uses code from dvips (thomas)
+-- adapted by piet ... etc. The tfm and vf readers are also derived from
+-- luatex. All do things a bit more luaish and errors are of course mine.
+
+local next = next
+local extract, band, lshift, rshift = bit32.extract, bit32.band, bit32.lshift, bit32.rshift
+local idiv = number.idiv
+local char = string.char
+local concat, insert, remove, copy = table.concat, table.insert, table.remove, table.copy
+local tobitstring = number.tobitstring
+local formatters = string.formatters
+local round = math.round
+
+local streams = utilities.streams
+local openstream = streams.open
+local streamsize = streams.size
+local readcardinal1 = streams.readcardinal1
+local readcardinal2 = streams.readcardinal2
+local readcardinal3 = streams.readcardinal3
+local readcardinal4 = streams.readcardinal4
+local readinteger1 = streams.readinteger1
+local readinteger2 = streams.readinteger2
+local readinteger3 = streams.readinteger3
+local readinteger4 = streams.readinteger4
+local readbyte = streams.readbyte
+local readbytes = streams.readbytes
+local readstring = streams.readstring
+local skipbytes = streams.skipbytes
+local getposition = streams.getposition
+local setposition = streams.setposition
+
+if not fonts then fonts = { handlers = { tfm = { } } } end
+
+local handlers = fonts.handlers
+local tfm = handlers.tfm or { }
+handlers.tfm = tfm
+local readers = tfm.readers or { }
+tfm.readers = readers
+
+tfm.version = 1.005
+tfm.cache = containers.define("fonts", "tfm", tfm.version, true)
+
+-- Performance is no real issue here so I didn't optimize too much. After
+-- all, these files are small and we mostly use opentype or type1 fonts.
+
+do
+
+ local function readbitmap(glyph,s,flagbyte)
+
+ local inputbyte = 0
+ local bitweight = 0
+ local dynf = 0
+ local remainder = 0
+ local realfunc = nil
+ local repeatcount = 0
+
+ local function getnyb() -- can be inlined
+ if bitweight == 0 then
+ bitweight = 16
+ inputbyte = readbyte(s)
+ return extract(inputbyte,4,4)
+ else
+ bitweight = 0
+ return band(inputbyte,15)
+ end
+ end
+
+ local function getbit() -- can be inlined
+ bitweight = rshift(bitweight,1)
+ if bitweight == 0 then -- actually we can check for 1
+ inputbyte = readbyte(s)
+ bitweight = 128
+ end
+ return band(inputbyte,bitweight)
+ end
+
+ local function pkpackednum()
+ local i = getnyb(s)
+ if i == 0 then
+ repeat
+ j = getnyb()
+ i = i + 1
+ until (j ~= 0)
+ if i > 3 then
+ return handlehuge(i,j)
+ else
+ for i=1,i do
+ j = j * 16 + getnyb()
+ end
+ return j - 15 + (13 - dynf) * 16 + dynf
+ end
+ elseif i <= dynf then
+ return i
+ elseif i < 14 then
+ return (i - dynf - 1) * 16 + getnyb() + dynf + 1
+ elseif i == 14 then
+ repeatcount = pkpackednum()
+ else
+ repeatcount = 1
+ end
+ return realfunc()
+ end
+
+ local function rest()
+ if remainder < 0 then
+ remainder = -remainder
+ return 0
+ elseif remainder > 4000 then
+ remainder = 4000 - remainder
+ return 4000
+ elseif remainder > 0 then
+ local i = remainder
+ remainder = 0
+ realfunc = pkpackednum
+ return i
+ else
+ -- error = "pk issue that shouldn't happen"
+ return 0
+ end
+ end
+
+ local function handlehuge(i,j)
+ while i ~= 0 do
+ j = lshift(j,4) + getnyb()
+ -- j = extract(j,8,4) + getnyb()
+ i = i - 1
+ end
+ remainder = j - 15 + (13 - dynf) * 16 + dynf
+ realfunc = rest
+ return rest()
+ end
+
+ local gpower = { [0] =
+ 0, 1, 3, 7, 15, 31, 63, 127,
+ 255, 511, 1023, 2047, 4095, 8191, 16383, 32767,
+ 65535
+ }
+
+ local raster = { }
+ local r = 0
+ glyph.stream = raster
+
+ local xsize = glyph.xsize
+ local ysize = glyph.ysize
+ local word = 0
+ local wordweight = 0
+ local wordwidth = idiv(xsize + 15,16)
+ local rowsleft = 0
+ local turnon = band(flagbyte,8) == 8 and true or false
+ local hbit = 0
+ local count = 0
+ --
+ realfunc = pkpackednum
+ dynf = idiv(flagbyte,16)
+ --
+ if dynf == 14 then
+ bitweight = 0
+ for i=1,ysize do
+ word = 0
+ wordweight = 32768
+ for j=1,xsize do
+ if getbit() ~= 0 then
+ word = word + wordweight
+ end
+ wordweight = rshift(wordweight,1)
+ if wordweight == 0 then
+ r = r + 1
+ raster[r] = word
+ word = 0
+ wordweight = 32768
+ end
+ end
+ if wordweight ~= 32768 then
+ r = r + 1
+ raster[r] = word
+ end
+ end
+ else
+ rowsleft = ysize
+ hbit = xsize
+ repeatcount = 0
+ wordweight = 16
+ word = 0
+ bitweight = 0
+ while rowsleft > 0 do
+ count = realfunc()
+ while count ~= 0 do
+ if count < wordweight and count < hbit then
+ if turnon then
+ word = word + gpower[wordweight] - gpower[wordweight - count]
+ end
+ hbit = hbit - count
+ wordweight = wordweight - count
+ count = 0
+ elseif count >= hbit and hbit <= wordweight then
+ if turnon then
+ word = word + gpower[wordweight] - gpower[wordweight - hbit]
+ end
+ r = r + 1
+ raster[r] = word
+ for i=1,repeatcount*wordwidth do
+ r = r + 1
+ raster[r] = raster[r - wordwidth]
+ end
+ rowsleft = rowsleft - repeatcount - 1
+ repeatcount = 0
+ word = 0
+ wordweight = 16
+ count = count - hbit
+ hbit = xsize
+ else
+ if turnon then
+ word = word + gpower[wordweight]
+ end
+ r = r + 1
+ raster[r] = word
+ word = 0
+ count = count - wordweight
+ hbit = hbit - wordweight
+ wordweight = 16
+ end
+ end
+ turnon = not turnon
+ end
+ if rowsleft ~= 0 or hbit ~= xsize then
+ print("ERROR",rowsleft,hbit,xsize)
+ -- error = "error while unpacking, more bits than required"
+ end
+ end
+
+ end
+
+ function readers.showpk(glyph)
+ local xsize = glyph.xsize
+ local ysize = glyph.ysize
+ local stream = glyph.stream
+ local result = { }
+ local rr = { }
+ local r = 0
+ local s = 0
+ local cw = idiv(xsize+ 7, 8)
+ local rw = idiv(xsize+15,16)
+ local extra = 2 * rw == cw
+ local b
+ for y=1,ysize do
+ r = 0
+ for x=1,rw-1 do
+ s = s + 1 ; b = stream[s]
+ r = r + 1 ; rr[r] = tobitstring(b,16,16)
+ end
+ s = s + 1 ; b = stream[s]
+ if extra then
+ r = r + 1 ; rr[r] = tobitstring(b,16,16)
+ else
+ r = r + 1 ; rr[r] = tobitstring(extract(b,8+(8-cw),cw),cw,cw)
+ end
+ result[y] = concat(rr)
+ end
+ return concat(result,"\n")
+ end
+
+ local template = formatters [ [[
+%.3N 0 %i %i %i %i d1
+q
+%i 0 0 %i %i %i cm
+BI
+ /W %i
+ /H %i
+ /IM true
+ /BPC 1
+ /D [1 0]
+ID %t
+EI
+Q]] ]
+
+ function readers.pktopdf(glyph,data,factor)
+ local width = data.width * factor
+ local xsize = glyph.xsize or 0
+ local ysize = glyph.ysize or 0
+ local xoffset = glyph.xoffset or 0
+ local yoffset = glyph.yoffset or 0
+ local stream = glyph.stream
+
+ local dpi = 1
+ local newdpi = 1
+
+ local xdpi = dpi * xsize / newdpi
+ local ydpi = dpi * ysize / newdpi
+
+ local llx = - xoffset
+ local lly = yoffset - ysize + 1
+ local urx = llx + xsize + 1
+ local ury = lly + ysize
+
+ local result = { }
+ local r = 0
+ local s = 0
+ local cw = idiv(xsize+ 7, 8)
+ local rw = idiv(xsize+15,16)
+ local extra = 2 * rw == cw
+ local b
+ for y=1,ysize do
+ for x=1,rw-1 do
+ s = s + 1 ; b = stream[s]
+ r = r + 1 ; result[r] = char(extract(b,8,8),extract(b,0,8))
+ end
+ s = s + 1 ; b = stream[s]
+ if extra then
+ r = r + 1 ; result[r] = char(extract(b,8,8),extract(b,0,8))
+ else
+ r = r + 1 ; result[r] = char(extract(b,8,8))
+ end
+ end
+ return template(width,llx,lly,urx,ury,xdpi,ydpi,llx,lly,xsize,ysize,result), width
+ end
+
+ function readers.loadpk(filename)
+ local s = openstream(filename)
+ local preamble = readcardinal1(s)
+ local version = readcardinal1(s)
+ local comment = readstring(s,readcardinal1(s))
+ local designsize = readcardinal4(s)
+ local checksum = readcardinal4(s)
+ local hppp = readcardinal4(s)
+ local vppp = readcardinal4(s)
+ if preamble ~= 247 or version ~= 89 or not vppp then
+ return { error = "invalid preamble" }
+ end
+ local glyphs = { }
+ local data = {
+ designsize = designsize,
+ comment = comment,
+ hppp = hppp,
+ vppp = vppp,
+ glyphs = glyphs,
+ }
+ while true do
+ local flagbyte = readcardinal1(s)
+ if flagbyte < 240 then
+ local c = band(flagbyte,7)
+ local length, index, width, pixels, xsize, ysize, xoffset, yoffset
+ if c >= 0 and c <= 3 then
+ length = band(flagbyte,7) * 256 + readcardinal1(s) - 3
+ index = readcardinal1(s)
+ width = readinteger3(s)
+ pixels = readcardinal1(s)
+ xsize = readcardinal1(s)
+ ysize = readcardinal1(s)
+ xoffset = readcardinal1(s)
+ yoffset = readcardinal1(s)
+ if xoffset > 127 then
+ xoffset = xoffset - 256
+ end
+ if yoffset > 127 then
+ yoffset = yoffset - 256
+ end
+ elseif c >= 4 and c <= 6 then
+ length = band(flagbyte,3) * 65536 + readcardinal1(s) * 256 + readcardinal1(s) - 4
+ index = readcardinal1(s)
+ width = readinteger3(s)
+ pixels = readcardinal2(s)
+ xsize = readcardinal2(s)
+ ysize = readcardinal2(s)
+ xoffset = readcardinal2(s)
+ yoffset = readcardinal2(s)
+ else -- 7
+ length = readcardinal4(s) - 9
+ index = readcardinal4(s)
+ width = readinteger4(s)
+ pixels = readcardinal4(s)
+ readcardinal4(s)
+ xsize = readcardinal4(s)
+ ysize = readcardinal4(s)
+ xoffset = readcardinal4(s)
+ yoffset = readcardinal4(s)
+ end
+ local glyph = {
+ index = index,
+ width = width,
+ pixels = pixels,
+ xsize = xsize,
+ ysize = ysize,
+ xoffset = xoffset,
+ yoffset = yoffset,
+ }
+ if length <= 0 then
+ data.error = "bad packet"
+ return data
+ end
+ readbitmap(glyph,s,flagbyte)
+ glyphs[index] = glyph
+ elseif flagbyte == 240 then
+ -- k[1] x[k]
+ skipbytes(s,readcardinal1(s))
+ elseif flagbyte == 241 then
+ -- k[2] x[k]
+ skipbytes(s,readcardinal2(s)*2)
+ elseif flagbyte == 242 then
+ -- k[3] x[k]
+ skipbytes(s,readcardinal3(s)*3)
+ elseif flagbyte == 243 then
+ -- k[4] x[k]
+ skipbytes(s,readcardinal4(s)*4) -- readinteger4
+ elseif flagbyte == 244 then
+ -- y[4]
+ skipbytes(s,4)
+ elseif flagbyte == 245 then
+ break
+ elseif flagbyte == 246 then
+ -- nop
+ else
+ data.error = "unknown pk command"
+ break
+ end
+ end
+ return data
+ end
+
+end
+
+do
+
+ local leftboundary = -1
+ local rightboundary = -2
+ local boundarychar = 65536
+
+ function readers.loadtfm(filename)
+ local data
+ --
+ local function someerror(m)
+ if not data then
+ data = { }
+ end
+ data.error = m or "fatal error"
+ return data
+ end
+ --
+ local s = openstream(filename)
+ if not s then
+ return someerror()
+ end
+ --
+ local wide = false
+ local header = 0
+ local max = 0
+ local size = streamsize(s)
+ local glyphs = table.setmetatableindex(function(t,k)
+ local v = {
+ -- we default because boundary chars have no dimension s
+ width = 0,
+ height = 0,
+ depth = 0,
+ italic = 0,
+ }
+ t[k] = v
+ return v
+ end)
+ local parameters = { }
+ local direction = 0
+ --
+ local lf, lh, bc, ec, nw, nh, nd, ni, nl, nk, ne, np
+ --
+ lf = readcardinal2(s)
+ if lf ~= 0 then
+ header = 6
+ max = 255
+ wide = false
+ lh = readcardinal2(s)
+ bc = readcardinal2(s)
+ ec = readcardinal2(s)
+ nw = readcardinal2(s)
+ nh = readcardinal2(s)
+ nd = readcardinal2(s)
+ ni = readcardinal2(s)
+ nl = readcardinal2(s)
+ nk = readcardinal2(s)
+ ne = readcardinal2(s)
+ np = readcardinal2(s)
+ else
+ header = 14
+ max = 65535
+ wide = readcardinal4(s) == 0
+ if not wide then
+ return someerror("invalid format")
+ end
+ lf = readcardinal4(s)
+ lh = readcardinal4(s)
+ bc = readcardinal4(s)
+ ec = readcardinal4(s)
+ nw = readcardinal4(s)
+ nh = readcardinal4(s)
+ nd = readcardinal4(s)
+ ni = readcardinal4(s)
+ nl = readcardinal4(s)
+ nk = readcardinal4(s)
+ ne = readcardinal4(s)
+ np = readcardinal4(s)
+ direction = readcardinal4(s)
+ end
+ if (bc > ec + 1) or (ec > max) then
+ return someerror("file is too small")
+ end
+ if bc > max then
+ bc, ec = 1, 0
+ end
+ local nlw = (wide and 2 or 1) * nl
+ local neew = (wide and 2 or 1) * ne
+ local ncw = (wide and 2 or 1) * (ec - bc + 1)
+ if lf ~= (header + lh + ncw + nw + nh + nd + ni + nlw + nk + neew + np) then
+ return someerror("file is too small")
+ end
+ if nw == 0 or nh == 0 or nd == 0 or ni == 0 then
+ return someerror("no glyphs")
+ end
+ if lf * 4 > size then
+ return someerror("file is too small")
+ end
+ local slh = lh
+ if lh < 2 then
+ return someerror("file is too small")
+ end
+ local checksum = readcardinal4(s)
+ local designsize = readcardinal2(s)
+ designsize = designsize * 256 + readcardinal1(s)
+ designsize = designsize * 16 + rshift(readcardinal1(s),4)
+ if designsize < 0xFFFF then
+ return someerror("weird designsize")
+ end
+ --
+ local alpha = 16
+ local z = designsize
+ while z >= 040000000 do
+ z = rshift(z,1)
+ alpha = alpha + alpha
+ end
+ local beta = idiv(256,alpha)
+ alpha = alpha * z
+ --
+ local function readscaled()
+ local a, b, c, d = readbytes(s,4)
+ local n = idiv(rshift(rshift(d*z,8)+c*z,8)+b*z,beta)
+ if a == 0 then
+ return n
+ elseif a == 255 then
+ return n - alpha
+ else
+ return 0
+ end
+ end
+ --
+ local function readunscaled()
+ local a, b, c, d = readbytes(s,4)
+ if a > 127 then
+ a = a - 256
+ end
+ return a * 0xFFFFF + b * 0xFFF + c * 0xF + rshift(d,4)
+ end
+ --
+ while lh > 2 do -- can be one-liner
+ skipbytes(s,4)
+ lh = lh - 1
+ end
+ local saved = getposition(s)
+ setposition(s,(header + slh + ncw) * 4 + 1)
+ local widths = { } for i=0,nw-1 do widths [i] = readscaled() end
+ local heights = { } for i=0,nh-1 do heights[i] = readscaled() end
+ local depths = { } for i=0,nd-1 do depths [i] = readscaled() end
+ local italics = { } for i=0,ni-1 do italics[i] = readscaled() end
+ if widths[0] ~= 0 or heights[0] ~= 0 or depths[0] ~= 0 then
+ return someerror("invalid dimensions")
+ end
+ --
+ local blabel = nl
+ local bchar = boundarychar
+ --
+ local ligatures = { }
+ if nl > 0 then
+ for i=0,nl-1 do
+ local a, b, c, d = readbytes(s,4)
+ ligatures[i] = {
+ skip = a,
+ nxt = b,
+ op = c,
+ rem = d,
+ }
+ if a > 128 then
+ if 256 * c + d >= nl then
+ return someerror("invalid ligature table")
+ end
+ if a == 255 and i == 0 then
+ bchar = b
+ end
+ else
+ if c < 128 then
+ -- whatever
+ elseif 256 * (c - 128) + d >= nk then
+ return someerror("invalid ligature table")
+ end
+ if (a < 128) and (i - 0 + a + 1 >= nl) then
+ return someerror("invalid ligature table")
+ end
+ end
+ if a == 255 then
+ blabel = 256 * c + d
+ end
+ end
+ end
+ local allkerns = { }
+ for i=0,nk-1 do
+ allkerns[i] = readscaled()
+ end
+ local extensibles = { }
+ for i=0,ne-1 do
+ extensibles[i] = wide and {
+ top = readcardinal2(s),
+ bot = readcardinal2(s),
+ mid = readcardinal2(s),
+ rep = readcardinal2(s),
+ } or {
+ top = readcardinal1(s),
+ bot = readcardinal1(s),
+ mid = readcardinal1(s),
+ rep = readcardinal1(s),
+ }
+ end
+ for i=1,np do
+ if i == 1 then
+ parameters[i] = readunscaled()
+ else
+ parameters[i] = readscaled()
+ end
+ end
+ for i=1,7 do
+ if not parameters[i] then
+ parameters[i] = 0
+ end
+ end
+ --
+ setposition(s,saved)
+ local extras = false
+ if blabel ~= nl then
+ local k = blabel
+ while true do
+ local l = ligatures[k]
+ local skip = l.skip
+ if skip <= 128 then
+ -- if l.op >= 128 then
+ -- extras = true -- kern
+ -- else
+ extras = true -- ligature
+ -- end
+ end
+ if skip == 0 then
+ k = k + 1
+ else
+ if skip >= 128 then
+ break
+ end
+ k = k + skip + 1
+ end
+ end
+ end
+ if extras then
+ local ligas = { }
+ local kerns = { }
+ local k = blabel
+ while true do
+ local l = ligatures[k]
+ local skip = l.skip
+ if skip <= 128 then
+ local nxt = l.nxt
+ local op = l.op
+ local rem = l.rem
+ if op >= 128 then
+ kerns[nxt] = allkerns[256 * (op - 128) + rem]
+ else
+ ligas[nxt] = { type = op * 2 + 1, char = rem }
+ end
+ end
+ if skip == 0 then
+ k = k + 1
+ else
+ if skip >= 128 then
+ break;
+ end
+ k = k + skip + 1
+ end
+ end
+ if next(kerns) then
+ local glyph = glyphs[leftboundary]
+ glyph.kerns = kerns
+ glyph.remainder = 0
+ end
+ if next(ligas) then
+ local glyph = glyphs[leftboundary]
+ glyph.ligatures = ligas
+ glyph.remainder = 0
+ end
+ end
+ for i=bc,ec do
+ local glyph, width, height, depth, italic, tag, remainder
+ if wide then
+ width = readcardinal2(s)
+ height = readcardinal1(s)
+ depth = readcardinal1(s)
+ italic = readcardinal1(s)
+ tag = readcardinal1(s)
+ remainder = readcardinal2(s)
+ else
+ width = readcardinal1(s)
+ height = readcardinal1(s)
+ depth = extract(height,0,4)
+ height = extract(height,4,4)
+ italic = readcardinal1(s)
+ tag = extract(italic,0,2)
+ italic = extract(italic,2,6)
+ remainder = readcardinal1(s)
+ end
+ if width == 0 then
+ -- nothing
+ else
+ if width >= nw or height >= nh or depth >= nd or italic >= ni then
+ return someerror("invalid dimension index")
+ end
+ local extensible, nextinsize
+ if tag == 0 then
+ -- nothing special
+ else
+ local r = remainder
+ if tag == 1 then
+ if r >= nl then
+ return someerror("invalid ligature index")
+ end
+ elseif tag == 2 then
+ if r < bc or r > ec then
+ return someerror("invalid chain index")
+ end
+ while r < i do
+ local g = glyphs[r]
+ if g.tag ~= list_tag then
+ break
+ end
+ r = g.remainder
+ end
+ if r == i then
+ return someerror("cycles in chain")
+ end
+ nextinsize = r
+ elseif tag == 3 then
+ if r >= ne then
+ return someerror("bad extensible")
+ end
+ extensible = extensibles[r] -- remainder ?
+ remainder = 0
+ end
+ end
+ glyphs[i] = {
+ width = widths [width],
+ height = heights[height],
+ depth = depths [depth],
+ italic = italics[italic],
+ tag = tag,
+ -- index = i,
+ remainder = remainder,
+ extensible = extensible,
+ next = nextinsize,
+ }
+ end
+ end
+ for i=bc,ec do
+ local glyph = glyphs[i]
+ if glyph.tag == 1 then
+ -- ligature
+ local k = glyph.remainder
+ local l = ligatures[k]
+ if l.skip > 128 then
+ k = 256 * l.op + l.rem
+ end
+ local ligas = { }
+ local kerns = { }
+ while true do
+ local l = ligatures[k]
+ local skip = l.skip
+ if skip <= 128 then
+ local nxt = l.nxt
+ local op = l.op
+ local rem = l.rem
+ if op >= 128 then
+ local kern = allkerns[256 * (op - 128) + rem]
+ if nxt == bchar then
+ kerns[rightboundary] = kern
+ end
+ kerns[nxt] = kern
+ else
+ local ligature = { type = op * 2 + 1, char = rem }
+ if nxt == bchar then
+ ligas[rightboundary] = ligature
+ end
+ ligas[nxt] = ligature -- shared
+ end
+ end
+ if skip == 0 then
+ k = k + 1
+ else
+ if skip >= 128 then
+ break
+ end
+ k = k + skip + 1
+ end
+ end
+ if next(kerns)then
+ glyph.kerns = kerns
+ glyph.remainder = 0
+ end
+ if next(ligas) then
+ glyph.ligatures = ligas
+ glyph.remainder = 0
+ end
+ end
+ end
+ --
+ if bchar ~= boundarychar then
+ glyphs[rightboundary] = copy(glyphs[bchar])
+ end
+ --
+ -- for k, v in next, glyphs do
+ -- v.tag = nil
+ -- v.remainder = nil
+ -- end
+ --
+ return {
+ name = file.nameonly(filename),
+ fontarea = file.pathpart(filename),
+ glyphs = glyphs,
+ parameters = parameters,
+ designsize = designsize,
+ size = designsize,
+ direction = direction,
+ -- checksum = checksum,
+ -- embedding = "unknown",
+ -- extend = 1000,
+ -- slant = 0,
+ -- squeeze = 0,
+ -- format = "unknown",
+ -- identity = "unknown",
+ -- mode = 0,
+ -- streamprovider = 0,
+ -- tounicode = 0,
+ -- type = "unknown",
+ -- units_per_em = 0,
+ -- used = false,
+ -- width = 0,
+ -- writingmode = "unknown",
+ }
+ end
+
+end
+
+do
+
+ local push = { "push" }
+ local push = { "pop" }
+
+ local w, x, y, z, f
+ local stack
+ local s, result, r
+ local alpha, beta, z
+
+ local function scaled1()
+ local a = readbytes(s,1)
+ if a == 0 then
+ return 0
+ elseif a == 255 then
+ return - alpha
+ else
+ return 0 -- error
+ end
+ end
+
+ local function scaled2()
+ local a, b = readbytes(s,2)
+ local sw = idiv(b*z,beta)
+ if a == 0 then
+ return sw
+ elseif a == 255 then
+ return sw - alpha
+ else
+ return 0 -- error
+ end
+ end
+
+ local function scaled3()
+ local a, b, c = readbytes(s,3)
+ local sw = idiv(rshift(c*z,8)+b*z,beta)
+ if a == 0 then
+ return sw
+ elseif a == 255 then
+ return sw - alpha
+ else
+ return 0 -- error
+ end
+ end
+
+ local function scaled4()
+ local a, b, c, d = readbytes(s,4)
+ local sw = idiv( rshift(rshift(d*z,8)+(c*z),8)+b*z,beta)
+ if a == 0 then
+ return sw
+ elseif a == 255 then
+ return sw - alpha
+ else
+ return 0 -- error
+ end
+ end
+
+ local function dummy()
+ end
+
+ local actions = {
+
+ [128] = function() r = r + 1 result[r] = { "slot", f or 1, readcardinal1(s) } p = p + 1 end,
+ [129] = function() r = r + 1 result[r] = { "slot", f or 1, readcardinal2(s) } p = p + 2 end,
+ [130] = function() r = r + 1 result[r] = { "slot", f or 1, readcardinal3(s) } p = p + 3 end,
+ [131] = function() r = r + 1 result[r] = { "slot", f or 1, readcardinal4(s) } p = p + 4 end,
+
+ [132] = function()
+ r = r + 1
+ result[r] = { "rule", scaled4(), scaled4() }
+ p = p + 8
+ end,
+
+ [133] = function()
+ r = r + 1 result[r] = push
+ r = r + 1 result[r] = { "slot", f or 1, readcardinal1(s) }
+ r = r + 1 result[r] = pop
+ p = p + 1
+ end,
+ [134] = function()
+ r = r + 1 result[r] = push
+ r = r + 1 result[r] = { "slot", f or 1, readcardinal2(s) }
+ r = r + 1 result[r] = pop
+ p = p + 2
+ end,
+ [135] = function()
+ r = r + 1 result[r] = push
+ r = r + 1 result[r] = { "slot", f or 1, readcardinal2(s) }
+ r = r + 1 result[r] = pop
+ p = p + 3
+ end,
+ [136] = function()
+ r = r + 1 result[r] = push
+ r = r + 1 result[r] = { "slot", f or 1, readcardinal4(s) }
+ r = r + 1 result[r] = pop
+ p = p + 4
+ end,
+
+ [137] = function()
+ r = r + 1 result[r] = push
+ r = r + 1 result[r] = { "rule", scaled4(), scaled4() }
+ r = r + 1 result[r] = pop
+ p = p + 8
+ end,
+
+ [138] = dummy, -- nop
+ [139] = dummy, -- bop
+ [140] = dummy, -- eop
+
+ [141] = function()
+ insert(stack, { w, x, y, z })
+ r = r + 1
+ result[r] = push
+ end,
+ [142] = function()
+ local t = remove(stack)
+ if t then
+ w, x, y, z = t[1], t[2], t[3], t[4]
+ r = r + 1
+ result[r] = pop
+ end
+ end,
+
+ [143] = function() r = r + 1 result[r] = { "right", scaled1() } p = p + 1 end,
+ [144] = function() r = r + 1 result[r] = { "right", scaled2() } p = p + 2 end,
+ [145] = function() r = r + 1 result[r] = { "right", scaled3() } p = p + 3 end,
+ [146] = function() r = r + 1 result[r] = { "right", scaled4() } p = p + 4 end,
+
+ [148] = function() w = scaled1() r = r + 1 result[r] = { "right", w } p = p + 1 end,
+ [149] = function() w = scaled2() r = r + 1 result[r] = { "right", w } p = p + 2 end,
+ [150] = function() w = scaled3() r = r + 1 result[r] = { "right", w } p = p + 3 end,
+ [151] = function() w = scaled4() r = r + 1 result[r] = { "right", w } p = p + 4 end,
+
+ [153] = function() x = scaled1() r = r + 1 result[r] = { "right", x } p = p + 1 end,
+ [154] = function() x = scaled2() r = r + 1 result[r] = { "right", x } p = p + 2 end,
+ [155] = function() x = scaled3() r = r + 1 result[r] = { "right", x } p = p + 3 end,
+ [156] = function() x = scaled4() r = r + 1 result[r] = { "right", x } p = p + 4 end,
+
+ [157] = function() r = r + 1 result[r] = { "down", scaled1() } p = p + 1 end,
+ [158] = function() r = r + 1 result[r] = { "down", scaled2() } p = p + 2 end,
+ [159] = function() r = r + 1 result[r] = { "down", scaled3() } p = p + 3 end,
+ [160] = function() r = r + 1 result[r] = { "down", scaled4() } p = p + 4 end,
+
+ [162] = function() y = scaled1() r = r + 1 result[r] = { "down", y } p = p + 1 end,
+ [163] = function() y = scaled2() r = r + 1 result[r] = { "down", y } p = p + 2 end,
+ [164] = function() y = scaled3() r = r + 1 result[r] = { "down", y } p = p + 3 end,
+ [165] = function() y = scaled3() r = r + 1 result[r] = { "down", y } p = p + 4 end,
+
+ [167] = function() z = scaled1() r = r + 1 ; result[r] = { "down", z } p = p + 4 end,
+ [168] = function() z = scaled2() r = r + 1 ; result[r] = { "down", z } p = p + 4 end,
+ [169] = function() z = scaled3() r = r + 1 ; result[r] = { "down", z } p = p + 4 end,
+ [170] = function() z = scaled4() r = r + 1 ; result[r] = { "down", z } p = p + 4 end,
+
+ [147] = function() r = r + 1 result[r] = { "right", w } end,
+ [152] = function() r = r + 1 result[r] = { "right", x } end,
+ [161] = function() r = r + 1 result[r] = { "down", y } end,
+ [166] = function() r = r + 1 result[r] = { "down", z } end,
+
+ [235] = function() f = readcardinal1(s) p = p + 1 end,
+ [236] = function() f = readcardinal2(s) p = p + 3 end,
+ [237] = function() f = readcardinal3(s) p = p + 3 end,
+ [238] = function() f = readcardinal4(s) p = p + 4 end,
+
+ [239] = function() local n = readcardinal1(s) r = r + 1 result[r] = { "special", readstring(s,n) } p = p + 1 + n end,
+ [240] = function() local n = readcardinal2(s) r = r + 1 result[r] = { "special", readstring(s,n) } p = p + 2 + n end,
+ [241] = function() local n = readcardinal3(s) r = r + 1 result[r] = { "special", readstring(s,n) } p = p + 3 + n end,
+ [242] = function() local n = readcardinal4(s) r = r + 1 result[r] = { "special", readstring(s,n) } p = p + 4 + n end,
+
+ [250] = function() local n = readcardinal1(s) r = r + 1 result[r] = { "pdf", readstring(s,n) } p = p + 1 + n end,
+ [251] = function() local n = readcardinal2(s) r = r + 1 result[r] = { "pdf", readstring(s,n) } p = p + 2 + n end,
+ [252] = function() local n = readcardinal3(s) r = r + 1 result[r] = { "pdf", readstring(s,n) } p = p + 3 + n end,
+ [253] = function() local n = readcardinal4(s) r = r + 1 result[r] = { "pdf", readstring(s,n) } p = p + 4 + n end,
+
+ }
+
+ table.setmetatableindex(actions,function(t,cmd)
+ local v
+ if cmd >= 0 and cmd <= 127 then
+ v = function()
+ if f == 0 then
+ f = 1
+ end
+ r = r + 1 ; result[r] = { "slot", f, cmd }
+ end
+ elseif cmd >= 171 and cmd <= 234 then
+ cmd = cmd - 170
+ v = function()
+ r = r + 1 ; result[r] = { "font", cmd }
+ end
+ else
+ v = dummy
+ end
+ t[cmd] = v
+ return v
+ end)
+
+ function readers.loadvf(filename,data)
+ --
+ local function someerror(m)
+ if not data then
+ data = { }
+ end
+ data.error = m or "fatal error"
+ return data
+ end
+ --
+ s = openstream(filename)
+ if not s then
+ return someerror()
+ end
+ --
+ local cmd = readcardinal1(s)
+ if cmd ~= 247 then
+ return someerror("bad preamble")
+ end
+ cmd = readcardinal1(s)
+ if cmd ~= 202 then
+ return someerror("bad version")
+ end
+ local header = readstring(s,readcardinal1(s))
+ local checksum = readcardinal4(s)
+ local designsize = idiv(readcardinal4(s),16)
+ local fonts = data and data.fonts or { }
+ local glyphs = data and data.glyphs or { }
+ --
+ alpha = 16
+ z = designsize
+ while z >= 040000000 do
+ z = rshift(z,1)
+ alpha = alpha + alpha
+ end
+ beta = idiv(256,alpha)
+ alpha = alpha * z
+ --
+ cmd = readcardinal1(s)
+ while true do
+ local n
+ if cmd == 243 then
+ n = readcardinal1(s) + 1
+ elseif cmd == 244 then
+ n = readcardinal2(s) + 1
+ elseif cmd == 245 then
+ n = readcardinal3(s) + 1
+ elseif cmd == 246 then
+ n = readcardinal4(s) + 1
+ else
+ break
+ end
+ local checksum = skipbytes(s,4)
+ local size = scaled4()
+ local designsize = idiv(readcardinal4(s),16)
+ local pathlen = readcardinal1(s)
+ local namelen = readcardinal1(s)
+ local path = readstring(s,pathlen)
+ local name = readstring(s,namelen)
+ fonts[n] = { path = path, name = name, size = size }
+ cmd = readcardinal1(s)
+ end
+ local index = 0
+ while cmd and cmd <= 242 do
+ local width = 0
+ local length = 0
+ local checksum = 0
+ if cmd == 242 then
+ length = readcardinal4(s)
+ checksum = readcardinal4(s)
+ width = readcardinal4(s)
+ else
+ length = cmd
+ checksum = readcardinal1(s)
+ width = readcardinal3(s)
+ end
+ w, x, y, z, f = 0, 0, 0, 0, false
+ stack, result, r, p = { }, { }, 0, 0
+ while p < length do
+ local cmd = readcardinal1(s)
+ p = p + 1
+ actions[cmd]()
+ end
+ local glyph = glyphs[index]
+ if glyph then
+ glyph.width = width
+ glyph.commands = result
+ else
+ glyphs[index] = {
+ width = width,
+ commands = result,
+ }
+ end
+ index = index + 1
+ if #stack > 0 then
+ -- error: more pushes than pops
+ end
+ if packet_length ~= 0 then
+ -- error: invalid packet length
+ end
+ cmd = readcardinal1(s)
+ end
+ if readcardinal1(s) ~= 248 then
+ -- error: no post
+ end
+ s, result, r = nil, nil, nil
+ if data then
+ data.glyphs = data.glyphs or glyphs
+ data.fonts = data.fonts or fonts
+ return data
+ else
+ return {
+ name = file.nameonly(filename),
+ fontarea = file.pathpart(filename),
+ glyphs = glyphs,
+ designsize = designsize,
+ header = header,
+ fonts = fonts,
+ }
+ end
+ end
+
+ -- the replacement loader (not sparse):
+
+ function readers.loadtfmvf(tfmname,size)
+ local vfname = file.addsuffix(file.nameonly(tfmfile),"vf")
+ local tfmfile = tfmname
+ local vffile = resolvers.findbinfile(vfname,"ovf")
+ if tfmfile and tfmfile ~= "" then
+ if size < 0 then
+ size = idiv(65536 * -size,100)
+ end
+ local data = readers.loadtfm(tfmfile)
+ if data.error then
+ return data
+ end
+ if vffile and vffile ~= "" then
+ data = readers.loadvf(vffile,data)
+ if data.error then
+ return data
+ end
+ end
+ local designsize = data.designsize
+ local glyphs = data.glyphs
+ local parameters = data.parameters
+ local fonts = data.fonts
+ if size ~= designsize then
+ local factor = size / designsize
+ for index, glyph in next, glyphs do
+ if next(glyph) then
+ glyph.width = round(factor*glyph.width)
+ glyph.height = round(factor*glyph.height)
+ glyph.depth = round(factor*glyph.depth)
+ local italic = glyph.italic
+ if italic == 0 then
+ glyph.italic = nil
+ else
+ glyph.italic = round(factor*glyph.italic)
+ end
+ --
+ local kerns = glyph.kerns
+ if kerns then
+ for index, kern in next, kerns do
+ kerns[index] = round(factor*kern)
+ end
+ end
+ --
+ local commands = glyph.commands
+ if commands then
+ for i=1,#commands do
+ local c = commands[i]
+ local t = c[1]
+ if t == "down" or t == "right" then
+ c[2] = round(factor*c[2])
+ elseif t == "rule" then
+ c[2] = round(factor*c[2])
+ c[3] = round(factor*c[3])
+ end
+ end
+ end
+ else
+ glyphs[index] = nil
+ end
+ end
+ for i=2,30 do
+ local p = parameters[i]
+ if p then
+ parameters[i] = round(factor*p)
+ else
+ break
+ end
+ end
+ if fonts then
+ for k, v in next, fonts do
+ v.size = round(factor*v.size)
+ end
+ end
+ else
+ for index, glyph in next, glyphs do
+ if next(glyph) then
+ if glyph.italic == 0 then
+ glyph.italic = nil
+ end
+ else
+ glyphs[index] = nil
+ end
+ end
+ end
+ --
+ parameters.slant = parameters[1]
+ parameters.space = parameters[2]
+ parameters.spacestretch = parameters[3]
+ parameters.spaceshrink = parameters[4]
+ parameters.xheight = parameters[5]
+ parameters.quad = parameters[6]
+ parameters.extraspace = parameters[7]
+ --
+ for i=1,7 do
+ parameters[i] = nil -- so no danger for async
+ end
+ --
+ data.characters = glyphs
+ data.glyphs = nil
+ data.size = size
+ -- we assume type1 for now ... maybe the format should be unknown
+ data.filename = tfmfile -- file.replacesuffix(tfmfile,"pfb")
+ data.format = "unknown"
+ --
+ return data
+ end
+ end
+
+end
+
+-- inspect(readers.loadtfmvf(resolvers.findfile("mi-iwonari.tfm")))
+-- inspect(readers.loadtfm(resolvers.findfile("texnansi-palatinonova-regular.tfm")))
+-- inspect(readers.loadtfm(resolvers.findfile("cmex10.tfm")))
+-- inspect(readers.loadtfm(resolvers.findfile("cmr10.tfm")))
+-- local t = readers.loadtfmvf("texnansi-lte50019.tfm")
+-- inspect(t)
diff --git a/tex/context/base/mkxl/lang-dis.lmt b/tex/context/base/mkxl/lang-dis.lmt
index 5c4ab1e34..36fea59c0 100644
--- a/tex/context/base/mkxl/lang-dis.lmt
+++ b/tex/context/base/mkxl/lang-dis.lmt
@@ -205,7 +205,7 @@ local flatten = languages.flatten
nodes.handlers.flattenline = flatten
function nodes.handlers.flatten(head,where)
- if head and (where == "box" or where == "adjusted_hbox") then
+ if head and (where == "box" or where == "adjustedhbox") then
return flatten(head)
end
return head
diff --git a/tex/context/base/mkxl/lang-hyp.lmt b/tex/context/base/mkxl/lang-hyp.lmt
index 590528495..90823851e 100644
--- a/tex/context/base/mkxl/lang-hyp.lmt
+++ b/tex/context/base/mkxl/lang-hyp.lmt
@@ -1645,7 +1645,7 @@ featureset.hyphenonly = hyphenonly == v_yes
function hyphenators.handler(head,groupcode)
if usedmethod then
- if optimize and (groupcode == "hbox" or groupcode == "adjusted_hbox") then
+ if optimize and (groupcode == "hbox" or groupcode == "adjustedhbox") then
if getcount("hyphenstate") > 0 then
forced = false
return usedmethod(head)
diff --git a/tex/context/base/mkxl/math-act.lmt b/tex/context/base/mkxl/math-act.lmt
index 6183d073a..0ac497d57 100644
--- a/tex/context/base/mkxl/math-act.lmt
+++ b/tex/context/base/mkxl/math-act.lmt
@@ -110,7 +110,7 @@ end
function mathematics.checkaccentbaseheight(target,original)
local mathparameters = target.mathparameters
if mathparameters and mathparameters.AccentBaseHeight == 0 then
- mathparameters.AccentBaseHeight = target.parameters.x_height -- needs checking
+ mathparameters.AccentBaseHeight = target.parameters.xheight -- needs checking
end
end
@@ -565,11 +565,11 @@ end
-- local function fix(target,original,targetcharacters,unicode,factor)
-- local chardata = targetcharacters[unicode]
-- if chardata and factor then
--- local accent = chardata.top_accent
+-- local accent = chardata.topaccent
-- if not accent then
-- local width = chardata.width or 0
-- local accent = (tonumber(factor) and factor * width) or (factor and minint)
--- chardata.top_accent = accent
+-- chardata.topaccent = accent
-- if trace_tweaking then
-- report_tweak("fixing accent %U",target,original,unicode)
-- end
@@ -715,15 +715,15 @@ local function extensiblecode(font,unicode)
if not char then
return unknown
end
- if character.horiz_variants then
- if character.vert_variants then
+ if character.hvariants then
+ if character.vvariants then
return { e_mixed, code, character }
else
local m = char.mathextensible
local e = m and extensibles[m]
return e and { e, code, character } or unknown
end
- elseif character.vert_variants then
+ elseif character.vvariants then
local m = char.mathextensible
local e = m and extensibles[m]
return e and { e, code, character } or unknown
@@ -765,19 +765,19 @@ local function horizontalcode(family,unicode)
local loffset = 0
local roffset = 0
if kind == e_left then
- local charlist = data[3].horiz_variants
+ local charlist = data[3].hvariants
if charlist then
local left = charlist[1]
loffset = abs((left["start"] or 0) - (left["end"] or 0))
end
elseif kind == e_right then
- local charlist = data[3].horiz_variants
+ local charlist = data[3].hvariants
if charlist then
local right = charlist[#charlist]
roffset = abs((right["start"] or 0) - (right["end"] or 0))
end
elseif kind == e_horizontal then
- local charlist = data[3].horiz_variants
+ local charlist = data[3].hvariants
if charlist then
local left = charlist[1]
local right = charlist[#charlist]
diff --git a/tex/context/base/mkxl/math-dim.lmt b/tex/context/base/mkxl/math-dim.lmt
new file mode 100644
index 000000000..1bf2420bf
--- /dev/null
+++ b/tex/context/base/mkxl/math-dim.lmt
@@ -0,0 +1,249 @@
+if not modules then modules = { } end modules ['math-dim'] = {
+ version = 1.001,
+ comment = "companion to math-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- The radical_rule value is also used as a trigger. In luatex the accent
+-- placement happens either the opentype way (using topaccent cum suis) or the
+-- traditional way. In order to determine what method to use the \Umathradicalrule
+-- setting is consulted to determine what method to use. This is more efficient
+-- than analyzing the (potentially spread over multiple families) situation. For
+-- this reason we need to set the radical_rule here. It used to be "<unset>" in
+-- which case the engine takes the rulethickness. In c-speak:
+--
+-- int compat_mode = (radical_rule(cur_style) == undefined_math_parameter) ;
+--
+-- In the meantime things have been updated and we now have two code paths.
+
+local abs, next = math.abs, next
+
+local defaults = {
+ axis = { default = { "AxisHeight", "axisheight" }, },
+ accent_base_height = { default = { "AccentBaseHeight", "xheight" }, },
+ fraction_del_size = { default = { "FractionDelimiterSize", "delim2" },
+ cramped_display_style = { "FractionDelimiterDisplayStyleSize", "delim1" },
+ display_style = { "FractionDelimiterDisplayStyleSize", "delim1" }, },
+ fraction_denom_down = { default = { "FractionDenominatorShiftDown", "denom2" },
+ cramped_display_style = { "FractionDenominatorDisplayStyleShiftDown", "denom1" },
+ display_style = { "FractionDenominatorDisplayStyleShiftDown", "denom1" }, },
+ fraction_denom_vgap = { default = { "FractionDenominatorGapMin", "defaultrulethickness" },
+ cramped_display_style = { "FractionDenominatorDisplayStyleGapMin", "3*defaultrulethickness" },
+ display_style = { "FractionDenominatorDisplayStyleGapMin", "3*defaultrulethickness" }, },
+ fraction_num_up = { default = { "FractionNumeratorShiftUp", "num2" },
+ cramped_display_style = { "FractionNumeratorDisplayStyleShiftUp", "num1" },
+ display_style = { "FractionNumeratorDisplayStyleShiftUp", "num1" }, },
+ fraction_num_vgap = { default = { "FractionNumeratorGapMin", "defaultrulethickness" },
+ cramped_display_style = { "FractionNumeratorDisplayStyleGapMin", "3*defaultrulethickness" },
+ display_style = { "FractionNumeratorDisplayStyleGapMin", "3*defaultrulethickness" }, },
+ skewed_fraction_hgap = { default = { "SkewedFractionHorizontalGap", "mathquad/2" },
+ cramped_display_style = { "SkewedFractionHorizontalGap", "mathquad/2" },
+ display_style = { "SkewedFractionHorizontalGap", "mathquad/2" }, },
+ skewed_fraction_vgap = { default = { "SkewedFractionVerticalGap", "xheight" },
+ cramped_display_style = { "SkewedFractionVerticalGap", "xheight" },
+ display_style = { "SkewedFractionVerticalGap", "xheight" }, },
+ fraction_rule = { default = { "FractionRuleThickness", "defaultrulethickness" }, },
+ limit_above_bgap = { default = { "UpperLimitBaselineRiseMin", "bigopspacing3" }, },
+ limit_above_vgap = { default = { "UpperLimitGapMin", "bigopspacing1" }, },
+ limit_above_kern = { default = { "0", "bigopspacing5" }, },
+ limit_below_bgap = { default = { "LowerLimitBaselineDropMin", "bigopspacing4" }, },
+ limit_below_vgap = { default = { "LowerLimitGapMin", "bigopspacing2" }, },
+ limit_below_kern = { default = { "0", "bigopspacing5" }, },
+ math_operator_size = { default = { "DisplayOperatorMinHeight", "mathxheight*3" }, }, -- 2
+ overbar_kern = { default = { "OverbarExtraAscender", "defaultrulethickness" }, },
+ overbar_rule = { default = { "OverbarRuleThickness", "defaultrulethickness" }, },
+ overbar_vgap = { default = { "OverbarVerticalGap", "3*defaultrulethickness" }, },
+ quad = { default = { "fontsize(f)", "mathquad" }, },
+ radical_kern = { default = { "RadicalExtraAscender", "defaultrulethickness" }, },
+ radical_rule = { default = { "RadicalRuleThickness", "defaultrulethickness" }, },
+ -- default = { "surdheight(f)", "defaultrulethickness" },
+ radical_vgap = { default = { "RadicalVerticalGap", "defaultrulethickness+(abs(defaultrulethickness)/4)" },
+ display_style = { "RadicalDisplayStyleVerticalGap", "defaultrulethickness+(abs(mathxheight)/4)" }, },
+ space_after_script = { default = { "SpaceAfterScript", "scriptspace" }, },
+ space_before_script = { default = { "SpaceAfterScript", "scriptspace" }, },
+ stack_denom_down = { default = { "StackBottomShiftDown", "denom2" },
+ cramped_display_style = { "StackBottomDisplayStyleShiftDown", "denom1" },
+ display_style = { "StackBottomDisplayStyleShiftDown", "denom1" }, },
+ stack_num_up = { default = { "StackTopShiftUp", "num3" },
+ cramped_display_style = { "StackTopDisplayStyleShiftUp", "num1" },
+ display_style = { "StackTopDisplayStyleShiftUp", "num1" }, },
+ stack_vgap = { default = { "StackGapMin", "3*defaultrulethickness" },
+ cramped_display_style = { "StackDisplayStyleGapMin", "7*defaultrulethickness" },
+ display_style = { "StackDisplayStyleGapMin", "7*defaultrulethickness" }, },
+ sub_shift_down = { default = { "SubscriptShiftDown", "sub1" }, },
+ sub_shift_drop = { default = { "SubscriptBaselineDropMin", "subdrop" }, },
+ sub_sup_shift_down = { default = { "SubscriptShiftDown", "sub2" }, },
+ sub_top_max = { default = { "SubscriptTopMax", "abs(mathxheight*4)/5" }, },
+ subsup_vgap = { default = { "SubSuperscriptGapMin", "4*defaultrulethickness" }, },
+ sup_bottom_min = { default = { "SuperscriptBottomMin", "abs(mathxheight)/4" }, },
+ sup_shift_drop = { default = { "SuperscriptBaselineDropMax", "supdrop" }, },
+ sup_shift_up = { cramped_display_style = { "SuperscriptShiftUpCramped", "sup3" },
+ cramped_script_script_style = { "SuperscriptShiftUpCramped", "sup3" },
+ cramped_script_style = { "SuperscriptShiftUpCramped", "sup3" },
+ cramped_text_style = { "SuperscriptShiftUpCramped", "sup3" },
+ display_style = { "SuperscriptShiftUp", "sup1" },
+ script_script_style = { "SuperscriptShiftUp", "sup2" },
+ script_style = { "SuperscriptShiftUp", "sup2" },
+ text_style = { "SuperscriptShiftUp", "sup2" }, },
+ sup_sub_bottom_max = { default = { "SuperscriptBottomMaxWithSubscript", "abs(mathxheight*4)/5" }, },
+ underbar_kern = { default = { "UnderbarExtraDescender", "0" }, },
+ underbar_rule = { default = { "UnderbarRuleThickness", "defaultrulethickness" }, },
+ underbar_vgap = { default = { "UnderbarVerticalGap", "3*defaultrulethickness" }, },
+ connector_overlap_min = { default = { "MinConnectorOverlap", "0.25*defaultrulethickness" }, },
+ over_delimiter_vgap = { default = { "StretchStackGapBelowMin", "bigopspacing1" }, },
+ over_delimiter_bgap = { default = { "StretchStackTopShiftUp", "bigopspacing3" }, },
+ under_delimiter_vgap = { default = { "StretchStackGapAboveMin", "bigopspacing2" }, },
+ under_delimiter_bgap = { default = { "StretchStackBottomShiftDown", "bigopspacing4" }, },
+ radical_degree_before = { default = { "RadicalKernBeforeDegree", "(5/18)*quad" }, },
+ radical_degree_after = { default = { "RadicalKernAfterDegree", "(-10/18)*quad" }, },
+ radical_degree_raise = { default = { "RadicalDegreeBottomRaisePercent", "60" }, },
+ no_limit_sub_factor = { default = { "NoLimitSubFactor", "0" }, },
+ no_limit_sup_factor = { default = { "NoLimitSupFactor", "0" }, },
+}
+
+local styles = {
+ 'cramped_display_style',
+ 'cramped_script_script_style',
+ 'cramped_script_style',
+ 'cramped_text_style',
+ 'display_style',
+ 'script_script_style',
+ 'script_style',
+ 'text_style',
+}
+
+for k, v in next, defaults do
+ for _, s in next, styles do
+ if not v[s] then
+ v[s] = v.default
+ end
+ end
+end
+
+-- we cannot use a metatable because we do a copy (takes a bit more work)
+--
+-- local mt = { } setmetatable(defaults,mt)
+--
+-- mt.__index = function(t,s)
+-- return t.default or t.text_style or 0
+-- end
+
+function mathematics.dimensions(dimens) -- beware, dimens get spoiled
+ if dimens.SpaceAfterScript then
+ dimens.SubscriptShiftDownWithSuperscript = dimens.SubscriptShiftDown * 1.5 -- move this one
+ return table.fastcopy(dimens), { }
+ elseif dimens.AxisHeight or dimens.axisheight then
+ local t = { }
+ local mathxheight = dimens.xheight or 10*65536
+ local mathquad = dimens.quad or 10*65536
+ local defaultrulethickness = dimens.FractionDenominatorGapMin or dimens.defaultrulethickness or 0.4*65536
+ dimens["0"] = 0
+ dimens["60"] = 60
+ dimens["0.25*defaultrulethickness"] = defaultrulethickness / 4
+ dimens["3*defaultrulethickness"] = 3 * defaultrulethickness
+ dimens["4*defaultrulethickness"] = 4 * defaultrulethickness
+ dimens["7*defaultrulethickness"] = 7 * defaultrulethickness
+ dimens["(5/18)*quad"] = (mathquad * 5) / 18
+ dimens["(-10/18)*quad"] = - (mathquad * 10) / 18
+ dimens["mathxheight*3"] = mathxheight * 3 -- needs checking
+ dimens["abs(mathxheight*4)/5"] = abs(mathxheight * 4) / 5
+ dimens["defaultrulethickness+(abs(defaultrulethickness)/4)"] = defaultrulethickness+(abs(defaultrulethickness) / 4)
+ dimens["defaultrulethickness+(abs(mathxheight)/4)"] = defaultrulethickness+(abs(mathxheight) / 4)
+ dimens["abs(mathxheight)/4"] = abs(mathxheight) / 4
+ dimens["abs(mathxheight*4)/5"] = abs(mathxheight * 4) / 5
+ dimens["<not set>"] = false
+ dimens["script_space"] = false -- at macro level
+ for variable, styles in next, defaults do
+ local tt = { }
+ for style, default in next, styles do
+ local one = default[1]
+ local two = default[2]
+ local value = dimens[one]
+ if value then
+ tt[style] = value
+ else
+ value = dimens[two]
+ if value == false then
+ tt[style] = nil
+ else
+ tt[style] = value or 0
+ end
+ end
+ end
+ t[variable] = tt
+ end
+ local d = {
+ AccentBaseHeight = t . accent_base_height . text_style,
+ AxisHeight = t . axis . text_style,
+ -- DelimitedSubFormulaMinHeight
+ DisplayOperatorMinHeight = t . math_operator_size . text_style, -- no longer let tex decide (weird values)
+ -- FlattenedAccentBaseHeight
+ FractionDenominatorDisplayStyleGapMin = t . fraction_denom_vgap . display_style,
+ FractionDenominatorDisplayStyleShiftDown = t . fraction_denom_down . display_style,
+ FractionDenominatorGapMin = t . fraction_denom_vgap . text_style,
+ FractionDenominatorShiftDown = t . fraction_denom_down . text_style,
+ FractionNumeratorDisplayStyleGapMin = t . fraction_num_vgap . display_style,
+ FractionNumeratorDisplayStyleShiftUp = t . fraction_num_up . display_style,
+ FractionNumeratorGapMin = t . fraction_num_vgap . text_style,
+ FractionNumeratorShiftUp = t . fraction_num_up . text_style,
+ FractionRuleThickness = t . fraction_rule . text_style,
+ FractionDelimiterSize = t . fraction_del_size . text_style,
+ FractionDelimiterDisplayStyleSize = t . fraction_del_size . display_style,
+ LowerLimitBaselineDropMin = t . limit_below_bgap . text_style,
+ LowerLimitGapMin = t . limit_below_vgap . text_style,
+ -- MathLeading
+ MinConnectorOverlap = t . connector_overlap_min . text_style,
+ OverbarExtraAscender = t . overbar_kern . text_style,
+ OverbarRuleThickness = t . overbar_rule . text_style,
+ OverbarVerticalGap = t . overbar_vgap . text_style,
+ RadicalDisplayStyleVerticalGap = t . radical_vgap . display_style,
+ RadicalExtraAscender = t . radical_kern . text_style,
+ RadicalRuleThickness = t . radical_rule . text_style,
+ RadicalVerticalGap = t . radical_vgap . text_style,
+ RadicalKernBeforeDegree = t . radical_degree_before . display_style,
+ RadicalKernAfterDegree = t . radical_degree_after . display_style,
+ RadicalDegreeBottomRaisePercent = t . radical_degree_raise . display_style,
+ -- ScriptPercentScaleDown
+ -- ScriptScriptPercentScaleDown
+ -- SkewedFractionHorizontalGap
+ -- SkewedFractionVerticalGap
+ SpaceAfterScript = t . space_after_script . text_style,
+ StackBottomDisplayStyleShiftDown = t . stack_denom_down . display_style,
+ StackBottomShiftDown = t . stack_denom_down . text_style,
+ StackDisplayStyleGapMin = t . stack_vgap . display_style,
+ StackGapMin = t . stack_vgap . text_style,
+ StackTopDisplayStyleShiftUp = t . stack_num_up . display_style,
+ StackTopShiftUp = t . stack_num_up . text_style,
+ StretchStackGapBelowMin = t . over_delimiter_vgap . text_style,
+ StretchStackTopShiftUp = t . over_delimiter_bgap . text_style,
+ StretchStackGapAboveMin = t . under_delimiter_vgap . text_style,
+ StretchStackBottomShiftDown = t . under_delimiter_bgap . text_style,
+ SubSuperscriptGapMin = t . subsup_vgap . text_style,
+ SubscriptBaselineDropMin = t . sub_shift_drop . text_style,
+ SubscriptShiftDown = t . sub_shift_down . text_style,
+ SubscriptShiftDownWithSuperscript = t . sub_sup_shift_down . text_style,
+ SubscriptTopMax = t . sub_top_max . text_style,
+ SuperscriptBaselineDropMax = t . sup_shift_drop . text_style,
+ SuperscriptBottomMaxWithSubscript = t . sup_sub_bottom_max . text_style,
+ SuperscriptBottomMin = t . sup_bottom_min . text_style,
+ SuperscriptShiftUp = t . sup_shift_up . text_style,
+ SuperscriptShiftUpCramped = t . sup_shift_up . cramped_text_style,
+ UnderbarExtraDescender = t . underbar_kern . text_style,
+ UnderbarRuleThickness = t . underbar_rule . text_style,
+ UnderbarVerticalGap = t . underbar_vgap . text_style,
+ UpperLimitBaselineRiseMin = t . limit_above_bgap . text_style,
+ UpperLimitGapMin = t . limit_above_vgap . text_style,
+ }
+
+ -- too fragile for tx/px ... even the same values give different results
+ d.DisplayOperatorMinHeight = nil
+ --
+ d.AccentBaseHeight = 0 -- here? still?
+ return d, t -- t only for diagnostics
+ else
+ return { }, { }
+ end
+end
+
diff --git a/tex/context/base/mkxl/math-fbk.lmt b/tex/context/base/mkxl/math-fbk.lmt
index 32ad909f7..80b99d83b 100644
--- a/tex/context/base/mkxl/math-fbk.lmt
+++ b/tex/context/base/mkxl/math-fbk.lmt
@@ -297,10 +297,10 @@ local function accent_to_extensible(target,newchr,original,oldchr,height,depth,s
break
end
end
- local hv = olddata.horiz_variants
+ local hv = olddata.hvariants
if hv then
hv = fastcopy(hv)
- newdata.horiz_variants = hv
+ newdata.hvariants = hv
for i=1,#hv do
local hvi = hv[i]
local oldglyph = hvi.glyph
@@ -314,7 +314,7 @@ local function accent_to_extensible(target,newchr,original,oldchr,height,depth,s
}
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)
+ report_fallbacks("error in fallback: no valid hvariants, slot %X, index %i",oldglyph,i)
end
end
end
@@ -393,7 +393,7 @@ local function smashed(data,unicode,private)
local height = target.parameters.xheight / 2
local c, done = accent_to_extensible(target,private,data.original,unicode,height,0,nil,-height,unicode)
if done then
- c.top_accent = nil -- or maybe also all the others
+ c.topaccent = nil -- or maybe also all the others
end
return c
end
@@ -717,7 +717,7 @@ virtualcharacters[0x305] = function(data)
height = height,
depth = depth,
commands = { { "rule", height, width } },
- horiz_variants = {
+ hvariants = {
{
advance = width,
["end"] = used,
diff --git a/tex/context/base/mkxl/math-ini.lmt b/tex/context/base/mkxl/math-ini.lmt
index d199d5063..4ac76fa62 100644
--- a/tex/context/base/mkxl/math-ini.lmt
+++ b/tex/context/base/mkxl/math-ini.lmt
@@ -601,7 +601,7 @@ function mathematics.big(tfmdata,unicode,n,method)
local t = tfmdata.characters
local c = t[unicode]
if c and n > 0 then
- local vv = c.vert_variants or c.next and t[c.next].vert_variants
+ local vv = c.vvariants or c.next and t[c.next].vvariants
if vv then
local vvn = vv[n]
return vvn and vvn.glyph or vv[#vv].glyph or unicode
diff --git a/tex/context/base/mkxl/math-ini.mkxl b/tex/context/base/mkxl/math-ini.mkxl
index 3404e25f3..8ff839107 100644
--- a/tex/context/base/mkxl/math-ini.mkxl
+++ b/tex/context/base/mkxl/math-ini.mkxl
@@ -65,7 +65,7 @@
% test $[[\char948 \cldcontext{utf.char(948)}]]$
\registerctxluafile{math-ini}{autosuffix}
-\registerctxluafile{math-dim}{}
+\registerctxluafile{math-dim}{autosuffix}
\registerctxluafile{math-act}{autosuffix}
\registerctxluafile{math-ext}{}
\registerctxluafile{math-vfu}{autosuffix}
diff --git a/tex/context/base/mkxl/math-noa.lmt b/tex/context/base/mkxl/math-noa.lmt
index 025333699..66e8caade 100644
--- a/tex/context/base/mkxl/math-noa.lmt
+++ b/tex/context/base/mkxl/math-noa.lmt
@@ -197,19 +197,19 @@ local undernoad_code = noadcodes.under
local overnoad_code = noadcodes.over
local vcenternoad_code = noadcodes.vcenter
-local noad_code = nodecodes.noad -- attr nucleus sub sup
-local accent_code = nodecodes.accent -- attr nucleus sub sup accent
-local radical_code = nodecodes.radical -- attr nucleus sub sup left degree
-local fraction_code = nodecodes.fraction -- attr nucleus sub sup left right
-local subbox_code = nodecodes.subbox -- attr list
-local submlist_code = nodecodes.submlist -- attr list
-local mathchar_code = nodecodes.mathchar -- attr fam char
-local mathtextchar_code = nodecodes.mathtextchar -- attr fam char
-local delimiter_code = nodecodes.delimiter -- attr small_fam small_char large_fam large_char
------ style_code = nodecodes.style -- attr style
------ parameter_code = nodecodes.parameter -- attr style
-local math_choice = nodecodes.choice -- attr display text script scriptscript
-local fence_code = nodecodes.fence -- attr subtype
+local noad_code = nodecodes.noad
+local accent_code = nodecodes.accent
+local radical_code = nodecodes.radical
+local fraction_code = nodecodes.fraction
+local subbox_code = nodecodes.subbox
+local submlist_code = nodecodes.submlist
+local mathchar_code = nodecodes.mathchar
+local mathtextchar_code = nodecodes.mathtextchar
+local delimiter_code = nodecodes.delimiter
+----- style_code = nodecodes.style
+----- parameter_code = nodecodes.parameter
+local math_choice = nodecodes.choice
+local fence_code = nodecodes.fence
local leftfence_code = fencecodes.left
local middlefence_code = fencecodes.middle
@@ -316,8 +316,8 @@ local function process(start,what,n,parent)
noad = getsuppre (start) if noad then process(noad,what,n,start) end -- list
noad = getsubpre (start) if noad then process(noad,what,n,start) end -- list
end
- noad = getfield(start,"accent") if noad then process(noad,what,n,start) end -- list
- noad = getfield(start,"bot_accent") if noad then process(noad,what,n,start) end -- list
+ noad = getfield(start,"topaccent") if noad then process(noad,what,n,start) end -- list
+ noad = getfield(start,"botaccent") if noad then process(noad,what,n,start) end -- list
-- elseif id == style_code then
-- -- has a next
-- elseif id == parameter_code then
@@ -375,8 +375,8 @@ local function processnested(current,what,n)
noad = getsuppre (current) if noad then process(noad,what,n,current) end -- list
noad = getsubpre (current) if noad then process(noad,what,n,current) end -- list
end
- noad = getfield(current,"accent") if noad then process(noad,what,n,current) end -- list
- noad = getfield(current,"bot_accent") if noad then process(noad,what,n,current) end -- list
+ noad = getfield(current,"topaccent") if noad then process(noad,what,n,current) end -- list
+ noad = getfield(current,"botaccent") if noad then process(noad,what,n,current) end -- list
end
end
@@ -423,8 +423,8 @@ local function processstep(current,process,n,id)
noad = getsuppre (current) if noad then process(noad,n,current) end -- list
noad = getsubpre (current) if noad then process(noad,n,current) end -- list
end
- noad = getfield(current,"accent") if noad then process(noad,n,current) end -- list
- noad = getfield(current,"bot_accent") if noad then process(noad,n,current) end -- list
+ noad = getfield(current,"topaccent") if noad then process(noad,n,current) end -- list
+ noad = getfield(current,"botaccent") if noad then process(noad,n,current) end -- list
end
end
@@ -584,7 +584,7 @@ do
end
end
families[delimiter_code] = function(pointer)
- if getfield(pointer,"small_fam") == 0 then
+ if getfield(pointer,"smallfamily") == 0 then
local a = getattr(pointer,a_mathfamily)
if a and a > 0 then
setattr(pointer,a_mathfamily,0)
@@ -593,23 +593,23 @@ do
a = a - 3
end
local fam = getfontoffamily(a)
- local char = getfield(pointer,"small_char")
+ local char = getfield(pointer,"smallchar")
local okay = fontcharacters[fam][char]
if okay then
- setfield(pointer,"small_fam",a)
+ setfield(pointer,"smallfamily",a)
elseif a > 2 then
- setfield(pointer,"small_fam",a-3)
+ setfield(pointer,"smallfamily",a-3)
end
- local char = getfield(pointer,"large_char")
+ local char = getfield(pointer,"largechar")
local okay = fontcharacters[fam][char]
if okay then
- setfield(pointer,"large_fam",a)
+ setfield(pointer,"largefamily",a)
elseif a > 2 then
- setfield(pointer,"large_fam",a-3)
+ setfield(pointer,"largefamily",a-3)
end
else
- setfield(pointer,"small_fam",0)
- setfield(pointer,"large_fam",0)
+ setfield(pointer,"smallfamily",0)
+ setfield(pointer,"largefamily",0)
end
end
end
@@ -827,8 +827,8 @@ end
-- empty and no larger next will be forced)
--
-- beware: we don't use \delcode but \Udelcode and as such have
--- no large_fam; also, we need to check for subtype and/or
--- small_fam not being 0 because \. sits in 0,0 by default
+-- no largefamily; also, we need to check for subtype and/or
+-- smallfamily not being 0 because \. sits in 0,0 by default
--
-- todo: just replace the character by an ord noad
-- and remove the right delimiter as well
diff --git a/tex/context/base/mkxl/math-tag.lmt b/tex/context/base/mkxl/math-tag.lmt
index fa10c51c2..9ecc7047a 100644
--- a/tex/context/base/mkxl/math-tag.lmt
+++ b/tex/context/base/mkxl/math-tag.lmt
@@ -43,18 +43,18 @@ local nextnode = nuts.traversers.node
local nodecodes = nodes.nodecodes
-local noad_code = nodecodes.noad -- attr nucleus sub sup
-local accent_code = nodecodes.accent -- attr nucleus sub sup accent
-local radical_code = nodecodes.radical -- attr nucleus sub sup left degree
-local fraction_code = nodecodes.fraction -- attr nucleus sub sup left right
-local subbox_code = nodecodes.subbox -- attr list
-local submlist_code = nodecodes.submlist -- attr list
-local mathchar_code = nodecodes.mathchar -- attr fam char
-local mathtextchar_code = nodecodes.mathtextchar -- attr fam char
-local delimiter_code = nodecodes.delimiter -- attr small_fam small_char large_fam large_char
-local style_code = nodecodes.style -- attr style
-local choice_code = nodecodes.choice -- attr display text script scriptscript
-local fence_code = nodecodes.fence -- attr subtype
+local noad_code = nodecodes.noad
+local accent_code = nodecodes.accent
+local radical_code = nodecodes.radical
+local fraction_code = nodecodes.fraction
+local subbox_code = nodecodes.subbox
+local submlist_code = nodecodes.submlist
+local mathchar_code = nodecodes.mathchar
+local mathtextchar_code = nodecodes.mathtextchar
+local delimiter_code = nodecodes.delimiter
+local style_code = nodecodes.style
+local choice_code = nodecodes.choice
+local fence_code = nodecodes.fence
local accentcodes = nodes.accentcodes
local fencecodes = nodes.fencecodes
@@ -526,39 +526,39 @@ process = function(start) -- we cannot use the processor as we have no finalizer
stop_tagged()
end
elseif id == accent_code then
- local accent = getfield(start,"accent")
- local bot_accent = getfield(start,"bot_accent")
- if bot_accent then
- if accent then
+ local topaccent = getfield(start,"topaccent")
+ local botaccent = getfield(start,"botaccent")
+ if botaccent then
+ if topaccent then
setattr(start,a_tagged,start_tagged("munderover", {
accent = true,
- top = getunicode(accent),
- bottom = getunicode(bot_accent),
+ top = getunicode(topaccent),
+ bottom = getunicode(botaccent),
topfixed = subtype == fixedtopaccent_code or subtype == fixedbothaccent_code,
bottomfixed = subtype == fixedbottomaccent_code or subtype == fixedbothaccent_code,
}))
processsubsup(start)
- process(bot_accent)
- process(accent)
+ process(botaccent)
+ process(topaccent)
stop_tagged()
else
setattr(start,a_tagged,start_tagged("munder", {
accent = true,
- bottom = getunicode(bot_accent),
+ bottom = getunicode(botaccent),
bottomfixed = subtype == fixedbottomaccent_code or subtype == fixedbothaccent_code,
}))
processsubsup(start)
- process(bot_accent)
+ process(botaccent)
stop_tagged()
end
- elseif accent then
+ elseif topaccent then
setattr(start,a_tagged,start_tagged("mover", {
accent = true,
- top = getunicode(accent),
+ top = getunicode(topaccent),
topfixed = subtype == fixedtopaccent_code or subtype == fixedbothaccent_code,
}))
processsubsup(start)
- process(accent)
+ process(topaccent)
stop_tagged()
else
processsubsup(start)
diff --git a/tex/context/base/mkxl/math-vfu.lmt b/tex/context/base/mkxl/math-vfu.lmt
index 6584b0158..abe336f53 100644
--- a/tex/context/base/mkxl/math-vfu.lmt
+++ b/tex/context/base/mkxl/math-vfu.lmt
@@ -9,7 +9,9 @@ if not modules then modules = { } end modules ['math-vfu'] = {
-- All these math vectors .. thanks to Aditya and Mojca they become better and
-- better. If you have problems with math fonts or miss characters report it to the
-- ConTeXt mailing list. Also thanks to Boguslaw for finding a couple of errors.
--- This mechanism will eventually disappear.
+
+-- This mechanism will eventually disappear or at least needs to be updated to the
+-- way lmtx does virtual fonts.
-- 20D6 -> 2190
-- 20D7 -> 2192
@@ -83,7 +85,7 @@ local shared = { }
local function brace(main,characters,id,size,unicode,first,rule,left,right,rule,last)
if not characters[unicode] then
characters[unicode] = {
- horiz_variants = {
+ hvariants = {
{ extender = 0, glyph = first },
{ extender = 1, glyph = rule },
{ extender = 0, glyph = left },
@@ -121,7 +123,7 @@ local function extension(main,characters,id,size,unicode,first,middle,last)
if lw == 0 then
lw = 1
end
- chr.horiz_variants = {
+ chr.hvariants = {
{ extender = 0, glyph = first, ["end"] = fw/2, start = 0, advance = fw },
{ extender = 1, glyph = middle, ["end"] = mw/2, start = mw/2, advance = mw },
{ extender = 0, glyph = last, ["end"] = 0, start = lw/2, advance = lw },
@@ -131,7 +133,7 @@ end
local function parent(main,characters,id,size,unicode,first,rule,last)
if not characters[unicode] then
characters[unicode] = {
- horiz_variants = {
+ hvariants = {
{ extender = 0, glyph = first },
{ extender = 1, glyph = rule },
{ extender = 0, glyph = last },
@@ -150,7 +152,7 @@ local function make(main,characters,id,size,n,m)
local dnslot = 0xFF200 + n
local uprule = 0xFF300 + m
local dnrule = 0xFF400 + m
- local xu = main.parameters.x_height + 0.3*size
+ local xu = main.parameters.xheight + 0.3*size
local xd = 0.3*size
local w = c.width or 0
local h = c.height or 0
@@ -226,7 +228,7 @@ 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.xheight
local slot = { "slot", id_of_smaller, private }
local commands = {
push, upcommand[up], slot,
@@ -659,10 +661,10 @@ local function copy_glyph(main,target,original,unicode,slot)
break -- safeguard (when testing stuff)
end
end
- local hv = olddata.horiz_variants
+ local hv = olddata.hvariants
if hv then
hv = fastcopy(hv)
- newdata.horiz_variants = hv
+ newdata.hvariants = hv
for i=1,#hv do
local hvi = hv[i]
local oldglyph = hvi.glyph
@@ -677,10 +679,10 @@ local function copy_glyph(main,target,original,unicode,slot)
hvi.glyph = addprivate(main,formatters["M-H-%H"](oldglyph),newdata)
end
end
- local vv = olddata.vert_variants
+ local vv = olddata.vvariants
if vv then
vv = fastcopy(vv)
- newdata.vert_variants = vv
+ newdata.vvariants = vv
for i=1,#vv do
local vvi = vv[i]
local oldglyph = vvi.glyph
@@ -822,8 +824,8 @@ function vfmath.define(specification,set,goodies)
properties.fullname = fullname .. "-" .. unique
end
--
- if not parameters.x_height then
- parameters.x_height = 0
+ if not parameters.xheight then
+ parameters.xheight = 0
end
--
local already_reported = false
@@ -845,32 +847,33 @@ function vfmath.define(specification,set,goodies)
elseif not newparameters then
report_virtual("no parameters set in font %a",name)
elseif ss.extension then
- mathparameters.math_x_height = newparameters.x_height or 0 -- math_x_height : height of x
- mathparameters.default_rule_thickness = newparameters[ 8] or 0 -- default_rule_thickness : thickness of \over bars
- mathparameters.big_op_spacing1 = newparameters[ 9] or 0 -- big_op_spacing1 : minimum clearance above a displayed op
- mathparameters.big_op_spacing2 = newparameters[10] or 0 -- big_op_spacing2 : minimum clearance below a displayed op
- mathparameters.big_op_spacing3 = newparameters[11] or 0 -- big_op_spacing3 : minimum baselineskip above displayed op
- mathparameters.big_op_spacing4 = newparameters[12] or 0 -- big_op_spacing4 : minimum baselineskip below displayed op
- mathparameters.big_op_spacing5 = newparameters[13] or 0 -- big_op_spacing5 : padding above and below displayed limits
+ mathparameters.xheight = newparameters.xheight or 0 -- mathxheight : height of x
+ mathparameters.defaultrulethickness = newparameters[ 8] or 0 -- defaultrulethickness : thickness of \over bars
+ mathparameters.bigopspacing1 = newparameters[ 9] or 0 -- bigopspacing1 : minimum clearance above a displayed op
+ mathparameters.bigopspacing2 = newparameters[10] or 0 -- bigopspacing2 : minimum clearance below a displayed op
+ mathparameters.bigopspacing3 = newparameters[11] or 0 -- bigopspacing3 : minimum baselineskip above displayed op
+ mathparameters.bigopspacing4 = newparameters[12] or 0 -- bigopspacing4 : minimum baselineskip below displayed op
+ mathparameters.bigopspacing5 = newparameters[13] or 0 -- bigopspacing5 : padding above and below displayed limits
-- report_virtual("loading and virtualizing font %a at size %p, setting ex parameters",name,size)
elseif ss.parameters then
- mathparameters.x_height = newparameters.x_height or mathparameters.x_height
- mathparameters.x_height = mathparameters.x_height or fp.x_height or 0 -- x_height : height of x
- mathparameters.num1 = newparameters[ 8] or 0 -- num1 : numerator shift-up in display styles
- mathparameters.num2 = newparameters[ 9] or 0 -- num2 : numerator shift-up in non-display, non-\atop
- mathparameters.num3 = newparameters[10] or 0 -- num3 : numerator shift-up in non-display \atop
- mathparameters.denom1 = newparameters[11] or 0 -- denom1 : denominator shift-down in display styles
- mathparameters.denom2 = newparameters[12] or 0 -- denom2 : denominator shift-down in non-display styles
- mathparameters.sup1 = newparameters[13] or 0 -- sup1 : superscript shift-up in uncramped display style
- mathparameters.sup2 = newparameters[14] or 0 -- sup2 : superscript shift-up in uncramped non-display
- mathparameters.sup3 = newparameters[15] or 0 -- sup3 : superscript shift-up in cramped styles
- mathparameters.sub1 = newparameters[16] or 0 -- sub1 : subscript shift-down if superscript is absent
- mathparameters.sub2 = newparameters[17] or 0 -- sub2 : subscript shift-down if superscript is present
- mathparameters.sup_drop = newparameters[18] or 0 -- sup_drop : superscript baseline below top of large box
- mathparameters.sub_drop = newparameters[19] or 0 -- sub_drop : subscript baseline below bottom of large box
- mathparameters.delim1 = newparameters[20] or 0 -- delim1 : size of \atopwithdelims delimiters in display styles
- mathparameters.delim2 = newparameters[21] or 0 -- delim2 : size of \atopwithdelims delimiters in non-displays
- mathparameters.axis_height = newparameters[22] or 0 -- axis_height : height of fraction lines above the baseline
+ mathparameters.xheight = newparameters.xheight
+ or mathparameters.xheight
+ or fs.xheight or 0 -- xheight : height of x
+ mathparameters.num1 = newparameters[ 8] or 0 -- num1 : numerator shift-up in display styles
+ mathparameters.num2 = newparameters[ 9] or 0 -- num2 : numerator shift-up in non-display, non-\atop
+ mathparameters.num3 = newparameters[10] or 0 -- num3 : numerator shift-up in non-display \atop
+ mathparameters.denom1 = newparameters[11] or 0 -- denom1 : denominator shift-down in display styles
+ mathparameters.denom2 = newparameters[12] or 0 -- denom2 : denominator shift-down in non-display styles
+ mathparameters.sup1 = newparameters[13] or 0 -- sup1 : superscript shift-up in uncramped display style
+ mathparameters.sup2 = newparameters[14] or 0 -- sup2 : superscript shift-up in uncramped non-display
+ mathparameters.sup3 = newparameters[15] or 0 -- sup3 : superscript shift-up in cramped styles
+ mathparameters.sub1 = newparameters[16] or 0 -- sub1 : subscript shift-down if superscript is absent
+ mathparameters.sub2 = newparameters[17] or 0 -- sub2 : subscript shift-down if superscript is present
+ mathparameters.sup_drop = newparameters[18] or 0 -- sup_drop : superscript baseline below top of large box
+ mathparameters.sub_drop = newparameters[19] or 0 -- sub_drop : subscript baseline below bottom of large box
+ mathparameters.delim1 = newparameters[20] or 0 -- delim1 : size of \atopwithdelims delimiters in display styles
+ mathparameters.delim2 = newparameters[21] or 0 -- delim2 : size of \atopwithdelims delimiters in non-displays
+ mathparameters.axisheight = newparameters[22] or 0 -- axisheight : height of fraction lines above the baseline
-- report_virtual("loading and virtualizing font %a at size %p, setting sy parameters",name,size)
end
if ss.overlay then
@@ -941,13 +944,13 @@ function vfmath.define(specification,set,goodies)
local kerns = fci.kerns
local width = fci.width
local italic = fci.italic
--- if trace_virtual then
--- report_virtual("character %C uses index %H in vector %a for font %a, %s, %s",
--- unicode,index,vectorname,fontname,
--- kerns and "adding kerns" or "no kerns",
--- kerns and "adding italic" or "no italic"
--- )
--- end
+ -- if trace_virtual then
+ -- report_virtual("character %C uses index %H in vector %a for font %a, %s, %s",
+ -- unicode,index,vectorname,fontname,
+ -- kerns and "adding kerns" or "no kerns",
+ -- kerns and "adding italic" or "no italic"
+ -- )
+ -- end
if italic and italic > 0 then
-- int_a^b
if isextension then
@@ -976,7 +979,7 @@ function vfmath.define(specification,set,goodies)
if skewchar then
local k = kerns[skewchar]
if k then
- t.top_accent = width/2 + k
+ t.topaccent = width/2 + k
end
end
characters[unicode] = t
@@ -1014,30 +1017,30 @@ function vfmath.define(specification,set,goodies)
if n then
t.next = offset + n
elseif variants_done then
- local vv = fci.vert_variants
+ local vv = fci.vvariants
if vv then
- t.vert_variants = vv
+ t.vvariants = vv
end
- local hv = fci.horiz_variants
+ local hv = fci.hvariants
if hv then
- t.horiz_variants = hv
+ t.hvariants = hv
end
else
- local vv = fci.vert_variants
+ local vv = fci.vvariants
if vv then
for i=1,#vv do
local vvi = vv[i]
vvi.glyph = vvi.glyph + offset
end
- t.vert_variants = vv
+ t.vvariants = vv
end
- local hv = fci.horiz_variants
+ local hv = fci.hvariants
if hv then
for i=1,#hv do
local hvi = hv[i]
hvi.glyph = hvi.glyph + offset
end
- t.horiz_variants = hv
+ t.hvariants = hv
end
end
characters[offset + index] = t
diff --git a/tex/context/base/mkxl/node-aux.lmt b/tex/context/base/mkxl/node-aux.lmt
index 1aeae3b45..0c9bfc837 100644
--- a/tex/context/base/mkxl/node-aux.lmt
+++ b/tex/context/base/mkxl/node-aux.lmt
@@ -221,7 +221,7 @@ local function tonodes(str,fnt,attr) -- (str,template_glyph) -- moved from blob-
n = copy_node(space)
elseif fonts then -- depedency
local parameters = fonts.hashes.identifiers[fnt].parameters
- space = new_glue(parameters.space,parameters.space_stretch,parameters.space_shrink)
+ space = new_glue(parameters.space,parameters.spacestretch,parameters.spaceshrink)
n = space
end
elseif template then
@@ -354,8 +354,8 @@ end
do
local parcodes = nodes.parcodes
- local hmodepar_code = parcodes.hmode_par
- local vmodepar_code = parcodes.vmode_par
+ local hmodepar_code = parcodes.hmodepar
+ local vmodepar_code = parcodes.vmodepar
local getnest = tex.getnest
local getsubtype = nuts.getsubtype
diff --git a/tex/context/base/mkxl/node-pro.lmt b/tex/context/base/mkxl/node-pro.lmt
index bbcbc9bdc..f38e8280b 100644
--- a/tex/context/base/mkxl/node-pro.lmt
+++ b/tex/context/base/mkxl/node-pro.lmt
@@ -111,11 +111,6 @@ do
local lineactions = tasks.actions("contributers")
local adjustactions = tasks.actions("adjusters")
- -- contribute_head : pre_box
- -- pre_adjust_head : pre_adjust
- -- just_box : box
- -- post_adjust_head : adjust
-
-- this was the "contributers" callback but we changed the interface
-- historically we use a different order than the callback
@@ -133,7 +128,7 @@ do
end
end
end
- elseif where == "post_adjust" or where == "pre_adjust" then
+ elseif where == "postadjust" or where == "preadjust" then
-- we use the same order as for lines
return adjustactions(head,where,tail,index)
end
diff --git a/tex/context/base/mkxl/node-rul.lmt b/tex/context/base/mkxl/node-rul.lmt
index 8fa02cc89..0d1a9548e 100644
--- a/tex/context/base/mkxl/node-rul.lmt
+++ b/tex/context/base/mkxl/node-rul.lmt
@@ -341,8 +341,15 @@ local function flush_ruled(head,f,l,d,level,parent,strip) -- not that fast but a
end
end
+ local first = 1
+ local last = level
+
+ if extra then
+ first = level
+ end
+
if mp and mp ~= "" then
- for i=extra and level or 1,level do
+ for i=first,last do
local r = usernutrule {
width = wd,
height = ht,
@@ -369,7 +376,7 @@ local function flush_ruled(head,f,l,d,level,parent,strip) -- not that fast but a
l = hpack_nodes(l,wd,"exactly")
inject(l,wd,ht,dp)
else
- for i=extra and level or 1,level do
+ for i=first,last do
local hd = (offset+(i-1)*dy)*e - m
local ht = hd + rulethickness
local dp = -hd + rulethickness
diff --git a/tex/context/base/mkxl/node-ser.lmt b/tex/context/base/mkxl/node-ser.lmt
index c14a3826f..333784803 100644
--- a/tex/context/base/mkxl/node-ser.lmt
+++ b/tex/context/base/mkxl/node-ser.lmt
@@ -52,9 +52,9 @@ local canbeignored = {
}
local canbechar = {
- char = true,
- small_char = true,
- large_char = true,
+ char = true,
+ smallchar = true,
+ largechar = true,
}
local fieldtypes = table.setmetatableindex(function(t,k)
@@ -119,7 +119,7 @@ local function to_table(n,flat,verbose,noattributes,done)
for field, fieldtype in sortedhash(fields) do
local value = n[field]
if value then
- if fieldtype == "attribute_list" or fieldtype == "attribute" then
+ if fieldtype == "attributelist" or fieldtype == "attribute" or fieldtype == "attribute_list" then
if noattributes then
result[value] = canbeignored[value]
else
diff --git a/tex/context/base/mkxl/node-typ.lmt b/tex/context/base/mkxl/node-typ.lmt
new file mode 100644
index 000000000..c09fd5f67
--- /dev/null
+++ b/tex/context/base/mkxl/node-typ.lmt
@@ -0,0 +1,135 @@
+if not modules then modules = { } end modules ['node-typ'] = {
+ version = 1.001,
+ comment = "companion to node-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- code has been moved to blob-ini.lua
+
+local typesetters = nodes.typesetters or { }
+nodes.typesetters = typesetters
+
+local nuts = nodes.nuts
+local tonode = nuts.tonode
+local tonut = nuts.tonut
+
+local setlink = nuts.setlink
+local setchar = nuts.setchar
+local setattrlist = nuts.setattrlist
+
+local getfont = nuts.getfont
+
+local hpack_node_list = nuts.hpack
+local vpack_node_list = nuts.vpack
+local full_hpack_list = nuts.fullhpack
+
+local nodepool = nuts.pool
+local new_glyph = nodepool.glyph
+local new_glue = nodepool.glue
+
+local utfvalues = utf.values
+
+local currentfont = font.current
+local currentattributes = nodes.currentattributes
+local fontparameters = fonts.hashes.parameters
+
+-- when attrid == true then take from glyph or current else use the given value
+
+-- todo: glyphscale etc
+
+local function tonodes(str,fontid,spacing,templateglyph,attrid) -- quick and dirty
+ local head, prev = nil, nil
+ if not fontid then
+ fontid = templateglyph and getfont(templateglyph) or currentfont()
+ end
+ if attrid == true then
+ if templateglyph then
+ attrid = false -- we copy with the glyph
+ else
+ attrid = currentattributes()
+ end
+ end
+ local fp = fontparameters[fontid]
+ local s, p, m
+ if spacing then
+ s, p, m = spacing, 0, 0
+ else
+ s, p, m = fp.space, fp.spacestretch, fp.spaceshrink
+ end
+ local spacedone = false
+ for c in utfvalues(str) do
+ local next
+ if c == 32 then
+ if not spacedone then
+ next = new_glue(s,p,m)
+ spacedone = true
+ end
+ elseif templateglyph then
+ next = copy_glyph(templateglyph)
+ setchar(next,c)
+ spacedone = false
+ else
+ next = new_glyph(fontid or 1,c)
+ spacedone = false
+ end
+ if not next then
+ -- nothing
+ elseif not head then
+ if attrid then
+ setattrlist(next,attrid)
+ end
+ head = next
+ else
+ if attrid then
+ setattrlist(next,attrid)
+ end
+ setlink(prev,next)
+ end
+ prev = next
+ end
+ return head
+end
+
+local function tohpack(str,fontid,spacing)
+ return hpack_node_list(tonodes(str,fontid,spacing),"exactly")
+end
+
+local function tohbox(str,fontid,spacing)
+ return full_hpack_list(tonodes(str,fontid,spacing),"exactly")
+end
+
+local function tovpack(str,fontid,spacing)
+ -- vpack is just a hack, and a proper implementation is on the agenda
+ -- as it needs more info etc than currently available
+ return vpack_node_list(tonodes(str,fontid,spacing))
+end
+
+local tovbox = tovpack -- for now no vpack filter
+
+local tnuts = { }
+nuts.typesetters = tnuts
+
+tnuts.tonodes = tonodes
+tnuts.tohpack = tohpack
+tnuts.tohbox = tohbox
+tnuts.tovpack = tovpack
+tnuts.tovbox = tovbox
+
+typesetters.tonodes = function(...) local h, b = tonodes(...) return tonode(h), b end
+typesetters.tohpack = function(...) local h, b = tohpack(...) return tonode(h), b end
+typesetters.tohbox = function(...) local h, b = tohbox (...) return tonode(h), b end
+typesetters.tovpack = function(...) local h, b = tovpack(...) return tonode(h), b end
+typesetters.tovbox = function(...) local h, b = tovbox (...) return tonode(h), b end
+
+typesetters.hpack = typesetters.tohpack -- obsolete
+typesetters.hbox = typesetters.tohbox -- obsolete
+typesetters.vpack = typesetters.tovpack -- obsolete
+
+-- context(nodes.typesetters.tohpack("Hello World!"))
+-- context(nodes.typesetters.tohbox ("Hello World!"))
+-- context(nodes.typesetters.tohpack("Hello World!",1,100*1024*10))
+-- context(nodes.typesetters.tohbox ("Hello World!",1,100*1024*10))
+
+string.tonodes = function(...) return tonode(tonodes(...)) end -- quite convenient
diff --git a/tex/context/base/mkxl/page-ini.lmt b/tex/context/base/mkxl/page-ini.lmt
index ef34687c6..ec2278c01 100644
--- a/tex/context/base/mkxl/page-ini.lmt
+++ b/tex/context/base/mkxl/page-ini.lmt
@@ -361,10 +361,10 @@ implement {
-- usage = "value",
-- actions = function()
-- local result = 0
--- if nodes.nuts.getspeciallist("contribute_head") then
+-- if nodes.nuts.getspeciallist("contributehead") then
-- result = result | 1
-- end
--- if nodes.nuts.getspeciallist("page_head") then
+-- if nodes.nuts.getspeciallist("pagehead") then
-- result = result | 2
-- end
-- return tokens.values.integer, result
diff --git a/tex/context/base/mkxl/scrn-ref.lmt b/tex/context/base/mkxl/scrn-ref.lmt
new file mode 100644
index 000000000..be298e2d1
--- /dev/null
+++ b/tex/context/base/mkxl/scrn-ref.lmt
@@ -0,0 +1,57 @@
+if not modules then modules = { } end modules ['scrn-ref'] = {
+ version = 1.001,
+ comment = "companion to scrn-int.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+interactions = interactions or { }
+interactions.references = interactions.references or { }
+local references = interactions.references
+
+local codeinjections = backends.codeinjections
+
+local identify = structures.references.identify
+
+local implement = interfaces.implement
+
+local function check(what)
+ if what and what ~= "" then
+ local set, bug = identify("",what)
+ return not bug and #set > 0 and set
+ end
+end
+
+function references.setopendocumentaction(open)
+ local opendocument = check(open)
+ if opendocument then
+ codeinjections.registerdocumentopenaction(opendocument)
+ end
+end
+
+function references.setclosedocumentaction(close)
+ local closedocument = check(close)
+ if closedocument then
+ codeinjections.registerdocumentcloseaction(closedocument)
+ end
+end
+
+function references.setopenpageaction(open)
+ local openpage = check(open)
+ if openpage then
+ codeinjections.registerpageopenaction(openpage)
+ end
+end
+
+function references.setclosepageaction(close)
+ local closepage = check(close)
+ if closepage then
+ codeinjections.registerpagecloseaction(closepage)
+ end
+end
+
+implement { name = "setopendocumentaction", arguments = "string", actions = references.setopendocumentaction }
+implement { name = "setclosedocumentaction", arguments = "string", actions = references.setclosedocumentaction }
+implement { name = "setopenpageaction", arguments = "string", actions = references.setopenpageaction }
+implement { name = "setclosepageaction", arguments = "string", actions = references.setclosepageaction }
diff --git a/tex/context/base/mkxl/scrn-ref.mklx b/tex/context/base/mkxl/scrn-ref.mklx
index d6fc6e127..ffe1fab16 100644
--- a/tex/context/base/mkxl/scrn-ref.mklx
+++ b/tex/context/base/mkxl/scrn-ref.mklx
@@ -13,7 +13,7 @@
\writestatus{loading}{ConTeXt Screen Macros / References}
-\registerctxluafile{scrn-ref}{}
+\registerctxluafile{scrn-ref}{autosuffix}
\unprotect
diff --git a/tex/context/base/mkxl/scrp-ini.lmt b/tex/context/base/mkxl/scrp-ini.lmt
index b71a530a2..a8856f148 100644
--- a/tex/context/base/mkxl/scrp-ini.lmt
+++ b/tex/context/base/mkxl/scrp-ini.lmt
@@ -871,8 +871,8 @@ do
if lastfont ~= font then
local pf = parameters[font]
space = pf.space
- stretch = pf.space_stretch
- shrink = pf.space_shrink
+ stretch = pf.spacestretch
+ shrink = pf.spaceshrink
lastfont = font
end
return new_glue(
diff --git a/tex/context/base/mkxl/spac-chr.lmt b/tex/context/base/mkxl/spac-chr.lmt
index e38f2a30e..554dc0400 100644
--- a/tex/context/base/mkxl/spac-chr.lmt
+++ b/tex/context/base/mkxl/spac-chr.lmt
@@ -131,7 +131,7 @@ local function nbsp(head,current)
if attr >= 1 and attr <= 3 then -- flushright
head, current = inject_nobreak_space(0x00A0,head,current,para.space,0,0)
else
- head, current = inject_nobreak_space(0x00A0,head,current,para.space,para.space_stretch,para.space_shrink)
+ head, current = inject_nobreak_space(0x00A0,head,current,para.space,para.spacestretch,para.spaceshrink)
end
setsubtype(current,spaceskip_code)
return head, current
@@ -190,7 +190,7 @@ local methods = {
head, current = remove_node(head,current,true)
if not is_punctuation[char] then
local p = fontparameters[font]
- head, current = insertnodebefore(head,current,new_glue(p.space,p.space_stretch,p.space_shrink))
+ head, current = insertnodebefore(head,current,new_glue(p.space,p.spacestretch,p.spaceshrink))
end
end
end
diff --git a/tex/context/base/mkxl/spac-prf.lmt b/tex/context/base/mkxl/spac-prf.lmt
index 2223c7730..c38cdc97b 100644
--- a/tex/context/base/mkxl/spac-prf.lmt
+++ b/tex/context/base/mkxl/spac-prf.lmt
@@ -269,9 +269,9 @@ end
profiling.get = getprofile
local function getpagelist()
- local pagehead = texlists.page_head
+ local pagehead = texlists.pagehead
if pagehead then
- pagehead = tonut(texlists.page_head)
+ pagehead = tonut(texlists.pagehead)
pagetail = find_node_tail(pagehead)
else
pagetail = nil
diff --git a/tex/context/base/mkxl/spac-ver.lmt b/tex/context/base/mkxl/spac-ver.lmt
index ca0544cf8..fcb1b7e7f 100644
--- a/tex/context/base/mkxl/spac-ver.lmt
+++ b/tex/context/base/mkxl/spac-ver.lmt
@@ -1054,7 +1054,7 @@ end
-- implementation
--- alignment box begin_of_par vmode_par hmode_par insert penalty before_display after_display
+-- alignment box begin_of_par vmodepar hmodepar insert penalty before_display after_display
function vspacing.snapbox(n,how)
local sv = snapmethods[how]
@@ -1440,7 +1440,7 @@ do
-- quit, we're not on the mvl
else
-- inefficient when we're at the end of a page
- local c = tonut(texlists.page_head)
+ local c = tonut(texlists.pagehead)
while c and c ~= n do
local id = getid(c)
if id == hlist_code then
@@ -1486,7 +1486,7 @@ do
--
local function getpagelist()
if not pagehead then
- pagehead = texlists.page_head
+ pagehead = texlists.pagehead
if pagehead then
pagehead = tonut(pagehead)
pagetail = find_node_tail(pagehead) -- no texlists.page_tail yet-- no texlists.page_tail yet
@@ -2263,7 +2263,7 @@ do
function vspacing.getnofpreviouslines(head)
if enabled then
if not thead then
- head = texlists.page_head
+ head = texlists.pagehead
end
local noflines = 0
if head then
@@ -2314,7 +2314,7 @@ do
if trace then
local newdepth = outer.prevdepth
local olddepth = newdepth
- if not texlists.page_head then
+ if not texlists.pagehead then
newdepth = ignoredepth
texset("prevdepth",ignoredepth)
outer.prevdepth = ignoredepth
@@ -2322,7 +2322,7 @@ do
report("page %i, prevdepth %p => %p",texgetcount("realpageno"),olddepth,newdepth)
-- report("list %s",nodes.idsandsubtypes(head))
else
- if not texlists.page_head then
+ if not texlists.pagehead then
texset("prevdepth",ignoredepth)
outer.prevdepth = ignoredepth
end
@@ -2353,7 +2353,7 @@ do
end
nest.prevdepth = depth
elseif id == temp_code and texgetnest("ptr") == 0 then
- local head = texgetlist("page_head")
+ local head = texgetlist("pagehead")
if head then
tail = getnodetail(head)
if tail and tail.id == hlist_code then
@@ -2472,11 +2472,11 @@ do
-- check if in mvl
if texgetnest("ptr") == 0 then
-- this flushes the contributions
- while getspeciallist("contribute_head") do
+ while getspeciallist("contributehead") do
triggerbuildpage()
end
-- now we consult the last line (if present)
- local head, tail = getspeciallist("page_head")
+ local head, tail = getspeciallist("pagehead")
if tail then
for n, id, subtype in treversenode, tail do
if id == hlist_code then
@@ -2521,7 +2521,7 @@ do
-- interfaces.implement {
-- name = "removelastline",
-- actions = function()
- -- local h, t = getspeciallist("page_head")
+ -- local h, t = getspeciallist("pagehead")
-- if t and getid(t) == hlist_code and getsubtype(t) == line_code then
-- local total = gettotal(t)
-- h = remove_node(h,t,true)
@@ -2663,10 +2663,10 @@ do
-- interfaces.implement {
-- name = "fakenextstrutline",
-- actions = function()
- -- local head = texlists.page_head
+ -- local head = texlists.pagehead
-- if head then
-- local head = remove_node(head,find_node_tail(head),true)
- -- texlists.page_head = head
+ -- texlists.pagehead = head
-- buildpage()
-- end
-- end
@@ -2675,13 +2675,13 @@ do
implement {
name = "removelastline",
actions = function()
- local head = texlists.page_head
+ local head = texlists.pagehead
if head then
local tail = find_node_tail(head)
if tail then
-- maybe check for hlist subtype 1
local head = remove_node(head,tail,true)
- texlists.page_head = head
+ texlists.pagehead = head
buildpage()
end
end
@@ -2691,7 +2691,7 @@ do
implement {
name = "showpagelist", -- will improve
actions = function()
- local head = texlists.page_head
+ local head = texlists.pagehead
if head then
print("start")
while head do
diff --git a/tex/context/base/mkxl/supp-box.lmt b/tex/context/base/mkxl/supp-box.lmt
index 03bb54137..8a290b5ae 100644
--- a/tex/context/base/mkxl/supp-box.lmt
+++ b/tex/context/base/mkxl/supp-box.lmt
@@ -757,9 +757,9 @@ end
implement {
name = "lastlinewidth",
actions = function()
- local head = tex.lists.page_head
+ local head = tex.lists.pagehead
-- list dimensions returns 3 value but we take the first
- context(head and getdimensions(getlist(find_tail(tonut(tex.lists.page_head)))) or 0)
+ context(head and getdimensions(getlist(find_tail(tonut(tex.lists.pagehead)))) or 0)
end
}
diff --git a/tex/context/base/mkxl/trac-jus.lmt b/tex/context/base/mkxl/trac-jus.lmt
new file mode 100644
index 000000000..e9c8fac28
--- /dev/null
+++ b/tex/context/base/mkxl/trac-jus.lmt
@@ -0,0 +1,122 @@
+if not modules then modules = { } end modules ['trac-jus'] = {
+ version = 1.001,
+ comment = "companion to trac-jus.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local checkers = typesetters.checkers or { }
+typesetters.checkers = checkers
+
+----- report_justification = logs.reporter("visualize","justification")
+
+local a_alignstate = attributes.private("alignstate")
+local a_justification = attributes.private("justification")
+
+local nuts = nodes.nuts
+
+local getfield = nuts.getfield
+local getlist = nuts.getlist
+local getattr = nuts.getattr
+local setattr = nuts.setattr
+local setlist = nuts.setlist
+local setlink = nuts.setlink
+local getwidth = nuts.getwidth
+local findtail = nuts.tail
+
+local nexthlist = nuts.traversers.hlist
+
+local getdimensions = nuts.dimensions
+local copylist = nuts.copylist
+
+local tracedrule = nodes.tracers.pool.nuts.rule
+
+local nodepool = nuts.pool
+
+local new_hlist = nodepool.hlist
+local new_kern = nodepool.kern
+
+local hlist_code = nodes.nodecodes.hlist
+
+local texsetattribute = tex.setattribute
+local unsetvalue = attributes.unsetvalue
+
+local enableaction = nodes.tasks.enableaction
+
+local min_threshold = 0
+local max_threshold = 0
+
+local function set(n)
+ enableaction("mvlbuilders", "typesetters.checkers.handler")
+ enableaction("vboxbuilders","typesetters.checkers.handler")
+ texsetattribute(a_justification,n or 1)
+ function typesetters.checkers.set(n)
+ texsetattribute(a_justification,n or 1)
+ end
+end
+
+local function reset()
+ texsetattribute(a_justification,unsetvalue)
+end
+
+checkers.set = set
+checkers.reset = reset
+
+interfaces.implement {
+ name = "showjustification",
+ actions = set
+}
+
+trackers.register("visualizers.justification", function(v)
+ if v then
+ set(1)
+ else
+ reset()
+ end
+end)
+
+function checkers.handler(head)
+ for current in nexthlist, head do
+ if getattr(current,a_justification) == 1 then
+ setattr(current,a_justification,0) -- kind of reset
+ local width = getwidth(current)
+ if width > 0 then
+ local list = getlist(current)
+ if list then
+ local naturalwidth, naturalheight, naturaldepth = getdimensions(list)
+ local delta = naturalwidth - width
+ if naturalwidth == 0 or delta == 0 then
+ -- special box
+ elseif delta >= max_threshold then
+ local rule = new_hlist(tracedrule(delta,naturalheight,naturaldepth,getfield(list,"glueset") == 1 and "trace:dr" or "trace:db"))
+ setlink(findtail(list),rule)
+ setlist(current,list)
+ elseif delta <= min_threshold then
+ local alignstate = getattr(list,a_alignstate)
+ if alignstate == 1 then
+ local rule = new_hlist(tracedrule(-delta,naturalheight,naturaldepth,"trace:dc"))
+ setlink(rule,list)
+ setlist(current,rule)
+ elseif alignstate == 2 then
+ local lrule = new_hlist(tracedrule(-delta/2,naturalheight,naturaldepth,"trace:dy"))
+ local rrule = copylist(lrule)
+ setlink(lrule,list)
+ setlink(findtail(list),new_kern(delta/2),rrule)
+ setlist(current,lrule)
+ elseif alignstate == 3 then
+ local rule = new_hlist(tracedrule(-delta,naturalheight,naturaldepth,"trace:dm"))
+ setlink(findtail(list),new_kern(delta),rule)
+ setlist(current,list)
+ else
+ local rule = new_hlist(tracedrule(-delta,naturalheight,naturaldepth,"trace:dg"))
+ setlink(findtail(list),new_kern(delta),rule)
+ setlist(current,list)
+ end
+ end
+ end
+ end
+ end
+ end
+ return head
+end
diff --git a/tex/context/base/mkxl/trac-jus.mkxl b/tex/context/base/mkxl/trac-jus.mkxl
index 3375e5ee7..387478cb1 100644
--- a/tex/context/base/mkxl/trac-jus.mkxl
+++ b/tex/context/base/mkxl/trac-jus.mkxl
@@ -13,7 +13,7 @@
\writestatus{loading}{ConTeXt Tracing Macros / Justification}
-\registerctxluafile{trac-jus}{}
+\registerctxluafile{trac-jus}{autosuffix}
\unprotect
diff --git a/tex/context/base/mkxl/typo-adj.lmt b/tex/context/base/mkxl/typo-adj.lmt
index 53abe4f1d..31a2c2c78 100644
--- a/tex/context/base/mkxl/typo-adj.lmt
+++ b/tex/context/base/mkxl/typo-adj.lmt
@@ -52,7 +52,7 @@ local postactions = {
}
-- function nodes.handlers.adjusters(head,where,tail)
--- if where == "pre_adjust" then
+-- if where == "preadjust" then
-- local a = getattr(tail,a_adjuster)
-- if a then
-- a = preactions[a]
@@ -60,7 +60,7 @@ local postactions = {
-- head = a(head,tail)
-- end
-- end
--- elseif where == "post_adjust" then
+-- elseif where == "postadjust" then
-- local a = getattr(tail,a_adjuster)
-- if a then
-- a = postactions[a]
@@ -75,12 +75,12 @@ local postactions = {
-- end
function nodes.handlers.adjusters(head,where,tail,index)
- if where == "pre_adjust" then
+ if where == "preadjust" then
local a = preactions[index]
if a then
head = a(head,tail)
end
- else -- if where == "post_adjust" then
+ else -- if where == "postadjust" then
local a = postactions[index]
if a then
head = a(head,tail)
diff --git a/tex/context/base/mkxl/typo-bld.lmt b/tex/context/base/mkxl/typo-bld.lmt
index 31cc0bb59..9c83adede 100644
--- a/tex/context/base/mkxl/typo-bld.lmt
+++ b/tex/context/base/mkxl/typo-bld.lmt
@@ -231,10 +231,10 @@ end
-- the check can go away
-- Todo: contrib_head can be any head (kind of) not per se the page one so maybe I will
--- intercept that in the engine with page_contribute_head or so.
+-- intercept that in the engine with contributehead or so.
function builders.buildpage_filter(groupcode)
- local head = texlists.contribute_head
+ local head = texlists.contributehead
if head then
local done = false
-- called quite often ... maybe time to remove timing
@@ -246,8 +246,8 @@ function builders.buildpage_filter(groupcode)
stoptiming(builders)
-- -- doesn't work here (not passed on?)
-- texset("pagegoal,texget("vsize") - texgetdimen("d_page_floats_inserted_top") - texgetdimen("d_page_floats_inserted_bottom")
- texlists.contribute_head = head or nil -- needs checking
- -- tex.setlist("contribute_head",head,head and nodes.tail(head))
+ texlists.contributehead = head or nil -- needs checking
+ -- tex.setlist("contributehead",head,head and nodes.tail(head))
return done and head or true -- no return value needed
else
-- happens quite often
diff --git a/tex/context/base/mkxl/typo-krn.lmt b/tex/context/base/mkxl/typo-krn.lmt
index 450194767..bfd50062d 100644
--- a/tex/context/base/mkxl/typo-krn.lmt
+++ b/tex/context/base/mkxl/typo-krn.lmt
@@ -207,7 +207,7 @@ local function kern_injector(fillup,kern)
if fillup then
local g = new_glue(kern)
setfield(g,"stretch",kern)
- setfield(g,"stretch_order",1)
+ setfield(g,"stretchorder",1)
return g
else
return new_kern(kern)
@@ -538,7 +538,7 @@ function kerns.handler(head)
elseif id == glue_code then
local subtype = getsubtype(start)
if subtype == userskip_code or subtype == xspaceskip_code or subtype == spaceskip_code then
- local width, stretch, shrink, stretch_order, shrink_order = getglue(start)
+ local width, stretch, shrink, stretchorder, shrinkorder = getglue(start)
if width > 0 then
local w = width + gluefactor * width * krn
stretch = stretch * w / width
@@ -546,10 +546,10 @@ function kerns.handler(head)
if fillup then
stretch = 2 * stretch
shrink = 2 * shrink
- stretch_order = 1
- -- shrink_order = 1 ?
+ stretchorder = 1
+ -- shrinkorder = 1 ?
end
- setglue(start,w,stretch,shrink,stretch_order,shrink_order)
+ setglue(start,w,stretch,shrink,stretchorder,shrinkorder)
end
end
bound = false
diff --git a/tex/context/base/mkxl/typo-mar.lmt b/tex/context/base/mkxl/typo-mar.lmt
index f8c135fa7..b590c9ecf 100644
--- a/tex/context/base/mkxl/typo-mar.lmt
+++ b/tex/context/base/mkxl/typo-mar.lmt
@@ -806,7 +806,7 @@ local function flushed(scope,parent) -- current is hlist
return done, continue
end
--- only when group : vbox|vmode_par
+-- only when group : vbox|vmodepar
-- only when subtype : line, box (no indent alignment cell)
local function handler(scope,head,group)
@@ -884,9 +884,9 @@ function margins.globalhandler(head,group) -- check group
report_margindata("ignored 1, group %a, stored %s, inhibit %a",group,nofstored,inhibit)
end
return head
- elseif group == "hmode_par" then
+ elseif group == "hmodepar" then
return handler(v_global,head,group)
- elseif group == "vmode_par" then -- experiment (for alignments)
+ elseif group == "vmodepar" then -- experiment (for alignments)
return handler(v_global,head,group)
-- this needs checking as we then get quite some one liners to process and
-- we cannot look ahead then:
diff --git a/tex/context/base/mkxl/typo-par.mkxl b/tex/context/base/mkxl/typo-par.mkxl
index 22450e76e..077d3566c 100644
--- a/tex/context/base/mkxl/typo-par.mkxl
+++ b/tex/context/base/mkxl/typo-par.mkxl
@@ -24,7 +24,7 @@
\unprotect
%registerctxluafile{node-ltp}{optimize}
-\registerctxluafile{node-ltp}{}
+\registerctxluafile{node-ltp}{autosuffix} % this one has to be updated!
\registerctxluafile{trac-par}{}
\registerctxluafile{typo-par}{}
diff --git a/tex/context/fonts/mkiv/type-imp-adobegaramond.mkiv b/tex/context/fonts/mkiv/type-imp-adobegaramond.mkiv
new file mode 100644
index 000000000..88ad5ed2c
--- /dev/null
+++ b/tex/context/fonts/mkiv/type-imp-adobegaramond.mkiv
@@ -0,0 +1,42 @@
+%D \module
+%D [ file=type-imp-adobegaramond,
+%D version=2021.10.30,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Adobe Garamond,
+%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.
+
+
+\starttypescriptcollection[adobegaramond]
+
+ \starttypescript [\s!serif] [adobegaramond] [\s!name]
+ \setups[font:fallback:serif]
+ \definefontsynonym [\s!Serif] [\s!file:AGaramondPro-Regular]
+ \definefontsynonym [\s!SerifItalic] [\s!file:AGaramondPro-Italic]
+ \definefontsynonym [\s!SerifBold] [\s!file:AGaramondPro-Semibold]
+ \stoptypescript
+
+ \starttypescript [\s!sans] [frutiger] [\s!name]
+ \setups[font:fallback:sans]
+ \definefontsynonym [\s!Sans] [\s!file:FrutigerLTStd-Roman]
+ \definefontsynonym [\s!SansItalic] [\s!file:FrutigerLTStd-Italic]
+ \definefontsynonym [\s!SansBold] [\s!file:FrutigerLTStd-Bold]
+ \stoptypescript
+
+ \starttypescript [\s!math] [garamond-math] [\s!name]
+ \loadfontgoodies[garamond-math]
+ \definefontsynonym [\s!MathRoman] [\s!file:garamond-math.otf] [\s!features={\s!math\mathsizesuffix,mathextra},\s!goodies=garamond-math]
+ \stoptypescript
+
+ \starttypescript[adobegaramond]
+ \definetypeface [adobegaramond] [\s!rm] [\s!serif] [adobegaramond] [\s!default]
+ \definetypeface [adobegaramond] [\s!ss] [\s!sans] [frutiger] [\s!default] [\s!rscale=0.85]
+ \definetypeface [adobegaramond] [\s!mm] [\s!math] [garamond-math] [\s!default]
+ \stoptypescript
+
+\stoptypescriptcollection
diff --git a/tex/context/fonts/mkiv/type-imp-ebgaramond.mkiv b/tex/context/fonts/mkiv/type-imp-ebgaramond.mkiv
index 05ac2f1fa..03bb91989 100644
--- a/tex/context/fonts/mkiv/type-imp-ebgaramond.mkiv
+++ b/tex/context/fonts/mkiv/type-imp-ebgaramond.mkiv
@@ -66,8 +66,8 @@
\stoptypescript
\starttypescript [\s!math] [ebgaramond] [\s!name]
- \loadfontgoodies[ebgaramond]
- \definefontsynonym [\s!MathRoman] [\s!file:garamond-math.otf] [\s!features={\s!math\mathsizesuffix,mathextra},\s!goodies=ebgaramond]
+ \loadfontgoodies[garamond-math]
+ \definefontsynonym [\s!MathRoman] [\s!file:garamond-math.otf] [\s!features={\s!math\mathsizesuffix,mathextra},\s!goodies=garamond-math]
\stoptypescript
\starttypescript[ebgaramond]
diff --git a/tex/context/interface/mkii/keys-pe.xml b/tex/context/interface/mkii/keys-pe.xml
index 76f6d8117..70fc55c34 100644
--- a/tex/context/interface/mkii/keys-pe.xml
+++ b/tex/context/interface/mkii/keys-pe.xml
@@ -1288,6 +1288,7 @@
<cd:constant name='tab' value='تب'/>
<cd:constant name='text' value='متن'/>
<cd:constant name='textalign' value='textalign'/>
+ <cd:constant name='textalternative' value='textalternative'/>
<cd:constant name='textcolor' value='رنگ‌متن'/>
<cd:constant name='textcommand' value='فرمان‌متن'/>
<cd:constant name='textdistance' value='فاصله‌متن'/>
diff --git a/tex/context/modules/mkiv/s-math-characters.lua b/tex/context/modules/mkiv/s-math-characters.lua
index 61b2c8808..fc697cae5 100644
--- a/tex/context/modules/mkiv/s-math-characters.lua
+++ b/tex/context/modules/mkiv/s-math-characters.lua
@@ -157,8 +157,8 @@ local alllookups = collectalllookups(tfmdata,"math","dflt")
-- skip
else
local next_sizes = char.next
- local v_variants = char.vert_variants
- local h_variants = char.horiz_variants
+ local vvariants = char.vvariants or char.vert_variants
+ local hvariants = char.hvariants or char.horiz_variants
local mathclass = info.mathclass
local mathspec = info.mathspec
local mathsymbol = info.mathsymbol
@@ -208,29 +208,29 @@ local alllookups = collectalllookups(tfmdata,"math","dflt")
done[next_sizes] = true
context.showmathcharactersnextentry(n,f_unicode(next_sizes),next_sizes)
next_sizes = characters[next_sizes]
- v_variants = next_sizes.vert_variants or v_variants
- h_variants = next_sizes.horiz_variants or h_variants
+ vvariants = next_sizes.vvariants or next_sizes.vert_variants or vvariants
+ hvariants = next_sizes.hvariants or next_sizes.horiz_variants or hvariants
if next_sizes then
next_sizes = next_sizes.next
end
end
end
context.showmathcharactersstopnext()
- if h_variants or v_variants then
+ if hvariants or vvariants then
context.showmathcharactersbetweennextandvariants()
end
end
- if h_variants then
+ if hvariants then
context.showmathcharactersstarthvariants()
- for i=1,#h_variants do -- we might go top-down in the original
- local vi = h_variants[i]
+ for i=1,#hvariants do -- we might go top-down in the original
+ local vi = hvariants[i]
context.showmathcharactershvariantsentry(i,f_unicode(vi.glyph),vi.glyph)
end
context.showmathcharactersstophvariants()
- elseif v_variants then
+ elseif vvariants then
context.showmathcharactersstartvvariants()
- for i=1,#v_variants do
- local vi = v_variants[#v_variants-i+1]
+ for i=1,#vvariants do
+ local vi = vvariants[#vvariants-i+1]
context.showmathcharactersvvariantsentry(i,f_unicode(vi.glyph),vi.glyph)
end
context.showmathcharactersstopvvariants()
diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua
index 7ac66bfc7..e50c388b9 100644
--- a/tex/generic/context/luatex/luatex-fonts-merged.lua
+++ b/tex/generic/context/luatex/luatex-fonts-merged.lua
@@ -1,6 +1,6 @@
-- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua
-- parent file : c:/data/develop/context/sources/luatex-fonts.lua
--- merge date : 2021-11-30 19:43
+-- merge date : 2021-12-03 15:17
do -- begin closure to overcome local limits and interference