diff options
author | Taco Hoekwater <taco@elvenkind.com> | 2011-06-01 08:54:21 +0000 |
---|---|---|
committer | Taco Hoekwater <taco@elvenkind.com> | 2011-06-01 08:54:21 +0000 |
commit | d7ccb42582f85acf30568913610ccf4d602023fb (patch) | |
tree | 7292e3545a420676878e7451b68892d360c62cb6 /Master/texmf-dist/tex/context/base/typo-krn.lua | |
parent | 2d62a6fe9b80def59c392268022f1f9a2d6e358f (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.lua | 204 |
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 |