summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/typo-krn.lua
diff options
context:
space:
mode:
authorTaco Hoekwater <taco@elvenkind.com>2011-06-01 08:54:21 +0000
committerTaco Hoekwater <taco@elvenkind.com>2011-06-01 08:54:21 +0000
commitd7ccb42582f85acf30568913610ccf4d602023fb (patch)
tree7292e3545a420676878e7451b68892d360c62cb6 /Master/texmf-dist/tex/context/base/typo-krn.lua
parent2d62a6fe9b80def59c392268022f1f9a2d6e358f (diff)
commit context 2011.05.18
git-svn-id: svn://tug.org/texlive/trunk@22719 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/context/base/typo-krn.lua')
-rw-r--r--Master/texmf-dist/tex/context/base/typo-krn.lua204
1 files changed, 128 insertions, 76 deletions
diff --git a/Master/texmf-dist/tex/context/base/typo-krn.lua b/Master/texmf-dist/tex/context/base/typo-krn.lua
index 746773e0a88..a9428439cd8 100644
--- a/Master/texmf-dist/tex/context/base/typo-krn.lua
+++ b/Master/texmf-dist/tex/context/base/typo-krn.lua
@@ -11,57 +11,80 @@ local utf = unicode.utf8
local next, type = next, type
local utfchar = utf.char
+local nodes, node, fonts = nodes, node, fonts
+
local has_attribute = node.has_attribute
local unset_attribute = node.unset_attribute
local find_node_tail = node.tail or node.slide
local free_node = node.free
+local free_nodelist = node.flush_list
local copy_node = node.copy
+local copy_nodelist = node.copy_list
local insert_node_before = node.insert_before
local insert_node_after = node.insert_after
-local make_glue_spec = nodes.glue_spec
-local make_kern_node = nodes.kern
-local glyph = node.id("glyph")
-local kern = node.id("kern")
-local disc = node.id('disc')
-local glue = node.id('glue')
-local hlist = node.id('hlist')
-local vlist = node.id('vlist')
+local texattribute = tex.attribute
+
+local nodepool = nodes.pool
+local tasks = nodes.tasks
+
+local new_gluespec = nodepool.gluespec
+local new_kern = nodepool.kern
+
+local nodecodes = nodes.nodecodes
+local kerncodes = nodes.kerncodes
+local skipcodes = nodes.skipcodes
+
+local glyph_code = nodecodes.glyph
+local kern_code = nodecodes.kern
+local disc_code = nodecodes.disc
+local glue_code = nodecodes.glue
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+
+local kerning_code = kerncodes.kerning
+local userkern_code = kerncodes.userkern
+local userskip_code = skipcodes.userskip
+
+local fonthashes = fonts.hashes
+local fontdata = fonthashes.identifiers
+local chardata = fonthashes.characters
+local quaddata = fonthashes.quads
-local fontdata = fonts.identifiers
-local chardata = fonts.characters
-local quaddata = fonts.quads
+typesetters = typesetters or { }
+local typesetters = typesetters
-kerns = kerns or { }
-kerns.mapping = kerns.mapping or { }
-kerns.factors = kerns.factors or { }
-kerns.attribute = attributes.private("kern")
+typesetters.kerns = typesetters.kerns or { }
+local kerns = typesetters.kerns
-storage.register("kerns/mapping", kerns.mapping, "kerns.mapping")
-storage.register("kerns/factors", kerns.factors, "kerns.factors")
+kerns.mapping = kerns.mapping or { }
+kerns.factors = kerns.factors or { }
+local a_kerns = attributes.private("kern")
+kerns.attribute = kerns.attribute
+
+storage.register("typesetters/kerns/mapping", kerns.mapping, "typesetters.kerns.mapping")
+storage.register("typesetters/kerns/factors", kerns.factors, "typesetters.kerns.factors")
local mapping = kerns.mapping
local factors = kerns.factors
-function kerns.setspacing(factor)
- local a = factors[factor]
- if not a then
- a = #mapping + 1
- factors[factors], mapping[a] = a, factor
- end
- tex.attribute[kerns.attribute] = a
- return a
-end
-
-- one must use liga=no and mode=base and kern=yes
-- use more helpers
-- make sure it runs after all others
-- there will be a width adaptor field in nodes so this will change
-- todo: interchar kerns / disc nodes / can be made faster
-local function process(namespace,attribute,head,force)
- local scale = tex.scale -- will go
+local gluefactor = 4 -- assumes quad = .5 enspace
+
+kerns.keepligature = false -- just for fun (todo: control setting with key/value)
+kerns.keeptogether = false -- just for fun (todo: control setting with key/value)
+
+-- can be optimized .. the prev thing .. but hardly worth the effort
+
+local function do_process(namespace,attribute,head,force) -- todo: glue so that we can fully stretch
local start, done, lastfont = head, false, nil
+local keepligature = kerns.keepligature
+local keeptogether = kerns.keeptogether
while start do
-- faster to test for attr first
local attr = force or has_attribute(start,attribute)
@@ -70,50 +93,65 @@ local function process(namespace,attribute,head,force)
local krn = mapping[attr]
if krn and krn ~= 0 then
local id = start.id
- if id == glyph then
+ if id == glyph_code then
lastfont = start.font
local c = start.components
if c then
+if keepligature and keepligature(start) then
+ -- keep 'm
+else
+ c = do_process(namespace,attribute,c,attr)
local s = start
+ local p, n = s.prev, s.next
local tail = find_node_tail(c)
- if s.prev then
- s.prev.next = c
- c.prev = s.prev
+ if p then
+ p.next = c
+ c.prev = p
else
head = c
end
- if s.next then
- s.next.prev = tail
+ if n then
+ n.prev = tail
end
- tail.next = s.next
+ tail.next = n
start = c
- start.attr = s.attr
- s.attr = nil
s.components = nil
- free_node(s)
+ -- we now leak nodes !
+ -- free_node(s)
done = true
+end
end
local prev = start.prev
if prev then
local pid = prev.id
if not pid then
-- nothing
- elseif pid == kern and prev.subtype == 0 then
- prev.subtype = 1
- prev.kern = prev.kern + scale(quaddata[lastfont],krn)
+ elseif pid == kern_code and prev.subtype == kerning_code then
+if keeptogether and prev.prev.id == glyph_code and keeptogether(prev.prev,start) then -- we could also pass start
+ -- keep 'm
+else
+ prev.subtype = userkern_code
+ prev.kern = prev.kern + quaddata[lastfont]*krn -- here
done = true
- elseif pid == glyph then
+end
+ elseif pid == glyph_code then
if prev.font == lastfont then
local prevchar, lastchar = prev.char, start.char
+if keeptogether and keeptogether(prev,start) then
+ -- keep 'm
+else
local kerns = chardata[lastfont][prevchar].kerns
local kern = kerns and kerns[lastchar] or 0
- krn = scale(kern+quaddata[lastfont],krn)
+ krn = kern + quaddata[lastfont]*krn -- here
+ insert_node_before(head,start,new_kern(krn))
+ done = true
+end
else
- krn = scale(quaddata[lastfont],krn)
+ krn = quaddata[lastfont]*krn -- here
+ insert_node_before(head,start,new_kern(krn))
+ done = true
end
- insert_node_before(head,start,make_kern_node(krn))
- done = true
- elseif pid == disc then
+ elseif pid == disc_code then
-- a bit too complicated, we can best not copy and just calculate
-- but we could have multiple glyphs involved so ...
local disc = prev -- disc
@@ -125,7 +163,7 @@ local function process(namespace,attribute,head,force)
pre.prev = before
before.next = pre
before.prev = nil
- pre = process(namespace,attribute,before,attr)
+ pre = do_process(namespace,attribute,before,attr)
pre = pre.next
pre.prev = nil
disc.pre = pre
@@ -137,7 +175,7 @@ local function process(namespace,attribute,head,force)
tail.next = after
after.prev = tail
after.next = nil
- post = process(namespace,attribute,post,attr)
+ post = do_process(namespace,attribute,post,attr)
tail.next = nil
disc.post = post
free_node(after)
@@ -152,7 +190,7 @@ local function process(namespace,attribute,head,force)
tail.next = after
after.prev = tail
after.next = nil
- replace = process(namespace,attribute,before,attr)
+ replace = do_process(namespace,attribute,before,attr)
replace = replace.next
replace.prev = nil
after.prev.next = nil
@@ -160,42 +198,41 @@ local function process(namespace,attribute,head,force)
free_node(after)
free_node(before)
else
- if prv and prv.id == glyph and prv.font == lastfont then
+ if prv and prv.id == glyph_code and prv.font == lastfont then
local prevchar, lastchar = prv.char, start.char
local kerns = chardata[lastfont][prevchar].kerns
local kern = kerns and kerns[lastchar] or 0
- krn = scale(kern+quaddata[lastfont],krn)
+ krn = kern + quaddata[lastfont]*krn -- here
else
- krn = scale(quaddata[lastfont],krn)
+ krn = quaddata[lastfont]*krn -- here
end
- disc.replace = make_kern_node(krn)
+ disc.replace = new_kern(krn)
end
end
end
- elseif id == glue and start.subtype == 0 then
+ elseif id == glue_code and start.subtype == userskip_code then
local s = start.spec
local w = s.width
if w > 0 then
- local width, stretch, shrink = w+2*scale(w,krn), s.stretch, s.shrink
- start.spec = make_glue_spec(width,scale(stretch,width/w),scale(shrink,width/w))
- -- local width, stretch, shrink = w+2*w*krn, s.stretch, s.shrink
- -- start.spec = make_glue_spec(width,stretch*width/w,shrink*width/w))
+ local width, stretch, shrink = w+gluefactor*w*krn, s.stretch, s.shrink
+ start.spec = new_gluespec(width,stretch*width/w,shrink*width/w)
done = true
end
- elseif false and id == kern and start.subtype == 0 then -- handle with glyphs
+ elseif false and id == kern_code and start.subtype == kerning_code then -- handle with glyphs
local sk = start.kern
if sk > 0 then
- -- start.kern = scale(sk,krn)
start.kern = sk*krn
done = true
end
- elseif lastfont and (id == hlist or id == vlist) then -- todo: lookahead
- if start.prev then
- insert_node_before(head,start,make_kern_node(scale(quaddata[lastfont],krn)))
+ elseif lastfont and (id == hlist_code or id == vlist_code) then -- todo: lookahead
+ local p = start.prev
+ if p and p.id ~= glue_code then
+ insert_node_before(head,start,new_kern(quaddata[lastfont]*krn))
done = true
end
- if start.next then
- insert_node_after(head,start,make_kern_node(scale(quaddata[lastfont],krn)))
+ local n = start.next
+ if n and n.id ~= glue_code then
+ insert_node_after(head,start,new_kern(quaddata[lastfont]*krn))
done = true
end
end
@@ -208,16 +245,31 @@ local function process(namespace,attribute,head,force)
return head, done
end
-kerns.process = function(namespace,attribute,head)
- return process(namespace,attribute,head) -- no direct map, because else fourth argument is tail == true
+local enabled = false
+
+function kerns.set(factor)
+ if not enabled then
+ tasks.enableaction("processors","typesetters.kerns.handler")
+ enabled = true
+ end
+ if factor ~= 0 then
+ local a = factors[factor]
+ if not a then
+ a = #mapping + 1
+ factors[factors], mapping[a] = a, factor
+ end
+ factor = a
+ end
+ texattribute[a_kerns] = factor
+ return factor
+end
+
+local function process(namespace,attribute,head)
+ return do_process(namespace,attribute,head) -- no direct map, because else fourth argument is tail == true
end
-lists.handle_kerning = nodes.install_attribute_handler {
- name = "kern",
+kerns.handler = nodes.installattributehandler {
+ name = "kern",
namespace = kerns,
- processor = kerns.process,
+ processor = process,
}
-
-function kerns.enable()
- tasks.enableaction("processors","lists.handle_kerning")
-end