Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Meta-decoration states are missing width of final decoration state #1338

Open
schtandard opened this issue Jun 7, 2024 · 1 comment
Open

Comments

@schtandard
Copy link
Contributor

Brief outline of the bug

Many decorations fill up "missing" path length (i.e. a bit of the path at the end that cannot be filled by the other states) in the final state, e.g. by saying

  \state{final}
  {
    \pgfpathlineto{\pgfpointdecoratedpathlast}
  }%

When used in a meta-decoration, this state seems to be omitted, leading to the meta-state not filling its specified width. Over the whole meta-decoration these missing parts can accumulate to a substantial length.

Minimal working example (MWE)

In this example, the final bit of the first centimeter of the decorated path should be a straight line, coming from the final state of the zigzag decorator. This seems to be omitted, however, the second state starts (and finishes) too early. Thus, the decoration does not cover the expected width of 2 cm.

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{decorations.pathmorphing}

\pgfdeclaremetadecoration{too short}{first}
  {%
    \state{first}[width=1cm, next state=second]
      {
        \decoration{zigzag}
      }%
    \state{second}[width=1cm, next state=final]
      {
        \decoration{curveto}
        \afterdecoration{
            \pgfusepath{stroke}
          }
      }%
    \state{final}{}
  }

\begin{document}

\begin{tikzpicture}
  \draw [help lines] (0,-1) grid (2,1);
  \path [decorate, decoration=too short] (0,0) -- (5,0);
\end{tikzpicture}

\end{document}

image

@schtandard
Copy link
Contributor Author

After some more tinkering, it looks like there is more to this. The decoration's final seems to be executed, but \pgfpointdecoratedpathlast points to the wrong coordinate, namely to (0pt,0pt) in the transformed coordinate system.

Additionally, the length of the input path seems to make a difference somehow, though this may be a separate bug: When it matches the decoration's width exactly, the resulting path is extended to the correct end point (though the decoration is still wrong). While this should not make a difference once the final transformation is fixed, it is a bit weird that the output path is apparently extended past the \pgfusepath in the meta-decoration's definition.

Here's an MWE illustrating this. foo steps to the side, draws a straight line parallel to the original one, and curves back to the line in the last 0.5 cm. In the meta-decoration it curves back to the end of the main state instead. When the input path has the length 2 cm, the result is extended. When the input path is longer, this (correctly) does not happen.

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{decorations.pathmorphing}

\pgfdeclaredecoration{foo}{initial}
  {%
    \state{initial}[
        width=0pt,
        next state=main,
        persistent precomputation={%
          \pgfmathsetlengthmacro\mainlength{\pgfdecoratedpathlength - .5cm}%
        },
      ]{
        \pgfpathlineto{\pgfpoint{0pt}{10pt}}
      }%
    \state{main}[width=\mainlength, next state=final]
      {
        \pgfpathlineto{\pgfpoint{\mainlength}{10pt}}
      }%
    \state{final}
      {
        \pgfpathcurveto
          {\pgfpoint{.1cm}{10pt}}
          {\pgfpoint{.4cm}{10pt}}
          {\pgfpointdecoratedpathlast}
      }%
  }

\pgfdeclaremetadecoration{too short}{first}
  {%
    \state{first}[width=1cm, next state=second]
      {
        \decoration{foo}
      }%
    \state{second}[width=1cm, next state=final]
      {
        \decoration{curveto}
        \afterdecoration{
            \pgfusepath{stroke}
          }
      }%
    \state{final}{}%
  }

\begin{document}

\begin{tikzpicture}
  \draw [help lines] (0,-2) grid (2,1);
  \draw [decorate, decoration=foo] (0,0) -- ++(1,0);
  \path [decorate, decoration=too short] (0,-1) -- ++(2.1,0);
  \path [decorate, decoration=too short] (0,-2) -- ++(2,0);
\end{tikzpicture}

\end{document}

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

1 participant