This represents an essentially complete rewrite of ncvisual and associated code. It had two major goals:
Improve the ncvisual API based off lessons learned, pursuant to the upcoming API freeze. In particular, I wanted to:
decouple ncvisuals from ncplanes. It should be possible to render a ncvisual to multiple planes, with different scaling each time. It should be possible to create an ncvisual without a plane, etc.
normalize the various ways of constructing an ncvisual -- file, memory, plane, etc.
Support multiple blitters, from 7-bit ASCII to Sixel. This required writing the blitters in several cases, and they're not yet in their final implementations (but the API is fine)
I have not yet unified Plots and Visuals, and might not, given that the Plot code works fine. We could at this point implement Plots in terms of Visuals, though -- the blitter backend range has been unified. Sixel is not yet implemented, though it is listed.
There is a new POC tool, blitter. It renders its arguments using all possible blitter+scaling combinations. Another new POC, resize, displays its argument, then resizes it to the screen size and displays that, explicitly making use of ncvisual_resize() rather than a scaling parameter to ncvisual_render().
This also eliminates some memory leaks and bugs we were seeing in trunk, and brings in Sixel scaffolding.
The C++ wrapper will also need patching back up; I cut most of it down while wrestling with this crap, urk.
Closes#638, #562, and #622.
* ncplane_at_* and ncplane_at_cursor_*
We had notcurses_at_yx() expanding into three distinct parts of
the cell structure, and ncplane_at_yx() / ncplane_at_cursor()
writing directly to a cell. It was annoying to remember which
was which. The latter two now have a signature matching
notcurses_at_yx(), while the old functionality has been moved
to ncplane_at_yx_cell() and ncplane_at_cursor_yx(). #476
* packaging: s/libtinfo/Terminfo/g
* rust: add stddim_yx()
* rust: check for valid init in unit tests
* rust: serialize up tests
* constify notcurses_term_dim_yx()
* rust: add dim wrappers
* remove notcurses_resize() from public API #367
* call notcurses_resize() from notcurses_refresh() #367
Fill-type functions used to return 0 for success, and -1
on failure. They now return the number of cells written
on success, similarly to ncvisual_render(). Resolves#427.
Resolves#410. notcurses_at_yx() accepted a cell*, but the
gcluster of this cell was always set to 0. The EGC is instead
a heap-allocated copy, returned as the primary return value.
This is due to the absence of an egcpool to bind against.
Existing callers can be converted thus:
* instead of passing cell 'c', pass &(c)->attrword, &(c)->channels
* either initialize 'c' with CELL_TRIVIAL_INITIALIZER, or set its
gcluster field to 0 following the call
I've updated all calls from tests/demos, updated the docs, and
updated the C++ and Python wrappers.
Add ncplane_bound(3). This allows a new plane N to be created in the
*bound* state relative to another ncplane B. If B moves, N moves the
same amount. If N is moved, the coordinates are taken relative to B
as opposed to the standard plane. If B is destroyed, N is destroyed.
Each plane can have many planes bound to it, but can only be bound to
a single plane. Add ncplane_reparent(3). This allows a plane to be
detached from any plane to which it is bound, and optionally rebound
to a new plane. The standard plane cannot be reparented.
Documentation and unit tests have been added for both.
* tetris: use NES gravities
* tetris: use NES grav multiplier of 50ms
* tetris: implement move down #421
* README: mention notcurses-tetris #421
* tetris: use double box for boundary #421
* tetris: extract background.h
* tetris: break up into chunks suitable for book
* tetris: do the rotations
ncplane_mergedown() is similar to the "Merge down" operation
in the GIMP. It writes to the destination plane the result
of rendering the source and destination frames per se.
Add four new fields to notcurses_options: margin_{tblr}, which requests margins to the top, right, bottom, and left. Render only within those margins, leaving the screen otherwise untouched (well, cleared if using the alternate screen). #293
* CMake: add USE_PANDOC, USE_DOXYGEN options #101
* README: mention rust
* start integrating rust into build #101
* CMake: add USE_NETWORK option for cargo
* Debian: build-dep on doxygen
* rust: colloquy checks in Cargo.lock
* extract NCKEY defines into their own include
* colloquy: use clap to parse CLI args
* CMake: unify option namespace
* Python: update include path
* Rust: fix up --frozen workings for -DUSE_NETWORK=off
* CMake: abstract out colloquy a little
* Sync direct.hh to the New Way
Get rid of annoying empty line in notcurses-view (and ncvisuals at offsets in general)
Implement most of the Selector widget. Need to add styling and scrolling still. #166
Reenable ubuntu focal build
Subtitles! We decode them, and display them in notcurses-view. If ncvisual_simple_streamer() is provided an extra ncplane, it will use it to display subtitles. #95
We now build Python by default, as things are working much better.
ncplane_set_base() now takes channel, attrword, and EGC, so you can usually avoid having to set up and release a cell. ncplane_set_base_cell() takes over duty from ncplane_set_base() for ease of conversion.
notcurses-demo and notcurses-view now both accept a 0 for delay multiplier, meaning 'go as fast as you possibly can'. Very small multipliers (e.g. 0.00001) no longer cause floating point exceptions.
fading routines no longer cause floating point exceptions on very small timescales.
Introduce the new type 'ncdirect', a stripped-down 'notcurses'
suitable for inline modification of regular output. Used the new
type because otherwise there were going to be if(directmode) checks
everywhere. Direct mode encompasses only colorizing and styling.
Add new man page notcurses_directmode(3). Add new section to README.
Add new PoC using direct mode RGB. Update demo table summary to use
direct mode.
As it turns out, we can't portably load the initial terminal contents
(there are some hacks of various EXTREME nature, but none of them are
worth it for the rather limited benefit). The O(1)-time damage
inference requires knowledge of what was previously present to
inibit unnecessary draws. We would then need some special cell value
indicating "not yet written to" to distinguish a purposeful null
cell from an initial cell. Again, we could do this, but for what value?
Finally, the idea of clearing new area on SIGWINCH was always flawed,
as we can't do that from a signal handler.
With the advent of direct mode #77, the reason for this largely goes
away in any case.
* palette_set: update pal256 damage map #230
* drone: use newest builders
* palette: send oc on exit for color reset #285
* palette_new: copy existing palette in #230
* Python: use checkRGB everywhere
* more palette unit testing
* add ncplane_set_*_palindex()
* render fg palindex #230
* palette index color is out of 1000
* jungle demo works #253
* sync up some docs #244
* sync README and man page
* notcurses_output() man page work
* pull attr/channels from output functions #244
* witherworm: clean up explicit moves #244
* still more man page work
* notcurses_lines, last of the man pages i think
* panelreel man page #244
* debian: ruby-ronn->pandoc
* debian: full multiarch compliance
* debian: symbols file
* pandoc: fix syntax for lexgrog
* fm6.mkv: strip audio
* pandoc: fix up apropos man syntax #249
* ncurses_lines man page
* introduce doctest over googletest #202
* call dtester in in targets
* doctest conversion #202
* channel.cpp -> doctest #202
* egcpool tests -> doctest #202
* input tests to doctester
* zaxis -> doctest
* drone: always define LANG
* libav to doctest #202
* panelreel tests to doctest #202
* spec that a C++17 compiler is now required for doctest #202
* enmetric tests -> doctest #202
* fade tests -> doctest #202
* notcurses test case -> doctest #202
* last conversion to doctest #202
* finish move to doctest #202
* drone: set up make test
Request and parse up mouse messages. We handle up to 11 mouse
buttons, 3 modifiers (currently thrown away), motion while
holding down a button, and loss/gain of focus. I've added twelve
new NCKEYs: one for each button, and one for release. In addition,
I've introduced the 'ncinput' struct, which encodes the nckey plus
extra data. The only extra data thus far is coordinates for mouse
events. It is not necessary to provide a ncinput to all input
functions; NULL can be provided if the caller doesn't care about
details. All demos are updated. notcurses-input has been updated
to decode full information of returned ncinputs.
The primary resource for this work was Dickey at al's "XTerm Control
Sequences", https://invisible-island.net/xterm/ctlseqs/ctlseqs.html.
* planereels tester #180
* suppress_banner in all tests
* tabletcb: start passing back tablet
* properly initialize fbbytes stat
* panelreel: logic fixes#178
* install all testing data
While ncurses 6.1 adds the `RGB` capability to terminfo, the flag is not
commonly used in terminfo entries as of now. The `COLORTERM` environment
variable is, otoh, commonly present and set to either `truecolor` or
`24bit` value by terminal emulators which support direct color.
Add a check for this if `RGB` is false (or absent)
With this check in I was able to properly appreciate the awesomeness of
notcurses demos :)
* boxdemo: clean up colors
* Fix crash on certain resizes due to corruption of damage map #152
* Rewrite ncplane_move_yx(), throwing out ~25 line of code
* implement notcurses_refresh() #150
Implement a fairly conservative, line-granularity, two-level damage map. One on the overall notcurses object is dirtied by planar moves, creations, deletions, and resizes. One on each ncplane is dirtied by glyph output, media rendering, fades, and erasure. #83 This has some definite false positives: a hidden plane which moves will damage a bunch of lines unnecessarily. For now, don't do things like that :D.
Extra byte per line per plane, shouldn't be a problem.
Two new stats for cell elisions and emissions
Allow keypress to interrupt view-demo
ncvisual_stream() now allows a callback per frame
Allow ncvisual_open() to create its own, perfectly-sized, ncplane #128
Typical performance prior to this PR:
4655 renders, 18.3s total (0.000305s min, 0.196s max, 0.0039s avg 253.9 fps)
401046.505KB total (9.688KB min, 139.697KB max, 86.15KB avg)
Emits/elides: def 1082115/116196 fg 10547624/7236460 bg 10602717/6208644
Elide rates: 9.70% 40.69% 36.93%
4680 renders, 18.4s total (0.000285s min, 0.15s max, 0.0039s avg 255.0 fps)
403078.188KB total (9.688KB min, 139.697KB max, 86.13KB avg)
Emits/elides: def 1088994/116196 fg 10604983/7267750 bg 10655426/6237472
Elide rates: 9.64% 40.66% 36.92%
4699 renders, 17.8s total (0.000227s min, 0.192s max, 0.0038s avg 263.8 fps)
403266.907KB total (9.688KB min, 139.697KB max, 85.82KB avg)
Emits/elides: def 1086511/116196 fg 10601709/7359116 bg 10661910/6326744
Elide rates: 9.66% 40.97% 37.24%
After this PR:
5625 renders, 15s total (9.36e-05s min, 0.187s max, 0.0027s avg 375.2 fps)
168365.640KB total (0.930KB min, 139.600KB max, 29.93KB avg)
Emits/elides: def 310575/116196 fg 4486002/4473416 bg 4116835/4630666
Elide rates: 27.23% 49.93% 52.94%
Cells emitted; 9928000 elided: 12572000 (55.88%)
5642 renders, 14.2s total (9.17e-05s min, 0.154s max, 0.0025s avg 397.0 fps)
168669.009KB total (0.605KB min, 139.600KB max, 29.90KB avg)
Emits/elides: def 310819/116196 fg 4499833/4482134 bg 4118562/4652470
Elide rates: 27.21% 49.90% 53.04%
Cells emitted; 9962160 elided: 12605840 (55.86%)
5650 renders, 14.3s total (0.000118s min, 0.143s max, 0.0025s avg 395.7 fps)
169461.884KB total (0.860KB min, 139.600KB max, 29.99KB avg)
Emits/elides: def 305431/116196 fg 4515396/4456376 bg 4149967/4613668
Elide rates: 27.56% 49.67% 52.65%
Cells emitted; 9945200 elided: 12654800 (55.99%)
on netcurses-demo, we're eliding about half of the total cells via this damage map. that's pretty fucking sweet! FPS increase of about 50% -- I'll take that any day of the fuckin' week, boyo. w00t!
https://www.youtube.com/watch?v=XbGs_qK2PQA
* improved alpha macros
* demo: use new alpha macros
* add ncplane_set_*_alpha()
* explicitly set fg for uniblock
* outro: background is a space #139
* distinct alpha channels for fg/bg #139
* rename 'background' cell to 'default' #142
* doc palette fades
* uniblock-demo: reset background to black
* warning about quantization
* some luigi love
* update cell documentation
* add unit test for move of stdplane
* MoveToLowerRight unit test
* ncplane_move_yx(): error to move stdscr
* better box permutations test
* luigi in megaman2 world
* stats: don't print 'em if we haven't got 'em