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:
| Method | Description |
|---|---|
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 remaps each source character before it is written. The callback receives the source character and its Point on the source surface, and returns Some(character) to write it or None to skip that cell. |
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. The Point is the coordinate on the source surface (top-left of the source is (0, 0)). Return None to skip a cell:
#![allow(unused)]
fn main() {
surface.draw_surface_with_transform(2, 2, &overlay, |ch, _| {
Some(Character::new(ch.code, Color::Red, ch.background, ch.flags))
});
}