Text Rendering

The text rendering classes describe how terminal text is drawn into a writable buffer. They turn String content into aligned labels, wrapped paragraphs, reusable text presets, and animated headlines.

Bitmap fonts plug into the same pipeline through TextOptions and Text. For font creation and font presets, see Font.

This page focuses on placing text inside rectangles, rendering wrapped text blocks, and reusing TextOptions across multiple Text instances. For the underlying Char and String value types, see Strings and Chars.

Details about the example output on this page

The examples below were rendered with the dedicated documentation helper doc/tools/drawing-text-reference.cpp at a fixed width of 72 terminal columns. This makes it easy to regenerate the visual output together with the code snippets.

Usage

Drawing Direct Strings and Aligned Labels

WritableBuffer provides two main entry points for text that does not need paragraph formatting:

  • drawText(Position, String) writes text at an exact start position.

  • drawText(String, Rectangle, Alignment, Color) aligns text inside a rectangle.

auto footer = String{};
footer.append(
    bg::BrightBlack,
    fg::BrightYellow,
    "[Q]",
    fg::BrightWhite,
    " quit  ",
    fg::BrightCyan,
    "[R]",
    fg::BrightWhite,
    " refresh");

buffer.drawText(Position{4, 4}, footer);

buffer.drawFilledFrame(
    Rectangle{42, 2, 24, 5},
    FrameStyle::LightWithRoundedCorners,
    Char{" ", Color{fg::Inherited, bg::Blue}},
    Color{fg::BrightCyan, bg::Inherited});
buffer.drawText("Overview", Rectangle{42, 2, 24, 5}, Alignment::Center, Color{fg::BrightWhite, bg::Inherited});

Use the position-based overload for status lines, overlays, and other exact placements. Use the rectangle overload for titles, centered labels, and other layout-driven text.

    drawText(Position, String)         drawText(String, Rectangle, ...) 
                                                                        
  012345678901234567890123456789          ╭──────────────────────╮      
                                                                      
    [Q] quit  [R] refresh                        Overview             
                                                                      
                                          ╰──────────────────────╯      
                                                                        
   exact position, mixed colors        same API, aligned in a rectangle 
                                                                        

Text Alignment Inside a Rectangle

Text uses the same Alignment model as the geometry and bitmap helpers. This means you can place a text block inside its target rectangle without manual offset calculations.

auto title = Text{String{"Short note"}, Rectangle{26, 2, 20, 4}, Alignment::Center};
title.setColor(Color{fg::BrightYellow, bg::Inherited});
buffer.drawText(title);

The same content can be anchored to the top-left, center, or bottom-right simply by changing the alignment value.

   Text uses the same alignment model as other geometry-aware drawing   
                                                                        
  ┌──────────────────┐    ┌──────────────────┐    ┌──────────────────┐  
Short note        │    │    Short note    │    │                  
                  │    │                  │    │        Short note
  └──────────────────┘    └──────────────────┘    └──────────────────┘  
        TopLeft                  Center               BottomRight       
                                                                        
                                                                        

Rendering Wrapped Paragraphs

Text becomes especially useful when text needs wrapping, paragraph spacing, or paragraph-aware indentation.

auto help = Text{
    String{"Navigation: Use arrow keys to move.\n\nActions: Press Enter to open."},
    Rectangle{10, 3, 52, 7},
    Alignment::TopLeft};
help.setParagraphSpacing(ParagraphSpacing::DoubleLine);
help.setWrappedLineIndent(2);
help.setColor(Color{fg::BrightWhite, bg::Inherited});

buffer.drawText(help);

This keeps the content, target rectangle, and paragraph behavior in one object. For the full paragraph-formatting reference, continue with Paragraph Options.

                                                                        
      ╔════════════════════════Help Panel════════════════════════╗      
                                                          
   Navigation: Use arrow keys to move.                    
                                                          
                                                          
                                                          
   Actions: Press Enter to open.                          
                                                          
                                                          
                                                          
      ╚══════════════════════════════════════════════════════════╝      
     Text automatically wraps and keeps explicit paragraph breaks.      

Reusing TextOptions and Animation

TextOptions bundles color sequences, fonts, animation, and paragraph layout settings into one reusable preset.

auto options = TextOptions{Alignment::Center};
options.setColorSequence(
    ColorSequence{
        Color{fg::BrightYellow, bg::Inherited},
        Color{fg::BrightRed, bg::Inherited},
        Color{fg::BrightMagenta, bg::Inherited},
        Color{fg::BrightCyan, bg::Inherited},
    });
options.setAnimation(TextAnimation::ColorDiagonal);

auto left = Text{String{"ALERT PANEL"}, Rectangle{4, 3, 28, 2}, Alignment::Center};
left.setTextOptions(options);
auto right = Text{String{"ALERT PANEL"}, Rectangle{40, 3, 28, 2}, Alignment::Center};
right.setTextOptions(options);

buffer.drawText(left, 1);
buffer.drawText(right, 3);

This works well when several labels or headings should share one visual style. TextAnimation::ColorDiagonal shifts the configured color sequence diagonally across the rendered text based on the supplied animation cycle.

                      Reuse one TextOptions preset                      
  ╭──────────────────────────────╮    ╭──────────────────────────────╮  
                              │    │                              
         ALERT PANEL          │    │         ALERT PANEL          
                              │    │                              
                              │    │                              
                              │    │                              
  ╰──────────────────────────────╯    ╰──────────────────────────────╯  
             cycle = 1                           cycle = 3              
                                                                        

Interface

class TextOptions

Options for text rendering.

This class combines text color, font, animation, and paragraph layout settings into one reusable configuration object that can be attached to a Text instance.

Note

Creating and copying text instances is expensive. Please keep and reuse created instances.

Public Functions

inline explicit TextOptions(const Alignment alignment) noexcept

Create a text options instance with the given alignment.

Parameters:

alignment – The text alignment inside the rectangle.

inline const ColorSequence &colorSequence() const noexcept

Get the optional text color sequence.

inline void setColorSequence(ColorSequence colorSequence) noexcept

Set the text color sequence.

Parameters:

colorSequence – The sequence of colors to apply while rendering the text.

inline Color color() const noexcept

Get the first text color from the configured sequence.

Returns:

The first sequence color, or the inherited color if no sequence is configured.

inline void setColor(const Color color) noexcept

Set a single text color.

Parameters:

color – The single base color to use for the rendered text.

inline const FontPtr &font() const noexcept

Get the optional font. If this is empty, regular text rendering is used.

inline void setFont(const FontPtr &font) noexcept

Set the font.

Parameters:

font – The font to use, or an empty pointer for regular terminal text rendering.

inline TextAnimation animation() const noexcept

Get the animation mode.

inline void setAnimation(const TextAnimation animation) noexcept

Set the animation mode.

Parameters:

animation – The animation mode to apply while rendering the text.

inline const ParagraphOptions &paragraphOptions() const noexcept

Get the paragraph options.

Returns:

The paragraph layout settings used for this text.

inline void setParagraphOptions(const ParagraphOptions &options) noexcept

Set the paragraph options.

Parameters:

options – The paragraph layout settings to copy into this text configuration.

inline Alignment alignment() const noexcept

The alignment of the paragraph.

For the Terminal::printParagraph calls, vertical alignment is ignored. For the drawText(Text) calls, the vertical alignment is used to align the text in the given rectangle.

inline void setAlignment(const Alignment alignment) noexcept

Set the alignment of the paragraph.

inline int lineIndent() const noexcept

The line indent for all lines.

Only valid if the alignment is set to Alignment::Left. This indent can be overridden by firstLineIndent and wrappedLineIndent.

inline void setLineIndent(const int indent) noexcept

Set the line indent for all lines.

Parameters:

indent – The new indent value. >=0

inline int firstLineIndent() const noexcept

Get the first line indent.

This is the indent for the first line of the paragraph. Only valid if the alignment is set to Alignment::Left.

1:| <first indent> A long text that is broken   |
2:| into multiple lines.                        |

inline void setFirstLineIndent(const int indent) noexcept

Set the first line indent.

Parameters:

indent – The new indent value. >=0 or cUseLineIndent to use lineIndent

inline int wrappedLineIndent() const noexcept

Get the indent for wrapped lines.

This is the indent for all lines that are wrapped at the terminal width. Only valid if the alignment is set to Alignment::Left.

1:| <first indent> A long text that is broken   |
2:| into multiple lines.                        |

inline void setWrappedLineIndent(const int indent) noexcept

Set the indent for wrapped lines.

Parameters:

indent – The new indent value. >=0 or cUseLineIndent to use lineIndent

inline ParagraphBackgroundMode backgroundMode() const noexcept

Get the background mode.

The background mode determines how the background of the paragraph is handled when lines are wrapped. It also controls how the background is extended for the last line in the paragraph.

inline void setBackgroundMode(const ParagraphBackgroundMode backgroundMode) noexcept

Set the background mode.

inline const String &lineBreakEndMark() const noexcept

Get the line break end mark.

The line break end mark is appended to the end of a line if it is wrapped to the next line. The line mark is always aligned to the last column of the terminal. If the mark contains color information, it will override the background color.

1:| A long text that is broken  <end mark> |
2:| into multiple lines.                   |

Returns:

The current line break end mark. Empty for no line break end mark.

inline void setLineBreakEndMark(String mark)

Set the line break end mark.

Parameters:

mark – The new line break end mark. Must not exceed two characters.

inline const String &lineBreakStartMark() const noexcept

Get the line break start mark.

The line break start mark prepends each wrapped line. The mark is inserted at the indentation column. If the mark contains color information, it will override the background color.

1:| A long text that is broken           |
2:| <start mark> into multiple lines.    |

Returns:

The current line break start mark. Empty for no line break start mark.

inline void setLineBreakStartMark(String mark)

Set the line break start mark.

Parameters:

mark – The new line break start mark. Must not exceed two characters.

inline ParagraphSpacing paragraphSpacing() const noexcept

The spacing between paragraphs.

The behavior of the paragraph spacing depends on the used interface. For the Terminal::printParagraph calls, newlines in the text are handled as simple line-breaks. The paragraph spacing is applied at the end of the call. Either just a newline or two newlines. For the drawText(Text) calls, a newline creates a new paragraph.

inline void setParagraphSpacing(const ParagraphSpacing spacing) noexcept

Set the paragraph spacing.

inline const std::u32string &wordSeparators() const noexcept

Get the word separators.

Word separators split a source line into words. Consecutive separators are rendered as a single space between words. Tabs use special tab-stop handling in left-aligned paragraphs before separator handling is applied.

inline void setWordSeparators(std::u32string separators) noexcept

Set the word separators.

Tabs remain special tab stops in left-aligned paragraphs and act as regular word separators in other alignments when included here.

Parameters:

separators – A string of Unicode characters that are used to split words.

inline const Char &wordBreakMark() const noexcept

Get the word break mark.

The word break mark is used when a long word had to be split in a paragraph.

inline void setWordBreakMark(Char mark) noexcept

Set the word break mark.

inline int maximumLineWraps() const noexcept

Get the maximum line wraps.

A value >0 limits the maximum line wraps for a paragraph. A line is only wrapped up to the given number of times. If after this number, the line would need to wrapped further to be fully displayed on the screen, the paragraphEllipsisMark is used to indicate that the line is incomplete. Embedded line-breaks are not counted as line wraps and reset the wrap count to zero.

Returns:

The maximum number of line wraps, or zero for unlimited line wraps.

inline void setMaximumLineWraps(const int lines) noexcept

Set the maximum number of line wraps.

Parameters:

lines – The maximum number of line wraps, or zero for unlimited line wraps.

inline const String &paragraphEllipsisMark() const noexcept

Get the paragraph ellipsis mark.

This string is used to indicate that a paragraph would have to be wrapped over even more lines to be displayed completely. A single character can be used, but a short text like (more…) works as well. Please note that the width of this mark further reduces the available space for the paragraph text.

Returns:

The paragraph ellipsis mark or an empty string if no ellipsis mark shall be used.

inline void setParagraphEllipsisMark(String mark) noexcept

Set the paragraph ellipsis mark.

We recommend using a single character or a very short text. Longer texts quickly make paragraph rendering impossible.

Parameters:

mark – The paragraph ellipsis mark. If empty, no ellipsis mark will be used.

inline const std::vector<int> &tabStops() const noexcept

Get the tab stops for the paragraph.

Only valid if the alignment is set to Alignment::Left. If a line (text up to a newline character) contains TAB characters, each tab character will pick the next tab-stop columns value from this array. If the column is larger than the current column, spacing is inserted until the cursor reaches the tab-stop column. If the tab column is smaller, or there is no further tab stop in the sequence, tabOverflowBehavior() is used to decide whether the tab becomes a single space or starts a wrapped continuation line. In centered or right-aligned paragraphs, tabs use wordSeparators instead of these tab stops. The special value cTabWrappedLineIndent can be used to use the same indent as for wrapped lines.

inline void setTabStops(std::vector<int> tabStops) noexcept

Set the tab stops.

inline TabOverflowBehavior tabOverflowBehavior() const noexcept

Get the overflow handling for non-advancing tab stops.

This mode is used if a TAB resolves to a tab-stop column that is not larger than the current column, or if there is no further configured tab stop.

inline void setTabOverflowBehavior(const TabOverflowBehavior behavior) noexcept

Set the overflow handling for non-advancing tab stops.

Parameters:

behavior – The behavior to use for tabs that do not advance the current line.

inline ParagraphOnError onError() const noexcept

Get the error resolution if a paragraph cannot be rendered with the given settings.

If the screen layout and the given parameters do not allow the paragraph to be rendered properly, this error resolution is used.

Returns:

The error resolution to use when a paragraph cannot be rendered.

inline void setOnError(const ParagraphOnError onError) noexcept

Set the error resolution.

Parameters:

onError – The error resolution to use when a paragraph cannot be rendered.

class Text

Describes a text block to render into a Buffer.

Note

Creating and copying text instances is expensive. Please keep and reuse created instances.

Public Functions

Text() = default

Create an empty text description.

inline Text(String text, Rectangle rect, const Alignment alignment = Alignment::TopLeft) noexcept

Create a text description for the given content and target rectangle.

Parameters:
  • text – The text content to render.

  • rect – The target rectangle.

  • alignment – The text alignment inside the rectangle.

inline const String &text() const noexcept

Get the text content.

inline void setText(String text) noexcept

Set the text content.

inline const Rectangle &rectangle() const noexcept

Get the target rectangle.

inline void setRectangle(const Rectangle rect) noexcept

Set the target rectangle.

inline const TextOptions &textOptions() const noexcept

Get the text options.

inline void setTextOptions(const TextOptions &options) noexcept

Set the text options.

inline const ColorSequence &colorSequence() const noexcept

Get the optional text color sequence.

inline void setColorSequence(ColorSequence colorSequence) noexcept

Set the text color sequence.

Parameters:

colorSequence – The sequence of colors to apply while rendering the text.

inline Color color() const noexcept

Get the first text color from the configured sequence.

Returns:

The first sequence color, or the inherited color if no sequence is configured.

inline void setColor(const Color color) noexcept

Set a single text color.

Parameters:

color – The single base color to use for the rendered text.

inline const FontPtr &font() const noexcept

Get the optional font. If this is empty, regular text rendering is used.

inline void setFont(const FontPtr &font) noexcept

Set the font.

Parameters:

font – The font to use, or an empty pointer for regular terminal text rendering.

inline TextAnimation animation() const noexcept

Get the animation mode.

inline void setAnimation(const TextAnimation animation) noexcept

Set the animation mode.

Parameters:

animation – The animation mode to apply while rendering the text.

inline Alignment alignment() const noexcept

The alignment of the paragraph.

For the Terminal::printParagraph calls, vertical alignment is ignored. For the drawText(Text) calls, the vertical alignment is used to align the text in the given rectangle.

inline void setAlignment(const Alignment alignment) noexcept

Set the alignment of the paragraph.

inline int lineIndent() const noexcept

The line indent for all lines.

Only valid if the alignment is set to Alignment::Left. This indent can be overridden by firstLineIndent and wrappedLineIndent.

inline void setLineIndent(const int indent) noexcept

Set the line indent for all lines.

Parameters:

indent – The new indent value. >=0

inline int firstLineIndent() const noexcept

Get the first line indent.

This is the indent for the first line of the paragraph. Only valid if the alignment is set to Alignment::Left.

1:| <first indent> A long text that is broken   |
2:| into multiple lines.                        |

inline void setFirstLineIndent(const int indent) noexcept

Set the first line indent.

Parameters:

indent – The new indent value. >=0 or cUseLineIndent to use lineIndent

inline int wrappedLineIndent() const noexcept

Get the indent for wrapped lines.

This is the indent for all lines that are wrapped at the terminal width. Only valid if the alignment is set to Alignment::Left.

1:| <first indent> A long text that is broken   |
2:| into multiple lines.                        |

inline void setWrappedLineIndent(const int indent) noexcept

Set the indent for wrapped lines.

Parameters:

indent – The new indent value. >=0 or cUseLineIndent to use lineIndent

inline ParagraphBackgroundMode backgroundMode() const noexcept

Get the background mode.

The background mode determines how the background of the paragraph is handled when lines are wrapped. It also controls how the background is extended for the last line in the paragraph.

inline void setBackgroundMode(const ParagraphBackgroundMode backgroundMode) noexcept

Set the background mode.

inline const String &lineBreakEndMark() const noexcept

Get the line break end mark.

The line break end mark is appended to the end of a line if it is wrapped to the next line. The line mark is always aligned to the last column of the terminal. If the mark contains color information, it will override the background color.

1:| A long text that is broken  <end mark> |
2:| into multiple lines.                   |

Returns:

The current line break end mark. Empty for no line break end mark.

inline void setLineBreakEndMark(String mark)

Set the line break end mark.

Parameters:

mark – The new line break end mark. Must not exceed two characters.

inline const String &lineBreakStartMark() const noexcept

Get the line break start mark.

The line break start mark prepends each wrapped line. The mark is inserted at the indentation column. If the mark contains color information, it will override the background color.

1:| A long text that is broken           |
2:| <start mark> into multiple lines.    |

Returns:

The current line break start mark. Empty for no line break start mark.

inline void setLineBreakStartMark(String mark)

Set the line break start mark.

Parameters:

mark – The new line break start mark. Must not exceed two characters.

inline ParagraphSpacing paragraphSpacing() const noexcept

The spacing between paragraphs.

The behavior of the paragraph spacing depends on the used interface. For the Terminal::printParagraph calls, newlines in the text are handled as simple line-breaks. The paragraph spacing is applied at the end of the call. Either just a newline or two newlines. For the drawText(Text) calls, a newline creates a new paragraph.

inline void setParagraphSpacing(const ParagraphSpacing spacing) noexcept

Set the paragraph spacing.

inline const std::u32string &wordSeparators() const noexcept

Get the word separators.

Word separators split a source line into words. Consecutive separators are rendered as a single space between words. Tabs use special tab-stop handling in left-aligned paragraphs before separator handling is applied.

inline void setWordSeparators(std::u32string separators) noexcept

Set the word separators.

Tabs remain special tab stops in left-aligned paragraphs and act as regular word separators in other alignments when included here.

Parameters:

separators – A string of Unicode characters that are used to split words.

inline const Char &wordBreakMark() const noexcept

Get the word break mark.

The word break mark is used when a long word had to be split in a paragraph.

inline void setWordBreakMark(Char mark) noexcept

Set the word break mark.

inline int maximumLineWraps() const noexcept

Get the maximum line wraps.

A value >0 limits the maximum line wraps for a paragraph. A line is only wrapped up to the given number of times. If after this number, the line would need to wrapped further to be fully displayed on the screen, the paragraphEllipsisMark is used to indicate that the line is incomplete. Embedded line-breaks are not counted as line wraps and reset the wrap count to zero.

Returns:

The maximum number of line wraps, or zero for unlimited line wraps.

inline void setMaximumLineWraps(const int lines) noexcept

Set the maximum number of line wraps.

Parameters:

lines – The maximum number of line wraps, or zero for unlimited line wraps.

inline const String &paragraphEllipsisMark() const noexcept

Get the paragraph ellipsis mark.

This string is used to indicate that a paragraph would have to be wrapped over even more lines to be displayed completely. A single character can be used, but a short text like (more…) works as well. Please note that the width of this mark further reduces the available space for the paragraph text.

Returns:

The paragraph ellipsis mark or an empty string if no ellipsis mark shall be used.

inline void setParagraphEllipsisMark(String mark) noexcept

Set the paragraph ellipsis mark.

We recommend using a single character or a very short text. Longer texts quickly make paragraph rendering impossible.

Parameters:

mark – The paragraph ellipsis mark. If empty, no ellipsis mark will be used.

inline const std::vector<int> &tabStops() const noexcept

Get the tab stops for the paragraph.

Only valid if the alignment is set to Alignment::Left. If a line (text up to a newline character) contains TAB characters, each tab character will pick the next tab-stop columns value from this array. If the column is larger than the current column, spacing is inserted until the cursor reaches the tab-stop column. If the tab column is smaller, or there is no further tab stop in the sequence, tabOverflowBehavior() is used to decide whether the tab becomes a single space or starts a wrapped continuation line. In centered or right-aligned paragraphs, tabs use wordSeparators instead of these tab stops. The special value cTabWrappedLineIndent can be used to use the same indent as for wrapped lines.

inline void setTabStops(std::vector<int> tabStops) noexcept

Set the tab stops.

inline TabOverflowBehavior tabOverflowBehavior() const noexcept

Get the overflow handling for non-advancing tab stops.

This mode is used if a TAB resolves to a tab-stop column that is not larger than the current column, or if there is no further configured tab stop.

inline void setTabOverflowBehavior(const TabOverflowBehavior behavior) noexcept

Set the overflow handling for non-advancing tab stops.

Parameters:

behavior – The behavior to use for tabs that do not advance the current line.

inline ParagraphOnError onError() const noexcept

Get the error resolution if a paragraph cannot be rendered with the given settings.

If the screen layout and the given parameters do not allow the paragraph to be rendered properly, this error resolution is used.

Returns:

The error resolution to use when a paragraph cannot be rendered.

inline void setOnError(const ParagraphOnError onError) noexcept

Set the error resolution.

Parameters:

onError – The error resolution to use when a paragraph cannot be rendered.

enum class erbsland::cterm::TextAnimation : uint8_t

Supported text animation styles used by Buffer::renderText().

Values:

enumerator None

No animation.

enumerator ColorDiagonal

Diagonal color animation. Requires a color sequence.