NAME
Term::Fabulous::Render::Frame - What one frame paints, command by command
SYNOPSIS
use Term::Fabulous::Render::Frame;
my $frame = Term::Fabulous::Render::Frame->new(
commands => $ui->render, # Clay's render commands
width => $ui->width,
height => $ui->height,
);
foreach my $index ( 0 .. $frame->command_count - 1 ) {
my $command = $frame->command($index);
my ( $x0, $y0, $x1, $y1 ) = @{ $frame->clip_rect($index) };
...
}
# The commands painted at a cell, the topmost first.
my @indices = $frame->topmost_at( 12, 3 );
DESCRIPTION
Most programs never use this module directly. Term::Fabulous::Render builds a Frame from the render commands Clay laid out, before it paints any of them, and keeps the Frame of the last frame ("last_frame" in Term::Fabulous::Render). Term::Fabulous hit-tests the mouse pointer with it, and Term::Fabulous::Render::Canvas uses it to decide which canvases can keep their cells.
A Frame is read-only. It works out (the painted cells on the first call that needs them, the rest when it is constructed):
the paint order
The order of Clay's commands, with one addition: Clay carries the background of a canvas in the canvas's own command, and the frame paints it as a rectangle right before that command.
the clip rect of every command
The rectangle of cells the command may paint into: the viewport (
[0, 0, width, height]), narrowed to the innermost scissor around the command. Clay surrounds the content of a clipping element, such as a scroll box, with aSCISSOR_STARTand aSCISSOR_ENDcommand; a scissor nested inside another is narrowed to it. Boxes are snapped to whole cells like everywhere else (see "cell_rect" in Term::Fabulous::Render::Geometry).the cells every command paints
Rectangles, text and canvases paint their box, borders the one-cell edge of every side whose Clay border width is greater than 0, and scissors nothing; all of them only inside their clip rect.
CONSTRUCTOR
new
my $frame = Term::Fabulous::Render::Frame->new( commands => \@commands, width => 80, height => 24 );
commands is an array reference of render commands in the format of "RENDER COMMANDS" in Clay::XS, in the order Clay emitted them; width and height are the size of the viewport in cells, numbers of at least 0. The command hashes are kept as they are, not copied.
Dies with a message starting with Term::Fabulous::Render::Frame: when an argument is invalid, when a command has a type other than rectangle, border, text, scissor start or end and custom (unhandled render command type IMAGE; Term::Fabulous widgets produce only these), and when a SCISSOR_END has no open scissor.
METHODS
All $index arguments are positions in the paint order, from 0 to command_count - 1; any other value dies.
commands
my @commands = $frame->commands;
The render commands in paint order. The hashes are Clay's own: read them, do not change them. Use $ui->widget_for( $command->{userData} ) to get the widget a command belongs to.
command_count
my $count = $frame->command_count;
The number of commands.
command
my $command = $frame->command($index);
One command, as in "commands".
width, height
my ( $columns, $rows ) = ( $frame->width, $frame->height );
The size of the viewport the Frame was built for.
clip_rect
my ( $x0, $y0, $x1, $y1 ) = @{ $frame->clip_rect($index) };
The rectangle of cells the command may paint into, as a new array reference [x0, y0, x1, y1]. x1 and y1 are exclusive, so the rectangle covers the columns x0 .. x1 - 1 and the rows y0 .. y1 - 1. When a scissor lies outside the viewport, the rectangle is empty (x1 == x0 or y1 == y0). A command outside its clip rect, such as content scrolled out of a scroll container, paints nothing.
painted_rects
my @rects = $frame->painted_rects($index);
The non-empty [x0, y0, x1, y1] rectangles the command paints, as new array references; none for a scissor or for a command outside its clip rect, up to four (one per edge) for a border.
painted_after
my $covered = $frame->painted_after( $index, [ $x0, $y0, $x1, $y1 ] );
1 when a command painted after the one at $index paints into the given rectangle, otherwise 0. A canvas that something is painted over cannot keep its cells from the last frame.
painted_over
my @rects = $frame->painted_over( $index, [ $x0, $y0, $x1, $y1 ] );
The parts of the given rectangle that commands painted after the one at $index paint into, as [x0, y0, x1, y1] rectangles, one per painted rectangle of those commands; they may overlap. Empty when nothing is painted over the rectangle. A sixel picture leaves these cells out.
topmost_at
my @indices = $frame->topmost_at( $x, $y );
The indices of the commands that paint the cell ($x, $y), the topmost (the one painted last) first. Empty when nothing is painted there.
SEE ALSO
Term::Fabulous::Render, Term::Fabulous::Render::Geometry, Term::Fabulous::Render::Canvas.