[mergeplane] 0 means remainder #1696

pull/2331/head
nick black 3 years ago committed by nick black
parent 042d810722
commit 3792dd5592

@ -18,7 +18,8 @@ rearrangements of Notcurses.
`ncplane_as_rgba()`, `ncplane_contents()`, and `ncvisual_from_plane()`,
which all used -1. A length of zero passed to line-drawing functions is
now an error. Several line-drawing functions now reliably return errors
as opposed to short successes.
as opposed to short successes. Dimensions of 0 to `ncplane_mergedown()`
now mean "everything".
* `ncvisual_geom()` has been introduced, using the `ncvgeom` struct
introduced for direct mode. This allows complete statement of geometry
for an `ncvisual`. It replaces `ncvisual_blitter_geom()`, which has been

@ -918,12 +918,18 @@ struct ncplane* ncplane_dup(struct ncplane* n, void* opaque);
// Merge the ncplane 'src' down onto the ncplane 'dst'. This is most rigorously
// defined as "write to 'dst' the frame that would be rendered were the entire
// stack made up only of 'src' and, below it, 'dst', and 'dst' was the entire
// rendering region." Merging is independent of the position of 'src' viz 'dst'
// on the z-axis. If 'src' does not intersect with 'dst', 'dst' will not be
// changed, but it is not an error. The source plane still exists following
// this operation. Do not supply the same plane for both 'src' and 'dst'.
int ncplane_mergedown(struct ncplane* restrict src, struct ncplane* restrict dst);
// stack made up only of the specified subregion of 'src' and, below it, the
// subregion of 'dst' having the specified origin. Merging is independent of
// the position of 'src' viz 'dst' on the z-axis. It is an error to define a
// subregion that is not entirely contained within 'src'. It is an error to
// define a target origin such that the projected subregion is not entirely
// contained within 'dst'. Behavior is undefined if 'src' and 'dst' are
// equivalent. 'dst' is modified, but 'src' remains unchanged. Neither 'src'
// nor 'dst' may have sprixels. Lengths of 0 mean "everything left".
int ncplane_mergedown(struct ncplane* restrict src, struct ncplane* restrict dst,
unsigned begsrcy, unsigned begsrcx,
unsigned leny, unsigned lenx,
unsigned dsty, unsigned dstx);
// Merge the entirety of 'src' down onto the ncplane 'dst'. If 'src' does not
// intersect with 'dst', 'dst' will not be changed, but it is not an error.

@ -205,7 +205,7 @@ typedef struct ncplane_options {
**void notcurses_drop_planes(struct notcurses* ***nc***);**
**int ncplane_mergedown(struct ncplane* ***src***, struct ncplane* ***dst***, int ***begsrcy***, int ***begsrcx***, int ***leny***, int ***lenx***, int ***dsty***, int ***dstx***);**
**int ncplane_mergedown(struct ncplane* ***src***, struct ncplane* ***dst***, unsigned ***begsrcy***, unsigned ***begsrcx***, unsigned ***leny***, unsigned ***lenx***, unsigned ***dsty***, unsigned ***dstx***);**
**int ncplane_mergedown_simple(struct ncplane* restrict ***src***, struct ncplane* restrict ***dst***);**

@ -452,17 +452,17 @@ namespace ncpp
return move_above (*above);
}
bool mergedown (Plane &dst, int begsrcy, int begsrcx, int leny, int lenx, int dsty, int dstx) const
bool mergedown (Plane &dst, unsigned begsrcy, unsigned begsrcx, unsigned leny, unsigned lenx, unsigned dsty, unsigned dstx) const
{
return mergedown (&dst, begsrcy, begsrcx, leny, lenx, dsty, dstx);
}
bool mergedown (Plane *dst, int begsrcy, int begsrcx, int leny, int lenx, int dsty, int dstx) const
bool mergedown (Plane *dst, unsigned begsrcy, unsigned begsrcx, unsigned leny, unsigned lenx, unsigned dsty, unsigned dstx) const
{
if (dst != nullptr && plane == dst->plane)
if (plane == dst->plane)
throw invalid_argument ("'dst' must refer to a different plane than the one this method is called on");
return error_guard (ncplane_mergedown (plane, dst != nullptr ? dst->plane : nullptr, begsrcy, begsrcx, leny, lenx, dsty, dstx), -1);
return error_guard (ncplane_mergedown (plane, dst->plane, begsrcy, begsrcx, leny, lenx, dsty, dstx), -1);
}
bool mergedown_simple (Plane &dst) const
@ -472,7 +472,7 @@ namespace ncpp
bool mergedown_simple (Plane *dst) const
{
if (dst == nullptr || plane == dst->plane)
if (plane == dst->plane)
throw invalid_argument ("'dst' must refer to a different plane than the one this method is called on");
return error_guard (ncplane_mergedown_simple (plane, dst->plane), -1);

@ -2302,28 +2302,32 @@ API int ncplane_stain(struct ncplane* n, int ystop, int xstop, uint64_t ul,
// Merge the entirety of 'src' down onto the ncplane 'dst'. If 'src' does not
// intersect with 'dst', 'dst' will not be changed, but it is not an error.
API int ncplane_mergedown_simple(struct ncplane* RESTRICT src,
struct ncplane* RESTRICT dst);
struct ncplane* RESTRICT dst)
__attribute__ ((nonnull (1, 2)));
// Merge the ncplane 'src' down onto the ncplane 'dst'. This is most rigorously
// defined as "write to 'dst' the frame that would be rendered were the entire
// stack made up only of the specified subregion of 'src' and, below it, the
// subregion of 'dst' having the specified origin. Merging is independent of
// the position of 'src' viz 'dst' on the z-axis. It is an error to define a
// subregion of zero area, or that is not entirely contained within 'src'. It
// is an error to define a target origin such that the projected subregion is
// not entirely contained within 'dst'. Behavior is undefined if 'src' and
// 'dst' are equivalent. 'dst' is modified, but 'src' remains unchanged.
// neither 'src' nor 'dst' may have sprixels.
// subregion that is not entirely contained within 'src'. It is an error to
// define a target origin such that the projected subregion is not entirely
// contained within 'dst'. Behavior is undefined if 'src' and 'dst' are
// equivalent. 'dst' is modified, but 'src' remains unchanged. Neither 'src'
// nor 'dst' may have sprixels. Lengths of 0 mean "everything left".
API int ncplane_mergedown(struct ncplane* RESTRICT src,
struct ncplane* RESTRICT dst,
int begsrcy, int begsrcx, int leny, int lenx,
int dsty, int dstx);
unsigned begsrcy, unsigned begsrcx,
unsigned leny, unsigned lenx,
unsigned dsty, unsigned dstx)
__attribute__ ((nonnull (1, 2)));
// Erase every cell in the ncplane (each cell is initialized to the null glyph
// and the default channels/styles). All cells associated with this ncplane are
// invalidated, and must not be used after the call, *excluding* the base cell.
// The cursor is homed. The plane's active attributes are unaffected.
API void ncplane_erase(struct ncplane* n);
API void ncplane_erase(struct ncplane* n)
__attribute__ ((nonnull (1)));
// Erase every cell in the region starting at {ystart, xstart} and having size
// {|ylen|x|xlen|} for non-zero lengths. If ystart and/or xstart are -1, the current

@ -526,31 +526,44 @@ postpaint(const tinfo* ti, nccell* lastframe, int dimy, int dimx,
// merging one plane down onto another is basically just performing a render
// using only these two planes, with the result written to the lower plane.
int ncplane_mergedown(ncplane* restrict src, ncplane* restrict dst,
int begsrcy, int begsrcx, int leny, int lenx,
int dsty, int dstx){
unsigned begsrcy, unsigned begsrcx,
unsigned leny, unsigned lenx,
unsigned dsty, unsigned dstx){
//fprintf(stderr, "Merging down %d/%d @ %d/%d to %d/%d\n", leny, lenx, begsrcy, begsrcx, dsty, dstx);
if(dsty >= dst->leny || dstx >= dst->lenx){
logerror("Dest origin %d/%d ≥ dest dimensions %d/%d\n",
if(dsty >= (unsigned)dst->leny || dstx >= (unsigned)dst->lenx){
logerror("dest origin %u/%u ≥ dest dimensions %d/%d\n",
dsty, dstx, dst->leny, dst->lenx);
return -1;
}
if(dst->leny - leny < dsty || dst->lenx - lenx < dstx){
logerror("Dest len %d/%d ≥ dest dimensions %d/%d\n",
logerror("dest len %u/%u ≥ dest dimensions %d/%d\n",
leny, lenx, dst->leny, dst->lenx);
return -1;
}
if(begsrcy >= src->leny || begsrcx >= src->lenx){
logerror("Source origin %d/%d ≥ source dimensions %d/%d\n",
if(begsrcy >= (unsigned)src->leny || begsrcx >= (unsigned)src->lenx){
logerror("source origin %u/%u ≥ source dimensions %d/%d\n",
begsrcy, begsrcx, src->leny, src->lenx);
return -1;
}
if(leny == 0){
if((leny = src->leny - begsrcy) == 0){
logerror("source area was zero height\n");
return -1;
}
}
if(lenx == 0){
if((lenx = src->lenx - begsrcx) == 0){
logerror("source area was zero width\n");
return -1;
}
}
if(src->leny - leny < begsrcy || src->lenx - lenx < begsrcx){
logerror("Source len %d/%d ≥ source dimensions %d/%d\n",
logerror("source len %u/%u ≥ source dimensions %d/%d\n",
leny, lenx, src->leny, src->lenx);
return -1;
}
if(src->sprite || dst->sprite){
logerror("Can't merge sprixel planes\n");
logerror("can't merge sprixel planes\n");
return -1;
}
const int totalcells = dst->leny * dst->lenx;
@ -558,7 +571,7 @@ int ncplane_mergedown(ncplane* restrict src, ncplane* restrict dst,
const size_t crenderlen = sizeof(struct crender) * totalcells;
struct crender* rvec = malloc(crenderlen);
if(!rendfb || !rvec){
logerror("Error allocating render state for %dx%d\n", leny, lenx);
logerror("error allocating render state for %ux%u\n", leny, lenx);
free(rendfb);
free(rvec);
return -1;
@ -580,14 +593,7 @@ int ncplane_mergedown(ncplane* restrict src, ncplane* restrict dst,
}
int ncplane_mergedown_simple(ncplane* restrict src, ncplane* restrict dst){
// have to check dst, since we used to accept a NULL dst to mean the
// standard plane (this was unsafe, since src might be in another pile).
if(dst == NULL){
return -1;
}
int dimy, dimx;
ncplane_dim_yx(dst, &dimy, &dimx);
return ncplane_mergedown(src, dst, 0, 0, ncplane_dim_y(src), ncplane_dim_x(src), 0, 0);
return ncplane_mergedown(src, dst, 0, 0, 0, 0, 0, 0);
}
// write the nccell's UTF-8 extended grapheme cluster to the provided FILE*.

@ -18,7 +18,7 @@ void DrawBoard() { // draw all fixed components of the game
stdplane_->get_dim(&y, &x);
board_top_y_ = y - (BOARD_HEIGHT + 2);
board_ = std::make_unique<ncpp::Plane>(BOARD_HEIGHT, BOARD_WIDTH * 2,
board_top_y_, x / 2 - (BOARD_WIDTH + 1));
board_top_y_, x / 2 - (BOARD_WIDTH + 1));
uint64_t channels = 0;
ncchannels_set_fg_rgb(&channels, 0x00b040);
ncchannels_set_bg_alpha(&channels, NCALPHA_TRANSPARENT);

Loading…
Cancel
Save