diff options
author | Hans Hagen <pragma@wxs.nl> | 2013-05-19 19:27:00 +0200 |
---|---|---|
committer | Hans Hagen <pragma@wxs.nl> | 2013-05-19 19:27:00 +0200 |
commit | 9a10021cd4cb23995ad3ffa915fc5b7f6890aaf8 (patch) | |
tree | 983e02c29872e4713a10a9dc8ae7708c6da3de88 /tex/context/base/typo-brk.lua | |
parent | 0deffde58a47f5c85a46a7d999ff9cf817b81cef (diff) | |
download | context-9a10021cd4cb23995ad3ffa915fc5b7f6890aaf8.tar.gz |
beta 2013.05.19 19:27
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 d6326ebeb..532909a30 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
|