red
考虑以下 MWE。我想为带框的物体 ( )赋予颜色 ( ) Hello
。不幸的是,它不能按预期工作,就好像带框的物体被屏蔽了一样。如何去除这样的屏蔽?
\documentclass{article}
\usepackage{xcolor}
\newsavebox\MyBox
\savebox\MyBox{Hello}
\begin{document}
\textcolor{red}{\usebox\MyBox}
\end{document}
答案1
\savebox
使用来定义\sbox
,后者在 LaTeX 中定义为:
\long\def\sbox#1#2{\setbox#1\hbox{%
\color@setgroup#2\color@endgroup}}
当包加载时,的文本参数\sbox
被包装在一个组\color@setgroup
和中:\color@endgroup
color
\def\color@setgroup{\begingroup\set@color}
\let\color@begingroup\begingroup
\def\color@endgroup{\endgraf\endgroup}
另外,在构建框时设置当前处于活动状态的颜色。这是故意的,因为其他属性(如字体)也是固定的。框内容在或\color@setgroup
中不会改变,字体系列或大小也无法更改。\textit
\textbf
颜色通常通过特殊来实现,那么以下定义会有所帮助:
\makeatletter
\newcommand{\sboxcolorless}[2]{%
\setbox#1\hbox{\color@begingroup#2\color@endgroup}%
}
\makeatother
将参数放入一个组中非常重要,这里\color@begingroup
和\color@endgroup
,因为#2
可以包含\color
命令,这些命令会自动重置颜色后组。如果缺少明确的组里面 \hbox
,重置颜色特殊会泄漏外部和\hbox
声明\setbox
。
\documentclass{article}
\usepackage{xcolor}
\newsavebox\MyBoxA
\savebox\MyBoxA{Hello}
\makeatletter
\newcommand{\sboxcolorless}[2]{%
\setbox#1\hbox{\color@begingroup#2\color@endgroup}%
}
\makeatother
\newsavebox\MyBoxB
\sboxcolorless\MyBoxB{Hello}
\begin{document}
\textcolor{red}{Red \usebox\MyBoxA\ red \usebox\MyBoxB\ red.}
\end{document}
但是,这个技巧取决于颜色的实现。LuaTeX 有一个属性的概念,其中颜色可以更接近字体属性的实现。包luacolor
实现了这一点。然后,元素、字符在创建时会归因于当前颜色。在框中重复使用不会改变这一点。因此,使用包的luacolor
示例看起来会有所不同,两个“Hello”都是黑色的:
如果您想要更多的可移植性和灵活性,可以使用宏,其中对固定属性的控制更大:
\documentclass{article}
\usepackage{xcolor}
\newcommand*{\Hello}{%
\begingroup
\fontfamily\rmdefault % roman font, no non-serif or typewriter
\upshape % no italics, small caps
% but series (bold) or font size are flexible
Hello%
\endgroup
}
\begin{document}
\textcolor{red}{Red \Hello\ \textbf{bold \Hello} \textit{italics \Hello}}
\end{document}
这也适用于所有颜色实现。
XeTeX 的注释
XeTeX 的颜色驱动程序xetex.def
通过 很晚才定义颜色命令\AtBeginDocument
。这意味着颜色命令是不是在前导码中完全可操作。例如,\textcolor{blue}{...}
如果在前导码中设置了框,框内也将不起作用。如果在 `\begin{document} 之后保存框,则框将像其他驱动程序的情况一样工作。
\documentclass{article}
\usepackage{xcolor}
\newsavebox\MyBox
\savebox\MyBox{Hello \textcolor{blue}{World}!}
\begin{document}
\textcolor{red}{Red \usebox\MyBox\ Red}
\savebox\MyBox{Hello \textcolor{blue}{World}!}
\textcolor{red}{Red \usebox\MyBox\ Red}
\end{document}
这种“奇怪”行为背后的原因是xetex.def
想要允许用户通过禁用堆栈颜色实现(在某些极少数情况下可能需要)\noXeTeXcolorstack
。
在序言中启用颜色的解决方法:
\makeatletter
\check@for@XeTeX@colorstack
\let\check@for@XeTeX@colorstack\relax
\makeatother
答案2
据我了解,当 LaTeX 使用 创建一个框时\savebox
,该框是在那一刻创建的,并且任何颜色都已被分配;所以当你 时\usebox
,当前颜色不会产生任何效果。
一个选项是最初用颜色定义框:
\savebox\MyBox{\textcolor{red}{Hello}}
另一个更灵活的解决方案是定义一个命令,在发出命令时动态构建框:
\documentclass{article}
\usepackage{xcolor}
\def\makecolbox#1#2{%
\hbox{\textcolor{#1}{#2}}%
}
\begin{document}
\makecolbox{red}{Hello}
\makecolbox{green}{Goodbye}
\makecolbox{black}{Whatever}
\end{document}
如果框的内容相同,则可以消除#2
,然后以这种方式对文本进行硬编码。
答案3
这里有一个蒂克兹解决方案。我定义了两个宏:
\savecolorablebox{boxname}{content}
定义并保存一个可着色的框。\usecoloredbox[color]{boxname}
使用并给盒子上色。
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{fadings}
\newcommand\savecolorablebox[2]{
\expandafter\newsavebox\csname#1\endcsname
\expandafter\savebox\csname#1\endcsname{\textcolor{white}{#2}}
\begin{tikzfadingfrompicture}[name=#1]
\node[text=transparent!0,fill=transparent!100]{\expandafter\usebox\csname#1\endcsname};
\end{tikzfadingfrompicture}
}
\newcommand\usecoloredbox[2][black]{%
\bgroup%
\pgfmathsetmacro\myw{width("\expandafter\usebox\csname#2\endcsname")}%
\pgfmathsetmacro\myh{height("\expandafter\usebox\csname#2\endcsname")}%
\pgfmathsetmacro\myd{depth("\expandafter\usebox\csname#2\endcsname")}%
\begin{tikzpicture}[baseline=-1 * \myh pt / 2 + \myd pt / 2]
\fill[path fading=#2,fit fading=false,fill=#1]
(-1 * \myw pt / 2, -1 * \myh pt / 2 - 1 * \myd pt / 2)
rectangle (\myw pt / 2,\myh pt /2 + \myd pt / 2);
\end{tikzpicture}%
\egroup%
}
\begin{document}
\savecolorablebox{MyBox}{Hello}
test \usecoloredbox[orange]{MyBox} test \usecoloredbox[blue]{MyBox}
\savecolorablebox{MyBox2}{Hello gg}
test \usecoloredbox[cyan]{MyBox2} test \usecoloredbox[green]{MyBox2}
\savecolorablebox{MyBox3}{$x=\frac{a}{b}$}
test \usecoloredbox[cyan]{MyBox3} test \usecoloredbox[red]{MyBox3}
\end{document}