正如有人建议的那样,我将重新措辞我之前的问题,这个问题并没有被关在棺材里。
正如@MartinScharrer 正确指出的那样,我问的是如何在换行后在边缘处光学对齐文本,更具体地说,当您事先不知道内容时。
模板中就是这种情况,其中的文本由用户提供。
由于 TeX 使用方框进行编写,因此侧边距始终存在,但在标题页或海报中使用大尺寸字体时,侧边距会变得更加明显。
使用 xelatex,我解决了单行句子的问题,但无法解决多行段落的问题。(同样,事先不知道文本。)
完美对齐,单句,事先未知的文字。
我想要的方式(手工完成,已知文本)
\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{\byauthor}{Your Name} % put your name here
\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}
答案1
LuaTeX 解决方案:
在 LuaTeX 中,您可以使用post_linebreak_filter
截取折线并添加一些偏移量。可以从 luaotfload 保存的 rawdata 中提取侧边距。添加偏移量后,必须重新打包水平盒以确定新的粘合设置。
要将其应用于文档中的每个垂直框,请在序言中添加
\usepackage{luacode}
\begin{luacode*}
local function drop_sidebearing(head, groupcode)
for n in node.traverse_id(node.id'hlist', head) do
local char = node.has_glyph(n.head)
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.xadvance = char.xadvance - off
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]
char.xadvance = char.xadvance - (desc.width-desc.boundingbox[3])*f.size/1000
end
end
local new_list = node.hpack(n.head, n.width, 'exactly')
new_list.head = nil
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*}
编辑:将相同的代码集成到原始示例中,并添加参数。仅当不在段落末尾时,\dropsidebearings
代码才会产生效果。\dropsidebearings
0
\documentclass{article}
\RequirePackage{xcolor}
\RequirePackage{xstring}
\usepackage{luacode}
\newcount\dropsidebearings
\begin{luacode*}
local function drop_sidebearing(head, groupcode)
if tex.count['dropsidebearings'] == 0 then
return true
end
for n in node.traverse_id(node.id'hlist', head) do
local char = node.has_glyph(n.head)
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.xadvance = char.xadvance - off
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]
char.xadvance = char.xadvance - (desc.width-desc.boundingbox[3])*f.size/1000
end
end
local new_list = node.hpack(n.head, n.width, 'exactly')
new_list.head = nil
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{\byauthor}{Your Name} % put your name here
\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}