summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/luatex/luaotfload
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2015-12-13 23:42:37 +0000
committerKarl Berry <karl@freefriends.org>2015-12-13 23:42:37 +0000
commit7937119a4012996251798f6a286ea904a05749f2 (patch)
tree7743f51a2906c0f0c9685f681e2a36646751290f /Master/texmf-dist/tex/luatex/luaotfload
parent3807f54388c3f5abc707c05be526c6c9c0c04623 (diff)
luaotfload (13dec15)
git-svn-id: svn://tug.org/texlive/trunk@39093 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/luatex/luaotfload')
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-2015-12-12.lua (renamed from Master/texmf-dist/tex/luatex/luaotfload/fontloader-2015-12-09.lua)3406
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/luaotfload-package.lua99
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/luaotfload-status.lua14
3 files changed, 2324 insertions, 1195 deletions
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-2015-12-09.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-2015-12-12.lua
index f4181c686c4..0eaf442ef32 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-2015-12-09.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-2015-12-12.lua
@@ -1,8 +1,53 @@
--- merged file : /home/phg/src/latex-dev/luaotfload/src/fontloader/luaotfload-package-merged.lua
--- parent file : /home/phg/src/latex-dev/luaotfload/src/fontloader/luaotfload-package.lua
--- merge date : Wed Dec 9 23:19:38 2015
+--[[info-----------------------------------------------------------------------
+ Luaotfload fontloader package
+ build 2015-12-12 20:06:58 by phg@phlegethon
+-------------------------------------------------------------------------------
-do -- begin closure to overcome local limits and interference
+ © 2015 PRAGMA ADE / ConTeXt Development Team
+
+ The code in this file is provided under the GPL v2.0 license. See the
+ file COPYING in the Luaotfload repository for details.
+
+ Report bugs to github.com/lualatex/luaotfload
+
+ This file has been assembled from components taken from Context. See
+ the Luaotfload documentation for details:
+
+ $ texdoc luaotfload
+ $ man 1 luaotfload-tool
+ $ man 5 luaotfload.conf
+
+ Included files:
+
+ · fontloader-data-con.lua
+ · fontloader-basics-nod.lua
+ · fontloader-font-ini.lua
+ · fontloader-font-con.lua
+ · fontloader-fonts-enc.lua
+ · fontloader-font-cid.lua
+ · fontloader-font-map.lua
+ · fontloader-fonts-syn.lua
+ · fontloader-font-tfm.lua
+ · fontloader-font-afm.lua
+ · fontloader-font-afk.lua
+ · fontloader-fonts-tfm.lua
+ · fontloader-font-oti.lua
+ · fontloader-font-otf.lua
+ · fontloader-font-otb.lua
+ · fontloader-fonts-inj.lua
+ · fontloader-fonts-ota.lua
+ · fontloader-fonts-otn.lua
+ · fontloader-font-otp.lua
+ · fontloader-fonts-lua.lua
+ · fontloader-font-def.lua
+ · fontloader-fonts-def.lua
+ · fontloader-fonts-ext.lua
+ · fontloader-fonts-cbk.lua
+
+--info]]-----------------------------------------------------------------------
+
+
+do --- [luaotfload, fontloader-2015-12-12.lua scope for “data-con” 675f5a0af45ffb3e0d2e2ab5d6c2e47b] ---
if not modules then modules={} end modules ['data-con']={
version=1.100,
@@ -114,9 +159,10 @@ function containers.cleanname(name)
return (gsub(lower(name),"[^%w\128-\255]+","-"))
end
-end -- closure
+end --- [luaotfload, fontloader-2015-12-12.lua scope for “data-con”] ---
-do -- begin closure to overcome local limits and interference
+
+do --- [luaotfload, fontloader-2015-12-12.lua scope for “basics-nod” d060e22b2afed6e7624f879b0e1a7d71] ---
if not modules then modules={} end modules ['luatex-fonts-nod']={
version=1.001,
@@ -158,6 +204,8 @@ local nodecodes={} for k,v in next,node.types () do nodecodes[string.gsub(v,"_"
local whatcodes={} for k,v in next,node.whatsits() do whatcodes[string.gsub(v,"_","")]=k end
local glyphcodes={ [0]="character","glyph","ligature","ghost","left","right" }
local disccodes={ [0]="discretionary","explicit","automatic","regular","first","second" }
+for i=0,#glyphcodes do glyphcodes[glyphcodes[i]]=i end
+for i=0,#disccodes do disccodes [disccodes [i]]=i end
nodes.nodecodes=nodecodes
nodes.whatcodes=whatcodes
nodes.whatsitcodes=whatcodes
@@ -306,9 +354,10 @@ end
nodes.setprop=nodes.setproperty
nodes.getprop=nodes.getproperty
-end -- closure
+end --- [luaotfload, fontloader-2015-12-12.lua scope for “basics-nod”] ---
+
-do -- begin closure to overcome local limits and interference
+do --- [luaotfload, fontloader-2015-12-12.lua scope for “font-ini” 179f0a75cda26696c1b1cd6d7fe0d8ae] ---
if not modules then modules={} end modules ['font-ini']={
version=1.001,
@@ -332,9 +381,10 @@ fonts.definers={ methods={} }
fonts.loggers={ register=function() end }
fontloader.totable=fontloader.to_table
-end -- closure
+end --- [luaotfload, fontloader-2015-12-12.lua scope for “font-ini”] ---
+
-do -- begin closure to overcome local limits and interference
+do --- [luaotfload, fontloader-2015-12-12.lua scope for “font-con” 5ae91fc3b5bb8d22b2fba27258d49971] ---
if not modules then modules={} end modules ['font-con']={
version=1.001,
@@ -462,8 +512,8 @@ end
constructors.setfactor()
function constructors.scaled(scaledpoints,designsize)
if scaledpoints<0 then
+ local factor=constructors.factor
if designsize then
- local factor=constructors.factor
if designsize>factor then
return (- scaledpoints/1000)*designsize
else
@@ -633,6 +683,7 @@ function constructors.scale(tfmdata,specification)
local hdelta=delta
local vdelta=delta
target.designsize=parameters.designsize
+ target.units=units
target.units_per_em=units
local direction=properties.direction or tfmdata.direction or 0
target.direction=direction
@@ -744,21 +795,28 @@ function constructors.scale(tfmdata,specification)
target.nomath=true
target.mathparameters=nil
end
- local italickey="italic"
- local useitalics=true
if hasmath then
- autoitalicamount=false
- elseif properties.textitalics then
- italickey="italic_correction"
- useitalics=false
- if properties.delaytextitalics then
+ local mathitalics=properties.mathitalics
+ if mathitalics==false then
+ if trace_defining then
+ report_defining("%s italics %s for font %a, fullname %a, filename %a","math",hasitalics and "ignored" or "disabled",name,fullname,filename)
+ end
+ hasitalics=false
+ autoitalicamount=false
+ end
+ else
+ local textitalics=properties.textitalics
+ if textitalics==false then
+ if trace_defining then
+ report_defining("%s italics %s for font %a, fullname %a, filename %a","text",hasitalics and "ignored" or "disabled",name,fullname,filename)
+ end
+ hasitalics=false
autoitalicamount=false
end
end
if trace_defining then
report_defining("defining tfm, name %a, fullname %a, filename %a, hscale %a, vscale %a, math %a, italics %a",
- name,fullname,filename,hdelta,vdelta,
- hasmath and "enabled" or "disabled",useitalics and "enabled" or "disabled")
+ name,fullname,filename,hdelta,vdelta,hasmath and "enabled" or "disabled",hasitalics and "enabled" or "disabled")
end
constructors.beforecopyingcharacters(target,tfmdata)
local sharedkerns={}
@@ -856,22 +914,6 @@ function constructors.scale(tfmdata,specification)
chr.right_protruding=protrusionfactor*width*vr
end
end
- if autoitalicamount then
- local vi=description.italic
- if not vi then
- local vi=description.boundingbox[3]-description.width+autoitalicamount
- if vi>0 then
- chr[italickey]=vi*hdelta
- end
- elseif vi~=0 then
- chr[italickey]=vi*hdelta
- end
- elseif hasitalics then
- local vi=description.italic
- if vi and vi~=0 then
- chr[italickey]=vi*hdelta
- end
- end
if hasmath then
local vn=character.next
if vn then
@@ -909,7 +951,11 @@ function constructors.scale(tfmdata,specification)
end
end
end
- local va=character.top_accent
+ local vi=character.vert_italic
+ if vi and vi~=0 then
+ chr.vert_italic=vi*hdelta
+ end
+ local va=character.accent
if va then
chr.top_accent=vdelta*va
end
@@ -932,6 +978,27 @@ function constructors.scale(tfmdata,specification)
chr.mathkern=kerns
end
end
+ if hasitalics then
+ local vi=character.italic
+ if vi and vi~=0 then
+ chr.italic=vi*hdelta
+ end
+ end
+ elseif autoitalicamount then
+ local vi=description.italic
+ if not vi then
+ local vi=description.boundingbox[3]-description.width+autoitalicamount
+ if vi>0 then
+ chr.italic=vi*hdelta
+ end
+ elseif vi~=0 then
+ chr.italic=vi*hdelta
+ end
+ elseif hasitalics then
+ local vi=character.italic
+ if vi and vi~=0 then
+ chr.italic=vi*hdelta
+ end
end
if haskerns then
local vk=character.kerns
@@ -994,6 +1061,7 @@ function constructors.scale(tfmdata,specification)
end
targetcharacters[unicode]=chr
end
+ properties.setitalics=hasitalics
constructors.aftercopyingcharacters(target,tfmdata)
constructors.trytosharefont(target,tfmdata)
return target
@@ -1034,11 +1102,20 @@ function constructors.finalize(tfmdata)
if not parameters.slantfactor then
parameters.slantfactor=tfmdata.slant or 0
end
- if not parameters.designsize then
- parameters.designsize=tfmdata.designsize or (factors.pt*10)
+ local designsize=parameters.designsize
+ if designsize then
+ parameters.minsize=tfmdata.minsize or designsize
+ parameters.maxsize=tfmdata.maxsize or designsize
+ else
+ designsize=factors.pt*10
+ parameters.designsize=designsize
+ parameters.minsize=designsize
+ parameters.maxsize=designsize
end
+ parameters.minsize=tfmdata.minsize or parameters.designsize
+ parameters.maxsize=tfmdata.maxsize or parameters.designsize
if not parameters.units then
- parameters.units=tfmdata.units_per_em or 1000
+ parameters.units=tfmdata.units or tfmdata.units_per_em or 1000
end
if not tfmdata.descriptions then
local descriptions={}
@@ -1101,6 +1178,7 @@ function constructors.finalize(tfmdata)
tfmdata.auto_protrude=nil
tfmdata.extend=nil
tfmdata.slant=nil
+ tfmdata.units=nil
tfmdata.units_per_em=nil
tfmdata.cache=nil
properties.finalized=true
@@ -1458,9 +1536,10 @@ function constructors.addcoreunicodes(unicodes)
return unicodes
end
-end -- closure
+end --- [luaotfload, fontloader-2015-12-12.lua scope for “font-con”] ---
-do -- begin closure to overcome local limits and interference
+
+do --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-enc” b224fe179312d924ffaf8334cf5ef15b] ---
if not modules then modules={} end modules ['luatex-font-enc']={
version=1.001,
@@ -1488,9 +1567,10 @@ setmetatable(fonts.encodings.agl,{ __index=function(t,k)
end
end })
-end -- closure
+end --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-enc”] ---
+
-do -- begin closure to overcome local limits and interference
+do --- [luaotfload, fontloader-2015-12-12.lua scope for “font-cid” 52421d1fdaa07ec4b1d936c6ff5079be] ---
if not modules then modules={} end modules ['font-cid']={
version=1.001,
@@ -1641,9 +1721,10 @@ function cid.getmap(specification)
return found
end
-end -- closure
+end --- [luaotfload, fontloader-2015-12-12.lua scope for “font-cid”] ---
+
-do -- begin closure to overcome local limits and interference
+do --- [luaotfload, fontloader-2015-12-12.lua scope for “font-map” 60c9f3d4d80944ce9123c9cddc1e57e5] ---
if not modules then modules={} end modules ['font-map']={
version=1.001,
@@ -1665,24 +1746,13 @@ local fonts=fonts or {}
local mappings=fonts.mappings or {}
fonts.mappings=mappings
local allocate=utilities.storage.allocate
-local function loadlumtable(filename)
- local lumname=file.replacesuffix(file.basename(filename),"lum")
- local lumfile=resolvers.findfile(lumname,"map") or ""
- if lumfile~="" and lfs.isfile(lumfile) then
- if trace_loading or trace_mapping then
- report_fonts("loading map table %a",lumfile)
- end
- lumunic=dofile(lumfile)
- return lumunic,lumfile
- end
-end
local hex=R("AF","09")
-local hexfour=(hex*hex*hex*hex)/function(s) return tonumber(s,16) end
-local hexsix=(hex*hex*hex*hex*hex*hex)/function(s) return tonumber(s,16) end
+local hexfour=(hex*hex*hex^-2)/function(s) return tonumber(s,16) end
+local hexsix=(hex*hex*hex^-4)/function(s) return tonumber(s,16) end
local dec=(R("09")^1)/tonumber
local period=P(".")
-local unicode=P("uni")*(hexfour*(period+P(-1))*Cc(false)+Ct(hexfour^1)*Cc(true))
-local ucode=P("u")*(hexsix*(period+P(-1))*Cc(false)+Ct(hexsix^1)*Cc(true))
+local unicode=(P("uni")+P("UNI"))*(hexfour*(period+P(-1))*Cc(false)+Ct(hexfour^1)*Cc(true))
+local ucode=(P("u")+P("U") )*(hexsix*(period+P(-1))*Cc(false)+Ct(hexsix^1)*Cc(true))
local index=P("index")*dec*Cc(false)
local parser=unicode+ucode+index
local parsers={}
@@ -1757,7 +1827,6 @@ local function fromunicode16(str)
return (tonumber(l,16))*0x400+tonumber(r,16)-0xDC00
end
end
-mappings.loadlumtable=loadlumtable
mappings.makenameparser=makenameparser
mappings.tounicode=tounicode
mappings.tounicode16=tounicode16
@@ -1788,244 +1857,162 @@ for k,v in next,overloads do
end
end
mappings.overloads=overloads
-function mappings.addtounicode(data,filename)
+function mappings.addtounicode(data,filename,checklookups)
local resources=data.resources
- local properties=data.properties
- local descriptions=data.descriptions
local unicodes=resources.unicodes
- local lookuptypes=resources.lookuptypes
if not unicodes then
return
end
+ local properties=data.properties
+ local descriptions=data.descriptions
unicodes['space']=unicodes['space'] or 32
unicodes['hyphen']=unicodes['hyphen'] or 45
unicodes['zwj']=unicodes['zwj'] or 0x200D
unicodes['zwnj']=unicodes['zwnj'] or 0x200C
- local private=fonts.constructors.privateoffset
- local unicodevector=fonts.encodings.agl.unicodes
+ local private=fonts.constructors and fonts.constructors.privateoffset or 0xF0000
+ local unicodevector=fonts.encodings.agl.unicodes or {}
+ local contextvector=fonts.encodings.agl.ctxcodes or {}
local missing={}
- local lumunic,uparser,oparser
- local cidinfo,cidnames,cidcodes,usedmap
- cidinfo=properties.cidinfo
- usedmap=cidinfo and fonts.cid.getmap(cidinfo)
+ local nofmissing=0
+ local oparser=nil
+ local cidnames=nil
+ local cidcodes=nil
+ local cidinfo=properties.cidinfo
+ 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
- uparser=makenameparser()
- local ns,nl=0,0
+ local ns=0
+ local nl=0
for unic,glyph in next,descriptions do
- local index=glyph.index
local name=glyph.name
- local r=overloads[name]
- if r then
- glyph.unicode=r.unicode
- elseif unic==-1 or unic>=private or (unic>=0xE000 and unic<=0xF8FF) or unic==0xFFFE or unic==0xFFFF then
- local unicode=lumunic and lumunic[name] or unicodevector[name]
- if unicode then
- glyph.unicode=unicode
- ns=ns+1
- end
- if (not unicode) and usedmap then
- local foundindex=lpegmatch(oparser,name)
- if foundindex then
- unicode=cidcodes[foundindex]
- if unicode then
- glyph.unicode=unicode
- ns=ns+1
- else
- local reference=cidnames[foundindex]
- if reference then
- local foundindex=lpegmatch(oparser,reference)
- if foundindex then
- unicode=cidcodes[foundindex]
- if unicode then
- glyph.unicode=unicode
- ns=ns+1
- end
- end
- if not unicode or unicode=="" then
- local foundcodes,multiple=lpegmatch(uparser,reference)
- if foundcodes then
- glyph.unicode=foundcodes
- if multiple then
- nl=nl+1
- unicode=true
- else
+ if name then
+ local index=glyph.index
+ local r=overloads[name]
+ if r then
+ glyph.unicode=r.unicode
+ elseif not unic or unic==-1 or unic>=private or (unic>=0xE000 and unic<=0xF8FF) or unic==0xFFFE or unic==0xFFFF then
+ local unicode=unicodevector[name] or contextvector[name]
+ if unicode then
+ glyph.unicode=unicode
+ ns=ns+1
+ end
+ if (not unicode) and usedmap then
+ local foundindex=lpegmatch(oparser,name)
+ if foundindex then
+ unicode=cidcodes[foundindex]
+ if unicode then
+ glyph.unicode=unicode
+ ns=ns+1
+ else
+ local reference=cidnames[foundindex]
+ if reference then
+ local foundindex=lpegmatch(oparser,reference)
+ if foundindex then
+ unicode=cidcodes[foundindex]
+ if unicode then
+ glyph.unicode=unicode
ns=ns+1
- unicode=foundcodes
+ end
+ end
+ if not unicode or unicode=="" then
+ local foundcodes,multiple=lpegmatch(uparser,reference)
+ if foundcodes then
+ glyph.unicode=foundcodes
+ if multiple then
+ nl=nl+1
+ unicode=true
+ else
+ ns=ns+1
+ unicode=foundcodes
+ end
end
end
end
end
end
end
- end
- if not unicode or unicode=="" then
- local split=lpegmatch(namesplitter,name)
- local nsplit=split and #split or 0
- local t,n={},0
- unicode=true
- for l=1,nsplit do
- local base=split[l]
- local u=unicodes[base] or unicodevector[base]
- if not u then
- break
- elseif type(u)=="table" then
- if u[1]>=private then
- unicode=false
- break
- end
- n=n+1
- t[n]=u[1]
- else
- if u>=private then
- unicode=false
- break
+ if not unicode or unicode=="" then
+ local split=lpegmatch(namesplitter,name)
+ local nsplit=split and #split or 0
+ if nsplit==0 then
+ elseif nsplit==1 then
+ local base=split[1]
+ local u=unicodes[base] or unicodevector[base] or contextvector[name]
+ if not u then
+ elseif type(u)=="table" then
+ if u[1]<private then
+ unicode=u
+ glyph.unicode=unicode
+ end
+ elseif u<private then
+ unicode=u
+ glyph.unicode=unicode
end
- n=n+1
- t[n]=u
- end
- end
- if n==0 then
- elseif n==1 then
- glyph.unicode=t[1]
- else
- glyph.unicode=t
- end
- nl=nl+1
- end
- if not unicode or unicode=="" then
- local foundcodes,multiple=lpegmatch(uparser,name)
- if foundcodes then
- glyph.unicode=foundcodes
- if multiple then
- nl=nl+1
- unicode=true
else
- ns=ns+1
- unicode=foundcodes
- end
- end
- end
- local r=overloads[unicode]
- if r then
- unicode=r.unicode
- glyph.unicode=unicode
- end
- if not unicode then
- missing[name]=true
- end
- end
- end
- if next(missing) then
- local guess={}
- local function check(gname,code,unicode)
- local description=descriptions[code]
- local variant=description.name
- if variant==gname then
- return
- end
- local unic=unicodes[variant]
- if unic==-1 or unic>=private or (unic>=0xE000 and unic<=0xF8FF) or unic==0xFFFE or unic==0xFFFF then
- else
- return
- end
- if descriptions[code].unicode then
- return
- end
- local g=guess[variant]
- if g then
- g[gname]=unicode
- else
- guess[variant]={ [gname]=unicode }
- end
- end
- for unicode,description in next,descriptions do
- local slookups=description.slookups
- if slookups then
- local gname=description.name
- for tag,data in next,slookups do
- local lookuptype=lookuptypes[tag]
- if lookuptype=="alternate" then
- for i=1,#data do
- check(gname,data[i],unicode)
- end
- elseif lookuptype=="substitution" then
- check(gname,data,unicode)
- end
- end
- end
- local mlookups=description.mlookups
- if mlookups then
- local gname=description.name
- for tag,list in next,mlookups do
- local lookuptype=lookuptypes[tag]
- if lookuptype=="alternate" then
- for i=1,#list do
- local data=list[i]
- for i=1,#data do
- check(gname,data[i],unicode)
+ local t,n={},0
+ for l=1,nsplit do
+ local base=split[l]
+ local u=unicodes[base] or unicodevector[base] or contextvector[name]
+ if not u then
+ break
+ elseif type(u)=="table" then
+ if u[1]>=private then
+ break
+ end
+ n=n+1
+ t[n]=u[1]
+ else
+ if u>=private then
+ break
+ end
+ n=n+1
+ t[n]=u
end
end
- elseif lookuptype=="substitution" then
- for i=1,#list do
- check(gname,list[i],unicode)
+ if n>0 then
+ if n==1 then
+ unicode=t[1]
+ else
+ unicode=t
+ end
+ glyph.unicode=unicode
end
end
+ nl=nl+1
end
- end
- end
- local done=true
- while done do
- done=false
- for k,v in next,guess do
- if type(v)~="number" then
- for kk,vv in next,v do
- if vv==-1 or vv>=private or (vv>=0xE000 and vv<=0xF8FF) or vv==0xFFFE or vv==0xFFFF then
- local uu=guess[kk]
- if type(uu)=="number" then
- guess[k]=uu
- done=true
- end
+ if not unicode or unicode=="" then
+ local foundcodes,multiple=lpegmatch(uparser,name)
+ if foundcodes then
+ glyph.unicode=foundcodes
+ if multiple then
+ nl=nl+1
+ unicode=true
else
- guess[k]=vv
- done=true
+ ns=ns+1
+ unicode=foundcodes
end
end
end
- end
- end
- local orphans=0
- local guessed=0
- for k,v in next,guess do
- if type(v)=="number" then
- descriptions[unicodes[k]].unicode=descriptions[v].unicode or v
- guessed=guessed+1
- else
- local t=nil
- local l=lower(k)
- local u=unicodes[l]
- if not u then
- orphans=orphans+1
- elseif u==-1 or u>=private or (u>=0xE000 and u<=0xF8FF) or u==0xFFFE or u==0xFFFF then
- local unicode=descriptions[u].unicode
- if unicode then
- descriptions[unicodes[k]].unicode=unicode
- guessed=guessed+1
- else
- orphans=orphans+1
- end
- else
- orphans=orphans+1
+ local r=overloads[unicode]
+ if r then
+ unicode=r.unicode
+ glyph.unicode=unicode
+ end
+ if not unicode then
+ missing[unic]=true
+ nofmissing=nofmissing+1
end
end
- end
- if trace_loading and orphans>0 or guessed>0 then
- report_fonts("%s glyphs with no related unicode, %s guessed, %s orphans",guessed+orphans,guessed,orphans)
+ else
end
end
+ if type(checklookups)=="function" then
+ checklookups(data,missing,nofmissing)
+ end
if trace_mapping then
for unic,glyph in table.sortedhash(descriptions) do
local name=glyph.name
@@ -2051,9 +2038,10 @@ function mappings.addtounicode(data,filename)
end
end
-end -- closure
+end --- [luaotfload, fontloader-2015-12-12.lua scope for “font-map”] ---
+
-do -- begin closure to overcome local limits and interference
+do --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-syn” 9729d0e49b770f78e88dab86739e0297] ---
if not modules then modules={} end modules ['luatex-fonts-syn']={
version=1.001,
@@ -2129,9 +2117,10 @@ function fonts.names.ignoredfile(filename)
return false
end
-end -- closure
+end --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-syn”] ---
+
-do -- begin closure to overcome local limits and interference
+do --- [luaotfload, fontloader-2015-12-12.lua scope for “font-tfm” bbee5eddb11211fb0a8d993db678bf3c] ---
if not modules then modules={} end modules ['font-tfm']={
version=1.001,
@@ -2153,6 +2142,9 @@ local readers=fonts.readers
local constructors=fonts.constructors
local encodings=fonts.encodings
local tfm=constructors.newhandler("tfm")
+tfm.version=1.000
+tfm.maxnestingdepth=5
+tfm.maxnestingsize=65536*1024
local tfmfeatures=constructors.newfeatures("tfm")
local registertfmfeature=tfmfeatures.register
constructors.resolvevirtualtoo=false
@@ -2165,9 +2157,11 @@ function tfm.setfeatures(tfmdata,features)
return {}
end
end
+local depth={}
local function read_from_tfm(specification)
local filename=specification.filename
local size=specification.size
+ depth[filename]=(depth[filename] or 0)+1
if trace_defining then
report_defining("loading tfm file %a at size %s",filename,size)
end
@@ -2211,6 +2205,25 @@ local function read_from_tfm(specification)
end
properties.virtualized=true
tfmdata.fonts=vfdata.fonts
+ tfmdata.type="virtual"
+ local fontlist=vfdata.fonts
+ local name=file.nameonly(filename)
+ for i=1,#fontlist do
+ local n=fontlist[i].name
+ local s=fontlist[i].size
+ local d=depth[filename]
+ s=constructors.scaled(s,vfdata.designsize)
+ if d>tfm.maxnestingdepth then
+ report_defining("too deeply nested virtual font %a with size %a, max nesting depth %s",n,s,tfm.maxnestingdepth)
+ fontlist[i]={ id=0 }
+ elseif (d>1) and (s>tfm.maxnestingsize) then
+ report_defining("virtual font %a exceeds size %s",n,s)
+ fontlist[i]={ id=0 }
+ else
+ local t,id=fonts.constructors.readanddefine(n,s)
+ fontlist[i]={ id=id }
+ end
+ end
end
end
end
@@ -2226,7 +2239,10 @@ local function read_from_tfm(specification)
properties.haslogatures=true
resources.unicodes={}
resources.lookuptags={}
+ depth[filename]=depth[filename]-1
return tfmdata
+ else
+ depth[filename]=depth[filename]-1
end
end
local function check_tfm(specification,fullname)
@@ -2259,9 +2275,10 @@ function readers.tfm(specification)
return check_tfm(specification,fullname)
end
-end -- closure
+end --- [luaotfload, fontloader-2015-12-12.lua scope for “font-tfm”] ---
-do -- begin closure to overcome local limits and interference
+
+do --- [luaotfload, fontloader-2015-12-12.lua scope for “font-afm” ece4863414d6b38c2e577110c9b55bd3] ---
if not modules then modules={} end modules ['font-afm']={
version=1.001,
@@ -2339,7 +2356,7 @@ local keys={}
function keys.FontName (data,line) data.metadata.fontname=strip (line)
data.metadata.fullname=strip (line) end
function keys.ItalicAngle (data,line) data.metadata.italicangle=tonumber (line) end
-function keys.IsFixedPitch(data,line) data.metadata.isfixedpitch=toboolean(line,true) end
+function keys.IsFixedPitch(data,line) data.metadata.monospaced=toboolean(line,true) end
function keys.CharWidth (data,line) data.metadata.charwidth=tonumber (line) end
function keys.XHeight (data,line) data.metadata.xheight=tonumber (line) end
function keys.Descender (data,line) data.metadata.descender=tonumber (line) end
@@ -2761,7 +2778,7 @@ local function copytotfm(data)
local emdash=0x2014
local spacer="space"
local spaceunits=500
- local monospaced=metadata.isfixedpitch
+ local monospaced=metadata.monospaced
local charwidth=metadata.charwidth
local italicangle=metadata.italicangle
local charxheight=metadata.xheight and metadata.xheight>0 and metadata.xheight
@@ -3113,9 +3130,10 @@ function readers.pfb(specification,method)
return readers.afm(specification,method)
end
-end -- closure
+end --- [luaotfload, fontloader-2015-12-12.lua scope for “font-afm”] ---
+
-do -- begin closure to overcome local limits and interference
+do --- [luaotfload, fontloader-2015-12-12.lua scope for “font-afk” b36a76ceb835f41f8c05b471000ddc14] ---
if not modules then modules={} end modules ['font-afk']={
version=1.001,
@@ -3282,9 +3300,10 @@ fonts.handlers.afm.helpdata={
}
}
-end -- closure
+end --- [luaotfload, fontloader-2015-12-12.lua scope for “font-afk”] ---
-do -- begin closure to overcome local limits and interference
+
+do --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-tfm” 8fd3865240e4e87e99e0739abeda2322] ---
if not modules then modules={} end modules ['luatex-fonts-tfm']={
version=1.001,
@@ -3322,9 +3341,10 @@ function fonts.readers.tfm(specification)
end
end
-end -- closure
+end --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-tfm”] ---
+
-do -- begin closure to overcome local limits and interference
+do --- [luaotfload, fontloader-2015-12-12.lua scope for “font-oti” 035a51b49029d7da48453ec5f1d65018] ---
if not modules then modules={} end modules ['font-oti']={
version=1.001,
@@ -3404,9 +3424,10 @@ registerotffeature {
}
}
-end -- closure
+end --- [luaotfload, fontloader-2015-12-12.lua scope for “font-oti”] ---
+
-do -- begin closure to overcome local limits and interference
+do --- [luaotfload, fontloader-2015-12-12.lua scope for “font-otf” b1a5f4340125198b1b0489ef903dd267] ---
if not modules then modules={} end modules ['font-otf']={
version=1.001,
@@ -3416,12 +3437,10 @@ if not modules then modules={} end modules ['font-otf']={
license="see context related readme files"
}
local utfbyte=utf.byte
-local format,gmatch,gsub,find,match,lower,strip=string.format,string.gmatch,string.gsub,string.find,string.match,string.lower,string.strip
+local gmatch,gsub,find,match,lower,strip=string.gmatch,string.gsub,string.find,string.match,string.lower,string.strip
local type,next,tonumber,tostring=type,next,tonumber,tostring
local abs=math.abs
-local insert=table.insert
-local lpegmatch=lpeg.match
-local reversed,concat,remove,sortedkeys=table.reversed,table.concat,table.remove,table.sortedkeys
+local reversed,concat,insert,remove,sortedkeys=table.reversed,table.concat,table.insert,table.remove,table.sortedkeys
local ioflush=io.flush
local fastcopy,tohash,derivetable=table.fastcopy,table.tohash,table.derive
local formatters=string.formatters
@@ -3435,6 +3454,7 @@ local stoptiming=statistics.stoptiming
local elapsedtime=statistics.elapsedtime
local findbinfile=resolvers.findbinfile
local trace_private=false registertracker("otf.private",function(v) trace_private=v end)
+local trace_subfonts=false registertracker("otf.subfonts",function(v) trace_subfonts=v end)
local trace_loading=false registertracker("otf.loading",function(v) trace_loading=v end)
local trace_features=false registertracker("otf.features",function(v) trace_features=v end)
local trace_dynamics=false registertracker("otf.dynamics",function(v) trace_dynamics=v end)
@@ -3447,7 +3467,7 @@ local report_otf=logs.reporter("fonts","otf loading")
local fonts=fonts
local otf=fonts.handlers.otf
otf.glists={ "gsub","gpos" }
-otf.version=2.803
+otf.version=2.819
otf.cache=containers.define("fonts","otf",otf.version,true)
local hashes=fonts.hashes
local definers=fonts.definers
@@ -3624,10 +3644,10 @@ local ordered_enhancers={
"reorganize subtables",
"check glyphs",
"check metadata",
- "check extra features",
"prepare tounicode",
"check encoding",
"add duplicates",
+ "expand lookups",
"cleanup tables",
"compact lookups",
"purge names",
@@ -3764,6 +3784,7 @@ function otf.load(filename,sub,featurefile)
end
end
if reload then
+ starttiming("fontloader")
report_otf("loading %a, hash %a",filename,hash)
local fontdata,messages
if sub then
@@ -3797,6 +3818,7 @@ function otf.load(filename,sub,featurefile)
data={
size=size,
time=time,
+ subfont=sub,
format=otf_format(filename),
featuredata=featurefiles,
resources={
@@ -3824,7 +3846,6 @@ function otf.load(filename,sub,featurefile)
tounicodetable=Ct(splitter),
},
}
- starttiming(data)
report_otf("file size: %s",size)
enhancers.apply(data,filename,fontdata)
local packtime={}
@@ -3841,10 +3862,10 @@ function otf.load(filename,sub,featurefile)
if cleanup>1 then
collectgarbage("collect")
end
- stoptiming(data)
+ stoptiming("fontloader")
if elapsedtime then
- report_otf("preprocessing and caching time %s, packtime %s",
- elapsedtime(data),packdata and elapsedtime(packtime) or 0)
+ report_otf("loading, optimizing, packing and caching time %s, pack time %s",
+ elapsedtime("fontloader"),packdata and elapsedtime(packtime) or 0)
end
close_font(fontdata)
if cleanup>3 then
@@ -3855,6 +3876,7 @@ function otf.load(filename,sub,featurefile)
collectgarbage("collect")
end
else
+ stoptiming("fontloader")
data=nil
report_otf("loading failed due to read error")
end
@@ -3896,6 +3918,7 @@ function otf.load(filename,sub,featurefile)
applyruntimefixes(filename,data)
end
enhance("add dimensions",data,filename,nil,false)
+enhance("check extra features",data,filename)
if trace_sequences then
showfeatureorder(data,filename)
end
@@ -3980,6 +4003,7 @@ local function somecopy(old)
end
end
actions["prepare glyphs"]=function(data,filename,raw)
+ local tableversion=tonumber(raw.table_version) or 0
local rawglyphs=raw.glyphs
local rawsubfonts=raw.subfonts
local rawcidinfo=raw.cidinfo
@@ -4000,65 +4024,114 @@ actions["prepare glyphs"]=function(data,filename,raw)
local cidmap=fonts.cid.getmap(rawcidinfo)
if cidmap then
rawcidinfo.usedname=cidmap.usedname
- local nofnames,nofunicodes=0,0
- local cidunicodes,cidnames=cidmap.unicodes,cidmap.names
+ local nofnames=0
+ local nofunicodes=0
+ local cidunicodes=cidmap.unicodes
+ local cidnames=cidmap.names
+ local cidtotal=0
+ local unique=trace_subfonts and {}
for cidindex=1,#rawsubfonts do
local subfont=rawsubfonts[cidindex]
local cidglyphs=subfont.glyphs
if includesubfonts then
metadata.subfonts[cidindex]=somecopy(subfont)
end
- for index=0,subfont.glyphcnt-1 do
- local glyph=cidglyphs[index]
- if glyph then
- local unicode=glyph.unicode
- if unicode>=0x00E000 and unicode<=0x00F8FF then
- unicode=-1
- elseif unicode>=0x0F0000 and unicode<=0x0FFFFD then
- unicode=-1
- elseif unicode>=0x100000 and unicode<=0x10FFFD then
- unicode=-1
- end
- local name=glyph.name or cidnames[index]
- if not unicode or unicode==-1 then
- unicode=cidunicodes[index]
- end
- if unicode and descriptions[unicode] then
- if trace_private then
- report_otf("preventing glyph %a at index %H to overload unicode %U",name or "noname",index,unicode)
+ local cidcnt,cidmin,cidmax
+ if tableversion>0.3 then
+ cidcnt=subfont.glyphcnt
+ cidmin=subfont.glyphmin
+ cidmax=subfont.glyphmax
+ else
+ cidcnt=subfont.glyphcnt
+ cidmin=0
+ cidmax=cidcnt-1
+ end
+ if trace_subfonts then
+ local cidtot=cidmax-cidmin+1
+ cidtotal=cidtotal+cidtot
+ report_otf("subfont: %i, min: %i, max: %i, cnt: %i, n: %i",cidindex,cidmin,cidmax,cidtot,cidcnt)
+ end
+ if cidcnt>0 then
+ for cidslot=cidmin,cidmax do
+ local glyph=cidglyphs[cidslot]
+ if glyph then
+ local index=tableversion>0.3 and glyph.orig_pos or cidslot
+ if trace_subfonts then
+ unique[index]=true
end
- unicode=-1
- end
- if not unicode or unicode==-1 then
- if not name then
- name=format("u%06X.ctx",private)
+ local unicode=glyph.unicode
+ if unicode>=0x00E000 and unicode<=0x00F8FF then
+ unicode=-1
+ elseif unicode>=0x0F0000 and unicode<=0x0FFFFD then
+ unicode=-1
+ elseif unicode>=0x100000 and unicode<=0x10FFFD then
+ unicode=-1
end
- unicode=private
- unicodes[name]=private
- if trace_private then
- report_otf("glyph %a at index %H is moved to private unicode slot %U",name,index,private)
+ local name=glyph.name or cidnames[index]
+ if not unicode or unicode==-1 then
+ unicode=cidunicodes[index]
end
- private=private+1
- nofnames=nofnames+1
- else
- if not name then
- name=format("u%06X.ctx",unicode)
+ if unicode and descriptions[unicode] then
+ if trace_private then
+ report_otf("preventing glyph %a at index %H to overload unicode %U",name or "noname",index,unicode)
+ end
+ unicode=-1
end
- unicodes[name]=unicode
- nofunicodes=nofunicodes+1
- end
- indices[index]=unicode
- local description={
- boundingbox=glyph.boundingbox,
- name=name or "unknown",
- cidindex=cidindex,
- index=index,
- glyph=glyph,
- }
- descriptions[unicode]=description
+ if not unicode or unicode==-1 then
+ if not name then
+ name=formatters["u%06X.ctx"](private)
+ end
+ unicode=private
+ unicodes[name]=private
+ if trace_private then
+ report_otf("glyph %a at index %H is moved to private unicode slot %U",name,index,private)
+ end
+ private=private+1
+ nofnames=nofnames+1
+ else
+ if not name then
+ name=formatters["u%06X.ctx"](unicode)
+ end
+ unicodes[name]=unicode
+ nofunicodes=nofunicodes+1
+ end
+ indices[index]=unicode
+ local description={
+ boundingbox=glyph.boundingbox,
+ name=name or "unknown",
+ cidindex=cidindex,
+ index=cidslot,
+ glyph=glyph,
+ }
+ descriptions[unicode]=description
+ local altuni=glyph.altuni
+ if altuni then
+ for i=1,#altuni do
+ local a=altuni[i]
+ local u=a.unicode
+ if u~=unicode then
+ local v=a.variant
+ if v then
+ local vv=variants[v]
+ if vv then
+ vv[u]=unicode
+ else
+ vv={ [u]=unicode }
+ variants[v]=vv
+ end
+ end
+ end
+ end
+ end
+ end
end
+ else
+ report_otf("potential problem: no glyphs found in subfont %i",cidindex)
end
end
+ if trace_subfonts then
+ report_otf("nofglyphs: %i, unique: %i",cidtotal,table.count(unique))
+ end
if trace_loading then
report_otf("cid font remapped, %s unicode points, %s symbolic names, %s glyphs",nofunicodes,nofnames,nofunicodes+nofnames)
end
@@ -4069,68 +4142,77 @@ actions["prepare glyphs"]=function(data,filename,raw)
report_otf("font %a has no glyphs",filename)
end
else
- for index=0,raw.glyphcnt-1 do
- local glyph=rawglyphs[index]
- if glyph then
- local unicode=glyph.unicode
- local name=glyph.name
- if not unicode or unicode==-1 then
- unicode=private
- unicodes[name]=private
- if trace_private then
- report_otf("glyph %a at index %H is moved to private unicode slot %U",name,index,private)
- end
- private=private+1
- else
- if unicode>criterium then
- local taken=descriptions[unicode]
- if taken then
- if unicode>=private then
- private=unicode+1
+ local cnt=raw.glyphcnt or 0
+ local min=tableversion>0.3 and raw.glyphmin or 0
+ local max=tableversion>0.3 and raw.glyphmax or (raw.glyphcnt-1)
+ if cnt>0 then
+ for index=min,max do
+ local glyph=rawglyphs[index]
+ if glyph then
+ local unicode=glyph.unicode
+ local name=glyph.name
+ if not unicode or unicode==-1 then
+ unicode=private
+ unicodes[name]=private
+ if trace_private then
+ report_otf("glyph %a at index %H is moved to private unicode slot %U",name,index,private)
+ end
+ private=private+1
+ else
+ if unicode>criterium then
+ local taken=descriptions[unicode]
+ if taken then
+ if unicode>=private then
+ private=unicode+1
+ else
+ private=private+1
+ end
+ descriptions[private]=taken
+ unicodes[taken.name]=private
+ indices[taken.index]=private
+ if trace_private then
+ report_otf("slot %U is moved to %U due to private in font",unicode)
+ end
else
- private=private+1
- end
- descriptions[private]=taken
- unicodes[taken.name]=private
- indices[taken.index]=private
- if trace_private then
- report_otf("slot %U is moved to %U due to private in font",unicode)
- end
- else
- if unicode>=private then
- private=unicode+1
+ if unicode>=private then
+ private=unicode+1
+ end
end
end
+ unicodes[name]=unicode
end
- unicodes[name]=unicode
- end
- indices[index]=unicode
- descriptions[unicode]={
- boundingbox=glyph.boundingbox,
- name=name,
- index=index,
- glyph=glyph,
- }
- local altuni=glyph.altuni
- if altuni then
- for i=1,#altuni do
- local a=altuni[i]
- local u=a.unicode
- local v=a.variant
- if v then
- local vv=variants[v]
- if vv then
- vv[u]=unicode
- else
- vv={ [u]=unicode }
- variants[v]=vv
+ indices[index]=unicode
+ descriptions[unicode]={
+ boundingbox=glyph.boundingbox,
+ name=name,
+ index=index,
+ glyph=glyph,
+ }
+ local altuni=glyph.altuni
+ if altuni then
+ for i=1,#altuni do
+ local a=altuni[i]
+ local u=a.unicode
+ if u~=unicode then
+ local v=a.variant
+ if v then
+ local vv=variants[v]
+ if vv then
+ vv[u]=unicode
+ else
+ vv={ [u]=unicode }
+ variants[v]=vv
+ end
+ end
end
end
end
+ else
+ report_otf("potential problem: glyph %U is used but empty",index)
end
- else
- report_otf("potential problem: glyph %U is used but empty",index)
end
+ else
+ report_otf("potential problem: no glyphs found")
end
end
resources.private=private
@@ -4226,7 +4308,7 @@ actions["add duplicates"]=function(data,filename,raw)
end
if u>0 then
local duplicate=table.copy(description)
- duplicate.comment=format("copy of U+%05X",unicode)
+ duplicate.comment=formatters["copy of %U"](unicode)
descriptions[u]=duplicate
if trace_loading then
report_otf("duplicating %U to %U with index %H (%s kerns)",unicode,u,description.index,n)
@@ -4247,7 +4329,7 @@ actions["analyze glyphs"]=function(data,filename,raw)
local marks={}
for unicode,description in next,descriptions do
local glyph=description.glyph
- local italic=glyph.italic_correction
+ local italic=glyph.italic_correction
if not italic then
elseif italic==0 then
else
@@ -4308,7 +4390,8 @@ end
actions["reorganize features"]=function(data,filename,raw)
local features={}
data.resources.features=features
- for k,what in next,otf.glists do
+ for k=1,#otf.glists do
+ local what=otf.glists[k]
local dw=raw[what]
if dw then
local f={}
@@ -4390,8 +4473,9 @@ actions["reorganize subtables"]=function(data,filename,raw)
local lookups={}
local chainedfeatures={}
resources.sequences=sequences
- resources.lookups=lookups
- for _,what in next,otf.glists do
+ resources.lookups=lookups
+ for k=1,#otf.glists do
+ local what=otf.glists[k]
local dw=raw[what]
if dw then
for k=1,#dw do
@@ -4565,12 +4649,15 @@ local function r_uncover(splitter,cache,cover,replacements)
end
actions["reorganize lookups"]=function(data,filename,raw)
if data.lookups then
- local splitter=data.helpers.tounicodetable
+ local helpers=data.helpers
+ local duplicates=data.resources.duplicates
+ local splitter=helpers.tounicodetable
local t_u_cache={}
local s_u_cache=t_u_cache
local t_h_cache={}
local s_h_cache=t_h_cache
local r_u_cache={}
+ helpers.matchcache=t_h_cache
for _,lookup in next,data.lookups do
local rules=lookup.rules
if rules then
@@ -4716,6 +4803,44 @@ actions["reorganize lookups"]=function(data,filename,raw)
end
end
end
+actions["expand lookups"]=function(data,filename,raw)
+ if data.lookups then
+ local cache=data.helpers.matchcache
+ if cache then
+ local duplicates=data.resources.duplicates
+ for key,hash in next,cache do
+ local done=nil
+ for key in next,hash do
+ local unicode=duplicates[key]
+ if not unicode then
+ elseif type(unicode)=="table" then
+ for i=1,#unicode do
+ local u=unicode[i]
+ if hash[u] then
+ elseif done then
+ done[u]=key
+ else
+ done={ [u]=key }
+ end
+ end
+ else
+ if hash[unicode] then
+ elseif done then
+ done[unicode]=key
+ else
+ done={ [unicode]=key }
+ end
+ end
+ end
+ if done then
+ for u in next,done do
+ hash[u]=true
+ end
+ end
+ end
+ end
+ end
+end
local function check_variants(unicode,the_variants,splitter,unicodes)
local variants=the_variants.variants
if variants then
@@ -4756,11 +4881,11 @@ local function check_variants(unicode,the_variants,splitter,unicodes)
parts=nil
end
end
- local italic_correction=the_variants.italic_correction
- if italic_correction and italic_correction==0 then
- italic_correction=nil
+ local italic=the_variants.italic
+ if italic and italic==0 then
+ italic=nil
end
- return variants,parts,italic_correction
+ return variants,parts,italic
end
actions["analyze math"]=function(data,filename,raw)
if raw.math then
@@ -4770,13 +4895,14 @@ actions["analyze math"]=function(data,filename,raw)
for unicode,description in next,data.descriptions do
local glyph=description.glyph
local mathkerns=glyph.mathkern
- local horiz_variants=glyph.horiz_variants
- local vert_variants=glyph.vert_variants
- local top_accent=glyph.top_accent
- if mathkerns or horiz_variants or vert_variants or top_accent then
+ local hvariants=glyph.horiz_variants
+ local vvariants=glyph.vert_variants
+ local accent=glyph.top_accent
+ local italic=glyph.italic_correction
+ if mathkerns or hvariants or vvariants or accent or italic then
local math={}
- if top_accent then
- math.top_accent=top_accent
+ if accent then
+ math.accent=accent
end
if mathkerns then
for k,v in next,mathkerns do
@@ -4792,15 +4918,14 @@ actions["analyze math"]=function(data,filename,raw)
end
math.kerns=mathkerns
end
- if horiz_variants then
- math.horiz_variants,math.horiz_parts,math.horiz_italic_correction=check_variants(unicode,horiz_variants,splitter,unicodes)
+ if hvariants then
+ math.hvariants,math.hparts,math.hitalic=check_variants(unicode,hvariants,splitter,unicodes)
end
- if vert_variants then
- math.vert_variants,math.vert_parts,math.vert_italic_correction=check_variants(unicode,vert_variants,splitter,unicodes)
+ if vvariants then
+ math.vvariants,math.vparts,math.vitalic=check_variants(unicode,vvariants,splitter,unicodes)
end
- local italic_correction=description.italic
- if italic_correction and italic_correction~=0 then
- math.italic_correction=italic_correction
+ if italic and italic~=0 then
+ math.italic=italic
end
description.math=math
end
@@ -4868,7 +4993,7 @@ actions["merge kern classes"]=function(data,filename,raw)
local subtable=subtables[s]
local kernclass=subtable.kernclass
local lookup=subtable.lookup or subtable.name
- if kernclass then
+ if kernclass then
if #kernclass>0 then
kernclass=kernclass[1]
lookup=type(kernclass.lookup)=="string" and kernclass.lookup or lookup
@@ -4893,14 +5018,16 @@ actions["merge kern classes"]=function(data,filename,raw)
if splt then
local extrakerns={}
local baseoffset=(fk-1)*maxseconds
- for sk=2,maxseconds do
+ for sk=2,maxseconds do
local sv=seconds[sk]
- local splt=split[sv]
- if splt then
- local offset=offsets[baseoffset+sk]
- if offset then
- for i=1,#splt do
- extrakerns[splt[i]]=offset
+ if sv then
+ local splt=split[sv]
+ if splt then
+ local offset=offsets[baseoffset+sk]
+ if offset then
+ for i=1,#splt do
+ extrakerns[splt[i]]=offset
+ end
end
end
end
@@ -4957,7 +5084,7 @@ actions["merge kern classes"]=function(data,filename,raw)
report_otf("%s kern overloads ignored",ignored)
end
if blocked>0 then
- report_otf("%s succesive kerns blocked",blocked)
+ report_otf("%s successive kerns blocked",blocked)
end
end
end
@@ -4986,16 +5113,18 @@ actions["check metadata"]=function(data,filename,raw)
ttftables[i].data="deleted"
end
end
+ local names=raw.names
if metadata.validation_state and table.contains(metadata.validation_state,"bad_ps_fontname") then
local function valid(what)
- local names=raw.names
- for i=1,#names do
- local list=names[i]
- local names=list.names
- if names then
- local name=names[what]
- if name and valid_ps_name(name) then
- return name
+ if names then
+ for i=1,#names do
+ local list=names[i]
+ local names=list.names
+ if names then
+ local name=names[what]
+ if name and valid_ps_name(name) then
+ return name
+ end
end
end
end
@@ -5018,6 +5147,28 @@ actions["check metadata"]=function(data,filename,raw)
check("fontname")
check("fullname")
end
+ if names then
+ local psname=metadata.psname
+ if not psname or psname=="" then
+ for i=1,#names do
+ local name=names[i]
+ if lower(name.lang)=="english (us)" then
+ local specification=name.names
+ if specification then
+ local postscriptname=specification.postscriptname
+ if postscriptname then
+ psname=postscriptname
+ end
+ end
+ end
+ break
+ end
+ end
+ if psname~=metadata.fontname then
+ report_otf("fontname %a, fullname %a, psname %a",metadata.fontname,metadata.fullname,psname)
+ end
+ metadata.psname=psname
+ end
end
actions["cleanup tables"]=function(data,filename,raw)
local duplicates=data.resources.duplicates
@@ -5113,7 +5264,7 @@ actions["reorganize glyph lookups"]=function(data,filename,raw)
end
end
local zero={ 0,0 }
-actions["reorganize glyph anchors"]=function(data,filename,raw)
+actions["reorganize glyph anchors"]=function(data,filename,raw)
local descriptions=data.descriptions
for unicode,description in next,descriptions do
local anchors=description.glyph.anchors
@@ -5315,9 +5466,13 @@ local function copytotfm(data,cache_id)
local spaceunits=500
local spacer="space"
local designsize=metadata.designsize or metadata.design_size or 100
+ local minsize=metadata.minsize or metadata.design_range_bottom or designsize
+ local maxsize=metadata.maxsize or metadata.design_range_top or designsize
local mathspecs=metadata.math
if designsize==0 then
designsize=100
+ minsize=100
+ maxsize=100
end
if mathspecs then
for name,value in next,mathspecs do
@@ -5332,8 +5487,10 @@ local function copytotfm(data,cache_id)
local d=descriptions[unicode]
local m=d.math
if m then
- local variants=m.horiz_variants
- local parts=m.horiz_parts
+ local italic=m.italic
+ local vitalic=m.vitalic
+ local variants=m.hvariants
+ local parts=m.hparts
if variants then
local c=character
for i=1,#variants do
@@ -5344,9 +5501,10 @@ local function copytotfm(data,cache_id)
c.horiz_variants=parts
elseif parts then
character.horiz_variants=parts
+ italic=m.hitalic
end
- local variants=m.vert_variants
- local parts=m.vert_parts
+ local variants=m.vvariants
+ local parts=m.vparts
if variants then
local c=character
for i=1,#variants do
@@ -5358,13 +5516,15 @@ local function copytotfm(data,cache_id)
elseif parts then
character.vert_variants=parts
end
- local italic_correction=m.vert_italic_correction
- if italic_correction then
- character.vert_italic_correction=italic_correction
+ if italic and italic~=0 then
+ character.italic=italic
end
- local top_accent=m.top_accent
- if top_accent then
- character.top_accent=top_accent
+ if vitalic and vitalic~=0 then
+ character.vert_italic=vitalic
+ end
+ local accent=m.accent
+ if accent then
+ character.accent=accent
end
local kerns=m.kerns
if kerns then
@@ -5376,14 +5536,14 @@ local function copytotfm(data,cache_id)
local filename=constructors.checkedfilename(resources)
local fontname=metadata.fontname
local fullname=metadata.fullname or fontname
- local psname=fontname or fullname
- local units=metadata.units_per_em or 1000
+ local psname=metadata.psname or fontname or fullname
+ local units=metadata.units or metadata.units_per_em or 1000
if units==0 then
units=1000
- metadata.units_per_em=1000
+ metadata.units=1000
report_otf("changing %a units to %a",0,units)
end
- local monospaced=metadata.isfixedpitch or (pfminfo.panose and pfminfo.panose.proportion=="Monospaced")
+ local monospaced=metadata.monospaced or metadata.isfixedpitch or (pfminfo.panose and pfminfo.panose.proportion=="Monospaced")
local charwidth=pfminfo.avgwidth
local charxheight=pfminfo.os2_xheight and pfminfo.os2_xheight>0 and pfminfo.os2_xheight
local italicangle=metadata.italicangle
@@ -5448,8 +5608,10 @@ local function copytotfm(data,cache_id)
end
end
parameters.designsize=(designsize/10)*65536
- parameters.ascender=abs(metadata.ascent or 0)
- parameters.descender=abs(metadata.descent or 0)
+ parameters.minsize=(minsize/10)*65536
+ parameters.maxsize=(maxsize/10)*65536
+ parameters.ascender=abs(metadata.ascender or metadata.ascent or 0)
+ parameters.descender=abs(metadata.descender or metadata.descent or 0)
parameters.units=units
properties.space=spacer
properties.encodingbytes=2
@@ -5628,10 +5790,104 @@ function otf.scriptandlanguage(tfmdata,attr)
local properties=tfmdata.properties
return properties.script or "dflt",properties.language or "dflt"
end
+local function justset(coverage,unicode,replacement)
+ coverage[unicode]=replacement
+end
+otf.coverup={
+ stepkey="subtables",
+ actions={
+ substitution=justset,
+ alternate=justset,
+ multiple=justset,
+ ligature=justset,
+ kern=justset,
+ },
+ register=function(coverage,lookuptype,format,feature,n,descriptions,resources)
+ local name=formatters["ctx_%s_%s"](feature,n)
+ if lookuptype=="kern" then
+ resources.lookuptypes[name]="position"
+ else
+ resources.lookuptypes[name]=lookuptype
+ end
+ for u,c in next,coverage do
+ local description=descriptions[u]
+ local slookups=description.slookups
+ if slookups then
+ slookups[name]=c
+ else
+ description.slookups={ [name]=c }
+ end
+ end
+ return name
+ end
+}
+local function getgsub(tfmdata,k,kind)
+ local description=tfmdata.descriptions[k]
+ if description then
+ local slookups=description.slookups
+ if slookups then
+ local shared=tfmdata.shared
+ local rawdata=shared and shared.rawdata
+ if rawdata then
+ local lookuptypes=rawdata.resources.lookuptypes
+ if lookuptypes then
+ local properties=tfmdata.properties
+ local validlookups,lookuplist=otf.collectlookups(rawdata,kind,properties.script,properties.language)
+ if validlookups then
+ for l=1,#lookuplist do
+ local lookup=lookuplist[l]
+ local found=slookups[lookup]
+ if found then
+ return found,lookuptypes[lookup]
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
+otf.getgsub=getgsub
+function otf.getsubstitution(tfmdata,k,kind,value)
+ local found,kind=getgsub(tfmdata,k,kind)
+ if not found then
+ elseif kind=="substitution" then
+ return found
+ elseif kind=="alternate" then
+ local choice=tonumber(value) or 1
+ return found[choice] or found[1] or k
+ end
+ return k
+end
+otf.getalternate=otf.getsubstitution
+function otf.getmultiple(tfmdata,k,kind)
+ local found,kind=getgsub(tfmdata,k,kind)
+ if found and kind=="multiple" then
+ return found
+ end
+ return { k }
+end
+function otf.getkern(tfmdata,left,right,kind)
+ local kerns=getgsub(tfmdata,left,kind or "kern",true)
+ if kerns then
+ local found=kerns[right]
+ local kind=type(found)
+ if kind=="table" then
+ found=found[1][3]
+ elseif kind~="number" then
+ found=false
+ end
+ if found then
+ return found*tfmdata.parameters.factor
+ end
+ end
+ return 0
+end
+
+end --- [luaotfload, fontloader-2015-12-12.lua scope for “font-otf”] ---
-end -- closure
-do -- begin closure to overcome local limits and interference
+do --- [luaotfload, fontloader-2015-12-12.lua scope for “font-otb” 93461f2f412a9b33b35a273c09b64291] ---
if not modules then modules={} end modules ['font-otb']={
version=1.001,
@@ -6158,8 +6414,8 @@ local function featuresinitializer(tfmdata,value)
local collectlookups=otf.collectlookups
local rawdata=tfmdata.shared.rawdata
local properties=tfmdata.properties
- local script=properties.script
- local language=properties.language
+ local script=properties.script
+ local language=properties.language
local basesubstitutions=rawdata.resources.features.gsub
local basepositionings=rawdata.resources.features.gpos
if basesubstitutions or basepositionings then
@@ -6216,9 +6472,10 @@ directives.register("fonts.otf.loader.basemethod",function(v)
end
end)
-end -- closure
+end --- [luaotfload, fontloader-2015-12-12.lua scope for “font-otb”] ---
+
-do -- begin closure to overcome local limits and interference
+do --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-inj” 2e61e59f1931a84336c6aea812e219c2] ---
if not modules then modules={} end modules ['font-inj']={
version=1.001,
@@ -6337,7 +6594,8 @@ end
function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmnext)
local dx=factor*(exit[1]-entry[1])
local dy=-factor*(exit[2]-entry[2])
- local ws,wn=tfmstart.width,tfmnext.width
+ local ws=tfmstart.width
+ local wn=tfmnext.width
nofregisteredcursives=nofregisteredcursives+1
if rlmode<0 then
dx=-(dx+wn)
@@ -6384,7 +6642,10 @@ function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmne
return dx,dy,nofregisteredcursives
end
function injections.setpair(current,factor,rlmode,r2lflag,spec,injection)
- local x,y,w,h=factor*spec[1],factor*spec[2],factor*spec[3],factor*spec[4]
+ local x=factor*spec[1]
+ local y=factor*spec[2]
+ local w=factor*spec[3]
+ local h=factor*spec[4]
if x~=0 or w~=0 or y~=0 or h~=0 then
local yoffset=y-h
local leftkern=x
@@ -6394,9 +6655,12 @@ function injections.setpair(current,factor,rlmode,r2lflag,spec,injection)
if rlmode and rlmode<0 then
leftkern,rightkern=rightkern,leftkern
end
+ if not injection then
+ injection="injections"
+ end
local p=rawget(properties,current)
if p then
- local i=rawget(p,"injections")
+ local i=rawget(p,injection)
if i then
if leftkern~=0 then
i.leftkern=(i.leftkern or 0)+leftkern
@@ -6408,19 +6672,19 @@ function injections.setpair(current,factor,rlmode,r2lflag,spec,injection)
i.yoffset=(i.yoffset or 0)+yoffset
end
elseif leftkern~=0 or rightkern~=0 then
- p.injections={
+ p[injection]={
leftkern=leftkern,
rightkern=rightkern,
yoffset=yoffset,
}
else
- p.injections={
+ p[injection]={
yoffset=yoffset,
}
end
elseif leftkern~=0 or rightkern~=0 then
properties[current]={
- injections={
+ [injection]={
leftkern=leftkern,
rightkern=rightkern,
yoffset=yoffset,
@@ -6428,7 +6692,7 @@ function injections.setpair(current,factor,rlmode,r2lflag,spec,injection)
}
else
properties[current]={
- injections={
+ [injection]={
yoffset=yoffset,
},
}
@@ -6467,7 +6731,7 @@ function injections.setkern(current,factor,rlmode,x,injection)
return 0,0
end
end
-function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase)
+function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk)
local dx,dy=factor*(ba[1]-ma[1]),factor*(ba[2]-ma[2])
nofregisteredmarks=nofregisteredmarks+1
if rlmode>=0 then
@@ -6477,11 +6741,15 @@ function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase)
if p then
local i=rawget(p,"injections")
if i then
- i.markx=dx
- i.marky=dy
- i.markdir=rlmode or 0
- i.markbase=nofregisteredmarks
- i.markbasenode=base
+ if i.markmark then
+ else
+ i.markx=dx
+ i.marky=dy
+ i.markdir=rlmode or 0
+ i.markbase=nofregisteredmarks
+ i.markbasenode=base
+ i.markmark=mkmk
+ end
else
p.injections={
markx=dx,
@@ -6489,6 +6757,7 @@ function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase)
markdir=rlmode or 0,
markbase=nofregisteredmarks,
markbasenode=base,
+ markmark=mkmk,
}
end
else
@@ -6499,6 +6768,7 @@ function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase)
markdir=rlmode or 0,
markbase=nofregisteredmarks,
markbasenode=base,
+ markmark=mkmk,
},
}
end
@@ -6603,27 +6873,33 @@ local function show_result(head)
current=getnext(current)
end
end
-local function collect_glyphs_1(head)
- local glyphs,nofglyphs={},0
- local marks,nofmarks={},0
+local function collect_glyphs(head,offsets)
+ local glyphs,glyphi,nofglyphs={},{},0
+ local marks,marki,nofmarks={},{},0
local nf,tm=nil,nil
- for n in traverse_id(glyph_code,head) do
- if getsubtype(n)<256 then
- local f=getfont(n)
- if f~=nf then
- nf=f
- tm=fontdata[nf].resources.marks
- end
- if tm and tm[getchar(n)] then
- nofmarks=nofmarks+1
- marks[nofmarks]=n
- else
- nofglyphs=nofglyphs+1
- glyphs[nofglyphs]=n
- end
+ local n=head
+ local function identify(n,what)
+ local f=getfont(n)
+ if f~=nf then
+ nf=f
+ tm=fontdata[nf].resources
+ if tm then
+ tm=tm.marks
+ end
+ end
+ if tm and tm[getchar(n)] then
+ nofmarks=nofmarks+1
+ marks[nofmarks]=n
+ marki[nofmarks]="injections"
+ else
+ nofglyphs=nofglyphs+1
+ glyphs[nofglyphs]=n
+ glyphi[nofglyphs]=what
+ end
+ if offsets then
local p=rawget(properties,n)
if p then
- local i=rawget(p,"injections")
+ local i=rawget(p,what)
if i then
local yoffset=i.yoffset
if yoffset and yoffset~=0 then
@@ -6633,36 +6909,47 @@ local function collect_glyphs_1(head)
end
end
end
- return glyphs,nofglyphs,marks,nofmarks
-end
-local function collect_glyphs_2(head)
- local glyphs,nofglyphs={},0
- local marks,nofmarks={},0
- local nf,tm=nil,nil
- for n in traverse_id(glyph_code,head) do
- if getsubtype(n)<256 then
- local f=getfont(n)
- if f~=nf then
- nf=f
- tm=fontdata[nf].resources.marks
- end
- if tm and tm[getchar(n)] then
- nofmarks=nofmarks+1
- marks[nofmarks]=n
- else
- nofglyphs=nofglyphs+1
- glyphs[nofglyphs]=n
- end
+ while n do
+ local id=getid(n)
+ if id==glyph_code then
+ identify(n,"injections")
+ elseif id==disc_code then
+ local d=getfield(n,"pre")
+ if d then
+ for n in traverse_id(glyph_code,d) do
+ if getsubtype(n)<256 then
+ identify(n,"preinjections")
+ end
+ end
+ end
+ local d=getfield(n,"post")
+ if d then
+ for n in traverse_id(glyph_code,d) do
+ if getsubtype(n)<256 then
+ identify(n,"postinjections")
+ end
+ end
+ end
+ local d=getfield(n,"replace")
+ if d then
+ for n in traverse_id(glyph_code,d) do
+ if getsubtype(n)<256 then
+ identify(n,"replaceinjections")
+ end
+ end
+ end
end
+ n=getnext(n)
end
- return glyphs,nofglyphs,marks,nofmarks
+ return glyphs,glyphi,nofglyphs,marks,marki,nofmarks
end
-local function inject_marks(marks,nofmarks)
+local function inject_marks(marks,marki,nofmarks)
for i=1,nofmarks do
local n=marks[i]
local pn=rawget(properties,n)
if pn then
- pn=rawget(pn,"injections")
+ local ni=marki[i]
+ local pn=rawget(pn,ni)
if pn then
local p=pn.markbasenode
if p then
@@ -6671,7 +6958,7 @@ local function inject_marks(marks,nofmarks)
local rightkern=nil
local pp=rawget(properties,p)
if pp then
- pp=rawget(pp,"injections")
+ pp=rawget(pp,ni)
if pp then
rightkern=pp.rightkern
end
@@ -6680,11 +6967,17 @@ local function inject_marks(marks,nofmarks)
if pn.markdir<0 then
ox=px-pn.markx-rightkern
else
- local leftkern=pp.leftkern
- if leftkern then
- ox=px-pn.markx
+
+
+ if false then
+ local leftkern=pp.leftkern
+ if leftkern then
+ ox=px-pn.markx-leftkern
+ else
+ ox=px-pn.markx
+ end
else
- ox=px-pn.markx-leftkern
+ ox=px-pn.markx
end
end
else
@@ -6697,12 +6990,7 @@ local function inject_marks(marks,nofmarks)
end
setfield(n,"xoffset",ox)
local py=getfield(p,"yoffset")
- local oy=0
- if marks[p] then
- oy=py+pn.marky
- else
- oy=getfield(n,"yoffset")+py+pn.marky
- end
+ local oy=getfield(n,"yoffset")+py+pn.marky
setfield(n,"yoffset",oy)
else
end
@@ -6710,14 +6998,14 @@ local function inject_marks(marks,nofmarks)
end
end
end
-local function inject_cursives(glyphs,nofglyphs)
+local function inject_cursives(glyphs,glyphi,nofglyphs)
local cursiveanchor,lastanchor=nil,nil
local minc,maxc,last=0,0,nil
for i=1,nofglyphs do
local n=glyphs[i]
local pn=rawget(properties,n)
if pn then
- pn=rawget(pn,"injections")
+ pn=rawget(pn,glyphi[i])
end
if pn then
local cursivex=pn.cursivex
@@ -6783,22 +7071,59 @@ local function inject_cursives(glyphs,nofglyphs)
end
end
end
-local function inject_kerns(head,list,length)
+local function inject_kerns(head,glist,ilist,length)
for i=1,length do
- local n=list[i]
+ local n=glist[i]
local pn=rawget(properties,n)
if pn then
- local i=rawget(pn,"injections")
- if i then
- local leftkern=i.leftkern
- if leftkern and leftkern~=0 then
- insert_node_before(head,n,newkern(leftkern))
- end
- local rightkern=i.rightkern
- if rightkern and rightkern~=0 then
- insert_node_after(head,n,newkern(rightkern))
- end
- end
+ local dp=nil
+ local dr=nil
+ local ni=ilist[i]
+ local p=nil
+ if ni=="injections" then
+ p=getprev(n)
+ if p then
+ local id=getid(p)
+ if id==disc_code then
+ dp=getfield(p,"post")
+ dr=getfield(p,"replace")
+ end
+ end
+ end
+ if dp then
+ local i=rawget(pn,"postinjections")
+ if i then
+ local leftkern=i.leftkern
+ if leftkern and leftkern~=0 then
+ local t=find_tail(dp)
+ insert_node_after(dp,t,newkern(leftkern))
+ setfield(p,"post",dp)
+ end
+ end
+ end
+ if dr then
+ local i=rawget(pn,"replaceinjections")
+ if i then
+ local leftkern=i.leftkern
+ if leftkern and leftkern~=0 then
+ local t=find_tail(dr)
+ insert_node_after(dr,t,newkern(leftkern))
+ setfield(p,"replace",dr)
+ end
+ end
+ else
+ local i=rawget(pn,ni)
+ if i then
+ local leftkern=i.leftkern
+ if leftkern and leftkern~=0 then
+ insert_node_before(head,n,newkern(leftkern))
+ end
+ local rightkern=i.rightkern
+ if rightkern and rightkern~=0 then
+ insert_node_after(head,n,newkern(rightkern))
+ end
+ end
+ end
end
end
end
@@ -6807,23 +7132,18 @@ local function inject_everything(head,where)
if trace_injections then
trace(head,"everything")
end
- local glyphs,nofglyphs,marks,nofmarks
- if nofregisteredpairs>0 then
- glyphs,nofglyphs,marks,nofmarks=collect_glyphs_1(head)
- else
- glyphs,nofglyphs,marks,nofmarks=collect_glyphs_2(head)
- end
+ local glyphs,glyphi,nofglyphs,marks,marki,nofmarks=collect_glyphs(head,nofregisteredpairs>0)
if nofglyphs>0 then
if nofregisteredcursives>0 then
- inject_cursives(glyphs,nofglyphs)
+ inject_cursives(glyphs,glyphi,nofglyphs)
end
if nofregisteredmarks>0 then
- inject_marks(marks,nofmarks)
+ inject_marks(marks,marki,nofmarks)
end
- inject_kerns(head,glyphs,nofglyphs)
+ inject_kerns(head,glyphs,glyphi,nofglyphs)
end
if nofmarks>0 then
- inject_kerns(head,marks,nofmarks)
+ inject_kerns(head,marks,marki,nofmarks)
end
if keepregisteredcounts then
keepregisteredcounts=false
@@ -6841,7 +7161,7 @@ local function inject_kerns_only(head,where)
trace(head,"kerns")
end
local n=head
- local p=nil
+ local p=nil
while n do
local id=getid(n)
if id==glyph_code then
@@ -6857,6 +7177,7 @@ local function inject_kerns_only(head,where)
if leftkern and leftkern~=0 then
local t=find_tail(d)
insert_node_after(d,t,newkern(leftkern))
+ setfield(p,"post",d)
end
end
end
@@ -6868,6 +7189,7 @@ local function inject_kerns_only(head,where)
if leftkern and leftkern~=0 then
local t=find_tail(d)
insert_node_after(d,t,newkern(leftkern))
+ setfield(p,"replace",d)
end
end
else
@@ -6889,8 +7211,6 @@ local function inject_kerns_only(head,where)
end
end
end
- else
- break
end
p=nil
elseif id==disc_code then
@@ -6945,7 +7265,7 @@ local function inject_kerns_only(head,where)
local h=d
for n in traverse_id(glyph_code,d) do
if getsubtype(n)<256 then
- local pn=rawget(properties,n)
+ local pn=rawget(properties,n)
if pn then
local i=rawget(pn,"replaceinjections")
if i then
@@ -6982,7 +7302,7 @@ local function inject_pairs_only(head,where)
trace(head,"pairs")
end
local n=head
- local p=nil
+ local p=nil
while n do
local id=getid(n)
if id==glyph_code then
@@ -6998,6 +7318,7 @@ local function inject_pairs_only(head,where)
if leftkern and leftkern~=0 then
local t=find_tail(d)
insert_node_after(d,t,newkern(leftkern))
+ setfield(p,"post",d)
end
end
end
@@ -7009,6 +7330,7 @@ local function inject_pairs_only(head,where)
if leftkern and leftkern~=0 then
local t=find_tail(d)
insert_node_after(d,t,newkern(leftkern))
+ setfield(p,"replace",d)
end
end
else
@@ -7023,24 +7345,22 @@ local function inject_pairs_only(head,where)
else
local i=rawget(pn,"injections")
if i then
- local yoffset=i.yoffset
- if yoffset and yoffset~=0 then
- setfield(n,"yoffset",yoffset)
- end
local leftkern=i.leftkern
if leftkern and leftkern~=0 then
- insert_node_before(head,n,newkern(leftkern))
+ head=insert_node_before(head,n,newkern(leftkern))
end
local rightkern=i.rightkern
if rightkern and rightkern~=0 then
insert_node_after(head,n,newkern(rightkern))
n=getnext(n)
end
+ local yoffset=i.yoffset
+ if yoffset and yoffset~=0 then
+ setfield(n,"yoffset",yoffset)
+ end
end
end
end
- else
- break
end
p=nil
elseif id==disc_code then
@@ -7049,16 +7369,12 @@ local function inject_pairs_only(head,where)
local h=d
for n in traverse_id(glyph_code,d) do
if getsubtype(n)<256 then
- local p=rawget(properties,n)
- if p then
- local i=rawget(p,"preinjections")
+ local pn=rawget(properties,n)
+ if pn then
+ local i=rawget(pn,"preinjections")
if i then
- local yoffset=i.yoffset
- if yoffset and yoffset~=0 then
- setfield(n,"yoffset",yoffset)
- end
local leftkern=i.leftkern
- if leftkern~=0 then
+ if leftkern and leftkern~=0 then
h=insert_node_before(h,n,newkern(leftkern))
end
local rightkern=i.rightkern
@@ -7066,6 +7382,10 @@ local function inject_pairs_only(head,where)
insert_node_after(head,n,newkern(rightkern))
n=getnext(n)
end
+ local yoffset=i.yoffset
+ if yoffset and yoffset~=0 then
+ setfield(n,"yoffset",yoffset)
+ end
end
end
else
@@ -7081,14 +7401,10 @@ local function inject_pairs_only(head,where)
local h=d
for n in traverse_id(glyph_code,d) do
if getsubtype(n)<256 then
- local p=rawget(properties,n)
- if p then
- local i=rawget(p,"postinjections")
+ local pn=rawget(properties,n)
+ if pn then
+ local i=rawget(pn,"postinjections")
if i then
- local yoffset=i.yoffset
- if yoffset and yoffset~=0 then
- setfield(n,"yoffset",yoffset)
- end
local leftkern=i.leftkern
if leftkern and leftkern~=0 then
h=insert_node_before(h,n,newkern(leftkern))
@@ -7098,6 +7414,10 @@ local function inject_pairs_only(head,where)
insert_node_after(head,n,newkern(rightkern))
n=getnext(n)
end
+ local yoffset=i.yoffset
+ if yoffset and yoffset~=0 then
+ setfield(n,"yoffset",yoffset)
+ end
end
end
else
@@ -7113,14 +7433,10 @@ local function inject_pairs_only(head,where)
local h=d
for n in traverse_id(glyph_code,d) do
if getsubtype(n)<256 then
- local p=rawget(properties,n)
- if p then
- local i=rawget(p,"replaceinjections")
+ local pn=rawget(properties,n)
+ if pn then
+ local i=rawget(pn,"replaceinjections")
if i then
- local yoffset=i.yoffset
- if yoffset and yoffset~=0 then
- setfield(n,"yoffset",yoffset)
- end
local leftkern=i.leftkern
if leftkern and leftkern~=0 then
h=insert_node_before(h,n,newkern(leftkern))
@@ -7130,6 +7446,10 @@ local function inject_pairs_only(head,where)
insert_node_after(head,n,newkern(rightkern))
n=getnext(n)
end
+ local yoffset=i.yoffset
+ if yoffset and yoffset~=0 then
+ setfield(n,"yoffset",yoffset)
+ end
end
end
else
@@ -7154,7 +7474,7 @@ local function inject_pairs_only(head,where)
end
return tonode(head),true
end
-function injections.handler(head,where)
+function injections.handler(head,where)
if nofregisteredmarks>0 or nofregisteredcursives>0 then
return inject_everything(head,where)
elseif nofregisteredpairs>0 then
@@ -7166,9 +7486,10 @@ function injections.handler(head,where)
end
end
-end -- closure
+end --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-inj”] ---
-do -- begin closure to overcome local limits and interference
+
+do --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-ota” e18236703ac20ece7ff45f9209a9b9d6] ---
if not modules then modules={} end modules ['font-otx']={
version=1.001,
@@ -7543,9 +7864,10 @@ directives.register("otf.analyze.useunicodemarks",function(v)
analyzers.useunicodemarks=v
end)
-end -- closure
+end --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-ota”] ---
+
-do -- begin closure to overcome local limits and interference
+do --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-otn” f01870a8622259f58ffbdc5718a53377] ---
if not modules then modules={} end modules ['font-otn']={
version=1.001,
@@ -7554,14 +7876,12 @@ if not modules then modules={} end modules ['font-otn']={
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files",
}
-local concat,insert,remove=table.concat,table.insert,table.remove
-local gmatch,gsub,find,match,lower,strip=string.gmatch,string.gsub,string.find,string.match,string.lower,string.strip
-local type,next,tonumber,tostring=type,next,tonumber,tostring
-local lpegmatch=lpeg.match
+local type,next,tonumber=type,next,tonumber
local random=math.random
local formatters=string.formatters
local logs,trackers,nodes,attributes=logs,trackers,nodes,attributes
local registertracker=trackers.register
+local registerdirective=directives.register
local fonts=fonts
local otf=fonts.handlers.otf
local trace_lookups=false registertracker("otf.lookups",function(v) trace_lookups=v end)
@@ -7580,6 +7900,13 @@ local trace_applied=false registertracker("otf.applied",function(v) trace_applie
local trace_steps=false registertracker("otf.steps",function(v) trace_steps=v end)
local trace_skips=false registertracker("otf.skips",function(v) trace_skips=v end)
local trace_directions=false registertracker("otf.directions",function(v) trace_directions=v end)
+local trace_kernruns=false registertracker("otf.kernruns",function(v) trace_kernruns=v end)
+local trace_discruns=false registertracker("otf.discruns",function(v) trace_discruns=v end)
+local trace_compruns=false registertracker("otf.compruns",function(v) trace_compruns=v end)
+local quit_on_no_replacement=true
+local zwnjruns=true
+registerdirective("otf.zwnjruns",function(v) zwnjruns=v end)
+registerdirective("otf.chain.quitonnoreplacement",function(value) quit_on_no_replacement=value end)
local report_direct=logs.reporter("fonts","otf direct")
local report_subchain=logs.reporter("fonts","otf subchain")
local report_chain=logs.reporter("fonts","otf chain")
@@ -7633,13 +7960,10 @@ local disccodes=nodes.disccodes
local glyph_code=nodecodes.glyph
local glue_code=nodecodes.glue
local disc_code=nodecodes.disc
-local whatsit_code=nodecodes.whatsit
local math_code=nodecodes.math
local dir_code=whatcodes.dir
local localpar_code=whatcodes.localpar
local discretionary_code=disccodes.discretionary
-local regular_code=disccodes.regular
-local automatic_code=disccodes.automatic
local ligature_code=glyphcodes.ligature
local privateattribute=attributes.private
local a_state=privateattribute('state')
@@ -7673,6 +7997,13 @@ local lookuptags=false
local handlers={}
local rlmode=0
local featurevalue=false
+local sweephead={}
+local sweepnode=nil
+local sweepprev=nil
+local sweepnext=nil
+local notmatchpre={}
+local notmatchpost={}
+local notmatchreplace={}
local checkstep=(nodes and nodes.tracers and nodes.tracers.steppers.check) or function() end
local registerstep=(nodes and nodes.tracers and nodes.tracers.steppers.register) or function() end
local registermessage=(nodes and nodes.tracers and nodes.tracers.steppers.message) or function() end
@@ -7742,6 +8073,65 @@ local function copy_glyph(g)
return n
end
end
+local function flattendisk(head,disc)
+ local replace=getfield(disc,"replace")
+ setfield(disc,"replace",nil)
+ free_node(disc)
+ if head==disc then
+ local next=getnext(disc)
+ if replace then
+ if next then
+ local tail=find_node_tail(replace)
+ setfield(tail,"next",next)
+ setfield(next,"prev",tail)
+ end
+ return replace,replace
+ elseif next then
+ return next,next
+ else
+ return
+ end
+ else
+ local next=getnext(disc)
+ local prev=getprev(disc)
+ if replace then
+ local tail=find_node_tail(replace)
+ if next then
+ setfield(tail,"next",next)
+ setfield(next,"prev",tail)
+ end
+ setfield(prev,"next",replace)
+ setfield(replace,"prev",prev)
+ return head,replace
+ else
+ if next then
+ setfield(next,"prev",prev)
+ end
+ setfield(prev,"next",next)
+ return head,next
+ end
+ end
+end
+local function appenddisc(disc,list)
+ local post=getfield(disc,"post")
+ local replace=getfield(disc,"replace")
+ local phead=list
+ local rhead=copy_node_list(list)
+ local ptail=find_node_tail(post)
+ local rtail=find_node_tail(replace)
+ if post then
+ setfield(ptail,"next",phead)
+ setfield(phead,"prev",ptail)
+ else
+ setfield(disc,"post",phead)
+ end
+ if replace then
+ setfield(rtail,"next",rhead)
+ setfield(rhead,"prev",rtail)
+ else
+ setfield(disc,"replace",rhead)
+ end
+end
local function markstoligature(kind,lookupname,head,start,stop,char)
if start==stop and getchar(start)==char then
return head,start
@@ -7769,8 +8159,8 @@ local function markstoligature(kind,lookupname,head,start,stop,char)
return head,base
end
end
-local function getcomponentindex(start)
- if getid(start)~=glyph_code then
+local function getcomponentindex(start)
+ if getid(start)~=glyph_code then
return 0
elseif getsubtype(start)==ligature_code then
local i=0
@@ -7786,14 +8176,22 @@ local function getcomponentindex(start)
return 0
end
end
+local a_noligature=attributes.private("noligature")
local function toligature(kind,lookupname,head,start,stop,char,markflag,discfound)
+ if getattr(start,a_noligature)==1 then
+ return head,start
+ end
if start==stop and getchar(start)==char then
resetinjection(start)
setfield(start,"char",char)
return head,start
end
+ local components=getfield(start,"components")
+ if components then
+ end
local prev=getprev(start)
local next=getnext(stop)
+ local comp=start
setfield(start,"prev",nil)
setfield(stop,"next",nil)
local base=copy_glyph(start)
@@ -7803,15 +8201,15 @@ local function toligature(kind,lookupname,head,start,stop,char,markflag,discfoun
resetinjection(base)
setfield(base,"char",char)
setfield(base,"subtype",ligature_code)
- setfield(base,"components",start)
+ setfield(base,"components",comp)
if prev then
setfield(prev,"next",base)
end
if next then
setfield(next,"prev",base)
end
- setfield(base,"next",next)
setfield(base,"prev",prev)
+ setfield(base,"next",next)
if not discfound then
local deletemarks=markflag~="mark"
local components=start
@@ -7829,7 +8227,9 @@ local function toligature(kind,lookupname,head,start,stop,char,markflag,discfoun
if trace_marks then
logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),getligaindex(start))
end
- head,current=insert_node_after(head,current,copy_node(start))
+ local n=copy_node(start)
+ copyinjection(n,start)
+ head,current=insert_node_after(head,current,n)
elseif trace_marks then
logwarning("%s: delete mark %s",pref(kind,lookupname),gref(char))
end
@@ -7848,16 +8248,75 @@ local function toligature(kind,lookupname,head,start,stop,char,markflag,discfoun
end
start=getnext(start)
end
+ else
+ local discprev=getfield(discfound,"prev")
+ local discnext=getfield(discfound,"next")
+ if discprev and discnext then
+ local pre=getfield(discfound,"pre")
+ local post=getfield(discfound,"post")
+ local replace=getfield(discfound,"replace")
+ if not replace then
+ local prev=getfield(base,"prev")
+ local copied=copy_node_list(comp)
+ setfield(discnext,"prev",nil)
+ setfield(discprev,"next",nil)
+ if pre then
+ setfield(discprev,"next",pre)
+ setfield(pre,"prev",discprev)
+ end
+ pre=comp
+ if post then
+ local tail=find_node_tail(post)
+ setfield(tail,"next",discnext)
+ setfield(discnext,"prev",tail)
+ setfield(post,"prev",nil)
+ else
+ post=discnext
+ end
+ setfield(prev,"next",discfound)
+ setfield(discfound,"prev",prev)
+ setfield(discfound,"next",next)
+ setfield(next,"prev",discfound)
+ setfield(base,"next",nil)
+ setfield(base,"prev",nil)
+ setfield(base,"components",copied)
+ setfield(discfound,"pre",pre)
+ setfield(discfound,"post",post)
+ setfield(discfound,"replace",base)
+ setfield(discfound,"subtype",discretionary_code)
+ base=prev
+ end
+ end
end
return head,base
end
-function handlers.gsub_single(head,start,kind,lookupname,replacement)
- if trace_singles then
- logprocess("%s: replacing %s by single %s",pref(kind,lookupname),gref(getchar(start)),gref(replacement))
+local function multiple_glyphs(head,start,multiple,ignoremarks)
+ local nofmultiples=#multiple
+ if nofmultiples>0 then
+ resetinjection(start)
+ setfield(start,"char",multiple[1])
+ if nofmultiples>1 then
+ local sn=getnext(start)
+ for k=2,nofmultiples do
+ local n=copy_node(start)
+ resetinjection(n)
+ setfield(n,"char",multiple[k])
+ setfield(n,"prev",start)
+ setfield(n,"next",sn)
+ if sn then
+ setfield(sn,"prev",n)
+ end
+ setfield(start,"next",n)
+ start=n
+ end
+ end
+ return head,start,true
+ else
+ if trace_multiples then
+ logprocess("no multiple for %s",gref(getchar(start)))
+ end
+ return head,start,false
end
- resetinjection(start)
- setfield(start,"char",replacement)
- return head,start,true
end
local function get_alternative_glyph(start,alternatives,value,trace_alternatives)
local n=#alternatives
@@ -7890,33 +8349,13 @@ local function get_alternative_glyph(start,alternatives,value,trace_alternatives
end
end
end
-local function multiple_glyphs(head,start,multiple,ignoremarks)
- local nofmultiples=#multiple
- if nofmultiples>0 then
- resetinjection(start)
- setfield(start,"char",multiple[1])
- if nofmultiples>1 then
- local sn=getnext(start)
- for k=2,nofmultiples do
- local n=copy_node(start)
- resetinjection(n)
- setfield(n,"char",multiple[k])
- setfield(n,"next",sn)
- setfield(n,"prev",start)
- if sn then
- setfield(sn,"prev",n)
- end
- setfield(start,"next",n)
- start=n
- end
- end
- return head,start,true
- else
- if trace_multiples then
- logprocess("no multiple for %s",gref(getchar(start)))
- end
- return head,start,false
+function handlers.gsub_single(head,start,kind,lookupname,replacement)
+ if trace_singles then
+ logprocess("%s: replacing %s by single %s",pref(kind,lookupname),gref(getchar(start)),gref(replacement))
end
+ resetinjection(start)
+ setfield(start,"char",replacement)
+ return head,start,true
end
function handlers.gsub_alternate(head,start,kind,lookupname,alternative,sequence)
local value=featurevalue==true and tfmdata.shared.features[kind] or featurevalue
@@ -7941,7 +8380,7 @@ function handlers.gsub_multiple(head,start,kind,lookupname,multiple,sequence)
return multiple_glyphs(head,start,multiple,sequence.flags[1])
end
function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
- local s,stop,discfound=getnext(start),nil,false
+ local s,stop=getnext(start),nil
local startchar=getchar(start)
if marks[startchar] then
while s do
@@ -7969,23 +8408,29 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
else
head,start=markstoligature(kind,lookupname,head,start,stop,lig)
end
- return head,start,true
+ return head,start,true,false
else
end
end
else
local skipmark=sequence.flags[1]
+ local discfound=false
+ local lastdisc=nil
while s do
local id=getid(s)
- if id==glyph_code and getsubtype(s)<256 then
- if getfont(s)==currentfont then
+ if id==glyph_code and getsubtype(s)<256 then
+ if getfont(s)==currentfont then
local char=getchar(s)
if skipmark and marks[char] then
s=getnext(s)
- else
- local lg=ligature[char]
+ else
+ local lg=ligature[char]
if lg then
- stop=s
+ if not discfound and lastdisc then
+ discfound=lastdisc
+ lastdisc=nil
+ end
+ stop=s
ligature=lg
s=getnext(s)
else
@@ -7996,13 +8441,13 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
break
end
elseif id==disc_code then
- discfound=true
+ lastdisc=s
s=getnext(s)
else
break
end
end
- local lig=ligature.ligature
+ local lig=ligature.ligature
if lig then
if stop then
if trace_ligatures then
@@ -8019,12 +8464,71 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
logprocess("%s: replacing %s by (no real) ligature %s case 3",pref(kind,lookupname),gref(startchar),gref(lig))
end
end
- return head,start,true
+ return head,start,true,discfound
else
end
end
+ return head,start,false,discfound
+end
+function handlers.gpos_single(head,start,kind,lookupname,kerns,sequence,injection)
+ local startchar=getchar(start)
+ local dx,dy,w,h=setpair(start,tfmdata.parameters.factor,rlmode,sequence.flags[4],kerns,injection)
+ if trace_kerns then
+ logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),dx,dy,w,h)
+ end
return head,start,false
end
+function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence,lookuphash,i,injection)
+ local snext=getnext(start)
+ if not snext then
+ return head,start,false
+ else
+ local prev=start
+ local done=false
+ local factor=tfmdata.parameters.factor
+ local lookuptype=lookuptypes[lookupname]
+ while snext and getid(snext)==glyph_code and getfont(snext)==currentfont and getsubtype(snext)<256 do
+ local nextchar=getchar(snext)
+ local krn=kerns[nextchar]
+ if not krn and marks[nextchar] then
+ prev=snext
+ snext=getnext(snext)
+ else
+ if not krn then
+ elseif type(krn)=="table" then
+ if lookuptype=="pair" then
+ local a,b=krn[2],krn[3]
+ if a and #a>0 then
+ local x,y,w,h=setpair(start,factor,rlmode,sequence.flags[4],a,injection)
+ if trace_kerns then
+ local startchar=getchar(start)
+ logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h)
+ end
+ end
+ if b and #b>0 then
+ local x,y,w,h=setpair(snext,factor,rlmode,sequence.flags[4],b,injection)
+ if trace_kerns then
+ local startchar=getchar(start)
+ logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h)
+ end
+ end
+ else
+ report_process("%s: check this out (old kern stuff)",pref(kind,lookupname))
+ end
+ done=true
+ elseif krn~=0 then
+ local k=setkern(snext,factor,rlmode,krn,injection)
+ if trace_kerns then
+ logprocess("%s: inserting kern %s between %s and %s",pref(kind,lookupname),k,gref(getchar(prev)),gref(nextchar))
+ end
+ done=true
+ end
+ break
+ end
+ end
+ return head,start,done
+ end
+end
function handlers.gpos_mark2base(head,start,kind,lookupname,markanchors,sequence)
local markchar=getchar(start)
if marks[markchar] then
@@ -8177,7 +8681,7 @@ function handlers.gpos_mark2mark(head,start,kind,lookupname,markanchors,sequence
if al[anchor] then
local ma=markanchors[anchor]
if ma then
- local dx,dy,bound=setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,characters[basechar])
+ local dx,dy,bound=setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,characters[basechar],true)
if trace_marks then
logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)",
pref(kind,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy)
@@ -8255,65 +8759,6 @@ function handlers.gpos_cursive(head,start,kind,lookupname,exitanchors,sequence)
return head,start,false
end
end
-function handlers.gpos_single(head,start,kind,lookupname,kerns,sequence)
- local startchar=getchar(start)
- local dx,dy,w,h=setpair(start,tfmdata.parameters.factor,rlmode,sequence.flags[4],kerns,characters[startchar])
- if trace_kerns then
- logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),dx,dy,w,h)
- end
- return head,start,false
-end
-function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence)
- local snext=getnext(start)
- if not snext then
- return head,start,false
- else
- local prev,done=start,false
- local factor=tfmdata.parameters.factor
- local lookuptype=lookuptypes[lookupname]
- while snext and getid(snext)==glyph_code and getfont(snext)==currentfont and getsubtype(snext)<256 do
- local nextchar=getchar(snext)
- local krn=kerns[nextchar]
- if not krn and marks[nextchar] then
- prev=snext
- snext=getnext(snext)
- else
- if not krn then
- elseif type(krn)=="table" then
- if lookuptype=="pair" then
- local a,b=krn[2],krn[3]
- if a and #a>0 then
- local startchar=getchar(start)
- local x,y,w,h=setpair(start,factor,rlmode,sequence.flags[4],a,characters[startchar])
- if trace_kerns then
- logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h)
- end
- end
- if b and #b>0 then
- local startchar=getchar(start)
- local x,y,w,h=setpair(snext,factor,rlmode,sequence.flags[4],b,characters[nextchar])
- if trace_kerns then
- logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h)
- end
- end
- else
- report_process("%s: check this out (old kern stuff)",pref(kind,lookupname))
- end
- done=true
- elseif krn~=0 then
- local k=setkern(snext,factor,rlmode,krn)
- if trace_kerns then
- logprocess("%s: inserting kern %s between %s and %s",pref(kind,lookupname),k,gref(getchar(prev)),gref(nextchar))
- end
- done=true
- end
- break
- end
- end
- return head,start,done
- end
-end
-local chainmores={}
local chainprocs={}
local function logprocess(...)
if trace_steps then
@@ -8333,10 +8778,6 @@ function chainprocs.chainsub(head,start,stop,kind,chainname,currentcontext,looku
logwarning("%s: a direct call to chainsub cannot happen",cref(kind,chainname,chainlookupname))
return head,start,false
end
-function chainmores.chainsub(head,start,stop,kind,chainname,currentcontext,lookuphash,lookuplist,chainlookupname,n)
- logprocess("%s: a direct call to chainsub cannot happen",cref(kind,chainname,chainlookupname))
- return head,start,false
-end
function chainprocs.reversesub(head,start,stop,kind,chainname,currentcontext,lookuphash,replacements)
local char=getchar(start)
local replacement=replacements[char]
@@ -8355,7 +8796,7 @@ function chainprocs.gsub_single(head,start,stop,kind,chainname,currentcontext,lo
local current=start
local subtables=currentlookup.subtables
if #subtables>1 then
- logwarning("todo: check if we need to loop over the replacements: %s",concat(subtables," "))
+ logwarning("todo: check if we need to loop over the replacements: % t",subtables)
end
while current do
if getid(current)==glyph_code then
@@ -8389,7 +8830,6 @@ function chainprocs.gsub_single(head,start,stop,kind,chainname,currentcontext,lo
end
return head,start,false
end
-chainmores.gsub_single=chainprocs.gsub_single
function chainprocs.gsub_multiple(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
local startchar=getchar(start)
local subtables=currentlookup.subtables
@@ -8414,7 +8854,6 @@ function chainprocs.gsub_multiple(head,start,stop,kind,chainname,currentcontext,
end
return head,start,false
end
-chainmores.gsub_multiple=chainprocs.gsub_multiple
function chainprocs.gsub_alternate(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
local current=start
local subtables=currentlookup.subtables
@@ -8456,7 +8895,6 @@ function chainprocs.gsub_alternate(head,start,stop,kind,chainname,currentcontext
end
return head,start,false
end
-chainmores.gsub_alternate=chainprocs.gsub_alternate
function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex)
local startchar=getchar(start)
local subtables=currentlookup.subtables
@@ -8476,13 +8914,19 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,
local s=getnext(start)
local discfound=false
local last=stop
- local nofreplacements=0
+ local nofreplacements=1
local skipmark=currentlookup.flags[1]
while s do
local id=getid(s)
if id==disc_code then
- s=getnext(s)
- discfound=true
+ if not discfound then
+ discfound=s
+ end
+ if s==stop then
+ break
+ else
+ s=getnext(s)
+ end
else
local schar=getchar(s)
if skipmark and marks[schar] then
@@ -8515,7 +8959,7 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,
end
end
head,start=toligature(kind,lookupname,head,start,stop,l2,currentlookup.flags[1],discfound)
- return head,start,true,nofreplacements
+ return head,start,true,nofreplacements,discfound
elseif trace_bugs then
if start==stop then
logwarning("%s: replacing character %s by ligature fails",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar))
@@ -8525,9 +8969,82 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,
end
end
end
- return head,start,false,0
+ return head,start,false,0,false
+end
+function chainprocs.gpos_single(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence)
+ local startchar=getchar(start)
+ local subtables=currentlookup.subtables
+ local lookupname=subtables[1]
+ local kerns=lookuphash[lookupname]
+ if kerns then
+ kerns=kerns[startchar]
+ if kerns then
+ local dx,dy,w,h=setpair(start,tfmdata.parameters.factor,rlmode,sequence.flags[4],kerns)
+ if trace_kerns then
+ logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),dx,dy,w,h)
+ end
+ end
+ end
+ return head,start,false
+end
+function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence)
+ local snext=getnext(start)
+ if snext then
+ local startchar=getchar(start)
+ local subtables=currentlookup.subtables
+ local lookupname=subtables[1]
+ local kerns=lookuphash[lookupname]
+ if kerns then
+ kerns=kerns[startchar]
+ if kerns then
+ local lookuptype=lookuptypes[lookupname]
+ local prev,done=start,false
+ local factor=tfmdata.parameters.factor
+ while snext and getid(snext)==glyph_code and getfont(snext)==currentfont and getsubtype(snext)<256 do
+ local nextchar=getchar(snext)
+ local krn=kerns[nextchar]
+ if not krn and marks[nextchar] then
+ prev=snext
+ snext=getnext(snext)
+ else
+ if not krn then
+ elseif type(krn)=="table" then
+ if lookuptype=="pair" then
+ local a,b=krn[2],krn[3]
+ if a and #a>0 then
+ local startchar=getchar(start)
+ local x,y,w,h=setpair(start,factor,rlmode,sequence.flags[4],a)
+ if trace_kerns then
+ logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h)
+ end
+ end
+ if b and #b>0 then
+ local startchar=getchar(start)
+ local x,y,w,h=setpair(snext,factor,rlmode,sequence.flags[4],b)
+ if trace_kerns then
+ logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h)
+ end
+ end
+ else
+ report_process("%s: check this out (old kern stuff)",cref(kind,chainname,chainlookupname))
+ end
+ done=true
+ elseif krn~=0 then
+ local k=setkern(snext,factor,rlmode,krn)
+ if trace_kerns then
+ logprocess("%s: inserting kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(getchar(prev)),gref(nextchar))
+ end
+ done=true
+ end
+ break
+ end
+ end
+ return head,start,done
+ end
+ end
+ end
+ return head,start,false
end
-chainmores.gsub_ligature=chainprocs.gsub_ligature
function chainprocs.gpos_mark2base(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
local markchar=getchar(start)
if marks[markchar] then
@@ -8691,7 +9208,7 @@ function chainprocs.gpos_mark2mark(head,start,stop,kind,chainname,currentcontext
if al[anchor] then
local ma=markanchors[anchor]
if ma then
- local dx,dy,bound=setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,characters[basechar])
+ local dx,dy,bound=setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,characters[basechar],true)
if trace_marks then
logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)",
cref(kind,chainname,chainlookupname,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy)
@@ -8778,113 +9295,286 @@ function chainprocs.gpos_cursive(head,start,stop,kind,chainname,currentcontext,l
end
return head,start,false
end
-function chainprocs.gpos_single(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence)
- local startchar=getchar(start)
- local subtables=currentlookup.subtables
- local lookupname=subtables[1]
- local kerns=lookuphash[lookupname]
- if kerns then
- kerns=kerns[startchar]
- if kerns then
- local dx,dy,w,h=setpair(start,tfmdata.parameters.factor,rlmode,sequence.flags[4],kerns,characters[startchar])
- if trace_kerns then
- logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),dx,dy,w,h)
+local function show_skip(kind,chainname,char,ck,class)
+ if ck[9] then
+ logwarning("%s: skipping char %s, class %a, rule %a, lookuptype %a, %a => %a",cref(kind,chainname),gref(char),class,ck[1],ck[2],ck[9],ck[10])
+ else
+ logwarning("%s: skipping char %s, class %a, rule %a, lookuptype %a",cref(kind,chainname),gref(char),class,ck[1],ck[2])
+ end
+end
+local function chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,chainindex,sequence,chainproc)
+ if not start then
+ return head,start,false
+ end
+ local startishead=start==head
+ local seq=ck[3]
+ local f=ck[4]
+ local l=ck[5]
+ local s=#seq
+ local done=false
+ local sweepnode=sweepnode
+ local sweeptype=sweeptype
+ local sweepoverflow=false
+ local checkdisc=getprev(head)
+ local keepdisc=not sweepnode
+ local lookaheaddisc=nil
+ local backtrackdisc=nil
+ local current=start
+ local last=start
+ local prev=getprev(start)
+ local i=f
+ while i<=l do
+ local id=getid(current)
+ if id==glyph_code then
+ i=i+1
+ last=current
+ current=getnext(current)
+ elseif id==disc_code then
+ if keepdisc then
+ keepdisc=false
+ if notmatchpre[current]~=notmatchreplace[current] then
+ lookaheaddisc=current
+ end
+ local replace=getfield(current,"replace")
+ while replace and i<=l do
+ if getid(replace)==glyph_code then
+ i=i+1
+ end
+ replace=getnext(replace)
+ end
+ last=current
+ current=getnext(c)
+ else
+ head,current=flattendisk(head,current)
+ end
+ else
+ last=current
+ current=getnext(current)
+ end
+ if current then
+ elseif sweepoverflow then
+ break
+ elseif sweeptype=="post" or sweeptype=="replace" then
+ current=getnext(sweepnode)
+ if current then
+ sweeptype=nil
+ sweepoverflow=true
+ else
+ break
end
end
end
- return head,start,false
-end
-chainmores.gpos_single=chainprocs.gpos_single
-function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence)
- local snext=getnext(start)
- if snext then
- local startchar=getchar(start)
- local subtables=currentlookup.subtables
- local lookupname=subtables[1]
- local kerns=lookuphash[lookupname]
- if kerns then
- kerns=kerns[startchar]
- if kerns then
- local lookuptype=lookuptypes[lookupname]
- local prev,done=start,false
- local factor=tfmdata.parameters.factor
- while snext and getid(snext)==glyph_code and getfont(snext)==currentfont and getsubtype(snext)<256 do
- local nextchar=getchar(snext)
- local krn=kerns[nextchar]
- if not krn and marks[nextchar] then
- prev=snext
- snext=getnext(snext)
- else
- if not krn then
- elseif type(krn)=="table" then
- if lookuptype=="pair" then
- local a,b=krn[2],krn[3]
- if a and #a>0 then
- local startchar=getchar(start)
- local x,y,w,h=setpair(start,factor,rlmode,sequence.flags[4],a,characters[startchar])
- if trace_kerns then
- logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h)
- end
- end
- if b and #b>0 then
- local startchar=getchar(start)
- local x,y,w,h=setpair(snext,factor,rlmode,sequence.flags[4],b,characters[nextchar])
- if trace_kerns then
- logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h)
- end
- end
- else
- report_process("%s: check this out (old kern stuff)",cref(kind,chainname,chainlookupname))
- local a,b=krn[2],krn[6]
- if a and a~=0 then
- local k=setkern(snext,factor,rlmode,a)
- if trace_kerns then
- logprocess("%s: inserting first kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(getchar(prev)),gref(nextchar))
- end
- end
- if b and b~=0 then
- logwarning("%s: ignoring second kern xoff %s",cref(kind,chainname,chainlookupname),b*factor)
- end
- end
- done=true
- elseif krn~=0 then
- local k=setkern(snext,factor,rlmode,krn)
- if trace_kerns then
- logprocess("%s: inserting kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(getchar(prev)),gref(nextchar))
- end
- done=true
+ if sweepoverflow then
+ local prev=current and getprev(current)
+ if not current or prev~=sweepnode then
+ local head=getnext(sweepnode)
+ local tail=nil
+ if prev then
+ tail=prev
+ setfield(current,"prev",sweepnode)
+ else
+ tail=find_node_tail(head)
+ end
+ setfield(sweepnode,"next",current)
+ setfield(head,"prev",nil)
+ setfield(tail,"next",nil)
+ appenddisc(sweepnode,head)
+ end
+ end
+ if l<s then
+ local i=l
+ local t=sweeptype=="post" or sweeptype=="replace"
+ while current and i<s do
+ local id=getid(current)
+ if id==glyph_code then
+ i=i+1
+ current=getnext(current)
+ elseif id==disc_code then
+ if keepdisc then
+ keepdisc=false
+ if notmatchpre[current]~=notmatchreplace[current] then
+ lookaheaddisc=current
+ end
+ local replace=getfield(c,"replace")
+ while replace and i<s do
+ if getid(replace)==glyph_code then
+ i=i+1
end
- break
+ replace=getnext(replace)
end
+ current=getnext(current)
+ elseif notmatchpre[current]~=notmatchreplace[current] then
+ head,current=flattendisk(head,current)
+ else
+ current=getnext(current)
+ end
+ else
+ current=getnext(current)
+ end
+ if not current and t then
+ current=getnext(sweepnode)
+ if current then
+ sweeptype=nil
end
- return head,start,done
end
end
end
- return head,start,false
-end
-chainmores.gpos_pair=chainprocs.gpos_pair
-local function show_skip(kind,chainname,char,ck,class)
- if ck[9] then
- logwarning("%s: skipping char %s, class %a, rule %a, lookuptype %a, %a => %a",cref(kind,chainname),gref(char),class,ck[1],ck[2],ck[9],ck[10])
+ if f>1 then
+ local current=prev
+ local i=f
+ local t=sweeptype=="pre" or sweeptype=="replace"
+ if not current and t and current==checkdisk then
+ current=getprev(sweepnode)
+ end
+ while current and i>1 do
+ local id=getid(current)
+ if id==glyph_code then
+ i=i-1
+ elseif id==disc_code then
+ if keepdisc then
+ keepdisc=false
+ if notmatchpost[current]~=notmatchreplace[current] then
+ backtrackdisc=current
+ end
+ local replace=getfield(current,"replace")
+ while replace and i>1 do
+ if getid(replace)==glyph_code then
+ i=i-1
+ end
+ replace=getnext(replace)
+ end
+ elseif notmatchpost[current]~=notmatchreplace[current] then
+ head,current=flattendisk(head,current)
+ end
+ end
+ current=getprev(current)
+ if t and current==checkdisk then
+ current=getprev(sweepnode)
+ end
+ end
+ end
+ local ok=false
+ if lookaheaddisc then
+ local cf=start
+ local cl=getprev(lookaheaddisc)
+ local cprev=getprev(start)
+ local insertedmarks=0
+ while cprev and getid(cf)==glyph_code and getfont(cf)==currentfont and getsubtype(cf)<256 and marks[getchar(cf)] do
+ insertedmarks=insertedmarks+1
+ cf=cprev
+ startishead=cf==head
+ cprev=getprev(cprev)
+ end
+ setfield(lookaheaddisc,"prev",cprev)
+ if cprev then
+ setfield(cprev,"next",lookaheaddisc)
+ end
+ setfield(cf,"prev",nil)
+ setfield(cl,"next",nil)
+ if startishead then
+ head=lookaheaddisc
+ end
+ local replace=getfield(lookaheaddisc,"replace")
+ local pre=getfield(lookaheaddisc,"pre")
+ local new=copy_node_list(cf)
+ local cnew=new
+ for i=1,insertedmarks do
+ cnew=getnext(cnew)
+ end
+ local clast=cnew
+ for i=f,l do
+ clast=getnext(clast)
+ end
+ if not notmatchpre[lookaheaddisc] then
+ cf,start,ok=chainproc(cf,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ end
+ if not notmatchreplace[lookaheaddisc] then
+ new,cnew,ok=chainproc(new,cnew,clast,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ end
+ if pre then
+ setfield(cl,"next",pre)
+ setfield(pre,"prev",cl)
+ end
+ if replace then
+ local tail=find_node_tail(new)
+ setfield(tail,"next",replace)
+ setfield(replace,"prev",tail)
+ end
+ setfield(lookaheaddisc,"pre",cf)
+ setfield(lookaheaddisc,"replace",new)
+ start=getprev(lookaheaddisc)
+ sweephead[cf]=getnext(clast)
+ sweephead[new]=getnext(last)
+ elseif backtrackdisc then
+ local cf=getnext(backtrackdisc)
+ local cl=start
+ local cnext=getnext(start)
+ local insertedmarks=0
+ while cnext and getid(cnext)==glyph_code and getfont(cnext)==currentfont and getsubtype(cnext)<256 and marks[getchar(cnext)] do
+ insertedmarks=insertedmarks+1
+ cl=cnext
+ cnext=getnext(cnext)
+ end
+ if cnext then
+ setfield(cnext,"prev",backtrackdisc)
+ end
+ setfield(backtrackdisc,"next",cnext)
+ setfield(cf,"prev",nil)
+ setfield(cl,"next",nil)
+ local replace=getfield(backtrackdisc,"replace")
+ local post=getfield(backtrackdisc,"post")
+ local new=copy_node_list(cf)
+ local cnew=find_node_tail(new)
+ for i=1,insertedmarks do
+ cnew=getprev(cnew)
+ end
+ local clast=cnew
+ for i=f,l do
+ clast=getnext(clast)
+ end
+ if not notmatchpost[backtrackdisc] then
+ cf,start,ok=chainproc(cf,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ end
+ if not notmatchreplace[backtrackdisc] then
+ new,cnew,ok=chainproc(new,cnew,clast,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ end
+ if post then
+ local tail=find_node_tail(post)
+ setfield(tail,"next",cf)
+ setfield(cf,"prev",tail)
+ else
+ post=cf
+ end
+ if replace then
+ local tail=find_node_tail(replace)
+ setfield(tail,"next",new)
+ setfield(new,"prev",tail)
+ else
+ replace=new
+ end
+ setfield(backtrackdisc,"post",post)
+ setfield(backtrackdisc,"replace",replace)
+ start=getprev(backtrackdisc)
+ sweephead[post]=getnext(clast)
+ sweephead[replace]=getnext(last)
else
- logwarning("%s: skipping char %s, class %a, rule %a, lookuptype %a",cref(kind,chainname),gref(char),class,ck[1],ck[2])
+ head,start,ok=chainproc(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
end
+ return head,start,ok
end
-local quit_on_no_replacement=true
-directives.register("otf.chain.quitonnoreplacement",function(value)
- quit_on_no_replacement=value
-end)
local function normal_handle_contextchain(head,start,kind,chainname,contexts,sequence,lookuphash)
+ local sweepnode=sweepnode
+ local sweeptype=sweeptype
+ local diskseen=false
+ local checkdisc=getprev(head)
local flags=sequence.flags
local done=false
local skipmark=flags[1]
local skipligature=flags[2]
local skipbase=flags[3]
- local someskip=skipmark or skipligature or skipbase
- local markclass=sequence.markclass
+ local markclass=sequence.markclass
local skipped=false
- for k=1,#contexts do
+ for k=1,#contexts do
local match=true
local current=start
local last=start
@@ -8894,14 +9584,20 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
if s==1 then
match=getid(current)==glyph_code and getfont(current)==currentfont and getsubtype(current)<256 and seq[1][getchar(current)]
else
- local f,l=ck[4],ck[5]
+ local f=ck[4]
+ local l=ck[5]
if f==1 and f==l then
else
if f==l then
else
+ local discfound=nil
local n=f+1
last=getnext(last)
while n<=l do
+ if not last and (sweeptype=="post" or sweeptype=="replace") then
+ last=getnext(sweepnode)
+ sweeptype=nil
+ end
if last then
local id=getid(last)
if id==glyph_code then
@@ -8909,7 +9605,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
local char=getchar(last)
local ccd=descriptions[char]
if ccd then
- local class=ccd.class
+ local class=ccd.class or "base"
if class==skipmark or class==skipligature or class==skipbase or (markclass and class=="mark" and not markclass[char]) then
skipped=true
if trace_skips then
@@ -8922,18 +9618,76 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
end
n=n+1
else
- match=false
+ if discfound then
+ notmatchreplace[discfound]=true
+ match=not notmatchpre[discfound]
+ else
+ match=false
+ end
break
end
else
- match=false
+ if discfound then
+ notmatchreplace[discfound]=true
+ match=not notmatchpre[discfound]
+ else
+ match=false
+ end
break
end
else
- match=false
+ if discfound then
+ notmatchreplace[discfound]=true
+ match=not notmatchpre[discfound]
+ else
+ match=false
+ end
break
end
elseif id==disc_code then
+ diskseen=true
+ discfound=last
+ notmatchpre[last]=nil
+ notmatchpost[last]=true
+ notmatchreplace[last]=nil
+ local pre=getfield(last,"pre")
+ local replace=getfield(last,"replace")
+ if pre then
+ local n=n
+ while pre do
+ if seq[n][getchar(pre)] then
+ n=n+1
+ pre=getnext(pre)
+ if n>l then
+ break
+ end
+ else
+ notmatchpre[last]=true
+ break
+ end
+ end
+ if n<=l then
+ notmatchpre[last]=true
+ end
+ else
+ notmatchpre[last]=true
+ end
+ if replace then
+ while replace do
+ if seq[n][getchar(replace)] then
+ n=n+1
+ replace=getnext(replace)
+ if n>l then
+ break
+ end
+ else
+ notmatchreplace[last]=true
+ match=not notmatchpre[last]
+ break
+ end
+ end
+ match=not notmatchpre[last]
+ end
last=getnext(last)
else
match=false
@@ -8949,49 +9703,132 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
if match and f>1 then
local prev=getprev(start)
if prev then
- local n=f-1
- while n>=1 do
- if prev then
- local id=getid(prev)
- if id==glyph_code then
- if getfont(prev)==currentfont and getsubtype(prev)<256 then
- local char=getchar(prev)
- local ccd=descriptions[char]
- if ccd then
- local class=ccd.class
- if class==skipmark or class==skipligature or class==skipbase or (markclass and class=="mark" and not markclass[char]) then
- skipped=true
- if trace_skips then
- show_skip(kind,chainname,char,ck,class)
+ if prev==checkdisc and (sweeptype=="pre" or sweeptype=="replace") then
+ prev=getprev(sweepnode)
+ end
+ if prev then
+ local discfound=nil
+ local n=f-1
+ while n>=1 do
+ if prev then
+ local id=getid(prev)
+ if id==glyph_code then
+ if getfont(prev)==currentfont and getsubtype(prev)<256 then
+ local char=getchar(prev)
+ local ccd=descriptions[char]
+ if ccd then
+ local class=ccd.class
+ if class==skipmark or class==skipligature or class==skipbase or (markclass and class=="mark" and not markclass[char]) then
+ skipped=true
+ if trace_skips then
+ show_skip(kind,chainname,char,ck,class)
+ end
+ elseif seq[n][char] then
+ n=n -1
+ else
+ if discfound then
+ notmatchreplace[discfound]=true
+ match=not notmatchpost[discfound]
+ else
+ match=false
+ end
+ break
end
- elseif seq[n][char] then
- n=n -1
else
- match=false
+ if discfound then
+ notmatchreplace[discfound]=true
+ match=not notmatchpost[discfound]
+ else
+ match=false
+ end
break
end
else
- match=false
+ if discfound then
+ notmatchreplace[discfound]=true
+ match=not notmatchpost[discfound]
+ else
+ match=false
+ end
break
end
+ elseif id==disc_code then
+ diskseen=true
+ discfound=prev
+ notmatchpre[prev]=true
+ notmatchpost[prev]=nil
+ notmatchreplace[prev]=nil
+ local pre=getfield(prev,"pre")
+ local post=getfield(prev,"post")
+ local replace=getfield(prev,"replace")
+ if pre~=start and post~=start and replace~=start then
+ if post then
+ local n=n
+ local posttail=find_node_tail(post)
+ while posttail do
+ if seq[n][getchar(posttail)] then
+ n=n-1
+ if posttail==post then
+ break
+ else
+ posttail=getprev(posttail)
+ if n<1 then
+ break
+ end
+ end
+ else
+ notmatchpost[prev]=true
+ break
+ end
+ end
+ if n>=1 then
+ notmatchpost[prev]=true
+ end
+ else
+ notmatchpost[prev]=true
+ end
+ if replace then
+ local replacetail=find_node_tail(replace)
+ while replacetail do
+ if seq[n][getchar(replacetail)] then
+ n=n-1
+ if replacetail==replace then
+ break
+ else
+ replacetail=getprev(replacetail)
+ if n<1 then
+ break
+ end
+ end
+ else
+ notmatchreplace[prev]=true
+ match=not notmatchpost[prev]
+ break
+ end
+ end
+ if not match then
+ break
+ end
+ else
+ end
+ else
+ end
+ elseif seq[n][32] then
+ n=n -1
else
match=false
break
end
- elseif id==disc_code then
- elseif seq[n][32] then
- n=n -1
+ prev=getprev(prev)
+ elseif seq[n][32] then
+ n=n-1
else
match=false
break
end
- prev=getprev(prev)
- elseif seq[n][32] then
- n=n -1
- else
- match=false
- break
end
+ else
+ match=false
end
else
match=false
@@ -8999,7 +9836,13 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
end
if match and s>l then
local current=last and getnext(last)
+ if not current then
+ if sweeptype=="post" or sweeptype=="replace" then
+ current=getnext(sweepnode)
+ end
+ end
if current then
+ local discfound=nil
local n=l+1
while n<=s do
if current then
@@ -9018,18 +9861,79 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
elseif seq[n][char] then
n=n+1
else
- match=false
+ if discfound then
+ notmatchreplace[discfound]=true
+ match=not notmatchpre[discfound]
+ else
+ match=false
+ end
break
end
else
- match=false
+ if discfound then
+ notmatchreplace[discfound]=true
+ match=not notmatchpre[discfound]
+ else
+ match=false
+ end
break
end
else
- match=false
+ if discfound then
+ notmatchreplace[discfound]=true
+ match=not notmatchpre[discfound]
+ else
+ match=false
+ end
break
end
elseif id==disc_code then
+ diskseen=true
+ discfound=current
+ notmatchpre[current]=nil
+ notmatchpost[current]=true
+ notmatchreplace[current]=nil
+ local pre=getfield(current,"pre")
+ local replace=getfield(current,"replace")
+ if pre then
+ local n=n
+ while pre do
+ if seq[n][getchar(pre)] then
+ n=n+1
+ pre=getnext(pre)
+ if n>s then
+ break
+ end
+ else
+ notmatchpre[current]=true
+ break
+ end
+ end
+ if n<=s then
+ notmatchpre[current]=true
+ end
+ else
+ notmatchpre[current]=true
+ end
+ if replace then
+ while replace do
+ if seq[n][getchar(replace)] then
+ n=n+1
+ replace=getnext(replace)
+ if n>s then
+ break
+ end
+ else
+ notmatchreplace[current]=true
+ match=notmatchpre[current]
+ break
+ end
+ end
+ if not match then
+ break
+ end
+ else
+ end
elseif seq[n][32] then
n=n+1
else
@@ -9050,6 +9954,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
end
end
if match then
+ local diskchain=diskseen or sweepnode
if trace_contexts then
local rule,lookuptype,f,l=ck[1],ck[2],ck[4],ck[5]
local char=getchar(start)
@@ -9068,10 +9973,14 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
local chainlookupname=chainlookups[1]
local chainlookup=lookuptable[chainlookupname]
if chainlookup then
- local cp=chainprocs[chainlookup.type]
- if cp then
+ local chainproc=chainprocs[chainlookup.type]
+ if chainproc then
local ok
- head,start,ok=cp(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ if diskchain then
+ head,start,ok=chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence,chainproc)
+ else
+ head,start,ok=chainproc(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ end
if ok then
done=true
end
@@ -9083,13 +9992,13 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
end
else
local i=1
- while true do
+ while start and true do
if skipped then
- while true do
+ while true do
local char=getchar(start)
local ccd=descriptions[char]
if ccd then
- local class=ccd.class
+ local class=ccd.class or "base"
if class==skipmark or class==skipligature or class==skipbase or (markclass and class=="mark" and not markclass[char]) then
start=getnext(start)
else
@@ -9105,26 +10014,33 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
if not chainlookup then
i=i+1
else
- local cp=chainmores[chainlookup.type]
- if not cp then
+ local chainproc=chainprocs[chainlookup.type]
+ if not chainproc then
logprocess("%s: %s is not yet supported",cref(kind,chainname,chainlookupname),chainlookup.type)
i=i+1
else
local ok,n
- head,start,ok,n=cp(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,i,sequence)
+ if diskchain then
+ head,start,ok=chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence,chainproc)
+ else
+ head,start,ok,n=chainproc(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,i,sequence)
+ end
if ok then
done=true
- i=i+(n or 1)
- else
- i=i+1
+ if n and n>1 then
+ if i+n>nofchainlookups then
+ break
+ else
+ end
+ end
end
+ i=i+1
end
end
- if i>nofchainlookups then
+ if i>nofchainlookups or not start then
break
elseif start then
start=getnext(start)
- else
end
end
end
@@ -9139,8 +10055,16 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
end
end
end
+ if done then
+ break
+ end
end
end
+ if diskseen then
+ notmatchpre={}
+ notmatchpost={}
+ notmatchreplace={}
+ end
return head,start,done
end
local verbose_handle_contextchain=function(font,...)
@@ -9211,7 +10135,7 @@ local function initialize(sequence,script,language,enabled)
local scripts=features[kind]
local languages=scripts[script] or scripts[wildcard]
if languages and (languages[language] or languages[wildcard]) then
- return { valid,autofeatures[kind] or false,sequence.chain or 0,kind,sequence }
+ return { valid,autofeatures[kind] or false,sequence,kind }
end
end
end
@@ -9251,6 +10175,175 @@ function otf.dataset(tfmdata,font)
end
return rl
end
+local function kernrun(disc,run)
+ if trace_kernruns then
+ report_run("kern")
+ end
+ local prev=getprev(disc)
+ local next=getnext(disc)
+ local pre=getfield(disc,"pre")
+ local post=getfield(disc,"post")
+ local replace=getfield(disc,"replace")
+ local prevmarks=prev
+ while prevmarks and getid(prevmarks)==glyph_code and marks[getchar(prevmarks)] and getfont(prevmarks)==currentfont and getsubtype(prevmarks)<256 do
+ prevmarks=getprev(prevmarks)
+ end
+ if prev and (pre or replace) and not (getid(prev)==glyph_code and getfont(prev)==currentfont and getsubtype(prev)<256) then
+ prev=false
+ end
+ if next and (post or replace) and not (getid(next)==glyph_code and getfont(next)==currentfont and getsubtype(next)<256) then
+ next=false
+ end
+ if not pre then
+ elseif prev then
+ local nest=getprev(pre)
+ setfield(pre,"prev",prev)
+ setfield(prev,"next",pre)
+ run(prevmarks,"preinjections")
+ setfield(pre,"prev",nest)
+ setfield(prev,"next",disc)
+ else
+ run(pre,"preinjections")
+ end
+ if not post then
+ elseif next then
+ local tail=find_node_tail(post)
+ setfield(tail,"next",next)
+ setfield(next,"prev",tail)
+ run(post,"postinjections",next)
+ setfield(tail,"next",nil)
+ setfield(next,"prev",disc)
+ else
+ run(post,"postinjections")
+ end
+ if not replace and prev and next then
+ setfield(prev,"next",next)
+ setfield(next,"prev",prev)
+ run(prevmarks,"injections",next)
+ setfield(prev,"next",disc)
+ setfield(next,"prev",disc)
+ elseif prev and next then
+ local tail=find_node_tail(replace)
+ local nest=getprev(replace)
+ setfield(replace,"prev",prev)
+ setfield(prev,"next",replace)
+ setfield(tail,"next",next)
+ setfield(next,"prev",tail)
+ run(prevmarks,"replaceinjections",next)
+ setfield(replace,"prev",nest)
+ setfield(prev,"next",disc)
+ setfield(tail,"next",nil)
+ setfield(next,"prev",disc)
+ elseif prev then
+ local nest=getprev(replace)
+ setfield(replace,"prev",prev)
+ setfield(prev,"next",replace)
+ run(prevmarks,"replaceinjections")
+ setfield(replace,"prev",nest)
+ setfield(prev,"next",disc)
+ elseif next then
+ local tail=find_node_tail(replace)
+ setfield(tail,"next",next)
+ setfield(next,"prev",tail)
+ run(replace,"replaceinjections",next)
+ setfield(tail,"next",nil)
+ setfield(next,"prev",disc)
+ else
+ run(replace,"replaceinjections")
+ end
+end
+local function comprun(disc,run)
+ if trace_compruns then
+ report_run("comp: %s",languages.serializediscretionary(disc))
+ end
+ local pre=getfield(disc,"pre")
+ if pre then
+ sweepnode=disc
+ sweeptype="pre"
+ local new,done=run(pre)
+ if done then
+ setfield(disc,"pre",new)
+ end
+ end
+ local post=getfield(disc,"post")
+ if post then
+ sweepnode=disc
+ sweeptype="post"
+ local new,done=run(post)
+ if done then
+ setfield(disc,"post",new)
+ end
+ end
+ local replace=getfield(disc,"replace")
+ if replace then
+ sweepnode=disc
+ sweeptype="replace"
+ local new,done=run(replace)
+ if done then
+ setfield(disc,"replace",new)
+ end
+ end
+ sweepnode=nil
+ sweeptype=nil
+end
+local function testrun(disc,trun,crun)
+ local next=getnext(disc)
+ if next then
+ local replace=getfield(disc,"replace")
+ if replace then
+ local prev=getprev(disc)
+ if prev then
+ local tail=find_node_tail(replace)
+ setfield(tail,"next",next)
+ setfield(next,"prev",tail)
+ if trun(replace,next) then
+ setfield(disc,"replace",nil)
+ setfield(prev,"next",replace)
+ setfield(replace,"prev",prev)
+ setfield(next,"prev",tail)
+ setfield(tail,"next",next)
+ setfield(disc,"prev",nil)
+ setfield(disc,"next",nil)
+ flush_node_list(disc)
+ return replace
+ else
+ setfield(tail,"next",nil)
+ setfield(next,"prev",disc)
+ end
+ else
+ end
+ else
+ end
+ else
+ end
+ comprun(disc,crun)
+ return next
+end
+local function discrun(disc,drun,krun)
+ local next=getnext(disc)
+ local prev=getprev(disc)
+ if trace_discruns then
+ report_run("disc")
+ end
+ if next and prev then
+ setfield(prev,"next",next)
+ drun(prev)
+ setfield(prev,"next",disc)
+ end
+ local pre=getfield(disc,"pre")
+ if not pre then
+ elseif prev then
+ local nest=getprev(pre)
+ setfield(pre,"prev",prev)
+ setfield(prev,"next",pre)
+ krun(prev,"preinjections")
+ setfield(pre,"prev",nest)
+ setfield(prev,"next",disc)
+ else
+ krun(pre,"preinjections")
+ end
+ return next
+end
local function featuresprocessor(head,font,attr)
local lookuphash=lookuphashes[font]
if not lookuphash then
@@ -9271,23 +10364,25 @@ local function featuresprocessor(head,font,attr)
lookuptags=resources.lookuptags
currentfont=font
rlmode=0
+ sweephead={}
local sequences=resources.sequences
local done=false
local datasets=otf.dataset(tfmdata,font,attr)
local dirstack={}
for s=1,#datasets do
local dataset=datasets[s]
- featurevalue=dataset[1]
- local sequence=dataset[5]
+ featurevalue=dataset[1]
+ local attribute=dataset[2]
+ local sequence=dataset[3]
+ local kind=dataset[4]
local rlparmode=0
local topstack=0
local success=false
- local attribute=dataset[2]
- local chain=dataset[3]
local typ=sequence.type
+ local gpossing=typ=="gpos_single" or typ=="gpos_pair"
local subtables=sequence.subtables
- if chain<0 then
- local handler=handlers[typ]
+ local handler=handlers[typ]
+ if typ=="gsub_reversecontextchain" then
local start=find_node_tail(head)
while start do
local id=getid(start)
@@ -9300,13 +10395,14 @@ local function featuresprocessor(head,font,attr)
a=true
end
if a then
+ local char=getchar(start)
for i=1,#subtables do
local lookupname=subtables[i]
local lookupcache=lookuphash[lookupname]
if lookupcache then
- local lookupmatch=lookupcache[getchar(start)]
+ local lookupmatch=lookupcache[char]
if lookupmatch then
- head,start,success=handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
+ head,start,success=handler(head,start,kind,lookupname,lookupmatch,sequence,lookuphash,i)
if success then
break
end
@@ -9327,7 +10423,6 @@ local function featuresprocessor(head,font,attr)
end
end
else
- local handler=handlers[typ]
local ns=#subtables
local start=head
rlmode=0
@@ -9337,12 +10432,19 @@ local function featuresprocessor(head,font,attr)
if not lookupcache then
report_missing_cache(typ,lookupname)
else
- local function subrun(start)
- local head=start
+ local function c_run(head)
local done=false
+ local start=sweephead[head]
+ if start then
+ sweephead[head]=nil
+ else
+ start=head
+ end
while start do
local id=getid(start)
- if id==glyph_code and getfont(start)==font and getsubtype(start)<256 then
+ if id~=glyph_code then
+ start=getnext(start)
+ elseif getfont(start)==font and getsubtype(start)<256 then
local a=getattr(start,0)
if a then
a=(a==attr) and (not attribute or getprop(start,a_state)==attribute)
@@ -9353,7 +10455,7 @@ local function featuresprocessor(head,font,attr)
local lookupmatch=lookupcache[getchar(start)]
if lookupmatch then
local ok
- head,start,ok=handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1)
+ head,start,ok=handler(head,start,kind,lookupname,lookupmatch,sequence,lookuphash,1)
if ok then
done=true
end
@@ -9363,43 +10465,98 @@ local function featuresprocessor(head,font,attr)
start=getnext(start)
end
else
- start=getnext(start)
+ return head,false
end
end
if done then
- success=true
- return head
+ success=true
end
+ return head,done
end
- local function kerndisc(disc)
- local prev=getprev(disc)
- local next=getnext(disc)
- if prev and next then
- setfield(prev,"next",next)
- local a=getattr(prev,0)
- if a then
- a=(a==attr) and (not attribute or getprop(prev,a_state)==attribute)
+ local function t_run(start,stop)
+ while start~=stop do
+ local id=getid(start)
+ if id==glyph_code and getfont(start)==font and getsubtype(start)<256 then
+ local a=getattr(start,0)
+ if a then
+ a=(a==attr) and (not attribute or getprop(start,a_state)==attribute)
+ else
+ a=not attribute or getprop(start,a_state)==attribute
+ end
+ if a then
+ local lookupmatch=lookupcache[getchar(start)]
+ if lookupmatch then
+ local s=getnext(start)
+ local l=nil
+ while s do
+ local lg=lookupmatch[getchar(s)]
+ if lg then
+ l=lg
+ s=getnext(s)
+ else
+ break
+ end
+ end
+ if l and l.ligature then
+ return true
+ end
+ end
+ end
+ start=getnext(start)
else
- a=not attribute or getprop(prev,a_state)==attribute
+ break
end
- if a then
- local lookupmatch=lookupcache[getchar(prev)]
- if lookupmatch then
- local h,d,ok=handler(head,prev,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1)
- if ok then
- done=true
- success=true
+ end
+ end
+ local function d_run(prev)
+ local a=getattr(prev,0)
+ if a then
+ a=(a==attr) and (not attribute or getprop(prev,a_state)==attribute)
+ else
+ a=not attribute or getprop(prev,a_state)==attribute
+ end
+ if a then
+ local lookupmatch=lookupcache[getchar(prev)]
+ if lookupmatch then
+ local h,d,ok=handler(head,prev,kind,lookupname,lookupmatch,sequence,lookuphash,1)
+ if ok then
+ done=true
+ success=true
+ end
+ end
+ end
+ end
+ local function k_run(sub,injection,last)
+ local a=getattr(sub,0)
+ if a then
+ a=(a==attr) and (not attribute or getprop(sub,a_state)==attribute)
+ else
+ a=not attribute or getprop(sub,a_state)==attribute
+ end
+ if a then
+ for n in traverse_nodes(sub) do
+ if n==last then
+ break
+ end
+ local id=getid(n)
+ if id==glyph_code then
+ local lookupmatch=lookupcache[getchar(n)]
+ if lookupmatch then
+ local h,d,ok=handler(sub,n,kind,lookupname,lookupmatch,sequence,lookuphash,1,injection)
+ if ok then
+ done=true
+ success=true
+ end
end
+ else
end
end
- setfield(prev,"next",disc)
end
- return next
end
while start do
local id=getid(start)
if id==glyph_code then
- if getfont(start)==font and getsubtype(start)<256 then
+ if getfont(start)==font and getsubtype(start)<256 then
local a=getattr(start,0)
if a then
a=(a==attr) and (not attribute or getprop(start,a_state)==attribute)
@@ -9407,13 +10564,18 @@ local function featuresprocessor(head,font,attr)
a=not attribute or getprop(start,a_state)==attribute
end
if a then
- local lookupmatch=lookupcache[getchar(start)]
+ local char=getchar(start)
+ local lookupmatch=lookupcache[char]
if lookupmatch then
local ok
- head,start,ok=handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1)
+ head,start,ok=handler(head,start,kind,lookupname,lookupmatch,sequence,lookuphash,1)
if ok then
success=true
+ elseif gpossing and zwnjruns and char==zwnj then
+ discrun(start,d_run)
end
+ elseif gpossing and zwnjruns and char==zwnj then
+ discrun(start,d_run)
end
if start then start=getnext(start) end
else
@@ -9423,62 +10585,15 @@ local function featuresprocessor(head,font,attr)
start=getnext(start)
end
elseif id==disc_code then
- if getsubtype(start)==discretionary_code then
- local pre=getfield(start,"pre")
- if pre then
- local new=subrun(pre)
- if new then setfield(start,"pre",new) end
- end
- local post=getfield(start,"post")
- if post then
- local new=subrun(post)
- if new then setfield(start,"post",new) end
- end
- local replace=getfield(start,"replace")
- if replace then
- local new=subrun(replace)
- if new then setfield(start,"replace",new) end
- end
-elseif typ=="gpos_single" or typ=="gpos_pair" then
- kerndisc(start)
- end
- start=getnext(start)
- elseif id==whatsit_code then
- local subtype=getsubtype(start)
- if subtype==dir_code then
- local dir=getfield(start,"dir")
- if dir=="+TRT" or dir=="+TLT" then
- topstack=topstack+1
- dirstack[topstack]=dir
- elseif dir=="-TRT" or dir=="-TLT" then
- topstack=topstack-1
- end
- local newdir=dirstack[topstack]
- if newdir=="+TRT" then
- rlmode=-1
- elseif newdir=="+TLT" then
- rlmode=1
- else
- rlmode=rlparmode
- end
- if trace_directions then
- report_process("directions after txtdir %a: parmode %a, txtmode %a, # stack %a, new dir %a",dir,rlparmode,rlmode,topstack,newdir)
- end
- elseif subtype==localpar_code then
- local dir=getfield(start,"dir")
- if dir=="TRT" then
- rlparmode=-1
- elseif dir=="TLT" then
- rlparmode=1
- else
- rlparmode=0
- end
- rlmode=rlparmode
- if trace_directions then
- report_process("directions after pardir %a: parmode %a, txtmode %a",dir,rlparmode,rlmode)
- end
+ if gpossing then
+ kernrun(start,k_run)
+ start=getnext(start)
+ elseif typ=="gsub_ligature" then
+ start=testrun(start,t_run,c_run)
+ else
+ comprun(start,c_run)
+ start=getnext(start)
end
- start=getnext(start)
elseif id==math_code then
start=getnext(end_of_math(start))
else
@@ -9487,12 +10602,19 @@ elseif typ=="gpos_single" or typ=="gpos_pair" then
end
end
else
- local function subrun(start)
- local head=start
+ local function c_run(head)
local done=false
+ local start=sweephead[head]
+ if start then
+ sweephead[head]=nil
+ else
+ start=head
+ end
while start do
local id=getid(start)
- if id==glyph_code and getfont(start)==font and getsubtype(start)<256 then
+ if id~=glyph_code then
+ start=getnext(start)
+ elseif getfont(start)==font and getsubtype(start)<256 then
local a=getattr(start,0)
if a then
a=(a==attr) and (not attribute or getprop(start,a_state)==attribute)
@@ -9500,14 +10622,15 @@ elseif typ=="gpos_single" or typ=="gpos_pair" then
a=not attribute or getprop(start,a_state)==attribute
end
if a then
+ local char=getchar(start)
for i=1,ns do
local lookupname=subtables[i]
local lookupcache=lookuphash[lookupname]
if lookupcache then
- local lookupmatch=lookupcache[getchar(start)]
+ local lookupmatch=lookupcache[char]
if lookupmatch then
local ok
- head,start,ok=handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
+ head,start,ok=handler(head,start,kind,lookupname,lookupmatch,sequence,lookuphash,i)
if ok then
done=true
break
@@ -9524,46 +10647,120 @@ elseif typ=="gpos_single" or typ=="gpos_pair" then
start=getnext(start)
end
else
- start=getnext(start)
+ return head,false
end
end
if done then
success=true
- return head
end
+ return head,done
end
- local function kerndisc(disc)
- local prev=getprev(disc)
- local next=getnext(disc)
- if prev and next then
- setfield(prev,"next",next)
- local a=getattr(prev,0)
- if a then
- a=(a==attr) and (not attribute or getprop(prev,a_state)==attribute)
- else
- a=not attribute or getprop(prev,a_state)==attribute
+ local function d_run(prev)
+ local a=getattr(prev,0)
+ if a then
+ a=(a==attr) and (not attribute or getprop(prev,a_state)==attribute)
+ else
+ a=not attribute or getprop(prev,a_state)==attribute
+ end
+ if a then
+ local char=getchar(prev)
+ for i=1,ns do
+ local lookupname=subtables[i]
+ local lookupcache=lookuphash[lookupname]
+ if lookupcache then
+ local lookupmatch=lookupcache[char]
+ if lookupmatch then
+ local h,d,ok=handler(head,prev,kind,lookupname,lookupmatch,sequence,lookuphash,i)
+ if ok then
+ done=true
+ break
+ end
+ end
+ else
+ report_missing_cache(typ,lookupname)
+ end
end
- if a then
- for i=1,ns do
- local lookupname=subtables[i]
- local lookupcache=lookuphash[lookupname]
- if lookupcache then
- local lookupmatch=lookupcache[getchar(prev)]
- if lookupmatch then
- local h,d,ok=handler(head,prev,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
- if ok then
- done=true
- break
+ end
+ end
+ local function k_run(sub,injection,last)
+ local a=getattr(sub,0)
+ if a then
+ a=(a==attr) and (not attribute or getprop(sub,a_state)==attribute)
+ else
+ a=not attribute or getprop(sub,a_state)==attribute
+ end
+ if a then
+ for n in traverse_nodes(sub) do
+ if n==last then
+ break
+ end
+ local id=getid(n)
+ if id==glyph_code then
+ local char=getchar(n)
+ for i=1,ns do
+ local lookupname=subtables[i]
+ local lookupcache=lookuphash[lookupname]
+ if lookupcache then
+ local lookupmatch=lookupcache[char]
+ if lookupmatch then
+ local h,d,ok=handler(head,n,kind,lookupname,lookupmatch,sequence,lookuphash,i,injection)
+ if ok then
+ done=true
+ break
+ end
end
+ else
+ report_missing_cache(typ,lookupname)
end
- else
- report_missing_cache(typ,lookupname)
end
+ else
end
end
- setfield(prev,"next",disc)
end
- return next
+ end
+ local function t_run(start,stop)
+ while start~=stop do
+ local id=getid(start)
+ if id==glyph_code and getfont(start)==font and getsubtype(start)<256 then
+ local a=getattr(start,0)
+ if a then
+ a=(a==attr) and (not attribute or getprop(start,a_state)==attribute)
+ else
+ a=not attribute or getprop(start,a_state)==attribute
+ end
+ if a then
+ local char=getchar(start)
+ for i=1,ns do
+ local lookupname=subtables[i]
+ local lookupcache=lookuphash[lookupname]
+ if lookupcache then
+ local lookupmatch=lookupcache[char]
+ if lookupmatch then
+ local s=getnext(start)
+ local l=nil
+ while s do
+ local lg=lookupmatch[getchar(s)]
+ if lg then
+ l=lg
+ s=getnext(s)
+ else
+ break
+ end
+ end
+ if l and l.ligature then
+ return true
+ end
+ end
+ else
+ report_missing_cache(typ,lookupname)
+ end
+ end
+ end
+ start=getnext(start)
+ else
+ break
+ end
+ end
end
while start do
local id=getid(start)
@@ -9580,16 +10777,21 @@ elseif typ=="gpos_single" or typ=="gpos_pair" then
local lookupname=subtables[i]
local lookupcache=lookuphash[lookupname]
if lookupcache then
- local lookupmatch=lookupcache[getchar(start)]
+ local char=getchar(start)
+ local lookupmatch=lookupcache[char]
if lookupmatch then
local ok
- head,start,ok=handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
+ head,start,ok=handler(head,start,kind,lookupname,lookupmatch,sequence,lookuphash,i)
if ok then
success=true
break
elseif not start then
break
+ elseif gpossing and zwnjruns and char==zwnj then
+ discrun(start,d_run)
end
+ elseif gpossing and zwnjruns and char==zwnj then
+ discrun(start,d_run)
end
else
report_missing_cache(typ,lookupname)
@@ -9603,62 +10805,15 @@ elseif typ=="gpos_single" or typ=="gpos_pair" then
start=getnext(start)
end
elseif id==disc_code then
- if getsubtype(start)==discretionary_code then
- local pre=getfield(start,"pre")
- if pre then
- local new=subrun(pre)
- if new then setfield(start,"pre",new) end
- end
- local post=getfield(start,"post")
- if post then
- local new=subrun(post)
- if new then setfield(start,"post",new) end
- end
- local replace=getfield(start,"replace")
- if replace then
- local new=subrun(replace)
- if new then setfield(start,"replace",new) end
- end
-elseif typ=="gpos_single" or typ=="gpos_pair" then
- kerndisc(start)
- end
- start=getnext(start)
- elseif id==whatsit_code then
- local subtype=getsubtype(start)
- if subtype==dir_code then
- local dir=getfield(start,"dir")
- if dir=="+TRT" or dir=="+TLT" then
- topstack=topstack+1
- dirstack[topstack]=dir
- elseif dir=="-TRT" or dir=="-TLT" then
- topstack=topstack-1
- end
- local newdir=dirstack[topstack]
- if newdir=="+TRT" then
- rlmode=-1
- elseif newdir=="+TLT" then
- rlmode=1
- else
- rlmode=rlparmode
- end
- if trace_directions then
- report_process("directions after txtdir %a: parmode %a, txtmode %a, # stack %a, new dir %a",dir,rlparmode,rlmode,topstack,newdir)
- end
- elseif subtype==localpar_code then
- local dir=getfield(start,"dir")
- if dir=="TRT" then
- rlparmode=-1
- elseif dir=="TLT" then
- rlparmode=1
- else
- rlparmode=0
- end
- rlmode=rlparmode
- if trace_directions then
- report_process("directions after pardir %a: parmode %a, txtmode %a",dir,rlparmode,rlmode)
- end
+ if gpossing then
+ kernrun(start,k_run)
+ start=getnext(start)
+ elseif typ=="gsub_ligature" then
+ start=testrun(start,t_run,c_run)
+ else
+ comprun(start,c_run)
+ start=getnext(start)
end
- start=getnext(start)
elseif id==math_code then
start=getnext(end_of_math(start))
else
@@ -9685,43 +10840,46 @@ local function generic(lookupdata,lookupname,unicode,lookuphash)
lookuphash[lookupname]={ [unicode]=lookupdata }
end
end
+local function ligature(lookupdata,lookupname,unicode,lookuphash)
+ local target=lookuphash[lookupname]
+ if not target then
+ target={}
+ lookuphash[lookupname]=target
+ end
+ for i=1,#lookupdata do
+ local li=lookupdata[i]
+ local tu=target[li]
+ if not tu then
+ tu={}
+ target[li]=tu
+ end
+ target=tu
+ end
+ target.ligature=unicode
+end
+local function pair(lookupdata,lookupname,unicode,lookuphash)
+ local target=lookuphash[lookupname]
+ if not target then
+ target={}
+ lookuphash[lookupname]=target
+ end
+ local others=target[unicode]
+ local paired=lookupdata[1]
+ if others then
+ others[paired]=lookupdata
+ else
+ others={ [paired]=lookupdata }
+ target[unicode]=others
+ end
+end
local action={
substitution=generic,
multiple=generic,
alternate=generic,
position=generic,
- ligature=function(lookupdata,lookupname,unicode,lookuphash)
- local target=lookuphash[lookupname]
- if not target then
- target={}
- lookuphash[lookupname]=target
- end
- for i=1,#lookupdata do
- local li=lookupdata[i]
- local tu=target[li]
- if not tu then
- tu={}
- target[li]=tu
- end
- target=tu
- end
- target.ligature=unicode
- end,
- pair=function(lookupdata,lookupname,unicode,lookuphash)
- local target=lookuphash[lookupname]
- if not target then
- target={}
- lookuphash[lookupname]=target
- end
- local others=target[unicode]
- local paired=lookupdata[1]
- if others then
- others[paired]=lookupdata
- else
- others={ [paired]=lookupdata }
- target[unicode]=others
- end
- end,
+ ligature=ligature,
+ pair=pair,
+ kern=pair,
}
local function prepare_lookups(tfmdata)
local rawdata=tfmdata.shared.rawdata
@@ -9732,13 +10890,14 @@ local function prepare_lookups(tfmdata)
local lookuptypes=resources.lookuptypes
local characters=tfmdata.characters
local descriptions=tfmdata.descriptions
+ local duplicates=resources.duplicates
for unicode,character in next,characters do
local description=descriptions[unicode]
if description then
local lookups=description.slookups
if lookups then
for lookupname,lookupdata in next,lookups do
- action[lookuptypes[lookupname]](lookupdata,lookupname,unicode,lookuphash)
+ action[lookuptypes[lookupname]](lookupdata,lookupname,unicode,lookuphash,duplicates)
end
end
local lookups=description.mlookups
@@ -9747,7 +10906,7 @@ local function prepare_lookups(tfmdata)
local lookuptype=lookuptypes[lookupname]
for l=1,#lookuplist do
local lookupdata=lookuplist[l]
- action[lookuptype](lookupdata,lookupname,unicode,lookuphash)
+ action[lookuptype](lookupdata,lookupname,unicode,lookuphash,duplicates)
end
end
end
@@ -9769,7 +10928,7 @@ local function prepare_lookups(tfmdata)
for name,anchor in next,anchors do
local lookups=anchor_to_lookup[name]
if lookups then
- for lookup,_ in next,lookups do
+ for lookup in next,lookups do
local target=lookuphash[lookup]
if target then
target[unicode]=anchors
@@ -9851,7 +11010,7 @@ local function prepare_contextchains(tfmdata)
if sequence[1] then
nt=nt+1
t[nt]={ nofrules,lookuptype,sequence,start,stop,rule.lookups,replacements }
- for unic,_ in next,sequence[start] do
+ for unic in next,sequence[start] do
local cu=contexts[unic]
if not cu then
contexts[unic]=t
@@ -9899,9 +11058,10 @@ registerotffeature {
}
otf.handlers=handlers
-end -- closure
+end --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-otn”] ---
-do -- begin closure to overcome local limits and interference
+
+do --- [luaotfload, fontloader-2015-12-12.lua scope for “font-otp” 18b4375155925ee1809150f4f6c3973b] ---
if not modules then modules={} end modules ['font-otp']={
version=1.001,
@@ -9910,9 +11070,8 @@ if not modules then modules={} end modules ['font-otp']={
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files"
}
-local next,type=next,type
+local next,type,tostring=next,type,tostring
local sort,concat=table.sort,table.concat
-local sortedhash=table.sortedhash
local trace_packing=false trackers.register("otf.packing",function(v) trace_packing=v end)
local trace_loading=false trackers.register("otf.loading",function(v) trace_loading=v end)
local report_otf=logs.reporter("fonts","otf loading")
@@ -10737,9 +11896,10 @@ end
otf.enhancers.unpack=unpackdata
otf.enhancers.pack=packdata
-end -- closure
+end --- [luaotfload, fontloader-2015-12-12.lua scope for “font-otp”] ---
+
-do -- begin closure to overcome local limits and interference
+do --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-lua” 50b8edb1db7009b6c661ab71ff24a466] ---
if not modules then modules={} end modules ['luatex-fonts-lua']={
version=1.001,
@@ -10772,9 +11932,10 @@ function fonts.readers.lua(specification)
end
end
-end -- closure
+end --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-lua”] ---
-do -- begin closure to overcome local limits and interference
+
+do --- [luaotfload, fontloader-2015-12-12.lua scope for “font-def” 3c71c27300a8cb5c29f5d278d2049fb6] ---
if not modules then modules={} end modules ['font-def']={
version=1.001,
@@ -10888,10 +12049,11 @@ end
function resolvers.name(specification)
local resolve=fonts.names.resolve
if resolve then
- local resolved,sub=resolve(specification.name,specification.sub,specification)
+ local resolved,sub,subindex=resolve(specification.name,specification.sub,specification)
if resolved then
specification.resolved=resolved
specification.sub=sub
+ specification.subindex=subindex
local suffix=lower(suffixonly(resolved))
if fonts.formats[suffix] then
specification.forced=suffix
@@ -10908,10 +12070,11 @@ end
function resolvers.spec(specification)
local resolvespec=fonts.names.resolvespec
if resolvespec then
- local resolved,sub=resolvespec(specification.name,specification.sub,specification)
+ local resolved,sub,subindex=resolvespec(specification.name,specification.sub,specification)
if resolved then
specification.resolved=resolved
specification.sub=sub
+ specification.subindex=subindex
specification.forced=lower(suffixonly(resolved))
specification.forcedname=resolved
specification.name=removesuffix(resolved)
@@ -11103,9 +12266,10 @@ function font.getfont(id)
end
callbacks.register('define_font',definers.read,"definition of fonts (tfmdata preparation)")
-end -- closure
+end --- [luaotfload, fontloader-2015-12-12.lua scope for “font-def”] ---
+
-do -- begin closure to overcome local limits and interference
+do --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-def” 8dc05f2aa96d2fd0245242c8fd3320eb] ---
if not modules then modules={} end modules ['luatex-font-def']={
version=1.001,
@@ -11185,9 +12349,10 @@ function fonts.definers.applypostprocessors(tfmdata)
return tfmdata
end
-end -- closure
+end --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-def”] ---
-do -- begin closure to overcome local limits and interference
+
+do --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-ext” 0eee87fb26b7d135da88ac0a43a8037a] ---
if not modules then modules={} end modules ['luatex-fonts-ext']={
version=1.001,
@@ -11404,9 +12569,10 @@ otffeatures.register {
}
}
-end -- closure
+end --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-ext”] ---
+
-do -- begin closure to overcome local limits and interference
+do --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-cbk” 3e86c6a492ca8d792f6b06149ba0dd57] ---
if not modules then modules={} end modules ['luatex-fonts-cbk']={
version=1.001,
@@ -11422,6 +12588,8 @@ end
local fonts=fonts
local nodes=nodes
local traverse_id=node.traverse_id
+local free_node=node.free
+local remove_node=node.remove
local glyph_code=nodes.nodecodes.glyph
local disc_code=nodes.nodecodes.disc
local ligaturing=node.ligaturing
@@ -11451,6 +12619,8 @@ function nodes.handlers.nodepass(head)
local basefonts={}
local prevfont=nil
local basefont=nil
+ local variants=nil
+ local redundant=nil
for n in traverse_id(glyph_code,head) do
local font=n.font
if font~=prevfont then
@@ -11472,10 +12642,47 @@ function nodes.handlers.nodepass(head)
basefonts[#basefonts+1]=basefont
end
end
+ local resources=tfmdata.resources
+ variants=resources and resources.variants
+ variants=variants and next(variants) and variants or false
+ end
+ else
+ local tfmdata=fontdata[prevfont]
+ if tfmdata then
+ local resources=tfmdata.resources
+ variants=resources and resources.variants
+ variants=variants and next(variants) and variants or false
+ end
+ end
+ end
+ if variants then
+ local char=n.char
+ if char>=0xFE00 and (char<=0xFE0F or (char>=0xE0100 and char<=0xE01EF)) then
+ local hash=variants[char]
+ if hash then
+ local p=n.prev
+ if p and p.id==glyph_code then
+ local variant=hash[p.char]
+ if variant then
+ p.char=variant
+ if not redundant then
+ redundant={ n }
+ else
+ redundant[#redundant+1]=n
+ end
+ end
+ end
end
end
end
end
+ if redundant then
+ for i=1,#redundant do
+ local n=redundant[i]
+ remove_node(head,n)
+ free_node(n)
+ end
+ end
for d in traverse_id(disc_code,head) do
local r=d.replace
if r then
@@ -11512,12 +12719,30 @@ function nodes.handlers.nodepass(head)
local range=basefonts[i]
local start=range[1]
local stop=range[2]
- if stop then
- start,stop=ligaturing(start,stop)
- start,stop=kerning(start,stop)
- elseif start then
- start=ligaturing(start)
- start=kerning(start)
+ if start or stop then
+ local prev=nil
+ local next=nil
+ local front=start==head
+ if stop then
+ next=stop.next
+ start,stop=ligaturing(start,stop)
+ start,stop=kerning(start,stop)
+ elseif start then
+ prev=start.prev
+ start=ligaturing(start)
+ start=kerning(start)
+ end
+ if prev then
+ start.prev=prev
+ prev.next=start
+ end
+ if next then
+ stop.next=next
+ next.prev=stop
+ end
+ if front then
+ head=start
+ end
end
end
end
@@ -11527,7 +12752,7 @@ function nodes.handlers.nodepass(head)
end
end
function nodes.handlers.basepass(head)
- if not basepass then
+ if basepass then
head=ligaturing(head)
head=kerning(head)
end
@@ -11549,4 +12774,7 @@ function nodes.simple_font_handler(head)
end
end
-end -- closure
+end --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-cbk”] ---
+
+
+--- vim:ft=lua:sw=2:ts=8:et:tw=79
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-package.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-package.lua
deleted file mode 100644
index 524dbcb05e8..00000000000
--- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-package.lua
+++ /dev/null
@@ -1,99 +0,0 @@
---
------------------------------------------------------------------------
--- FILE: luaotfload-package.lua
--- DESCRIPTION: Luatex fontloader packaging
--- REQUIREMENTS: luatex, mtx-package
--- AUTHOR: Philipp Gesang
--- LICENSE: GNU GPL v2.0
------------------------------------------------------------------------
---
-
---- The original initialization sequence by Hans Hagen, see the file
---- luatex-fonts.lua for details:
----
---- [01] l-lua.lua
---- [02] l-lpeg.lua
---- [03] l-function.lua
---- [04] l-string.lua
---- [05] l-table.lua
---- [06] l-io.lua
---- [07] l-file.lua
---- [08] l-boolean.lua
---- [09] l-math.lua
---- [10] util-str.lua
---- [11] luatex-basics-gen.lua
---- [12] data-con.lua
---- [13] luatex-basics-nod.lua
---- [14] font-ini.lua
---- [15] font-con.lua
---- [16] luatex-fonts-enc.lua
---- [17] font-cid.lua
---- [18] font-map.lua
---- [19] luatex-fonts-syn.lua
---- [20] font-tfm.lua
---- [21] font-afm.lua
---- [22] font-afk.lua
---- [23] luatex-fonts-tfm.lua
---- [24] font-oti.lua
---- [25] font-otf.lua
---- [26] font-otb.lua
---- [27] luatex-fonts-inj.lua
---- [28] luatex-fonts-ota.lua
---- [29] luatex-fonts-otn.lua
---- [30] font-otp.lua
---- [31] luatex-fonts-lua.lua
---- [32] font-def.lua
---- [33] luatex-fonts-def.lua
---- [34] luatex-fonts-ext.lua
---- [35] luatex-fonts-cbk.lua
----
---- Of these, nos. 01--10 are provided by the Lualibs. Keeping them
---- around in the Luaotfload fontloader is therefore unnecessary.
---- Packaging needs to account for this difference.
-
-loadmodule "l-lua.lua"
-loadmodule "l-lpeg.lua"
-loadmodule "l-function.lua"
-loadmodule "l-string.lua"
-loadmodule "l-table.lua"
-loadmodule "l-io.lua"
-loadmodule "l-file.lua"
-loadmodule "l-boolean.lua"
-loadmodule "l-math.lua"
-loadmodule "util-str.lua"
-
---- Another file containing auxiliary definitions must be present
---- prior to initialization of the configuration.
-
-loadmodule "luatex-basics-gen.lua"
-
---- The files below constitute the “fontloader proper”. Some of the
---- functionality like file resolvers is overloaded later by
---- Luaotfload. Consequently, the resulting package is pretty
---- bare-bones and not usable independently.
-
-loadmodule("data-con.lua")
-loadmodule("luatex-basics-nod.lua")
-loadmodule("font-ini.lua")
-loadmodule("font-con.lua")
-loadmodule("luatex-fonts-enc.lua")
-loadmodule("font-cid.lua")
-loadmodule("font-map.lua")
-loadmodule("luatex-fonts-syn.lua")
-loadmodule("font-tfm.lua")
-loadmodule("font-afm.lua")
-loadmodule("font-afk.lua")
-loadmodule("luatex-fonts-tfm.lua")
-loadmodule("font-oti.lua")
-loadmodule("font-otf.lua")
-loadmodule("font-otb.lua")
-loadmodule("luatex-fonts-inj.lua")
-loadmodule("luatex-fonts-ota.lua")
-loadmodule("luatex-fonts-otn.lua")
-loadmodule("font-otp.lua")
-loadmodule("luatex-fonts-lua.lua")
-loadmodule("font-def.lua")
-loadmodule("luatex-fonts-def.lua")
-loadmodule("luatex-fonts-ext.lua")
-loadmodule("luatex-fonts-cbk.lua")
-
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-status.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-status.lua
index 94dc1fd75b9..34a206312a9 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-2015-12-09.lua", "76f5af1071a3fd169f0a80704a6a5f5e" },
+ { "fontloader-2015-12-12.lua", "bcc0cb6536e04a9ee4693848a505d568" },
{ "fontloader-util-str.lua", "cc6f38cc53aff51d60e2223bf922bb0d" },
{ "fontloader-swiglib-test.lua", "c1cdeff07e5b8896f7aa98ce50c31618" },
{ "fontloader-swiglib.lua", "3a350d89416637073b7f09e281dc7c11" },
@@ -46,10 +46,9 @@ return {
{ "fontloader-tl2014.lua", "5bce3c40d6841694d6be5ad3680d5b10" },
{ "fontloader-reference.lua", "f3481efe06dc45db0dc7404aa96754e3" },
{ "fontloader-basics-gen.lua", "aa7229a3a0ae35d19bbe46e71d65bd2c" },
- { "luaotfload-package.lua", "dcc2311200ba2b0efa2ac76b152b9720" },
{ "mktests", "918cb50be9ee8bd645ac1a27dc501e8c" },
- { "mkstatus", "fcc6c1817169a64cdf8b0ef48bec36a2" },
- { "mkimport", "8c94dde3cfe04864e1785e6fc8bebc96" },
+ { "mkstatus", "76308532fa0175ac046e6ed1bf11e4b8" },
+ { "mkimport", "988e04fc571b2984eb21894cf0ea76e5" },
{ "mkglyphlist", "0acaf0fbc9dce6fda4e717a7ddcfdef6" },
{ "mkcharacters", "5274a32b25f2dc1f55e75546c551035e" },
{ "luaotfload-glyphlist.lua", "ff440162d1b8a78a586375ee65630c21" },
@@ -71,8 +70,9 @@ return {
},
["notes"]={
["committer"]="Philipp Gesang <phg@phi-gamma.net>",
- ["loader"]="fontloader-2015-12-09.lua",
- ["revision"]="656e7a115ab7c87743be59808713908f1d22fa6c",
- ["timestamp"]="2015-12-09 23:02:31 +0100",
+ ["description"]="v2.6-fix-2",
+ ["loader"]="fontloader-2015-12-12.lua",
+ ["revision"]="2fdaee0d9a2687e99b1f44be15b6876be22a495b",
+ ["timestamp"]="2015-12-12 20:05:29 +0100",
},
} \ No newline at end of file