summaryrefslogtreecommitdiff
path: root/macros/luatex/generic
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-11-06 03:00:54 +0000
committerNorbert Preining <norbert@preining.info>2019-11-06 03:00:54 +0000
commit590fd8b560523cdaea19c59aea61e781138e87f8 (patch)
tree0da2c5c68b4f6860feef746ecf9e8b76157c80bb /macros/luatex/generic
parenta78951f836b9edaab2dd593f38e33732f0d03cbd (diff)
CTAN sync 201911060300
Diffstat (limited to 'macros/luatex/generic')
-rw-r--r--macros/luatex/generic/lualibs/NEWS3
-rw-r--r--macros/luatex/generic/lualibs/README.md4
-rw-r--r--macros/luatex/generic/lualibs/lualibs-basic-merged.lua205
-rw-r--r--macros/luatex/generic/lualibs/lualibs-extended-merged.lua68
-rw-r--r--macros/luatex/generic/lualibs/lualibs-gzip.lua135
-rw-r--r--macros/luatex/generic/lualibs/lualibs-lpeg.lua2
-rw-r--r--macros/luatex/generic/lualibs/lualibs-lua.lua6
-rw-r--r--macros/luatex/generic/lualibs/lualibs-table.lua31
-rw-r--r--macros/luatex/generic/lualibs/lualibs-unicode.lua84
-rw-r--r--macros/luatex/generic/lualibs/lualibs-util-lua.lua10
-rw-r--r--macros/luatex/generic/lualibs/lualibs-util-str.lua35
-rw-r--r--macros/luatex/generic/lualibs/lualibs-util-tab.lua20
-rw-r--r--macros/luatex/generic/lualibs/lualibs-util-tpl.lua66
-rw-r--r--macros/luatex/generic/lualibs/lualibs.dtx18
-rw-r--r--macros/luatex/generic/lualibs/lualibs.pdfbin80996 -> 96295 bytes
-rw-r--r--macros/luatex/generic/luaotfload/NEWS7
-rw-r--r--macros/luatex/generic/luaotfload/README.md4
-rw-r--r--macros/luatex/generic/luaotfload/filegraph.pdfbin39711 -> 39841 bytes
-rw-r--r--macros/luatex/generic/luaotfload/fontloader-2019-10-29.lua (renamed from macros/luatex/generic/luaotfload/fontloader-2019-08-11.lua)371
-rw-r--r--macros/luatex/generic/luaotfload/fontloader-basics-nod.lua18
-rw-r--r--macros/luatex/generic/luaotfload/fontloader-font-con.lua7
-rw-r--r--macros/luatex/generic/luaotfload/fontloader-font-dsp.lua14
-rw-r--r--macros/luatex/generic/luaotfload/fontloader-font-ocl.lua204
-rw-r--r--macros/luatex/generic/luaotfload/fontloader-font-osd.lua2
-rw-r--r--macros/luatex/generic/luaotfload/fontloader-font-otc.lua18
-rw-r--r--macros/luatex/generic/luaotfload/fontloader-font-otl.lua3
-rw-r--r--macros/luatex/generic/luaotfload/fontloader-font-ots.lua16
-rw-r--r--macros/luatex/generic/luaotfload/fontloader-font-oup.lua20
-rw-r--r--macros/luatex/generic/luaotfload/fontloader-l-lpeg.lua2
-rw-r--r--macros/luatex/generic/luaotfload/fontloader-l-lua.lua6
-rw-r--r--macros/luatex/generic/luaotfload/fontloader-l-table.lua31
-rw-r--r--macros/luatex/generic/luaotfload/fontloader-l-unicode.lua84
-rw-r--r--macros/luatex/generic/luaotfload/fontloader-reference.lua227
-rw-r--r--macros/luatex/generic/luaotfload/fontloader-util-str.lua35
-rw-r--r--macros/luatex/generic/luaotfload/luaotfload-auxiliary.lua133
-rw-r--r--macros/luatex/generic/luaotfload/luaotfload-colors.lua5
-rw-r--r--macros/luatex/generic/luaotfload/luaotfload-conf.pdfbin77515 -> 77675 bytes
-rw-r--r--macros/luatex/generic/luaotfload/luaotfload-configuration.lua8
-rw-r--r--macros/luatex/generic/luaotfload/luaotfload-database.lua70
-rw-r--r--macros/luatex/generic/luaotfload/luaotfload-diagnostics.lua4
-rw-r--r--macros/luatex/generic/luaotfload/luaotfload-embolden.lua4
-rw-r--r--macros/luatex/generic/luaotfload/luaotfload-features.lua31
-rw-r--r--macros/luatex/generic/luaotfload/luaotfload-filelist.lua7
-rw-r--r--macros/luatex/generic/luaotfload/luaotfload-glyphlist.lua4
-rw-r--r--macros/luatex/generic/luaotfload/luaotfload-harf-define.lua394
-rw-r--r--macros/luatex/generic/luaotfload/luaotfload-harf-plug.lua983
-rw-r--r--macros/luatex/generic/luaotfload/luaotfload-init.lua395
-rw-r--r--macros/luatex/generic/luaotfload/luaotfload-latex.pdfbin353062 -> 394415 bytes
-rw-r--r--macros/luatex/generic/luaotfload/luaotfload-letterspace.lua4
-rw-r--r--macros/luatex/generic/luaotfload/luaotfload-loaders.lua17
-rw-r--r--macros/luatex/generic/luaotfload/luaotfload-log.lua10
-rw-r--r--macros/luatex/generic/luaotfload/luaotfload-main.lua42
-rw-r--r--macros/luatex/generic/luaotfload/luaotfload-main.tex138
-rw-r--r--macros/luatex/generic/luaotfload/luaotfload-multiscript.lua4
-rw-r--r--macros/luatex/generic/luaotfload/luaotfload-notdef.lua4
-rw-r--r--macros/luatex/generic/luaotfload/luaotfload-parsers.lua8
-rw-r--r--macros/luatex/generic/luaotfload/luaotfload-resolvers.lua12
-rw-r--r--macros/luatex/generic/luaotfload/luaotfload-status.lua87
-rw-r--r--macros/luatex/generic/luaotfload/luaotfload-tool.12
-rw-r--r--macros/luatex/generic/luaotfload/luaotfload-tool.lua5
-rw-r--r--macros/luatex/generic/luaotfload/luaotfload-tool.pdfbin76761 -> 76923 bytes
-rw-r--r--macros/luatex/generic/luaotfload/luaotfload-tool.rst4
-rw-r--r--macros/luatex/generic/luaotfload/luaotfload-tounicode.lua200
-rw-r--r--macros/luatex/generic/luaotfload/luaotfload-unicode.lua4
-rw-r--r--macros/luatex/generic/luaotfload/luaotfload.conf.52
-rw-r--r--macros/luatex/generic/luaotfload/luaotfload.conf.rst4
-rw-r--r--macros/luatex/generic/luaotfload/luaotfload.sty2
-rw-r--r--macros/luatex/generic/luaotfload/scripts-demo.pdfbin0 -> 21422 bytes
-rw-r--r--macros/luatex/generic/luaotfload/scripts-demo.tex15
-rw-r--r--macros/luatex/generic/luaotfload/shaper-demo-graphite.pdfbin0 -> 8487 bytes
-rw-r--r--macros/luatex/generic/luaotfload/shaper-demo-graphite.tex9
-rw-r--r--macros/luatex/generic/luaotfload/shaper-demo.pdfbin0 -> 8411 bytes
-rw-r--r--macros/luatex/generic/luaotfload/shaper-demo.tex7
73 files changed, 3285 insertions, 1089 deletions
diff --git a/macros/luatex/generic/lualibs/NEWS b/macros/luatex/generic/lualibs/NEWS
index 66ee05e8cb..73e5961b3b 100644
--- a/macros/luatex/generic/lualibs/NEWS
+++ b/macros/luatex/generic/lualibs/NEWS
@@ -1,4 +1,7 @@
History of the lualibs package
+2019/10/29 v2.68/
+ * sync with Context current as of 2019/10/29
+
2019/08/11 v2.67/
* sync with Context current as of 2019/08/11
diff --git a/macros/luatex/generic/lualibs/README.md b/macros/luatex/generic/lualibs/README.md
index b89ca40fb7..d8a1b99167 100644
--- a/macros/luatex/generic/lualibs/README.md
+++ b/macros/luatex/generic/lualibs/README.md
@@ -1,8 +1,8 @@
# The Lualibs Package
-VERSION: 2.67
+VERSION: 2.68
-DATE: 2019-08-11
+DATE: 2019-11-05
Lualibs is a collection of Lua modules useful for general programming.
diff --git a/macros/luatex/generic/lualibs/lualibs-basic-merged.lua b/macros/luatex/generic/lualibs/lualibs-basic-merged.lua
index 0cb07cea2a..bee6c7de54 100644
--- a/macros/luatex/generic/lualibs/lualibs-basic-merged.lua
+++ b/macros/luatex/generic/lualibs/lualibs-basic-merged.lua
@@ -1,6 +1,6 @@
-- merged file : lualibs-basic-merged.lua
-- parent file : lualibs-basic.lua
--- merge date : Tue Aug 13 20:13:08 2019
+-- merge date : Tue Oct 29 16:47:31 2019
do -- begin closure to overcome local limits and interference
@@ -20,6 +20,9 @@ if LUAVERSION<5.2 and jit then
MINORVERSION=2
LUAVERSION=5.2
end
+if lua and lua.openfile then
+ io.open=lua.openfile
+end
if not lpeg then
lpeg=require("lpeg")
end
@@ -613,7 +616,7 @@ patterns.propername=(uppercase+lowercase+underscore)*(uppercase+lowercase+unders
patterns.somecontent=(anything-newline-space)^1
patterns.beginline=#(1-newline)
patterns.longtostring=Cs(whitespace^0/""*((patterns.quoted+nonwhitespace^1+whitespace^1/""*(endofstring+Cc(" ")))^0))
-function anywhere(pattern)
+local function anywhere(pattern)
return (1-P(pattern))^0*P(pattern)
end
lpeg.anywhere=anywhere
@@ -3954,43 +3957,98 @@ if not modules then modules={} end modules ['l-gzip']={
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files"
}
-if not gzip then
- return
-end
-local suffix,suffixes=file.suffix,file.suffixes
-function gzip.load(filename)
- local f=io.open(filename,"rb")
- if not f then
- elseif suffix(filename)=="gz" then
- f:close()
- local g=gzip.open(filename,"rb")
- if g then
- local str=g:read("*all")
- g:close()
+if gzip then
+ local suffix,suffixes=file.suffix,file.suffixes
+ function gzip.load(filename)
+ local f=io.open(filename,"rb")
+ if not f then
+ elseif suffix(filename)=="gz" then
+ f:close()
+ local g=gzip.open(filename,"rb")
+ if g then
+ local str=g:read("*all")
+ g:close()
+ return str
+ end
+ else
+ local str=f:read("*all")
+ f:close()
return str
end
- else
- local str=f:read("*all")
- f:close()
- return str
end
-end
-function gzip.save(filename,data)
- if suffix(filename)~="gz" then
- filename=filename..".gz"
+ function gzip.save(filename,data)
+ if suffix(filename)~="gz" then
+ filename=filename..".gz"
+ end
+ local f=io.open(filename,"wb")
+ if f then
+ local s=zlib.compress(data or "",9,nil,15+16)
+ f:write(s)
+ f:close()
+ return #s
+ end
end
- local f=io.open(filename,"wb")
- if f then
- local s=zlib.compress(data or "",9,nil,15+16)
- f:write(s)
- f:close()
- return #s
+ function gzip.suffix(filename)
+ local suffix,extra=suffixes(filename)
+ local gzipped=extra=="gz"
+ return suffix,gzipped
end
+else
end
-function gzip.suffix(filename)
- local suffix,extra=suffixes(filename)
- local gzipped=extra=="gz"
- return suffix,gzipped
+if flate then
+ local type=type
+ local find=string.find
+ local compress=flate.gz_compress
+ local decompress=flate.gz_decompress
+ local absmax=128*1024*1024
+ local initial=64*1024
+ local identifier="^\x1F\x8B\x08"
+ function gzip.compressed(s)
+ return s and find(s,identifier)
+ end
+ function gzip.compress(s,level)
+ if s and not find(s,identifier) then
+ if not level then
+ level=3
+ elseif level<=0 then
+ return s
+ elseif level>9 then
+ level=9
+ end
+ return compress(s,level) or s
+ end
+ end
+ function gzip.decompress(s,size,iterate)
+ if s and find(s,identifier) then
+ if type(size)~="number" then
+ size=initial
+ end
+ if size>absmax then
+ size=absmax
+ end
+ if type(iterate)=="number" then
+ max=size*iterate
+ elseif iterate==nil or iterate==true then
+ iterate=true
+ max=absmax
+ end
+ if max>absmax then
+ max=absmax
+ end
+ while true do
+ local d=decompress(s,size)
+ if d then
+ return d
+ end
+ size=2*size
+ if not iterate or size>max then
+ return false
+ end
+ end
+ else
+ return s
+ end
+ end
end
end -- closure
@@ -5097,49 +5155,52 @@ 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))
+if bit32 then
+ local rshift=bit32.rshift
+ 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
-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)
+ 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
-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)
+ 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
-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)
+ 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
-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)
+ 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
end
local pattern=Cs (
diff --git a/macros/luatex/generic/lualibs/lualibs-extended-merged.lua b/macros/luatex/generic/lualibs/lualibs-extended-merged.lua
index b3fecf2c3e..c2502401af 100644
--- a/macros/luatex/generic/lualibs/lualibs-extended-merged.lua
+++ b/macros/luatex/generic/lualibs/lualibs-extended-merged.lua
@@ -1,6 +1,6 @@
-- merged file : lualibs-extended-merged.lua
-- parent file : lualibs-extended.lua
--- merge date : Tue Aug 13 20:12:59 2019
+-- merge date : Tue Oct 29 16:47:22 2019
do -- begin closure to overcome local limits and interference
@@ -366,7 +366,7 @@ local environment={
stripzero=patterns.stripzero,
stripzeros=patterns.stripzeros,
escapedquotes=string.escapedquotes,
- FORMAT=string.f9,
+ FORMAT=string.f6,
}
local arguments={ "a1" }
setmetatable(arguments,{ __index=function(t,k)
@@ -574,12 +574,25 @@ local format_n=function()
n=n+1
return format("((a%s %% 1 == 0) and format('%%i',a%s) or tostring(a%s))",n,n,n)
end
-local format_N=function(f)
- n=n+1
- if not f or f=="" then
- f=".9"
- end
- return format("(((a%s %% 1 == 0) and format('%%i',a%s)) or lpegmatch(stripzero,format('%%%sf',a%s)))",n,n,f,n)
+local format_N if environment.FORMAT then
+ format_N=function(f)
+ n=n+1
+ if not f or f=="" then
+ return format("FORMAT(a%s,'%%.9f')",n)
+ elseif f==".6" then
+ return format("FORMAT(a%s)",n)
+ else
+ return format("FORMAT(a%s,'%%%sf')",n,f)
+ end
+ end
+else
+ format_N=function(f)
+ n=n+1
+ if not f or f=="" then
+ f=".9"
+ end
+ return format("(((a%s %% 1 == 0) and format('%%i',a%s)) or lpegmatch(stripzero,format('%%%sf',a%s)))",n,n,f,n)
+ end
end
local format_a=function(f)
n=n+1
@@ -1416,7 +1429,21 @@ function table.fastserialize(t,prefix)
m=m+1
r[m]="{"
if n>0 then
- for i=0,n do
+ local v=t[0]
+ if v then
+ local tv=type(v)
+ if tv=="string" then
+ m=m+1 r[m]=f_indexed_string(0,v)
+ elseif tv=="number" then
+ m=m+1 r[m]=f_indexed_number(0,v)
+ elseif tv=="table" then
+ m=m+1 r[m]=f_indexed_table(0)
+ fastserialize(v)
+ elseif tv=="boolean" then
+ m=m+1 r[m]=f_indexed_boolean(0,v)
+ end
+ end
+ for i=1,n do
local v=t[i]
local tv=type(v)
if tv=="string" then
@@ -3377,6 +3404,11 @@ luautilities.nofstrippedchunks=0
luautilities.nofstrippedbytes=0
local strippedchunks={}
luautilities.strippedchunks=strippedchunks
+if not LUATEXENGINE then
+ LUATEXENGINE=status.luatex_engine and string.lower(status.luatex_engine)
+ JITSUPPORTED=LUATEXENGINE=="luajittex" or jit
+ CONTEXTLMTXMODE=CONTEXTLMTXMODE or (LUATEXENGINE=="luametatex" and 1) or 0
+end
luautilities.suffixes={
tma="tma",
tmc=(CONTEXTLMTXMODE and CONTEXTLMTXMODE>0 and "tmd") or (jit and "tmb") or "tmc",
@@ -3386,7 +3418,7 @@ luautilities.suffixes={
luv="luv",
luj="luj",
tua="tua",
- tuc="tuc",
+ tuc=(CONTEXTLMTXMODE and CONTEXTLMTXMODE>0 and "tud") or (jit and "tub") or "tuc",
}
local function register(name)
if tracestripping then
@@ -3833,6 +3865,7 @@ local report_template=logs.reporter("template")
local tostring,next=tostring,next
local format,sub,byte=string.format,string.sub,string.byte
local P,C,R,Cs,Cc,Carg,lpegmatch,lpegpatterns=lpeg.P,lpeg.C,lpeg.R,lpeg.Cs,lpeg.Cc,lpeg.Carg,lpeg.match,lpeg.patterns
+local formatters=string.formatters
local replacer
local function replacekey(k,t,how,recursive)
local v=t[k]
@@ -3901,6 +3934,10 @@ local function replaceoptional(l,m,r,t,how,recurse)
local v=t[l]
return v and v~="" and lpegmatch(replacer,r,1,t,how or "lua",recurse or false) or ""
end
+local function replaceformatted(l,m,r,t,how,recurse)
+ local v=t[r]
+ return v and formatters[l](v)
+end
local single=P("%")
local double=P("%%")
local lquoted=P("%[")
@@ -3914,16 +3951,19 @@ local nolquoted=lquoted/''
local norquoted=rquoted/''
local nolquotedq=lquotedq/''
local norquotedq=rquotedq/''
+local nolformatted=P(":")/"%%"
+local norformatted=P(":")/""
local noloptional=P("%?")/''
local noroptional=P("?%")/''
local nomoptional=P(":")/''
local args=Carg(1)*Carg(2)*Carg(3)
-local key=nosingle*((C((1-nosingle )^1)*args)/replacekey )*nosingle
-local quoted=nolquotedq*((C((1-norquotedq )^1)*args)/replacekeyquoted )*norquotedq
-local unquoted=nolquoted*((C((1-norquoted )^1)*args)/replacekeyunquoted)*norquoted
+local key=nosingle*((C((1-nosingle)^1)*args)/replacekey)*nosingle
+local quoted=nolquotedq*((C((1-norquotedq)^1)*args)/replacekeyquoted)*norquotedq
+local unquoted=nolquoted*((C((1-norquoted)^1)*args)/replacekeyunquoted)*norquoted
local optional=noloptional*((C((1-nomoptional)^1)*nomoptional*C((1-noroptional)^1)*args)/replaceoptional)*noroptional
+local formatted=nosingle*((Cs(nolformatted*(1-norformatted )^1)*norformatted*C((1-nosingle)^1)*args)/replaceformatted)*nosingle
local any=P(1)
- replacer=Cs((unquoted+quoted+escape+optional+key+any)^0)
+ replacer=Cs((unquoted+quoted+formatted+escape+optional+key+any)^0)
local function replace(str,mapping,how,recurse)
if mapping and str then
return lpegmatch(replacer,str,1,mapping,how or "lua",recurse or false) or str
diff --git a/macros/luatex/generic/lualibs/lualibs-gzip.lua b/macros/luatex/generic/lualibs/lualibs-gzip.lua
index 5100e47222..31466bde8f 100644
--- a/macros/luatex/generic/lualibs/lualibs-gzip.lua
+++ b/macros/luatex/generic/lualibs/lualibs-gzip.lua
@@ -5,50 +5,113 @@ if not modules then modules = { } end modules ['l-gzip'] = {
license = "see context related readme files"
}
-if not gzip then
+if gzip then
- -- no fallback yet
+ local suffix, suffixes = file.suffix, file.suffixes
- return
-
-end
-
-local suffix, suffixes = file.suffix, file.suffixes
-
-function gzip.load(filename)
- local f = io.open(filename,"rb")
- if not f then
- -- invalid file
- elseif suffix(filename) == "gz" then
- f:close()
- local g = gzip.open(filename,"rb")
- if g then
- local str = g:read("*all")
- g:close()
+ function gzip.load(filename)
+ local f = io.open(filename,"rb")
+ if not f then
+ -- invalid file
+ elseif suffix(filename) == "gz" then
+ f:close()
+ local g = gzip.open(filename,"rb")
+ if g then
+ local str = g:read("*all")
+ g:close()
+ return str
+ end
+ else
+ local str = f:read("*all")
+ f:close()
return str
end
- else
- local str = f:read("*all")
- f:close()
- return str
end
-end
-function gzip.save(filename,data)
- if suffix(filename) ~= "gz" then
- filename = filename .. ".gz"
+ function gzip.save(filename,data)
+ if suffix(filename) ~= "gz" then
+ filename = filename .. ".gz"
+ end
+ local f = io.open(filename,"wb")
+ if f then
+ local s = zlib.compress(data or "",9,nil,15+16)
+ f:write(s)
+ f:close()
+ return #s
+ end
end
- local f = io.open(filename,"wb")
- if f then
- local s = zlib.compress(data or "",9,nil,15+16)
- f:write(s)
- f:close()
- return #s
+
+ function gzip.suffix(filename)
+ local suffix, extra = suffixes(filename)
+ local gzipped = extra == "gz"
+ return suffix, gzipped
end
+
+else
+
+ -- todo: fallback on flate
+
end
-function gzip.suffix(filename)
- local suffix, extra = suffixes(filename)
- local gzipped = extra == "gz"
- return suffix, gzipped
+if flate then
+
+ local type = type
+ local find = string.find
+
+ local compress = flate.gz_compress
+ local decompress = flate.gz_decompress
+
+ local absmax = 128*1024*1024
+ local initial = 64*1024
+ local identifier = "^\x1F\x8B\x08"
+
+ function gzip.compressed(s)
+ return s and find(s,identifier)
+ end
+
+ function gzip.compress(s,level)
+ if s and not find(s,identifier) then -- the find check might go away
+ if not level then
+ level = 3
+ elseif level <= 0 then
+ return s
+ elseif level > 9 then
+ level = 9
+ end
+ return compress(s,level) or s
+ end
+ end
+
+ function gzip.decompress(s,size,iterate)
+ if s and find(s,identifier) then
+ if type(size) ~= "number" then
+ size = initial
+ end
+ if size > absmax then
+ size = absmax
+ end
+ if type(iterate) == "number" then
+ max = size * iterate
+ elseif iterate == nil or iterate == true then
+ iterate = true
+ max = absmax
+ end
+ if max > absmax then
+ max = absmax
+ end
+ while true do
+ local d = decompress(s,size)
+ if d then
+ return d
+ end
+ size = 2 * size
+ if not iterate or size > max then
+ return false
+ end
+ end
+ else
+ return s
+ end
+ end
+
end
diff --git a/macros/luatex/generic/lualibs/lualibs-lpeg.lua b/macros/luatex/generic/lualibs/lualibs-lpeg.lua
index 51bc1d3df3..7979a40fb9 100644
--- a/macros/luatex/generic/lualibs/lualibs-lpeg.lua
+++ b/macros/luatex/generic/lualibs/lualibs-lpeg.lua
@@ -295,7 +295,7 @@ patterns.longtostring = Cs(whitespace^0/"" * ((patterns.quoted + nonwhitespace^
-- return P { P(pattern) + 1 * V(1) }
-- end
-function anywhere(pattern) -- faster
+local function anywhere(pattern) -- faster
return (1-P(pattern))^0 * P(pattern)
end
diff --git a/macros/luatex/generic/lualibs/lualibs-lua.lua b/macros/luatex/generic/lualibs/lualibs-lua.lua
index 6e9606e849..51399216cc 100644
--- a/macros/luatex/generic/lualibs/lualibs-lua.lua
+++ b/macros/luatex/generic/lualibs/lualibs-lua.lua
@@ -35,6 +35,12 @@ if LUAVERSION < 5.2 and jit then
LUAVERSION = 5.2
end
+-- this is lmtx only:
+
+if lua and lua.openfile then
+ io.open = lua.openfile
+end
+
-- lpeg
if not lpeg then
diff --git a/macros/luatex/generic/lualibs/lualibs-table.lua b/macros/luatex/generic/lualibs/lualibs-table.lua
index cffdcc23e2..e828203867 100644
--- a/macros/luatex/generic/lualibs/lualibs-table.lua
+++ b/macros/luatex/generic/lualibs/lualibs-table.lua
@@ -287,6 +287,37 @@ local function sortedhash(t,cmp)
return nothing
end
+-- local function iterate(t,i)
+-- local i = i + 1
+-- if i <= t.n then
+-- local k = t[i]
+-- return i, k, t.t[k]
+-- end
+-- end
+--
+-- local function indexedhash(t,cmp)
+-- if t then
+-- local s
+-- if cmp then
+-- -- it would be nice if the sort function would accept a third argument (or nicer, an optional first)
+-- s = sortedhashkeys(t,function(a,b) return cmp(t,a,b) end)
+-- else
+-- s = sortedkeys(t) -- the robust one
+-- end
+-- local m = #s
+-- if m == 1 then
+-- return next, t
+-- elseif m > 0 then
+-- s.n = m
+-- s.t = t
+-- return iterate, s, 0
+-- end
+-- end
+-- return nothing
+-- end
+--
+-- -- for i, k, v in indexedhash(t) do print(k,v,s) end
+
table.sortedhash = sortedhash
table.sortedpairs = sortedhash -- obsolete
diff --git a/macros/luatex/generic/lualibs/lualibs-unicode.lua b/macros/luatex/generic/lualibs/lualibs-unicode.lua
index 73d1eb7660..2708d14760 100644
--- a/macros/luatex/generic/lualibs/lualibs-unicode.lua
+++ b/macros/luatex/generic/lualibs/lualibs-unicode.lua
@@ -1081,56 +1081,62 @@ 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))
+if bit32 then
+
+ local rshift = bit32.rshift
+
+ 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
-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)
+ 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
-end
-local l_remap = Cs((p_utf8byte/little+P(1)/"")^0)
-local b_remap = Cs((p_utf8byte/big +P(1)/"")^0)
+ 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)
+ 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
-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)
+ 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
-end
-utf.utf8_to_utf16_be = utf8_to_utf16_be
-utf.utf8_to_utf16_le = utf8_to_utf16_le
+ 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)
+ 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
+
end
local pattern = Cs (
diff --git a/macros/luatex/generic/lualibs/lualibs-util-lua.lua b/macros/luatex/generic/lualibs/lualibs-util-lua.lua
index f7e6e4f313..fb4088e7b6 100644
--- a/macros/luatex/generic/lualibs/lualibs-util-lua.lua
+++ b/macros/luatex/generic/lualibs/lualibs-util-lua.lua
@@ -28,6 +28,13 @@ luautilities.nofstrippedbytes = 0
local strippedchunks = { } -- allocate()
luautilities.strippedchunks = strippedchunks
+if not LUATEXENGINE then
+ --- probably mtxrun ...
+ LUATEXENGINE = status.luatex_engine and string.lower(status.luatex_engine)
+ JITSUPPORTED = LUATEXENGINE == "luajittex" or jit
+ CONTEXTLMTXMODE = CONTEXTLMTXMODE or (LUATEXENGINE == "luametatex" and 1) or 0
+end
+
luautilities.suffixes = {
tma = "tma",
tmc = (CONTEXTLMTXMODE and CONTEXTLMTXMODE > 0 and "tmd") or (jit and "tmb") or "tmc",
@@ -37,7 +44,8 @@ luautilities.suffixes = {
luv = "luv",
luj = "luj",
tua = "tua",
- tuc = "tuc",
+ -- tuc = "tuc",
+ tuc = (CONTEXTLMTXMODE and CONTEXTLMTXMODE > 0 and "tud") or (jit and "tub") or "tuc",
}
-- environment.loadpreprocessedfile can be set to a preprocessor
diff --git a/macros/luatex/generic/lualibs/lualibs-util-str.lua b/macros/luatex/generic/lualibs/lualibs-util-str.lua
index ad22302df0..432b39ec5a 100644
--- a/macros/luatex/generic/lualibs/lualibs-util-str.lua
+++ b/macros/luatex/generic/lualibs/lualibs-util-str.lua
@@ -633,7 +633,7 @@ local environment = {
stripzeros = patterns.stripzeros,
escapedquotes = string.escapedquotes,
- FORMAT = string.f9,
+ FORMAT = string.f6,
}
-- -- --
@@ -908,7 +908,7 @@ local format_L = function()
return format("(a%s and 'TRUE' or 'FALSE')",n)
end
-local format_n = function() -- strips leading and trailing zeros and removes .0
+local format_n = function() -- strips leading and trailing zeros and removes .0, beware: can produce e notation
n = n + 1
return format("((a%s %% 1 == 0) and format('%%i',a%s) or tostring(a%s))",n,n,n)
end
@@ -938,13 +938,30 @@ end
-- end
-- end
-local format_N = function(f) -- strips leading and trailing zeros
- n = n + 1
- -- stripzero (singular) as we only have a number
- if not f or f == "" then
- f = ".9"
- end -- always a leading number !
- return format("(((a%s %% 1 == 0) and format('%%i',a%s)) or lpegmatch(stripzero,format('%%%sf',a%s)))",n,n,f,n)
+local format_N if environment.FORMAT then
+
+ format_N = function(f)
+ n = n + 1
+ if not f or f == "" then
+ return format("FORMAT(a%s,'%%.9f')",n)
+ elseif f == ".6" then
+ return format("FORMAT(a%s)",n)
+ else
+ return format("FORMAT(a%s,'%%%sf')",n,f)
+ end
+ end
+
+else
+
+ format_N = function(f) -- strips leading and trailing zeros
+ n = n + 1
+ -- stripzero (singular) as we only have a number
+ if not f or f == "" then
+ f = ".9"
+ end -- always a leading number !
+ return format("(((a%s %% 1 == 0) and format('%%i',a%s)) or lpegmatch(stripzero,format('%%%sf',a%s)))",n,n,f,n)
+ end
+
end
local format_a = function(f)
diff --git a/macros/luatex/generic/lualibs/lualibs-util-tab.lua b/macros/luatex/generic/lualibs/lualibs-util-tab.lua
index f970d8ace0..410292ca8a 100644
--- a/macros/luatex/generic/lualibs/lualibs-util-tab.lua
+++ b/macros/luatex/generic/lualibs/lualibs-util-tab.lua
@@ -341,7 +341,21 @@ function table.fastserialize(t,prefix) -- todo, move local function out
m = m + 1
r[m] = "{"
if n > 0 then
- for i=0,n do
+ local v = t[0]
+ if v then
+ local tv = type(v)
+ if tv == "string" then
+ m = m + 1 r[m] = f_indexed_string(0,v)
+ elseif tv == "number" then
+ m = m + 1 r[m] = f_indexed_number(0,v)
+ elseif tv == "table" then
+ m = m + 1 r[m] = f_indexed_table(0)
+ fastserialize(v)
+ elseif tv == "boolean" then
+ m = m + 1 r[m] = f_indexed_boolean(0,v)
+ end
+ end
+ for i=1,n do
local v = t[i]
local tv = type(v)
if tv == "string" then
@@ -355,6 +369,8 @@ function table.fastserialize(t,prefix) -- todo, move local function out
end
end
end
+ -- hm, can't we avoid this ... lua should have a way to check if there
+ -- is a hash part
for k, v in next, t do
local tk = type(k)
if tk == "number" then
@@ -411,7 +427,7 @@ function table.deserialize(str)
return code
end
--- inspect(table.fastserialize { a = 1, b = { 4, { 5, 6 } }, c = { d = 7, e = 'f"g\nh' } })
+-- inspect(table.fastserialize { a = 1, b = { [0]=4, { 5, 6 } }, c = { d = 7, e = 'f"g\nh' } })
function table.load(filename,loader)
if filename then
diff --git a/macros/luatex/generic/lualibs/lualibs-util-tpl.lua b/macros/luatex/generic/lualibs/lualibs-util-tpl.lua
index 57d7df3a91..318f2efc3b 100644
--- a/macros/luatex/generic/lualibs/lualibs-util-tpl.lua
+++ b/macros/luatex/generic/lualibs/lualibs-util-tpl.lua
@@ -20,6 +20,8 @@ local tostring, next = tostring, next
local format, sub, byte = string.format, string.sub, string.byte
local P, C, R, Cs, Cc, Carg, lpegmatch, lpegpatterns = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs, lpeg.Cc, lpeg.Carg, lpeg.match, lpeg.patterns
+local formatters = string.formatters
+
-- todo: make installable template.new
local replacer
@@ -133,34 +135,42 @@ local function replaceoptional(l,m,r,t,how,recurse)
return v and v ~= "" and lpegmatch(replacer,r,1,t,how or "lua",recurse or false) or ""
end
-local single = P("%") -- test %test% test : resolves test
-local double = P("%%") -- test 10%% test : %% becomes %
-local lquoted = P("%[") -- test '%[test]%' test : resolves to test with escaped "'s
-local rquoted = P("]%") --
-local lquotedq = P("%(") -- test %(test)% test : resolves to 'test' with escaped "'s
-local rquotedq = P(")%") --
-
-local escape = double / '%%'
-local nosingle = single / ''
-local nodouble = double / ''
-local nolquoted = lquoted / ''
-local norquoted = rquoted / ''
-local nolquotedq = lquotedq / ''
-local norquotedq = rquotedq / ''
-
-local noloptional = P("%?") / ''
-local noroptional = P("?%") / ''
-local nomoptional = P(":") / ''
-
-
-local args = Carg(1) * Carg(2) * Carg(3)
-local key = nosingle * ((C((1-nosingle )^1) * args) / replacekey ) * nosingle
-local quoted = nolquotedq * ((C((1-norquotedq )^1) * args) / replacekeyquoted ) * norquotedq
-local unquoted = nolquoted * ((C((1-norquoted )^1) * args) / replacekeyunquoted) * norquoted
-local optional = noloptional * ((C((1-nomoptional)^1) * nomoptional * C((1-noroptional)^1) * args) / replaceoptional) * noroptional
-local any = P(1)
+local function replaceformatted(l,m,r,t,how,recurse)
+ local v = t[r]
+ return v and formatters[l](v)
+end
- replacer = Cs((unquoted + quoted + escape + optional + key + any)^0)
+local single = P("%") -- test %test% test : resolves test
+local double = P("%%") -- test 10%% test : %% becomes %
+local lquoted = P("%[") -- test '%[test]%' test : resolves to test with escaped "'s
+local rquoted = P("]%") --
+local lquotedq = P("%(") -- test %(test)% test : resolves to 'test' with escaped "'s
+local rquotedq = P(")%") --
+
+local escape = double / '%%'
+local nosingle = single / ''
+local nodouble = double / ''
+local nolquoted = lquoted / ''
+local norquoted = rquoted / ''
+local nolquotedq = lquotedq / ''
+local norquotedq = rquotedq / ''
+
+local nolformatted = P(":") / "%%"
+local norformatted = P(":") / ""
+
+local noloptional = P("%?") / ''
+local noroptional = P("?%") / ''
+local nomoptional = P(":") / ''
+
+local args = Carg(1) * Carg(2) * Carg(3)
+local key = nosingle * ((C((1-nosingle)^1) * args) / replacekey) * nosingle
+local quoted = nolquotedq * ((C((1-norquotedq)^1) * args) / replacekeyquoted) * norquotedq
+local unquoted = nolquoted * ((C((1-norquoted)^1) * args) / replacekeyunquoted) * norquoted
+local optional = noloptional * ((C((1-nomoptional)^1) * nomoptional * C((1-noroptional)^1) * args) / replaceoptional) * noroptional
+local formatted = nosingle * ((Cs(nolformatted * (1-norformatted )^1) * norformatted * C((1-nosingle)^1) * args) / replaceformatted) * nosingle
+local any = P(1)
+
+ replacer = Cs((unquoted + quoted + formatted + escape + optional + key + any)^0)
local function replace(str,mapping,how,recurse)
if mapping and str then
@@ -179,6 +189,8 @@ end
-- print(replace([[test %[x]% test]],{ x = [[a "x"  a]]}))
-- print(replace([[test %(x)% test]],{ x = [[a "x"  a]]}))
-- print(replace([[convert %?x: -x "%x%" ?% %?y: -y "%y%" ?%]],{ x = "yes" }))
+-- print(replace("test %:0.3N:x% test",{ x = 123.45 }))
+-- print(replace("test %:0.3N:x% test",{ x = 12345 }))
templates.replace = replace
diff --git a/macros/luatex/generic/lualibs/lualibs.dtx b/macros/luatex/generic/lualibs/lualibs.dtx
index 8c302400f1..f5ae0342ac 100644
--- a/macros/luatex/generic/lualibs/lualibs.dtx
+++ b/macros/luatex/generic/lualibs/lualibs.dtx
@@ -37,7 +37,7 @@
\input docstrip.tex
\Msg{************************************************************************}
\Msg{* Installation}
-\Msg{* Package: lualibs 2019-08-11 v2.67 Lua additional functions.}
+\Msg{* Package: lualibs 2019-11-05 v2.68 Lua additional functions.}
\Msg{************************************************************************}
\keepsilent
@@ -107,7 +107,7 @@ and lualibs-extended.lua.
%<*driver>
\NeedsTeXFormat{LaTeX2e}
\ProvidesFile{lualibs.drv}
- [2019/08/11 v2.67 Lua Libraries.]
+ [2019/11/05 v2.68 Lua Libraries.]
\documentclass{ltxdoc}
\usepackage{fancyvrb,xspace}
\usepackage[x11names]{xcolor}
@@ -208,7 +208,7 @@ and lualibs-extended.lua.
% \GetFileInfo{lualibs.drv}
%
% \title{The \identifier{lualibs} package}
-% \date{2019/08/11 v2.67}
+% \date{2019/11/05 v2.68}
% \author{Élie Roux · \email{elie.roux@telecom-bretagne.eu}\\
% Philipp Gesang · \email{phg@phi-gamma.net}\\
% Ulrike Fischer · \email{fischer@troubleshooting-tex.de}\\
@@ -429,8 +429,8 @@ lualibs = lualibs or { }
lualibs.module_info = {
name = "lualibs",
- version = "2.67", --TAGVERSION
- date = "2019-08-11", --TAGDATE
+ version = "2.68", --TAGVERSION
+ date = "2019-11-05", --TAGDATE
description = "ConTeXt Lua standard libraries.",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL & Elie Roux & Philipp Gesang",
copyright = "PRAGMA ADE / ConTeXt Development Team",
@@ -583,8 +583,8 @@ local loadmodule = lualibs.loadmodule
local lualibs_basic_module = {
name = "lualibs-basic",
- version = "2.67", --TAGVERSION
- date = "2019-08-11", --TAGDATE
+ version = "2.68", --TAGVERSION
+ date = "2019-11-05", --TAGDATE
description = "ConTeXt Lua libraries -- basic collection.",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL & Elie Roux & Philipp Gesang",
copyright = "PRAGMA ADE / ConTeXt Development Team",
@@ -665,8 +665,8 @@ lualibs = lualibs or { }
local lualibs_extended_module = {
name = "lualibs-extended",
- version = "2.67", --TAGVERSION
- date = "2019-08-11", --TAGDATE
+ version = "2.68", --TAGVERSION
+ date = "2019-11-05", --TAGDATE
description = "ConTeXt Lua libraries -- extended collection.",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL & Elie Roux & Philipp Gesang",
copyright = "PRAGMA ADE / ConTeXt Development Team",
diff --git a/macros/luatex/generic/lualibs/lualibs.pdf b/macros/luatex/generic/lualibs/lualibs.pdf
index ad1ee3061b..08716de05a 100644
--- a/macros/luatex/generic/lualibs/lualibs.pdf
+++ b/macros/luatex/generic/lualibs/lualibs.pdf
Binary files differ
diff --git a/macros/luatex/generic/luaotfload/NEWS b/macros/luatex/generic/luaotfload/NEWS
index 39bfcc4cc3..86b9dd9b2d 100644
--- a/macros/luatex/generic/luaotfload/NEWS
+++ b/macros/luatex/generic/luaotfload/NEWS
@@ -1,5 +1,12 @@
Change History
--------------
+2019-11-04 luaotfload v3.1
+ * added code to use the harfbuzz library of luahbtex ("mode=harf")
+ * fonts in ttc can now be indexed by name
+ * remove a number of lua tables from the global enviroment (_G) to reduce the polution.
+ Kept there are only the tables luaotfload, fonts and nodes.
+ * sync with context files from 2019-10-29
+
2019-09-13 luaotfload v3.0
* invisible option to avoid that some glyph are shown (issue #63)
* correct small bug in xheight calculation
diff --git a/macros/luatex/generic/luaotfload/README.md b/macros/luatex/generic/luaotfload/README.md
index a6f24d4ab9..ca760b1bab 100644
--- a/macros/luatex/generic/luaotfload/README.md
+++ b/macros/luatex/generic/luaotfload/README.md
@@ -1,8 +1,8 @@
# The Luaotfload Package
-VERSION: 3.00
+VERSION: 3.1
-DATE: 2019-09-13
+DATE: 2019-11-04
## Description
diff --git a/macros/luatex/generic/luaotfload/filegraph.pdf b/macros/luatex/generic/luaotfload/filegraph.pdf
index a14afaa169..95b296c599 100644
--- a/macros/luatex/generic/luaotfload/filegraph.pdf
+++ b/macros/luatex/generic/luaotfload/filegraph.pdf
Binary files differ
diff --git a/macros/luatex/generic/luaotfload/fontloader-2019-08-11.lua b/macros/luatex/generic/luaotfload/fontloader-2019-10-29.lua
index b4d3f3ce12..dc98bd5696 100644
--- a/macros/luatex/generic/luaotfload/fontloader-2019-08-11.lua
+++ b/macros/luatex/generic/luaotfload/fontloader-2019-10-29.lua
@@ -1,6 +1,6 @@
--[[info-----------------------------------------------------------------------
Luaotfload fontloader package
- build 2019-08-13 18:34:34
+ build 2019-10-29 22:02:47
-------------------------------------------------------------------------------
© 2019 PRAGMA ADE / ConTeXt Development Team
@@ -62,7 +62,7 @@
--info]]-----------------------------------------------------------------------
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “data-con” 7ce546725b1550f655c78ac9d69419ca] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “data-con” 7ce546725b1550f655c78ac9d69419ca] ---
if not modules then modules={} end modules ['data-con']={
version=1.100,
@@ -174,10 +174,10 @@ function containers.cleanname(name)
return (gsub(lower(name),"[^%w\128-\255]+","-"))
end
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “data-con”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “data-con”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “basics-nod” 65064d03c2650a1761ee13ebd9e1400a] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “basics-nod” c05f47077c709bbf12a8758852dc4e06] ---
if not modules then modules={} end modules ['luatex-fonts-nod']={
version=1.001,
@@ -247,6 +247,7 @@ nuts.getchar=direct.getchar
nuts.getcomponents=direct.getcomponents
nuts.getdirection=direct.getdirection
nuts.getdisc=direct.getdisc
+nuts.getreplace=direct.getreplace
nuts.getfield=direct.getfield
nuts.getfont=direct.getfont
nuts.getid=direct.getid
@@ -263,6 +264,7 @@ nuts.setchar=direct.setchar
nuts.setcomponents=direct.setcomponents
nuts.setdirection=direct.setdirection
nuts.setdisc=direct.setdisc
+nuts.setreplace=direct.setreplace
nuts.setfield=setfield
nuts.setkern=direct.setkern
nuts.setlink=direct.setlink
@@ -380,11 +382,22 @@ do
node=nuts.traverse(dummy),
}
end
+if not nuts.setreplace then
+ local getdisc=nuts.getdisc
+ local setfield=nuts.setfield
+ function nuts.getreplace(n)
+ local _,_,h,_,_,t=getdisc(n,true)
+ return h,t
+ end
+ function nuts.setreplace(n,h)
+ setfield(n,"replace",h)
+ end
+end
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “basics-nod”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “basics-nod”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “basics-chr” 58b7ef0c486e06090b362971b9f85e27] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “basics-chr” 58b7ef0c486e06090b362971b9f85e27] ---
characters=characters or {}
@@ -3994,10 +4007,10 @@ characters.indicgroups={
},
}
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “basics-chr”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “basics-chr”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “font-ini” 4299a02110bbd7c0d27e131235c5319d] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “font-ini” 4299a02110bbd7c0d27e131235c5319d] ---
if not modules then modules={} end modules ['font-ini']={
version=1.001,
@@ -4035,10 +4048,10 @@ fonts.privateoffsets={
keepnames=false,
}
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “font-ini”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “font-ini”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “fonts-mis” bc9eb43c27f63ce9d0fff67e104fe1c6] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “fonts-mis” bc9eb43c27f63ce9d0fff67e104fe1c6] ---
if not modules then modules={} end modules ['luatex-font-mis']={
version=1.001,
@@ -4070,10 +4083,10 @@ function font.each()
return table.sortedhash(fonts.hashes.identifiers)
end
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “fonts-mis”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “fonts-mis”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “font-con” ca733211a0555d9a93b1e2f7ebc937d3] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “font-con” 8b35e7c2203d5b57c61942e07cee2c0a] ---
if not modules then modules={} end modules ['font-con']={
version=1.001,
@@ -4376,7 +4389,8 @@ function constructors.scale(tfmdata,specification)
local units=parameters.units or 1000
targetproperties.language=properties.language or "dflt"
targetproperties.script=properties.script or "dflt"
- targetproperties.mode=properties.mode or "base"
+ targetproperties.mode=properties.mode or "base"
+ targetproperties.method=properties.method
local askedscaledpoints=scaledpoints
local scaledpoints,delta=constructors.calculatescale(tfmdata,scaledpoints,nil,specification)
local hdelta=delta
@@ -5416,10 +5430,10 @@ function constructors.addcoreunicodes(unicodes)
return unicodes
end
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “font-con”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “font-con”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “fonts-enc” 3e71a54297e8f85a1ac438bb0f20dd79] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “fonts-enc” 3e71a54297e8f85a1ac438bb0f20dd79] ---
if not modules then modules={} end modules ['luatex-font-enc']={
version=1.001,
@@ -5488,10 +5502,10 @@ function encodings.load(filename)
return containers.write(encodings.cache,name,data)
end
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “fonts-enc”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “fonts-enc”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “font-cid” 4d87988efa86020a14708ee03c23415f] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “font-cid” 4d87988efa86020a14708ee03c23415f] ---
if not modules then modules={} end modules ['font-cid']={
version=1.001,
@@ -5642,10 +5656,10 @@ function cid.getmap(specification)
return found
end
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “font-cid”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “font-cid”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “font-map” f486746e90fe972de4b73e208ac7cbb2] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “font-map” f486746e90fe972de4b73e208ac7cbb2] ---
if not modules then modules={} end modules ['font-map']={
version=1.001,
@@ -6033,10 +6047,10 @@ function mappings.addtounicode(data,filename,checklookups,forceligatures)
end
end
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “font-map”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “font-map”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “font-vfc” 94937140f2c909e9c831ba021f1ab303] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “font-vfc” 94937140f2c909e9c831ba021f1ab303] ---
if not modules then modules={} end modules ['font-vfc']={
version=1.001,
@@ -6134,10 +6148,10 @@ helpers.commands=utilities.storage.allocate {
dummy=dummy,
}
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “font-vfc”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “font-vfc”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “font-otr” b1c03925c949027c86f781785fa7a208] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “font-otr” b1c03925c949027c86f781785fa7a208] ---
if not modules then modules={} end modules ['font-otr']={
version=1.001,
@@ -7987,10 +8001,10 @@ function readers.extend(fontdata)
end
end
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “font-otr”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “font-otr”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “font-oti” dbae7722baae24d917a17176553825cf] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “font-oti” dbae7722baae24d917a17176553825cf] ---
if not modules then modules={} end modules ['font-oti']={
version=1.001,
@@ -8133,10 +8147,10 @@ function otffeatures.checkeddefaultlanguage(featuretype,autolanguage,languages)
end
end
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “font-oti”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “font-oti”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “font-ott” aba6d8335a5f38a5a62d3631492f3392] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “font-ott” aba6d8335a5f38a5a62d3631492f3392] ---
if not modules then modules={} end modules ["font-ott"]={
version=1.001,
@@ -9255,10 +9269,10 @@ function otffeatures.normalize(features,wrap)
end
end
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “font-ott”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “font-ott”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “font-cff” 98d5a660ea803b65cb883c009ecf3c0b] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “font-cff” 98d5a660ea803b65cb883c009ecf3c0b] ---
if not modules then modules={} end modules ['font-cff']={
version=1.001,
@@ -11282,10 +11296,10 @@ function readers.cffcheck(filename)
end
end
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “font-cff”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “font-cff”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “font-ttf” 44e61cef50dab9b1aaf48130f9367c34] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “font-ttf” 44e61cef50dab9b1aaf48130f9367c34] ---
if not modules then modules={} end modules ['font-ttf']={
version=1.001,
@@ -12455,10 +12469,10 @@ function readers.gvar(f,fontdata,specification,glyphdata,shapedata)
end
end
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “font-ttf”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “font-ttf”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “font-dsp” b5bf2f1c198e027a0d4ededcdf3947b4] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “font-dsp” 5d3db0184c903829b2c5bddcb8cdb14c] ---
if not modules then modules={} end modules ['font-dsp']={
version=1.001,
@@ -15092,6 +15106,8 @@ function readers.cpal(f,fontdata,specification)
fontdata.colorpalettes=palettes
end
end
+local compress=gzip and gzip.compress
+local compressed=compress and gzip.compressed
function readers.svg(f,fontdata,specification)
local tableoffset=gotodatatable(f,fontdata,"svg",specification.glyphs)
if tableoffset then
@@ -15113,10 +15129,14 @@ function readers.svg(f,fontdata,specification)
for i=1,nofentries do
local entry=entries[i]
setposition(f,entry.offset)
+ local data=readstring(f,entry.length)
+ if compressed and not compressed(data) then
+ data=compress(data)
+ end
entries[i]={
first=entry.first,
last=entry.last,
- data=readstring(f,entry.length)
+ data=data
}
end
fontdata.svgshapes=entries
@@ -15699,10 +15719,10 @@ function readers.mvar(f,fontdata,specification)
end
end
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “font-dsp”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “font-dsp”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “font-oup” 669e479e716999edc626a1f045bd76fa] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “font-oup” 0cef35af01739f52fd09feb5401192ae] ---
if not modules then modules={} end modules ['font-oup']={
version=1.001,
@@ -16379,6 +16399,9 @@ local function checklookups(fontdata,missing,nofmissing)
end
end
end
+local firstprivate=fonts.privateoffsets and fonts.privateoffsets.textbase or 0xF0000
+local puafirst=0xE000
+local pualast=0xF8FF
local function unifymissing(fontdata)
if not fonts.mappings then
require("font-map")
@@ -16389,18 +16412,19 @@ local function unifymissing(fontdata)
resources.unicodes=unicodes
for unicode,d in next,fontdata.descriptions do
if unicode<privateoffset then
- local name=d.name
- if name then
- unicodes[name]=unicode
+ if unicode>=puafirst and unicode<=pualast then
+ else
+ local name=d.name
+ if name then
+ unicodes[name]=unicode
+ end
end
+ else
end
end
fonts.mappings.addtounicode(fontdata,fontdata.filename,checklookups)
resources.unicodes=nil
end
-local firstprivate=fonts.privateoffsets and fonts.privateoffsets.textbase or 0xF0000
-local puafirst=0xE000
-local pualast=0xF8FF
local function unifyglyphs(fontdata,usenames)
local private=fontdata.private or privateoffset
local glyphs=fontdata.glyphs
@@ -18339,10 +18363,10 @@ function readers.expand(data)
expandlookups(sublookups)
end
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “font-oup”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “font-oup”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “font-otl” 940f9c5ad84f4968a8488f4da2d15e2d] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “font-otl” ec0241b7465a7713e53c246e8e9fb2a8] ---
if not modules then modules={} end modules ['font-otl']={
version=1.001,
@@ -18370,11 +18394,12 @@ local trace_defining=false registertracker("fonts.defining",function(v) trace_d
local report_otf=logs.reporter("fonts","otf loading")
local fonts=fonts
local otf=fonts.handlers.otf
-otf.version=3.109
+otf.version=3.110
otf.cache=containers.define("fonts","otl",otf.version,true)
otf.svgcache=containers.define("fonts","svg",otf.version,true)
otf.pngcache=containers.define("fonts","png",otf.version,true)
otf.pdfcache=containers.define("fonts","pdf",otf.version,true)
+otf.mpscache=containers.define("fonts","mps",otf.version,true)
otf.svgenabled=false
otf.pngenabled=false
local otfreaders=otf.readers
@@ -19045,10 +19070,10 @@ otf.coverup={
end
}
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “font-otl”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “font-otl”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “font-oto” 52804afd96f4be005f513a012b874668] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “font-oto” 52804afd96f4be005f513a012b874668] ---
if not modules then modules={} end modules ['font-oto']={
version=1.001,
@@ -19506,10 +19531,10 @@ registerotffeature {
}
otf.basemodeinitializer=featuresinitializer
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “font-oto”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “font-oto”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “font-otj” 66c7a910d95d4a52b81061de776898e1] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “font-otj” 66c7a910d95d4a52b81061de776898e1] ---
if not modules then modules={} end modules ['font-otj']={
version=1.001,
@@ -20966,10 +20991,10 @@ function injections.handler(head,where)
end
end
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “font-otj”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “font-otj”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “font-ota” d6dfb94563d6a52675e274b2e673e4a6] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “font-ota” d6dfb94563d6a52675e274b2e673e4a6] ---
if not modules then modules={} end modules ['font-ota']={
version=1.001,
@@ -21346,10 +21371,10 @@ directives.register("otf.analyze.useunicodemarks",function(v)
analyzers.useunicodemarks=v
end)
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “font-ota”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “font-ota”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “font-ots” d5504847a278385cd0d20ecf1b3d59cc] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “font-ots” d6a0ce4b40cd4ee1895e2248dcf87d37] ---
if not modules then modules={} end modules ['font-ots']={
version=1.001,
@@ -21408,7 +21433,6 @@ registertracker("otf.actions","otf.substitutions","otf.positions")
registertracker("otf.sample","otf.steps","otf.substitutions","otf.positions","otf.analyzing")
registertracker("otf.sample.silent","otf.steps=silent","otf.substitutions","otf.positions","otf.analyzing")
local nuts=nodes.nuts
-local getfield=nuts.getfield
local getnext=nuts.getnext
local setnext=nuts.setnext
local getprev=nuts.getprev
@@ -21424,6 +21448,7 @@ local getchar=nuts.getchar
local setchar=nuts.setchar
local getdisc=nuts.getdisc
local setdisc=nuts.setdisc
+local getreplace=nuts.getreplace
local setlink=nuts.setlink
local getcomponents=nuts.getcomponents
local setcomponents=nuts.setcomponents
@@ -23002,7 +23027,7 @@ local function chaindisk(head,start,dataset,sequence,rlmode,skiphash,ck)
if keepdisc then
keepdisc=false
lookaheaddisc=current
- local replace=getfield(current,"replace")
+ local replace=getreplace(current)
if not replace then
sweepoverflow=true
sweepnode=current
@@ -23074,7 +23099,7 @@ local function chaindisk(head,start,dataset,sequence,rlmode,skiphash,ck)
if notmatchpre[current]~=notmatchreplace[current] then
lookaheaddisc=current
end
- local replace=getfield(current,"replace")
+ local replace=getreplace(current)
while replace and i<s do
if getid(replace)==glyph_code then
i=i+1
@@ -23118,7 +23143,7 @@ local function chaindisk(head,start,dataset,sequence,rlmode,skiphash,ck)
if notmatchpost[current]~=notmatchreplace[current] then
backtrackdisc=current
end
- local replace=getfield(current,"replace")
+ local replace=getreplace(current)
while replace and i>1 do
if getid(replace)==glyph_code then
i=i-1
@@ -24082,7 +24107,7 @@ local function t_run_single(start,stop,font,attr,lookupcache)
end
while getid(s)==disc_code do
ss=getnext(s)
- s=getfield(s,"replace")
+ s=getreplace(s)
if not s then
s=ss
ss=nil
@@ -24109,7 +24134,7 @@ local function t_run_single(start,stop,font,attr,lookupcache)
end
while getid(s)==disc_code do
ss=getnext(s)
- s=getfield(s,"replace")
+ s=getreplace(s)
if not s then
s=ss
ss=nil
@@ -24236,7 +24261,7 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps)
end
while getid(s)==disc_code do
ss=getnext(s)
- s=getfield(s,"replace")
+ s=getreplace(s)
if not s then
s=ss
ss=nil
@@ -24263,7 +24288,7 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps)
end
while getid(s)==disc_code do
ss=getnext(s)
- s=getfield(s,"replace")
+ s=getreplace(s)
if not s then
s=ss
ss=nil
@@ -24963,10 +24988,10 @@ registerotffeature {
},
}
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “font-ots”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “font-ots”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “font-osd” 79eb2fc4a71364fd73c8b996a109f5df] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “font-osd” 39e92f6e575741646d75ea79e3be87f3] ---
if not modules then modules={} end modules ['font-osd']={
version=1.001,
@@ -26046,7 +26071,7 @@ local function reorder_one(head,start,stop,font,attr,nbspaces)
local cp=getprev(current)
local cnsn=getnext(cns)
setlink(cp,n)
- setlink(cns,current)
+ setlink(cns,current)
setlink(c,cnsn)
if c==stop then
stop=cp
@@ -27398,10 +27423,10 @@ for i=1,nofscripts do
methods[scripts_two[i]]=method_two
end
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “font-osd”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “font-osd”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “font-ocl” b720867fb19a23f0b50377efd2a3c54a] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “font-ocl” ba40df1a92b9b42a5c70d20c28f44759] ---
if not modules then modules={} end modules ['font-ocl']={
version=1.001,
@@ -27410,9 +27435,13 @@ if not modules then modules={} end modules ['font-ocl']={
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files"
}
+if CONTEXTLMTXMODE and CONTEXTLMTXMODE>0 then
+ return
+end
local tostring,tonumber,next=tostring,tonumber,next
local round,max=math.round,math.round
-local sortedkeys,sortedhash=table.sortedkeys,table.sortedhash
+local gsub,find=string.gsub,string.find
+local sortedkeys,sortedhash,concat=table.sortedkeys,table.sortedhash,table.concat
local setmetatableindex=table.setmetatableindex
local formatters=string.formatters
local tounicode=fonts.mappings.tounicode
@@ -27422,6 +27451,7 @@ local rightcommand=helpers.commands.right
local leftcommand=helpers.commands.left
local downcommand=helpers.commands.down
local otf=fonts.handlers.otf
+local otfregister=otf.features.register
local f_color=formatters["%.3f %.3f %.3f rg"]
local f_gray=formatters["%.3f g"]
if context then
@@ -27515,7 +27545,7 @@ end
local start={ "pdf","mode","font" }
local push={ "pdf","page","q" }
local pop={ "pdf","page","Q" }
-local function initialize(tfmdata,kind,value)
+local function initializeoverlay(tfmdata,kind,value)
if value then
local resources=tfmdata.resources
local palettes=resources.colorpalettes
@@ -27557,52 +27587,39 @@ local function initialize(tfmdata,kind,value)
local s=#colorlist
local goback=w~=0 and leftcommand[w] or nil
local t={
- start,
- not u and actualb or { "pdf","page",(getactualtext(tounicode(u))) }
+ not u and actualb or { "pdf","page",(getactualtext(tounicode(u))) },
+ push,
}
local n=2
local l=nil
- local f=false
for i=1,s do
local entry=colorlist[i]
local v=colorvalues[entry.class] or default
if v and l~=v then
- if f then
- n=n+1 t[n]=pop
- end
- n=n+1 t[n]=push
- 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
n=n+1 t[n]=goback
end
end
- if f then
- n=n+1 t[n]=pop
- end
+ n=n+1 t[n]=pop
n=n+1 t[n]=actuale
character.commands=t
end
end
end
+ return true
end
end
end
-fonts.handlers.otf.features.register {
+otfregister {
name="colr",
description="color glyphs",
manipulators={
- base=initialize,
- node=initialize,
+ base=initializeoverlay,
+ node=initializeoverlay,
}
}
do
@@ -27653,14 +27670,20 @@ local function pdftovirtual(tfmdata,pdfshapes,kind)
local data=nil
local dx=nil
local dy=nil
+ local scale=1
if typ=="table" then
data=pdf.data
- dx=pdf.dx or 0
- dy=pdf.dy or 0
+ dx=pdf.x or pdf.dx or 0
+ dy=pdf.y or pdf.dy or 0
+ scale=pdf.scale or 1
elseif typ=="string" then
data=pdf
dx=0
dy=0
+ elseif typ=="number" then
+ data=pdf
+ dx=0
+ dy=0
end
if data then
local bt=unicode and getactualtext(unicode)
@@ -27669,9 +27692,9 @@ local function pdftovirtual(tfmdata,pdfshapes,kind)
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),
+ downcommand [dp+dy*hfactor],
+ rightcommand[ dx*hfactor],
+ vfimage(scale*wd,ht,dp,data,pdfshapes.filename or ""),
actuale,
}
character[kind]=true
@@ -27705,24 +27728,27 @@ do
name="otfsvg",
program="inkscape",
method="pipeto",
- template="--shell > temp-otf-svg-shape.log",
+ template="--export-area-drawing --shell > temp-otf-svg-shape.log",
reporter=report_svg,
}
if not runner then
runner=function()
- return io.open("inkscape --shell > temp-otf-svg-shape.log","w")
+ return io.popen("inkscape --export-area-drawing --shell > temp-otf-svg-shape.log","w")
end
end
- function otfsvg.topdf(svgshapes)
+ function otfsvg.topdf(svgshapes,tfmdata)
local pdfshapes={}
local inkscape=runner()
if inkscape then
+ local indices=fonts.getindices(tfmdata)
+ local descriptions=tfmdata.descriptions
local nofshapes=#svgshapes
local f_svgfile=formatters["temp-otf-svg-shape-%i.svg"]
local f_pdffile=formatters["temp-otf-svg-shape-%i.pdf"]
local f_convert=formatters["%s --export-pdf=%s\n"]
local filterglyph=otfsvg.filterglyph
local nofdone=0
+ local processed={}
report_svg("processing %i svg containers",nofshapes)
statistics.starttiming()
for i=1,nofshapes do
@@ -27734,24 +27760,51 @@ do
local pdffile=f_pdffile(index)
savedata(svgfile,data)
inkscape:write(f_convert(svgfile,pdffile))
- pdfshapes[index]=true
+ processed[index]=true
nofdone=nofdone+1
- if nofdone%100==0 then
- report_svg("%i shapes processed",nofdone)
+ if nofdone%25==0 then
+ report_svg("%i shapes submitted",nofdone)
end
end
end
end
+ if nofdone%25~=0 then
+ report_svg("%i shapes submitted",nofdone)
+ end
+ report_svg("processing can be going on for a while")
inkscape:write("quit\n")
inkscape:close()
report_svg("processing %i pdf results",nofshapes)
- for index in next,pdfshapes do
+ for index in next,processed do
local svgfile=f_svgfile(index)
local pdffile=f_pdffile(index)
- pdfshapes[index]=loaddata(pdffile)
+ local pdfdata=loaddata(pdffile)
+ if pdfdata and pdfdata~="" then
+ pdfshapes[index]={
+ data=pdfdata,
+ }
+ end
remove(svgfile)
remove(pdffile)
end
+ local characters=tfmdata.characters
+ for k,v in next,characters do
+ local d=descriptions[k]
+ local i=d.index
+ if i then
+ local p=pdfshapes[i]
+ if p then
+ local w=d.width
+ local l=d.boundingbox[1]
+ local r=d.boundingbox[3]
+ p.scale=(r-l)/w
+ p.x=l
+ end
+ end
+ end
+ if not next(pdfshapes) then
+ report_svg("there are no converted shapes, fix your setup")
+ end
statistics.stoptiming()
if statistics.elapsedseconds then
report_svg("svg conversion time %s",statistics.elapsedseconds() or "-")
@@ -27770,19 +27823,20 @@ local function initializesvg(tfmdata,kind,value)
end
local pdffile=containers.read(otf.pdfcache,hash)
local pdfshapes=pdffile and pdffile.pdfshapes
- if not pdfshapes or pdffile.timestamp~=timestamp then
+ if not pdfshapes or pdffile.timestamp~=timestamp or not next(pdfshapes) then
local svgfile=containers.read(otf.svgcache,hash)
local svgshapes=svgfile and svgfile.svgshapes
- pdfshapes=svgshapes and otfsvg.topdf(svgshapes) or {}
+ pdfshapes=svgshapes and otfsvg.topdf(svgshapes,tfmdata,otf.pdfcache.writable,hash) or {}
containers.write(otf.pdfcache,hash,{
pdfshapes=pdfshapes,
timestamp=timestamp,
})
end
pdftovirtual(tfmdata,pdfshapes,"svg")
+ return true
end
end
-fonts.handlers.otf.features.register {
+otfregister {
name="svg",
description="svg glyphs",
manipulators={
@@ -27865,9 +27919,10 @@ local function initializepng(tfmdata,kind,value)
})
end
pdftovirtual(tfmdata,pdfshapes,"png")
+ return true
end
end
-fonts.handlers.otf.features.register {
+otfregister {
name="sbix",
description="sbix glyphs",
manipulators={
@@ -27875,7 +27930,7 @@ fonts.handlers.otf.features.register {
node=initializepng,
}
}
-fonts.handlers.otf.features.register {
+otfregister {
name="cblc",
description="cblc glyphs",
manipulators={
@@ -27883,11 +27938,36 @@ fonts.handlers.otf.features.register {
node=initializepng,
}
}
+if context then
+ local function initializecolor(tfmdata,kind,value)
+ if value=="auto" then
+ return
+ initializeoverlay(tfmdata,kind,value) or
+ initializesvg(tfmdata,kind,value) or
+ initializepng(tfmdata,kind,value)
+ elseif value=="overlay" then
+ return initializeoverlay(tfmdata,kind,value)
+ elseif value=="svg" then
+ return initializesvg(tfmdata,kind,value)
+ elseif value=="png" or value=="bitmap" then
+ return initializepng(tfmdata,kind,value)
+ else
+ end
+ end
+ otfregister {
+ name="color",
+ description="color glyphs",
+ manipulators={
+ base=initializecolor,
+ node=initializecolor,
+ }
+ }
+end
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “font-ocl”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “font-ocl”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “font-otc” 95a4ff28ba4afb55a978a4aecfd688bf] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “font-otc” 1204a2fdc436e644127c0aa38ab69607] ---
if not modules then modules={} end modules ['font-otc']={
version=1.001,
@@ -27907,9 +27987,10 @@ local fonts=fonts
local otf=fonts.handlers.otf
local registerotffeature=otf.features.register
local setmetatableindex=table.setmetatableindex
-local checkmerge=fonts.helpers.checkmerge
-local checkflags=fonts.helpers.checkflags
-local checksteps=fonts.helpers.checksteps
+local fonthelpers=fonts.helpers
+local checkmerge=fonthelpers.checkmerge
+local checkflags=fonthelpers.checkflags
+local checksteps=fonthelpers.checksteps
local normalized={
substitution="substitution",
single="substitution",
@@ -28031,6 +28112,7 @@ local function addfeature(data,feature,specifications)
local done=0
local skip=0
local aglunicodes=false
+ local privateslot=fonthelpers.privateslot
local specifications=validspecification(specifications,feature)
if not specifications then
return
@@ -28053,6 +28135,12 @@ local function addfeature(data,feature,specifications)
return u
end
end
+ if privateslot then
+ u=privateslot(code)
+ if u then
+ return u
+ end
+ end
local u=lpegmatch(p,code)
if u then
return u
@@ -28082,7 +28170,7 @@ local function addfeature(data,feature,specifications)
replacement=replacement[1]
end
replacement=tounicode(replacement)
- if replacement and descriptions[replacement] then
+ if replacement and (nocheck or descriptions[replacement]) then
cover(coverage,unicode,replacement)
done=done+1
else
@@ -28452,7 +28540,6 @@ local function addfeature(data,feature,specifications)
local featuretype=normalized[specification.type or "substitution"] or "substitution"
local featureflags=specification.flags or noflags
local nocheck=specification.nocheck
- local futuresteps=specification.futuresteps
local featureorder=specification.order or { feature }
local featurechain=(featuretype=="chainsubstitution" or featuretype=="chainposition") and 1 or 0
local nofsteps=0
@@ -28637,10 +28724,10 @@ end
otf.enhancers.enhance=enhance
otf.enhancers.register("check extra features",enhance)
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “font-otc”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “font-otc”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “font-onr” d4d2449b4084e6afb1837ae5835082cc] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “font-onr” d4d2449b4084e6afb1837ae5835082cc] ---
if not modules then modules={} end modules ['font-onr']={
version=1.001,
@@ -29012,10 +29099,10 @@ function readers.getinfo(filename)
end
end
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “font-onr”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “font-onr”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “font-one” 987c5c5ed3754ad2feab80985067d59e] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “font-one” 987c5c5ed3754ad2feab80985067d59e] ---
if not modules then modules={} end modules ['font-one']={
version=1.001,
@@ -29726,10 +29813,10 @@ registerafmenhancer("normalize features",enhance_normalize_features)
registerafmenhancer("check extra features",otfenhancers.enhance)
registerafmenhancer("fix names",enhance_fix_names)
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “font-one”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “font-one”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “font-afk” 54d554530e75c57c56ee76234724e26d] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “font-afk” 54d554530e75c57c56ee76234724e26d] ---
if not modules then modules={} end modules ['font-afk']={
version=1.001,
@@ -29896,10 +29983,10 @@ fonts.handlers.afm.helpdata={
}
}
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “font-afk”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “font-afk”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “fonts-tfm” 3bbba3214fd0b8c6f35ad85592fc2917] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “fonts-tfm” 3bbba3214fd0b8c6f35ad85592fc2917] ---
if not modules then modules={} end modules ['luatex-fonts-tfm']={
version=1.001,
@@ -30414,10 +30501,10 @@ registertfmfeature {
}
}
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “fonts-tfm”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “fonts-tfm”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “font-lua” 55b281fb98f7bd848fc19928f376f647] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “font-lua” 55b281fb98f7bd848fc19928f376f647] ---
if not modules then modules={} end modules ['font-lua']={
version=1.001,
@@ -30457,10 +30544,10 @@ function readers.lua(specification)
return check_lua(specification,fullname)
end
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “font-lua”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “font-lua”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “font-def” f66c365dae4499f982d8bf16e5d37de3] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “font-def” f66c365dae4499f982d8bf16e5d37de3] ---
if not modules then modules={} end modules ['font-def']={
version=1.001,
@@ -30862,10 +30949,10 @@ function font.getfont(id)
end
callbacks.register('define_font',definers.read,"definition of fonts (tfmdata preparation)")
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “font-def”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “font-def”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “fonts-def” 5ad79120ebc5e60f4d322fb3ee13bffe] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “fonts-def” 5ad79120ebc5e60f4d322fb3ee13bffe] ---
if not modules then modules={} end modules ['luatex-fonts-def']={
version=1.001,
@@ -30946,10 +31033,10 @@ function fonts.definers.applypostprocessors(tfmdata)
return tfmdata
end
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “fonts-def”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “fonts-def”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “fonts-ext” 01015ab3758cdc2af29394e6d502a91a] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “fonts-ext” 01015ab3758cdc2af29394e6d502a91a] ---
if not modules then modules={} end modules ['luatex-fonts-ext']={
version=1.001,
@@ -31135,10 +31222,10 @@ registerotffeature {
}
}
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “fonts-ext”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “fonts-ext”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “font-imp-tex” 77c374b0ef00c2fb12188ec42beb4257] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “font-imp-tex” 77c374b0ef00c2fb12188ec42beb4257] ---
if not modules then modules={} end modules ['font-imp-tex']={
version=1.001,
@@ -31237,10 +31324,10 @@ registerotffeature {
description="arabic digits",
}
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “font-imp-tex”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “font-imp-tex”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “font-imp-ligatures” 043daa4fcccf2560868da359d71d3a4a] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “font-imp-ligatures” 043daa4fcccf2560868da359d71d3a4a] ---
if not modules then modules={} end modules ['font-imp-ligatures']={
version=1.001,
@@ -31354,10 +31441,10 @@ if context then
}
end
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “font-imp-ligatures”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “font-imp-ligatures”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “font-imp-italics” fe1ca80fb5ea4a2f8d2d5c484e7ba913] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “font-imp-italics” fe1ca80fb5ea4a2f8d2d5c484e7ba913] ---
if not modules then modules={} end modules ['font-imp-italics']={
version=1.001,
@@ -31463,10 +31550,10 @@ if context then
registerafmfeature(dimensions_specification)
end
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “font-imp-italics”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “font-imp-italics”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “font-imp-effects” 73a660359a0ec71e44cc2b7225a715ac] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “font-imp-effects” 73a660359a0ec71e44cc2b7225a715ac] ---
if not modules then modules={} end modules ['font-imp-effects']={
version=1.001,
@@ -31823,10 +31910,10 @@ local specification={
registerotffeature(specification)
registerafmfeature(specification)
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “font-imp-effects”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “font-imp-effects”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “fonts-lig” b9dbe77ce747d4c35bb2a20ffbe5aa51] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “fonts-lig” b9dbe77ce747d4c35bb2a20ffbe5aa51] ---
fonts.handlers.otf.addfeature {
@@ -33895,10 +33982,10 @@ fonts.handlers.otf.addfeature {
["type"]="ligature",
}
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “fonts-lig”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “fonts-lig”] ---
-do --- [luaotfload, fontloader-2019-08-13.lua scope for “fonts-gbn” d25472d54c4841db43a745764a63533e] ---
+do --- [luaotfload, fontloader-2019-10-29.lua scope for “fonts-gbn” d25472d54c4841db43a745764a63533e] ---
if not modules then modules={} end modules ['luatex-fonts-gbn']={
version=1.001,
@@ -34163,7 +34250,7 @@ function nodes.simple_font_handler(head,groupcode,size,packtype,direction)
return head
end
-end --- [luaotfload, fontloader-2019-08-13.lua scope for “fonts-gbn”] ---
+end --- [luaotfload, fontloader-2019-10-29.lua scope for “fonts-gbn”] ---
--- vim:ft=lua:sw=2:ts=8:et:tw=79
diff --git a/macros/luatex/generic/luaotfload/fontloader-basics-nod.lua b/macros/luatex/generic/luaotfload/fontloader-basics-nod.lua
index 418b9d69d4..172fcc7f7e 100644
--- a/macros/luatex/generic/luaotfload/fontloader-basics-nod.lua
+++ b/macros/luatex/generic/luaotfload/fontloader-basics-nod.lua
@@ -99,6 +99,7 @@ nuts.getchar = direct.getchar
nuts.getcomponents = direct.getcomponents
nuts.getdirection = direct.getdirection
nuts.getdisc = direct.getdisc
+nuts.getreplace = direct.getreplace
nuts.getfield = direct.getfield
nuts.getfont = direct.getfont
nuts.getid = direct.getid
@@ -115,6 +116,7 @@ nuts.setchar = direct.setchar
nuts.setcomponents = direct.setcomponents
nuts.setdirection = direct.setdirection
nuts.setdisc = direct.setdisc
+nuts.setreplace = direct.setreplace
nuts.setfield = setfield
nuts.setkern = direct.setkern
nuts.setlink = direct.setlink
@@ -261,3 +263,19 @@ do
}
end
+
+if not nuts.setreplace then
+
+ local getdisc = nuts.getdisc
+ local setfield = nuts.setfield
+
+ function nuts.getreplace(n)
+ local _, _, h, _, _, t = getdisc(n,true)
+ return h, t
+ end
+
+ function nuts.setreplace(n,h)
+ setfield(n,"replace",h)
+ end
+
+end
diff --git a/macros/luatex/generic/luaotfload/fontloader-font-con.lua b/macros/luatex/generic/luaotfload/fontloader-font-con.lua
index 9c1e825fa2..652794142b 100644
--- a/macros/luatex/generic/luaotfload/fontloader-font-con.lua
+++ b/macros/luatex/generic/luaotfload/fontloader-font-con.lua
@@ -444,9 +444,10 @@ function constructors.scale(tfmdata,specification)
-- boundarychar = 65536, -- there is now a string 'right_boundary'
-- false_boundarychar = 65536, -- produces invalid tfm in luatex
--
- targetproperties.language = properties.language or "dflt" -- inherited
- targetproperties.script = properties.script or "dflt" -- inherited
- targetproperties.mode = properties.mode or "base" -- inherited
+ targetproperties.language = properties.language or "dflt" -- inherited
+ targetproperties.script = properties.script or "dflt" -- inherited
+ targetproperties.mode = properties.mode or "base" -- inherited
+ targetproperties.method = properties.method
--
local askedscaledpoints = scaledpoints
local scaledpoints, delta = constructors.calculatescale(tfmdata,scaledpoints,nil,specification) -- no shortcut, dan be redefined
diff --git a/macros/luatex/generic/luaotfload/fontloader-font-dsp.lua b/macros/luatex/generic/luaotfload/fontloader-font-dsp.lua
index 79749741c3..7777f9c6ad 100644
--- a/macros/luatex/generic/luaotfload/fontloader-font-dsp.lua
+++ b/macros/luatex/generic/luaotfload/fontloader-font-dsp.lua
@@ -3159,6 +3159,14 @@ function readers.cpal(f,fontdata,specification)
end
end
+local compress = gzip and gzip.compress
+local compressed = compress and gzip.compressed
+
+-- At some point I will delay loading and only store the offsets (in context lmtx
+-- only).
+
+-- compressed = false
+
function readers.svg(f,fontdata,specification)
local tableoffset = gotodatatable(f,fontdata,"svg",specification.glyphs)
if tableoffset then
@@ -3184,10 +3192,14 @@ function readers.svg(f,fontdata,specification)
for i=1,nofentries do
local entry = entries[i]
setposition(f,entry.offset)
+ local data = readstring(f,entry.length)
+ if compressed and not compressed(data) then
+ data = compress(data)
+ end
entries[i] = {
first = entry.first,
last = entry.last,
- data = readstring(f,entry.length)
+ data = data
}
end
fontdata.svgshapes = entries
diff --git a/macros/luatex/generic/luaotfload/fontloader-font-ocl.lua b/macros/luatex/generic/luaotfload/fontloader-font-ocl.lua
index d79ed657e0..3752203fa2 100644
--- a/macros/luatex/generic/luaotfload/fontloader-font-ocl.lua
+++ b/macros/luatex/generic/luaotfload/fontloader-font-ocl.lua
@@ -8,9 +8,14 @@ if not modules then modules = { } end modules ['font-ocl'] = {
-- todo : user list of colors
+if CONTEXTLMTXMODE and CONTEXTLMTXMODE > 0 then
+ return
+end
+
local tostring, tonumber, next = tostring, tonumber, next
local round, max = math.round, math.round
-local sortedkeys, sortedhash = table.sortedkeys, table.sortedhash
+local gsub, find = string.gsub, string.find
+local sortedkeys, sortedhash, concat = table.sortedkeys, table.sortedhash, table.concat
local setmetatableindex = table.setmetatableindex
local formatters = string.formatters
@@ -24,6 +29,7 @@ local leftcommand = helpers.commands.left
local downcommand = helpers.commands.down
local otf = fonts.handlers.otf
+local otfregister = otf.features.register
local f_color = formatters["%.3f %.3f %.3f rg"]
local f_gray = formatters["%.3f g"]
@@ -150,7 +156,7 @@ local pop = { "pdf", "page", "Q" }
-- -- only shows the first glyph in acrobat and nothing more. No problem with other
-- -- renderers.
--
--- local function initialize(tfmdata,kind,value) -- hm, always value
+-- local function initializeoverlay(tfmdata,kind,value) -- hm, always value
-- if value then
-- local resources = tfmdata.resources
-- local palettes = resources.colorpalettes
@@ -193,11 +199,11 @@ local pop = { "pdf", "page", "Q" }
-- local goback = w ~= 0 and leftcommand[w] or nil -- needs checking: are widths the same
-- local t = {
-- start,
--- not u and actualb or { "pdf", "page", (getactualtext(tounicode(u))) }
+-- not u and actualb or { "pdf", "page", (getactualtext(tounicode(u))) },
+-- push,
-- }
--- local n = 2
+-- local n = 3
-- local l = nil
--- n = n + 1 t[n] = push
-- for i=1,s do
-- local entry = colorlist[i]
-- local v = colorvalues[entry.class] or default
@@ -220,11 +226,8 @@ local pop = { "pdf", "page", "Q" }
-- end
-- end
-- end
---
--- -- Here we have no color change in BT .. ET and more q Q pairs but even then acrobat
--- -- fails displaying the overlays correctly. Other renderers do it right.
-local function initialize(tfmdata,kind,value)
+local function initializeoverlay(tfmdata,kind,value)
if value then
local resources = tfmdata.resources
local palettes = resources.colorpalettes
@@ -271,54 +274,40 @@ local function initialize(tfmdata,kind,value)
local s = #colorlist
local goback = w ~= 0 and leftcommand[w] or nil -- needs checking: are widths the same
local t = {
- start, -- really needed
- not u and actualb or { "pdf", "page", (getactualtext(tounicode(u))) }
+ not u and actualb or { "pdf", "page", (getactualtext(tounicode(u))) },
+ push,
}
local n = 2
local l = nil
- local f = false
for i=1,s do
local entry = colorlist[i]
local v = colorvalues[entry.class] or default
if v and l ~= v then
- if f then
- n = n + 1 t[n] = pop
- end
- n = n + 1 t[n] = push
- 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
n = n + 1 t[n] = goback
end
end
- if f then
- n = n + 1 t[n] = pop
- end
+ n = n + 1 t[n] = pop
n = n + 1 t[n] = actuale
- -- n = n + 1 t[n] = stop -- not needed
character.commands = t
end
end
end
+ return true
end
end
end
-fonts.handlers.otf.features.register {
+otfregister {
name = "colr",
description = "color glyphs",
manipulators = {
- base = initialize,
- node = initialize,
+ base = initializeoverlay,
+ node = initializeoverlay,
}
}
@@ -382,19 +371,25 @@ local function pdftovirtual(tfmdata,pdfshapes,kind) -- kind = png|svg
for unicode, character in sortedhash(characters) do -- sort is nicer for svg
local index = character.index
if index then
- local pdf = pdfshapes[index]
- local typ = type(pdf)
- local data = nil
- local dx = nil
- local dy = nil
+ local pdf = pdfshapes[index]
+ local typ = type(pdf)
+ local data = nil
+ local dx = nil
+ local dy = nil
+ local scale = 1
if typ == "table" then
- data = pdf.data
- dx = pdf.dx or 0
- dy = pdf.dy or 0
+ data = pdf.data
+ dx = pdf.x or pdf.dx or 0
+ dy = pdf.y or pdf.dy or 0
+ scale = pdf.scale or 1
elseif typ == "string" then
data = pdf
dx = 0
dy = 0
+ elseif typ == "number" then
+ data = pdf
+ dx = 0
+ dy = 0
end
if data then
-- We can delay storage by a lua function in commands: but then we need to
@@ -404,12 +399,20 @@ local function pdftovirtual(tfmdata,pdfshapes,kind) -- kind = png|svg
local wd = character.width or 0
local ht = character.height or 0
local dp = character.depth or 0
- -- The down and right will change too (we can move that elsewhere).
+ -- The down and right will change too (we can move that elsewhere). We have
+ -- a different treatment in lmtx but the next kind of works. These images are
+ -- a mess anyway as in svg the bbox can be messed up absent). A png image
+ -- needs the x/y. I might normalize this once we moev to lmtx exlusively.
character.commands = {
not unicode and actualb or { "pdf", "page", (getactualtext(unicode)) },
- downcommand[dp + dy * hfactor],
- rightcommand[dx * hfactor],
- vfimage(wd,ht,dp,data,name),
+ -- lmtx (when we deal with depth in vfimage, currently disabled):
+ -- downcommand [dy * hfactor],
+ -- rightcommand[dx * hfactor],
+ -- vfimage(wd,ht,dp,data,name),
+ -- mkiv
+ downcommand [dp + dy * hfactor],
+ rightcommand[ dx * hfactor],
+ vfimage(scale*wd,ht,dp,data,pdfshapes.filename or ""),
actuale,
}
character[kind] = true
@@ -455,7 +458,7 @@ do
name = "otfsvg",
program = "inkscape",
method = "pipeto",
- template = "--shell > temp-otf-svg-shape.log",
+ template = "--export-area-drawing --shell > temp-otf-svg-shape.log",
reporter = report_svg,
}
@@ -464,20 +467,31 @@ do
-- poor mans variant for generic:
--
runner = function()
- return io.open("inkscape --shell > temp-otf-svg-shape.log","w")
+ return io.popen("inkscape --export-area-drawing --shell > temp-otf-svg-shape.log","w")
end
end
- function otfsvg.topdf(svgshapes)
+ -- There are svg out there with bad viewBox specifications where shapes lay outside that area,
+ -- but trying to correct that didn't work out well enough so I discarded that code. BTW, we
+ -- decouple the inskape run and the loading run because inkscape is working in the background
+ -- in the files so we need to have unique files.
+ --
+ -- Because a generic setup can be flawed we need to catch bad inkscape runs which add a bit of
+ -- ugly overhead. Bah.
+
+ function otfsvg.topdf(svgshapes,tfmdata)
local pdfshapes = { }
local inkscape = runner()
if inkscape then
- local nofshapes = #svgshapes
- local f_svgfile = formatters["temp-otf-svg-shape-%i.svg"]
- local f_pdffile = formatters["temp-otf-svg-shape-%i.pdf"]
- local f_convert = formatters["%s --export-pdf=%s\n"]
- local filterglyph = otfsvg.filterglyph
- local nofdone = 0
+ local indices = fonts.getindices(tfmdata)
+ local descriptions = tfmdata.descriptions
+ local nofshapes = #svgshapes
+ local f_svgfile = formatters["temp-otf-svg-shape-%i.svg"]
+ local f_pdffile = formatters["temp-otf-svg-shape-%i.pdf"]
+ local f_convert = formatters["%s --export-pdf=%s\n"]
+ local filterglyph = otfsvg.filterglyph
+ local nofdone = 0
+ local processed = { }
report_svg("processing %i svg containers",nofshapes)
statistics.starttiming()
for i=1,nofshapes do
@@ -489,24 +503,55 @@ do
local pdffile = f_pdffile(index)
savedata(svgfile,data)
inkscape:write(f_convert(svgfile,pdffile))
- pdfshapes[index] = true
+ processed[index] = true
nofdone = nofdone + 1
- if nofdone % 100 == 0 then
- report_svg("%i shapes processed",nofdone)
+ if nofdone % 25 == 0 then
+ report_svg("%i shapes submitted",nofdone)
end
end
end
end
+ if nofdone % 25 ~= 0 then
+ report_svg("%i shapes submitted",nofdone)
+ end
+ report_svg("processing can be going on for a while")
inkscape:write("quit\n")
inkscape:close()
report_svg("processing %i pdf results",nofshapes)
- for index in next, pdfshapes do
+ for index in next, processed do
local svgfile = f_svgfile(index)
local pdffile = f_pdffile(index)
- pdfshapes[index] = loaddata(pdffile)
+ -- local fntdata = descriptions[indices[index]]
+ -- local bounds = fntdata and fntdata.boundingbox
+ local pdfdata = loaddata(pdffile)
+ if pdfdata and pdfdata ~= "" then
+ pdfshapes[index] = {
+ data = pdfdata,
+ -- x = bounds and bounds[1] or 0,
+ -- y = bounds and bounds[2] or 0,
+ }
+ end
remove(svgfile)
remove(pdffile)
end
+ local characters = tfmdata.characters
+ for k, v in next, characters do
+ local d = descriptions[k]
+ local i = d.index
+ if i then
+ local p = pdfshapes[i]
+ if p then
+ local w = d.width
+ local l = d.boundingbox[1]
+ local r = d.boundingbox[3]
+ p.scale = (r - l) / w
+ p.x = l
+ end
+ end
+ end
+ if not next(pdfshapes) then
+ report_svg("there are no converted shapes, fix your setup")
+ end
statistics.stoptiming()
if statistics.elapsedseconds then
report_svg("svg conversion time %s",statistics.elapsedseconds() or "-")
@@ -527,20 +572,23 @@ local function initializesvg(tfmdata,kind,value) -- hm, always value
end
local pdffile = containers.read(otf.pdfcache,hash)
local pdfshapes = pdffile and pdffile.pdfshapes
- if not pdfshapes or pdffile.timestamp ~= timestamp then
+ if not pdfshapes or pdffile.timestamp ~= timestamp or not next(pdfshapes) then
+ -- the next test tries to catch errors in generic usage but of course can result
+ -- in running again and again
local svgfile = containers.read(otf.svgcache,hash)
local svgshapes = svgfile and svgfile.svgshapes
- pdfshapes = svgshapes and otfsvg.topdf(svgshapes) or { }
+ pdfshapes = svgshapes and otfsvg.topdf(svgshapes,tfmdata,otf.pdfcache.writable,hash) or { }
containers.write(otf.pdfcache, hash, {
pdfshapes = pdfshapes,
timestamp = timestamp,
})
end
pdftovirtual(tfmdata,pdfshapes,"svg")
+ return true
end
end
-fonts.handlers.otf.features.register {
+otfregister {
name = "svg",
description = "svg glyphs",
manipulators = {
@@ -648,10 +696,11 @@ local function initializepng(tfmdata,kind,value) -- hm, always value
end
--
pdftovirtual(tfmdata,pdfshapes,"png")
+ return true
end
end
-fonts.handlers.otf.features.register {
+otfregister {
name = "sbix",
description = "sbix glyphs",
manipulators = {
@@ -660,7 +709,7 @@ fonts.handlers.otf.features.register {
}
}
-fonts.handlers.otf.features.register {
+otfregister {
name = "cblc",
description = "cblc glyphs",
manipulators = {
@@ -668,3 +717,36 @@ fonts.handlers.otf.features.register {
node = initializepng,
}
}
+
+if context then
+
+ -- untested in generic and might clash with other color trickery
+ -- anyway so let's stick to context only
+
+ local function initializecolor(tfmdata,kind,value)
+ if value == "auto" then
+ return
+ initializeoverlay(tfmdata,kind,value) or
+ initializesvg(tfmdata,kind,value) or
+ initializepng(tfmdata,kind,value)
+ elseif value == "overlay" then
+ return initializeoverlay(tfmdata,kind,value)
+ elseif value == "svg" then
+ return initializesvg(tfmdata,kind,value)
+ elseif value == "png" or value == "bitmap" then
+ return initializepng(tfmdata,kind,value)
+ else
+ -- forget about it
+ end
+ end
+
+ otfregister {
+ name = "color",
+ description = "color glyphs",
+ manipulators = {
+ base = initializecolor,
+ node = initializecolor,
+ }
+ }
+
+end
diff --git a/macros/luatex/generic/luaotfload/fontloader-font-osd.lua b/macros/luatex/generic/luaotfload/fontloader-font-osd.lua
index 203c1d79d4..b97ac9c6f5 100644
--- a/macros/luatex/generic/luaotfload/fontloader-font-osd.lua
+++ b/macros/luatex/generic/luaotfload/fontloader-font-osd.lua
@@ -1285,7 +1285,7 @@ local function reorder_one(head,start,stop,font,attr,nbspaces)
local cp = getprev(current)
local cnsn = getnext(cns)
setlink(cp,n)
- setlink(cns,current)
+ setlink(cns,current) -- cns ?
setlink(c,cnsn)
if c == stop then
stop = cp
diff --git a/macros/luatex/generic/luaotfload/fontloader-font-otc.lua b/macros/luatex/generic/luaotfload/fontloader-font-otc.lua
index a774a81c2c..2643d022a5 100644
--- a/macros/luatex/generic/luaotfload/fontloader-font-otc.lua
+++ b/macros/luatex/generic/luaotfload/fontloader-font-otc.lua
@@ -22,9 +22,10 @@ local otf = fonts.handlers.otf
local registerotffeature = otf.features.register
local setmetatableindex = table.setmetatableindex
-local checkmerge = fonts.helpers.checkmerge
-local checkflags = fonts.helpers.checkflags
-local checksteps = fonts.helpers.checksteps
+local fonthelpers = fonts.helpers
+local checkmerge = fonthelpers.checkmerge
+local checkflags = fonthelpers.checkflags
+local checksteps = fonthelpers.checksteps
local normalized = {
substitution = "substitution",
@@ -167,6 +168,7 @@ local function addfeature(data,feature,specifications)
local done = 0
local skip = 0
local aglunicodes = false
+ local privateslot = fonthelpers.privateslot
local specifications = validspecification(specifications,feature)
if not specifications then
@@ -196,6 +198,13 @@ local function addfeature(data,feature,specifications)
return u
end
end
+ if privateslot then
+ u = privateslot(code) -- no creation !
+ if u then
+ -- unicodes[code] = u
+ return u
+ end
+ end
local u = lpegmatch(p,code)
if u then
-- unicodes[code] = u
@@ -229,7 +238,7 @@ local function addfeature(data,feature,specifications)
replacement = replacement[1]
end
replacement = tounicode(replacement)
- if replacement and descriptions[replacement] then
+ if replacement and (nocheck or descriptions[replacement]) then
cover(coverage,unicode,replacement)
done = done + 1
else
@@ -620,7 +629,6 @@ local function addfeature(data,feature,specifications)
local featuretype = normalized[specification.type or "substitution"] or "substitution"
local featureflags = specification.flags or noflags
local nocheck = specification.nocheck
- local futuresteps = specification.futuresteps
local featureorder = specification.order or { feature }
local featurechain = (featuretype == "chainsubstitution" or featuretype == "chainposition") and 1 or 0
local nofsteps = 0
diff --git a/macros/luatex/generic/luaotfload/fontloader-font-otl.lua b/macros/luatex/generic/luaotfload/fontloader-font-otl.lua
index f8cd8217cd..5d3bd4230c 100644
--- a/macros/luatex/generic/luaotfload/fontloader-font-otl.lua
+++ b/macros/luatex/generic/luaotfload/fontloader-font-otl.lua
@@ -52,11 +52,12 @@ local report_otf = logs.reporter("fonts","otf loading")
local fonts = fonts
local otf = fonts.handlers.otf
-otf.version = 3.109 -- beware: also sync font-mis.lua and in mtx-fonts
+otf.version = 3.110 -- beware: also sync font-mis.lua and in mtx-fonts
otf.cache = containers.define("fonts", "otl", otf.version, true)
otf.svgcache = containers.define("fonts", "svg", otf.version, true)
otf.pngcache = containers.define("fonts", "png", otf.version, true)
otf.pdfcache = containers.define("fonts", "pdf", otf.version, true)
+otf.mpscache = containers.define("fonts", "mps", otf.version, true)
otf.svgenabled = false
otf.pngenabled = false
diff --git a/macros/luatex/generic/luaotfload/fontloader-font-ots.lua b/macros/luatex/generic/luaotfload/fontloader-font-ots.lua
index 6313022006..5091fd7657 100644
--- a/macros/luatex/generic/luaotfload/fontloader-font-ots.lua
+++ b/macros/luatex/generic/luaotfload/fontloader-font-ots.lua
@@ -177,7 +177,6 @@ registertracker("otf.sample.silent", "otf.steps=silent","otf.substitutions","otf
local nuts = nodes.nuts
-local getfield = nuts.getfield
local getnext = nuts.getnext
local setnext = nuts.setnext
local getprev = nuts.getprev
@@ -193,6 +192,7 @@ local getchar = nuts.getchar
local setchar = nuts.setchar
local getdisc = nuts.getdisc
local setdisc = nuts.setdisc
+local getreplace = nuts.getreplace
local setlink = nuts.setlink
local getcomponents = nuts.getcomponents -- the original one, not yet node-aux
local setcomponents = nuts.setcomponents -- the original one, not yet node-aux
@@ -2090,7 +2090,7 @@ local function chaindisk(head,start,dataset,sequence,rlmode,skiphash,ck)
if keepdisc then
keepdisc = false
lookaheaddisc = current
- local replace = getfield(current,"replace")
+ local replace = getreplace(current)
if not replace then
sweepoverflow = true
sweepnode = current
@@ -2167,7 +2167,7 @@ local function chaindisk(head,start,dataset,sequence,rlmode,skiphash,ck)
lookaheaddisc = current
end
-- we assume a simple text only replace (we could use nuts.count)
- local replace = getfield(current,"replace")
+ local replace = getreplace(current)
while replace and i < s do
if getid(replace) == glyph_code then
i = i + 1
@@ -2213,7 +2213,7 @@ local function chaindisk(head,start,dataset,sequence,rlmode,skiphash,ck)
backtrackdisc = current
end
-- we assume a simple text only replace (we could use nuts.count)
- local replace = getfield(current,"replace")
+ local replace = getreplace(current)
while replace and i > 1 do
if getid(replace) == glyph_code then
i = i - 1
@@ -3386,7 +3386,7 @@ local function t_run_single(start,stop,font,attr,lookupcache)
-- how about post ... we can probably merge this into the while
while getid(s) == disc_code do
ss = getnext(s)
- s = getfield(s,"replace")
+ s = getreplace(s)
if not s then
s = ss
ss = nil
@@ -3413,7 +3413,7 @@ local function t_run_single(start,stop,font,attr,lookupcache)
end
while getid(s) == disc_code do
ss = getnext(s)
- s = getfield(s,"replace")
+ s = getreplace(s)
if not s then
s = ss
ss = nil
@@ -3556,7 +3556,7 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps)
end
while getid(s) == disc_code do
ss = getnext(s)
- s = getfield(s,"replace")
+ s = getreplace(s)
if not s then
s = ss
ss = nil
@@ -3583,7 +3583,7 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps)
end
while getid(s) == disc_code do
ss = getnext(s)
- s = getfield(s,"replace")
+ s = getreplace(s)
if not s then
s = ss
ss = nil
diff --git a/macros/luatex/generic/luaotfload/fontloader-font-oup.lua b/macros/luatex/generic/luaotfload/fontloader-font-oup.lua
index 51b1c248f8..0e7e25808c 100644
--- a/macros/luatex/generic/luaotfload/fontloader-font-oup.lua
+++ b/macros/luatex/generic/luaotfload/fontloader-font-oup.lua
@@ -720,6 +720,10 @@ local function checklookups(fontdata,missing,nofmissing)
end
end
+local firstprivate = fonts.privateoffsets and fonts.privateoffsets.textbase or 0xF0000
+local puafirst = 0xE000
+local pualast = 0xF8FF
+
local function unifymissing(fontdata)
if not fonts.mappings then
require("font-map")
@@ -730,20 +734,22 @@ local function unifymissing(fontdata)
resources.unicodes = unicodes
for unicode, d in next, fontdata.descriptions do
if unicode < privateoffset then
- local name = d.name
- if name then
- unicodes[name] = unicode
+ if unicode >= puafirst and unicode <= pualast then
+ -- report_unicodes("resolving private unicode %U",unicode)
+ else
+ local name = d.name
+ if name then
+ unicodes[name] = unicode
+ end
end
+ else
+ -- report_unicodes("resolving private unicode %U",unicode)
end
end
fonts.mappings.addtounicode(fontdata,fontdata.filename,checklookups)
resources.unicodes = nil
end
-local firstprivate = fonts.privateoffsets and fonts.privateoffsets.textbase or 0xF0000
-local puafirst = 0xE000
-local pualast = 0xF8FF
-
local function unifyglyphs(fontdata,usenames)
local private = fontdata.private or privateoffset
local glyphs = fontdata.glyphs
diff --git a/macros/luatex/generic/luaotfload/fontloader-l-lpeg.lua b/macros/luatex/generic/luaotfload/fontloader-l-lpeg.lua
index 51bc1d3df3..7979a40fb9 100644
--- a/macros/luatex/generic/luaotfload/fontloader-l-lpeg.lua
+++ b/macros/luatex/generic/luaotfload/fontloader-l-lpeg.lua
@@ -295,7 +295,7 @@ patterns.longtostring = Cs(whitespace^0/"" * ((patterns.quoted + nonwhitespace^
-- return P { P(pattern) + 1 * V(1) }
-- end
-function anywhere(pattern) -- faster
+local function anywhere(pattern) -- faster
return (1-P(pattern))^0 * P(pattern)
end
diff --git a/macros/luatex/generic/luaotfload/fontloader-l-lua.lua b/macros/luatex/generic/luaotfload/fontloader-l-lua.lua
index 6e9606e849..51399216cc 100644
--- a/macros/luatex/generic/luaotfload/fontloader-l-lua.lua
+++ b/macros/luatex/generic/luaotfload/fontloader-l-lua.lua
@@ -35,6 +35,12 @@ if LUAVERSION < 5.2 and jit then
LUAVERSION = 5.2
end
+-- this is lmtx only:
+
+if lua and lua.openfile then
+ io.open = lua.openfile
+end
+
-- lpeg
if not lpeg then
diff --git a/macros/luatex/generic/luaotfload/fontloader-l-table.lua b/macros/luatex/generic/luaotfload/fontloader-l-table.lua
index cffdcc23e2..e828203867 100644
--- a/macros/luatex/generic/luaotfload/fontloader-l-table.lua
+++ b/macros/luatex/generic/luaotfload/fontloader-l-table.lua
@@ -287,6 +287,37 @@ local function sortedhash(t,cmp)
return nothing
end
+-- local function iterate(t,i)
+-- local i = i + 1
+-- if i <= t.n then
+-- local k = t[i]
+-- return i, k, t.t[k]
+-- end
+-- end
+--
+-- local function indexedhash(t,cmp)
+-- if t then
+-- local s
+-- if cmp then
+-- -- it would be nice if the sort function would accept a third argument (or nicer, an optional first)
+-- s = sortedhashkeys(t,function(a,b) return cmp(t,a,b) end)
+-- else
+-- s = sortedkeys(t) -- the robust one
+-- end
+-- local m = #s
+-- if m == 1 then
+-- return next, t
+-- elseif m > 0 then
+-- s.n = m
+-- s.t = t
+-- return iterate, s, 0
+-- end
+-- end
+-- return nothing
+-- end
+--
+-- -- for i, k, v in indexedhash(t) do print(k,v,s) end
+
table.sortedhash = sortedhash
table.sortedpairs = sortedhash -- obsolete
diff --git a/macros/luatex/generic/luaotfload/fontloader-l-unicode.lua b/macros/luatex/generic/luaotfload/fontloader-l-unicode.lua
index 13e0a3fa1c..c57aaf33eb 100644
--- a/macros/luatex/generic/luaotfload/fontloader-l-unicode.lua
+++ b/macros/luatex/generic/luaotfload/fontloader-l-unicode.lua
@@ -1081,56 +1081,62 @@ 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))
+if bit32 then
+
+ local rshift = bit32.rshift
+
+ 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
-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)
+ 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
-end
-local l_remap = Cs((p_utf8byte/little+P(1)/"")^0)
-local b_remap = Cs((p_utf8byte/big +P(1)/"")^0)
+ 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)
+ 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
-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)
+ 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
-end
-utf.utf8_to_utf16_be = utf8_to_utf16_be
-utf.utf8_to_utf16_le = utf8_to_utf16_le
+ 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)
+ 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
+
end
local pattern = Cs (
diff --git a/macros/luatex/generic/luaotfload/fontloader-reference.lua b/macros/luatex/generic/luaotfload/fontloader-reference.lua
index 3120f45135..b8a21fc937 100644
--- a/macros/luatex/generic/luaotfload/fontloader-reference.lua
+++ b/macros/luatex/generic/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 : 08/11/19 20:03:46
+-- merge date : 10/29/19 15:00:00
do -- begin closure to overcome local limits and interference
@@ -20,6 +20,9 @@ if LUAVERSION<5.2 and jit then
MINORVERSION=2
LUAVERSION=5.2
end
+if lua and lua.openfile then
+ io.open=lua.openfile
+end
if not lpeg then
lpeg=require("lpeg")
end
@@ -296,7 +299,7 @@ patterns.propername=(uppercase+lowercase+underscore)*(uppercase+lowercase+unders
patterns.somecontent=(anything-newline-space)^1
patterns.beginline=#(1-newline)
patterns.longtostring=Cs(whitespace^0/""*((patterns.quoted+nonwhitespace^1+whitespace^1/""*(endofstring+Cc(" ")))^0))
-function anywhere(pattern)
+local function anywhere(pattern)
return (1-P(pattern))^0*P(pattern)
end
lpeg.anywhere=anywhere
@@ -3433,7 +3436,7 @@ local environment={
stripzero=patterns.stripzero,
stripzeros=patterns.stripzeros,
escapedquotes=string.escapedquotes,
- FORMAT=string.f9,
+ FORMAT=string.f6,
}
local arguments={ "a1" }
setmetatable(arguments,{ __index=function(t,k)
@@ -3641,12 +3644,25 @@ local format_n=function()
n=n+1
return format("((a%s %% 1 == 0) and format('%%i',a%s) or tostring(a%s))",n,n,n)
end
-local format_N=function(f)
- n=n+1
- if not f or f=="" then
- f=".9"
- end
- return format("(((a%s %% 1 == 0) and format('%%i',a%s)) or lpegmatch(stripzero,format('%%%sf',a%s)))",n,n,f,n)
+local format_N if environment.FORMAT then
+ format_N=function(f)
+ n=n+1
+ if not f or f=="" then
+ return format("FORMAT(a%s,'%%.9f')",n)
+ elseif f==".6" then
+ return format("FORMAT(a%s)",n)
+ else
+ return format("FORMAT(a%s,'%%%sf')",n,f)
+ end
+ end
+else
+ format_N=function(f)
+ n=n+1
+ if not f or f=="" then
+ f=".9"
+ end
+ return format("(((a%s %% 1 == 0) and format('%%i',a%s)) or lpegmatch(stripzero,format('%%%sf',a%s)))",n,n,f,n)
+ end
end
local format_a=function(f)
n=n+1
@@ -4865,6 +4881,7 @@ nuts.getchar=direct.getchar
nuts.getcomponents=direct.getcomponents
nuts.getdirection=direct.getdirection
nuts.getdisc=direct.getdisc
+nuts.getreplace=direct.getreplace
nuts.getfield=direct.getfield
nuts.getfont=direct.getfont
nuts.getid=direct.getid
@@ -4881,6 +4898,7 @@ nuts.setchar=direct.setchar
nuts.setcomponents=direct.setcomponents
nuts.setdirection=direct.setdirection
nuts.setdisc=direct.setdisc
+nuts.setreplace=direct.setreplace
nuts.setfield=setfield
nuts.setkern=direct.setkern
nuts.setlink=direct.setlink
@@ -4998,6 +5016,17 @@ do
node=nuts.traverse(dummy),
}
end
+if not nuts.setreplace then
+ local getdisc=nuts.getdisc
+ local setfield=nuts.setfield
+ function nuts.getreplace(n)
+ local _,_,h,_,_,t=getdisc(n,true)
+ return h,t
+ end
+ function nuts.setreplace(n,h)
+ setfield(n,"replace",h)
+ end
+end
end -- closure
@@ -8989,7 +9018,8 @@ function constructors.scale(tfmdata,specification)
local units=parameters.units or 1000
targetproperties.language=properties.language or "dflt"
targetproperties.script=properties.script or "dflt"
- targetproperties.mode=properties.mode or "base"
+ targetproperties.mode=properties.mode or "base"
+ targetproperties.method=properties.method
local askedscaledpoints=scaledpoints
local scaledpoints,delta=constructors.calculatescale(tfmdata,scaledpoints,nil,specification)
local hdelta=delta
@@ -19773,6 +19803,8 @@ function readers.cpal(f,fontdata,specification)
fontdata.colorpalettes=palettes
end
end
+local compress=gzip and gzip.compress
+local compressed=compress and gzip.compressed
function readers.svg(f,fontdata,specification)
local tableoffset=gotodatatable(f,fontdata,"svg",specification.glyphs)
if tableoffset then
@@ -19794,10 +19826,14 @@ function readers.svg(f,fontdata,specification)
for i=1,nofentries do
local entry=entries[i]
setposition(f,entry.offset)
+ local data=readstring(f,entry.length)
+ if compressed and not compressed(data) then
+ data=compress(data)
+ end
entries[i]={
first=entry.first,
last=entry.last,
- data=readstring(f,entry.length)
+ data=data
}
end
fontdata.svgshapes=entries
@@ -21059,6 +21095,9 @@ local function checklookups(fontdata,missing,nofmissing)
end
end
end
+local firstprivate=fonts.privateoffsets and fonts.privateoffsets.textbase or 0xF0000
+local puafirst=0xE000
+local pualast=0xF8FF
local function unifymissing(fontdata)
if not fonts.mappings then
require("font-map")
@@ -21069,18 +21108,19 @@ local function unifymissing(fontdata)
resources.unicodes=unicodes
for unicode,d in next,fontdata.descriptions do
if unicode<privateoffset then
- local name=d.name
- if name then
- unicodes[name]=unicode
+ if unicode>=puafirst and unicode<=pualast then
+ else
+ local name=d.name
+ if name then
+ unicodes[name]=unicode
+ end
end
+ else
end
end
fonts.mappings.addtounicode(fontdata,fontdata.filename,checklookups)
resources.unicodes=nil
end
-local firstprivate=fonts.privateoffsets and fonts.privateoffsets.textbase or 0xF0000
-local puafirst=0xE000
-local pualast=0xF8FF
local function unifyglyphs(fontdata,usenames)
local private=fontdata.private or privateoffset
local glyphs=fontdata.glyphs
@@ -23049,11 +23089,12 @@ local trace_defining=false registertracker("fonts.defining",function(v) trace_d
local report_otf=logs.reporter("fonts","otf loading")
local fonts=fonts
local otf=fonts.handlers.otf
-otf.version=3.109
+otf.version=3.110
otf.cache=containers.define("fonts","otl",otf.version,true)
otf.svgcache=containers.define("fonts","svg",otf.version,true)
otf.pngcache=containers.define("fonts","png",otf.version,true)
otf.pdfcache=containers.define("fonts","pdf",otf.version,true)
+otf.mpscache=containers.define("fonts","mps",otf.version,true)
otf.svgenabled=false
otf.pngenabled=false
local otfreaders=otf.readers
@@ -26076,7 +26117,6 @@ registertracker("otf.actions","otf.substitutions","otf.positions")
registertracker("otf.sample","otf.steps","otf.substitutions","otf.positions","otf.analyzing")
registertracker("otf.sample.silent","otf.steps=silent","otf.substitutions","otf.positions","otf.analyzing")
local nuts=nodes.nuts
-local getfield=nuts.getfield
local getnext=nuts.getnext
local setnext=nuts.setnext
local getprev=nuts.getprev
@@ -26092,6 +26132,7 @@ local getchar=nuts.getchar
local setchar=nuts.setchar
local getdisc=nuts.getdisc
local setdisc=nuts.setdisc
+local getreplace=nuts.getreplace
local setlink=nuts.setlink
local getcomponents=nuts.getcomponents
local setcomponents=nuts.setcomponents
@@ -27670,7 +27711,7 @@ local function chaindisk(head,start,dataset,sequence,rlmode,skiphash,ck)
if keepdisc then
keepdisc=false
lookaheaddisc=current
- local replace=getfield(current,"replace")
+ local replace=getreplace(current)
if not replace then
sweepoverflow=true
sweepnode=current
@@ -27742,7 +27783,7 @@ local function chaindisk(head,start,dataset,sequence,rlmode,skiphash,ck)
if notmatchpre[current]~=notmatchreplace[current] then
lookaheaddisc=current
end
- local replace=getfield(current,"replace")
+ local replace=getreplace(current)
while replace and i<s do
if getid(replace)==glyph_code then
i=i+1
@@ -27786,7 +27827,7 @@ local function chaindisk(head,start,dataset,sequence,rlmode,skiphash,ck)
if notmatchpost[current]~=notmatchreplace[current] then
backtrackdisc=current
end
- local replace=getfield(current,"replace")
+ local replace=getreplace(current)
while replace and i>1 do
if getid(replace)==glyph_code then
i=i-1
@@ -28750,7 +28791,7 @@ local function t_run_single(start,stop,font,attr,lookupcache)
end
while getid(s)==disc_code do
ss=getnext(s)
- s=getfield(s,"replace")
+ s=getreplace(s)
if not s then
s=ss
ss=nil
@@ -28777,7 +28818,7 @@ local function t_run_single(start,stop,font,attr,lookupcache)
end
while getid(s)==disc_code do
ss=getnext(s)
- s=getfield(s,"replace")
+ s=getreplace(s)
if not s then
s=ss
ss=nil
@@ -28904,7 +28945,7 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps)
end
while getid(s)==disc_code do
ss=getnext(s)
- s=getfield(s,"replace")
+ s=getreplace(s)
if not s then
s=ss
ss=nil
@@ -28931,7 +28972,7 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps)
end
while getid(s)==disc_code do
ss=getnext(s)
- s=getfield(s,"replace")
+ s=getreplace(s)
if not s then
s=ss
ss=nil
@@ -30708,7 +30749,7 @@ local function reorder_one(head,start,stop,font,attr,nbspaces)
local cp=getprev(current)
local cnsn=getnext(cns)
setlink(cp,n)
- setlink(cns,current)
+ setlink(cns,current)
setlink(c,cnsn)
if c==stop then
stop=cp
@@ -32071,9 +32112,13 @@ if not modules then modules={} end modules ['font-ocl']={
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files"
}
+if CONTEXTLMTXMODE and CONTEXTLMTXMODE>0 then
+ return
+end
local tostring,tonumber,next=tostring,tonumber,next
local round,max=math.round,math.round
-local sortedkeys,sortedhash=table.sortedkeys,table.sortedhash
+local gsub,find=string.gsub,string.find
+local sortedkeys,sortedhash,concat=table.sortedkeys,table.sortedhash,table.concat
local setmetatableindex=table.setmetatableindex
local formatters=string.formatters
local tounicode=fonts.mappings.tounicode
@@ -32083,6 +32128,7 @@ local rightcommand=helpers.commands.right
local leftcommand=helpers.commands.left
local downcommand=helpers.commands.down
local otf=fonts.handlers.otf
+local otfregister=otf.features.register
local f_color=formatters["%.3f %.3f %.3f rg"]
local f_gray=formatters["%.3f g"]
if context then
@@ -32139,7 +32185,7 @@ end
local start={ "pdf","mode","font" }
local push={ "pdf","page","q" }
local pop={ "pdf","page","Q" }
-local function initialize(tfmdata,kind,value)
+local function initializeoverlay(tfmdata,kind,value)
if value then
local resources=tfmdata.resources
local palettes=resources.colorpalettes
@@ -32181,52 +32227,39 @@ local function initialize(tfmdata,kind,value)
local s=#colorlist
local goback=w~=0 and leftcommand[w] or nil
local t={
- start,
- not u and actualb or { "pdf","page",(getactualtext(tounicode(u))) }
+ not u and actualb or { "pdf","page",(getactualtext(tounicode(u))) },
+ push,
}
local n=2
local l=nil
- local f=false
for i=1,s do
local entry=colorlist[i]
local v=colorvalues[entry.class] or default
if v and l~=v then
- if f then
- n=n+1 t[n]=pop
- end
- n=n+1 t[n]=push
- 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
n=n+1 t[n]=goback
end
end
- if f then
- n=n+1 t[n]=pop
- end
+ n=n+1 t[n]=pop
n=n+1 t[n]=actuale
character.commands=t
end
end
end
+ return true
end
end
end
-fonts.handlers.otf.features.register {
+otfregister {
name="colr",
description="color glyphs",
manipulators={
- base=initialize,
- node=initialize,
+ base=initializeoverlay,
+ node=initializeoverlay,
}
}
do
@@ -32277,14 +32310,20 @@ local function pdftovirtual(tfmdata,pdfshapes,kind)
local data=nil
local dx=nil
local dy=nil
+ local scale=1
if typ=="table" then
data=pdf.data
- dx=pdf.dx or 0
- dy=pdf.dy or 0
+ dx=pdf.x or pdf.dx or 0
+ dy=pdf.y or pdf.dy or 0
+ scale=pdf.scale or 1
elseif typ=="string" then
data=pdf
dx=0
dy=0
+ elseif typ=="number" then
+ data=pdf
+ dx=0
+ dy=0
end
if data then
local bt=unicode and getactualtext(unicode)
@@ -32293,9 +32332,9 @@ local function pdftovirtual(tfmdata,pdfshapes,kind)
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),
+ downcommand [dp+dy*hfactor],
+ rightcommand[ dx*hfactor],
+ vfimage(scale*wd,ht,dp,data,pdfshapes.filename or ""),
actuale,
}
character[kind]=true
@@ -32329,24 +32368,27 @@ do
name="otfsvg",
program="inkscape",
method="pipeto",
- template="--shell > temp-otf-svg-shape.log",
+ template="--export-area-drawing --shell > temp-otf-svg-shape.log",
reporter=report_svg,
}
if not runner then
runner=function()
- return io.open("inkscape --shell > temp-otf-svg-shape.log","w")
+ return io.popen("inkscape --export-area-drawing --shell > temp-otf-svg-shape.log","w")
end
end
- function otfsvg.topdf(svgshapes)
+ function otfsvg.topdf(svgshapes,tfmdata)
local pdfshapes={}
local inkscape=runner()
if inkscape then
+ local indices=fonts.getindices(tfmdata)
+ local descriptions=tfmdata.descriptions
local nofshapes=#svgshapes
local f_svgfile=formatters["temp-otf-svg-shape-%i.svg"]
local f_pdffile=formatters["temp-otf-svg-shape-%i.pdf"]
local f_convert=formatters["%s --export-pdf=%s\n"]
local filterglyph=otfsvg.filterglyph
local nofdone=0
+ local processed={}
report_svg("processing %i svg containers",nofshapes)
statistics.starttiming()
for i=1,nofshapes do
@@ -32358,24 +32400,51 @@ do
local pdffile=f_pdffile(index)
savedata(svgfile,data)
inkscape:write(f_convert(svgfile,pdffile))
- pdfshapes[index]=true
+ processed[index]=true
nofdone=nofdone+1
- if nofdone%100==0 then
- report_svg("%i shapes processed",nofdone)
+ if nofdone%25==0 then
+ report_svg("%i shapes submitted",nofdone)
end
end
end
end
+ if nofdone%25~=0 then
+ report_svg("%i shapes submitted",nofdone)
+ end
+ report_svg("processing can be going on for a while")
inkscape:write("quit\n")
inkscape:close()
report_svg("processing %i pdf results",nofshapes)
- for index in next,pdfshapes do
+ for index in next,processed do
local svgfile=f_svgfile(index)
local pdffile=f_pdffile(index)
- pdfshapes[index]=loaddata(pdffile)
+ local pdfdata=loaddata(pdffile)
+ if pdfdata and pdfdata~="" then
+ pdfshapes[index]={
+ data=pdfdata,
+ }
+ end
remove(svgfile)
remove(pdffile)
end
+ local characters=tfmdata.characters
+ for k,v in next,characters do
+ local d=descriptions[k]
+ local i=d.index
+ if i then
+ local p=pdfshapes[i]
+ if p then
+ local w=d.width
+ local l=d.boundingbox[1]
+ local r=d.boundingbox[3]
+ p.scale=(r-l)/w
+ p.x=l
+ end
+ end
+ end
+ if not next(pdfshapes) then
+ report_svg("there are no converted shapes, fix your setup")
+ end
statistics.stoptiming()
if statistics.elapsedseconds then
report_svg("svg conversion time %s",statistics.elapsedseconds() or "-")
@@ -32394,19 +32463,20 @@ local function initializesvg(tfmdata,kind,value)
end
local pdffile=containers.read(otf.pdfcache,hash)
local pdfshapes=pdffile and pdffile.pdfshapes
- if not pdfshapes or pdffile.timestamp~=timestamp then
+ if not pdfshapes or pdffile.timestamp~=timestamp or not next(pdfshapes) then
local svgfile=containers.read(otf.svgcache,hash)
local svgshapes=svgfile and svgfile.svgshapes
- pdfshapes=svgshapes and otfsvg.topdf(svgshapes) or {}
+ pdfshapes=svgshapes and otfsvg.topdf(svgshapes,tfmdata,otf.pdfcache.writable,hash) or {}
containers.write(otf.pdfcache,hash,{
pdfshapes=pdfshapes,
timestamp=timestamp,
})
end
pdftovirtual(tfmdata,pdfshapes,"svg")
+ return true
end
end
-fonts.handlers.otf.features.register {
+otfregister {
name="svg",
description="svg glyphs",
manipulators={
@@ -32489,9 +32559,10 @@ local function initializepng(tfmdata,kind,value)
})
end
pdftovirtual(tfmdata,pdfshapes,"png")
+ return true
end
end
-fonts.handlers.otf.features.register {
+otfregister {
name="sbix",
description="sbix glyphs",
manipulators={
@@ -32499,7 +32570,7 @@ fonts.handlers.otf.features.register {
node=initializepng,
}
}
-fonts.handlers.otf.features.register {
+otfregister {
name="cblc",
description="cblc glyphs",
manipulators={
@@ -32507,6 +32578,11 @@ fonts.handlers.otf.features.register {
node=initializepng,
}
}
+if context then
+
+--removed
+
+end
end -- closure
@@ -32530,9 +32606,10 @@ local fonts=fonts
local otf=fonts.handlers.otf
local registerotffeature=otf.features.register
local setmetatableindex=table.setmetatableindex
-local checkmerge=fonts.helpers.checkmerge
-local checkflags=fonts.helpers.checkflags
-local checksteps=fonts.helpers.checksteps
+local fonthelpers=fonts.helpers
+local checkmerge=fonthelpers.checkmerge
+local checkflags=fonthelpers.checkflags
+local checksteps=fonthelpers.checksteps
local normalized={
substitution="substitution",
single="substitution",
@@ -32654,6 +32731,7 @@ local function addfeature(data,feature,specifications)
local done=0
local skip=0
local aglunicodes=false
+ local privateslot=fonthelpers.privateslot
local specifications=validspecification(specifications,feature)
if not specifications then
return
@@ -32676,6 +32754,12 @@ local function addfeature(data,feature,specifications)
return u
end
end
+ if privateslot then
+ u=privateslot(code)
+ if u then
+ return u
+ end
+ end
local u=lpegmatch(p,code)
if u then
return u
@@ -32705,7 +32789,7 @@ local function addfeature(data,feature,specifications)
replacement=replacement[1]
end
replacement=tounicode(replacement)
- if replacement and descriptions[replacement] then
+ if replacement and (nocheck or descriptions[replacement]) then
cover(coverage,unicode,replacement)
done=done+1
else
@@ -33075,7 +33159,6 @@ local function addfeature(data,feature,specifications)
local featuretype=normalized[specification.type or "substitution"] or "substitution"
local featureflags=specification.flags or noflags
local nocheck=specification.nocheck
- local futuresteps=specification.futuresteps
local featureorder=specification.order or { feature }
local featurechain=(featuretype=="chainsubstitution" or featuretype=="chainposition") and 1 or 0
local nofsteps=0
diff --git a/macros/luatex/generic/luaotfload/fontloader-util-str.lua b/macros/luatex/generic/luaotfload/fontloader-util-str.lua
index ad22302df0..432b39ec5a 100644
--- a/macros/luatex/generic/luaotfload/fontloader-util-str.lua
+++ b/macros/luatex/generic/luaotfload/fontloader-util-str.lua
@@ -633,7 +633,7 @@ local environment = {
stripzeros = patterns.stripzeros,
escapedquotes = string.escapedquotes,
- FORMAT = string.f9,
+ FORMAT = string.f6,
}
-- -- --
@@ -908,7 +908,7 @@ local format_L = function()
return format("(a%s and 'TRUE' or 'FALSE')",n)
end
-local format_n = function() -- strips leading and trailing zeros and removes .0
+local format_n = function() -- strips leading and trailing zeros and removes .0, beware: can produce e notation
n = n + 1
return format("((a%s %% 1 == 0) and format('%%i',a%s) or tostring(a%s))",n,n,n)
end
@@ -938,13 +938,30 @@ end
-- end
-- end
-local format_N = function(f) -- strips leading and trailing zeros
- n = n + 1
- -- stripzero (singular) as we only have a number
- if not f or f == "" then
- f = ".9"
- end -- always a leading number !
- return format("(((a%s %% 1 == 0) and format('%%i',a%s)) or lpegmatch(stripzero,format('%%%sf',a%s)))",n,n,f,n)
+local format_N if environment.FORMAT then
+
+ format_N = function(f)
+ n = n + 1
+ if not f or f == "" then
+ return format("FORMAT(a%s,'%%.9f')",n)
+ elseif f == ".6" then
+ return format("FORMAT(a%s)",n)
+ else
+ return format("FORMAT(a%s,'%%%sf')",n,f)
+ end
+ end
+
+else
+
+ format_N = function(f) -- strips leading and trailing zeros
+ n = n + 1
+ -- stripzero (singular) as we only have a number
+ if not f or f == "" then
+ f = ".9"
+ end -- always a leading number !
+ return format("(((a%s %% 1 == 0) and format('%%i',a%s)) or lpegmatch(stripzero,format('%%%sf',a%s)))",n,n,f,n)
+ end
+
end
local format_a = function(f)
diff --git a/macros/luatex/generic/luaotfload/luaotfload-auxiliary.lua b/macros/luatex/generic/luaotfload/luaotfload-auxiliary.lua
index d3b5c73418..9538a15bb0 100644
--- a/macros/luatex/generic/luaotfload/luaotfload-auxiliary.lua
+++ b/macros/luatex/generic/luaotfload/luaotfload-auxiliary.lua
@@ -6,8 +6,8 @@
local ProvidesLuaModule = {
name = "luaotfload-auxiliary",
- version = "3.00", --TAGVERSION
- date = "2019-09-13", --TAGDATE
+ version = "3.1", --TAGVERSION
+ date = "2019-11-04", --TAGDATE
description = "luaotfload submodule / auxiliary functions",
license = "GPL v2.0"
}
@@ -39,6 +39,13 @@ local stringbyte = string.byte
local stringfind = string.find
local tablecopy = table.copy
+local harf = luaotfload.harfbuzz
+local GSUBtag, GPOStag
+if harf then
+ GSUBtag = harf.Tag.new("GSUB")
+ GPOStag = harf.Tag.new("GPOS")
+end
+
local aux = { }
local luaotfload_callbacks = { }
@@ -101,6 +108,14 @@ luaotfload_callbacks [#luaotfload_callbacks + 1] = {
"patch_font", set_sscale_dimens, "set_sscale_dimens",
}
+-- Starting with LuaTeX 1.11.2, this is a more reliable way of selecting the
+-- right font than relying on psnames
+luaotfload_callbacks [#luaotfload_callbacks + 1] = {
+ "patch_font", function(fontdata)
+ fontdata.subfont = fontdata.specification.sub or 1
+ end, "set_font_index",
+}
+
local default_units = 1000
--- fontobj -> int
@@ -349,15 +364,27 @@ function aux.slot_of_name(font_id, glyphname, unsafe)
local tfmdata = identifiers [font_id]
if not tfmdata then return raw_slot_of_name (font_id, glyphname) end
- local resources = tfmdata.resources if not resources then return false end
- local unicodes = resources.unicodes if not unicodes then return false end
-
- local unicode = unicodes [glyphname]
- if unicode then
- if type (unicode) == "number" then
- return unicode
- else
- return unicode [1] --- for multiple components
+ local hbdata = tfmdata.hb
+ if hbdata then
+ local hbshared = hbdata.shared
+ local nominals = hbshared.nominals
+ local hbfont = hbshared.font
+
+ local gid = hbfont:get_glyph_from_name(glyphname)
+ if gid ~= nil then
+ return nominals[gid] or gid + hbshared.gid_offset
+ end
+ else
+ local resources = tfmdata.resources if not resources then return false end
+ local unicodes = resources.unicodes if not unicodes then return false end
+
+ local unicode = unicodes [glyphname]
+ if unicode then
+ if type (unicode) == "number" then
+ return unicode
+ else
+ return unicode [1] --- for multiple components
+ end
end
end
return false
@@ -412,6 +439,11 @@ local function get_features(tfmdata)
return features
end
+local function get_hbface(tfmdata)
+ if not tfmdata.hb then return end
+ return tfmdata.hbshared.face
+end
+
--[[doc--
This function, modeled after “check_script()” from fontspec, returns
true if in the given font, the script “asked_script” is accounted for in at
@@ -429,9 +461,22 @@ function aux.provides_script(font_id, asked_script)
return false
end
asked_script = stringlower(asked_script)
- if font_id and font_id > 0 then
- local tfmdata = identifiers[font_id]
- if not tfmdata then return false end
+ local tfmdata = identifiers[font_id]
+ if not tfmdata then
+ logreport ("log", 0, "aux", "no font with id %d", font_id)
+ return false
+ end
+ local hbface = get_hbface(tfmdata)
+ if hbface then
+ local script = harf.Tag.new(asked_script == "dflt" and "DFLT"
+ or asked_script)
+ for _, tag in next, { GSUBtag, GPOStag } do
+ if hbface:ot_layout_find_script(tag, script) then
+ return true
+ end
+ end
+ return false
+ else
local features = get_features (tfmdata)
if features == false then
logreport ("log", 1, "aux", "font no %d lacks a features table", font_id)
@@ -452,7 +497,6 @@ function aux.provides_script(font_id, asked_script)
"font no %d (%s) defines no feature for script %s",
font_id, fontname, asked_script)
end
- logreport ("log", 0, "aux", "no font with id %d", font_id)
return false
end
@@ -477,8 +521,30 @@ function aux.provides_language(font_id, asked_script, asked_language)
return false
end
asked_script = stringlower(asked_script)
- asked_language = stringlower(asked_language)
- if font_id and font_id > 0 then
+ local tfmdata = identifiers[font_id]
+ if not tfmdata then
+ logreport ("log", 0, "aux", "no font with id %d", font_id)
+ return false
+ end
+ local hbface = get_hbface(tfmdata)
+ if hbface then
+ asked_language = stringupper(asked_language)
+ if asked_language == "DFLT" then
+ return aux.provides_script(font_id, asked_script)
+ end
+ local script = harf.Tag.new(asked_script == "dflt" and "DFLT"
+ or asked_script)
+ local language = harf.Tag.new(asked_language == "DFLT" and "dflt"
+ or asked_language)
+ for _, tag in next, { GSUBtag, GPOStag } do
+ local _, script_idx = hbface:ot_layout_find_script(tag, script)
+ if hbface:ot_layout_find_language(tag, script_idx, language) then
+ return true
+ end
+ end
+ return false
+ else
+ asked_language = stringlower(asked_language)
local tfmdata = identifiers[font_id]
if not tfmdata then return false end
local features = get_features (tfmdata)
@@ -504,9 +570,8 @@ function aux.provides_language(font_id, asked_script, asked_language)
"font no %d (%s) defines no feature "
.. "for script %s with language %s",
font_id, fontname, asked_script, asked_language)
+ return false
end
- logreport ("log", 0, "aux", "no font with id %d", font_id)
- return false
end
--[[doc--
@@ -558,12 +623,32 @@ function aux.provides_feature(font_id, asked_script,
return false
end
asked_script = stringlower(asked_script)
- asked_language = stringlower(asked_language)
asked_feature = lpegmatch(strip_garbage, asked_feature)
- if font_id > 0 then
- local tfmdata = identifiers[font_id]
- if not tfmdata then return false end
+ local tfmdata = identifiers[font_id]
+ if not tfmdata then
+ logreport ("log", 0, "aux", "no font with id %d", font_id)
+ return false
+ end
+ local hbface = get_hbface(tfmdata)
+ if hbface then
+ asked_language = stringupper(asked_language)
+ local script = harf.Tag.new(asked_script == "dflt" and "DFLT"
+ or asked_script)
+ local language = harf.Tag.new(asked_language == "DFLT" and "dflt"
+ or asked_language)
+ local feature = harf.Tag.new(feature)
+
+ for _, tag in next, { GSUBtag, GPOStag } do
+ local _, script_idx = hbface:ot_layout_find_script(tag, script)
+ local _, language_idx = hbface:ot_layout_find_language(tag, script_idx, language)
+ if hbface:ot_layout_find_feature(tag, script_idx, language_idx, feature) then
+ return true
+ end
+ end
+ return false
+ else
+ asked_language = stringlower(asked_language)
local features = get_features (tfmdata)
if features == false then
logreport ("log", 1, "aux", "font no %d lacks a features table", font_id)
@@ -588,8 +673,6 @@ function aux.provides_feature(font_id, asked_script,
"font no %d (%s) does not define feature %s for script %s with language %s",
font_id, fontname, asked_feature, asked_script, asked_language)
end
- logreport ("log", 0, "aux", "no font with id %d", font_id)
- return false
end
-----------------------------------------------------------------------
diff --git a/macros/luatex/generic/luaotfload/luaotfload-colors.lua b/macros/luatex/generic/luaotfload/luaotfload-colors.lua
index fdae0c4450..ae78130b4f 100644
--- a/macros/luatex/generic/luaotfload/luaotfload-colors.lua
+++ b/macros/luatex/generic/luaotfload/luaotfload-colors.lua
@@ -5,8 +5,8 @@
local ProvidesLuaModule = {
name = "luaotfload-colors",
- version = "3.00", --TAGVERSION
- date = "2019-09-13", --TAGDATE
+ version = "3.1", --TAGVERSION
+ date = "2019-11-04", --TAGDATE
description = "luaotfload submodule / color",
license = "GPL v2.0",
author = "Khaled Hosny, Elie Roux, Philipp Gesang, Dohyun Kim, David Carlisle",
@@ -405,6 +405,7 @@ return function ()
initializers = {
base = setcolor,
node = setcolor,
+ plug = setcolor,
}
}
return true
diff --git a/macros/luatex/generic/luaotfload/luaotfload-conf.pdf b/macros/luatex/generic/luaotfload/luaotfload-conf.pdf
index edea84a1d7..031fb0987a 100644
--- a/macros/luatex/generic/luaotfload/luaotfload-conf.pdf
+++ b/macros/luatex/generic/luaotfload/luaotfload-conf.pdf
Binary files differ
diff --git a/macros/luatex/generic/luaotfload/luaotfload-configuration.lua b/macros/luatex/generic/luaotfload/luaotfload-configuration.lua
index fc30cc8343..e9b818df2d 100644
--- a/macros/luatex/generic/luaotfload/luaotfload-configuration.lua
+++ b/macros/luatex/generic/luaotfload/luaotfload-configuration.lua
@@ -7,8 +7,8 @@
local ProvidesLuaModule = {
name = "luaotfload-configuration",
- version = "3.00", --TAGVERSION
- date = "2019-09-13", --TAGDATE
+ version = "3.1", --TAGVERSION
+ date = "2019-11-04", --TAGDATE
description = "luaotfload submodule / config file reader",
license = "GPL v2.0"
}
@@ -62,7 +62,7 @@ local filejoin = file.join
local filereplacesuffix = file.replacesuffix
local logreport = print -- overloaded later
-local getwritablepath = caches.getwritablepath
+local getwritablepath = luaotfload.fontloader.caches.getwritablepath
local config_parser -- set later during init
@@ -382,7 +382,7 @@ local set_default_features = function ()
global = { },
defaults = { },
}
- current_features = luaotfload.features
+ local current_features = luaotfload.features
for var, val in next, default_features do
if var == "global" then
current_features.global = val
diff --git a/macros/luatex/generic/luaotfload/luaotfload-database.lua b/macros/luatex/generic/luaotfload/luaotfload-database.lua
index 0610618905..10a0853c89 100644
--- a/macros/luatex/generic/luaotfload/luaotfload-database.lua
+++ b/macros/luatex/generic/luaotfload/luaotfload-database.lua
@@ -5,8 +5,8 @@
do -- block to avoid to many local variables error
local ProvidesLuaModule = {
name = "luaotfload-database",
- version = "3.00", --TAGVERSION
- date = "2019-09-13", --TAGDATE
+ version = "3.1", --TAGVERSION
+ date = "2019-11-04", --TAGDATE
description = "luaotfload submodule / database",
license = "GPL v2.0",
author = "Khaled Hosny, Elie Roux, Philipp Gesang, Marcel Krüger",
@@ -148,7 +148,6 @@ local gzipload = gzip.load
local gzipsave = gzip.save
local iolines = io.lines
local ioopen = io.open
-local iopopen = io.popen
local kpseexpand_path = kpse.expand_path
local kpsefind_file = kpse.find_file
local kpselookup = kpse.lookup
@@ -168,13 +167,14 @@ local stringgmatch = string.gmatch
local stringgsub = string.gsub
local stringlower = string.lower
local stringsub = string.sub
-local stringupper = string.upper
local tableconcat = table.concat
local tablesort = table.sort
local utf8len = utf8.len
local utf8offset = utf8.offset
--- these come from Lualibs/Context
+local context_environment = luaotfload.fontloader
+local caches = context_environment.caches
local filebasename = file.basename
local filecollapsepath = file.collapsepath or file.collapse_path
local filedirname = file.dirname
@@ -198,9 +198,9 @@ local tablecontains = table.contains
local tablecopy = table.copy
local tablefastcopy = table.fastcopy
local tabletofile = table.tofile
-local tabletohash = table.tohash
local tableserialize = table.serialize
local names = fonts and fonts.names or { }
+local resolversfindfile = context_environment.resolvers.findfile
--- some of our own
local unicode = require'luaotfload-unicode'
@@ -736,7 +736,7 @@ lookup_font_file = function (filename)
if not found then
local type = file.suffix(filename)
if type ~= "" then
- found = resolvers.findfile(filename, type)
+ found = resolversfindfile(filename, type)
end
end
@@ -746,7 +746,7 @@ lookup_font_file = function (filename)
for i=1, #type1_metrics do
local format = type1_metrics[i]
- if resolvers.findfile(filename, format) then
+ if resolversfindfile(filename, format) then
return file.addsuffix(filename, format), format, true
end
end
@@ -785,7 +785,7 @@ local get_font_file = function (index)
end
local basename = entry.basename
if entry.location == "texmf" then
- local fullname = resolvers.findfile(basename, entry.format)
+ local fullname = resolversfindfile(basename, entry.format)
if fullname then
return true, fullname, entry.subfont
end
@@ -809,7 +809,7 @@ local verify_font_file = function (basename)
if path and lfsisfile(path) then
return true
end
- if resolvers.findfile(basename) then
+ if resolversfindfile(basename) then
return true
end
return false
@@ -2125,9 +2125,8 @@ do
return
end
- if splitcomma == nil then
- splitcomma = luaotfload.parsers and luaotfload.parsers.splitcomma
- end
+ local splitcomma = luaotfload.parsers and luaotfload.parsers.splitcomma
+
if stringsub (formats, 1, 1) == "+" then -- add
formats = lpegmatch (splitcomma, stringsub (formats, 2))
if formats then
@@ -2281,7 +2280,14 @@ local truncate_string = function (str, restrict)
local tw = config.luaotfload.misc.termwidth
local wd = tw - restrict
local len = utf8len (str)
- if wd - len < 0 then
+ if not len then
+ -- str is not valid UTF-8... We will assume a 8-bit
+ -- encoding and forward it verbatim to the output.
+ len = #str
+ if wd - len < 0 then
+ str = ".." .. stringsub(str, len - wd + 2)
+ end
+ elseif wd - len < 0 then
--- combined length exceeds terminal,
str = ".." .. stringsub(str, utf8offset(str, - wd + 2))
end
@@ -3098,6 +3104,39 @@ end
--[[doc--
+ Get the subfont index corresponding to a given psname in a
+ font collection
+
+--doc]]--
+
+local function lookup_subfont_index(filepath, psname)
+ assert(name_index)
+ -- if not name_index then name_index = load_names () end
+ local filestatus = name_index.status[filepath]
+ local mappings = name_index.mappings
+ if filestatus then
+ for subfont, idx in next, filestatus.index do
+ if mappings[idx].psname == psname then
+ return subfont or 1
+ end
+ end
+ end
+
+ -- If that didn't work, we do a manual search
+ psname = sanitize_fontname(psname)
+ local err, info = read_font_file (filepath)
+ if #info == 0 then return 1 end
+ for i = 1, #info do
+ for _, names in next, info[i].platformnames do
+ if psname == sanitize_fontname(names.postscriptname) then
+ return i
+ end
+ end
+ end
+end
+
+--[[doc--
+
collect_font_filenames -- Scan the three search path categories for
font files. This constitutes the first pass of the update mode.
@@ -3707,8 +3746,6 @@ end
--- PHG: we need to investigate these, maybe they’re useful as early
--- hooks
-local ignoredfile = function () return false end
-
local reportmissingbase = function ()
logreport ("info", 0, "db", --> bug‽
"Font name database not found but expected by fontloader.")
@@ -3737,7 +3774,7 @@ local resolve = function (name, subfont)
end
local api = {
- ignoredfile = ignoredfile,
+ ignoredfile = function() return false end,
reportmissingbase = reportmissingbase,
reportmissingname = reportmissingname,
getfilename = getfilename,
@@ -3770,6 +3807,7 @@ local export = {
count_font_files = count_font_files,
nth_font_filename = nth_font_filename,
font_slice = font_slice,
+ lookup_subfont_index = lookup_subfont_index,
--- font cache
purge_cache = purge_cache,
erase_cache = erase_cache,
diff --git a/macros/luatex/generic/luaotfload/luaotfload-diagnostics.lua b/macros/luatex/generic/luaotfload/luaotfload-diagnostics.lua
index b38c1add0d..1dc24ba6ee 100644
--- a/macros/luatex/generic/luaotfload/luaotfload-diagnostics.lua
+++ b/macros/luatex/generic/luaotfload/luaotfload-diagnostics.lua
@@ -7,8 +7,8 @@
local ProvidesLuaModule = {
name = "luaotfload-diagnostics",
- version = "3.00", --TAGVERSION
- date = "2019-09-13", --TAGDATE
+ version = "3.1", --TAGVERSION
+ date = "2019-11-04", --TAGDATE
description = "luaotfload-tool submodule / diagnostics",
license = "GPL v2.0"
}
diff --git a/macros/luatex/generic/luaotfload/luaotfload-embolden.lua b/macros/luatex/generic/luaotfload/luaotfload-embolden.lua
index bd2237f086..8d51249976 100644
--- a/macros/luatex/generic/luaotfload/luaotfload-embolden.lua
+++ b/macros/luatex/generic/luaotfload/luaotfload-embolden.lua
@@ -5,8 +5,8 @@
local ProvidesLuaModule = {
name = "luaotfload-embolden",
- version = "3.00", --TAGVERSION
- date = "2019-09-13", --TAGDATE
+ version = "3.1", --TAGVERSION
+ date = "2019-11-04", --TAGDATE
description = "luaotfload submodule / color",
license = "GPL v2.0",
author = "Marcel Krüger"
diff --git a/macros/luatex/generic/luaotfload/luaotfload-features.lua b/macros/luatex/generic/luaotfload/luaotfload-features.lua
index 3901d940dd..bf56c4e3d1 100644
--- a/macros/luatex/generic/luaotfload/luaotfload-features.lua
+++ b/macros/luatex/generic/luaotfload/luaotfload-features.lua
@@ -5,8 +5,8 @@
local ProvidesLuaModule = {
name = "luaotfload-features",
- version = "3.00", --TAGVERSION
- date = "2019-09-13", --TAGDATE
+ version = "3.1", --TAGVERSION
+ date = "2019-11-04", --TAGDATE
description = "luaotfload submodule / features",
license = "GPL v2.0",
author = "Hans Hagen, Khaled Hosny, Elie Roux, Philipp Gesang, Marcel Krüger",
@@ -26,6 +26,7 @@ local lpeg = require "lpeg"
local lpegmatch = lpeg.match
local P = lpeg.P
local R = lpeg.R
+local S = lpeg.S
local C = lpeg.C
local table = table
@@ -338,10 +339,9 @@ end
local extract_subfont
do
local eof = P(-1)
- local digit = R"09"
--- Theoretically a valid subfont address can be up to ten
- --- digits long.
- local sub_expr = P"(" * C(digit^1) * P")" * eof
+ --- digits long. Additionally we allow names
+ local sub_expr = P"(" * C((1 - S"()")^1) * P")" * eof
local full_path = C(P(1 - sub_expr)^1)
extract_subfont = full_path * sub_expr
end
@@ -371,7 +371,7 @@ local handle_request = function (specification)
local fullpath, sub = lpegmatch(extract_subfont,
specification.specification)
if fullpath and sub then
- specification.sub = tonumber(sub)
+ specification.sub = tonumber(sub) or sub
specification.name = fullpath
else
specification.name = specification.specification
@@ -428,12 +428,7 @@ local handle_request = function (specification)
--- investigated it any further (luatex-fonts-ext), so it will
--- just stay here.
features.normal = normalize (request.features)
- local subfont = tonumber (request.sub)
- if subfont and subfont >= 0 then
- specification.sub = subfont + 1
- else
- specification.sub = false
- end
+ specification.sub = request.sub or specification.sub or false
if request.features and request.features.mode
and fonts.readers[request.features.mode] then
@@ -572,8 +567,8 @@ local autofeatures = {
local add_auto_features = function ()
local nfeats = #autofeatures
- logreport ("both", 5, "features",
- "auto-installing %d feature definitions", nfeats)
+ report ("both", 5, "features",
+ "auto-installing %d feature definitions", nfeats)
for i = 1, nfeats do
local name, spec, desc = unpack (autofeatures [i])
spec.description = desc
@@ -582,12 +577,10 @@ local add_auto_features = function ()
end
return function ()
- logreport = luaotfload.log.report
-
if not fonts and fonts.handlers then
- logreport ("log", 0, "features",
- "OTF mechanisms missing -- did you forget to \z
- load a font loader?")
+ report ("log", 0, "features",
+ "OTF mechanisms missing -- did you forget to \z
+ load a font loader?")
return false
end
add_auto_features ()
diff --git a/macros/luatex/generic/luaotfload/luaotfload-filelist.lua b/macros/luatex/generic/luaotfload/luaotfload-filelist.lua
index ade50b4316..24868eb315 100644
--- a/macros/luatex/generic/luaotfload/luaotfload-filelist.lua
+++ b/macros/luatex/generic/luaotfload/luaotfload-filelist.lua
@@ -6,8 +6,8 @@
local ProvidesLuaModule = {
name = "luaotfload-filelist",
- version = "3.00", --TAGVERSION
- date = "2019-09-13", --TAGDATE
+ version = "3.1", --TAGVERSION
+ date = "2019-11-04", --TAGDATE
description = "luaotfload submodule / filelist",
license = "GPL v2.0"
}
@@ -248,11 +248,14 @@ luaotfload.filelist.data =
{ name = "letterspace" ,kind = kind_library, ext =".lua", gitdir=gitdirsrc, texdir=texdirtex, gitpref = "luaotfload-" },
{ name = "embolden" ,kind = kind_library, ext =".lua", gitdir=gitdirsrc, texdir=texdirtex, gitpref = "luaotfload-" },
{ name = "notdef" ,kind = kind_library, ext =".lua", gitdir=gitdirsrc, texdir=texdirtex, gitpref = "luaotfload-" },
+ { name = "harf-define" ,kind = kind_library, ext =".lua", gitdir=gitdirsrc, texdir=texdirtex, gitpref = "luaotfload-" },
+ { name = "harf-plug" ,kind = kind_library, ext =".lua", gitdir=gitdirsrc, texdir=texdirtex, gitpref = "luaotfload-" },
{ name = "loaders" ,kind = kind_library, ext =".lua", gitdir=gitdirsrc, texdir=texdirtex, gitpref = "luaotfload-" },
{ name = "multiscript" ,kind = kind_library, ext =".lua", gitdir=gitdirsrc, texdir=texdirtex, gitpref = "luaotfload-" },
{ name = "parsers" ,kind = kind_library, ext =".lua", gitdir=gitdirsrc, texdir=texdirtex, gitpref = "luaotfload-" },
{ name = "resolvers" ,kind = kind_library, ext =".lua", gitdir=gitdirsrc, texdir=texdirtex, gitpref = "luaotfload-" },
{ name = "unicode" ,kind = kind_library, ext =".lua", gitdir=gitdirsrc, texdir=texdirtex, gitpref = "luaotfload-" },
+ { name = "tounicode" ,kind = kind_library, ext =".lua", gitdir=gitdirsrc, texdir=texdirtex, gitpref = "luaotfload-" },
{ name = "characters" ,kind = kind_generated, ext =".lua", gitdir=gitdirgen, texdir=texdirtex, gitpref = "luaotfload-", script="mkcharacter" },
{ name = "glyphlist" ,kind = kind_generated, ext =".lua", gitdir=gitdirgen, texdir=texdirtex, gitpref = "luaotfload-", script="mkglyphlist" },
diff --git a/macros/luatex/generic/luaotfload/luaotfload-glyphlist.lua b/macros/luatex/generic/luaotfload/luaotfload-glyphlist.lua
index 1ba46ab0d7..fe655149ad 100644
--- a/macros/luatex/generic/luaotfload/luaotfload-glyphlist.lua
+++ b/macros/luatex/generic/luaotfload/luaotfload-glyphlist.lua
@@ -1,7 +1,7 @@
local ProvidesLuaModule = {
name = "luaotfload-glyphlist",
- version = "3.00", --TAGVERSION
- date = "2019-09-13", --TAGDATE
+ version = "3.1", --TAGVERSION
+ date = "2019-11-04", --TAGDATE
description = "luaotfload submodule / autogenerated glyphlist",
copyright = "derived from https://raw.githubusercontent.com/adobe-type-tools/agl-aglfn/master/glyphlist.txt",
original = "Adobe Glyph List, version 2.0, September 20, 2002",
diff --git a/macros/luatex/generic/luaotfload/luaotfload-harf-define.lua b/macros/luatex/generic/luaotfload/luaotfload-harf-define.lua
new file mode 100644
index 0000000000..e8154cb719
--- /dev/null
+++ b/macros/luatex/generic/luaotfload/luaotfload-harf-define.lua
@@ -0,0 +1,394 @@
+-----------------------------------------------------------------------
+-- FILE: luaotfload-harf-define.lua
+-- DESCRIPTION: part of luaotfload / HarfBuzz / font definition
+-----------------------------------------------------------------------
+do -- block to avoid to many local variables error
+ local ProvidesLuaModule = {
+ name = "luaotfload-harf-define",
+ version = "3.1", --TAGVERSION
+ date = "2019-11-04", --TAGDATE
+ description = "luaotfload submodule / database",
+ license = "GPL v2.0",
+ author = "Khaled Hosny, Marcel Krüger",
+ copyright = "Luaotfload Development Team",
+ }
+
+ if luatexbase and luatexbase.provides_module then
+ luatexbase.provides_module (ProvidesLuaModule)
+ end
+end
+
+local stringlower = string.lower
+local stringupper = string.upper
+local gsub = string.gsub
+
+local hb = luaotfload.harfbuzz
+
+local hbfonts = {}
+
+local cfftag = hb.Tag.new("CFF ")
+local cff2tag = hb.Tag.new("CFF2")
+local os2tag = hb.Tag.new("OS/2")
+local posttag = hb.Tag.new("post")
+local glyftag = hb.Tag.new("glyf")
+
+local containers = luaotfload.fontloader.containers
+local hbcacheversion = 1.0
+local facecache = containers.define("fonts", "hb", hbcacheversion, true)
+
+local function loadfont(spec)
+ local path, sub = spec.resolved, spec.sub or 1
+
+ local key = string.format("%s:%d", gsub(path, "[/\\]", ":"), sub)
+
+ local attributes = lfs.attributes(path)
+ local size, date = attributes.size or 0, attributes.modification or 0
+
+ local cached = containers.read(facecache, key)
+ local iscached = cached and cached.date == date and cached.size == size
+
+ local hbface = iscached and cached.face or hb.Face.new(path, sub - 1)
+ local tags = hbface and hbface:get_table_tags()
+ -- If the face has no table tags then it isn’t a valid SFNT font that
+ -- HarfBuzz can handle.
+ if not tags then return end
+ local hbfont = iscached and cached.font or hb.Font.new(hbface)
+
+ if not iscached then
+ local upem = hbface:get_upem()
+
+ -- The engine seems to use the font type to tell whether there is a CFF
+ -- table or not, so we check for that here.
+ local fonttype = nil
+ local hasos2 = false
+ local haspost = false
+ for i = 1, #tags do
+ local tag = tags[i]
+ if tag == cfftag or tag == cff2tag then
+ fonttype = "opentype"
+ elseif tag == glyftag then
+ fonttype = "truetype"
+ elseif tag == os2tag then
+ hasos2 = true
+ elseif tag == posttag then
+ haspost = true
+ end
+ end
+
+ local fontextents = hbfont:get_h_extents()
+ local ascender = fontextents and fontextents.ascender or upem * .8
+ local descender = fontextents and fontextents.descender or upem * .2
+
+ local gid = hbfont:get_nominal_glyph(0x0020)
+ local space = gid and hbfont:get_glyph_h_advance(gid) or upem / 2
+
+ local slant = 0
+ if haspost then
+ local post = hbface:get_table(posttag)
+ local length = post:get_length()
+ local data = post:get_data()
+ if length >= 32 and string.unpack(">i4", data) <= 0x00030000 then
+ local italicangle = string.unpack(">i4", data, 5) / 2^16
+ if italicangle ~= 0 then
+ slant = -math.tan(italicangle * math.pi / 180) * 65536.0
+ end
+ end
+ end
+
+ -- Load glyph metrics for all glyphs in the font. We used to do this on
+ -- demand to make loading fonts faster, but hit many limitations inside
+ -- the engine (mainly with shared backend fonts, where the engine would
+ -- assume all fonts it decides to share load the same set of glyphs).
+ --
+ -- Getting glyph advances is fast enough, but glyph extents are slower
+ -- especially in CFF fonts. We might want to have an option to ignore exact
+ -- glyph extents and use font ascender and descender if this proved to be
+ -- too slow.
+ local glyphcount = hbface:get_glyph_count()
+ local glyphs = {}
+ for gid = 0, glyphcount - 1 do
+ local width = hbfont:get_glyph_h_advance(gid)
+ local height, depth, italic = nil, nil, nil
+ local extents = hbfont:get_glyph_extents(gid)
+ if extents then
+ height = extents.y_bearing
+ depth = extents.y_bearing + extents.height
+ if extents.x_bearing < 0 then
+ italic = -extents.x_bearing
+ end
+ end
+ glyphs[gid] = {
+ width = width,
+ height = height or ascender,
+ depth = -(depth or descender),
+ italic = italic or 0,
+ }
+ end
+
+ local unicodes = hbface:collect_unicodes()
+ local characters = {}
+ local nominals = {}
+ for _, uni in next, unicodes do
+ local glyph = hbfont:get_nominal_glyph(uni)
+ if glyph then
+ characters[uni] = glyph
+ nominals[glyph] = uni
+ end
+ end
+
+ local xheight, capheight = 0, 0
+ if hasos2 then
+ local os2 = hbface:get_table(os2tag)
+ local length = os2:get_length()
+ local data = os2:get_data()
+ if length >= 96 and string.unpack(">H", data) > 1 then
+ -- We don’t need much of the table, so we read from hard-coded offsets.
+ xheight = string.unpack(">H", data, 87)
+ capheight = string.unpack(">H", data, 89)
+ end
+ end
+
+ if xheight == 0 then
+ local gid = characters[120] -- x
+ if gid then
+ xheight = glyphs[gid].height
+ else
+ xheight = ascender / 2
+ end
+ end
+
+ if capheight == 0 then
+ local gid = characters[88] -- X
+ if gid then
+ capheight = glyphs[gid].height
+ else
+ capheight = ascender
+ end
+ end
+
+ cached = {
+ date = date,
+ size = size,
+ gid_offset = 0x120000,
+ upem = upem,
+ fonttype = fonttype,
+ space = space,
+ xheight = xheight,
+ capheight = capheight,
+ slant = slant,
+ glyphs = glyphs,
+ nominals = nominals,
+ unicodes = characters,
+ psname = hbface:get_name(hb.ot.NAME_ID_POSTSCRIPT_NAME),
+ fullname = hbface:get_name(hb.ot.NAME_ID_FULL_NAME),
+ haspng = hbface:ot_color_has_png(),
+ loaded = {}, -- Cached loaded glyph data.
+ }
+
+ containers.write(facecache, key, cached)
+ end
+ cached.face = hbface
+ cached.font = hbfont
+ return cached
+end
+
+-- Drop illegal characters from PS Name, per the spec
+-- https://docs.microsoft.com/en-us/typography/opentype/spec/name#nid6
+local function sanitize(psname)
+ return psname:gsub('[][\0-\32\127-\255(){}<>/%%]', '-')
+end
+
+-- Ligatures. The value is a character "ligature" table as described in the
+-- manual.
+local tlig ={
+ [0x2013] = { [0x002D] = { char = 0x2014 } }, -- [---]
+ [0x002D] = { [0x002D] = { char = 0x2013 } }, -- [--]
+ [0x0060] = { [0x0060] = { char = 0x201C } }, -- [``]
+ [0x0027] = { [0x0027] = { char = 0x201D } }, -- ['']
+ [0x0021] = { [0x0060] = { char = 0x00A1 } }, -- [!`]
+ [0x003F] = { [0x0060] = { char = 0x00BF } }, -- [?`]
+ [0x002C] = { [0x002C] = { char = 0x201E } }, -- [,,]
+ [0x003C] = { [0x003C] = { char = 0x00AB } }, -- [<<]
+ [0x003E] = { [0x003E] = { char = 0x00BB } }, -- [>>]
+}
+
+local function scalefont(data, spec)
+ local size = spec.size
+ local features = spec.features.normal
+ features.mode = 'plug'
+ features.features = 'harf'
+ fonts.constructors.checkedfeatures("otf", features)
+ local hbface = data.face
+ local hbfont = data.font
+ local upem = data.upem
+ local space = data.space
+ local gid_offset = data.gid_offset
+
+ if size < 0 then
+ size = -655.36 * size
+ end
+
+ -- We shape in font units (at UPEM) and then scale output with the desired
+ -- sfont size.
+ local scale = size / upem
+ hbfont:set_scale(upem, upem)
+
+ -- Populate font’s characters table.
+ local glyphs = data.glyphs
+ local characters = {}
+ for gid, glyph in next, glyphs do
+ characters[gid_offset + gid] = {
+ index = gid,
+ width = glyph.width * scale,
+ height = glyph.height * scale,
+ depth = glyph.depth * scale,
+ italic = glyph.italic * scale,
+ }
+ end
+
+ local unicodes = data.unicodes
+ for uni, gid in next, unicodes do
+ characters[uni] = characters[gid_offset + gid]
+ end
+
+ -- Select font palette, we support `palette=index` option, and load the first
+ -- one otherwise.
+ local paletteidx = tonumber(features.palette or features.colr) or 1
+
+ -- Load CPAL palette from the font.
+ local palette = nil
+ if hbface:ot_color_has_palettes() and hbface:ot_color_has_layers() then
+ local count = hbface:ot_color_palette_get_count()
+ if paletteidx <= count then
+ palette = hbface:ot_color_palette_get_colors(paletteidx)
+ end
+ end
+
+ local letterspace = 0
+ if features.letterspace then
+ letterspace = tonumber(features.letterspace) / 100 * upem
+ elseif features.kernfactor then
+ letterspace = tonumber(features.kernfactor) * upem
+ end
+ space = space + letterspace
+
+ local slantfactor = nil
+ if features.slant then
+ slantfactor = tonumber(features.slant) * 1000
+ end
+
+ local mode = nil
+ local width = nil
+ if features.embolden then
+ mode = 2
+ -- The multiplication by 7200.0/7227 is to undo the opposite conversion
+ -- the engine is doing and make the final number written in the PDF file
+ -- match XeTeX’s.
+ width = (size * tonumber(features.embolden) / 6553.6) * (7200.0/7227)
+ end
+
+ local hscale = upem
+ local extendfactor = nil
+ if features.extend then
+ extendfactor = tonumber(features.extend) * 1000
+ hscale = hscale * tonumber(features.extend)
+ end
+
+ local vscale = upem
+ local squeezefactor = nil
+ if features.squeeze then
+ squeezefactor = tonumber(features.squeeze) * 1000
+ vscale = vscale * tonumber(features.squeeze)
+ end
+
+ if features.tlig then
+ for char in next, characters do
+ local ligatures = tlig[char]
+ if ligatures then
+ characters[char].ligatures = ligatures
+ end
+ end
+ end
+
+ local tfmdata = {
+ name = spec.specification,
+ filename = spec.resolved,
+ subfont = spec.sub or 1,
+ designsize = size,
+ psname = sanitize(data.psname),
+ fullname = data.fullname,
+ index = spec.index,
+ size = size,
+ units_per_em = upem,
+ embedding = "subset",
+ tounicode = 1,
+ nomath = true,
+ format = data.fonttype,
+ slant = slantfactor,
+ mode = mode,
+ width = width,
+ extend = extendfactor,
+ squeeze = squeezefactor,
+ characters = characters,
+ parameters = {
+ slant = data.slant,
+ space = space * scale,
+ space_stretch = space * scale / 2,
+ space_shrink = space * scale / 3,
+ x_height = data.xheight * scale,
+ quad = size,
+ extra_space = space * scale / 3,
+ [8] = data.capheight * scale, -- for XeTeX compatibility.
+ },
+ hb = {
+ scale = scale,
+ spec = spec,
+ palette = palette,
+ shared = data,
+ letterspace = letterspace,
+ hscale = hscale,
+ vscale = vscale,
+ },
+ specification = spec,
+ shared = {},
+ properties = {},
+ }
+ tfmdata.shared.processes = fonts.handlers.otf.setfeatures(tfmdata, features)
+ return tfmdata
+end
+
+-- Register a reader for `harf` mode (`mode=harf` font option) so that we only
+-- load fonts when explicitly requested. Fonts we load will be shaped by the
+-- harf plugin in luaotfload-harf-plug.
+fonts.readers.harf = function(spec)
+ if not spec.resolved then return end
+ local rawfeatures = spec.features.raw
+ local hb_features = {}
+ spec.hb_features = hb_features
+
+ if rawfeatures.language then
+ local language = stringupper(rawfeatures.language)
+ spec.language = hb.Language.new(language == "DFLT" and "dflt"
+ or language)
+ end
+ if rawfeatures.script then
+ local script = stringlower(rawfeatures.script)
+ spec.script = hb.Script.new(script == "dflt" and "DFLT"
+ or script)
+ end
+ for key, val in next, rawfeatures do
+ if key:len() == 4 then
+ -- 4-letter options are likely font features, but not always, so we do
+ -- some checks below. Other options will be queried
+ -- from spec.features.normal.
+ if val == true or val == false then
+ val = (val and '+' or '-')..key
+ hb_features[#hb_features + 1] = hb.Feature.new(val)
+ elseif tonumber(val) then
+ val = '+'..key..'='..tonumber(val) - 1
+ hb_features[#hb_features + 1] = hb.Feature.new(val)
+ end
+ end
+ end
+ return scalefont(loadfont(spec), spec)
+end
diff --git a/macros/luatex/generic/luaotfload/luaotfload-harf-plug.lua b/macros/luatex/generic/luaotfload/luaotfload-harf-plug.lua
new file mode 100644
index 0000000000..123a1c4563
--- /dev/null
+++ b/macros/luatex/generic/luaotfload/luaotfload-harf-plug.lua
@@ -0,0 +1,983 @@
+-----------------------------------------------------------------------
+-- FILE: luaotfload-harf-plug.lua
+-- DESCRIPTION: part of luaotfload / HarfBuzz / fontloader plugin
+-----------------------------------------------------------------------
+do -- block to avoid to many local variables error
+ local ProvidesLuaModule = {
+ name = "luaotfload-harf-plug",
+ version = "3.1", --TAGVERSION
+ date = "2019-11-04", --TAGDATE
+ description = "luaotfload submodule / database",
+ license = "GPL v2.0",
+ author = "Khaled Hosny, Marcel Krüger",
+ copyright = "Luaotfload Development Team",
+ }
+
+ if luatexbase and luatexbase.provides_module then
+ luatexbase.provides_module (ProvidesLuaModule)
+ end
+end
+
+local hb = luaotfload.harfbuzz
+
+local assert = assert
+local next = next
+local tonumber = tonumber
+local type = type
+local format = string.format
+local open = io.open
+local tableinsert = table.insert
+local tableremove = table.remove
+local ostmpname = os.tmpname
+local osremove = os.remove
+
+local direct = node.direct
+local tonode = direct.tonode
+local todirect = direct.todirect
+local traverse = direct.traverse
+local insertbefore = direct.insert_before
+local insertafter = direct.insert_after
+local protectglyph = direct.protect_glyph
+local newnode = direct.new
+local freenode = direct.free
+local copynode = direct.copy
+local removenode = direct.remove
+local copynodelist = direct.copy_list
+local ischar = direct.is_char
+local uses_font = direct.uses_font
+
+local getattrs = direct.getattributelist
+local setattrs = direct.setattributelist
+local getchar = direct.getchar
+local setchar = direct.setchar
+local getdir = direct.getdir
+local setdir = direct.setdir
+local getdisc = direct.getdisc
+local setdisc = direct.setdisc
+local getfont = direct.getfont
+local getdata = direct.getdata
+local setdata = direct.setdata
+local getfont = direct.getfont
+local setfont = direct.setfont
+local getfield = direct.getfield
+local setfield = direct.setfield
+local getid = direct.getid
+local getkern = direct.getkern
+local setkern = direct.setkern
+local getnext = direct.getnext
+local setnext = direct.setnext
+local getoffsets = direct.getoffsets
+local setoffsets = direct.setoffsets
+local getproperty = direct.getproperty
+local setproperty = direct.setproperty
+local getprev = direct.getprev
+local setprev = direct.setprev
+local getsubtype = direct.getsubtype
+local setsubtype = direct.setsubtype
+local getwidth = direct.getwidth
+local setwidth = direct.setwidth
+local is_char = direct.is_char
+local tail = direct.tail
+
+local properties = direct.get_properties_table()
+
+local imgnode = img.node
+
+local disc_t = node.id("disc")
+local glue_t = node.id("glue")
+local glyph_t = node.id("glyph")
+local dir_t = node.id("dir")
+local kern_t = node.id("kern")
+local localpar_t = node.id("local_par")
+local whatsit_t = node.id("whatsit")
+local pdfliteral_t = node.subtype("pdf_literal")
+
+local explicitdisc_t = 1
+local fontkern_t = 0
+local italiccorr_t = 3
+local regulardisc_t = 3
+local spaceskip_t = 13
+
+local invalid_l = hb.Language.new()
+local invalid_s = hb.Script.new()
+
+local dir_ltr = hb.Direction.new("ltr")
+local dir_rtl = hb.Direction.new("rtl")
+local fl_unsafe = hb.Buffer.GLYPH_FLAG_UNSAFE_TO_BREAK
+
+local startactual_p = "luaotfload_startactualtext"
+local endactual_p = "luaotfload_endactualtext"
+
+-- "Copy" properties as done by LuaTeX: Make old properties metatable
+local function copytable(old)
+ local new = {}
+ for k, v in next, old do
+ if type(v) == "table" then v = copytable(v) end
+ new[k] = v
+ end
+ setmetatable(new, getmetatable(old))
+ return new
+end
+
+-- Set and get properties.
+local function setprop(n, prop, value)
+ local props = properties[n]
+ if not props then
+ props = {}
+ properties[n] = props
+ end
+ props[prop] = value
+end
+
+local function inherit(t, base, properties)
+ local n = newnode(t)
+ setattrs(n, getattrs(base))
+ if properties then
+ setproperty(n, setmetatable({}, {__index = properties}))
+ end
+ return n
+end
+-- New kern node of amount `v`, inheriting the properties/attributes of `n`.
+local function newkern(v, n)
+ local kern = inherit(kern_t, n, getproperty(n))
+ setkern(kern, v)
+ return kern
+end
+
+local function insertkern(head, current, kern, rtl)
+ if rtl then
+ head = insertbefore(head, current, kern)
+ else
+ head, current = insertafter(head, current, kern)
+ end
+ return head, current
+end
+
+-- Convert list of integers to UTF-16 hex string used in PDF.
+local function to_utf16_hex(uni)
+ if uni < 0x10000 then
+ return format("%04X", uni)
+ else
+ uni = uni - 0x10000
+ local hi = 0xD800 + (uni // 0x400)
+ local lo = 0xDC00 + (uni % 0x400)
+ return format("%04X%04X", hi, lo)
+ end
+end
+
+local process
+
+-- Legacy TeX Input Method Disguised as Font Ligatures hack.
+--
+-- Single replacements, keyed by character to replace. Handled separately
+-- because TeX ligaturing mechanism does not support one-to-one replacements.
+local trep = {
+ [0x0022] = 0x201D, -- ["]
+ [0x0027] = 0x2019, -- [']
+ [0x0060] = 0x2018, -- [`]
+}
+
+local function itemize(head, fontid, direction)
+ local fontdata = font.getfont(fontid)
+ local hbdata = fontdata and fontdata.hb
+ local spec = fontdata and fontdata.specification
+ local options = spec and spec.features.raw
+ local texlig = options and options.tlig
+
+ local runs, codes = {}, {}
+ local dirstack = {}
+ local currdir = direction or "TLT"
+ local lastskip, lastdir = true
+ local lastrun = {}
+
+ for n, id, subtype in direct.traverse(head) do
+ local code = 0xFFFC -- OBJECT REPLACEMENT CHARACTER
+ local skip = false
+
+ if id == glyph_t then
+ if is_char(n) and getfont(n) == fontid then
+ code = getchar(n)
+ else
+ skip = true
+ end
+ elseif id == glue_t and subtype == spaceskip_t then
+ code = 0x0020 -- SPACE
+ skip = lastskip
+ elseif id == disc_t then
+ if uses_font(n, fontid) then
+ code = 0x00AD -- SOFT HYPHEN
+ else
+ skip = true
+ end
+ elseif id == dir_t then
+ local dir = getdir(n)
+ if dir:sub(1, 1) == "+" then
+ -- Push the current direction to the stack.
+ tableinsert(dirstack, currdir)
+ currdir = dir:sub(2)
+ else
+ assert(currdir == dir:sub(2))
+ -- Pop the last direction from the stack.
+ currdir = tableremove(dirstack)
+ end
+ skip = lastskip
+ elseif id == localpar_t then
+ currdir = getdir(n)
+ skip = lastskip
+ end
+
+ if not skip and texlig then
+ local replacement = trep[code]
+ if replacement then
+ code = replacement
+ end
+ end
+
+ codes[#codes + 1] = code
+
+ if lastdir ~= currdir or lastskip ~= skip then
+ lastrun.after = n
+ lastrun = {
+ start = #codes,
+ len = 1,
+ font = fontid,
+ dir = currdir == "TRT" and dir_rtl or dir_ltr,
+ skip = skip,
+ codes = codes,
+ }
+ runs[#runs + 1] = lastrun
+ lastdir, lastskip = currdir, skip
+ else
+ lastrun.len = lastrun.len + 1
+ end
+ end
+
+ return runs
+end
+
+
+-- Check if it is not safe to break before this glyph.
+local function unsafetobreak(glyph)
+ return glyph
+ and glyph.flags
+ and glyph.flags & fl_unsafe
+end
+
+local shape
+
+-- Make s a sub run, used by discretionary nodes.
+local function makesub(run, codes, nodelist)
+ local subrun = {
+ start = 1,
+ len = #codes,
+ font = run.font,
+ dir = run.dir,
+ fordisc = true,
+ node = nodelist,
+ codes = codes,
+ }
+ local glyphs
+ if nodelist == 0 then -- FIXME: This shouldn't happen
+ nodelist = nil
+ end
+ nodelist, glyphs = shape(nodelist, nodelist, subrun)
+ return { glyphs = glyphs, run = subrun, head = nodelist }
+end
+
+local function printnodes(label, head, after)
+ after = tonode(after)
+ for n in node.traverse(tonode(head)) do
+ if n == after then return end
+ print(label, n, n.font or '', n.char or '')
+ local pre, post, rep = getdisc(todirect(n))
+ if pre then
+ printnodes(label .. '<', pre)
+ end
+ if post then
+ printnodes(label .. '>', post)
+ end
+ if rep then
+ printnodes(label .. '=', rep)
+ end
+ end
+end
+-- Main shaping function that calls HarfBuzz, and does some post-processing of
+-- the output.
+function shape(head, node, run)
+ local codes = run.codes
+ local offset = run.start
+ local nodeindex = offset
+ run.start = offset
+ local len = run.len
+ local fontid = run.font
+ local dir = run.dir
+ local fordisc = run.fordisc
+ local cluster = offset - 2
+
+ local fontdata = font.getfont(fontid)
+ local hbdata = fontdata.hb
+ local spec = hbdata.spec
+ local features = spec.hb_features
+ local options = spec.features.raw
+ local hbshared = hbdata.shared
+ local hbfont = hbshared.font
+
+ local lang = spec.language or invalid_l
+ local script = spec.script or invalid_s
+ local shapers = options.shaper and { options.shaper } or {}
+
+ local buf = hb.Buffer.new()
+ buf:set_direction(dir)
+ buf:set_script(script)
+ buf:set_language(lang)
+ buf:set_cluster_level(buf.CLUSTER_LEVEL_MONOTONE_CHARACTERS)
+ buf:add_codepoints(codes, offset - 1, len)
+
+ local hscale = hbdata.hscale
+ local vscale = hbdata.vscale
+ hbfont:set_scale(hscale, vscale)
+
+ if hb.shape_full(hbfont, buf, features, shapers) then
+ -- The engine wants the glyphs in logical order, but HarfBuzz outputs them
+ -- in visual order, so we reverse RTL buffers.
+ if dir:is_backward() then buf:reverse() end
+
+ local glyphs = buf:get_glyphs()
+
+ local i = 0
+ while i < #glyphs do
+ i = i + 1
+ local glyph = glyphs[i]
+
+ -- Calculate the Unicode code points of this glyph. If cluster did not
+ -- change then this is a glyph inside a complex cluster and will be
+ -- handled with the start of its cluster.
+ if cluster ~= glyph.cluster then
+ cluster = glyph.cluster
+ for i = nodeindex, cluster do node = getnext(node) end
+ nodeindex = cluster + 1
+ local hex = ""
+ local str = ""
+ local nextcluster
+ for j = i+1, #glyphs do
+ nextcluster = glyphs[j].cluster
+ if cluster ~= nextcluster then
+ glyph.nglyphs = j - i
+ goto NEXTCLUSTERFOUND -- break
+ end
+ end -- else -- only executed if the loop reached the end without
+ -- finding another cluster
+ nextcluster = offset + len - 1
+ glyph.nglyphs = #glyphs + 1 - i
+ ::NEXTCLUSTERFOUND:: -- end
+ glyph.nextcluster = nextcluster
+ do
+ local node = node
+ for j = cluster,nextcluster-1 do
+ local id = getid(node)
+ if id == glyph_t or id == glue_t then
+ local code = codes[j + 1]
+ hex = hex..to_utf16_hex(code)
+ str = str..utf8.char(code)
+ end
+ end
+ glyph.tounicode = hex
+ glyph.string = str
+ end
+ if not fordisc then
+ local discindex = nil
+ local disc = node
+ for j = cluster + 1, nextcluster do
+ if codes[j] == 0x00AD then
+ discindex = j
+ break
+ end
+ disc = getnext(disc)
+ end
+ if discindex then
+ -- Discretionary found.
+ local startindex, stopindex = nil, nil
+ local startglyph, stopglyph = nil, nil
+
+ -- Find the previous glyph that is safe to break at.
+ local startglyph = i
+ while startglyph > 1
+ and codes[glyphs[startglyph - 1].cluster + 1] ~= 0x20
+ and codes[glyphs[startglyph - 1].cluster + 1] ~= 0xFFFC
+ and unsafetobreak(glyphs[startglyph]) do
+ startglyph = startglyph - 1
+ end
+ -- Get the corresponding character index.
+ startindex = glyphs[startglyph].cluster + 1
+
+ -- Find the next glyph that is safe to break at.
+ stopglyph = i + 1
+ local lastcluster = glyphs[i].cluster
+ while stopglyph <= #glyphs
+ and codes[glyphs[stopglyph].cluster + 1] ~= 0x20
+ and codes[glyphs[stopglyph].cluster + 1] ~= 0xFFFC
+ and (unsafetobreak(glyphs[stopglyph])
+ or lastcluster == glyphs[stopglyph].cluster) do
+ lastcluster = glyphs[stopglyph].cluster
+ stopglyph = stopglyph + 1
+ end
+
+ stopindex = stopglyph <= #glyphs and glyphs[stopglyph].cluster + 1
+ or offset + len
+
+ local startnode, stopnode = node, node
+ for j=nodeindex - 1, startindex, -1 do
+ startnode = getprev(startnode)
+ end
+ for j=nodeindex + 1, stopindex do
+ stopnode = getnext(stopnode)
+ end
+
+ glyphs[startglyph] = glyph
+ glyph.cluster = startindex - 1
+ glyph.nextcluster = startindex
+ for j = stopglyph, #glyphs do
+ local glyph = glyphs[j]
+ glyph.cluster = glyph.cluster - (stopindex - startindex) + 1
+ end
+ len = len - (stopindex - startindex) + 1
+ table.move(glyphs, stopglyph, #glyphs + stopglyph - startglyph - 1, startglyph + 1)
+
+ local subcodes, subindex = {}
+ do
+ local node = startnode
+ while node ~= stopnode do
+ if node == disc then
+ subindex = #subcodes
+ startindex = startindex + 1
+ node = getnext(node)
+ elseif getid(node) == disc_t then
+ local oldnode = node
+ startnode, node = removenode(startnode, node)
+ freenode(oldnode)
+ tableremove(codes, startindex)
+ else
+ subcodes[#subcodes + 1] = tableremove(codes, startindex)
+ node = getnext(node)
+ end
+ end
+ end
+
+ local pre, post, rep, lastpre, lastpost, lastrep = getdisc(disc, true)
+ local precodes, postcodes, repcodes = {}, {}, {}
+ table.move(subcodes, 1, subindex, 1, repcodes)
+ for n, id, subtype in traverse(rep) do
+ repcodes[#repcodes + 1] = getfont(n) == fontid and getchar(n) or 0xFFFC
+ end
+ table.move(subcodes, subindex + 1, #subcodes, #repcodes + 1, repcodes)
+ table.move(subcodes, 1, subindex, 1, precodes)
+ for n, id, subtype in traverse(pre) do
+ precodes[#precodes + 1] = getfont(n) == fontid and getchar(n) or 0xFFFC
+ end
+ for n, id, subtype in traverse(post) do
+ postcodes[#postcodes + 1] = getfont(n) == fontid and getchar(n) or 0xFFFC
+ end
+ table.move(subcodes, subindex + 1, #subcodes, #postcodes + 1, postcodes)
+ if startnode ~= disc then
+ local newpre = copynodelist(startnode, disc)
+ setnext(tail(newpre), pre)
+ pre = newpre
+ end
+ if post then
+ setnext(lastpost, copynodelist(getnext(disc), stopnode))
+ else
+ post = copynodelist(getnext(disc), stopnode)
+ end
+ if startnode ~= disc then
+ local predisc = getprev(disc)
+ setnext(predisc, rep)
+ setprev(rep, predisc)
+ if startnode == head then
+ head = disc
+ else
+ local before = getprev(startnode)
+ setnext(before, disc)
+ setprev(disc, before)
+ end
+ setprev(startnode, nil)
+ rep = startnode
+ lastrep = lastrep or predisc
+ end
+ if getnext(disc) ~= stopnode then
+ setnext(getprev(stopnode), nil)
+ setprev(stopnode, disc)
+ setprev(getnext(disc), lastrep)
+ setnext(lastrep, getnext(disc))
+ rep = rep or getnext(disc)
+ setnext(disc, stopnode)
+ end
+ glyph.replace = makesub(run, repcodes, rep)
+ glyph.pre = makesub(run, precodes, pre)
+ glyph.post = makesub(run, postcodes, post)
+ i = startglyph
+ node = disc
+ cluster = glyph.cluster
+ nodeindex = cluster + 1
+ end
+ end
+ end
+ end
+ return head, glyphs, run.len - len
+ end
+
+ return head, {}, 0
+end
+
+local function color_to_rgba(color)
+ local r = color.red / 255
+ local g = color.green / 255
+ local b = color.blue / 255
+ local a = color.alpha / 255
+ if a ~= 1 then
+ -- XXX: alpha
+ return format('%s %s %s rg', r, g, b)
+ else
+ return format('%s %s %s rg', r, g, b)
+ end
+end
+
+-- Cache of color glyph PNG data for bookkeeping, only because I couldn’t
+-- figure how to make the engine load the image from the binary data directly.
+local pngcache = {}
+local pngcachefiles = {}
+local function cachedpng(data)
+ local hash = md5.sumhexa(data)
+ local i = pngcache[hash]
+ if not i then
+ local path = ostmpname()
+ pngcachefiles[#pngcachefiles + 1] = path
+ open(path, "wb"):write(data):close()
+ -- local file = open(path, "wb"):write():close()
+ -- file:write(data)
+ -- file:close()
+ i = img.scan{filename = path}
+ pngcache[hash] = i
+ end
+ return i
+end
+
+local function get_png_glyph(gid, fontid, characters, haspng)
+ return gid
+end
+
+local push_cmd = { "push" }
+local pop_cmd = { "pop" }
+local nop_cmd = { "nop" }
+local save_cmd = { "pdf", "page", "q" }
+local restore_cmd = { "pdf", "page", "Q" }
+
+-- Convert glyphs to nodes and collect font characters.
+local function tonodes(head, node, run, glyphs)
+ local nodeindex = run.start
+ local dir = run.dir
+ local fontid = run.font
+ local fontdata = font.getfont(fontid)
+ local characters = fontdata.characters
+ local hbdata = fontdata.hb
+ local palette = hbdata.palette
+ local hbshared = hbdata.shared
+ local hbface = hbshared.face
+ local nominals = hbshared.nominals
+ local hbfont = hbshared.font
+ local fontglyphs = hbshared.glyphs
+ local gid_offset = hbshared.gid_offset
+ local rtl = dir:is_backward()
+ local lastprops
+
+ local scale = hbdata.scale
+ local letterspace = hbdata.letterspace
+
+ local haspng = hbshared.haspng
+ local fonttype = hbshared.fonttype
+
+ local nextcluster
+
+ for i, glyph in ipairs(glyphs) do
+ if glyph.cluster + 1 >= nodeindex then -- Reached a new cluster
+ nextcluster = glyph.nextcluster
+ assert(nextcluster)
+ for j = nodeindex, glyph.cluster do
+ local oldnode = node
+ head, node = removenode(head, node)
+ freenode(oldnode)
+ end
+ lastprops = getproperty(node)
+ nodeindex = glyph.cluster + 1
+ elseif nextcluster + 1 == nodeindex then -- Oops, we went too far
+ nodeindex = nodeindex - 1
+ local new = inherit(glyph_t, getprev(node), lastprops)
+ setfont(new, fontid)
+ head, node = insertbefore(head, node, new)
+ end
+ local gid = glyph.codepoint
+ local char = nominals[gid] or gid_offset + gid
+ local id = getid(node)
+
+ if glyph.replace then
+ -- For discretionary the glyph itself is skipped and a discretionary node
+ -- is output in place of it.
+ local rep, pre, post = glyph.replace, glyph.pre, glyph.post
+
+ setdisc(node, tonodes(pre.head, pre.head, pre.run, pre.glyphs),
+ tonodes(post.head, post.head, post.run, post.glyphs),
+ tonodes(rep.head, rep.head, rep.run, rep.glyphs))
+ node = getnext(node)
+ nodeindex = nodeindex + 1
+ elseif glyph.skip then
+ local oldnode = node
+ head, node = removenode(head, node)
+ freenode(oldnode)
+ nodeindex = nodeindex + 1
+ else
+ if id == glyph_t then
+ local done
+ local fontglyph = fontglyphs[gid]
+ local character = characters[char]
+
+ if not character.commands then
+ if palette then
+ local layers = fontglyph.layers
+ if layers == nil then
+ layers = hbface:ot_color_glyph_get_layers(gid) or false
+ fontglyph.layers = layers
+ end
+ if layers then
+ local cmds = {} -- Every layer will add 5 cmds
+ local prev_color = nil
+ for j = 1, #layers do
+ local layer = layers[j]
+ local layerchar = characters[gid_offset + layer.glyph]
+ if layerchar.height > character.height then
+ character.height = layerchar.height
+ end
+ if layerchar.depth > character.depth then
+ character.depth = layerchar.depth
+ end
+ -- color_index has a special value, 0x10000, that mean use text
+ -- color, we don’t check for it here explicitly since we will
+ -- get nil anyway.
+ local color = palette[layer.color_index]
+ cmds[5*j - 4] = (color and not prev_color) and save_cmd or nop_cmd
+ cmds[5*j - 3] = prev_color == color and nop_cmd or (color and {"pdf", "page", color_to_rgba(color)} or restore_cmd)
+ cmds[5*j - 2] = push_cmd
+ cmds[5*j - 1] = {"char", layer.glyph + gid_offset}
+ cmds[5*j] = pop_cmd
+ fontglyphs[layer.glyph].used = true
+ prev_color = color
+ end
+ cmds[#cmds + 1] = prev_color and restore_cmd
+ if not character.colored then
+ local coloredcharacter = {}
+ for k,v in next, character do
+ coloredcharacter[k] = v
+ end
+ coloredcharacter.commands = cmds
+ local newcharacters = {[gid + 0x130000] = coloredcharacter}
+ characters[gid + 0x130000] = coloredcharacter
+ if char ~= gid + gid_offset then
+ newcharacters[char] = coloredcharacter
+ characters[char] = coloredcharacter
+ character.colored = char
+ else
+ character.colored = gid + 0x130000
+ end
+ font.addcharacters(fontid, {characters = newcharacters})
+ end
+ char = character.colored
+ character = characters[char]
+ end
+ end
+
+ if haspng then
+ local pngglyph = character.pngglyph
+ if pngglyph == nil then
+ local pngblob = hbfont:ot_color_glyph_get_png(gid)
+ if pngblob then
+ local glyphimg = cachedpng(pngblob:get_data())
+ local pngchar = { }
+ for k,v in next, character do
+ pngchar[k] = v
+ end
+ local i = img.copy(glyphimg)
+ i.width = character.width
+ i.depth = 0
+ i.height = character.height + character.depth
+ pngchar.commands = fonttype and {
+ {"push"}, {"char", gid_offset + gid}, {"pop"},
+ {"down", character.depth}, {"image", i}
+ } or { {"down", character.depth}, {"image", i} }
+ if not nominals[gid] then
+ char = 0x130000 + gid
+ end
+ characters[char] = pngchar
+ pngglyph = char
+ font.addcharacters(fontid, {characters = {[char] = pngchar}})
+ end
+ character.pngglyph = pngglyph
+ end
+ if pngglyph then
+ char = pngglyph
+ elseif not fonttype then
+ -- Color bitmap font with no glyph outlines (like Noto
+ -- Color Emoji) but has no bitmap for current glyph (most likely
+ -- `.notdef` glyph). The engine does not know how to embed such
+ -- fonts, so we don’t want them to reach the backend as it will cause
+ -- a fatal error. We use `nullfont` instead. That is a hack, but I
+ -- think it is good enough for now. We could make the glyph virtual
+ -- with empty commands suh that LuaTeX ignores it, but we still want
+ -- a missing glyph warning.
+ -- We insert the glyph node and move on, no further work is needed.
+ setfont(node, 0)
+ done = true
+ end
+ end
+ end
+ if not done then
+ local oldcharacter = characters[getchar(node)]
+ -- If the glyph index of current font character is the same as shaped
+ -- glyph, keep the node char unchanged. Helps with primitives that
+ -- take characters as input but actually work on glyphs, like
+ -- `\rpcode`.
+ if character.commands or not oldcharacter
+ or character.index ~= oldcharacter.index then
+ setchar(node, char)
+ end
+ local xoffset = (rtl and -glyph.x_offset or glyph.x_offset) * scale
+ local yoffset = glyph.y_offset * scale
+ setoffsets(node, xoffset, yoffset)
+
+ fontglyph.used = fonttype and true
+
+ -- The engine will use this string when printing a glyph node e.g. in
+ -- overfull messages, otherwise it will be trying to print our
+ -- invalid pseudo Unicode code points.
+ -- If the string is empty it means this glyph is part of a larger
+ -- cluster and we don’t to print anything for it as the first glyph
+ -- in the cluster will have the string of the whole cluster.
+ local props = properties[node]
+ if not props then
+ props = {}
+ properties[node] = props
+ end
+ props.glyph_info = glyph.string or ""
+
+ -- Handle PDF text extraction:
+ -- * Find how many characters in this cluster and how many glyphs,
+ -- * If there is more than 0 characters
+ -- * One glyph: one to one or one to many mapping, can be
+ -- represented by font’s /ToUnicode
+ -- * More than one: many to one or many to many mapping, can be
+ -- represented by /ActualText spans.
+ -- * If there are zero characters, then this glyph is part of complex
+ -- cluster that will be covered by an /ActualText span.
+ local tounicode = glyph.tounicode
+ if tounicode then
+ if glyph.nglyphs == 1
+ and not character.commands
+ and not fontglyph.tounicode then
+ fontglyph.tounicode = tounicode
+ elseif character.commands or tounicode ~= fontglyph.tounicode then
+ setprop(node, startactual_p, tounicode)
+ glyphs[i + glyph.nglyphs - 1].endactual = true
+ end
+ end
+ if glyph.endactual then
+ setprop(node, endactual_p, true)
+ end
+ local x_advance = glyph.x_advance + letterspace
+ local width = fontglyph.width
+ if width ~= x_advance then
+ -- The engine always uses the glyph width from the font, so we need
+ -- to insert a kern node if the x advance is different.
+ local kern = newkern((x_advance - width) * scale, node)
+ head, node = insertkern(head, node, kern, rtl)
+ end
+ end
+ elseif id == glue_t and getsubtype(node) == spaceskip_t then
+ -- If the glyph advance is different from the font space, then a
+ -- substitution or positioning was applied to the space glyph changing
+ -- it from the default, so reset the glue using the new advance.
+ -- We are intentionally not comparing with the existing glue width as
+ -- spacing after the period is larger by default in TeX.
+ local width = (glyph.x_advance + letterspace) * scale
+ if fontdata.parameters.space ~= width then
+ setwidth(node, width)
+ setfield(node, "stretch", width / 2)
+ setfield(node, "shrink", width / 3)
+ end
+ elseif id == kern_t and getsubtype(node) == italiccorr_t then
+ -- If this is an italic correction node and the previous node is a
+ -- glyph, update its kern value with the glyph’s italic correction.
+ local prevchar, prevfontid = ischar(getprev(node))
+ if prevfontid == fontid and prevchar and prevchar > 0 then
+ local italic = characters[prevchar].italic
+ if italic then
+ setkern(node, italic)
+ end
+ end
+ end
+ node = getnext(node)
+ nodeindex = nodeindex + 1
+ end
+ end
+ while node ~= run.after do
+ local oldnode = node
+ head, node = removenode(head, node)
+ freenode(oldnode)
+ end
+
+ return head, node
+end
+
+local function shape_run(head, current, run)
+ if not run.skip then
+ -- Font loaded with our loader and an HarfBuzz face is present, do our
+ -- shaping.
+ local fontid = run.font
+ local fontdata = font.getfont(fontid)
+ local options = fontdata.specification.features.raw
+
+ local glyphs, offset
+ head, glyphs, offset = shape(head, current, run)
+ return offset, tonodes(head, current, run, glyphs)
+ else
+ return 0, head, run.after
+ end
+end
+
+function process(head, font, direction)
+ local newhead, current = head, head
+ local runs = itemize(head, font, direction)
+
+ local offset = 0
+ for i = 1,#runs do
+ local run = runs[i]
+ run.start = run.start - offset
+ local new_offset
+ new_offset, newhead, current = shape_run(newhead, current, run)
+ offset = offset + new_offset
+ end
+
+ return newhead or head
+end
+
+local function pageliteral(data)
+ local n = newnode(whatsit_t, pdfliteral_t)
+ setfield(n, "mode", 1) -- page
+ setdata(n, data)
+ return n
+end
+
+local function post_process(head)
+ for n in traverse(head) do
+ local props = properties[n]
+
+ local startactual, endactual
+ if props then
+ startactual = rawget(props, startactual_p)
+ endactual = rawget(props, endactual_p)
+ end
+
+ if startactual then
+ local actualtext = "/Span<</ActualText<FEFF"..startactual..">>>BDC"
+ head = insertbefore(head, n, pageliteral(actualtext))
+ end
+
+ if endactual then
+ head = insertafter(head, n, pageliteral("EMC"))
+ end
+
+ local replace = getfield(n, "replace")
+ if replace then
+ setfield(n, "replace", post_process(replace))
+ end
+
+ local subhead = getfield(n, "head")
+ if subhead then
+ setfield(n, "head", post_process(subhead))
+ end
+ end
+ return head
+end
+
+local function post_process_nodes(head, groupcode)
+ return tonode(post_process(todirect(head)))
+end
+
+local function run_cleanup()
+ -- Remove temporary PNG files that we created, if any.
+ -- FIXME: It would be nice if we wouldn't need this
+ for _, path in next, pngcachefiles do
+ osremove(path)
+ end
+end
+
+local function set_tounicode()
+ for fontid, fontdata in font.each() do
+ local hbdata = fontdata.hb
+ if hbdata and fontid == pdf.getfontname(fontid) then
+ local characters = fontdata.characters
+ local newcharacters = {}
+ local hbshared = hbdata.shared
+ local glyphs = hbshared.glyphs
+ local nominals = hbshared.nominals
+ local gid_offset = hbshared.gid_offset
+ for gid = 0, #glyphs do
+ local glyph = glyphs[gid]
+ if glyph.used then
+ local character = characters[gid + gid_offset]
+ newcharacters[gid + gid_offset] = character
+ local unicode = nominals[gid]
+ if unicode then
+ newcharacters[unicode] = character
+ end
+ character.tounicode = glyph.tounicode or "FFFD"
+ character.used = true
+ end
+ end
+ font.addcharacters(fontid, { characters = newcharacters })
+ end
+ end
+end
+
+-- FIXME: Move this into generic parts of luaotfload
+local utfchar = utf8.char
+local function get_glyph_info(n)
+ n = todirect(n)
+ local props = properties[n]
+ return props and props.glyph_info or utfchar(getchar(n)):gsub('\0', '^^@')
+end
+
+fonts.handlers.otf.registerplugin('harf', process)
+
+-- luatexbase does not know how to handle `wrapup_run` callback, teach it.
+-- TODO: Move these into ltluatex
+luatexbase.callbacktypes.wrapup_run = 1 -- simple
+luatexbase.callbacktypes.glyph_info = 1 -- simple
+
+local base_callback_descriptions = luatexbase.callback_descriptions
+local base_add_to_callback = luatexbase.add_to_callback
+local base_remove_from_callback = luatexbase.remove_from_callback
+
+-- Remove all existing functions from given callback, insert ours, then
+-- reinsert the removed ones, so ours takes a priority.
+local function add_to_callback(name, func)
+ local saved_callbacks = {}, ff, dd
+ for k, v in next, base_callback_descriptions(name) do
+ saved_callbacks[k] = { base_remove_from_callback(name, v) }
+ end
+ base_add_to_callback(name, func, "Harf "..name.." callback")
+ for _, v in next, saved_callbacks do
+ base_add_to_callback(name, v[1], v[2])
+ end
+end
+
+add_to_callback('pre_output_filter', post_process_nodes) -- FIXME: Wrong callback, but I want to get rid of the whole function anyway
+add_to_callback('wrapup_run', run_cleanup)
+add_to_callback('finish_pdffile', set_tounicode)
+add_to_callback('glyph_info', get_glyph_info)
diff --git a/macros/luatex/generic/luaotfload/luaotfload-init.lua b/macros/luatex/generic/luaotfload/luaotfload-init.lua
index 6a80546d43..5f7b710d9b 100644
--- a/macros/luatex/generic/luaotfload/luaotfload-init.lua
+++ b/macros/luatex/generic/luaotfload/luaotfload-init.lua
@@ -7,8 +7,8 @@
local ProvidesLuaModule = {
name = "luaotfload-init",
- version = "3.00", --TAGVERSION
- date = "2019-09-13", --TAGDATE
+ version = "3.1", --TAGVERSION
+ date = "2019-11-04", --TAGDATE
description = "luaotfload submodule / initialization",
license = "GPL v2.0"
}
@@ -78,122 +78,6 @@ local logreport --- filled in after loading the log module
--doc]]--
-local init_early = function ()
-
- local store = { }
- config = config or { } --- global
- config.luaotfload = config.luaotfload or { }
- config.lualibs = config.lualibs or { }
- config.lualibs.verbose = false
- config.lualibs.prefer_merged = true
- config.lualibs.load_extended = true
- fonts = fonts or { }
-
- require "lualibs"
-
- if not lualibs then error "this module requires Luaotfload" end
- if not luaotfload then error "this module requires Luaotfload" end
-
- --[[doc--
-
- The logger needs to be in place prior to loading the fontloader due
- to order of initialization being crucial for the logger functions
- that are swapped.
-
- --doc]]--
-
- luaotfload.loaders.luaotfload "log"
- log = luaotfload.log
- logreport = log.report
- log.set_loglevel (default_log_level)
-
- logreport ("log", 4, "init", "Concealing callback.register().")
- store.trapped_register = callback.register
-
- callback.register = function (id)
- logreport ("log", 4, "init",
- "Dummy callback.register() invoked on %s.",
- id)
- end
-
- --[[doc--
-
- By default, the fontloader requires a number of \emphasis{private
- attributes} for internal use.
- These must be kept consistent with the attribute handling methods
- as provided by \identifier{luatexbase}.
- Our strategy is to override the function that allocates new
- attributes before we initialize the font loader, making it a
- wrapper around \luafunction{luatexbase.new_attribute}.\footnote{%
- Many thanks, again, to Hans Hagen for making this part
- configurable!
- }
- The attribute identifiers are prefixed “\fileent{luaotfload@}” to
- avoid name clashes.
-
- --doc]]--
-
- local new_attribute = luatexbase.new_attribute
- local the_attributes = luatexbase.attributes
-
- attributes = attributes or { } --- this writes a global, sorry
-
- attributes.private = function (name)
- local attr = "luaotfload@" .. name --- used to be: “otfl@”
- local number = the_attributes[attr]
- if not number then number = new_attribute(attr) end
- return number
- end
-
- luaotfload.loaders.fontloader "basics-gen"
-
- return store
-end --- [init_early]
-
---[[doc--
-
- These next lines replicate the behavior of
- \fileent{luatex-fonts.lua}.
-
---doc]]--
-
-local push_namespaces = function ()
- logreport ("log", 4, "init", "push namespace for font loader")
- local normalglobal = { }
- for k, v in next, _G do
- normalglobal[k] = v
- end
- return normalglobal
-end
-
-local pop_namespaces = function (normalglobal,
- isolate,
- context_environment)
- if normalglobal then
- local _G = _G
- local mode = "non-destructive"
- if isolate then mode = "destructive" end
- logreport ("log", 4, "init", "pop namespace from font loader -- " .. mode)
- for k, v in next, _G do
- if not normalglobal[k] then
- context_environment[k] = v
- if isolate then
- _G[k] = nil
- end
- end
- end
- for k, v in next, normalglobal do
- _G[k] = v
- end
- -- just to be sure:
- setmetatable(context_environment, _G)
- else
- logreport ("both", 0, "init",
- "irrecoverable error during pop_namespace: no globals to restore")
- os.exit ()
- end
-end
-
--- below paths are relative to the texmf-context
local ltx = "tex/generic/context/luatex"
local ctx = { "tex/context/base/mkiv", "tex/context/base" }
@@ -308,159 +192,71 @@ local load_context_modules = function (pth)
end
-local init_adapt = function ()
+local function init_main(early_hook)
+ config = config or { } --- global
+ config.luaotfload = config.luaotfload or { }
+ config.lualibs = config.lualibs or { }
+ config.lualibs.verbose = false
+ config.lualibs.prefer_merged = true
+ config.lualibs.load_extended = true
+ fonts = fonts or { }
+
+ require "lualibs"
- local context_environment = { }
- local our_environment = push_namespaces ()
+ if not lualibs then error "this module requires Luaotfload" end
+ if not luaotfload then error "this module requires Luaotfload" end
--[[doc--
- The font loader requires that the attribute with index zero be
- zero. We happily oblige.
- (Cf. \fileent{luatex-fonts-nod.lua}.)
+ The logger needs to be in place prior to loading the fontloader due
+ to order of initialization being crucial for the logger functions
+ that are swapped.
--doc]]--
- tex.attribute[0] = 0
-
- return our_environment, context_environment
-
-end --- [init_adapt]
-
---[[doc--
+ luaotfload.loaders.luaotfload "log"
+ log = luaotfload.log
+ logreport = log.report
+ log.set_loglevel (default_log_level)
- In Context, characters.data is where the data from char-def.lua
- resides. The file is huge (>4.4 MB as of 2016) and only a stripped
- down version is part of the isolated font loader. Nevertheless, we
- include an excerpt generated by the mkcharacters script that contains
- a subset of the fields of each character defined and some extra
- metadata.
+ logreport ("log", 4, "init", "Concealing callback.register().")
+ local trapped_register = callback.register
- Currently, these are (compare the mkcharacters script!)
+ callback.register = function (id)
+ logreport ("log", 4, "init",
+ "Dummy callback.register() invoked on %s.",
+ id)
+ end
- · "direction"
- · "mirror"
- · "category"
- · "textclass"
+ --[[doc--
- The directional information is required for packages like Simurgh [0]
- to work correctly. In an early stage [1] it was necessary to load
- further files from Context directly, including the full blown version
- of char-def. Since we have no use for most of the so imported
- functionality, the required parts have been isolated and are now
- instated along with luaotfload-characters.lua. We can extend the set
- of imported features easily should it not be enough.
+ By default, the fontloader requires a number of \emphasis{private
+ attributes} for internal use.
+ These must be kept consistent with the attribute handling methods
+ as provided by \identifier{luatexbase}.
+ Our strategy is to override the function that allocates new
+ attributes before we initialize the font loader, making it a
+ wrapper around \luafunction{luatexbase.new_attribute}.\footnote{%
+ Many thanks, again, to Hans Hagen for making this part
+ configurable!
+ }
+ The attribute identifiers are prefixed “\fileent{luaotfload@}” to
+ avoid name clashes.
- [0] https://github.com/persian-tex/simurgh
- [1] http://tex.stackexchange.com/a/132301/14066
+ --doc]]--
---doc]]--
+ local new_attribute = luatexbase.new_attribute
+ local the_attributes = luatexbase.attributes
---[[--14.12.2018disable characters
---characters = characters or { } --- should be created in basics-gen
---characters.data = nil
---local chardef = "luaotfload-characters"
---
---do
--- local setmetatableindex = function (t, f)
--- local mt = getmetatable (t)
--- if mt then
--- mt.__index = f
--- else
--- setmetatable (t, { __index = f })
--- end
--- end
---
--- --- there are some special tables for each field that provide access
--- --- to fields of the character table by means of a metatable
---
--- local mkcharspecial = function (characters, tablename, field)
---
--- local chardata = characters.data
---
--- if chardata then
--- local newspecial = { }
--- characters [tablename] = newspecial --> e.g. “characters.data.mirrors”
---
--- local idx = function (t, char)
--- local c = chardata [char]
--- if c then
--- local m = c [field] --> e.g. “mirror”
--- if m then
--- t [char] = m
--- return m
--- end
--- end
--- newspecial [char] = false
--- return char
--- end
---
--- setmetatableindex (newspecial, idx)
--- end
---
--- end
---
--- local mkcategories = function (characters) -- different from the others
---
--- local chardata = characters.data
--- local categories = characters.categories or { }
--- characters.categories = categories
---
--- setmetatable (categories, { __index = function (t, char)
--- if char then
--- local c = chardata [char]
--- c = c.category or char
--- t [char] = c
--- return c
--- end
--- end})
---
--- end
---
--- local load_failed = false
--- local chardata --> characters.data; loaded on demand
---
--- local load_chardef = function ()
---
--- logreport ("both", 1, "aux", "Loading character metadata from %s.", chardef)
--- chardata = dofile (kpse.find_file (chardef, "lua"))
---
--- if chardata == nil then
--- logreport ("both", 0, "aux",
--- "Could not load %s; continuing with empty character table.",
--- chardef)
--- chardata = { }
--- load_failed = true
--- end
---
--- characters = { } --- nuke metatable
--- characters.data = chardata
--- characters.classifiers = chardata.classifiers
--- chardata.classifiers = nil
---
--- --- institute some of the functionality from char-ini.lua
---
--- mkcharspecial (characters, "mirrors", "mirror")
--- mkcharspecial (characters, "directions", "direction")
--- mkcharspecial (characters, "textclasses", "textclass")
--- mkcategories (characters)
---
--- end
---
--- local charindex = function (t, k)
--- if chardata == nil and load_failed ~= true then
--- load_chardef ()
--- end
---
--- return rawget (characters, k)
--- end
---
--- setmetatableindex (characters, charindex)
---
---end
---]] --14.12.2018disable characters
-
-local init_main = function ()
+ local context_environment = luaotfload.fontloader
+ context_environment.attributes = {
+ private = function (name)
+ local attr = "luaotfload@" .. name --- used to be: “otfl@”
+ local number = the_attributes[attr]
+ if not number then number = new_attribute(attr) end
+ return number
+ end
+ }
--[[doc--
@@ -473,6 +269,20 @@ local init_main = function ()
local load_fontloader_module = luaotfload.loaders.fontloader
local ignore_module = luaotfload.loaders.ignore
+ load_fontloader_module "basics-gen"
+
+ if early_hook then early_hook() end
+
+ --[[doc--
+
+ The font loader requires that the attribute with index zero be
+ zero. We happily oblige.
+ (Cf. \fileent{luatex-fonts-nod.lua}.)
+
+ --doc]]--
+
+ tex.attribute[0] = 0
+
--[[doc--
Now that things are sorted out we can finally load the
@@ -574,14 +384,14 @@ local init_main = function ()
logreport ("log", 0, "init",
"Loading fontloader from absolute path “%s”.",
fontloader)
- local _void = require (fontloader)
+ local _void = assert (loadfile (fontloader, nil, context_environment)) ()
elseif kpsefind_file (fontloader) then
local path = kpsefind_file (fontloader)
logreport ("log", 0, "init",
"Loading fontloader “%s” from kpse-resolved path “%s”.",
fontloader, path)
- local _void = require (path)
+ local _void = assert (loadfile (path, nil, context_environment)) ()
elseif kpsefind_file (("fontloader-%s.lua"):format(fontloader)) then
logreport ("log", 0, "init",
@@ -605,43 +415,12 @@ local init_main = function ()
logreport ("log", 0, "init",
"Context OpenType loader version “%s”",
fonts.handlers.otf.version)
+ callback.register = trapped_register
+ nodes = context_environment.nodes
+ -- setmetatable(context_environment, nil) -- Would be nice, might break the
+ -- fontloader
end --- [init_main]
-local init_cleanup = function (store)
- --- reinstate all the stuff we had to move out of the way to
- --- accomodate the loader
-
- --[[doc--
-
- Here we adjust the globals created during font loader
- initialization. If the second argument to
- \luafunction{pop_namespaces()} is \verb|true| this will restore the
- state of \luafunction{_G}, eliminating every global generated since
- the last call to \luafunction{push_namespaces()}. At the moment we
- see no reason to do this, and since the font loader is considered
- an essential part of \identifier{luatex} as well as a very well
- organized piece of code, we happily concede it the right to add to
- \luafunction{_G} if needed.
-
- --doc]]--
-
- pop_namespaces (store.our_environment,
- false,
- store.context_environment)
-
- --[[doc--
-
- \subsection{Callbacks}
- After the fontloader is ready we can restore the callback trap
- from \identifier{luatexbase}.
-
- --doc]]--
-
- logreport ("log", 4, "init",
- "Restoring original callback.register().")
- callback.register = store.trapped_register
-end --- [init_cleanup]
-
local init_post_install_callbacks = function ()
--[[doc--
@@ -654,7 +433,7 @@ local init_post_install_callbacks = function ()
--doc]]--
-- MK Pass current text direction to simple_font_handler
- local handler = nodes.simple_font_handler
+ local handler = luaotfload.fontloader.nodes.simple_font_handler
local callback = function(head, groupcode, _, _, direction)
if not direction then
direction = tex.get'textdir'
@@ -774,20 +553,14 @@ local init_post = function ()
return n
end --- [init_post]
-return {
- early = init_early,
- main = function (store)
- local starttime = os.gettimeofday ()
- store.our_environment, store.context_environment = init_adapt ()
- init_main ()
- init_cleanup (store)
- logreport ("both", 1, "init",
- "fontloader loaded in %0.3f seconds",
- os.gettimeofday() - starttime)
- local n = init_post ()
- logreport ("both", 5, "init", "post hook terminated, %d actions performed", n)
- return true
- end
-}
-
+return function (early_hook)
+ local starttime = os.gettimeofday ()
+ init_main (early_hook)
+ logreport ("both", 1, "init",
+ "fontloader loaded in %0.3f seconds",
+ os.gettimeofday() - starttime)
+ local n = init_post ()
+ logreport ("both", 5, "init", "post hook terminated, %d actions performed", n)
+ return true
+end
-- vim:tw=79:sw=2:ts=2:expandtab
diff --git a/macros/luatex/generic/luaotfload/luaotfload-latex.pdf b/macros/luatex/generic/luaotfload/luaotfload-latex.pdf
index 8b128aed7e..28391b2e8a 100644
--- a/macros/luatex/generic/luaotfload/luaotfload-latex.pdf
+++ b/macros/luatex/generic/luaotfload/luaotfload-latex.pdf
Binary files differ
diff --git a/macros/luatex/generic/luaotfload/luaotfload-letterspace.lua b/macros/luatex/generic/luaotfload/luaotfload-letterspace.lua
index bbd045e4f8..a58d59ba1a 100644
--- a/macros/luatex/generic/luaotfload/luaotfload-letterspace.lua
+++ b/macros/luatex/generic/luaotfload/luaotfload-letterspace.lua
@@ -5,8 +5,8 @@
local ProvidesLuaModule = {
name = "luaotfload-letterspace",
- version = "3.00", --TAGVERSION
- date = "2019-09-13", --TAGDATE
+ version = "3.1", --TAGVERSION
+ date = "2019-11-04", --TAGDATE
description = "luaotfload submodule / color",
license = "GPL v2.0",
copyright = "PRAGMA ADE / ConTeXt Development Team",
diff --git a/macros/luatex/generic/luaotfload/luaotfload-loaders.lua b/macros/luatex/generic/luaotfload/luaotfload-loaders.lua
index 11e63c571a..c2c2320ff8 100644
--- a/macros/luatex/generic/luaotfload/luaotfload-loaders.lua
+++ b/macros/luatex/generic/luaotfload/luaotfload-loaders.lua
@@ -8,8 +8,8 @@
local ProvidesLuaModule = {
name = "luaotfload-loaders",
- version = "3.00", --TAGVERSION
- date = "2019-09-13", --TAGDATE
+ version = "3.1", --TAGVERSION
+ date = "2019-11-04", --TAGDATE
description = "luaotfload submodule / callback handling",
license = "GPL v2.0"
}
@@ -27,17 +27,8 @@ if not luaotfload then error "this module requires Luaotfload" end
local logreport = luaotfload.log and luaotfload.log.report or print
local lua_reader = function (specification)
- local fullname = specification.filename or ""
- if fullname == "" then
- local forced = specification.forced or ""
- if forced ~= "" then
- fullname = specification.name .. "." .. forced
- else
- fullname = specification.name
- end
- end
- local fullname = resolvers.findfile (fullname) or ""
- if fullname ~= "" then
+ local fullname = specification.resolved
+ if fullname then
local loader = loadfile (fullname)
loader = loader and loader ()
return loader and loader (specification)
diff --git a/macros/luatex/generic/luaotfload/luaotfload-log.lua b/macros/luatex/generic/luaotfload/luaotfload-log.lua
index 04012632fa..e6bb042b4f 100644
--- a/macros/luatex/generic/luaotfload/luaotfload-log.lua
+++ b/macros/luatex/generic/luaotfload/luaotfload-log.lua
@@ -6,8 +6,8 @@
local ProvidesLuaModule = {
name = "luaotfload-log",
- version = "3.00", --TAGVERSION
- date = "2019-09-13", --TAGDATE
+ version = "3.1", --TAGVERSION
+ date = "2019-11-04", --TAGDATE
description = "luaotfload submodule / logging",
license = "GPL v2.0",
author = "Khaled Hosny, Elie Roux, Philipp Gesang",
@@ -220,16 +220,16 @@ else
end
end
-stdout = function (writer, category, ...)
+local stdout = function (writer, category, ...)
local res = { module_name, "|", category, ":" }
local nargs = select("#", ...)
if nargs == 0 then
--writeln tableconcat(res, " ")
--return
elseif nargs == 1 then
- res[#res+1] = select(1, ...) -- around 30% faster than unpack()
+ res[5] = ... -- around 30% faster than unpack()
else
- res[#res+1] = stringformat(...)
+ res[5] = stringformat(...)
end
writer (tableconcat(res, " "))
end
diff --git a/macros/luatex/generic/luaotfload/luaotfload-main.lua b/macros/luatex/generic/luaotfload/luaotfload-main.lua
index 26bbfab506..d17a1d9b26 100644
--- a/macros/luatex/generic/luaotfload/luaotfload-main.lua
+++ b/macros/luatex/generic/luaotfload/luaotfload-main.lua
@@ -20,8 +20,8 @@ local authors = "\z
-- version number is used below!
local ProvidesLuaModule = {
name = "luaotfload-main",
- version = "3.00", --TAGVERSION
- date = "2019-09-13", --TAGDATE
+ version = "3.1", --TAGVERSION
+ date = "2019-11-04", --TAGDATE
description = "luaotfload entry point",
author = authors,
copyright = authors,
@@ -142,12 +142,12 @@ local timing_info = {
t_init = { },
}
-local make_loader = function (prefix)
+local make_loader = function (prefix, load_helper)
return function (name)
local t_0 = osgettimeofday ()
local modname = make_loader_name (prefix, name)
--- We don’t want the stack info from inside, so just pcall().
- local ok, data = pcall (require, modname)
+ local ok, data = pcall (load_helper or require, modname)
local t_end = osgettimeofday ()
timing_info.t_load [name] = t_end - t_0
if not ok then
@@ -190,6 +190,16 @@ local dummy_loader = function (name)
name)
end
+local context_environment = setmetatable({}, {__index = _G})
+luaotfload.fontloader = context_environment
+local function context_isolated_load(name)
+ local fullname = kpse.find_file(name, 'lua')
+ if not fullname then
+ error(string.format('Fontloader module "%s" could not be found.', name))
+ end
+ return assert(loadfile(fullname, nil, context_environment))(name)
+end
+
local context_loader = function (name, path)
luaotfload.log.report ("log", 3, "load",
"Loading module “%s” from Context.",
@@ -209,7 +219,7 @@ local context_loader = function (name, path)
path)
end
end
- local ret = require (modpath)
+ local ret = context_isolated_load (modpath)
local t_end = osgettimeofday ()
timing_info.t_load [name] = t_end - t_0
@@ -228,7 +238,7 @@ local install_loaders = function ()
local loaders = { }
local loadmodule = make_loader "luaotfload"
loaders.luaotfload = loadmodule
- loaders.fontloader = make_loader "fontloader"
+ loaders.fontloader = make_loader ("fontloader", context_isolated_load)
loaders.context = context_loader
loaders.ignore = dummy_loader
----loaders.plaintex = make_loader "luatex" --=> for Luatex-Plain
@@ -275,15 +285,13 @@ luaotfload.main = function ()
local starttime = osgettimeofday ()
local init = loadmodule "init" --- fontloader initialization
- local store = init.early () --- injects the log module too
- local logreport = luaotfload.log.report
+ init (function ()
- initialize "parsers" --- fonts.conf and syntax
- initialize "configuration" --- configuration options
+ initialize "parsers" --- fonts.conf and syntax
+ initialize "configuration" --- configuration options
+ end)
- if not init.main (store) then
- logreport ("log", 0, "load", "Main fontloader initialization failed.")
- end
+ local logreport = luaotfload.log.report
initialize "loaders" --- Font loading; callbacks
initialize "database" --- Font management.
@@ -297,11 +305,19 @@ luaotfload.main = function ()
end
initialize "features" --- font request and feature handling
+
loadmodule "letterspace" --- extra character kerning
loadmodule "embolden" --- fake bold
loadmodule "notdef" --- missing glyph handling
+ local harfstatus, harfbuzz = pcall(require, 'luaharfbuzz')
+ if harfstatus then
+ luaotfload.harfbuzz = harfbuzz
+ loadmodule "harf-define"
+ loadmodule "harf-plug"
+ end
initialize "auxiliary" --- additional high-level functionality
loadmodule "multiscript" --- ...
+ loadmodule "tounicode"
luaotfload.aux.start_rewrite_fontname () --- to be migrated to fontspec
diff --git a/macros/luatex/generic/luaotfload/luaotfload-main.tex b/macros/luatex/generic/luaotfload/luaotfload-main.tex
index 8fdb4048ad..dbc8d73e7d 100644
--- a/macros/luatex/generic/luaotfload/luaotfload-main.tex
+++ b/macros/luatex/generic/luaotfload/luaotfload-main.tex
@@ -32,11 +32,10 @@
\beginfrontmatter
\setdocumenttitle {The \identifier{luaotfload} package}
- \setdocumentdate {2019-09-13 v3.00}
- \setdocumentauthor {Elie Roux · Khaled Hosny · Philipp Gesang · Ulrike Fischer\\
- Home: \hyperlink {https://github.com/lualatex/luaotfload}\\
- New Home: \hyperlink {https://github.com/u-fischer/luaotfload}\\
- Support: \email {lualatex-dev@tug.org}}
+ \setdocumentdate {2019-11-04 v3.1}
+ \setdocumentauthor {LaTeX3 Project\\
+ Elie Roux · Khaled Hosny · Philipp Gesang · Ulrike Fischer · Marcel Krüger\\
+ Home: \hyperlink {https://github.com/latex3/luaotfload}}
\typesetdocumenttitle
@@ -55,34 +54,56 @@
\pdfbookmark[1]{\contentsname}{table}
\typesetcontent
-\beginsection {New in version 3.00 (by Ulrike Fischer/Marcel Krüger)}
+\beginsection {Engine and version support}
+\identifier{luaotfload} is a quite large and complex package. It imports code from context which is actively developed along with the luatex binary. It is not possible
+to support a large number of engines variants or versions.
+
+Supported is the \identifier{luatex} versions of a current TeXLive 2019 (and a current MiKTeX). Beginning with version 3.1 of this package also \identifier{luahbtex} is supported.
+\endsection
+
+\beginsection{Changes}
+\beginsubsection {New in version 3.1 (by Ulrike Fischer/Marcel Krüger)}
+\begin{itemize}
+\item The package has been moved to the github of the LaTeX3 Project and is now maintained
+ officially by the LaTeX3 Project team.
+\item Code to use the harfbuzz library of luahbtex has been added. See the description of the harf mode.
+\item fonts in ttc-collections can now be indexed by name.
+\item To reduce the polution of the global lua enviroment a number of lua tables have been removed.
+ Only the tables \identifier{luaotfload}, \identifier{fonts} and \identifier{nodes} have been kept there.
+\item The fontloader has been synched with the context files from 2019-10-29.
+
+\end{itemize}
+\endsubsection
+
+
+\beginsubsection {New in version 3.00 (by Ulrike Fischer/Marcel Krüger)}
\begin{itemize}
\item Default Ignorable characters are now invisible by default (issue 63). This can be deactivated with the option \texttt{invisible}.
\end{itemize}
-\endsection
+\endsubsection
-\beginsection {New in version 2.99 (by Ulrike Fischer)}
+\beginsubsection {New in version 2.99 (by Ulrike Fischer)}
\begin{itemize}
\item Code cleanup.
\item The fontloader has been synched with the context files from 2019-08-11.
\end{itemize}
-\endsection
-\beginsection {New in version 2.98 (by Ulrike Fischer)}
+\endsubsection
+\beginsubsection {New in version 2.98 (by Ulrike Fischer)}
\begin{itemize}
\item The\marginpar{\mbox{}\hfill \textbf{breaking change!}} handling of missing chars has been changed. In This version a missing char will insert the \inlinecode{/.notdef} char of the fonts (this is sometimes a space, sometimes a rectangle with a cross) and no longer simply ignore the glyph. This behaviour can be reverted by using \inlinecode{notdef=false} as font feature.
\item The font feature \inlinecode{embolden} can now be used to fake a bold font.
\item The fontloader has been synched with the context files from 2019-07-04.
\end{itemize}
-\endsection
-\beginsection {New in version 2.97 (by Ulrike Fischer)}
+\endsubsection
+\beginsubsection {New in version 2.97 (by Ulrike Fischer)}
\begin{itemize}
\item the new generic fontloader improves the handling of large fonts (but some fonts still need a 64bit luatex version to create the font files).
\item A number of small bug (also in luaotfload-tool) have been corrected, see the NEWS file for details.
\end{itemize}
-\endsection
+\endsubsection
-\beginsection {New in version 2.96 (by Ulrike Fischer)}
+\beginsubsection {New in version 2.96 (by Ulrike Fischer)}
\begin{itemize}
\item In\marginpar{\mbox{}\hfill \textbf{Incompatible change!}}
version 2.95 letterspacing was broken due to a change in the fontloader (issue 38). This has been repaired. At the same time a number of oddities and bugs in the letterspacing has been corrected. This can change existing documents. See page~\pageref{p:letterspace} for more information.
@@ -90,11 +111,11 @@ version 2.95 letterspacing was broken due to a change in the fontloader (issue 3
\item A problem with the detection of bold fonts has been corrected (issue 41, pull request 42).
\end{itemize}
-\endsection
+\endsubsection
-\beginsection {New in version 2.95 (by Ulrike Fischer)}
+\beginsubsection {New in version 2.95 (by Ulrike Fischer)}
\begin{itemize}
\item
This version imports from context the generic fontloader in the version of 2019-01-28. Contrary to the last announcement, it still works with luatex 1.07. So updates will continue.
@@ -106,8 +127,8 @@ This version imports from context the generic fontloader in the version of 2019-
\item The resolver code has be refactorated (pull request 36).
\end{itemize}
-\endsection
-\beginsection {New in version 2.94 (by Ulrike Fischer)}
+\endsubsection
+\beginsubsection {New in version 2.94 (by Ulrike Fischer)}
\begin{itemize}
\item
This version imports from context the generic fontloader in the version of 2018-12-19. It is the last version that works with luatex 1.07 and texlive 2018. As context has moved to luatex 1.09 newer versions of the fontloader needs now this luatex version too. This means that until the texlive 2018 freeze there will be probably no update of luaotfload.
@@ -116,13 +137,13 @@ This version imports from context the generic fontloader in the version of 2018-
\end{itemize}
-\endsection
+\endsubsection
-\beginsection {New in version 2.93 (by Ulrike Fischer)}
+\beginsubsection {New in version 2.93 (by Ulrike Fischer)}
Mainly internal clean up of the version info to allow automatic versioning.
-\endsection
+\endsubsection
-\beginsection {New in version 2.92 (by Ulrike Fischer)}
+\beginsubsection {New in version 2.92 (by Ulrike Fischer)}
\begin{itemize}
@@ -131,15 +152,15 @@ Mainly internal clean up of the version info to allow automatic versioning.
\item The syntax \inlinecode{file:} for legacy font works again (issue \#11).
\item The fontloader has been synched with the newest context version from october, 18.
\end{itemize}
-\endsection
-\beginsection {New in version 2.91 (by Ulrike Fischer)}
+\endsubsection
+\beginsubsection {New in version 2.91 (by Ulrike Fischer)}
This version mostly correct two bugs found in the previous fontloader: Glyphvariants weren't copied and pasted correctly. Glyphs encoded in the PUA couldn't be accessed anymore.
-\endsection
+\endsubsection
-\beginsection {New in version 2.9 (by Ulrike Fischer)}
+\beginsubsection {New in version 2.9 (by Ulrike Fischer)}
On the one side there is not very much new in this version: The native components of \identifier{Luaotfload} are nearly unchanged. A few bugs have been corrected, the various files lists which loads the components of the font loader have been cleaned up.
@@ -154,7 +175,7 @@ On the other side there is a lot new:
\beginaltitem {Lualibs} The update of the fontloader files also required an update of the \identifier{Lualibs} package. This \identifier{Luaotfload} version needs version 2.6 of \identifier{Lualibs}.
\endaltitem
- \beginaltitem {Maintenance} As the current maintainer wasn't available and it was urgent to get a \identifier{Luaotfload} compatible with \LUATEX 1.08/1.09 maintenance has been transfered to Ulrike Fischer and Marcel Krüger. The package is currently maintained and developed at \hyperlink{https://github.com/u-fischer/luaotfload}. Issues should be reported there.
+ \beginaltitem {Maintenance} As the current maintainer wasn't available and it was urgent to get a \identifier{Luaotfload} compatible with \LUATEX 1.08/1.09 maintenance has been transfered to Ulrike Fischer and Marcel Krüger. The package was maintained and developed at \hyperlink{https://github.com/u-fischer/luaotfload}. Issues should be reported there.
\endaltitem
\beginaltitem {Documentation}
@@ -163,6 +184,7 @@ On the other side there is a lot new:
\enddescriptions
+\endsubsection
\endsection
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\beginsection {Introduction}
@@ -181,11 +203,8 @@ These fonts can contain many more characters than \TEX fonts, as well
as additional functionality like ligatures, old-style numbers, small
capitals, etc., and support more complex writing systems like Arabic
and Indic\footnote{%
- Unfortunately, \identifier{luaotfload} doesn‘t support many Indic
- scripts right now.
- Assistance in implementing the prerequisites is greatly
- appreciated.
-}
+ Unfortunately, the default fontloader of \identifier{luaotfload} doesn‘t support many Indic
+ scripts correctly. For these scripts it is recommended to use the harf mode along with the binary \identifier{luahbtex}.}
scripts.
\OpenType fonts are widely deployed and available for all modern
@@ -382,7 +401,7 @@ where \meta{prefix} is either \inlinecode{file:} or \inlinecode {name:}.\footnot
%
For a working example see the
\hyperlink [test in the luaotfload
- repo]{https://github.com/u-fischer/luaotfload/blob/master/testfiles/my-resolver.lvt}.
+ repo]{https://github.com/latex3/luaotfload/blob/master/testfiles/my-resolver.lvt}.
}
%
It determines whether the font loader should interpret the request as
@@ -563,8 +582,8 @@ non-standard directory:
\identifier{TrueType} collection files (the extension is usually
\inlinecode{.ttc}) contain more than a single font. In order to refer to these
-subfonts, the respective index may be added in parentheses after the file
-name.\footnote{%
+subfonts, the respective index or the respective PostScript font name may be
+added in parentheses after the file name.\footnote{%
Incidentally, this syntactical detail also prevents one from loading files
that end in balanced parentheses.
}
@@ -572,6 +591,8 @@ name.\footnote{%
\beginlisting
\font \cambriamain = "file:cambria.ttc(0)" at 10pt
\font \cambriamath = "file:cambria.ttc(1)" at 10pt
+ \font \Cambriamain = "file:cambria.ttc(Cambria)" at 10pt
+ \font \Cambriamath = "file:cambria.ttc(CambriaMath)" at 10pt
\endlisting
and likewise, requesting subfont inside a TTC container by path:
@@ -721,10 +742,9 @@ obviously, \inlinecode{random}.
\begindescriptions
\beginaltitem {mode}
- Until version 2.94
- \identifier{luaotfload} had two \OpenType processing
+ \identifier{luaotfload} had three \OpenType processing
\emphasis{modes}:
- \identifier{base} and \identifier{node}.
+ \identifier{base}, \identifier{node} and \identifier{harf}.
\identifier{base} mode works by mapping \OpenType
features to traditional \TEX ligature and kerning mechanisms.
@@ -744,12 +764,42 @@ obviously, \inlinecode{random}.
mode, and \identifier{base} mode has to be requested where needed,
e.~g. for math fonts.
- Since version 2.94 it is possible to call other font renderers with the mode key. A simple example with a plain reader can be found at \hyperlink{https://github.com/u-fischer/luaotfload/pull/26\#issuecomment-437716326}.
- A more useful example needs the new experimental harftex engine (windows binaries can be found at w32tex.org), and the harf renderer (\hyperlink{https://github.com/khaledhosny/harf}). With both it is possible to render a font using the harfbuzz library (used also by xetex).
+ \identifier{harf} mode is new in version 3.1 and needs the new \identifier{luahbtex} engine (the mode is ignored if \identifier{luahbtex} is not used). With it is possible to render a font using the harfbuzz library in-built in the new engine. \identifier{harf} mode improves greatly the rendering of indic and arabic scripts and is highly recommended for such scripts.
+
+ When using \identifier{harf} mode it is required to set also the script correctly:
+
+
+ \beginlisting
+ \font\burmesefont={file:NotoSerifMyanmar-Regular.ttf:mode=harf;script=mymr;}
+ \font\devafont={file:NotoSansDevanagari-Regular.ttf:mode=harf;script=deva;}
+ \font\banglafont={name:Noto Sans Bengali:mode=harf;script=beng;}
+ \font\tibetanfont={name:Noto Serif Tibetan:mode=harf;script=tibt;}
+ \endlisting
+ \includegraphics{scripts-demo}
+
+
+ It is possible to call other font renderers with the mode key. A simple example with a plain reader can be found at \url{https://github.com/latex3/luaotfload/pull/26#issuecomment-437716326}.
\endaltitem
+ \beginaltitem {shaper} \label{shaper-tag}
+ If \identifier{luahbtex} and \identifier{harf} mode are used it is possible to specify a shaper, like \identifier{graphite2} or \identifier{ot} (open type).
+
+ \beginlisting
+ \pardir TRT\textdir TRT
+ \font\test={file:AwamiNastaliq-Regular.ttf:mode=harf;shaper=ot}
+ \endlisting
+
+ \includegraphics{shaper-demo}
+
+ \beginlisting
+ \pardir TRT\textdir TRT
+ \font\test={file:AwamiNastaliq-Regular.ttf:mode=harf;shaper=graphite2}
+ \endlisting
+
+ \includegraphics{shaper-demo-graphite}
+ \endaltitem
\beginaltitem {script} \label{script-tag}
An \OpenType script tag;\footnote{%
See \hyperlink {http://www.microsoft.com/typography/otspec/scripttags.htm}
@@ -948,7 +998,7 @@ obviously, \inlinecode{random}.
\font \test = LatinModernRoman:protrusion=default
\endlisting
\endaltitem
-
+
\beginaltitem {invisible}
Default Ignorable characters are control characters that should be invisible by default even if the font has glyphs for them. Since version 3.0 luaotfload makes them invisible, this can be switch on and off with the \texttt{invisible}. By default it is on.
@@ -960,16 +1010,16 @@ obviously, \inlinecode{random}.
\endlisting
{\font\amiri={file:amiri-regular.ttf} at 20pt \amiri \char"200Dي\char"200D}
-
+
\beginlisting
\font\amiri={file:amiri-regular.ttf:-invisible;} at 20pt \amiri
\char"200Dي\char"200D
\endlisting
{\font\amiri={file:amiri-regular.ttf:-invisible;} at 20pt \amiri \char"200Dي\char"200D}
-
- \endaltitem
+
+ \endaltitem
\enddescriptions
\endsubsection
diff --git a/macros/luatex/generic/luaotfload/luaotfload-multiscript.lua b/macros/luatex/generic/luaotfload/luaotfload-multiscript.lua
index ed3aef05c3..56d381a911 100644
--- a/macros/luatex/generic/luaotfload/luaotfload-multiscript.lua
+++ b/macros/luatex/generic/luaotfload/luaotfload-multiscript.lua
@@ -5,8 +5,8 @@
local ProvidesLuaModule = {
name = "luaotfload-multiscript",
- version = "3.00", --TAGVERSION
- date = "2019-09-13", --TAGDATE
+ version = "3.1", --TAGVERSION
+ date = "2019-11-04", --TAGDATE
description = "luaotfload submodule / multiscript",
license = "GPL v2.0",
author = "Marcel Krüger"
diff --git a/macros/luatex/generic/luaotfload/luaotfload-notdef.lua b/macros/luatex/generic/luaotfload/luaotfload-notdef.lua
index 0cc972a0e3..53f4af8e3a 100644
--- a/macros/luatex/generic/luaotfload/luaotfload-notdef.lua
+++ b/macros/luatex/generic/luaotfload/luaotfload-notdef.lua
@@ -5,8 +5,8 @@
local ProvidesLuaModule = {
name = "luaotfload-notdef",
- version = "3.00", --TAGVERSION
- date = "2019-09-13", --TAGDATE
+ version = "3.1", --TAGVERSION
+ date = "2019-11-04", --TAGDATE
description = "luaotfload submodule / color",
license = "GPL v2.0",
author = "Marcel Krüger"
diff --git a/macros/luatex/generic/luaotfload/luaotfload-parsers.lua b/macros/luatex/generic/luaotfload/luaotfload-parsers.lua
index f9fd5c919e..4a2d6305e1 100644
--- a/macros/luatex/generic/luaotfload/luaotfload-parsers.lua
+++ b/macros/luatex/generic/luaotfload/luaotfload-parsers.lua
@@ -7,8 +7,8 @@
local ProvidesLuaModule = {
name = "luaotfload-parsers",
- version = "3.00", --TAGVERSION
- date = "2019-09-13", --TAGDATE
+ version = "3.1", --TAGVERSION
+ date = "2019-11-04", --TAGDATE
description = "luaotfload submodule / filelist",
license = "GPL v2.0"
}
@@ -603,7 +603,9 @@ local combolist = Ct(combodef1 * (comborowsep * combodef)^1)
--- Note to self: subfonts apparently start at index 0. Tested with
--- Cambria.ttc that includes “Cambria Math” at 0 and “Cambria” at 1.
--- Other values cause luatex to segfault.
-local subfont = P"(" * Cg((1 - S"()")^1, "sub") * P")"
+local subfont = P"(" * Cg(R'09'^1 / function (s)
+ return tonumber(s) + 1
+ end + (1 - S"()")^1, "sub") * P")"
--- lookups -----------------------------------------------------------
local fontname = C((1-S":(/")^1) --- like luatex-fonts
diff --git a/macros/luatex/generic/luaotfload/luaotfload-resolvers.lua b/macros/luatex/generic/luaotfload/luaotfload-resolvers.lua
index 5146f1d20e..97e85f0a41 100644
--- a/macros/luatex/generic/luaotfload/luaotfload-resolvers.lua
+++ b/macros/luatex/generic/luaotfload/luaotfload-resolvers.lua
@@ -11,8 +11,8 @@
local ProvidesLuaModule = {
name = "luaotfload-resolvers",
- version = "3.00", --TAGVERSION
- date = "2019-09-13", --TAGDATE
+ version = "3.1", --TAGVERSION
+ date = "2019-11-04", --TAGDATE
description = "luaotfload submodule / resolvers",
license = "GPL v2.0"
}
@@ -148,11 +148,12 @@ end
local tex_formats = { "tfm", "ofm" }
+local resolvers_findfile = luaotfload.fontloader.resolvers.findfile
local resolve_tex_format = function (specification)
local name = specification.name
for i=1, #tex_formats do
local format = tex_formats [i]
- local resolved = resolvers.findfile(name, format)
+ local resolved = resolvers_findfile(name, format)
if resolved then
return resolved, format
end
@@ -241,6 +242,7 @@ local function resolve_kpse (specification)
end
end
+local lookup_subfont_index = fonts.names.lookup_subfont_index
local function wrap_resolver(resolver)
return function (specification)
local filename, sub, forced = resolver(specification)
@@ -253,6 +255,10 @@ local function wrap_resolver(resolver)
specification.filename = filename
specification.name = filename
specification.sub = sub or specification.sub
+ if type(specification.sub) == "string" then
+ specification.sub =
+ lookup_subfont_index(filename, specification.sub)
+ end
specification.forced = specification.forced or forced
if not specification.forced then
local suffix = stringlower (filesuffix (filename))
diff --git a/macros/luatex/generic/luaotfload/luaotfload-status.lua b/macros/luatex/generic/luaotfload/luaotfload-status.lua
index 69948c43ca..3221986ca7 100644
--- a/macros/luatex/generic/luaotfload/luaotfload-status.lua
+++ b/macros/luatex/generic/luaotfload/luaotfload-status.lua
@@ -1,18 +1,18 @@
return {
["hashes"]={
- { "fontloader-2019-08-11.lua", "9ad89bd01fccf2f98b8777ad42851c58" },
+ { "fontloader-2019-10-29.lua", "8b7d755e08cfef0826429ffa68271eb3" },
{ "fontloader-util-fil.lua", "4bb3e4dc72e308d8ed67cd7a80027fa7" },
- { "fontloader-util-str.lua", "3c829af0b336703e62cb5a1cb7a6e503" },
- { "fontloader-l-unicode.lua", "d46cc6cf18fb3f368ef1e404dc9fcb5c" },
+ { "fontloader-util-str.lua", "fc15d89c4c35f7338d09fc7644fac181" },
+ { "fontloader-l-unicode.lua", "9bc311ce08ce498f9caacb6164ea1d9f" },
{ "fontloader-l-math.lua", "a373be3ed2db0d5f98588fa81abca48f" },
{ "fontloader-l-boolean.lua", "18ed6c4b2c40dd87224ea33229548d20" },
{ "fontloader-l-file.lua", "3d6ea476061292a0da98c3f65cdabe46" },
{ "fontloader-l-io.lua", "42608ad95eb2822fdc370d1c11f08fb5" },
- { "fontloader-l-table.lua", "63b13279139d2f94d29238b0d6242330" },
+ { "fontloader-l-table.lua", "9844897b04a01bb197427d71de71de2b" },
{ "fontloader-l-string.lua", "e1347bef0eeeff9f098df83b30b32df9" },
{ "fontloader-l-function.lua", "f771cc91839ebcdfc094083434fbe00f" },
- { "fontloader-l-lpeg.lua", "a5364ddabb490408da9276ea7f7a7ba1" },
- { "fontloader-l-lua.lua", "9e5e9d4f3b8f9e337f28aa2322192b94" },
+ { "fontloader-l-lpeg.lua", "efe630e3a9a1d269120e59cfd8fba4ba" },
+ { "fontloader-l-lua.lua", "dda8438a34886bb767dbad381f1ea70a" },
{ "fontloader-fonts-gbn.lua", "d25472d54c4841db43a745764a63533e" },
{ "fontloader-fonts-lig.lua", "b9dbe77ce747d4c35bb2a20ffbe5aa51" },
{ "fontloader-fonts-ext.lua", "01015ab3758cdc2af29394e6d502a91a" },
@@ -21,7 +21,7 @@ return {
{ "fontloader-fonts-enc.lua", "3e71a54297e8f85a1ac438bb0f20dd79" },
{ "fontloader-fonts-mis.lua", "bc9eb43c27f63ce9d0fff67e104fe1c6" },
{ "fontloader-basics-chr.lua", "58b7ef0c486e06090b362971b9f85e27" },
- { "fontloader-basics-nod.lua", "65064d03c2650a1761ee13ebd9e1400a" },
+ { "fontloader-basics-nod.lua", "c05f47077c709bbf12a8758852dc4e06" },
{ "fontloader-font-imp-effects.lua", "73a660359a0ec71e44cc2b7225a715ac" },
{ "fontloader-font-imp-italics.lua", "fe1ca80fb5ea4a2f8d2d5c484e7ba913" },
{ "fontloader-font-imp-ligatures.lua", "043daa4fcccf2560868da359d71d3a4a" },
@@ -31,16 +31,16 @@ return {
{ "fontloader-font-afk.lua", "54d554530e75c57c56ee76234724e26d" },
{ "fontloader-font-one.lua", "987c5c5ed3754ad2feab80985067d59e" },
{ "fontloader-font-onr.lua", "d4d2449b4084e6afb1837ae5835082cc" },
- { "fontloader-font-otc.lua", "95a4ff28ba4afb55a978a4aecfd688bf" },
- { "fontloader-font-ocl.lua", "b720867fb19a23f0b50377efd2a3c54a" },
- { "fontloader-font-osd.lua", "79eb2fc4a71364fd73c8b996a109f5df" },
- { "fontloader-font-ots.lua", "d5504847a278385cd0d20ecf1b3d59cc" },
+ { "fontloader-font-otc.lua", "1204a2fdc436e644127c0aa38ab69607" },
+ { "fontloader-font-ocl.lua", "ba40df1a92b9b42a5c70d20c28f44759" },
+ { "fontloader-font-osd.lua", "39e92f6e575741646d75ea79e3be87f3" },
+ { "fontloader-font-ots.lua", "d6a0ce4b40cd4ee1895e2248dcf87d37" },
{ "fontloader-font-ota.lua", "d6dfb94563d6a52675e274b2e673e4a6" },
{ "fontloader-font-otj.lua", "66c7a910d95d4a52b81061de776898e1" },
{ "fontloader-font-oto.lua", "52804afd96f4be005f513a012b874668" },
- { "fontloader-font-otl.lua", "940f9c5ad84f4968a8488f4da2d15e2d" },
- { "fontloader-font-oup.lua", "669e479e716999edc626a1f045bd76fa" },
- { "fontloader-font-dsp.lua", "b5bf2f1c198e027a0d4ededcdf3947b4" },
+ { "fontloader-font-otl.lua", "ec0241b7465a7713e53c246e8e9fb2a8" },
+ { "fontloader-font-oup.lua", "0cef35af01739f52fd09feb5401192ae" },
+ { "fontloader-font-dsp.lua", "5d3db0184c903829b2c5bddcb8cdb14c" },
{ "fontloader-font-ttf.lua", "44e61cef50dab9b1aaf48130f9367c34" },
{ "fontloader-font-cff.lua", "98d5a660ea803b65cb883c009ecf3c0b" },
{ "fontloader-font-ott.lua", "aba6d8335a5f38a5a62d3631492f3392" },
@@ -49,43 +49,46 @@ return {
{ "fontloader-font-vfc.lua", "94937140f2c909e9c831ba021f1ab303" },
{ "fontloader-font-map.lua", "f486746e90fe972de4b73e208ac7cbb2" },
{ "fontloader-font-cid.lua", "4d87988efa86020a14708ee03c23415f" },
- { "fontloader-font-con.lua", "ca733211a0555d9a93b1e2f7ebc937d3" },
+ { "fontloader-font-con.lua", "8b35e7c2203d5b57c61942e07cee2c0a" },
{ "fontloader-font-ini.lua", "4299a02110bbd7c0d27e131235c5319d" },
{ "fontloader-data-con.lua", "7ce546725b1550f655c78ac9d69419ca" },
- { "fontloader-reference.lua", "759787e7ee75437382c0a2c4f8fe3b81" },
+ { "fontloader-reference.lua", "5be3565068a1929b173bde862b48a30e" },
{ "fontloader-basics-gen.lua", "b21e91bbd534f77e368f0ec13f865aed" },
{ "mktests", "c7cff7025962922944376acc1ffa9c47" },
- { "mkstatus", "64b9a6b302168fced414830a53fdcce1" },
+ { "mkstatus", "32b8eee5316ca3100e4434db79d08230" },
{ "mkcharacters", "92c24bb582fc84c0365634f29eb89863" },
{ "mkglyphlist", "557836886d4f0e6d656eac3ded4456a2" },
{ "mkimport", "60e0b11a1a68719033e86a3e0f4d5e86" },
- { "luaotfload-glyphlist.lua", "df822678061548ce6b510a0c1c7fc103" },
+ { "luaotfload-glyphlist.lua", "6dc41351ebdb122e044bed6d3fc2ca4b" },
{ "luaotfload-characters.lua", "593ce9dccf6ddc4f7d4be0514f581102" },
- { "luaotfload-unicode.lua", "d9ce2f2a07e951be6310e85fdfcc785d" },
- { "luaotfload-resolvers.lua", "0b0d407501e68537971484ac2256af20" },
- { "luaotfload-parsers.lua", "9b199d5157d9972c415aee7f9350df5b" },
- { "luaotfload-multiscript.lua", "3a4cfa1687c9d1694cbf728183bb066e" },
- { "luaotfload-loaders.lua", "007be1e29cf23779f4d9d0097b56cc4a" },
- { "luaotfload-notdef.lua", "982810e9197d2261ffdc3acd5d8dcecf" },
- { "luaotfload-embolden.lua", "92dfba7dbf10484c85f7e3c971691f8e" },
- { "luaotfload-letterspace.lua", "bb123f78712cc0342419f3c2a5f6a940" },
- { "luaotfload-features.lua", "45ab2c6405c678f8834339fe0d9fb47a" },
- { "luaotfload-database.lua", "da3c5b55a086a2213ee825ecc2bf7e0f" },
- { "luaotfload-configuration.lua", "015022f5b9597254afafff26f9f0f98c" },
- { "luaotfload-colors.lua", "81a23496c5f5c855674b05180869b8cf" },
- { "luaotfload-auxiliary.lua", "81432ebaebfce3df73b5949e1001d13c" },
- { "luaotfload-filelist.lua", "aa3c9fa695042573d6f6c2e5d0c23558" },
- { "luaotfload-tool.lua", "1833a47868c3e5958d492bb947d39dec" },
- { "luaotfload-diagnostics.lua", "53dbf51623658f1e325d2e6279a2ee15" },
- { "luaotfload-log.lua", "30491ef5890898d5ae3af44f72e82b1f" },
- { "luaotfload-init.lua", "479854a620629b1934d16723aa4cae0c" },
- { "luaotfload-main.lua", "95c7d3ce348ac83e0659f7332e98eacc" },
+ { "luaotfload-tounicode.lua", "b87cab857631c47f5c2bbfa4dc1b5598" },
+ { "luaotfload-unicode.lua", "eaf637834d735afce54cf81721b89626" },
+ { "luaotfload-resolvers.lua", "7bcd23bf0c4079174679f61c315f54ed" },
+ { "luaotfload-parsers.lua", "23b0550fcc6bf872714d882b8d15f465" },
+ { "luaotfload-multiscript.lua", "bd0b25f9b9b21ad1e1a24fb88dc5cdbf" },
+ { "luaotfload-loaders.lua", "34d130aa4e365639baecfa0481e34d13" },
+ { "luaotfload-harf-plug.lua", "59429664d9bebfbf0e0bfa8a8bdd85e3" },
+ { "luaotfload-harf-define.lua", "f0aafaecaddbc43f665a076195ed9205" },
+ { "luaotfload-notdef.lua", "ce00644d5801c6fac2e274626a52ecf2" },
+ { "luaotfload-embolden.lua", "7ff4b7e2970f2748a4d881b23085495d" },
+ { "luaotfload-letterspace.lua", "2b24d57529363de4a004510da84bafd9" },
+ { "luaotfload-features.lua", "b8c279955bcc473f02ad77b46942eb29" },
+ { "luaotfload-database.lua", "131587572dcf49769bec7e085ab61281" },
+ { "luaotfload-configuration.lua", "a59a94e07e20998144c91d5eb44b9302" },
+ { "luaotfload-colors.lua", "c13f4c88058e2c4869205ad015765070" },
+ { "luaotfload-auxiliary.lua", "77bcb55f9d215ad8a61701dc64e9a07e" },
+ { "luaotfload-filelist.lua", "96967c2f4ad091f2a8c74a50294c25d5" },
+ { "luaotfload-tool.lua", "9a53d4aedf71012530be90303aabe0d9" },
+ { "luaotfload-diagnostics.lua", "f521a2b70b24bd23fb23d3d08d7845bf" },
+ { "luaotfload-log.lua", "28c5c63d7af789ab7ca5757870dfc595" },
+ { "luaotfload-init.lua", "ebb2e936d4c95cab76649897f6af0e25" },
+ { "luaotfload-main.lua", "e4208f459c12b57a6996b4c7e9adbb8b" },
},
["notes"]={
- ["committer"]="Marcel Fabian Krüger <tex@2krueger.de>",
- ["description"]="v3.00/2019-09-13",
- ["loader"]="fontloader-2019-08-11.lua",
- ["revision"]="e758f5d39e3d416e4bc1e2a23918abed744563ae",
- ["timestamp"]="2019-09-13 00:43:25 +0200",
+ ["committer"]="Ulrike Fischer <fischer@troubleshooting-tex.de>",
+ ["description"]="v3.1/2019-11-04",
+ ["loader"]="fontloader-2019-10-29.lua",
+ ["revision"]="cdc212ae76bc0f839d116c8f66af98445ba9f307",
+ ["timestamp"]="2019-11-03 15:29:57 +0100",
},
} \ No newline at end of file
diff --git a/macros/luatex/generic/luaotfload/luaotfload-tool.1 b/macros/luatex/generic/luaotfload/luaotfload-tool.1
index 3636d2f6e6..c2d754baa3 100644
--- a/macros/luatex/generic/luaotfload/luaotfload-tool.1
+++ b/macros/luatex/generic/luaotfload/luaotfload-tool.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH LUAOTFLOAD-TOOL 1 "2019-09-13" "3.00" "text processing"
+.TH LUAOTFLOAD-TOOL 1 "2019-11-04" "3.1" "text processing"
.SH NAME
luaotfload-tool \- generate and query the Luaotfload font names database
.
diff --git a/macros/luatex/generic/luaotfload/luaotfload-tool.lua b/macros/luatex/generic/luaotfload/luaotfload-tool.lua
index 06729778f4..12bf2b3a42 100644
--- a/macros/luatex/generic/luaotfload/luaotfload-tool.lua
+++ b/macros/luatex/generic/luaotfload/luaotfload-tool.lua
@@ -9,8 +9,8 @@
local ProvidesLuaModule = {
name = "luaotfload-tool",
- version = "3.00", --TAGVERSION
- date = "2019-09-13", --TAGDATE
+ version = "3.1", --TAGVERSION
+ date = "2019-11-04", --TAGDATE
description = "luaotfload-tool / database functionality",
license = "GPL v2.0"
}
@@ -25,6 +25,7 @@ local version = ProvidesLuaModule.version
luaotfload.version = ProvidesLuaModule.version
luaotfload.min_luatex_version = { 0, 95, 0 }
luaotfload.self = "luaotfload-tool"
+luaotfload.fontloader = _G -- We don't isolate the fontloader here
--[[doc--
diff --git a/macros/luatex/generic/luaotfload/luaotfload-tool.pdf b/macros/luatex/generic/luaotfload/luaotfload-tool.pdf
index 697cfefd3c..76c2bb6df8 100644
--- a/macros/luatex/generic/luaotfload/luaotfload-tool.pdf
+++ b/macros/luatex/generic/luaotfload/luaotfload-tool.pdf
Binary files differ
diff --git a/macros/luatex/generic/luaotfload/luaotfload-tool.rst b/macros/luatex/generic/luaotfload/luaotfload-tool.rst
index 5d61e04368..1c1ec3161e 100644
--- a/macros/luatex/generic/luaotfload/luaotfload-tool.rst
+++ b/macros/luatex/generic/luaotfload/luaotfload-tool.rst
@@ -6,9 +6,9 @@
generate and query the Luaotfload font names database
-----------------------------------------------------------------------
-:Date: 2019-09-13
+:Date: 2019-11-04
:Copyright: GPL v2.0
-:Version: 3.00
+:Version: 3.1
:Manual section: 1
:Manual group: text processing
diff --git a/macros/luatex/generic/luaotfload/luaotfload-tounicode.lua b/macros/luatex/generic/luaotfload/luaotfload-tounicode.lua
new file mode 100644
index 0000000000..3636f79220
--- /dev/null
+++ b/macros/luatex/generic/luaotfload/luaotfload-tounicode.lua
@@ -0,0 +1,200 @@
+-----------------------------------------------------------------------
+-- FILE: luaotfload-tounicode.lua
+-- DESCRIPTION: part of luaotfload / tounicode overwrites
+-----------------------------------------------------------------------
+
+local ProvidesLuaModule = {
+ name = "luaotfload-tounicode",
+ version = "3.1", --TAGVERSION
+ date = "2019-11-04", --TAGDATE
+ description = "luaotfload submodule / tounicode",
+ license = "GPL v2.0",
+ author = "Hans Hagen, Khaled Hosny, Elie Roux, Philipp Gesang, Marcel Krüger",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+}
+
+if luatexbase and luatexbase.provides_module then
+ luatexbase.provides_module (ProvidesLuaModule)
+end
+
+local overloads = {
+ -- rougly based on texglyphlist-g2u.txt
+
+ -- ff = { unicode = {0x0066, 0x0066} },
+ -- ffi = { unicode = {0x0066, 0x0066, 0x0069} },
+ -- ffl = { unicode = {0x0066, 0x0066, 0x006C} },
+ -- fi = { unicode = {0x0066, 0x0069} },
+ -- fl = { unicode = {0x0066, 0x006C} },
+ longst = { unicode = {0x017F, 0x0074} },
+ st = { unicode = {0x0073, 0x0074} },
+ AEsmall = { unicode = 0x00E6 },
+ Aacutesmall = { unicode = 0x00E1 },
+ Acircumflexsmall = { unicode = 0x00E2 },
+ Acute = { unicode = 0x00B4 },
+ Acutesmall = { unicode = 0x00B4 },
+ Adieresissmall = { unicode = 0x00E4 },
+ Agravesmall = { unicode = 0x00E0 },
+ Aringsmall = { unicode = 0x00E5 },
+ Asmall = { unicode = 0x0061 },
+ Atildesmall = { unicode = 0x00E3 },
+ Brevesmall = { unicode = 0x02D8 },
+ Bsmall = { unicode = 0x0062 },
+ Caron = { unicode = 0x02C7 },
+ Caronsmall = { unicode = 0x02C7 },
+ Ccedillasmall = { unicode = 0x00E7 },
+ Cedillasmall = { unicode = 0x00B8 },
+ Circumflexsmall = { unicode = 0x02C6 },
+ Csmall = { unicode = 0x0063 },
+ Dieresis = { unicode = 0x00A8 },
+ DieresisAcute = { unicode = 0xF6CC },
+ DieresisGrave = { unicode = 0xF6CD },
+ Dieresissmall = { unicode = 0x00A8 },
+ Dotaccentsmall = { unicode = 0x02D9 },
+ Dsmall = { unicode = 0x0064 },
+ Eacutesmall = { unicode = 0x00E9 },
+ Ecircumflexsmall = { unicode = 0x00EA },
+ Edieresissmall = { unicode = 0x00EB },
+ Egravesmall = { unicode = 0x00E8 },
+ Esmall = { unicode = 0x0065 },
+ Ethsmall = { unicode = 0x00F0 },
+ Fsmall = { unicode = 0x0066 },
+ Grave = { unicode = 0x0060 },
+ Gravesmall = { unicode = 0x0060 },
+ Gsmall = { unicode = 0x0067 },
+ Hsmall = { unicode = 0x0068 },
+ Hungarumlaut = { unicode = 0x02DD },
+ Hungarumlautsmall = { unicode = 0x02DD },
+ Iacutesmall = { unicode = 0x00ED },
+ Icircumflexsmall = { unicode = 0x00EE },
+ Idieresissmall = { unicode = 0x00EF },
+ Igravesmall = { unicode = 0x00EC },
+ Ismall = { unicode = 0x0069 },
+ Jsmall = { unicode = 0x006A },
+ Ksmall = { unicode = 0x006B },
+ LL = { unicode = {0x004C, 0x004C} },
+ Lslashsmall = { unicode = 0x0142 },
+ Lsmall = { unicode = 0x006C },
+ Macron = { unicode = 0x00AF },
+ Macronsmall = { unicode = 0x00AF },
+ Msmall = { unicode = 0x006D },
+ Nsmall = { unicode = 0x006E },
+ Ntildesmall = { unicode = 0x00F1 },
+ OEsmall = { unicode = 0x0153 },
+ Oacutesmall = { unicode = 0x00F3 },
+ Ocircumflexsmall = { unicode = 0x00F4 },
+ Odieresissmall = { unicode = 0x00F6 },
+ Ogoneksmall = { unicode = 0x02DB },
+ Ogravesmall = { unicode = 0x00F2 },
+ Oslashsmall = { unicode = 0x00F8 },
+ Osmall = { unicode = 0x006F },
+ Otildesmall = { unicode = 0x00F5 },
+ Psmall = { unicode = 0x0070 },
+ Qsmall = { unicode = 0x0071 },
+ Ringsmall = { unicode = 0x02DA },
+ Rsmall = { unicode = 0x0072 },
+ Scaronsmall = { unicode = 0x0161 },
+ Ssmall = { unicode = 0x0073 },
+ Thornsmall = { unicode = 0x00FE },
+ Tildesmall = { unicode = 0x02DC },
+ Tsmall = { unicode = 0x0074 },
+ Uacutesmall = { unicode = 0x00FA },
+ Ucircumflexsmall = { unicode = 0x00FB },
+ Udieresissmall = { unicode = 0x00FC },
+ Ugravesmall = { unicode = 0x00F9 },
+ Usmall = { unicode = 0x0075 },
+ Vsmall = { unicode = 0x0076 },
+ Wsmall = { unicode = 0x0077 },
+ Xsmall = { unicode = 0x0078 },
+ Yacutesmall = { unicode = 0x00FD },
+ Ydieresissmall = { unicode = 0x00FF },
+ Ysmall = { unicode = 0x0079 },
+ Zcaronsmall = { unicode = 0x017E },
+ Zsmall = { unicode = 0x007A },
+ ampersandsmall = { unicode = 0x0026 },
+ asuperior = { unicode = 0x0061 },
+ bsuperior = { unicode = 0x0062 },
+ centinferior = { unicode = 0x00A2 },
+ centoldstyle = { unicode = 0x00A2 },
+ centsuperior = { unicode = 0x00A2 },
+ commainferior = { unicode = 0x002C },
+ commasuperior = { unicode = 0x002C },
+ copyrightsans = { unicode = 0x00A9 },
+ copyrightserif = { unicode = 0x00A9 },
+ cyrBreve = { unicode = 0x02D8 },
+ cyrFlex = { unicode = {0x00A0, 0x0311} },
+ cyrbreve = { unicode = 0x02D8 },
+ cyrflex = { unicode = {0x00A0, 0x0311} },
+ dblGrave = { unicode = {0x00A0, 0x030F} },
+ dblgrave = { unicode = {0x00A0, 0x030F} },
+ dieresisacute = { unicode = {0x00A0, 0x0308, 0x0301} },
+ dieresisgrave = { unicode = {0x00A0, 0x0308, 0x0300} },
+ dollarinferior = { unicode = 0x0024 },
+ dollaroldstyle = { unicode = 0x0024 },
+ dollarsuperior = { unicode = 0x0024 },
+ dotlessj = { unicode = 0x0237 },
+ dsuperior = { unicode = 0x0064 },
+ eightoldstyle = { unicode = 0x0038 },
+ esuperior = { unicode = 0x0065 },
+ exclamdownsmall = { unicode = 0x00A1 },
+ exclamsmall = { unicode = 0x0021 },
+ fiveoldstyle = { unicode = 0x0035 },
+ fouroldstyle = { unicode = 0x0034 },
+ hypheninferior = { unicode = 0x002D },
+ hyphensuperior = { unicode = 0x002D },
+ isuperior = { unicode = 0x0069 },
+ ll = { unicode = {0x006C, 0x006C} },
+ lsuperior = { unicode = 0x006C },
+ msuperior = { unicode = 0x006D },
+ nineoldstyle = { unicode = 0x0039 },
+ onefitted = { unicode = 0x0031 },
+ oneoldstyle = { unicode = 0x0031 },
+ osuperior = { unicode = 0x006F },
+ periodinferior = { unicode = 0x002E },
+ periodsuperior = { unicode = 0x002E },
+ questiondownsmall = { unicode = 0x00BF },
+ questionsmall = { unicode = 0x003F },
+ registersans = { unicode = 0x00AE },
+ registerserif = { unicode = 0x00AE },
+ rsuperior = { unicode = 0x0072 },
+ rupiah = { unicode = 0x20A8 },
+ sevenoldstyle = { unicode = 0x0037 },
+ sixoldstyle = { unicode = 0x0036 },
+ ssuperior = { unicode = 0x0073 },
+ threeoldstyle = { unicode = 0x0033 },
+ trademarksans = { unicode = 0x2122 },
+ trademarkserif = { unicode = 0x2122 },
+ tsuperior = { unicode = 0x0074 },
+ twooldstyle = { unicode = 0x0032 },
+ zerooldstyle = { unicode = 0x0030 },
+ FFsmall = { unicode = {0x0066, 0x0066} },
+ FFIsmall = { unicode = {0x0066, 0x0066, 0x0069} },
+ FFLsmall = { unicode = {0x0066, 0x0066, 0x006C} },
+ FIsmall = { unicode = {0x0066, 0x0069} },
+ FLsmall = { unicode = {0x0066, 0x006C} },
+ Germandblssmall = { unicode = {0x0073, 0x0073} },
+ SSsmall = { unicode = {0x0073, 0x0073} },
+}
+-- For values that are used multiple times
+local function registeroverload(mapped)
+ mapped = {unicode = mapped}
+ local function multiset(first, ...)
+ if first then
+ rawset(overloads, first, mapped)
+ return multiset(...)
+ end
+ end
+ return multiset
+end
+
+-- These come from ConTeXt
+registeroverload { 0x49, 0x4A } ("IJ", "I_J", 0x0132)
+registeroverload { 0x69, 0x6A } ("ij", "i_j", 0x0133)
+registeroverload { 0x66, 0x66 } ("ff", "f_f", 0xFB00)
+registeroverload { 0x66, 0x69 } ("fi", "f_i", 0xFB01)
+registeroverload { 0x66, 0x6C } ("fl", "f_l", 0xFB02)
+registeroverload { 0x66, 0x66, 0x69 } ("ffi", "f_f_i", 0xFB03)
+registeroverload { 0x66, 0x66, 0x6C } ("ffl", "f_f_l", 0xFB04)
+registeroverload { 0x66, 0x6A } ("fj", "f_j")
+registeroverload { 0x66, 0x6B } ("fk", "f_k")
+
+fonts.mappings.overloads = overloads
diff --git a/macros/luatex/generic/luaotfload/luaotfload-unicode.lua b/macros/luatex/generic/luaotfload/luaotfload-unicode.lua
index d7cb98a338..c1bdf3cbd2 100644
--- a/macros/luatex/generic/luaotfload/luaotfload-unicode.lua
+++ b/macros/luatex/generic/luaotfload/luaotfload-unicode.lua
@@ -5,8 +5,8 @@
local ProvidesLuaModule = {
name = "luaotfload-unicode",
- version = "3.00", --TAGVERSION
- date = "2019-09-13", --TAGDATE
+ version = "3.1", --TAGVERSION
+ date = "2019-11-04", --TAGDATE
description = "luaotfload submodule / Unicode helpers",
license = "CC0 1.0 Universal",
author = "Marcel Krüger"
diff --git a/macros/luatex/generic/luaotfload/luaotfload.conf.5 b/macros/luatex/generic/luaotfload/luaotfload.conf.5
index 1173d9a3de..9726ad7aac 100644
--- a/macros/luatex/generic/luaotfload/luaotfload.conf.5
+++ b/macros/luatex/generic/luaotfload/luaotfload.conf.5
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH LUAOTFLOAD.CONF 5 "2019-09-13" "3.00" "text processing"
+.TH LUAOTFLOAD.CONF 5 "2019-11-04" "3.1" "text processing"
.SH NAME
luaotfload.conf \- Luaotfload configuration file
.
diff --git a/macros/luatex/generic/luaotfload/luaotfload.conf.rst b/macros/luatex/generic/luaotfload/luaotfload.conf.rst
index 7b85fd1a28..18042188b8 100644
--- a/macros/luatex/generic/luaotfload/luaotfload.conf.rst
+++ b/macros/luatex/generic/luaotfload/luaotfload.conf.rst
@@ -6,9 +6,9 @@
Luaotfload configuration file
-----------------------------------------------------------------------
-:Date: 2019-09-13
+:Date: 2019-11-04
:Copyright: GPL v2.0
-:Version: 3.00
+:Version: 3.1
:Manual section: 5
:Manual group: text processing
diff --git a/macros/luatex/generic/luaotfload/luaotfload.sty b/macros/luatex/generic/luaotfload/luaotfload.sty
index 1dede25f2f..4dc2553d33 100644
--- a/macros/luatex/generic/luaotfload/luaotfload.sty
+++ b/macros/luatex/generic/luaotfload/luaotfload.sty
@@ -40,7 +40,7 @@
\fi
\ifdefined\ProvidesPackage
\ProvidesPackage{luaotfload}%
- [2019/09/13 v3.00 OpenType layout system]
+ [2019/11/04 v3.1 OpenType layout system]
\fi
\directlua{
if xpcall(function ()%
diff --git a/macros/luatex/generic/luaotfload/scripts-demo.pdf b/macros/luatex/generic/luaotfload/scripts-demo.pdf
new file mode 100644
index 0000000000..f0f1bb0065
--- /dev/null
+++ b/macros/luatex/generic/luaotfload/scripts-demo.pdf
Binary files differ
diff --git a/macros/luatex/generic/luaotfload/scripts-demo.tex b/macros/luatex/generic/luaotfload/scripts-demo.tex
new file mode 100644
index 0000000000..4bbe06064c
--- /dev/null
+++ b/macros/luatex/generic/luaotfload/scripts-demo.tex
@@ -0,0 +1,15 @@
+\documentclass{standalone}
+
+\font\burmesefont={file:NotoSerifMyanmar-Regular.ttf:mode=harf;script=mymr;}
+\font\devafont={file:NotoSansDevanagari-Regular.ttf:mode=harf;script=deva;}
+\font\banglafont={file:NotoSansBengali-Regular.ttf:mode=harf;script=beng;}
+\font\tibetanfont={file:NotoSerifTibetan-Regular.ttf:mode=harf;script=tibt;}
+\standaloneenv{tabular}
+\begin{document}
+\begin{tabular}{l}
+\burmesefont မ္မတီခေါင်းလောင်းကြီ\\
+\devafont क्रर्कि \\
+\banglafont কণ্যা এখন কি করিবে\\
+\tibetanfont སྐྱེས་ཙམ་ཉིད་ནས་ཆེ་མཐོངས་དང༌།
+\end{tabular}
+\end{document} \ No newline at end of file
diff --git a/macros/luatex/generic/luaotfload/shaper-demo-graphite.pdf b/macros/luatex/generic/luaotfload/shaper-demo-graphite.pdf
new file mode 100644
index 0000000000..3c97c23522
--- /dev/null
+++ b/macros/luatex/generic/luaotfload/shaper-demo-graphite.pdf
Binary files differ
diff --git a/macros/luatex/generic/luaotfload/shaper-demo-graphite.tex b/macros/luatex/generic/luaotfload/shaper-demo-graphite.tex
new file mode 100644
index 0000000000..cf83fb2f70
--- /dev/null
+++ b/macros/luatex/generic/luaotfload/shaper-demo-graphite.tex
@@ -0,0 +1,9 @@
+\documentclass[12pt]{standalone}
+
+\begin{document}
+
+\pardir TRT\textdir TRT
+\font\test={file:AwamiNastaliq-Regular.ttf:mode=harf;shaper=graphite2}
+\test
+اُرْشَلیمئے
+\end{document}
diff --git a/macros/luatex/generic/luaotfload/shaper-demo.pdf b/macros/luatex/generic/luaotfload/shaper-demo.pdf
new file mode 100644
index 0000000000..183b062e1f
--- /dev/null
+++ b/macros/luatex/generic/luaotfload/shaper-demo.pdf
Binary files differ
diff --git a/macros/luatex/generic/luaotfload/shaper-demo.tex b/macros/luatex/generic/luaotfload/shaper-demo.tex
new file mode 100644
index 0000000000..b4931dcfc2
--- /dev/null
+++ b/macros/luatex/generic/luaotfload/shaper-demo.tex
@@ -0,0 +1,7 @@
+\documentclass[12pt]{standalone}
+\begin{document}
+\pardir TRT\textdir TRT
+\font\test={file:AwamiNastaliq-Regular.ttf:mode=harf;shaper=ot}
+\test
+اُرْشَلیمئے
+\end{document}