diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/fontloader/misc/fontloader-font-gbn.lua | 5 | ||||
-rw-r--r-- | src/fontloader/misc/fontloader-font-otr.lua | 220 | ||||
-rw-r--r-- | src/fontloader/misc/fontloader-font-ots.lua | 46 | ||||
-rw-r--r-- | src/fontloader/runtime/fontloader-reference.lua | 183 |
4 files changed, 315 insertions, 139 deletions
diff --git a/src/fontloader/misc/fontloader-font-gbn.lua b/src/fontloader/misc/fontloader-font-gbn.lua index f81c877..a645a97 100644 --- a/src/fontloader/misc/fontloader-font-gbn.lua +++ b/src/fontloader/misc/fontloader-font-gbn.lua @@ -19,7 +19,6 @@ local nodes = nodes local nuts = nodes.nuts -- context abstraction of direct nodes local traverse_id = nuts.traverse_id -local free_node = nuts.free local remove_node = nuts.remove local glyph_code = nodes.nodecodes.glyph @@ -137,9 +136,7 @@ function nodes.handlers.nodepass(head) end if redundant then for i=1,#redundant do - local n = redundant[i] - remove_node(nuthead,n) - free_node(n) + remove_node(nuthead,redundant[i],true) end end for d in traverse_id(disc_code,nuthead) do diff --git a/src/fontloader/misc/fontloader-font-otr.lua b/src/fontloader/misc/fontloader-font-otr.lua index 1fc338b..0ad1e19 100644 --- a/src/fontloader/misc/fontloader-font-otr.lua +++ b/src/fontloader/misc/fontloader-font-otr.lua @@ -148,7 +148,7 @@ local function reportskippedtable(tag) end -- We have quite some data tables. We are somewhat ff compatible with names but as I used --- the information form the microsoft site there can be differences. Eventually I might end +-- the information from the microsoft site there can be differences. Eventually I might end -- up with a different ordering and naming. local reservednames = { [0] = @@ -163,14 +163,14 @@ local reservednames = { [0] = "manufacturer", "designer", "description", -- descriptor in ff - "venderurl", + "vendorurl", "designerurl", "license", "licenseurl", "reserved", "typographicfamily", -- preffamilyname "typographicsubfamily", -- prefmodifiers - "compatiblefullname", -- for mac + "compatiblefullname", -- for mac "sampletext", "cidfindfontname", "wwsfamily", @@ -244,7 +244,16 @@ local decoders = { macintosh = { }, iso = { }, windows = { - ["unicode bmp"] = utf16_to_utf8_be + -- maybe always utf16 + ["unicode semantics"] = utf16_to_utf8_be, + ["unicode bmp"] = utf16_to_utf8_be, + ["unicode full"] = utf16_to_utf8_be, + ["unicode 1.0 semantics"] = utf16_to_utf8_be, + ["unicode 1.1 semantics"] = utf16_to_utf8_be, + ["unicode 2.0 bmp"] = utf16_to_utf8_be, + ["unicode 2.0 full"] = utf16_to_utf8_be, + ["unicode variation sequences"] = utf16_to_utf8_be, + ["unicode full repertoire"] = utf16_to_utf8_be, }, custom = { }, } @@ -702,7 +711,17 @@ local panosewidths = { -- useful information about what we deal with. The complication is that we need -- to filter the best one available. -function readers.name(f,fontdata) +local platformnames = { + postscriptname = true, + fullname = true, + family = true, + subfamily = true, + typographicfamily = true, + typographicsubfamily = true, + compatiblefullname = true, +} + +function readers.name(f,fontdata,specification) local datatable = fontdata.tables.name if datatable then setposition(f,datatable.offset) @@ -710,6 +729,7 @@ function readers.name(f,fontdata) local nofnames = readushort(f) local offset = readushort(f) -- we can also provide a raw list as extra, todo as option + local start = datatable.offset + offset local namelists = { unicode = { }, windows = { }, @@ -738,7 +758,7 @@ function readers.name(f,fontdata) language = language, name = name, length = readushort(f), - offset = readushort(f), + offset = start + readushort(f), } else skipshort(f,2) @@ -766,7 +786,6 @@ function readers.name(f,fontdata) -- -- we need to choose one we like, for instance an unicode one -- - local start = datatable.offset + offset local names = { } local done = { } -- @@ -783,7 +802,7 @@ function readers.name(f,fontdata) local encoding = name.encoding local language = name.language if (not e or encoding == e) and (not l or language == l) then - setposition(f,start+name.offset) + setposition(f,name.offset) local content = readstring(f,name.length) local decoder = decoders[platform] if decoder then @@ -812,11 +831,57 @@ function readers.name(f,fontdata) filter("unicode") -- fontdata.names = names + -- + if specification.platformnames then + local collected = { } + for platform, namelist in next, namelists do + local filtered = false + for i=1,#namelist do + local entry = namelist[i] + local name = entry.name + if platformnames[name] then + setposition(f,entry.offset) + local content = readstring(f,entry.length) + local encoding = entry.encoding + local decoder = decoders[platform] + if decoder then + decoder = decoder[encoding] + end + if decoder then + content = decoder(content) + end + if filtered then + filtered[name] = content + else + filtered = { [name] = content } + end + end + end + if filtered then + collected[platform] = filtered + end + end + fontdata.platformnames = collected + end else fontdata.names = { } end end +----- validutf = lpeg.patterns.utf8character^0 * P(-1) +local validutf = lpeg.patterns.validutf8 + +local function getname(fontdata,key) + local names = fontdata.names + if names then + local value = names[key] + if value then + local content = value.content + return lpegmatch(validutf,content) and content or nil + end + end +end + -- This table is an original windows (with its precursor os/2) table. In ff this one is -- part of the pfminfo table but here we keep it separate (for now). We will create a -- properties table afterwards. @@ -1733,69 +1798,69 @@ otf.unpackoutlines = unpackoutlines -- some properties in order to read following tables. When details is true we also -- initialize the glyphs data. ------ validutf = lpeg.patterns.utf8character^0 * P(-1) -local validutf = lpeg.patterns.validutf8 - -local function getname(fontdata,key) - local names = fontdata.names - if names then - local value = names[key] - if value then - local content = value.content - return lpegmatch(validutf,content) and content or nil - end - end -end - -local function getinfo(maindata,sub) +local function getinfo(maindata,sub,platformnames) local fontdata = sub and maindata.subfonts and maindata.subfonts[sub] or maindata - local names = fontdata.names + local names = fontdata.names + local info = nil if names then - local metrics = fontdata.windowsmetrics or { } - local postscript = fontdata.postscript or { } - local fontheader = fontdata.fontheader or { } - local cffinfo = fontdata.cffinfo or { } - local filename = fontdata.filename - local weight = getname(fontdata,"weight") or cffinfo.weight or metrics.weight - local width = getname(fontdata,"width") or cffinfo.width or metrics.width - return { -- we inherit some inconsistencies/choices from ff - subfontindex = fontdata.subfontindex or sub or 0, - -- filename = filename, - -- version = name("version"), - -- format = fontdata.format, - fontname = getname(fontdata,"postscriptname"), - fullname = getname(fontdata,"fullname"), -- or file.nameonly(filename) - familyname = getname(fontdata,"typographicfamily") or getname(fontdata,"family"), - subfamily = getname(fontdata,"subfamily"), - modifiers = getname(fontdata,"typographicsubfamily"), - weight = weight and lower(weight), - width = width and lower(width), - pfmweight = metrics.weightclass or 400, -- will become weightclass - pfmwidth = metrics.widthclass or 5, -- will become widthclass - panosewidth = metrics.panosewidth, - panoseweight = metrics.panoseweight, - italicangle = postscript.italicangle or 0, - units = fontheader.units or 0, - designsize = fontdata.designsize, - minsize = fontdata.minsize, - maxsize = fontdata.maxsize, - monospaced = (tonumber(postscript.monospaced or 0) > 0) or metrics.panosewidth == "monospaced", - averagewidth = metrics.averagewidth, - xheight = metrics.xheight, - ascender = metrics.typoascender, - descender = metrics.typodescender, + local metrics = fontdata.windowsmetrics or { } + local postscript = fontdata.postscript or { } + local fontheader = fontdata.fontheader or { } + local cffinfo = fontdata.cffinfo or { } + local filename = fontdata.filename + local weight = getname(fontdata,"weight") or cffinfo.weight or metrics.weight + local width = getname(fontdata,"width") or cffinfo.width or metrics.width + local fontname = getname(fontdata,"postscriptname") + local fullname = getname(fontdata,"fullname") + local family = getname(fontdata,"family") + local subfamily = getname(fontdata,"subfamily") + local familyname = getname(fontdata,"typographicfamily") or family + local subfamilyname = getname(fontdata,"typographicsubfamily") or subfamily + local compatiblename = getname(fontdata,"compatiblefullname") + info = { -- we inherit some inconsistencies/choices from ff + subfontindex = fontdata.subfontindex or sub or 0, + -- filename = filename, + version = getname(fontdata,"version"), + -- format = fontdata.format, + fontname = fontname, + fullname = fullname, + family = family, + subfamily = subfamily, + familyname = familyname, + subfamilyname = subfamilyname, + compatiblename = compatiblename, + weight = weight and lower(weight), + width = width and lower(width), + pfmweight = metrics.weightclass or 400, -- will become weightclass + pfmwidth = metrics.widthclass or 5, -- will become widthclass + panosewidth = metrics.panosewidth, + panoseweight = metrics.panoseweight, + italicangle = postscript.italicangle or 0, + units = fontheader.units or 0, + designsize = fontdata.designsize, + minsize = fontdata.minsize, + maxsize = fontdata.maxsize, + monospaced = (tonumber(postscript.monospaced or 0) > 0) or metrics.panosewidth == "monospaced", + averagewidth = metrics.averagewidth, + xheight = metrics.xheight, + capheight = metrics.capheight, -- not always present and probably crap + ascender = metrics.typoascender, + descender = metrics.typodescender, + platformnames = platformnames and fontdata.platformnames or nil, } elseif n then - return { + info = { filename = fontdata.filename, comment = "there is no info for subfont " .. n, } else - return { + info = { filename = fontdata.filename, comment = "there is no info", } end + -- inspect(info) + return info end local function loadtables(f,specification,offset) @@ -1870,6 +1935,7 @@ local function readdata(f,offset,specification) end end -- + -- readers["os/2"](f,fontdata,specification) readers["head"](f,fontdata,specification) readers["maxp"](f,fontdata,specification) @@ -1989,7 +2055,10 @@ local function loadfont(specification,n) specification.details = true end if specification.details then - specification.info = true + specification.info = true -- not really used any more + end + if specification.platformnames then + specification.platformnames = true -- not really used any more end local function message(str) report("fatal error in file %a: %s\n%s",specification.filename,str,debug.traceback()) @@ -2043,7 +2112,7 @@ function readers.loadfont(filename,n) descriptions = fontdata.descriptions, format = fontdata.format, goodies = { }, - metadata = getinfo(fontdata,n), + metadata = getinfo(fontdata,n), -- no platformnames here ! properties = { hasitalics = fontdata.hasitalics or false, }, @@ -2067,27 +2136,38 @@ function readers.loadfont(filename,n) end end -function readers.getinfo(filename,n,details) +function readers.getinfo(filename,specification) -- string, nil|number|table + -- platformnames is optional and not used by context (a too unpredictable mess + -- that only add to the confusion) .. so it's only for checking things + local subfont = nil + local platformname = false + if type(specification) == "table" then + subfont = tonumber(specification.subfont) + platformnames = specification.platformnames + else + subfont = tonumber(specification) + end local fontdata = loadfont { - filename = filename, - details = true, + filename = filename, + details = true, + platformnames = platformnames, } if fontdata then local subfonts = fontdata.subfonts if not subfonts then - return getinfo(fontdata) - elseif type(n) ~= "number" then + return getinfo(fontdata,nil,platformnames) + elseif not subfont then local info = { } for i=1,#subfonts do - info[i] = getinfo(fontdata,i) + info[i] = getinfo(fontdata,i,platformnames) end return info - elseif n > 1 and n <= subfonts then - return getinfo(fontdata,n) + elseif subfont > 1 and subfont <= #subfonts then + return getinfo(fontdata,subfont,platformnames) else return { filename = filename, - comment = "there is no subfont " .. n .. " in this file" + comment = "there is no subfont " .. subfont .. " in this file" } end else diff --git a/src/fontloader/misc/fontloader-font-ots.lua b/src/fontloader/misc/fontloader-font-ots.lua index 4d5e8ec..d67db6d 100644 --- a/src/fontloader/misc/fontloader-font-ots.lua +++ b/src/fontloader/misc/fontloader-font-ots.lua @@ -2716,8 +2716,8 @@ function otf.dataset(tfmdata,font) -- generic variant, overloaded in context return rl end -local function report_disc(n) - report_run("kern: %s > %s",disc,languages.serializediscretionary(disc)) +local function report_disc(what,n) + report_run("%s: %s > %s",what,n,languages.serializediscretionary(n)) end local function kernrun(disc,k_run,font,attr,...) @@ -2725,7 +2725,7 @@ local function kernrun(disc,k_run,font,attr,...) -- we catch <font 1><disc font 2> -- if trace_kernruns then - report_disc("kern") + report_disc("kern",disc) end -- local prev, next = getboth(disc) @@ -2819,7 +2819,7 @@ end local function comprun(disc,c_run,...) if trace_compruns then - report_disc("comp") + report_disc("comp",disc) end -- local pre, post, replace = getdisc(disc) @@ -2866,31 +2866,35 @@ end local function testrun(disc,t_run,c_run,...) if trace_testruns then - report_disc("test") + report_disc("test",disc) end local prev, next = getboth(disc) if not next then -- weird discretionary return end - local pre, post, replace, pretail, posttail, replacetail = getdisc(disc) + local pre, post, replace, pretail, posttail, replacetail = getdisc(disc,true) local done = false if replace and prev then - -- only look ahead - -- local nest = getprev(replace) + -- this is a bit strange as we only do replace here and not post + -- anyway, we only look ahead ... the idea is that we discard a + -- disc when there is a ligature crossing the replace boundary setlink(replacetail,next) - if t_run(replace,next,...) then - setfield(disc,"replace",nil) -- beware, side effects of nest so first + local ok, overflow = t_run(replace,next,...) + if ok and overflow then + -- so, we can have crossed the boundary + setfield(disc,"replace",nil) setlink(prev,replace) - setlink(replacetail,next) + -- setlink(replacetail,next) setboth(disc) flush_node_list(disc) return replace, true -- restart .. tricky ! else + -- we stay inside the disc setnext(replacetail) setprev(next,disc) end - -- pre, post, replace, pretail, posttail, replacetail = getdisc(disc) + -- pre, post, replace, pretail, posttail, replacetail = getdisc(disc,true) end -- -- like comprun @@ -2945,7 +2949,7 @@ end -- local function discrun(disc,drun,krun) -- local prev, next = getboth(disc) -- if trace_discruns then --- report_disc("disc") +-- report_disc("disc",disc) -- end -- if next and prev then -- setnext(prev,next) @@ -3043,7 +3047,13 @@ local function t_run_single(start,stop,font,attr,lookupcache) -- if we need more than ligatures we can outline the code and use functions local s = getnext(start) local l = nil + local d = 0 while s do + if s == stop then + d = 1 + elseif d > 0 then + d = d + 1 + end local lg = lookupmatch[getchar(s)] if lg then l = lg @@ -3053,7 +3063,7 @@ local function t_run_single(start,stop,font,attr,lookupcache) end end if l and l.ligature then - return true + return true, d > 1 end end end @@ -3168,7 +3178,13 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps) -- if we need more than ligatures we can outline the code and use functions local s = getnext(start) local l = nil + local d = 0 while s do + if s == stop then + d = 1 + elseif d > 0 then + d = d + 1 + end local lg = lookupmatch[getchar(s)] if lg then l = lg @@ -3178,7 +3194,7 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps) end end if l and l.ligature then - return true + return true, d > 1 end end else diff --git a/src/fontloader/runtime/fontloader-reference.lua b/src/fontloader/runtime/fontloader-reference.lua index e4ae182..a4677ef 100644 --- a/src/fontloader/runtime/fontloader-reference.lua +++ b/src/fontloader/runtime/fontloader-reference.lua @@ -1,6 +1,6 @@ -- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua -- parent file : c:/data/develop/context/sources/luatex-fonts.lua --- merge date : 04/04/16 13:06:24 +-- merge date : 04/11/16 19:04:35 do -- begin closure to overcome local limits and interference @@ -8184,7 +8184,7 @@ local reservednames={ [0]="copyright", "manufacturer", "designer", "description", - "venderurl", + "vendorurl", "designerurl", "license", "licenseurl", @@ -8244,7 +8244,15 @@ local decoders={ macintosh={}, iso={}, windows={ - ["unicode bmp"]=utf16_to_utf8_be + ["unicode semantics"]=utf16_to_utf8_be, + ["unicode bmp"]=utf16_to_utf8_be, + ["unicode full"]=utf16_to_utf8_be, + ["unicode 1.0 semantics"]=utf16_to_utf8_be, + ["unicode 1.1 semantics"]=utf16_to_utf8_be, + ["unicode 2.0 bmp"]=utf16_to_utf8_be, + ["unicode 2.0 full"]=utf16_to_utf8_be, + ["unicode variation sequences"]=utf16_to_utf8_be, + ["unicode full repertoire"]=utf16_to_utf8_be, }, custom={}, } @@ -8355,13 +8363,23 @@ local panosewidths={ [ 8]="verycondensed", [ 9]="monospaced", } -function readers.name(f,fontdata) +local platformnames={ + postscriptname=true, + fullname=true, + family=true, + subfamily=true, + typographicfamily=true, + typographicsubfamily=true, + compatiblefullname=true, +} +function readers.name(f,fontdata,specification) local datatable=fontdata.tables.name if datatable then setposition(f,datatable.offset) local format=readushort(f) local nofnames=readushort(f) local offset=readushort(f) + local start=datatable.offset+offset local namelists={ unicode={}, windows={}, @@ -8388,7 +8406,7 @@ function readers.name(f,fontdata) language=language, name=name, length=readushort(f), - offset=readushort(f), + offset=start+readushort(f), } else skipshort(f,2) @@ -8406,7 +8424,6 @@ function readers.name(f,fontdata) skipshort(f,5) end end - local start=datatable.offset+offset local names={} local done={} local function filter(platform,e,l) @@ -8418,7 +8435,7 @@ function readers.name(f,fontdata) local encoding=name.encoding local language=name.language if (not e or encoding==e) and (not l or language==l) then - setposition(f,start+name.offset) + setposition(f,name.offset) local content=readstring(f,name.length) local decoder=decoders[platform] if decoder then @@ -8444,10 +8461,52 @@ function readers.name(f,fontdata) filter("macintosh") filter("unicode") fontdata.names=names + if specification.platformnames then + local collected={} + for platform,namelist in next,namelists do + local filtered=false + for i=1,#namelist do + local entry=namelist[i] + local name=entry.name + if platformnames[name] then + setposition(f,entry.offset) + local content=readstring(f,entry.length) + local encoding=entry.encoding + local decoder=decoders[platform] + if decoder then + decoder=decoder[encoding] + end + if decoder then + content=decoder(content) + end + if filtered then + filtered[name]=content + else + filtered={ [name]=content } + end + end + end + if filtered then + collected[platform]=filtered + end + end + fontdata.platformnames=collected + end else fontdata.names={} end end +local validutf=lpeg.patterns.validutf8 +local function getname(fontdata,key) + local names=fontdata.names + if names then + local value=names[key] + if value then + local content=value.content + return lpegmatch(validutf,content) and content or nil + end + end +end readers["os/2"]=function(f,fontdata) local datatable=fontdata.tables["os/2"] if datatable then @@ -9233,20 +9292,10 @@ local function unpackoutlines(data) end otf.packoutlines=packoutlines otf.unpackoutlines=unpackoutlines -local validutf=lpeg.patterns.validutf8 -local function getname(fontdata,key) - local names=fontdata.names - if names then - local value=names[key] - if value then - local content=value.content - return lpegmatch(validutf,content) and content or nil - end - end -end -local function getinfo(maindata,sub) +local function getinfo(maindata,sub,platformnames) local fontdata=sub and maindata.subfonts and maindata.subfonts[sub] or maindata local names=fontdata.names + local info=nil if names then local metrics=fontdata.windowsmetrics or {} local postscript=fontdata.postscript or {} @@ -9255,13 +9304,23 @@ local function getinfo(maindata,sub) local filename=fontdata.filename local weight=getname(fontdata,"weight") or cffinfo.weight or metrics.weight local width=getname(fontdata,"width") or cffinfo.width or metrics.width - return { + local fontname=getname(fontdata,"postscriptname") + local fullname=getname(fontdata,"fullname") + local family=getname(fontdata,"family") + local subfamily=getname(fontdata,"subfamily") + local familyname=getname(fontdata,"typographicfamily") or family + local subfamilyname=getname(fontdata,"typographicsubfamily") or subfamily + local compatiblename=getname(fontdata,"compatiblefullname") + info={ subfontindex=fontdata.subfontindex or sub or 0, - fontname=getname(fontdata,"postscriptname"), - fullname=getname(fontdata,"fullname"), - familyname=getname(fontdata,"typographicfamily") or getname(fontdata,"family"), - subfamily=getname(fontdata,"subfamily"), - modifiers=getname(fontdata,"typographicsubfamily"), + version=getname(fontdata,"version"), + fontname=fontname, + fullname=fullname, + family=family, + subfamily=subfamily, + familyname=familyname, + subfamilyname=subfamilyname, + compatiblename=compatiblename, weight=weight and lower(weight), width=width and lower(width), pfmweight=metrics.weightclass or 400, @@ -9276,20 +9335,23 @@ local function getinfo(maindata,sub) monospaced=(tonumber(postscript.monospaced or 0)>0) or metrics.panosewidth=="monospaced", averagewidth=metrics.averagewidth, xheight=metrics.xheight, + capheight=metrics.capheight, ascender=metrics.typoascender, descender=metrics.typodescender, + platformnames=platformnames and fontdata.platformnames or nil, } elseif n then - return { + info={ filename=fontdata.filename, comment="there is no info for subfont "..n, } else - return { + info={ filename=fontdata.filename, comment="there is no info", } end + return info end local function loadtables(f,specification,offset) if offset then @@ -9470,7 +9532,10 @@ local function loadfont(specification,n) specification.details=true end if specification.details then - specification.info=true + specification.info=true + end + if specification.platformnames then + specification.platformnames=true end local function message(str) report("fatal error in file %a: %s\n%s",specification.filename,str,debug.traceback()) @@ -9538,27 +9603,36 @@ function readers.loadfont(filename,n) } end end -function readers.getinfo(filename,n,details) +function readers.getinfo(filename,specification) + local subfont=nil + local platformname=false + if type(specification)=="table" then + subfont=tonumber(specification.subfont) + platformnames=specification.platformnames + else + subfont=tonumber(specification) + end local fontdata=loadfont { filename=filename, details=true, + platformnames=platformnames, } if fontdata then local subfonts=fontdata.subfonts if not subfonts then - return getinfo(fontdata) - elseif type(n)~="number" then + return getinfo(fontdata,nil,platformnames) + elseif not subfont then local info={} for i=1,#subfonts do - info[i]=getinfo(fontdata,i) + info[i]=getinfo(fontdata,i,platformnames) end return info - elseif n>1 and n<=subfonts then - return getinfo(fontdata,n) + elseif subfont>1 and subfont<=#subfonts then + return getinfo(fontdata,subfont,platformnames) else return { filename=filename, - comment="there is no subfont "..n.." in this file" + comment="there is no subfont "..subfont.." in this file" } end else @@ -20229,12 +20303,12 @@ function otf.dataset(tfmdata,font) end return rl end -local function report_disc(n) - report_run("kern: %s > %s",disc,languages.serializediscretionary(disc)) +local function report_disc(what,n) + report_run("%s: %s > %s",what,n,languages.serializediscretionary(n)) end local function kernrun(disc,k_run,font,attr,...) if trace_kernruns then - report_disc("kern") + report_disc("kern",disc) end local prev,next=getboth(disc) local nextstart=next @@ -20315,7 +20389,7 @@ local function kernrun(disc,k_run,font,attr,...) end local function comprun(disc,c_run,...) if trace_compruns then - report_disc("comp") + report_disc("comp",disc) end local pre,post,replace=getdisc(disc) local renewed=false @@ -20355,20 +20429,20 @@ local function comprun(disc,c_run,...) end local function testrun(disc,t_run,c_run,...) if trace_testruns then - report_disc("test") + report_disc("test",disc) end local prev,next=getboth(disc) if not next then return end - local pre,post,replace,pretail,posttail,replacetail=getdisc(disc) + local pre,post,replace,pretail,posttail,replacetail=getdisc(disc,true) local done=false if replace and prev then setlink(replacetail,next) - if t_run(replace,next,...) then - setfield(disc,"replace",nil) + local ok,overflow=t_run(replace,next,...) + if ok and overflow then + setfield(disc,"replace",nil) setlink(prev,replace) - setlink(replacetail,next) setboth(disc) flush_node_list(disc) return replace,true @@ -20460,7 +20534,13 @@ local function t_run_single(start,stop,font,attr,lookupcache) if lookupmatch then local s=getnext(start) local l=nil + local d=0 while s do + if s==stop then + d=1 + elseif d>0 then + d=d+1 + end local lg=lookupmatch[getchar(s)] if lg then l=lg @@ -20470,7 +20550,7 @@ local function t_run_single(start,stop,font,attr,lookupcache) end end if l and l.ligature then - return true + return true,d>1 end end end @@ -20560,7 +20640,13 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps) if lookupmatch then local s=getnext(start) local l=nil + local d=0 while s do + if s==stop then + d=1 + elseif d>0 then + d=d+1 + end local lg=lookupmatch[getchar(s)] if lg then l=lg @@ -20570,7 +20656,7 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps) end end if l and l.ligature then - return true + return true,d>1 end end else @@ -23666,7 +23752,6 @@ local fonts=fonts local nodes=nodes local nuts=nodes.nuts local traverse_id=nuts.traverse_id -local free_node=nuts.free local remove_node=nuts.remove local glyph_code=nodes.nodecodes.glyph local disc_code=nodes.nodecodes.disc @@ -23769,9 +23854,7 @@ function nodes.handlers.nodepass(head) end if redundant then for i=1,#redundant do - local n=redundant[i] - remove_node(nuthead,n) - free_node(n) + remove_node(nuthead,redundant[i],true) end end for d in traverse_id(disc_code,nuthead) do |