Skip to content

Commit

Permalink
python: PoC up through dimensions/output
Browse files Browse the repository at this point in the history
  • Loading branch information
dankamongmen committed Jan 9, 2020
1 parent 16cd377 commit 32cdc58
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 3 deletions.
59 changes: 59 additions & 0 deletions python/src/notcurses/build_notcurses.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,30 @@
)

ffibuild.cdef("""
typedef struct cell {
// These 32 bits are either a single-byte, single-character grapheme cluster
// (values 0--0x7f), or an offset into a per-ncplane attached pool of
// varying-length UTF-8 grapheme clusters. This pool may thus be up to 32MB.
uint32_t gcluster; // 1 * 4b -> 4b
// CELL_STYLE_* attributes (16 bits) + 16 reserved bits
uint32_t attrword; // + 4b -> 8b
// (channels & 0x8000000000000000ull): left half of wide character
// (channels & 0x4000000000000000ull): foreground is *not* "default color"
// (channels & 0x3000000000000000ull): foreground alpha (2 bits)
// (channels & 0x0f00000000000000ull): reserved, must be 0
// (channels & 0x00ffffff00000000ull): foreground in 3x8 RGB (rrggbb)
// (channels & 0x0000000080000000ull): right half of wide character
// (channels & 0x0000000040000000ull): background is *not* "default color"
// (channels & 0x0000000030000000ull): background alpha (2 bits)
// (channels & 0x000000000f000000ull): reserved, must be 0
// (channels & 0x0000000000ffffffull): background in 3x8 RGB (rrggbb)
// At render time, these 24-bit values are quantized down to terminal
// capabilities, if necessary. There's a clear path to 10-bit support should
// we one day need it, but keep things cagey for now. "default color" is
// best explained by color(3NCURSES). ours is the same concept. until the
// "not default color" bit is set, any color you load will be ignored.
uint64_t channels; // + 8b == 16b
} cell;
typedef enum {
NCLOGLEVEL_SILENT, // default. print nothing once fullscreen service begins
NCLOGLEVEL_PANIC, // print diagnostics immediately related to crashing
Expand Down Expand Up @@ -55,6 +79,41 @@
int notcurses_stop(struct notcurses*);
int notcurses_render(struct notcurses*);
struct ncplane* notcurses_stdplane(struct notcurses*);
int ncplane_set_base(struct ncplane* ncp, const cell* c);
int ncplane_base(struct ncplane* ncp, cell* c);
void ncplane_erase(struct ncplane* n);
void cell_release(struct ncplane* n, cell* c);
typedef enum {
NCALIGN_LEFT,
NCALIGN_CENTER,
NCALIGN_RIGHT,
} ncalign_e;
int ncplane_cursor_move_yx(struct ncplane* n, int y, int x);
void ncplane_cursor_yx(struct ncplane* n, int* y, int* x);
int ncplane_putc_yx(struct ncplane* n, int y, int x, const cell* c);
int ncplane_putsimple_yx(struct ncplane* n, int y, int x, char c);
typedef struct ncstats {
uint64_t renders; // number of successful notcurses_render() runs
uint64_t failed_renders; // number of aborted renders, should be 0
uint64_t render_bytes; // bytes emitted to ttyfp
int64_t render_max_bytes; // max bytes emitted for a frame
int64_t render_min_bytes; // min bytes emitted for a frame
uint64_t render_ns; // nanoseconds spent in notcurses_render()
int64_t render_max_ns; // max ns spent in notcurses_render()
int64_t render_min_ns; // min ns spent in successful notcurses_render()
uint64_t cellelisions; // cells we elided entirely thanks to damage maps
uint64_t cellemissions; // cells we emitted due to inferred damage
uint64_t fbbytes; // total bytes devoted to all active framebuffers
uint64_t fgelisions; // RGB fg elision count
uint64_t fgemissions; // RGB fg emissions
uint64_t bgelisions; // RGB bg elision count
uint64_t bgemissions; // RGB bg emissions
uint64_t defaultelisions; // default color was emitted
uint64_t defaultemissions; // default color was elided
} ncstats;
void notcurses_stats(struct notcurses* nc, ncstats* stats);
void notcurses_reset_stats(struct notcurses* nc, ncstats* stats);
void ncplane_dim_yx(struct ncplane* n, int* rows, int* cols);
""")

if __name__ == "__main__":
Expand Down
51 changes: 48 additions & 3 deletions python/src/notcurses/notcurses.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,54 @@
import locale
from _notcurses import lib, ffi

class Cell:
def __init__(self, ncplane):
self.c = ffi.new("cell *")
self.c.gcluster = 0x20
self.c.channels = 0
self.c.attrword = 0
self.ncp = ncplane

def __del__(self):
lib.cell_release(self.ncp.getNcplane(), self.c)

def setBgRGB(self, r, g, b):
if r < 0 or r > 255:
raise ValueError("Bad red value")
if g < 0 or g > 255:
raise ValueError("Bad green value")
if b < 0 or b > 255:
raise ValueError("Bad blue value")
self.c.channels = r * 65536 + g * 256 + b # FIXME

def getNccell(self):
return self.c

class Ncplane:
def __init__(self, plane):
self.n = plane

def setBase(self, cell):
return lib.ncplane_set_base(self.n, cell.getNccell())

def getNcplane(self):
return self.n

def putSimpleYX(self, y, x, ch):
return lib.ncplane_putsimple_yx(self.n, y, x, ch)

def getDimensions(self):
y = ffi.new("int *")
x = ffi.new("int *")
lib.ncplane_dim_yx(self.n, y, x)
return (y[0], x[0])

class Notcurses:
def __init__(self):
opts = ffi.new("notcurses_options *")
#opts.inhibit_alternate_screen = True
opts.inhibit_alternate_screen = True
self.nc = lib.notcurses_init(opts, sys.stdout)
self.stdplane = lib.notcurses_stdplane(self.nc)
self.stdncplane = Ncplane(lib.notcurses_stdplane(self.nc))

def __del__(self):
lib.notcurses_stop(self.nc)
Expand All @@ -20,9 +58,16 @@ def render(self):
return lib.notcurses_render(self.nc)

def stdplane(self):
return self.stdplane
return self.stdncplane

if __name__ == '__main__':
locale.setlocale(locale.LC_ALL, "")
nc = Notcurses()
c = Cell(nc.stdplane())
c.setBgRGB(0x80, 0xc0, 0x80)
nc.stdplane().setBase(c)
dims = nc.stdplane().getDimensions()
for y in range(dims[0]):
for x in range(dims[1]):
nc.stdplane().putSimpleYX(y, x, b'X')
nc.render()

0 comments on commit 32cdc58

Please sign in to comment.