pgf-tikz / pgf

A Portable Graphic Format for TeX
https://pgf-tikz.github.io/
1.15k stars 109 forks source link

Guidance on bidi texts and babel #677

Open jbezos opened 5 years ago

jbezos commented 5 years ago

As the current maintaner of babel, I'd like to make pgf compatible with bidi text using luatex. The aim is to generate graphics with Arabic, Hebrew, Farsi, etc., text without explicit markup (ie, the direction is set by the pgf commands). After a few experiments with nodes, it seems the hooks provided by pgf could do the trick. For example (and with the corresponding internal macro):

\g@addto@macro\pgfsys@beginpicture{\textdir TLT} \g@addto@macro\tikz@atbegin@node{\textdir TRT}

But I'm not sure this is the way to go or there are better alternatives. Here is a sample file (from the Persian lshort):

\documentclass{book}

\usepackage[bidi=basic]{babel}
\babelprovide[import,main]{persian}
\babelfont{rm}{FreeSerif}

\usepackage{tikz}
\usetikzlibrary{%
  arrows,%
  shapes.misc,%
  chains,%
  scopes,%
  }

\makeatletter
\g@addto@macro\pgfsys@beginpicture{\textdir TLT}
\g@addto@macro\tikz@atbegin@node{\textdir TRT}

\begin{document}

\begin{center}
\begin{tikzpicture}[point/.style={coordinate},thick,draw=black!50,>=stealth',
                    tip/.style={->,shorten >=1pt},every join/.style={rounded corners},
                    skip loop/.style={to path={-- ++(0,#1) -| (\tikztotarget)}},
                    hv path/.style={to path={-| (\tikztotarget)}},
                    vh path/.style={to path={|- (\tikztotarget)}},
                 terminal/.style={
            rounded rectangle,
            minimum size=6mm,
            thick,draw=black!50,
            top color=white,bottom color=black!20,
            font=\ttfamily\tiny},
                nonterminal/.style={
                       rectangle,
                       minimum size=6mm,
                       thick,
                       draw=red!50!black!50,         % 50% red and 50% black,
                       top color=white,              % a shading that is white at the top...
                       bottom color=red!50!black!20, % and something else at the bottom
                       font=\tiny}]
                       \message{**** \the\textdir -- \the\bodydir}
\matrix[column sep=4mm] {
  % First row:
  & & & & & & & & & & & \node (plus) [terminal] {+};\\
  % Second row:
  \node (p1) [point] {}; &     \node (ui1)    [nonterminal] {عدد بدون‌علامت}; &
  \node (p2) [point] {}; &     \node (dot)    [terminal]    {.};                &
  \node (p3) [point] {}; &     \node (digit) [terminal]     {رقم};            &
  \node (p4) [point] {}; &     \node (p5)     [point] {};                       &
  \node (p6) [point] {}; &     \node (e)      [terminal]    {E};                &
  \node (p7) [point] {}; &                                                      &
  \node (p8) [point] {}; &     \node (ui2)    [nonterminal] {عدد بدون‌علامت}; &
  \node (p9) [point] {}; &     \node (p10)    [point]       {};\\
  % Third row:
  & & & & & & & & & & & \node (minus)[terminal] {-};\\
};
{ [start chain]
  \chainin (p1);
  \chainin (ui1)   [join=by tip];
  \chainin (p2)    [join];
  \chainin (dot)   [join=by tip];
  \chainin (p3)    [join];
  \chainin (digit) [join=by tip];
  \chainin (p4)    [join];
  { [start branch=digit loop]
    \chainin (p3) [join=by {skip loop=-6mm,tip}];
  }
  \chainin (p5)    [join,join=with p2 by {skip loop=6mm,tip}];
  \chainin (p6)    [join];
  \chainin (e)     [join=by tip];
  \chainin (p7)    [join];
  { [start branch=plus]
    \chainin (plus) [join=by {vh path,tip}];
    \chainin (p8)    [join=by {hv path,tip}];
  }
  { [start branch=minus]
    \chainin (minus) [join=by {vh path,tip}];
    \chainin (p8)    [join=by {hv path,tip}];
  }
  \chainin (p8)    [join];
  \chainin (ui2)   [join=by tip];
  \chainin (p9)    [join,join=with p6 by {skip loop=-11mm,tip}];
  \chainin (p10)   [join=by tip];
}
\end{tikzpicture}
\end{center}

\end{document}
hmenke commented 5 years ago

Unfortunately I only speak languages with Latin alphabet, so I am pretty useless here, but it is an interesting problem and it should definitely be addressed.

jbezos commented 5 years ago

Let me then pose a similar problem. Let's assume I want to set the color, to underline, to enclose in braces, to add a bullet before, etc., of any text inside a figure (very likely, the text start is enough). The point of my question is, how can I catch every possible piece of text (or most of them) inside a figure? I'd say \tikz@atbegin@node is a good candidate for nodes. (The code to be inserted at those places is my problem.)

hmenke commented 5 years ago

I've had a look at this again. First of all, instead of appending to the low-level macro \tikz@atbegin@node it is better to use the execute at begin node key.

Anyway, I think what you are looking for are these two hooks: https://github.com/pgf-tikz/pgf/blob/5d179300a9dcc879414cb86bca28d6a3f2fc0a08/tex/generic/pgf/systemlayer/pgfsys.code.tex#L619-L630