我想创建一个 TikZ 样式,使用包\contour{<colour>}{<text>}
中的宏为节点文本添加粗轮廓contour
(如问题的答案中所示TikZ:文本周围有光晕?),即我想定义一种风格,halo
以便
\node [halo] {Text};
相当于
\node {\contour{red}{Text}};
我的问题是我无法告诉 TikZ 使用节点文本作为宏的参数。
该font
选项仅适用于类似的开关\itshape
(与相反\textit{}
,后者要求在参数中提供斜体文本)。
有两个键execute at begin node={<code>}
和execute at end node={<code>}
可用于在节点的开头和结尾调用代码,但我无法\contour
使用execute at begin node={\contour{red{}
和拆分命令,execute at end node={}}
因为括号不匹配。{
用\bgroup
和}
替换\egroup
会失败Missing } inserted
。
以下是可供玩的 MWE:
\documentclass{article}
\usepackage{tikz}
\usepackage[outline]{contour}
\contourlength{1.2pt}
\begin{document}
\begin{tikzpicture}
\node {\contour{red}{Text}};
% \node [font=\contour{red}{}] {Text}; % Doesn't change the text
% \node [execute at begin node={\contour{red}{},execute at end node={}}] {Text}; % Fails with ``Runaway argument?''
% \node [execute at begin node={\contour{red}\bgroup},execute at end node={\egroup}] {Text}; % Fails with ``Missing } inserted''
\end{tikzpicture}
\end{document}
答案1
在查看源代码contour
(至少在pdftex
驱动程序部分)后,我发现它将文本排版两次,一次用于轮廓,一次正常。内容必须很短(即不是\long
),并且以限制水平模式。问题是 TikZ 将节点内容作为框而不是宏参数处理。这通常非常好,因为它允许节点中的逐字内容等,但不允许直接访问和\contour
其他宏所需的未排版内容。
请注意,\contour
如果您使用 ,则部分适用于盒装内容\unhbox
。问题是您需要它两次并且无法更改颜色!因此,要么两者都具有相同的颜色,这使得轮廓不太有用,要么您只有轮廓没有真正的文本。我修补了contour
源代码(仅供pdftex
参考)以便您到达那里:
% (uncomment the `%` lines to enable typesetting of the real text, but in the same color than the contour)
\documentclass{article}
\usepackage{tikz}
\usepackage[outline]{contour}
\contourlength{.1pt}
\makeatletter
\def\tikzcontour#1{%
\begingroup
\color{#1}%
%\def\contourcolor{#1}%
\begin{lrbox}{\@tempboxa}%
}
% Mostly taken from `\@contour@outline` from `contour`s `pdftex.cnt` driver file:
% Work with pdftex only
\def\endtikzcontour{%
\end{lrbox}%
%\setbox0=\hbox{\usebox\@tempboxa}%
\begingroup
\setlength\con@length{\con@base@length}%
\setlength\con@length{2\con@length}%
\setlength\con@length{0.99626400996\con@length}%
%\color{\contourcolor}%
\con@coloroff
\pdfliteral{%
q
1 j
1 J
1 Tr
\strip@pt\con@length\space w
}%
%\rlap
\mbox% change back to `\rlap` when "real" text is drawn
{\unhbox\@tempboxa}%
\pdfliteral{%
Q
}%
\endgroup
%\unhbox0
\endgroup
}
\makeatother
\begin{document}
\begin{tikzpicture}
\node [execute at begin node={\tikzcontour{red}},execute at end node={\endtikzcontour}] {Text};
\end{tikzpicture}
\end{document}
得出:
但是,可以使用与我的collcell
包收集单元内容相同的技术来收集 TikZ 节点的内容tabular
,即跳过内部代码头并逐个标记地读取它,直到到达末尾。
这里有一些概念验证的快速解决方案,它重用了 中的代码collcell
。请勿\collectcell
与同一文件中的表一起使用。有时间的话,我会编写一个专用的、更稳定的解决方案。
\documentclass{article}
\usepackage{tikz}
\usepackage[outline]{contour}
\contourlength{.05em}
\usepackage{collcell}
\makeatletter
\def\collect@cell@look@{%
\cc@case
\@sptoken{%
\edef\collect@cell@spaces{\collect@cell@spaces\space}%
\collect@cell@eatspace
}%
\bgroup{\collect@cell@group}%
\egroup{\afterassignment\collect@cell@end\let\@let@token=}%
%\egroup{\collect@cell@end}%
\default{\collect@cell@arg}%
\endcc@case
}
\def\tikzcontour#1#2{\@tikzcontour{#1}#2\@endtikzcontour}
\def\@tikzcontour#1#2\ignorespaces#3\@endtikzcontour{%
\bgroup%
\ifx\tikz@textcolor\pgfutil@empty%
\else%
\pgfutil@colorlet{.}{\tikz@textcolor}%
\fi%
\pgfsetcolor{.}%
\setbox\tikz@figbox=\box\pgfutil@voidb@x%
\tikz@uninstallcommands%
\tikz@halign@check%
\contour{#1}{\ignorespaces #3\unskip}%
\egroup
\tikz@fig@collectresetcolor%
}
\let\collcell@afteruser=\empty
\makeatother
\tikzset{contour/.style={execute at begin node={\collectcell{\tikzcontour{#1}}\ignorespaces}}}
\begin{document}
\begin{tikzpicture}
\node [draw,green,contour=red,circle] {Text};
\end{tikzpicture}
\end{document}