mirror of
https://github.com/dankamongmen/notcurses.git
synced 2024-11-02 09:40:15 +00:00
b0915d1db6
This completes the work for #1068. This addressed a subtle issue. When we're using pixel->semigraphic art, we want slightly different rendering. Essentially, imagine that we have two images, each two pixels tall and one pixel wide. The top image is a transparent pixel above a white pixel. The bottom image is a white pixel above a black pixel. We'd expect the result to be two white pixels, but we can instead get a black pixel above a white pixel. This is because the *background* color is being merged from the bottom plane, but really we want the *top* color. Ncvisuals are now blitted along with information regarding which quadrants they draw over, and when appropriate, we invert the foreground and background. Closes #1068.
127 lines
5.8 KiB
Markdown
127 lines
5.8 KiB
Markdown
% notcurses_render(3)
|
|
% nick black <nickblack@linux.com>
|
|
% v2.1.7
|
|
|
|
# NAME
|
|
|
|
notcurses_render - sync the physical display to the virtual ncplanes
|
|
|
|
# SYNOPSIS
|
|
|
|
**#include <notcurses/notcurses.h>**
|
|
|
|
**int ncpile_render(struct ncplane* n);**
|
|
|
|
**int ncpile_rasterize(struct ncplane* n);**
|
|
|
|
**int notcurses_render(struct notcurses* ***nc***);**
|
|
|
|
**char* notcurses_at_yx(struct notcurses* ***nc***, int ***yoff***, int ***xoff***, uint16_t* ***styles***, uint64_t* ***channels***);**
|
|
|
|
**int notcurses_render_to_file(struct notcurses* ***nc***, FILE* ***fp***);**
|
|
|
|
**int notcurses_render_to_buffer(struct notcurses* ***nc***, char\*\* ***buf***, size_t* ***buflen***);**
|
|
|
|
# DESCRIPTION
|
|
|
|
Rendering reduces a pile of **ncplane**s to a single plane, proceeding from the
|
|
top to the bottom along a pile's z-axis. The result is a matrix of **nccell**s
|
|
(see **notcurses_cell**). Rasterizing takes this matrix, together with the
|
|
current state of the visual area, and produces a stream of optimized control
|
|
sequences and EGCs for the terminal. By writing this stream to the terminal,
|
|
the physical display is synced to some pile's planes.
|
|
|
|
**ncpile_render** performs the first of these tasks for the pile of which **n**
|
|
is a part. The output is maintained internally; calling **ncpile_render** again
|
|
on the same pile will replace this state with a fresh render. Multiple piles
|
|
can be concurrently rendered. **ncpile_rasterize** performs rasterization, and
|
|
writes the result to the terminal. It is a blocking call, and only one
|
|
rasterization operation may proceed at a time. It does not destroy the
|
|
render output, and can be called multiple times on the same render.
|
|
**notcurses_render** calls **ncpile_render** and **ncpile_rasterize** on the
|
|
standard plane, for backwards compatibility. It is an exclusive blocking call.
|
|
|
|
It is necessary to call **ncpile_rasterize** or **notcurses_render** to
|
|
generate any visible output; the various notcurses_output(3) calls only draw to
|
|
the virtual ncplanes. Most of the notcurses statistics are updated as a result
|
|
of a render (see **notcurses_stats(3)**), and screen geometry is refreshed
|
|
(similarly to **notcurses_refresh(3)**) *following* the render.
|
|
|
|
While **notcurses_render** is called, you **must not call any other functions
|
|
modifying the same pile**. Other piles may be freely accessed and modified.
|
|
The pile being rendered may be accessed, but not modified.
|
|
|
|
**notcurses_render_to_buffer** performs the render and raster processes of
|
|
**notcurses_render**, but does not write the resulting buffer to the
|
|
terminal. The user is responsible for writing the buffer to the terminal in
|
|
its entirety. If there is an error, subsequent frames will be out of sync,
|
|
and **notcurses_refresh(3)** must be called.
|
|
|
|
A render operation consists of two logical phases: generation of the rendered
|
|
scene, and blitting this scene to the terminal (these two phases might actually
|
|
be interleaved, streaming the output as it is rendered). Frame generation
|
|
requires determining an extended grapheme cluster, foreground color, background
|
|
color, and style for each cell of the physical terminal. Writing the scene
|
|
requires synthesizing a set of UTF-8-encoded characters and escape codes
|
|
appropriate for the terminal (relying on terminfo(5)), and writing this
|
|
sequence to the output **FILE**. If the **renderfp** value was not NULL in the
|
|
original call to **notcurses_init**, the frame will be written to that **FILE**
|
|
as well. This write does not affect statistics.
|
|
|
|
Each cell can be rendered in isolation, though synthesis of the stream carries
|
|
dependencies between cells.
|
|
|
|
## Cell rendering algorithm
|
|
|
|
Recall that there is a total ordering on the N ncplanes, and that the standard
|
|
plane always exists, with geometry equal to the physical screen. Each cell of
|
|
the physical screen is thus intersected by some totally ordered subset of
|
|
planes **P0**, **P1**...**Pi**, where 0 < **i** ≤ **N**. At each cell, rendering starts at
|
|
the topmost intersecting plane **P0**. The algorithm descends until either:
|
|
|
|
* it has locked in an extended grapheme cluster, and fore/background colors, or
|
|
* all **i** planes have been examined
|
|
|
|
At each plane **P**, we consider a cell **C**. This cell is the intersecting cell,
|
|
unless that cell has no EGC. In that case, **C** is the plane's default cell.
|
|
|
|
* If we have not yet determined an EGC, and **C** has a non-zero EGC, use the EGC and style of **C**.
|
|
* If we have not yet locked in a foreground color, and **C** is not foreground-transparent, use the foreground color of **C** (see [BUGS][] below). If **C** is **CELL_ALPHA_OPAQUE**, lock the color in.
|
|
* If we have not yet locked in a background color, and **C** is not background-transparent, use the background color of **C** (see [BUGS][] below). If **C** is **CELL_ALPHA_OPAQUE**, lock the color in.
|
|
|
|
If the algorithm concludes without an EGC, the cell is rendered with no glyph
|
|
and a default background. If the algorithm concludes without a color locked in,
|
|
the color as computed thus far is used.
|
|
|
|
**notcurses_at_yx** retrieves a call *as rendered*. The EGC in that cell is
|
|
copied and returned; it must be **free(3)**d by the caller.
|
|
|
|
# RETURN VALUES
|
|
|
|
On success, 0 is returned. On failure, a non-zero value is returned. A success
|
|
will result in the **renders** stat being increased by 1. A failure will result
|
|
in the **failed_renders** stat being increased by 1.
|
|
|
|
**notcurses_at_yx** returns a heap-allocated copy of the cell's EGC on success,
|
|
and **NULL** on failure.
|
|
|
|
# BUGS
|
|
|
|
In addition to the RGB colors, it is possible to use the "default foreground color"
|
|
and "default background color" inherited from the terminal. Since
|
|
notcurses doesn't know what these colors are, they are not considered for
|
|
purposes of color blending.
|
|
|
|
# SEE ALSO
|
|
|
|
**notcurses(3)**,
|
|
**notcurses_cell(3)**,
|
|
**notcurses_input(3)**,
|
|
**notcurses_output(3)**,
|
|
**notcurses_plane(3)**,
|
|
**notcurses_refresh(3)**,
|
|
**notcurses_stats(3)**,
|
|
**notcurses_visual(3)**,
|
|
**console_codes(4)**,
|
|
**utf-8(7)**
|