# sidebearings and precision left/right alignment

As was suggested, I will rephrase my previous question, which is not confined in a coffin.

As @MartinScharrer rightly points out, I am asking how to optically align text at the margins after linebreaking, more specifically when you do not know in advance the content.

This is the case in templates, where the text is provided by a user.

Since TeX compose with boxes, the sidebearings are always there, but they become more noticeable when using large size fonts in title pages or posters.

Working with xelatex I solved this problem for single line sentences, but failed to do so with multiline paragraphs. (Again, text unknown in advance.)

Perfect alignment, single sentence, text unknown in advance.

Variable right gaps in a multiple line title.

The way I would like, (done by hand, known text)

    \documentclass{article}

\RequirePackage{xcolor}
\RequirePackage{xstring}

%% scrapping sidebearing both L & R

\newcommand\shaveLR[1]{%
\if\relax\detokenize{#1}\relax\else% check  empty
\StrLeft{#1}{1}[\tempi]%    the first char
\StrRight{#1}{1}[\tempii]%  the last char
\kern-\XeTeXglyphbounds1 \the\XeTeXcharglyph\expandafter\tempi% first char L un-kernig
#1%  input string
\kern-\XeTeXglyphbounds3 \the\XeTeXcharglyph\expandafter\tempii% last char R un-kernig
\fi}

\newcommand{\hairlineiv}[1][green]{%
\leavevmode%
\kern-0.1pt %
\smash{\color{#1}\vrule height 4\baselineskip depth 5pt width 0.1pt}%
\kern-0.1pt}

\newcommand{\hairlinei}[1][red]{%
\leavevmode\kern-0.1pt %
\smash{\color{#1}\vrule height 35pt depth 15pt width 0.1pt}%
\kern-0.1pt}

\newcommand{\byauthor}{}
\newcommand{\longtitles}{}

\begin{document}
\pagestyle{empty}

\renewcommand{\longtitles}{Long titles must be exactly align with the vertical green bar.}% the main title

%%%% examples
\newcommand{\thislongtitleR}{%
\shaveLR{Long titles must be}\\%
\shaveLR{exactly align with}\\%
\shaveLR{the vertical green}\\%
\shaveLR{bar.}}

\Large \flushright
Note the gap between\\ the red line and the 'e'.

\vspace{\baselineskip}
{\sffamily\fontsize{60}{60}\selectfont
by \byauthor\hairlinei}
\vspace{\baselineskip}

No gap here after\\ zeroing the kern.

\vspace{1\baselineskip}
{\sffamily\fontsize{60}{60}\selectfont
by \shaveLR{\byauthor}\hairlinei}
\vspace{2\baselineskip}

\newpage
\Large \flushright The way it is:
\vspace{1\baselineskip}
\begin{minipage}{1.3\textwidth}
\raggedleft\sffamily\fontsize{50}{60}\selectfont\bfseries \longtitles\hairlineiv\par
\end{minipage}

\vspace{2\baselineskip}
\Large \flushright The way it should be:
\vspace{1\baselineskip}

\begin{minipage}{1.3\textwidth}
\raggedleft\sffamily\fontsize{50}{60}\selectfont\bfseries \thislongtitleR\hairlineiv
\end{minipage}

\end{document}

• Perhaps talk directly to the maintainers of xcoffins? They are after all the ones to implement your suggestions... – remco Apr 17 '18 at 18:52
• github.com/latex3/latex3 or more precisely github.com/latex3/latex3/tree/master/l3experimental maybe open there a feature request issue? – user4686 Apr 17 '18 at 19:02
• Please report feature requests or bug reports directly to the package authors. This is a question & answer side and your post does not fit into this scheme. – Martin Scharrer Apr 18 '18 at 11:21
• isn't this more of an issue for microtype than xcoffins? to specify protrusion for the relevant characters to get better optical alignment at the margins? – David Carlisle Apr 18 '18 at 12:07
• @MartinScharrer I fail to see why this is off topic, it is asking how to optically align text at the margins after linebreaking. The suggestion that it's xcoffins that does that is secondary. – David Carlisle Apr 18 '18 at 12:54

A LuaTeX solution:

In LuaTeX, you can use the post_linebreak_filter to intercept the broken lines and add some offsets. The sidebearings can be extracted from rawdata saved by luaotfload. After adding the offsets, the hboxes have to be repacked to determine the new glue settings.

\usepackage{luacode}
\begin{luacode*}
for n in node.traverse_id(node.id'hlist', head) do
if char then
local f = font.getfont(char.font)
if f.shared then
local off = f.shared.rawdata.descriptions[char.char].boundingbox[1]*f.size/1000
char.xoffset = char.xoffset - off
end
end
for ch in node.traverse_id(node.id'glyph', n.head) do
char = ch
end
if char then
local f = font.getfont(char.font)
if f.shared then
local desc = f.shared.rawdata.descriptions[char.char]
end
end
local new_list = node.hpack(n.head, n.width, 'exactly')
n.glue_order = new_list.glue_order
n.glue_set = new_list.glue_set
n.glue_sign = new_list.glue_sign
node.free(new_list)
end
return true
end
luatexbase.add_to_callback('post_linebreak_filter', drop_sidebearing, 'Drop sidebearings after linebreaking')
\end{luacode*}


EDIT: The same code integrated into the original example with an added parameter \dropsidebearings. The code will only have an effect if \dropsidebearings is not 0 at the end of the paragraph.

\documentclass{article}

\RequirePackage{xcolor}
\RequirePackage{xstring}

\usepackage{luacode}
\newcount\dropsidebearings
\begin{luacode*}
if tex.count['dropsidebearings'] == 0 then
return true
end
for n in node.traverse_id(node.id'hlist', head) do
if char then
local f = font.getfont(char.font)
if f.shared then
local off = f.shared.rawdata.descriptions[char.char].boundingbox[1]*f.size/1000
char.xoffset = char.xoffset - off
end
end
for ch in node.traverse_id(node.id'glyph', n.head) do
char = ch
end
if char then
local f = font.getfont(char.font)
if f.shared then
local desc = f.shared.rawdata.descriptions[char.char]
end
end
local new_list = node.hpack(n.head, n.width, 'exactly')
n.glue_order = new_list.glue_order
n.glue_set = new_list.glue_set
n.glue_sign = new_list.glue_sign
node.free(new_list)
end
return true
end
luatexbase.add_to_callback('post_linebreak_filter', drop_sidebearing, 'Drop sidebearings after linebreaking')
\end{luacode*}

\newcommand{\hairlineiv}[1][green]{%
\leavevmode%
\kern-0.1pt %
\smash{\color{#1}\vrule height 4\baselineskip depth 5pt width 0.1pt}%
\kern-0.1pt
}

\newcommand{\hairlinei}[1][red]{%
\leavevmode\kern-0.1pt %
\smash{\color{#1}\vrule height 35pt depth 15pt width 0.1pt}%
\kern-0.1pt
}

\begin{document}
\pagestyle{empty}

\newcommand{\longtitles}{Long titles must be exactly align with the vertical green bar.}% the main title

\Large \flushright
Note the gap between\\ the red line and the 'e'.
\protrudechars=1

\vspace{\baselineskip}
{\sffamily\fontsize{60}{60}\selectfont
by \byauthor\hairlinei}
\vspace{\baselineskip}

No gap here after\\ zeroing the kern.

\vspace{1\baselineskip}
{\sffamily\fontsize{60}{60}\selectfont
\dropsidebearings=1
by \byauthor\hairlinei\par}
\vspace{2\baselineskip}

\newpage
\Large \flushright The way it is:
\vspace{1\baselineskip}
\begin{minipage}{1.3\textwidth}
\raggedleft\sffamily\fontsize{50}{60}\selectfont\bfseries \longtitles\hairlineiv\par
\end{minipage}

\vspace{2\baselineskip}
\Large \flushright The way it should be:
\vspace{1\baselineskip}

\begin{minipage}{1.3\textwidth}
\dropsidebearings=1
\raggedleft\sffamily\fontsize{50}{60}\selectfont\bfseries \longtitles\hairlineiv
\end{minipage}

\end{document}

• It certainly works with LuaTex! Thank you Marcel. Now we only have to conquer XeLatex! Or move myself to LuaTex. I will mark your answer as satisfactory as soon as I check that it is possible to recompile safely some of my real life files. – Simon Dispa Apr 19 '18 at 19:46
• (I can not claim that I understand how the invocation works.) – Simon Dispa Apr 19 '18 at 19:52
• @ Marcel Krüger Thank you very much. So far everything works fine. While I start learning lua: the routine operates over the whole document (flawless). So you get right and left optical alignment on, perhaps, parts you might what to leave untouched. Is it possible to start and stop it, from an external switch? I know this question is beyond the scope of the original. – Simon Dispa Apr 20 '18 at 18:44
• @SimonDispa I added an edit with a parameter to control this on a per paragraph level. – Marcel Krüger Apr 20 '18 at 20:28
• @ Marcel Krüger Thank you again!. Just what I wanted. Perhaps you would like to comment on this solution. I found several question on sidebearing and/or side-bearing with LuaTeX as a limitation to jump to LuaTeX. (I am not allow to comment because I have not earn enough points.) tex.stackexchange.com/questions/45549/…. – Simon Dispa Apr 20 '18 at 21:34