diff options
author | Marius <mariausol@gmail.com> | 2010-07-04 15:32:09 +0300 |
---|---|---|
committer | Marius <mariausol@gmail.com> | 2010-07-04 15:32:09 +0300 |
commit | 85b7bc695629926641c7cb752fd478adfdf374f3 (patch) | |
tree | 80293f5aaa7b95a500a78392c39688d8ee7a32fc /tex/context/base/typo-brk.lua | |
download | context-85b7bc695629926641c7cb752fd478adfdf374f3.tar.gz |
stable 2010-05-24 13:10
Diffstat (limited to 'tex/context/base/typo-brk.lua')
-rw-r--r-- | tex/context/base/typo-brk.lua | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/tex/context/base/typo-brk.lua b/tex/context/base/typo-brk.lua new file mode 100644 index 000000000..8f7a00f9d --- /dev/null +++ b/tex/context/base/typo-brk.lua @@ -0,0 +1,208 @@ +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 settings_to_array = aux.settings_to_array +local has_attribute = node.has_attribute +local unset_attribute = node.unset_attribute +local set_attribute = node.set_attribute +local copy_node = node.copy +local free_node = node.free +local insert_node_before = node.insert_before +local insert_node_after = node.insert_after +local make_penalty_node = nodes.penalty +local make_glue_node = nodes.glue +local make_disc_node = nodes.disc +local make_glyph_node = nodes.glyph +local remove_node = nodes.remove -- ! nodes +local tonodes = blobs.tonodes + +local glyph = node.id("glyph") +local kern = node.id("kern") + +breakpoints = breakpoints or { } +breakpoints.mapping = breakpoints.mapping or { } +breakpoints.methods = breakpoints.methods or { } +breakpoints.attribute = attributes.private("breakpoint") + +storage.register("breakpoints/mapping", breakpoints.mapping, "breakpoints.mapping") + +local mapping = breakpoints.mapping + +function breakpoints.setreplacement(id,char,language,settings) + char = utfbyte(char) + local map = mapping[id] + if not map then + map = { } + mapping[id] = map + end + local cmap = map[char] + if not cmap then + cmap = { } + map[char] = cmap + end + local left, right, middle = settings.left, settings.right, settings.middle + cmap[language or ""] = { + kind = tonumber(settings.kind) 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 { kind or 1, before or 1, after or 1 } +end + +local function insert_break(head,start,before,after) + insert_node_before(head,start,make_penalty_node(before)) + insert_node_before(head,start,make_glue_node(0)) + insert_node_after(head,start,make_glue_node(0)) + insert_node_after(head,start,make_penalty_node(after)) +end + +breakpoints.methods[1] = function(head,start) + if start.prev and start.next then + insert_break(head,start,10000,0) + end + return head, start +end +breakpoints.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,make_disc_node()) + 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 +breakpoints.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,make_disc_node()) + 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 +breakpoints.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,make_disc_node()) + start.pre, start.post, start.replace = copy_node(tmp), copy_node(tmp), tmp + insert_break(head,start,10000,10000) + end + return head, start +end +breakpoints.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,make_disc_node()) + start.pre, start.post, start.replace = tonodes(settings.right,tmp), tonodes(settings.left,tmp), tonodes(settings.middle,tmp) + free_node(tmp) + insert_break(head,start,10000,10000) + end + return head, start +end + +local methods = breakpoints.methods + +function breakpoints.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 then + local attr = has_attribute(start,attribute) + if attr and attr > 0 then + unset_attribute(start,attribute) -- maybe test for subtype > 256 (faster) + -- look ahead and back n chars + local map = mapping[attr] + if map then + 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 then -- gamble on same attribute (not that important actually) + if map[next.char] then + break + elseif m == 1 then + local method = methods[smap.kind] + if method then + head, start = method(head,start,smap) + done = true + end + break + else + m = m - 1 + next = next.next + end + elseif id == kern and next.subtype == 0 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 and start.subtype == 0 then + -- ignore intercharacter kerning, will go way + else + n = 0 + end + start = start.next + end + return head, done +end + +chars.handle_breakpoints = nodes.install_attribute_handler { + name = "breakpoint", + namespace = breakpoints, + processor = breakpoints.process, +} + +function breakpoints.enable() + tasks.enableaction("processors","chars.handle_breakpoints") +end |