Can TeX do ugly typesetting (with poor kerning)?
An approach with XeTeX and \XeTeXinterchartoks
(i.e. compile the below with xelatex
):
\documentclass{article}
\usepackage{lipsum}
\input{random}
\newcount\randnum
\newcommand{\randkern}{%
\setrannum{\randnum}{-30}{30}%
\kern \dimexpr(\randnum pt/10)\relax
}
\XeTeXinterchartokenstate = 1
\XeTeXinterchartoks 0 0 = {\randkern}
\begin{document}
\lipsum[1]
\end{document}
You can make the range smaller if you'd like less aggressive miskerning, e.g. changing {-30}{30}
to {-10}{20}
gives:
The idea is simply to insert a random kern between any two characters. For example, if we typed something like:
L\kern 0.4pt o\kern 1.3pt r\kern -1.0pt e\kern -0.4pt m
and so on, we'd have the result from the image above. The above code just does this, with two shortcuts:
- Defines a
\randkern
, using packagerandom
to generate random numbers, and the\dimexpr
primitive introduced in e-TeX). - Uses
\XeTeXinterchartoks
(documented in the XeTeX reference guide). Setting\XeTeXinterchartoks 0 0
to\randkern
inserts the token\randkern
between any two characters of class 0 (most characters are of class 0 by default). For example, when our text contains the characterL
followed by the charactero
, XeTeX treats it as if you had typed the token\randkern
between them (like typingL\randkern o
).
With LuaTeX, there’s a kerning
callback provided, which we can use for exactly this purpose. There is no built-in equivalent of \XeTeXinterchartoks
, but the appeal of LuaTeX is that a lot of such functionality we can implement ourselves, in Lua. We can get:
with (compile the below with lualatex
)
\documentclass{article}
\usepackage{lipsum}
\directlua{dofile('randomkern.lua')}
\begin{document}
\lipsum[1]
\end{document}
where randomkern.lua
is:
function rekern(head)
local i = head
while i~=nil do
j = i.next
-- Skip over discretionary (hyphen) nodes
while j~=nil and node.type(j.id)=='disc' do
j = j.next
end
-- Insert a kern node between successive glyph nodes
if node.type(i.id)=='glyph' and j~=nil and node.type(j.id)=='glyph' then
k = node.new(node.id('kern'))
head, i = node.insert_after(head, i, k)
assert(node.type(i.id)=='kern')
end
-- Tweak existing kerns (including ones we inserted) by a random amount
if node.type(i.id)=='kern' then
i.kern = i.kern + math.random(65536*-1, 65536*2)
end
i = i.next
end
end
luatexbase.add_to_callback('kerning', rekern, 'Introduce random kern nodes')
The idea is that the kerning
callback gets a list of nodes: for example,
temp
local_par
hlist indent {}
glyph L
glyph o
glyph r
glyph e
glyph m
glue <spaceskip: 218235 plus 109117^0 minus 72745^0>
glyph i
glyph p
disc
glyph s
glyph u
glyph m
glue <spaceskip: 218235 plus 109117^0 minus 72745^0>
glyph d
glyph o
disc
glyph l
glyph o
glyph r
glue <spaceskip: 218235 plus 109117^0 minus 72745^0>
glyph s
glyph i
glyph t
and so on. We simply traverse this list, and between every two consecutive glyph
nodes (possibly with a disc
node between them), we insert a kern
node, and give it a random value. (TeX stores all dimensions (lengths, etc.) internally in scaled points, where 65536 sp = 1 pt.)
Note that this version handles hyphenation automatically: only the kerning changes; the set of valid hyphenation or line-break points remains the same.