diff --git a/USAGE.md b/USAGE.md index 78860bf3d..89f17a74c 100644 --- a/USAGE.md +++ b/USAGE.md @@ -2452,8 +2452,22 @@ a file. Both RGBA and BGRA 8bpc arrangements can be used. // are actual data. There must be 'rows' lines. The total size of 'rgba' // must thus be at least (rows * rowstride) bytes, of which (rows * cols * 4) // bytes are actual data. The resulting plane will be ceil('rows'/2)x'cols'. -ncvisual* ncvisual_from_rgba(notcurses* nc, const void* rgba, int rows, int rowstride, int cols); +struct ncvisual* ncvisual_from_rgba(struct notcurses* nc, const void* rgba, + int rows, int rowstride, int cols); // ncvisual_from_rgba(), but for BGRA. -ncvisual* ncvisual_from_bgra(notcurses* nc, const void* bgra, int rows, int rowstride, int cols); +struct ncvisual* ncvisual_from_bgra(struct notcurses* nc, const void* bgra, + int rows, int rowstride, int cols); +``` + +Finally, an `ncvisual` can be "promoted" from the contents of a plane. + +```c +// Promote an ncplane 'n' to an ncvisual. The plane should not be associated +// with an existing ncvisual, and may contain only spaces, half blocks, and +// full blocks. The latter will be checked, and any other glyph will result +// in a NULL being returned. This function exists so that planes can be +// subjected to ncvisual transformations. If possible, it's usually better +// to create the ncvisual from memory using ncvisual_from_rgba(). +struct ncvisual* ncvisual_from_plane(struct ncplane* n); ``` diff --git a/doc/man/man3/notcurses_visual.3.md b/doc/man/man3/notcurses_visual.3.md index 8220b3000..f34813e23 100644 --- a/doc/man/man3/notcurses_visual.3.md +++ b/doc/man/man3/notcurses_visual.3.md @@ -32,6 +32,8 @@ typedef int (*streamcb)(struct notcurses*, struct ncvisual*, void*); **struct ncvisual* ncvisual_from_bgra(struct notcurses* nc, const void* bgra, int rows, int rowstride, int cols);** +**struct ncvisual* ncvisual_from_plane(struct ncplane* n);** + **void ncvisual_destroy(struct ncvisual* ncv);** **nc_err_e ncvisual_decode(struct ncvisual* nc);** @@ -74,6 +76,11 @@ is necessary. The resulting plane will be ceil(**rows**/2) rows, and **cols** columns. It will not be necessary to call **ncvisual_decode**, but it is still necessary to call **ncvisual_render**. +The contents of an **ncplane** can be "promoted" into an **ncvisual** with +**ncvisual_from_ncplane**. The existing plane will be bound and decoded to a +new **ncvisual**. Only spaces, half blocks, and full blocks may be present +in the plane. + **ncvisual_rotate** executes a rotation of **rads** radians, in the clockwise (positive) or counterclockwise (negative) direction. If the **ncvisual** owns (created) its underlying **ncplane**, that plane will be resized as necessary @@ -96,6 +103,9 @@ will be updated. **ncvisual_decode** returns **NCERR_SUCCESS** on success, or likewise updates **err** in the event of an error. **ncvisual_render** returns the number of cells emitted, or -1 on error. +**ncvisual_from_plane** returns **NULL** if the **ncvisual** cannot be created +and bound. This is usually due to illegal content in the source **ncplane**. + # NOTES Multimedia decoding requires that Notcurses be built with either FFmpeg or diff --git a/python/src/notcurses/build_notcurses.py b/python/src/notcurses/build_notcurses.py index bf9e964d3..d690698f0 100644 --- a/python/src/notcurses/build_notcurses.py +++ b/python/src/notcurses/build_notcurses.py @@ -431,6 +431,7 @@ int ncplane_rotate_cw(struct ncplane* n); int ncplane_rotate_ccw(struct ncplane* n); int ncvisual_rotate(struct ncvisual* n, double rads); void ncplane_translate(const struct ncplane* src, const struct ncplane* dst, int* y, int* x); +struct ncvisual* ncvisual_from_plane(struct ncplane* n); bool ncplane_translate_abs(const struct ncplane* n, int* y, int* x); typedef enum { NCPLOT_1x1, // full block █