summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/doc/luatex/fontloader-luaotfload/luaotfload-letterspace.luax
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/doc/luatex/fontloader-luaotfload/luaotfload-letterspace.luax')
-rw-r--r--Master/texmf-dist/doc/luatex/fontloader-luaotfload/luaotfload-letterspace.luax683
1 files changed, 0 insertions, 683 deletions
diff --git a/Master/texmf-dist/doc/luatex/fontloader-luaotfload/luaotfload-letterspace.luax b/Master/texmf-dist/doc/luatex/fontloader-luaotfload/luaotfload-letterspace.luax
deleted file mode 100644
index df93dbe1b70..00000000000
--- a/Master/texmf-dist/doc/luatex/fontloader-luaotfload/luaotfload-letterspace.luax
+++ /dev/null
@@ -1,683 +0,0 @@
-if not modules then modules = { } end modules ['letterspace'] = {
- version = "2.8",
- comment = "companion to luaotfload-main.lua",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL; adapted by Philipp Gesang",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
---- 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
-
--- UF
-texio.write_nl ("------------------")
-texio.write_nl ("!!!!! UF: Using CHANGED luaotfload-letterspace 2017-07-14 !!!!!")
-texio.write_nl ("------------------")
--- /UF
-
-local getmetatable = getmetatable
-local require = require
-local setmetatable = setmetatable
-local tonumber = tonumber
-
-local next = next
-local nodes, node, fonts = nodes, node, fonts
-
-local nodedirect = nodes.nuts
-
-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 getprev = nodedirect.getprev or field_getter "prev"
-local setprev = nodedirect.setprev or field_setter "prev"
-
---- since r5336
-local getboth = nodedirect.getboth or function (n)
- return getprev (n), getnext (n)
-end
-
-local setlink = nodedirect.setlink or function (a, b)
- setnext (a, b)
- setprev (b, a)
-end
-
-local getdisc = nodedirect.getdisc or field_getter "disc"
-local setdisc = nodedirect.setdisc or field_setter "disc"
-
-local getsubtype = nodedirect.getsubtype or field_getter "subtype"
-local setsubtype = nodedirect.setsubtype or field_setter "subtype"
-
-local getchar = nodedirect.getchar or field_getter "subtype"
-local setchar = nodedirect.setchar or field_setter "subtype"
-
-local find_node_tail = nodedirect.tail
-local todirect = nodedirect.tonut
-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 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 fonthashes = fonts.hashes
-local chardata = fonthashes.characters
-local quaddata = fonthashes.quads
-local otffeatures = fonts.constructors.newfeatures "otf"
-
---[[doc--
-
- Since the letterspacing method was derived initially from Context’s
- typo-krn.lua we keep the sub-namespace “letterspace” inside the
- “luaotfload” table.
-
---doc]]--
-
-luaotfload.letterspace = luaotfload.letterspace or { }
-local letterspace = luaotfload.letterspace
-
-letterspace.keepligature = false
-letterspace.keeptogether = false
-
----=================================================================---
---- preliminary definitions
----=================================================================---
--- We set up a layer emulating some Context internals that are needed
--- for the letterspacing callback.
------------------------------------------------------------------------
---- 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
-
-if not chardata then
- chardata = { }
- 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
- if tfmdata then
- local characters = tfmdata.characters
- t[k] = characters
- return characters
- end
- end
- end)
- 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 newUF = node.direct.new
-
-local kern_injector = function (fillup, kern)
- if fillup then
- local g = newUF("glue")
- setfield(g, "stretch", kern)
- setfield(g, "stretch_order", 1)
- return g
- end
- local g = newUF("kern")
- setfield(g,"kern",kern)
- return g
-end
--- /UF
-
-local kernable_skip = function (n)
- local st = getsubtype (n)
- return st == userskip_code
- or st == spaceskip_code
- 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.
- This is an adaptation of the Context character kerning mechanism
- that emulates XeTeX-style fontwise letterspacing. Note that in its
- present state it is far inferior to the original, which is
- attribute-based and ignores font-boundaries. Nevertheless, due to
- popular demand the following callback has been added.
-
---doc]]--
-
-local kernfactors = { } --- fontid -> factor
-
-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 identifiers = fonthashes.identifiers
- local kernfactors = kernfactors
- 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
- 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
- -- keep 'm
- c = nil
- else
- while c do
- local s = start
- local p, n = getboth (s)
- if p then
- setlink (p, c)
- else
- head = c
- end
- if n then
- local tail = find_node_tail(c)
- setlink (tail, n)
- end
- start = c
- setfield(s, "components", nil)
- free_node(s) --> double free with multipart components
- c = getfield (start, "components")
- end
- end
- end -- kern ligature
-
- --- 3) apply the extra kerning
- local prev = getprev(start)
- if prev then
- local pid = getid(prev)
-
- if not pid then
- -- nothing
-
- elseif pid == glue_code and kernable_skip(prev) then
- local spec = getfield(prev, "spec")
- local wd = getfield(spec, "width")
- 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))
- end
-
- elseif pid == kern_code then
- local prev_subtype = getsubtype(prev)
- if prev_subtype == kerning_code --- context does this by means of an
- or prev_subtype == userkern_code --- attribute; we may need a test
- then
-
- local pprev = getprev(prev)
- local pprev_id = getid(pprev)
-
- if keeptogether
- and pprev_id == glyph_code
- and keeptogether(pprev, start)
- then
- -- keep
- else
- setsubtype (prev, userkern_code)
- local prev_kern = getfield(prev, "kern")
- prev_kern = prev_kern + quaddata[lastfont] * krn
- setfield (prev, "kern", prev_kern)
- end
- end
-
- elseif pid == glyph_code then
- if getfont(prev) == lastfont then
- local prevchar = getchar(prev)
- local lastchar = getchar(start)
- if keeptogether and keeptogether(prev, start) then
- -- keep 'm
- elseif identifiers[lastfont] then
- local lastfontchars = chardata[lastfont]
- if lastfontchars then
- local prevchardata = lastfontchars[prevchar]
- if not prevchardata then
- --- font doesn’t contain the glyph
- else
- local kern = 0
- local kerns = prevchardata.kerns
- if kerns then kern = kerns[lastchar] or kern end
- krn = kern + quaddata[lastfont]*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
-
- elseif pid == disc_code then
- local disc = prev -- disc
- local pre, post, replace = getdisc (disc)
- local prv = getprev(disc)
- local nxt = getnext(disc)
-
- if pre and prv then -- must pair with start.prev
- -- this one happens in most cases
- local before = copy_node(prv)
- setprev(pre, before)
- setnext(before, pre)
- setprev(before, nil)
- pre = kerncharacters (before)
- pre = getnext(pre)
- setprev(pre, nil)
- setfield(disc, "pre", pre)
- free_node(before)
- end
-
- if post and nxt then -- must pair with start
- local after = copy_node(nxt)
- local tail = find_node_tail(post)
- setnext(tail, after)
- setprev(after, tail)
- setnext(after, nil)
- post = kerncharacters (post)
- setnext(tail, nil)
- setfield(disc, "post", post)
- free_node(after)
- end
-
- if replace and prv and nxt then -- must pair with start and start.prev
- local before = copy_node(prv)
- local after = copy_node(nxt)
- local tail = find_node_tail(replace)
- setprev(replace, before)
- setnext(before, replace)
- setprev(before, nil)
- setnext(tail, after)
- setprev(after, tail)
- setnext(after, nil)
- replace = kerncharacters (before)
- replace = getnext(replace)
- setprev(replace, nil)
- setnext(getprev(after), nil)
- setfield(disc, "replace", replace)
- free_node(after)
- free_node(before)
-
- elseif identifiers[lastfont] then
- if prv
- and getid(prv) == glyph_code
- and getfont(prv) == lastfont
- then
- local kern = 0
- local prevchar = getchar(prv)
- local lastchar = getchar(start)
- local lastfontchars = chardata[lastfont]
- if lastfontchars then
- local prevchardata = lastfontchars[prevchar]
- if not prevchardata then
- --- font doesn’t contain the glyph
- else
- local kerns = prevchardata.kerns
- if kerns then kern = kerns[lastchar] or kern end
- end
- end
- krn = kern + quaddata[lastfont]*krn -- here
- else
- krn = quaddata[lastfont]*krn -- here
- end
- setfield(disc, "replace", kern_injector(false, krn))
- end --[[if replace and prv and nxt]]
- end --[[if not pid]]
- end --[[if prev]]
- end --[[if id == glyph_code]]
-
- ::nextnode::
- if start then
- start = getnext(start)
- end
- end
- return head
-end
-
----=================================================================---
---- integration
----=================================================================---
-
---- · callback: kerncharacters
---- · enabler: enablefontkerning
---- · disabler: disablefontkerning
-
---- callback wrappers
-
---- (node_t -> node_t) -> string -> string list -> bool
-local registered_as = { } --- procname -> callbacks
-local add_processor = function (processor, name, ...)
- local callbacks = { ... }
- for i=1, #callbacks do
- luatexbase.add_to_callback(callbacks[i], processor, name)
- end
- registered_as[name] = callbacks --- for removal
- return true
-end
-
---- string -> bool
-local remove_processor = function (name)
- local callbacks = registered_as[name]
- if callbacks then
- for i=1, #callbacks do
- luatexbase.remove_from_callback(callbacks[i], name)
- end
- return true
- end
- return false --> unregistered
-end
-
---- When font kerning is requested, usually by defining a font with the
---- ``letterspace`` parameter, we inject a wrapper for the
---- ``kerncharacters()`` node processor in the relevant callbacks. This
---- wrapper initially converts the received head node into its “direct”
---- counterpart. Likewise, the callback result is converted back to an
---- ordinary node prior to returning. Internally, ``kerncharacters()``
---- performs all node operations on direct nodes.
-
---- unit -> bool
-local enablefontkerning = function ( )
-
- local handler = function (hd)
- local direct_hd = todirect (hd)
- logreport ("term", 5, "letterspace",
- "kerncharacters() invoked with node.direct interface \z
- (``%s`` -> ``%s``)", tostring (hd), tostring (direct_hd))
- local direct_hd = kerncharacters (direct_hd)
- if not direct_hd then --- bad
- logreport ("both", 0, "letterspace",
- "kerncharacters() failed to return a valid new head")
- end
- return tonode (direct_hd)
- end
-
- return add_processor( handler
- , "luaotfload.letterspace"
- , "pre_linebreak_filter"
- , "hpack_filter")
-end
-
---- unit -> bool
----al disablefontkerning = function ( )
----eturn remove_processor "luaotfload.letterspace"
----
-
---[[doc--
-
- Fontwise kerning is enabled via the “kernfactor” option at font
- definition time. Unlike the Context implementation which relies on
- Luatex attributes, it uses a font property for passing along the
- letterspacing factor of a node.
-
- The callback is activated the first time a letterspaced font is
- requested and stays active until the end of the run. Since the font
- is a property of individual glyphs, every glyph in the entire
- document must be checked for the kern property. This is quite
- inefficient compared to Context’s attribute based approach, but Xetex
- compatibility reduces our options significantly.
-
---doc]]--
-
-
-local fontkerning_enabled = false --- callback state
-
---- fontobj -> float -> unit
-local initializefontkerning = function (tfmdata, factor)
- if factor ~= "max" then
- factor = tonumber (factor) or 0
- end
- if factor == "max" or factor ~= 0 then
- local fontproperties = tfmdata.properties
- if fontproperties then
- --- hopefully this field stays unused otherwise
- fontproperties.kerncharacters = factor
- end
- if not fontkerning_enabled then
- fontkerning_enabled = enablefontkerning ()
- end
- end
-end
-
---- like the font colorization, fontwise kerning is hooked into the
---- feature mechanism
-
-otffeatures.register {
- name = "kernfactor",
- description = "kernfactor",
- initializers = {
- base = initializefontkerning,
- node = initializefontkerning,
- }
-}
-
---[[doc--
-
- The “letterspace” feature is essentially identical with the above
- “kernfactor” method, but scales the factor to percentages to match
- Xetex’s behavior. (See the Xetex reference, page 5, section 1.2.2.)
-
- Since Xetex doesn’t appear to have a (documented) “max” keyword, we
- assume all input values are numeric.
-
---doc]]--
-
-local initializecompatfontkerning = function (tfmdata, percentage)
- local factor = tonumber (percentage)
- if not factor then
- logreport ("both", 0, "letterspace",
- "Invalid argument to letterspace: %s (type %q), " ..
- "was expecting percentage as Lua number instead.",
- percentage, type (percentage))
- return
- end
- return initializefontkerning (tfmdata, factor * 0.01)
-end
-
-otffeatures.register {
- name = "letterspace",
- description = "letterspace",
- initializers = {
- base = initializecompatfontkerning,
- node = initializecompatfontkerning,
- }
-}
-
---[[example--
-
-See https://bitbucket.org/phg/lua-la-tex-tests/src/tip/pln-letterspace-8-compare.tex
-for an example.
-
---example]]--
-
---- vim:sw=2:ts=2:expandtab:tw=71
-