OSDN Git Service

f8b97c144b65841cab8318b884a4a3791a2fa08d
[luatex-ja/luatexja.git] / src / ltj-lineskip.lua
1 --
2 -- ltj-lineskip.lua
3 --
4 luatexja.load_module 'base'; local ltjb = luatexja.base
5 luatexja.load_module 'direction'; local ltjd = luatexja.direction
6 luatexja.lineskip = luatexja.lineskip or {}
7
8 local to_direct = node.direct.todirect
9 local ltjl = luatexja.lineskip
10 local id_glue    = node.id 'glue'
11 local id_penalty = node.id 'penalty'
12 local id_hlist   = node.id 'hlist'
13 local setfield = node.direct.setfield
14 local getfield = node.direct.getfield
15 local getlist = node.direct.getlist
16 local node_new = node.direct.new
17 local node_prev = node.direct.getprev
18 local node_next = node.direct.getnext
19 local getid = node.direct.getid
20 local getsubtype = node.direct.getsubtype
21 local texget = tex.get
22
23 local node_getglue = node.getglue
24 local setglue = node.direct.setglue
25 local function copy_glue (new_glue, old_glue_name, subtype, new_w)
26    setfield(new_glue, 'subtype', subtype)
27    local w,st,sp,sto,spo = texget(old_glue_name, true)
28    setglue(new_glue, new_w or w, st, sp, sto, spo)
29 end
30 ltjl.copy_glue = copy_glue
31
32 function ltjl.p_dummy(before, after)
33    return nil, 0
34 end
35 function ltjl.l_dummy(dist, g, adj, normal, bw, loc)
36    if dist < tex.lineskiplimit then
37       copy_glue(g, 'lineskip', 1, texget('lineskip', false) + adj)
38    else
39       copy_glue(g, 'baselineskip', 2, normal)
40    end
41 end
42
43 local ltj_profiler, ltj_skip = ltjl.p_dummy, ltjl.l_dummy
44 function ltjl.setting(profiler, skip_method)
45    ltj_profiler = ltjl['p_'..tostring(profiler)] or ltjl.p_dummy
46    ltj_skip = ltjl['l_'..tostring(skip_method)] or ltjl.l_dummy
47 end
48
49 do
50 local traverse_id = node.direct.traverse_id
51 local function adjust_glue(nh)
52    local h = to_direct(nh)
53    local bw = texget('baselineskip',false)
54    for x in traverse_id(id_glue, h) do
55      local xs = getsubtype(x)
56      if (xs==1) or (xs==2) then
57         local p, n = node_prev(x), node_next(x)
58         if p then
59         local pid = getid(p)
60            while (id_glue<=pid) and (pid<=id_penalty) and node_prev(p) do 
61              p = node_prev(p); pid = getid(p)
62            end
63            if pid==id_hlist and getid(n)==id_hlist then
64              local normal = bw - getfield(p, 'depth') - getfield(n, 'height')
65              local lmin, adj = ltj_profiler(p, n, false, bw)
66              ltj_skip(lmin or normal, x, adj, normal, bw)
67            end
68         end
69      end
70    end
71    return true
72 end
73 ltjb.add_to_callback('post_linebreak_filter', adjust_glue, 'ltj.lineskip', 10000)
74 end
75
76 do
77 local p_dummy = ltjl.p_dummy
78 local make_dir_whatsit = luatexja.direction.make_dir_whatsit
79 local get_dir_count = luatexja.direction.get_dir_count
80 local node_write = node.direct.write
81
82 local function dir_adjust_append_vlist(b, loc, prev, mirrored)
83    local old_b = to_direct(b)
84    local new_b = loc=='box' and 
85       make_dir_whatsit(old_b, old_b, get_dir_count(), 'append_vlist') or old_b
86    if prev > -65536000 then
87       local bw = texget('baselineskip', false)
88       local normal = bw - prev - getfield(new_b, mirrored and 'depth' or 'height')
89       local lmin, adj = nil, 0
90       local tail = to_direct(tex.nest[tex.nest.ptr].tail)
91       if p_dummy~=ltj_profiler then
92          while tail and (id_glue<=getid(tail)) and (getid(tail)<=id_penalty) do
93             tail = node_prev(tail)
94          end
95       end
96       if tail then
97          if getid(tail)==id_hlist and getid(new_b)==id_hlist then
98             if getfield(tail, 'depth')==prev then 
99                lmin, adj = ltj_profiler(tail, new_b, mirrored, bw)
100             end
101          end
102       end
103       local g = node_new(id_glue)
104       ltj_skip(lmin or normal, g, adj, normal, bw, loc); node_write(g)
105    end
106    node_write(new_b)
107    tex.prevdepth = getfield(new_b, mirrored and 'height' or 'depth')
108    return nil -- do nothing on tex side
109 end
110 ltjb.add_to_callback('append_to_vlist_filter', dir_adjust_append_vlist, 'ltj.lineskip', 10000)
111 end
112