1

I have just discovered externalize and want to use it in my document that contains lots of trees with shaded arrows. The arrows are shaded with some "hack" that I found on this site (unfortunately I can't seem to find the source at the moment). It works perfectly fine---albeit slow---when used in my document, but fails when externalised.

I get this error

! Extra }, or forgotten \endgroup.
\pgf@externalend ->\unskip \egroup \egroup 
                                           {\def \pgf@external@trim {0}\def ...
l.88   \end{forest}

Unfortunately I am no Tex-Expert and can't seem to figure out what's going wrong. Here is a MWE:

\documentclass[a4paper,12pt, twoside,dvipsnames]{article}

\usepackage[dvipsnames]{xcolor}

\usepackage{tikz}
\usetikzlibrary{external}
\tikzexternalize[mode=list and make, prefix=ext-tikz/]
\usepackage[external]{forest}

\usetikzlibrary{fadings, arrows.meta}


\makeatletter
\newif\iftikz@shading@path

\tikzset{
    % There are three circumstances in which the fading sep is needed:
    % 1. Arrows which do not update the bounding box (which is most of them).
    % 2. Line caps/joins and mitres that extend outside the natural bounding 
    %    box of the path (these are not calculated by PGF).
    % 3. Other reasons that haven't been anticipated.
    fading xsep/.store in=\pgfpathfadingxsep,
    fading ysep/.store in=\pgfpathfadingysep,
    fading sep/.style={fading xsep=#1, fading ysep=#1},
    fading sep=0.0cm,
    shading path/.code={%
        % Prevent this stuff happning recursively.
        \iftikz@shading@path%
        \else%
            \tikz@shading@pathtrue%
            % \tikz@addmode installs the `modes' (e.g., fill, draw, shade) 
            % to be applied to the path. It isn't usualy for doing more
            % changes to the path's construction.
            \tikz@addmode{%
                \pgfgetpath\pgf@currentfadingpath%
                % Get the boudning box of the current path size including the fading sep
                \pgfextract@process\pgf@fadingpath@southwest{\pgfpointadd{\pgfqpoint{\pgf@pathminx}{\pgf@pathminy}}%
                    {\pgfpoint{-\pgfpathfadingxsep}{-\pgfpathfadingysep}}}%%
                \pgfextract@process\pgf@fadingpath@northeast{\pgfpointadd{\pgfqpoint{\pgf@pathmaxx}{\pgf@pathmaxy}}%
                    {\pgfpoint{\pgfpathfadingxsep}{\pgfpathfadingysep}}}%
                % Clear the path
                \pgfsetpath\pgfutil@empty%                          
                % Interrupt the path and picture to create a fading.
                \pgfinterruptpath%
                \pgfinterruptpicture%
                    \begin{tikzfadingfrompicture}[name=.]
                        \path [shade=none,fill=none, #1] \pgfextra{%
                            % Set the softpath. Any transformations in #1 will have no effect.
                            % This will *not* update the bounding box...
                            \pgfsetpath\pgf@currentfadingpath%
                            % ...so it is done manually.
                            \pgf@fadingpath@southwest
                            \expandafter\pgf@protocolsizes{\the\pgf@x}{\the\pgf@y}%
                            \pgf@fadingpath@northeast%
                            \expandafter\pgf@protocolsizes{\the\pgf@x}{\the\pgf@y}%
                        };
                        % Now get the bounding of the picture.
                        \xdef\pgf@fadingboundingbox@southwest{\noexpand\pgfqpoint{\the\pgf@picminx}{\the\pgf@picminy}}%
                        \xdef\pgf@fadingboundingbox@northeast{\noexpand\pgfqpoint{\the\pgf@picmaxx}{\the\pgf@picmaxy}}%
                        %
                    \end{tikzfadingfrompicture}%
                \endpgfinterruptpicture%
                \endpgfinterruptpath%
                % Install a rectangle that covers the shaded/faded path picture.                                
                \pgfpathrectanglecorners{\pgf@fadingboundingbox@southwest}{\pgf@fadingboundingbox@northeast}%
                % Make the fading happen.
                \def\tikz@path@fading{.}%
                \tikz@mode@fade@pathtrue%
                \tikz@fade@adjustfalse%10pt
                % Shift the fading to the mid point of the rectangle
                \pgfpointscale{0.5}{\pgfpointadd{\pgf@fadingboundingbox@southwest}{\pgf@fadingboundingbox@northeast}}%
                \edef\tikz@fade@transform{shift={(\the\pgf@x,\the\pgf@y)}}%
            }%
        \fi%
    }
}

\begin{document}

\begingroup
    \centering
    \begin{forest}
        [, phantom, for children={fit=band}, s sep'+=60pt
            [ 2, name=l1 ]
            [ 2, name=r1 ]
        ]
        \path [left color=orange, right color=MidnightBlue, shading path={draw=transparent!0, dashed, -Latex}] (l1) .. controls ++(0,-1) and ++(0,-1) .. (r1);
    \end{forest}
\endgroup

\end{document}

I tried to reduce the example as much as possible, but it still remains a lot of code. The tikzset part is copied from this site, and I honestly have no idea what it does - it works though, unless forest is externalised.

Edit: The issue seems to be limited to forest, this tikzpicture can be externalised without problems:

\begin{tikzpicture}
    \path [left color=orange, right color=MidnightBlue, shading path={draw=transparent!0, dashed, -Latex}] (0,1) .. controls ++(0,-1) and ++(0,-1) .. (1,1);
\end{tikzpicture}
  • Forest and externalisation do not always mix well, even under more auspicious conditions. I really don't think it is surprising this would fail. I'm not sure how the fading from picture stuff is implemented, but I'd worry it may be optimised away. I'd suggest disabling externalisation for trees which use this feature. – cfr Feb 21 '18 at 3:09
  • Although that's probably not why if you can use the arrow in tikzpicture environments, I guess. Does it work with externalisation there? Or is it a Forest-specific issue? – cfr Feb 21 '18 at 3:12
  • @cfr It seems to be limited to forest. A single shaded arrow in a tikzpicture could be externalised without problems. I added an example to the question. – FAS Feb 21 '18 at 9:43
  • If you really need it and can't just disable externalisation for affected trees, I'd suggest emailing Forest's author. If you could find the source of the hack, you could also ask that person. – cfr Feb 22 '18 at 0:53
  • tex.stackexchange.com/a/137438 is likely your source? – cfr Feb 22 '18 at 1:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.