9

I found this rendering from here on this site but with no explanation or working example to go with it. How do I do this? I'm pretty familiar with TikZ but I'm having trouble finding text that is curved along the vertical as most examples of curved text are along the horizontal.

2 Answers2

11

The new text effects along path decoration in the CVS version of PGF can almost do this, although some tweaking is required. This decoration can parametrize the "effects" that are applied to the text (e.g., for scaling or coloring) according to the number of the character in the text. Text grouped inside braces is regarded as a single character:

\documentclass[border=0.125cm]{standalone}

\usepackage{tikz} \usetikzlibrary{decorations.text,math}

\begin{document}

\def\themousestail{% {Fury said to} {a mouse, That} {he met} {in the} {house,} {Let us} {both go} {to law:} {I will} {prosecute} {YOU. ---} {Come, I'll} {take no} {denial;} {We must} {have a} {trial:} {For} {really} {this} {morning} {I've} {nothing} {to do.'} {Said the} {mouse to} {the cur,} {Such a} {trial,} {dear sir,} {With no} {jury or} {judge,} {would be} {wasting} {our breath.'} {I'll be} {judge,} {I'll be} {jury,'} {Said} {cunning} {old Fury;} {I'll try} {the whole} {cause,} {and} {condemn} {you} {to} {death.'} }

% The text effects along path decoration puts each % character (or characters within braces) % in the text into a TikZ node.

\tikz\draw [decoration={text effects along path, text/.expanded=\themousestail, text effects/.cd, % parametrize the number of the characters. character count=\i, character total=\n, % These are the "effects" (node options) used for calculating the width % of the bounding box of the character node % (i.e., how far to move along the decorated path). character widths={rotate=90, scale=1-\i/\n0.5, execute at begin node=\strut, inner ysep=-0.76ex},% Ugh, -0.76ex by trial and error. % `text along path' makes the characters slope with the path characters={anchor=base west, scale=1-\i/\n0.5}}, decorate] (0,0) .. controls ++(1,-1.5) and ++(1,2) .. (0,-5) .. controls ++(-1,-2) and ++(1,1.75) .. (0,-10) .. controls ++(-1,-1.75) and ++(0,1) .. (0,-14);

\tikz\draw [decoration={text effects along path, text/.expanded=\themousestail, text effects/.cd, character count=\i, character total=\n, character widths={rotate=90, scale=1-\i/\n0.5, execute at begin node=\strut, inner ysep=-0.76ex},% Ugh, -0.76ex by trial and error. % `text along path' makes characters slope with the path. characters={text along path, rotate=90, anchor=base west, scale=1-\i/\n0.5}}, decorate] (0,0) .. controls ++(1,-1.5) and ++(1,2) .. (0,-5) .. controls ++(-1,-2) and ++(1,1.75) .. (0,-10) .. controls ++(-1,-1.75) and ++(0,1) .. (0,-14);

\tikz\draw [decoration={text effects along path, text/.expanded=\themousestail, text effects/.cd, character count=\i, character total=\n, character widths={rotate=90, scale=1-\i/\n0.5, execute at begin node=\strut, inner ysep=-0.76ex},% Ugh, -0.76ex by trial and error. characters={anchor=base west, scale=1-\i/\n0.5, evaluate={\c=\i/\n*100;}, text=red!\c!blue}}, decorate] (0,0) .. controls ++(1,-1.5) and ++(1,2) .. (0,-5) .. controls ++(-1,-2) and ++(1,1.75) .. (0,-10) .. controls ++(-1,-1.75) and ++(0,1) .. (0,-14);

\end{document}

\end{document}

enter image description here

Note, care must be taken with how the path is constructed. If the path isn't smooth some of the rotated lines will look a bit wrong:

\documentclass[border=0.125cm]{standalone}

\usepackage{tikz} \usetikzlibrary{decorations.text} \begin{document}

\def\themousestail{% {Fury said to} {a mouse, That} {he met} {in the} {house,} {Let us} {both go} {to law:} {I will} {prosecute} {YOU. --- Come,} {I'll take no} {denial; We} {must have a} {trial: For} {really this} {morning I've} {nothing} {to do.''} {Said the} {mouse to the} {cur,Such} {a trial,} {dear Sir,} {With} {no jury} {or judge,} {would be} {wasting} {our} {breath.''} {I'll be} {judge, I'll} {be jury,''} {Said} {cunning} {old Fury:} {I'll} {try the} {whole} {cause,} {and} {condemn} {you} {to} {death.''}}

% The text effects along path decoration puts each % character (or characters within braces) % in the text into a TikZ node.

\tikz\draw [decoration={text effects along path, text/.expanded=\themousestail, text effects/.cd, % These are the node options used for calculating the width of each character % (i.e., how far to move along the decorated path). character widths={rotate=90, execute at begin node=\strut, inner ysep=-0.875ex}, % These are the node options applied to each character. characters={anchor=base west}}, decorate] (0,0) arc (50:0:3 and 3) arc (0:-40:2 and 3) arc (130:180:2 and 3) arc (180:230:2 and 3) arc (50:-50:2 and 3);

\tikz\draw [decoration={text effects along path, text/.expanded=\themousestail, text effects/.cd, character widths={rotate=90, execute at begin node=\strut, inner ysep=-0.875ex}, % `text along path' makes the characters slope with the path characters={text along path, rotate=90, anchor=base west}}, decorate] (0,0) arc (50:0:3 and 3) arc (0:-40:2 and 3) arc (130:180:2 and 3) arc (180:230:2 and 3) arc (50:-50:2 and 3);

\end{document}

enter image description here

quark67
  • 4,166
Mark Wibrow
  • 70,437
  • Nice. Is there a way to not have to break the text manually? – Holene Nov 09 '13 at 08:37
  • @Holene Currently no. By default the separator is the (soft) space but could be changed to another character. Using braces (as I did above) enables groups of characters to be treated as single characters. In the "mouses tail" example, if such automatic breaking existed what would its operating criterion be? Numbers of characters? 1, 2 or 3 words? Certainly if you look at the original Lewis Carroll, the breaking doesn't follow an algorithm (or not one that I can see anyway). – Mark Wibrow Nov 09 '13 at 08:56
  • Good question about the operating criterion. I thought it could be some constraint in a similar manner to the arcs defining the curve the left alignment of the text is following. Then accept words to break or not to break, with some defined accepted badness level outside of the right curve, for instance? If you get my point... – Holene Nov 09 '13 at 11:16
8

enter image description here

An alternative way to make the tail using Asymptote:

// mousetail.asy :
// 
// to get a standalone mousetail.pdf, run
// asy -f pdf mousetail.asy 
//
unitsize(1pt);
import fontsize;
defaultpen(fontsize(10pt));
string[] s={
"Fury said to",
"a mouse, That",
"he met in the",
"house, ``Let us",
"both go to law:",
"I will prosecute",
"YOU.  --- Come,",
"I'll take no",
"denial; We",
"must have a",
"trial:  For",
"really this",
"morning", 
"I've nothing",
"to do.'' Said", 
"the mouse to",
"the cur,",
"``Such a trial,",
"dear Sir,",
"With no", 
"jury or", 
"judge,",
"would be",
"wasting", 
"our",
"breath.''",
"``I'll be",
"judge,",
"I'll be"
,"jury,''",
"Said",
"cun-",
"ning",
"old",
"Fury:",
"``I'll",
"try the",
"whole",
"cause,",
"and",
"con-",
"demn",  
"you",
"to",
"death.''",
};

guide tail=(152,504)..(196,418)..(152,277)..(203,128)..(183,28);
tail=scale(0.95)*tail;
draw(tail,gray(0.6));
real tailsize=arclength(tail);
real dl=tailsize/(s.length-1);
pair linedir;
real t;
Label L;
for(int i=0;i<s.length-1;++i){
  t=arctime(tail,dl*i);          // get the value of time parameter at i-th point 
  linedir=dir(tail,t);           // get the direction of i-th line
  linedir*=(0,1);                // rotate it 90 degrees to get the direction of i-th line
  L=Label(s[i],(0,0),(0,0));     // center i-th Label at the origing
  L=rotate(degrees(linedir))*L;  // rotate it to the angle of i-th line direction
  label(Label(L,t),tail);        // draw i-th label 
}

// draw the last label as a special case 
label(s[s.length-1],point(tail,3.95),SW);
g.kov
  • 21,864
  • 1
  • 58
  • 95