summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/luatex/luaotfload/fontloader-reference.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/luatex/luaotfload/fontloader-reference.lua')
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-reference.lua2734
1 files changed, 1320 insertions, 1414 deletions
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-reference.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-reference.lua
index 0a14e6082d3..0c9bfcc380f 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-reference.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-reference.lua
@@ -1,6 +1,6 @@
-- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua
-- parent file : c:/data/develop/context/sources/luatex-fonts.lua
--- merge date : 10/18/18 00:07:52
+-- merge date : 12/19/18 19:22:22
do -- begin closure to overcome local limits and interference
@@ -554,64 +554,6 @@ function lpeg.counter(pattern,action)
return function(str) n=0;lpegmatch(pattern,str);return n end
end
end
-utf=utf or (unicode and unicode.utf8) or {}
-local utfcharacters=utf and utf.characters or string.utfcharacters
-local utfgmatch=utf and utf.gmatch
-local utfchar=utf and utf.char
-lpeg.UP=lpeg.P
-if utfcharacters then
- function lpeg.US(str)
- local p=P(false)
- for uc in utfcharacters(str) do
- p=p+P(uc)
- end
- return p
- end
-elseif utfgmatch then
- function lpeg.US(str)
- local p=P(false)
- for uc in utfgmatch(str,".") do
- p=p+P(uc)
- end
- return p
- end
-else
- function lpeg.US(str)
- local p=P(false)
- local f=function(uc)
- p=p+P(uc)
- end
- lpegmatch((utf8char/f)^0,str)
- return p
- end
-end
-local range=utf8byte*utf8byte+Cc(false)
-function lpeg.UR(str,more)
- local first,last
- if type(str)=="number" then
- first=str
- last=more or first
- else
- first,last=lpegmatch(range,str)
- if not last then
- return P(str)
- end
- end
- if first==last then
- return P(str)
- elseif utfchar and (last-first<8) then
- local p=P(false)
- for i=first,last do
- p=p+P(utfchar(i))
- end
- return p
- else
- local f=function(b)
- return b>=first and b<=last
- end
- return utf8byte/f
- end
-end
function lpeg.is_lpeg(p)
return p and lpegtype(p)=="pattern"
end
@@ -1107,7 +1049,6 @@ local table,string=table,string
local concat,sort,insert,remove=table.concat,table.sort,table.insert,table.remove
local format,lower,dump=string.format,string.lower,string.dump
local getmetatable,setmetatable=getmetatable,setmetatable
-local getinfo=debug.getinfo
local lpegmatch,patterns=lpeg.match,lpeg.patterns
local floor=math.floor
local stripper=patterns.stripper
@@ -1669,20 +1610,23 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif tv=="function" then
if functions then
- local f=getinfo(v).what=="C" and dump(dummy) or dump(v)
- if tk=="number" then
- if hexify then
- handle(format("%s [0x%X]=load(%q),",depth,k,f))
+ local getinfo=debug and debug.getinfo
+ if getinfo then
+ local f=getinfo(v).what=="C" and dump(dummy) or dump(v)
+ if tk=="number" then
+ if hexify then
+ handle(format("%s [0x%X]=load(%q),",depth,k,f))
+ else
+ handle(format("%s [%s]=load(%q),",depth,k,f))
+ end
+ elseif tk=="boolean" then
+ handle(format("%s [%s]=load(%q),",depth,k and "true" or "false",f))
+ elseif tk~="string" then
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ handle(format("%s %s=load(%q),",depth,k,f))
else
- handle(format("%s [%s]=load(%q),",depth,k,f))
+ handle(format("%s [%q]=load(%q),",depth,k,f))
end
- elseif tk=="boolean" then
- handle(format("%s [%s]=load(%q),",depth,k and "true" or "false",f))
- elseif tk~="string" then
- elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
- handle(format("%s %s=load(%q),",depth,k,f))
- else
- handle(format("%s [%q]=load(%q),",depth,k,f))
end
end
else
@@ -3088,699 +3032,6 @@ 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
- utf.char=string.utfcharacter or (utf8 and utf8.char)
- if not utf.char then
- local char=string.char
- if bit32 then
- local rshift=bit32.rshift
- function utf.char(n)
- if n<0x80 then
- return char(n)
- elseif n<0x800 then
- return char(
- 0xC0+rshift(n,6),
- 0x80+(n%0x40)
- )
- elseif n<0x10000 then
- return char(
- 0xE0+rshift(n,12),
- 0x80+(rshift(n,6)%0x40),
- 0x80+(n%0x40)
- )
- elseif n<0x200000 then
- return char(
- 0xF0+rshift(n,18),
- 0x80+(rshift(n,12)%0x40),
- 0x80+(rshift(n,6)%0x40),
- 0x80+(n%0x40)
- )
- else
- return ""
- end
- end
- else
- local floor=math.floor
- 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
- end
-end
-if not utf.byte then
- utf.byte=string.utfvalue or (utf8 and utf8.codepoint)
- if not utf.byte then
- local utf8byte=patterns.utf8byte
- function utf.byte(c)
- return lpegmatch(utf8byte,c)
- end
- 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
- utf.len=string.utflength or (utf8 and utf8.len)
- 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
-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,rshift(b,8))
- else
- b=b-0x10000
- local b1=rshift(b,10)+0xD800
- local b2=b%1024+0xDC00
- return char(b1%256,rshift(b1,8),b2%256,rshift(b2,8))
- end
-end
-local function big(b)
- if b<0x10000 then
- return char(rshift(b,8),b%256)
- else
- b=b-0x10000
- local b1=rshift(b,10)+0xD800
- local b2=b%1024+0xDC00
- return char(rshift(b1,8),b1%256,rshift(b2,8),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
-if bit32 then
- local extract=bit32.extract
- local char=string.char
- function unicode.toutf32string(n)
- if n<=0xFF then
- return
- char(n).."\000\000\000"
- elseif n<=0xFFFF then
- return
- char(extract(n,0,8))..char(extract(n,8,8)).."\000\000"
- elseif n<=0xFFFFFF then
- return
- char(extract(n,0,8))..char(extract(n,8,8))..char(extract(n,16,8)).."\000"
- else
- return
- char(extract(n,0,8))..char(extract(n,8,8))..char(extract(n,16,8))..char(extract(n,24,8))
- end
- end
-end
-local len=utf.len
-local rep=rep
-function string.utfpadd(s,n)
- if n and n~=0 then
- local l=len(s)
- if n>0 then
- local d=n-l
- if d>0 then
- return rep(c or " ",d)..s
- end
- else
- local d=- n-l
- if d>0 then
- return s..rep(c or " ",d)
- end
- end
- end
- return s
-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",
@@ -4649,6 +3900,10 @@ function strings.newcollector()
end
end
end
+local f_16_16=formatters["%0.5N"]
+function number.to16dot16(n)
+ return f_16_16(n/65536.0)
+end
end -- closure
@@ -4661,6 +3916,7 @@ if not modules then modules={} end modules ['util-fil']={
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files"
}
+local tonumber=tonumber
local byte=string.byte
local char=string.char
utilities=utilities or {}
@@ -4819,17 +4075,17 @@ end
function files.readfixed2(f)
local a,b=byte(f:read(2),1,2)
if a>=0x80 then
- return (a-0x100)+b/0x100
+ tonumber((a-0x100).."."..b)
else
- return (a )+b/0x100
+ tonumber((a ).."."..b)
end
end
function files.readfixed4(f)
local a,b,c,d=byte(f:read(4),1,4)
if a>=0x80 then
- return (0x100*a+b-0x10000)+(0x100*c+d)/0x10000
+ tonumber((0x100*a+b-0x10000).."."..(0x100*c+d))
else
- return (0x100*a+b )+(0x100*c+d)/0x10000
+ tonumber((0x100*a+b ).."."..(0x100*c+d))
end
end
if bit32 then
@@ -4963,6 +4219,7 @@ local match,gmatch,gsub,lower=string.match,string.gmatch,string.gsub,string.lowe
local formatters,split,format,dump=string.formatters,string.split,string.format,string.dump
local loadfile,type=loadfile,type
local setmetatable,getmetatable,collectgarbage=setmetatable,getmetatable,collectgarbage
+local floor=math.floor
local dummyfunction=function()
end
local dummyreporter=function(c)
@@ -5273,6 +4530,59 @@ if arg then
end
end
end
+if not number.idiv then
+ function number.idiv(i,d)
+ return floor(i/d)
+ end
+end
+local u=unicode and unicode.utf8
+if u then
+ utf.lower=u.lower
+ utf.upper=u.upper
+ utf.char=u.char
+ utf.byte=u.byte
+ utf.len=u.len
+ if lpeg.setutfcasers then
+ lpeg.setutfcasers(u.lower,u.upper)
+ end
+ local bytepairs=string.bytepairs
+ local utfchar=utf.char
+ local concat=table.concat
+ function utf.utf16_to_utf8_be(s)
+ if not s then
+ return nil
+ elseif s=="" then
+ return ""
+ end
+ local result,r,more={},0,0
+ for left,right in bytepairs(s) do
+ if right then
+ local now=256*left+right
+ if more>0 then
+ now=(more-0xD800)*0x400+(now-0xDC00)+0x10000
+ more=0
+ r=r+1
+ result[r]=utfchar(now)
+ elseif now>=0xD800 and now<=0xDBFF then
+ more=now
+ else
+ r=r+1
+ result[r]=utfchar(now)
+ end
+ end
+ end
+ return concat(result)
+ end
+ local characters=string.utfcharacters
+ function utf.split(str)
+ local t,n={},0
+ for s in characters(str) do
+ n=n+1
+ t[n]=s
+ end
+ return t
+ end
+end
end -- closure
@@ -9839,9 +9149,9 @@ function constructors.scale(tfmdata,specification)
constructors.aftercopyingcharacters(target,tfmdata)
constructors.trytosharefont(target,tfmdata)
local vfonts=target.fonts
-if isvirtual or target.type=="virtual" or properties.virtualized then
+ if isvirtual or target.type=="virtual" or properties.virtualized then
properties.virtualized=true
-target.type="virtual"
+ target.type="virtual"
if not vfonts or #vfonts==0 then
target.fonts={ { id=0 } }
end
@@ -9921,23 +9231,20 @@ function constructors.finalize(tfmdata)
if not properties.virtualized then
properties.virtualized=tfmdata.type=="virtual"
end
- if not tfmdata.properties then
- tfmdata.properties={
- fontname=tfmdata.fontname,
- filename=tfmdata.filename,
- fullname=tfmdata.fullname,
- name=tfmdata.name,
- psname=tfmdata.psname,
- encodingbytes=tfmdata.encodingbytes or 1,
- embedding=tfmdata.embedding or "subset",
- tounicode=tfmdata.tounicode or 1,
- cidinfo=tfmdata.cidinfo or nil,
- format=tfmdata.format or "type1",
- direction=tfmdata.direction or 0,
- writingmode=tfmdata.writingmode or "horizontal",
- identity=tfmdata.identity or "horizontal",
- }
- end
+ properties.fontname=tfmdata.fontname
+ properties.filename=tfmdata.filename
+ properties.fullname=tfmdata.fullname
+ properties.name=tfmdata.name
+ properties.psname=tfmdata.psname
+ properties.encodingbytes=tfmdata.encodingbytes or 1
+ properties.embedding=tfmdata.embedding or "subset"
+ properties.tounicode=tfmdata.tounicode or 1
+ properties.cidinfo=tfmdata.cidinfo or nil
+ properties.format=tfmdata.format or "type1"
+ properties.direction=tfmdata.direction or 0
+ properties.writingmode=tfmdata.writingmode or "horizontal"
+ properties.identity=tfmdata.identity or "horizontal"
+ properties.usedbitmap=tfmdata.usedbitmap
if not tfmdata.resources then
tfmdata.resources={}
end
@@ -11164,7 +10471,7 @@ if not modules then modules={} end modules ['font-vfc']={
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files"
}
-local select=select
+local select,type=select,type
local insert=table.insert
local fonts=fonts
local helpers=fonts.helpers
@@ -11176,7 +10483,7 @@ local dummy={ "comment" }
function helpers.prependcommands(commands,...)
insert(commands,1,push)
for i=select("#",...),1,-1 do
- local s=select(i,...)
+ local s=(select(i,...))
if s then
insert(commands,1,s)
end
@@ -11188,7 +10495,29 @@ function helpers.appendcommands(commands,...)
insert(commands,1,push)
insert(commands,pop)
for i=1,select("#",...) do
- local s=select(i,...)
+ local s=(select(i,...))
+ if s then
+ insert(commands,s)
+ end
+ end
+ return commands
+end
+function helpers.prependcommandtable(commands,t)
+ insert(commands,1,push)
+ for i=#t,1,-1 do
+ local s=t[i]
+ if s then
+ insert(commands,1,s)
+ end
+ end
+ insert(commands,pop)
+ return commands
+end
+function helpers.appendcommandtable(commands,t)
+ insert(commands,1,push)
+ insert(commands,pop)
+ for i=1,#t do
+ local s=t[i]
if s then
insert(commands,s)
end
@@ -11244,6 +10573,7 @@ if not modules then modules={} end modules ['font-otr']={
}
local next,type,tonumber=next,type,tonumber
local byte,lower,char,gsub=string.byte,string.lower,string.char,string.gsub
+local fullstrip=string.fullstrip
local floor,round=math.floor,math.round
local P,R,S,C,Cs,Cc,Ct,Carg,Cmt=lpeg.P,lpeg.R,lpeg.S,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.Ct,lpeg.Carg,lpeg.Cmt
local lpegmatch=lpeg.match
@@ -11520,19 +10850,29 @@ local helpers={}
readers.helpers=helpers
local function gotodatatable(f,fontdata,tag,criterium)
if criterium and f then
- local datatable=fontdata.tables[tag]
- if datatable then
- local tableoffset=datatable.offset
- setposition(f,tableoffset)
- return tableoffset
+ local tables=fontdata.tables
+ if tables then
+ local datatable=tables[tag]
+ if datatable then
+ local tableoffset=datatable.offset
+ setposition(f,tableoffset)
+ return tableoffset
+ end
+ else
+ report("no tables")
end
end
end
local function reportskippedtable(f,fontdata,tag,criterium)
if criterium and f then
- local datatable=fontdata.tables[tag]
- if datatable then
- report("loading of table %a skipped",tag)
+ local tables=fontdata.tables
+ if tables then
+ local datatable=tables[tag]
+ if datatable then
+ report("loading of table %a skipped",tag)
+ end
+ else
+ report("no tables")
end
end
end
@@ -11556,6 +10896,15 @@ local platformnames={
typographicsubfamily=true,
compatiblefullname=true,
}
+local platformextras={
+ uniqueid=true,
+ version=true,
+ copyright=true,
+ license=true,
+ licenseurl=true,
+ manufacturer=true,
+ vendorurl=true,
+}
function readers.name(f,fontdata,specification)
local tableoffset=gotodatatable(f,fontdata,"name",true)
if tableoffset then
@@ -11608,6 +10957,17 @@ function readers.name(f,fontdata,specification)
local names={}
local done={}
local extras={}
+ local function decoded(platform,encoding,content)
+ local decoder=decoders[platform]
+ if decoder then
+ decoder=decoder[encoding]
+ end
+ if decoder then
+ return decoder(content)
+ else
+ return content
+ end
+ end
local function filter(platform,e,l)
local namelist=namelists[platform]
for i=1,#namelist do
@@ -11619,14 +10979,7 @@ function readers.name(f,fontdata,specification)
local language=name.language
if (not e or encoding==e) and (not l or language==l) then
setposition(f,name.offset)
- local content=readstring(f,name.length)
- local decoder=decoders[platform]
- if decoder then
- decoder=decoder[encoding]
- end
- if decoder then
- content=decoder(content)
- end
+ local content=decoded(platform,encoding,readstring(f,name.length))
if nametag then
names[nametag]={
content=content,
@@ -11650,22 +11003,15 @@ function readers.name(f,fontdata,specification)
fontdata.extras=extras
if specification.platformnames then
local collected={}
+ local platformextras=specification.platformextras and platformextras
for platform,namelist in next,namelists do
local filtered=false
for i=1,#namelist do
local entry=namelist[i]
local name=entry.name
- if platformnames[name] then
+ if platformnames[name] or (platformextras and platformextras[name]) then
setposition(f,entry.offset)
- local content=readstring(f,entry.length)
- local encoding=entry.encoding
- local decoder=decoders[platform]
- if decoder then
- decoder=decoder[encoding]
- end
- if decoder then
- content=decoder(content)
- end
+ local content=decoded(platform,entry.encoding,readstring(f,entry.length))
if filtered then
filtered[name]=content
else
@@ -11730,7 +11076,7 @@ readers["os/2"]=function(f,fontdata)
if version>=1 then
windowsmetrics.codepageranges={ readulong(f),readulong(f) }
end
- if version>=3 then
+ if version>=2 then
windowsmetrics.xheight=readshort(f)
windowsmetrics.capheight=readshort(f)
windowsmetrics.defaultchar=readushort(f)
@@ -11748,10 +11094,13 @@ end
readers.head=function(f,fontdata)
local tableoffset=gotodatatable(f,fontdata,"head",true)
if tableoffset then
+ local version=readulong(f)
+ local fontversion=readulong(f)
local fontheader={
- version=readfixed(f),
- revision=readfixed(f),
- checksum=readulong(f),
+ version=version,
+ fontversion=number.to16dot16(fontversion),
+ fontversionnumber=fontversion,
+ checksum=readushort(f)*0x10000+readushort(f),
magic=readulong(f),
flags=readushort(f),
units=readushort(f),
@@ -11777,7 +11126,7 @@ readers.hhea=function(f,fontdata,specification)
local tableoffset=gotodatatable(f,fontdata,"hhea",specification.details)
if tableoffset then
fontdata.horizontalheader={
- version=readfixed(f),
+ version=readulong(f),
ascender=readfword(f),
descender=readfword(f),
linegap=readfword(f),
@@ -11805,7 +11154,7 @@ readers.vhea=function(f,fontdata,specification)
local tableoffset=gotodatatable(f,fontdata,"vhea",specification.details)
if tableoffset then
fontdata.verticalheader={
- version=readfixed(f),
+ version=readulong(f),
ascender=readfword(f),
descender=readfword(f),
linegap=readfword(f),
@@ -11832,15 +11181,15 @@ end
readers.maxp=function(f,fontdata,specification)
local tableoffset=gotodatatable(f,fontdata,"maxp",specification.details)
if tableoffset then
- local version=readfixed(f)
+ local version=readulong(f)
local nofglyphs=readushort(f)
fontdata.nofglyphs=nofglyphs
- if version==0.5 then
+ if version==0x00005000 then
fontdata.maximumprofile={
version=version,
nofglyphs=nofglyphs,
}
- elseif version==1.0 then
+ elseif version==0x00010000 then
fontdata.maximumprofile={
version=version,
nofglyphs=nofglyphs,
@@ -11877,7 +11226,7 @@ readers.hmtx=function(f,fontdata,specification)
local leftsidebearing=0
for i=0,nofmetrics-1 do
local glyph=glyphs[i]
- width=readshort(f)
+ width=readshort(f)
leftsidebearing=readshort(f)
if width~=0 then
glyph.width=width
@@ -11923,7 +11272,7 @@ end
readers.post=function(f,fontdata,specification)
local tableoffset=gotodatatable(f,fontdata,"post",true)
if tableoffset then
- local version=readfixed(f)
+ local version=readulong(f)
fontdata.postscript={
version=version,
italicangle=round(1000*readfixed(f))/1000,
@@ -11936,11 +11285,11 @@ readers.post=function(f,fontdata,specification)
maxmemtype1=readulong(f),
}
if not specification.glyphs then
- elseif version==1.0 then
+ elseif version==0x00010000 then
for index=0,#standardromanencoding do
glyphs[index].name=standardromanencoding[index]
end
- elseif version==2.0 then
+ elseif version==0x00020000 then
local glyphs=fontdata.glyphs
local nofglyphs=readushort(f)
local indices={}
@@ -11971,8 +11320,6 @@ readers.post=function(f,fontdata,specification)
end
end
end
- elseif version==2.5 then
- elseif version==3.0 then
end
else
fontdata.postscript={}
@@ -12529,14 +11876,16 @@ local function getinfo(maindata,sub,platformnames,rawfamilynames,metricstoo,inst
designsize=fontdata.designsize,
minsize=fontdata.minsize,
maxsize=fontdata.maxsize,
+ boundingbox=fontheader and { fontheader.xmin or 0,fontheader.ymin or 0,fontheader.xmax or 0,fontheader.ymax or 0 } or nil,
monospaced=(tonumber(postscript.monospaced or 0)>0) or metrics.panosewidth=="monospaced",
averagewidth=metrics.averagewidth,
xheight=metrics.xheight,
- capheight=metrics.capheight,
+ capheight=metrics.capheight or fontdata.maxy,
ascender=metrics.typoascender,
descender=metrics.typodescender,
platformnames=platformnames or nil,
instancenames=instancenames or nil,
+ tableoffsets=fontdata.tableoffsets,
}
if metricstoo then
local keys={
@@ -12594,7 +11943,7 @@ local function loadtables(f,specification,offset)
}
for i=1,fontdata.noftables do
local tag=lower(stripstring(readstring(f,4)))
- local checksum=readulong(f)
+ local checksum=readushort(f)*0x10000+readushort(f)
local offset=readulong(f)
local length=readulong(f)
if offset+length>filesize then
@@ -12612,7 +11961,7 @@ local function loadtables(f,specification,offset)
else
fontdata.format="truetype"
end
- return fontdata
+ return fontdata,tables
end
local function prepareglyps(fontdata)
local glyphs=setmetatableindex(function(t,k)
@@ -12633,7 +11982,7 @@ local function readtable(tag,f,fontdata,specification,...)
end
local variablefonts_supported=(context and true) or (logs and logs.application and true) or false
local function readdata(f,offset,specification)
- local fontdata=loadtables(f,specification,offset)
+ local fontdata,tables=loadtables(f,specification,offset)
if specification.glyphs then
prepareglyps(fontdata)
end
@@ -12743,9 +12092,18 @@ local function readdata(f,offset,specification)
readtable("gpos",f,fontdata,specification)
readtable("math",f,fontdata,specification)
fontdata.locations=nil
- fontdata.tables=nil
fontdata.cidmaps=nil
fontdata.dictionaries=nil
+ if specification.tableoffsets then
+ fontdata.tableoffsets=tables
+ setmetatableindex(tables,{
+ version=fontdata.version,
+ noftables=fontdata.noftables,
+ searchrange=fontdata.searchrange,
+ entryselector=fontdata.entryselector,
+ rangeshift=fontdata.rangeshift,
+ })
+ end
return fontdata
end
local function loadfontdata(specification)
@@ -12849,7 +12207,7 @@ local function loadfont(specification,n,instance)
specification.instance=specification.instance or instance
end
local function message(str)
- report("fatal error in file %a: %s\n%s",specification.filename,str,debug.traceback())
+ report("fatal error in file %a: %s\n%s",specification.filename,str,debug and debug.traceback())
end
local ok,result=xpcall(loadfontdata,message,specification)
if ok then
@@ -12871,12 +12229,25 @@ function readers.loadshapes(filename,n,instance,streams)
v.index=nil
v.math=nil
end
+ local names=fontdata.names
+ if names then
+ for k,v in next,names do
+ names[k]=fullstrip(v.content)
+ end
+ end
end
return fontdata and {
filename=filename,
format=fontdata.format,
glyphs=fontdata.glyphs,
units=fontdata.fontheader.units,
+ cffinfo=fontdata.cffinfo,
+ fontheader=fontdata.fontheader,
+ horizontalheader=fontdata.horizontalheader,
+ verticalheader=fontdata.verticalheader,
+ maximumprofile=fontdata.maximumprofile,
+ names=fontdata.names,
+ postscript=fontdata.postscript,
} or {
filename=filename,
format="unknown",
@@ -12928,7 +12299,7 @@ function readers.loadfont(filename,n,instance)
mathconstants=fontdata.mathconstants,
colorpalettes=fontdata.colorpalettes,
svgshapes=fontdata.svgshapes,
- sbixshapes=fontdata.sbixshapes,
+ pngshapes=fontdata.pngshapes,
variabledata=fontdata.variabledata,
foundtables=fontdata.foundtables,
},
@@ -12940,10 +12311,12 @@ function readers.getinfo(filename,specification)
local platformnames=false
local rawfamilynames=false
local instancenames=true
+ local tableoffsets=false
if type(specification)=="table" then
subfont=tonumber(specification.subfont)
platformnames=specification.platformnames
rawfamilynames=specification.rawfamilynames
+ tableoffsets=specification.tableoffsets
else
subfont=tonumber(specification)
end
@@ -12952,6 +12325,7 @@ function readers.getinfo(filename,specification)
details=true,
platformnames=platformnames,
instancenames=true,
+ tableoffsets=tableoffsets,
}
if fontdata then
local subfonts=fontdata.subfonts
@@ -14219,7 +13593,7 @@ if not modules then modules={} end modules ['font-cff']={
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files"
}
-local next,type,tonumber=next,type,tonumber
+local next,type,tonumber,rawget=next,type,tonumber,rawget
local byte,char,gmatch=string.byte,string.char,string.gmatch
local concat,remove,unpack=table.concat,table.remove,table.unpack
local floor,abs,round,ceil,min,max=math.floor,math.abs,math.round,math.ceil,math.min,math.max
@@ -14227,6 +13601,8 @@ local P,C,R,S,C,Cs,Ct=lpeg.P,lpeg.C,lpeg.R,lpeg.S,lpeg.C,lpeg.Cs,lpeg.Ct
local lpegmatch=lpeg.match
local formatters=string.formatters
local bytetable=string.bytetable
+local idiv=number.idiv
+local rshift,band,extract=bit32.rshift,bit32.band,bit32.extract
local readers=fonts.handlers.otf.readers
local streamreader=readers.streamreader
local readstring=streamreader.readstring
@@ -14421,8 +13797,25 @@ do
end+P("\05")/function()
result.fontbbox={ unpack(stack,1,4) }
top=0
- end
-+P("\13")/function()
+ end+P("\06")/function()
+ result.bluevalues={ unpack(stack,1,top) }
+ top=0
+ end+P("\07")/function()
+ result.otherblues={ unpack(stack,1,top) }
+ top=0
+ end+P("\08")/function()
+ result.familyblues={ unpack(stack,1,top) }
+ top=0
+ end+P("\09")/function()
+ result.familyotherblues={ unpack(stack,1,top) }
+ top=0
+ end+P("\10")/function()
+ result.strhw=stack[top]
+ top=0
+ end+P("\11")/function()
+ result.strvw=stack[top]
+ top=0
+ end+P("\13")/function()
result.uniqueid=stack[top]
top=0
end+P("\14")/function()
@@ -14488,6 +13881,21 @@ do
end+P("\08")/function()
result.strokewidth=stack[top]
top=0
+ end+P("\09")/function()
+ result.bluescale=stack[top]
+ top=0
+ end+P("\10")/function()
+ result.bluesnap=stack[top]
+ top=0
+ end+P("\11")/function()
+ result.bluefuzz=stack[top]
+ top=0
+ end+P("\12")/function()
+ result.stemsnaph={ unpack(stack,1,top) }
+ top=0
+ end+P("\13")/function()
+ result.stemsnapv={ unpack(stack,1,top) }
+ top=0
end+P("\20")/function()
result.syntheticbase=stack[top]
top=0
@@ -14531,24 +13939,24 @@ do
top=0
end
)
- local p_last=P("\x0F")/"0"+P("\x1F")/"1"+P("\x2F")/"2"+P("\x3F")/"3"+P("\x4F")/"4"+P("\x5F")/"5"+P("\x6F")/"6"+P("\x7F")/"7"+P("\x8F")/"8"+P("\x9F")/"9"+P("\xAF")/""+P("\xBF")/""+P("\xCF")/""+P("\xDF")/""+P("\xEF")/""+R("\xF0\xFF")/""
local remap={
["\x00"]="00",["\x01"]="01",["\x02"]="02",["\x03"]="03",["\x04"]="04",["\x05"]="05",["\x06"]="06",["\x07"]="07",["\x08"]="08",["\x09"]="09",["\x0A"]="0.",["\x0B"]="0E",["\x0C"]="0E-",["\x0D"]="0",["\x0E"]="0-",["\x0F"]="0",
- ["\x10"]="10",["\x11"]="11",["\x12"]="12",["\x13"]="13",["\x14"]="14",["\x15"]="15",["\x16"]="16",["\x17"]="17",["\x18"]="18",["\x19"]="19",["\x1A"]="0.",["\x1B"]="0E",["\x1C"]="0E-",["\x1D"]="0",["\x1E"]="0-",["\x1F"]="0",
- ["\x20"]="20",["\x21"]="21",["\x22"]="22",["\x23"]="23",["\x24"]="24",["\x25"]="25",["\x26"]="26",["\x27"]="27",["\x28"]="28",["\x29"]="29",["\x2A"]="0.",["\x2B"]="0E",["\x2C"]="0E-",["\x2D"]="0",["\x2E"]="0-",["\x2F"]="0",
- ["\x30"]="30",["\x31"]="31",["\x32"]="32",["\x33"]="33",["\x34"]="34",["\x35"]="35",["\x36"]="36",["\x37"]="37",["\x38"]="38",["\x39"]="39",["\x3A"]="0.",["\x3B"]="0E",["\x3C"]="0E-",["\x3D"]="0",["\x3E"]="0-",["\x3F"]="0",
- ["\x40"]="40",["\x41"]="41",["\x42"]="42",["\x43"]="43",["\x44"]="44",["\x45"]="45",["\x46"]="46",["\x47"]="47",["\x48"]="48",["\x49"]="49",["\x4A"]="0.",["\x4B"]="0E",["\x4C"]="0E-",["\x4D"]="0",["\x4E"]="0-",["\x4F"]="0",
- ["\x50"]="50",["\x51"]="51",["\x52"]="52",["\x53"]="53",["\x54"]="54",["\x55"]="55",["\x56"]="56",["\x57"]="57",["\x58"]="58",["\x59"]="59",["\x5A"]="0.",["\x5B"]="0E",["\x5C"]="0E-",["\x5D"]="0",["\x5E"]="0-",["\x5F"]="0",
- ["\x60"]="60",["\x61"]="61",["\x62"]="62",["\x63"]="63",["\x64"]="64",["\x65"]="65",["\x66"]="66",["\x67"]="67",["\x68"]="68",["\x69"]="69",["\x6A"]="0.",["\x6B"]="0E",["\x6C"]="0E-",["\x6D"]="0",["\x6E"]="0-",["\x6F"]="0",
- ["\x70"]="70",["\x71"]="71",["\x72"]="72",["\x73"]="73",["\x74"]="74",["\x75"]="75",["\x76"]="76",["\x77"]="77",["\x78"]="78",["\x79"]="79",["\x7A"]="0.",["\x7B"]="0E",["\x7C"]="0E-",["\x7D"]="0",["\x7E"]="0-",["\x7F"]="0",
- ["\x80"]="80",["\x81"]="81",["\x82"]="82",["\x83"]="83",["\x84"]="84",["\x85"]="85",["\x86"]="86",["\x87"]="87",["\x88"]="88",["\x89"]="89",["\x8A"]="0.",["\x8B"]="0E",["\x8C"]="0E-",["\x8D"]="0",["\x8E"]="0-",["\x8F"]="0",
- ["\x90"]="90",["\x91"]="91",["\x92"]="92",["\x93"]="93",["\x94"]="94",["\x95"]="95",["\x96"]="96",["\x97"]="97",["\x98"]="98",["\x99"]="99",["\x9A"]="0.",["\x9B"]="0E",["\x9C"]="0E-",["\x9D"]="0",["\x9E"]="0-",["\x9F"]="0",
+ ["\x10"]="10",["\x11"]="11",["\x12"]="12",["\x13"]="13",["\x14"]="14",["\x15"]="15",["\x16"]="16",["\x17"]="17",["\x18"]="18",["\x19"]="19",["\x1A"]="1.",["\x1B"]="1E",["\x1C"]="1E-",["\x1D"]="1",["\x1E"]="1-",["\x1F"]="1",
+ ["\x20"]="20",["\x21"]="21",["\x22"]="22",["\x23"]="23",["\x24"]="24",["\x25"]="25",["\x26"]="26",["\x27"]="27",["\x28"]="28",["\x29"]="29",["\x2A"]="2.",["\x2B"]="2E",["\x2C"]="2E-",["\x2D"]="2",["\x2E"]="2-",["\x2F"]="2",
+ ["\x30"]="30",["\x31"]="31",["\x32"]="32",["\x33"]="33",["\x34"]="34",["\x35"]="35",["\x36"]="36",["\x37"]="37",["\x38"]="38",["\x39"]="39",["\x3A"]="3.",["\x3B"]="3E",["\x3C"]="3E-",["\x3D"]="3",["\x3E"]="3-",["\x3F"]="3",
+ ["\x40"]="40",["\x41"]="41",["\x42"]="42",["\x43"]="43",["\x44"]="44",["\x45"]="45",["\x46"]="46",["\x47"]="47",["\x48"]="48",["\x49"]="49",["\x4A"]="4.",["\x4B"]="4E",["\x4C"]="4E-",["\x4D"]="4",["\x4E"]="4-",["\x4F"]="4",
+ ["\x50"]="50",["\x51"]="51",["\x52"]="52",["\x53"]="53",["\x54"]="54",["\x55"]="55",["\x56"]="56",["\x57"]="57",["\x58"]="58",["\x59"]="59",["\x5A"]="5.",["\x5B"]="5E",["\x5C"]="5E-",["\x5D"]="5",["\x5E"]="5-",["\x5F"]="5",
+ ["\x60"]="60",["\x61"]="61",["\x62"]="62",["\x63"]="63",["\x64"]="64",["\x65"]="65",["\x66"]="66",["\x67"]="67",["\x68"]="68",["\x69"]="69",["\x6A"]="6.",["\x6B"]="6E",["\x6C"]="6E-",["\x6D"]="6",["\x6E"]="6-",["\x6F"]="6",
+ ["\x70"]="70",["\x71"]="71",["\x72"]="72",["\x73"]="73",["\x74"]="74",["\x75"]="75",["\x76"]="76",["\x77"]="77",["\x78"]="78",["\x79"]="79",["\x7A"]="7.",["\x7B"]="7E",["\x7C"]="7E-",["\x7D"]="7",["\x7E"]="7-",["\x7F"]="7",
+ ["\x80"]="80",["\x81"]="81",["\x82"]="82",["\x83"]="83",["\x84"]="84",["\x85"]="85",["\x86"]="86",["\x87"]="87",["\x88"]="88",["\x89"]="89",["\x8A"]="8.",["\x8B"]="8E",["\x8C"]="8E-",["\x8D"]="8",["\x8E"]="8-",["\x8F"]="8",
+ ["\x90"]="90",["\x91"]="91",["\x92"]="92",["\x93"]="93",["\x94"]="94",["\x95"]="95",["\x96"]="96",["\x97"]="97",["\x98"]="98",["\x99"]="99",["\x9A"]="9.",["\x9B"]="9E",["\x9C"]="9E-",["\x9D"]="9",["\x9E"]="9-",["\x9F"]="9",
["\xA0"]=".0",["\xA1"]=".1",["\xA2"]=".2",["\xA3"]=".3",["\xA4"]=".4",["\xA5"]=".5",["\xA6"]=".6",["\xA7"]=".7",["\xA8"]=".8",["\xA9"]=".9",["\xAA"]="..",["\xAB"]=".E",["\xAC"]=".E-",["\xAD"]=".",["\xAE"]=".-",["\xAF"]=".",
["\xB0"]="E0",["\xB1"]="E1",["\xB2"]="E2",["\xB3"]="E3",["\xB4"]="E4",["\xB5"]="E5",["\xB6"]="E6",["\xB7"]="E7",["\xB8"]="E8",["\xB9"]="E9",["\xBA"]="E.",["\xBB"]="EE",["\xBC"]="EE-",["\xBD"]="E",["\xBE"]="E-",["\xBF"]="E",
["\xC0"]="E-0",["\xC1"]="E-1",["\xC2"]="E-2",["\xC3"]="E-3",["\xC4"]="E-4",["\xC5"]="E-5",["\xC6"]="E-6",["\xC7"]="E-7",["\xC8"]="E-8",["\xC9"]="E-9",["\xCA"]="E-.",["\xCB"]="E-E",["\xCC"]="E-E-",["\xCD"]="E-",["\xCE"]="E--",["\xCF"]="E-",
["\xD0"]="-0",["\xD1"]="-1",["\xD2"]="-2",["\xD3"]="-3",["\xD4"]="-4",["\xD5"]="-5",["\xD6"]="-6",["\xD7"]="-7",["\xD8"]="-8",["\xD9"]="-9",["\xDA"]="-.",["\xDB"]="-E",["\xDC"]="-E-",["\xDD"]="-",["\xDE"]="--",["\xDF"]="-",
}
- local p_nibbles=P("\30")*Cs(((1-p_last)/remap)^0+p_last)/function(n)
+ local p_last=S("\x0F\x1F\x2F\x3F\x4F\x5F\x6F\x7F\x8F\x9F\xAF\xBF")+R("\xF0\xFF")
+ local p_nibbles=P("\30")*Cs(((1-p_last)/remap)^0*(P(1)/remap))/function(n)
top=top+1
stack[top]=tonumber(n) or 0
end
@@ -15169,7 +14577,7 @@ do
if trace_charstrings then
showstate("stem")
end
- stems=stems+top/2
+ stems=stems+idiv(top,2)
top=0
end
local function getmask()
@@ -15188,13 +14596,13 @@ do
if trace_charstrings then
showstate(operator==19 and "hintmark" or "cntrmask")
end
- stems=stems+top/2
+ stems=stems+idiv(top,2)
top=0
if stems==0 then
elseif stems<=8 then
return 1
else
- return floor((stems+7)/8)
+ return idiv(stems+7,8)
end
end
local function unsupported(t)
@@ -15233,7 +14641,7 @@ do
local function hsbw()
if version==1 then
if trace_charstrings then
- showstate("dotsection")
+ showstate("hsbw")
end
width=stack[top]
end
@@ -15419,76 +14827,98 @@ do
[036]=hflex1,
[037]=flex1,
}
- local c_endchar=char(14)
- local passon do
- local rshift=bit32.rshift
- local band=bit32.band
- local round=math.round
- local encode=table.setmetatableindex(function(t,i)
- for i=-2048,-1130 do
- t[i]=char(28,band(rshift(i,8),0xFF),band(i,0xFF))
- end
- for i=-1131,-108 do
- local v=0xFB00-i-108
- t[i]=char(band(rshift(v,8),0xFF),band(v,0xFF))
- end
- for i=-107,107 do
- t[i]=char(i+139)
- end
- for i=108,1131 do
- local v=0xF700+i-108
- t[i]=char(band(rshift(v,8),0xFF),band(v,0xFF))
- end
- for i=1132,2048 do
- t[i]=char(28,band(rshift(i,8),0xFF),band(i,0xFF))
- end
- return t[i]
- end)
- local function setvsindex()
- local vsindex=stack[top]
- updateregions(vsindex)
- top=top-1
+ local chars=setmetatableindex(function (t,k)
+ local v=char(k)
+ t[k]=v
+ return v
+ end)
+ local c_endchar=chars[14]
+ local encode={}
+ setmetatableindex(encode,function(t,i)
+ for i=-2048,-1130 do
+ t[i]=char(28,band(rshift(i,8),0xFF),band(i,0xFF))
end
- local function blend()
- local n=stack[top]
- top=top-1
- if not axis then
- elseif n==1 then
- top=top-nofregions
- local v=stack[top]
+ for i=-1131,-108 do
+ local v=0xFB00-i-108
+ t[i]=char(band(rshift(v,8),0xFF),band(v,0xFF))
+ end
+ for i=-107,107 do
+ t[i]=chars[i+139]
+ end
+ for i=108,1131 do
+ local v=0xF700+i-108
+ t[i]=char(extract(v,8,8),extract(v,0,8))
+ end
+ for i=1132,2048 do
+ t[i]=char(28,band(rshift(i,8),0xFF),band(i,0xFF))
+ end
+ setmetatableindex(encode,function(t,k)
+ local r=round(k)
+ local v=rawget(t,r)
+ if v then
+ return v
+ end
+ local v1=floor(k)
+ local v2=floor((k-v1)*0x10000)
+ return char(255,extract(v1,8,8),extract(v1,0,8),extract(v2,8,8),extract(v2,0,8))
+ end)
+ return t[i]
+ end)
+ readers.cffencoder=encode
+ local function p_setvsindex()
+ local vsindex=stack[top]
+ updateregions(vsindex)
+ top=top-1
+ end
+ local function p_blend()
+ local n=stack[top]
+ top=top-1
+ if not axis then
+ elseif n==1 then
+ top=top-nofregions
+ local v=stack[top]
+ for r=1,nofregions do
+ v=v+stack[top+r]*factors[r]
+ end
+ stack[top]=round(v)
+ else
+ top=top-nofregions*n
+ local d=top
+ local k=top-n
+ for i=1,n do
+ k=k+1
+ local v=stack[k]
for r=1,nofregions do
- v=v+stack[top+r]*factors[r]
- end
- stack[top]=round(v)
- else
- top=top-nofregions*n
- local d=top
- local k=top-n
- for i=1,n do
- k=k+1
- local v=stack[k]
- for r=1,nofregions do
- v=v+stack[d+r]*factors[r]
- end
- stack[k]=round(v)
- d=d+nofregions
+ v=v+stack[d+r]*factors[r]
end
+ stack[k]=round(v)
+ d=d+nofregions
end
end
- passon=function(operation)
- if operation==15 then
- setvsindex()
- elseif operation==16 then
- blend()
- else
- for i=1,top do
- r=r+1
- result[r]=encode[stack[i]]
- end
- r=r+1
- result[r]=char(operation)
- top=0
- end
+ end
+ local function p_getstem()
+ local n=0
+ if top%2~=0 then
+ n=1
+ end
+ if top>n then
+ stems=stems+idiv(top-n,2)
+ end
+ end
+ local function p_getmask()
+ local n=0
+ if top%2~=0 then
+ n=1
+ end
+ if top>n then
+ stems=stems+idiv(top-n,2)
+ end
+ if stems==0 then
+ return 0
+ elseif stems<=8 then
+ return 1
+ else
+ return idiv(stems+7,8)
end
end
local process
@@ -15576,19 +15006,90 @@ do
elseif t==12 then
i=i+1
local t=tab[i]
- local a=subactions[t]
- if a then
- a(t)
+ if justpass then
+ if t>=34 or t<=37 then
+ for i=1,top do
+ r=r+1;result[r]=encode[stack[i]]
+ end
+ r=r+1;result[r]=chars[12]
+ r=r+1;result[r]=chars[t]
+ top=0
+ else
+ local a=subactions[t]
+ if a then
+ a(t)
+ else
+ top=0
+ end
+ end
else
- if trace_charstrings then
- showvalue("<subaction>",t)
+ local a=subactions[t]
+ if a then
+ a(t)
+ else
+ if trace_charstrings then
+ showvalue("<subaction>",t)
+ end
+ top=0
end
- top=0
end
i=i+1
elseif justpass then
- passon(t)
- i=i+1
+ if t==15 then
+ p_setvsindex()
+ i=i+1
+ elseif t==16 then
+ local s=p_blend() or 0
+ i=i+s+1
+ elseif t==1 or t==3 or t==18 or operation==23 then
+ p_getstem()
+if true then
+ if top>0 then
+ for i=1,top do
+ r=r+1;result[r]=encode[stack[i]]
+ end
+ top=0
+ end
+ r=r+1;result[r]=chars[t]
+else
+ top=0
+end
+ i=i+1
+ elseif t==19 or t==20 then
+ local s=p_getmask() or 0
+if true then
+ if top>0 then
+ for i=1,top do
+ r=r+1;result[r]=encode[stack[i]]
+ end
+ top=0
+ end
+ r=r+1;result[r]=chars[t]
+ for j=1,s do
+ i=i+1
+ r=r+1;result[r]=chars[tab[i]]
+ end
+else
+ i=i+s
+ top=0
+end
+ i=i+1
+ elseif t==9 then
+ top=0
+ i=i+1
+ elseif t==13 then
+ local s=hsbw() or 0
+ i=i+s+1
+ else
+ if top>0 then
+ for i=1,top do
+ r=r+1;result[r]=encode[stack[i]]
+ end
+ top=0
+ end
+ r=r+1;result[r]=chars[t]
+ i=i+1
+ end
else
local a=actions[t]
if a then
@@ -15609,18 +15110,20 @@ do
end
end
local function setbias(globals,locals)
- if version==1 then
- return
- false,
- false
- else
local g,l=#globals,#locals
return
((g<1240 and 107) or (g<33900 and 1131) or 32768)+1,
((l<1240 and 107) or (l<33900 and 1131) or 32768)+1
- end
end
local function processshape(tab,index)
+ if not tab then
+ glyphs[index]={
+ boundingbox={ 0,0,0,0 },
+ width=0,
+ name=charset and charset[index] or nil,
+ }
+ return
+ end
tab=bytetable(tab)
x=0
y=0
@@ -15733,15 +15236,18 @@ do
glyphs=glphs or {}
globalbias,localbias=setbias(globals,locals)
nominalwidth,defaultwidth=setwidths(dictionary.private)
- startparsing(fontdata,data,streams)
- for index=1,#charstrings do
- processshape(charstrings[index],index-1)
- charstrings[index]=nil
+ if charstrings then
+ startparsing(fontdata,data,streams)
+ for index=1,#charstrings do
+ processshape(charstrings[index],index-1)
+ end
+ stopparsing(fontdata,data)
+ else
+ report("no charstrings")
end
- stopparsing(fontdata,data)
return glyphs
end
- parsecharstring=function(fontdata,data,dictionary,tab,glphs,index,doshapes,tversion)
+ parsecharstring=function(fontdata,data,dictionary,tab,glphs,index,doshapes,tversion,streams)
keepcurve=doshapes
version=tversion
strings=data.strings
@@ -15750,6 +15256,7 @@ do
charset=false
vsindex=dictionary.vsindex or 0
glyphs=glphs or {}
+ justpass=streams==true
globalbias,localbias=setbias(globals,locals)
nominalwidth,defaultwidth=setwidths(dictionary.private)
processshape(tab,index-1)
@@ -15903,7 +15410,7 @@ local function readfdselect(f,fontdata,data,glyphs,doshapes,version,streams)
local format=readbyte(f)
if format==1 then
for i=0,nofglyphs do
- local index=readbyte(i)
+ local index=readbyte(f)
fdindex[i]=index
if index>maxindex then
maxindex=index
@@ -15932,30 +15439,33 @@ local function readfdselect(f,fontdata,data,glyphs,doshapes,version,streams)
end
if maxindex>=0 then
local cidarray=cid.fdarray
- setposition(f,header.offset+cidarray)
- local dictionaries=readlengths(f)
- for i=1,#dictionaries do
- dictionaries[i]=readstring(f,dictionaries[i])
- end
- parsedictionaries(data,dictionaries)
- cid.dictionaries=dictionaries
- readcidprivates(f,data)
- for i=1,#dictionaries do
- readlocals(f,data,dictionaries[i])
- end
- startparsing(fontdata,data,streams)
- for i=1,#charstrings do
- parsecharstring(fontdata,data,dictionaries[fdindex[i]+1],charstrings[i],glyphs,i,doshapes,version)
- charstrings[i]=nil
+ if cidarray then
+ setposition(f,header.offset+cidarray)
+ local dictionaries=readlengths(f)
+ for i=1,#dictionaries do
+ dictionaries[i]=readstring(f,dictionaries[i])
+ end
+ parsedictionaries(data,dictionaries)
+ cid.dictionaries=dictionaries
+ readcidprivates(f,data)
+ for i=1,#dictionaries do
+ readlocals(f,data,dictionaries[i])
+ end
+ startparsing(fontdata,data,streams)
+ for i=1,#charstrings do
+ parsecharstring(fontdata,data,dictionaries[fdindex[i]+1],charstrings[i],glyphs,i,doshapes,version,streams)
+ end
+ stopparsing(fontdata,data)
+ else
+ report("no cid array")
end
- stopparsing(fontdata,data)
end
end
local gotodatatable=readers.helpers.gotodatatable
local function cleanup(data,dictionaries)
end
function readers.cff(f,fontdata,specification)
- local tableoffset=gotodatatable(f,fontdata,"cff",specification.details)
+ local tableoffset=gotodatatable(f,fontdata,"cff",specification.details or specification.glyphs)
if tableoffset then
local header=readheader(f)
if header.major~=1 then
@@ -15976,14 +15486,16 @@ function readers.cff(f,fontdata,specification)
parsedictionaries(data,dictionaries,"cff")
local dic=dictionaries[1]
local cid=dic.cid
- fontdata.cffinfo={
- familynamename=dic.familyname,
+ local cffinfo={
+ familyname=dic.familyname,
fullname=dic.fullname,
boundingbox=dic.boundingbox,
weight=dic.weight,
italicangle=dic.italicangle,
underlineposition=dic.underlineposition,
underlinethickness=dic.underlinethickness,
+ defaultwidth=dic.defaultwidthx,
+ nominalwidth=dic.nominalwidthx,
monospaced=dic.monospaced,
}
fontdata.cidinfo=cid and {
@@ -15991,12 +15503,30 @@ function readers.cff(f,fontdata,specification)
ordering=cid.ordering,
supplement=cid.supplement,
}
- if specification.glyphs then
- local all=specification.shapes or false
+ fontdata.cffinfo=cffinfo
+ local all=specification.shapes or specification.streams or false
+ if specification.glyphs or all then
if cid and cid.fdselect then
- readfdselect(f,fontdata,data,glyphs,all,"cff")
+ readfdselect(f,fontdata,data,glyphs,all,"cff",specification.streams)
else
- readnoselect(f,fontdata,data,glyphs,all,"cff")
+ readnoselect(f,fontdata,data,glyphs,all,"cff",specification.streams)
+ end
+ end
+ local private=dic.private
+ if private then
+ local data=private.data
+ if type(data)=="table" then
+ cffinfo.defaultwidth=data.defaultwidth or cffinfo.defaultwidth
+ cffinfo.nominalwidth=data.nominalwidth or cffinfo.nominalwidth
+ cffinfo.bluevalues=data.bluevalues
+ cffinfo.otherblues=data.otherblues
+ cffinfo.familyblues=data.familyblues
+ cffinfo.familyotherblues=data.familyotherblues
+ cffinfo.bluescale=data.bluescale
+ cffinfo.blueshift=data.blueshift
+ cffinfo.bluefuzz=data.bluefuzz
+ cffinfo.stdhw=data.stdhw
+ cffinfo.stdvw=data.stdvw
end
end
cleanup(data,dictionaries)
@@ -16030,7 +15560,7 @@ function readers.cff2(f,fontdata,specification)
end
data.factors=specification.factors
local cid=data.dictionaries[1].cid
- local all=specification.shapes or false
+ local all=specification.shapes or specification.streams or false
if cid and cid.fdselect then
readfdselect(f,fontdata,data,glyphs,all,"cff2",specification.streams)
else
@@ -16060,7 +15590,7 @@ function readers.cffcheck(filename)
dictionaries=dictionaries,
strings=strings,
glyphs=glyphs,
- nofglyphs=4,
+ nofglyphs=0,
}
parsedictionaries(data,dictionaries,"cff")
local cid=data.dictionaries[1].cid
@@ -16087,8 +15617,10 @@ if not modules then modules={} end modules ['font-ttf']={
local next,type,unpack=next,type,unpack
local band,rshift=bit32.band,bit32.rshift
local sqrt,round=math.sqrt,math.round
-local char=string.char
+local char,rep=string.char,string.rep
local concat=table.concat
+local idiv=number.idiv
+local setmetatableindex=table.setmetatableindex
local report=logs.reporter("otf reader","ttf")
local trace_deltas=false
local readers=fonts.handlers.otf.readers
@@ -16153,22 +15685,41 @@ local function mergecomposites(glyphs,shapes)
local yscale=matrix[4]
local xoffset=matrix[5]
local yoffset=matrix[6]
- for i=1,#subpoints do
- local p=subpoints[i]
- local x=p[1]
- local y=p[2]
- nofpoints=nofpoints+1
- points[nofpoints]={
- xscale*x+xrotate*y+xoffset,
- yscale*y+yrotate*x+yoffset,
- p[3]
- }
+ local count=#subpoints
+ if xscale==1 and yscale==1 and xrotate==0 and yrotate==0 then
+ for i=1,count do
+ local p=subpoints[i]
+ nofpoints=nofpoints+1
+ points[nofpoints]={
+ p[1]+xoffset,
+ p[2]+yoffset,
+ p[3]
+ }
+ end
+ else
+ for i=1,count do
+ local p=subpoints[i]
+ local x=p[1]
+ local y=p[2]
+ nofpoints=nofpoints+1
+ points[nofpoints]={
+ xscale*x+xrotate*y+xoffset,
+ yscale*y+yrotate*x+yoffset,
+ p[3]
+ }
+ end
end
- for i=1,#subcontours do
+ local subcount=#subcontours
+ if subcount==1 then
nofcontours=nofcontours+1
- contours[nofcontours]=offset+subcontours[i]
+ contours[nofcontours]=offset+subcontours[1]
+ else
+ for i=1,#subcontours do
+ nofcontours=nofcontours+1
+ contours[nofcontours]=offset+subcontours[i]
+ end
end
- offset=offset+#subpoints
+ offset=offset+count
else
report("missing contours composite %s, component %s of %s, glyph %s",index,i,#components,subindex)
end
@@ -16178,7 +15729,7 @@ local function mergecomposites(glyphs,shapes)
shape.components=nil
return contours,points
end
- for index=1,#glyphs do
+ for index=0,#glyphs-1 do
local shape=shapes[index]
if shape then
local components=shape.components
@@ -16188,7 +15739,7 @@ local function mergecomposites(glyphs,shapes)
end
end
end
-local function readnothing(f,nofcontours)
+local function readnothing(f)
return {
type="nothing",
}
@@ -16282,8 +15833,8 @@ local function applyaxis(glyph,shape,deltas,dowidth)
end
end
local quadratic=false
-local function contours2outlines_normal(glyphs,shapes)
- for index=1,#glyphs do
+local function contours2outlines_normal(glyphs,shapes)
+ for index=0,#glyphs-1 do
local shape=shapes[index]
if shape then
local glyph=glyphs[index]
@@ -16398,7 +15949,7 @@ local function contours2outlines_normal(glyphs,shapes)
end
end
local function contours2outlines_shaped(glyphs,shapes,keepcurve)
- for index=1,#glyphs do
+ for index=0,#glyphs-1 do
local shape=shapes[index]
if shape then
local glyph=glyphs[index]
@@ -16577,115 +16128,128 @@ local function toshort(n)
end
return char(band(rshift(n,8),0xFF),band(n,0xFF))
end
+local chars=setmetatableindex(function(t,k)
+ for i=0,255 do local v=char(i) t[i]=v end return t[k]
+end)
local function repackpoints(glyphs,shapes)
local noboundingbox={ 0,0,0,0 }
local result={}
- for index=1,#glyphs do
+ local xpoints={}
+ local ypoints={}
+ for index=0,#glyphs-1 do
local shape=shapes[index]
if shape then
local r=0
local glyph=glyphs[index]
- if false then
- else
- local contours=shape.contours
- local nofcontours=contours and #contours or 0
- local boundingbox=glyph.boundingbox or noboundingbox
- r=r+1 result[r]=toshort(nofcontours)
- r=r+1 result[r]=toshort(boundingbox[1])
- r=r+1 result[r]=toshort(boundingbox[2])
- r=r+1 result[r]=toshort(boundingbox[3])
- r=r+1 result[r]=toshort(boundingbox[4])
- if nofcontours>0 then
- for i=1,nofcontours do
- r=r+1 result[r]=toshort(contours[i]-1)
- end
- r=r+1 result[r]=s_zero
- local points=shape.points
- local currentx=0
- local currenty=0
- local xpoints={}
- local ypoints={}
- local x=0
- local y=0
- local lastflag=nil
- local nofflags=0
- for i=1,#points do
- local pt=points[i]
- local px=pt[1]
- local py=pt[2]
- local fl=pt[3] and 0x01 or 0x00
- if px==currentx then
- fl=fl+0x10
+ local contours=shape.contours
+ local nofcontours=contours and #contours or 0
+ local boundingbox=glyph.boundingbox or noboundingbox
+ r=r+1 result[r]=toshort(nofcontours)
+ r=r+1 result[r]=toshort(boundingbox[1])
+ r=r+1 result[r]=toshort(boundingbox[2])
+ r=r+1 result[r]=toshort(boundingbox[3])
+ r=r+1 result[r]=toshort(boundingbox[4])
+ if nofcontours>0 then
+ for i=1,nofcontours do
+ r=r+1 result[r]=toshort(contours[i]-1)
+ end
+ r=r+1 result[r]=s_zero
+ local points=shape.points
+ local currentx=0
+ local currenty=0
+ local x=0
+ local y=0
+ local lastflag=nil
+ local nofflags=0
+ for i=1,#points do
+ local pt=points[i]
+ local px=pt[1]
+ local py=pt[2]
+ local fl=pt[3] and 0x01 or 0x00
+ if px==currentx then
+ fl=fl+0x10
+ else
+ local dx=round(px-currentx)
+ x=x+1
+ if dx<-255 or dx>255 then
+ xpoints[x]=toshort(dx)
+ elseif dx<0 then
+ fl=fl+0x02
+ xpoints[x]=chars[-dx]
+ elseif dx>0 then
+ fl=fl+0x12
+ xpoints[x]=chars[dx]
else
- local dx=round(px-currentx)
- if dx<-255 or dx>255 then
- x=x+1 xpoints[x]=toshort(dx)
- elseif dx<0 then
- fl=fl+0x02
- x=x+1 xpoints[x]=char(-dx)
- elseif dx>0 then
- fl=fl+0x12
- x=x+1 xpoints[x]=char(dx)
- else
- fl=fl+0x02
- x=x+1 xpoints[x]=c_zero
- end
+ fl=fl+0x02
+ xpoints[x]=c_zero
end
- if py==currenty then
- fl=fl+0x20
+ end
+ if py==currenty then
+ fl=fl+0x20
+ else
+ local dy=round(py-currenty)
+ y=y+1
+ if dy<-255 or dy>255 then
+ ypoints[y]=toshort(dy)
+ elseif dy<0 then
+ fl=fl+0x04
+ ypoints[y]=chars[-dy]
+ elseif dy>0 then
+ fl=fl+0x24
+ ypoints[y]=chars[dy]
else
- local dy=round(py-currenty)
- if dy<-255 or dy>255 then
- y=y+1 ypoints[y]=toshort(dy)
- elseif dy<0 then
- fl=fl+0x04
- y=y+1 ypoints[y]=char(-dy)
- elseif dy>0 then
- fl=fl+0x24
- y=y+1 ypoints[y]=char(dy)
- else
- fl=fl+0x04
- y=y+1 ypoints[y]=c_zero
- end
- end
- currentx=px
- currenty=py
- if lastflag==fl then
- nofflags=nofflags+1
- else
- if nofflags==1 then
- r=r+1 result[r]=char(lastflag)
- elseif nofflags==2 then
- r=r+1 result[r]=char(lastflag,lastflag)
- elseif nofflags>2 then
- lastflag=lastflag+0x08
- r=r+1 result[r]=char(lastflag,nofflags-1)
- end
- nofflags=1
- lastflag=fl
+ fl=fl+0x04
+ ypoints[y]=c_zero
end
end
- if nofflags==1 then
- r=r+1 result[r]=char(lastflag)
- elseif nofflags==2 then
- r=r+1 result[r]=char(lastflag,lastflag)
- elseif nofflags>2 then
- lastflag=lastflag+0x08
- r=r+1 result[r]=char(lastflag,nofflags-1)
- end
- r=r+1 result[r]=concat(xpoints)
- r=r+1 result[r]=concat(ypoints)
+ currentx=px
+ currenty=py
+ if lastflag==fl then
+ nofflags=nofflags+1
+ else
+ if nofflags==1 then
+ r=r+1 result[r]=chars[lastflag]
+ elseif nofflags==2 then
+ r=r+1 result[r]=char(lastflag,lastflag)
+ elseif nofflags>2 then
+ lastflag=lastflag+0x08
+ r=r+1 result[r]=char(lastflag,nofflags-1)
+ end
+ nofflags=1
+ lastflag=fl
+ end
+ end
+ if nofflags==1 then
+ r=r+1 result[r]=chars[lastflag]
+ elseif nofflags==2 then
+ r=r+1 result[r]=char(lastflag,lastflag)
+ elseif nofflags>2 then
+ lastflag=lastflag+0x08
+ r=r+1 result[r]=char(lastflag,nofflags-1)
+ end
+ r=r+1 result[r]=concat(xpoints,"",1,x)
+ r=r+1 result[r]=concat(ypoints,"",1,y)
+ end
+ local stream=concat(result,"",1,r)
+ local length=#stream
+ local padding=idiv(length+3,4)*4-length
+ if padding>0 then
+ if padding==1 then
+ padding="\0"
+ elseif padding==2 then
+ padding="\0\0"
+ else
+ padding="\0\0\0"
end
+ padding=stream..padding
end
- glyph.stream=concat(result,"",1,r)
- else
+ glyph.stream=stream
end
end
end
+local flags={}
local function readglyph(f,nofcontours)
local points={}
- local instructions={}
- local flags={}
local contours={}
for i=1,nofcontours do
contours[i]=readshort(f)+1
@@ -16698,9 +16262,15 @@ local function readglyph(f,nofcontours)
local flag=readbyte(f)
flags[i]=flag
if band(flag,0x08)~=0 then
- for j=1,readbyte(f) do
+ local n=readbyte(f)
+ if n==1 then
i=i+1
flags[i]=flag
+ else
+ for j=1,n do
+ i=i+1
+ flags[i]=flag
+ end
end
end
i=i+1
@@ -16708,15 +16278,13 @@ local function readglyph(f,nofcontours)
local x=0
for i=1,nofpoints do
local flag=flags[i]
- local short=band(flag,0x02)~=0
- local same=band(flag,0x10)~=0
- if short then
- if same then
+ if band(flag,0x02)~=0 then
+ if band(flag,0x10)~=0 then
x=x+readbyte(f)
else
x=x-readbyte(f)
end
- elseif same then
+ elseif band(flag,0x10)~=0 then
else
x=x+readshort(f)
end
@@ -16725,15 +16293,13 @@ local function readglyph(f,nofcontours)
local y=0
for i=1,nofpoints do
local flag=flags[i]
- local short=band(flag,0x04)~=0
- local same=band(flag,0x20)~=0
- if short then
- if same then
+ if band(flag,0x04)~=0 then
+ if band(flag,0x20)~=0 then
y=y+readbyte(f)
else
y=y-readbyte(f)
end
- elseif same then
+ elseif band(flag,0x20)~=0 then
else
y=y+readshort(f)
end
@@ -16816,7 +16382,7 @@ local function readcomposite(f)
if band(flags,0x0100)~=0 then
instructions=true
end
- if not band(flags,0x0020)~=0 then
+ if band(flags,0x0020)==0 then
break
end
end
@@ -16831,21 +16397,27 @@ function readers.loca(f,fontdata,specification)
if datatable then
local offset=fontdata.tables.glyf.offset
local format=fontdata.fontheader.indextolocformat
+ local profile=fontdata.maximumprofile
+ local nofglyphs=profile and profile.nofglyphs
local locations={}
setposition(f,datatable.offset)
if format==1 then
- local nofglyphs=datatable.length/4-2
+ if not nofglyphs then
+ nofglyphs=idiv(datatable.length,4)-1
+ end
for i=0,nofglyphs do
locations[i]=offset+readulong(f)
end
fontdata.nofglyphs=nofglyphs
else
- local nofglyphs=datatable.length/2-2
+ if not nofglyphs then
+ nofglyphs=idiv(datatable.length,2)-1
+ end
for i=0,nofglyphs do
locations[i]=offset+readushort(f)*2
end
- fontdata.nofglyphs=nofglyphs
end
+ fontdata.nofglyphs=nofglyphs
fontdata.locations=locations
end
end
@@ -16860,15 +16432,16 @@ function readers.glyf(f,fontdata,specification)
local filesize=fontdata.filesize
local nothing={ 0,0,0,0 }
local shapes={}
- local loadshapes=specification.shapes or specification.instance
- for index=0,nofglyphs do
+ local loadshapes=specification.shapes or specification.instance or specification.streams
+ for index=0,nofglyphs-1 do
local location=locations[index]
+ local length=locations[index+1]-location
if location>=filesize then
report("discarding %s glyphs due to glyph location bug",nofglyphs-index+1)
fontdata.nofglyphs=index-1
fontdata.badfont=true
break
- elseif location>0 then
+ elseif length>0 then
setposition(f,location)
local nofcontours=readshort(f)
glyphs[index].boundingbox={
@@ -16879,7 +16452,7 @@ function readers.glyf(f,fontdata,specification)
}
if not loadshapes then
elseif nofcontours==0 then
- shapes[index]=readnothing(f,nofcontours)
+ shapes[index]=readnothing(f)
elseif nofcontours>0 then
shapes[index]=readglyph(f,nofcontours)
else
@@ -16887,7 +16460,7 @@ function readers.glyf(f,fontdata,specification)
end
else
if loadshapes then
- shapes[index]={}
+ shapes[index]=readnothing(f)
end
glyphs[index].boundingbox=nothing
end
@@ -16904,7 +16477,13 @@ function readers.glyf(f,fontdata,specification)
contours2outlines_shaped(glyphs,shapes,specification.shapes)
end
elseif specification.shapes then
- contours2outlines_normal(glyphs,shapes)
+ if specification.streams then
+ repackpoints(glyphs,shapes)
+ else
+ contours2outlines_normal(glyphs,shapes)
+ end
+ elseif specification.streams then
+ repackpoints(glyphs,shapes)
end
end
end
@@ -17205,10 +16784,11 @@ local readers=fonts.handlers.otf.readers
local streamreader=readers.streamreader
local setposition=streamreader.setposition
local getposition=streamreader.getposition
-local readushort=streamreader.readcardinal2
-local readulong=streamreader.readcardinal4
+local readuinteger=streamreader.readcardinal1
+local readushort=streamreader.readcardinal2
+local readulong=streamreader.readcardinal4
local readinteger=streamreader.readinteger1
-local readshort=streamreader.readinteger2
+local readshort=streamreader.readinteger2
local readstring=streamreader.readstring
local readtag=streamreader.readtag
local readbytes=streamreader.readbytes
@@ -17228,6 +16808,7 @@ directives.register("fonts.streamreader",function()
streamreader=utilities.streams
setposition=streamreader.setposition
getposition=streamreader.getposition
+ readuinteger=streamreader.readcardinal1
readushort=streamreader.readcardinal2
readulong=streamreader.readcardinal4
readinteger=streamreader.readinteger1
@@ -19117,7 +18698,7 @@ do
end
local function loadvariations(f,fontdata,variationsoffset,lookuptypes,featurehash,featureorder)
setposition(f,variationsoffset)
- local version=readulong(f)
+ local version=readulong(f)
local nofrecords=readulong(f)
local records={}
for i=1,nofrecords do
@@ -19824,59 +19405,269 @@ function readers.sbix(f,fontdata,specification)
for i=1,nofstrikes do
strikes[i]=readulong(f)
end
+ local shapes={}
+ local done=0
+ for i=1,nofstrikes do
+ local strikeoffset=strikes[i]+tableoffset
+ setposition(f,strikeoffset)
+ strikes[i]={
+ ppem=readushort(f),
+ ppi=readushort(f),
+ offset=strikeoffset
+ }
+ end
+ sort(strikes,function(a,b)
+ if b.ppem==a.ppem then
+ return b.ppi<a.ppi
+ else
+ return b.ppem<a.ppem
+ end
+ end)
+ local glyphs={}
+ for i=1,nofstrikes do
+ local strike=strikes[i]
+ local strikeppem=strike.ppem
+ local strikeppi=strike.ppi
+ local strikeoffset=strike.offset
+ setposition(f,strikeoffset)
+ for i=0,nofglyphs do
+ glyphs[i]=readulong(f)
+ end
+ local glyphoffset=glyphs[0]
+ for i=0,nofglyphs-1 do
+ local nextoffset=glyphs[i+1]
+ if not shapes[i] then
+ local datasize=nextoffset-glyphoffset
+ if datasize>0 then
+ setposition(f,strikeoffset+glyphoffset)
+ shapes[i]={
+ x=readshort(f),
+ y=readshort(f),
+ tag=readtag(f),
+ data=readstring(f,datasize-8),
+ ppem=strikeppem,
+ ppi=strikeppi,
+ }
+ done=done+1
+ if done==nofglyphs then
+ break
+ end
+ end
+ end
+ glyphoffset=nextoffset
+ end
+ end
+ fontdata.pngshapes=shapes
+ end
+end
+do
+ local function getmetrics(f)
+ return {
+ ascender=readinteger(f),
+ descender=readinteger(f),
+ widthmax=readuinteger(f),
+ caretslopedumerator=readinteger(f),
+ caretslopedenominator=readinteger(f),
+ caretoffset=readinteger(f),
+ minorigin=readinteger(f),
+ minadvance=readinteger(f),
+ maxbefore=readinteger(f),
+ minafter=readinteger(f),
+ pad1=readinteger(f),
+ pad2=readinteger(f),
+ }
+ end
+ local function getbigmetrics(f)
+ return {
+ height=readuinteger(f),
+ width=readuinteger(f),
+ horiBearingX=readinteger(f),
+ horiBearingY=readinteger(f),
+ horiAdvance=readuinteger(f),
+ vertBearingX=readinteger(f),
+ vertBearingY=readinteger(f),
+ vertAdvance=readuinteger(f),
+ }
+ end
+ local function getsmallmetrics(f)
+ return {
+ height=readuinteger(f),
+ width=readuinteger(f),
+ bearingX=readinteger(f),
+ bearingY=readinteger(f),
+ advance=readuinteger(f),
+ }
+ end
+ function readers.cblc(f,fontdata,specification)
+ local ctdttableoffset=gotodatatable(f,fontdata,"cbdt",specification.glyphs)
+ if not ctdttableoffset then
+ return
+ end
+ local cblctableoffset=gotodatatable(f,fontdata,"cblc",specification.glyphs)
+ if cblctableoffset then
+ local majorversion=readushort(f)
+ local minorversion=readushort(f)
+ local nofsizetables=readulong(f)
+ local sizetables={}
local shapes={}
- local done=0
- for i=1,nofstrikes do
- local strikeoffset=strikes[i]+tableoffset
- setposition(f,strikeoffset)
- strikes[i]={
- ppem=readushort(f),
- ppi=readushort(f),
- offset=strikeoffset
+ local subtables={}
+ for i=1,nofsizetables do
+ sizetables[i]={
+ subtables=readulong(f),
+ indexsize=readulong(f),
+ nofsubtables=readulong(f),
+ colorref=readulong(f),
+ hormetrics=getmetrics(f),
+ vermetrics=getmetrics(f),
+ firstindex=readushort(f),
+ lastindex=readushort(f),
+ ppemx=readbyte(f),
+ ppemy=readbyte(f),
+ bitdepth=readbyte(f),
+ flags=readbyte(f),
}
end
- sort(strikes,function(a,b)
- if b.ppem==a.ppem then
- return b.ppi<a.ppi
+ sort(sizetables,function(a,b)
+ if b.ppemx==a.ppemx then
+ return b.bitdepth<a.bitdepth
else
- return b.ppem<a.ppem
+ return b.ppemx<a.ppemx
end
end)
- local glyphs={}
- for i=1,nofstrikes do
- local strike=strikes[i]
- local strikeppem=strike.ppem
- local strikeppi=strike.ppi
- local strikeoffset=strike.offset
- setposition(f,strikeoffset)
- for i=0,nofglyphs do
- glyphs[i]=readulong(f)
- end
- local glyphoffset=glyphs[0]
- for i=0,nofglyphs-1 do
- local nextoffset=glyphs[i+1]
- if not shapes[i] then
- local datasize=nextoffset-glyphoffset
- if datasize>0 then
- setposition(f,strikeoffset+glyphoffset)
- shapes[i]={
- x=readshort(f),
- y=readshort(f),
- tag=readtag(f),
- data=readstring(f,datasize-8),
- ppem=strikeppem,
- ppi=strikeppi,
- }
- done=done+1
- if done==nofglyphs then
- break
+ for i=1,nofsizetables do
+ local s=sizetables[i]
+ local d=false
+ for j=s.firstindex,s.lastindex do
+ if not shapes[j] then
+ shapes[j]=i
+ d=true
+ end
+ end
+ if d then
+ s.used=true
+ end
+ end
+ for i=1,nofsizetables do
+ local s=sizetables[i]
+ if s.used then
+ local offset=s.subtables
+ setposition(f,cblctableoffset+offset)
+ for j=1,s.nofsubtables do
+ local firstindex=readushort(f)
+ local lastindex=readushort(f)
+ local tableoffset=readulong(f)+offset
+ for k=firstindex,lastindex do
+ if shapes[k]==i then
+ local s=subtables[tableoffset]
+ if not s then
+ s={
+ firstindex=firstindex,
+ lastindex=lastindex,
+ }
+ subtables[tableoffset]=s
+ end
+ shapes[k]=s
end
end
end
- glyphoffset=nextoffset
end
end
- fontdata.sbixshapes=shapes
+ for offset,subtable in sortedhash(subtables) do
+ local tabletype=readushort(f)
+ subtable.format=readushort(f)
+ local baseoffset=readulong(f)+ctdttableoffset
+ local offsets={}
+ local metrics=nil
+ if tabletype==1 then
+ for i=subtable.firstindex,subtable.lastindex do
+ offsets[i]=readulong(f)+baseoffset
+ end
+ skipbytes(f,4)
+ elseif tabletype==2 then
+ local size=readulong(f)
+ local done=baseoffset
+ metrics=getbigmetrics(f)
+ for i=subtable.firstindex,subtable.lastindex do
+ offsets[i]=done
+ done=done+size
+ end
+ elseif tabletype==3 then
+ local n=subtable.lastindex-subtable.firstindex+2
+ for i=subtable.firstindex,subtable.lastindex do
+ offsets[i]=readushort(f)+baseoffset
+ end
+ if math.odd(n) then
+ skipbytes(f,4)
+ else
+ skipbytes(f,2)
+ end
+ elseif tabletype==4 then
+ for i=1,readulong(f) do
+ offsets[readushort(f)]=readushort(f)+baseoffset
+ end
+ elseif tabletype==5 then
+ local size=readulong(f)
+ local done=baseoffset
+ metrics=getbigmetrics(f)
+ local n=readulong(f)
+ for i=1,n do
+ offsets[readushort(f)]=done
+ done=done+size
+ end
+ if math.odd(n) then
+ skipbytes(f,2)
+ end
+ else
+ return
+ end
+ subtable.offsets=offsets
+ subtable.metrics=metrics
+ end
+ local default={ width=0,height=0 }
+ local glyphs=fontdata.glyphs
+ for index,subtable in sortedhash(shapes) do
+ if type(subtable)=="table" then
+ local data=nil
+ local metrics=default
+ local format=subtable.format
+ local offset=subtable.offsets[index]
+ setposition(f,offset)
+ if format==17 then
+ metrics=getsmallmetrics(f)
+ data=readstring(f,readulong(f))
+ elseif format==18 then
+ metrics=getbigmetrics(f)
+ data=readstring(f,readulong(f))
+ elseif format==19 then
+ metrics=subtable.metrics
+ data=readstring(f,readulong(f))
+ else
+ end
+ local x=metrics.width
+ local y=metrics.height
+ shapes[index]={
+ x=x,
+ y=y,
+ data=data,
+ }
+ local glyph=glyphs[index]
+ if not glyph.boundingbox then
+ local width=glyph.width
+ local height=width*y/x
+ glyph.boundingbox={ 0,0,width,height }
+ end
+ else
+ shapes[index]={
+ x=0,
+ y=0,
+ data="",
+ }
+ end
+ end
+ fontdata.pngshapes=shapes
+ end
+ end
+ function readers.cbdt(f,fontdata,specification)
end
end
function readers.stat(f,fontdata,specification)
@@ -19986,8 +19777,7 @@ function readers.avar(f,fontdata,specification)
end
return false
end
- local majorversion=readushort(f)
- local minorversion=readushort(f)
+ local version=readulong(f)
local reserved=readushort(f)
local nofaxis=readushort(f)
local segments={}
@@ -20877,7 +20667,7 @@ local function unifymissing(fontdata)
fonts.mappings.addtounicode(fontdata,fontdata.filename,checklookups)
resources.unicodes=nil
end
-local firstprivate=fonts.privateoffsets.textbase or 0xF0000
+local firstprivate=fonts.privateoffsets and fonts.privateoffsets.textbase or 0xF0000
local puafirst=0xE000
local pualast=0xF8FF
local function unifyglyphs(fontdata,usenames)
@@ -22832,13 +22622,13 @@ 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.106
+otf.version=3.107
otf.cache=containers.define("fonts","otl",otf.version,true)
otf.svgcache=containers.define("fonts","svg",otf.version,true)
-otf.sbixcache=containers.define("fonts","sbix",otf.version,true)
+otf.pngcache=containers.define("fonts","png",otf.version,true)
otf.pdfcache=containers.define("fonts","pdf",otf.version,true)
otf.svgenabled=false
-otf.sbixenabled=false
+otf.pngenabled=false
local otfreaders=otf.readers
local hashes=fonts.hashes
local definers=fonts.definers
@@ -22906,7 +22696,7 @@ function otf.load(filename,sub,instance)
report_otf("forced reload of %a due to hard coded flag",filename)
reload=true
end
- if reload then
+ if reload then
report_otf("loading %a, hash %a",filename,hash)
starttiming(otfreaders,true)
data=otfreaders.loadfont(filename,sub or 1,instance)
@@ -22914,7 +22704,7 @@ function otf.load(filename,sub,instance)
local used=checkmemory()
local resources=data.resources
local svgshapes=resources.svgshapes
- local sbixshapes=resources.sbixshapes
+ local pngshapes=resources.pngshapes
if cleanup==0 then
checkmemory(used,threshold,tracememory)
end
@@ -22937,15 +22727,15 @@ function otf.load(filename,sub,instance)
checkmemory(used,threshold,tracememory)
end
end
- if sbixshapes then
- resources.sbixshapes=nil
- if otf.sbixenabled then
+ if pngshapes then
+ resources.pngshapes=nil
+ if otf.pngenabled then
local timestamp=os.date()
- containers.write(otf.sbixcache,hash,{
- sbixshapes=sbixshapes,
+ containers.write(otf.pngcache,hash,{
+ pngshapes=pngshapes,
timestamp=timestamp,
})
- data.properties.sbix={
+ data.properties.png={
hash=hash,
timestamp=timestamp,
}
@@ -26345,22 +26135,17 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature,rlmode,skip
else
end
end
- else
+ else
local discfound=false
- local lastdisc=nil
local hasmarks=marks[startchar]
while current do
local char,id=ischar(current,currentfont)
if char then
if skiphash and skiphash[char] then
current=getnext(current)
- else
- local lg=ligature[char]
+ else
+ local lg=ligature[char]
if lg then
- if not discfound and lastdisc then
- discfound=lastdisc
- lastdisc=nil
- end
if marks[char] then
hasmarks=true
end
@@ -26374,42 +26159,82 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature,rlmode,skip
elseif char==false then
break
elseif id==disc_code then
- local replace=getfield(current,"replace")
- if replace then
- while replace do
- local char,id=ischar(replace,currentfont)
- if char then
- local lg=ligature[char]
- if lg then
- if marks[char] then
- hasmarks=true
- end
- ligature=lg
- replace=getnext(replace)
- else
- return head,start,false,false
- end
- else
- return head,start,false,false
- end
- end
- stop=current
- end
- lastdisc=current
- current=getnext(current)
+ discfound=current
+ break
else
break
end
end
+ if discfound then
+ local pre,post,replace=getdisc(discfound)
+ local match
+ if replace then
+ local char=ischar(replace,currentfont)
+ if char and ligature[char] then
+ match=true
+ end
+ end
+ if not match and pre then
+ local char=ischar(pre,currentfont)
+ if char and ligature[char] then
+ match=true
+ end
+ end
+ if not match and not pre or not replace then
+ local n=getnext(discfound)
+ local char=ischar(n,currentfont)
+ if char and ligature[char] then
+ match=true
+ end
+ end
+ if match then
+ local ishead=head==start
+ local prev=getprev(start)
+ if stop then
+ setnext(stop)
+ local tail=getprev(stop)
+ local copy=copy_node_list(start)
+ local liat=find_node_tail(copy)
+ if pre and replace then
+ setlink(liat,pre)
+ end
+ if replace then
+ setlink(tail,replace)
+ end
+ pre=copy
+ replace=start
+ else
+ setnext(start)
+ local copy=copy_node(start)
+ if pre then
+ setlink(copy,pre)
+ end
+ if replace then
+ setlink(start,replace)
+ end
+ pre=copy
+ replace=start
+ end
+ setdisc(discfound,pre,post,replace)
+ if prev then
+ setlink(prev,discfound)
+ else
+ setprev(discfound)
+ head=discfound
+ end
+ start=discfound
+ return head,start,true,true
+ end
+ end
local lig=ligature.ligature
if lig then
if stop then
if trace_ligatures then
local stopchar=getchar(stop)
- head,start=toligature(head,start,stop,lig,dataset,sequence,skiphash,discfound,hasmarks)
+ head,start=toligature(head,start,stop,lig,dataset,sequence,skiphash,false,hasmarks)
logprocess("%s: replacing %s upto %s by ligature %s case 2",pref(dataset,sequence),gref(startchar),gref(stopchar),gref(lig))
else
- head,start=toligature(head,start,stop,lig,dataset,sequence,skiphash,discfound,hasmarks)
+ head,start=toligature(head,start,stop,lig,dataset,sequence,skiphash,false,hasmarks)
end
else
resetinjection(start)
@@ -26418,11 +26243,11 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature,rlmode,skip
logprocess("%s: replacing %s by (no real) ligature %s case 3",pref(dataset,sequence),gref(startchar),gref(lig))
end
end
- return head,start,true,discfound
+ return head,start,true,false
else
end
end
- return head,start,false,discfound
+ return head,start,false,false
end
function handlers.gpos_single(head,start,dataset,sequence,kerns,rlmode,skiphash,step,injection)
local startchar=getchar(start)
@@ -28901,9 +28726,10 @@ do
a=true
end
if a then
- local ok
- head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,skiphash,step)
- if start then
+ local ok,df
+ head,start,ok,df=handler(head,start,dataset,sequence,lookupmatch,rlmode,skiphash,step)
+ if df then
+ elseif start then
start=getnext(start)
end
else
@@ -28957,21 +28783,24 @@ do
a=true
end
if a then
+ local ok,df
for i=m[1],m[2] do
local step=steps[i]
local lookupcache=step.coverage
local lookupmatch=lookupcache[char]
if lookupmatch then
- local ok
- head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,skiphash,step)
- if ok then
+ head,start,ok,df=handler(head,start,dataset,sequence,lookupmatch,rlmode,skiphash,step)
+ if df then
+ break
+ elseif ok then
break
elseif not start then
break
end
end
end
- if start then
+ if df then
+ elseif start then
start=getnext(start)
end
else
@@ -31348,11 +31177,13 @@ else
sharedpalettes[name]=values
for i=1,#values do
local v=values[i]
- values[i]=hash[f_color(
- max(round((v.r or 0)*255),255)/255,
- max(round((v.g or 0)*255),255)/255,
- max(round((v.b or 0)*255),255)/255
- )]
+ if v then
+ values[i]=hash[f_color(
+ max(round((v.r or 0)*255),255)/255,
+ max(round((v.g or 0)*255),255)/255,
+ max(round((v.b or 0)*255),255)/255
+ )]
+ end
end
end
end
@@ -31376,7 +31207,7 @@ local pop={ "pdf","page","Q" }
if not LUATEXFUNCTIONALITY or LUATEXFUNCTIONALITY<6472 then
start={ "nop" }
end
-local function initialize(tfmdata,kind,value)
+local function initialize(tfmdata,kind,value)
if value then
local resources=tfmdata.resources
local palettes=resources.colorpalettes
@@ -31386,7 +31217,13 @@ local function initialize(tfmdata,kind,value)
converted=setmetatableindex(convert)
resources.converted=converted
end
- local colorvalues=sharedpalettes[value] or converted[palettes[tonumber(value) or 1] or palettes[1]] or {}
+ local colorvalues=sharedpalettes[value]
+ local default=false
+ if colorvalues then
+ default=colorvalues[#colorvalues]
+ else
+ colorvalues=converted[palettes[tonumber(value) or 1] or palettes[1]] or {}
+ end
local classes=#colorvalues
if classes==0 then
return
@@ -31399,7 +31236,6 @@ local function initialize(tfmdata,kind,value)
{ id=0 }
}
local getactualtext=otf.getactualtext
- local default=colorvalues[#colorvalues]
local b,e=getactualtext(tounicode(0xFFFD))
local actualb={ "pdf","page",b }
local actuale={ "pdf","page",e }
@@ -31430,6 +31266,12 @@ local function initialize(tfmdata,kind,value)
f=true
n=n+1 t[n]=v
l=v
+ else
+ if f then
+ n=n+1 t[n]=pop
+ end
+ f=false
+ l=nil
end
n=n+1 t[n]=charcommand[entry.slot]
if s>1 and i<s and goback then
@@ -31472,7 +31314,7 @@ do
done=f_used(n)
hashed[pdf]=done
end
- return nil,done,nil
+ return done
end
else
local openpdf=pdfe.new
@@ -31485,7 +31327,7 @@ do
done=f_used(n)
hashed[pdf]=done
end
- return nil,done,nil
+ return done
end
end
end
@@ -31506,6 +31348,10 @@ local function pdftovirtual(tfmdata,pdfshapes,kind)
local b,e=getactualtext(tounicode(0xFFFD))
local actualb={ "pdf","page",b }
local actuale={ "pdf","page",e }
+ local vfimage=lpdf and lpdf.vfimage or function(wd,ht,dp,data,name)
+ local name=storepdfdata(data)
+ return { "image",{ filename=name,width=wd,height=ht,depth=dp } }
+ end
for unicode,character in sortedhash(characters) do
local index=character.index
if index then
@@ -31524,21 +31370,18 @@ local function pdftovirtual(tfmdata,pdfshapes,kind)
dy=0
end
if data then
- local setcode,name,nilcode=storepdfdata(data)
- if name then
- local bt=unicode and getactualtext(unicode)
- local wd=character.width or 0
- local ht=character.height or 0
- local dp=character.depth or 0
- character.commands={
- not unicode and actualb or { "pdf","page",(getactualtext(unicode)) },
- downcommand[dp+dy*hfactor],
- rightcommand[dx*hfactor],
- { "image",{ filename=name,width=wd,height=ht,depth=dp } },
- actuale,
- }
- character[kind]=true
- end
+ local bt=unicode and getactualtext(unicode)
+ local wd=character.width or 0
+ local ht=character.height or 0
+ local dp=character.depth or 0
+ character.commands={
+ not unicode and actualb or { "pdf","page",(getactualtext(unicode)) },
+ downcommand[dp+dy*hfactor],
+ rightcommand[dx*hfactor],
+ vfimage(wd,ht,dp,data,name),
+ actuale,
+ }
+ character[kind]=true
end
end
end
@@ -31654,40 +31497,40 @@ fonts.handlers.otf.features.register {
node=initializesvg,
}
}
-local otfsbix=otf.sbix or {}
-otf.sbix=otfsbix
-otf.sbixenabled=true
+local otfpng=otf.png or {}
+otf.png=otfpng
+otf.pngenabled=true
do
- local report_sbix=logs.reporter("fonts","sbix conversion")
+ local report_png=logs.reporter("fonts","png conversion")
local loaddata=io.loaddata
local savedata=io.savedata
local remove=os.remove
local runner=sandbox and sandbox.registerrunner {
- name="otfsbix",
+ name="otfpng",
program="gm",
- template="convert -quality 100 temp-otf-sbix-shape.sbix temp-otf-sbix-shape.pdf > temp-otf-svg-shape.log",
+ template="convert -quality 100 temp-otf-png-shape.png temp-otf-png-shape.pdf > temp-otf-svg-shape.log",
}
if not runner then
runner=function()
- return os.execute("gm convert -quality 100 temp-otf-sbix-shape.sbix temp-otf-sbix-shape.pdf > temp-otf-svg-shape.log")
+ return os.execute("gm convert -quality 100 temp-otf-png-shape.png temp-otf-png-shape.pdf > temp-otf-svg-shape.log")
end
end
- function otfsbix.topdf(sbixshapes)
+ function otfpng.topdf(pngshapes)
local pdfshapes={}
- local sbixfile="temp-otf-sbix-shape.sbix"
- local pdffile="temp-otf-sbix-shape.pdf"
+ local pngfile="temp-otf-png-shape.png"
+ local pdffile="temp-otf-png-shape.pdf"
local nofdone=0
- local indices=sortedkeys(sbixshapes)
+ local indices=sortedkeys(pngshapes)
local nofindices=#indices
- report_sbix("processing %i sbix containers",nofindices)
+ report_png("processing %i png containers",nofindices)
statistics.starttiming()
for i=1,nofindices do
local index=indices[i]
- local entry=sbixshapes[index]
- local data=entry.data
+ local entry=pngshapes[index]
+ local data=entry.data
local x=entry.x
local y=entry.y
- savedata(sbixfile,data)
+ savedata(pngfile,data)
runner()
pdfshapes[index]={
x=x~=0 and x or nil,
@@ -31696,47 +31539,55 @@ do
}
nofdone=nofdone+1
if nofdone%100==0 then
- report_sbix("%i shapes processed",nofdone)
+ report_png("%i shapes processed",nofdone)
end
end
- report_sbix("processing %i pdf results",nofindices)
- remove(sbixfile)
+ report_png("processing %i pdf results",nofindices)
+ remove(pngfile)
remove(pdffile)
statistics.stoptiming()
if statistics.elapsedseconds then
- report_sbix("sbix conversion time %s",statistics.elapsedseconds() or "-")
+ report_png("png conversion time %s",statistics.elapsedseconds() or "-")
end
return pdfshapes
end
end
-local function initializesbix(tfmdata,kind,value)
- if value and otf.sbixenabled then
- local sbix=tfmdata.properties.sbix
- local hash=sbix and sbix.hash
- local timestamp=sbix and sbix.timestamp
+local function initializepng(tfmdata,kind,value)
+ if value and otf.pngenabled then
+ local png=tfmdata.properties.png
+ local hash=png and png.hash
+ local timestamp=png and png.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 sbixfile=containers.read(otf.sbixcache,hash)
- local sbixshapes=sbixfile and sbixfile.sbixshapes
- pdfshapes=sbixshapes and otfsbix.topdf(sbixshapes) or {}
+ local pngfile=containers.read(otf.pngcache,hash)
+ local pngshapes=pngfile and pngfile.pngshapes
+ pdfshapes=pngshapes and otfpng.topdf(pngshapes) or {}
containers.write(otf.pdfcache,hash,{
pdfshapes=pdfshapes,
timestamp=timestamp,
})
end
- pdftovirtual(tfmdata,pdfshapes,"sbix")
+ pdftovirtual(tfmdata,pdfshapes,"png")
end
end
fonts.handlers.otf.features.register {
name="sbix",
description="sbix glyphs",
manipulators={
- base=initializesbix,
- node=initializesbix,
+ base=initializepng,
+ node=initializepng,
+ }
+}
+fonts.handlers.otf.features.register {
+ name="cblc",
+ description="cblc glyphs",
+ manipulators={
+ base=initializepng,
+ node=initializepng,
}
}
@@ -32508,7 +32359,7 @@ local match,lower,gsub,strip,find=string.match,string.lower,string.gsub,string.s
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,Cf,Cg=lpeg.P,lpeg.S,lpeg.R,lpeg.Cmt,lpeg.C,lpeg.Ct,lpeg.Cs,lpeg.Carg,lpeg.Cf,lpeg.Cg
+local P,S,R,V,Cmt,C,Ct,Cs,Carg,Cf,Cg,Cc=lpeg.P,lpeg.S,lpeg.R,lpeg.V,lpeg.Cmt,lpeg.C,lpeg.Ct,lpeg.Cs,lpeg.Carg,lpeg.Cf,lpeg.Cg,lpeg.Cc
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)
@@ -32551,14 +32402,21 @@ do
local routines,vector,chars,n,m
local initialize=function(str,position,size)
n=0
- m=size
+ m=size
return position+1
end
local setroutine=function(str,position,index,size,filename)
- local forward=position+tonumber(size)
+ if routines[index] then
+ return false
+ end
+ local forward=position+size
local stream=decrypt(sub(str,position+1,forward),4330,4)
routines[index]={ byte(stream,1,#stream) }
- return forward
+ n=n+1
+ if n>=m then
+ return #str
+ end
+ return forward+1
end
local setvector=function(str,position,name,size,filename)
local forward=position+tonumber(size)
@@ -32598,7 +32456,7 @@ do
local p_np=spacing*(P("NP")+P("|"))
local p_nd=spacing*(P("ND")+P("|"))
local p_filterroutines=
- (1-subroutines)^0*subroutines*spaces*Cmt(cardinal,initialize)*(Cmt(cardinal*spaces*cardinal*p_rd*Carg(1),setroutine)*p_np+P(1))^1
+ (1-subroutines)^0*subroutines*spaces*Cmt(cardinal,initialize)*(Cmt(cardinal*spaces*cardinal*p_rd*Carg(1),setroutine)*p_np+(1-p_nd))^1
local p_filtershapes=
(1-charstrings)^0*charstrings*spaces*Cmt(cardinal,initialize)*(Cmt(name*spaces*cardinal*p_rd*Carg(1),setshapes)*p_nd+P(1))^1
local p_filternames=Ct (
@@ -32607,7 +32465,18 @@ do
local p_filterencoding=(1-encoding)^0*encoding*spaces*digits*spaces*array*(1-dup)^0*Cf(
Ct("")*Cg(spacing*dup*spaces*cardinal*spaces*name*spaces*put)^1
,rawset)
- local function loadpfbvector(filename,shapestoo)
+ local key=spacing*P("/")*R("az","AZ")
+ local str=spacing*Cs { (P("(")/"")*((1-P("\\(")-P("\\)")-S("()"))+V(1))^0*(P(")")/"") }
+ local num=spacing*(R("09")+S("+-."))^1/tonumber
+ local arr=spacing*Ct (S("[{")*(num)^0*spacing*S("]}"))
+ local boo=spacing*(P("true")*Cc(true)+P("false")*Cc(false))
+ local nam=spacing*P("/")*Cs(R("az","AZ")^1)
+ local p_filtermetadata=(
+ P("/")*Carg(1)*((
+ C("version")*str+C("Copyright")*str+C("Notice")*str+C("FullName")*str+C("FamilyName")*str+C("Weight")*str+C("ItalicAngle")*num+C("isFixedPitch")*boo+C("UnderlinePosition")*num+C("UnderlineThickness")*num+C("FontName")*nam+C("FontMatrix")*arr+C("FontBBox")*arr
+ ) )/function(t,k,v) t[lower(k)]=v end+P(1)
+ )^0*Carg(1)
+ local function loadpfbvector(filename,shapestoo,streams)
local data=io.loaddata(resolvers.findfile(filename))
if not data then
report_pfb("no data in %a",filename)
@@ -32625,9 +32494,10 @@ do
binary=decrypt(binary,55665,4)
local names={}
local encoding=lpegmatch(p_filterencoding,ascii)
+ local metadata=lpegmatch(p_filtermetadata,ascii,1,{})
local glyphs={}
routines,vector,chars={},{},{}
- if shapestoo then
+ if shapestoo or streams then
lpegmatch(p_filterroutines,binary,1,filename)
lpegmatch(p_filtershapes,binary,1,filename)
local data={
@@ -32639,13 +32509,13 @@ do
}
},
}
- fonts.handlers.otf.readers.parsecharstrings(false,data,glyphs,true,true)
+ fonts.handlers.otf.readers.parsecharstrings(false,data,glyphs,true,"cff",streams)
else
lpegmatch(p_filternames,binary,1,filename)
end
names=vector
routines,vector,chars=nil,nil,nil
- return names,encoding,glyphs
+ return names,encoding,glyphs,metadata
end
local pfb=handlers.pfb or {}
handlers.pfb=pfb
@@ -33731,6 +33601,7 @@ if not modules then modules={} end modules ['font-tfm']={
local next,type=next,type
local match,format=string.match,string.format
local concat,sortedhash=table.concat,table.sortedhash
+local idiv=number.idiv
local trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end)
local trace_features=false trackers.register("tfm.features",function(v) trace_features=v end)
local report_defining=logs.reporter("fonts","defining")
@@ -33766,147 +33637,190 @@ function tfm.setfeatures(tfmdata,features)
end
end
local depth={}
-local function read_from_tfm(specification)
- local filename=specification.filename
- local size=specification.size
- depth[filename]=(depth[filename] or 0)+1
- if trace_defining then
- report_defining("loading tfm file %a at size %s",filename,size)
- end
- local tfmdata=font.read_tfm(filename,size)
- if tfmdata then
- local features=specification.features and specification.features.normal or {}
- local features=constructors.checkedfeatures("tfm",features)
- specification.features.normal=features
- local newtfmdata=(depth[filename]==1) and tfm.reencode(tfmdata,specification)
- if newtfmdata then
- tfmdata=newtfmdata
+local read_from_tfm,check_tfm do
+ local tfmreaders=context and tfm.readers
+ local loadtfmvf=tfmreaders and tfmreaders.loadtfmvf
+ local loadtfm=font.read_tfm
+ local loadvf=font.read_vf
+ directives.register("fonts.tfm.builtin",function(v)
+ loadtfmvf=tfmreaders and tfmreaders.loadtfmvf
+ if v and loadtfm then
+ loadtfmvf=false
end
- local resources=tfmdata.resources or {}
- local properties=tfmdata.properties or {}
- local parameters=tfmdata.parameters or {}
- local shared=tfmdata.shared or {}
- shared.features=features
- shared.resources=resources
- properties.name=tfmdata.name
- properties.fontname=tfmdata.fontname
- properties.psname=tfmdata.psname
- properties.fullname=tfmdata.fullname
- properties.filename=specification.filename
- properties.format=fonts.formats.tfm
- tfmdata.properties=properties
- tfmdata.resources=resources
- tfmdata.parameters=parameters
- tfmdata.shared=shared
- shared.rawdata={ resources=resources }
- shared.features=features
- if newtfmdata then
- if not resources.marks then
- resources.marks={}
- end
- if not resources.sequences then
- resources.sequences={}
- end
- if not resources.features then
- resources.features={
- gsub={},
- gpos={},
- }
- end
- if not tfmdata.changed then
- tfmdata.changed={}
- end
- if not tfmdata.descriptions then
- tfmdata.descriptions=tfmdata.characters
- end
- otf.readers.addunicodetable(tfmdata)
- tfmenhancers.apply(tfmdata,filename)
- constructors.applymanipulators("tfm",tfmdata,features,trace_features,report_tfm)
- otf.readers.unifymissing(tfmdata)
- fonts.mappings.addtounicode(tfmdata,filename)
- tfmdata.tounicode=1
- local tounicode=fonts.mappings.tounicode
- for unicode,v in next,tfmdata.characters do
- local u=v.unicode
- if u then
- v.tounicode=tounicode(u)
- end
- end
- if tfmdata.usedbitmap then
- tfm.addtounicode(tfmdata)
- end
- end
- shared.processes=next(features) and tfm.setfeatures(tfmdata,features) or nil
- parameters.factor=1
- parameters.size=size
- parameters.slant=parameters.slant or parameters[1] or 0
- parameters.space=parameters.space or parameters[2] or 0
- parameters.space_stretch=parameters.space_stretch or parameters[3] or 0
- parameters.space_shrink=parameters.space_shrink or parameters[4] or 0
- parameters.x_height=parameters.x_height or parameters[5] or 0
- parameters.quad=parameters.quad or parameters[6] or 0
- parameters.extra_space=parameters.extra_space or parameters[7] or 0
- constructors.enhanceparameters(parameters)
- properties.private=properties.private or tfmdata.private or privateoffset
- if newtfmdata then
- elseif constructors.resolvevirtualtoo then
- fonts.loggers.register(tfmdata,file.suffix(filename),specification)
- local vfname=findbinfile(specification.name,'ovf')
- if vfname and vfname~="" then
- local vfdata=font.read_vf(vfname,size)
- if vfdata then
- local chars=tfmdata.characters
- for k,v in next,vfdata.characters do
- chars[k].commands=v.commands
- end
- properties.virtualized=true
- tfmdata.fonts=vfdata.fonts
- tfmdata.type="virtual"
- local fontlist=vfdata.fonts
- local name=file.nameonly(filename)
- for i=1,#fontlist do
- local n=fontlist[i].name
- local s=fontlist[i].size
- local d=depth[filename]
- s=constructors.scaled(s,vfdata.designsize)
- if d>tfm.maxnestingdepth then
- report_defining("too deeply nested virtual font %a with size %a, max nesting depth %s",n,s,tfm.maxnestingdepth)
- fontlist[i]={ id=0 }
- elseif (d>1) and (s>tfm.maxnestingsize) then
- report_defining("virtual font %a exceeds size %s",n,s)
- fontlist[i]={ id=0 }
- else
- local t,id=fonts.constructors.readanddefine(n,s)
- fontlist[i]={ id=id }
+ end)
+ read_from_tfm=function(specification)
+ local filename=specification.filename
+ local size=specification.size
+ depth[filename]=(depth[filename] or 0)+1
+ if trace_defining then
+ report_defining("loading tfm file %a at size %s",filename,size)
+ end
+ local tfmdata
+ if loadtfmvf then
+ tfmdata=loadtfmvf(filename,size)
+ else
+ tfmdata=loadtfm(filename,size)
+ end
+ if tfmdata then
+ local features=specification.features and specification.features.normal or {}
+ local features=constructors.checkedfeatures("tfm",features)
+ specification.features.normal=features
+ local newtfmdata=(depth[filename]==1) and tfm.reencode(tfmdata,specification)
+ if newtfmdata then
+ tfmdata=newtfmdata
+ end
+ local resources=tfmdata.resources or {}
+ local properties=tfmdata.properties or {}
+ local parameters=tfmdata.parameters or {}
+ local shared=tfmdata.shared or {}
+ shared.features=features
+ shared.resources=resources
+ properties.name=tfmdata.name
+ properties.fontname=tfmdata.fontname
+ properties.psname=tfmdata.psname
+ properties.fullname=tfmdata.fullname
+ properties.filename=specification.filename
+ properties.format=tfmdata.format or fonts.formats.tfm
+ properties.usedbitmap=tfmdata.usedbitmap
+ tfmdata.properties=properties
+ tfmdata.resources=resources
+ tfmdata.parameters=parameters
+ tfmdata.shared=shared
+ shared.rawdata={ resources=resources }
+ shared.features=features
+ if newtfmdata then
+ if not resources.marks then
+ resources.marks={}
+ end
+ if not resources.sequences then
+ resources.sequences={}
+ end
+ if not resources.features then
+ resources.features={
+ gsub={},
+ gpos={},
+ }
+ end
+ if not tfmdata.changed then
+ tfmdata.changed={}
+ end
+ if not tfmdata.descriptions then
+ tfmdata.descriptions=tfmdata.characters
+ end
+ otf.readers.addunicodetable(tfmdata)
+ tfmenhancers.apply(tfmdata,filename)
+ constructors.applymanipulators("tfm",tfmdata,features,trace_features,report_tfm)
+ otf.readers.unifymissing(tfmdata)
+ fonts.mappings.addtounicode(tfmdata,filename)
+ tfmdata.tounicode=1
+ local tounicode=fonts.mappings.tounicode
+ for unicode,v in next,tfmdata.characters do
+ local u=v.unicode
+ if u then
+ v.tounicode=tounicode(u)
+ end
+ end
+ if tfmdata.usedbitmap then
+ tfm.addtounicode(tfmdata)
+ end
+ end
+ shared.processes=next(features) and tfm.setfeatures(tfmdata,features) or nil
+ if size<0 then
+ size=idiv(65536*-size,100)
+ end
+ parameters.factor=1
+ parameters.units=1000
+ parameters.size=size
+ parameters.slant=parameters.slant or parameters[1] or 0
+ parameters.space=parameters.space or parameters[2] or 0
+ parameters.space_stretch=parameters.space_stretch or parameters[3] or 0
+ parameters.space_shrink=parameters.space_shrink or parameters[4] or 0
+ parameters.x_height=parameters.x_height or parameters[5] or 0
+ parameters.quad=parameters.quad or parameters[6] or 0
+ parameters.extra_space=parameters.extra_space or parameters[7] or 0
+ constructors.enhanceparameters(parameters)
+ properties.private=properties.private or tfmdata.private or privateoffset
+ if newtfmdata then
+ elseif loadtfmvf then
+ local fonts=tfmdata.fonts
+ if fonts then
+ for i=1,#fonts do
+ local font=fonts[i]
+ local id=font.id
+ if not id then
+ local name=font.name
+ local size=font.size
+ if name and size then
+ local data,id=constructors.readanddefine(name,size)
+ if id then
+ font.id=id
+ font.name=nil
+ font.size=nil
+ end
+ end
+ end
+ end
+ end
+ elseif constructors.resolvevirtualtoo then
+ fonts.loggers.register(tfmdata,file.suffix(filename),specification)
+ local vfname=findbinfile(specification.name,'ovf')
+ if vfname and vfname~="" then
+ local vfdata=loadvf(vfname,size)
+ if vfdata then
+ local chars=tfmdata.characters
+ for k,v in next,vfdata.characters do
+ chars[k].commands=v.commands
+ end
+ properties.virtualized=true
+ tfmdata.fonts=vfdata.fonts
+ tfmdata.type="virtual"
+ local fontlist=vfdata.fonts
+ local name=file.nameonly(filename)
+ for i=1,#fontlist do
+ local n=fontlist[i].name
+ local s=fontlist[i].size
+ local d=depth[filename]
+ s=constructors.scaled(s,vfdata.designsize)
+ if d>tfm.maxnestingdepth then
+ report_defining("too deeply nested virtual font %a with size %a, max nesting depth %s",n,s,tfm.maxnestingdepth)
+ fontlist[i]={ id=0 }
+ elseif (d>1) and (s>tfm.maxnestingsize) then
+ report_defining("virtual font %a exceeds size %s",n,s)
+ fontlist[i]={ id=0 }
+ else
+ local t,id=constructors.readanddefine(n,s)
+ fontlist[i]={ id=id }
+ end
end
end
end
end
+ properties.haskerns=true
+ properties.hasligatures=true
+ properties.hasitalics=true
+ resources.unicodes={}
+ resources.lookuptags={}
+ depth[filename]=depth[filename]-1
+ return tfmdata
+ else
+ depth[filename]=depth[filename]-1
end
- properties.haskerns=true
- properties.hasligatures=true
- resources.unicodes={}
- resources.lookuptags={}
- depth[filename]=depth[filename]-1
- return tfmdata
- else
- depth[filename]=depth[filename]-1
end
-end
-local function check_tfm(specification,fullname)
- local foundname=findbinfile(fullname,'tfm') or ""
- if foundname=="" then
- foundname=findbinfile(fullname,'ofm') or ""
- end
- if foundname=="" then
- foundname=fonts.names.getfilename(fullname,"tfm") or ""
- end
- if foundname~="" then
- specification.filename=foundname
- specification.format="ofm"
- return read_from_tfm(specification)
- elseif trace_defining then
- report_defining("loading tfm with name %a fails",specification.name)
+ check_tfm=function(specification,fullname)
+ local foundname=findbinfile(fullname,'tfm') or ""
+ if foundname=="" then
+ foundname=findbinfile(fullname,'ofm') or ""
+ end
+ if foundname=="" then
+ foundname=fonts.names.getfilename(fullname,"tfm") or ""
+ end
+ if foundname~="" then
+ specification.filename=foundname
+ specification.format="ofm"
+ return read_from_tfm(specification)
+ elseif trace_defining then
+ report_defining("loading tfm with name %a fails",specification.name)
+ end
end
end
readers.check_tfm=check_tfm
@@ -33966,7 +33880,7 @@ do
local encoding=false
local vector=false
if type(pfbfile)=="string" then
- local pfb=fonts.constructors.handlers.pfb
+ local pfb=constructors.handlers.pfb
if pfb and pfb.loadvector then
local v,e=pfb.loadvector(pfbfile)
if v then
@@ -33994,7 +33908,7 @@ do
local originals=tfmdata.characters
local indices={}
local parentfont={ "font",1 }
- local private=tfmdata or fonts.constructors.privateoffset
+ local private=tfmdata.privateoffset or constructors.privateoffset
local reported=encdone[tfmfile][encfile]
local backmap=vector and table.swapped(vector)
local done={}
@@ -34084,21 +33998,16 @@ CMapName currentdict /CMap defineresource pop end
end
end
]]
- local flushstreamobject=lpdf and lpdf.flushstreamobject
- local setfontattributes=pdf.setfontattributes
- if flushstreamobject then
- else
+ local flushstreamobject=lpdf and lpdf.flushstreamobject
+ local setfontattributes=lpdf and lpdf.setfontattributes
+ if not flushstreamobject then
flushstreamobject=function(data)
- return pdf.obj {
- immediate=true,
- type="stream",
- string=data,
- }
+ return pdf.obj { immediate=true,type="stream",string=data }
end
end
if not setfontattributes then
setfontattributes=function(id,data)
- print(format("your luatex is too old so no tounicode bitmap font%i",id))
+ return pdf.setfontattributes(id,data)
end
end
function tfm.addtounicode(tfmdata)
@@ -34373,9 +34282,6 @@ function resolvers.name(specification)
features.normal=normal
end
normal.instance=instance
- if not callbacks.supported.glyph_stream_provider then
- normal.variableshapes=true
- end
end
local suffix=lower(suffixonly(resolved))
if fonts.formats[suffix] then
@@ -35233,7 +35139,7 @@ do -- begin closure to overcome local limits and interference
if not modules then modules={} end modules ['font-imp-effects']={
version=1.001,
- comment="companion to font-ini.mkiv and hand-ini.mkiv",
+ 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"