OSDN Git Service

a2c43db172c976d32fdeb1e5338551e88b2ec98d
[luatex-ja/luatexja.git] / src / luatexja-core.lua
1 local node_type = node.type
2 local node_new = node.new
3 local node_prev = node.prev
4 local node_next = node.next
5 local has_attr = node.has_attribute
6 local node_insert_before = node.insert_before
7 local node_insert_after = node.insert_after
8 local node_hpack = node.hpack
9 local round = tex.round
10
11 local id_penalty = node.id('penalty')
12 local id_glyph = node.id('glyph')
13 local id_glue_spec = node.id('glue_spec')
14 local id_glue = node.id('glue')
15 local id_kern = node.id('kern')
16 local id_hlist = node.id('hlist')
17 local id_vlist = node.id('vlist')
18 local id_rule = node.id('rule')
19 local id_math = node.id('math')
20 local id_whatsit = node.id('whatsit')
21
22 local attr_jchar_class = luatexbase.attributes['luatexja@charclass']
23 local attr_curjfnt = luatexbase.attributes['luatexja@curjfnt']
24 local attr_yablshift = luatexbase.attributes['luatexja@yablshift']
25 local attr_ykblshift = luatexbase.attributes['luatexja@ykblshift']
26 local attr_icflag = luatexbase.attributes['luatexja@icflag']
27 -- attr_icflag: 1: kern from \/, 2: 'lineend' kern from JFM
28
29 local lang_ja_token = token.create('luatexja@japanese')
30 local lang_ja = lang_ja_token[2]
31
32 -- 
33 local rgjc_get_range_setting = ltj.int_get_range_setting 
34 local rgjc_char_to_range     = ltj.int_char_to_range
35 local rgjc_is_ucs_in_japanese_char = ltj.int_is_ucs_in_japanese_char
36 local ljfm_find_char_class = ltj.int_find_char_class
37
38 ------------------------------------------------------------------------
39 -- naming:
40 --    ltj.ext_... : called from \directlua{}
41 --    ltj.int_... : called from other Lua codes, but not from \directlua{}
42 --    (other)     : only called from this file
43
44 -- error messages
45 function ltj.error(s,t)
46   tex.error('LuaTeX-ja error: ' .. s ,t) 
47 end
48
49 -- Three aux. functions, bollowed from tex.web
50 local unity=65536
51 local function print_scaled(s)
52    local out=''
53    local delta=10
54    if s<0 then 
55       out=out..'-'; s=-s
56    end
57    out=out..tostring(math.floor(s/unity)) .. '.'
58    s=10*(s%unity)+5
59    repeat
60       if delta>unity then s=s+32768-50000 end
61       out=out .. tostring(math.floor(s/unity)) 
62       s=10*(s%unity)
63       delta=delta*10
64    until s<=delta
65    return out
66 end
67
68 local function print_glue(d,order)
69    local out=print_scaled(d)
70    if order>0 then
71       out=out..'fi'
72       while order>1 do
73          out=out..'l'; order=order-1
74       end
75    else 
76       out=out..'pt'
77    end
78    return out
79 end
80
81 local function print_spec(p)
82    local out=print_scaled(p.width)..'pt'
83    if p.stretch~=0 then
84       out=out..' plus '..print_glue(p.stretch,p.stretch_order)
85    end
86    if p.shrink~=0 then
87       out=out..' minus '..print_glue(p.shrink,p.shrink_order)
88    end
89 return out
90 end
91
92 -- return true if and only if p is a Japanese character node
93 local function is_japanese_glyph_node(p)
94    return p and (p.id==id_glyph) 
95    and (p.font==has_attr(p,attr_curjfnt))
96 end
97
98
99 ------------------------------------------------------------------------
100 -- CODE FOR STACK TABLE FOR CHARACTER PROPERTIES (prefix: cstb)
101 ------------------------------------------------------------------------
102
103 ---- table: charprop_stack_table [stack_level][chr_code].{pre|post|xsp}
104 local charprop_stack_table={}; charprop_stack_table[0]={}
105
106 local function cstb_get_stack_level()
107   local i = tex.getcount('ltj@@stack')
108   if tex.currentgrouplevel > tex.getcount('ltj@@group@level') then
109     i = i+1 -- new stack level
110     tex.setcount('ltj@@group@level', tex.currentgrouplevel)
111     for j,v in pairs(charprop_stack_table) do -- clear the stack above i
112       if j>=i then charprop_stack_table[j]=nil end
113     end
114     charprop_stack_table[i] = table.fastcopy(charprop_stack_table[i-1])
115     tex.setcount('ltj@@stack', i)
116   end
117   return i
118 end
119
120 -- EXT
121 function ltj.ext_set_stack_table(g,m,c,p,lb,ub)
122   local i = cstb_get_stack_level()
123   if p<lb or p>ub then 
124      ltj.error('Invalid code (' .. p .. '), should in the range '
125                .. tostring(lb) .. '..' .. tostring(ub) .. '.',
126             {"I'm going to use 0 instead of that illegal code value."})
127      p=0
128   elseif c<-1 or c>0x10FFFF then
129      ltj.error('Invalid character code (' .. p 
130                .. '), should in the range -1.."10FFFF.',{})
131      return 
132   elseif not charprop_stack_table[i][c] then 
133      charprop_stack_table[i][c] = {} 
134   end
135   charprop_stack_table[i][c][m] = p
136   if g=='global' then
137     for j,v in pairs(charprop_stack_table) do 
138       if not charprop_stack_table[j][c] then charprop_stack_table[j][c] = {} end
139       charprop_stack_table[j][c][m] = p
140     end
141   end
142 end
143
144 local function cstb_get_penalty_table(m,c)
145   local i = charprop_stack_table[tex.getcount('ltj@@stack')][c]
146   if i then i=i[m] end
147   return i or 0
148 end
149
150 local function cstb_get_inhibit_xsp_table(c)
151   local i = charprop_stack_table[tex.getcount('ltj@@stack')][c]
152   if i then i=i.xsp end
153   return i or 3
154 end
155 ltj.int_get_inhibit_xsp_table = cstb_get_inhibit_xsp_table
156
157 ------------------------------------------------------------------------
158 -- CODE FOR GETTING/SETTING PARAMETERS 
159 ------------------------------------------------------------------------
160
161 -- EXT: print parameters that don't need arguments
162 function ltj.ext_get_parameter_unary(k)
163    if k == 'yabaselineshift' then
164       tex.write(print_scaled(tex.getattribute('luatexja@yablshift'))..'pt')
165    elseif k == 'ykbaselineshift' then
166       tex.write(print_scaled(tex.getattribute('luatexja@ykblshift'))..'pt')
167    elseif k == 'kanjiskip' then
168       tex.write(print_spec(tex.getskip('kanjiskip')))
169    elseif k == 'xkanjiskip' then
170       tex.write(print_spec(tex.getskip('xkanjiskip')))
171    elseif k == 'jcharwidowpenalty' then
172       tex.write(tex.getcount('jcharwidowpenalty'))
173    elseif k == 'autospacing' then
174       tex.write(tostring(ltj.auto_spacing))
175    elseif k == 'autoxspacing' then
176       tex.write(tostring(ltj.auto_xspacing))
177    elseif k == 'differentjfm' then
178       if ltj.calc_between_two_jchar_aux==ltj.calc_between_two_jchar_aux_large then
179          tex.write('large')
180       elseif ltj.calc_between_two_jchar_aux==ltj.calc_between_two_jchar_aux_small then
181          tex.write('small')
182       elseif ltj.calc_between_two_jchar_aux==ltj.calc_between_two_jchar_aux_average then
183          tex.write('average')
184       elseif ltj.calc_between_two_jchar_aux==ltj.calc_between_two_jchar_aux_both then
185          tex.write('both')
186       else -- This can't happen.
187          tex.write('???')
188       end
189    end
190 end
191
192 -- EXT: print parameters that need arguments
193 function ltj.ext_get_parameter_binary(k,c)
194    if k == 'jcharrange' then
195       if c<0 or c>216 then c=0 end
196       tex.write(rgjc_get_range_setting(c))
197    else
198       if c<0 or c>0x10FFFF then
199          ltj.error('Invalid character code (' .. c 
200                    .. '), should in the range 0.."10FFFF.',
201                 {"I'm going to use 0 instead of that illegal character code."})
202          c=0
203       end
204       if k == 'prebreakpenalty' then
205          tex.write(cstb_get_penalty_table('pre',c))
206       elseif k == 'postbreakpenalty' then
207          tex.write(cstb_get_penalty_table('post',c))
208       elseif k == 'kcatcode' then
209          tex.write(cstb_get_penalty_table('kcat',c))
210       elseif k == 'chartorange' then 
211          tex.write(rgjc_char_to_range(c))
212       elseif k == 'cjkxspmode' or k == 'asciixspmode' then
213          tex.write(cstb_get_inhibit_xsp_table(c))
214       end
215    end
216 end
217
218 -- EXT: print \global if necessary
219 function ltj.ext_print_global()
220   if ltj.isglobal=='global' then tex.sprint('\\global') end
221 end
222
223
224 ------------------------------------------------------------------------
225 -- MAIN PROCESS STEP 1: replace fonts (prefix: main1)
226 ------------------------------------------------------------------------
227
228 --- the following function is modified from jafontspec.lua (by K. Maeda).
229 --- Instead of "%", we use U+FFFFF for suppressing spaces.
230 local function main1_process_input_buffer(buffer)
231    local c = utf.byte(buffer, utf.len(buffer))
232    local p = node_new(id_glyph)
233    p.char = c
234    if utf.len(buffer) > 0 
235    and rgjc_is_ucs_in_japanese_char(p) then
236         buffer = buffer .. string.char(0xF3,0xBF,0xBF,0xBF) -- U+FFFFF
237    end
238    return buffer
239 end
240
241 local function main1_suppress_hyphenate_ja(head)
242    local p
243    for p in node.traverse(head) do
244       if p.id == id_glyph then
245          if rgjc_is_ucs_in_japanese_char(p) then
246             local v = has_attr(p, attr_curjfnt)
247             if v then 
248                p.font = v 
249                node.set_attribute(p,attr_jchar_class,
250                  ljfm_find_char_class(p.char, ltj.font_metric_table[v].jfm))
251             end
252             v = has_attr(p, attr_ykblshift)
253             if v then 
254                node.set_attribute(p, attr_yablshift, v)
255             else
256                node.unset_attribute(p, attr_yablshift)
257             end
258             p.lang=lang_ja
259          end
260       end
261    end
262    lang.hyphenate(head)
263    return head -- 共通化のため値を返す
264 end
265
266 -- CALLBACKS
267 luatexbase.add_to_callback('process_input_buffer', 
268    function (buffer)
269      return main1_process_input_buffer(buffer)
270    end,'ltj.process_input_buffer')
271 luatexbase.add_to_callback('hpack_filter', 
272   function (head,groupcode,size,packtype)
273      return main1_suppress_hyphenate_ja(head)
274   end,'ltj.hpack_filter_pre',0)
275 luatexbase.add_to_callback('hyphenate', 
276  function (head,tail)
277     return main1_suppress_hyphenate_ja(head)
278  end,'ltj.hyphenate')
279
280
281 ------------------------------------------------------------------------
282 -- MAIN PROCESS STEP 2: insert glue/kerns from JFM (prefix: main2)
283 ------------------------------------------------------------------------
284
285 -- EXT: for \inhibitglue
286 function ltj.ext_create_inhibitglue_node()
287    local g=node_new(id_whatsit, node.subtype('user_defined'))
288    g.user_id=30111; g.type=number; g.value=1; node.write(g)
289 end
290
291
292 local function main2_find_size_metric(px)
293    if is_japanese_glyph_node(px) then
294       return ltj.font_metric_table[px.font].size, ltj.font_metric_table[px.font].jfm
295    else 
296       return nil, nil
297    end
298 end
299
300 local function main2_new_jfm_glue(size,mt,bc,ac)
301 -- mt: metric key, bc, ac: char classes
302    local g=nil
303    local w=bc*0x800+ac
304    local z = ltj.metrics[mt]
305    if z.glue[w] then
306       local h = node_new(id_glue_spec)
307       h.width   = round(size*z.glue[w][0])
308       h.stretch = round(size*z.glue[w][1])
309       h.shrink  = round(size*z.glue[w][2])
310       h.stretch_order=0; h.shrink_order=0
311       g = node_new(id_glue)
312       g.subtype = 0; g.spec = h
313    elseif z.kern[w] then
314       g = node_new(id_kern)
315       g.subtype = 1; g.kern = round(size*z.kern[w])
316    end
317    return g
318 end
319
320 -- return value: g (glue/kern from JFM), w (width of 'lineend' kern)
321 local function main2_calc(qs,qm,q,p,last,ihb_flag)
322    -- q, p: node (possibly null)
323    local ps, pm, g, h
324    local w = 0
325    if (not p) or p==last then
326       -- q is the last node
327       if not qm then
328          return nil, 0
329       elseif not ihb_flag then 
330          g=main2_new_jfm_glue(qs,qm,
331                             has_attr(q,attr_jchar_class),
332                                 ljfm_find_char_class('boxbdd',qm))
333       end
334    elseif qs==0 then
335       -- p is the first node etc.
336       ps, pm = main2_find_size_metric(p)
337       if not pm then
338          return nil, 0
339       elseif not ihb_flag then 
340          g=main2_new_jfm_glue(ps,pm,
341                                 ljfm_find_char_class('boxbdd',pm),
342                                 has_attr(p,attr_jchar_class))
343       end
344    else -- p and q are not nil
345       ps, pm = main2_find_size_metric(p)
346       if ihb_flag or ((not pm) and (not qm)) then 
347          g = nil
348       elseif (qs==ps) and (qm==pm) then 
349          -- Both p and q are Japanese glyph nodes, and same metric and size
350          g = main2_new_jfm_glue(ps,pm,
351                                 has_attr(q,attr_jchar_class),
352                                 has_attr(p,attr_jchar_class))
353       elseif not qm then
354          -- q is not a Japanese glyph node
355          g = main2_new_jfm_glue(ps,pm,
356                                 ljfm_find_char_class('jcharbdd',pm),
357                                 has_attr(p,attr_jchar_class))
358       elseif not pm then
359          -- p is not a Japanese glyph node
360          g = main2_new_jfm_glue(qs,qm,
361                                 has_attr(q,attr_jchar_class),
362                                 ljfm_find_char_class('jcharbdd',qm))
363       else
364          g = main2_new_jfm_glue(qs,qm,
365                                 has_attr(q,attr_jchar_class),
366                                 ljfm_find_char_class('diffmet',qm))
367          h = main2_new_jfm_glue(ps,pm,
368                                 ljfm_find_char_class('diffmet',pm),
369                                 has_attr(p,attr_jchar_class))
370          g = ltj.calc_between_two_jchar_aux(g,h)
371       end
372    end
373    if g then node.set_attribute(g, attr_icflag, 3) end
374    if qm then
375       local x = ljfm_find_char_class('lineend', qm)
376       if x~=0  then
377          x = has_attr(q,attr_jchar_class)*0x800 + x
378          if ltj.metrics[qm].kern[x] then 
379             w = round(qs*ltj.metrics[qm].kern[x])
380          end
381       end
382    end
383
384    return g, w
385 end
386
387 local function main2_between_two_char(head,q,p,p_bp,ihb_flag,last)
388    local qs = 0; local g, w
389    local qm = nil
390    if q then
391       qs, qm = main2_find_size_metric(q)
392    end
393    g, w = main2_calc(qs, qm, q, p, last, ihb_flag)
394    if w~=0 and (not p_bp) then
395       p_bp = node_new(id_penalty); p_bp.penalty = 0
396       head = node_insert_before(head, p, p_bp)
397    end
398    if g then
399       if g.id==id_kern then 
400          g.kern = round(g.kern - w)
401       else
402          g.spec.width = round(g.spec.width - w)
403       end
404       head = node_insert_before(head, p, g)
405    elseif w~=0 then
406       g = node_new(id_kern); g.kern = -w; g.subtype = 1
407       node.set_attribute(g,attr_icflag,2)
408       head = node_insert_before(head, p, g)
409       -- this g might be replaced by \[x]kanjiskip in step 3.
410    end
411    if w~=0 then
412       g = node_new(id_kern); g.kern = w; g.subtype = 0
413       head = node_insert_before(head, p_bp, g)
414    end
415 return head, p_bp
416 end
417
418 -- In the beginning of a hlist created by line breaking, there are the followings:
419 --   - a hbox by \parindent
420 --   - a whatsit node which contains local paragraph materials.
421 -- When we insert jfm glues, we ignore these nodes.
422 local function main2_is_parindent_box(p)
423    if p.id==id_hlist then 
424       return (p.subtype==3)
425       -- hlist (subtype=3) is a box by \parindent
426    elseif p.id==id_whatsit then 
427       return (p.subtype==node.subtype('local_par'))
428    end
429 end
430
431 -- next three functions deal with inserting penalty by kinsoku.
432 local function main2_add_penalty_before(head,p,p_bp,pen)
433    if p_bp then
434       p_bp.penalty = p_bp.penalty + pen
435    else -- we must create a new penalty node
436       local g = node_new(id_penalty); g.penalty = pen
437       local q = node_prev(p)
438       if q then
439          if has_attr(q, attr_icflag) ~= 3 then
440             q = p
441          end
442          return node_insert_before(head, q, g)
443       end
444    end
445    return head
446 end
447
448 local function main2_add_kinsoku_penalty(head,p,p_bp)
449    local c = p.char
450    local e = cstb_get_penalty_table('pre',c)
451    if e~=0 then
452       head = main2_add_penalty_before(head, p, p_bp, e)
453    end
454    e = cstb_get_penalty_table('post',c)
455    if e~=0 then
456       local q = node_next(p)
457       if q and q.id==id_penalty then
458          q.penalty = q.penalty + e
459          return false
460       else 
461          q = node_new(id_penalty); q.penalty = e
462          node_insert_after(head,p,q)
463          return true
464       end
465    end
466 end
467
468 local function main2_add_widow_penalty(head,widow_node,widow_bp)
469    if not widow_node then 
470       return head
471    else
472       return main2_add_penalty_before(head, widow_node,
473                  widow_bp, tex.getcount('jcharwidowpenalty'))
474    end
475 end
476
477 local depth=""
478
479 -- Insert jfm glue: main routine
480 -- mode = true iff insert_jfm_glue is called from pre_linebreak_filter
481 local function main2_insert_jfm_glue(head, mode)
482    local p = head
483    local p_bp = nil -- p と直前の文字の間の penalty node
484    local q = nil  -- the previous node of p
485    local widow_node = nil -- 最後の「句読点扱いでない」和文文字
486    local widow_bp = nil -- \jcharwidowpenalty 挿入位置
487    local last -- the sentinel 
488    local ihb_flag = false -- is \inhibitglue specified?
489    local g
490    -- initialization
491    if not p then return head 
492    elseif mode then
493       while p and main2_is_parindent_box(p) do p=node_next(p) end
494       last=node.tail(head)
495       if last and last.id==id_glue and last.subtype==15 then
496          last=node.prev(last)
497          while (last and last.id==id_penalty) do last=node.prev(last) end
498       end
499       if last then last=node_next(last) end
500    else -- 番人を挿入
501       last=node.tail(head); g = node_new('kern')
502       node_insert_after(head,last,g); last = g
503    end
504    -- main loop
505    while q~=last do
506       if p.id==id_whatsit and p.subtype==node.subtype('user_defined')
507          and p.user_id==30111 then
508          g = p; p = node_next(p)
509          ihb_flag = true; head, p = node.remove(head, g)
510       else
511          head, p_bp = main2_between_two_char(head, q, p, p_bp, ihb_flag, last)
512          q=p; ihb_flag=false
513          if is_japanese_glyph_node(p) then
514             if cstb_get_penalty_table('kcat',p.char)%2~=1 then
515                widow_node = p; widow_bp = p_bp
516             end
517             if main2_add_kinsoku_penalty(head, p, p_bp) then
518                p_bp = node_next(p); p = p_bp
519             else p_bp = nil
520             end
521          else p_bp = nil
522          end
523          p=node_next(p)
524       end
525    end
526    if mode then
527       -- Insert \jcharwidowpenalty
528       head = main2_add_widow_penalty(head, widow_node, widow_bp)
529       -- cleanup
530       p = node_prev(last)
531       if p and p.id==id_kern and has_attr(p,attr_icflag)==2 then
532          head = node.remove(head, p)
533       end
534    else
535       head = node.remove(head, last)
536    end
537    return head
538 end
539
540
541 ------------------------------------------------------------------------
542 -- MAIN PROCESS STEP 4: width of japanese chars (prefix: main4)
543 ------------------------------------------------------------------------
544
545 -- TeX's \hss
546 local function main4_get_hss()
547    local hss = node_new(id_glue)
548    local fil_spec = node_new(id_glue_spec)
549    fil_spec.width = 0
550    fil_spec.stretch = 65536
551    fil_spec.stretch_order = 2
552    fil_spec.shrink = 65536
553    fil_spec.shrink_order = 2
554    hss.spec = fil_spec
555    return hss
556 end
557
558 local function main4_set_ja_width(head)
559    local p = head
560    local met_tb, t, s, g, th, q, a
561    local m = false -- is in math mode?
562    while p do
563       local v=has_attr(p,attr_yablshift) or 0
564       if p.id==id_glyph then
565          p.yoffset = p.yoffset-v
566          if is_japanese_glyph_node(p) then
567             met_tb = ltj.font_metric_table[p.font]
568             t = ltj.metrics[met_tb.jfm]
569             s = t.char_type[has_attr(p,attr_jchar_class)]
570             if not(s.left==0.0 and s.down==0.0 
571                    and round(s.width*met_tb.size)==p.width) then
572                -- must be encapsuled by a \hbox
573                head, q = node.remove(head,p)
574                p.next=nil
575                p.yoffset=round(p.yoffset-met_tb.size*s.down)
576                p.xoffset=round(p.xoffset-met_tb.size*s.left)
577                node_insert_after(p, p, main4_get_hss())
578                g = node_hpack(p, round(met_tb.size*s.width), 'exactly')
579                g.height = round(met_tb.size*s.height)
580                g.depth = round(met_tb.size*s.depth)
581                head, p = node_insert_before(head, q, g)
582                p = q
583             else p=node_next(p)
584             end
585          else p=node_next(p)
586          end
587       elseif p.id==id_math then
588          m=(p.subtype==0); p=node_next(p)
589       else
590          if m then
591             if p.id==id_hlist or p.id==id_vlist then
592                p.shift=p.shift+v
593             elseif p.id==id_rule then
594                p.height=p.height-v; p.depth=p.depth+v 
595             end
596          end
597          p=node_next(p)
598       end
599    end
600 return head
601 end
602
603 -- main process
604 -- mode = true iff main_process is called from pre_linebreak_filter
605 local function main_process(head, mode)
606    local p = head
607    p = main2_insert_jfm_glue(p,mode)
608    p = ltj.int_insert_kanji_skip(p)
609    p = main4_set_ja_width(p)
610    return p
611 end
612
613
614 -- debug
615 local debug_depth
616 function ltj.ext_show_node_list(head,depth,print_fn)
617    debug_depth = depth
618    if head then
619       debug_show_node_list_X(head, print_fn)
620    else
621       print_fn(debug_depth .. ' (null list)')
622    end
623 end
624 function debug_show_node_list_X(p,print_fn)
625    debug_depth=debug_depth.. '.'
626    local k = debug_depth
627    while p do
628       local pt=node_type(p.id)
629       if pt == 'glyph' then
630          print_fn(debug_depth.. ' glyph  ', p.subtype, utf.char(p.char), p.font)
631       elseif pt=='hlist' then
632          print_fn(debug_depth.. ' hlist  ', p.subtype, '(' .. print_scaled(p.height)
633             .. '+' .. print_scaled(p.depth)
634          .. ')x' .. print_scaled(p.width) )
635          debug_show_node_list_X(p.head,print_fn)
636          debug_depth=k
637       elseif pt == 'whatsit' then
638          print_fn(debug_depth.. ' whatsit', p.subtype)
639       elseif pt == 'glue' then
640          print_fn(debug_depth.. ' glue   ', p.subtype, print_spec(p.spec))
641       elseif pt == 'kern' then
642          print_fn(debug_depth.. ' kern   ', p.subtype, print_scaled(p.kern) .. 'pt')
643       elseif pt == 'penalty' then
644          print_fn(debug_depth.. ' penalty', p.penalty)
645       else
646          print_fn(debug_depth.. ' ' .. node.type(p.id), p.subtype)
647       end
648       p=node_next(p)
649    end
650 end
651
652
653
654 -- callbacks
655 luatexbase.add_to_callback('pre_linebreak_filter', 
656    function (head,groupcode)
657      return main_process(head, true)
658    end,'ltj.pre_linebreak_filter',2)
659 luatexbase.add_to_callback('hpack_filter', 
660   function (head,groupcode,size,packtype)
661      return main_process(head, false)
662   end,'ltj.hpack_filter',2)