El ejemplo del látex

El ejemplo del látex

Tengo algunos problemas con la alineación del texto a lo largo del camino en tikz. Hice una forma personalizada y escribí texto a lo largo del camino dentro de ella de la siguiente manera:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{decorations.text}
\begin{document}
\begin{tikzpicture}

% shape
\draw (70:3) arc (70:110:3)
   -- (110:5)  arc (110:70:5)
   -- cycle;

\path[
  postaction={
    decorate,
    decoration={
      text along path,
      text align = center,
      text={Gershon Daly Bonifacy Yaw}
    }
  }
]
(105:4.5) arc (105:75:4.5)
(105:4.0) arc (105:75:4.0)
(105:3.5) arc (105:75:3.5);

\end{tikzpicture}
\end{document}

El resultado es bastante bueno, pero hay pequeños problemas. Esta es la salidasinalineación central:

sin alineación

y esto esconalineación central:

con alineación

Mi problema es que quiero un salto de línea correcto (no romper líneas en el medio de la palabra) y una alineación relativa a la línea central de la forma, no al camino.

Sé que al representar texto a lo largo del camino, cada letra se ajusta de manera diferente \hboxy gira en el grado correcto por separado.

¿Alguna sugerencia?

ACTUALIZAR:

EnesteLa ruta de respuesta se decora solo en caso de que el texto se ajuste a la ruta. ¿Puede haber un enfoque similar para decorar el camino solo con texto ajustado y dejar el resto del texto en los otros caminos?

ACTUALIZACIÓN 2:

Puedo ocultar texto si el texto no se ajusta a la ruta redefiniendo el estado de sangría izquierda como se indica enrespuesta mencionada arriba:

\makeatletter
  \pgfkeys{
    /pgf/decoration/omit long text/.code={%
      \expandafter\def\csname pgf@decorate@@text along path@left indent@options\expandafter\expandafter\expandafter\endcsname\expandafter\expandafter\expandafter{\csname pgf@decorate@@text along path@left indent@options\endcsname,switch if less than=\pgf@lib@dec@text@width to final}%
    },
  }
\makeatother

Mi idea es no solo omitir el texto tipográfico (cambiar al estado final), sino también establecer alguna marca que signifique que el texto no está tipográfico, para poder disminuir la longitud del texto y llamar a la decoración nuevamente.

Respuesta1

Siguiendo mi idea (en un comentario a la pregunta del OP), hice algunos experimentos con LuaTeX. Estos son los resultados preliminares.

El ejemplo del látex

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{decorations.text}
\directlua{dofile("testing.lua")}
\begin{document}
\sffamily

% Before entering tikzpicture
\directlua{PrepareText({{105,75,4.5}, {105,75,4}, {105,75,3.5}}, 
           "Gershon Daly Bonifacy Yaw")}
\begin{tikzpicture}
\draw (70:3) arc (70:110:3)
   -- (110:5)  arc (110:70:5)
   -- cycle;
\directlua{TypeInArcs()}
\end{tikzpicture}
%
% A second example
\directlua{PrepareText({{105,75,4.5}, {105,75,4}, {105,75,3.5}}, 
"This is another longer test, which does not Fit")}
\begin{tikzpicture}
\draw (70:3) arc (70:110:3)
   -- (110:5)  arc (110:70:5)
   -- cycle;
\directlua{TypeInArcs()}
\end{tikzpicture}
%
% Third example
\directlua{PrepareText({{105,75,4.5}, {105,75,4}, {105,75,3.5}, {105,75,3}}, 
"This is another longer test, which now does Fit")}
\begin{tikzpicture}
\draw (70:2.5) arc (70:110:2.5)
   -- (110:5)  arc (110:70:5)
   -- cycle;
\directlua{TypeInArcs()}
\end{tikzpicture}

\end{document}

El resultado

Después de compilar conlualatex

Resultado

El código lua

Guárdalo en un archivo testing.lua:

function GetLinesFromBox()
        local lines,i,j,l,d,list,words
        lines = {}; j = 1;
        d=node.types();
        list = tex.box[0].head
        node.unprotect_glyphs(list)
        for l in node.traverse(list) do
            if (d[l.id]=="hlist") then
                words = {}; i = 1
                for l in node.traverse(l.head) do
                    if (d[l.id]=="glyph") then
                        words[i] = string.char(l.char)
                        i=i+1
                    end
                    if (d[l.id]=="glue") then
                        words[i] = " "
                        i=i+1
                    end
                end
                lines[j] = table.concat(words,"")
                j=j+1
            end
        end
        return lines
end

function ComputeLengthArc(start_, end_, radius)
    return (radius*(math.abs(start_-end_)*2*math.pi/360))
end

global_arcs = {}
global_text = ""

function PrepareText(arcs, text)
    local j,l
    global_arcs = arcs
    global_text = text
    tex.print("\\setbox0=\\vbox{\\centering\\parshape ", #arcs)
    for j=1,#arcs do
        l = ComputeLengthArc(arcs[j][1], arcs[j][2], arcs[j][3] )
        tex.print("0cm "..l.."cm ")
    end
    tex.print("\\noindent ".. text .. "}")
end

function TypeInArcs()
    local lines,j
    lines = GetLinesFromBox()
    for j=1,#global_arcs do
        if lines[j]~=nil then
            tex.sprint("\\path[ postaction = { decorate, decoration = {")
            tex.sprint("  text along path,")
            tex.sprint("  text align = center,")
            tex.sprint("  text={"..lines[j].."}")
            tex.sprint("} } ]")
            tex.sprint("("..global_arcs[j][1]..":"..global_arcs[j][3]..
                  ") arc ("..global_arcs[j][1]..":"..global_arcs[j][2]..":"..global_arcs[j][3]..");")
        end
    end
end

Explicaciones y advertencias

Esto es sólo una prueba de concepto. El algoritmo es muy ingenuo. Escribí el texto en el cuadro 0 de TeX, pero con a parshapecon las longitudes adecuadas para cada línea. Luego examino los nodos resultantes de lua, asumiendo que cada uno hboxes una línea, cada uno glyphdentro de ese cuadro es un carácter y cada uno gluees un espacio. De esta manera "reconstruyo" la cadena que se usará para cada línea más adelante, al dibujar la imagen tikz.

Hay algunos problemas que no resolví (no sé cómo):

  1. Las ligaduras en el texto rompen el algoritmo porque producen glifos que no tienen equivalente ascii. Por eso escribí "Fit" en lugar de "fit", para evitar la ligadura "fi".
  2. Por la misma razón, probablemente no se permitan caracteres acentuados (no probado)
  3. Aparentemente, tikz interfiere con el mecanismo de boxeo TeX, porque si intento crear la caja dentro del entorno tikz, no se produce ninguna caja. Por eso tengo que "preparar" la caja antes de entrar a tikz.
  4. Probablemente aún no se han encontrado más problemas (no se han probado mucho)

información relacionada