1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
-------------------------------------------------------------------------------
-- FILE: luaotfload-dvi.lua
-- DESCRIPTION: part of luaotfload / DVI
-------------------------------------------------------------------------------
assert(luaotfload_module, "This is a part of luaotfload and should not be loaded independently") {
name = "luaotfload-dvi",
version = "3.16", --TAGVERSION
date = "2020-12-31", --TAGDATE
description = "luaotfload submodule / DVI",
license = "GPL v2.0",
author = "Marcel Krüger",
copyright = "Luaotfload Development Team",
}
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,
},
}
|