From d8dcfd9af18a15af70ec86d8e01e6d7a0f43c35c Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Thu, 30 Jul 2015 07:53:30 +0200
Subject: [aux] do not rely on the AGL being loaded at initialization time
---
src/luaotfload-auxiliary.lua | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/src/luaotfload-auxiliary.lua b/src/luaotfload-auxiliary.lua
index 1ef581e..dce0d60 100644
--- a/src/luaotfload-auxiliary.lua
+++ b/src/luaotfload-auxiliary.lua
@@ -19,6 +19,7 @@ local aux = luaotfload.aux
local log = luaotfload.log
local report = log.report
local fonthashes = fonts.hashes
+local encodings = fonts.encodings
local identifiers = fonthashes.identifiers
local fontnames = fonts.names
@@ -214,8 +215,6 @@ luatexbase.add_to_callback(
--- glyphs and characters
-----------------------------------------------------------------------
-local agl = fonts.encodings.agl
-
--- int -> int -> bool
local font_has_glyph = function (font_id, codepoint)
local fontdata = fonts.hashes.identifiers[font_id]
@@ -232,7 +231,7 @@ aux.font_has_glyph = font_has_glyph
local raw_slot_of_name = function (font_id, glyphname)
local fontdata = font.fonts[font_id]
if fontdata.type == "virtual" then --- get base font for glyph idx
- local codepoint = agl.unicodes[glyphname]
+ local codepoint = encodings.agl.unicodes[glyphname]
local glyph = fontdata.characters[codepoint]
if fontdata.characters[codepoint] then
return codepoint
@@ -293,7 +292,7 @@ local indices
--- int -> (string | false)
local name_of_slot = function (codepoint)
if not indices then --- this will load the glyph list
- local unicodes = agl.unicodes
+ local unicodes = encodings.agl.unicodes
indices = table.swapped(unicodes)
end
local glyphname = indices[codepoint]
--
cgit v1.2.3
From e05c2e2c2f72788e63da7334e054fd887bd22e70 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Thu, 27 Aug 2015 23:08:11 +0200
Subject: [main] install stub for main initialization hook
---
src/luaotfload-main.lua | 8 ++++++++
src/luaotfload.sty | 1 +
2 files changed, 9 insertions(+)
diff --git a/src/luaotfload-main.lua b/src/luaotfload-main.lua
index b633ed7..36db2c3 100644
--- a/src/luaotfload-main.lua
+++ b/src/luaotfload-main.lua
@@ -266,4 +266,12 @@ load_luaotfload_module "auxiliary" --- additional high-level functionality
luaotfload.aux.start_rewrite_fontname () --- to be migrated to fontspec
+luaotfload.main = function ()
+ local starttime = os.gettimeofday ()
+ --- XXX stub
+ logreport ("both", 0, "main",
+ "initialization completed in %0.3f seconds",
+ os.gettimeofday() - starttime)
+end
+
-- vim:tw=79:sw=4:ts=4:et
diff --git a/src/luaotfload.sty b/src/luaotfload.sty
index c9c9864..ec62dad 100644
--- a/src/luaotfload.sty
+++ b/src/luaotfload.sty
@@ -45,4 +45,5 @@
\RequirePackage{luatexbase}
\fi
\RequireLuaModule{luaotfload-main}
+\directlua{local _void = luaotfload.main ()}
--
cgit v1.2.3
From 7cd218b920814322d002f915ed5c8bb0132cf40a Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Thu, 27 Aug 2015 23:28:32 +0200
Subject: [main,loaders] regroup callback handling code with loaders
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
... changing the meaning of the file’s designation instead of adding yet
another file.
All the callback manipulation is now contained inside that module which
will inject most of its functionality only when its main ``.install()``
method is called.
---
src/luaotfload-loaders.lua | 147 ++++++++++++++++++++++++++++++++++++---------
src/luaotfload-main.lua | 116 +++++------------------------------
2 files changed, 134 insertions(+), 129 deletions(-)
diff --git a/src/luaotfload-loaders.lua b/src/luaotfload-loaders.lua
index 901d4d8..061789c 100644
--- a/src/luaotfload-loaders.lua
+++ b/src/luaotfload-loaders.lua
@@ -1,34 +1,127 @@
-if not modules then modules = { } end modules ["loaders"] = {
- version = "2.5",
- comment = "companion to luaotfload-main.lua",
- author = "Hans Hagen, Khaled Hosny, Elie Roux, Philipp Gesang",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
+#!/usr/bin/env texlua
+-----------------------------------------------------------------------
+-- FILE: luaotfload-loaders.lua
+-- DESCRIPTION: Luaotfload callback handling
+-- REQUIREMENTS: luatex v.0.80 or later; packages lualibs, luatexbase
+-- AUTHOR: Philipp Gesang (Phg), , Hans Hagen, Khaled Hosny, Elie Roux
+-- VERSION: just consult Git, okay?
+-----------------------------------------------------------------------
+--
+--- Contains parts of the earlier main script.
+
+if not lualibs then error "this module requires Luaotfload" end
+if not luaotfload then error "this module requires Luaotfload" end
+
+local logreport = luaotfload.log and luaotfload.log.report or print
+local add_to_callback = luatexbase.add_to_callback
+local create_callback = luatexbase.create_callback
+local reset_callback = luatexbase.reset_callback
+local call_callback = luatexbase.call_callback
+local dummy_function = function () end
+
+local install_formats = function ()
+ local fonts = fonts
+ if not fonts then return false end
+
+ local readers = fonts.readers
+ local handlers = fonts.handlers
+ local formats = fonts.formats
+ if not readers or not handlers or not formats then return false end
+
+ local aux = function (which, reader)
+ if not which or type (which) ~= "string" then return false end
+ formats [which] = "type1"
+ readers [which] = reader
+ handlers [which] = { }
+ return true
+ end
+
+ return aux ("pfa", function (spec) return readers.opentype (spec, "pfa", "type1") end)
+ and aux ("pfb", function (spec) return readers.opentype (spec, "pfb", "type1") end)
+ and aux ("ofm", readers.tfm)
+end
+
+--[[doc--
-local fonts = fonts
-local readers = fonts.readers
-local handlers = fonts.handlers
-local formats = fonts.formats
-
-local pfb_reader = function (specification)
- return readers.opentype (specification, "pfb", "type1")
-end
-
-local pfa_reader = function (specification)
- return readers.opentype (specification, "pfa", "type1")
+ \subsection{\CONTEXT override}
+ \label{define-font}
+ We provide a simplified version of the original font definition
+ callback.
+
+--doc]]--
+
+
+local definers = { } --- (string, spec -> size -> id -> tmfdata) hash_t
+do
+ local read = fonts.definers.read
+
+ local patch = function (specification, size, id)
+ local fontdata = read (specification, size, id)
+ if type (fontdata) == "table" and fontdata.shared then
+ --- We need to test for the “shared” field here
+ --- or else the fontspec capheight callback will
+ --- operate on tfm fonts.
+ call_callback ("luaotfload.patch_font", fontdata, specification)
+ else
+ call_callback ("luaotfload.patch_font_unsafe", fontdata, specification)
+ end
+ return fontdata
+ end
+
+ local mk_info = function (name)
+ local definer = name == "patch" and patch or read
+ return function (specification, size, id)
+ logreport ("both", 0, "main", "defining font no. %d", id)
+ logreport ("both", 0, "main", " > active font definer: %q", name)
+ logreport ("both", 0, "main", " > spec %q", specification)
+ logreport ("both", 0, "main", " > at size %.2f pt", size / 2^16)
+ local result = definer (specification, size, id)
+ if not result then
+ logreport ("both", 0, "main", " > font definition failed")
+ return
+ elseif type (result) == "number" then
+ logreport ("both", 0, "main", " > font definition yielded id %d", result)
+ return result
+ end
+ logreport ("both", 0, "main", " > font definition successful")
+ logreport ("both", 0, "main", " > name %q", result.name or "")
+ logreport ("both", 0, "main", " > fontname %q", result.fontname or "")
+ logreport ("both", 0, "main", " > fullname %q", result.fullname or "")
+ return result
+ end
+ end
+
+ definers.patch = patch
+ definers.generic = read
+ definers.info_patch = mk_info "patch"
+ definers.info_generic = mk_info "generic"
end
-formats.pfa = "type1"
-readers.pfa = pfa_reader
-handlers.pfa = { }
+--[[doc--
+
+ We create callbacks for patching fonts on the fly, to be used by
+ other packages. In addition to the regular \identifier{patch_font}
+ callback there is an unsafe variant \identifier{patch_font_unsafe}
+ that will be invoked even if the target font lacks certain essential
+ tfmdata tables.
-formats.pfb = "type1"
-readers.pfb = pfb_reader
-handlers.pfb = { }
+ The callbacks initially contain the empty function that we are going
+ to override below.
-formats.ofm = "type1"
-readers.ofm = readers.tfm
-handlers.ofm = { }
+--doc]]--
+return {
+ install = function ()
+ if not install_formats () then
+ logreport ("both", 0, "main", "error initializing OFM/PF{A,B} loaders")
+ end
+ create_callback("luaotfload.patch_font", "simple", dummy_function)
+ create_callback("luaotfload.patch_font_unsafe", "simple", dummy_function)
+
+ reset_callback "define_font"
+ local definer = config.luaotfload.run.definer
+ add_to_callback ("define_font", definers[definer or "patch"],
+ "luaotfload.define_font", 1)
+ end
+}
-- vim:tw=71:sw=2:ts=2:expandtab
diff --git a/src/luaotfload-main.lua b/src/luaotfload-main.lua
index 36db2c3..fe27215 100644
--- a/src/luaotfload-main.lua
+++ b/src/luaotfload-main.lua
@@ -67,12 +67,6 @@ luaotfload.module = {
local luatexbase = luatexbase
local require = require
local type = type
-local add_to_callback = luatexbase.add_to_callback
-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 error, warning, info, log =
luatexbase.provides_module(luaotfload.module)
@@ -165,110 +159,28 @@ end
luaotfload.init.main (store)
-load_luaotfload_module "loaders" --- Type1 font wrappers
-load_luaotfload_module "database" --- Font management.
-load_luaotfload_module "colors" --- Per-font colors.
-
-luaotfload.resolvers = load_luaotfload_module "resolvers" --- Font lookup
-
-luaotfload.resolvers.install ()
-
-if not config.actions.reconfigure () then
- logreport ("log", 0, "load", "Post-configuration hooks failed.")
-end
-
---[[doc--
-
- We create callbacks for patching fonts on the fly, to be used by
- other packages. In addition to the regular \identifier{patch_font}
- callback there is an unsafe variant \identifier{patch_font_unsafe}
- that will be invoked even if the target font lacks certain essential
- tfmdata tables.
-
- The callbacks initially contain the empty function that we are going to
- override below.
-
---doc]]--
-
-create_callback("luaotfload.patch_font", "simple", dummy_function)
-create_callback("luaotfload.patch_font_unsafe", "simple", dummy_function)
-
---[[doc--
-
- \subsection{\CONTEXT override}
- \label{define-font}
- We provide a simplified version of the original font definition
- callback.
+luaotfload.main = function ()
+ local starttime = os.gettimeofday ()
---doc]]--
+ luaotfload.loaders = load_luaotfload_module "loaders" --- Font loading; callbacks
+ luaotfload.loaders.install ()
+ load_luaotfload_module "database" --- Font management.
+ load_luaotfload_module "colors" --- Per-font colors.
-local definers = { } --- (string, spec -> size -> id -> tmfdata) hash_t
-do
- local read = fonts.definers.read
-
- local patch = function (specification, size, id)
- local fontdata = read (specification, size, id)
- if type (fontdata) == "table" and fontdata.shared then
- --- We need to test for the “shared” field here
- --- or else the fontspec capheight callback will
- --- operate on tfm fonts.
- call_callback ("luaotfload.patch_font", fontdata, specification)
- else
- call_callback ("luaotfload.patch_font_unsafe", fontdata, specification)
- end
- return fontdata
- end
+ luaotfload.resolvers = load_luaotfload_module "resolvers" --- Font lookup
+ luaotfload.resolvers.install ()
- local mk_info = function (name)
- local definer = name == "patch" and patch or read
- return function (specification, size, id)
- logreport ("both", 0, "main", "defining font no. %d", id)
- logreport ("both", 0, "main", " > active font definer: %q", name)
- logreport ("both", 0, "main", " > spec %q", specification)
- logreport ("both", 0, "main", " > at size %.2f pt", size / 2^16)
- local result = definer (specification, size, id)
- if not result then
- logreport ("both", 0, "main", " > font definition failed")
- return
- elseif type (result) == "number" then
- logreport ("both", 0, "main", " > font definition yielded id %d", result)
- return result
- end
- logreport ("both", 0, "main", " > font definition successful")
- logreport ("both", 0, "main", " > name %q", result.name or "")
- logreport ("both", 0, "main", " > fontname %q", result.fontname or "")
- logreport ("both", 0, "main", " > fullname %q", result.fullname or "")
- return result
- end
+ if not config.actions.reconfigure () then
+ logreport ("log", 0, "load", "Post-configuration hooks failed.")
end
- definers.patch = patch
- definers.generic = read
- definers.info_patch = mk_info "patch"
- definers.info_generic = mk_info "generic"
-end
-
-reset_callback "define_font"
-
---[[doc--
+ load_luaotfload_module "features" --- font request and feature handling
+ load_luaotfload_module "letterspace" --- extra character kerning
+ load_luaotfload_module "auxiliary" --- additional high-level functionality
- Finally we register the callbacks.
+ luaotfload.aux.start_rewrite_fontname () --- to be migrated to fontspec
---doc]]--
-
-local definer = config.luaotfload.run.definer
-add_to_callback ("define_font", definers[definer], "luaotfload.define_font", 1)
-
-load_luaotfload_module "features" --- font request and feature handling
-load_luaotfload_module "letterspace" --- extra character kerning
-load_luaotfload_module "auxiliary" --- additional high-level functionality
-
-luaotfload.aux.start_rewrite_fontname () --- to be migrated to fontspec
-
-luaotfload.main = function ()
- local starttime = os.gettimeofday ()
- --- XXX stub
logreport ("both", 0, "main",
"initialization completed in %0.3f seconds",
os.gettimeofday() - starttime)
--
cgit v1.2.3
From c6fdf62a060ad9e77c461d5eb7a55699fa6c7249 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Thu, 27 Aug 2015 23:39:46 +0200
Subject: [loaders] {re,un}-scope locals for economy
---
src/luaotfload-loaders.lua | 57 +++++++++++++++++++++++++++++-----------------
1 file changed, 36 insertions(+), 21 deletions(-)
diff --git a/src/luaotfload-loaders.lua b/src/luaotfload-loaders.lua
index 061789c..f722d85 100644
--- a/src/luaotfload-loaders.lua
+++ b/src/luaotfload-loaders.lua
@@ -12,12 +12,7 @@
if not lualibs then error "this module requires Luaotfload" end
if not luaotfload then error "this module requires Luaotfload" end
-local logreport = luaotfload.log and luaotfload.log.report or print
-local add_to_callback = luatexbase.add_to_callback
-local create_callback = luatexbase.create_callback
-local reset_callback = luatexbase.reset_callback
-local call_callback = luatexbase.call_callback
-local dummy_function = function () end
+local logreport = luaotfload.log and luaotfload.log.report or print
local install_formats = function ()
local fonts = fonts
@@ -29,7 +24,11 @@ local install_formats = function ()
if not readers or not handlers or not formats then return false end
local aux = function (which, reader)
- if not which or type (which) ~= "string" then return false end
+ if not which or type (which) ~= "string"
+ or not reader or type (reader) ~= "function" then
+ logreport ("both", 2, "main", "error installing reader for “%s”", which)
+ return false
+ end
formats [which] = "type1"
readers [which] = reader
handlers [which] = { }
@@ -51,7 +50,7 @@ end
--doc]]--
-local definers = { } --- (string, spec -> size -> id -> tmfdata) hash_t
+local definers --- (string, spec -> size -> id -> tmfdata) hash_t
do
local read = fonts.definers.read
@@ -61,7 +60,7 @@ do
--- We need to test for the “shared” field here
--- or else the fontspec capheight callback will
--- operate on tfm fonts.
- call_callback ("luaotfload.patch_font", fontdata, specification)
+ luatexbase.call_callback ("luaotfload.patch_font", fontdata, specification)
else
call_callback ("luaotfload.patch_font_unsafe", fontdata, specification)
end
@@ -91,10 +90,12 @@ do
end
end
- definers.patch = patch
- definers.generic = read
- definers.info_patch = mk_info "patch"
- definers.info_generic = mk_info "generic"
+ definers = {
+ patch = patch,
+ generic = read,
+ info_patch = mk_info "patch",
+ info_generic = mk_info "generic",
+ }
end
--[[doc--
@@ -110,18 +111,32 @@ end
--doc]]--
+local install_callbacks = function ()
+ local create_callback = luatexbase.create_callback
+ local dummy_function = function () end
+ create_callback ("luaotfload.patch_font", "simple", dummy_function)
+ create_callback ("luaotfload.patch_font_unsafe", "simple", dummy_function)
+ luatexbase.reset_callback "define_font"
+ local definer = config.luaotfload.run.definer
+ luatexbase.add_to_callback ("define_font",
+ definers[definer or "patch"],
+ "luaotfload.define_font",
+ 1)
+ return true
+end
+
return {
install = function ()
+ local ret = true
if not install_formats () then
logreport ("both", 0, "main", "error initializing OFM/PF{A,B} loaders")
+ ret = false
end
- create_callback("luaotfload.patch_font", "simple", dummy_function)
- create_callback("luaotfload.patch_font_unsafe", "simple", dummy_function)
-
- reset_callback "define_font"
- local definer = config.luaotfload.run.definer
- add_to_callback ("define_font", definers[definer or "patch"],
- "luaotfload.define_font", 1)
+ if not install_callbacks () then
+ logreport ("both", 0, "main", "error installing font loader callbacks")
+ ret = false
+ end
+ return ret
end
}
--- vim:tw=71:sw=2:ts=2:expandtab
+-- vim:tw=79:sw=2:ts=2:expandtab
--
cgit v1.2.3
From c3db46b819beebb892698513bd51341b9a691786 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Thu, 27 Aug 2015 23:42:44 +0200
Subject: [main,loaders] adjust noise and check status of loader init
---
src/luaotfload-loaders.lua | 26 +++++++++++++-------------
src/luaotfload-main.lua | 4 +++-
2 files changed, 16 insertions(+), 14 deletions(-)
diff --git a/src/luaotfload-loaders.lua b/src/luaotfload-loaders.lua
index f722d85..44216d7 100644
--- a/src/luaotfload-loaders.lua
+++ b/src/luaotfload-loaders.lua
@@ -26,7 +26,7 @@ local install_formats = function ()
local aux = function (which, reader)
if not which or type (which) ~= "string"
or not reader or type (reader) ~= "function" then
- logreport ("both", 2, "main", "error installing reader for “%s”", which)
+ logreport ("both", 2, "loaders", "Error installing reader for “%s”.", which)
return false
end
formats [which] = "type1"
@@ -70,22 +70,22 @@ do
local mk_info = function (name)
local definer = name == "patch" and patch or read
return function (specification, size, id)
- logreport ("both", 0, "main", "defining font no. %d", id)
- logreport ("both", 0, "main", " > active font definer: %q", name)
- logreport ("both", 0, "main", " > spec %q", specification)
- logreport ("both", 0, "main", " > at size %.2f pt", size / 2^16)
+ logreport ("both", 0, "loaders", "defining font no. %d", id)
+ logreport ("both", 0, "loaders", " > active font definer: %q", name)
+ logreport ("both", 0, "loaders", " > spec %q", specification)
+ logreport ("both", 0, "loaders", " > at size %.2f pt", size / 2^16)
local result = definer (specification, size, id)
if not result then
- logreport ("both", 0, "main", " > font definition failed")
+ logreport ("both", 0, "loaders", " > font definition failed")
return
elseif type (result) == "number" then
- logreport ("both", 0, "main", " > font definition yielded id %d", result)
+ logreport ("both", 0, "loaders", " > font definition yielded id %d", result)
return result
end
- logreport ("both", 0, "main", " > font definition successful")
- logreport ("both", 0, "main", " > name %q", result.name or "")
- logreport ("both", 0, "main", " > fontname %q", result.fontname or "")
- logreport ("both", 0, "main", " > fullname %q", result.fullname or "")
+ logreport ("both", 0, "loaders", " > font definition successful")
+ logreport ("both", 0, "loaders", " > name %q", result.name or "")
+ logreport ("both", 0, "loaders", " > fontname %q", result.fontname or "")
+ logreport ("both", 0, "loaders", " > fullname %q", result.fullname or "")
return result
end
end
@@ -129,11 +129,11 @@ return {
install = function ()
local ret = true
if not install_formats () then
- logreport ("both", 0, "main", "error initializing OFM/PF{A,B} loaders")
+ logreport ("log", 0, "loaders", "Error initializing OFM/PF{A,B} loaders.")
ret = false
end
if not install_callbacks () then
- logreport ("both", 0, "main", "error installing font loader callbacks")
+ logreport ("log", 0, "loaders", "Error installing font loader callbacks.")
ret = false
end
return ret
diff --git a/src/luaotfload-main.lua b/src/luaotfload-main.lua
index fe27215..32eb04d 100644
--- a/src/luaotfload-main.lua
+++ b/src/luaotfload-main.lua
@@ -163,7 +163,9 @@ luaotfload.main = function ()
local starttime = os.gettimeofday ()
luaotfload.loaders = load_luaotfload_module "loaders" --- Font loading; callbacks
- luaotfload.loaders.install ()
+ if not luaotfload.loaders.install () then
+ logreport ("log", 0, "load", "Callback and loader initialization failed.")
+ end
load_luaotfload_module "database" --- Font management.
load_luaotfload_module "colors" --- Per-font colors.
--
cgit v1.2.3
From c7967b7a69bc5cf4e0c2e38b4e552c2587a7502d Mon Sep 17 00:00:00 2001
From: Dohyun Kim
Date: Fri, 25 Sep 2015 14:01:40 +0900
Subject: [colors] support displayed math
---
src/luaotfload-colors.lua | 52 ++++++++++++++++++++++++++++-------------------
1 file changed, 31 insertions(+), 21 deletions(-)
diff --git a/src/luaotfload-colors.lua b/src/luaotfload-colors.lua
index 89884b6..2171a68 100644
--- a/src/luaotfload-colors.lua
+++ b/src/luaotfload-colors.lua
@@ -192,6 +192,7 @@ local whatsit_t = nodetype("whatsit")
local disc_t = nodetype("disc")
local pdfliteral_t = node.subtype("pdf_literal")
local colorstack_t = node.subtype("pdf_colorstack")
+local mlist_to_hlist = node.mlist_to_hlist
local color_callback
local color_attr = luatexbase.new_attribute("luaotfload_color_attribute")
@@ -230,8 +231,6 @@ local get_font_color = function (font_id)
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
@@ -240,26 +239,24 @@ values during the node list traversal.
--- (node * (string | nil)) -> (node * (string | nil))
local node_colorize
-node_colorize = function (head, current_color)
+node_colorize = function (head, toplevel, current_color)
local n = head
while n do
local n_id = getid(n)
if n_id == hlist_t or n_id == vlist_t then
- cnt = cnt + 1
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)
+ n_list, current_color = node_colorize(n_list, false, 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
@@ -303,7 +300,7 @@ node_colorize = function (head, current_color)
n = getnext(n)
end
- if cnt == 0 and current_color then
+ if toplevel and current_color then
head, _, current_color = color_whatsit(head, nodetail(head), current_color, false, true)
end
@@ -314,7 +311,7 @@ end
--- node -> node
local color_handler = function (head)
head = todirect(head)
- head = node_colorize(head)
+ head = node_colorize(head, true)
head = tonode(head)
-- now append our page resources
@@ -351,6 +348,8 @@ local color_handler = function (head)
end
local color_callback_activated = 0
+local add_to_callback = luatexbase.add_to_callback
+local priority_in_callback = luatexbase.priority_in_callback
--- unit -> unit
add_color_callback = function ( )
@@ -360,19 +359,30 @@ add_color_callback = function ( )
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")
+ add_to_callback(color_callback,
+ color_handler,
+ "luaotfload.color_handler")
+ 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")
+ add_to_callback("mlist_to_hlist",
+ function (head, display_type, need_penalties)
+ if priority_in_callback("mlist_to_hlist","luaotfload.color_handler") == 1 then
+ head = mlist_to_hlist(head, display_type, need_penalties)
+ end
+ if display_type == "text" then
+ return head
+ end
+ return color_handler(head)
+ end,
+ "luaotfload.color_handler")
color_callback_activated = 1
end
end
--
cgit v1.2.3
From 4a76c3abcdf750cbf1e825d0fce637e35f63b10a Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Sun, 27 Sep 2015 18:28:14 +0200
Subject: [main, parsers] prepare for deferred initialization
---
src/luaotfload-init.lua | 4 ++--
src/luaotfload-main.lua | 6 +++++-
src/luaotfload-parsers.lua | 49 +++++++++++++++++++++-------------------------
3 files changed, 29 insertions(+), 30 deletions(-)
diff --git a/src/luaotfload-init.lua b/src/luaotfload-init.lua
index a493cc1..a5e5bec 100644
--- a/src/luaotfload-init.lua
+++ b/src/luaotfload-init.lua
@@ -38,8 +38,8 @@ local logreport --- filled in after loading the log module
--[[doc--
\subsection{Preparing the Font Loader}
- We treat the fontloader as a black box so behavior is consistent
- between formats.
+ We treat the fontloader as a semi-black box so behavior is
+ consistent between formats.
We load the fontloader code directly in the same fashion as the
Plain format \identifier{luatex-fonts} that is part of Context.
How this is executed depends on the presence on the
diff --git a/src/luaotfload-main.lua b/src/luaotfload-main.lua
index 32eb04d..3005f5a 100644
--- a/src/luaotfload-main.lua
+++ b/src/luaotfload-main.lua
@@ -150,7 +150,11 @@ local logreport = log.report
--doc]]--
-load_luaotfload_module "parsers" --- fonts.conf and syntax
+local tmp = load_luaotfload_module "parsers" --- fonts.conf and syntax
+if not tmp.init () then
+ logreport ("log", 0, "load", "Failed to install the parsers.")
+end
+
load_luaotfload_module "configuration" --- configuration options
if not config.actions.apply_defaults () then
diff --git a/src/luaotfload-parsers.lua b/src/luaotfload-parsers.lua
index a52b5d4..151cb9e 100644
--- a/src/luaotfload-parsers.lua
+++ b/src/luaotfload-parsers.lua
@@ -2,26 +2,14 @@
-------------------------------------------------------------------------------
-- FILE: luaotfload-parsers.lua
-- DESCRIPTION: various lpeg-based parsers used in Luaotfload
--- REQUIREMENTS: Luaotfload > 2.4
--- AUTHOR: Philipp Gesang (Phg),
+-- REQUIREMENTS: Luaotfload > 2.6
+-- AUTHOR: Philipp Gesang (Phg),
-- VERSION: same as Luaotfload
-- CREATED: 2014-01-14 10:15:20+0100
-------------------------------------------------------------------------------
--
-if not modules then modules = { } end modules ['luaotfload-parsers'] = {
- version = "2.5",
- comment = "companion to luaotfload-main.lua",
- author = "Philipp Gesang",
- copyright = "Luaotfload Development Team",
- license = "GNU GPL v2.0"
-}
-
-luaotfload = luaotfload or { }
-luaotfload.parsers = luaotfload.parsers or { }
-local parsers = luaotfload.parsers
-parsers.traversal_maxdepth = 42 --- prevent stack overflows
-local traversal_maxdepth = parsers.traversal_maxdepth --- TODO could be an option
+local traversal_maxdepth = 42 --- prevent stack overflows
local rawset = rawset
@@ -42,8 +30,7 @@ local filedirname = file.dirname
local io = io
local ioopen = io.open
-local log = luaotfload.log
-local logreport = log.report
+local logreport = print
local string = string
local stringsub = string.sub
@@ -399,10 +386,6 @@ local read_fonts_conf = function (path_list, find_files)
return acc
end
-luaotfload.parsers.read_fonts_conf = read_fonts_conf
-
-
-
-------------------------------------------------------------------------------
--- MISC PARSERS
-------------------------------------------------------------------------------
@@ -410,10 +393,8 @@ luaotfload.parsers.read_fonts_conf = read_fonts_conf
local trailingslashes = slash^1 * P(-1)
local stripslashes = C((1 - trailingslashes)^0)
-parsers.stripslashes = stripslashes
local splitcomma = Ct((C(noncomma^1) + comma)^1)
-parsers.splitcomma = splitcomma
@@ -653,8 +634,6 @@ local font_request = Ct(path_lookup * (colon^-1 * features)^-1
--- v2.5 parser: 1065 rules
--- v1.2 parser: 230 rules
-luaotfload.parsers.font_request = font_request
-
-------------------------------------------------------------------------------
--- INI FILES
-------------------------------------------------------------------------------
@@ -731,7 +710,7 @@ local ini_variables = Cg (Cf (Ct "" * ini_variable^0, rawset), "variables")
local ini_section = Ct (ini_heading * ini_variables)
local ini_sections = skip_line^0 * ini_section^0
-local config = Ct (ini_sections)
+local parse_config = Ct (ini_sections)
--[=[doc--
@@ -763,6 +742,22 @@ local config = Ct (ini_sections)
--doc]=]--
-luaotfload.parsers.config = config
+return {
+ init = function ()
+ logreport = luaotfload.log.report
+ luaotfload.parsers = {
+ --- parameters
+ traversal_maxdepth = traversal_maxdepth,
+ --- main parsers
+ read_fonts_conf = read_fonts_conf,
+ font_request = font_request,
+ config = parse_config,
+ --- common patterns
+ stripslashes = stripslashes,
+ splitcomma = splitcomma,
+ }
+ return true
+ end
+}
-- vim:ft=lua:tw=71:et:sw=2:sts=4:ts=8
--
cgit v1.2.3
From 974d9c6a280e42d01eb4a7c810900f9b4855e919 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Sun, 27 Sep 2015 18:43:41 +0200
Subject: [main, conf] prepare for deferred loading
---
src/luaotfload-configuration.lua | 57 ++++++++++++++++++++--------------------
src/luaotfload-main.lua | 22 ++++++++--------
2 files changed, 40 insertions(+), 39 deletions(-)
diff --git a/src/luaotfload-configuration.lua b/src/luaotfload-configuration.lua
index e2cfbd8..263c8ad 100644
--- a/src/luaotfload-configuration.lua
+++ b/src/luaotfload-configuration.lua
@@ -6,7 +6,6 @@
-- AUTHOR: Philipp Gesang (Phg),
-- AUTHOR: Dohyun Kim
-- VERSION: same as Luaotfload
--- MODIFIED: 2015-05-05
-------------------------------------------------------------------------------
--
@@ -18,17 +17,12 @@ if not modules then modules = { } end modules ["luaotfload-configuration"] = {
license = "GNU GPL v2.0"
}
-luaotfload = luaotfload or { }
-config = config or { }
-config.luaotfload = { }
-
local status_file = "luaotfload-status"
local luaotfloadstatus = require (status_file)
-local stringexplode = string.explode
+local string = string
local stringfind = string.find
local stringformat = string.format
-local string = string
local stringstrip = string.strip
local stringsub = string.sub
@@ -55,9 +49,7 @@ local lpegmatch = lpeg.match
local commasplitter = lpeg.splitat ","
local equalssplitter = lpeg.splitat "="
-local kpse = kpse
local kpseexpand_path = kpse.expand_path
-local kpselookup = kpse.lookup
local lfs = lfs
local lfsisfile = lfs.isfile
@@ -67,16 +59,12 @@ local file = file
local filejoin = file.join
local filereplacesuffix = file.replacesuffix
+local logreport = print -- overloaded later
+local getwritablepath = caches.getwritablepath
-local parsers = luaotfload.parsers
-
-local log = luaotfload.log
-local logreport = log.report
-
-local config_parser = parsers.config
-local stripslashes = parsers.stripslashes
-local getwritablepath = caches.getwritablepath
+local config_parser -- set later during init
+local stripslashes -- set later during init
-------------------------------------------------------------------------------
--- SETTINGS
@@ -301,8 +289,11 @@ local set_name_resolver = function ()
end
local set_loglevel = function ()
- log.set_loglevel (config.luaotfload.run.log_level)
- return true
+ if luaotfload then
+ luaotfload.log.set_loglevel (config.luaotfload.run.log_level)
+ return true
+ end
+ return false
end
local build_cache_paths = function ()
@@ -846,7 +837,7 @@ local read = function (extra)
return false
end
- local parsed = lpegmatch (parsers.config, raw)
+ local parsed = lpegmatch (config_parser, raw)
if not parsed then
logreport ("both", 2, "conf", "Error parsing configuration file %q.", readme)
return false
@@ -912,13 +903,23 @@ end
--- EXPORTS
-------------------------------------------------------------------------------
-luaotfload.default_config = default_config
-
-config.actions = {
- read = read,
- apply = apply,
- apply_defaults = apply_defaults,
- reconfigure = reconfigure,
- dump = dump,
+return {
+ init = function ()
+ config.luaotfload = { }
+ logreport = luaotfload.log.report
+ local parsers = luaotfload.parsers
+ config_parser = parsers.config
+ stripslashes = parsers.stripslashes
+
+ luaotfload.default_config = default_config
+ config.actions = {
+ read = read,
+ apply = apply,
+ apply_defaults = apply_defaults,
+ reconfigure = reconfigure,
+ dump = dump,
+ }
+ return true
+ end
}
diff --git a/src/luaotfload-main.lua b/src/luaotfload-main.lua
index 3005f5a..73f9a75 100644
--- a/src/luaotfload-main.lua
+++ b/src/luaotfload-main.lua
@@ -15,6 +15,7 @@
local initial_log_level = 0
luaotfload = luaotfload or { }
+config = config or { }
local luaotfload = luaotfload
luaotfload.log = luaotfload.log or { }
luaotfload.version = "2.6"
@@ -150,22 +151,21 @@ local logreport = log.report
--doc]]--
-local tmp = load_luaotfload_module "parsers" --- fonts.conf and syntax
-if not tmp.init () then
- logreport ("log", 0, "load", "Failed to install the parsers.")
-end
-
-load_luaotfload_module "configuration" --- configuration options
-
-if not config.actions.apply_defaults () then
- logreport ("log", 0, "load", "Configuration unsuccessful.")
-end
-
luaotfload.init.main (store)
luaotfload.main = function ()
local starttime = os.gettimeofday ()
+ local tmp = load_luaotfload_module "parsers" --- fonts.conf and syntax
+ if not tmp.init () then
+ logreport ("log", 0, "load", "Failed to install the parsers.")
+ end
+
+ local tmp = load_luaotfload_module "configuration" --- configuration options
+ if not tmp.init() or not config.actions.apply_defaults () then
+ logreport ("log", 0, "load", "Configuration unsuccessful.")
+ end
+
luaotfload.loaders = load_luaotfload_module "loaders" --- Font loading; callbacks
if not luaotfload.loaders.install () then
logreport ("log", 0, "load", "Callback and loader initialization failed.")
--
cgit v1.2.3
From 145203842d83591fc9e67322472994c481d5aadc Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Sun, 27 Sep 2015 18:50:22 +0200
Subject: [main] move toplevel statements into init routine
---
src/luaotfload-main.lua | 17 ++++++++---------
1 file changed, 8 insertions(+), 9 deletions(-)
diff --git a/src/luaotfload-main.lua b/src/luaotfload-main.lua
index 73f9a75..9e57dbf 100644
--- a/src/luaotfload-main.lua
+++ b/src/luaotfload-main.lua
@@ -139,26 +139,21 @@ local load_fontloader_module = make_loader "fontloader"
luaotfload.loaders.luaotfload = load_luaotfload_module
luaotfload.loaders.fontloader = load_fontloader_module
-luaotfload.init = load_luaotfload_module "init" --- fontloader initialization
-
-local store = luaotfload.init.early ()
-local log = luaotfload.log
-local logreport = log.report
-
--[[doc--
Now we load the modules written for \identifier{luaotfload}.
--doc]]--
-luaotfload.init.main (store)
-
luaotfload.main = function ()
local starttime = os.gettimeofday ()
+ local init = load_luaotfload_module "init" --- fontloader initialization
+ local store = init.early () --- injects the log module too
+ local logreport = luaotfload.log.report
local tmp = load_luaotfload_module "parsers" --- fonts.conf and syntax
if not tmp.init () then
- logreport ("log", 0, "load", "Failed to install the parsers.")
+ logreport ("log", 0, "load", "Failed to install the parsers module.")
end
local tmp = load_luaotfload_module "configuration" --- configuration options
@@ -166,6 +161,10 @@ luaotfload.main = function ()
logreport ("log", 0, "load", "Configuration unsuccessful.")
end
+ if not init.main (store) then
+ logreport ("log", 0, "load", "Main fontloader initialization failed.")
+ end
+
luaotfload.loaders = load_luaotfload_module "loaders" --- Font loading; callbacks
if not luaotfload.loaders.install () then
logreport ("log", 0, "load", "Callback and loader initialization failed.")
--
cgit v1.2.3
From 1497cfdbee7193ab84f87daa6229b54be3209cd4 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Sun, 27 Sep 2015 19:18:06 +0200
Subject: [main, db] convert for deferred initialization
Also clean up the local name of the logger for consistency with the rest
of the code base.
---
src/luaotfload-database.lua | 440 +++++++++++++++++++++++---------------------
1 file changed, 226 insertions(+), 214 deletions(-)
diff --git a/src/luaotfload-database.lua b/src/luaotfload-database.lua
index f4aab16..d9d7594 100644
--- a/src/luaotfload-database.lua
+++ b/src/luaotfload-database.lua
@@ -45,7 +45,7 @@ local stripslashes = parsers.stripslashes
local splitcomma = parsers.splitcomma
local log = luaotfload.log
-local report = log.report
+local logreport = log and log.report or print -- overriden later on
local report_status = log.names_status
local report_status_start = log.names_status_start
local report_status_stop = log.names_status_stop
@@ -119,19 +119,10 @@ local tablefastcopy = table.fastcopy
local tabletofile = table.tofile
local tabletohash = table.tohash
local tableserialize = table.serialize
---- the font loader namespace is “fonts”, same as in Context
---- we need to put some fallbacks into place for when running
---- as a script
-fonts = fonts or { }
-fonts.names = fonts.names or { }
-fonts.definers = fonts.definers or { }
-
-local names = fonts.names
+local names = fonts and fonts.names or { }
+
local name_index = nil --> upvalue for names.data
local lookup_cache = nil --> for names.lookups
-names.version = 2.51
-names.data = nil --- contains the loaded database
-names.lookups = nil --- contains the lookup cache
--- string -> (string * string)
local make_luanames = function (path)
@@ -485,12 +476,12 @@ load_names = function (dry_run, no_rebuild)
local foundname, data = load_lua_file (config.luaotfload.paths.index_path_lua)
if data then
- report ("log", 0, "db",
- "Font names database loaded from %s", foundname)
- report ("term", 3, "db",
- "Font names database loaded from %s", foundname)
- report ("info", 3, "db", "Loading took %0.f ms.",
- 1000 * (osgettimeofday () - starttime))
+ logreport ("log", 0, "db",
+ "Font names database loaded from %s", foundname)
+ logreport ("term", 3, "db",
+ "Font names database loaded from %s", foundname)
+ logreport ("info", 3, "db", "Loading took %0.f ms.",
+ 1000 * (osgettimeofday () - starttime))
local db_version, names_version
if data.meta then
@@ -503,32 +494,32 @@ load_names = function (dry_run, no_rebuild)
end
names_version = names.version
if db_version ~= names_version then
- report ("both", 0, "db",
- [[Version mismatch; expected %4.3f, got %4.3f.]],
- names_version, db_version)
+ logreport ("both", 0, "db",
+ [[Version mismatch; expected %4.3f, got %4.3f.]],
+ names_version, db_version)
if not fonts_reloaded then
- report ("both", 0, "db", [[Force rebuild.]])
+ logreport ("both", 0, "db", [[Force rebuild.]])
data = update_names ({ }, true, false)
if not data then
- report ("both", 0, "db",
- "Database creation unsuccessful.")
+ logreport ("both", 0, "db",
+ "Database creation unsuccessful.")
end
end
end
else
if no_rebuild == true then
- report ("both", 2, "db",
- [[Database does not exist, skipping rebuild though.]])
+ logreport ("both", 2, "db",
+ [[Database does not exist, skipping rebuild though.]])
return false
end
- report ("both", 0, "db",
- [[Font names database not found, generating new one.]])
- report ("both", 0, "db",
- [[This can take several minutes; please be patient.]])
+ logreport ("both", 0, "db",
+ [[Font names database not found, generating new one.]])
+ logreport ("both", 0, "db",
+ [[This can take several minutes; please be patient.]])
data = update_names (initialize_namedata (get_font_filter ()),
nil, dry_run)
if not data then
- report ("both", 0, "db", "Database creation unsuccessful.")
+ logreport ("both", 0, "db", "Database creation unsuccessful.")
end
end
return data
@@ -559,12 +550,12 @@ local load_lookups
load_lookups = function ( )
local foundname, data = load_lua_file(config.luaotfload.paths.lookup_path_lua)
if data then
- report("log", 0, "cache", "Lookup cache loaded from %s.", foundname)
- report("term", 3, "cache",
- "Lookup cache loaded from %s.", foundname)
+ logreport ("log", 0, "cache", "Lookup cache loaded from %s.", foundname)
+ logreport ("term", 3, "cache",
+ "Lookup cache loaded from %s.", foundname)
else
- report("both", 1, "cache",
- "No lookup cache, creating empty.")
+ logreport ("both", 1, "cache",
+ "No lookup cache, creating empty.")
data = { }
end
lookup_cache = data
@@ -780,23 +771,24 @@ local lookup_font_name_cached
lookup_font_name_cached = function (specification)
if not lookup_cache then load_lookups () end
local request = hash_request(specification)
- report("both", 4, "cache", "Looking for %q in cache ...",
- request)
+ logreport ("both", 4, "cache", "Looking for %q in cache ...",
+ request)
local found = lookup_cache [request]
--- case 1) cache positive ----------------------------------------
if found then --- replay fields from cache hit
- report("info", 4, "cache", "Found!")
+ logreport ("info", 4, "cache", "Found!")
local basename = found[1]
--- check the presence of the file in case it’s been removed
local success = verify_font_file (basename)
if success == true then
return basename, found[2], true
end
- report("both", 4, "cache", "Cached file not found; resolving again.")
+ logreport ("both", 4, "cache",
+ "Cached file not found; resolving again.")
else
- report("both", 4, "cache", "Not cached; resolving.")
+ logreport ("both", 4, "cache", "Not cached; resolving.")
end
--- case 2) cache negative ----------------------------------------
@@ -807,16 +799,16 @@ lookup_font_name_cached = function (specification)
end
--- ... then we add the fields to the cache ... ...
local entry = { filename, subfont }
- report("both", 4, "cache", "New entry: %s.", request)
+ logreport ("both", 4, "cache", "New entry: %s.", request)
lookup_cache [request] = entry
--- obviously, the updated cache needs to be stored.
--- TODO this should trigger a save only once the
--- document is compiled (finish_pdffile callback?)
- report("both", 5, "cache", "Saving updated cache.")
+ logreport ("both", 5, "cache", "Saving updated cache.")
local success = save_lookups ()
if not success then --- sad, but not critical
- report("both", 0, "cache", "Error writing cache.")
+ logreport ("both", 0, "cache", "Error writing cache.")
end
return filename, subfont
end
@@ -973,8 +965,8 @@ local lookup_familyname = function (specification, name, style, askedsize)
if not success then
return nil, nil
end
- report ("info", 2, "db", "Match found: %s(%d).",
- resolved, subfont or 0)
+ logreport ("info", 2, "db", "Match found: %s(%d).",
+ resolved, subfont or 0)
return resolved, subfont
end
@@ -1140,9 +1132,9 @@ reload_db = function (why, caller, ...)
local namedata = name_index
local formats = tableconcat (namedata.meta.formats, ",")
- report ("both", 0, "db",
- "Reload initiated (formats: %s); reason: %q.",
- formats, why)
+ logreport ("both", 0, "db",
+ "Reload initiated (formats: %s); reason: %q.",
+ formats, why)
set_font_filter (formats)
namedata = update_names (namedata, false, false)
@@ -1153,7 +1145,7 @@ reload_db = function (why, caller, ...)
return caller (...)
end
- report ("both", 0, "db", "Database update unsuccessful.")
+ logreport ("both", 0, "db", "Database update unsuccessful.")
end
--- string -> string -> int
@@ -1237,15 +1229,15 @@ find_closest = function (name, limit)
if n_distances > 0 then --- got some data
tablesort(distances)
limit = mathmin(n_distances, limit)
- report(false, 1, "query",
- "Displaying %d distance levels.", limit)
+ logreport (false, 1, "query",
+ "Displaying %d distance levels.", limit)
for i = 1, limit do
local dist = distances[i]
local namelst = by_distance[dist]
- report(false, 0, "query",
- "Distance from \"%s\": %s\n "
- .. tableconcat (namelst, "\n "),
+ logreport (false, 0, "query",
+ "Distance from \"%s\": %s\n "
+ .. tableconcat (namelst, "\n "),
name, dist)
end
@@ -1273,7 +1265,7 @@ local load_font_file = function (filename, subfont)
local rawfont, _msg = fontloaderopen (filename, subfont)
--local rawfont, _msg = fontloaderinfo (filename, subfont)
if not rawfont then
- report ("log", 1, "db", "ERROR: failed to open %s.", filename)
+ logreport ("log", 1, "db", "ERROR: failed to open %s.", filename)
return
end
return rawfont
@@ -1316,8 +1308,8 @@ local get_english_names = function (metadata)
end
-- no (English) names table, probably a broken font
- report("both", 3, "db",
- "%s: missing or broken English names table.", basename)
+ logreport ("both", 3, "db",
+ "%s: missing or broken English names table.", basename)
return { fontname = metadata.fontname,
fullname = metadata.fullname, }
end
@@ -1343,9 +1335,9 @@ local get_raw_info = function (metadata, basename)
--- Broken names table, e.g. avkv.ttf with UTF-16 strings;
--- we put some dummies in place like the fontloader
--- (font-otf.lua) does.
- report("both", 3, "db",
- "%s has invalid postscript font names, using dummies.",
- basename)
+ logreport ("both", 3, "db",
+ "%s has invalid postscript font names, using dummies.",
+ basename)
fontname = "bad-fontname-" .. basename
fullname = "bad-fullname-" .. basename
end
@@ -1619,7 +1611,7 @@ local compare_timestamps = function (fullname,
if targetentrystatus ~= nil
and targetentrystatus.timestamp == targettimestamp then
- report ("log", 3, "db", "Font %q already read.", fullname)
+ logreport ("log", 3, "db", "Font %q already read.", fullname)
return false
end
@@ -1641,7 +1633,7 @@ local compare_timestamps = function (fullname,
targetentrystatus.index [targetindex + 1] = location
end
- report ("log", 3, "db", "Font %q already indexed.", fullname)
+ logreport ("log", 3, "db", "Font %q already indexed.", fullname)
return false
end
@@ -1721,8 +1713,8 @@ local read_font_names = function (fullname,
--- 1) skip if blacklisted
if names.blacklist[fullname] or names.blacklist[basename] then
- report("log", 2, "db",
- "Ignoring blacklisted font %q.", fullname)
+ logreport ("log", 2, "db",
+ "Ignoring blacklisted font %q.", fullname)
return false
end
@@ -1745,8 +1737,8 @@ local read_font_names = function (fullname,
local loader = loaders [format] --- ot_fullinfo, t1_fullinfo
if not loader then
- report ("both", 0, "db",
- "Unknown format: %q, skipping.", format)
+ logreport ("both", 0, "db",
+ "Unknown format: %q, skipping.", format)
return false
end
@@ -1755,8 +1747,8 @@ local read_font_names = function (fullname,
local info = fontloaderinfo (fullname)
if not info then
- report ("log", 1, "db",
- "Failed to read basic information from %q", basename)
+ logreport ("log", 1, "db",
+ "Failed to read basic information from %q", basename)
return false
end
@@ -1830,9 +1822,7 @@ end
fonts.path_normalize = path_normalize
-names.blacklist = { }
-
-local blacklist = names.blacklist
+local blacklist = { }
local p_blacklist --- prefixes of dirs
--- string list -> string list
@@ -1861,8 +1851,8 @@ local create_blacklist = function (blacklist, whitelist)
local result = { }
local dirs = { }
- report("info", 2, "db", "Blacklisting %d files and directories.",
- #blacklist)
+ logreport ("info", 2, "db", "Blacklisting %d files and directories.",
+ #blacklist)
for i=1, #blacklist do
local entry = blacklist[i]
if lfsisdir(entry) then
@@ -1872,7 +1862,7 @@ local create_blacklist = function (blacklist, whitelist)
end
end
- report("info", 2, "db", "Whitelisting %d files.", #whitelist)
+ logreport ("info", 2, "db", "Whitelisting %d files.", #whitelist)
for i=1, #whitelist do
result[whitelist[i]] = nil
end
@@ -1914,9 +1904,9 @@ read_blacklist = function ()
if first_chr == "%" or stringis_empty(line) then
-- comment or empty line
elseif first_chr == "-" then
- report ("both", 3, "db",
- "Whitelisted file %q via %q.",
- line, path)
+ logreport ("both", 3, "db",
+ "Whitelisted file %q via %q.",
+ line, path)
whitelist[#whitelist+1] = stringsub(line, 2, -1)
else
local cmt = stringfind(line, "%%")
@@ -1924,9 +1914,9 @@ read_blacklist = function ()
line = stringsub(line, 1, cmt - 1)
end
line = stringstrip(line)
- report ("both", 3, "db",
- "Blacklisted file %q via %q.",
- line, path)
+ logreport ("both", 3, "db",
+ "Blacklisted file %q via %q.",
+ line, path)
blacklist[#blacklist+1] = line
end
end
@@ -2123,24 +2113,24 @@ end
--- string -> string -> string * string list
local collect_font_filenames_dir = function (dirname, location)
if lpegmatch (p_blacklist, dirname) then
- report ("both", 4, "db",
- "Skipping blacklisted directory %s.", dirname)
+ logreport ("both", 4, "db",
+ "Skipping blacklisted directory %s.", dirname)
--- ignore
return { }
end
local found = find_font_files (dirname, location ~= "texmf" and location ~= "local")
if not found then
- report ("both", 4, "db",
- "No such directory: %q; skipping.", dirname)
+ logreport ("both", 4, "db",
+ "No such directory: %q; skipping.", dirname)
return { }
end
local nfound = #found
local files = { }
- report ("both", 4, "db",
- "%d font files detected in %s.",
- nfound, dirname)
+ logreport ("both", 4, "db",
+ "%d font files detected in %s.",
+ nfound, dirname)
for j = 1, nfound do
local fullname = found[j]
files[#files + 1] = { path_normalize (fullname), location }
@@ -2184,14 +2174,14 @@ local collect_font_filenames_texmf = function ()
local osfontdir = kpseexpand_path "$OSFONTDIR"
if stringis_empty (osfontdir) then
- report ("info", 1, "db", "Scanning TEXMF for fonts...")
+ logreport ("info", 1, "db", "Scanning TEXMF for fonts...")
else
- report ("info", 1, "db", "Scanning TEXMF and $OSFONTDIR for fonts...")
+ logreport ("info", 1, "db", "Scanning TEXMF and $OSFONTDIR for fonts...")
if log.get_loglevel () > 3 then
local osdirs = filesplitpath (osfontdir)
- report ("info", 0, "db", "$OSFONTDIR has %d entries:", #osdirs)
+ logreport ("info", 0, "db", "$OSFONTDIR has %d entries:", #osdirs)
for i = 1, #osdirs do
- report ("info", 0, "db", "[%d] %s", i, osdirs[i])
+ logreport ("info", 0, "db", "[%d] %s", i, osdirs[i])
end
end
end
@@ -2205,14 +2195,14 @@ local collect_font_filenames_texmf = function ()
end
local tasks = filter_out_pwd (filesplitpath (fontdirs))
- report ("info", 3, "db",
- "Initiating scan of %d directories.", #tasks)
+ logreport ("info", 3, "db",
+ "Initiating scan of %d directories.", #tasks)
local files = { }
for _, dir in next, tasks do
files = tableappend (files, collect_font_filenames_dir (dir, "texmf"))
end
- report ("term", 3, "db", "Collected %d files.", #files)
+ logreport ("term", 3, "db", "Collected %d files.", #files)
return files
end
@@ -2247,14 +2237,14 @@ end
--- string list -> size_t
local count_removed = function (old)
- report("log", 4, "db", "Checking removed files.")
+ logreport ("log", 4, "db", "Checking removed files.")
local nrem = 0
local nold = #old
for i = 1, nold do
local f = old[i]
if not kpsereadable_file (f) then
- report("log", 2, "db",
- "File %s does not exist in file system.")
+ logreport ("log", 2, "db",
+ "File %s does not exist in file system.")
nrem = nrem + 1
end
end
@@ -2281,7 +2271,7 @@ local retrieve_namedata = function (files, currentnames, targetnames, dry_run)
local nfiles = #files
local nnew = 0
- report ("info", 1, "db", "Scanning %d collected font files ...", nfiles)
+ logreport ("info", 1, "db", "Scanning %d collected font files ...", nfiles)
local bylocation = { texmf = { 0, 0 }
, ["local"] = { 0, 0 }
@@ -2294,12 +2284,12 @@ local retrieve_namedata = function (files, currentnames, targetnames, dry_run)
count[1] = count[1] + 1
if dry_run == true then
local truncated = truncate_string (fullname, 43)
- report ("log", 2, "db", "Would have been loading %s.", fullname)
+ logreport ("log", 2, "db", "Would have been loading %s.", fullname)
report_status ("term", "db", "Would have been loading %s", truncated)
--- skip the read_font_names part
else
local truncated = truncate_string (fullname, 32)
- report ("log", 2, "db", "Loading font %s.", fullname)
+ logreport ("log", 2, "db", "Loading font %s.", fullname)
report_status ("term", "db", "Loading font %s", truncated)
local new = read_font_names (fullname, currentnames,
targetnames, location)
@@ -2311,8 +2301,8 @@ local retrieve_namedata = function (files, currentnames, targetnames, dry_run)
end
report_status_stop ("term", "db", "Scanned %d files, %d new.", nfiles, nnew)
for location, count in next, bylocation do
- report ("term", 4, "db", " * %s: %d files, %d new",
- location, count[1], count[2])
+ logreport ("term", 4, "db", " * %s: %d files, %d new",
+ location, count[1], count[2])
end
return nnew
end
@@ -2321,15 +2311,15 @@ end
local collect_font_filenames_system = function ()
local n_scanned, n_new = 0, 0
- report ("info", 1, "db", "Scanning system fonts...")
- report ("info", 2, "db",
- "Searching in static system directories...")
+ logreport ("info", 1, "db", "Scanning system fonts...")
+ logreport ("info", 2, "db",
+ "Searching in static system directories...")
local files = { }
for _, dir in next, get_os_dirs () do
tableappend (files, collect_font_filenames_dir (dir, "system"))
end
- report ("term", 3, "db", "Collected %d files.", #files)
+ logreport ("term", 3, "db", "Collected %d files.", #files)
return files
end
@@ -2355,25 +2345,25 @@ end
--- unit -> string * string list
local collect_font_filenames_local = function ()
local pwd = lfscurrentdir ()
- report ("both", 1, "db", "Scanning for fonts in $PWD (%q) ...", pwd)
+ logreport ("both", 1, "db", "Scanning for fonts in $PWD (%q) ...", pwd)
local files = collect_font_filenames_dir (pwd, "local")
local nfiles = #files
if nfiles > 0 then
targetnames.meta["local"] = true --- prevent saving to disk
- report ("term", 1, "db", "Found %d files.", pwd)
+ logreport ("term", 1, "db", "Found %d files.", pwd)
else
- report ("term", 1, "db",
- "Couldn’t find a thing here. What a waste.", pwd)
+ logreport ("term", 1, "db",
+ "Couldn’t find a thing here. What a waste.", pwd)
end
- report ("term", 3, "db", "Collected %d files.", #files)
+ logreport ("term", 3, "db", "Collected %d files.", #files)
return files
end
--- fontentry list -> filemap
generate_filedata = function (mappings)
- report ("both", 2, "db", "Creating filename map.")
+ logreport ("both", 2, "db", "Creating filename map.")
local nmappings = #mappings
@@ -2435,10 +2425,10 @@ generate_filedata = function (mappings)
if inbase then
local present = inbase [basename]
if present then
- report ("both", 4, "db",
- "Conflicting basename: %q already indexed \z
- in category %s, ignoring.",
- barename, location)
+ logreport ("both", 4, "db",
+ "Conflicting basename: %q already indexed \z
+ in category %s, ignoring.",
+ barename, location)
conflicts.basenames = conflicts.basenames + 1
--- track conflicts per font
@@ -2465,10 +2455,10 @@ generate_filedata = function (mappings)
if inbare then
local present = inbare [barename]
if present then
- report ("both", 4, "db",
- "Conflicting barename: %q already indexed \z
- in category %s/%s, ignoring.",
- barename, location, format)
+ logreport ("both", 4, "db",
+ "Conflicting barename: %q already indexed \z
+ in category %s/%s, ignoring.",
+ barename, location, format)
conflicts.barenames = conflicts.barenames + 1
--- track conflicts per font
@@ -2650,7 +2640,7 @@ end
collect_families = function (mappings)
- report ("info", 2, "db", "Analyzing families.")
+ logreport ("info", 2, "db", "Analyzing families.")
local families = {
["local"] = { },
@@ -2746,7 +2736,7 @@ local style_categories = { "r", "b", "i", "bi" }
local bold_categories = { "b", "bi" }
group_modifiers = function (mappings, families)
- report ("info", 2, "db", "Analyzing shapes, weights, and styles.")
+ logreport ("info", 2, "db", "Analyzing shapes, weights, and styles.")
for location, location_data in next, families do
for format, format_data in next, location_data do
for familyname, collected in next, format_data do
@@ -2845,7 +2835,7 @@ end
order_design_sizes = function (families)
- report ("info", 2, "db", "Ordering design sizes.")
+ logreport ("info", 2, "db", "Ordering design sizes.")
for location, data in next, families do
for format, data in next, data do
@@ -2870,7 +2860,7 @@ end
--- unit -> string * string list
local collect_font_filenames = function ()
- report ("info", 4, "db", "Scanning the filesystem for font files.")
+ logreport ("info", 4, "db", "Scanning the filesystem for font files.")
local filenames = { }
local bisect = config.luaotfload.misc.bisect
@@ -2900,7 +2890,7 @@ end
--- int -> string
local nth_font_filename = function (n)
- report ("info", 4, "db", "Picking font file no. %d.", n)
+ logreport ("info", 4, "db", "Picking font file no. %d.", n)
if not p_blacklist then
read_blacklist ()
end
@@ -2915,7 +2905,7 @@ end
--doc]]--
local font_slice = function (lo, hi)
- report ("info", 4, "db", "Retrieving font files nos. %d--%d.", lo, hi)
+ logreport ("info", 4, "db", "Retrieving font files nos. %d--%d.", lo, hi)
if not p_blacklist then
read_blacklist ()
end
@@ -2937,7 +2927,7 @@ end
--- unit -> int
local count_font_files = function ()
- report ("info", 4, "db", "Counting font files.")
+ logreport ("info", 4, "db", "Counting font files.")
if not p_blacklist then
read_blacklist ()
end
@@ -3063,31 +3053,31 @@ local collect_statistics = function (mappings)
itemlist = tableconcat (itemlist, ", ")
end
- report ("both", 0, "db",
- " · %4d × %s.",
- freq, itemlist)
+ logreport ("both", 0, "db",
+ " · %4d × %s.",
+ freq, itemlist)
end
end
- report ("both", 0, "", "~~~~ font index statistics ~~~~")
- report ("both", 0, "db",
- " · Collected %d fonts (%d names) in %d families.",
- #mappings, n_fullname, n_family)
+ logreport ("both", 0, "", "~~~~ font index statistics ~~~~")
+ logreport ("both", 0, "db",
+ " · Collected %d fonts (%d names) in %d families.",
+ #mappings, n_fullname, n_family)
pprint_top (families, 4, true)
- report ("both", 0, "db",
- " · %d different “subfamily” kinds.",
- setsize (subfamily))
+ logreport ("both", 0, "db",
+ " · %d different “subfamily” kinds.",
+ setsize (subfamily))
pprint_top (subfamily, 4)
- report ("both", 0, "db",
- " · %d different “prefmodifiers” kinds.",
- setsize (prefmodifiers))
+ logreport ("both", 0, "db",
+ " · %d different “prefmodifiers” kinds.",
+ setsize (prefmodifiers))
pprint_top (prefmodifiers, 4)
- report ("both", 0, "db",
- " · %d different “fontstyle_name” kinds.",
- setsize (fontstyle_name))
+ logreport ("both", 0, "db",
+ " · %d different “fontstyle_name” kinds.",
+ setsize (fontstyle_name))
pprint_top (fontstyle_name, 4)
end
@@ -3121,7 +3111,7 @@ update_names = function (currentnames, force, dry_run)
local conf = config.luaotfload
if conf.run.live ~= false and conf.db.update_live == false then
- report ("info", 2, "db", "Skipping database update.")
+ logreport ("info", 2, "db", "Skipping database update.")
--- skip all db updates
return currentnames or name_index
end
@@ -3133,15 +3123,16 @@ update_names = function (currentnames, force, dry_run)
- “targetnames” is the final table to return
- force is whether we rebuild it from scratch or not
]]
- report("both", 1, "db", "Updating the font names database"
- .. (force and " forcefully." or "."))
+ logreport ("both", 1, "db",
+ "Updating the font names database"
+ .. (force and " forcefully." or "."))
if config.luaotfload.db.skip_read == true then
--- the difference to a “dry run” is that we don’t search
--- for font files entirely. we also ignore the “force”
--- parameter since it concerns only the font files.
- report ("info", 2, "db",
- "Ignoring font files, reusing old data.")
+ logreport ("info", 2, "db",
+ "Ignoring font files, reusing old data.")
currentnames = load_names (false)
targetnames = currentnames
else
@@ -3152,8 +3143,9 @@ update_names = function (currentnames, force, dry_run)
currentnames = load_names (dry_run)
end
if currentnames.meta.version ~= names.version then
- report ("both", 1, "db", "No font names database or old "
- .. "one found; generating new one.")
+ logreport ("both", 1, "db",
+ "No font names database or old \z
+ one found; generating new one.")
currentnames = initialize_namedata (get_font_filter ())
end
end
@@ -3176,9 +3168,9 @@ update_names = function (currentnames, force, dry_run)
targetnames,
dry_run)
- report ("info", 3, "db",
- "Found %d font files; %d new, %d stale entries.",
- #font_filenames, n_new, n_rem)
+ logreport ("info", 3, "db",
+ "Found %d font files; %d new, %d stale entries.",
+ #font_filenames, n_new, n_rem)
end
--- pass 3 (optional): collect some stats about the raw font info
@@ -3204,27 +3196,27 @@ update_names = function (currentnames, force, dry_run)
--- pass 7: order design size tables
targetnames.families = order_design_sizes (targetnames.families)
- report ("info", 3, "db",
- "Rebuilt in %0.f ms.",
- 1000 * (osgettimeofday () - starttime))
+ logreport ("info", 3, "db",
+ "Rebuilt in %0.f ms.",
+ 1000 * (osgettimeofday () - starttime))
name_index = targetnames
if dry_run ~= true then
if n_new + n_rem == 0 then
- report ("info", 2, "db",
- "No new or removed fonts, skip saving to disk.")
+ logreport ("info", 2, "db",
+ "No new or removed fonts, skip saving to disk.")
else
local success, reason = save_names ()
if not success then
- report ("both", 0, "db",
- "Failed to save database to disk: %s",
- reason)
+ logreport ("both", 0, "db",
+ "Failed to save database to disk: %s",
+ reason)
end
end
if flush_lookup_cache () and save_lookups () then
- report ("both", 2, "cache", "Lookup cache emptied.")
+ logreport ("both", 2, "cache", "Lookup cache emptied.")
return targetnames
end
end
@@ -3241,18 +3233,18 @@ save_lookups = function ( )
caches.compile (lookup_cache, luaname, lucname)
--- double check ...
if lfsisfile (luaname) and lfsisfile (lucname) then
- report ("both", 3, "cache", "Lookup cache saved.")
+ logreport ("both", 3, "cache", "Lookup cache saved.")
return true
end
- report ("info", 0, "cache", "Could not compile lookup cache.")
+ logreport ("info", 0, "cache", "Could not compile lookup cache.")
return false
end
- report ("info", 0, "cache", "Lookup cache file not writable.")
+ logreport ("info", 0, "cache", "Lookup cache file not writable.")
if not fileiswritable (luaname) then
- report ("info", 0, "cache", "Failed to write %s.", luaname)
+ logreport ("info", 0, "cache", "Failed to write %s.", luaname)
end
if not fileiswritable (lucname) then
- report ("info", 0, "cache", "Failed to write %s.", lucname)
+ logreport ("info", 0, "cache", "Failed to write %s.", lucname)
end
return false
end
@@ -3281,33 +3273,33 @@ save_names = function (currentnames)
tabletofile (luaname, currentnames, true)
caches.compile (currentnames, luaname, lucname)
end
- report ("info", 2, "db", "Font index saved at ...")
+ logreport ("info", 2, "db", "Font index saved at ...")
local success = false
if lfsisfile (luaname) then
- report ("info", 2, "db", "Text: " .. luaname)
+ logreport ("info", 2, "db", "Text: " .. luaname)
success = true
end
if lfsisfile (gzname) then
- report ("info", 2, "db", "Gzip: " .. gzname)
+ logreport ("info", 2, "db", "Gzip: " .. gzname)
success = true
end
if lfsisfile (lucname) then
- report ("info", 2, "db", "Byte: " .. lucname)
+ logreport ("info", 2, "db", "Byte: " .. lucname)
success = true
end
if success then
return true
else
- report ("info", 0, "db", "Could not compile font index.")
+ logreport ("info", 0, "db", "Could not compile font index.")
return false
end
end
- report ("info", 0, "db", "Index file not writable")
+ logreport ("info", 0, "db", "Index file not writable")
if not fileiswritable (luaname) then
- report ("info", 0, "db", "Failed to write %s.", luaname)
+ logreport ("info", 0, "db", "Failed to write %s.", luaname)
end
if not fileiswritable (lucname) then
- report ("info", 0, "db", "Failed to write %s.", lucname)
+ logreport ("info", 0, "db", "Failed to write %s.", lucname)
end
return false
end
@@ -3321,7 +3313,7 @@ end
--- string -> string -> string list -> string list -> string list -> unit
local print_cache = function (category, path, luanames, lucnames, rest)
local report_indeed = function (...)
- report("info", 0, "cache", ...)
+ logreport ("info", 0, "cache", ...)
end
report_indeed("Luaotfload cache: %s", category)
report_indeed("location: %s", path)
@@ -3333,15 +3325,15 @@ end
--- string -> string -> string list -> bool -> bool
local purge_from_cache = function (category, path, list, all)
- report("info", 1, "cache", "Luaotfload cache: %s %s",
- (all and "erase" or "purge"), category)
- report("info", 1, "cache", "location: %s",path)
+ logreport ("info", 1, "cache", "Luaotfload cache: %s %s",
+ (all and "erase" or "purge"), category)
+ logreport ("info", 1, "cache", "location: %s", path)
local n = 0
for i=1,#list do
local filename = list[i]
if stringfind(filename,"luatex%-cache") then -- safeguard
if all then
- report("info", 5, "cache", "Removing %s.", filename)
+ logreport ("info", 5, "cache", "Removing %s.", filename)
osremove(filename)
n = n + 1
else
@@ -3350,7 +3342,7 @@ local purge_from_cache = function (category, path, list, all)
local checkname = file.replacesuffix(
filename, "lua", "luc")
if lfsisfile(checkname) then
- report("info", 5, "cache", "Removing %s.", filename)
+ logreport ("info", 5, "cache", "Removing %s.", filename)
osremove(filename)
n = n + 1
end
@@ -3358,7 +3350,7 @@ local purge_from_cache = function (category, path, list, all)
end
end
end
- report("info", 1, "cache", "Removed lua files : %i", n)
+ logreport ("info", 1, "cache", "Removed lua files : %i", n)
return true
end
@@ -3435,7 +3427,7 @@ local erase_cache = function ( )
end
local separator = function ( )
- report("info", 0, string.rep("-", 67))
+ logreport ("info", 0, string.rep("-", 67))
end
--- unit -> unit
@@ -3464,35 +3456,55 @@ end
--- export functionality to the namespace “fonts.names”
-----------------------------------------------------------------------
-names.set_font_filter = set_font_filter
-names.flush_lookup_cache = flush_lookup_cache
-names.save_lookups = save_lookups
-names.load = load_names
-names.access_font_index = access_font_index
-names.data = function () return name_index end
-names.save = save_names
-names.update = update_names
-names.lookup_font_file = lookup_font_file
-names.lookup_font_name = lookup_font_name
-names.lookup_font_name_cached = lookup_font_name_cached
-names.getfilename = lookup_fullpath
-names.lookup_fullpath = lookup_fullpath
-names.read_blacklist = read_blacklist
-names.sanitize_fontname = sanitize_fontname
-names.getmetadata = getmetadata
-names.set_location_precedence = set_location_precedence
-names.count_font_files = count_font_files
-names.nth_font_filename = nth_font_filename
-names.font_slice = font_slice
-
---- font cache
-names.purge_cache = purge_cache
-names.erase_cache = erase_cache
-names.show_cache = show_cache
-
-names.find_closest = find_closest
-
--- for testing purpose
-names.read_fonts_conf = read_fonts_conf
+local export = {
+ set_font_filter = set_font_filter,
+ flush_lookup_cache = flush_lookup_cache,
+ save_lookups = save_lookups,
+ load = load_names,
+ access_font_index = access_font_index,
+ data = function () return name_index end,
+ save = save_names,
+ update = update_names,
+ lookup_font_file = lookup_font_file,
+ lookup_font_name = lookup_font_name,
+ lookup_font_name_cached = lookup_font_name_cached,
+ getfilename = lookup_fullpath,
+ lookup_fullpath = lookup_fullpath,
+ read_blacklist = read_blacklist,
+ sanitize_fontname = sanitize_fontname,
+ getmetadata = getmetadata,
+ set_location_precedence = set_location_precedence,
+ count_font_files = count_font_files,
+ nth_font_filename = nth_font_filename,
+ font_slice = font_slice,
+ --- font cache
+ purge_cache = purge_cache,
+ erase_cache = erase_cache,
+ show_cache = show_cache,
+ find_closest = find_closest,
+ -- for testing purpose
+ read_fonts_conf = read_fonts_conf,
+}
+
+return {
+ init = function ()
+ --- the font loader namespace is “fonts”, same as in Context
+ --- we need to put some fallbacks into place for when running
+ --- as a script
+ log = luaotfload.log
+ logreport = log.report
+ fonts = fonts or { }
+ local fonts = fonts
+ fonts.names = fonts.names or names
+ fonts.definers = fonts.definers or { }
+
+ names.blacklist = blacklist
+ names.version = 2.51
+ names.data = nil --- contains the loaded database
+ names.lookups = nil --- contains the lookup cache
+
+ for sym, ref in next, export do names[sym] = ref end
+ end
+}
-- vim:tw=71:sw=4:ts=4:expandtab
--
cgit v1.2.3
From 780113609ffbb146c1b5a825cb25025246cdba2a Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Sun, 27 Sep 2015 20:17:02 +0200
Subject: [main, *] convert for centralized initialization routine
---
src/luaotfload-colors.lua | 78 +++++++++++++++++---------------
src/luaotfload-configuration.lua | 4 ++
src/luaotfload-database.lua | 6 +--
src/luaotfload-features.lua | 81 +++++++++++++++++----------------
src/luaotfload-init.lua | 2 +
src/luaotfload-loaders.lua | 2 +-
src/luaotfload-main.lua | 96 ++++++++++++++++++++++++++--------------
7 files changed, 157 insertions(+), 112 deletions(-)
diff --git a/src/luaotfload-colors.lua b/src/luaotfload-colors.lua
index 89884b6..a0b80bd 100644
--- a/src/luaotfload-colors.lua
+++ b/src/luaotfload-colors.lua
@@ -19,8 +19,7 @@ explanation: http://tug.org/pipermail/luatex/2013-May/004305.html
--doc]]--
-local log = luaotfload.log
-local logreport = log.report
+local logreport = luaotfload and luaotfload.log.report or print
local nodedirect = node.direct
local newnode = nodedirect.new
@@ -44,10 +43,7 @@ local texsettoks = tex.settoks
local texgettoks = tex.gettoks
local stringformat = string.format
-
-local otffeatures = fonts.constructors.newfeatures("otf")
local identifiers = fonts.hashes.identifiers
-local registerotffeature = otffeatures.register
local add_color_callback --[[ this used to be a global‽ ]]
@@ -101,36 +97,6 @@ local sanitize_color_expression = function (digits)
return sanitized
end
---[[doc--
-``setcolor`` modifies tfmdata.properties.color in place
---doc]]--
-
---- fontobj -> string -> unit
----
---- (where “string” is a rgb value as three octet
---- hexadecimal, with an optional fourth transparency
---- value)
----
-local setcolor = function (tfmdata, value)
- local sanitized = sanitize_color_expression(value)
- local properties = tfmdata.properties
-
- if sanitized then
- properties.color = sanitized
- add_color_callback()
- end
-end
-
-registerotffeature {
- name = "color",
- description = "color",
- initializers = {
- base = setcolor,
- node = setcolor,
- }
-}
-
-
--- something is carried around in ``res``
--- for later use by color_handler() --- but what?
@@ -377,5 +343,47 @@ add_color_callback = function ( )
end
end
+--[[doc--
+``setcolor`` modifies tfmdata.properties.color in place
+--doc]]--
+
+--- fontobj -> string -> unit
+---
+--- (where “string” is a rgb value as three octet
+--- hexadecimal, with an optional fourth transparency
+--- value)
+---
+local setcolor = function (tfmdata, value)
+ local sanitized = sanitize_color_expression(value)
+ local properties = tfmdata.properties
+
+ if sanitized then
+ properties.color = sanitized
+ add_color_callback()
+ end
+end
+
+return {
+ init = function ()
+ logreport = luaotfload.log.report
+ if not fonts then
+ logreport ("log", 0, "color",
+ "OTF mechanisms missing -- did you forget to \z
+ load a font loader?")
+ return false
+ end
+ fonts.handlers.otf.features.register {
+ name = "color",
+ description = "color",
+ initializers = {
+ base = setcolor,
+ node = setcolor,
+ }
+ }
+ return true
+ end
+}
+
+
-- vim:tw=71:sw=4:ts=4:expandtab
diff --git a/src/luaotfload-configuration.lua b/src/luaotfload-configuration.lua
index 263c8ad..86a302e 100644
--- a/src/luaotfload-configuration.lua
+++ b/src/luaotfload-configuration.lua
@@ -919,6 +919,10 @@ return {
reconfigure = reconfigure,
dump = dump,
}
+ if not apply_defaults () then
+ logreport ("log", 0, "load",
+ "Configuration unsuccessful: error loading default settings.")
+ end
return true
end
}
diff --git a/src/luaotfload-database.lua b/src/luaotfload-database.lua
index d9d7594..4af2451 100644
--- a/src/luaotfload-database.lua
+++ b/src/luaotfload-database.lua
@@ -3491,9 +3491,8 @@ return {
--- the font loader namespace is “fonts”, same as in Context
--- we need to put some fallbacks into place for when running
--- as a script
- log = luaotfload.log
- logreport = log.report
- fonts = fonts or { }
+ if not fonts then return false end
+ logreport = luaotfload.log.report
local fonts = fonts
fonts.names = fonts.names or names
fonts.definers = fonts.definers or { }
@@ -3504,6 +3503,7 @@ return {
names.lookups = nil --- contains the lookup cache
for sym, ref in next, export do names[sym] = ref end
+ return true
end
}
diff --git a/src/luaotfload-features.lua b/src/luaotfload-features.lua
index 9b895ce..6fb2114 100644
--- a/src/luaotfload-features.lua
+++ b/src/luaotfload-features.lua
@@ -921,24 +921,13 @@ end
---[[ end included font-ltx.lua ]]
---[[doc--
-This uses the code from luatex-fonts-merged (<- font-otc.lua) instead
-of the removed luaotfload-font-otc.lua.
-
-TODO find out how far we get setting features without these lines,
-relying on luatex-fonts only (it *does* handle features somehow, after
-all).
---doc]]--
-
--- we assume that the other otf stuff is loaded already
+-- We assume that the other otf stuff is loaded already; though there’s
+-- another check below during the initialization phase.
---[[ begin snippet from font-otc.lua ]]
local trace_loading = false trackers.register("otf.loading", function(v) trace_loading = v end)
local report_otf = logs.reporter("fonts","otf loading")
-local otf = fonts.handlers.otf
-local registerotffeature = otf.features.register
-
--[[HH--
In the userdata interface we can not longer tweak the loaded font as
@@ -960,7 +949,7 @@ setmetatableindex(types, function(t,k) t[k] = k return k end) -- "key"
local everywhere = { ["*"] = { ["*"] = true } } -- or: { ["*"] = { "*" } }
local noflags = { }
-local function addfeature(data,feature,specifications)
+local function addfeature (data, feature, specifications)
local descriptions = data.descriptions
local resources = data.resources
local lookups = resources.lookups
@@ -1100,26 +1089,9 @@ local function addfeature(data,feature,specifications)
end
end
-
-otf.enhancers.addfeature = addfeature
-
-local extrafeatures = { }
-
-function otf.addfeature(name,specification)
- extrafeatures[name] = specification
-end
-
-local function enhance(data,filename,raw)
- for feature, specification in next, extrafeatures do
- addfeature(data,feature,specification)
- end
-end
-
-otf.enhancers.register("check extra features",enhance)
-
---[[ end snippet from font-otc.lua ]]
-local tlig = {
+local tlig_specification = {
{
type = "substitution",
features = everywhere,
@@ -1167,9 +1139,6 @@ local tlig = {
},
}
-otf.addfeature ("tlig", tlig)
-otf.addfeature ("trep", { })
-
local anum_arabic = { --- these are the same as in font-otc
[0x0030] = 0x0660,
[0x0031] = 0x0661,
@@ -1228,11 +1197,45 @@ local anum_specification = {
},
}
-otf.addfeature ("anum", anum_specification)
+return {
+ init = function ()
+
+ if not fonts and fonts.handlers then
+ logreport ("log", 0, "color",
+ "OTF mechanisms missing -- did you forget to \z
+ load a font loader?")
+ return false
+ end
+
+ local otf = fonts.handlers.otf
-registerotffeature {
- name = "anum",
- description = "arabic digits",
+ local extrafeatures = {
+ tlig = tlig_specification,
+ trep = { },
+ anum = anum_specification,
+ }
+
+ otf.enhancers.register ("check extra features",
+ function (data,filename, raw)
+ for feature, specification in next, extrafeatures do
+ addfeature (data, feature, specification)
+ end
+ end)
+
+ logreport = luaotfload.log.report
+ if not fonts then
+ logreport ("log", 0, "color",
+ "OTF mechanisms missing -- did you forget to \z
+ load a font loader?")
+ return false
+ end
+
+ otf.features.register {
+ name = "anum",
+ description = "arabic digits",
+ }
+ return true
+ end
}
-- vim:tw=71:sw=4:ts=4:expandtab
diff --git a/src/luaotfload-init.lua b/src/luaotfload-init.lua
index a5e5bec..af71cb2 100644
--- a/src/luaotfload-init.lua
+++ b/src/luaotfload-init.lua
@@ -431,6 +431,8 @@ return {
os.gettimeofday() - starttime)
local n = init_post ()
logreport ("both", 5, "init", "post hook terminated, %d actions performed", n)
+ return true
end
}
+-- vim:tw=79:sw=2:ts=2:expandtab
diff --git a/src/luaotfload-loaders.lua b/src/luaotfload-loaders.lua
index 44216d7..89a9fff 100644
--- a/src/luaotfload-loaders.lua
+++ b/src/luaotfload-loaders.lua
@@ -126,7 +126,7 @@ local install_callbacks = function ()
end
return {
- install = function ()
+ init = function ()
local ret = true
if not install_formats () then
logreport ("log", 0, "loaders", "Error initializing OFM/PF{A,B} loaders.")
diff --git a/src/luaotfload-main.lua b/src/luaotfload-main.lua
index 9e57dbf..815a2f0 100644
--- a/src/luaotfload-main.lua
+++ b/src/luaotfload-main.lua
@@ -13,6 +13,9 @@
--- version 2.4 to 2.5. Thus, the comments are still in TeX (Latex)
--- markup.
+local os = os
+local osgettimeofday = os.gettimeofday
+
local initial_log_level = 0
luaotfload = luaotfload or { }
config = config or { }
@@ -125,70 +128,95 @@ local make_loader_name = function (prefix, name)
return name
end
+local timing_info = {
+ t_load = { },
+ t_init = { },
+}
+
local make_loader = function (prefix)
return function (name)
+ local t_0 = osgettimeofday ()
local modname = make_loader_name (prefix, name)
- return require (modname)
+ local data = require (modname)
+ local t_end = osgettimeofday ()
+ timing_info.t_load [name] = t_end - t_0
+ return data
end
end
-local load_luaotfload_module = make_loader "luaotfload"
------ load_luaotfload_module = make_loader "luatex" --=> for Luatex-Plain
-local load_fontloader_module = make_loader "fontloader"
+local install_loaders = function ()
+ local loaders = { }
+ local loadmodule = make_loader "luaotfload"
+ loaders.luaotfload = loadmodule
+ loaders.fontloader = make_loader "fontloader"
+----loaders.plaintex = make_loader "luatex" --=> for Luatex-Plain
+
+ loaders.initialize = function (name)
+ local tmp = loadmodule (name)
+ local logreport = luaotfload.log.report
+ if type (tmp) == "table" then
+ local init = tmp.init
+ if init and type (init) == "function" then
+ local t_0 = osgettimeofday ()
+ if not init () then
+ logreport ("log", 0, "load",
+ "Failed to load module “%s”.", name)
+ return
+ end
+ local t_end = osgettimeofday ()
+ local d_t = t_end - t_0
+ logreport ("log", 4, "load",
+ "Module “%s” loaded in %d ms.",
+ d_t)
+ timing_info.t_init [name] = d_t
+ end
+ end
+ end
-luaotfload.loaders.luaotfload = load_luaotfload_module
-luaotfload.loaders.fontloader = load_fontloader_module
+ return loaders
+end
---[[doc--
- Now we load the modules written for \identifier{luaotfload}.
+luaotfload.main = function ()
---doc]]--
+ luaotfload.loaders = install_loaders ()
+ local loaders = luaotfload.loaders
+ local loadmodule = loaders.luaotfload
+ local initialize = loaders.initialize
-luaotfload.main = function ()
- local starttime = os.gettimeofday ()
- local init = load_luaotfload_module "init" --- fontloader initialization
- local store = init.early () --- injects the log module too
+ local starttime = osgettimeofday ()
+ local init = loadmodule "init" --- fontloader initialization
+ local store = init.early () --- injects the log module too
local logreport = luaotfload.log.report
- local tmp = load_luaotfload_module "parsers" --- fonts.conf and syntax
- if not tmp.init () then
- logreport ("log", 0, "load", "Failed to install the parsers module.")
- end
-
- local tmp = load_luaotfload_module "configuration" --- configuration options
- if not tmp.init() or not config.actions.apply_defaults () then
- logreport ("log", 0, "load", "Configuration unsuccessful.")
- end
+ initialize "parsers" --- fonts.conf and syntax
+ initialize "configuration" --- configuration options
if not init.main (store) then
logreport ("log", 0, "load", "Main fontloader initialization failed.")
end
- luaotfload.loaders = load_luaotfload_module "loaders" --- Font loading; callbacks
- if not luaotfload.loaders.install () then
- logreport ("log", 0, "load", "Callback and loader initialization failed.")
- end
-
- load_luaotfload_module "database" --- Font management.
- load_luaotfload_module "colors" --- Per-font colors.
+ initialize "loaders" --- Font loading; callbacks
+ initialize "database" --- Font management.
+ initialize "colors" --- Per-font colors.
- luaotfload.resolvers = load_luaotfload_module "resolvers" --- Font lookup
+ luaotfload.resolvers = loadmodule "resolvers" --- Font lookup
luaotfload.resolvers.install ()
if not config.actions.reconfigure () then
logreport ("log", 0, "load", "Post-configuration hooks failed.")
end
- load_luaotfload_module "features" --- font request and feature handling
- load_luaotfload_module "letterspace" --- extra character kerning
- load_luaotfload_module "auxiliary" --- additional high-level functionality
+ initialize "features" --- font request and feature handling
+ loadmodule "letterspace" --- extra character kerning
+ loadmodule "auxiliary" --- additional high-level functionality
luaotfload.aux.start_rewrite_fontname () --- to be migrated to fontspec
logreport ("both", 0, "main",
"initialization completed in %0.3f seconds",
- os.gettimeofday() - starttime)
+ osgettimeofday() - starttime)
+----inspect (timing_info)
end
-- vim:tw=79:sw=4:ts=4:et
--
cgit v1.2.3
From 120c852ccd7a1579310ed855a4d8b1322a1f9d09 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Wed, 28 Oct 2015 06:48:50 +0100
Subject: main: fix module insertion and throw away luatexbase-provided
resources
---
src/luaotfload-main.lua | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)
diff --git a/src/luaotfload-main.lua b/src/luaotfload-main.lua
index 815a2f0..3d68a17 100644
--- a/src/luaotfload-main.lua
+++ b/src/luaotfload-main.lua
@@ -72,16 +72,9 @@ local luatexbase = luatexbase
local require = require
local type = type
-local error, warning, info, log =
+local _error, _warning, _info, _log =
luatexbase.provides_module(luaotfload.module)
-luaotfload.log.tex = {
- error = error,
- warning = warning,
- info = info,
- log = log,
-}
-
--[[doc--
We set the minimum version requirement for \LUATEX to v0.76,
@@ -167,7 +160,7 @@ local install_loaders = function ()
local d_t = t_end - t_0
logreport ("log", 4, "load",
"Module “%s” loaded in %d ms.",
- d_t)
+ name, d_t)
timing_info.t_init [name] = d_t
end
end
--
cgit v1.2.3
From d2e389383564c7f7faf9dd93976e5d548924e1e4 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Wed, 28 Oct 2015 06:54:43 +0100
Subject: [db] fix behavior when starting with no data
---
src/luaotfload-database.lua | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/src/luaotfload-database.lua b/src/luaotfload-database.lua
index 4af2451..1845643 100644
--- a/src/luaotfload-database.lua
+++ b/src/luaotfload-database.lua
@@ -354,7 +354,7 @@ local initialize_namedata = function (formats, created)
status = { }, -- was: status; map abspath -> mapping
mappings = { }, -- TODO: check if still necessary after rewrite
names = { },
--- files = { }, -- created later
+ files = { }, -- created later
meta = {
created = created or now,
formats = formats,
@@ -2236,7 +2236,12 @@ end
--doc]]--
--- string list -> size_t
-local count_removed = function (old)
+local count_removed = function (files)
+ if not files or not files.full then
+ logreport ("log", 4, "db", "Empty file store; no data to work with.")
+ return 0
+ end
+ local old = files.full
logreport ("log", 4, "db", "Checking removed files.")
local nrem = 0
local nold = #old
@@ -3161,7 +3166,7 @@ update_names = function (currentnames, force, dry_run)
--- pass 2: read font files (normal case) or reuse information
--- present in index
- n_rem = count_removed (currentnames.files.full)
+ n_rem = count_removed (currentnames.files)
n_new = retrieve_namedata (font_filenames,
currentnames,
--
cgit v1.2.3
From 811d385a2c903f001ceb719ae1a29ce4586b16b4 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Wed, 28 Oct 2015 06:56:07 +0100
Subject: [loaders] fix call to missing local
---
src/luaotfload-loaders.lua | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/luaotfload-loaders.lua b/src/luaotfload-loaders.lua
index 89a9fff..b644266 100644
--- a/src/luaotfload-loaders.lua
+++ b/src/luaotfload-loaders.lua
@@ -62,7 +62,7 @@ do
--- operate on tfm fonts.
luatexbase.call_callback ("luaotfload.patch_font", fontdata, specification)
else
- call_callback ("luaotfload.patch_font_unsafe", fontdata, specification)
+ luatexbase.call_callback ("luaotfload.patch_font_unsafe", fontdata, specification)
end
return fontdata
end
--
cgit v1.2.3
From 5907d3909cdc508f7804434d4a88d3977530ed64 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Wed, 28 Oct 2015 07:03:11 +0100
Subject: [db] fix access to restructured globals
---
src/luaotfload-database.lua | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/src/luaotfload-database.lua b/src/luaotfload-database.lua
index 1845643..b871954 100644
--- a/src/luaotfload-database.lua
+++ b/src/luaotfload-database.lua
@@ -39,11 +39,6 @@ if not modules then modules = { } end modules ['luaotfload-database'] = {
local lpeg = require "lpeg"
local P, Cc, lpegmatch = lpeg.P, lpeg.Cc, lpeg.match
-local parsers = luaotfload.parsers
-local read_fonts_conf = parsers.read_fonts_conf
-local stripslashes = parsers.stripslashes
-local splitcomma = parsers.splitcomma
-
local log = luaotfload.log
local logreport = log and log.report or print -- overriden later on
local report_status = log.names_status
@@ -1820,8 +1815,6 @@ do
end
end
-fonts.path_normalize = path_normalize
-
local blacklist = { }
local p_blacklist --- prefixes of dirs
@@ -1953,6 +1946,9 @@ do
return
end
+ if splitcomma == nil then
+ splitcomma = luaotfload.parsers and luaotfload.parsers.splitcomma
+ end
if stringsub (formats, 1, 1) == "+" then -- add
formats = lpegmatch (splitcomma, stringsub (formats, 2))
if formats then
@@ -2138,10 +2134,12 @@ local collect_font_filenames_dir = function (dirname, location)
return files
end
-
--- string list -> string list
local filter_out_pwd = function (dirs)
local result = { }
+ if stripslashes == nil then
+ stripslashes = luaotfload.parsers and luaotfload.parsers.stripslashes
+ end
local pwd = path_normalize (lpegmatch (stripslashes,
lfscurrentdir ()))
for i = 1, #dirs do
@@ -2223,7 +2221,10 @@ local function get_os_dirs ()
"/usr/local/etc/fonts/fonts.conf",
"/etc/fonts/fonts.conf",
}
- local os_dirs = read_fonts_conf(fonts_conves, find_files)
+ if not luaotfload.parsers then
+ logreport ("log", 0, "db", "Fatal: no fonts.conf parser.")
+ end
+ local os_dirs = luaotfload.parsers.read_fonts_conf(fonts_conves, find_files)
return os_dirs
end
return {}
@@ -3488,7 +3489,6 @@ local export = {
show_cache = show_cache,
find_closest = find_closest,
-- for testing purpose
- read_fonts_conf = read_fonts_conf,
}
return {
--
cgit v1.2.3
From a29b5562c526a9079f09ea022db5fa4951c18c58 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Wed, 28 Oct 2015 07:09:22 +0100
Subject: [tool] fix interfacing with database
---
src/luaotfload-tool.lua | 53 ++++++++++++++++++++++++-------------------------
1 file changed, 26 insertions(+), 27 deletions(-)
diff --git a/src/luaotfload-tool.lua b/src/luaotfload-tool.lua
index e240e4c..fdc6c62 100755
--- a/src/luaotfload-tool.lua
+++ b/src/luaotfload-tool.lua
@@ -143,15 +143,14 @@ require"luaotfload-basics-gen.lua"
texio.write, texio.write_nl = backup.write, backup.write_nl
utilities = backup.utilities
+fonts = { names = { } } -- for db; normally provided by the fontloaders
+
require "luaotfload-log.lua" --- this populates the luaotfload.log.* namespace
require "luaotfload-parsers" --- fonts.conf, configuration, and request syntax
require "luaotfload-configuration" --- configuration file handling
require "luaotfload-database"
require "alt_getopt"
-local names = fonts.names
-local sanitize_fontname = names.sanitize_fontname
-
local log = luaotfload.log
local report = log.report
@@ -272,7 +271,7 @@ local about = [[
local version_msg = function ( )
local out = function (...) texiowrite_nl (stringformat (...)) end
local uname = os.uname ()
- local meta = names.getmetadata ()
+ local meta = fonts.names.getmetadata ()
out (about, luaotfload.self)
out ("%s version: %q", luaotfload.self, version)
out ("Revision: %q", config.luaotfload.status.notes.revision)
@@ -673,7 +672,7 @@ subfont_by_name = function (lst, askedname, n)
local font = lst[n]
if font then
- if sanitize_fontname (font.fullname) == askedname then
+ if fonts.names.sanitize_fontname (font.fullname) == askedname then
return font
end
return subfont_by_name (lst, askedname, n+1)
@@ -690,10 +689,10 @@ The font info knows two levels of detail:
--doc]]--
local show_font_info = function (basename, askedname, detail, warnings)
- local filenames = names.data().files
+ local filenames = fonts.names.data().files
local index = filenames.base[basename]
local fullname = filenames.full[index]
- askedname = sanitize_fontname (askedname)
+ askedname = fonts.names.sanitize_fontname (askedname)
if not fullname then -- texmf
fullname = resolvers.findfile(basename)
end
@@ -797,17 +796,17 @@ actions.help = function (job)
end
actions.blacklist = function (job)
- names.read_blacklist()
+ fonts.names.read_blacklist()
local n = 0
- for n, entry in next, tablesortedkeys(names.blacklist) do
+ for n, entry in next, tablesortedkeys(fonts.names.blacklist) do
iowrite (stringformat("(%d %s)\n", n, entry))
end
return true, false
end
actions.generate = function (job)
- local _ = names.update (fontnames, job.force_reload, job.dry_run)
- local namedata = names.data ()
+ local _ = fonts.names.update (fontnames, job.force_reload, job.dry_run)
+ local namedata = fonts.names.data ()
if namedata then
report ("info", 2, "db", "Fonts in the database: %i", #namedata.mappings)
return true, true
@@ -895,7 +894,7 @@ local bisect_start = function ()
end
report ("info", 2, "bisect",
"Starting bisection of font database %q.", bisect_status_file)
- local n = names.count_font_files ()
+ local n = fonts.names.count_font_files ()
local pivot = mathfloor (n / 2)
local data = { { 1, n, pivot } }
report ("info", 0, "bisect", "Initializing pivot to %d.", pivot)
@@ -946,7 +945,7 @@ local bisect_terminate = function (nsteps, culprit)
report ("info", 1, "bisect",
"Bisection completed after %d steps.", nsteps)
report ("info", 0, "bisect",
- "Bad file: %s.", names.nth_font_filename (culprit))
+ "Bad file: %s.", fonts.names.nth_font_filename (culprit))
report ("info", 0, "bisect",
"Run with --bisect=stop to finish bisection.")
return true, false
@@ -959,7 +958,7 @@ end
--doc]]--
local list_remainder = function (lo, hi)
- local fonts = names.font_slice (lo, hi)
+ local fonts = fonts.names.font_slice (lo, hi)
report ("info", 0, "bisect", "%d fonts left.", hi - lo + 1)
for i = 1, #fonts do
report ("info", 1, "bisect", " · %2d: %s", lo, fonts[i])
@@ -1110,9 +1109,9 @@ actions.bisect = function (job)
end
actions.flush = function (job)
- local success = names.flush_lookup_cache()
+ local success = fonts.names.flush_lookup_cache()
if success then
- local success = names.save_lookups()
+ local success = fonts.names.save_lookups()
if success then
report ("info", 2, "cache", "Lookup cache emptied")
return true, true
@@ -1122,9 +1121,9 @@ actions.flush = function (job)
end
local cache_directives = {
- ["purge"] = names.purge_cache,
- ["erase"] = names.erase_cache,
- ["show"] = names.show_cache,
+ ["purge"] = fonts.names.purge_cache,
+ ["erase"] = fonts.names.erase_cache,
+ ["show"] = fonts.names.show_cache,
}
actions.cache = function (job)
@@ -1154,7 +1153,7 @@ actions.query = function (job)
features = { },
}
- tmpspec = names.handle_request (tmpspec)
+ tmpspec = fonts.names.handle_request (tmpspec)
if not tmpspec.size then
tmpspec.size = 655360 --- assume 10pt
@@ -1165,13 +1164,13 @@ actions.query = function (job)
if tmpspec.lookup == "name"
or tmpspec.lookup == "anon" --- not *exactly* as resolvers.anon
then
- foundname, subfont = names.resolve_name (tmpspec)
+ foundname, subfont = fonts.names.resolve_name (tmpspec)
if foundname then
- foundname, _, success = names.font_file_lookup (foundname)
+ foundname, _, success = fonts.names.font_file_lookup (foundname)
end
elseif tmpspec.lookup == "file" then
foundname, _, success =
- names.font_file_lookup (tmpspec.name)
+ fonts.names.font_file_lookup (tmpspec.name)
end
if success then
@@ -1196,7 +1195,7 @@ actions.query = function (job)
if job.fuzzy == true then
report (false, 0, "resolve",
"Looking for close matches, this may take a while ...")
- local _success = names.find_closest(query, job.fuzzy_limit)
+ local _success = fonts.names.find_closest(query, job.fuzzy_limit)
end
end
return true, true
@@ -1274,7 +1273,7 @@ local splitcomma = luaotfload.parsers.splitcomma
actions.list = function (job)
local criterion = job.criterion
local asked_fields = job.asked_fields
- local name_index = names.data ()
+ local name_index = fonts.names.data ()
if asked_fields then
asked_fields = lpegmatch(splitcomma, asked_fields)
@@ -1286,7 +1285,7 @@ actions.list = function (job)
end
if not name_index then
- name_index = names.load()
+ name_index = fonts.names.load()
end
local mappings = name_index.mappings
@@ -1528,7 +1527,7 @@ local process_cmdline = function ( ) -- unit -> jobspec
elseif v == "D" then
result.dry_run = true
elseif v == "p" then
- names.set_location_precedence {
+ fonts.names.set_location_precedence {
"local", "texmf", "system"
}
elseif v == "b" then
--
cgit v1.2.3
From 3b2349244c00df1393f3aedb910e7e458a52a7ea Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Wed, 28 Oct 2015 07:17:04 +0100
Subject: [tool] defer import of logger
---
src/luaotfload-tool.lua | 207 ++++++++++++++++++++++++++----------------------
1 file changed, 114 insertions(+), 93 deletions(-)
diff --git a/src/luaotfload-tool.lua b/src/luaotfload-tool.lua
index fdc6c62..6b84a6d 100755
--- a/src/luaotfload-tool.lua
+++ b/src/luaotfload-tool.lua
@@ -151,8 +151,12 @@ require "luaotfload-configuration" --- configuration file handling
require "luaotfload-database"
require "alt_getopt"
-local log = luaotfload.log
-local report = log.report
+local logreport
+
+local init_modules = function ()
+ logreport = luaotfload.log.report
+end
+
local help_messages = {
["luaotfload-tool"] = [[
@@ -702,9 +706,9 @@ local show_font_info = function (basename, askedname, detail, warnings)
if nfonts > 0 then -- true type collection
local subfont
if askedname then
- report (true, 1, "resolve",
- [[%s is part of the font collection %s]],
- askedname, basename)
+ logreport (true, 1, "resolve",
+ [[%s is part of the font collection %s]],
+ askedname, basename)
subfont = subfont_by_name(shortinfo, askedname)
end
if subfont then
@@ -713,11 +717,11 @@ local show_font_info = function (basename, askedname, detail, warnings)
show_full_info(fullname, subfont, warnings)
end
else -- list all subfonts
- report (true, 1, "resolve",
- [[%s is a font collection]], basename)
+ logreport (true, 1, "resolve",
+ [[%s is a font collection]], basename)
for subfont = 1, nfonts do
- report (true, 1, "resolve",
- [[Showing info for font no. %d]], n)
+ logreport (true, 1, "resolve",
+ [[Showing info for font no. %d]], n)
show_info_items(shortinfo[subfont])
if detail == true then
show_full_info(fullname, subfont, warnings)
@@ -731,7 +735,7 @@ local show_font_info = function (basename, askedname, detail, warnings)
end
end
else
- report (true, 1, "resolve", "Font %s not found", filename)
+ logreport (true, 1, "resolve", "Font %s not found", filename)
end
end
@@ -759,9 +763,9 @@ local actions = { } --- (jobspec -> (bool * bool)) list
actions.loglevel = function (job)
local lvl = job.log_level
if lvl then
- log.set_loglevel(lvl)
- report ("info", 3, "util", "Setting the log level to %d.", lvl)
- report ("log", 2, "util", "Lua=%q", _VERSION)
+ luaotfload.log.set_loglevel(lvl)
+ logreport ("info", 3, "util", "Setting the log level to %d.", lvl)
+ logreport ("log", 2, "util", "Lua=%q", _VERSION)
end
return true, true
end
@@ -808,7 +812,9 @@ actions.generate = function (job)
local _ = fonts.names.update (fontnames, job.force_reload, job.dry_run)
local namedata = fonts.names.data ()
if namedata then
- report ("info", 2, "db", "Fonts in the database: %i", #namedata.mappings)
+ logreport ("info", 2, "db",
+ "Fonts in the database: %i",
+ #namedata.mappings)
return true, true
end
return false, false
@@ -844,12 +850,14 @@ local write_bisect_status = function (data)
osdate ("%Y-%m-d %H:%M:%S", os.time ()),
payload)
if status and iosavedata (bisect_status_file, status) then
- report ("info", 4, "bisect",
- "Bisection state written to %s.", bisect_status_file)
+ logreport ("info", 4, "bisect",
+ "Bisection state written to %s.",
+ bisect_status_file)
return true
end
- report ("info", 0, "bisect",
- "Failed to write bisection state to %s.", bisect_status_file)
+ logreport ("info", 0, "bisect",
+ "Failed to write bisection state to %s.",
+ bisect_status_file)
return false
end
@@ -861,16 +869,22 @@ end
--- unit -> state list
local read_bisect_status = function ()
- report ("info", 4, "bisect", "Testing for status file: %q.", bisect_status_file)
+ logreport ("info", 4, "bisect",
+ "Testing for status file: %q.",
+ bisect_status_file)
if not lfsisfile (bisect_status_file) then
- report ("info", 2, "bisect", "No such file: %q.", bisect_status_file)
- report ("info", 0, "bisect", "Not in bisect mode.")
+ logreport ("info", 2, "bisect",
+ "No such file: %q.", bisect_status_file)
+ logreport ("info", 0, "bisect",
+ "Not in bisect mode.")
return false
end
- report ("info", 4, "bisect", "Reading status file: %q.", bisect_status_file)
+ logreport ("info", 4, "bisect",
+ "Reading status file: %q.", bisect_status_file)
local success, status = pcall (dofile, bisect_status_file)
if not success then
- report ("info", 0, "bisect", "Could not read status file.")
+ logreport ("info", 0, "bisect",
+ "Could not read status file.")
return false
end
return status
@@ -885,19 +899,21 @@ end
local bisect_start = function ()
if lfsisfile (bisect_status_file) then
- report ("info", 0, "bisect",
- "Bisect session in progress.",
- bisect_status_file)
- report ("info", 0, "bisect",
- "Use --bisect=stop to erase it before starting over.")
+ logreport ("info", 0, "bisect",
+ "Bisect session in progress.",
+ bisect_status_file)
+ logreport ("info", 0, "bisect",
+ "Use --bisect=stop to erase it before starting over.")
return false, false
end
- report ("info", 2, "bisect",
- "Starting bisection of font database %q.", bisect_status_file)
+ logreport ("info", 2, "bisect",
+ "Starting bisection of font database %q.",
+ bisect_status_file)
local n = fonts.names.count_font_files ()
local pivot = mathfloor (n / 2)
local data = { { 1, n, pivot } }
- report ("info", 0, "bisect", "Initializing pivot to %d.", pivot)
+ logreport ("info", 0, "bisect",
+ "Initializing pivot to %d.", pivot)
if write_bisect_status (data) then
return true, false
end
@@ -911,21 +927,23 @@ end
--doc]]--
local bisect_stop = function ()
- report ("info", 3, "bisect", "Erasing bisection state at %s.", bisect_status_file)
+ logreport ("info", 3, "bisect",
+ "Erasing bisection state at %s.",
+ bisect_status_file)
if lfsisfile (bisect_status_file) then
local success, msg = os.remove (bisect_status_file)
if not success then
- report ("info", 2, "bisect",
- "Failed to erase file %s (%s).",
- bisect_status_file, msg)
+ logreport ("info", 2, "bisect",
+ "Failed to erase file %s (%s).",
+ bisect_status_file, msg)
end
end
if lfsisdir (bisect_status_path) then
local success, msg = os.remove (bisect_status_path)
if not success then
- report ("info", 2, "bisect",
- "Failed to erase directory %s (%s).",
- bisect_status_path, msg)
+ logreport ("info", 2, "bisect",
+ "Failed to erase directory %s (%s).",
+ bisect_status_path, msg)
end
end
if lfsisfile (bisect_status_file) then
@@ -942,12 +960,12 @@ end
--doc]]--
local bisect_terminate = function (nsteps, culprit)
- report ("info", 1, "bisect",
- "Bisection completed after %d steps.", nsteps)
- report ("info", 0, "bisect",
- "Bad file: %s.", fonts.names.nth_font_filename (culprit))
- report ("info", 0, "bisect",
- "Run with --bisect=stop to finish bisection.")
+ logreport ("info", 1, "bisect",
+ "Bisection completed after %d steps.", nsteps)
+ logreport ("info", 0, "bisect",
+ "Bad file: %s.", fonts.names.nth_font_filename (culprit))
+ logreport ("info", 0, "bisect",
+ "Run with --bisect=stop to finish bisection.")
return true, false
end
@@ -959,9 +977,9 @@ end
local list_remainder = function (lo, hi)
local fonts = fonts.names.font_slice (lo, hi)
- report ("info", 0, "bisect", "%d fonts left.", hi - lo + 1)
+ logreport ("info", 0, "bisect", "%d fonts left.", hi - lo + 1)
for i = 1, #fonts do
- report ("info", 1, "bisect", " · %2d: %s", lo, fonts[i])
+ logreport ("info", 1, "bisect", " · %2d: %s", lo, fonts[i])
lo = lo + 1
end
end
@@ -994,8 +1012,9 @@ local bisect_set = function (outcome)
local lo, hi, pivot = unpack (previous)
- report ("info", 3, "bisect", "Previous step %d: lo=%d, hi=%d, pivot=%d.",
- nsteps, lo, hi, pivot)
+ logreport ("info", 3, "bisect",
+ "Previous step %d: lo=%d, hi=%d, pivot=%d.",
+ nsteps, lo, hi, pivot)
if outcome == "bad" then
hi = pivot
@@ -1006,9 +1025,9 @@ local bisect_set = function (outcome)
return bisect_terminate (nsteps, lo)
end
pivot = mathfloor ((lo + hi) / 2)
- report ("info", 0, "bisect",
- "Continuing with the lower segment: lo=%d, hi=%d, pivot=%d.",
- lo, hi, pivot)
+ logreport ("info", 0, "bisect",
+ "Continuing with the lower segment: lo=%d, hi=%d, pivot=%d.",
+ lo, hi, pivot)
elseif outcome == "good" then
lo = pivot + 1
if lo >= hi then --- complete
@@ -1018,11 +1037,12 @@ local bisect_set = function (outcome)
return bisect_terminate (nsteps, lo)
end
pivot = mathfloor ((lo + hi) / 2)
- report ("info", 0, "bisect",
- "Continuing with the upper segment: lo=%d, hi=%d, pivot=%d.",
- lo, hi, pivot)
+ logreport ("info", 0, "bisect",
+ "Continuing with the upper segment: lo=%d, hi=%d, pivot=%d.",
+ lo, hi, pivot)
else -- can’t happen
- report ("info", 0, "bisect", "What the hell?", lo, hi, pivot)
+ logreport ("info", 0, "bisect",
+ "What the hell?", lo, hi, pivot)
return false, false
end
@@ -1049,13 +1069,13 @@ local bisect_status = function ()
if nsteps > 1 then
for i = nsteps - 1, 1, -1 do
local step = status[i]
- report ("info", 2, "bisect", "Step %d: lo=%d, hi=%d, pivot=%d.",
- i, unpack (step))
+ logreport ("info", 2, "bisect", "Step %d: lo=%d, hi=%d, pivot=%d.",
+ i, unpack (step))
end
end
local current = status[nsteps]
- report ("info", 0, "bisect", "Step %d: lo=%d, hi=%d, pivot=%d.",
- nsteps, unpack (current))
+ logreport ("info", 0, "bisect", "Step %d: lo=%d, hi=%d, pivot=%d.",
+ nsteps, unpack (current))
return true, false
end
@@ -1081,10 +1101,10 @@ local bisect_run = function ()
current = status[nsteps - 1]
end
local lo, hi, pivot = unpack (current)
- report ("info", 3, "bisect", "Previous step %d: lo=%d, hi=%d, pivot=%d.",
- nsteps, lo, hi, pivot)
- report ("info", 1, "bisect", "Step %d: Testing fonts from %d to %d.",
- currentstep, lo, pivot)
+ logreport ("info", 3, "bisect", "Previous step %d: lo=%d, hi=%d, pivot=%d.",
+ nsteps, lo, hi, pivot)
+ logreport ("info", 1, "bisect", "Step %d: Testing fonts from %d to %d.",
+ currentstep, lo, pivot)
config.luaotfload.misc.bisect = { lo, pivot }
return true, true
end
@@ -1102,7 +1122,7 @@ actions.bisect = function (job)
local mode = job.bisect
local runner = bisect_modes[mode]
if not runner then
- report ("info", 0, "bisect", "Unknown directive %q.", mode)
+ logreport ("info", 0, "bisect", "Unknown directive %q.", mode)
return false, false
end
return runner (job)
@@ -1113,7 +1133,7 @@ actions.flush = function (job)
if success then
local success = fonts.names.save_lookups()
if success then
- report ("info", 2, "cache", "Lookup cache emptied")
+ logreport ("info", 2, "cache", "Lookup cache emptied")
return true, true
end
end
@@ -1129,8 +1149,8 @@ local cache_directives = {
actions.cache = function (job)
local directive = cache_directives[job.cache]
if not directive or type(directive) ~= "function" then
- report ("info", 2, "cache",
- "Invalid font cache directive %s.", job.cache)
+ logreport ("info", 2, "cache",
+ "Invalid font cache directive %s.", job.cache)
return false, false
end
if directive() then
@@ -1174,27 +1194,27 @@ actions.query = function (job)
end
if success then
- report (false, 0, "resolve", "Font %q found!", query)
+ logreport (false, 0, "resolve", "Font %q found!", query)
if subfont then
- report (false, 0, "resolve",
- "Resolved file name %q, subfont nr. %q",
- foundname, subfont)
+ logreport (false, 0, "resolve",
+ "Resolved file name %q, subfont nr. %q",
+ foundname, subfont)
else
- report (false, 0, "resolve",
- "Resolved file name %q", foundname)
+ logreport (false, 0, "resolve",
+ "Resolved file name %q", foundname)
end
if job.show_info then
show_font_info (foundname, query, job.full_info, job.warnings)
iowrite "\n"
end
else
- report (false, 0, "resolve", "Cannot find %q in index.", query)
- report (false, 0, "resolve",
- "Hint: use the --fuzzy option to display suggestions.",
- query)
+ logreport (false, 0, "resolve", "Cannot find %q in index.", query)
+ logreport (false, 0, "resolve",
+ "Hint: use the --fuzzy option to display suggestions.",
+ query)
if job.fuzzy == true then
- report (false, 0, "resolve",
- "Looking for close matches, this may take a while ...")
+ logreport (false, 0, "resolve",
+ "Looking for close matches, this may take a while ...")
local _success = fonts.names.find_closest(query, job.fuzzy_limit)
end
end
@@ -1268,14 +1288,13 @@ set_primary_field = function (fields, addme, acc, n)
return acc
end
-local splitcomma = luaotfload.parsers.splitcomma
-
actions.list = function (job)
local criterion = job.criterion
local asked_fields = job.asked_fields
local name_index = fonts.names.data ()
if asked_fields then
+ local splitcomma = luaotfload.parsers.splitcomma
asked_fields = lpegmatch(splitcomma, asked_fields)
end
@@ -1292,7 +1311,7 @@ actions.list = function (job)
local nmappings = #mappings
if criterion == "*" then
- report (false, 1, "list", "All %d entries", nmappings)
+ logreport (false, 1, "list", "All %d entries", nmappings)
for i=1, nmappings do
local entry = mappings[i]
local fields = get_fields(entry, asked_fields)
@@ -1307,12 +1326,12 @@ actions.list = function (job)
criterion = criterion[1]
asked_fields = set_primary_field(asked_fields, criterion)
- report (false, 1, "list", "By %s", criterion)
+ logreport (false, 1, "list", "By %s", criterion)
--- firstly, build a list of fonts to operate on
local targets = { }
if asked_value then --- only those whose value matches
- report (false, 2, "list", "Restricting to value %s", asked_value)
+ logreport (false, 2, "list", "Restricting to value %s", asked_value)
for i=1, nmappings do
local entry = mappings[i]
if entry[criterion]
@@ -1357,7 +1376,7 @@ actions.list = function (job)
end
end
local ntargets = #targets
- report (false, 2, "list", "%d entries", ntargets)
+ logreport (false, 2, "list", "%d entries", ntargets)
--- now, output the collection
for i=1, ntargets do
@@ -1494,7 +1513,7 @@ local process_cmdline = function ( ) -- unit -> jobspec
elseif v == "log" then
local str = optarg[n]
if str then
- finalizers = log.set_logout(str, finalizers)
+ finalizers = luaotfload.log.set_logout(str, finalizers)
end
elseif v == "find" then
action_pending["query"] = true
@@ -1588,6 +1607,8 @@ local process_cmdline = function ( ) -- unit -> jobspec
end
local main = function ( ) -- unit -> int
+ if init_modules () == false then return -42 end
+
local retval = 0
local job = process_cmdline()
@@ -1598,23 +1619,23 @@ local main = function ( ) -- unit -> int
local actionname = action_sequence[i]
local exit = false
if action_pending[actionname] then
- report ("log", 3, "util", "Preparing for task", "%s", actionname)
+ logreport ("log", 3, "util", "Preparing for task", "%s", actionname)
local action = actions[actionname]
local success, continue = action(job)
if not success then
- report (false, 0, "util",
- "Failed to execute task.", "%s", actionname)
+ logreport (false, 0, "util",
+ "Failed to execute task.", "%s", actionname)
retval = -1
exit = true
elseif not continue then
- report (false, 3, "util",
- "Task completed, exiting.", "%s", actionname)
+ logreport (false, 3, "util",
+ "Task completed, exiting.", "%s", actionname)
exit = true
else
- report (false, 3, "util",
- "Task completed successfully.", "%s", actionname)
+ logreport (false, 3, "util",
+ "Task completed successfully.", "%s", actionname)
end
end
if exit then break end
--
cgit v1.2.3
From c810fcae82effa6c73b7da19e0b94d735be9f767 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Wed, 28 Oct 2015 07:31:42 +0100
Subject: [tool] adapt to current initialization
---
src/luaotfload-tool.lua | 51 +++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 47 insertions(+), 4 deletions(-)
diff --git a/src/luaotfload-tool.lua b/src/luaotfload-tool.lua
index 6b84a6d..181bd5c 100755
--- a/src/luaotfload-tool.lua
+++ b/src/luaotfload-tool.lua
@@ -145,16 +145,59 @@ utilities = backup.utilities
fonts = { names = { } } -- for db; normally provided by the fontloaders
-require "luaotfload-log.lua" --- this populates the luaotfload.log.* namespace
-require "luaotfload-parsers" --- fonts.conf, configuration, and request syntax
-require "luaotfload-configuration" --- configuration file handling
-require "luaotfload-database"
+local require_init = { }
+
+local loadmodule = function (name)
+ local v = require ("luaotfload-" .. name)
+ if v then
+ local mod = { }
+ local tv = type (v)
+ if tv == "table" then
+ mod.name = name
+ mod.init = v.init
+ require_init [#require_init + 1] = mod
+ elseif tv == "function" then
+ mod.name = name
+ mod.init = v
+ require_init [#require_init + 1] = mod
+ end
+ end
+end
+
require "alt_getopt"
+loadmodule "log.lua" --- this populates the luaotfload.log.* namespace
+loadmodule "parsers" --- fonts.conf, configuration, and request syntax
+loadmodule "configuration" --- configuration file handling
+loadmodule "database"
+
local logreport
local init_modules = function ()
+ --- NB we don’t command the logger at this point.
+ local todo = #require_init
+ local ret = true
+ for i = 1, todo do
+ local mod = require_init[i]
+ local name = mod.name
+ local init = mod.init
+ if type (init) ~= "function" then
+ error ("luaotfload broken; module "
+ .. name .. " missing initializers!")
+ end
+ local v = mod.init ()
+ if v == true then
+ --- evaluated well
+ elseif type (v) == "table" then
+ luaotfload[name] = v
+ else
+ error ("luaotfload broken; initialization of module "
+ .. name .. " returned " .. tostring (v) .. ".")
+ return false
+ end
+ end
logreport = luaotfload.log.report
+ return ret
end
--
cgit v1.2.3
From d7a36a33d8d57a5aec9232364cf0bd307523281c Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Wed, 28 Oct 2015 07:52:00 +0100
Subject: [*] update news
---
NEWS | 1 +
1 file changed, 1 insertion(+)
diff --git a/NEWS b/NEWS
index a1ffb1e..bf2441d 100644
--- a/NEWS
+++ b/NEWS
@@ -14,6 +14,7 @@ Change History
* Move remaining functionality from ``luaotfload-override`` into
initialization
* Write names index if fonts were removed
+ * Separate module loading from initialization
2014/07/13, luaotfload v2.5
* Remove legacy code.
--
cgit v1.2.3
From 4f053696e1813fde4bd6cebbb77ff2a1e1f6800b Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Thu, 29 Oct 2015 07:14:40 +0100
Subject: [fontloader] sync with Context as of 2015-10-29
---
src/fontloader/misc/fontloader-basics-nod.lua | 3 +
src/fontloader/misc/fontloader-font-afm.lua | 18 +-
src/fontloader/misc/fontloader-font-con.lua | 114 +-
src/fontloader/misc/fontloader-font-def.lua | 6 +-
src/fontloader/misc/fontloader-font-map.lua | 473 ++--
src/fontloader/misc/fontloader-font-otb.lua | 10 +-
src/fontloader/misc/fontloader-font-otf.lua | 583 ++++-
src/fontloader/misc/fontloader-font-otp.lua | 5 +-
src/fontloader/misc/fontloader-font-tfm.lua | 1 +
src/fontloader/misc/fontloader-fonts-cbk.lua | 33 +-
src/fontloader/misc/fontloader-fonts-inj.lua | 375 +--
src/fontloader/misc/fontloader-fonts-otn.lua | 2125 +++++++++++-----
src/fontloader/misc/fontloader-fonts.lua | 18 +-
src/fontloader/misc/fontloader-l-lpeg.lua | 2 +-
src/fontloader/misc/fontloader-l-lua.lua | 34 +-
src/fontloader/misc/fontloader-l-string.lua | 7 +-
src/fontloader/misc/fontloader-l-table.lua | 2 +-
src/fontloader/misc/fontloader-mplib.lua | 114 +-
src/fontloader/misc/fontloader-mplib.tex | 21 +-
src/fontloader/misc/fontloader-plain.tex | 25 +-
src/fontloader/misc/fontloader-test.tex | 26 +-
src/fontloader/misc/fontloader-util-str.lua | 13 +-
src/fontloader/runtime/fontloader-reference.lua | 2947 ++++++++++++++++-------
23 files changed, 4803 insertions(+), 2152 deletions(-)
diff --git a/src/fontloader/misc/fontloader-basics-nod.lua b/src/fontloader/misc/fontloader-basics-nod.lua
index 1ec2895..39400a3 100644
--- a/src/fontloader/misc/fontloader-basics-nod.lua
+++ b/src/fontloader/misc/fontloader-basics-nod.lua
@@ -56,6 +56,9 @@ local whatcodes = { } for k,v in next, node.whatsits() do whatcodes[string.gs
local glyphcodes = { [0] = "character", "glyph", "ligature", "ghost", "left", "right" }
local disccodes = { [0] = "discretionary", "explicit", "automatic", "regular", "first", "second" }
+for i=0,#glyphcodes do glyphcodes[glyphcodes[i]] = i end
+for i=0,#disccodes do disccodes [disccodes [i]] = i end
+
nodes.nodecodes = nodecodes
nodes.whatcodes = whatcodes
nodes.whatsitcodes = whatcodes
diff --git a/src/fontloader/misc/fontloader-font-afm.lua b/src/fontloader/misc/fontloader-font-afm.lua
index a96c668..329639b 100644
--- a/src/fontloader/misc/fontloader-font-afm.lua
+++ b/src/fontloader/misc/fontloader-font-afm.lua
@@ -152,14 +152,14 @@ end
local keys = { }
-function keys.FontName (data,line) data.metadata.fontname = strip (line) -- get rid of spaces
- data.metadata.fullname = strip (line) end
-function keys.ItalicAngle (data,line) data.metadata.italicangle = tonumber (line) end
-function keys.IsFixedPitch(data,line) data.metadata.isfixedpitch = toboolean(line,true) end
-function keys.CharWidth (data,line) data.metadata.charwidth = tonumber (line) end
-function keys.XHeight (data,line) data.metadata.xheight = tonumber (line) end
-function keys.Descender (data,line) data.metadata.descender = tonumber (line) end
-function keys.Ascender (data,line) data.metadata.ascender = tonumber (line) end
+function keys.FontName (data,line) data.metadata.fontname = strip (line) -- get rid of spaces
+ data.metadata.fullname = strip (line) end
+function keys.ItalicAngle (data,line) data.metadata.italicangle = tonumber (line) end
+function keys.IsFixedPitch(data,line) data.metadata.monospaced = toboolean(line,true) end
+function keys.CharWidth (data,line) data.metadata.charwidth = tonumber (line) end
+function keys.XHeight (data,line) data.metadata.xheight = tonumber (line) end
+function keys.Descender (data,line) data.metadata.descender = tonumber (line) end
+function keys.Ascender (data,line) data.metadata.ascender = tonumber (line) end
function keys.Comment (data,line)
-- Comment DesignSize 12 (pts)
-- Comment TFM designsize: 12 (in points)
@@ -640,7 +640,7 @@ local function copytotfm(data)
local spacer = "space"
local spaceunits = 500
--
- local monospaced = metadata.isfixedpitch
+ local monospaced = metadata.monospaced
local charwidth = metadata.charwidth
local italicangle = metadata.italicangle
local charxheight = metadata.xheight and metadata.xheight > 0 and metadata.xheight
diff --git a/src/fontloader/misc/fontloader-font-con.lua b/src/fontloader/misc/fontloader-font-con.lua
index 72fbb5c..383a403 100644
--- a/src/fontloader/misc/fontloader-font-con.lua
+++ b/src/fontloader/misc/fontloader-font-con.lua
@@ -191,10 +191,9 @@ in the process; numbers are of course copies. Here 65536 equals 1pt. (Due to
excessive memory usage in CJK fonts, we no longer pass the boundingbox.)
--ldx]]--
--- The scaler is only used for otf and afm and virtual fonts. If
--- a virtual font has italic correction make sure to set the
--- hasitalics flag. Some more flags will be added in
--- the future.
+-- The scaler is only used for otf and afm and virtual fonts. If a virtual font has italic
+-- correction make sure to set the hasitalics flag. Some more flags will be added in the
+-- future.
--[[ldx--
The reason why the scaler was originally split, is that for a while we experimented
@@ -426,6 +425,7 @@ function constructors.scale(tfmdata,specification)
local vdelta = delta
--
target.designsize = parameters.designsize -- not really needed so it might become obsolete
+ target.units = units
target.units_per_em = units -- just a trigger for the backend
--
local direction = properties.direction or tfmdata.direction or 0 -- pointless, as we don't use omf fonts at all
@@ -562,26 +562,27 @@ function constructors.scale(tfmdata,specification)
target.mathparameters = nil -- nop
end
--
- local italickey = "italic"
- local useitalics = true -- something context
- --
- -- some context specific trickery (this will move to a plugin)
+ -- Here we support some context specific trickery (this might move to a plugin). During the
+ -- transition to opentype the engine had troubles with italics so we had some additional code
+ -- for fixing that. In node mode (text) we don't care much if italics gets passed because
+ -- the engine does nothign with them then.
--
if hasmath then
- -- the latest luatex can deal with it itself so we now disable this
- -- mechanism here
- --
- -- if properties.mathitalics then
- -- italickey = "italic_correction"
- -- if trace_defining then
- -- report_defining("math italics disabled for font %a, fullname %a, filename %a",name,fullname,filename)
- -- end
- -- end
- autoitalicamount = false -- new
- elseif properties.textitalics then
- italickey = "italic_correction"
- useitalics = false
- if properties.delaytextitalics then
+ local mathitalics = properties.mathitalics
+ if mathitalics == false then
+ if trace_defining then
+ report_defining("%s italics %s for font %a, fullname %a, filename %a","math",hasitalics and "ignored" or "disabled",name,fullname,filename)
+ end
+ hasitalics = false
+ autoitalicamount = false
+ end
+ else
+ local textitalics = properties.textitalics
+ if textitalics == false then
+ if trace_defining then
+ report_defining("%s italics %s for font %a, fullname %a, filename %a","text",hasitalics and "ignored" or "disabled",name,fullname,filename)
+ end
+ hasitalics = false
autoitalicamount = false
end
end
@@ -590,8 +591,7 @@ function constructors.scale(tfmdata,specification)
--
if trace_defining then
report_defining("defining tfm, name %a, fullname %a, filename %a, hscale %a, vscale %a, math %a, italics %a",
- name,fullname,filename,hdelta,vdelta,
- hasmath and "enabled" or "disabled",useitalics and "enabled" or "disabled")
+ name,fullname,filename,hdelta,vdelta,hasmath and "enabled" or "disabled",hasitalics and "enabled" or "disabled")
end
--
constructors.beforecopyingcharacters(target,tfmdata)
@@ -606,15 +606,15 @@ function constructors.scale(tfmdata,specification)
local c = changed[unicode]
if c then
description = descriptions[c] or descriptions[unicode] or character
- character = characters[c] or character
- index = description.index or c
+ character = characters[c] or character
+ index = description.index or c
else
description = descriptions[unicode] or character
- index = description.index or unicode
+ index = description.index or unicode
end
else
description = descriptions[unicode] or character
- index = description.index or unicode
+ index = description.index or unicode
end
local width = description.width
local height = description.height
@@ -699,23 +699,6 @@ function constructors.scale(tfmdata,specification)
end
end
--
- if autoitalicamount then
- local vi = description.italic
- if not vi then
- local vi = description.boundingbox[3] - description.width + autoitalicamount
- if vi > 0 then -- < 0 indicates no overshoot or a very small auto italic
- chr[italickey] = vi*hdelta
- end
- elseif vi ~= 0 then
- chr[italickey] = vi*hdelta
- end
- elseif hasitalics then
- local vi = description.italic
- if vi and vi ~= 0 then
- chr[italickey] = vi*hdelta
- end
- end
- -- to be tested
if hasmath then
-- todo, just operate on descriptions.math
local vn = character.next
@@ -754,7 +737,7 @@ function constructors.scale(tfmdata,specification)
end
end
end
- local va = character.top_accent
+ local va = character.accent
if va then
chr.top_accent = vdelta*va
end
@@ -777,6 +760,27 @@ function constructors.scale(tfmdata,specification)
chr.mathkern = kerns -- singular -> should be patched in luatex !
end
end
+ if hasitalics then
+ local vi = character.italic
+ if vi and vi ~= 0 then
+ chr.italic = vi*hdelta
+ end
+ end
+ elseif autoitalicamount then -- itlc feature
+ local vi = description.italic
+ if not vi then
+ local vi = description.boundingbox[3] - description.width + autoitalicamount
+ if vi > 0 then -- < 0 indicates no overshoot or a very small auto italic
+ chr.italic = vi*hdelta
+ end
+ elseif vi ~= 0 then
+ chr.italic = vi*hdelta
+ end
+ elseif hasitalics then -- unlikely
+ local vi = character.italic
+ if vi and vi ~= 0 then
+ chr.italic = vi*hdelta
+ end
end
if haskerns then
local vk = character.kerns
@@ -843,6 +847,8 @@ function constructors.scale(tfmdata,specification)
targetcharacters[unicode] = chr
end
--
+ properties.setitalics = hasitalics -- for postprocessing
+ --
constructors.aftercopyingcharacters(target,tfmdata)
--
constructors.trytosharefont(target,tfmdata)
@@ -895,12 +901,21 @@ function constructors.finalize(tfmdata)
parameters.slantfactor = tfmdata.slant or 0
end
--
- if not parameters.designsize then
- parameters.designsize = tfmdata.designsize or (factors.pt * 10)
+ local designsize = parameters.designsize
+ if designsize then
+ parameters.minsize = tfmdata.minsize or designsize
+ parameters.maxsize = tfmdata.maxsize or designsize
+ else
+ designsize = factors.pt * 10
+ parameters.designsize = designsize
+ parameters.minsize = designsize
+ parameters.maxsize = designsize
end
+ parameters.minsize = tfmdata.minsize or parameters.designsize
+ parameters.maxsize = tfmdata.maxsize or parameters.designsize
--
if not parameters.units then
- parameters.units = tfmdata.units_per_em or 1000
+ parameters.units = tfmdata.units or tfmdata.units_per_em or 1000
end
--
if not tfmdata.descriptions then
@@ -976,6 +991,7 @@ function constructors.finalize(tfmdata)
tfmdata.auto_protrude = nil
tfmdata.extend = nil
tfmdata.slant = nil
+ tfmdata.units = nil
tfmdata.units_per_em = nil
--
tfmdata.cache = nil
diff --git a/src/fontloader/misc/fontloader-font-def.lua b/src/fontloader/misc/fontloader-font-def.lua
index fdded3c..add42ee 100644
--- a/src/fontloader/misc/fontloader-font-def.lua
+++ b/src/fontloader/misc/fontloader-font-def.lua
@@ -183,10 +183,11 @@ end
function resolvers.name(specification)
local resolve = fonts.names.resolve
if resolve then
- local resolved, sub = resolve(specification.name,specification.sub,specification) -- we pass specification for overloaded versions
+ local resolved, sub, subindex = resolve(specification.name,specification.sub,specification) -- we pass specification for overloaded versions
if resolved then
specification.resolved = resolved
specification.sub = sub
+ specification.subindex = subindex
local suffix = lower(suffixonly(resolved))
if fonts.formats[suffix] then
specification.forced = suffix
@@ -204,10 +205,11 @@ end
function resolvers.spec(specification)
local resolvespec = fonts.names.resolvespec
if resolvespec then
- local resolved, sub = resolvespec(specification.name,specification.sub,specification) -- we pass specification for overloaded versions
+ local resolved, sub, subindex = resolvespec(specification.name,specification.sub,specification) -- we pass specification for overloaded versions
if resolved then
specification.resolved = resolved
specification.sub = sub
+ specification.subindex = subindex
specification.forced = lower(suffixonly(resolved))
specification.forcedname = resolved
specification.name = removesuffix(resolved)
diff --git a/src/fontloader/misc/fontloader-font-map.lua b/src/fontloader/misc/fontloader-font-map.lua
index 69474ba..b645d9a 100644
--- a/src/fontloader/misc/fontloader-font-map.lua
+++ b/src/fontloader/misc/fontloader-font-map.lua
@@ -31,25 +31,27 @@ of obsolete. Some code may move to runtime or auxiliary modules.
The name to unciode related code will stay of course.
--ldx]]--
-local function loadlumtable(filename) -- will move to font goodies
- local lumname = file.replacesuffix(file.basename(filename),"lum")
- local lumfile = resolvers.findfile(lumname,"map") or ""
- if lumfile ~= "" and lfs.isfile(lumfile) then
- if trace_loading or trace_mapping then
- report_fonts("loading map table %a",lumfile)
- end
- lumunic = dofile(lumfile)
- return lumunic, lumfile
- end
-end
+-- local function loadlumtable(filename) -- will move to font goodies
+-- local lumname = file.replacesuffix(file.basename(filename),"lum")
+-- local lumfile = resolvers.findfile(lumname,"map") or ""
+-- if lumfile ~= "" and lfs.isfile(lumfile) then
+-- if trace_loading or trace_mapping then
+-- report_fonts("loading map table %a",lumfile)
+-- end
+-- lumunic = dofile(lumfile)
+-- return lumunic, lumfile
+-- end
+-- end
local hex = R("AF","09")
-local hexfour = (hex*hex*hex*hex) / function(s) return tonumber(s,16) end
-local hexsix = (hex*hex*hex*hex*hex*hex) / function(s) return tonumber(s,16) end
+----- hexfour = (hex*hex*hex*hex) / function(s) return tonumber(s,16) end
+----- hexsix = (hex*hex*hex*hex*hex*hex) / function(s) return tonumber(s,16) end
+local hexfour = (hex*hex*hex^-2) / function(s) return tonumber(s,16) end
+local hexsix = (hex*hex*hex^-4) / function(s) return tonumber(s,16) end
local dec = (R("09")^1) / tonumber
local period = P(".")
-local unicode = P("uni") * (hexfour * (period + P(-1)) * Cc(false) + Ct(hexfour^1) * Cc(true))
-local ucode = P("u") * (hexsix * (period + P(-1)) * Cc(false) + Ct(hexsix ^1) * Cc(true))
+local unicode = (P("uni") + P("UNI")) * (hexfour * (period + P(-1)) * Cc(false) + Ct(hexfour^1) * Cc(true)) -- base planes
+local ucode = (P("u") + P("U") ) * (hexsix * (period + P(-1)) * Cc(false) + Ct(hexsix ^1) * Cc(true)) -- extended
local index = P("index") * dec * Cc(false)
local parser = unicode + ucode + index
@@ -168,7 +170,6 @@ end
-- return s
-- end
-mappings.loadlumtable = loadlumtable
mappings.makenameparser = makenameparser
mappings.tounicode = tounicode
mappings.tounicode16 = tounicode16
@@ -179,13 +180,13 @@ local ligseparator = P("_")
local varseparator = P(".")
local namesplitter = Ct(C((1 - ligseparator - varseparator)^1) * (ligseparator * C((1 - ligseparator - varseparator)^1))^0)
+-- maybe: ff fi fl ffi ffl => f_f f_i f_l f_f_i f_f_l
+
-- local function test(name)
-- local split = lpegmatch(namesplitter,name)
-- print(string.formatters["%s: [% t]"](name,split))
-- end
--- maybe: ff fi fl ffi ffl => f_f f_i f_l f_f_i f_f_l
-
-- test("i.f_")
-- test("this")
-- test("this.that")
@@ -221,332 +222,184 @@ end
mappings.overloads = overloads
-function mappings.addtounicode(data,filename)
- local resources = data.resources
- local properties = data.properties
- local descriptions = data.descriptions
- local unicodes = resources.unicodes
- local lookuptypes = resources.lookuptypes
+function mappings.addtounicode(data,filename,checklookups)
+ local resources = data.resources
+ local unicodes = resources.unicodes
if not unicodes then
return
end
+ local properties = data.properties
+ local descriptions = data.descriptions
-- we need to move this code
unicodes['space'] = unicodes['space'] or 32
unicodes['hyphen'] = unicodes['hyphen'] or 45
unicodes['zwj'] = unicodes['zwj'] or 0x200D
unicodes['zwnj'] = unicodes['zwnj'] or 0x200C
- local private = fonts.constructors.privateoffset
- local unicodevector = fonts.encodings.agl.unicodes -- loaded runtime in context
- ----- namevector = fonts.encodings.agl.names -- loaded runtime in context
- local missing = { }
- local lumunic, uparser, oparser
- local cidinfo, cidnames, cidcodes, usedmap
- --
- cidinfo = properties.cidinfo
- usedmap = cidinfo and fonts.cid.getmap(cidinfo)
--
+ local private = fonts.constructors and fonts.constructors.privateoffset or 0xF0000 -- 0x10FFFF
+ local unicodevector = fonts.encodings.agl.unicodes or { } -- loaded runtime in context
+ local contextvector = fonts.encodings.agl.ctxcodes or { } -- loaded runtime in context
+ local missing = { }
+ local nofmissing = 0
+ local oparser = nil
+ local cidnames = nil
+ local cidcodes = nil
+ local cidinfo = properties.cidinfo
+ local usedmap = cidinfo and fonts.cid.getmap(cidinfo)
+ local uparser = makenameparser() -- hm, every time?
if usedmap then
- oparser = usedmap and makenameparser(cidinfo.ordering)
- cidnames = usedmap.names
- cidcodes = usedmap.unicodes
+ oparser = usedmap and makenameparser(cidinfo.ordering)
+ cidnames = usedmap.names
+ cidcodes = usedmap.unicodes
end
- uparser = makenameparser()
- local ns, nl = 0, 0
+ local ns = 0
+ local nl = 0
+ --
for unic, glyph in next, descriptions do
- local index = glyph.index
- local name = glyph.name
- local r = overloads[name]
- if r then
- -- get rid of weird ligatures
- -- glyph.name = r.name
- glyph.unicode = r.unicode
- elseif unic == -1 or unic >= private or (unic >= 0xE000 and unic <= 0xF8FF) or unic == 0xFFFE or unic == 0xFFFF then
- local unicode = lumunic and lumunic[name] or unicodevector[name]
- if unicode then
- glyph.unicode = unicode
- ns = ns + 1
- end
- -- cidmap heuristics, beware, there is no guarantee for a match unless
- -- the chain resolves
- if (not unicode) and usedmap then
- local foundindex = lpegmatch(oparser,name)
- if foundindex then
- unicode = cidcodes[foundindex] -- name to number
- if unicode then
- glyph.unicode = unicode
- ns = ns + 1
- else
- local reference = cidnames[foundindex] -- number to name
- if reference then
- local foundindex = lpegmatch(oparser,reference)
- if foundindex then
- unicode = cidcodes[foundindex]
- if unicode then
- glyph.unicode = unicode
- ns = ns + 1
+ local name = glyph.name
+ if name then
+ local index = glyph.index
+ local r = overloads[name]
+ if r then
+ -- get rid of weird ligatures
+ -- glyph.name = r.name
+ glyph.unicode = r.unicode
+ elseif not unic or unic == -1 or unic >= private or (unic >= 0xE000 and unic <= 0xF8FF) or unic == 0xFFFE or unic == 0xFFFF then
+ local unicode = unicodevector[name] or contextvector[name]
+ if unicode then
+ glyph.unicode = unicode
+ ns = ns + 1
+ end
+ -- cidmap heuristics, beware, there is no guarantee for a match unless
+ -- the chain resolves
+ if (not unicode) and usedmap then
+ local foundindex = lpegmatch(oparser,name)
+ if foundindex then
+ unicode = cidcodes[foundindex] -- name to number
+ if unicode then
+ glyph.unicode = unicode
+ ns = ns + 1
+ else
+ local reference = cidnames[foundindex] -- number to name
+ if reference then
+ local foundindex = lpegmatch(oparser,reference)
+ if foundindex then
+ unicode = cidcodes[foundindex]
+ if unicode then
+ glyph.unicode = unicode
+ ns = ns + 1
+ end
end
- end
- if not unicode or unicode == "" then
- local foundcodes, multiple = lpegmatch(uparser,reference)
- if foundcodes then
- glyph.unicode = foundcodes
- if multiple then
- nl = nl + 1
- unicode = true
- else
- ns = ns + 1
- unicode = foundcodes
+ if not unicode or unicode == "" then
+ local foundcodes, multiple = lpegmatch(uparser,reference)
+ if foundcodes then
+ glyph.unicode = foundcodes
+ if multiple then
+ nl = nl + 1
+ unicode = true
+ else
+ ns = ns + 1
+ unicode = foundcodes
+ end
end
end
end
end
end
end
- end
- -- a.whatever or a_b_c.whatever or a_b_c (no numbers) a.b_
- --
- -- It is not trivial to find a solution that suits all fonts. We tried several alternatives
- -- and this one seems to work reasonable also with fonts that use less standardized naming
- -- schemes. The extra private test is tested by KE and seems to work okay with non-typical
- -- fonts as well.
- --
- -- 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
- local t, n = { }, 0
- unicode = true
- for l=1,nsplit do
- local base = split[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
+ -- a.whatever or a_b_c.whatever or a_b_c (no numbers) a.b_
+ --
+ -- It is not trivial to find a solution that suits all fonts. We tried several alternatives
+ -- and this one seems to work reasonable also with fonts that use less standardized naming
+ -- schemes. The extra private test is tested by KE and seems to work okay with non-typical
+ -- fonts as well.
+ --
+ if not unicode or unicode == "" then
+ local split = lpegmatch(namesplitter,name)
+ local nsplit = split and #split or 0 -- add if
+ if nsplit == 0 then
+ -- skip
+ elseif nsplit == 1 then
+ local base = split[1]
+ local u = unicodes[base] or unicodevector[base] or contextvector[name]
+ if not u then
+ -- skip
+ elseif type(u) == "table" then
+ -- unlikely
+ if u[1] < private then
+ unicode = u
+ glyph.unicode = unicode
+ end
+ elseif u < private then
+ unicode = u
+ glyph.unicode = unicode
end
- 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
- end
- -- last resort (we might need to catch private here as well)
- if not unicode or unicode == "" then
- local foundcodes, multiple = lpegmatch(uparser,name)
- if foundcodes then
- glyph.unicode = foundcodes
- if multiple then
- nl = nl + 1
- unicode = true
- else
- ns = ns + 1
- unicode = foundcodes
- end
- end
- end
- -- check using substitutes and alternates
- local r = overloads[unicode]
- if r then
- unicode = r.unicode
- glyph.unicode = unicode
- end
- --
- if not unicode then
- missing[name] = true
- end
- end
- end
- if next(missing) then
- local guess = { }
- -- helper
- local function check(gname,code,unicode)
- local description = descriptions[code]
- -- no need to add a self reference
- local variant = description.name
- if variant == gname then
- return
- end
- -- the variant already has a unicode (normally that resultrs in a default tounicode to self)
- local unic = unicodes[variant]
- if unic == -1 or unic >= private or (unic >= 0xE000 and unic <= 0xF8FF) or unic == 0xFFFE or unic == 0xFFFF then
- -- no default mapping and therefore maybe no tounicode yet
- else
- return
- end
- -- the variant already has a tounicode
- if descriptions[code].unicode then
- return
- end
- -- add to the list
- local g = guess[variant]
- -- local r = overloads[unicode]
- -- if r then
- -- unicode = r.unicode
- -- end
- if g then
- g[gname] = unicode
- else
- guess[variant] = { [gname] = unicode }
- end
- end
- --
- for unicode, description in next, descriptions do
- local slookups = description.slookups
- if slookups then
- local gname = description.name
- for tag, data in next, slookups do
- local lookuptype = lookuptypes[tag]
- if lookuptype == "alternate" then
- for i=1,#data do
- check(gname,data[i],unicode)
- end
- elseif lookuptype == "substitution" then
- check(gname,data,unicode)
- end
- end
- end
- local mlookups = description.mlookups
- if mlookups then
- local gname = description.name
- for tag, list in next, mlookups do
- local lookuptype = lookuptypes[tag]
- if lookuptype == "alternate" then
- for i=1,#list do
- local data = list[i]
- for i=1,#data do
- check(gname,data[i],unicode)
+ local t, n = { }, 0
+ for l=1,nsplit do
+ local base = split[l]
+ local u = unicodes[base] or unicodevector[base] or contextvector[name]
+ if not u then
+ break
+ elseif type(u) == "table" then
+ if u[1] >= private then
+ break
+ end
+ n = n + 1
+ t[n] = u[1]
+ else
+ if u >= private then
+ break
+ end
+ n = n + 1
+ t[n] = u
end
end
- elseif lookuptype == "substitution" then
- for i=1,#list do
- check(gname,list[i],unicode)
+ if n > 0 then
+ if n == 1 then
+ unicode = t[1]
+ else
+ unicode = t
+ end
+ glyph.unicode = unicode
end
end
+ nl = nl + 1
end
- end
- end
- -- resolve references
- local done = true
- while done do
- done = false
- for k, v in next, guess do
- if type(v) ~= "number" then
- for kk, vv in next, v do
- if vv == -1 or vv >= private or (vv >= 0xE000 and vv <= 0xF8FF) or vv == 0xFFFE or vv == 0xFFFF then
- local uu = guess[kk]
- if type(uu) == "number" then
- guess[k] = uu
- done = true
- end
+ -- last resort (we might need to catch private here as well)
+ if not unicode or unicode == "" then
+ local foundcodes, multiple = lpegmatch(uparser,name)
+ if foundcodes then
+ glyph.unicode = foundcodes
+ if multiple then
+ nl = nl + 1
+ unicode = true
else
- guess[k] = vv
- done = true
+ ns = ns + 1
+ unicode = foundcodes
end
end
end
- end
- end
- -- wrap up
- local orphans = 0
- local guessed = 0
- for k, v in next, guess do
- if type(v) == "number" then
- descriptions[unicodes[k]].unicode = descriptions[v].unicode or v -- can also be a table
- guessed = guessed + 1
- else
- local t = nil
- local l = lower(k)
- local u = unicodes[l]
- if not u then
- orphans = orphans + 1
- elseif u == -1 or u >= private or (u >= 0xE000 and u <= 0xF8FF) or u == 0xFFFE or u == 0xFFFF then
- local unicode = descriptions[u].unicode
- if unicode then
- descriptions[unicodes[k]].unicode = unicode
- guessed = guessed + 1
- else
- orphans = orphans + 1
- end
- else
- orphans = orphans + 1
+ -- check using substitutes and alternates
+ local r = overloads[unicode]
+ if r then
+ unicode = r.unicode
+ glyph.unicode = unicode
+ end
+ --
+ if not unicode then
+ missing[unic] = true
+ nofmissing = nofmissing + 1
end
end
+ else
+ -- no name
end
- if trace_loading and orphans > 0 or guessed > 0 then
- report_fonts("%s glyphs with no related unicode, %s guessed, %s orphans",guessed+orphans,guessed,orphans)
- end
end
+ if type(checklookups) == "function" then
+ checklookups(data,missing,nofmissing)
+ end
+ -- todo: go lowercase
if trace_mapping then
for unic, glyph in table.sortedhash(descriptions) do
local name = glyph.name
diff --git a/src/fontloader/misc/fontloader-font-otb.lua b/src/fontloader/misc/fontloader-font-otb.lua
index 4e955a1..c9f5d4a 100644
--- a/src/fontloader/misc/fontloader-font-otb.lua
+++ b/src/fontloader/misc/fontloader-font-otb.lua
@@ -321,14 +321,14 @@ local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplis
for unicode, character in next, characters do
local description = descriptions[unicode]
- local lookups = description.slookups
+ local lookups = description.slookups
if lookups then
for l=1,#lookuplist do
local lookupname = lookuplist[l]
local lookupdata = lookups[lookupname]
if lookupdata then
local lookuptype = lookuptypes[lookupname]
- local action = actions[lookuptype]
+ local action = actions[lookuptype]
if action then
action(lookupdata,lookuptags,lookupname,description,unicode)
end
@@ -342,7 +342,7 @@ local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplis
local lookuplist = lookups[lookupname]
if lookuplist then
local lookuptype = lookuptypes[lookupname]
- local action = actions[lookuptype]
+ local action = actions[lookuptype]
if action then
for i=1,#lookuplist do
action(lookuplist[i],lookuptags,lookupname,description,unicode)
@@ -614,8 +614,8 @@ local function featuresinitializer(tfmdata,value)
local collectlookups = otf.collectlookups
local rawdata = tfmdata.shared.rawdata
local properties = tfmdata.properties
- local script = properties.script
- local language = properties.language
+ local script = properties.script -- or "dflt" -- can be nil
+ local language = properties.language -- or "dflt" -- can be nil
local basesubstitutions = rawdata.resources.features.gsub
local basepositionings = rawdata.resources.features.gpos
--
diff --git a/src/fontloader/misc/fontloader-font-otf.lua b/src/fontloader/misc/fontloader-font-otf.lua
index e7a97c6..0ca1e98 100644
--- a/src/fontloader/misc/fontloader-font-otf.lua
+++ b/src/fontloader/misc/fontloader-font-otf.lua
@@ -12,15 +12,19 @@ if not modules then modules = { } end modules ['font-otf'] = {
-- to_table -> totable
-- ascent descent
+-- to be checked: combinations like:
+--
+-- current="ABCD" with [A]=nothing, [BC]=ligature, [D]=single (applied to result of BC so funny index)
+--
+-- unlikely but possible
+
-- more checking against low level calls of functions
local utfbyte = utf.byte
-local format, gmatch, gsub, find, match, lower, strip = string.format, string.gmatch, string.gsub, string.find, string.match, string.lower, string.strip
+local gmatch, gsub, find, match, lower, strip = string.gmatch, string.gsub, string.find, string.match, string.lower, string.strip
local type, next, tonumber, tostring = type, next, tonumber, tostring
local abs = math.abs
-local insert = table.insert
-local lpegmatch = lpeg.match
-local reversed, concat, remove, sortedkeys = table.reversed, table.concat, table.remove, table.sortedkeys
+local reversed, concat, insert, remove, sortedkeys = table.reversed, table.concat, table.insert, table.remove, table.sortedkeys
local ioflush = io.flush
local fastcopy, tohash, derivetable = table.fastcopy, table.tohash, table.derive
local formatters = string.formatters
@@ -54,7 +58,7 @@ local otf = fonts.handlers.otf
otf.glists = { "gsub", "gpos" }
-otf.version = 2.812 -- beware: also sync font-mis.lua
+otf.version = 2.819 -- beware: also sync font-mis.lua and in mtx-fonts
otf.cache = containers.define("fonts", "otf", otf.version, true)
local hashes = fonts.hashes
@@ -283,13 +287,17 @@ local ordered_enhancers = {
"check glyphs",
"check metadata",
- "check extra features", -- after metadata
+-- "check extra features", -- after metadata
"prepare tounicode",
"check encoding", -- moved
"add duplicates",
+ "expand lookups", -- a temp hack awaiting the lua loader
+
+-- "check extra features", -- after metadata and duplicates
+
"cleanup tables",
"compact lookups",
@@ -386,6 +394,7 @@ function otf.load(filename,sub,featurefile) -- second argument (format) is gone
if featurefile then
name = name .. "@" .. file.removesuffix(file.basename(featurefile))
end
+ -- or: sub = tonumber(sub)
if sub == "" then
sub = false
end
@@ -442,6 +451,7 @@ function otf.load(filename,sub,featurefile) -- second argument (format) is gone
end
end
if reload then
+ starttiming("fontloader")
report_otf("loading %a, hash %a",filename,hash)
local fontdata, messages
if sub then
@@ -476,6 +486,7 @@ function otf.load(filename,sub,featurefile) -- second argument (format) is gone
data = {
size = size,
time = time,
+ subfont = sub,
format = otf_format(filename),
featuredata = featurefiles,
resources = {
@@ -512,7 +523,6 @@ function otf.load(filename,sub,featurefile) -- second argument (format) is gone
tounicodetable = Ct(splitter),
},
}
- starttiming(data)
report_otf("file size: %s", size)
enhancers.apply(data,filename,fontdata)
local packtime = { }
@@ -529,10 +539,10 @@ function otf.load(filename,sub,featurefile) -- second argument (format) is gone
if cleanup > 1 then
collectgarbage("collect")
end
- stoptiming(data)
+ stoptiming("fontloader")
if elapsedtime then -- not in generic
- report_otf("preprocessing and caching time %s, packtime %s",
- elapsedtime(data),packdata and elapsedtime(packtime) or 0)
+ report_otf("loading, optimizing, packing and caching time %s, pack time %s",
+ elapsedtime("fontloader"),packdata and elapsedtime(packtime) or 0)
end
close_font(fontdata) -- free memory
if cleanup > 3 then
@@ -543,6 +553,7 @@ function otf.load(filename,sub,featurefile) -- second argument (format) is gone
collectgarbage("collect")
end
else
+ stoptiming("fontloader")
data = nil
report_otf("loading failed due to read error")
end
@@ -589,6 +600,7 @@ function otf.load(filename,sub,featurefile) -- second argument (format) is gone
applyruntimefixes(filename,data)
end
enhance("add dimensions",data,filename,nil,false)
+enhance("check extra features",data,filename)
if trace_sequences then
showfeatureorder(data,filename)
end
@@ -697,7 +709,7 @@ local function somecopy(old) -- fast one
end
end
--- not setting hasitalics and class (when nil) during table cronstruction can save some mem
+-- not setting hasitalics and class (when nil) during table construction can save some mem
actions["prepare glyphs"] = function(data,filename,raw)
local tableversion = tonumber(raw.table_version) or 0
@@ -780,7 +792,7 @@ actions["prepare glyphs"] = function(data,filename,raw)
end
if not unicode or unicode == -1 then -- or unicode >= criterium then
if not name then
- name = format("u%06X.ctx",private)
+ name = formatters["u%06X.ctx"](private)
end
unicode = private
unicodes[name] = private
@@ -803,7 +815,7 @@ actions["prepare glyphs"] = function(data,filename,raw)
-- end
-- end
if not name then
- name = format("u%06X.ctx",unicode)
+ name = formatters["u%06X.ctx"](unicode)
end
unicodes[name] = unicode
nofunicodes = nofunicodes + 1
@@ -819,35 +831,35 @@ actions["prepare glyphs"] = function(data,filename,raw)
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
+ 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
end
else
@@ -916,7 +928,7 @@ end
end
indices[index] = unicode
-- if not name then
- -- name = format("u%06X",unicode) -- u%06X.ctx
+ -- name = formatters["u%06X"](unicode) -- u%06X.ctx
-- end
descriptions[unicode] = {
-- width = glyph.width,
@@ -1089,7 +1101,7 @@ actions["add duplicates"] = function(data,filename,raw)
end
if u > 0 then -- and
local duplicate = table.copy(description) -- else packing problem
- duplicate.comment = format("copy of U+%05X", unicode)
+ duplicate.comment = formatters["copy of %U"](unicode)
descriptions[u] = duplicate
-- validduplicates[#validduplicates+1] = u
if trace_loading then
@@ -1107,16 +1119,16 @@ end
-- boundingbox: split into ht/dp takes more memory (larger tables and less sharing)
actions["analyze glyphs"] = function(data,filename,raw) -- maybe integrate this in the previous
- local descriptions = data.descriptions
- local resources = data.resources
- local metadata = data.metadata
- local properties = data.properties
- local hasitalics = false
- local widths = { }
- local marks = { } -- always present (saves checking)
+ local descriptions = data.descriptions
+ local resources = data.resources
+ local metadata = data.metadata
+ local properties = data.properties
+ local hasitalics = false
+ local widths = { }
+ local marks = { } -- always present (saves checking)
for unicode, description in next, descriptions do
- local glyph = description.glyph
- local italic = glyph.italic_correction
+ local glyph = description.glyph
+ local italic = glyph.italic_correction -- only in a math font (we also have vert/horiz)
if not italic then
-- skip
elseif italic == 0 then
@@ -1185,7 +1197,8 @@ end
actions["reorganize features"] = function(data,filename,raw) -- combine with other
local features = { }
data.resources.features = features
- for k, what in next, otf.glists do
+ for k=1,#otf.glists do
+ local what = otf.glists[k]
local dw = raw[what]
if dw then
local f = { }
@@ -1254,6 +1267,140 @@ actions["reorganize anchor classes"] = function(data,filename,raw)
end
end
+-- local function checklookups(data,missing,nofmissing)
+-- local resources = data.resources
+-- local unicodes = resources.unicodes
+-- local lookuptypes = resources.lookuptypes
+-- if not unicodes or not lookuptypes then
+-- return
+-- elseif nofmissing <= 0 then
+-- return
+-- end
+-- local descriptions = data.descriptions
+-- local private = fonts.constructors and fonts.constructors.privateoffset or 0xF0000 -- 0x10FFFF
+-- --
+-- local ns, nl = 0, 0
+
+-- local guess = { }
+-- -- helper
+-- local function check(gname,code,unicode)
+-- local description = descriptions[code]
+-- -- no need to add a self reference
+-- local variant = description.name
+-- if variant == gname then
+-- return
+-- end
+-- -- the variant already has a unicode (normally that results in a default tounicode to self)
+-- local unic = unicodes[variant]
+-- if unic == -1 or unic >= private or (unic >= 0xE000 and unic <= 0xF8FF) or unic == 0xFFFE or unic == 0xFFFF then
+-- -- no default mapping and therefore maybe no tounicode yet
+-- else
+-- return
+-- end
+-- -- the variant already has a tounicode
+-- if descriptions[code].unicode then
+-- return
+-- end
+-- -- add to the list
+-- local g = guess[variant]
+-- -- local r = overloads[unicode]
+-- -- if r then
+-- -- unicode = r.unicode
+-- -- end
+-- if g then
+-- g[gname] = unicode
+-- else
+-- guess[variant] = { [gname] = unicode }
+-- end
+-- end
+-- --
+-- for unicode, description in next, descriptions do
+-- local slookups = description.slookups
+-- if slookups then
+-- local gname = description.name
+-- for tag, data in next, slookups do
+-- local lookuptype = lookuptypes[tag]
+-- if lookuptype == "alternate" then
+-- for i=1,#data do
+-- check(gname,data[i],unicode)
+-- end
+-- elseif lookuptype == "substitution" then
+-- check(gname,data,unicode)
+-- end
+-- end
+-- end
+-- local mlookups = description.mlookups
+-- if mlookups then
+-- local gname = description.name
+-- for tag, list in next, mlookups do
+-- local lookuptype = lookuptypes[tag]
+-- if lookuptype == "alternate" then
+-- for i=1,#list do
+-- local data = list[i]
+-- for i=1,#data do
+-- check(gname,data[i],unicode)
+-- end
+-- end
+-- elseif lookuptype == "substitution" then
+-- for i=1,#list do
+-- check(gname,list[i],unicode)
+-- end
+-- end
+-- end
+-- end
+-- end
+-- -- resolve references
+-- local done = true
+-- while done do
+-- done = false
+-- for k, v in next, guess do
+-- if type(v) ~= "number" then
+-- for kk, vv in next, v do
+-- if vv == -1 or vv >= private or (vv >= 0xE000 and vv <= 0xF8FF) or vv == 0xFFFE or vv == 0xFFFF then
+-- local uu = guess[kk]
+-- if type(uu) == "number" then
+-- guess[k] = uu
+-- done = true
+-- end
+-- else
+-- guess[k] = vv
+-- done = true
+-- end
+-- end
+-- end
+-- end
+-- end
+-- -- wrap up
+-- local orphans = 0
+-- local guessed = 0
+-- for k, v in next, guess do
+-- if type(v) == "number" then
+-- descriptions[unicodes[k]].unicode = descriptions[v].unicode or v -- can also be a table
+-- guessed = guessed + 1
+-- else
+-- local t = nil
+-- local l = lower(k)
+-- local u = unicodes[l]
+-- if not u then
+-- orphans = orphans + 1
+-- elseif u == -1 or u >= private or (u >= 0xE000 and u <= 0xF8FF) or u == 0xFFFE or u == 0xFFFF then
+-- local unicode = descriptions[u].unicode
+-- if unicode then
+-- descriptions[unicodes[k]].unicode = unicode
+-- guessed = guessed + 1
+-- else
+-- orphans = orphans + 1
+-- end
+-- else
+-- orphans = orphans + 1
+-- end
+-- end
+-- end
+-- if trace_loading and orphans > 0 or guessed > 0 then
+-- report_otf("%s glyphs with no related unicode, %s guessed, %s orphans",guessed+orphans,guessed,orphans)
+-- end
+-- end
+
actions["prepare tounicode"] = function(data,filename,raw)
fonts.mappings.addtounicode(data,filename)
end
@@ -1288,8 +1435,9 @@ actions["reorganize subtables"] = function(data,filename,raw)
local lookups = { }
local chainedfeatures = { }
resources.sequences = sequences
- resources.lookups = lookups
- for _, what in next, otf.glists do
+ resources.lookups = lookups -- we also have lookups in data itself
+ for k=1,#otf.glists do
+ local what = otf.glists[k]
local dw = raw[what]
if dw then
for k=1,#dw do
@@ -1375,12 +1523,6 @@ actions["reorganize subtables"] = function(data,filename,raw)
end
end
--- test this:
---
--- for _, what in next, otf.glists do
--- raw[what] = nil
--- end
-
actions["prepare lookups"] = function(data,filename,raw)
local lookups = raw.lookups
if lookups then
@@ -1494,12 +1636,16 @@ end
actions["reorganize lookups"] = function(data,filename,raw) -- we could check for "" and n == 0
-- we prefer the before lookups in a normal order
if data.lookups then
- local splitter = data.helpers.tounicodetable
- local t_u_cache = { }
- local s_u_cache = t_u_cache -- string keys
- local t_h_cache = { }
- local s_h_cache = t_h_cache -- table keys (so we could use one cache)
- local r_u_cache = { } -- maybe shared
+ local helpers = data.helpers
+ local duplicates = data.resources.duplicates
+ local splitter = helpers.tounicodetable
+ local t_u_cache = { }
+ local s_u_cache = t_u_cache -- string keys
+ local t_h_cache = { }
+ local s_h_cache = t_h_cache -- table keys (so we could use one cache)
+ local r_u_cache = { } -- maybe shared
+ helpers.matchcache = t_h_cache -- so that we can add duplicates
+ --
for _, lookup in next, data.lookups do
local rules = lookup.rules
if rules then
@@ -1653,6 +1799,50 @@ actions["reorganize lookups"] = function(data,filename,raw) -- we could check fo
end
end
+actions["expand lookups"] = function(data,filename,raw) -- we could check for "" and n == 0
+ if data.lookups then
+ local cache = data.helpers.matchcache
+ if cache then
+ local duplicates = data.resources.duplicates
+ for key, hash in next, cache do
+ local done = nil
+ for key in next, hash do
+ local unicode = duplicates[key]
+ if not unicode then
+ -- no duplicate
+ elseif type(unicode) == "table" then
+ -- multiple duplicates
+ for i=1,#unicode do
+ local u = unicode[i]
+ if hash[u] then
+ -- already in set
+ elseif done then
+ done[u] = key
+ else
+ done = { [u] = key }
+ end
+ end
+ else
+ -- one duplicate
+ if hash[unicode] then
+ -- already in set
+ elseif done then
+ done[unicode] = key
+ else
+ done = { [unicode] = key }
+ end
+ end
+ end
+ if done then
+ for u in next, done do
+ hash[u] = true
+ end
+ end
+ end
+ end
+ end
+end
+
local function check_variants(unicode,the_variants,splitter,unicodes)
local variants = the_variants.variants
if variants then -- use splitter
@@ -1693,11 +1883,11 @@ local function check_variants(unicode,the_variants,splitter,unicodes)
parts = nil
end
end
- local italic_correction = the_variants.italic_correction
- if italic_correction and italic_correction == 0 then
- italic_correction = nil
+ local italic = the_variants.italic
+ if italic and italic == 0 then
+ italic = nil
end
- return variants, parts, italic_correction
+ return variants, parts, italic
end
actions["analyze math"] = function(data,filename,raw)
@@ -1706,15 +1896,16 @@ actions["analyze math"] = function(data,filename,raw)
local unicodes = data.resources.unicodes
local splitter = data.helpers.tounicodetable
for unicode, description in next, data.descriptions do
- local glyph = description.glyph
- local mathkerns = glyph.mathkern -- singular
- local horiz_variants = glyph.horiz_variants
- local vert_variants = glyph.vert_variants
- local top_accent = glyph.top_accent
- if mathkerns or horiz_variants or vert_variants or top_accent then
+ local glyph = description.glyph
+ local mathkerns = glyph.mathkern -- singular
+ local hvariants = glyph.horiz_variants
+ local vvariants = glyph.vert_variants
+ local accent = glyph.top_accent
+ local italic = glyph.italic_correction
+ if mathkerns or hvariants or vvariants or accent or italic then
local math = { }
- if top_accent then
- math.top_accent = top_accent
+ if accent then
+ math.accent = accent
end
if mathkerns then
for k, v in next, mathkerns do
@@ -1730,15 +1921,14 @@ actions["analyze math"] = function(data,filename,raw)
end
math.kerns = mathkerns
end
- if horiz_variants then
- math.horiz_variants, math.horiz_parts, math.horiz_italic_correction = check_variants(unicode,horiz_variants,splitter,unicodes)
+ if hvariants then
+ math.hvariants, math.hparts, math.hitalic = check_variants(unicode,hvariants,splitter,unicodes)
end
- if vert_variants then
- math.vert_variants, math.vert_parts, math.vert_italic_correction = check_variants(unicode,vert_variants,splitter,unicodes)
+ if vvariants then
+ math.vvariants, math.vparts, math.vitalic = check_variants(unicode,vvariants,splitter,unicodes)
end
- local italic_correction = description.italic
- if italic_correction and italic_correction ~= 0 then
- math.italic_correction = italic_correction
+ if italic and italic ~= 0 then
+ math.italic = italic
end
description.math = math
end
@@ -1903,7 +2093,7 @@ actions["merge kern classes"] = function(data,filename,raw)
report_otf("%s kern overloads ignored",ignored)
end
if blocked > 0 then
- report_otf("%s succesive kerns blocked",blocked)
+ report_otf("%s successive kerns blocked",blocked)
end
end
end
@@ -1940,18 +2130,21 @@ actions["check metadata"] = function(data,filename,raw)
end
end
--
+ local names = raw.names
+ --
if metadata.validation_state and table.contains(metadata.validation_state,"bad_ps_fontname") then
-- the ff library does a bit too much (and wrong) checking ... so we need to catch this
-- at least for now
local function valid(what)
- local names = raw.names
- for i=1,#names do
- local list = names[i]
- local names = list.names
- if names then
- local name = names[what]
- if name and valid_ps_name(name) then
- return name
+ if names then
+ for i=1,#names do
+ local list = names[i]
+ local names = list.names
+ if names then
+ local name = names[what]
+ if name and valid_ps_name(name) then
+ return name
+ end
end
end
end
@@ -1975,6 +2168,33 @@ actions["check metadata"] = function(data,filename,raw)
check("fullname")
end
--
+ if names then
+ local psname = metadata.psname
+ if not psname or psname == "" then
+ for i=1,#names do
+ local name = names[i]
+ -- Currently we use the same restricted search as in the new context (specific) font loader
+ -- but we might add more lang checks (it worked ok in the new loaded so now we're in sync)
+ -- This check here is also because there are (esp) cjk fonts out there with psnames different
+ -- from fontnames (gives a bad lookup in backend).
+ if lower(name.lang) == "english (us)" then
+ local specification = name.names
+ if specification then
+ local postscriptname = specification.postscriptname
+ if postscriptname then
+ psname = postscriptname
+ end
+ end
+ end
+ break
+ end
+ end
+ if psname ~= metadata.fontname then
+ report_otf("fontname %a, fullname %a, psname %a",metadata.fontname,metadata.fullname,psname)
+ end
+ metadata.psname = psname
+ end
+ --
end
actions["cleanup tables"] = function(data,filename,raw)
@@ -2000,7 +2220,9 @@ end
-- we can share { } as it is never set
---- ligatures have an extra specification.char entry that we don't use
+-- ligatures have an extra specification.char entry that we don't use
+
+-- mlookups only with pairs and ligatures
actions["reorganize glyph lookups"] = function(data,filename,raw)
local resources = data.resources
@@ -2081,14 +2303,14 @@ actions["reorganize glyph lookups"] = function(data,filename,raw)
if mlookups then
description.mlookups = mlookups
end
+ -- description.lookups = nil
end
end
-
end
local zero = { 0, 0 }
-actions["reorganize glyph anchors"] = function(data,filename,raw) -- when we replace inplace we safe entries
+actions["reorganize glyph anchors"] = function(data,filename,raw)
local descriptions = data.descriptions
for unicode, description in next, descriptions do
local anchors = description.glyph.anchors
@@ -2311,7 +2533,7 @@ end
-- we cannot share descriptions as virtual fonts might extend them (ok,
-- we could use a cache with a hash
--
--- we already assing an empty tabel to characters as we can add for
+-- we already assign an empty tabel to characters as we can add for
-- instance protruding info and loop over characters; one is not supposed
-- to change descriptions and if one does so one should make a copy!
@@ -2334,10 +2556,14 @@ local function copytotfm(data,cache_id)
local spaceunits = 500
local spacer = "space"
local designsize = metadata.designsize or metadata.design_size or 100
+ local minsize = metadata.minsize or metadata.design_range_bottom or designsize
+ local maxsize = metadata.maxsize or metadata.design_range_top or designsize
local mathspecs = metadata.math
--
if designsize == 0 then
designsize = 100
+ minsize = 100
+ maxsize = 100
end
if mathspecs then
for name, value in next, mathspecs do
@@ -2355,8 +2581,11 @@ local function copytotfm(data,cache_id)
local m = d.math
if m then
-- watch out: luatex uses horiz_variants for the parts
- local variants = m.horiz_variants
- local parts = m.horiz_parts
+ --
+ local italic = m.italic
+ --
+ local variants = m.hvariants
+ local parts = m.hparts
-- local done = { [unicode] = true }
if variants then
local c = character
@@ -2373,9 +2602,11 @@ local function copytotfm(data,cache_id)
c.horiz_variants = parts
elseif parts then
character.horiz_variants = parts
+ italic = m.hitalic
end
- local variants = m.vert_variants
- local parts = m.vert_parts
+ --
+ local variants = m.vvariants
+ local parts = m.vparts
-- local done = { [unicode] = true }
if variants then
local c = character
@@ -2392,15 +2623,18 @@ local function copytotfm(data,cache_id)
c.vert_variants = parts
elseif parts then
character.vert_variants = parts
+ italic = m.vitalic
end
- local italic_correction = m.vert_italic_correction
- if italic_correction then
- character.vert_italic_correction = italic_correction -- was c.
+ --
+ if italic and italic ~= 0 then
+ character.italic = italic -- overload
end
- local top_accent = m.top_accent
- if top_accent then
- character.top_accent = top_accent
+ --
+ local accent = m.accent
+ if accent then
+ character.accent = accent
end
+ --
local kerns = m.kerns
if kerns then
character.mathkerns = kerns
@@ -2413,16 +2647,16 @@ local function copytotfm(data,cache_id)
local filename = constructors.checkedfilename(resources)
local fontname = metadata.fontname
local fullname = metadata.fullname or fontname
- local psname = fontname or fullname
- local units = metadata.units_per_em or 1000
+ local psname = metadata.psname or fontname or fullname
+ local units = metadata.units or metadata.units_per_em or 1000
--
if units == 0 then -- catch bugs in fonts
units = 1000 -- maybe 2000 when ttf
- metadata.units_per_em = 1000
+ metadata.units = 1000
report_otf("changing %a units to %a",0,units)
end
--
- local monospaced = metadata.isfixedpitch or (pfminfo.panose and pfminfo.panose.proportion == "Monospaced")
+ local monospaced = metadata.monospaced or metadata.isfixedpitch or (pfminfo.panose and pfminfo.panose.proportion == "Monospaced")
local charwidth = pfminfo.avgwidth -- or unset
local charxheight = pfminfo.os2_xheight and pfminfo.os2_xheight > 0 and pfminfo.os2_xheight
-- charwidth = charwidth * units/1000
@@ -2492,17 +2726,16 @@ local function copytotfm(data,cache_id)
end
end
--
- parameters.designsize = (designsize/10)*65536
- parameters.ascender = abs(metadata.ascent or 0)
- parameters.descender = abs(metadata.descent or 0)
- parameters.units = units
+ parameters.designsize = (designsize/10)*65536
+ parameters.minsize = (minsize /10)*65536
+ parameters.maxsize = (maxsize /10)*65536
+ parameters.ascender = abs(metadata.ascender or metadata.ascent or 0)
+ parameters.descender = abs(metadata.descender or metadata.descent or 0)
+ parameters.units = units
--
properties.space = spacer
properties.encodingbytes = 2
properties.format = data.format or otf_format(filename) or formats.otf
--- if units ~= 1000 and format ~= "truetype" then
--- properties.format = "truetype"
--- end
properties.noglyphnames = true
properties.filename = filename
properties.fontname = fontname
@@ -2703,3 +2936,111 @@ function otf.scriptandlanguage(tfmdata,attr)
local properties = tfmdata.properties
return properties.script or "dflt", properties.language or "dflt"
end
+
+-- a little bit of abstraction
+
+local function justset(coverage,unicode,replacement)
+ coverage[unicode] = replacement
+end
+
+otf.coverup = {
+ stepkey = "subtables",
+ actions = {
+ substitution = justset,
+ alternate = justset,
+ multiple = justset,
+ ligature = justset,
+ kern = justset,
+ },
+ register = function(coverage,lookuptype,format,feature,n,descriptions,resources)
+ local name = formatters["ctx_%s_%s"](feature,n)
+ if lookuptype == "kern" then
+ resources.lookuptypes[name] = "position"
+ else
+ resources.lookuptypes[name] = lookuptype
+ end
+ for u, c in next, coverage do
+ local description = descriptions[u]
+ local slookups = description.slookups
+ if slookups then
+ slookups[name] = c
+ else
+ description.slookups = { [name] = c }
+ end
+-- inspect(feature,description)
+ end
+ return name
+ end
+}
+
+-- moved from font-oth.lua
+
+local function getgsub(tfmdata,k,kind)
+ local description = tfmdata.descriptions[k]
+ if description then
+ local slookups = description.slookups -- we assume only slookups (we can always extend)
+ if slookups then
+ local shared = tfmdata.shared
+ local rawdata = shared and shared.rawdata
+ if rawdata then
+ local lookuptypes = rawdata.resources.lookuptypes
+ if lookuptypes then
+ local properties = tfmdata.properties
+ -- we could cache these
+ local validlookups, lookuplist = otf.collectlookups(rawdata,kind,properties.script,properties.language)
+ if validlookups then
+ for l=1,#lookuplist do
+ local lookup = lookuplist[l]
+ local found = slookups[lookup]
+ if found then
+ return found, lookuptypes[lookup]
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+otf.getgsub = getgsub -- returns value, gsub_kind
+
+function otf.getsubstitution(tfmdata,k,kind,value)
+ local found, kind = getgsub(tfmdata,k,kind)
+ if not found then
+ --
+ elseif kind == "substitution" then
+ return found
+ elseif kind == "alternate" then
+ local choice = tonumber(value) or 1 -- no random here (yet)
+ return found[choice] or found[1] or k
+ end
+ return k
+end
+
+otf.getalternate = otf.getsubstitution
+
+function otf.getmultiple(tfmdata,k,kind)
+ local found, kind = getgsub(tfmdata,k,kind)
+ if found and kind == "multiple" then
+ return found
+ end
+ return { k }
+end
+
+function otf.getkern(tfmdata,left,right,kind)
+ local kerns = getgsub(tfmdata,left,kind or "kern",true) -- for now we use getsub
+ if kerns then
+ local found = kerns[right]
+ local kind = type(found)
+ if kind == "table" then
+ found = found[1][3] -- can be more clever
+ elseif kind ~= "number" then
+ found = false
+ end
+ if found then
+ return found * tfmdata.parameters.factor
+ end
+ end
+ return 0
+end
diff --git a/src/fontloader/misc/fontloader-font-otp.lua b/src/fontloader/misc/fontloader-font-otp.lua
index ebf36ed..91bd05b 100644
--- a/src/fontloader/misc/fontloader-font-otp.lua
+++ b/src/fontloader/misc/fontloader-font-otp.lua
@@ -12,9 +12,8 @@ if not modules then modules = { } end modules ['font-otp'] = {
--
-- 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 next, type, tostring = next, type, tostring
local sort, concat = table.sort, table.concat
-local sortedhash = table.sortedhash
local trace_packing = false trackers.register("otf.packing", function(v) trace_packing = v end)
local trace_loading = false trackers.register("otf.loading", function(v) trace_loading = v end)
@@ -148,6 +147,7 @@ end
-- we then need to sort more thanks to random hashing
local function packdata(data)
+
if data then
-- stripdata(data)
local h, t, c = { }, { }, { }
@@ -537,6 +537,7 @@ local unpacked_mt = {
}
local function unpackdata(data)
+
if data then
local tables = data.tables
if tables then
diff --git a/src/fontloader/misc/fontloader-font-tfm.lua b/src/fontloader/misc/fontloader-font-tfm.lua
index ab03788..401dc83 100644
--- a/src/fontloader/misc/fontloader-font-tfm.lua
+++ b/src/fontloader/misc/fontloader-font-tfm.lua
@@ -24,6 +24,7 @@ local constructors = fonts.constructors
local encodings = fonts.encodings
local tfm = constructors.newhandler("tfm")
+tfm.version = 1.000
local tfmfeatures = constructors.newfeatures("tfm")
local registertfmfeature = tfmfeatures.register
diff --git a/src/fontloader/misc/fontloader-fonts-cbk.lua b/src/fontloader/misc/fontloader-fonts-cbk.lua
index 81b5b6e..9da8151 100644
--- a/src/fontloader/misc/fontloader-fonts-cbk.lua
+++ b/src/fontloader/misc/fontloader-fonts-cbk.lua
@@ -160,12 +160,31 @@ function nodes.handlers.nodepass(head)
local range = basefonts[i]
local start = range[1]
local stop = range[2]
- if stop then
- start, stop = ligaturing(start,stop)
- start, stop = kerning(start,stop)
- elseif start then
- start = ligaturing(start)
- start = kerning(start)
+ -- maybe even: if start and start ~= stop then
+ if start or stop then
+ local prev = nil
+ local next = nil
+ local front = start == head
+ if stop then
+ next = stop.next
+ start, stop = ligaturing(start,stop)
+ start, stop = kerning(start,stop)
+ elseif start then
+ prev = start.prev
+ start = ligaturing(start)
+ start = kerning(start)
+ end
+ if prev then
+ start.prev = prev
+ prev.next = start
+ end
+ if next then
+ stop.next = next
+ next.prev = stop
+ end
+ if front then
+ head = start
+ end
end
end
end
@@ -176,7 +195,7 @@ function nodes.handlers.nodepass(head)
end
function nodes.handlers.basepass(head)
- if not basepass then
+ if basepass then
head = ligaturing(head)
head = kerning(head)
end
diff --git a/src/fontloader/misc/fontloader-fonts-inj.lua b/src/fontloader/misc/fontloader-fonts-inj.lua
index 332e920..36781f7 100644
--- a/src/fontloader/misc/fontloader-fonts-inj.lua
+++ b/src/fontloader/misc/fontloader-fonts-inj.lua
@@ -8,7 +8,16 @@ if not modules then modules = { } end modules ['font-inj'] = {
-- This property based variant is not faster but looks nicer than the attribute one. We
-- need to use rawget (which is apbout 4 times slower than a direct access but we cannot
--- get/set that one for our purpose!
+-- get/set that one for our purpose! This version does a bit more with discretionaries
+-- (and Kai has tested it with his collection of weird fonts.)
+
+-- There is some duplicate code here (especially in the the pre/post/replace branches) but
+-- we go for speed. We could store a list of glyph and mark nodes when registering but it's
+-- cleaner to have an identification pass here. Also, I need to keep tracing in mind so
+-- being too clever here is dangerous.
+
+-- The subtype test is not needed as there will be no (new) properties set, given that we
+-- reset the properties.
if not nodes.properties then return end
@@ -80,8 +89,7 @@ function injections.resetcounts()
keepregisteredcounts = false
end
--- We need to make sure that a possible metatable will not kick in
--- unexpectedly.
+-- We need to make sure that a possible metatable will not kick in unexpectedly.
function injections.reset(n)
local p = rawget(properties,n)
@@ -146,7 +154,8 @@ end
function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmnext) -- hm: nuts or nodes
local dx = factor*(exit[1]-entry[1])
local dy = -factor*(exit[2]-entry[2])
- local ws, wn = tfmstart.width, tfmnext.width
+ local ws = tfmstart.width
+ local wn = tfmnext.width
nofregisteredcursives = nofregisteredcursives + 1
if rlmode < 0 then
dx = -(dx + wn)
@@ -195,7 +204,10 @@ function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmne
end
function injections.setpair(current,factor,rlmode,r2lflag,spec,injection) -- r2lflag & tfmchr not used
- local x, y, w, h = factor*spec[1], factor*spec[2], factor*spec[3], factor*spec[4]
+ local x = factor*spec[1]
+ local y = factor*spec[2]
+ local w = factor*spec[3]
+ local h = factor*spec[4]
if x ~= 0 or w ~= 0 or y ~= 0 or h ~= 0 then -- okay?
local yoffset = y - h
local leftkern = x -- both kerns are set in a pair kern compared
@@ -205,9 +217,12 @@ function injections.setpair(current,factor,rlmode,r2lflag,spec,injection) -- r2l
if rlmode and rlmode < 0 then
leftkern, rightkern = rightkern, leftkern
end
+ if not injection then
+ injection = "injections"
+ end
local p = rawget(properties,current)
if p then
- local i = rawget(p,"injections")
+ local i = rawget(p,injection)
if i then
if leftkern ~= 0 then
i.leftkern = (i.leftkern or 0) + leftkern
@@ -219,19 +234,19 @@ function injections.setpair(current,factor,rlmode,r2lflag,spec,injection) -- r2l
i.yoffset = (i.yoffset or 0) + yoffset
end
elseif leftkern ~= 0 or rightkern ~= 0 then
- p.injections = {
+ p[injection] = {
leftkern = leftkern,
rightkern = rightkern,
yoffset = yoffset,
}
else
- p.injections = {
+ p[injection] = {
yoffset = yoffset,
}
end
elseif leftkern ~= 0 or rightkern ~= 0 then
properties[current] = {
- injections = {
+ [injection] = {
leftkern = leftkern,
rightkern = rightkern,
yoffset = yoffset,
@@ -239,7 +254,7 @@ function injections.setpair(current,factor,rlmode,r2lflag,spec,injection) -- r2l
}
else
properties[current] = {
- injections = {
+ [injection] = {
yoffset = yoffset,
},
}
@@ -250,10 +265,9 @@ function injections.setpair(current,factor,rlmode,r2lflag,spec,injection) -- r2l
return x, y, w, h -- no bound
end
--- this needs checking for rl < 0 but it is unlikely that a r2l script
--- uses kernclasses between glyphs so we're probably safe (KE has a
--- problematic font where marks interfere with rl < 0 in the previous
--- case)
+-- This needs checking for rl < 0 but it is unlikely that a r2l script uses kernclasses between
+-- glyphs so we're probably safe (KE has a problematic font where marks interfere with rl < 0 in
+-- the previous case)
function injections.setkern(current,factor,rlmode,x,injection)
local dx = factor * x
@@ -285,7 +299,7 @@ function injections.setkern(current,factor,rlmode,x,injection)
end
end
-function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase) -- ba=baseanchor, ma=markanchor
+function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk) -- ba=baseanchor, ma=markanchor
local dx, dy = factor*(ba[1]-ma[1]), factor*(ba[2]-ma[2])
nofregisteredmarks = nofregisteredmarks + 1
-- markanchors[nofregisteredmarks] = base
@@ -293,14 +307,20 @@ function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase) -- ba=basean
dx = tfmbase.width - dx -- see later commented ox
end
local p = rawget(properties,start)
+ -- hm, dejavu serif does a sloppy mark2mark before mark2base
if p then
local i = rawget(p,"injections")
if i then
- i.markx = dx
- i.marky = dy
- i.markdir = rlmode or 0
- i.markbase = nofregisteredmarks
- i.markbasenode = base
+ if i.markmark then
+ -- out of order mkmk: yes or no or option
+ else
+ i.markx = dx
+ i.marky = dy
+ i.markdir = rlmode or 0
+ i.markbase = nofregisteredmarks
+ i.markbasenode = base
+ i.markmark = mkmk
+ end
else
p.injections = {
markx = dx,
@@ -308,6 +328,7 @@ function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase) -- ba=basean
markdir = rlmode or 0,
markbase = nofregisteredmarks,
markbasenode = base,
+ markmark = mkmk,
}
end
else
@@ -318,6 +339,7 @@ function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase) -- ba=basean
markdir = rlmode or 0,
markbase = nofregisteredmarks,
markbasenode = base,
+ markmark = mkmk,
},
}
end
@@ -430,30 +452,36 @@ local function show_result(head)
end
end
--- we could also check for marks here but maybe not all are registered (needs checking)
-
-local function collect_glyphs_1(head)
- local glyphs, nofglyphs = { }, 0
- local marks, nofmarks = { }, 0
+local function collect_glyphs(head,offsets)
+ local glyphs, glyphi, nofglyphs = { }, { }, 0
+ local marks, marki, nofmarks = { }, { }, 0
local nf, tm = nil, nil
- for n in traverse_id(glyph_code,head) do -- only needed for relevant fonts
- if getsubtype(n) < 256 then
- local f = getfont(n)
- if f ~= nf then
- nf = f
- tm = fontdata[nf].resources.marks -- other hash in ctx
- end
- if tm and tm[getchar(n)] then
- nofmarks = nofmarks + 1
- marks[nofmarks] = n
- else
- nofglyphs = nofglyphs + 1
- glyphs[nofglyphs] = n
+ local n = head
+
+ local function identify(n,what)
+ local f = getfont(n)
+ if f ~= nf then
+ nf = f
+ -- other hash in ctx:
+ tm = fontdata[nf].resources
+ if tm then
+ tm = tm.marks
end
+ end
+ if tm and tm[getchar(n)] then
+ nofmarks = nofmarks + 1
+ marks[nofmarks] = n
+ marki[nofmarks] = "injections"
+ else
+ nofglyphs = nofglyphs + 1
+ glyphs[nofglyphs] = n
+ glyphi[nofglyphs] = what
+ end
+ if offsets then
-- yoffsets can influence curs steps
local p = rawget(properties,n)
if p then
- local i = rawget(p,"injections")
+ local i = rawget(p,what)
if i then
local yoffset = i.yoffset
if yoffset and yoffset ~= 0 then
@@ -463,38 +491,50 @@ local function collect_glyphs_1(head)
end
end
end
- return glyphs, nofglyphs, marks, nofmarks
-end
-local function collect_glyphs_2(head)
- local glyphs, nofglyphs = { }, 0
- local marks, nofmarks = { }, 0
- local nf, tm = nil, nil
- for n in traverse_id(glyph_code,head) do
- if getsubtype(n) < 256 then
- local f = getfont(n)
- if f ~= nf then
- nf = f
- tm = fontdata[nf].resources.marks -- other hash in ctx
- end
- if tm and tm[getchar(n)] then
- nofmarks = nofmarks + 1
- marks[nofmarks] = n
- else
- nofglyphs = nofglyphs + 1
- glyphs[nofglyphs] = n
- end
+ while n do -- only needed for relevant fonts
+ local id = getid(n)
+ if id == glyph_code then
+ identify(n,"injections")
+ elseif id == disc_code then
+ local d = getfield(n,"pre")
+ if d then
+ for n in traverse_id(glyph_code,d) do
+ if getsubtype(n) < 256 then
+ identify(n,"preinjections")
+ end
+ end
+ end
+ local d = getfield(n,"post")
+ if d then
+ for n in traverse_id(glyph_code,d) do
+ if getsubtype(n) < 256 then
+ identify(n,"postinjections")
+ end
+ end
+ end
+ local d = getfield(n,"replace")
+ if d then
+ for n in traverse_id(glyph_code,d) do
+ if getsubtype(n) < 256 then
+ identify(n,"replaceinjections")
+ end
+ end
+ end
end
+ n = getnext(n)
end
- return glyphs, nofglyphs, marks, nofmarks
+
+ return glyphs, glyphi, nofglyphs, marks, marki, nofmarks
end
-local function inject_marks(marks,nofmarks)
+local function inject_marks(marks,marki,nofmarks)
for i=1,nofmarks do
- local n = marks[i]
+ local n = marks[i]
local pn = rawget(properties,n)
if pn then
- pn = rawget(pn,"injections")
+ local ni = marki[i]
+ local pn = rawget(pn,ni)
if pn then
local p = pn.markbasenode
if p then
@@ -503,7 +543,7 @@ local function inject_marks(marks,nofmarks)
local rightkern = nil
local pp = rawget(properties,p)
if pp then
- pp = rawget(pp,"injections")
+ pp = rawget(pp,ni)
if pp then
rightkern = pp.rightkern
end
@@ -516,13 +556,22 @@ local function inject_marks(marks,nofmarks)
else
-- kern(x) glyph(p) kern(w-x) mark(n)
-- ox = px - getfield(p,"width") + pn.markx - pp.leftkern
- local leftkern = pp.leftkern
- if leftkern then
- ox = px - pn.markx
+ --
+ -- According to Kai we don't need to handle leftkern here but I'm
+ -- pretty sure I've run into a case where it was needed so maybe
+ -- some day we need something more clever here.
+ --
+ if false then
+ -- a mark with kerning
+ local leftkern = pp.leftkern
+ if leftkern then
+ ox = px - pn.markx - leftkern
+ else
+ ox = px - pn.markx
+ end
else
- ox = px - pn.markx - leftkern
+ ox = px - pn.markx
end
--- report_injections("l2r case 1: %p",ox)
end
else
-- we need to deal with fonts that have marks with width
@@ -548,12 +597,13 @@ local function inject_marks(marks,nofmarks)
setfield(n,"xoffset",ox)
--
local py = getfield(p,"yoffset")
- local oy = 0
- if marks[p] then
- oy = py + pn.marky
- else
- oy = getfield(n,"yoffset") + py + pn.marky
- end
+-- local oy = 0
+-- if marks[p] then
+-- oy = py + pn.marky
+-- else
+-- oy = getfield(n,"yoffset") + py + pn.marky
+-- end
+ local oy = getfield(n,"yoffset") + py + pn.marky
setfield(n,"yoffset",oy)
else
-- normally this can't happen (only when in trace mode which is a special case anyway)
@@ -564,14 +614,14 @@ local function inject_marks(marks,nofmarks)
end
end
-local function inject_cursives(glyphs,nofglyphs)
+local function inject_cursives(glyphs,glyphi,nofglyphs)
local cursiveanchor, lastanchor = nil, nil
local minc, maxc, last = 0, 0, nil
for i=1,nofglyphs do
- local n = glyphs[i]
+ local n = glyphs[i]
local pn = rawget(properties,n)
if pn then
- pn = rawget(pn,"injections")
+ pn = rawget(pn,glyphi[i])
end
if pn then
local cursivex = pn.cursivex
@@ -630,7 +680,7 @@ local function inject_cursives(glyphs,nofglyphs)
-- if maxc > 0 and not cursiveanchor then
-- local ny = getfield(n,"yoffset")
-- for i=maxc,minc,-1 do
- -- local ti = glyphs[i]
+ -- local ti = glyphs[i][1]
-- ny = ny + properties[ti].cursivedy
-- setfield(ti,"yoffset",ny) -- why not add ?
-- end
@@ -647,23 +697,67 @@ local function inject_cursives(glyphs,nofglyphs)
end
end
-local function inject_kerns(head,list,length)
- -- todo: pre/post/replace
+-- G +D-pre G
+-- D-post+
+-- +D-replace+
+--
+-- G +D-pre +D-pre
+-- D-post +D-post
+-- +D-replace +D-replace
+
+local function inject_kerns(head,glist,ilist,length) -- not complete ! compare with inject_kerns_only (but unlikely disc here)
for i=1,length do
- local n = list[i]
+ local n = glist[i]
local pn = rawget(properties,n)
if pn then
- local i = rawget(pn,"injections")
- if i then
- local leftkern = i.leftkern
- if leftkern and leftkern ~= 0 then
- insert_node_before(head,n,newkern(leftkern)) -- type 0/2
- end
- local rightkern = i.rightkern
- if rightkern and rightkern ~= 0 then
- insert_node_after(head,n,newkern(rightkern)) -- type 0/2
- end
- end
+ local dp = nil
+ local dr = nil
+ local ni = ilist[i]
+ local p = nil
+ if ni == "injections" then
+ p = getprev(n)
+ if p then
+ local id = getid(p)
+ if id == disc_code then
+ dp = getfield(p,"post")
+ dr = getfield(p,"replace")
+ end
+ end
+ end
+ if dp then
+ local i = rawget(pn,"postinjections")
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ local t = find_tail(dp)
+ insert_node_after(dp,t,newkern(leftkern))
+ setfield(p,"post",dp) -- currently we need to force a tail refresh
+ end
+ end
+ end
+ if dr then
+ local i = rawget(pn,"replaceinjections")
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ local t = find_tail(dr)
+ insert_node_after(dr,t,newkern(leftkern))
+ setfield(p,"replace",dr) -- currently we need to force a tail refresh
+ end
+ end
+ else
+ local i = rawget(pn,ni)
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ insert_node_before(head,n,newkern(leftkern)) -- type 0/2
+ end
+ local rightkern = i.rightkern
+ if rightkern and rightkern ~= 0 then
+ insert_node_after(head,n,newkern(rightkern)) -- type 0/2
+ end
+ end
+ end
end
end
end
@@ -673,23 +767,18 @@ local function inject_everything(head,where)
if trace_injections then
trace(head,"everything")
end
- local glyphs, nofglyphs, marks, nofmarks
- if nofregisteredpairs > 0 then
- glyphs, nofglyphs, marks, nofmarks = collect_glyphs_1(head)
- else
- glyphs, nofglyphs, marks, nofmarks = collect_glyphs_2(head)
- end
+ local glyphs, glyphi, nofglyphs, marks, marki, nofmarks = collect_glyphs(head,nofregisteredpairs > 0)
if nofglyphs > 0 then
if nofregisteredcursives > 0 then
- inject_cursives(glyphs,nofglyphs)
+ inject_cursives(glyphs,glyphi,nofglyphs)
end
if nofregisteredmarks > 0 then -- and nofmarks > 0
- inject_marks(marks,nofmarks)
+ inject_marks(marks,marki,nofmarks)
end
- inject_kerns(head,glyphs,nofglyphs)
+ inject_kerns(head,glyphs,glyphi,nofglyphs)
end
if nofmarks > 0 then
- inject_kerns(head,marks,nofmarks)
+ inject_kerns(head,marks,marki,nofmarks)
end
if keepregisteredcounts then
keepregisteredcounts = false
@@ -702,13 +791,21 @@ local function inject_everything(head,where)
return tonode(head), true
end
+-- G +D-pre G
+-- D-post+
+-- +D-replace+
+--
+-- G +D-pre +D-pre
+-- D-post +D-post
+-- +D-replace +D-replace
+
local function inject_kerns_only(head,where)
head = tonut(head)
if trace_injections then
trace(head,"kerns")
end
local n = head
- local p = nil
+ local p = nil -- disc node when non-nil
while n do
local id = getid(n)
if id == glyph_code then
@@ -724,6 +821,7 @@ local function inject_kerns_only(head,where)
if leftkern and leftkern ~= 0 then
local t = find_tail(d)
insert_node_after(d,t,newkern(leftkern))
+ setfield(p,"post",d) -- currently we need to force a tail refresh
end
end
end
@@ -735,6 +833,7 @@ local function inject_kerns_only(head,where)
if leftkern and leftkern ~= 0 then
local t = find_tail(d)
insert_node_after(d,t,newkern(leftkern))
+ setfield(p,"replace",d) -- currently we need to force a tail refresh
end
end
else
@@ -747,6 +846,7 @@ local function inject_kerns_only(head,where)
end
end
else
+ -- this is the most common case
local i = rawget(pn,"injections")
if i then
local leftkern = i.leftkern
@@ -756,8 +856,6 @@ local function inject_kerns_only(head,where)
end
end
end
- else
- break
end
p = nil
elseif id == disc_code then
@@ -812,7 +910,7 @@ local function inject_kerns_only(head,where)
local h = d
for n in traverse_id(glyph_code,d) do
if getsubtype(n) < 256 then
- local pn = rawget(properties,n) -- why can it be empty { }
+ local pn = rawget(properties,n)
if pn then
local i = rawget(pn,"replaceinjections")
if i then
@@ -850,9 +948,8 @@ local function inject_pairs_only(head,where)
if trace_injections then
trace(head,"pairs")
end
- --
local n = head
- local p = nil
+ local p = nil -- disc node when non-nil
while n do
local id = getid(n)
if id == glyph_code then
@@ -868,6 +965,7 @@ local function inject_pairs_only(head,where)
if leftkern and leftkern ~= 0 then
local t = find_tail(d)
insert_node_after(d,t,newkern(leftkern))
+ setfield(p,"post",d) -- currently we need to force a tail refresh
end
-- local rightkern = i.rightkern
-- if rightkern and rightkern ~= 0 then
@@ -884,6 +982,7 @@ local function inject_pairs_only(head,where)
if leftkern and leftkern ~= 0 then
local t = find_tail(d)
insert_node_after(d,t,newkern(leftkern))
+ setfield(p,"replace",d) -- currently we need to force a tail refresh
end
-- local rightkern = i.rightkern
-- if rightkern and rightkern ~= 0 then
@@ -909,24 +1008,22 @@ local function inject_pairs_only(head,where)
-- this is the most common case
local i = rawget(pn,"injections")
if i then
- local yoffset = i.yoffset
- if yoffset and yoffset ~= 0 then
- setfield(n,"yoffset",yoffset)
- end
local leftkern = i.leftkern
if leftkern and leftkern ~= 0 then
- insert_node_before(head,n,newkern(leftkern))
+ head = insert_node_before(head,n,newkern(leftkern))
end
local rightkern = i.rightkern
if rightkern and rightkern ~= 0 then
insert_node_after(head,n,newkern(rightkern))
n = getnext(n) -- to be checked
end
+ local yoffset = i.yoffset
+ if yoffset and yoffset ~= 0 then
+ setfield(n,"yoffset",yoffset)
+ end
end
end
end
- else
- break
end
p = nil
elseif id == disc_code then
@@ -935,16 +1032,12 @@ local function inject_pairs_only(head,where)
local h = d
for n in traverse_id(glyph_code,d) do
if getsubtype(n) < 256 then
- local p = rawget(properties,n)
- if p then
- local i = rawget(p,"preinjections")
+ local pn = rawget(properties,n)
+ if pn then
+ local i = rawget(pn,"preinjections")
if i then
- local yoffset = i.yoffset
- if yoffset and yoffset ~= 0 then
- setfield(n,"yoffset",yoffset)
- end
local leftkern = i.leftkern
- if leftkern ~= 0 then
+ if leftkern and leftkern ~= 0 then
h = insert_node_before(h,n,newkern(leftkern))
end
local rightkern = i.rightkern
@@ -952,6 +1045,10 @@ local function inject_pairs_only(head,where)
insert_node_after(head,n,newkern(rightkern))
n = getnext(n) -- to be checked
end
+ local yoffset = i.yoffset
+ if yoffset and yoffset ~= 0 then
+ setfield(n,"yoffset",yoffset)
+ end
end
end
else
@@ -967,14 +1064,10 @@ local function inject_pairs_only(head,where)
local h = d
for n in traverse_id(glyph_code,d) do
if getsubtype(n) < 256 then
- local p = rawget(properties,n)
- if p then
- local i = rawget(p,"postinjections")
+ local pn = rawget(properties,n)
+ if pn then
+ local i = rawget(pn,"postinjections")
if i then
- local yoffset = i.yoffset
- if yoffset and yoffset ~= 0 then
- setfield(n,"yoffset",yoffset)
- end
local leftkern = i.leftkern
if leftkern and leftkern ~= 0 then
h = insert_node_before(h,n,newkern(leftkern))
@@ -984,6 +1077,10 @@ local function inject_pairs_only(head,where)
insert_node_after(head,n,newkern(rightkern))
n = getnext(n) -- to be checked
end
+ local yoffset = i.yoffset
+ if yoffset and yoffset ~= 0 then
+ setfield(n,"yoffset",yoffset)
+ end
end
end
else
@@ -999,14 +1096,10 @@ local function inject_pairs_only(head,where)
local h = d
for n in traverse_id(glyph_code,d) do
if getsubtype(n) < 256 then
- local p = rawget(properties,n)
- if p then
- local i = rawget(p,"replaceinjections")
+ local pn = rawget(properties,n)
+ if pn then
+ local i = rawget(pn,"replaceinjections")
if i then
- local yoffset = i.yoffset
- if yoffset and yoffset ~= 0 then
- setfield(n,"yoffset",yoffset)
- end
local leftkern = i.leftkern
if leftkern and leftkern ~= 0 then
h = insert_node_before(h,n,newkern(leftkern))
@@ -1016,6 +1109,10 @@ local function inject_pairs_only(head,where)
insert_node_after(head,n,newkern(rightkern))
n = getnext(n) -- to be checked
end
+ local yoffset = i.yoffset
+ if yoffset and yoffset ~= 0 then
+ setfield(n,"yoffset",yoffset)
+ end
end
end
else
@@ -1042,7 +1139,7 @@ local function inject_pairs_only(head,where)
return tonode(head), true
end
-function injections.handler(head,where) -- optimize for n=1 ?
+function injections.handler(head,where)
if nofregisteredmarks > 0 or nofregisteredcursives > 0 then
return inject_everything(head,where)
elseif nofregisteredpairs > 0 then
diff --git a/src/fontloader/misc/fontloader-fonts-otn.lua b/src/fontloader/misc/fontloader-fonts-otn.lua
index dd3aa61..1b99c56 100644
--- a/src/fontloader/misc/fontloader-fonts-otn.lua
+++ b/src/fontloader/misc/fontloader-fonts-otn.lua
@@ -6,12 +6,16 @@ if not modules then modules = { } end modules ['font-otn'] = {
license = "see context related readme files",
}
--- todo: looks like we have a leak somewhere (probably in ligatures)
--- todo: copy attributes to disc
-
-- this is a context version which can contain experimental code, but when we
-- have serious patches we also need to change the other two font-otn files
+-- at some point i might decide to convert the whole list into a table and then
+-- run over that instead (but it has some drawbacks as we also need to deal with
+-- attributes and such so we need to keep a lot of track - which is why i rejected
+-- that method - although it has become a bit easier in the meantime so it might
+-- become an alternative (by that time i probably have gone completely lua) .. the
+-- usual chicken-egg issues ... maybe mkix as it's no real tex any more then
+
-- preprocessors = { "nodes" }
-- anchor class : mark, mkmk, curs, mklg (todo)
@@ -40,7 +44,18 @@ if not modules then modules = { } end modules ['font-otn'] = {
-- mark (to mark) code is still not what it should be (too messy but we need some more extreem husayni tests)
-- remove some optimizations (when I have a faster machine)
--
--- maybe redo the lot some way (more context specific)
+-- beware:
+--
+-- we do some disc jugling where we need to keep in mind that the
+-- pre, post and replace fields can have prev pointers to a nesting
+-- node ... i wonder if that is still needed
+--
+-- not possible:
+--
+-- \discretionary {alpha-} {betagammadelta}
+-- {\discretionary {alphabeta-} {gammadelta}
+-- {\discretionary {alphabetagamma-} {delta}
+-- {alphabetagammadelta}}}
--[[ldx--
This module is a bit more split up that I'd like but since we also want to test
@@ -65,9 +80,12 @@ is currently acceptable. Not all functions are implemented yet, often because I
lack the fonts for testing. Many scripts are not yet supported either, but I will
look into them as soon as users ask for it.
-Because there are different interpretations possible, I will extend the code
-with more (configureable) variants. I can also add hooks for users so that they can
-write their own extensions.
+The specification leaves room for interpretation. In case of doubt the microsoft
+implementation is the reference as it is the most complete one. As they deal with
+lots of scripts and fonts, Kai and Ivo did a lot of testing of the generic code and
+their suggestions help improve the code. I'm aware that not all border cases can be
+taken care of, unless we accept excessive runtime, and even then the interference
+with other mechanisms (like hyphenation) are not trivial.
Glyphs are indexed not by unicode but in their own way. This is because there is no
relationship with unicode at all, apart from the fact that a font might cover certain
@@ -94,12 +112,12 @@ when there's a fix in the library or code that
results in different tables.
--ldx]]--
--- action handler chainproc chainmore comment
+-- action handler chainproc
--
--- gsub_single ok ok ok
--- gsub_multiple ok ok not implemented yet
--- gsub_alternate ok ok not implemented yet
--- gsub_ligature ok ok ok
+-- gsub_single ok ok
+-- gsub_multiple ok ok
+-- gsub_alternate ok ok
+-- gsub_ligature ok ok
-- gsub_context ok --
-- gsub_contextchain ok --
-- gsub_reversecontextchain ok --
@@ -123,7 +141,6 @@ results in different tables.
-- chainmore : multiple substitutions triggered by contextual lookup (e.g. fij -> f + ij)
--
-- remark: the 'not implemented yet' variants will be done when we have fonts that use them
--- remark: we need to check what to do with discretionaries
-- We used to have independent hashes for lookups but as the tags are unique
-- we now use only one hash. If needed we can have multiple again but in that
@@ -131,16 +148,14 @@ results in different tables.
-- Todo: make plugin feature that operates on char/glyphnode arrays
-local concat, insert, remove = table.concat, table.insert, table.remove
-local gmatch, gsub, find, match, lower, strip = string.gmatch, string.gsub, string.find, string.match, string.lower, string.strip
-local type, next, tonumber, tostring = type, next, tonumber, tostring
-local lpegmatch = lpeg.match
+local type, next, tonumber = type, next, tonumber
local random = math.random
local formatters = string.formatters
local logs, trackers, nodes, attributes = logs, trackers, nodes, attributes
-local registertracker = trackers.register
+local registertracker = trackers.register
+local registerdirective = directives.register
local fonts = fonts
local otf = fonts.handlers.otf
@@ -162,6 +177,16 @@ local trace_steps = false registertracker("otf.steps", function(v
local trace_skips = false registertracker("otf.skips", function(v) trace_skips = v end)
local trace_directions = false registertracker("otf.directions", function(v) trace_directions = v end)
+local trace_kernruns = false registertracker("otf.kernruns", function(v) trace_kernruns = v end)
+local trace_discruns = false registertracker("otf.discruns", function(v) trace_discruns = v end)
+local trace_compruns = false registertracker("otf.compruns", function(v) trace_compruns = v end)
+
+local quit_on_no_replacement = true -- maybe per font
+local zwnjruns = true
+
+registerdirective("otf.zwnjruns", function(v) zwnjruns = v end)
+registerdirective("otf.chain.quitonnoreplacement",function(value) quit_on_no_replacement = value end)
+
local report_direct = logs.reporter("fonts","otf direct")
local report_subchain = logs.reporter("fonts","otf subchain")
local report_chain = logs.reporter("fonts","otf chain")
@@ -230,11 +255,7 @@ 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
@@ -286,6 +307,15 @@ local handlers = { }
local rlmode = 0
local featurevalue = false
+local sweephead = { }
+local sweepnode = nil
+local sweepprev = nil
+local sweepnext = nil
+
+local notmatchpre = { }
+local notmatchpost = { }
+local notmatchreplace = { }
+
-- head is always a whatsit so we can safely assume that head is not changed
-- we use this for special testing and documentation
@@ -376,8 +406,66 @@ local function copy_glyph(g) -- next and prev are untouched !
end
end
---
+local function flattendisk(head,disc)
+ local replace = getfield(disc,"replace")
+ setfield(disc,"replace",nil)
+ free_node(disc)
+ if head == disc then
+ local next = getnext(disc)
+ if replace then
+ if next then
+ local tail = find_node_tail(replace)
+ setfield(tail,"next",next)
+ setfield(next,"prev",tail)
+ end
+ return replace, replace
+ elseif next then
+ return next, next
+ else
+ return -- maybe warning
+ end
+ else
+ local next = getnext(disc)
+ local prev = getprev(disc)
+ if replace then
+ local tail = find_node_tail(replace)
+ if next then
+ setfield(tail,"next",next)
+ setfield(next,"prev",tail)
+ end
+ setfield(prev,"next",replace)
+ setfield(replace,"prev",prev)
+ return head, replace
+ else
+ if next then
+ setfield(next,"prev",prev)
+ end
+ setfield(prev,"next",next)
+ return head, next
+ end
+ end
+end
+local function appenddisc(disc,list)
+ local post = getfield(disc,"post")
+ local replace = getfield(disc,"replace")
+ local phead = list
+ local rhead = copy_node_list(list)
+ local ptail = find_node_tail(post)
+ local rtail = find_node_tail(replace)
+ if post then
+ setfield(ptail,"next",phead)
+ setfield(phead,"prev",ptail)
+ else
+ setfield(disc,"post",phead)
+ end
+ if replace then
+ setfield(rtail,"next",rhead)
+ setfield(rhead,"prev",rtail)
+ else
+ setfield(disc,"replace",rhead)
+ end
+end
-- start is a mark and we need to keep that one
@@ -416,8 +504,8 @@ end
-- iteration this becomes a KAF-LAM-ALEF with a SHADDA on the second and a FATHA on the
-- third component.
-local function getcomponentindex(start)
- if getid(start) ~= glyph_code then
+local function getcomponentindex(start) -- we could store this offset in the glyph (nofcomponents)
+ if getid(start) ~= glyph_code then -- and then get rid of all components
return 0
elseif getsubtype(start) == ligature_code then
local i = 0
@@ -434,16 +522,28 @@ local function getcomponentindex(start)
end
end
--- eventually we will do positioning in an other way (needs addional w/h/d fields)
+local a_noligature = attributes.private("noligature")
local function toligature(kind,lookupname,head,start,stop,char,markflag,discfound) -- brr head
+ if getattr(start,a_noligature) == 1 then
+ -- so we can do: e\noligature{ff}e e\noligature{f}fie (we only look at the first)
+ return head, start
+ end
if start == stop and getchar(start) == char then
resetinjection(start)
setfield(start,"char",char)
return head, start
end
+ -- needs testing (side effects):
+ local components = getfield(start,"components")
+ if components then
+ -- we get a double free .. needs checking
+ -- flush_node_list(components)
+ end
+ --
local prev = getprev(start)
local next = getnext(stop)
+ local comp = start
setfield(start,"prev",nil)
setfield(stop,"next",nil)
local base = copy_glyph(start)
@@ -453,15 +553,15 @@ local function toligature(kind,lookupname,head,start,stop,char,markflag,discfoun
resetinjection(base)
setfield(base,"char",char)
setfield(base,"subtype",ligature_code)
- setfield(base,"components",start) -- start can have components
+ setfield(base,"components",comp) -- start can have components ... do we need to flush?
if prev then
setfield(prev,"next",base)
end
if next then
setfield(next,"prev",base)
end
- setfield(base,"next",next)
setfield(base,"prev",prev)
+ setfield(base,"next",next)
if not discfound then
local deletemarks = markflag ~= "mark"
local components = start
@@ -480,7 +580,9 @@ local function toligature(kind,lookupname,head,start,stop,char,markflag,discfoun
if trace_marks then
logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),getligaindex(start))
end
- head, current = insert_node_after(head,current,copy_node(start)) -- unlikely that mark has components
+ local n = copy_node(start)
+ copyinjection(n,start)
+ head, current = insert_node_after(head,current,n) -- unlikely that mark has components
elseif trace_marks then
logwarning("%s: delete mark %s",pref(kind,lookupname),gref(char))
end
@@ -501,17 +603,85 @@ local function toligature(kind,lookupname,head,start,stop,char,markflag,discfoun
end
start = getnext(start)
end
+ else
+ -- discfound ... forget about marks .. probably no scripts that hyphenate and have marks
+ local discprev = getfield(discfound,"prev")
+ local discnext = getfield(discfound,"next")
+ if discprev and discnext then
+ -- we assume normalization in context, and don't care about generic ... especially
+ -- \- can give problems as there we can have a negative char but that won't match
+ -- anyway
+ local pre = getfield(discfound,"pre")
+ local post = getfield(discfound,"post")
+ local replace = getfield(discfound,"replace")
+ if not replace then -- todo: signal simple hyphen
+ local prev = getfield(base,"prev")
+ local copied = copy_node_list(comp)
+ setfield(discnext,"prev",nil) -- also blocks funny assignments
+ setfield(discprev,"next",nil) -- also blocks funny assignments
+ if pre then
+ setfield(discprev,"next",pre)
+ setfield(pre,"prev",discprev)
+ end
+ pre = comp
+ if post then
+ local tail = find_node_tail(post)
+ setfield(tail,"next",discnext)
+ setfield(discnext,"prev",tail)
+ setfield(post,"prev",nil)
+ else
+ post = discnext
+ end
+ setfield(prev,"next",discfound)
+ setfield(discfound,"prev",prev)
+ setfield(discfound,"next",next)
+ setfield(next,"prev",discfound)
+ setfield(base,"next",nil)
+ setfield(base,"prev",nil)
+ setfield(base,"components",copied)
+ setfield(discfound,"pre",pre)
+ setfield(discfound,"post",post)
+ setfield(discfound,"replace",base)
+ setfield(discfound,"subtype",discretionary_code)
+ base = prev -- restart
+ end
+ end
end
return head, base
end
-function handlers.gsub_single(head,start,kind,lookupname,replacement)
- if trace_singles then
- logprocess("%s: replacing %s by single %s",pref(kind,lookupname),gref(getchar(start)),gref(replacement))
+local function multiple_glyphs(head,start,multiple,ignoremarks)
+ local nofmultiples = #multiple
+ if nofmultiples > 0 then
+ resetinjection(start)
+ setfield(start,"char",multiple[1])
+ if nofmultiples > 1 then
+ local sn = getnext(start)
+ for k=2,nofmultiples do -- todo: use insert_node
+-- untested:
+--
+-- while ignoremarks and marks[getchar(sn)] then
+-- local sn = getnext(sn)
+-- end
+ local n = copy_node(start) -- ignore components
+ resetinjection(n)
+ setfield(n,"char",multiple[k])
+ setfield(n,"prev",start)
+ setfield(n,"next",sn)
+ if sn then
+ setfield(sn,"prev",n)
+ end
+ setfield(start,"next",n)
+ start = n
+ end
+ end
+ return head, start, true
+ else
+ if trace_multiples then
+ logprocess("no multiple for %s",gref(getchar(start)))
+ end
+ return head, start, false
end
- resetinjection(start)
- setfield(start,"char",replacement)
- return head, start, true
end
local function get_alternative_glyph(start,alternatives,value,trace_alternatives)
@@ -546,38 +716,15 @@ local function get_alternative_glyph(start,alternatives,value,trace_alternatives
end
end
-local function multiple_glyphs(head,start,multiple,ignoremarks)
- local nofmultiples = #multiple
- if nofmultiples > 0 then
- resetinjection(start)
- setfield(start,"char",multiple[1])
- if nofmultiples > 1 then
- local sn = getnext(start)
- for k=2,nofmultiples do -- todo: use insert_node
--- untested:
---
--- while ignoremarks and marks[getchar(sn)] then
--- local sn = getnext(sn)
--- end
- local n = copy_node(start) -- ignore components
- resetinjection(n)
- setfield(n,"char",multiple[k])
- setfield(n,"next",sn)
- setfield(n,"prev",start)
- if sn then
- setfield(sn,"prev",n)
- end
- setfield(start,"next",n)
- start = n
- end
- end
- return head, start, true
- else
- if trace_multiples then
- logprocess("no multiple for %s",gref(getchar(start)))
- end
- return head, start, false
+-- handlers
+
+function handlers.gsub_single(head,start,kind,lookupname,replacement)
+ if trace_singles then
+ logprocess("%s: replacing %s by single %s",pref(kind,lookupname),gref(getchar(start)),gref(replacement))
end
+ resetinjection(start)
+ setfield(start,"char",replacement)
+ return head, start, true
end
function handlers.gsub_alternate(head,start,kind,lookupname,alternative,sequence)
@@ -605,7 +752,7 @@ function handlers.gsub_multiple(head,start,kind,lookupname,multiple,sequence)
end
function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
- local s, stop, discfound = getnext(start), nil, false
+ local s, stop = getnext(start), nil
local startchar = getchar(start)
if marks[startchar] then
while s do
@@ -633,24 +780,30 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
else
head, start = markstoligature(kind,lookupname,head,start,stop,lig)
end
- return head, start, true
+ return head, start, true, false
else
-- ok, goto next lookup
end
end
else
- local skipmark = sequence.flags[1]
+ local skipmark = sequence.flags[1]
+ local discfound = false
+ local lastdisc = nil
while s do
local id = getid(s)
- if id == glyph_code and getsubtype(s)<256 then
- if getfont(s) == currentfont then
+ if id == glyph_code and getsubtype(s)<256 then -- not needed
+ if getfont(s) == currentfont then -- also not needed only when mark
local char = getchar(s)
if skipmark and marks[char] then
s = getnext(s)
- else
- local lg = ligature[char]
+ else -- ligature is a tree
+ local lg = ligature[char] -- can there be multiple in a row? maybe in a bad font
if lg then
- stop = s
+ if not discfound and lastdisc then
+ discfound = lastdisc
+ lastdisc = nil
+ end
+ stop = s -- needed for fake so outside then
ligature = lg
s = getnext(s)
else
@@ -661,13 +814,13 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
break
end
elseif id == disc_code then
- discfound = true
+ lastdisc = s
s = getnext(s)
else
break
end
end
- local lig = ligature.ligature
+ local lig = ligature.ligature -- can't we get rid of this .ligature?
if lig then
if stop then
if trace_ligatures then
@@ -685,14 +838,88 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
logprocess("%s: replacing %s by (no real) ligature %s case 3",pref(kind,lookupname),gref(startchar),gref(lig))
end
end
- return head, start, true
+ return head, start, true, discfound
else
- -- weird but happens
+ -- weird but happens, pseudo ligatures ... just the components
end
end
+ return head, start, false, discfound
+end
+
+function handlers.gpos_single(head,start,kind,lookupname,kerns,sequence,injection)
+ local startchar = getchar(start)
+ local dx, dy, w, h = setpair(start,tfmdata.parameters.factor,rlmode,sequence.flags[4],kerns,injection) -- ,characters[startchar])
+ if trace_kerns then
+ logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),dx,dy,w,h)
+ end
return head, start, false
end
+function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence,lookuphash,i,injection)
+ -- todo: kerns in disc nodes: pre, post, replace -> loop over disc too
+ -- todo: kerns in components of ligatures
+ local snext = getnext(start)
+ if not snext then
+ return head, start, false
+ else
+ local prev = start
+ local done = false
+ local factor = tfmdata.parameters.factor
+ local lookuptype = lookuptypes[lookupname]
+ while snext and getid(snext) == glyph_code and getfont(snext) == currentfont and getsubtype(snext)<256 do
+ local nextchar = getchar(snext)
+ local krn = kerns[nextchar]
+ if not krn and marks[nextchar] then
+ prev = snext
+ snext = getnext(snext)
+ else
+ if not krn then
+ -- skip
+ elseif type(krn) == "table" then
+ if lookuptype == "pair" then -- probably not needed
+ local a, b = krn[2], krn[3]
+ if a and #a > 0 then
+ local x, y, w, h = setpair(start,factor,rlmode,sequence.flags[4],a,injection) -- characters[startchar])
+ if trace_kerns then
+ local startchar = getchar(start)
+ logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h)
+ end
+ end
+ if b and #b > 0 then
+ local x, y, w, h = setpair(snext,factor,rlmode,sequence.flags[4],b,injection) -- characters[nextchar])
+ if trace_kerns then
+ local startchar = getchar(start)
+ logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h)
+ end
+ end
+ else -- wrong ... position has different entries
+ report_process("%s: check this out (old kern stuff)",pref(kind,lookupname))
+ -- local a, b = krn[2], krn[6]
+ -- if a and a ~= 0 then
+ -- local k = setkern(snext,factor,rlmode,a)
+ -- if trace_kerns then
+ -- logprocess("%s: inserting first kern %s between %s and %s",pref(kind,lookupname),k,gref(getchar(prev)),gref(nextchar))
+ -- end
+ -- end
+ -- if b and b ~= 0 then
+ -- logwarning("%s: ignoring second kern xoff %s",pref(kind,lookupname),b*factor)
+ -- end
+ end
+ done = true
+ elseif krn ~= 0 then
+ local k = setkern(snext,factor,rlmode,krn,injection)
+ if trace_kerns then
+ logprocess("%s: inserting kern %s between %s and %s",pref(kind,lookupname),k,gref(getchar(prev)),gref(nextchar)) -- prev?
+ end
+ done = true
+ end
+ break
+ end
+ end
+ return head, start, done
+ end
+end
+
--[[ldx--
We get hits on a mark, but we're not sure if the it has to be applied so
we need to explicitly test for basechar, baselig and basemark entries.
@@ -855,7 +1082,7 @@ function handlers.gpos_mark2mark(head,start,kind,lookupname,markanchors,sequence
if al[anchor] then
local ma = markanchors[anchor]
if ma then
- local dx, dy, bound = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,characters[basechar])
+ local dx, dy, bound = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,characters[basechar],true)
if trace_marks then
logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)",
pref(kind,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy)
@@ -938,85 +1165,11 @@ function handlers.gpos_cursive(head,start,kind,lookupname,exitanchors,sequence)
end
end
-function handlers.gpos_single(head,start,kind,lookupname,kerns,sequence)
- local startchar = getchar(start)
- local dx, dy, w, h = setpair(start,tfmdata.parameters.factor,rlmode,sequence.flags[4],kerns,characters[startchar])
- if trace_kerns then
- logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),dx,dy,w,h)
- end
- return head, start, false
-end
-
-function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence)
- -- todo: kerns in disc nodes: pre, post, replace -> loop over disc too
- -- todo: kerns in components of ligatures
- local snext = getnext(start)
- if not snext then
- return head, start, false
- else
- local prev, done = start, false
- local factor = tfmdata.parameters.factor
- local lookuptype = lookuptypes[lookupname]
- while snext and getid(snext) == glyph_code and getfont(snext) == currentfont and getsubtype(snext)<256 do
- local nextchar = getchar(snext)
- local krn = kerns[nextchar]
- if not krn and marks[nextchar] then
- prev = snext
- snext = getnext(snext)
- else
- if not krn then
- -- skip
- elseif type(krn) == "table" then
- if lookuptype == "pair" then -- probably not needed
- local a, b = krn[2], krn[3]
- if a and #a > 0 then
- local startchar = getchar(start)
- local x, y, w, h = setpair(start,factor,rlmode,sequence.flags[4],a,characters[startchar])
- if trace_kerns then
- logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h)
- end
- end
- if b and #b > 0 then
- local startchar = getchar(start)
- local x, y, w, h = setpair(snext,factor,rlmode,sequence.flags[4],b,characters[nextchar])
- if trace_kerns then
- logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h)
- end
- end
- else -- wrong ... position has different entries
- report_process("%s: check this out (old kern stuff)",pref(kind,lookupname))
- -- local a, b = krn[2], krn[6]
- -- if a and a ~= 0 then
- -- local k = setkern(snext,factor,rlmode,a)
- -- if trace_kerns then
- -- logprocess("%s: inserting first kern %s between %s and %s",pref(kind,lookupname),k,gref(getchar(prev)),gref(nextchar))
- -- end
- -- end
- -- if b and b ~= 0 then
- -- logwarning("%s: ignoring second kern xoff %s",pref(kind,lookupname),b*factor)
- -- end
- end
- done = true
- elseif krn ~= 0 then
- local k = setkern(snext,factor,rlmode,krn)
- if trace_kerns then
- logprocess("%s: inserting kern %s between %s and %s",pref(kind,lookupname),k,gref(getchar(prev)),gref(nextchar))
- end
- done = true
- end
- break
- end
- end
- return head, start, done
- end
-end
-
--[[ldx--
I will implement multiple chain replacements once I run into a font that uses
it. It's not that complex to handle.
--ldx]]--
-local chainmores = { }
local chainprocs = { }
local function logprocess(...)
@@ -1045,11 +1198,6 @@ function chainprocs.chainsub(head,start,stop,kind,chainname,currentcontext,looku
return head, start, false
end
-function chainmores.chainsub(head,start,stop,kind,chainname,currentcontext,lookuphash,lookuplist,chainlookupname,n)
- logprocess("%s: a direct call to chainsub cannot happen",cref(kind,chainname,chainlookupname))
- return head, start, false
-end
-
-- The reversesub is a special case, which is why we need to store the replacements
-- in a bit weird way. There is no lookup and the replacement comes from the lookup
-- itself. It is meant mostly for dealing with Urdu.
@@ -1116,8 +1264,7 @@ as less as needed but that would also make the code even more messy.
-- end
--[[ldx--
-Here we replace start by a single variant, First we delete the rest of the
-match.
+Here we replace start by a single variant.
--ldx]]--
function chainprocs.gsub_single(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex)
@@ -1125,7 +1272,7 @@ function chainprocs.gsub_single(head,start,stop,kind,chainname,currentcontext,lo
local current = start
local subtables = currentlookup.subtables
if #subtables > 1 then
- logwarning("todo: check if we need to loop over the replacements: %s",concat(subtables," "))
+ logwarning("todo: check if we need to loop over the replacements: % t",subtables)
end
while current do
if getid(current) == glyph_code then
@@ -1160,11 +1307,8 @@ function chainprocs.gsub_single(head,start,stop,kind,chainname,currentcontext,lo
return head, start, false
end
-chainmores.gsub_single = chainprocs.gsub_single
-
--[[ldx--
-Here we replace start by a sequence of new glyphs. First we delete the rest of
-the match.
+Here we replace start by a sequence of new glyphs.
--ldx]]--
function chainprocs.gsub_multiple(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
@@ -1193,8 +1337,6 @@ function chainprocs.gsub_multiple(head,start,stop,kind,chainname,currentcontext,
return head, start, false
end
-chainmores.gsub_multiple = chainprocs.gsub_multiple
-
--[[ldx--
Here we replace start by new glyph. First we delete the rest of the match.
--ldx]]--
@@ -1249,8 +1391,6 @@ function chainprocs.gsub_alternate(head,start,stop,kind,chainname,currentcontext
return head, start, false
end
-chainmores.gsub_alternate = chainprocs.gsub_alternate
-
--[[ldx--
When we replace ligatures we use a helper that handles the marks. I might change
this function (move code inline and handle the marks by a separate function). We
@@ -1276,13 +1416,19 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,
local s = getnext(start)
local discfound = false
local last = stop
- local nofreplacements = 0
+ local nofreplacements = 1
local skipmark = currentlookup.flags[1]
while s do
local id = getid(s)
if id == disc_code then
- s = getnext(s)
- discfound = true
+ if not discfound then
+ discfound = s
+ end
+ if s == stop then
+ break -- okay? or before the disc
+ else
+ s = getnext(s)
+ end
else
local schar = getchar(s)
if skipmark and marks[schar] then -- marks
@@ -1315,7 +1461,7 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,
end
end
head, start = toligature(kind,lookupname,head,start,stop,l2,currentlookup.flags[1],discfound)
- return head, start, true, nofreplacements
+ return head, start, true, nofreplacements, discfound
elseif trace_bugs then
if start == stop then
logwarning("%s: replacing character %s by ligature fails",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar))
@@ -1325,11 +1471,97 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,
end
end
end
- return head, start, false, 0
+ return head, start, false, 0, false
+end
+
+function chainprocs.gpos_single(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence)
+ -- untested .. needs checking for the new model
+ local startchar = getchar(start)
+ local subtables = currentlookup.subtables
+ local lookupname = subtables[1]
+ local kerns = lookuphash[lookupname]
+ if kerns then
+ kerns = kerns[startchar] -- needed ?
+ if kerns then
+ local dx, dy, w, h = setpair(start,tfmdata.parameters.factor,rlmode,sequence.flags[4],kerns) -- ,characters[startchar])
+ if trace_kerns then
+ logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),dx,dy,w,h)
+ end
+ end
+ end
+ return head, start, false
+end
+
+function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence)
+ local snext = getnext(start)
+ if snext then
+ local startchar = getchar(start)
+ local subtables = currentlookup.subtables
+ local lookupname = subtables[1]
+ local kerns = lookuphash[lookupname]
+ if kerns then
+ kerns = kerns[startchar]
+ if kerns then
+ local lookuptype = lookuptypes[lookupname]
+ local prev, done = start, false
+ local factor = tfmdata.parameters.factor
+ while snext and getid(snext) == glyph_code and getfont(snext) == currentfont and getsubtype(snext)<256 do
+ local nextchar = getchar(snext)
+ local krn = kerns[nextchar]
+ if not krn and marks[nextchar] then
+ prev = snext
+ snext = getnext(snext)
+ else
+ if not krn then
+ -- skip
+ elseif type(krn) == "table" then
+ if lookuptype == "pair" then
+ local a, b = krn[2], krn[3]
+ if a and #a > 0 then
+ local startchar = getchar(start)
+ local x, y, w, h = setpair(start,factor,rlmode,sequence.flags[4],a) -- ,characters[startchar])
+ if trace_kerns then
+ logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h)
+ end
+ end
+ if b and #b > 0 then
+ local startchar = getchar(start)
+ local x, y, w, h = setpair(snext,factor,rlmode,sequence.flags[4],b) -- ,characters[nextchar])
+ if trace_kerns then
+ logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h)
+ end
+ end
+ else
+ report_process("%s: check this out (old kern stuff)",cref(kind,chainname,chainlookupname))
+ -- local a, b = krn[2], krn[6]
+ -- if a and a ~= 0 then
+ -- local k = setkern(snext,factor,rlmode,a)
+ -- if trace_kerns then
+ -- logprocess("%s: inserting first kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(getchar(prev)),gref(nextchar))
+ -- end
+ -- end
+ -- if b and b ~= 0 then
+ -- logwarning("%s: ignoring second kern xoff %s",cref(kind,chainname,chainlookupname),b*factor)
+ -- end
+ end
+ done = true
+ elseif krn ~= 0 then
+ local k = setkern(snext,factor,rlmode,krn)
+ if trace_kerns then
+ logprocess("%s: inserting kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(getchar(prev)),gref(nextchar))
+ end
+ done = true
+ end
+ break
+ end
+ end
+ return head, start, done
+ end
+ end
+ end
+ return head, start, false
end
-chainmores.gsub_ligature = chainprocs.gsub_ligature
-
function chainprocs.gpos_mark2base(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
local markchar = getchar(start)
if marks[markchar] then
@@ -1497,7 +1729,7 @@ function chainprocs.gpos_mark2mark(head,start,stop,kind,chainname,currentcontext
if al[anchor] then
local ma = markanchors[anchor]
if ma then
- local dx, dy, bound = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,characters[basechar])
+ local dx, dy, bound = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,characters[basechar],true)
if trace_marks then
logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)",
cref(kind,chainname,chainlookupname,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy)
@@ -1588,133 +1820,346 @@ function chainprocs.gpos_cursive(head,start,stop,kind,chainname,currentcontext,l
return head, start, false
end
-function chainprocs.gpos_single(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence)
- -- untested .. needs checking for the new model
- local startchar = getchar(start)
- local subtables = currentlookup.subtables
- local lookupname = subtables[1]
- local kerns = lookuphash[lookupname]
- if kerns then
- kerns = kerns[startchar] -- needed ?
- if kerns then
- local dx, dy, w, h = setpair(start,tfmdata.parameters.factor,rlmode,sequence.flags[4],kerns,characters[startchar])
- if trace_kerns then
- logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),dx,dy,w,h)
+-- what pointer to return, spec says stop
+-- to be discussed ... is bidi changer a space?
+-- elseif char == zwnj and sequence[n][32] then -- brrr
+
+-- somehow l or f is global
+-- we don't need to pass the currentcontext, saves a bit
+-- make a slow variant then can be activated but with more tracing
+
+local function show_skip(kind,chainname,char,ck,class)
+ if ck[9] then
+ logwarning("%s: skipping char %s, class %a, rule %a, lookuptype %a, %a => %a",cref(kind,chainname),gref(char),class,ck[1],ck[2],ck[9],ck[10])
+ else
+ logwarning("%s: skipping char %s, class %a, rule %a, lookuptype %a",cref(kind,chainname),gref(char),class,ck[1],ck[2])
+ end
+end
+
+-- A previous version had disc collapsing code in the (single sub) handler plus some
+-- checking in the main loop, but that left the pre/post sequences undone. The best
+-- solution is to add some checking there and backtrack when a replace/post matches
+-- but it takes a bit of work to figure out an efficient way (this is what the sweep*
+-- names refer to). I might look into that variant one day again as it can replace
+-- some other code too. In that approach we can have a special version for gub and pos
+-- which gains some speed. This method does the test and passes info to the handlers
+-- (sweepnode, sweepmode, sweepprev, sweepnext, etc). Here collapsing is handled in the
+-- main loop which also makes code elsewhere simpler (i.e. no need for the other special
+-- runners and disc code in ligature building). I also experimented with pushing preceding
+-- glyphs sequences in the replace/pre fields beforehand which saves checking afterwards
+-- but at the cost of duplicate glyphs (memory) but it's too much overhead (runtime).
+--
+-- In the meantime Kai had moved the code from the single chain into a more general handler
+-- and this one (renamed to chaindisk) is used now. I optimized the code a bit and brought
+-- it in sycn with the other code. Hopefully I didn't introduce errors. Note: this somewhat
+-- complex approach is meant for fonts that implement (for instance) ligatures by character
+-- replacement which to some extend is not that suitable for hyphenation. I also use some
+-- helpers. This method passes some states but reparses the list. There is room for a bit of
+-- speed up but that will be done in the context version. (In fact a partial rewrite of all
+-- code can bring some more efficientry.)
+--
+-- I didn't test it with extremes but successive disc nodes still can give issues but in
+-- order to handle that we need more complex code which also slows down even more. The main
+-- loop variant could deal with that: test, collapse, backtrack.
+
+local function chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,chainindex,sequence,chainproc)
+
+ if not start then
+ return head, start, false
+ end
+
+ local startishead = start == head
+ local seq = ck[3]
+ local f = ck[4]
+ local l = ck[5]
+ local s = #seq
+ local done = false
+ local sweepnode = sweepnode
+ local sweeptype = sweeptype
+ local sweepoverflow = false
+ local checkdisc = getprev(head) -- hm bad name head
+ local keepdisc = not sweepnode
+ local lookaheaddisc = nil
+ local backtrackdisc = nil
+ local current = start
+ local last = start
+ local prev = getprev(start)
+
+ -- fishy: so we can overflow and then go on in the sweep?
+
+ local i = f
+ while i <= l do
+ local id = getid(current)
+ if id == glyph_code then
+ i = i + 1
+ last = current
+ current = getnext(current)
+ elseif id == disc_code then
+ if keepdisc then
+ keepdisc = false
+ if notmatchpre[current] ~= notmatchreplace[current] then
+ lookaheaddisc = current
+ end
+ local replace = getfield(current,"replace")
+ while replace and i <= l do
+ if getid(replace) == glyph_code then
+ i = i + 1
+ end
+ replace = getnext(replace)
+ end
+ last = current
+ current = getnext(c)
+ else
+ head, current = flattendisk(head,current)
+ end
+ else
+ last = current
+ current = getnext(current)
+ end
+ if current then
+ -- go on
+ elseif sweepoverflow then
+ -- we already are folling up on sweepnode
+ break
+ elseif sweeptype == "post" or sweeptype == "replace" then
+ current = getnext(sweepnode)
+ if current then
+ sweeptype = nil
+ sweepoverflow = true
+ else
+ break
end
end
end
- return head, start, false
-end
-chainmores.gpos_single = chainprocs.gpos_single -- okay?
+ if sweepoverflow then
+ local prev = current and getprev(current)
+ if not current or prev ~= sweepnode then
+ local head = getnext(sweepnode)
+ local tail = nil
+ if prev then
+ tail = prev
+ setfield(current,"prev",sweepnode)
+ else
+ tail = find_node_tail(head)
+ end
+ setfield(sweepnode,"next",current)
+ setfield(head,"prev",nil)
+ setfield(tail,"next",nil)
+ appenddisc(sweepnode,head)
+ end
+ end
--- when machines become faster i will make a shared function
+ if l < s then
+ local i = l
+ local t = sweeptype == "post" or sweeptype == "replace"
+ while current and i < s do
+ local id = getid(current)
+ if id == glyph_code then
+ i = i + 1
+ current = getnext(current)
+ elseif id == disc_code then
+ if keepdisc then
+ keepdisc = false
+ if notmatchpre[current] ~= notmatchreplace[current] then
+ lookaheaddisc = current
+ end
+ local replace = getfield(c,"replace")
+ while replace and i < s do
+ if getid(replace) == glyph_code then
+ i = i + 1
+ end
+ replace = getnext(replace)
+ end
+ current = getnext(current)
+ elseif notmatchpre[current] ~= notmatchreplace[current] then
+ head, current = flattendisk(head,current)
+ else
+ current = getnext(current) -- HH
+ end
+ else
+ current = getnext(current)
+ end
+ if not current and t then
+ current = getnext(sweepnode)
+ if current then
+ sweeptype = nil
+ end
+ end
+ end
+ end
-function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence)
- local snext = getnext(start)
- if snext then
- local startchar = getchar(start)
- local subtables = currentlookup.subtables
- local lookupname = subtables[1]
- local kerns = lookuphash[lookupname]
- if kerns then
- kerns = kerns[startchar]
- if kerns then
- local lookuptype = lookuptypes[lookupname]
- local prev, done = start, false
- local factor = tfmdata.parameters.factor
- while snext and getid(snext) == glyph_code and getfont(snext) == currentfont and getsubtype(snext)<256 do
- local nextchar = getchar(snext)
- local krn = kerns[nextchar]
- if not krn and marks[nextchar] then
- prev = snext
- snext = getnext(snext)
- else
- if not krn then
- -- skip
- elseif type(krn) == "table" then
- if lookuptype == "pair" then
- local a, b = krn[2], krn[3]
- if a and #a > 0 then
- local startchar = getchar(start)
- local x, y, w, h = setpair(start,factor,rlmode,sequence.flags[4],a,characters[startchar])
- if trace_kerns then
- logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h)
- end
- end
- if b and #b > 0 then
- local startchar = getchar(start)
- local x, y, w, h = setpair(snext,factor,rlmode,sequence.flags[4],b,characters[nextchar])
- if trace_kerns then
- logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h)
- end
- end
- else
- report_process("%s: check this out (old kern stuff)",cref(kind,chainname,chainlookupname))
- local a, b = krn[2], krn[6]
- if a and a ~= 0 then
- local k = setkern(snext,factor,rlmode,a)
- if trace_kerns then
- logprocess("%s: inserting first kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(getchar(prev)),gref(nextchar))
- end
- end
- if b and b ~= 0 then
- logwarning("%s: ignoring second kern xoff %s",cref(kind,chainname,chainlookupname),b*factor)
- end
- end
- done = true
- elseif krn ~= 0 then
- local k = setkern(snext,factor,rlmode,krn)
- if trace_kerns then
- logprocess("%s: inserting kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(getchar(prev)),gref(nextchar))
- end
- done = true
+ if f > 1 then
+ local current = prev
+ local i = f
+ local t = sweeptype == "pre" or sweeptype == "replace"
+ if not current and t and current == checkdisk then
+ current = getprev(sweepnode)
+ end
+ while current and i > 1 do -- missing getprev added / moved outside
+ local id = getid(current)
+ if id == glyph_code then
+ i = i - 1
+ elseif id == disc_code then
+ if keepdisc then
+ keepdisc = false
+ if notmatchpost[current] ~= notmatchreplace[current] then
+ backtrackdisc = current
+ end
+ local replace = getfield(current,"replace")
+ while replace and i > 1 do
+ if getid(replace) == glyph_code then
+ i = i - 1
end
- break
+ replace = getnext(replace)
end
+ elseif notmatchpost[current] ~= notmatchreplace[current] then
+ head, current = flattendisk(head,current)
end
- return head, start, done
+ end
+ current = getprev(current)
+ if t and current == checkdisk then
+ current = getprev(sweepnode)
end
end
end
- return head, start, false
-end
-chainmores.gpos_pair = chainprocs.gpos_pair -- okay?
+ local ok = false
+ if lookaheaddisc then
--- what pointer to return, spec says stop
--- to be discussed ... is bidi changer a space?
--- elseif char == zwnj and sequence[n][32] then -- brrr
+ local cf = start
+ local cl = getprev(lookaheaddisc)
+ local cprev = getprev(start)
+ local insertedmarks = 0
--- somehow l or f is global
--- we don't need to pass the currentcontext, saves a bit
--- make a slow variant then can be activated but with more tracing
+ while cprev and getid(cf) == glyph_code and getfont(cf) == currentfont and getsubtype(cf) < 256 and marks[getchar(cf)] do
+ insertedmarks = insertedmarks + 1
+ cf = cprev
+ startishead = cf == head
+ cprev = getprev(cprev)
+ end
+
+ setfield(lookaheaddisc,"prev",cprev)
+ if cprev then
+ setfield(cprev,"next",lookaheaddisc)
+ end
+ setfield(cf,"prev",nil)
+ setfield(cl,"next",nil)
+ if startishead then
+ head = lookaheaddisc
+ end
+
+ local replace = getfield(lookaheaddisc,"replace")
+ local pre = getfield(lookaheaddisc,"pre")
+ local new = copy_node_list(cf)
+ local cnew = new
+ for i=1,insertedmarks do
+ cnew = getnext(cnew)
+ end
+ local clast = cnew
+ for i=f,l do
+ clast = getnext(clast)
+ end
+ if not notmatchpre[lookaheaddisc] then
+ cf, start, ok = chainproc(cf,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ end
+ if not notmatchreplace[lookaheaddisc] then
+ new, cnew, ok = chainproc(new,cnew,clast,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ end
+ if pre then
+ setfield(cl,"next",pre)
+ setfield(pre,"prev",cl)
+ end
+ if replace then
+ local tail = find_node_tail(new)
+ setfield(tail,"next",replace)
+ setfield(replace,"prev",tail)
+ end
+ setfield(lookaheaddisc,"pre",cf) -- also updates tail
+ setfield(lookaheaddisc,"replace",new) -- also updates tail
+
+ start = getprev(lookaheaddisc)
+ sweephead[cf] = getnext(clast)
+ sweephead[new] = getnext(last)
+
+ elseif backtrackdisc then
+
+ local cf = getnext(backtrackdisc)
+ local cl = start
+ local cnext = getnext(start)
+ local insertedmarks = 0
+
+ while cnext and getid(cnext) == glyph_code and getfont(cnext) == currentfont and getsubtype(cnext) < 256 and marks[getchar(cnext)] do
+ insertedmarks = insertedmarks + 1
+ cl = cnext
+ cnext = getnext(cnext)
+ end
+ if cnext then
+ setfield(cnext,"prev",backtrackdisc)
+ end
+ setfield(backtrackdisc,"next",cnext)
+ setfield(cf,"prev",nil)
+ setfield(cl,"next",nil)
+ local replace = getfield(backtrackdisc,"replace")
+ local post = getfield(backtrackdisc,"post")
+ local new = copy_node_list(cf)
+ local cnew = find_node_tail(new)
+ for i=1,insertedmarks do
+ cnew = getprev(cnew)
+ end
+ local clast = cnew
+ for i=f,l do
+ clast = getnext(clast)
+ end
+ if not notmatchpost[backtrackdisc] then
+ cf, start, ok = chainproc(cf,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ end
+ if not notmatchreplace[backtrackdisc] then
+ new, cnew, ok = chainproc(new,cnew,clast,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ end
+ if post then
+ local tail = find_node_tail(post)
+ setfield(tail,"next",cf)
+ setfield(cf,"prev",tail)
+ else
+ post = cf
+ end
+ if replace then
+ local tail = find_node_tail(replace)
+ setfield(tail,"next",new)
+ setfield(new,"prev",tail)
+ else
+ replace = new
+ end
+ setfield(backtrackdisc,"post",post) -- also updates tail
+ setfield(backtrackdisc,"replace",replace) -- also updates tail
+ start = getprev(backtrackdisc)
+ sweephead[post] = getnext(clast)
+ sweephead[replace] = getnext(last)
-local function show_skip(kind,chainname,char,ck,class)
- if ck[9] then
- logwarning("%s: skipping char %s, class %a, rule %a, lookuptype %a, %a => %a",cref(kind,chainname),gref(char),class,ck[1],ck[2],ck[9],ck[10])
else
- logwarning("%s: skipping char %s, class %a, rule %a, lookuptype %a",cref(kind,chainname),gref(char),class,ck[1],ck[2])
- end
-end
-local quit_on_no_replacement = true
+ head, start, ok = chainproc(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
-directives.register("otf.chain.quitonnoreplacement",function(value) -- maybe per font
- quit_on_no_replacement = value
-end)
+ end
+
+ return head, start, ok
+end
local function normal_handle_contextchain(head,start,kind,chainname,contexts,sequence,lookuphash)
- -- local rule, lookuptype, sequence, f, l, lookups = ck[1], ck[2] ,ck[3], ck[4], ck[5], ck[6]
+ local sweepnode = sweepnode
+ local sweeptype = sweeptype
+ local diskseen = false
+ local checkdisc = getprev(head)
local flags = sequence.flags
local done = false
local skipmark = flags[1]
local skipligature = flags[2]
local skipbase = flags[3]
- local someskip = skipmark or skipligature or skipbase -- could be stored in flags for a fast test (hm, flags could be false !)
- local markclass = sequence.markclass -- todo, first we need a proper test
+ local markclass = sequence.markclass
local skipped = false
- for k=1,#contexts do
+
+ for k=1,#contexts do -- i've only seen ccmp having > 1 (e.g. dejavu)
local match = true
local current = start
local last = start
@@ -1728,7 +2173,8 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
else
-- maybe we need a better space check (maybe check for glue or category or combination)
-- we cannot optimize for n=2 because there can be disc nodes
- local f, l = ck[4], ck[5]
+ local f = ck[4]
+ local l = ck[5]
-- current match
if f == 1 and f == l then -- current only
-- already a hit
@@ -1738,9 +2184,14 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
if f == l then -- new, else last out of sync (f is > 1)
-- match = true
else
+ local discfound = nil
local n = f + 1
last = getnext(last)
while n <= l do
+ if not last and (sweeptype == "post" or sweeptype == "replace") then
+ last = getnext(sweepnode)
+ sweeptype = nil
+ end
if last then
local id = getid(last)
if id == glyph_code then
@@ -1748,7 +2199,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
local char = getchar(last)
local ccd = descriptions[char]
if ccd then
- local class = ccd.class
+ local class = ccd.class or "base"
if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then
skipped = true
if trace_skips then
@@ -1761,18 +2212,77 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
end
n = n + 1
else
- match = false
+ if discfound then
+ notmatchreplace[discfound] = true
+ match = not notmatchpre[discfound]
+ else
+ match = false
+ end
break
end
else
- match = false
+ if discfound then
+ notmatchreplace[discfound] = true
+ match = not notmatchpre[discfound]
+ else
+ match = false
+ end
break
end
else
- match = false
+ if discfound then
+ notmatchreplace[discfound] = true
+ match = not notmatchpre[discfound]
+ else
+ match = false
+ end
break
end
elseif id == disc_code then
+ diskseen = true
+ discfound = last
+ notmatchpre[last] = nil
+ notmatchpost[last] = true
+ notmatchreplace[last] = nil
+ local pre = getfield(last,"pre")
+ local replace = getfield(last,"replace")
+ if pre then
+ local n = n
+ while pre do
+ if seq[n][getchar(pre)] then
+ n = n + 1
+ pre = getnext(pre)
+ if n > l then
+ break
+ end
+ else
+ notmatchpre[last] = true
+ break
+ end
+ end
+ if n <= l then
+ notmatchpre[last] = true
+ end
+ else
+ notmatchpre[last] = true
+ end
+ if replace then
+ -- so far we never entered this branch
+ while replace do
+ if seq[n][getchar(replace)] then
+ n = n + 1
+ replace = getnext(replace)
+ if n > l then
+ break
+ end
+ else
+ notmatchreplace[last] = true
+ match = not notmatchpre[last]
+ break
+ end
+ end
+ match = not notmatchpre[last]
+ end
last = getnext(last)
else
match = false
@@ -1789,50 +2299,137 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
if match and f > 1 then
local prev = getprev(start)
if prev then
- local n = f-1
- while n >= 1 do
- if prev then
- local id = getid(prev)
- if id == glyph_code then
- if getfont(prev) == currentfont and getsubtype(prev)<256 then -- normal char
- local char = getchar(prev)
- local ccd = descriptions[char]
- if ccd then
- local class = ccd.class
- if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then
- skipped = true
- if trace_skips then
- show_skip(kind,chainname,char,ck,class)
+ if prev == checkdisc and (sweeptype == "pre" or sweeptype == "replace") then
+ prev = getprev(sweepnode)
+ -- sweeptype = nil
+ end
+ if prev then
+ local discfound = nil
+ local n = f - 1
+ while n >= 1 do
+ if prev then
+ local id = getid(prev)
+ if id == glyph_code then
+ if getfont(prev) == currentfont and getsubtype(prev)<256 then -- normal char
+ local char = getchar(prev)
+ local ccd = descriptions[char]
+ if ccd then
+ local class = ccd.class
+ if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then
+ skipped = true
+ if trace_skips then
+ show_skip(kind,chainname,char,ck,class)
+ end
+ elseif seq[n][char] then
+ n = n -1
+ else
+ if discfound then
+ notmatchreplace[discfound] = true
+ match = not notmatchpost[discfound]
+ else
+ match = false
+ end
+ break
end
- elseif seq[n][char] then
- n = n -1
else
- match = false
+ if discfound then
+ notmatchreplace[discfound] = true
+ match = not notmatchpost[discfound]
+ else
+ match = false
+ end
break
end
else
- match = false
+ if discfound then
+ notmatchreplace[discfound] = true
+ match = not notmatchpost[discfound]
+ else
+ match = false
+ end
break
end
+ elseif id == disc_code then
+ -- the special case: f i where i becomes dottless i ..
+ diskseen = true
+ discfound = prev
+ notmatchpre[prev] = true
+ notmatchpost[prev] = nil
+ notmatchreplace[prev] = nil
+ local pre = getfield(prev,"pre")
+ local post = getfield(prev,"post")
+ local replace = getfield(prev,"replace")
+ if pre ~= start and post ~= start and replace ~= start then
+ if post then
+ local n = n
+ local posttail = find_node_tail(post)
+ while posttail do
+ if seq[n][getchar(posttail)] then
+ n = n - 1
+ if posttail == post then
+ break
+ else
+ posttail = getprev(posttail)
+ if n < 1 then
+ break
+ end
+ end
+ else
+ notmatchpost[prev] = true
+ break
+ end
+ end
+ if n >= 1 then
+ notmatchpost[prev] = true
+ end
+ else
+ notmatchpost[prev] = true
+ end
+ if replace then
+ -- we seldom enter this branch (e.g. on brill efficient)
+ local replacetail = find_node_tail(replace)
+ while replacetail do
+ if seq[n][getchar(replacetail)] then
+ n = n - 1
+ if replacetail == replace then
+ break
+ else
+ replacetail = getprev(replacetail)
+ if n < 1 then
+ break
+ end
+ end
+ else
+ notmatchreplace[prev] = true
+ match = not notmatchpost[prev]
+ break
+ end
+ end
+ if not match then
+ break
+ end
+ else
+ -- skip 'm
+ end
+ else
+ -- skip 'm
+ end
+ elseif seq[n][32] then
+ n = n -1
else
match = false
break
end
- elseif id == disc_code then
- -- skip 'm
- elseif seq[n][32] then
- n = n -1
+ prev = getprev(prev)
+ elseif seq[n][32] then -- somewhat special, as zapfino can have many preceding spaces
+ n = n - 1
else
match = false
break
end
- prev = getprev(prev)
- elseif seq[n][32] then -- somewhat special, as zapfino can have many preceding spaces
- n = n -1
- else
- match = false
- break
end
+ else
+ match = false
end
else
match = false
@@ -1841,7 +2438,14 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
-- after
if match and s > l then
local current = last and getnext(last)
+ if not current then
+ if sweeptype == "post" or sweeptype == "replace" then
+ current = getnext(sweepnode)
+ -- sweeptype = nil
+ end
+ end
if current then
+ local discfound = nil
-- removed optimization for s-l == 1, we have to deal with marks anyway
local n = l + 1
while n <= s do
@@ -1861,19 +2465,81 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
elseif seq[n][char] then
n = n + 1
else
- match = false
+ if discfound then
+ notmatchreplace[discfound] = true
+ match = not notmatchpre[discfound]
+ else
+ match = false
+ end
break
end
+ else
+ if discfound then
+ notmatchreplace[discfound] = true
+ match = not notmatchpre[discfound]
+ else
+ match = false
+ end
+ break
+ end
+ else
+ if discfound then
+ notmatchreplace[discfound] = true
+ match = not notmatchpre[discfound]
else
match = false
+ end
+ break
+ end
+ elseif id == disc_code then
+ diskseen = true
+ discfound = current
+ notmatchpre[current] = nil
+ notmatchpost[current] = true
+ notmatchreplace[current] = nil
+ local pre = getfield(current,"pre")
+ local replace = getfield(current,"replace")
+ if pre then
+ local n = n
+ while pre do
+ if seq[n][getchar(pre)] then
+ n = n + 1
+ pre = getnext(pre)
+ if n > s then
+ break
+ end
+ else
+ notmatchpre[current] = true
+ break
+ end
+ end
+ if n <= s then
+ notmatchpre[current] = true
+ end
+ else
+ notmatchpre[current] = true
+ end
+ if replace then
+ -- so far we never entered this branch
+ while replace do
+ if seq[n][getchar(replace)] then
+ n = n + 1
+ replace = getnext(replace)
+ if n > s then
+ break
+ end
+ else
+ notmatchreplace[current] = true
+ match = notmatchpre[current]
+ break
+ end
+ end
+ if not match then
break
end
else
- match = false
- break
+ -- skip 'm
end
- elseif id == disc_code then
- -- skip 'm
elseif seq[n][32] then -- brrr
n = n + 1
else
@@ -1894,7 +2560,8 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
end
end
if match then
- -- ck == currentcontext
+ -- can lookups be of a different type ?
+ local diskchain = diskseen or sweepnode
if trace_contexts then
local rule, lookuptype, f, l = ck[1], ck[2], ck[4], ck[5]
local char = getchar(start)
@@ -1914,10 +2581,14 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
local chainlookupname = chainlookups[1]
local chainlookup = lookuptable[chainlookupname]
if chainlookup then
- local cp = chainprocs[chainlookup.type]
- if cp then
+ local chainproc = chainprocs[chainlookup.type]
+ if chainproc then
local ok
- head, start, ok = cp(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ if diskchain then
+ head, start, ok = chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence,chainproc)
+ else
+ head, start, ok = chainproc(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ end
if ok then
done = true
end
@@ -1929,13 +2600,13 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
end
else
local i = 1
- while true do
+ while start and true do
if skipped then
- while true do
+ while true do -- todo: use properties
local char = getchar(start)
local ccd = descriptions[char]
if ccd then
- local class = ccd.class
+ local class = ccd.class or "base"
if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then
start = getnext(start)
else
@@ -1946,36 +2617,51 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
end
end
end
+ -- see remark in ms standard under : LookupType 5: Contextual Substitution Subtable
local chainlookupname = chainlookups[i]
local chainlookup = lookuptable[chainlookupname]
if not chainlookup then
- -- okay, n matches, < n replacements
+ -- we just advance
i = i + 1
else
- local cp = chainmores[chainlookup.type]
- if not cp then
+ local chainproc = chainprocs[chainlookup.type]
+ if not chainproc then
-- actually an error
logprocess("%s: %s is not yet supported",cref(kind,chainname,chainlookupname),chainlookup.type)
i = i + 1
else
local ok, n
- head, start, ok, n = cp(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,i,sequence)
+ if diskchain then
+ head, start, ok = chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence,chainproc)
+ else
+ head, start, ok, n = chainproc(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,i,sequence)
+ end
-- messy since last can be changed !
if ok then
done = true
- -- skip next one(s) if ligature
- i = i + (n or 1)
- else
- i = i + 1
+ if n and n > 1 then
+ -- we have a ligature (cf the spec we advance one but we really need to test it
+ -- as there are fonts out there that are fuzzy and have too many lookups:
+ --
+ -- U+1105 U+119E U+1105 U+119E : sourcehansansklight: script=hang ccmp=yes
+ --
+ if i + n > nofchainlookups then
+ -- if trace_contexts then
+ -- logprocess("%s: quitting lookups",cref(kind,chainname))
+ -- end
+ break
+ else
+ -- we need to carry one
+ end
+ end
end
+ i = i + 1
end
end
- if i > nofchainlookups then
+ if i > nofchainlookups or not start then
break
elseif start then
start = getnext(start)
- else
- -- weird
end
end
end
@@ -1990,8 +2676,16 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
end
end
end
+ if done then
+ break -- out of contexts (new, needs checking)
+ end
end
end
+ if diskseen then -- maybe move up so that we can turn checking on/off
+ notmatchpre = { }
+ notmatchpost = { }
+ notmatchreplace = { }
+ end
return head, start, done
end
@@ -2076,13 +2770,13 @@ local function initialize(sequence,script,language,enabled)
local order = sequence.order
if order then
for i=1,#order do --
- local kind = order[i] --
+ local kind = order[i] --
local valid = enabled[kind]
if valid then
local scripts = features[kind] --
local languages = scripts[script] or scripts[wildcard]
if languages and (languages[language] or languages[wildcard]) then
- return { valid, autofeatures[kind] or false, sequence.chain or 0, kind, sequence }
+ return { valid, autofeatures[kind] or false, sequence, kind }
end
end
end
@@ -2126,32 +2820,216 @@ function otf.dataset(tfmdata,font) -- generic variant, overloaded in context
return rl
end
--- elseif id == glue_code then
--- if p[5] then -- chain
--- local pc = pp[32]
--- if pc then
--- start, ok = start, false -- p[1](start,kind,p[2],pc,p[3],p[4])
--- if ok then
--- done = true
--- end
--- if start then start = getnext(start) end
--- else
--- start = getnext(start)
--- end
--- else
--- start = getnext(start)
--- end
+-- assumptions:
+--
+-- * languages that use complex disc nodes
+
+local function kernrun(disc,run)
+ --
+ -- we catch
+ --
+ if trace_kernruns then
+ report_run("kern") -- will be more detailed
+ end
+ --
+ local prev = getprev(disc) -- todo, keep these in the main loop
+ local next = getnext(disc) -- todo, keep these in the main loop
+ --
+ local pre = getfield(disc,"pre")
+ local post = getfield(disc,"post")
+ local replace = getfield(disc,"replace")
+ --
+ local prevmarks = prev
+ --
+ -- can be optional, because why on earth do we get a disc after a mark (okay, maybe when a ccmp
+ -- has happened but then it should be in the disc so basically this test indicates an error)
+ --
+ while prevmarks and getid(prevmarks) == glyph_code and marks[getchar(prevmarks)] and getfont(prevmarks) == currentfont and getsubtype(prevmarks) < 256 do
+ prevmarks = getprev(prevmarks)
+ end
+ --
+ if prev and (pre or replace) and not (getid(prev) == glyph_code and getfont(prev) == currentfont and getsubtype(prev)<256) then
+ prev = false
+ end
+ if next and (post or replace) and not (getid(next) == glyph_code and getfont(next) == currentfont and getsubtype(next)<256) then
+ next = false
+ end
+ --
+ if not pre then
+ -- go on
+ elseif prev then
+ local nest = getprev(pre)
+ setfield(pre,"prev",prev)
+ setfield(prev,"next",pre)
+ run(prevmarks,"preinjections")
+ setfield(pre,"prev",nest)
+ setfield(prev,"next",disc)
+ else
+ run(pre,"preinjections")
+ end
+ --
+ if not post then
+ -- go on
+ elseif next then
+ local tail = find_node_tail(post)
+ setfield(tail,"next",next)
+ setfield(next,"prev",tail)
+ run(post,"postinjections",next)
+ setfield(tail,"next",nil)
+ setfield(next,"prev",disc)
+ else
+ run(post,"postinjections")
+ end
+ --
+ if not replace and prev and next then
+ -- this should be already done by discfound
+ setfield(prev,"next",next)
+ setfield(next,"prev",prev)
+ run(prevmarks,"injections",next)
+ setfield(prev,"next",disc)
+ setfield(next,"prev",disc)
+ elseif prev and next then
+ local tail = find_node_tail(replace)
+ local nest = getprev(replace)
+ setfield(replace,"prev",prev)
+ setfield(prev,"next",replace)
+ setfield(tail,"next",next)
+ setfield(next,"prev",tail)
+ run(prevmarks,"replaceinjections",next)
+ setfield(replace,"prev",nest)
+ setfield(prev,"next",disc)
+ setfield(tail,"next",nil)
+ setfield(next,"prev",disc)
+ elseif prev then
+ local nest = getprev(replace)
+ setfield(replace,"prev",prev)
+ setfield(prev,"next",replace)
+ run(prevmarks,"replaceinjections")
+ setfield(replace,"prev",nest)
+ setfield(prev,"next",disc)
+ elseif next then
+ local tail = find_node_tail(replace)
+ setfield(tail,"next",next)
+ setfield(next,"prev",tail)
+ run(replace,"replaceinjections",next)
+ setfield(tail,"next",nil)
+ setfield(next,"prev",disc)
+ else
+ run(replace,"replaceinjections")
+ end
+end
--- there will be a new direction parser (pre-parsed etc)
+-- the if new test might be dangerous as luatex will check / set some tail stuff
+-- in a temp node
--- less bytecode: 290 -> 254
---
--- attr = attr or false
---
--- local a = getattr(start,0)
--- if (a == attr and (not attribute or getprop(start,a_state) == attribute)) or (not attribute or getprop(start,a_state) == attribute) then
--- -- the action
--- end
+local function comprun(disc,run)
+ if trace_compruns then
+ report_run("comp: %s",languages.serializediscretionary(disc))
+ end
+ --
+ local pre = getfield(disc,"pre")
+ if pre then
+ sweepnode = disc
+ sweeptype = "pre" -- in alternative code preinjections is used (also used then for proeprties, saves a variable)
+ local new, done = run(pre)
+ if done then
+ setfield(disc,"pre",new)
+ end
+ end
+ --
+ local post = getfield(disc,"post")
+ if post then
+ sweepnode = disc
+ sweeptype = "post"
+ local new, done = run(post)
+ if done then
+ setfield(disc,"post",new)
+ end
+ end
+ --
+ local replace = getfield(disc,"replace")
+ if replace then
+ sweepnode = disc
+ sweeptype = "replace"
+ local new, done = run(replace)
+ if done then
+ setfield(disc,"replace",new)
+ end
+ end
+ sweepnode = nil
+ sweeptype = nil
+end
+
+local function testrun(disc,trun,crun) -- use helper
+ local next = getnext(disc)
+ if next then
+ local replace = getfield(disc,"replace")
+ if replace then
+ local prev = getprev(disc)
+ if prev then
+ -- only look ahead
+ local tail = find_node_tail(replace)
+ -- local nest = getprev(replace)
+ setfield(tail,"next",next)
+ setfield(next,"prev",tail)
+ if trun(replace,next) then
+ setfield(disc,"replace",nil) -- beware, side effects of nest so first
+ setfield(prev,"next",replace)
+ setfield(replace,"prev",prev)
+ setfield(next,"prev",tail)
+ setfield(tail,"next",next)
+ setfield(disc,"prev",nil)
+ setfield(disc,"next",nil)
+ flush_node_list(disc)
+ return replace -- restart
+ else
+ setfield(tail,"next",nil)
+ setfield(next,"prev",disc)
+ end
+ else
+ -- weird case
+ end
+ else
+ -- no need
+ end
+ else
+ -- weird case
+ end
+ comprun(disc,crun)
+ return next
+end
+
+local function discrun(disc,drun,krun)
+ local next = getnext(disc)
+ local prev = getprev(disc)
+ if trace_discruns then
+ report_run("disc") -- will be more detailed
+ end
+ if next and prev then
+ setfield(prev,"next",next)
+ -- setfield(next,"prev",prev)
+ drun(prev)
+ setfield(prev,"next",disc)
+ -- setfield(next,"prev",disc)
+ end
+ --
+ local pre = getfield(disc,"pre")
+ if not pre then
+ -- go on
+ elseif prev then
+ local nest = getprev(pre)
+ setfield(pre,"prev",prev)
+ setfield(prev,"next",pre)
+ krun(prev,"preinjections")
+ setfield(pre,"prev",nest)
+ setfield(prev,"next",disc)
+ else
+ krun(pre,"preinjections")
+ end
+ return next
+end
+
+-- todo: maybe run lr and rl stretches
local function featuresprocessor(head,font,attr)
@@ -2180,6 +3058,7 @@ local function featuresprocessor(head,font,attr)
currentfont = font
rlmode = 0
+ sweephead = { }
local sequences = resources.sequences
local done = false
@@ -2195,23 +3074,27 @@ local function featuresprocessor(head,font,attr)
-- Keeping track of the headnode is needed for devanagari (I generalized it a bit
-- so that multiple cases are also covered.)
- -- todo: retain prev
+ -- We don't goto the next node of a disc node is created so that we can then treat
+ -- the pre, post and replace. It's abit of a hack but works out ok for most cases.
+
+ -- there can be less subtype and attr checking in the comprun etc helpers
for s=1,#datasets do
- local dataset = datasets[s]
- featurevalue = dataset[1] -- todo: pass to function instead of using a global
-
- local sequence = dataset[5] -- sequences[s] -- also dataset[5]
- local rlparmode = 0
- local topstack = 0
- local success = false
- local attribute = dataset[2]
- local chain = dataset[3] -- sequence.chain or 0
- local typ = sequence.type
- local subtables = sequence.subtables
- if chain < 0 then
+ local dataset = datasets[s]
+ featurevalue = dataset[1] -- todo: pass to function instead of using a global
+ local attribute = dataset[2]
+ local sequence = dataset[3] -- sequences[s] -- also dataset[5]
+ local kind = dataset[4]
+ ----- chain = dataset[5] -- sequence.chain or 0
+ local rlparmode = 0
+ local topstack = 0
+ local success = false
+ local typ = sequence.type
+ local gpossing = typ == "gpos_single" or typ == "gpos_pair" -- maybe all of them
+ local subtables = sequence.subtables
+ local handler = handlers[typ]
+ if typ == "gsub_reversecontextchain" then -- chain < 0
-- this is a limited case, no special treatments like 'init' etc
- local handler = handlers[typ]
-- we need to get rid of this slide! probably no longer needed in latest luatex
local start = find_node_tail(head) -- slow (we can store tail because there's always a skip at the end): todo
while start do
@@ -2225,13 +3108,15 @@ local function featuresprocessor(head,font,attr)
a = true
end
if a then
+ local char = getchar(start)
for i=1,#subtables do
local lookupname = subtables[i]
local lookupcache = lookuphash[lookupname]
if lookupcache then
- local lookupmatch = lookupcache[getchar(start)]
+ local lookupmatch = lookupcache[char]
if lookupmatch then
- head, start, success = handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
+ -- todo: disc?
+ head, start, success = handler(head,start,kind,lookupname,lookupmatch,sequence,lookuphash,i)
if success then
break
end
@@ -2252,24 +3137,30 @@ local function featuresprocessor(head,font,attr)
end
end
else
- local handler = handlers[typ]
local ns = #subtables
local start = head -- local ?
rlmode = 0 -- to be checked ?
if ns == 1 then -- happens often
- local lookupname = subtables[1]
+ local lookupname = subtables[1]
local lookupcache = lookuphash[lookupname]
if not lookupcache then -- also check for empty cache
report_missing_cache(typ,lookupname)
else
- local function subrun(start)
- -- mostly for gsub, gpos would demand a more clever approach
- local head = start
- local done = false
+ local function c_run(head) -- no need to check for 256 and attr probably also the same
+ local done = false
+ local start = sweephead[head]
+ if start then
+ sweephead[head] = nil
+ else
+ start = head
+ end
while start do
local id = getid(start)
- if id == glyph_code and getfont(start) == font and getsubtype(start) < 256 then
+ if id ~= glyph_code then
+ -- very unlikely
+ start = getnext(start)
+ elseif getfont(start) == font and getsubtype(start) < 256 then
local a = getattr(start,0)
if a then
a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
@@ -2281,7 +3172,7 @@ local function featuresprocessor(head,font,attr)
if lookupmatch then
-- sequence kan weg
local ok
- head, start, ok = handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1)
+ head, start, ok = handler(head,start,kind,lookupname,lookupmatch,sequence,lookuphash,1)
if ok then
done = true
end
@@ -2291,48 +3182,106 @@ local function featuresprocessor(head,font,attr)
start = getnext(start)
end
else
- start = getnext(start)
+ return head, false
end
end
if done then
- success = true
- return head
+ success = true -- needed in this subrun?
end
+ return head, done
end
- local function kerndisc(disc) -- we can assume that prev and next are glyphs
- local prev = getprev(disc)
- local next = getnext(disc)
- if prev and next then
- setfield(prev,"next",next)
- -- setfield(next,"prev",prev)
- local a = getattr(prev,0)
- if a then
- a = (a == attr) and (not attribute or getprop(prev,a_state) == attribute)
+ local function t_run(start,stop)
+ while start ~= stop do
+ local id = getid(start)
+ if id == glyph_code and getfont(start) == font and getsubtype(start) < 256 then
+ local a = getattr(start,0)
+ if a then
+ a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
+ else
+ a = not attribute or getprop(start,a_state) == attribute
+ end
+ if a then
+ local lookupmatch = lookupcache[getchar(start)]
+ if lookupmatch then -- hm, hyphens can match (tlig) so we need to really check
+ -- if we need more than ligatures we can outline the code and use functions
+ local s = getnext(start)
+ local l = nil
+ while s do
+ local lg = lookupmatch[getchar(s)]
+ if lg then
+ l = lg
+ s = getnext(s)
+ else
+ break
+ end
+ end
+ if l and l.ligature then
+ return true
+ end
+ end
+ end
+ start = getnext(start)
else
- a = not attribute or getprop(prev,a_state) == attribute
+ break
end
- if a then
- local lookupmatch = lookupcache[getchar(prev)]
- if lookupmatch then
- -- sequence kan weg
- local h, d, ok = handler(head,prev,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1)
- if ok then
- done = true
- success = true
+ end
+ end
+
+ local function d_run(prev) -- we can assume that prev and next are glyphs
+ local a = getattr(prev,0)
+ if a then
+ a = (a == attr) and (not attribute or getprop(prev,a_state) == attribute)
+ else
+ a = not attribute or getprop(prev,a_state) == attribute
+ end
+ if a then
+ local lookupmatch = lookupcache[getchar(prev)]
+ if lookupmatch then
+ -- sequence kan weg
+ local h, d, ok = handler(head,prev,kind,lookupname,lookupmatch,sequence,lookuphash,1)
+ if ok then
+ done = true
+ success = true
+ end
+ end
+ end
+ end
+
+ local function k_run(sub,injection,last)
+ local a = getattr(sub,0)
+ if a then
+ a = (a == attr) and (not attribute or getprop(sub,a_state) == attribute)
+ else
+ a = not attribute or getprop(sub,a_state) == attribute
+ end
+ if a then
+ -- sequence kan weg
+ for n in traverse_nodes(sub) do -- only gpos
+ if n == last then
+ break
+ end
+ local id = getid(n)
+ if id == glyph_code then
+ local lookupmatch = lookupcache[getchar(n)]
+ if lookupmatch then
+ local h, d, ok = handler(sub,n,kind,lookupname,lookupmatch,sequence,lookuphash,1,injection)
+ if ok then
+ done = true
+ success = true
+ end
end
+ else
+ -- message
end
end
- setfield(prev,"next",disc)
- -- setfield(next,"prev",disc)
end
- return next
end
while start do
local id = getid(start)
if id == glyph_code then
- if getfont(start) == font and getsubtype(start) < 256 then
+ if getfont(start) == font and getsubtype(start) < 256 then -- why a 256 test ...
local a = getattr(start,0)
if a then
a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
@@ -2340,59 +3289,52 @@ local function featuresprocessor(head,font,attr)
a = not attribute or getprop(start,a_state) == attribute
end
if a then
- local lookupmatch = lookupcache[getchar(start)]
+ local char = getchar(start)
+ local lookupmatch = lookupcache[char]
if lookupmatch then
-- sequence kan weg
local ok
- head, start, ok = handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1)
+ head, start, ok = handler(head,start,kind,lookupname,lookupmatch,sequence,lookuphash,1)
if ok then
success = true
+ elseif gpossing and zwnjruns and char == zwnj then
+ discrun(start,d_run)
end
+ elseif gpossing and zwnjruns and char == zwnj then
+ discrun(start,d_run)
end
if start then start = getnext(start) end
else
- start = getnext(start)
+ start = getnext(start)
end
else
start = getnext(start)
end
elseif id == disc_code then
- -- mostly for gsub
- if getsubtype(start) == discretionary_code then
- local pre = getfield(start,"pre")
- if pre then
- local new = subrun(pre)
- if new then setfield(start,"pre",new) end
- end
- local post = getfield(start,"post")
- if post then
- local new = subrun(post)
- if new then setfield(start,"post",new) end
- end
- local replace = getfield(start,"replace")
- if replace then
- local new = subrun(replace)
- if new then setfield(start,"replace",new) end
- end
-elseif typ == "gpos_single" or typ == "gpos_pair" then
- kerndisc(start)
+ if gpossing then
+ kernrun(start,k_run)
+ start = getnext(start)
+ elseif typ == "gsub_ligature" then
+ start = testrun(start,t_run,c_run)
+ else
+ comprun(start,c_run)
+ start = getnext(start)
end
- start = getnext(start)
elseif id == whatsit_code then -- will be function
local subtype = getsubtype(start)
if subtype == dir_code then
local dir = getfield(start,"dir")
- if dir == "+TRT" or dir == "+TLT" then
+ if dir == "+TLT" then
topstack = topstack + 1
dirstack[topstack] = dir
- elseif dir == "-TRT" or dir == "-TLT" then
- topstack = topstack - 1
- end
- local newdir = dirstack[topstack]
- if newdir == "+TRT" then
- rlmode = -1
- elseif newdir == "+TLT" then
rlmode = 1
+ elseif dir == "+TRT" then
+ topstack = topstack + 1
+ dirstack[topstack] = dir
+ rlmode = -1
+ elseif dir == "-TLT" or dir == "-TRT" then
+ topstack = topstack - 1
+ rlmode = dirstack[topstack] == "+TRT" and -1 or 1
else
rlmode = rlparmode
end
@@ -2422,15 +3364,23 @@ elseif typ == "gpos_single" or typ == "gpos_pair" then
end
end
end
+
else
- local function subrun(start)
- -- mostly for gsub, gpos would demand a more clever approach
- local head = start
- local done = false
+ local function c_run(head)
+ local done = false
+ local start = sweephead[head]
+ if start then
+ sweephead[head] = nil
+ else
+ start = head
+ end
while start do
local id = getid(start)
- if id == glyph_code and getfont(start) == font and getsubtype(start) < 256 then
+ if id ~= glyph_code then
+ -- very unlikely
+ start = getnext(start)
+ elseif getfont(start) == font and getsubtype(start) < 256 then
local a = getattr(start,0)
if a then
a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
@@ -2438,15 +3388,16 @@ elseif typ == "gpos_single" or typ == "gpos_pair" then
a = not attribute or getprop(start,a_state) == attribute
end
if a then
+ local char = getchar(start)
for i=1,ns do
local lookupname = subtables[i]
local lookupcache = lookuphash[lookupname]
if lookupcache then
- local lookupmatch = lookupcache[getchar(start)]
+ local lookupmatch = lookupcache[char]
if lookupmatch then
-- we could move all code inline but that makes things even more unreadable
local ok
- head, start, ok = handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
+ head, start, ok = handler(head,start,kind,lookupname,lookupmatch,sequence,lookuphash,i)
if ok then
done = true
break
@@ -2464,50 +3415,127 @@ elseif typ == "gpos_single" or typ == "gpos_pair" then
start = getnext(start)
end
else
- start = getnext(start)
+ return head, false
end
end
if done then
success = true
- return head
end
+ return head, done
end
- local function kerndisc(disc) -- we can assume that prev and next are glyphs
- local prev = getprev(disc)
- local next = getnext(disc)
- if prev and next then
- setfield(prev,"next",next)
- -- setfield(next,"prev",prev)
- local a = getattr(prev,0)
- if a then
- a = (a == attr) and (not attribute or getprop(prev,a_state) == attribute)
- else
- a = not attribute or getprop(prev,a_state) == attribute
+ local function d_run(prev)
+ local a = getattr(prev,0)
+ if a then
+ a = (a == attr) and (not attribute or getprop(prev,a_state) == attribute)
+ else
+ a = not attribute or getprop(prev,a_state) == attribute
+ end
+ if a then
+ -- brr prev can be disc
+ local char = getchar(prev)
+ for i=1,ns do
+ local lookupname = subtables[i]
+ local lookupcache = lookuphash[lookupname]
+ if lookupcache then
+ local lookupmatch = lookupcache[char]
+ if lookupmatch then
+ -- we could move all code inline but that makes things even more unreadable
+ local h, d, ok = handler(head,prev,kind,lookupname,lookupmatch,sequence,lookuphash,i)
+ if ok then
+ done = true
+ break
+ end
+ end
+ else
+ report_missing_cache(typ,lookupname)
+ end
end
- if a then
- for i=1,ns do
- local lookupname = subtables[i]
- local lookupcache = lookuphash[lookupname]
- if lookupcache then
- local lookupmatch = lookupcache[getchar(prev)]
- if lookupmatch then
- -- we could move all code inline but that makes things even more unreadable
- local h, d, ok = handler(head,prev,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
- if ok then
- done = true
- break
+ end
+ end
+
+ local function k_run(sub,injection,last)
+ local a = getattr(sub,0)
+ if a then
+ a = (a == attr) and (not attribute or getprop(sub,a_state) == attribute)
+ else
+ a = not attribute or getprop(sub,a_state) == attribute
+ end
+ if a then
+ for n in traverse_nodes(sub) do -- only gpos
+ if n == last then
+ break
+ end
+ local id = getid(n)
+ if id == glyph_code then
+ local char = getchar(n)
+ for i=1,ns do
+ local lookupname = subtables[i]
+ local lookupcache = lookuphash[lookupname]
+ if lookupcache then
+ local lookupmatch = lookupcache[char]
+ if lookupmatch then
+ local h, d, ok = handler(head,n,kind,lookupname,lookupmatch,sequence,lookuphash,i,injection)
+ if ok then
+ done = true
+ break
+ end
end
+ else
+ report_missing_cache(typ,lookupname)
+ end
+ end
+ else
+ -- message
+ end
+ end
+ end
+ end
+
+ local function t_run(start,stop)
+ while start ~= stop do
+ local id = getid(start)
+ if id == glyph_code and getfont(start) == font and getsubtype(start) < 256 then
+ local a = getattr(start,0)
+ if a then
+ a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
+ else
+ a = not attribute or getprop(start,a_state) == attribute
+ end
+ if a then
+ local char = getchar(start)
+ for i=1,ns do
+ local lookupname = subtables[i]
+ local lookupcache = lookuphash[lookupname]
+ if lookupcache then
+ local lookupmatch = lookupcache[char]
+ if lookupmatch then
+ -- if we need more than ligatures we can outline the code and use functions
+ local s = getnext(start)
+ local l = nil
+ while s do
+ local lg = lookupmatch[getchar(s)]
+ if lg then
+ l = lg
+ s = getnext(s)
+ else
+ break
+ end
+ end
+ if l and l.ligature then
+ return true
+ end
+ end
+ else
+ report_missing_cache(typ,lookupname)
end
- else
- report_missing_cache(typ,lookupname)
end
end
+ start = getnext(start)
+ else
+ break
end
- setfield(prev,"next",disc)
- -- setfield(next,"prev",disc)
end
- return next
end
while start do
@@ -2522,21 +3550,26 @@ elseif typ == "gpos_single" or typ == "gpos_pair" then
end
if a then
for i=1,ns do
- local lookupname = subtables[i]
+ local lookupname = subtables[i]
local lookupcache = lookuphash[lookupname]
if lookupcache then
- local lookupmatch = lookupcache[getchar(start)]
+ local char = getchar(start)
+ local lookupmatch = lookupcache[char]
if lookupmatch then
-- we could move all code inline but that makes things even more unreadable
local ok
- head, start, ok = handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
+ head, start, ok = handler(head,start,kind,lookupname,lookupmatch,sequence,lookuphash,i)
if ok then
success = true
break
elseif not start then
-- don't ask why ... shouldn't happen
break
+ elseif gpossing and zwnjruns and char == zwnj then
+ discrun(start,d_run)
end
+ elseif gpossing and zwnjruns and char == zwnj then
+ discrun(start,d_run)
end
else
report_missing_cache(typ,lookupname)
@@ -2550,42 +3583,30 @@ elseif typ == "gpos_single" or typ == "gpos_pair" then
start = getnext(start)
end
elseif id == disc_code then
- -- mostly for gsub
- if getsubtype(start) == discretionary_code then
- local pre = getfield(start,"pre")
- if pre then
- local new = subrun(pre)
- if new then setfield(start,"pre",new) end
- end
- local post = getfield(start,"post")
- if post then
- local new = subrun(post)
- if new then setfield(start,"post",new) end
- end
- local replace = getfield(start,"replace")
- if replace then
- local new = subrun(replace)
- if new then setfield(start,"replace",new) end
- end
-elseif typ == "gpos_single" or typ == "gpos_pair" then
- kerndisc(start)
+ if gpossing then
+ kernrun(start,k_run)
+ start = getnext(start)
+ elseif typ == "gsub_ligature" then
+ start = testrun(start,t_run,c_run)
+ else
+ comprun(start,c_run)
+ start = getnext(start)
end
- start = getnext(start)
elseif id == whatsit_code then
local subtype = getsubtype(start)
if subtype == dir_code then
local dir = getfield(start,"dir")
- if dir == "+TRT" or dir == "+TLT" then
+ if dir == "+TLT" then
topstack = topstack + 1
dirstack[topstack] = dir
- elseif dir == "-TRT" or dir == "-TLT" then
- topstack = topstack - 1
- end
- local newdir = dirstack[topstack]
- if newdir == "+TRT" then
- rlmode = -1
- elseif newdir == "+TLT" then
rlmode = 1
+ elseif dir == "+TRT" then
+ topstack = topstack + 1
+ dirstack[topstack] = dir
+ rlmode = -1
+ elseif dir == "-TLT" or dir == "-TRT" then
+ topstack = topstack - 1
+ rlmode = dirstack[topstack] == "+TRT" and -1 or 1
else
rlmode = rlparmode
end
@@ -2629,6 +3650,8 @@ elseif typ == "gpos_single" or typ == "gpos_pair" then
return head, done
end
+-- this might move to the loader
+
local function generic(lookupdata,lookupname,unicode,lookuphash)
local target = lookuphash[lookupname]
if target then
@@ -2638,47 +3661,48 @@ local function generic(lookupdata,lookupname,unicode,lookuphash)
end
end
-local action = {
+local function ligature(lookupdata,lookupname,unicode,lookuphash)
+ local target = lookuphash[lookupname]
+ if not target then
+ target = { }
+ lookuphash[lookupname] = target
+ end
+ for i=1,#lookupdata do
+ local li = lookupdata[i]
+ local tu = target[li]
+ if not tu then
+ tu = { }
+ target[li] = tu
+ end
+ target = tu
+ end
+ target.ligature = unicode
+end
+
+local function pair(lookupdata,lookupname,unicode,lookuphash)
+ local target = lookuphash[lookupname]
+ if not target then
+ target = { }
+ lookuphash[lookupname] = target
+ end
+ local others = target[unicode]
+ local paired = lookupdata[1]
+ if others then
+ others[paired] = lookupdata
+ else
+ others = { [paired] = lookupdata }
+ target[unicode] = others
+ end
+end
+local action = {
substitution = generic,
multiple = generic,
alternate = generic,
position = generic,
-
- ligature = function(lookupdata,lookupname,unicode,lookuphash)
- local target = lookuphash[lookupname]
- if not target then
- target = { }
- lookuphash[lookupname] = target
- end
- for i=1,#lookupdata do
- local li = lookupdata[i]
- local tu = target[li]
- if not tu then
- tu = { }
- target[li] = tu
- end
- target = tu
- end
- target.ligature = unicode
- end,
-
- pair = function(lookupdata,lookupname,unicode,lookuphash)
- local target = lookuphash[lookupname]
- if not target then
- target = { }
- lookuphash[lookupname] = target
- end
- local others = target[unicode]
- local paired = lookupdata[1]
- if others then
- others[paired] = lookupdata
- else
- others = { [paired] = lookupdata }
- target[unicode] = others
- end
- end,
-
+ ligature = ligature,
+ pair = pair,
+ kern = pair,
}
local function prepare_lookups(tfmdata)
@@ -2691,12 +3715,17 @@ local function prepare_lookups(tfmdata)
local lookuptypes = resources.lookuptypes
local characters = tfmdata.characters
local descriptions = tfmdata.descriptions
+ local duplicates = resources.duplicates
-- we cannot free the entries in the descriptions as sometimes we access
-- then directly (for instance anchors) ... selectively freeing does save
-- much memory as it's only a reference to a table and the slot in the
-- description hash is not freed anyway
+ -- we can delay this using metatables so that we don't make the hashes for
+ -- features we don't use but then we need to loop over the characters
+ -- many times so we gain nothing
+
for unicode, character in next, characters do -- we cannot loop over descriptions !
local description = descriptions[unicode]
@@ -2706,7 +3735,7 @@ local function prepare_lookups(tfmdata)
local lookups = description.slookups
if lookups then
for lookupname, lookupdata in next, lookups do
- action[lookuptypes[lookupname]](lookupdata,lookupname,unicode,lookuphash)
+ action[lookuptypes[lookupname]](lookupdata,lookupname,unicode,lookuphash,duplicates)
end
end
@@ -2716,7 +3745,7 @@ local function prepare_lookups(tfmdata)
local lookuptype = lookuptypes[lookupname]
for l=1,#lookuplist do
local lookupdata = lookuplist[l]
- action[lookuptype](lookupdata,lookupname,unicode,lookuphash)
+ action[lookuptype](lookupdata,lookupname,unicode,lookuphash,duplicates)
end
end
end
@@ -2740,7 +3769,7 @@ local function prepare_lookups(tfmdata)
for name, anchor in next, anchors do
local lookups = anchor_to_lookup[name]
if lookups then
- for lookup, _ in next, lookups do
+ for lookup in next, lookups do
local target = lookuphash[lookup]
if target then
target[unicode] = anchors
@@ -2760,6 +3789,8 @@ local function prepare_lookups(tfmdata)
end
+-- so far
+
local function split(replacement,original)
local result = { }
for i=1,#replacement do
@@ -2835,7 +3866,7 @@ local function prepare_contextchains(tfmdata)
-- use sequence[start] instead but it's somewhat ugly.
nt = nt + 1
t[nt] = { nofrules, lookuptype, sequence, start, stop, rule.lookups, replacements }
- for unic, _ in next, sequence[start] do
+ for unic in next, sequence[start] do
local cu = contexts[unic]
if not cu then
contexts[unic] = t
diff --git a/src/fontloader/misc/fontloader-fonts.lua b/src/fontloader/misc/fontloader-fonts.lua
index c81e8cd..f18ba35 100644
--- a/src/fontloader/misc/fontloader-fonts.lua
+++ b/src/fontloader/misc/fontloader-fonts.lua
@@ -27,16 +27,10 @@ if not modules then modules = { } end modules ['luatex-fonts'] = {
-- also add more helper code here, but that depends to what extend metatex (sidetrack of context)
-- evolves into a low level layer (depends on time, as usual).
-texio.write_nl("")
-texio.write_nl("--------------------------------------------------------------------------------")
-texio.write_nl("The font code has been brought in sync with the context version of 2014.12.21 so")
-texio.write_nl("if things don't work out as expected the interfacing needs to be checked. When")
-texio.write_nl("this works as expected a second upgrade will happen that gives a more complete")
-texio.write_nl("support and another sync with the context code (that new code is currently being")
-texio.write_nl("tested. The base pass is now integrated in the main pass. The results can differ")
-texio.write_nl("from those in context because there we integrate some mechanisms differently.")
-texio.write_nl("--------------------------------------------------------------------------------")
-texio.write_nl("")
+-- The code here is the same as in context version 2015.09.11 but the rendering in context can be
+-- different from generic. This can be a side effect of additional callbacks, additional features
+-- and interferences between mechanisms between macro packages. We use the rendering in context
+-- and luatex-plain as reference for issues.
utf = utf or unicode.utf8
@@ -221,9 +215,9 @@ if non_generic_context.luatex_fonts.skip_loading ~= true then
loadmodule('font-oti.lua')
loadmodule('font-otf.lua')
loadmodule('font-otb.lua')
- loadmodule('luatex-fonts-inj.lua')
+ loadmodule('luatex-fonts-inj.lua') -- normally the same as font-inj.lua
loadmodule('luatex-fonts-ota.lua')
- loadmodule('luatex-fonts-otn.lua')
+ loadmodule('luatex-fonts-otn.lua') -- normally the same as font-otn.lua
loadmodule('font-otp.lua')
loadmodule('luatex-fonts-lua.lua')
loadmodule('font-def.lua') -- this code (stripped) might end up in luatex-fonts-def.lua
diff --git a/src/fontloader/misc/fontloader-l-lpeg.lua b/src/fontloader/misc/fontloader-l-lpeg.lua
index 55a0d89..5be1246 100644
--- a/src/fontloader/misc/fontloader-l-lpeg.lua
+++ b/src/fontloader/misc/fontloader-l-lpeg.lua
@@ -82,7 +82,7 @@ local lpegtype, lpegmatch, lpegprint = lpeg.type, lpeg.match, lpeg.print
-- let's start with an inspector:
if setinspector then
- setinspector(function(v) if lpegtype(v) then lpegprint(v) return true end end)
+ setinspector("lpeg",function(v) if lpegtype(v) then lpegprint(v) return true end end)
end
-- Beware, we predefine a bunch of patterns here and one reason for doing so
diff --git a/src/fontloader/misc/fontloader-l-lua.lua b/src/fontloader/misc/fontloader-l-lua.lua
index 1a2a987..cb61829 100644
--- a/src/fontloader/misc/fontloader-l-lua.lua
+++ b/src/fontloader/misc/fontloader-l-lua.lua
@@ -129,22 +129,36 @@ local print, select, tostring = print, select, tostring
local inspectors = { }
-function setinspector(inspector) -- global function
- inspectors[#inspectors+1] = inspector
+function setinspector(kind,inspector) -- global function
+ inspectors[kind] = inspector
end
function inspect(...) -- global function
for s=1,select("#",...) do
local value = select(s,...)
- local done = false
- for i=1,#inspectors do
- done = inspectors[i](value)
- if done then
- break
+ if value == nil then
+ print("nil")
+ else
+ local done = false
+ -- type driven (table)
+ local kind = type(value)
+ local inspector = inspectors[kind]
+ if inspector then
+ done = inspector(value)
+ if done then
+ break
+ end
+ end
+ -- whatever driven (token, node, ...)
+ for kind, inspector in next, inspectors do
+ done = inspector(value)
+ if done then
+ break
+ end
+ end
+ if not done then
+ print(tostring(value))
end
- end
- if not done then
- print(tostring(value))
end
end
end
diff --git a/src/fontloader/misc/fontloader-l-string.lua b/src/fontloader/misc/fontloader-l-string.lua
index 70c66f6..e9dc2bb 100644
--- a/src/fontloader/misc/fontloader-l-string.lua
+++ b/src/fontloader/misc/fontloader-l-string.lua
@@ -192,10 +192,11 @@ string.itself = function(s) return s end
-- also handy (see utf variant)
-local pattern = Ct(C(1)^0) -- string and not utf !
+local pattern_c = Ct( C(1) ^0) -- string and not utf !
+local pattern_b = Ct((C(1)/byte)^0)
-function string.totable(str)
- return lpegmatch(pattern,str)
+function string.totable(str,bytes)
+ return lpegmatch(bytes and pattern_b or pattern_c,str)
end
-- handy from within tex:
diff --git a/src/fontloader/misc/fontloader-l-table.lua b/src/fontloader/misc/fontloader-l-table.lua
index b02f210..552097e 100644
--- a/src/fontloader/misc/fontloader-l-table.lua
+++ b/src/fontloader/misc/fontloader-l-table.lua
@@ -1144,7 +1144,7 @@ function table.print(t,...)
end
if setinspector then
- setinspector(function(v) if type(v) == "table" then serialize(print,v,"table") return true end end)
+ setinspector("table",function(v) if type(v) == "table" then serialize(print,v,"table") return true end end)
end
-- -- -- obsolete but we keep them for a while and might comment them later -- -- --
diff --git a/src/fontloader/misc/fontloader-mplib.lua b/src/fontloader/misc/fontloader-mplib.lua
index c6628ac..fd6eb97 100644
--- a/src/fontloader/misc/fontloader-mplib.lua
+++ b/src/fontloader/misc/fontloader-mplib.lua
@@ -22,7 +22,9 @@ if metapost and metapost.version then
else
- local format, concat, abs, match = string.format, table.concat, math.abs, string.match
+ local format, match, gsub = string.format, string.match, string.gsub
+ local concat = table.concat
+ local abs = math.abs
local mplib = require ('mplib')
local kpse = require ('kpse')
@@ -144,10 +146,101 @@ else
metapost.make = metapost.make or function()
end
+ local template = [[
+ \pdfoutput=1
+ \pdfpkresolution600
+ \pdfcompresslevel=9
+ %s\relax
+ \hsize=100in
+ \vsize=\hsize
+ \hoffset=-1in
+ \voffset=\hoffset
+ \topskip=0pt
+ \setbox0=\hbox{%s}\relax
+ \pageheight=\ht0
+ \pagewidth=\wd0
+ \box0
+ \bye
+ ]]
+
+ metapost.texrunner = "mtxrun --script plain"
+
+ local texruns = 0 -- per document
+ local texhash = { } -- per document
+
+ function metapost.maketext(mpd,str,what)
+ -- inefficient but one can always use metafun .. it's more a test
+ -- feature
+ local verbatimtex = mpd.verbatimtex
+ if not verbatimtex then
+ verbatimtex = { }
+ mpd.verbatimtex = verbatimtex
+ end
+ if what == 1 then
+ table.insert(verbatimtex,str)
+ else
+ local texcode = format(template,concat(verbatimtex,"\n"),str)
+ local texdone = texhash[texcode]
+ local jobname = tex.jobname
+ if not texdone then
+ texruns = texruns + 1
+ texdone = texruns
+ texhash[texcode] = texdone
+ local texname = format("%s-mplib-%s.tmp",jobname,texdone)
+ local logname = format("%s-mplib-%s.log",jobname,texdone)
+ local pdfname = format("%s-mplib-%s.pdf",jobname,texdone)
+ io.savedata(texname,texcode)
+ os.execute(format("%s %s",metapost.texrunner,texname))
+ os.remove(texname)
+ os.remove(logname)
+ end
+ return format('"image::%s-mplib-%s.pdf" infont defaultfont',jobname,texdone)
+ end
+ end
+
+ local function mpprint(buffer,...)
+ for i=1,select("#",...) do
+ local value = select(i,...)
+ if value ~= nil then
+ local t = type(value)
+ if t == "number" then
+ buffer[#buffer+1] = format("%.16f",value)
+ elseif t == "string" then
+ buffer[#buffer+1] = value
+ elseif t == "table" then
+ buffer[#buffer+1] = "(" .. concat(value,",") .. ")"
+ else -- boolean or whatever
+ buffer[#buffer+1] = tostring(value)
+ end
+ end
+ end
+ end
+
+ function metapost.runscript(mpd,code)
+ local code = loadstring(code)
+ if type(code) == "function" then
+ local buffer = { }
+ function metapost.print(...)
+ mpprint(buffer,...)
+ end
+ code()
+ -- mpd.buffer = buffer -- for tracing
+ return concat(buffer,"")
+ end
+ return ""
+ end
+
function metapost.load(name)
+ local mpd = {
+ buffer = { },
+ verbatim = { }
+ }
local mpx = mplib.new {
ini_version = true,
- find_file = metapost.finder,
+ find_file = metapost.finder,
+ make_text = function(...) return metapost.maketext (mpd,...) end,
+ run_script = function(...) return metapost.runscript(mpd,...) end,
+ extensions = 1,
}
local result
if not mpx then
@@ -217,8 +310,8 @@ else
return figure:objects()
end
- function metapost.convert(result, flusher)
- metapost.flush(result, flusher)
+ function metapost.convert(result,flusher)
+ metapost.flush(result,flusher)
return true -- done
end
@@ -239,8 +332,13 @@ else
end
function pdf_textfigure(font,size,text,width,height,depth)
- text = text:gsub(".","\\hbox{%1}") -- kerning happens in metapost
- tex.sprint(format("\\MPLIBtextext{%s}{%s}{%s}{%s}{%s}",font,size,text,0,-( 7200/ 7227)/65536*depth))
+ local how, what = match(text,"^(.-)::(.+)$")
+ if how == "image" then
+ tex.sprint(format("\\MPLIBpdftext{%s}{%s}",what,depth))
+ else
+ text = gsub(text,".","\\hbox{%1}") -- kerning happens in metapost
+ tex.sprint(format("\\MPLIBtextext{%s}{%s}{%s}{%s}",font,size,text,depth))
+ end
end
local bend_tolerance = 131/65536
@@ -375,8 +473,10 @@ else
pdf_literalcode("Q")
else
local cs = object.color
+ local cr = false
if cs and #cs > 0 then
- pdf_literalcode(metapost.colorconverter(cs))
+ cs, cr = metapost.colorconverter(cs)
+ pdf_literalcode(cs)
end
local ml = object.miterlimit
if ml and ml ~= miterlimit then
diff --git a/src/fontloader/misc/fontloader-mplib.tex b/src/fontloader/misc/fontloader-mplib.tex
index 09dd179..f9de4b2 100644
--- a/src/fontloader/misc/fontloader-mplib.tex
+++ b/src/fontloader/misc/fontloader-mplib.tex
@@ -106,15 +106,14 @@
%D Text items have a special handler:
-\def\MPLIBtextext#1#2#3#4#5%
+\def\MPLIBtextext#1#2#3#4%
{\begingroup
\setbox\mplibscratchbox\hbox
{\font\temp=#1 at #2bp%
\temp
#3}%
\setbox\mplibscratchbox\hbox
- {\hskip#4 bp%
- \raise#5 bp%
+ {\raise#4sp%
\box\mplibscratchbox}%
\wd\mplibscratchbox0pt%
\ht\mplibscratchbox0pt%
@@ -122,4 +121,20 @@
\box\mplibscratchbox
\endgroup}
+\def\MPLIBpdftext#1#2%
+ {\ifcsname mplib::#1\endcsname
+ % already done, forgotten outside convert group
+ \message{}%
+ \else
+ \message{}%
+ \immediate\pdfximage{#1}% we cannot remove the file as it is included last
+ \expandafter\edef\csname mplib::#1\endcsname{\the\pdflastximage}%
+ \fi
+ \setbox\mplibscratchbox\hbox
+ {\raise#2sp\hbox{\pdfrefximage\csname mplib::#1\endcsname}}%
+ \wd\mplibscratchbox0pt%
+ \ht\mplibscratchbox0pt%
+ \dp\mplibscratchbox0pt%
+ \box\mplibscratchbox}
+
\endinput
diff --git a/src/fontloader/misc/fontloader-plain.tex b/src/fontloader/misc/fontloader-plain.tex
index c9a9e36..9902c49 100644
--- a/src/fontloader/misc/fontloader-plain.tex
+++ b/src/fontloader/misc/fontloader-plain.tex
@@ -11,7 +11,26 @@
\directlua {tex.enableprimitives('', tex.extraprimitives())}
-\pdfoutput=1
+% We assume that pdf is used.
+
+\pdfoutput 1
+
+% We set the page dimensions because otherwise the backend does weird things
+% when we have for instance this on a line of its own:
+%
+% \hbox to 100cm {\hss wide indeed\hss}
+%
+% The page dimension calculation is a fuzzy one as there are some compensations
+% for the \hoffset and \voffset and such. I remember long discussions and much
+% trial and error in figuring this out during pdftex development times. Where
+% a dvi driver will project on a papersize (and thereby clip) the pdf backend
+% has to deal with the lack of a page concept on tex by some guessing. Normally
+% a macro package will set the dimensions to something reasonable anyway.
+
+\pagewidth 8.5in
+\pageheight 11.0in
+
+% We load some code at runtime:
\everyjob \expandafter {%
\the\everyjob
@@ -20,9 +39,11 @@
\input {luatex-math}%
\input {luatex-languages}%
\input {luatex-mplib}%
- % \input {luatex-gadgets}%
+ \input {luatex-gadgets}%
}
+% We also patch the version number:
+
\edef\fmtversion{\fmtversion+luatex}
\dump
diff --git a/src/fontloader/misc/fontloader-test.tex b/src/fontloader/misc/fontloader-test.tex
index 6f48e0c..f851aab 100644
--- a/src/fontloader/misc/fontloader-test.tex
+++ b/src/fontloader/misc/fontloader-test.tex
@@ -1,3 +1,5 @@
+% texformat=luatex-plain
+
%D \module
%D [ file=luatex-test,
%D version=2009.12.01,
@@ -33,12 +35,12 @@
\font\mathtest=cambria(math) {\mathtest 123}
-\font\gothic=msgothic(ms-gothic) {\gothic whatever}
+% \font\gothic=msgothic(ms-gothic) {\gothic whatever} % no longer in windows 10
\bgroup
- \pdfprotrudechars2
- \pdfadjustspacing2
+ \ifdefined\pdfprotrudechars \pdfprotrudechars \else \protrudechars \fi 2 \relax
+ \ifdefined\pdfadjustspacing \pdfadjustspacing \else \adjustspacing \fi 2 \relax
\font\testb=file:lmroman12-regular:+liga;extend=1.5 at 12pt \testb \input tufte \par
\font\testb=file:lmroman12-regular:+liga;slant=0.8 at 12pt \testb \input tufte \par
@@ -48,12 +50,30 @@
\setmplibformat{plain}
+\directlua {
+ function MpTest()
+ metapost.print("fullcircle scaled 3cm")
+ end
+}
+
\mplibcode
beginfig(1) ;
draw fullcircle
scaled 10cm
withcolor red
withpen pencircle xscaled 4mm yscaled 2mm rotated 30 ;
+ draw "test" infont defaultfont scaled 4 ;
+ verbatimtex \sl etex;
+ draw btex some more test etex scaled 2 ;
+ currentpicture := currentpicture shifted (0,1cm) ;
+ verbatimtex \bf etex;
+ draw btex another test etex scaled 2 ;
+ currentpicture := currentpicture shifted (0,1cm) ;
+ draw btex another test etex scaled 2 ;
+ draw
+ runscript("MpTest()")
+ withcolor green
+ withpen pencircle xscaled 2mm yscaled 1mm rotated 20 ;
endfig ;
\endmplibcode
diff --git a/src/fontloader/misc/fontloader-util-str.lua b/src/fontloader/misc/fontloader-util-str.lua
index c2139b1..95534c8 100644
--- a/src/fontloader/misc/fontloader-util-str.lua
+++ b/src/fontloader/misc/fontloader-util-str.lua
@@ -6,7 +6,7 @@ if not modules then modules = { } end modules ['util-str'] = {
license = "see context related readme files"
}
-utilities = utilities or {}
+utilities = utilities or { }
utilities.strings = utilities.strings or { }
local strings = utilities.strings
@@ -354,7 +354,16 @@ function string.autosingle(s,sep)
return ("'" .. tostring(s) .. "'")
end
-local tracedchars = { }
+local tracedchars = { [0] =
+ -- the regular bunch
+ "[null]", "[soh]", "[stx]", "[etx]", "[eot]", "[enq]", "[ack]", "[bel]",
+ "[bs]", "[ht]", "[lf]", "[vt]", "[ff]", "[cr]", "[so]", "[si]",
+ "[dle]", "[dc1]", "[dc2]", "[dc3]", "[dc4]", "[nak]", "[syn]", "[etb]",
+ "[can]", "[em]", "[sub]", "[esc]", "[fs]", "[gs]", "[rs]", "[us]",
+ -- plus space
+ "[space]", -- 0x20
+}
+
string.tracedchars = tracedchars
strings.tracers = tracedchars
diff --git a/src/fontloader/runtime/fontloader-reference.lua b/src/fontloader/runtime/fontloader-reference.lua
index d8095a2..a2a598b 100644
--- a/src/fontloader/runtime/fontloader-reference.lua
+++ b/src/fontloader/runtime/fontloader-reference.lua
@@ -1,6 +1,6 @@
-- merged file : luatex-fonts-merged.lua
-- parent file : luatex-fonts.lua
--- merge date : 05/24/15 12:42:55
+-- merge date : 10/09/15 21:28:28
do -- begin closure to overcome local limits and interference
@@ -57,21 +57,33 @@ if not package.loaders then
end
local print,select,tostring=print,select,tostring
local inspectors={}
-function setinspector(inspector)
- inspectors[#inspectors+1]=inspector
+function setinspector(kind,inspector)
+ inspectors[kind]=inspector
end
function inspect(...)
for s=1,select("#",...) do
local value=select(s,...)
- local done=false
- for i=1,#inspectors do
- done=inspectors[i](value)
- if done then
- break
+ if value==nil then
+ print("nil")
+ else
+ local done=false
+ local kind=type(value)
+ local inspector=inspectors[kind]
+ if inspector then
+ done=inspector(value)
+ if done then
+ break
+ end
+ end
+ for kind,inspector in next,inspectors do
+ done=inspector(value)
+ if done then
+ break
+ end
+ end
+ if not done then
+ print(tostring(value))
end
- end
- if not done then
- print(tostring(value))
end
end
end
@@ -112,7 +124,7 @@ local floor=math.floor
local P,R,S,V,Ct,C,Cs,Cc,Cp,Cmt=lpeg.P,lpeg.R,lpeg.S,lpeg.V,lpeg.Ct,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.Cp,lpeg.Cmt
local lpegtype,lpegmatch,lpegprint=lpeg.type,lpeg.match,lpeg.print
if setinspector then
- setinspector(function(v) if lpegtype(v) then lpegprint(v) return true end end)
+ setinspector("lpeg",function(v) if lpegtype(v) then lpegprint(v) return true end end)
end
lpeg.patterns=lpeg.patterns or {}
local patterns=lpeg.patterns
@@ -995,9 +1007,10 @@ function string.valid(str,default)
return (type(str)=="string" and str~="" and str) or default or nil
end
string.itself=function(s) return s end
-local pattern=Ct(C(1)^0)
-function string.totable(str)
- return lpegmatch(pattern,str)
+local pattern_c=Ct(C(1)^0)
+local pattern_b=Ct((C(1)/byte)^0)
+function string.totable(str,bytes)
+ return lpegmatch(bytes and pattern_b or pattern_c,str)
end
local replacer=lpeg.replacer("@","%%")
function string.tformat(fmt,...)
@@ -1884,7 +1897,7 @@ function table.print(t,...)
end
end
if setinspector then
- setinspector(function(v) if type(v)=="table" then serialize(print,v,"table") return true end end)
+ setinspector("table",function(v) if type(v)=="table" then serialize(print,v,"table") return true end end)
end
function table.sub(t,i,j)
return { unpack(t,i,j) }
@@ -2937,7 +2950,13 @@ function string.autosingle(s,sep)
end
return ("'"..tostring(s).."'")
end
-local tracedchars={}
+local tracedchars={ [0]=
+ "[null]","[soh]","[stx]","[etx]","[eot]","[enq]","[ack]","[bel]",
+ "[bs]","[ht]","[lf]","[vt]","[ff]","[cr]","[so]","[si]",
+ "[dle]","[dc1]","[dc2]","[dc3]","[dc4]","[nak]","[syn]","[etb]",
+ "[can]","[em]","[sub]","[esc]","[fs]","[gs]","[rs]","[us]",
+ "[space]",
+}
string.tracedchars=tracedchars
strings.tracers=tracedchars
function string.tracedchar(b)
@@ -3886,6 +3905,8 @@ local nodecodes={} for k,v in next,node.types () do nodecodes[string.gsub(v,"_"
local whatcodes={} for k,v in next,node.whatsits() do whatcodes[string.gsub(v,"_","")]=k end
local glyphcodes={ [0]="character","glyph","ligature","ghost","left","right" }
local disccodes={ [0]="discretionary","explicit","automatic","regular","first","second" }
+for i=0,#glyphcodes do glyphcodes[glyphcodes[i]]=i end
+for i=0,#disccodes do disccodes [disccodes [i]]=i end
nodes.nodecodes=nodecodes
nodes.whatcodes=whatcodes
nodes.whatsitcodes=whatcodes
@@ -4361,6 +4382,7 @@ function constructors.scale(tfmdata,specification)
local hdelta=delta
local vdelta=delta
target.designsize=parameters.designsize
+ target.units=units
target.units_per_em=units
local direction=properties.direction or tfmdata.direction or 0
target.direction=direction
@@ -4472,21 +4494,28 @@ function constructors.scale(tfmdata,specification)
target.nomath=true
target.mathparameters=nil
end
- local italickey="italic"
- local useitalics=true
if hasmath then
- autoitalicamount=false
- elseif properties.textitalics then
- italickey="italic_correction"
- useitalics=false
- if properties.delaytextitalics then
+ local mathitalics=properties.mathitalics
+ if mathitalics==false then
+ if trace_defining then
+ report_defining("%s italics %s for font %a, fullname %a, filename %a","math",hasitalics and "ignored" or "disabled",name,fullname,filename)
+ end
+ hasitalics=false
+ autoitalicamount=false
+ end
+ else
+ local textitalics=properties.textitalics
+ if textitalics==false then
+ if trace_defining then
+ report_defining("%s italics %s for font %a, fullname %a, filename %a","text",hasitalics and "ignored" or "disabled",name,fullname,filename)
+ end
+ hasitalics=false
autoitalicamount=false
end
end
if trace_defining then
report_defining("defining tfm, name %a, fullname %a, filename %a, hscale %a, vscale %a, math %a, italics %a",
- name,fullname,filename,hdelta,vdelta,
- hasmath and "enabled" or "disabled",useitalics and "enabled" or "disabled")
+ name,fullname,filename,hdelta,vdelta,hasmath and "enabled" or "disabled",hasitalics and "enabled" or "disabled")
end
constructors.beforecopyingcharacters(target,tfmdata)
local sharedkerns={}
@@ -4584,22 +4613,6 @@ function constructors.scale(tfmdata,specification)
chr.right_protruding=protrusionfactor*width*vr
end
end
- if autoitalicamount then
- local vi=description.italic
- if not vi then
- local vi=description.boundingbox[3]-description.width+autoitalicamount
- if vi>0 then
- chr[italickey]=vi*hdelta
- end
- elseif vi~=0 then
- chr[italickey]=vi*hdelta
- end
- elseif hasitalics then
- local vi=description.italic
- if vi and vi~=0 then
- chr[italickey]=vi*hdelta
- end
- end
if hasmath then
local vn=character.next
if vn then
@@ -4637,7 +4650,7 @@ function constructors.scale(tfmdata,specification)
end
end
end
- local va=character.top_accent
+ local va=character.accent
if va then
chr.top_accent=vdelta*va
end
@@ -4660,6 +4673,27 @@ function constructors.scale(tfmdata,specification)
chr.mathkern=kerns
end
end
+ if hasitalics then
+ local vi=character.italic
+ if vi and vi~=0 then
+ chr.italic=vi*hdelta
+ end
+ end
+ elseif autoitalicamount then
+ local vi=description.italic
+ if not vi then
+ local vi=description.boundingbox[3]-description.width+autoitalicamount
+ if vi>0 then
+ chr.italic=vi*hdelta
+ end
+ elseif vi~=0 then
+ chr.italic=vi*hdelta
+ end
+ elseif hasitalics then
+ local vi=character.italic
+ if vi and vi~=0 then
+ chr.italic=vi*hdelta
+ end
end
if haskerns then
local vk=character.kerns
@@ -4722,6 +4756,7 @@ function constructors.scale(tfmdata,specification)
end
targetcharacters[unicode]=chr
end
+ properties.setitalics=hasitalics
constructors.aftercopyingcharacters(target,tfmdata)
constructors.trytosharefont(target,tfmdata)
return target
@@ -4762,11 +4797,20 @@ function constructors.finalize(tfmdata)
if not parameters.slantfactor then
parameters.slantfactor=tfmdata.slant or 0
end
- if not parameters.designsize then
- parameters.designsize=tfmdata.designsize or (factors.pt*10)
+ local designsize=parameters.designsize
+ if designsize then
+ parameters.minsize=tfmdata.minsize or designsize
+ parameters.maxsize=tfmdata.maxsize or designsize
+ else
+ designsize=factors.pt*10
+ parameters.designsize=designsize
+ parameters.minsize=designsize
+ parameters.maxsize=designsize
end
+ parameters.minsize=tfmdata.minsize or parameters.designsize
+ parameters.maxsize=tfmdata.maxsize or parameters.designsize
if not parameters.units then
- parameters.units=tfmdata.units_per_em or 1000
+ parameters.units=tfmdata.units or tfmdata.units_per_em or 1000
end
if not tfmdata.descriptions then
local descriptions={}
@@ -4829,6 +4873,7 @@ function constructors.finalize(tfmdata)
tfmdata.auto_protrude=nil
tfmdata.extend=nil
tfmdata.slant=nil
+ tfmdata.units=nil
tfmdata.units_per_em=nil
tfmdata.cache=nil
properties.finalized=true
@@ -5393,24 +5438,13 @@ 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 ""
- if lumfile~="" and lfs.isfile(lumfile) then
- if trace_loading or trace_mapping then
- report_fonts("loading map table %a",lumfile)
- end
- lumunic=dofile(lumfile)
- return lumunic,lumfile
- end
-end
local hex=R("AF","09")
-local hexfour=(hex*hex*hex*hex)/function(s) return tonumber(s,16) end
-local hexsix=(hex*hex*hex*hex*hex*hex)/function(s) return tonumber(s,16) end
+local hexfour=(hex*hex*hex^-2)/function(s) return tonumber(s,16) end
+local hexsix=(hex*hex*hex^-4)/function(s) return tonumber(s,16) end
local dec=(R("09")^1)/tonumber
local period=P(".")
-local unicode=P("uni")*(hexfour*(period+P(-1))*Cc(false)+Ct(hexfour^1)*Cc(true))
-local ucode=P("u")*(hexsix*(period+P(-1))*Cc(false)+Ct(hexsix^1)*Cc(true))
+local unicode=(P("uni")+P("UNI"))*(hexfour*(period+P(-1))*Cc(false)+Ct(hexfour^1)*Cc(true))
+local ucode=(P("u")+P("U") )*(hexsix*(period+P(-1))*Cc(false)+Ct(hexsix^1)*Cc(true))
local index=P("index")*dec*Cc(false)
local parser=unicode+ucode+index
local parsers={}
@@ -5485,7 +5519,6 @@ local function fromunicode16(str)
return (tonumber(l,16))*0x400+tonumber(r,16)-0xDC00
end
end
-mappings.loadlumtable=loadlumtable
mappings.makenameparser=makenameparser
mappings.tounicode=tounicode
mappings.tounicode16=tounicode16
@@ -5516,244 +5549,162 @@ for k,v in next,overloads do
end
end
mappings.overloads=overloads
-function mappings.addtounicode(data,filename)
+function mappings.addtounicode(data,filename,checklookups)
local resources=data.resources
- local properties=data.properties
- local descriptions=data.descriptions
local unicodes=resources.unicodes
- local lookuptypes=resources.lookuptypes
if not unicodes then
return
end
+ local properties=data.properties
+ local descriptions=data.descriptions
unicodes['space']=unicodes['space'] or 32
unicodes['hyphen']=unicodes['hyphen'] or 45
unicodes['zwj']=unicodes['zwj'] or 0x200D
unicodes['zwnj']=unicodes['zwnj'] or 0x200C
- local private=fonts.constructors.privateoffset
- local unicodevector=fonts.encodings.agl.unicodes
+ local private=fonts.constructors and fonts.constructors.privateoffset or 0xF0000
+ local unicodevector=fonts.encodings.agl.unicodes or {}
+ local contextvector=fonts.encodings.agl.ctxcodes or {}
local missing={}
- local lumunic,uparser,oparser
- local cidinfo,cidnames,cidcodes,usedmap
- cidinfo=properties.cidinfo
- usedmap=cidinfo and fonts.cid.getmap(cidinfo)
+ local nofmissing=0
+ local oparser=nil
+ local cidnames=nil
+ local cidcodes=nil
+ local cidinfo=properties.cidinfo
+ local usedmap=cidinfo and fonts.cid.getmap(cidinfo)
+ local uparser=makenameparser()
if usedmap then
- oparser=usedmap and makenameparser(cidinfo.ordering)
- cidnames=usedmap.names
- cidcodes=usedmap.unicodes
+ oparser=usedmap and makenameparser(cidinfo.ordering)
+ cidnames=usedmap.names
+ cidcodes=usedmap.unicodes
end
- uparser=makenameparser()
- local ns,nl=0,0
+ local ns=0
+ local nl=0
for unic,glyph in next,descriptions do
- local index=glyph.index
local name=glyph.name
- local r=overloads[name]
- if r then
- glyph.unicode=r.unicode
- elseif unic==-1 or unic>=private or (unic>=0xE000 and unic<=0xF8FF) or unic==0xFFFE or unic==0xFFFF then
- local unicode=lumunic and lumunic[name] or unicodevector[name]
- if unicode then
- glyph.unicode=unicode
- ns=ns+1
- end
- if (not unicode) and usedmap then
- local foundindex=lpegmatch(oparser,name)
- if foundindex then
- unicode=cidcodes[foundindex]
- if unicode then
- glyph.unicode=unicode
- ns=ns+1
- else
- local reference=cidnames[foundindex]
- if reference then
- local foundindex=lpegmatch(oparser,reference)
- if foundindex then
- unicode=cidcodes[foundindex]
- if unicode then
- glyph.unicode=unicode
- ns=ns+1
- end
- end
- if not unicode or unicode=="" then
- local foundcodes,multiple=lpegmatch(uparser,reference)
- if foundcodes then
- glyph.unicode=foundcodes
- if multiple then
- nl=nl+1
- unicode=true
- else
+ if name then
+ local index=glyph.index
+ local r=overloads[name]
+ if r then
+ glyph.unicode=r.unicode
+ elseif not unic or unic==-1 or unic>=private or (unic>=0xE000 and unic<=0xF8FF) or unic==0xFFFE or unic==0xFFFF then
+ local unicode=unicodevector[name] or contextvector[name]
+ if unicode then
+ glyph.unicode=unicode
+ ns=ns+1
+ end
+ if (not unicode) and usedmap then
+ local foundindex=lpegmatch(oparser,name)
+ if foundindex then
+ unicode=cidcodes[foundindex]
+ if unicode then
+ glyph.unicode=unicode
+ ns=ns+1
+ else
+ local reference=cidnames[foundindex]
+ if reference then
+ local foundindex=lpegmatch(oparser,reference)
+ if foundindex then
+ unicode=cidcodes[foundindex]
+ if unicode then
+ glyph.unicode=unicode
ns=ns+1
- unicode=foundcodes
+ end
+ end
+ if not unicode or unicode=="" then
+ local foundcodes,multiple=lpegmatch(uparser,reference)
+ if foundcodes then
+ glyph.unicode=foundcodes
+ if multiple then
+ nl=nl+1
+ unicode=true
+ else
+ ns=ns+1
+ unicode=foundcodes
+ end
end
end
end
end
end
end
- end
- if not unicode or unicode=="" then
- local split=lpegmatch(namesplitter,name)
- local nsplit=split and #split or 0
- local t,n={},0
- unicode=true
- for l=1,nsplit do
- local base=split[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
+ if not unicode or unicode=="" then
+ local split=lpegmatch(namesplitter,name)
+ local nsplit=split and #split or 0
+ if nsplit==0 then
+ elseif nsplit==1 then
+ local base=split[1]
+ local u=unicodes[base] or unicodevector[base] or contextvector[name]
+ if not u then
+ elseif type(u)=="table" then
+ if u[1]=private or (unic>=0xE000 and unic<=0xF8FF) or unic==0xFFFE or unic==0xFFFF then
- else
- return
- end
- if descriptions[code].unicode then
- return
- end
- local g=guess[variant]
- if g then
- g[gname]=unicode
- else
- guess[variant]={ [gname]=unicode }
- end
- end
- for unicode,description in next,descriptions do
- local slookups=description.slookups
- if slookups then
- local gname=description.name
- for tag,data in next,slookups do
- local lookuptype=lookuptypes[tag]
- if lookuptype=="alternate" then
- for i=1,#data do
- check(gname,data[i],unicode)
- end
- elseif lookuptype=="substitution" then
- check(gname,data,unicode)
- end
- end
- end
- local mlookups=description.mlookups
- if mlookups then
- local gname=description.name
- for tag,list in next,mlookups do
- local lookuptype=lookuptypes[tag]
- if lookuptype=="alternate" then
- for i=1,#list do
- local data=list[i]
- for i=1,#data do
- check(gname,data[i],unicode)
+ local t,n={},0
+ for l=1,nsplit do
+ local base=split[l]
+ local u=unicodes[base] or unicodevector[base] or contextvector[name]
+ if not u then
+ break
+ elseif type(u)=="table" then
+ if u[1]>=private then
+ break
+ end
+ n=n+1
+ t[n]=u[1]
+ else
+ if u>=private then
+ break
+ end
+ n=n+1
+ t[n]=u
end
end
- elseif lookuptype=="substitution" then
- for i=1,#list do
- check(gname,list[i],unicode)
+ if n>0 then
+ if n==1 then
+ unicode=t[1]
+ else
+ unicode=t
+ end
+ glyph.unicode=unicode
end
end
- end
- end
- end
- local done=true
- while done do
- done=false
- for k,v in next,guess do
- if type(v)~="number" then
- for kk,vv in next,v do
- if vv==-1 or vv>=private or (vv>=0xE000 and vv<=0xF8FF) or vv==0xFFFE or vv==0xFFFF then
- local uu=guess[kk]
- if type(uu)=="number" then
- guess[k]=uu
- done=true
- end
+ nl=nl+1
+ end
+ if not unicode or unicode=="" then
+ local foundcodes,multiple=lpegmatch(uparser,name)
+ if foundcodes then
+ glyph.unicode=foundcodes
+ if multiple then
+ nl=nl+1
+ unicode=true
else
- guess[k]=vv
- done=true
+ ns=ns+1
+ unicode=foundcodes
end
end
end
- end
- end
- local orphans=0
- local guessed=0
- for k,v in next,guess do
- if type(v)=="number" then
- descriptions[unicodes[k]].unicode=descriptions[v].unicode or v
- guessed=guessed+1
- else
- local t=nil
- local l=lower(k)
- local u=unicodes[l]
- if not u then
- orphans=orphans+1
- elseif u==-1 or u>=private or (u>=0xE000 and u<=0xF8FF) or u==0xFFFE or u==0xFFFF then
- local unicode=descriptions[u].unicode
- if unicode then
- descriptions[unicodes[k]].unicode=unicode
- guessed=guessed+1
- else
- orphans=orphans+1
- end
- else
- orphans=orphans+1
+ local r=overloads[unicode]
+ if r then
+ unicode=r.unicode
+ glyph.unicode=unicode
+ end
+ if not unicode then
+ missing[unic]=true
+ nofmissing=nofmissing+1
end
end
- end
- if trace_loading and orphans>0 or guessed>0 then
- report_fonts("%s glyphs with no related unicode, %s guessed, %s orphans",guessed+orphans,guessed,orphans)
+ else
end
end
+ if type(checklookups)=="function" then
+ checklookups(data,missing,nofmissing)
+ end
if trace_mapping then
for unic,glyph in table.sortedhash(descriptions) do
local name=glyph.name
@@ -5881,6 +5832,7 @@ local readers=fonts.readers
local constructors=fonts.constructors
local encodings=fonts.encodings
local tfm=constructors.newhandler("tfm")
+tfm.version=1.000
local tfmfeatures=constructors.newfeatures("tfm")
local registertfmfeature=tfmfeatures.register
constructors.resolvevirtualtoo=false
@@ -6067,7 +6019,7 @@ local keys={}
function keys.FontName (data,line) data.metadata.fontname=strip (line)
data.metadata.fullname=strip (line) end
function keys.ItalicAngle (data,line) data.metadata.italicangle=tonumber (line) end
-function keys.IsFixedPitch(data,line) data.metadata.isfixedpitch=toboolean(line,true) end
+function keys.IsFixedPitch(data,line) data.metadata.monospaced=toboolean(line,true) end
function keys.CharWidth (data,line) data.metadata.charwidth=tonumber (line) end
function keys.XHeight (data,line) data.metadata.xheight=tonumber (line) end
function keys.Descender (data,line) data.metadata.descender=tonumber (line) end
@@ -6489,7 +6441,7 @@ local function copytotfm(data)
local emdash=0x2014
local spacer="space"
local spaceunits=500
- local monospaced=metadata.isfixedpitch
+ local monospaced=metadata.monospaced
local charwidth=metadata.charwidth
local italicangle=metadata.italicangle
local charxheight=metadata.xheight and metadata.xheight>0 and metadata.xheight
@@ -7144,12 +7096,10 @@ if not modules then modules={} end modules ['font-otf']={
license="see context related readme files"
}
local utfbyte=utf.byte
-local format,gmatch,gsub,find,match,lower,strip=string.format,string.gmatch,string.gsub,string.find,string.match,string.lower,string.strip
+local gmatch,gsub,find,match,lower,strip=string.gmatch,string.gsub,string.find,string.match,string.lower,string.strip
local type,next,tonumber,tostring=type,next,tonumber,tostring
local abs=math.abs
-local insert=table.insert
-local lpegmatch=lpeg.match
-local reversed,concat,remove,sortedkeys=table.reversed,table.concat,table.remove,table.sortedkeys
+local reversed,concat,insert,remove,sortedkeys=table.reversed,table.concat,table.insert,table.remove,table.sortedkeys
local ioflush=io.flush
local fastcopy,tohash,derivetable=table.fastcopy,table.tohash,table.derive
local formatters=string.formatters
@@ -7176,7 +7126,7 @@ local report_otf=logs.reporter("fonts","otf loading")
local fonts=fonts
local otf=fonts.handlers.otf
otf.glists={ "gsub","gpos" }
-otf.version=2.812
+otf.version=2.819
otf.cache=containers.define("fonts","otf",otf.version,true)
local hashes=fonts.hashes
local definers=fonts.definers
@@ -7353,10 +7303,10 @@ local ordered_enhancers={
"reorganize subtables",
"check glyphs",
"check metadata",
- "check extra features",
"prepare tounicode",
"check encoding",
"add duplicates",
+ "expand lookups",
"cleanup tables",
"compact lookups",
"purge names",
@@ -7493,6 +7443,7 @@ function otf.load(filename,sub,featurefile)
end
end
if reload then
+ starttiming("fontloader")
report_otf("loading %a, hash %a",filename,hash)
local fontdata,messages
if sub then
@@ -7526,6 +7477,7 @@ function otf.load(filename,sub,featurefile)
data={
size=size,
time=time,
+ subfont=sub,
format=otf_format(filename),
featuredata=featurefiles,
resources={
@@ -7553,7 +7505,6 @@ function otf.load(filename,sub,featurefile)
tounicodetable=Ct(splitter),
},
}
- starttiming(data)
report_otf("file size: %s",size)
enhancers.apply(data,filename,fontdata)
local packtime={}
@@ -7570,10 +7521,10 @@ function otf.load(filename,sub,featurefile)
if cleanup>1 then
collectgarbage("collect")
end
- stoptiming(data)
+ stoptiming("fontloader")
if elapsedtime then
- report_otf("preprocessing and caching time %s, packtime %s",
- elapsedtime(data),packdata and elapsedtime(packtime) or 0)
+ report_otf("loading, optimizing, packing and caching time %s, pack time %s",
+ elapsedtime("fontloader"),packdata and elapsedtime(packtime) or 0)
end
close_font(fontdata)
if cleanup>3 then
@@ -7584,6 +7535,7 @@ function otf.load(filename,sub,featurefile)
collectgarbage("collect")
end
else
+ stoptiming("fontloader")
data=nil
report_otf("loading failed due to read error")
end
@@ -7625,6 +7577,7 @@ function otf.load(filename,sub,featurefile)
applyruntimefixes(filename,data)
end
enhance("add dimensions",data,filename,nil,false)
+enhance("check extra features",data,filename)
if trace_sequences then
showfeatureorder(data,filename)
end
@@ -7785,7 +7738,7 @@ actions["prepare glyphs"]=function(data,filename,raw)
end
if not unicode or unicode==-1 then
if not name then
- name=format("u%06X.ctx",private)
+ name=formatters["u%06X.ctx"](private)
end
unicode=private
unicodes[name]=private
@@ -7796,7 +7749,7 @@ actions["prepare glyphs"]=function(data,filename,raw)
nofnames=nofnames+1
else
if not name then
- name=format("u%06X.ctx",unicode)
+ name=formatters["u%06X.ctx"](unicode)
end
unicodes[name]=unicode
nofunicodes=nofunicodes+1
@@ -7810,25 +7763,25 @@ actions["prepare glyphs"]=function(data,filename,raw)
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
+ 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
@@ -8014,7 +7967,7 @@ actions["add duplicates"]=function(data,filename,raw)
end
if u>0 then
local duplicate=table.copy(description)
- duplicate.comment=format("copy of U+%05X",unicode)
+ duplicate.comment=formatters["copy of %U"](unicode)
descriptions[u]=duplicate
if trace_loading then
report_otf("duplicating %U to %U with index %H (%s kerns)",unicode,u,description.index,n)
@@ -8035,7 +7988,7 @@ actions["analyze glyphs"]=function(data,filename,raw)
local marks={}
for unicode,description in next,descriptions do
local glyph=description.glyph
- local italic=glyph.italic_correction
+ local italic=glyph.italic_correction
if not italic then
elseif italic==0 then
else
@@ -8096,7 +8049,8 @@ end
actions["reorganize features"]=function(data,filename,raw)
local features={}
data.resources.features=features
- for k,what in next,otf.glists do
+ for k=1,#otf.glists do
+ local what=otf.glists[k]
local dw=raw[what]
if dw then
local f={}
@@ -8178,8 +8132,9 @@ actions["reorganize subtables"]=function(data,filename,raw)
local lookups={}
local chainedfeatures={}
resources.sequences=sequences
- resources.lookups=lookups
- for _,what in next,otf.glists do
+ resources.lookups=lookups
+ for k=1,#otf.glists do
+ local what=otf.glists[k]
local dw=raw[what]
if dw then
for k=1,#dw do
@@ -8353,12 +8308,15 @@ local function r_uncover(splitter,cache,cover,replacements)
end
actions["reorganize lookups"]=function(data,filename,raw)
if data.lookups then
- local splitter=data.helpers.tounicodetable
+ local helpers=data.helpers
+ local duplicates=data.resources.duplicates
+ local splitter=helpers.tounicodetable
local t_u_cache={}
local s_u_cache=t_u_cache
local t_h_cache={}
local s_h_cache=t_h_cache
local r_u_cache={}
+ helpers.matchcache=t_h_cache
for _,lookup in next,data.lookups do
local rules=lookup.rules
if rules then
@@ -8504,6 +8462,44 @@ actions["reorganize lookups"]=function(data,filename,raw)
end
end
end
+actions["expand lookups"]=function(data,filename,raw)
+ if data.lookups then
+ local cache=data.helpers.matchcache
+ if cache then
+ local duplicates=data.resources.duplicates
+ for key,hash in next,cache do
+ local done=nil
+ for key in next,hash do
+ local unicode=duplicates[key]
+ if not unicode then
+ elseif type(unicode)=="table" then
+ for i=1,#unicode do
+ local u=unicode[i]
+ if hash[u] then
+ elseif done then
+ done[u]=key
+ else
+ done={ [u]=key }
+ end
+ end
+ else
+ if hash[unicode] then
+ elseif done then
+ done[unicode]=key
+ else
+ done={ [unicode]=key }
+ end
+ end
+ end
+ if done then
+ for u in next,done do
+ hash[u]=true
+ end
+ end
+ end
+ end
+ end
+end
local function check_variants(unicode,the_variants,splitter,unicodes)
local variants=the_variants.variants
if variants then
@@ -8544,11 +8540,11 @@ local function check_variants(unicode,the_variants,splitter,unicodes)
parts=nil
end
end
- local italic_correction=the_variants.italic_correction
- if italic_correction and italic_correction==0 then
- italic_correction=nil
+ local italic=the_variants.italic
+ if italic and italic==0 then
+ italic=nil
end
- return variants,parts,italic_correction
+ return variants,parts,italic
end
actions["analyze math"]=function(data,filename,raw)
if raw.math then
@@ -8558,13 +8554,14 @@ actions["analyze math"]=function(data,filename,raw)
for unicode,description in next,data.descriptions do
local glyph=description.glyph
local mathkerns=glyph.mathkern
- local horiz_variants=glyph.horiz_variants
- local vert_variants=glyph.vert_variants
- local top_accent=glyph.top_accent
- if mathkerns or horiz_variants or vert_variants or top_accent then
+ local hvariants=glyph.horiz_variants
+ local vvariants=glyph.vert_variants
+ local accent=glyph.top_accent
+ local italic=glyph.italic_correction
+ if mathkerns or hvariants or vvariants or accent or italic then
local math={}
- if top_accent then
- math.top_accent=top_accent
+ if accent then
+ math.accent=accent
end
if mathkerns then
for k,v in next,mathkerns do
@@ -8580,15 +8577,14 @@ actions["analyze math"]=function(data,filename,raw)
end
math.kerns=mathkerns
end
- if horiz_variants then
- math.horiz_variants,math.horiz_parts,math.horiz_italic_correction=check_variants(unicode,horiz_variants,splitter,unicodes)
+ if hvariants then
+ math.hvariants,math.hparts,math.hitalic=check_variants(unicode,hvariants,splitter,unicodes)
end
- if vert_variants then
- math.vert_variants,math.vert_parts,math.vert_italic_correction=check_variants(unicode,vert_variants,splitter,unicodes)
+ if vvariants then
+ math.vvariants,math.vparts,math.vitalic=check_variants(unicode,vvariants,splitter,unicodes)
end
- local italic_correction=description.italic
- if italic_correction and italic_correction~=0 then
- math.italic_correction=italic_correction
+ if italic and italic~=0 then
+ math.italic=italic
end
description.math=math
end
@@ -8745,7 +8741,7 @@ actions["merge kern classes"]=function(data,filename,raw)
report_otf("%s kern overloads ignored",ignored)
end
if blocked>0 then
- report_otf("%s succesive kerns blocked",blocked)
+ report_otf("%s successive kerns blocked",blocked)
end
end
end
@@ -8774,16 +8770,18 @@ actions["check metadata"]=function(data,filename,raw)
ttftables[i].data="deleted"
end
end
+ local names=raw.names
if metadata.validation_state and table.contains(metadata.validation_state,"bad_ps_fontname") then
local function valid(what)
- local names=raw.names
- for i=1,#names do
- local list=names[i]
- local names=list.names
- if names then
- local name=names[what]
- if name and valid_ps_name(name) then
- return name
+ if names then
+ for i=1,#names do
+ local list=names[i]
+ local names=list.names
+ if names then
+ local name=names[what]
+ if name and valid_ps_name(name) then
+ return name
+ end
end
end
end
@@ -8806,6 +8804,28 @@ actions["check metadata"]=function(data,filename,raw)
check("fontname")
check("fullname")
end
+ if names then
+ local psname=metadata.psname
+ if not psname or psname=="" then
+ for i=1,#names do
+ local name=names[i]
+ if lower(name.lang)=="english (us)" then
+ local specification=name.names
+ if specification then
+ local postscriptname=specification.postscriptname
+ if postscriptname then
+ psname=postscriptname
+ end
+ end
+ end
+ break
+ end
+ end
+ if psname~=metadata.fontname then
+ report_otf("fontname %a, fullname %a, psname %a",metadata.fontname,metadata.fullname,psname)
+ end
+ metadata.psname=psname
+ end
end
actions["cleanup tables"]=function(data,filename,raw)
local duplicates=data.resources.duplicates
@@ -8901,7 +8921,7 @@ actions["reorganize glyph lookups"]=function(data,filename,raw)
end
end
local zero={ 0,0 }
-actions["reorganize glyph anchors"]=function(data,filename,raw)
+actions["reorganize glyph anchors"]=function(data,filename,raw)
local descriptions=data.descriptions
for unicode,description in next,descriptions do
local anchors=description.glyph.anchors
@@ -9103,9 +9123,13 @@ local function copytotfm(data,cache_id)
local spaceunits=500
local spacer="space"
local designsize=metadata.designsize or metadata.design_size or 100
+ local minsize=metadata.minsize or metadata.design_range_bottom or designsize
+ local maxsize=metadata.maxsize or metadata.design_range_top or designsize
local mathspecs=metadata.math
if designsize==0 then
designsize=100
+ minsize=100
+ maxsize=100
end
if mathspecs then
for name,value in next,mathspecs do
@@ -9120,8 +9144,9 @@ local function copytotfm(data,cache_id)
local d=descriptions[unicode]
local m=d.math
if m then
- local variants=m.horiz_variants
- local parts=m.horiz_parts
+ local italic=m.italic
+ local variants=m.hvariants
+ local parts=m.hparts
if variants then
local c=character
for i=1,#variants do
@@ -9132,9 +9157,10 @@ local function copytotfm(data,cache_id)
c.horiz_variants=parts
elseif parts then
character.horiz_variants=parts
+ italic=m.hitalic
end
- local variants=m.vert_variants
- local parts=m.vert_parts
+ local variants=m.vvariants
+ local parts=m.vparts
if variants then
local c=character
for i=1,#variants do
@@ -9145,14 +9171,14 @@ local function copytotfm(data,cache_id)
c.vert_variants=parts
elseif parts then
character.vert_variants=parts
+ italic=m.vitalic
end
- local italic_correction=m.vert_italic_correction
- if italic_correction then
- character.vert_italic_correction=italic_correction
+ if italic and italic~=0 then
+ character.italic=italic
end
- local top_accent=m.top_accent
- if top_accent then
- character.top_accent=top_accent
+ local accent=m.accent
+ if accent then
+ character.accent=accent
end
local kerns=m.kerns
if kerns then
@@ -9164,14 +9190,14 @@ local function copytotfm(data,cache_id)
local filename=constructors.checkedfilename(resources)
local fontname=metadata.fontname
local fullname=metadata.fullname or fontname
- local psname=fontname or fullname
- local units=metadata.units_per_em or 1000
+ local psname=metadata.psname or fontname or fullname
+ local units=metadata.units or metadata.units_per_em or 1000
if units==0 then
units=1000
- metadata.units_per_em=1000
+ metadata.units=1000
report_otf("changing %a units to %a",0,units)
end
- local monospaced=metadata.isfixedpitch or (pfminfo.panose and pfminfo.panose.proportion=="Monospaced")
+ local monospaced=metadata.monospaced or metadata.isfixedpitch or (pfminfo.panose and pfminfo.panose.proportion=="Monospaced")
local charwidth=pfminfo.avgwidth
local charxheight=pfminfo.os2_xheight and pfminfo.os2_xheight>0 and pfminfo.os2_xheight
local italicangle=metadata.italicangle
@@ -9236,8 +9262,10 @@ local function copytotfm(data,cache_id)
end
end
parameters.designsize=(designsize/10)*65536
- parameters.ascender=abs(metadata.ascent or 0)
- parameters.descender=abs(metadata.descent or 0)
+ parameters.minsize=(minsize/10)*65536
+ parameters.maxsize=(maxsize/10)*65536
+ parameters.ascender=abs(metadata.ascender or metadata.ascent or 0)
+ parameters.descender=abs(metadata.descender or metadata.descent or 0)
parameters.units=units
properties.space=spacer
properties.encodingbytes=2
@@ -9416,6 +9444,99 @@ function otf.scriptandlanguage(tfmdata,attr)
local properties=tfmdata.properties
return properties.script or "dflt",properties.language or "dflt"
end
+local function justset(coverage,unicode,replacement)
+ coverage[unicode]=replacement
+end
+otf.coverup={
+ stepkey="subtables",
+ actions={
+ substitution=justset,
+ alternate=justset,
+ multiple=justset,
+ ligature=justset,
+ kern=justset,
+ },
+ register=function(coverage,lookuptype,format,feature,n,descriptions,resources)
+ local name=formatters["ctx_%s_%s"](feature,n)
+ if lookuptype=="kern" then
+ resources.lookuptypes[name]="position"
+ else
+ resources.lookuptypes[name]=lookuptype
+ end
+ for u,c in next,coverage do
+ local description=descriptions[u]
+ local slookups=description.slookups
+ if slookups then
+ slookups[name]=c
+ else
+ description.slookups={ [name]=c }
+ end
+ end
+ return name
+ end
+}
+local function getgsub(tfmdata,k,kind)
+ local description=tfmdata.descriptions[k]
+ if description then
+ local slookups=description.slookups
+ if slookups then
+ local shared=tfmdata.shared
+ local rawdata=shared and shared.rawdata
+ if rawdata then
+ local lookuptypes=rawdata.resources.lookuptypes
+ if lookuptypes then
+ local properties=tfmdata.properties
+ local validlookups,lookuplist=otf.collectlookups(rawdata,kind,properties.script,properties.language)
+ if validlookups then
+ for l=1,#lookuplist do
+ local lookup=lookuplist[l]
+ local found=slookups[lookup]
+ if found then
+ return found,lookuptypes[lookup]
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
+otf.getgsub=getgsub
+function otf.getsubstitution(tfmdata,k,kind,value)
+ local found,kind=getgsub(tfmdata,k,kind)
+ if not found then
+ elseif kind=="substitution" then
+ return found
+ elseif kind=="alternate" then
+ local choice=tonumber(value) or 1
+ return found[choice] or found[1] or k
+ end
+ return k
+end
+otf.getalternate=otf.getsubstitution
+function otf.getmultiple(tfmdata,k,kind)
+ local found,kind=getgsub(tfmdata,k,kind)
+ if found and kind=="multiple" then
+ return found
+ end
+ return { k }
+end
+function otf.getkern(tfmdata,left,right,kind)
+ local kerns=getgsub(tfmdata,left,kind or "kern",true)
+ if kerns then
+ local found=kerns[right]
+ local kind=type(found)
+ if kind=="table" then
+ found=found[1][3]
+ elseif kind~="number" then
+ found=false
+ end
+ if found then
+ return found*tfmdata.parameters.factor
+ end
+ end
+ return 0
+end
end -- closure
@@ -9946,8 +10067,8 @@ local function featuresinitializer(tfmdata,value)
local collectlookups=otf.collectlookups
local rawdata=tfmdata.shared.rawdata
local properties=tfmdata.properties
- local script=properties.script
- local language=properties.language
+ local script=properties.script
+ local language=properties.language
local basesubstitutions=rawdata.resources.features.gsub
local basepositionings=rawdata.resources.features.gpos
if basesubstitutions or basepositionings then
@@ -10125,7 +10246,8 @@ end
function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmnext)
local dx=factor*(exit[1]-entry[1])
local dy=-factor*(exit[2]-entry[2])
- local ws,wn=tfmstart.width,tfmnext.width
+ local ws=tfmstart.width
+ local wn=tfmnext.width
nofregisteredcursives=nofregisteredcursives+1
if rlmode<0 then
dx=-(dx+wn)
@@ -10172,7 +10294,10 @@ function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmne
return dx,dy,nofregisteredcursives
end
function injections.setpair(current,factor,rlmode,r2lflag,spec,injection)
- local x,y,w,h=factor*spec[1],factor*spec[2],factor*spec[3],factor*spec[4]
+ local x=factor*spec[1]
+ local y=factor*spec[2]
+ local w=factor*spec[3]
+ local h=factor*spec[4]
if x~=0 or w~=0 or y~=0 or h~=0 then
local yoffset=y-h
local leftkern=x
@@ -10182,9 +10307,12 @@ function injections.setpair(current,factor,rlmode,r2lflag,spec,injection)
if rlmode and rlmode<0 then
leftkern,rightkern=rightkern,leftkern
end
+ if not injection then
+ injection="injections"
+ end
local p=rawget(properties,current)
if p then
- local i=rawget(p,"injections")
+ local i=rawget(p,injection)
if i then
if leftkern~=0 then
i.leftkern=(i.leftkern or 0)+leftkern
@@ -10196,19 +10324,19 @@ function injections.setpair(current,factor,rlmode,r2lflag,spec,injection)
i.yoffset=(i.yoffset or 0)+yoffset
end
elseif leftkern~=0 or rightkern~=0 then
- p.injections={
+ p[injection]={
leftkern=leftkern,
rightkern=rightkern,
yoffset=yoffset,
}
else
- p.injections={
+ p[injection]={
yoffset=yoffset,
}
end
elseif leftkern~=0 or rightkern~=0 then
properties[current]={
- injections={
+ [injection]={
leftkern=leftkern,
rightkern=rightkern,
yoffset=yoffset,
@@ -10216,7 +10344,7 @@ function injections.setpair(current,factor,rlmode,r2lflag,spec,injection)
}
else
properties[current]={
- injections={
+ [injection]={
yoffset=yoffset,
},
}
@@ -10255,7 +10383,7 @@ function injections.setkern(current,factor,rlmode,x,injection)
return 0,0
end
end
-function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase)
+function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk)
local dx,dy=factor*(ba[1]-ma[1]),factor*(ba[2]-ma[2])
nofregisteredmarks=nofregisteredmarks+1
if rlmode>=0 then
@@ -10265,11 +10393,15 @@ function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase)
if p then
local i=rawget(p,"injections")
if i then
- i.markx=dx
- i.marky=dy
- i.markdir=rlmode or 0
- i.markbase=nofregisteredmarks
- i.markbasenode=base
+ if i.markmark then
+ else
+ i.markx=dx
+ i.marky=dy
+ i.markdir=rlmode or 0
+ i.markbase=nofregisteredmarks
+ i.markbasenode=base
+ i.markmark=mkmk
+ end
else
p.injections={
markx=dx,
@@ -10277,6 +10409,7 @@ function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase)
markdir=rlmode or 0,
markbase=nofregisteredmarks,
markbasenode=base,
+ markmark=mkmk,
}
end
else
@@ -10287,6 +10420,7 @@ function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase)
markdir=rlmode or 0,
markbase=nofregisteredmarks,
markbasenode=base,
+ markmark=mkmk,
},
}
end
@@ -10391,27 +10525,33 @@ local function show_result(head)
current=getnext(current)
end
end
-local function collect_glyphs_1(head)
- local glyphs,nofglyphs={},0
- local marks,nofmarks={},0
+local function collect_glyphs(head,offsets)
+ local glyphs,glyphi,nofglyphs={},{},0
+ local marks,marki,nofmarks={},{},0
local nf,tm=nil,nil
- for n in traverse_id(glyph_code,head) do
- if getsubtype(n)<256 then
- local f=getfont(n)
- if f~=nf then
- nf=f
- tm=fontdata[nf].resources.marks
- end
- if tm and tm[getchar(n)] then
- nofmarks=nofmarks+1
- marks[nofmarks]=n
- else
- nofglyphs=nofglyphs+1
- glyphs[nofglyphs]=n
- end
+ local n=head
+ local function identify(n,what)
+ local f=getfont(n)
+ if f~=nf then
+ nf=f
+ tm=fontdata[nf].resources
+ if tm then
+ tm=tm.marks
+ end
+ end
+ if tm and tm[getchar(n)] then
+ nofmarks=nofmarks+1
+ marks[nofmarks]=n
+ marki[nofmarks]="injections"
+ else
+ nofglyphs=nofglyphs+1
+ glyphs[nofglyphs]=n
+ glyphi[nofglyphs]=what
+ end
+ if offsets then
local p=rawget(properties,n)
if p then
- local i=rawget(p,"injections")
+ local i=rawget(p,what)
if i then
local yoffset=i.yoffset
if yoffset and yoffset~=0 then
@@ -10421,36 +10561,47 @@ local function collect_glyphs_1(head)
end
end
end
- return glyphs,nofglyphs,marks,nofmarks
-end
-local function collect_glyphs_2(head)
- local glyphs,nofglyphs={},0
- local marks,nofmarks={},0
- local nf,tm=nil,nil
- for n in traverse_id(glyph_code,head) do
- if getsubtype(n)<256 then
- local f=getfont(n)
- if f~=nf then
- nf=f
- tm=fontdata[nf].resources.marks
- end
- if tm and tm[getchar(n)] then
- nofmarks=nofmarks+1
- marks[nofmarks]=n
- else
- nofglyphs=nofglyphs+1
- glyphs[nofglyphs]=n
- end
+ while n do
+ local id=getid(n)
+ if id==glyph_code then
+ identify(n,"injections")
+ elseif id==disc_code then
+ local d=getfield(n,"pre")
+ if d then
+ for n in traverse_id(glyph_code,d) do
+ if getsubtype(n)<256 then
+ identify(n,"preinjections")
+ end
+ end
+ end
+ local d=getfield(n,"post")
+ if d then
+ for n in traverse_id(glyph_code,d) do
+ if getsubtype(n)<256 then
+ identify(n,"postinjections")
+ end
+ end
+ end
+ local d=getfield(n,"replace")
+ if d then
+ for n in traverse_id(glyph_code,d) do
+ if getsubtype(n)<256 then
+ identify(n,"replaceinjections")
+ end
+ end
+ end
end
+ n=getnext(n)
end
- return glyphs,nofglyphs,marks,nofmarks
+ return glyphs,glyphi,nofglyphs,marks,marki,nofmarks
end
-local function inject_marks(marks,nofmarks)
+local function inject_marks(marks,marki,nofmarks)
for i=1,nofmarks do
local n=marks[i]
local pn=rawget(properties,n)
if pn then
- pn=rawget(pn,"injections")
+ local ni=marki[i]
+ local pn=rawget(pn,ni)
if pn then
local p=pn.markbasenode
if p then
@@ -10459,7 +10610,7 @@ local function inject_marks(marks,nofmarks)
local rightkern=nil
local pp=rawget(properties,p)
if pp then
- pp=rawget(pp,"injections")
+ pp=rawget(pp,ni)
if pp then
rightkern=pp.rightkern
end
@@ -10468,11 +10619,17 @@ local function inject_marks(marks,nofmarks)
if pn.markdir<0 then
ox=px-pn.markx-rightkern
else
- local leftkern=pp.leftkern
- if leftkern then
- ox=px-pn.markx
+
+
+ if false then
+ local leftkern=pp.leftkern
+ if leftkern then
+ ox=px-pn.markx-leftkern
+ else
+ ox=px-pn.markx
+ end
else
- ox=px-pn.markx-leftkern
+ ox=px-pn.markx
end
end
else
@@ -10485,12 +10642,7 @@ local function inject_marks(marks,nofmarks)
end
setfield(n,"xoffset",ox)
local py=getfield(p,"yoffset")
- local oy=0
- if marks[p] then
- oy=py+pn.marky
- else
- oy=getfield(n,"yoffset")+py+pn.marky
- end
+ local oy=getfield(n,"yoffset")+py+pn.marky
setfield(n,"yoffset",oy)
else
end
@@ -10498,14 +10650,14 @@ local function inject_marks(marks,nofmarks)
end
end
end
-local function inject_cursives(glyphs,nofglyphs)
+local function inject_cursives(glyphs,glyphi,nofglyphs)
local cursiveanchor,lastanchor=nil,nil
local minc,maxc,last=0,0,nil
for i=1,nofglyphs do
local n=glyphs[i]
local pn=rawget(properties,n)
if pn then
- pn=rawget(pn,"injections")
+ pn=rawget(pn,glyphi[i])
end
if pn then
local cursivex=pn.cursivex
@@ -10571,22 +10723,59 @@ local function inject_cursives(glyphs,nofglyphs)
end
end
end
-local function inject_kerns(head,list,length)
+local function inject_kerns(head,glist,ilist,length)
for i=1,length do
- local n=list[i]
+ local n=glist[i]
local pn=rawget(properties,n)
if pn then
- local i=rawget(pn,"injections")
- if i then
- local leftkern=i.leftkern
- if leftkern and leftkern~=0 then
- insert_node_before(head,n,newkern(leftkern))
- end
- local rightkern=i.rightkern
- if rightkern and rightkern~=0 then
- insert_node_after(head,n,newkern(rightkern))
- end
- end
+ local dp=nil
+ local dr=nil
+ local ni=ilist[i]
+ local p=nil
+ if ni=="injections" then
+ p=getprev(n)
+ if p then
+ local id=getid(p)
+ if id==disc_code then
+ dp=getfield(p,"post")
+ dr=getfield(p,"replace")
+ end
+ end
+ end
+ if dp then
+ local i=rawget(pn,"postinjections")
+ if i then
+ local leftkern=i.leftkern
+ if leftkern and leftkern~=0 then
+ local t=find_tail(dp)
+ insert_node_after(dp,t,newkern(leftkern))
+ setfield(p,"post",dp)
+ end
+ end
+ end
+ if dr then
+ local i=rawget(pn,"replaceinjections")
+ if i then
+ local leftkern=i.leftkern
+ if leftkern and leftkern~=0 then
+ local t=find_tail(dr)
+ insert_node_after(dr,t,newkern(leftkern))
+ setfield(p,"replace",dr)
+ end
+ end
+ else
+ local i=rawget(pn,ni)
+ if i then
+ local leftkern=i.leftkern
+ if leftkern and leftkern~=0 then
+ insert_node_before(head,n,newkern(leftkern))
+ end
+ local rightkern=i.rightkern
+ if rightkern and rightkern~=0 then
+ insert_node_after(head,n,newkern(rightkern))
+ end
+ end
+ end
end
end
end
@@ -10595,23 +10784,18 @@ local function inject_everything(head,where)
if trace_injections then
trace(head,"everything")
end
- local glyphs,nofglyphs,marks,nofmarks
- if nofregisteredpairs>0 then
- glyphs,nofglyphs,marks,nofmarks=collect_glyphs_1(head)
- else
- glyphs,nofglyphs,marks,nofmarks=collect_glyphs_2(head)
- end
+ local glyphs,glyphi,nofglyphs,marks,marki,nofmarks=collect_glyphs(head,nofregisteredpairs>0)
if nofglyphs>0 then
if nofregisteredcursives>0 then
- inject_cursives(glyphs,nofglyphs)
+ inject_cursives(glyphs,glyphi,nofglyphs)
end
if nofregisteredmarks>0 then
- inject_marks(marks,nofmarks)
+ inject_marks(marks,marki,nofmarks)
end
- inject_kerns(head,glyphs,nofglyphs)
+ inject_kerns(head,glyphs,glyphi,nofglyphs)
end
if nofmarks>0 then
- inject_kerns(head,marks,nofmarks)
+ inject_kerns(head,marks,marki,nofmarks)
end
if keepregisteredcounts then
keepregisteredcounts=false
@@ -10629,7 +10813,7 @@ local function inject_kerns_only(head,where)
trace(head,"kerns")
end
local n=head
- local p=nil
+ local p=nil
while n do
local id=getid(n)
if id==glyph_code then
@@ -10645,6 +10829,7 @@ local function inject_kerns_only(head,where)
if leftkern and leftkern~=0 then
local t=find_tail(d)
insert_node_after(d,t,newkern(leftkern))
+ setfield(p,"post",d)
end
end
end
@@ -10656,6 +10841,7 @@ local function inject_kerns_only(head,where)
if leftkern and leftkern~=0 then
local t=find_tail(d)
insert_node_after(d,t,newkern(leftkern))
+ setfield(p,"replace",d)
end
end
else
@@ -10677,8 +10863,6 @@ local function inject_kerns_only(head,where)
end
end
end
- else
- break
end
p=nil
elseif id==disc_code then
@@ -10733,7 +10917,7 @@ local function inject_kerns_only(head,where)
local h=d
for n in traverse_id(glyph_code,d) do
if getsubtype(n)<256 then
- local pn=rawget(properties,n)
+ local pn=rawget(properties,n)
if pn then
local i=rawget(pn,"replaceinjections")
if i then
@@ -10770,7 +10954,7 @@ local function inject_pairs_only(head,where)
trace(head,"pairs")
end
local n=head
- local p=nil
+ local p=nil
while n do
local id=getid(n)
if id==glyph_code then
@@ -10786,6 +10970,7 @@ local function inject_pairs_only(head,where)
if leftkern and leftkern~=0 then
local t=find_tail(d)
insert_node_after(d,t,newkern(leftkern))
+ setfield(p,"post",d)
end
end
end
@@ -10797,6 +10982,7 @@ local function inject_pairs_only(head,where)
if leftkern and leftkern~=0 then
local t=find_tail(d)
insert_node_after(d,t,newkern(leftkern))
+ setfield(p,"replace",d)
end
end
else
@@ -10811,24 +10997,22 @@ local function inject_pairs_only(head,where)
else
local i=rawget(pn,"injections")
if i then
- local yoffset=i.yoffset
- if yoffset and yoffset~=0 then
- setfield(n,"yoffset",yoffset)
- end
local leftkern=i.leftkern
if leftkern and leftkern~=0 then
- insert_node_before(head,n,newkern(leftkern))
+ head=insert_node_before(head,n,newkern(leftkern))
end
local rightkern=i.rightkern
if rightkern and rightkern~=0 then
insert_node_after(head,n,newkern(rightkern))
n=getnext(n)
end
+ local yoffset=i.yoffset
+ if yoffset and yoffset~=0 then
+ setfield(n,"yoffset",yoffset)
+ end
end
end
end
- else
- break
end
p=nil
elseif id==disc_code then
@@ -10837,16 +11021,12 @@ local function inject_pairs_only(head,where)
local h=d
for n in traverse_id(glyph_code,d) do
if getsubtype(n)<256 then
- local p=rawget(properties,n)
- if p then
- local i=rawget(p,"preinjections")
+ local pn=rawget(properties,n)
+ if pn then
+ local i=rawget(pn,"preinjections")
if i then
- local yoffset=i.yoffset
- if yoffset and yoffset~=0 then
- setfield(n,"yoffset",yoffset)
- end
local leftkern=i.leftkern
- if leftkern~=0 then
+ if leftkern and leftkern~=0 then
h=insert_node_before(h,n,newkern(leftkern))
end
local rightkern=i.rightkern
@@ -10854,6 +11034,10 @@ local function inject_pairs_only(head,where)
insert_node_after(head,n,newkern(rightkern))
n=getnext(n)
end
+ local yoffset=i.yoffset
+ if yoffset and yoffset~=0 then
+ setfield(n,"yoffset",yoffset)
+ end
end
end
else
@@ -10869,14 +11053,10 @@ local function inject_pairs_only(head,where)
local h=d
for n in traverse_id(glyph_code,d) do
if getsubtype(n)<256 then
- local p=rawget(properties,n)
- if p then
- local i=rawget(p,"postinjections")
+ local pn=rawget(properties,n)
+ if pn then
+ local i=rawget(pn,"postinjections")
if i then
- local yoffset=i.yoffset
- if yoffset and yoffset~=0 then
- setfield(n,"yoffset",yoffset)
- end
local leftkern=i.leftkern
if leftkern and leftkern~=0 then
h=insert_node_before(h,n,newkern(leftkern))
@@ -10886,6 +11066,10 @@ local function inject_pairs_only(head,where)
insert_node_after(head,n,newkern(rightkern))
n=getnext(n)
end
+ local yoffset=i.yoffset
+ if yoffset and yoffset~=0 then
+ setfield(n,"yoffset",yoffset)
+ end
end
end
else
@@ -10901,14 +11085,10 @@ local function inject_pairs_only(head,where)
local h=d
for n in traverse_id(glyph_code,d) do
if getsubtype(n)<256 then
- local p=rawget(properties,n)
- if p then
- local i=rawget(p,"replaceinjections")
+ local pn=rawget(properties,n)
+ if pn then
+ local i=rawget(pn,"replaceinjections")
if i then
- local yoffset=i.yoffset
- if yoffset and yoffset~=0 then
- setfield(n,"yoffset",yoffset)
- end
local leftkern=i.leftkern
if leftkern and leftkern~=0 then
h=insert_node_before(h,n,newkern(leftkern))
@@ -10918,6 +11098,10 @@ local function inject_pairs_only(head,where)
insert_node_after(head,n,newkern(rightkern))
n=getnext(n)
end
+ local yoffset=i.yoffset
+ if yoffset and yoffset~=0 then
+ setfield(n,"yoffset",yoffset)
+ end
end
end
else
@@ -10942,7 +11126,7 @@ local function inject_pairs_only(head,where)
end
return tonode(head),true
end
-function injections.handler(head,where)
+function injections.handler(head,where)
if nofregisteredmarks>0 or nofregisteredcursives>0 then
return inject_everything(head,where)
elseif nofregisteredpairs>0 then
@@ -11342,14 +11526,12 @@ if not modules then modules={} end modules ['font-otn']={
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files",
}
-local concat,insert,remove=table.concat,table.insert,table.remove
-local gmatch,gsub,find,match,lower,strip=string.gmatch,string.gsub,string.find,string.match,string.lower,string.strip
-local type,next,tonumber,tostring=type,next,tonumber,tostring
-local lpegmatch=lpeg.match
+local type,next,tonumber=type,next,tonumber
local random=math.random
local formatters=string.formatters
local logs,trackers,nodes,attributes=logs,trackers,nodes,attributes
local registertracker=trackers.register
+local registerdirective=directives.register
local fonts=fonts
local otf=fonts.handlers.otf
local trace_lookups=false registertracker("otf.lookups",function(v) trace_lookups=v end)
@@ -11368,6 +11550,13 @@ local trace_applied=false registertracker("otf.applied",function(v) trace_applie
local trace_steps=false registertracker("otf.steps",function(v) trace_steps=v end)
local trace_skips=false registertracker("otf.skips",function(v) trace_skips=v end)
local trace_directions=false registertracker("otf.directions",function(v) trace_directions=v end)
+local trace_kernruns=false registertracker("otf.kernruns",function(v) trace_kernruns=v end)
+local trace_discruns=false registertracker("otf.discruns",function(v) trace_discruns=v end)
+local trace_compruns=false registertracker("otf.compruns",function(v) trace_compruns=v end)
+local quit_on_no_replacement=true
+local zwnjruns=true
+registerdirective("otf.zwnjruns",function(v) zwnjruns=v end)
+registerdirective("otf.chain.quitonnoreplacement",function(value) quit_on_no_replacement=value end)
local report_direct=logs.reporter("fonts","otf direct")
local report_subchain=logs.reporter("fonts","otf subchain")
local report_chain=logs.reporter("fonts","otf chain")
@@ -11426,8 +11615,6 @@ 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')
@@ -11461,6 +11648,13 @@ local lookuptags=false
local handlers={}
local rlmode=0
local featurevalue=false
+local sweephead={}
+local sweepnode=nil
+local sweepprev=nil
+local sweepnext=nil
+local notmatchpre={}
+local notmatchpost={}
+local notmatchreplace={}
local checkstep=(nodes and nodes.tracers and nodes.tracers.steppers.check) or function() end
local registerstep=(nodes and nodes.tracers and nodes.tracers.steppers.register) or function() end
local registermessage=(nodes and nodes.tracers and nodes.tracers.steppers.message) or function() end
@@ -11530,6 +11724,65 @@ local function copy_glyph(g)
return n
end
end
+local function flattendisk(head,disc)
+ local replace=getfield(disc,"replace")
+ setfield(disc,"replace",nil)
+ free_node(disc)
+ if head==disc then
+ local next=getnext(disc)
+ if replace then
+ if next then
+ local tail=find_node_tail(replace)
+ setfield(tail,"next",next)
+ setfield(next,"prev",tail)
+ end
+ return replace,replace
+ elseif next then
+ return next,next
+ else
+ return
+ end
+ else
+ local next=getnext(disc)
+ local prev=getprev(disc)
+ if replace then
+ local tail=find_node_tail(replace)
+ if next then
+ setfield(tail,"next",next)
+ setfield(next,"prev",tail)
+ end
+ setfield(prev,"next",replace)
+ setfield(replace,"prev",prev)
+ return head,replace
+ else
+ if next then
+ setfield(next,"prev",prev)
+ end
+ setfield(prev,"next",next)
+ return head,next
+ end
+ end
+end
+local function appenddisc(disc,list)
+ local post=getfield(disc,"post")
+ local replace=getfield(disc,"replace")
+ local phead=list
+ local rhead=copy_node_list(list)
+ local ptail=find_node_tail(post)
+ local rtail=find_node_tail(replace)
+ if post then
+ setfield(ptail,"next",phead)
+ setfield(phead,"prev",ptail)
+ else
+ setfield(disc,"post",phead)
+ end
+ if replace then
+ setfield(rtail,"next",rhead)
+ setfield(rhead,"prev",rtail)
+ else
+ setfield(disc,"replace",rhead)
+ end
+end
local function markstoligature(kind,lookupname,head,start,stop,char)
if start==stop and getchar(start)==char then
return head,start
@@ -11557,8 +11810,8 @@ local function markstoligature(kind,lookupname,head,start,stop,char)
return head,base
end
end
-local function getcomponentindex(start)
- if getid(start)~=glyph_code then
+local function getcomponentindex(start)
+ if getid(start)~=glyph_code then
return 0
elseif getsubtype(start)==ligature_code then
local i=0
@@ -11574,14 +11827,22 @@ local function getcomponentindex(start)
return 0
end
end
+local a_noligature=attributes.private("noligature")
local function toligature(kind,lookupname,head,start,stop,char,markflag,discfound)
+ if getattr(start,a_noligature)==1 then
+ return head,start
+ end
if start==stop and getchar(start)==char then
resetinjection(start)
setfield(start,"char",char)
return head,start
end
+ local components=getfield(start,"components")
+ if components then
+ end
local prev=getprev(start)
local next=getnext(stop)
+ local comp=start
setfield(start,"prev",nil)
setfield(stop,"next",nil)
local base=copy_glyph(start)
@@ -11591,15 +11852,15 @@ local function toligature(kind,lookupname,head,start,stop,char,markflag,discfoun
resetinjection(base)
setfield(base,"char",char)
setfield(base,"subtype",ligature_code)
- setfield(base,"components",start)
+ setfield(base,"components",comp)
if prev then
setfield(prev,"next",base)
end
if next then
setfield(next,"prev",base)
end
- setfield(base,"next",next)
setfield(base,"prev",prev)
+ setfield(base,"next",next)
if not discfound then
local deletemarks=markflag~="mark"
local components=start
@@ -11617,7 +11878,9 @@ local function toligature(kind,lookupname,head,start,stop,char,markflag,discfoun
if trace_marks then
logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),getligaindex(start))
end
- head,current=insert_node_after(head,current,copy_node(start))
+ local n=copy_node(start)
+ copyinjection(n,start)
+ head,current=insert_node_after(head,current,n)
elseif trace_marks then
logwarning("%s: delete mark %s",pref(kind,lookupname),gref(char))
end
@@ -11636,16 +11899,75 @@ local function toligature(kind,lookupname,head,start,stop,char,markflag,discfoun
end
start=getnext(start)
end
+ else
+ local discprev=getfield(discfound,"prev")
+ local discnext=getfield(discfound,"next")
+ if discprev and discnext then
+ local pre=getfield(discfound,"pre")
+ local post=getfield(discfound,"post")
+ local replace=getfield(discfound,"replace")
+ if not replace then
+ local prev=getfield(base,"prev")
+ local copied=copy_node_list(comp)
+ setfield(discnext,"prev",nil)
+ setfield(discprev,"next",nil)
+ if pre then
+ setfield(discprev,"next",pre)
+ setfield(pre,"prev",discprev)
+ end
+ pre=comp
+ if post then
+ local tail=find_node_tail(post)
+ setfield(tail,"next",discnext)
+ setfield(discnext,"prev",tail)
+ setfield(post,"prev",nil)
+ else
+ post=discnext
+ end
+ setfield(prev,"next",discfound)
+ setfield(discfound,"prev",prev)
+ setfield(discfound,"next",next)
+ setfield(next,"prev",discfound)
+ setfield(base,"next",nil)
+ setfield(base,"prev",nil)
+ setfield(base,"components",copied)
+ setfield(discfound,"pre",pre)
+ setfield(discfound,"post",post)
+ setfield(discfound,"replace",base)
+ setfield(discfound,"subtype",discretionary_code)
+ base=prev
+ end
+ end
end
return head,base
end
-function handlers.gsub_single(head,start,kind,lookupname,replacement)
- if trace_singles then
- logprocess("%s: replacing %s by single %s",pref(kind,lookupname),gref(getchar(start)),gref(replacement))
+local function multiple_glyphs(head,start,multiple,ignoremarks)
+ local nofmultiples=#multiple
+ if nofmultiples>0 then
+ resetinjection(start)
+ setfield(start,"char",multiple[1])
+ if nofmultiples>1 then
+ local sn=getnext(start)
+ for k=2,nofmultiples do
+ local n=copy_node(start)
+ resetinjection(n)
+ setfield(n,"char",multiple[k])
+ setfield(n,"prev",start)
+ setfield(n,"next",sn)
+ if sn then
+ setfield(sn,"prev",n)
+ end
+ setfield(start,"next",n)
+ start=n
+ end
+ end
+ return head,start,true
+ else
+ if trace_multiples then
+ logprocess("no multiple for %s",gref(getchar(start)))
+ end
+ return head,start,false
end
- resetinjection(start)
- setfield(start,"char",replacement)
- return head,start,true
end
local function get_alternative_glyph(start,alternatives,value,trace_alternatives)
local n=#alternatives
@@ -11678,33 +12000,13 @@ local function get_alternative_glyph(start,alternatives,value,trace_alternatives
end
end
end
-local function multiple_glyphs(head,start,multiple,ignoremarks)
- local nofmultiples=#multiple
- if nofmultiples>0 then
- resetinjection(start)
- setfield(start,"char",multiple[1])
- if nofmultiples>1 then
- local sn=getnext(start)
- for k=2,nofmultiples do
- local n=copy_node(start)
- resetinjection(n)
- setfield(n,"char",multiple[k])
- setfield(n,"next",sn)
- setfield(n,"prev",start)
- if sn then
- setfield(sn,"prev",n)
- end
- setfield(start,"next",n)
- start=n
- end
- end
- return head,start,true
- else
- if trace_multiples then
- logprocess("no multiple for %s",gref(getchar(start)))
- end
- return head,start,false
+function handlers.gsub_single(head,start,kind,lookupname,replacement)
+ if trace_singles then
+ logprocess("%s: replacing %s by single %s",pref(kind,lookupname),gref(getchar(start)),gref(replacement))
end
+ resetinjection(start)
+ setfield(start,"char",replacement)
+ return head,start,true
end
function handlers.gsub_alternate(head,start,kind,lookupname,alternative,sequence)
local value=featurevalue==true and tfmdata.shared.features[kind] or featurevalue
@@ -11729,7 +12031,7 @@ function handlers.gsub_multiple(head,start,kind,lookupname,multiple,sequence)
return multiple_glyphs(head,start,multiple,sequence.flags[1])
end
function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
- local s,stop,discfound=getnext(start),nil,false
+ local s,stop=getnext(start),nil
local startchar=getchar(start)
if marks[startchar] then
while s do
@@ -11757,23 +12059,29 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
else
head,start=markstoligature(kind,lookupname,head,start,stop,lig)
end
- return head,start,true
+ return head,start,true,false
else
end
end
else
local skipmark=sequence.flags[1]
+ local discfound=false
+ local lastdisc=nil
while s do
local id=getid(s)
- if id==glyph_code and getsubtype(s)<256 then
- if getfont(s)==currentfont then
+ if id==glyph_code and getsubtype(s)<256 then
+ if getfont(s)==currentfont then
local char=getchar(s)
if skipmark and marks[char] then
s=getnext(s)
- else
- local lg=ligature[char]
+ else
+ local lg=ligature[char]
if lg then
- stop=s
+ if not discfound and lastdisc then
+ discfound=lastdisc
+ lastdisc=nil
+ end
+ stop=s
ligature=lg
s=getnext(s)
else
@@ -11784,13 +12092,13 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
break
end
elseif id==disc_code then
- discfound=true
+ lastdisc=s
s=getnext(s)
else
break
end
end
- local lig=ligature.ligature
+ local lig=ligature.ligature
if lig then
if stop then
if trace_ligatures then
@@ -11807,12 +12115,71 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
logprocess("%s: replacing %s by (no real) ligature %s case 3",pref(kind,lookupname),gref(startchar),gref(lig))
end
end
- return head,start,true
+ return head,start,true,discfound
else
end
end
+ return head,start,false,discfound
+end
+function handlers.gpos_single(head,start,kind,lookupname,kerns,sequence,injection)
+ local startchar=getchar(start)
+ local dx,dy,w,h=setpair(start,tfmdata.parameters.factor,rlmode,sequence.flags[4],kerns,injection)
+ if trace_kerns then
+ logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),dx,dy,w,h)
+ end
return head,start,false
end
+function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence,lookuphash,i,injection)
+ local snext=getnext(start)
+ if not snext then
+ return head,start,false
+ else
+ local prev=start
+ local done=false
+ local factor=tfmdata.parameters.factor
+ local lookuptype=lookuptypes[lookupname]
+ while snext and getid(snext)==glyph_code and getfont(snext)==currentfont and getsubtype(snext)<256 do
+ local nextchar=getchar(snext)
+ local krn=kerns[nextchar]
+ if not krn and marks[nextchar] then
+ prev=snext
+ snext=getnext(snext)
+ else
+ if not krn then
+ elseif type(krn)=="table" then
+ if lookuptype=="pair" then
+ local a,b=krn[2],krn[3]
+ if a and #a>0 then
+ local x,y,w,h=setpair(start,factor,rlmode,sequence.flags[4],a,injection)
+ if trace_kerns then
+ local startchar=getchar(start)
+ logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h)
+ end
+ end
+ if b and #b>0 then
+ local x,y,w,h=setpair(snext,factor,rlmode,sequence.flags[4],b,injection)
+ if trace_kerns then
+ local startchar=getchar(start)
+ logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h)
+ end
+ end
+ else
+ report_process("%s: check this out (old kern stuff)",pref(kind,lookupname))
+ end
+ done=true
+ elseif krn~=0 then
+ local k=setkern(snext,factor,rlmode,krn,injection)
+ if trace_kerns then
+ logprocess("%s: inserting kern %s between %s and %s",pref(kind,lookupname),k,gref(getchar(prev)),gref(nextchar))
+ end
+ done=true
+ end
+ break
+ end
+ end
+ return head,start,done
+ end
+end
function handlers.gpos_mark2base(head,start,kind,lookupname,markanchors,sequence)
local markchar=getchar(start)
if marks[markchar] then
@@ -11965,7 +12332,7 @@ function handlers.gpos_mark2mark(head,start,kind,lookupname,markanchors,sequence
if al[anchor] then
local ma=markanchors[anchor]
if ma then
- local dx,dy,bound=setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,characters[basechar])
+ local dx,dy,bound=setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,characters[basechar],true)
if trace_marks then
logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)",
pref(kind,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy)
@@ -12043,65 +12410,6 @@ function handlers.gpos_cursive(head,start,kind,lookupname,exitanchors,sequence)
return head,start,false
end
end
-function handlers.gpos_single(head,start,kind,lookupname,kerns,sequence)
- local startchar=getchar(start)
- local dx,dy,w,h=setpair(start,tfmdata.parameters.factor,rlmode,sequence.flags[4],kerns,characters[startchar])
- if trace_kerns then
- logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),dx,dy,w,h)
- end
- return head,start,false
-end
-function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence)
- local snext=getnext(start)
- if not snext then
- return head,start,false
- else
- local prev,done=start,false
- local factor=tfmdata.parameters.factor
- local lookuptype=lookuptypes[lookupname]
- while snext and getid(snext)==glyph_code and getfont(snext)==currentfont and getsubtype(snext)<256 do
- local nextchar=getchar(snext)
- local krn=kerns[nextchar]
- if not krn and marks[nextchar] then
- prev=snext
- snext=getnext(snext)
- else
- if not krn then
- elseif type(krn)=="table" then
- if lookuptype=="pair" then
- local a,b=krn[2],krn[3]
- if a and #a>0 then
- local startchar=getchar(start)
- local x,y,w,h=setpair(start,factor,rlmode,sequence.flags[4],a,characters[startchar])
- if trace_kerns then
- logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h)
- end
- end
- if b and #b>0 then
- local startchar=getchar(start)
- local x,y,w,h=setpair(snext,factor,rlmode,sequence.flags[4],b,characters[nextchar])
- if trace_kerns then
- logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h)
- end
- end
- else
- report_process("%s: check this out (old kern stuff)",pref(kind,lookupname))
- end
- done=true
- elseif krn~=0 then
- local k=setkern(snext,factor,rlmode,krn)
- if trace_kerns then
- logprocess("%s: inserting kern %s between %s and %s",pref(kind,lookupname),k,gref(getchar(prev)),gref(nextchar))
- end
- done=true
- end
- break
- end
- end
- return head,start,done
- end
-end
-local chainmores={}
local chainprocs={}
local function logprocess(...)
if trace_steps then
@@ -12121,10 +12429,6 @@ function chainprocs.chainsub(head,start,stop,kind,chainname,currentcontext,looku
logwarning("%s: a direct call to chainsub cannot happen",cref(kind,chainname,chainlookupname))
return head,start,false
end
-function chainmores.chainsub(head,start,stop,kind,chainname,currentcontext,lookuphash,lookuplist,chainlookupname,n)
- logprocess("%s: a direct call to chainsub cannot happen",cref(kind,chainname,chainlookupname))
- return head,start,false
-end
function chainprocs.reversesub(head,start,stop,kind,chainname,currentcontext,lookuphash,replacements)
local char=getchar(start)
local replacement=replacements[char]
@@ -12143,7 +12447,7 @@ function chainprocs.gsub_single(head,start,stop,kind,chainname,currentcontext,lo
local current=start
local subtables=currentlookup.subtables
if #subtables>1 then
- logwarning("todo: check if we need to loop over the replacements: %s",concat(subtables," "))
+ logwarning("todo: check if we need to loop over the replacements: % t",subtables)
end
while current do
if getid(current)==glyph_code then
@@ -12177,7 +12481,6 @@ function chainprocs.gsub_single(head,start,stop,kind,chainname,currentcontext,lo
end
return head,start,false
end
-chainmores.gsub_single=chainprocs.gsub_single
function chainprocs.gsub_multiple(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
local startchar=getchar(start)
local subtables=currentlookup.subtables
@@ -12202,7 +12505,6 @@ function chainprocs.gsub_multiple(head,start,stop,kind,chainname,currentcontext,
end
return head,start,false
end
-chainmores.gsub_multiple=chainprocs.gsub_multiple
function chainprocs.gsub_alternate(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
local current=start
local subtables=currentlookup.subtables
@@ -12244,7 +12546,6 @@ function chainprocs.gsub_alternate(head,start,stop,kind,chainname,currentcontext
end
return head,start,false
end
-chainmores.gsub_alternate=chainprocs.gsub_alternate
function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex)
local startchar=getchar(start)
local subtables=currentlookup.subtables
@@ -12264,13 +12565,19 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,
local s=getnext(start)
local discfound=false
local last=stop
- local nofreplacements=0
+ local nofreplacements=1
local skipmark=currentlookup.flags[1]
while s do
local id=getid(s)
if id==disc_code then
- s=getnext(s)
- discfound=true
+ if not discfound then
+ discfound=s
+ end
+ if s==stop then
+ break
+ else
+ s=getnext(s)
+ end
else
local schar=getchar(s)
if skipmark and marks[schar] then
@@ -12303,7 +12610,7 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,
end
end
head,start=toligature(kind,lookupname,head,start,stop,l2,currentlookup.flags[1],discfound)
- return head,start,true,nofreplacements
+ return head,start,true,nofreplacements,discfound
elseif trace_bugs then
if start==stop then
logwarning("%s: replacing character %s by ligature fails",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar))
@@ -12313,10 +12620,83 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,
end
end
end
- return head,start,false,0
+ return head,start,false,0,false
end
-chainmores.gsub_ligature=chainprocs.gsub_ligature
-function chainprocs.gpos_mark2base(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
+function chainprocs.gpos_single(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence)
+ local startchar=getchar(start)
+ local subtables=currentlookup.subtables
+ local lookupname=subtables[1]
+ local kerns=lookuphash[lookupname]
+ if kerns then
+ kerns=kerns[startchar]
+ if kerns then
+ local dx,dy,w,h=setpair(start,tfmdata.parameters.factor,rlmode,sequence.flags[4],kerns)
+ if trace_kerns then
+ logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),dx,dy,w,h)
+ end
+ end
+ end
+ return head,start,false
+end
+function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence)
+ local snext=getnext(start)
+ if snext then
+ local startchar=getchar(start)
+ local subtables=currentlookup.subtables
+ local lookupname=subtables[1]
+ local kerns=lookuphash[lookupname]
+ if kerns then
+ kerns=kerns[startchar]
+ if kerns then
+ local lookuptype=lookuptypes[lookupname]
+ local prev,done=start,false
+ local factor=tfmdata.parameters.factor
+ while snext and getid(snext)==glyph_code and getfont(snext)==currentfont and getsubtype(snext)<256 do
+ local nextchar=getchar(snext)
+ local krn=kerns[nextchar]
+ if not krn and marks[nextchar] then
+ prev=snext
+ snext=getnext(snext)
+ else
+ if not krn then
+ elseif type(krn)=="table" then
+ if lookuptype=="pair" then
+ local a,b=krn[2],krn[3]
+ if a and #a>0 then
+ local startchar=getchar(start)
+ local x,y,w,h=setpair(start,factor,rlmode,sequence.flags[4],a)
+ if trace_kerns then
+ logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h)
+ end
+ end
+ if b and #b>0 then
+ local startchar=getchar(start)
+ local x,y,w,h=setpair(snext,factor,rlmode,sequence.flags[4],b)
+ if trace_kerns then
+ logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h)
+ end
+ end
+ else
+ report_process("%s: check this out (old kern stuff)",cref(kind,chainname,chainlookupname))
+ end
+ done=true
+ elseif krn~=0 then
+ local k=setkern(snext,factor,rlmode,krn)
+ if trace_kerns then
+ logprocess("%s: inserting kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(getchar(prev)),gref(nextchar))
+ end
+ done=true
+ end
+ break
+ end
+ end
+ return head,start,done
+ end
+ end
+ end
+ return head,start,false
+end
+function chainprocs.gpos_mark2base(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
local markchar=getchar(start)
if marks[markchar] then
local subtables=currentlookup.subtables
@@ -12479,7 +12859,7 @@ function chainprocs.gpos_mark2mark(head,start,stop,kind,chainname,currentcontext
if al[anchor] then
local ma=markanchors[anchor]
if ma then
- local dx,dy,bound=setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,characters[basechar])
+ local dx,dy,bound=setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,characters[basechar],true)
if trace_marks then
logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)",
cref(kind,chainname,chainlookupname,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy)
@@ -12566,113 +12946,286 @@ function chainprocs.gpos_cursive(head,start,stop,kind,chainname,currentcontext,l
end
return head,start,false
end
-function chainprocs.gpos_single(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence)
- local startchar=getchar(start)
- local subtables=currentlookup.subtables
- local lookupname=subtables[1]
- local kerns=lookuphash[lookupname]
- if kerns then
- kerns=kerns[startchar]
- if kerns then
- local dx,dy,w,h=setpair(start,tfmdata.parameters.factor,rlmode,sequence.flags[4],kerns,characters[startchar])
- if trace_kerns then
- logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),dx,dy,w,h)
+local function show_skip(kind,chainname,char,ck,class)
+ if ck[9] then
+ logwarning("%s: skipping char %s, class %a, rule %a, lookuptype %a, %a => %a",cref(kind,chainname),gref(char),class,ck[1],ck[2],ck[9],ck[10])
+ else
+ logwarning("%s: skipping char %s, class %a, rule %a, lookuptype %a",cref(kind,chainname),gref(char),class,ck[1],ck[2])
+ end
+end
+local function chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,chainindex,sequence,chainproc)
+ if not start then
+ return head,start,false
+ end
+ local startishead=start==head
+ local seq=ck[3]
+ local f=ck[4]
+ local l=ck[5]
+ local s=#seq
+ local done=false
+ local sweepnode=sweepnode
+ local sweeptype=sweeptype
+ local sweepoverflow=false
+ local checkdisc=getprev(head)
+ local keepdisc=not sweepnode
+ local lookaheaddisc=nil
+ local backtrackdisc=nil
+ local current=start
+ local last=start
+ local prev=getprev(start)
+ local i=f
+ while i<=l do
+ local id=getid(current)
+ if id==glyph_code then
+ i=i+1
+ last=current
+ current=getnext(current)
+ elseif id==disc_code then
+ if keepdisc then
+ keepdisc=false
+ if notmatchpre[current]~=notmatchreplace[current] then
+ lookaheaddisc=current
+ end
+ local replace=getfield(current,"replace")
+ while replace and i<=l do
+ if getid(replace)==glyph_code then
+ i=i+1
+ end
+ replace=getnext(replace)
+ end
+ last=current
+ current=getnext(c)
+ else
+ head,current=flattendisk(head,current)
+ end
+ else
+ last=current
+ current=getnext(current)
+ end
+ if current then
+ elseif sweepoverflow then
+ break
+ elseif sweeptype=="post" or sweeptype=="replace" then
+ current=getnext(sweepnode)
+ if current then
+ sweeptype=nil
+ sweepoverflow=true
+ else
+ break
end
end
end
- return head,start,false
-end
-chainmores.gpos_single=chainprocs.gpos_single
-function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence)
- local snext=getnext(start)
- if snext then
- local startchar=getchar(start)
- local subtables=currentlookup.subtables
- local lookupname=subtables[1]
- local kerns=lookuphash[lookupname]
- if kerns then
- kerns=kerns[startchar]
- if kerns then
- local lookuptype=lookuptypes[lookupname]
- local prev,done=start,false
- local factor=tfmdata.parameters.factor
- while snext and getid(snext)==glyph_code and getfont(snext)==currentfont and getsubtype(snext)<256 do
- local nextchar=getchar(snext)
- local krn=kerns[nextchar]
- if not krn and marks[nextchar] then
- prev=snext
- snext=getnext(snext)
- else
- if not krn then
- elseif type(krn)=="table" then
- if lookuptype=="pair" then
- local a,b=krn[2],krn[3]
- if a and #a>0 then
- local startchar=getchar(start)
- local x,y,w,h=setpair(start,factor,rlmode,sequence.flags[4],a,characters[startchar])
- if trace_kerns then
- logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h)
- end
- end
- if b and #b>0 then
- local startchar=getchar(start)
- local x,y,w,h=setpair(snext,factor,rlmode,sequence.flags[4],b,characters[nextchar])
- if trace_kerns then
- logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h)
- end
- end
- else
- report_process("%s: check this out (old kern stuff)",cref(kind,chainname,chainlookupname))
- local a,b=krn[2],krn[6]
- if a and a~=0 then
- local k=setkern(snext,factor,rlmode,a)
- if trace_kerns then
- logprocess("%s: inserting first kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(getchar(prev)),gref(nextchar))
- end
- end
- if b and b~=0 then
- logwarning("%s: ignoring second kern xoff %s",cref(kind,chainname,chainlookupname),b*factor)
- end
- end
- done=true
- elseif krn~=0 then
- local k=setkern(snext,factor,rlmode,krn)
- if trace_kerns then
- logprocess("%s: inserting kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(getchar(prev)),gref(nextchar))
- end
- done=true
+ if sweepoverflow then
+ local prev=current and getprev(current)
+ if not current or prev~=sweepnode then
+ local head=getnext(sweepnode)
+ local tail=nil
+ if prev then
+ tail=prev
+ setfield(current,"prev",sweepnode)
+ else
+ tail=find_node_tail(head)
+ end
+ setfield(sweepnode,"next",current)
+ setfield(head,"prev",nil)
+ setfield(tail,"next",nil)
+ appenddisc(sweepnode,head)
+ end
+ end
+ if l %a",cref(kind,chainname),gref(char),class,ck[1],ck[2],ck[9],ck[10])
+ if f>1 then
+ local current=prev
+ local i=f
+ local t=sweeptype=="pre" or sweeptype=="replace"
+ if not current and t and current==checkdisk then
+ current=getprev(sweepnode)
+ end
+ while current and i>1 do
+ local id=getid(current)
+ if id==glyph_code then
+ i=i-1
+ elseif id==disc_code then
+ if keepdisc then
+ keepdisc=false
+ if notmatchpost[current]~=notmatchreplace[current] then
+ backtrackdisc=current
+ end
+ local replace=getfield(current,"replace")
+ while replace and i>1 do
+ if getid(replace)==glyph_code then
+ i=i-1
+ end
+ replace=getnext(replace)
+ end
+ elseif notmatchpost[current]~=notmatchreplace[current] then
+ head,current=flattendisk(head,current)
+ end
+ end
+ current=getprev(current)
+ if t and current==checkdisk then
+ current=getprev(sweepnode)
+ end
+ end
+ end
+ local ok=false
+ if lookaheaddisc then
+ local cf=start
+ local cl=getprev(lookaheaddisc)
+ local cprev=getprev(start)
+ local insertedmarks=0
+ while cprev and getid(cf)==glyph_code and getfont(cf)==currentfont and getsubtype(cf)<256 and marks[getchar(cf)] do
+ insertedmarks=insertedmarks+1
+ cf=cprev
+ startishead=cf==head
+ cprev=getprev(cprev)
+ end
+ setfield(lookaheaddisc,"prev",cprev)
+ if cprev then
+ setfield(cprev,"next",lookaheaddisc)
+ end
+ setfield(cf,"prev",nil)
+ setfield(cl,"next",nil)
+ if startishead then
+ head=lookaheaddisc
+ end
+ local replace=getfield(lookaheaddisc,"replace")
+ local pre=getfield(lookaheaddisc,"pre")
+ local new=copy_node_list(cf)
+ local cnew=new
+ for i=1,insertedmarks do
+ cnew=getnext(cnew)
+ end
+ local clast=cnew
+ for i=f,l do
+ clast=getnext(clast)
+ end
+ if not notmatchpre[lookaheaddisc] then
+ cf,start,ok=chainproc(cf,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ end
+ if not notmatchreplace[lookaheaddisc] then
+ new,cnew,ok=chainproc(new,cnew,clast,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ end
+ if pre then
+ setfield(cl,"next",pre)
+ setfield(pre,"prev",cl)
+ end
+ if replace then
+ local tail=find_node_tail(new)
+ setfield(tail,"next",replace)
+ setfield(replace,"prev",tail)
+ end
+ setfield(lookaheaddisc,"pre",cf)
+ setfield(lookaheaddisc,"replace",new)
+ start=getprev(lookaheaddisc)
+ sweephead[cf]=getnext(clast)
+ sweephead[new]=getnext(last)
+ elseif backtrackdisc then
+ local cf=getnext(backtrackdisc)
+ local cl=start
+ local cnext=getnext(start)
+ local insertedmarks=0
+ while cnext and getid(cnext)==glyph_code and getfont(cnext)==currentfont and getsubtype(cnext)<256 and marks[getchar(cnext)] do
+ insertedmarks=insertedmarks+1
+ cl=cnext
+ cnext=getnext(cnext)
+ end
+ if cnext then
+ setfield(cnext,"prev",backtrackdisc)
+ end
+ setfield(backtrackdisc,"next",cnext)
+ setfield(cf,"prev",nil)
+ setfield(cl,"next",nil)
+ local replace=getfield(backtrackdisc,"replace")
+ local post=getfield(backtrackdisc,"post")
+ local new=copy_node_list(cf)
+ local cnew=find_node_tail(new)
+ for i=1,insertedmarks do
+ cnew=getprev(cnew)
+ end
+ local clast=cnew
+ for i=f,l do
+ clast=getnext(clast)
+ end
+ if not notmatchpost[backtrackdisc] then
+ cf,start,ok=chainproc(cf,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ end
+ if not notmatchreplace[backtrackdisc] then
+ new,cnew,ok=chainproc(new,cnew,clast,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ end
+ if post then
+ local tail=find_node_tail(post)
+ setfield(tail,"next",cf)
+ setfield(cf,"prev",tail)
+ else
+ post=cf
+ end
+ if replace then
+ local tail=find_node_tail(replace)
+ setfield(tail,"next",new)
+ setfield(new,"prev",tail)
+ else
+ replace=new
+ end
+ setfield(backtrackdisc,"post",post)
+ setfield(backtrackdisc,"replace",replace)
+ start=getprev(backtrackdisc)
+ sweephead[post]=getnext(clast)
+ sweephead[replace]=getnext(last)
else
- logwarning("%s: skipping char %s, class %a, rule %a, lookuptype %a",cref(kind,chainname),gref(char),class,ck[1],ck[2])
+ head,start,ok=chainproc(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
end
+ return head,start,ok
end
-local quit_on_no_replacement=true
-directives.register("otf.chain.quitonnoreplacement",function(value)
- quit_on_no_replacement=value
-end)
local function normal_handle_contextchain(head,start,kind,chainname,contexts,sequence,lookuphash)
+ local sweepnode=sweepnode
+ local sweeptype=sweeptype
+ local diskseen=false
+ local checkdisc=getprev(head)
local flags=sequence.flags
local done=false
local skipmark=flags[1]
local skipligature=flags[2]
local skipbase=flags[3]
- local someskip=skipmark or skipligature or skipbase
- local markclass=sequence.markclass
+ local markclass=sequence.markclass
local skipped=false
- for k=1,#contexts do
+ for k=1,#contexts do
local match=true
local current=start
local last=start
@@ -12682,14 +13235,20 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
if s==1 then
match=getid(current)==glyph_code and getfont(current)==currentfont and getsubtype(current)<256 and seq[1][getchar(current)]
else
- local f,l=ck[4],ck[5]
+ local f=ck[4]
+ local l=ck[5]
if f==1 and f==l then
else
if f==l then
else
+ local discfound=nil
local n=f+1
last=getnext(last)
while n<=l do
+ if not last and (sweeptype=="post" or sweeptype=="replace") then
+ last=getnext(sweepnode)
+ sweeptype=nil
+ end
if last then
local id=getid(last)
if id==glyph_code then
@@ -12697,7 +13256,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
local char=getchar(last)
local ccd=descriptions[char]
if ccd then
- local class=ccd.class
+ local class=ccd.class or "base"
if class==skipmark or class==skipligature or class==skipbase or (markclass and class=="mark" and not markclass[char]) then
skipped=true
if trace_skips then
@@ -12710,18 +13269,76 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
end
n=n+1
else
- match=false
+ if discfound then
+ notmatchreplace[discfound]=true
+ match=not notmatchpre[discfound]
+ else
+ match=false
+ end
break
end
else
- match=false
+ if discfound then
+ notmatchreplace[discfound]=true
+ match=not notmatchpre[discfound]
+ else
+ match=false
+ end
break
end
else
- match=false
+ if discfound then
+ notmatchreplace[discfound]=true
+ match=not notmatchpre[discfound]
+ else
+ match=false
+ end
break
end
elseif id==disc_code then
+ diskseen=true
+ discfound=last
+ notmatchpre[last]=nil
+ notmatchpost[last]=true
+ notmatchreplace[last]=nil
+ local pre=getfield(last,"pre")
+ local replace=getfield(last,"replace")
+ if pre then
+ local n=n
+ while pre do
+ if seq[n][getchar(pre)] then
+ n=n+1
+ pre=getnext(pre)
+ if n>l then
+ break
+ end
+ else
+ notmatchpre[last]=true
+ break
+ end
+ end
+ if n<=l then
+ notmatchpre[last]=true
+ end
+ else
+ notmatchpre[last]=true
+ end
+ if replace then
+ while replace do
+ if seq[n][getchar(replace)] then
+ n=n+1
+ replace=getnext(replace)
+ if n>l then
+ break
+ end
+ else
+ notmatchreplace[last]=true
+ match=not notmatchpre[last]
+ break
+ end
+ end
+ match=not notmatchpre[last]
+ end
last=getnext(last)
else
match=false
@@ -12737,49 +13354,132 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
if match and f>1 then
local prev=getprev(start)
if prev then
- local n=f-1
- while n>=1 do
- if prev then
- local id=getid(prev)
- if id==glyph_code then
- if getfont(prev)==currentfont and getsubtype(prev)<256 then
- local char=getchar(prev)
- local ccd=descriptions[char]
- if ccd then
- local class=ccd.class
- if class==skipmark or class==skipligature or class==skipbase or (markclass and class=="mark" and not markclass[char]) then
- skipped=true
- if trace_skips then
- show_skip(kind,chainname,char,ck,class)
+ if prev==checkdisc and (sweeptype=="pre" or sweeptype=="replace") then
+ prev=getprev(sweepnode)
+ end
+ if prev then
+ local discfound=nil
+ local n=f-1
+ while n>=1 do
+ if prev then
+ local id=getid(prev)
+ if id==glyph_code then
+ if getfont(prev)==currentfont and getsubtype(prev)<256 then
+ local char=getchar(prev)
+ local ccd=descriptions[char]
+ if ccd then
+ local class=ccd.class
+ if class==skipmark or class==skipligature or class==skipbase or (markclass and class=="mark" and not markclass[char]) then
+ skipped=true
+ if trace_skips then
+ show_skip(kind,chainname,char,ck,class)
+ end
+ elseif seq[n][char] then
+ n=n -1
+ else
+ if discfound then
+ notmatchreplace[discfound]=true
+ match=not notmatchpost[discfound]
+ else
+ match=false
+ end
+ break
end
- elseif seq[n][char] then
- n=n -1
else
- match=false
+ if discfound then
+ notmatchreplace[discfound]=true
+ match=not notmatchpost[discfound]
+ else
+ match=false
+ end
break
end
else
- match=false
+ if discfound then
+ notmatchreplace[discfound]=true
+ match=not notmatchpost[discfound]
+ else
+ match=false
+ end
break
end
+ elseif id==disc_code then
+ diskseen=true
+ discfound=prev
+ notmatchpre[prev]=true
+ notmatchpost[prev]=nil
+ notmatchreplace[prev]=nil
+ local pre=getfield(prev,"pre")
+ local post=getfield(prev,"post")
+ local replace=getfield(prev,"replace")
+ if pre~=start and post~=start and replace~=start then
+ if post then
+ local n=n
+ local posttail=find_node_tail(post)
+ while posttail do
+ if seq[n][getchar(posttail)] then
+ n=n-1
+ if posttail==post then
+ break
+ else
+ posttail=getprev(posttail)
+ if n<1 then
+ break
+ end
+ end
+ else
+ notmatchpost[prev]=true
+ break
+ end
+ end
+ if n>=1 then
+ notmatchpost[prev]=true
+ end
+ else
+ notmatchpost[prev]=true
+ end
+ if replace then
+ local replacetail=find_node_tail(replace)
+ while replacetail do
+ if seq[n][getchar(replacetail)] then
+ n=n-1
+ if replacetail==replace then
+ break
+ else
+ replacetail=getprev(replacetail)
+ if n<1 then
+ break
+ end
+ end
+ else
+ notmatchreplace[prev]=true
+ match=not notmatchpost[prev]
+ break
+ end
+ end
+ if not match then
+ break
+ end
+ else
+ end
+ else
+ end
+ elseif seq[n][32] then
+ n=n -1
else
match=false
break
end
- elseif id==disc_code then
- elseif seq[n][32] then
- n=n -1
+ prev=getprev(prev)
+ elseif seq[n][32] then
+ n=n-1
else
match=false
break
end
- prev=getprev(prev)
- elseif seq[n][32] then
- n=n -1
- else
- match=false
- break
end
+ else
+ match=false
end
else
match=false
@@ -12787,7 +13487,13 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
end
if match and s>l then
local current=last and getnext(last)
+ if not current then
+ if sweeptype=="post" or sweeptype=="replace" then
+ current=getnext(sweepnode)
+ end
+ end
if current then
+ local discfound=nil
local n=l+1
while n<=s do
if current then
@@ -12803,21 +13509,82 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
if trace_skips then
show_skip(kind,chainname,char,ck,class)
end
- elseif seq[n][char] then
+ elseif seq[n][char] then
+ n=n+1
+ else
+ if discfound then
+ notmatchreplace[discfound]=true
+ match=not notmatchpre[discfound]
+ else
+ match=false
+ end
+ break
+ end
+ else
+ if discfound then
+ notmatchreplace[discfound]=true
+ match=not notmatchpre[discfound]
+ else
+ match=false
+ end
+ break
+ end
+ else
+ if discfound then
+ notmatchreplace[discfound]=true
+ match=not notmatchpre[discfound]
+ else
+ match=false
+ end
+ break
+ end
+ elseif id==disc_code then
+ diskseen=true
+ discfound=current
+ notmatchpre[current]=nil
+ notmatchpost[current]=true
+ notmatchreplace[current]=nil
+ local pre=getfield(current,"pre")
+ local replace=getfield(current,"replace")
+ if pre then
+ local n=n
+ while pre do
+ if seq[n][getchar(pre)] then
+ n=n+1
+ pre=getnext(pre)
+ if n>s then
+ break
+ end
+ else
+ notmatchpre[current]=true
+ break
+ end
+ end
+ if n<=s then
+ notmatchpre[current]=true
+ end
+ else
+ notmatchpre[current]=true
+ end
+ if replace then
+ while replace do
+ if seq[n][getchar(replace)] then
n=n+1
+ replace=getnext(replace)
+ if n>s then
+ break
+ end
else
- match=false
+ notmatchreplace[current]=true
+ match=notmatchpre[current]
break
end
- else
- match=false
+ end
+ if not match then
break
end
else
- match=false
- break
end
- elseif id==disc_code then
elseif seq[n][32] then
n=n+1
else
@@ -12838,6 +13605,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
end
end
if match then
+ local diskchain=diskseen or sweepnode
if trace_contexts then
local rule,lookuptype,f,l=ck[1],ck[2],ck[4],ck[5]
local char=getchar(start)
@@ -12856,10 +13624,14 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
local chainlookupname=chainlookups[1]
local chainlookup=lookuptable[chainlookupname]
if chainlookup then
- local cp=chainprocs[chainlookup.type]
- if cp then
+ local chainproc=chainprocs[chainlookup.type]
+ if chainproc then
local ok
- head,start,ok=cp(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ if diskchain then
+ head,start,ok=chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence,chainproc)
+ else
+ head,start,ok=chainproc(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ end
if ok then
done=true
end
@@ -12871,13 +13643,13 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
end
else
local i=1
- while true do
+ while start and true do
if skipped then
- while true do
+ while true do
local char=getchar(start)
local ccd=descriptions[char]
if ccd then
- local class=ccd.class
+ local class=ccd.class or "base"
if class==skipmark or class==skipligature or class==skipbase or (markclass and class=="mark" and not markclass[char]) then
start=getnext(start)
else
@@ -12893,26 +13665,33 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
if not chainlookup then
i=i+1
else
- local cp=chainmores[chainlookup.type]
- if not cp then
+ local chainproc=chainprocs[chainlookup.type]
+ if not chainproc then
logprocess("%s: %s is not yet supported",cref(kind,chainname,chainlookupname),chainlookup.type)
i=i+1
else
local ok,n
- head,start,ok,n=cp(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,i,sequence)
+ if diskchain then
+ head,start,ok=chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence,chainproc)
+ else
+ head,start,ok,n=chainproc(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,i,sequence)
+ end
if ok then
done=true
- i=i+(n or 1)
- else
- i=i+1
+ if n and n>1 then
+ if i+n>nofchainlookups then
+ break
+ else
+ end
+ end
end
+ i=i+1
end
end
- if i>nofchainlookups then
+ if i>nofchainlookups or not start then
break
elseif start then
start=getnext(start)
- else
end
end
end
@@ -12927,8 +13706,16 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
end
end
end
+ if done then
+ break
+ end
end
end
+ if diskseen then
+ notmatchpre={}
+ notmatchpost={}
+ notmatchreplace={}
+ end
return head,start,done
end
local verbose_handle_contextchain=function(font,...)
@@ -12999,7 +13786,7 @@ local function initialize(sequence,script,language,enabled)
local scripts=features[kind]
local languages=scripts[script] or scripts[wildcard]
if languages and (languages[language] or languages[wildcard]) then
- return { valid,autofeatures[kind] or false,sequence.chain or 0,kind,sequence }
+ return { valid,autofeatures[kind] or false,sequence,kind }
end
end
end
@@ -13039,6 +13826,175 @@ function otf.dataset(tfmdata,font)
end
return rl
end
+local function kernrun(disc,run)
+ if trace_kernruns then
+ report_run("kern")
+ end
+ local prev=getprev(disc)
+ local next=getnext(disc)
+ local pre=getfield(disc,"pre")
+ local post=getfield(disc,"post")
+ local replace=getfield(disc,"replace")
+ local prevmarks=prev
+ while prevmarks and getid(prevmarks)==glyph_code and marks[getchar(prevmarks)] and getfont(prevmarks)==currentfont and getsubtype(prevmarks)<256 do
+ prevmarks=getprev(prevmarks)
+ end
+ if prev and (pre or replace) and not (getid(prev)==glyph_code and getfont(prev)==currentfont and getsubtype(prev)<256) then
+ prev=false
+ end
+ if next and (post or replace) and not (getid(next)==glyph_code and getfont(next)==currentfont and getsubtype(next)<256) then
+ next=false
+ end
+ if not pre then
+ elseif prev then
+ local nest=getprev(pre)
+ setfield(pre,"prev",prev)
+ setfield(prev,"next",pre)
+ run(prevmarks,"preinjections")
+ setfield(pre,"prev",nest)
+ setfield(prev,"next",disc)
+ else
+ run(pre,"preinjections")
+ end
+ if not post then
+ elseif next then
+ local tail=find_node_tail(post)
+ setfield(tail,"next",next)
+ setfield(next,"prev",tail)
+ run(post,"postinjections",next)
+ setfield(tail,"next",nil)
+ setfield(next,"prev",disc)
+ else
+ run(post,"postinjections")
+ end
+ if not replace and prev and next then
+ setfield(prev,"next",next)
+ setfield(next,"prev",prev)
+ run(prevmarks,"injections",next)
+ setfield(prev,"next",disc)
+ setfield(next,"prev",disc)
+ elseif prev and next then
+ local tail=find_node_tail(replace)
+ local nest=getprev(replace)
+ setfield(replace,"prev",prev)
+ setfield(prev,"next",replace)
+ setfield(tail,"next",next)
+ setfield(next,"prev",tail)
+ run(prevmarks,"replaceinjections",next)
+ setfield(replace,"prev",nest)
+ setfield(prev,"next",disc)
+ setfield(tail,"next",nil)
+ setfield(next,"prev",disc)
+ elseif prev then
+ local nest=getprev(replace)
+ setfield(replace,"prev",prev)
+ setfield(prev,"next",replace)
+ run(prevmarks,"replaceinjections")
+ setfield(replace,"prev",nest)
+ setfield(prev,"next",disc)
+ elseif next then
+ local tail=find_node_tail(replace)
+ setfield(tail,"next",next)
+ setfield(next,"prev",tail)
+ run(replace,"replaceinjections",next)
+ setfield(tail,"next",nil)
+ setfield(next,"prev",disc)
+ else
+ run(replace,"replaceinjections")
+ end
+end
+local function comprun(disc,run)
+ if trace_compruns then
+ report_run("comp: %s",languages.serializediscretionary(disc))
+ end
+ local pre=getfield(disc,"pre")
+ if pre then
+ sweepnode=disc
+ sweeptype="pre"
+ local new,done=run(pre)
+ if done then
+ setfield(disc,"pre",new)
+ end
+ end
+ local post=getfield(disc,"post")
+ if post then
+ sweepnode=disc
+ sweeptype="post"
+ local new,done=run(post)
+ if done then
+ setfield(disc,"post",new)
+ end
+ end
+ local replace=getfield(disc,"replace")
+ if replace then
+ sweepnode=disc
+ sweeptype="replace"
+ local new,done=run(replace)
+ if done then
+ setfield(disc,"replace",new)
+ end
+ end
+ sweepnode=nil
+ sweeptype=nil
+end
+local function testrun(disc,trun,crun)
+ local next=getnext(disc)
+ if next then
+ local replace=getfield(disc,"replace")
+ if replace then
+ local prev=getprev(disc)
+ if prev then
+ local tail=find_node_tail(replace)
+ setfield(tail,"next",next)
+ setfield(next,"prev",tail)
+ if trun(replace,next) then
+ setfield(disc,"replace",nil)
+ setfield(prev,"next",replace)
+ setfield(replace,"prev",prev)
+ setfield(next,"prev",tail)
+ setfield(tail,"next",next)
+ setfield(disc,"prev",nil)
+ setfield(disc,"next",nil)
+ flush_node_list(disc)
+ return replace
+ else
+ setfield(tail,"next",nil)
+ setfield(next,"prev",disc)
+ end
+ else
+ end
+ else
+ end
+ else
+ end
+ comprun(disc,crun)
+ return next
+end
+local function discrun(disc,drun,krun)
+ local next=getnext(disc)
+ local prev=getprev(disc)
+ if trace_discruns then
+ report_run("disc")
+ end
+ if next and prev then
+ setfield(prev,"next",next)
+ drun(prev)
+ setfield(prev,"next",disc)
+ end
+ local pre=getfield(disc,"pre")
+ if not pre then
+ elseif prev then
+ local nest=getprev(pre)
+ setfield(pre,"prev",prev)
+ setfield(prev,"next",pre)
+ krun(prev,"preinjections")
+ setfield(pre,"prev",nest)
+ setfield(prev,"next",disc)
+ else
+ krun(pre,"preinjections")
+ end
+ return next
+end
local function featuresprocessor(head,font,attr)
local lookuphash=lookuphashes[font]
if not lookuphash then
@@ -13059,23 +14015,25 @@ local function featuresprocessor(head,font,attr)
lookuptags=resources.lookuptags
currentfont=font
rlmode=0
+ sweephead={}
local sequences=resources.sequences
local done=false
local datasets=otf.dataset(tfmdata,font,attr)
local dirstack={}
for s=1,#datasets do
local dataset=datasets[s]
- featurevalue=dataset[1]
- local sequence=dataset[5]
+ featurevalue=dataset[1]
+ local attribute=dataset[2]
+ local sequence=dataset[3]
+ local kind=dataset[4]
local rlparmode=0
local topstack=0
local success=false
- local attribute=dataset[2]
- local chain=dataset[3]
local typ=sequence.type
+ local gpossing=typ=="gpos_single" or typ=="gpos_pair"
local subtables=sequence.subtables
- if chain<0 then
- local handler=handlers[typ]
+ local handler=handlers[typ]
+ if typ=="gsub_reversecontextchain" then
local start=find_node_tail(head)
while start do
local id=getid(start)
@@ -13088,13 +14046,14 @@ local function featuresprocessor(head,font,attr)
a=true
end
if a then
+ local char=getchar(start)
for i=1,#subtables do
local lookupname=subtables[i]
local lookupcache=lookuphash[lookupname]
if lookupcache then
- local lookupmatch=lookupcache[getchar(start)]
+ local lookupmatch=lookupcache[char]
if lookupmatch then
- head,start,success=handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
+ head,start,success=handler(head,start,kind,lookupname,lookupmatch,sequence,lookuphash,i)
if success then
break
end
@@ -13115,7 +14074,6 @@ local function featuresprocessor(head,font,attr)
end
end
else
- local handler=handlers[typ]
local ns=#subtables
local start=head
rlmode=0
@@ -13125,12 +14083,19 @@ local function featuresprocessor(head,font,attr)
if not lookupcache then
report_missing_cache(typ,lookupname)
else
- local function subrun(start)
- local head=start
+ local function c_run(head)
local done=false
+ local start=sweephead[head]
+ if start then
+ sweephead[head]=nil
+ else
+ start=head
+ end
while start do
local id=getid(start)
- if id==glyph_code and getfont(start)==font and getsubtype(start)<256 then
+ if id~=glyph_code then
+ start=getnext(start)
+ elseif getfont(start)==font and getsubtype(start)<256 then
local a=getattr(start,0)
if a then
a=(a==attr) and (not attribute or getprop(start,a_state)==attribute)
@@ -13141,7 +14106,7 @@ local function featuresprocessor(head,font,attr)
local lookupmatch=lookupcache[getchar(start)]
if lookupmatch then
local ok
- head,start,ok=handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1)
+ head,start,ok=handler(head,start,kind,lookupname,lookupmatch,sequence,lookuphash,1)
if ok then
done=true
end
@@ -13151,43 +14116,98 @@ local function featuresprocessor(head,font,attr)
start=getnext(start)
end
else
- start=getnext(start)
+ return head,false
end
end
if done then
- success=true
- return head
+ success=true
end
+ return head,done
end
- local function kerndisc(disc)
- local prev=getprev(disc)
- local next=getnext(disc)
- if prev and next then
- setfield(prev,"next",next)
- local a=getattr(prev,0)
- if a then
- a=(a==attr) and (not attribute or getprop(prev,a_state)==attribute)
+ local function t_run(start,stop)
+ while start~=stop do
+ local id=getid(start)
+ if id==glyph_code and getfont(start)==font and getsubtype(start)<256 then
+ local a=getattr(start,0)
+ if a then
+ a=(a==attr) and (not attribute or getprop(start,a_state)==attribute)
+ else
+ a=not attribute or getprop(start,a_state)==attribute
+ end
+ if a then
+ local lookupmatch=lookupcache[getchar(start)]
+ if lookupmatch then
+ local s=getnext(start)
+ local l=nil
+ while s do
+ local lg=lookupmatch[getchar(s)]
+ if lg then
+ l=lg
+ s=getnext(s)
+ else
+ break
+ end
+ end
+ if l and l.ligature then
+ return true
+ end
+ end
+ end
+ start=getnext(start)
else
- a=not attribute or getprop(prev,a_state)==attribute
+ break
end
- if a then
- local lookupmatch=lookupcache[getchar(prev)]
- if lookupmatch then
- local h,d,ok=handler(head,prev,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1)
- if ok then
- done=true
- success=true
+ end
+ end
+ local function d_run(prev)
+ local a=getattr(prev,0)
+ if a then
+ a=(a==attr) and (not attribute or getprop(prev,a_state)==attribute)
+ else
+ a=not attribute or getprop(prev,a_state)==attribute
+ end
+ if a then
+ local lookupmatch=lookupcache[getchar(prev)]
+ if lookupmatch then
+ local h,d,ok=handler(head,prev,kind,lookupname,lookupmatch,sequence,lookuphash,1)
+ if ok then
+ done=true
+ success=true
+ end
+ end
+ end
+ end
+ local function k_run(sub,injection,last)
+ local a=getattr(sub,0)
+ if a then
+ a=(a==attr) and (not attribute or getprop(sub,a_state)==attribute)
+ else
+ a=not attribute or getprop(sub,a_state)==attribute
+ end
+ if a then
+ for n in traverse_nodes(sub) do
+ if n==last then
+ break
+ end
+ local id=getid(n)
+ if id==glyph_code then
+ local lookupmatch=lookupcache[getchar(n)]
+ if lookupmatch then
+ local h,d,ok=handler(sub,n,kind,lookupname,lookupmatch,sequence,lookuphash,1,injection)
+ if ok then
+ done=true
+ success=true
+ end
end
+ else
end
end
- setfield(prev,"next",disc)
end
- return next
end
while start do
local id=getid(start)
if id==glyph_code then
- if getfont(start)==font and getsubtype(start)<256 then
+ if getfont(start)==font and getsubtype(start)<256 then
local a=getattr(start,0)
if a then
a=(a==attr) and (not attribute or getprop(start,a_state)==attribute)
@@ -13195,13 +14215,18 @@ local function featuresprocessor(head,font,attr)
a=not attribute or getprop(start,a_state)==attribute
end
if a then
- local lookupmatch=lookupcache[getchar(start)]
+ local char=getchar(start)
+ local lookupmatch=lookupcache[char]
if lookupmatch then
local ok
- head,start,ok=handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1)
+ head,start,ok=handler(head,start,kind,lookupname,lookupmatch,sequence,lookuphash,1)
if ok then
success=true
+ elseif gpossing and zwnjruns and char==zwnj then
+ discrun(start,d_run)
end
+ elseif gpossing and zwnjruns and char==zwnj then
+ discrun(start,d_run)
end
if start then start=getnext(start) end
else
@@ -13211,41 +14236,30 @@ local function featuresprocessor(head,font,attr)
start=getnext(start)
end
elseif id==disc_code then
- if getsubtype(start)==discretionary_code then
- local pre=getfield(start,"pre")
- if pre then
- local new=subrun(pre)
- if new then setfield(start,"pre",new) end
- end
- local post=getfield(start,"post")
- if post then
- local new=subrun(post)
- if new then setfield(start,"post",new) end
- end
- local replace=getfield(start,"replace")
- if replace then
- local new=subrun(replace)
- if new then setfield(start,"replace",new) end
- end
-elseif typ=="gpos_single" or typ=="gpos_pair" then
- kerndisc(start)
+ if gpossing then
+ kernrun(start,k_run)
+ start=getnext(start)
+ elseif typ=="gsub_ligature" then
+ start=testrun(start,t_run,c_run)
+ else
+ comprun(start,c_run)
+ start=getnext(start)
end
- start=getnext(start)
elseif id==whatsit_code then
local subtype=getsubtype(start)
if subtype==dir_code then
local dir=getfield(start,"dir")
- if dir=="+TRT" or dir=="+TLT" then
+ if dir=="+TLT" then
topstack=topstack+1
dirstack[topstack]=dir
- elseif dir=="-TRT" or dir=="-TLT" then
- topstack=topstack-1
- end
- local newdir=dirstack[topstack]
- if newdir=="+TRT" then
- rlmode=-1
- elseif newdir=="+TLT" then
rlmode=1
+ elseif dir=="+TRT" then
+ topstack=topstack+1
+ dirstack[topstack]=dir
+ rlmode=-1
+ elseif dir=="-TLT" or dir=="-TRT" then
+ topstack=topstack-1
+ rlmode=dirstack[topstack]=="+TRT" and -1 or 1
else
rlmode=rlparmode
end
@@ -13275,12 +14289,19 @@ elseif typ=="gpos_single" or typ=="gpos_pair" then
end
end
else
- local function subrun(start)
- local head=start
+ local function c_run(head)
local done=false
+ local start=sweephead[head]
+ if start then
+ sweephead[head]=nil
+ else
+ start=head
+ end
while start do
local id=getid(start)
- if id==glyph_code and getfont(start)==font and getsubtype(start)<256 then
+ if id~=glyph_code then
+ start=getnext(start)
+ elseif getfont(start)==font and getsubtype(start)<256 then
local a=getattr(start,0)
if a then
a=(a==attr) and (not attribute or getprop(start,a_state)==attribute)
@@ -13288,14 +14309,15 @@ elseif typ=="gpos_single" or typ=="gpos_pair" then
a=not attribute or getprop(start,a_state)==attribute
end
if a then
+ local char=getchar(start)
for i=1,ns do
local lookupname=subtables[i]
local lookupcache=lookuphash[lookupname]
if lookupcache then
- local lookupmatch=lookupcache[getchar(start)]
+ local lookupmatch=lookupcache[char]
if lookupmatch then
local ok
- head,start,ok=handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
+ head,start,ok=handler(head,start,kind,lookupname,lookupmatch,sequence,lookuphash,i)
if ok then
done=true
break
@@ -13312,46 +14334,120 @@ elseif typ=="gpos_single" or typ=="gpos_pair" then
start=getnext(start)
end
else
- start=getnext(start)
+ return head,false
end
end
if done then
success=true
- return head
end
+ return head,done
end
- local function kerndisc(disc)
- local prev=getprev(disc)
- local next=getnext(disc)
- if prev and next then
- setfield(prev,"next",next)
- local a=getattr(prev,0)
- if a then
- a=(a==attr) and (not attribute or getprop(prev,a_state)==attribute)
- else
- a=not attribute or getprop(prev,a_state)==attribute
+ local function d_run(prev)
+ local a=getattr(prev,0)
+ if a then
+ a=(a==attr) and (not attribute or getprop(prev,a_state)==attribute)
+ else
+ a=not attribute or getprop(prev,a_state)==attribute
+ end
+ if a then
+ local char=getchar(prev)
+ for i=1,ns do
+ local lookupname=subtables[i]
+ local lookupcache=lookuphash[lookupname]
+ if lookupcache then
+ local lookupmatch=lookupcache[char]
+ if lookupmatch then
+ local h,d,ok=handler(head,prev,kind,lookupname,lookupmatch,sequence,lookuphash,i)
+ if ok then
+ done=true
+ break
+ end
+ end
+ else
+ report_missing_cache(typ,lookupname)
+ end
end
- if a then
- for i=1,ns do
- local lookupname=subtables[i]
- local lookupcache=lookuphash[lookupname]
- if lookupcache then
- local lookupmatch=lookupcache[getchar(prev)]
- if lookupmatch then
- local h,d,ok=handler(head,prev,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
- if ok then
- done=true
- break
+ end
+ end
+ local function k_run(sub,injection,last)
+ local a=getattr(sub,0)
+ if a then
+ a=(a==attr) and (not attribute or getprop(sub,a_state)==attribute)
+ else
+ a=not attribute or getprop(sub,a_state)==attribute
+ end
+ if a then
+ for n in traverse_nodes(sub) do
+ if n==last then
+ break
+ end
+ local id=getid(n)
+ if id==glyph_code then
+ local char=getchar(n)
+ for i=1,ns do
+ local lookupname=subtables[i]
+ local lookupcache=lookuphash[lookupname]
+ if lookupcache then
+ local lookupmatch=lookupcache[char]
+ if lookupmatch then
+ local h,d,ok=handler(head,n,kind,lookupname,lookupmatch,sequence,lookuphash,i,injection)
+ if ok then
+ done=true
+ break
+ end
end
+ else
+ report_missing_cache(typ,lookupname)
+ end
+ end
+ else
+ end
+ end
+ end
+ end
+ local function t_run(start,stop)
+ while start~=stop do
+ local id=getid(start)
+ if id==glyph_code and getfont(start)==font and getsubtype(start)<256 then
+ local a=getattr(start,0)
+ if a then
+ a=(a==attr) and (not attribute or getprop(start,a_state)==attribute)
+ else
+ a=not attribute or getprop(start,a_state)==attribute
+ end
+ if a then
+ local char=getchar(start)
+ for i=1,ns do
+ local lookupname=subtables[i]
+ local lookupcache=lookuphash[lookupname]
+ if lookupcache then
+ local lookupmatch=lookupcache[char]
+ if lookupmatch then
+ local s=getnext(start)
+ local l=nil
+ while s do
+ local lg=lookupmatch[getchar(s)]
+ if lg then
+ l=lg
+ s=getnext(s)
+ else
+ break
+ end
+ end
+ if l and l.ligature then
+ return true
+ end
+ end
+ else
+ report_missing_cache(typ,lookupname)
end
- else
- report_missing_cache(typ,lookupname)
end
end
+ start=getnext(start)
+ else
+ break
end
- setfield(prev,"next",disc)
end
- return next
end
while start do
local id=getid(start)
@@ -13368,16 +14464,21 @@ elseif typ=="gpos_single" or typ=="gpos_pair" then
local lookupname=subtables[i]
local lookupcache=lookuphash[lookupname]
if lookupcache then
- local lookupmatch=lookupcache[getchar(start)]
+ local char=getchar(start)
+ local lookupmatch=lookupcache[char]
if lookupmatch then
local ok
- head,start,ok=handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
+ head,start,ok=handler(head,start,kind,lookupname,lookupmatch,sequence,lookuphash,i)
if ok then
success=true
break
elseif not start then
break
+ elseif gpossing and zwnjruns and char==zwnj then
+ discrun(start,d_run)
end
+ elseif gpossing and zwnjruns and char==zwnj then
+ discrun(start,d_run)
end
else
report_missing_cache(typ,lookupname)
@@ -13391,41 +14492,30 @@ elseif typ=="gpos_single" or typ=="gpos_pair" then
start=getnext(start)
end
elseif id==disc_code then
- if getsubtype(start)==discretionary_code then
- local pre=getfield(start,"pre")
- if pre then
- local new=subrun(pre)
- if new then setfield(start,"pre",new) end
- end
- local post=getfield(start,"post")
- if post then
- local new=subrun(post)
- if new then setfield(start,"post",new) end
- end
- local replace=getfield(start,"replace")
- if replace then
- local new=subrun(replace)
- if new then setfield(start,"replace",new) end
- end
-elseif typ=="gpos_single" or typ=="gpos_pair" then
- kerndisc(start)
+ if gpossing then
+ kernrun(start,k_run)
+ start=getnext(start)
+ elseif typ=="gsub_ligature" then
+ start=testrun(start,t_run,c_run)
+ else
+ comprun(start,c_run)
+ start=getnext(start)
end
- start=getnext(start)
elseif id==whatsit_code then
local subtype=getsubtype(start)
if subtype==dir_code then
local dir=getfield(start,"dir")
- if dir=="+TRT" or dir=="+TLT" then
+ if dir=="+TLT" then
topstack=topstack+1
dirstack[topstack]=dir
- elseif dir=="-TRT" or dir=="-TLT" then
- topstack=topstack-1
- end
- local newdir=dirstack[topstack]
- if newdir=="+TRT" then
- rlmode=-1
- elseif newdir=="+TLT" then
rlmode=1
+ elseif dir=="+TRT" then
+ topstack=topstack+1
+ dirstack[topstack]=dir
+ rlmode=-1
+ elseif dir=="-TLT" or dir=="-TRT" then
+ topstack=topstack-1
+ rlmode=dirstack[topstack]=="+TRT" and -1 or 1
else
rlmode=rlparmode
end
@@ -13473,43 +14563,46 @@ local function generic(lookupdata,lookupname,unicode,lookuphash)
lookuphash[lookupname]={ [unicode]=lookupdata }
end
end
+local function ligature(lookupdata,lookupname,unicode,lookuphash)
+ local target=lookuphash[lookupname]
+ if not target then
+ target={}
+ lookuphash[lookupname]=target
+ end
+ for i=1,#lookupdata do
+ local li=lookupdata[i]
+ local tu=target[li]
+ if not tu then
+ tu={}
+ target[li]=tu
+ end
+ target=tu
+ end
+ target.ligature=unicode
+end
+local function pair(lookupdata,lookupname,unicode,lookuphash)
+ local target=lookuphash[lookupname]
+ if not target then
+ target={}
+ lookuphash[lookupname]=target
+ end
+ local others=target[unicode]
+ local paired=lookupdata[1]
+ if others then
+ others[paired]=lookupdata
+ else
+ others={ [paired]=lookupdata }
+ target[unicode]=others
+ end
+end
local action={
substitution=generic,
multiple=generic,
alternate=generic,
position=generic,
- ligature=function(lookupdata,lookupname,unicode,lookuphash)
- local target=lookuphash[lookupname]
- if not target then
- target={}
- lookuphash[lookupname]=target
- end
- for i=1,#lookupdata do
- local li=lookupdata[i]
- local tu=target[li]
- if not tu then
- tu={}
- target[li]=tu
- end
- target=tu
- end
- target.ligature=unicode
- end,
- pair=function(lookupdata,lookupname,unicode,lookuphash)
- local target=lookuphash[lookupname]
- if not target then
- target={}
- lookuphash[lookupname]=target
- end
- local others=target[unicode]
- local paired=lookupdata[1]
- if others then
- others[paired]=lookupdata
- else
- others={ [paired]=lookupdata }
- target[unicode]=others
- end
- end,
+ ligature=ligature,
+ pair=pair,
+ kern=pair,
}
local function prepare_lookups(tfmdata)
local rawdata=tfmdata.shared.rawdata
@@ -13520,13 +14613,14 @@ local function prepare_lookups(tfmdata)
local lookuptypes=resources.lookuptypes
local characters=tfmdata.characters
local descriptions=tfmdata.descriptions
+ local duplicates=resources.duplicates
for unicode,character in next,characters do
local description=descriptions[unicode]
if description then
local lookups=description.slookups
if lookups then
for lookupname,lookupdata in next,lookups do
- action[lookuptypes[lookupname]](lookupdata,lookupname,unicode,lookuphash)
+ action[lookuptypes[lookupname]](lookupdata,lookupname,unicode,lookuphash,duplicates)
end
end
local lookups=description.mlookups
@@ -13535,7 +14629,7 @@ local function prepare_lookups(tfmdata)
local lookuptype=lookuptypes[lookupname]
for l=1,#lookuplist do
local lookupdata=lookuplist[l]
- action[lookuptype](lookupdata,lookupname,unicode,lookuphash)
+ action[lookuptype](lookupdata,lookupname,unicode,lookuphash,duplicates)
end
end
end
@@ -13557,7 +14651,7 @@ local function prepare_lookups(tfmdata)
for name,anchor in next,anchors do
local lookups=anchor_to_lookup[name]
if lookups then
- for lookup,_ in next,lookups do
+ for lookup in next,lookups do
local target=lookuphash[lookup]
if target then
target[unicode]=anchors
@@ -13639,7 +14733,7 @@ local function prepare_contextchains(tfmdata)
if sequence[1] then
nt=nt+1
t[nt]={ nofrules,lookuptype,sequence,start,stop,rule.lookups,replacements }
- for unic,_ in next,sequence[start] do
+ for unic in next,sequence[start] do
local cu=contexts[unic]
if not cu then
contexts[unic]=t
@@ -13698,9 +14792,8 @@ if not modules then modules={} end modules ['font-otp']={
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files"
}
-local next,type=next,type
+local next,type,tostring=next,type,tostring
local sort,concat=table.sort,table.concat
-local sortedhash=table.sortedhash
local trace_packing=false trackers.register("otf.packing",function(v) trace_packing=v end)
local trace_loading=false trackers.register("otf.loading",function(v) trace_loading=v end)
local report_otf=logs.reporter("fonts","otf loading")
@@ -14676,10 +15769,11 @@ end
function resolvers.name(specification)
local resolve=fonts.names.resolve
if resolve then
- local resolved,sub=resolve(specification.name,specification.sub,specification)
+ local resolved,sub,subindex=resolve(specification.name,specification.sub,specification)
if resolved then
specification.resolved=resolved
specification.sub=sub
+ specification.subindex=subindex
local suffix=lower(suffixonly(resolved))
if fonts.formats[suffix] then
specification.forced=suffix
@@ -14696,10 +15790,11 @@ end
function resolvers.spec(specification)
local resolvespec=fonts.names.resolvespec
if resolvespec then
- local resolved,sub=resolvespec(specification.name,specification.sub,specification)
+ local resolved,sub,subindex=resolvespec(specification.name,specification.sub,specification)
if resolved then
specification.resolved=resolved
specification.sub=sub
+ specification.subindex=subindex
specification.forced=lower(suffixonly(resolved))
specification.forcedname=resolved
specification.name=removesuffix(resolved)
@@ -15341,12 +16436,30 @@ function nodes.handlers.nodepass(head)
local range=basefonts[i]
local start=range[1]
local stop=range[2]
- if stop then
- start,stop=ligaturing(start,stop)
- start,stop=kerning(start,stop)
- elseif start then
- start=ligaturing(start)
- start=kerning(start)
+ if start or stop then
+ local prev=nil
+ local next=nil
+ local front=start==head
+ if stop then
+ next=stop.next
+ start,stop=ligaturing(start,stop)
+ start,stop=kerning(start,stop)
+ elseif start then
+ prev=start.prev
+ start=ligaturing(start)
+ start=kerning(start)
+ end
+ if prev then
+ start.prev=prev
+ prev.next=start
+ end
+ if next then
+ stop.next=next
+ next.prev=stop
+ end
+ if front then
+ head=start
+ end
end
end
end
@@ -15356,7 +16469,7 @@ function nodes.handlers.nodepass(head)
end
end
function nodes.handlers.basepass(head)
- if not basepass then
+ if basepass then
head=ligaturing(head)
head=kerning(head)
end
--
cgit v1.2.3
From 7fd7d54817edbf75ff4e0a574769a27a851a5240 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Thu, 29 Oct 2015 07:21:18 +0100
Subject: [tool] adapt outdated usage info
---
src/luaotfload-tool.lua | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/luaotfload-tool.lua b/src/luaotfload-tool.lua
index 181bd5c..8b7bc33 100755
--- a/src/luaotfload-tool.lua
+++ b/src/luaotfload-tool.lua
@@ -109,6 +109,7 @@ config.lualibs.prefer_merged = true
config.lualibs.load_extended = true
require "lualibs"
+
local iosavedata = io.savedata
local lfsisdir = lfs.isdir
local lfsisfile = lfs.isfile
@@ -138,7 +139,7 @@ local backup = {
}
texio.write, texio.write_nl = dummy_function, dummy_function
-require"luaotfload-basics-gen.lua"
+require "luaotfload-basics-gen.lua"
texio.write, texio.write_nl = backup.write, backup.write_nl
utilities = backup.utilities
@@ -216,8 +217,7 @@ Usage: %s [OPTIONS...]
-q --quiet don't output anything
-v --verbose=LEVEL be more verbose (print the searched directories)
- -vv print the loaded fonts
- -vvv print all steps of directory searching
+ -v, -vv .. -vvvvvvvvv set loglevel in unary
--log=stdout redirect log output to stdout
-V --version print version and exit
--
cgit v1.2.3
From 1bffc1c923412efa9b45f370d771d1ebacbcbaef Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Thu, 29 Oct 2015 07:26:34 +0100
Subject: [log] fix format strings passed to os.date()
In the name of MS compiler compatibility
bow before the Middle Ages.
---
src/luaotfload-log.lua | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/luaotfload-log.lua b/src/luaotfload-log.lua
index 7c012f4..e5db310 100644
--- a/src/luaotfload-log.lua
+++ b/src/luaotfload-log.lua
@@ -91,7 +91,7 @@ local set_logout = function (s, finalizers)
logout = "redirect"
local chan = choose_logfile ()
chan:write (stringformat ("logging initiated at %s",
- osdate ("%Y-%m-%d %h:%m:%s", --- i. e. osdate "%F %T"
+ osdate ("%Y-%m-%d %H:%M:%S", --- i. e. osdate "%F %T"
ostime ())))
local writefile = function (...)
if select ("#", ...) == 2 then
@@ -118,7 +118,7 @@ local set_logout = function (s, finalizers)
finalizers[#finalizers+1] = function ()
chan:write (stringformat ("\nlogging finished at %s\n",
- osdate ("%Y-%m-%d %h:%m:%s", --- i. e. osdate "%F %T"
+ osdate ("%Y-%m-%d %H:%M:%S", --- i. e. osdate "%F %T"
ostime ())))
chan:close ()
texiowrite = texio.write
--
cgit v1.2.3
From e52df63570da80bf121fd9b9294de5a2d037f1b6 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Thu, 29 Oct 2015 07:37:39 +0100
Subject: [main] dejumble module loader message
---
src/luaotfload-main.lua | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/luaotfload-main.lua b/src/luaotfload-main.lua
index 3d68a17..ff2b48d 100644
--- a/src/luaotfload-main.lua
+++ b/src/luaotfload-main.lua
@@ -109,15 +109,15 @@ end
local make_loader_name = function (prefix, name)
local msg = luaotfload.log and luaotfload.log.report or print
- if prefix then
+ if prefix and name then
msg ("log", 7, "load",
- "Composing fontloader name from constitutents %s, %s",
+ "Composing module name from constituents %s, %s",
prefix, name)
return prefix .. "-" .. name .. ".lua"
end
msg ("log", 7, "load",
- "Loading fontloader file %s literally.",
- name)
+ "Loading module %s literally.",
+ tostring (name))
return name
end
--
cgit v1.2.3
From 4ab63d7a670d90f9ffcbd2c35b363c432c043d5d Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Thu, 29 Oct 2015 07:39:59 +0100
Subject: [diagnose] fix indentation of status message
---
src/luaotfload-diagnostics.lua | 30 +++++++++++++++---------------
1 file changed, 15 insertions(+), 15 deletions(-)
diff --git a/src/luaotfload-diagnostics.lua b/src/luaotfload-diagnostics.lua
index 80e461c..255b5a5 100644
--- a/src/luaotfload-diagnostics.lua
+++ b/src/luaotfload-diagnostics.lua
@@ -655,27 +655,27 @@ local diagnose = function (job)
you may sleep well.")
return true, false
end
- out ( [[===============================================
- WARNING
- ===============================================
+ out ( [[===============================================
+ WARNING
+ ===============================================
- The diagnostic detected %d errors.
+ The diagnostic detected %d errors.
- This version of luaotfload may have been
- tampered with. Modified versions of the
- luaotfload source are unsupported. Read the log
- carefully and get a clean version from CTAN or
- github:
+ This version of luaotfload may have been
+ tampered with. Modified versions of the
+ luaotfload source are unsupported. Read the log
+ carefully and get a clean version from CTAN or
+ github:
- × http://www.ctan.org/pkg/luaotfload
- × https://github.com/lualatex/luaotfload/releases
+ × http://www.ctan.org/pkg/luaotfload
+ × https://github.com/lualatex/luaotfload/releases
- If you are uncertain as to how to proceed, then
- ask on the lualatex mailing list:
+ If you are uncertain as to how to proceed, then
+ ask on the lualatex mailing list:
- http://www.tug.org/mailman/listinfo/lualatex-dev
+ http://www.tug.org/mailman/listinfo/lualatex-dev
- ===============================================
+ ===============================================
]], errcnt)
return true, false
end
--
cgit v1.2.3
From dfdee4a9f3e968c5493f9e4166503624edfe5eb0 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Thu, 29 Oct 2015 08:03:33 +0100
Subject: [db] fix passing inverse format list
---
src/luaotfload-database.lua | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/luaotfload-database.lua b/src/luaotfload-database.lua
index b871954..086f46f 100644
--- a/src/luaotfload-database.lua
+++ b/src/luaotfload-database.lua
@@ -1921,9 +1921,8 @@ end
local p_font_filter
do
- local current_formats = { }
-
local extension_pattern = function (list)
+ if type (list) ~= "table" or #list == 0 then return P(-1) end
local pat
for i=#list, 1, -1 do
local e = list[i]
@@ -1940,6 +1939,8 @@ do
--- small helper to adjust the font filter pattern (--formats
--- option)
+ local current_formats = { }
+
set_font_filter = function (formats)
if not formats or type (formats) ~= "string" then
--
cgit v1.2.3
From 6c0c403a3b6fa01604935960a46eb1e10a4586af Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Thu, 29 Oct 2015 08:22:36 +0100
Subject: [tool,resolvers,db] fix references to the fonts table
This makes the ``--find`` option to luaotfload-too work again.
---
src/luaotfload-database.lua | 3 ++-
src/luaotfload-main.lua | 2 +-
src/luaotfload-resolvers.lua | 32 ++++++++++++++++----------------
src/luaotfload-tool.lua | 7 +++----
4 files changed, 22 insertions(+), 22 deletions(-)
diff --git a/src/luaotfload-database.lua b/src/luaotfload-database.lua
index 086f46f..b84b48d 100644
--- a/src/luaotfload-database.lua
+++ b/src/luaotfload-database.lua
@@ -3501,7 +3501,8 @@ return {
logreport = luaotfload.log.report
local fonts = fonts
fonts.names = fonts.names or names
- fonts.definers = fonts.definers or { }
+ fonts.formats = fonts.formats or { }
+ fonts.definers = fonts.definers or { resolvers = { } }
names.blacklist = blacklist
names.version = 2.51
diff --git a/src/luaotfload-main.lua b/src/luaotfload-main.lua
index ff2b48d..98afee0 100644
--- a/src/luaotfload-main.lua
+++ b/src/luaotfload-main.lua
@@ -194,7 +194,7 @@ luaotfload.main = function ()
initialize "colors" --- Per-font colors.
luaotfload.resolvers = loadmodule "resolvers" --- Font lookup
- luaotfload.resolvers.install ()
+ luaotfload.resolvers.init ()
if not config.actions.reconfigure () then
logreport ("log", 0, "load", "Post-configuration hooks failed.")
diff --git a/src/luaotfload-resolvers.lua b/src/luaotfload-resolvers.lua
index 42ea2fd..2e34a4e 100644
--- a/src/luaotfload-resolvers.lua
+++ b/src/luaotfload-resolvers.lua
@@ -37,15 +37,9 @@ local stringlower = string.lower
local stringformat = string.format
local filesuffix = file.suffix
local fileremovesuffix = file.removesuffix
-local formats = fonts.formats
-local names = fonts.names
-local encodings = fonts.encodings
local luatexbase = luatexbase
local logreport = luaotfload.log.report
-formats.ofm = "type1"
-encodings.known = encodings.known or { }
-
--[[doc--
\identifier{luaotfload} promises easy access to system fonts.
@@ -70,9 +64,9 @@ encodings.known = encodings.known or { }
local resolve_file
resolve_file = function (specification)
- local name = names.lookup_font_file (specification.name)
+ local name = fonts.names.lookup_font_file (specification.name)
local suffix = filesuffix (name)
- if formats[suffix] then
+ if fonts.formats[suffix] then
specification.forced = stringlower (suffix)
specification.forcedname = fileremovesuffix(name)
else
@@ -101,7 +95,7 @@ resolve_path = function (specification)
resolve_file (specification)
else
local suffix = filesuffix (name)
- if formats[suffix] then
+ if fonts.formats[suffix] then
specification.forced = stringlower (suffix)
specification.name = fileremovesuffix(name)
specification.forcedname = name
@@ -122,9 +116,9 @@ end
local resolve_name
resolve_name = function (specification)
- local resolver = names.lookup_font_name_cached
+ local resolver = fonts.names.lookup_font_name_cached
if config.luaotfload.run.resolver == "normal" then
- resolver = names.lookup_font_name
+ resolver = fonts.names.lookup_font_name
end
local resolved, subfont = resolver (specification)
if resolved then
@@ -210,7 +204,7 @@ local resolve_kpse
resolve_kpse = function (specification)
local name = specification.name
local suffix = filesuffix (name)
- if suffix and formats[suffix] then
+ if suffix and fonts.formats[suffix] then
name = fileremovesuffix (name)
if resolvers.findfile (name, suffix) then
specification.forced = stringlower (suffix)
@@ -218,7 +212,7 @@ resolve_kpse = function (specification)
return
end
end
- for t, format in next, formats do --- brute force
+ for t, format in next, fonts.formats do --- brute force
if kpsefind_file (name, format) then
specification.forced = t
specification.name = name
@@ -238,8 +232,11 @@ local resolve_my = function (specification)
end
return {
- install = function ( )
- luatexbase.create_callback ("luaotfload.resolve_font", "simple", function () end)
+ init = function ( )
+ if luatexbase and luatexbase.create_callback then
+ luatexbase.create_callback ("luaotfload.resolve_font",
+ "simple", function () end)
+ end
logreport ("log", 5, "resolvers", "installing font resolvers", name)
local request_resolvers = fonts.definers.resolvers
request_resolvers.file = resolve_file
@@ -248,8 +245,11 @@ return {
request_resolvers.path = resolve_path
request_resolvers.kpse = resolve_kpse
request_resolvers.my = resolve_my
+ fonts.formats.ofm = "type1"
+ fonts.encodings = fonts.encodings or { }
+ fonts.encodings.known = fonts.encodings.known or { }
return true
- end, --- [.install]
+ end, --- [.init]
}
--- vim:ft=lua:ts=8:sw=4:et
diff --git a/src/luaotfload-tool.lua b/src/luaotfload-tool.lua
index 8b7bc33..e92f5fb 100755
--- a/src/luaotfload-tool.lua
+++ b/src/luaotfload-tool.lua
@@ -76,7 +76,6 @@ else -- 5.2
runtime = { "stock", _VERSION }
end
-
local C, Ct, P, S = lpeg.C, lpeg.Ct, lpeg.P, lpeg.S
local lpegmatch = lpeg.match
@@ -84,7 +83,6 @@ local loader_file = "luatexbase.loader.lua"
local loader_path = assert(kpsefind_file(loader_file, "lua"),
"File '"..loader_file.."' not found")
-
string.quoted = string.quoted or function (str)
return string.format("%q",str)
end
@@ -171,6 +169,7 @@ loadmodule "log.lua" --- this populates the luaotfload.log.* namespace
loadmodule "parsers" --- fonts.conf, configuration, and request syntax
loadmodule "configuration" --- configuration file handling
loadmodule "database"
+loadmodule "resolvers" --- Font lookup
local logreport
@@ -237,7 +236,7 @@ Usage: %s [OPTIONS...]
-c --no-compress do not gzip index file (text version only)
-l --flush-lookups empty lookup cache of font requests
-D --dry-run skip loading of fonts, just scan
- --formats=[+|-]EXTENSIONS set, add, or subtract formats to index
+ --formats=[+|-]EXTENSIONS set, add, or subtract file formats
-p --prefer-texmf prefer fonts in the TEXMF over system fonts
--max-fonts=N process at most N font files
@@ -1227,7 +1226,7 @@ actions.query = function (job)
if tmpspec.lookup == "name"
or tmpspec.lookup == "anon" --- not *exactly* as resolvers.anon
then
- foundname, subfont = fonts.names.resolve_name (tmpspec)
+ foundname, subfont = fonts.definers.resolvers.name (tmpspec)
if foundname then
foundname, _, success = fonts.names.font_file_lookup (foundname)
end
--
cgit v1.2.3
From 72a9a971cb229656e021ab56894ac73baa62c0c0 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Fri, 30 Oct 2015 00:15:55 +0100
Subject: [tool] fix --file lookup
---
src/luaotfload-tool.lua | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/src/luaotfload-tool.lua b/src/luaotfload-tool.lua
index e92f5fb..5508ffc 100755
--- a/src/luaotfload-tool.lua
+++ b/src/luaotfload-tool.lua
@@ -1226,13 +1226,12 @@ actions.query = function (job)
if tmpspec.lookup == "name"
or tmpspec.lookup == "anon" --- not *exactly* as resolvers.anon
then
- foundname, subfont = fonts.definers.resolvers.name (tmpspec)
+ foundname, _, success = fonts.names.lookup_font_name (tmpspec)
if foundname then
- foundname, _, success = fonts.names.font_file_lookup (foundname)
+ foundname, _, success = fonts.names.lookup_font_file (foundname)
end
elseif tmpspec.lookup == "file" then
- foundname, _, success =
- fonts.names.font_file_lookup (tmpspec.name)
+ foundname, _, success = fonts.names.lookup_font_file (tmpspec.name)
end
if success then
--
cgit v1.2.3
From 32d25b33ee109f1979db85d7ddf563246d6bcb7f Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Fri, 30 Oct 2015 07:42:58 +0100
Subject: [tool] display fuzzy hint only when not fuzzing
---
src/luaotfload-tool.lua | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/src/luaotfload-tool.lua b/src/luaotfload-tool.lua
index 5508ffc..022b659 100755
--- a/src/luaotfload-tool.lua
+++ b/src/luaotfload-tool.lua
@@ -1250,13 +1250,14 @@ actions.query = function (job)
end
else
logreport (false, 0, "resolve", "Cannot find %q in index.", query)
- logreport (false, 0, "resolve",
- "Hint: use the --fuzzy option to display suggestions.",
- query)
if job.fuzzy == true then
logreport (false, 0, "resolve",
"Looking for close matches, this may take a while ...")
local _success = fonts.names.find_closest(query, job.fuzzy_limit)
+ else
+ logreport (false, 0, "resolve",
+ "Hint: use the --fuzzy option to display suggestions.",
+ query)
end
end
return true, true
--
cgit v1.2.3
From e1a19fbda5bb54a1378620c8df9c2d42ed087fee Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Fri, 30 Oct 2015 07:53:08 +0100
Subject: [db] omit duplicate entries from fuzzed lookup results
---
src/luaotfload-database.lua | 24 ++++++++++++++++++++++--
1 file changed, 22 insertions(+), 2 deletions(-)
diff --git a/src/luaotfload-database.lua b/src/luaotfload-database.lua
index b84b48d..1bc2768 100644
--- a/src/luaotfload-database.lua
+++ b/src/luaotfload-database.lua
@@ -1171,6 +1171,25 @@ local iterative_levenshtein = function (s1, s2)
return costs[len2]--- lower right has the distance
end
+--- string list -> string list
+local delete_dupes = function (lst)
+ local n0 = #lst
+ if n0 == 0 then return lst end
+ tablesort (lst)
+ local ret = { }
+ local last
+ for i = 1, n0 do
+ local cur = lst[i]
+ if cur ~= last then
+ last = cur
+ ret[#ret + 1] = cur
+ end
+ end
+ logreport (false, 8, "query",
+ "Removed %d duplicate names.", n0 - #ret)
+ return ret
+end
+
--- string -> int -> bool
find_closest = function (name, limit)
local name = sanitize_fontname (name)
@@ -1216,6 +1235,7 @@ find_closest = function (name, limit)
else --- append
namelst[#namelst+1] = fullname
end
+
by_distance[dist] = namelst
end
@@ -1229,11 +1249,11 @@ find_closest = function (name, limit)
for i = 1, limit do
local dist = distances[i]
- local namelst = by_distance[dist]
+ local namelst = delete_dupes (by_distance[dist])
logreport (false, 0, "query",
"Distance from \"%s\": %s\n "
.. tableconcat (namelst, "\n "),
- name, dist)
+ name, dist)
end
return true
--
cgit v1.2.3
From 330440f784cb12b0902fd80271e568c59da64771 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Thu, 5 Nov 2015 22:05:00 +0100
Subject: [main] clean up unused and irrelevant pieces
---
src/luaotfload-main.lua | 14 +++-----------
1 file changed, 3 insertions(+), 11 deletions(-)
diff --git a/src/luaotfload-main.lua b/src/luaotfload-main.lua
index 98afee0..5fa316d 100644
--- a/src/luaotfload-main.lua
+++ b/src/luaotfload-main.lua
@@ -7,23 +7,15 @@
-- MODIFIED: 2015-06-09 23:08:18+0200
-----------------------------------------------------------------------
--
---- Note:
---- This file was part of the original luaotfload.dtx and has been
---- converted to a pure Lua file during the transition from Luaotfload
---- version 2.4 to 2.5. Thus, the comments are still in TeX (Latex)
---- markup.
-local os = os
local osgettimeofday = os.gettimeofday
-
-local initial_log_level = 0
-luaotfload = luaotfload or { }
config = config or { }
+luaotfload = luaotfload or { }
local luaotfload = luaotfload
luaotfload.log = luaotfload.log or { }
luaotfload.version = "2.6"
luaotfload.loaders = { }
-luaotfload.min_luatex_version = 79 --- i. e. 0.79
+luaotfload.min_luatex_version = 80 --- i. e. 0.79
luaotfload.fontloader_package = "reference" --- default: from current Context
local authors = "\z
@@ -40,7 +32,7 @@ local authors = "\z
luaotfload.module = {
name = "luaotfload-main",
version = 2.60001,
- date = "2015/05/26",
+ date = "2015/11/05",
description = "OpenType layout system.",
author = authors,
copyright = authors,
--
cgit v1.2.3
From 8395eb8efec1ac9e311541d9834f1a939b91e710 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Thu, 5 Nov 2015 22:08:47 +0100
Subject: [*] kill off file headers
We have the VCS info in the status file; these things are just silly.
---
src/luaotfload-auxiliary.lua | 2 --
src/luaotfload-configuration.lua | 1 -
src/luaotfload-diagnostics.lua | 2 --
src/luaotfload-init.lua | 2 --
src/luaotfload-loaders.lua | 1 -
src/luaotfload-main.lua | 2 --
src/luaotfload-parsers.lua | 4 +---
src/luaotfload-resolvers.lua | 2 --
src/luaotfload-tool.lua | 2 --
9 files changed, 1 insertion(+), 17 deletions(-)
diff --git a/src/luaotfload-auxiliary.lua b/src/luaotfload-auxiliary.lua
index dce0d60..15541af 100644
--- a/src/luaotfload-auxiliary.lua
+++ b/src/luaotfload-auxiliary.lua
@@ -4,8 +4,6 @@
-- DESCRIPTION: part of luaotfload
-- REQUIREMENTS: luaotfload 2.6
-- AUTHOR: Khaled Hosny, Élie Roux, Philipp Gesang
--- VERSION: 2.6
--- MODIFIED: 2015-03-29 12:43:26+0200
-----------------------------------------------------------------------
--
diff --git a/src/luaotfload-configuration.lua b/src/luaotfload-configuration.lua
index 86a302e..6f94195 100644
--- a/src/luaotfload-configuration.lua
+++ b/src/luaotfload-configuration.lua
@@ -5,7 +5,6 @@
-- REQUIREMENTS: Luaotfload 2.6 or above
-- AUTHOR: Philipp Gesang (Phg),
-- AUTHOR: Dohyun Kim
--- VERSION: same as Luaotfload
-------------------------------------------------------------------------------
--
diff --git a/src/luaotfload-diagnostics.lua b/src/luaotfload-diagnostics.lua
index 255b5a5..582105a 100644
--- a/src/luaotfload-diagnostics.lua
+++ b/src/luaotfload-diagnostics.lua
@@ -4,8 +4,6 @@
-- DESCRIPTION: functionality accessible by the --diagnose option
-- REQUIREMENTS: luaotfload-tool.lua
-- AUTHOR: Philipp Gesang (Phg),
--- VERSION: 2.5
--- MODIFIED: 2014-01-02 21:23:06+0100
-----------------------------------------------------------------------
--
local names = fonts.names
diff --git a/src/luaotfload-init.lua b/src/luaotfload-init.lua
index af71cb2..1c2046d 100644
--- a/src/luaotfload-init.lua
+++ b/src/luaotfload-init.lua
@@ -4,8 +4,6 @@
-- DESCRIPTION: Luaotfload font loader initialization
-- REQUIREMENTS: luatex v.0.80 or later; packages lualibs, luatexbase
-- AUTHOR: Philipp Gesang (Phg),
--- VERSION: 1.0
--- CREATED: 2015-05-26 07:50:54+0200
-----------------------------------------------------------------------
--
diff --git a/src/luaotfload-loaders.lua b/src/luaotfload-loaders.lua
index b644266..38062f6 100644
--- a/src/luaotfload-loaders.lua
+++ b/src/luaotfload-loaders.lua
@@ -4,7 +4,6 @@
-- DESCRIPTION: Luaotfload callback handling
-- REQUIREMENTS: luatex v.0.80 or later; packages lualibs, luatexbase
-- AUTHOR: Philipp Gesang (Phg), , Hans Hagen, Khaled Hosny, Elie Roux
--- VERSION: just consult Git, okay?
-----------------------------------------------------------------------
--
--- Contains parts of the earlier main script.
diff --git a/src/luaotfload-main.lua b/src/luaotfload-main.lua
index 5fa316d..85c9cee 100644
--- a/src/luaotfload-main.lua
+++ b/src/luaotfload-main.lua
@@ -3,8 +3,6 @@
-- DESCRIPTION: Luaotfload entry point
-- REQUIREMENTS: luatex v.0.80 or later; packages lualibs, luatexbase
-- AUTHOR: Élie Roux, Khaled Hosny, Philipp Gesang
--- VERSION: same as Luaotfload
--- MODIFIED: 2015-06-09 23:08:18+0200
-----------------------------------------------------------------------
--
diff --git a/src/luaotfload-parsers.lua b/src/luaotfload-parsers.lua
index 151cb9e..0349cdc 100644
--- a/src/luaotfload-parsers.lua
+++ b/src/luaotfload-parsers.lua
@@ -2,10 +2,8 @@
-------------------------------------------------------------------------------
-- FILE: luaotfload-parsers.lua
-- DESCRIPTION: various lpeg-based parsers used in Luaotfload
--- REQUIREMENTS: Luaotfload > 2.6
+-- REQUIREMENTS: Luaotfload >= 2.6
-- AUTHOR: Philipp Gesang (Phg),
--- VERSION: same as Luaotfload
--- CREATED: 2014-01-14 10:15:20+0100
-------------------------------------------------------------------------------
--
diff --git a/src/luaotfload-resolvers.lua b/src/luaotfload-resolvers.lua
index 2e34a4e..3d7f6b0 100644
--- a/src/luaotfload-resolvers.lua
+++ b/src/luaotfload-resolvers.lua
@@ -5,8 +5,6 @@
-- DESCRIPTION: Resolvers for hooking into the fontloader
-- REQUIREMENTS: Luaotfload and a decent bit of courage
-- AUTHOR: Philipp Gesang (Phg),
--- VERSION: 1.0
--- CREATED: 2015-07-23 07:31:50+0200
-----------------------------------------------------------------------
--
--- The bare fontloader uses a set of simplistic file name resolvers
diff --git a/src/luaotfload-tool.lua b/src/luaotfload-tool.lua
index 6c54f29..e9a434a 100755
--- a/src/luaotfload-tool.lua
+++ b/src/luaotfload-tool.lua
@@ -4,9 +4,7 @@
-- DESCRIPTION: database functionality
-- REQUIREMENTS: luaotfload 2.6
-- AUTHOR: Khaled Hosny, Élie Roux, Philipp Gesang
--- VERSION: 2.6
-- LICENSE: GPL v2.0
--- MODIFIED: 2015-03-29 12:43:00+0200
-----------------------------------------------------------------------
luaotfload = luaotfload or { }
--
cgit v1.2.3
From 0a1d8feda744a647f56d97805e6e5d07d107cd71 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Thu, 5 Nov 2015 22:16:05 +0100
Subject: [mk*] kill version and modification headers from scripts too
---
scripts/mkcharacters | 2 --
scripts/mkglyphlist | 2 --
scripts/mkimport | 2 --
scripts/mktests | 2 --
4 files changed, 8 deletions(-)
diff --git a/scripts/mkcharacters b/scripts/mkcharacters
index abed2c9..9e9fd1a 100755
--- a/scripts/mkcharacters
+++ b/scripts/mkcharacters
@@ -5,8 +5,6 @@
-- DESCRIPTION: import parts of char-def.lua
-- REQUIREMENTS: lua, ConTeXt, the lualibs package
-- AUTHOR: Philipp Gesang (Phg),
--- VERSION: 2.5
--- MODIFIED: 2014-02-11 07:24:25+0100
-----------------------------------------------------------------------
-- we create a stripped-down version of char-def.lua
-----------------------------------------------------------------------
diff --git a/scripts/mkglyphlist b/scripts/mkglyphlist
index 8fde098..f66a686 100755
--- a/scripts/mkglyphlist
+++ b/scripts/mkglyphlist
@@ -5,8 +5,6 @@
-- DESCRIPTION: part of the luaotfload package
-- REQUIREMENTS: lua, lpeg, luasocket, the lualibs package
-- AUTHOR: Philipp Gesang (Phg),
--- VERSION: 2.5
--- MODIFIED: 2014-02-11 06:44:50+0100
-----------------------------------------------------------------------
-- interesting thread on the Context list:
-- http://www.ntg.nl/pipermail/ntg-context/2008/029057.html
diff --git a/scripts/mkimport b/scripts/mkimport
index 0833ccb..e8b83c0 100755
--- a/scripts/mkimport
+++ b/scripts/mkimport
@@ -5,8 +5,6 @@
-- DESCRIPTION: check luaotfload imports against Context
-- REQUIREMENTS: luatex, the lualibs package, Context MkIV
-- AUTHOR: Philipp Gesang (Phg),
--- VERSION: 42
--- CREATED: 2014-12-08 22:36:15+0100
-------------------------------------------------------------------------------
--
diff --git a/scripts/mktests b/scripts/mktests
index b36b6dd..757e360 100755
--- a/scripts/mktests
+++ b/scripts/mktests
@@ -5,8 +5,6 @@
-- DESCRIPTION: test the behavior of Luaotfload
-- REQUIREMENTS: Luatex > 0.76, Luaotfload
-- AUTHOR: Philipp Gesang (Phg),
--- VERSION: 2.4
--- MODIFIED: 2014-05-15 22:16:47+0200
-----------------------------------------------------------------------
--
--===================================================================--
--
cgit v1.2.3
From de66d7228b7b91c93cb38c8bf50008f7137b0985 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Thu, 5 Nov 2015 23:07:53 +0100
Subject: [graph] update to current state of affairs
---
doc/Makefile | 2 +-
doc/filegraph.dot | 175 ++++++++++++++++++++++++++++++++++++++----------------
2 files changed, 126 insertions(+), 51 deletions(-)
diff --git a/doc/Makefile b/doc/Makefile
index ed340a4..6d68281 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -47,7 +47,7 @@ $(DOTPDF): $(DOT)
@echo "creating file graph ($(DOTPDF))"
$(DO_GRAPHVIZ)
-.PHONY: clean mrproper
+.PHONY: clean mrproper graph doc all manuals
clean:
@$(RM) -- *.log *.aux *.toc *.idx *.ind *.ilg *.out
diff --git a/doc/filegraph.dot b/doc/filegraph.dot
index e1a9937..af3c8ad 100644
--- a/doc/filegraph.dot
+++ b/doc/filegraph.dot
@@ -10,8 +10,8 @@ strict digraph luaotfload_files { //looks weird with circo ...
size = "21cm";
rankdir = LR;
- ranksep = 0.618;
- nodesep = 1.618;
+ ranksep = 0.618;
+ nodesep = 1.618;
edge [
arrowhead = onormal,
@@ -30,37 +30,38 @@ strict digraph luaotfload_files { //looks weird with circo ...
fontdbutil -> font_names [label="--update",
style=dashed]
- luaotfload -> otfl_fonts_merged [label="merged"]
- luaotfload -> merged_lua_libs [label="unmerged", style=solid]
- luaotfload -> merged_luatex_fonts [label="unmerged", style=solid]
- luaotfload -> merged_context_libs [label="unmerged", style=solid]
+ luaotfload -> merged_lua_libs [style=solid]
+ luaotfload -> luaotfload_init [label="main()", style=solid]
+ luaotfload -> luaotfload_libs [label="main()", style=solid]
- luaotfload -> luaotfload_libs
- luaotfload -> otfl_blacklist_cnf
-
- otfl_fonts_merged -> merged_lua_libs [label="merged",
- style=dotted,
- lhead=cluster_merged]
- otfl_fonts_merged -> merged_luatex_fonts [label="merged",
+ fontloader -> merged_luatex_fonts [label="merged",
style=dotted,
lhead=cluster_merged]
- otfl_fonts_merged -> merged_context_libs [label="merged",
+ fontloader -> merged_context_libs [label="merged",
style=dotted,
lhead=cluster_merged]
+ luaotfload_init -> luaotfload_log [label="init_early()", style=solid]
+ luaotfload_init -> luaotfload_basics_gen [label="init_early()", style=solid]
+ luaotfload_init -> fontloader [label="init_main()", style=solid]
+
+ luaotfload_init -> merged_luatex_fonts [label="unmerged", style=solid]
+ luaotfload_init -> merged_context_libs [label="unmerged", style=solid]
+
merged_luatex_fonts -> font_age [label="luatex-fonts-enc.lua",
ltail=cluster_merged]
fontdbutil -> fontdbutil_diagnostics [label="--diagnose"]
-
fontdbutil -> status [label="version information"]
- fontdbutil_diagnostics -> status [constraint=no, label="hash files"]
+ luaotfload_package -> fontloader [label="merges", style=dashed]
merged_luatex_fonts -> characters [label="luaotfload-auxiliary.lua",
ltail=cluster_merged]
- luaotfload_libs -> font_names [label="luaotfload-database.lua"]
+ luaotfload_libs -> font_names [label="luaotfload-database.lua"]
+ luaotfload_libs -> otfl_blacklist_cnf [label="luaotfload-database.lua"]
+
mkstatus -> status [label="generates from distribution files",
style=dashed]
@@ -71,13 +72,30 @@ strict digraph luaotfload_files { //looks weird with circo ...
mkcharacters -> characters [label="generates from Context’s char-def.lua",
style=dashed]
+ fontdbutil_diagnostics -> status [label="hash files"]
+
+ mkimport -> merged_luatex_fonts [label="pulls", style=dashed, constraint=no];
+ mkimport -> merged_context_libs [label="pulls", style=dashed, constraint=no];
+
subgraph { rank = same;
- mkcharacters;
- mkglyphlist;
- mkstatus;
fontdbutil;
luaotfload }
+ subgraph cluster_scripts {
+ node [style=filled, color=white];
+ style = "filled,rounded";
+ color = "#44000011:#CCCCCC77";
+ //nodesep = "3.0";
+ rank = same;
+ label = "Standalone scripts";
+ gradientangle=90;
+ mkcharacters;
+ mkglyphlist;
+ mkimport;
+ mktest;
+ mkstatus;
+ }
+
/* ····································································
* main files
* ································································· */
@@ -90,6 +108,14 @@ strict digraph luaotfload_files { //looks weird with circo ...
style = "filled,rounded",
penwidth=2]
+ luaotfload_package [label = "luaotfload-package.lua",
+ shape = rect,
+ width = "3.2cm",
+ height = "1.2cm",
+ color = "#01012222",
+ style = "filled,rounded",
+ penwidth=2]
+
fontdbutil_diagnostics [label = "luaotfload-diagnostics.lua",
shape = rect,
width = "3.2cm",
@@ -98,27 +124,43 @@ strict digraph luaotfload_files { //looks weird with circo ...
style = "filled,rounded",
penwidth=2]
+ mktest [label = "mktest",
+ shape = rect,
+ width = "3.2cm",
+ height = "0.618cm",
+ color = "#FFFFFF66",
+ style = "filled,rounded",
+ penwidth=2]
+
+ mkimport [label = "mkimport",
+ shape = rect,
+ width = "3.2cm",
+ height = "0.618cm",
+ color = "#FFFFFF66",
+ style = "filled,rounded",
+ penwidth=2]
+
mkstatus [label = "mkstatus",
shape = rect,
width = "3.2cm",
- height = "1.2cm",
- color = "#01012222",
+ height = "0.618cm",
+ color = "#FFFFFF66",
style = "filled,rounded",
penwidth=2]
mkglyphlist [label = "mkglyphlist",
shape = rect,
width = "3.2cm",
- height = "1.2cm",
- color = "#01012222",
+ height = "0.618cm",
+ color = "#FFFFFF66",
style = "filled,rounded",
penwidth=2]
mkcharacters [label = "mkcharacters",
shape = rect,
width = "3.2cm",
- height = "1.2cm",
- color = "#01012222",
+ height = "0.618cm",
+ color = "#FFFFFF66",
style = "filled,rounded",
penwidth=2]
@@ -138,13 +180,37 @@ strict digraph luaotfload_files { //looks weird with circo ...
* style = "filled,rounded",
* penwidth=2]
*/
- otfl_fonts_merged [label = "luaotfload-fontloader.lua",
- shape = rect,
- width = "3.2cm",
- height = "1.2cm",
- color = "#01012222",
- style = "filled,rounded",
- penwidth=2]
+ luaotfload_init [label = "luaotfload-init.lua",
+ shape = rect,
+ width = "3.2cm",
+ height = "1.2cm",
+ color = "#44440122",
+ style = "filled,rounded",
+ penwidth=2]
+
+ luaotfload_log [label = "luaotfload-log.lua",
+ shape = rect,
+ width = "3.2cm",
+ height = "1.2cm",
+ color = "#44440122",
+ style = "filled,rounded",
+ penwidth=2]
+
+ luaotfload_basics_gen [label = "fontloader-basics-gen.lua",
+ shape = rect,
+ width = "3.2cm",
+ height = "1.2cm",
+ color = "#FFFFFF66",
+ style = "filled,rounded",
+ penwidth=2]
+
+ fontloader [label = "fontloader-reference.lua",
+ shape = rect,
+ width = "3.2cm",
+ height = "1.2cm",
+ color = "#FFFFFF66",
+ style = "filled,rounded",
+ penwidth=2]
/* ····································································
* luaotfload files
@@ -193,15 +259,16 @@ strict digraph luaotfload_files { //looks weird with circo ...
luaotfload_libs [
shape = box,
style = "filled,rounded",
- color = "grey90:goldenrod4",
+ color = "grey90",
fontsize = 10,
label = <
| Luaotfload Libraries |
- luaotfload-auxiliary.lua | luaotfload-features.lua |
- luaotfload-loaders.lua | luaotfload-color.lua |
- luaotfload-log.lua | luaotfload-letterspace.lua |
- luaotfload-parsers.lua | luaotfload-database.lua |
+ luaotfload-auxiliary.lua | luaotfload-features.lua |
+ luaotfload-loaders.lua | luaotfload-colors.lua |
+ luaotfload-resolvers.lua | luaotfload-letterspace.lua |
+ luaotfload-parsers.lua | luaotfload-database.lua |
+ luaotfload-configuration.lua | |
>,
]
@@ -213,28 +280,40 @@ strict digraph luaotfload_files { //looks weird with circo ...
subgraph cluster_merged {
node [style=filled, color=white];
style = "filled,rounded";
- color = "grey90:dodgerblue4";
+ color = "#912CEE33";
//nodesep = "3.0";
rank = same;
label = "Merged Libraries";
gradientangle=0;
- merged_lua_libs;
merged_luatex_fonts;
merged_context_libs;
}
- otfl_fonts_merged -> merged_lua_libs
- otfl_fonts_merged -> merged_luatex_fonts
- otfl_fonts_merged -> merged_context_libs
+ fontloader -> merged_luatex_fonts
+ fontloader -> merged_context_libs
+
+ subgraph cluster_fontloader {
+ node [style=filled, color=white];
+ style = "filled,rounded";
+ color = "bisque";
+ //nodesep = "3.0";
+ rank = same;
+ label = "Fontloader";
+ gradientangle=0;
+ luaotfload_basics_gen;
+ fontloader;
+ }
merged_lua_libs [
shape = box,
style = "filled,rounded",
- color = "#FFFFFFAA",
+ color = "#CCCC1166",
+ fontsize = 10,
fontsize = 10,
label = <
- | Lua Libraries from Context |
+ |
+ Lualibs – Lua Libraries from Context |
l-lua.lua | l-lpeg.lua | l-function.lua |
l-string.lua | l-table.lua | l-io.lua |
l-file.lua | l-boolean.lua | l-math.lua |
@@ -251,17 +330,13 @@ strict digraph luaotfload_files { //looks weird with circo ...
label = <
| Font Loader (LuaTeX-Fonts) |
- luatex-basics-gen.lua | luatex-basics-nod.lua |
+ luatex-fonts-cbk.lua | luatex-basics-nod.lua |
luatex-fonts-enc.lua | luatex-fonts-syn.lua |
luatex-font-tfm.lua | luatex-font-afm.lua |
luatex-font-afk.lua | luatex-fonts-tfm.lua |
luatex-fonts-chr.lua | luatex-fonts-lua.lua |
luatex-fonts-inj.lua | luatex-fonts-otn.lua |
luatex-fonts-def.lua | luatex-fonts-ext.lua |
- luatex-fonts-cbk.lua |
-
-
-
>,
]
--
cgit v1.2.3
From 6b80e23341e454f6416d8c36c16820dcdf9a7bba Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Thu, 5 Nov 2015 23:09:12 +0100
Subject: [doc] kill off Context prototype
This was an experiment to improve documentation. Certain items like the
BNF syntax of the request parser proved too tedious to convert. Also
verbatim semantics differ greatly which requires tons of hacks to work
around. Not worth it.
---
doc/luaotfload-context.tex | 485 ---------------------------------------------
1 file changed, 485 deletions(-)
delete mode 100644 doc/luaotfload-context.tex
diff --git a/doc/luaotfload-context.tex b/doc/luaotfload-context.tex
deleted file mode 100644
index 6c8d4b2..0000000
--- a/doc/luaotfload-context.tex
+++ /dev/null
@@ -1,485 +0,0 @@
-% macros=mkvi
-%% Copyright (C) 2009-2014
-%%
-%% by Elie Roux
-%% and Khaled Hosny
-%% and Philipp Gesang
-%%
-%% This file is part of Luaotfload.
-%%
-%% Home: https://github.com/lualatex/luaotfload
-%% Support: .
-%%
-%% Luaotfload is under the GPL v2.0 (exactly) license.
-%%
-%% ----------------------------------------------------------------------------
-%%
-%% Luaotfload is free software; you can redistribute it and/or
-%% modify it under the terms of the GNU General Public License
-%% as published by the Free Software Foundation; version 2
-%% of the License.
-%%
-%% Luaotfload is distributed in the hope that it will be useful,
-%% but WITHOUT ANY WARRANTY; without even the implied warranty of
-%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-%% GNU General Public License for more details.
-%%
-%% You should have received a copy of the GNU General Public License
-%% along with Luaotfload; if not, see .
-%%
-%% ----------------------------------------------------------------------------
-%%
-
-\unprotect
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% layout and paper
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-\setuppapersize [A5] [A5] %% 148×210
-
-\definelayout [mainlayout] [
- backspace=15mm, %% 133
- textwidth=103mm,
- topspace=15mm,
-]
-
-\setuplayout [mainlayout]
-
-\setuppagenumbering [location=,alternative=doublesided]
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% colors
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-\usecolors [x11]
-\definecolor [primarycolor] [dodgerblue4]
-\definecolor [secondarycolor] [goldenrod4]
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% interaction
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-\setupinteraction [
- state=start,
- page=no,
- click=yes,
- style=italic,
- color=primarycolor,
- contrastcolor=secondarycolor,
- title={The Luaotfload package},
- subtitle={OpenType layout system for Plain TeX and LaTeX},
- author={Elie Roux & Khaled Hosny & Philipp Gesang},
- keywords={luatex, lualatex, unicode, opentype},
-]
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% fonts
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-\usemodule [simplefonts]
-
-\definefontfeature [default] [default] [mode=base,liga=yes,dlig=yes,tlig=yes,onum=yes]
-\definefontfeature [monospace] [liga=no,tlig=no,onum=no]
-
-\definefontfamily [mainface] [serif] [Linux Libertine O] [features=default]
-%definefontfamily [mainface] [serif] [Liberation Serif] [feature=default]
-%definefontfamily [mainface] [sans] [Iwona] [feature=default]
-\definefontfamily [mainface] [sans] [Iwona Medium] [
- feature=default,
- it=file:IwonaMedium-Italic.otf,
- tf=file:IwonaMedium-Regular.otf,
- bf=file:Iwona-Bold.otf,
- bi=file:Iwona-BoldItalic.otf,
-]
-%definefontfamily [mainface] [sans] [DejaVu Sans] [feature=default]
-\definefontfamily [mainface] [mono] [Liberation Mono] [scale=0.85,features=monospace]
-
-\setupbodyfont [mainface,10pt]
-
-\def \LUA {Lua}
-\def \LUALATEX {Lua\LATEX}
-\def \OpenType {\identifier{Open\kern-.25ex Type}}
-
-\definealternativestyle [emphasis:texmacro] [\ss \it \letterbackslash] [\ss \it \letterbackslash]
-\definealternativestyle [emphasis:identifier] [\ss] [\ss]
-\definealternativestyle [emphasis:normal] [\sl] [\sl]
-\definealternativestyle [emphasis:abbrev] [{\feature [+][smallcaps]}] [{\feature [+][smallcaps]}]
-\definealternativestyle [emphasis:Largefont] [{\switchtobodyfont[14pt]}] [{\switchtobodyfont[14pt]}]
-\definealternativestyle [emphasis:smallcaps] [{\feature [+][smallcaps]}] [{\feature [+][smallcaps]}]
-%definealternativestyle [emphasis:nonproportional] [\mono] [\mono]
-\definealternativestyle [emphasis:nonproportional] [\tt] [\tt]
-\definealternativestyle [head:section] [{\roman\feature[+][smallcaps]}] [{\roman\feature[+][smallcaps]}]
-\definealternativestyle [head:subsection] [{\roman\feature[+][smallcaps]}] [{\roman\feature[+][smallcaps]}]
-\definealternativestyle [head:subsubsection] [{\roman\feature[+][smallcaps]}] [{\roman\feature[+][smallcaps]}]
-\definealternativestyle [typing:luafunction] [\italic] [\italic]
-\definealternativestyle [typing:fileent] [\tt] [\tt]
-
-\definehighlight [texmacro] [style=emphasis:texmacro] %% cs
-\definehighlight [identifier] [style=emphasis:identifier] %% names
-\definehighlight [abbrev] [style=emphasis:abbrev] %% acronyms
-\definehighlight [emphasis] [style=emphasis:normal] %% level 1 emph
-
-\definehighlight [Largefont] [style=emphasis:Largefont] %% font size
-\definehighlight [smallcaps] [style=emphasis:smallcaps] %% font feature
-\definehighlight [nonproportional] [style=emphasis:nonproportional] %% font switch
-
-\definetype [fileent] [style=typing:fileent]
-\definetype [luafunction] [style=typing:luafunction]
-\setuptyping [style=ttx]
-
-\definebodyfontenvironment [8pt]
-\definebodyfontenvironment [10pt]
-\definebodyfontenvironment [12pt]
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% headings
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-\setuphead [section] [style=head:section, alternative=inmargin]
-\setuphead [subsection] [style=head:subsection, alternative=inmargin]
-\setuphead [subsubsection] [style=head:subsubsection,alternative=inmargin]
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% running headers
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-\setupheadertexts
- [{\tfx \getmarking[section]}] [pagenumber]
- [pagenumber] [{\tfx \fileent{Luaotfload} Manual}]
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% structurals
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%% section
-\def \beginsection {\dosingleempty \section_begin_indeed}
-
-\def \section_begin_indeed [#ref]#title{%
- \iffirstargument
- \startsection [reference=#ref,title=#title]%
- \else
- \startsection [title=#title]%
- \fi
-}
-
-\let \endsection \stopsection
-
-%% subsection
-\def \beginsubsection {\dosingleempty \section_begin_indeed}
-
-\def \subsection_begin_indeed [#ref]#title{%
- \iffirstargument
- \startsubsection [reference=#ref,title=#title]%
- \else
- \startsubsection [title=#title]%
- \fi
-}
-
-\let \endsubsection \stopsection
-
-%% subsubsection
-\def \beginsubsubsection {\dosingleempty \section_begin_indeed}
-
-\def \subsubsection_begin_indeed [#ref]#title{%
- \iffirstargument
- \startsubsubsection [reference=#ref,title=#title]%
- \else
- \startsubsubsection [title=#title]%
- \fi
-}
-
-\let \endsubsubsection \stopsection
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% inline verbatim
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%% Context offers both \type{…} and \type<<…>>, but not an unbalanced
-%% one that we could map directly onto Latex’s \verb|…|.
-
-\definetype [inlinecode_indeed] [style=emphasis:nonproportional]
-
-%% The listings macros don’t seem to handle backslashes and braces
-%% well. We emulate this behavior by handling the escaping in Lua.
-
-\startluacode
- local lpeg = require "lpeg"
- local Cs, P, S = lpeg.Cs, lpeg.P, lpeg.S
- local lpegmatch = lpeg.match
- local unescape_char = S[[\letterbackslash\letterleftbrace\letterrightbrace]]
- local backslash = P[[\letterbackslash]]
- local unescape = Cs (((backslash / "" * unescape_char) + 1)^0)
- commands.unescape_things = function (str)
- context.type (lpegmatch (unescape, str))
- end
-\stopluacode
-
-\unexpanded \def \inlinecode #content{%
- \ctxcommand {unescape_things \!!bs \detokenize {#content}\!!es}%
-}
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% codelistings
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Now *that’s* what I call easy.
-
-\unexpanded \def \beginlisting {%
- \grabbufferdatadirect{listing}{beginlisting}{endlisting}%
-}
-
-\unexpanded \def \endlisting {\typebuffer [listing]}
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% enumerations and lists
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-\definedescription [descriptionitem] [
- align=right,
- alternative=hanging,
- width=2em,
-]
-
-\def \begindescriptions {%
- \begingroup
- \def \beginnormalitem ##1\endnormalitem{%
- \startitem##1\stopitem
- }
- \let \endnormalitem \relax
- \let \beginaltitem \startdescriptionitem
- \let \endaltitem \stopdescriptionitem
-}
-
-\let \enddescriptions \endgroup
-
-
-\definedescription [definitionitem] [
- align=right,
- alternative=hanging,
-]
-
-\def \begindefinitions {%
- \begingroup
- \def \beginnormalitem ##1\endnormalitem{%
- \startitem##1\stopitem
- }
- \let \endnormalitem \relax
- \let \beginaltitem \startdefinitionitem
- \let \endaltitem \stopdefinitionitem
-}
-
-\let \enddefinitions \endgroup
-
-
-\definedescription [filelistitem] [
- align=normal,
- alternative=hanging,
- headstyle=typing:fileent,
- width=4cm,
-]
-
-\def \beginfilelist {%
- \begingroup
- \def \beginnormalitem ##1\endnormalitem{%
- \startitem##1\stopitem
- }
- \let \endnormalitem \relax
- \let \beginaltitem \startfilelistitem
- \let \endaltitem \stopfilelistitem
-}
-
-\let \endfilelist \endgroup
-
-\definedescription [functionlistitem] [
- align=normal,
- alternative=hanging,
- headstyle=typing:luafunction,
- width=4cm,
-]
-
-\def \beginfunctionlist {%
- \begingroup
- \def \beginnormalitem ##1\endnormalitem{%
- \startitem##1\stopitem
- }
- \let \endnormalitem \relax
- \let \beginaltitem \startfunctionlistitem
- \let \endaltitem \stopfunctionlistitem
-}
-
-\let \endfunctionlist \endgroup
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% columns
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-\def \begindoublecolumns {\startcolumns [2]}
-\let \enddoublecolumns \stopcolumns
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% alignment
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-\setupnarrower [before={\blank[line]},after={\blank[line]}]
-\let \beginnarrower \startnarrower
-\let \endnarrower \stopnarrower
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% special elements
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-\definefont [lmromantenregular] [file:lmroman10-regular.otf*default]
-
-\def \meta #1{%
- {\lmromantenregular<}%
- {\italic #1}%
- {\lmromantenregular>}%
-}
-
-\def \beginabstractcontent {%
- \grabbufferdatadirect{abstractcontent}{beginabstractcontent}{endabstractcontent}%
-}
-
-\let \endabstractcontent \relax
-
-\def \setdocumenttitle #1{\setvalue {document_title}{#1}}
-\def \setdocumentdate #1{\setvalue {document_date}{#1}}
-\def \setdocumentauthor #1{\setvalue {document_author}{#1}}
-
-\let \typesetdocumenttitle \relax
-\let \beginfrontmatter \relax
-
-\def \endfrontmatter {
- \startstandardmakeup
- \vfill
- \strut \hfill
- \startframed [frame=off,align=middle,width=.5\textwidth]
- \Largefont{\getvalue {document_title}}
- \stopframed
- \hfill \strut \par
-
- \blank [2*big]
-
- \strut \hfill
- \startframed [frame=off,align=middle,width=.65\textwidth]
- \setuplocalinterlinespace [18pt]
- \getvalue {document_author}
- \stopframed
- \hfill \strut \par
-
- \vfill
- \strut \hfill \getvalue {document_date} \hfill \strut
- \blank [2*big]
-
- \strut \hfill
- \startframed [width=.7\textwidth,align=normal,style=tfx,frame=off]%
- \getbuffer [abstractcontent]
- \stopframed
- \hfill \strut
- \stopstandardmakeup
-}
-
-\let \typesetcontent \completecontent
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% floats
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% XXX we can improve on this part later
-
-\usemodule [vim]
-\definevimtyping [bnf] [syntax=bnf]
-\definefloat [syntax] [figure]
-
-\def \beginsyntaxfloat #reference#caption{%
- \begingroup
- \edef \currentreference {#reference}%
- \edef \currentcaption {#caption}%
- \grabbufferdatadirect{rawsyntaxdata}{beginsyntaxfloat}{endsyntaxfloat}%
-}
-
-\def \endsyntaxfloat {%
- \savebuffer [rawsyntaxdata] [rawsyntaxdata]
- \startplacesyntax [
- reference=\currentreference,
- title={\currentcaption},
- ]
- %% there’s no \typebnfbuffer in t-vim :(
- \typebnffile {\jobname-rawsyntaxdata.tmp}
- \stopplacesyntax
- \endgroup%
-}
-
-\def \figurefloat #reference#caption#file{%
- \startplacefigure [
- reference=#reference,
- title={#caption},
- ]
- \externalfigure [#file] [width=\textwidth]
- \stopplacefigure
-}
-
-
-\def \tablefloat #reference#caption#content{%
- \startplacetable [
- reference=#reference,
- title={#caption},
- ]
- #content
- \stopplacetable
-}
-
-
-%% tables
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% tables
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-\setupxtable [frame=off,option=stretch,textwidth=\dimexpr(\textwidth/2)]
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% hyperlinks and references
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-\unexpanded \def \hyperlink{%
- \dosingleempty \hyperlink_indeed%
-}
-
-\def \hyperlink_indeed [#text]#url{%
- \iffirstargument
- \useURL [temporary_url] [#url] [] [#text]%
- \else
- \useURL [temporary_url] [#url]%
- \fi%
- \from [temporary_url]%
-}
-
-
-\def \email #1{\goto{#1}[url(mailto:#1)]}
-
-\def \label #tag{\reference [#tag]\empty}
-\def \pageref #tag{\at{page}{#tag}}
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% escaped characters
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-\let \charpercent \letterpercent
-\let \charbackslash \letterbackslash
-\let \chartilde \lettertilde
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% main
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-\protect
-
-\newif \ifcontextmkiv \contextmkivtrue
-
-\starttext
- \input luaotfload-main.tex
-\stoptext
-
--
cgit v1.2.3
From 4540a7d25d8a2dbbc3c773f2f27f2f1d7604b2ea Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Thu, 5 Nov 2015 23:29:15 +0100
Subject: [doc] fix manual build
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
``\luafunction`` appears to now have some fragile semantics that we’d
rather avoid. Also the Latex folks finally got rid of the ``\luatex…``
namespace for primitives.
---
doc/luaotfload-latex.tex | 6 +++---
doc/luaotfload-main.tex | 48 ++++++++++++++++++++++++------------------------
2 files changed, 27 insertions(+), 27 deletions(-)
diff --git a/doc/luaotfload-latex.tex b/doc/luaotfload-latex.tex
index 34c494d..9f09f4f 100644
--- a/doc/luaotfload-latex.tex
+++ b/doc/luaotfload-latex.tex
@@ -1,4 +1,4 @@
-\luatexsuppresslongerror1%% sigh ...
+\suppresslongerror1%% sigh ...
%% Copyright (C) 2009-2014
%%
%% by Elie Roux
@@ -129,7 +129,7 @@
\definehighlight [fileent][\ttfamily\restoreunderscore] %% files, dirs
\definehighlight [texmacro][\sffamily\itshape\textbackslash] %% cs
-\definehighlight [luafunction][\sffamily\itshape\restoreunderscore] %% lua identifiers
+\definehighlight [luaident][\sffamily\itshape\restoreunderscore] %% lua identifiers
\definehighlight [identifier][\sffamily] %% names
\definehighlight [abbrev][\rmfamily\scshape] %% acronyms
\definehighlight [emphasis][\rmfamily\slshape] %% level 1 emph
@@ -301,7 +301,7 @@
\definelist [descriptions]{\normalitem {\textbf \first}\hfill\break}
\definelist [definitions]{\normalitem {\fileent {\first}}}
\definelist [filelist]{\normalitem {\fileent {\first}}\space--\hskip 1em}
-\definelist [functionlist]{\normalitem {\luafunction {\first}}\hfill\break}
+\definelist [functionlist]{\normalitem {\luaident {\first}}\hfill\break}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% columns
diff --git a/doc/luaotfload-main.tex b/doc/luaotfload-main.tex
index c01beba..8f548fa 100644
--- a/doc/luaotfload-main.tex
+++ b/doc/luaotfload-main.tex
@@ -32,7 +32,7 @@
\beginfrontmatter
\setdocumenttitle {The \identifier{luaotfload} package}
- \setdocumentdate {2015/03/29 v2.6}
+ \setdocumentdate {2015/11/05 v2.6}
\setdocumentauthor {Elie Roux · Khaled Hosny · Philipp Gesang\\
Home: \hyperlink {https://github.com/lualatex/luaotfload}\\
Support: \email {lualatex-dev@tug.org}}
@@ -233,7 +233,7 @@ where \meta{prefix} is either \inlinecode{file:} or \inlinecode {name:}.\footnot
needed, for instance when supplying a customized tex distribution.
The \inlinecode {my} lookup takes this a step further: it lets you define
- a custom resolver function and hook it into the \luafunction{resolve_font}
+ a custom resolver function and hook it into the \luaident{resolve_font}
callback.
%
This ensures full control over how a file is located.
@@ -664,7 +664,7 @@ obviously, \inlinecode{random}.
Specific pairs of letters and ligatures may be exempt from
letterspacing by defining the \LUA functions
- \luafunction{keeptogether} and \luafunction{keepligature},
+ \luaident{keeptogether} and \luaident{keepligature},
respectively, inside the namespace \inlinecode {luaotfload.letterspace}.
%
Both functions are called whenever the letterspacing callback
@@ -673,10 +673,10 @@ obviously, \inlinecode{random}.
If they return a true-ish value, no extra kern is inserted at
the current position.
%
- \luafunction{keeptogether} receives a pair of consecutive
+ \luaident{keeptogether} receives a pair of consecutive
glyph nodes in order of their appearance in the node list.
%
- \luafunction{keepligature} receives a single node which can be
+ \luaident{keepligature} receives a single node which can be
analyzed into components.
%
(For details refer to the \emphasis{glyph nodes} section in the
@@ -1254,7 +1254,7 @@ The purpose of this addition twofold.
Firstly, \identifier{luaotfload} failed to provide a stable interface
to internals in the past which resulted in an unmanageable situation
of different packages abusing the raw access to font objects by means
-of the \luafunction{patch_font} callback.
+of the \luaident{patch_font} callback.
%
When the structure of the font object changed due to an update, all
of these imploded and several packages had to be fixed while
@@ -1275,7 +1275,7 @@ additions.
\beginsubsection {Callback Functions}
-The \luafunction{patch_font} callback is inserted in the wrapper
+The \luaident{patch_font} callback is inserted in the wrapper
\identifier{luaotfload} provides for the font definition callback.
%
At this place it allows manipulating the font object immediately after
@@ -1367,8 +1367,8 @@ are defined for which scripts.
\beginfunctionlist
\beginaltitem {aux.font_has_glyph (id : int, index : int)}
- Predicate that returns true if the font \luafunction{id}
- has glyph \luafunction{index}.
+ Predicate that returns true if the font \luaident{id}
+ has glyph \luaident{index}.
\endaltitem
\beginaltitem {aux.slot_of_name(name : string)}
@@ -1377,33 +1377,33 @@ are defined for which scripts.
\endaltitem
\beginaltitem {aux.name_of_slot(slot : int)}
- The inverse of \luafunction{slot_of_name}; note that this
+ The inverse of \luaident{slot_of_name}; note that this
might be incomplete as multiple glyph names may map to the
same codepoint, only one of which is returned by
- \luafunction{name_of_slot}.
+ \luaident{name_of_slot}.
\endaltitem
\beginaltitem {aux.provides_script(id : int, script : string)}
- Test if a font supports \luafunction{script}.
+ Test if a font supports \luaident{script}.
\endaltitem
\beginaltitem {aux.provides_language(id : int, script : string, language : string)}
- Test if a font defines \luafunction{language} for a given
- \luafunction{script}.
+ Test if a font defines \luaident{language} for a given
+ \luaident{script}.
\endaltitem
\beginaltitem {aux.provides_feature(id : int, script : string,
language : string, feature : string)}
- Test if a font defines \luafunction{feature} for
- \luafunction{language} for a given \luafunction{script}.
+ Test if a font defines \luaident{feature} for
+ \luaident{language} for a given \luaident{script}.
\endaltitem
\beginaltitem {aux.get_math_dimension(id : int, dimension : string)}
- Get the dimension \luafunction{dimension} of font \luafunction{id}.
+ Get the dimension \luaident{dimension} of font \luaident{id}.
\endaltitem
\beginaltitem {aux.sprint_math_dimension(id : int, dimension : string)}
- Same as \luafunction{get_math_dimension()}, but output the value
+ Same as \luaident{get_math_dimension()}, but output the value
in scaled points at the \TEX end.
\endaltitem
@@ -1416,7 +1416,7 @@ are defined for which scripts.
%% not implemented, may come back later
\beginfunctionlist
% \beginaltitem {aux.scan_external_dir(dir : string)}
-% Include fonts in directory \luafunction{dir} in font lookups without
+% Include fonts in directory \luaident{dir} in font lookups without
% adding them to the database.
%
\beginaltitem {aux.read_font_index (void)}
@@ -1527,9 +1527,9 @@ Another strategy that helps avoiding problems is to not access raw
Some of them, even though they are dangerous to access, have not been
overridden or disabled.
%
-Thus, whenever possible prefer the functions in the \luafunction{aux}
+Thus, whenever possible prefer the functions in the \luaident{aux}
namespace over direct manipulation of font objects. For example, raw
-access to the \luafunction{font.fonts} table like:
+access to the \luaident{font.fonts} table like:
\beginlisting
local somefont = font.fonts[2]
@@ -1537,16 +1537,16 @@ access to the \luafunction{font.fonts} table like:
\noindent can render already defined fonts unusable.
%
-Instead, the function \luafunction{font.getfont()} should be used
+Instead, the function \luaident{font.getfont()} should be used
because it has been replaced by a safe variant.
-However, \luafunction{font.getfont()} only covers fonts handled by the
+However, \luaident{font.getfont()} only covers fonts handled by the
font loader, e.~g. \identifier{OpenType} and \identifier{TrueType}
fonts, but not \abbrev{tfm} or \abbrev{ofm}.
%
Should you absolutely require access to all fonts known to \LUATEX,
including the virtual and autogenerated ones, then you need to query
-both \luafunction{font.getfont()} and \luafunction{font.fonts}.
+both \luaident{font.getfont()} and \luaident{font.fonts}.
%
In this case, best define you own accessor:
--
cgit v1.2.3
From 3f18c8edd4a571eb57faebc18a423e541f474ea2 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Thu, 5 Nov 2015 23:39:38 +0100
Subject: [*] update NEWS
---
NEWS | 2 ++
1 file changed, 2 insertions(+)
diff --git a/NEWS b/NEWS
index bf2441d..d5688b6 100644
--- a/NEWS
+++ b/NEWS
@@ -15,6 +15,8 @@ Change History
initialization
* Write names index if fonts were removed
* Separate module loading from initialization
+ * Custom fontloader package with the files from Lualibs removed
+ * Lualibs are now a dependency when used in a TeX run as well
2014/07/13, luaotfload v2.5
* Remove legacy code.
--
cgit v1.2.3
From 6a7d1e67bb6e6fd073450a104ebe3ca934eaf14c Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Fri, 6 Nov 2015 00:02:56 +0100
Subject: [doc] update manual wrt files
---
doc/luaotfload-main.tex | 104 ++++++++++++++++++++++++++++--------------------
1 file changed, 61 insertions(+), 43 deletions(-)
diff --git a/doc/luaotfload-main.tex b/doc/luaotfload-main.tex
index 8f548fa..a5ed940 100644
--- a/doc/luaotfload-main.tex
+++ b/doc/luaotfload-main.tex
@@ -1056,23 +1056,21 @@ An example with explicit paths:
\endsection
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-\beginsection {Files from \CONTEXT and \LUATEX-Fonts}
+\beginsection {The Fontloader Package}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-\identifier{luaotfload} relies on code originally written by Hans
-Hagen for the \hyperlink[\identifier{\CONTEXT}]{http://wiki.contextgarden.net}
+To a large extent, \identifier{luaotfload} relies on code originally
+written by Hans Hagen for the
+\hyperlink[\identifier{\CONTEXT}]{http://wiki.contextgarden.net}
format.
%
-It integrates the font loader as distributed in
-the \identifier{\LUATEX-Fonts} package.
+It integrates the font loader, written entirely in \LUA, as distributed
+in the \identifier{\LUATEX-Fonts} package.
%
The original \LUA source files have been combined using the
-\fileent{mtx-package} script into a single, self-contained blob.
-In this form the font loader has no further dependencies\footnote{%
- It covers, however, to some extent the functionality of the
- \identifier{lualibs} package.
-}
-and requires only minor adaptions to integrate into
+\fileent{mtx-package} script into a single, self-contained blob. In
+this form the font loader depends only on the \identifier{lualibs}
+package and requires only minor adaptions to integrate into
\identifier{luaotfload}.
%
The guiding principle is to let \CONTEXT/\LUATEX-Fonts take care of
@@ -1093,13 +1091,13 @@ Below is a commented list of the files distributed with
See figure \ref{file-graph} on page \pageref{file-graph} for a
graphical representation of the dependencies.
%
-From \LUATEX-Fonts, only the file \fileent{luatex-fonts-merged.lua}
-has been imported as \fileent{luaotfload-fontloader.lua}.
-%
-It is generated by \fileent{mtx-package}, a \LUA source code merging
-too developed by Hans Hagen.\footnote{%
- \fileent{mtx-package} is
- \hyperlink [part of \CONTEXT]{http://repo.or.cz/w/context.git/blob_plain/refs/heads/origin:/scripts/context/lua/mtx-package.lua}
+Through the script \fileent{luaotfload-package.lua} the \CONTEXT
+utility \fileent{mtx-package} is invoked to create the
+\identifier{luaotfload} fontloader as a merged (amalgamated) source
+file.\footnote{%
+ \fileent{mtx-package}, a \LUA source code merging tool developed by
+ Hans Hagen, is
+ \hyperlink [part of \CONTEXT]{https://bitbucket.org/phg/context-mirror/src/726a663be481042003566d4614266b940b5a0c91/scripts/context/lua/mtx-package.lua?at=beta}
and requires \fileent{mtxrun}.
Run
\inlinecode {mtxrun --script package --help}
@@ -1107,31 +1105,46 @@ too developed by Hans Hagen.\footnote{%
For the actual merging code see the file
\fileent{util-mrg.lua} that is part of \CONTEXT.
}
-It houses several \LUA files that can be classed in three
-categories.
+%
+This file constitutes the “reference fontloader” and is part of the
+\identifier{luaotfload} package as \fileent{fontloader-reference.lua}.
+A companion to it, \fileent{luatex-basics-gen.lua} must be loaded
+beforehand to set up parts of the environment required by the \CONTEXT
+libraries.
+%
+During a \TEX\ run, the fontloader initialization and injection happens
+in the module \fileent{luaotfload-init.lua}.
+
+A number of \emphasis{\LUA utility libraries} that are already provided
+by \identifier{lualibs} package are not part of the \identifier{luaotfload}
+fontloader.\footnote{%
+ Faithful listeners will remember the pre-2.6 era when the fontloader
+ used to be integrated as-is which caused all kinds of code
+ duplication with the pervasive \identifier{Lualibs} package.
+ This conceptual glitch has since been amended by tightening the
+ coupling with the excellent \CONTEXT\ toolchain.
+}
+\beginnarrower
+ \begindoublecolumns
+ \begindefinitions
+ \beginaltitem {l-lua.lua} \endaltitem
+ \beginaltitem {l-lpeg.lua} \endaltitem
+ \beginaltitem {l-function.lua} \endaltitem
+ \beginaltitem {l-string.lua} \endaltitem
+ \beginaltitem {l-table.lua} \endaltitem
+ \beginaltitem {l-io.lua} \endaltitem
+ \beginaltitem {l-file.lua} \endaltitem
+ \beginaltitem {l-boolean.lua} \endaltitem
+ \beginaltitem {l-math.lua} \endaltitem
+ \beginaltitem {util-str.lua} \endaltitem
+ \enddefinitions
+ \enddoublecolumns
+\endnarrower
-\begindefinitions
- \beginnormalitem
- \emphasis{\LUA utility libraries}, a subset
- of what is provided by the \identifier{lualibs}
- package.
-
- \begindoublecolumns
- \begindefinitions
- \beginaltitem {l-lua.lua} \endaltitem
- \beginaltitem {l-lpeg.lua} \endaltitem
- \beginaltitem {l-function.lua} \endaltitem
- \beginaltitem {l-string.lua} \endaltitem
- \beginaltitem {l-table.lua} \endaltitem
- \beginaltitem {l-io.lua} \endaltitem
- \beginaltitem {l-file.lua} \endaltitem
- \beginaltitem {l-boolean.lua} \endaltitem
- \beginaltitem {l-math.lua} \endaltitem
- \beginaltitem {util-str.lua} \endaltitem
- \enddefinitions
- \enddoublecolumns
- \endnormalitem
+The reference fontloader is home to several \LUA files that can be
+grouped twofold as below:
+\begindefinitions
\beginnormalitem
The \emphasis{font loader} itself.
These files have been written for
@@ -1139,7 +1152,6 @@ categories.
with \identifier{luaotfload}.
\begindoublecolumns
\begindefinitions
- \beginaltitem{luatex-basics-gen.lua} \endaltitem
\beginaltitem{luatex-basics-nod.lua} \endaltitem
\beginaltitem{luatex-fonts-enc.lua} \endaltitem
\beginaltitem{luatex-fonts-syn.lua} \endaltitem
@@ -1209,7 +1221,10 @@ files not contained in the merge. Some of these have no equivalent in
font feature handling; incorporates some of the code from
\fileent{font-otc} from \CONTEXT;
\endaltitem
- \beginaltitem {luaotfload-override.lua}
+ \beginaltitem {luaotfload-configuration.lua}
+ handling of \fileent{luaotfload.conf(5)}.
+ \endaltitem
+ \beginaltitem {luaotfload-log.lua}
overrides the \CONTEXT logging functionality.
\endaltitem
\beginaltitem {luaotfload-loaders.lua}
@@ -1222,6 +1237,9 @@ files not contained in the merge. Some of these have no equivalent in
\beginaltitem {luaotfload-database.lua}
font names database.
\endaltitem
+ \beginaltitem {luaotfload-resolvers.lua}
+ file name resolvers.
+ \endaltitem
\beginaltitem {luaotfload-colors.lua}
color handling.
\endaltitem
--
cgit v1.2.3
From 8860ba7e4cb6009ac4abca9abd37cf276c786a45 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Fri, 6 Nov 2015 00:10:40 +0100
Subject: [doc] adapt to state of the art; stub section for configuration
---
doc/luaotfload-main.tex | 28 +++++++++++++++++++---------
1 file changed, 19 insertions(+), 9 deletions(-)
diff --git a/doc/luaotfload-main.tex b/doc/luaotfload-main.tex
index a5ed940..46f66b5 100644
--- a/doc/luaotfload-main.tex
+++ b/doc/luaotfload-main.tex
@@ -1072,9 +1072,10 @@ The original \LUA source files have been combined using the
this form the font loader depends only on the \identifier{lualibs}
package and requires only minor adaptions to integrate into
\identifier{luaotfload}.
-%
-The guiding principle is to let \CONTEXT/\LUATEX-Fonts take care of
-the implementation, and update the imported code from time to time.
+
+The guiding principle is to let \CONTEXT/\LUATEX-Fonts take care of the
+implementation, and update the imported code as frequently as
+necessary.
%
As maintainers, we aim at importing files from upstream essentially
\emphasis{unmodified}, except for renaming them to prevent name
@@ -1194,11 +1195,12 @@ merged file, it will load the individual \LUA libraries
instead.
%
Their names remain the same as in \CONTEXT (without the
-\inlinecode {otfl}-prefix) since we imported the relevant section of
-\fileent{luatex-fonts.lua} unmodified into \fileent{luaotfload-main.lua}.
-Thus if you prefer running bleeding edge code from the
-\CONTEXT beta, all you have to do is remove
-\fileent{luaotfload-merged.lua} from the search path.
+\inlinecode {luaotfload}-prefix) since the initialization mirrors
+the sequence in \LUATEX-Fonts.
+%% FIXME this is a config option nowadays!
+%Thus if you prefer running bleeding edge code from the \CONTEXT beta,
+%all you have to do is remove \fileent{luaotfload-merged.lua} from the
+%search path.
Also, the merged file at some point loads the Adobe Glyph List from a
\LUA table that is contained in \fileent{luaotfload-glyphlist.lua},
@@ -1206,8 +1208,9 @@ which is automatically generated by the script
\fileent{mkglyphlist}.\footnote{%
See \fileent{luaotfload-font-enc.lua}.
The hard-coded file name is why we have to replace the procedure
- that loads the file in \fileent{luaotfload-override.lua}.
+ that loads the file in \fileent{luaotfload-init.lua}.
}
+%
There is a make target \identifier{glyphs} that will create a fresh
glyph list so we don’t need to import it from \CONTEXT any longer.
@@ -1259,6 +1262,13 @@ files not contained in the merge. Some of these have no equivalent in
\endsection
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\beginsection {Configuration Files}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\emphasis{Caution}: For the authoritative documentation, consult the
+manpage for \fileent{luaotfload.conf(5)}.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\beginsection {Auxiliary Functions}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--
cgit v1.2.3
From 28dc7605d7875058227c5690a8f6354e1979d1b5 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Fri, 6 Nov 2015 00:17:32 +0100
Subject: [doc] remove redundant namespace prefixing for primitives
---
doc/luaotfload-latex.tex | 18 +++++++++---------
doc/luaotfload-main.tex | 40 ++++++++++++++++++++--------------------
2 files changed, 29 insertions(+), 29 deletions(-)
diff --git a/doc/luaotfload-latex.tex b/doc/luaotfload-latex.tex
index 9f09f4f..32ad3cb 100644
--- a/doc/luaotfload-latex.tex
+++ b/doc/luaotfload-latex.tex
@@ -220,9 +220,9 @@
\newcount \othercatcode \othercatcode 12
\newcount \activecatcode \othercatcode 13
-\newluatexcatcodetable \vrbcatcodes
-\setluatexcatcodetable \vrbcatcodes {%
- \luatexcatcodetable \CatcodeTableIniTeX
+\newcatcodetable \vrbcatcodes
+\setcatcodetable \vrbcatcodes {%
+ \catcodetable \CatcodeTableIniTeX
\catcode 9 \othercatcode %% \tabasciicode
\catcode 13 \othercatcode %% \endoflineasciicode
\catcode 12 \othercatcode %% \formfeedasciicode
@@ -230,22 +230,22 @@
\catcode 32 \othercatcode %% \spaceasciicode
}
-\newluatexcatcodetable \literalcatcodes
-\setluatexcatcodetable \literalcatcodes {%
- \luatexcatcodetable \CatcodeTableString
+\newcatcodetable \literalcatcodes
+\setcatcodetable \literalcatcodes {%
+ \catcodetable \CatcodeTableString
\catcode 32 \activecatcode %% \spaceasciicode
}
\def \beginlisting {%
\begingroup
- \luatexcatcodetable \vrbcatcodes
+ \catcodetable \vrbcatcodes
\beginlistingindeed%
}
\directlua {
local texprint = tex.print
local stringsub = string.sub
- local backslash = string.byte (0x5c)
+ local backslash = string.char (0x5c)
document = document or { }
document.printlines = function (buffer)
for _, line in next, string.explode (buffer, "\noexpand\n") do
@@ -266,7 +266,7 @@
\begin {quote}
\bgroup
\addfontfeature {RawFeature=-tlig;-liga}%% So one can’t just turn them all off at once using the ``Ligatures`` key?
- \luatexcatcodetable \literalcatcodes
+ \catcodetable \literalcatcodes
\obeyspaces
\obeylines
\directlua{document.printlines ([==[\detokenize {#1}]==])}
diff --git a/doc/luaotfload-main.tex b/doc/luaotfload-main.tex
index 46f66b5..7badffd 100644
--- a/doc/luaotfload-main.tex
+++ b/doc/luaotfload-main.tex
@@ -1116,31 +1116,31 @@ libraries.
During a \TEX\ run, the fontloader initialization and injection happens
in the module \fileent{luaotfload-init.lua}.
-A number of \emphasis{\LUA utility libraries} that are already provided
-by \identifier{lualibs} package are not part of the \identifier{luaotfload}
-fontloader.\footnote{%
+A number of \emphasis{\LUA utility libraries} are not part of the
+\identifier{luaotfload} fontloader, contrary to its equivalent in
+\LUATEX-Fonts. These are already provided by the \identifier{lualibs}
+and have thus been omitted from the merge.\footnote{%
Faithful listeners will remember the pre-2.6 era when the fontloader
used to be integrated as-is which caused all kinds of code
- duplication with the pervasive \identifier{Lualibs} package.
+ duplication with the pervasive \identifier{lualibs} package.
This conceptual glitch has since been amended by tightening the
coupling with the excellent \CONTEXT\ toolchain.
}
-\beginnarrower
- \begindoublecolumns
- \begindefinitions
- \beginaltitem {l-lua.lua} \endaltitem
- \beginaltitem {l-lpeg.lua} \endaltitem
- \beginaltitem {l-function.lua} \endaltitem
- \beginaltitem {l-string.lua} \endaltitem
- \beginaltitem {l-table.lua} \endaltitem
- \beginaltitem {l-io.lua} \endaltitem
- \beginaltitem {l-file.lua} \endaltitem
- \beginaltitem {l-boolean.lua} \endaltitem
- \beginaltitem {l-math.lua} \endaltitem
- \beginaltitem {util-str.lua} \endaltitem
- \enddefinitions
- \enddoublecolumns
-\endnarrower
+
+\begindoublecolumns
+ \begindefinitions
+ \beginaltitem {l-lua.lua} \endaltitem
+ \beginaltitem {l-lpeg.lua} \endaltitem
+ \beginaltitem {l-function.lua} \endaltitem
+ \beginaltitem {l-string.lua} \endaltitem
+ \beginaltitem {l-table.lua} \endaltitem
+ \beginaltitem {l-io.lua} \endaltitem
+ \beginaltitem {l-file.lua} \endaltitem
+ \beginaltitem {l-boolean.lua} \endaltitem
+ \beginaltitem {l-math.lua} \endaltitem
+ \beginaltitem {util-str.lua} \endaltitem
+ \enddefinitions
+\enddoublecolumns
The reference fontloader is home to several \LUA files that can be
grouped twofold as below:
--
cgit v1.2.3
From 15685e52158389814e17d0b855a78851b3b3f879 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Sat, 7 Nov 2015 00:28:03 +0100
Subject: [doc] revise listings printer
---
doc/Makefile | 2 +-
doc/luaotfload-latex.tex | 73 ++++++++++++++++++++++++++++++++++++------------
2 files changed, 56 insertions(+), 19 deletions(-)
diff --git a/doc/Makefile b/doc/Makefile
index 6d68281..0355a0e 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -1,6 +1,6 @@
NAME = luaotfload
DOCPDF = $(NAME).pdf
-DOCSRC = $(NAME)-latex.tex
+DOCSRC = $(NAME)-latex.tex $(NAME)-main.tex
SCRIPTNAME = luaotfload-tool
TOOLMANSRC = $(SCRIPTNAME).rst
diff --git a/doc/luaotfload-latex.tex b/doc/luaotfload-latex.tex
index 32ad3cb..e3541c5 100644
--- a/doc/luaotfload-latex.tex
+++ b/doc/luaotfload-latex.tex
@@ -230,48 +230,85 @@
\catcode 32 \othercatcode %% \spaceasciicode
}
+\directlua {
+ document = document or { }
+ document.vrbcatcodesidx = tonumber (\the \vrbcatcodes)
+}
+
\newcatcodetable \literalcatcodes
\setcatcodetable \literalcatcodes {%
\catcodetable \CatcodeTableString
\catcode 32 \activecatcode %% \spaceasciicode
}
+\def \listingsurroundskip {\vskip \baselineskip}
+
\def \beginlisting {%
+ \noindent
\begingroup
\catcodetable \vrbcatcodes
\beginlistingindeed%
}
\directlua {
- local texprint = tex.print
- local stringsub = string.sub
- local backslash = string.char (0x5c)
- document = document or { }
+ local texsprint = tex.sprint
+ local stringis_empty = string.is_empty
+ local stringsub = string.sub
+ local stringgsub = string.gsub
+ %local backslash = unicode.utf8.char (0x200c)
+ local backslash = unicode.utf8.char (0x5c)
+ local escaped = [[\string\string\string\]]
document.printlines = function (buffer)
- for _, line in next, string.explode (buffer, "\noexpand\n") do
- if stringsub (line, 1, 1) == " " then
- line = backslash .. line
+ local lines = string.explode (buffer, "\noexpand\n")
+ print ""
+ for i, line in next, lines do
+ local line = stringgsub (line, backslash, escaped)
+ if stringis_empty (line) then
+ print (i, "listing: ")
+ texsprint [[\string\listingpar]]
+ else
+ local line = [[\string\beginlistingline]]
+ .. line
+ .. [[\string\endlistingline]]
+ .. [[\string\listingpar]]
+ print (i, "listing: «" .. line .. "»")
+ texsprint (document.vrbcatcodesidx, line)
end
- texprint (-1, line)
- texprint (-1, "")
end
end
}
+\def \listingpar {\endgraf}
+
+\let \endlistingline \relax
+\let \endlisting \relax
+
+\protected \def \beginlistingline{%
+ \leavevmode
+ \begingroup
+ \beginlistinglineindeed%
+}
+
+\def \beginlistinglineindeed #1\endlistingline{%
+ \endgroup
+ \hbox{%
+ \addfontfeature {RawFeature=-tlig;-liga}%% So one can’t just turn them all off at once using the ``Ligatures`` key?
+ \obeyspaces
+ #1}%
+}
+
\def \beginlistingindeed#1\endlisting{%
\endgroup
\begingroup
+ \endgraf
+ \listingsurroundskip
\ttfamily
\small
- \begin {quote}
- \bgroup
- \addfontfeature {RawFeature=-tlig;-liga}%% So one can’t just turn them all off at once using the ``Ligatures`` key?
- \catcodetable \literalcatcodes
- \obeyspaces
- \obeylines
- \directlua{document.printlines ([==[\detokenize {#1}]==])}
- \egroup
- \end {quote}
+ \parindent = 0em
+ \leftskip = 2em
+ \hangindent = 2em
+ \directlua{document.printlines ([==[\detokenize {#1}]==])}%
+ \listingsurroundskip
\endgroup
}
--
cgit v1.2.3
From 65c8b21ab3bf907357b203a7b5c6fb5b0a971cea Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Sat, 7 Nov 2015 00:42:06 +0100
Subject: [doc] expand documentation of config files
---
doc/luaotfload-main.tex | 73 ++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 66 insertions(+), 7 deletions(-)
diff --git a/doc/luaotfload-main.tex b/doc/luaotfload-main.tex
index 7badffd..4b5e2e8 100644
--- a/doc/luaotfload-main.tex
+++ b/doc/luaotfload-main.tex
@@ -686,7 +686,7 @@ obviously, \inlinecode{random}.
user.
\endaltitem
-\ifcontextmkiv
+\iffalse
\startbuffer [printvectors]
\directlua{inspect(fonts.protrusions.setups.default)
inspect(fonts.expansions.setups.default)}
@@ -706,7 +706,7 @@ obviously, \inlinecode{random}.
%
Alternatively and with loss of information, you can dump
those tables into your terminal by issuing
- \unless \ifcontextmkiv
+ \unless \iffalse
\beginlisting
\directlua{inspect(fonts.protrusions.setups.default)
inspect(fonts.expansions.setups.default)}
@@ -763,7 +763,7 @@ Currently (2014) there are three of them:
remapping feature.
}:
- \unless \ifcontextmkiv
+ \unless \iffalse
%% Using braced arg syntax with inline code appears to be
%% impossible within Latex tables -- just ignore the weird
%% exclamation points below.
@@ -905,7 +905,7 @@ directories.
\tablefloat {table-searchpaths}
{List of paths searched for each supported operating system.}
{%
- \unless \ifcontextmkiv
+ \unless \iffalse
\begincentered
\begintabulate [lp{.5\textwidth}]
\beginrow
@@ -1262,18 +1262,77 @@ files not contained in the merge. Some of these have no equivalent in
\endsection
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\beginsection {Packaging a Fontloader}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+TODO % it’s simple, though
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\beginsection {Configuration Files}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-\emphasis{Caution}: For the authoritative documentation, consult the
-manpage for \fileent{luaotfload.conf(5)}.
+\beginnarrower
+ \emphasis{Caution}: For the authoritative documentation, consult the
+ manpage for \fileent{luaotfload.conf(5)}.
+\endnarrower
+
+The runtime behavior of \identifier{Luaotfload} can be customized by
+means of a configuration file.
+% location
+At startup, it attempts to locate a file called \fileent
+{luaotfload.conf} or \fileent {luaotfloadrc} at a number of candidate
+locations:
+
+\begincentered
+ \begindefinitions
+ \beginnormalitem \fileent{./luaotfload.conf} \endnormalitem
+ \beginnormalitem \fileent{./luaotfloadrc} \endnormalitem
+ \beginnormalitem \fileent{\$XDG_CONFIG_HOME/luaotfload/luaotfload.conf} \endnormalitem
+ \beginnormalitem \fileent{\$XDG_CONFIG_HOME/luaotfload/luaotfload.rc} \endnormalitem
+ \beginnormalitem \fileent{~/.luaotfloadrc} \endnormalitem
+ \enddefinitions
+\endcentered
+
+\beginnarrower
+ \emphasis{Caution}: The configuration potentially modifies the final
+ document. A project-local file belongs under version control along
+ with the rest of the document. This is to ensure that everybody who
+ builds the project also receives the same customizations as the
+ author.
+\endnarrower
+
+% syntax
+% example settings
+
+An example for customization via \fileent {luaotfload.conf} might look
+as below:
+
+\beginlisting
+; Example luaotfload.conf containing a rudimentary configuration
+[db]
+ update-live = false
+[run]
+ color-callback = pre_linebreak_filter
+ definer = info_patch
+ log-level = 5
+[default-features]
+ global = mode=base
+\endlisting
+
+This specifies that for the given project, \identifier{Luaotfload}
+shall not attempt to automatically scan for fonts if it can’t resolve a
+request. The font-based colorization will happen during \LUATEX’s
+pre-linebreak filter. The fontloader will output verbose information
+about the fonts at definition time along with globally increased
+verbosity. Lastly, the fontloader defaults to the less expensive
+\luaident{base} mode like it does in \CONTEXT.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\beginsection {Auxiliary Functions}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-With release version 2.2, \identifier{luaotfload} received
+With release version 2.2, \identifier{Luaotfload} received
additional functions for package authors to call from outside
(see the file \fileent{luaotfload-auxiliary.lua} for details).
%
--
cgit v1.2.3
From 54e6a5293dbff1e3775c2c3478b80c244608a4a5 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Sat, 7 Nov 2015 08:26:48 +0100
Subject: [doc] briefly describe config file syntax
---
doc/luaotfload-main.tex | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/doc/luaotfload-main.tex b/doc/luaotfload-main.tex
index 4b5e2e8..112572f 100644
--- a/doc/luaotfload-main.tex
+++ b/doc/luaotfload-main.tex
@@ -1303,8 +1303,14 @@ locations:
\endnarrower
% syntax
+The syntax is fairly close to the format used by
+\fileent{git-config(1)} which in turn was derived from the popular
+\identifier{.INI} format: Lines of key-value pairs are grouped under
+different configuration “sections”.\footnote{%
+ The configuration parser in \fileent {luoatfload-parsers.lua} might
+ be employed by other packages for similar purposes.
+}
% example settings
-
An example for customization via \fileent {luaotfload.conf} might look
as below:
--
cgit v1.2.3
From 55945326011925fa81cca8cf2b5b9376025451a5 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Sat, 7 Nov 2015 08:44:55 +0100
Subject: [doc] introduce fontloader switching
---
doc/luaotfload-main.tex | 31 ++++++++++++++++++++++++++-----
1 file changed, 26 insertions(+), 5 deletions(-)
diff --git a/doc/luaotfload-main.tex b/doc/luaotfload-main.tex
index 112572f..cc242e8 100644
--- a/doc/luaotfload-main.tex
+++ b/doc/luaotfload-main.tex
@@ -43,6 +43,11 @@
This package is an adaptation of the \CONTEXT font loading system.
It allows for loading \OpenType fonts with an extended syntax and adds
support for a variety of font features.
+
+ After discussion of the font loading API, this manual gives an
+ overview of the core components of \identifier{Luaotfload}: The
+ packaged font loader code, the names database, configuration, and
+ helper functions on the \LUA\ end.
\endabstractcontent
\endfrontmatter
@@ -1056,9 +1061,11 @@ An example with explicit paths:
\endsection
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-\beginsection {The Fontloader Package}
+\beginsection {The Fontloader}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\beginsubsection {Overview}
+
To a large extent, \identifier{luaotfload} relies on code originally
written by Hans Hagen for the
\hyperlink[\identifier{\CONTEXT}]{http://wiki.contextgarden.net}
@@ -1086,6 +1093,10 @@ This job has been greatly alleviated since the advent of
manually spotted and extracted from the \CONTEXT source code in a
complicated and error-prone fashion.
+\endsubsection
+
+\beginsubsection {Contents and Dependencies}
+
Below is a commented list of the files distributed with
\identifier{luaotfload} in one way or the other.
%
@@ -1260,14 +1271,23 @@ files not contained in the merge. Some of these have no equivalent in
{Schematic of the files in \identifier{Luaotfload}}
{filegraph.pdf}
-\endsection
+\endsubsection
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-\beginsection {Packaging a Fontloader}
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\beginsubsection {Packaging}
+
+The fontloader code is integrated as an isolated component that can be
+switched out on demand.
+To specify the fontloader you wish to use, the configuration file
+(described in section \ref{sec:conf}) provides the option
+\inlinecode{fontloader}. Its value can be one of the identifiers
+\inlinecode{default} or \inlinecode{reference} or the name of a file
+somewhere in the search path of \LUATEX.
TODO % it’s simple, though
+\endsubsection
+\endsection
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\beginsection {Configuration Files}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1277,6 +1297,7 @@ TODO % it’s simple, though
manpage for \fileent{luaotfload.conf(5)}.
\endnarrower
+\label{sec:conf}
The runtime behavior of \identifier{Luaotfload} can be customized by
means of a configuration file.
% location
--
cgit v1.2.3
From 389fe13c73832215d8486e43ed3c52f6c96f45ca Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Mon, 9 Nov 2015 08:03:29 +0100
Subject: [main,init] add no-op loader for fontloader files
---
src/luaotfload-init.lua | 38 +++++++++++++++++++++++---------------
src/luaotfload-main.lua | 12 ++++++++++++
2 files changed, 35 insertions(+), 15 deletions(-)
diff --git a/src/luaotfload-init.lua b/src/luaotfload-init.lua
index 1c2046d..1d6d1a5 100644
--- a/src/luaotfload-init.lua
+++ b/src/luaotfload-init.lua
@@ -203,6 +203,7 @@ end --- [init_adapt]
local init_main = function ()
local load_fontloader_module = luaotfload.loaders.fontloader
+ local ignore_module = luaotfload.loaders.ignore
--[[doc--
@@ -214,26 +215,33 @@ local init_main = function ()
--doc]]--
+ logreport ("log", 4, "init",
+ "Loading fontloader as merged package.")
load_fontloader_module (luaotfload.fontloader_package)
---load_fontloader_module "font-odv.lua" --- <= Devanagari support from Context
if not fonts then
- --- the loading sequence is known to change, so this might have to
- --- be updated with future updates!
- --- do not modify it though unless there is a change to the merged
- --- package!
- load_fontloader_module "l-lua"
- load_fontloader_module "l-lpeg"
- load_fontloader_module "l-function"
- load_fontloader_module "l-string"
- load_fontloader_module "l-table"
- load_fontloader_module "l-io"
- load_fontloader_module "l-file"
- load_fontloader_module "l-boolean"
- load_fontloader_module "l-math"
- load_fontloader_module "util-str"
- load_fontloader_module "luatex-basics-gen"
+ logreport ("log", 4, "init",
+ "Loading fontloader components individually.")
+ --- The loading sequence is known to change, so this might have to be
+ --- updated with future updates. Do not modify it though unless there is
+ --- a change to the upstream package!
+
+ --- Since 2.6 those are directly provided by the Lualibs package.
+ ignore_module "l-lua"
+ ignore_module "l-lpeg"
+ ignore_module "l-function"
+ ignore_module "l-string"
+ ignore_module "l-table"
+ ignore_module "l-io"
+ ignore_module "l-file"
+ ignore_module "l-boolean"
+ ignore_module "l-math"
+ ignore_module "util-str"
+ ignore_module "luatex-basics-gen"
+
+ --- These constitute the fontloader proper.
load_fontloader_module "data-con"
load_fontloader_module "luatex-basics-nod"
load_fontloader_module "font-ini"
diff --git a/src/luaotfload-main.lua b/src/luaotfload-main.lua
index 85c9cee..686ce0e 100644
--- a/src/luaotfload-main.lua
+++ b/src/luaotfload-main.lua
@@ -127,11 +127,23 @@ local make_loader = function (prefix)
end
end
+--[[doc--
+ Certain files are kept around that aren’t loaded because they are part of
+ the imported fontloader. In order to keep the initialization structure
+ intact we also provide a no-op version of the module loader that can be
+ called in the expected places.
+--doc]]--
+
+local dummy_loader = function (name)
+ luaotfload.log.report("log", 3, "load", "Skipping module “%s”.", name)
+end
+
local install_loaders = function ()
local loaders = { }
local loadmodule = make_loader "luaotfload"
loaders.luaotfload = loadmodule
loaders.fontloader = make_loader "fontloader"
+ loaders.ignore = dummy_loader
----loaders.plaintex = make_loader "luatex" --=> for Luatex-Plain
loaders.initialize = function (name)
--
cgit v1.2.3
From 60f41dfbc13f06a1b43a4e66798a0d043d210eee Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Mon, 9 Nov 2015 08:16:19 +0100
Subject: [init,conf] enable direct loading of fontloader components
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
For now, this pertains only to the modules we ship in Luaotfload. For
loading from Context we still need a step to distinguish between the
namespaced versions of the files, the pure ones in texmf/…/base, and the
Luatex-Fonts ones.
But yeah, setting
[run]
fontloader = unpackaged
in the luaotfloadrc now works splendidly.
---
src/luaotfload-configuration.lua | 8 +++---
src/luaotfload-init.lua | 53 +++++++++++++++++++++++++---------------
2 files changed, 38 insertions(+), 23 deletions(-)
diff --git a/src/luaotfload-configuration.lua b/src/luaotfload-configuration.lua
index 6f94195..1fe30fe 100644
--- a/src/luaotfload-configuration.lua
+++ b/src/luaotfload-configuration.lua
@@ -127,9 +127,11 @@ local feature_presets = {
--doc]]--
local registered_loaders = {
- default = luaotfloadstatus and luaotfloadstatus.notes.loader or "reference",
- reference = "reference",
- tl2014 = "tl2014",
+ default = luaotfloadstatus and luaotfloadstatus.notes.loader or "reference",
+ reference = "reference",
+ unpackaged = "unpackaged",
+ context = "context",
+ tl2014 = "tl2014",
}
--[[doc--
diff --git a/src/luaotfload-init.lua b/src/luaotfload-init.lua
index 1d6d1a5..c2899d7 100644
--- a/src/luaotfload-init.lua
+++ b/src/luaotfload-init.lua
@@ -215,14 +215,11 @@ local init_main = function ()
--doc]]--
- logreport ("log", 4, "init",
- "Loading fontloader as merged package.")
- load_fontloader_module (luaotfload.fontloader_package)
-
- ---load_fontloader_module "font-odv.lua" --- <= Devanagari support from Context
+ local fontloader = config.luaotfload and config.luaotfload.run.fontloader
+ or "reference"
- if not fonts then
- logreport ("log", 4, "init",
+ if fontloader == "unpackaged" then
+ logreport ("both", 4, "init",
"Loading fontloader components individually.")
--- The loading sequence is known to change, so this might have to be
--- updated with future updates. Do not modify it though unless there is
@@ -243,27 +240,43 @@ local init_main = function ()
--- These constitute the fontloader proper.
load_fontloader_module "data-con"
- load_fontloader_module "luatex-basics-nod"
+ load_fontloader_module "basics-nod"
load_fontloader_module "font-ini"
load_fontloader_module "font-con"
- load_fontloader_module "luatex-fonts-enc"
+ load_fontloader_module "fonts-enc"
load_fontloader_module "font-cid"
load_fontloader_module "font-map"
- load_fontloader_module "luatex-fonts-syn"
- load_fontloader_module "luatex-fonts-tfm"
+ load_fontloader_module "fonts-syn"
+ load_fontloader_module "fonts-tfm"
load_fontloader_module "font-oti"
load_fontloader_module "font-otf"
load_fontloader_module "font-otb"
- load_fontloader_module "luatex-fonts-inj" --> since 2014-01-07, replaces node-inj.lua
- load_fontloader_module "luatex-fonts-ota"
- load_fontloader_module "luatex-fonts-otn" --> since 2014-01-07, replaces font-otn.lua
- load_fontloader_module "font-otp" --> since 2013-04-23
- load_fontloader_module "luatex-fonts-lua"
+ load_fontloader_module "fonts-inj" --> since 2014-01-07, replaces node-inj.lua
+ load_fontloader_module "fonts-ota"
+ load_fontloader_module "fonts-otn" --> since 2014-01-07, replaces font-otn.lua
+ load_fontloader_module "font-otp" --> since 2013-04-23
+ load_fontloader_module "fonts-lua"
load_fontloader_module "font-def"
- load_fontloader_module "luatex-fonts-def"
- load_fontloader_module "luatex-fonts-ext"
- load_fontloader_module "luatex-fonts-cbk"
- end --- non-merge fallback scope
+ load_fontloader_module "fonts-def"
+ load_fontloader_module "fonts-ext"
+ load_fontloader_module "fonts-cbk"
+
+ elseif fontloader == "context" then
+ logreport ("both", 4, "init",
+ "Loading fontloader components from context.")
+ logreport ("both", 0, "init", "NOT IMPLEMENTED YET.")
+ os.exit(-42)
+
+ elseif fontloader then
+ fontloader = tostring (fontloader)
+ --- “reference”, “default”
+ logreport ("both", 4, "init",
+ "Attempting to load fontloader “%s”.",
+ fontloader)
+ load_fontloader_module (luaotfload.fontloader_package)
+ end
+
+ ---load_fontloader_module "font-odv.lua" --- <= Devanagari support from Context
end --- [init_main]
--
cgit v1.2.3
From a67b8e37ab846a79c69ee26761835934680e41b4 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Tue, 10 Nov 2015 08:02:36 +0100
Subject: [main] implement a loader for Context files
---
src/luaotfload-main.lua | 39 +++++++++++++++++++++++++++++----------
1 file changed, 29 insertions(+), 10 deletions(-)
diff --git a/src/luaotfload-main.lua b/src/luaotfload-main.lua
index 686ce0e..0ed57da 100644
--- a/src/luaotfload-main.lua
+++ b/src/luaotfload-main.lua
@@ -99,16 +99,24 @@ end
local make_loader_name = function (prefix, name)
local msg = luaotfload.log and luaotfload.log.report or print
- if prefix and name then
- msg ("log", 7, "load",
- "Composing module name from constituents %s, %s",
- prefix, name)
- return prefix .. "-" .. name .. ".lua"
+ if not name then
+ msg ("both", 0, "load",
+ "Fatal error: make_loader_name (“%s”, “%s”).",
+ tostring (prefix), tostring (name))
+ return "dummy-name"
end
- msg ("log", 7, "load",
- "Loading module %s literally.",
- tostring (name))
- return name
+ name = tostring (name)
+ if prefix == false then
+ msg ("log", 9, "load",
+ "No prefix requested, passing module name “%s” unmodified.",
+ name)
+ return tostring (name) .. ".lua"
+ end
+ prefix = tostring (prefix)
+ msg ("log", 9, "load",
+ "Composing module name from constituents %s, %s.",
+ prefix, name)
+ return prefix .. "-" .. name .. ".lua"
end
local timing_info = {
@@ -135,7 +143,17 @@ end
--doc]]--
local dummy_loader = function (name)
- luaotfload.log.report("log", 3, "load", "Skipping module “%s”.", name)
+ luaotfload.log.report("log", 3, "load", "Skipping module “%s” on purpose.", name)
+end
+
+local context_loader = function (name)
+ luaotfload.log.report("log", 3, "load", "Loading module “%s” from Context.", name)
+ local t_0 = osgettimeofday ()
+ local modname = make_loader_name (false, name)
+ local data = require (modname)
+ local t_end = osgettimeofday ()
+ timing_info.t_load [name] = t_end - t_0
+ return data
end
local install_loaders = function ()
@@ -143,6 +161,7 @@ local install_loaders = function ()
local loadmodule = make_loader "luaotfload"
loaders.luaotfload = loadmodule
loaders.fontloader = make_loader "fontloader"
+ loaders.context = context_loader
loaders.ignore = dummy_loader
----loaders.plaintex = make_loader "luatex" --=> for Luatex-Plain
--
cgit v1.2.3
From 43f18a389a1380e950cea104f3ada32c88c47863 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Tue, 10 Nov 2015 08:06:55 +0100
Subject: [init] access the context loader from init
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Works fine now by choosing the “context” fontloader in luaotfloadrc.
---
src/luaotfload-init.lua | 37 ++++++++++++++++++++++++++++++++++++-
1 file changed, 36 insertions(+), 1 deletion(-)
diff --git a/src/luaotfload-init.lua b/src/luaotfload-init.lua
index c2899d7..ca5d9ec 100644
--- a/src/luaotfload-init.lua
+++ b/src/luaotfload-init.lua
@@ -203,6 +203,7 @@ end --- [init_adapt]
local init_main = function ()
local load_fontloader_module = luaotfload.loaders.fontloader
+ local load_context_module = luaotfload.loaders.context
local ignore_module = luaotfload.loaders.ignore
--[[doc--
@@ -265,7 +266,41 @@ local init_main = function ()
logreport ("both", 4, "init",
"Loading fontloader components from context.")
logreport ("both", 0, "init", "NOT IMPLEMENTED YET.")
- os.exit(-42)
+ --- Since 2.6 those are directly provided by the Lualibs package.
+ ignore_module "l-lua"
+ ignore_module "l-lpeg"
+ ignore_module "l-function"
+ ignore_module "l-string"
+ ignore_module "l-table"
+ ignore_module "l-io"
+ ignore_module "l-file"
+ ignore_module "l-boolean"
+ ignore_module "l-math"
+ ignore_module "util-str"
+
+ --- These constitute the fontloader proper.
+ load_context_module "luatex-basics-gen"
+ load_context_module "data-con"
+ load_context_module "luatex-basics-nod"
+ load_context_module "font-ini"
+ load_context_module "font-con"
+ load_context_module "luatex-fonts-enc"
+ load_context_module "font-cid"
+ load_context_module "font-map"
+ load_context_module "luatex-fonts-syn"
+ load_context_module "luatex-fonts-tfm"
+ load_context_module "font-oti"
+ load_context_module "font-otf"
+ load_context_module "font-otb"
+ load_context_module "luatex-fonts-inj" --> since 2014-01-07, replaces node-inj.lua
+ load_context_module "luatex-fonts-ota"
+ load_context_module "luatex-fonts-otn" --> since 2014-01-07, replaces font-otn.lua
+ load_context_module "font-otp" --> since 2013-04-23
+ load_context_module "luatex-fonts-lua"
+ load_context_module "font-def"
+ load_context_module "luatex-fonts-def"
+ load_context_module "luatex-fonts-ext"
+ load_context_module "luatex-fonts-cbk"
elseif fontloader then
fontloader = tostring (fontloader)
--
cgit v1.2.3
From 952d2c9b24c1b2e6f0f48df28981c1f2674137f4 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Tue, 10 Nov 2015 08:17:38 +0100
Subject: [doc] add directions for loading Context libs
---
doc/luaotfload-main.tex | 24 +++++++++++-------------
1 file changed, 11 insertions(+), 13 deletions(-)
diff --git a/doc/luaotfload-main.tex b/doc/luaotfload-main.tex
index cc242e8..5ea70d8 100644
--- a/doc/luaotfload-main.tex
+++ b/doc/luaotfload-main.tex
@@ -1201,17 +1201,17 @@ grouped twofold as below:
\endnormalitem
\enddefinitions
-Note that if \identifier{luaotfload} cannot locate the
-merged file, it will load the individual \LUA libraries
-instead.
-%
-Their names remain the same as in \CONTEXT (without the
-\inlinecode {luaotfload}-prefix) since the initialization mirrors
-the sequence in \LUATEX-Fonts.
-%% FIXME this is a config option nowadays!
-%Thus if you prefer running bleeding edge code from the \CONTEXT beta,
-%all you have to do is remove \fileent{luaotfload-merged.lua} from the
-%search path.
+As an alternative to the merged file, \identifier {Luaotfload} may load
+individual unpackaged \LUA libraries that come with the source, or even
+use the files from Context directly.
+%
+Thus if you prefer running bleeding edge code from the \CONTEXT beta,
+all you have to do is to choose the \inlinecode {context} fontloader
+via the configuration file (see section \ref{sec:conf} below).
+%
+This will make \identifier {Luaotfload} locate the \CONTEXT source via
+\identifier{kpathsea} lookups and use those instead of the fontloader
+%% TODO allow choosing the context path
Also, the merged file at some point loads the Adobe Glyph List from a
\LUA table that is contained in \fileent{luaotfload-glyphlist.lua},
@@ -1283,8 +1283,6 @@ To specify the fontloader you wish to use, the configuration file
\inlinecode{default} or \inlinecode{reference} or the name of a file
somewhere in the search path of \LUATEX.
-TODO % it’s simple, though
-
\endsubsection
\endsection
--
cgit v1.2.3
From 54e74772fab02405bf90362d76884e88b63eb381 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Thu, 12 Nov 2015 08:15:06 +0100
Subject: [conf] implement path-based fontloader specification
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Makes the config test for paths specified as “context:/path/to/texmf”
and return a ("context", path) pair that is intended for use as the base
path of the fontloader files.
---
src/luaotfload-configuration.lua | 31 ++++++++++++++++++++++++++++---
1 file changed, 28 insertions(+), 3 deletions(-)
diff --git a/src/luaotfload-configuration.lua b/src/luaotfload-configuration.lua
index 1fe30fe..4ac8c50 100644
--- a/src/luaotfload-configuration.lua
+++ b/src/luaotfload-configuration.lua
@@ -134,6 +134,33 @@ local registered_loaders = {
tl2014 = "tl2014",
}
+local pick_fontloader = function (s)
+ local ldr = registered_loaders[s]
+ if ldr ~= nil and type (ldr) == "string" then
+ logreport ("log", 2, "conf", "Using predefined fontloader \"%s\".", ldr)
+ return ldr
+ end
+ local idx = stringfind (s, ":")
+ if idx and idx > 2 then
+ if stringsub (s, 1, idx - 1) == "context" then
+ local pth = stringsub (s, idx + 1)
+ pth = stringstrip (pth)
+ logreport ("log", 2, "conf", "Context base path specified at \"%s\".", pth)
+ if lfsisdir (pth) then
+ logreport ("log", 5, "conf", "Context base path exists at \"%s\".", pth)
+ return { "context", pth }
+ end
+ pth = kpseexpand_path (pth)
+ if lfsisdir (pth) then
+ logreport ("log", 5, "conf", "Context base path exists at \"%s\".", pth)
+ return { "context", pth }
+ end
+ logreport ("both", 0, "conf", "Context base path not found at \"%s\".", pth)
+ end
+ end
+ return nil
+end
+
--[[doc--
The ``post_linebreak_filter`` has been made the default callback for
@@ -468,10 +495,8 @@ local option_spec = {
in_t = string_t,
out_t = string_t,
transform = function (id)
- local ldr = registered_loaders[id]
+ local ldr = pick_fontloader (id)
if ldr ~= nil then
- logreport ("log", 2, "conf",
- "Using predefined fontloader \"%s\".", ldr)
return ldr
end
logreport ("log", 0, "conf",
--
cgit v1.2.3
From d8f160fc0518155a9ae995dfb16fc0d29937aa7c Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Tue, 17 Nov 2015 22:29:41 +0100
Subject: [conf] correctly set default fontloader
---
src/luaotfload-configuration.lua | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/luaotfload-configuration.lua b/src/luaotfload-configuration.lua
index 4ac8c50..0ce9467 100644
--- a/src/luaotfload-configuration.lua
+++ b/src/luaotfload-configuration.lua
@@ -198,7 +198,7 @@ local default_config = {
definer = "patch",
log_level = 0,
color_callback = "post_linebreak_filter",
- live = true,
+ fontloader = "default",
},
misc = {
bisect = false,
--
cgit v1.2.3
From 6e2184e0226de1e76e7195493b781b99f56eb879 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Tue, 17 Nov 2015 22:33:04 +0100
Subject: [conf] return path instead of pair to prevent type-mismatch
The (fontloader, path) return value cannot pass the post-config
validation because the value of ``run.fontloader`` is of type string.
Since the path is always checked during configuration we can just
forward it as-is and attempt a path load later on.
---
src/luaotfload-configuration.lua | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/luaotfload-configuration.lua b/src/luaotfload-configuration.lua
index 0ce9467..efed573 100644
--- a/src/luaotfload-configuration.lua
+++ b/src/luaotfload-configuration.lua
@@ -148,12 +148,12 @@ local pick_fontloader = function (s)
logreport ("log", 2, "conf", "Context base path specified at \"%s\".", pth)
if lfsisdir (pth) then
logreport ("log", 5, "conf", "Context base path exists at \"%s\".", pth)
- return { "context", pth }
+ return pth
end
pth = kpseexpand_path (pth)
if lfsisdir (pth) then
logreport ("log", 5, "conf", "Context base path exists at \"%s\".", pth)
- return { "context", pth }
+ return pth
end
logreport ("both", 0, "conf", "Context base path not found at \"%s\".", pth)
end
--
cgit v1.2.3
From ec1984766b941087425acca1b4d4fa8201c86639 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Tue, 17 Nov 2015 22:51:30 +0100
Subject: [init] rework fontloader choices
---
src/luaotfload-init.lua | 35 +++++++++++++++++++++++++++++------
1 file changed, 29 insertions(+), 6 deletions(-)
diff --git a/src/luaotfload-init.lua b/src/luaotfload-init.lua
index ca5d9ec..2676ec7 100644
--- a/src/luaotfload-init.lua
+++ b/src/luaotfload-init.lua
@@ -8,6 +8,7 @@
--
local setmetatable = setmetatable
+local kpselookup = kpse.lookup
--[[doc--
@@ -218,6 +219,7 @@ local init_main = function ()
local fontloader = config.luaotfload and config.luaotfload.run.fontloader
or "reference"
+ fontloader = tostring (fontloader)
if fontloader == "unpackaged" then
logreport ("both", 4, "init",
@@ -302,13 +304,34 @@ local init_main = function ()
load_context_module "luatex-fonts-ext"
load_context_module "luatex-fonts-cbk"
- elseif fontloader then
- fontloader = tostring (fontloader)
- --- “reference”, “default”
- logreport ("both", 4, "init",
- "Attempting to load fontloader “%s”.",
+ elseif lfs.isdir (fontloader) then
+ logreport ("both", 2, "init",
+ "Attempting to load Context files under prefix “%s”.",
+ fontloader)
+ TODO()
+
+ elseif lfs.isfile (fontloader) then
+ logreport ("both", 2, "init",
+ "Attempting to load fontloader from absolute path “%s”.",
+ fontloader)
+ local _void = require (fontloader)
+
+ elseif kpselookup (fontloader) then
+ local pth = kpselookup (fontloader)
+ logreport ("both", 2, "init",
+ "Attempting to load fontloader “%s” from kpse-resolved path “%s”.",
+ fontloader, path)
+ local _void = require (path)
+
+ else --- “reference”, “default”
+ logreport ("log", 6, "init",
+ "No match for fontloader spec “%s”.",
+ fontloader)
+ fontloader = luaotfload.fontloader_package
+ logreport ("log", 4, "init",
+ "Using predefined fontloader “%s”.",
fontloader)
- load_fontloader_module (luaotfload.fontloader_package)
+ load_fontloader_module (fontloader)
end
---load_fontloader_module "font-odv.lua" --- <= Devanagari support from Context
--
cgit v1.2.3
From 2bcb46cfec8b8d988e12f44d6297f4fb5f9e879b Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Tue, 17 Nov 2015 23:08:58 +0100
Subject: [init] unify both Context load branches
---
src/luaotfload-init.lua | 103 +++++++++++++++++++++++++++++-------------------
1 file changed, 63 insertions(+), 40 deletions(-)
diff --git a/src/luaotfload-init.lua b/src/luaotfload-init.lua
index 2676ec7..a42801f 100644
--- a/src/luaotfload-init.lua
+++ b/src/luaotfload-init.lua
@@ -182,6 +182,65 @@ local pop_namespaces = function (normalglobal,
end
end
+local context_modules = {
+
+ --- Since 2.6 those are directly provided by the Lualibs package.
+ { false, "l-lua" },
+ { false, "l-lpeg" },
+ { false, "l-function" },
+ { false, "l-string" },
+ { false, "l-table" },
+ { false, "l-io" },
+ { false, "l-file" },
+ { false, "l-boolean" },
+ { false, "l-math" },
+ { false, "util-str" },
+
+ --- These constitute the fontloader proper.
+ { true, "luatex-basics-gen" },
+ { true, "data-con" },
+ { true, "luatex-basics-nod" },
+ { true, "font-ini" },
+ { true, "font-con" },
+ { true, "luatex-fonts-enc" },
+ { true, "font-cid" },
+ { true, "font-map" },
+ { true, "luatex-fonts-syn" },
+ { true, "luatex-fonts-tfm" },
+ { true, "font-oti" },
+ { true, "font-otf" },
+ { true, "font-otb" },
+ { true, "luatex-fonts-inj" }, --> since 2014-01-07, replaces node-inj.lua
+ { true, "luatex-fonts-ota" },
+ { true, "luatex-fonts-otn" }, --> since 2014-01-07, replaces font-otn.lua
+ { true, "font-otp" }, --> since 2013-04-23
+ { true, "luatex-fonts-lua" },
+ { true, "font-def" },
+ { true, "luatex-fonts-def" },
+ { true, "luatex-fonts-ext" },
+ { true, "luatex-fonts-cbk" },
+
+} --[[context_modules]]
+
+local load_context_modules = function (pth)
+
+ local load_context_module = luaotfload.loaders.context
+ local ignore_module = luaotfload.loaders.ignore
+
+ logreport ("both", 2, "init",
+ "Loading fontloader components from context.")
+ local n = #context_modules
+ for i = 1, n do
+ local state, spec = unpack (context_modules [i])
+ if state == false then
+ ignore_module (spec)
+ elseif state == true then
+ load_context_module (spec)
+ end
+ end
+
+end
+
local init_adapt = function ()
local context_environment = { }
@@ -204,7 +263,6 @@ end --- [init_adapt]
local init_main = function ()
local load_fontloader_module = luaotfload.loaders.fontloader
- local load_context_module = luaotfload.loaders.context
local ignore_module = luaotfload.loaders.ignore
--[[doc--
@@ -265,50 +323,15 @@ local init_main = function ()
load_fontloader_module "fonts-cbk"
elseif fontloader == "context" then
- logreport ("both", 4, "init",
- "Loading fontloader components from context.")
- logreport ("both", 0, "init", "NOT IMPLEMENTED YET.")
- --- Since 2.6 those are directly provided by the Lualibs package.
- ignore_module "l-lua"
- ignore_module "l-lpeg"
- ignore_module "l-function"
- ignore_module "l-string"
- ignore_module "l-table"
- ignore_module "l-io"
- ignore_module "l-file"
- ignore_module "l-boolean"
- ignore_module "l-math"
- ignore_module "util-str"
-
- --- These constitute the fontloader proper.
- load_context_module "luatex-basics-gen"
- load_context_module "data-con"
- load_context_module "luatex-basics-nod"
- load_context_module "font-ini"
- load_context_module "font-con"
- load_context_module "luatex-fonts-enc"
- load_context_module "font-cid"
- load_context_module "font-map"
- load_context_module "luatex-fonts-syn"
- load_context_module "luatex-fonts-tfm"
- load_context_module "font-oti"
- load_context_module "font-otf"
- load_context_module "font-otb"
- load_context_module "luatex-fonts-inj" --> since 2014-01-07, replaces node-inj.lua
- load_context_module "luatex-fonts-ota"
- load_context_module "luatex-fonts-otn" --> since 2014-01-07, replaces font-otn.lua
- load_context_module "font-otp" --> since 2013-04-23
- load_context_module "luatex-fonts-lua"
- load_context_module "font-def"
- load_context_module "luatex-fonts-def"
- load_context_module "luatex-fonts-ext"
- load_context_module "luatex-fonts-cbk"
+ logreport ("both", 2, "init",
+ "Attempting to load Context modules in lookup path.")
+ load_context_modules ()
elseif lfs.isdir (fontloader) then
logreport ("both", 2, "init",
"Attempting to load Context files under prefix “%s”.",
fontloader)
- TODO()
+ load_context_modules (fontloader)
elseif lfs.isfile (fontloader) then
logreport ("both", 2, "init",
--
cgit v1.2.3
From 0bfd03b4fcdf1cbf3f1fb8e8afa7a2c4d917715a Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Tue, 17 Nov 2015 23:56:44 +0100
Subject: [main,init] implement path dependent loading of context modules
---
src/luaotfload-init.lua | 61 ++++++++++++++++++++++++++++---------------------
src/luaotfload-main.lua | 39 ++++++++++++++++++++++++++-----
2 files changed, 68 insertions(+), 32 deletions(-)
diff --git a/src/luaotfload-init.lua b/src/luaotfload-init.lua
index a42801f..2755f78 100644
--- a/src/luaotfload-init.lua
+++ b/src/luaotfload-init.lua
@@ -182,6 +182,10 @@ local pop_namespaces = function (normalglobal,
end
end
+--- below paths are relative to the texmf-context
+local ltx = "tex/generic/context/luatex"
+local ctx = "tex/context/base"
+
local context_modules = {
--- Since 2.6 those are directly provided by the Lualibs package.
@@ -197,28 +201,28 @@ local context_modules = {
{ false, "util-str" },
--- These constitute the fontloader proper.
- { true, "luatex-basics-gen" },
- { true, "data-con" },
- { true, "luatex-basics-nod" },
- { true, "font-ini" },
- { true, "font-con" },
- { true, "luatex-fonts-enc" },
- { true, "font-cid" },
- { true, "font-map" },
- { true, "luatex-fonts-syn" },
- { true, "luatex-fonts-tfm" },
- { true, "font-oti" },
- { true, "font-otf" },
- { true, "font-otb" },
- { true, "luatex-fonts-inj" }, --> since 2014-01-07, replaces node-inj.lua
- { true, "luatex-fonts-ota" },
- { true, "luatex-fonts-otn" }, --> since 2014-01-07, replaces font-otn.lua
- { true, "font-otp" }, --> since 2013-04-23
- { true, "luatex-fonts-lua" },
- { true, "font-def" },
- { true, "luatex-fonts-def" },
- { true, "luatex-fonts-ext" },
- { true, "luatex-fonts-cbk" },
+ { ltx, "luatex-basics-gen" },
+ { ctx, "data-con" },
+ { ltx, "luatex-basics-nod" },
+ { ctx, "font-ini" },
+ { ctx, "font-con" },
+ { ltx, "luatex-fonts-enc" },
+ { ctx, "font-cid" },
+ { ctx, "font-map" },
+ { ltx, "luatex-fonts-syn" },
+ { ltx, "luatex-fonts-tfm" },
+ { ctx, "font-oti" },
+ { ctx, "font-otf" },
+ { ctx, "font-otb" },
+ { ltx, "luatex-fonts-inj" }, --> since 2014-01-07, replaces node-inj.lua
+ { ltx, "luatex-fonts-ota" },
+ { ltx, "luatex-fonts-otn" }, --> since 2014-01-07, replaces font-otn.lua
+ { ctx, "font-otp" }, --> since 2013-04-23
+ { ltx, "luatex-fonts-lua" },
+ { ctx, "font-def" },
+ { ltx, "luatex-fonts-def" },
+ { ltx, "luatex-fonts-ext" },
+ { ltx, "luatex-fonts-cbk" },
} --[[context_modules]]
@@ -231,11 +235,16 @@ local load_context_modules = function (pth)
"Loading fontloader components from context.")
local n = #context_modules
for i = 1, n do
- local state, spec = unpack (context_modules [i])
- if state == false then
+ local sub, spec = unpack (context_modules [i])
+ if sub == false then
ignore_module (spec)
- elseif state == true then
- load_context_module (spec)
+ elseif type (sub) == "string" then
+ load_context_module (spec, file.join (pth, sub))
+ else
+ logreport ("both", 0, "init",
+ "Internal error, please report. \z
+ This is not your fault.")
+ os.exit (-1)
end
end
diff --git a/src/luaotfload-main.lua b/src/luaotfload-main.lua
index 0ed57da..62765e4 100644
--- a/src/luaotfload-main.lua
+++ b/src/luaotfload-main.lua
@@ -98,7 +98,8 @@ end
--doc]]--
local make_loader_name = function (prefix, name)
- local msg = luaotfload.log and luaotfload.log.report or print
+ local msg = luaotfload.log and luaotfload.log.report
+ or function (...) texio.write_nl ("log", ...) end
if not name then
msg ("both", 0, "load",
"Fatal error: make_loader_name (“%s”, “%s”).",
@@ -143,17 +144,43 @@ end
--doc]]--
local dummy_loader = function (name)
- luaotfload.log.report("log", 3, "load", "Skipping module “%s” on purpose.", name)
+ luaotfload.log.report ("log", 3, "load",
+ "Skipping module “%s” on purpose.",
+ name)
end
-local context_loader = function (name)
- luaotfload.log.report("log", 3, "load", "Loading module “%s” from Context.", name)
+local context_loader = function (name, path)
+ luaotfload.log.report ("log", 3, "load",
+ "Loading module “%s” from Context.",
+ name)
local t_0 = osgettimeofday ()
local modname = make_loader_name (false, name)
- local data = require (modname)
+ local modpath = modname
+ if path then
+ if lfs.isdir (path) then
+ luaotfload.log.report ("log", 3, "load",
+ "Prepending path “%s”.",
+ path)
+ modpath = file.join (path, modname)
+ else
+ luaotfload.log.report ("both", 0, "load",
+ "Non-existant path “%s” specified, ignoring.",
+ path)
+ end
+ end
+ local ret = require (modpath)
local t_end = osgettimeofday ()
timing_info.t_load [name] = t_end - t_0
- return data
+
+ if ret ~= true then
+ --- require () returns “true” upon success unless the loaded file
+ --- yields a non-zero exit code. This isn’t per se indicating that
+ --- something isn’t right, but against HH’s coding practices. We’ll
+ --- silently ignore this ever happening on lower log levels.
+ luaotfload.log.report ("log", 4, "load",
+ "Module “%s” returned “%s”.", ret)
+ end
+ return ret
end
local install_loaders = function ()
--
cgit v1.2.3
From 17b8126f260a4f80a041ab179ceb68abf425c359 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Wed, 18 Nov 2015 07:47:47 +0100
Subject: [init] fix pathless Context module loading
---
src/luaotfload-init.lua | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/src/luaotfload-init.lua b/src/luaotfload-init.lua
index 2755f78..f1d1a8e 100644
--- a/src/luaotfload-init.lua
+++ b/src/luaotfload-init.lua
@@ -228,8 +228,8 @@ local context_modules = {
local load_context_modules = function (pth)
- local load_context_module = luaotfload.loaders.context
- local ignore_module = luaotfload.loaders.ignore
+ local load_module = luaotfload.loaders.context
+ local ignore_module = luaotfload.loaders.ignore
logreport ("both", 2, "init",
"Loading fontloader components from context.")
@@ -239,7 +239,11 @@ local load_context_modules = function (pth)
if sub == false then
ignore_module (spec)
elseif type (sub) == "string" then
- load_context_module (spec, file.join (pth, sub))
+ if pth then
+ load_module (spec, file.join (pth, sub))
+ else
+ load_module (spec)
+ end
else
logreport ("both", 0, "init",
"Internal error, please report. \z
--
cgit v1.2.3
From 85bc85c1f116f759c59ef06f27bb37c0d2bb80f6 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Wed, 18 Nov 2015 07:52:24 +0100
Subject: [init] handle case for reference loader first
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Since it’s the trivial case, expected in 99 % of runs.
---
src/luaotfload-init.lua | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/src/luaotfload-init.lua b/src/luaotfload-init.lua
index f1d1a8e..5b21d70 100644
--- a/src/luaotfload-init.lua
+++ b/src/luaotfload-init.lua
@@ -292,7 +292,11 @@ local init_main = function ()
or "reference"
fontloader = tostring (fontloader)
- if fontloader == "unpackaged" then
+ if fontloader == "reference" or fontloader == "default" then
+ logreport ("log", 4, "init", "Using reference fontloader.")
+ load_fontloader_module (luaotfload.fontloader_package)
+
+ elseif fontloader == "unpackaged" then
logreport ("both", 4, "init",
"Loading fontloader components individually.")
--- The loading sequence is known to change, so this might have to be
@@ -359,7 +363,7 @@ local init_main = function ()
fontloader, path)
local _void = require (path)
- else --- “reference”, “default”
+ else
logreport ("log", 6, "init",
"No match for fontloader spec “%s”.",
fontloader)
@@ -372,6 +376,9 @@ local init_main = function ()
---load_fontloader_module "font-odv.lua" --- <= Devanagari support from Context
+ logreport ("both", 0, "init",
+ "Context OpenType loader version “%s”",
+ fonts.handlers.otf.version)
end --- [init_main]
local init_cleanup = function (store)
--
cgit v1.2.3
From 671f654e671cc2b255b21b937bbfd7f63cf43c22 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Wed, 18 Nov 2015 08:04:17 +0100
Subject: [init] treat known fontloaders as special case
Defaulting too soon will prevent loading other loaders like the TL 2014
one we ship for backwards compatibility.
---
src/luaotfload-init.lua | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/src/luaotfload-init.lua b/src/luaotfload-init.lua
index 5b21d70..0f7464a 100644
--- a/src/luaotfload-init.lua
+++ b/src/luaotfload-init.lua
@@ -363,13 +363,19 @@ local init_main = function ()
fontloader, path)
local _void = require (path)
+ elseif fontloader then
+ logreport ("log", 4, "init",
+ "Using predefined fontloader “%s”.",
+ fontloader)
+ load_fontloader_module (fontloader)
+
else
- logreport ("log", 6, "init",
- "No match for fontloader spec “%s”.",
+ logreport ("log", 4, "init",
+ "No match for requested fontloader “%s”.",
fontloader)
fontloader = luaotfload.fontloader_package
logreport ("log", 4, "init",
- "Using predefined fontloader “%s”.",
+ "Defaulting to predefined fontloader “%s”.",
fontloader)
load_fontloader_module (fontloader)
end
--
cgit v1.2.3
From 66715ea0131082efdca3267d3ab663153b0372e9 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Thu, 19 Nov 2015 00:00:43 +0100
Subject: [man] document fontloader switch
---
doc/luaotfload.conf.rst | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/doc/luaotfload.conf.rst b/doc/luaotfload.conf.rst
index 2a339ce..12dd887 100644
--- a/doc/luaotfload.conf.rst
+++ b/doc/luaotfload.conf.rst
@@ -276,6 +276,8 @@ Section ``run``
+------------------+--------+------------------------------+
| resolver | s | ``"cached"`` |
+------------------+--------+------------------------------+
+| fontloader | s | ``"default"`` |
++------------------+--------+------------------------------+
The ``color-callback`` option determines the stage at which fonts that
defined with a ``color=xxyyzz`` feature will be colorized. By default
@@ -294,6 +296,29 @@ one that comes with the vanilla fontloader. Beware that this might
break tools like Fontspect that rely on the ``patch_font`` callback
provided by Luaotfload to perform important corrections on font data.
+The fontloader backend can be selected by setting the value of
+``fontloader``. Other than the default, which selects the packaged
+``reference`` loader as shipped with Luaotfload, a file name accessible
+by kpathsea can be specified. Alternatively, the individual files that
+constitute the fontloader can be loaded directly. While less efficient,
+this greatly aids debugging since error messages will reference the
+actual line numbers of the source files and explanatory comments are
+not stripped. Currently, three distinct loading strategies are
+available: ``unpackaged`` will load the batch that is part of
+Luaotfload. These contain the identical source code that the reference
+fontloader has been compiled from. Another option, ``context`` will
+attempt to load the same files by their names in the Context format
+from the search path. Consequently this option allows to use the
+version of Context that comes with the TeX distribution. Distros tend
+to prefer the stable version (“current” in Context jargon) of those
+files so certain bugs encountered in the more bleeding edge Luaotfload
+can be avoided this way. A third option is to use ``context`` with a
+colon to specify a directory prefix where the *TEXMF* is located that
+the files should be loaded from, e. g. ``context:~/context/tex/texmf-context``.
+This can be used when referencing another distribution like the Context
+minimals that is installed under a different path not indexed by
+kpathsea.
+
The value of ``log-level`` sets the default verbosity of messages
printed by Luaotfload. Only messages defined with a verbosity of less
than or equal to the supplied value will be output on the terminal.
--
cgit v1.2.3
From b3565971e4ea5525da149268b1cd372b8d77f42c Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Thu, 19 Nov 2015 08:11:22 +0100
Subject: [import] allow passing search location on command line
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
And btw don’t hard code my own homedir =)
---
scripts/mkimport | 35 +++++++++++++++++++++++++++--------
1 file changed, 27 insertions(+), 8 deletions(-)
diff --git a/scripts/mkimport b/scripts/mkimport
index e8b83c0..9ea224a 100755
--- a/scripts/mkimport
+++ b/scripts/mkimport
@@ -51,7 +51,7 @@ local tableconcat = table.concat
-- config
-------------------------------------------------------------------------------
-local context_root = "/home/phg/context/tex/texmf-context"
+local parms = { }
local our_prefix = "fontloader"
local luatex_fonts_prefix = "luatex"
local fontloader_subdir = "src/fontloader"
@@ -69,7 +69,6 @@ local subdirs = {
local searchdirs = {
--- order is important!
fontloader_subdir,
- context_root
}
local prefixes = {
@@ -259,7 +258,7 @@ end
local derive_category_path = function (cat)
local subpath = origin_paths[cat] or die ("category " .. cat .. " unknown")
- local location = file.join (context_root, subpath)
+ local location = file.join (parms.context_root, subpath)
if not lfsisdir (location) then
die ("invalid base path defined for category "
.. cat .. " at " .. location)
@@ -482,7 +481,8 @@ end --[[ [local import_file = function (name, kind)] ]]
local import = function (arg)
if #arg > 1 then
- local name = arg[2] or die ("invalid filename " .. tostring (arg[2]))
+ local tgt = parms.target
+ local name = tgt or die ("invalid filename " .. tostring (tgt))
local stat = import_file (name)
if stat == import_failed then
die ("failed to import file " .. name)
@@ -526,10 +526,10 @@ local search_paths = function (target)
end
- local found = find_in_path (context_root, origin_paths.context, target)
+ local found = find_in_path (parms.context_root, origin_paths.context, target)
if found then return found end
- local found = find_in_path (context_root, origin_paths.fontloader, target)
+ local found = find_in_path (parms.context_root, origin_paths.fontloader, target)
if found then return found end
return false
end
@@ -656,7 +656,7 @@ local describe = function (target, location)
end
local tell = function (arg)
- local target = arg[2]
+ local target = parms.target
if not target then die "no filename given" end
local location = search (target)
@@ -846,12 +846,31 @@ local check_job = function (j)
return job_kind[j] or die ("invalid job type “%s”.", j)
end
+local parse_argv = function (argv)
+ local job
+ local tgt
+ local pth
+
+ local argc = #arg
+ if argc < 1 or argc > 3 then return "help" end
+ job = arg[1] or "help"
+ if argc > 1 then
+ tgt = arg[2]
+ if argc == 3 then pth = arg[3] end
+ end
+ if not pth then pth = "~/context/tex/texmf-context" end
+ parms.context_root = kpse.expand_path (pth)
+ parms.target = tgt
+ searchdirs [#searchdirs + 1] = pth
+ return job
+end
+
-------------------------------------------------------------------------------
-- entry point
-------------------------------------------------------------------------------
local main = function ()
- local job = arg[1] or "help"
+ local job = parse_argv (arg)
local runner = check_job (job)
return runner(arg)
end
--
cgit v1.2.3
From f385ec0f5919feed2839f6146a6ebbbce5926354 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Fri, 20 Nov 2015 00:01:41 +0100
Subject: [chars] allow passing location of char-def.lua on command line
---
scripts/mkcharacters | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/scripts/mkcharacters b/scripts/mkcharacters
index 9e9fd1a..59582f2 100755
--- a/scripts/mkcharacters
+++ b/scripts/mkcharacters
@@ -13,7 +13,7 @@
-- config
-----------------------------------------------------------------------
local charfile = "./build/luaotfload-characters.lua"
-local chardef = "/home/phg/base/char-def.lua"
+local chardef = arg[1]
--- for every code point char-def.lua provides a set of fields. they
--- are:
@@ -63,6 +63,11 @@ for _, lib in next, { "lualibs-lua.lua",
require(found)
end
+if not chardef then
+ chardef = kpse.expand_path("~/context/tex/texmf-context/tex/context/base/")
+ .. "/char-def.lua"
+end
+
if not (chardef and lfs.isfile(chardef)) then
--- we could grab the file from contextgarden but as Context is part
--- of TL it’s not worth bothering
@@ -70,6 +75,9 @@ if not (chardef and lfs.isfile(chardef)) then
"Could not find ConTeXt.")
end
+io.write(string.format("extracting data from char-def.lua at %s\n",
+ chardef))
+
-----------------------------------------------------------------------
-- functionality
-----------------------------------------------------------------------
--
cgit v1.2.3
From 3a12cad2b229d501ef6835d27797a1a18fb981ef Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Fri, 20 Nov 2015 00:23:45 +0100
Subject: [conf] plug in the correct resolvers (fallout from db reorganization)
---
src/luaotfload-configuration.lua | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/luaotfload-configuration.lua b/src/luaotfload-configuration.lua
index efed573..57311dc 100644
--- a/src/luaotfload-configuration.lua
+++ b/src/luaotfload-configuration.lua
@@ -308,9 +308,9 @@ local set_name_resolver = function ()
--- replace the resolver from luatex-fonts
if config.luaotfload.db.resolver == "cached" then
logreport ("both", 2, "cache", "Caching of name: lookups active.")
- names.resolvespec = names.resolve_cached
+ names.resolvespec = fonts.names.lookup_font_name_cached
else
- names.resolvespec = names.resolve_name
+ names.resolvespec = fonts.names.lookup_font_name
end
end
return true
--
cgit v1.2.3
From cf6c8c94cc88db6564ccea266b3c6d8f7a5bb1a1 Mon Sep 17 00:00:00 2001
From: Philipp Gesang
Date: Fri, 20 Nov 2015 00:43:05 +0100
Subject: [tests] adapt lookup test runner (fallout from db reorganization)
---
scripts/mktests | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 59 insertions(+), 6 deletions(-)
diff --git a/scripts/mktests b/scripts/mktests
index 757e360..ad8c4f5 100755
--- a/scripts/mktests
+++ b/scripts/mktests
@@ -18,14 +18,68 @@ local tests = { }
local lpeg = require "lpeg"
local lpegmatch = lpeg.match
+config = { luaotfload = { } }
+luatexbase = { }
+
kpse.set_program_name "luatex"
require "lualibs"
require "luaotfload-basics-gen.lua"
require "luaotfload-log.lua"
-require "luaotfload-parsers"
-require "luaotfload-configuration"
-require "luaotfload-database"
+
+fonts = { names = { } } -- for db; normally provided by the fontloaders
+
+local require_init = { }
+
+local loadmodule = function (name)
+ local v = require ("luaotfload-" .. name)
+ if v then
+ local mod = { }
+ local tv = type (v)
+ if tv == "table" then
+ mod.name = name
+ mod.init = v.init
+ require_init [#require_init + 1] = mod
+ elseif tv == "function" then
+ mod.name = name
+ mod.init = v
+ require_init [#require_init + 1] = mod
+ end
+ end
+end
+
+require "alt_getopt"
+
+loadmodule "log.lua" --- this populates the luaotfload.log.* namespace
+loadmodule "parsers" --- fonts.conf, configuration, and request syntax
+loadmodule "configuration" --- configuration file handling
+loadmodule "database"
+loadmodule "resolvers" --- Font lookup
+
+do --- init_modules
+ --- NB we don’t command the logger at this point.
+ local todo = #require_init
+ local ret = true
+ for i = 1, todo do
+ local mod = require_init[i]
+ local name = mod.name
+ local init = mod.init
+ if type (init) ~= "function" then
+ error ("luaotfload broken; module "
+ .. name .. " missing initializers!")
+ end
+ local v = mod.init ()
+ if v == true then
+ --- evaluated well
+ elseif type (v) == "table" then
+ luaotfload[name] = v
+ else
+ error ("luaotfload broken; initialization of module "
+ .. name .. " returned " .. tostring (v) .. ".")
+ return false
+ end
+ end
+end
local names = fonts.names
@@ -234,7 +288,6 @@ local default_spec = {
local resolve_font_name = function ()
local failed, total = 0, 0
- local resolve_name = names.resolve_name
for nset = 1, #font_name_tests do
local set = font_name_tests[nset]
@@ -246,7 +299,7 @@ local resolve_font_name = function ()
local input_spec = table.copy (default_spec)
input_spec.name = input
input_spec.specification = input_spec.lookup .. ":" .. input
- local result = resolve_name (input_spec) == output
+ local result = fonts.names.lookup_font_name (input_spec) == output
total = total + 1
if not result then
failed = failed + 1
@@ -260,7 +313,7 @@ local resolve_font_name = function ()
.. ":" .. input_spec.name
input_spec.optsize = input_spec.optsize or default_spec.optsize
input_spec.style = translate_style [input_spec.style]
- local result = resolve_name (input_spec) == output
+ local result = fonts.names.lookup_font_name (input_spec) == output
total = total + 1
if not result then
failed = failed + 1
--
cgit v1.2.3