This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
Coordinates and Units
Layout units
A font's size is in layout units per em, and everything a layout returns is in layout units: glyph positions and advances, line and run extents, the layout's size, caret positions and selection rectangles. They are single-floats, unhinted and unrounded.
To draw at a scale, multiply. A layout made with a font of size 16, drawn
at 2 pixels per layout unit, gives 32-pixel text; the raster and atlas
backends take this factor as :scale. For UI text the simplest choice is a
font size in pixels and a scale of 1, times the display's scale factor.
The y axis
layout-text's :y-axis picks one of two conventions. Every y a layout
returns, and every y hit testing takes, follows it.
:y-axis :down (the default) is screen space. The first line's top is
at y 0 and lines go down; the first baseline is at the font's ascent.
:y-axis :up is world space. Every y is negated, so the text hangs
below the origin, as text in a scene with y up should.
(tr:layout-text (format nil "a~%b") font) ; :down
;; line 0: baseline 14.85, line-box y 0.0, height 18.625: from 0 down to 18.625
;; line 1: baseline 33.48, line-box y 18.625, height 18.625
(tr:layout-text (format nil "a~%b") font :y-axis :up) ; :up
;; line 0: baseline -14.85, line-box y -18.625, height 18.625: from 0 down to -18.625
;; line 1: baseline -33.48, line-box y -37.25, height 18.625
X coordinates are the same in both. A rect's x and y are always its
smallest coordinates, and its width and height positive. So in an :up
layout a rectangle's rect-y is its bottom edge: the first line's box
runs from y -18.625 up to 0.
The raster and atlas backends draw into images whose rows grow downwards from the layout's top, whichever convention the layout uses.
Where things are
| Value | In horizontal text |
|---|---|
glyph-x, glyph-y |
The glyph's origin, on the baseline. |
line-baseline |
The baseline's y. |
line-box |
The line's share of the layout: the layout's width by the line's height. |
line-content |
The part of the line box its visible content takes up, without trailing whitespace. |
run-box |
The part of the line box the run takes up, trailing whitespace included. |
layout-width, layout-height |
The box from (0, 0) the lines fill. |
The layout's box starts at x 0 and y 0 and is layout-width by
layout-height, downwards in a :down layout and upwards from the
negative y in an :up layout. Ink can stray outside it: hanging trailing
spaces, accents above the ascent, and glyphs that overhang their advance.
For vertical text, see Vertical Text.
To put a layout somewhere, add an offset to every position, or draw it under a transform.
Placing glyph outlines
Glyph outlines (glyph-outline) are always in font orientation, y up,
relative to the glyph's origin on the baseline. For an outline point
(ox, oy) of a glyph at (gx, gy):
| Glyph | :y-axis :down |
:y-axis :up |
|---|---|---|
| ordinary, or upright in vertical text | (gx + ox, gy - oy) |
(gx + ox, gy + oy) |
glyph-rotated-p (sideways in vertical text) |
(gx + oy, gy + ox) |
(gx + oy, gy - ox) |
A rotated glyph is turned 90° clockwise: its font x axis runs down the column and its y axis to the right.
The outline is in layout units of the font it came from. When a renderer
keeps outlines in ems, made from a font of size 1, it scales them by the
glyph font's size: (gx + ox × size, gy - oy × size).
Pixel snapping
Layout positions are fractional. Renderers decide how to snap:
- the raster and atlas backends round each glyph's x to the nearest quarter of a pixel and its y to a whole pixel, and draw it from a bitmap made at that quarter;
- outline and distance-field renderers usually draw at the exact position.
Keep the layout's positions and snap at drawing time, after any transform; laying out in pixels at the target size, with a scale of 1, keeps snapping predictable.
Text in a scene
For text placed in a 3D or 2D world with y up, make the font at size 1, so a
layout unit is an em, and lay out with :y-axis :up:
(tr:with-font (font "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf" :size 1)
(let ((layout (tr:layout-text "Sign" font :y-axis :up)))
(list (tr:layout-width layout) (tr:layout-height layout)
(map 'list (lambda (g) (list (tr:glyph-x g) (tr:glyph-y g)))
(tr:layout-glyphs layout)))))
;; => (2.1811523 1.1640625
;; ((0.0 -0.92822266) (0.6347656 -0.92822266) (0.91259766 -0.92822266)
;; (1.5473633 -0.92822266)))
The text is 2.18 ems wide and hangs from y 0 to y -1.16. Scale it by the height you want for an em, and translate it to center it or put its baseline where you want.