7

There seems to be a problem with tikzmark and xelatex. Ulrike Fischer from the xetex list helped to track this down. The following code does not work when compiled with xelatex but produces the expected result when compiled with pdflatex:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{tikzmark}


\begin{document}

x\pgfmark{tA}some text \pgfmark{tB} some text
\begin{tikzpicture}[remember picture]
\draw (0,0)node (A){A} rectangle (1,1)node (B){B};
\end{tikzpicture}
\begin{tikzpicture}[remember picture]
\draw (0,0)node {\pgfmark{nA}} rectangle (1,1)node {\pgfmark{nB}};
\end{tikzpicture}

\vspace{3cm}\centering
\begin{tikzpicture}[overlay,remember picture]
\draw[red,->] (0,0)--(pic cs:tA) (0,0)--(pic cs:tB);
\draw[blue,->](0,0)--(pic cs:nA) (0,0)--(pic cs:nB); %nB faulty
\draw[green,->](0,0)--(A) (0,0)--(B);
\end{tikzpicture}

\end{document} 

Is there a quick fix to this? The problem appeared after upgrading from texlive 2013 to texlive 2014.

Edit: The original code used \subnodebut it doesn't work either:

\documentclass{article}
\usepackage{forest}

\usetikzlibrary{tikzmark}


\begin{document}


\begin{forest}
[V
[\subnode{ap1}{AP}
[ungewaschen]]
[V{[ \subnode{arg11}{1}, \subnode{arg12}{2} ]}
[isst]]]
\end{forest}
\begin{forest}
[V
[\subnode{ap2}{AP}
[ungewaschen]]
[V{[\subnode{arg21}{1} ]}]]
\end{forest}
\begin{tikzpicture}[overlay,remember picture]
%% this works with tikzmark
%% \draw[->, bend angle=40, bend left] ($(pic cs:ap1)+(1ex,2ex)$) to($(pic cs:arg11)+(1ex,2.5ex)$);
%% \draw[->, bend angle=40, bend left] ($(pic cs:ap1)+(1ex,2ex)$) to($(pic cs:arg12)+(1ex,2.5ex)$); % 1ex links, 2ex hoch
%% %
%% this used to work with subnode in texlive 2013 but is broken now
%% \draw[->, bend angle=40, bend left] ($(pic cs:ap2)+(1ex,2ex)$) to($(pic cs:arg21)+(1ex,2.5ex)$);
\draw[->, bend angle=40, bend left] (ap1.north) to (arg11.north);
\draw[->, bend angle=40, bend left] (ap1.north) to (arg12.north); 
%
\draw[->, bend angle=40, bend left] (ap2.north) to (arg21.north);
\end{tikzpicture}


\end{document}

The AP should be connected to 1 and 2 respectively, but the arrows are up in the air.

enter image description here

  • 2
    For this example only, \documentclass{article} \newcount\pdftexversion \pdftexversion140 \def\pgfsysdriver{pgfsys-dvipdfm.def} \usepackage{tikz} \usetikzlibrary{tikzmark} \begin{document} ... \end{document} gives correct result. However, experts should investigate pgfsys-xetex.def and pgfsys-dvipdfmx.def which are used in usual usage of xelatex. – Akira Kakuto Feb 23 '15 at 6:01
  • Thanks! Would this work for all similar problems? And whom should I contact? The tikzmark package maintainer? xelatex people? pgfmaintainers? – Stefan Müller Feb 23 '15 at 16:39
  • Well it looks like a problem in the driver, probably with the definition of \pgfsys@hboxsynced. It is not possible to save a position inside a node. E.g. node {\pdfsavepos\write\@auxout{\@percentchar\the\pdflastxpos}} always store the zero coordinate. So probably the pgf maintainer should be informed. – Ulrike Fischer Feb 23 '15 at 18:47
  • 1
    Well you didn't invest much time in this bug report. Bug reports can lurk around quite long and so imho they should be self contained. Links to discussions which could be edited or deleted at any time can be inserted as additional material but are not a substitute. – Ulrike Fischer Feb 25 '15 at 13:09
  • 1
    For your example code then you wouldn't need \pgfmark inside the node as you could give a name to the node and use that instead. \tikzmark and \pgfmark shouldn't be used inside an existing tikzpicture. I wrote the \subnode command to avoid this problem since lots of people seemed to insist on using \tikzmark inside a tikzpicture! – Loop Space Mar 29 '15 at 20:41
3

Thanks to @UlrikeFischer and @AkiraKakuto's comment.


In PGF, the command \pgfsys@hboxsynced is used to put some text at a specified position. There are two ways to do so:

  • work hard with \hskip and \raise;

  • tell the PDF renderers to do the dirty work for you.


When LaTeX is used, pgfsys-pdftex.def implements \pgfsys@hboxsynced by the first method. And as @AkiraKakuto suggested, the implementation in pgfsys-common-pdf-via-dvi.def uses the first method as well.

However when XeLaTeX is used, the implementation in pgfsys-common-pdf-via-dvi.def is overwritten by pgfsys-dvipdfmx.def, which uses the second method. Now all texts are put at the origin together with some positioning information. PDF renderers will recognize these information and shift those texts to the right place. However \tikzmark and any other marking macro will not work anymore because what you are marking is the origin.


Despite that we can implement \pgfsys@hboxsynced by ourselves, which need a bunch of knowledge regarding XeLaTeX, we might play around with the positioning information.

Notice that the positioning information is processed by \pgfsys@transformcm. So we might try

\let\temp=\pgfsys@transformcm
\def\pgfsys@transformcm#1#2#3#4#5#6{
    \rememberxshift{#5}
    \rememberyshift{#6}
    \temp{#1}{#2}{#3}{#4}{#5}{#6}
}

And then we can fix the \tikzmark or whatever marking macro by the information.


More technical details

  • \pgf@pt@x is the dimension for x-shift.
  • so \hskip\pgf@pt@x belongs to the first method.
  • on the other hand, anything like \pgflowlevelsynccm, \pgfsys@invoke, \special, is related to the second method.
  • A minimal example is
    \tikz[overlay]\node[xshift=100]{Some \pgfmark{X} Text};
    \tikz[overlay,remember picture]\draw(pic cs:X)circle(.1);
    
  • A ever simpler example is (we are not even inside a pgfpicture)
    \newbox\mybox
    \setbox\mybox=\hbox{Some \pgfmark{Y} Text 2}
    \pgftransformxshift{100}
    \pgfsys@hboxsynced\mybox
    
    \tikz[overlay,remember picture]\draw(pic cs:Y)circle(.1);
    

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.