Image for post
Image for post

UI Programming

Add Curved Text to Your Apps

How to properly add some curved text in your app

Another week, another feature for our app. This week I had to make some research about how to add some curved text to our app.

I searched a lot and end up on different resources: from an official (but outdated) Apple example with CoreText, to a post on Stack Overflow written in Swift 2, 3, and 4. However, none of them offered a straightforward, easy to follow, mathematically sound approach.

I made several experiments, trials, and errors, before reaching this solution. I had to properly understand several concepts of how the text can be rendered on the screen and it could be useful to write them on (digital) paper for both the future me and anyone who could need it.

A caveat before starting: this article contains a bit of math, basic geometry, and some concepts of calculus, but nothing extremely complex. I tried to simplify them with graphs and to limit them to the minimum. Don’t be scared!

The Goal

What we want is to draw some text, with custom fonts and colors, on a curved line, rotating the letters so that the result will look like this.

Image for post
Image for post

From a first investigation, this cannot be done out of the box in a UILabel. To achieve that we need to perform some computations and we need to draw every letter one at a time, computing its position and rotation before drawing it.

The Maths

The underlying maths is geometry. Let’s suppose that we want to draw our text over an arc of a circle.

Image for post
Image for post

The only thing we know is the x-coordinate of all of our characters. What we need to compute are both:

  • the y-coordinate of the letter;
  • the rotation we need to imprint to the letter.

Luckily, both of them can be extracted pretty easily once we have the formula of the circle.

The Y-Coordinate

From our years in secondary school, we could remember that the equation of a circle is:

Image for post
Image for post

where r is the radius of the circle while x and y are its coordinates. So, let’s suppose for a while that we know the radius r, we can invert the formula and obtain a function that, given a value x, returns the correspondent y.

Image for post
Image for post

Now, how can we compute the radius? Well, this is something we can do with some considerations.

  1. When the curve is maximum, we can think that all our text stays on the full half of the circumference. Therefore, the r is equal to half of the text length.
  2. If the curve is not at its maximum, we know that the distance for all the letters from the center must be the same.
  3. To keep the same distance, we need to move the center up or down by some value C, so that all the letters are at the same distance. That means that our radius is growing, but how much?
  4. We can consider half of the text’s length as one side of a triangle rectangle while C is the other side. We can then compute the hypotenuse with Pitagoras theorem. The hypotenuse is our radius!

Basically, when the text is straight, we are rendering it using an infinitely big circle. The more the text is rounded, the smaller the circle, up to a circle whose radius is equal to half of the length of the text, given a font.

The code of the two functions we can use to compute the radius and the y-coordinate are the following:

Now, given any x-coordinate of a letter, we can compute the corresponding y-coordinate passing the radius rand the x to the halfCircle function.

The Rotation

Now that we have all these functions, we can compute the rotation of each letter. From trigonometry, we can remember that the rotation we have to imprint to the letter is defined by the angle created by the tangent of the letter.

Image for post
Image for post

At this point, we first need to compute the tangent. A mathematically perfect approach would require us to compute the first derivative of our function and ask for the value of the derivative in the middle point of the letter.

However, we can cheat a bit and simplify the computation, saving us from computing the derivative. In fact, we can consider every letter as a rectangle. We can use the (xi, yi) of the leftmost point of the letter and the (xf, yf) of the rightmost point. Now, we can compute the slope m of the tangent with the formula:

Image for post
Image for post

The rotation angle is then simply atan(m)

Drawing the Letters

We have all the relevant ingredients to draw our letters. But how can we do that? Apple provides us with a UIGraphicsImageRenderer object that lets us draw something in a context and extract a UIImage from it.

Then, to draw some text, we can leverage an API of NSAttributedString that is draw(at: CGPoint, with attributed: [NSAttribiutedString.Key: Any]). This method allows us to specify a point and to draw some text at that point.

Everything looks pretty fine: we know the x and the y, so we can draw the letter in the proper position, but… How can we rotate it? There is no API to rotate a letter!

Do not despair, my friend. If you can’t rotate the letter, we can rotate the paper! Or, in the UIKit world, the context on which we have to draw the letter.

A CGContext offer some methods to rotate, translate, and scale the context itself. The important thing to remember is to save the state of the context before applying any transform. In this way, can restore it to the original state before drawing the next letter. This is extremely important because, otherwise, the transform would compose on each other and it will make really hard to reason about the coordinate system.

So… let’s put the drawing code together!

The code is a bit long, but it’s because I add a comment at every line to explain what is going on.

The most interesting part is the for loop, where most of the computation takes place. In that loop, we compute (x,y) and (x2, y2) to compute the slope m. From the slope, we can compute the angletheta for the rotation. We compute also (xm, ym), that is the medium point of the letter. All of this happens between line 58 and line 73.

From line 81 to line 99, we move the context, centering it in the letter middle point, we apply the transform and we draw the letter.

The Result

The final result of this code is very well rendered by the following short video:

Image for post
Image for post

Here I’m playing with the inflection parameter that is used through the whole code to compute the r, x and y values. There are some other parameters you can customize: the kerning of the string, for example, can provide interesting results.

Conclusion

In today's article, we explored how to draw some curved text in our application. The approach we used is mathematically sound: it uses a couple of functions to deduct the position and rotation of the letters.

A very interesting side effect of this approach is that we can plug-in almost every continuous, derivable function in place of the half circle and we can be able to draw some text following any line we want!

The Startup

Medium's largest active publication, followed by +756K people. Follow to join our community.

Riccardo Cipolleschi

Written by

Hi everybody, I’m Riccardo. Senior iOS Engineer at Bending Spoons, I breathe iOS development: apps and tools. I love to share my knowledge with others.

The Startup

Medium's largest active publication, followed by +756K people. Follow to join our community.

Riccardo Cipolleschi

Written by

Hi everybody, I’m Riccardo. Senior iOS Engineer at Bending Spoons, I breathe iOS development: apps and tools. I love to share my knowledge with others.

The Startup

Medium's largest active publication, followed by +756K people. Follow to join our community.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store