diff --git a/doc/man/man1/notcurses-demo.1.md b/doc/man/man1/notcurses-demo.1.md index dc5b291de..5748b6842 100644 --- a/doc/man/man1/notcurses-demo.1.md +++ b/doc/man/man1/notcurses-demo.1.md @@ -25,6 +25,7 @@ The demonstrations include (see NOTES below): * (a)llglyph—scroll the glyphs of your font * (b)oxes—pulsating boxes with a transparent center * (c)hunli—the strongest woman in the world +* (d)ragon—the Harter-Heighway dragon curve * (e)agle—they took some time off my life, back in the day * (f)allin'—the screen falls apart under heavy blows * (g)rid—a gradient of color lain atop a great grid @@ -71,7 +72,7 @@ At any time, press 'q' to quit. The demo is best run in at least an 80x45 termin **-V**: Print the program name and version, and exit with success. demospec: Select which demos to run, and what order to run them in. The -default is **ixeaythnbcgrwuvlsfjqo**. See above for a list of demos. +default is **ixeaydthnbcgrwuvlsfjqo**. See above for a list of demos. Default margins are all 0, and thus the full screen will be rendered. Using **-m**, margins can be supplied. Provide a single number to set all four margins diff --git a/src/demo/demo.c b/src/demo/demo.c index 69f4da737..0ed63d725 100644 --- a/src/demo/demo.c +++ b/src/demo/demo.c @@ -19,7 +19,7 @@ static int democount; static demoresult* results; static char *datadir = NOTCURSES_SHARE; -static const char DEFAULT_DEMO[] = "ixeaythnbcgrwuvlsfjqo"; +static const char DEFAULT_DEMO[] = "ixeaydthnbcgrwuvlsfjqo"; atomic_bool interrupted = ATOMIC_VAR_INIT(false); // checked following demos, whether aborted, failed, or otherwise @@ -75,20 +75,20 @@ static struct { } demos[26] = { { "allglyph", allglyphs_demo, false, }, { "box", box_demo, false, }, - {"chunli", chunli_demo, true, }, - { NULL, NULL, false, }, + { "chunli", chunli_demo, true, }, + { "dragon", dragon_demo, false, }, { "eagle", eagle_demo, true, }, { "fallin'", fallin_demo, false, }, { "grid", grid_demo, false, }, { "highcon", highcontrast_demo, false, }, { "intro", intro, false, }, { "jungle", jungle_demo, true, }, - { NULL, NULL, false, }, + { NULL, NULL, false, }, // FIXME { "luigi", luigi_demo, true, }, - { NULL, NULL, false, }, + { NULL, NULL, false, }, // mojibake { "normal", normal_demo, false, }, { "outro", outro, false, }, - { NULL, NULL, false, }, + { NULL, NULL, false, }, // pango { "qrcode", qrcode_demo, false, }, // is blank without USE_QRCODEGEN { "reel", reel_demo, false, }, { "sliders", sliding_puzzle_demo, false, }, @@ -98,7 +98,7 @@ static struct { { "whiteout", witherworm_demo, false, }, { "xray", xray_demo, false, }, { "yield", yield_demo, false, }, - { NULL, NULL, false, }, + { NULL, NULL, false, }, // zoo }; static void @@ -360,8 +360,10 @@ summary_table(struct ncdirect* nc, const char* spec){ qprefix(results[i].stats.render_ns, GIG, rtimebuf, 0); bprefix(results[i].stats.render_bytes, 1, totalbuf, 0); uint32_t rescolor; - if(results[i].result != 0){ + if(results[i].result < 0){ rescolor = 0xff303c; + }else if(results[i].result > 0){ + rescolor = 0xffaa22; }else if(!results[i].stats.renders){ rescolor = 0xbbbbbb; }else{ diff --git a/src/demo/demo.h b/src/demo/demo.h index 7850fe4b0..679d24db4 100644 --- a/src/demo/demo.h +++ b/src/demo/demo.h @@ -38,6 +38,7 @@ int witherworm_demo(struct notcurses* nc); int box_demo(struct notcurses* nc); int trans_demo(struct notcurses* nc); int chunli_demo(struct notcurses* nc); +int dragon_demo(struct notcurses* nc); int qrcode_demo(struct notcurses* nc); int grid_demo(struct notcurses* nc); int fallin_demo(struct notcurses* nc); diff --git a/src/demo/dragon.c b/src/demo/dragon.c new file mode 100644 index 000000000..92a85455e --- /dev/null +++ b/src/demo/dragon.c @@ -0,0 +1,108 @@ +#include "demo.h" + +// lame as fuck lol +static bool done; +static uint32_t pixel; +static int y, x, dy, dx; + +static int +dragonmayer(struct ncvisual* ncv, const char* str, int iters){ + char c; + int r; + while( (c = *str++) ){ + switch(c){ + case 'X': + if(iters > 1){ + if( (r = dragonmayer(ncv, "X+YF+", iters - 1)) ){ + return r; + } + } + break; + case 'Y': + if(iters > 1){ + if( (r = dragonmayer(ncv, "-FX-Y", iters - 1)) ){ + return r; + } + } + break; + case '+': { int tmp = dy; dy = -dx; dx = tmp; break; } + case '-': { int tmp = -dy; dy = dx; dx = tmp; break; } + case 'F': // FIXME want a line + // FIXME some of these will fail...hella lame, check against dims + if(ncvisual_set_yx(ncv, y, x, pixel) < 0){ + done = true; + } + x += dx; + y += dy; + break; + default: + return -1; + } + } + return 0; +} + +int dragon_demo(struct notcurses* nc){ + int dimy, dimx; + struct ncplane* n = notcurses_stddim_yx(nc, &dimy, &dimx); + // we use a Lindenmayer string rewriting system. the classic dragon curve + // system is X -> X+YF+, Y -> -FX-Y, where F is forward, - is turn left, and + // + is turn right. + const char LINDENSTART[] = "FX"; + const int SCALE = 1; + dimy *= 2; + dimx *= 2; + int dxstart, dystart; + if(dimy > dimx){ + dystart = 0; + dxstart = SCALE; + }else{ + dystart = SCALE; + dxstart = 0; + } + size_t fbbytes = sizeof(uint32_t) * dimy * dimx; + uint32_t* rgba = malloc(fbbytes); + if(rgba == NULL){ + return -1; + } + memset(rgba, 0, fbbytes); + for(int i = 0 ; i < dimy * dimx ; ++i){ + ncpixel_set_a(&rgba[i], 0xff); + } + struct ncvisual* ncv = ncvisual_from_rgba(rgba, dimy, dimx * sizeof(uint32_t), dimx); + if(ncv == NULL){ + free(rgba); + return -1; + } + free(rgba); + struct timespec scaled; + timespec_div(&demodelay, 4, &scaled); + int iters = 0; + do{ + ++iters; + pixel = 0xffffffffull; + ncpixel_set_rgb(&pixel, 0, 0x11 * iters, 0); + dx = dxstart; + dy = dystart; + x = dimx / 2; + y = dimy / 2; + int r = dragonmayer(ncv, LINDENSTART, iters); + if(r){ + ncvisual_destroy(ncv); + return r; + } + struct ncvisual_options vopts = { + .n = n, + .blitter = NCBLIT_2x2, + }; + if(ncvisual_render(nc, ncv, &vopts) == NULL){ + ncvisual_destroy(ncv); + return -1; + } + DEMO_RENDER(nc); + demo_nanosleep(nc, &scaled); + ncplane_erase(n); + }while(!done); + ncvisual_destroy(ncv); + return 0; +} diff --git a/src/lib/plot.h b/src/lib/plot.h index dfacbee76..977b427a6 100644 --- a/src/lib/plot.h +++ b/src/lib/plot.h @@ -82,6 +82,7 @@ class ncppplot { ncpp->maxy = maxy; ncpp->vertical_indep = opts->flags & NCPLOT_OPTION_VERTICALI; ncpp->exponentiali = opts->flags & NCPLOT_OPTION_EXPONENTIALD; + ncpp->detectonlymax = opts->flags & NCPLOT_OPTION_DETECTMAXONLY; if( (ncpp->detectdomain = (miny == maxy)) ){ ncpp->maxy = 0; ncpp->miny = std::numeric_limits::max();