-local function calc_ja_ja_aux(gb,ga, db, da)
- local rbb, rab = (1-db)/2, (1-da)/2 -- 「前の文字」由来のグルーの割合
- local rba, raa = (1+db)/2, (1+da)/2 -- 「前の文字」由来のグルーの割合
- if diffmet_rule ~= math.two_pleft and diffmet_rule ~= math.two_pright
- and diffmet_rule ~= math.two_paverage then
- rbb, rab, rba, raa = 1,0,0,1
- end
- if not gb then
- if ga then gb = node_new(id_kern); gb.kern = 0 else return nil end
- elseif not ga then
- ga = node_new(id_kern); ga.kern = 0
- end
-
- local k = node.type(gb.id) .. node.type(ga.id)
- if k == 'glueglue' then
- -- 両方とも glue.
- gb.spec.width = round(diffmet_rule(
- rbb*gb.spec.width + rba*ga.spec.width,
- rab*gb.spec.width + raa*ga.spec.width ))
- gb.spec.stretch = round(diffmet_rule(
- rbb*gb.spec.stretch + rba*ga.spec.stretch,
- rab*gb.spec.stretch + raa*ga.spec.stretch ))
- gb.spec.shrink = -round(diffmet_rule(
- -rbb*gb.spec.shrink - rba*ga.spec.shrink,
- -rab*gb.spec.shrink - raa*ga.spec.shrink ))
- node.free(ga)
- return gb
- elseif k == 'kernkern' then
- -- 両方とも kern.
- gb.kern = round(diffmet_rule(
- rbb*gb.kern + rba*ga.kern,
- rab*gb.kern + raa*ga.kern ))
- node.free(ga)
- return gb
- elseif k == 'kernglue' then
- -- gb: kern, ga: glue
- ga.spec.width = round(diffmet_rule(
- rbb*gb.kern + rba*ga.spec.width,
- rab*gb.kern + raa*ga.spec.width ))
- ga.spec.stretch = round(diffmet_rule(
- rba*ga.spec.stretch, raa*ga.spec.stretch ))
- ga.spec.shrink = -round(diffmet_rule(
- -rba*ga.spec.shrink,-raa*ga.spec.shrink ))
- node.free(gb)
- return ga
- else
- -- gb: glue, ga: kern
- gb.spec.width = round(diffmet_rule(
- rba*ga.kern + rbb*gb.spec.width,
- raa*ga.kern + rab*gb.spec.width ))
- gb.spec.stretch = round(diffmet_rule(
- rbb*gb.spec.stretch, rab*gb.spec.stretch ))
- gb.spec.shrink = -round(diffmet_rule(
- -rbb*gb.spec.shrink,-rab*gb.spec.shrink ))
- node.free(ga)
- return gb
+local calc_ja_ja_aux
+do
+ local bg_ag = 2*id_glue - id_glue
+ local bg_ak = 2*id_glue - id_kern
+ local bk_ag = 2*id_kern - id_glue
+ local bk_ak = 2*id_kern - id_kern
+
+ calc_ja_ja_aux = function (gb,ga, db, da)
+ local rbb, rab = (1-db)/2, (1-da)/2 -- 「前の文字」由来のグルーの割合
+ local rba, raa = (1+db)/2, (1+da)/2 -- 「前の文字」由来のグルーの割合
+ if diffmet_rule ~= math.two_pleft and diffmet_rule ~= math.two_pright
+ and diffmet_rule ~= math.two_paverage then
+ rbb, rab, rba, raa = 1,0,0,1
+ end
+ if not gb then
+ if ga then
+ gb = node_new(id_kern); setfield(gb, 'kern', 0)
+ else return nil end
+ elseif not ga then
+ ga = node_new(id_kern); setfield(ga, 'kern', 0)
+ end
+
+ local k = 2*getid(gb) - getid(ga)
+ if k == bg_ag then
+ local bs, as = getfield(gb, 'spec'), getfield(ga, 'spec')
+ -- 両方とも glue.
+ local bd, ad = getfield(bs, 'width'), getfield(as, 'width')
+ setfield(bs, 'width', round(diffmet_rule(rbb*bd + rba*ad, rab*bd + raa*ad)))
+ bd, ad = getfield(bs, 'stretch'), getfield(as, 'stretch')
+ setfield(bs, 'stretch', round(diffmet_rule(rbb*bd + rba*ad, rab*bd + raa*ad)))
+ bd, ad = getfield(bs, 'shrink'), getfield(as, 'shrink')
+ setfield(bs, 'shrink', -round(diffmet_rule(-rbb*bd - rba*ad, -rab*bd - raa*ad)))
+ node_free(ga)
+ return gb
+ elseif k == bk_ak then
+ -- 両方とも kern.
+ local bd, ad = getfield(gb, 'kern'), getfield(ga, 'kern')
+ setfield(gb, 'kern', round(diffmet_rule(rbb*bd + rba*ad, rab*bd + raa*ad)))
+ node_free(ga)
+ return gb
+ elseif k == bk_ag then
+ local as = getfield(ga, 'spec')
+ -- gb: kern, ga: glue
+ local bd, ad = getfield(gb, 'kern'), getfield(as, 'width')
+ setfield(as, 'width', round(diffmet_rule(rbb*bd + rba*ad, rab*bd + raa*ad)))
+ ad = getfield(as, 'stretch')
+ setfield(bs, 'stretch', round(diffmet_rule(rba*ad, raa*ad)))
+ ad = getfield(as, 'shrink')
+ setfield(bs, 'shrink', -round(diffmet_rule(-rba*ad, -raa*ad)))
+ node_free(gb)
+ return ga
+ else
+ local bs = getfield(gb, 'spec')
+ -- gb: glue, ga: kern
+ local bd, ad = getfield(bs, 'width'), getfield(ga, 'kern')
+ setfield(bs, 'width', round(diffmet_rule(rbb*bd + rba*ad, rab*bd + raa*ad)))
+ bd = getfield(bs, 'stretch')
+ setfield(bs, 'stretch', round(diffmet_rule(rbb*bd, rab*bd)))
+ bd = getfield(bs, 'shrink')
+ setfield(bs, 'shrink', -round(diffmet_rule(-rbb*bd, -rab*bd)))
+ node_free(ga)
+ return gb
+ end