OSDN Git Service

Moved Lua codes of test17-priority.tex into ltj-adjust.lua.
[luatex-ja/luatexja.git] / src / ltj-adjust.lua
1 --
2 -- luatexja/otf.lua
3 --
4 luatexbase.provides_module({
5   name = 'luatexja.adjust',
6   date = '2012/09/27',
7   version = '0.1',
8   description = 'Advanced line adjustment for LuaTeX-ja',
9 })
10 module('luatexja.adjust', package.seeall)
11
12 local id_hlist = node.id('hlist')
13 local id_glue  = node.id('glue')
14 local id_glue_spec = node.id('glue_spec')
15 local attr_icflag = luatexbase.attributes['ltj@icflag']
16
17 local PACKED = 2
18 local FROM_JFM = 6
19 local KANJI_SKIP = 9
20 local XKANJI_SKIP = 10
21
22 local priority_table = {
23    XKANJI_SKIP,
24    FROM_JFM + 2,
25    FROM_JFM + 1,
26    FROM_JFM,
27    FROM_JFM - 1,
28    FROM_JFM - 2,
29    KANJI_SKIP
30 }
31
32 local PROCESSED_BEGIN_FLAG = 32
33 local function get_attr_icflag(p)
34    return (node.has_attribute(p, attr_icflag) or 0) % PROCESSED_BEGIN_FLAG
35 end
36
37 -- box 内で伸縮された glue の合計値を計算
38
39 local function get_stretched(q, go, gs)
40    local qs = q.spec
41    if not qs.writable then return 0 end
42    if gs == 1 then -- stretching
43       if qs.stretch_order == go then return qs.stretch end
44    else -- shrinking
45       if qs.shrink_order == go then return qs.shrink end
46    end
47 end
48
49 local function get_total_stretched(p)
50    local go, gf, gs = p.glue_order, p.glue_set, p.glue_sign
51    local res = {
52       [0] = 0,
53       glue_set = gf, name = (gs==1) and 'stretch' or 'shrink'
54    }
55    for i=1,#priority_table do res[priority_table[i]]=0 end
56    if go ~= 0 then return nil end
57    if gs ~= 1 and gs ~= 2 then return res end
58    for q in node.traverse_id(id_glue, p.head) do
59       local a, ic = get_stretched(q, go, gs), get_attr_icflag(q)
60       --print(ic)
61       if   type(res[ic]) == 'number' then res[ic] = res[ic] + a
62       else                                res[0]  = res[0]  + a
63       end
64    end
65    return res
66 end
67
68 local function clear_stretch(p, ic, name)
69    --print('clear ' .. ic)
70    for q in node.traverse_id(id_glue, p.head) do
71       if get_attr_icflag(q) == ic then
72          local qs = q.spec
73          if qs.writable then
74             qs[name..'_order'], qs[name] = 0, 0
75          end
76       end
77    end
78 end
79
80 local function set_stretch(p, after, before, ic, name)
81    if before > 0 then
82       --print (ic, before, after)
83       local ratio = after/before
84       for q in node.traverse_id(id_glue, p.head) do
85          if get_attr_icflag(q) == ic then
86             local qs = q.spec
87             if qs.writable and qs[name..'_order'] == 0 then
88                qs[name] = qs[name]*ratio
89             end
90          end
91       end
92    end
93 end
94
95
96 function adjust_width(head) 
97    if not head then return head end
98    for p in node.traverse_id(id_hlist, head) do
99       local res = get_total_stretched(p)
100       --print(table.serialize(res))
101       if res then
102          -- 調整量の合計
103          local total = 0
104          for i,v in pairs(res) do 
105             if type(i)=='number' then
106                total = total + v
107             end
108          end; total = tex.round(total * res.glue_set)
109          if total <= res[0] then -- 和文処理グルー以外で足りる
110             for _,v in pairs(priority_table) do clear_stretch(p, v, res.name) end
111             local f = node.hpack(p.head, p.width, 'exactly')
112             f.head, p.glue_set, p.glue_sign, p.glue_order 
113                = nil, f.glue_set, f.glue_sign, f.glue_order
114             node.free(f)
115          else
116             total = total - res[0]
117             for i = 1, #priority_table do
118                local v = priority_table[i]
119                if total <= res[v] then
120                   for j = i+1,#priority_table do
121                      clear_stretch(p, priority_table[j], res.name)
122                   end
123                   set_stretch(p, total, res[v], v, res.name)
124                   local f = node.hpack(p.head, p.width, 'exactly')
125                   f.head, p.glue_set, p.glue_sign, p.glue_order 
126                      = nil, f.glue_set, f.glue_sign, f.glue_order
127                   node.free(f)
128                   --print(p.glue_set, p.glue_sign, p.glue_order)
129                   return head
130                end
131                total = total - res[v]
132             end
133          end
134       end
135    end
136    return head
137 end
138