Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Drawing characters on a Surface

The most basic operation that can be performed on a surface is drawing a character at a specific position. This allows for more complex operations like drawing text, lines, rectangles, etc. to be built on top of it.

A surface has the following methods that can be used to manipulate characters and how they are drown on the surface:

MethodDescription
write_char(...)Writes a character at the specified position. If the position is outside the clip area, the character will not be drawn.
write_chars(...)Writes a slice of characters from left to right starting at a given position. Each character keeps its own code, colors and flags. Cells outside the clip area are skipped.
char(...)Returns the current character at the specified position or None if the position is outside the clip area or invalid.
clear(...)Clears/Fills the entire clip area with the specified character. If the clip area is not visible, the surface will not be cleared. Origin and clip are left unchanged.
reset(...)Fills the entire surface with the specified character and restores the origin and clip to the full surface. Use this when preparing an overlay that will be copied later.
draw_surface(...)Copies another surface onto this one at a given position. Transparent foreground or background colors in the source do not overwrite the destination, which allows layered compositing.
draw_surface_with_transform(...)Same as draw_surface, but a callback can remap each source character (code, colors or flags) before it is written.

Example:

#![allow(unused)]
fn main() {
use appcui::graphics::*;

let mut surface = Surface::new(100, 50);
// Set the origin point to (10,10)
surface.set_origin(10, 10);
// Set the clip area to (10,10,20,20)
surface.set_clip(10, 10, 20, 20);
// Clear the clip area
surface.clear(Character::new('*', Color::Silver, Color::Black, CharFlags::None))
// write a character at position (5,5) relativ to the origin
// point (10,10) => the character will be drawn at position (15,15)
surface.write_char(5, 5, Character::new('A', Color::Yellow, Color::DarkBlue, CharFlags::None));
}

clear only paints the current clip. reset is stronger: it restores clip and origin and then fills every cell. That is the usual way to prepare a secondary surface with transparent characters before copying it with draw_surface:

#![allow(unused)]
fn main() {
use appcui::graphics::*;

let mut overlay = Surface::new(10, 5);
overlay.reset(Character::new('\0', Color::Transparent, Color::Transparent, CharFlags::None));
overlay.write_string(0, 0, "Hi", CharAttribute::with_color(Color::Yellow, Color::Transparent), false);

let mut surface = Surface::new(40, 12);
surface.clear(Character::new(' ', Color::White, Color::DarkBlue, CharFlags::None));
surface.draw_surface(2, 2, &overlay);
}

draw_surface_with_transform is the same copy, but you can tint or mask the source:

#![allow(unused)]
fn main() {
surface.draw_surface_with_transform(2, 2, &overlay, |ch| {
    Character::new(ch.code, Color::Red, ch.background, ch.flags)
});
}