Skip to content

Instantly share code, notes, and snippets.

@zauguin
Last active April 7, 2020 16:13
Show Gist options
  • Save zauguin/16acd354ee07a909210895f63bc3acb0 to your computer and use it in GitHub Desktop.
Save zauguin/16acd354ee07a909210895f63bc3acb0 to your computer and use it in GitHub Desktop.
luaotfload output enhancment for DVI mode
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 define_font = font.define
local disc_t = node.id'disc'
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 node.direct.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 node.direct.traverse_id(disc_t, head) do if node.direct.uses_font(n, font) then
local pre, post, rep = getdisc(n)
for n, c, f in node.direct.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 node.direct.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 node.direct.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)
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')
local name = '[' .. newfont.name .. ']:'
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)
tfmdata.backend_font = lookup
lookup.font = define_font(newfont)
end
fonts.constructors.features.otf.register {
name = "dvifont",
default = true,
manipulators = {
node = manipulate,
base = manipulate,
},
processors = {
node = process,
base = process,
},
}
\RequirePackage{iftex}
\ifLuaTeX
\directlua{require'luadvi'}
\fi
\documentclass{article}
\pagestyle{empty}
\usepackage{fontawesome5}
\usepackage{fontspec}
\setmainfont{Latin Modern Roman}
\begin{document}
\Huge
\faArrowRight\faArrowLeft
abc
\addfontfeature{FakeBold=1}
def
\addfontfeature{FakeStretch=2}
ghi
\addfontfeature{FakeSlant=1}
jkl
\end{document}
@agrahn
Copy link

agrahn commented Apr 7, 2020

I get a segmentation fault with

dvisvgm --zoom=-1 --exact --font-format=woff2 test.dvi

@zauguin
Copy link
Author

zauguin commented Apr 7, 2020

@agrahn That's because dvisvgm doesn't support this way of passing fonts currently. Martin is working on dvisvgm to add this support.

@agrahn
Copy link

agrahn commented Apr 7, 2020

Thank you all, Martin (@mgieseki) and Marcel!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment