t* My version of sent URI git clone git://git.codevoid.de/sent-sdk.git DIR Log DIR Files DIR Refs DIR README DIR LICENSE --- DIR commit 8e81a9be0097719bfb30d7f5802d5e72fbfc2fa6 DIR parent 982e80256045fcbe6e41dd057b21539480098a70 URI Author: c0dev0id <sh+github[at]codevoid[dot]de> Date: Tue, 1 Dec 2020 20:41:55 +0100 rework patches Diffstat: D .gitignore | 30 ------------------------------ A config.h | 59 +++++++++++++++++++++++++++++++ A patches/sent-bilinearscaling-1.0.d… | 88 +++++++++++++++++++++++++++++++ A patches/sent-options-20190213-72d3… | 72 +++++++++++++++++++++++++++++++ A patches/sent-progress-bar-1.0.diff | 31 +++++++++++++++++++++++++++++++ M sent.1 | 11 +++++++++++ M sent.c | 1084 +++++++++++++++++-------------- 7 files changed, 841 insertions(+), 534 deletions(-) --- DIR diff --git a/.gitignore b/.gitignore t@@ -1,30 +0,0 @@ -# Object files -*.o -*.ko -*.obj -*.elf - -# Libraries -*.lib -*.a - -# Shared objects (inc. Windows DLLs) -*.dll -*.so -*.so.* -*.dylib - -# Executables -*.exe -*.out -*.app -*.i*86 -*.x86_64 -*.hex -/sent - -# vim -*.swp -*~ - -config.h DIR diff --git a/config.h b/config.h t@@ -0,0 +1,59 @@ +/* See LICENSE file for copyright and license details. */ + +static char *fontfallbacks[] = { + "dejavu sans", + "roboto", + "ubuntu", +}; +#define NUMFONTSCALES 42 +#define FONTSZ(x) ((int)(10.0 * powf(1.1288, (x)))) /* x in [0, NUMFONTSCALES-1] */ + +static const char *colors[] = { + "#226622", /* foreground color */ + "#080808", /* background color */ +}; + +static const float linespacing = 1.4; + +/* how much screen estate is to be used at max for the content */ +static const float usablewidth = 0.75; +static const float usableheight = 0.75; + +/* height of the presentation progress bar */ +static const int progressheight = 12; + +static Mousekey mshortcuts[] = { + /* button function argument */ + { Button1, advance, {.i = +1} }, + { Button3, advance, {.i = -1} }, + { Button4, advance, {.i = -1} }, + { Button5, advance, {.i = +1} }, +}; + +static Shortcut shortcuts[] = { + /* keysym function argument */ + { XK_Escape, quit, {0} }, + { XK_q, quit, {0} }, + { XK_Right, advance, {.i = +1} }, + { XK_Left, advance, {.i = -1} }, + { XK_Return, advance, {.i = +1} }, + { XK_space, advance, {.i = +1} }, + { XK_BackSpace, advance, {.i = -1} }, + { XK_l, advance, {.i = +1} }, + { XK_h, advance, {.i = -1} }, + { XK_j, advance, {.i = +1} }, + { XK_k, advance, {.i = -1} }, + { XK_Down, advance, {.i = +1} }, + { XK_Up, advance, {.i = -1} }, + { XK_Next, advance, {.i = +1} }, + { XK_Prior, advance, {.i = -1} }, + { XK_n, advance, {.i = +1} }, + { XK_p, advance, {.i = -1} }, + { XK_r, reload, {0} }, +}; + +static Filter filters[] = { + { "\\.ff$", "cat" }, + { "\\.ff.bz2$", "bunzip2" }, + { "\\.[a-z0-9]+$", "2ff" }, +}; DIR diff --git a/patches/sent-bilinearscaling-1.0.diff b/patches/sent-bilinearscaling-1.0.diff t@@ -0,0 +1,88 @@ +diff --git a/sent.c b/sent.c +index 0da2bff..d92cf3b 100644 +--- a/sent.c ++++ b/sent.c +@@ -282,27 +282,66 @@ ffprepare(Image *img) + img->state |= SCALED; + } + ++static unsigned char double_to_uchar_clamp255(double dbl) ++{ ++ dbl = round(dbl); ++ ++ return ++ (dbl < 0.0) ? 0 : ++ (dbl > 255.0) ? 255 : (unsigned char)dbl; ++} ++ ++static int int_clamp(int integer, int lower, int upper) ++{ ++ if (integer < lower) ++ return lower; ++ else if (integer >= upper) ++ return upper - 1; ++ else ++ return integer; ++} ++ + void + ffscale(Image *img) + { +- unsigned int x, y; +- unsigned int width = img->ximg->width; +- unsigned int height = img->ximg->height; +- char* newBuf = img->ximg->data; +- unsigned char* ibuf; +- unsigned int jdy = img->ximg->bytes_per_line / 4 - width; +- unsigned int dx = (img->bufwidth << 10) / width; +- +- for (y = 0; y < height; y++) { +- unsigned int bufx = img->bufwidth / width; +- ibuf = &img->buf[y * img->bufheight / height * img->bufwidth * 3]; +- +- for (x = 0; x < width; x++) { +- *newBuf++ = (ibuf[(bufx >> 10)*3+2]); +- *newBuf++ = (ibuf[(bufx >> 10)*3+1]); +- *newBuf++ = (ibuf[(bufx >> 10)*3+0]); ++ const unsigned width = img->ximg->width; ++ const unsigned height = img->ximg->height; ++ unsigned char* newBuf = (unsigned char*)img->ximg->data; ++ const unsigned jdy = img->ximg->bytes_per_line / 4 - width; ++ ++ const double x_scale = ((double)img->bufwidth/(double)width); ++ const double y_scale = ((double)img->bufheight/(double)height); ++ ++ for (unsigned y = 0; y < height; ++y) { ++ const double old_y = (double)y * y_scale; ++ const double y_factor = ceil(old_y) - old_y; ++ const int old_y_int_0 = int_clamp((int)floor(old_y), 0, img->bufheight); ++ const int old_y_int_1 = int_clamp((int)ceil(old_y), 0, img->bufheight); ++ ++ for (unsigned x = 0; x < width; ++x) { ++ const double old_x = (double)x * x_scale; ++ const double x_factor = ceil(old_x) - old_x; ++ const int old_x_int_0 = int_clamp((int)floor(old_x), 0, img->bufwidth); ++ const int old_x_int_1 = int_clamp((int)ceil(old_x), 0, img->bufwidth); ++ ++ const unsigned c00_pos = 3*((old_x_int_0) + ((old_y_int_0)*img->bufwidth)); ++ const unsigned c01_pos = 3*((old_x_int_0) + ((old_y_int_1)*img->bufwidth)); ++ const unsigned c10_pos = 3*((old_x_int_1) + ((old_y_int_0)*img->bufwidth)); ++ const unsigned c11_pos = 3*((old_x_int_1) + ((old_y_int_1)*img->bufwidth)); ++ ++ for (int i = 2; i >= 0 ; --i) { ++ const unsigned char c00 = img->buf[c00_pos + i]; ++ const unsigned char c01 = img->buf[c01_pos + i]; ++ const unsigned char c10 = img->buf[c10_pos + i]; ++ const unsigned char c11 = img->buf[c11_pos + i]; ++ ++ const double x_result_0 = (double)c00*x_factor + (double)c10*(1.0 - x_factor); ++ const double x_result_1 = (double)c01*x_factor + (double)c11*(1.0 - x_factor); ++ const double result = x_result_0*y_factor + x_result_1*(1.0 - y_factor); ++ ++ *newBuf++ = double_to_uchar_clamp255(result); ++ } + newBuf++; +- bufx += dx; + } + newBuf += jdy; + } DIR diff --git a/patches/sent-options-20190213-72d33d4.diff b/patches/sent-options-20190213-72d33d4.diff t@@ -0,0 +1,72 @@ +From 3a348cc15a97df8e8784b129800293dcfba28f3f Mon Sep 17 00:00:00 2001 +From: Sunur Efe Vural <efe@efe.kim> +Date: Wed, 13 Feb 2019 14:28:17 -0500 +Subject: [PATCH] Commandline Options + +A simple patch that adds extra commandline options to sent. +--- + sent.1 | 11 +++++++++++ + sent.c | 11 ++++++++++- + 2 files changed, 21 insertions(+), 1 deletion(-) + +diff --git a/sent.1 b/sent.1 +index fabc614..5d55bf4 100644 +--- a/sent.1 ++++ b/sent.1 +@@ -5,6 +5,9 @@ + .Nd simple plaintext presentation tool + .Sh SYNOPSIS + .Nm ++.Op Fl f Ar font ++.Op Fl c Ar fgcolor ++.Op Fl b Ar bgcolor + .Op Fl v + .Op Ar file + .Sh DESCRIPTION +@@ -21,6 +24,14 @@ few minutes. + .Bl -tag -width Ds + .It Fl v + Print version information to stdout and exit. ++.It Fl f Ar font ++Defines the ++.Ar font ++when sent is run. ++.It Fl c Ar fgcolor ++Defines the foreground color when sent is run. ++.It Fl b Ar bgcolor ++Defines the background color when sent is run. + .El + .Sh USAGE + .Bl -tag -width Ds +diff --git a/sent.c b/sent.c +index c50a572..0b36e32 100644 +--- a/sent.c ++++ b/sent.c +@@ -675,7 +675,7 @@ configure(XEvent *e) + void + usage() + { +- die("usage: %s [file]", argv0); ++ die("usage: %s [-c fgcolor] [-b bgcolor] [-f font] [file]", argv0); + } + + int +@@ -687,6 +687,15 @@ main(int argc, char *argv[]) + case 'v': + fprintf(stderr, "sent-"VERSION"\n"); + return 0; ++ case 'f': ++ fontfallbacks[0] = EARGF(usage()); ++ break; ++ case 'c': ++ colors[0] = EARGF(usage()); ++ break; ++ case 'b': ++ colors[1] = EARGF(usage()); ++ break; + default: + usage(); + } ARGEND +-- +2.20.1 + DIR diff --git a/patches/sent-progress-bar-1.0.diff b/patches/sent-progress-bar-1.0.diff t@@ -0,0 +1,31 @@ +diff --git a/config.def.h b/config.def.h +index 60eb376..25d89e0 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -19,6 +19,9 @@ static const float linespacing = 1.4; + static const float usablewidth = 0.75; + static const float usableheight = 0.75; + ++/* height of the presentation progress bar */ ++static const int progressheight = 5; ++ + static Mousekey mshortcuts[] = { + /* button function argument */ + { Button1, advance, {.i = +1} }, +diff --git a/sent.c b/sent.c +index c50a572..046466e 100644 +--- a/sent.c ++++ b/sent.c +@@ -533,6 +533,12 @@ xdraw() + 0, + slides[idx].lines[i], + 0); ++ if (idx != 0 && progressheight != 0) { ++ drw_rect(d, ++ 0, xw.h - progressheight, ++ (xw.w * idx)/(slidecount - 1), progressheight, ++ 1, 0); ++ } + drw_map(d, xw.win, 0, 0, xw.w, xw.h); + } else { + if (!(im->state & SCALED)) DIR diff --git a/sent.1 b/sent.1 t@@ -5,6 +5,9 @@ .Nd simple plaintext presentation tool .Sh SYNOPSIS .Nm +.Op Fl f Ar font +.Op Fl c Ar fgcolor +.Op Fl b Ar bgcolor .Op Fl v .Op Ar file .Sh DESCRIPTION t@@ -21,6 +24,14 @@ few minutes. .Bl -tag -width Ds .It Fl v Print version information to stdout and exit. +.It Fl f Ar font +Defines the +.Ar font +when sent is run. +.It Fl c Ar fgcolor +Defines the foreground color when sent is run. +.It Fl b Ar bgcolor +Defines the background color when sent is run. .El .Sh USAGE .Bl -tag -width Ds DIR diff --git a/sent.c b/sent.c t@@ -31,59 +31,59 @@ char *argv0; #define MAXFONTSTRLEN 128 typedef enum { - NONE = 0, - SCALED = 1, + NONE = 0, + SCALED = 1, } imgstate; typedef struct { - unsigned char *buf; - unsigned int bufwidth, bufheight; - imgstate state; - XImage *ximg; - int numpasses; + unsigned char *buf; + unsigned int bufwidth, bufheight; + imgstate state; + XImage *ximg; + int numpasses; } Image; typedef struct { - char *regex; - char *bin; + char *regex; + char *bin; } Filter; typedef struct { - unsigned int linecount; - char **lines; - Image *img; - char *embed; + unsigned int linecount; + char **lines; + Image *img; + char *embed; } Slide; /* Purely graphic info */ typedef struct { - Display *dpy; - Window win; - Atom wmdeletewin, netwmname; - Visual *vis; - XSetWindowAttributes attrs; - int scr; - int w, h; - int uw, uh; /* usable dimensions for drawing text and images */ + Display *dpy; + Window win; + Atom wmdeletewin, netwmname; + Visual *vis; + XSetWindowAttributes attrs; + int scr; + int w, h; + int uw, uh; /* usable dimensions for drawing text and images */ } XWindow; typedef union { - int i; - unsigned int ui; - float f; - const void *v; + int i; + unsigned int ui; + float f; + const void *v; } Arg; typedef struct { - unsigned int b; - void (*func)(const Arg *); - const Arg arg; + unsigned int b; + void (*func)(const Arg *); + const Arg arg; } Mousekey; typedef struct { - KeySym keysym; - void (*func)(const Arg *); - const Arg arg; + KeySym keysym; + void (*func)(const Arg *); + const Arg arg; } Shortcut; static void fffree(Image *img); t@@ -127,562 +127,638 @@ static Fnt *fonts[NUMFONTSCALES]; static int running = 1; static void (*handler[LASTEvent])(XEvent *) = { - [ButtonPress] = bpress, - [ClientMessage] = cmessage, - [ConfigureNotify] = configure, - [Expose] = expose, - [KeyPress] = kpress, + [ButtonPress] = bpress, + [ClientMessage] = cmessage, + [ConfigureNotify] = configure, + [Expose] = expose, + [KeyPress] = kpress, }; -int filter(int fd, const char *cmd) +int +filter(int fd, const char *cmd) { - int fds[2]; - - if (pipe(fds) < 0) - die("sent: Unable to create pipe:"); - - switch (fork()) { - case -1: - die("sent: Unable to fork:"); - case 0: - dup2(fd, 0); - dup2(fds[1], 1); - close(fds[0]); - close(fds[1]); - execlp("sh", "sh", "-c", cmd, (char *)0); - fprintf(stderr, "sent: execlp sh -c '%s': %s\n", cmd, strerror(errno)); - _exit(1); - } - close(fds[1]); - return fds[0]; + int fds[2]; + + if (pipe(fds) < 0) + die("sent: Unable to create pipe:"); + + switch (fork()) { + case -1: + die("sent: Unable to fork:"); + case 0: + dup2(fd, 0); + dup2(fds[1], 1); + close(fds[0]); + close(fds[1]); + execlp("sh", "sh", "-c", cmd, (char *)0); + fprintf(stderr, "sent: execlp sh -c '%s': %s\n", cmd, strerror(errno)); + _exit(1); + } + close(fds[1]); + return fds[0]; } -void fffree(Image *img) +void +fffree(Image *img) { - free(img->buf); - if (img->ximg) - XDestroyImage(img->ximg); - free(img); + free(img->buf); + if (img->ximg) + XDestroyImage(img->ximg); + free(img); } -void ffload(Slide *s) +void +ffload(Slide *s) { - uint32_t y, x; - uint16_t *row; - uint8_t opac, fg_r, fg_g, fg_b, bg_r, bg_g, bg_b; - size_t rowlen, off, nbytes, i; - ssize_t count; - unsigned char hdr[16]; - char *bin = NULL; - char *filename; - regex_t regex; - int fdin, fdout; - - if (s->img || !(filename = s->embed) || !s->embed[0]) - return; /* already done */ - - for (i = 0; i < LEN(filters); i++) { - if (regcomp(®ex, filters[i].regex, - REG_NOSUB | REG_EXTENDED | REG_ICASE)) { - fprintf(stderr, "sent: Invalid regex '%s'\n", filters[i].regex); - continue; - } - if (!regexec(®ex, filename, 0, NULL, 0)) { - bin = filters[i].bin; - regfree(®ex); - break; - } - regfree(®ex); - } - if (!bin) - die("sent: Unable to find matching filter for '%s'", filename); - - if ((fdin = open(filename, O_RDONLY)) < 0) - die("sent: Unable to open '%s':", filename); - - if ((fdout = filter(fdin, bin)) < 0) - die("sent: Unable to filter '%s':", filename); - close(fdin); - - if (read(fdout, hdr, 16) != 16) - die("sent: Unable to read filtered file '%s':", filename); - if (memcmp("farbfeld", hdr, 8)) - die("sent: Filtered file '%s' has no valid farbfeld header", filename); - - s->img = ecalloc(1, sizeof(Image)); - s->img->bufwidth = ntohl(*(uint32_t *)&hdr[8]); - s->img->bufheight = ntohl(*(uint32_t *)&hdr[12]); - - if (s->img->buf) - free(s->img->buf); - /* internally the image is stored in 888 format */ - s->img->buf = ecalloc(s->img->bufwidth * s->img->bufheight, strlen("888")); - - /* scratch buffer to read row by row */ - rowlen = s->img->bufwidth * 2 * strlen("RGBA"); - row = ecalloc(1, rowlen); - - /* extract window background color channels for transparency */ - bg_r = (sc[ColBg].pixel >> 16) % 256; - bg_g = (sc[ColBg].pixel >> 8) % 256; - bg_b = (sc[ColBg].pixel >> 0) % 256; - - for (off = 0, y = 0; y < s->img->bufheight; y++) { - nbytes = 0; - while (nbytes < rowlen) { - count = read(fdout, (char *)row + nbytes, rowlen - nbytes); - if (count < 0) - die("sent: Unable to read from pipe:"); - nbytes += count; - } - for (x = 0; x < rowlen / 2; x += 4) { - fg_r = ntohs(row[x + 0]) / 257; - fg_g = ntohs(row[x + 1]) / 257; - fg_b = ntohs(row[x + 2]) / 257; - opac = ntohs(row[x + 3]) / 257; - /* blend opaque part of image data with window background color to - * emulate transparency */ - s->img->buf[off++] = (fg_r * opac + bg_r * (255 - opac)) / 255; - s->img->buf[off++] = (fg_g * opac + bg_g * (255 - opac)) / 255; - s->img->buf[off++] = (fg_b * opac + bg_b * (255 - opac)) / 255; - } - } - - free(row); - close(fdout); + uint32_t y, x; + uint16_t *row; + uint8_t opac, fg_r, fg_g, fg_b, bg_r, bg_g, bg_b; + size_t rowlen, off, nbytes, i; + ssize_t count; + unsigned char hdr[16]; + char *bin = NULL; + char *filename; + regex_t regex; + int fdin, fdout; + + if (s->img || !(filename = s->embed) || !s->embed[0]) + return; /* already done */ + + for (i = 0; i < LEN(filters); i++) { + if (regcomp(®ex, filters[i].regex, + REG_NOSUB | REG_EXTENDED | REG_ICASE)) { + fprintf(stderr, "sent: Invalid regex '%s'\n", filters[i].regex); + continue; + } + if (!regexec(®ex, filename, 0, NULL, 0)) { + bin = filters[i].bin; + regfree(®ex); + break; + } + regfree(®ex); + } + if (!bin) + die("sent: Unable to find matching filter for '%s'", filename); + + if ((fdin = open(filename, O_RDONLY)) < 0) + die("sent: Unable to open '%s':", filename); + + if ((fdout = filter(fdin, bin)) < 0) + die("sent: Unable to filter '%s':", filename); + close(fdin); + + if (read(fdout, hdr, 16) != 16) + die("sent: Unable to read filtered file '%s':", filename); + if (memcmp("farbfeld", hdr, 8)) + die("sent: Filtered file '%s' has no valid farbfeld header", filename); + + s->img = ecalloc(1, sizeof(Image)); + s->img->bufwidth = ntohl(*(uint32_t *)&hdr[8]); + s->img->bufheight = ntohl(*(uint32_t *)&hdr[12]); + + if (s->img->buf) + free(s->img->buf); + /* internally the image is stored in 888 format */ + s->img->buf = ecalloc(s->img->bufwidth * s->img->bufheight, strlen("888")); + + /* scratch buffer to read row by row */ + rowlen = s->img->bufwidth * 2 * strlen("RGBA"); + row = ecalloc(1, rowlen); + + /* extract window background color channels for transparency */ + bg_r = (sc[ColBg].pixel >> 16) % 256; + bg_g = (sc[ColBg].pixel >> 8) % 256; + bg_b = (sc[ColBg].pixel >> 0) % 256; + + for (off = 0, y = 0; y < s->img->bufheight; y++) { + nbytes = 0; + while (nbytes < rowlen) { + count = read(fdout, (char *)row + nbytes, rowlen - nbytes); + if (count < 0) + die("sent: Unable to read from pipe:"); + nbytes += count; + } + for (x = 0; x < rowlen / 2; x += 4) { + fg_r = ntohs(row[x + 0]) / 257; + fg_g = ntohs(row[x + 1]) / 257; + fg_b = ntohs(row[x + 2]) / 257; + opac = ntohs(row[x + 3]) / 257; + /* blend opaque part of image data with window background color to + * emulate transparency */ + s->img->buf[off++] = (fg_r * opac + bg_r * (255 - opac)) / 255; + s->img->buf[off++] = (fg_g * opac + bg_g * (255 - opac)) / 255; + s->img->buf[off++] = (fg_b * opac + bg_b * (255 - opac)) / 255; + } + } + + free(row); + close(fdout); } -void ffprepare(Image *img) +void +ffprepare(Image *img) { - int depth = DefaultDepth(xw.dpy, xw.scr); - int width = xw.uw; - int height = xw.uh; + int depth = DefaultDepth(xw.dpy, xw.scr); + int width = xw.uw; + int height = xw.uh; - if (xw.uw * img->bufheight > xw.uh * img->bufwidth) - width = img->bufwidth * xw.uh / img->bufheight; - else - height = img->bufheight * xw.uw / img->bufwidth; + if (xw.uw * img->bufheight > xw.uh * img->bufwidth) + width = img->bufwidth * xw.uh / img->bufheight; + else + height = img->bufheight * xw.uw / img->bufwidth; - if (depth < 24) - die("sent: Display color depths < 24 not supported"); + if (depth < 24) + die("sent: Display color depths < 24 not supported"); - if (!(img->ximg = XCreateImage(xw.dpy, CopyFromParent, depth, ZPixmap, 0, - NULL, width, height, 32, 0))) - die("sent: Unable to create XImage"); + if (!(img->ximg = XCreateImage(xw.dpy, CopyFromParent, depth, ZPixmap, 0, + NULL, width, height, 32, 0))) + die("sent: Unable to create XImage"); - img->ximg->data = ecalloc(height, img->ximg->bytes_per_line); - if (!XInitImage(img->ximg)) - die("sent: Unable to initiate XImage"); + img->ximg->data = ecalloc(height, img->ximg->bytes_per_line); + if (!XInitImage(img->ximg)) + die("sent: Unable to initiate XImage"); - ffscale(img); - img->state |= SCALED; + ffscale(img); + img->state |= SCALED; } -void ffscale(Image *img) +static unsigned char double_to_uchar_clamp255(double dbl) { - unsigned int x, y; - unsigned int width = img->ximg->width; - unsigned int height = img->ximg->height; - char* newBuf = img->ximg->data; - unsigned char* ibuf; - unsigned int jdy = img->ximg->bytes_per_line / 4 - width; - unsigned int dx = (img->bufwidth << 10) / width; - - for (y = 0; y < height; y++) { - unsigned int bufx = img->bufwidth / width; - ibuf = &img->buf[y * img->bufheight / height * img->bufwidth * 3]; - - for (x = 0; x < width; x++) { - *newBuf++ = (ibuf[(bufx >> 10)*3+2]); - *newBuf++ = (ibuf[(bufx >> 10)*3+1]); - *newBuf++ = (ibuf[(bufx >> 10)*3+0]); - newBuf++; - bufx += dx; - } - newBuf += jdy; - } + dbl = round(dbl); + + return + (dbl < 0.0) ? 0 : + (dbl > 255.0) ? 255 : (unsigned char)dbl; +} + +static int int_clamp(int integer, int lower, int upper) +{ + if (integer < lower) + return lower; + else if (integer >= upper) + return upper - 1; + else + return integer; +} + +void +ffscale(Image *img) +{ + const unsigned width = img->ximg->width; + const unsigned height = img->ximg->height; + unsigned char* newBuf = (unsigned char*)img->ximg->data; + const unsigned jdy = img->ximg->bytes_per_line / 4 - width; + + const double x_scale = ((double)img->bufwidth/(double)width); + const double y_scale = ((double)img->bufheight/(double)height); + + for (unsigned y = 0; y < height; ++y) { + const double old_y = (double)y * y_scale; + const double y_factor = ceil(old_y) - old_y; + const int old_y_int_0 = int_clamp((int)floor(old_y), 0, img->bufheight); + const int old_y_int_1 = int_clamp((int)ceil(old_y), 0, img->bufheight); + + for (unsigned x = 0; x < width; ++x) { + const double old_x = (double)x * x_scale; + const double x_factor = ceil(old_x) - old_x; + const int old_x_int_0 = int_clamp((int)floor(old_x), 0, img->bufwidth); + const int old_x_int_1 = int_clamp((int)ceil(old_x), 0, img->bufwidth); + + const unsigned c00_pos = 3*((old_x_int_0) + ((old_y_int_0)*img->bufwidth)); + const unsigned c01_pos = 3*((old_x_int_0) + ((old_y_int_1)*img->bufwidth)); + const unsigned c10_pos = 3*((old_x_int_1) + ((old_y_int_0)*img->bufwidth)); + const unsigned c11_pos = 3*((old_x_int_1) + ((old_y_int_1)*img->bufwidth)); + + for (int i = 2; i >= 0 ; --i) { + const unsigned char c00 = img->buf[c00_pos + i]; + const unsigned char c01 = img->buf[c01_pos + i]; + const unsigned char c10 = img->buf[c10_pos + i]; + const unsigned char c11 = img->buf[c11_pos + i]; + + const double x_result_0 = (double)c00*x_factor + (double)c10*(1.0 - x_factor); + const double x_result_1 = (double)c01*x_factor + (double)c11*(1.0 - x_factor); + const double result = x_result_0*y_factor + x_result_1*(1.0 - y_factor); + + *newBuf++ = double_to_uchar_clamp255(result); + } + newBuf++; + } + newBuf += jdy; + } } -void ffdraw(Image *img) +void +ffdraw(Image *img) { - int xoffset = (xw.w - img->ximg->width) / 2; - int yoffset = (xw.h - img->ximg->height) / 2; - XPutImage(xw.dpy, xw.win, d->gc, img->ximg, 0, 0, - xoffset, yoffset, img->ximg->width, img->ximg->height); - XFlush(xw.dpy); + int xoffset = (xw.w - img->ximg->width) / 2; + int yoffset = (xw.h - img->ximg->height) / 2; + XPutImage(xw.dpy, xw.win, d->gc, img->ximg, 0, 0, + xoffset, yoffset, img->ximg->width, img->ximg->height); + XFlush(xw.dpy); } -void getfontsize(Slide *s, unsigned int *width, unsigned int *height) +void +getfontsize(Slide *s, unsigned int *width, unsigned int *height) { - int i, j; - unsigned int curw, newmax; - float lfac = linespacing * (s->linecount - 1) + 1; - - /* fit height */ - for (j = NUMFONTSCALES - 1; j >= 0; j--) - if (fonts[j]->h * lfac <= xw.uh) - break; - LIMIT(j, 0, NUMFONTSCALES - 1); - drw_setfontset(d, fonts[j]); - - /* fit width */ - *width = 0; - for (i = 0; i < s->linecount; i++) { - curw = drw_fontset_getwidth(d, s->lines[i]); - newmax = (curw >= *width); - while (j > 0 && curw > xw.uw) { - drw_setfontset(d, fonts[--j]); - curw = drw_fontset_getwidth(d, s->lines[i]); - } - if (newmax) - *width = curw; - } - *height = fonts[j]->h * lfac; + int i, j; + unsigned int curw, newmax; + float lfac = linespacing * (s->linecount - 1) + 1; + + /* fit height */ + for (j = NUMFONTSCALES - 1; j >= 0; j--) + if (fonts[j]->h * lfac <= xw.uh) + break; + LIMIT(j, 0, NUMFONTSCALES - 1); + drw_setfontset(d, fonts[j]); + + /* fit width */ + *width = 0; + for (i = 0; i < s->linecount; i++) { + curw = drw_fontset_getwidth(d, s->lines[i]); + newmax = (curw >= *width); + while (j > 0 && curw > xw.uw) { + drw_setfontset(d, fonts[--j]); + curw = drw_fontset_getwidth(d, s->lines[i]); + } + if (newmax) + *width = curw; + } + *height = fonts[j]->h * lfac; } -void cleanup(int slidesonly) +void +cleanup(int slidesonly) { - unsigned int i, j; - - if (!slidesonly) { - for (i = 0; i < NUMFONTSCALES; i++) - drw_fontset_free(fonts[i]); - free(sc); - drw_free(d); - - XDestroyWindow(xw.dpy, xw.win); - XSync(xw.dpy, False); - XCloseDisplay(xw.dpy); - } - - if (slides) { - for (i = 0; i < slidecount; i++) { - for (j = 0; j < slides[i].linecount; j++) - free(slides[i].lines[j]); - free(slides[i].lines); - if (slides[i].img) - fffree(slides[i].img); - } - if (!slidesonly) { - free(slides); - slides = NULL; - } - } + unsigned int i, j; + + if (!slidesonly) { + for (i = 0; i < NUMFONTSCALES; i++) + drw_fontset_free(fonts[i]); + free(sc); + drw_free(d); + + XDestroyWindow(xw.dpy, xw.win); + XSync(xw.dpy, False); + XCloseDisplay(xw.dpy); + } + + if (slides) { + for (i = 0; i < slidecount; i++) { + for (j = 0; j < slides[i].linecount; j++) + free(slides[i].lines[j]); + free(slides[i].lines); + if (slides[i].img) + fffree(slides[i].img); + } + if (!slidesonly) { + free(slides); + slides = NULL; + } + } } -void reload(const Arg *arg) +void +reload(const Arg *arg) { - FILE *fp = NULL; - unsigned int i; - - if (!fname) { - fprintf(stderr, "sent: Cannot reload from stdin. Use a file!\n"); - return; - } - - cleanup(1); - slidecount = 0; - - if (!(fp = fopen(fname, "r"))) - die("sent: Unable to open '%s' for reading:", fname); - load(fp); - fclose(fp); - - LIMIT(idx, 0, slidecount-1); - for (i = 0; i < slidecount; i++) - ffload(&slides[i]); - xdraw(); + FILE *fp = NULL; + unsigned int i; + + if (!fname) { + fprintf(stderr, "sent: Cannot reload from stdin. Use a file!\n"); + return; + } + + cleanup(1); + slidecount = 0; + + if (!(fp = fopen(fname, "r"))) + die("sent: Unable to open '%s' for reading:", fname); + load(fp); + fclose(fp); + + LIMIT(idx, 0, slidecount-1); + for (