diff options
author | Hans Hagen <pragma@wxs.nl> | 2013-05-20 02:00:00 +0200 |
---|---|---|
committer | Hans Hagen <pragma@wxs.nl> | 2013-05-20 02:00:00 +0200 |
commit | bd95a21d2b31a5fab1b4cc7c2b0334823fb3a3e9 (patch) | |
tree | 831128c411476f077eb7910d8c08f524d3ee43ec /tex/context/base/typo-brk.lua | |
parent | 9a10021cd4cb23995ad3ffa915fc5b7f6890aaf8 (diff) | |
download | context-bd95a21d2b31a5fab1b4cc7c2b0334823fb3a3e9.tar.gz |
beta 2013.05.20 02:00
Diffstat (limited to 'tex/context/base/typo-brk.lua')
-rw-r--r-- | tex/context/base/typo-brk.lua | 604 |
1 files changed, 302 insertions, 302 deletions
diff --git a/tex/context/base/typo-brk.lua b/tex/context/base/typo-brk.lua index 532909a30..d6326ebeb 100644 --- a/tex/context/base/typo-brk.lua +++ b/tex/context/base/typo-brk.lua @@ -1,302 +1,302 @@ -if not modules then modules = { } end modules ['typo-brk'] = {
- version = 1.001,
- comment = "companion to typo-brk.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- this code dates from the beginning and is kind of experimental; it
--- will be optimized and improved soon
-
-local next, type, tonumber = next, type, tonumber
-local utfbyte, utfchar = utf.byte, utf.char
-local format = string.format
-
-local trace_breakpoints = false trackers.register("typesetters.breakpoints", function(v) trace_breakpoints = v end)
-
-local report_breakpoints = logs.reporter("typesetting","breakpoints")
-
-local nodes, node = nodes, node
-
-local settings_to_array = utilities.parsers.settings_to_array
-local copy_node = node.copy
-local copy_nodelist = node.copy_list
-local free_node = node.free
-local insert_node_before = node.insert_before
-local insert_node_after = node.insert_after
-local remove_node = nodes.remove -- ! nodes
-
-local tonodes = nodes.tonodes
-
-local texattribute = tex.attribute
-local unsetvalue = attributes.unsetvalue
-
-local nodepool = nodes.pool
-local tasks = nodes.tasks
-
-local v_reset = interfaces.variables.reset
-
-local new_penalty = nodepool.penalty
-local new_glue = nodepool.glue
-local new_disc = nodepool.disc
-
-local nodecodes = nodes.nodecodes
-local kerncodes = nodes.kerncodes
-
-local glyph_code = nodecodes.glyph
-local kern_code = nodecodes.kern
-
-local kerning_code = kerncodes.kerning
-
-local typesetters = typesetters
-
-typesetters.breakpoints = typesetters.breakpoints or {}
-local breakpoints = typesetters.breakpoints
-
-breakpoints.mapping = breakpoints.mapping or { }
-breakpoints.numbers = breakpoints.numbers or { }
-
-breakpoints.methods = breakpoints.methods or { }
-local methods = breakpoints.methods
-
-local a_breakpoints = attributes.private("breakpoint")
-breakpoints.attribute = a_breakpoints
-
-storage.register("typesetters/breakpoints/mapping", breakpoints.mapping, "typesetters.breakpoints.mapping")
-
-local mapping = breakpoints.mapping
-local numbers = breakpoints.mapping
-
-for i=1,#mapping do
- local m = mapping[i]
- numbers[m.name] = m
-end
-
-local function insert_break(head,start,before,after)
- insert_node_before(head,start,new_penalty(before))
- insert_node_before(head,start,new_glue(0))
- insert_node_after(head,start,new_glue(0))
- insert_node_after(head,start,new_penalty(after))
-end
-
-methods[1] = function(head,start)
- if start.prev and start.next then
- insert_break(head,start,10000,0)
- end
- return head, start
-end
-
-methods[2] = function(head,start) -- ( => (-
- if start.prev and start.next then
- local tmp
- head, start, tmp = remove_node(head,start)
- head, start = insert_node_before(head,start,new_disc())
- start.attr = copy_nodelist(tmp.attr) -- todo: critical only
- start.replace = tmp
- local tmp, hyphen = copy_node(tmp), copy_node(tmp)
- hyphen.char = languages.prehyphenchar(tmp.lang)
- tmp.next, hyphen.prev = hyphen, tmp
- start.post = tmp
- insert_break(head,start,10000,10000)
- end
- return head, start
-end
-
-methods[3] = function(head,start) -- ) => -)
- if start.prev and start.next then
- local tmp
- head, start, tmp = remove_node(head,start)
- head, start = insert_node_before(head,start,new_disc())
- start.attr = copy_nodelist(tmp.attr) -- todo: critical only
- start.replace = tmp
- local tmp, hyphen = copy_node(tmp), copy_node(tmp)
- hyphen.char = languages.prehyphenchar(tmp.lang)
- tmp.prev, hyphen.next = hyphen, tmp
- start.pre = hyphen
- insert_break(head,start,10000,10000)
- end
- return head, start
-end
-
-methods[4] = function(head,start) -- - => - - -
- if start.prev and start.next then
- local tmp
- head, start, tmp = remove_node(head,start)
- head, start = insert_node_before(head,start,new_disc())
- start.attr = copy_nodelist(tmp.attr) -- todo: critical only
- start.pre, start.post, start.replace = copy_node(tmp), copy_node(tmp), tmp
- insert_break(head,start,10000,10000)
- end
- return head, start
-end
-
-methods[5] = function(head,start,settings) -- x => p q r
- if start.prev and start.next then
- local tmp
- head, start, tmp = remove_node(head,start)
- head, start = insert_node_before(head,start,new_disc())
- local attr = tmp.attr
- local font = tmp.font
- start.attr = copy_nodelist(attr) -- todo: critical only
- local left, right, middle = settings.left, settings.right, settings.middle
- if left then
- start.pre = tonodes(tostring(left),font,attr) -- was right
- end
- if right then
- start.post = tonodes(tostring(right),font,attr) -- was left
- end
- if middle then
- start.replace = tonodes(tostring(middle),font,attr)
- end
- free_node(tmp)
- insert_break(head,start,10000,10000)
- end
- return head, start
-end
-
-local function process(namespace,attribute,head)
- local done, numbers = false, languages.numbers
- local start, n = head, 0
- while start do
- local id = start.id
- if id == glyph_code then
- local attr = start[a_breakpoints]
- if attr and attr > 0 then
- start[a_breakpoints] = unsetvalue -- maybe test for subtype > 256 (faster)
- -- look ahead and back n chars
- local data = mapping[attr]
- if data then
- local map = data.characters
- local cmap = map[start.char]
- if cmap then
- local lang = start.lang
- -- we do a sanity check for language
- local smap = lang and lang >= 0 and lang < 0x7FFF and (cmap[numbers[lang]] or cmap[""])
- if smap then
- if n >= smap.nleft then
- local m = smap.nright
- local next = start.next
- while next do -- gamble on same attribute (not that important actually)
- local id = next.id
- if id == glyph_code then -- gamble on same attribute (not that important actually)
- if map[next.char] then
- break
- elseif m == 1 then
- local method = methods[smap.type]
- if method then
- head, start = method(head,start,smap)
- done = true
- end
- break
- else
- m = m - 1
- next = next.next
- end
- elseif id == kern_code and next.subtype == kerning_code then
- next = next.next
- -- ignore intercharacter kerning, will go way
- else
- -- we can do clever and set n and jump ahead but ... not now
- break
- end
- end
- end
- n = 0
- else
- n = n + 1
- end
- else
- n = n + 1
- end
- else
- n = 0
- end
- else
- -- n = n + 1 -- if we want single char handling (|-|) then we will use grouping and then we need this
- end
- elseif id == kern_code and start.subtype == kerning_code then
- -- ignore intercharacter kerning, will go way
- else
- n = 0
- end
- start = start.next
- end
- return head, done
-end
-
-local enabled = false
-
-function breakpoints.define(name)
- local data = numbers[name]
- if data then
- -- error
- else
- local number = #mapping + 1
- local data = {
- name = name,
- number = number,
- characters = { },
- }
- mapping[number] = data
- numbers[name] = data
- end
-end
-
-function breakpoints.setreplacement(name,char,language,settings)
- char = utfbyte(char)
- local data = numbers[name]
- if data then
- local characters = data.characters
- local cmap = characters[char]
- if not cmap then
- cmap = { }
- characters[char] = cmap
- end
- local left, right, middle = settings.left, settings.right, settings.middle
- cmap[language or ""] = {
- type = tonumber(settings.type) or 1,
- nleft = tonumber(settings.nleft) or 1,
- nright = tonumber(settings.nright) or 1,
- left = left ~= "" and left or nil,
- right = right ~= "" and right or nil,
- middle = middle ~= "" and middle or nil,
- } -- was { type or 1, before or 1, after or 1 }
- end
-end
-
-function breakpoints.set(n)
- if n == v_reset then
- n = unsetvalue
- else
- n = mapping[n]
- if not n then
- n = unsetvalue
- else
- if not enabled then
- if trace_breakpoints then
- report_breakpoints("enabling breakpoints handler")
- end
- tasks.enableaction("processors","typesetters.breakpoints.handler")
- end
- n = n.number
- end
- end
- texattribute[a_breakpoints] = n
-end
-
-breakpoints.handler = nodes.installattributehandler {
- name = "breakpoint",
- namespace = breakpoints,
- processor = process,
-}
-
--- function breakpoints.enable()
--- tasks.enableaction("processors","typesetters.breakpoints.handler")
--- end
-
--- interface
-
-commands.definebreakpoints = breakpoints.define
-commands.definebreakpoint = breakpoints.setreplacement
-commands.setbreakpoints = breakpoints.set
+if not modules then modules = { } end modules ['typo-brk'] = { + version = 1.001, + comment = "companion to typo-brk.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- this code dates from the beginning and is kind of experimental; it +-- will be optimized and improved soon + +local next, type, tonumber = next, type, tonumber +local utfbyte, utfchar = utf.byte, utf.char +local format = string.format + +local trace_breakpoints = false trackers.register("typesetters.breakpoints", function(v) trace_breakpoints = v end) + +local report_breakpoints = logs.reporter("typesetting","breakpoints") + +local nodes, node = nodes, node + +local settings_to_array = utilities.parsers.settings_to_array +local copy_node = node.copy +local copy_nodelist = node.copy_list +local free_node = node.free +local insert_node_before = node.insert_before +local insert_node_after = node.insert_after +local remove_node = nodes.remove -- ! nodes + +local tonodes = nodes.tonodes + +local texattribute = tex.attribute +local unsetvalue = attributes.unsetvalue + +local nodepool = nodes.pool +local tasks = nodes.tasks + +local v_reset = interfaces.variables.reset + +local new_penalty = nodepool.penalty +local new_glue = nodepool.glue +local new_disc = nodepool.disc + +local nodecodes = nodes.nodecodes +local kerncodes = nodes.kerncodes + +local glyph_code = nodecodes.glyph +local kern_code = nodecodes.kern + +local kerning_code = kerncodes.kerning + +local typesetters = typesetters + +typesetters.breakpoints = typesetters.breakpoints or {} +local breakpoints = typesetters.breakpoints + +breakpoints.mapping = breakpoints.mapping or { } +breakpoints.numbers = breakpoints.numbers or { } + +breakpoints.methods = breakpoints.methods or { } +local methods = breakpoints.methods + +local a_breakpoints = attributes.private("breakpoint") +breakpoints.attribute = a_breakpoints + +storage.register("typesetters/breakpoints/mapping", breakpoints.mapping, "typesetters.breakpoints.mapping") + +local mapping = breakpoints.mapping +local numbers = breakpoints.mapping + +for i=1,#mapping do + local m = mapping[i] + numbers[m.name] = m +end + +local function insert_break(head,start,before,after) + insert_node_before(head,start,new_penalty(before)) + insert_node_before(head,start,new_glue(0)) + insert_node_after(head,start,new_glue(0)) + insert_node_after(head,start,new_penalty(after)) +end + +methods[1] = function(head,start) + if start.prev and start.next then + insert_break(head,start,10000,0) + end + return head, start +end + +methods[2] = function(head,start) -- ( => (- + if start.prev and start.next then + local tmp + head, start, tmp = remove_node(head,start) + head, start = insert_node_before(head,start,new_disc()) + start.attr = copy_nodelist(tmp.attr) -- todo: critical only + start.replace = tmp + local tmp, hyphen = copy_node(tmp), copy_node(tmp) + hyphen.char = languages.prehyphenchar(tmp.lang) + tmp.next, hyphen.prev = hyphen, tmp + start.post = tmp + insert_break(head,start,10000,10000) + end + return head, start +end + +methods[3] = function(head,start) -- ) => -) + if start.prev and start.next then + local tmp + head, start, tmp = remove_node(head,start) + head, start = insert_node_before(head,start,new_disc()) + start.attr = copy_nodelist(tmp.attr) -- todo: critical only + start.replace = tmp + local tmp, hyphen = copy_node(tmp), copy_node(tmp) + hyphen.char = languages.prehyphenchar(tmp.lang) + tmp.prev, hyphen.next = hyphen, tmp + start.pre = hyphen + insert_break(head,start,10000,10000) + end + return head, start +end + +methods[4] = function(head,start) -- - => - - - + if start.prev and start.next then + local tmp + head, start, tmp = remove_node(head,start) + head, start = insert_node_before(head,start,new_disc()) + start.attr = copy_nodelist(tmp.attr) -- todo: critical only + start.pre, start.post, start.replace = copy_node(tmp), copy_node(tmp), tmp + insert_break(head,start,10000,10000) + end + return head, start +end + +methods[5] = function(head,start,settings) -- x => p q r + if start.prev and start.next then + local tmp + head, start, tmp = remove_node(head,start) + head, start = insert_node_before(head,start,new_disc()) + local attr = tmp.attr + local font = tmp.font + start.attr = copy_nodelist(attr) -- todo: critical only + local left, right, middle = settings.left, settings.right, settings.middle + if left then + start.pre = tonodes(tostring(left),font,attr) -- was right + end + if right then + start.post = tonodes(tostring(right),font,attr) -- was left + end + if middle then + start.replace = tonodes(tostring(middle),font,attr) + end + free_node(tmp) + insert_break(head,start,10000,10000) + end + return head, start +end + +local function process(namespace,attribute,head) + local done, numbers = false, languages.numbers + local start, n = head, 0 + while start do + local id = start.id + if id == glyph_code then + local attr = start[a_breakpoints] + if attr and attr > 0 then + start[a_breakpoints] = unsetvalue -- maybe test for subtype > 256 (faster) + -- look ahead and back n chars + local data = mapping[attr] + if data then + local map = data.characters + local cmap = map[start.char] + if cmap then + local lang = start.lang + -- we do a sanity check for language + local smap = lang and lang >= 0 and lang < 0x7FFF and (cmap[numbers[lang]] or cmap[""]) + if smap then + if n >= smap.nleft then + local m = smap.nright + local next = start.next + while next do -- gamble on same attribute (not that important actually) + local id = next.id + if id == glyph_code then -- gamble on same attribute (not that important actually) + if map[next.char] then + break + elseif m == 1 then + local method = methods[smap.type] + if method then + head, start = method(head,start,smap) + done = true + end + break + else + m = m - 1 + next = next.next + end + elseif id == kern_code and next.subtype == kerning_code then + next = next.next + -- ignore intercharacter kerning, will go way + else + -- we can do clever and set n and jump ahead but ... not now + break + end + end + end + n = 0 + else + n = n + 1 + end + else + n = n + 1 + end + else + n = 0 + end + else + -- n = n + 1 -- if we want single char handling (|-|) then we will use grouping and then we need this + end + elseif id == kern_code and start.subtype == kerning_code then + -- ignore intercharacter kerning, will go way + else + n = 0 + end + start = start.next + end + return head, done +end + +local enabled = false + +function breakpoints.define(name) + local data = numbers[name] + if data then + -- error + else + local number = #mapping + 1 + local data = { + name = name, + number = number, + characters = { }, + } + mapping[number] = data + numbers[name] = data + end +end + +function breakpoints.setreplacement(name,char,language,settings) + char = utfbyte(char) + local data = numbers[name] + if data then + local characters = data.characters + local cmap = characters[char] + if not cmap then + cmap = { } + characters[char] = cmap + end + local left, right, middle = settings.left, settings.right, settings.middle + cmap[language or ""] = { + type = tonumber(settings.type) or 1, + nleft = tonumber(settings.nleft) or 1, + nright = tonumber(settings.nright) or 1, + left = left ~= "" and left or nil, + right = right ~= "" and right or nil, + middle = middle ~= "" and middle or nil, + } -- was { type or 1, before or 1, after or 1 } + end +end + +function breakpoints.set(n) + if n == v_reset then + n = unsetvalue + else + n = mapping[n] + if not n then + n = unsetvalue + else + if not enabled then + if trace_breakpoints then + report_breakpoints("enabling breakpoints handler") + end + tasks.enableaction("processors","typesetters.breakpoints.handler") + end + n = n.number + end + end + texattribute[a_breakpoints] = n +end + +breakpoints.handler = nodes.installattributehandler { + name = "breakpoint", + namespace = breakpoints, + processor = process, +} + +-- function breakpoints.enable() +-- tasks.enableaction("processors","typesetters.breakpoints.handler") +-- end + +-- interface + +commands.definebreakpoints = breakpoints.define +commands.definebreakpoint = breakpoints.setreplacement +commands.setbreakpoints = breakpoints.set |