olsak / OpTeX

OpTeX - LuaTeX format with extended Plain TeX macros
http://petr.olsak.net/optex/
35 stars 13 forks source link

Problem with color of some text nodes in Tikz #73

Closed ldonetti closed 2 years ago

ldonetti commented 2 years ago

With the new (1.04) version of OpTeX I found a problem with the color of the text in some TikZ nodes. The issue did not happen with the previous versions of OpTex so I think it might be related to the changes in the color handling.

A minimal example showing the issue is the following:

\load [tikz]
\tikzpicture
% If I uncomment the following line, "test" is correctly typeset in red
%\leaders\hrule height0pt depth0pt\hskip0pt\relax
\node[red] {test};
\endtikzpicture
\bye

I expect the text test to be typeset in red, but instead it is black.

I had a similar problem with ConTeXt in the past and I found a workaround on tex.stackexchange. Trying to adapt the ConTeXt workaround, I found that if I uncomment the line starting with \leaders, the text is correctly typeset in red. However, I can't really understand what's going on, I don't know if the workaround can be simplified or if it can be considered a proper fix.

vlasakm commented 2 years ago

Thank you for the report and deep analysis. I am responsible for the current behaviour, but the coloring design is very much like the ConTeXt one, so, as you found out, same things apply.

The issue is, that OpTeX's new color handling is trying to be smart and emits color changing PDF literals only when they are really needed. For example \Blue\Red\Blue\Red\Blue is essentially free. It also starts every page with a clean slate, and has to set even the default color (which is black).

TikZ handles its colors by itself. It doesn't use the high level OpTeX interface and instead emits its own color changing PDF literals. So when it is time to typeset test in red, TikZ directly emits "change color to red". Then much later, OpTeX comes and sees that there is a t (from the wordtest) that has to be typeset and the default color (black) has not yet been set, so it forces it.

\leaders prevents the issue, because OpTeX sets the black color before the \leaders not before the t, and so the earlier red setting is in fact the one that applies. But anything which OpTeX considers colorable would work, such as a glyph/letter.

Now how to solve this problem. The possibilities, which don't' require users changing their docuements:

1) Modify TikZ to always something emit nonintrusive but colorable, so current OpTeX color is forcibly set before the TikZ picture, not lazily in the middle of it. 2) Consider all PDF literals as potentially color changing. This is almost like the previous one, but nothing new colorable is inserted, just the color change emitted by TikZ is considered as colorable. (This was also discussed in the original pull request, where we decided against it, https://github.com/olsak/OpTeX/pull/57#issuecomment-869174015, https://github.com/olsak/OpTeX/pull/57#issuecomment-880214750). But moreover this also applies to the middle of TikZ picture, where there might also be mixed use of OpTeX / TikZ color. 3) Make TikZ use OpTeX coloring. Would be nice, but this is very much out of scope.

I like 2) the most, and because TikZ seems very thorough withs its PDF color changes, saves and restores, hopefully there shouldn't be problems even in more complex situations. For example this works with 2):

\fontfam[lm]
\load [tikz]

\tikzpicture
\node at (-2, 0) [red]   {text \Blue test \Red};
\node at ( 0, 0) [blue]  {m\Brown ore};
\node at ( 2, 0) [yellow]{tests};
\endtikzpicture
after
\bye

2021-08-27-173804