Фон Я был занят книгой о мировых письменностях и языках в течение нескольких лет. Она охватываетвсеперечисленные скрипты в юникоде, а также около десятка, для которых пока нет стандарта юникода и я использую изображения вместо шрифтов.
С шрифтами Noto, unicode LuaLaTeX и l3 maturing я смог напечатать разумный диапазон для всех сценариев, как это было необходимо в написании. За исключением восточноазиатских сценариев, для которых у меня есть только несколько страниц на сценарий. Я использую в качестве основного шрифта Brill и добавил резервные шрифты, чтобы охватить остальные сценарии. Книга на данный момент составляет около 350 страниц, и я ожидаю, что она достигнет окончательного размера в 600 страниц. Чтобы охватить точки unicode, шрифты должны предоставить +-150 000 глифов. Не все кодовые точки используются в книге, как я упоминал ранее, по моим оценкам, мне нужно только около половины этого. Очевидно и понятно, что скорость компиляции является проблемой, поэтому я пытаюсь понять алгоритм, используемый luaotfload-fallback.lua, чтобы попытаться увидеть, смогу ли я улучшить время обработки. Я ищу стратегии для оптимизации времени компиляции не только для моего документа, но и в целом.
Я выявил узкие места в основном в трех областях: a) шрифты b) изображения c) ведение журнала (запись на диск в целом). Изображения Я буду использовать препроцессор и оптимизировать их все, а также создавать pdf-файлы. Я буду использовать Golang для препроцессора, который также может делать разметку, если это необходимо. Идеи для шрифтов и ведения журнала см. ниже.
У меня есть эта (сумасшедшая) идея, что информация о глифе, необходимая узлам во время обработки, должна быть получена через локальный сервер, чтобы некоторые задачи можно было вынести на внешний сервер и запускать с параллелизмом. Я думаю о некоей форме приоритетной очереди, чтобы данные для часто используемых кодовых точек могли обслуживаться быстро, а любые неиспользуемые кодовые точки при втором запуске извлекались из кэша. Опять же, здесь я буду использовать Golang и sqlite3, поскольку все локально. На данный момент у меня есть таблица Lua, которая сопоставляет точки Unicode со шрифтами на основе файла конфигурации.
Все журналы также должны быть отправлены на сервер, а не записаны на диск. Также может быть сделано для aux-файлов.
Генерация pdf также занимает время, но я не решил на данный момент, можно ли ее оптимизировать. Текущая скорость компиляции составляет около 1,3 секунды на страницу + начальная 30-40 секунд.
Вопрос Может ли кто-нибудь объяснить мне алгоритмические шаги в luaotfload-fallback.lua? Когда и как это используется LuaTeX при построении документа? В какой момент нужна информация о глифе? Приветствуются любые идеи. Спасибо, что дочитали до этого места.
решение1
Это вообще не отвечает на вопрос, поставленный в заголовке, но я думаю, что это решает проблемы, изложенные в тексте вопроса (надеюсь).
Косвенный ответ
Вот решение, которое загружает 231 уникальный шрифт и печатает 83 020 уникальных символов (103 страницы) за 7,505 секунд (в среднем) с использованием LuaLaTeX.
Сначала запустите этот скрипт, чтобы загрузить все шрифты:
#!/bin/sh
set -eu
mkdir fonts
cd fonts
git clone --depth 1 --no-checkout --filter=blob:none \
https://github.com/notofonts/notofonts.github.io.git
cd notofonts.github.io
git sparse-checkout set --no-cone '!/*' '/fonts/**/hinted/ttf/*-Regular.ttf'
git checkout main
cd ..
git clone --depth 1 --no-checkout --filter=blob:none \
https://github.com/notofonts/noto-cjk.git
cd noto-cjk
git sparse-checkout set --no-cone '!/*' '/Serif/SubsetOTF/**/*-Regular.otf'
git checkout main
cd ..
wget -O unifont-Regular.otf \
https://unifoundry.com/pub/unifont/unifont-15.1.04/font-builds/unifont-15.1.04.otf
wget -O unifont_upper-Regular.otf \
https://unifoundry.com/pub/unifont/unifont-15.1.04/font-builds/unifont_upper-15.1.04.otf
wget -O NotoEmoji-Regular.ttf \
"$(curl 'https://fonts.googleapis.com/css2?family=Noto+Emoji' | grep -o 'https.*ttf')"
cd ..
Затем поместите следующее all-characters.lua
:
-- Save some globals for speed
local ipairs = ipairs
local max = math.max
local new_node = node.new
local node_write = node.write
local pairs = pairs
-- Define some constants
local GLUE_ID = node.id("glue")
local GLYPH_ID = node.id("glyph")
local SIZE = tex.sp("10pt")
-- Get all the fonts
local fontpaths = dir.glob("**-Regular.*", "./fonts")
-- Sort the fonts such that the "preferred" fonts are last
table.sort(fontpaths, function(a, b)
local a = file.nameonly(a):match("(.+)-Regular")
local b = file.nameonly(b):match("(.+)-Regular")
if a:match("Serif") and not b:match("Serif") then
return false
end
if b:match("Serif") and not a:match("Serif") then
return true
end
if a:match("unifont") and not b:match("unifont") then
return true
end
if b:match("unifont") and not a:match("unifont") then
return false
end
if #a == #b then
return a > b
end
return #a > #b
end)
-- Create a mapping from codepoint to font id
local by_character = {}
local virtual_fonts = {}
for _, filename in ipairs(fontpaths) do
local fontdata = fonts.definers.read {
lookup = "file",
name = filename,
size = SIZE,
features = {},
}
local id = font.define(fontdata)
fonts.definers.register(fontdata, id)
virtual_fonts[#virtual_fonts + 1] = { id = id }
for codepoint, char in pairs(fontdata.characters) do
if char.unicode == codepoint then
by_character[codepoint] = {
width = char.width,
height = char.height,
depth = char.depth,
font = id,
commands = {
{ "slot", #virtual_fonts, codepoint }
},
}
end
end
end
local function print_all_chars()
local count = 0
tex.forcehmode()
for codepoint, data in table.sortedpairs(by_character) do
local glyph = new_node(GLYPH_ID)
glyph.font = data.font
glyph.char = codepoint
local space = new_node(GLUE_ID)
space.width = max(2 * SIZE - glyph.width, 0)
glyph.next = space
node_write(glyph)
count = count + 1
end
tex.sprint("\\par Characters: " .. count)
tex.sprint("\\par Fonts: " .. #virtual_fonts)
end
-- Make the virtual font
local id = font.define {
name = "all-characters",
parameters = {},
characters = by_character,
properties = {},
type = "virtual",
fonts = virtual_fonts,
}
local new_command
if ltx then
new_command = function(name, func)
local index = luatexbase.new_luafunction(name)
lua.get_functions_table()[index] = func
token.set_lua(name, index, "protected")
end
elseif context then
new_command = function(name, func)
interfaces.implement {
name = name,
actions = func,
public = true,
}
end
end
new_command("printallchars", print_all_chars)
new_command("allcharactersfont", function() font.current(id) end)
Затем вы можете распечатать все символы, используя следующий документ:
\documentclass{article}
\ExplSyntaxOn
\lua_load_module:n { all-characters }
\ExplSyntaxOn
\begin{document}
\printallchars
\end{document}
ConTeXt на 50% быстрее — в среднем 4,849 секунды:
\ctxloadluafile{all-characters}
\starttext
\printallchars
\stoptext
Что еще более полезно, это также определяет виртуальный шрифт \allcharactersfont
, содержащий символы из всех загруженных шрифтов:
\documentclass{article}
\pagestyle{empty}
\ExplSyntaxOn
\lua_load_module:n { all-characters }
\ExplSyntaxOn
\begin{document}
{\allcharactersfont
A Ξ Ж س
क ௵ ෴ ფ
ጄ ᑠ ᘟ Ⅶ
∰ ⡿ だ 㬯
䷥