What would be the best way to draw text that follows a curve

Lets say that in this case I want to draw text that follows bézier curve, what would be the best way of achieving this?

I do know how to achieve it by drawing text char by char and calculating angle for each char, but that just seems like overkill.

Maybe create geometry along the curve and apply a texture with the prerendered text to it would work.

You could flatten the path into linear segments on small ranges to speed up tangents’ calculations.

I used to start with a similar algorithm, but if you need “pixel perfect” alignment with the curve, I don’t think you have any other choice than yours. Maybe using a LUT to precompute angles.

1 Like

If your not worried about it lining up right id pass a interpolating array to a custom spritebatch and drawInto by building monogame from source. The problem with text here is You have to either draw the text from spritefont yourself and call draw or alter monogames source.

At the moment i would think to do it without a huge performance hit and for it to actually line up right. Would be to build monogame from source then make a spritebatch overload that passes a bezier to your own overloaded copy of DrawInto modify that DrawInto to take a bezier then work on it within.

The way you would do that (modify the output position of DrawInto) is by passing the x y modification your calculating within drawInto as a positional addition added just before passing off to DrawInternal.

The real problem for performance is the offset.X is your time across the curve.
However you don’t know the total line length without calling MeasureString so you would have to call measure string at the start of your custom DrawInto to be able to get a timing scalar for offset.X. offset.X can’t be precalculated which is what DrawInto does is kerns the text. Fortunately DrawInto already does this for SpriteEffects so what you would do is to simply short circut that to always get the size even when SpriteEffects.None would skip the measure call.

I.E. MeasureString gives a size.X so offset.X / size.X = the interpolation time on the bezier curve. The same apply’s to Y for a bezier surface patch.

I think it would work pretty easily though like that. It would be very little code to add to your own custom copy of DrawInto. It would require you to build monogame from source but its essentially just copying drawinto and modifying it.

Im actually working on a prototype class were i could add that without rebuilding monogame, if it were up to par id post it, but its not.

The post is here however A silly question. you can see how DrawString right down to DrawInternal fundamentally draws text. So you can imagine simply added the bezier position results just prior to setting the vertex data. Which is what DrawInternal normally starts the process of doing.

1 Like