纯文本彩色文本

纯文本彩色文本

最近我对纯 TeX 产生了兴趣,因为它比常规 LaTeX 具有更大的灵活性。

在我的文档中,我希望使用文本的灰度。在 LaTeX 中,通过包可以产生此结果color。David Carlisletexdoc color提供了有关该包的出色文档graphics,但缺少有关实现的大量文档。

或者,我可以尝试以自己的方式来解决xcolor,虽然在实施方面会复杂得多,但请注意,该包中也缺少有关实施的完整章节。

我在论坛上找到了一些解决方法comp.text.texhttp://compgroups.net/comp.text.tex/problem-using-color-and-graphicx-in-plain-tex/1918061),这当然非常简单的并且(如果你愿意)方便的但这些解决方案本质上与使用纯 TeX 的原因,即纯 TeX 格式不受时间流逝的影响。在纯 TeX 文档中使用 LaTeX 包可能会被认为触及灰色区域,例如“该包不太可能在不久的将来发生变化”。但是,从我的角度来看,这个问题的目的可以延伸得更远,给出图形驱动程序(我假设它在包和相关包中发挥作用)和 TeXcolor之间互锁的实现概述。color

所以我想询问一下该color包在纯 TeX 中的实现,或者具有类似功能的替代实现。

答案1

由于问题集中在学习如何使用原语来完成这些事情(我同意大卫的回答以普通方式加载color包裹是更简单的方法)。

我在这里要做的是实现与该color包所采用的方法大致相同的方法,并对经典 TeX(dvipsdvipdfm(x)驱动程序)、PDF 模式下的 pdfTeX/LuaTeX 和 XeTeX 进行适当的测试。由于还有一些事情要做,我将在代码中穿插一些注释。

首先,设置一个条件来测试直接 PDF 输出

\newif\ifpdfmode

\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname pdfoutput\endcsname\relax
\else
  \ifnum\pdfoutput>0 %
    \expandafter\expandafter\expandafter\pdfmodetrue
  \fi
\fi

将当前颜色定义为黑色,使用以便\edef一旦定义就没有条件(同样的想法适用于其余代码)

\edef\currentcolor{%
  \ifpdfmode
    0 g 0 G%
  \else
    gray 0%
  \fi
}

设置预定义颜色:我刚刚做了一个(红色)作为演示:

\edef\colorred{%
  \ifpdfmode
    1 0 0 rg 1 0 0 RG%
  \else
    rgb 1 0 0%
  \fi
}

对于直接 PDF 输出,可能有一个可用的颜色堆栈(自 pdfTeX 1.40.0 起)。一次性测试会告诉我们这一点:如果没有堆栈,只需手动恢复颜色。有关详细信息,请参阅此处的 pdfTeX 手册。

\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname pdfcolorstack\endcsname\relax
  \ifpdfmode
    \def\pdfcolorstackpush{\pdfliteral{\currentcolor}}%
    \let\pdfcolorstackpop\pdfcolorstackpush
  \fi
\else
  \chardef\colorstack=0 %
  \def\pdfcolorstackpush{%
    \pdfcolorstack\colorstackcnt push{\currentcolor}%
  }%
  \def\pdfcolorstackpop{%
    \pdfcolorstack\colorstackcnt pop\relax%
  }%
\fi

设置颜色的主要宏从测试开始:如果参数是预定义颜色的名称,则使用该名称,否则假设为硬编码的引擎特定值。(更复杂的方法是将颜色转换为正确的格式:因为问题中没有要求这样做,所以我将其留作练习)。设置颜色后,插入适当的特殊(注意,\edef将再次意味着在使用时没有条件):

\edef\color#1{%
  \begingroup\noexpand\expandafter\noexpand\expandafter\noexpand\expandafter\endgroup
  \noexpand\expandafter\noexpand\ifx\noexpand\csname color#1\noexpand\endcsname\relax
    \def\noexpand\currentcolor{#1}%
  \noexpand\else
    \noexpand\expandafter\let\noexpand\expandafter\noexpand\currentcolor
      \noexpand\csname color#1\noexpand\endcsname
  \noexpand\fi
  \ifpdfmode
    \noexpand\pdfcolorstackpush
  \else
    \special{color push \noexpand\currentcolor}%
  \fi
  \aftergroup\noexpand\resetcolor
}

按照该color方法,还使用适当的特殊方法创建重置宏。

\edef\resetcolor{%
  \ifpdfmode
    \noexpand\pdfcolorstackpop
  \else
    \special{color pop}%
  \fi
}

演示本身。上面的实现依赖于框内的分组级别,在 LaTeX 中,这将由\savebox“包装器”完成\hbox(等等)。实际上情况并非如此,因此颜色安全框需要一个组。当然,这可以放在一组适当的包装器宏中:

\newbox\mybox
\setbox\mybox=\hbox{\begingroup\color{red}Red text\endgroup}
Surrounding text \box\mybox \space and more of it.
\bye

(注意:我构建上述内容的方式与使用 DocStrip 创建单独文件的方式非常相似。由于不涉及 DocStrip,因此这需要一些条件/edef工作。)

答案2

乳胶graphicscolor包装可以以普通纤维形式使用。http://www.ctan.org/pkg/miniltx

的维护者texdoc选择展示grfguide.pdf如果texdoc color您去texdoc color.pdf那么您将获得彩色包文档,其中包括完整索引的源列表。

plain tex 具有一些优点,它是一种简单的格式,可用于教授如何构建格式,但我真的无法想象它比 latex 更灵活。LaTeX 不会删除任何功能。

答案3

我在 OPmac 软件包中为 plainTeX 实现了全彩色功能。所以我知道问题出在哪里。

\pdfliteral您可以使用或简单地将颜色选择器放入排版材料中\special,但您必须记住,从 TeX 的角度来看,颜色从这一点到页面末尾的变化与分组/段落等无关。例如,\pdfliteral{1 0 0 r}意味着从这一点到页面末尾的所有文本(包括脚注、页码等)都是红色,下一页重新初始化为黑色。如果您在框中打印某些内容,而这些内容不能分成更多页面,那么

\hbox{\pdfliteral{1 0 0 r}Something in red\pdfliteral{0 g}}

就足够了。但如果颜色可以分成更多页面,或者您需要颜色堆栈(即可以返回到以前的颜色 - 没有明确的黑色),那么您必须更正标题/脚注,\plainoutput并且必须在页面上实现颜色管理系统,管理颜色堆栈等。此外,PDF 中有两种类型的颜色选择器:用于描边和用于填充。您可以独立管理它们,也可以在任何地方将两者设置为相同的颜色。

我已经在 OPmac 的技术文档中从实施的角度描述了所有这些功能:opmac-d.pdf,但抱歉,它只有捷克语。

答案4

我尝试重写 Joseph Wright 编写的宏,使其更易读。他的宏不太易读,因为 1) 在测试原语是否存在时存在多余的 expandafters、begingroups、csnames 等;2)\edef对宏的两个变体使用了 ,而不是仅使用\ifpdfmode一次 。

该评论与约瑟夫的回答相同。

\newif\ifpdfmode

\ifx\pdfoutput\undefined
\else
  \ifnum\pdfoutput>0 \pdfmodetrue
  \fi
\fi

\ifpdfmode

\def\colorblack   {0 g 0 G}
\def\colorred     {1 0 0 rg 1 0 0 RG}
\def\colorgreen   {0 1 0 rg 0 1 0 RG}
\def\colorblue    {0 0 1 rg 0 0 1 RG}

\ifx\pdfcolorstack\undefined
  \def\pdfcolorstackpush{\pdfliteral{\currentcolor}}
  \let\pdfcolorstackpop\pdfcolorstackpush
\else
  \mathchardef\colorstackcnt=\pdfcolorstackinit page {\colorblack}
  \def\pdfcolorstackpush{\pdfcolorstack\colorstackcnt push{\currentcolor}}
  \def\pdfcolorstackpop{\pdfcolorstack\colorstackcnt pop}
\fi

\else % of \ifpdfmode

\def\colorblack   {gray 0}
\def\colorred     {rgb 1 0 0}
\def\colorgreen   {rgb 0 1 0}
\def\colorblue    {rgb 0 0 1}

\def\pdfcolorstackpush{\special{color push \currentcolor}}
\def\pdfcolorstackpop{\special{color pop}}

\fi  % of \ifpdfmode

\def\color#1{\expandafter
  \ifx\csname color#1\endcsname \relax \def\currentcolor{#1}%
  \else \edef\currentcolor{\csname color#1\endcsname}%
  \fi
  \pdfcolorstackpush  
  \aftergroup\pdfcolorstackpop
}
\let\currentcolor=\colorblack

如果颜色扩展到更多页,我们需要将页码设置为黑色:

\footline={\color{black}\hss\tenrm\folio\hss}

测试如下:

Surrounding text {\color{red}Red text} and more of it.

Text {\color{blue}text
     {\color{green}gree gr ee g re eg re
     \vfil\break 
     egrg ree g reeg ree greeg grr reeg ree gre eee
     green text} textik} end.

\bye

编辑我关于将页码设为黑色的第一个建议只是对新问题的简单介绍。现在,我们可以\footline=...从代码中删除该行,这样我们就可以更概念化地处理问题。

我们需要重新定义,\plainoutput以便\headline\footline \topins\footins在每一页都用黑色初始化。为此,我们在输出例程中本地设置\currentcolor\colorblack,并且我们需要用 ,对包围,\makeheadline和。这意味着以下重新定义:\makefooline\unvbox\topins\footnoterule\unvbox\footins\pdfcolorstackpush\pdfcolorstackpop

\def\plainoutput{%
  \let\currentcolor=\colorblack
  \shipout\vbox{\pdfcolorstackpush\makeheadline\pdfcolorstackpop
                \pagebody
                \pdfcolorstackpush\makefootline\pdfcolorstackpop}%
  \advancepageno
  \ifnum\outputpenalty>-20000 \else\dosupereject\fi
}    
\def\pagecontents{%
  \ifvoid\topins\else\pdfcolorstackpush\unvbox\topins\pdfcolorstackpop\fi
  \dimen0=\dp255 \unvbox255
  \ifvoid\footins\else 
    \vskip\skip\footins
    \pdfcolorstackpush\footnoterule
    \unvbox\footins\pdfcolorstackpop\fi
  \csname ifr@ggedbottom\endcsname \kern-\dimen0 \vfil \fi
}

笔记颜色堆栈与 TeX 分组机制的同步是通过 实现的\aftergroup,这有时很脆弱。Joseph 提到问题在于,\setbox=\hbox{...\aftergroup\token...}因为\aftergroup标记是在设置框后处理的,因此\pdfcolorstackpop插入到使用的材料中\setbox,而不是在 内\hbox。因此我们需要编写

\setbox0=\hbox{{\color{red}text}}

第二个例子,它很脆弱,\footnote*{\color{green}text}但你可以重新定义\footnote,让用户更舒服。

笔记2PDFTeX 提供多个堆栈,PDF 规范提供了两种类型的颜色选择器:1 0 0 r用于填充和1 0 0 R用于描边。上面的示例并行使用了两个选择器(如color.sty),但我们可以为第二个颜色选择器初始化第二个独立的颜色堆栈,并让用户可以选择正确的颜色选择器(用于文本或线条),就像 OPmac 所做的那样。但问题就在这里:xdvipdfmx使用 时没有更多独立的颜色堆栈。并且在宏级别实现两个独立的颜色堆栈稍微复杂一些(OPmac 这样做是因为它的宏比\pdfcolorstack原始宏更旧)。

相关内容