X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Ftessellimage.c;h=4fcf7b176c77a39e50c0d49333b336cbb87f6aba;hp=ec05fb98dbe27fe614ba8a592b785913f2d3afe8;hb=78add6e627ee5f10e1fa6f3852602ea5066eee5a;hpb=39809ded547bdbb08207d3e514950425215b4410 diff --git a/hacks/tessellimage.c b/hacks/tessellimage.c index ec05fb98..4fcf7b17 100644 --- a/hacks/tessellimage.c +++ b/hacks/tessellimage.c @@ -1,4 +1,4 @@ -/* tessellimage, Copyright (c) 2014 Jamie Zawinski +/* tessellimage, Copyright (c) 2014-2018 Jamie Zawinski * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -31,7 +31,7 @@ struct state { int delay; Bool outline_p, cache_p, fill_p; double duration, duration2; - int max_depth; + int max_depth, max_resolution; double start_time, start_time2; XImage *img, *delta; @@ -83,6 +83,10 @@ tessellimage_init (Display *dpy, Window window) st->max_depth = get_integer_resource (st->dpy, "maxDepth", "MaxDepth"); if (st->max_depth < 100) st->max_depth = 100; + st->max_resolution = get_integer_resource (st->dpy, + "maxResolution", "MaxResolution"); + if (st->max_resolution < 0) st->max_resolution = 0; + st->duration = get_float_resource (st->dpy, "duration", "Seconds"); if (st->duration < 1) st->duration = 1; @@ -577,7 +581,7 @@ tessellate (struct state *st) XCopyArea (st->dpy, st->cache[st->thresh], st->output, st->pgc, - 0, 0, st->delta->width, st->delta->height, + 0, 0, st->xgwa.width, st->xgwa.height, 0, 0); } else if (ticked_p) @@ -589,6 +593,7 @@ tessellate (struct state *st) int nv = 0; int ntri = 0; int x, y, i; + double wscale = st->xgwa.width / (double) st->delta->width; #if 0 fprintf(stderr, "%s: thresh %d/%d = %d=%d\n", @@ -657,10 +662,10 @@ tessellate (struct state *st) if (st->output) XFreePixmap (st->dpy, st->output); st->output = XCreatePixmap (st->dpy, st->window, - st->delta->width, st->delta->height, + st->xgwa.width, st->xgwa.height, st->xgwa.depth); XFillRectangle (st->dpy, st->output, st->pgc, - 0, 0, st->delta->width, st->delta->height); + 0, 0, st->xgwa.width, st->xgwa.height); #ifdef DO_VORONOI @@ -706,14 +711,14 @@ tessellate (struct state *st) { XPoint xp[3]; unsigned long color; - xp[0].x = p[v[i].p1].x; xp[0].y = p[v[i].p1].y; - xp[1].x = p[v[i].p2].x; xp[1].y = p[v[i].p2].y; - xp[2].x = p[v[i].p3].x; xp[2].y = p[v[i].p3].y; + xp[0].x = p[v[i].p1].x * wscale; xp[0].y = p[v[i].p1].y * wscale; + xp[1].x = p[v[i].p2].x * wscale; xp[1].y = p[v[i].p2].y * wscale; + xp[2].x = p[v[i].p3].x * wscale; xp[2].y = p[v[i].p3].y * wscale; /* Set the color of this triangle to the pixel at its midpoint. */ color = XGetPixel (st->img, - (xp[0].x + xp[1].x + xp[2].x) / 3, - (xp[0].y + xp[1].y + xp[2].y) / 3); + (xp[0].x + xp[1].x + xp[2].x) / (3 * wscale), + (xp[0].y + xp[1].y + xp[2].y) / (3 * wscale)); XSetForeground (st->dpy, st->pgc, color); XFillPolygon (st->dpy, st->output, st->pgc, xp, countof(xp), @@ -747,7 +752,7 @@ tessellate (struct state *st) { st->cache[st->thresh] = XCreatePixmap (st->dpy, st->window, - st->delta->width, st->delta->height, + st->xgwa.width, st->xgwa.height, st->xgwa.depth); if (! st->cache[st->thresh]) { @@ -759,7 +764,7 @@ tessellate (struct state *st) st->output, st->cache[st->thresh], st->pgc, - 0, 0, st->delta->width, st->delta->height, + 0, 0, st->xgwa.width, st->xgwa.height, 0, 0); } } @@ -774,8 +779,9 @@ static Pixmap get_deltap (struct state *st) { int x, y; - int w = st->delta->width; - int h = st->delta->height; + int w = st->xgwa.width; + int h = st->xgwa.height; + double wscale = st->xgwa.width / (double) st->delta->width; XImage *dimg; Visual *v = st->xgwa.visual; @@ -799,7 +805,7 @@ get_deltap (struct state *st) for (y = 0; y < h; y++) for (x = 0; x < w; x++) { - unsigned long v = XGetPixel (st->delta, x, y) << 5; + unsigned long v = XGetPixel (st->delta, x / wscale, y / wscale) << 5; unsigned long p = (((v << rpos) & rmsk) | ((v << gpos) & gmsk) | ((v << bpos) & bmsk)); @@ -832,11 +838,23 @@ tessellimage_draw (Display *dpy, Window window, void *closure) if (!st->img_loader && st->start_time + st->duration < double_time()) { + int w = st->xgwa.width; + int h = st->xgwa.height; + + /* Analysing a full-resolution image on a Retina display is too slow, + so scale down the source at image-load time. */ + if (st->max_resolution > 10) + { + if (w > h && w > st->max_resolution) + h = st->max_resolution * h / w, w = st->max_resolution; + else if (h > st->max_resolution) + w = st->max_resolution * w / h, h = st->max_resolution; + } + /* fprintf(stderr,"%s: loading %d x %d\n", progname, w, h); */ + XClearWindow (st->dpy, st->window); if (st->image) XFreePixmap (dpy, st->image); - st->image = XCreatePixmap (st->dpy, st->window, - st->xgwa.width, st->xgwa.height, - st->xgwa.depth); + st->image = XCreatePixmap (st->dpy, st->window, w, h, st->xgwa.depth); st->img_loader = load_image_async_simple (0, st->xgwa.screen, st->window, st->image, 0, &st->geom); goto DONE; @@ -851,16 +869,12 @@ tessellimage_draw (Display *dpy, Window window, void *closure) XCopyArea (st->dpy, (st->button_down_p ? get_deltap (st) : st->output), st->window, st->wgc, - 0, 0, st->delta->width, st->delta->height, - (st->xgwa.width - st->delta->width) / 2, - (st->xgwa.height - st->delta->height) / 2); + 0, 0, st->xgwa.width, st->xgwa.height, 0, 0); else if (!st->nthreshes) XCopyArea (st->dpy, st->image, st->window, st->wgc, - 0, 0, st->xgwa.width, st->xgwa.height, - 0, - 0); + 0, 0, st->xgwa.width, st->xgwa.height, 0, 0); DONE: @@ -918,12 +932,14 @@ tessellimage_free (Display *dpy, Window window, void *closure) static const char *tessellimage_defaults [] = { ".background: black", ".foreground: white", + ".lowrez: True", "*dontClearRoot: True", "*fpsSolid: true", "*delay: 30000", "*duration: 120", "*duration2: 0.4", "*maxDepth: 30000", + "*maxResolution: 1024", "*outline: True", "*fillScreen: True", "*cache: True", @@ -939,6 +955,7 @@ static XrmOptionDescRec tessellimage_options [] = { { "-duration", ".duration", XrmoptionSepArg, 0 }, { "-duration2", ".duration2", XrmoptionSepArg, 0 }, { "-max-depth", ".maxDepth", XrmoptionSepArg, 0 }, + { "-max-resolution", ".maxResolution", XrmoptionSepArg, 0 }, { "-outline", ".outline", XrmoptionNoArg, "True" }, { "-no-outline", ".outline", XrmoptionNoArg, "False" }, { "-fill-screen", ".fillScreen", XrmoptionNoArg, "True" },