我希望有一个命令\globalred
,使所有后续文本变为红色,即使该命令是在组内发出的。例如,TeX 文件的输出
\documentclass{article}
\begin{document}
a {\globalred b} c
\end{document}
应该是 ,用红色的c
。我确实有一些非常棘手的解决方案,但它只能通过重新定义\set@color
和\reset@color
命令来工作,从pdftex.def
到它们所在的位置版本 0.03t(或者使用 2007 年之前的旧 TeX 安装):
\documentclass{article}
\usepackage[pdftex]{xcolor}
\makeatletter
\def\set@color {\pdfliteral{\current@color}%
\aftergroup\reset@color}
\def\reset@color{\pdfliteral{\current@color}}
\def\globalred {\xdef\current@color{\xcolor@ {}{1 0 0 rg 1 0 0 RG}{rgb}{1,0,0}}%
\set@color}
\makeatother
\begin{document}
a {\globalred b} c
\end{document}
这让我想到以下问题:
- 有没有“官方”的方法来实现我的目标?
- 为什么
\set@color
从较新的pdftex.def
版本开始不再具有全局作用,尽管我\current@color
用进行了全局重新定义\xdef
?(这是设计选择还是新实现的不可预见的副作用\set@color
?)
让我简单解释一下我是如何想到这个的:在上面我的代码中,我粗略地模拟了beamer
生成透明文本的操作。beamer
旨在以一种超越群体的方式来做到这一点(参见用户指南,第 24 页和第 79 页),但它似乎不再起作用了;至少对我来说,第 79 页上的示例给出了奇怪的输出:
同样的问题(和黑客解决方案)出现在这个问题是我的。
答案1
在 LaTeX 中没有官方的方法来实现这一点。颜色变化与组绑定。“全局技巧”之所以适用于旧版本,pdftex.def
是因为那里的颜色实现存在缺陷。旧版本的 pdfTeX 不提供颜色堆栈,因此在分页方面存在严重问题。
Dvips 提供了一个颜色堆栈,其中当前颜色放在驱动程序的堆栈上,颜色更改后,堆栈的颜色会恢复,而\current@color
不会在恢复颜色值时使用。pdftex.def
如果和 pdfTeX 不是太旧的话,现在也会发生同样的情况。此外,pdfTeX 通过支持多个颜色堆栈改进了 dvips 的颜色堆栈。例如,可以为脚注(包pdfcol
)使用额外的颜色堆栈来支持跨页脚注的颜色更改。有关其他示例,请参阅包pdfcolparrallel
或pdfcolparcolumns
。此外,可以通过这种方式管理颜色以外的其他参数,请参阅pdftransparent
透明度或的示例包pdfrender
。
\documentclass{article}
\usepackage[pdftex]{xcolor}
\makeatletter
\def\set@color{%
\pdfliteral{\current@color}%
\aftergroup\reset@color
}
\def\reset@color{%
\pdfliteral{\current@color}%
}
% colorfix stuff for old implementation of color for pdfTeX
\RequirePackage{ltxcmds}
\AtBeginDocument{%
\ltx@ifundefined{@ldc@l@r}{%
\let\@ldc@l@r\color
\def\color{%
\ltx@IfUndefined{if@inlabel}{}{%
\csname if@inlabel\expandafter\endcsname
\expandafter\leavevmode\csname fi\endcsname
}%
\@ldc@l@r
}%
}{}%
\ltx@ifundefined{@lduseb@x}{%
\ltx@IfUndefined{usebox}{}{%
\let\@lduseb@x\usebox
\def\usebox#1{\@lduseb@x{#1}\reset@color}%
}%
}{}%
}
\newcommand*{\globalcolor}{%
\let\saved@set@color\set@color
\def\set@color{%
\saved@set@color
\global\let\current@color\current@color
\let\set@color\saved@set@color
}%
\color
}
\makeatother
\begin{document}
a \textcolor{blue}{b \globalcolor{red}c }d
\end{document}
\pdfcolorstack
可以禁用,然后pdftex.def
会自动切换到旧行为。但是,这也会破坏与颜色无关的其他内容(例如pdfrender
,,pdftransparent
...)。
而这\globalcolor
对其他驱动程序不起作用dvips
。因此我不推荐这种方法。
答案2
好的,我想出了另一个不起作用的解决方案禁用pdf 颜色堆栈,但操纵它。这个想法是使用set
原始选项\pdfcolorstack
。我希望这比问题中的粗略想法有更少的副作用。(一个缺点是,我对的重新定义会\reset@color
导致分页符出现问题;请参阅 Heiko Oberdieck 的评论。)
编辑:现在解决方案适用于pdflatex
和latex -> dvips
。我对驱动程序的代码不太满意dvips
,但看起来如果color pop
用于空颜色堆栈,驱动程序不会抱怨。
\documentclass{article}
\usepackage{xcolor}
\makeatletter
\let\rs@c\reset@color
\def\dvips@driver{dvips.def}
\def\pdftex@driver{pdftex.def}
\ifx\Gin@driver\pdftex@driver
\def\reset@color{%
\rs@c
\pdfcolorstack\@pdfcolorstack set{\current@color}%
}
\fi
\ifx\Gin@driver\dvips@driver
\def\reset@color{%
\rs@c
\rs@c
\set@color
}
\fi
\newcommand*{\globalcolor}{%
\let\saved@set@color\set@color
\def\set@color{%
\saved@set@color
\let\set@color\saved@set@color
\global\let\current@color\current@color
}%
\color
}
\makeatother
\begin{document}
\textcolor{green}{%
a \textcolor{blue}{b \globalcolor{red} c }d \textcolor{black} e
}f
\end{document}