mirror of
https://github.com/dankamongmen/notcurses
synced 2025-03-09 09:09:03 -04:00
render piles to file/buffer
Replace notcurses_render_to_file() and notcurses_render_to_buffer() with variants that work on arbitrary piles (the former only worked on the standard pile). Rewrite the former as trivial wrappers around the latter, and deprecate the former. Closes #1770.
This commit is contained in:
parent
921c2ce033
commit
379453c8ea
4
NEWS.md
4
NEWS.md
@ -28,6 +28,10 @@ rearrangements of Notcurses.
|
||||
They map to `NCLOGLEVEL_WARNING` and `NCLOGLEVEL_TRACE`, respectively.
|
||||
* New functions `ncvisual_from_rgb_packed()` and `ncvisual_from_rgb_loose()`.
|
||||
* New stat `sprixelbytes`.
|
||||
* Added new functions `ncpile_render_to_buffer()` and
|
||||
`ncpile_render_to_file()`. Rewrote `notcurses_render_to_buffer()` and
|
||||
`notcurses_render_to_file()` as trivial wrappers around these functions,
|
||||
and deprecated the latter. They will be removed in ABI3.
|
||||
|
||||
* 2.3.4 (2021-06-12)
|
||||
* Added the flag `NCVISUAL_OPTION_NOINTERPOLATE` to use non-interpolative
|
||||
|
9
USAGE.md
9
USAGE.md
@ -191,14 +191,13 @@ int ncpile_rasterize(struct ncplane* n);
|
||||
int notcurses_render(struct notcurses* nc);
|
||||
|
||||
// Perform the rendering and rasterization portion of notcurses_render(), but
|
||||
// do not write the resulting buffer out to the terminal. Using this function,
|
||||
// the user can control the writeout process, and render a second frame while
|
||||
// writing another. The returned buffer must be freed by the caller.
|
||||
int notcurses_render_to_buffer(struct notcurses* nc, char** buf, size_t* buflen);
|
||||
// do not write the resulting buffer out to the terminal. The returned buffer
|
||||
// must be freed by the caller.
|
||||
int ncpile_render_to_buffer(struct ncplane* p, char** buf, size_t* buflen);
|
||||
|
||||
// Write the last rendered frame, in its entirety, to 'fp'. If
|
||||
// notcurses_render() has not yet been called, nothing will be written.
|
||||
int notcurses_render_to_file(struct notcurses* nc, FILE* fp);
|
||||
int ncpile_render_to_file(struct ncplane* p, FILE* fp);
|
||||
|
||||
// Retrieve the contents of the specified cell as last rendered. The EGC is
|
||||
// returned, or NULL on error. This EGC must be free()d by the caller. The
|
||||
|
@ -18,9 +18,9 @@ notcurses_render - sync the physical display to a virtual pile
|
||||
|
||||
**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 ncpile_render_to_file(struct ncplane* ***p***, FILE* ***fp***);**
|
||||
|
||||
**int notcurses_render_to_buffer(struct notcurses* ***nc***, char\*\* ***buf***, size_t* ***buflen***);**
|
||||
**int ncpile_render_to_buffer(struct ncplane* ***p***, char\*\* ***buf***, size_t* ***buflen***);**
|
||||
|
||||
# DESCRIPTION
|
||||
|
||||
@ -50,11 +50,11 @@ 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.
|
||||
**ncpile_render_to_buffer** performs the render and raster processes of
|
||||
**ncpile_render** and **ncpile_rasterize**, 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
|
||||
|
@ -66,7 +66,7 @@ also resets all cumulative stats (immediate stats such as **fbbytes** are not
|
||||
reset).
|
||||
|
||||
**renders** is the number of successful calls to **notcurses_render(3)**
|
||||
or **notcurses_render_to_buffer(3)**. **failed_renders** is the number of
|
||||
or **ncpile_render_to_buffer(3)**. **failed_renders** is the number of
|
||||
unsuccessful calls to these functions. **failed_renders** should be 0;
|
||||
renders are not expected to fail except under exceptional circumstances.
|
||||
should **notcurses_render(3)** fail while writing out a frame to the terminal,
|
||||
@ -81,12 +81,12 @@ ingest and reflect a frame is dependent on the size of the rasterized frame.
|
||||
**render_ns**, **render_max_ns**, and **render_min_ns** track the total
|
||||
amount of time spent rendering frames in nanoseconds. Rendering
|
||||
takes place in **ncpile_render** (called by **notcurses_render(3)** and
|
||||
**notcurses_render_to_buffer**). This step is independent of the terminal.
|
||||
**ncpile_render_to_buffer**). This step is independent of the terminal.
|
||||
|
||||
**raster_ns**, **raster_max_ns**, and **raster_min_ns** track the total
|
||||
amount of time spent rasterizing frames in nanoseconds. Rasterizing
|
||||
takes place in **ncpile_raster** (called by **notcurses_raster(3)** and
|
||||
**notcurses_render_to_buffer**). This step depends on the terminal definitions.
|
||||
**ncpile_render_to_buffer**). This step depends on the terminal definitions.
|
||||
The same frame might not rasterize to the same bytes for different terminals.
|
||||
|
||||
**writeout_ns**, **writeout_max_ns**, and **writeout_min_ns** track the total
|
||||
|
@ -200,16 +200,6 @@ namespace ncpp
|
||||
return error_guard (notcurses_render (nc), -1);
|
||||
}
|
||||
|
||||
bool render_to_buffer (char** buf, size_t* buflen) const NOEXCEPT_MAYBE
|
||||
{
|
||||
return error_guard (notcurses_render_to_buffer (nc, buf, buflen), -1);
|
||||
}
|
||||
|
||||
bool render_to_file (FILE* fp) const NOEXCEPT_MAYBE
|
||||
{
|
||||
return error_guard (notcurses_render_to_file (nc, fp), -1);
|
||||
}
|
||||
|
||||
void get_term_dim (int *rows, int *cols) const noexcept
|
||||
{
|
||||
notcurses_term_dim_yx (nc, rows, cols);
|
||||
|
@ -941,15 +941,15 @@ API int ncpile_rasterize(struct ncplane* n);
|
||||
// Renders and rasterizes the standard pile in one shot. Blocking call.
|
||||
API int notcurses_render(struct notcurses* nc);
|
||||
|
||||
// Perform the rendering and rasterization portion of notcurses_render(), but
|
||||
// do not write the resulting buffer out to the terminal. Using this function,
|
||||
// the user can control the writeout process, and render a second frame while
|
||||
// writing another. The returned buffer must be freed by the caller.
|
||||
API int notcurses_render_to_buffer(struct notcurses* nc, char** buf, size_t* buflen);
|
||||
// Perform the rendering and rasterization portion of ncpile_render() and
|
||||
// ncpile_rasterize(), but do not write the resulting buffer out to the
|
||||
// terminal. Using this function, the user can control the writeout process.
|
||||
// The returned buffer must be freed by the caller.
|
||||
API int ncpile_render_to_buffer(struct ncplane* p, char** buf, size_t* buflen);
|
||||
|
||||
// Write the last rendered frame, in its entirety, to 'fp'. If
|
||||
// notcurses_render() has not yet been called, nothing will be written.
|
||||
API int notcurses_render_to_file(struct notcurses* nc, FILE* fp);
|
||||
API int ncpile_render_to_file(struct ncplane* p, FILE* fp);
|
||||
|
||||
// Return the topmost ncplane of the standard pile.
|
||||
API struct ncplane* notcurses_top(struct notcurses* n);
|
||||
@ -4349,6 +4349,12 @@ channels_set_bg_default(uint64_t* channels){
|
||||
API __attribute__ ((deprecated)) int ncvisual_inflate(struct ncvisual* n, int scale)
|
||||
__attribute__ ((nonnull (1)));
|
||||
|
||||
API int notcurses_render_to_buffer(struct notcurses* nc, char** buf, size_t* buflen)
|
||||
__attribute__ ((deprecated));
|
||||
|
||||
API int notcurses_render_to_file(struct notcurses* nc, FILE* fp)
|
||||
__attribute__ ((deprecated));
|
||||
|
||||
typedef nccell cell; // FIXME backwards-compat, remove in ABI3
|
||||
|
||||
#define CELL_ALPHA_HIGHCONTRAST NCALPHA_HIGHCONTRAST
|
||||
|
@ -1231,7 +1231,9 @@ int notcurses_refresh(notcurses* nc, int* restrict dimy, int* restrict dimx){
|
||||
return 0;
|
||||
}
|
||||
|
||||
int notcurses_render_to_file(notcurses* nc, FILE* fp){
|
||||
int ncpile_render_to_file(ncplane* n, FILE* fp){
|
||||
notcurses* nc = ncplane_notcurses(n);
|
||||
ncpile* p = ncplane_pile(n);
|
||||
if(nc->lfdimx == 0 || nc->lfdimy == 0){
|
||||
return 0;
|
||||
}
|
||||
@ -1241,23 +1243,20 @@ int notcurses_render_to_file(notcurses* nc, FILE* fp){
|
||||
if(out == NULL){
|
||||
return -1;
|
||||
}
|
||||
ncpile p;
|
||||
p.dimy = nc->margin_t;
|
||||
p.dimx = nc->margin_l;
|
||||
const int count = (nc->lfdimx > p.dimx ? nc->lfdimx : p.dimx) *
|
||||
(nc->lfdimy > p.dimy ? nc->lfdimy : p.dimy);
|
||||
p.crender = malloc(count * sizeof(*p.crender));
|
||||
if(p.crender == NULL){
|
||||
const int count = (nc->lfdimx > p->dimx ? nc->lfdimx : p->dimx) *
|
||||
(nc->lfdimy > p->dimy ? nc->lfdimy : p->dimy);
|
||||
p->crender = malloc(count * sizeof(*p->crender));
|
||||
if(p->crender == NULL){
|
||||
fclose(out);
|
||||
free(rastered);
|
||||
return -1;
|
||||
}
|
||||
init_rvec(p.crender, count);
|
||||
init_rvec(p->crender, count);
|
||||
for(int i = 0 ; i < count ; ++i){
|
||||
p.crender[i].s.damaged = 1;
|
||||
p->crender[i].s.damaged = 1;
|
||||
}
|
||||
int ret = raster_and_write(nc, &p, out);
|
||||
free(p.crender);
|
||||
int ret = raster_and_write(nc, p, out);
|
||||
free(p->crender);
|
||||
if(ret > 0){
|
||||
if(fprintf(fp, "%s", rastered) == ret){
|
||||
ret = 0;
|
||||
@ -1270,6 +1269,9 @@ int notcurses_render_to_file(notcurses* nc, FILE* fp){
|
||||
return ret;
|
||||
}
|
||||
|
||||
int notcurses_render_to_file(notcurses* nc, FILE* fp){
|
||||
return ncpile_render_to_file(notcurses_stdplane(nc), fp);
|
||||
}
|
||||
|
||||
// We execute the painter's algorithm, starting from our topmost plane. The
|
||||
// damagevector should be all zeros on input. On success, it will reflect
|
||||
@ -1377,12 +1379,12 @@ int notcurses_render(notcurses* nc){
|
||||
// for now, we just run the top half of notcurses_render(), and copy out the
|
||||
// memstream from within rstate. we want to allocate our own here, and return
|
||||
// it, to avoid the copy, but we need feed the params through to do so FIXME.
|
||||
int notcurses_render_to_buffer(notcurses* nc, char** buf, size_t* buflen){
|
||||
ncplane* stdn = notcurses_stdplane(nc);
|
||||
if(ncpile_render(stdn)){
|
||||
int ncpile_render_to_buffer(ncplane* p, char** buf, size_t* buflen){
|
||||
if(ncpile_render(p)){
|
||||
return -1;
|
||||
}
|
||||
int bytes = notcurses_rasterize_inner(nc, ncplane_pile(stdn), nc->rstate.mstreamfp);
|
||||
notcurses* nc = ncplane_notcurses(p);
|
||||
int bytes = notcurses_rasterize_inner(nc, ncplane_pile(p), nc->rstate.mstreamfp);
|
||||
pthread_mutex_lock(&nc->statlock);
|
||||
update_render_bytes(&nc->stats, bytes);
|
||||
pthread_mutex_unlock(&nc->statlock);
|
||||
@ -1397,6 +1399,10 @@ int notcurses_render_to_buffer(notcurses* nc, char** buf, size_t* buflen){
|
||||
return 0;
|
||||
}
|
||||
|
||||
int notcurses_render_to_buffer(notcurses* nc, char** buf, size_t* buflen){
|
||||
return ncpile_render_to_buffer(notcurses_stdplane(nc), buf, buflen);
|
||||
}
|
||||
|
||||
// copy the UTF8-encoded EGC out of the cell, whether simple or complex. the
|
||||
// result is not tied to the ncplane, and persists across erases / destruction.
|
||||
static inline char*
|
||||
|
Loading…
x
Reference in New Issue
Block a user