Text Rendering

To render a single line of text, use text:

draw centered(text("Some text"))

The text function takes a single argument—the string of text to draw—and returns a drawable which represents that text. Text always rests on the bottom of its enclosing bounds (its baseline is fixed to the bottom):

draw at(10, 10, 200, 40, drawable {
    draw fill(gray(0.8))
    draw text("Sitting way on the bottom.")

Note how the descenders on letters like g and y stick out of the bottom. Text can draw outside its layout bounds, so make sure you account for this.

Measuring text yields its overall width and the height of a capital letter (the "cap height") above the baseline.

var size = measure(0, 0, text("Some text to measure."))
// The overall width of the text.
// The cap height of the text.

You can use the __fontName, __fontSize, and __textColor variables to control text rendering.

__fontName = "Baskerville"
__fontSize = 64
__textColor = srgb(0.6, 0.5, 1)
draw centered(text("Fancy!"))

Note that these are dynamic bindings, so they will reset back to their old values when you exit a function or drawable.

Multi-line Text

To render text which can wrap onto multiple lines, use multiline.

draw at(50, 50, 100, 100, multiline("The quick brown fox jumps over the lazy dog."))

Multi-line text respects __fontName, __fontSize, and __textColor, just like text does. It also supports __textAlignment, which currently supports two values: #left for left-aligned text (the default) and #center for center-aligned text.

__fontName = "Avenir Next"
__fontSize = 16
__textColor = srgb(1.0, 0.7, 0)
__textAlignment = #center
draw at(50, 50, 100, 100, multiline("The quick brown fox jumps over the lazy dog."))

Measuring multiline yields a bounding box around the text wrapped to the proposed width. Typically you should propose a large height to avoid text being truncated vertically.

var dog = multiline("The quick brown fox jumps over the lazy dog.")
// Note the different heights when wrapped to different widths.
show(measure(100, 10000, dog).height)
show(measure(300, 10000, dog).height)

Note: I don't like having two functions. I'd rather just have a parameter controlling wrapping. I'd also like to make __fontName, __fontSize and so on parameters to text, but we need named parameters to avoid this being unwieldy. We may end up with some font attributes passed in as parameters and some passed in dynamic bindings. It would also be nice to have more metrics available than just the cap height. As always, let me know if you have any feedback on how this works.