summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/fontloader/luaotfload-package.lua96
-rw-r--r--src/fontloader/misc/fontloader-basics.tex70
-rw-r--r--src/fontloader/misc/fontloader-font-con.lua22
-rw-r--r--src/fontloader/misc/fontloader-font-map.lua57
-rw-r--r--src/fontloader/misc/fontloader-font-otf.lua376
-rw-r--r--src/fontloader/misc/fontloader-font-otp.lua2
-rw-r--r--src/fontloader/misc/fontloader-fonts-cbk.lua42
-rw-r--r--src/fontloader/misc/fontloader-fonts-inj.lua11
-rw-r--r--src/fontloader/misc/fontloader-fonts-otn.lua33
-rw-r--r--src/fontloader/misc/fontloader-l-lpeg.lua236
-rw-r--r--src/fontloader/misc/fontloader-l-math.lua4
-rw-r--r--src/fontloader/misc/fontloader-l-table.lua280
-rw-r--r--src/fontloader/misc/fontloader-mplib.tex1
-rw-r--r--src/fontloader/misc/fontloader-plain.tex1
-rw-r--r--src/fontloader/misc/fontloader-util-str.lua28
-rw-r--r--src/fontloader/runtime/fontloader-fontloader.lua698
-rw-r--r--src/luaotfload-auxiliary.lua6
-rw-r--r--src/luaotfload-colors.lua240
-rw-r--r--src/luaotfload-configuration.lua43
-rw-r--r--src/luaotfload-init.lua59
-rw-r--r--src/luaotfload-loaders.lua4
-rw-r--r--src/luaotfload-main.lua112
-rwxr-xr-xsrc/luaotfload-tool.lua8
-rw-r--r--src/luaotfload.sty27
24 files changed, 1668 insertions, 788 deletions
diff --git a/src/fontloader/luaotfload-package.lua b/src/fontloader/luaotfload-package.lua
new file mode 100644
index 0000000..b60ae17
--- /dev/null
+++ b/src/fontloader/luaotfload-package.lua
@@ -0,0 +1,96 @@
+--
+-----------------------------------------------------------------------
+-- FILE: luaotfload-package.lua
+-- DESCRIPTION: Luatex fontloader packaging
+-- REQUIREMENTS: luatex
+-- AUTHOR: Philipp Gesang
+-- LICENSE: GNU GPL v2.0
+-- CREATED: 2015-03-29 12:07:33+0200
+-----------------------------------------------------------------------
+--
+
+--- The original initialization sequence by Hans Hagen, see the file
+--- luatex-fonts.lua for details:
+---
+--- [01] l-lua.lua
+--- [02] l-lpeg.lua
+--- [03] l-function.lua
+--- [04] l-string.lua
+--- [05] l-table.lua
+--- [06] l-io.lua
+--- [07] l-file.lua
+--- [08] l-boolean.lua
+--- [09] l-math.lua
+--- [10] util-str.lua
+--- [11] luatex-basics-gen.lua
+--- [12] data-con.lua
+--- [13] luatex-basics-nod.lua
+--- [14] font-ini.lua
+--- [15] font-con.lua
+--- [16] luatex-fonts-enc.lua
+--- [17] font-cid.lua
+--- [18] font-map.lua
+--- [19] luatex-fonts-syn.lua
+--- [20] font-tfm.lua
+--- [21] font-afm.lua
+--- [22] font-afk.lua
+--- [23] luatex-fonts-tfm.lua
+--- [24] font-oti.lua
+--- [25] font-otf.lua
+--- [26] font-otb.lua
+--- [27] luatex-fonts-inj.lua
+--- [28] luatex-fonts-ota.lua
+--- [29] luatex-fonts-otn.lua
+--- [30] font-otp.lua
+--- [31] luatex-fonts-lua.lua
+--- [32] font-def.lua
+--- [33] luatex-fonts-def.lua
+--- [34] luatex-fonts-ext.lua
+--- [35] luatex-fonts-cbk.lua
+---
+--- Of these, nos. 01--10 are provided by the Lualibs. Keeping them
+--- around in the Luaotfload fontloader is therefore unnecessary.
+--- Packaging needs to account for this difference.
+
+loadmodule "l-lua.lua"
+loadmodule "l-lpeg.lua"
+loadmodule "l-function.lua"
+loadmodule "l-string.lua"
+loadmodule "l-table.lua"
+loadmodule "l-io.lua"
+loadmodule "l-file.lua"
+loadmodule "l-boolean.lua"
+loadmodule "l-math.lua"
+loadmodule "util-str.lua"
+
+--- The files below constitute the “fontloader proper”. Some of the
+--- functionality like file resolvers is overloaded later by
+--- Luaotfload. Consequently, the resulting package is pretty
+--- bare-bones and not usable independently.
+
+loadmodule("luatex-basics-gen.lua")
+loadmodule("data-con.lua")
+loadmodule("luatex-basics-nod.lua")
+loadmodule("font-ini.lua")
+loadmodule("font-con.lua")
+loadmodule("luatex-fonts-enc.lua")
+loadmodule("font-cid.lua")
+loadmodule("font-map.lua")
+loadmodule("luatex-fonts-syn.lua")
+loadmodule("font-tfm.lua")
+loadmodule("font-afm.lua")
+loadmodule("font-afk.lua")
+loadmodule("luatex-fonts-tfm.lua")
+loadmodule("font-oti.lua")
+loadmodule("font-otf.lua")
+loadmodule("font-otb.lua")
+loadmodule("luatex-fonts-inj.lua")
+loadmodule("luatex-fonts-ota.lua")
+loadmodule("luatex-fonts-otn.lua")
+loadmodule("font-otp.lua")
+loadmodule("luatex-fonts-lua.lua")
+loadmodule("font-def.lua")
+loadmodule("luatex-fonts-def.lua")
+loadmodule("luatex-fonts-ext.lua")
+loadmodule("luatex-fonts-cbk.lua")
+
diff --git a/src/fontloader/misc/fontloader-basics.tex b/src/fontloader/misc/fontloader-basics.tex
index abe4989..1180c68 100644
--- a/src/fontloader/misc/fontloader-basics.tex
+++ b/src/fontloader/misc/fontloader-basics.tex
@@ -20,4 +20,74 @@
{\global\advance\lastallocatedattribute 1
\attributedef#1\lastallocatedattribute}
+% maybe we will have luatex-basics.lua some day for instance when more
+% (pdf) primitives have moved to macros)
+
+\directlua {
+
+ gadgets = gadgets or { } % reserved namespace
+
+ gadgets.functions = { }
+ local registered = {}
+
+ function gadgets.functions.reverve()
+ local numb = newtoken.scan_int()
+ local name = newtoken.scan_string()
+ local okay = string.gsub(name,"[\string\\ ]","")
+ registered[okay] = numb
+ texio.write_nl("reserving lua function '"..okay.."' with number "..numb)
+ end
+
+ function gadgets.functions.register(name,f)
+ local okay = string.gsub(name,"[\string\\ ]","")
+ local numb = registered[okay]
+ if numb then
+ texio.write_nl("registering lua function '"..okay.."' with number "..numb)
+ lua.get_functions_table()[numb] = f
+ else
+ texio.write_nl("lua function '"..okay.."' is not reserved")
+ end
+ end
+
+}
+
+\newcount\lastallocatedluafunction
+
+\def\newluafunction#1%
+ {\ifdefined#1\else
+ \global\advance\lastallocatedluafunction 1
+ \global\chardef#1\lastallocatedluafunction
+ \directlua{gadgets.functions.reserve()}#1{\detokenize{#1}}%
+ \fi}
+
+% an example of usage (if we ever support it it will go to the plain gadgets module):
+%
+% \directlua {
+%
+% local cct = nil
+% local chr = nil
+%
+% gadgets.functions.register("UcharcatLuaOne",function()
+% chr = newtoken.scan_int()
+% cct = tex.getcatcode(chr)
+% tex.setcatcode(chr,newtoken.scan_int())
+% tex.sprint(unicode.utf8.char(chr))
+% end)
+%
+% gadgets.functions.register("UcharcatLuaTwo",function()
+% tex.setcatcode(chr,cct)
+% end)
+%
+% }
+%
+% \def\Ucharcat
+% {\expandafter\expandafter\expandafter\luafunction
+% \expandafter\expandafter\expandafter\UcharcatLuaTwo
+% \luafunction\UcharcatLuaOne}
+%
+% A:\the\catcode65:\Ucharcat 65 11:A:\the\catcode65\par
+% A:\the\catcode65:\Ucharcat 65 5:A:\the\catcode65\par
+% A:\the\catcode65:\Ucharcat 65 11:A:\the\catcode65\par
+
+
\endinput
diff --git a/src/fontloader/misc/fontloader-font-con.lua b/src/fontloader/misc/fontloader-font-con.lua
index bb96912..72fbb5c 100644
--- a/src/fontloader/misc/fontloader-font-con.lua
+++ b/src/fontloader/misc/fontloader-font-con.lua
@@ -507,6 +507,7 @@ function constructors.scale(tfmdata,specification)
local nonames = properties.noglyphnames
local haskerns = properties.haskerns or properties.mode == "base" -- we can have afm in node mode
local hasligatures = properties.hasligatures or properties.mode == "base" -- we can have afm in node mode
+ local realdimensions = properties.realdimensions
--
if changed and not next(changed) then
changed = false
@@ -618,6 +619,27 @@ function constructors.scale(tfmdata,specification)
local width = description.width
local height = description.height
local depth = description.depth
+ if realdimensions then
+ -- this is mostly for checking issues
+ if not height or height == 0 then
+ local bb = description.boundingbox
+ local ht = bb[4]
+ if ht ~= 0 then
+ height = ht
+ end
+ if not depth or depth == 0 then
+ local dp = -bb[2]
+ if dp ~= 0 then
+ depth = dp
+ end
+ end
+ elseif not depth or depth == 0 then
+ local dp = -description.boundingbox[2]
+ if dp ~= 0 then
+ depth = dp
+ end
+ end
+ end
if width then width = hdelta*width else width = scaledwidth end
if height then height = vdelta*height else height = scaledheight end
-- if depth then depth = vdelta*depth else depth = scaleddepth end
diff --git a/src/fontloader/misc/fontloader-font-map.lua b/src/fontloader/misc/fontloader-font-map.lua
index e26f28e..69474ba 100644
--- a/src/fontloader/misc/fontloader-font-map.lua
+++ b/src/fontloader/misc/fontloader-font-map.lua
@@ -23,6 +23,8 @@ local fonts = fonts or { }
local mappings = fonts.mappings or { }
fonts.mappings = mappings
+local allocate = utilities.storage.allocate
+
--[[ldx--
<p>Eventually this code will disappear because map files are kind
of obsolete. Some code may move to runtime or auxiliary modules.</p>
@@ -194,7 +196,7 @@ local namesplitter = Ct(C((1 - ligseparator - varseparator)^1) * (ligseparator *
-- to be completed .. for fonts that use unicodes for ligatures which
-- is a actually a bad thing and should be avoided in the first place
-local overloads = {
+local overloads = allocate {
IJ = { name = "I_J", unicode = { 0x49, 0x4A }, mess = 0x0132 },
ij = { name = "i_j", unicode = { 0x69, 0x6A }, mess = 0x0133 },
ff = { name = "f_f", unicode = { 0x66, 0x66 }, mess = 0xFB00 },
@@ -311,6 +313,59 @@ function mappings.addtounicode(data,filename)
-- The next time I look into this, I'll add an extra analysis step to the otf loader (we can
-- resolve some tounicodes by looking into the gsub data tables that are bound to glyphs.
--
+-- a real tricky last resort:
+--
+-- local lookups = glyph.lookups
+-- if lookups then
+-- for _, lookup in next, lookups do -- assume consistency else we need to sort
+-- for i=1,#lookup do
+-- local l = lookup[i]
+-- if l.type == "ligature" then
+-- local s = l.specification
+-- if s.char == glyph.name then
+-- local components = s.components
+-- if components then
+-- local t, n = { }, 0
+-- unicode = true
+-- for l=1,#components do
+-- local base = components[l]
+-- local u = unicodes[base] or unicodevector[base]
+-- if not u then
+-- break
+-- elseif type(u) == "table" then
+-- if u[1] >= private then
+-- unicode = false
+-- break
+-- end
+-- n = n + 1
+-- t[n] = u[1]
+-- else
+-- if u >= private then
+-- unicode = false
+-- break
+-- end
+-- n = n + 1
+-- t[n] = u
+-- end
+-- end
+-- if n == 0 then -- done then
+-- -- nothing
+-- elseif n == 1 then
+-- glyph.unicode = t[1]
+-- else
+-- glyph.unicode = t
+-- end
+-- nl = nl + 1
+-- break
+-- end
+-- end
+-- end
+-- end
+-- if unicode then
+-- break
+-- end
+-- end
+-- end
if not unicode or unicode == "" then
local split = lpegmatch(namesplitter,name)
local nsplit = split and #split or 0
diff --git a/src/fontloader/misc/fontloader-font-otf.lua b/src/fontloader/misc/fontloader-font-otf.lua
index c7e83a4..e7a97c6 100644
--- a/src/fontloader/misc/fontloader-font-otf.lua
+++ b/src/fontloader/misc/fontloader-font-otf.lua
@@ -36,6 +36,7 @@ local elapsedtime = statistics.elapsedtime
local findbinfile = resolvers.findbinfile
local trace_private = false registertracker("otf.private", function(v) trace_private = v end)
+local trace_subfonts = false registertracker("otf.subfonts", function(v) trace_subfonts = v end)
local trace_loading = false registertracker("otf.loading", function(v) trace_loading = v end)
local trace_features = false registertracker("otf.features", function(v) trace_features = v end)
local trace_dynamics = false registertracker("otf.dynamics", function(v) trace_dynamics = v end)
@@ -53,7 +54,7 @@ local otf = fonts.handlers.otf
otf.glists = { "gsub", "gpos" }
-otf.version = 2.803 -- beware: also sync font-mis.lua
+otf.version = 2.812 -- beware: also sync font-mis.lua
otf.cache = containers.define("fonts", "otf", otf.version, true)
local hashes = fonts.hashes
@@ -107,6 +108,7 @@ registerdirective("fonts.otf.loader.pack", function(v) packdata =
registerdirective("fonts.otf.loader.syncspace", function(v) syncspace = v end)
registerdirective("fonts.otf.loader.forcenotdef", function(v) forcenotdef = v end)
registerdirective("fonts.otf.loader.overloadkerns", function(v) overloadkerns = v end)
+-----------------("fonts.otf.loader.alldimensions", function(v) alldimensions = v end)
function otf.fileformat(filename)
local leader = lower(io.loadchunk(filename,4))
@@ -637,17 +639,27 @@ actions["add dimensions"] = function(data,filename)
-- d.name = ".notdef"
-- end
if bb then
- local ht, dp = bb[4], -bb[2]
- if ht == 0 or ht < 0 then
- -- not set
- else
- d.height = ht
- end
- if dp == 0 or dp < 0 then
- -- not set
- else
- d.depth = dp
- end
+ local ht = bb[4]
+ local dp = -bb[2]
+ -- if alldimensions then
+ -- if ht ~= 0 then
+ -- d.height = ht
+ -- end
+ -- if dp ~= 0 then
+ -- d.depth = dp
+ -- end
+ -- else
+ if ht == 0 or ht < 0 then
+ -- not set
+ else
+ d.height = ht
+ end
+ if dp == 0 or dp < 0 then
+ -- not set
+ else
+ d.depth = dp
+ end
+ -- end
end
end
end
@@ -688,6 +700,7 @@ end
-- not setting hasitalics and class (when nil) during table cronstruction can save some mem
actions["prepare glyphs"] = function(data,filename,raw)
+ local tableversion = tonumber(raw.table_version) or 0
local rawglyphs = raw.glyphs
local rawsubfonts = raw.subfonts
local rawcidinfo = raw.cidinfo
@@ -711,81 +724,139 @@ actions["prepare glyphs"] = function(data,filename,raw)
local cidmap = fonts.cid.getmap(rawcidinfo)
if cidmap then
rawcidinfo.usedname = cidmap.usedname
- local nofnames, nofunicodes = 0, 0
- local cidunicodes, cidnames = cidmap.unicodes, cidmap.names
+ local nofnames = 0
+ local nofunicodes = 0
+ local cidunicodes = cidmap.unicodes
+ local cidnames = cidmap.names
+ local cidtotal = 0
+ local unique = trace_subfonts and { }
for cidindex=1,#rawsubfonts do
local subfont = rawsubfonts[cidindex]
local cidglyphs = subfont.glyphs
if includesubfonts then
metadata.subfonts[cidindex] = somecopy(subfont)
end
- -- we have delayed loading so we cannot use next
- for index=0,subfont.glyphcnt-1 do -- we could take the previous glyphcnt instead of 0
- local glyph = cidglyphs[index]
- if glyph then
- local unicode = glyph.unicode
- if unicode >= 0x00E000 and unicode <= 0x00F8FF then
- unicode = -1
- elseif unicode >= 0x0F0000 and unicode <= 0x0FFFFD then
- unicode = -1
- elseif unicode >= 0x100000 and unicode <= 0x10FFFD then
- unicode = -1
- end
- local name = glyph.name or cidnames[index]
- if not unicode or unicode == -1 then -- or unicode >= criterium then
- unicode = cidunicodes[index]
- end
- if unicode and descriptions[unicode] then
- if trace_private then
- report_otf("preventing glyph %a at index %H to overload unicode %U",name or "noname",index,unicode)
+ local cidcnt, cidmin, cidmax
+ if tableversion > 0.3 then
+ -- we have delayed loading so we cannot use next
+ cidcnt = subfont.glyphcnt
+ cidmin = subfont.glyphmin
+ cidmax = subfont.glyphmax
+ else
+ cidcnt = subfont.glyphcnt
+ cidmin = 0
+ cidmax = cidcnt - 1
+ end
+ if trace_subfonts then
+ local cidtot = cidmax - cidmin + 1
+ cidtotal = cidtotal + cidtot
+ report_otf("subfont: %i, min: %i, max: %i, cnt: %i, n: %i",cidindex,cidmin,cidmax,cidtot,cidcnt)
+ end
+ if cidcnt > 0 then
+ for cidslot=cidmin,cidmax do
+ local glyph = cidglyphs[cidslot]
+ if glyph then
+ local index = tableversion > 0.3 and glyph.orig_pos or cidslot
+ if trace_subfonts then
+ unique[index] = true
end
- unicode = -1
- end
- if not unicode or unicode == -1 then -- or unicode >= criterium then
- if not name then
- name = format("u%06X.ctx",private)
+ local unicode = glyph.unicode
+ if unicode >= 0x00E000 and unicode <= 0x00F8FF then
+ unicode = -1
+ elseif unicode >= 0x0F0000 and unicode <= 0x0FFFFD then
+ unicode = -1
+ elseif unicode >= 0x100000 and unicode <= 0x10FFFD then
+ unicode = -1
end
- unicode = private
- unicodes[name] = private
- if trace_private then
- report_otf("glyph %a at index %H is moved to private unicode slot %U",name,index,private)
+ local name = glyph.name or cidnames[index]
+ if not unicode or unicode == -1 then -- or unicode >= criterium then
+ unicode = cidunicodes[index]
end
- private = private + 1
- nofnames = nofnames + 1
- else
- -- if unicode > criterium then
- -- local taken = descriptions[unicode]
- -- if taken then
- -- private = private + 1
- -- descriptions[private] = taken
- -- unicodes[taken.name] = private
- -- indices[taken.index] = private
- -- if trace_private then
- -- report_otf("slot %U is moved to %U due to private in font",unicode)
- -- end
- -- end
- -- end
- if not name then
- name = format("u%06X.ctx",unicode)
+ if unicode and descriptions[unicode] then
+ if trace_private then
+ report_otf("preventing glyph %a at index %H to overload unicode %U",name or "noname",index,unicode)
+ end
+ unicode = -1
+ end
+ if not unicode or unicode == -1 then -- or unicode >= criterium then
+ if not name then
+ name = format("u%06X.ctx",private)
+ end
+ unicode = private
+ unicodes[name] = private
+ if trace_private then
+ report_otf("glyph %a at index %H is moved to private unicode slot %U",name,index,private)
+ end
+ private = private + 1
+ nofnames = nofnames + 1
+ else
+ -- if unicode > criterium then
+ -- local taken = descriptions[unicode]
+ -- if taken then
+ -- private = private + 1
+ -- descriptions[private] = taken
+ -- unicodes[taken.name] = private
+ -- indices[taken.index] = private
+ -- if trace_private then
+ -- report_otf("slot %U is moved to %U due to private in font",unicode)
+ -- end
+ -- end
+ -- end
+ if not name then
+ name = format("u%06X.ctx",unicode)
+ end
+ unicodes[name] = unicode
+ nofunicodes = nofunicodes + 1
end
- unicodes[name] = unicode
- nofunicodes = nofunicodes + 1
+ indices[index] = unicode -- each index is unique (at least now)
+ local description = {
+ -- width = glyph.width,
+ boundingbox = glyph.boundingbox,
+ -- name = glyph.name or name or "unknown", -- uniXXXX
+ name = name or "unknown", -- uniXXXX
+ cidindex = cidindex,
+ index = cidslot,
+ glyph = glyph,
+ }
+ descriptions[unicode] = description
+local altuni = glyph.altuni
+if altuni then
+ -- local d
+ for i=1,#altuni do
+ local a = altuni[i]
+ local u = a.unicode
+ if u ~= unicode then
+ local v = a.variant
+ if v then
+ -- tricky: no addition to d? needs checking but in practice such dups are either very simple
+ -- shapes or e.g cjk with not that many features
+ local vv = variants[v]
+ if vv then
+ vv[u] = unicode
+ else -- xits-math has some:
+ vv = { [u] = unicode }
+ variants[v] = vv
+ end
+ -- elseif d then
+ -- d[#d+1] = u
+ -- else
+ -- d = { u }
+ end
+ end
+ end
+ -- if d then
+ -- duplicates[unicode] = d -- is this needed ?
+ -- end
+end
end
- indices[index] = unicode -- each index is unique (at least now)
- local description = {
- -- width = glyph.width,
- boundingbox = glyph.boundingbox,
- name = glyph.name or name or "unknown", -- uniXXXX
- cidindex = cidindex,
- index = index,
- glyph = glyph,
- }
- descriptions[unicode] = description
- else
- -- report_otf("potential problem: glyph %U is used but empty",index)
end
+ else
+ report_otf("potential problem: no glyphs found in subfont %i",cidindex)
end
end
+ if trace_subfonts then
+ report_otf("nofglyphs: %i, unique: %i",cidtotal,table.count(unique))
+ end
if trace_loading then
report_otf("cid font remapped, %s unicode points, %s symbolic names, %s glyphs",nofunicodes, nofnames, nofunicodes+nofnames)
end
@@ -798,87 +869,97 @@ actions["prepare glyphs"] = function(data,filename,raw)
else
- for index=0,raw.glyphcnt-1 do -- not raw.glyphmax-1 (as that will crash)
- local glyph = rawglyphs[index]
- if glyph then
- local unicode = glyph.unicode
- local name = glyph.name
- if not unicode or unicode == -1 then -- or unicode >= criterium then
- unicode = private
- unicodes[name] = private
- if trace_private then
- report_otf("glyph %a at index %H is moved to private unicode slot %U",name,index,private)
- end
- private = private + 1
- else
- -- We have a font that uses and exposes the private area. As this is rather unreliable it's
- -- advised no to trust slots here (better use glyphnames). Anyway, we need a double check:
- -- we need to move already moved entries and we also need to bump the next private to after
- -- the (currently) last slot. This could leave us with a hole but we have holes anyway.
- if unicode > criterium then
- -- \definedfont[file:HANBatang-LVT.ttf] \fontchar{uF0135} \char"F0135
- local taken = descriptions[unicode]
- if taken then
- if unicode >= private then
- private = unicode + 1 -- restart private (so we can have mixed now)
+ local cnt = raw.glyphcnt or 0
+ local min = tableversion > 0.3 and raw.glyphmin or 0
+ local max = tableversion > 0.3 and raw.glyphmax or (raw.glyphcnt - 1)
+ if cnt > 0 then
+-- for index=0,cnt-1 do
+ for index=min,max do
+ local glyph = rawglyphs[index]
+ if glyph then
+ local unicode = glyph.unicode
+ local name = glyph.name
+ if not unicode or unicode == -1 then -- or unicode >= criterium then
+ unicode = private
+ unicodes[name] = private
+ if trace_private then
+ report_otf("glyph %a at index %H is moved to private unicode slot %U",name,index,private)
+ end
+ private = private + 1
+ else
+ -- We have a font that uses and exposes the private area. As this is rather unreliable it's
+ -- advised no to trust slots here (better use glyphnames). Anyway, we need a double check:
+ -- we need to move already moved entries and we also need to bump the next private to after
+ -- the (currently) last slot. This could leave us with a hole but we have holes anyway.
+ if unicode > criterium then
+ -- \definedfont[file:HANBatang-LVT.ttf] \fontchar{uF0135} \char"F0135
+ local taken = descriptions[unicode]
+ if taken then
+ if unicode >= private then
+ private = unicode + 1 -- restart private (so we can have mixed now)
+ else
+ private = private + 1 -- move on
+ end
+ descriptions[private] = taken
+ unicodes[taken.name] = private
+ indices[taken.index] = private
+ if trace_private then
+ report_otf("slot %U is moved to %U due to private in font",unicode)
+ end
else
- private = private + 1 -- move on
- end
- descriptions[private] = taken
- unicodes[taken.name] = private
- indices[taken.index] = private
- if trace_private then
- report_otf("slot %U is moved to %U due to private in font",unicode)
- end
- else
- if unicode >= private then
- private = unicode + 1 -- restart (so we can have mixed now)
+ if unicode >= private then
+ private = unicode + 1 -- restart (so we can have mixed now)
+ end
end
end
+ unicodes[name] = unicode
end
- unicodes[name] = unicode
- end
- indices[index] = unicode
- -- if not name then
- -- name = format("u%06X",unicode) -- u%06X.ctx
- -- end
- descriptions[unicode] = {
- -- width = glyph.width,
- boundingbox = glyph.boundingbox,
- name = name,
- index = index,
- glyph = glyph,
- }
- local altuni = glyph.altuni
- if altuni then
- -- local d
- for i=1,#altuni do
- local a = altuni[i]
- local u = a.unicode
- local v = a.variant
- if v then
- -- tricky: no addition to d? needs checking but in practice such dups are either very simple
- -- shapes or e.g cjk with not that many features
- local vv = variants[v]
- if vv then
- vv[u] = unicode
- else -- xits-math has some:
- vv = { [u] = unicode }
- variants[v] = vv
+ indices[index] = unicode
+ -- if not name then
+ -- name = format("u%06X",unicode) -- u%06X.ctx
+ -- end
+ descriptions[unicode] = {
+ -- width = glyph.width,
+ boundingbox = glyph.boundingbox,
+ name = name,
+ index = index,
+ glyph = glyph,
+ }
+ local altuni = glyph.altuni
+ if altuni then
+ -- local d
+ for i=1,#altuni do
+ local a = altuni[i]
+ local u = a.unicode
+ if u ~= unicode then
+ local v = a.variant
+ if v then
+ -- tricky: no addition to d? needs checking but in practice such dups are either very simple
+ -- shapes or e.g cjk with not that many features
+ local vv = variants[v]
+ if vv then
+ vv[u] = unicode
+ else -- xits-math has some:
+ vv = { [u] = unicode }
+ variants[v] = vv
+ end
+ -- elseif d then
+ -- d[#d+1] = u
+ -- else
+ -- d = { u }
+ end
end
- -- elseif d then
- -- d[#d+1] = u
- -- else
- -- d = { u }
end
+ -- if d then
+ -- duplicates[unicode] = d -- is this needed ?
+ -- end
end
- -- if d then
- -- duplicates[unicode] = d -- is this needed ?
- -- end
+ else
+ report_otf("potential problem: glyph %U is used but empty",index)
end
- else
- report_otf("potential problem: glyph %U is used but empty",index)
end
+ else
+ report_otf("potential problem: no glyphs found")
end
end
@@ -963,8 +1044,8 @@ actions["check encoding"] = function(data,filename,raw)
end
if mapdata then
- mapdata.map = { } -- clear some memory
- mapdata.backmap = { } -- clear some memory
+ mapdata.map = { } -- clear some memory (virtual and created each time anyway)
+ mapdata.backmap = { } -- clear some memory (virtual and created each time anyway)
end
end
@@ -980,7 +1061,6 @@ actions["add duplicates"] = function(data,filename,raw)
local unicodes = resources.unicodes -- name to unicode
local indices = resources.indices -- index to unicodes
local duplicates = resources.duplicates
-
for unicode, d in next, duplicates do
local nofduplicates = #d
if nofduplicates > 4 then
diff --git a/src/fontloader/misc/fontloader-font-otp.lua b/src/fontloader/misc/fontloader-font-otp.lua
index 63e4184..ebf36ed 100644
--- a/src/fontloader/misc/fontloader-font-otp.lua
+++ b/src/fontloader/misc/fontloader-font-otp.lua
@@ -9,6 +9,8 @@ if not modules then modules = { } end modules ['font-otp'] = {
-- todo: pack math (but not that much to share)
--
-- pitfall 5.2: hashed tables can suddenly become indexed with nil slots
+--
+-- unless we sort all hashes we can get a different pack order (no big deal but size can differ)
local next, type = next, type
local sort, concat = table.sort, table.concat
diff --git a/src/fontloader/misc/fontloader-fonts-cbk.lua b/src/fontloader/misc/fontloader-fonts-cbk.lua
index ce19c88..81b5b6e 100644
--- a/src/fontloader/misc/fontloader-fonts-cbk.lua
+++ b/src/fontloader/misc/fontloader-fonts-cbk.lua
@@ -17,6 +17,9 @@ local nodes = nodes
-- Fonts: (might move to node-gef.lua)
local traverse_id = node.traverse_id
+local free_node = node.free
+local remove_node = node.remove
+
local glyph_code = nodes.nodecodes.glyph
local disc_code = nodes.nodecodes.disc
@@ -57,6 +60,8 @@ function nodes.handlers.nodepass(head)
local basefonts = { }
local prevfont = nil
local basefont = nil
+ local variants = nil
+ local redundant = nil
for n in traverse_id(glyph_code,head) do
local font = n.font
if font ~= prevfont then
@@ -78,9 +83,46 @@ function nodes.handlers.nodepass(head)
basefonts[#basefonts+1] = basefont
end
end
+ local resources = tfmdata.resources
+ variants = resources and resources.variants
+ variants = variants and next(variants) and variants or false
+ end
+ else
+ local tfmdata = fontdata[prevfont]
+ if tfmdata then
+ local resources = tfmdata.resources
+ variants = resources and resources.variants
+ variants = variants and next(variants) and variants or false
end
end
end
+ if variants then
+ local char = n.char
+ if char >= 0xFE00 and (char <= 0xFE0F or (char >= 0xE0100 and char <= 0xE01EF)) then
+ local hash = variants[char]
+ if hash then
+ local p = n.prev
+ if p and p.id == glyph_code then
+ local variant = hash[p.char]
+ if variant then
+ p.char = variant
+ if not redundant then
+ redundant = { n }
+ else
+ redundant[#redundant+1] = n
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ if redundant then
+ for i=1,#redundant do
+ local n = redundant[i]
+ remove_node(head,n)
+ free_node(n)
+ end
end
for d in traverse_id(disc_code,head) do
local r = d.replace
diff --git a/src/fontloader/misc/fontloader-fonts-inj.lua b/src/fontloader/misc/fontloader-fonts-inj.lua
index cb9ed89..332e920 100644
--- a/src/fontloader/misc/fontloader-fonts-inj.lua
+++ b/src/fontloader/misc/fontloader-fonts-inj.lua
@@ -647,10 +647,10 @@ local function inject_cursives(glyphs,nofglyphs)
end
end
-local function inject_kerns(head,glyphs,nofglyphs)
+local function inject_kerns(head,list,length)
-- todo: pre/post/replace
- for i=1,#glyphs do
- local n = glyphs[i]
+ for i=1,length do
+ local n = list[i]
local pn = rawget(properties,n)
if pn then
local i = rawget(pn,"injections")
@@ -688,6 +688,9 @@ local function inject_everything(head,where)
end
inject_kerns(head,glyphs,nofglyphs)
end
+ if nofmarks > 0 then
+ inject_kerns(head,marks,nofmarks)
+ end
if keepregisteredcounts then
keepregisteredcounts = false
else
@@ -998,7 +1001,7 @@ local function inject_pairs_only(head,where)
if getsubtype(n) < 256 then
local p = rawget(properties,n)
if p then
- local i = rawget(pn,"replaceinjections")
+ local i = rawget(p,"replaceinjections")
if i then
local yoffset = i.yoffset
if yoffset and yoffset ~= 0 then
diff --git a/src/fontloader/misc/fontloader-fonts-otn.lua b/src/fontloader/misc/fontloader-fonts-otn.lua
index 3f53078..dd3aa61 100644
--- a/src/fontloader/misc/fontloader-fonts-otn.lua
+++ b/src/fontloader/misc/fontloader-fonts-otn.lua
@@ -29,7 +29,6 @@ if not modules then modules = { } end modules ['font-otn'] = {
-- todo:
--
--- kerning is probably not yet ok for latin around dics nodes (interesting challenge)
-- extension infrastructure (for usage out of context)
-- sorting features according to vendors/renderers
-- alternative loop quitters
@@ -169,6 +168,7 @@ local report_chain = logs.reporter("fonts","otf chain")
local report_process = logs.reporter("fonts","otf process")
local report_prepare = logs.reporter("fonts","otf prepare")
local report_warning = logs.reporter("fonts","otf warning")
+local report_run = logs.reporter("fonts","otf run")
registertracker("otf.verbose_chain", function(v) otf.setcontextchain(v and "verbose") end)
registertracker("otf.normal_chain", function(v) otf.setcontextchain(v and "normal") end)
@@ -197,12 +197,18 @@ local getfont = nuts.getfont
local getsubtype = nuts.getsubtype
local getchar = nuts.getchar
+local insert_node_before = nuts.insert_before
local insert_node_after = nuts.insert_after
local delete_node = nuts.delete
+local remove_node = nuts.remove
local copy_node = nuts.copy
+local copy_node_list = nuts.copy_list
local find_node_tail = nuts.tail
local flush_node_list = nuts.flush_list
+local free_node = nuts.free
local end_of_math = nuts.end_of_math
+local traverse_nodes = nuts.traverse
+local traverse_id = nuts.traverse_id
local setmetatableindex = table.setmetatableindex
@@ -226,13 +232,15 @@ local dir_code = whatcodes.dir
local localpar_code = whatcodes.localpar
local discretionary_code = disccodes.discretionary
+local regular_code = disccodes.regular
+local automatic_code = disccodes.automatic
local ligature_code = glyphcodes.ligature
local privateattribute = attributes.private
-- Something is messed up: we have two mark / ligature indices, one at the injection
--- end and one here ... this is bases in KE's patches but there is something fishy
+-- end and one here ... this is based on KE's patches but there is something fishy
-- there as I'm pretty sure that for husayni we need some connection (as it's much
-- more complex than an average font) but I need proper examples of all cases, not
-- of only some.
@@ -368,7 +376,7 @@ local function copy_glyph(g) -- next and prev are untouched !
end
end
---
+--
-- start is a mark and we need to keep that one
@@ -1826,15 +1834,8 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
break
end
end
- elseif f == 2 then
- match = seq[1][32]
else
- for n=f-1,1 do
- if not seq[n][32] then
- match = false
- break
- end
- end
+ match = false
end
end
-- after
@@ -1887,15 +1888,8 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
break
end
end
- elseif s-l == 1 then
- match = seq[s][32]
else
- for n=l+1,s do
- if not seq[n][32] then
- match = false
- break
- end
- end
+ match = false
end
end
end
@@ -2627,6 +2621,7 @@ elseif typ == "gpos_single" or typ == "gpos_pair" then
if trace_steps then -- ?
registerstep(head)
end
+
end
head = tonode(head)
diff --git a/src/fontloader/misc/fontloader-l-lpeg.lua b/src/fontloader/misc/fontloader-l-lpeg.lua
index 192e32f..55a0d89 100644
--- a/src/fontloader/misc/fontloader-l-lpeg.lua
+++ b/src/fontloader/misc/fontloader-l-lpeg.lua
@@ -10,6 +10,8 @@ if not modules then modules = { } end modules ['l-lpeg'] = {
-- if i can use new features like capture / 2 and .B (at first sight the xml
-- parser is some 5% slower)
+-- lpeg.P("abc") is faster than lpeg.P("a") * lpeg.P("b") * lpeg.P("c")
+
-- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
-- move utf -> l-unicode
@@ -19,7 +21,7 @@ lpeg = require("lpeg")
-- The latest lpeg doesn't have print any more, and even the new ones are not
-- available by default (only when debug mode is enabled), which is a pitty as
--- as it helps nailign down bottlenecks. Performance seems comparable: some 10%
+-- as it helps nailing down bottlenecks. Performance seems comparable: some 10%
-- slower pattern compilation, same parsing speed, although,
--
-- local p = lpeg.C(lpeg.P(1)^0 * lpeg.P(-1))
@@ -834,121 +836,185 @@ end
-- experiment:
--- local function make(t)
--- local p
--- local keys = sortedkeys(t)
--- for i=1,#keys do
--- local k = keys[i]
--- local v = t[k]
--- if not p then
--- if next(v) then
--- p = P(k) * make(v)
--- else
--- p = P(k)
--- end
--- else
--- if next(v) then
--- p = p + P(k) * make(v)
--- else
--- p = p + P(k)
--- end
--- end
--- end
--- return p
--- end
-
--- local function make(t)
--- local p = P(false)
--- local keys = sortedkeys(t)
--- for i=1,#keys do
--- local k = keys[i]
--- local v = t[k]
--- if next(v) then
--- p = p + P(k) * make(v)
--- else
--- p = p + P(k)
--- end
--- end
--- return p
--- end
-
--- function lpeg.utfchartabletopattern(list) -- goes to util-lpg
--- local tree = { }
--- for i=1,#list do
--- local t = tree
--- for c in gmatch(list[i],".") do
--- local tc = t[c]
--- if not tc then
--- tc = { }
--- t[c] = tc
--- end
--- t = tc
--- end
--- end
--- return make(tree)
--- end
+local p_false = P(false)
+local p_true = P(true)
-local function make(t,hash)
- local p = P(false)
+local function make(t)
+ local function making(t)
+ local p = p_false
+ local keys = sortedkeys(t)
+ for i=1,#keys do
+ local k = keys[i]
+ if k ~= "" then
+ local v = t[k]
+ if v == true then
+ p = p + P(k) * p_true
+ elseif v == false then
+ -- can't happen
+ else
+ p = p + P(k) * making(v)
+ end
+ end
+ end
+ if t[""] then
+ p = p + p_true
+ end
+ return p
+ end
+ local p = p_false
local keys = sortedkeys(t)
for i=1,#keys do
local k = keys[i]
- local v = t[k]
- local h = hash[v]
- if h then
- if next(v) then
- p = p + P(k) * (make(v,hash) + P(true))
+ if k ~= "" then
+ local v = t[k]
+ if v == true then
+ p = p + P(k) * p_true
+ elseif v == false then
+ -- can't happen
else
- p = p + P(k) * P(true)
+ p = p + P(k) * making(v)
end
- else
- if next(v) then
- p = p + P(k) * make(v,hash)
+ end
+ end
+ return p
+end
+
+local function collapse(t,x)
+ if type(t) ~= "table" then
+ return t, x
+ else
+ local n = next(t)
+ if n == nil then
+ return t, x
+ elseif next(t,n) == nil then
+ -- one entry
+ local k = n
+ local v = t[k]
+ if type(v) == "table" then
+ return collapse(v,x..k)
else
- p = p + P(k)
+ return v, x .. k
+ end
+ else
+ local tt = { }
+ for k, v in next, t do
+ local vv, kk = collapse(v,k)
+ tt[kk] = vv
end
+ return tt, x
end
end
- return p
end
function lpeg.utfchartabletopattern(list) -- goes to util-lpg
local tree = { }
- local hash = { }
local n = #list
if n == 0 then
- -- we could always use this branch
for s in next, list do
local t = tree
+ local p, pk
for c in gmatch(s,".") do
- local tc = t[c]
- if not tc then
- tc = { }
- t[c] = tc
+ if t == true then
+ t = { [c] = true, [""] = true }
+ p[pk] = t
+ p = t
+ t = false
+ elseif t == false then
+ t = { [c] = false }
+ p[pk] = t
+ p = t
+ t = false
+ else
+ local tc = t[c]
+ if not tc then
+ tc = false
+ t[c] = false
+ end
+ p = t
+ t = tc
end
- t = tc
+ pk = c
+ end
+ if t == false then
+ p[pk] = true
+ elseif t == true then
+ -- okay
+ else
+ t[""] = true
end
- hash[t] = s
end
else
for i=1,n do
- local t = tree
local s = list[i]
+ local t = tree
+ local p, pk
for c in gmatch(s,".") do
- local tc = t[c]
- if not tc then
- tc = { }
- t[c] = tc
+ if t == true then
+ t = { [c] = true, [""] = true }
+ p[pk] = t
+ p = t
+ t = false
+ elseif t == false then
+ t = { [c] = false }
+ p[pk] = t
+ p = t
+ t = false
+ else
+ local tc = t[c]
+ if not tc then
+ tc = false
+ t[c] = false
+ end
+ p = t
+ t = tc
end
- t = tc
+ pk = c
+ end
+ if t == false then
+ p[pk] = true
+ elseif t == true then
+ -- okay
+ else
+ t[""] = true
end
- hash[t] = s
end
end
- return make(tree,hash)
+-- collapse(tree,"") -- needs testing, maybe optional, slightly faster because P("x")*P("X") seems slower than P"(xX") (why)
+-- inspect(tree)
+ return make(tree)
end
--- inspect ( lpeg.utfchartabletopattern {
+-- local t = { "start", "stoep", "staart", "paard" }
+-- local p = lpeg.Cs((lpeg.utfchartabletopattern(t)/string.upper + 1)^1)
+
+-- local t = { "a", "abc", "ac", "abe", "abxyz", "xy", "bef","aa" }
+-- local p = lpeg.Cs((lpeg.utfchartabletopattern(t)/string.upper + 1)^1)
+
+-- inspect(lpegmatch(p,"a"))
+-- inspect(lpegmatch(p,"aa"))
+-- inspect(lpegmatch(p,"aaaa"))
+-- inspect(lpegmatch(p,"ac"))
+-- inspect(lpegmatch(p,"bc"))
+-- inspect(lpegmatch(p,"zzbczz"))
+-- inspect(lpegmatch(p,"zzabezz"))
+-- inspect(lpegmatch(p,"ab"))
+-- inspect(lpegmatch(p,"abc"))
+-- inspect(lpegmatch(p,"abe"))
+-- inspect(lpegmatch(p,"xa"))
+-- inspect(lpegmatch(p,"bx"))
+-- inspect(lpegmatch(p,"bax"))
+-- inspect(lpegmatch(p,"abxyz"))
+-- inspect(lpegmatch(p,"foobarbefcrap"))
+
+-- local t = { ["^"] = 1, ["^^"] = 2, ["^^^"] = 3, ["^^^^"] = 4 }
+-- local p = lpeg.Cs((lpeg.utfchartabletopattern(t)/t + 1)^1)
+-- inspect(lpegmatch(p," ^ ^^ ^^^ ^^^^ ^^^^^ ^^^^^^ ^^^^^^^ "))
+
+-- local t = { ["^^"] = 2, ["^^^"] = 3, ["^^^^"] = 4 }
+-- local p = lpeg.Cs((lpeg.utfchartabletopattern(t)/t + 1)^1)
+-- inspect(lpegmatch(p," ^ ^^ ^^^ ^^^^ ^^^^^ ^^^^^^ ^^^^^^^ "))
+
+-- lpeg.utfchartabletopattern {
-- utfchar(0x00A0), -- nbsp
-- utfchar(0x2000), -- enquad
-- utfchar(0x2001), -- emquad
@@ -964,7 +1030,7 @@ end
-- utfchar(0x200B), -- zerowidthspace
-- utfchar(0x202F), -- narrownobreakspace
-- utfchar(0x205F), -- math thinspace
--- } )
+-- }
-- a few handy ones:
--
diff --git a/src/fontloader/misc/fontloader-l-math.lua b/src/fontloader/misc/fontloader-l-math.lua
index 43f60b5..ec62919 100644
--- a/src/fontloader/misc/fontloader-l-math.lua
+++ b/src/fontloader/misc/fontloader-l-math.lua
@@ -8,6 +8,10 @@ if not modules then modules = { } end modules ['l-math'] = {
local floor, sin, cos, tan = math.floor, math.sin, math.cos, math.tan
+if not math.ceiling then
+ math.ceiling = math.ceil
+end
+
if not math.round then
function math.round(x) return floor(x + 0.5) end
end
diff --git a/src/fontloader/misc/fontloader-l-table.lua b/src/fontloader/misc/fontloader-l-table.lua
index 97e0441..b02f210 100644
--- a/src/fontloader/misc/fontloader-l-table.lua
+++ b/src/fontloader/misc/fontloader-l-table.lua
@@ -39,7 +39,7 @@ end
function table.keys(t)
if t then
local keys, k = { }, 0
- for key, _ in next, t do
+ for key in next, t do
k = k + 1
keys[k] = key
end
@@ -50,44 +50,126 @@ function table.keys(t)
end
-- local function compare(a,b)
--- local ta, tb = type(a), type(b) -- needed, else 11 < 2
--- if ta == tb then
+-- local ta = type(a) -- needed, else 11 < 2
+-- local tb = type(b) -- needed, else 11 < 2
+-- if ta == tb and ta == "number" then
-- return a < b
-- else
-- return tostring(a) < tostring(b) -- not that efficient
-- end
-- end
+-- local function compare(a,b)
+-- local ta = type(a) -- needed, else 11 < 2
+-- local tb = type(b) -- needed, else 11 < 2
+-- if ta == tb and (ta == "number" or ta == "string") then
+-- return a < b
+-- else
+-- return tostring(a) < tostring(b) -- not that efficient
+-- end
+-- end
+
+-- local function sortedkeys(tab)
+-- if tab then
+-- local srt, category, s = { }, 0, 0 -- 0=unknown 1=string, 2=number 3=mixed
+-- for key in next, tab do
+-- s = s + 1
+-- srt[s] = key
+-- if category == 3 then
+-- -- no further check
+-- else
+-- local tkey = type(key)
+-- if tkey == "string" then
+-- category = (category == 2 and 3) or 1
+-- elseif tkey == "number" then
+-- category = (category == 1 and 3) or 2
+-- else
+-- category = 3
+-- end
+-- end
+-- end
+-- if category == 0 or category == 3 then
+-- sort(srt,compare)
+-- else
+-- sort(srt)
+-- end
+-- return srt
+-- else
+-- return { }
+-- end
+-- end
+
+-- local function compare(a,b)
+-- local ta = type(a) -- needed, else 11 < 2
+-- local tb = type(b) -- needed, else 11 < 2
+-- if ta == tb and (ta == "number" or ta == "string") then
+-- return a < b
+-- else
+-- return tostring(a) < tostring(b) -- not that efficient
+-- end
+-- end
+
+-- local function compare(a,b)
+-- local ta = type(a) -- needed, else 11 < 2
+-- if ta == "number" or ta == "string" then
+-- local tb = type(b) -- needed, else 11 < 2
+-- if ta == tb then
+-- return a < b
+-- end
+-- end
+-- return tostring(a) < tostring(b) -- not that efficient
+-- end
+
local function compare(a,b)
local ta = type(a) -- needed, else 11 < 2
- local tb = type(b) -- needed, else 11 < 2
- if ta == tb and ta == "number" then
- return a < b
- else
- return tostring(a) < tostring(b) -- not that efficient
+ if ta == "number" then
+ local tb = type(b) -- needed, else 11 < 2
+ if ta == tb then
+ return a < b
+ elseif tb == "string" then
+ return tostring(a) < b
+ end
+ elseif ta == "string" then
+ local tb = type(b) -- needed, else 11 < 2
+ if ta == tb then
+ return a < b
+ else
+ return a < tostring(b)
+ end
end
+ return tostring(a) < tostring(b) -- not that efficient
end
local function sortedkeys(tab)
if tab then
local srt, category, s = { }, 0, 0 -- 0=unknown 1=string, 2=number 3=mixed
- for key,_ in next, tab do
+ for key in next, tab do
s = s + 1
srt[s] = key
if category == 3 then
-- no further check
+ elseif category == 1 then
+ if type(key) ~= "string" then
+ category = 3
+ end
+ elseif category == 2 then
+ if type(key) ~= "number" then
+ category = 3
+ end
else
local tkey = type(key)
if tkey == "string" then
- category = (category == 2 and 3) or 1
+ category = 1
elseif tkey == "number" then
- category = (category == 1 and 3) or 2
+ category = 2
else
category = 3
end
end
end
- if category == 0 or category == 3 then
+ if s < 2 then
+ -- nothing to sort
+ elseif category == 3 then
sort(srt,compare)
else
sort(srt)
@@ -101,13 +183,15 @@ end
local function sortedhashonly(tab)
if tab then
local srt, s = { }, 0
- for key,_ in next, tab do
+ for key in next, tab do
if type(key) == "string" then
s = s + 1
srt[s] = key
end
end
- sort(srt)
+ if s > 1 then
+ sort(srt)
+ end
return srt
else
return { }
@@ -117,13 +201,15 @@ end
local function sortedindexonly(tab)
if tab then
local srt, s = { }, 0
- for key,_ in next, tab do
+ for key in next, tab do
if type(key) == "number" then
s = s + 1
srt[s] = key
end
end
- sort(srt)
+ if s > 1 then
+ sort(srt)
+ end
return srt
else
return { }
@@ -133,13 +219,15 @@ end
local function sortedhashkeys(tab,cmp) -- fast one
if tab then
local srt, s = { }, 0
- for key,_ in next, tab do
+ for key in next, tab do
if key then
s= s + 1
srt[s] = key
end
end
- sort(srt,cmp)
+ if s > 1 then
+ sort(srt,cmp)
+ end
return srt
else
return { }
@@ -149,7 +237,7 @@ end
function table.allkeys(t)
local keys = { }
for k, v in next, t do
- for k, v in next, v do
+ for k in next, v do
keys[k] = true
end
end
@@ -172,19 +260,21 @@ local function sortedhash(t,cmp)
else
s = sortedkeys(t) -- the robust one
end
- local n = 0
local m = #s
- local function kv() -- (s)
- if n < m then
- n = n + 1
- local k = s[n]
- return k, t[k]
+ if m == 1 then
+ return next, t
+ elseif m > 0 then
+ local n = 0
+ return function()
+ if n < m then
+ n = n + 1
+ local k = s[n]
+ return k, t[k]
+ end
end
end
- return kv -- , s
- else
- return nothing
end
+ return nothing
end
table.sortedhash = sortedhash
@@ -328,7 +418,7 @@ end
local function copy(t, tables) -- taken from lua wiki, slightly adapted
tables = tables or { }
- local tcopy = {}
+ local tcopy = { }
if not tables[t] then
tables[t] = tcopy
end
@@ -388,7 +478,7 @@ function table.fromhash(t)
return hsh
end
-local noquotes, hexify, handle, reduce, compact, inline, functions
+local noquotes, hexify, handle, compact, inline, functions
local reserved = table.tohash { -- intercept a language inconvenience: no reserved words as key
'and', 'break', 'do', 'else', 'elseif', 'end', 'false', 'for', 'function', 'if',
@@ -396,33 +486,67 @@ local reserved = table.tohash { -- intercept a language inconvenience: no reserv
'NaN', 'goto',
}
+-- local function simple_table(t)
+-- if #t > 0 then
+-- local n = 0
+-- for _,v in next, t do
+-- n = n + 1
+-- end
+-- if n == #t then
+-- local tt, nt = { }, 0
+-- for i=1,#t do
+-- local v = t[i]
+-- local tv = type(v)
+-- if tv == "number" then
+-- nt = nt + 1
+-- if hexify then
+-- tt[nt] = format("0x%X",v)
+-- else
+-- tt[nt] = tostring(v) -- tostring not needed
+-- end
+-- elseif tv == "string" then
+-- nt = nt + 1
+-- tt[nt] = format("%q",v)
+-- elseif tv == "boolean" then
+-- nt = nt + 1
+-- tt[nt] = v and "true" or "false"
+-- else
+-- return nil
+-- end
+-- end
+-- return tt
+-- end
+-- end
+-- return nil
+-- end
+
local function simple_table(t)
- if #t > 0 then
+ local nt = #t
+ if nt > 0 then
local n = 0
for _,v in next, t do
n = n + 1
+ -- if type(v) == "table" then
+ -- return nil
+ -- end
end
- if n == #t then
- local tt, nt = { }, 0
- for i=1,#t do
+ if n == nt then
+ local tt = { }
+ for i=1,nt do
local v = t[i]
local tv = type(v)
if tv == "number" then
- nt = nt + 1
if hexify then
- tt[nt] = format("0x%X",v)
+ tt[i] = format("0x%X",v)
else
- tt[nt] = tostring(v) -- tostring not needed
+ tt[i] = tostring(v) -- tostring not needed
end
elseif tv == "string" then
- nt = nt + 1
- tt[nt] = format("%q",v)
+ tt[i] = format("%q",v)
elseif tv == "boolean" then
- nt = nt + 1
- tt[nt] = v and "true" or "false"
+ tt[i] = v and "true" or "false"
else
- tt = nil
- break
+ return nil
end
end
return tt
@@ -480,14 +604,6 @@ local function do_serialize(root,name,depth,level,indexed)
end
-- we could check for k (index) being number (cardinal)
if root and next(root) ~= nil then
- -- local first, last = nil, 0 -- #root cannot be trusted here (will be ok in 5.2 when ipairs is gone)
- -- if compact then
- -- -- NOT: for k=1,#root do (we need to quit at nil)
- -- for k,v in ipairs(root) do -- can we use next?
- -- if not first then first = k end
- -- last = last + 1
- -- end
- -- end
local first, last = nil, 0
if compact then
last = #root
@@ -503,12 +619,10 @@ local function do_serialize(root,name,depth,level,indexed)
end
local sk = sortedkeys(root)
for i=1,#sk do
- local k = sk[i]
- local v = root[k]
- --~ if v == root then
- -- circular
- --~ else
- local tv, tk = type(v), type(k)
+ local k = sk[i]
+ local v = root[k]
+ local tv = type(v)
+ local tk = type(k)
if compact and first and tk == "number" and k >= first and k <= last then
if tv == "number" then
if hexify then
@@ -517,11 +631,7 @@ local function do_serialize(root,name,depth,level,indexed)
handle(format("%s %s,",depth,v)) -- %.99g
end
elseif tv == "string" then
- if reduce and tonumber(v) then
- handle(format("%s %s,",depth,v))
- else
- handle(format("%s %q,",depth,v))
- end
+ handle(format("%s %q,",depth,v))
elseif tv == "table" then
if next(v) == nil then
handle(format("%s {},",depth))
@@ -577,34 +687,18 @@ local function do_serialize(root,name,depth,level,indexed)
end
end
elseif tv == "string" then
- if reduce and tonumber(v) then
- if tk == "number" then
- if hexify then
- handle(format("%s [0x%X]=%s,",depth,k,v))
- else
- handle(format("%s [%s]=%s,",depth,k,v))
- end
- elseif tk == "boolean" then
- handle(format("%s [%s]=%s,",depth,k and "true" or "false",v))
- elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
- handle(format("%s %s=%s,",depth,k,v))
+ if tk == "number" then
+ if hexify then
+ handle(format("%s [0x%X]=%q,",depth,k,v))
else
- handle(format("%s [%q]=%s,",depth,k,v))
+ handle(format("%s [%s]=%q,",depth,k,v))
end
+ elseif tk == "boolean" then
+ handle(format("%s [%s]=%q,",depth,k and "true" or "false",v))
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ handle(format("%s %s=%q,",depth,k,v))
else
- if tk == "number" then
- if hexify then
- handle(format("%s [0x%X]=%q,",depth,k,v))
- else
- handle(format("%s [%s]=%q,",depth,k,v))
- end
- elseif tk == "boolean" then
- handle(format("%s [%s]=%q,",depth,k and "true" or "false",v))
- elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
- handle(format("%s %s=%q,",depth,k,v))
- else
- handle(format("%s [%q]=%q,",depth,k,v))
- end
+ handle(format("%s [%q]=%q,",depth,k,v))
end
elseif tv == "table" then
if next(v) == nil then
@@ -690,7 +784,6 @@ local function do_serialize(root,name,depth,level,indexed)
handle(format("%s [%q]=%q,",depth,k,tostring(v)))
end
end
- --~ end
end
end
if level > 0 then
@@ -707,7 +800,6 @@ local function serialize(_handle,root,name,specification) -- handle wins
noquotes = specification.noquotes
hexify = specification.hexify
handle = _handle or specification.handle or print
- reduce = specification.reduce or false
functions = specification.functions
compact = specification.compact
inline = specification.inline and compact
@@ -724,7 +816,6 @@ local function serialize(_handle,root,name,specification) -- handle wins
noquotes = false
hexify = false
handle = _handle or print
- reduce = false
compact = true
inline = true
functions = true
@@ -798,15 +889,6 @@ end
table.tohandle = serialize
--- sometimes tables are real use (zapfino extra pro is some 85M) in which
--- case a stepwise serialization is nice; actually, we could consider:
---
--- for line in table.serializer(root,name,reduce,noquotes) do
--- ...(line)
--- end
---
--- so this is on the todo list
-
local maxtab = 2*1024
function table.tofile(filename,root,name,specification)
diff --git a/src/fontloader/misc/fontloader-mplib.tex b/src/fontloader/misc/fontloader-mplib.tex
index 8af9f2d..09dd179 100644
--- a/src/fontloader/misc/fontloader-mplib.tex
+++ b/src/fontloader/misc/fontloader-mplib.tex
@@ -61,6 +61,7 @@
%D Now load the needed \LUA\ code.
\directlua{dofile(kpse.find_file('luatex-mplib.lua'))}
+% \directlua{dofile(resolvers.findfile('luatex-mplib.lua'))}
%D The following code takes care of encapsulating the literals:
diff --git a/src/fontloader/misc/fontloader-plain.tex b/src/fontloader/misc/fontloader-plain.tex
index 1ea8558..c9a9e36 100644
--- a/src/fontloader/misc/fontloader-plain.tex
+++ b/src/fontloader/misc/fontloader-plain.tex
@@ -20,6 +20,7 @@
\input {luatex-math}%
\input {luatex-languages}%
\input {luatex-mplib}%
+ % \input {luatex-gadgets}%
}
\edef\fmtversion{\fmtversion+luatex}
diff --git a/src/fontloader/misc/fontloader-util-str.lua b/src/fontloader/misc/fontloader-util-str.lua
index a677a82..c2139b1 100644
--- a/src/fontloader/misc/fontloader-util-str.lua
+++ b/src/fontloader/misc/fontloader-util-str.lua
@@ -44,7 +44,12 @@ end
if not number then number = { } end -- temp hack for luatex-fonts
-local stripper = patterns.stripzeros
+local stripper = patterns.stripzeros
+local newline = patterns.newline
+local endofstring = patterns.endofstring
+local whitespace = patterns.whitespace
+local spacer = patterns.spacer
+local spaceortab = patterns.spaceortab
local function points(n)
n = tonumber(n)
@@ -62,12 +67,12 @@ number.basepoints = basepoints
-- str = " \n \ntest \n test\ntest "
-- print("["..string.gsub(string.collapsecrlf(str),"\n","+").."]")
-local rubish = patterns.spaceortab^0 * patterns.newline
-local anyrubish = patterns.spaceortab + patterns.newline
+local rubish = spaceortab^0 * newline
+local anyrubish = spaceortab + newline
local anything = patterns.anything
-local stripped = (patterns.spaceortab^1 / "") * patterns.newline
+local stripped = (spaceortab^1 / "") * newline
local leading = rubish^0 / ""
-local trailing = (anyrubish^1 * patterns.endofstring) / ""
+local trailing = (anyrubish^1 * endofstring) / ""
local redundant = rubish^3 / "\n"
local pattern = Cs(leading * (trailing + redundant + stripped + anything)^0)
@@ -129,7 +134,7 @@ local pattern =
return ""
end
end
- + patterns.newline * Cp() / function(position)
+ + newline * Cp() / function(position)
extra, start = 0, position
end
+ patterns.anything
@@ -162,11 +167,6 @@ end
-- return str
-- end
-local newline = patterns.newline
-local endofstring = patterns.endofstring
-local whitespace = patterns.whitespace
-local spacer = patterns.spacer
-
local space = spacer^0
local nospace = space/""
local endofline = nospace * newline
@@ -1117,3 +1117,9 @@ local pattern =
function string.optionalquoted(str)
return lpegmatch(pattern,str) or str
end
+
+local pattern = Cs((newline / (os.newline or "\r") + 1)^0)
+
+function string.replacenewlines(str)
+ return lpegmatch(pattern,str)
+end
diff --git a/src/fontloader/runtime/fontloader-fontloader.lua b/src/fontloader/runtime/fontloader-fontloader.lua
index b662152..d8095a2 100644
--- a/src/fontloader/runtime/fontloader-fontloader.lua
+++ b/src/fontloader/runtime/fontloader-fontloader.lua
@@ -1,6 +1,6 @@
-- merged file : luatex-fonts-merged.lua
-- parent file : luatex-fonts.lua
--- merge date : 03/10/15 12:09:17
+-- merge date : 05/24/15 12:42:55
do -- begin closure to overcome local limits and interference
@@ -660,62 +660,142 @@ function lpeg.append(list,pp,delayed,checked)
end
return p
end
-local function make(t,hash)
- local p=P(false)
+local p_false=P(false)
+local p_true=P(true)
+local function make(t)
+ local function making(t)
+ local p=p_false
+ local keys=sortedkeys(t)
+ for i=1,#keys do
+ local k=keys[i]
+ if k~="" then
+ local v=t[k]
+ if v==true then
+ p=p+P(k)*p_true
+ elseif v==false then
+ else
+ p=p+P(k)*making(v)
+ end
+ end
+ end
+ if t[""] then
+ p=p+p_true
+ end
+ return p
+ end
+ local p=p_false
local keys=sortedkeys(t)
for i=1,#keys do
local k=keys[i]
- local v=t[k]
- local h=hash[v]
- if h then
- if next(v) then
- p=p+P(k)*(make(v,hash)+P(true))
+ if k~="" then
+ local v=t[k]
+ if v==true then
+ p=p+P(k)*p_true
+ elseif v==false then
else
- p=p+P(k)*P(true)
+ p=p+P(k)*making(v)
end
- else
- if next(v) then
- p=p+P(k)*make(v,hash)
+ end
+ end
+ return p
+end
+local function collapse(t,x)
+ if type(t)~="table" then
+ return t,x
+ else
+ local n=next(t)
+ if n==nil then
+ return t,x
+ elseif next(t,n)==nil then
+ local k=n
+ local v=t[k]
+ if type(v)=="table" then
+ return collapse(v,x..k)
else
- p=p+P(k)
+ return v,x..k
end
+ else
+ local tt={}
+ for k,v in next,t do
+ local vv,kk=collapse(v,k)
+ tt[kk]=vv
+ end
+ return tt,x
end
end
- return p
end
function lpeg.utfchartabletopattern(list)
local tree={}
- local hash={}
local n=#list
if n==0 then
for s in next,list do
local t=tree
+ local p,pk
for c in gmatch(s,".") do
- local tc=t[c]
- if not tc then
- tc={}
- t[c]=tc
+ if t==true then
+ t={ [c]=true,[""]=true }
+ p[pk]=t
+ p=t
+ t=false
+ elseif t==false then
+ t={ [c]=false }
+ p[pk]=t
+ p=t
+ t=false
+ else
+ local tc=t[c]
+ if not tc then
+ tc=false
+ t[c]=false
+ end
+ p=t
+ t=tc
end
- t=tc
+ pk=c
+ end
+ if t==false then
+ p[pk]=true
+ elseif t==true then
+ else
+ t[""]=true
end
- hash[t]=s
end
else
for i=1,n do
- local t=tree
local s=list[i]
+ local t=tree
+ local p,pk
for c in gmatch(s,".") do
- local tc=t[c]
- if not tc then
- tc={}
- t[c]=tc
+ if t==true then
+ t={ [c]=true,[""]=true }
+ p[pk]=t
+ p=t
+ t=false
+ elseif t==false then
+ t={ [c]=false }
+ p[pk]=t
+ p=t
+ t=false
+ else
+ local tc=t[c]
+ if not tc then
+ tc=false
+ t[c]=false
+ end
+ p=t
+ t=tc
end
- t=tc
+ pk=c
+ end
+ if t==false then
+ p[pk]=true
+ elseif t==true then
+ else
+ t[""]=true
end
- hash[t]=s
end
end
- return make(tree,hash)
+ return make(tree)
end
patterns.containseol=lpeg.finder(eol)
local function nextstep(n,step,result)
@@ -961,7 +1041,7 @@ end
function table.keys(t)
if t then
local keys,k={},0
- for key,_ in next,t do
+ for key in next,t do
k=k+1
keys[k]=key
end
@@ -972,32 +1052,51 @@ function table.keys(t)
end
local function compare(a,b)
local ta=type(a)
- local tb=type(b)
- if ta==tb and ta=="number" then
- return a<b
- else
- return tostring(a)<tostring(b)
+ if ta=="number" then
+ local tb=type(b)
+ if ta==tb then
+ return a<b
+ elseif tb=="string" then
+ return tostring(a)<b
+ end
+ elseif ta=="string" then
+ local tb=type(b)
+ if ta==tb then
+ return a<b
+ else
+ return a<tostring(b)
+ end
end
+ return tostring(a)<tostring(b)
end
local function sortedkeys(tab)
if tab then
local srt,category,s={},0,0
- for key,_ in next,tab do
+ for key in next,tab do
s=s+1
srt[s]=key
if category==3 then
+ elseif category==1 then
+ if type(key)~="string" then
+ category=3
+ end
+ elseif category==2 then
+ if type(key)~="number" then
+ category=3
+ end
else
local tkey=type(key)
if tkey=="string" then
- category=(category==2 and 3) or 1
+ category=1
elseif tkey=="number" then
- category=(category==1 and 3) or 2
+ category=2
else
category=3
end
end
end
- if category==0 or category==3 then
+ if s<2 then
+ elseif category==3 then
sort(srt,compare)
else
sort(srt)
@@ -1010,13 +1109,15 @@ end
local function sortedhashonly(tab)
if tab then
local srt,s={},0
- for key,_ in next,tab do
+ for key in next,tab do
if type(key)=="string" then
s=s+1
srt[s]=key
end
end
- sort(srt)
+ if s>1 then
+ sort(srt)
+ end
return srt
else
return {}
@@ -1025,13 +1126,15 @@ end
local function sortedindexonly(tab)
if tab then
local srt,s={},0
- for key,_ in next,tab do
+ for key in next,tab do
if type(key)=="number" then
s=s+1
srt[s]=key
end
end
- sort(srt)
+ if s>1 then
+ sort(srt)
+ end
return srt
else
return {}
@@ -1040,13 +1143,15 @@ end
local function sortedhashkeys(tab,cmp)
if tab then
local srt,s={},0
- for key,_ in next,tab do
+ for key in next,tab do
if key then
s=s+1
srt[s]=key
end
end
- sort(srt,cmp)
+ if s>1 then
+ sort(srt,cmp)
+ end
return srt
else
return {}
@@ -1055,7 +1160,7 @@ end
function table.allkeys(t)
local keys={}
for k,v in next,t do
- for k,v in next,v do
+ for k in next,v do
keys[k]=true
end
end
@@ -1074,19 +1179,21 @@ local function sortedhash(t,cmp)
else
s=sortedkeys(t)
end
- local n=0
local m=#s
- local function kv()
- if n<m then
- n=n+1
- local k=s[n]
- return k,t[k]
+ if m==1 then
+ return next,t
+ elseif m>0 then
+ local n=0
+ return function()
+ if n<m then
+ n=n+1
+ local k=s[n]
+ return k,t[k]
+ end
end
end
- return kv
- else
- return nothing
end
+ return nothing
end
table.sortedhash=sortedhash
table.sortedpairs=sortedhash
@@ -1228,39 +1335,36 @@ function table.fromhash(t)
end
return hsh
end
-local noquotes,hexify,handle,reduce,compact,inline,functions
+local noquotes,hexify,handle,compact,inline,functions
local reserved=table.tohash {
'and','break','do','else','elseif','end','false','for','function','if',
'in','local','nil','not','or','repeat','return','then','true','until','while',
'NaN','goto',
}
local function simple_table(t)
- if #t>0 then
+ local nt=#t
+ if nt>0 then
local n=0
for _,v in next,t do
n=n+1
end
- if n==#t then
- local tt,nt={},0
- for i=1,#t do
+ if n==nt then
+ local tt={}
+ for i=1,nt do
local v=t[i]
local tv=type(v)
if tv=="number" then
- nt=nt+1
if hexify then
- tt[nt]=format("0x%X",v)
+ tt[i]=format("0x%X",v)
else
- tt[nt]=tostring(v)
+ tt[i]=tostring(v)
end
elseif tv=="string" then
- nt=nt+1
- tt[nt]=format("%q",v)
+ tt[i]=format("%q",v)
elseif tv=="boolean" then
- nt=nt+1
- tt[nt]=v and "true" or "false"
+ tt[i]=v and "true" or "false"
else
- tt=nil
- break
+ return nil
end
end
return tt
@@ -1314,7 +1418,8 @@ local function do_serialize(root,name,depth,level,indexed)
for i=1,#sk do
local k=sk[i]
local v=root[k]
- local tv,tk=type(v),type(k)
+ local tv=type(v)
+ local tk=type(k)
if compact and first and tk=="number" and k>=first and k<=last then
if tv=="number" then
if hexify then
@@ -1323,11 +1428,7 @@ local function do_serialize(root,name,depth,level,indexed)
handle(format("%s %s,",depth,v))
end
elseif tv=="string" then
- if reduce and tonumber(v) then
- handle(format("%s %s,",depth,v))
- else
- handle(format("%s %q,",depth,v))
- end
+ handle(format("%s %q,",depth,v))
elseif tv=="table" then
if next(v)==nil then
handle(format("%s {},",depth))
@@ -1383,34 +1484,18 @@ local function do_serialize(root,name,depth,level,indexed)
end
end
elseif tv=="string" then
- if reduce and tonumber(v) then
- if tk=="number" then
- if hexify then
- handle(format("%s [0x%X]=%s,",depth,k,v))
- else
- handle(format("%s [%s]=%s,",depth,k,v))
- end
- elseif tk=="boolean" then
- handle(format("%s [%s]=%s,",depth,k and "true" or "false",v))
- elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
- handle(format("%s %s=%s,",depth,k,v))
+ if tk=="number" then
+ if hexify then
+ handle(format("%s [0x%X]=%q,",depth,k,v))
else
- handle(format("%s [%q]=%s,",depth,k,v))
+ handle(format("%s [%s]=%q,",depth,k,v))
end
+ elseif tk=="boolean" then
+ handle(format("%s [%s]=%q,",depth,k and "true" or "false",v))
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ handle(format("%s %s=%q,",depth,k,v))
else
- if tk=="number" then
- if hexify then
- handle(format("%s [0x%X]=%q,",depth,k,v))
- else
- handle(format("%s [%s]=%q,",depth,k,v))
- end
- elseif tk=="boolean" then
- handle(format("%s [%s]=%q,",depth,k and "true" or "false",v))
- elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
- handle(format("%s %s=%q,",depth,k,v))
- else
- handle(format("%s [%q]=%q,",depth,k,v))
- end
+ handle(format("%s [%q]=%q,",depth,k,v))
end
elseif tv=="table" then
if next(v)==nil then
@@ -1507,7 +1592,6 @@ local function serialize(_handle,root,name,specification)
noquotes=specification.noquotes
hexify=specification.hexify
handle=_handle or specification.handle or print
- reduce=specification.reduce or false
functions=specification.functions
compact=specification.compact
inline=specification.inline and compact
@@ -1524,7 +1608,6 @@ local function serialize(_handle,root,name,specification)
noquotes=false
hexify=false
handle=_handle or print
- reduce=false
compact=true
inline=true
functions=true
@@ -2658,6 +2741,9 @@ if not modules then modules={} end modules ['l-math']={
license="see context related readme files"
}
local floor,sin,cos,tan=math.floor,math.sin,math.cos,math.tan
+if not math.ceiling then
+ math.ceiling=math.ceil
+end
if not math.round then
function math.round(x) return floor(x+0.5) end
end
@@ -2715,6 +2801,11 @@ else
end
if not number then number={} end
local stripper=patterns.stripzeros
+local newline=patterns.newline
+local endofstring=patterns.endofstring
+local whitespace=patterns.whitespace
+local spacer=patterns.spacer
+local spaceortab=patterns.spaceortab
local function points(n)
n=tonumber(n)
return (not n or n==0) and "0pt" or lpegmatch(stripper,format("%.5fpt",n/65536))
@@ -2725,12 +2816,12 @@ local function basepoints(n)
end
number.points=points
number.basepoints=basepoints
-local rubish=patterns.spaceortab^0*patterns.newline
-local anyrubish=patterns.spaceortab+patterns.newline
+local rubish=spaceortab^0*newline
+local anyrubish=spaceortab+newline
local anything=patterns.anything
-local stripped=(patterns.spaceortab^1/"")*patterns.newline
+local stripped=(spaceortab^1/"")*newline
local leading=rubish^0/""
-local trailing=(anyrubish^1*patterns.endofstring)/""
+local trailing=(anyrubish^1*endofstring)/""
local redundant=rubish^3/"\n"
local pattern=Cs(leading*(trailing+redundant+stripped+anything)^0)
function strings.collapsecrlf(str)
@@ -2776,17 +2867,13 @@ local pattern=Carg(1)/function(t)
else
return ""
end
- end+patterns.newline*Cp()/function(position)
+ end+newline*Cp()/function(position)
extra,start=0,position
end+patterns.anything
)^1)
function strings.tabtospace(str,tab)
return lpegmatch(pattern,str,1,tab or 7)
end
-local newline=patterns.newline
-local endofstring=patterns.endofstring
-local whitespace=patterns.whitespace
-local spacer=patterns.spacer
local space=spacer^0
local nospace=space/""
local endofline=nospace*newline
@@ -3355,6 +3442,10 @@ local pattern=Cs(dquote*(equote-P(-2))^0*dquote)
function string.optionalquoted(str)
return lpegmatch(pattern,str) or str
end
+local pattern=Cs((newline/(os.newline or "\r")+1)^0)
+function string.replacenewlines(str)
+ return lpegmatch(pattern,str)
+end
end -- closure
@@ -4336,7 +4427,8 @@ function constructors.scale(tfmdata,specification)
local stackmath=not properties.nostackmath
local nonames=properties.noglyphnames
local haskerns=properties.haskerns or properties.mode=="base"
- local hasligatures=properties.hasligatures or properties.mode=="base"
+ local hasligatures=properties.hasligatures or properties.mode=="base"
+ local realdimensions=properties.realdimensions
if changed and not next(changed) then
changed=false
end
@@ -4417,6 +4509,26 @@ function constructors.scale(tfmdata,specification)
local width=description.width
local height=description.height
local depth=description.depth
+ if realdimensions then
+ if not height or height==0 then
+ local bb=description.boundingbox
+ local ht=bb[4]
+ if ht~=0 then
+ height=ht
+ end
+ if not depth or depth==0 then
+ local dp=-bb[2]
+ if dp~=0 then
+ depth=dp
+ end
+ end
+ elseif not depth or depth==0 then
+ local dp=-description.boundingbox[2]
+ if dp~=0 then
+ depth=dp
+ end
+ end
+ end
if width then width=hdelta*width else width=scaledwidth end
if height then height=vdelta*height else height=scaledheight end
if depth and depth~=0 then
@@ -5280,6 +5392,7 @@ local report_fonts=logs.reporter("fonts","loading")
local fonts=fonts or {}
local mappings=fonts.mappings or {}
fonts.mappings=mappings
+local allocate=utilities.storage.allocate
local function loadlumtable(filename)
local lumname=file.replacesuffix(file.basename(filename),"lum")
local lumfile=resolvers.findfile(lumname,"map") or ""
@@ -5381,7 +5494,7 @@ mappings.fromunicode16=fromunicode16
local ligseparator=P("_")
local varseparator=P(".")
local namesplitter=Ct(C((1-ligseparator-varseparator)^1)*(ligseparator*C((1-ligseparator-varseparator)^1))^0)
-local overloads={
+local overloads=allocate {
IJ={ name="I_J",unicode={ 0x49,0x4A },mess=0x0132 },
ij={ name="i_j",unicode={ 0x69,0x6A },mess=0x0133 },
ff={ name="f_f",unicode={ 0x66,0x66 },mess=0xFB00 },
@@ -7050,6 +7163,7 @@ local stoptiming=statistics.stoptiming
local elapsedtime=statistics.elapsedtime
local findbinfile=resolvers.findbinfile
local trace_private=false registertracker("otf.private",function(v) trace_private=v end)
+local trace_subfonts=false registertracker("otf.subfonts",function(v) trace_subfonts=v end)
local trace_loading=false registertracker("otf.loading",function(v) trace_loading=v end)
local trace_features=false registertracker("otf.features",function(v) trace_features=v end)
local trace_dynamics=false registertracker("otf.dynamics",function(v) trace_dynamics=v end)
@@ -7062,7 +7176,7 @@ local report_otf=logs.reporter("fonts","otf loading")
local fonts=fonts
local otf=fonts.handlers.otf
otf.glists={ "gsub","gpos" }
-otf.version=2.803
+otf.version=2.812
otf.cache=containers.define("fonts","otf",otf.version,true)
local hashes=fonts.hashes
local definers=fonts.definers
@@ -7551,15 +7665,16 @@ actions["add dimensions"]=function(data,filename)
report_otf("mark %a with width %b found in %a",d.name or "<noname>",wd,basename)
end
if bb then
- local ht,dp=bb[4],-bb[2]
- if ht==0 or ht<0 then
- else
- d.height=ht
- end
- if dp==0 or dp<0 then
- else
- d.depth=dp
- end
+ local ht=bb[4]
+ local dp=-bb[2]
+ if ht==0 or ht<0 then
+ else
+ d.height=ht
+ end
+ if dp==0 or dp<0 then
+ else
+ d.depth=dp
+ end
end
end
end
@@ -7594,6 +7709,7 @@ local function somecopy(old)
end
end
actions["prepare glyphs"]=function(data,filename,raw)
+ local tableversion=tonumber(raw.table_version) or 0
local rawglyphs=raw.glyphs
local rawsubfonts=raw.subfonts
local rawcidinfo=raw.cidinfo
@@ -7614,66 +7730,114 @@ actions["prepare glyphs"]=function(data,filename,raw)
local cidmap=fonts.cid.getmap(rawcidinfo)
if cidmap then
rawcidinfo.usedname=cidmap.usedname
- local nofnames,nofunicodes=0,0
- local cidunicodes,cidnames=cidmap.unicodes,cidmap.names
+ local nofnames=0
+ local nofunicodes=0
+ local cidunicodes=cidmap.unicodes
+ local cidnames=cidmap.names
+ local cidtotal=0
+ local unique=trace_subfonts and {}
for cidindex=1,#rawsubfonts do
local subfont=rawsubfonts[cidindex]
local cidglyphs=subfont.glyphs
if includesubfonts then
metadata.subfonts[cidindex]=somecopy(subfont)
end
- for index=0,subfont.glyphcnt-1 do
- local glyph=cidglyphs[index]
- if glyph then
- local unicode=glyph.unicode
- if unicode>=0x00E000 and unicode<=0x00F8FF then
- unicode=-1
- elseif unicode>=0x0F0000 and unicode<=0x0FFFFD then
- unicode=-1
- elseif unicode>=0x100000 and unicode<=0x10FFFD then
- unicode=-1
- end
- local name=glyph.name or cidnames[index]
- if not unicode or unicode==-1 then
- unicode=cidunicodes[index]
- end
- if unicode and descriptions[unicode] then
- if trace_private then
- report_otf("preventing glyph %a at index %H to overload unicode %U",name or "noname",index,unicode)
+ local cidcnt,cidmin,cidmax
+ if tableversion>0.3 then
+ cidcnt=subfont.glyphcnt
+ cidmin=subfont.glyphmin
+ cidmax=subfont.glyphmax
+ else
+ cidcnt=subfont.glyphcnt
+ cidmin=0
+ cidmax=cidcnt-1
+ end
+ if trace_subfonts then
+ local cidtot=cidmax-cidmin+1
+ cidtotal=cidtotal+cidtot
+ report_otf("subfont: %i, min: %i, max: %i, cnt: %i, n: %i",cidindex,cidmin,cidmax,cidtot,cidcnt)
+ end
+ if cidcnt>0 then
+ for cidslot=cidmin,cidmax do
+ local glyph=cidglyphs[cidslot]
+ if glyph then
+ local index=tableversion>0.3 and glyph.orig_pos or cidslot
+ if trace_subfonts then
+ unique[index]=true
end
- unicode=-1
- end
- if not unicode or unicode==-1 then
- if not name then
- name=format("u%06X.ctx",private)
+ local unicode=glyph.unicode
+ if unicode>=0x00E000 and unicode<=0x00F8FF then
+ unicode=-1
+ elseif unicode>=0x0F0000 and unicode<=0x0FFFFD then
+ unicode=-1
+ elseif unicode>=0x100000 and unicode<=0x10FFFD then
+ unicode=-1
end
- unicode=private
- unicodes[name]=private
- if trace_private then
- report_otf("glyph %a at index %H is moved to private unicode slot %U",name,index,private)
+ local name=glyph.name or cidnames[index]
+ if not unicode or unicode==-1 then
+ unicode=cidunicodes[index]
end
- private=private+1
- nofnames=nofnames+1
- else
- if not name then
- name=format("u%06X.ctx",unicode)
+ if unicode and descriptions[unicode] then
+ if trace_private then
+ report_otf("preventing glyph %a at index %H to overload unicode %U",name or "noname",index,unicode)
+ end
+ unicode=-1
end
- unicodes[name]=unicode
- nofunicodes=nofunicodes+1
- end
- indices[index]=unicode
- local description={
- boundingbox=glyph.boundingbox,
- name=glyph.name or name or "unknown",
- cidindex=cidindex,
- index=index,
- glyph=glyph,
- }
- descriptions[unicode]=description
- else
+ if not unicode or unicode==-1 then
+ if not name then
+ name=format("u%06X.ctx",private)
+ end
+ unicode=private
+ unicodes[name]=private
+ if trace_private then
+ report_otf("glyph %a at index %H is moved to private unicode slot %U",name,index,private)
+ end
+ private=private+1
+ nofnames=nofnames+1
+ else
+ if not name then
+ name=format("u%06X.ctx",unicode)
+ end
+ unicodes[name]=unicode
+ nofunicodes=nofunicodes+1
+ end
+ indices[index]=unicode
+ local description={
+ boundingbox=glyph.boundingbox,
+ name=name or "unknown",
+ cidindex=cidindex,
+ index=cidslot,
+ glyph=glyph,
+ }
+ descriptions[unicode]=description
+local altuni=glyph.altuni
+if altuni then
+ for i=1,#altuni do
+ local a=altuni[i]
+ local u=a.unicode
+ if u~=unicode then
+ local v=a.variant
+ if v then
+ local vv=variants[v]
+ if vv then
+ vv[u]=unicode
+ else
+ vv={ [u]=unicode }
+ variants[v]=vv
+ end
+ end
+ end
+ end
+end
+ end
end
+ else
+ report_otf("potential problem: no glyphs found in subfont %i",cidindex)
end
end
+ if trace_subfonts then
+ report_otf("nofglyphs: %i, unique: %i",cidtotal,table.count(unique))
+ end
if trace_loading then
report_otf("cid font remapped, %s unicode points, %s symbolic names, %s glyphs",nofunicodes,nofnames,nofunicodes+nofnames)
end
@@ -7684,68 +7848,77 @@ actions["prepare glyphs"]=function(data,filename,raw)
report_otf("font %a has no glyphs",filename)
end
else
- for index=0,raw.glyphcnt-1 do
- local glyph=rawglyphs[index]
- if glyph then
- local unicode=glyph.unicode
- local name=glyph.name
- if not unicode or unicode==-1 then
- unicode=private
- unicodes[name]=private
- if trace_private then
- report_otf("glyph %a at index %H is moved to private unicode slot %U",name,index,private)
- end
- private=private+1
- else
- if unicode>criterium then
- local taken=descriptions[unicode]
- if taken then
- if unicode>=private then
- private=unicode+1
+ local cnt=raw.glyphcnt or 0
+ local min=tableversion>0.3 and raw.glyphmin or 0
+ local max=tableversion>0.3 and raw.glyphmax or (raw.glyphcnt-1)
+ if cnt>0 then
+ for index=min,max do
+ local glyph=rawglyphs[index]
+ if glyph then
+ local unicode=glyph.unicode
+ local name=glyph.name
+ if not unicode or unicode==-1 then
+ unicode=private
+ unicodes[name]=private
+ if trace_private then
+ report_otf("glyph %a at index %H is moved to private unicode slot %U",name,index,private)
+ end
+ private=private+1
+ else
+ if unicode>criterium then
+ local taken=descriptions[unicode]
+ if taken then
+ if unicode>=private then
+ private=unicode+1
+ else
+ private=private+1
+ end
+ descriptions[private]=taken
+ unicodes[taken.name]=private
+ indices[taken.index]=private
+ if trace_private then
+ report_otf("slot %U is moved to %U due to private in font",unicode)
+ end
else
- private=private+1
- end
- descriptions[private]=taken
- unicodes[taken.name]=private
- indices[taken.index]=private
- if trace_private then
- report_otf("slot %U is moved to %U due to private in font",unicode)
- end
- else
- if unicode>=private then
- private=unicode+1
+ if unicode>=private then
+ private=unicode+1
+ end
end
end
+ unicodes[name]=unicode
end
- unicodes[name]=unicode
- end
- indices[index]=unicode
- descriptions[unicode]={
- boundingbox=glyph.boundingbox,
- name=name,
- index=index,
- glyph=glyph,
- }
- local altuni=glyph.altuni
- if altuni then
- for i=1,#altuni do
- local a=altuni[i]
- local u=a.unicode
- local v=a.variant
- if v then
- local vv=variants[v]
- if vv then
- vv[u]=unicode
- else
- vv={ [u]=unicode }
- variants[v]=vv
+ indices[index]=unicode
+ descriptions[unicode]={
+ boundingbox=glyph.boundingbox,
+ name=name,
+ index=index,
+ glyph=glyph,
+ }
+ local altuni=glyph.altuni
+ if altuni then
+ for i=1,#altuni do
+ local a=altuni[i]
+ local u=a.unicode
+ if u~=unicode then
+ local v=a.variant
+ if v then
+ local vv=variants[v]
+ if vv then
+ vv[u]=unicode
+ else
+ vv={ [u]=unicode }
+ variants[v]=vv
+ end
+ end
end
end
end
+ else
+ report_otf("potential problem: glyph %U is used but empty",index)
end
- else
- report_otf("potential problem: glyph %U is used but empty",index)
end
+ else
+ report_otf("potential problem: no glyphs found")
end
end
resources.private=private
@@ -10398,9 +10571,9 @@ local function inject_cursives(glyphs,nofglyphs)
end
end
end
-local function inject_kerns(head,glyphs,nofglyphs)
- for i=1,#glyphs do
- local n=glyphs[i]
+local function inject_kerns(head,list,length)
+ for i=1,length do
+ local n=list[i]
local pn=rawget(properties,n)
if pn then
local i=rawget(pn,"injections")
@@ -10437,6 +10610,9 @@ local function inject_everything(head,where)
end
inject_kerns(head,glyphs,nofglyphs)
end
+ if nofmarks>0 then
+ inject_kerns(head,marks,nofmarks)
+ end
if keepregisteredcounts then
keepregisteredcounts=false
else
@@ -10727,7 +10903,7 @@ local function inject_pairs_only(head,where)
if getsubtype(n)<256 then
local p=rawget(properties,n)
if p then
- local i=rawget(pn,"replaceinjections")
+ local i=rawget(p,"replaceinjections")
if i then
local yoffset=i.yoffset
if yoffset and yoffset~=0 then
@@ -11198,6 +11374,7 @@ local report_chain=logs.reporter("fonts","otf chain")
local report_process=logs.reporter("fonts","otf process")
local report_prepare=logs.reporter("fonts","otf prepare")
local report_warning=logs.reporter("fonts","otf warning")
+local report_run=logs.reporter("fonts","otf run")
registertracker("otf.verbose_chain",function(v) otf.setcontextchain(v and "verbose") end)
registertracker("otf.normal_chain",function(v) otf.setcontextchain(v and "normal") end)
registertracker("otf.replacements","otf.singles,otf.multiples,otf.alternatives,otf.ligatures")
@@ -11220,12 +11397,18 @@ local setprop=nuts.setprop
local getfont=nuts.getfont
local getsubtype=nuts.getsubtype
local getchar=nuts.getchar
+local insert_node_before=nuts.insert_before
local insert_node_after=nuts.insert_after
local delete_node=nuts.delete
+local remove_node=nuts.remove
local copy_node=nuts.copy
+local copy_node_list=nuts.copy_list
local find_node_tail=nuts.tail
local flush_node_list=nuts.flush_list
+local free_node=nuts.free
local end_of_math=nuts.end_of_math
+local traverse_nodes=nuts.traverse
+local traverse_id=nuts.traverse_id
local setmetatableindex=table.setmetatableindex
local zwnj=0x200C
local zwj=0x200D
@@ -11243,6 +11426,8 @@ local math_code=nodecodes.math
local dir_code=whatcodes.dir
local localpar_code=whatcodes.localpar
local discretionary_code=disccodes.discretionary
+local regular_code=disccodes.regular
+local automatic_code=disccodes.automatic
local ligature_code=glyphcodes.ligature
local privateattribute=attributes.private
local a_state=privateattribute('state')
@@ -12596,15 +12781,8 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
break
end
end
- elseif f==2 then
- match=seq[1][32]
else
- for n=f-1,1 do
- if not seq[n][32] then
- match=false
- break
- end
- end
+ match=false
end
end
if match and s>l then
@@ -12654,15 +12832,8 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
break
end
end
- elseif s-l==1 then
- match=seq[s][32]
else
- for n=l+1,s do
- if not seq[n][32] then
- match=false
- break
- end
- end
+ match=false
end
end
end
@@ -15039,6 +15210,8 @@ end
local fonts=fonts
local nodes=nodes
local traverse_id=node.traverse_id
+local free_node=node.free
+local remove_node=node.remove
local glyph_code=nodes.nodecodes.glyph
local disc_code=nodes.nodecodes.disc
local ligaturing=node.ligaturing
@@ -15068,6 +15241,8 @@ function nodes.handlers.nodepass(head)
local basefonts={}
local prevfont=nil
local basefont=nil
+ local variants=nil
+ local redundant=nil
for n in traverse_id(glyph_code,head) do
local font=n.font
if font~=prevfont then
@@ -15089,10 +15264,47 @@ function nodes.handlers.nodepass(head)
basefonts[#basefonts+1]=basefont
end
end
+ local resources=tfmdata.resources
+ variants=resources and resources.variants
+ variants=variants and next(variants) and variants or false
+ end
+ else
+ local tfmdata=fontdata[prevfont]
+ if tfmdata then
+ local resources=tfmdata.resources
+ variants=resources and resources.variants
+ variants=variants and next(variants) and variants or false
+ end
+ end
+ end
+ if variants then
+ local char=n.char
+ if char>=0xFE00 and (char<=0xFE0F or (char>=0xE0100 and char<=0xE01EF)) then
+ local hash=variants[char]
+ if hash then
+ local p=n.prev
+ if p and p.id==glyph_code then
+ local variant=hash[p.char]
+ if variant then
+ p.char=variant
+ if not redundant then
+ redundant={ n }
+ else
+ redundant[#redundant+1]=n
+ end
+ end
+ end
end
end
end
end
+ if redundant then
+ for i=1,#redundant do
+ local n=redundant[i]
+ remove_node(head,n)
+ free_node(n)
+ end
+ end
for d in traverse_id(disc_code,head) do
local r=d.replace
if r then
diff --git a/src/luaotfload-auxiliary.lua b/src/luaotfload-auxiliary.lua
index b3fa795..1ef581e 100644
--- a/src/luaotfload-auxiliary.lua
+++ b/src/luaotfload-auxiliary.lua
@@ -2,10 +2,10 @@
-----------------------------------------------------------------------
-- FILE: luaotfload-auxiliary.lua
-- DESCRIPTION: part of luaotfload
--- REQUIREMENTS: luaotfload 2.5
+-- REQUIREMENTS: luaotfload 2.6
-- AUTHOR: Khaled Hosny, Élie Roux, Philipp Gesang
--- VERSION: 2.5
--- MODIFIED: 2014-01-02 21:24:25+0100
+-- VERSION: 2.6
+-- MODIFIED: 2015-03-29 12:43:26+0200
-----------------------------------------------------------------------
--
diff --git a/src/luaotfload-colors.lua b/src/luaotfload-colors.lua
index 9be2974..ff4dc13 100644
--- a/src/luaotfload-colors.lua
+++ b/src/luaotfload-colors.lua
@@ -1,7 +1,7 @@
if not modules then modules = { } end modules ['luaotfload-colors'] = {
- version = "2.5",
+ version = "2.6",
comment = "companion to luaotfload-main.lua (font color)",
- author = "Khaled Hosny, Elie Roux, Philipp Gesang",
+ author = "Khaled Hosny, Elie Roux, Philipp Gesang, Dohyun Kim",
copyright = "Luaotfload Development Team",
license = "GNU GPL v2.0"
}
@@ -22,19 +22,28 @@ explanation: http://tug.org/pipermail/luatex/2013-May/004305.html
local log = luaotfload.log
local logreport = log.report
-local newnode = node.new
-local nodetype = node.id
-local traverse_nodes = node.traverse
-local insert_node_before = node.insert_before
-local insert_node_after = node.insert_after
+local nodedirect = node.direct
+local newnode = nodedirect.new
+local insert_node_before = nodedirect.insert_before
+local insert_node_after = nodedirect.insert_after
+local todirect = nodedirect.todirect
+local tonode = nodedirect.tonode
+local setfield = nodedirect.setfield
+local getid = nodedirect.getid
+local getfont = nodedirect.getfont
+local getlist = nodedirect.getlist
+local getsubtype = nodedirect.getsubtype
+local getnext = nodedirect.getnext
+local nodetail = nodedirect.tail
+local getattribute = nodedirect.has_attribute
+local setattribute = nodedirect.set_attribute
local texset = tex.set
local texget = tex.get
+local texsettoks = tex.settoks
+local texgettoks = tex.gettoks
local stringformat = string.format
-local stringgsub = string.gsub
-local stringfind = string.find
-local stringsub = string.sub
local otffeatures = fonts.constructors.newfeatures("otf")
local identifiers = fonts.hashes.identifiers
@@ -66,10 +75,11 @@ local lpegmatch = lpeg.match
local C, Cg, Ct, P, R, S = lpeg.C, lpeg.Cg, lpeg.Ct, lpeg.P, lpeg.R, lpeg.S
local digit16 = R("09", "af", "AF")
+local opaque = S("fF") * S("fF")
local octet = C(digit16 * digit16)
local p_rgb = octet * octet * octet
-local p_rgba = p_rgb * octet
+local p_rgba = p_rgb * (octet - opaque)
local valid_digits = C(p_rgba + p_rgb) -- matches eight or six hex digits
local p_Crgb = Cg(octet/hex_to_dec, "red") --- for captures
@@ -174,143 +184,195 @@ end
--- Luatex internal types
+local nodetype = node.id
local glyph_t = nodetype("glyph")
local hlist_t = nodetype("hlist")
local vlist_t = nodetype("vlist")
local whatsit_t = nodetype("whatsit")
-local page_insert_t = nodetype("page_insert")
-local sub_box_t = nodetype("sub_box")
-
---- node -> nil | -1 | color‽
-local lookup_next_color
-lookup_next_color = function (head) --- paragraph material
- for n in traverse_nodes(head) do
- local n_id = n.id
-
- if n_id == glyph_t then
- local n_font
- if identifiers[n_font]
- and identifiers[n_font].properties
- and identifiers[n_font].properties.color
- then
- return identifiers[n.font].properties.color
- else
- return -1
- end
-
- elseif n_id == vlist_t or n_id == hlist_t or n_id == sub_box_t then
- local r = lookup_next_color(n.list)
- if r then
- return r
- end
-
- elseif n_id == whatsit_t or n_id == page_insert_t then
- return -1
+local disc_t = nodetype("disc")
+local pdfliteral_t = node.subtype("pdf_literal")
+local colorstack_t = node.subtype("pdf_colorstack")
+
+local color_callback
+local color_attr = luatexbase.new_attribute("luaotfload_color_attribute")
+
+-- (node * node * string * bool * (bool | nil)) -> (node * node * (string | nil))
+local color_whatsit
+color_whatsit = function (head, curr, color, push, tail)
+ local pushdata = hex_to_rgba(color)
+ local colornode = newnode(whatsit_t, colorstack_t)
+ setfield(colornode, "stack", 0)
+ setfield(colornode, "command", push and 1 or 2) -- 1: push, 2: pop
+ setfield(colornode, "data", push and pushdata or nil)
+ if tail then
+ head, curr = insert_node_after (head, curr, colornode)
+ else
+ head = insert_node_before(head, curr, colornode)
+ end
+ if not push and color:len() > 6 then
+ local colornode = newnode(whatsit_t, pdfliteral_t)
+ setfield(colornode, "mode", 2)
+ setfield(colornode, "data", "/TransGs1 gs")
+ if tail then
+ head, curr = insert_node_after (head, curr, colornode)
+ else
+ head = insert_node_before(head, curr, colornode)
end
end
- return nil
+ color = push and color or nil
+ return head, curr, color
+end
+
+-- number -> string | nil
+local get_font_color = function (font_id)
+ local tfmdata = identifiers[font_id]
+ local font_color = tfmdata and tfmdata.properties and tfmdata.properties.color
+ return font_color
end
+local cnt = 0
+
--[[doc--
While the second argument and second returned value are apparently
always nil when the function is called, they temporarily take string
values during the node list traversal.
--doc]]--
-local cnt = 0
---- node -> string -> int -> (node * string)
+--- (node * (string | nil)) -> (node * (string | nil))
local node_colorize
-node_colorize = function (head, current_color, next_color)
- for n in traverse_nodes(head) do
- local n_id = n.id
- local nextnode = n.next
-
- if n_id == hlist_t or n_id == vlist_t or n_id == sub_box_t then
- local next_color_in = lookup_next_color(nextnode) or next_color
- n.list, current_color = node_colorize(n.list, current_color, next_color_in)
+node_colorize = function (head, current_color)
+ local n = head
+ while n do
+ local n_id = getid(n)
- elseif n_id == glyph_t then
+ if n_id == hlist_t or n_id == vlist_t then
cnt = cnt + 1
- local tfmdata = identifiers[n.font]
+ local n_list = getlist(n)
+ if getattribute(n_list, color_attr) then
+ if current_color then
+ head, n, current_color = color_whatsit(head, n, current_color, false)
+ end
+ else
+ n_list, current_color = node_colorize(n_list, current_color)
+ if current_color and getsubtype(n) == 1 then -- created by linebreak
+ n_list, _, current_color = color_whatsit(n_list, nodetail(n_list), current_color, false, true)
+ end
+ setfield(n, "head", n_list)
+ end
+ cnt = cnt - 1
+ elseif n_id == glyph_t then
--- colorization is restricted to those fonts
--- that received the “color” property upon
--- loading (see ``setcolor()`` above)
- if tfmdata and tfmdata.properties and tfmdata.properties.color then
- local font_color = tfmdata.properties.color
--- luaotfload.info(
--- "n: %d; %s; %d %s, %s",
--- cnt, utf.char(n.char), n.font, "<TRUE>", font_color)
- if font_color ~= current_color then
- local pushcolor = hex_to_rgba(font_color)
- local push = newnode(whatsit_t, 8)
- push.mode = 1
- push.data = pushcolor
- head = insert_node_before(head, n, push)
- current_color = font_color
+ local font_color = get_font_color(getfont(n))
+ if font_color ~= current_color then
+ if current_color then
+ head, n, current_color = color_whatsit(head, n, current_color, false)
end
- local next_color_in = lookup_next_color (nextnode) or next_color
- if next_color_in ~= font_color then
- local _, popcolor = hex_to_rgba(font_color)
- local pop = newnode(whatsit_t, 8)
- pop.mode = 1
- pop.data = popcolor
- head = insert_node_after(head, n, pop)
- current_color = nil
+ if font_color then
+ head, n, current_color = color_whatsit(head, n, font_color, true)
end
+ end
--- else
--- luaotfload.info(
--- "n: %d; %s; %d %s",
--- cnt, utf.char(n.char), n.font, "<FALSE>")
+ if current_color and color_callback == "pre_linebreak_filter" then
+ local nn = getnext(n)
+ while nn and getid(nn) == glyph_t do
+ local font_color = get_font_color(getfont(nn))
+ if font_color == current_color then
+ n = nn
+ else
+ break
+ end
+ nn = getnext(nn)
+ end
+ if getid(nn) == disc_t then
+ head, n, current_color = color_whatsit(head, nn, current_color, false, true)
+ else
+ head, n, current_color = color_whatsit(head, n, current_color, false, true)
+ end
end
+
+ elseif n_id == whatsit_t then
+ if current_color then
+ head, n, current_color = color_whatsit(head, n, current_color, false)
+ end
+
end
+
+ n = getnext(n)
end
+
+ if cnt == 0 and current_color then
+ head, _, current_color = color_whatsit(head, nodetail(head), current_color, false, true)
+ end
+
+ setattribute(head, color_attr, 1)
return head, current_color
end
--- node -> node
local color_handler = function (head)
- local new_head = node_colorize(head, nil, nil)
+ head = todirect(head)
+ head = node_colorize(head)
+ head = tonode(head)
+
-- now append our page resources
if res then
res["1"] = true
local tpr = texget("pdfpageresources")
+ local no_extgs = not tpr:find("/ExtGState<<.*>>")
+ local pgf_loaded = no_extgs and luaotfload.pgf_loaded
+ if pgf_loaded then
+ tpr = texgettoks(pgf_loaded) -- see luaotfload.sty
+ end
+
local t = ""
for k in pairs(res) do
- local str = stringformat("/TransGs%s<</ca %s/CA %s>>", k, k, k)
- if not stringfind(tpr,str) then
+ local str = stringformat("/TransGs%s<</ca %s>>", k, k) -- don't touch stroking elements
+ if not tpr:find(str) then
t = t .. str
end
end
- print""
if t ~= "" then
- print(">>", tpr, "<<")
- if not stringfind(tpr,"/ExtGState<<.*>>") then
- tpr = tpr.."/ExtGState<<>>"
+ if pgf_loaded then
+ texsettoks("global", pgf_loaded, tpr..t)
+ else
+ if no_extgs then
+ tpr = tpr .. "/ExtGState<<>>"
+ end
+ tpr = tpr:gsub("/ExtGState<<", "%1"..t)
+ texset("global", "pdfpageresources", tpr)
end
- tpr = stringgsub(tpr,"/ExtGState<<","%1"..t)
- texset("global", "pdfpageresources", tpr)
- print(">>", tpr, "<<")
end
res = nil -- reset res
end
- return new_head
+ return head
end
local color_callback_activated = 0
--- unit -> unit
add_color_callback = function ( )
- local color_callback = config.luaotfload.run.color_callback
+ color_callback = config.luaotfload.run.color_callback
if not color_callback then
- color_callback = "pre_linebreak_filter"
+ color_callback = "post_linebreak_filter"
end
if color_callback_activated == 0 then
luatexbase.add_to_callback(color_callback,
color_handler,
"luaotfload.color_handler")
+ luatexbase.add_to_callback("hpack_filter",
+ function (head, groupcode)
+ if groupcode == "hbox" or
+ groupcode == "adjusted_hbox" or
+ groupcode == "align_set" then
+ head = color_handler(head)
+ end
+ return head
+ end,
+ "luaotfload.color_handler")
color_callback_activated = 1
end
end
diff --git a/src/luaotfload-configuration.lua b/src/luaotfload-configuration.lua
index b198697..e9393c5 100644
--- a/src/luaotfload-configuration.lua
+++ b/src/luaotfload-configuration.lua
@@ -2,17 +2,18 @@
-------------------------------------------------------------------------------
-- FILE: luaotfload-configuration.lua
-- DESCRIPTION: config file reader
--- REQUIREMENTS: Luaotfload 2.5 or above
+-- REQUIREMENTS: Luaotfload 2.6 or above
-- AUTHOR: Philipp Gesang (Phg), <phg42.2a@gmail.com>
+-- AUTHOR: Dohyun Kim <nomosnomos@gmail.com>
-- VERSION: same as Luaotfload
--- MODIFIED: 2015-03-16 07:48:58+0100
+-- MODIFIED: 2015-05-05
-------------------------------------------------------------------------------
--
if not modules then modules = { } end modules ["luaotfload-configuration"] = {
- version = "2.5",
+ version = "2.6",
comment = "part of Luaotfload",
- author = "Philipp Gesang",
+ author = "Philipp Gesang, Dohyun Kim",
copyright = "Luaotfload Development Team",
license = "GNU GPL v2.0"
}
@@ -144,6 +145,23 @@ local registered_loaders = {
tl2013 = "tl2013",
}
+--[[doc--
+
+ The ``post_linebreak_filter`` has been made the default callback for
+ hooking the colorizer into. This helps with the linebreaking whose
+ inserted hyphens would remain unaffected by the coloring otherwise.
+
+ http://tex.stackexchange.com/q/238539/14066
+
+--doc]]--
+
+local permissible_color_callbacks = {
+ default = "post_linebreak_filter",
+ pre_linebreak_filter = "pre_linebreak_filter",
+ post_linebreak_filter = "post_linebreak_filter",
+ pre_output_filter = "pre_output_filter",
+}
+
-------------------------------------------------------------------------------
--- DEFAULTS
@@ -163,7 +181,7 @@ local default_config = {
resolver = "cached",
definer = "patch",
log_level = 0,
- color_callback = "pre_linebreak_filter",
+ color_callback = "post_linebreak_filter",
live = true,
},
misc = {
@@ -479,9 +497,20 @@ local option_spec = {
color_callback = {
in_t = string_t,
out_t = string_t,
- transform = function (cb)
+ transform = function (cb_spec)
--- These are the two that make sense.
- return cb == "pre_output_filter" and cb or "pre_linebreak_filter"
+ local cb = permissible_color_callbacks[cb_spec]
+ if cb then
+ logreport ("log", 3, "conf",
+ "Using callback \"%s\" for font colorization.",
+ cb)
+ return cb
+ end
+ logreport ("log", 0, "conf",
+ "Requested callback identifier \"%s\" invalid, "
+ .. "falling back to default.",
+ cb_spec)
+ return permissible_color_callbacks.default
end,
},
},
diff --git a/src/luaotfload-init.lua b/src/luaotfload-init.lua
new file mode 100644
index 0000000..4968877
--- /dev/null
+++ b/src/luaotfload-init.lua
@@ -0,0 +1,59 @@
+#!/usr/bin/env texlua
+-----------------------------------------------------------------------
+-- FILE: luaotfload-init.lua
+-- DESCRIPTION: Luaotfload font loader initialization
+-- REQUIREMENTS: luatex v.0.80 or later; packages lualibs, luatexbase
+-- AUTHOR: Philipp Gesang (Phg), <phg@phi-gamma.net>
+-- VERSION: 1.0
+-- CREATED: 2015-05-26 07:50:54+0200
+-----------------------------------------------------------------------
+--
+
+--[[doc--
+
+ Initialization phases:
+
+ - Load Lualibs from package
+ - Set up the logger routines
+ - Load Fontloader
+ - as package specified in configuration
+ - from Context install
+ - (optional: from raw unpackaged files distributed with
+ Luaotfload)
+
+ The initialization of the Lualibs may be made configurable in the
+ future as well allowing to load both the files and the merged package
+ depending on a configuration setting. However, this would require
+ separating out the configuration parser into a self-contained
+ package, which might be problematic due to its current dependency on
+ the Lualibs itself.
+
+--doc]]--
+
+config = config or { }
+local config = config
+config.luaotfload = config.luaotfload or { }
+
+config.lualibs = config.lualibs or { }
+config.lualibs.verbose = false
+config.lualibs.prefer_merged = true
+config.lualibs.load_extended = true
+
+require "lualibs"
+
+if not lualibs then error("this module requires Luaotfload") end
+if not luaotfload then error("this module requires Luaotfload") end
+
+local load_luaotfload_module = luaotfload.loaders.luaotfload
+local load_fontloader_module = luaotfload.loaders.fontloader
+
+--[[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]]--
+
+load_luaotfload_module "log"
+
diff --git a/src/luaotfload-loaders.lua b/src/luaotfload-loaders.lua
index 2aa8c7c..901d4d8 100644
--- a/src/luaotfload-loaders.lua
+++ b/src/luaotfload-loaders.lua
@@ -27,4 +27,8 @@ formats.pfb = "type1"
readers.pfb = pfb_reader
handlers.pfb = { }
+formats.ofm = "type1"
+readers.ofm = readers.tfm
+handlers.ofm = { }
+
-- vim:tw=71:sw=2:ts=2:expandtab
diff --git a/src/luaotfload-main.lua b/src/luaotfload-main.lua
index ee8966c..a825dc3 100644
--- a/src/luaotfload-main.lua
+++ b/src/luaotfload-main.lua
@@ -1,10 +1,10 @@
-----------------------------------------------------------------------
-- FILE: luaotfload-main.lua
--- DESCRIPTION: Luatex fontloader initialization
--- REQUIREMENTS: luatex v.0.79 or later; packages lualibs, luatexbase
+-- DESCRIPTION: Luaotfload initialization
+-- REQUIREMENTS: luatex v.0.80 or later; packages lualibs, luatexbase
-- AUTHOR: Élie Roux, Khaled Hosny, Philipp Gesang
-- VERSION: same as Luaotfload
--- MODIFIED: 2015-03-11 07:49:20+0100
+-- MODIFIED: 2015-06-09 23:08:18+0200
-----------------------------------------------------------------------
--
--- Note:
@@ -13,15 +13,34 @@
--- version 2.4 to 2.5. Thus, the comments are still in TeX (Latex)
--- markup.
-if not modules then modules = { } end modules ["luaotfload-main"] = {
- version = "2.5",
- comment = "fontloader initialization",
- author = "Hans Hagen, Khaled Hosny, Elie Roux, Philipp Gesang",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "GNU General Public License v. 2.0"
-}
+local initial_log_level = 0
+luaotfload = luaotfload or { }
+local luaotfload = luaotfload
+luaotfload.log = luaotfload.log or { }
+luaotfload.version = "2.6"
+luaotfload.loaders = { }
+
+local authors = "\z
+ Hans Hagen,\z
+ Khaled Hosny,\z
+ Elie Roux,\z
+ Will Robertson,\z
+ Philipp Gesang,\z
+ Dohyun Kim,\z
+ Reuben Thomas\z
+"
+luaotfload.module = {
+ name = "luaotfload-main",
+ version = 2.60001,
+ date = "2015/05/26",
+ description = "OpenType layout system.",
+ author = authors,
+ copyright = authors,
+ license = "GPL v2.0"
+}
+
--[[doc--
This file initializes the system and loads the font loader. To
@@ -43,25 +62,9 @@ if not modules then modules = { } end modules ["luaotfload-main"] = {
--doc]]--
-local initial_log_level = 0
-
-luaotfload = luaotfload or { }
-local luaotfload = luaotfload
-luaotfload.log = luaotfload.log or { }
-luaotfload.version = "2.5-2" -- FIXME version belongs in common init
-
-luaotfload.module = {
- name = "luaotfload-main",
- version = 2.50001,
- date = "2014/07/16",
- description = "OpenType layout system.",
- author = "Elie Roux & Hans Hagen",
- copyright = "Elie Roux",
- license = "GPL v2.0"
-}
-
local luatexbase = luatexbase
+local require = require
local setmetatable = setmetatable
local type, next = type, next
local stringlower = string.lower
@@ -75,7 +78,7 @@ local create_callback = luatexbase.create_callback
local reset_callback = luatexbase.reset_callback
local call_callback = luatexbase.call_callback
-local dummy_function = function () end --- XXX this will be moved to the luaotfload namespace when we have the init module
+local dummy_function = function () end --- XXX this will be moved to the luaotfload namespace when we have the init module
local error, warning, info, log =
luatexbase.provides_module(luaotfload.module)
@@ -102,7 +105,8 @@ luaotfload.log.tex = {
--doc]]--
local min_luatex_version = 79 --- i. e. 0.79
-local fontloader_package = "fontloader" --- default: from current Context
+--local fontloader_package = "fontloader" --- default: from current Context
+local fontloader_package = "slim"
if tex.luatexversion < min_luatex_version then
warning ("LuaTeX v%.2f is old, v%.2f or later is recommended.",
@@ -111,15 +115,6 @@ if tex.luatexversion < min_luatex_version then
warning ("using fallback fontloader -- newer functionality not available")
fontloader_package = "tl2014" --- TODO fallback should be configurable too
--- we install a fallback for older versions as a safety
- if not node.end_of_math then
- local math_t = node.id "math"
- local traverse_nodes = node.traverse_id
- node.end_of_math = function (n)
- for n in traverse_nodes (math_t, n.next) do
- return n
- end
- end
- end
end
--[[doc--
@@ -140,7 +135,10 @@ local load_luaotfload_module = make_loader "luaotfload"
----- load_luaotfload_module = make_loader "luatex" --=> for Luatex-Plain
local load_fontloader_module = make_loader "fontloader"
-load_luaotfload_module "log" --- log messages
+luaotfload.loaders.luaotfload = load_luaotfload_module
+luaotfload.loaders.fontloader = load_fontloader_module
+
+load_luaotfload_module "init" --- fontloader initialization
local log = luaotfload.log
local logreport = log.report
@@ -149,36 +147,6 @@ log.set_loglevel (default_log_level)
--[[doc--
- Before \TeX Live 2013 version, \LUATEX had a bug that made ofm fonts
- fail when called with their extension. There was a side-effect making
- ofm totally unloadable when luaotfload was present. The following
- lines are a patch for this bug. The utility of these lines is
- questionable as they are not necessary since \TeX Live 2013. They
- should be removed in the next version.
-
---doc]]--
-
-local Cs, P, lpegmatch = lpeg.Cs, lpeg.P, lpeg.match
-
-local p_dot, p_slash = P".", P"/"
-local p_suffix = (p_dot * (1 - p_dot - p_slash)^1 * P(-1)) / ""
-local p_removesuffix = Cs((p_suffix + 1)^1)
-
-local find_vf_file = function (name)
- local fullname = kpsefind_file(name, "ovf")
- if not fullname then
- --fullname = kpsefind_file(file.removesuffix(name), "ovf")
- fullname = kpsefind_file(lpegmatch(p_removesuffix, name), "ovf")
- end
- if fullname then
- logreport ("log", 0, "main",
- "loading virtual font file %s.", fullname)
- end
- return fullname
-end
-
---[[doc--
-
\subsection{Preparing the Font Loader}
We treat the fontloader as a black box so behavior is consistent
between formats.
@@ -418,8 +386,6 @@ add_to_callback("hpack_filter",
nodes.simple_font_handler,
"luaotfload.node_processor",
1)
-add_to_callback("find_vf_file",
- find_vf_file, "luaotfload.find_vf_file")
load_luaotfload_module "override" --- load glyphlist on demand
@@ -540,8 +506,10 @@ request_resolvers.anon = function (specification)
local name = specification.name
for i=1, #type1_formats do
local format = type1_formats[i]
+ local suffix = filesuffix (name)
if resolvers.findfile(name, format) then
- specification.forcedname = file.addsuffix(name, format)
+ local usename = suffix == format and file.removesuffix (name) or name
+ specification.forcedname = file.addsuffix (usename, format)
specification.forced = format
return
end
diff --git a/src/luaotfload-tool.lua b/src/luaotfload-tool.lua
index 2330aee..36c23bd 100755
--- a/src/luaotfload-tool.lua
+++ b/src/luaotfload-tool.lua
@@ -2,15 +2,15 @@
-----------------------------------------------------------------------
-- FILE: luaotfload-tool.lua
-- DESCRIPTION: database functionality
--- REQUIREMENTS: luaotfload 2.5
+-- REQUIREMENTS: luaotfload 2.6
-- AUTHOR: Khaled Hosny, Élie Roux, Philipp Gesang
--- VERSION: 2.5
+-- VERSION: 2.6
-- LICENSE: GPL v2.0
--- MODIFIED: 2014-07-24 22:10:32+0200
+-- MODIFIED: 2015-03-29 12:43:00+0200
-----------------------------------------------------------------------
luaotfload = luaotfload or { }
-local version = "2.5-2" --- <int: major>.<int: minor>-<int: fixes>
+local version = "2.6"
luaotfload.version = version
luaotfload.self = "luaotfload-tool"
diff --git a/src/luaotfload.sty b/src/luaotfload.sty
index 4ebe3cb..34f9a87 100644
--- a/src/luaotfload.sty
+++ b/src/luaotfload.sty
@@ -1,8 +1,9 @@
-%% Copyright (C) 2009-2014
+%% Copyright (C) 2009-2015
%%
%% by Elie Roux <elie.roux@telecom-bretagne.eu>
%% and Khaled Hosny <khaledhosny@eglug.org>
%% and Philipp Gesang <philipp.gesang@alumni.uni-heidelberg.de>
+%% and Dohyun Kim <nomosnomos@gmail.com>
%%
%% This file is part of Luaotfload.
%%
@@ -33,15 +34,35 @@
\csname ifluaotfloadloaded\endcsname
\let\ifluaotfloadloaded\endinput
\bgroup\expandafter\expandafter\expandafter\egroup
-\expandafter\ifx\csname ProvidesPackage\endcsname\relax
+\expandafter\ifx\csname selectfont\endcsname\relax
\input luatexbase.sty
\else
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{luaotfload}%
%% FIXME The date is meaningless, we need to find a way to
%% use the git revision instead.
- [2014/07/24 v2.5-2 OpenType layout system]
+ [2015/03/29 v2.6 OpenType layout system]
\RequirePackage{luatexbase}
\fi
\RequireLuaModule{luaotfload-main}
+% for compatibility with beamer class, which loads pgf package.
+\ifcsname selectfont\endcsname
+ \AtBeginDocument{\@ifpackageloaded{pgfsys}{
+ \csname newtoks\endcsname\pgf@sys@pgf@resource@list@extgs@toks
+ \directlua{luaotfload.pgf_loaded=\the\allocationnumber}
+ \def\pgf@sys@pgf@resource@list@extgs{\the\pgf@sys@pgf@resource@list@extgs@toks}
+ \def\pgf@sys@addpdfresource@extgs@plain#1{\global\pgf@sys@pgf@resource@list@extgs@toks
+ \expandafter{\the\pgf@sys@pgf@resource@list@extgs@toks #1}}
+ }{}}
+\endinput\fi
+% under plain tex, tikz (pgf) should be loaded before luaotfload.
+\ifcsname pgf@sys@pgf@resource@list@extgs\endcsname\else\endinput\fi
+\count255=\the\catcode`@\relax
+\catcode`@=11\relax
+\newtoks\pgf@sys@pgf@resource@list@extgs@toks
+\directlua{luaotfload.pgf_loaded=\the\allocationnumber}
+\def\pgf@sys@pgf@resource@list@extgs{\the\pgf@sys@pgf@resource@list@extgs@toks}
+\def\pgf@sys@addpdfresource@extgs@plain#1{\global\pgf@sys@pgf@resource@list@extgs@toks
+ \expandafter{\the\pgf@sys@pgf@resource@list@extgs@toks #1}}
+\catcode`@=\the\count255\relax