diff options
author | Karl Berry <karl@freefriends.org> | 2022-06-16 20:19:58 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2022-06-16 20:19:58 +0000 |
commit | 1f9af4111f133e2a9a62e36bd20422ca1d5ac470 (patch) | |
tree | d64c35d980053e3079e2b16f47bef444186f45ef /Master/texmf-dist/tex/luatex/luaotfload | |
parent | 33d74394baff89dc3d7f6018d5ddfcd8fdcda490 (diff) |
luaotfload (16jun22)
git-svn-id: svn://tug.org/texlive/trunk@63611 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/luatex/luaotfload')
47 files changed, 1960 insertions, 876 deletions
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-2022-02-24.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-2022-06-15.lua index aee123be032..5e0af8e4846 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-2022-02-24.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-2022-06-15.lua @@ -1,6 +1,6 @@ --[[info----------------------------------------------------------------------- Luaotfload fontloader package - build 2022-02-24 08:04:22 + build 2022-06-15 18:33:10 ------------------------------------------------------------------------------- © 2022 PRAGMA ADE / ConTeXt Development Team @@ -63,7 +63,7 @@ --info]]----------------------------------------------------------------------- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “data-con” 23a0f5386d46a1c157ae82a373e35fa0] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “data-con” 23a0f5386d46a1c157ae82a373e35fa0] --- if not modules then modules={} end modules ['data-con']={ version=1.100, @@ -184,10 +184,10 @@ function containers.cleanname(name) return (gsub(lower(name),"[^%w\128-\255]+","-")) end -end --- [luaotfload, fontloader-2022-02-24.lua scope for “data-con”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “data-con”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “basics-nod” 1750af43148def9e7a75c6900a96f9dc] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “basics-nod” 1750af43148def9e7a75c6900a96f9dc] --- if not modules then modules={} end modules ['luatex-fonts-nod']={ version=1.001, @@ -454,10 +454,10 @@ do end end -end --- [luaotfload, fontloader-2022-02-24.lua scope for “basics-nod”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “basics-nod”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “basics-chr” 1bb1ea05b5ca1bb5a9848b9eb66322bf] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “basics-chr” ce4afac7ba19471f3c8f90800839f315] --- characters=characters or {} @@ -4291,10 +4291,10 @@ characters.indicgroups={ }, } -end --- [luaotfload, fontloader-2022-02-24.lua scope for “basics-chr”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “basics-chr”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “font-ini” 5343de60613adb24cdd7a8d2ee1d153c] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “font-ini” 5343de60613adb24cdd7a8d2ee1d153c] --- if not modules then modules={} end modules ['font-ini']={ version=1.001, @@ -4335,10 +4335,10 @@ if node and not tex.getfontoffamily then tex.getfontoffamily=node.family_font end -end --- [luaotfload, fontloader-2022-02-24.lua scope for “font-ini”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “font-ini”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “fonts-mis” 17e967c9ec4d001deefd43ddf25e98f7] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “fonts-mis” 17e967c9ec4d001deefd43ddf25e98f7] --- if not modules then modules={} end modules ['luatex-font-mis']={ version=1.001, @@ -4370,10 +4370,10 @@ function font.each() return table.sortedhash(fonts.hashes.identifiers) end -end --- [luaotfload, fontloader-2022-02-24.lua scope for “fonts-mis”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “fonts-mis”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “font-con” 724e5dd14aec2d4d189f8619898004cf] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “font-con” 724e5dd14aec2d4d189f8619898004cf] --- if not modules then modules={} end modules ['font-con']={ version=1.001, @@ -5741,10 +5741,10 @@ function constructors.addcoreunicodes(unicodes) return unicodes end -end --- [luaotfload, fontloader-2022-02-24.lua scope for “font-con”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “font-con”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “fonts-enc” c24fd6b4f34f87b9c4ff5e6193ce2656] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “fonts-enc” c24fd6b4f34f87b9c4ff5e6193ce2656] --- if not modules then modules={} end modules ['luatex-font-enc']={ version=1.001, @@ -5819,10 +5819,10 @@ function encodings.load(filename) return containers.write(encodings.cache,name,data) end -end --- [luaotfload, fontloader-2022-02-24.lua scope for “fonts-enc”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “fonts-enc”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “font-cid” 22b0367742fb253deef84ef7ccf5e8de] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “font-cid” 22b0367742fb253deef84ef7ccf5e8de] --- if not modules then modules={} end modules ['font-cid']={ version=1.001, @@ -5973,10 +5973,10 @@ function cid.getmap(specification) return found end -end --- [luaotfload, fontloader-2022-02-24.lua scope for “font-cid”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “font-cid”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “font-map” c4a39db5ad822b348aa61bca5f4a599a] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “font-map” 27ee748150e56f5f0e5f0fefc864f35e] --- if not modules then modules={} end modules ['font-map']={ version=1.001, @@ -6164,9 +6164,9 @@ function mappings.addtounicode(data,filename,checklookups,forceligatures) local usedmap=cidinfo and fonts.cid.getmap(cidinfo) local uparser=makenameparser() if usedmap then - oparser=usedmap and makenameparser(cidinfo.ordering) - cidnames=usedmap.names - cidcodes=usedmap.unicodes + oparser=usedmap and makenameparser(cidinfo.ordering) + cidnames=usedmap.names + cidcodes=usedmap.unicodes end local ns=0 local nl=0 @@ -6384,10 +6384,10 @@ function mappings.addtounicode(data,filename,checklookups,forceligatures) end end -end --- [luaotfload, fontloader-2022-02-24.lua scope for “font-map”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “font-map”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “font-vfc” a81c29eda98cd62cbebdb6c93544b50d] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “font-vfc” a81c29eda98cd62cbebdb6c93544b50d] --- if not modules then modules={} end modules ['font-vfc']={ version=1.001, @@ -6484,10 +6484,10 @@ helpers.commands=utilities.storage.allocate { dummy=dummy, } -end --- [luaotfload, fontloader-2022-02-24.lua scope for “font-vfc”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “font-vfc”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “font-otr” 91f70c1216e60227e1437b6c8dcd8647] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “font-otr” 1896ac990a961f6d6fec551ca9b52a83] --- if not modules then modules={} end modules ['font-otr']={ version=1.001, @@ -8295,13 +8295,13 @@ function readers.getinfo(filename,specification) } end end -function readers.rehash(fontdata,hashmethod) +function readers.rehash() report("the %a helper is not yet implemented","rehash") end -function readers.checkhash(fontdata) +function readers.checkhash() report("the %a helper is not yet implemented","checkhash") end -function readers.pack(fontdata,hashmethod) +function readers.pack() report("the %a helper is not yet implemented","pack") end function readers.unpack(fontdata) @@ -8331,10 +8331,10 @@ function readers.extend(fontdata) end end -end --- [luaotfload, fontloader-2022-02-24.lua scope for “font-otr”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “font-otr”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “font-oti” 309a75f9c14b77d87e94eba827dc4e71] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “font-oti” 309a75f9c14b77d87e94eba827dc4e71] --- if not modules then modules={} end modules ['font-oti']={ version=1.001, @@ -8477,10 +8477,10 @@ function otffeatures.checkeddefaultlanguage(featuretype,autolanguage,languages) end end -end --- [luaotfload, fontloader-2022-02-24.lua scope for “font-oti”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “font-oti”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “font-ott” 3f67b1b1d40bbc222681d8db4aff0f42] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “font-ott” 3f67b1b1d40bbc222681d8db4aff0f42] --- if not modules then modules={} end modules ["font-ott"]={ version=1.001, @@ -9596,10 +9596,10 @@ function otffeatures.normalize(features,wrap) end end -end --- [luaotfload, fontloader-2022-02-24.lua scope for “font-ott”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “font-ott”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “font-cff” e38c1a40e1d1d577cdf7920fa50d0654] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “font-cff” e38c1a40e1d1d577cdf7920fa50d0654] --- if not modules then modules={} end modules ['font-cff']={ version=1.001, @@ -11828,10 +11828,10 @@ function readers.cffcheck(filename) end end -end --- [luaotfload, fontloader-2022-02-24.lua scope for “font-cff”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “font-cff”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “font-ttf” feba1fdc80160343b24f89ef978e53cb] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “font-ttf” a3ff07150b3535fd32f68748d53fcd36] --- if not modules then modules={} end modules ['font-ttf']={ version=1.001, @@ -12011,95 +12011,123 @@ local function applyaxis(glyph,shape,deltas,dowidth) end end elseif cnt>0 then - local function find(i) - local prv=cnt - for j=1,cnt do - local nxt=dpoints[j] - if nxt==i then - return false,j,false - elseif nxt>i then - return prv,false,j - end - prv=j - end - return prv,false,1 - end - for i=1,nofpoints do - local d1,d2,d3=find(i) - local p2=points[i] - if d2 then - xv[i]=xvalues[d2] - yv[i]=yvalues[d2] - else - local n1=dpoints[d1] - local n3=dpoints[d3] - if n1>nofpoints then - n1=nofpoints - end - if n3>nofpoints then - n3=nofpoints - end - local p1=points[n1] - local p3=points[n3] - local p1x=p1[1] - local p2x=p2[1] - local p3x=p3[1] - local p1y=p1[2] - local p2y=p2[2] - local p3y=p3[2] - local x1=xvalues[d1] - local y1=yvalues[d1] - local x3=xvalues[d3] - local y3=yvalues[d3] - local fx - local fy - if p1x==p3x then - if x1==x3 then - fx=x1 - else - fx=0 - end - elseif p2x<=min(p1x,p3x) then - if p1x<p3x then - fx=x1 - else - fx=x3 - end - elseif p2x>=max(p1x,p3x) then - if p1x>p3x then - fx=x1 - else - fx=x3 + local contours=shape.contours + local nofcontours=#contours + local first=1 + local firstindex=1 + for contour=1,nofcontours do + local last=contours[contour] + if last>=first then + local lastindex=cnt + if firstindex<cnt then + for currentindex=firstindex,cnt do + local found=dpoints[currentindex] + if found<=first then + firstindex=currentindex + end + if found==last then + lastindex=currentindex + break; + elseif found>last then + break + end end - else - fx=(p2x-p1x)/(p3x-p1x) - fx=(1-fx)*x1+fx*x3 end - if p1y==p3y then - if y1==y3 then - fy=y1 - else - fy=0 - end - elseif p2y<=min(p1y,p3y) then - if p1y<p3y then - fy=y1 - else - fy=y3 + local function find(i) + local prv=lastindex + for j=firstindex,lastindex do + local nxt=dpoints[j] + if nxt==i then + return false,j,false + elseif nxt>i then + return prv,false,j + end + prv=j end - elseif p2y>=max(p1y,p3y) then - if p1y>p3y then - fy=y1 + return prv,false,firstindex + end + for point=first,last do + local d1,d2,d3=find(point) + local p2=points[point] + if d2 then + xv[point]=xvalues[d2] + yv[point]=yvalues[d2] else - fy=y3 + local n1=dpoints[d1] + local n3=dpoints[d3] + if n1>nofpoints then + n1=nofpoints + end + if n3>nofpoints then + n3=nofpoints + end + local p1=points[n1] + local p3=points[n3] + local p1x=p1[1] + local p2x=p2[1] + local p3x=p3[1] + local p1y=p1[2] + local p2y=p2[2] + local p3y=p3[2] + local x1=xvalues[d1] + local y1=yvalues[d1] + local x3=xvalues[d3] + local y3=yvalues[d3] + local fx + local fy + if p1x==p3x then + if x1==x3 then + fx=x1 + else + fx=0 + end + elseif p2x<=min(p1x,p3x) then + if p1x<p3x then + fx=x1 + else + fx=x3 + end + elseif p2x>=max(p1x,p3x) then + if p1x>p3x then + fx=x1 + else + fx=x3 + end + else + fx=(p2x-p1x)/(p3x-p1x) + fx=(1-fx)*x1+fx*x3 + end + if p1y==p3y then + if y1==y3 then + fy=y1 + else + fy=0 + end + elseif p2y<=min(p1y,p3y) then + if p1y<p3y then + fy=y1 + else + fy=y3 + end + elseif p2y>=max(p1y,p3y) then + if p1y>p3y then + fy=y1 + else + fy=y3 + end + else + fy=(p2y-p1y)/(p3y-p1y) + fy=(1-fy)*y1+fy*y3 + end + xv[point]=fx + yv[point]=fy end - else - fy=(p2y-p1y)/(p3y-p1y) - fy=(1-fy)*y1+fy*y3 end - xv[i]=fx - yv[i]=fy + if lastindex<cnt then + firstindex=lastindex+1 + end end + first=last+1 end for i=1,nofpoints do local pi=points[i] @@ -13063,10 +13091,10 @@ function readers.gvar(f,fontdata,specification,glyphdata,shapedata) end end -end --- [luaotfload, fontloader-2022-02-24.lua scope for “font-ttf”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “font-ttf”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “font-dsp” 7616dae672693fd8ec0f1892358019a2] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “font-dsp” 4935e6605ffd7bf57e66f0b6c132f883] --- if not modules then modules={} end modules ['font-dsp']={ version=1.001, @@ -15112,7 +15140,7 @@ do local scriptoffset=tableoffset+readushort(f) local featureoffset=tableoffset+readushort(f) local lookupoffset=tableoffset+readushort(f) - local variationsoffset=version>0x00010000 and (tableoffset+readulong(f)) or 0 + local variationsoffset=version>0x00010000 and readulong(f) or 0 if not scriptoffset then return end @@ -15132,7 +15160,7 @@ do resolvelookups(f,lookupoffset,fontdata,lookups,lookuptypes,lookuphandlers,what,tableoffset) end if variationsoffset>0 then - loadvariations(f,fontdata,variationsoffset,lookuptypes,featurehash,featureorder) + loadvariations(f,fontdata,tableoffset+variationsoffset,lookuptypes,featurehash,featureorder) end end end @@ -16247,6 +16275,7 @@ function readers.hvar(f,fontdata,specification) local variations={} local innerindex={} local outerindex={} + local deltas={} if variationoffset>0 then regions,deltas=readvariationdata(f,variationoffset,factors) end @@ -16343,10 +16372,10 @@ function readers.mvar(f,fontdata,specification) end end -end --- [luaotfload, fontloader-2022-02-24.lua scope for “font-dsp”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “font-dsp”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “font-oup” e6e2cc0a202aec2c787d5524e64d340a] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “font-oup” 76dc3379061e5650f772909966b5759e] --- if not modules then modules={} end modules ['font-oup']={ version=1.001, @@ -16359,6 +16388,7 @@ local next,type=next,type local P,R,S=lpeg.P,lpeg.R,lpeg.S local lpegmatch=lpeg.match local insert,remove,copy,unpack=table.insert,table.remove,table.copy,table.unpack +local find=string.find local formatters=string.formatters local sortedkeys=table.sortedkeys local sortedhash=table.sortedhash @@ -17217,61 +17247,137 @@ local function unifyglyphs(fontdata,usenames) fontdata.nofglyphs=nofglyphs return indices,names end -local p_crappyname do +local stripredundant do local p_hex=R("af","AF","09") local p_digit=R("09") local p_done=S("._-")^0+P(-1) + local p_style=P(".") local p_alpha=R("az","AZ") local p_ALPHA=R("AZ") - p_crappyname=( + local p_crappyname=( lpeg.utfchartabletopattern({ "uni","u" },true)*S("Xx_")^0*p_hex^1 +lpeg.utfchartabletopattern({ "identity","glyph","jamo" },true)*p_hex^1 +lpeg.utfchartabletopattern({ "index","afii" },true)*p_digit^1 +p_digit*p_hex^3+p_alpha*p_digit^1 +P("aj")*p_digit^1+P("eh_")*(p_digit^1+p_ALPHA*p_digit^1)+(1-P("_"))^1*P("_uni")*p_hex^1+P("_")*P(1)^1 )*p_done -end -local forcekeep=false -directives.register("otf.keepnames",function(v) - report_cleanup("keeping weird glyph names, expect larger files and more memory usage") - forcekeep=v -end) -local function stripredundant(fontdata) - local descriptions=fontdata.descriptions - if descriptions then - local n=0 - local c=0 - if (not context and fonts.privateoffsets.keepnames) or forcekeep then - for unicode,d in next,descriptions do - if d.class=="base" then - d.class=nil - c=c+1 + if context then + local forcekeep=false + directives.register("otf.keepnames",function(v) + report_cleanup("keeping weird glyph names, expect larger files and more memory usage") + forcekeep=v + end) + local function stripvariants(descriptions,list) + local n=list and #list or 0 + if n>0 then + for i=1,n do + local g=list[i] + if g then + local d=descriptions[g] + if d and d.name then + d.name=nil + n=n+1 + end + end end end - else - for unicode,d in next,descriptions do - local name=d.name - if name and lpegmatch(p_crappyname,name) then - d.name=nil - n=n+1 - end - if d.class=="base" then - d.class=nil - c=c+1 + return n + end + local function stripparts(descriptions,list) + local n=list and #list or 0 + if n>0 then + for i=1,n do + local g=list[i].glyph + if g then + local d=descriptions[g] + if d and d.name then + d.name=nil + n=n+1 + end + end end end + return n end - if trace_cleanup then - if n>0 then - report_cleanup("%s bogus names removed (verbose unicode)",n) + local function collectsimple(fontdata) + return nil + end + stripredundant=function(fontdata) + local descriptions=fontdata.descriptions + if descriptions then + local n=0 + local c=0 + for unicode,d in next,descriptions do + local m=d.math + if m then + n=n+stripvariants(descriptions,m.vvariants) + n=n+stripvariants(descriptions,m.hvariants) + n=n+stripparts (descriptions,m.vparts) + n=n+stripparts (descriptions,m.hparts) + end + end + if forcekeep then + for unicode,d in next,descriptions do + if d.class=="base" then + d.class=nil + c=c+1 + end + end + else + local keeplist=collectsimple(fontdata) + for unicode,d in next,descriptions do + local name=d.name + if name then + if keeplist and keeplist[name] then + elseif lpegmatch(p_crappyname,name) then + d.name=nil + n=n+1 + end + end + if d.class=="base" then + d.class=nil + c=c+1 + end + end + end + if trace_cleanup then + if n>0 then + report_cleanup("%s bogus names removed (verbose unicode)",n) + end + if c>0 then + report_cleanup("%s base class tags removed (default is base)",c) + end + end end - if c>0 then - report_cleanup("%s base class tags removed (default is base)",c) + end + else + stripredundant=function(fontdata) + local descriptions=fontdata.descriptions + if descriptions then + if fonts.privateoffsets.keepnames then + for unicode,d in next,descriptions do + if d.class=="base" then + d.class=nil + end + end + else + for unicode,d in next,descriptions do + local name=d.name + if name then + if lpegmatch(p_crappyname,name) then + d.name=nil + end + end + if d.class=="base" then + d.class=nil + end + end + end end end end + readers.stripredundant=stripredundant end -readers.stripredundant=stripredundant function readers.getcomponents(fontdata) local resources=fontdata.resources if resources then @@ -17355,8 +17461,7 @@ readers.unifymissing=unifymissing function readers.rehash(fontdata,hashmethod) if not (fontdata and fontdata.glyphs) then return - end - if hashmethod=="indices" then + elseif hashmethod=="indices" then fontdata.hashmethod="indices" elseif hashmethod=="names" then fontdata.hashmethod="names" @@ -19108,10 +19213,10 @@ end expandlookups(sublookups,sequences) end -end --- [luaotfload, fontloader-2022-02-24.lua scope for “font-oup”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “font-oup”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “font-otl” 67078f58bc1a612e4646523538a4e3eb] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “font-otl” 308b1aab04bc131da7eb8e8c3b0471d4] --- if not modules then modules={} end modules ['font-otl']={ version=1.001, @@ -19139,7 +19244,7 @@ local trace_defining=false registertracker("fonts.defining",function(v) trace_d local report_otf=logs.reporter("fonts","otf loading") local fonts=fonts local otf=fonts.handlers.otf -otf.version=3.119 +otf.version=3.120 otf.cache=containers.define("fonts","otl",otf.version,true) otf.svgcache=containers.define("fonts","svg",otf.version,true) otf.pngcache=containers.define("fonts","png",otf.version,true) @@ -19839,10 +19944,10 @@ otf.coverup={ end } -end --- [luaotfload, fontloader-2022-02-24.lua scope for “font-otl”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “font-otl”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “font-oto” 9febc4d75d17a543cd73fb17918f7307] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “font-oto” 9febc4d75d17a543cd73fb17918f7307] --- if not modules then modules={} end modules ['font-oto']={ version=1.001, @@ -20311,10 +20416,10 @@ registerotffeature { } otf.basemodeinitializer=featuresinitializer -end --- [luaotfload, fontloader-2022-02-24.lua scope for “font-oto”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “font-oto”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “font-otj” b2c165bd6771a57633f992d07384b739] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “font-otj” b2c165bd6771a57633f992d07384b739] --- if not modules then modules={} end modules ['font-otj']={ version=1.001, @@ -21807,10 +21912,10 @@ function injections.handler(head,where) end end -end --- [luaotfload, fontloader-2022-02-24.lua scope for “font-otj”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “font-otj”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “font-ota” 2bb12d708e35bc05443eba791e2554e7] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “font-ota” 2bb12d708e35bc05443eba791e2554e7] --- if not modules then modules={} end modules ['font-ota']={ version=1.001, @@ -22304,10 +22409,10 @@ directives.register("otf.analyze.useunicodemarks",function(v) analyzers.useunicodemarks=v end) -end --- [luaotfload, fontloader-2022-02-24.lua scope for “font-ota”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “font-ota”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “font-ots” 55316a605d11a1d07d38795224c90a63] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “font-ots” 55316a605d11a1d07d38795224c90a63] --- if not modules then modules={} end modules ['font-ots']={ version=1.001, @@ -25967,10 +26072,10 @@ registerotffeature { }, } -end --- [luaotfload, fontloader-2022-02-24.lua scope for “font-ots”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “font-ots”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “font-osd” a67b6fb465e7a8b9ecf7c6bbf8dfda03] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “font-osd” 9b5337b0051b8e42b6c8329127c59794] --- if not modules then modules={} end modules ['font-osd']={ version=1.001, @@ -25979,6 +26084,14 @@ if not modules then modules={} end modules ['font-osd']={ copyright="TAT Zetwerk / PRAGMA ADE / ConTeXt Development Team", license="see context related readme files" } +local experiment1=false +local experiment2=false +local experiment2b1=false +local experiment2b2=false +experiments.register("fonts.indic.experiment1",function(v) experiment1=v end) +experiments.register("fonts.indic.experiment2",function(v) experiment2=v end) +experiments.register("fonts.indic.experiment2b1",function(v) experiment2b1=v end) +experiments.register("fonts.indic.experiment2b2",function(v) experiment2b2=v end) local insert,remove,imerge,copy,tohash=table.insert,table.remove,table.imerge,table.copy,table.tohash local next,type,rawget=next,type,rawget local formatters=string.formatters @@ -27508,7 +27621,7 @@ local function reorder_two(head,start,stop,font,attr,nbspaces) local subpos=nil local postpos=nil reorderreph.coverage={} - rephbase[font]={} + rephbase[font]={} for i=1,#seqsubset do local subset=seqsubset[i] local kind=subset[1] @@ -27685,7 +27798,7 @@ local function reorder_two(head,start,stop,font,attr,nbspaces) logprocess("reorder two, handle nbsp") end end - else + else local last=getnext(stop) while current~=last do local next=getnext(current) @@ -27748,7 +27861,7 @@ local function reorder_two(head,start,stop,font,attr,nbspaces) logprocess("reorder two, handle matra") end end - if not moved[current] and dependent_vowel[char] then + if dependent_vowel[char] then if pre_mark[char] then moved[current]=true local prev,next=getboth(current) @@ -27927,8 +28040,8 @@ local function analyze_next_chars_one(c,font,variant) if not n then return c end + local v=ischar(n,font) if variant==1 then - local v=ischar(n,font) if v and nukta[v] then n=getnext(n) if n then @@ -27961,7 +28074,6 @@ local function analyze_next_chars_one(c,font,variant) end end elseif variant==2 then - local v=ischar(n,font) if v and nukta[v] then c=n end @@ -27985,11 +28097,11 @@ local function analyze_next_chars_one(c,font,variant) end end end - local n=getnext(c) + n=getnext(c) if not n then return c end - local v=ischar(n,font) + v=ischar(n,font) if not v then return c end @@ -28094,12 +28206,11 @@ local function analyze_next_chars_one(c,font,variant) end end local function analyze_next_chars_two(c,font) - local n,v - n=getnext(c) + local n=getnext(c) if not n then return c end - v=ischar(n,font) + local v=ischar(n,font) if v and nukta[v] then c=n end @@ -28605,10 +28716,10 @@ for i=1,nofscripts do methods[scripts_two[i]]=method_two end -end --- [luaotfload, fontloader-2022-02-24.lua scope for “font-osd”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “font-osd”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “font-ocl” 2a377351ae23c339764ec8ce2e8e9164] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “font-ocl” 2a377351ae23c339764ec8ce2e8e9164] --- if not modules then modules={} end modules ['font-ocl']={ version=1.001, @@ -29156,10 +29267,10 @@ if context then } end -end --- [luaotfload, fontloader-2022-02-24.lua scope for “font-ocl”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “font-ocl”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “font-otc” 582295d3d1e44cd4a31e8bbc1156f7c1] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “font-otc” 57f5270b894e40efa93149c7d3fb0209] --- if not modules then modules={} end modules ['font-otc']={ version=1.001, @@ -29276,7 +29387,7 @@ local function validspecification(specification,name) return specification,name end end -local function addfeature(data,feature,specifications) +local function addfeature(data,feature,specifications,prepareonly) if not specifications then report_otf("missing specification") return @@ -29575,8 +29686,6 @@ local function addfeature(data,feature,specifications) local rules=list.rules local coverage={} if rules then - local rulehash={} - local rulesize=0 local lookuptype=types[featuretype] for nofrules=1,#rules do local rule=rules[nofrules] @@ -29607,6 +29716,14 @@ local function addfeature(data,feature,specifications) local lookups=rule.lookups or false local subtype=nil if lookups and sublookups then + if #lookups>0 then + local ns=stop-start+1 + for i=1,ns do + if lookups[i]==nil then + lookups[i]=0 + end + end + end local l={} for k,v in sortedhash(lookups) do local t=type(v) @@ -29654,8 +29771,7 @@ local function addfeature(data,feature,specifications) hashed[i]=t end sequence=hashed - rulesize=rulesize+1 - rulehash[rulesize]={ + local ruleset={ nofrules, lookuptype, sequence, @@ -29667,8 +29783,15 @@ local function addfeature(data,feature,specifications) } for unic in sortedhash(sequence[start]) do local cu=coverage[unic] - if not cu then - coverage[unic]=rulehash + if cu then + local n=cu.n+1 + cu[n]=ruleset + cu.n=n + else + coverage[unic]={ + ruleset, + n=1, + } end end sequence.n=nofsequences @@ -29676,7 +29799,6 @@ local function addfeature(data,feature,specifications) end end end - rulehash.n=rulesize end return coverage end @@ -29897,8 +30019,11 @@ local function addfeature(data,feature,specifications) order=featureorder, [stepkey]=steps, nofsteps=nofsteps, - type=types[featuretype], + type=specification.handler or types[featuretype], } + if prepareonly then + return sequence + end end end if sequence then @@ -29969,10 +30094,10 @@ end otf.enhancers.enhance=enhance otf.enhancers.register("check extra features",enhance) -end --- [luaotfload, fontloader-2022-02-24.lua scope for “font-otc”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “font-otc”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “font-onr” 6d161533f3437435e12a0ad64866df44] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “font-onr” 6d161533f3437435e12a0ad64866df44] --- if not modules then modules={} end modules ['font-onr']={ version=1.001, @@ -30345,10 +30470,10 @@ function readers.getinfo(filename) end end -end --- [luaotfload, fontloader-2022-02-24.lua scope for “font-onr”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “font-onr”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “font-one” bd39d42055a44ca2002f8ddbbbbf27c3] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “font-one” bd39d42055a44ca2002f8ddbbbbf27c3] --- if not modules then modules={} end modules ['font-one']={ version=1.001, @@ -31063,10 +31188,10 @@ registerafmenhancer("normalize features",enhance_normalize_features) registerafmenhancer("check extra features",otfenhancers.enhance) registerafmenhancer("fix names",enhance_fix_names) -end --- [luaotfload, fontloader-2022-02-24.lua scope for “font-one”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “font-one”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “font-afk” 9da14e0fb22129c053acc599d1312544] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “font-afk” 9da14e0fb22129c053acc599d1312544] --- if not modules then modules={} end modules ['font-afk']={ version=1.001, @@ -31233,10 +31358,10 @@ fonts.handlers.afm.helpdata={ } } -end --- [luaotfload, fontloader-2022-02-24.lua scope for “font-afk”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “font-afk”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “fonts-tfm” f0eb5e2a8068b17ad401bb7efdba1630] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “fonts-tfm” f0eb5e2a8068b17ad401bb7efdba1630] --- if not modules then modules={} end modules ['luatex-fonts-tfm']={ version=1.001, @@ -31751,10 +31876,10 @@ registertfmfeature { } } -end --- [luaotfload, fontloader-2022-02-24.lua scope for “fonts-tfm”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “fonts-tfm”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “font-lua” 1fbfdf7b689b2bdfd0e3bb9bf74ce136] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “font-lua” 1fbfdf7b689b2bdfd0e3bb9bf74ce136] --- if not modules then modules={} end modules ['font-lua']={ version=1.001, @@ -31794,10 +31919,10 @@ function readers.lua(specification) return check_lua(specification,fullname) end -end --- [luaotfload, fontloader-2022-02-24.lua scope for “font-lua”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “font-lua”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “font-def” b9d908c2338b7dc443ce9d1e9fcb7139] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “font-def” b9d908c2338b7dc443ce9d1e9fcb7139] --- if not modules then modules={} end modules ['font-def']={ version=1.001, @@ -32197,10 +32322,10 @@ if not context then callbacks.register('define_font',definers.read,"definition of fonts (tfmdata preparation)") end -end --- [luaotfload, fontloader-2022-02-24.lua scope for “font-def”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “font-def”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “font-shp” a40862fe382d26c1f3753431254bcfdd] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “font-shp” a40862fe382d26c1f3753431254bcfdd] --- if not modules then modules={} end modules ['font-shp']={ version=1.001, @@ -32565,10 +32690,10 @@ callback.register("glyph_stream_provider",function(id,index,mode) return "" end) -end --- [luaotfload, fontloader-2022-02-24.lua scope for “font-shp”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “font-shp”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “fonts-def” f435e0875f203f343157baeff876ec9c] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “fonts-def” f435e0875f203f343157baeff876ec9c] --- if not modules then modules={} end modules ['luatex-fonts-def']={ version=1.001, @@ -32649,10 +32774,10 @@ function fonts.definers.applypostprocessors(tfmdata) return tfmdata end -end --- [luaotfload, fontloader-2022-02-24.lua scope for “fonts-def”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “fonts-def”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “fonts-ext” 32013cbc5d5d336be8b1d1e5879d86c4] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “fonts-ext” 32013cbc5d5d336be8b1d1e5879d86c4] --- if not modules then modules={} end modules ['luatex-fonts-ext']={ version=1.001, @@ -32838,10 +32963,10 @@ registerotffeature { } } -end --- [luaotfload, fontloader-2022-02-24.lua scope for “fonts-ext”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “fonts-ext”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “font-imp-tex” ceb087ef6fa2f89aed7179f60ddf8f35] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “font-imp-tex” ceb087ef6fa2f89aed7179f60ddf8f35] --- if not modules then modules={} end modules ['font-imp-tex']={ version=1.001, @@ -32940,10 +33065,10 @@ registerotffeature { description="arabic digits", } -end --- [luaotfload, fontloader-2022-02-24.lua scope for “font-imp-tex”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “font-imp-tex”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “font-imp-ligatures” 26ffcf089391445f7af59536c8814364] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “font-imp-ligatures” 250f6f4488ee770c23177afb2ff75676] --- if not modules then modules={} end modules ['font-imp-ligatures']={ version=1.001, @@ -33038,12 +33163,12 @@ local function blockligatures(str) before=before, current={ one,two }, after=after, - lookups={ 1 }, + lookups={ 1,false }, } revert[new]={ current={ one,zwj }, after={ two }, - lookups={ 1 }, + lookups={ 1,false }, } end end @@ -33057,10 +33182,10 @@ if context then } end -end --- [luaotfload, fontloader-2022-02-24.lua scope for “font-imp-ligatures”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “font-imp-ligatures”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “font-imp-italics” defcb415bc1e0a0999b27773902adc18] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “font-imp-italics” defcb415bc1e0a0999b27773902adc18] --- if not modules then modules={} end modules ['font-imp-italics']={ version=1.001, @@ -33164,10 +33289,10 @@ if context then registerafmfeature(dimensions_specification) end -end --- [luaotfload, fontloader-2022-02-24.lua scope for “font-imp-italics”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “font-imp-italics”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “font-imp-effects” d05997c1826355548ec9aec1346f9f23] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “font-imp-effects” d05997c1826355548ec9aec1346f9f23] --- if not modules then modules={} end modules ['font-imp-effects']={ version=1.001, @@ -33524,10 +33649,10 @@ local specification={ registerotffeature(specification) registerafmfeature(specification) -end --- [luaotfload, fontloader-2022-02-24.lua scope for “font-imp-effects”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “font-imp-effects”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “fonts-lig” fbd251eea3810a43a8d5542319361d68] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “fonts-lig” fbd251eea3810a43a8d5542319361d68] --- fonts.handlers.otf.addfeature { @@ -35596,10 +35721,10 @@ fonts.handlers.otf.addfeature { ["type"]="ligature", } -end --- [luaotfload, fontloader-2022-02-24.lua scope for “fonts-lig”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “fonts-lig”] --- -do --- [luaotfload, fontloader-2022-02-24.lua scope for “fonts-gbn” 34e4543a02f6fbc8c2ade896cb6dc7df] --- +do --- [luaotfload, fontloader-2022-06-15.lua scope for “fonts-gbn” 34e4543a02f6fbc8c2ade896cb6dc7df] --- if not modules then modules={} end modules ['luatex-fonts-gbn']={ version=1.001, @@ -35864,7 +35989,7 @@ function nodes.simple_font_handler(head,groupcode,size,packtype,direction) return head end -end --- [luaotfload, fontloader-2022-02-24.lua scope for “fonts-gbn”] --- +end --- [luaotfload, fontloader-2022-06-15.lua scope for “fonts-gbn”] --- --- vim:ft=lua:sw=2:ts=8:et:tw=79 diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-dsp.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-dsp.lua index 7028f7c0877..d0367832846 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-dsp.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-dsp.lua @@ -2515,7 +2515,7 @@ do local scriptoffset = tableoffset + readushort(f) local featureoffset = tableoffset + readushort(f) local lookupoffset = tableoffset + readushort(f) - local variationsoffset = version > 0x00010000 and (tableoffset + readulong(f)) or 0 + local variationsoffset = version > 0x00010000 and readulong(f) or 0 if not scriptoffset then return end @@ -2541,7 +2541,7 @@ do end -- if variationsoffset > 0 then - loadvariations(f,fontdata,variationsoffset,lookuptypes,featurehash,featureorder) + loadvariations(f,fontdata,tableoffset + variationsoffset,lookuptypes,featurehash,featureorder) end end end @@ -3820,6 +3820,7 @@ function readers.hvar(f,fontdata,specification) local variations = { } local innerindex = { } -- size is mapcount local outerindex = { } -- size is mapcount + local deltas = { } if variationoffset > 0 then regions, deltas = readvariationdata(f,variationoffset,factors) diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-imp-ligatures.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-imp-ligatures.lua index 091eb5d4b45..02833707ba2 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-imp-ligatures.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-imp-ligatures.lua @@ -104,14 +104,14 @@ local function blockligatures(str) before = before, current = { one, two }, after = after, - lookups = { 1 }, -- not shared ! + lookups = { 1, false }, -- not shared ! } revert[new] = { -- before = before, current = { one, zwj }, -- after = { two, unpack(after) }, after = { two }, - lookups = { 1 }, -- not shared ! + lookups = { 1, false }, -- not shared ! } end end diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-map.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-map.lua index c983ea96343..4aa937ed162 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-map.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-map.lua @@ -253,9 +253,9 @@ function mappings.addtounicode(data,filename,checklookups,forceligatures) local usedmap = cidinfo and fonts.cid.getmap(cidinfo) local uparser = makenameparser() -- hm, every time? if usedmap then - oparser = usedmap and makenameparser(cidinfo.ordering) - cidnames = usedmap.names - cidcodes = usedmap.unicodes + oparser = usedmap and makenameparser(cidinfo.ordering) + cidnames = usedmap.names + cidcodes = usedmap.unicodes end local ns = 0 local nl = 0 diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-osd.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-osd.lua index 34c04729039..d169faf64dd 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-osd.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-osd.lua @@ -6,6 +6,16 @@ if not modules then modules = { } end modules ['font-osd'] = { -- script devanag license = "see context related readme files" } +local experiment1 = false +local experiment2 = false +local experiment2b1 = false +local experiment2b2 = false + +experiments.register("fonts.indic.experiment1", function(v) experiment1 = v end) +experiments.register("fonts.indic.experiment2", function(v) experiment2 = v end) +experiments.register("fonts.indic.experiment2b1", function(v) experiment2b1 = v end) +experiments.register("fonts.indic.experiment2b2", function(v) experiment2b2 = v end) + -- we need to check nbsphash (context only) -- A few remarks: @@ -1382,13 +1392,16 @@ local function reorder_one(head,start,stop,font,attr,nbspaces) end if reph or vattu then +-- print(">>> has reph or vattu") local current = start local cns = nil local done = false while current ~= stop do +-- print("\t>>> current ~= stop yet") local c = current local n = getnext(current) if ra[getchar(current)] and halant[getchar(n)] then +-- print("\t\t>>> current ra; next halant") c = n n = getnext(n) local b, bn = base, base @@ -1402,6 +1415,7 @@ local function reorder_one(head,start,stop,font,attr,nbspaces) if getstate(current,s_rphf) then -- position Reph (Ra + H) after post-base 'matra' (if any) since these -- become marks on the 'matra', not on the base glyph +-- print("\t\t\t>>> ra + halant form → reph") if b ~= current then if current == start then if head == start then @@ -1421,6 +1435,7 @@ local function reorder_one(head,start,stop,font,attr,nbspaces) end elseif cns and getnext(cns) ~= current then -- todo: optimize next -- position below-base Ra (vattu) following the consonants on which it is placed (either the base consonant or one of the pre-base consonants) +-- print("\t\t\t>>> ra below base (vattu) → rkrf") local cp = getprev(current) local cnsn = getnext(cns) setlink(cp,n) @@ -1434,14 +1449,17 @@ local function reorder_one(head,start,stop,font,attr,nbspaces) current = getprev(n) end else +-- print("\t\t>>> NOT! current ra; next halant") local char = getchar(current) if consonant[char] then +-- print("\t\t\t>>> is consonant") cns = current local next = getnext(cns) if halant[getchar(next)] then cns = next end if not vatucache[char] then +-- print("\t\t\t\t>>> is in vatucache") next = getnext(cns) while dependent_vowel[getchar(next)] do cns = next @@ -1449,6 +1467,7 @@ local function reorder_one(head,start,stop,font,attr,nbspaces) end end elseif char == c_nbsp then +-- print("\t\t\t>>> is nbsp") nbspaces = nbspaces + 1 cns = current local next = getnext(cns) @@ -1917,6 +1936,8 @@ local function reorder_two(head,start,stop,font,attr,nbspaces) -- maybe do a pas reorderreph.coverage = { } -- use local rephbase[font] = { } -- use local +-- print("!!!!!! reorder two ") + for i=1,#seqsubset do -- this can be done more efficient, the last test and less getnext @@ -2104,6 +2125,7 @@ local function reorder_two(head,start,stop,font,attr,nbspaces) -- maybe do a pas end end else -- not Stand Alone cluster +-- print("!!!! not standalone cluster") local last = getnext(stop) while current ~= last do -- find base consonant local next = getnext(current) @@ -2173,7 +2195,10 @@ local function reorder_two(head,start,stop,font,attr,nbspaces) -- maybe do a pas end end -- - if not moved[current] and dependent_vowel[char] then +-- print("char: " .. char) +-- if not moved[current] and dependent_vowel[char] then + if dependent_vowel[char] then +-- print(">>!! dependent vowel") if pre_mark[char] then -- or: if before_main or before_half moved[current] = true -- can be helper to remove one node @@ -2384,8 +2409,8 @@ local function analyze_next_chars_one(c,font,variant) -- skip one dependent vowe if not n then return c end + local v = ischar(n,font) if variant == 1 then - local v = ischar(n,font) if v and nukta[v] then n = getnext(n) if n then @@ -2418,7 +2443,6 @@ local function analyze_next_chars_one(c,font,variant) -- skip one dependent vowe end end elseif variant == 2 then - local v = ischar(n,font) if v and nukta[v] then c = n end @@ -2443,11 +2467,11 @@ local function analyze_next_chars_one(c,font,variant) -- skip one dependent vowe end end -- c = ms_matra(c) - local n = getnext(c) + n = getnext(c) if not n then return c end - local v = ischar(n,font) + v = ischar(n,font) if not v then return c end @@ -2555,13 +2579,22 @@ local function analyze_next_chars_one(c,font,variant) -- skip one dependent vowe end end +-- Consonant syllable: +-- +-- { C + [ N ] + < H + [ < ZWNJ | ZWJ > ] | < ZWNJ | ZWJ > + H > } +-- + C +-- + [ N ] +-- + [ A ] +-- + [ < H + [ < ZWNJ|ZWJ > ] | { M } + [ N ] + [ H ] > ] +-- + [ SM ] +-- + [ ( VD ) ] + local function analyze_next_chars_two(c,font) - local n, v - n = getnext(c) + local n = getnext(c) if not n then return c end - v = ischar(n,font) + local v = ischar(n,font) if v and nukta[v] then c = n end @@ -2677,6 +2710,10 @@ local function analyze_next_chars_two(c,font) for k=1,#vowels do local v = vowels[k] if pre_mark[v] and not already_pre_mark then +-- print(">>> pre_mark") +-- if dependent_vowel[v] then +-- print(">>>> dependent vowel") +-- end already_pre_mark = true elseif above_mark[v] and not already_above_mark then already_above_mark = true @@ -3031,12 +3068,15 @@ local function method_two(head,font,attr) end end if independent_vowel[char] then +-- print("!!>>> independent_vowel") -- vowel-based syllable: [Ra+H]+V+[N]+[<[<ZWJ|ZWNJ>]+H+C|ZWJ+C>]+[{M}+[N]+[H]]+[SM]+[(VD)] current = analyze_next_chars_one(c,font,1) syllableend = current else +-- print("!!>>> dependent vowel") local standalone = char == c_nbsp if standalone then +-- print("!!>>> standalone") nbspaces = nbspaces + 1 local p = getprev(current) if not p then @@ -3050,10 +3090,12 @@ local function method_two(head,font,attr) end end if standalone then +-- print("!!>>>>>>> next standalone") -- Stand Alone cluster (at the start of the word only): #[Ra+H]+NBSP+[N]+[<[<ZWJ|ZWNJ>]+H+C>]+[{M}+[N]+[H]]+[SM]+[(VD)] current = analyze_next_chars_one(c,font,2) syllableend = current elseif consonant[getchar(current)] then +-- print("!!>>>>>>> a consonant") -- WHY current INSTEAD OF c ? -- Consonant syllable: {C+[N]+<H+[<ZWNJ|ZWJ>]|<ZWNJ|ZWJ>+H>} + C+[N]+[A] + [< H+[<ZWNJ|ZWJ>] | {M}+[N]+[H]>]+[SM]+[(VD)] current = analyze_next_chars_two(current,font) -- not c ! @@ -3062,6 +3104,7 @@ local function method_two(head,font,attr) end end if syllableend then +-- print("!!!>>> syllable end") syllabe = syllabe + 1 local c = syllablestart local n = getnext(syllableend) diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otc.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otc.lua index 2c955dbce90..67b77b11134 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otc.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otc.lua @@ -130,7 +130,7 @@ local function validspecification(specification,name) end end -local function addfeature(data,feature,specifications) +local function addfeature(data,feature,specifications,prepareonly) -- todo: add some validator / check code so that we're more tolerant to -- user errors @@ -226,6 +226,9 @@ local function addfeature(data,feature,specifications) local stepkey = coverup.stepkey local register = coverup.register + -- todo: directly pass a coverage i.e. for privates that later will be + -- set + local function prepare_substitution(list,featuretype,nocheck) local coverage = { } local cover = coveractions[featuretype] @@ -461,13 +464,13 @@ local function addfeature(data,feature,specifications) return false end + -- 0 == remove, false = ignore (remove is default) + local function prepare_chain(list,featuretype,sublookups,nocheck) -- todo: coveractions local rules = list.rules local coverage = { } if rules then - local rulehash = { } - local rulesize = 0 local lookuptype = types[featuretype] for nofrules=1,#rules do local rule = rules[nofrules] @@ -498,6 +501,15 @@ local function addfeature(data,feature,specifications) local lookups = rule.lookups or false local subtype = nil if lookups and sublookups then + -- inspect(lookups) + if #lookups > 0 then + local ns = stop - start + 1 + for i=1,ns do + if lookups[i] == nil then + lookups[i] = 0 + end + end + end local l = { } for k, v in sortedhash(lookups) do local t = type(v) @@ -535,6 +547,7 @@ local function addfeature(data,feature,specifications) if nofsequences > 0 then -- we merge coverage into one -- we copy as we can have different fonts if hassteps(lookups) then + -- sequence is the before|current|after match list local hashed = { } for i=1,nofsequences do local t = { } @@ -547,9 +560,9 @@ local function addfeature(data,feature,specifications) end hashed[i] = t end + -- hashed is the before|current|after match hash sequence = hashed - rulesize = rulesize + 1 - rulehash[rulesize] = { + local ruleset = { nofrules, -- 1 lookuptype, -- 2 sequence, -- 3 @@ -561,8 +574,15 @@ local function addfeature(data,feature,specifications) } for unic in sortedhash(sequence[start]) do local cu = coverage[unic] - if not cu then - coverage[unic] = rulehash -- can now be done cleaner i think + if cu then + local n = cu.n + 1 + cu[n] = ruleset + cu.n = n + else + coverage[unic] = { + ruleset, + n = 1, + } end end sequence.n = nofsequences @@ -571,7 +591,6 @@ local function addfeature(data,feature,specifications) end end end - rulehash.n = rulesize end return coverage end @@ -811,8 +830,11 @@ local function addfeature(data,feature,specifications) order = featureorder, [stepkey] = steps, nofsteps = nofsteps, - type = types[featuretype], + type = specification.handler or types[featuretype], } + if prepareonly then + return sequence + end end end @@ -900,6 +922,23 @@ local function enhance(data,filename,raw) end end +-- local function enhance(data,filename,raw) +-- local first = 1 +-- local last = #extrafeatures +-- while true do +-- for slot=first,last do +-- local specification = extrafeatures[slot] +-- addfeature(data,specification.name,specification) +-- end +-- if #extrafeatures > last then +-- first = last + 1 +-- last = #extrafeatures +-- else +-- break +-- end +-- end +-- end + otf.enhancers.enhance = enhance otf.enhancers.register("check extra features",enhance) diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otl.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otl.lua index ae2dda4f396..f36e533ca09 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otl.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otl.lua @@ -52,7 +52,7 @@ local report_otf = logs.reporter("fonts","otf loading") local fonts = fonts local otf = fonts.handlers.otf -otf.version = 3.119 -- beware: also sync font-mis.lua and in mtx-fonts +otf.version = 3.120 -- beware: also sync font-mis.lua and in mtx-fonts otf.cache = containers.define("fonts", "otl", otf.version, true) otf.svgcache = containers.define("fonts", "svg", otf.version, true) otf.pngcache = containers.define("fonts", "png", otf.version, true) diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otr.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otr.lua index 286367ed9ea..339de109f80 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otr.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otr.lua @@ -2499,15 +2499,15 @@ function readers.getinfo(filename,specification) -- string, nil|number|table end end -function readers.rehash(fontdata,hashmethod) +function readers.rehash() -- fontdata,hashmethod report("the %a helper is not yet implemented","rehash") end -function readers.checkhash(fontdata) +function readers.checkhash() --fontdata report("the %a helper is not yet implemented","checkhash") end -function readers.pack(fontdata,hashmethod) +function readers.pack() -- fontdata,hashmethod report("the %a helper is not yet implemented","pack") end diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-oup.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-oup.lua index 3bd2fe48288..248aad04d2a 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-oup.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-oup.lua @@ -10,6 +10,7 @@ local next, type = next, type local P, R, S = lpeg.P, lpeg.R, lpeg.S local lpegmatch = lpeg.match local insert, remove, copy, unpack = table.insert, table.remove, table.copy, table.unpack +local find = string.find local formatters = string.formatters local sortedkeys = table.sortedkeys @@ -944,15 +945,18 @@ local function unifyglyphs(fontdata,usenames) return indices, names end -local p_crappyname do +local stripredundant do + local p_hex = R("af","AF","09") local p_digit = R("09") local p_done = S("._-")^0 + P(-1) + -- local p_style = P(".ss") * p_digit * p_digit * P(-1) + local p_style = P(".") local p_alpha = R("az","AZ") local p_ALPHA = R("AZ") - p_crappyname = ( + local p_crappyname = ( -- (P("uni") + P("UNI") + P("Uni") + P("U") + P("u")) lpeg.utfchartabletopattern({ "uni", "u" },true) * S("Xx_")^0 @@ -980,56 +984,182 @@ local p_crappyname do * P(1)^1 ) * p_done -end + -- In context we only keep glyph names because of tracing and access by name + -- so weird names make no sense. --- In context we only keep glyph names because of tracing and access by name --- so weird names make no sense. + if context then -local forcekeep = false -- only for testing something + local forcekeep = false -- only for testing something +-- local forcekeep = true -directives.register("otf.keepnames",function(v) - report_cleanup("keeping weird glyph names, expect larger files and more memory usage") - forcekeep = v -end) + directives.register("otf.keepnames",function(v) + report_cleanup("keeping weird glyph names, expect larger files and more memory usage") + forcekeep = v + end) -local function stripredundant(fontdata) - local descriptions = fontdata.descriptions - if descriptions then - local n = 0 - local c = 0 - -- in context we always strip - if (not context and fonts.privateoffsets.keepnames) or forcekeep then - for unicode, d in next, descriptions do - if d.class == "base" then - d.class = nil - c = c + 1 + -- local p_lesscrappyname = + -- lpeg.utfchartabletopattern({ "uni", "u" },true) + -- * S("Xx")^0 + -- * p_hex^1 + -- * p_style + + local function stripvariants(descriptions,list) + local n = list and #list or 0 + if n > 0 then + for i=1,n do + local g = list[i] + if g then + local d = descriptions[g] + if d and d.name then + d.name = nil + n = n + 1 + end + end end end - else - for unicode, d in next, descriptions do - local name = d.name - if name and lpegmatch(p_crappyname,name) then - d.name = nil - n = n + 1 + return n + end + + local function stripparts(descriptions,list) + local n = list and #list or 0 + if n > 0 then + for i=1,n do + local g = list[i].glyph + if g then + local d = descriptions[g] + if d and d.name then + d.name = nil + n = n + 1 + end + end end - if d.class == "base" then - d.class = nil - c = c + 1 + end + return n + end + + -- local function collectsimple(fontdata) + -- local resources = fontdata.resources + -- local sequences = resources and resources.sequences + -- if sequences then + -- local keeplist = { } + -- for i=1,#sequences do + -- local s = sequences[i] + -- if s.type == "gsub_single" then + -- -- only simple ones + -- local features = s.features + -- local steps = s.steps + -- if features and steps then + -- local okay = false + -- for k, v in next, features do + -- if find(k,"^ss%d%d") then + -- okay = true + -- break + -- end + -- end + -- if okay then + -- for i=1,#steps do + -- local coverage = steps[i].coverage + -- if coverage then + -- for k, v in next, coverage do + -- keeplist[k] = v + -- end + -- end + -- end + -- end + -- end + -- end + -- end + -- return next(keeplist) and keeplist or nil + -- end + -- end + + local function collectsimple(fontdata) + return nil + end + + stripredundant = function(fontdata) + local descriptions = fontdata.descriptions + if descriptions then + local n = 0 + local c = 0 + for unicode, d in next, descriptions do + local m = d.math + if m then + n = n + stripvariants(descriptions,m.vvariants) + n = n + stripvariants(descriptions,m.hvariants) + n = n + stripparts (descriptions,m.vparts) + n = n + stripparts (descriptions,m.hparts) + end + end + if forcekeep then + for unicode, d in next, descriptions do + if d.class == "base" then + d.class = nil + c = c + 1 + end + end + else + local keeplist = collectsimple(fontdata) + for unicode, d in next, descriptions do + local name = d.name + if name then + -- if lpegmatch(p_lesscrappyname,name) then + if keeplist and keeplist[name] then + -- keep name + elseif lpegmatch(p_crappyname,name) then + d.name = nil + n = n + 1 + end + end + if d.class == "base" then + d.class = nil + c = c + 1 + end + end + end + if trace_cleanup then + if n > 0 then + report_cleanup("%s bogus names removed (verbose unicode)",n) + end + if c > 0 then + report_cleanup("%s base class tags removed (default is base)",c) + end end end end - if trace_cleanup then - if n > 0 then - report_cleanup("%s bogus names removed (verbose unicode)",n) - end - if c > 0 then - report_cleanup("%s base class tags removed (default is base)",c) + + else + + stripredundant = function(fontdata) + local descriptions = fontdata.descriptions + if descriptions then + if fonts.privateoffsets.keepnames then + for unicode, d in next, descriptions do + if d.class == "base" then + d.class = nil + end + end + else + for unicode, d in next, descriptions do + local name = d.name + if name then + if lpegmatch(p_crappyname,name) then + d.name = nil + end + end + if d.class == "base" then + d.class = nil + end + end + end end end + end -end -readers.stripredundant = stripredundant + readers.stripredundant = stripredundant + +end function readers.getcomponents(fontdata) -- handy for resolving ligatures when names are missing local resources = fontdata.resources @@ -1128,8 +1258,7 @@ readers.unifymissing = unifymissing function readers.rehash(fontdata,hashmethod) -- TODO: combine loops in one if not (fontdata and fontdata.glyphs) then return - end - if hashmethod == "indices" then + elseif hashmethod == "indices" then fontdata.hashmethod = "indices" elseif hashmethod == "names" then fontdata.hashmethod = "names" @@ -1137,7 +1266,6 @@ function readers.rehash(fontdata,hashmethod) -- TODO: combine loops in one unifyresources(fontdata,indices) copyduplicates(fontdata) unifymissing(fontdata) - -- stripredundant(fontdata) else fontdata.hashmethod = "unicodes" local indices = unifyglyphs(fontdata) diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-ttf.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-ttf.lua index a2658d595ab..d1a3972b2c4 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-ttf.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-ttf.lua @@ -247,115 +247,148 @@ local function applyaxis(glyph,shape,deltas,dowidth) -- Not the most efficient solution but we seldom do this. We -- actually need to avoid the extra points here but I'll deal -- with that when needed. - local function find(i) - local prv = cnt - for j=1,cnt do - local nxt = dpoints[j] - if nxt == i then - return false, j, false - elseif nxt > i then - return prv, false, j - end - prv = j - end - return prv, false, 1 - end - -- We need the first and last points untouched so we first - -- collect data. - for i=1,nofpoints do - local d1, d2, d3 = find(i) - local p2 = points[i] - if d2 then - xv[i] = xvalues[d2] - yv[i] = yvalues[d2] - else - local n1 = dpoints[d1] - local n3 = dpoints[d3] - -- Some day I need to figure out these extra points but - -- I'll wait till the standard is more clear and fonts - -- become better (ntg-context: fraunces.ttf > abcdef). - if n1 > nofpoints then - n1 = nofpoints - end - if n3 > nofpoints then - n3 = nofpoints - end - -- - local p1 = points[n1] - local p3 = points[n3] - local p1x = p1[1] - local p2x = p2[1] - local p3x = p3[1] - local p1y = p1[2] - local p2y = p2[2] - local p3y = p3[2] - local x1 = xvalues[d1] - local y1 = yvalues[d1] - local x3 = xvalues[d3] - local y3 = yvalues[d3] - -- - local fx - local fy - -- - if p1x == p3x then - if x1 == x3 then - fx = x1 - else - fx = 0 - end - elseif p2x <= min(p1x,p3x) then - if p1x < p3x then - fx = x1 - else - fx = x3 - end - elseif p2x >= max(p1x,p3x) then - if p1x > p3x then - fx = x1 - else - fx = x3 + local contours = shape.contours + local nofcontours = #contours + local first = 1 + local firstindex = 1 + for contour=1,nofcontours do + local last = contours[contour] + if last >= first then + local lastindex = cnt + if firstindex < cnt then + for currentindex=firstindex,cnt do + local found = dpoints[currentindex] + if found <= first then + firstindex = currentindex + end + if found == last then + lastindex = currentindex + break; + elseif found > last then + break + end end - else - fx = (p2x - p1x)/(p3x - p1x) - fx = (1 - fx) * x1 + fx * x3 end - -- - if p1y == p3y then - if y1 == y3 then - fy = y1 - else - fy = 0 - end - elseif p2y <= min(p1y,p3y) then - if p1y < p3y then - fy = y1 - else - fy = y3 + -- print("unicode: ",glyph.unicode or "?") + -- print("contour: ",first,contour,last) + -- print("index : ",firstindex,lastindex,cnt) + -- print("points : ",dpoints[firstindex],dpoints[lastindex]) + local function find(i) + local prv = lastindex + for j=firstindex,lastindex do + local nxt = dpoints[j] + if nxt == i then + return false, j, false + elseif nxt > i then + return prv, false, j + end + prv = j end - elseif p2y >= max(p1y,p3y) then - if p1y > p3y then - fy = y1 + return prv, false, firstindex + end + -- We need the first and last points untouched so we first + -- collect data. + for point=first,last do + local d1, d2, d3 = find(point) + local p2 = points[point] + if d2 then + xv[point] = xvalues[d2] + yv[point] = yvalues[d2] else - fy = y3 + local n1 = dpoints[d1] + local n3 = dpoints[d3] + -- Some day I need to figure out these extra points but + -- I'll wait till the standard is more clear and fonts + -- become better (ntg-context: fraunces.ttf > abcdef). + if n1 > nofpoints then + n1 = nofpoints + end + if n3 > nofpoints then + n3 = nofpoints + end + -- + local p1 = points[n1] + local p3 = points[n3] + local p1x = p1[1] + local p2x = p2[1] + local p3x = p3[1] + local p1y = p1[2] + local p2y = p2[2] + local p3y = p3[2] + local x1 = xvalues[d1] + local y1 = yvalues[d1] + local x3 = xvalues[d3] + local y3 = yvalues[d3] + -- + local fx + local fy + -- + if p1x == p3x then + if x1 == x3 then + fx = x1 + else + fx = 0 + end + elseif p2x <= min(p1x,p3x) then + if p1x < p3x then + fx = x1 + else + fx = x3 + end + elseif p2x >= max(p1x,p3x) then + if p1x > p3x then + fx = x1 + else + fx = x3 + end + else + fx = (p2x - p1x)/(p3x - p1x) + fx = (1 - fx) * x1 + fx * x3 + end + -- + if p1y == p3y then + if y1 == y3 then + fy = y1 + else + fy = 0 + end + elseif p2y <= min(p1y,p3y) then + if p1y < p3y then + fy = y1 + else + fy = y3 + end + elseif p2y >= max(p1y,p3y) then + if p1y > p3y then + fy = y1 + else + fy = y3 + end + else + fy = (p2y - p1y)/(p3y - p1y) + fy = (1 - fy) * y1 + fy * y3 + end + -- -- maybe: + -- if p1y ~= p3y then + -- fy = (p2y - p1y)/(p3y - p1y) + -- fy = (1 - fy) * y1 + fy * y3 + -- elseif abs(p1y-p2y) < abs(p3y-p2y) then + -- fy = y1 + -- else + -- fy = y3 + -- end + -- + xv[point] = fx + yv[point] = fy end - else - fy = (p2y - p1y)/(p3y - p1y) - fy = (1 - fy) * y1 + fy * y3 end - -- -- maybe: - -- if p1y ~= p3y then - -- fy = (p2y - p1y)/(p3y - p1y) - -- fy = (1 - fy) * y1 + fy * y3 - -- elseif abs(p1y-p2y) < abs(p3y-p2y) then - -- fy = y1 - -- else - -- fy = y3 - -- end - -- - xv[i] = fx - yv[i] = fy + if lastindex < cnt then + firstindex = lastindex + 1 + end end + first = last + 1 end + for i=1,nofpoints do local pi = points[i] local fx = xv[i] diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-reference.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-reference.lua index 736856d2beb..13389b292ad 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-reference.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/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 : 2022-01-21 20:10 +-- merge date : 2022-05-11 11:34 do -- begin closure to overcome local limits and interference @@ -10902,9 +10902,9 @@ function mappings.addtounicode(data,filename,checklookups,forceligatures) local usedmap=cidinfo and fonts.cid.getmap(cidinfo) local uparser=makenameparser() if usedmap then - oparser=usedmap and makenameparser(cidinfo.ordering) - cidnames=usedmap.names - cidcodes=usedmap.unicodes + oparser=usedmap and makenameparser(cidinfo.ordering) + cidnames=usedmap.names + cidcodes=usedmap.unicodes end local ns=0 local nl=0 @@ -13108,13 +13108,13 @@ function readers.getinfo(filename,specification) } end end -function readers.rehash(fontdata,hashmethod) +function readers.rehash() report("the %a helper is not yet implemented","rehash") end -function readers.checkhash(fontdata) +function readers.checkhash() report("the %a helper is not yet implemented","checkhash") end -function readers.pack(fontdata,hashmethod) +function readers.pack() report("the %a helper is not yet implemented","pack") end function readers.unpack(fontdata) @@ -15557,95 +15557,123 @@ local function applyaxis(glyph,shape,deltas,dowidth) end end elseif cnt>0 then - local function find(i) - local prv=cnt - for j=1,cnt do - local nxt=dpoints[j] - if nxt==i then - return false,j,false - elseif nxt>i then - return prv,false,j - end - prv=j - end - return prv,false,1 - end - for i=1,nofpoints do - local d1,d2,d3=find(i) - local p2=points[i] - if d2 then - xv[i]=xvalues[d2] - yv[i]=yvalues[d2] - else - local n1=dpoints[d1] - local n3=dpoints[d3] - if n1>nofpoints then - n1=nofpoints - end - if n3>nofpoints then - n3=nofpoints - end - local p1=points[n1] - local p3=points[n3] - local p1x=p1[1] - local p2x=p2[1] - local p3x=p3[1] - local p1y=p1[2] - local p2y=p2[2] - local p3y=p3[2] - local x1=xvalues[d1] - local y1=yvalues[d1] - local x3=xvalues[d3] - local y3=yvalues[d3] - local fx - local fy - if p1x==p3x then - if x1==x3 then - fx=x1 - else - fx=0 - end - elseif p2x<=min(p1x,p3x) then - if p1x<p3x then - fx=x1 - else - fx=x3 - end - elseif p2x>=max(p1x,p3x) then - if p1x>p3x then - fx=x1 - else - fx=x3 + local contours=shape.contours + local nofcontours=#contours + local first=1 + local firstindex=1 + for contour=1,nofcontours do + local last=contours[contour] + if last>=first then + local lastindex=cnt + if firstindex<cnt then + for currentindex=firstindex,cnt do + local found=dpoints[currentindex] + if found<=first then + firstindex=currentindex + end + if found==last then + lastindex=currentindex + break; + elseif found>last then + break + end end - else - fx=(p2x-p1x)/(p3x-p1x) - fx=(1-fx)*x1+fx*x3 end - if p1y==p3y then - if y1==y3 then - fy=y1 - else - fy=0 - end - elseif p2y<=min(p1y,p3y) then - if p1y<p3y then - fy=y1 - else - fy=y3 + local function find(i) + local prv=lastindex + for j=firstindex,lastindex do + local nxt=dpoints[j] + if nxt==i then + return false,j,false + elseif nxt>i then + return prv,false,j + end + prv=j end - elseif p2y>=max(p1y,p3y) then - if p1y>p3y then - fy=y1 + return prv,false,firstindex + end + for point=first,last do + local d1,d2,d3=find(point) + local p2=points[point] + if d2 then + xv[point]=xvalues[d2] + yv[point]=yvalues[d2] else - fy=y3 + local n1=dpoints[d1] + local n3=dpoints[d3] + if n1>nofpoints then + n1=nofpoints + end + if n3>nofpoints then + n3=nofpoints + end + local p1=points[n1] + local p3=points[n3] + local p1x=p1[1] + local p2x=p2[1] + local p3x=p3[1] + local p1y=p1[2] + local p2y=p2[2] + local p3y=p3[2] + local x1=xvalues[d1] + local y1=yvalues[d1] + local x3=xvalues[d3] + local y3=yvalues[d3] + local fx + local fy + if p1x==p3x then + if x1==x3 then + fx=x1 + else + fx=0 + end + elseif p2x<=min(p1x,p3x) then + if p1x<p3x then + fx=x1 + else + fx=x3 + end + elseif p2x>=max(p1x,p3x) then + if p1x>p3x then + fx=x1 + else + fx=x3 + end + else + fx=(p2x-p1x)/(p3x-p1x) + fx=(1-fx)*x1+fx*x3 + end + if p1y==p3y then + if y1==y3 then + fy=y1 + else + fy=0 + end + elseif p2y<=min(p1y,p3y) then + if p1y<p3y then + fy=y1 + else + fy=y3 + end + elseif p2y>=max(p1y,p3y) then + if p1y>p3y then + fy=y1 + else + fy=y3 + end + else + fy=(p2y-p1y)/(p3y-p1y) + fy=(1-fy)*y1+fy*y3 + end + xv[point]=fx + yv[point]=fy end - else - fy=(p2y-p1y)/(p3y-p1y) - fy=(1-fy)*y1+fy*y3 end - xv[i]=fx - yv[i]=fy + if lastindex<cnt then + firstindex=lastindex+1 + end end + first=last+1 end for i=1,nofpoints do local pi=points[i] @@ -19792,6 +19820,7 @@ function readers.hvar(f,fontdata,specification) local variations={} local innerindex={} local outerindex={} + local deltas={} if variationoffset>0 then regions,deltas=readvariationdata(f,variationoffset,factors) end @@ -21181,7 +21210,7 @@ local trace_defining=false registertracker("fonts.defining",function(v) trace_d local report_otf=logs.reporter("fonts","otf loading") local fonts=fonts local otf=fonts.handlers.otf -otf.version=3.119 +otf.version=3.120 otf.cache=containers.define("fonts","otl",otf.version,true) otf.svgcache=containers.define("fonts","svg",otf.version,true) otf.pngcache=containers.define("fonts","png",otf.version,true) @@ -23855,6 +23884,7 @@ local next,type=next,type local P,R,S=lpeg.P,lpeg.R,lpeg.S local lpegmatch=lpeg.match local insert,remove,copy,unpack=table.insert,table.remove,table.copy,table.unpack +local find=string.find local formatters=string.formatters local sortedkeys=table.sortedkeys local sortedhash=table.sortedhash @@ -24713,61 +24743,137 @@ local function unifyglyphs(fontdata,usenames) fontdata.nofglyphs=nofglyphs return indices,names end -local p_crappyname do +local stripredundant do local p_hex=R("af","AF","09") local p_digit=R("09") local p_done=S("._-")^0+P(-1) + local p_style=P(".") local p_alpha=R("az","AZ") local p_ALPHA=R("AZ") - p_crappyname=( + local p_crappyname=( lpeg.utfchartabletopattern({ "uni","u" },true)*S("Xx_")^0*p_hex^1 +lpeg.utfchartabletopattern({ "identity","glyph","jamo" },true)*p_hex^1 +lpeg.utfchartabletopattern({ "index","afii" },true)*p_digit^1 +p_digit*p_hex^3+p_alpha*p_digit^1 +P("aj")*p_digit^1+P("eh_")*(p_digit^1+p_ALPHA*p_digit^1)+(1-P("_"))^1*P("_uni")*p_hex^1+P("_")*P(1)^1 )*p_done -end -local forcekeep=false -directives.register("otf.keepnames",function(v) - report_cleanup("keeping weird glyph names, expect larger files and more memory usage") - forcekeep=v -end) -local function stripredundant(fontdata) - local descriptions=fontdata.descriptions - if descriptions then - local n=0 - local c=0 - if (not context and fonts.privateoffsets.keepnames) or forcekeep then - for unicode,d in next,descriptions do - if d.class=="base" then - d.class=nil - c=c+1 + if context then + local forcekeep=false + directives.register("otf.keepnames",function(v) + report_cleanup("keeping weird glyph names, expect larger files and more memory usage") + forcekeep=v + end) + local function stripvariants(descriptions,list) + local n=list and #list or 0 + if n>0 then + for i=1,n do + local g=list[i] + if g then + local d=descriptions[g] + if d and d.name then + d.name=nil + n=n+1 + end + end end end - else - for unicode,d in next,descriptions do - local name=d.name - if name and lpegmatch(p_crappyname,name) then - d.name=nil - n=n+1 - end - if d.class=="base" then - d.class=nil - c=c+1 + return n + end + local function stripparts(descriptions,list) + local n=list and #list or 0 + if n>0 then + for i=1,n do + local g=list[i].glyph + if g then + local d=descriptions[g] + if d and d.name then + d.name=nil + n=n+1 + end + end end end + return n end - if trace_cleanup then - if n>0 then - report_cleanup("%s bogus names removed (verbose unicode)",n) + local function collectsimple(fontdata) + return nil + end + stripredundant=function(fontdata) + local descriptions=fontdata.descriptions + if descriptions then + local n=0 + local c=0 + for unicode,d in next,descriptions do + local m=d.math + if m then + n=n+stripvariants(descriptions,m.vvariants) + n=n+stripvariants(descriptions,m.hvariants) + n=n+stripparts (descriptions,m.vparts) + n=n+stripparts (descriptions,m.hparts) + end + end + if forcekeep then + for unicode,d in next,descriptions do + if d.class=="base" then + d.class=nil + c=c+1 + end + end + else + local keeplist=collectsimple(fontdata) + for unicode,d in next,descriptions do + local name=d.name + if name then + if keeplist and keeplist[name] then + elseif lpegmatch(p_crappyname,name) then + d.name=nil + n=n+1 + end + end + if d.class=="base" then + d.class=nil + c=c+1 + end + end + end + if trace_cleanup then + if n>0 then + report_cleanup("%s bogus names removed (verbose unicode)",n) + end + if c>0 then + report_cleanup("%s base class tags removed (default is base)",c) + end + end end - if c>0 then - report_cleanup("%s base class tags removed (default is base)",c) + end + else + stripredundant=function(fontdata) + local descriptions=fontdata.descriptions + if descriptions then + if fonts.privateoffsets.keepnames then + for unicode,d in next,descriptions do + if d.class=="base" then + d.class=nil + end + end + else + for unicode,d in next,descriptions do + local name=d.name + if name then + if lpegmatch(p_crappyname,name) then + d.name=nil + end + end + if d.class=="base" then + d.class=nil + end + end + end end end end + readers.stripredundant=stripredundant end -readers.stripredundant=stripredundant function readers.getcomponents(fontdata) local resources=fontdata.resources if resources then @@ -24851,8 +24957,7 @@ readers.unifymissing=unifymissing function readers.rehash(fontdata,hashmethod) if not (fontdata and fontdata.glyphs) then return - end - if hashmethod=="indices" then + elseif hashmethod=="indices" then fontdata.hashmethod="indices" elseif hashmethod=="names" then fontdata.hashmethod="names" @@ -30883,7 +30988,7 @@ local function validspecification(specification,name) return specification,name end end -local function addfeature(data,feature,specifications) +local function addfeature(data,feature,specifications,prepareonly) if not specifications then report_otf("missing specification") return @@ -31182,8 +31287,6 @@ local function addfeature(data,feature,specifications) local rules=list.rules local coverage={} if rules then - local rulehash={} - local rulesize=0 local lookuptype=types[featuretype] for nofrules=1,#rules do local rule=rules[nofrules] @@ -31214,6 +31317,14 @@ local function addfeature(data,feature,specifications) local lookups=rule.lookups or false local subtype=nil if lookups and sublookups then + if #lookups>0 then + local ns=stop-start+1 + for i=1,ns do + if lookups[i]==nil then + lookups[i]=0 + end + end + end local l={} for k,v in sortedhash(lookups) do local t=type(v) @@ -31261,8 +31372,7 @@ local function addfeature(data,feature,specifications) hashed[i]=t end sequence=hashed - rulesize=rulesize+1 - rulehash[rulesize]={ + local ruleset={ nofrules, lookuptype, sequence, @@ -31274,8 +31384,15 @@ local function addfeature(data,feature,specifications) } for unic in sortedhash(sequence[start]) do local cu=coverage[unic] - if not cu then - coverage[unic]=rulehash + if cu then + local n=cu.n+1 + cu[n]=ruleset + cu.n=n + else + coverage[unic]={ + ruleset, + n=1, + } end end sequence.n=nofsequences @@ -31283,7 +31400,6 @@ local function addfeature(data,feature,specifications) end end end - rulehash.n=rulesize end return coverage end @@ -31504,8 +31620,11 @@ local function addfeature(data,feature,specifications) order=featureorder, [stepkey]=steps, nofsteps=nofsteps, - type=types[featuretype], + type=specification.handler or types[featuretype], } + if prepareonly then + return sequence + end end end if sequence then @@ -31587,6 +31706,14 @@ if not modules then modules={} end modules ['font-osd']={ copyright="TAT Zetwerk / PRAGMA ADE / ConTeXt Development Team", license="see context related readme files" } +local experiment1=false +local experiment2=false +local experiment2b1=false +local experiment2b2=false +experiments.register("fonts.indic.experiment1",function(v) experiment1=v end) +experiments.register("fonts.indic.experiment2",function(v) experiment2=v end) +experiments.register("fonts.indic.experiment2b1",function(v) experiment2b1=v end) +experiments.register("fonts.indic.experiment2b2",function(v) experiment2b2=v end) local insert,remove,imerge,copy,tohash=table.insert,table.remove,table.imerge,table.copy,table.tohash local next,type,rawget=next,type,rawget local formatters=string.formatters @@ -33099,7 +33226,7 @@ local function reorder_two(head,start,stop,font,attr,nbspaces) local subpos=nil local postpos=nil reorderreph.coverage={} - rephbase[font]={} + rephbase[font]={} for i=1,#seqsubset do local subset=seqsubset[i] local kind=subset[1] @@ -33276,7 +33403,7 @@ local function reorder_two(head,start,stop,font,attr,nbspaces) logprocess("reorder two, handle nbsp") end end - else + else local last=getnext(stop) while current~=last do local next=getnext(current) @@ -33339,7 +33466,7 @@ local function reorder_two(head,start,stop,font,attr,nbspaces) logprocess("reorder two, handle matra") end end - if not moved[current] and dependent_vowel[char] then + if dependent_vowel[char] then if pre_mark[char] then moved[current]=true local prev,next=getboth(current) @@ -33518,8 +33645,8 @@ local function analyze_next_chars_one(c,font,variant) if not n then return c end + local v=ischar(n,font) if variant==1 then - local v=ischar(n,font) if v and nukta[v] then n=getnext(n) if n then @@ -33552,7 +33679,6 @@ local function analyze_next_chars_one(c,font,variant) end end elseif variant==2 then - local v=ischar(n,font) if v and nukta[v] then c=n end @@ -33576,11 +33702,11 @@ local function analyze_next_chars_one(c,font,variant) end end end - local n=getnext(c) + n=getnext(c) if not n then return c end - local v=ischar(n,font) + v=ischar(n,font) if not v then return c end @@ -33685,12 +33811,11 @@ local function analyze_next_chars_one(c,font,variant) end end local function analyze_next_chars_two(c,font) - local n,v - n=getnext(c) + local n=getnext(c) if not n then return c end - v=ischar(n,font) + local v=ischar(n,font) if v and nukta[v] then c=n end @@ -37702,12 +37827,12 @@ local function blockligatures(str) before=before, current={ one,two }, after=after, - lookups={ 1 }, + lookups={ 1,false }, } revert[new]={ current={ one,zwj }, after={ two }, - lookups={ 1 }, + lookups={ 1,false }, } end end diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-auxiliary.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-auxiliary.lua index b34c56508e2..eb211809020 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-auxiliary.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-auxiliary.lua @@ -6,8 +6,8 @@ assert(luaotfload_module, "This is a part of luaotfload and should not be loaded independently") { name = "luaotfload-auxiliary", - version = "3.21", --TAGVERSION - date = "2022-03-18", --TAGDATE + version = "3.22", --TAGVERSION + date = "2022-06-15", --TAGDATE description = "luaotfload submodule / auxiliary functions", license = "GPL v2.0" } diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-bcp47.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-bcp47.lua new file mode 100644 index 00000000000..03dc65e5bc9 --- /dev/null +++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-bcp47.lua @@ -0,0 +1,85 @@ +-- Suport for parsing BCP47 based language tags into components +local normalize_case, language_tag do + local l = lpeg or require'lpeg' + local function rep(base, num, max) + max = max or num + if num == 1 then + if max == 1 then + return base + else + return base * base^-(max-1) + end + end + return base * rep(base, num - 1, max - 1) + end + local eor = #(l.P'-' + -1) -- End of record + local alpha = l.R('az', 'AZ') + local alphanum = l.R('az', 'AZ', '09') + local digit = l.R'09' + normalize_case = l.Cs( + (alphanum^2/string.lower) + * ( + ('-' * (alphanum/string.upper) * (rep(alphanum, 3)/string.lower)) + + ('-' * alphanum^3/string.lower) + + ('-' * rep(alphanum, 2)/string.upper) + )^0 + * ('-' * alphanum * '-' * l.P(1)^1 / string.lower)^-1 + + alphanum * '-' * l.P(1)^1 / string.lower + ) * -1 + local extlang = l.Cg(rep(alpha, 3), 'extlang') + local language = l.Cg(rep(alpha, 2, 3), 'language') * ('-' * extlang * eor)^-1 + local script = l.Cg(rep(alpha, 4), 'script') + local region = l.Cg(rep(alpha, 2) + rep(digit, 3), 'region') + local variant = l.Cg(rep(alphanum, 5, 8) + digit * rep(alphanum, 3), 'variant') + local singleton = l.R('09', 'aw', 'yz') + local extension = l.Cg(l.C(singleton) * l.Ct(('-' * l.C(rep(alphanum, 2, 8)))^1)) + local privateuse = l.P'x' * l.Cg(l.Ct(('-' * l.C(rep(alphanum, 2, 8)))^1), 'private') + local irregular = + l.P'en-GB-oed' * l.Cc{language = 'en', region = 'GB', variant = 'oxendict'} + + l.P'i-ami' * l.Cc{language = 'ami'} + + l.P'i-bnn' * l.Cc{language = 'bnn'} + + l.P'i-default' * l.Cc{language = 'i-default'} -- Not deprecated + + l.P'i-enochian' * l.Cc{language = 'i-enochian'} -- The non-existance of a non deprecated language code for enochian + -- demonstrates a shocking for the language of my ancestors + + l.P'i-hak' * l.Cc{language = 'hak'} + + l.P'i-klingon' * l.Cc{language = 'tlh'} + + l.P'i-lux' * l.Cc{language = 'lb'} + + l.P'i-mingo' * l.Cc{language = 'i-mingo'} -- Not deprecated + + l.P'i-navajo' * l.Cc{language = 'nv'} + + l.P'i-pwn' * l.Cc{language = 'pwn'} + + l.P'i-tao' * l.Cc{language = 'tao'} + + l.P'i-tay' * l.Cc{language = 'tay'} + + l.P'i-tsu' * l.Cc{language = 'tsu'} + + l.P'sgn-BE-FR' * l.Cc{language = 'sfb'} + + l.P'sgn-BE-NL' * l.Cc{language = 'vgt'} + + l.P'sgn-CH-DE' * l.Cc{language = 'sgg'} + local regular = + l.P'art-lojban' * l.Cc{language = 'jbo'} + + l.P'cel-gaulish' * l.Cc{language = '...'} + + l.P'no-bok' * l.Cc{language = 'nb'} + + l.P'no-nyn' * l.Cc{language = 'nn'} + + l.P'zh-guoyu' * l.Cc{language = 'cmn'} + + l.P'zh-hakka' * l.Cc{language = 'hak'} + + l.P'zh-min' * l.Cc{language = '...'} + + l.P'zh-min-nan' * l.Cc{language = 'nan'} + + l.P'zh-xiang' * l.Cc{language = 'hsn'} + local grandfathered = irregular + regular + local langtag = language * ('-' * script * eor)^-1 + * ('-' * region * eor)^-1 + * ('-' * variant)^0 + * (#('-' * singleton * '-') * l.Cg(l.Cf(l.Ct'' * ('-' * extension)^0, rawset), 'extension'))^-1 + * ('-' * privateuse)^-1 + language_tag = (grandfathered + l.Ct(langtag + privateuse)) * l.Cp()--* -1 +end +local function parse(tag) + tag = normalize_case:match(tag) + if not tag then return end + local parsed, pos = language_tag:match(tag) + print(require'inspect'{parsed, pos}) + -- if not parsed then return parsed end + return tag, parsed +end +for l in io.lines() do + print(parse(l)) + -- io.stdout:write(parse(l), '\n') +end diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-case.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-case.lua index 33bb1bc9246..f5a147334d1 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-case.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-case.lua @@ -21,6 +21,7 @@ local setdisc = direct.setdisc local getdisc = direct.getdisc local getfield = direct.getfield local remove = direct.remove +local free = direct.free local copy = direct.copy local insert_after = direct.insert_after local traverse = direct.traverse @@ -34,41 +35,133 @@ local disc = node.id'disc' -- * Final_Sigma is never language dependent -- * Other contexts are always language dependent -- * The only languages with special mappings are Lithuanian (lt/"LTH "/lit), Turkish (tr/"TRK "/tur), and Azeri/Azerbaijani (az/"AZE "/aze) +-- (Additionally we add special mappings for de-x-eszett, el, el-x-iota, hy-x-yiwn which are not present in SpecialCasing.txt) ]] -local font_lang = setmetatable({}, {__index = function(t, fid) - local f = font.getfont(fid) - local lang = f.specification.features.normal.language - lang = lang == 'lth' and 'lt' or lang == 'trk' and 'tr' or lang == 'aze' and 'az' or false - t[fid] = lang - return lang -end}) +local UPPER_MASK = 0x3FF +local HAS_VOWEL = 0x200000 +local HAS_YPOGEGRAMMENI = 0x400000 +local HAS_ACCENT = 0x800000 +local HAS_DIALYTIKA = 0x1000000 +local HAS_OTHER_GREEK_DIACRITIC = 0x2000000 -local function is_Final_Sigma(font, mapping, n, after) - mapping = mapping.Final_Sigma - if not mapping then return false end - mapping = mapping._ - if not mapping then return false end +local greek_data +local greek_diacritic = { + [0x0300] = HAS_ACCENT, + [0x0301] = HAS_ACCENT, + [0x0342] = HAS_ACCENT, + [0x0302] = HAS_ACCENT, + [0x0303] = HAS_ACCENT, + [0x0311] = HAS_ACCENT, + [0x0308] = HAS_DIALYTIKA, + [0x0344] = HAS_DIALYTIKA | HAS_ACCENT, + [0x0345] = HAS_YPOGEGRAMMENI, + [0x0304] = HAS_OTHER_GREEK_DIACRITIC, + [0x0306] = HAS_OTHER_GREEK_DIACRITIC, + [0x0313] = HAS_OTHER_GREEK_DIACRITIC, + [0x0314] = HAS_OTHER_GREEK_DIACRITIC, + [0x0343] = HAS_OTHER_GREEK_DIACRITIC, +} + +local greek_precombined_iota = { + [0x0391] = 0x1FBC, + [0x0397] = 0x1FCC, + [0x03A9] = 0x1FFC, +} + +-- Greek handling based on https://icu.unicode.org/design/case/greek-upper +-- with smaller variations since we ant to preserve nodes whenever possible. +local function init_greek_data() + local NFD = require'lua-uni-normalize'.NFD + local data = {} + greek_data = data + + local vowels = { + [utf8.codepoint'Α'] = true, [utf8.codepoint'Ε'] = true, + [utf8.codepoint'Η'] = true, [utf8.codepoint'Ι'] = true, + [utf8.codepoint'Ο'] = true, [utf8.codepoint'Ω'] = true, + [utf8.codepoint'Υ'] = true, + } + local function handle_char(c) + local decomp = NFD(utf8.char(c)) + local first = utf8.codepoint(decomp) + local upper = uppercase[first] + if upper then + if not tonumber(upper) then + upper = upper._ + assert(#upper == 1) + upper = upper[1] + end + else + upper = first + end + if upper > UPPER_MASK then return end -- Only happens for unassigned codepoints + local datum = upper + if vowels[upper] then + datum = datum | HAS_VOWEL + end + if utf8.len(decomp) > 1 then + for _, c in utf8.codes(decomp) do + local dia = greek_diacritic[c] + if dia and dia ~= HAS_OTHER_GREEK_DIACRITIC then datum = datum | dia end + end + end + data[c] = datum + end + for c = 0x0370, 0x03ff do handle_char(c) end + for c = 0x1f00, 0x1fff do handle_char(c) end + for c = 0x2126, 0x2126 do handle_char(c) end +end + +local function font_lang(feature) + return setmetatable({}, {__index = function(t, fid) + local f = font.getfont(fid) + local features = f.specification.features.normal + local lang = features[feature] + if type(lang) ~= 'string' or lang == 'auto' then + lang = features.language + lang = lang == 'lth' and 'lt' + or lang == 'trk' and 'tr' + or lang == 'aze' and 'az' + or lang == 'hye' and 'hy' + or (lang == 'ell' or lang == 'pgr') and 'el' + or false + end + t[fid] = lang + return lang + end}) +end + +local function is_followed_by_cased(font, n, after) n = getnext(n) repeat while n do local char, id = is_char(n, font) - if id == disc then + if not char and id == disc then after = getnext(n) n = getfield(n, 'replace') char, id = is_char(n, font) - elseif char then + end + if char then if not case_ignorable[char] then - return not cased[char] and mapping + return cased[char] end n = getnext(n) else - return mapping + return false end end n, after = after until not n - return mapping + return false +end + +local function is_Final_Sigma(font, mapping, n, after) + mapping = mapping.Final_Sigma + if not mapping then return false end + mapping = mapping._ + if not mapping then return false end + return not is_followed_by_cased(font, n, after) and mapping end local function is_More_Above(font, mapping, n, after) @@ -150,56 +243,181 @@ local function is_Language_Mapping(font, mapping, n, after, seen_soft_dotted, se return is_More_Above(font, mapping, n, after) or is_Not_Before_Dot(font, mapping, n, after) or mapping._ -- Might be nil end -local function process(table) - local function processor(head, font, after, seen_cased, seen_soft_dotted, seen_I) +local function process(table, feature) + local font_lang = font_lang(feature) + -- The other seen_... are booleans, while seen_greek has more states: + -- - nil: Not greek + -- - true: Greek. Last was not a vowel with accent and without dialytika + -- - node: Greek. Last vowel with accent and without dialytika + local function processor(head, font, after, seen_cased, seen_soft_dotted, seen_I, seen_greek) local lang = font_lang[font] + local greek, greek_iota + if lang == 'el' or lang == 'el-x-iota' then + if table == uppercase then + if not greek_data then + init_greek_data() + end + greek, greek_iota = greek_data, lang == 'el-x-iota' + end + lang = false + end local n = head while n do do local new = has_glyph(n) if n ~= new then - seen_cased, seen_soft_dotted, seen_I = nil + seen_cased, seen_soft_dotted, seen_I, seen_greek = nil end n = new end if not n then break end local char, id = is_char(n, font) if char then - local mapping = table[char] - if mapping then - if tonumber(mapping) then - setchar(n, mapping) + if greek and (char >= 0x0370 and char <= 0x03ff or char >= 0x1f00 and char <= 0x1fff or char == 0x2126) then + -- In the greek uppercase situation we want to remove diacritics except under some exceptions. + local first_datum = greek[char] or 0 + local datum = first_datum + local upper = datum & UPPER_MASK + -- When a vowel ges an accent removed and does not have a dialytika and is followed by a Ι or Υ, + -- then this iota or ypsilon gets a dialytika. + if datum & HAS_VOWEL ~= 0 and seen_greek and seen_greek ~= true and (upper == 0x0399 or upper == 0x03a5) then + datum = datum | HAS_DIALYTIKA; + end + local has_ypogegrammeni = datum & HAS_YPOGEGRAMMENI ~= 0 + local add_ypogegrammeni = has_ypogegrammeni + local post = getnext(n) + local last + local saved_tonos, saved_dialytika + while post do + local char = is_char(post, font) + if not char then break end + local diacritic_data = greek_diacritic[char] + if not diacritic_data then break end + -- Preserve flags to be aware if a dialytika has to be reinserted + -- TODO: Keep dialytika node around + datum = datum | diacritic_data + -- Preserve ypogegrammeni (iota subscript) but convert them into capital iotas. + -- If el-x-iota is active keep the combining character instead. + if diacritic_data & HAS_YPOGEGRAMMENI ~= 0 then + has_ypogegrammeni = true + if not greek_iota then + setchar(post, 0x0399) + end + last = post + post = getnext(post) + else + -- Otherwise they get removed + local old = post + head, post = remove(head, post) + if char == 0x0301 and not saved_tonos then + -- But if we have a tonos we might want to reinsert it later + saved_tonos = old + elseif diacritic_data & HAS_DIALYTIKA ~= 0 and not saved_dialytika then + -- Similar for dilytika + saved_dialytika = old + else + free(old) + end + end + end + -- Special case: An isolated Ή preserves the tonos. + if upper == 0x0397 + and not has_ypogegrammeni + and not seen_cased + and not is_followed_by_cased(font, n, after) + then + if first_datum & HAS_ACCENT ~= 0 then + upper = 0x0389 + -- If it's precomposed we don't have to keep any combining accents + if saved_tonos then + free(saved_tonos) + saved_tonos = nil + end + end else - mapping = seen_cased and is_Final_Sigma(font, mapping, n, after) - or lang and is_Language_Mapping(font, mapping[lang], n, after, seen_soft_dotted, seen_I) - or mapping._ - if #mapping == 0 then - head, n = remove(head, n) - goto continue + -- Not the special case so we don't have to keep the tonos node + if saved_tonos then + free(saved_tonos) + saved_tonos = nil + end + -- Handle precomposed dialytika. If both a combining ans a precomposed + -- dialyika are present (typically because the precomposed one is + -- automatically added at the beginning) prefer the combining one to + -- preserve attributes. + if datum & HAS_DIALYTIKA ~= 0 and not saved_dialytika then + if upper == 0x0399 then -- upper == 'Ι' + upper = 0x03AA + elseif upper == 0x03A5 then -- upper == 'Υ' + upper = 0x03AB + else + assert(false) -- Should not be possible + end + end + end + if greek_iota and add_ypogegrammeni then + local mapped = greek_precombined_iota[upper] + if mapped then -- AFAICT always true + upper = mapped + add_ypogegrammeni = false + end + end + setchar(n, upper) + -- Potentially reinsert accents + if saved_dialytika then + head, n = insert_after(head, n, saved_dialytika) + setchar(n, 0x0308) -- Needed since we might have a U+0344 (COMBINING GREEK DIALYTIKA TONOS) + end + if saved_tonos then + head, n = insert_after(head, n, saved_tonos) + end + if add_ypogegrammeni then + head, n = insert_after(head, n, copy(n)) + setchar(n, 0x0399) + end + -- If we preserved any combining ypogegrammeni nodes, skip them now + n = last or n + seen_greek = datum & (HAS_VOWEL | HAS_ACCENT | HAS_DIALYTIKA) == HAS_VOWEL | HAS_ACCENT and n or true + seen_I, seen_soft_dotted = nil + else + local mapping = table[char] + if mapping then + if tonumber(mapping) then + setchar(n, mapping) else - setchar(n, mapping[1]) - for i=2, #mapping do - head, n = insert_after(head, n, copy(n)) - setchar(n, mapping[i]) + mapping = seen_cased and is_Final_Sigma(font, mapping, n, after) + or lang and is_Language_Mapping(font, mapping[lang], n, after, seen_soft_dotted, seen_I) + or mapping._ + if #mapping == 0 then + local old = n + head, n = remove(head, n) + free(old) + goto continue + else + setchar(n, mapping[1]) + for i=2, #mapping do + head, n = insert_after(head, n, copy(n)) + setchar(n, mapping[i]) + end end end end + local char_ccc = ccc[char] + if not char_ccc or char_ccc == 230 then + seen_I = char == 0x49 or nil + seen_soft_dotted = soft_dotted[char] + end + seen_greek = nil end if not case_ignorable[char] then seen_cased = cased[char] or nil end - local char_ccc = ccc[char] - if not char_ccc or char_ccc == 230 then - seen_I = char == 0x49 or nil - seen_soft_dotted = soft_dotted[char] - end elseif id == disc and uses_font(n, font) then local pre, post, rep = getdisc(n) local after = getnext(n) - pre, post, rep, seen_cased, seen_soft_dotted, seen_I = - processor(pre, font, nil, seen_cased, seen_soft_dotted, seen_I), - processor(post, font, after), - processor(rep, font, after, seen_cased, seen_soft_dotted, seen_I) + pre, post, rep, seen_cased, seen_soft_dotted, seen_I, seen_greek = + processor(pre, font, nil, seen_cased, seen_soft_dotted, seen_I, seen_greek), + processor(post, font, after, seen_greek), + processor(rep, font, after, seen_cased, seen_soft_dotted, seen_I, seen_greek) setdisc(n, pre, post, rep) else seen_cased, seen_soft_dotted, seen_I = nil @@ -207,12 +425,12 @@ local function process(table) n = getnext(n) ::continue:: end - return head, seen_cased, seen_soft_dotted, seen_I + return head, seen_cased, seen_soft_dotted, seen_I, seen_greek end - return function(head, font) return (processor(head, font)) end + return function(head, font, ...) return (processor(head, font)) end end -local upper_process = process(uppercase) +local upper_process = process(uppercase, 'upper') otfregister { name = 'upper', description = 'Map to uppercase', @@ -225,7 +443,7 @@ otfregister { }, } -local lower_process = process(lowercase) +local lower_process = process(lowercase, 'lower') otfregister { name = 'lower', description = 'Map to lowercase', diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-colors.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-colors.lua index 05248b2a82e..075b5210f5a 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-colors.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-colors.lua @@ -5,8 +5,8 @@ assert(luaotfload_module, "This is a part of luaotfload and should not be loaded independently") { name = "luaotfload-colors", - version = "3.21", --TAGVERSION - date = "2022-03-18", --TAGDATE + version = "3.22", --TAGVERSION + date = "2022-06-15", --TAGDATE description = "luaotfload submodule / color", license = "GPL v2.0", author = "Khaled Hosny, Elie Roux, Philipp Gesang, Dohyun Kim, David Carlisle", @@ -48,18 +48,22 @@ local nodetail = nodedirect.tail local getattribute = nodedirect.has_attribute local setattribute = nodedirect.set_attribute +local call_callback = luatexbase.call_callback + local stringformat = string.format local identifiers = fonts.hashes.identifiers local add_color_callback --[[ this used to be a global‽ ]] +local custom_setcolor, custom_settransparent + --[[doc-- Color string parser. --doc]]-- local lpeg = require"lpeg" local lpegmatch = lpeg.match -local C, Cg, Ct, P, R, S = lpeg.C, lpeg.Cg, lpeg.Ct, lpeg.P, lpeg.R, lpeg.S +local C, Cc, P, R, S = lpeg.C, lpeg.Cc, lpeg.P, lpeg.R, lpeg.S local spaces = S"\t "^0 local digit16 = R("09", "af", "AF") @@ -68,12 +72,43 @@ local octet = digit16 * digit16 / function(s) return tonumber(s, 16) / 255 end -local extract_color = spaces * octet * octet * octet / function(r,g,b) +local function lpeg_repeat(patt, count) + patt = P(patt) + local result = patt + for i = 2, count do + result = result * patt + end + return result +end + +local split_color = spaces * C(lpeg_repeat(digit16, 6)) * (opaque + C(lpeg_repeat(digit16, 2)))^-1 * spaces * -1 + + spaces * (C((spaces * (1 - S', ')^1)^1) + Cc(nil)) * spaces * (',' * spaces * C((spaces * (1 - S' ,')^1)^1)^-1 * spaces)^-1 * -1 + +luatexbase.create_callback('luaotfload.split_color', 'exclusive', function(value) + local rgb, a = lpegmatch(split_color, value) + if not rgb and not a then + logreport("both", 0, "color", + "%q is not a valid rgb[a] color expression", + digits) + end + return rgb, a +end) + +local extract_color = octet * octet * octet / function(r,g,b) return stringformat("%.3g %.3g %.3g rg", r, g, b) - end * (opaque + octet)^-1 * spaces * -1 + end * -1 +luatexbase.create_callback('luaotfload.parse_color', 'exclusive', function(value) + local rgb = lpegmatch(extract_color, value) + if not rgb then + logreport("both", 0, "color", + "Invalid color part in color expression %q", + value) + end + return rgb +end) ---- something is carried around in ``res`` ---- for later use by color_handler() --- but what? +-- Keep the currently collected page resources needed for the current +-- colors in `res`. local res = nil @@ -86,17 +121,37 @@ local function pageresources(alpha) return f end +local extract_transparent = octet * -1 +luatexbase.create_callback('luaotfload.parse_transparent', 'exclusive', function(value) + local a + if type(value) == 'string' then + a = lpegmatch(extract_transparent, value) + if not a then + logreport("both", 0, "color", + "Invalid transparency part in color expression %q", + value) + end + else + a = value + end + if a then + a = pageresources(a) + end + return a +end) + + --- string -> (string | nil) local function sanitize_color_expression (digits) digits = tostring(digits) - local rgb, a = lpegmatch(extract_color, digits) - if not rgb then - logreport("both", 0, "color", - "%q is not a valid rgb[a] color expression", - digits) - return + local rgb, a = call_callback('luaotfload.split_color', digits) + if rgb then + rgb = call_callback('luaotfload.parse_color', rgb) end - return rgb, (a and pageresources(a)) + if a then + a = call_callback('luaotfload.parse_transparent', a) + end + return rgb, a end local color_stack = 0 @@ -125,8 +180,6 @@ local colorstack_t = node.subtype("pdf_colorstack") local color_callback local color_attr = luatexbase.new_attribute("luaotfload_color_attribute") -local custom_setcolor - -- Pass nil for new_color or old_color to indicate no color -- If color is nil, pass tail to decide where to add whatsit local function color_whatsit (head, curr, stack, old_color, new_color, tail) @@ -391,8 +444,38 @@ end function luaotfload.set_colorhandler(cb) custom_setcolor = cb end +function luaotfload.set_transparenthandler(cb) + custom_settransparent = cb +end +function luaotfload.set_transparent_colorstack(stack) + if type(transparent_stack) == 'number' then + tex.error"luaotfload's transparency stack can't be changed after it has been used" + else + local t = type(stack) + if t == 'function' or t == 'number' then + function transparent_stack() + if t == 'function' then + transparent_stack = stack() + else + transparent_stack = stack + end + return transparent_stack + end + else + tex.error("Invalid argument in luaotfload.set_transparent_colorstack") + end + end +end + +setmetatable(fonts.handlers.otf.statistics.usedfeatures.color, { + __index = function(t, k) + t[k] = k + return k + end, +}) return function () + assert(logreport == luaotfload.log.report) logreport = luaotfload.log.report if not fonts then logreport ("log", 0, "color", diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-configuration.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-configuration.lua index 5a7205ba69e..8368425334b 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-configuration.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-configuration.lua @@ -7,8 +7,8 @@ assert(luaotfload_module, "This is a part of luaotfload and should not be loaded independently") { name = "luaotfload-configuration", - version = "3.21", --TAGVERSION - date = "2022-03-18", --TAGDATE + version = "3.22", --TAGVERSION + date = "2022-06-15", --TAGDATE description = "luaotfload submodule / config file reader", license = "GPL v2.0" } diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-database.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-database.lua index ff43b975055..63f799ca41e 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-database.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-database.lua @@ -5,8 +5,8 @@ do -- block to avoid to many local variables error assert(luaotfload_module, "This is a part of luaotfload and should not be loaded independently") { name = "luaotfload-database", - version = "3.21", --TAGVERSION - date = "2022-03-18", --TAGDATE + version = "3.22", --TAGVERSION + date = "2022-06-15", --TAGDATE description = "luaotfload submodule / database", license = "GPL v2.0", author = "Khaled Hosny, Elie Roux, Philipp Gesang, Marcel Krüger", @@ -201,7 +201,7 @@ local resolversfindfile = context_environment.resolvers.findfile --- some of our own local unicode = require'luaotfload-unicode' -local casefold = unicode.casefold +local casefold = require'lua-uni-case'.casefold local alphnum_only = unicode.alphnum_only local name_index = nil --> upvalue for names.data @@ -516,8 +516,11 @@ end local function load_lua_file (path_lua, path_luc) local foundname, chunk = load_maybe_gzip (path_luc, true) if foundname then - chunk = assert (load (chunk, 'b')) + chunk = load (chunk, 'b') else + chunk = nil + end + if not chunk then foundname, chunk = load_maybe_gzip (path_lua, false) if foundname then chunk = assert (load (chunk, 't')) @@ -2435,7 +2438,7 @@ local function count_removed (files) local f = old[i] if not kpsereadable_file (f) then logreport ("log", 2, "db", - "File %q does not exist in file system.") + "File %q does not exist in file system.", f) nrem = nrem + 1 end end diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-diagnostics.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-diagnostics.lua index e0403d932ca..25f79419a61 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-diagnostics.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-diagnostics.lua @@ -7,8 +7,8 @@ assert(luaotfload_module, "This is a part of luaotfload and should not be loaded independently") { name = "luaotfload-diagnostics", - version = "3.21", --TAGVERSION - date = "2022-03-18", --TAGDATE + version = "3.22", --TAGVERSION + date = "2022-06-15", --TAGDATE description = "luaotfload-tool submodule / diagnostics", license = "GPL v2.0" } diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-dvi.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-dvi.lua index 3991eb110d3..da045d1d340 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-dvi.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-dvi.lua @@ -6,8 +6,8 @@ assert(luaotfload_module, "This is a part of luaotfload and should not be loaded independently") { name = "luaotfload-dvi", - version = "3.21", --TAGVERSION - date = "2022-03-18", --TAGDATE + version = "3.22", --TAGVERSION + date = "2022-06-15", --TAGDATE description = "luaotfload submodule / DVI", license = "GPL v2.0", author = "Marcel Krüger", diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-embolden.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-embolden.lua index 5699611da35..7bc4da5a763 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-embolden.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-embolden.lua @@ -5,8 +5,8 @@ assert(luaotfload_module, "This is a part of luaotfload and should not be loaded independently") { name = "luaotfload-embolden", - version = "3.21", --TAGVERSION - date = "2022-03-18", --TAGDATE + version = "3.22", --TAGVERSION + date = "2022-06-15", --TAGDATE description = "luaotfload submodule / embolden", license = "GPL v2.0", author = "Marcel Krüger" diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-fallback.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-fallback.lua index d9a85b75785..253d16051ca 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-fallback.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-fallback.lua @@ -5,8 +5,8 @@ assert(luaotfload_module, "This is a part of luaotfload and should not be loaded independently") { name = "luaotfload-fallback", - version = "3.21", --TAGVERSION - date = "2022-03-18", --TAGDATE + version = "3.22", --TAGVERSION + date = "2022-06-15", --TAGDATE description = "luaotfload submodule / fallback", license = "GPL v2.0", author = "Marcel Krüger" diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-features.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-features.lua index 01c04becb1f..6e64020570e 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-features.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-features.lua @@ -5,8 +5,8 @@ assert(luaotfload_module, "This is a part of luaotfload and should not be loaded independently") { name = "luaotfload-features", - version = "3.21", --TAGVERSION - date = "2022-03-18", --TAGDATE + version = "3.22", --TAGVERSION + date = "2022-06-15", --TAGDATE description = "luaotfload submodule / features", license = "GPL v2.0", author = "Hans Hagen, Khaled Hosny, Elie Roux, Philipp Gesang, Marcel Krüger", @@ -30,8 +30,6 @@ local table = table local tabletohash = table.tohash local tablesort = table.sort -local stringunpack = string.unpack - --- this appears to be based in part on luatex-fonts-def.lua local fonts = fonts @@ -56,15 +54,6 @@ else normalize = otf.features.normalize end ---[[HH (font-xtx) -- - tricky: we sort of bypass the parser and directly feed all into - the sub parser ---HH]]-- - -function definers.getspecification(str) - return "", str, "", ":", str -end - local log = luaotfload.log local report = log.report @@ -76,7 +65,7 @@ local function cmp_by_idx (a, b) return a.idx < b.idx end local defined_combos = 0 -local function handle_combination (combo, spec) +local function handle_combination (combo, spec, size) defined_combos = defined_combos + 1 if not combo [1] then report ("both", 0, "features", @@ -143,7 +132,7 @@ local function handle_combination (combo, spec) local basechar = basefnt.characters local baseprop = basefnt.properties - baseprop.name = spec.name + baseprop.name = spec baseprop.virtualized = true basefnt.fonts = fontids @@ -194,13 +183,16 @@ local function handle_combination (combo, spec) " *> font %d / %d: imported %d glyphs into combo.", i, nc, cnt) end - spec.lookup = "combo" - spec.file = basefnt.filename - spec.name = stringformat ("luaotfload<%d>", defined_combos) - spec.features = { normal = { spec.specification } } - spec.forced = "evl" - spec.eval = function () return basefnt end - return spec + return { + lookup = "combo", + file = basefnt.filename, + name = stringformat ("luaotfload<%d>", defined_combos), + specification = spec, + features = { normal = { } }, + forced = "evl", + eval = function () return basefnt end, + size = size, + } end ---[[ begin excerpt from font-ott.lua ]] @@ -359,10 +351,9 @@ do extract_subfont = full_path * sub_expr end ---- spec -> spec -local function handle_request (specification) +local function analyze(spec_string, size) local request = lpegmatch(luaotfload.parsers.font_request, - specification.specification) + spec_string) ----inspect(request) if not request then --- happens when called with an absolute path @@ -370,7 +361,7 @@ local function handle_request (specification) --- we try to behave as friendly as possible --- just go with it ... report("log", 1, "features", "invalid request %q of type anon", - specification.specification) + spec_string) report("log", 1, "features", "use square bracket syntax or consult the documentation.") --- The result of \fontname must be re-feedable into \font @@ -382,36 +373,62 @@ local function handle_request (specification) --- parentheses). --- https://github.com/lualatex/luaotfload/issues/57 local fullpath, sub = lpegmatch(extract_subfont, - specification.specification) + spec_string) if fullpath and sub then - specification.sub = tonumber(sub) or sub - specification.name = fullpath + return { + lookup = 'path', + sub = tonumber(sub) or sub, + name = fullpath, + size = size, + } else - specification.name = specification.specification + return { + lookup = 'path', + name = spec_string, + size = size, + } end - specification.lookup = "path" - return specification end local lookup, name = request.lookup, request.name if lookup == "combo" then - return handle_combination (name, specification) + return handle_combination (name, spec_string, size) end - local features = specification.features - if not features then - features = { } - specification.features = features - end + local features = { + raw = request.features or {} + } - features.raw = request.features or {} - request.features = apply_default_features(features.raw) + local specification = { + specification = spec_string, + size = size, + lookup = lookup, + name = name, + sub = request.sub or false, + features = features, + } - if name then - specification.name = name - specification.lookup = lookup or specification.lookup + if lookup == 'id' then + local original_font = fontidentifiers [request.id] + if not original_font then return end + local original_spec = original_font.specification + if not original_spec then return end + if size < 0 then + specification.size = original_spec.size * size // -1000 + end + specification.lookup = original_spec.lookup + specification.name = original_spec.name + specification.sub = specification.sub or original_spec.sub + specification.style = original_spec.style + specification.optsize = original_spec.optsize + specification.forced = original_spec.forced + if original_spec.features then + features.raw = table.merged(original_spec.features.raw, features.raw) + end end + local processed_features = apply_default_features(features.raw) + if request.modifiers then local style, optsize = handle_slashed(request.modifiers) specification.style, specification.optsize = style, optsize @@ -420,11 +437,11 @@ local function handle_request (specification) for n=1, #import_values do local feat = import_values[n][1] local keep = import_values[n][2] - local newvalue = request.features[feat] + local newvalue = processed_features[feat] if newvalue then - specification[feat] = request.features[feat] + specification[feat] = newvalue if not keep then - request.features[feat] = nil + processed_features[feat] = nil end end end @@ -432,7 +449,7 @@ local function handle_request (specification) --- The next line sets the “rand” feature to “random”; I haven’t --- investigated it any further (luatex-fonts-ext), so it will --- just stay here. - features.normal = normalize (request.features) + features.normal = normalize (processed_features) if features.normal.instance then if features.normal.axis then report("term and log", 0, "features", "instance and axis provided, instance will be ignored") @@ -440,7 +457,6 @@ local function handle_request (specification) specification.instance = features.normal.instance end end - specification.sub = request.sub or specification.sub or false local forced_mode = request.features and request.features.mode if forced_mode then @@ -453,8 +469,7 @@ local function handle_request (specification) return specification end -fonts.names.handle_request = handle_request - +fonts.definers.analyze = analyze if as_script == true then --- skip the remainder of the file report ("log", 5, "features", @@ -463,7 +478,7 @@ if as_script == true then --- skip the remainder of the file end do - local helpers = fonts.handlers.otf.readers.helpers + local helpers = otf.readers.helpers local axistofactors = helpers.axistofactors local cleanname = helpers.cleanname local getaxisscale = helpers.getaxisscale @@ -479,7 +494,7 @@ do function helpers.getfactors(tfmdata, instance) -- `instance` might refer to an `axis` value here assert(instance == true or type(instance) == "string", "Fontloader changed interface of helpers.getfactors. This is a bug, please notify the luaotfload maintainers.") local variabledata = tfmdata.variabledata - if not variabledata or instance == "" then return end + if not variabledata then return end local instances = variabledata.instances local axis = variabledata.axis local designaxis = variabledata.designaxis @@ -525,15 +540,6 @@ do end end --- MK: Added -function fonts.definers.analyze (spec_string, size) - return handle_request { - size = size, - specification = spec_string, - } -end --- /MK - -- We assume that the other otf stuff is loaded already; though there’s -- another check below during the initialization phase. diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-filelist.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-filelist.lua index 191e6fd81b1..a5dac9e640f 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-filelist.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-filelist.lua @@ -6,8 +6,8 @@ if luaotfload_module then luaotfload_module { name = "luaotfload-filelist", - version = "3.21", --TAGVERSION - date = "2022-03-18", --TAGDATE + version = "3.22", --TAGVERSION + date = "2022-06-15", --TAGDATE description = "luaotfload submodule / filelist", license = "GPL v2.0" } end diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-glyphlist.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-glyphlist.lua index b13d9db86fa..f585e298b8c 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-glyphlist.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-glyphlist.lua @@ -1,8 +1,8 @@ if luaotfload_module then luaotfload_module { name = "luaotfload-glyphlist", - version = "3.21", --TAGVERSION - date = "2022-03-18", --TAGDATE + version = "3.22", --TAGVERSION + date = "2022-06-15", --TAGDATE description = "luaotfload submodule / autogenerated glyphlist", copyright = "derived from https://raw.githubusercontent.com/adobe-type-tools/agl-aglfn/master/glyphlist.txt", original = "Adobe Glyph List, version 2.0, September 20, 2002", diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-harf-define.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-harf-define.lua index d311020cd4a..c3b0a8509e0 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-harf-define.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-harf-define.lua @@ -5,8 +5,8 @@ do -- block to avoid to many local variables error assert(luaotfload_module, "This is a part of luaotfload and should not be loaded independently") { name = "luaotfload-harf-define", - version = "3.21", --TAGVERSION - date = "2022-03-18", --TAGDATE + version = "3.22", --TAGVERSION + date = "2022-06-15", --TAGDATE description = "luaotfload submodule / HarfBuzz font loading", license = "GPL v2.0", author = "Khaled Hosny, Marcel Krüger", @@ -87,7 +87,7 @@ local variable_pattern do local number = l.C(l.S'+-'^-1 * (l.R'09'^1 * ('.' * l.R'09'^0)^-1 + '.' * l.R'09'^1)) local name_or_tag = l.C(l.R('AZ', 'az')^1) local pair = l.Ct(name_or_tag * white * '=' * white * (number + l.Cc(nil) * 'auto')) - variable_pattern = l.Ct(pair * (white * ',' * white * pair)^0) + variable_pattern = l.Ct(pair * (white * ',' * white * pair)^0) * -1 end local function loadfont(spec) diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-harf-plug.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-harf-plug.lua index be05980a491..df0d0cf136c 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-harf-plug.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-harf-plug.lua @@ -4,8 +4,8 @@ ----------------------------------------------------------------------- assert(luaotfload_module, "This is a part of luaotfload and should not be loaded independently") { name = "luaotfload-harf-plug", - version = "3.21", --TAGVERSION - date = "2022-03-18", --TAGDATE + version = "3.22", --TAGVERSION + date = "2022-06-15", --TAGDATE description = "luaotfload submodule / HarfBuzz shaping", license = "GPL v2.0", author = "Khaled Hosny, Marcel Krüger", @@ -136,8 +136,8 @@ local function setprop(n, prop, value) props[prop] = value end -local function inherit(t, base, properties) - local n = newnode(t) +local function inherit(t, sub, base, properties) + local n = newnode(t, sub) setattrs(n, getattrs(base)) if properties then setproperty(n, setmetatable({}, {__index = properties})) @@ -146,7 +146,7 @@ local function inherit(t, base, properties) end -- New kern node of amount `v`, inheriting the properties/attributes of `n`. local function newkern(v, n) - local kern = inherit(kern_t, n, getproperty(n)) + local kern = inherit(kern_t, 0, n, getproperty(n)) setkern(kern, v) return kern end @@ -293,7 +293,7 @@ end local function unsafetobreak(glyph) return glyph and glyph.flags - and glyph.flags & fl_unsafe + and glyph.flags & fl_unsafe ~= 0 end local shape @@ -782,11 +782,11 @@ local function tonodes(head, node, run, glyphs) elseif nextcluster + 1 == nodeindex then -- Oops, we went too far nodeindex = nodeindex - 1 if node then - local new = inherit(glyph_t, getprev(node), lastprops) + local new = inherit(glyph_t, 0, getprev(node), lastprops) head, node = insertbefore(head, node, new) else node = tail(head) - local new = inherit(glyph_t, node, lastprops) + local new = inherit(glyph_t, 0, node, lastprops) head, node = insertafter(head, node, new) end setfont(node, fontid) @@ -1050,8 +1050,8 @@ function process(head, font, _attr, direction) return newhead or head end -local function pageliteral(data) - local n = newnode(whatsit_t, pdfliteral_t) +local function pageliteral(data, base) + local n = inherit(whatsit_t, pdfliteral_t, base, getproperty(base)) setwhatsitfield(n, "mode", 1) -- page setwhatsitfield(n, "data", data) -- page return n @@ -1069,12 +1069,12 @@ local function post_process(head) if startactual then local actualtext = "/Span<</ActualText<FEFF"..startactual..">>>BDC" - head = insertbefore(head, n, pageliteral(actualtext)) + head = insertbefore(head, n, pageliteral(actualtext, n)) props[startactual_p] = nil end if endactual then - head = insertafter(head, n, pageliteral("EMC")) + head = insertafter(head, n, pageliteral("EMC", n)) props[endactual_p] = nil end diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-harf-var-cff2.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-harf-var-cff2.lua index e9cff0c1adf..2ca928d32a1 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-harf-var-cff2.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-harf-var-cff2.lua @@ -5,8 +5,8 @@ do assert(luaotfload_module, "This is a part of luaotfload and should not be loaded independently") { name = "luaotfload-harf-var-cff2", - version = "3.21", --TAGVERSION - date = "2022-03-18", --TAGDATE + version = "3.22", --TAGVERSION + date = "2022-06-15", --TAGDATE description = "luaotfload submodule / CFF2 table processing", license = "GPL v2.0", author = "Marcel Krüger", @@ -371,7 +371,7 @@ local function parse_vstore(buf, offset, variation) return variation_data end -function parse_cff2(buf, i0, coords) +local function parse_cff2(buf, i0, coords) local fontid = 1 local major, minor, hdrSize, topSize = string.unpack(">BBBH", buf, i0) if major ~= 2 then error[[Unsupported CFF version]] end diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-harf-var-t2-writer.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-harf-var-t2-writer.lua index 7b44822e59f..72239343d89 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-harf-var-t2-writer.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-harf-var-t2-writer.lua @@ -5,8 +5,8 @@ do assert(luaotfload_module, "This is a part of luaotfload and should not be loaded independently") { name = "luaotfload-harf-var-t2-writer", - version = "3.21", --TAGVERSION - date = "2022-03-18", --TAGDATE + version = "3.22", --TAGVERSION + date = "2022-06-15", --TAGDATE description = "luaotfload submodule / Type 2 charstring writer", license = "GPL v2.0", author = "Marcel Krüger", diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-harf-var-ttf.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-harf-var-ttf.lua index 7835466757c..b39cd753ae4 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-harf-var-ttf.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-harf-var-ttf.lua @@ -5,8 +5,8 @@ do assert(luaotfload_module, "This is a part of luaotfload and should not be loaded independently") { name = "luaotfload-harf-var-ttf", - version = "3.21", --TAGVERSION - date = "2022-03-18", --TAGDATE + version = "3.22", --TAGVERSION + date = "2022-06-15", --TAGDATE description = "luaotfload submodule / gvar table processing", license = "GPL v2.0", author = "Marcel Krüger", @@ -166,11 +166,12 @@ local function parse_glyf(loca, glyf, gid) payload_length = payload_length + 8 end if flags & 0x120 == 0x100 then -- Only applies to the last character - payload_length = payload_length + 2 + sio.readcardinal2(offset + payload_length) + payload_length = payload_length + 2 + sio.readcardinal2(glyf, offset + payload_length) end component.flags = flags component.payload = glyf:sub(offset, offset + payload_length - 1) components[#components+1] = component + offset = offset + payload_length until flags & 0x20 == 0 return components else @@ -328,6 +329,9 @@ local function serialize_glyf(points, map) local x, y = component.x, component.y x = x and math.floor(x + .5) y = y and math.floor(y + .5) + if component.flags & 0x3 == 0x2 and (x >= 0x100 or x < -0x100 or y >= 0x100 or y < 0x100) then + component.flags = component.flags | 0x1 + end result = result .. string.pack(component.flags & 0x2 == 0 and '>I2I2' or component.flags & 0x1 == 0x1 and '>I2I2i2i2' @@ -395,7 +399,13 @@ local function interpolate_glyf(loca, gvar_index, gvar, glyf, gid, coords, map) if not var then local start = loca[gid+1] + 1 local stop = loca[gid+2] - return glyf:sub(start, stop) + -- If the glyph uses components then we can never just copy it but have to parse + -- it to rewrite the components if necessary. + if stop >= start + 2 and sio.readinteger2(glyf, start) < 0 then + return serialize_glyf(parse_glyf(loca, glyf, gid), map) + else + return glyf:sub(start, stop) + end end local points = parse_glyf(loca, glyf, gid) if not points then return '' end diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-hashing.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-hashing.lua new file mode 100644 index 00000000000..e88eab706c1 --- /dev/null +++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-hashing.lua @@ -0,0 +1,2 @@ +local constructors = fonts.constructors +local original_hashfeatures = constructors.hashfeatures diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-init.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-init.lua index 8cb2b5ad3d1..ff959e35023 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-init.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-init.lua @@ -7,8 +7,8 @@ assert(luaotfload_module, "This is a part of luaotfload and should not be loaded independently") { name = "luaotfload-init", - version = "3.21", --TAGVERSION - date = "2022-03-18", --TAGDATE + version = "3.22", --TAGVERSION + date = "2022-06-15", --TAGDATE description = "luaotfload submodule / initialization", license = "GPL v2.0" } diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-letterspace.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-letterspace.lua index 311279f09d8..ef19afe3842 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-letterspace.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-letterspace.lua @@ -5,8 +5,8 @@ assert(luaotfload_module, "This is a part of luaotfload and should not be loaded independently") { name = "luaotfload-letterspace", - version = "3.21", --TAGVERSION - date = "2022-03-18", --TAGDATE + version = "3.22", --TAGVERSION + date = "2022-06-15", --TAGDATE description = "luaotfload submodule / letterspacing", license = "GPL v2.0", copyright = "PRAGMA ADE / ConTeXt Development Team", diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-loaders.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-loaders.lua index fcae6e6d9ec..eb094430772 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-loaders.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-loaders.lua @@ -8,8 +8,8 @@ assert(luaotfload_module, "This is a part of luaotfload and should not be loaded independently") { name = "luaotfload-loaders", - version = "3.21", --TAGVERSION - date = "2022-03-18", --TAGDATE + version = "3.22", --TAGVERSION + date = "2022-06-15", --TAGDATE description = "luaotfload submodule / callback handling", license = "GPL v2.0" } @@ -104,32 +104,80 @@ local function not_found_msg (specification, size, id) logreport ("both", 0, "loaders", "--------------------------------------------------------") end ---[[doc-- - \subsection{\CONTEXT override} - \label{define-font} - We provide a simplified version of the original font definition - callback. +local definers --- (string, spec -> size -> id -> tmfdata) hash_t +do + local hashed_cache = {} + local fontdata_cache = fonts.hashes.identifiers + local function register(fontdata, id) + if fontdata and id then + local hash = fontdata.properties.hash + if not hash then + logreport('both', 2, 'loaders', "Registering font %s with id %s with missing hash.", id, fontdata.properties.filename or "unknown") + elseif not hashed_cache[hash] then + hashed_cache[hash] = id + logreport('both', 4, 'loaders', "Registering font %s with id %s and hash %s.", id, fontdata.properties.filename or "unknown", hash) + end + fontdata_cache[id] = fontdata + end + end + function registered(hash) + local id = hashed_cache[hash] + return id, fontdata_cache[id] + end + fonts.definers.register = register + fonts.definers.registered = registered ---doc]]-- + local extra_hash_funcs = {} + local function ltx_read(spec, size, id) + spec = type(spec) == 'string' and fonts.definers.analyze(spec, size) or spec + spec = fonts.definers.resolve(spec) + + local hash = fonts.constructors.hashinstance(spec) + + -- extra_hash_func allows the loader to determine additional hash parts + -- depending on the actual font. This is used e.g. for variable fonts which + -- should be hashed based on their designsize / modifiers too. + local extra_hash_func = extra_hash_funcs[hash] + if extra_hash_func then + hash = hash .. ' @ ' .. table.join(extra_hash_func(spec), ' @ ') + end + + local cached = registered(hash) + if cached then return cached end -- already loaded + + local fontdata = fonts.definers.loadfont(spec) + if not fontdata then + logreport('both', 2, 'loaders', 'Failed to load font ' .. spec.name) + return + end + + -- If extra_hash_func was already set then the hash is already extended. + -- Otherwise we have to do it now if requested. + if not extra_hash_func then + extra_hash_func = fontdata.properties.extra_hash_func + if extra_hash_func then + hash = hash .. ' @ ' .. table.join(extra_hash_func(spec), ' @ ') + end + end + fontdata.properties.hash = hash + register(fontdata, id) + return fontdata + end -local definers --- (string, spec -> size -> id -> tmfdata) hash_t -do - local ctx_read = fonts.definers.read - local register = fonts.definers.register local function read(specification, size, id) - local tfmdata = ctx_read(specification, size, id) - if not tfmdata or id or tonumber(tfmdata) then - return tfmdata + local fontdata = ltx_read(specification, size, id) + if not fontdata or id or tonumber(fontdata) then + return fontdata end - id = font.define(tfmdata) - register(tfmdata, id) + id = font.define(fontdata) + register(fontdata, id) return id end local function patch (specification, size, id) - local fontdata = ctx_read (specification, size, id) + local fontdata = ltx_read (specification, size, id) ----if not fontdata then not_found_msg (specification, size, id) end if type (fontdata) == "table" and fontdata.encodingbytes == 2 then --- We need to test for `encodingbytes` to avoid passing diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-log.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-log.lua index 8622b465ef2..74b364e874c 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-log.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-log.lua @@ -6,8 +6,8 @@ assert(luaotfload_module, "This is a part of luaotfload and should not be loaded independently") { name = "luaotfload-log", - version = "3.21", --TAGVERSION - date = "2022-03-18", --TAGDATE + version = "3.22", --TAGVERSION + date = "2022-06-15", --TAGDATE description = "luaotfload submodule / logging", license = "GPL v2.0", author = "Khaled Hosny, Elie Roux, Philipp Gesang", diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-multiscript.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-multiscript.lua index c315698a564..bc3921e203c 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-multiscript.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-multiscript.lua @@ -5,8 +5,8 @@ assert(luaotfload_module, "This is a part of luaotfload and should not be loaded independently") { name = "luaotfload-multiscript", - version = "3.21", --TAGVERSION - date = "2022-03-18", --TAGDATE + version = "3.22", --TAGVERSION + date = "2022-06-15", --TAGDATE description = "luaotfload submodule / multiscript", license = "GPL v2.0", author = "Marcel Krüger" diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-notdef.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-notdef.lua index fb763390f14..418ea79d57b 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-notdef.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-notdef.lua @@ -5,8 +5,8 @@ assert(luaotfload_module, "This is a part of luaotfload and should not be loaded independently") { name = "luaotfload-notdef", - version = "3.21", --TAGVERSION - date = "2022-03-18", --TAGDATE + version = "3.22", --TAGVERSION + date = "2022-06-15", --TAGDATE description = "luaotfload submodule / notdef", license = "GPL v2.0", author = "Marcel Krüger" diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-parsers.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-parsers.lua index 6219525a7fd..b2cc9c30ead 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-parsers.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-parsers.lua @@ -7,8 +7,8 @@ assert(luaotfload_module, "This is a part of luaotfload and should not be loaded independently") { name = "luaotfload-parsers", - version = "3.21", --TAGVERSION - date = "2022-03-18", --TAGDATE + version = "3.22", --TAGVERSION + date = "2022-06-15", --TAGDATE description = "luaotfload submodule / parsers", license = "GPL v2.0" } @@ -498,27 +498,6 @@ local function handle_xetex_option (val) return tostring(1 + tonumber(val)) end ---[[doc-- - - Dirty test if a file: request is actually a path: lookup; don’t - ask! Note this fails on Windows-style absolute paths. These will - *really* have to use the correct request. - ---doc]]-- - -local function check_garbage (_,i, garbage) - if stringfind(garbage, "/") then - logreport("log", 0, "load", --- ffs use path! - "warning: path in file: lookups is deprecated; ") - logreport("log", 0, "load", "use bracket syntax instead!") - logreport("log", 0, "load", - "position: %d; full match: %q", - i, garbage) - return true - end - return false -end - local featuresep = comma + semicolon --- modifiers --------------------------------------------------------- @@ -598,10 +577,12 @@ local combolist = Ct(combodef1 * (comborowsep * combodef)^1) local subfont = P"(" * Cg(R'09'^1 / function (s) return tonumber(s) + 1 end + (1 - S"()")^1, "sub") * P")" +-- An optional subfont shouldn't use subfont^-1 to ensure that parens +-- at the subfont location are never interpreted in different ways. +local maybe_subfont = subfont + #(1 - P"(" + -1) --- lookups ----------------------------------------------------------- local fontname = C((1-S":(/")^1) --- like luatex-fonts -local unsupported = Cmt((1-S":(")^1, check_garbage) local combo = Cg(P"combo", "lookup") * colon * ws * Cg(combolist, "name") --- initially we intended file: to emulate the behavior of @@ -610,10 +591,10 @@ local combo = Cg(P"combo", "lookup") * colon * ws --- turns out fontspec and other widely used packages rely on file: --- with paths already, so we’ll add a less strict rule here. anyways, --- we’ll emit a warning. -local prefixed = P"file:" * ws * Cg(Cc"path", "lookup") - * Cg(unsupported, "name") - + Cg(P"name" + "file" + "kpse" + "my", "lookup") +local prefixed = Cg(P"name" + "file" + "kpse" + "my", "lookup") * colon * ws * Cg(fontname, "name") + + Cg(P"id", "lookup") + * colon * ws * Cg(R'09'^1 / tonumber, "id") local unprefixed = Cg(Cc"anon", "lookup") * Cg(fontname, "name") --- Bracketed “path” lookups: These may contain any character except --- for unbalanced brackets. A backslash escapes any following @@ -628,7 +609,6 @@ local path_balanced = { (path_content + V(2))^1 , lbrk * V(1)^-1 * rbrk } local path_lookup = Cg(Cc"path", "lookup") * lbrk * Cg(Cs(path_balanced), "name") * rbrk - * subfont^-1 --- features ---------------------------------------------------------- local balanced_braces = P{((1 - S'{}') + '{' * V(1) * '}')^0} @@ -655,12 +635,11 @@ local feature_list = Cf(Ct"" --- top-level rules --------------------------------------------------- --- \font\foo=<specification>:<features> local features = Cg(feature_list, "features") -local specification = (prefixed + unprefixed) - * subfont^-1 +local specification = (path_lookup + prefixed + unprefixed) + * maybe_subfont * modifier_list -local font_request = Ct(path_lookup * (colon^-1 * features)^-1 - + combo --> TODO: feature list needed? - + specification * (colon * features)^-1) +local font_request = Ct(specification * (colon^-1 * features)^-1 + + combo) --> TODO: feature list needed? -- lpeg.print(font_request) --- v2.5 parser: 1065 rules diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-resolvers.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-resolvers.lua index 0034010817b..135a843cf3d 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-resolvers.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-resolvers.lua @@ -11,8 +11,8 @@ assert(luaotfload_module, "This is a part of luaotfload and should not be loaded independently") { name = "luaotfload-resolvers", - version = "3.21", --TAGVERSION - date = "2022-03-18", --TAGDATE + version = "3.22", --TAGVERSION + date = "2022-06-15", --TAGDATE description = "luaotfload submodule / resolvers", license = "GPL v2.0" } @@ -148,6 +148,10 @@ local function resolve_tex_format (specification) local name = specification.name for i=1, #tex_formats do local format = tex_formats [i] + local name = name + if name:sub(-#format-1) ~= '.' .. format then -- Add an explicit extension to avoid finding local fonts in other formats + name = name .. '.' .. format + end local resolved = resolvers_findfile(name, format) if resolved then return resolved, format @@ -231,8 +235,8 @@ local function resolve_kpse (specification) local resolved = resolvers_findfile(name, suffix) if resolved then return resolved end end - for t, format in next, fonts.formats do --- brute force - local resolved = kpsefind_file (name, format) + for _, t in ipairs{'otf', 'ttf', 'pfb', 'lua', 'afm'} do --- brute force + local resolved = resolvers_findfile (name, t) if resolved then return resolved, t end end end diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-scripts.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-scripts.lua index 60b6f603dce..8d98f7ce37b 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-scripts.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-scripts.lua @@ -5,8 +5,8 @@ assert(luaotfload_module, "This is a part of luaotfload and should not be loaded independently") { name = "luaotfload-script", - version = "3.21", --TAGVERSION - date = "2022-03-18", --TAGDATE + version = "3.22", --TAGVERSION + date = "2022-06-15", --TAGDATE description = "luaotfload submodule / Script helpers", license = "CC0 1.0 Universal", author = "Marcel Krüger" diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-status.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-status.lua index 5bd21db80ce..7ec80b14fb5 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-status.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-status.lua @@ -1,6 +1,6 @@ return { ["hashes"]={ - { "fontloader-2022-02-24.lua", "4dc8ce07471f8af7aa98d835df654768" }, + { "fontloader-2022-06-15.lua", "1d9c716b5c1d6ff84bee5e4ba3631eac" }, { "fontloader-util-fil.lua", "d0accf4180201efd567816a25ad5e037" }, { "fontloader-util-str.lua", "f4a9dd15c3e40cd3915749ac13837c95" }, { "fontloader-l-unicode.lua", "f368874f11f3c525de5864fd413e4b24" }, @@ -24,7 +24,7 @@ return { { "fontloader-basics-nod.lua", "1750af43148def9e7a75c6900a96f9dc" }, { "fontloader-font-imp-effects.lua", "d05997c1826355548ec9aec1346f9f23" }, { "fontloader-font-imp-italics.lua", "defcb415bc1e0a0999b27773902adc18" }, - { "fontloader-font-imp-ligatures.lua", "26ffcf089391445f7af59536c8814364" }, + { "fontloader-font-imp-ligatures.lua", "250f6f4488ee770c23177afb2ff75676" }, { "fontloader-font-imp-tex.lua", "ceb087ef6fa2f89aed7179f60ddf8f35" }, { "fontloader-font-shp.lua", "a40862fe382d26c1f3753431254bcfdd" }, { "fontloader-font-def.lua", "b9d908c2338b7dc443ce9d1e9fcb7139" }, @@ -33,67 +33,67 @@ return { { "fontloader-font-one.lua", "bd39d42055a44ca2002f8ddbbbbf27c3" }, { "fontloader-font-onr.lua", "6d161533f3437435e12a0ad64866df44" }, { "fontloader-font-ocl.lua", "2a377351ae23c339764ec8ce2e8e9164" }, - { "fontloader-font-osd.lua", "a67b6fb465e7a8b9ecf7c6bbf8dfda03" }, - { "fontloader-font-otc.lua", "582295d3d1e44cd4a31e8bbc1156f7c1" }, + { "fontloader-font-osd.lua", "9b5337b0051b8e42b6c8329127c59794" }, + { "fontloader-font-otc.lua", "57f5270b894e40efa93149c7d3fb0209" }, { "fontloader-font-ots.lua", "55316a605d11a1d07d38795224c90a63" }, { "fontloader-font-ota.lua", "2bb12d708e35bc05443eba791e2554e7" }, - { "fontloader-font-oup.lua", "e6e2cc0a202aec2c787d5524e64d340a" }, + { "fontloader-font-oup.lua", "76dc3379061e5650f772909966b5759e" }, { "fontloader-font-otj.lua", "b2c165bd6771a57633f992d07384b739" }, { "fontloader-font-oto.lua", "9febc4d75d17a543cd73fb17918f7307" }, - { "fontloader-font-otl.lua", "67078f58bc1a612e4646523538a4e3eb" }, + { "fontloader-font-otl.lua", "308b1aab04bc131da7eb8e8c3b0471d4" }, { "fontloader-font-ott.lua", "3f67b1b1d40bbc222681d8db4aff0f42" }, { "fontloader-font-oti.lua", "309a75f9c14b77d87e94eba827dc4e71" }, - { "fontloader-font-dsp.lua", "7616dae672693fd8ec0f1892358019a2" }, - { "fontloader-font-ttf.lua", "feba1fdc80160343b24f89ef978e53cb" }, + { "fontloader-font-dsp.lua", "4935e6605ffd7bf57e66f0b6c132f883" }, + { "fontloader-font-ttf.lua", "a3ff07150b3535fd32f68748d53fcd36" }, { "fontloader-font-cff.lua", "e38c1a40e1d1d577cdf7920fa50d0654" }, - { "fontloader-font-otr.lua", "91f70c1216e60227e1437b6c8dcd8647" }, + { "fontloader-font-otr.lua", "1896ac990a961f6d6fec551ca9b52a83" }, { "fontloader-font-vfc.lua", "a81c29eda98cd62cbebdb6c93544b50d" }, - { "fontloader-font-map.lua", "c4a39db5ad822b348aa61bca5f4a599a" }, + { "fontloader-font-map.lua", "27ee748150e56f5f0e5f0fefc864f35e" }, { "fontloader-font-cid.lua", "22b0367742fb253deef84ef7ccf5e8de" }, { "fontloader-font-con.lua", "724e5dd14aec2d4d189f8619898004cf" }, { "fontloader-font-ini.lua", "5343de60613adb24cdd7a8d2ee1d153c" }, { "fontloader-data-con.lua", "23a0f5386d46a1c157ae82a373e35fa0" }, - { "fontloader-reference.lua", "066680a4fe38fad14eb27f56d4616104" }, + { "fontloader-reference.lua", "c256fdcc4661bf9c868002fe0f996d73" }, { "fontloader-basics-gen.lua", "4bc43036e9796fccb0b8869f4b05bf2e" }, { "mktests", "918cb50be9ee8bd645ac1a27dc501e8c" }, - { "mkstatus", "1ad0366dc654e0d374b13acb88bdc195" }, + { "mkstatus", "8bffa407d2323b24683f726fc6c1a634" }, { "mkcharacters", "bfca0e96e1e351afe7077502f9595af9" }, { "mkglyphlist", "7a8a8fdc0eac7fac2f13ec8f4e8e7aa9" }, { "mkimport", "7d62f1042e548f8b9368f26b9ba4be5c" }, - { "luaotfload-glyphlist.lua", "990d281cc4c46f219d34f2104bf31409" }, + { "luaotfload-glyphlist.lua", "a1eda1d4588777f77459f86bbe1f7500" }, { "luaotfload-characters.lua", "76415ca3ede312cad6e09038323489ae" }, - { "luaotfload-dvi.lua", "8ddc7ee49050bcef1682c054f00d3bf5" }, - { "luaotfload-tounicode.lua", "fb7b0f47a74b414177bea5f982abf1de" }, - { "luaotfload-unicode.lua", "65c7651d19fe06ec17196c22c533f768" }, - { "luaotfload-resolvers.lua", "7fd3c8d3d5a76c89227110177e7979f3" }, - { "luaotfload-parsers.lua", "a7eb408eae165d6a61d11a705cab1b98" }, - { "luaotfload-fallback.lua", "e218dc2d291d024f2d1b45da766f6cfc" }, - { "luaotfload-szss.lua", "5d97cb13052848afe1aba7e7ebc1469c" }, - { "luaotfload-scripts.lua", "b987b6592183d5cc5ec858d5792cc381" }, - { "luaotfload-multiscript.lua", "3f88fec616eb7b3f56fc5932a0f1e4d8" }, - { "luaotfload-loaders.lua", "e9f98d4904d245facab3932c505ea0f8" }, - { "luaotfload-harf-plug.lua", "09076cf26ee8160a8eb667c6be500069" }, - { "luaotfload-harf-define.lua", "16079aa19c3862e2e8f6b8cb91cf037a" }, - { "luaotfload-notdef.lua", "c06af0d71ab75a68f3445ecc6fa4e7b3" }, - { "luaotfload-embolden.lua", "04466a99226e5724ef9287ec1a28263a" }, - { "luaotfload-letterspace.lua", "000b624f54d934aff044862b7a64d4e2" }, - { "luaotfload-features.lua", "26ff83b26be22a1962db807b51a362dc" }, - { "luaotfload-database.lua", "315be26e69005984329b81aa331e1365" }, - { "luaotfload-configuration.lua", "5b294133cd45a4a6f4b94388dbfc2964" }, - { "luaotfload-colors.lua", "5989cddee9b5371697c559ec201e27e7" }, - { "luaotfload-auxiliary.lua", "56ff5ca809e974b5630cdce6d287982d" }, - { "luaotfload-filelist.lua", "007dac159b4407ea6cb04dbfbc4d4c87" }, - { "luaotfload-tool.lua", "c3dcd23a9eb499b5878381b6ec01d8c9" }, - { "luaotfload-diagnostics.lua", "90d352ac043f299aa343830084deaa00" }, - { "luaotfload-log.lua", "22964216fb42c7b07623fc43da5149ac" }, - { "luaotfload-init.lua", "8acaf9e42a9c9fa1c398a0944d1a4d50" }, + { "luaotfload-dvi.lua", "be1944354d7a1d6d4098966c9cc276b2" }, + { "luaotfload-tounicode.lua", "20fa6d02bae4274d7fbe18ff8683ca76" }, + { "luaotfload-unicode.lua", "69d17d1de56d8c0abdfb77ef7c11dfd6" }, + { "luaotfload-resolvers.lua", "490ba5d0a7b5164f9908f690507e5569" }, + { "luaotfload-parsers.lua", "daf4e973fb452f6a24d90c9a12508445" }, + { "luaotfload-fallback.lua", "56b58f94896f842ef46f25cad0be39bb" }, + { "luaotfload-szss.lua", "5512c588c3e53528f430d3dcd5342c61" }, + { "luaotfload-scripts.lua", "85cd3d5a0df9a0faaf8888fca2352d91" }, + { "luaotfload-multiscript.lua", "e84b33ced34f4ede4549e64831ba2e14" }, + { "luaotfload-loaders.lua", "4b5f6a7ba70f6cbe4eb10c98cc54e39e" }, + { "luaotfload-harf-plug.lua", "061fac6736fbe443c13fa66b1780366d" }, + { "luaotfload-harf-define.lua", "ff5743a2e17370ec42e2715e7dcd3efa" }, + { "luaotfload-notdef.lua", "a00724307cd32649101537414600da85" }, + { "luaotfload-embolden.lua", "2050240a6c33c2cfbb4573f2c3f25507" }, + { "luaotfload-letterspace.lua", "da30005de64912955267159c4310e215" }, + { "luaotfload-features.lua", "cba1c85ff9f4bb3d1af3d3e40db30536" }, + { "luaotfload-database.lua", "306e312f8d5cdebbfc8256bad91197ad" }, + { "luaotfload-configuration.lua", "b9f0b1bebfc3cb0e79688c101b428ba5" }, + { "luaotfload-colors.lua", "ceca08c762415386b78bbe6621ca2ba8" }, + { "luaotfload-auxiliary.lua", "ef7e3f0b64c4dbfc1a498ce4078195aa" }, + { "luaotfload-filelist.lua", "fb3ab92adb3e379822ed4568429b746c" }, + { "luaotfload-tool.lua", "e2f826b49e3baff8d46f2454b985cf39" }, + { "luaotfload-diagnostics.lua", "d7d7005692d1499e9685ab08f6152bf2" }, + { "luaotfload-log.lua", "20d82599e760f75a4c080d2b08dfe084" }, + { "luaotfload-init.lua", "0cf48cf4dbb22324a4b3e449830f21c5" }, { "luaotfload-main.lua", "b19c9cc34cf1d676c39f872cfb41aef6" }, }, ["notes"]={ ["committer"]="Marcel Fabian Krüger <tex@2krueger.de>", - ["description"]="v3.21/2022-03-18", - ["loader"]="fontloader-2022-02-24.lua", - ["revision"]="f3b4cee7b284e3e9d780315400166c53a4579f55", - ["timestamp"]="2022-03-18 14:09:12 +0100", + ["description"]="v3.22/2022-06-15", + ["loader"]="fontloader-2022-06-15.lua", + ["revision"]="deb1cfef038a70ebd5a5762394adcbc0889c5cbf", + ["timestamp"]="2022-06-15 19:23:05 +0200", }, }
\ No newline at end of file diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-suppress.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-suppress.lua index 71698946c38..6b105effbb8 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-suppress.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-suppress.lua @@ -5,8 +5,8 @@ assert(luaotfload_module, "This is a part of luaotfload and should not be loaded independently") { name = "luaotfload-suppress", - version = "3.21", --TAGVERSION - date = "2022-03-18", --TAGDATE + version = "3.22", --TAGVERSION + date = "2022-06-15", --TAGDATE description = "luaotfload submodule / suppress", license = "GPL v2.0", author = "Marcel Krüger" diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-szss.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-szss.lua index b1d77704cc5..760e5c29b83 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-szss.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-szss.lua @@ -5,8 +5,8 @@ assert(luaotfload_module, "This is a part of luaotfload and should not be loaded independently") { name = "luaotfload-szss", - version = "3.21", --TAGVERSION - date = "2022-03-18", --TAGDATE + version = "3.22", --TAGVERSION + date = "2022-06-15", --TAGDATE description = "luaotfload submodule / Special feature handling", license = "GPL v2.0", author = "Marcel Krüger" diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-t3.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-t3.lua new file mode 100644 index 00000000000..215ba4b918b --- /dev/null +++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-t3.lua @@ -0,0 +1,142 @@ +----------------------------------------------------------------------- +-- FILE: luaotfload-t3.lua +-- DESCRIPTION: part of luaotfload / Type 3 +----------------------------------------------------------------------- +do -- block to avoid to many local variables error + assert(luaotfload_module, "This is a part of luaotfload and should not be loaded independently") { + name = "luaotfload-t3", + version = "3.22", --TAGVERSION + date = "2022-06-15", --TAGDATE + description = "luaotfload submodule / Type 3 font handling", + license = "GPL v2.0", + author = "Marcel Krüger", + copyright = "Luaotfload Development Team", + } +end + +--[[ +local function u8_to_utf16be(s) + local d = {} + local i = 0 + for _, cp, cp2 in utf8.codes(s) do + i = i + 1 + if cp > 0x10000 then + cp = cp - 0x10000 + local high = (cp>>10) | 0xD800 + local low = (cp&0x3FF) | 0xDC00 + d[i] = string.format('%04X%04X', high, low) + else + d[i] = string.format('%04X', cp) + end + end + return table.concat(d, '', 1, i) +end +]] + +local function t3factory(basename, designsize, callback) + local count = 0 + local gid_to_t3 = {} + local t3_to_gid = {} + return function(size) + local fids = {} + return function(gid, width, unicode) + local t3id = gid_to_t3[gid] + if not t3id then + t3id = count + count = count + 1 + gid_to_t3[gid] = t3id + t3_to_gid[t3id] = gid + end + local t3fid, t3cid = t3id >> 8, ~(t3id & 0xFF) + local fid = fids[t3fid + 1] + local fontdir = fid and font.getfont(fid) + local characters = fontdir and fontdir.characters + if not (characters and characters[t3cid]) then + characters = characters or {} + -- First create the character + local char = { + width = width, + height = 0, -- We never look at these two anyway + depth = 0, + tounicode = unicode, + } + characters[t3cid] = char + if fid then -- Font already exists + font.addcharacters(fid, { + characters = { + [t3cid] = char, + }, + }) + else + fontdir = { + name = basename .. '_' .. basesize .. '_' .. t3fid, + format = 'type3', + psname = 'none', + filename = 'not_a_real_filename', -- Can't be null to ensure reuse + fullname = basename .. basesize .. '_' .. t3fid, + characters = characters, + designsize = basesize, + size = size, + cidinfo = {}, -- Can't be null to ensure reuse + attributes = '/FontDescriptor<<\z + /Type/FontDescriptor\z + /FontName/VirtualLuaFont\z + /Flags 4\z + /ItalicAngle 0\z + >>', -- TODO: Needs work + t3_handler = function(stage, _, cid) + cid = cid and assert(t3_to_gid[(t3fid << 8) | ~cid]) + return callback(stage, cid) + end + } + fid = font.define(fontdir) + fids[t3fid + 1] = fid + end + end + vf.font(fid) + vf.char(t3cid) + end + end +end + +luatexbase.add_to_callback('provide_charproc_data', function(stage, fid, ...) + local fontdir = font.getfont(fid) + if not fontdir then error'Unknown font' end + local handler = fontdir.t3_handler + if not handler then error'Missing t3handler in Type 3 font' end + return handler(stage, fid, ...) +end, 'luaotfload.t3') + +return t3factory +--[===[ + function callback(stage, cid) + if stage == 1 then + local char = assert(characters[cid]) + local head = assert(char.head) + local resource = tex.saveboxresource(head, nil--[[attributes]], nil--[[resources]], true--[[immediate]], 0--[[mode]], nil--[[margin]]) + local name = string.format('/F%i', pdf.getxformname(resource)) + local resources = characters.resources + if resources then + characters.resources = string.format('%s %s %i 0 R', resources, name, resource) + else + characters.resources = string.format('%s %i 0 R', name, resource) + end + char.resource = name + elseif stage == 2 then + local char = assert(characters[cid]) + width = char.width/65781 + return pdf.obj{ + type = 'stream', + immediate = true, + -- objnum = + -- attr = + -- compresslevel = + string = string.format('%g 0 d0 %s Do', width, char.resource) + }, width + elseif stage == 3 then + return 65781/655360, string.format('/XObject<<%s>>', characters.resources) + end + print(stage, fid, cid) + end, + } +]===] diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-tounicode.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-tounicode.lua index 155ffb2d948..96ffd562b0a 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-tounicode.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-tounicode.lua @@ -5,8 +5,8 @@ assert(luaotfload_module, "This is a part of luaotfload and should not be loaded independently") { name = "luaotfload-tounicode", - version = "3.21", --TAGVERSION - date = "2022-03-18", --TAGDATE + version = "3.22", --TAGVERSION + date = "2022-06-15", --TAGDATE description = "luaotfload submodule / tounicode", license = "GPL v2.0", author = "Hans Hagen, Khaled Hosny, Elie Roux, Philipp Gesang, Marcel Krüger", diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-unicode.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-unicode.lua index c20c81ef8eb..e504f892e25 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-unicode.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-unicode.lua @@ -5,8 +5,8 @@ assert(luaotfload_module, "This is a part of luaotfload and should not be loaded independently") { name = "luaotfload-unicode", - version = "3.21", --TAGVERSION - date = "2022-03-18", --TAGDATE + version = "3.22", --TAGVERSION + date = "2022-06-15", --TAGDATE description = "luaotfload submodule / Unicode helpers", license = "CC0 1.0 Universal", author = "Marcel Krüger" @@ -23,46 +23,6 @@ local codepoint = lpeg.S'0123456789ABCDEF'^4/function(c)return tonumber(c, 16)en local empty = {} local result = {} -local casefold do - local nl = ('#' * (1-lpeg.P'\n')^0)^-1 * '\n' - local entry = codepoint * "; " * lpeg.C(1) * ";" * lpeg.Ct((' ' * codepoint)^1) * "; " * nl - local file = lpeg.Cf( - lpeg.Ct( - lpeg.Cg(lpeg.Ct"", "C") - * lpeg.Cg(lpeg.Ct"", "F") - * lpeg.Cg(lpeg.Ct"", "S") - * lpeg.Cg(lpeg.Ct"", "T")) - * nl^0 * lpeg.Cg(entry)^0 * nl^0 * -1 - , function(t, base, class, mapping) - rawset(rawget(t, class), base, mapping) - return t - end) - - local f = io.open(kpse.find_file"CaseFolding.txt") - local data = file:match(f:read'*a') - f:close() - function casefold(s, full, special) - local first = special and data.T or empty - local second = data.C - local third = full and data.F or data.S - local result = result - for i = #result, 1, -1 do result[i] = nil end - local i = 1 - for _, c in utf8codes(s) do - local datum = first[c] or second[c] or third[c] - if datum then - local l = #datum - move(datum, 1, l, i, result) - i = i + l - else - result[i] = c - i = i + 1 - end - end - return utf8char(unpack(result)) - end -end - local alphnum_only do local niceentry = lpeg.Cg(codepoint * ';' * (1-lpeg.P';')^0 * ';' * lpeg.S'LN' * lpeg.Cc(true)) local entry = niceentry^0 * (1-lpeg.P'\n')^0 * lpeg.P'\n' @@ -232,8 +192,58 @@ do f:close() end +do + local function eq(a, b) + if not a then return false end + if not b then return false end + if a == b then return true end + if #a ~= #b then return false end + for i=1,#a do if a[i] ~= b[i] then return false end end + return true + end + local function collapse(t, inherited) + inherited = t._ or inherited + local empty = true + for k,v in next, t do + if k ~= '_' then + if eq(inherited, collapse(v, inherited)) then + t[k] = nil + else + empty = false + end + end + end + return empty and inherited + end + local function cleanup(t) + for k,v in next, t do + if not tonumber(v) then + local collapsed = collapse(v) + if collapsed and #collapsed == 1 then + v = collapsed[1] + if k == v then + v = nil + end + t[k] = v + end + end + end + end + cleanup(uppercase) + cleanup(lowercase) +end + +-- Here we manipulate the uppercase table a bit to add the `de-alt` language using capital eszett. +uppercase[0x00DF]['de-x-eszett'] = { _ = { 0x1E9E } } +uppercase[0x00DF]['de-alt'] = uppercase[0x00DF]['de-x-eszett'] + +-- Special handling for Eastern Armenian based on Unicode document L2/20-143. +uppercase[0x0587]['hy'] = { _ = { 0x0535, 0x054E } } +-- Resore Unicode behavior. This entry is redundant, but we have to be aware of it +-- if we later start to ignore unknown private use tags +uppercase[0x0587]['hy-x-yiwn'] = { _ = uppercase[0x0587]._ } + return { - casefold = casefold, alphnum_only = alphnum_only, casemapping = { uppercase = uppercase, diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload.lua index 5b65b364d85..34181d0af77 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload.lua @@ -20,8 +20,8 @@ local authors = "\z -- version number is used below! local ProvidesLuaModule = { name = "luaotfload", - version = "3.21", --TAGVERSION - date = "2022-03-18", --TAGDATE + version = "3.22", --TAGVERSION + date = "2022-06-15", --TAGDATE description = "Lua based OpenType font support", author = authors, copyright = authors, diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload.sty b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload.sty index e5dba96300c..6c9ceb1f436 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload.sty +++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload.sty @@ -39,7 +39,7 @@ \fi \ifdefined\ProvidesPackage \ProvidesPackage{luaotfload}% - [2022/03/18 v3.21 OpenType layout system] + [2022/06/15 v3.22 OpenType layout system] \fi \directlua{ if xpcall(function ()% |