6

I have a couple of questions about text decoration in tikz when the text is longer than the path to decorate:

  1. Why doesn't the decoration begin at the beginning of the line (whereas it is correctly truncated at the end)?
  2. Why there is too much/not enough horizontal space between letters when the text is bent, if a negative raise is used?

See here:

\documentclass[a4paper]{book}
\usepackage{tikz}
\usetikzlibrary{decorations.text,shapes}
\usetikzlibrary{matrix}
\begin{document}
    \begin{tikzpicture}
    \matrix[column sep=7em,row sep=7ex]{%
    \draw[postaction={decorate,decoration={text along path,text align=center,
        text={Why doesn't this begin at the beginning of the line?}}}]
        (0,0) to (1,0);
        &
    \draw[postaction={decorate,decoration={text along path,text align=center,
        text={Idem as the previous one}}}]
        (0,0) to[bend right] (1,0);
        &
    \draw[postaction={decorate,decoration={text along path,text align=center,
        text={Idem as the previous one}}}]
        (0,0) to[bend left] (1,0);
        \\
    \draw[postaction={decorate,decoration={text along path,text align=center,raise=-3ex,
        text={Idem as the previous one}}}]
        (0,0) to (1,0);
        &
    \draw[postaction={decorate,decoration={text along path,text align=center,raise=-3ex,
        text={Moreover, why is there so much space between the bended letters?}}}]
        (0,0) to[bend right] (1,0);
        &
    \draw[postaction={decorate,decoration={text along path,text align=center,raise=-3ex,
        text={Moreover, why is there so little space between the bended letters?}}}]
        (0,0) to[bend left] (1,0);
        \\
    };
    \end{tikzpicture}
\end{document}

enter image description here

Edit:

Symbol 1 explained why this happens, but I still don't understand the reason.

Wouldn't the following one be a more coherent behavior?

enter image description here

Or even the following one?

enter image description here enter image description here enter image description here

Is it only because it's too difficult to do it automatically?

P.S. = This question arises because I'd like to explain what I intended with "horizontally squashed" in a comment of mine to this cfr's answer.

5

1.

If the text is too long, PGF will insert a negative left indent (and/or right indent, depends on align=right/center/left). So it looks like the text starts earlier.

However, PGF maintains a length called \pgfdecoratedremainingdistance which is the remaining distance on the input path. (manual page 1001.) By the design of decoration, it is a finite state automaton and it will terminate if \pgfdecoratedremainingdistance is less than 1pt. (pgfmoduledecorations.code.tex line 789.)

Once the automaton terminates, PGF will finalize this path and there is no chance to print the remaining texts. (Perhaps you can deceive PGF by making this length positive. But the real question is: where are you going to be?)

2.

Because the spacing/position is done with respect to a coordinate system whose x-axis is the path itself. No matter you lower or raise the character, their widths remain the same.

For edited part

1

add this

\makeatletter
\pgfutil@namedef{pgf@decorate@@text along path@left indent@options}{
    width={max(\pgf@lib@dec@text@indent@left,0)},next state=scan
}

2

add this instead

\makeatletter
\pgfkeys{
    /pgf/decoration automaton/width/.code={
        \ifx\pgf@lib@dec@text@indent@left\undefined
            \def\pgf@decorate@width{#1}\pgf@decorate@switch@if#1 to final\pgf@stop
        \else
            % deceive the automaton by making the remaining distance longer
            \advance\pgfdecoratedremainingdistance-\pgf@lib@dec@text@indent@left
            \def\pgf@decorate@width{#1}\pgf@decorate@switch@if#1 to final\pgf@stop
            \advance\pgfdecoratedremainingdistance\pgf@lib@dec@text@indent@left
        \fi
    }
}
\def\pgf@decorate@@movealongpath{%
  \advance\pgfdecoratedinputsegmentcompleteddistance\pgf@decorate@distancetomove%
  \advance\pgfdecoratedinputsegmentremainingdistance-\pgf@decorate@distancetomove%
  \ifdim\pgfdecoratedinputsegmentremainingdistance>0pt\relax%
    \let\pgf@next\pgf@decorate@@@movealongpath%
  \else%
    \begingroup
      % check if we are at the last path
      \pgf@decorate@processnextinputsegmentobject%
      \ifx\pgf@decorate@currentinputsegmentobjects\pgfutil@empty%
        % if yes, then insist to keep decorating on this path
        \let\pgf@next\pgf@decorate@@@@movealongpath%
      \else%
        % if no, process the next segment again outside the group
        \def\pgf@next{
          \pgf@decorate@processnextinputsegmentobject
          \pgf@decorate@@movealongpath
        }
      \fi%
      \pgfmath@smuggleone\pgf@next
    \endgroup
  \fi%
  \pgf@next%
}
\def\pgf@decorate@@@@movealongpath{
  \pgf@decorate@movealonginputsegment{\the\pgf@decorate@distancetomove}%
  \pgf@decorate@distancetomove0pt\relax
}

3

I think this is obvious

  • Thank you for your answer! 1. I don't want the text go further, I want it to begin at the begin and truncate at the end of the line. 2. Why isn't the text simply shifted down? Compare the 3rd to the 6th example. For the reason of this question, see the P.S. and the linked post. – CarLaTeX Mar 16 '17 at 4:02
  • 1. declare a new decoration. 2. They are simply shifted down. In tikzlibrarydecorations.code.tex, raise will cause just \pgftransformyshift{#1}. – Symbol 1 Mar 16 '17 at 12:46
  • 1. Of course, with a shorter decoration there is no problem, but why tikz doesn't start from the beginning, if it ends at the end? 2. It's not a simple shift because the chars are squashed, too! – CarLaTeX Mar 16 '17 at 13:12
  • @CarLaTeX I expanded my answer. – Symbol 1 Mar 23 '17 at 1:04
  • Eventually, the answer I wanted, as it is clearly visible from n. 3, is simply that tikz shifts any single character, not the whole decoration! Thank you for you gorgeous post! – CarLaTeX Mar 23 '17 at 5:10

Your Answer

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

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