From 195d57dba1533a03204aa8b7ff26ed2bb28d3405 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Mon, 9 May 2016 07:15:44 +0200
Subject: [fontloader] sync with Context as of 2016-05-09
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Fixes #349 and #357.
Also the new AFM code is due, let’s see what else we need to use it.
---
src/fontloader/misc/fontloader-font-gbn.lua | 20 +-
src/fontloader/misc/fontloader-font-otj.lua | 30 +-
src/fontloader/misc/fontloader-font-otl.lua | 8 +-
src/fontloader/misc/fontloader-font-oto.lua | 2 +
src/fontloader/misc/fontloader-font-ots.lua | 3 +
src/fontloader/misc/fontloader-fonts.lua | 7 +-
src/fontloader/runtime/fontloader-reference.lua | 5236 ++++++++++++-----------
7 files changed, 2674 insertions(+), 2632 deletions(-)
diff --git a/src/fontloader/misc/fontloader-font-gbn.lua b/src/fontloader/misc/fontloader-font-gbn.lua
index daa072b..a02406b 100644
--- a/src/fontloader/misc/fontloader-font-gbn.lua
+++ b/src/fontloader/misc/fontloader-font-gbn.lua
@@ -126,17 +126,19 @@ function nodes.handlers.nodepass(head)
local variant = hash[getchar(p)]
if variant then
setchar(p,variant)
- if not redundant then
- redundant = { n }
- else
- redundant[#redundant+1] = n
- end
end
end
end
+ -- per generic user request we always remove selectors
+ if not redundant then
+ redundant = { n }
+ else
+ redundant[#redundant+1] = n
+ end
end
end
end
+ local nofbasefonts = #basefonts
if redundant then
for i=1,#redundant do
local r = redundant[i]
@@ -147,8 +149,8 @@ function nodes.handlers.nodepass(head)
else
setlink(p,n)
end
- if b > 0 then
- for i=1,b do
+ if nofbasefonts > 0 then
+ for i=1,nofbasefonts do
local bi = basefonts[i]
if r == bi[1] then
bi[1] = n
@@ -192,8 +194,8 @@ function nodes.handlers.nodepass(head)
end
end
end
- if basemodepass and #basefonts > 0 then
- for i=1,#basefonts do
+ if basemodepass and nofbasefonts > 0 then
+ for i=1,nofbasefonts do
local range = basefonts[i]
local start = range[1]
local stop = range[2]
diff --git a/src/fontloader/misc/fontloader-font-otj.lua b/src/fontloader/misc/fontloader-font-otj.lua
index 6ff80d8..b65a9db 100644
--- a/src/fontloader/misc/fontloader-font-otj.lua
+++ b/src/fontloader/misc/fontloader-font-otj.lua
@@ -1255,11 +1255,11 @@ local function inject_everything(head,where)
insert_node_after(pre,n,newkern(rightkern))
done = true
end
- end
- if hasmarks then
- local pm = i.markbasenode
- if pm then
- processmark(pm,current,i)
+ if hasmarks then
+ local pm = i.markbasenode
+ if pm then
+ processmark(pm,current,i)
+ end
end
end
end
@@ -1287,11 +1287,11 @@ local function inject_everything(head,where)
insert_node_after(post,n,newkern(rightkern))
done = true
end
- end
- if hasmarks then
- local pm = i.markbasenode
- if pm then
- processmark(pm,current,i)
+ if hasmarks then
+ local pm = i.markbasenode
+ if pm then
+ processmark(pm,current,i)
+ end
end
end
end
@@ -1319,11 +1319,11 @@ local function inject_everything(head,where)
insert_node_after(replace,n,newkern(rightkern))
done = true
end
- end
- if hasmarks then
- local pm = i.markbasenode
- if pm then
- processmark(pm,current,i)
+ if hasmarks then
+ local pm = i.markbasenode
+ if pm then
+ processmark(pm,current,i)
+ end
end
end
end
diff --git a/src/fontloader/misc/fontloader-font-otl.lua b/src/fontloader/misc/fontloader-font-otl.lua
index f7b6eb5..01342a9 100644
--- a/src/fontloader/misc/fontloader-font-otl.lua
+++ b/src/fontloader/misc/fontloader-font-otl.lua
@@ -101,6 +101,12 @@ registerdirective("fonts.otf.loader.forcenotdef", function(v) forcenotdef =
-- end
-- end
+-- Enhancers are used to apply fixes and extensions to fonts. For instance, we use them
+-- to implement tlig and trep features. They are not neccessarily bound to opentype
+-- fonts but can also apply to type one fonts, given that they obey the structure of an
+-- opentype font. They are not to be confused with format specific features but maybe
+-- some are so generic that they might eventually move to this mechanism.
+
local ordered_enhancers = {
"check extra features",
}
@@ -302,7 +308,7 @@ function otf.load(filename,sub,featurefile) -- second argument (format) is gone
--
enhancers.apply(data,filename,data)
--
- constructors.addcoreunicodes(unicodes)
+ -- constructors.addcoreunicodes(data.resources.unicodes) -- still needed ?
--
if applyruntimefixes then
applyruntimefixes(filename,data)
diff --git a/src/fontloader/misc/fontloader-font-oto.lua b/src/fontloader/misc/fontloader-font-oto.lua
index b7ee717..23beba7 100644
--- a/src/fontloader/misc/fontloader-font-oto.lua
+++ b/src/fontloader/misc/fontloader-font-oto.lua
@@ -450,3 +450,5 @@ registerotffeature {
base = featuresinitializer,
}
}
+
+otf.basemodeinitializer = featuresinitializer
diff --git a/src/fontloader/misc/fontloader-font-ots.lua b/src/fontloader/misc/fontloader-font-ots.lua
index 21225c2..c173de2 100644
--- a/src/fontloader/misc/fontloader-font-ots.lua
+++ b/src/fontloader/misc/fontloader-font-ots.lua
@@ -3652,6 +3652,9 @@ registerotffeature {
}
}
+otf.nodemodeinitializer = featuresinitializer
+otf.featuresprocessor = featuresprocessor
+
-- This can be used for extra handlers, but should be used with care!
otf.handlers = handlers -- used in devanagari
diff --git a/src/fontloader/misc/fontloader-fonts.lua b/src/fontloader/misc/fontloader-fonts.lua
index e1ec376..1d2f203 100644
--- a/src/fontloader/misc/fontloader-fonts.lua
+++ b/src/fontloader/misc/fontloader-fonts.lua
@@ -230,8 +230,6 @@ if non_generic_context.luatex_fonts.skip_loading ~= true then
loadmodule('luatex-fonts-syn.lua')
loadmodule('font-tfm.lua')
- loadmodule('font-afm.lua')
- loadmodule('font-afk.lua')
loadmodule('font-oti.lua')
-- These are the old loader and processing modules. These use the built-in font loader and
@@ -260,6 +258,11 @@ if non_generic_context.luatex_fonts.skip_loading ~= true then
loadmodule('font-ots.lua')
loadmodule('font-osd.lua')
+ -- type one code
+
+ loadmodule('font-one.lua') -- was font-afm.lua
+ loadmodule('font-afk.lua')
+
-- common code
loadmodule('font-lua.lua')
diff --git a/src/fontloader/runtime/fontloader-reference.lua b/src/fontloader/runtime/fontloader-reference.lua
index 5f35ded..3e6f1d1 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 : 05/01/16 09:52:32
+-- merge date : 05/08/16 17:30:49
do -- begin closure to overcome local limits and interference
@@ -6973,51 +6973,61 @@ end -- closure
do -- begin closure to overcome local limits and interference
-if not modules then modules={} end modules ['font-afm']={
+if not modules then modules={} end modules ['font-oti']={
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 fonts,logs,trackers,containers,resolvers=fonts,logs,trackers,containers,resolvers
-local next,type,tonumber=next,type,tonumber
-local match,gmatch,lower,gsub,strip,find=string.match,string.gmatch,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,lpegmatch,patterns=lpeg.P,lpeg.S,lpeg.R,lpeg.Cmt,lpeg.C,lpeg.Ct,lpeg.Cs,lpeg.match,lpeg.patterns
-local derivetable=table.derive
-local trace_features=false trackers.register("afm.features",function(v) trace_features=v end)
-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 trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end)
-local report_afm=logs.reporter("fonts","afm loading")
-local setmetatableindex=table.setmetatableindex
-local findbinfile=resolvers.findbinfile
-local definers=fonts.definers
-local readers=fonts.readers
+local lower=string.lower
+local fonts=fonts
local constructors=fonts.constructors
-local afm=constructors.newhandler("afm")
-local pfb=constructors.newhandler("pfb")
-local afmfeatures=constructors.newfeatures("afm")
-local registerafmfeature=afmfeatures.register
-afm.version=1.501
-afm.cache=containers.define("fonts","afm",afm.version,true)
-afm.autoprefixed=true
-afm.helpdata={}
-afm.syncspace=true
-afm.addligatures=true
-afm.addtexligatures=true
-afm.addkerns=true
-local overloads=fonts.mappings.overloads
-local applyruntimefixes=fonts.treatments and fonts.treatments.applyfixes
+local otf=constructors.newhandler("otf")
+local otffeatures=constructors.newfeatures("otf")
+local registerotffeature=otffeatures.register
+local otftables=otf.tables or {}
+otf.tables=otftables
+local allocate=utilities.storage.allocate
+registerotffeature {
+ name="features",
+ description="initialization of feature handler",
+ default=true,
+}
local function setmode(tfmdata,value)
if value then
tfmdata.properties.mode=lower(value)
end
end
-registerafmfeature {
+local function setlanguage(tfmdata,value)
+ if value then
+ local cleanvalue=lower(value)
+ local languages=otftables and otftables.languages
+ local properties=tfmdata.properties
+ if not languages then
+ properties.language=cleanvalue
+ elseif languages[value] then
+ properties.language=cleanvalue
+ else
+ properties.language="dflt"
+ end
+ end
+end
+local function setscript(tfmdata,value)
+ if value then
+ local cleanvalue=lower(value)
+ local scripts=otftables and otftables.scripts
+ local properties=tfmdata.properties
+ if not scripts then
+ properties.script=cleanvalue
+ elseif scripts[value] then
+ properties.script=cleanvalue
+ else
+ properties.script="dflt"
+ end
+ end
+end
+registerotffeature {
name="mode",
description="mode",
initializers={
@@ -7025,1217 +7035,76 @@ registerafmfeature {
node=setmode,
}
}
-local comment=P("Comment")
-local spacing=patterns.spacer
-local lineend=patterns.newline
-local words=C((1-lineend)^1)
-local number=C((R("09")+S("."))^1)/tonumber*spacing^0
-local data=lpeg.Carg(1)
-local pattern=(
- comment*spacing*(
- data*(
- ("CODINGSCHEME"*spacing*words )/function(fd,a) end+("DESIGNSIZE"*spacing*number*words )/function(fd,a) fd[ 1]=a end+("CHECKSUM"*spacing*number*words )/function(fd,a) fd[ 2]=a end+("SPACE"*spacing*number*"plus"*number*"minus"*number)/function(fd,a,b,c) fd[ 3],fd[ 4],fd[ 5]=a,b,c end+("QUAD"*spacing*number )/function(fd,a) fd[ 6]=a end+("EXTRASPACE"*spacing*number )/function(fd,a) fd[ 7]=a end+("NUM"*spacing*number*number*number )/function(fd,a,b,c) fd[ 8],fd[ 9],fd[10]=a,b,c end+("DENOM"*spacing*number*number )/function(fd,a,b ) fd[11],fd[12]=a,b end+("SUP"*spacing*number*number*number )/function(fd,a,b,c) fd[13],fd[14],fd[15]=a,b,c end+("SUB"*spacing*number*number )/function(fd,a,b) fd[16],fd[17]=a,b end+("SUPDROP"*spacing*number )/function(fd,a) fd[18]=a end+("SUBDROP"*spacing*number )/function(fd,a) fd[19]=a end+("DELIM"*spacing*number*number )/function(fd,a,b) fd[20],fd[21]=a,b end+("AXISHEIGHT"*spacing*number )/function(fd,a) fd[22]=a end
- )+(1-lineend)^0
- )+(1-comment)^1
-)^0
-local function scan_comment(str)
- local fd={}
- lpegmatch(pattern,str,1,fd)
- return fd
-end
-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.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
-function keys.Ascender (data,line) data.metadata.ascender=tonumber (line) end
-function keys.Comment (data,line)
- line=lower(line)
- local designsize=match(line,"designsize[^%d]*(%d+)")
- if designsize then data.metadata.designsize=tonumber(designsize) end
-end
-local function get_charmetrics(data,charmetrics,vector)
- local characters=data.characters
- local chr,ind={},0
- for k,v in gmatch(charmetrics,"([%a]+) +(.-) *;") do
- if k=='C' then
- v=tonumber(v)
- if v<0 then
- ind=ind+1
+registerotffeature {
+ name="language",
+ description="language",
+ initializers={
+ base=setlanguage,
+ node=setlanguage,
+ }
+}
+registerotffeature {
+ name="script",
+ description="script",
+ initializers={
+ base=setscript,
+ node=setscript,
+ }
+}
+otftables.featuretypes=allocate {
+ gpos_single="position",
+ gpos_pair="position",
+ gpos_cursive="position",
+ gpos_mark2base="position",
+ gpos_mark2ligature="position",
+ gpos_mark2mark="position",
+ gpos_context="position",
+ gpos_contextchain="position",
+ gsub_single="substitution",
+ gsub_multiple="substitution",
+ gsub_alternate="substitution",
+ gsub_ligature="substitution",
+ gsub_context="substitution",
+ gsub_contextchain="substitution",
+ gsub_reversecontextchain="substitution",
+ gsub_reversesub="substitution",
+}
+function otffeatures.checkeddefaultscript(featuretype,autoscript,scripts)
+ if featuretype=="position" then
+ local default=scripts.dflt
+ if default then
+ if autoscript=="position" or autoscript==true then
+ return default
else
- ind=v
+ report_otf("script feature %s not applied, enable default positioning")
end
- chr={
- index=ind
- }
- elseif k=='WX' then
- chr.width=tonumber(v)
- elseif k=='N' then
- characters[v]=chr
- elseif k=='B' then
- local llx,lly,urx,ury=match(v,"^ *(.-) +(.-) +(.-) +(.-)$")
- chr.boundingbox={ tonumber(llx),tonumber(lly),tonumber(urx),tonumber(ury) }
- elseif k=='L' then
- local plus,becomes=match(v,"^(.-) +(.-)$")
- local ligatures=chr.ligatures
- if ligatures then
- ligatures[plus]=becomes
- else
- chr.ligatures={ [plus]=becomes }
+ else
+ end
+ elseif featuretype=="substitution" then
+ local default=scripts.dflt
+ if default then
+ if autoscript=="substitution" or autoscript==true then
+ return default
end
end
end
end
-local function get_kernpairs(data,kernpairs)
- local characters=data.characters
- for one,two,value in gmatch(kernpairs,"KPX +(.-) +(.-) +(.-)\n") do
- local chr=characters[one]
- if chr then
- local kerns=chr.kerns
- if kerns then
- kerns[two]=tonumber(value)
+function otffeatures.checkeddefaultlanguage(featuretype,autolanguage,languages)
+ if featuretype=="position" then
+ local default=languages.dflt
+ if default then
+ if autolanguage=="position" or autolanguage==true then
+ return default
else
- chr.kerns={ [two]=tonumber(value) }
+ report_otf("language feature %s not applied, enable default positioning")
end
+ else
end
- end
-end
-local function get_variables(data,fontmetrics)
- for key,rest in gmatch(fontmetrics,"(%a+) *(.-)[\n\r]") do
- local keyhandler=keys[key]
- if keyhandler then
- keyhandler(data,rest)
- end
- end
-end
-local get_indexes
-do
- local fontloader=fontloader
- local get_indexes_old=false
- if fontloader then
- local font_to_table=fontloader.to_table
- local open_font=fontloader.open
- local close_font=fontloader.close
- get_indexes_old=function(data,pfbname)
- local pfbblob=open_font(pfbname)
- if pfbblob then
- local characters=data.characters
- local pfbdata=font_to_table(pfbblob)
- if pfbdata then
- local glyphs=pfbdata.glyphs
- if glyphs then
- if trace_loading then
- report_afm("getting index data from %a",pfbname)
- end
- for index,glyph in next,glyphs do
- local name=glyph.name
- if name then
- local char=characters[name]
- if char then
- if trace_indexing then
- report_afm("glyph %a has index %a",name,index)
- end
- char.index=index
- end
- end
- end
- elseif trace_loading then
- report_afm("no glyph data in pfb file %a",pfbname)
- end
- elseif trace_loading then
- report_afm("no data in pfb file %a",pfbname)
- end
- close_font(pfbblob)
- elseif trace_loading then
- report_afm("invalid pfb file %a",pfbname)
- end
- end
- end
- local n,m
- local progress=function(str,position,name,size)
- local forward=position+tonumber(size)+3+2
- n=n+1
- if n>=m then
- return #str,name
- elseif forward<#str then
- return forward,name
- else
- return #str,name
- end
- end
- local initialize=function(str,position,size)
- n=0
- m=tonumber(size)
- return position+1
- end
- local charstrings=P("/CharStrings")
- local name=P("/")*C((R("az")+R("AZ")+R("09")+S("-_."))^1)
- local size=C(R("09")^1)
- local spaces=P(" ")^1
- local p_filternames=Ct (
- (1-charstrings)^0*charstrings*spaces*Cmt(size,initialize)*(Cmt(name*P(" ")^1*C(R("09")^1),progress)+P(1))^1
- )
- local decrypt
- do
- local r,c1,c2,n=0,0,0,0
- local function step(c)
- local cipher=byte(c)
- local plain=bxor(cipher,rshift(r,8))
- r=((cipher+r)*c1+c2)%65536
- return char(plain)
- end
- decrypt=function(binary)
- r,c1,c2,n=55665,52845,22719,4
- binary=gsub(binary,".",step)
- return sub(binary,n+1)
- end
- end
- local function loadpfbvector(filename)
- local data=io.loaddata(resolvers.findfile(filename))
- if not find(data,"!PS%-AdobeFont%-") then
- print("no font",filename)
- return
- end
- if not data then
- print("no data",filename)
- return
- end
- local ascii,binary=match(data,"(.*)eexec%s+......(.*)")
- if not binary then
- print("no binary",filename)
- return
- end
- binary=decrypt(binary,4)
- local vector=lpegmatch(p_filternames,binary)
- vector[0]=table.remove(vector,1)
- if not vector then
- print("no vector",filename)
- return
- end
- return vector
- end
- get_indexes=function(data,pfbname)
- local vector=loadpfbvector(pfbname)
- if vector then
- local characters=data.characters
- if trace_loading then
- report_afm("getting index data from %a",pfbname)
- end
- for index=1,#vector do
- local name=vector[index]
- local char=characters[name]
- if char then
- if trace_indexing then
- report_afm("glyph %a has index %a",name,index)
- end
- char.index=index
- end
- end
- end
- end
- if get_indexes_old then
- afm.use_new_indexer=true
- get_indexes_new=get_indexes
- get_indexes=function(data,pfbname)
- if afm.use_new_indexer then
- return get_indexes_new(data,pfbname)
- else
- return get_indexes_old(data,pfbname)
- end
- end
- end
-end
-local function readafm(filename)
- local ok,afmblob,size=resolvers.loadbinfile(filename)
- if ok and afmblob then
- local data={
- resources={
- filename=resolvers.unresolve(filename),
- version=afm.version,
- creator="context mkiv",
- },
- properties={
- hasitalics=false,
- },
- goodies={},
- metadata={
- filename=file.removesuffix(file.basename(filename))
- },
- characters={
- },
- descriptions={
- },
- }
- afmblob=gsub(afmblob,"StartCharMetrics(.-)EndCharMetrics",function(charmetrics)
- if trace_loading then
- report_afm("loading char metrics")
- end
- get_charmetrics(data,charmetrics,vector)
- return ""
- end)
- afmblob=gsub(afmblob,"StartKernPairs(.-)EndKernPairs",function(kernpairs)
- if trace_loading then
- report_afm("loading kern pairs")
- end
- get_kernpairs(data,kernpairs)
- return ""
- end)
- afmblob=gsub(afmblob,"StartFontMetrics%s+([%d%.]+)(.-)EndFontMetrics",function(version,fontmetrics)
- if trace_loading then
- report_afm("loading variables")
- end
- data.afmversion=version
- get_variables(data,fontmetrics)
- data.fontdimens=scan_comment(fontmetrics)
- return ""
- end)
- return data
- else
- if trace_loading then
- report_afm("no valid afm file %a",filename)
- end
- return nil
- end
-end
-local addkerns,addligatures,addtexligatures,unify,normalize,fixnames
-function afm.load(filename)
- filename=resolvers.findfile(filename,'afm') or ""
- if filename~="" and not fonts.names.ignoredfile(filename) then
- local name=file.removesuffix(file.basename(filename))
- local data=containers.read(afm.cache,name)
- local attr=lfs.attributes(filename)
- local size,time=attr.size or 0,attr.modification or 0
- local pfbfile=file.replacesuffix(name,"pfb")
- local pfbname=resolvers.findfile(pfbfile,"pfb") or ""
- if pfbname=="" then
- pfbname=resolvers.findfile(file.basename(pfbfile),"pfb") or ""
- end
- local pfbsize,pfbtime=0,0
- if pfbname~="" then
- local attr=lfs.attributes(pfbname)
- pfbsize=attr.size or 0
- pfbtime=attr.modification or 0
- end
- if not data or data.size~=size or data.time~=time or data.pfbsize~=pfbsize or data.pfbtime~=pfbtime then
- report_afm("reading %a",filename)
- data=readafm(filename)
- if data then
- if pfbname~="" then
- data.resources.filename=resolvers.unresolve(pfbname)
- get_indexes(data,pfbname)
- elseif trace_loading then
- report_afm("no pfb file for %a",filename)
- end
- report_afm("unifying %a",filename)
- unify(data,filename)
- if afm.addligatures then
- report_afm("add ligatures")
- addligatures(data)
- end
- if afm.addtexligatures then
- report_afm("add tex ligatures")
- addtexligatures(data)
- end
- if afm.addkerns then
- report_afm("add extra kerns")
- addkerns(data)
- end
- normalize(data)
- fixnames(data)
- report_afm("add tounicode data")
- fonts.mappings.addtounicode(data,filename)
- data.size=size
- data.time=time
- data.pfbsize=pfbsize
- data.pfbtime=pfbtime
- report_afm("saving %a in cache",name)
- data.resources.unicodes=nil
- data=containers.write(afm.cache,name,data)
- data=containers.read(afm.cache,name)
- end
- if applyruntimefixes and data then
- applyruntimefixes(filename,data)
- end
- end
- return data
- else
- return nil
- end
-end
-local uparser=fonts.mappings.makenameparser()
-unify=function(data,filename)
- local unicodevector=fonts.encodings.agl.unicodes
- local unicodes={}
- local names={}
- local private=constructors.privateoffset
- local descriptions=data.descriptions
- for name,blob in next,data.characters do
- local code=unicodevector[name]
- if not code then
- code=lpegmatch(uparser,name)
- if not code then
- code=private
- private=private+1
- report_afm("assigning private slot %U for unknown glyph name %a",code,name)
- end
- end
- local index=blob.index
- unicodes[name]=code
- names[name]=index
- blob.name=name
- descriptions[code]={
- boundingbox=blob.boundingbox,
- width=blob.width,
- kerns=blob.kerns,
- index=index,
- name=name,
- }
- end
- for unicode,description in next,descriptions do
- local kerns=description.kerns
- if kerns then
- local krn={}
- for name,kern in next,kerns do
- local unicode=unicodes[name]
- if unicode then
- krn[unicode]=kern
- else
- end
- end
- description.kerns=krn
- end
- end
- data.characters=nil
- local resources=data.resources
- local filename=resources.filename or file.removesuffix(file.basename(filename))
- resources.filename=resolvers.unresolve(filename)
- resources.unicodes=unicodes
- resources.marks={}
- resources.private=private
-end
-local everywhere={ ["*"]={ ["*"]=true } }
-local noflags={ false,false,false,false }
-afm.experimental_normalize=false
-normalize=function(data)
- if type(afm.experimental_normalize)=="function" then
- afm.experimental_normalize(data)
- end
-end
-fixnames=function(data)
- for k,v in next,data.descriptions do
- local n=v.name
- local r=overloads[n]
- if r then
- local name=r.name
- if trace_indexing then
- report_afm("renaming characters %a to %a",n,name)
- end
- v.name=name
- v.unicode=r.unicode
- end
- end
-end
-local addthem=function(rawdata,ligatures)
- if ligatures then
- local descriptions=rawdata.descriptions
- local resources=rawdata.resources
- local unicodes=resources.unicodes
- for ligname,ligdata in next,ligatures do
- local one=descriptions[unicodes[ligname]]
- if one then
- for _,pair in next,ligdata do
- local two,three=unicodes[pair[1]],unicodes[pair[2]]
- if two and three then
- local ol=one.ligatures
- if ol then
- if not ol[two] then
- ol[two]=three
- end
- else
- one.ligatures={ [two]=three }
- end
- end
- end
- end
- end
- end
-end
-addligatures=function(rawdata) addthem(rawdata,afm.helpdata.ligatures ) end
-addtexligatures=function(rawdata) addthem(rawdata,afm.helpdata.texligatures) end
-addkerns=function(rawdata)
- local descriptions=rawdata.descriptions
- local resources=rawdata.resources
- local unicodes=resources.unicodes
- local function do_it_left(what)
- if what then
- for unicode,description in next,descriptions do
- local kerns=description.kerns
- if kerns then
- local extrakerns
- for complex,simple in next,what do
- complex=unicodes[complex]
- simple=unicodes[simple]
- if complex and simple then
- local ks=kerns[simple]
- if ks and not kerns[complex] then
- if extrakerns then
- extrakerns[complex]=ks
- else
- extrakerns={ [complex]=ks }
- end
- end
- end
- end
- if extrakerns then
- description.extrakerns=extrakerns
- end
- end
- end
- end
- end
- local function do_it_copy(what)
- if what then
- for complex,simple in next,what do
- complex=unicodes[complex]
- simple=unicodes[simple]
- if complex and simple then
- local complexdescription=descriptions[complex]
- if complexdescription then
- local simpledescription=descriptions[complex]
- if simpledescription then
- local extrakerns
- local kerns=simpledescription.kerns
- if kerns then
- for unicode,kern in next,kerns do
- if extrakerns then
- extrakerns[unicode]=kern
- else
- extrakerns={ [unicode]=kern }
- end
- end
- end
- local extrakerns=simpledescription.extrakerns
- if extrakerns then
- for unicode,kern in next,extrakerns do
- if extrakerns then
- extrakerns[unicode]=kern
- else
- extrakerns={ [unicode]=kern }
- end
- end
- end
- if extrakerns then
- complexdescription.extrakerns=extrakerns
- end
- end
- end
- end
- end
- end
- end
- do_it_left(afm.helpdata.leftkerned)
- do_it_left(afm.helpdata.bothkerned)
- do_it_copy(afm.helpdata.bothkerned)
- do_it_copy(afm.helpdata.rightkerned)
-end
-local function adddimensions(data)
- if data then
- for unicode,description in next,data.descriptions do
- local bb=description.boundingbox
- if bb then
- local ht,dp=bb[4],-bb[2]
- if ht==0 or ht<0 then
- else
- description.height=ht
- end
- if dp==0 or dp<0 then
- else
- description.depth=dp
- end
- end
- end
- end
-end
-local function copytotfm(data)
- if data and data.descriptions then
- local metadata=data.metadata
- local resources=data.resources
- local properties=derivetable(data.properties)
- local descriptions=derivetable(data.descriptions)
- local goodies=derivetable(data.goodies)
- local characters={}
- local parameters={}
- local unicodes=resources.unicodes
- for unicode,description in next,data.descriptions do
- characters[unicode]={}
- end
- local filename=constructors.checkedfilename(resources)
- local fontname=metadata.fontname or metadata.fullname
- local fullname=metadata.fullname or metadata.fontname
- local endash=0x0020
- local emdash=0x2014
- local spacer="space"
- local spaceunits=500
- local monospaced=metadata.monospaced
- local charwidth=metadata.charwidth
- local italicangle=metadata.italicangle
- local charxheight=metadata.xheight and metadata.xheight>0 and metadata.xheight
- properties.monospaced=monospaced
- parameters.italicangle=italicangle
- parameters.charwidth=charwidth
- parameters.charxheight=charxheight
- if properties.monospaced then
- if descriptions[endash] then
- spaceunits,spacer=descriptions[endash].width,"space"
- end
- if not spaceunits and descriptions[emdash] then
- spaceunits,spacer=descriptions[emdash].width,"emdash"
- end
- if not spaceunits and charwidth then
- spaceunits,spacer=charwidth,"charwidth"
- end
- else
- if descriptions[endash] then
- spaceunits,spacer=descriptions[endash].width,"space"
- end
- if not spaceunits and charwidth then
- spaceunits,spacer=charwidth,"charwidth"
- end
- end
- spaceunits=tonumber(spaceunits)
- if spaceunits<200 then
- end
- parameters.slant=0
- parameters.space=spaceunits
- parameters.space_stretch=500
- parameters.space_shrink=333
- parameters.x_height=400
- parameters.quad=1000
- if italicangle and italicangle~=0 then
- parameters.italicangle=italicangle
- parameters.italicfactor=math.cos(math.rad(90+italicangle))
- parameters.slant=- math.tan(italicangle*math.pi/180)
- end
- if monospaced then
- parameters.space_stretch=0
- parameters.space_shrink=0
- elseif afm.syncspace then
- parameters.space_stretch=spaceunits/2
- parameters.space_shrink=spaceunits/3
- end
- parameters.extra_space=parameters.space_shrink
- if charxheight then
- parameters.x_height=charxheight
- else
- local x=0x0078
- if x then
- local x=descriptions[x]
- if x then
- parameters.x_height=x.height
- end
- end
- end
- local fd=data.fontdimens
- if fd and fd[8] and fd[9] and fd[10] then
- for k,v in next,fd do
- parameters[k]=v
- end
- end
- parameters.designsize=(metadata.designsize or 10)*65536
- parameters.ascender=abs(metadata.ascender or 0)
- parameters.descender=abs(metadata.descender or 0)
- parameters.units=1000
- properties.spacer=spacer
- properties.encodingbytes=2
- properties.format=fonts.formats[filename] or "type1"
- properties.filename=filename
- properties.fontname=fontname
- properties.fullname=fullname
- properties.psname=fullname
- properties.name=filename or fullname or fontname
- if next(characters) then
- return {
- characters=characters,
- descriptions=descriptions,
- parameters=parameters,
- resources=resources,
- properties=properties,
- goodies=goodies,
- }
- end
- end
- return nil
-end
-function afm.setfeatures(tfmdata,features)
- local okay=constructors.initializefeatures("afm",tfmdata,features,trace_features,report_afm)
- if okay then
- return constructors.collectprocessors("afm",tfmdata,features,trace_features,report_afm)
- else
- return {}
- end
-end
-local function addtables(data)
- local resources=data.resources
- local lookuptags=resources.lookuptags
- local unicodes=resources.unicodes
- if not lookuptags then
- lookuptags={}
- resources.lookuptags=lookuptags
- end
- setmetatableindex(lookuptags,function(t,k)
- local v=type(k)=="number" and ("lookup "..k) or k
- t[k]=v
- return v
- end)
- if not unicodes then
- unicodes={}
- resources.unicodes=unicodes
- setmetatableindex(unicodes,function(t,k)
- setmetatableindex(unicodes,nil)
- for u,d in next,data.descriptions do
- local n=d.name
- if n then
- t[n]=u
- end
- end
- return rawget(t,k)
- end)
- end
- constructors.addcoreunicodes(unicodes)
-end
-local function afmtotfm(specification)
- local afmname=specification.filename or specification.name
- if specification.forced=="afm" or specification.format=="afm" then
- if trace_loading then
- report_afm("forcing afm format for %a",afmname)
- end
- else
- local tfmname=findbinfile(afmname,"ofm") or ""
- if tfmname~="" then
- if trace_loading then
- report_afm("fallback from afm to tfm for %a",afmname)
- end
- return
- end
- end
- if afmname~="" then
- local features=constructors.checkedfeatures("afm",specification.features.normal)
- specification.features.normal=features
- constructors.hashinstance(specification,true)
- specification=definers.resolve(specification)
- local cache_id=specification.hash
- local tfmdata=containers.read(constructors.cache,cache_id)
- if not tfmdata then
- local rawdata=afm.load(afmname)
- if rawdata and next(rawdata) then
- addtables(rawdata)
- adddimensions(rawdata)
- tfmdata=copytotfm(rawdata)
- if tfmdata and next(tfmdata) then
- local shared=tfmdata.shared
- if not shared then
- shared={}
- tfmdata.shared=shared
- end
- shared.rawdata=rawdata
- shared.features=features
- shared.processes=afm.setfeatures(tfmdata,features)
- end
- elseif trace_loading then
- report_afm("no (valid) afm file found with name %a",afmname)
- end
- tfmdata=containers.write(constructors.cache,cache_id,tfmdata)
- end
- return tfmdata
- end
-end
-local function read_from_afm(specification)
- local tfmdata=afmtotfm(specification)
- if tfmdata then
- tfmdata.properties.name=specification.name
- tfmdata=constructors.scale(tfmdata,specification)
- local allfeatures=tfmdata.shared.features or specification.features.normal
- constructors.applymanipulators("afm",tfmdata,allfeatures,trace_features,report_afm)
- fonts.loggers.register(tfmdata,'afm',specification)
- end
- return tfmdata
-end
-local function prepareligatures(tfmdata,ligatures,value)
- if value then
- local descriptions=tfmdata.descriptions
- local hasligatures=false
- for unicode,character in next,tfmdata.characters do
- local description=descriptions[unicode]
- local dligatures=description.ligatures
- if dligatures then
- local cligatures=character.ligatures
- if not cligatures then
- cligatures={}
- character.ligatures=cligatures
- end
- for unicode,ligature in next,dligatures do
- cligatures[unicode]={
- char=ligature,
- type=0
- }
- end
- hasligatures=true
- end
- end
- tfmdata.properties.hasligatures=hasligatures
- end
-end
-local function preparekerns(tfmdata,kerns,value)
- if value then
- local rawdata=tfmdata.shared.rawdata
- local resources=rawdata.resources
- local unicodes=resources.unicodes
- local descriptions=tfmdata.descriptions
- local haskerns=false
- for u,chr in next,tfmdata.characters do
- local d=descriptions[u]
- local newkerns=d[kerns]
- if newkerns then
- local kerns=chr.kerns
- if not kerns then
- kerns={}
- chr.kerns=kerns
- end
- for k,v in next,newkerns do
- local uk=unicodes[k]
- if uk then
- kerns[uk]=v
- end
- end
- haskerns=true
- end
- end
- tfmdata.properties.haskerns=haskerns
- end
-end
-local list={
- [0x0027]=0x2019,
-}
-local function texreplacements(tfmdata,value)
- local descriptions=tfmdata.descriptions
- local characters=tfmdata.characters
- for k,v in next,list do
- characters [k]=characters [v]
- descriptions[k]=descriptions[v]
- end
-end
-local function ligatures (tfmdata,value) prepareligatures(tfmdata,'ligatures',value) end
-local function texligatures(tfmdata,value) prepareligatures(tfmdata,'texligatures',value) end
-local function kerns (tfmdata,value) preparekerns (tfmdata,'kerns',value) end
-local function extrakerns (tfmdata,value) preparekerns (tfmdata,'extrakerns',value) end
-registerafmfeature {
- name="liga",
- description="traditional ligatures",
- initializers={
- base=ligatures,
- node=ligatures,
- }
-}
-registerafmfeature {
- name="kern",
- description="intercharacter kerning",
- initializers={
- base=kerns,
- node=kerns,
- }
-}
-registerafmfeature {
- name="extrakerns",
- description="additional intercharacter kerning",
- initializers={
- base=extrakerns,
- node=extrakerns,
- }
-}
-registerafmfeature {
- name='tlig',
- description='tex ligatures',
- initializers={
- base=texligatures,
- node=texligatures,
- }
-}
-registerafmfeature {
- name='trep',
- description='tex replacements',
- initializers={
- base=texreplacements,
- node=texreplacements,
- }
-}
-local check_tfm=readers.check_tfm
-fonts.formats.afm="type1"
-fonts.formats.pfb="type1"
-local function check_afm(specification,fullname)
- local foundname=findbinfile(fullname,'afm') or ""
- if foundname=="" then
- foundname=fonts.names.getfilename(fullname,"afm") or ""
- end
- if foundname=="" and afm.autoprefixed then
- local encoding,shortname=match(fullname,"^(.-)%-(.*)$")
- if encoding and shortname and fonts.encodings.known[encoding] then
- shortname=findbinfile(shortname,'afm') or ""
- if shortname~="" then
- foundname=shortname
- if trace_defining then
- report_afm("stripping encoding prefix from filename %a",afmname)
- end
- end
- end
- end
- if foundname~="" then
- specification.filename=foundname
- specification.format="afm"
- return read_from_afm(specification)
- end
-end
-function readers.afm(specification,method)
- local fullname,tfmdata=specification.filename or "",nil
- if fullname=="" then
- local forced=specification.forced or ""
- if forced~="" then
- tfmdata=check_afm(specification,specification.name.."."..forced)
- end
- if not tfmdata then
- method=method or definers.method or "afm or tfm"
- if method=="tfm" then
- tfmdata=check_tfm(specification,specification.name)
- elseif method=="afm" then
- tfmdata=check_afm(specification,specification.name)
- elseif method=="tfm or afm" then
- tfmdata=check_tfm(specification,specification.name) or check_afm(specification,specification.name)
- else
- tfmdata=check_afm(specification,specification.name) or check_tfm(specification,specification.name)
- end
- end
- else
- tfmdata=check_afm(specification,fullname)
- end
- return tfmdata
-end
-function readers.pfb(specification,method)
- local original=specification.specification
- if trace_defining then
- report_afm("using afm reader for %a",original)
- end
- specification.specification=gsub(original,"%.pfb",".afm")
- specification.forced="afm"
- return readers.afm(specification,method)
-end
-
-end -- closure
-
-do -- begin closure to overcome local limits and interference
-
-if not modules then modules={} end modules ['font-afk']={
- version=1.001,
- comment="companion to font-afm.lua",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files",
- dataonly=true,
-}
-local allocate=utilities.storage.allocate
-fonts.handlers.afm.helpdata={
- ligatures=allocate {
- ['f']={
- { 'f','ff' },
- { 'i','fi' },
- { 'l','fl' },
- },
- ['ff']={
- { 'i','ffi' }
- },
- ['fi']={
- { 'i','fii' }
- },
- ['fl']={
- { 'i','fli' }
- },
- ['s']={
- { 't','st' }
- },
- ['i']={
- { 'j','ij' }
- },
- },
- texligatures=allocate {
- ['quoteleft']={
- { 'quoteleft','quotedblleft' }
- },
- ['quoteright']={
- { 'quoteright','quotedblright' }
- },
- ['hyphen']={
- { 'hyphen','endash' }
- },
- ['endash']={
- { 'hyphen','emdash' }
- }
- },
- leftkerned=allocate {
- AEligature="A",aeligature="a",
- OEligature="O",oeligature="o",
- IJligature="I",ijligature="i",
- AE="A",ae="a",
- OE="O",oe="o",
- IJ="I",ij="i",
- Ssharp="S",ssharp="s",
- },
- rightkerned=allocate {
- AEligature="E",aeligature="e",
- OEligature="E",oeligature="e",
- IJligature="J",ijligature="j",
- AE="E",ae="e",
- OE="E",oe="e",
- IJ="J",ij="j",
- Ssharp="S",ssharp="s",
- },
- bothkerned=allocate {
- Acircumflex="A",acircumflex="a",
- Ccircumflex="C",ccircumflex="c",
- Ecircumflex="E",ecircumflex="e",
- Gcircumflex="G",gcircumflex="g",
- Hcircumflex="H",hcircumflex="h",
- Icircumflex="I",icircumflex="i",
- Jcircumflex="J",jcircumflex="j",
- Ocircumflex="O",ocircumflex="o",
- Scircumflex="S",scircumflex="s",
- Ucircumflex="U",ucircumflex="u",
- Wcircumflex="W",wcircumflex="w",
- Ycircumflex="Y",ycircumflex="y",
- Agrave="A",agrave="a",
- Egrave="E",egrave="e",
- Igrave="I",igrave="i",
- Ograve="O",ograve="o",
- Ugrave="U",ugrave="u",
- Ygrave="Y",ygrave="y",
- Atilde="A",atilde="a",
- Itilde="I",itilde="i",
- Otilde="O",otilde="o",
- Utilde="U",utilde="u",
- Ntilde="N",ntilde="n",
- Adiaeresis="A",adiaeresis="a",Adieresis="A",adieresis="a",
- Ediaeresis="E",ediaeresis="e",Edieresis="E",edieresis="e",
- Idiaeresis="I",idiaeresis="i",Idieresis="I",idieresis="i",
- Odiaeresis="O",odiaeresis="o",Odieresis="O",odieresis="o",
- Udiaeresis="U",udiaeresis="u",Udieresis="U",udieresis="u",
- Ydiaeresis="Y",ydiaeresis="y",Ydieresis="Y",ydieresis="y",
- Aacute="A",aacute="a",
- Cacute="C",cacute="c",
- Eacute="E",eacute="e",
- Iacute="I",iacute="i",
- Lacute="L",lacute="l",
- Nacute="N",nacute="n",
- Oacute="O",oacute="o",
- Racute="R",racute="r",
- Sacute="S",sacute="s",
- Uacute="U",uacute="u",
- Yacute="Y",yacute="y",
- Zacute="Z",zacute="z",
- Dstroke="D",dstroke="d",
- Hstroke="H",hstroke="h",
- Tstroke="T",tstroke="t",
- Cdotaccent="C",cdotaccent="c",
- Edotaccent="E",edotaccent="e",
- Gdotaccent="G",gdotaccent="g",
- Idotaccent="I",idotaccent="i",
- Zdotaccent="Z",zdotaccent="z",
- Amacron="A",amacron="a",
- Emacron="E",emacron="e",
- Imacron="I",imacron="i",
- Omacron="O",omacron="o",
- Umacron="U",umacron="u",
- Ccedilla="C",ccedilla="c",
- Kcedilla="K",kcedilla="k",
- Lcedilla="L",lcedilla="l",
- Ncedilla="N",ncedilla="n",
- Rcedilla="R",rcedilla="r",
- Scedilla="S",scedilla="s",
- Tcedilla="T",tcedilla="t",
- Ohungarumlaut="O",ohungarumlaut="o",
- Uhungarumlaut="U",uhungarumlaut="u",
- Aogonek="A",aogonek="a",
- Eogonek="E",eogonek="e",
- Iogonek="I",iogonek="i",
- Uogonek="U",uogonek="u",
- Aring="A",aring="a",
- Uring="U",uring="u",
- Abreve="A",abreve="a",
- Ebreve="E",ebreve="e",
- Gbreve="G",gbreve="g",
- Ibreve="I",ibreve="i",
- Obreve="O",obreve="o",
- Ubreve="U",ubreve="u",
- Ccaron="C",ccaron="c",
- Dcaron="D",dcaron="d",
- Ecaron="E",ecaron="e",
- Lcaron="L",lcaron="l",
- Ncaron="N",ncaron="n",
- Rcaron="R",rcaron="r",
- Scaron="S",scaron="s",
- Tcaron="T",tcaron="t",
- Zcaron="Z",zcaron="z",
- dotlessI="I",dotlessi="i",
- dotlessJ="J",dotlessj="j",
- AEligature="AE",aeligature="ae",AE="AE",ae="ae",
- OEligature="OE",oeligature="oe",OE="OE",oe="oe",
- IJligature="IJ",ijligature="ij",IJ="IJ",ij="ij",
- Lstroke="L",lstroke="l",Lslash="L",lslash="l",
- Ostroke="O",ostroke="o",Oslash="O",oslash="o",
- Ssharp="SS",ssharp="ss",
- Aumlaut="A",aumlaut="a",
- Eumlaut="E",eumlaut="e",
- Iumlaut="I",iumlaut="i",
- Oumlaut="O",oumlaut="o",
- Uumlaut="U",uumlaut="u",
- }
-}
-
-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",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
-}
-local lower=string.lower
-local fonts=fonts
-local constructors=fonts.constructors
-local otf=constructors.newhandler("otf")
-local otffeatures=constructors.newfeatures("otf")
-local registerotffeature=otffeatures.register
-local otftables=otf.tables or {}
-otf.tables=otftables
-local allocate=utilities.storage.allocate
-registerotffeature {
- name="features",
- description="initialization of feature handler",
- default=true,
-}
-local function setmode(tfmdata,value)
- if value then
- tfmdata.properties.mode=lower(value)
- end
-end
-local function setlanguage(tfmdata,value)
- if value then
- local cleanvalue=lower(value)
- local languages=otftables and otftables.languages
- local properties=tfmdata.properties
- if not languages then
- properties.language=cleanvalue
- elseif languages[value] then
- properties.language=cleanvalue
- else
- properties.language="dflt"
- end
- end
-end
-local function setscript(tfmdata,value)
- if value then
- local cleanvalue=lower(value)
- local scripts=otftables and otftables.scripts
- local properties=tfmdata.properties
- if not scripts then
- properties.script=cleanvalue
- elseif scripts[value] then
- properties.script=cleanvalue
- else
- properties.script="dflt"
- end
- end
-end
-registerotffeature {
- name="mode",
- description="mode",
- initializers={
- base=setmode,
- node=setmode,
- }
-}
-registerotffeature {
- name="language",
- description="language",
- initializers={
- base=setlanguage,
- node=setlanguage,
- }
-}
-registerotffeature {
- name="script",
- description="script",
- initializers={
- base=setscript,
- node=setscript,
- }
-}
-otftables.featuretypes=allocate {
- gpos_single="position",
- gpos_pair="position",
- gpos_cursive="position",
- gpos_mark2base="position",
- gpos_mark2ligature="position",
- gpos_mark2mark="position",
- gpos_context="position",
- gpos_contextchain="position",
- gsub_single="substitution",
- gsub_multiple="substitution",
- gsub_alternate="substitution",
- gsub_ligature="substitution",
- gsub_context="substitution",
- gsub_contextchain="substitution",
- gsub_reversecontextchain="substitution",
- gsub_reversesub="substitution",
-}
-function otffeatures.checkeddefaultscript(featuretype,autoscript,scripts)
- if featuretype=="position" then
- local default=scripts.dflt
- if default then
- if autoscript=="position" or autoscript==true then
- return default
- else
- report_otf("script feature %s not applied, enable default positioning")
- end
- else
- end
- elseif featuretype=="substitution" then
- local default=scripts.dflt
- if default then
- if autoscript=="substitution" or autoscript==true then
- return default
- end
- end
- end
-end
-function otffeatures.checkeddefaultlanguage(featuretype,autolanguage,languages)
- if featuretype=="position" then
- local default=languages.dflt
- if default then
- if autolanguage=="position" or autolanguage==true then
- return default
- else
- report_otf("language feature %s not applied, enable default positioning")
- end
- else
- end
- elseif featuretype=="substitution" then
- local default=languages.dflt
- if default then
- if autolanguage=="substitution" or autolanguage==true then
- return default
+ elseif featuretype=="substitution" then
+ local default=languages.dflt
+ if default then
+ if autolanguage=="substitution" or autolanguage==true then
+ return default
end
end
end
@@ -15827,7 +14696,6 @@ function otf.load(filename,sub,featurefile)
otfreaders.expand(data)
otfreaders.addunicodetable(data)
enhancers.apply(data,filename,data)
- constructors.addcoreunicodes(unicodes)
if applyruntimefixes then
applyruntimefixes(filename,data)
end
@@ -16658,6 +15526,7 @@ registerotffeature {
base=featuresinitializer,
}
}
+otf.basemodeinitializer=featuresinitializer
end -- closure
@@ -17713,11 +16582,11 @@ local function inject_everything(head,where)
insert_node_after(pre,n,newkern(rightkern))
done=true
end
- end
- if hasmarks then
- local pm=i.markbasenode
- if pm then
- processmark(pm,current,i)
+ if hasmarks then
+ local pm=i.markbasenode
+ if pm then
+ processmark(pm,current,i)
+ end
end
end
end
@@ -17743,11 +16612,11 @@ local function inject_everything(head,where)
insert_node_after(post,n,newkern(rightkern))
done=true
end
- end
- if hasmarks then
- local pm=i.markbasenode
- if pm then
- processmark(pm,current,i)
+ if hasmarks then
+ local pm=i.markbasenode
+ if pm then
+ processmark(pm,current,i)
+ end
end
end
end
@@ -17773,11 +16642,11 @@ local function inject_everything(head,where)
insert_node_after(replace,n,newkern(rightkern))
done=true
end
- end
- if hasmarks then
- local pm=i.markbasenode
- if pm then
- processmark(pm,current,i)
+ if hasmarks then
+ local pm=i.markbasenode
+ if pm then
+ processmark(pm,current,i)
+ end
end
end
end
@@ -21284,6 +20153,8 @@ registerotffeature {
node=featuresprocessor,
}
}
+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)
@@ -21826,1556 +20697,2710 @@ local function initializedevanagi(tfmdata)
end
end
end
- if valid[kind] then
- for i=1,nofsteps do
- local step=steps[i]
- local coverage=step.coverage
- if coverage then
- local reph=false
- if step.osdstep then
- for k,v in next,ra do
- local r=coverage[k]
- if r then
- local h=false
- for k,v in next,halant do
- local h=r[k]
- if h then
- reph=h.ligature or false
- break
- end
- end
- if reph then
- break
- end
- end
- end
- else
- end
- seqsubset[#seqsubset+1]={ kind,coverage,reph }
- end
+ if valid[kind] then
+ for i=1,nofsteps do
+ local step=steps[i]
+ local coverage=step.coverage
+ if coverage then
+ local reph=false
+ if step.osdstep then
+ for k,v in next,ra do
+ local r=coverage[k]
+ if r then
+ local h=false
+ for k,v in next,halant do
+ local h=r[k]
+ if h then
+ reph=h.ligature or false
+ break
+ end
+ end
+ if reph then
+ break
+ end
+ end
+ end
+ else
+ end
+ seqsubset[#seqsubset+1]={ kind,coverage,reph }
+ end
+ end
+ end
+ if kind=="pref" then
+ local sequence=dataset[3]
+ local steps=sequence.steps
+ local nofsteps=sequence.nofsteps
+ for i=1,nofsteps do
+ local step=steps[i]
+ local coverage=step.coverage
+ if coverage then
+ for k,v in next,halant do
+ local h=coverage[k]
+ if h then
+ local found=false
+ for k,v in next,h do
+ found=v and v.ligature
+ if found then
+ pre_base_reordering_consonants[k]=found
+ break
+ end
+ end
+ if found then
+ break
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ if script=="deva" then
+ sharedfeatures["dv04"]=true
+ elseif script=="dev2" then
+ sharedfeatures["dv01"]=true
+ sharedfeatures["dv02"]=true
+ sharedfeatures["dv03"]=true
+ sharedfeatures["dv04"]=true
+ elseif script=="mlym" then
+ sharedfeatures["pstf"]=true
+ elseif script=="mlm2" then
+ sharedfeatures["pstf"]=true
+ sharedfeatures["pref"]=true
+ sharedfeatures["dv03"]=true
+ gsubfeatures ["dv03"]=dev2_defaults
+ insert(sequences,insertindex,sequence_reorder_pre_base_reordering_consonants)
+ end
+ end
+ end
+end
+registerotffeature {
+ name="devanagari",
+ description="inject additional features",
+ default=true,
+ initializers={
+ node=initializedevanagi,
+ },
+}
+local function deva_initialize(font,attr)
+ local tfmdata=fontdata[font]
+ local datasets=otf.dataset(tfmdata,font,attr)
+ local devanagaridata=datasets.devanagari
+ if not devanagaridata then
+ devanagaridata={
+ reph=false,
+ vattu=false,
+ blwfcache={},
+ }
+ datasets.devanagari=devanagaridata
+ local resources=tfmdata.resources
+ local devanagari=resources.devanagari
+ for s=1,#datasets do
+ local dataset=datasets[s]
+ if dataset and dataset[1] then
+ local kind=dataset[4]
+ if kind=="rphf" then
+ devanagaridata.reph=true
+ elseif kind=="blwf" then
+ devanagaridata.vattu=true
+ devanagaridata.blwfcache=devanagari.blwfcache
+ end
+ end
+ end
+ end
+ return devanagaridata.reph,devanagaridata.vattu,devanagaridata.blwfcache
+end
+local function deva_reorder(head,start,stop,font,attr,nbspaces)
+ local reph,vattu,blwfcache=deva_initialize(font,attr)
+ local current=start
+ local n=getnext(start)
+ local base=nil
+ local firstcons=nil
+ local lastcons=nil
+ local basefound=false
+ if reph and ra[getchar(start)] and halant[getchar(n)] then
+ if n==stop then
+ return head,stop,nbspaces
+ end
+ if getchar(getnext(n))==c_zwj then
+ current=start
+ else
+ current=getnext(n)
+ setprop(start,a_state,s_rphf)
+ end
+ end
+ if getchar(current)==c_nbsp then
+ if current==stop then
+ stop=getprev(stop)
+ head=remove_node(head,current)
+ free_node(current)
+ return head,stop,nbspaces
+ else
+ nbspaces=nbspaces+1
+ base=current
+ firstcons=current
+ lastcons=current
+ current=getnext(current)
+ if current~=stop then
+ if nukta[getchar(current)] then
+ current=getnext(current)
+ end
+ if getchar(current)==c_zwj then
+ if current~=stop then
+ local next=getnext(current)
+ if next~=stop and halant[getchar(next)] then
+ current=next
+ next=getnext(current)
+ local tmp=next and getnext(next) or nil
+ local changestop=next==stop
+ local tempcurrent=copy_node(next)
+ copyinjection(tempcurrent,next)
+ local nextcurrent=copy_node(current)
+ copyinjection(nextcurrent,current)
+ setlink(tempcurrent,nextcurrent)
+ setprop(tempcurrent,a_state,s_blwf)
+ tempcurrent=processcharacters(tempcurrent,font)
+ setprop(tempcurrent,a_state,unsetvalue)
+ if getchar(next)==getchar(tempcurrent) then
+ flush_list(tempcurrent)
+ local n=copy_node(current)
+ copyinjection(n,current)
+ setchar(current,dotted_circle)
+ head=insert_node_after(head,current,n)
+ else
+ setchar(current,getchar(tempcurrent))
+ local freenode=getnext(current)
+ setlink(current,tmp)
+ free_node(freenode)
+ flush_list(tempcurrent)
+ if changestop then
+ stop=current
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ while not basefound do
+ local char=getchar(current)
+ if consonant[char] then
+ setprop(current,a_state,s_half)
+ if not firstcons then
+ firstcons=current
+ end
+ lastcons=current
+ if not base then
+ base=current
+ elseif blwfcache[char] then
+ setprop(current,a_state,s_blwf)
+ else
+ base=current
+ end
+ end
+ basefound=current==stop
+ current=getnext(current)
+ end
+ if base~=lastcons then
+ local np=base
+ local n=getnext(base)
+ local ch=getchar(n)
+ if nukta[ch] then
+ np=n
+ n=getnext(n)
+ ch=getchar(n)
+ end
+ if halant[ch] then
+ if lastcons~=stop then
+ local ln=getnext(lastcons)
+ if nukta[getchar(ln)] then
+ lastcons=ln
+ end
+ end
+ local nn=getnext(n)
+ local ln=getnext(lastcons)
+ setlink(np,nn)
+ setnext(lastcons,n)
+ if ln then
+ setprev(ln,n)
+ end
+ setnext(n,ln)
+ setprev(n,lastcons)
+ if lastcons==stop then
+ stop=n
+ end
+ end
+ end
+ n=getnext(start)
+ if n~=stop and ra[getchar(start)] and halant[getchar(n)] and not zw_char[getchar(getnext(n))] then
+ local matra=base
+ if base~=stop then
+ local next=getnext(base)
+ if dependent_vowel[getchar(next)] then
+ matra=next
+ end
+ end
+ local sp=getprev(start)
+ local nn=getnext(n)
+ local mn=getnext(matra)
+ setlink(sp,nn)
+ setlink(matra,start)
+ setlink(n,mn)
+ if head==start then
+ head=nn
+ end
+ start=nn
+ if matra==stop then
+ stop=n
+ end
+ end
+ local current=start
+ while current~=stop do
+ local next=getnext(current)
+ if next~=stop and halant[getchar(next)] and getchar(getnext(next))==c_zwnj then
+ setprop(current,a_state,unsetvalue)
+ end
+ current=next
+ end
+ if base~=stop and getprop(base,a_state) then
+ local next=getnext(base)
+ if halant[getchar(next)] and not (next~=stop and getchar(getnext(next))==c_zwj) then
+ setprop(base,a_state,unsetvalue)
+ end
+ end
+ local current,allreordered,moved=start,false,{ [base]=true }
+ local a,b,p,bn=base,base,base,getnext(base)
+ if base~=stop and nukta[getchar(bn)] then
+ a,b,p=bn,bn,bn
+ end
+ while not allreordered do
+ local c=current
+ local n=getnext(current)
+ local l=nil
+ if c~=stop then
+ local ch=getchar(n)
+ if nukta[ch] then
+ c=n
+ n=getnext(n)
+ ch=getchar(n)
+ end
+ if c~=stop then
+ if halant[ch] then
+ c=n
+ n=getnext(n)
+ ch=getchar(n)
+ end
+ while c~=stop and dependent_vowel[ch] do
+ c=n
+ n=getnext(n)
+ ch=getchar(n)
+ end
+ if c~=stop then
+ if vowel_modifier[ch] then
+ c=n
+ n=getnext(n)
+ ch=getchar(n)
+ end
+ if c~=stop and stress_tone_mark[ch] then
+ c=n
+ n=getnext(n)
end
end
- if kind=="pref" then
- local sequence=dataset[3]
- local steps=sequence.steps
- local nofsteps=sequence.nofsteps
- for i=1,nofsteps do
- local step=steps[i]
- local coverage=step.coverage
- if coverage then
- for k,v in next,halant do
- local h=coverage[k]
- if h then
- local found=false
- for k,v in next,h do
- found=v and v.ligature
- if found then
- pre_base_reordering_consonants[k]=found
- break
- end
- end
- if found then
- break
- end
- end
+ end
+ end
+ local bp=getprev(firstcons)
+ local cn=getnext(current)
+ local last=getnext(c)
+ while cn~=last do
+ if pre_mark[getchar(cn)] then
+ if bp then
+ setnext(bp,cn)
+ end
+ local prev,next=getboth(cn)
+ if next then
+ setprev(next,prev)
+ end
+ setnext(prev,next)
+ if cn==stop then
+ stop=prev
+ end
+ setprev(cn,bp)
+ setlink(cn,firstcons)
+ if firstcons==start then
+ if head==start then
+ head=cn
+ end
+ start=cn
+ end
+ break
+ end
+ cn=getnext(cn)
+ end
+ allreordered=c==stop
+ current=getnext(c)
+ end
+ if reph or vattu then
+ local current,cns=start,nil
+ while current~=stop do
+ local c=current
+ local n=getnext(current)
+ if ra[getchar(current)] and halant[getchar(n)] then
+ c=n
+ n=getnext(n)
+ local b,bn=base,base
+ while bn~=stop do
+ local next=getnext(bn)
+ if dependent_vowel[getchar(next)] then
+ b=next
+ end
+ bn=next
+ end
+ if getprop(current,a_state)==s_rphf then
+ if b~=current then
+ if current==start then
+ if head==start then
+ head=n
end
+ start=n
+ end
+ if b==stop then
+ stop=c
end
+ local prev=getprev(current)
+ setlink(prev,n)
+ local next=getnext(b)
+ setlink(c,next)
+ setlink(b,current)
+ end
+ elseif cns and getnext(cns)~=current then
+ local cp=getprev(current)
+ local cnsn=getnext(cns)
+ setlink(cp,n)
+ setlink(cns,current)
+ setlink(c,cnsn)
+ if c==stop then
+ stop=cp
+ break
+ end
+ current=getprev(n)
+ end
+ else
+ local char=getchar(current)
+ if consonant[char] then
+ cns=current
+ local next=getnext(cns)
+ if halant[getchar(next)] then
+ cns=next
+ end
+ elseif char==c_nbsp then
+ nbspaces=nbspaces+1
+ cns=current
+ local next=getnext(cns)
+ if halant[getchar(next)] then
+ cns=next
end
end
end
- if script=="deva" then
- sharedfeatures["dv04"]=true
- elseif script=="dev2" then
- sharedfeatures["dv01"]=true
- sharedfeatures["dv02"]=true
- sharedfeatures["dv03"]=true
- sharedfeatures["dv04"]=true
- elseif script=="mlym" then
- sharedfeatures["pstf"]=true
- elseif script=="mlm2" then
- sharedfeatures["pstf"]=true
- sharedfeatures["pref"]=true
- sharedfeatures["dv03"]=true
- gsubfeatures ["dv03"]=dev2_defaults
- insert(sequences,insertindex,sequence_reorder_pre_base_reordering_consonants)
- end
+ current=getnext(current)
end
end
+ if getchar(base)==c_nbsp then
+ nbspaces=nbspaces-1
+ head=remove_node(head,base)
+ free_node(base)
+ end
+ return head,stop,nbspaces
end
-registerotffeature {
- name="devanagari",
- description="inject additional features",
- default=true,
- initializers={
- node=initializedevanagi,
- },
-}
-local function deva_initialize(font,attr)
- local tfmdata=fontdata[font]
- local datasets=otf.dataset(tfmdata,font,attr)
- local devanagaridata=datasets.devanagari
- if not devanagaridata then
- devanagaridata={
- reph=false,
- vattu=false,
- blwfcache={},
- }
- datasets.devanagari=devanagaridata
- local resources=tfmdata.resources
- local devanagari=resources.devanagari
- for s=1,#datasets do
- local dataset=datasets[s]
- if dataset and dataset[1] then
- local kind=dataset[4]
- if kind=="rphf" then
- devanagaridata.reph=true
- elseif kind=="blwf" then
- devanagaridata.vattu=true
- devanagaridata.blwfcache=devanagari.blwfcache
+function handlers.devanagari_reorder_matras(head,start)
+ local current=start
+ local startfont=getfont(start)
+ local startattr=getprop(start,a_syllabe)
+ while current do
+ local char=ischar(current,startfont)
+ local next=getnext(current)
+ if char and getprop(current,a_syllabe)==startattr then
+ if halant[char] and not getprop(current,a_state) then
+ if next then
+ local char=ischar(next,startfont)
+ if char and zw_char[char] and getprop(next,a_syllabe)==startattr then
+ current=next
+ next=getnext(current)
+ end
end
+ local startnext=getnext(start)
+ head=remove_node(head,start)
+ setlink(start,next)
+ setlink(current,start)
+ start=startnext
+ break
end
end
+ current=next
end
- return devanagaridata.reph,devanagaridata.vattu,devanagaridata.blwfcache
+ return head,start,true
end
-local function deva_reorder(head,start,stop,font,attr,nbspaces)
- local reph,vattu,blwfcache=deva_initialize(font,attr)
- local current=start
- local n=getnext(start)
- local base=nil
- local firstcons=nil
- local lastcons=nil
- local basefound=false
- if reph and ra[getchar(start)] and halant[getchar(n)] then
- if n==stop then
- return head,stop,nbspaces
- end
- if getchar(getnext(n))==c_zwj then
- current=start
+function handlers.devanagari_reorder_reph(head,start)
+ local current=getnext(start)
+ local startnext=nil
+ local startprev=nil
+ local startfont=getfont(start)
+ local startattr=getprop(start,a_syllabe)
+ while current do
+ local char=ischar(current,font)
+ if char and getprop(current,a_syllabe)==startattr then
+ if halant[char] and not getprop(current,a_state) then
+ local next=getnext(current)
+ if next then
+ local nextchar=ischar(next,font)
+ if nextchar and zw_char[nextchar] and getprop(next,a_syllabe)==startattr then
+ current=next
+ next=getnext(current)
+ end
+ end
+ startnext=getnext(start)
+ head=remove_node(head,start)
+ setlink(start,next)
+ setlink(current,start)
+ start=startnext
+ startattr=getprop(start,a_syllabe)
+ break
+ end
+ current=getnext(current)
else
- current=getnext(n)
- setprop(start,a_state,s_rphf)
+ break
end
end
- if getchar(current)==c_nbsp then
- if current==stop then
- stop=getprev(stop)
- head=remove_node(head,current)
- free_node(current)
- return head,stop,nbspaces
- else
- nbspaces=nbspaces+1
- base=current
- firstcons=current
- lastcons=current
- current=getnext(current)
- if current~=stop then
- if nukta[getchar(current)] then
- current=getnext(current)
+ if not startnext then
+ current=getnext(start)
+ while current do
+ local char=ischar(current,font)
+ if char and getprop(current,a_syllabe)==startattr then
+ if getprop(current,a_state)==s_pstf then
+ startnext=getnext(start)
+ head=remove_node(head,start)
+ local prev=getprev(current)
+ setlink(prev,start)
+ setlink(start,current)
+ start=startnext
+ startattr=getprop(start,a_syllabe)
+ break
end
- if getchar(current)==c_zwj then
- if current~=stop then
- local next=getnext(current)
- if next~=stop and halant[getchar(next)] then
- current=next
- next=getnext(current)
- local tmp=next and getnext(next) or nil
- local changestop=next==stop
- local tempcurrent=copy_node(next)
- copyinjection(tempcurrent,next)
- local nextcurrent=copy_node(current)
- copyinjection(nextcurrent,current)
- setlink(tempcurrent,nextcurrent)
- setprop(tempcurrent,a_state,s_blwf)
- tempcurrent=processcharacters(tempcurrent,font)
- setprop(tempcurrent,a_state,unsetvalue)
- if getchar(next)==getchar(tempcurrent) then
- flush_list(tempcurrent)
- local n=copy_node(current)
- copyinjection(n,current)
- setchar(current,dotted_circle)
- head=insert_node_after(head,current,n)
- else
- setchar(current,getchar(tempcurrent))
- local freenode=getnext(current)
- setlink(current,tmp)
- free_node(freenode)
- flush_list(tempcurrent)
- if changestop then
- stop=current
- end
- end
+ current=getnext(current)
+ else
+ break
+ end
+ end
+ end
+ if not startnext then
+ current=getnext(start)
+ local c=nil
+ while current do
+ local char=ischar(current,font)
+ if char and getprop(current,a_syllabe)==startattr then
+ if not c and mark_above_below_post[char] and reorder_class[char]~="after subscript" then
+ c=current
+ end
+ current=getnext(current)
+ else
+ break
+ end
+ end
+ if c then
+ startnext=getnext(start)
+ head=remove_node(head,start)
+ local prev=getprev(c)
+ setlink(prev,start)
+ setlink(start,c)
+ start=startnext
+ startattr=getprop(start,a_syllabe)
+ end
+ end
+ if not startnext then
+ current=start
+ local next=getnext(current)
+ while next do
+ local nextchar=ischar(next,font)
+ if nextchar and getprop(next,a_syllabe)==startattr then
+ current=next
+ next=getnext(current)
+ else
+ break
+ end
+ end
+ if start~=current then
+ startnext=getnext(start)
+ head=remove_node(head,start)
+ local next=getnext(current)
+ setlink(start,next)
+ setlink(current,"next",start)
+ start=startnext
+ end
+ end
+ return head,start,true
+end
+function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start)
+ local current=start
+ local startnext=nil
+ local startprev=nil
+ local startfont=getfont(start)
+ local startattr=getprop(start,a_syllabe)
+ while current do
+ local char=ischar(current,font)
+ if char and getprop(current,a_syllabe)==startattr then
+ local next=getnext(current)
+ if halant[char] and not getprop(current,a_state) then
+ if next then
+ local nextchar=ischar(next,font)
+ if nextchar and getprop(next,a_syllabe)==startattr then
+ if nextchar==c_zwnj or nextchar==c_zwj then
+ current=next
+ next=getnext(current)
end
end
end
+ startnext=getnext(start)
+ removenode(start,start)
+ setlink(start,next)
+ setlink(current,start)
+ start=startnext
+ break
end
+ current=next
+ else
+ break
end
end
- while not basefound do
- local char=getchar(current)
- if consonant[char] then
- setprop(current,a_state,s_half)
- if not firstcons then
- firstcons=current
- end
- lastcons=current
- if not base then
- base=current
- elseif blwfcache[char] then
- setprop(current,a_state,s_blwf)
- else
- base=current
- end
- end
- basefound=current==stop
- current=getnext(current)
- end
- if base~=lastcons then
- local np=base
- local n=getnext(base)
- local ch=getchar(n)
- if nukta[ch] then
- np=n
- n=getnext(n)
- ch=getchar(n)
- end
- if halant[ch] then
- if lastcons~=stop then
- local ln=getnext(lastcons)
- if nukta[getchar(ln)] then
- lastcons=ln
+ if not startnext then
+ current=getnext(start)
+ startattr=getprop(start,a_syllabe)
+ while current do
+ local char=ischar(current,font)
+ if char and getprop(current,a_syllabe)==startattr then
+ if not consonant[char] and getprop(current,a_state) then
+ startnext=getnext(start)
+ removenode(start,start)
+ local prev=getprev(current)
+ setlink(start,prev)
+ setlink(start,current)
+ start=startnext
+ break
end
- end
- local nn=getnext(n)
- local ln=getnext(lastcons)
- setlink(np,nn)
- setnext(lastcons,n)
- if ln then
- setprev(ln,n)
- end
- setnext(n,ln)
- setprev(n,lastcons)
- if lastcons==stop then
- stop=n
+ current=getnext(current)
+ else
+ break
end
end
end
- n=getnext(start)
- if n~=stop and ra[getchar(start)] and halant[getchar(n)] and not zw_char[getchar(getnext(n))] then
- local matra=base
- if base~=stop then
- local next=getnext(base)
- if dependent_vowel[getchar(next)] then
- matra=next
- end
- end
- local sp=getprev(start)
- local nn=getnext(n)
- local mn=getnext(matra)
- setlink(sp,nn)
- setlink(matra,start)
- setlink(n,mn)
- if head==start then
- head=nn
- end
- start=nn
- if matra==stop then
- stop=n
+ return head,start,true
+end
+function handlers.devanagari_remove_joiners(head,start,kind,lookupname,replacement)
+ local stop=getnext(start)
+ local font=getfont(start)
+ local last=start
+ while stop do
+ local char=ischar(stop,font)
+ if char and (char==c_zwnj or char==c_zwj) then
+ last=stop
+ stop=getnext(stop)
+ else
+ break
end
end
- local current=start
- while current~=stop do
- local next=getnext(current)
- if next~=stop and halant[getchar(next)] and getchar(getnext(next))==c_zwnj then
- setprop(current,a_state,unsetvalue)
- end
- current=next
+ local prev=getprev(start)
+ if stop then
+ setnext(last)
+ setlink(prev,stop)
+ elseif prev then
+ setnext(prev)
end
- if base~=stop and getprop(base,a_state) then
- local next=getnext(base)
- if halant[getchar(next)] and not (next~=stop and getchar(getnext(next))==c_zwj) then
- setprop(base,a_state,unsetvalue)
- end
+ if head==start then
+ head=stop
end
- local current,allreordered,moved=start,false,{ [base]=true }
- local a,b,p,bn=base,base,base,getnext(base)
- if base~=stop and nukta[getchar(bn)] then
- a,b,p=bn,bn,bn
+ flush_list(start)
+ return head,stop,true
+end
+local function dev2_initialize(font,attr)
+ local devanagari=fontdata[font].resources.devanagari
+ if devanagari then
+ return devanagari.seqsubset or {},devanagari.reorderreph or {}
+ else
+ return {},{}
end
- while not allreordered do
- local c=current
- local n=getnext(current)
- local l=nil
- if c~=stop then
- local ch=getchar(n)
- if nukta[ch] then
- c=n
- n=getnext(n)
- ch=getchar(n)
- end
- if c~=stop then
- if halant[ch] then
- c=n
- n=getnext(n)
- ch=getchar(n)
+end
+local function dev2_reorder(head,start,stop,font,attr,nbspaces)
+ local seqsubset,reorderreph=dev2_initialize(font,attr)
+ local reph=false
+ local halfpos=nil
+ local basepos=nil
+ local subpos=nil
+ local postpos=nil
+ local locl={}
+ for i=1,#seqsubset do
+ local subset=seqsubset[i]
+ local kind=subset[1]
+ local lookupcache=subset[2]
+ if kind=="rphf" then
+ for k,v in next,ra do
+ local r=lookupcache[k]
+ if r then
+ for k,v in next,halant do
+ local h=r[k]
+ if h then
+ reph=h.ligature or false
+ break
+ end
+ end
+ if reph then
+ break
+ end
end
- while c~=stop and dependent_vowel[ch] do
- c=n
- n=getnext(n)
- ch=getchar(n)
+ end
+ local current=start
+ local last=getnext(stop)
+ while current~=last do
+ if current~=stop then
+ local c=locl[current] or getchar(current)
+ local found=lookupcache[c]
+ if found then
+ local next=getnext(current)
+ local n=locl[next] or getchar(next)
+ if found[n] then
+ local afternext=next~=stop and getnext(next)
+ if afternext and zw_char[getchar(afternext)] then
+ current=next
+ current=getnext(current)
+ elseif current==start then
+ setprop(current,a_state,s_rphf)
+ current=next
+ else
+ current=next
+ end
+ end
+ end
end
- if c~=stop then
- if vowel_modifier[ch] then
- c=n
- n=getnext(n)
- ch=getchar(n)
+ current=getnext(current)
+ end
+ elseif kind=="pref" then
+ local current=start
+ local last=getnext(stop)
+ while current~=last do
+ if current~=stop then
+ local c=locl[current] or getchar(current)
+ local found=lookupcache[c]
+ if found then
+ local next=getnext(current)
+ local n=locl[next] or getchar(next)
+ if found[n] then
+ setprop(current,a_state,s_pref)
+ setprop(next,a_state,s_pref)
+ current=next
+ end
end
- if c~=stop and stress_tone_mark[ch] then
- c=n
- n=getnext(n)
+ end
+ current=getnext(current)
+ end
+ elseif kind=="half" then
+ local current=start
+ local last=getnext(stop)
+ while current~=last do
+ if current~=stop then
+ local c=locl[current] or getchar(current)
+ local found=lookupcache[c]
+ if found then
+ local next=getnext(current)
+ local n=locl[next] or getchar(next)
+ if found[n] then
+ if next~=stop and getchar(getnext(next))==c_zwnj then
+ current=next
+ else
+ setprop(current,a_state,s_half)
+ if not halfpos then
+ halfpos=current
+ end
+ end
+ current=getnext(current)
+ end
end
end
+ current=getnext(current)
end
- end
- local bp=getprev(firstcons)
- local cn=getnext(current)
- local last=getnext(c)
- while cn~=last do
- if pre_mark[getchar(cn)] then
- if bp then
- setnext(bp,cn)
- end
- local prev,next=getboth(cn)
- if next then
- setprev(next,prev)
- end
- setnext(prev,next)
- if cn==stop then
- stop=prev
+ elseif kind=="blwf" then
+ local current=start
+ local last=getnext(stop)
+ while current~=last do
+ if current~=stop then
+ local c=locl[current] or getchar(current)
+ local found=lookupcache[c]
+ if found then
+ local next=getnext(current)
+ local n=locl[next] or getchar(next)
+ if found[n] then
+ setprop(current,a_state,s_blwf)
+ setprop(next,a_state,s_blwf)
+ current=next
+ subpos=current
+ end
+ end
end
- setprev(cn,bp)
- setlink(cn,firstcons)
- if firstcons==start then
- if head==start then
- head=cn
+ current=getnext(current)
+ end
+ elseif kind=="pstf" then
+ local current=start
+ local last=getnext(stop)
+ while current~=last do
+ if current~=stop then
+ local c=locl[current] or getchar(current)
+ local found=lookupcache[c]
+ if found then
+ local next=getnext(current)
+ local n=locl[next] or getchar(next)
+ if found[n] then
+ setprop(current,a_state,s_pstf)
+ setprop(next,a_state,s_pstf)
+ current=next
+ postpos=current
+ end
end
- start=cn
end
- break
+ current=getnext(current)
end
- cn=getnext(cn)
end
- allreordered=c==stop
- current=getnext(c)
end
- if reph or vattu then
- local current,cns=start,nil
- while current~=stop do
- local c=current
- local n=getnext(current)
- if ra[getchar(current)] and halant[getchar(n)] then
- c=n
- n=getnext(n)
- local b,bn=base,base
- while bn~=stop do
- local next=getnext(bn)
- if dependent_vowel[getchar(next)] then
- b=next
- end
- bn=next
+ reorderreph.coverage={ [reph]=true }
+ local current,base,firstcons=start,nil,nil
+ if getprop(start,a_state)==s_rphf then
+ current=getnext(getnext(start))
+ end
+ if current~=getnext(stop) and getchar(current)==c_nbsp then
+ if current==stop then
+ stop=getprev(stop)
+ head=remove_node(head,current)
+ free_node(current)
+ return head,stop,nbspaces
+ else
+ nbspaces=nbspaces+1
+ base=current
+ current=getnext(current)
+ if current~=stop then
+ local char=getchar(current)
+ if nukta[char] then
+ current=getnext(current)
+ char=getchar(current)
end
- if getprop(current,a_state)==s_rphf then
- if b~=current then
- if current==start then
- if head==start then
- head=n
+ if char==c_zwj then
+ local next=getnext(current)
+ if current~=stop and next~=stop and halant[getchar(next)] then
+ current=next
+ next=getnext(current)
+ local tmp=getnext(next)
+ local changestop=next==stop
+ setnext(next,nil)
+ setprop(current,a_state,s_pref)
+ current=processcharacters(current,font)
+ setprop(current,a_state,s_blwf)
+ current=processcharacters(current,font)
+ setprop(current,a_state,s_pstf)
+ current=processcharacters(current,font)
+ setprop(current,a_state,unsetvalue)
+ if halant[getchar(current)] then
+ setnext(getnext(current),tmp)
+ local nc=copy_node(current)
+ copyinjection(nc,current)
+ setchar(current,dotted_circle)
+ head=insert_node_after(head,current,nc)
+ else
+ setnext(current,tmp)
+ if changestop then
+ stop=current
end
- start=n
- end
- if b==stop then
- stop=c
end
- local prev=getprev(current)
- setlink(prev,n)
- local next=getnext(b)
- setlink(c,next)
- setlink(b,current)
- end
- elseif cns and getnext(cns)~=current then
- local cp=getprev(current)
- local cnsn=getnext(cns)
- setlink(cp,n)
- setlink(cns,current)
- setlink(c,cnsn)
- if c==stop then
- stop=cp
- break
end
- current=getprev(n)
end
- else
- local char=getchar(current)
- if consonant[char] then
- cns=current
- local next=getnext(cns)
- if halant[getchar(next)] then
- cns=next
+ end
+ end
+ else
+ local last=getnext(stop)
+ while current~=last do
+ local next=getnext(current)
+ if consonant[getchar(current)] then
+ if not (current~=stop and next~=stop and halant[getchar(next)] and getchar(getnext(next))==c_zwj) then
+ if not firstcons then
+ firstcons=current
end
- elseif char==c_nbsp then
- nbspaces=nbspaces+1
- cns=current
- local next=getnext(cns)
- if halant[getchar(next)] then
- cns=next
+ local a=getprop(current,a_state)
+ if not (a==s_pref or a==s_blwf or a==s_pstf) then
+ base=current
end
end
end
- current=getnext(current)
+ current=next
+ end
+ if not base then
+ base=firstcons
end
end
- if getchar(base)==c_nbsp then
- nbspaces=nbspaces-1
- head=remove_node(head,base)
- free_node(base)
+ if not base then
+ if getprop(start,a_state)==s_rphf then
+ setprop(start,a_state,unsetvalue)
+ end
+ return head,stop,nbspaces
+ else
+ if getprop(base,a_state) then
+ setprop(base,a_state,unsetvalue)
+ end
+ basepos=base
end
- return head,stop,nbspaces
-end
-function handlers.devanagari_reorder_matras(head,start)
- local current=start
- local startfont=getfont(start)
- local startattr=getprop(start,a_syllabe)
- while current do
- local char=ischar(current,startfont)
- local next=getnext(current)
- if char and getprop(current,a_syllabe)==startattr then
- if halant[char] and not getprop(current,a_state) then
- if next then
- local char=ischar(next,startfont)
- if char and zw_char[char] and getprop(next,a_syllabe)==startattr then
- current=next
- next=getnext(current)
+ if not halfpos then
+ halfpos=base
+ end
+ if not subpos then
+ subpos=base
+ end
+ if not postpos then
+ postpos=subpos or base
+ end
+ local moved={}
+ local current=start
+ local last=getnext(stop)
+ while current~=last do
+ local char,target,cn=locl[current] or getchar(current),nil,getnext(current)
+ local tpm=twopart_mark[char]
+ if tpm then
+ local extra=copy_node(current)
+ copyinjection(extra,current)
+ char=tpm[1]
+ setchar(current,char)
+ setchar(extra,tpm[2])
+ head=insert_node_after(head,current,extra)
+ end
+ if not moved[current] and dependent_vowel[char] then
+ if pre_mark[char] then
+ moved[current]=true
+ local prev,next=getboth(current)
+ setlink(prev,next)
+ if current==stop then
+ stop=getprev(current)
+ end
+ if halfpos==start then
+ if head==start then
+ head=current
end
+ start=current
end
- local startnext=getnext(start)
- head=remove_node(head,start)
- setlink(start,next)
- setlink(current,start)
- start=startnext
- break
+ local prev=getprev(halfpos)
+ setlink(prev,current)
+ setlink(current,halfpos)
+ halfpos=current
+ elseif above_mark[char] then
+ target=basepos
+ if subpos==basepos then
+ subpos=current
+ end
+ if postpos==basepos then
+ postpos=current
+ end
+ basepos=current
+ elseif below_mark[char] then
+ target=subpos
+ if postpos==subpos then
+ postpos=current
+ end
+ subpos=current
+ elseif post_mark[char] then
+ target=postpos
+ postpos=current
end
- end
- current=next
- end
- return head,start,true
-end
-function handlers.devanagari_reorder_reph(head,start)
- local current=getnext(start)
- local startnext=nil
- local startprev=nil
- local startfont=getfont(start)
- local startattr=getprop(start,a_syllabe)
- while current do
- local char=ischar(current,font)
- if char and getprop(current,a_syllabe)==startattr then
- if halant[char] and not getprop(current,a_state) then
- local next=getnext(current)
- if next then
- local nextchar=ischar(next,font)
- if nextchar and zw_char[nextchar] and getprop(next,a_syllabe)==startattr then
- current=next
- next=getnext(current)
+ if mark_above_below_post[char] then
+ local prev=getprev(current)
+ if prev~=target then
+ local next=getnext(current)
+ setlink(next,prev)
+ if current==stop then
+ stop=prev
end
+ local next=getnext(target)
+ setlink(current,next)
+ setlink(target,current)
end
- startnext=getnext(start)
- head=remove_node(head,start)
- setlink(start,next)
- setlink(current,start)
- start=startnext
- startattr=getprop(start,a_syllabe)
- break
end
- current=getnext(current)
- else
- break
end
+ current=cn
end
- if not startnext then
- current=getnext(start)
- while current do
- local char=ischar(current,font)
- if char and getprop(current,a_syllabe)==startattr then
- if getprop(current,a_state)==s_pstf then
- startnext=getnext(start)
- head=remove_node(head,start)
- local prev=getprev(current)
- setlink(prev,start)
- setlink(start,current)
- start=startnext
- startattr=getprop(start,a_syllabe)
- break
- end
- current=getnext(current)
- else
- break
+ local current,c=start,nil
+ while current~=stop do
+ local char=getchar(current)
+ if halant[char] or stress_tone_mark[char] then
+ if not c then
+ c=current
end
+ else
+ c=nil
end
- end
- if not startnext then
- current=getnext(start)
- local c=nil
- while current do
- local char=ischar(current,font)
- if char and getprop(current,a_syllabe)==startattr then
- if not c and mark_above_below_post[char] and reorder_class[char]~="after subscript" then
- c=current
- end
- current=getnext(current)
- else
- break
+ local next=getnext(current)
+ if c and nukta[getchar(next)] then
+ if head==c then
+ head=next
+ end
+ if stop==next then
+ stop=current
end
- end
- if c then
- startnext=getnext(start)
- head=remove_node(head,start)
local prev=getprev(c)
- setlink(prev,start)
- setlink(start,c)
- start=startnext
- startattr=getprop(start,a_syllabe)
- end
- end
- if not startnext then
- current=start
- local next=getnext(current)
- while next do
- local nextchar=ischar(next,font)
- if nextchar and getprop(next,a_syllabe)==startattr then
- current=next
- next=getnext(current)
- else
- break
+ setlink(next,prev)
+ local nextnext=getnext(next)
+ setnext(current,nextnext)
+ local nextnextnext=getnext(nextnext)
+ if nextnextnext then
+ setprev(nextnextnext,current)
end
+ setlink(nextnext,c)
end
- if start~=current then
- startnext=getnext(start)
- head=remove_node(head,start)
- local next=getnext(current)
- setlink(start,next)
- setlink(current,"next",start)
- start=startnext
- end
+ if stop==current then break end
+ current=getnext(current)
end
- return head,start,true
+ if getchar(base)==c_nbsp then
+ nbspaces=nbspaces-1
+ head=remove_node(head,base)
+ free_node(base)
+ end
+ return head,stop,nbspaces
end
-function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start)
- local current=start
- local startnext=nil
- local startprev=nil
- local startfont=getfont(start)
- local startattr=getprop(start,a_syllabe)
- while current do
- local char=ischar(current,font)
- if char and getprop(current,a_syllabe)==startattr then
- local next=getnext(current)
- if halant[char] and not getprop(current,a_state) then
- if next then
- local nextchar=ischar(next,font)
- if nextchar and getprop(next,a_syllabe)==startattr then
- if nextchar==c_zwnj or nextchar==c_zwj then
- current=next
- next=getnext(current)
+local separator={}
+imerge(separator,consonant)
+imerge(separator,independent_vowel)
+imerge(separator,dependent_vowel)
+imerge(separator,vowel_modifier)
+imerge(separator,stress_tone_mark)
+for k,v in next,nukta do separator[k]=true end
+for k,v in next,halant do separator[k]=true end
+local function analyze_next_chars_one(c,font,variant)
+ local n=getnext(c)
+ if not n then
+ return c
+ end
+ if variant==1 then
+ local v=ischar(n,font)
+ if v and nukta[v] then
+ n=getnext(n)
+ if n then
+ v=ischar(n,font)
+ end
+ end
+ if n and v then
+ local nn=getnext(n)
+ if nn then
+ local vv=ischar(nn,font)
+ if vv then
+ local nnn=getnext(nn)
+ if nnn then
+ local vvv=ischar(nnn,font)
+ if vvv then
+ if vv==c_zwj and consonant[vvv] then
+ c=nnn
+ elseif (vv==c_zwnj or vv==c_zwj) and halant[vvv] then
+ local nnnn=getnext(nnn)
+ if nnnn then
+ local vvvv=ischar(nnnn)
+ if vvvv and consonant[vvvv] then
+ c=nnnn
+ end
+ end
+ end
end
end
end
- startnext=getnext(start)
- removenode(start,start)
- setlink(start,next)
- setlink(current,start)
- start=startnext
- break
end
- current=next
- else
- break
end
- end
- if not startnext then
- current=getnext(start)
- startattr=getprop(start,a_syllabe)
- while current do
- local char=ischar(current,font)
- if char and getprop(current,a_syllabe)==startattr then
- if not consonant[char] and getprop(current,a_state) then
- startnext=getnext(start)
- removenode(start,start)
- local prev=getprev(current)
- setlink(start,prev)
- setlink(start,current)
- start=startnext
- break
+ elseif variant==2 then
+ local v=ischar(n,font)
+ if v and nukta[v] then
+ c=n
+ end
+ n=getnext(c)
+ if n then
+ v=ischar(n,font)
+ if v then
+ local nn=getnext(n)
+ if nn then
+ local vv=ischar(nn,font)
+ if vv and zw_char[vv] then
+ n=nn
+ v=vv
+ nn=getnext(nn)
+ vv=nn and ischar(nn,font)
+ end
+ if vv and halant[v] and consonant[vv] then
+ c=nn
+ end
end
- current=getnext(current)
- else
- break
end
end
end
- return head,start,true
-end
-function handlers.devanagari_remove_joiners(head,start,kind,lookupname,replacement)
- local stop=getnext(start)
- local font=getfont(start)
- local last=start
- while stop do
- local char=ischar(stop,font)
- if char and (char==c_zwnj or char==c_zwj) then
- last=stop
- stop=getnext(stop)
- else
- break
+ local n=getnext(c)
+ if not n then
+ return c
+ end
+ local v=ischar(n,font)
+ if not v then
+ return c
+ end
+ if dependent_vowel[v] then
+ c=getnext(c)
+ n=getnext(c)
+ if not n then
+ return c
+ end
+ v=ischar(n,font)
+ if not v then
+ return c
end
end
- local prev=getprev(start)
- if stop then
- setnext(last)
- setlink(prev,stop)
- elseif prev then
- setnext(prev)
+ if nukta[v] then
+ c=getnext(c)
+ n=getnext(c)
+ if not n then
+ return c
+ end
+ v=ischar(n,font)
+ if not v then
+ return c
+ end
end
- if head==start then
- head=stop
+ if halant[v] then
+ c=getnext(c)
+ n=getnext(c)
+ if not n then
+ return c
+ end
+ v=ischar(n,font)
+ if not v then
+ return c
+ end
end
- flush_list(start)
- return head,stop,true
-end
-local function dev2_initialize(font,attr)
- local devanagari=fontdata[font].resources.devanagari
- if devanagari then
- return devanagari.seqsubset or {},devanagari.reorderreph or {}
+ if vowel_modifier[v] then
+ c=getnext(c)
+ n=getnext(c)
+ if not n then
+ return c
+ end
+ v=ischar(n,font)
+ if not v then
+ return c
+ end
+ end
+ if stress_tone_mark[v] then
+ c=getnext(c)
+ n=getnext(c)
+ if not n then
+ return c
+ end
+ v=ischar(n,font)
+ if not v then
+ return c
+ end
+ end
+ if stress_tone_mark[v] then
+ return n
else
- return {},{}
+ return c
end
end
-local function dev2_reorder(head,start,stop,font,attr,nbspaces)
- local seqsubset,reorderreph=dev2_initialize(font,attr)
- local reph=false
- local halfpos=nil
- local basepos=nil
- local subpos=nil
- local postpos=nil
- local locl={}
- for i=1,#seqsubset do
- local subset=seqsubset[i]
- local kind=subset[1]
- local lookupcache=subset[2]
- if kind=="rphf" then
- for k,v in next,ra do
- local r=lookupcache[k]
- if r then
- for k,v in next,halant do
- local h=r[k]
- if h then
- reph=h.ligature or false
- break
- end
- end
- if reph then
- break
- end
- end
- end
- local current=start
- local last=getnext(stop)
- while current~=last do
- if current~=stop then
- local c=locl[current] or getchar(current)
- local found=lookupcache[c]
- if found then
- local next=getnext(current)
- local n=locl[next] or getchar(next)
- if found[n] then
- local afternext=next~=stop and getnext(next)
- if afternext and zw_char[getchar(afternext)] then
- current=next
- current=getnext(current)
- elseif current==start then
- setprop(current,a_state,s_rphf)
- current=next
- else
- current=next
- end
- end
- end
- end
- current=getnext(current)
- end
- elseif kind=="pref" then
- local current=start
- local last=getnext(stop)
- while current~=last do
- if current~=stop then
- local c=locl[current] or getchar(current)
- local found=lookupcache[c]
- if found then
- local next=getnext(current)
- local n=locl[next] or getchar(next)
- if found[n] then
- setprop(current,a_state,s_pref)
- setprop(next,a_state,s_pref)
- current=next
- end
- end
- end
- current=getnext(current)
- end
- elseif kind=="half" then
- local current=start
- local last=getnext(stop)
- while current~=last do
- if current~=stop then
- local c=locl[current] or getchar(current)
- local found=lookupcache[c]
- if found then
- local next=getnext(current)
- local n=locl[next] or getchar(next)
- if found[n] then
- if next~=stop and getchar(getnext(next))==c_zwnj then
- current=next
- else
- setprop(current,a_state,s_half)
- if not halfpos then
- halfpos=current
- end
- end
- current=getnext(current)
- end
- end
- end
- current=getnext(current)
- end
- elseif kind=="blwf" then
- local current=start
- local last=getnext(stop)
- while current~=last do
- if current~=stop then
- local c=locl[current] or getchar(current)
- local found=lookupcache[c]
- if found then
- local next=getnext(current)
- local n=locl[next] or getchar(next)
- if found[n] then
- setprop(current,a_state,s_blwf)
- setprop(next,a_state,s_blwf)
- current=next
- subpos=current
+local function analyze_next_chars_two(c,font)
+ local n=getnext(c)
+ if not n then
+ return c
+ end
+ local v=ischar(n,font)
+ if v and nukta[v] then
+ c=n
+ end
+ n=c
+ while true do
+ local nn=getnext(n)
+ if nn then
+ local vv=ischar(nn,font)
+ if vv then
+ if halant[vv] then
+ n=nn
+ local nnn=getnext(nn)
+ if nnn then
+ local vvv=ischar(nnn,font)
+ if vvv and zw_char[vvv] then
+ n=nnn
end
end
- end
- current=getnext(current)
- end
- elseif kind=="pstf" then
- local current=start
- local last=getnext(stop)
- while current~=last do
- if current~=stop then
- local c=locl[current] or getchar(current)
- local found=lookupcache[c]
- if found then
- local next=getnext(current)
- local n=locl[next] or getchar(next)
- if found[n] then
- setprop(current,a_state,s_pstf)
- setprop(next,a_state,s_pstf)
- current=next
- postpos=current
+ elseif vv==c_zwnj or vv==c_zwj then
+ local nnn=getnext(nn)
+ if nnn then
+ local vvv=ischar(nnn,font)
+ if vvv and halant[vvv] then
+ n=nnn
end
end
+ else
+ break
end
- current=getnext(current)
- end
- end
- end
- reorderreph.coverage={ [reph]=true }
- local current,base,firstcons=start,nil,nil
- if getprop(start,a_state)==s_rphf then
- current=getnext(getnext(start))
- end
- if current~=getnext(stop) and getchar(current)==c_nbsp then
- if current==stop then
- stop=getprev(stop)
- head=remove_node(head,current)
- free_node(current)
- return head,stop,nbspaces
- else
- nbspaces=nbspaces+1
- base=current
- current=getnext(current)
- if current~=stop then
- local char=getchar(current)
- if nukta[char] then
- current=getnext(current)
- char=getchar(current)
- end
- if char==c_zwj then
- local next=getnext(current)
- if current~=stop and next~=stop and halant[getchar(next)] then
- current=next
- next=getnext(current)
- local tmp=getnext(next)
- local changestop=next==stop
- setnext(next,nil)
- setprop(current,a_state,s_pref)
- current=processcharacters(current,font)
- setprop(current,a_state,s_blwf)
- current=processcharacters(current,font)
- setprop(current,a_state,s_pstf)
- current=processcharacters(current,font)
- setprop(current,a_state,unsetvalue)
- if halant[getchar(current)] then
- setnext(getnext(current),tmp)
- local nc=copy_node(current)
- copyinjection(nc,current)
- setchar(current,dotted_circle)
- head=insert_node_after(head,current,nc)
- else
- setnext(current,tmp)
- if changestop then
- stop=current
+ local nn=getnext(n)
+ if nn then
+ local vv=ischar(nn,font)
+ if vv and consonant[vv] then
+ n=nn
+ local nnn=getnext(nn)
+ if nnn then
+ local vvv=ischar(nnn,font)
+ if vvv and nukta[vvv] then
+ n=nnn
end
end
+ c=n
+ else
+ break
end
+ else
+ break
end
+ else
+ break
end
- end
- else
- local last=getnext(stop)
- while current~=last do
- local next=getnext(current)
- if consonant[getchar(current)] then
- if not (current~=stop and next~=stop and halant[getchar(next)] and getchar(getnext(next))==c_zwj) then
- if not firstcons then
- firstcons=current
- end
- local a=getprop(current,a_state)
- if not (a==s_pref or a==s_blwf or a==s_pstf) then
- base=current
- end
- end
- end
- current=next
- end
- if not base then
- base=firstcons
+ else
+ break
end
end
- if not base then
- if getprop(start,a_state)==s_rphf then
- setprop(start,a_state,unsetvalue)
- end
- return head,stop,nbspaces
- else
- if getprop(base,a_state) then
- setprop(base,a_state,unsetvalue)
- end
- basepos=base
+ if not c then
+ return
end
- if not halfpos then
- halfpos=base
+ local n=getnext(c)
+ if not n then
+ return c
end
- if not subpos then
- subpos=base
+ local v=ischar(n,font)
+ if not v then
+ return c
end
- if not postpos then
- postpos=subpos or base
+ if v==c_anudatta then
+ c=n
+ n=getnext(c)
+ if not n then
+ return c
+ end
+ v=ischar(n,font)
+ if not v then
+ return c
+ end
end
- local moved={}
- local current=start
- local last=getnext(stop)
- while current~=last do
- local char,target,cn=locl[current] or getchar(current),nil,getnext(current)
- local tpm=twopart_mark[char]
- if tpm then
- local extra=copy_node(current)
- copyinjection(extra,current)
- char=tpm[1]
- setchar(current,char)
- setchar(extra,tpm[2])
- head=insert_node_after(head,current,extra)
+ if halant[v] then
+ c=n
+ n=getnext(c)
+ if not n then
+ return c
end
- if not moved[current] and dependent_vowel[char] then
- if pre_mark[char] then
- moved[current]=true
- local prev,next=getboth(current)
- setlink(prev,next)
- if current==stop then
- stop=getprev(current)
- end
- if halfpos==start then
- if head==start then
- head=current
- end
- start=current
- end
- local prev=getprev(halfpos)
- setlink(prev,current)
- setlink(current,halfpos)
- halfpos=current
- elseif above_mark[char] then
- target=basepos
- if subpos==basepos then
- subpos=current
- end
- if postpos==basepos then
- postpos=current
- end
- basepos=current
- elseif below_mark[char] then
- target=subpos
- if postpos==subpos then
- postpos=current
- end
- subpos=current
- elseif post_mark[char] then
- target=postpos
- postpos=current
+ v=ischar(n,font)
+ if not v then
+ return c
+ end
+ if v==c_zwnj or v==c_zwj then
+ c=n
+ n=getnext(c)
+ if not n then
+ return c
end
- if mark_above_below_post[char] then
- local prev=getprev(current)
- if prev~=target then
- local next=getnext(current)
- setlink(next,prev)
- if current==stop then
- stop=prev
- end
- local next=getnext(target)
- setlink(current,next)
- setlink(target,current)
- end
+ v=ischar(n,font)
+ if not v then
+ return c
end
end
- current=cn
- end
- local current,c=start,nil
- while current~=stop do
- local char=getchar(current)
- if halant[char] or stress_tone_mark[char] then
- if not c then
- c=current
+ else
+ if dependent_vowel[v] then
+ c=n
+ n=getnext(c)
+ if not n then
+ return c
+ end
+ v=ischar(n,font)
+ if not v then
+ return c
end
- else
- c=nil
end
- local next=getnext(current)
- if c and nukta[getchar(next)] then
- if head==c then
- head=next
+ if nukta[v] then
+ c=n
+ n=getnext(c)
+ if not n then
+ return c
end
- if stop==next then
- stop=current
+ v=ischar(n,font)
+ if not v then
+ return c
end
- local prev=getprev(c)
- setlink(next,prev)
- local nextnext=getnext(next)
- setnext(current,nextnext)
- local nextnextnext=getnext(nextnext)
- if nextnextnext then
- setprev(nextnextnext,current)
+ end
+ if halant[v] then
+ c=n
+ n=getnext(c)
+ if not n then
+ return c
+ end
+ v=ischar(n,font)
+ if not v then
+ return c
end
- setlink(nextnext,c)
end
- if stop==current then break end
- current=getnext(current)
end
- if getchar(base)==c_nbsp then
- nbspaces=nbspaces-1
- head=remove_node(head,base)
- free_node(base)
+ if vowel_modifier[v] then
+ c=n
+ n=getnext(c)
+ if not n then
+ return c
+ end
+ v=ischar(n,font)
+ if not v then
+ return c
+ end
end
- return head,stop,nbspaces
-end
-local separator={}
-imerge(separator,consonant)
-imerge(separator,independent_vowel)
-imerge(separator,dependent_vowel)
-imerge(separator,vowel_modifier)
-imerge(separator,stress_tone_mark)
-for k,v in next,nukta do separator[k]=true end
-for k,v in next,halant do separator[k]=true end
-local function analyze_next_chars_one(c,font,variant)
- local n=getnext(c)
- if not n then
+ if stress_tone_mark[v] then
+ c=n
+ n=getnext(c)
+ if not n then
+ return c
+ end
+ v=ischar(n,font)
+ if not v then
+ return c
+ end
+ end
+ if stress_tone_mark[v] then
+ return n
+ else
return c
end
- if variant==1 then
- local v=ischar(n,font)
- if v and nukta[v] then
- n=getnext(n)
- if n then
- v=ischar(n,font)
+end
+local function inject_syntax_error(head,current,mark)
+ local signal=copy_node(current)
+ copyinjection(signal,current)
+ if mark==pre_mark then
+ setchar(signal,dotted_circle)
+ else
+ setchar(current,dotted_circle)
+ end
+ return insert_node_after(head,current,signal)
+end
+function methods.deva(head,font,attr)
+ head=tonut(head)
+ local current=head
+ local start=true
+ local done=false
+ local nbspaces=0
+ while current do
+ local char=ischar(current,font)
+ if char then
+ done=true
+ local syllablestart=current
+ local syllableend=nil
+ local c=current
+ local n=getnext(c)
+ local first=char
+ if n and ra[first] then
+ local second=ischar(n,font)
+ if second and halant[second] then
+ local n=getnext(n)
+ if n then
+ local third=ischar(n,font)
+ if third then
+ c=n
+ first=third
+ end
+ end
+ end
end
- end
- if n and v then
- local nn=getnext(n)
- if nn then
- local vv=ischar(nn,font)
- if vv then
- local nnn=getnext(nn)
- if nnn then
- local vvv=ischar(nnn,font)
- if vvv then
- if vv==c_zwj and consonant[vvv] then
- c=nnn
- elseif (vv==c_zwnj or vv==c_zwj) and halant[vvv] then
- local nnnn=getnext(nnn)
- if nnnn then
- local vvvv=ischar(nnnn)
- if vvvv and consonant[vvvv] then
- c=nnnn
- end
+ local standalone=first==c_nbsp
+ if standalone then
+ local prev=getprev(current)
+ if prev then
+ local prevchar=ischar(prev,font)
+ if not prevchar then
+ elseif not separator[prevchar] then
+ else
+ standalone=false
+ end
+ else
+ end
+ end
+ if standalone then
+ local syllableend=analyze_next_chars_one(c,font,2)
+ current=getnext(syllableend)
+ if syllablestart~=syllableend then
+ head,current,nbspaces=deva_reorder(head,syllablestart,syllableend,font,attr,nbspaces)
+ current=getnext(current)
+ end
+ else
+ if consonant[char] then
+ local prevc=true
+ while prevc do
+ prevc=false
+ local n=getnext(current)
+ if not n then
+ break
+ end
+ local v=ischar(n,font)
+ if not v then
+ break
+ end
+ if nukta[v] then
+ n=getnext(n)
+ if not n then
+ break
+ end
+ v=ischar(n,font)
+ if not v then
+ break
+ end
+ end
+ if halant[v] then
+ n=getnext(n)
+ if not n then
+ break
+ end
+ v=ischar(n,font)
+ if not v then
+ break
+ end
+ if v==c_zwnj or v==c_zwj then
+ n=getnext(n)
+ if not n then
+ break
+ end
+ v=ischar(n,font)
+ if not v then
+ break
end
end
+ if consonant[v] then
+ prevc=true
+ current=n
+ end
end
end
- end
- end
- end
- elseif variant==2 then
- local v=ischar(n,font)
- if v and nukta[v] then
- c=n
- end
- n=getnext(c)
- if n then
- v=ischar(n,font)
- if v then
- local nn=getnext(n)
- if nn then
- local vv=ischar(nn,font)
- if vv and zw_char[vv] then
- n=nn
- v=vv
- nn=getnext(nn)
- vv=nn and ischar(nn,font)
+ local n=getnext(current)
+ if n then
+ local v=ischar(n,font)
+ if v and nukta[v] then
+ current=n
+ n=getnext(current)
+ end
+ end
+ syllableend=current
+ current=n
+ if current then
+ local v=ischar(current,font)
+ if not v then
+ elseif halant[v] then
+ local n=getnext(current)
+ if n then
+ local v=ischar(n,font)
+ if v and zw_char[v] then
+ syllableend=n
+ current=getnext(n)
+ else
+ syllableend=current
+ current=n
+ end
+ else
+ syllableend=current
+ current=n
+ end
+ else
+ if dependent_vowel[v] then
+ syllableend=current
+ current=getnext(current)
+ v=ischar(current,font)
+ end
+ if v and vowel_modifier[v] then
+ syllableend=current
+ current=getnext(current)
+ v=ischar(current,font)
+ end
+ if v and stress_tone_mark[v] then
+ syllableend=current
+ current=getnext(current)
+ end
+ end
+ end
+ if syllablestart~=syllableend then
+ head,current,nbspaces=deva_reorder(head,syllablestart,syllableend,font,attr,nbspaces)
+ current=getnext(current)
+ end
+ elseif independent_vowel[char] then
+ syllableend=current
+ current=getnext(current)
+ if current then
+ local v=ischar(current,font)
+ if v then
+ if vowel_modifier[v] then
+ syllableend=current
+ current=getnext(current)
+ v=ischar(current,font)
+ end
+ if v and stress_tone_mark[v] then
+ syllableend=current
+ current=getnext(current)
+ end
+ end
end
- if vv and halant[v] and consonant[vv] then
- c=nn
+ else
+ local mark=mark_four[char]
+ if mark then
+ head,current=inject_syntax_error(head,current,mark)
end
+ current=getnext(current)
end
end
+ else
+ current=getnext(current)
end
+ start=false
end
- local n=getnext(c)
- if not n then
- return c
- end
- local v=ischar(n,font)
- if not v then
- return c
- end
- if dependent_vowel[v] then
- c=getnext(c)
- n=getnext(c)
- if not n then
- return c
- end
- v=ischar(n,font)
- if not v then
- return c
- end
- end
- if nukta[v] then
- c=getnext(c)
- n=getnext(c)
- if not n then
- return c
- end
- v=ischar(n,font)
- if not v then
- return c
- end
+ if nbspaces>0 then
+ head=replace_all_nbsp(head)
end
- if halant[v] then
- c=getnext(c)
- n=getnext(c)
- if not n then
- return c
+ head=tonode(head)
+ return head,done
+end
+function methods.dev2(head,font,attr)
+ head=tonut(head)
+ local current=head
+ local start=true
+ local done=false
+ local syllabe=0
+ local nbspaces=0
+ while current do
+ local syllablestart=nil
+ local syllableend=nil
+ local char=ischar(current,font)
+ if char then
+ done=true
+ syllablestart=current
+ local c=current
+ local n=getnext(current)
+ if n and ra[char] then
+ local nextchar=ischar(n,font)
+ if nextchar and halant[nextchar] then
+ local n=getnext(n)
+ if n then
+ local nextnextchar=ischar(n,font)
+ if nextnextchar then
+ c=n
+ char=nextnextchar
+ end
+ end
+ end
+ end
+ if independent_vowel[char] then
+ current=analyze_next_chars_one(c,font,1)
+ syllableend=current
+ else
+ local standalone=char==c_nbsp
+ if standalone then
+ nbspaces=nbspaces+1
+ local p=getprev(current)
+ if not p then
+ elseif ischar(p,font) then
+ elseif not separator[getchar(p)] then
+ else
+ standalone=false
+ end
+ end
+ if standalone then
+ current=analyze_next_chars_one(c,font,2)
+ syllableend=current
+ elseif consonant[getchar(current)] then
+ current=analyze_next_chars_two(current,font)
+ syllableend=current
+ end
+ end
end
- v=ischar(n,font)
- if not v then
- return c
+ if syllableend then
+ syllabe=syllabe+1
+ local c=syllablestart
+ local n=getnext(syllableend)
+ while c~=n do
+ setprop(c,a_syllabe,syllabe)
+ c=getnext(c)
+ end
end
- end
- if vowel_modifier[v] then
- c=getnext(c)
- n=getnext(c)
- if not n then
- return c
+ if syllableend and syllablestart~=syllableend then
+ head,current,nbspaces=dev2_reorder(head,syllablestart,syllableend,font,attr,nbspaces)
end
- v=ischar(n,font)
- if not v then
- return c
+ if not syllableend then
+ local char=ischar(current,font)
+ if char and not getprop(current,a_state) then
+ local mark=mark_four[char]
+ if mark then
+ head,current=inject_syntax_error(head,current,mark)
+ end
+ end
end
+ start=false
+ current=getnext(current)
end
- if stress_tone_mark[v] then
- c=getnext(c)
- n=getnext(c)
- if not n then
- return c
- end
- v=ischar(n,font)
- if not v then
- return c
- end
+ if nbspaces>0 then
+ head=replace_all_nbsp(head)
end
- if stress_tone_mark[v] then
- return n
- else
- return c
+ head=tonode(head)
+ return head,done
+end
+methods.mlym=methods.deva
+methods.mlm2=methods.dev2
+
+end -- closure
+
+do -- begin closure to overcome local limits and interference
+
+if not modules then modules={} end modules ['font-one']={
+ 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 fonts,logs,trackers,containers,resolvers=fonts,logs,trackers,containers,resolvers
+local next,type,tonumber=next,type,tonumber
+local match,gmatch,lower,gsub,strip,find=string.match,string.gmatch,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,lpegmatch,patterns=lpeg.P,lpeg.S,lpeg.R,lpeg.Cmt,lpeg.C,lpeg.Ct,lpeg.Cs,lpeg.match,lpeg.patterns
+local derivetable=table.derive
+local trace_features=false trackers.register("afm.features",function(v) trace_features=v end)
+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 trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end)
+local report_afm=logs.reporter("fonts","afm loading")
+local setmetatableindex=table.setmetatableindex
+local findbinfile=resolvers.findbinfile
+local definers=fonts.definers
+local readers=fonts.readers
+local constructors=fonts.constructors
+local afm=constructors.newhandler("afm")
+local pfb=constructors.newhandler("pfb")
+local otf=fonts.handlers.otf
+local otfreaders=otf.readers
+local otfenhancers=otf.enhancers
+local afmfeatures=constructors.newfeatures("afm")
+local registerafmfeature=afmfeatures.register
+afm.version=1.505
+afm.cache=containers.define("fonts","afm",afm.version,true)
+afm.autoprefixed=true
+afm.helpdata={}
+afm.syncspace=true
+local overloads=fonts.mappings.overloads
+local applyruntimefixes=fonts.treatments and fonts.treatments.applyfixes
+local comment=P("Comment")
+local spacing=patterns.spacer
+local lineend=patterns.newline
+local words=C((1-lineend)^1)
+local number=C((R("09")+S("."))^1)/tonumber*spacing^0
+local data=lpeg.Carg(1)
+local pattern=(
+ comment*spacing*(
+ data*(
+ ("CODINGSCHEME"*spacing*words )/function(fd,a) end+("DESIGNSIZE"*spacing*number*words )/function(fd,a) fd[ 1]=a end+("CHECKSUM"*spacing*number*words )/function(fd,a) fd[ 2]=a end+("SPACE"*spacing*number*"plus"*number*"minus"*number)/function(fd,a,b,c) fd[ 3],fd[ 4],fd[ 5]=a,b,c end+("QUAD"*spacing*number )/function(fd,a) fd[ 6]=a end+("EXTRASPACE"*spacing*number )/function(fd,a) fd[ 7]=a end+("NUM"*spacing*number*number*number )/function(fd,a,b,c) fd[ 8],fd[ 9],fd[10]=a,b,c end+("DENOM"*spacing*number*number )/function(fd,a,b ) fd[11],fd[12]=a,b end+("SUP"*spacing*number*number*number )/function(fd,a,b,c) fd[13],fd[14],fd[15]=a,b,c end+("SUB"*spacing*number*number )/function(fd,a,b) fd[16],fd[17]=a,b end+("SUPDROP"*spacing*number )/function(fd,a) fd[18]=a end+("SUBDROP"*spacing*number )/function(fd,a) fd[19]=a end+("DELIM"*spacing*number*number )/function(fd,a,b) fd[20],fd[21]=a,b end+("AXISHEIGHT"*spacing*number )/function(fd,a) fd[22]=a end
+ )+(1-lineend)^0
+ )+(1-comment)^1
+)^0
+local function scan_comment(str)
+ local fd={}
+ lpegmatch(pattern,str,1,fd)
+ return fd
+end
+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.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
+function keys.Ascender (data,line) data.metadata.ascender=tonumber (line) end
+function keys.Comment (data,line)
+ line=lower(line)
+ local designsize=match(line,"designsize[^%d]*(%d+)")
+ if designsize then data.metadata.designsize=tonumber(designsize) end
+end
+local function get_charmetrics(data,charmetrics,vector)
+ local characters=data.characters
+ local chr,ind={},0
+ for k,v in gmatch(charmetrics,"([%a]+) +(.-) *;") do
+ if k=='C' then
+ v=tonumber(v)
+ if v<0 then
+ ind=ind+1
+ else
+ ind=v
+ end
+ chr={
+ index=ind
+ }
+ elseif k=='WX' then
+ chr.width=tonumber(v)
+ elseif k=='N' then
+ characters[v]=chr
+ elseif k=='B' then
+ local llx,lly,urx,ury=match(v,"^ *(.-) +(.-) +(.-) +(.-)$")
+ chr.boundingbox={ tonumber(llx),tonumber(lly),tonumber(urx),tonumber(ury) }
+ elseif k=='L' then
+ local plus,becomes=match(v,"^(.-) +(.-)$")
+ local ligatures=chr.ligatures
+ if ligatures then
+ ligatures[plus]=becomes
+ else
+ chr.ligatures={ [plus]=becomes }
+ end
+ end
end
end
-local function analyze_next_chars_two(c,font)
- local n=getnext(c)
- if not n then
- return c
- end
- local v=ischar(n,font)
- if v and nukta[v] then
- c=n
- end
- n=c
- while true do
- local nn=getnext(n)
- if nn then
- local vv=ischar(nn,font)
- if vv then
- if halant[vv] then
- n=nn
- local nnn=getnext(nn)
- if nnn then
- local vvv=ischar(nnn,font)
- if vvv and zw_char[vvv] then
- n=nnn
- end
- end
- elseif vv==c_zwnj or vv==c_zwj then
- local nnn=getnext(nn)
- if nnn then
- local vvv=ischar(nnn,font)
- if vvv and halant[vvv] then
- n=nnn
- end
- end
- else
- break
- end
- local nn=getnext(n)
- if nn then
- local vv=ischar(nn,font)
- if vv and consonant[vv] then
- n=nn
- local nnn=getnext(nn)
- if nnn then
- local vvv=ischar(nnn,font)
- if vvv and nukta[vvv] then
- n=nnn
- end
- end
- c=n
- else
- break
- end
- else
- break
- end
+local function get_kernpairs(data,kernpairs)
+ local characters=data.characters
+ for one,two,value in gmatch(kernpairs,"KPX +(.-) +(.-) +(.-)\n") do
+ local chr=characters[one]
+ if chr then
+ local kerns=chr.kerns
+ if kerns then
+ kerns[two]=tonumber(value)
else
- break
+ chr.kerns={ [two]=tonumber(value) }
end
- else
- break
end
end
- if not c then
- return
+end
+local function get_variables(data,fontmetrics)
+ for key,rest in gmatch(fontmetrics,"(%a+) *(.-)[\n\r]") do
+ local keyhandler=keys[key]
+ if keyhandler then
+ keyhandler(data,rest)
+ end
end
- local n=getnext(c)
- if not n then
- return c
+end
+local get_indexes
+do
+ local n,m
+ local progress=function(str,position,name,size)
+ local forward=position+tonumber(size)+3+2
+ n=n+1
+ if n>=m then
+ return #str,name
+ elseif forward<#str then
+ return forward,name
+ else
+ return #str,name
+ end
end
- local v=ischar(n,font)
- if not v then
- return c
+ local initialize=function(str,position,size)
+ n=0
+ m=tonumber(size)
+ return position+1
end
- if v==c_anudatta then
- c=n
- n=getnext(c)
- if not n then
- return c
+ local charstrings=P("/CharStrings")
+ local name=P("/")*C((R("az")+R("AZ")+R("09")+S("-_."))^1)
+ local size=C(R("09")^1)
+ local spaces=P(" ")^1
+ local p_filternames=Ct (
+ (1-charstrings)^0*charstrings*spaces*Cmt(size,initialize)*(Cmt(name*P(" ")^1*C(R("09")^1),progress)+P(1))^1
+ )
+ local decrypt
+ do
+ local r,c1,c2,n=0,0,0,0
+ local function step(c)
+ local cipher=byte(c)
+ local plain=bxor(cipher,rshift(r,8))
+ r=((cipher+r)*c1+c2)%65536
+ return char(plain)
end
- v=ischar(n,font)
- if not v then
- return c
+ decrypt=function(binary)
+ r,c1,c2,n=55665,52845,22719,4
+ binary=gsub(binary,".",step)
+ return sub(binary,n+1)
end
end
- if halant[v] then
- c=n
- n=getnext(c)
- if not n then
- return c
+ local function loadpfbvector(filename)
+ local data=io.loaddata(resolvers.findfile(filename))
+ if not find(data,"!PS%-AdobeFont%-") then
+ print("no font",filename)
+ return
end
- v=ischar(n,font)
- if not v then
- return c
+ if not data then
+ print("no data",filename)
+ return
end
- if v==c_zwnj or v==c_zwj then
- c=n
- n=getnext(c)
- if not n then
- return c
- end
- v=ischar(n,font)
- if not v then
- return c
- end
+ local ascii,binary=match(data,"(.*)eexec%s+......(.*)")
+ if not binary then
+ print("no binary",filename)
+ return
end
- else
- if dependent_vowel[v] then
- c=n
- n=getnext(c)
- if not n then
- return c
- end
- v=ischar(n,font)
- if not v then
- return c
- end
+ binary=decrypt(binary,4)
+ local vector=lpegmatch(p_filternames,binary)
+ vector[0]=table.remove(vector,1)
+ if not vector then
+ print("no vector",filename)
+ return
end
- if nukta[v] then
- c=n
- n=getnext(c)
- if not n then
- return c
+ return vector
+ end
+ get_indexes=function(data,pfbname)
+ local vector=loadpfbvector(pfbname)
+ if vector then
+ local characters=data.characters
+ if trace_loading then
+ report_afm("getting index data from %a",pfbname)
end
- v=ischar(n,font)
- if not v then
- return c
+ for index=1,#vector do
+ local name=vector[index]
+ local char=characters[name]
+ if char then
+ if trace_indexing then
+ report_afm("glyph %a has index %a",name,index)
+ end
+ char.index=index
+ end
end
end
- if halant[v] then
- c=n
- n=getnext(c)
- if not n then
- return c
+ end
+end
+local function readafm(filename)
+ local ok,afmblob,size=resolvers.loadbinfile(filename)
+ if ok and afmblob then
+ local data={
+ resources={
+ filename=resolvers.unresolve(filename),
+ version=afm.version,
+ creator="context mkiv",
+ },
+ properties={
+ hasitalics=false,
+ },
+ goodies={},
+ metadata={
+ filename=file.removesuffix(file.basename(filename))
+ },
+ characters={
+ },
+ descriptions={
+ },
+ }
+ afmblob=gsub(afmblob,"StartCharMetrics(.-)EndCharMetrics",function(charmetrics)
+ if trace_loading then
+ report_afm("loading char metrics")
end
- v=ischar(n,font)
- if not v then
- return c
+ get_charmetrics(data,charmetrics,vector)
+ return ""
+ end)
+ afmblob=gsub(afmblob,"StartKernPairs(.-)EndKernPairs",function(kernpairs)
+ if trace_loading then
+ report_afm("loading kern pairs")
+ end
+ get_kernpairs(data,kernpairs)
+ return ""
+ end)
+ afmblob=gsub(afmblob,"StartFontMetrics%s+([%d%.]+)(.-)EndFontMetrics",function(version,fontmetrics)
+ if trace_loading then
+ report_afm("loading variables")
end
+ data.afmversion=version
+ get_variables(data,fontmetrics)
+ data.fontdimens=scan_comment(fontmetrics)
+ return ""
+ end)
+ return data
+ else
+ if trace_loading then
+ report_afm("no valid afm file %a",filename)
end
+ return nil
end
- if vowel_modifier[v] then
- c=n
- n=getnext(c)
- if not n then
- return c
+end
+local addkerns,unify,normalize,fixnames,addligatures,addtexligatures
+function afm.load(filename)
+ filename=resolvers.findfile(filename,'afm') or ""
+ if filename~="" and not fonts.names.ignoredfile(filename) then
+ local name=file.removesuffix(file.basename(filename))
+ local data=containers.read(afm.cache,name)
+ local attr=lfs.attributes(filename)
+ local size,time=attr.size or 0,attr.modification or 0
+ local pfbfile=file.replacesuffix(name,"pfb")
+ local pfbname=resolvers.findfile(pfbfile,"pfb") or ""
+ if pfbname=="" then
+ pfbname=resolvers.findfile(file.basename(pfbfile),"pfb") or ""
end
- v=ischar(n,font)
- if not v then
- return c
+ local pfbsize,pfbtime=0,0
+ if pfbname~="" then
+ local attr=lfs.attributes(pfbname)
+ pfbsize=attr.size or 0
+ pfbtime=attr.modification or 0
end
- end
- if stress_tone_mark[v] then
- c=n
- n=getnext(c)
- if not n then
- return c
+ if not data or data.size~=size or data.time~=time or data.pfbsize~=pfbsize or data.pfbtime~=pfbtime then
+ report_afm("reading %a",filename)
+ data=readafm(filename)
+ if data then
+ if pfbname~="" then
+ data.resources.filename=resolvers.unresolve(pfbname)
+ get_indexes(data,pfbname)
+ elseif trace_loading then
+ report_afm("no pfb file for %a",filename)
+ end
+ if trace_loading then
+ report_afm("unifying %a",filename)
+ end
+ unify(data,filename)
+ if trace_loading then
+ report_afm("add ligatures")
+ end
+ addligatures(data)
+ if trace_loading then
+ report_afm("add extra kerns")
+ end
+ addkerns(data)
+ if trace_loading then
+ report_afm("normalizing")
+ end
+ normalize(data)
+ if trace_loading then
+ report_afm("fixing names")
+ end
+ fixnames(data)
+ if trace_loading then
+ report_afm("add tounicode data")
+ end
+ fonts.mappings.addtounicode(data,filename)
+ otfreaders.pack(data)
+ data.size=size
+ data.time=time
+ data.pfbsize=pfbsize
+ data.pfbtime=pfbtime
+ report_afm("saving %a in cache",name)
+ data=containers.write(afm.cache,name,data)
+ data=containers.read(afm.cache,name)
+ end
end
- v=ischar(n,font)
- if not v then
- return c
+ if data then
+ otfreaders.unpack(data)
+ otfreaders.expand(data)
+ otfreaders.addunicodetable(data)
+ otfenhancers.apply(data,filename,data)
+ if applyruntimefixes then
+ applyruntimefixes(filename,data)
+ end
end
- end
- if stress_tone_mark[v] then
- return n
- else
- return c
- end
-end
-local function inject_syntax_error(head,current,mark)
- local signal=copy_node(current)
- copyinjection(signal,current)
- if mark==pre_mark then
- setchar(signal,dotted_circle)
+ return data
else
- setchar(current,dotted_circle)
+ return nil
end
- return insert_node_after(head,current,signal)
end
-function methods.deva(head,font,attr)
- head=tonut(head)
- local current=head
- local start=true
- local done=false
- local nbspaces=0
- while current do
- local char=ischar(current,font)
- if char then
- done=true
- local syllablestart=current
- local syllableend=nil
- local c=current
- local n=getnext(c)
- local first=char
- if n and ra[first] then
- local second=ischar(n,font)
- if second and halant[second] then
- local n=getnext(n)
- if n then
- local third=ischar(n,font)
- if third then
- c=n
- first=third
- end
- end
- end
+local uparser=fonts.mappings.makenameparser()
+unify=function(data,filename)
+ local unicodevector=fonts.encodings.agl.unicodes
+ local unicodes={}
+ local names={}
+ local private=constructors.privateoffset
+ local descriptions=data.descriptions
+ for name,blob in next,data.characters do
+ local code=unicodevector[name]
+ if not code then
+ code=lpegmatch(uparser,name)
+ if not code then
+ code=private
+ private=private+1
+ report_afm("assigning private slot %U for unknown glyph name %a",code,name)
end
- local standalone=first==c_nbsp
- if standalone then
- local prev=getprev(current)
- if prev then
- local prevchar=ischar(prev,font)
- if not prevchar then
- elseif not separator[prevchar] then
- else
- standalone=false
- end
+ end
+ local index=blob.index
+ unicodes[name]=code
+ names[name]=index
+ blob.name=name
+ descriptions[code]={
+ boundingbox=blob.boundingbox,
+ width=blob.width,
+ kerns=blob.kerns,
+ index=index,
+ name=name,
+ }
+ end
+ for unicode,description in next,descriptions do
+ local kerns=description.kerns
+ if kerns then
+ local krn={}
+ for name,kern in next,kerns do
+ local unicode=unicodes[name]
+ if unicode then
+ krn[unicode]=kern
else
end
end
- if standalone then
- local syllableend=analyze_next_chars_one(c,font,2)
- current=getnext(syllableend)
- if syllablestart~=syllableend then
- head,current,nbspaces=deva_reorder(head,syllablestart,syllableend,font,attr,nbspaces)
- current=getnext(current)
- end
- else
- if consonant[char] then
- local prevc=true
- while prevc do
- prevc=false
- local n=getnext(current)
- if not n then
- break
- end
- local v=ischar(n,font)
- if not v then
- break
- end
- if nukta[v] then
- n=getnext(n)
- if not n then
- break
- end
- v=ischar(n,font)
- if not v then
- break
- end
- end
- if halant[v] then
- n=getnext(n)
- if not n then
- break
- end
- v=ischar(n,font)
- if not v then
- break
- end
- if v==c_zwnj or v==c_zwj then
- n=getnext(n)
- if not n then
- break
- end
- v=ischar(n,font)
- if not v then
- break
- end
- end
- if consonant[v] then
- prevc=true
- current=n
+ description.kerns=krn
+ end
+ end
+ data.characters=nil
+ local resources=data.resources
+ local filename=resources.filename or file.removesuffix(file.basename(filename))
+ resources.filename=resolvers.unresolve(filename)
+ resources.unicodes=unicodes
+ resources.marks={}
+ resources.private=private
+end
+local everywhere={ ["*"]={ ["*"]=true } }
+local noflags={ false,false,false,false }
+normalize=function(data)
+ local ligatures=setmetatableindex("table")
+ local kerns=setmetatableindex("table")
+ local extrakerns=setmetatableindex("table")
+ for u,c in next,data.descriptions do
+ local l=c.ligatures
+ local k=c.kerns
+ local e=c.extrakerns
+ if l then
+ ligatures[u]=l
+ for u,v in next,l do
+ l[u]={ ligature=v }
+ 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
+ if e then
+ extrakerns[u]=e
+ for u,v in next,e do
+ e[u]=v
+ end
+ c.extrakerns=nil
+ 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
+ if next(extrakerns) then
+ features.gpos.extrakerns=everywhere
+ data.properties.haskerns=true
+ sequences[#sequences+1]={
+ features={
+ extrakerns=everywhere,
+ },
+ flags=noflags,
+ name="p_s_1",
+ nofsteps=1,
+ order={ "extrakerns" },
+ type="gpos_pair",
+ steps={
+ {
+ format="kern",
+ coverage=extrakerns,
+ },
+ },
+ }
+ end
+ data.resources.features=features
+ data.resources.sequences=sequences
+end
+fixnames=function(data)
+ for k,v in next,data.descriptions do
+ local n=v.name
+ local r=overloads[n]
+ if r then
+ local name=r.name
+ if trace_indexing then
+ report_afm("renaming characters %a to %a",n,name)
+ end
+ v.name=name
+ v.unicode=r.unicode
+ end
+ end
+end
+local addthem=function(rawdata,ligatures)
+ if ligatures then
+ local descriptions=rawdata.descriptions
+ local resources=rawdata.resources
+ local unicodes=resources.unicodes
+ for ligname,ligdata in next,ligatures do
+ local one=descriptions[unicodes[ligname]]
+ if one then
+ for _,pair in next,ligdata do
+ local two,three=unicodes[pair[1]],unicodes[pair[2]]
+ if two and three then
+ local ol=one.ligatures
+ if ol then
+ if not ol[two] then
+ ol[two]=three
end
+ else
+ one.ligatures={ [two]=three }
end
end
- local n=getnext(current)
- if n then
- local v=ischar(n,font)
- if v and nukta[v] then
- current=n
- n=getnext(current)
- end
- end
- syllableend=current
- current=n
- if current then
- local v=ischar(current,font)
- if not v then
- elseif halant[v] then
- local n=getnext(current)
- if n then
- local v=ischar(n,font)
- if v and zw_char[v] then
- syllableend=n
- current=getnext(n)
+ end
+ end
+ end
+ end
+end
+addligatures=function(rawdata) addthem(rawdata,afm.helpdata.ligatures ) end
+addtexligatures=function(rawdata) addthem(rawdata,afm.helpdata.texligatures) end
+addkerns=function(rawdata)
+ local descriptions=rawdata.descriptions
+ local resources=rawdata.resources
+ local unicodes=resources.unicodes
+ local function do_it_left(what)
+ if what then
+ for unicode,description in next,descriptions do
+ local kerns=description.kerns
+ if kerns then
+ local extrakerns
+ for complex,simple in next,what do
+ complex=unicodes[complex]
+ simple=unicodes[simple]
+ if complex and simple then
+ local ks=kerns[simple]
+ if ks and not kerns[complex] then
+ if extrakerns then
+ extrakerns[complex]=ks
else
- syllableend=current
- current=n
+ extrakerns={ [complex]=ks }
end
- else
- syllableend=current
- current=n
- end
- else
- if dependent_vowel[v] then
- syllableend=current
- current=getnext(current)
- v=ischar(current,font)
- end
- if v and vowel_modifier[v] then
- syllableend=current
- current=getnext(current)
- v=ischar(current,font)
- end
- if v and stress_tone_mark[v] then
- syllableend=current
- current=getnext(current)
end
end
end
- if syllablestart~=syllableend then
- head,current,nbspaces=deva_reorder(head,syllablestart,syllableend,font,attr,nbspaces)
- current=getnext(current)
+ if extrakerns then
+ description.extrakerns=extrakerns
end
- elseif independent_vowel[char] then
- syllableend=current
- current=getnext(current)
- if current then
- local v=ischar(current,font)
- if v then
- if vowel_modifier[v] then
- syllableend=current
- current=getnext(current)
- v=ischar(current,font)
+ end
+ end
+ end
+ end
+ local function do_it_copy(what)
+ if what then
+ for complex,simple in next,what do
+ complex=unicodes[complex]
+ simple=unicodes[simple]
+ if complex and simple then
+ local complexdescription=descriptions[complex]
+ if complexdescription then
+ local simpledescription=descriptions[complex]
+ if simpledescription then
+ local extrakerns
+ local kerns=simpledescription.kerns
+ if kerns then
+ for unicode,kern in next,kerns do
+ if extrakerns then
+ extrakerns[unicode]=kern
+ else
+ extrakerns={ [unicode]=kern }
+ end
+ end
end
- if v and stress_tone_mark[v] then
- syllableend=current
- current=getnext(current)
+ local extrakerns=simpledescription.extrakerns
+ if extrakerns then
+ for unicode,kern in next,extrakerns do
+ if extrakerns then
+ extrakerns[unicode]=kern
+ else
+ extrakerns={ [unicode]=kern }
+ end
+ end
+ end
+ if extrakerns then
+ complexdescription.extrakerns=extrakerns
end
end
end
+ end
+ end
+ end
+ end
+ do_it_left(afm.helpdata.leftkerned)
+ do_it_left(afm.helpdata.bothkerned)
+ do_it_copy(afm.helpdata.bothkerned)
+ do_it_copy(afm.helpdata.rightkerned)
+end
+local function adddimensions(data)
+ if data then
+ for unicode,description in next,data.descriptions do
+ local bb=description.boundingbox
+ if bb then
+ local ht,dp=bb[4],-bb[2]
+ if ht==0 or ht<0 then
else
- local mark=mark_four[char]
- if mark then
- head,current=inject_syntax_error(head,current,mark)
- end
- current=getnext(current)
+ description.height=ht
+ end
+ if dp==0 or dp<0 then
+ else
+ description.depth=dp
+ end
+ end
+ end
+ end
+end
+local function copytotfm(data)
+ if data and data.descriptions then
+ local metadata=data.metadata
+ local resources=data.resources
+ local properties=derivetable(data.properties)
+ local descriptions=derivetable(data.descriptions)
+ local goodies=derivetable(data.goodies)
+ local characters={}
+ local parameters={}
+ local unicodes=resources.unicodes
+ for unicode,description in next,data.descriptions do
+ characters[unicode]={}
+ end
+ local filename=constructors.checkedfilename(resources)
+ local fontname=metadata.fontname or metadata.fullname
+ local fullname=metadata.fullname or metadata.fontname
+ local endash=0x0020
+ local emdash=0x2014
+ local spacer="space"
+ local spaceunits=500
+ local monospaced=metadata.monospaced
+ local charwidth=metadata.charwidth
+ local italicangle=metadata.italicangle
+ local charxheight=metadata.xheight and metadata.xheight>0 and metadata.xheight
+ properties.monospaced=monospaced
+ parameters.italicangle=italicangle
+ parameters.charwidth=charwidth
+ parameters.charxheight=charxheight
+ if properties.monospaced then
+ if descriptions[endash] then
+ spaceunits,spacer=descriptions[endash].width,"space"
+ end
+ if not spaceunits and descriptions[emdash] then
+ spaceunits,spacer=descriptions[emdash].width,"emdash"
+ end
+ if not spaceunits and charwidth then
+ spaceunits,spacer=charwidth,"charwidth"
+ end
+ else
+ if descriptions[endash] then
+ spaceunits,spacer=descriptions[endash].width,"space"
+ end
+ if not spaceunits and charwidth then
+ spaceunits,spacer=charwidth,"charwidth"
+ end
+ end
+ spaceunits=tonumber(spaceunits)
+ if spaceunits<200 then
+ end
+ parameters.slant=0
+ parameters.space=spaceunits
+ parameters.space_stretch=500
+ parameters.space_shrink=333
+ parameters.x_height=400
+ parameters.quad=1000
+ if italicangle and italicangle~=0 then
+ parameters.italicangle=italicangle
+ parameters.italicfactor=math.cos(math.rad(90+italicangle))
+ parameters.slant=- math.tan(italicangle*math.pi/180)
+ end
+ if monospaced then
+ parameters.space_stretch=0
+ parameters.space_shrink=0
+ elseif afm.syncspace then
+ parameters.space_stretch=spaceunits/2
+ parameters.space_shrink=spaceunits/3
+ end
+ parameters.extra_space=parameters.space_shrink
+ if charxheight then
+ parameters.x_height=charxheight
+ else
+ local x=0x0078
+ if x then
+ local x=descriptions[x]
+ if x then
+ parameters.x_height=x.height
end
end
- else
- current=getnext(current)
end
- start=false
+ local fd=data.fontdimens
+ if fd and fd[8] and fd[9] and fd[10] then
+ for k,v in next,fd do
+ parameters[k]=v
+ end
+ end
+ parameters.designsize=(metadata.designsize or 10)*65536
+ parameters.ascender=abs(metadata.ascender or 0)
+ parameters.descender=abs(metadata.descender or 0)
+ parameters.units=1000
+ properties.spacer=spacer
+ properties.encodingbytes=2
+ properties.format=fonts.formats[filename] or "type1"
+ properties.filename=filename
+ properties.fontname=fontname
+ properties.fullname=fullname
+ properties.psname=fullname
+ properties.name=filename or fullname or fontname
+ if next(characters) then
+ return {
+ characters=characters,
+ descriptions=descriptions,
+ parameters=parameters,
+ resources=resources,
+ properties=properties,
+ goodies=goodies,
+ }
+ end
end
- if nbspaces>0 then
- head=replace_all_nbsp(head)
+ return nil
+end
+function afm.setfeatures(tfmdata,features)
+ local okay=constructors.initializefeatures("afm",tfmdata,features,trace_features,report_afm)
+ if okay then
+ return constructors.collectprocessors("afm",tfmdata,features,trace_features,report_afm)
+ else
+ return {}
end
- head=tonode(head)
- return head,done
end
-function methods.dev2(head,font,attr)
- head=tonut(head)
- local current=head
- local start=true
- local done=false
- local syllabe=0
- local nbspaces=0
- while current do
- local syllablestart=nil
- local syllableend=nil
- local char=ischar(current,font)
- if char then
- done=true
- syllablestart=current
- local c=current
- local n=getnext(current)
- if n and ra[char] then
- local nextchar=ischar(n,font)
- if nextchar and halant[nextchar] then
- local n=getnext(n)
- if n then
- local nextnextchar=ischar(n,font)
- if nextnextchar then
- c=n
- char=nextnextchar
- end
+local function addtables(data)
+ local resources=data.resources
+ local lookuptags=resources.lookuptags
+ local unicodes=resources.unicodes
+ if not lookuptags then
+ lookuptags={}
+ resources.lookuptags=lookuptags
+ end
+ setmetatableindex(lookuptags,function(t,k)
+ local v=type(k)=="number" and ("lookup "..k) or k
+ t[k]=v
+ return v
+ end)
+ if not unicodes then
+ unicodes={}
+ resources.unicodes=unicodes
+ setmetatableindex(unicodes,function(t,k)
+ setmetatableindex(unicodes,nil)
+ for u,d in next,data.descriptions do
+ local n=d.name
+ if n then
+ t[n]=u
+ end
+ end
+ return rawget(t,k)
+ end)
+ end
+ constructors.addcoreunicodes(unicodes)
+end
+local function afmtotfm(specification)
+ local afmname=specification.filename or specification.name
+ if specification.forced=="afm" or specification.format=="afm" then
+ if trace_loading then
+ report_afm("forcing afm format for %a",afmname)
+ end
+ else
+ local tfmname=findbinfile(afmname,"ofm") or ""
+ if tfmname~="" then
+ if trace_loading then
+ report_afm("fallback from afm to tfm for %a",afmname)
+ end
+ return
+ end
+ end
+ if afmname~="" then
+ local features=constructors.checkedfeatures("afm",specification.features.normal)
+ specification.features.normal=features
+ constructors.hashinstance(specification,true)
+ specification=definers.resolve(specification)
+ local cache_id=specification.hash
+ local tfmdata=containers.read(constructors.cache,cache_id)
+ if not tfmdata then
+ local rawdata=afm.load(afmname)
+ if rawdata and next(rawdata) then
+ addtables(rawdata)
+ adddimensions(rawdata)
+ tfmdata=copytotfm(rawdata)
+ if tfmdata and next(tfmdata) then
+ local shared=tfmdata.shared
+ if not shared then
+ shared={}
+ tfmdata.shared=shared
end
+ shared.rawdata=rawdata
+ shared.dynamics={}
+ tfmdata.changed={}
+ shared.features=features
+ shared.processes=afm.setfeatures(tfmdata,features)
end
+ elseif trace_loading then
+ report_afm("no (valid) afm file found with name %a",afmname)
end
- if independent_vowel[char] then
- current=analyze_next_chars_one(c,font,1)
- syllableend=current
- else
- local standalone=char==c_nbsp
- if standalone then
- nbspaces=nbspaces+1
- local p=getprev(current)
- if not p then
- elseif ischar(p,font) then
- elseif not separator[getchar(p)] then
- else
- standalone=false
+ tfmdata=containers.write(constructors.cache,cache_id,tfmdata)
+ end
+ return tfmdata
+ end
+end
+local function read_from_afm(specification)
+ local tfmdata=afmtotfm(specification)
+ if tfmdata then
+ tfmdata.properties.name=specification.name
+ tfmdata=constructors.scale(tfmdata,specification)
+ local allfeatures=tfmdata.shared.features or specification.features.normal
+ constructors.applymanipulators("afm",tfmdata,allfeatures,trace_features,report_afm)
+ fonts.loggers.register(tfmdata,'afm',specification)
+ end
+ return tfmdata
+end
+local function prepareligatures(tfmdata,ligatures,value)
+ if value then
+ local descriptions=tfmdata.descriptions
+ local hasligatures=false
+ for unicode,character in next,tfmdata.characters do
+ local description=descriptions[unicode]
+ local dligatures=description.ligatures
+ if dligatures then
+ local cligatures=character.ligatures
+ if not cligatures then
+ cligatures={}
+ character.ligatures=cligatures
+ end
+ for unicode,ligature in next,dligatures do
+ cligatures[unicode]={
+ char=ligature,
+ type=0
+ }
+ end
+ hasligatures=true
+ end
+ end
+ tfmdata.properties.hasligatures=hasligatures
+ end
+end
+local function preparekerns(tfmdata,kerns,value)
+ if value then
+ local rawdata=tfmdata.shared.rawdata
+ local resources=rawdata.resources
+ local unicodes=resources.unicodes
+ local descriptions=tfmdata.descriptions
+ local haskerns=false
+ for u,chr in next,tfmdata.characters do
+ local d=descriptions[u]
+ local newkerns=d[kerns]
+ if newkerns then
+ local kerns=chr.kerns
+ if not kerns then
+ kerns={}
+ chr.kerns=kerns
+ end
+ for k,v in next,newkerns do
+ local uk=unicodes[k]
+ if uk then
+ kerns[uk]=v
end
end
- if standalone then
- current=analyze_next_chars_one(c,font,2)
- syllableend=current
- elseif consonant[getchar(current)] then
- current=analyze_next_chars_two(current,font)
- syllableend=current
+ haskerns=true
+ end
+ end
+ tfmdata.properties.haskerns=haskerns
+ end
+end
+local list={
+ [0x0027]=0x2019,
+}
+local function texreplacements(tfmdata,value)
+ local descriptions=tfmdata.descriptions
+ local characters=tfmdata.characters
+ for k,v in next,list do
+ characters [k]=characters [v]
+ descriptions[k]=descriptions[v]
+ end
+end
+local function extrakerns (tfmdata,value) preparekerns (tfmdata,'extrakerns',value) 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,
+ }
+}
+registerafmfeature {
+ name="features",
+ description="features",
+ default=true,
+ initializers={
+ node=otf.nodemodeinitializer,
+ base=otf.basemodeinitializer,
+ },
+ processors={
+ node=otf.featuresprocessor,
+ }
+}
+local check_tfm=readers.check_tfm
+fonts.formats.afm="type1"
+fonts.formats.pfb="type1"
+local function check_afm(specification,fullname)
+ local foundname=findbinfile(fullname,'afm') or ""
+ if foundname=="" then
+ foundname=fonts.names.getfilename(fullname,"afm") or ""
+ end
+ if foundname=="" and afm.autoprefixed then
+ local encoding,shortname=match(fullname,"^(.-)%-(.*)$")
+ if encoding and shortname and fonts.encodings.known[encoding] then
+ shortname=findbinfile(shortname,'afm') or ""
+ if shortname~="" then
+ foundname=shortname
+ if trace_defining then
+ report_afm("stripping encoding prefix from filename %a",afmname)
end
end
end
- if syllableend then
- syllabe=syllabe+1
- local c=syllablestart
- local n=getnext(syllableend)
- while c~=n do
- setprop(c,a_syllabe,syllabe)
- c=getnext(c)
- end
- end
- if syllableend and syllablestart~=syllableend then
- head,current,nbspaces=dev2_reorder(head,syllablestart,syllableend,font,attr,nbspaces)
+ end
+ if foundname~="" then
+ specification.filename=foundname
+ specification.format="afm"
+ return read_from_afm(specification)
+ end
+end
+function readers.afm(specification,method)
+ local fullname,tfmdata=specification.filename or "",nil
+ if fullname=="" then
+ local forced=specification.forced or ""
+ if forced~="" then
+ tfmdata=check_afm(specification,specification.name.."."..forced)
end
- if not syllableend then
- local char=ischar(current,font)
- if char and not getprop(current,a_state) then
- local mark=mark_four[char]
- if mark then
- head,current=inject_syntax_error(head,current,mark)
- end
+ if not tfmdata then
+ method=method or definers.method or "afm or tfm"
+ if method=="tfm" then
+ tfmdata=check_tfm(specification,specification.name)
+ elseif method=="afm" then
+ tfmdata=check_afm(specification,specification.name)
+ elseif method=="tfm or afm" then
+ tfmdata=check_tfm(specification,specification.name) or check_afm(specification,specification.name)
+ else
+ tfmdata=check_afm(specification,specification.name) or check_tfm(specification,specification.name)
end
end
- start=false
- current=getnext(current)
+ else
+ tfmdata=check_afm(specification,fullname)
end
- if nbspaces>0 then
- head=replace_all_nbsp(head)
+ return tfmdata
+end
+function readers.pfb(specification,method)
+ local original=specification.specification
+ if trace_defining then
+ report_afm("using afm reader for %a",original)
end
- head=tonode(head)
- return head,done
+ specification.specification=gsub(original,"%.pfb",".afm")
+ specification.forced="afm"
+ return readers.afm(specification,method)
end
-methods.mlym=methods.deva
-methods.mlm2=methods.dev2
+
+end -- closure
+
+do -- begin closure to overcome local limits and interference
+
+if not modules then modules={} end modules ['font-afk']={
+ version=1.001,
+ comment="companion to font-afm.lua",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files",
+ dataonly=true,
+}
+local allocate=utilities.storage.allocate
+fonts.handlers.afm.helpdata={
+ ligatures=allocate {
+ ['f']={
+ { 'f','ff' },
+ { 'i','fi' },
+ { 'l','fl' },
+ },
+ ['ff']={
+ { 'i','ffi' }
+ },
+ ['fi']={
+ { 'i','fii' }
+ },
+ ['fl']={
+ { 'i','fli' }
+ },
+ ['s']={
+ { 't','st' }
+ },
+ ['i']={
+ { 'j','ij' }
+ },
+ },
+ texligatures=allocate {
+ ['quoteleft']={
+ { 'quoteleft','quotedblleft' }
+ },
+ ['quoteright']={
+ { 'quoteright','quotedblright' }
+ },
+ ['hyphen']={
+ { 'hyphen','endash' }
+ },
+ ['endash']={
+ { 'hyphen','emdash' }
+ }
+ },
+ leftkerned=allocate {
+ AEligature="A",aeligature="a",
+ OEligature="O",oeligature="o",
+ IJligature="I",ijligature="i",
+ AE="A",ae="a",
+ OE="O",oe="o",
+ IJ="I",ij="i",
+ Ssharp="S",ssharp="s",
+ },
+ rightkerned=allocate {
+ AEligature="E",aeligature="e",
+ OEligature="E",oeligature="e",
+ IJligature="J",ijligature="j",
+ AE="E",ae="e",
+ OE="E",oe="e",
+ IJ="J",ij="j",
+ Ssharp="S",ssharp="s",
+ },
+ bothkerned=allocate {
+ Acircumflex="A",acircumflex="a",
+ Ccircumflex="C",ccircumflex="c",
+ Ecircumflex="E",ecircumflex="e",
+ Gcircumflex="G",gcircumflex="g",
+ Hcircumflex="H",hcircumflex="h",
+ Icircumflex="I",icircumflex="i",
+ Jcircumflex="J",jcircumflex="j",
+ Ocircumflex="O",ocircumflex="o",
+ Scircumflex="S",scircumflex="s",
+ Ucircumflex="U",ucircumflex="u",
+ Wcircumflex="W",wcircumflex="w",
+ Ycircumflex="Y",ycircumflex="y",
+ Agrave="A",agrave="a",
+ Egrave="E",egrave="e",
+ Igrave="I",igrave="i",
+ Ograve="O",ograve="o",
+ Ugrave="U",ugrave="u",
+ Ygrave="Y",ygrave="y",
+ Atilde="A",atilde="a",
+ Itilde="I",itilde="i",
+ Otilde="O",otilde="o",
+ Utilde="U",utilde="u",
+ Ntilde="N",ntilde="n",
+ Adiaeresis="A",adiaeresis="a",Adieresis="A",adieresis="a",
+ Ediaeresis="E",ediaeresis="e",Edieresis="E",edieresis="e",
+ Idiaeresis="I",idiaeresis="i",Idieresis="I",idieresis="i",
+ Odiaeresis="O",odiaeresis="o",Odieresis="O",odieresis="o",
+ Udiaeresis="U",udiaeresis="u",Udieresis="U",udieresis="u",
+ Ydiaeresis="Y",ydiaeresis="y",Ydieresis="Y",ydieresis="y",
+ Aacute="A",aacute="a",
+ Cacute="C",cacute="c",
+ Eacute="E",eacute="e",
+ Iacute="I",iacute="i",
+ Lacute="L",lacute="l",
+ Nacute="N",nacute="n",
+ Oacute="O",oacute="o",
+ Racute="R",racute="r",
+ Sacute="S",sacute="s",
+ Uacute="U",uacute="u",
+ Yacute="Y",yacute="y",
+ Zacute="Z",zacute="z",
+ Dstroke="D",dstroke="d",
+ Hstroke="H",hstroke="h",
+ Tstroke="T",tstroke="t",
+ Cdotaccent="C",cdotaccent="c",
+ Edotaccent="E",edotaccent="e",
+ Gdotaccent="G",gdotaccent="g",
+ Idotaccent="I",idotaccent="i",
+ Zdotaccent="Z",zdotaccent="z",
+ Amacron="A",amacron="a",
+ Emacron="E",emacron="e",
+ Imacron="I",imacron="i",
+ Omacron="O",omacron="o",
+ Umacron="U",umacron="u",
+ Ccedilla="C",ccedilla="c",
+ Kcedilla="K",kcedilla="k",
+ Lcedilla="L",lcedilla="l",
+ Ncedilla="N",ncedilla="n",
+ Rcedilla="R",rcedilla="r",
+ Scedilla="S",scedilla="s",
+ Tcedilla="T",tcedilla="t",
+ Ohungarumlaut="O",ohungarumlaut="o",
+ Uhungarumlaut="U",uhungarumlaut="u",
+ Aogonek="A",aogonek="a",
+ Eogonek="E",eogonek="e",
+ Iogonek="I",iogonek="i",
+ Uogonek="U",uogonek="u",
+ Aring="A",aring="a",
+ Uring="U",uring="u",
+ Abreve="A",abreve="a",
+ Ebreve="E",ebreve="e",
+ Gbreve="G",gbreve="g",
+ Ibreve="I",ibreve="i",
+ Obreve="O",obreve="o",
+ Ubreve="U",ubreve="u",
+ Ccaron="C",ccaron="c",
+ Dcaron="D",dcaron="d",
+ Ecaron="E",ecaron="e",
+ Lcaron="L",lcaron="l",
+ Ncaron="N",ncaron="n",
+ Rcaron="R",rcaron="r",
+ Scaron="S",scaron="s",
+ Tcaron="T",tcaron="t",
+ Zcaron="Z",zcaron="z",
+ dotlessI="I",dotlessi="i",
+ dotlessJ="J",dotlessj="j",
+ AEligature="AE",aeligature="ae",AE="AE",ae="ae",
+ OEligature="OE",oeligature="oe",OE="OE",oe="oe",
+ IJligature="IJ",ijligature="ij",IJ="IJ",ij="ij",
+ Lstroke="L",lstroke="l",Lslash="L",lslash="l",
+ Ostroke="O",ostroke="o",Oslash="O",oslash="o",
+ Ssharp="SS",ssharp="ss",
+ Aumlaut="A",aumlaut="a",
+ Eumlaut="E",eumlaut="e",
+ Iumlaut="I",iumlaut="i",
+ Oumlaut="O",oumlaut="o",
+ Uumlaut="U",uumlaut="u",
+ }
+}
end -- closure
@@ -24164,17 +24189,18 @@ function nodes.handlers.nodepass(head)
local variant=hash[getchar(p)]
if variant then
setchar(p,variant)
- if not redundant then
- redundant={ n }
- else
- redundant[#redundant+1]=n
- end
end
end
end
+ if not redundant then
+ redundant={ n }
+ else
+ redundant[#redundant+1]=n
+ end
end
end
end
+ local nofbasefonts=#basefonts
if redundant then
for i=1,#redundant do
local r=redundant[i]
@@ -24185,8 +24211,8 @@ function nodes.handlers.nodepass(head)
else
setlink(p,n)
end
- if b>0 then
- for i=1,b do
+ if nofbasefonts>0 then
+ for i=1,nofbasefonts do
local bi=basefonts[i]
if r==bi[1] then
bi[1]=n
@@ -24230,8 +24256,8 @@ function nodes.handlers.nodepass(head)
end
end
end
- if basemodepass and #basefonts>0 then
- for i=1,#basefonts do
+ if basemodepass and nofbasefonts>0 then
+ for i=1,nofbasefonts do
local range=basefonts[i]
local start=range[1]
local stop=range[2]
--
cgit v1.2.3
From ad8c9fb7abbcd547dcc63e33abee2f2172c750eb Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Mon, 9 May 2016 07:23:40 +0200
Subject: [import,fontloader] pull new AFM/Type1 code
---
doc/filegraph.dot | 2 +-
doc/luaotfload-main.tex | 2 +-
scripts/mkimport | 34 +-
scripts/mkstatus | 2 +-
src/fontloader/misc/fontloader-font-afm.lua | 1206 --------------------------
src/fontloader/misc/fontloader-font-one.lua | 1220 +++++++++++++++++++++++++++
src/luaotfload-init.lua | 8 +-
src/luaotfload-tool.lua | 4 +-
8 files changed, 1246 insertions(+), 1232 deletions(-)
delete mode 100644 src/fontloader/misc/fontloader-font-afm.lua
create mode 100644 src/fontloader/misc/fontloader-font-one.lua
diff --git a/doc/filegraph.dot b/doc/filegraph.dot
index b274461..0c2dad1 100644
--- a/doc/filegraph.dot
+++ b/doc/filegraph.dot
@@ -356,7 +356,7 @@ strict digraph luaotfload_files { //looks weird with circo ...
font-tfm.lua |
- font-afm.lua |
+ font-one.lua |
font-afk.lua |
font-oti.lua |
diff --git a/doc/luaotfload-main.tex b/doc/luaotfload-main.tex
index 05c3670..bebb7df 100644
--- a/doc/luaotfload-main.tex
+++ b/doc/luaotfload-main.tex
@@ -1279,7 +1279,7 @@ grouped twofold as below:
\beginaltitem{font-cid.lua} \endaltitem
\beginaltitem{font-map.lua} \endaltitem
\beginaltitem{font-tfm.lua} \endaltitem
- \beginaltitem{font-afm.lua} \endaltitem
+ \beginaltitem{font-one.lua} \endaltitem
\beginaltitem{font-afk.lua} \endaltitem
\beginaltitem{font-oti.lua} \endaltitem
\beginaltitem{font-otr.lua} \endaltitem
diff --git a/scripts/mkimport b/scripts/mkimport
index 25d7560..e2b6f72 100755
--- a/scripts/mkimport
+++ b/scripts/mkimport
@@ -228,7 +228,6 @@ local imports = {
context = { --=> all merged
{ name = "data-con" , ours = "data-con" , kind = kind_merged },
{ name = "font-afk" , ours = "font-afk" , kind = kind_merged },
- { name = "font-afm" , ours = "font-afm" , kind = kind_merged },
{ name = "font-cff" , ours = "font-cff" , kind = kind_merged },
{ name = "font-cid" , ours = "font-cid" , kind = kind_merged },
{ name = "font-con" , ours = "font-con" , kind = kind_merged },
@@ -238,6 +237,7 @@ local imports = {
{ name = "font-ini" , ours = "font-ini" , kind = kind_merged },
{ name = "font-lua" , ours = "font-lua" , kind = kind_merged },
{ name = "font-map" , ours = "font-map" , kind = kind_merged },
+ { name = "font-one" , ours = "font-one" , kind = kind_merged },
{ name = "font-osd" , ours = "font-osd" , kind = kind_merged },
{ name = "font-ota" , ours = "font-ota" , kind = kind_merged },
{ name = "font-otd" , ours = "font-otd" , kind = kind_merged },
@@ -294,20 +294,20 @@ local package = {
--- [20] font-map.lua
--- [21] luatex-fonts-syn.lua
--- [22] font-tfm.lua
---- [23] font-afm.lua
---- [24] font-afk.lua
---- [25] font-oti.lua
---- [26] font-otr.lua
---- [27] font-cff.lua
---- [28] font-ttf.lua
---- [29] font-dsp.lua
---- [30] font-oup.lua
---- [31] font-otl.lua
---- [32] font-oto.lua
---- [33] font-otj.lua
---- [34] font-ota.lua
---- [35] font-ots.lua
---- [36] font-osd.lua
+--- [23] font-oti.lua
+--- [24] font-otr.lua
+--- [25] font-cff.lua
+--- [26] font-ttf.lua
+--- [27] font-dsp.lua
+--- [28] font-oup.lua
+--- [29] font-otl.lua
+--- [30] font-oto.lua
+--- [31] font-otj.lua
+--- [32] font-ota.lua
+--- [33] font-ots.lua
+--- [34] font-osd.lua
+--- [35] font-one.lua
+--- [36] font-afk.lua
--- [37] font-lua.lua
--- [38] font-def.lua
--- [39] font-xtx.lua
@@ -358,8 +358,6 @@ local package = {
"font-map",
"fonts-syn",
"font-tfm",
- "font-afm",
- "font-afk",
"font-oti",
"font-otr",
"font-cff",
@@ -372,6 +370,8 @@ local package = {
"font-ota",
"font-ots",
"font-osd",
+ "font-one",
+ "font-afk",
"font-lua",
"font-def",
"fonts-ext",
diff --git a/scripts/mkstatus b/scripts/mkstatus
index f9ff7eb..6a05833 100755
--- a/scripts/mkstatus
+++ b/scripts/mkstatus
@@ -84,7 +84,7 @@ local names = {
{ miscdir, "fontloader-basics-nod.lua", },
{ miscdir, "fontloader-data-con.lua", },
{ miscdir, "fontloader-font-afk.lua", },
- { miscdir, "fontloader-font-afm.lua", },
+ { miscdir, "fontloader-font-one.lua", },
{ miscdir, "fontloader-font-cid.lua", },
{ miscdir, "fontloader-font-con.lua", },
{ miscdir, "fontloader-font-def.lua", },
diff --git a/src/fontloader/misc/fontloader-font-afm.lua b/src/fontloader/misc/fontloader-font-afm.lua
deleted file mode 100644
index 0d6b7cb..0000000
--- a/src/fontloader/misc/fontloader-font-afm.lua
+++ /dev/null
@@ -1,1206 +0,0 @@
-if not modules then modules = { } end modules ['font-afm'] = {
- 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"
-}
-
---[[ldx--
-Some code may look a bit obscure but this has to do with the
-fact that we also use this code for testing and much code evolved
-in the transition from to to .
-
-The following code still has traces of intermediate font support
-where we handles font encodings. Eventually font encoding goes
-away.
-
-The embedding of a font involves creating temporary files and
-depending on your system setup that can fail. It took more than a
-day to figure out why sometimes embedding failed in mingw luatex
-where running on a real path like c:\... failed while running on
-say e:\... being a link worked well. The native windows binaries
-don't have this issue.
-
---ldx]]--
-
-local fonts, logs, trackers, containers, resolvers = fonts, logs, trackers, containers, resolvers
-
-local next, type, tonumber = next, type, tonumber
-local match, gmatch, lower, gsub, strip, find = string.match, string.gmatch, 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, lpegmatch, patterns = lpeg.P, lpeg.S, lpeg.R, lpeg.Cmt, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.match, lpeg.patterns
-local derivetable = table.derive
-
-local trace_features = false trackers.register("afm.features", function(v) trace_features = v end)
-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 trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end)
-
-local report_afm = logs.reporter("fonts","afm loading")
-
-local setmetatableindex = table.setmetatableindex
-
-local findbinfile = resolvers.findbinfile
-
-local definers = fonts.definers
-local readers = fonts.readers
-local constructors = fonts.constructors
-
-local afm = constructors.newhandler("afm")
-local pfb = constructors.newhandler("pfb")
-
-local afmfeatures = constructors.newfeatures("afm")
-local registerafmfeature = afmfeatures.register
-
-afm.version = 1.501 -- incrementing this number one up will force a re-cache
-afm.cache = containers.define("fonts", "afm", afm.version, true)
-afm.autoprefixed = true -- this will become false some day (catches texnansi-blabla.*)
-
-afm.helpdata = { } -- set later on so no local for this
-afm.syncspace = true -- when true, nicer stretch values
-afm.addligatures = true -- best leave this set to true
-afm.addtexligatures = true -- best leave this set to true
-afm.addkerns = true -- best leave this set to true
-
-local overloads = fonts.mappings.overloads
-
-local applyruntimefixes = fonts.treatments and fonts.treatments.applyfixes
-
-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,
- }
-}
-
---[[ldx--
-We start with the basic reader which we give a name similar to the
-built in and reader.
---ldx]]--
-
---~ Comment FONTIDENTIFIER LMMATHSYMBOLS10
---~ Comment CODINGSCHEME TEX MATH SYMBOLS
---~ Comment DESIGNSIZE 10.0 pt
---~ Comment CHECKSUM O 4261307036
---~ Comment SPACE 0 plus 0 minus 0
---~ Comment QUAD 1000
---~ Comment EXTRASPACE 0
---~ Comment NUM 676.508 393.732 443.731
---~ Comment DENOM 685.951 344.841
---~ Comment SUP 412.892 362.892 288.889
---~ Comment SUB 150 247.217
---~ Comment SUPDROP 386.108
---~ Comment SUBDROP 50
---~ Comment DELIM 2390 1010
---~ Comment AXISHEIGHT 250
-
-local comment = P("Comment")
-local spacing = patterns.spacer -- S(" \t")^1
-local lineend = patterns.newline -- S("\n\r")
-local words = C((1 - lineend)^1)
-local number = C((R("09") + S("."))^1) / tonumber * spacing^0
-local data = lpeg.Carg(1)
-
-local pattern = ( -- needs testing ... not used anyway as we no longer need math afm's
- comment * spacing *
- (
- data * (
- ("CODINGSCHEME" * spacing * words ) / function(fd,a) end +
- ("DESIGNSIZE" * spacing * number * words ) / function(fd,a) fd[ 1] = a end +
- ("CHECKSUM" * spacing * number * words ) / function(fd,a) fd[ 2] = a end +
- ("SPACE" * spacing * number * "plus" * number * "minus" * number) / function(fd,a,b,c) fd[ 3], fd[ 4], fd[ 5] = a, b, c end +
- ("QUAD" * spacing * number ) / function(fd,a) fd[ 6] = a end +
- ("EXTRASPACE" * spacing * number ) / function(fd,a) fd[ 7] = a end +
- ("NUM" * spacing * number * number * number ) / function(fd,a,b,c) fd[ 8], fd[ 9], fd[10] = a, b, c end +
- ("DENOM" * spacing * number * number ) / function(fd,a,b ) fd[11], fd[12] = a, b end +
- ("SUP" * spacing * number * number * number ) / function(fd,a,b,c) fd[13], fd[14], fd[15] = a, b, c end +
- ("SUB" * spacing * number * number ) / function(fd,a,b) fd[16], fd[17] = a, b end +
- ("SUPDROP" * spacing * number ) / function(fd,a) fd[18] = a end +
- ("SUBDROP" * spacing * number ) / function(fd,a) fd[19] = a end +
- ("DELIM" * spacing * number * number ) / function(fd,a,b) fd[20], fd[21] = a, b end +
- ("AXISHEIGHT" * spacing * number ) / function(fd,a) fd[22] = a end
- )
- + (1-lineend)^0
- )
- + (1-comment)^1
-)^0
-
-local function scan_comment(str)
- local fd = { }
- lpegmatch(pattern,str,1,fd)
- return fd
-end
-
--- On a rainy day I will rewrite this in lpeg ... or we can use the (slower) fontloader
--- as in now supports afm/pfb loading but it's not too bad to have different methods
--- for testing approaches.
-
-local keys = { }
-
-function keys.FontName (data,line) data.metadata.fontname = strip (line) -- get rid of spaces
- data.metadata.fullname = strip (line) end
-function keys.ItalicAngle (data,line) data.metadata.italicangle = tonumber (line) 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
-function keys.Ascender (data,line) data.metadata.ascender = tonumber (line) end
-function keys.Comment (data,line)
- -- Comment DesignSize 12 (pts)
- -- Comment TFM designsize: 12 (in points)
- line = lower(line)
- local designsize = match(line,"designsize[^%d]*(%d+)")
- if designsize then data.metadata.designsize = tonumber(designsize) end
-end
-
-local function get_charmetrics(data,charmetrics,vector)
- local characters = data.characters
- local chr, ind = { }, 0
- for k, v in gmatch(charmetrics,"([%a]+) +(.-) *;") do
- if k == 'C' then
- v = tonumber(v)
- if v < 0 then
- ind = ind + 1 -- ?
- else
- ind = v
- end
- chr = {
- index = ind
- }
- elseif k == 'WX' then
- chr.width = tonumber(v)
- elseif k == 'N' then
- characters[v] = chr
- elseif k == 'B' then
- local llx, lly, urx, ury = match(v,"^ *(.-) +(.-) +(.-) +(.-)$")
- chr.boundingbox = { tonumber(llx), tonumber(lly), tonumber(urx), tonumber(ury) }
- elseif k == 'L' then
- local plus, becomes = match(v,"^(.-) +(.-)$")
- local ligatures = chr.ligatures
- if ligatures then
- ligatures[plus] = becomes
- else
- chr.ligatures = { [plus] = becomes }
- end
- end
- end
-end
-
-local function get_kernpairs(data,kernpairs)
- local characters = data.characters
- for one, two, value in gmatch(kernpairs,"KPX +(.-) +(.-) +(.-)\n") do
- local chr = characters[one]
- if chr then
- local kerns = chr.kerns
- if kerns then
- kerns[two] = tonumber(value)
- else
- chr.kerns = { [two] = tonumber(value) }
- end
- end
- end
-end
-
-local function get_variables(data,fontmetrics)
- for key, rest in gmatch(fontmetrics,"(%a+) *(.-)[\n\r]") do
- local keyhandler = keys[key]
- if keyhandler then
- keyhandler(data,rest)
- end
- end
-end
-
-local get_indexes
-
-do
-
- -- old font loader
-
- local fontloader = fontloader
- local get_indexes_old = false
-
- if fontloader then
-
- local font_to_table = fontloader.to_table
- local open_font = fontloader.open
- local close_font = fontloader.close
-
- get_indexes_old = function(data,pfbname)
- local pfbblob = open_font(pfbname)
- if pfbblob then
- local characters = data.characters
- local pfbdata = font_to_table(pfbblob)
- if pfbdata then
- local glyphs = pfbdata.glyphs
- if glyphs then
- if trace_loading then
- report_afm("getting index data from %a",pfbname)
- end
- for index, glyph in next, glyphs do
- local name = glyph.name
- if name then
- local char = characters[name]
- if char then
- if trace_indexing then
- report_afm("glyph %a has index %a",name,index)
- end
- char.index = index
- end
- end
- end
- elseif trace_loading then
- report_afm("no glyph data in pfb file %a",pfbname)
- end
- elseif trace_loading then
- report_afm("no data in pfb file %a",pfbname)
- end
- close_font(pfbblob)
- elseif trace_loading then
- report_afm("invalid pfb file %a",pfbname)
- end
- end
-
- end
-
- -- new (unfinished) font loader but i see no differences between
- -- old and new (one bad vector with old)
-
- local n, m
-
- local progress = function(str,position,name,size)
- local forward = position + tonumber(size) + 3 + 2
- n = n + 1
- if n >= m then
- return #str, name
- elseif forward < #str then
- return forward, name
- else
- return #str, name
- end
- end
-
- local initialize = function(str,position,size)
- n = 0
- m = tonumber(size)
- return position + 1
- end
-
- local charstrings = P("/CharStrings")
- local name = P("/") * C((R("az")+R("AZ")+R("09")+S("-_."))^1)
- local size = C(R("09")^1)
- local spaces = P(" ")^1
-
- local p_filternames = Ct (
- (1-charstrings)^0 * charstrings * spaces * Cmt(size,initialize)
- * (Cmt(name * P(" ")^1 * C(R("09")^1), progress) + P(1))^1
- )
-
- -- if one of first 4 not 0-9A-F then binary else hex
-
- local decrypt
-
- do
-
- local r, c1, c2, n = 0, 0, 0, 0
-
- local function step(c)
- local cipher = byte(c)
- local plain = bxor(cipher,rshift(r,8))
- r = ((cipher + r) * c1 + c2) % 65536
- return char(plain)
- end
-
- decrypt = function(binary)
- r, c1, c2, n = 55665, 52845, 22719, 4
- binary = gsub(binary,".",step)
- return sub(binary,n+1)
- end
-
- -- local pattern = Cs((P(1) / step)^1)
- --
- -- decrypt = function(binary)
- -- r, c1, c2, n = 55665, 52845, 22719, 4
- -- binary = lpegmatch(pattern,binary)
- -- return sub(binary,n+1)
- -- end
-
- end
-
- local function loadpfbvector(filename)
- -- for the moment limited to encoding only
-
- local data = io.loaddata(resolvers.findfile(filename))
-
- if not find(data,"!PS%-AdobeFont%-") then
- print("no font",filename)
- return
- end
-
- if not data then
- print("no data",filename)
- return
- end
-
- local ascii, binary = match(data,"(.*)eexec%s+......(.*)")
-
- if not binary then
- print("no binary",filename)
- return
- end
-
- binary = decrypt(binary,4)
-
- local vector = lpegmatch(p_filternames,binary)
-
- vector[0] = table.remove(vector,1)
-
- if not vector then
- print("no vector",filename)
- return
- end
-
- return vector
-
- end
-
- get_indexes = function(data,pfbname)
- local vector = loadpfbvector(pfbname)
- if vector then
- local characters = data.characters
- if trace_loading then
- report_afm("getting index data from %a",pfbname)
- end
- for index=1,#vector do
- local name = vector[index]
- local char = characters[name]
- if char then
- if trace_indexing then
- report_afm("glyph %a has index %a",name,index)
- end
- char.index = index
- end
- end
- end
- end
-
- if get_indexes_old then
-
- afm.use_new_indexer = true
- get_indexes_new = get_indexes
-
- get_indexes = function(data,pfbname)
- if afm.use_new_indexer then
- return get_indexes_new(data,pfbname)
- else
- return get_indexes_old(data,pfbname)
- end
- end
-
- end
-
-end
-
-local function readafm(filename)
- local ok, afmblob, size = resolvers.loadbinfile(filename) -- has logging
- if ok and afmblob then
- local data = {
- resources = {
- filename = resolvers.unresolve(filename),
- version = afm.version,
- creator = "context mkiv",
- },
- properties = {
- hasitalics = false,
- },
- goodies = {
- },
- metadata = {
- filename = file.removesuffix(file.basename(filename))
- },
- characters = {
- -- a temporary store
- },
- descriptions = {
- -- the final store
- },
- }
- afmblob = gsub(afmblob,"StartCharMetrics(.-)EndCharMetrics", function(charmetrics)
- if trace_loading then
- report_afm("loading char metrics")
- end
- get_charmetrics(data,charmetrics,vector)
- return ""
- end)
- afmblob = gsub(afmblob,"StartKernPairs(.-)EndKernPairs", function(kernpairs)
- if trace_loading then
- report_afm("loading kern pairs")
- end
- get_kernpairs(data,kernpairs)
- return ""
- end)
- afmblob = gsub(afmblob,"StartFontMetrics%s+([%d%.]+)(.-)EndFontMetrics", function(version,fontmetrics)
- if trace_loading then
- report_afm("loading variables")
- end
- data.afmversion = version
- get_variables(data,fontmetrics)
- data.fontdimens = scan_comment(fontmetrics) -- todo: all lpeg, no time now
- return ""
- end)
- return data
- else
- if trace_loading then
- report_afm("no valid afm file %a",filename)
- end
- return nil
- end
-end
-
---[[ldx--
-We cache files. Caching is taken care of in the loader. We cheat a bit
-by adding ligatures and kern information to the afm derived data. That
-way we can set them faster when defining a font.
---ldx]]--
-
-local addkerns, addligatures, addtexligatures, unify, normalize, fixnames -- we will implement these later
-
-function afm.load(filename)
- -- hm, for some reasons not resolved yet
- filename = resolvers.findfile(filename,'afm') or ""
- if filename ~= "" and not fonts.names.ignoredfile(filename) then
- local name = file.removesuffix(file.basename(filename))
- local data = containers.read(afm.cache,name)
- local attr = lfs.attributes(filename)
- local size, time = attr.size or 0, attr.modification or 0
- --
- local pfbfile = file.replacesuffix(name,"pfb")
- local pfbname = resolvers.findfile(pfbfile,"pfb") or ""
- if pfbname == "" then
- pfbname = resolvers.findfile(file.basename(pfbfile),"pfb") or ""
- end
- local pfbsize, pfbtime = 0, 0
- if pfbname ~= "" then
- local attr = lfs.attributes(pfbname)
- pfbsize = attr.size or 0
- pfbtime = attr.modification or 0
- end
- if not data or data.size ~= size or data.time ~= time or data.pfbsize ~= pfbsize or data.pfbtime ~= pfbtime then
- report_afm("reading %a",filename)
- data = readafm(filename)
- if data then
- if pfbname ~= "" then
- data.resources.filename = resolvers.unresolve(pfbname)
- get_indexes(data,pfbname)
- elseif trace_loading then
- report_afm("no pfb file for %a",filename)
- -- data.resources.filename = "unset" -- better than loading the afm file
- end
- report_afm("unifying %a",filename)
- unify(data,filename)
- if afm.addligatures then
- report_afm("add ligatures")
- addligatures(data)
- end
- if afm.addtexligatures then
- report_afm("add tex ligatures")
- addtexligatures(data)
- end
- if afm.addkerns then
- report_afm("add extra kerns")
- addkerns(data)
- end
- normalize(data)
- fixnames(data)
- report_afm("add tounicode data")
- fonts.mappings.addtounicode(data,filename)
- data.size = size
- data.time = time
- data.pfbsize = pfbsize
- data.pfbtime = pfbtime
- report_afm("saving %a in cache",name)
- data.resources.unicodes = nil -- consistent with otf but here we save not much
- data = containers.write(afm.cache, name, data)
- data = containers.read(afm.cache,name)
- end
- if applyruntimefixes and data then
- applyruntimefixes(filename,data)
- end
- end
- return data
- else
- return nil
- end
-end
-
-local uparser = fonts.mappings.makenameparser()
-
-unify = function(data, filename)
- local unicodevector = fonts.encodings.agl.unicodes -- loaded runtime in context
- local unicodes = { }
- local names = { }
- local private = constructors.privateoffset
- local descriptions = data.descriptions
- for name, blob in next, data.characters do
- local code = unicodevector[name] -- or characters.name_to_unicode[name]
- if not code then
- code = lpegmatch(uparser,name)
- if not code then
- code = private
- private = private + 1
- report_afm("assigning private slot %U for unknown glyph name %a",code,name)
- end
- end
- local index = blob.index
- unicodes[name] = code
- names[name] = index
- blob.name = name
- descriptions[code] = {
- boundingbox = blob.boundingbox,
- width = blob.width,
- kerns = blob.kerns,
- index = index,
- name = name,
- }
- end
- for unicode, description in next, descriptions do
- local kerns = description.kerns
- if kerns then
- local krn = { }
- for name, kern in next, kerns do
- local unicode = unicodes[name]
- if unicode then
- krn[unicode] = kern
- else
- -- print(unicode,name)
- end
- end
- description.kerns = krn
- end
- end
- data.characters = nil
- local resources = data.resources
- local filename = resources.filename or file.removesuffix(file.basename(filename))
- resources.filename = resolvers.unresolve(filename) -- no shortcut
- resources.unicodes = unicodes -- name to unicode
- resources.marks = { } -- todo
- -- resources.names = names -- name to index
- resources.private = private
-end
-
-local everywhere = { ["*"] = { ["*"] = true } } -- or: { ["*"] = { "*" } }
-local noflags = { false, false, false, false }
-
-afm.experimental_normalize = false
-
-normalize = function(data)
- if type(afm.experimental_normalize) == "function" then
- afm.experimental_normalize(data)
- end
-end
-
-fixnames = function(data)
- for k, v in next, data.descriptions do
- local n = v.name
- local r = overloads[n]
- if r then
- local name = r.name
- if trace_indexing then
- report_afm("renaming characters %a to %a",n,name)
- end
- v.name = name
- v.unicode = r.unicode
- end
- end
-end
-
---[[ldx--
-These helpers extend the basic table with extra ligatures, texligatures
-and extra kerns. This saves quite some lookups later.
---ldx]]--
-
-local addthem = function(rawdata,ligatures)
- if ligatures then
- local descriptions = rawdata.descriptions
- local resources = rawdata.resources
- local unicodes = resources.unicodes
- -- local names = resources.names
- for ligname, ligdata in next, ligatures do
- local one = descriptions[unicodes[ligname]]
- if one then
- for _, pair in next, ligdata do
- local two, three = unicodes[pair[1]], unicodes[pair[2]]
- if two and three then
- local ol = one.ligatures
- if ol then
- if not ol[two] then
- ol[two] = three
- end
- else
- one.ligatures = { [two] = three }
- end
- end
- end
- end
- end
- end
-end
-
-addligatures = function(rawdata) addthem(rawdata,afm.helpdata.ligatures ) end
-addtexligatures = function(rawdata) addthem(rawdata,afm.helpdata.texligatures) end
-
---[[ldx--
-We keep the extra kerns in separate kerning tables so that we can use
-them selectively.
---ldx]]--
-
--- This is rather old code (from the beginning when we had only tfm). If
--- we unify the afm data (now we have names all over the place) then
--- we can use shcodes but there will be many more looping then. But we
--- could get rid of the tables in char-cmp then. Als, in the generic version
--- we don't use the character database. (Ok, we can have a context specific
--- variant).
-
-addkerns = function(rawdata) -- using shcodes is not robust here
- local descriptions = rawdata.descriptions
- local resources = rawdata.resources
- local unicodes = resources.unicodes
- local function do_it_left(what)
- if what then
- for unicode, description in next, descriptions do
- local kerns = description.kerns
- if kerns then
- local extrakerns
- for complex, simple in next, what do
- complex = unicodes[complex]
- simple = unicodes[simple]
- if complex and simple then
- local ks = kerns[simple]
- if ks and not kerns[complex] then
- if extrakerns then
- extrakerns[complex] = ks
- else
- extrakerns = { [complex] = ks }
- end
- end
- end
- end
- if extrakerns then
- description.extrakerns = extrakerns
- end
- end
- end
- end
- end
- local function do_it_copy(what)
- if what then
- for complex, simple in next, what do
- complex = unicodes[complex]
- simple = unicodes[simple]
- if complex and simple then
- local complexdescription = descriptions[complex]
- if complexdescription then -- optional
- local simpledescription = descriptions[complex]
- if simpledescription then
- local extrakerns
- local kerns = simpledescription.kerns
- if kerns then
- for unicode, kern in next, kerns do
- if extrakerns then
- extrakerns[unicode] = kern
- else
- extrakerns = { [unicode] = kern }
- end
- end
- end
- local extrakerns = simpledescription.extrakerns
- if extrakerns then
- for unicode, kern in next, extrakerns do
- if extrakerns then
- extrakerns[unicode] = kern
- else
- extrakerns = { [unicode] = kern }
- end
- end
- end
- if extrakerns then
- complexdescription.extrakerns = extrakerns
- end
- end
- end
- end
- end
- end
- end
- -- add complex with values of simplified when present
- do_it_left(afm.helpdata.leftkerned)
- do_it_left(afm.helpdata.bothkerned)
- -- copy kerns from simple char to complex char unless set
- do_it_copy(afm.helpdata.bothkerned)
- do_it_copy(afm.helpdata.rightkerned)
-end
-
---[[ldx--
-The copying routine looks messy (and is indeed a bit messy).
---ldx]]--
-
-local function adddimensions(data) -- we need to normalize afm to otf i.e. indexed table instead of name
- if data then
- for unicode, description in next, data.descriptions do
- local bb = description.boundingbox
- if bb then
- local ht, dp = bb[4], -bb[2]
- if ht == 0 or ht < 0 then
- -- no need to set it and no negative heights, nil == 0
- else
- description.height = ht
- end
- if dp == 0 or dp < 0 then
- -- no negative depths and no negative depths, nil == 0
- else
- description.depth = dp
- end
- end
- end
- end
-end
-
-local function copytotfm(data)
- if data and data.descriptions then
- local metadata = data.metadata
- local resources = data.resources
- local properties = derivetable(data.properties)
- local descriptions = derivetable(data.descriptions)
- local goodies = derivetable(data.goodies)
- local characters = { }
- local parameters = { }
- local unicodes = resources.unicodes
- --
- for unicode, description in next, data.descriptions do -- use parent table
- characters[unicode] = { }
- end
- --
- local filename = constructors.checkedfilename(resources)
- local fontname = metadata.fontname or metadata.fullname
- local fullname = metadata.fullname or metadata.fontname
- local endash = 0x0020 -- space
- local emdash = 0x2014
- local spacer = "space"
- local spaceunits = 500
- --
- local monospaced = metadata.monospaced
- local charwidth = metadata.charwidth
- local italicangle = metadata.italicangle
- local charxheight = metadata.xheight and metadata.xheight > 0 and metadata.xheight
- properties.monospaced = monospaced
- parameters.italicangle = italicangle
- parameters.charwidth = charwidth
- parameters.charxheight = charxheight
- -- same as otf
- if properties.monospaced then
- if descriptions[endash] then
- spaceunits, spacer = descriptions[endash].width, "space"
- end
- if not spaceunits and descriptions[emdash] then
- spaceunits, spacer = descriptions[emdash].width, "emdash"
- end
- if not spaceunits and charwidth then
- spaceunits, spacer = charwidth, "charwidth"
- end
- else
- if descriptions[endash] then
- spaceunits, spacer = descriptions[endash].width, "space"
- end
- if not spaceunits and charwidth then
- spaceunits, spacer = charwidth, "charwidth"
- end
- end
- spaceunits = tonumber(spaceunits)
- if spaceunits < 200 then
- -- todo: warning
- end
- --
- parameters.slant = 0
- parameters.space = spaceunits
- parameters.space_stretch = 500
- parameters.space_shrink = 333
- parameters.x_height = 400
- parameters.quad = 1000
- --
- if italicangle and italicangle ~= 0 then
- parameters.italicangle = italicangle
- parameters.italicfactor = math.cos(math.rad(90+italicangle))
- parameters.slant = - math.tan(italicangle*math.pi/180)
- end
- if monospaced then
- parameters.space_stretch = 0
- parameters.space_shrink = 0
- elseif afm.syncspace then
- parameters.space_stretch = spaceunits/2
- parameters.space_shrink = spaceunits/3
- end
- parameters.extra_space = parameters.space_shrink
- if charxheight then
- parameters.x_height = charxheight
- else
- -- same as otf
- local x = 0x0078 -- x
- if x then
- local x = descriptions[x]
- if x then
- parameters.x_height = x.height
- end
- end
- --
- end
- local fd = data.fontdimens
- if fd and fd[8] and fd[9] and fd[10] then -- math
- for k,v in next, fd do
- parameters[k] = v
- end
- end
- --
- parameters.designsize = (metadata.designsize or 10)*65536
- parameters.ascender = abs(metadata.ascender or 0)
- parameters.descender = abs(metadata.descender or 0)
- parameters.units = 1000
- --
- properties.spacer = spacer
- properties.encodingbytes = 2
- properties.format = fonts.formats[filename] or "type1"
- properties.filename = filename
- properties.fontname = fontname
- properties.fullname = fullname
- properties.psname = fullname
- properties.name = filename or fullname or fontname
- --
- if next(characters) then
- return {
- characters = characters,
- descriptions = descriptions,
- parameters = parameters,
- resources = resources,
- properties = properties,
- goodies = goodies,
- }
- end
- end
- return nil
-end
-
---[[ldx--
-Originally we had features kind of hard coded for
-files but since I expect to support more font formats, I decided
-to treat this fontformat like any other and handle features in a
-more configurable way.
---ldx]]--
-
-function afm.setfeatures(tfmdata,features)
- local okay = constructors.initializefeatures("afm",tfmdata,features,trace_features,report_afm)
- if okay then
- return constructors.collectprocessors("afm",tfmdata,features,trace_features,report_afm)
- else
- return { } -- will become false
- end
-end
-
-local function addtables(data)
- local resources = data.resources
- local lookuptags = resources.lookuptags
- local unicodes = resources.unicodes
- if not lookuptags then
- lookuptags = { }
- resources.lookuptags = lookuptags
- end
- setmetatableindex(lookuptags,function(t,k)
- local v = type(k) == "number" and ("lookup " .. k) or k
- t[k] = v
- return v
- end)
- if not unicodes then
- unicodes = { }
- resources.unicodes = unicodes
- setmetatableindex(unicodes,function(t,k)
- setmetatableindex(unicodes,nil)
- for u, d in next, data.descriptions do
- local n = d.name
- if n then
- t[n] = u
- end
- end
- return rawget(t,k)
- end)
- end
- constructors.addcoreunicodes(unicodes) -- do we really need this?
-end
-
-local function afmtotfm(specification)
- local afmname = specification.filename or specification.name
- if specification.forced == "afm" or specification.format == "afm" then -- move this one up
- if trace_loading then
- report_afm("forcing afm format for %a",afmname)
- end
- else
- local tfmname = findbinfile(afmname,"ofm") or ""
- if tfmname ~= "" then
- if trace_loading then
- report_afm("fallback from afm to tfm for %a",afmname)
- end
- return -- just that
- end
- end
- if afmname ~= "" then
- -- weird, isn't this already done then?
- local features = constructors.checkedfeatures("afm",specification.features.normal)
- specification.features.normal = features
- constructors.hashinstance(specification,true) -- also weird here
- --
- specification = definers.resolve(specification) -- new, was forgotten
- local cache_id = specification.hash
- local tfmdata = containers.read(constructors.cache, cache_id) -- cache with features applied
- if not tfmdata then
- local rawdata = afm.load(afmname)
- if rawdata and next(rawdata) then
- addtables(rawdata)
- adddimensions(rawdata)
- tfmdata = copytotfm(rawdata)
- if tfmdata and next(tfmdata) then
- local shared = tfmdata.shared
- if not shared then
- shared = { }
- tfmdata.shared = shared
- end
- shared.rawdata = rawdata
- shared.features = features
- shared.processes = afm.setfeatures(tfmdata,features)
- end
- elseif trace_loading then
- report_afm("no (valid) afm file found with name %a",afmname)
- end
- tfmdata = containers.write(constructors.cache,cache_id,tfmdata)
- end
- return tfmdata
- end
-end
-
---[[ldx--
-As soon as we could intercept the reader, I implemented an
- reader. Since traditional could use
-fonts with companions, the following method also could handle
-those cases, but now that we can handle directly we no longer
-need this features.
---ldx]]--
-
-local function read_from_afm(specification)
- local tfmdata = afmtotfm(specification)
- if tfmdata then
- tfmdata.properties.name = specification.name
- tfmdata = constructors.scale(tfmdata, specification)
- local allfeatures = tfmdata.shared.features or specification.features.normal
- constructors.applymanipulators("afm",tfmdata,allfeatures,trace_features,report_afm)
- fonts.loggers.register(tfmdata,'afm',specification)
- end
- return tfmdata
-end
-
---[[ldx--
-Here comes the implementation of a few features. We only implement
-those that make sense for this format.
---ldx]]--
-
-local function prepareligatures(tfmdata,ligatures,value)
- if value then
- local descriptions = tfmdata.descriptions
- local hasligatures = false
- for unicode, character in next, tfmdata.characters do
- local description = descriptions[unicode]
- local dligatures = description.ligatures
- if dligatures then
- local cligatures = character.ligatures
- if not cligatures then
- cligatures = { }
- character.ligatures = cligatures
- end
- for unicode, ligature in next, dligatures do
- cligatures[unicode] = {
- char = ligature,
- type = 0
- }
- end
- hasligatures = true
- end
- end
- tfmdata.properties.hasligatures = hasligatures
- end
-end
-
-local function preparekerns(tfmdata,kerns,value)
- if value then
- local rawdata = tfmdata.shared.rawdata
- local resources = rawdata.resources
- local unicodes = resources.unicodes
- local descriptions = tfmdata.descriptions
- local haskerns = false
- for u, chr in next, tfmdata.characters do
- local d = descriptions[u]
- local newkerns = d[kerns]
- if newkerns then
- local kerns = chr.kerns
- if not kerns then
- kerns = { }
- chr.kerns = kerns
- end
- for k,v in next, newkerns do
- local uk = unicodes[k]
- if uk then
- kerns[uk] = v
- end
- end
- haskerns = true
- end
- end
- tfmdata.properties.haskerns = haskerns
- end
-end
-
-local list = {
- -- [0x0022] = 0x201D,
- [0x0027] = 0x2019,
- -- [0x0060] = 0x2018,
-}
-
-local function texreplacements(tfmdata,value)
- local descriptions = tfmdata.descriptions
- local characters = tfmdata.characters
- for k, v in next, list do
- characters [k] = characters [v] -- we forget about kerns
- descriptions[k] = descriptions[v] -- we forget about kerns
- end
-end
-
-local function ligatures (tfmdata,value) prepareligatures(tfmdata,'ligatures', value) end
-local function texligatures(tfmdata,value) prepareligatures(tfmdata,'texligatures',value) end
-local function kerns (tfmdata,value) preparekerns (tfmdata,'kerns', value) end
-local function extrakerns (tfmdata,value) preparekerns (tfmdata,'extrakerns', value) end
-
-registerafmfeature {
- name = "liga",
- description = "traditional ligatures",
- initializers = {
- base = ligatures,
- node = ligatures,
- }
-}
-
-registerafmfeature {
- name = "kern",
- description = "intercharacter kerning",
- initializers = {
- base = kerns,
- node = kerns,
- }
-}
-
-registerafmfeature {
- name = "extrakerns",
- description = "additional intercharacter kerning",
- initializers = {
- base = extrakerns,
- node = extrakerns,
- }
-}
-
-registerafmfeature {
- name = 'tlig',
- description = 'tex ligatures',
- initializers = {
- base = texligatures,
- node = texligatures,
- }
-}
-
-registerafmfeature {
- name = 'trep',
- description = 'tex replacements',
- initializers = {
- base = texreplacements,
- node = texreplacements,
- }
-}
-
--- readers
-
-local check_tfm = readers.check_tfm
-
-fonts.formats.afm = "type1"
-fonts.formats.pfb = "type1"
-
-local function check_afm(specification,fullname)
- local foundname = findbinfile(fullname, 'afm') or "" -- just to be sure
- if foundname == "" then
- foundname = fonts.names.getfilename(fullname,"afm") or ""
- end
- if foundname == "" and afm.autoprefixed then
- local encoding, shortname = match(fullname,"^(.-)%-(.*)$") -- context: encoding-name.*
- if encoding and shortname and fonts.encodings.known[encoding] then
- shortname = findbinfile(shortname,'afm') or "" -- just to be sure
- if shortname ~= "" then
- foundname = shortname
- if trace_defining then
- report_afm("stripping encoding prefix from filename %a",afmname)
- end
- end
- end
- end
- if foundname ~= "" then
- specification.filename = foundname
- specification.format = "afm"
- return read_from_afm(specification)
- end
-end
-
-function readers.afm(specification,method)
- local fullname, tfmdata = specification.filename or "", nil
- if fullname == "" then
- local forced = specification.forced or ""
- if forced ~= "" then
- tfmdata = check_afm(specification,specification.name .. "." .. forced)
- end
- if not tfmdata then
- method = method or definers.method or "afm or tfm"
- if method == "tfm" then
- tfmdata = check_tfm(specification,specification.name)
- elseif method == "afm" then
- tfmdata = check_afm(specification,specification.name)
- elseif method == "tfm or afm" then
- tfmdata = check_tfm(specification,specification.name) or check_afm(specification,specification.name)
- else -- method == "afm or tfm" or method == "" then
- tfmdata = check_afm(specification,specification.name) or check_tfm(specification,specification.name)
- end
- end
- else
- tfmdata = check_afm(specification,fullname)
- end
- return tfmdata
-end
-
-function readers.pfb(specification,method) -- only called when forced
- local original = specification.specification
- if trace_defining then
- report_afm("using afm reader for %a",original)
- end
- specification.specification = gsub(original,"%.pfb",".afm")
- specification.forced = "afm"
- return readers.afm(specification,method)
-end
diff --git a/src/fontloader/misc/fontloader-font-one.lua b/src/fontloader/misc/fontloader-font-one.lua
new file mode 100644
index 0000000..3602fd4
--- /dev/null
+++ b/src/fontloader/misc/fontloader-font-one.lua
@@ -0,0 +1,1220 @@
+if not modules then modules = { } end modules ['font-one'] = {
+ 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"
+}
+
+--[[ldx--
+Some code may look a bit obscure but this has to do with the fact that we also use
+this code for testing and much code evolved in the transition from to
+ to .
+
+The following code still has traces of intermediate font support where we handles
+font encodings. Eventually font encoding went away but we kept some code around in
+other modules.
+
+This version implements a node mode approach so that users can also more easily
+add features.
+--ldx]]--
+
+local fonts, logs, trackers, containers, resolvers = fonts, logs, trackers, containers, resolvers
+
+local next, type, tonumber = next, type, tonumber
+local match, gmatch, lower, gsub, strip, find = string.match, string.gmatch, 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, lpegmatch, patterns = lpeg.P, lpeg.S, lpeg.R, lpeg.Cmt, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.match, lpeg.patterns
+local derivetable = table.derive
+
+local trace_features = false trackers.register("afm.features", function(v) trace_features = v end)
+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 trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end)
+
+local report_afm = logs.reporter("fonts","afm loading")
+
+local setmetatableindex = table.setmetatableindex
+
+local findbinfile = resolvers.findbinfile
+
+local definers = fonts.definers
+local readers = fonts.readers
+local constructors = fonts.constructors
+
+local afm = constructors.newhandler("afm")
+local pfb = constructors.newhandler("pfb")
+local otf = fonts.handlers.otf
+
+local otfreaders = otf.readers
+local otfenhancers = otf.enhancers
+
+local afmfeatures = constructors.newfeatures("afm")
+local registerafmfeature = afmfeatures.register
+
+afm.version = 1.505 -- incrementing this number one up will force a re-cache
+afm.cache = containers.define("fonts", "afm", afm.version, true)
+afm.autoprefixed = true -- this will become false some day (catches texnansi-blabla.*)
+
+afm.helpdata = { } -- set later on so no local for this
+afm.syncspace = true -- when true, nicer stretch values
+
+local overloads = fonts.mappings.overloads
+
+local applyruntimefixes = fonts.treatments and fonts.treatments.applyfixes
+
+--[[ldx--
+We start with the basic reader which we give a name similar to the
+built in and reader.
+--ldx]]--
+
+--~ Comment FONTIDENTIFIER LMMATHSYMBOLS10
+--~ Comment CODINGSCHEME TEX MATH SYMBOLS
+--~ Comment DESIGNSIZE 10.0 pt
+--~ Comment CHECKSUM O 4261307036
+--~ Comment SPACE 0 plus 0 minus 0
+--~ Comment QUAD 1000
+--~ Comment EXTRASPACE 0
+--~ Comment NUM 676.508 393.732 443.731
+--~ Comment DENOM 685.951 344.841
+--~ Comment SUP 412.892 362.892 288.889
+--~ Comment SUB 150 247.217
+--~ Comment SUPDROP 386.108
+--~ Comment SUBDROP 50
+--~ Comment DELIM 2390 1010
+--~ Comment AXISHEIGHT 250
+
+local comment = P("Comment")
+local spacing = patterns.spacer -- S(" \t")^1
+local lineend = patterns.newline -- S("\n\r")
+local words = C((1 - lineend)^1)
+local number = C((R("09") + S("."))^1) / tonumber * spacing^0
+local data = lpeg.Carg(1)
+
+local pattern = ( -- needs testing ... not used anyway as we no longer need math afm's
+ comment * spacing *
+ (
+ data * (
+ ("CODINGSCHEME" * spacing * words ) / function(fd,a) end +
+ ("DESIGNSIZE" * spacing * number * words ) / function(fd,a) fd[ 1] = a end +
+ ("CHECKSUM" * spacing * number * words ) / function(fd,a) fd[ 2] = a end +
+ ("SPACE" * spacing * number * "plus" * number * "minus" * number) / function(fd,a,b,c) fd[ 3], fd[ 4], fd[ 5] = a, b, c end +
+ ("QUAD" * spacing * number ) / function(fd,a) fd[ 6] = a end +
+ ("EXTRASPACE" * spacing * number ) / function(fd,a) fd[ 7] = a end +
+ ("NUM" * spacing * number * number * number ) / function(fd,a,b,c) fd[ 8], fd[ 9], fd[10] = a, b, c end +
+ ("DENOM" * spacing * number * number ) / function(fd,a,b ) fd[11], fd[12] = a, b end +
+ ("SUP" * spacing * number * number * number ) / function(fd,a,b,c) fd[13], fd[14], fd[15] = a, b, c end +
+ ("SUB" * spacing * number * number ) / function(fd,a,b) fd[16], fd[17] = a, b end +
+ ("SUPDROP" * spacing * number ) / function(fd,a) fd[18] = a end +
+ ("SUBDROP" * spacing * number ) / function(fd,a) fd[19] = a end +
+ ("DELIM" * spacing * number * number ) / function(fd,a,b) fd[20], fd[21] = a, b end +
+ ("AXISHEIGHT" * spacing * number ) / function(fd,a) fd[22] = a end
+ )
+ + (1-lineend)^0
+ )
+ + (1-comment)^1
+)^0
+
+local function scan_comment(str)
+ local fd = { }
+ lpegmatch(pattern,str,1,fd)
+ return fd
+end
+
+-- On a rainy day I will rewrite this in lpeg ... or we can use the (slower) fontloader
+-- as in now supports afm/pfb loading but it's not too bad to have different methods
+-- for testing approaches.
+
+local keys = { }
+
+function keys.FontName (data,line) data.metadata.fontname = strip (line) -- get rid of spaces
+ data.metadata.fullname = strip (line) end
+function keys.ItalicAngle (data,line) data.metadata.italicangle = tonumber (line) 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
+function keys.Ascender (data,line) data.metadata.ascender = tonumber (line) end
+function keys.Comment (data,line)
+ -- Comment DesignSize 12 (pts)
+ -- Comment TFM designsize: 12 (in points)
+ line = lower(line)
+ local designsize = match(line,"designsize[^%d]*(%d+)")
+ if designsize then data.metadata.designsize = tonumber(designsize) end
+end
+
+local function get_charmetrics(data,charmetrics,vector)
+ local characters = data.characters
+ local chr, ind = { }, 0
+ for k, v in gmatch(charmetrics,"([%a]+) +(.-) *;") do
+ if k == 'C' then
+ v = tonumber(v)
+ if v < 0 then
+ ind = ind + 1 -- ?
+ else
+ ind = v
+ end
+ chr = {
+ index = ind
+ }
+ elseif k == 'WX' then
+ chr.width = tonumber(v)
+ elseif k == 'N' then
+ characters[v] = chr
+ elseif k == 'B' then
+ local llx, lly, urx, ury = match(v,"^ *(.-) +(.-) +(.-) +(.-)$")
+ chr.boundingbox = { tonumber(llx), tonumber(lly), tonumber(urx), tonumber(ury) }
+ elseif k == 'L' then
+ local plus, becomes = match(v,"^(.-) +(.-)$")
+ local ligatures = chr.ligatures
+ if ligatures then
+ ligatures[plus] = becomes
+ else
+ chr.ligatures = { [plus] = becomes }
+ end
+ end
+ end
+end
+
+local function get_kernpairs(data,kernpairs)
+ local characters = data.characters
+ for one, two, value in gmatch(kernpairs,"KPX +(.-) +(.-) +(.-)\n") do
+ local chr = characters[one]
+ if chr then
+ local kerns = chr.kerns
+ if kerns then
+ kerns[two] = tonumber(value)
+ else
+ chr.kerns = { [two] = tonumber(value) }
+ end
+ end
+ end
+end
+
+local function get_variables(data,fontmetrics)
+ for key, rest in gmatch(fontmetrics,"(%a+) *(.-)[\n\r]") do
+ local keyhandler = keys[key]
+ if keyhandler then
+ keyhandler(data,rest)
+ end
+ end
+end
+
+-- new (unfinished) pfb loader but i see no differences between
+-- old and new (one bad vector with old)
+
+local get_indexes
+
+do
+
+ local n, m
+
+ local progress = function(str,position,name,size)
+ local forward = position + tonumber(size) + 3 + 2
+ n = n + 1
+ if n >= m then
+ return #str, name
+ elseif forward < #str then
+ return forward, name
+ else
+ return #str, name
+ end
+ end
+
+ local initialize = function(str,position,size)
+ n = 0
+ m = tonumber(size)
+ return position + 1
+ end
+
+ local charstrings = P("/CharStrings")
+ local name = P("/") * C((R("az")+R("AZ")+R("09")+S("-_."))^1)
+ local size = C(R("09")^1)
+ local spaces = P(" ")^1
+
+ local p_filternames = Ct (
+ (1-charstrings)^0 * charstrings * spaces * Cmt(size,initialize)
+ * (Cmt(name * P(" ")^1 * C(R("09")^1), progress) + P(1))^1
+ )
+
+ -- if one of first 4 not 0-9A-F then binary else hex
+
+ local decrypt
+
+ do
+
+ local r, c1, c2, n = 0, 0, 0, 0
+
+ local function step(c)
+ local cipher = byte(c)
+ local plain = bxor(cipher,rshift(r,8))
+ r = ((cipher + r) * c1 + c2) % 65536
+ return char(plain)
+ end
+
+ decrypt = function(binary)
+ r, c1, c2, n = 55665, 52845, 22719, 4
+ binary = gsub(binary,".",step)
+ return sub(binary,n+1)
+ end
+
+ -- local pattern = Cs((P(1) / step)^1)
+ --
+ -- decrypt = function(binary)
+ -- r, c1, c2, n = 55665, 52845, 22719, 4
+ -- binary = lpegmatch(pattern,binary)
+ -- return sub(binary,n+1)
+ -- end
+
+ end
+
+ local function loadpfbvector(filename)
+ -- for the moment limited to encoding only
+
+ local data = io.loaddata(resolvers.findfile(filename))
+
+ if not find(data,"!PS%-AdobeFont%-") then
+ print("no font",filename)
+ return
+ end
+
+ if not data then
+ print("no data",filename)
+ return
+ end
+
+ local ascii, binary = match(data,"(.*)eexec%s+......(.*)")
+
+ if not binary then
+ print("no binary",filename)
+ return
+ end
+
+ binary = decrypt(binary,4)
+
+ local vector = lpegmatch(p_filternames,binary)
+
+ vector[0] = table.remove(vector,1)
+
+ if not vector then
+ print("no vector",filename)
+ return
+ end
+
+ return vector
+
+ end
+
+ get_indexes = function(data,pfbname)
+ local vector = loadpfbvector(pfbname)
+ if vector then
+ local characters = data.characters
+ if trace_loading then
+ report_afm("getting index data from %a",pfbname)
+ end
+ for index=1,#vector do
+ local name = vector[index]
+ local char = characters[name]
+ if char then
+ if trace_indexing then
+ report_afm("glyph %a has index %a",name,index)
+ end
+ char.index = index
+ end
+ end
+ end
+ end
+
+end
+
+local function readafm(filename)
+ local ok, afmblob, size = resolvers.loadbinfile(filename) -- has logging
+ if ok and afmblob then
+ local data = {
+ resources = {
+ filename = resolvers.unresolve(filename),
+ version = afm.version,
+ creator = "context mkiv",
+ },
+ properties = {
+ hasitalics = false,
+ },
+ goodies = {
+ },
+ metadata = {
+ filename = file.removesuffix(file.basename(filename))
+ },
+ characters = {
+ -- a temporary store
+ },
+ descriptions = {
+ -- the final store
+ },
+ }
+ afmblob = gsub(afmblob,"StartCharMetrics(.-)EndCharMetrics", function(charmetrics)
+ if trace_loading then
+ report_afm("loading char metrics")
+ end
+ get_charmetrics(data,charmetrics,vector)
+ return ""
+ end)
+ afmblob = gsub(afmblob,"StartKernPairs(.-)EndKernPairs", function(kernpairs)
+ if trace_loading then
+ report_afm("loading kern pairs")
+ end
+ get_kernpairs(data,kernpairs)
+ return ""
+ end)
+ afmblob = gsub(afmblob,"StartFontMetrics%s+([%d%.]+)(.-)EndFontMetrics", function(version,fontmetrics)
+ if trace_loading then
+ report_afm("loading variables")
+ end
+ data.afmversion = version
+ get_variables(data,fontmetrics)
+ data.fontdimens = scan_comment(fontmetrics) -- todo: all lpeg, no time now
+ return ""
+ end)
+ return data
+ else
+ if trace_loading then
+ report_afm("no valid afm file %a",filename)
+ end
+ return nil
+ end
+end
+
+--[[ldx--
+We cache files. Caching is taken care of in the loader. We cheat a bit by adding
+ligatures and kern information to the afm derived data. That way we can set them faster
+when defining a font.
+
+We still keep the loading two phased: first we load the data in a traditional
+fashion and later we transform it to sequences.
+--ldx]]--
+
+local addkerns, unify, normalize, fixnames, addligatures, addtexligatures
+
+function afm.load(filename)
+ filename = resolvers.findfile(filename,'afm') or ""
+ if filename ~= "" and not fonts.names.ignoredfile(filename) then
+ local name = file.removesuffix(file.basename(filename))
+ local data = containers.read(afm.cache,name)
+ local attr = lfs.attributes(filename)
+ local size, time = attr.size or 0, attr.modification or 0
+ --
+ local pfbfile = file.replacesuffix(name,"pfb")
+ local pfbname = resolvers.findfile(pfbfile,"pfb") or ""
+ if pfbname == "" then
+ pfbname = resolvers.findfile(file.basename(pfbfile),"pfb") or ""
+ end
+ local pfbsize, pfbtime = 0, 0
+ if pfbname ~= "" then
+ local attr = lfs.attributes(pfbname)
+ pfbsize = attr.size or 0
+ pfbtime = attr.modification or 0
+ end
+ if not data or data.size ~= size or data.time ~= time or data.pfbsize ~= pfbsize or data.pfbtime ~= pfbtime then
+ report_afm("reading %a",filename)
+ data = readafm(filename)
+ if data then
+ if pfbname ~= "" then
+ data.resources.filename = resolvers.unresolve(pfbname)
+ get_indexes(data,pfbname)
+ elseif trace_loading then
+ report_afm("no pfb file for %a",filename)
+ -- data.resources.filename = "unset" -- better than loading the afm file
+ end
+ -- we now have all the data loaded
+ if trace_loading then
+ report_afm("unifying %a",filename)
+ end
+ unify(data,filename)
+ if trace_loading then
+ report_afm("add ligatures") -- there can be missing ones
+ end
+ addligatures(data)
+ if trace_loading then
+ report_afm("add extra kerns")
+ end
+ addkerns(data)
+ if trace_loading then
+ report_afm("normalizing")
+ end
+ normalize(data)
+ if trace_loading then
+ report_afm("fixing names")
+ end
+ fixnames(data)
+ if trace_loading then
+ report_afm("add tounicode data")
+ end
+ -- otfreaders.addunicodetable(data) -- only when not done yet
+ fonts.mappings.addtounicode(data,filename)
+ -- otfreaders.extend(data)
+ otfreaders.pack(data)
+ data.size = size
+ data.time = time
+ data.pfbsize = pfbsize
+ data.pfbtime = pfbtime
+ report_afm("saving %a in cache",name)
+ -- data.resources.unicodes = nil -- consistent with otf but here we save not much
+ data = containers.write(afm.cache, name, data)
+ data = containers.read(afm.cache,name)
+ end
+ end
+ if data then
+ -- constructors.addcoreunicodes(unicodes)
+ otfreaders.unpack(data)
+ otfreaders.expand(data) -- inline tables
+ otfreaders.addunicodetable(data) -- only when not done yet
+ otfenhancers.apply(data,filename,data)
+ if applyruntimefixes then
+ applyruntimefixes(filename,data)
+ end
+ end
+ return data
+ else
+ return nil
+ end
+end
+
+local uparser = fonts.mappings.makenameparser()
+
+unify = function(data, filename)
+ local unicodevector = fonts.encodings.agl.unicodes -- loaded runtime in context
+ local unicodes = { }
+ local names = { }
+ local private = constructors.privateoffset
+ local descriptions = data.descriptions
+ for name, blob in next, data.characters do
+ local code = unicodevector[name] -- or characters.name_to_unicode[name]
+ if not code then
+ code = lpegmatch(uparser,name)
+ if not code then
+ code = private
+ private = private + 1
+ report_afm("assigning private slot %U for unknown glyph name %a",code,name)
+ end
+ end
+ local index = blob.index
+ unicodes[name] = code
+ names[name] = index
+ blob.name = name
+ descriptions[code] = {
+ boundingbox = blob.boundingbox,
+ width = blob.width,
+ kerns = blob.kerns,
+ index = index,
+ name = name,
+ }
+ end
+ for unicode, description in next, descriptions do
+ local kerns = description.kerns
+ if kerns then
+ local krn = { }
+ for name, kern in next, kerns do
+ local unicode = unicodes[name]
+ if unicode then
+ krn[unicode] = kern
+ else
+ -- print(unicode,name)
+ end
+ end
+ description.kerns = krn
+ end
+ end
+ data.characters = nil
+ local resources = data.resources
+ local filename = resources.filename or file.removesuffix(file.basename(filename))
+ resources.filename = resolvers.unresolve(filename) -- no shortcut
+ resources.unicodes = unicodes -- name to unicode
+ resources.marks = { } -- todo
+ -- resources.names = names -- name to index
+ resources.private = private
+end
+
+local everywhere = { ["*"] = { ["*"] = true } } -- or: { ["*"] = { "*" } }
+local noflags = { false, false, false, false }
+
+normalize = function(data)
+ local ligatures = setmetatableindex("table")
+ local kerns = setmetatableindex("table")
+ local extrakerns = setmetatableindex("table")
+ for u, c in next, data.descriptions do
+ local l = c.ligatures
+ local k = c.kerns
+ local e = c.extrakerns
+ if l then
+ ligatures[u] = l
+ for u, v in next, l do
+ l[u] = { ligature = v }
+ end
+ c.ligatures = nil
+ end
+ if k then
+ kerns[u] = k
+ for u, v in next, k do
+ k[u] = v -- { v, 0 }
+ end
+ c.kerns = nil
+ end
+ if e then
+ extrakerns[u] = e
+ for u, v in next, e do
+ e[u] = v -- { v, 0 }
+ end
+ c.extrakerns = nil
+ end
+ end
+ local features = {
+ gpos = { },
+ gsub = { },
+ }
+ local sequences = {
+ -- only filled ones
+ }
+ 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
+ if next(extrakerns) then
+ features.gpos.extrakerns = everywhere
+ data.properties.haskerns = true
+ sequences[#sequences+1] = {
+ features = {
+ extrakerns = everywhere,
+ },
+ flags = noflags,
+ name = "p_s_1",
+ nofsteps = 1,
+ order = { "extrakerns" },
+ type = "gpos_pair",
+ steps = {
+ {
+ format = "kern",
+ coverage = extrakerns,
+ },
+ },
+ }
+ end
+ -- todo: compress kerns
+ data.resources.features = features
+ data.resources.sequences = sequences
+end
+
+fixnames = function(data)
+ for k, v in next, data.descriptions do
+ local n = v.name
+ local r = overloads[n]
+ if r then
+ local name = r.name
+ if trace_indexing then
+ report_afm("renaming characters %a to %a",n,name)
+ end
+ v.name = name
+ v.unicode = r.unicode
+ end
+ end
+end
+
+--[[ldx--
+These helpers extend the basic table with extra ligatures, texligatures
+and extra kerns. This saves quite some lookups later.
+--ldx]]--
+
+local addthem = function(rawdata,ligatures)
+ if ligatures then
+ local descriptions = rawdata.descriptions
+ local resources = rawdata.resources
+ local unicodes = resources.unicodes
+ -- local names = resources.names
+ for ligname, ligdata in next, ligatures do
+ local one = descriptions[unicodes[ligname]]
+ if one then
+ for _, pair in next, ligdata do
+ local two, three = unicodes[pair[1]], unicodes[pair[2]]
+ if two and three then
+ local ol = one.ligatures
+ if ol then
+ if not ol[two] then
+ ol[two] = three
+ end
+ else
+ one.ligatures = { [two] = three }
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+addligatures = function(rawdata) addthem(rawdata,afm.helpdata.ligatures ) end
+addtexligatures = function(rawdata) addthem(rawdata,afm.helpdata.texligatures) end
+
+--[[ldx--
+We keep the extra kerns in separate kerning tables so that we can use
+them selectively.
+--ldx]]--
+
+-- This is rather old code (from the beginning when we had only tfm). If
+-- we unify the afm data (now we have names all over the place) then
+-- we can use shcodes but there will be many more looping then. But we
+-- could get rid of the tables in char-cmp then. Als, in the generic version
+-- we don't use the character database. (Ok, we can have a context specific
+-- variant).
+
+addkerns = function(rawdata) -- using shcodes is not robust here
+ local descriptions = rawdata.descriptions
+ local resources = rawdata.resources
+ local unicodes = resources.unicodes
+ local function do_it_left(what)
+ if what then
+ for unicode, description in next, descriptions do
+ local kerns = description.kerns
+ if kerns then
+ local extrakerns
+ for complex, simple in next, what do
+ complex = unicodes[complex]
+ simple = unicodes[simple]
+ if complex and simple then
+ local ks = kerns[simple]
+ if ks and not kerns[complex] then
+ if extrakerns then
+ extrakerns[complex] = ks
+ else
+ extrakerns = { [complex] = ks }
+ end
+ end
+ end
+ end
+ if extrakerns then
+ description.extrakerns = extrakerns
+ end
+ end
+ end
+ end
+ end
+ local function do_it_copy(what)
+ if what then
+ for complex, simple in next, what do
+ complex = unicodes[complex]
+ simple = unicodes[simple]
+ if complex and simple then
+ local complexdescription = descriptions[complex]
+ if complexdescription then -- optional
+ local simpledescription = descriptions[complex]
+ if simpledescription then
+ local extrakerns
+ local kerns = simpledescription.kerns
+ if kerns then
+ for unicode, kern in next, kerns do
+ if extrakerns then
+ extrakerns[unicode] = kern
+ else
+ extrakerns = { [unicode] = kern }
+ end
+ end
+ end
+ local extrakerns = simpledescription.extrakerns
+ if extrakerns then
+ for unicode, kern in next, extrakerns do
+ if extrakerns then
+ extrakerns[unicode] = kern
+ else
+ extrakerns = { [unicode] = kern }
+ end
+ end
+ end
+ if extrakerns then
+ complexdescription.extrakerns = extrakerns
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ -- add complex with values of simplified when present
+ do_it_left(afm.helpdata.leftkerned)
+ do_it_left(afm.helpdata.bothkerned)
+ -- copy kerns from simple char to complex char unless set
+ do_it_copy(afm.helpdata.bothkerned)
+ do_it_copy(afm.helpdata.rightkerned)
+end
+
+--[[ldx--
+The copying routine looks messy (and is indeed a bit messy).
+--ldx]]--
+
+local function adddimensions(data) -- we need to normalize afm to otf i.e. indexed table instead of name
+ if data then
+ for unicode, description in next, data.descriptions do
+ local bb = description.boundingbox
+ if bb then
+ local ht, dp = bb[4], -bb[2]
+ if ht == 0 or ht < 0 then
+ -- no need to set it and no negative heights, nil == 0
+ else
+ description.height = ht
+ end
+ if dp == 0 or dp < 0 then
+ -- no negative depths and no negative depths, nil == 0
+ else
+ description.depth = dp
+ end
+ end
+ end
+ end
+end
+
+local function copytotfm(data)
+ if data and data.descriptions then
+ local metadata = data.metadata
+ local resources = data.resources
+ local properties = derivetable(data.properties)
+ local descriptions = derivetable(data.descriptions)
+ local goodies = derivetable(data.goodies)
+ local characters = { }
+ local parameters = { }
+ local unicodes = resources.unicodes
+ --
+ for unicode, description in next, data.descriptions do -- use parent table
+ characters[unicode] = { }
+ end
+ --
+ local filename = constructors.checkedfilename(resources)
+ local fontname = metadata.fontname or metadata.fullname
+ local fullname = metadata.fullname or metadata.fontname
+ local endash = 0x0020 -- space
+ local emdash = 0x2014
+ local spacer = "space"
+ local spaceunits = 500
+ --
+ local monospaced = metadata.monospaced
+ local charwidth = metadata.charwidth
+ local italicangle = metadata.italicangle
+ local charxheight = metadata.xheight and metadata.xheight > 0 and metadata.xheight
+ properties.monospaced = monospaced
+ parameters.italicangle = italicangle
+ parameters.charwidth = charwidth
+ parameters.charxheight = charxheight
+ -- same as otf
+ if properties.monospaced then
+ if descriptions[endash] then
+ spaceunits, spacer = descriptions[endash].width, "space"
+ end
+ if not spaceunits and descriptions[emdash] then
+ spaceunits, spacer = descriptions[emdash].width, "emdash"
+ end
+ if not spaceunits and charwidth then
+ spaceunits, spacer = charwidth, "charwidth"
+ end
+ else
+ if descriptions[endash] then
+ spaceunits, spacer = descriptions[endash].width, "space"
+ end
+ if not spaceunits and charwidth then
+ spaceunits, spacer = charwidth, "charwidth"
+ end
+ end
+ spaceunits = tonumber(spaceunits)
+ if spaceunits < 200 then
+ -- todo: warning
+ end
+ --
+ parameters.slant = 0
+ parameters.space = spaceunits
+ parameters.space_stretch = 500
+ parameters.space_shrink = 333
+ parameters.x_height = 400
+ parameters.quad = 1000
+ --
+ if italicangle and italicangle ~= 0 then
+ parameters.italicangle = italicangle
+ parameters.italicfactor = math.cos(math.rad(90+italicangle))
+ parameters.slant = - math.tan(italicangle*math.pi/180)
+ end
+ if monospaced then
+ parameters.space_stretch = 0
+ parameters.space_shrink = 0
+ elseif afm.syncspace then
+ parameters.space_stretch = spaceunits/2
+ parameters.space_shrink = spaceunits/3
+ end
+ parameters.extra_space = parameters.space_shrink
+ if charxheight then
+ parameters.x_height = charxheight
+ else
+ -- same as otf
+ local x = 0x0078 -- x
+ if x then
+ local x = descriptions[x]
+ if x then
+ parameters.x_height = x.height
+ end
+ end
+ --
+ end
+ local fd = data.fontdimens
+ if fd and fd[8] and fd[9] and fd[10] then -- math
+ for k,v in next, fd do
+ parameters[k] = v
+ end
+ end
+ --
+ parameters.designsize = (metadata.designsize or 10)*65536
+ parameters.ascender = abs(metadata.ascender or 0)
+ parameters.descender = abs(metadata.descender or 0)
+ parameters.units = 1000
+ --
+ properties.spacer = spacer
+ properties.encodingbytes = 2
+ properties.format = fonts.formats[filename] or "type1"
+ properties.filename = filename
+ properties.fontname = fontname
+ properties.fullname = fullname
+ properties.psname = fullname
+ properties.name = filename or fullname or fontname
+ --
+ if next(characters) then
+ return {
+ characters = characters,
+ descriptions = descriptions,
+ parameters = parameters,
+ resources = resources,
+ properties = properties,
+ goodies = goodies,
+ }
+ end
+ end
+ return nil
+end
+
+--[[ldx--
+Originally we had features kind of hard coded for
+files but since I expect to support more font formats, I decided
+to treat this fontformat like any other and handle features in a
+more configurable way.
+--ldx]]--
+
+function afm.setfeatures(tfmdata,features)
+ local okay = constructors.initializefeatures("afm",tfmdata,features,trace_features,report_afm)
+ if okay then
+ return constructors.collectprocessors("afm",tfmdata,features,trace_features,report_afm)
+ else
+ return { } -- will become false
+ end
+end
+
+local function addtables(data)
+ local resources = data.resources
+ local lookuptags = resources.lookuptags
+ local unicodes = resources.unicodes
+ if not lookuptags then
+ lookuptags = { }
+ resources.lookuptags = lookuptags
+ end
+ setmetatableindex(lookuptags,function(t,k)
+ local v = type(k) == "number" and ("lookup " .. k) or k
+ t[k] = v
+ return v
+ end)
+ if not unicodes then
+ unicodes = { }
+ resources.unicodes = unicodes
+ setmetatableindex(unicodes,function(t,k)
+ setmetatableindex(unicodes,nil)
+ for u, d in next, data.descriptions do
+ local n = d.name
+ if n then
+ t[n] = u
+ end
+ end
+ return rawget(t,k)
+ end)
+ end
+ constructors.addcoreunicodes(unicodes) -- do we really need this?
+end
+
+local function afmtotfm(specification)
+ local afmname = specification.filename or specification.name
+ if specification.forced == "afm" or specification.format == "afm" then -- move this one up
+ if trace_loading then
+ report_afm("forcing afm format for %a",afmname)
+ end
+ else
+ local tfmname = findbinfile(afmname,"ofm") or ""
+ if tfmname ~= "" then
+ if trace_loading then
+ report_afm("fallback from afm to tfm for %a",afmname)
+ end
+ return -- just that
+ end
+ end
+ if afmname ~= "" then
+ -- weird, isn't this already done then?
+ local features = constructors.checkedfeatures("afm",specification.features.normal)
+ specification.features.normal = features
+ constructors.hashinstance(specification,true) -- also weird here
+ --
+ specification = definers.resolve(specification) -- new, was forgotten
+ local cache_id = specification.hash
+ local tfmdata = containers.read(constructors.cache, cache_id) -- cache with features applied
+ if not tfmdata then
+ local rawdata = afm.load(afmname)
+ if rawdata and next(rawdata) then
+ addtables(rawdata)
+ adddimensions(rawdata)
+ tfmdata = copytotfm(rawdata)
+ if tfmdata and next(tfmdata) then
+ local shared = tfmdata.shared
+ if not shared then
+ shared = { }
+ tfmdata.shared = shared
+ end
+ shared.rawdata = rawdata
+ shared.dynamics = { }
+ tfmdata.changed = { }
+ shared.features = features
+ shared.processes = afm.setfeatures(tfmdata,features)
+ end
+ elseif trace_loading then
+ report_afm("no (valid) afm file found with name %a",afmname)
+ end
+ tfmdata = containers.write(constructors.cache,cache_id,tfmdata)
+ end
+ return tfmdata
+ end
+end
+
+--[[ldx--
+As soon as we could intercept the reader, I implemented an
+ reader. Since traditional could use
+fonts with companions, the following method also could handle
+those cases, but now that we can handle directly we no longer
+need this features.
+--ldx]]--
+
+local function read_from_afm(specification)
+ local tfmdata = afmtotfm(specification)
+ if tfmdata then
+ tfmdata.properties.name = specification.name
+ tfmdata = constructors.scale(tfmdata, specification)
+ local allfeatures = tfmdata.shared.features or specification.features.normal
+ constructors.applymanipulators("afm",tfmdata,allfeatures,trace_features,report_afm)
+ fonts.loggers.register(tfmdata,'afm',specification)
+ end
+ return tfmdata
+end
+
+--[[ldx--
+Here comes the implementation of a few features. We only implement
+those that make sense for this format.
+--ldx]]--
+
+local function prepareligatures(tfmdata,ligatures,value)
+ if value then
+ local descriptions = tfmdata.descriptions
+ local hasligatures = false
+ for unicode, character in next, tfmdata.characters do
+ local description = descriptions[unicode]
+ local dligatures = description.ligatures
+ if dligatures then
+ local cligatures = character.ligatures
+ if not cligatures then
+ cligatures = { }
+ character.ligatures = cligatures
+ end
+ for unicode, ligature in next, dligatures do
+ cligatures[unicode] = {
+ char = ligature,
+ type = 0
+ }
+ end
+ hasligatures = true
+ end
+ end
+ tfmdata.properties.hasligatures = hasligatures
+ end
+end
+
+local function preparekerns(tfmdata,kerns,value)
+ if value then
+ local rawdata = tfmdata.shared.rawdata
+ local resources = rawdata.resources
+ local unicodes = resources.unicodes
+ local descriptions = tfmdata.descriptions
+ local haskerns = false
+ for u, chr in next, tfmdata.characters do
+ local d = descriptions[u]
+ local newkerns = d[kerns]
+ if newkerns then
+ local kerns = chr.kerns
+ if not kerns then
+ kerns = { }
+ chr.kerns = kerns
+ end
+ for k,v in next, newkerns do
+ local uk = unicodes[k]
+ if uk then
+ kerns[uk] = v
+ end
+ end
+ haskerns = true
+ end
+ end
+ tfmdata.properties.haskerns = haskerns
+ end
+end
+
+local list = {
+ -- [0x0022] = 0x201D,
+ [0x0027] = 0x2019,
+ -- [0x0060] = 0x2018,
+}
+
+local function texreplacements(tfmdata,value)
+ local descriptions = tfmdata.descriptions
+ local characters = tfmdata.characters
+ for k, v in next, list do
+ characters [k] = characters [v] -- we forget about kerns
+ descriptions[k] = descriptions[v] -- we forget about kerns
+ end
+end
+
+-- local function ligatures (tfmdata,value) prepareligatures(tfmdata,'ligatures', value) end
+-- local function texligatures(tfmdata,value) prepareligatures(tfmdata,'texligatures',value) end
+-- local function kerns (tfmdata,value) preparekerns (tfmdata,'kerns', value) end
+local function extrakerns (tfmdata,value) preparekerns (tfmdata,'extrakerns', value) 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,
+ }
+}
+
+registerafmfeature {
+ name = "features",
+ description = "features",
+ default = true,
+ initializers = {
+ node = otf.nodemodeinitializer,
+ base = otf.basemodeinitializer,
+ },
+ processors = {
+ node = otf.featuresprocessor,
+ }
+}
+
+-- readers
+
+local check_tfm = readers.check_tfm
+
+fonts.formats.afm = "type1"
+fonts.formats.pfb = "type1"
+
+local function check_afm(specification,fullname)
+ local foundname = findbinfile(fullname, 'afm') or "" -- just to be sure
+ if foundname == "" then
+ foundname = fonts.names.getfilename(fullname,"afm") or ""
+ end
+ if foundname == "" and afm.autoprefixed then
+ local encoding, shortname = match(fullname,"^(.-)%-(.*)$") -- context: encoding-name.*
+ if encoding and shortname and fonts.encodings.known[encoding] then
+ shortname = findbinfile(shortname,'afm') or "" -- just to be sure
+ if shortname ~= "" then
+ foundname = shortname
+ if trace_defining then
+ report_afm("stripping encoding prefix from filename %a",afmname)
+ end
+ end
+ end
+ end
+ if foundname ~= "" then
+ specification.filename = foundname
+ specification.format = "afm"
+ return read_from_afm(specification)
+ end
+end
+
+function readers.afm(specification,method)
+ local fullname, tfmdata = specification.filename or "", nil
+ if fullname == "" then
+ local forced = specification.forced or ""
+ if forced ~= "" then
+ tfmdata = check_afm(specification,specification.name .. "." .. forced)
+ end
+ if not tfmdata then
+ method = method or definers.method or "afm or tfm"
+ if method == "tfm" then
+ tfmdata = check_tfm(specification,specification.name)
+ elseif method == "afm" then
+ tfmdata = check_afm(specification,specification.name)
+ elseif method == "tfm or afm" then
+ tfmdata = check_tfm(specification,specification.name) or check_afm(specification,specification.name)
+ else -- method == "afm or tfm" or method == "" then
+ tfmdata = check_afm(specification,specification.name) or check_tfm(specification,specification.name)
+ end
+ end
+ else
+ tfmdata = check_afm(specification,fullname)
+ end
+ return tfmdata
+end
+
+function readers.pfb(specification,method) -- only called when forced
+ local original = specification.specification
+ if trace_defining then
+ report_afm("using afm reader for %a",original)
+ end
+ specification.specification = gsub(original,"%.pfb",".afm")
+ specification.forced = "afm"
+ return readers.afm(specification,method)
+end
diff --git a/src/luaotfload-init.lua b/src/luaotfload-init.lua
index bcc0e18..dfa4c56 100644
--- a/src/luaotfload-init.lua
+++ b/src/luaotfload-init.lua
@@ -251,8 +251,6 @@ local context_modules = {
{ ctx, "font-map" },
{ ltx, "luatex-fonts-syn" },
{ ctx, "font-tfm" },
- { ctx, "font-afm" },
- { ctx, "font-afk" },
{ ctx, "font-oti" },
{ ctx, "font-otr" },
{ ctx, "font-cff" },
@@ -265,6 +263,8 @@ local context_modules = {
{ ctx, "font-ota" },
{ ctx, "font-ots" },
{ ctx, "font-osd" },
+ { ctx, "font-one" },
+ { ctx, "font-afk" },
{ ctx, "font-lua" },
{ ctx, "font-def" },
{ ltx, "luatex-fonts-ext" },
@@ -509,8 +509,6 @@ local init_main = function ()
load_fontloader_module "font-map"
load_fontloader_module "fonts-syn"
load_fontloader_module "font-tfm"
- load_fontloader_module "font-afm"
- load_fontloader_module "font-afk"
load_fontloader_module "font-oti"
load_fontloader_module "font-otr"
load_fontloader_module "font-cff"
@@ -523,6 +521,8 @@ local init_main = function ()
load_fontloader_module "font-ota"
load_fontloader_module "font-ots"
load_fontloader_module "font-osd"
+ load_fontloader_module "font-one"
+ load_fontloader_module "font-afk"
load_fontloader_module "font-lua"
load_fontloader_module "font-def"
load_fontloader_module "fonts-ext"
diff --git a/src/luaotfload-tool.lua b/src/luaotfload-tool.lua
index 35dc9b3..a24643c 100755
--- a/src/luaotfload-tool.lua
+++ b/src/luaotfload-tool.lua
@@ -145,8 +145,6 @@ require "fontloader-fonts-enc"
require "fontloader-font-cid"
require "fontloader-font-map"
require "fontloader-font-tfm"
-require "fontloader-font-afm"
-require "fontloader-font-afk"
require "fontloader-font-oti"
require "fontloader-font-otr"
require "fontloader-font-cff"
@@ -159,6 +157,8 @@ require "fontloader-font-oto"
------- "fontloader-font-ota"
------- "fontloader-font-ots"
------- "fontloader-font-osd"
+require "fontloader-font-one"
+require "fontloader-font-afk"
require "fontloader-font-lua"
require "fontloader-font-def"
require "fontloader-fonts-ext"
--
cgit v1.2.3
From 73b4fc1146ada179e7783fd118aa7f1377a09e52 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Mon, 9 May 2016 08:04:13 +0200
Subject: [db] fix inclusion of AFM fonts
The assumption that the AFM/PFB pair will reside in the same directory
together is wrong for TeX Live. Hence the new lookup against kpse.
---
src/luaotfload-database.lua | 33 +++++++++++++++++++--------------
1 file changed, 19 insertions(+), 14 deletions(-)
diff --git a/src/luaotfload-database.lua b/src/luaotfload-database.lua
index 437091f..7434b72 100644
--- a/src/luaotfload-database.lua
+++ b/src/luaotfload-database.lua
@@ -207,8 +207,7 @@ local make_luanames = function (path)
end
local format_precedence = {
- "otf", "ttc", "ttf", "afm",
- -- "pfb" --- may come back before Luatex 1.0
+ "otf", "ttc", "ttf", "afm", "pfb"
}
local location_precedence = {
@@ -1664,7 +1663,8 @@ local loaders = {
otf = ot_fullinfo,
ttc = ot_fullinfo,
ttf = ot_fullinfo,
---- pfb = t1_fullinfo,
+ afm = t1_fullinfo,
+ pfb = t1_fullinfo,
}
--- not side-effect free!
@@ -2057,6 +2057,16 @@ do
end
end
+local locate_matching_pfb = function (afmfile, dir)
+ local pfbname = filereplacesuffix (afmfile, "pfb")
+ local pfbpath = dir .. "/" .. pfbname
+ if lfsisfile (pfbpath) then
+ return pfbpath
+ end
+ --- Check for match in texmf too
+ return kpsefind_file (pfbname, "type1 fonts")
+end
+
local process_dir_tree
process_dir_tree = function (acc, dirs)
if not next (dirs) then --- done
@@ -2084,12 +2094,10 @@ process_dir_tree = function (acc, dirs)
ent = stringlower (ent)
if lpegmatch (p_font_filter, ent) then
+ newfiles[#newfiles+1] = fullpath
if filesuffix (ent) == "afm" then
- --- fontloader.open() will load the afm
- --- iff both files are in the same directory
- local pfbpath = filereplacesuffix
- (fullpath, "pfb")
- if lfsisfile (pfbpath) then
+ local pfbpath = locate_matching_pfb (ent, dir)
+ if pfbpath then
newfiles[#newfiles+1] = pfbpath
end
else
@@ -2121,12 +2129,8 @@ local process_dir = function (dir)
if lpegmatch (p_font_filter, ent)
then
if filesuffix (ent) == "afm" then
- --- fontloader.open() will load the afm
- --- iff both files are in the same
- --- directory
- local pfbpath = filereplacesuffix
- (fullpath, "pfb")
- if lfsisfile (pfbpath) then
+ local pfbpath = locate_matching_pfb (ent, dir)
+ if pfbpath then
files[#files+1] = pfbpath
end
else
@@ -2261,6 +2265,7 @@ local collect_font_filenames_texmf = function ()
fontdirs = kpseexpand_path "$OPENTYPEFONTS"
fontdirs = fontdirs .. path_separator .. kpseexpand_path "$TTFONTS"
fontdirs = fontdirs .. path_separator .. kpseexpand_path "$T1FONTS"
+ fontdirs = fontdirs .. path_separator .. kpseexpand_path "$AFMFONTS"
if stringis_empty (fontdirs) then
return { }
--
cgit v1.2.3
From 5445ecc4583a34ab66d61bbce240a558b2db5b2b Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Mon, 9 May 2016 22:35:57 +0200
Subject: [tool] fix invocation of names.update()
---
src/luaotfload-tool.lua | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/luaotfload-tool.lua b/src/luaotfload-tool.lua
index a24643c..d01673d 100755
--- a/src/luaotfload-tool.lua
+++ b/src/luaotfload-tool.lua
@@ -797,7 +797,7 @@ actions.blacklist = function (job)
end
actions.generate = function (job)
- local _ = fonts.names.update (fontnames, job.force_reload, job.dry_run)
+ local _ = fonts.names.update ({ }, job.force_reload, job.dry_run)
local namedata = fonts.names.data ()
if namedata then
logreport ("info", 2, "db",
--
cgit v1.2.3
From bf6b707f32d39e417814d74c88d617ad42899d06 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Wed, 11 May 2016 07:44:49 +0200
Subject: [fontloader] sync with Context as of 2016-05-11
---
src/fontloader/misc/fontloader-font-map.lua | 228 ++++++-------
src/fontloader/misc/fontloader-font-one.lua | 343 +++++++++----------
src/fontloader/misc/fontloader-font-otl.lua | 2 +-
src/fontloader/misc/fontloader-font-oup.lua | 3 +-
src/fontloader/runtime/fontloader-reference.lua | 424 +++++++++++-------------
5 files changed, 457 insertions(+), 543 deletions(-)
diff --git a/src/fontloader/misc/fontloader-font-map.lua b/src/fontloader/misc/fontloader-font-map.lua
index 509e751..838c741 100644
--- a/src/fontloader/misc/fontloader-font-map.lua
+++ b/src/fontloader/misc/fontloader-font-map.lua
@@ -45,7 +45,7 @@ of obsolete. Some code may move to runtime or auxiliary modules.
-- end
-- end
-local hex = R("AF","09")
+local hex = R("AF","af","09")
----- hexfour = (hex*hex*hex*hex) / function(s) return tonumber(s,16) end
----- 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
@@ -295,145 +295,145 @@ function mappings.addtounicode(data,filename,checklookups)
local ns = 0
local nl = 0
--
- for unic, glyph in next, descriptions do
+ for du, glyph in next, descriptions do
local name = glyph.name
if name then
- local index = glyph.index
- local r = overloads[name]
- if r then
+ local overload = overloads[name]
+ if overload then
-- get rid of weird ligatures
- -- glyph.name = r.name
- 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
- -- cidmap heuristics, beware, there is no guarantee for a match unless
- -- the chain resolves
- if (not unicode) and usedmap then
- local foundindex = lpegmatch(oparser,name)
- if foundindex then
- unicode = cidcodes[foundindex] -- name to number
- if unicode then
- glyph.unicode = unicode
- ns = ns + 1
- else
- local reference = cidnames[foundindex] -- number to name
- if reference then
- local foundindex = lpegmatch(oparser,reference)
- if foundindex then
- unicode = cidcodes[foundindex]
- if unicode then
- glyph.unicode = unicode
- ns = ns + 1
+ -- glyph.name = overload.name
+ glyph.unicode = overload.unicode
+ else
+ local gu = glyph.unicode -- can already be set (number or table)
+ if not gu or gu == -1 or du >= private or (du >= 0xE000 and du <= 0xF8FF) or du == 0xFFFE or du == 0xFFFF then
+ local unicode = unicodevector[name] or contextvector[name]
+ if unicode then
+ glyph.unicode = unicode
+ ns = ns + 1
+ end
+ -- cidmap heuristics, beware, there is no guarantee for a match unless
+ -- the chain resolves
+ if (not unicode) and usedmap then
+ local foundindex = lpegmatch(oparser,name)
+ if foundindex then
+ unicode = cidcodes[foundindex] -- name to number
+ if unicode then
+ glyph.unicode = unicode
+ ns = ns + 1
+ else
+ local reference = cidnames[foundindex] -- number to name
+ 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
- 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
+ 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
- -- a.whatever or a_b_c.whatever or a_b_c (no numbers) a.b_
- --
- -- It is not trivial to find a solution that suits all fonts. We tried several alternatives
- -- and this one seems to work reasonable also with fonts that use less standardized naming
- -- schemes. The extra private test is tested by KE and seems to work okay with non-typical
- -- fonts as well.
- --
- if not unicode or unicode == "" then
- local split = lpegmatch(namesplitter,name)
- local nsplit = split and #split or 0 -- add if
- if nsplit == 0 then
- -- skip
- elseif nsplit == 1 then
- local base = split[1]
- local u = unicodes[base] or unicodevector[base] or contextvector[name]
- if not u then
+ -- a.whatever or a_b_c.whatever or a_b_c (no numbers) a.b_
+ --
+ -- It is not trivial to find a solution that suits all fonts. We tried several alternatives
+ -- and this one seems to work reasonable also with fonts that use less standardized naming
+ -- schemes. The extra private test is tested by KE and seems to work okay with non-typical
+ -- fonts as well.
+ --
+ if not unicode or unicode == "" then
+ local split = lpegmatch(namesplitter,name)
+ local nsplit = split and #split or 0 -- add if
+ if nsplit == 0 then
-- skip
- elseif type(u) == "table" then
- -- unlikely
- if u[1] < private then
- unicode = u
- glyph.unicode = unicode
- end
- elseif u < private then
- unicode = u
- glyph.unicode = unicode
- end
- else
- local t, n = { }, 0
- for l=1,nsplit do
- local base = split[l]
+ elseif nsplit == 1 then
+ local base = split[1]
local u = unicodes[base] or unicodevector[base] or contextvector[name]
if not u then
- break
+ -- skip
elseif type(u) == "table" then
- if u[1] >= private then
- break
+ -- unlikely
+ if u[1] < private then
+ unicode = u
+ glyph.unicode = unicode
end
- n = n + 1
- t[n] = u[1]
- else
- if u >= private then
+ elseif u < private then
+ unicode = u
+ glyph.unicode = unicode
+ end
+ else
+ 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
+ if n > 0 then
+ if n == 1 then
+ unicode = t[1]
+ else
+ unicode = t
end
- n = n + 1
- t[n] = u
+ glyph.unicode = unicode
end
end
- if n > 0 then
- if n == 1 then
- unicode = t[1]
+ nl = nl + 1
+ end
+ -- last resort (we might need to catch private here as well)
+ 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
- unicode = t
+ ns = ns + 1
+ unicode = foundcodes
end
- glyph.unicode = unicode
end
end
- nl = nl + 1
- end
- -- last resort (we might need to catch private here as well)
- 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
+ -- check using substitutes and alternates
+ local r = overloads[unicode]
+ if r then
+ unicode = r.unicode
+ glyph.unicode = unicode
+ end
+ --
+ if not unicode then
+ missing[du] = true
+ nofmissing = nofmissing + 1
end
- end
- -- check using substitutes and alternates
- 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
- else
- -- no name
end
end
if type(checklookups) == "function" then
diff --git a/src/fontloader/misc/fontloader-font-one.lua b/src/fontloader/misc/fontloader-font-one.lua
index 3602fd4..af32463 100644
--- a/src/fontloader/misc/fontloader-font-one.lua
+++ b/src/fontloader/misc/fontloader-font-one.lua
@@ -21,13 +21,13 @@ add features.
local fonts, logs, trackers, containers, resolvers = fonts, logs, trackers, containers, resolvers
-local next, type, tonumber = next, type, tonumber
+local next, type, tonumber, rawget = next, type, tonumber, rawget
local match, gmatch, lower, gsub, strip, find = string.match, string.gmatch, 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, lpegmatch, patterns = lpeg.P, lpeg.S, lpeg.R, lpeg.Cmt, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.match, lpeg.patterns
-local derivetable = table.derive
+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 lpegmatch, patterns = lpeg.match, lpeg.patterns
local trace_features = false trackers.register("afm.features", function(v) trace_features = v end)
local trace_indexing = false trackers.register("afm.indexing", function(v) trace_indexing = v end)
@@ -37,6 +37,7 @@ local trace_defining = false trackers.register("fonts.defining", function(v
local report_afm = logs.reporter("fonts","afm loading")
local setmetatableindex = table.setmetatableindex
+local derivetable = table.derive
local findbinfile = resolvers.findbinfile
@@ -54,7 +55,7 @@ local otfenhancers = otf.enhancers
local afmfeatures = constructors.newfeatures("afm")
local registerafmfeature = afmfeatures.register
-afm.version = 1.505 -- incrementing this number one up will force a re-cache
+afm.version = 1.507 -- incrementing this number one up will force a re-cache
afm.cache = containers.define("fonts", "afm", afm.version, true)
afm.autoprefixed = true -- this will become false some day (catches texnansi-blabla.*)
@@ -66,54 +67,55 @@ local overloads = fonts.mappings.overloads
local applyruntimefixes = fonts.treatments and fonts.treatments.applyfixes
--[[ldx--
-We start with the basic reader which we give a name similar to the
-built in and reader.
+We start with the basic reader which we give a name similar to the built in
+and reader.
--ldx]]--
---~ Comment FONTIDENTIFIER LMMATHSYMBOLS10
---~ Comment CODINGSCHEME TEX MATH SYMBOLS
---~ Comment DESIGNSIZE 10.0 pt
---~ Comment CHECKSUM O 4261307036
---~ Comment SPACE 0 plus 0 minus 0
---~ Comment QUAD 1000
---~ Comment EXTRASPACE 0
---~ Comment NUM 676.508 393.732 443.731
---~ Comment DENOM 685.951 344.841
---~ Comment SUP 412.892 362.892 288.889
---~ Comment SUB 150 247.217
---~ Comment SUPDROP 386.108
---~ Comment SUBDROP 50
---~ Comment DELIM 2390 1010
---~ Comment AXISHEIGHT 250
+-- Comment FONTIDENTIFIER LMMATHSYMBOLS10
+-- Comment CODINGSCHEME TEX MATH SYMBOLS
+-- Comment DESIGNSIZE 10.0 pt
+-- Comment CHECKSUM O 4261307036
+-- Comment SPACE 0 plus 0 minus 0
+-- Comment QUAD 1000
+-- Comment EXTRASPACE 0
+-- Comment NUM 676.508 393.732 443.731
+-- Comment DENOM 685.951 344.841
+-- Comment SUP 412.892 362.892 288.889
+-- Comment SUB 150 247.217
+-- Comment SUPDROP 386.108
+-- Comment SUBDROP 50
+-- Comment DELIM 2390 1010
+-- Comment AXISHEIGHT 250
local comment = P("Comment")
local spacing = patterns.spacer -- S(" \t")^1
local lineend = patterns.newline -- S("\n\r")
-local words = C((1 - lineend)^1)
-local number = C((R("09") + S("."))^1) / tonumber * spacing^0
-local data = lpeg.Carg(1)
+local words = spacing * C((1 - lineend)^1)
+local number = spacing * C((R("09") + S("."))^1) / tonumber * spacing^0
+local data = Carg(1)
+local plus = P("plus") * number
+local minus = P("minus") * number
local pattern = ( -- needs testing ... not used anyway as we no longer need math afm's
- comment * spacing *
- (
- data * (
- ("CODINGSCHEME" * spacing * words ) / function(fd,a) end +
- ("DESIGNSIZE" * spacing * number * words ) / function(fd,a) fd[ 1] = a end +
- ("CHECKSUM" * spacing * number * words ) / function(fd,a) fd[ 2] = a end +
- ("SPACE" * spacing * number * "plus" * number * "minus" * number) / function(fd,a,b,c) fd[ 3], fd[ 4], fd[ 5] = a, b, c end +
- ("QUAD" * spacing * number ) / function(fd,a) fd[ 6] = a end +
- ("EXTRASPACE" * spacing * number ) / function(fd,a) fd[ 7] = a end +
- ("NUM" * spacing * number * number * number ) / function(fd,a,b,c) fd[ 8], fd[ 9], fd[10] = a, b, c end +
- ("DENOM" * spacing * number * number ) / function(fd,a,b ) fd[11], fd[12] = a, b end +
- ("SUP" * spacing * number * number * number ) / function(fd,a,b,c) fd[13], fd[14], fd[15] = a, b, c end +
- ("SUB" * spacing * number * number ) / function(fd,a,b) fd[16], fd[17] = a, b end +
- ("SUPDROP" * spacing * number ) / function(fd,a) fd[18] = a end +
- ("SUBDROP" * spacing * number ) / function(fd,a) fd[19] = a end +
- ("DELIM" * spacing * number * number ) / function(fd,a,b) fd[20], fd[21] = a, b end +
- ("AXISHEIGHT" * spacing * number ) / function(fd,a) fd[22] = a end
- )
- + (1-lineend)^0
+ comment * spacing * (
+ data * (
+ ("CODINGSCHEME" * words ) / function(t,a) end +
+ ("DESIGNSIZE" * number * words ) / function(t,a) t[ 1] = a end +
+ ("CHECKSUM" * number * words ) / function(t,a) t[ 2] = a end +
+ ("SPACE" * number * plus * minus ) / function(t,a,b,c) t[ 3], t[ 4], t[ 5] = a, b, c end +
+ ("QUAD" * number ) / function(t,a) t[ 6] = a end +
+ ("EXTRASPACE" * number ) / function(t,a) t[ 7] = a end +
+ ("NUM" * number * number * number ) / function(t,a,b,c) t[ 8], t[ 9], t[10] = a, b, c end +
+ ("DENOM" * number * number ) / function(t,a,b) t[11], t[12] = a, b end +
+ ("SUP" * number * number * number ) / function(t,a,b,c) t[13], t[14], t[15] = a, b, c end +
+ ("SUB" * number * number ) / function(t,a,b) t[16], t[17] = a, b end +
+ ("SUPDROP" * number ) / function(t,a) t[18] = a end +
+ ("SUBDROP" * number ) / function(t,a) t[19] = a end +
+ ("DELIM" * number * number ) / function(t,a,b) t[20], t[21] = a, b end +
+ ("AXISHEIGHT" * number ) / function(t,a) t[22] = a end
)
+ + (1-lineend)^0
+ )
+ (1-comment)^1
)^0
@@ -123,27 +125,47 @@ local function scan_comment(str)
return fd
end
--- On a rainy day I will rewrite this in lpeg ... or we can use the (slower) fontloader
--- as in now supports afm/pfb loading but it's not too bad to have different methods
--- for testing approaches.
-
-local keys = { }
-
-function keys.FontName (data,line) data.metadata.fontname = strip (line) -- get rid of spaces
- data.metadata.fullname = strip (line) end
-function keys.ItalicAngle (data,line) data.metadata.italicangle = tonumber (line) 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
-function keys.Ascender (data,line) data.metadata.ascender = tonumber (line) end
-function keys.Comment (data,line)
- -- Comment DesignSize 12 (pts)
- -- Comment TFM designsize: 12 (in points)
- line = lower(line)
- local designsize = match(line,"designsize[^%d]*(%d+)")
- if designsize then data.metadata.designsize = tonumber(designsize) end
-end
+-- Comment DesignSize 12 (pts)
+-- Comment TFM designsize: 12 (in points)
+
+local keys = {
+
+ FontName = function(data,line)
+ data.metadata.fontname = strip(line) -- get rid of spaces
+ data.metadata.fullname = strip(line)
+ end,
+
+ ItalicAngle = function(data,line)
+ data.metadata.italicangle = tonumber(line)
+ end,
+
+ IsFixedPitch = function(data,line)
+ data.metadata.monospaced = toboolean(line,true)
+ end,
+
+ CharWidth = function(data,line)
+ data.metadata.charwidth = tonumber(line)
+ end,
+
+ XHeight = function(data,line)
+ data.metadata.xheight = tonumber(line)
+ end,
+
+ Descender = function(data,line)
+ data.metadata.descender = tonumber (line)
+ end,
+
+ Ascender = function(data,line)
+ data.metadata.ascender = tonumber (line)
+ end,
+
+ Comment = function(data,line)
+ line = lower(line)
+ local designsize = match(line,"designsize[^%d]*(%d+)")
+ if designsize then data.metadata.designsize = tonumber(designsize) end
+ end,
+
+}
local function get_charmetrics(data,charmetrics,vector)
local characters = data.characters
@@ -202,8 +224,10 @@ local function get_variables(data,fontmetrics)
end
end
--- new (unfinished) pfb loader but i see no differences between
--- old and new (one bad vector with old)
+--[[ldx--
+We now use a new (unfinished) pfb loader but I see no differences between the old
+and new vectors (we actually had one bad vector with the old loader).
+--ldx]]--
local get_indexes
@@ -353,29 +377,30 @@ local function readafm(filename)
-- the final store
},
}
- afmblob = gsub(afmblob,"StartCharMetrics(.-)EndCharMetrics", function(charmetrics)
+-- afmblob = gsub(afmblob,"StartCharMetrics(.-)EndCharMetrics", function(charmetrics)
+ for charmetrics in gmatch(afmblob,"StartCharMetrics(.-)EndCharMetrics") do
if trace_loading then
report_afm("loading char metrics")
end
get_charmetrics(data,charmetrics,vector)
- return ""
- end)
- afmblob = gsub(afmblob,"StartKernPairs(.-)EndKernPairs", function(kernpairs)
+ break
+ end
+ for kernpairs in gmatch(afmblob,"StartKernPairs(.-)EndKernPairs") do
if trace_loading then
report_afm("loading kern pairs")
end
get_kernpairs(data,kernpairs)
- return ""
- end)
- afmblob = gsub(afmblob,"StartFontMetrics%s+([%d%.]+)(.-)EndFontMetrics", function(version,fontmetrics)
+ break
+ end
+ for version, fontmetrics in gmatch(afmblob,"StartFontMetrics%s+([%d%.]+)(.-)EndFontMetrics") do
if trace_loading then
report_afm("loading variables")
end
data.afmversion = version
get_variables(data,fontmetrics)
data.fontdimens = scan_comment(fontmetrics) -- todo: all lpeg, no time now
- return ""
- end)
+ break
+ end
return data
else
if trace_loading then
@@ -391,10 +416,38 @@ ligatures and kern information to the afm derived data. That way we can set them
when defining a font.
We still keep the loading two phased: first we load the data in a traditional
-fashion and later we transform it to sequences.
+fashion and later we transform it to sequences. Then we apply some methods also
+used in opentype fonts (like tlig).
--ldx]]--
-local addkerns, unify, normalize, fixnames, addligatures, addtexligatures
+local enhancers = {
+ -- It's cleaner to implement them after we've seen what we are
+ -- dealing with.
+}
+
+local steps = {
+ "unify names",
+ "add ligatures",
+ "add extra kerns",
+ "normalize features",
+ "fix names",
+-- "add tounicode data",
+}
+
+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_afm("applying enhancer %a",step)
+ end
+ enhancer(data,filename)
+ else
+ report_afm("invalid enhancer %a",step)
+ end
+ end
+end
function afm.load(filename)
filename = resolvers.findfile(filename,'afm') or ""
@@ -427,29 +480,7 @@ function afm.load(filename)
-- data.resources.filename = "unset" -- better than loading the afm file
end
-- we now have all the data loaded
- if trace_loading then
- report_afm("unifying %a",filename)
- end
- unify(data,filename)
- if trace_loading then
- report_afm("add ligatures") -- there can be missing ones
- end
- addligatures(data)
- if trace_loading then
- report_afm("add extra kerns")
- end
- addkerns(data)
- if trace_loading then
- report_afm("normalizing")
- end
- normalize(data)
- if trace_loading then
- report_afm("fixing names")
- end
- fixnames(data)
- if trace_loading then
- report_afm("add tounicode data")
- end
+ applyenhancers(data,filename)
-- otfreaders.addunicodetable(data) -- only when not done yet
fonts.mappings.addtounicode(data,filename)
-- otfreaders.extend(data)
@@ -475,14 +506,14 @@ function afm.load(filename)
end
end
return data
- else
- return nil
end
end
-local uparser = fonts.mappings.makenameparser()
+-- we run a more advanced analyzer later on anyway
-unify = function(data, filename)
+local uparser = fonts.mappings.makenameparser() -- each time
+
+enhancers["unify names"] = function(data, filename)
local unicodevector = fonts.encodings.agl.unicodes -- loaded runtime in context
local unicodes = { }
local names = { }
@@ -492,7 +523,7 @@ unify = function(data, filename)
local code = unicodevector[name] -- or characters.name_to_unicode[name]
if not code then
code = lpegmatch(uparser,name)
- if not code then
+ if type(code) ~= "number" then
code = private
private = private + 1
report_afm("assigning private slot %U for unknown glyph name %a",code,name)
@@ -538,7 +569,7 @@ end
local everywhere = { ["*"] = { ["*"] = true } } -- or: { ["*"] = { "*" } }
local noflags = { false, false, false, false }
-normalize = function(data)
+enhancers["normalize features"] = function(data)
local ligatures = setmetatableindex("table")
local kerns = setmetatableindex("table")
local extrakerns = setmetatableindex("table")
@@ -639,7 +670,7 @@ normalize = function(data)
data.resources.sequences = sequences
end
-fixnames = function(data)
+enhancers["fix names"] = function(data)
for k, v in next, data.descriptions do
local n = v.name
local r = overloads[n]
@@ -686,8 +717,13 @@ local addthem = function(rawdata,ligatures)
end
end
-addligatures = function(rawdata) addthem(rawdata,afm.helpdata.ligatures ) end
-addtexligatures = function(rawdata) addthem(rawdata,afm.helpdata.texligatures) end
+enhancers["add ligatures"] = function(rawdata)
+ addthem(rawdata,afm.helpdata.ligatures)
+end
+
+-- enhancers["add tex ligatures"] = function(rawdata)
+-- addthem(rawdata,afm.helpdata.texligatures)
+-- end
--[[ldx--
We keep the extra kerns in separate kerning tables so that we can use
@@ -701,7 +737,7 @@ them selectively.
-- we don't use the character database. (Ok, we can have a context specific
-- variant).
-addkerns = function(rawdata) -- using shcodes is not robust here
+enhancers["add extra kerns"] = function(rawdata) -- using shcodes is not robust here
local descriptions = rawdata.descriptions
local resources = rawdata.resources
local unicodes = resources.unicodes
@@ -929,10 +965,9 @@ local function copytotfm(data)
end
--[[ldx--
-Originally we had features kind of hard coded for
-files but since I expect to support more font formats, I decided
-to treat this fontformat like any other and handle features in a
-more configurable way.
+Originally we had features kind of hard coded for files but since I
+expect to support more font formats, I decided to treat this fontformat like any
+other and handle features in a more configurable way.
--ldx]]--
function afm.setfeatures(tfmdata,features)
@@ -1046,85 +1081,9 @@ local function read_from_afm(specification)
end
--[[ldx--
-Here comes the implementation of a few features. We only implement
-those that make sense for this format.
+We have the usual two modes and related features initializers and processors.
--ldx]]--
-local function prepareligatures(tfmdata,ligatures,value)
- if value then
- local descriptions = tfmdata.descriptions
- local hasligatures = false
- for unicode, character in next, tfmdata.characters do
- local description = descriptions[unicode]
- local dligatures = description.ligatures
- if dligatures then
- local cligatures = character.ligatures
- if not cligatures then
- cligatures = { }
- character.ligatures = cligatures
- end
- for unicode, ligature in next, dligatures do
- cligatures[unicode] = {
- char = ligature,
- type = 0
- }
- end
- hasligatures = true
- end
- end
- tfmdata.properties.hasligatures = hasligatures
- end
-end
-
-local function preparekerns(tfmdata,kerns,value)
- if value then
- local rawdata = tfmdata.shared.rawdata
- local resources = rawdata.resources
- local unicodes = resources.unicodes
- local descriptions = tfmdata.descriptions
- local haskerns = false
- for u, chr in next, tfmdata.characters do
- local d = descriptions[u]
- local newkerns = d[kerns]
- if newkerns then
- local kerns = chr.kerns
- if not kerns then
- kerns = { }
- chr.kerns = kerns
- end
- for k,v in next, newkerns do
- local uk = unicodes[k]
- if uk then
- kerns[uk] = v
- end
- end
- haskerns = true
- end
- end
- tfmdata.properties.haskerns = haskerns
- end
-end
-
-local list = {
- -- [0x0022] = 0x201D,
- [0x0027] = 0x2019,
- -- [0x0060] = 0x2018,
-}
-
-local function texreplacements(tfmdata,value)
- local descriptions = tfmdata.descriptions
- local characters = tfmdata.characters
- for k, v in next, list do
- characters [k] = characters [v] -- we forget about kerns
- descriptions[k] = descriptions[v] -- we forget about kerns
- end
-end
-
--- local function ligatures (tfmdata,value) prepareligatures(tfmdata,'ligatures', value) end
--- local function texligatures(tfmdata,value) prepareligatures(tfmdata,'texligatures',value) end
--- local function kerns (tfmdata,value) preparekerns (tfmdata,'kerns', value) end
-local function extrakerns (tfmdata,value) preparekerns (tfmdata,'extrakerns', value) end
-
local function setmode(tfmdata,value)
if value then
tfmdata.properties.mode = lower(value)
@@ -1214,7 +1173,7 @@ function readers.pfb(specification,method) -- only called when forced
if trace_defining then
report_afm("using afm reader for %a",original)
end
- specification.specification = gsub(original,"%.pfb",".afm")
+ specification.specification = file.replacesuffix(original,"afm")
specification.forced = "afm"
return readers.afm(specification,method)
end
diff --git a/src/fontloader/misc/fontloader-font-otl.lua b/src/fontloader/misc/fontloader-font-otl.lua
index 01342a9..304b6b9 100644
--- a/src/fontloader/misc/fontloader-font-otl.lua
+++ b/src/fontloader/misc/fontloader-font-otl.lua
@@ -53,7 +53,7 @@ local report_otf = logs.reporter("fonts","otf loading")
local fonts = fonts
local otf = fonts.handlers.otf
-otf.version = 3.019 -- beware: also sync font-mis.lua and in mtx-fonts
+otf.version = 3.020 -- beware: also sync font-mis.lua and in mtx-fonts
otf.cache = containers.define("fonts", "otl", otf.version, true)
local otfreaders = otf.readers
diff --git a/src/fontloader/misc/fontloader-font-oup.lua b/src/fontloader/misc/fontloader-font-oup.lua
index 3b6d8ea..bd47e71 100644
--- a/src/fontloader/misc/fontloader-font-oup.lua
+++ b/src/fontloader/misc/fontloader-font-oup.lua
@@ -586,7 +586,8 @@ local function checklookups(fontdata,missing,nofmissing)
local done = { }
for i, r in next, missing do
if r then
- local name = descriptions[i].name or f_index(i)
+ local data = descriptions[i]
+ local name = data and data.name or f_index(i)
if not ignore[name] then
done[name] = true
end
diff --git a/src/fontloader/runtime/fontloader-reference.lua b/src/fontloader/runtime/fontloader-reference.lua
index 3e6f1d1..b848937 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 : 05/08/16 17:30:49
+-- merge date : 05/10/16 23:43:55
do -- begin closure to overcome local limits and interference
@@ -6414,7 +6414,7 @@ local fonts=fonts or {}
local mappings=fonts.mappings or {}
fonts.mappings=mappings
local allocate=utilities.storage.allocate
-local hex=R("AF","09")
+local hex=R("AF","af","09")
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
@@ -6549,127 +6549,128 @@ function mappings.addtounicode(data,filename,checklookups)
end
local ns=0
local nl=0
- for unic,glyph in next,descriptions do
+ for du,glyph in next,descriptions do
local name=glyph.name
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
- 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
+ local overload=overloads[name]
+ if overload then
+ glyph.unicode=overload.unicode
+ else
+ local gu=glyph.unicode
+ if not gu or gu==-1 or du>=private or (du>=0xE000 and du<=0xF8FF) or du==0xFFFE or du==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
- 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
- break
+ if u[1]=private then
+ elseif u=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
- n=n+1
- t[n]=u
+ end
+ if n>0 then
+ if n==1 then
+ unicode=t[1]
+ else
+ unicode=t
+ end
+ glyph.unicode=unicode
end
end
- if n>0 then
- if n==1 then
- unicode=t[1]
+ 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
- unicode=t
+ ns=ns+1
+ unicode=foundcodes
end
- glyph.unicode=unicode
end
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
+ local r=overloads[unicode]
+ if r then
+ unicode=r.unicode
+ glyph.unicode=unicode
+ end
+ if not unicode then
+ missing[du]=true
+ nofmissing=nofmissing+1
end
- end
- 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
- else
end
end
if type(checklookups)=="function" then
@@ -13052,7 +13053,8 @@ local function checklookups(fontdata,missing,nofmissing)
local done={}
for i,r in next,missing do
if r then
- local name=descriptions[i].name or f_index(i)
+ local data=descriptions[i]
+ local name=data and data.name or f_index(i)
if not ignore[name] then
done[name]=true
end
@@ -14514,7 +14516,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.019
+otf.version=3.020
otf.cache=containers.define("fonts","otl",otf.version,true)
local otfreaders=otf.readers
local hashes=fonts.hashes
@@ -22260,19 +22262,20 @@ if not modules then modules={} end modules ['font-one']={
license="see context related readme files"
}
local fonts,logs,trackers,containers,resolvers=fonts,logs,trackers,containers,resolvers
-local next,type,tonumber=next,type,tonumber
+local next,type,tonumber,rawget=next,type,tonumber,rawget
local match,gmatch,lower,gsub,strip,find=string.match,string.gmatch,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,lpegmatch,patterns=lpeg.P,lpeg.S,lpeg.R,lpeg.Cmt,lpeg.C,lpeg.Ct,lpeg.Cs,lpeg.match,lpeg.patterns
-local derivetable=table.derive
+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 lpegmatch,patterns=lpeg.match,lpeg.patterns
local trace_features=false trackers.register("afm.features",function(v) trace_features=v end)
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 trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end)
local report_afm=logs.reporter("fonts","afm loading")
local setmetatableindex=table.setmetatableindex
+local derivetable=table.derive
local findbinfile=resolvers.findbinfile
local definers=fonts.definers
local readers=fonts.readers
@@ -22284,7 +22287,7 @@ local otfreaders=otf.readers
local otfenhancers=otf.enhancers
local afmfeatures=constructors.newfeatures("afm")
local registerafmfeature=afmfeatures.register
-afm.version=1.505
+afm.version=1.507
afm.cache=containers.define("fonts","afm",afm.version,true)
afm.autoprefixed=true
afm.helpdata={}
@@ -22294,35 +22297,52 @@ local applyruntimefixes=fonts.treatments and fonts.treatments.applyfixes
local comment=P("Comment")
local spacing=patterns.spacer
local lineend=patterns.newline
-local words=C((1-lineend)^1)
-local number=C((R("09")+S("."))^1)/tonumber*spacing^0
-local data=lpeg.Carg(1)
+local words=spacing*C((1-lineend)^1)
+local number=spacing*C((R("09")+S("."))^1)/tonumber*spacing^0
+local data=Carg(1)
+local plus=P("plus")*number
+local minus=P("minus")*number
local pattern=(
comment*spacing*(
- data*(
- ("CODINGSCHEME"*spacing*words )/function(fd,a) end+("DESIGNSIZE"*spacing*number*words )/function(fd,a) fd[ 1]=a end+("CHECKSUM"*spacing*number*words )/function(fd,a) fd[ 2]=a end+("SPACE"*spacing*number*"plus"*number*"minus"*number)/function(fd,a,b,c) fd[ 3],fd[ 4],fd[ 5]=a,b,c end+("QUAD"*spacing*number )/function(fd,a) fd[ 6]=a end+("EXTRASPACE"*spacing*number )/function(fd,a) fd[ 7]=a end+("NUM"*spacing*number*number*number )/function(fd,a,b,c) fd[ 8],fd[ 9],fd[10]=a,b,c end+("DENOM"*spacing*number*number )/function(fd,a,b ) fd[11],fd[12]=a,b end+("SUP"*spacing*number*number*number )/function(fd,a,b,c) fd[13],fd[14],fd[15]=a,b,c end+("SUB"*spacing*number*number )/function(fd,a,b) fd[16],fd[17]=a,b end+("SUPDROP"*spacing*number )/function(fd,a) fd[18]=a end+("SUBDROP"*spacing*number )/function(fd,a) fd[19]=a end+("DELIM"*spacing*number*number )/function(fd,a,b) fd[20],fd[21]=a,b end+("AXISHEIGHT"*spacing*number )/function(fd,a) fd[22]=a end
- )+(1-lineend)^0
- )+(1-comment)^1
+ data*(
+ ("CODINGSCHEME"*words )/function(t,a) end+("DESIGNSIZE"*number*words )/function(t,a) t[ 1]=a end+("CHECKSUM"*number*words )/function(t,a) t[ 2]=a end+("SPACE"*number*plus*minus )/function(t,a,b,c) t[ 3],t[ 4],t[ 5]=a,b,c end+("QUAD"*number )/function(t,a) t[ 6]=a end+("EXTRASPACE"*number )/function(t,a) t[ 7]=a end+("NUM"*number*number*number )/function(t,a,b,c) t[ 8],t[ 9],t[10]=a,b,c end+("DENOM"*number*number )/function(t,a,b) t[11],t[12]=a,b end+("SUP"*number*number*number )/function(t,a,b,c) t[13],t[14],t[15]=a,b,c end+("SUB"*number*number )/function(t,a,b) t[16],t[17]=a,b end+("SUPDROP"*number )/function(t,a) t[18]=a end+("SUBDROP"*number )/function(t,a) t[19]=a end+("DELIM"*number*number )/function(t,a,b) t[20],t[21]=a,b end+("AXISHEIGHT"*number )/function(t,a) t[22]=a end
+ )+(1-lineend)^0
+ )+(1-comment)^1
)^0
local function scan_comment(str)
local fd={}
lpegmatch(pattern,str,1,fd)
return fd
end
-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.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
-function keys.Ascender (data,line) data.metadata.ascender=tonumber (line) end
-function keys.Comment (data,line)
- line=lower(line)
- local designsize=match(line,"designsize[^%d]*(%d+)")
- if designsize then data.metadata.designsize=tonumber(designsize) end
-end
+local keys={
+ FontName=function(data,line)
+ data.metadata.fontname=strip(line)
+ data.metadata.fullname=strip(line)
+ end,
+ ItalicAngle=function(data,line)
+ data.metadata.italicangle=tonumber(line)
+ end,
+ IsFixedPitch=function(data,line)
+ data.metadata.monospaced=toboolean(line,true)
+ end,
+ CharWidth=function(data,line)
+ data.metadata.charwidth=tonumber(line)
+ end,
+ XHeight=function(data,line)
+ data.metadata.xheight=tonumber(line)
+ end,
+ Descender=function(data,line)
+ data.metadata.descender=tonumber (line)
+ end,
+ Ascender=function(data,line)
+ data.metadata.ascender=tonumber (line)
+ end,
+ Comment=function(data,line)
+ line=lower(line)
+ local designsize=match(line,"designsize[^%d]*(%d+)")
+ if designsize then data.metadata.designsize=tonumber(designsize) end
+ end,
+}
local function get_charmetrics(data,charmetrics,vector)
local characters=data.characters
local chr,ind={},0
@@ -22483,29 +22503,29 @@ local function readafm(filename)
descriptions={
},
}
- afmblob=gsub(afmblob,"StartCharMetrics(.-)EndCharMetrics",function(charmetrics)
+ for charmetrics in gmatch(afmblob,"StartCharMetrics(.-)EndCharMetrics") do
if trace_loading then
report_afm("loading char metrics")
end
get_charmetrics(data,charmetrics,vector)
- return ""
- end)
- afmblob=gsub(afmblob,"StartKernPairs(.-)EndKernPairs",function(kernpairs)
+ break
+ end
+ for kernpairs in gmatch(afmblob,"StartKernPairs(.-)EndKernPairs") do
if trace_loading then
report_afm("loading kern pairs")
end
get_kernpairs(data,kernpairs)
- return ""
- end)
- afmblob=gsub(afmblob,"StartFontMetrics%s+([%d%.]+)(.-)EndFontMetrics",function(version,fontmetrics)
+ break
+ end
+ for version,fontmetrics in gmatch(afmblob,"StartFontMetrics%s+([%d%.]+)(.-)EndFontMetrics") do
if trace_loading then
report_afm("loading variables")
end
data.afmversion=version
get_variables(data,fontmetrics)
data.fontdimens=scan_comment(fontmetrics)
- return ""
- end)
+ break
+ end
return data
else
if trace_loading then
@@ -22514,7 +22534,29 @@ local function readafm(filename)
return nil
end
end
-local addkerns,unify,normalize,fixnames,addligatures,addtexligatures
+local enhancers={
+}
+local steps={
+ "unify names",
+ "add ligatures",
+ "add extra kerns",
+ "normalize features",
+ "fix names",
+}
+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_afm("applying enhancer %a",step)
+ end
+ enhancer(data,filename)
+ else
+ report_afm("invalid enhancer %a",step)
+ end
+ end
+end
function afm.load(filename)
filename=resolvers.findfile(filename,'afm') or ""
if filename~="" and not fonts.names.ignoredfile(filename) then
@@ -22543,29 +22585,7 @@ function afm.load(filename)
elseif trace_loading then
report_afm("no pfb file for %a",filename)
end
- if trace_loading then
- report_afm("unifying %a",filename)
- end
- unify(data,filename)
- if trace_loading then
- report_afm("add ligatures")
- end
- addligatures(data)
- if trace_loading then
- report_afm("add extra kerns")
- end
- addkerns(data)
- if trace_loading then
- report_afm("normalizing")
- end
- normalize(data)
- if trace_loading then
- report_afm("fixing names")
- end
- fixnames(data)
- if trace_loading then
- report_afm("add tounicode data")
- end
+ applyenhancers(data,filename)
fonts.mappings.addtounicode(data,filename)
otfreaders.pack(data)
data.size=size
@@ -22587,12 +22607,10 @@ function afm.load(filename)
end
end
return data
- else
- return nil
end
end
-local uparser=fonts.mappings.makenameparser()
-unify=function(data,filename)
+local uparser=fonts.mappings.makenameparser()
+enhancers["unify names"]=function(data,filename)
local unicodevector=fonts.encodings.agl.unicodes
local unicodes={}
local names={}
@@ -22602,7 +22620,7 @@ unify=function(data,filename)
local code=unicodevector[name]
if not code then
code=lpegmatch(uparser,name)
- if not code then
+ if type(code)~="number" then
code=private
private=private+1
report_afm("assigning private slot %U for unknown glyph name %a",code,name)
@@ -22644,7 +22662,7 @@ unify=function(data,filename)
end
local everywhere={ ["*"]={ ["*"]=true } }
local noflags={ false,false,false,false }
-normalize=function(data)
+enhancers["normalize features"]=function(data)
local ligatures=setmetatableindex("table")
local kerns=setmetatableindex("table")
local extrakerns=setmetatableindex("table")
@@ -22742,7 +22760,7 @@ normalize=function(data)
data.resources.features=features
data.resources.sequences=sequences
end
-fixnames=function(data)
+enhancers["fix names"]=function(data)
for k,v in next,data.descriptions do
local n=v.name
local r=overloads[n]
@@ -22781,9 +22799,10 @@ local addthem=function(rawdata,ligatures)
end
end
end
-addligatures=function(rawdata) addthem(rawdata,afm.helpdata.ligatures ) end
-addtexligatures=function(rawdata) addthem(rawdata,afm.helpdata.texligatures) end
-addkerns=function(rawdata)
+enhancers["add ligatures"]=function(rawdata)
+ addthem(rawdata,afm.helpdata.ligatures)
+end
+enhancers["add extra kerns"]=function(rawdata)
local descriptions=rawdata.descriptions
local resources=rawdata.resources
local unicodes=resources.unicodes
@@ -23083,71 +23102,6 @@ local function read_from_afm(specification)
end
return tfmdata
end
-local function prepareligatures(tfmdata,ligatures,value)
- if value then
- local descriptions=tfmdata.descriptions
- local hasligatures=false
- for unicode,character in next,tfmdata.characters do
- local description=descriptions[unicode]
- local dligatures=description.ligatures
- if dligatures then
- local cligatures=character.ligatures
- if not cligatures then
- cligatures={}
- character.ligatures=cligatures
- end
- for unicode,ligature in next,dligatures do
- cligatures[unicode]={
- char=ligature,
- type=0
- }
- end
- hasligatures=true
- end
- end
- tfmdata.properties.hasligatures=hasligatures
- end
-end
-local function preparekerns(tfmdata,kerns,value)
- if value then
- local rawdata=tfmdata.shared.rawdata
- local resources=rawdata.resources
- local unicodes=resources.unicodes
- local descriptions=tfmdata.descriptions
- local haskerns=false
- for u,chr in next,tfmdata.characters do
- local d=descriptions[u]
- local newkerns=d[kerns]
- if newkerns then
- local kerns=chr.kerns
- if not kerns then
- kerns={}
- chr.kerns=kerns
- end
- for k,v in next,newkerns do
- local uk=unicodes[k]
- if uk then
- kerns[uk]=v
- end
- end
- haskerns=true
- end
- end
- tfmdata.properties.haskerns=haskerns
- end
-end
-local list={
- [0x0027]=0x2019,
-}
-local function texreplacements(tfmdata,value)
- local descriptions=tfmdata.descriptions
- local characters=tfmdata.characters
- for k,v in next,list do
- characters [k]=characters [v]
- descriptions[k]=descriptions[v]
- end
-end
-local function extrakerns (tfmdata,value) preparekerns (tfmdata,'extrakerns',value) end
local function setmode(tfmdata,value)
if value then
tfmdata.properties.mode=lower(value)
@@ -23228,7 +23182,7 @@ function readers.pfb(specification,method)
if trace_defining then
report_afm("using afm reader for %a",original)
end
- specification.specification=gsub(original,"%.pfb",".afm")
+ specification.specification=file.replacesuffix(original,"afm")
specification.forced="afm"
return readers.afm(specification,method)
end
--
cgit v1.2.3
From d20186dc4653791d1ebb8eb4be9c05716879686f Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Thu, 12 May 2016 20:09:38 +0200
Subject: [fontloader] import new AFM loader directly from Hans
---
src/fontloader/misc/fontloader-font-one.lua | 382 ++++++++++++++++------------
1 file changed, 216 insertions(+), 166 deletions(-)
diff --git a/src/fontloader/misc/fontloader-font-one.lua b/src/fontloader/misc/fontloader-font-one.lua
index af32463..b2446db 100644
--- a/src/fontloader/misc/fontloader-font-one.lua
+++ b/src/fontloader/misc/fontloader-font-one.lua
@@ -87,143 +87,6 @@ and reader.
-- Comment DELIM 2390 1010
-- Comment AXISHEIGHT 250
-local comment = P("Comment")
-local spacing = patterns.spacer -- S(" \t")^1
-local lineend = patterns.newline -- S("\n\r")
-local words = spacing * C((1 - lineend)^1)
-local number = spacing * C((R("09") + S("."))^1) / tonumber * spacing^0
-local data = Carg(1)
-local plus = P("plus") * number
-local minus = P("minus") * number
-
-local pattern = ( -- needs testing ... not used anyway as we no longer need math afm's
- comment * spacing * (
- data * (
- ("CODINGSCHEME" * words ) / function(t,a) end +
- ("DESIGNSIZE" * number * words ) / function(t,a) t[ 1] = a end +
- ("CHECKSUM" * number * words ) / function(t,a) t[ 2] = a end +
- ("SPACE" * number * plus * minus ) / function(t,a,b,c) t[ 3], t[ 4], t[ 5] = a, b, c end +
- ("QUAD" * number ) / function(t,a) t[ 6] = a end +
- ("EXTRASPACE" * number ) / function(t,a) t[ 7] = a end +
- ("NUM" * number * number * number ) / function(t,a,b,c) t[ 8], t[ 9], t[10] = a, b, c end +
- ("DENOM" * number * number ) / function(t,a,b) t[11], t[12] = a, b end +
- ("SUP" * number * number * number ) / function(t,a,b,c) t[13], t[14], t[15] = a, b, c end +
- ("SUB" * number * number ) / function(t,a,b) t[16], t[17] = a, b end +
- ("SUPDROP" * number ) / function(t,a) t[18] = a end +
- ("SUBDROP" * number ) / function(t,a) t[19] = a end +
- ("DELIM" * number * number ) / function(t,a,b) t[20], t[21] = a, b end +
- ("AXISHEIGHT" * number ) / function(t,a) t[22] = a end
- )
- + (1-lineend)^0
- )
- + (1-comment)^1
-)^0
-
-local function scan_comment(str)
- local fd = { }
- lpegmatch(pattern,str,1,fd)
- return fd
-end
-
--- Comment DesignSize 12 (pts)
--- Comment TFM designsize: 12 (in points)
-
-local keys = {
-
- FontName = function(data,line)
- data.metadata.fontname = strip(line) -- get rid of spaces
- data.metadata.fullname = strip(line)
- end,
-
- ItalicAngle = function(data,line)
- data.metadata.italicangle = tonumber(line)
- end,
-
- IsFixedPitch = function(data,line)
- data.metadata.monospaced = toboolean(line,true)
- end,
-
- CharWidth = function(data,line)
- data.metadata.charwidth = tonumber(line)
- end,
-
- XHeight = function(data,line)
- data.metadata.xheight = tonumber(line)
- end,
-
- Descender = function(data,line)
- data.metadata.descender = tonumber (line)
- end,
-
- Ascender = function(data,line)
- data.metadata.ascender = tonumber (line)
- end,
-
- Comment = function(data,line)
- line = lower(line)
- local designsize = match(line,"designsize[^%d]*(%d+)")
- if designsize then data.metadata.designsize = tonumber(designsize) end
- end,
-
-}
-
-local function get_charmetrics(data,charmetrics,vector)
- local characters = data.characters
- local chr, ind = { }, 0
- for k, v in gmatch(charmetrics,"([%a]+) +(.-) *;") do
- if k == 'C' then
- v = tonumber(v)
- if v < 0 then
- ind = ind + 1 -- ?
- else
- ind = v
- end
- chr = {
- index = ind
- }
- elseif k == 'WX' then
- chr.width = tonumber(v)
- elseif k == 'N' then
- characters[v] = chr
- elseif k == 'B' then
- local llx, lly, urx, ury = match(v,"^ *(.-) +(.-) +(.-) +(.-)$")
- chr.boundingbox = { tonumber(llx), tonumber(lly), tonumber(urx), tonumber(ury) }
- elseif k == 'L' then
- local plus, becomes = match(v,"^(.-) +(.-)$")
- local ligatures = chr.ligatures
- if ligatures then
- ligatures[plus] = becomes
- else
- chr.ligatures = { [plus] = becomes }
- end
- end
- end
-end
-
-local function get_kernpairs(data,kernpairs)
- local characters = data.characters
- for one, two, value in gmatch(kernpairs,"KPX +(.-) +(.-) +(.-)\n") do
- local chr = characters[one]
- if chr then
- local kerns = chr.kerns
- if kerns then
- kerns[two] = tonumber(value)
- else
- chr.kerns = { [two] = tonumber(value) }
- end
- end
- end
-end
-
-local function get_variables(data,fontmetrics)
- for key, rest in gmatch(fontmetrics,"(%a+) *(.-)[\n\r]") do
- local keyhandler = keys[key]
- if keyhandler then
- keyhandler(data,rest)
- end
- end
-end
-
--[[ldx--
We now use a new (unfinished) pfb loader but I see no differences between the old
and new vectors (we actually had one bad vector with the old loader).
@@ -353,6 +216,196 @@ do
end
+--[[ldx--
+We start with the basic reader which we give a name similar to the built in
+and reader.
+--ldx]]--
+
+-- Comment FONTIDENTIFIER LMMATHSYMBOLS10
+-- Comment CODINGSCHEME TEX MATH SYMBOLS
+-- Comment DESIGNSIZE 10.0 pt
+-- Comment CHECKSUM O 4261307036
+-- Comment SPACE 0 plus 0 minus 0
+-- Comment QUAD 1000
+-- Comment EXTRASPACE 0
+-- Comment NUM 676.508 393.732 443.731
+-- Comment DENOM 685.951 344.841
+-- Comment SUP 412.892 362.892 288.889
+-- Comment SUB 150 247.217
+-- Comment SUPDROP 386.108
+-- Comment SUBDROP 50
+-- Comment DELIM 2390 1010
+-- Comment AXISHEIGHT 250
+-- Comment DesignSize 12 (pts)
+-- Comment TFM designsize: 12 (in points)
+
+local parser do -- no need for a further speedup with locals
+
+ local spacing = patterns.spacer
+ local lineend = patterns.newline
+ local number = spacing * (R("09") + S("."))^1 / tonumber
+ local name = spacing * C((1-spacing)^1)
+ local words = spacing * (1 - lineend)^1 / strip
+ local rest = (1 - lineend)^0
+ local fontdata = Carg(1)
+ local semicolon = spacing * P(";")
+ local plus = P("plus") * number
+ local minus = P("minus") * number
+
+ -- kern pairs
+
+ local function addkernpair(data,one,two,value)
+ local chr = data.characters[one]
+ if chr then
+ local kerns = chr.kerns
+ if kerns then
+ kerns[two] = tonumber(value)
+ else
+ chr.kerns = { [two] = tonumber(value) }
+ end
+ end
+ end
+
+ local p_kernpair = (fontdata * P("KPX") * name * name * number) / addkernpair
+
+ -- char metrics
+
+ local chr = false
+ local ind = 0
+
+ local function start()
+ ind = 0
+ chr = { }
+ end
+
+ local function stop()
+ ind = 0
+ chr = false
+ end
+
+ local function setindex(i)
+ if i < 0 then
+ ind = ind + 1 -- ?
+ else
+ ind = i
+ end
+ chr = {
+ index = ind
+ }
+ end
+
+ local function setwidth(width)
+ chr.width = width
+ end
+
+ local function setname(data,name)
+ data.characters[name] = chr
+ end
+
+ local function setboundingbox(boundingbox)
+ chr.boundingbox = boundingbox
+ end
+
+ local function setligature(plus,becomes)
+ local ligatures = chr.ligatures
+ if ligatures then
+ ligatures[plus] = becomes
+ else
+ chr.ligatures = { [plus] = becomes }
+ end
+ end
+
+ local p_charmetric = ( (
+ P("C") * number / setindex
+ + P("WX") * number / setwidth
+ + P("N") * fontdata * name / setname
+ + P("B") * Ct((number)^4) / setboundingbox
+ + P("L") * (name)^2 / setligature
+ ) * semicolon )^1
+
+ local p_charmetrics = P("StartCharMetrics") * number * (p_charmetric + (1-P("EndCharMetrics")))^0 * P("EndCharMetrics")
+ local p_kernpairs = P("StartKernPairs") * number * (p_kernpair + (1-P("EndKernPairs")) )^0 * P("EndKernPairs")
+
+ local function set_1(data,key,a) data.metadata[lower(key)] = a end
+ local function set_2(data,key,a,b) data.metadata[lower(key)] = { a, b } end
+ local function set_3(data,key,a,b,c) data.metadata[lower(key)] = { a, b, c } end
+
+ local p_parameters = P(false)
+ + P("FontName") * fontdata * words / function(data,line)
+ data.metadata.fontname = line
+ data.metadata.fullname = line
+ end
+ + P("ItalicAngle") * fontdata * number / function(data,angle)
+ data.metadata.italicangle = angle
+ end
+ + P("IsFixedPitch") * fontdata * name / function(data,pitch)
+ data.metadata.monospaced = toboolean(pitch,true)
+ end
+ + P("CharWidth") * fontdata * number / function(data,width)
+ data.metadata.charwidth = width
+ end
+ + P("XHeight") * fontdata * number / function(data,xheight)
+ data.metadata.xheight = xheight
+ end
+ + P("Descender") * fontdata * number / function(data,descender)
+ data.metadata.descender = descender
+ end
+ + P("Ascender") * fontdata * number / function(data,ascender)
+ data.metadata.ascender = ascender
+ end
+ + P("Comment") * spacing * ( P(false)
+ + (fontdata * C("DESIGNSIZE") * number * rest) / set_1 -- 1
+ + (fontdata * C("TFM designsize") * number * rest) / set_1
+ + (fontdata * C("DesignSize") * number * rest) / set_1
+ + (fontdata * C("CODINGSCHEME") * words * rest) / set_1 --
+ + (fontdata * C("CHECKSUM") * number * words * rest) / set_1 -- 2
+ + (fontdata * C("SPACE") * number * plus * minus * rest) / set_3 -- 3 4 5
+ + (fontdata * C("QUAD") * number * rest) / set_1 -- 6
+ + (fontdata * C("EXTRASPACE") * number * rest) / set_1 -- 7
+ + (fontdata * C("NUM") * number * number * number * rest) / set_3 -- 8 9 10
+ + (fontdata * C("DENOM") * number * number * rest) / set_2 -- 11 12
+ + (fontdata * C("SUP") * number * number * number * rest) / set_3 -- 13 14 15
+ + (fontdata * C("SUB") * number * number * rest) / set_2 -- 16 17
+ + (fontdata * C("SUPDROP") * number * rest) / set_1 -- 18
+ + (fontdata * C("SUBDROP") * number * rest) / set_1 -- 19
+ + (fontdata * C("DELIM") * number * number * rest) / set_2 -- 20 21
+ + (fontdata * C("AXISHEIGHT") * number * rest) / set_1 -- 22
+ )
+
+ parser = (P("StartFontMetrics") / start)
+ * (
+ p_charmetrics
+ + p_kernpairs
+ + p_parameters
+ + (1-P("EndFontMetrics"))
+ )^0
+ * (P("EndFontMetrics") / stop)
+
+end
+
+
+local data = {
+ resources = {
+ filename = resolvers.unresolve(filename),
+-- version = afm.version,
+ creator = "context mkiv",
+ },
+ properties = {
+ hasitalics = false,
+ },
+ goodies = {
+ },
+ metadata = {
+ filename = file.removesuffix(file.basename(filename))
+ },
+ characters = {
+ -- a temporary store
+ },
+ descriptions = {
+ -- the final store
+ },
+}
+
local function readafm(filename)
local ok, afmblob, size = resolvers.loadbinfile(filename) -- has logging
if ok and afmblob then
@@ -377,30 +430,7 @@ local function readafm(filename)
-- the final store
},
}
--- afmblob = gsub(afmblob,"StartCharMetrics(.-)EndCharMetrics", function(charmetrics)
- for charmetrics in gmatch(afmblob,"StartCharMetrics(.-)EndCharMetrics") do
- if trace_loading then
- report_afm("loading char metrics")
- end
- get_charmetrics(data,charmetrics,vector)
- break
- end
- for kernpairs in gmatch(afmblob,"StartKernPairs(.-)EndKernPairs") do
- if trace_loading then
- report_afm("loading kern pairs")
- end
- get_kernpairs(data,kernpairs)
- break
- end
- for version, fontmetrics in gmatch(afmblob,"StartFontMetrics%s+([%d%.]+)(.-)EndFontMetrics") do
- if trace_loading then
- report_afm("loading variables")
- end
- data.afmversion = version
- get_variables(data,fontmetrics)
- data.fontdimens = scan_comment(fontmetrics) -- todo: all lpeg, no time now
- break
- end
+ lpegmatch(parser,afmblob,1,data)
return data
else
if trace_loading then
@@ -929,11 +959,31 @@ local function copytotfm(data)
end
--
end
- local fd = data.fontdimens
- if fd and fd[8] and fd[9] and fd[10] then -- math
- for k,v in next, fd do
- parameters[k] = v
- end
+ --
+ if metadata.sup then
+ local dummy = { 0, 0, 0}
+ parameters[ 1] = metadata.designsize or 0
+ parameters[ 2] = metadata.checksum or 0
+ parameters[ 3],
+ parameters[ 4],
+ parameters[ 5] = unpack(metadata.space or dummy)
+ parameters[ 6] = metadata.quad or 0
+ parameters[ 7] = metadata.extraspace or 0
+ parameters[ 8],
+ parameters[ 9],
+ parameters[10] = unpack(metadata.num or dummy)
+ parameters[11],
+ parameters[12] = unpack(metadata.denom or dummy)
+ parameters[13],
+ parameters[14],
+ parameters[15] = unpack(metadata.sup or dummy)
+ parameters[16],
+ parameters[17] = unpack(metadata.sub or dummy)
+ parameters[18] = metadata.supdrop or 0
+ parameters[19] = metadata.subdrop or 0
+ parameters[20],
+ parameters[21] = unpack(metadata.delim or dummy)
+ parameters[22] = metadata.axisheight
end
--
parameters.designsize = (metadata.designsize or 10)*65536
--
cgit v1.2.3
From 19bc52023e3c345855c41ba36911143ed094bf1a Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Thu, 12 May 2016 22:57:50 +0200
Subject: [features,loaders] tidy up loading of afm
---
src/luaotfload-features.lua | 18 ++++++++++++++----
src/luaotfload-loaders.lua | 16 ++++++++++++----
2 files changed, 26 insertions(+), 8 deletions(-)
diff --git a/src/luaotfload-features.lua b/src/luaotfload-features.lua
index 5152fab..8263b51 100644
--- a/src/luaotfload-features.lua
+++ b/src/luaotfload-features.lua
@@ -1221,8 +1221,12 @@ local handle_request = function (specification)
request.features = apply_default_features(request.features)
if name then
- specification.name = name
- specification.lookup = lookup or specification.lookup
+ if lookup == "file" then
+ specification.filename = name
+ name = file.removesuffix (name)
+ end
+ specification.name = name
+ specification.lookup = lookup or specification.lookup
end
if request.modifiers then
@@ -1245,7 +1249,12 @@ local handle_request = function (specification)
--- The next line sets the “rand” feature to “random”; I haven’t
--- investigated it any further (luatex-fonts-ext), so it will
--- just stay here.
- specification.features.normal = normalize (request.features)
+ local features = specification.features
+ if not features then
+ features = { }
+ specification.features = features
+ end
+ features.normal = normalize (request.features)
local subfont = tonumber (specification.sub)
if subfont and subfont >= 0 then
specification.sub = subfont + 1
@@ -1253,8 +1262,9 @@ local handle_request = function (specification)
return specification
end
+fonts.names.handle_request = handle_request
+
if as_script == true then --- skip the remainder of the file
- fonts.names.handle_request = handle_request
report ("log", 5, "features",
"Exiting early from luaotfload-features.lua.")
return
diff --git a/src/luaotfload-loaders.lua b/src/luaotfload-loaders.lua
index f6cb272..0a0185b 100644
--- a/src/luaotfload-loaders.lua
+++ b/src/luaotfload-loaders.lua
@@ -49,12 +49,19 @@ local unsupported_reader = function (format)
end
end
-local afm_compat_message = function (specification, method)
+local afm_reader = fonts.readers.afm
+
+local afm_compat_message = function (specification)
+ local name = specification.name
+ local filename = specification.filename
logreport ("both", 4, "loaders",
"PFB format only supported with matching \z
- AFM; redirecting (“%s”, “%s”).",
- tostring (specification.name), tostring (method))
- return fonts.readers.afm (specification, method)
+ AFM; redirecting (“%s”, “afm”).",
+ tostring (specification.name))
+ specification.forced = "afm"
+ specification.forcedname = filename
+ specification.filename = file.replacesuffix (filename, "afm")
+ return afm_reader (specification, "afm")
end
local install_formats = function ()
@@ -89,6 +96,7 @@ local install_formats = function ()
return aux ("evl", eval_reader)
and aux ("lua", lua_reader)
and aux ("pfa", unsupported_reader "pfa")
+ and aux ("afm", function (spec) return afm_reader (spec, "afm") end)
and aux ("pfb", afm_compat_message) --- pfb loader is incomplete
and aux ("ofm", readers.tfm)
and aux ("dfont", unsupported_reader "dfont")
--
cgit v1.2.3
From 499160de78a15bc9d9d24c4d1962fbd17b080f6e Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Thu, 12 May 2016 23:55:19 +0200
Subject: [features] update addfeature()
---
src/luaotfload-features.lua | 525 ++++++++++++++++++++++++++++++++------------
1 file changed, 379 insertions(+), 146 deletions(-)
diff --git a/src/luaotfload-features.lua b/src/luaotfload-features.lua
index 8263b51..d6531d3 100644
--- a/src/luaotfload-features.lua
+++ b/src/luaotfload-features.lua
@@ -1340,15 +1340,15 @@ local function current_addfeature(data,feature,specifications)
if not features or not sequences then
return
end
- local gsubfeatures = features.gsub
- if gsubfeatures and gsubfeatures[feature] then
- return -- already present
- end
+ -- feature has to be unique but the name entry wins eventually
+
local fontfeatures = resources.features or everywhere
local unicodes = resources.unicodes
local splitter = lpeg.splitter(" ",unicodes)
local done = 0
local skip = 0
+ local aglunicodes = false
+
if not specifications[1] then
-- so we accept a one entry specification
specifications = { specifications }
@@ -1357,11 +1357,24 @@ local function current_addfeature(data,feature,specifications)
local function tounicode(code)
if not code then
return
- elseif type(code) == "number" then
+ end
+ if type(code) == "number" then
return code
- else
- return unicodes[code] or utfbyte(code)
end
+ local u = unicodes[code]
+ if u then
+ return u
+ end
+ if utflen(code) == 1 then
+ u = utfbyte(code)
+ if u then
+ return u
+ end
+ end
+ if not aglunicodes then
+ aglunicodes = fonts.encodings.agl.unicodes -- delayed
+ end
+ return aglunicodes[code]
end
local coverup = otf.coverup
@@ -1369,9 +1382,281 @@ local function current_addfeature(data,feature,specifications)
local stepkey = coverup.stepkey
local register = coverup.register
+ local function prepare_substitution(list,featuretype)
+ local coverage = { }
+ local cover = coveractions[featuretype]
+ for code, replacement in next, list do
+ local unicode = tounicode(code)
+ local description = descriptions[unicode]
+ if description then
+ if type(replacement) == "table" then
+ replacement = replacement[1]
+ end
+ replacement = tounicode(replacement)
+ if replacement and descriptions[replacement] then
+ cover(coverage,unicode,replacement)
+ done = done + 1
+ else
+ skip = skip + 1
+ end
+ else
+ skip = skip + 1
+ end
+ end
+ return coverage
+ end
+
+ local function prepare_alternate(list,featuretype)
+ local coverage = { }
+ local cover = coveractions[featuretype]
+ for code, replacement in next, list do
+ local unicode = tounicode(code)
+ local description = descriptions[unicode]
+ if not description then
+ skip = skip + 1
+ elseif type(replacement) == "table" then
+ local r = { }
+ for i=1,#replacement do
+ local u = tounicode(replacement[i])
+ r[i] = descriptions[u] and u or unicode
+ end
+ cover(coverage,unicode,r)
+ done = done + 1
+ else
+ local u = tounicode(replacement)
+ if u then
+ cover(coverage,unicode,{ u })
+ done = done + 1
+ else
+ skip = skip + 1
+ end
+ end
+ end
+ return coverage
+ end
+
+ local function prepare_multiple(list,featuretype)
+ local coverage = { }
+ local cover = coveractions[featuretype]
+ for code, replacement in next, list do
+ local unicode = tounicode(code)
+ local description = descriptions[unicode]
+ if not description then
+ skip = skip + 1
+ elseif type(replacement) == "table" then
+ local r, n = { }, 0
+ for i=1,#replacement do
+ local u = tounicode(replacement[i])
+ if descriptions[u] then
+ n = n + 1
+ r[n] = u
+ end
+ end
+ if n > 0 then
+ cover(coverage,unicode,r)
+ done = done + 1
+ else
+ skip = skip + 1
+ end
+ else
+ local u = tounicode(replacement)
+ if u then
+ cover(coverage,unicode,{ u })
+ done = done + 1
+ else
+ skip = skip + 1
+ end
+ end
+ end
+ return coverage
+ end
+
+ local function prepare_ligature(list,featuretype)
+ local coverage = { }
+ local cover = coveractions[featuretype]
+ for code, ligature in next, list do
+ local unicode = tounicode(code)
+ local description = descriptions[unicode]
+ if description then
+ if type(ligature) == "string" then
+ ligature = { lpegmatch(splitter,ligature) }
+ end
+ local present = true
+ for i=1,#ligature do
+ local l = ligature[i]
+ local u = tounicode(l)
+ if descriptions[u] then
+ ligature[i] = u
+ else
+ present = false
+ break
+ end
+ end
+ if present then
+ cover(coverage,unicode,ligature)
+ done = done + 1
+ else
+ skip = skip + 1
+ end
+ else
+ skip = skip + 1
+ end
+ end
+ return coverage
+ end
+
+ local function prepare_kern(list,featuretype)
+ local coverage = { }
+ local cover = coveractions[featuretype]
+ for code, replacement in next, list do
+ local unicode = tounicode(code)
+ local description = descriptions[unicode]
+ if description and type(replacement) == "table" then
+ local r = { }
+ for k, v in next, replacement do
+ local u = tounicode(k)
+ if u then
+ r[u] = v
+ end
+ end
+ if next(r) then
+ cover(coverage,unicode,r)
+ done = done + 1
+ else
+ skip = skip + 1
+ end
+ else
+ skip = skip + 1
+ end
+ end
+ return coverage
+ end
+
+ local function prepare_pair(list,featuretype)
+ local coverage = { }
+ local cover = coveractions[featuretype]
+ if cover then
+ for code, replacement in next, list do
+ local unicode = tounicode(code)
+ local description = descriptions[unicode]
+ if description and type(replacement) == "table" then
+ local r = { }
+ for k, v in next, replacement do
+ local u = tounicode(k)
+ if u then
+ r[u] = v
+ end
+ end
+ if next(r) then
+ cover(coverage,unicode,r)
+ done = done + 1
+ else
+ skip = skip + 1
+ end
+ else
+ skip = skip + 1
+ end
+ end
+ else
+ report_otf("unknown cover type %a",featuretype)
+ end
+ return coverage
+ end
+
+ local function prepare_chain(list,featuretype,sublookups)
+ -- todo: coveractions
+ local rules = list.rules
+ local coverage = { }
+ if rules then
+ local rulehash = { }
+ local rulesize = 0
+ local sequence = { }
+ local nofsequences = 0
+ local lookuptype = types[featuretype]
+ for nofrules=1,#rules do
+ local rule = rules[nofrules]
+ local current = rule.current
+ local before = rule.before
+ local after = rule.after
+ local replacements = rule.replacements or false
+ local sequence = { }
+ local nofsequences = 0
+ if before then
+ for n=1,#before do
+ nofsequences = nofsequences + 1
+ sequence[nofsequences] = before[n]
+ end
+ end
+ local start = nofsequences + 1
+ for n=1,#current do
+ nofsequences = nofsequences + 1
+ sequence[nofsequences] = current[n]
+ end
+ local stop = nofsequences
+ if after then
+ for n=1,#after do
+ nofsequences = nofsequences + 1
+ sequence[nofsequences] = after[n]
+ end
+ end
+ local lookups = rule.lookups or false
+ local subtype = nil
+ if lookups and sublookups then
+ for k, v in next, lookups do
+ local lookup = sublookups[v]
+ if lookup then
+ lookups[k] = lookup
+ if not subtype then
+ subtype = lookup.type
+ end
+ else
+ -- already expanded
+ end
+ end
+ end
+ if nofsequences > 0 then -- we merge coverage into one
+ -- we copy as we can have different fonts
+ local hashed = { }
+ for i=1,nofsequences do
+ local t = { }
+ local s = sequence[i]
+ for i=1,#s do
+ local u = tounicode(s[i])
+ if u then
+ t[u] = true
+ end
+ end
+ hashed[i] = t
+ end
+ sequence = hashed
+ -- now we create the rule
+ rulesize = rulesize + 1
+ rulehash[rulesize] = {
+ nofrules, -- 1
+ lookuptype, -- 2
+ sequence, -- 3
+ start, -- 4
+ stop, -- 5
+ lookups, -- 6 (6/7 also signal of what to do)
+ replacements, -- 7
+ subtype, -- 8
+ }
+ for unic in next, sequence[start] do
+ local cu = coverage[unic]
+ if not cu then
+ coverage[unic] = rulehash -- can now be done cleaner i think
+ end
+ end
+ end
+ end
+ end
+ return coverage
+ end
+
for s=1,#specifications do
local specification = specifications[s]
local valid = specification.valid
+ local feature = specification.name or feature
if not valid or valid(data,specification,feature) then
local initialize = specification.initialize
if initialize then
@@ -1379,185 +1664,133 @@ local function current_addfeature(data,feature,specifications)
specification.initialize = initialize(specification,data) and initialize or nil
end
local askedfeatures = specification.features or everywhere
- local askedsteps = specifications.steps or specification.subtables or { specification.data } or { }
+ local askedsteps = specification.steps or specification.subtables or { specification.data } or { }
local featuretype = normalized[specification.type or "substitution"] or "substitution"
local featureflags = specification.flags or noflags
local featureorder = specification.order or { feature }
- local added = false
+ local featurechain = (featuretype == "chainsubstitution" or featuretype == "chainposition") and 1 or 0
local nofsteps = 0
local steps = { }
+ local sublookups = specification.lookups
+ local category = nil
+ if sublookups then
+ local s = { }
+ for i=1,#sublookups do
+ local specification = sublookups[i]
+ local askedsteps = specification.steps or specification.subtables or { specification.data } or { }
+ local featuretype = normalized[specification.type or "substitution"] or "substitution"
+ local featureflags = specification.flags or noflags
+ local nofsteps = 0
+ local steps = { }
+ for i=1,#askedsteps do
+ local list = askedsteps[i]
+ local coverage = nil
+ local format = nil
+ if featuretype == "substitution" then
+ coverage = prepare_substitution(list,featuretype)
+ elseif featuretype == "ligature" then
+ coverage = prepare_ligature(list,featuretype)
+ elseif featuretype == "alternate" then
+ coverage = prepare_alternate(list,featuretype)
+ elseif featuretype == "multiple" then
+ coverage = prepare_multiple(list,featuretype)
+ elseif featuretype == "kern" then
+ format = "kern"
+ coverage = prepare_kern(list,featuretype)
+ elseif featuretype == "pair" then
+ format = "pair"
+ coverage = prepare_pair(list,featuretype)
+ end
+ if coverage and next(coverage) then
+ nofsteps = nofsteps + 1
+ steps[nofsteps] = register(coverage,featuretype,format,feature,nofsteps,descriptions,resources)
+ end
+ end
+ s[i] = {
+ [stepkey] = steps,
+ nofsteps = nofsteps,
+ type = types[featuretype],
+ }
+ end
+ sublookups = s
+ end
for i=1,#askedsteps do
local list = askedsteps[i]
- local coverage = { }
- local cover = coveractions[featuretype]
+ local coverage = nil
local format = nil
- if not cover then
- -- unknown
- elseif featuretype == "substitution" then
- for code, replacement in next, list do
- local unicode = tounicode(code)
- local description = descriptions[unicode]
- if description then
- if type(replacement) == "table" then
- replacement = replacement[1]
- end
- replacement = tounicode(replacement)
- if replacement and descriptions[replacement] then
- cover(coverage,unicode,replacement)
- done = done + 1
- else
- skip = skip + 1
- end
- else
- skip = skip + 1
- end
- end
+ if featuretype == "substitution" then
+ category = "gsub"
+ coverage = prepare_substitution(list,featuretype)
elseif featuretype == "ligature" then
- for code, ligature in next, list do
- local unicode = tounicode(code)
- local description = descriptions[unicode]
- if description then
- if type(ligature) == "string" then
- ligature = { lpegmatch(splitter,ligature) }
- end
- local present = true
- for i=1,#ligature do
- local l = ligature[i]
- local u = tounicode(l)
- if descriptions[u] then
- ligature[i] = u
- else
- present = false
- break
- end
- end
- if present then
- cover(coverage,unicode,ligature)
- done = done + 1
- else
- skip = skip + 1
- end
- else
- skip = skip + 1
- end
- end
+ category = "gsub"
+ coverage = prepare_ligature(list,featuretype)
elseif featuretype == "alternate" then
- for code, replacement in next, list do
- local unicode = tounicode(code)
- local description = descriptions[unicode]
- if not description then
- skip = skip + 1
- elseif type(replacement) == "table" then
- local r = { }
- for i=1,#replacement do
- local u = tounicode(replacement[i])
- r[i] = descriptions[u] and u or unicode
- end
- cover(coverage,unicode,r)
- done = done + 1
- else
- local u = tounicode(replacement)
- if u then
- cover(coverage,unicode,{ u })
- done = done + 1
- else
- skip = skip + 1
- end
- end
- end
- elseif featuretype == "multiple" then -- todo: unicode can be table
- for code, replacement in next, list do
- local unicode = tounicode(code)
- local description = descriptions[unicode]
- if not description then
- skip = skip + 1
- elseif type(replacement) == "table" then
- local r, n = { }, 0
- for i=1,#replacement do
- local u = tounicode(replacement[i])
- if descriptions[u] then
- n = n + 1
- r[n] = u
- end
- end
- if n > 0 then
- cover(coverage,unicode,r)
- done = done + 1
- else
- skip = skip + 1
- end
- else
- local u = tounicode(replacement)
- if u then
- cover(coverage,unicode,{ u })
- done = done + 1
- else
- skip = skip + 1
- end
- end
- end
+ category = "gsub"
+ coverage = prepare_alternate(list,featuretype)
+ elseif featuretype == "multiple" then
+ category = "gsub"
+ coverage = prepare_multiple(list,featuretype)
elseif featuretype == "kern" then
- for code, replacement in next, list do
- local unicode = tounicode(code)
- local description = descriptions[unicode]
- if description and type(replacement) == "table" then
- local r = { }
- for k, v in next, replacement do
- local u = tounicode(k)
- if u then
- r[u] = v
- end
- end
- if next(r) then
- cover(coverage,unicode,r)
- done = done + 1
- else
- skip = skip + 1
- end
- else
- skip = skip + 1
- end
- end
- format = "kern"
+ category = "gpos"
+ format = "kern"
+ coverage = prepare_kern(list,featuretype)
+ elseif featuretype == "pair" then
+ category = "gpos"
+ format = "pair"
+ coverage = prepare_pair(list,featuretype)
+ elseif featuretype == "chainsubstitution" then
+ category = "gsub"
+ coverage = prepare_chain(list,featuretype,sublookups)
+ elseif featuretype == "chainposition" then
+ category = "gpos"
+ coverage = prepare_chain(list,featuretype,sublookups)
+ else
+ report_otf("not registering feature %a, unknown category",feature)
+ return
end
- if next(coverage) then
- added = true
+ if coverage and next(coverage) then
nofsteps = nofsteps + 1
steps[nofsteps] = register(coverage,featuretype,format,feature,nofsteps,descriptions,resources)
end
end
- if added then
+ if nofsteps > 0 then
-- script = { lang1, lang2, lang3 } or script = { lang1 = true, ... }
for k, v in next, askedfeatures do
if v[1] then
askedfeatures[k] = tohash(v)
end
end
+ if featureflags[1] then featureflags[1] = "mark" end
+ if featureflags[2] then featureflags[2] = "ligature" end
+ if featureflags[3] then featureflags[3] = "base" end
local sequence = {
- chain = 0,
+ chain = featurechain,
features = { [feature] = askedfeatures },
flags = featureflags,
- name = feature, -- not needed
+ name = feature, -- redundant
order = featureorder,
[stepkey] = steps,
nofsteps = nofsteps,
type = types[featuretype],
}
+ -- todo : before|after|index
if specification.prepend then
insert(sequences,1,sequence)
else
insert(sequences,sequence)
end
-- register in metadata (merge as there can be a few)
- if not gsubfeatures then
- gsubfeatures = { }
- fontfeatures.gsub = gsubfeatures
+ local features = fontfeatures[category]
+ if not features then
+ features = { }
+ fontfeatures[category] = features
end
- local k = gsubfeatures[feature]
+ local k = features[feature]
if not k then
k = { }
- gsubfeatures[feature] = k
+ features[feature] = k
end
+ --
for script, languages in next, askedfeatures do
local kk = k[script]
if not kk then
--
cgit v1.2.3
From 934edcaba82997bd64bfe5dd3a08e07c59056ba1 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Fri, 13 May 2016 00:03:29 +0200
Subject: [loaders] make AFM wrappers more consistent
---
src/luaotfload-loaders.lua | 20 +++++++++++---------
1 file changed, 11 insertions(+), 9 deletions(-)
diff --git a/src/luaotfload-loaders.lua b/src/luaotfload-loaders.lua
index 0a0185b..e5298b2 100644
--- a/src/luaotfload-loaders.lua
+++ b/src/luaotfload-loaders.lua
@@ -51,19 +51,23 @@ end
local afm_reader = fonts.readers.afm
-local afm_compat_message = function (specification)
+local afm_loader = function (specification)
local name = specification.name
local filename = specification.filename
- logreport ("both", 4, "loaders",
- "PFB format only supported with matching \z
- AFM; redirecting (“%s”, “afm”).",
- tostring (specification.name))
specification.forced = "afm"
specification.forcedname = filename
specification.filename = file.replacesuffix (filename, "afm")
return afm_reader (specification, "afm")
end
+local afm_compat_message = function (specification)
+ logreport ("both", 4, "loaders",
+ "PFB format only supported with matching \z
+ AFM; redirecting (“%s”, “afm”).",
+ tostring (specification.name))
+ return afm_loader (specification)
+end
+
local install_formats = function ()
local fonts = fonts
if not fonts then return false end
@@ -71,9 +75,8 @@ local install_formats = function ()
local readers = fonts.readers
local sequence = readers.sequence
local seqset = table.tohash (sequence)
- local handlers = fonts.handlers
local formats = fonts.formats
- if not readers or not handlers or not formats then return false end
+ if not readers or not formats then return false end
local aux = function (which, reader)
if not which or type (which) ~= "string"
@@ -83,7 +86,6 @@ local install_formats = function ()
end
formats [which] = "type1"
readers [which] = reader
- handlers [which] = { }
if not seqset [which] then
logreport ("both", 3, "loaders",
"Extending reader sequence for “%s”.", which)
@@ -96,7 +98,7 @@ local install_formats = function ()
return aux ("evl", eval_reader)
and aux ("lua", lua_reader)
and aux ("pfa", unsupported_reader "pfa")
- and aux ("afm", function (spec) return afm_reader (spec, "afm") end)
+ and aux ("afm", afm_loader)
and aux ("pfb", afm_compat_message) --- pfb loader is incomplete
and aux ("ofm", readers.tfm)
and aux ("dfont", unsupported_reader "dfont")
--
cgit v1.2.3
From 563c3df1e1690132b1bf76fad59bd157254c53b1 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Fri, 13 May 2016 07:20:44 +0200
Subject: [loaders] implement readable load failure message
Add a message that includes the information relevant for
troubleshooting.
Due to the spammy nature of the message printed by Fontspec this is not
exactly useful with Latex so disabled by default for now.
---
src/luaotfload-loaders.lua | 23 +++++++++++++++++++----
1 file changed, 19 insertions(+), 4 deletions(-)
diff --git a/src/luaotfload-loaders.lua b/src/luaotfload-loaders.lua
index e5298b2..c21c9eb 100644
--- a/src/luaotfload-loaders.lua
+++ b/src/luaotfload-loaders.lua
@@ -104,6 +104,22 @@ local install_formats = function ()
and aux ("dfont", unsupported_reader "dfont")
end
+local not_found_msg = function (specification, size, id)
+ logreport ("both", 0, "loaders", "")
+ logreport ("both", 0, "loaders",
+ "--------------------------------------------------------")
+ logreport ("both", 0, "loaders", "")
+ logreport ("both", 0, "loaders", "Font definition failed for:")
+ logreport ("both", 0, "loaders", "")
+ logreport ("both", 0, "loaders", " > id : %d", id)
+ logreport ("both", 0, "loaders", " > specification : %q", specification)
+ if size > 0 then
+ logreport ("both", 0, "loaders", " > size : %.2f pt", size / 2^16)
+ end
+ logreport ("both", 0, "loaders", "")
+ logreport ("both", 0, "loaders",
+ "--------------------------------------------------------")
+end
--[[doc--
\subsection{\CONTEXT override}
@@ -120,6 +136,7 @@ do
local patch = function (specification, size, id)
local fontdata = read (specification, size, id)
+----if not fontdata then not_found_msg (specification, size, id) end
if type (fontdata) == "table" and fontdata.shared then
--- We need to test for the “shared” field here
--- or else the fontspec capheight callback will
@@ -139,10 +156,8 @@ do
logreport ("both", 0, "loaders", " > spec %q", specification)
logreport ("both", 0, "loaders", " > at size %.2f pt", size / 2^16)
local result = definer (specification, size, id)
- if not result then
- logreport ("both", 0, "loaders", " > font definition failed")
- return
- elseif type (result) == "number" then
+ if not result then return not_found_msg (specification, size, id) end
+ if type (result) == "number" then
logreport ("both", 0, "loaders", " > font definition yielded id %d", result)
return result
end
--
cgit v1.2.3
From 5a833d339a50cdaf1eb76f42619a1cdbf3637215 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Wed, 18 May 2016 07:50:14 +0200
Subject: [fontloader] sync with Context as of 2016-05-18
---
src/fontloader/misc/fontloader-font-one.lua | 414 +-----------------------
src/fontloader/misc/fontloader-font-otr.lua | 1 +
src/fontloader/misc/fontloader-fonts.lua | 1 +
src/fontloader/runtime/fontloader-reference.lua | 383 ++++++++++++----------
4 files changed, 230 insertions(+), 569 deletions(-)
diff --git a/src/fontloader/misc/fontloader-font-one.lua b/src/fontloader/misc/fontloader-font-one.lua
index b2446db..77f2560 100644
--- a/src/fontloader/misc/fontloader-font-one.lua
+++ b/src/fontloader/misc/fontloader-font-one.lua
@@ -55,7 +55,7 @@ local otfenhancers = otf.enhancers
local afmfeatures = constructors.newfeatures("afm")
local registerafmfeature = afmfeatures.register
-afm.version = 1.507 -- incrementing this number one up will force a re-cache
+afm.version = 1.512 -- incrementing this number one up will force a re-cache
afm.cache = containers.define("fonts", "afm", afm.version, true)
afm.autoprefixed = true -- this will become false some day (catches texnansi-blabla.*)
@@ -66,380 +66,6 @@ local overloads = fonts.mappings.overloads
local applyruntimefixes = fonts.treatments and fonts.treatments.applyfixes
---[[ldx--
-We start with the basic reader which we give a name similar to the built in
-and reader.
---ldx]]--
-
--- Comment FONTIDENTIFIER LMMATHSYMBOLS10
--- Comment CODINGSCHEME TEX MATH SYMBOLS
--- Comment DESIGNSIZE 10.0 pt
--- Comment CHECKSUM O 4261307036
--- Comment SPACE 0 plus 0 minus 0
--- Comment QUAD 1000
--- Comment EXTRASPACE 0
--- Comment NUM 676.508 393.732 443.731
--- Comment DENOM 685.951 344.841
--- Comment SUP 412.892 362.892 288.889
--- Comment SUB 150 247.217
--- Comment SUPDROP 386.108
--- Comment SUBDROP 50
--- Comment DELIM 2390 1010
--- Comment AXISHEIGHT 250
-
---[[ldx--
-We now use a new (unfinished) pfb loader but I see no differences between the old
-and new vectors (we actually had one bad vector with the old loader).
---ldx]]--
-
-local get_indexes
-
-do
-
- local n, m
-
- local progress = function(str,position,name,size)
- local forward = position + tonumber(size) + 3 + 2
- n = n + 1
- if n >= m then
- return #str, name
- elseif forward < #str then
- return forward, name
- else
- return #str, name
- end
- end
-
- local initialize = function(str,position,size)
- n = 0
- m = tonumber(size)
- return position + 1
- end
-
- local charstrings = P("/CharStrings")
- local name = P("/") * C((R("az")+R("AZ")+R("09")+S("-_."))^1)
- local size = C(R("09")^1)
- local spaces = P(" ")^1
-
- local p_filternames = Ct (
- (1-charstrings)^0 * charstrings * spaces * Cmt(size,initialize)
- * (Cmt(name * P(" ")^1 * C(R("09")^1), progress) + P(1))^1
- )
-
- -- if one of first 4 not 0-9A-F then binary else hex
-
- local decrypt
-
- do
-
- local r, c1, c2, n = 0, 0, 0, 0
-
- local function step(c)
- local cipher = byte(c)
- local plain = bxor(cipher,rshift(r,8))
- r = ((cipher + r) * c1 + c2) % 65536
- return char(plain)
- end
-
- decrypt = function(binary)
- r, c1, c2, n = 55665, 52845, 22719, 4
- binary = gsub(binary,".",step)
- return sub(binary,n+1)
- end
-
- -- local pattern = Cs((P(1) / step)^1)
- --
- -- decrypt = function(binary)
- -- r, c1, c2, n = 55665, 52845, 22719, 4
- -- binary = lpegmatch(pattern,binary)
- -- return sub(binary,n+1)
- -- end
-
- end
-
- local function loadpfbvector(filename)
- -- for the moment limited to encoding only
-
- local data = io.loaddata(resolvers.findfile(filename))
-
- if not find(data,"!PS%-AdobeFont%-") then
- print("no font",filename)
- return
- end
-
- if not data then
- print("no data",filename)
- return
- end
-
- local ascii, binary = match(data,"(.*)eexec%s+......(.*)")
-
- if not binary then
- print("no binary",filename)
- return
- end
-
- binary = decrypt(binary,4)
-
- local vector = lpegmatch(p_filternames,binary)
-
- vector[0] = table.remove(vector,1)
-
- if not vector then
- print("no vector",filename)
- return
- end
-
- return vector
-
- end
-
- get_indexes = function(data,pfbname)
- local vector = loadpfbvector(pfbname)
- if vector then
- local characters = data.characters
- if trace_loading then
- report_afm("getting index data from %a",pfbname)
- end
- for index=1,#vector do
- local name = vector[index]
- local char = characters[name]
- if char then
- if trace_indexing then
- report_afm("glyph %a has index %a",name,index)
- end
- char.index = index
- end
- end
- end
- end
-
-end
-
---[[ldx--
-We start with the basic reader which we give a name similar to the built in
-and reader.
---ldx]]--
-
--- Comment FONTIDENTIFIER LMMATHSYMBOLS10
--- Comment CODINGSCHEME TEX MATH SYMBOLS
--- Comment DESIGNSIZE 10.0 pt
--- Comment CHECKSUM O 4261307036
--- Comment SPACE 0 plus 0 minus 0
--- Comment QUAD 1000
--- Comment EXTRASPACE 0
--- Comment NUM 676.508 393.732 443.731
--- Comment DENOM 685.951 344.841
--- Comment SUP 412.892 362.892 288.889
--- Comment SUB 150 247.217
--- Comment SUPDROP 386.108
--- Comment SUBDROP 50
--- Comment DELIM 2390 1010
--- Comment AXISHEIGHT 250
--- Comment DesignSize 12 (pts)
--- Comment TFM designsize: 12 (in points)
-
-local parser do -- no need for a further speedup with locals
-
- local spacing = patterns.spacer
- local lineend = patterns.newline
- local number = spacing * (R("09") + S("."))^1 / tonumber
- local name = spacing * C((1-spacing)^1)
- local words = spacing * (1 - lineend)^1 / strip
- local rest = (1 - lineend)^0
- local fontdata = Carg(1)
- local semicolon = spacing * P(";")
- local plus = P("plus") * number
- local minus = P("minus") * number
-
- -- kern pairs
-
- local function addkernpair(data,one,two,value)
- local chr = data.characters[one]
- if chr then
- local kerns = chr.kerns
- if kerns then
- kerns[two] = tonumber(value)
- else
- chr.kerns = { [two] = tonumber(value) }
- end
- end
- end
-
- local p_kernpair = (fontdata * P("KPX") * name * name * number) / addkernpair
-
- -- char metrics
-
- local chr = false
- local ind = 0
-
- local function start()
- ind = 0
- chr = { }
- end
-
- local function stop()
- ind = 0
- chr = false
- end
-
- local function setindex(i)
- if i < 0 then
- ind = ind + 1 -- ?
- else
- ind = i
- end
- chr = {
- index = ind
- }
- end
-
- local function setwidth(width)
- chr.width = width
- end
-
- local function setname(data,name)
- data.characters[name] = chr
- end
-
- local function setboundingbox(boundingbox)
- chr.boundingbox = boundingbox
- end
-
- local function setligature(plus,becomes)
- local ligatures = chr.ligatures
- if ligatures then
- ligatures[plus] = becomes
- else
- chr.ligatures = { [plus] = becomes }
- end
- end
-
- local p_charmetric = ( (
- P("C") * number / setindex
- + P("WX") * number / setwidth
- + P("N") * fontdata * name / setname
- + P("B") * Ct((number)^4) / setboundingbox
- + P("L") * (name)^2 / setligature
- ) * semicolon )^1
-
- local p_charmetrics = P("StartCharMetrics") * number * (p_charmetric + (1-P("EndCharMetrics")))^0 * P("EndCharMetrics")
- local p_kernpairs = P("StartKernPairs") * number * (p_kernpair + (1-P("EndKernPairs")) )^0 * P("EndKernPairs")
-
- local function set_1(data,key,a) data.metadata[lower(key)] = a end
- local function set_2(data,key,a,b) data.metadata[lower(key)] = { a, b } end
- local function set_3(data,key,a,b,c) data.metadata[lower(key)] = { a, b, c } end
-
- local p_parameters = P(false)
- + P("FontName") * fontdata * words / function(data,line)
- data.metadata.fontname = line
- data.metadata.fullname = line
- end
- + P("ItalicAngle") * fontdata * number / function(data,angle)
- data.metadata.italicangle = angle
- end
- + P("IsFixedPitch") * fontdata * name / function(data,pitch)
- data.metadata.monospaced = toboolean(pitch,true)
- end
- + P("CharWidth") * fontdata * number / function(data,width)
- data.metadata.charwidth = width
- end
- + P("XHeight") * fontdata * number / function(data,xheight)
- data.metadata.xheight = xheight
- end
- + P("Descender") * fontdata * number / function(data,descender)
- data.metadata.descender = descender
- end
- + P("Ascender") * fontdata * number / function(data,ascender)
- data.metadata.ascender = ascender
- end
- + P("Comment") * spacing * ( P(false)
- + (fontdata * C("DESIGNSIZE") * number * rest) / set_1 -- 1
- + (fontdata * C("TFM designsize") * number * rest) / set_1
- + (fontdata * C("DesignSize") * number * rest) / set_1
- + (fontdata * C("CODINGSCHEME") * words * rest) / set_1 --
- + (fontdata * C("CHECKSUM") * number * words * rest) / set_1 -- 2
- + (fontdata * C("SPACE") * number * plus * minus * rest) / set_3 -- 3 4 5
- + (fontdata * C("QUAD") * number * rest) / set_1 -- 6
- + (fontdata * C("EXTRASPACE") * number * rest) / set_1 -- 7
- + (fontdata * C("NUM") * number * number * number * rest) / set_3 -- 8 9 10
- + (fontdata * C("DENOM") * number * number * rest) / set_2 -- 11 12
- + (fontdata * C("SUP") * number * number * number * rest) / set_3 -- 13 14 15
- + (fontdata * C("SUB") * number * number * rest) / set_2 -- 16 17
- + (fontdata * C("SUPDROP") * number * rest) / set_1 -- 18
- + (fontdata * C("SUBDROP") * number * rest) / set_1 -- 19
- + (fontdata * C("DELIM") * number * number * rest) / set_2 -- 20 21
- + (fontdata * C("AXISHEIGHT") * number * rest) / set_1 -- 22
- )
-
- parser = (P("StartFontMetrics") / start)
- * (
- p_charmetrics
- + p_kernpairs
- + p_parameters
- + (1-P("EndFontMetrics"))
- )^0
- * (P("EndFontMetrics") / stop)
-
-end
-
-
-local data = {
- resources = {
- filename = resolvers.unresolve(filename),
--- version = afm.version,
- creator = "context mkiv",
- },
- properties = {
- hasitalics = false,
- },
- goodies = {
- },
- metadata = {
- filename = file.removesuffix(file.basename(filename))
- },
- characters = {
- -- a temporary store
- },
- descriptions = {
- -- the final store
- },
-}
-
-local function readafm(filename)
- local ok, afmblob, size = resolvers.loadbinfile(filename) -- has logging
- if ok and afmblob then
- local data = {
- resources = {
- filename = resolvers.unresolve(filename),
- version = afm.version,
- creator = "context mkiv",
- },
- properties = {
- hasitalics = false,
- },
- goodies = {
- },
- metadata = {
- filename = file.removesuffix(file.basename(filename))
- },
- characters = {
- -- a temporary store
- },
- descriptions = {
- -- the final store
- },
- }
- lpegmatch(parser,afmblob,1,data)
- return data
- else
- if trace_loading then
- report_afm("no valid afm file %a",filename)
- end
- return nil
- end
-end
-
--[[ldx--
We cache files. Caching is taken care of in the loader. We cheat a bit by adding
ligatures and kern information to the afm derived data. That way we can set them faster
@@ -500,16 +126,8 @@ function afm.load(filename)
end
if not data or data.size ~= size or data.time ~= time or data.pfbsize ~= pfbsize or data.pfbtime ~= pfbtime then
report_afm("reading %a",filename)
- data = readafm(filename)
+ data = afm.readers.loadfont(filename,pfbname)
if data then
- if pfbname ~= "" then
- data.resources.filename = resolvers.unresolve(pfbname)
- get_indexes(data,pfbname)
- elseif trace_loading then
- report_afm("no pfb file for %a",filename)
- -- data.resources.filename = "unset" -- better than loading the afm file
- end
- -- we now have all the data loaded
applyenhancers(data,filename)
-- otfreaders.addunicodetable(data) -- only when not done yet
fonts.mappings.addtounicode(data,filename)
@@ -961,29 +579,29 @@ local function copytotfm(data)
end
--
if metadata.sup then
- local dummy = { 0, 0, 0}
- parameters[ 1] = metadata.designsize or 0
- parameters[ 2] = metadata.checksum or 0
+ local dummy = { 0, 0, 0 }
+ parameters[ 1] = metadata.designsize or 0
+ parameters[ 2] = metadata.checksum or 0
parameters[ 3],
parameters[ 4],
- parameters[ 5] = unpack(metadata.space or dummy)
- parameters[ 6] = metadata.quad or 0
- parameters[ 7] = metadata.extraspace or 0
+ parameters[ 5] = unpack(metadata.space or dummy)
+ parameters[ 6] = metadata.quad or 0
+ parameters[ 7] = metadata.extraspace or 0
parameters[ 8],
parameters[ 9],
- parameters[10] = unpack(metadata.num or dummy)
+ parameters[10] = unpack(metadata.num or dummy)
parameters[11],
- parameters[12] = unpack(metadata.denom or dummy)
+ parameters[12] = unpack(metadata.denom or dummy)
parameters[13],
parameters[14],
- parameters[15] = unpack(metadata.sup or dummy)
+ parameters[15] = unpack(metadata.sup or dummy)
parameters[16],
- parameters[17] = unpack(metadata.sub or dummy)
- parameters[18] = metadata.supdrop or 0
- parameters[19] = metadata.subdrop or 0
+ parameters[17] = unpack(metadata.sub or dummy)
+ parameters[18] = metadata.supdrop or 0
+ parameters[19] = metadata.subdrop or 0
parameters[20],
- parameters[21] = unpack(metadata.delim or dummy)
- parameters[22] = metadata.axisheight
+ parameters[21] = unpack(metadata.delim or dummy)
+ parameters[22] = metadata.axisheight or 0
end
--
parameters.designsize = (metadata.designsize or 10)*65536
diff --git a/src/fontloader/misc/fontloader-font-otr.lua b/src/fontloader/misc/fontloader-font-otr.lua
index 24f6854..c967e24 100644
--- a/src/fontloader/misc/fontloader-font-otr.lua
+++ b/src/fontloader/misc/fontloader-font-otr.lua
@@ -1874,6 +1874,7 @@ local function getinfo(maindata,sub,platformnames,rawfamilynames)
-- format = fontdata.format,
fontname = fontname,
fullname = fullname,
+ -- cfffullname = cff.fullname,
family = family,
subfamily = subfamily,
familyname = familyname,
diff --git a/src/fontloader/misc/fontloader-fonts.lua b/src/fontloader/misc/fontloader-fonts.lua
index 1d2f203..c493844 100644
--- a/src/fontloader/misc/fontloader-fonts.lua
+++ b/src/fontloader/misc/fontloader-fonts.lua
@@ -260,6 +260,7 @@ if non_generic_context.luatex_fonts.skip_loading ~= true then
-- type one code
+ loadmodule('font-onr.lua') -- was font-afm.lua
loadmodule('font-one.lua') -- was font-afm.lua
loadmodule('font-afk.lua')
diff --git a/src/fontloader/runtime/fontloader-reference.lua b/src/fontloader/runtime/fontloader-reference.lua
index b848937..f10f139 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 : 05/10/16 23:43:55
+-- merge date : 05/17/16 10:06:55
do -- begin closure to overcome local limits and interference
@@ -22254,149 +22254,32 @@ end -- closure
do -- begin closure to overcome local limits and interference
-if not modules then modules={} end modules ['font-one']={
+if not modules then modules={} end modules ['font-onr']={
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 fonts,logs,trackers,containers,resolvers=fonts,logs,trackers,containers,resolvers
+local fonts,logs,trackers,resolvers=fonts,logs,trackers,resolvers
local next,type,tonumber,rawget=next,type,tonumber,rawget
-local match,gmatch,lower,gsub,strip,find=string.match,string.gmatch,string.lower,string.gsub,string.strip,string.find
+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 lpegmatch,patterns=lpeg.match,lpeg.patterns
-local trace_features=false trackers.register("afm.features",function(v) trace_features=v end)
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 trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end)
local report_afm=logs.reporter("fonts","afm loading")
-local setmetatableindex=table.setmetatableindex
-local derivetable=table.derive
-local findbinfile=resolvers.findbinfile
-local definers=fonts.definers
-local readers=fonts.readers
-local constructors=fonts.constructors
-local afm=constructors.newhandler("afm")
-local pfb=constructors.newhandler("pfb")
-local otf=fonts.handlers.otf
-local otfreaders=otf.readers
-local otfenhancers=otf.enhancers
-local afmfeatures=constructors.newfeatures("afm")
-local registerafmfeature=afmfeatures.register
-afm.version=1.507
-afm.cache=containers.define("fonts","afm",afm.version,true)
-afm.autoprefixed=true
-afm.helpdata={}
-afm.syncspace=true
-local overloads=fonts.mappings.overloads
-local applyruntimefixes=fonts.treatments and fonts.treatments.applyfixes
-local comment=P("Comment")
-local spacing=patterns.spacer
-local lineend=patterns.newline
-local words=spacing*C((1-lineend)^1)
-local number=spacing*C((R("09")+S("."))^1)/tonumber*spacing^0
-local data=Carg(1)
-local plus=P("plus")*number
-local minus=P("minus")*number
-local pattern=(
- comment*spacing*(
- data*(
- ("CODINGSCHEME"*words )/function(t,a) end+("DESIGNSIZE"*number*words )/function(t,a) t[ 1]=a end+("CHECKSUM"*number*words )/function(t,a) t[ 2]=a end+("SPACE"*number*plus*minus )/function(t,a,b,c) t[ 3],t[ 4],t[ 5]=a,b,c end+("QUAD"*number )/function(t,a) t[ 6]=a end+("EXTRASPACE"*number )/function(t,a) t[ 7]=a end+("NUM"*number*number*number )/function(t,a,b,c) t[ 8],t[ 9],t[10]=a,b,c end+("DENOM"*number*number )/function(t,a,b) t[11],t[12]=a,b end+("SUP"*number*number*number )/function(t,a,b,c) t[13],t[14],t[15]=a,b,c end+("SUB"*number*number )/function(t,a,b) t[16],t[17]=a,b end+("SUPDROP"*number )/function(t,a) t[18]=a end+("SUBDROP"*number )/function(t,a) t[19]=a end+("DELIM"*number*number )/function(t,a,b) t[20],t[21]=a,b end+("AXISHEIGHT"*number )/function(t,a) t[22]=a end
- )+(1-lineend)^0
- )+(1-comment)^1
-)^0
-local function scan_comment(str)
- local fd={}
- lpegmatch(pattern,str,1,fd)
- return fd
-end
-local keys={
- FontName=function(data,line)
- data.metadata.fontname=strip(line)
- data.metadata.fullname=strip(line)
- end,
- ItalicAngle=function(data,line)
- data.metadata.italicangle=tonumber(line)
- end,
- IsFixedPitch=function(data,line)
- data.metadata.monospaced=toboolean(line,true)
- end,
- CharWidth=function(data,line)
- data.metadata.charwidth=tonumber(line)
- end,
- XHeight=function(data,line)
- data.metadata.xheight=tonumber(line)
- end,
- Descender=function(data,line)
- data.metadata.descender=tonumber (line)
- end,
- Ascender=function(data,line)
- data.metadata.ascender=tonumber (line)
- end,
- Comment=function(data,line)
- line=lower(line)
- local designsize=match(line,"designsize[^%d]*(%d+)")
- if designsize then data.metadata.designsize=tonumber(designsize) end
- end,
-}
-local function get_charmetrics(data,charmetrics,vector)
- local characters=data.characters
- local chr,ind={},0
- for k,v in gmatch(charmetrics,"([%a]+) +(.-) *;") do
- if k=='C' then
- v=tonumber(v)
- if v<0 then
- ind=ind+1
- else
- ind=v
- end
- chr={
- index=ind
- }
- elseif k=='WX' then
- chr.width=tonumber(v)
- elseif k=='N' then
- characters[v]=chr
- elseif k=='B' then
- local llx,lly,urx,ury=match(v,"^ *(.-) +(.-) +(.-) +(.-)$")
- chr.boundingbox={ tonumber(llx),tonumber(lly),tonumber(urx),tonumber(ury) }
- elseif k=='L' then
- local plus,becomes=match(v,"^(.-) +(.-)$")
- local ligatures=chr.ligatures
- if ligatures then
- ligatures[plus]=becomes
- else
- chr.ligatures={ [plus]=becomes }
- end
- end
- end
-end
-local function get_kernpairs(data,kernpairs)
- local characters=data.characters
- for one,two,value in gmatch(kernpairs,"KPX +(.-) +(.-) +(.-)\n") do
- local chr=characters[one]
- if chr then
- local kerns=chr.kerns
- if kerns then
- kerns[two]=tonumber(value)
- else
- chr.kerns={ [two]=tonumber(value) }
- end
- end
- end
-end
-local function get_variables(data,fontmetrics)
- for key,rest in gmatch(fontmetrics,"(%a+) *(.-)[\n\r]") do
- local keyhandler=keys[key]
- if keyhandler then
- keyhandler(data,rest)
- end
- end
-end
+fonts=fonts or {}
+local handlers=fonts.handlers or {}
+fonts.handlers=handlers
+local afm=handlers.afm or {}
+handlers.afm=afm
+local readers=afm.readers or {}
+afm.readers=readers
+afm.version=1.512
local get_indexes
do
local n,m
@@ -22440,14 +22323,14 @@ do
end
local function loadpfbvector(filename)
local data=io.loaddata(resolvers.findfile(filename))
- if not find(data,"!PS%-AdobeFont%-") then
- print("no font",filename)
- return
- end
if not data then
print("no data",filename)
return
end
+ if not find(data,"!PS%-AdobeFont%-") then
+ print("no font",filename)
+ return
+ end
local ascii,binary=match(data,"(.*)eexec%s+......(.*)")
if not binary then
print("no binary",filename)
@@ -22455,7 +22338,9 @@ do
end
binary=decrypt(binary,4)
local vector=lpegmatch(p_filternames,binary)
- vector[0]=table.remove(vector,1)
+ if vector[1]==".notdef" then
+ vector[0]=table.remove(vector,1)
+ end
if not vector then
print("no vector",filename)
return
@@ -22482,9 +22367,104 @@ do
end
end
end
-local function readafm(filename)
- local ok,afmblob,size=resolvers.loadbinfile(filename)
- if ok and afmblob then
+local spacing=patterns.whitespace
+local lineend=patterns.newline
+local number=spacing*S("+-")^-1*(R("09")+S("."))^1/tonumber
+local name=spacing*C((1-spacing)^1)
+local words=spacing*(1-lineend)^1/strip
+local rest=(1-lineend)^0
+local fontdata=Carg(1)
+local semicolon=spacing*P(";")
+local plus=P("plus")*number
+local minus=P("minus")*number
+local function addkernpair(data,one,two,value)
+ local chr=data.characters[one]
+ if chr then
+ local kerns=chr.kerns
+ if kerns then
+ kerns[two]=tonumber(value)
+ else
+ chr.kerns={ [two]=tonumber(value) }
+ end
+ end
+end
+local p_kernpair=(fontdata*P("KPX")*name*name*number)/addkernpair
+local chr=false
+local ind=0
+local function start(data,version)
+ data.metadata.afmversion=version
+ ind=0
+ chr={}
+end
+local function stop()
+ ind=0
+ chr=false
+end
+local function setindex(i)
+ if i<0 then
+ ind=ind+1
+ else
+ ind=i
+ end
+ chr={
+ index=ind
+ }
+end
+local function setwidth(width)
+ chr.width=width
+end
+local function setname(data,name)
+ data.characters[name]=chr
+end
+local function setboundingbox(boundingbox)
+ chr.boundingbox=boundingbox
+end
+local function setligature(plus,becomes)
+ local ligatures=chr.ligatures
+ if ligatures then
+ ligatures[plus]=becomes
+ else
+ chr.ligatures={ [plus]=becomes }
+ end
+end
+local p_charmetric=((
+ P("C")*number/setindex+P("WX")*number/setwidth+P("N")*fontdata*name/setname+P("B")*Ct((number)^4)/setboundingbox+P("L")*(name)^2/setligature
+ )*semicolon )^1
+local p_charmetrics=P("StartCharMetrics")*number*(p_charmetric+(1-P("EndCharMetrics")))^0*P("EndCharMetrics")
+local p_kernpairs=P("StartKernPairs")*number*(p_kernpair+(1-P("EndKernPairs" )))^0*P("EndKernPairs" )
+local function set_1(data,key,a) data.metadata[lower(key)]=a end
+local function set_2(data,key,a,b) data.metadata[lower(key)]={ a,b } end
+local function set_3(data,key,a,b,c) data.metadata[lower(key)]={ a,b,c } end
+local p_parameters=P(false)+fontdata*((P("FontName")+P("FullName")+P("FamilyName"))/lower)*words/function(data,key,value)
+ data.metadata[key]=value
+ end+fontdata*((P("Weight")+P("Version"))/lower)*name/function(data,key,value)
+ data.metadata[key]=value
+ end+fontdata*P("IsFixedPitch")*name/function(data,pitch)
+ data.metadata.monospaced=toboolean(pitch,true)
+ end+fontdata*P("FontBBox")*Ct(number^4)/function(data,boundingbox)
+ data.metadata.boundingbox=boundingbox
+ end+fontdata*((P("CharWidth")+P("CapHeight")+P("XHeight")+P("Descender")+P("Ascender")+P("ItalicAngle"))/lower)*number/function(data,key,value)
+ data.metadata[key]=value
+ end+P("Comment")*spacing*(P(false)+(fontdata*C("DESIGNSIZE")*number*rest)/set_1
++(fontdata*C("TFM designsize")*number*rest)/set_1+(fontdata*C("DesignSize")*number*rest)/set_1+(fontdata*C("CODINGSCHEME")*words*rest)/set_1
++(fontdata*C("CHECKSUM")*number*words*rest)/set_1
++(fontdata*C("SPACE")*number*plus*minus*rest)/set_3
++(fontdata*C("QUAD")*number*rest)/set_1
++(fontdata*C("EXTRASPACE")*number*rest)/set_1
++(fontdata*C("NUM")*number*number*number*rest)/set_3
++(fontdata*C("DENOM")*number*number*rest)/set_2
++(fontdata*C("SUP")*number*number*number*rest)/set_3
++(fontdata*C("SUB")*number*number*rest)/set_2
++(fontdata*C("SUPDROP")*number*rest)/set_1
++(fontdata*C("SUBDROP")*number*rest)/set_1
++(fontdata*C("DELIM")*number*number*rest)/set_2
++(fontdata*C("AXISHEIGHT")*number*rest)/set_1
+ )
+local fullparser=(P("StartFontMetrics")*fontdata*name/start )*(p_charmetrics+p_kernpairs+p_parameters+(1-P("EndFontMetrics")) )^0*(P("EndFontMetrics")/stop )
+local infoparser=(P("StartFontMetrics")*fontdata*name/start )*(p_parameters+(1-P("EndFontMetrics")) )^0*(P("EndFontMetrics")/stop )
+local function read(filename,parser)
+ local afmblob=io.loaddata(filename)
+ if afmblob then
local data={
resources={
filename=resolvers.unresolve(filename),
@@ -22503,29 +22483,10 @@ local function readafm(filename)
descriptions={
},
}
- for charmetrics in gmatch(afmblob,"StartCharMetrics(.-)EndCharMetrics") do
- if trace_loading then
- report_afm("loading char metrics")
- end
- get_charmetrics(data,charmetrics,vector)
- break
- end
- for kernpairs in gmatch(afmblob,"StartKernPairs(.-)EndKernPairs") do
- if trace_loading then
- report_afm("loading kern pairs")
- end
- get_kernpairs(data,kernpairs)
- break
- end
- for version,fontmetrics in gmatch(afmblob,"StartFontMetrics%s+([%d%.]+)(.-)EndFontMetrics") do
- if trace_loading then
- report_afm("loading variables")
- end
- data.afmversion=version
- get_variables(data,fontmetrics)
- data.fontdimens=scan_comment(fontmetrics)
- break
+ if trace_loading then
+ report_afm("parsing afm file %a",filename)
end
+ lpegmatch(parser,afmblob,1,data)
return data
else
if trace_loading then
@@ -22534,6 +22495,73 @@ local function readafm(filename)
return nil
end
end
+function readers.loadfont(afmname,pfbname)
+ local data=read(resolvers.findfile(afmname),fullparser)
+ if data then
+ if not pfbname or pfbname=="" then
+ pfbname=file.replacesuffix(file.nameonly(afmname),"pfb")
+ pfbname=resolvers.findfile(pfbname)
+ end
+ if pfbname and pfbname~="" then
+ data.resources.filename=resolvers.unresolve(pfbname)
+ get_indexes(data,pfbname)
+ elseif trace_loading then
+ report_afm("no pfb file for %a",afmname)
+ end
+ return data
+ end
+end
+function readers.getinfo(filename)
+ local data=read(resolvers.findfile(filename),infoparser)
+ if data then
+ return data.metadata
+ end
+end
+
+end -- closure
+
+do -- begin closure to overcome local limits and interference
+
+if not modules then modules={} end modules ['font-one']={
+ 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 fonts,logs,trackers,containers,resolvers=fonts,logs,trackers,containers,resolvers
+local next,type,tonumber,rawget=next,type,tonumber,rawget
+local match,gmatch,lower,gsub,strip,find=string.match,string.gmatch,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 lpegmatch,patterns=lpeg.match,lpeg.patterns
+local trace_features=false trackers.register("afm.features",function(v) trace_features=v end)
+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 trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end)
+local report_afm=logs.reporter("fonts","afm loading")
+local setmetatableindex=table.setmetatableindex
+local derivetable=table.derive
+local findbinfile=resolvers.findbinfile
+local definers=fonts.definers
+local readers=fonts.readers
+local constructors=fonts.constructors
+local afm=constructors.newhandler("afm")
+local pfb=constructors.newhandler("pfb")
+local otf=fonts.handlers.otf
+local otfreaders=otf.readers
+local otfenhancers=otf.enhancers
+local afmfeatures=constructors.newfeatures("afm")
+local registerafmfeature=afmfeatures.register
+afm.version=1.512
+afm.cache=containers.define("fonts","afm",afm.version,true)
+afm.autoprefixed=true
+afm.helpdata={}
+afm.syncspace=true
+local overloads=fonts.mappings.overloads
+local applyruntimefixes=fonts.treatments and fonts.treatments.applyfixes
local enhancers={
}
local steps={
@@ -22577,14 +22605,8 @@ function afm.load(filename)
end
if not data or data.size~=size or data.time~=time or data.pfbsize~=pfbsize or data.pfbtime~=pfbtime then
report_afm("reading %a",filename)
- data=readafm(filename)
+ data=afm.readers.loadfont(filename,pfbname)
if data then
- if pfbname~="" then
- data.resources.filename=resolvers.unresolve(pfbname)
- get_indexes(data,pfbname)
- elseif trace_loading then
- report_afm("no pfb file for %a",filename)
- end
applyenhancers(data,filename)
fonts.mappings.addtounicode(data,filename)
otfreaders.pack(data)
@@ -22975,11 +22997,30 @@ local function copytotfm(data)
end
end
end
- local fd=data.fontdimens
- if fd and fd[8] and fd[9] and fd[10] then
- for k,v in next,fd do
- parameters[k]=v
- end
+ if metadata.sup then
+ local dummy={ 0,0,0 }
+ parameters[ 1]=metadata.designsize or 0
+ parameters[ 2]=metadata.checksum or 0
+ parameters[ 3],
+ parameters[ 4],
+ parameters[ 5]=unpack(metadata.space or dummy)
+ parameters[ 6]=metadata.quad or 0
+ parameters[ 7]=metadata.extraspace or 0
+ parameters[ 8],
+ parameters[ 9],
+ parameters[10]=unpack(metadata.num or dummy)
+ parameters[11],
+ parameters[12]=unpack(metadata.denom or dummy)
+ parameters[13],
+ parameters[14],
+ parameters[15]=unpack(metadata.sup or dummy)
+ parameters[16],
+ parameters[17]=unpack(metadata.sub or dummy)
+ parameters[18]=metadata.supdrop or 0
+ parameters[19]=metadata.subdrop or 0
+ parameters[20],
+ parameters[21]=unpack(metadata.delim or dummy)
+ parameters[22]=metadata.axisheight or 0
end
parameters.designsize=(metadata.designsize or 10)*65536
parameters.ascender=abs(metadata.ascender or 0)
--
cgit v1.2.3
From e7b0a9520127d4b143ceaa1240bd199219f341e8 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Wed, 18 May 2016 07:51:00 +0200
Subject: [featurs,loaders] adjust loader specifications to Context conventions
---
src/luaotfload-features.lua | 7 ++++---
src/luaotfload-loaders.lua | 9 +++------
2 files changed, 7 insertions(+), 9 deletions(-)
diff --git a/src/luaotfload-features.lua b/src/luaotfload-features.lua
index d6531d3..ae4ac77 100644
--- a/src/luaotfload-features.lua
+++ b/src/luaotfload-features.lua
@@ -1122,7 +1122,6 @@ local import_values = {
-- "style", "optsize",--> from slashed notation; handled otherwise
{ "lookup", false },
{ "sub", false },
- { "mode", true },
}
local lookup_types = { "anon" , "file", "kpse"
@@ -1222,8 +1221,10 @@ local handle_request = function (specification)
if name then
if lookup == "file" then
- specification.filename = name
- name = file.removesuffix (name)
+ local suffix = file.suffix (name)
+ specification.forcedname = name
+ specification.forced = suffix
+ name = file.removesuffix (name)
end
specification.name = name
specification.lookup = lookup or specification.lookup
diff --git a/src/luaotfload-loaders.lua b/src/luaotfload-loaders.lua
index c21c9eb..fd3e711 100644
--- a/src/luaotfload-loaders.lua
+++ b/src/luaotfload-loaders.lua
@@ -52,12 +52,9 @@ end
local afm_reader = fonts.readers.afm
local afm_loader = function (specification)
- local name = specification.name
- local filename = specification.filename
- specification.forced = "afm"
- specification.forcedname = filename
- specification.filename = file.replacesuffix (filename, "afm")
- return afm_reader (specification, "afm")
+ specification.forced = "afm"
+ specification.sub = false
+ return afm_reader (specification)
end
local afm_compat_message = function (specification)
--
cgit v1.2.3
From 72f10523323c3e5183f91931db56dcf38f92b68d Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Thu, 19 May 2016 08:25:34 +0200
Subject: [fontloader] include font-one.lua
---
scripts/mkimport | 17 +-
scripts/mkstatus | 1 +
src/fontloader/misc/fontloader-font-onr.lua | 405 ++++++++++++++++++++++++++++
src/luaotfload-init.lua | 2 +
src/luaotfload-loaders.lua | 8 +-
src/luaotfload-tool.lua | 1 +
6 files changed, 424 insertions(+), 10 deletions(-)
create mode 100644 src/fontloader/misc/fontloader-font-onr.lua
diff --git a/scripts/mkimport b/scripts/mkimport
index e2b6f72..93f4b89 100755
--- a/scripts/mkimport
+++ b/scripts/mkimport
@@ -237,6 +237,7 @@ local imports = {
{ name = "font-ini" , ours = "font-ini" , kind = kind_merged },
{ name = "font-lua" , ours = "font-lua" , kind = kind_merged },
{ name = "font-map" , ours = "font-map" , kind = kind_merged },
+ { name = "font-onr" , ours = "font-onr" , kind = kind_merged },
{ name = "font-one" , ours = "font-one" , kind = kind_merged },
{ name = "font-osd" , ours = "font-osd" , kind = kind_merged },
{ name = "font-ota" , ours = "font-ota" , kind = kind_merged },
@@ -306,13 +307,14 @@ local package = {
--- [32] font-ota.lua
--- [33] font-ots.lua
--- [34] font-osd.lua
---- [35] font-one.lua
---- [36] font-afk.lua
---- [37] font-lua.lua
---- [38] font-def.lua
---- [39] font-xtx.lua
---- [40] luatex-fonts-ext.lua
---- [41] font-gbn.lua
+--- [35] font-onr.lua
+--- [36] font-one.lua
+--- [37] font-afk.lua
+--- [38] font-lua.lua
+--- [39] font-def.lua
+--- [40] font-xtx.lua
+--- [41] luatex-fonts-ext.lua
+--- [42] font-gbn.lua
---
--- Of these, nos. 01--11 are provided by the Lualibs. Keeping them
--- around in the Luaotfload fontloader is therefore unnecessary.
@@ -370,6 +372,7 @@ local package = {
"font-ota",
"font-ots",
"font-osd",
+ "font-onr",
"font-one",
"font-afk",
"font-lua",
diff --git a/scripts/mkstatus b/scripts/mkstatus
index 6a05833..5b29913 100755
--- a/scripts/mkstatus
+++ b/scripts/mkstatus
@@ -84,6 +84,7 @@ local names = {
{ miscdir, "fontloader-basics-nod.lua", },
{ miscdir, "fontloader-data-con.lua", },
{ miscdir, "fontloader-font-afk.lua", },
+ { miscdir, "fontloader-font-onr.lua", },
{ miscdir, "fontloader-font-one.lua", },
{ miscdir, "fontloader-font-cid.lua", },
{ miscdir, "fontloader-font-con.lua", },
diff --git a/src/fontloader/misc/fontloader-font-onr.lua b/src/fontloader/misc/fontloader-font-onr.lua
new file mode 100644
index 0000000..2699f25
--- /dev/null
+++ b/src/fontloader/misc/fontloader-font-onr.lua
@@ -0,0 +1,405 @@
+if not modules then modules = { } end modules ['font-onr'] = {
+ 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"
+}
+
+--[[ldx--
+Some code may look a bit obscure but this has to do with the fact that we also use
+this code for testing and much code evolved in the transition from to
+ to .
+
+The following code still has traces of intermediate font support where we handles
+font encodings. Eventually font encoding went away but we kept some code around in
+other modules.
+
+This version implements a node mode approach so that users can also more easily
+add features.
+--ldx]]--
+
+local fonts, logs, trackers, resolvers = fonts, logs, trackers, resolvers
+
+local next, type, tonumber, rawget = next, type, tonumber, rawget
+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 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")
+
+fonts = fonts or { }
+local handlers = fonts.handlers or { }
+fonts.handlers = handlers
+local afm = handlers.afm or { }
+handlers.afm = afm
+local readers = afm.readers or { }
+afm.readers = readers
+
+afm.version = 1.512 -- incrementing this number one up will force a re-cache
+
+--[[ldx--
+We start with the basic reader which we give a name similar to the built in
+and reader.
+We use a new (unfinished) pfb loader but I see no differences between the old
+and new vectors (we actually had one bad vector with the old loader).
+--ldx]]--
+
+local get_indexes
+
+do
+
+ local n, m
+
+ local progress = function(str,position,name,size)
+ local forward = position + tonumber(size) + 3 + 2
+ n = n + 1
+ if n >= m then
+ return #str, name
+ elseif forward < #str then
+ return forward, name
+ else
+ return #str, name
+ end
+ end
+
+ local initialize = function(str,position,size)
+ n = 0
+ m = tonumber(size)
+ return position + 1
+ end
+
+ local charstrings = P("/CharStrings")
+ local name = P("/") * C((R("az")+R("AZ")+R("09")+S("-_."))^1)
+ local size = C(R("09")^1)
+ local spaces = P(" ")^1
+
+ local p_filternames = Ct (
+ (1-charstrings)^0 * charstrings * spaces * Cmt(size,initialize)
+ * (Cmt(name * P(" ")^1 * C(R("09")^1), progress) + P(1))^1
+ )
+
+ -- if one of first 4 not 0-9A-F then binary else hex
+
+ local decrypt
+
+ do
+
+ local r, c1, c2, n = 0, 0, 0, 0
+
+ local function step(c)
+ local cipher = byte(c)
+ local plain = bxor(cipher,rshift(r,8))
+ r = ((cipher + r) * c1 + c2) % 65536
+ return char(plain)
+ end
+
+ decrypt = function(binary)
+ r, c1, c2, n = 55665, 52845, 22719, 4
+ binary = gsub(binary,".",step)
+ return sub(binary,n+1)
+ end
+
+ -- local pattern = Cs((P(1) / step)^1)
+ --
+ -- decrypt = function(binary)
+ -- r, c1, c2, n = 55665, 52845, 22719, 4
+ -- binary = lpegmatch(pattern,binary)
+ -- return sub(binary,n+1)
+ -- end
+
+ end
+
+ local function loadpfbvector(filename)
+ -- for the moment limited to encoding only
+
+ local data = io.loaddata(resolvers.findfile(filename))
+
+ if not data then
+ print("no data",filename)
+ return
+ end
+
+ if not find(data,"!PS%-AdobeFont%-") then
+ print("no font",filename)
+ return
+ end
+
+ local ascii, binary = match(data,"(.*)eexec%s+......(.*)")
+
+ if not binary then
+ print("no binary",filename)
+ return
+ end
+
+ binary = decrypt(binary,4)
+
+ local vector = lpegmatch(p_filternames,binary)
+
+ if vector[1] == ".notdef" then
+ -- tricky
+ vector[0] = table.remove(vector,1)
+ end
+
+ if not vector then
+ print("no vector",filename)
+ return
+ end
+
+ return vector
+
+ end
+
+ get_indexes = function(data,pfbname)
+ local vector = loadpfbvector(pfbname)
+ if vector then
+ local characters = data.characters
+ if trace_loading then
+ report_afm("getting index data from %a",pfbname)
+ end
+ for index=1,#vector do
+ local name = vector[index]
+ local char = characters[name]
+ if char then
+ if trace_indexing then
+ report_afm("glyph %a has index %a",name,index)
+ end
+ char.index = index
+ end
+ end
+ end
+ end
+
+end
+
+--[[ldx--
+We start with the basic reader which we give a name similar to the built in
+and reader. We only need data that is relevant for our use. We don't support
+more complex arrangements like multiple master (obsolete), direction specific kerning, etc.
+--ldx]]--
+
+local spacing = patterns.whitespace
+local lineend = patterns.newline
+local number = spacing * S("+-")^-1 * (R("09") + S("."))^1 / tonumber
+local name = spacing * C((1-spacing)^1)
+local words = spacing * (1 - lineend)^1 / strip
+local rest = (1 - lineend)^0
+local fontdata = Carg(1)
+local semicolon = spacing * P(";")
+local plus = P("plus") * number
+local minus = P("minus") * number
+
+-- kern pairs
+
+local function addkernpair(data,one,two,value)
+ local chr = data.characters[one]
+ if chr then
+ local kerns = chr.kerns
+ if kerns then
+ kerns[two] = tonumber(value)
+ else
+ chr.kerns = { [two] = tonumber(value) }
+ end
+ end
+end
+
+local p_kernpair = (fontdata * P("KPX") * name * name * number) / addkernpair
+
+-- char metrics
+
+local chr = false
+local ind = 0
+
+local function start(data,version)
+ data.metadata.afmversion = version
+ ind = 0
+ chr = { }
+end
+
+local function stop()
+ ind = 0
+ chr = false
+end
+
+local function setindex(i)
+ if i < 0 then
+ ind = ind + 1 -- ?
+ else
+ ind = i
+ end
+ chr = {
+ index = ind
+ }
+end
+
+local function setwidth(width)
+ chr.width = width
+end
+
+local function setname(data,name)
+ data.characters[name] = chr
+end
+
+local function setboundingbox(boundingbox)
+ chr.boundingbox = boundingbox
+end
+
+local function setligature(plus,becomes)
+ local ligatures = chr.ligatures
+ if ligatures then
+ ligatures[plus] = becomes
+ else
+ chr.ligatures = { [plus] = becomes }
+ end
+end
+
+local p_charmetric = ( (
+ P("C") * number / setindex
+ + P("WX") * number / setwidth
+ + P("N") * fontdata * name / setname
+ + P("B") * Ct((number)^4) / setboundingbox
+ + P("L") * (name)^2 / setligature
+ ) * semicolon )^1
+
+local p_charmetrics = P("StartCharMetrics") * number * (p_charmetric + (1-P("EndCharMetrics")))^0 * P("EndCharMetrics")
+local p_kernpairs = P("StartKernPairs") * number * (p_kernpair + (1-P("EndKernPairs" )))^0 * P("EndKernPairs" )
+
+local function set_1(data,key,a) data.metadata[lower(key)] = a end
+local function set_2(data,key,a,b) data.metadata[lower(key)] = { a, b } end
+local function set_3(data,key,a,b,c) data.metadata[lower(key)] = { a, b, c } end
+
+-- Notice string
+-- EncodingScheme string
+-- MappingScheme integer
+-- EscChar integer
+-- CharacterSet string
+-- Characters integer
+-- IsBaseFont boolean
+-- VVector number number
+-- IsFixedV boolean
+
+local p_parameters = P(false)
+ + fontdata
+ * ((P("FontName") + P("FullName") + P("FamilyName"))/lower)
+ * words / function(data,key,value)
+ data.metadata[key] = value
+ end
+ + fontdata
+ * ((P("Weight") + P("Version"))/lower)
+ * name / function(data,key,value)
+ data.metadata[key] = value
+ end
+ + fontdata
+ * P("IsFixedPitch")
+ * name / function(data,pitch)
+ data.metadata.monospaced = toboolean(pitch,true)
+ end
+ + fontdata
+ * P("FontBBox")
+ * Ct(number^4) / function(data,boundingbox)
+ data.metadata.boundingbox = boundingbox
+ end
+ + fontdata
+ * ((P("CharWidth") + P("CapHeight") + P("XHeight") + P("Descender") + P("Ascender") + P("ItalicAngle"))/lower)
+ * number / function(data,key,value)
+ data.metadata[key] = value
+ end
+ + P("Comment") * spacing * ( P(false)
+ + (fontdata * C("DESIGNSIZE") * number * rest) / set_1 -- 1
+ + (fontdata * C("TFM designsize") * number * rest) / set_1
+ + (fontdata * C("DesignSize") * number * rest) / set_1
+ + (fontdata * C("CODINGSCHEME") * words * rest) / set_1 --
+ + (fontdata * C("CHECKSUM") * number * words * rest) / set_1 -- 2
+ + (fontdata * C("SPACE") * number * plus * minus * rest) / set_3 -- 3 4 5
+ + (fontdata * C("QUAD") * number * rest) / set_1 -- 6
+ + (fontdata * C("EXTRASPACE") * number * rest) / set_1 -- 7
+ + (fontdata * C("NUM") * number * number * number * rest) / set_3 -- 8 9 10
+ + (fontdata * C("DENOM") * number * number * rest) / set_2 -- 11 12
+ + (fontdata * C("SUP") * number * number * number * rest) / set_3 -- 13 14 15
+ + (fontdata * C("SUB") * number * number * rest) / set_2 -- 16 17
+ + (fontdata * C("SUPDROP") * number * rest) / set_1 -- 18
+ + (fontdata * C("SUBDROP") * number * rest) / set_1 -- 19
+ + (fontdata * C("DELIM") * number * number * rest) / set_2 -- 20 21
+ + (fontdata * C("AXISHEIGHT") * number * rest) / set_1 -- 22
+ )
+
+local fullparser = ( P("StartFontMetrics") * fontdata * name / start )
+ * ( p_charmetrics + p_kernpairs + p_parameters + (1-P("EndFontMetrics")) )^0
+ * ( P("EndFontMetrics") / stop )
+
+local infoparser = ( P("StartFontMetrics") * fontdata * name / start )
+ * ( p_parameters + (1-P("EndFontMetrics")) )^0
+ * ( P("EndFontMetrics") / stop )
+
+-- infoparser = ( P("StartFontMetrics") * fontdata * name / start )
+-- * ( p_parameters + (1-P("EndFontMetrics") - P("StartCharMetrics")) )^0
+-- * ( (P("EndFontMetrics") + P("StartCharMetrics")) / stop )
+
+local function read(filename,parser)
+ local afmblob = io.loaddata(filename)
+ if afmblob then
+ local data = {
+ resources = {
+ filename = resolvers.unresolve(filename),
+ version = afm.version,
+ creator = "context mkiv",
+ },
+ properties = {
+ hasitalics = false,
+ },
+ goodies = {
+ },
+ metadata = {
+ filename = file.removesuffix(file.basename(filename))
+ },
+ characters = {
+ -- a temporary store
+ },
+ descriptions = {
+ -- the final store
+ },
+ }
+ if trace_loading then
+ report_afm("parsing afm file %a",filename)
+ end
+ lpegmatch(parser,afmblob,1,data)
+ return data
+ else
+ if trace_loading then
+ report_afm("no valid afm file %a",filename)
+ end
+ return nil
+ end
+end
+
+function readers.loadfont(afmname,pfbname)
+ local data = read(resolvers.findfile(afmname),fullparser)
+ if data then
+ if not pfbname or pfbname == "" then
+ pfbname = file.replacesuffix(file.nameonly(afmname),"pfb")
+ pfbname = resolvers.findfile(pfbname)
+ end
+ if pfbname and pfbname ~= "" then
+ data.resources.filename = resolvers.unresolve(pfbname)
+ get_indexes(data,pfbname)
+ elseif trace_loading then
+ report_afm("no pfb file for %a",afmname)
+ -- data.resources.filename = "unset" -- better than loading the afm file
+ end
+ return data
+ end
+end
+
+function readers.getinfo(filename)
+ local data = read(resolvers.findfile(filename),infoparser)
+ if data then
+ return data.metadata
+ end
+end
+
diff --git a/src/luaotfload-init.lua b/src/luaotfload-init.lua
index dfa4c56..48a8eba 100644
--- a/src/luaotfload-init.lua
+++ b/src/luaotfload-init.lua
@@ -263,6 +263,7 @@ local context_modules = {
{ ctx, "font-ota" },
{ ctx, "font-ots" },
{ ctx, "font-osd" },
+ { ctx, "font-onr" },
{ ctx, "font-one" },
{ ctx, "font-afk" },
{ ctx, "font-lua" },
@@ -521,6 +522,7 @@ local init_main = function ()
load_fontloader_module "font-ota"
load_fontloader_module "font-ots"
load_fontloader_module "font-osd"
+ load_fontloader_module "font-onr"
load_fontloader_module "font-one"
load_fontloader_module "font-afk"
load_fontloader_module "font-lua"
diff --git a/src/luaotfload-loaders.lua b/src/luaotfload-loaders.lua
index fd3e711..68cc50f 100644
--- a/src/luaotfload-loaders.lua
+++ b/src/luaotfload-loaders.lua
@@ -52,9 +52,11 @@ end
local afm_reader = fonts.readers.afm
local afm_loader = function (specification)
- specification.forced = "afm"
- specification.sub = false
- return afm_reader (specification)
+ specification.forced = "afm"
+ specification.sub = false
+ specification.forcedname = file.addsuffix(specification.name, "afm")
+ inspect(specification)
+ return afm_reader (specification, "afm")
end
local afm_compat_message = function (specification)
diff --git a/src/luaotfload-tool.lua b/src/luaotfload-tool.lua
index d01673d..bc9e425 100755
--- a/src/luaotfload-tool.lua
+++ b/src/luaotfload-tool.lua
@@ -157,6 +157,7 @@ require "fontloader-font-oto"
------- "fontloader-font-ota"
------- "fontloader-font-ots"
------- "fontloader-font-osd"
+require "fontloader-font-onr"
require "fontloader-font-one"
require "fontloader-font-afk"
require "fontloader-font-lua"
--
cgit v1.2.3
From 274ca61bf7ea43543c5aea53873f22c8b598b4a9 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Fri, 20 May 2016 08:06:55 +0200
Subject: [fontloader] sync with Context as of 2016-05-22
---
src/fontloader/misc/fontloader-font-con.lua | 2 -
src/fontloader/misc/fontloader-font-dsp.lua | 1 -
src/fontloader/misc/fontloader-font-gbn.lua | 1 -
src/fontloader/misc/fontloader-font-ini.lua | 2 -
src/fontloader/misc/fontloader-font-map.lua | 1 -
src/fontloader/misc/fontloader-font-one.lua | 14 ++++-
src/fontloader/misc/fontloader-font-onr.lua | 38 ++++++-----
src/fontloader/misc/fontloader-font-osd.lua | 3 -
src/fontloader/misc/fontloader-font-ota.lua | 1 -
src/fontloader/misc/fontloader-font-otd.lua | 3 -
src/fontloader/misc/fontloader-font-otj.lua | 2 -
src/fontloader/misc/fontloader-font-oto.lua | 2 -
src/fontloader/misc/fontloader-font-otr.lua | 4 +-
src/fontloader/misc/fontloader-font-ots.lua | 35 +++++------
src/fontloader/misc/fontloader-font-tfm.lua | 2 +-
src/fontloader/runtime/fontloader-reference.lua | 83 ++++++++++++-------------
16 files changed, 93 insertions(+), 101 deletions(-)
diff --git a/src/fontloader/misc/fontloader-font-con.lua b/src/fontloader/misc/fontloader-font-con.lua
index b118535..45ecdd6 100644
--- a/src/fontloader/misc/fontloader-font-con.lua
+++ b/src/fontloader/misc/fontloader-font-con.lua
@@ -10,7 +10,6 @@ if not modules then modules = { } end modules ['font-con'] = {
local next, tostring, rawget = next, tostring, rawget
local format, match, lower, gsub = string.format, string.match, string.lower, string.gsub
-local utfbyte = utf.byte
local sort, insert, concat, sortedkeys, serialize, fastcopy = table.sort, table.insert, table.concat, table.sortedkeys, table.serialize, table.fastcopy
local derivetable = table.derive
@@ -1286,7 +1285,6 @@ function constructors.initializefeatures(what,tfmdata,features,trace,report)
local properties = tfmdata.properties or { } -- brrr
local whathandler = handlers[what]
local whatfeatures = whathandler.features
- local whatinitializers = whatfeatures.initializers
local whatmodechecker = whatfeatures.modechecker
-- properties.mode can be enforces (for instance in font-otd)
local mode = properties.mode or (whatmodechecker and whatmodechecker(tfmdata,features,features.mode)) or features.mode or "base"
diff --git a/src/fontloader/misc/fontloader-font-dsp.lua b/src/fontloader/misc/fontloader-font-dsp.lua
index 330a940..e35d6da 100644
--- a/src/fontloader/misc/fontloader-font-dsp.lua
+++ b/src/fontloader/misc/fontloader-font-dsp.lua
@@ -69,7 +69,6 @@ local readers = fonts.handlers.otf.readers
local streamreader = readers.streamreader
local setposition = streamreader.setposition
-local skipbytes = streamreader.skip
local skipshort = streamreader.skipshort
local readushort = streamreader.readcardinal2 -- 16-bit unsigned integer
local readulong = streamreader.readcardinal4 -- 24-bit unsigned integer
diff --git a/src/fontloader/misc/fontloader-font-gbn.lua b/src/fontloader/misc/fontloader-font-gbn.lua
index a02406b..1ae817d 100644
--- a/src/fontloader/misc/fontloader-font-gbn.lua
+++ b/src/fontloader/misc/fontloader-font-gbn.lua
@@ -19,7 +19,6 @@ local nodes = nodes
local nuts = nodes.nuts -- context abstraction of direct nodes
local traverse_id = nuts.traverse_id
-local remove_node = nuts.remove
local free_node = nuts.free
local glyph_code = nodes.nodecodes.glyph
diff --git a/src/fontloader/misc/fontloader-font-ini.lua b/src/fontloader/misc/fontloader-font-ini.lua
index c547f89..abc3194 100644
--- a/src/fontloader/misc/fontloader-font-ini.lua
+++ b/src/fontloader/misc/fontloader-font-ini.lua
@@ -12,8 +12,6 @@ if not modules then modules = { } end modules ['font-ini'] = {
local allocate = utilities.storage.allocate
-local report_defining = logs.reporter("fonts","defining")
-
fonts = fonts or { }
local fonts = fonts
diff --git a/src/fontloader/misc/fontloader-font-map.lua b/src/fontloader/misc/fontloader-font-map.lua
index 838c741..db43495 100644
--- a/src/fontloader/misc/fontloader-font-map.lua
+++ b/src/fontloader/misc/fontloader-font-map.lua
@@ -10,7 +10,6 @@ local tonumber, next, type = tonumber, next, type
local match, format, find, concat, gsub, lower = string.match, string.format, string.find, table.concat, string.gsub, string.lower
local P, R, S, C, Ct, Cc, lpegmatch = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.match
-local utfbyte = utf.byte
local floor = math.floor
local formatters = string.formatters
diff --git a/src/fontloader/misc/fontloader-font-one.lua b/src/fontloader/misc/fontloader-font-one.lua
index 77f2560..a9f78f4 100644
--- a/src/fontloader/misc/fontloader-font-one.lua
+++ b/src/fontloader/misc/fontloader-font-one.lua
@@ -812,7 +812,8 @@ local function check_afm(specification,fullname)
end
function readers.afm(specification,method)
- local fullname, tfmdata = specification.filename or "", nil
+ local fullname = specification.filename or ""
+ local tfmdata = nil
if fullname == "" then
local forced = specification.forced or ""
if forced ~= "" then
@@ -841,7 +842,16 @@ function readers.pfb(specification,method) -- only called when forced
if trace_defining then
report_afm("using afm reader for %a",original)
end
- specification.specification = file.replacesuffix(original,"afm")
specification.forced = "afm"
+ local function swap(name)
+ local value = specification[swap]
+ if value then
+ specification[swap] = gsub("%.pfb",".afm",1)
+ end
+ end
+ swap("filename")
+ swap("fullname")
+ swap("forcedname")
+ swap("specification")
return readers.afm(specification,method)
end
diff --git a/src/fontloader/misc/fontloader-font-onr.lua b/src/fontloader/misc/fontloader-font-onr.lua
index 2699f25..a4969ad 100644
--- a/src/fontloader/misc/fontloader-font-onr.lua
+++ b/src/fontloader/misc/fontloader-font-onr.lua
@@ -33,6 +33,7 @@ local trace_indexing = false trackers.register("afm.indexing", function(v
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 { }
@@ -122,19 +123,19 @@ do
local data = io.loaddata(resolvers.findfile(filename))
if not data then
- print("no data",filename)
+ report_pfb("no data in %a",filename)
return
end
- if not find(data,"!PS%-AdobeFont%-") then
- print("no font",filename)
+ if not (find(data,"!PS%-AdobeFont%-") or find(data,"%%!FontType1")) then
+ report_pfb("no font in %a",filename)
return
end
local ascii, binary = match(data,"(.*)eexec%s+......(.*)")
if not binary then
- print("no binary",filename)
+ report_pfb("no binary data in %a",filename)
return
end
@@ -148,7 +149,7 @@ do
end
if not vector then
- print("no vector",filename)
+ report_pfb("no vector in %a",filename)
return
end
@@ -184,16 +185,18 @@ and reader. We only need data that is relevant for our use. We don'
more complex arrangements like multiple master (obsolete), direction specific kerning, etc.
--ldx]]--
-local spacing = patterns.whitespace
-local lineend = patterns.newline
-local number = spacing * S("+-")^-1 * (R("09") + S("."))^1 / tonumber
-local name = spacing * C((1-spacing)^1)
-local words = spacing * (1 - lineend)^1 / strip
-local rest = (1 - lineend)^0
-local fontdata = Carg(1)
-local semicolon = spacing * P(";")
-local plus = P("plus") * number
-local minus = P("minus") * number
+local spacer = patterns.spacer
+local whitespace = patterns.whitespace
+local lineend = patterns.newline
+local spacing = spacer^0
+local number = spacing * S("+-")^-1 * (R("09") + S("."))^1 / tonumber
+local name = spacing * C((1 - whitespace)^1)
+local words = spacing * ((1 - lineend)^1 / strip)
+local rest = (1 - lineend)^0
+local fontdata = Carg(1)
+local semicolon = spacing * P(";")
+local plus = spacing * P("plus") * number
+local minus = spacing * P("minus") * number
-- kern pairs
@@ -333,6 +336,10 @@ local fullparser = ( P("StartFontMetrics") * fontdata * name / start )
* ( p_charmetrics + p_kernpairs + p_parameters + (1-P("EndFontMetrics")) )^0
* ( P("EndFontMetrics") / stop )
+local fullparser = ( P("StartFontMetrics") * fontdata * name / start )
+ * ( p_charmetrics + p_kernpairs + p_parameters + (1-P("EndFontMetrics")) )^0
+ * ( P("EndFontMetrics") / stop )
+
local infoparser = ( P("StartFontMetrics") * fontdata * name / start )
* ( p_parameters + (1-P("EndFontMetrics")) )^0
* ( P("EndFontMetrics") / stop )
@@ -402,4 +409,3 @@ function readers.getinfo(filename)
return data.metadata
end
end
-
diff --git a/src/fontloader/misc/fontloader-font-osd.lua b/src/fontloader/misc/fontloader-font-osd.lua
index 6ff2e38..d2bb210 100644
--- a/src/fontloader/misc/fontloader-font-osd.lua
+++ b/src/fontloader/misc/fontloader-font-osd.lua
@@ -79,9 +79,6 @@ fonts.analyzers.methods = fonts.analyzers.methods or { node = { otf = { } } }
local otf = fonts.handlers.otf
-local nodecodes = nodes.nodecodes
-local glyph_code = nodecodes.glyph
-
local handlers = otf.handlers
local methods = fonts.analyzers.methods
diff --git a/src/fontloader/misc/fontloader-font-ota.lua b/src/fontloader/misc/fontloader-font-ota.lua
index 6a3804a..42566eb 100644
--- a/src/fontloader/misc/fontloader-font-ota.lua
+++ b/src/fontloader/misc/fontloader-font-ota.lua
@@ -44,7 +44,6 @@ local getchar = nuts.getchar
local ischar = nuts.is_char
local traverse_id = nuts.traverse_id
-local traverse_node_list = nuts.traverse
local end_of_math = nuts.end_of_math
local nodecodes = nodes.nodecodes
diff --git a/src/fontloader/misc/fontloader-font-otd.lua b/src/fontloader/misc/fontloader-font-otd.lua
index 2257caa..fc5ba64 100644
--- a/src/fontloader/misc/fontloader-font-otd.lua
+++ b/src/fontloader/misc/fontloader-font-otd.lua
@@ -36,9 +36,6 @@ local contextmerged = specifiers.contextmerged
local setmetatableindex = table.setmetatableindex
-local otffeatures = fonts.constructors.newfeatures("otf")
-local registerotffeature = otffeatures.register
-
local a_to_script = { }
local a_to_language = { }
diff --git a/src/fontloader/misc/fontloader-font-otj.lua b/src/fontloader/misc/fontloader-font-otj.lua
index b65a9db..61baf93 100644
--- a/src/fontloader/misc/fontloader-font-otj.lua
+++ b/src/fontloader/misc/fontloader-font-otj.lua
@@ -27,7 +27,6 @@ if not modules then modules = { } end modules ['font-otj'] = {
if not nodes.properties then return end
local next, rawget = next, rawget
-local utfchar = utf.char
local fastcopy = table.fastcopy
local registertracker = trackers.register
@@ -92,7 +91,6 @@ local traverse_id = nuts.traverse_id
local traverse_char = nuts.traverse_char
local insert_node_before = nuts.insert_before
local insert_node_after = nuts.insert_after
-local find_tail = nuts.tail
local properties = nodes.properties.data
diff --git a/src/fontloader/misc/fontloader-font-oto.lua b/src/fontloader/misc/fontloader-font-oto.lua
index 23beba7..1199778 100644
--- a/src/fontloader/misc/fontloader-font-oto.lua
+++ b/src/fontloader/misc/fontloader-font-oto.lua
@@ -14,8 +14,6 @@ local concat, unpack = table.concat, table.unpack
local insert, remove = table.insert, table.remove
local format, gmatch, gsub, find, match, lower, strip = string.format, string.gmatch, string.gsub, string.find, string.match, string.lower, string.strip
local type, next, tonumber, tostring, rawget = type, next, tonumber, tostring, rawget
-local lpegmatch = lpeg.match
-local utfchar = utf.char
local trace_baseinit = false trackers.register("otf.baseinit", function(v) trace_baseinit = v end)
local trace_singles = false trackers.register("otf.singles", function(v) trace_singles = v end)
diff --git a/src/fontloader/misc/fontloader-font-otr.lua b/src/fontloader/misc/fontloader-font-otr.lua
index c967e24..6595262 100644
--- a/src/fontloader/misc/fontloader-font-otr.lua
+++ b/src/fontloader/misc/fontloader-font-otr.lua
@@ -99,7 +99,7 @@ readers.streamreader = streamreader
local openfile = streamreader.open
local closefile = streamreader.close
-local skipbytes = streamreader.skip
+----- skipbytes = streamreader.skip
local setposition = streamreader.setposition
local skipshort = streamreader.skipshort
local readbytes = streamreader.readbytes
@@ -108,7 +108,7 @@ local readbyte = streamreader.readcardinal1 -- 8-bit unsigned integer
local readushort = streamreader.readcardinal2 -- 16-bit unsigned integer
local readuint = streamreader.readcardinal3 -- 24-bit unsigned integer
local readulong = streamreader.readcardinal4 -- 24-bit unsigned integer
-local readchar = streamreader.readinteger1 -- 8-bit signed integer
+----- readchar = streamreader.readinteger1 -- 8-bit signed integer
local readshort = streamreader.readinteger2 -- 16-bit signed integer
local readlong = streamreader.readinteger4 -- 24-bit unsigned integer
local readfixed = streamreader.readfixed4
diff --git a/src/fontloader/misc/fontloader-font-ots.lua b/src/fontloader/misc/fontloader-font-ots.lua
index c173de2..669668e 100644
--- a/src/fontloader/misc/fontloader-font-ots.lua
+++ b/src/fontloader/misc/fontloader-font-ots.lua
@@ -145,10 +145,8 @@ local report_direct = logs.reporter("fonts","otf direct")
local report_subchain = logs.reporter("fonts","otf subchain")
local report_chain = logs.reporter("fonts","otf chain")
local report_process = logs.reporter("fonts","otf process")
------ report_prepare = logs.reporter("fonts","otf prepare")
local report_warning = logs.reporter("fonts","otf warning")
local report_run = logs.reporter("fonts","otf run")
-local report_check = logs.reporter("fonts","otf check")
registertracker("otf.replacements", "otf.singles,otf.multiples,otf.alternatives,otf.ligatures")
registertracker("otf.positions","otf.marks,otf.kerns,otf.cursive")
@@ -185,10 +183,7 @@ local setlink = nuts.setlink
local ischar = nuts.is_char
-local insert_node_before = nuts.insert_before
local insert_node_after = nuts.insert_after
-local delete_node = nuts.delete
-local remove_node = nuts.remove
local copy_node = nuts.copy
local copy_node_list = nuts.copy_list
local find_node_tail = nuts.tail
@@ -3064,7 +3059,7 @@ local function c_run_single(head,font,attr,lookupcache,step,dataset,sequence,rlm
while start do
local char = ischar(start,font)
if char then
- local a = getattr(start,0)
+ local a = attr and getattr(start,0)
if not a or (a == attr) then
local lookupmatch = lookupcache[char]
if lookupmatch then
@@ -3097,7 +3092,7 @@ local function t_run_single(start,stop,font,attr,lookupcache)
while start ~= stop do
local char = ischar(start,font)
if char then
- local a = getattr(start,0)
+ local a = attr and getattr(start,0)
if not a or (a == attr) then
local lookupmatch = lookupcache[char]
if lookupmatch then -- hm, hyphens can match (tlig) so we need to really check
@@ -3132,7 +3127,7 @@ local function t_run_single(start,stop,font,attr,lookupcache)
end
-- local function d_run_single(prev,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
--- local a = getattr(prev,0)
+-- local a = attr and getattr(prev,0)
-- if not a or (a == attr) then
-- local char = ischar(prev) -- can be disc
-- if char then
@@ -3149,7 +3144,7 @@ end
-- end
local function k_run_single(sub,injection,last,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
- local a = getattr(sub,0)
+ local a = attr and getattr(sub,0)
if not a or (a == attr) then
for n in traverse_nodes(sub) do -- only gpos
if n == last then
@@ -3181,7 +3176,7 @@ local function c_run_multiple(head,font,attr,steps,nofsteps,dataset,sequence,rlm
while start do
local char = ischar(start,font)
if char then
- local a = getattr(start,0)
+ local a = attr and getattr(start,0)
if not a or (a == attr) then
for i=1,nofsteps do
local step = steps[i]
@@ -3228,7 +3223,7 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps)
while start ~= stop do
local char = ischar(start,font)
if char then
- local a = getattr(start,0)
+ local a = attr and getattr(start,0)
if not a or (a == attr) then
for i=1,nofsteps do
local step = steps[i]
@@ -3271,7 +3266,7 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps)
end
-- local function d_run_multiple(prev,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
--- local a = getattr(prev,0)
+-- local a = attr and getattr(prev,0)
-- if not a or (a == attr) then
-- local char = ischar(prev) -- can be disc
-- if char then
@@ -3297,7 +3292,7 @@ end
-- end
local function k_run_multiple(sub,injection,last,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
- local a = getattr(sub,0)
+ local a = attr and getattr(sub,0)
if not a or (a == attr) then
for n in traverse_nodes(sub) do -- only gpos
if n == last then
@@ -3394,6 +3389,10 @@ local function featuresprocessor(head,font,attr)
end
+ if attr == 0 then
+ attr = false -- some 10% faster when no dynamics but hardly measureable on real runs
+ end
+
head = tonut(head)
if trace_steps then
@@ -3405,7 +3404,7 @@ local function featuresprocessor(head,font,attr)
local done = false
local datasets = otf.dataset(tfmdata,font,attr)
- local dirstack = { } -- could move outside function btu we can have local runss
+ local dirstack = { } -- could move outside function but we can have local runs
sweephead = { }
@@ -3451,7 +3450,7 @@ local function featuresprocessor(head,font,attr)
while start do
local char = ischar(start,font)
if char then
- local a = getattr(start,0)
+ local a = attr and getattr(start,0)
if not a or (a == attr) then
for i=1,nofsteps do
local step = steps[i]
@@ -3489,14 +3488,12 @@ local function featuresprocessor(head,font,attr)
local step = steps[1]
local lookupcache = step.coverage
if not lookupcache then
- -- can't happen, no check in loop either
report_missing_coverage(dataset,sequence)
else
-
while start do
local char, id = ischar(start,font)
if char then
- local a = getattr(start,0)
+ local a = attr and getattr(start,0)
if a then
a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
else
@@ -3553,7 +3550,7 @@ local function featuresprocessor(head,font,attr)
while start do
local char, id = ischar(start,font)
if char then
- local a = getattr(start,0)
+ local a = attr and getattr(start,0)
if a then
a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
else
diff --git a/src/fontloader/misc/fontloader-font-tfm.lua b/src/fontloader/misc/fontloader-font-tfm.lua
index 8e92c48..f790064 100644
--- a/src/fontloader/misc/fontloader-font-tfm.lua
+++ b/src/fontloader/misc/fontloader-font-tfm.lua
@@ -29,7 +29,7 @@ tfm.maxnestingdepth = 5
tfm.maxnestingsize = 65536*1024
local tfmfeatures = constructors.newfeatures("tfm")
-local registertfmfeature = tfmfeatures.register
+----- registertfmfeature = tfmfeatures.register
constructors.resolvevirtualtoo = false -- wil be set in font-ctx.lua
diff --git a/src/fontloader/runtime/fontloader-reference.lua b/src/fontloader/runtime/fontloader-reference.lua
index f10f139..9e7d889 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 : 05/17/16 10:06:55
+-- merge date : 05/22/16 15:18:33
do -- begin closure to overcome local limits and interference
@@ -5034,7 +5034,6 @@ if not modules then modules={} end modules ['font-ini']={
license="see context related readme files"
}
local allocate=utilities.storage.allocate
-local report_defining=logs.reporter("fonts","defining")
fonts=fonts or {}
local fonts=fonts
fonts.hashes={ identifiers=allocate() }
@@ -5061,7 +5060,6 @@ if not modules then modules={} end modules ['font-con']={
}
local next,tostring,rawget=next,tostring,rawget
local format,match,lower,gsub=string.format,string.match,string.lower,string.gsub
-local utfbyte=utf.byte
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)
@@ -6087,7 +6085,6 @@ function constructors.initializefeatures(what,tfmdata,features,trace,report)
local properties=tfmdata.properties or {}
local whathandler=handlers[what]
local whatfeatures=whathandler.features
- local whatinitializers=whatfeatures.initializers
local whatmodechecker=whatfeatures.modechecker
local mode=properties.mode or (whatmodechecker and whatmodechecker(tfmdata,features,features.mode)) or features.mode or "base"
properties.mode=mode
@@ -6403,7 +6400,6 @@ if not modules then modules={} end modules ['font-map']={
local tonumber,next,type=tonumber,next,type
local match,format,find,concat,gsub,lower=string.match,string.format,string.find,table.concat,string.gsub,string.lower
local P,R,S,C,Ct,Cc,lpegmatch=lpeg.P,lpeg.R,lpeg.S,lpeg.C,lpeg.Ct,lpeg.Cc,lpeg.match
-local utfbyte=utf.byte
local floor=math.floor
local formatters=string.formatters
local trace_loading=false trackers.register("fonts.loading",function(v) trace_loading=v end)
@@ -6839,7 +6835,6 @@ tfm.version=1.000
tfm.maxnestingdepth=5
tfm.maxnestingsize=65536*1024
local tfmfeatures=constructors.newfeatures("tfm")
-local registertfmfeature=tfmfeatures.register
constructors.resolvevirtualtoo=false
fonts.formats.tfm="type1"
fonts.formats.ofm="type1"
@@ -7148,7 +7143,6 @@ local streamreader=utilities.files
readers.streamreader=streamreader
local openfile=streamreader.open
local closefile=streamreader.close
-local skipbytes=streamreader.skip
local setposition=streamreader.setposition
local skipshort=streamreader.skipshort
local readbytes=streamreader.readbytes
@@ -7156,8 +7150,7 @@ local readstring=streamreader.readstring
local readbyte=streamreader.readcardinal1
local readushort=streamreader.readcardinal2
local readuint=streamreader.readcardinal3
-local readulong=streamreader.readcardinal4
-local readchar=streamreader.readinteger1
+local readulong=streamreader.readcardinal4
local readshort=streamreader.readinteger2
local readlong=streamreader.readinteger4
local readfixed=streamreader.readfixed4
@@ -10597,7 +10590,6 @@ local report=logs.reporter("otf reader")
local readers=fonts.handlers.otf.readers
local streamreader=readers.streamreader
local setposition=streamreader.setposition
-local skipbytes=streamreader.skip
local skipshort=streamreader.skipshort
local readushort=streamreader.readcardinal2
local readulong=streamreader.readcardinal4
@@ -15170,8 +15162,6 @@ local concat,unpack=table.concat,table.unpack
local insert,remove=table.insert,table.remove
local format,gmatch,gsub,find,match,lower,strip=string.format,string.gmatch,string.gsub,string.find,string.match,string.lower,string.strip
local type,next,tonumber,tostring,rawget=type,next,tonumber,tostring,rawget
-local lpegmatch=lpeg.match
-local utfchar=utf.char
local trace_baseinit=false trackers.register("otf.baseinit",function(v) trace_baseinit=v end)
local trace_singles=false trackers.register("otf.singles",function(v) trace_singles=v end)
local trace_multiples=false trackers.register("otf.multiples",function(v) trace_multiples=v end)
@@ -15543,7 +15533,6 @@ if not modules then modules={} end modules ['font-otj']={
}
if not nodes.properties then return end
local next,rawget=next,rawget
-local utfchar=utf.char
local fastcopy=table.fastcopy
local registertracker=trackers.register
local trace_injections=false registertracker("fonts.injections",function(v) trace_injections=v end)
@@ -15588,7 +15577,6 @@ local traverse_id=nuts.traverse_id
local traverse_char=nuts.traverse_char
local insert_node_before=nuts.insert_before
local insert_node_after=nuts.insert_after
-local find_tail=nuts.tail
local properties=nodes.properties.data
function injections.installnewkern(nk)
newkern=nk or newkern
@@ -16865,7 +16853,6 @@ local getsubtype=nuts.getsubtype
local getchar=nuts.getchar
local ischar=nuts.is_char
local traverse_id=nuts.traverse_id
-local traverse_node_list=nuts.traverse
local end_of_math=nuts.end_of_math
local nodecodes=nodes.nodecodes
local disc_code=nodecodes.disc
@@ -17257,7 +17244,6 @@ local report_chain=logs.reporter("fonts","otf chain")
local report_process=logs.reporter("fonts","otf process")
local report_warning=logs.reporter("fonts","otf warning")
local report_run=logs.reporter("fonts","otf run")
-local report_check=logs.reporter("fonts","otf check")
registertracker("otf.replacements","otf.singles,otf.multiples,otf.alternatives,otf.ligatures")
registertracker("otf.positions","otf.marks,otf.kerns,otf.cursive")
registertracker("otf.actions","otf.replacements,otf.positions")
@@ -17288,10 +17274,7 @@ local getdisc=nuts.getdisc
local setdisc=nuts.setdisc
local setlink=nuts.setlink
local ischar=nuts.is_char
-local insert_node_before=nuts.insert_before
local insert_node_after=nuts.insert_after
-local delete_node=nuts.delete
-local remove_node=nuts.remove
local copy_node=nuts.copy
local copy_node_list=nuts.copy_list
local find_node_tail=nuts.tail
@@ -19686,7 +19669,7 @@ local function c_run_single(head,font,attr,lookupcache,step,dataset,sequence,rlm
while start do
local char=ischar(start,font)
if char then
- local a=getattr(start,0)
+ local a=attr and getattr(start,0)
if not a or (a==attr) then
local lookupmatch=lookupcache[char]
if lookupmatch then
@@ -19716,7 +19699,7 @@ local function t_run_single(start,stop,font,attr,lookupcache)
while start~=stop do
local char=ischar(start,font)
if char then
- local a=getattr(start,0)
+ local a=attr and getattr(start,0)
if not a or (a==attr) then
local lookupmatch=lookupcache[char]
if lookupmatch then
@@ -19749,7 +19732,7 @@ local function t_run_single(start,stop,font,attr,lookupcache)
end
end
local function k_run_single(sub,injection,last,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
- local a=getattr(sub,0)
+ local a=attr and getattr(sub,0)
if not a or (a==attr) then
for n in traverse_nodes(sub) do
if n==last then
@@ -19780,7 +19763,7 @@ local function c_run_multiple(head,font,attr,steps,nofsteps,dataset,sequence,rlm
while start do
local char=ischar(start,font)
if char then
- local a=getattr(start,0)
+ local a=attr and getattr(start,0)
if not a or (a==attr) then
for i=1,nofsteps do
local step=steps[i]
@@ -19821,7 +19804,7 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps)
while start~=stop do
local char=ischar(start,font)
if char then
- local a=getattr(start,0)
+ local a=attr and getattr(start,0)
if not a or (a==attr) then
for i=1,nofsteps do
local step=steps[i]
@@ -19862,7 +19845,7 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps)
end
end
local function k_run_multiple(sub,injection,last,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
- local a=getattr(sub,0)
+ local a=attr and getattr(sub,0)
if not a or (a==attr) then
for n in traverse_nodes(sub) do
if n==last then
@@ -19944,6 +19927,9 @@ local function featuresprocessor(head,font,attr)
nesting=nesting-1
return head,false
end
+ if attr==0 then
+ attr=false
+ end
head=tonut(head)
if trace_steps then
checkstep(head)
@@ -19981,7 +19967,7 @@ local function featuresprocessor(head,font,attr)
while start do
local char=ischar(start,font)
if char then
- local a=getattr(start,0)
+ local a=attr and getattr(start,0)
if not a or (a==attr) then
for i=1,nofsteps do
local step=steps[i]
@@ -20022,7 +20008,7 @@ local function featuresprocessor(head,font,attr)
while start do
local char,id=ischar(start,font)
if char then
- local a=getattr(start,0)
+ local a=attr and getattr(start,0)
if a then
a=(a==attr) and (not attribute or getprop(start,a_state)==attribute)
else
@@ -20072,7 +20058,7 @@ local function featuresprocessor(head,font,attr)
while start do
local char,id=ischar(start,font)
if char then
- local a=getattr(start,0)
+ local a=attr and getattr(start,0)
if a then
a=(a==attr) and (not attribute or getprop(start,a_state)==attribute)
else
@@ -20297,8 +20283,6 @@ fonts=fonts or {}
fonts.analyzers=fonts.analyzers or {}
fonts.analyzers.methods=fonts.analyzers.methods or { node={ otf={} } }
local otf=fonts.handlers.otf
-local nodecodes=nodes.nodecodes
-local glyph_code=nodecodes.glyph
local handlers=otf.handlers
local methods=fonts.analyzers.methods
local otffeatures=fonts.constructors.newfeatures("otf")
@@ -22272,6 +22256,7 @@ 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
@@ -22324,16 +22309,16 @@ do
local function loadpfbvector(filename)
local data=io.loaddata(resolvers.findfile(filename))
if not data then
- print("no data",filename)
+ report_pfb("no data in %a",filename)
return
end
- if not find(data,"!PS%-AdobeFont%-") then
- print("no font",filename)
+ if not (find(data,"!PS%-AdobeFont%-") or find(data,"%%!FontType1")) then
+ report_pfb("no font in %a",filename)
return
end
local ascii,binary=match(data,"(.*)eexec%s+......(.*)")
if not binary then
- print("no binary",filename)
+ report_pfb("no binary data in %a",filename)
return
end
binary=decrypt(binary,4)
@@ -22342,7 +22327,7 @@ do
vector[0]=table.remove(vector,1)
end
if not vector then
- print("no vector",filename)
+ report_pfb("no vector in %a",filename)
return
end
return vector
@@ -22367,16 +22352,18 @@ do
end
end
end
-local spacing=patterns.whitespace
+local spacer=patterns.spacer
+local whitespace=patterns.whitespace
local lineend=patterns.newline
+local spacing=spacer^0
local number=spacing*S("+-")^-1*(R("09")+S("."))^1/tonumber
-local name=spacing*C((1-spacing)^1)
-local words=spacing*(1-lineend)^1/strip
+local name=spacing*C((1-whitespace)^1)
+local words=spacing*((1-lineend)^1/strip)
local rest=(1-lineend)^0
local fontdata=Carg(1)
local semicolon=spacing*P(";")
-local plus=P("plus")*number
-local minus=P("minus")*number
+local plus=spacing*P("plus")*number
+local minus=spacing*P("minus")*number
local function addkernpair(data,one,two,value)
local chr=data.characters[one]
if chr then
@@ -22461,6 +22448,7 @@ local p_parameters=P(false)+fontdata*((P("FontName")+P("FullName")+P("FamilyName
+(fontdata*C("AXISHEIGHT")*number*rest)/set_1
)
local fullparser=(P("StartFontMetrics")*fontdata*name/start )*(p_charmetrics+p_kernpairs+p_parameters+(1-P("EndFontMetrics")) )^0*(P("EndFontMetrics")/stop )
+local fullparser=(P("StartFontMetrics")*fontdata*name/start )*(p_charmetrics+p_kernpairs+p_parameters+(1-P("EndFontMetrics")) )^0*(P("EndFontMetrics")/stop )
local infoparser=(P("StartFontMetrics")*fontdata*name/start )*(p_parameters+(1-P("EndFontMetrics")) )^0*(P("EndFontMetrics")/stop )
local function read(filename,parser)
local afmblob=io.loaddata(filename)
@@ -23195,7 +23183,8 @@ local function check_afm(specification,fullname)
end
end
function readers.afm(specification,method)
- local fullname,tfmdata=specification.filename or "",nil
+ local fullname=specification.filename or ""
+ local tfmdata=nil
if fullname=="" then
local forced=specification.forced or ""
if forced~="" then
@@ -23223,8 +23212,17 @@ function readers.pfb(specification,method)
if trace_defining then
report_afm("using afm reader for %a",original)
end
- specification.specification=file.replacesuffix(original,"afm")
specification.forced="afm"
+ local function swap(name)
+ local value=specification[swap]
+ if value then
+ specification[swap]=gsub("%.pfb",".afm",1)
+ end
+ end
+ swap("filename")
+ swap("fullname")
+ swap("forcedname")
+ swap("specification")
return readers.afm(specification,method)
end
@@ -24092,7 +24090,6 @@ local fonts=fonts
local nodes=nodes
local nuts=nodes.nuts
local traverse_id=nuts.traverse_id
-local remove_node=nuts.remove
local free_node=nuts.free
local glyph_code=nodes.nodecodes.glyph
local disc_code=nodes.nodecodes.disc
--
cgit v1.2.3
From e62c662512440af0ebc4ce1f4fe81a51fc4888a3 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Wed, 25 May 2016 07:39:53 +0200
Subject: [fontloader] import fix by Hans for crashes with ancient Linotype
Palatino files
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The crash happens with these broken files MS used to ship:
beef66370e7124eb683514ad9ad07576 palabi.ttf
975972a205fd91a532d1b7433281af70 palab.ttf
be4590eba976dace111b6686f6dade52 palai.ttf
96261bb90c9babbf8042ce7f43200d65 pala.ttf
on account of a broken rule in the “s_s_l” lookup. The change removes
the entire lookup in this case since otherwise the rest of the font
behaves *very* strange.
---
src/fontloader/misc/fontloader-font-dsp.lua | 65 +++++++++++++++++------------
1 file changed, 39 insertions(+), 26 deletions(-)
diff --git a/src/fontloader/misc/fontloader-font-dsp.lua b/src/fontloader/misc/fontloader-font-dsp.lua
index e35d6da..e265f48 100644
--- a/src/fontloader/misc/fontloader-font-dsp.lua
+++ b/src/fontloader/misc/fontloader-font-dsp.lua
@@ -1598,6 +1598,14 @@ do
local reported = { }
+ local function report_issue(i,what,sequence,kind)
+ local name = sequence.name
+ if not reported[name] then
+ report("rule %i in %s lookup %a has %s lookups",i,what,name,kind)
+ reported[name] = true
+ end
+ end
+
for i=lastsequence+1,nofsequences do
local sequence = sequences[i]
local steps = sequence.steps
@@ -1609,18 +1617,10 @@ do
local rule = rules[i]
local rlookups = rule.lookups
if not rlookups then
- local name = sequence.name
- if not reported[name] then
- report("rule %i in %s lookup %a has %s lookups",i,what,name,"no")
- reported[name] = true
- end
+ report_issue(i,what,sequence,"no")
elseif not next(rlookups) then
- local name = sequence.name
- if not reported[name] then
- -- can be ok as it aborts a chain sequence
- report("rule %i in %s lookup %a has %s lookups",i,what,name,"empty")
- reported[name] = true
- end
+ -- can be ok as it aborts a chain sequence
+ report_issue(i,what,sequence,"empty")
rule.lookups = nil
else
for index, lookupid in sortedhash(rlookups) do -- nicer
@@ -1630,21 +1630,34 @@ do
-- as in another one
nofsublookups = nofsublookups + 1
-- report("registering %i as sublookup %i",lookupid,nofsublookups)
- local d = lookups[lookupid].done
- h = {
- index = nofsublookups, -- handy for tracing
- name = f_lookupname(lookupprefix,"d",lookupid+lookupidoffset),
- derived = true, -- handy for tracing
- steps = d.steps,
- nofsteps = d.nofsteps,
- type = d.lookuptype,
- markclass = d.markclass or nil,
- flags = d.flags,
- -- chain = d.chain,
- }
- sublookuplist[nofsublookups] = h
- sublookuphash[lookupid] = nofsublookups
- sublookupcheck[lookupid] = 1
+ local lookup = lookups[lookupid]
+ if lookup then
+ local d = lookup.done
+ if d then
+ h = {
+ index = nofsublookups, -- handy for tracing
+ name = f_lookupname(lookupprefix,"d",lookupid+lookupidoffset),
+ derived = true, -- handy for tracing
+ steps = d.steps,
+ nofsteps = d.nofsteps,
+ type = d.lookuptype,
+ markclass = d.markclass or nil,
+ flags = d.flags,
+ -- chain = d.chain,
+ }
+ sublookuplist[nofsublookups] = h
+ sublookuphash[lookupid] = nofsublookups
+ sublookupcheck[lookupid] = 1
+ else
+ report_issue(i,what,sequence,"missing")
+ rule.lookups = nil
+ break
+ end
+ else
+ report_issue(i,what,sequence,"bad")
+ rule.lookups = nil
+ break
+ end
else
sublookupcheck[lookupid] = sublookupcheck[lookupid] + 1
end
--
cgit v1.2.3
From 67ad1263d0328fc74928a9a1d06ea9aa0ee9a116 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Thu, 26 May 2016 13:40:58 +0200
Subject: [db] ditch fontforge compatibility code
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Remove all the FF stuff and the config option. The transition is
complete, no need to keep these things around any longer.
Since we won’t be going back to the FF loader we might as well dispose
of the junk identifiers and the translation layer as well.
---
doc/luaotfload.conf.rst | 6 +-
src/luaotfload-configuration.lua | 10 +-
src/luaotfload-database.lua | 295 +++++++++++++++------------------------
3 files changed, 119 insertions(+), 192 deletions(-)
diff --git a/doc/luaotfload.conf.rst b/doc/luaotfload.conf.rst
index 7b7f342..16f055b 100644
--- a/doc/luaotfload.conf.rst
+++ b/doc/luaotfload.conf.rst
@@ -188,10 +188,8 @@ If ``update-live`` is set, Luaotfload will reload the database if it
cannot find a requested font. Those who prefer to update manually using
**luaotfload-tool** should unset this flag.
-The option ``use-fontforge`` switches name scanning back to the old
-method that relies on the builtin ``fontloader`` library. This is
-interesting for reference until the Fontforge code will be removed
-eventually.
+The option ``use-fontforge`` had a meaning during the transition to the
+Lua-only Opentype reader. At present it is ignored.
Section ``default-features``
-----------------------------------------------------------------------
diff --git a/src/luaotfload-configuration.lua b/src/luaotfload-configuration.lua
index 8cdebe0..3ac5c1e 100644
--- a/src/luaotfload-configuration.lua
+++ b/src/luaotfload-configuration.lua
@@ -387,17 +387,9 @@ local set_fontforge = function ()
end
local use_ff = config.luaotfload.db.use_fontforge
if use_ff == true then
- if not _G.fontloader then
logreport ("both", 0, "db",
- "Fontforge loader was requested but the fontloader \z
- library is missing.")
- return false
+ "Fontforge loader was requested but not supported anymore.")
end
- logreport ("log", 0, "db", "Loading font data with FontForge.")
- names.use_fontforge (true)
- else
- logreport ("log", 4, "db", "Loading font data with the Lua loader.")
- names.use_fontforge (false)
end
return true
end
diff --git a/src/luaotfload-database.lua b/src/luaotfload-database.lua
index 7434b72..96329f8 100644
--- a/src/luaotfload-database.lua
+++ b/src/luaotfload-database.lua
@@ -132,11 +132,6 @@ local fontshandlers = fonts.handlers or { }
local otfhandler = fonts.handlers.otf or { }
fonts.handlers = fontshandlers
-local read_font_file = otfhandler.readers.loadfont
-local read_font_info = read_font_file
-local close_font_file = function () end
-local get_english_names
-
local gzipload = gzip.load
local gzipsave = gzip.save
local iolines = io.lines
@@ -354,25 +349,25 @@ This is a sketch of the luaotfload db:
full : (int, string) hash; // idx -> full path
}
and fontentry = { // finalized by collect_families()
- basename : string; // file name without path "foo.otf"
- conflicts : { barename : int; basename : int }; // filename conflict with font at index; happens with subfonts
- familyname : string; // sanitized name of the font family the font belongs to, usually from the names table
- fontname : string; // sanitized name of the font
- format : string; // "otf" | "ttf" | "afm" (* | "pfb" *)
- fullname : string; // sanitized full name of the font including style modifiers
- fullpath : string; // path to font in filesystem
- index : int; // index in the mappings table
- italicangle : float; // italic angle; non-zero with oblique faces
- location : string; // "texmf" | "system" | "local"
- metafamily : string; // alternative family identifier if appropriate, sanitized
- plainname : string; // unsanitized font name
- prefmodifiers : string; // sanitized preferred subfamily (names table 14)
- psname : string; // PostScript name
- size : (false | float * float * float); // if available, size info from the size table converted from decipoints
- subfamily : string; // sanitized subfamily (names table 2)
- subfont : (int | bool); // integer if font is part of a TrueType collection ("ttc")
- version : string; // font version string
- weight : int; // usWeightClass
+ basename : string; // file name without path "foo.otf"
+ conflicts : { barename : int; basename : int }; // filename conflict with font at index; happens with subfonts
+ familyname : string; // sanitized name of the font family the font belongs to, usually from the names table
+ fontname : string; // sanitized name of the font
+ format : string; // "otf" | "ttf" | "afm" (* | "pfb" *)
+ fullname : string; // sanitized full name of the font including style modifiers
+ fullpath : string; // path to font in filesystem
+ index : int; // index in the mappings table
+ italicangle : float; // italic angle; non-zero with oblique faces
+ location : string; // "texmf" | "system" | "local"
+ metafamily : string; // alternative family identifier if appropriate, sanitized
+ plainname : string; // unsanitized font name
+ typographicsubfamily : string; // sanitized preferred subfamily (names table 14)
+ psname : string; // PostScript name
+ size : (false | float * float * float); // if available, size info from the size table converted from decipoints
+ subfamily : string; // sanitized subfamily (names table 2)
+ subfont : (int | bool); // integer if font is part of a TrueType collection ("ttc")
+ version : string; // font version string
+ weight : int; // usWeightClass
}
and filestatus = (string, // fullname
{ index : int list; // pointer into mappings
@@ -1015,7 +1010,7 @@ local lookup_fontname = function (specification, name, style)
style = style_category [style]
for i = 1, #mappings do
local face = mappings [i]
- local prefmodifiers = face.prefmodifiers
+ local typographicsubfamily = face.typographicsubfamily
local subfamily = face.subfamily
if face.fontname == name
or face.fullname == name
@@ -1023,17 +1018,17 @@ local lookup_fontname = function (specification, name, style)
then
return face.basename, face.subfont
elseif face.familyname == name then
- if prefmodifiers == style
+ if typographicsubfamily == style
or subfamily == style
then
fallback = face
- elseif regular_synonym [prefmodifiers]
+ elseif regular_synonym [typographicsubfamily]
or regular_synonym [subfamily]
then
lastresort = face
end
elseif face.metafamily == name
- and ( regular_synonym [prefmodifiers]
+ and ( regular_synonym [typographicsubfamily]
or regular_synonym [subfamily])
then
lastresort = face
@@ -1081,12 +1076,12 @@ end
size should that be? Xetex appears to pick the “normal” (unmarked)
size: with Adobe fonts this would be the one that is neither
“caption” nor “subhead” nor “display” &c ... For fonts by Adobe this
- seems to be the one that does not receive a “prefmodifiers” field.
- (IOW Adobe uses the “prefmodifiers” field to encode the design size
- in more or less human readable format.) However, this is not true
- of LM and EB Garamond. As this matters only where there are
- multiple design sizes to a given font/style combination, we put a
- workaround in place that chooses that unmarked version.
+ seems to be the one that does not receive a “typographicsubfamily”
+ field. (IOW Adobe uses the “typographicsubfamily” field to encode
+ the design size in more or less human readable format.) However,
+ this is not true of LM and EB Garamond. As this matters only where
+ there are multiple design sizes to a given font/style combination,
+ we put a workaround in place that chooses that unmarked version.
The first return value of “lookup_font_name” is the file name of the
requested font (string). It can be passed to the fullname resolver
@@ -1303,8 +1298,18 @@ find_closest = function (name, limit)
return false
end --- find_closest()
+local read_font_file = function (filename, subfont)
+ return otfhandler.readers.getinfo (filename,
+ { subfont = subfont
+ , details = false
+ , platformnames = true
+ , rawfamilynames = true
+ })
+end
+
local load_font_file = function (filename, subfont)
- local rawfont, _msg = read_font_file (filename, subfont, true)
+ local rawfont, _msg = read_font_file (filename, subfont)
+
if not rawfont then
logreport ("log", 1, "db", "ERROR: failed to open %s.", filename)
return
@@ -1335,29 +1340,6 @@ local get_size_info = function (rawinfo)
return false
end
---[[doc--
- get_english_names_from_ff -- For legacy Fontforge-style names
- tables. Extracted from the actual names table, not the font item
- itself.
---doc]]--
-
-local get_english_names_from_ff = function (metadata)
- local names = metadata.names
- if names then
- for _, raw_namedata in next, names do
- if raw_namedata.lang == "English (US)" then
- return raw_namedata.names
- end
- end
- end
-
- -- no (English) names table, probably a broken font
- logreport ("both", 3, "db",
- "%s: missing or broken English names table.", basename)
- return { fontname = metadata.fontname,
- fullname = metadata.fullname, }
-end
-
--[[doc--
map_enlish_names -- Names-table for Lua fontloader objects. This
may vanish eventually once we ditch Fontforge completely. Only
@@ -1365,17 +1347,7 @@ end
stick to that part.
--doc]]--
-local names_items = {
- compatfull = "compatiblefullname",
- fullname = "fullname",
- postscriptname = "postscriptname",
- preffamily = "typographicfamily",
- prefmodifiers = "typographicsubfamily",
- family = "family",
- subfamily = "subfamily",
-}
-
-local map_english_names = function (metadata)
+local get_english_names = function (metadata)
local namesource
local platformnames = metadata.platformnames
--[[--
@@ -1411,16 +1383,9 @@ local map_english_names = function (metadata)
--namesource = platformnames.macintosh or platformnames.windows
namesource = platformnames.windows or platformnames.macintosh
end
- namesource = namesource or metadata
- local nameinfo = { }
- for ours, theirs in next, names_items do
- nameinfo [ours] = namesource [theirs]
- end
- return nameinfo
+ return namesource or metadata
end
-get_english_names = map_english_names
-
--[[--
In case of broken PS names we set some dummies.
@@ -1461,46 +1426,46 @@ local organize_namedata = function (rawinfo,
nametable,
basename,
info)
- local default_name = nametable.compatfull
+ local default_name = nametable.compatiblefullname
or nametable.fullname
or nametable.postscriptname
or rawinfo.fullname
or rawinfo.fontname
or info.fullname
or info.fontname
- local default_family = nametable.preffamily
+ local default_family = nametable.typographicfamily
or nametable.family
or rawinfo.familyname
or info.familyname
--- local default_modifier = nametable.prefmodifiers
+-- local default_modifier = nametable.typographicsubfamily
-- or nametable.subfamily
local fontnames = {
--- see
--- https://developer.apple.com/fonts/TTRefMan/RM06/Chap6name.html
--- http://www.microsoft.com/typography/OTSPEC/name.htm#NameIDs
english = {
- --- where a “compatfull” field is given, the value of “fullname” is
- --- either identical or differs by separating the style
- --- with a hyphen and omitting spaces. (According to the
- --- spec, “compatfull” is “Macintosh only”.)
- --- Of the three “fullname” fields, this one appears to be the one
- --- with the entire name given in a legible,
- --- non-abbreviated fashion, for most fonts at any rate.
- --- However, in some fonts (e.g. CMU) all three fields are
- --- identical.
- fullname = --[[ 18 ]] nametable.compatfull
+ --- where a “compatiblefullname” field is given, the value
+ --- of “fullname” is either identical or differs by
+ --- separating the style with a hyphen and omitting spaces.
+ --- (According to the spec, “compatiblefullname” is
+ --- “Macintosh only”.) Of the three “fullname” fields, this
+ --- one appears to be the one with the entire name given in
+ --- a legible, non-abbreviated fashion, for most fonts at
+ --- any rate. However, in some fonts (e.g. CMU) all three
+ --- fields are identical.
+ fullname = --[[ 18 ]] nametable.compatiblefullname
or --[[ 4 ]] nametable.fullname
or default_name,
--- we keep both the “preferred family” and the “family”
--- values around since both are valid but can turn out
--- quite differently, e.g. with Latin Modern:
- --- preffamily: “Latin Modern Sans”,
+ --- typographicfamily: “Latin Modern Sans”,
--- family: “LM Sans 10”
- preffamily = --[[ 16 ]] nametable.preffamilyname,
- family = --[[ 1 ]] nametable.family or default_family,
- prefmodifiers = --[[ 17 ]] nametable.prefmodifiers,
- subfamily = --[[ 2 ]] nametable.subfamily or rawinfo.subfamilyname,
- psname = --[[ 6 ]] nametable.postscriptname,
+ family = --[[ 1 ]] nametable.family or default_family,
+ subfamily = --[[ 2 ]] nametable.subfamily or rawinfo.subfamilyname,
+ psname = --[[ 6 ]] nametable.postscriptname,
+ typographicfamily = --[[ 16 ]] nametable.typographicfamily,
+ typographicsubfamily = --[[ 17 ]] nametable.typographicsubfamily,
},
metadata = {
@@ -1595,7 +1560,6 @@ ot_fullinfo = function (filename,
style = style,
version = rawinfo.version,
}
- close_font_file (metadata) --> FF only
return res
end
@@ -1622,12 +1586,12 @@ t1_fullinfo = function (filename, _subfont, location, basename, format)
local weight
sanitized = sanitize_fontnames ({
- fontname = fontname,
- psname = fullname,
- metafamily = familyname,
- familyname = familyname,
- weight = metadata.weight, --- string identifier
- prefmodifiers = style,
+ fontname = fontname,
+ psname = fullname,
+ metafamily = familyname,
+ familyname = familyname,
+ weight = metadata.weight, --- string identifier
+ typographicsubfamily = style,
})
weight = sanitized.weight
@@ -1641,21 +1605,21 @@ t1_fullinfo = function (filename, _subfont, location, basename, format)
end
return {
- basename = basename,
- fullpath = filename,
- subfont = false,
- location = location or "system",
- format = format,
- fullname = sanitized.fullname,
- fontname = sanitized.fontname,
- familyname = sanitized.familyname,
- plainname = fullname,
- psname = sanitized.fontname,
- version = metadata.version,
- size = false,
- prefmodifiers = style ~= "" and style or weight,
- weight = metadata.pfminfo and pfminfo.weight or 400,
- italicangle = italicangle,
+ basename = basename,
+ fullpath = filename,
+ subfont = false,
+ location = location or "system",
+ format = format,
+ fullname = sanitized.fullname,
+ fontname = sanitized.fontname,
+ familyname = sanitized.familyname,
+ plainname = fullname,
+ psname = sanitized.fontname,
+ version = metadata.version,
+ size = false,
+ typographicsubfamily = style ~= "" and style or weight,
+ weight = metadata.pfminfo and pfminfo.weight or 400,
+ italicangle = italicangle,
}
end
@@ -2601,11 +2565,10 @@ do
return false
end
- pick_style = function (prefmodifiers,
- subfamily)
+ pick_style = function (typographicsubfamily, subfamily)
local style
- if prefmodifiers then
- style = choose_exact (prefmodifiers)
+ if typographicsubfamily then
+ style = choose_exact (typographicsubfamily)
elseif subfamily then
style = choose_exact (subfamily)
end
@@ -2635,7 +2598,7 @@ do
--- we use only exact matches here since there are constructs
--- like “regularitalic” (Cabin, Bodoni Old Fashion)
- check_regular = function (prefmodifiers,
+ check_regular = function (typographicsubfamily,
subfamily,
italicangle,
weight,
@@ -2643,7 +2606,7 @@ do
local plausible_weight = false
--[[--
This filters out undesirable candidates that specify their
- prefmodifiers or subfamily as “regular” but are actually of
+ typographicsubfamily or subfamily as “regular” but are actually of
“semibold” or other weight—another drawback of the
oversimplifying classification into only three styles (r, i,
b, bi).
@@ -2655,8 +2618,8 @@ do
end
if plausible_weight then
- if prefmodifiers and regular_synonym [prefmodifiers]
- or subfamily and regular_synonym [subfamily]
+ if typographicsubfamily and regular_synonym [typographicsubfamily]
+ or subfamily and regular_synonym [subfamily]
then
return "r"
end
@@ -2681,13 +2644,13 @@ local pull_values = function (entry)
entry.subfont = file.subfont
--- pull name info ...
- entry.psname = english.psname
- entry.fontname = info.fontname or metadata.fontname
- entry.fullname = english.fullname or info.fullname
- entry.prefmodifiers = english.prefmodifiers
- entry.familyname = metadata.familyname or english.preffamily or english.family
- entry.plainname = names.fullname
- entry.subfamily = english.subfamily
+ entry.psname = english.psname
+ entry.fontname = info.fontname or metadata.fontname
+ entry.fullname = english.fullname or info.fullname
+ entry.typographicsubfamily = english.typographicsubfamily
+ entry.familyname = metadata.familyname or english.typographicfamily or english.family
+ entry.plainname = names.fullname
+ entry.subfamily = english.subfamily
--- pull style info ...
entry.italicangle = style.italicangle
@@ -2747,20 +2710,17 @@ local collect_families = function (mappings)
pull_values (entry)
end
- local subtable = get_subtable (families, entry)
-
- local familyname = entry.familyname
- local prefmodifiers = entry.prefmodifiers
- local subfamily = entry.subfamily
-
- local weight = entry.weight
- local pfmweight = entry.pfmweight
- local italicangle = entry.italicangle
-
- local modifier = pick_style (prefmodifiers, subfamily)
+ local subtable = get_subtable (families, entry)
+ local familyname = entry.familyname
+ local typographicsubfamily = entry.typographicsubfamily
+ local subfamily = entry.subfamily
+ local weight = entry.weight
+ local pfmweight = entry.pfmweight
+ local italicangle = entry.italicangle
+ local modifier = pick_style (typographicsubfamily, subfamily)
if not modifier then --- regular, exact only
- modifier = check_regular (prefmodifiers,
+ modifier = check_regular (typographicsubfamily,
subfamily,
italicangle,
weight,
@@ -2999,7 +2959,7 @@ local collect_statistics = function (mappings)
local sum_dsnsize, n_dsnsize = 0, 0
local fullname, family, families = { }, { }, { }
- local subfamily, prefmodifiers = { }, { }
+ local subfamily, typographicsubfamily = { }, { }
local addtohash = function (hash, item)
if item then
@@ -3055,10 +3015,10 @@ local collect_statistics = function (mappings)
local names = entry.names.sanitized
local englishnames = names.english
- addtohash (fullname, englishnames.fullname)
- addtohash (family, englishnames.family)
- addtohash (subfamily, englishnames.subfamily)
- addtohash (prefmodifiers, englishnames.prefmodifiers)
+ addtohash (fullname, englishnames.fullname)
+ addtohash (family, englishnames.family)
+ addtohash (subfamily, englishnames.subfamily)
+ addtohash (typographicsubfamily, englishnames.typographicsubfamily)
addtoset (families, englishnames.family, englishnames.fullname)
@@ -3129,9 +3089,9 @@ local collect_statistics = function (mappings)
pprint_top (subfamily, 4)
logreport ("both", 0, "db",
- " · %d different “prefmodifiers” kinds.",
- setsize (prefmodifiers))
- pprint_top (prefmodifiers, 4)
+ " · %d different “typographicsubfamily” kinds.",
+ setsize (typographicsubfamily))
+ pprint_top (typographicsubfamily, 4)
end
@@ -3148,7 +3108,7 @@ local collect_statistics = function (mappings)
},
-- style = {
-- subfamily = subfamily,
--- prefmodifiers = prefmodifiers,
+-- typographicsubfamily = typographicsubfamily,
-- },
}
end
@@ -3505,29 +3465,6 @@ local show_cache = function ( )
return true
end
-local use_fontforge = function (val)
- if val == true then
- local fontloader = fontloader
- read_font_info = fontloader.info
- read_font_file = fontloader.open
- close_font_file = fontloader.close
- get_english_names = get_english_names_from_ff
- else
- local wrapper = function (filename, subfont)
- return otfhandler.readers.getinfo (filename,
- { subfont = subfont
- , details = false
- , platformnames = true
- , rawfamilynames = true
- })
- end
- read_font_file = wrapper
- read_font_info = wrapper
- close_font_file = function () end
- get_english_names = map_english_names
- end
-end
-
-----------------------------------------------------------------------
--- export functionality to the namespace “fonts.names”
-----------------------------------------------------------------------
@@ -3559,7 +3496,7 @@ local export = {
show_cache = show_cache,
find_closest = find_closest,
--- transitionary
- use_fontforge = use_fontforge,
+ use_fontforge = false,
}
return {
@@ -3575,7 +3512,7 @@ return {
fonts.definers = fonts.definers or { resolvers = { } }
names.blacklist = blacklist
- names.version = 2.7
+ names.version = 2.8
names.data = nil --- contains the loaded database
names.lookups = nil --- contains the lookup cache
--
cgit v1.2.3
From 9bc8a2425b2608b8a93e91042191421ad81dc956 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Tue, 31 May 2016 08:20:22 +0200
Subject: [db] fix name assignment
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Address issue #356
The DejaVu Family needs stricter handling of fallback choices so we take
the font’s avertised width into consideration. This used to be easier
with the old loader since it had some decent heuristics in place for the
more or less reliable “fontstyle_name”.
---
src/luaotfload-database.lua | 45 ++++++++++++++++++++++++++++++++++-----------
1 file changed, 34 insertions(+), 11 deletions(-)
diff --git a/src/luaotfload-database.lua b/src/luaotfload-database.lua
index 96329f8..00d14de 100644
--- a/src/luaotfload-database.lua
+++ b/src/luaotfload-database.lua
@@ -2537,6 +2537,7 @@ end
local bold_spectrum_low = 501 --- 500 is medium, 900 heavy/black
local bold_weight = 700
+local normal_width = 5
local pick_style
local pick_fallback_style
@@ -2569,13 +2570,15 @@ do
local style
if typographicsubfamily then
style = choose_exact (typographicsubfamily)
+ if style then return style end
elseif subfamily then
style = choose_exact (subfamily)
+ if style then return style end
end
- return style
+ return false
end
- pick_fallback_style = function (italicangle, weight, pfmweight)
+ pick_fallback_style = function (italicangle, pfmweight, width)
--[[--
More aggressive, but only to determine bold faces.
Note: Before you make this test more inclusive, ensure
@@ -2586,7 +2589,8 @@ do
treating weights > 500 as bold or allowing synonyms like
“heavy”, “black”.
--]]--
- if pfmweight == bold_weight then --- bold spectrum matches
+ if width == normal_width and pfmweight == bold_weight then
+ --- bold spectrum matches
if italicangle == 0 then
return "b"
end
@@ -2602,6 +2606,7 @@ do
subfamily,
italicangle,
weight,
+ width,
pfmweight)
local plausible_weight = false
--[[--
@@ -2611,17 +2616,32 @@ do
oversimplifying classification into only three styles (r, i,
b, bi).
--]]--
-
if italicangle == 0 then
- if pfmweight == 400 then plausible_weight = true
- elseif weight and regular_synonym [weight] then plausible_weight = true end
+ if pfmweight == 400 then
+ --[[--
+ Some fonts like Dejavu advertise an undistinguished
+ regular and a “condensed” version with the same
+ weight whilst also providing the style info in the
+ typographic subfamily instead of the subfamily (i. e.
+ the converse of what Adobe’s doing). The only way to
+ weed out the undesired pseudo-regular shape is to
+ peek at its advertised width (4 vs. 5).
+ --]]--
+ if width then
+ plausible_weight = width == normal_width
+ else
+ plausible_weight = true
+ end
+ elseif weight and regular_synonym [weight] then
+ plausible_weight = true
+ end
end
if plausible_weight then
- if typographicsubfamily and regular_synonym [typographicsubfamily]
- or subfamily and regular_synonym [subfamily]
- then
- return "r"
+ if subfamily then
+ if regular_synonym [subfamily] then return "r" end
+ elseif typographicsubfamily then
+ if regular_synonym [typographicsubfamily] then return "r" end
end
end
return false
@@ -2656,6 +2676,7 @@ local pull_values = function (entry)
entry.italicangle = style.italicangle
entry.size = style.size
entry.weight = style.weight
+ entry.width = style.width
entry.pfmweight = style.pfmweight
if config.luaotfload.db.strip == true then
@@ -2715,6 +2736,7 @@ local collect_families = function (mappings)
local typographicsubfamily = entry.typographicsubfamily
local subfamily = entry.subfamily
local weight = entry.weight
+ local width = entry.width
local pfmweight = entry.pfmweight
local italicangle = entry.italicangle
local modifier = pick_style (typographicsubfamily, subfamily)
@@ -2724,11 +2746,12 @@ local collect_families = function (mappings)
subfamily,
italicangle,
weight,
+ width,
pfmweight)
end
if not modifier then
- modifier = pick_fallback_style (italicangle, weight, pfmweight)
+ modifier = pick_fallback_style (italicangle, pfmweight, width)
end
if modifier then
--
cgit v1.2.3
From 1354f05f0ff1ca157d2976721b29341ba1c4598a Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Fri, 3 Jun 2016 08:19:24 +0200
Subject: [aux] remove double scaling of capheight from typoascender
Fix #358
The typographic ascender value from the metrics (Windows metrics) table
comes prescaled by the fontloader but we scaled it nevertheless. This is
not true, however, for the value in the metrics table. Fix the access
method to treat the values differently.
---
src/luaotfload-auxiliary.lua | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/src/luaotfload-auxiliary.lua b/src/luaotfload-auxiliary.lua
index e482aba..3c43eb9 100644
--- a/src/luaotfload-auxiliary.lua
+++ b/src/luaotfload-auxiliary.lua
@@ -212,15 +212,19 @@ end
local query_ascender = function (fontdata)
local parameters = fontdata.parameters if not parameters then return false end
+ local ascender = parameters.ascender
+ if ascender then
+ return ascender --- pre-scaled
+ end
+
local shared = fontdata.shared if not shared then return false end
local rawdata = shared.rawdata if not rawdata then return false end
local metadata = rawdata.metadata if not metadata then return false end
- local ascender = parameters.ascender
- or metadata.ascender if not ascender then return false end
+ ascender = metadata.ascender if not ascender then return false end
local size = parameters.size if not size then return false end
local units = lookup_units (fontdata)
if not units or units == 0 then return false end
- return ascender * size / units
+ return ascender * size / units --- scaled
end
local query_capheight = function (fontdata)
--
cgit v1.2.3
From 8218c0b56e7e175a3ed931300766950491d9e719 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Tue, 7 Jun 2016 07:51:42 +0200
Subject: [conf] fix malformed file
This was introduced with commit 67ad1263d032 during a code removal
frenzy.
Many thanks to @grizzilus for pointing that one out:
https://github.com/phi-gamma/luaotfload/commit/67ad1263d0328fc74928a9a1d06ea9aa0ee9a116#commitcomment-17726875
---
src/luaotfload-configuration.lua | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/luaotfload-configuration.lua b/src/luaotfload-configuration.lua
index 3ac5c1e..c707b63 100644
--- a/src/luaotfload-configuration.lua
+++ b/src/luaotfload-configuration.lua
@@ -389,7 +389,6 @@ local set_fontforge = function ()
if use_ff == true then
logreport ("both", 0, "db",
"Fontforge loader was requested but not supported anymore.")
- end
end
return true
end
--
cgit v1.2.3
From 68f523b6660baaabd4fee994d5be79a3a9afda37 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Tue, 7 Jun 2016 07:58:55 +0200
Subject: [db] include values of missing fields in diagnostic
---
src/luaotfload-database.lua | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/luaotfload-database.lua b/src/luaotfload-database.lua
index 00d14de..da2d5d0 100644
--- a/src/luaotfload-database.lua
+++ b/src/luaotfload-database.lua
@@ -1402,8 +1402,9 @@ local get_raw_info = function (metadata, basename)
--- we put some dummies in place like the fontloader
--- (font-otf.lua) does.
logreport ("both", 3, "db",
- "invalid names table of font %s, using dummies.",
- basename)
+ "Invalid names table of font %s, using dummies. \z
+ Reported: fontname=%q, fullname=%q.",
+ basename, fontname, fullname)
fontname = "bad-fontname-" .. basename
fullname = "bad-fullname-" .. basename
end
--
cgit v1.2.3
From 37f8c42a1b560df3f1bc1444405c772f00340f88 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Wed, 8 Jun 2016 08:23:38 +0200
Subject: [db] resolve symlinks when traversing the file system
Addresses #359 and #325
To avoid duplicate entries, paths have to be resolved before collecting
them. This necessitates loop detection of some sort, currently
implemented naively as a flat table containing the directories already
traversed.
---
src/luaotfload-database.lua | 72 ++++++++++++++++++++++++++-------------------
1 file changed, 41 insertions(+), 31 deletions(-)
diff --git a/src/luaotfload-database.lua b/src/luaotfload-database.lua
index da2d5d0..5645b63 100644
--- a/src/luaotfload-database.lua
+++ b/src/luaotfload-database.lua
@@ -2033,7 +2033,7 @@ local locate_matching_pfb = function (afmfile, dir)
end
local process_dir_tree
-process_dir_tree = function (acc, dirs)
+process_dir_tree = function (acc, dirs, done)
if not next (dirs) then --- done
return acc
end
@@ -2042,46 +2042,56 @@ process_dir_tree = function (acc, dirs)
local dir = dirs[#dirs]
dirs[#dirs] = nil
- if lfschdir (dir) then
- lfschdir (pwd)
-
- local newfiles = { }
- local blacklist = names.blacklist
- for ent in lfsdir (dir) do
- --- filter right away
- if ent ~= "." and ent ~= ".." and not blacklist[ent] then
- local fullpath = dir .. "/" .. ent
- if lfsisdir (fullpath)
- and not lpegmatch (p_blacklist, fullpath)
- then
- dirs[#dirs+1] = fullpath
- elseif lfsisfile (fullpath) then
- ent = stringlower (ent)
-
- if lpegmatch (p_font_filter, ent) then
- newfiles[#newfiles+1] = fullpath
- if filesuffix (ent) == "afm" then
- local pfbpath = locate_matching_pfb (ent, dir)
- if pfbpath then
- newfiles[#newfiles+1] = pfbpath
- end
- else
- newfiles[#newfiles+1] = fullpath
+ if not lfschdir (dir) then
+ --- Cannot cd; skip.
+ return process_dir_tree (acc, dirs, done)
+ end
+
+ dir = lfscurrentdir () --- resolve symlinks
+ lfschdir (pwd)
+ if tablecontains (done, dir) then
+ --- Already traversed. Note that it’d be unsafe to rely on the
+ --- hash part above due to Lua only processing up to 32 bytes
+ --- of string data. The lookup shouldn’t impact performance too
+ --- much but we could check the performance of alternative data
+ --- structures at some point.
+ return process_dir_tree (acc, dirs, done)
+ end
+
+ local newfiles = { }
+ local blacklist = names.blacklist
+ for ent in lfsdir (dir) do
+ --- filter right away
+ if ent ~= "." and ent ~= ".." and not blacklist[ent] then
+ local fullpath = dir .. "/" .. ent
+ if lfsisdir (fullpath)
+ and not lpegmatch (p_blacklist, fullpath)
+ then
+ dirs[#dirs+1] = fullpath
+ elseif lfsisfile (fullpath) then
+ ent = stringlower (ent)
+ if lpegmatch (p_font_filter, ent) then
+ newfiles[#newfiles+1] = fullpath
+ if filesuffix (ent) == "afm" then
+ local pfbpath = locate_matching_pfb (ent, dir)
+ if pfbpath then
+ newfiles[#newfiles+1] = pfbpath
end
+ else
+ newfiles[#newfiles+1] = fullpath
end
-
end
end
end
- return process_dir_tree (tableappend (acc, newfiles), dirs)
end
- --- cannot cd; skip
- return process_dir_tree (acc, dirs)
+ done [#done + 1] = dir
+ return process_dir_tree (tableappend (acc, newfiles), dirs, done)
end
local process_dir = function (dir)
local pwd = lfscurrentdir ()
if lfschdir (dir) then
+ dir = lfscurrentdir () --- resolve symlinks
lfschdir (pwd)
local files = { }
@@ -2114,7 +2124,7 @@ end
local find_font_files = function (root, recurse)
if lfsisdir (root) then
if recurse == true then
- return process_dir_tree ({}, { root })
+ return process_dir_tree ({}, { root }, {})
else --- kpathsea already delivered the necessary subdirs
return process_dir (root)
end
--
cgit v1.2.3
From a8cae347b3c8a3154c36444e5d38705b59e5e57e Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Fri, 10 Jun 2016 07:43:41 +0200
Subject: [fontloader] sync with Context as of 2016-05-31
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This corresponds to commit a274872832cd on the mirror repo. The changes
since then were numerous but seem to introduce a couple new files we
didn’t ask for =) Later.
---
src/fontloader/misc/fontloader-font-con.lua | 37 ++++---
src/fontloader/misc/fontloader-font-dsp.lua | 29 +++---
src/fontloader/misc/fontloader-font-otj.lua | 11 +-
src/fontloader/misc/fontloader-font-otl.lua | 2 +-
src/fontloader/runtime/fontloader-reference.lua | 127 +++++++++++++++---------
5 files changed, 128 insertions(+), 78 deletions(-)
diff --git a/src/fontloader/misc/fontloader-font-con.lua b/src/fontloader/misc/fontloader-font-con.lua
index 45ecdd6..367f807 100644
--- a/src/fontloader/misc/fontloader-font-con.lua
+++ b/src/fontloader/misc/fontloader-font-con.lua
@@ -337,6 +337,20 @@ function constructors.enhanceparameters(parameters)
}
end
+local function mathkerns(v,vdelta)
+ local k = { }
+ for i=1,#v do
+ local entry = v[i]
+ local height = entry.height
+ local kern = entry.kern
+ k[i] = {
+ height = height and vdelta*height or 0,
+ kern = kern and vdelta*kern or 0,
+ }
+ end
+ return k
+end
+
function constructors.scale(tfmdata,specification)
local target = { } -- the new table
--
@@ -748,22 +762,15 @@ function constructors.scale(tfmdata,specification)
chr.top_accent = vdelta*va
end
if stackmath then
- local mk = character.mathkerns -- not in math ?
+ local mk = character.mathkerns
if mk then
- local kerns = { }
- local v = mk.top_right if v then local k = { } for i=1,#v do local vi = v[i]
- k[i] = { height = vdelta*vi.height, kern = vdelta*vi.kern }
- end kerns.top_right = k end
- local v = mk.top_left if v then local k = { } for i=1,#v do local vi = v[i]
- k[i] = { height = vdelta*vi.height, kern = vdelta*vi.kern }
- end kerns.top_left = k end
- local v = mk.bottom_left if v then local k = { } for i=1,#v do local vi = v[i]
- k[i] = { height = vdelta*vi.height, kern = vdelta*vi.kern }
- end kerns.bottom_left = k end
- local v = mk.bottom_right if v then local k = { } for i=1,#v do local vi = v[i]
- k[i] = { height = vdelta*vi.height, kern = vdelta*vi.kern }
- end kerns.bottom_right = k end
- chr.mathkern = kerns -- singular -> should be patched in luatex !
+ local tr, tl, br, bl = mk.topright, mk.topleft, mk.bottomright, mk.bottomleft
+ chr.mathkern = { -- singular -> should be patched in luatex !
+ top_right = tr and mathkerns(tr,vdelta) or nil,
+ top_left = tl and mathkerns(tl,vdelta) or nil,
+ bottom_right = br and mathkerns(br,vdelta) or nil,
+ bottom_left = bl and mathkerns(bl,vdelta) or nil,
+ }
end
end
if hasitalics then
diff --git a/src/fontloader/misc/fontloader-font-dsp.lua b/src/fontloader/misc/fontloader-font-dsp.lua
index e265f48..37ae166 100644
--- a/src/fontloader/misc/fontloader-font-dsp.lua
+++ b/src/fontloader/misc/fontloader-font-dsp.lua
@@ -715,6 +715,8 @@ function gsubhandlers.single(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofg
end
end
+-- we see coverage format 0x300 in some old ms fonts
+
local function sethandler(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,what)
local tableoffset = lookupoffset + offset
setposition(f,tableoffset)
@@ -1628,12 +1630,12 @@ do
if not h then
-- here we have a lookup that is used independent as well
-- as in another one
- nofsublookups = nofsublookups + 1
- -- report("registering %i as sublookup %i",lookupid,nofsublookups)
local lookup = lookups[lookupid]
if lookup then
local d = lookup.done
if d then
+ nofsublookups = nofsublookups + 1
+ -- report("registering %i as sublookup %i",lookupid,nofsublookups)
h = {
index = nofsublookups, -- handy for tracing
name = f_lookupname(lookupprefix,"d",lookupid+lookupidoffset),
@@ -2027,16 +2029,15 @@ local function readmathglyphinfo(f,fontdata,offset)
local function get(offset)
setposition(f,kernoffset+offset)
local n = readushort(f)
- if n > 0 then
+ if n == 0 then
+ local k = readmathvalue(f)
+ if k == 0 then
+ -- no need for it (happens sometimes)
+ else
+ return { { kern = k } }
+ end
+ else
local l = { }
- -- for i=1,n do
- -- l[i] = { readushort(f), 0 } -- height, kern
- -- skipshort(f)
- -- end
- -- for i=1,n do
- -- l[i][2] = readushort(f)
- -- skipshort(f)
- -- end
for i=1,n do
l[i] = { height = readmathvalue(f) }
end
@@ -2071,10 +2072,10 @@ local function readmathglyphinfo(f,fontdata,offset)
if next(kernset) then
local glyph = glyphs[coverage[i]]
local math = glyph.math
- if not math then
- glyph.math = { kerns = kernset }
- else
+ if math then
math.kerns = kernset
+ else
+ glyph.math = { kerns = kernset }
end
end
end
diff --git a/src/fontloader/misc/fontloader-font-otj.lua b/src/fontloader/misc/fontloader-font-otj.lua
index 61baf93..0db30c6 100644
--- a/src/fontloader/misc/fontloader-font-otj.lua
+++ b/src/fontloader/misc/fontloader-font-otj.lua
@@ -753,7 +753,7 @@ local function inject_pairs_only(head,where)
end
local leftkern = i.leftkern
if leftkern and leftkern ~= 0 then
- insert_node_before(head,current,newkern(leftkern))
+ head = insert_node_before(head,current,newkern(leftkern))
end
local rightkern = i.rightkern
if rightkern and rightkern ~= 0 then
@@ -1521,10 +1521,19 @@ function injections.handler(head,where)
head = injectspaces(head)
end
if nofregisteredmarks > 0 or nofregisteredcursives > 0 then
+ if trace_injections then
+ report_injections("injection variant %a","everything")
+ end
return inject_everything(head,where)
elseif nofregisteredpairs > 0 then
+ if trace_injections then
+ report_injections("injection variant %a","pairs")
+ end
return inject_pairs_only(head,where)
elseif nofregisteredkerns > 0 then
+ if trace_injections then
+ report_injections("injection variant %a","kerns")
+ end
return inject_kerns_only(head,where)
else
return head, false
diff --git a/src/fontloader/misc/fontloader-font-otl.lua b/src/fontloader/misc/fontloader-font-otl.lua
index 304b6b9..73e3df9 100644
--- a/src/fontloader/misc/fontloader-font-otl.lua
+++ b/src/fontloader/misc/fontloader-font-otl.lua
@@ -53,7 +53,7 @@ local report_otf = logs.reporter("fonts","otf loading")
local fonts = fonts
local otf = fonts.handlers.otf
-otf.version = 3.020 -- beware: also sync font-mis.lua and in mtx-fonts
+otf.version = 3.021 -- beware: also sync font-mis.lua and in mtx-fonts
otf.cache = containers.define("fonts", "otl", otf.version, true)
local otfreaders = otf.readers
diff --git a/src/fontloader/runtime/fontloader-reference.lua b/src/fontloader/runtime/fontloader-reference.lua
index 9e7d889..4d1ef83 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 : 05/22/16 15:18:33
+-- merge date : 05/31/16 09:02:55
do -- begin closure to overcome local limits and interference
@@ -5286,6 +5286,19 @@ function constructors.enhanceparameters(parameters)
extra=extra,
}
end
+local function mathkerns(v,vdelta)
+ local k={}
+ for i=1,#v do
+ local entry=v[i]
+ local height=entry.height
+ local kern=entry.kern
+ k[i]={
+ height=height and vdelta*height or 0,
+ kern=kern and vdelta*kern or 0,
+ }
+ end
+ return k
+end
function constructors.scale(tfmdata,specification)
local target={}
if tonumber(specification) then
@@ -5624,22 +5637,15 @@ function constructors.scale(tfmdata,specification)
chr.top_accent=vdelta*va
end
if stackmath then
- local mk=character.mathkerns
+ local mk=character.mathkerns
if mk then
- local kerns={}
- local v=mk.top_right if v then local k={} for i=1,#v do local vi=v[i]
- k[i]={ height=vdelta*vi.height,kern=vdelta*vi.kern }
- end kerns.top_right=k end
- local v=mk.top_left if v then local k={} for i=1,#v do local vi=v[i]
- k[i]={ height=vdelta*vi.height,kern=vdelta*vi.kern }
- end kerns.top_left=k end
- local v=mk.bottom_left if v then local k={} for i=1,#v do local vi=v[i]
- k[i]={ height=vdelta*vi.height,kern=vdelta*vi.kern }
- end kerns.bottom_left=k end
- local v=mk.bottom_right if v then local k={} for i=1,#v do local vi=v[i]
- k[i]={ height=vdelta*vi.height,kern=vdelta*vi.kern }
- end kerns.bottom_right=k end
- chr.mathkern=kerns
+ local tr,tl,br,bl=mk.topright,mk.topleft,mk.bottomright,mk.bottomleft
+ chr.mathkern={
+ top_right=tr and mathkerns(tr,vdelta) or nil,
+ top_left=tl and mathkerns(tl,vdelta) or nil,
+ bottom_right=br and mathkerns(br,vdelta) or nil,
+ bottom_left=bl and mathkerns(bl,vdelta) or nil,
+ }
end
end
if hasitalics then
@@ -11953,6 +11959,13 @@ do
end
end
local reported={}
+ local function report_issue(i,what,sequence,kind)
+ local name=sequence.name
+ if not reported[name] then
+ report("rule %i in %s lookup %a has %s lookups",i,what,name,kind)
+ reported[name]=true
+ end
+ end
for i=lastsequence+1,nofsequences do
local sequence=sequences[i]
local steps=sequence.steps
@@ -11964,37 +11977,42 @@ do
local rule=rules[i]
local rlookups=rule.lookups
if not rlookups then
- local name=sequence.name
- if not reported[name] then
- report("rule %i in %s lookup %a has %s lookups",i,what,name,"no")
- reported[name]=true
- end
+ report_issue(i,what,sequence,"no")
elseif not next(rlookups) then
- local name=sequence.name
- if not reported[name] then
- report("rule %i in %s lookup %a has %s lookups",i,what,name,"empty")
- reported[name]=true
- end
+ report_issue(i,what,sequence,"empty")
rule.lookups=nil
else
for index,lookupid in sortedhash(rlookups) do
local h=sublookuphash[lookupid]
if not h then
- nofsublookups=nofsublookups+1
- local d=lookups[lookupid].done
- h={
- index=nofsublookups,
- name=f_lookupname(lookupprefix,"d",lookupid+lookupidoffset),
- derived=true,
- steps=d.steps,
- nofsteps=d.nofsteps,
- type=d.lookuptype,
- markclass=d.markclass or nil,
- flags=d.flags,
- }
- sublookuplist[nofsublookups]=h
- sublookuphash[lookupid]=nofsublookups
- sublookupcheck[lookupid]=1
+ local lookup=lookups[lookupid]
+ if lookup then
+ local d=lookup.done
+ if d then
+ nofsublookups=nofsublookups+1
+ h={
+ index=nofsublookups,
+ name=f_lookupname(lookupprefix,"d",lookupid+lookupidoffset),
+ derived=true,
+ steps=d.steps,
+ nofsteps=d.nofsteps,
+ type=d.lookuptype,
+ markclass=d.markclass or nil,
+ flags=d.flags,
+ }
+ sublookuplist[nofsublookups]=h
+ sublookuphash[lookupid]=nofsublookups
+ sublookupcheck[lookupid]=1
+ else
+ report_issue(i,what,sequence,"missing")
+ rule.lookups=nil
+ break
+ end
+ else
+ report_issue(i,what,sequence,"bad")
+ rule.lookups=nil
+ break
+ end
else
sublookupcheck[lookupid]=sublookupcheck[lookupid]+1
end
@@ -12335,7 +12353,13 @@ local function readmathglyphinfo(f,fontdata,offset)
local function get(offset)
setposition(f,kernoffset+offset)
local n=readushort(f)
- if n>0 then
+ if n==0 then
+ local k=readmathvalue(f)
+ if k==0 then
+ else
+ return { { kern=k } }
+ end
+ else
local l={}
for i=1,n do
l[i]={ height=readmathvalue(f) }
@@ -12371,10 +12395,10 @@ local function readmathglyphinfo(f,fontdata,offset)
if next(kernset) then
local glyph=glyphs[coverage[i]]
local math=glyph.math
- if not math then
- glyph.math={ kerns=kernset }
- else
+ if math then
math.kerns=kernset
+ else
+ glyph.math={ kerns=kernset }
end
end
end
@@ -14508,7 +14532,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.020
+otf.version=3.021
otf.cache=containers.define("fonts","otl",otf.version,true)
local otfreaders=otf.readers
local hashes=fonts.hashes
@@ -16147,7 +16171,7 @@ local function inject_pairs_only(head,where)
end
local leftkern=i.leftkern
if leftkern and leftkern~=0 then
- insert_node_before(head,current,newkern(leftkern))
+ head=insert_node_before(head,current,newkern(leftkern))
end
local rightkern=i.rightkern
if rightkern and rightkern~=0 then
@@ -16808,10 +16832,19 @@ function injections.handler(head,where)
head=injectspaces(head)
end
if nofregisteredmarks>0 or nofregisteredcursives>0 then
+ if trace_injections then
+ report_injections("injection variant %a","everything")
+ end
return inject_everything(head,where)
elseif nofregisteredpairs>0 then
+ if trace_injections then
+ report_injections("injection variant %a","pairs")
+ end
return inject_pairs_only(head,where)
elseif nofregisteredkerns>0 then
+ if trace_injections then
+ report_injections("injection variant %a","kerns")
+ end
return inject_kerns_only(head,where)
else
return head,false
--
cgit v1.2.3
From e391f0e473b9a2987bd27841f96f91f3379b767d Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Fri, 10 Jun 2016 08:00:50 +0200
Subject: [init] adapt Context base path for file loader
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Fix issue #344
The paths changed a while ago making a change necessary. We can’t just
replace the path because older versions of the tree would fail,
rendering bisection unusable. We compensate by testing the candidate
directories beforehand.
---
src/luaotfload-init.lua | 41 +++++++++++++++++++++++++++++++----------
1 file changed, 31 insertions(+), 10 deletions(-)
diff --git a/src/luaotfload-init.lua b/src/luaotfload-init.lua
index 48a8eba..3c0b622 100644
--- a/src/luaotfload-init.lua
+++ b/src/luaotfload-init.lua
@@ -9,6 +9,7 @@
local setmetatable = setmetatable
local kpselookup = kpse.lookup
+local lfsisdir = lfs.isdir
--[[doc--
@@ -223,7 +224,7 @@ end
--- below paths are relative to the texmf-context
local ltx = "tex/generic/context/luatex"
-local ctx = "tex/context/base"
+local ctx = { "tex/context/base/mkiv", "tex/context/base" }
local context_modules = {
@@ -285,17 +286,37 @@ local load_context_modules = function (pth)
local sub, spec = unpack (context_modules [i])
if sub == false then
ignore_module (spec)
- elseif type (sub) == "string" then
- if pth then
+ else
+ local tsub = type (sub)
+ if not pth then
+ load_module (spec)
+ elseif tsub == "string" then
load_module (spec, file.join (pth, sub))
+ elseif tsub == "table" then
+ local pfx
+ local nsub = #sub
+ for j = 1, nsub do
+ local full = file.join (pth, sub [j])
+ if lfsisdir (full) then --- pick the first real one
+ pfx = full
+ break
+ end
+ end
+ if pfx then
+ load_module (spec, pfx)
+ else
+ logreport ("both", 0, "init",
+ "None of the %d search paths for module %q exist; \z
+ falling back to default path.",
+ nsub, tostring (spec))
+ load_module (spec) --- maybe we’ll get by after all?
+ end
else
- load_module (spec)
+ logreport ("both", 0, "init",
+ "Internal error, please report. \z
+ This is not your fault.")
+ os.exit (-1)
end
- else
- logreport ("both", 0, "init",
- "Internal error, please report. \z
- This is not your fault.")
- os.exit (-1)
end
end
@@ -535,7 +556,7 @@ local init_main = function ()
"Loading Context modules in lookup path.")
load_context_modules ()
- elseif lfs.isdir (fontloader) then
+ elseif lfsisdir (fontloader) then
logreport ("log", 0, "init",
"Loading Context files under prefix “%s”.",
fontloader)
--
cgit v1.2.3
From 3bbb743eb16f83c118776a7689b4826911c41bb1 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Sat, 11 Jun 2016 12:02:12 +0200
Subject: [features] fix missing local
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The new addfeature() as of 499160de78a1 accesses utf8.len() which wasn’t
imported at this point. Another import, utf8.char(), became irrelevant.
Spotted by @doyunkim
---
src/luaotfload-features.lua | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/luaotfload-features.lua b/src/luaotfload-features.lua
index ae4ac77..b6e889e 100644
--- a/src/luaotfload-features.lua
+++ b/src/luaotfload-features.lua
@@ -1296,8 +1296,9 @@ local report_otf = logs.reporter("fonts","otf loading")
--- start locals for addfeature()
-local utfbyte = unicode.utf8.byte
-local utfchar = unicode.utf8.char
+local utf8 = unicode.utf8
+local utfbyte = utf8.byte
+local utflen = utf8.len
local otf = handlers and handlers.otf --- filled in later during initialization
--
cgit v1.2.3
From d8ba9c36eaf49c1f28b8e8f11c969b77ece32db4 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Sun, 12 Jun 2016 18:14:33 +0200
Subject: [fontloader] sync with Context as of 2016-06-12
---
src/fontloader/misc/fontloader-font-con.lua | 51 +-
src/fontloader/misc/fontloader-font-dsp.lua | 144 ++-
src/fontloader/misc/fontloader-font-map.lua | 4 +-
src/fontloader/misc/fontloader-font-one.lua | 6 +-
src/fontloader/misc/fontloader-font-osd.lua | 2 +-
src/fontloader/misc/fontloader-font-ota.lua | 2 +-
src/fontloader/misc/fontloader-font-otd.lua | 48 +-
src/fontloader/misc/fontloader-font-oti.lua | 4 +-
src/fontloader/misc/fontloader-font-otj.lua | 2 +
src/fontloader/misc/fontloader-font-otl.lua | 28 +-
src/fontloader/misc/fontloader-font-otr.lua | 37 +-
src/fontloader/misc/fontloader-font-ots.lua | 15 +-
src/fontloader/misc/fontloader-font-oup.lua | 56 ++
src/fontloader/misc/fontloader-font-tfm.lua | 4 +-
src/fontloader/misc/fontloader-fonts-ext.lua | 2 +-
src/fontloader/misc/fontloader-fonts.lua | 2 +
src/fontloader/misc/fontloader-math.tex | 12 +-
src/fontloader/runtime/fontloader-reference.lua | 1131 ++++++++++++++++++++++-
18 files changed, 1464 insertions(+), 86 deletions(-)
diff --git a/src/fontloader/misc/fontloader-font-con.lua b/src/fontloader/misc/fontloader-font-con.lua
index 367f807..1a0daff 100644
--- a/src/fontloader/misc/fontloader-font-con.lua
+++ b/src/fontloader/misc/fontloader-font-con.lua
@@ -1049,6 +1049,29 @@ function constructors.hashfeatures(specification) -- will be overloaded
return "unknown"
end
+-- hashmethods.normal = function(list)
+-- local s = { }
+-- local n = 0
+-- for k, v in next, list do
+-- if not k then
+-- -- no need to add to hash
+-- elseif k == "number" or k == "features" then
+-- -- no need to add to hash (maybe we need a skip list)
+-- else
+-- n = n + 1
+-- s[n] = k
+-- end
+-- end
+-- if n > 0 then
+-- sort(s)
+-- for i=1,n do
+-- local k = s[i]
+-- s[i] = k .. '=' .. tostring(list[k])
+-- end
+-- return concat(s,"+")
+-- end
+-- end
+
hashmethods.normal = function(list)
local s = { }
local n = 0
@@ -1059,15 +1082,11 @@ hashmethods.normal = function(list)
-- no need to add to hash (maybe we need a skip list)
else
n = n + 1
- s[n] = k
+ s[n] = k .. '=' .. tostring(v)
end
end
if n > 0 then
sort(s)
- for i=1,n do
- local k = s[i]
- s[i] = k .. '=' .. tostring(list[k])
- end
return concat(s,"+")
end
end
@@ -1236,7 +1255,11 @@ function constructors.getfeatureaction(what,where,mode,name)
end
end
-function constructors.newhandler(what) -- could be a metatable newindex
+local newhandler = { }
+constructors.handlers = newhandler -- downward compatible
+constructors.newhandler = newhandler
+
+local function setnewhandler(what) -- could be a metatable newindex
local handler = handlers[what]
if not handler then
handler = { }
@@ -1245,7 +1268,16 @@ function constructors.newhandler(what) -- could be a metatable newindex
return handler
end
-function constructors.newfeatures(what) -- could be a metatable newindex
+setmetatable(newhandler, {
+ __call = function(t,k) local v = t[k] return v end,
+ __index = function(t,k) local v = setnewhandler(k) t[k] = v return v end,
+})
+
+local newfeatures = { }
+constructors.newfeatures = newfeatures -- downward compatible
+constructors.features = newfeatures
+
+local function setnewfeatures(what)
local handler = handlers[what]
local features = handler.features
if not features then
@@ -1265,6 +1297,11 @@ function constructors.newfeatures(what) -- could be a metatable newindex
return features
end
+setmetatable(newfeatures, {
+ __call = function(t,k) local v = t[k] return v end,
+ __index = function(t,k) local v = setnewfeatures(k) t[k] = v return v end,
+})
+
--[[ldx--
We need to check for default features. For this we provide
a helper function.
diff --git a/src/fontloader/misc/fontloader-font-dsp.lua b/src/fontloader/misc/fontloader-font-dsp.lua
index 37ae166..9726c51 100644
--- a/src/fontloader/misc/fontloader-font-dsp.lua
+++ b/src/fontloader/misc/fontloader-font-dsp.lua
@@ -76,6 +76,7 @@ local readshort = streamreader.readinteger2 -- 16-bit signed integer
local readfword = readshort
local readstring = streamreader.readstring
local readtag = streamreader.readtag
+local readbytes = streamreader.readbytes
local gsubhandlers = { }
local gposhandlers = { }
@@ -2191,7 +2192,7 @@ function readers.math(f,fontdata,specification)
setposition(f,tableoffset)
local version = readulong(f)
if version ~= 0x00010000 then
- report("table version %a of %a is not supported (yet), maybe font %s is bad",version,what,fontdata.filename)
+ report("table version %a of %a is not supported (yet), maybe font %s is bad",version,"math",fontdata.filename)
return
end
local constants = readushort(f)
@@ -2211,3 +2212,144 @@ function readers.math(f,fontdata,specification)
end
end
end
+
+function readers.colr(f,fontdata,specification)
+ if specification.details then
+ local datatable = fontdata.tables.colr
+ if datatable then
+ local tableoffset = datatable.offset
+ setposition(f,tableoffset)
+ local version = readushort(f)
+ if version ~= 0 then
+ report("table version %a of %a is not supported (yet), maybe font %s is bad",version,"colr",fontdata.filename)
+ return
+ end
+ if not fontdata.tables.cpal then
+ report("color table %a in font %a has no mandate %a table","colr",fontdata.filename,"cpal")
+ fontdata.colorpalettes = { }
+ end
+ local glyphs = fontdata.glyphs
+ local nofglyphs = readushort(f)
+ local baseoffset = readulong(f)
+ local layeroffset = readulong(f)
+ local noflayers = readushort(f)
+ local layerrecords = { }
+ local maxclass = 0
+ -- The special value 0xFFFF is foreground (but we index from 1). It
+ -- more looks like indices into a palette so 'class' is a better name
+ -- than 'palette'.
+ setposition(f,tableoffset + layeroffset)
+ for i=1,noflayers do
+ local slot = readushort(f)
+ local class = readushort(f)
+ if class < 0xFFFF then
+ class = class + 1
+ if class > maxclass then
+ maxclass = class
+ end
+ end
+ layerrecords[i] = {
+ slot = slot,
+ class = class,
+ }
+ end
+ fontdata.maxcolorclass = maxclass
+ setposition(f,tableoffset + baseoffset)
+ for i=0,nofglyphs-1 do
+ local glyphindex = readushort(f)
+ local firstlayer = readushort(f)
+ local noflayers = readushort(f)
+ local t = { }
+ for i=1,noflayers do
+ t[i] = layerrecords[firstlayer+i]
+ end
+ glyphs[glyphindex].colors = t
+ end
+ end
+ end
+end
+
+function readers.cpal(f,fontdata,specification)
+ if specification.details then
+ local datatable = fontdata.tables.cpal
+ if datatable then
+ local tableoffset = datatable.offset
+ setposition(f,tableoffset)
+ local version = readushort(f)
+ if version > 1 then
+ report("table version %a of %a is not supported (yet), maybe font %s is bad",version,"cpal",fontdata.filename)
+ return
+ end
+ local nofpaletteentries = readushort(f)
+ local nofpalettes = readushort(f)
+ local nofcolorrecords = readushort(f)
+ local firstcoloroffset = readulong(f)
+ local colorrecords = { }
+ local palettes = { }
+ for i=1,nofpalettes do
+ palettes[i] = readushort(f)
+ end
+ if version == 1 then
+ -- used for guis
+ local palettettypesoffset = readulong(f)
+ local palettelabelsoffset = readulong(f)
+ local paletteentryoffset = readulong(f)
+ end
+ setposition(f,tableoffset+firstcoloroffset)
+ for i=1,nofcolorrecords do
+ local b, g, r, a = readbytes(f,4)
+ colorrecords[i] = {
+ r, g, b, a ~= 255 and a or nil,
+ }
+ end
+ for i=1,nofpalettes do
+ local p = { }
+ local o = palettes[i]
+ for j=1,nofpaletteentries do
+ p[j] = colorrecords[o+j]
+ end
+ palettes[i] = p
+ end
+ fontdata.colorpalettes = palettes
+ end
+ end
+end
+
+function readers.svg(f,fontdata,specification)
+ if specification.details then
+ local datatable = fontdata.tables.svg
+ if datatable then
+ local tableoffset = datatable.offset
+ setposition(f,tableoffset)
+ local version = readushort(f)
+ if version ~= 0 then
+ report("table version %a of %a is not supported (yet), maybe font %s is bad",version,"svg",fontdata.filename)
+ return
+ end
+ local glyphs = fontdata.glyphs
+ local indexoffset = tableoffset + readulong(f)
+ local reserved = readulong(f)
+ setposition(f,indexoffset)
+ local nofentries = readushort(f)
+ local entries = { }
+ for i=1,nofentries do
+ entries[i] = {
+ first = readushort(f),
+ last = readushort(f),
+ offset = indexoffset + readulong(f),
+ length = readulong(f),
+ }
+ end
+ for i=1,nofentries do
+ local entry = entries[i]
+ setposition(f,entry.offset)
+ entries[i] = {
+ first = entry.first,
+ last = entry.last,
+ data = readstring(f,entry.length)
+ }
+ end
+ fontdata.svgshapes = entries
+ end
+ end
+end
diff --git a/src/fontloader/misc/fontloader-font-map.lua b/src/fontloader/misc/fontloader-font-map.lua
index db43495..6151b37 100644
--- a/src/fontloader/misc/fontloader-font-map.lua
+++ b/src/fontloader/misc/fontloader-font-map.lua
@@ -139,7 +139,7 @@ local f_double = formatters["%04X%04X"]
-- end
-- end
-local function tounicode16(unicode,name)
+local function tounicode16(unicode)
if unicode < 0xD7FF or (unicode > 0xDFFF and unicode <= 0xFFFF) then
return f_single(unicode)
else
@@ -148,7 +148,7 @@ local function tounicode16(unicode,name)
end
end
-local function tounicode16sequence(unicodes,name)
+local function tounicode16sequence(unicodes)
local t = { }
for l=1,#unicodes do
local u = unicodes[l]
diff --git a/src/fontloader/misc/fontloader-font-one.lua b/src/fontloader/misc/fontloader-font-one.lua
index a9f78f4..a6f47e8 100644
--- a/src/fontloader/misc/fontloader-font-one.lua
+++ b/src/fontloader/misc/fontloader-font-one.lua
@@ -45,14 +45,14 @@ local definers = fonts.definers
local readers = fonts.readers
local constructors = fonts.constructors
-local afm = constructors.newhandler("afm")
-local pfb = constructors.newhandler("pfb")
+local afm = constructors.handlers.afm
+local pfb = constructors.handlers.pfb
local otf = fonts.handlers.otf
local otfreaders = otf.readers
local otfenhancers = otf.enhancers
-local afmfeatures = constructors.newfeatures("afm")
+local afmfeatures = constructors.features.afm
local registerafmfeature = afmfeatures.register
afm.version = 1.512 -- incrementing this number one up will force a re-cache
diff --git a/src/fontloader/misc/fontloader-font-osd.lua b/src/fontloader/misc/fontloader-font-osd.lua
index d2bb210..a3dda67 100644
--- a/src/fontloader/misc/fontloader-font-osd.lua
+++ b/src/fontloader/misc/fontloader-font-osd.lua
@@ -82,7 +82,7 @@ local otf = fonts.handlers.otf
local handlers = otf.handlers
local methods = fonts.analyzers.methods
-local otffeatures = fonts.constructors.newfeatures("otf")
+local otffeatures = fonts.constructors.features.otf
local registerotffeature = otffeatures.register
local nuts = nodes.nuts
diff --git a/src/fontloader/misc/fontloader-font-ota.lua b/src/fontloader/misc/fontloader-font-ota.lua
index 42566eb..4ddb831 100644
--- a/src/fontloader/misc/fontloader-font-ota.lua
+++ b/src/fontloader/misc/fontloader-font-ota.lua
@@ -55,7 +55,7 @@ local fontdata = fonts.hashes.identifiers
local categories = characters and characters.categories or { } -- sorry, only in context
local chardata = characters and characters.data
-local otffeatures = fonts.constructors.newfeatures("otf")
+local otffeatures = fonts.constructors.features.otf
local registerotffeature = otffeatures.register
--[[ldx--
diff --git a/src/fontloader/misc/fontloader-font-otd.lua b/src/fontloader/misc/fontloader-font-otd.lua
index fc5ba64..64cb1bc 100644
--- a/src/fontloader/misc/fontloader-font-otd.lua
+++ b/src/fontloader/misc/fontloader-font-otd.lua
@@ -132,6 +132,10 @@ local wildcard = "*"
-- needs checking: some added features can pass twice
+local P, C, Cc, lpegmatch = lpeg.P, lpeg.C, lpeg.Cc, lpeg.match
+
+local pattern = P("always") * (P(-1) * Cc(true) + P(":") * C((1-P(-1))^1))
+
local function initialize(sequence,script,language,s_enabled,a_enabled,font,attr,dynamic,ra,autoscript,autolanguage)
local features = sequence.features
if features then
@@ -148,21 +152,34 @@ local function initialize(sequence,script,language,s_enabled,a_enabled,font,attr
e_e = s_enabled and s_enabled[kind] -- the value (font)
end
if e_e then
- local scripts = features[kind] --
- local languages = scripts[script] or scripts[wildcard]
- if not languages and autoscript then
- langages = defaultscript(featuretype,autoscript,scripts)
- end
- if languages then
- -- we need detailed control over default becase we want to trace
- -- only first attribute match check, so we assume simple fina's
- local valid = false
- if languages[language] then
- valid = e_e
- elseif languages[wildcard] then
- valid = e_e
- elseif autolanguage and defaultlanguage(featuretype,autolanguage,languages) then
- valid = e_e
+ local valid = type(e_e) == "string" and lpegmatch(pattern,e_e)
+ if valid then
+ -- we have hit always
+ local attribute = autofeatures[kind] or false
+ if trace_applied then
+ report_process(
+ "font %s, dynamic %a (%a), feature %a, script %a, language %a, lookup %a, value %a",
+ font,attr or 0,dynamic,kind,"*","*",sequence.name,valid)
+ end
+ ra[#ra+1] = { valid, attribute, sequence, kind }
+ else
+ -- we already checked for e_e
+ local scripts = features[kind] --
+ local languages = scripts[script] or scripts[wildcard]
+ if not languages and autoscript then
+ langages = defaultscript(featuretype,autoscript,scripts)
+ end
+ if languages then
+ -- we need detailed control over default becase we want to trace
+ -- only first attribute match check, so we assume simple fina's
+ -- local valid = false
+ if languages[language] then
+ valid = e_e
+ elseif languages[wildcard] then
+ valid = e_e
+ elseif autolanguage and defaultlanguage(featuretype,autolanguage,languages) then
+ valid = e_e
+ end
end
if valid then
local attribute = autofeatures[kind] or false
@@ -241,6 +258,7 @@ function otf.dataset(tfmdata,font,attr) -- attr only when explicit (as in specia
local autoscript = (s_enabled and s_enabled.autoscript ) or (a_enabled and a_enabled.autoscript )
local autolanguage = (s_enabled and s_enabled.autolanguage) or (a_enabled and a_enabled.autolanguage)
for s=1,#sequences do
+ -- just return nil or ra step
initialize(sequences[s],script,language,s_enabled,a_enabled,font,attr,dynamic,ra,autoscript,autolanguage)
end
end
diff --git a/src/fontloader/misc/fontloader-font-oti.lua b/src/fontloader/misc/fontloader-font-oti.lua
index bacd001..d74d2d5 100644
--- a/src/fontloader/misc/fontloader-font-oti.lua
+++ b/src/fontloader/misc/fontloader-font-oti.lua
@@ -11,8 +11,8 @@ local lower = string.lower
local fonts = fonts
local constructors = fonts.constructors
-local otf = constructors.newhandler("otf")
-local otffeatures = constructors.newfeatures("otf")
+local otf = constructors.handlers.otf
+local otffeatures = constructors.features.otf
local registerotffeature = otffeatures.register
local otftables = otf.tables or { }
diff --git a/src/fontloader/misc/fontloader-font-otj.lua b/src/fontloader/misc/fontloader-font-otj.lua
index 0db30c6..d1408fd 100644
--- a/src/fontloader/misc/fontloader-font-otj.lua
+++ b/src/fontloader/misc/fontloader-font-otj.lua
@@ -24,6 +24,8 @@ if not modules then modules = { } end modules ['font-otj'] = {
-- The use_advance code is just a test and is meant for testing and manuals. There is no
-- performance (or whatever) gain and using kerns is somewhat cleaner (at least for now).
+-- Maybe: subtype fontkern when pure kerns.
+
if not nodes.properties then return end
local next, rawget = next, rawget
diff --git a/src/fontloader/misc/fontloader-font-otl.lua b/src/fontloader/misc/fontloader-font-otl.lua
index 73e3df9..c7c278a 100644
--- a/src/fontloader/misc/fontloader-font-otl.lua
+++ b/src/fontloader/misc/fontloader-font-otl.lua
@@ -53,8 +53,12 @@ local report_otf = logs.reporter("fonts","otf loading")
local fonts = fonts
local otf = fonts.handlers.otf
-otf.version = 3.021 -- beware: also sync font-mis.lua and in mtx-fonts
+otf.version = 3.022 -- beware: also sync font-mis.lua and in mtx-fonts
otf.cache = containers.define("fonts", "otl", otf.version, true)
+otf.svgcache = containers.define("fonts", "svg", otf.version, true)
+otf.pdfcache = containers.define("fonts", "pdf", otf.version, true)
+
+otf.svgenabled = false
local otfreaders = otf.readers
@@ -63,7 +67,7 @@ local definers = fonts.definers
local readers = fonts.readers
local constructors = fonts.constructors
-local otffeatures = constructors.newfeatures("otf")
+local otffeatures = constructors.features.otf
local registerotffeature = otffeatures.register
local enhancers = allocate()
@@ -270,6 +274,25 @@ function otf.load(filename,sub,featurefile) -- second argument (format) is gone
--
--
if data then
+ --
+ local resources = data.resources
+ local svgshapes = resources.svgshapes
+ if svgshapes then
+ resources.svgshapes = nil
+ if otf.svgenabled then
+ local timestamp = os.date()
+ -- work in progress ... a bit boring to do
+ containers.write(otf.svgcache,hash, {
+ svgshapes = svgshapes,
+ timestamp = timestamp,
+ })
+ data.properties.svg = {
+ hash = hash,
+ timestamp = timestamp,
+ }
+ end
+ end
+ --
otfreaders.compact(data)
otfreaders.rehash(data,"unicodes")
otfreaders.addunicodetable(data)
@@ -346,7 +369,6 @@ end
local function copytotfm(data,cache_id)
if data then
local metadata = data.metadata
- local resources = data.resources
local properties = derivetable(data.properties)
local descriptions = derivetable(data.descriptions)
local goodies = derivetable(data.goodies)
diff --git a/src/fontloader/misc/fontloader-font-otr.lua b/src/fontloader/misc/fontloader-font-otr.lua
index 6595262..e09e87d 100644
--- a/src/fontloader/misc/fontloader-font-otr.lua
+++ b/src/fontloader/misc/fontloader-font-otr.lua
@@ -129,12 +129,11 @@ local function readlongdatetime(f)
return 0x100000000 * d + 0x1000000 * e + 0x10000 * f + 0x100 * g + h
end
-local tableversion = 0.004
-local privateoffset = fonts.constructors and fonts.constructors.privateoffset or 0xF0000 -- 0x10FFFF
+local tableversion = 0.004
+readers.tableversion = tableversion
+local privateoffset = fonts.constructors and fonts.constructors.privateoffset or 0xF0000 -- 0x10FFFF
+local reportedskipped = { }
-readers.tableversion = tableversion
-
-local reportedskipped = { }
local function reportskippedtable(tag)
if not reportedskipped[tag] then
@@ -1657,6 +1656,26 @@ function readers.glyf(f,fontdata,specification) -- part goes to cff module
end
end
+-- Experimental (we need fonts).
+
+function readers.colr(f,fontdata,specification)
+ if specification.details then
+ reportskippedtable("colr")
+ end
+end
+
+function readers.cpal(f,fontdata,specification)
+ if specification.details then
+ reportskippedtable("cpal")
+ end
+end
+
+function readers.svg(f,fontdata,specification)
+ if specification.details then
+ reportskippedtable("svg")
+ end
+end
+
-- Here we have a table that we really need for later processing although a more advanced gpos table
-- can also be available. Todo: we need a 'fake' lookup for this (analogue to ff).
@@ -1997,6 +2016,9 @@ local function readdata(f,offset,specification)
readers["cmap"](f,fontdata,specification)
readers["loca"](f,fontdata,specification)
readers["glyf"](f,fontdata,specification)
+ readers["colr"](f,fontdata,specification)
+ readers["cpal"](f,fontdata,specification)
+ readers["svg" ](f,fontdata,specification)
readers["kern"](f,fontdata,specification)
readers["gdef"](f,fontdata,specification)
readers["gsub"](f,fontdata,specification)
@@ -2165,7 +2187,8 @@ function readers.loadfont(filename,n)
goodies = { },
metadata = getinfo(fontdata,n), -- no platformnames here !
properties = {
- hasitalics = fontdata.hasitalics or false,
+ hasitalics = fontdata.hasitalics or false,
+ maxcolorclass = fontdata.maxcolorclass,
},
resources = {
-- filename = fontdata.filename,
@@ -2182,6 +2205,8 @@ function readers.loadfont(filename,n)
version = getname(fontdata,"version"),
cidinfo = fontdata.cidinfo,
mathconstants = fontdata.mathconstants,
+ colorpalettes = fontdata.colorpalettes,
+ svgshapes = fontdata.svgshapes,
},
}
end
diff --git a/src/fontloader/misc/fontloader-font-ots.lua b/src/fontloader/misc/fontloader-font-ots.lua
index 669668e..51704bf 100644
--- a/src/fontloader/misc/fontloader-font-ots.lua
+++ b/src/fontloader/misc/fontloader-font-ots.lua
@@ -124,7 +124,7 @@ local trace_cursive = false registertracker("otf.cursive", function(v
local trace_preparing = false registertracker("otf.preparing", function(v) trace_preparing = v end)
local trace_bugs = false registertracker("otf.bugs", function(v) trace_bugs = v end)
local trace_details = false registertracker("otf.details", function(v) trace_details = v end)
-local trace_applied = false registertracker("otf.applied", function(v) trace_applied = v end)
+----- trace_applied = false registertracker("otf.applied", function(v) trace_applied = v end)
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)
@@ -239,7 +239,7 @@ local cursonce = true
local fonthashes = fonts.hashes
local fontdata = fonthashes.identifiers
-local otffeatures = fonts.constructors.newfeatures("otf")
+local otffeatures = fonts.constructors.features.otf
local registerotffeature = otffeatures.register
local onetimemessage = fonts.loggers.onetimemessage or function() end
@@ -3389,9 +3389,13 @@ local function featuresprocessor(head,font,attr)
end
- if attr == 0 then
- attr = false -- some 10% faster when no dynamics but hardly measureable on real runs
- end
+ -- some 10% faster when no dynamics but hardly measureable on real runs .. but: it only
+ -- works when we have no other dynamics as otherwise the zero run will be applied to the
+ -- whole stream for which we then need to pass another variable which we won't
+
+ -- if attr == 0 then
+ -- attr = false
+ -- end
head = tonut(head)
@@ -3484,7 +3488,6 @@ local function featuresprocessor(head,font,attr)
local start = head -- local ?
rlmode = 0 -- to be checked ?
if nofsteps == 1 then -- happens often
-
local step = steps[1]
local lookupcache = step.coverage
if not lookupcache then
diff --git a/src/fontloader/misc/fontloader-font-oup.lua b/src/fontloader/misc/fontloader-font-oup.lua
index bd47e71..e2d209a 100644
--- a/src/fontloader/misc/fontloader-font-oup.lua
+++ b/src/fontloader/misc/fontloader-font-oup.lua
@@ -707,6 +707,19 @@ local function unifyglyphs(fontdata,usenames)
end
end
--
+ local colorpalettes = resources.colorpalettes
+ if colorpalettes then
+ for index=1,#glyphs do
+ local colors = glyphs[index].colors
+ if colors then
+ for i=1,#colors do
+ local c = colors[i]
+ c.slot = indices[c.slot]
+ end
+ end
+ end
+ end
+ --
fontdata.private = private
fontdata.glyphs = nil
fontdata.names = names
@@ -1159,6 +1172,7 @@ function readers.pack(data)
local sequences = resources.sequences
local sublookups = resources.sublookups
local features = resources.features
+ local palettes = resources.colorpalettes
local chardata = characters and characters.data
local descriptions = data.descriptions or data.glyphs
@@ -1191,6 +1205,14 @@ function readers.pack(data)
end
end
end
+ -- if palettes then
+ -- local color = description.color
+ -- if color then
+ -- for i=1,#color do
+ -- color[i] = pack_normal(color[i])
+ -- end
+ -- end
+ -- end
end
local function packthem(sequences)
@@ -1315,6 +1337,16 @@ function readers.pack(data)
end
end
+ if palettes then
+ for i=1,#palettes do
+ local p = palettes[i]
+ for j=1,#p do
+ p[j] = pack_indexed(p[j])
+ end
+ end
+
+ end
+
if not success(1,pass) then
return
end
@@ -1462,6 +1494,7 @@ function readers.unpack(data)
local sequences = resources.sequences
local sublookups = resources.sublookups
local features = resources.features
+ local palettes = resources.colorpalettes
local unpacked = { }
setmetatable(unpacked,unpacked_mt)
for unicode, description in next, descriptions do
@@ -1488,6 +1521,17 @@ function readers.unpack(data)
end
end
end
+ -- if palettes then
+ -- local color = description.color
+ -- if color then
+ -- for i=1,#color do
+ -- local tv = tables[color[i]]
+ -- if tv then
+ -- color[i] = tv
+ -- end
+ -- end
+ -- end
+ -- end
end
local function unpackthem(sequences)
@@ -1717,6 +1761,18 @@ function readers.unpack(data)
end
end
+ if palettes then
+ for i=1,#palettes do
+ local p = palettes[i]
+ for j=1,#p do
+ local tv = tables[p[j]]
+ if tv then
+ p[j] = tv
+ end
+ end
+ end
+ end
+
data.tables = nil
end
end
diff --git a/src/fontloader/misc/fontloader-font-tfm.lua b/src/fontloader/misc/fontloader-font-tfm.lua
index f790064..ab6d795 100644
--- a/src/fontloader/misc/fontloader-font-tfm.lua
+++ b/src/fontloader/misc/fontloader-font-tfm.lua
@@ -23,12 +23,12 @@ local readers = fonts.readers
local constructors = fonts.constructors
local encodings = fonts.encodings
-local tfm = constructors.newhandler("tfm")
+local tfm = constructors.handlers.tfm
tfm.version = 1.000
tfm.maxnestingdepth = 5
tfm.maxnestingsize = 65536*1024
-local tfmfeatures = constructors.newfeatures("tfm")
+local tfmfeatures = constructors.features.tfm
----- registertfmfeature = tfmfeatures.register
constructors.resolvevirtualtoo = false -- wil be set in font-ctx.lua
diff --git a/src/fontloader/misc/fontloader-fonts-ext.lua b/src/fontloader/misc/fontloader-fonts-ext.lua
index b60d045..9d8d307 100644
--- a/src/fontloader/misc/fontloader-fonts-ext.lua
+++ b/src/fontloader/misc/fontloader-fonts-ext.lua
@@ -12,7 +12,7 @@ if context then
end
local fonts = fonts
-local otffeatures = fonts.constructors.newfeatures("otf")
+local otffeatures = fonts.constructors.features.otf
-- A few generic extensions.
diff --git a/src/fontloader/misc/fontloader-fonts.lua b/src/fontloader/misc/fontloader-fonts.lua
index c493844..83d52d9 100644
--- a/src/fontloader/misc/fontloader-fonts.lua
+++ b/src/fontloader/misc/fontloader-fonts.lua
@@ -186,6 +186,7 @@ if non_generic_context.luatex_fonts.skip_loading ~= true then
loadmodule("l-file.lua")
loadmodule("l-boolean.lua")
loadmodule("l-math.lua")
+ loadmodule("l-unicode.lua")
-- A few slightly higher level support modules:
@@ -257,6 +258,7 @@ if non_generic_context.luatex_fonts.skip_loading ~= true then
loadmodule('font-ota.lua')
loadmodule('font-ots.lua')
loadmodule('font-osd.lua')
+ loadmodule('font-ocl.lua') -- svg needs 0.97 (for fix in memstreams)
-- type one code
diff --git a/src/fontloader/misc/fontloader-math.tex b/src/fontloader/misc/fontloader-math.tex
index 604b4a1..b249021 100644
--- a/src/fontloader/misc/fontloader-math.tex
+++ b/src/fontloader/misc/fontloader-math.tex
@@ -40,9 +40,9 @@
\font\tenbf = file:lmroman10-bold.otf:+liga;+kern;+tlig;+trep at 10pt
\font\tenbi = file:lmroman10-bolditalic.otf:+liga;+kern;+tlig;+trep at 10pt
%
- \font\mathfonttextupright = file:latinmodern-math.otf:ssty=0;fixmath=yes at 10pt
- \font\mathfontscriptupright = file:latinmodern-math.otf:ssty=1;fixmath=yes at 7pt
- \font\mathfontscriptscriptupright = file:latinmodern-math.otf:ssty=2;fixmath=yes at 5pt
+ \font\mathfonttextupright = file:latinmodern-math.otf:script=math;ssty=0;mathsize=yes at 10pt
+ \font\mathfontscriptupright = file:latinmodern-math.otf:script=math;ssty=1;mathsize=yes at 7pt
+ \font\mathfontscriptscriptupright = file:latinmodern-math.otf:script=math;ssty=2;mathsize=yes at 5pt
%
\textfont 0 = \mathfonttextupright
\scriptfont 0 = \mathfontscriptupright
@@ -61,9 +61,9 @@
\font\tenbf = file:lucidabrightot-demi.otf:+liga;+kern;+tlig;+trep at 10pt
\font\tenbi = file:lucidabrightot-demiitalic.otf:+liga;+kern;+tlig;+trep at 10pt
%
- \font\mathfonttextupright = file:lucidabrightmathot.otf:ssty=0;fixmath=yes at 10pt
- \font\mathfontscriptupright = file:lucidabrightmathot.otf:ssty=1;fixmath=yes at 7pt
- \font\mathfontscriptscriptupright = file:lucidabrightmathot.otf:ssty=2;fixmath=yes at 5pt
+ \font\mathfonttextupright = file:lucidabrightmathot.otf:script=math;ssty=0;mathsize=yes at 10pt
+ \font\mathfontscriptupright = file:lucidabrightmathot.otf:script=math;ssty=1;mathsize=yes at 7pt
+ \font\mathfontscriptscriptupright = file:lucidabrightmathot.otf:script=math;ssty=2;mathsize=yes at 5pt
%
\textfont 0 = \mathfonttextupright
\scriptfont 0 = \mathfontscriptupright
diff --git a/src/fontloader/runtime/fontloader-reference.lua b/src/fontloader/runtime/fontloader-reference.lua
index 4d1ef83..350d3cf 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 : 05/31/16 09:02:55
+-- merge date : 06/10/16 23:51:36
do -- begin closure to overcome local limits and interference
@@ -2785,6 +2785,620 @@ end -- closure
do -- begin closure to overcome local limits and interference
+if not modules then modules={} end modules ['l-unicode']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+utf=utf or (unicode and unicode.utf8) or {}
+utf.characters=utf.characters or string.utfcharacters
+utf.values=utf.values or string.utfvalues
+local type=type
+local char,byte,format,sub,gmatch=string.char,string.byte,string.format,string.sub,string.gmatch
+local concat=table.concat
+local P,C,R,Cs,Ct,Cmt,Cc,Carg,Cp=lpeg.P,lpeg.C,lpeg.R,lpeg.Cs,lpeg.Ct,lpeg.Cmt,lpeg.Cc,lpeg.Carg,lpeg.Cp
+local lpegmatch=lpeg.match
+local patterns=lpeg.patterns
+local tabletopattern=lpeg.utfchartabletopattern
+local bytepairs=string.bytepairs
+local finder=lpeg.finder
+local replacer=lpeg.replacer
+local utfvalues=utf.values
+local utfgmatch=utf.gmatch
+local p_utftype=patterns.utftype
+local p_utfstricttype=patterns.utfstricttype
+local p_utfoffset=patterns.utfoffset
+local p_utf8char=patterns.utf8character
+local p_utf8byte=patterns.utf8byte
+local p_utfbom=patterns.utfbom
+local p_newline=patterns.newline
+local p_whitespace=patterns.whitespace
+if not unicode then
+ unicode={ utf=utf }
+end
+if not utf.char then
+ local floor,char=math.floor,string.char
+ function utf.char(n)
+ if n<0x80 then
+ return char(n)
+ elseif n<0x800 then
+ return char(
+ 0xC0+floor(n/0x40),
+ 0x80+(n%0x40)
+ )
+ elseif n<0x10000 then
+ return char(
+ 0xE0+floor(n/0x1000),
+ 0x80+(floor(n/0x40)%0x40),
+ 0x80+(n%0x40)
+ )
+ elseif n<0x200000 then
+ return char(
+ 0xF0+floor(n/0x40000),
+ 0x80+(floor(n/0x1000)%0x40),
+ 0x80+(floor(n/0x40)%0x40),
+ 0x80+(n%0x40)
+ )
+ else
+ return ""
+ end
+ end
+end
+if not utf.byte then
+ local utf8byte=patterns.utf8byte
+ function utf.byte(c)
+ return lpegmatch(utf8byte,c)
+ end
+end
+local utfchar,utfbyte=utf.char,utf.byte
+function utf.filetype(data)
+ return data and lpegmatch(p_utftype,data) or "unknown"
+end
+local toentities=Cs (
+ (
+ patterns.utf8one+(
+ patterns.utf8two+patterns.utf8three+patterns.utf8four
+ )/function(s) local b=utfbyte(s) if b<127 then return s else return format("%X;",b) end end
+ )^0
+)
+patterns.toentities=toentities
+function utf.toentities(str)
+ return lpegmatch(toentities,str)
+end
+local one=P(1)
+local two=C(1)*C(1)
+local four=C(R(utfchar(0xD8),utfchar(0xFF)))*C(1)*C(1)*C(1)
+local pattern=P("\254\255")*Cs((
+ four/function(a,b,c,d)
+ local ab=0xFF*byte(a)+byte(b)
+ local cd=0xFF*byte(c)+byte(d)
+ return utfchar((ab-0xD800)*0x400+(cd-0xDC00)+0x10000)
+ end+two/function(a,b)
+ return utfchar(byte(a)*256+byte(b))
+ end+one
+ )^1 )+P("\255\254")*Cs((
+ four/function(b,a,d,c)
+ local ab=0xFF*byte(a)+byte(b)
+ local cd=0xFF*byte(c)+byte(d)
+ return utfchar((ab-0xD800)*0x400+(cd-0xDC00)+0x10000)
+ end+two/function(b,a)
+ return utfchar(byte(a)*256+byte(b))
+ end+one
+ )^1 )
+function string.toutf(s)
+ return lpegmatch(pattern,s) or s
+end
+local validatedutf=Cs (
+ (
+ patterns.utf8one+patterns.utf8two+patterns.utf8three+patterns.utf8four+P(1)/"�"
+ )^0
+)
+patterns.validatedutf=validatedutf
+function utf.is_valid(str)
+ return type(str)=="string" and lpegmatch(validatedutf,str) or false
+end
+if not utf.len then
+ local n,f=0,1
+ local utfcharcounter=patterns.utfbom^-1*Cmt (
+ Cc(1)*patterns.utf8one^1+Cc(2)*patterns.utf8two^1+Cc(3)*patterns.utf8three^1+Cc(4)*patterns.utf8four^1,
+ function(_,t,d)
+ n=n+(t-f)/d
+ f=t
+ return true
+ end
+ )^0
+ function utf.len(str)
+ n,f=0,1
+ lpegmatch(utfcharcounter,str or "")
+ return n
+ end
+end
+utf.length=utf.len
+if not utf.sub then
+ local utflength=utf.length
+ local b,e,n,first,last=0,0,0,0,0
+ local function slide_zero(s,p)
+ n=n+1
+ if n>=last then
+ e=p-1
+ else
+ return p
+ end
+ end
+ local function slide_one(s,p)
+ n=n+1
+ if n==first then
+ b=p
+ end
+ if n>=last then
+ e=p-1
+ else
+ return p
+ end
+ end
+ local function slide_two(s,p)
+ n=n+1
+ if n==first then
+ b=p
+ else
+ return true
+ end
+ end
+ local pattern_zero=Cmt(p_utf8char,slide_zero)^0
+ local pattern_one=Cmt(p_utf8char,slide_one )^0
+ local pattern_two=Cmt(p_utf8char,slide_two )^0
+ local pattern_first=C(patterns.utf8character)
+ function utf.sub(str,start,stop)
+ if not start then
+ return str
+ end
+ if start==0 then
+ start=1
+ end
+ if not stop then
+ if start<0 then
+ local l=utflength(str)
+ start=l+start
+ else
+ start=start-1
+ end
+ b,n,first=0,0,start
+ lpegmatch(pattern_two,str)
+ if n>=first then
+ return sub(str,b)
+ else
+ return ""
+ end
+ end
+ if start<0 or stop<0 then
+ local l=utf.length(str)
+ if start<0 then
+ start=l+start
+ if start<=0 then
+ start=1
+ else
+ start=start+1
+ end
+ end
+ if stop<0 then
+ stop=l+stop
+ if stop==0 then
+ stop=1
+ else
+ stop=stop+1
+ end
+ end
+ end
+ if start==1 and stop==1 then
+ return lpegmatch(pattern_first,str) or ""
+ elseif start>stop then
+ return ""
+ elseif start>1 then
+ b,e,n,first,last=0,0,0,start-1,stop
+ lpegmatch(pattern_one,str)
+ if n>=first and e==0 then
+ e=#str
+ end
+ return sub(str,b,e)
+ else
+ b,e,n,last=1,0,0,stop
+ lpegmatch(pattern_zero,str)
+ if e==0 then
+ e=#str
+ end
+ return sub(str,b,e)
+ end
+ end
+end
+function utf.remapper(mapping,option,action)
+ local variant=type(mapping)
+ if variant=="table" then
+ action=action or mapping
+ if option=="dynamic" then
+ local pattern=false
+ table.setmetatablenewindex(mapping,function(t,k,v) rawset(t,k,v) pattern=false end)
+ return function(str)
+ if not str or str=="" then
+ return ""
+ else
+ if not pattern then
+ pattern=Cs((tabletopattern(mapping)/action+p_utf8char)^0)
+ end
+ return lpegmatch(pattern,str)
+ end
+ end
+ elseif option=="pattern" then
+ return Cs((tabletopattern(mapping)/action+p_utf8char)^0)
+ else
+ local pattern=Cs((tabletopattern(mapping)/action+p_utf8char)^0)
+ return function(str)
+ if not str or str=="" then
+ return ""
+ else
+ return lpegmatch(pattern,str)
+ end
+ end,pattern
+ end
+ elseif variant=="function" then
+ if option=="pattern" then
+ return Cs((p_utf8char/mapping+p_utf8char)^0)
+ else
+ local pattern=Cs((p_utf8char/mapping+p_utf8char)^0)
+ return function(str)
+ if not str or str=="" then
+ return ""
+ else
+ return lpegmatch(pattern,str)
+ end
+ end,pattern
+ end
+ else
+ return function(str)
+ return str or ""
+ end
+ end
+end
+function utf.replacer(t)
+ local r=replacer(t,false,false,true)
+ return function(str)
+ return lpegmatch(r,str)
+ end
+end
+function utf.subtituter(t)
+ local f=finder (t)
+ local r=replacer(t,false,false,true)
+ return function(str)
+ local i=lpegmatch(f,str)
+ if not i then
+ return str
+ elseif i>#str then
+ return str
+ else
+ return lpegmatch(r,str)
+ end
+ end
+end
+local utflinesplitter=p_utfbom^-1*lpeg.tsplitat(p_newline)
+local utfcharsplitter_ows=p_utfbom^-1*Ct(C(p_utf8char)^0)
+local utfcharsplitter_iws=p_utfbom^-1*Ct((p_whitespace^1+C(p_utf8char))^0)
+local utfcharsplitter_raw=Ct(C(p_utf8char)^0)
+patterns.utflinesplitter=utflinesplitter
+function utf.splitlines(str)
+ return lpegmatch(utflinesplitter,str or "")
+end
+function utf.split(str,ignorewhitespace)
+ if ignorewhitespace then
+ return lpegmatch(utfcharsplitter_iws,str or "")
+ else
+ return lpegmatch(utfcharsplitter_ows,str or "")
+ end
+end
+function utf.totable(str)
+ return lpegmatch(utfcharsplitter_raw,str)
+end
+function utf.magic(f)
+ local str=f:read(4) or ""
+ local off=lpegmatch(p_utfoffset,str)
+ if off<4 then
+ f:seek('set',off)
+ end
+ return lpegmatch(p_utftype,str)
+end
+local utf16_to_utf8_be,utf16_to_utf8_le
+local utf32_to_utf8_be,utf32_to_utf8_le
+local utf_16_be_getbom=patterns.utfbom_16_be^-1
+local utf_16_le_getbom=patterns.utfbom_16_le^-1
+local utf_32_be_getbom=patterns.utfbom_32_be^-1
+local utf_32_le_getbom=patterns.utfbom_32_le^-1
+local utf_16_be_linesplitter=utf_16_be_getbom*lpeg.tsplitat(patterns.utf_16_be_nl)
+local utf_16_le_linesplitter=utf_16_le_getbom*lpeg.tsplitat(patterns.utf_16_le_nl)
+local utf_32_be_linesplitter=utf_32_be_getbom*lpeg.tsplitat(patterns.utf_32_be_nl)
+local utf_32_le_linesplitter=utf_32_le_getbom*lpeg.tsplitat(patterns.utf_32_le_nl)
+local more=0
+local p_utf16_to_utf8_be=C(1)*C(1)/function(left,right)
+ local now=256*byte(left)+byte(right)
+ if more>0 then
+ now=(more-0xD800)*0x400+(now-0xDC00)+0x10000
+ more=0
+ return utfchar(now)
+ elseif now>=0xD800 and now<=0xDBFF then
+ more=now
+ return ""
+ else
+ return utfchar(now)
+ end
+end
+local p_utf16_to_utf8_le=C(1)*C(1)/function(right,left)
+ local now=256*byte(left)+byte(right)
+ if more>0 then
+ now=(more-0xD800)*0x400+(now-0xDC00)+0x10000
+ more=0
+ return utfchar(now)
+ elseif now>=0xD800 and now<=0xDBFF then
+ more=now
+ return ""
+ else
+ return utfchar(now)
+ end
+end
+local p_utf32_to_utf8_be=C(1)*C(1)*C(1)*C(1)/function(a,b,c,d)
+ return utfchar(256*256*256*byte(a)+256*256*byte(b)+256*byte(c)+byte(d))
+end
+local p_utf32_to_utf8_le=C(1)*C(1)*C(1)*C(1)/function(a,b,c,d)
+ return utfchar(256*256*256*byte(d)+256*256*byte(c)+256*byte(b)+byte(a))
+end
+p_utf16_to_utf8_be=P(true)/function() more=0 end*utf_16_be_getbom*Cs(p_utf16_to_utf8_be^0)
+p_utf16_to_utf8_le=P(true)/function() more=0 end*utf_16_le_getbom*Cs(p_utf16_to_utf8_le^0)
+p_utf32_to_utf8_be=P(true)/function() more=0 end*utf_32_be_getbom*Cs(p_utf32_to_utf8_be^0)
+p_utf32_to_utf8_le=P(true)/function() more=0 end*utf_32_le_getbom*Cs(p_utf32_to_utf8_le^0)
+patterns.utf16_to_utf8_be=p_utf16_to_utf8_be
+patterns.utf16_to_utf8_le=p_utf16_to_utf8_le
+patterns.utf32_to_utf8_be=p_utf32_to_utf8_be
+patterns.utf32_to_utf8_le=p_utf32_to_utf8_le
+utf16_to_utf8_be=function(s)
+ if s and s~="" then
+ return lpegmatch(p_utf16_to_utf8_be,s)
+ else
+ return s
+ end
+end
+local utf16_to_utf8_be_t=function(t)
+ if not t then
+ return nil
+ elseif type(t)=="string" then
+ t=lpegmatch(utf_16_be_linesplitter,t)
+ end
+ for i=1,#t do
+ local s=t[i]
+ if s~="" then
+ t[i]=lpegmatch(p_utf16_to_utf8_be,s)
+ end
+ end
+ return t
+end
+utf16_to_utf8_le=function(s)
+ if s and s~="" then
+ return lpegmatch(p_utf16_to_utf8_le,s)
+ else
+ return s
+ end
+end
+local utf16_to_utf8_le_t=function(t)
+ if not t then
+ return nil
+ elseif type(t)=="string" then
+ t=lpegmatch(utf_16_le_linesplitter,t)
+ end
+ for i=1,#t do
+ local s=t[i]
+ if s~="" then
+ t[i]=lpegmatch(p_utf16_to_utf8_le,s)
+ end
+ end
+ return t
+end
+utf32_to_utf8_be=function(s)
+ if s and s~="" then
+ return lpegmatch(p_utf32_to_utf8_be,s)
+ else
+ return s
+ end
+end
+local utf32_to_utf8_be_t=function(t)
+ if not t then
+ return nil
+ elseif type(t)=="string" then
+ t=lpegmatch(utf_32_be_linesplitter,t)
+ end
+ for i=1,#t do
+ local s=t[i]
+ if s~="" then
+ t[i]=lpegmatch(p_utf32_to_utf8_be,s)
+ end
+ end
+ return t
+end
+utf32_to_utf8_le=function(s)
+ if s and s~="" then
+ return lpegmatch(p_utf32_to_utf8_le,s)
+ else
+ return s
+ end
+end
+local utf32_to_utf8_le_t=function(t)
+ if not t then
+ return nil
+ elseif type(t)=="string" then
+ t=lpegmatch(utf_32_le_linesplitter,t)
+ end
+ for i=1,#t do
+ local s=t[i]
+ if s~="" then
+ t[i]=lpegmatch(p_utf32_to_utf8_le,s)
+ end
+ end
+ return t
+end
+utf.utf16_to_utf8_le_t=utf16_to_utf8_le_t
+utf.utf16_to_utf8_be_t=utf16_to_utf8_be_t
+utf.utf32_to_utf8_le_t=utf32_to_utf8_le_t
+utf.utf32_to_utf8_be_t=utf32_to_utf8_be_t
+utf.utf16_to_utf8_le=utf16_to_utf8_le
+utf.utf16_to_utf8_be=utf16_to_utf8_be
+utf.utf32_to_utf8_le=utf32_to_utf8_le
+utf.utf32_to_utf8_be=utf32_to_utf8_be
+function utf.utf8_to_utf8_t(t)
+ return type(t)=="string" and lpegmatch(utflinesplitter,t) or t
+end
+function utf.utf16_to_utf8_t(t,endian)
+ return endian and utf16_to_utf8_be_t(t) or utf16_to_utf8_le_t(t) or t
+end
+function utf.utf32_to_utf8_t(t,endian)
+ return endian and utf32_to_utf8_be_t(t) or utf32_to_utf8_le_t(t) or t
+end
+local function little(b)
+ if b<0x10000 then
+ return char(b%256,b/256)
+ else
+ b=b-0x10000
+ local b1,b2=b/1024+0xD800,b%1024+0xDC00
+ return char(b1%256,b1/256,b2%256,b2/256)
+ end
+end
+local function big(b)
+ if b<0x10000 then
+ return char(b/256,b%256)
+ else
+ b=b-0x10000
+ local b1,b2=b/1024+0xD800,b%1024+0xDC00
+ return char(b1/256,b1%256,b2/256,b2%256)
+ end
+end
+local l_remap=Cs((p_utf8byte/little+P(1)/"")^0)
+local b_remap=Cs((p_utf8byte/big+P(1)/"")^0)
+local function utf8_to_utf16_be(str,nobom)
+ if nobom then
+ return lpegmatch(b_remap,str)
+ else
+ return char(254,255)..lpegmatch(b_remap,str)
+ end
+end
+local function utf8_to_utf16_le(str,nobom)
+ if nobom then
+ return lpegmatch(l_remap,str)
+ else
+ return char(255,254)..lpegmatch(l_remap,str)
+ end
+end
+utf.utf8_to_utf16_be=utf8_to_utf16_be
+utf.utf8_to_utf16_le=utf8_to_utf16_le
+function utf.utf8_to_utf16(str,littleendian,nobom)
+ if littleendian then
+ return utf8_to_utf16_le(str,nobom)
+ else
+ return utf8_to_utf16_be(str,nobom)
+ end
+end
+local pattern=Cs (
+ (p_utf8byte/function(unicode ) return format("0x%04X",unicode) end)*(p_utf8byte*Carg(1)/function(unicode,separator) return format("%s0x%04X",separator,unicode) end)^0
+)
+function utf.tocodes(str,separator)
+ return lpegmatch(pattern,str,1,separator or " ")
+end
+function utf.ustring(s)
+ return format("U+%05X",type(s)=="number" and s or utfbyte(s))
+end
+function utf.xstring(s)
+ return format("0x%05X",type(s)=="number" and s or utfbyte(s))
+end
+function utf.toeight(str)
+ if not str or str=="" then
+ return nil
+ end
+ local utftype=lpegmatch(p_utfstricttype,str)
+ if utftype=="utf-8" then
+ return sub(str,4)
+ elseif utftype=="utf-16-be" then
+ return utf16_to_utf8_be(str)
+ elseif utftype=="utf-16-le" then
+ return utf16_to_utf8_le(str)
+ else
+ return str
+ end
+end
+local p_nany=p_utf8char/""
+if utfgmatch then
+ function utf.count(str,what)
+ if type(what)=="string" then
+ local n=0
+ for _ in utfgmatch(str,what) do
+ n=n+1
+ end
+ return n
+ else
+ return #lpegmatch(Cs((P(what)/" "+p_nany)^0),str)
+ end
+ end
+else
+ local cache={}
+ function utf.count(str,what)
+ if type(what)=="string" then
+ local p=cache[what]
+ if not p then
+ p=Cs((P(what)/" "+p_nany)^0)
+ cache[p]=p
+ end
+ return #lpegmatch(p,str)
+ else
+ return #lpegmatch(Cs((P(what)/" "+p_nany)^0),str)
+ end
+ end
+end
+if not utf.characters then
+ function utf.characters(str)
+ return gmatch(str,".[\128-\191]*")
+ end
+ string.utfcharacters=utf.characters
+end
+if not utf.values then
+ local find=string.find
+ local dummy=function()
+ end
+ function utf.values(str)
+ local n=#str
+ if n==0 then
+ return dummy
+ elseif n==1 then
+ return function() return utfbyte(str) end
+ else
+ local p=1
+ return function()
+ local b,e=find(str,".[\128-\191]*",p)
+ if b then
+ p=e+1
+ return utfbyte(sub(str,b,e))
+ end
+ end
+ end
+ end
+ string.utfvalues=utf.values
+end
+function utf.chrlen(u)
+ return
+ (u<0x80 and 1) or
+ (u<0xE0 and 2) or
+ (u<0xF0 and 3) or
+ (u<0xF8 and 4) or
+ (u<0xFC and 5) or
+ (u<0xFE and 6) or 0
+end
+
+end -- closure
+
+do -- begin closure to overcome local limits and interference
+
if not modules then modules={} end modules ['util-str']={
version=1.001,
comment="companion to luat-lib.mkiv",
@@ -5890,15 +6504,11 @@ hashmethods.normal=function(list)
elseif k=="number" or k=="features" then
else
n=n+1
- s[n]=k
+ s[n]=k..'='..tostring(v)
end
end
if n>0 then
sort(s)
- for i=1,n do
- local k=s[i]
- s[i]=k..'='..tostring(list[k])
- end
return concat(s,"+")
end
end
@@ -6045,7 +6655,10 @@ function constructors.getfeatureaction(what,where,mode,name)
end
end
end
-function constructors.newhandler(what)
+local newhandler={}
+constructors.handlers=newhandler
+constructors.newhandler=newhandler
+local function setnewhandler(what)
local handler=handlers[what]
if not handler then
handler={}
@@ -6053,7 +6666,14 @@ function constructors.newhandler(what)
end
return handler
end
-function constructors.newfeatures(what)
+setmetatable(newhandler,{
+ __call=function(t,k) local v=t[k] return v end,
+ __index=function(t,k) local v=setnewhandler(k) t[k]=v return v end,
+})
+local newfeatures={}
+constructors.newfeatures=newfeatures
+constructors.features=newfeatures
+local function setnewfeatures(what)
local handler=handlers[what]
local features=handler.features
if not features then
@@ -6072,6 +6692,10 @@ function constructors.newfeatures(what)
end
return features
end
+setmetatable(newfeatures,{
+ __call=function(t,k) local v=t[k] return v end,
+ __index=function(t,k) local v=setnewfeatures(k) t[k]=v return v end,
+})
function constructors.checkedfeatures(what,features)
local defaults=handlers[what].features.defaults
if features and next(features) then
@@ -6440,7 +7064,7 @@ local function makenameparser(str)
end
local f_single=formatters["%04X"]
local f_double=formatters["%04X%04X"]
-local function tounicode16(unicode,name)
+local function tounicode16(unicode)
if unicode<0xD7FF or (unicode>0xDFFF and unicode<=0xFFFF) then
return f_single(unicode)
else
@@ -6448,7 +7072,7 @@ local function tounicode16(unicode,name)
return f_double(floor(unicode/1024)+0xD800,unicode%1024+0xDC00)
end
end
-local function tounicode16sequence(unicodes,name)
+local function tounicode16sequence(unicodes)
local t={}
for l=1,#unicodes do
local u=unicodes[l]
@@ -6836,11 +7460,11 @@ local handlers=fonts.handlers
local readers=fonts.readers
local constructors=fonts.constructors
local encodings=fonts.encodings
-local tfm=constructors.newhandler("tfm")
+local tfm=constructors.handlers.tfm
tfm.version=1.000
tfm.maxnestingdepth=5
tfm.maxnestingsize=65536*1024
-local tfmfeatures=constructors.newfeatures("tfm")
+local tfmfeatures=constructors.features.tfm
constructors.resolvevirtualtoo=false
fonts.formats.tfm="type1"
fonts.formats.ofm="type1"
@@ -6985,8 +7609,8 @@ if not modules then modules={} end modules ['font-oti']={
local lower=string.lower
local fonts=fonts
local constructors=fonts.constructors
-local otf=constructors.newhandler("otf")
-local otffeatures=constructors.newfeatures("otf")
+local otf=constructors.handlers.otf
+local otffeatures=constructors.features.otf
local registerotffeature=otffeatures.register
local otftables=otf.tables or {}
otf.tables=otftables
@@ -7172,8 +7796,8 @@ local function readlongdatetime(f)
return 0x100000000*d+0x1000000*e+0x10000*f+0x100*g+h
end
local tableversion=0.004
-local privateoffset=fonts.constructors and fonts.constructors.privateoffset or 0xF0000
readers.tableversion=tableversion
+local privateoffset=fonts.constructors and fonts.constructors.privateoffset or 0xF0000
local reportedskipped={}
local function reportskippedtable(tag)
if not reportedskipped[tag] then
@@ -8177,6 +8801,21 @@ function readers.glyf(f,fontdata,specification)
reportskippedtable("glyf")
end
end
+function readers.colr(f,fontdata,specification)
+ if specification.details then
+ reportskippedtable("colr")
+ end
+end
+function readers.cpal(f,fontdata,specification)
+ if specification.details then
+ reportskippedtable("cpal")
+ end
+end
+function readers.svg(f,fontdata,specification)
+ if specification.details then
+ reportskippedtable("svg")
+ end
+end
function readers.kern(f,fontdata,specification)
if specification.kerns then
local datatable=fontdata.tables.kern
@@ -8485,6 +9124,9 @@ local function readdata(f,offset,specification)
readers["cmap"](f,fontdata,specification)
readers["loca"](f,fontdata,specification)
readers["glyf"](f,fontdata,specification)
+ readers["colr"](f,fontdata,specification)
+ readers["cpal"](f,fontdata,specification)
+ readers["svg" ](f,fontdata,specification)
readers["kern"](f,fontdata,specification)
readers["gdef"](f,fontdata,specification)
readers["gsub"](f,fontdata,specification)
@@ -8640,6 +9282,7 @@ function readers.loadfont(filename,n)
metadata=getinfo(fontdata,n),
properties={
hasitalics=fontdata.hasitalics or false,
+ maxcolorclass=fontdata.maxcolorclass,
},
resources={
filename=filename,
@@ -8655,6 +9298,8 @@ function readers.loadfont(filename,n)
version=getname(fontdata,"version"),
cidinfo=fontdata.cidinfo,
mathconstants=fontdata.mathconstants,
+ colorpalettes=fontdata.colorpalettes,
+ svgshapes=fontdata.svgshapes,
},
}
end
@@ -10603,6 +11248,7 @@ local readshort=streamreader.readinteger2
local readfword=readshort
local readstring=streamreader.readstring
local readtag=streamreader.readtag
+local readbytes=streamreader.readbytes
local gsubhandlers={}
local gposhandlers={}
local lookupidoffset=-1
@@ -12502,7 +13148,7 @@ function readers.math(f,fontdata,specification)
setposition(f,tableoffset)
local version=readulong(f)
if version~=0x00010000 then
- report("table version %a of %a is not supported (yet), maybe font %s is bad",version,what,fontdata.filename)
+ report("table version %a of %a is not supported (yet), maybe font %s is bad",version,"math",fontdata.filename)
return
end
local constants=readushort(f)
@@ -12522,6 +13168,140 @@ function readers.math(f,fontdata,specification)
end
end
end
+function readers.colr(f,fontdata,specification)
+ if specification.details then
+ local datatable=fontdata.tables.colr
+ if datatable then
+ local tableoffset=datatable.offset
+ setposition(f,tableoffset)
+ local version=readushort(f)
+ if version~=0 then
+ report("table version %a of %a is not supported (yet), maybe font %s is bad",version,"colr",fontdata.filename)
+ return
+ end
+ if not fontdata.tables.cpal then
+ report("color table %a in font %a has no mandate %a table","colr",fontdata.filename,"cpal")
+ fontdata.colorpalettes={}
+ end
+ local glyphs=fontdata.glyphs
+ local nofglyphs=readushort(f)
+ local baseoffset=readulong(f)
+ local layeroffset=readulong(f)
+ local noflayers=readushort(f)
+ local layerrecords={}
+ local maxclass=0
+ setposition(f,tableoffset+layeroffset)
+ for i=1,noflayers do
+ local slot=readushort(f)
+ local class=readushort(f)
+ if class<0xFFFF then
+ class=class+1
+ if class>maxclass then
+ maxclass=class
+ end
+ end
+ layerrecords[i]={
+ slot=slot,
+ class=class,
+ }
+ end
+ fontdata.maxcolorclass=maxclass
+ setposition(f,tableoffset+baseoffset)
+ for i=0,nofglyphs-1 do
+ local glyphindex=readushort(f)
+ local firstlayer=readushort(f)
+ local noflayers=readushort(f)
+ local t={}
+ for i=1,noflayers do
+ t[i]=layerrecords[firstlayer+i]
+ end
+ glyphs[glyphindex].colors=t
+ end
+ end
+ end
+end
+function readers.cpal(f,fontdata,specification)
+ if specification.details then
+ local datatable=fontdata.tables.cpal
+ if datatable then
+ local tableoffset=datatable.offset
+ setposition(f,tableoffset)
+ local version=readushort(f)
+ if version>1 then
+ report("table version %a of %a is not supported (yet), maybe font %s is bad",version,"cpal",fontdata.filename)
+ return
+ end
+ local nofpaletteentries=readushort(f)
+ local nofpalettes=readushort(f)
+ local nofcolorrecords=readushort(f)
+ local firstcoloroffset=readulong(f)
+ local colorrecords={}
+ local palettes={}
+ for i=1,nofpalettes do
+ palettes[i]=readushort(f)
+ end
+ if version==1 then
+ local palettettypesoffset=readulong(f)
+ local palettelabelsoffset=readulong(f)
+ local paletteentryoffset=readulong(f)
+ end
+ setposition(f,tableoffset+firstcoloroffset)
+ for i=1,nofcolorrecords do
+ local b,g,r,a=readbytes(f,4)
+ colorrecords[i]={
+ r,g,b,a~=255 and a or nil,
+ }
+ end
+ for i=1,nofpalettes do
+ local p={}
+ local o=palettes[i]
+ for j=1,nofpaletteentries do
+ p[j]=colorrecords[o+j]
+ end
+ palettes[i]=p
+ end
+ fontdata.colorpalettes=palettes
+ end
+ end
+end
+function readers.svg(f,fontdata,specification)
+ if specification.details then
+ local datatable=fontdata.tables.svg
+ if datatable then
+ local tableoffset=datatable.offset
+ setposition(f,tableoffset)
+ local version=readushort(f)
+ if version~=0 then
+ report("table version %a of %a is not supported (yet), maybe font %s is bad",version,"svg",fontdata.filename)
+ return
+ end
+ local glyphs=fontdata.glyphs
+ local indexoffset=tableoffset+readulong(f)
+ local reserved=readulong(f)
+ setposition(f,indexoffset)
+ local nofentries=readushort(f)
+ local entries={}
+ for i=1,nofentries do
+ entries[i]={
+ first=readushort(f),
+ last=readushort(f),
+ offset=indexoffset+readulong(f),
+ length=readulong(f),
+ }
+ end
+ for i=1,nofentries do
+ local entry=entries[i]
+ setposition(f,entry.offset)
+ entries[i]={
+ first=entry.first,
+ last=entry.last,
+ data=readstring(f,entry.length)
+ }
+ end
+ fontdata.svgshapes=entries
+ end
+ end
+end
end -- closure
@@ -13179,6 +13959,18 @@ local function unifyglyphs(fontdata,usenames)
end
end
end
+ local colorpalettes=resources.colorpalettes
+ if colorpalettes then
+ for index=1,#glyphs do
+ local colors=glyphs[index].colors
+ if colors then
+ for i=1,#colors do
+ local c=colors[i]
+ c.slot=indices[c.slot]
+ end
+ end
+ end
+ end
fontdata.private=private
fontdata.glyphs=nil
fontdata.names=names
@@ -13579,6 +14371,7 @@ function readers.pack(data)
local sequences=resources.sequences
local sublookups=resources.sublookups
local features=resources.features
+ local palettes=resources.colorpalettes
local chardata=characters and characters.data
local descriptions=data.descriptions or data.glyphs
if not descriptions then
@@ -13721,6 +14514,14 @@ function readers.pack(data)
end
end
end
+ if palettes then
+ for i=1,#palettes do
+ local p=palettes[i]
+ for j=1,#p do
+ p[j]=pack_indexed(p[j])
+ end
+ end
+ end
if not success(1,pass) then
return
end
@@ -13841,6 +14642,7 @@ function readers.unpack(data)
local sequences=resources.sequences
local sublookups=resources.sublookups
local features=resources.features
+ local palettes=resources.colorpalettes
local unpacked={}
setmetatable(unpacked,unpacked_mt)
for unicode,description in next,descriptions do
@@ -14079,6 +14881,17 @@ function readers.unpack(data)
end
end
end
+ if palettes then
+ for i=1,#palettes do
+ local p=palettes[i]
+ for j=1,#p do
+ local tv=tables[p[j]]
+ if tv then
+ p[j]=tv
+ end
+ end
+ end
+ end
data.tables=nil
end
end
@@ -14532,14 +15345,17 @@ 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.021
+otf.version=3.022
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)
+otf.svgenabled=false
local otfreaders=otf.readers
local hashes=fonts.hashes
local definers=fonts.definers
local readers=fonts.readers
local constructors=fonts.constructors
-local otffeatures=constructors.newfeatures("otf")
+local otffeatures=constructors.features.otf
local registerotffeature=otffeatures.register
local enhancers=allocate()
otf.enhancers=enhancers
@@ -14679,6 +15495,22 @@ function otf.load(filename,sub,featurefile)
starttiming(otfreaders)
data=otfreaders.loadfont(filename,sub or 1)
if data then
+ local resources=data.resources
+ local svgshapes=resources.svgshapes
+ if svgshapes then
+ resources.svgshapes=nil
+ if otf.svgenabled then
+ local timestamp=os.date()
+ containers.write(otf.svgcache,hash,{
+ svgshapes=svgshapes,
+ timestamp=timestamp,
+ })
+ data.properties.svg={
+ hash=hash,
+ timestamp=timestamp,
+ }
+ end
+ end
otfreaders.compact(data)
otfreaders.rehash(data,"unicodes")
otfreaders.addunicodetable(data)
@@ -14732,7 +15564,6 @@ end
local function copytotfm(data,cache_id)
if data then
local metadata=data.metadata
- local resources=data.resources
local properties=derivetable(data.properties)
local descriptions=derivetable(data.descriptions)
local goodies=derivetable(data.goodies)
@@ -16893,7 +17724,7 @@ local math_code=nodecodes.math
local fontdata=fonts.hashes.identifiers
local categories=characters and characters.categories or {}
local chardata=characters and characters.data
-local otffeatures=fonts.constructors.newfeatures("otf")
+local otffeatures=fonts.constructors.features.otf
local registerotffeature=otffeatures.register
local s_init=1 local s_rphf=7
local s_medi=2 local s_half=8
@@ -17258,7 +18089,6 @@ local trace_cursive=false registertracker("otf.cursive",function(v) trace_cursiv
local trace_preparing=false registertracker("otf.preparing",function(v) trace_preparing=v end)
local trace_bugs=false registertracker("otf.bugs",function(v) trace_bugs=v end)
local trace_details=false registertracker("otf.details",function(v) trace_details=v end)
-local trace_applied=false registertracker("otf.applied",function(v) trace_applied=v end)
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)
@@ -17346,7 +18176,7 @@ local getligaindex=injections.getligaindex
local cursonce=true
local fonthashes=fonts.hashes
local fontdata=fonthashes.identifiers
-local otffeatures=fonts.constructors.newfeatures("otf")
+local otffeatures=fonts.constructors.features.otf
local registerotffeature=otffeatures.register
local onetimemessage=fonts.loggers.onetimemessage or function() end
otf.defaultnodealternate="none"
@@ -19960,9 +20790,6 @@ local function featuresprocessor(head,font,attr)
nesting=nesting-1
return head,false
end
- if attr==0 then
- attr=false
- end
head=tonut(head)
if trace_steps then
checkstep(head)
@@ -20318,7 +21145,7 @@ fonts.analyzers.methods=fonts.analyzers.methods or { node={ otf={} } }
local otf=fonts.handlers.otf
local handlers=otf.handlers
local methods=fonts.analyzers.methods
-local otffeatures=fonts.constructors.newfeatures("otf")
+local otffeatures=fonts.constructors.features.otf
local registerotffeature=otffeatures.register
local nuts=nodes.nuts
local tonode=nuts.tonode
@@ -22271,6 +23098,250 @@ end -- closure
do -- begin closure to overcome local limits and interference
+if not modules then modules={} end modules ['font-ocl']={
+ version=1.001,
+ comment="companion to font-otf.lua (context)",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local formatters=string.formatters
+local otf=fonts.handlers.otf
+local f_color_start=formatters["pdf:direct: %f %f %f rg"]
+local s_color_stop="pdf:direct:"
+if context then
+ local startactualtext=nil
+ local stopactualtext=nil
+ function otf.getactualtext(n)
+ if not startactualtext then
+ startactualtext=backends.codeinjections.startunicodetoactualtext
+ stopactualtext=backends.codeinjections.stopunicodetoactualtext
+ end
+ return startactualtext(n),stopactualtext()
+ end
+else
+ local tounicode=fonts.mappings.tounicode16
+ function otf.getactualtext(n)
+ return "/Span << /ActualText >> BDC","EMC"
+ end
+end
+local function initializecolr(tfmdata,kind,value)
+ if value then
+ local palettes=tfmdata.resources.colorpalettes
+ if palettes then
+ local palette=palettes[tonumber(value) or 1] or palettes[1] or {}
+ local classes=#palette
+ if classes==0 then
+ return
+ end
+ local characters=tfmdata.characters
+ local descriptions=tfmdata.descriptions
+ local properties=tfmdata.properties
+ local colorvalues={}
+ properties.virtualized=true
+ tfmdata.fonts={
+ { id=0 }
+ }
+ for i=1,classes do
+ local p=palette[i]
+ colorvalues[i]={ "special",f_color_start(p[1]/255,p[2]/255,p[3]/255) }
+ end
+ local getactualtext=otf.getactualtext
+ for unicode,character in next,characters do
+ local description=descriptions[unicode]
+ if description then
+ local colorlist=description.colors
+ if colorlist then
+ local b,e=getactualtext(unicode)
+ local w=character.width or 0
+ local s=#colorlist
+ local n=1
+ local t={
+ { "special","pdf:direct: q "..b }
+ }
+ for i=1,s do
+ local entry=colorlist[i]
+ n=n+1 t[n]=colorvalues[entry.class]
+ n=n+1 t[n]={ "char",entry.slot }
+ if s>1 and itestrun then
+ report_svg("quiting test run")
+ break
+ end
+ end
+ os.remove(svgfile)
+ 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
+ end
+ os.remove(svgfile)
+ texio.write("done]")
+ return pdfshapes
+ end
+end
+local function initializesvg(tfmdata,kind,value)
+ if value and otf.svgenabled then
+ local characters=tfmdata.characters
+ local descriptions=tfmdata.descriptions
+ local properties=tfmdata.properties
+ local svg=properties.svg
+ local hash=svg and svg.hash
+ local timestamp=svg and svg.timestamp
+ if not hash then
+ return
+ end
+ local pdffile=containers.read(otf.pdfcache,hash)
+ local pdfshapes=pdffile and pdffile.pdfshapes
+ if not pdfshapes or pdffile.timestamp~=timestamp then
+ local svgfile=containers.read(otf.svgcache,hash)
+ local svgshapes=svgfile and svgfile.svgshapes
+ pdfshapes=svgshapes and otfsvg.topdf(svgshapes) or {}
+ containers.write(otf.pdfcache,hash,{
+ pdfshapes=pdfshapes,
+ timestamp=timestamp,
+ })
+ end
+ if not pdfshapes or not next(pdfshapes) then
+ return
+ end
+ properties.virtualized=true
+ tfmdata.fonts={
+ { id=0 }
+ }
+ local getactualtext=otf.getactualtext
+ local storepdfdata=otfsvg.storepdfdata
+ local nop={ "nop" }
+ for unicode,character in next,characters do
+ local index=character.index
+ if index then
+ local pdf=pdfshapes[index]
+ if pdf then
+ local setcode,name,nilcode=storepdfdata(pdf)
+ if name then
+ local bt,et=getactualtext(unicode)
+ local wd=character.width or 0
+ local ht=character.height or 0
+ local dp=character.depth or 0
+ character.commands={
+ { "special","pdf:direct:"..bt },
+ { "down",dp },
+ setcode and { "lua",setcode } or nop,
+ { "image",{ filename=name,width=wd,height=ht,depth=dp } },
+ nilcode and { "lua",nilcode } or nop,
+ { "special","pdf:direct:"..et },
+ }
+ character.svg=true
+ end
+ end
+ end
+ end
+ end
+end
+fonts.handlers.otf.features.register {
+ name="svg",
+ description="svg glyphs",
+ manipulators={
+ base=initializesvg,
+ node=initializesvg,
+ }
+}
+
+end -- closure
+
+do -- begin closure to overcome local limits and interference
+
if not modules then modules={} end modules ['font-onr']={
version=1.001,
comment="companion to font-ini.mkiv",
@@ -22569,12 +23640,12 @@ local findbinfile=resolvers.findbinfile
local definers=fonts.definers
local readers=fonts.readers
local constructors=fonts.constructors
-local afm=constructors.newhandler("afm")
-local pfb=constructors.newhandler("pfb")
+local afm=constructors.handlers.afm
+local pfb=constructors.handlers.pfb
local otf=fonts.handlers.otf
local otfreaders=otf.readers
local otfenhancers=otf.enhancers
-local afmfeatures=constructors.newfeatures("afm")
+local afmfeatures=constructors.features.afm
local registerafmfeature=afmfeatures.register
afm.version=1.512
afm.cache=containers.define("fonts","afm",afm.version,true)
@@ -23901,7 +24972,7 @@ if context then
os.exit()
end
local fonts=fonts
-local otffeatures=fonts.constructors.newfeatures("otf")
+local otffeatures=fonts.constructors.features.otf
local function initializeitlc(tfmdata,value)
if value then
local parameters=tfmdata.parameters
--
cgit v1.2.3
From f167b470d1831575735694406eca44963f76cb3f Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Sun, 12 Jun 2016 18:18:43 +0200
Subject: [fontloader] import font-ocl
Some of the more absurd aspects of fonts ;) This will fork inkscape for
the actual SVG processing.
---
doc/filegraph.dot | 3 +
doc/luaotfload-main.tex | 1 +
scripts/mkimport | 19 +-
scripts/mkstatus | 1 +
src/fontloader/misc/fontloader-font-ocl.lua | 297 ++++++++++++++++++++++++++++
src/luaotfload-init.lua | 2 +
6 files changed, 315 insertions(+), 8 deletions(-)
create mode 100644 src/fontloader/misc/fontloader-font-ocl.lua
diff --git a/doc/filegraph.dot b/doc/filegraph.dot
index 0c2dad1..34c462a 100644
--- a/doc/filegraph.dot
+++ b/doc/filegraph.dot
@@ -385,6 +385,9 @@ strict digraph luaotfload_files { //looks weird with circo ...
font-xtx.lua |
font-gbn.lua |
+
+ font-ocl.lua |
+
>,
]
diff --git a/doc/luaotfload-main.tex b/doc/luaotfload-main.tex
index bebb7df..e238901 100644
--- a/doc/luaotfload-main.tex
+++ b/doc/luaotfload-main.tex
@@ -1293,6 +1293,7 @@ grouped twofold as below:
\beginaltitem{font-ota.lua} \endaltitem
\beginaltitem{font-ots.lua} \endaltitem
\beginaltitem{font-osd.lua} \endaltitem
+ \beginaltitem{font-ocl.lua} \endaltitem
\beginaltitem{font-lua.lua} \endaltitem
\beginaltitem{font-def.lua} \endaltitem
\beginaltitem{font-xtx.lua} \endaltitem
diff --git a/scripts/mkimport b/scripts/mkimport
index 93f4b89..1dc0a29 100755
--- a/scripts/mkimport
+++ b/scripts/mkimport
@@ -237,6 +237,7 @@ local imports = {
{ name = "font-ini" , ours = "font-ini" , kind = kind_merged },
{ name = "font-lua" , ours = "font-lua" , kind = kind_merged },
{ name = "font-map" , ours = "font-map" , kind = kind_merged },
+ { name = "font-ocl" , ours = "font-ocl" , kind = kind_merged },
{ name = "font-onr" , ours = "font-onr" , kind = kind_merged },
{ name = "font-one" , ours = "font-one" , kind = kind_merged },
{ name = "font-osd" , ours = "font-osd" , kind = kind_merged },
@@ -307,14 +308,15 @@ local package = {
--- [32] font-ota.lua
--- [33] font-ots.lua
--- [34] font-osd.lua
---- [35] font-onr.lua
---- [36] font-one.lua
---- [37] font-afk.lua
---- [38] font-lua.lua
---- [39] font-def.lua
---- [40] font-xtx.lua
---- [41] luatex-fonts-ext.lua
---- [42] font-gbn.lua
+--- [35] font-ocl.lua
+--- [36] font-onr.lua
+--- [37] font-one.lua
+--- [38] font-afk.lua
+--- [39] font-lua.lua
+--- [40] font-def.lua
+--- [41] font-xtx.lua
+--- [42] luatex-fonts-ext.lua
+--- [43] font-gbn.lua
---
--- Of these, nos. 01--11 are provided by the Lualibs. Keeping them
--- around in the Luaotfload fontloader is therefore unnecessary.
@@ -372,6 +374,7 @@ local package = {
"font-ota",
"font-ots",
"font-osd",
+ "font-ocl",
"font-onr",
"font-one",
"font-afk",
diff --git a/scripts/mkstatus b/scripts/mkstatus
index 5b29913..10f6680 100755
--- a/scripts/mkstatus
+++ b/scripts/mkstatus
@@ -113,6 +113,7 @@ local names = {
{ miscdir, "fontloader-font-ota.lua", },
{ miscdir, "fontloader-font-ots.lua", },
{ miscdir, "fontloader-font-osd.lua", },
+ { miscdir, "fontloader-font-ocl.lua", },
--- lua libraries
{ miscdir, "fontloader-languages.lua", },
diff --git a/src/fontloader/misc/fontloader-font-ocl.lua b/src/fontloader/misc/fontloader-font-ocl.lua
new file mode 100644
index 0000000..9661083
--- /dev/null
+++ b/src/fontloader/misc/fontloader-font-ocl.lua
@@ -0,0 +1,297 @@
+if not modules then modules = { } end modules ['font-ocl'] = {
+ version = 1.001,
+ comment = "companion to font-otf.lua (context)",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo : user list of colors
+
+local formatters = string.formatters
+
+local otf = fonts.handlers.otf
+
+local f_color_start = formatters["pdf:direct: %f %f %f rg"]
+local s_color_stop = "pdf:direct:"
+
+if context then
+
+ local startactualtext = nil
+ local stopactualtext = nil
+
+ function otf.getactualtext(n)
+ if not startactualtext then
+ startactualtext = backends.codeinjections.startunicodetoactualtext
+ stopactualtext = backends.codeinjections.stopunicodetoactualtext
+ end
+ return startactualtext(n), stopactualtext()
+ end
+
+else
+
+ local tounicode = fonts.mappings.tounicode16
+
+ function otf.getactualtext(n)
+ return "/Span << /ActualText >> BDC", "EMC"
+ end
+
+end
+
+local function initializecolr(tfmdata,kind,value) -- hm, always value
+ if value then
+ local palettes = tfmdata.resources.colorpalettes
+ if palettes then
+ --
+ local palette = palettes[tonumber(value) or 1] or palettes[1] or { }
+ local classes = #palette
+ if classes == 0 then
+ return
+ end
+ --
+ local characters = tfmdata.characters
+ local descriptions = tfmdata.descriptions
+ local properties = tfmdata.properties
+ local colorvalues = { }
+ --
+ properties.virtualized = true
+ tfmdata.fonts = {
+ { id = 0 }
+ }
+ --
+ for i=1,classes do
+ local p = palette[i]
+ colorvalues[i] = { "special", f_color_start(p[1]/255,p[2]/255,p[3]/255) }
+ end
+ --
+ local getactualtext = otf.getactualtext
+ --
+ for unicode, character in next, characters do
+ local description = descriptions[unicode]
+ if description then
+ local colorlist = description.colors
+ if colorlist then
+ local b, e = getactualtext(unicode)
+ local w = character.width or 0
+ local s = #colorlist
+ local n = 1
+ local t = {
+ { "special", "pdf:direct: q " .. b }
+ }
+ for i=1,s do
+ local entry = colorlist[i]
+ n = n + 1 t[n] = colorvalues[entry.class]
+ n = n + 1 t[n] = { "char", entry.slot }
+ if s > 1 and i < s and w ~= 0 then
+ n = n + 1 t[n] = { "right", -w }
+ end
+ end
+ n = n + 1 t[n] = { "special", "pdf:direct:" .. e .. " Q" }
+ character.commands = t
+ end
+ end
+ end
+ end
+ end
+end
+
+fonts.handlers.otf.features.register {
+ name = "colr",
+ description = "color glyphs",
+ manipulators = {
+ base = initializecolr,
+ node = initializecolr,
+ }
+}
+
+local otfsvg = otf.svg or { }
+otf.svg = otfsvg
+otf.svgenabled = true
+
+do
+
+ local nofstreams = 0
+
+ -- local f_setstream = formatters[ [[io.savedata("svg-glyph-%05i",%q)]] ]
+ -- local f_getstream = formatters[ [[svg-glyph-%05i]] ]
+
+ -- function otfsvg.storepdfdata(pdf)
+ -- nofstreams = nofstreams + 1
+ -- storepdfdata = function(pdf)
+ -- nofstreams = nofstreams + 1
+ -- return f_setstream(nofstreams,pdf), f_getstream(nofstreams)
+ -- end
+ -- end
+
+ local f_name = formatters[ [[svg-glyph-%05i]] ]
+ local f_used = context and formatters[ [[original:///%s]] ] or formatters[ [[%s]] ]
+
+ local cache = { }
+
+ function otfsvg.storepdfdata(pdf)
+ nofstreams = nofstreams + 1
+ local o, n = epdf.openMemStream(pdf,#pdf,f_name(nofstreams))
+ cache[n] = o -- we need to keep in mem
+ return nil, f_used(n), nil
+ end
+
+ if context then
+
+ local storepdfdata = otfsvg.storepdfdata
+ local initialized = false
+
+ function otfsvg.storepdfdata(pdf)
+ if not initialized then
+ if resolvers.setmemstream then
+ local f_setstream = formatters[ [[resolvers.setmemstream("svg-glyph-%05i",%q,true)]] ]
+ local f_getstream = formatters[ [[memstream:///svg-glyph-%05i]] ]
+ local f_nilstream = formatters[ [[resolvers.resetmemstream("svg-glyph-%05i",true)]] ]
+ storepdfdata = function(pdf)
+ nofstreams = nofstreams + 1
+ return
+ f_setstream(nofstreams,pdf),
+ f_getstream(nofstreams),
+ f_nilstream(nofstreams)
+ end
+ otfsvg.storepdfdata = storepdfdata
+ end
+ initialized = true
+ end
+ return storepdfdata(pdf)
+ end
+
+ end
+
+end
+
+if context and xml.convert then
+
+ local report_svg = logs.reporter("fonts","svg conversion")
+
+ 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 command = [[python "c:\Users\Hans Hagen\AppData\Roaming\Python\Scripts\cairosvg" -f pdf ]] .. svgfile .. " -o " .. pdffile
+ local testrun = false
+ local pdfshapes = { }
+ local nofshapes = #svgshapes
+ report_svg("processing %i svg containers",nofshapes)
+ for i=1,nofshapes do
+ local entry = svgshapes[i]
+ for j=entry.first,entry.last do
+ local svg = xml.convert(entry.data)
+ local data = xml.first(svg,"/svg[@id='glyph"..j.."']")
+ io.savedata(svgfile,tostring(data))
+ report_svg("processing svg shape of glyph %i in container %i",j,i)
+ os.execute(command)
+ pdfshapes[j] = io.loaddata(pdffile)
+ end
+ if testrun and i > testrun then
+ report_svg("quiting test run")
+ break
+ end
+ end
+ os.remove(svgfile)
+ 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
+ -- cross our fingers .. some, day i will filter
+ texio.write(formatters["%i "](j))
+ io.savedata(svgfile,tostring(entry.data))
+ os.execute(command)
+ pdfshapes[j] = io.loaddata(pdffile)
+ end
+ end
+ os.remove(svgfile)
+ texio.write("done]")
+ return pdfshapes
+ end
+
+end
+
+local function initializesvg(tfmdata,kind,value) -- hm, always value
+ if value and otf.svgenabled then
+ local characters = tfmdata.characters
+ local descriptions = tfmdata.descriptions
+ local properties = tfmdata.properties
+ --
+ local svg = properties.svg
+ local hash = svg and svg.hash
+ local timestamp = svg and svg.timestamp
+ if not hash then
+ return
+ end
+ --
+ local pdffile = containers.read(otf.pdfcache,hash)
+ local pdfshapes = pdffile and pdffile.pdfshapes
+ if not pdfshapes or pdffile.timestamp ~= timestamp then
+ local svgfile = containers.read(otf.svgcache,hash)
+ local svgshapes = svgfile and svgfile.svgshapes
+ pdfshapes = svgshapes and otfsvg.topdf(svgshapes) or { }
+ containers.write(otf.pdfcache, hash, {
+ pdfshapes = pdfshapes,
+ timestamp = timestamp,
+ })
+ end
+ if not pdfshapes or not next(pdfshapes) then
+ return
+ end
+ --
+ properties.virtualized = true
+ tfmdata.fonts = {
+ { id = 0 }
+ }
+ --
+ local getactualtext = otf.getactualtext
+ local storepdfdata = otfsvg.storepdfdata
+ --
+ local nop = { "nop" }
+ --
+ for unicode, character in next, characters do
+ local index = character.index
+ if index then
+ local pdf = pdfshapes[index]
+ if pdf then
+ local setcode, name, nilcode = storepdfdata(pdf)
+ if name then
+ local bt, et = getactualtext(unicode)
+ local wd = character.width or 0
+ local ht = character.height or 0
+ local dp = character.depth or 0
+ character.commands = {
+ { "special", "pdf:direct:" .. bt },
+ { "down", dp },
+ setcode and { "lua", setcode } or nop,
+ { "image", { filename = name, width = wd, height = ht, depth = dp } },
+ nilcode and { "lua", nilcode } or nop,
+ { "special", "pdf:direct:" .. et },
+ }
+ character.svg = true
+ end
+ end
+ end
+ end
+ end
+end
+
+fonts.handlers.otf.features.register {
+ name = "svg",
+ description = "svg glyphs",
+ manipulators = {
+ base = initializesvg,
+ node = initializesvg,
+ }
+}
diff --git a/src/luaotfload-init.lua b/src/luaotfload-init.lua
index 3c0b622..c977b49 100644
--- a/src/luaotfload-init.lua
+++ b/src/luaotfload-init.lua
@@ -264,6 +264,7 @@ local context_modules = {
{ ctx, "font-ota" },
{ ctx, "font-ots" },
{ ctx, "font-osd" },
+ { ctx, "font-ocl" },
{ ctx, "font-onr" },
{ ctx, "font-one" },
{ ctx, "font-afk" },
@@ -543,6 +544,7 @@ local init_main = function ()
load_fontloader_module "font-ota"
load_fontloader_module "font-ots"
load_fontloader_module "font-osd"
+ load_fontloader_module "font-ocl"
load_fontloader_module "font-onr"
load_fontloader_module "font-one"
load_fontloader_module "font-afk"
--
cgit v1.2.3
From 04f559ba1bc2caa232eded21d500d070142bfa1f Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Sun, 12 Jun 2016 18:33:15 +0200
Subject: [db] fix crash with missing name data
---
src/luaotfload-database.lua | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/luaotfload-database.lua b/src/luaotfload-database.lua
index 5645b63..b017340 100644
--- a/src/luaotfload-database.lua
+++ b/src/luaotfload-database.lua
@@ -1396,7 +1396,6 @@ local get_raw_info = function (metadata, basename)
local fontname = metadata.fontname
local fullname = metadata.fullname
- local validation_state = metadata.validation_state
if not fontname or not fullname then
--- Broken names table, e.g. avkv.ttf with UTF-16 strings;
--- we put some dummies in place like the fontloader
@@ -1404,7 +1403,8 @@ local get_raw_info = function (metadata, basename)
logreport ("both", 3, "db",
"Invalid names table of font %s, using dummies. \z
Reported: fontname=%q, fullname=%q.",
- basename, fontname, fullname)
+ tostring (basename), tostring (fontname),
+ tostring (fullname))
fontname = "bad-fontname-" .. basename
fullname = "bad-fullname-" .. basename
end
--
cgit v1.2.3
From e32722cb62bfe37116d3d97659040463bc381719 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Sun, 12 Jun 2016 18:43:11 +0200
Subject: [db] adapt error handling to new fontloader conventions
---
src/luaotfload-database.lua | 35 +++++++++++++++++++++--------------
1 file changed, 21 insertions(+), 14 deletions(-)
diff --git a/src/luaotfload-database.lua b/src/luaotfload-database.lua
index b017340..7495ff2 100644
--- a/src/luaotfload-database.lua
+++ b/src/luaotfload-database.lua
@@ -1298,23 +1298,29 @@ find_closest = function (name, limit)
return false
end --- find_closest()
+--- string -> uint -> bool * (string | rawdata)
local read_font_file = function (filename, subfont)
- return otfhandler.readers.getinfo (filename,
- { subfont = subfont
- , details = false
- , platformnames = true
- , rawfamilynames = true
- })
+ local fontdata = otfhandler.readers.getinfo (filename,
+ { subfont = subfont
+ , details = false
+ , platformnames = true
+ , rawfamilynames = true
+ })
+ local msg = fontdata.comment
+ if msg then
+ return false, msg
+ end
+ return true, fontdata
end
local load_font_file = function (filename, subfont)
- local rawfont, _msg = read_font_file (filename, subfont)
-
- if not rawfont then
- logreport ("log", 1, "db", "ERROR: failed to open %s.", filename)
+ local err, ret = read_font_file (filename, subfont)
+ if err == false then
+ logreport ("both", 1, "db", "ERROR: failed to open %q: %q.",
+ tostring (filename), tostring (ret))
return
end
- return rawfont
+ return ret
end
--- rawdata -> (int * int * int | bool)
@@ -1773,11 +1779,12 @@ local read_font_names = function (fullname,
--- 4) get basic info, abort if fontloader can’t read it
- local info = read_font_file (fullname)
+ local err, info = read_font_file (fullname)
- if not info then
+ if err == false then
logreport ("log", 1, "db",
- "Failed to read basic information from %q", basename)
+ "Failed to read basic information from %q: %q",
+ basename, tostring (info))
return false
end
--
cgit v1.2.3
From ba744a4bce3ed03eefbf2b4746fa24e6d388d9ff Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Tue, 14 Jun 2016 23:09:47 +0200
Subject: [fontloader] sync with Context as of 2016-06-14
---
src/fontloader/misc/fontloader-font-dsp.lua | 16 +++++++++-------
src/fontloader/misc/fontloader-font-otr.lua | 7 ++++---
src/fontloader/runtime/fontloader-reference.lua | 25 ++++++++++++++-----------
3 files changed, 27 insertions(+), 21 deletions(-)
diff --git a/src/fontloader/misc/fontloader-font-dsp.lua b/src/fontloader/misc/fontloader-font-dsp.lua
index 9726c51..a1ae17f 100644
--- a/src/fontloader/misc/fontloader-font-dsp.lua
+++ b/src/fontloader/misc/fontloader-font-dsp.lua
@@ -2214,9 +2214,9 @@ function readers.math(f,fontdata,specification)
end
function readers.colr(f,fontdata,specification)
- if specification.details then
- local datatable = fontdata.tables.colr
- if datatable then
+ local datatable = fontdata.tables.colr
+ if datatable then
+ if specification.glyphs then
local tableoffset = datatable.offset
setposition(f,tableoffset)
local version = readushort(f)
@@ -2266,11 +2266,12 @@ function readers.colr(f,fontdata,specification)
glyphs[glyphindex].colors = t
end
end
+ fontdata.hascolor = true
end
end
function readers.cpal(f,fontdata,specification)
- if specification.details then
+ if specification.glyphs then
local datatable = fontdata.tables.cpal
if datatable then
local tableoffset = datatable.offset
@@ -2316,9 +2317,9 @@ function readers.cpal(f,fontdata,specification)
end
function readers.svg(f,fontdata,specification)
- if specification.details then
- local datatable = fontdata.tables.svg
- if datatable then
+ local datatable = fontdata.tables.svg
+ if datatable then
+ if specification.glyphs then
local tableoffset = datatable.offset
setposition(f,tableoffset)
local version = readushort(f)
@@ -2351,5 +2352,6 @@ function readers.svg(f,fontdata,specification)
end
fontdata.svgshapes = entries
end
+ fontdata.hascolor = true
end
end
diff --git a/src/fontloader/misc/fontloader-font-otr.lua b/src/fontloader/misc/fontloader-font-otr.lua
index e09e87d..7d0bf04 100644
--- a/src/fontloader/misc/fontloader-font-otr.lua
+++ b/src/fontloader/misc/fontloader-font-otr.lua
@@ -1659,19 +1659,19 @@ end
-- Experimental (we need fonts).
function readers.colr(f,fontdata,specification)
- if specification.details then
+ if specification.glyphs then
reportskippedtable("colr")
end
end
function readers.cpal(f,fontdata,specification)
- if specification.details then
+ if specification.glyphs then
reportskippedtable("cpal")
end
end
function readers.svg(f,fontdata,specification)
- if specification.details then
+ if specification.glyphs then
reportskippedtable("svg")
end
end
@@ -2189,6 +2189,7 @@ function readers.loadfont(filename,n)
properties = {
hasitalics = fontdata.hasitalics or false,
maxcolorclass = fontdata.maxcolorclass,
+ hascolor = fontdata.hascolor or false,
},
resources = {
-- filename = fontdata.filename,
diff --git a/src/fontloader/runtime/fontloader-reference.lua b/src/fontloader/runtime/fontloader-reference.lua
index 350d3cf..6f96d97 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/10/16 23:51:36
+-- merge date : 06/13/16 17:00:29
do -- begin closure to overcome local limits and interference
@@ -8802,17 +8802,17 @@ function readers.glyf(f,fontdata,specification)
end
end
function readers.colr(f,fontdata,specification)
- if specification.details then
+ if specification.glyphs then
reportskippedtable("colr")
end
end
function readers.cpal(f,fontdata,specification)
- if specification.details then
+ if specification.glyphs then
reportskippedtable("cpal")
end
end
function readers.svg(f,fontdata,specification)
- if specification.details then
+ if specification.glyphs then
reportskippedtable("svg")
end
end
@@ -9283,6 +9283,7 @@ function readers.loadfont(filename,n)
properties={
hasitalics=fontdata.hasitalics or false,
maxcolorclass=fontdata.maxcolorclass,
+ hascolor=fontdata.hascolor or false,
},
resources={
filename=filename,
@@ -13169,9 +13170,9 @@ function readers.math(f,fontdata,specification)
end
end
function readers.colr(f,fontdata,specification)
- if specification.details then
- local datatable=fontdata.tables.colr
- if datatable then
+ local datatable=fontdata.tables.colr
+ if datatable then
+ if specification.glyphs then
local tableoffset=datatable.offset
setposition(f,tableoffset)
local version=readushort(f)
@@ -13218,10 +13219,11 @@ function readers.colr(f,fontdata,specification)
glyphs[glyphindex].colors=t
end
end
+ fontdata.hascolor=true
end
end
function readers.cpal(f,fontdata,specification)
- if specification.details then
+ if specification.glyphs then
local datatable=fontdata.tables.cpal
if datatable then
local tableoffset=datatable.offset
@@ -13265,9 +13267,9 @@ function readers.cpal(f,fontdata,specification)
end
end
function readers.svg(f,fontdata,specification)
- if specification.details then
- local datatable=fontdata.tables.svg
- if datatable then
+ local datatable=fontdata.tables.svg
+ if datatable then
+ if specification.glyphs then
local tableoffset=datatable.offset
setposition(f,tableoffset)
local version=readushort(f)
@@ -13300,6 +13302,7 @@ function readers.svg(f,fontdata,specification)
end
fontdata.svgshapes=entries
end
+ fontdata.hascolor=true
end
end
--
cgit v1.2.3