Skip to main content
3 of 4
Extended the answer with updated code and a new equidistant based method
jVincent
  • 14.8k
  • 1
  • 44
  • 76

This is just a quick sketching out of an answer (rescales galore!)

 textOnCurve[text_, f_, n_, p_: 0.01] := 
    Text[Rotate[text, ArcTan @@ (f[Rescale[n + p, {0, 1}, {p, 1 - p}]] - 
                                 f[Rescale[n - p, {0, 1}, {p, 1 - p}]])], f[n]]

 textCurve[string_, f_, stylef_: (# &), range_: {0, 1}] := 
  With[{chars = Characters@string}, 
  MapIndexed[textOnCurve[stylef@#1, f, Rescale[#2[[1]],{1, Length@chars}, range]] &, chars]]

Which can then be used like:

pts = {{0, 0}, {1, 1}, {2, -1}, {3, 0}};
LocatorPane[Dynamic[pts],
 Dynamic@(
  f = BezierFunction[pts];
  Show[Graphics[{Point[pts], Line[pts],
     textCurve["Some text here", f, Style[#, 20] &, {0.2, 0.6}]
     }, Axes -> True]
   , ParametricPlot[f[t], {t, 0, 1}]])
, LocatorAutoCreate -> True]

Curvy Text

Update

This can be improved by adding proper positioning by fixing the lower midpoint in the rotation and position. Also using Szabolcs very nice equidistant spacings. However as I have stated in comments kerning is going to be trouble unless it's really taken seriusly into consideration.

 textOnCurve[text_,f_,n_,p_: 0.01]:=
 With[{angle=ArcTan@@Subtract@@(f/@Rescale[{n+p,n-p},{0,1},{p,1-p}])},
  Rotate[Text[text,f[n],{0,-1}],angle,f[n]]
 ]
 
equidistantTextCurve[string_,f_,stylef_: (#&),range_: {0,1}]:=
 Module[{chars,distance},
  chars=Characters@string;
  distance=functionEquidistant[f,Length@chars,range];
  MapIndexed[textOnCurve[stylef@#1,f,distance[[#2[[1]]]]]&,chars]
]

LocatorPane[Dynamic[pts],
Dynamic@(f = BezierFunction[pts];
 Show[Graphics[{Point[pts], Line[pts],
  equidistantTextCurve["Mathematica.StackExchange.Com", f, 
   Style[#, 18] &, {0.15, 0.8}]
  }, Frame -> True, PlotRange -> 2], 
 ParametricPlot[f[t], {t, 0, 1}]]), LocatorAutoCreate -> True]

Better curve text with equidistant characters

I'll leave it as an exercise to calculate proper kerning and getting an even better result.

jVincent
  • 14.8k
  • 1
  • 44
  • 76