概述

概述

概述

希望创建一个具有随机(且不连续重复)背景颜色且标题也是随机的页面。

问题

该代码有两个问题。首先,根据当前页面的背景颜色生成互补的随机颜色是无效的。其次,为章节标题中的每个单词分配唯一的互补颜色的代码也是无效的。

代码

一个相对较短的例子:

\ctxlua{math.randomseed( 101 )}
\setupcolors[state=start]

\definecolor[ThemeColourGreen][h=8DC366]
\definecolor[ThemeColourBlue][h=79C9EF]
\definecolor[ThemeColourYellow][h=FFD631]

\startMPinclusions
  color colours[];
  colours[0] := \MPcolor{ThemeColourGreen};
  colours[1] := \MPcolor{ThemeColourBlue};
  colours[2] := \MPcolor{ThemeColourYellow};
  max_colours := 3;

  color base_colour;
  color old_base_colour;

  vardef ThemeBase( expr colour ) =
    fill Page withcolor transparent(1, .85, colour );
  enddef;

  vardef RandomColour =
    colours[ round( uniformdeviate( max_colours - 1 ) ) ]
  enddef;

  vardef GenerateRandomColour( expr colour ) =
    color random_colour;

    forever:
      random_colour := RandomColour;
      exitunless random_colour = colour;
    endfor;

    random_colour
  enddef;

  base_colour := RandomColour;
  old_base_colour := base_colour;
\stopMPinclusions

\startuseMPgraphic{page:ThemeBackground}
  base_colour := GenerateRandomColour( old_base_colour );
  ThemeBase( base_colour );
  old_base_colour := base_colour;
\stopuseMPgraphic

\startuseMPgraphic{heading:ThemeTitleStyle}
  color complementary_colour;
  complementary_colour := GenerateRandomColour( base_colour );
  draw textext( \MPstring{heading:title} ) rotated 30
    withcolor complementary_colour;
\stopuseMPgraphic

\defineoverlay[page:ThemeBackground][\uniqueMPgraphic{page:ThemeBackground}]
\defineoverlay[page:ThemeStyle][\uniqueMPgraphic{page:ThemeStyle}]

\defineframed[ThemeTitleStyle][
  background=\useMPgraphic{ThemeTitleStyle},
]

% Called by processwords
\def\processword#1{%
  \setMPtext{heading:title}{#1}%
  \useMPgraphic{heading:ThemeTitleStyle}
}

\define[1]\ThemeChapterTitle{\processwords{#1}}
\setuphead[chapter][deeptextcommand={\ThemeChapterTitle}]

\starttext
  \setupbackgrounds[page][background={page:ThemeBackground}]
  \startchapter[title=One is 1st] \input knuth \stopchapter
  \startchapter[title=Two is 2nd] \input zapf \stopchapter
  \startchapter[title=Three is 3rd] \input knuth \stopchapter
  \startchapter[title=Four is 4th] \input zapf \stopchapter
  \startchapter[title=Five is 5th] \input knuth \stopchapter
  \startchapter[title=Six is 6th] \input zapf \stopchapter
\stoptext

算法

我认为该算法是:

  1. 开始 MetaPost 包含。
  2. 定义一个全局的“颜色”数组来存储可用的颜色。
  3. 生成一个随机的初始颜色,并初始化“先前”的颜色。
  4. 创建新页面。
  5. 为页面背景生成新的随机颜色。
  6. 如果新的随机颜色与之前的相同,则重复上一步。
  7. 创建页面的标题。
  8. 对于标题中的每个单词,生成一种与页面背景不冲突的互补颜色。

然而,测试时发现:

  • 章节标题绘制在页面背景之前;
  • \processwords命令并未调用\processword标题中的每个单词。

有关的

这与以下问题相关:

不同之处在于我需要生成一种随机颜色,以使其不与给定的颜色冲突。

问题

如何为章节标题中的每个单词选择随机颜色,以使所选颜色不与页面背景颜色冲突?

注意:我使用 MetaPost(而不是仅仅 ConTeXt),因为我想 (1) 跟踪页面颜色;(2) 使用命令生成轮廓字体graphictext

答案1

感谢 Marco 的评论,并意识到标题是在页面背景之前写的:

\ctxlua{math.randomseed( os.time() )}
%\ctxlua{math.randomseed( 105 )}

\setupcolors[state=start]

\definecolor[ThemeColourGreen][h=8DC366]
\definecolor[ThemeColourBlue][h=79C9EF]
\definecolor[ThemeColourYellow][h=FFD631]

\startMPinclusions
  color colours[];
  colours[0] := \MPcolor{ThemeColourGreen};
  colours[1] := \MPcolor{ThemeColourBlue};
  colours[2] := \MPcolor{ThemeColourYellow};

  % Determine the maximum colour index.
  max_colours := 0;
  forever:
    exitunless known(colours[max_colours+1]);
    max_colours := max_colours + 1;
  endfor;   

  numeric base_index;
  boolean new_page;

  base_index := 0;
  new_page := true;

  vardef ThemeBase( expr colour ) =
    fill Page withcolor transparent(1, .85, colour );
  enddef;

  % Return a random number up to max_colours - 1.
  vardef RandomColourIndex =
    (round( uniformdeviate( max_colours - 1 ) ))
  enddef;

  % Return a random number that is not equal to the given number,
  % using modulus math and the maximum number of available colours.
  vardef DiscontinuousRandomIndex( expr index ) =
    ((index + 1 + RandomColourIndex) mod (max_colours + 1))
  enddef;
\stopMPinclusions

\startuseMPgraphic{page:ThemeBackground}
  ThemeBase( colours[ base_index ] );

  % Force the ThemeTitleStyle to pick a new background colour. This is
  % required because ThemeTitleStyle is executed before ThemeBackround.
  new_page := true;
\stopuseMPgraphic

\startuseMPgraphic{heading:ThemeTitleStyle}
  % On each new page, pick a unique base colour for the background.
  if new_page:
    new_page := false;
    base_index := DiscontinuousRandomIndex( base_index );
  fi

  % Pick a colour that differs from the page background.
  complementary_index := DiscontinuousRandomIndex( base_index );

  % Draw each word in the title using one of the complementary colours.
  draw textext( \MPstring{heading:title} ) rotated 30
    withcolor colours[ complementary_index ];
\stopuseMPgraphic

\defineoverlay[page:ThemeBackground][\uniqueMPgraphic{page:ThemeBackground}]
\defineoverlay[page:ThemeStyle][\uniqueMPgraphic{page:ThemeStyle}]

\defineframed[ThemeTitleStyle][
  background=\useMPgraphic{ThemeTitleStyle},
]

% Called by applytosplitstringword for each word in the title.
\def\processword#1{%
  \setMPtext{heading:title}{#1}%
  \useMPgraphic{heading:ThemeTitleStyle}
}

\define[1]\ThemeChapterTitle{\applytosplitstringword\processword{#1}}
\setuphead[chapter][deeptextcommand={\ThemeChapterTitle}]

\starttext
  \setupbackgrounds[page][background={page:ThemeBackground}]
  \startchapter[title={One is 1st}] \input knuth \stopchapter
  \startchapter[title={Two is 2nd}] \input zapf \stopchapter
  \startchapter[title={Three is 3rd}] \input knuth \stopchapter
  \startchapter[title={Four is 4th}] \input zapf \stopchapter
  \startchapter[title={Five is 5th}] \input knuth \stopchapter
  \startchapter[title={Six is 6th}] \input zapf \stopchapter
\stoptext

然后,将随机颜色应用于标题中的每个单词,以使颜色永远不会与页面背景颜色冲突。

相关内容