Skip to content

Commit

Permalink
Dankamongmen/ncvisual blit (#2276)
Browse files Browse the repository at this point in the history
* [heuristics] GNU screen 4x never has rgb

* [BitmapSmoothMove] only WARN in test until sixel supports this #2258

* add minimal example for #2266

* contour: enable sextants

* interp PoC: clean up ncvisual #2266

* ncselector_options: constify string arguments

* Constify strings in selector/mselector_items

Use internal types to track items within the
selector/mselector widgets, rather than pressing the
user-provided item structs into double-duty. With this
change, we can constify the strings within those
user-provided items. Do so, also removing the internal-side
elements. Update documentation. Closes #2267.

* constify ncmenu_item/_section strings

* Use Windows pipes for input readiness notification (#2263)

* [windows] use CreatePipe for input #2244
* [input] read and write to Windows readiness handles #2244
* inputready_fd: not on windows, alas

* for now, if it's on windows, it's windows terminal #2248

* tabbed janitorial work

clean up memory leak of tab names
ignore NCTYPE_RELEASE in tabbed PoC
constify strings in nctabbed_options

* notcurses-demo FPS graph: back to straight seconds

* [info] expand some emoji into proper literals

* drop textplay PoC

* remove poc for issue #2266

* constify ncselector_item reference fix #2270

* [ncplayer] restore pause functionality with NCTYPE_RELEASE

* stop pushing termtype to interrogate_terminfo

* menu PoC: ignore NCTYPE_RELEASE

* properly name Windows Terminal

* [windows] HANDLE, not PHANDLE

* ncvisual_render -> ncvisual_blit (core/test) #1462

* ncvisual_render -> ncvisual_blit (docs)

* ncvisual_render -> ncvisual_blit (nctetris)

* [keller] fix up for ncvisual_blit() #1462

* stacking tests: ncvisual_render() -> ncvisual_blit() #1462

* all PoCs: ncvisual_render -> ncvisual_blit #1462

* restore ncvisual_inflate(), for now

* pixel PoC / ncneofetch -> ncvisual_blit() #1462

* notcurses-info: ncvisual_blit, inline all emoji #1462

* rotate PoCpp: ncvisual_blit() #1462

* xray/grid: ncvisual_blit() #1462

* remove last instances of ncvisual_render() #1462

* remove old-style notcurses_ rendering functions

Make notcurses_render() a static inline wrapper around
ncpile_render(). Remove the deprecated
notcurses_render_to_file() and ncpile_render_to_file().
ABI3 work #1777.

* ncstrwidth() becomes static inline wrapper #1777

* remove deprecated ncvisual_subtitle()

* kill ncvisual_inflate(), long deprecated #1777

* remove deprecated palette256 wrappers #1777

* kill ncplane_new() #1777

* remove deprecated renderfp field from notcurses_options #1777

* reorder ncstats fields to match documentation #1777

* kill deprecated style functions #1777

* ncplane_move{top, bottom} become static inline #1777

* fix up move_above()/move_below() #1777

* ncplane_pixelgeom -> ncplane_pixel_geom() #1777

* ncstyle functions ought return uint16_t #1777 #2200

* ncvisualplane_create: provide new pile functionality #1462

* introduce ncvisual_blit() #1462

* reduce ncvisual_render() to wrapper around ncvisual_blit() #1462

* convert most ncvisual_render()s to ncvisual_blit() #1642

Co-authored-by: joseLuís <joseluis@andamira.net>
  • Loading branch information
dankamongmen and joseluis authored Oct 16, 2021
1 parent 9fa16c9 commit 31bd0e2
Show file tree
Hide file tree
Showing 66 changed files with 638 additions and 641 deletions.
11 changes: 11 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,17 @@ rearrangements of Notcurses.
* `ncvisualplane_create()` now allows for a new pile to be created, by
passing a `NULL` ancestor `ncplane` in `vopts`. The first argument is
now a `struct notcurses*` rather than a `struct ncplane*`.
* `ncvisual_render()` has been deprecated in favor of the new function
`ncvisual_blit()`. When a `NULL` `vopts->n` is passed to `ncvisual_blit()`,
a new plane is created (as it was in `ncvisual_render()`, but that plane
is the root of a new pile, rather than a child of the standard plane.
The only tricky conversion is if you previously had `vopts.n` as `NULL`,
and were not using `NCVISUAL_OPTION_CHILDPLANE` (or were passing `NULL`
as `vopts`). This would result in a new plane bound to the standard plane
with `ncvisual_render()`, but with `ncvisual_blit()` it will create a new
pile. To keep the behavior, explicitly pass the standard plane as
`vopts->n`, and include `NCVISUAL_OPTION_CHILDPLANE` in `vopts->flags`.
All other cases will continue to work as they did before.

* 2.4.5 (2021-10-06)
* The poorly-considered function `ncplane_boundlist()`, added in 2.3.17, has
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ If things break or seem otherwise lackluster, **please** consult the
Notcurses will not make use of bitmap protocols unless the terminal positively
indicates support for them, even if `NCBLIT_PIXEL` has been requested. Likewise,
sextants (`NCBLIT_3x2`) won't be used without Unicode 13 support, etc.
`ncvisual_render()` will use the best blitter available, unless
`ncvisual_blit()` will use the best blitter available, unless
`NCVISUAL_OPTION_NODEGRADE` is provided (in which case it will fail).
</details>

Expand Down
33 changes: 7 additions & 26 deletions USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -3312,8 +3312,8 @@ int ncvisual_set_yx(const struct ncvisual* n, int y, int x, uint32_t pixel);
// If a subtitle ought be displayed at this time, return a new plane (bound
// to 'parent' containing the subtitle, which might be text or graphics
// (depending on the input format).
struct ncplane* ncvisual_subtitle(struct ncplane* parent,
const struct ncvisual* ncv);
struct ncplane* ncvisual_subtitle_plane(struct ncplane* parent,
const struct ncvisual* ncv);
```
And finally, the `ncvisual` can be blitted to one or more `ncplane`s:
Expand All @@ -3330,8 +3330,8 @@ And finally, the `ncvisual` can be blitted to one or more `ncplane`s:
// specify any region beyond the boundaries of the frame. Returns the (possibly
// newly-created) plane to which we drew. Pixels may not be blitted to the
// standard plane.
struct ncplane* ncvisual_render(struct notcurses* nc, struct ncvisual* ncv,
const struct ncvisual_options* vopts)
struct ncplane* ncvisual_blit(struct notcurses* nc, struct ncvisual* ncv,
const struct ncvisual_options* vopts);
// Create a new plane as prescribed in opts, either as a child of 'vopts->n',
// or the root of a new pile if 'vopts->n' is NULL (or 'vopts' itself is NULL).
Expand All @@ -3342,7 +3342,7 @@ ncvisualplane_create(struct notcurses* nc, const struct ncplane_options* opts,
struct ncvisual* ncv, struct ncvisual_options* vopts);
// decode the next frame ala ncvisual_decode(), but if we have reached the end,
// rewind to the first frame of the ncvisual. a subsequent `ncvisual_render()`
// rewind to the first frame of the ncvisual. a subsequent `ncvisual_blit()`
// will render the first frame, as if the ncvisual had been closed and reopened.
// the return values remain the same as those of ncvisual_decode().
int ncvisual_decode_loop(struct ncvisual* nc);
Expand Down Expand Up @@ -3435,27 +3435,8 @@ typedef int (*streamcb)(struct ncplane*, struct ncvisual*,
// Shut up and display my frames! Provide as an argument to ncvisual_stream().
// If you'd like subtitles to be decoded, provide an ncplane as the curry. If the
// curry is NULL, subtitles will not be displayed.
static inline int
ncvisual_simple_streamer(struct ncplane* n, struct ncvisual* ncv,
const struct timespec* tspec, void* curry){
if(notcurses_render(ncplane_notcurses(n))){
return -1;
}
int ret = 0;
if(curry){
// need a cast for C++ callers
struct ncplane* subncp = (struct ncplane*)curry;
char* subtitle = ncvisual_subtitle(ncv);
if(subtitle){
if(ncplane_putstr_yx(subncp, 0, 0, subtitle) < 0){
ret = -1;
}
free(subtitle);
}
}
clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, tspec, NULL);
return ret;
}
int ncvisual_simple_streamer(struct ncvisual* ncv, struct ncvisual_options* vopts,
const struct timespec* tspec, void* curry);
// Stream the entirety of the media, according to its own timing. Blocking,
// obviously. streamer may be NULL; it is otherwise called for each frame, and
Expand Down
2 changes: 1 addition & 1 deletion doc/HACKING.md
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ Its `data` field holds RGBA pixels as provided from disk or memory. Its `pixx`,
`rowstride` bytes, each containing `pixx` RGBA pixels at the front, plus any
necessary padding (external libraries might generate padded output).

`ncvisual_render` works with at least four geometries:
`ncvisual_blit` works with at least four geometries:
* `vopts->begy`/`begx`: offsets into unscaled data (pixels)
* `vopts->leny`/`lenx`: lengths of unscaled data to use (pixels)
* These geometries, when summed, must not exceed `ncv->pixy`/`ncv->pixx`.
Expand Down
6 changes: 3 additions & 3 deletions doc/man/man3/notcurses_menu.3.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ struct ncplane;
struct notcurses;

struct ncmenu_section {
char* name; // utf-8 c string
const char* name; // utf-8 c string
struct ncmenu_item {
char* desc; // utf-8 menu item, NULL for horizontal separator
ncinput shortcut; // shortcut, all should be distinct
const char* desc; // utf-8 menu item, NULL for horizontal separator
ncinput shortcut; // shortcut, all should be distinct
}* items;
int itemcount;
};
Expand Down
11 changes: 5 additions & 6 deletions doc/man/man3/notcurses_multiselector.3.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,14 @@ struct notcurses;
struct ncmultiselector;

struct ncmselector_item {
char* option;
char* desc;
bool selected;
const char* option;
const char* desc;
};

typedef struct ncmultiselector_options {
char* title; // title may be NULL, inhibiting riser
char* secondary; // secondary may be NULL
char* footer; // footer may be NULL
const char* title; // title may be NULL, inhibiting riser
const char* secondary; // secondary may be NULL
const char* footer; // footer may be NULL
struct ncmselector_item* items; // initial items, statuses
// default item (selected at start)
unsigned defidx;
Expand Down
2 changes: 1 addition & 1 deletion doc/man/man3/notcurses_plane.3.md
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ the size of a cell in pixels (these ought be the same across planes).
**maxbmapy** and **maxbmapx** describe the largest bitmap which can be
displayed in the plane. Any parameter (save **n**) may be **NULL**.
When a plane is blitted to using **ncvisual_render** and **NCBLIT_PIXEL** (see
When a plane is blitted to using **ncvisual_blit** and **NCBLIT_PIXEL** (see
**notcurses_visual(3)**), it ceases to accept cell-based output. The sprixel
will remain associated until a new sprixel is blitted to the plane, the plane
is resized, the plane is erased, or the plane is destroyed. The base cell of a
Expand Down
10 changes: 5 additions & 5 deletions doc/man/man3/notcurses_selector.3.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ struct notcurses;
struct ncselector;

struct ncselector_item {
char* option;
char* desc;
const char* option;
const char* desc;
};

typedef struct ncselector_options {
char* title; // title may be NULL, inhibiting riser
char* secondary; // secondary may be NULL
char* footer; // footer may be NULL
const char* title; // title may be NULL, inhibiting riser
const char* secondary; // secondary may be NULL
const char* footer; // footer may be NULL
struct ncselector_item* items; // initial items and descriptions
// default item (selected at start)
unsigned defidx;
Expand Down
2 changes: 1 addition & 1 deletion doc/man/man3/notcurses_tabbed.3.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ typedef struct nctabbed_options {
uint64_t selchan; // channel for the selected tab header
uint64_t hdrchan; // channel for unselected tab headers
uint64_t sepchan; // channel for the tab separator
char* separator; // separator string (copied by nctabbed_create())
const char* separator; // separator string (copied by nctabbed_create())
uint64_t flags; // bitmask of NCTABBED_OPTION_*
} nctabbed_options;

Expand Down
16 changes: 9 additions & 7 deletions doc/man/man3/notcurses_visual.3.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ typedef int (*streamcb)(struct notcurses*, struct ncvisual*, void*);

**int ncvisual_decode_loop(struct ncvisual* ***ncv***);**

**struct ncplane* ncvisual_render(struct notcurses* ***nc***, struct ncvisual* ***ncv***, const struct ncvisual_options* ***vopts***);**
**struct ncplane* ncvisual_blit(struct notcurses* ***nc***, struct ncvisual* ***ncv***, const struct ncvisual_options* ***vopts***);**

**static inline struct ncplane* ncvisualplane_create(struct notcurses* ***nc***, const struct ncplane_options* ***opts***, struct ncvisual* ***ncv***, struct ncvisual_options* ***vopts***);**

**static inline struct ncplane* ncvisualplane_create(struct notcurses* ***nc***, const struct ncplane_options* ***opts***, struct ncvisual* ***ncv***, struct ncvisual_options* ***vopts***);**

Expand Down Expand Up @@ -159,7 +161,7 @@ if the current frame had such a subtitle. Note that the same subtitle might
be returned for multiple frames, or might not. It is atypical for all frames
to have subtitles. Subtitles can be text or graphics.

**ncvisual_render** blits the visual to an **ncplane**, based on the contents
**ncvisual_blit** draws the visual to an **ncplane**, based on the contents
of its **struct ncvisual_options**. If ***n*** is not **NULL**, it specifies the
plane on which to render, and ***y***/***x*** specify a location within that plane.
Otherwise, a new plane will be created, and placed at ***y***/***x*** relative to
Expand Down Expand Up @@ -273,7 +275,7 @@ information.

Some terminals support pixel-based output via one of a number of protocols.
**NCBLIT_PIXEL** has some stringent requirements on the type of planes it can
be used with; it is usually best to let **ncvisual_render** create the backing
be used with; it is usually best to let **ncvisual_blit** create the backing
plane by providing a **NULL** value for **n**. If you must bring your own
plane, it must be perfectly sized for the bitmap (i.e. large enough, and not
more than a full cell larger in either dimension--the bitmap, always placed at
Expand Down Expand Up @@ -307,12 +309,12 @@ that the entire file is properly-formed.
failure. It is only necessary for multimedia-based visuals. It advances one
frame for each call. **ncvisual_decode_loop** has the same return values: when
called following decoding of the last frame, it will return 1, but a subsequent
**ncvisual_render** will return the first frame.
**ncvisual_blit** will return the first frame.

**ncvisual_from_plane** returns **NULL** if the **ncvisual** cannot be created
and bound. This is usually due to illegal content in the source **ncplane**.

**ncvisual_render** returns **NULL** on error, and otherwise the plane to
**ncvisual_blit** returns **NULL** on error, and otherwise the plane to
which the visual was rendered. If **opts->n** is provided, this will be
**opts->n**. Otherwise, a plane will be created, perfectly sized for the
visual and the specified blitter.
Expand Down Expand Up @@ -369,7 +371,7 @@ sprixel cannot be accessed.
**ncvisual_rotate** currently supports only **M_PI**/2 and -**M_PI**/2
radians for **rads**, but this will change soon.

**ncvisual_render** should be able to create new planes in piles other than
**ncvisual_blit** should be able to create new planes in piles other than
the standard pile. This ought become a reality soon.

**ncvisual_stream** currently requires a multimedia engine, which is silly.
Expand All @@ -378,7 +380,7 @@ This will change in the near future.
Sprixels interact poorly with multiple planes, and such usage is discouraged.
This situation might improve in the future.

Multiple threads may not currently call **ncvisual_render** concurrently
Multiple threads may not currently call **ncvisual_blit** concurrently
using the same **ncvisual**, even if targeting distinct **ncplane**s. This
will likely change in the future.

Expand Down
4 changes: 2 additions & 2 deletions include/ncpp/Visual.hh
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ namespace ncpp
return ncvisual_decode_loop (visual);
}

ncplane* render (const ncvisual_options* vopts) const NOEXCEPT_MAYBE
ncplane* blit (const ncvisual_options* vopts) const NOEXCEPT_MAYBE
{
return error_guard<ncplane*, ncplane*> (ncvisual_render (get_notcurses (), visual, vopts), nullptr);
return error_guard<ncplane*, ncplane*> (ncvisual_blit (get_notcurses (), visual, vopts), nullptr);
}

int stream (const ncvisual_options* vopts, float timescale, ncstreamcb streamer, void *curry = nullptr) const NOEXCEPT_MAYBE
Expand Down
59 changes: 36 additions & 23 deletions include/notcurses/notcurses.h
Original file line number Diff line number Diff line change
Expand Up @@ -2899,7 +2899,7 @@ API int ncvisual_decode(struct ncvisual* nc)
__attribute__ ((nonnull (1)));

// decode the next frame ala ncvisual_decode(), but if we have reached the end,
// rewind to the first frame of the ncvisual. a subsequent 'ncvisual_render()'
// rewind to the first frame of the ncvisual. a subsequent 'ncvisual_blit()'
// will render the first frame, as if the ncvisual had been closed and reopened.
// the return values remain the same as those of ncvisual_decode().
API int ncvisual_decode_loop(struct ncvisual* nc)
Expand Down Expand Up @@ -2945,6 +2945,21 @@ API int ncvisual_set_yx(const struct ncvisual* n, int y, int x, uint32_t pixel)
// standard plane.
API struct ncplane* ncvisual_render(struct notcurses* nc, struct ncvisual* ncv,
const struct ncvisual_options* vopts)
__attribute__ ((deprecated)) __attribute__ ((nonnull (2)));

// Render the decoded frame according to the provided options (which may be
// NULL). The plane used for rendering depends on vopts->n and vopts->flags.
// If NCVISUAL_OPTION_CHILDPLANE is set, vopts->n must not be NULL, and the
// plane will always be created as a child of vopts->n. If this flag is not
// set, and vopts->n is NULL, a new plane is created as root of a new pile.
// If the flag is not set and vopts->n is not NULL, we render to vopts->n.
// A subregion of the visual can be rendered using 'begx', 'begy', 'lenx', and
// 'leny'. Negative values for 'begy' or 'begx' are an error. It is an error to
// specify any region beyond the boundaries of the frame. Returns the (possibly
// newly-created) plane to which we drew. Pixels may not be blitted to the
// standard plane.
API struct ncplane* ncvisual_blit(struct notcurses* nc, struct ncvisual* ncv,
const struct ncvisual_options* vopts)
__attribute__ ((nonnull (2)));

// Create a new plane as prescribed in opts, either as a child of 'vopts->n',
Expand Down Expand Up @@ -2972,7 +2987,7 @@ ncvisualplane_create(struct notcurses* nc, const struct ncplane_options* opts,
memset(vopts, 0, sizeof(*vopts));
}
vopts->n = newn;
if(ncvisual_render(nc, ncv, vopts) == NULL){
if(ncvisual_blit(nc, ncv, vopts) == NULL){
ncplane_destroy(newn);
vopts->n = NULL;
return NULL;
Expand Down Expand Up @@ -3047,7 +3062,7 @@ API int ncblit_rgb_loose(const void* data, int linesize,

// The ncpixel API facilitates direct management of the pixels within an
// ncvisual (ncvisuals keep a backing store of 32-bit RGBA pixels, and render
// them down to terminal graphics in ncvisual_render()).
// them down to terminal graphics in ncvisual_blit()).
//
// Per libav, we "store as BGRA on little-endian, and ARGB on big-endian".
// This is an RGBA *byte-order* scheme. libav emits bytes, not words. Those
Expand Down Expand Up @@ -3350,17 +3365,15 @@ API void ncplane_greyscale(struct ncplane* n);
//
// At all times, exactly one item is selected.
struct ncselector_item {
char* option;
char* desc;
size_t opcolumns; // filled in by library
size_t desccolumns; // filled in by library
const char* option;
const char* desc;
};

typedef struct ncselector_options {
char* title; // title may be NULL, inhibiting riser, saving two rows.
char* secondary; // secondary may be NULL
char* footer; // footer may be NULL
struct ncselector_item* items; // initial items and descriptions
const char* title; // title may be NULL, inhibiting riser, saving two rows.
const char* secondary; // secondary may be NULL
const char* footer; // footer may be NULL
const struct ncselector_item* items; // initial items and descriptions
// default item (selected at start), must be < itemcount unless itemcount is
// 0, in which case 'defidx' must also be 0
unsigned defidx;
Expand Down Expand Up @@ -3409,8 +3422,8 @@ API bool ncselector_offer_input(struct ncselector* n, const ncinput* nc)
API void ncselector_destroy(struct ncselector* n, char** item);

struct ncmselector_item {
char* option;
char* desc;
const char* option;
const char* desc;
bool selected;
};

Expand All @@ -3436,10 +3449,10 @@ struct ncmselector_item {
// Unlike the selector widget, zero to all of the items can be selected, but
// also the widget does not support adding or removing items at runtime.
typedef struct ncmultiselector_options {
char* title; // title may be NULL, inhibiting riser, saving two rows.
char* secondary; // secondary may be NULL
char* footer; // footer may be NULL
struct ncmselector_item* items; // initial items, descriptions, and statuses
const char* title; // title may be NULL, inhibiting riser, saving two rows.
const char* secondary; // secondary may be NULL
const char* footer; // footer may be NULL
const struct ncmselector_item* items; // initial items, descriptions, and statuses
// maximum number of options to display at once, 0 to use all available space
unsigned maxdisplay;
// exhaustive styling options
Expand Down Expand Up @@ -3546,12 +3559,12 @@ API void nctree_destroy(struct nctree* n);
// a plane resize, menus will be automatically moved/resized. Elements can be
// dynamically enabled or disabled at all levels (menu, section, and item),
struct ncmenu_item {
char* desc; // utf-8 menu item, NULL for horizontal separator
const char* desc; // utf-8 menu item, NULL for horizontal separator
ncinput shortcut; // shortcut, all should be distinct
};

struct ncmenu_section {
char* name; // utf-8 c string
const char* name; // utf-8 c string
int itemcount;
struct ncmenu_item* items;
ncinput shortcut; // shortcut, will be underlined if present in name
Expand Down Expand Up @@ -3673,7 +3686,7 @@ typedef struct nctabbed_options {
uint64_t selchan; // channel for the selected tab header
uint64_t hdrchan; // channel for unselected tab headers
uint64_t sepchan; // channel for the tab separator
char* separator; // separator string (copied by nctabbed_create())
const char* separator; // separator string (copied by nctabbed_create())
uint64_t flags; // bitmask of NCTABBED_OPTION_*
} nctabbed_options;

Expand Down Expand Up @@ -4009,17 +4022,17 @@ typedef struct ncsubproc_options {

// see exec(2). p-types use $PATH. e-type passes environment vars.
API ALLOC struct ncsubproc* ncsubproc_createv(struct ncplane* n, const ncsubproc_options* opts,
const char* bin, char* const arg[],
const char* bin, char* const arg[],
ncfdplane_callback cbfxn, ncfdplane_done_cb donecbfxn)
__attribute__ ((nonnull (1)));

API ALLOC struct ncsubproc* ncsubproc_createvp(struct ncplane* n, const ncsubproc_options* opts,
const char* bin, char* const arg[],
const char* bin, char* const arg[],
ncfdplane_callback cbfxn, ncfdplane_done_cb donecbfxn)
__attribute__ ((nonnull (1)));

API ALLOC struct ncsubproc* ncsubproc_createvpe(struct ncplane* n, const ncsubproc_options* opts,
const char* bin, char* const arg[], char* const env[],
const char* bin, char* const arg[], char* const env[],
ncfdplane_callback cbfxn, ncfdplane_done_cb donecbfxn)
__attribute__ ((nonnull (1)));

Expand Down
Loading

0 comments on commit 31bd0e2

Please sign in to comment.