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.

This is a follow up question to Adding nodes in a style

If I use the following code, I obtain a strange behavior:

Code

\documentclass[tikz]{standalone}
\usetikzlibrary{matrix,fit,backgrounds}
\tikzset{
  fill first cell/.style={
    append after command={
      \pgfextra
        \pgfonlayer{background}
          \tikzset{every node/.style=}
          \node[fit=(\tikzlastnode-\the\pgfmatrixcurrentcolumn-\the\pgfmatrixcurrentrow), inner sep=+0pt, fill=#1] {};
        \endpgfonlayer
      \endpgfextra
    }
  },
  fill first cell/.default=red!7
}
\begin{document}
\begin{tikzpicture}
\matrix (m) [matrix of nodes, fill first cell] {
  1 & 2 \\
  3 & 4 \\
};
\end{tikzpicture}
\end{document}

Output

output

Desired output

desired output

Everything looks as expected when printed. However, the PDF viewer shows all the letters slightly bolder. This behavior can be seen in the two outputs shown above. I strongly suspect that the content of the matrix is drawn twice.

I know it is drawn at least once after the code from my style. To prove it, remove the background layer command and the red rectangle will still appear in the background from the number 4.

Furthermore, if I use a pgfnode instead of a Tikz node the problem does not appear.

What is causing this behavior and how can I fix it?

Edit

With the help of @percusse, @DavidCarlisle, and @AndrewSwann I have been able to find a shorter MWE as well as a better way to check for the existence of the bug.

The following code exhibits the bug:

\documentclass[tikz]{standalone}
\begin{document}
\showoutput
\begin{tikzpicture}
\path node {x}
      \pgfextra
        \node{};
      \endpgfextra
;
\end{tikzpicture}
\end{document}

By using the following command pdflatex mwe.tex | grep cmr/ | wc -l you can check how many times the character x is being printed. 1 means no bug, 2 means bug.

By playing with the content of \pgfextra ... \endpgfextra I have made some additional observations:

  • \pgfnode{rectangle}{node}{}{}{} does not exhibit the bug, so it seems to be a Tikz problem
  • \draw (0,0) -- (0,1) -- (1,1) -- (1,0) -- cycle; does not exhibit the bug either
  • \draw (0,0) -- (0,1) -- (1,1) -- (1,0) -- cycle node {}; does exhibit the bug
  • \draw (0,0) -- (0,1) -- (1,1) -- (1,0) -- cycle; \node {}; does not exhibit the bug

The lines composing the path do not seem to be drawn twice. However, in the following code, both nodes, x and y, are printed twice.

\documentclass[tikz]{standalone}
\begin{document}
\showoutput
\begin{tikzpicture}
\path node {x} node {y}
      \pgfextra
        \node{};
      \endpgfextra
;
\end{tikzpicture}
\end{document}

Workaround (Obsolete, see the solution instead)

This question is not yet answered, however there is now a workaround available: just add a \path; before the \node{}; inside \pgfextra.

Solution

As mentionned in Adding nodes in a style and in @MarkWibrow's answer, the problem was a lack of protection of the outer path in \pgfextra. The classical way to protect is to use \pgfinterruptpath. This is however not enough when inserting TikZ nodes and it must be coupled with \setbox\tikz@figbox=\box\pgfutil@voidb@x. The fixed MWE looks like:

\documentclass[tikz]{standalone}
\begin{document}
\showoutput
\begin{tikzpicture}
\path node {x}
      \pgfextra
        \pgfinterruptpath
          \makeatletter\setbox\tikz@figbox=\box\pgfutil@voidb@x\makeatother
          \node{};
        \endpgfinterruptpath
      \endpgfextra
;
\end{tikzpicture}
\end{document}

The \pgfinterrupath serves two purposes. If on top of a node x we were drawing a path, it would make sure the node y would not delete it. In our case, it is needed for \makeatletter\setbox\tikz@figbox=\box\pgfutil@voidb@x\makeatother not discard the x node.

This solution works for TikZ/PGF version 2.10 and the CVS version. The problem mentionned by @MarkWibrow in the CVS version was the following: When the fit node was encountered, the nodes of the matrix were all inserted in the background layer instead of the main layer where they belong. This was a bug (http://sourceforge.net/p/pgf/bugs/260/) that is now fixed. If using exclusively the CVS version (after September 9 2013) the following code works:

\documentclass[tikz]{standalone}
\begin{document}
\showoutput
\begin{tikzpicture}
\path node {x}
      \pgfextra
        \pgfinterruptpath
          \node{};
        \endpgfinterruptpath
      \endpgfextra
;
\end{tikzpicture}
\end{document}
share|improve this question
    
This looks like a viewer issue. Add \matrix (m) at (0,0) [matrix of nodes] { 1 & 2 \ 3 &|[inner sep=0pt,text=yellow]| 4 \}; to your code and there is no leak. There is however an issue of aliasing which is common in various viewers. See this tex.stackexchange.com/q/49614/3235 As far as I can see there is no redrawing in your code. –  percusse Sep 1 '13 at 14:48
    
Thanks for the link, I will check it out. I am not sure what the code snippet should do. I do really think the content of the matrix is written twice given that the background layer has no effect. –  Nicolas Dudebout Sep 1 '13 at 15:03
    
Background layer only draws the red rectangle after the matrix is drawn. There is no replication of the actual matrix content. –  percusse Sep 1 '13 at 15:04
    
Try removing the two pgfonlayer lines and see that the number 4 stays on top of the red rectangle even though the rectangle is supposedly drawn after. –  Nicolas Dudebout Sep 1 '13 at 15:05
    
Not really you are using append after command. That makes the node created but not placed immediately such that you can use its name and position for future path without actually drawing it so layering is redundant here. You can check \pgfpositionnodelater etc. in the manual for more low level explanations. –  percusse Sep 1 '13 at 15:09

3 Answers 3

up vote 3 down vote accepted

All nodes in a path are positioned in a special box called \tikz@figbox. When something is done with nodes, something like the following occurs at some point:

\setbox\tikz@figbox=\hbox\bgroup%
   \setbox\pgfutil@tempboxa=\copy\tikz@figbox%
   \unhbox\pgfutil@tempboxa%
   %
   % Code inserting/positioning node content
   %
\egroup%

At the end of a path the box is used and becomes void (which is why the insertion of \path; seems to work).

In the case given above the OP starts a path (a \node is a special kind of path - the \path is inserted automatically) inside another path (a \matrix is a type of node, which is, therefore, a kind of path).

As the \tikz@figbox contents from the matrix are not voided before the \node command, the matrix contents are also inserted into the box for the node contents. It is possible to put \setbox\tikz@figbox=\box\pgfutil@voidb@x before the node command to see that this corrects the issue.

Effectively what the OP has done (more or less) is this:

\newbox\mybox
\setbox\mybox=\hbox{matrix}
{\setbox\mybox=\hbox{\copy\mybox\space node}1. \box\mybox}
2. \box\mybox

Which produces

1. matrix node 2. matrix

I personally don't see it as a bug, the approach given by the OP is not really a good way to do things. \pgfextra has to be used with care if other paths/pictures are being used (e.g., using \pgfinuterruptpath \endpgfinterruptpath). Although in this case it doesn't solve the problem.

Either way, the duplication does not occur with the latest CVS versions, but it is also the case that the append after command key doesn't produce the required effect either.

share|improve this answer
    
Thank you for your answer. I follow the reasonning but I fail to understand what is your recommended course of action. I also do not know what is my "approach" is it the append after command or the workaround that is clearly a hack? –  Nicolas Dudebout Sep 2 '13 at 15:00
    
If you think using append after command is a bad idea, I would welcome your input in the question mentionned at the beginning of the question. This is what triggered it all. –  Nicolas Dudebout Sep 2 '13 at 15:03
    
@NicolasDudebout anything involving starting path inside another path without being careful is likely to result in unexpected results or errors. There is a /tikz/row <row> column <column> style (see "Cell Styles and Options" in the manual) which could be used in this MWE case (but obviously the cells have to specified manually), and layers wouldn't be needed. If this isn't satisfactory, or doesn't generalize sufficiently then AFAIK it cannot be done any other way than in the "Adding nodes in a style" question. –  Mark Wibrow Sep 4 '13 at 16:39
    
That was the point of my question. I was asking what care was needed to use a node inside pgfextra. I have extracted the fix from your answer for easy reference in the future. Thank you for your help. Regarding the row and column styles, it does not work in my case as I am working on extending these to have real row and column support (not the every row that does not have a real notion of row but just applies to every node in a row). –  Nicolas Dudebout Sep 5 '13 at 14:18
    
let us continue this discussion in chat –  percusse Sep 6 '13 at 14:19
\documentclass[tikz]{standalone}
\usetikzlibrary{matrix,fit,backgrounds}
\tikzset{
  fill first cell/.style={
    append after command={
      \pgfextra
        \pgfonlayer{background}
          \tikzset{every node/.style=}
          \node[fit=(\tikzlastnode-\the\pgfmatrixcurrentcolumn-\the\pgfmatrixcurrentrow), inner sep=+0pt, fill=#1] {};
        \endpgfonlayer
      \endpgfextra
    }
  },
  fill first cell/.default=red!7
}
\begin{document}
\showoutput
\begin{tikzpicture}
\matrix (m) [matrix of nodes, fill first cell] {
  1 & 2 \\
  3 & 4 \\
};
\end{tikzpicture}
\end{document}

Then look at the log

$ grep "cmr/m/n/10" tkmatrix.log
.........................\OT1/cmr/m/n/10 1
.........................\OT1/cmr/m/n/10 2
.........................\OT1/cmr/m/n/10 3
.........................\OT1/cmr/m/n/10 4
.........................\OT1/cmr/m/n/10 1
.........................\OT1/cmr/m/n/10 2
.........................\OT1/cmr/m/n/10 3
.........................\OT1/cmr/m/n/10 4

You are correct in your observation that the matrix is drawn twice.

share|improve this answer
    
I did not know I could find this information somewhere. Thank you for showing me this. Any idea about what might be the cause? –  Nicolas Dudebout Sep 1 '13 at 15:24
    
@NicolasDudebout no but I thought I might nudge those who do know something about tikz to look a bit deeper:-) –  David Carlisle Sep 1 '13 at 15:26
    
Certainly appreciated and really helpful in confirming my impression. Thanks –  Nicolas Dudebout Sep 1 '13 at 15:27
    
+1 for the TikZ silver badge! :) –  Paulo Cereda Sep 2 '13 at 0:40

The matrix is being drawn twice and this is caused by the presence of a drawing command in your \pgfextra. Here is a test file to show the behaviour.

\documentclass[tikz]{standalone}

\pdfcompresslevel=0

\tikzset{ff/.style={append after command={\pgfextra\node {};\endpgfextra}}}

\begin{document}
\begin{tikzpicture}
\node[ff] (0,0) {XY};
\end{tikzpicture}
\end{document}

pgfcompresslevel=0 means that the resulting pdf file is in more readable form. From the above code you get the following pdf code twice in the output

BT
/F8 9.9626 Tf 3.321 3.321 Td [(XY)]TJ
ET

the first on lines 26-28, the second on lines 51-53. Removing \node {}; from the pdfextra material, produces a pdf file with only one occurance of the printing command.

Note that I have not used any backgroud, fit or matrix libraries for this.

share|improve this answer
    
It confirms what I have seen. Replacing \node {}; with \pgfnode {rectangle}{north}{}{foo}{Foo} also does not double the printing. It seems to be something in Tikz rather than PGF causing the problem. Not just drawing per se. –  Nicolas Dudebout Sep 1 '13 at 15:32
    
@NicolasDudebout That is a good observation about \node vs. \pgfnode. –  Andrew Swann Sep 1 '13 at 15:55
    
@NicolasDudebout I've checked the code a little and the problem is that the main node is suspended (but not interrupted) so when the additional node is finished it also finishes the main node. But since it is in the append after command it is resumed once again and reprinted afterwards. Quite perplexing indeed, I didn't know that before. \pgfnode doesn't have a specific path operation so waits until the main node issues a path operation. I really don't know how to explain it in proper terms hahah. Great stuff. –  percusse Sep 1 '13 at 18:44
    
Should I report a bug somewhere? –  Nicolas Dudebout Sep 1 '13 at 18:45
    
Actually, I tried putting a path instead of a pgfnode or a node and the problem is not here. I used \draw (0,0) -- (0,1) -- (1,1) -- (1,0) -- cycle; for example and I do not get doubling. –  Nicolas Dudebout Sep 1 '13 at 18:54

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.