pgf-tikz / pgf

A Portable Graphic Format for TeX
https://pgf-tikz.github.io/
1.14k stars 108 forks source link

Multiple definitions of cyan color in patterns library #993

Open lanpirot opened 3 years ago

lanpirot commented 3 years ago

When using the patterns package with patterns of cyan color, the pattern will be rendered in a different cyan color, than the filling of a path.

In the MWE below, I expect a mono-colored rectangle, as the pattern color is identical to the fill color. This also happens, when using the patterns.meta package.

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{patterns} 

\begin{document}
    \begin{tikzpicture}
        \def\myrect{(0,0) rectangle (5,5)}
        \path [fill=cyan] \myrect;
        \pattern [pattern=north west lines, pattern color=cyan] \myrect;
    \end{tikzpicture}
\end{document}

image

There probably is an alternative definition of cyan in some sub-library. Maybe one definition of cyan is #00FFFF/{0.0, 1.0, 1.0} and the other #00B7EB/{rgb}{0.0, 0.72, 0.92}? https://latexcolor.com mentions the latter as "Cyan (process)".

hmenke commented 3 years ago

One of them must be using the wrong color model. As a workaround you can add

\usepackage[rgb]{xcolor}

before loading tikz.

ilayn commented 3 years ago

I don't think this is a color issue but a blend issue. Does it also happen with other colors too, say, yellow or magenta? You are probably seeing the background color through the hatch lines.

lanpirot commented 3 years ago

I tested it with blue, red, green and black. There the fill and pattern color are identical. No, the background color cannot be seen behind the hatch lines (in my real document, I have thicker pattern lines and noticed, that different cyan colors are produced).

ilayn commented 3 years ago

You need to test with mixtured colors hence my proposition yellow and magenta. The primary color channels are saturated by default hence you won't see any difference.

lanpirot commented 3 years ago

Both magenta and yellow are similarly broken.

My current workaround is just redefining cyan before the picture.

hmenke commented 3 years ago

No, it's a color issue. I had a look at the uncompressed PDF and the lines are drawn with 1 0 0 0 k, i.e. in CMYK color model, but “uncolored” patterns always have /DeviceRGB in them. Stupid xcolor mixes color models by default.

ilayn commented 3 years ago

Hmm, then I can't find an explanation for this

\documentclass{standalone}
%\usepackage[usedvipsnames]{xcolor}
\usepackage{tikz}

\usetikzlibrary{patterns} 

\begin{document}
    \begin{tikzpicture}
        \fill[fill=cyan, pattern=north west lines, pattern color=cyan] (0,0) rectangle (5,5);
    \end{tikzpicture}
\end{document}

image

Maybe I'm missing a detail

lanpirot commented 3 years ago

Hmm, then I can't find an explanation for this

\documentclass{standalone}
%\usepackage[usedvipsnames]{xcolor}
\usepackage{tikz}

\usetikzlibrary{patterns} 

\begin{document}
    \begin{tikzpicture}
        \fill[fill=cyan, pattern=north west lines, pattern color=cyan] (0,0) rectangle (5,5);
    \end{tikzpicture}
\end{document}

image

Maybe I'm missing a detail

There is no fill in your rectangle (either no fill, or default white fill idk enough about tikz). What I meant is that somehow the fill color and pattern color are not identical. I.e. the rightmost rectangle of this MWE should be mono-colored. patterns

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{patterns} 

\begin{document}
    \begin{tikzpicture}
        \fill [fill=cyan] (0,0) rectangle (5,5);
        \pattern [pattern=north west lines, pattern color=cyan] (5,0) rectangle (10,5);
        \fill [fill=cyan] (10,0) rectangle (15,5);
        \pattern [pattern=north west lines, pattern color=cyan] (10,0) rectangle (15,5);
    \end{tikzpicture}
\end{document}
muzimuzhi commented 3 years ago

The fill=cyan results in 1 0 0 0 k, i.e. in CMYK color space, while pattern color=cyan results in 0 1 1 in DeviceRGB color space. What you see is the rendering difference between these two colors. It seems pgf always writes /Pattern /DeviceRGB and converts pattern color to rgb.

hmenke commented 3 years ago

We can make “uncolored” patterns obey the global color model, but that wouldn't help with the problem here because the user then still has to select cmyk (or rgb) globally by loading xcolor. The main issue here is that xcolor mixes color models without warning.

ilayn commented 3 years ago

Why would xcolor use different color mode for the same name? How does it understand when to mix? If you select a color from one model like dvipsnames and one from cmyk etc then there is no other way to not to mix models. So I am quite surprised that the same name leads to different color spaces. As tested above, yellow and magenta leads to the same problem.

muzimuzhi commented 3 years ago

So I am quite surprised that the same name leads to different color spaces. As tested above, yellow and magenta leads to the same problem.

@ilayn That's not the case.

  1. By default, xcolor colors will in different color spaces. For example, red is in RGB and cyan in CMYK.
  2. But PDF allows only one color space per "uncolored" pattern. See PDF Ref. v1.7, sec. 4.6.2, unnumbered subsection "Uncolored Tilling Patterns".
  3. Hence pgf has to choose a color space for every "uncolored" pattern, which at present is always DeviceRGB, and do color conversions when needed. It is the PDF constraint and the resulting color conversions that result in "same name leads to different color spaces".
ilayn commented 3 years ago

Yes because in cyan and (that's the reason I asked), yellow, magenta black are primary colors of CMYK. So it makes sense to define it wherever it is primary. This is not what I am confused about; whenever you say cyan it has a single definition right? And there are no other colors here. So both cyans should have mapped to the same warped output. How did it decide to pick one ? So TikZ converted it then it's not xcolor's problem. Otherwise this is a shortcoming of the standard and not TikZ or xcolor's

muzimuzhi commented 3 years ago

whenever you say cyan it has a single definition right?

Not exactly.

Firstly, xcolor supports defining named color in multiple color spaces. And this is how base colors, those documented in texdoc xcolor, sec. 4.1 "Base colors (always available)", are defined. See xcolor.sty at texlive/r41044, lines 1430 to 1451.

Secondly, even if a color is defined in only one color space, it could be converted to another. So strictly speaking, no matter how color mycolor is defined, \usepackage[rgb]{xcolor} \color{mycolor} and \usepackage[cmyk]{xcolor} \color{mycolor} will write different colors to pdf.

Lastly, due to the differences in conversion functions, rounding errors, and rendering effects, I think there is no promise that readers can render an xcolor color used in different color spaces, either caused by definition or by conversion, indistinguishable.

Edit: IMHO, this might be a shortcoming of the standard, or one might think xcolor should stick to only one color space throughout a document by default (so pgf could get and set it for "uncolored" patterns).

ilayn commented 3 years ago

We are saying the same thing.

xcolor is not saying at any point "you know what I'm going to change the model of cyan". Once the package is set the definitions are read and unless modified, all invocations are (should be) the same at runtime. So it is not changing the model, it seems to me that TikZ is overpromising here.

We should probably mention this in the docs somewhere that if you are going to mix and match stick to RGB definitions of the colors. And if you want to print load it with CMYK.

muzimuzhi commented 3 years ago

More to do (but do not know when to implement):

An interesting finding (maybe just to me): According to wikipedia, cyan do has two "definitions",

While both the additive secondary and the subtractive primary are called cyan, they can be substantially different from one another. Cyan printing ink is typically more saturated than the RGB secondary cyan, depending on what RGB color space and ink are considered.

This basically explains the different two colors we see in OP's example.

hmenke commented 3 years ago

I think this “magic inference” of the color model from the chosen pattern color is not a good idea. First of all it doesn't work for Plain TeX, because there is no standard way of handling colors and color models and second this is too ambiguous in my opinion. For example, what is the resulting color model of cyan!50!red? Can you tell me without having to read the manual or try and see? My take on this is to adhere to the global color model (or RGB if none is chosen) and document that people better select their color model. Maybe we should even force the xcolor color model to RGB if none was selected to prevent these problems in the future, although that would potentially affect old documents quite severely.

muzimuzhi commented 3 years ago

For printing purposes, users might expect all colors in CMYK.

josephwright commented 3 years ago

As an aside, you might want to look at the work in l3color on multiple models: it's now part of l3kernel so generally available in LaTeX. Patterns are not included just yet, but they are on the to-do list.