Index: apps/plugins/fractals/fractal_sets.h =================================================================== --- apps/plugins/fractals/fractal_sets.h (revision 24287) +++ apps/plugins/fractals/fractal_sets.h (working copy) @@ -48,7 +48,8 @@ void *button_yield_ctx); void (*move)(int dx, int dy); int (*zoom)(int factor); - int (*precision)(int d); + int (*change_precision)(int d); + void (*change_colors)(int d); }; #endif Index: apps/plugins/fractals/fractal.h =================================================================== --- apps/plugins/fractals/fractal.h (revision 24287) +++ apps/plugins/fractals/fractal.h (working copy) @@ -110,18 +110,24 @@ #define FRACTAL_RESET BUTTON_REC #elif CONFIG_KEYPAD == GIGABEAT_PAD -#define FRACTAL_QUIT BUTTON_POWER -#define FRACTAL_UP BUTTON_UP -#define FRACTAL_DOWN BUTTON_DOWN -#define FRACTAL_LEFT BUTTON_LEFT -#define FRACTAL_RIGHT BUTTON_RIGHT -#define FRACTAL_ZOOM_IN_PRE BUTTON_SELECT -#define FRACTAL_ZOOM_IN (BUTTON_SELECT | BUTTON_REL) -#define FRACTAL_ZOOM_OUT_PRE BUTTON_SELECT -#define FRACTAL_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT) -#define FRACTAL_PRECISION_INC BUTTON_VOL_UP -#define FRACTAL_PRECISION_DEC BUTTON_VOL_DOWN -#define FRACTAL_RESET BUTTON_A +#define FRACTAL_QUIT BUTTON_POWER +#define FRACTAL_UP BUTTON_UP +#define FRACTAL_DOWN BUTTON_DOWN +#define FRACTAL_LEFT BUTTON_LEFT +#define FRACTAL_RIGHT BUTTON_RIGHT +#define FRACTAL_ZOOM_IN_PRE BUTTON_SELECT +#define FRACTAL_ZOOM_IN (BUTTON_SELECT | BUTTON_REL) +#define FRACTAL_ZOOM_OUT_PRE BUTTON_SELECT +#define FRACTAL_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT) +#define FRACTAL_PRECISION_INC_PRE BUTTON_VOL_UP +#define FRACTAL_PRECISION_INC (BUTTON_VOL_UP | BUTTON_REPEAT) +#define FRACTAL_PRECISION_DEC_PRE BUTTON_VOL_DOWN +#define FRACTAL_PRECISION_DEC (BUTTON_VOL_DOWN | BUTTON_REPEAT) +#define FRACTAL_COLORS_INC_PRE BUTTON_VOL_UP +#define FRACTAL_COLORS_INC (BUTTON_VOL_UP | BUTTON_REL) +#define FRACTAL_COLORS_DEC_PRE BUTTON_VOL_DOWN +#define FRACTAL_COLORS_DEC (BUTTON_VOL_DOWN | BUTTON_REL) +#define FRACTAL_RESET BUTTON_A #elif CONFIG_KEYPAD == SANSA_E200_PAD #define FRACTAL_QUIT BUTTON_POWER @@ -255,6 +261,8 @@ #elif CONFIG_KEYPAD == COWON_D2_PAD #define FRACTAL_QUIT BUTTON_POWER +#define FRACTAL_PRECISION_INC BUTTON_PLUS +#define FRACTAL_PRECISION_DEC BUTTON_MINUS #elif CONFIG_KEYPAD == CREATIVEZVM_PAD #define FRACTAL_QUIT BUTTON_BACK @@ -335,11 +343,11 @@ #define FRACTAL_ZOOM_OUT_PRE BUTTON_TOPLEFT #define FRACTAL_ZOOM_OUT (BUTTON_TOPLEFT | BUTTON_REL) #endif -#ifndef FRACTAL_PRECISION_INC -#define FRACTAL_PRECISION_INC BUTTON_BOTTOMRIGHT +#ifndef FRACTAL_COLORS_INC +#define FRACTAL_COLORS_INC BUTTON_BOTTOMRIGHT #endif -#ifndef FRACTAL_PRECISION_DEC -#define FRACTAL_PRECISION_DEC BUTTON_BOTTOMLEFT +#ifndef FRACTAL_COLORS_DEC +#define FRACTAL_COLORS_DEC BUTTON_BOTTOMLEFT #endif #ifndef FRACTAL_RESET #define FRACTAL_RESET BUTTON_CENTER Index: apps/plugins/fractals/mandelbrot_set.c =================================================================== --- apps/plugins/fractals/mandelbrot_set.c (revision 24287) +++ apps/plugins/fractals/mandelbrot_set.c (working copy) @@ -22,29 +22,62 @@ ****************************************************************************/ #include "mandelbrot_set.h" -#define BUTTON_YIELD_TIMEOUT (HZ / 4) +/* + * + * Macros + * + */ +#define BUTTON_YIELD_TIMEOUT (HZ / 4) + +#define NUM_COLORS_USED 345 /* max possible value of max_iter */ +#define NUM_LCD_COLORS ((unsigned)(1 << LCD_DEPTH)) + +#ifdef HAVE_LCD_COLOR +#define CONVERGENCE_COLOR LCD_RGBPACK(0, 0, 0) +#else +#define CONVERGENCE_COLOR 0 +#endif + +#define LCOLOR(c) ((c * NUM_LCD_COLORS) / NUM_COLORS_USED) + #ifdef USEGSLIB -static unsigned char imgbuffer[LCD_HEIGHT]; +#define COLOR(c) (unsigned char)LCOLOR(c) #else -static fb_data imgbuffer[LCD_HEIGHT]; +#define COLOR(c) (fb_data)LCOLOR(c) #endif -#define NUM_COLORS ((unsigned)(1 << LCD_DEPTH)) - /* - * Spread iter's colors over color range. - * 345 (=15*26-45) is max_iter maximal value - * This implementation ignores pixel format, thus it is not uniformly spread + * + * Globals + * */ -#define LCOLOR(iter) ((iter * NUM_COLORS) / 345) +#ifdef USEGSLIB +static unsigned char colors_cache[NUM_COLORS_USED]; +static unsigned char imgbuffer[LCD_HEIGHT]; +#else +static fb_data colors_cache[NUM_COLORS_USED]; +static fb_data imgbuffer[LCD_HEIGHT]; +#endif + #ifdef HAVE_LCD_COLOR -#define COLOR(iter) (fb_data)LCOLOR(iter) -#define CONVERGENCE_COLOR LCD_RGBPACK(0, 0, 0) -#else /* greyscale */ -#define COLOR(iter) (unsigned char)LCOLOR(iter) -#define CONVERGENCE_COLOR 0 +/* array of arbitrary prime numbers */ +static const unsigned color_multipliers[] = { + 1, /* no color change */ + 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819, + 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, + 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, + 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, + 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, + 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, + 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, + 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, + 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, + 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, +}; + +static unsigned color_scheme; /* current index in primes */ #endif #if CONFIG_LCD == LCD_SSD1815 @@ -93,15 +126,22 @@ static int mandelbrot_zoom(int factor); -static int mandelbrot_precision(int d); +static int mandelbrot_change_precision(int d); +static void mandelbrot_change_colors(int d); + struct fractal_ops mandelbrot_ops = { - .init = mandelbrot_init, - .calc = NULL, - .move = mandelbrot_move, - .zoom = mandelbrot_zoom, - .precision = mandelbrot_precision, + .init = mandelbrot_init, + .calc = NULL, + .move = mandelbrot_move, + .zoom = mandelbrot_zoom, + .change_precision = mandelbrot_change_precision, +#ifdef HAVE_LCD_COLOR + .change_colors = mandelbrot_change_colors, +#else + .change_colors = NULL, +#endif }; #define LOG2_OUT_OF_BOUNDS -32767 @@ -153,6 +193,22 @@ return 0; } +static void recalc_colors(void) +{ + int i; + + for (i = 0; i < NUM_COLORS_USED; i++) + { +#ifdef HAVE_LCD_COLOR + /* This implementation ignores pixel format, thus it is not uniformly + * spread. It is merely a naive way to change color */ + colors_cache[i] = COLOR(i * color_multipliers[color_scheme]); +#else + colors_cache[i] = COLOR(i); +#endif + } +} + static void mandelbrot_init(void) { ops = &mandelbrot_ops; @@ -163,6 +219,11 @@ y_max = MB_YFAC; recalc_parameters(); + +#ifdef HAVE_LCD_COLOR + color_scheme = 0; +#endif + recalc_colors(); } static int mandelbrot_calc_low_prec(struct fractal_rect *rect, @@ -208,7 +269,7 @@ if (n_iter > max_iter) imgbuffer[p_y] = CONVERGENCE_COLOR; else - imgbuffer[p_y] = COLOR(n_iter); + imgbuffer[p_y] = colors_cache[n_iter]; /* be nice to other threads: * if at least one tick has passed, yield */ @@ -305,7 +366,7 @@ if (n_iter > max_iter) imgbuffer[p_y] = CONVERGENCE_COLOR; else - imgbuffer[p_y] = COLOR(n_iter); + imgbuffer[p_y] = colors_cache[n_iter]; /* be nice to other threads: * if at least one tick has passed, yield */ @@ -384,14 +445,12 @@ res = recalc_parameters(); if (res) /* zoom not possible, revert */ - { mandelbrot_zoom(-factor); - } return res; } -static int mandelbrot_precision(int d) +static int mandelbrot_change_precision(int d) { int changed = 0; @@ -412,3 +471,15 @@ return changed; } +#ifdef HAVE_LCD_COLOR +static void mandelbrot_change_colors(int d) +{ + unsigned num_color_multipliers = ARRAYLEN(color_multipliers); + + color_scheme = (unsigned)(color_scheme + d + num_color_multipliers) % + num_color_multipliers; + + recalc_colors(); +} +#endif + Index: apps/plugins/fractals/fractal.c =================================================================== --- apps/plugins/fractals/fractal.c (revision 24287) +++ apps/plugins/fractals/fractal.c (working copy) @@ -70,6 +70,8 @@ case FRACTAL_ZOOM_OUT: case FRACTAL_PRECISION_INC: case FRACTAL_PRECISION_DEC: + case FRACTAL_COLORS_INC: + case FRACTAL_COLORS_DEC: case FRACTAL_RESET: #ifdef FRACTAL_ZOOM_IN2 case FRACTAL_ZOOM_IN2: @@ -88,6 +90,12 @@ (FRACTAL_PRECISION_DEC_PRE != FRACTAL_PRECISION_INC_PRE) case FRACTAL_PRECISION_DEC_PRE: #endif +#ifdef FRACTAL_COLORS_INC_PRE + case FRACTAL_COLORS_INC_PRE: +#endif +#ifdef FRACTAL_COLORS_DEC_PRE + case FRACTAL_COLORS_DEC_PRE: +#endif return 1; default: *button = BUTTON_NONE; @@ -235,7 +243,7 @@ if (lastbutton != FRACTAL_PRECISION_DEC_PRE) break; #endif - if (ops->precision(-1)) + if (ops->change_precision(-1)) redraw = REDRAW_FULL_OVERLAY; break; @@ -245,11 +253,37 @@ if (lastbutton != FRACTAL_PRECISION_INC_PRE) break; #endif - if (ops->precision(+1)) + if (ops->change_precision(+1)) redraw = REDRAW_FULL_OVERLAY; break; + case FRACTAL_COLORS_INC: +#ifdef FRACTAL_COLORS_INC_PRE + if (lastbutton != FRACTAL_COLORS_INC_PRE) + break; +#endif + if (ops->change_colors) + { + ops->change_colors(+1); + redraw = REDRAW_FULL_OVERLAY; + } + + break; + + case FRACTAL_COLORS_DEC: +#ifdef FRACTAL_COLORS_DEC_PRE + if (lastbutton != FRACTAL_COLORS_DEC_PRE) + break; +#endif + if (ops->change_colors) + { + ops->change_colors(-1); + redraw = REDRAW_FULL_OVERLAY; + } + + break; + case FRACTAL_RESET: ops->init(); redraw = REDRAW_FULL; Index: manual/plugins/fractals.tex =================================================================== --- manual/plugins/fractals.tex (revision 24287) +++ manual/plugins/fractals.tex (working copy) @@ -6,57 +6,90 @@ \begin{btnmap}{}{} Direction keys \opt{HAVEREMOTEKEYMAP}{&} - & Move about the image\\ + & Move about the image + \\ + % \opt{RECORDER_PAD,IRIVER_H10_PAD}{\ButtonPlay} \opt{ONDIO_PAD}{\ButtonMenu\ / \ButtonMenu+\ButtonUp} - \opt{IRIVER_H100_PAD,IRIVER_H300_PAD,IAUDIO_X5_PAD,GIGABEAT_PAD,MROBE100_PAD}{\ButtonSelect} + \opt{IRIVER_H100_PAD,IRIVER_H300_PAD,IAUDIO_X5_PAD,GIGABEAT_PAD,MROBE100_PAD} + {\ButtonSelect} \opt{IPOD_4G_PAD,IPOD_3G_PAD,SANSA_E200_PAD,SANSA_FUZE_PAD}{\ButtonScrollFwd} \opt{SANSA_C200_PAD,GIGABEAT_S_PAD}{\ButtonVolUp} \opt{COWON_D2_PAD}{\TouchTopRight} \opt{HAVEREMOTEKEYMAP}{& } - & Zoom in\\ + & Zoom in + \\ + % \opt{RECORDER_PAD}{\ButtonOn} \opt{ONDIO_PAD}{\ButtonMenu+\ButtonDown} \opt{IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonMode} - \opt{IPOD_4G_PAD,IPOD_3G_PAD,SANSA_E200_PAD,SANSA_FUZE_PAD}{\ButtonScrollBack} + \opt{IPOD_4G_PAD,IPOD_3G_PAD,SANSA_E200_PAD,SANSA_FUZE_PAD} + {\ButtonScrollBack} \opt{IAUDIO_X5_PAD,GIGABEAT_PAD,MROBE100_PAD}{Long \ButtonSelect} \opt{IRIVER_H10_PAD}{Long \ButtonPlay} \opt{SANSA_C200_PAD,GIGABEAT_S_PAD}{\ButtonVolDown} \opt{COWON_D2_PAD}{\TouchTopLeft} \opt{HAVEREMOTEKEYMAP}{& } - & Zoom out\\ + & Zoom out + \nopt{GIGABEAT_S_PAD}{ + \\ + % - \opt{RECORDER_PAD}{\ButtonFOne} - \opt{ONDIO_PAD}{\ButtonMenu+\ButtonLeft} - \opt{IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonOn+\ButtonLeft} - \opt{IPOD_4G_PAD,IPOD_3G_PAD,SANSA_E200_PAD,SANSA_FUZE_PAD,SANSA_C200_PAD}{\ButtonSelect+\ButtonLeft} - \opt{IAUDIO_X5_PAD}{Long \ButtonPlay} - \opt{IRIVER_H10_PAD}{\ButtonRew} + \opt{GIGABEAT_PAD}{\ButtonVolUp} + \opt{COWON_D2_PAD}{\TouchBottomRight} + \opt{HAVEREMOTEKEYMAP}{& } + & Switch to next color scheme + \\ + + % \opt{GIGABEAT_PAD}{\ButtonVolDown} - \opt{GIGABEAT_S_PAD}{\ButtonNext} - \opt{MROBE100_PAD}{\ButtonPlay} \opt{COWON_D2_PAD}{\TouchBottomLeft} \opt{HAVEREMOTEKEYMAP}{& } - & Decrease iteration depth (less detail)\\ + & Switch to previous color scheme + } + \nopt{}{ + \\ + % \opt{RECORDER_PAD}{\ButtonFTwo} \opt{ONDIO_PAD}{\ButtonMenu+\ButtonRight} \opt{IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonOn+\ButtonRight} - \opt{IPOD_4G_PAD,IPOD_3G_PAD,SANSA_E200_PAD,SANSA_FUZE_PAD,SANSA_C200_PAD}{\ButtonSelect+\ButtonRight} + \opt{IPOD_4G_PAD,IPOD_3G_PAD,SANSA_E200_PAD,SANSA_FUZE_PAD,SANSA_C200_PAD} + {\ButtonSelect{}+\ButtonRight} \opt{IAUDIO_X5_PAD}{\ButtonPlay} \opt{IRIVER_H10_PAD}{\ButtonFF} - \opt{GIGABEAT_PAD}{\ButtonVolUp} + \opt{GIGABEAT_PAD}{Long \ButtonVolUp} \opt{GIGABEAT_S_PAD}{\ButtonPrev} \opt{MROBE100_PAD}{\ButtonMenu} - \opt{COWON_D2_PAD}{\TouchBottomRight} + \opt{COWON_D2_PAD}{\ButtonPlus} \opt{HAVEREMOTEKEYMAP}{& } - & Increase iteration depth (more detail)\\ + & Increase iteration depth (more detail) + \\ + % + \opt{RECORDER_PAD}{\ButtonFOne} + \opt{ONDIO_PAD}{\ButtonMenu+\ButtonLeft} + \opt{IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonOn+\ButtonLeft} + \opt{IPOD_4G_PAD,IPOD_3G_PAD,SANSA_E200_PAD,SANSA_FUZE_PAD,SANSA_C200_PAD} + {\ButtonSelect{}+\ButtonLeft} + \opt{IAUDIO_X5_PAD}{Long \ButtonPlay} + \opt{IRIVER_H10_PAD}{\ButtonRew} + \opt{GIGABEAT_PAD}{Long \ButtonVolDown} + \opt{GIGABEAT_S_PAD}{\ButtonNext} + \opt{MROBE100_PAD}{\ButtonPlay} + \opt{COWON_D2_PAD}{\ButtonMinus} + \opt{HAVEREMOTEKEYMAP}{& } + & Decrease iteration depth (less detail) + } + \\ + + % \opt{RECORDER_PAD}{\ButtonFThree} \opt{ONDIO_PAD}{\ButtonMenu+\ButtonOff} - \opt{IRIVER_H100_PAD,IRIVER_H300_PAD,IAUDIO_X5_PAD,SANSA_E200_PAD,SANSA_C200_PAD}{\ButtonRec} + \opt{IRIVER_H100_PAD,IRIVER_H300_PAD,IAUDIO_X5_PAD,SANSA_E200_PAD,% + SANSA_C200_PAD}{\ButtonRec} \opt{SANSA_FUZE_PAD}{Long \ButtonSelect} \opt{IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonSelect+\ButtonPlay} \opt{IRIVER_H10_PAD}{\ButtonPlay + \ButtonRew} @@ -65,7 +98,9 @@ \opt{MROBE100_PAD}{\ButtonDisplay} \opt{COWON_D2_PAD}{\TouchCenter} \opt{HAVEREMOTEKEYMAP}{& } - & Reset and return to the default image\\ + & Reset and return to the default image + \\ + % \opt{RECORDER_PAD,ONDIO_PAD,IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonOff} \opt{IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonSelect+\ButtonMenu} @@ -76,6 +111,7 @@ \opt{HAVEREMOTEKEYMAP}{& \opt{IRIVER_RC_H100_PAD}{\ButtonRCStop} } - & Quit\\ + & Quit + \\ \end{btnmap} \end{table}