diff --git a/configure.ac b/configure.ac index 845d563..fe33ace 100644 --- a/configure.ac +++ b/configure.ac @@ -59,11 +59,19 @@ AC_TRY_COMPILE([#include ],[Sleep(42);], [AC_MSG_RESULT(yes) AC_DEFINE(HAVE_SLEEP, 1, [Define to 1 if you have the `Sleep' function.])], [AC_MSG_RESULT(no)]) + AC_MSG_CHECKING(for fsin/fcos) AC_TRY_COMPILE([],[asm("fsin\n\tfcos");], [AC_MSG_RESULT(yes) AC_DEFINE(HAVE_FSIN_FCOS, 1, [Define to 1 if you have the `fsin' and `fcos' operands.])], [AC_MSG_RESULT(no)]) + +AC_MSG_CHECKING(for fldln2/fxch/fyl2x) +AC_TRY_COMPILE([],[asm("fldln2; fldln2; fxch; fyl2x");], + [AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_FLDLN2, 1, [Define to 1 if you have the `fldln2' and other floating points operands.])], + [AC_MSG_RESULT(no)]) + AC_CHECK_LIB(m, sin, MATH_LIBS="${MATH_LIBS} -lm") CACA_DRIVERS="" diff --git a/cucul/bitmap.c b/cucul/bitmap.c index 7dd679a..548239e 100644 --- a/cucul/bitmap.c +++ b/cucul/bitmap.c @@ -32,6 +32,8 @@ #include "cucul.h" #include "cucul_internals.h" +#define CP437 0 + /* * Local variables */ @@ -57,7 +59,7 @@ static int const hsv_palette[] = }; /* RGB palette for the new colour picker */ -static int rgb_palette[] = +static int const rgb_palette[] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x7ff, @@ -77,7 +79,7 @@ static int rgb_palette[] = 0xfff, 0xfff, 0xfff, }; -static int rgb_weight[] = +static int const rgb_weight[] = { //2, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 @@ -106,6 +108,7 @@ static int rgb_weight[] = * Local prototypes */ static void mask2shift(unsigned int, int *, int *); +static float gammapow(float x, float y); static void get_rgba_default(struct cucul_bitmap const *, uint8_t *, int, int, unsigned int *, unsigned int *, unsigned int *, @@ -174,6 +177,63 @@ static void mask2shift(unsigned int mask, int *right, int *left) *left = 12 - lshift; } +static float gammapow(float x, float y) +{ +#ifdef HAVE_FLDLN2 + register double logx; + register long double v, e; +#else + register float tmp, t, r; + int i; +#endif + + if(x == 0.0) + return y == 0.0 ? 1.0 : 0.0; + +#ifdef HAVE_FLDLN2 + /* FIXME: this can be optimised by directly calling fyl2x for x and y */ + asm volatile("fldln2; fxch; fyl2x" + : "=t" (logx) : "0" (x) : "st(1)"); + + asm volatile("fldl2e\n\t" + "fmul %%st(1)\n\t" + "fst %%st(1)\n\t" + "frndint\n\t" + "fxch\n\t" + "fsub %%st(1)\n\t" + "f2xm1\n\t" + : "=t" (v), "=u" (e) : "0" (y * logx)); + v += 1.0; + asm volatile("fscale" + : "=t" (v) : "0" (v), "u" (e)); + return v; +#else + /* Compute ln(x) as ln(1+t) where t = x - 1, x ∈ ]0,1[ + * ln(1+t) = t - t^2/2 + t^3/3 - t^4/4 + t^5/5 ... + * The convergence is quite slow, especially when x is near 0. */ + tmp = t = r = x - 1.0; + for(i = 2; i < 30; i++) + { + r *= -t; + tmp += r / i; + } + + /* Compute x^-y as e^t where t = y*ln(x): + * e^t = 1 + t/1! + t^2/2! + t^3/3! + t^4/4! + t^5/5! ... + * The convergence is a lot faster here, thanks to the factorial. */ + r = t = - y * tmp; + tmp = 1.0 + t; + for(i = 2; i < 16; i++) + { + r = r * t / i; + tmp += r; + } + + /* Return x^y as 1/(x^-y) */ + return 1.0 / tmp; +#endif +} + /** * \brief Create an internal bitmap object. * @@ -312,7 +372,7 @@ void cucul_set_bitmap_gamma(struct cucul_bitmap *bitmap, float gamma) bitmap->gamma = gamma; for(i = 0; i < 4096; i++) - bitmap->gammatab[i] = 4096.0 * cucul_powf((float)i / 4096.0, 1.0 / gamma); + bitmap->gammatab[i] = 4096.0 * gammapow((float)i / 4096.0, 1.0 / gamma); } /** @@ -448,21 +508,17 @@ void cucul_draw_bitmap(cucul_t *qq, int x1, int y1, int x2, int y2, /* FIXME: choose better characters! */ #if !defined(_DOXYGEN_SKIP_ME) -# define DCHMAX ((sizeof(density_chars)/sizeof(char const)/4)-1) +# define DCHMAX ((sizeof(density_chars)/sizeof(*density_chars))) #endif - static char const density_chars[] = - " " - "...." - "::::" - ";=;=" - "tftf" - "%$%$" - "SK&Z" - "XWGM" - "@@@@" - "8888" - "####" - "????"; + static char const * density_chars[] = + { +#if CP437 + " ", ":", "░", "▒", "?" + /* "0", "1", "2", "3", "?" */ +#else + " ", ".", ":", ";", "t", "%", "S", "X", "@", "8", "?" +#endif + }; int x, y, w, h, pitch, deltax, deltay; @@ -552,7 +608,7 @@ void cucul_draw_bitmap(cucul_t *qq, int x1, int y1, int x2, int y2, int error[3]; enum cucul_color outfg = 0, outbg = 0; - char outch; + char const *outch; r = g = b = a = 0; @@ -675,7 +731,7 @@ void cucul_draw_bitmap(cucul_t *qq, int x1, int y1, int x2, int y2, distmin = dist; } } - outch = density_chars[4 * ch]; + outch = density_chars[ch]; if(qq->dithering == CUCUL_DITHERING_FSTEIN) { @@ -695,7 +751,7 @@ void cucul_draw_bitmap(cucul_t *qq, int x1, int y1, int x2, int y2, ch = 0; else if(ch > (int)(DCHMAX - 1)) ch = DCHMAX - 1; - outch = density_chars[4 * ch]; + outch = density_chars[ch]; if(qq->dithering == CUCUL_DITHERING_FSTEIN) { @@ -723,7 +779,7 @@ void cucul_draw_bitmap(cucul_t *qq, int x1, int y1, int x2, int y2, /* Now output the character */ cucul_set_color(qq, outfg, outbg); - cucul_putchar(qq, x, y, outch); + cucul_putstr(qq, x, y, outch); _increment_dither(); }