Skip to content

TurtleText

Ryan Srichai edited this page Oct 18, 2025 · 16 revisions

TurtleText is an extension to turtle that adds a simple way to write text to the screen. It turns out that text rendering in graphics can get quite complicated but keep in mind that turtleText comes with many limitations including:

  • Simplified font format incompatible with standard font file formats
  • Only 430 characters currently supported across the latin, cyrillic, and greek alphabets as well as numbers and some symbols (not a hard limit, but a limit of how many characters that I have personally created)
  • No support for variable stroke-width within a character, this makes creating a font like Times New Roman impossible
  • Font builder tool still in development (legacy tool is built in scratch)
  • The C language isn't super good at handling unicode in general

That said, for simple applications and tools, this library has proved sufficient.

To initialise turtleText you have to first initialse turtle. Once that's done you can initialise turtleText with turtleTextInit():

/* initialise turtleText */
turtleTextInit("config/roberto.tgl");

We'll need to supply this function a path to a .tgl font file. Now this isn't a file type that you'll ever see in the wild. This is a font file with a special format used only by this library (it's called tgl for textGL, the old name for this library). I have created two fonts which are located in the config folder of the repository. These fonts are roberto.tgl, a font based on google's roboto, and robertoMono.tgl which is based on roboto mono.

You can also initialise turtleText with NULL, which will load turtleText's internal copy of roberto.tgl. This means that binaries created with turtle are portable and don't depend on this font file being present to render text (if you use any font other than roberto.tgl, then you'll need that file to exist at runtime otherwise the font will revert to roberto).

There are two main functions of turtleText. turtleTextWriteString and turtleTextGetStringLength

Writing Text

Lets write to the screen:

turtleTextWriteString("Hello World", 0, 0, 20, 50); // write "Hello World" to the center of the screen with a size of 20
image

The arguments of this function are the

  • string, a null terminated C string
  • X, coordinate
  • Y, coordinate
  • size, height of text in coordinates
  • align, a value ranging from 0 to 100, with 0 being left justified, 50 being center justified, and 100 being right justified

Lets analyse exactly where the text is written to, I'll draw a dot at (0, 0):

turtlePenColor(0, 0, 0);
turtleTextWriteString("Hello World", 0, 0, 20, 50); // write "Hello World" to the center of the screen with a size of 20
turtleGoto(0, 0);
turtlePenSize(3);
turtlePenColor(255, 0, 0);
turtlePenDown();
turtlePenUp();
turtleMainLoop();
image

Note that the height that the text is drawn at is centered at the specified height. This is true for any alignment:

turtlePenColor(0, 0, 0);
turtleTextWriteString("Hello World", 0, 0, 20, 0);
turtleGoto(0, 0);
turtlePenSize(3);
turtlePenColor(255, 0, 0);
turtlePenDown();
turtlePenUp();
turtleMainLoop();
image

The other core feature of turtleText is getting the length, in coordinates, of the a string of text. All you need for this function is the string and the size.

double renderLength = turtleTextGetStringLength("Hello World", 20);
printf("%lf\n", renderLength);

This is useful for sizing elements dynamically as text changes

turtlePenColor(0, 0, 0);
turtleTextWriteString("Hello World", 0, 0, 20, 50);
double renderLength = turtleTextGetStringLength("Hello World", 20);
turtleGoto(-renderLength / 2 - 2, -11);
turtlePenSize(1);
turtlePenColor(255, 0, 0);
turtlePenDown();
turtleGoto(renderLength / 2 + 2, -11);
turtleGoto(renderLength / 2 + 2, 11);
turtleGoto(-renderLength / 2 - 2, 11);
turtleGoto(-renderLength / 2 - 2, -11);
turtlePenUp();
turtleMainLoop();
image

Variants

A unicode variant of writing text called turtleTextWriteUnicode() exists to allow non-ASCII characters to be written.

turtleTextWriteUnicode(u8"çöp", 0, 0, 20, 50);
image

There is also a formatted variant of both the turtleTextWriteString and turtleTextWriteUnicode functions which works like printf. The string argument has moved to the back of the function so keep that in mind.

int32_t iter = 10;
turtleTextWriteStringf(0, 0, 20, 50, "iter %d", iter);
image

And there's a unicode version

int32_t microseconds = 1500;
turtleTextWriteUnicodef(0, 0, 20, 50, u8"%dμs", microseconds);
image

All of these versions also have a separate function that allows rotation:

/* Write a string to the screen (with rotation) */
void turtleTextWriteStringRotated(const char *str, double x, double y, double size, double align, double rotate);

/* Write a formatted string to the screen (with rotation) */
void turtleTextWriteStringfRotated(double x, double y, double size, double align, double rotate, const char *str, ...);

/* Write a utf8-string to the screen (with rotation) */
void turtleTextWriteUnicodeRotated(const char *str, double x, double y, double size, double align, double rotate);

/* Write a formatted utf8-string to the screen (with rotation) */
void turtleTextWriteUnicodefRotated(double x, double y, double size, double align, double rotate, const char *str, ...);

Note that this rotation is a bearing angle in degrees, with 0 being not rotated, 90 being rotated clockwise by 90 degrees, and etc.

If you simply want all the features all the time, feel free to use the turtleTextWriteUnicodefRotated() function exclusively. The limited options provide minor performance benefits for applications that don't need rotation, unicode, or special formatting.

All Functions

Clone this wiki locally