diff options
Diffstat (limited to 'Master/texmf-dist/tex/luatex/luatexko/luatexko.lua')
-rw-r--r-- | Master/texmf-dist/tex/luatex/luatexko/luatexko.lua | 162 |
1 files changed, 104 insertions, 58 deletions
diff --git a/Master/texmf-dist/tex/luatex/luatexko/luatexko.lua b/Master/texmf-dist/tex/luatex/luatexko/luatexko.lua index 1165d706bd7..b85cb734817 100644 --- a/Master/texmf-dist/tex/luatex/luatexko/luatexko.lua +++ b/Master/texmf-dist/tex/luatex/luatexko/luatexko.lua @@ -10,17 +10,25 @@ -- and version 1.3c or later is part of all distributions of LaTeX -- version 2006/05/20 or later. -module('luatexko', package.seeall) - local err,warn,info,log = luatexbase.provides_module({ name = 'luatexko', - date = '2013/05/19', - version = '1.1', + date = '2013/07/03', + version = 1.2, description = 'Korean linebreaking and font-switching', author = 'Dohyun Kim', license = 'LPPL v1.3+', }) +luatexko = luatexko or {} +local luatexko = luatexko + +local dotemphnode,rubynode,ulinebox = {},{},{} +luatexko.dotemphnode = dotemphnode +luatexko.rubynode = rubynode +luatexko.ulinebox = ulinebox +luatexko.hangulmain = luatexko.hangulmain or false +luatexko.hanjafontforhanja = luatexko.hanjafontforhanja or false + local stringbyte = string.byte local stringgsub = string.gsub local stringchar = string.char @@ -28,14 +36,14 @@ local stringfind = string.find local stringmatch = string.match local stringgmatch = string.gmatch local stringformat = string.format +local string_sub = string.sub local mathfloor = math.floor local tex_round = tex.round local tex_sp = tex.sp local fontdefine = font.define +local utf8char = unicode.utf8.char local fontdata = fonts.hashes.identifiers -local font_define_func = callback.find("define_font") -local utf8char = unicode.utf8.char local remove_node = node.remove local insert_before = node.insert_before @@ -67,7 +75,6 @@ local add_to_callback = luatexbase.add_to_callback local gluenode = node.id("glue") local gluespecnode = node.id("glue_spec") local glyphnode = node.id("glyph") -local discnode = node.id("disc") local mathnode = node.id("math") local hlistnode = node.id("hlist") local vlistnode = node.id("vlist") @@ -85,11 +92,6 @@ local new_rule = node.new(rulenode) local emsize = 655360 -dotemphnode = {} -rubynode = {} -ulinebox = {} -hanjafontforhanja = false - local cjkclass = { [0x2018] = 1, -- ‘ [0x201C] = 1, -- “ @@ -383,6 +385,7 @@ local latin_fullstop = { local latin_quotes = { [0x0028] = 0x0029, -- ( ) + [0x003C] = 0x003E, -- < > [0x2018] = 0x2019, -- ‘ ’ [0x201C] = 0x201D, -- “ ” } @@ -528,7 +531,7 @@ local function get_font_table (fid) if fontdata[fid] then return fontdata[fid] else - return font.getfont(fid) + return font.fonts[fid] end end end @@ -564,15 +567,20 @@ local function get_char_boundingbox(fid, chr) end local function get_unicode_char(curr) - if curr.char > 0 and curr.char < 0xF0000 then return curr.char end - local uni = has_attribute(curr, luakounicodeattr) + if (curr.char > 0 and curr.char < 0xE000) -- no pua + or (curr.char > 0xF8FF and curr.char < 0xF0000) then + return curr.char + end + -- tounicode is not reliable. backend bug + local uni = get_font_char(curr.font, curr.char) + uni = uni and uni.tounicode + uni = uni and string_sub(uni,1,4) -- seems ok for old hangul + if uni then return tonumber(uni,16) end + uni = has_attribute(curr, luakounicodeattr) if uni then return uni end return curr.char end ----------------------------- --- cjk linebreak and spacing ----------------------------- local function get_hlist_class_first (hlist) local curr = hlist.head while curr do @@ -606,6 +614,9 @@ local function get_hlist_class_last (hlist,prevchar,prevfont) return prevchar, prevfont end +---------------------------- +-- cjk linebreak and spacing +---------------------------- local function kanjiskip (head,curr) insert_before(head,curr,make_luako_glue(0, emsize*0.1, emsize*0.02)) end @@ -732,7 +743,7 @@ local function cjk_insert_nodes(head,curr,currchar,currfont,prevchar,prevfont) local stretch = 0 local shrink = emsize * cjk_glue_spec[p][c][2] insert_before(head,curr,make_luako_glue(width, stretch, shrink)) - elseif p < 10 and c < 10 and p ~= 8 and c ~= 9 then + elseif p < 10 and c < 9 then -- break between chosong and chosong kanjiskip(head,curr) elseif (p < 10 and c == 10) or (p == 10 and c < 10) then if xspcode[currchar] then @@ -780,20 +791,11 @@ local function cjk_insert_nodes(head,curr,currchar,currfont,prevchar,prevfont) koreanlatinskip(head,curr,currfont,prevfont,was_penalty) elseif p == 7 and c == 7 then interhangulskip(head,curr,currfont,prevfont,was_penalty) - elseif p < 10 and c < 10 and p ~= 8 and c ~= 9 then + elseif p < 10 and c < 9 then -- break between chosong and chosong interhanjaskip(head,curr,was_penalty) end end end - -- for dot emphasis - if has_attribute(curr,dotemphattr) - and c ~= 0 - and c ~= 7 - and p ~= 8 - and c ~= 8 then - unset_attribute(curr,dotemphattr) - end - return currchar,currfont end @@ -1348,26 +1350,22 @@ local function hangulspaceskip (engfont, hfontid, nglue) return tex_round(hsp), tex_round(hst), tex_round(hsh) end -local hangulfontlist = {} - local function font_substitute(head) for curr in traverse_id(glyphnode, head) do local eng = get_font_table(curr.font) local engfontchar = get_font_char(curr.font, curr.char) - if not eng then -- no font table of plain tex cm font - engfontchar = get_cjk_class(curr.char) == 10 - end if curr.char and not engfontchar then local korid = false local hangul = has_attribute(curr, hangfntattr) local hanja = has_attribute(curr, hanjfntattr) local ftable = {hangul, hanja} - if hanjafontforhanja then + if luatexko.hanjafontforhanja then local uni = get_unicode_char(curr) uni = uni and get_cjk_class(uni) if uni and uni < 7 then ftable = {hanja, hangul} end end - for _,fid in ipairs(ftable) do + for i=1,#ftable do + local fid = ftable[i] if fid then local c = get_font_char(fid, curr.char) if c then @@ -1375,7 +1373,9 @@ local function font_substitute(head) curr.font = fid -- adjust next glue by hangul font space local nxt = curr.next - if hangulmain and nxt and nxt.id == gluenode and nxt.subtype and nxt.subtype == 0 then + local hangulmain = eng and nxt and luatexko.hangulmain + hangulmain = hangulmain and get_font_char(fid, 32) + if hangulmain and nxt.id == gluenode and nxt.subtype and nxt.subtype == 0 then local sp,st,sh = hangulspaceskip(eng, fid, nxt) if sp and st and sh then nxt.spec.width = sp @@ -1414,7 +1414,7 @@ end ------------------------------------ --- vetical typesetting: EXPERIMENTAL -- don't use this +-- vertical typesetting: EXPERIMENTAL -- don't use this ------------------------------------ ---[[no vwidth in luaotfload v2 local tsbtable = {} @@ -1523,10 +1523,12 @@ local function cjk_vertical_font (vf) end local function activate_vertical_virtual (tfmdata,value) - if value then + local loaded = luatexbase.priority_in_callback("luaotfload.patch_font", + "luatexko.vertical_virtual_font") + if value and not loaded then add_to_callback("luaotfload.patch_font", cjk_vertical_font, - "luatexko.vetical_virtual_font") + "luatexko.vertical_virtual_font") end end @@ -1540,6 +1542,28 @@ otffeatures.register { } --no vwidth in luaotfload v2]] +local function reorderTM (head) + for curr in traverse_id(glyphnode, head) do + if curr.width > 0 then -- old hangul vertical typesetting is broken? + local uni = get_unicode_char(curr) + if uni and (uni == 0x302E or uni == 0x302F) then + local p = curr.prev + while p do + if p.id ~= glyphnode then break end + local pc = get_cjk_class(get_unicode_char(p)) + if pc == 7 or pc == 8 then + head = insert_before(head,p,copy_node(curr)) + head = remove_node(head,curr) + break + end + p = p.prev + end + end + end + end + return head +end + ---------------------------------- -- add to callback : pre-linebreak ---------------------------------- @@ -1557,6 +1581,7 @@ add_to_callback('hpack_filter', function(head) spread_ruby_base_box(head) head = compress_fullwidth_punctuations(head) -- head = no_ruby_at_margin(head) + head = reorderTM(head) return head end, 'luatexko.hpack_filter') @@ -1575,6 +1600,7 @@ add_to_callback('pre_linebreak_filter', function(head) head = compress_fullwidth_punctuations(head) discourage_char_widow(head, nodeslide(head)) head = no_ruby_at_margin(head) + head = reorderTM(head) return head end, 'luatexko.pre_linebreak_filter') @@ -1585,20 +1611,39 @@ end, 'luatexko.pre_linebreak_filter') local function after_linebreak_dotemph (head) for curr in traverse(head) do if curr.id == hlistnode then -- hlist may be nested!!! - after_linebreak_dotemph(curr.head) + curr.head = after_linebreak_dotemph(curr.head) elseif curr.id == glyphnode then local attr = has_attribute(curr,dotemphattr) if attr and attr > 0 then - local d = copy_node(dotemphnode[attr]) - local dot = d.head - d.head = get_kernnode(-curr.width/2-d.width/2) - d.head.next = dot - d.width = 0 - insert_after(head,curr,d) + local cc = get_cjk_class(get_unicode_char(curr)) + if cc and (cc == 0 or cc == 7 or cc == 8) then + local basewd = curr.width or 0 + if cc == 8 then -- check next char for old hangul jung/jongseong + local nn = curr.next + while nn do + if nn.id ~= glyphnode then break end + local uni = get_unicode_char(nn) + local nc = get_cjk_class(uni) + if nc and nc == 9 and uni ~= 0x302E and uni ~= 0x302F then + basewd = basewd + (nn.width or 0) + else + break + end + nn = nn.next + end + end + local d = copy_node(dotemphnode[attr]) + local dot = d.head + d.head = get_kernnode(basewd/2-d.width/2) + d.head.next = dot + d.width = 0 + head = insert_before(head,curr,d) + end unset_attribute(curr,dotemphattr) end end end + return head end ------------------------------- @@ -1649,9 +1694,10 @@ local function draw_underline(head,curr,width,ulinenum,ulstart) and nd.subtype == whatsitspecial and nd.data and stringfind(nd.data,"luako:uline") then - remove_node(head,nd) + head = remove_node(head,nd) end end + return head end local function after_linebreak_underline(head,glueorder,glueset,gluesign,ulinenum) @@ -1659,7 +1705,7 @@ local function after_linebreak_underline(head,glueorder,glueset,gluesign,ulinenu if ulstart and ulstart.id == gluenode then ulstart = ulstart.next end for curr in traverse(head) do if curr.id == hlistnode then - ulinenum = after_linebreak_underline(curr.head,curr.glue_order,curr.glue_set,curr.glue_sign,ulinenum) + curr.head,ulinenum = after_linebreak_underline(curr.head,curr.glue_order,curr.glue_set,curr.glue_sign,ulinenum) elseif curr.id == whatsitnode and curr.subtype == whatsitspecial and curr.data then if stringfind(curr.data,"luako:ulinebegin=") then @@ -1668,33 +1714,33 @@ local function after_linebreak_underline(head,glueorder,glueset,gluesign,ulinenu elseif ulstart and ulinenum and stringfind(curr.data,'luako:ulineend') then local wd = nodedimensions(glueset,gluesign,glueorder,ulstart,curr) - draw_underline(head,curr,wd,ulinenum,ulstart) + head = draw_underline(head,curr,wd,ulinenum,ulstart) ulinebox[ulinenum] = nil ulinenum = nil end end if ulstart and ulinenum and curr == nodetail(head) then local wd = nodedimensions(glueset,gluesign,glueorder,ulstart,curr) - draw_underline(head,curr,wd,ulinenum,ulstart) + head = draw_underline(head,curr,wd,ulinenum,ulstart) end end - return ulinenum + return head, ulinenum end ----------------------------------- -- add to callback : post-linebreak ----------------------------------- add_to_callback('vpack_filter', function(head) - after_linebreak_dotemph(head) + head = after_linebreak_dotemph(head) after_linebreak_ruby(head) - after_linebreak_underline(head) - return true + head = after_linebreak_underline(head) + return head end, 'luatexko.vpack_filter') add_to_callback("post_linebreak_filter", function(head) - after_linebreak_dotemph(head) + head = after_linebreak_dotemph(head) after_linebreak_ruby(head) - after_linebreak_underline(head) - return true + head = after_linebreak_underline(head) + return head end, 'luatexko.post_linebreak_filter') |