测试当前颜色是否为黑色

测试当前颜色是否为黑色

下面的 MWE 通过\TypsetInBlueOnlyIfCurrentColorIsBlack宏完全实现了我想要的功能:

在此处输入图片描述

\TypsetInBlueOnlyIfCurrentColorIsBlack旨在将其参数的颜色更改为蓝色,仅有的如果当前颜色黑色。否则,将使用当前颜色。

问题:

  • 我期望xcolor会提供一个宏来执行此操作,但找不到它。因此,想知道这种方法是否存在任何明显的问题,或者是否提供了官方接口。

参考:

代码:

\documentclass{article}
\usepackage{xcolor}
\usepackage{xstring}

%% At this point the default color is black so save that.
\edef\BlackColor{\csname\string\color@.\endcsname}

\makeatletter
\newcommand{\@CurrentColor}{}% Make sure we are not using an existing macro
\newcommand*{\TypsetInBlueOnlyIfCurrentColorIsBlack}[1]{%
    \edef\@CurrentColor{\csname\string\color@.\endcsname}% Get current color
    \IfStrEq{\@CurrentColor}{\BlackColor}{%
        {\bfseries\ttfamily\textcolor{blue}{#1}}% current color IS black
    }{%
        {\bfseries\ttfamily#1}%  current color is NOT black
    }%
}
\makeatother

\begin{document}
    Following should be in blue:
    \TypsetInBlueOnlyIfCurrentColorIsBlack{blue}.

\color{red}
    Following should be in red:
    \TypsetInBlueOnlyIfCurrentColorIsBlack{red}.

\color{blue}
    Following should also be in blue:
    \TypsetInBlueOnlyIfCurrentColorIsBlack{blue}.
\end{document}

答案1

接口?expl3当然是使用!

\storecolor可以存储需要进行比较的颜色表示。

我定义了一个通用的比较命令,并且也定义了你的命令作为特例。

在开始文档时,传递给的列表中的每种颜色\storecolors也会black在内部表示中进行转换并存储在属性列表中。这是为了提高效率,但实际上并非必要:它节省了评估中的几个步骤。

主命令转换内部表示中的当前颜色,并将其与作为第一个参数给出的颜色进行比较(仅限命名的颜色,但可以概括)。如果测试返回 true,则使用作为第二个参数指定的颜色来打印第三个参数;否则不执行任何颜色更改。

\documentclass{article}
\usepackage{xcolor}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\perhapschangecolor}{mmm}
 {% #1 = color to compare with current
  % #2 = color to use if match
  % #3 = text
  \peter_color_change:nnn { #1 } { #2 } { #3 }
 }
% the same but with black and blue preset
\NewDocumentCommand{\TypsetInBlueOnlyIfCurrentColorIsBlack}{m}
 {
  \perhapschangecolor{black}{blue}{#1}
 }
\NewDocumentCommand{\storecolors}{m}
 {% black is always stored
  \AtBeginDocument { \peter_color_store:n { black,#1 } }
 }

\prop_new:N \g_peter_color_stored_prop
\tl_new:N \l__peter_color_current_tl

\cs_new:Nn \peter_color_store:n
 {
  \hbox_set:Nn \l_tmpa_box
   {
    \clist_map_inline:nn { #1 }
     {
      \color{##1}
      \driver_color_pickup:N \l_tmpa_tl
      \prop_gput:NnV \g_peter_color_stored_prop { ##1 } \l_tmpa_tl
     }
   }
 }

\cs_new_protected:Nn \peter_color_change:nnn
 {
  \driver_color_pickup:N \l__peter_color_current_tl
  \prop_if_in:NnTF \g_peter_color_stored_prop { #1 }
   {% more efficient test
    \str_if_eq:eeTF
     { \l__peter_color_current_tl }
     { \prop_item:Nn \g_peter_color_stored_prop { #1 } }
     { \textcolor{#2}{#3} }
     { #3 }
   }
   {
    \hbox_set:Nn \l_tmpa_box
     {
      \color{#1}
      \driver_color_pickup:N \l_tmpa_tl
      \tl_gset_eq:NN \g_tmpa_tl \l_tmpa_tl
     }
    \driver_color_pickup:N \l_tmpa_tl
    \str_if_eq:eeTF { \g_tmpa_tl } { \l_tmpa_tl }
     { \textcolor{#2}{#3} }
     { #3 }
   }
 }
\ExplSyntaxOff

\storecolors{red!60}

\begin{document}

    Following should be in blue:
    \TypsetInBlueOnlyIfCurrentColorIsBlack{blue}

\color{red}
    Following should be in red:
    \TypsetInBlueOnlyIfCurrentColorIsBlack{red}

\color{blue}
    Following should be in blue:
    \TypsetInBlueOnlyIfCurrentColorIsBlack{blue}

\color{black}
    Following should be in pale red:
    \perhapschangecolor{black}{red!60}{red!60}

\color{red!60}
    Following should be in pale red:
    \perhapschangecolor{black}{red!60}{red!60} 

\color{blue}
    Following should be in blue:
    \perhapschangecolor{black}{red!60}{blue}

    % blue has not been stored, but the test succeeds as well
    Following should be in pale red:
    \perhapschangecolor{blue}{red!60}{red!60}

\end{document}

在此处输入图片描述

相关内容