summaryrefslogtreecommitdiff
path: root/tex/context/base/typo-cap.lua
diff options
context:
space:
mode:
authorMarius <mariausol@gmail.com>2010-07-04 15:32:09 +0300
committerMarius <mariausol@gmail.com>2010-07-04 15:32:09 +0300
commit85b7bc695629926641c7cb752fd478adfdf374f3 (patch)
tree80293f5aaa7b95a500a78392c39688d8ee7a32fc /tex/context/base/typo-cap.lua
downloadcontext-85b7bc695629926641c7cb752fd478adfdf374f3.tar.gz
stable 2010-05-24 13:10
Diffstat (limited to 'tex/context/base/typo-cap.lua')
-rw-r--r--tex/context/base/typo-cap.lua210
1 files changed, 210 insertions, 0 deletions
diff --git a/tex/context/base/typo-cap.lua b/tex/context/base/typo-cap.lua
new file mode 100644
index 000000000..5f741da7c
--- /dev/null
+++ b/tex/context/base/typo-cap.lua
@@ -0,0 +1,210 @@
+if not modules then modules = { } end modules ['typo-cap'] = {
+ version = 1.001,
+ comment = "companion to typo-cap.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local next, type = next, type
+local format, insert = string.format, table.insert
+
+local trace_casing = false trackers.register("nodes.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 glyph = node.id("glyph")
+local kern = node.id("kern")
+
+local fontdata = fonts.ids
+local fontchar = fonts.chr
+local chardata = characters.data
+
+cases = cases or { }
+cases.actions = { }
+cases.attribute = attributes.private("case")
+
+local actions = cases.actions
+local lastfont = nil
+
+-- we use char0 as placeholder for the larger font
+
+local function helper(start, code, codes, special, attribute, once)
+ local char = start.char
+ local dc = chardata[char]
+ if dc then
+ local fnt = start.font
+ if special then
+ if start.char == 0 then
+ lastfont = fnt
+ local prev, next = start.prev, start.next
+ prev.next = next
+ if next then
+ next.prev = prev
+ end
+ return prev, true
+ elseif lastfont and start.prev.id ~= glyph then
+ fnt = lastfont
+ start.font = lastfont
+ end
+ end
+ -- local ifc = fontdata[fnt].characters
+ local ifc = fontchar[fnt]
+ local ucs = dc[codes]
+ if ucs then
+ local ok = true
+ for i=1,#ucs do
+ ok = ok and ifc[ucs[i]]
+ end
+ if ok then
+ local prev, original = start, start
+ for i=1,#ucs do
+ local chr = ucs[i]
+ prev = start
+ if i == 1 then
+ start.char = chr
+ else
+ local g = copy_node(original)
+ g.char = chr
+ local next = start.next
+ g.prev = start
+ if next then
+ g.next = next
+ start.next = g
+ next.prev = g
+ end
+ start = g
+ end
+ end
+ if once then lastfont = nil end
+ return prev, true
+ end
+ if once then lastfont = nil end
+ return start, false
+ end
+ local uc = dc[code]
+ if uc and ifc[uc] then
+ start.char = uc
+ if once then lastfont = nil end
+ return start, true
+ end
+ end
+ if once then lastfont = nil end
+ return start, false
+end
+
+actions[1] = function(start,attribute)
+ lastfont = nil
+ return helper(start,'uccode','uccodes')
+end
+
+actions[2] = function(start,attribute)
+ lastfont = nil
+ return helper(start,'lccode','lccodes')
+end
+
+actions[3] = function(start,attribute)
+ lastfont = nil
+ local prev = start.prev
+ if prev and prev.id == kern and prev.subtype == 0 then
+ prev = prev.prev
+ end
+ if not prev or prev.id ~= glyph then
+ --- only the first character is treated
+ for n in traverse_id(glyph,start.next) do
+ if has_attribute(n,attribute) then
+ unset_attribute(n,attribute)
+ end
+ end
+ return helper(start,'uccode','uccodes')
+ else
+ return start, false
+ end
+end
+
+actions[4] = function(start,attribute)
+ lastfont = nil
+ local prev = start.prev
+ if prev and prev.id == kern and prev.subtype == 0 then
+ prev = prev.prev
+ end
+ if not prev or prev.id ~= glyph then
+ return helper(start,'uccode','uccodes')
+ else
+ return start, false
+ end
+end
+
+actions[5] = function(start,attribute) -- 3
+ return helper(start,'uccode','uccodes',true,attribute,true)
+end
+
+actions[6] = function(start,attribute) -- 4
+ return helper(start,'uccode','uccodes',true,attribute,false)
+end
+
+actions[8] = function(start)
+ lastfont = nil
+ local ch = start.char
+ local mr = math.random
+ -- local tfm = fontdata[start.font].characters
+ local tfm = fontchar[start.font]
+ if chardata[ch].lccode then
+ while true do
+ local d = chardata[mr(1,0xFFFF)]
+ if d then
+ local uc = d.uccode
+ if uc and tfm[uc] then
+ start.char = uc
+ return start, true
+ end
+ end
+ end
+ elseif chardata[ch].uccode then
+ while true do
+ local d = chardata[mr(1,0xFFFF)]
+ if d then
+ local lc = d.lccode
+ if lc and tfm[lc] then
+ start.char = lc
+ return start, true
+ end
+ end
+ end
+ else
+ return start, false
+ end
+end
+
+-- node.traverse_id_attr
+
+function cases.process(namespace,attribute,head) -- not real fast but also not used on much data
+ lastfont = 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
+ end
+ end
+ end
+ lastfont = nil
+ return head, done
+end
+
+chars.handle_casing = nodes.install_attribute_handler {
+ name = "case",
+ namespace = cases,
+ processor = cases.process,
+}
+
+function cases.enable()
+ tasks.enableaction("processors","chars.handle_casing")
+end