diff options
Diffstat (limited to 'src/fontloader/misc/fontloader-fonts-inj.lua')
-rw-r--r-- | src/fontloader/misc/fontloader-fonts-inj.lua | 385 |
1 files changed, 208 insertions, 177 deletions
diff --git a/src/fontloader/misc/fontloader-fonts-inj.lua b/src/fontloader/misc/fontloader-fonts-inj.lua index 3b93382..cb9ed89 100644 --- a/src/fontloader/misc/fontloader-fonts-inj.lua +++ b/src/fontloader/misc/fontloader-fonts-inj.lua @@ -14,13 +14,12 @@ if not nodes.properties then return end local next, rawget = next, rawget local utfchar = utf.char +local fastcopy = table.fastcopy local trace_injections = false trackers.register("fonts.injections", function(v) trace_injections = v end) local report_injections = logs.reporter("fonts","injections") -report_injections("using experimental injector") - local attributes, nodes, node = attributes, nodes, node fonts = fonts @@ -81,19 +80,42 @@ function injections.resetcounts() keepregisteredcounts = false end +-- We need to make sure that a possible metatable will not kick in +-- unexpectedly. + function injections.reset(n) - local p = rawget(properties,start) - if p and p.injections then - -- todo: decrement counters? tricky as we then need to change the nof* to not increment - -- when we change a property - p.injections = nil -- should we keep the liga index? + local p = rawget(properties,n) + if p and rawget(p,"injections") then + p.injections = nil + end +end + +function injections.copy(target,source) + local sp = rawget(properties,source) + if sp then + local tp = rawget(properties,target) + local si = rawget(sp,"injections") + if si then + si = fastcopy(si) + if tp then + tp.injections = si + else + propertydata[target] = { + injections = si, + } + end + else + if tp then + tp.injections = nil + end + end end end function injections.setligaindex(n,index) local p = rawget(properties,n) if p then - local i = p.injections + local i = rawget(p,"injections") if i then i.ligaindex = index else @@ -113,9 +135,9 @@ end function injections.getligaindex(n,default) local p = rawget(properties,n) if p then - p = p.injections - if p then - return p.ligaindex or default + local i = rawget(p,"injections") + if i then + return i.ligaindex or default end end return default @@ -134,7 +156,7 @@ function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmne -- local p = rawget(properties,start) if p then - local i = p.injections + local i = rawget(p,"injections") if i then i.cursiveanchor = true else @@ -151,7 +173,7 @@ function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmne end local p = rawget(properties,nxt) if p then - local i = p.injections + local i = rawget(p,"injections") if i then i.cursivex = dx i.cursivey = dy @@ -185,14 +207,16 @@ function injections.setpair(current,factor,rlmode,r2lflag,spec,injection) -- r2l end local p = rawget(properties,current) if p then - local i = p.injections + local i = rawget(p,"injections") if i then - if leftkern ~= 0 or rightkern ~= 0 then - i.leftkern = i.leftkern or 0 + leftkern - i.rightkern = i.rightkern or 0 + rightkern + if leftkern ~= 0 then + i.leftkern = (i.leftkern or 0) + leftkern + end + if rightkern ~= 0 then + i.rightkern = (i.rightkern or 0) + rightkern end if yoffset ~= 0 then - i.yoffset = i.yoffset or 0 + yoffset + i.yoffset = (i.yoffset or 0) + yoffset end elseif leftkern ~= 0 or rightkern ~= 0 then p.injections = { @@ -240,9 +264,9 @@ function injections.setkern(current,factor,rlmode,x,injection) injection = "injections" end if p then - local i = p[injection] + local i = rawget(p,injection) if i then - i.leftkern = dx + i.leftkern or 0 + i.leftkern = dx + (i.leftkern or 0) else p[injection] = { leftkern = dx, @@ -270,7 +294,7 @@ function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase) -- ba=basean end local p = rawget(properties,start) if p then - local i = p.injections + local i = rawget(p,"injections") if i then i.markx = dx i.marky = dy @@ -313,18 +337,18 @@ local function show(n,what,nested,symbol) if n then local p = rawget(properties,n) if p then - local p = p[what] - if p then - local leftkern = p.leftkern or 0 - local rightkern = p.rightkern or 0 - local yoffset = p.yoffset or 0 - local markx = p.markx or 0 - local marky = p.marky or 0 - local markdir = p.markdir or 0 - local markbase = p.markbase or 0 -- will be markbasenode - local cursivex = p.cursivex or 0 - local cursivey = p.cursivey or 0 - local ligaindex = p.ligaindex or 0 + local i = rawget(p,what) + if i then + local leftkern = i.leftkern or 0 + local rightkern = i.rightkern or 0 + local yoffset = i.yoffset or 0 + local markx = i.markx or 0 + local marky = i.marky or 0 + local markdir = i.markdir or 0 + local markbase = i.markbase or 0 -- will be markbasenode + local cursivex = i.cursivex or 0 + local cursivey = i.cursivey or 0 + local ligaindex = i.ligaindex or 0 local margin = nested and 4 or 2 -- if rightkern ~= 0 or yoffset ~= 0 then @@ -355,9 +379,9 @@ local function showsub(n,what,where) report_injections("end subrun") end -local function trace(head) - report_injections("begin run: %s kerns, %s pairs, %s marks and %s cursives registered", - nofregisteredkerns,nofregisteredpairs,nofregisteredmarks,nofregisteredcursives) +local function trace(head,where) + report_injections("begin run %s: %s kerns, %s pairs, %s marks and %s cursives registered", + where or "",nofregisteredkerns,nofregisteredpairs,nofregisteredmarks,nofregisteredcursives) local n = head while n do local id = getid(n) @@ -414,10 +438,6 @@ local function collect_glyphs_1(head) local nf, tm = nil, nil for n in traverse_id(glyph_code,head) do -- only needed for relevant fonts if getsubtype(n) < 256 then - local pn = rawget(properties,n) - if pn then - pn = pn.injections - end local f = getfont(n) if f ~= nf then nf = f @@ -431,10 +451,14 @@ local function collect_glyphs_1(head) glyphs[nofglyphs] = n end -- yoffsets can influence curs steps - if pn then - local yoffset = pn.yoffset - if yoffset and yoffset ~= 0 then - setfield(n,"yoffset",yoffset) + local p = rawget(properties,n) + if p then + local i = rawget(p,"injections") + if i then + local yoffset = i.yoffset + if yoffset and yoffset ~= 0 then + setfield(n,"yoffset",yoffset) + end end end end @@ -470,18 +494,20 @@ local function inject_marks(marks,nofmarks) local n = marks[i] local pn = rawget(properties,n) if pn then - pn = pn.injections - end - if pn then - -- local markbase = pn.markbase - -- if markbase then - -- local p = markanchors[markbase] + pn = rawget(pn,"injections") + if pn then local p = pn.markbasenode if p then local px = getfield(p,"xoffset") local ox = 0 + local rightkern = nil local pp = rawget(properties,p) - local rightkern = pp and pp.rightkern + if pp then + pp = rawget(pp,"injections") + if pp then + rightkern = pp.rightkern + end + end if rightkern then -- x and w ~= 0 if pn.markdir < 0 then -- kern(w-x) glyph(p) kern(x) mark(n) @@ -490,8 +516,13 @@ local function inject_marks(marks,nofmarks) else -- kern(x) glyph(p) kern(w-x) mark(n) -- ox = px - getfield(p,"width") + pn.markx - pp.leftkern - ox = px - pn.markx - pp.leftkern - -- report_injections("l2r case 1: %p",ox) + local leftkern = pp.leftkern + if leftkern then + ox = px - pn.markx + else + ox = px - pn.markx - leftkern + end +-- report_injections("l2r case 1: %p",ox) end else -- we need to deal with fonts that have marks with width @@ -525,10 +556,10 @@ local function inject_marks(marks,nofmarks) end setfield(n,"yoffset",oy) else - -- normally this can't happen (only when in trace mode which is a special case anyway) + -- normally this can't happen (only when in trace mode which is a special case anyway) -- report_injections("missing mark anchor %i",pn.markbase or 0) end - -- end + end end end end @@ -540,14 +571,14 @@ local function inject_cursives(glyphs,nofglyphs) local n = glyphs[i] local pn = rawget(properties,n) if pn then - pn = pn.injections + pn = rawget(pn,"injections") end if pn then local cursivex = pn.cursivex if cursivex then if cursiveanchor then if cursivex ~= 0 then - pn.leftkern = pn.leftkern or 0 + cursivex + pn.leftkern = (pn.leftkern or 0) + cursivex end if lastanchor then if maxc == 0 then @@ -622,16 +653,16 @@ local function inject_kerns(head,glyphs,nofglyphs) local n = glyphs[i] local pn = rawget(properties,n) if pn then - pn = pn.injections - end - if pn then - local leftkern = pn.leftkern - if leftkern ~= 0 then - insert_node_before(head,n,newkern(leftkern)) -- type 0/2 - end - local rightkern = pn.rightkern - if rightkern and rightkern ~= 0 then - insert_node_after(head,n,newkern(rightkern)) -- type 0/2 + local i = rawget(pn,"injections") + if i then + local leftkern = i.leftkern + if leftkern and leftkern ~= 0 then + insert_node_before(head,n,newkern(leftkern)) -- type 0/2 + end + local rightkern = i.rightkern + if rightkern and rightkern ~= 0 then + insert_node_after(head,n,newkern(rightkern)) -- type 0/2 + end end end end @@ -640,7 +671,7 @@ end local function inject_everything(head,where) head = tonut(head) if trace_injections then - trace(head) + trace(head,"everything") end local glyphs, nofglyphs, marks, nofmarks if nofregisteredpairs > 0 then @@ -652,7 +683,7 @@ local function inject_everything(head,where) if nofregisteredcursives > 0 then inject_cursives(glyphs,nofglyphs) end - if nofregisteredmarks > 0 then + if nofregisteredmarks > 0 then -- and nofmarks > 0 inject_marks(marks,nofmarks) end inject_kerns(head,glyphs,nofglyphs) @@ -671,7 +702,7 @@ end local function inject_kerns_only(head,where) head = tonut(head) if trace_injections then - trace(head) + trace(head,"kerns") end local n = head local p = nil @@ -684,10 +715,10 @@ local function inject_kerns_only(head,where) if p then local d = getfield(p,"post") if d then - local pn = pn.postinjections - if pn then - local leftkern = pn.leftkern - if leftkern ~= 0 then + local i = rawget(pn,"postinjections") + if i then + local leftkern = i.leftkern + if leftkern and leftkern ~= 0 then local t = find_tail(d) insert_node_after(d,t,newkern(leftkern)) end @@ -695,28 +726,28 @@ local function inject_kerns_only(head,where) end local d = getfield(p,"replace") if d then - local pn = pn.replaceinjections - if pn then - local leftkern = pn.leftkern - if leftkern ~= 0 then + local i = rawget(pn,"replaceinjections") + if i then + local leftkern = i.leftkern + if leftkern and leftkern ~= 0 then local t = find_tail(d) insert_node_after(d,t,newkern(leftkern)) end end else - local pn = pn.injections - if pn then - local leftkern = pn.leftkern - if leftkern ~= 0 then + local i = rawget(pn,"injections") + if i then + local leftkern = i.leftkern + if leftkern and leftkern ~= 0 then setfield(p,"replace",newkern(leftkern)) end end end else - local pn = pn.injections - if pn then - local leftkern = pn.leftkern - if leftkern ~= 0 then + local i = rawget(pn,"injections") + if i then + local leftkern = i.leftkern + if leftkern and leftkern ~= 0 then head = insert_node_before(head,n,newkern(leftkern)) end end @@ -734,12 +765,12 @@ local function inject_kerns_only(head,where) if getsubtype(n) < 256 then local pn = rawget(properties,n) if pn then - pn = pn.preinjections - end - if pn then - local leftkern = pn.leftkern - if leftkern ~= 0 then - h = insert_node_before(h,n,newkern(leftkern)) + local i = rawget(pn,"preinjections") + if i then + local leftkern = i.leftkern + if leftkern and leftkern ~= 0 then + h = insert_node_before(h,n,newkern(leftkern)) + end end end else @@ -757,12 +788,12 @@ local function inject_kerns_only(head,where) if getsubtype(n) < 256 then local pn = rawget(properties,n) if pn then - pn = pn.postinjections - end - if pn then - local leftkern = pn.leftkern - if leftkern ~= 0 then - h = insert_node_before(h,n,newkern(leftkern)) + local i = rawget(pn,"postinjections") + if i then + local leftkern = i.leftkern + if leftkern and leftkern ~= 0 then + h = insert_node_before(h,n,newkern(leftkern)) + end end end else @@ -780,12 +811,12 @@ local function inject_kerns_only(head,where) if getsubtype(n) < 256 then local pn = rawget(properties,n) -- why can it be empty { } if pn then - pn = pn.replaceinjections - end - if pn then - local leftkern = pn.leftkern - if leftkern ~= 0 then - h = insert_node_before(h,n,newkern(leftkern)) + local i = rawget(pn,"replaceinjections") + if i then + local leftkern = i.leftkern + if leftkern and leftkern ~= 0 then + h = insert_node_before(h,n,newkern(leftkern)) + end end end else @@ -814,7 +845,7 @@ end local function inject_pairs_only(head,where) head = tonut(head) if trace_injections then - trace(head) + trace(head,"pairs") end -- local n = head @@ -828,14 +859,14 @@ local function inject_pairs_only(head,where) if p then local d = getfield(p,"post") if d then - local pn = pn.postinjections - if pn then - local leftkern = pn.leftkern - if leftkern ~= 0 then + local i = rawget(pn,"postinjections") + if i then + local leftkern = i.leftkern + if leftkern and leftkern ~= 0 then local t = find_tail(d) insert_node_after(d,t,newkern(leftkern)) end - -- local rightkern = pn.rightkern + -- local rightkern = i.rightkern -- if rightkern and rightkern ~= 0 then -- insert_node_after(head,n,newkern(rightkern)) -- n = getnext(n) -- to be checked @@ -844,27 +875,27 @@ local function inject_pairs_only(head,where) end local d = getfield(p,"replace") if d then - local pn = pn.replaceinjections - if pn then - local leftkern = pn.leftkern - if leftkern ~= 0 then + local i = rawget(pn,"replaceinjections") + if i then + local leftkern = i.leftkern + if leftkern and leftkern ~= 0 then local t = find_tail(d) insert_node_after(d,t,newkern(leftkern)) end - -- local rightkern = pn.rightkern + -- local rightkern = i.rightkern -- if rightkern and rightkern ~= 0 then -- insert_node_after(head,n,newkern(rightkern)) -- n = getnext(n) -- to be checked -- end end else - local pn = pn.injections - if pn then - local leftkern = pn.leftkern - if leftkern ~= 0 then + local i = rawget(pn,"injections") + if i then + local leftkern = i.leftkern + if leftkern and leftkern ~= 0 then setfield(p,"replace",newkern(leftkern)) end - -- local rightkern = pn.rightkern + -- local rightkern = i.rightkern -- if rightkern and rightkern ~= 0 then -- insert_node_after(head,n,newkern(rightkern)) -- n = getnext(n) -- to be checked @@ -873,17 +904,17 @@ local function inject_pairs_only(head,where) end else -- this is the most common case - local pn = pn.injections - if pn then - local yoffset = pn.yoffset + local i = rawget(pn,"injections") + if i then + local yoffset = i.yoffset if yoffset and yoffset ~= 0 then setfield(n,"yoffset",yoffset) end - local leftkern = pn.leftkern - if leftkern ~= 0 then + local leftkern = i.leftkern + if leftkern and leftkern ~= 0 then insert_node_before(head,n,newkern(leftkern)) end - local rightkern = pn.rightkern + local rightkern = i.rightkern if rightkern and rightkern ~= 0 then insert_node_after(head,n,newkern(rightkern)) n = getnext(n) -- to be checked @@ -901,23 +932,23 @@ local function inject_pairs_only(head,where) local h = d for n in traverse_id(glyph_code,d) do if getsubtype(n) < 256 then - local pn = rawget(properties,n) - if pn then - pn = pn.preinjections - end - if pn then - local yoffset = pn.yoffset - if yoffset and yoffset ~= 0 then - setfield(n,"yoffset",yoffset) - end - local leftkern = pn.leftkern - if leftkern ~= 0 then - h = insert_node_before(h,n,newkern(leftkern)) - end - local rightkern = pn.rightkern - if rightkern and rightkern ~= 0 then - insert_node_after(head,n,newkern(rightkern)) - n = getnext(n) -- to be checked + local p = rawget(properties,n) + if p then + local i = rawget(p,"preinjections") + if i then + local yoffset = i.yoffset + if yoffset and yoffset ~= 0 then + setfield(n,"yoffset",yoffset) + end + local leftkern = i.leftkern + if leftkern ~= 0 then + h = insert_node_before(h,n,newkern(leftkern)) + end + local rightkern = i.rightkern + if rightkern and rightkern ~= 0 then + insert_node_after(head,n,newkern(rightkern)) + n = getnext(n) -- to be checked + end end end else @@ -933,23 +964,23 @@ local function inject_pairs_only(head,where) local h = d for n in traverse_id(glyph_code,d) do if getsubtype(n) < 256 then - local pn = rawget(properties,n) - if pn then - pn = pn.postinjections - end - if pn then - local yoffset = pn.yoffset - if yoffset and yoffset ~= 0 then - setfield(n,"yoffset",yoffset) - end - local leftkern = pn.leftkern - if leftkern ~= 0 then - h = insert_node_before(h,n,newkern(leftkern)) - end - local rightkern = pn.rightkern - if rightkern and rightkern ~= 0 then - insert_node_after(head,n,newkern(rightkern)) - n = getnext(n) -- to be checked + local p = rawget(properties,n) + if p then + local i = rawget(p,"postinjections") + if i then + local yoffset = i.yoffset + if yoffset and yoffset ~= 0 then + setfield(n,"yoffset",yoffset) + end + local leftkern = i.leftkern + if leftkern and leftkern ~= 0 then + h = insert_node_before(h,n,newkern(leftkern)) + end + local rightkern = i.rightkern + if rightkern and rightkern ~= 0 then + insert_node_after(head,n,newkern(rightkern)) + n = getnext(n) -- to be checked + end end end else @@ -965,23 +996,23 @@ local function inject_pairs_only(head,where) local h = d for n in traverse_id(glyph_code,d) do if getsubtype(n) < 256 then - local pn = rawget(properties,n) - if pn then - pn = pn.replaceinjections - end - if pn then - local yoffset = pn.yoffset - if yoffset and yoffset ~= 0 then - setfield(n,"yoffset",yoffset) - end - local leftkern = pn.leftkern - if leftkern ~= 0 then - h = insert_node_before(h,n,newkern(leftkern)) - end - local rightkern = pn.rightkern - if rightkern and rightkern ~= 0 then - insert_node_after(head,n,newkern(rightkern)) - n = getnext(n) -- to be checked + local p = rawget(properties,n) + if p then + local i = rawget(pn,"replaceinjections") + if i then + local yoffset = i.yoffset + if yoffset and yoffset ~= 0 then + setfield(n,"yoffset",yoffset) + end + local leftkern = i.leftkern + if leftkern and leftkern ~= 0 then + h = insert_node_before(h,n,newkern(leftkern)) + end + local rightkern = i.rightkern + if rightkern and rightkern ~= 0 then + insert_node_after(head,n,newkern(rightkern)) + n = getnext(n) -- to be checked + end end end else |