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
128
129
130
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,
},
}
|