[quantanal] recover control sequence with ncplane_at_yx()

pull/2506/head
nick black 2 years ago committed by nick black
parent 0e190d0bc0
commit 635da75c3c

@ -9,6 +9,8 @@ rearrangements of Notcurses.
`NCOPTION_SCROLLING`, `NCOPTION_NO_CLEAR_BITMAPS`,
`NCOPTION_NO_ALTERNATE_SCREEN`, and `NCOPTION_PRESERVE_CURSOR`.
* Added `ncvisual_from_sixel()`.
* The control sequence corresponding to a pixel-blitted `ncvisual()`
can be retrieved by using `ncplane_at_yx()` on the sprixel plane.
* 3.0.1 (2021-12-14)
* Added the `NCPLANE_OPTION_VSCROLL` flag. Creating an `ncplane` with this

@ -375,6 +375,10 @@ secondary column of a wide glyph with **ncplane_at_yx_cell** will fill in
the **nccell** argument such that **nccell_extended_gcluster(3)** returns an
empty string, and **nccell_wide_right_p(3)** returns **true**.
If **ncplane_at_yx** is invoked upon a sprixel plane, the control sequence will
be returned for any valid coordinates (note that this may be quite large).
This does not apply to **ncplane_at_yx_cell**, which will return an error.
**ncplane_set_name** sets the plane's name, freeing any old name. ***name***
may be **NULL**. **ncplane_set_name** duplicates the provided name internally.

@ -1876,18 +1876,22 @@ API int ncplane_scrollup_child(struct ncplane* n, const struct ncplane* child)
// characters, spaces, half blocks, and full blocks. The plane must have
// an even number of columns. Use the ncvisual rotation for a more
// flexible approach.
API int ncplane_rotate_cw(struct ncplane* n);
API int ncplane_rotate_ccw(struct ncplane* n);
API int ncplane_rotate_cw(struct ncplane* n)
__attribute__ ((nonnull (1)));
API int ncplane_rotate_ccw(struct ncplane* n)
__attribute__ ((nonnull (1)));
// Retrieve the current contents of the cell under the cursor. The EGC is
// returned, or NULL on error. This EGC must be free()d by the caller. The
// stylemask and channels are written to 'stylemask' and 'channels', respectively.
API char* ncplane_at_cursor(struct ncplane* n, uint16_t* stylemask, uint64_t* channels);
API char* ncplane_at_cursor(struct ncplane* n, uint16_t* stylemask, uint64_t* channels)
__attribute__ ((nonnull (1)));
// Retrieve the current contents of the cell under the cursor into 'c'. This
// cell is invalidated if the associated plane is destroyed. Returns the number
// of bytes in the EGC, or -1 on error.
API int ncplane_at_cursor_cell(struct ncplane* n, nccell* c);
API int ncplane_at_cursor_cell(struct ncplane* n, nccell* c)
__attribute__ ((nonnull (1, 2)));
// Retrieve the current contents of the specified cell. The EGC is returned, or
// NULL on error. This EGC must be free()d by the caller. The stylemask and
@ -1895,16 +1899,20 @@ API int ncplane_at_cursor_cell(struct ncplane* n, nccell* c);
// represents how the cell will be used during rendering, and thus integrates
// any base cell where appropriate. If called upon the secondary columns of a
// wide glyph, the EGC will be returned (i.e. this function does not distinguish
// between the primary and secondary columns of a wide glyph).
// between the primary and secondary columns of a wide glyph). If called on a
// sprixel plane, its control sequence is returned for all valid locations.
API char* ncplane_at_yx(const struct ncplane* n, int y, int x,
uint16_t* stylemask, uint64_t* channels);
uint16_t* stylemask, uint64_t* channels)
__attribute__ ((nonnull (1)));
// Retrieve the current contents of the specified cell into 'c'. This cell is
// invalidated if the associated plane is destroyed. Returns the number of
// bytes in the EGC, or -1 on error. Unlike ncplane_at_yx(), when called upon
// the secondary columns of a wide glyph, the return can be distinguished from
// the primary column (nccell_wide_right_p(c) will return true).
API int ncplane_at_yx_cell(struct ncplane* n, int y, int x, nccell* c);
// the primary column (nccell_wide_right_p(c) will return true). It is an
// error to call this on a sprixel plane (unlike ncplane_at_yx()).
API int ncplane_at_yx_cell(struct ncplane* n, int y, int x, nccell* c)
__attribute__ ((nonnull (1, 4)));
// Create a flat string from the EGCs of the selected region of the ncplane
// 'n'. Start at the plane's 'begy'x'begx' coordinate (which must lie on the
@ -1912,20 +1920,24 @@ API int ncplane_at_yx_cell(struct ncplane* n, int y, int x, nccell* c);
// 'lenx' can be specified as 0 to go through the boundary of the plane.
// -1 can be specified for 'begx'/'begy' to use the current cursor location.
API char* ncplane_contents(struct ncplane* n, int begy, int begx,
unsigned leny, unsigned lenx);
unsigned leny, unsigned lenx)
__attribute__ ((nonnull (1)));
// Manipulate the opaque user pointer associated with this plane.
// ncplane_set_userptr() returns the previous userptr after replacing
// it with 'opaque'. the others simply return the userptr.
API void* ncplane_set_userptr(struct ncplane* n, void* opaque);
API void* ncplane_userptr(struct ncplane* n);
API void* ncplane_set_userptr(struct ncplane* n, void* opaque)
__attribute__ ((nonnull (1)));
API void* ncplane_userptr(struct ncplane* n)
__attribute__ ((nonnull (1)));
// Find the center coordinate of a plane, preferring the top/left in the
// case of an even number of rows/columns (in such a case, there will be one
// more cell to the bottom/right of the center than the top/left). The
// center is then modified relative to the plane's origin.
API void ncplane_center_abs(const struct ncplane* n, int* RESTRICT y,
int* RESTRICT x);
int* RESTRICT x)
__attribute__ ((nonnull (1)));
// Create an RGBA flat array from the selected region of the ncplane 'nc'.
// Start at the plane's 'begy'x'begx' coordinate (which must lie on the

@ -229,6 +229,15 @@ char* ncplane_at_yx(const ncplane* n, int y, int x, uint16_t* stylemask, uint64_
logerror("invalid coordinates: %d/%d", y, x);
return NULL;
}
if(n->sprite){
if(stylemask){
*stylemask = 0;
}
if(channels){
*channels = 0;
}
return strdup(n->sprite->glyph.buf);
}
const nccell* yx = &n->fb[nfbcellidx(n, y, x)];
// if we're the right side of a wide glyph, we return the main glyph
if(nccell_wide_right_p(yx)){
@ -258,6 +267,10 @@ int ncplane_at_cursor_cell(ncplane* n, nccell* c){
}
int ncplane_at_yx_cell(ncplane* n, int y, int x, nccell* c){
if(n->sprite){
logerror("invoked on a sprixel plane");
return -1;
}
if(y < 0){
if(y != -1){
logerror("invalid y: %d", y);

@ -1,8 +1,10 @@
#include <inttypes.h>
#include <notcurses/notcurses.h>
#include <compat/compat.h>
int main(int argc, char** argv){
if(argc < 2){
fprintf(stderr, "usage: %s images...\n", *argv);
fprintf(stderr, "usage: %s images..." NL, *argv);
return EXIT_FAILURE;
}
struct notcurses_options opts = {0};
@ -20,7 +22,7 @@ int main(int argc, char** argv){
struct ncvisual* ncv = ncvisual_from_file(*argv);
if(ncv == NULL){
notcurses_stop(nc);
fprintf(stderr, "error opening %s\n", *argv);
fprintf(stderr, "error opening %s" NL, *argv);
return EXIT_FAILURE;
}
struct ncplane* ncp = ncplane_dup(stdn, NULL);
@ -34,16 +36,25 @@ int main(int argc, char** argv){
vopts.flags = NCVISUAL_OPTION_NODEGRADE;
if(ncvisual_blit(nc, ncv, &vopts) == NULL){
notcurses_stop(nc);
fprintf(stderr, "error rendering %s\n", *argv);
fprintf(stderr, "error rendering %s" NL, *argv);
return EXIT_FAILURE;
}
// FIXME acquire sixel as s
char* s = strdup("");
char* s;
if((s = ncplane_at_yx(ncp, 0, 0, NULL, NULL)) == NULL){
notcurses_stop(nc);
fprintf(stderr, "error retrieving sixel for %s" NL, *argv);
return EXIT_FAILURE;
}
ncplane_set_fg_rgb(stdn, 0x74b72e);
size_t slen = strlen(s);
ncplane_printf(stdn, " control sequence: %" PRIuPTR " byte%s\n",
slen, slen == 1 ? "" : "s");
notcurses_render(nc);
unsigned leny = 0, lenx = 0; // FIXME
struct ncvisual* quantncv = ncvisual_from_sixel(s, leny, lenx);
if(quantncv == NULL){
notcurses_stop(nc);
fprintf(stderr, "error loading %zuB sixel\n", strlen(s));
fprintf(stderr, "error loading %" PRIuPTR "B sixel" NL, slen);
free(s);
return EXIT_FAILURE;
}

Loading…
Cancel
Save