Errors
cl-textrender signals one condition, textrender-error, for every failure
in it and in the libraries under it. You never need to handle a
cl-harfbuzz, cl-icu, cl-ft2 or cl-sdf condition: their errors are reported
in terms of the cl-textrender call that failed.
textrender-error
(handler-case (tr:layout-text "abc" font :spans '((2 9 :data :red)))
(tr:textrender-error (e)
(list (tr:textrender-error-message e)
(tr:textrender-error-hint e))))
;; => ("The span (2 9 :DATA :RED) ends at 9, past the end of the text, which has 3 characters."
;; "A span is (START END &key FONT FEATURES DATA), where START and END are
;; character indexes with 0 <= START <= END <= the length of the text.")
textrender-error-messagesays what went wrong, in terms of the call.textrender-error-hintsays what to do about it, or isnil.- The report, as
princprints it, is the message, then the hint on a line of its own.
textrender-error is a subtype of error.
Type errors
Every exported function declares the types of its arguments, which SBCL checks as the function is entered, before it does anything:
-
An argument of the wrong type, a number out of range, such as a size of 0, a negative width or
:max-lines 0, a keyword argument outside its documented choices, such as:align :middleor:hinting :full, and an empty font list given tolayout-textsignal a standardtype-errorthat names the argument and the type it takes. SBCL may list a type's choices in another order:The value :MIDDLE is not of type (MEMBER :CENTER :LEFT :START :JUSTIFY :RIGHT :END) when binding :ALIGN -
Written as a constant, such an argument is caught sooner: SBCL warns as it compiles the call, and ASDF stops loading the system with it.
; caught WARNING: ; Constant ; :MIDDLE conflicts with its asserted type ; (MEMBER :JUSTIFY :CENTER :RIGHT :LEFT :END :START). -
What a declared type cannot say is checked in the function. An element of a list that is of the wrong type, such as a tab stop that is not a positive real or a variation that is not a
("tag" . value)pair, is atype-errortoo. The rest, such as a span outside the text, an index past its end and a destroyed face or font, signalstextrender-error, as below.
Every error
Fonts
| When | Message | Hint |
|---|---|---|
| The font file does not exist or cannot be read | Could not read the font file path: it does not exist or cannot be read. | Check the path and the file's permissions. |
| The data is not a font | path is not a font. (The font data is not a font, for an octet vector.) | Pass a TrueType or OpenType font, or a font collection. WOFF and WOFF2 web fonts must be converted to one of those first. |
:index is past the faces of a collection |
path has n faces, so face i does not exist. (The font data has …, for an octet vector.) | Pass an :INDEX below n. |
An axis in :variations is not the font's |
The font has no "wght" axis; its axes are "wdth", "opsz". | Pass only the font's own axes in :VARIATIONS. |
:variations given for a font that is not variable |
The font has no "wght" axis; it is not a variable font. | Leave out :VARIATIONS for a font that is not variable. |
| A destroyed font is used | The font has been destroyed with DESTROY-FONT. | Make it again with MAKE-FONT or FACE-FONT, and destroy it only when nothing uses it any more. |
| A destroyed face is used | The face has been destroyed with DESTROY-FACE. | Make it again with MAKE-FACE, and destroy it only when nothing uses it any more. |
A destroyed face or font is reported wherever it is used: layout-text,
face-font, face-cache, font-cache, font-glyph-id,
font-glyph-advance, glyph-outline, the cached outlines and the
backends. Destroying a face destroys its fonts, so they report themselves
destroyed.
Layout
| When | Message | Hint |
|---|---|---|
A span's :font is an empty list |
The font list is empty. | Pass a FONT, or a list of FONTs: the primary first, then its fallbacks. |
| Something in a font list is not a font | Element 2 of the font list is :BOLD, not a FONT. | The same. |
A span's :font is neither a font nor a list |
:BOLD is not a FONT. | The same. |
| A span is not a list of start, end and options | The span … is not of the form (START END &key FONT FEATURES DATA). | A span is (START END &key FONT FEATURES DATA), where START and END are character indexes with 0 <= START <= END <= the length of the text. |
| A span has an unknown option | The span (0 1 :COLOUR :RED) has the unknown option :COLOUR. | The same. |
A span's :features is not a list of strings |
The span … has :FEATURES "smcp", not a list of strings. | Give :FEATURES as a list of strings such as ("smcp" "-liga"). |
| A span ends past the text | The span (2 9 :DATA :RED) ends at 9, past the end of the text, which has 3 characters. | A span is (START END &key …). |
| A span starts after its end | The span (2 1 :DATA :X) starts at 2, after its end. | A span is (START END &key …). |
The :tab-stops positions do not increase |
The tab stops (200 100) are not in increasing order: 100 comes after 200. | Give :TAB-STOPS as positions along the line in increasing order, or as one interval. |
| HarfBuzz cannot parse a feature string | "bad feature!" is not a valid feature. | Write features in HarfBuzz's syntax: "liga" or "+liga" to turn one on, "-liga" to turn it off, "aalt=2" for a value, "smcp[3:5]" for a range. |
Hit testing
| When | Message | Hint |
|---|---|---|
| An index is past the end of the text | Index 7 is past the end of the text, which has 3 characters. | Text indexes are character positions, from 0 to the length of the text. |
This applies to caret-position, caret-segment, move-caret,
selection-rectangles, next-caret-index, previous-caret-index and
line-at-index. A negative index is a type-error.
Outlines
| When | Message | Hint |
|---|---|---|
outline-quadratics of an outline with cubics, without :tolerance |
The outline has cubic segments, which a quadratic-only vector needs a tolerance to approximate. | Pass :TOLERANCE, or make the outline with GLYPH-OUTLINE's :QUADRATIC T. |
Optional systems
| When | Message | Hint |
|---|---|---|
| FreeType cannot draw a glyph, as when its outline is damaged | Glyph 36 of #<FONT DejaVu Sans 16.0 {…}> cannot be rasterized: Could not load glyph 36: the glyph's outline is damaged. | The font's data for this glyph is damaged, or of a kind FreeType does not draw. Draw the text in another font. |
| A glyph's outline cannot be made into a distance field | Glyph g of font cannot be made into a distance field: … | The font's outline of this glyph is malformed. Draw it another way, such as rasterized. |
What is not an error
- A character no font has is drawn as the primary font's
.notdefglyph (glyph 0), not reported. - A glyph ID a font does not have, given to any function that takes one,
is answered for as the font's
.notdef: its advance, outline, image and field. A malformed font's character map that points past its last glyph counts as no glyph, so the character falls back to the next font, or is drawn as.notdef. - An index inside a grapheme is moved back to the grapheme's start.
- A point outside the text, given to
hit-test, is clamped to the nearest line and character. move-caretat either end of the text returns the index unchanged.- Destroying a face or font twice does nothing. Rasterizers and atlases are never destroyed: they hold nothing that needs it.