Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

While trying to use a variable pattern in TikZ with varying pattern color, I found that it did not seem to work. Here's a minimal working example:

\documentclass[tikz]{standalone}
\usetikzlibrary{patterns}
%
%
\tikzset{slope/.store in=\slope}
%
\pgfdeclarepatternformonly[\slope]{slant lines}
{\pgfpoint{-.1mm/\slope}{-.1mm}}{\pgfpoint{1.1mm/\slope}{1.1mm}}
{\pgfpoint{1mm/\slope}{1mm}}
{
    \pgfsetlinewidth{0.4pt}
    \pgfpathmoveto{\pgfpoint{-.1mm/\slope}{-.1mm}}
    \pgfpathlineto{\pgfpoint{1.1mm/\slope}{1.1mm}}
    \pgfusepath{stroke}
}
%
%
\newcommand{\theslope}{0.7}
%
\pgfdeclarepatternformonly{diagonal lines}
{\pgfpoint{-.1mm/\theslope}{-.1mm}}{\pgfpoint{1.1mm/\theslope}{1.1mm}}
{\pgfpoint{1mm/\theslope}{1mm}}
{
    \pgfsetlinewidth{0.4pt}
    \pgfpathmoveto{\pgfpoint{-.1mm/\theslope}{-.1mm}}
    \pgfpathlineto{\pgfpoint{1.1mm/\theslope}{1.1mm}}
    \pgfusepath{stroke}
}
%
%
\begin{document}
\begin{tikzpicture}
    \draw[pattern=diagonal lines,pattern color=blue] (0,0) rectangle (5,5);
    \tikzset{every path/.append style={xshift=6cm}}
    \draw[pattern=slant lines,pattern color=blue,slope=0.7] (0,0) rectangle (5,5);
\end{tikzpicture}
\end{document}

The output looks like this:

enter image description here

If I understand the system correctly, both squares should be filled with diagonal blue lines. But for the variable-slope pattern, the pattern color=blue option seems to have been ignored.

Am I doing something wrong, or is this an actual bug? In either case, is there a reasonable way for me to make it right?

share|improve this question
1  
@percusse I don't think that this is a duplicate. The linked answer isn't even talking about pattern colors. And the five pointed stars pattern doesn't react to \pattern color neither. On this note: Using the example pattern stars from the PGF manual and adding an otherwise not even used macro to the optional list of variables, the stars will stay black. –  Qrrbrbirlbel Nov 25 '12 at 2:14
    
@percusse: I'm pretty sure this is not a duplicate. First, I don't believe this issue is addressed in the answers to the linked question. Secondly, even if the answer to my question were contained in the answers already given to that question, the questions are definitely different. Mine is a question about a very specific issue, whereas the other is more generally about how to construct patterns. –  Charles Staats Nov 25 '12 at 2:42
    
I wonder if perhaps form-only patterns are already pattern schema (with a new instance created every time the pattern is used with a different pattern color), and declaring a new pattern schema removes the dependence on pattern color unless it is added back explicitly. If so, Qrrbrbirlbel's solution (below) may be the only viable one, in spite of its use of color commands inside a form-only declaration. –  Charles Staats Nov 25 '12 at 2:57
    
You are right. I'll make sure the question stays open by prodding the mods. I've provided an answer and removed the duplicate comment. –  percusse Nov 25 '12 at 3:05
add comment

2 Answers

up vote 4 down vote accepted

From the manual p.162, As such, form-only patterns do not have any colors of their own, but when it is used the current pattern color is used as its color.

The reason for this is because form-only pattern declarations without variables are frozen so TikZ can set a pattern color beforehand and the pattern inherits that stroke color. However patterns with variables are not frozen and reevaluated whenever they are called. So the color should be set each time independently. As Qrrbirlbel's answer, the color should be provided to the pattern at the time of creation.

\documentclass[tikz]{standalone}
\usetikzlibrary{patterns}
\tikzset{
    slope/.code={\edef\slope{#1}},
    slope/.default=0.5,
    slope
}
\makeatletter
\pgfdeclarepatternformonly[\tikz@pattern@color,\slope]{slant lines}
{\pgfpoint{-.1mm/\slope}{-.1mm}}
{\pgfpoint{1.1mm/\slope}{1.1mm}}
{\pgfpoint{1mm/\slope}{1mm}}
{
    \pgfsetlinewidth{0.4pt}
    \pgfpathmoveto{\pgfpoint{-.1mm/\slope}{-.1mm}}
    \pgfpathlineto{\pgfpoint{1.1mm/\slope}{1.1mm}}
    \pgfsetstrokecolor{\tikz@pattern@color}
    \pgfusepath{stroke}
}
\makeatother
\begin{document}
\begin{tikzpicture}
    \fill[pattern=slant lines,pattern color=red] (0,0) rectangle (5,5);
    \fill[pattern color=blue,pattern=slant lines,slope=0.3] (5,0) rectangle (10,5);
\end{tikzpicture}
\end{document}

enter image description here

share|improve this answer
    
Yeah, that's basically what I did but with the actual (and easy to remember) internal name of pattern color/\tikz@pattern@color. –  Qrrbrbirlbel Nov 25 '12 at 3:22
    
@Qrrbrbirlbel Yes, the problem is that /tikz/pattern color is a /.code so what you receive from the key is not a color name. –  percusse Nov 25 '12 at 3:26
    
Well, before digging through thousand files and lines of PGF code, I rather use a manual and lazy approach. –  Qrrbrbirlbel Nov 25 '12 at 3:37
    
@Qrrbrbirlbel Actually I'm lazy too, I'm searching the keywords in all PGF files at once. Whatever comes with \tikzset or \def I just go to that file :) –  percusse Nov 25 '12 at 8:08
    
Hehe, of course! I didn't meant literally going through every line and file. That could probably take days! On that note: If you add that fact that /tikz/pattern color contains code and line 14 of tikzlibrarypatterns.code.tex (\tikzoption{pattern color}{\edef\tikz@pattern@color{#1}}) to your answer, I'd safely remove my otherwise redundant answer. –  Qrrbrbirlbel Nov 25 '12 at 9:54
show 3 more comments

In my solution, I appended \def\patterncolor{#1} to the original pattern color style and added \patterncolor to the variables of \pgfdeclarepatternformonly alongside of \slope and used it with \pgfsetstrokecolor{\patterncolor}.

percusse's answer uses basically the same approach, but with the actual internal name of the /tikz/pattern color/\tikz@pattern@color which I faked with \patterncolor.

Code

\documentclass[tikz]{standalone}
\usetikzlibrary{patterns}
\tikzset{
    slope/.store in=\slope,
%    patternkolor/.store in=\patterncolor,% with the next line changed to:
                                          % pattern color/.append style={patternkolor=#1}
    pattern color/.append code={\def\patterncolor{#1}}
}

\newcommand{\theslope}{0.7}

\pgfdeclarepatternformonly{diagonal lines}
{\pgfpoint{-.1mm/\theslope}{-.1mm}}{\pgfpoint{1.1mm/\theslope}{1.1mm}}
{\pgfpoint{1mm/\theslope}{1mm}}
{
    \pgfsetlinewidth{0.4pt}
    \pgfpathmoveto{\pgfpoint{-.1mm/\theslope}{-.1mm}}
    \pgfpathlineto{\pgfpoint{1.1mm/\theslope}{1.1mm}}
    \pgfusepath{stroke}
}

\pgfdeclarepatternformonly[\slope,\patterncolor]{slant lines}
{\pgfpoint{-.1mm/\slope}{-.1mm}}{\pgfpoint{1.1mm/\slope}{1.1mm}}
{\pgfpoint{1mm/\slope}{1mm}}
{
    \pgfsetlinewidth{0.4pt}
    \pgfpathmoveto{\pgfpoint{-.1mm/\slope}{-.1mm}}
    \pgfpathlineto{\pgfpoint{1.1mm/\slope}{1.1mm}}
    \pgfsetstrokecolor{\patterncolor}
    \pgfusepath{stroke}
}

\begin{document}
\begin{tikzpicture}
    \draw[pattern=diagonal lines,pattern color=blue] (0,0) rectangle (5,5);
    \tikzset{every path/.append style={xshift=6cm}}
    \draw[pattern=slant lines, slope=0.7,pattern color=blue] (0,0) rectangle (5,5);
\end{tikzpicture}
\begin{tikzpicture}
    \draw[pattern=slant lines, slope=0.7,pattern color=green] (0,0) rectangle (5,5);
    \tikzset{every path/.append style={xshift=6cm}}
    \draw[pattern=slant lines, slope=0.2,pattern color=green] (0,0) rectangle (5,5);
\end{tikzpicture}
\end{document}

Output

enter image description here enter image description here

share|improve this answer
    
While I will wait to see if there is a solution that does not involve using color commands within the declaration of a form-only pattern, this definitely appears to be a viable workaround. –  Charles Staats Nov 25 '12 at 2:49
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.