¿Qué algoritmo utiliza LuaLaTeX para las fuentes alternativas?

¿Qué algoritmo utiliza LuaLaTeX para las fuentes alternativas?

Fondo He estado ocupado con un libro sobre las escrituras y los idiomas del mundo de forma intermitente durante un par de años. Cubretodolos scripts enumerados en Unicode, así como una docena aproximadamente, donde aún no existe un estándar Unicode y uso imágenes en lugar de fuentes.

Con las fuentes Noto, Unicode LuaLaTeX y l3 madurando, he podido imprimir un rango razonable para todos los scripts, según sea necesario en la redacción. Con la excepción de los guiones de Asia oriental, solo tengo unas pocas páginas por guión. Utilizo Brill como fuente principal y agregué fuentes alternativas para cubrir el resto de los scripts. El libro hasta ahora ronda las 350 páginas y anticipo que alcanzará un tamaño final de 600 páginas. Para cubrir los puntos Unicode, las fuentes deben proporcionar +-150.000 glifos. No todos los puntos de código se utilizan en el libro, como mencioné anteriormente, en mi opinión, solo necesito aproximadamente la mitad de eso. Obviamente y es comprensible, la velocidad de compilación es un problema, por lo que estoy tratando de comprender el algoritmo utilizado por luaotfload-fallback.lua para intentar ver si puedo mejorar el tiempo de procesamiento. Estoy buscando estrategias para optimizar los tiempos de compilación, no solo de mi documento, sino en general.

He identificado cuellos de botella principalmente en tres áreas: a) fuentes b) imágenes c) registro (escrituras en disco en general). Imágenes. Usaré un preprocesador y las optimizaré todas, además de producir archivos PDF. Usaré Golang para el preprocesador, que también puede marcar si es necesario. Ideas para fuentes y registros ver más abajo.

  1. Tengo esta (loca) idea de que la información de glifo requerida en los nodos durante el procesamiento se obtenga a través de un servidor local, por lo que algunas tareas se pueden externalizar y ejecutar con concurrencia. Estoy pensando en algún tipo de cola de prioridad, de modo que los datos de los puntos de código utilizados con frecuencia se puedan entregar rápidamente y los puntos de código no utilizados en una segunda ejecución se eliminen del caché. Nuevamente aquí usaré Golang y sqlite3 ya que todo es local. Tengo una tabla Lua en este momento, que asigna puntos Unicode a fuentes, en función de un archivo de configuración.

  2. Todos los registros también se enviarán a un servidor en lugar de escribirse en el disco. También se puede hacer para los archivos auxiliares.

  3. La generación del pdf también lleva tiempo, pero en este momento no estoy seguro de si se puede optimizar. La velocidad de compilación actual es de aproximadamente 1,3 segundos por página + una inicial de 30 a 40 segundos.

Pregunta ¿Alguien puede explicarme los pasos algorítmicos en luaotfload-fallback.lua? ¿Cuándo y cómo LuaTeX lo utiliza al crear un documento? ¿En qué momento se necesita la información del glifo? Cualquier idea es bienvenida. Gracias por leer hasta aquí.

Respuesta1

Esto no responde en absoluto a la pregunta en el título de la pregunta, pero creo que aborda los problemas presentados en el cuerpo de la pregunta (con suerte).

Respuesta indirecta

Aquí hay una solución que carga 231 fuentes únicas e imprime 83 020 caracteres únicos (103 páginas) en 7,505 segundos (en promedio) usando LuaLaTeX.

Primero, ejecuta este script para descargar todas las fuentes:

#!/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 ..

Luego, coloque lo siguiente en 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)

Luego, podrás imprimir todos los caracteres utilizando el siguiente documento:

\documentclass{article}

\ExplSyntaxOn
\lua_load_module:n { all-characters }
\ExplSyntaxOn

\begin{document}
    \printallchars
\end{document}

ConTeXt es un 50 % más rápido con una media de 4,849 segundos:

\ctxloadluafile{all-characters}

\starttext
    \printallchars
\stoptext

Lo que es más útil es que esto también define una fuente virtual \allcharactersfont que contiene caracteres de todas las fuentes cargadas:

\documentclass{article}
\pagestyle{empty}

\ExplSyntaxOn
\lua_load_module:n { all-characters }
\ExplSyntaxOn

\begin{document}
    {\allcharactersfont
        A Ξ Ж س
        क ௵ ෴ ფ
        ጄ ᑠ ᘟ Ⅶ
        ∰ ⡿ だ 㬯

información relacionada