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-cap.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-cap.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/typo-cap.lua | 203 |
1 files changed, 136 insertions, 67 deletions
diff --git a/Master/texmf-dist/tex/context/base/typo-cap.lua b/Master/texmf-dist/tex/context/base/typo-cap.lua index 5f741da7c1d..2e20a95e7e4 100644 --- a/Master/texmf-dist/tex/context/base/typo-cap.lua +++ b/Master/texmf-dist/tex/context/base/typo-cap.lua @@ -8,36 +8,73 @@ if not modules then modules = { } end modules ['typo-cap'] = { local next, type = next, type local format, insert = string.format, table.insert +local div = math.div -local trace_casing = false trackers.register("nodes.casing", function(v) trace_casing = v end) +local trace_casing = false trackers.register("typesetters.casing", function(v) trace_casing = v end) -local has_attribute = node.has_attribute -local unset_attribute = node.unset_attribute -local set_attribute = node.set_attribute -local traverse_id = node.traverse_id +local report_casing = logs.reporter("typesetting","casing") -local glyph = node.id("glyph") -local kern = node.id("kern") +local nodes, node = nodes, node -local fontdata = fonts.ids -local fontchar = fonts.chr -local chardata = characters.data +local has_attribute = node.has_attribute +local unset_attribute = node.unset_attribute +local set_attribute = node.set_attribute +local traverse_id = node.traverse_id +local copy_node = node.copy -cases = cases or { } -cases.actions = { } -cases.attribute = attributes.private("case") +local texattribute = tex.attribute -local actions = cases.actions -local lastfont = nil +local nodecodes = nodes.nodecodes +local skipcodes = nodes.skipcodes +local kerncodes = nodes.kerncodes --- we use char0 as placeholder for the larger font +local glyph_code = nodecodes.glyph +local kern_code = nodecodes.kern -local function helper(start, code, codes, special, attribute, once) +local kerning_code = kerncodes.kerning +local userskip_code = skipcodes.userskip + +local tasks = nodes.tasks + +local fonthashes = fonts.hashes +local fontdata = fonthashes.identifiers +local fontchar = fonthashes.characters + +local chardata = characters.data + +typesetters = typesetters or { } +local typesetters = typesetters + +typesetters.cases = typesetters.cases or { } +local cases = typesetters.cases + +cases.actions = { } +local actions = cases.actions +cases.attribute = c_cases -- no longer needed +local a_cases = attributes.private("case") + +local lastfont = nil + +-- we use char(0) as placeholder for the larger font, so we need to remove it +-- before it can do further harm +-- +-- we could do the whole glyph run here (till no more attributes match) but +-- then we end up with more code .. maybe i will clean this up anyway as the +-- lastfont hack is somewhat ugly .. on the other hand, we need to deal with +-- cases like: +-- +-- \WORD {far too \Word{many \WORD{more \word{pushed} in between} useless} words} + +local uccodes = characters.uccodes +local lccodes = characters.lccodes + +local function helper(start, codes, special, attribute, once) local char = start.char - local dc = chardata[char] + local dc = codes[char] if dc then local fnt = start.font if special then + -- will become function if start.char == 0 then lastfont = fnt local prev, next = start.prev, start.next @@ -45,24 +82,24 @@ local function helper(start, code, codes, special, attribute, once) if next then next.prev = prev end +--~ node.free(start) return prev, true - elseif lastfont and start.prev.id ~= glyph then + elseif lastfont and start.prev.id ~= glyph_code then fnt = lastfont start.font = lastfont end end - -- local ifc = fontdata[fnt].characters local ifc = fontchar[fnt] - local ucs = dc[codes] - if ucs then + if type(dc) == "table" then local ok = true - for i=1,#ucs do - ok = ok and ifc[ucs[i]] + for i=1,#dc do + ok = ok and ifc[dc[i]] end if ok then + -- tood; use generic injector local prev, original = start, start - for i=1,#ucs do - local chr = ucs[i] + for i=1,#dc do + local chr = dc[i] prev = start if i == 1 then start.char = chr @@ -84,10 +121,8 @@ local function helper(start, code, codes, special, attribute, once) end if once then lastfont = nil end return start, false - end - local uc = dc[code] - if uc and ifc[uc] then - start.char = uc + elseif ifc[dc] then + start.char = dc if once then lastfont = nil end return start, true end @@ -98,28 +133,32 @@ end actions[1] = function(start,attribute) lastfont = nil - return helper(start,'uccode','uccodes') + return helper(start,uccodes) end actions[2] = function(start,attribute) lastfont = nil - return helper(start,'lccode','lccodes') + return helper(start,lccodes) end -actions[3] = function(start,attribute) +actions[3] = function(start,attribute,attr) lastfont = nil local prev = start.prev - if prev and prev.id == kern and prev.subtype == 0 then + if prev and prev.id == kern_code and prev.subtype == kerning_code then prev = prev.prev end - if not prev or prev.id ~= glyph then + if not prev or prev.id ~= glyph_code then --- only the first character is treated - for n in traverse_id(glyph,start.next) do - if has_attribute(n,attribute) then + for n in traverse_id(glyph_code,start.next) do + if has_attribute(n,attribute) == attr then unset_attribute(n,attribute) + else + -- break -- we can have nested mess end end - return helper(start,'uccode','uccodes') + -- we could return the last in the range and save some scanning + -- but why bother + return helper(start,uccodes) else return start, false end @@ -128,22 +167,22 @@ end actions[4] = function(start,attribute) lastfont = nil local prev = start.prev - if prev and prev.id == kern and prev.subtype == 0 then + if prev and prev.id == kern_code and prev.subtype == kerning_code then prev = prev.prev end - if not prev or prev.id ~= glyph then - return helper(start,'uccode','uccodes') + if not prev or prev.id ~= glyph_code then + return helper(start,uccodes) else return start, false end end actions[5] = function(start,attribute) -- 3 - return helper(start,'uccode','uccodes',true,attribute,true) + return helper(start,uccodes,true,attribute,true) end actions[6] = function(start,attribute) -- 4 - return helper(start,'uccode','uccodes',true,attribute,false) + return helper(start,uccodes,true,attribute,false) end actions[8] = function(start) @@ -152,59 +191,89 @@ actions[8] = function(start) local mr = math.random -- local tfm = fontdata[start.font].characters local tfm = fontchar[start.font] - if chardata[ch].lccode then + if lccodes[ch] then while true do local d = chardata[mr(1,0xFFFF)] if d then - local uc = d.uccode - if uc and tfm[uc] then + local uc = uccodes[d] + if uc and tfm[uc] then -- this also intercepts tables start.char = uc return start, true end end end - elseif chardata[ch].uccode then + elseif uccodes[ch] then while true do local d = chardata[mr(1,0xFFFF)] if d then - local lc = d.lccode - if lc and tfm[lc] then + local lc = lccodes[d] + if lc and tfm[lc] then -- this also intercepts tables start.char = lc return start, true end end end - else - return start, false end + return start, false end -- node.traverse_id_attr -function cases.process(namespace,attribute,head) -- not real fast but also not used on much data +local function process(namespace,attribute,head) -- not real fast but also not used on much data lastfont = nil + local lastattr = nil local done = false - for start in traverse_id(glyph,head) do - local attr = has_attribute(start,attribute) - if attr and attr > 0 then - unset_attribute(start,attribute) - local action = actions[attr] - if action then - local _, ok = action(start,attribute) - done = done and ok + local start = head + while start do -- while because start can jump ahead + local id = start.id + if id == glyph_code then + local attr = has_attribute(start,attribute) + if attr and attr > 0 then + if attr ~= lastattr then + lastfont = nil + lastattr = attr + end + unset_attribute(start,attribute) + local action = actions[attr%100] -- map back to low number + if action then + start, ok = action(start,attribute,attr) + done = done and ok + if trace_casing then + report_casing("case trigger %s, instance %s, result %s",attr%100,div(attr,100),tostring(ok)) + end + elseif trace_casing then + report_casing("unknown case trigger %s",attr) + end end end + if start then + start = start.next + end end lastfont = nil return head, done end -chars.handle_casing = nodes.install_attribute_handler { - name = "case", - namespace = cases, - processor = cases.process, -} +local m, enabled = 0, false -- a trick to make neighbouring ranges work -function cases.enable() - tasks.enableaction("processors","chars.handle_casing") +function cases.set(n) + if not enabled then + tasks.enableaction("processors","typesetters.cases.handler") + if trace_casing then + report_casing("enabling case handler") + end + enabled = true + end + if m == 100 then + m = 1 + else + m = m + 1 + end + texattribute[a_cases] = m * 100 + n end + +cases.handler = nodes.installattributehandler { + name = "case", + namespace = cases, + processor = process, +} |