summaryrefslogtreecommitdiff
path: root/macros/luatex/generic/luaotfload/luaotfload-dvi.lua
diff options
context:
space:
mode:
Diffstat (limited to 'macros/luatex/generic/luaotfload/luaotfload-dvi.lua')
-rw-r--r--macros/luatex/generic/luaotfload/luaotfload-dvi.lua131
1 files changed, 131 insertions, 0 deletions
diff --git a/macros/luatex/generic/luaotfload/luaotfload-dvi.lua b/macros/luatex/generic/luaotfload/luaotfload-dvi.lua
new file mode 100644
index 0000000000..b57934fdb6
--- /dev/null
+++ b/macros/luatex/generic/luaotfload/luaotfload-dvi.lua
@@ -0,0 +1,131 @@
+-------------------------------------------------------------------------------
+-- FILE: luaotfload-dvi.lua
+-- DESCRIPTION: part of luaotfload / DVI
+-------------------------------------------------------------------------------
+
+
+local ProvidesLuaModule = {
+ name = "luaotfload-dvi",
+ version = "3.15", --TAGVERSION
+ date = "2020-09-02", --TAGDATE
+ description = "luaotfload submodule / DVI",
+ license = "GPL v2.0",
+ author = "Marcel Krüger",
+ copyright = "Luaotfload Development Team",
+}
+
+if luatexbase and luatexbase.provides_module then
+ luatexbase.provides_module (ProvidesLuaModule)
+end
+
+local getfont = font.getfont
+local setfont = node.direct.setfont
+local getdisc = node.direct.getdisc
+local traverse_glyph = node.direct.traverse_glyph
+local traverse_id = node.direct.traverse_id
+local uses_font = node.direct.uses_font
+local define_font = font.define
+local disc_t = node.id'disc'
+
+-- DVI output support
+--
+-- When writing DVI files, we can't assume that the DVI reader has access to our
+-- font dictionaries, so we need an independent representation for our glyphs. The
+-- approach we chose in coordination with the dvisvgm author is to create a DVI font
+-- name which indicates the font filename and some essential backend parameters
+-- (especially otential extend, shrink, embolden, etc. factors) and then use GIDs in
+-- the page stream.
+--
+-- Normally we could easily implement this using virtual fonts, but because we are
+-- dealing with DVI output, LuaTeX is not evaluating virtual fonts by itself.
+-- So instead, we process the shaped output and replace all glyph nodes with glyph
+-- nodes from special fonts which have the characteristics expected brom the DVI reader.
+
+-- mapped_fonts maps fontids from the user to fontids used in the DVI file
+local mapped_fonts = setmetatable({}, {__index = function(t, fid)
+ local font = getfont(fid)
+ local mapped = font.backend_font or false
+ t[fid] = mapped
+ return mapped
+end})
+
+local function process(head, font)
+ local mapping = mapped_fonts[font]
+ if not mapping then return head end
+ local mapped_font = mapping.font
+ for n, c, f in traverse_glyph(head) do if f == font then
+ local mapped = mapping[c]
+ if mapped then setfont(n, mapped_font, mapped) end
+ end end
+ for n in traverse_id(disc_t, head) do if uses_font(n, font) then
+ local pre, post, rep = getdisc(n)
+ for n, c, f in traverse_glyph(pre) do if f == font then
+ local mapped = mapping[c]
+ if mapped then setfont(n, mapped_font, mapped) end
+ end end
+ for n, c, f in traverse_glyph(post) do if f == font then
+ local mapped = mapping[c]
+ if mapped then setfont(n, mapped_font, mapped) end
+ end end
+ for n, c, f in traverse_glyph(rep) do if f == font then
+ local mapped = mapping[c]
+ if mapped then setfont(n, mapped_font, mapped) end
+ end end
+ end end
+end
+local function manipulate(tfmdata, _, dvi_kind)
+ if dvi_kind ~= 'dvisvgm' then
+ texio.write_nl(string.format('WARNING (luaotfload): Unsupported DVI backend %q, falling back to dvisvgm.', dvi_kind))
+ end
+ -- Legacy fonts can be written to the DVI file directly
+ if 2 ~= (tfmdata.encodingbytes or ((tfmdata.format == 'truetype' or tfmdata.format == 'opentype') and 2 or 1)) then
+ return
+ end
+ local newfont = {}
+ for k,v in pairs(tfmdata) do
+ newfont[k] = v
+ end
+ local newchars = {}
+ newfont.characters = newchars
+ local lookup = {}
+ for k,v in pairs(tfmdata.characters) do
+ local newchar = {
+ width = v.width, -- Only width should really be necessary
+ height = v.height,
+ depth = v.depth,
+ }
+ newchars[v.index or k] = newchar
+ lookup[k] = v.index or k
+ end
+ newfont.checksum = string.unpack('>I4', 'LuaF') -- Use a magic checksum such that the reader
+ -- can uniquely identify these fonts.
+ local name = '[' .. newfont.name .. ']:' -- TODO: Why .name? I would have expected .filename
+ if newfont.subfont and newfont.subfont ~= 1 then
+ name = name .. 'index=' .. tostring(math.tointeger(newfont.subfont-1)) .. ';'
+ end
+ if newfont.extend and newfont.extend ~= 1000 then
+ name = name .. 'extend=' .. tostring(math.tointeger(math.round(newfont.extend*65.536))) .. ';'
+ end
+ if newfont.slant and newfont.slant ~= 0 then
+ name = name .. 'slant=' .. tostring(math.tointeger(math.round(newfont.slant*65.536))) .. ';'
+ end
+ if newfont.mode == 2 and newfont.width and newfont.width ~= 0 then
+ name = name .. 'embolden=' .. tostring(math.tointeger(math.round(newfont.width*65.78176))) .. ';'
+ end
+ newfont.name = name:sub(1,-2) -- Stri th trailing : or ;
+ tfmdata.backend_font = lookup
+ lookup.font = define_font(newfont)
+end
+
+fonts.constructors.features.otf.register {
+ name = "dvifont",
+ default = "dvisvgm",
+ manipulators = {
+ node = manipulate,
+ base = manipulate,
+ },
+ processors = {
+ node = process,
+ base = process,
+ },
+}