summaryrefslogtreecommitdiff
path: root/src/fontloader/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'src/fontloader/runtime')
-rw-r--r--src/fontloader/runtime/fontloader-basics-gen.lua1
-rw-r--r--src/fontloader/runtime/fontloader-reference.lua1228
2 files changed, 832 insertions, 397 deletions
diff --git a/src/fontloader/runtime/fontloader-basics-gen.lua b/src/fontloader/runtime/fontloader-basics-gen.lua
index 2a68b1c..871e548 100644
--- a/src/fontloader/runtime/fontloader-basics-gen.lua
+++ b/src/fontloader/runtime/fontloader-basics-gen.lua
@@ -97,6 +97,7 @@ local remapper = {
-- fea = "font feature files", -- no longer supported
pfb = "type1 fonts", -- needed for vector loading
afm = "afm",
+ enc = "enc files",
}
function resolvers.findfile(name,fileformat)
diff --git a/src/fontloader/runtime/fontloader-reference.lua b/src/fontloader/runtime/fontloader-reference.lua
index 9785988..e6738ea 100644
--- a/src/fontloader/runtime/fontloader-reference.lua
+++ b/src/fontloader/runtime/fontloader-reference.lua
@@ -1,6 +1,6 @@
-- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua
-- parent file : c:/data/develop/context/sources/luatex-fonts.lua
--- merge date : 06/15/16 20:18:05
+-- merge date : 07/13/16 15:09:54
do -- begin closure to overcome local limits and interference
@@ -1487,6 +1487,7 @@ local function do_serialize(root,name,depth,level,indexed)
else
handle(format("%s [%s]=%s,",depth,k and "true" or "false",v))
end
+ elseif tk~="string" then
elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
if hexify then
handle(format("%s %s=0x%X,",depth,k,v))
@@ -1509,6 +1510,7 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif tk=="boolean" then
handle(format("%s [%s]=%q,",depth,k and "true" or "false",v))
+ elseif tk~="string" then
elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s=%q,",depth,k,v))
else
@@ -1524,6 +1526,7 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif tk=="boolean" then
handle(format("%s [%s]={},",depth,k and "true" or "false"))
+ elseif tk~="string" then
elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s={},",depth,k))
else
@@ -1540,6 +1543,7 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif tk=="boolean" then
handle(format("%s [%s]={ %s },",depth,k and "true" or "false",concat(st,", ")))
+ elseif tk~="string" then
elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s={ %s },",depth,k,concat(st,", ")))
else
@@ -1560,6 +1564,7 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif tk=="boolean" then
handle(format("%s [%s]=%s,",depth,tostring(k),v and "true" or "false"))
+ elseif tk~="string" then
elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s=%s,",depth,k,v and "true" or "false"))
else
@@ -1576,6 +1581,7 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif tk=="boolean" then
handle(format("%s [%s]=load(%q),",depth,k and "true" or "false",f))
+ elseif tk~="string" then
elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s=load(%q),",depth,k,f))
else
@@ -1591,6 +1597,7 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif tk=="boolean" then
handle(format("%s [%s]=%q,",depth,k and "true" or "false",tostring(v)))
+ elseif tk~="string" then
elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s=%q,",depth,k,tostring(v)))
else
@@ -4161,7 +4168,7 @@ end
function files.readinteger1(f)
local n=byte(f:read(1))
if n>=0x80 then
- return n-0xFF-1
+ return n-0x100
else
return n
end
@@ -4177,7 +4184,7 @@ function files.readinteger2(f)
local a,b=byte(f:read(2),1,2)
local n=0x100*a+b
if n>=0x8000 then
- return n-0xFFFF-1
+ return n-0x10000
else
return n
end
@@ -4186,6 +4193,15 @@ function files.readcardinal3(f)
local a,b,c=byte(f:read(3),1,3)
return 0x10000*a+0x100*b+c
end
+function files.readinteger3(f)
+ local a,b,c=byte(f:read(3),1,3)
+ local n=0x10000*a+0x100*b+c
+ if n>=0x80000 then
+ return n-0x1000000
+ else
+ return n
+ end
+end
function files.readcardinal4(f)
local a,b,c,d=byte(f:read(4),1,4)
return 0x1000000*a+0x10000*b+0x100*c+d
@@ -4194,7 +4210,7 @@ function files.readinteger4(f)
local a,b,c,d=byte(f:read(4),1,4)
local n=0x1000000*a+0x10000*b+0x100*c+d
if n>=0x8000000 then
- return n-0xFFFFFFFF-1
+ return n-0x100000000
else
return n
end
@@ -4203,7 +4219,7 @@ function files.readfixed4(f)
local a,b,c,d=byte(f:read(4),1,4)
local n=0x100*a+b
if n>=0x8000 then
- return n-0xFFFF-1+(0x100*c+d)/0xFFFF
+ return n-0x10000+(0x100*c+d)/0xFFFF
else
return n+(0x100*c+d)/0xFFFF
end
@@ -4311,6 +4327,7 @@ local remapper={
cidmap="cid maps",
pfb="type1 fonts",
afm="afm",
+ enc="enc files",
}
function resolvers.findfile(name,fileformat)
name=string.gsub(name,"\\","/")
@@ -5673,7 +5690,7 @@ if not modules then modules={} end modules ['font-con']={
license="see context related readme files"
}
local next,tostring,rawget=next,tostring,rawget
-local format,match,lower,gsub=string.format,string.match,string.lower,string.gsub
+local format,match,lower,gsub,find=string.format,string.match,string.lower,string.gsub,string.find
local sort,insert,concat,sortedkeys,serialize,fastcopy=table.sort,table.insert,table.concat,table.sortedkeys,table.serialize,table.fastcopy
local derivetable=table.derive
local trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end)
@@ -5693,89 +5710,6 @@ constructors.version=1.01
constructors.cache=containers.define("fonts","constructors",constructors.version,false)
constructors.privateoffset=0xF0000
constructors.cacheintex=true
-constructors.keys={
- properties={
- encodingbytes="number",
- embedding="number",
- cidinfo={},
- format="string",
- fontname="string",
- fullname="string",
- filename="filename",
- psname="string",
- name="string",
- virtualized="boolean",
- hasitalics="boolean",
- autoitalicamount="basepoints",
- nostackmath="boolean",
- noglyphnames="boolean",
- mode="string",
- hasmath="boolean",
- mathitalics="boolean",
- textitalics="boolean",
- finalized="boolean",
- },
- parameters={
- mathsize="number",
- scriptpercentage="float",
- scriptscriptpercentage="float",
- units="cardinal",
- designsize="scaledpoints",
- expansion={
- stretch="integerscale",
- shrink="integerscale",
- step="integerscale",
- auto="boolean",
- },
- protrusion={
- auto="boolean",
- },
- slantfactor="float",
- extendfactor="float",
- factor="float",
- hfactor="float",
- vfactor="float",
- size="scaledpoints",
- units="scaledpoints",
- scaledpoints="scaledpoints",
- slantperpoint="scaledpoints",
- spacing={
- width="scaledpoints",
- stretch="scaledpoints",
- shrink="scaledpoints",
- extra="scaledpoints",
- },
- xheight="scaledpoints",
- quad="scaledpoints",
- ascender="scaledpoints",
- descender="scaledpoints",
- synonyms={
- space="spacing.width",
- spacestretch="spacing.stretch",
- spaceshrink="spacing.shrink",
- extraspace="spacing.extra",
- x_height="xheight",
- space_stretch="spacing.stretch",
- space_shrink="spacing.shrink",
- extra_space="spacing.extra",
- em="quad",
- ex="xheight",
- slant="slantperpoint",
- },
- },
- description={
- width="basepoints",
- height="basepoints",
- depth="basepoints",
- boundingbox={},
- },
- character={
- width="scaledpoints",
- height="scaledpoints",
- depth="scaledpoints",
- italic="scaledpoints",
- },
-}
local designsizes=allocate()
constructors.designsizes=designsizes
local loadedfonts=allocate()
@@ -5913,6 +5847,23 @@ local function mathkerns(v,vdelta)
end
return k
end
+local psfake=0
+local function fixedpsname(psname,fallback)
+ local usedname=psname
+ if psname and psname~="" then
+ if find(psname," ") then
+ usedname=gsub(psname,"[%s]+","-")
+ else
+ end
+ elseif not fallback or fallback=="" then
+ psfake=psfake+1
+ psname="fakename-"..psfake
+ else
+ psname=fallback
+ usedname=gsub(psname,"[^a-zA-Z0-9]+","-")
+ end
+ return usedname,psname~=usedname
+end
function constructors.scale(tfmdata,specification)
local target={}
if tonumber(specification) then
@@ -5986,14 +5937,12 @@ function constructors.scale(tfmdata,specification)
target.cidinfo=properties.cidinfo
target.format=properties.format
target.cache=constructors.cacheintex and "yes" or "renew"
- local fontname=properties.fontname or tfmdata.fontname
- local fullname=properties.fullname or tfmdata.fullname
- local filename=properties.filename or tfmdata.filename
- local psname=properties.psname or tfmdata.psname
+ local fontname=properties.fontname or tfmdata.fontname
+ local fullname=properties.fullname or tfmdata.fullname
+ local filename=properties.filename or tfmdata.filename
+ local psname=properties.psname or tfmdata.psname
local name=properties.name or tfmdata.name
- if not psname or psname=="" then
- psname=fontname or (fullname and fonts.names.cleanname(fullname))
- end
+ local psname,psfixed=fixedpsname(psname,fontname or fullname or file.nameonly(filename))
target.fontname=fontname
target.fullname=fullname
target.filename=filename
@@ -6106,8 +6055,9 @@ function constructors.scale(tfmdata,specification)
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",hasitalics and "enabled" or "disabled")
+ report_defining("defining tfm, name %a, fullname %a, filename %a, %spsname %a, hscale %a, vscale %a, math %a, italics %a",
+ name,fullname,filename,psfixed and "(fixed) " or "",psname,hdelta,vdelta,
+ hasmath and "enabled" or "disabled",hasitalics and "enabled" or "disabled")
end
constructors.beforecopyingcharacters(target,tfmdata)
local sharedkerns={}
@@ -6849,19 +6799,61 @@ if context then
os.exit()
end
local fonts=fonts
-fonts.encodings={}
-fonts.encodings.agl={}
-fonts.encodings.known={}
-setmetatable(fonts.encodings.agl,{ __index=function(t,k)
+local encodings={}
+fonts.encodings=encodings
+encodings.agl={}
+encodings.known={}
+setmetatable(encodings.agl,{ __index=function(t,k)
if k=="unicodes" then
texio.write(" <loading (extended) adobe glyph list>")
local unicodes=dofile(resolvers.findfile("font-age.lua"))
- fonts.encodings.agl={ unicodes=unicodes }
+ encodings.agl={ unicodes=unicodes }
return unicodes
else
return nil
end
end })
+encodings.cache=containers.define("fonts","enc",encodings.version,true)
+function encodings.load(filename)
+ local name=file.removesuffix(filename)
+ local data=containers.read(encodings.cache,name)
+ if data then
+ return data
+ end
+ local vector,tag,hash,unicodes={},"",{},{}
+ local foundname=resolvers.findfile(filename,'enc')
+ if foundname and foundname~="" then
+ local ok,encoding,size=resolvers.loadbinfile(foundname)
+ if ok and encoding then
+ encoding=string.gsub(encoding,"%%(.-)\n","")
+ local unicoding=encodings.agl.unicodes
+ local tag,vec=string.match(encoding,"/(%w+)%s*%[(.*)%]%s*def")
+ local i=0
+ for ch in string.gmatch(vec,"/([%a%d%.]+)") do
+ if ch~=".notdef" then
+ vector[i]=ch
+ if not hash[ch] then
+ hash[ch]=i
+ else
+ end
+ local u=unicoding[ch]
+ if u then
+ unicodes[u]=i
+ end
+ end
+ i=i+1
+ end
+ end
+ end
+ local data={
+ name=name,
+ tag=tag,
+ vector=vector,
+ hash=hash,
+ unicodes=unicodes
+ }
+ return containers.write(encodings.cache,name,data)
+end
end -- closure
@@ -7033,7 +7025,7 @@ local P,R,S,C,Ct,Cc,lpegmatch=lpeg.P,lpeg.R,lpeg.S,lpeg.C,lpeg.Ct,lpeg.Cc,lpeg.m
local floor=math.floor
local formatters=string.formatters
local trace_loading=false trackers.register("fonts.loading",function(v) trace_loading=v end)
-local trace_mapping=false trackers.register("fonts.mapping",function(v) trace_unimapping=v end)
+local trace_mapping=false trackers.register("fonts.mapping",function(v) trace_mapping=v end)
local report_fonts=logs.reporter("fonts","loading")
local force_ligatures=false directives.register("fonts.mapping.forceligatures",function(v) force_ligatures=v end)
local fonts=fonts or {}
@@ -7149,6 +7141,9 @@ function mappings.addtounicode(data,filename,checklookups)
local resources=data.resources
local unicodes=resources.unicodes
if not unicodes then
+ if trace_mapping then
+ report_fonts("no unicode list, quitting tounicode for %a",filename)
+ end
return
end
local properties=data.properties
@@ -7337,8 +7332,8 @@ function mappings.addtounicode(data,filename,checklookups)
end
if trace_mapping then
for unic,glyph in table.sortedhash(descriptions) do
- local name=glyph.name
- local index=glyph.index
+ local name=glyph.name or "-"
+ local index=glyph.index or 0
local unicode=glyph.unicode
if unicode then
if type(unicode)=="table" then
@@ -7441,164 +7436,6 @@ end -- closure
do -- begin closure to overcome local limits and interference
-if not modules then modules={} end modules ['font-tfm']={
- version=1.001,
- comment="companion to font-ini.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
-}
-local next=next
-local match=string.match
-local trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end)
-local trace_features=false trackers.register("tfm.features",function(v) trace_features=v end)
-local report_defining=logs.reporter("fonts","defining")
-local report_tfm=logs.reporter("fonts","tfm loading")
-local findbinfile=resolvers.findbinfile
-local fonts=fonts
-local handlers=fonts.handlers
-local readers=fonts.readers
-local constructors=fonts.constructors
-local encodings=fonts.encodings
-local tfm=constructors.handlers.tfm
-tfm.version=1.000
-tfm.maxnestingdepth=5
-tfm.maxnestingsize=65536*1024
-local tfmfeatures=constructors.features.tfm
-constructors.resolvevirtualtoo=false
-fonts.formats.tfm="type1"
-fonts.formats.ofm="type1"
-function tfm.setfeatures(tfmdata,features)
- local okay=constructors.initializefeatures("tfm",tfmdata,features,trace_features,report_tfm)
- if okay then
- return constructors.collectprocessors("tfm",tfmdata,features,trace_features,report_tfm)
- else
- 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
- local tfmdata=font.read_tfm(filename,size)
- if tfmdata then
- local features=specification.features and specification.features.normal or {}
- local resources=tfmdata.resources or {}
- local properties=tfmdata.properties or {}
- local parameters=tfmdata.parameters or {}
- local shared=tfmdata.shared or {}
- properties.name=tfmdata.name
- properties.fontname=tfmdata.fontname
- properties.psname=tfmdata.psname
- properties.filename=specification.filename
- properties.format=fonts.formats.tfm
- parameters.size=size
- tfmdata.properties=properties
- tfmdata.resources=resources
- tfmdata.parameters=parameters
- tfmdata.shared=shared
- shared.rawdata={}
- shared.features=features
- shared.processes=next(features) and tfm.setfeatures(tfmdata,features) or nil
- parameters.slant=parameters.slant or parameters[1] or 0
- parameters.space=parameters.space or parameters[2] or 0
- parameters.space_stretch=parameters.space_stretch or parameters[3] or 0
- parameters.space_shrink=parameters.space_shrink or parameters[4] or 0
- parameters.x_height=parameters.x_height or parameters[5] or 0
- parameters.quad=parameters.quad or parameters[6] or 0
- parameters.extra_space=parameters.extra_space or parameters[7] or 0
- constructors.enhanceparameters(parameters)
- if constructors.resolvevirtualtoo then
- fonts.loggers.register(tfmdata,file.suffix(filename),specification)
- local vfname=findbinfile(specification.name,'ovf')
- if vfname and vfname~="" then
- local vfdata=font.read_vf(vfname,size)
- if vfdata then
- local chars=tfmdata.characters
- for k,v in next,vfdata.characters do
- chars[k].commands=v.commands
- 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
- local allfeatures=tfmdata.shared.features or specification.features.normal
- constructors.applymanipulators("tfm",tfmdata,allfeatures.normal,trace_features,report_tfm)
- if not features.encoding then
- local encoding,filename=match(properties.filename,"^(.-)%-(.*)$")
- if filename and encoding and encodings.known and encodings.known[encoding] then
- features.encoding=encoding
- end
- end
- properties.haskerns=true
- properties.hasligatures=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)
- local foundname=findbinfile(fullname,'tfm') or ""
- if foundname=="" then
- foundname=findbinfile(fullname,'ofm') or ""
- end
- if foundname=="" then
- foundname=fonts.names.getfilename(fullname,"tfm") or ""
- end
- if foundname~="" then
- specification.filename=foundname
- specification.format="ofm"
- return read_from_tfm(specification)
- elseif trace_defining then
- report_defining("loading tfm with name %a fails",specification.name)
- end
-end
-readers.check_tfm=check_tfm
-function readers.tfm(specification)
- local fullname=specification.filename or ""
- if fullname=="" then
- local forced=specification.forced or ""
- if forced~="" then
- fullname=specification.name.."."..forced
- else
- fullname=specification.name
- end
- end
- return check_tfm(specification,fullname)
-end
-readers.ofm=readers.tfm
-
-end -- closure
-
-do -- begin closure to overcome local limits and interference
-
if not modules then modules={} end modules ['font-oti']={
version=1.001,
comment="companion to font-ini.mkiv",
@@ -7625,6 +7462,7 @@ local function setmode(tfmdata,value)
tfmdata.properties.mode=lower(value)
end
end
+otf.modeinitializer=setmode
local function setlanguage(tfmdata,value)
if value then
local cleanvalue=lower(value)
@@ -11355,10 +11193,15 @@ local function readcoverage(f,offset,simple)
end
return coverage
end
-local function readclassdef(f,offset)
+local function readclassdef(f,offset,preset)
setposition(f,offset)
local classdefformat=readushort(f)
local classdef={}
+ if type(preset)=="number" then
+ for k=0,preset-1 do
+ classdef[k]=1
+ end
+ end
if classdefformat==1 then
local index=readushort(f)
local nofclassdef=readushort(f)
@@ -11380,6 +11223,13 @@ local function readclassdef(f,offset)
else
report("unknown classdef format %a ",classdefformat)
end
+ if type(preset)=="table" then
+ for k in next,preset do
+ if not classdef[k] then
+ classdef[k]=1
+ end
+ end
+ end
return classdef
end
local function classtocoverage(defs)
@@ -11479,7 +11329,7 @@ local function covered(subset,all)
end
return used
end
-local function readlookuparray(f,noflookups)
+local function readlookuparray(f,noflookups,nofcurrent)
local lookups={}
if noflookups>0 then
local length=0
@@ -11522,7 +11372,7 @@ local function unchainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,n
for i=2,nofcurrent do
current[i]={ readushort(f) }
end
- local lookups=readlookuparray(f,noflookups)
+ local lookups=readlookuparray(f,noflookups,nofcurrent)
rules[#rules+1]={
current=current,
lookups=lookups
@@ -11544,7 +11394,7 @@ local function unchainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,n
local rules={}
if subclasssets then
coverage=readcoverage(f,tableoffset+coverage)
- currentclassdef=readclassdef(f,tableoffset+currentclassdef)
+ currentclassdef=readclassdef(f,tableoffset+currentclassdef,coverage)
local currentclasses=classtocoverage(currentclassdef,fontdata.glyphs)
for class=1,#subclasssets do
local offset=subclasssets[class]
@@ -11563,7 +11413,7 @@ local function unchainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,n
for i=2,nofcurrent do
current[i]=currentclasses[readushort(f)+1]
end
- local lookups=readlookuparray(f,noflookups)
+ local lookups=readlookuparray(f,noflookups,nofcurrent)
rules[#rules+1]={
current=current,
lookups=lookups
@@ -11587,7 +11437,7 @@ local function unchainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,n
elseif subtype==3 then
local current=readarray(f)
local noflookups=readushort(f)
- local lookups=readlookuparray(f,noflookups)
+ local lookups=readlookuparray(f,noflookups,#current)
current=readcoveragearray(f,tableoffset,current,true)
return {
format="coverage",
@@ -11642,7 +11492,7 @@ local function chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nof
end
end
local noflookups=readushort(f)
- local lookups=readlookuparray(f,noflookups)
+ local lookups=readlookuparray(f,noflookups,nofcurrent)
rules[#rules+1]={
before=before,
current=current,
@@ -11668,9 +11518,9 @@ local function chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nof
local rules={}
if subclasssets then
local coverage=readcoverage(f,tableoffset+coverage)
- local beforeclassdef=readclassdef(f,tableoffset+beforeclassdef)
- local currentclassdef=readclassdef(f,tableoffset+currentclassdef)
- local afterclassdef=readclassdef(f,tableoffset+afterclassdef)
+ local beforeclassdef=readclassdef(f,tableoffset+beforeclassdef,nofglyphs)
+ local currentclassdef=readclassdef(f,tableoffset+currentclassdef,coverage)
+ local afterclassdef=readclassdef(f,tableoffset+afterclassdef,nofglyphs)
local beforeclasses=classtocoverage(beforeclassdef,fontdata.glyphs)
local currentclasses=classtocoverage(currentclassdef,fontdata.glyphs)
local afterclasses=classtocoverage(afterclassdef,fontdata.glyphs)
@@ -11707,7 +11557,7 @@ local function chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nof
end
end
local noflookups=readushort(f)
- local lookups=readlookuparray(f,noflookups)
+ local lookups=readlookuparray(f,noflookups,nofcurrent)
rules[#rules+1]={
before=before,
current=current,
@@ -11735,7 +11585,7 @@ local function chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nof
local current=readarray(f)
local after=readarray(f)
local noflookups=readushort(f)
- local lookups=readlookuparray(f,noflookups)
+ local lookups=readlookuparray(f,noflookups,#current)
before=readcoveragearray(f,tableoffset,before,true)
current=readcoveragearray(f,tableoffset,current,true)
after=readcoveragearray(f,tableoffset,after,true)
@@ -12061,8 +11911,8 @@ function gposhandlers.pair(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofgly
local nofclasses2=readushort(f)
local classlist=readpairclasssets(f,nofclasses1,nofclasses2,format1,format2)
coverage=readcoverage(f,tableoffset+coverage)
- classdef1=readclassdef(f,tableoffset+classdef1)
- classdef2=readclassdef(f,tableoffset+classdef2)
+ classdef1=readclassdef(f,tableoffset+classdef1,coverage)
+ classdef2=readclassdef(f,tableoffset+classdef2,nofglyphs)
local usedcoverage={}
for g1,c1 in next,classdef1 do
if coverage[g1] then
@@ -14090,6 +13940,7 @@ function readers.getcomponents(fontdata)
end
end
end
+readers.unifymissing=unifymissing
function readers.rehash(fontdata,hashmethod)
if not (fontdata and fontdata.glyphs) then
return
@@ -15363,7 +15214,7 @@ local trace_defining=false registertracker("fonts.defining",function(v) trace_de
local report_otf=logs.reporter("fonts","otf loading")
local fonts=fonts
local otf=fonts.handlers.otf
-otf.version=3.023
+otf.version=3.025
otf.cache=containers.define("fonts","otl",otf.version,true)
otf.svgcache=containers.define("fonts","svg",otf.version,true)
otf.pdfcache=containers.define("fonts","pdf",otf.version,true)
@@ -15541,7 +15392,7 @@ function otf.load(filename,sub,featurefile)
collectgarbage("collect")
end
stoptiming(otfreaders)
- if elapsedtime then
+ if elapsedtime then
report_otf("loading, optimizing, packing and caching time %s",elapsedtime(otfreaders))
end
if cleanup>3 then
@@ -15703,13 +15554,13 @@ local function copytotfm(data,cache_id)
spaceunits,spacer=charwidth,"charwidth"
end
end
- spaceunits=tonumber(spaceunits) or 500
+ spaceunits=tonumber(spaceunits) or units/2
parameters.slant=0
- parameters.space=spaceunits
+ parameters.space=spaceunits
parameters.space_stretch=1*units/2
- parameters.space_shrink=1*units/3
- parameters.x_height=2*units/5
- parameters.quad=units
+ parameters.space_shrink=1*units/3
+ parameters.x_height=2*units/5
+ parameters.quad=units
if spaceunits<2*units/5 then
end
if italicangle and italicangle~=0 then
@@ -16119,7 +15970,7 @@ local function registerbasehash(tfmdata)
basehash[hash]=base
end
properties.basehash=base
- properties.fullname=properties.fullname.."-"..base
+ properties.fullname=(properties.fullname or properties.name).."-"..base
applied={}
end
local function registerbasefeature(feature,value)
@@ -16187,6 +16038,10 @@ local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplis
local trace_singles=trace_baseinit and trace_singles
local trace_alternatives=trace_baseinit and trace_alternatives
local trace_ligatures=trace_baseinit and trace_ligatures
+ if not changed then
+ changed={}
+ tfmdata.changed=changed
+ end
for i=1,#lookuplist do
local sequence=lookuplist[i]
local steps=sequence.steps
@@ -16340,7 +16195,8 @@ local function featuresinitializer(tfmdata,value)
local properties=tfmdata.properties
local script=properties.script
local language=properties.language
- local rawfeatures=rawdata.resources.features
+ local rawresources=rawdata.resources
+ local rawfeatures=rawresources and rawresources.features
local basesubstitutions=rawfeatures and rawfeatures.gsub
local basepositionings=rawfeatures and rawfeatures.gpos
if basesubstitutions or basepositionings then
@@ -16411,7 +16267,7 @@ local registertracker=trackers.register
local trace_injections=false registertracker("fonts.injections",function(v) trace_injections=v end)
local trace_marks=false registertracker("fonts.injections.marks",function(v) trace_marks=v end)
local trace_cursive=false registertracker("fonts.injections.cursive",function(v) trace_cursive=v end)
-local trace_spaces=false registertracker("otf.spaces",function(v) trace_spaces=v end)
+local trace_spaces=false registertracker("fonts.injections.spaces",function(v) trace_spaces=v end)
local use_advance=false directives.register("fonts.injections.advance",function(v) use_advance=v end)
local report_injections=logs.reporter("fonts","injections")
local report_spaces=logs.reporter("fonts","spaces")
@@ -17293,6 +17149,10 @@ local function inject_everything(head,where)
nofmarks=nofmarks+1
marks[nofmarks]=current
else
+local yoffset=i.yoffset
+if yoffset and yoffset~=0 then
+ setfield(current,"yoffset",yoffset)
+end
if hascursives then
local cursivex=i.cursivex
if cursivex then
@@ -17344,10 +17204,6 @@ local function inject_everything(head,where)
cursiveanchor=nil
end
end
- local yoffset=i.yoffset
- if yoffset and yoffset~=0 then
- setfield(current,"yoffset",yoffset)
- end
local leftkern=i.leftkern
if leftkern and leftkern~=0 then
insert_node_before(head,current,newkern(leftkern))
@@ -17594,6 +17450,37 @@ function nodes.injections.setspacekerns(font,sequence)
triggers={ [font]=sequence }
end
end
+local getthreshold
+if context then
+ local threshold=1
+ local parameters=fonts.hashes.parameters
+ directives.register("otf.threshold",function(v) threshold=tonumber(v) or 1 end)
+ getthreshold=function(font)
+ local p=parameters[font]
+ local f=p.factor
+ local s=p.spacing
+ local t=threshold*(s and s.width or p.space or 0)-2
+ return t>0 and t or 0,f
+ end
+else
+ injections.threshold=0
+ getthreshold=function(font)
+ local p=fontdata[font].parameters
+ local f=p.factor
+ local s=p.spacing
+ local t=injections.threshold*(s and s.width or p.space or 0)-2
+ return t>0 and t or 0,f
+ end
+end
+injections.getthreshold=getthreshold
+function injections.isspace(n,threshold)
+ if getid(n)==glue_code then
+ local w=getfield(n,"width")
+ if threshold and w>threshold then
+ return 32
+ end
+ end
+end
local function injectspaces(head)
if not triggers then
return head,false
@@ -17609,10 +17496,9 @@ local function injectspaces(head)
local function updatefont(font,trig)
leftkerns=trig.left
rightkerns=trig.right
- local par=fontdata[font].parameters
- factor=par.factor
- threshold=par.spacing.width-1
lastfont=font
+ threshold,
+ factor=getthreshold(font)
end
for n in traverse_id(glue_code,tonut(head)) do
local prev,next=getboth(n)
@@ -17631,7 +17517,7 @@ local function injectspaces(head)
end
end
if prevchar then
- local font=getfont(next)
+ local font=getfont(prev)
local trig=triggers[font]
if trig then
if lastfont~=font then
@@ -17644,7 +17530,7 @@ local function injectspaces(head)
end
if leftkern then
local old=getfield(n,"width")
- if old>=threshold then
+ if old>threshold then
if rightkern then
local new=old+(leftkern+rightkern)*factor
if trace_spaces then
@@ -17663,7 +17549,7 @@ local function injectspaces(head)
leftkern=false
elseif rightkern then
local old=getfield(n,"width")
- if old>=threshold then
+ if old>threshold then
local new=old+rightkern*factor
if trace_spaces then
report_spaces("[%p -> %p] %C",nextchar,old,new)
@@ -18114,11 +18000,7 @@ local trace_kernruns=false registertracker("otf.kernruns",function(v) trace_kern
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 trace_testruns=false registertracker("otf.testruns",function(v) trace_testruns=v end)
-local quit_on_no_replacement=true
-local zwnjruns=true
local optimizekerns=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")
@@ -18195,6 +18077,7 @@ local getligaindex=injections.getligaindex
local cursonce=true
local fonthashes=fonts.hashes
local fontdata=fonthashes.identifiers
+local fontfeatures=fonthashes.features
local otffeatures=fonts.constructors.features.otf
local registerotffeature=otffeatures.register
local onetimemessage=fonts.loggers.onetimemessage or function() end
@@ -18214,14 +18097,8 @@ local notmatchpre={}
local notmatchpost={}
local notmatchreplace={}
local handlers={}
-local function isspace(n)
- if getid(n)==glue_code then
- local w=getfield(n,"width")
- if w>=threshold then
- return 32
- end
- end
-end
+local isspace=injections.isspace
+local getthreshold=injections.getthreshold
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
@@ -18499,7 +18376,7 @@ end
end
return head,base
end
-local function multiple_glyphs(head,start,multiple,ignoremarks)
+local function multiple_glyphs(head,start,multiple,ignoremarks,what)
local nofmultiples=#multiple
if nofmultiples>0 then
resetinjection(start)
@@ -18513,6 +18390,17 @@ local function multiple_glyphs(head,start,multiple,ignoremarks)
insert_node_after(head,start,n)
start=n
end
+ if what==true then
+ elseif what>1 then
+ local m=multiple[nofmultiples]
+ for i=2,what do
+ local n=copy_node(start)
+ resetinjection(n)
+ setchar(n,m)
+ insert_node_after(head,start,n)
+ start=n
+ end
+ end
end
return head,start,true
else
@@ -18583,7 +18471,7 @@ function handlers.gsub_multiple(head,start,dataset,sequence,multiple)
if trace_multiples then
logprocess("%s: replacing %s by multiple %s",pref(dataset,sequence),gref(getchar(start)),gref(multiple))
end
- return multiple_glyphs(head,start,multiple,sequence.flags[1])
+ return multiple_glyphs(head,start,multiple,sequence.flags[1],dataset[1])
end
function handlers.gsub_ligature(head,start,dataset,sequence,ligature)
local current=getnext(start)
@@ -19038,7 +18926,7 @@ function chainprocs.gsub_multiple(head,start,stop,dataset,sequence,currentlookup
if trace_multiples then
logprocess("%s: replacing %s by multiple characters %s",cref(dataset,sequence),gref(startchar),gref(replacement))
end
- return multiple_glyphs(head,start,replacement,sequence.flags[1])
+ return multiple_glyphs(head,start,replacement,sequence.flags[1],dataset[1])
end
return head,start,false
end
@@ -19050,7 +18938,7 @@ function chainprocs.gsub_alternate(head,start,stop,dataset,sequence,currentlooku
end
local kind=dataset[4]
local what=dataset[1]
- local value=what==true and tfmdata.shared.features[kind] or what
+ local value=what==true and tfmdata.shared.features[kind] or what
local current=start
while current do
local currentchar=ischar(current)
@@ -19991,16 +19879,13 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
end
end
prev=getprev(prev)
- elseif seq[n][32] then
+ elseif seq[n][32] and isspace(prev,threshold) then
n=n-1
prev=getprev(prev)
else
match=false
break
end
- elseif seq[n][32] then
- n=n-1
- prev=getprev(prev)
else
match=false
break
@@ -20114,15 +19999,13 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
else
end
current=getnext(current)
- elseif seq[n][32] then
+ elseif seq[n][32] and isspace(current,threshold) then
n=n+1
+ current=getnext(current)
else
match=false
break
end
- elseif seq[n][32] then
- n=n+1
- current=getnext(current)
else
match=false
break
@@ -20217,7 +20100,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
if replacements then
head,start,done=reversesub(head,start,last,dataset,sequence,replacements,rlmode)
else
- done=quit_on_no_replacement
+ done=true
if trace_contexts then
logprocess("%s: skipping match",cref(dataset,sequence))
end
@@ -20366,10 +20249,10 @@ local function kernrun(disc,k_run,font,attr,...)
break
end
end
- if prev and (pre or replace) and not ischar(prev,font) then
+ if prev and not ischar(prev,font) then
prev=false
end
- if next and (post or replace) and not ischar(next,font) then
+ if next and not ischar(next,font) then
next=false
end
if pre then
@@ -20795,8 +20678,8 @@ local function featuresprocessor(head,font,attr)
descriptions=tfmdata.descriptions
characters=tfmdata.characters
marks=tfmdata.resources.marks
- factor=tfmdata.parameters.factor
- threshold=tfmdata.parameters.spacing.width or 65536*10
+ threshold,
+ factor=getthreshold(font)
elseif currentfont~=font then
report_warning("nested call with a different font, level %s, quitting",nesting)
nesting=nesting-1
@@ -20824,15 +20707,12 @@ local function featuresprocessor(head,font,attr)
local steps=sequence.steps
local nofsteps=sequence.nofsteps
if not steps then
- local h,d,ok=handler(head,start,dataset,sequence,nil,nil,nil,0,font,attr)
+ local h,d,ok=handler(head,head,dataset,sequence,nil,nil,nil,0,font,attr)
if ok then
success=true
if h then
head=h
end
- if d then
- start=d
- end
end
elseif typ=="gsub_reversecontextchain" then
local start=find_node_tail(head)
@@ -21017,9 +20897,25 @@ otf.nodemodeinitializer=featuresinitializer
otf.featuresprocessor=featuresprocessor
otf.handlers=handlers
local setspacekerns=nodes.injections.setspacekerns if not setspacekerns then os.exit() end
-function otf.handlers.trigger_space_kerns(head,start,dataset,sequence,_,_,_,_,font,attr)
- setspacekerns(font,sequence)
- return head,start,true
+if fontfeatures then
+ function otf.handlers.trigger_space_kerns(head,start,dataset,sequence,_,_,_,_,font,attr)
+ local features=fontfeatures[font]
+ local enabled=features.spacekern==true and features.kern==true
+ if enabled then
+ setspacekerns(font,sequence)
+ end
+ return head,start,enabled
+ end
+else
+ function otf.handlers.trigger_space_kerns(head,start,dataset,sequence,_,_,_,_,font,attr)
+ local shared=fontdata[font].shared
+ local features=shared and shared.features
+ local enabled=features and features.spacekern==true and features.kern==true
+ if enabled then
+ setspacekerns(font,sequence)
+ end
+ return head,start,enabled
+ end
end
local function hasspacekerns(data)
local sequences=data.resources.sequences
@@ -21053,8 +20949,8 @@ otf.readers.registerextender {
local function spaceinitializer(tfmdata,value)
local resources=tfmdata.resources
local spacekerns=resources and resources.spacekerns
- if spacekerns==nil then
- local properties=tfmdata.properties
+ local properties=tfmdata.properties
+ if value and spacekerns==nil then
if properties and properties.hasspacekerns then
local sequences=resources.sequences
local left={}
@@ -21067,7 +20963,20 @@ local function spaceinitializer(tfmdata,value)
if steps then
local kern=sequence.features.kern
if kern then
- feat=feat or kern
+ if feat then
+ for script,languages in next,kern do
+ local f=feat[k]
+ if f then
+ for l in next,languages do
+ f[l]=true
+ end
+ else
+ feat[script]=languages
+ end
+ end
+ else
+ feat=kern
+ end
for i=1,#steps do
local step=steps[i]
local coverage=step.coverage
@@ -23117,7 +23026,7 @@ if not modules then modules={} end modules ['font-ocl']={
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files"
}
-local tostring,next=tostring,next
+local tostring,next,format=tostring,next,string.format
local formatters=string.formatters
local otf=fonts.handlers.otf
local f_color_start=formatters["pdf:direct: %f %f %f rg"]
@@ -23234,70 +23143,62 @@ do
end
end
end
-if context and xml.convert then
+do
local report_svg=logs.reporter("fonts","svg conversion")
- local xmlconvert=xml.convert
- local xmlfirst=xml.first
local loaddata=io.loaddata
local savedata=io.savedata
local remove=os.remove
+ if context and xml.convert then
+ local xmlconvert=xml.convert
+ local xmlfirst=xml.first
+ function otfsvg.filterglyph(entry,index)
+ local svg=xmlconvert(entry.data)
+ local root=svg and xmlfirst(svg,"/svg[@id='glyph"..index.."']")
+ local data=root and tostring(root)
+ return data
+ end
+ else
+ function otfsvg.filterglyph(entry,index)
+ return entry.data
+ end
+ end
function otfsvg.topdf(svgshapes)
- local inkscape=io.popen("inkscape --shell 2>&1","w")
+ local inkscape=io.popen("inkscape --shell > temp-otf-svg-shape.log","w")
local pdfshapes={}
local nofshapes=#svgshapes
local f_svgfile=formatters["temp-otf-svg-shape-%i.svg"]
local f_pdffile=formatters["temp-otf-svg-shape-%i.pdf"]
local f_convert=formatters["%s --export-pdf=%s\n"]
+ local filterglyph=otfsvg.filterglyph
report_svg("processing %i svg containers",nofshapes)
statistics.starttiming()
for i=1,nofshapes do
local entry=svgshapes[i]
- for j=entry.first,entry.last do
- local svg=xmlconvert(entry.data)
- local root=svg and xmlfirst(svg,"/svg[@id='glyph"..j.."']")
- local data=root and tostring(root)
+ for index=entry.first,entry.last do
+ local data=filterglyph(entry,index)
if data and data~="" then
- local svgfile=f_svgfile(j)
- local pdffile=f_pdffile(j)
+ local svgfile=f_svgfile(index)
+ local pdffile=f_pdffile(index)
savedata(svgfile,data)
inkscape:write(f_convert(svgfile,pdffile))
- pdfshapes[j]=true
+ pdfshapes[index]=true
end
end
end
inkscape:write("quit\n")
inkscape:close()
report_svg("processing %i pdf results",nofshapes)
- for i in next,pdfshapes do
- local svgfile=f_svgfile(i)
- local pdffile=f_pdffile(i)
- pdfshapes[i]=loaddata(pdffile)
+ for index in next,pdfshapes do
+ local svgfile=f_svgfile(index)
+ local pdffile=f_pdffile(index)
+ pdfshapes[index]=loaddata(pdffile)
remove(svgfile)
remove(pdffile)
end
statistics.stoptiming()
- report_svg("conversion time: %0.3f",statistics.elapsedtime())
- return pdfshapes
- end
-else
- function otfsvg.topdf(svgshapes)
- local svgfile="temp-otf-svg-shape.svg"
- local pdffile="temp-otf-svg-shape.pdf"
- local command="inkscape "..svgfile.." --export-pdf="..pdffile
- local pdfshapes={}
- local nofshapes=#svgshapes
- texio.write(formatters["[converting %i svg glyphs to pdf using command %q : "](nofshapes,command))
- for i=1,nofshapes do
- local entry=svgshapes[i]
- for j=entry.first,entry.last do
- texio.write(formatters["%i "](j))
- io.savedata(svgfile,tostring(entry.data))
- os.execute(command)
- pdfshapes[j]=io.loaddata(pdffile)
- end
+ if statistics.elapsedseconds then
+ report_svg("svg conversion time %s",statistics.elapsedseconds())
end
- os.remove(svgfile)
- texio.write("done]")
return pdfshapes
end
end
@@ -23380,20 +23281,18 @@ if not modules then modules={} end modules ['font-onr']={
license="see context related readme files"
}
local fonts,logs,trackers,resolvers=fonts,logs,trackers,resolvers
-local next,type,tonumber,rawget=next,type,tonumber,rawget
+local next,type,tonumber,rawget,rawset=next,type,tonumber,rawget,rawset
local match,lower,gsub,strip,find=string.match,string.lower,string.gsub,string.strip,string.find
local char,byte,sub=string.char,string.byte,string.sub
local abs=math.abs
local bxor,rshift=bit32.bxor,bit32.rshift
-local P,S,R,Cmt,C,Ct,Cs,Carg=lpeg.P,lpeg.S,lpeg.R,lpeg.Cmt,lpeg.C,lpeg.Ct,lpeg.Cs,lpeg.Carg
+local P,S,R,Cmt,C,Ct,Cs,Carg,Cf,Cg=lpeg.P,lpeg.S,lpeg.R,lpeg.Cmt,lpeg.C,lpeg.Ct,lpeg.Cs,lpeg.Carg,lpeg.Cf,lpeg.Cg
local lpegmatch,patterns=lpeg.match,lpeg.patterns
local trace_indexing=false trackers.register("afm.indexing",function(v) trace_indexing=v end)
local trace_loading=false trackers.register("afm.loading",function(v) trace_loading=v end)
local report_afm=logs.reporter("fonts","afm loading")
-local report_afm=logs.reporter("fonts","pfb loading")
-fonts=fonts or {}
-local handlers=fonts.handlers or {}
-fonts.handlers=handlers
+local report_pfb=logs.reporter("fonts","pfb loading")
+local handlers=fonts.handlers
local afm=handlers.afm or {}
handlers.afm=afm
local readers=afm.readers or {}
@@ -23415,16 +23314,25 @@ do
end
local initialize=function(str,position,size)
n=0
- m=tonumber(size)
+ m=size
return position+1
end
local charstrings=P("/CharStrings")
+ local encoding=P("/Encoding")
+ local dup=P("dup")
+ local put=P("put")
+ local array=P("array")
local name=P("/")*C((R("az")+R("AZ")+R("09")+S("-_."))^1)
- local size=C(R("09")^1)
+ local digits=R("09")^1
+ local cardinal=digits/tonumber
local spaces=P(" ")^1
+ local spacing=patterns.whitespace^0
local p_filternames=Ct (
- (1-charstrings)^0*charstrings*spaces*Cmt(size,initialize)*(Cmt(name*P(" ")^1*C(R("09")^1),progress)+P(1))^1
+ (1-charstrings)^0*charstrings*spaces*Cmt(cardinal,initialize)*(Cmt(name*spaces*cardinal,progress)+P(1))^1
)
+ local p_filterencoding=(1-encoding)^0*encoding*spaces*digits*spaces*array*(1-dup)^0*Cf(
+ Ct("")*Cg(spacing*dup*spaces*cardinal*spaces*name*spaces*put)^1
+,rawset)
local decrypt
do
local r,c1,c2,n=0,0,0,0
@@ -23457,15 +23365,20 @@ do
end
binary=decrypt(binary,4)
local vector=lpegmatch(p_filternames,binary)
- if vector[1]==".notdef" then
- vector[0]=table.remove(vector,1)
+ for i=1,#vector do
+ vector[i-1]=vector[i]
end
+ vector[#vector]=nil
if not vector then
report_pfb("no vector in %a",filename)
return
end
- return vector
+ local encoding=lpegmatch(p_filterencoding,ascii)
+ return vector,encoding
end
+ local pfb=handlers.pfb or {}
+ handlers.pfb=pfb
+ pfb.loadvector=loadpfbvector
get_indexes=function(data,pfbname)
local vector=loadpfbvector(pfbname)
if vector then
@@ -23691,6 +23604,7 @@ local steps={
"add ligatures",
"add extra kerns",
"normalize features",
+ "check extra features",
"fix names",
}
local function applyenhancers(data,filename)
@@ -23904,6 +23818,7 @@ enhancers["normalize features"]=function(data)
data.resources.features=features
data.resources.sequences=sequences
end
+enhancers["check extra features"]=otf.enhancers.enhance
enhancers["fix names"]=function(data)
for k,v in next,data.descriptions do
local n=v.name
@@ -24265,17 +24180,12 @@ local function read_from_afm(specification)
end
return tfmdata
end
-local function setmode(tfmdata,value)
- if value then
- tfmdata.properties.mode=lower(value)
- end
-end
registerafmfeature {
name="mode",
description="mode",
initializers={
- base=setmode,
- node=setmode,
+ base=otf.modeinitializer,
+ node=otf.modeinitializer,
}
}
registerafmfeature {
@@ -24290,7 +24200,6 @@ registerafmfeature {
node=otf.featuresprocessor,
}
}
-local check_tfm=readers.check_tfm
fonts.formats.afm="type1"
fonts.formats.pfb="type1"
local function check_afm(specification,fullname)
@@ -24325,7 +24234,8 @@ function readers.afm(specification,method)
tfmdata=check_afm(specification,specification.name.."."..forced)
end
if not tfmdata then
- method=method or definers.method or "afm or tfm"
+ local check_tfm=readers.check_tfm
+ method=(check_tfm and (method or definers.method or "afm or tfm")) or "afm"
if method=="tfm" then
tfmdata=check_tfm(specification,specification.name)
elseif method=="afm" then
@@ -24533,6 +24443,529 @@ end -- closure
do -- begin closure to overcome local limits and interference
+if not modules then modules={} end modules ['font-tfm']={
+ version=1.001,
+ comment="companion to font-ini.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local next,type=next,type
+local match,format=string.match,string.format
+local concat,sortedhash=table.concat,table.sortedhash
+local trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end)
+local trace_features=false trackers.register("tfm.features",function(v) trace_features=v end)
+local report_defining=logs.reporter("fonts","defining")
+local report_tfm=logs.reporter("fonts","tfm loading")
+local findbinfile=resolvers.findbinfile
+local setmetatableindex=table.setmetatableindex
+local fonts=fonts
+local handlers=fonts.handlers
+local readers=fonts.readers
+local constructors=fonts.constructors
+local encodings=fonts.encodings
+local tfm=constructors.handlers.tfm
+tfm.version=1.000
+tfm.maxnestingdepth=5
+tfm.maxnestingsize=65536*1024
+local otf=fonts.handlers.otf
+local tfmfeatures=constructors.features.tfm
+local registertfmfeature=tfmfeatures.register
+constructors.resolvevirtualtoo=false
+fonts.formats.tfm="type1"
+fonts.formats.ofm="type1"
+function tfm.setfeatures(tfmdata,features)
+ local okay=constructors.initializefeatures("tfm",tfmdata,features,trace_features,report_tfm)
+ if okay then
+ return constructors.collectprocessors("tfm",tfmdata,features,trace_features,report_tfm)
+ else
+ return {}
+ end
+end
+local depth={}
+local enhancers={}
+local steps={
+ "normalize features",
+ "check extra features"
+}
+enhancers["check extra features"]=otf.enhancers.enhance
+local function applyenhancers(data,filename)
+ for i=1,#steps do
+ local step=steps[i]
+ local enhancer=enhancers[step]
+ if enhancer then
+ if trace_loading then
+ report_tfm("applying enhancer %a",step)
+ end
+ enhancer(data,filename)
+ else
+ report_tfm("invalid enhancer %a",step)
+ end
+ end
+end
+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
+ local tfmdata=font.read_tfm(filename,size)
+ if tfmdata then
+ local features=specification.features and specification.features.normal or {}
+ local features=constructors.checkedfeatures("tfm",features)
+ specification.features.normal=features
+ local newtfmdata=(depth[filename]==1) and tfm.reencode(tfmdata,specification)
+ if newtfmdata then
+ tfmdata=newtfmdata
+ end
+ local resources=tfmdata.resources or {}
+ local properties=tfmdata.properties or {}
+ local parameters=tfmdata.parameters or {}
+ local shared=tfmdata.shared or {}
+ shared.features=features
+ shared.resources=resources
+ properties.name=tfmdata.name
+ properties.fontname=tfmdata.fontname
+ properties.psname=tfmdata.psname
+ properties.fullname=tfmdata.fullname
+ properties.filename=specification.filename
+ properties.format=fonts.formats.tfm
+ tfmdata.properties=properties
+ tfmdata.resources=resources
+ tfmdata.parameters=parameters
+ tfmdata.shared=shared
+ shared.rawdata={ resources=resources }
+ shared.features=features
+ if newtfmdata then
+ if not resources.marks then
+ resources.marks={}
+ end
+ if not resources.sequences then
+ resources.sequences={}
+ end
+ if not resources.features then
+ resources.features={
+ gsub={},
+ gpos={},
+ }
+ end
+ if not tfmdata.changed then
+ tfmdata.changed={}
+ end
+ if not tfmdata.descriptions then
+ tfmdata.descriptions=tfmdata.characters
+ end
+ otf.readers.addunicodetable(tfmdata)
+ applyenhancers(tfmdata,filename)
+ constructors.applymanipulators("tfm",tfmdata,features,trace_features,report_tfm)
+ otf.readers.unifymissing(tfmdata)
+ fonts.mappings.addtounicode(tfmdata,filename)
+ tfmdata.tounicode=1
+ local tounicode=fonts.mappings.tounicode
+ for unicode,v in next,tfmdata.characters do
+ local u=v.unicode
+ if u then
+ v.tounicode=tounicode(u)
+ end
+ end
+ if tfmdata.usedbitmap then
+ tfm.addtounicode(tfmdata)
+ end
+ end
+ shared.processes=next(features) and tfm.setfeatures(tfmdata,features) or nil
+ parameters.factor=1
+ parameters.size=size
+ parameters.slant=parameters.slant or parameters[1] or 0
+ parameters.space=parameters.space or parameters[2] or 0
+ parameters.space_stretch=parameters.space_stretch or parameters[3] or 0
+ parameters.space_shrink=parameters.space_shrink or parameters[4] or 0
+ parameters.x_height=parameters.x_height or parameters[5] or 0
+ parameters.quad=parameters.quad or parameters[6] or 0
+ parameters.extra_space=parameters.extra_space or parameters[7] or 0
+ constructors.enhanceparameters(parameters)
+ if newtfmdata then
+ elseif constructors.resolvevirtualtoo then
+ fonts.loggers.register(tfmdata,file.suffix(filename),specification)
+ local vfname=findbinfile(specification.name,'ovf')
+ if vfname and vfname~="" then
+ local vfdata=font.read_vf(vfname,size)
+ if vfdata then
+ local chars=tfmdata.characters
+ for k,v in next,vfdata.characters do
+ chars[k].commands=v.commands
+ 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
+ properties.haskerns=true
+ properties.hasligatures=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)
+ local foundname=findbinfile(fullname,'tfm') or ""
+ if foundname=="" then
+ foundname=findbinfile(fullname,'ofm') or ""
+ end
+ if foundname=="" then
+ foundname=fonts.names.getfilename(fullname,"tfm") or ""
+ end
+ if foundname~="" then
+ specification.filename=foundname
+ specification.format="ofm"
+ return read_from_tfm(specification)
+ elseif trace_defining then
+ report_defining("loading tfm with name %a fails",specification.name)
+ end
+end
+readers.check_tfm=check_tfm
+function readers.tfm(specification)
+ local fullname=specification.filename or ""
+ if fullname=="" then
+ local forced=specification.forced or ""
+ if forced~="" then
+ fullname=specification.name.."."..forced
+ else
+ fullname=specification.name
+ end
+ end
+ return check_tfm(specification,fullname)
+end
+readers.ofm=readers.tfm
+do
+ local outfiles={}
+ local tfmcache=table.setmetatableindex(function(t,tfmdata)
+ local id=font.define(tfmdata)
+ t[tfmdata]=id
+ return id
+ end)
+ local encdone=table.setmetatableindex("table")
+ function tfm.reencode(tfmdata,specification)
+ local features=specification.features
+ if not features then
+ return
+ end
+ local features=features.normal
+ if not features then
+ return
+ end
+ local tfmfile=file.basename(tfmdata.name)
+ local encfile=features.reencode
+ local pfbfile=features.pfbfile
+ local bitmap=features.bitmap
+ if not encfile then
+ return
+ end
+ local pfbfile=outfiles[tfmfile]
+ if pfbfile==nil then
+ if bitmap then
+ pfbfile=false
+ elseif type(pfbfile)~="string" then
+ pfbfile=tfmfile
+ end
+ if type(pfbfile)=="string" then
+ pfbfile=file.addsuffix(pfbfile,"pfb")
+ report_tfm("using type1 shapes from %a for %a",pfbfile,tfmfile)
+ else
+ report_tfm("using bitmap shapes for %a",tfmfile)
+ pfbfile=false
+ end
+ outfiles[tfmfile]=pfbfile
+ end
+ local encoding=false
+ local vector=false
+ if type(pfbfile)=="string" then
+ local pfb=fonts.constructors.handlers.pfb
+ if pfb and pfb.loadvector then
+ local v,e=pfb.loadvector(pfbfile)
+ if v then
+ vector=v
+ end
+ if e then
+ encoding=e
+ end
+ end
+ end
+ if type(encfile)=="string" and encfile~="auto" then
+ encoding=fonts.encodings.load(file.addsuffix(encfile,"enc"))
+ if encoding then
+ encoding=encoding.vector
+ end
+ end
+ if not encoding then
+ report_tfm("bad encoding for %a, quitting",tfmfile)
+ return
+ end
+ local unicoding=fonts.encodings.agl and fonts.encodings.agl.unicodes
+ local virtualid=tfmcache[tfmdata]
+ local tfmdata=table.copy(tfmdata)
+ local characters={}
+ local originals=tfmdata.characters
+ local indices={}
+ local parentfont={ "font",1 }
+ local private=fonts.constructors.privateoffset
+ local reported=encdone[tfmfile][encfile]
+ local backmap=vector and table.swapped(vector)
+ local done={}
+ for index,name in sortedhash(encoding) do
+ local unicode=unicoding[name]
+ local original=originals[index]
+ if original then
+ if unicode then
+ original.unicode=unicode
+ else
+ unicode=private
+ private=private+1
+ if not reported then
+ report_tfm("glyph %a in font %a with encoding %a gets unicode %U",name,tfmfile,encfile,unicode)
+ end
+ end
+ characters[unicode]=original
+ indices[index]=unicode
+ original.name=name
+ if backmap then
+ original.index=backmap[name]
+ else
+ original.commands={ parentfont,{ "char",index } }
+ original.oindex=index
+ end
+ done[name]=true
+ elseif not done[name] then
+ report_tfm("bad index %a in font %a with name %a",index,tfmfile,name)
+ end
+ end
+ encdone[tfmfile][encfile]=true
+ for k,v in next,characters do
+ local kerns=v.kerns
+ if kerns then
+ local t={}
+ for k,v in next,kerns do
+ local i=indices[k]
+ if i then
+ t[i]=v
+ end
+ end
+ v.kerns=next(t) and t or nil
+ end
+ local ligatures=v.ligatures
+ if ligatures then
+ local t={}
+ for k,v in next,ligatures do
+ local i=indices[k]
+ if i then
+ t[i]=v
+ v.char=indices[v.char]
+ end
+ end
+ v.ligatures=next(t) and t or nil
+ end
+ end
+ tfmdata.fonts={ { id=virtualid } }
+ tfmdata.characters=characters
+ tfmdata.fullname=tfmdata.fullname or tfmdata.name
+ tfmdata.psname=file.nameonly(pfbfile or tfmdata.name)
+ tfmdata.filename=pfbfile
+ tfmdata.encodingbytes=2
+ tfmdata.format="type1"
+ tfmdata.tounicode=1
+ tfmdata.embedding="subset"
+ tfmdata.usedbitmap=bitmap and virtualid
+ return tfmdata
+ end
+end
+do
+ local template=[[
+/CIDInit /ProcSet findresource begin
+ 12 dict begin
+ begincmap
+ /CIDSystemInfo << /Registry (TeX) /Ordering (bitmap-%s) /Supplement 0 >> def
+ /CMapName /TeX-bitmap-%s def
+ /CMapType 2 def
+ 1 begincodespacerange
+ <00> <FF>
+ endcodespacerange
+ %s beginbfchar
+%s
+ endbfchar
+ endcmap
+CMapName currentdict /CMap defineresource pop end
+end
+end
+]]
+ local flushstreamobject=lpdf and lpdf.flushstreamobject
+ local setfontattributes=pdf.setfontattributes
+ if not flushstreamobject then
+ flushstreamobject=function(data)
+ return pdf.obj {
+ immediate=true,
+ type="stream",
+ string=data,
+ }
+ end
+ end
+ if not setfontattributes then
+ setfontattributes=function(id,data)
+ print(format("your luatex is too old so no tounicode bitmap font%i",id))
+ end
+ end
+ function tfm.addtounicode(tfmdata)
+ local id=tfmdata.usedbitmap
+ local map={}
+ local char={}
+ for k,v in next,tfmdata.characters do
+ local index=v.oindex
+ local tounicode=v.tounicode
+ if index and tounicode then
+ map[index]=tounicode
+ end
+ end
+ for k,v in sortedhash(map) do
+ char[#char+1]=format("<%02X> <%s>",k,v)
+ end
+ char=concat(char,"\n")
+ local stream=format(template,id,id,#char,char)
+ local reference=flushstreamobject(stream,nil,true)
+ setfontattributes(id,format("/ToUnicode %i 0 R",reference))
+ end
+end
+do
+ local everywhere={ ["*"]={ ["*"]=true } }
+ local noflags={ false,false,false,false }
+ enhancers["normalize features"]=function(data)
+ local ligatures=setmetatableindex("table")
+ local kerns=setmetatableindex("table")
+ local characters=data.characters
+ for u,c in next,characters do
+ local l=c.ligatures
+ local k=c.kerns
+ if l then
+ ligatures[u]=l
+ for u,v in next,l do
+ l[u]={ ligature=v.char }
+ end
+ c.ligatures=nil
+ end
+ if k then
+ kerns[u]=k
+ for u,v in next,k do
+ k[u]=v
+ end
+ c.kerns=nil
+ end
+ end
+ for u,l in next,ligatures do
+ for k,v in next,l do
+ local vl=v.ligature
+ local dl=ligatures[vl]
+ if dl then
+ for kk,vv in next,dl do
+ v[kk]=vv
+ end
+ end
+ end
+ end
+ local features={
+ gpos={},
+ gsub={},
+ }
+ local sequences={
+ }
+ if next(ligatures) then
+ features.gsub.liga=everywhere
+ data.properties.hasligatures=true
+ sequences[#sequences+1]={
+ features={
+ liga=everywhere,
+ },
+ flags=noflags,
+ name="s_s_0",
+ nofsteps=1,
+ order={ "liga" },
+ type="gsub_ligature",
+ steps={
+ {
+ coverage=ligatures,
+ },
+ },
+ }
+ end
+ if next(kerns) then
+ features.gpos.kern=everywhere
+ data.properties.haskerns=true
+ sequences[#sequences+1]={
+ features={
+ kern=everywhere,
+ },
+ flags=noflags,
+ name="p_s_0",
+ nofsteps=1,
+ order={ "kern" },
+ type="gpos_pair",
+ steps={
+ {
+ format="kern",
+ coverage=kerns,
+ },
+ },
+ }
+ end
+ data.resources.features=features
+ data.resources.sequences=sequences
+ data.shared.resources=data.shared.resources or resources
+ end
+end
+registertfmfeature {
+ name="mode",
+ description="mode",
+ initializers={
+ base=otf.modeinitializer,
+ node=otf.modeinitializer,
+ }
+}
+registertfmfeature {
+ name="features",
+ description="features",
+ default=true,
+ initializers={
+ base=otf.basemodeinitializer,
+ node=otf.nodemodeinitializer,
+ },
+ processors={
+ node=otf.featuresprocessor,
+ }
+}
+
+end -- closure
+
+do -- begin closure to overcome local limits and interference
+
if not modules then modules={} end modules ['font-lua']={
version=1.001,
comment="companion to font-ini.mkiv",
@@ -24582,10 +25015,11 @@ if not modules then modules={} end modules ['font-def']={
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files"
}
-local format,gmatch,match,find,lower,gsub=string.format,string.gmatch,string.match,string.find,string.lower,string.gsub
+local lower,gsub=string.lower,string.gsub
local tostring,next=tostring,next
local lpegmatch=lpeg.match
local suffixonly,removesuffix=file.suffix,file.removesuffix
+local formatters=string.formatters
local allocate=utilities.storage.allocate
local trace_defining=false trackers .register("fonts.defining",function(v) trace_defining=v end)
local directive_embedall=false directives.register("fonts.embedall",function(v) directive_embedall=v end)
@@ -24746,7 +25180,7 @@ function definers.applypostprocessors(tfmdata)
local extrahash=postprocessors[i](tfmdata)
if type(extrahash)=="string" and extrahash~="" then
extrahash=gsub(lower(extrahash),"[^a-z]","-")
- properties.fullname=format("%s-%s",properties.fullname,extrahash)
+ properties.fullname=formatters["%s-%s"](properties.fullname,extrahash)
end
end
end