summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-letterspace.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/luatex/luaotfload/luaotfload-letterspace.lua')
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/luaotfload-letterspace.lua347
1 files changed, 112 insertions, 235 deletions
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-letterspace.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-letterspace.lua
index 292e05bbbfe..c89d89cfded 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-letterspace.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-letterspace.lua
@@ -5,12 +5,12 @@
local ProvidesLuaModule = {
name = "luaotfload-letterspace",
- version = "2.95", --TAGVERSION
- date = "2019-01-28", --TAGDATE
+ version = "2.96", --TAGVERSION
+ date = "2019-02-14", --TAGDATE
description = "luaotfload submodule / color",
license = "GPL v2.0",
copyright = "PRAGMA ADE / ConTeXt Development Team",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL; adapted by Philipp Gesang, Ulrike Fischer"
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL; adapted by Philipp Gesang, Ulrike Fischer, Marcel Krüger"
}
if luatexbase and luatexbase.provides_module then
@@ -20,80 +20,66 @@ end
--- This code diverged quite a bit from its origin in Context. Please
--- do *not* report bugs on the Context list.
-local log = luaotfload.log
-local logreport = log.report
+local logreport = luaotfload.log.report
local getmetatable = getmetatable
-local require = require
local setmetatable = setmetatable
local tonumber = tonumber
+local unpack = table.unpack
local next = next
-local nodes, node, fonts = nodes, node, fonts
+local node, fonts = node, fonts
-local nodedirect = nodes.nuts
+local nodedirect = node.direct
local getfield = nodedirect.getfield
local setfield = nodedirect.setfield
-local field_setter = function (name) return function (n, ...) setfield (n, name, ...) end end
-local field_getter = function (name) return function (n, ...) getfield (n, name, ...) end end
-
local getfont = nodedirect.getfont
local getid = nodedirect.getid
-local getnext = nodedirect.getnext or field_getter "next"
-local setnext = nodedirect.setnext or field_setter "next"
+local getnext = nodedirect.getnext
+local setnext = nodedirect.setnext
-local getprev = nodedirect.getprev or field_getter "prev"
-local setprev = nodedirect.setprev or field_setter "prev"
+local getprev = nodedirect.getprev
+local setprev = nodedirect.setprev
---- since r5336
-local getboth = nodedirect.getboth or function (n)
- return getprev (n), getnext (n)
-end
+local getboth = nodedirect.getboth
-local setlink = nodedirect.setlink or function (a, b)
- setnext (a, b)
- setprev (b, a)
-end
+local setlink = nodedirect.setlink
+
+local getdisc = nodedirect.getdisc
+local setdisc = nodedirect.setdisc
-local getdisc = nodedirect.getdisc or field_getter "disc"
-local setdisc = nodedirect.setdisc or field_setter "disc"
+local getsubtype = nodedirect.getsubtype
+local setsubtype = nodedirect.setsubtype
-local getsubtype = nodedirect.getsubtype or field_getter "subtype"
-local setsubtype = nodedirect.setsubtype or field_setter "subtype"
+local getchar = nodedirect.getchar
+local setchar = nodedirect.setchar
-local getchar = nodedirect.getchar or field_getter "subtype"
-local setchar = nodedirect.setchar or field_setter "subtype"
+local getkern = nodedirect.getkern
+local setkern = nodedirect.setkern
+
+local getglue = nodedirect.getglue
+local setglue = nodedirect.setglue
local find_node_tail = nodedirect.tail
-local todirect = nodedirect.tonut
+local todirect = nodedirect.todirect
local tonode = nodedirect.tonode
local insert_node_before = nodedirect.insert_before
-local free_node = nodedirect.free -- may cause double free
-local free_node = function (n)
- logreport ("term", 5, "letterspace", "not calling free_node(%d)", n)
- -- free_node (n)
-end
+local free_node = nodedirect.free
local copy_node = nodedirect.copy
local new_node = nodedirect.new
-local nodepool = nodedirect.pool
--- local new_kern = nodepool.kern -- UF removed 2017-07-14
-
-local nodecodes = nodes.nodecodes
-
-local glyph_code = nodecodes.glyph
-local kern_code = nodecodes.kern
-local disc_code = nodecodes.disc
-local math_code = nodecodes.math
-local glue_code = nodecodes.glue
+local glyph_code = node.id"glyph"
+local kern_code = node.id"kern"
+local disc_code = node.id"disc"
+local glue_code = node.id"glue"
local fonthashes = fonts.hashes
+local identifiers = fonthashes.identifiers
local chardata = fonthashes.characters
-local quaddata = fonthashes.quads
local otffeatures = fonts.constructors.newfeatures "otf"
--[[doc--
@@ -107,8 +93,10 @@ local otffeatures = fonts.constructors.newfeatures "otf"
luaotfload.letterspace = luaotfload.letterspace or { }
local letterspace = luaotfload.letterspace
-letterspace.keepligature = false
+local lectured = false
+letterspace.keepligature = true
letterspace.keeptogether = false
+letterspace.keepwordspacing = false
---=================================================================---
--- preliminary definitions
@@ -119,105 +107,19 @@ letterspace.keeptogether = false
--- node-ini
-----------------------------------------------------------------------
-local bothways = function (t) return table.swapped (t, t) end
-local kerncodes = bothways { [0] = "fontkern"
- , [1] = "userkern"
- , [2] = "accentkern"
- }
-local skipcodes = bothways { [0] = "userskip"
- , [13] = "spaceskip"
- , [14] = "xspaceskip"
- }
-
-kerncodes.kerning = kerncodes.fontkern --- idiosyncrasy
-local kerning_code = kerncodes.kerning
-local userkern_code = kerncodes.userkern
-local userskip_code = skipcodes.userskip
-local spaceskip_code = skipcodes.spaceskip
-local xspaceskip_code = skipcodes.xspaceskip
-
------------------------------------------------------------------------
---- node-res
------------------------------------------------------------------------
-
-local glue_spec = new_node "glue_spec"
-
-local new_gluespec = function (width,
- stretch, shrink,
- stretch_order, shrink_order)
- local spec = copy_node(glue_spec)
- if width then setfield(spec, "width" , width ) end
- if stretch then setfield(spec, "stretch" , stretch ) end
- if shrink then setfield(spec, "shrink" , shrink ) end
- if stretch_order then setfield(spec, "stretch_order", stretch_order) end
- if shrink_order then setfield(spec, "shrink_order" , shrink_order ) end
- return spec
-end
-
-local new_glue = function (width, stretch, shrink,
- stretch_order, shrink_order)
- local n = new_node "glue"
- if not width then return n end
- -- no spec
- if width == false then
- local width = tonumber(width)
- if width then
- setfield(n, "spec",
- new_gluespec(width, stretch, shrink,
- stretch_order, shrink_order))
- end
- else
- -- shared
- setfield(n, "spec", copy_node(width))
- end
- return n
-end
-
------------------------------------------------------------------------
---- font-hsh
------------------------------------------------------------------------
---- some initialization resembling font-hsh
-local fonthashes = fonts.hashes
-local identifiers = fonthashes.identifiers --- was: fontdata
-local chardata = fonthashes.characters
-local quaddata = fonthashes.quads
-local parameters = fonthashes.parameters
-
---- ('a, 'a) hash -> (('a, 'a) hash -> 'a -> 'a) -> ('a, 'a) hash
-local setmetatableindex = function (t, f)
- local mt = getmetatable(t)
- if mt then
- mt.__index = f
- else
- setmetatable(t, { __index = f })
- end
- return t
-end
-
-if not parameters then
- parameters = { }
- 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)
- --fonthashes.parameters = parameters
-end
+local kerning_code = 0
+local userkern_code = 1
+local userskip_code = 0
+local spaceskip_code = 13
+local xspaceskip_code = 14
if not chardata then
chardata = { }
- setmetatableindex(chardata, function(t, k)
+ table.setmetatableindex(chardata, function(t, k)
if k == true then
return chardata[currentfont()]
else
- local tfmdata = identifiers[k]
- if not tfmdata then --- unsafe
- tfmdata = font.fonts[k]
- end
+ local tfmdata = font.getfont(k) or font.fonts[k]
if tfmdata then
local characters = tfmdata.characters
t[k] = characters
@@ -228,37 +130,19 @@ if not chardata then
fonthashes.characters = chardata
end
-if not quaddata then
- quaddata = { }
- setmetatableindex(quaddata, function(t, k)
- if k == true then
- return quads[currentfont()]
- else
- local parameters = parameters[k]
- local quad = parameters and parameters.quad or 0
- t[k] = quad
- return quad
- end
- end)
- --fonthashes.quads = quaddata
-end
-
---=================================================================---
--- character kerning functionality
---=================================================================---
-- UF changed 2017-07-14
-local nodedirectnew = node.direct.new
-
local kern_injector = function (fillup, kern)
if fillup then
- local g = nodedirectnew("glue")
- setfield(g, "stretch", kern)
- setfield(g, "stretch_order", 1)
+ local g = new_node(glue_code)
+ setglue(g, 0, kern, 0, 1, 0)
return g
end
- local g = nodedirectnew("kern")
- setfield(g,"kern",kern)
+ local g = new_node(kern_code)
+ setkern(g,kern)
return g
end
-- /UF
@@ -270,15 +154,6 @@ local kernable_skip = function (n)
or st == xspaceskip_code
end
-local function spec_injector (fillup, width, stretch, shrink)
- if fillup then
- local spec = new_gluespec(width, 2 * stretch, 2 * shrink)
- setfield(spec, "stretch_order", 1)
- return spec
- end
- return new_gluespec(width,stretch,shrink)
-end
-
--[[doc--
Caveat lector.
@@ -290,67 +165,78 @@ end
--doc]]--
-local kernfactors = { } --- fontid -> factor
+local kernamounts = table.setmetatableindex(function (t, f) --- fontid -> {kern, fill}
+ local tfmdata = font.getfont(f) or font.fonts[f]
+ if tfmdata then
+ local fontproperties = tfmdata.properties
+ local fontparameters = tfmdata.parameters
+ if fontproperties and fontparameters then
+ local r
+ if fontproperties.kerncharacters == "max" then
+ r = {fontparameters.quad/4, true}
+ elseif fontproperties.kerncharacters then
+ r = {fontproperties.kerncharacters * fontparameters.quad, false}
+ else
+ r = {}
+ end
+ t[f] = r
+ return r
+ end
+ end
+ return {}
+end)
local kerncharacters
kerncharacters = function (head)
local start = head
local lastfont = nil
- local keepligature = letterspace.keepligature --- function
local keeptogether = letterspace.keeptogether --- function
- local fillup = false
+ local keepligature = letterspace.keepligature
+-- if not lectured and keepligature ~= true then
+-- logreport ("both", 0, "letterspace",
+-- "Breaking ligatures through letterspacing is deprecated and "
+-- .. "will be removed soon. Please disable unwanted ligatures through "
+-- .. "font features instead and reset luaotfload.letterspace.keepligature "
+-- .. "to true to maintain compatibility with future versions of luaotfload.")
+-- lectured = true
+-- end
+ if type(keepligature) ~= "function" then
+ local savedligature = keepligature
+ keepligature = function() return savedligature end
+ end
+ local keepwordspacing = letterspace.keepwordspacing
+ if type(keepwordspacing) ~= "function" then
+ local savedwordspacing = keepwordspacing
+ keepwordspacing = function() return savedwordspacing end
+ end
- local identifiers = fonthashes.identifiers
- local kernfactors = kernfactors
+ local kernamounts = kernamounts
local firstkern = true
while start do
local id = getid(start)
if id == glyph_code then
--- 1) look up kern factor (slow, but cached rudimentarily)
- local krn
local fontid = getfont(start)
- do
- krn = kernfactors[fontid]
- if not krn then
- local tfmdata = identifiers[fontid]
- if not tfmdata then -- unsafe
- tfmdata = font.fonts[fontid]
- end
- if tfmdata then
- fontproperties = tfmdata.properties
- if fontproperties then
- krn = fontproperties.kerncharacters
- end
- end
- kernfactors[fontid] = krn
- end
- if not krn or krn == 0 then
- firstkern = true
+ local krn, fillup = unpack(kernamounts[fontid])
+ if not krn or krn == 0 then
+ firstkern = true
+ goto nextnode
+ elseif firstkern then
+ firstkern = false
+ if (id ~= disc_code) and (not getfield(start, "components")) then
+ --- not a ligature, skip node
goto nextnode
- elseif firstkern then
- firstkern = false
- if (id ~= disc_code) and (not getfield(start, "components")) then
- --- not a ligature, skip node
- goto nextnode
- end
end
end
- if krn == "max" then
- krn = .25
- fillup = true
- else
- fillup = false
- end
-
lastfont = fontid
--- 2) resolve ligatures
local c = getfield(start, "components")
if c then
- if keepligature and keepligature(start) then
+ if keepligature(start) then
-- keep 'm
c = nil
else
@@ -382,18 +268,18 @@ kerncharacters = function (head)
if not pid then
-- nothing
- elseif pid == glue_code and kernable_skip(prev) then
- local spec = getfield(prev, "spec")
- local wd = getfield(spec, "width")
+ elseif pid == glue_code and kernable_skip(prev)
+ and not keepwordspacing(prev, lastfont) then
+ local wd, stretch, shrink = getglue(prev)
if wd > 0 then
- --- formula taken from Context
- --- existing_width extended by four times the
- --- width times the font’s kernfactor
- local newwd = wd + --[[two en to a quad]] 4 * wd * krn
- local stretched = (getfield(spec,"stretch") * newwd) / wd
- local shrunk = (getfield(spec,"shrink") * newwd) / wd
- setfield(prev, "spec",
- spec_injector(fillup, newwd, stretched, shrunk))
+ local newwd = wd + krn
+ local stretched = (stretch * newwd) / wd
+ local shrunk = (shrink * newwd) / wd
+ if fillup then
+ setglue(prev, newwd, 2 * stretched, 2 * shrunk, 1, 0)
+ else
+ setglue(prev, newwd, stretched, shrunk, 0, 0)
+ end
end
elseif pid == kern_code then
@@ -412,9 +298,9 @@ kerncharacters = function (head)
-- keep
else
setsubtype (prev, userkern_code)
- local prev_kern = getfield(prev, "kern")
- prev_kern = prev_kern + quaddata[lastfont] * krn
- setfield (prev, "kern", prev_kern)
+ local prev_kern = getkern(prev)
+ prev_kern = prev_kern + krn
+ setkern (prev, prev_kern)
end
end
@@ -434,13 +320,12 @@ kerncharacters = function (head)
local kern = 0
local kerns = prevchardata.kerns
if kerns then kern = kerns[lastchar] or kern end
- krn = kern + quaddata[lastfont]*krn -- here
+ krn = kern + krn -- here
insert_node_before(head,start,kern_injector(fillup,krn))
end
end
end
else
- krn = quaddata[lastfont]*krn -- here
insert_node_before(head,start,kern_injector(fillup,krn))
end
@@ -470,7 +355,7 @@ kerncharacters = function (head)
setprev(after, tail)
setnext(after, nil)
post = kerncharacters (post)
- setnext(tail, nil)
+ setnext(getprev(after), nil)
setfield(disc, "post", post)
free_node(after)
end
@@ -489,7 +374,7 @@ kerncharacters = function (head)
replace = getnext(replace)
setprev(replace, nil)
setnext(getprev(after), nil)
- setfield(disc, "replace", replace)
+ setfield(disc, "replace", replace)
free_node(after)
free_node(before)
@@ -511,9 +396,7 @@ kerncharacters = function (head)
if kerns then kern = kerns[lastchar] or kern end
end
end
- krn = kern + quaddata[lastfont]*krn -- here
- else
- krn = quaddata[lastfont]*krn -- here
+ krn = kern + krn -- here
end
setfield(disc, "replace", kern_injector(false, krn))
end --[[if replace and prv and nxt]]
@@ -535,7 +418,6 @@ end
--- · callback: kerncharacters
--- · enabler: enablefontkerning
---- · disabler: disablefontkerning
--- callback wrappers
@@ -592,11 +474,6 @@ local enablefontkerning = function ( )
, "hpack_filter")
end
---- unit -> bool
----al disablefontkerning = function ( )
----eturn remove_processor "luaotfload.letterspace"
----
-
--[[doc--
Fontwise kerning is enabled via the “kernfactor” option at font