summaryrefslogtreecommitdiff
path: root/luaotfload-extralibs.lua
diff options
context:
space:
mode:
authorPhilipp Gesang <phg42.2a@gmail.com>2013-12-28 07:19:10 -0800
committerPhilipp Gesang <phg42.2a@gmail.com>2013-12-28 07:19:10 -0800
commitc0bb510a8a5bd18094043777cb7c320caa8283ce (patch)
tree696a6ae6aba988bce950b9173c8d52ecdb148a68 /luaotfload-extralibs.lua
parentc8a6d4cfba7a0d5d53917f709a973292931e0d3e (diff)
parent3371bb25ce3d7cd703b7b25dec6aafd305b4833a (diff)
downloadluaotfload-c0bb510a8a5bd18094043777cb7c320caa8283ce.tar.gz
Merge pull request #159 from phi-gamma/master
make fontwise letterspacing an official supported feature
Diffstat (limited to 'luaotfload-extralibs.lua')
-rw-r--r--luaotfload-extralibs.lua536
1 files changed, 0 insertions, 536 deletions
diff --git a/luaotfload-extralibs.lua b/luaotfload-extralibs.lua
deleted file mode 100644
index 21f738c..0000000
--- a/luaotfload-extralibs.lua
+++ /dev/null
@@ -1,536 +0,0 @@
-if not modules then modules = { } end modules ["extralibs"] = {
- version = "2.4",
- comment = "companion to luaotfload.lua",
- author = "Hans Hagen, Philipp Gesang",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "GPL v.2.0",
-}
-
--- extralibs: set up an emulation layer to load additional Context
--- libraries
-
---===================================================================--
---- PREPARE
---===================================================================--
-
-local getmetatable = getmetatable
-local require = require
-local select = select
-local setmetatable = setmetatable
-local tonumber = tonumber
-
-local texattribute = tex.attribute
-
-local new_node = node.new
-local copy_node = node.copy
-local otffeatures = fonts.constructors.newfeatures "otf"
-
------------------------------------------------------------------------
---- namespace
------------------------------------------------------------------------
-
---- The “typesetters” namespace isn’t bad at all; there is no need
---- to remove it after loading.
-
-typesetters = typesetters or { }
-local typesetters = typesetters
-typesetters.kerns = typesetters.kerns or { }
-local kerns = typesetters.kerns
-kerns.mapping = kerns.mapping or { }
-kerns.factors = kerns.factors or { }
-
-local kern_callback = "typesetters.kerncharacters"
-
-typesetters.kernfont = typesetters.kernfont or { }
-local kernfont = typesetters.kernfont
-
------------------------------------------------------------------------
---- node-ini
------------------------------------------------------------------------
-
-nodes = nodes or { } --- should be present with luaotfload
-local bothways = function (t) return table.swapped (t, t) end
-
-local kerncodes = bothways({
- [0] = "fontkern",
- [1] = "userkern",
- [2] = "accentkern",
-})
-
-kerncodes.kerning = kerncodes.fontkern --- idiosyncrasy
-
-nodes.kerncodes = kerncodes
-
-nodes.skipcodes = bothways({
- [ 0] = "userskip",
- [ 1] = "lineskip",
- [ 2] = "baselineskip",
- [ 3] = "parskip",
- [ 4] = "abovedisplayskip",
- [ 5] = "belowdisplayskip",
- [ 6] = "abovedisplayshortskip",
- [ 7] = "belowdisplayshortskip",
- [ 8] = "leftskip",
- [ 9] = "rightskip",
- [ 10] = "topskip",
- [ 11] = "splittopskip",
- [ 12] = "tabskip",
- [ 13] = "spaceskip",
- [ 14] = "xspaceskip",
- [ 15] = "parfillskip",
- [ 16] = "thinmuskip",
- [ 17] = "medmuskip",
- [ 18] = "thickmuskip",
- [100] = "leaders",
- [101] = "cleaders",
- [102] = "xleaders",
- [103] = "gleaders",
-})
-
------------------------------------------------------------------------
---- node-res
------------------------------------------------------------------------
-
-nodes.pool = nodes.pool or { }
-local pool = nodes.pool
-
-local kern = new_node("kern", nodes.kerncodes.userkern)
-local glue_spec = new_node "glue_spec"
-
-pool.kern = function (k)
- local n = copy_node(kern)
- n.kern = k
- return n
-end
-
-pool.gluespec = function (width, stretch, shrink,
- stretch_order, shrink_order)
- local s = copy_node(glue_spec)
- if width then s.width = width end
- if stretch then s.stretch = stretch end
- if shrink then s.shrink = shrink end
- if stretch_order then s.stretch_order = stretch_order end
- if shrink_order then s.shrink_order = shrink_order end
- return s
-end
-
-pool.glue = function (width, stretch, shrink,
- stretch_order, shrink_order)
- local n = new_node"glue"
- if not width then
- -- no spec
- elseif width == false or tonumber(width) then
- local s = copy_node(glue_spec)
- if width then s.width = width end
- if stretch then s.stretch = stretch end
- if shrink then s.shrink = shrink end
- if stretch_order then s.stretch_order = stretch_order end
- if shrink_order then s.shrink_order = shrink_order end
- n.spec = s
- else
- -- shared
- 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 markdata = fonthashes.marks
-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
-
-if not markdata then
- markdata = { }
- setmetatableindex(markdata, function(t, k)
- if k == true then
- return marks[currentfont()]
- else
- local resources = { }
-
- if identifiers[k] then
- resources = identifiers[k].resources or { }
- end
-
- local marks = resources.marks or { }
- t[k] = marks
- return marks
- end
- end)
- fonthashes.marks = markdata
-end
-
---- next stems from the multilingual interface
-interfaces = interfaces or { }
-interfaces.variables = interfaces.variables or { }
-interfaces.variables.max = "max"
-
------------------------------------------------------------------------
---- attr-ini
------------------------------------------------------------------------
-
-attributes = attributes or { } --- to be removed with cleanup
-
-local hidden = {
- a_kerns = luatexbase.new_attribute("typo-krn:a_kerns", true),
- a_fontkern = luatexbase.new_attribute("typo-krn:a_fontkern", true),
-}
-
-attributes.private = attributes.private or function (attr_name)
- local res = hidden[attr_name]
- if not res then
- res = luatexbase.new_attribute(attr_name)
- end
- return res
-end
-
-if luatexbase.get_unset_value then
- attributes.unsetvalue = luatexbase.get_unset_value()
-else -- old luatexbase
- attributes.unsetvalue = (luatexbase.luatexversion < 37) and -1
- or -2147483647
-end
-
------------------------------------------------------------------------
---- luat-sto
------------------------------------------------------------------------
-
---- Storage is so ridiculously well designed in Context it’s a pity
---- we can’t just force every package author to use it.
-
-storage = storage or { }
-storage.register = storage.register or function (...)
- local t = { ... }
- --- sorry
- return t
-end
-
------------------------------------------------------------------------
---- node-fin
------------------------------------------------------------------------
-
-local plugin_store = { }
-
-local installattributehandler = function (plugin)
- --- Context has some load() magic here.
- plugin_store[plugin.name] = plugin.processor
-end
-
-nodes.installattributehandler = installattributehandler
-
------------------------------------------------------------------------
---- node-tsk
------------------------------------------------------------------------
-
-nodes.tasks = nodes.tasks or { }
-nodes.tasks.enableaction = function () end
-
------------------------------------------------------------------------
---- core-ctx
------------------------------------------------------------------------
-
-commands = commands or { }
-
---===================================================================--
---- LOAD
---===================================================================--
-
---- we should be ready at this moment to insert the libraries
-
-require "luaotfload-typo-krn" --- typesetters.kerns
-require "luaotfload-letterspace" --- typesetters.kernfont
-
---===================================================================--
---- CLEAN
---===================================================================--
---- interface
------------------------------------------------------------------------
-
-local factors = kerns.factors
-local mapping = kerns.mapping
-local unsetvalue = attributes.unset_value
-local process_kerns = plugin_store.kern
-
---- kern_callback : normal
---- · callback: process_kerns
---- · enabler: enablecharacterkerning
---- · disabler: disablecharacterkerning
---- · interface: kerns.set
-
---- kernfont_callback : fontwise
---- · callback: kernfont.handler
---- · 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
-
---- we use the same callbacks as a node processor in Context
---- unit -> bool
-local enablecharacterkerning = function ( )
- return add_processor(function (head)
- return process_kerns("kerns", hidden.a_kerns, head)
- end,
- "typesetters.kerncharacters",
- "pre_linebreak_filter", "hpack_filter"
- )
-end
-
---- unit -> bool
-local disablecharacterkerning = function ( )
- return remove_processor "typesetters.kerncharacters"
-end
-
-kerns.enablecharacterkerning = enablecharacterkerning
-kerns.disablecharacterkerning = disablecharacterkerning
-
---- now for the simplistic variant
---- unit -> bool
-local enablefontkerning = function ( )
- return add_processor( kernfont.handler
- , "typesetters.kernfont"
- , "pre_linebreak_filter"
- , "hpack_filter")
-end
-
---- unit -> bool
-local disablefontkerning = function ( )
- return remove_processor "typesetters.kernfont"
-end
-
---- fontwise kerning uses a font property for passing along the
---- letterspacing factor
-
-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
- logs.names_report ("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,
- }
-}
-
-kerns.set = nil
-
-local characterkerning_enabled = false
-
-kerns.set = function (factor)
- if factor ~= "max" then
- factor = tonumber(factor) or 0
- end
- if factor == "max" or factor ~= 0 then
- if not characterkerning_enabled then
- enablecharacterkerning()
- characterkerning_enabled = true
- end
- local a = factors[factor]
- if not a then
- a = #mapping + 1
- factors[factors], mapping[a] = a, factor
- end
- factor = a
- else
- factor = unsetvalue
- end
- texattribute[hidden.a_kerns] = factor
- return factor
-end
-
-
-
------------------------------------------------------------------------
---- options
------------------------------------------------------------------------
-
-kerns .keepligature = false --- supposed to be of type function
-kerns .keeptogether = false --- supposed to be of type function
-kernfont.keepligature = false --- supposed to be of type function
-kernfont.keeptogether = false --- supposed to be of type function
-
------------------------------------------------------------------------
---- erase fake Context layer
------------------------------------------------------------------------
-
-attributes = nil
---commands = nil --- used in lualibs
-storage = nil --- not to confuse with utilities.storage
-nodes.tasks = nil
-
-collectgarbage"collect"
-
---[[example--
-
-\input luaotfload.sty
-\def\setcharacterkerning#1{% #1 factor : float
- \directlua{typesetters.kerns.set(0.618)}%
-}
-%directlua{typesetters.kerns.enablecharacterkerning()}
-
-\font\iwona = "name:Iwona:mode=node" at 42pt
-\font\lmregular = "name:Latin Modern Roman:mode=node" at 42pt
-
-{\iwona
- foo
- {\setcharacterkerning{0.618}%
- bar}
- baz}
-
-{\lmregular
- foo {\setcharacterkerning{0.125}ff fi ffi fl Th} baz}
-
-{\lmregular
- \directlua{ %% I’m not exactly sure how those work
- typesetters.kerns.keepligature = function (start)
- print("[liga]", start)
- return true
- end
- typesetters.kerns.keeptogether = function (start)
- print("[keeptogether]", start)
- return true
- end}%
- foo {\setcharacterkerning{0.125}ff fi ffi fl Th} baz}
-
-\bye
---example]]--
-
--- vim:ts=2:sw=2:expandtab