From 1030dc837b10a03a02a85d5504cbeec168ce49e2 Mon Sep 17 00:00:00 2001 From: Bernie Innocenti Date: Mon, 03 May 2010 21:53:47 +0000 Subject: Import XaoS r489 (trunk after version 3.5) --- (limited to 'src/ui-hlp/render.c') diff --git a/src/ui-hlp/render.c b/src/ui-hlp/render.c new file mode 100644 index 0000000..f105e92 --- /dev/null +++ b/src/ui-hlp/render.c @@ -0,0 +1,664 @@ + +#ifdef _plan9_ +#include +#include +#ifdef _plan9v2_ +#include /* not needed in plan9v3 */ +#endif +#else +#include +#include +#include +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_GETTEXT +#include +#else +#define gettext(STRING) STRING +#endif + +#define SILENT 0 +#define ERRORS 1 +#define MESSAGES 2 +#define ALL 3 +static int noiselevel; +/*static struct uih_context *uih, *gc;*/ +static struct uih_context *gc; +static struct uih_context *uih; +static int newline = 1; +static int interrupt = 0; +static void error(CONST char *str) +{ + if (noiselevel < ERRORS) + return; + if (!gc) + x_error(gettext("Error: %s"), str); + uih_error(gc, str); +} + +static void uiherror(struct uih_context *c) +{ + if (noiselevel < ERRORS) + return; + if (!gc) { + uih_printmessages(c); + } else + uih_error(gc, uih->errstring); +} + +static void printmsg(const char *text, ...) +{ + va_list ap; + if (noiselevel < MESSAGES) + return; + va_start(ap, text); + if (!gc) { + vprintf(text, ap); + printf("\n"); + } else { + char s[256]; + vsprintf(s, text, ap); + uih_message(gc, s); + interrupt |= gc->interrupt |= gc->passfunc(gc, 1, s, 100); + uih_clearwindows(gc); + } +} + +static int +passfunc(struct uih_context *c, int display, CONST char *text, + float percent) +{ + if (noiselevel < ALL) + return 0; + if (gc) { + if (gc->passfunc != NULL) + interrupt |= gc->interrupt |= + gc->passfunc(gc, display, text, percent); + uih_clearwindows(gc); + return interrupt; + } else if (display) { + { + if (newline) + printf("\n"), newline = 0; + printf("\r %s %3.2f%% ", text, (double) percent); + fflush(stdout); + } + } + return 0; +} + + +struct frame_info { + vrect rect; + number_t angle; + char *name; + int newimage; +}; +static void +save_frame_dist(uih_context * c, int backward, struct frame_info *f1, + struct frame_info *f2) +{ + xio_file f; + int x1, y1; + char str[256]; + if (!(f2->rect.mc - f2->rect.nc) || !(f2->rect.mi - f2->rect.ni)) + return; + /*printf ("Frame\n"); */ + sprintf(str, "%s.%c", f1->name, backward ? 'b' : 'p'); + f = xio_wopen(str); + if (f == NULL) { + x_error(gettext("Cannot open motion vector file!")); + return; + } + for (y1 = 0; y1 < (c->image->height + 7) / 8; y1++) { + for (x1 = 0; x1 < (c->image->width + 7) / 8; x1++) { + number_t x, y; + number_t x2, y2; + number_t tmp; + x = f1->rect.nc + (x1 * 8 + 4) * (f1->rect.mc - + f1->rect.nc) / + c->image->width; + y = f1->rect.ni + (y1 * 8 + 4) * (f1->rect.mi - + f1->rect.ni) / + c->image->height; + + if (f2->angle != f1->angle) { + tmp = + x * cos(f2->angle - f1->angle) - y * sin(f2->angle - + f1->angle); + y = x * sin(f2->angle - f1->angle) + y * cos(f2->angle - + f1->angle); + x = tmp; + } + x2 = (x - f2->rect.nc) * c->image->width / (f2->rect.mc - + f2->rect.nc); + y2 = (y - f2->rect.ni) * c->image->height / (f2->rect.mi - + f2->rect.ni); + sprintf(str, "%3.2g %3.2g ", + ((int) ((x2 - (x1 * 8 + 4)) * 10)) / 10.0, + ((int) ((y2 - (y1 * 8 + 4)) * 10)) / 10.0); + xio_puts(str, f); + } + xio_putc('\n', f); + } + xio_close(f); + /*printf ("Frameend\n"); */ +} + +#define MAXBFRAMES 5 +#define IFRAMEDIST (27) +static int iframedist; +static int mvectors; +static xio_file patf; +static void +uih_encodeframe(int startpos, int endpos, struct frame_info *curframe) +{ + static int lastiframe = -200; + static struct frame_info lastp; + static struct frame_info bframes[MAXBFRAMES]; + static int nbframes = 0; + int i; + char type; + if (!gc) + printf(" motion"); + fflush(stdout); + if (endpos > startpos + 4) { + if (endpos - lastiframe > iframedist) + type = 'I'; + else + type = 'P'; + } else { + if (endpos - lastiframe > iframedist) + type = 'I'; + else + type = (startpos - lastiframe) % 3 ? 'B' : 'P'; + if (startpos != endpos) + type = 'P'; + } + if (curframe->newimage) + type = 'I'; + if (mvectors) { + switch (type) { + case 'I': + if (startpos) + save_frame_dist(uih, 0, curframe, &lastp); + lastp = *curframe; + break; + case 'P': + save_frame_dist(uih, 0, curframe, &lastp); + lastp = *curframe; + break; + case 'B': + save_frame_dist(uih, 0, curframe, &lastp); + if (nbframes < MAXBFRAMES) { + bframes[nbframes] = *curframe; + bframes[nbframes].name = mystrdup(curframe->name); + nbframes++; + } + break; + } + } + xio_putc(type, patf); + if (type == 'I') + lastiframe = startpos; + if (startpos != endpos) { + while (startpos != endpos) + xio_putc('p', patf), startpos++; + } + if (!gc) + printf(" %c", type); + fflush(stdout); + if (mvectors) { + if (type != 'B' && nbframes) { + if (!gc) + printf(" backframes"); + fflush(stdout); + for (i = 0; i < nbframes; i++) { + save_frame_dist(uih, 1, bframes + i, curframe); + fflush(stdout); + free(bframes[i].name); + } + nbframes = 0; + } + } + xio_flush(patf); +} + +extern struct filteraction antialias_filter; +int +uih_renderanimation(struct uih_context *gc1, CONST char *basename, + CONST xio_constpath animation, int width, int height, + float pixelwidth, float pixelheight, int frametime, + int type, int antialias, int slowmode, + int letterspersec, CONST char *catalog, + int motionvectors, int iframedist2) +{ + struct palette *pal = + createpalette(0, 0, type, 0, 0, NULL, NULL, NULL, NULL, NULL); + struct image *img; + xio_file of; + FILE *f; + xio_file af; + char s[200]; + int lastframenum = -1; + int aliasnum = 0; + static char *saveddata; + int newimage; + int y; + + struct frame_info curframe; + int framenum = 0; + + + noiselevel = ALL; + gc = gc1; + if (gc) + gc->incalculation = 1; + + mvectors = motionvectors; + printmsg(gettext("Vectors: %i"), motionvectors); + if (iframedist2) + iframedist = iframedist2; + else + iframedist = 27; + + printmsg(gettext("Initializing")); + if (!(type & (TRUECOLOR24 | TRUECOLOR | TRUECOLOR16 | GRAYSCALE))) + antialias = 0; + + while (uih_filters[aliasnum] != &antialias_filter) + aliasnum++; + + if (!pal) { + error(gettext("Cannot create palette")); + if (gc) + gc->incalculation = 0; + return 0; + } + if (!pixelwidth) + pixelwidth = 29.0 / width; + if (!pixelheight) + pixelheight = 21.5 / height; + img = create_image_mem(width, height, 2, pal, pixelwidth, pixelheight); + if (!img) { + error(gettext("Cannot create image\n")); + if (gc) + gc->incalculation = 0; + destroypalette(pal); + return 0; + } + saveddata = + (char *) malloc(img->width * img->height * img->bytesperpixel); + if (saveddata == NULL) { + error(gettext("Cannot create checking buffer!")); + if (gc) + gc->incalculation = 0; + destroy_image(img); + destroypalette(pal); + return 0; + } + uih = uih_mkcontext(0, img, passfunc, NULL, NULL); + if (!uih) { + error(gettext("Cannot create context\n")); + if (gc) + gc->incalculation = 0; + destroy_image(img); + destroypalette(pal); + free(saveddata); + return 0; + } + uih->fcontext->slowmode = 1; + uih_constantframetime(uih, frametime); + af = xio_ropen(animation); + if (af == NULL) { + error(gettext("Cannot open animation file\n")); + if (gc) + gc->incalculation = 0; + uih_freecontext(uih); + destroy_image(img); + destroypalette(pal); + free(saveddata); + return 0; + } + + if (!gc) { + printmsg(gettext("Loading catalogs")); + if (!gc) { + uih_loadcatalog(uih, "english"); + if (uih->errstring) { + uiherror(uih); + if (gc) + gc->incalculation = 0; + uih_freecontext(uih); + destroy_image(img); + destroypalette(pal); + free(saveddata); + xio_close(af); + return 0; + } + } + if (catalog != NULL) + uih_loadcatalog(uih, catalog); + if (uih->errstring) { + uiherror(uih); + if (gc) + gc->incalculation = 0; + uih_freecontext(uih); + destroy_image(img); + destroypalette(pal); + free(saveddata); + if (!gc) + uih_freecatalog(uih); + xio_close(af); + return 0; + } + printmsg(gettext("Processing command line options")); + { + CONST menuitem *item; + dialogparam *d; + while ((item = menu_delqueue(&d)) != NULL) { + menu_activate(item, uih, d); + } + } + if (uih->errstring) { + uiherror(uih); + if (gc) + gc->incalculation = 0; + uih_freecontext(uih); + destroy_image(img); + destroypalette(pal); + free(saveddata); + if (!gc) + uih_freecatalog(uih); + xio_close(af); + return 0; + } + } + + printmsg(gettext("Enabling animation replay\n")); + + uih_replayenable(uih, af, animation, 1); + + sprintf(s, "%s.par", basename); + of = xio_wopen(s); + if (of == NULL) { + error(gettext("Cannot open image file")); + if (gc) + gc->incalculation = 0; + uih_freecontext(uih); + destroy_image(img); + destroypalette(pal); + free(saveddata); + if (!gc) + uih_freecatalog(uih); + return 0; + } + sprintf(s, "%s.pat", basename); + patf = xio_wopen(s); + if (patf == NULL) { + error(gettext("Cannot open pattern file")); + if (gc) + gc->incalculation = 0; + uih_freecontext(uih); + destroy_image(img); + destroypalette(pal); + free(saveddata); + if (!gc) + uih_freecatalog(uih); + xio_close(of); + return 0; + } + uih_letterspersec(uih, letterspersec); + + + + if (!gc) + x_message(gettext("Entering calculation loop!")); + else + printmsg(gettext("Entering calculation loop!")); + + while ((uih->play || uih->display) && !interrupt) { + if (uih->errstring) { + uiherror(uih); + if (gc) + gc->incalculation = 0; + uih_freecontext(uih); + destroy_image(img); + destroypalette(pal); + free(saveddata); + if (!gc) + uih_freecatalog(uih); + xio_close(of); + xio_close(patf); + return 0; + } + fflush(stdout); + tl_process_group(syncgroup, NULL); + uih_update(uih, 0, 0, 0); + + + if (uih->display) { + + if (lastframenum < framenum - 1) { + if (lastframenum == framenum - 1) + printmsg(gettext("Frame %i skipped."), framenum - 1); + else + printmsg(gettext("Frames %i - %i skipped."), + lastframenum, framenum - 1); + } + + printmsg(gettext("Frame %4i: "), framenum); + + newline = 1; + newimage = 0; + if (uih->recalculatemode > 0) { + if (!gc) + printf("calculating"), fflush(stdout); + if (slowmode) + uih_newimage(uih), uih->fcontext->version++; + } + if (antialias && !uih->filter[aliasnum]) { + if (!gc) + printf("antialias "); + uih->aliasnum = aliasnum; + uih_enablefilter(uih, aliasnum); + } + uih_prepare_image(uih); + + if (!gc) + printf(" rendering"); + fflush(stdout); + uih_drawwindows(uih); + + y = 0; + if (lastframenum >= 0) { + for (; y < img->height; y++) + if (memcmp + (saveddata + img->width * img->bytesperpixel * y, + uih->image->currlines[y], + img->width * img->bytesperpixel)) + break; + } + + + if (y != img->height) { + for (; y < img->height; y++) + memcpy(saveddata + img->width * img->bytesperpixel * y, + uih->image->currlines[y], + img->width * img->bytesperpixel); + if (framenum) + uih_encodeframe(lastframenum, framenum - 1, &curframe); + if (!gc) + printf(" saving"); + fflush(stdout); + sprintf(s, "%s%04i.png", basename, framenum); + curframe.rect = uih->fcontext->rs; + curframe.angle = uih->fcontext->angle; + curframe.name = s; + curframe.newimage = newimage; + + + f = fopen(s, "wb"); + if (f == NULL) { + error(gettext("Cannot open image file")); + if (gc) + gc->incalculation = 0; + uih_freecontext(uih); + destroy_image(img); + destroypalette(pal); + free(saveddata); + if (!gc) + uih_freecatalog(uih); + xio_close(of); + xio_close(patf); + return 0; + } + writepng(f, uih->image); + printmsg(gettext(" done.")); + uih_displayed(uih); + lastframenum = framenum; + } else { + printmsg(gettext(" skipping...")); + uih_displayed(uih); + } + } + xio_puts(s, of); + xio_puts("\n", of); + xio_flush(of); + framenum++; + } + curframe.newimage = 1; + if (framenum) + uih_encodeframe(lastframenum, framenum - 1, &curframe); + if (uih->errstring) { + uiherror(uih); + if (gc) + gc->incalculation = 0; + uih_freecontext(uih); + destroy_image(img); + destroypalette(pal); + free(saveddata); + if (!gc) + uih_freecatalog(uih); + xio_close(of); + xio_close(patf); + return 0; + } + xio_close(of); + free(saveddata); + xio_close(patf); + uih_freecontext(uih); + destroy_image(img); + destroypalette(pal); + if (interrupt) + error(gettext("Calculation interrupted")); + else { + if (!gc) + x_message(gettext("Calculation finished")); + else + printmsg(gettext("Calculation finished")); + } + if (gc) + gc->incalculation = 0; + if (!gc) + uih_freecatalog(uih); + return 1; +} + +int +uih_renderimage(struct uih_context *gc1, xio_file af, + CONST xio_constpath path, struct image *img, int antialias, + CONST char *catalog, int noise) +{ + int aliasnum = 0; + int ok = 1; + noiselevel = noise; + gc = gc1; + if (gc) + gc->incalculation = 1; + + while (uih_filters[aliasnum] != &antialias_filter) + aliasnum++; + + uih = uih_mkcontext(0, img, passfunc, NULL, NULL); + if (!uih) { + error(gettext("Cannot create context\n")); + if (gc) + gc->incalculation = 0; + return 0; + } + uih->fcontext->slowmode = 1; + uih_constantframetime(uih, 1000000 / 10); + + if (!gc) { + printmsg(gettext("Loading catalogs")); + uih_loadcatalog(uih, "english"); + if (uih->errstring) { + fprintf(stderr, uih->errstring); + uih_clearmessages(uih); + uih->errstring = NULL; + } + if (catalog != NULL) + uih_loadcatalog(uih, catalog); + if (uih->errstring) { + fprintf(stderr, uih->errstring); + uih_clearmessages(uih); + uih->errstring = NULL; + } + if (uih->errstring) { + uih_freecatalog(uih); + uih_freecontext(uih); + uiherror(uih); + if (gc) + gc->incalculation = 0; + return 0; + } + } + + uih_load(uih, af, path); + if (uih->errstring) { + uiherror(uih); + uih_freecatalog(uih); + uih_freecontext(uih); + if (gc) + gc->incalculation = 0; + return 0; + } + printmsg(gettext("Entering calculation loop!")); + + tl_process_group(syncgroup, NULL); + uih_update(uih, 0, 0, 0); + + uih_newimage(uih), uih->fcontext->version++; + if (antialias && !uih->filter[aliasnum]) { + uih->aliasnum = aliasnum; + uih_enablefilter(uih, aliasnum); + } + uih_prepare_image(uih); + if (uih->errstring) + ok = 0; + uih_drawwindows(uih); + if (uih->errstring) + ok = 0; + uih_freecontext(uih); + uih_freecatalog(uih); + if (interrupt) + error(gettext("Calculation interrupted")); + else { + printmsg(gettext("Calculation finished")); + } + if (gc) + gc->incalculation = 0; + return 1; +} -- cgit v0.9.1