Color picker now offers full HSV selection
Added a slider to choose value, which re-renders the rainbow-colored box on the left (which now only displays hue/saturation).
This commit is contained in:
parent
128f73f731
commit
0c858122b5
3 changed files with 247 additions and 64 deletions
BIN
data/images/ui/color_picker_val.png
Normal file
BIN
data/images/ui/color_picker_val.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
|
|
@ -7,7 +7,7 @@ Various contributors (see below, and AUTHORS.txt)
|
|||
http://www.tuxpaint.org/
|
||||
|
||||
|
||||
2022.February.27 (0.9.28)
|
||||
2022.March.2 (0.9.28)
|
||||
* Improvements to "Paint" and "Lines" tools:
|
||||
------------------------------------------
|
||||
* Brush spacing may now be altered within Tux Paint.
|
||||
|
|
@ -106,6 +106,10 @@ http://www.tuxpaint.org/
|
|||
form a desired color. Undo/Redo is available!
|
||||
Bill Kendrick <bill@newbreedsoftware.com>
|
||||
|
||||
* The rainbow palette color picker now acts as a true
|
||||
Hue/Saturation/Value picker, with the addition of a "value" slider.
|
||||
Bill Kendrick <bill@newbreedsoftware.com>
|
||||
|
||||
* Show a "pipette"-shaped mouse pointer when selecting a
|
||||
color from the color palette, or the picture.
|
||||
Bill Kendrick <bill@newbreedsoftware.com>
|
||||
|
|
|
|||
305
src/tuxpaint.c
305
src/tuxpaint.c
|
|
@ -22,7 +22,7 @@
|
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
(See COPYING.txt)
|
||||
|
||||
June 14, 2002 - February 23, 2022
|
||||
June 14, 2002 - March 2, 2022
|
||||
*/
|
||||
|
||||
#include "platform.h"
|
||||
|
|
@ -1523,8 +1523,9 @@ static SDL_Surface *img_magic_paint, *img_magic_fullscreen;
|
|||
static SDL_Surface *img_shapes_corner, *img_shapes_center;
|
||||
static SDL_Surface *img_bold, *img_italic;
|
||||
static SDL_Surface *img_label_select, *img_label_apply;
|
||||
static SDL_Surface *img_color_picker, *img_color_picker_thumb, *img_paintwell, *img_color_sel, *img_color_mix;
|
||||
static int color_picker_x, color_picker_y;
|
||||
static SDL_Surface *img_color_picker, *img_color_picker_thumb, *img_color_picker_val;
|
||||
static SDL_Surface *img_paintwell, *img_color_sel, *img_color_mix;
|
||||
static int color_picker_x, color_picker_y, color_picker_v;
|
||||
static int color_mixer_reset;
|
||||
|
||||
static SDL_Surface *img_title_on, *img_title_off, *img_title_large_on, *img_title_large_off;
|
||||
|
|
@ -2093,6 +2094,9 @@ static int do_new_dialog(void);
|
|||
static int do_new_dialog_add_colors(SDL_Surface * *thumbs, int num_files, int *d_places, char * *d_names,
|
||||
char * *d_exts, int *white_in_palette);
|
||||
static int do_color_picker(void);
|
||||
static void draw_color_picker_crosshairs(int color_picker_left, int color_picker_top, int color_picker_val_left, int color_picker_val_top);
|
||||
static void draw_color_picker_values(int l, int t);
|
||||
static void render_color_picker_palette(void);
|
||||
static int do_color_sel(int temp_mode);
|
||||
static int do_color_mix(void);
|
||||
static void draw_color_mixer_blank_example(void);
|
||||
|
|
@ -21886,7 +21890,8 @@ static int do_color_picker(void)
|
|||
SDL_Event event;
|
||||
SDLKey key;
|
||||
int color_picker_left, color_picker_top;
|
||||
int back_left, back_top;
|
||||
int color_picker_val_left, color_picker_val_top;
|
||||
int back_left, back_top, done_left, done_top;
|
||||
SDL_Rect color_example_dest;
|
||||
SDL_Surface *backup;
|
||||
SDL_Rect r_color_picker;
|
||||
|
|
@ -21895,7 +21900,9 @@ static int do_color_picker(void)
|
|||
valhat_x = valhat_y = hatmotioner = 0;
|
||||
hide_blinking_cursor();
|
||||
|
||||
|
||||
do_setcursor(cursor_hand);
|
||||
getpixel_img_color_picker = getpixels[img_color_picker->format->BytesPerPixel];
|
||||
|
||||
|
||||
/* Draw button box: */
|
||||
|
|
@ -21975,6 +21982,8 @@ static int do_color_picker(void)
|
|||
|
||||
/* Draw color palette: */
|
||||
|
||||
render_color_picker_palette();
|
||||
|
||||
color_picker_left = r_final.x;
|
||||
color_picker_top = r_final.y;
|
||||
|
||||
|
|
@ -21989,42 +21998,25 @@ static int do_color_picker(void)
|
|||
r_color_picker.h = dest.h;
|
||||
|
||||
|
||||
/* Draw last color position: */
|
||||
/* Draw values: */
|
||||
|
||||
dest.x = color_picker_x + color_picker_left - 3;
|
||||
dest.y = color_picker_y + color_picker_top - 1;
|
||||
dest.w = 7;
|
||||
dest.h = 3;
|
||||
color_picker_val_left = color_picker_left + img_color_picker->w + 2;
|
||||
color_picker_val_top = color_picker_top;
|
||||
|
||||
SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format, 0, 0, 0));
|
||||
draw_color_picker_values(color_picker_val_left, color_picker_val_top);
|
||||
|
||||
dest.x = color_picker_x + color_picker_left - 1;
|
||||
dest.y = color_picker_y + color_picker_top - 3;
|
||||
dest.w = 3;
|
||||
dest.h = 7;
|
||||
|
||||
SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format, 0, 0, 0));
|
||||
/* Draw crosshairs */
|
||||
|
||||
dest.x = color_picker_x + color_picker_left - 2;
|
||||
dest.y = color_picker_y + color_picker_top;
|
||||
dest.w = 5;
|
||||
dest.h = 1;
|
||||
draw_color_picker_crosshairs(color_picker_left, color_picker_top, color_picker_val_left, color_picker_val_top);
|
||||
|
||||
SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format, 255, 255, 255));
|
||||
|
||||
dest.x = color_picker_x + color_picker_left;
|
||||
dest.y = color_picker_y + color_picker_top - 2;
|
||||
dest.w = 1;
|
||||
dest.h = 5;
|
||||
|
||||
SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format, 255, 255, 255));
|
||||
|
||||
|
||||
/* Determine spot for example color: */
|
||||
|
||||
color_example_dest.x = color_picker_left + img_color_picker->w + 2;
|
||||
color_example_dest.x = color_picker_left + img_color_picker->w + 2 + img_back->w + 2;
|
||||
color_example_dest.y = color_picker_top + 2;
|
||||
color_example_dest.w = r_final.w / 2 - 2;
|
||||
color_example_dest.w = r_final.w / 2 - 2 - img_back->w - 2;
|
||||
color_example_dest.h = r_final.h / 2 - 4;
|
||||
|
||||
|
||||
|
|
@ -22055,8 +22047,7 @@ static int do_color_picker(void)
|
|||
|
||||
/* Show "Back" button */
|
||||
|
||||
back_left =
|
||||
(((PROMPT_W - 96 * 2) + w * 2 - img_color_picker->w) - img_back->w) / 2 + color_picker_left + img_color_picker->w;
|
||||
back_left = r_final.x + r_final.w - img_back->w - 2;
|
||||
back_top = color_picker_top + img_color_picker->h - img_back->h - 2;
|
||||
|
||||
dest.x = back_left;
|
||||
|
|
@ -22069,6 +22060,15 @@ static int do_color_picker(void)
|
|||
SDL_BlitSurface(img_openlabels_back, NULL, screen, &dest);
|
||||
|
||||
|
||||
/* Show "Done" button */
|
||||
done_left = back_left - img_yes->w - 2;
|
||||
done_top = back_top;
|
||||
|
||||
dest.x = done_left;
|
||||
dest.y = done_top;
|
||||
|
||||
SDL_BlitSurface(img_yes, NULL, screen, &dest);
|
||||
|
||||
SDL_Flip(screen);
|
||||
|
||||
|
||||
|
|
@ -22114,18 +22114,87 @@ static int do_color_picker(void)
|
|||
{
|
||||
if (event.button.x >= color_picker_left &&
|
||||
event.button.x < color_picker_left + img_color_picker->w &&
|
||||
event.button.y >= color_picker_top && event.button.y < color_picker_top + img_color_picker->h)
|
||||
event.button.y >= color_picker_top &&
|
||||
event.button.y < color_picker_top + img_color_picker->h)
|
||||
{
|
||||
/* Picked a color! */
|
||||
|
||||
chose = 1;
|
||||
done = 1;
|
||||
|
||||
x = event.button.x - color_picker_left;
|
||||
y = event.button.y - color_picker_top;
|
||||
|
||||
color_picker_x = x;
|
||||
color_picker_y = y;
|
||||
|
||||
/* Update (entire) color box */
|
||||
SDL_GetRGB(getpixel_img_color_picker(img_color_picker, x, y), img_color_picker->format, &r, &g, &b);
|
||||
|
||||
SDL_FillRect(screen, &color_example_dest, SDL_MapRGB(screen->format, r, g, b));
|
||||
|
||||
SDL_UpdateRect(screen,
|
||||
color_example_dest.x, color_example_dest.y,
|
||||
color_example_dest.w, color_example_dest.h);
|
||||
|
||||
|
||||
/* Reposition hue/sat crosshair */
|
||||
dest.x = color_picker_left;
|
||||
dest.y = color_picker_top;
|
||||
SDL_BlitSurface(img_color_picker, NULL, screen, &dest);
|
||||
draw_color_picker_crosshairs(color_picker_left, color_picker_top, color_picker_val_left, color_picker_val_top);
|
||||
SDL_UpdateRect(screen, dest.x, dest.y, dest.w, dest.h);
|
||||
}
|
||||
else if (event.button.x >= color_picker_val_left &&
|
||||
event.button.y >= color_picker_val_top &&
|
||||
event.button.x <= color_picker_val_left + img_back->w &&
|
||||
event.button.y <= color_picker_val_top + img_color_picker_val->h)
|
||||
{
|
||||
/* Picked a value from the slider */
|
||||
|
||||
y = event.button.y - color_picker_val_top;
|
||||
color_picker_v = y;
|
||||
|
||||
/* Re-render the palette with the new value */
|
||||
render_color_picker_palette();
|
||||
|
||||
/* Update (entire) color box */
|
||||
SDL_GetRGB(getpixel_img_color_picker(img_color_picker, color_picker_x, color_picker_y), img_color_picker->format, &r, &g, &b);
|
||||
|
||||
SDL_FillRect(screen, &color_example_dest, SDL_MapRGB(screen->format, r, g, b));
|
||||
|
||||
SDL_UpdateRect(screen,
|
||||
color_example_dest.x, color_example_dest.y,
|
||||
color_example_dest.w, color_example_dest.h);
|
||||
|
||||
|
||||
/* Redraw hue/sat palette, and val slider, and redraw crosshairs */
|
||||
draw_color_picker_values(color_picker_val_left, color_picker_val_top);
|
||||
|
||||
dest.x = color_picker_left;
|
||||
dest.y = color_picker_top;
|
||||
SDL_BlitSurface(img_color_picker, NULL, screen, &dest);
|
||||
SDL_UpdateRect(screen, dest.x, dest.y, dest.w, dest.h);
|
||||
|
||||
draw_color_picker_crosshairs(color_picker_left, color_picker_top, color_picker_val_left, color_picker_val_top);
|
||||
|
||||
dest.x = color_picker_val_left;
|
||||
dest.y = color_picker_val_top;
|
||||
dest.w = img_back->w;
|
||||
dest.h = img_color_picker_val->h;
|
||||
SDL_UpdateRect(screen, dest.x, dest.y, dest.w, dest.h);
|
||||
|
||||
dest.x = color_picker_left;
|
||||
dest.y = color_picker_top;
|
||||
dest.w = img_color_picker->w;
|
||||
dest.h = img_color_picker->h;
|
||||
SDL_UpdateRect(screen, dest.x, dest.y, dest.w, dest.h);
|
||||
}
|
||||
else if (event.button.x >= done_left &&
|
||||
event.button.x < done_left + img_yes->w &&
|
||||
event.button.y >= done_top && event.button.y < done_top + img_yes->h)
|
||||
{
|
||||
/* Accepting color */
|
||||
|
||||
chose = 1;
|
||||
done = 1;
|
||||
}
|
||||
else if (event.button.x >= back_left &&
|
||||
event.button.x < back_left + img_back->w &&
|
||||
|
|
@ -22153,37 +22222,40 @@ static int do_color_picker(void)
|
|||
x = event.button.x - color_picker_left;
|
||||
y = event.button.y - color_picker_top;
|
||||
|
||||
getpixel_img_color_picker = getpixels[img_color_picker->format->BytesPerPixel];
|
||||
SDL_GetRGB(getpixel_img_color_picker(img_color_picker, x, y), img_color_picker->format, &r, &g, &b);
|
||||
|
||||
dest.x = color_example_dest.x + color_example_dest.w / 4;
|
||||
dest.y = color_example_dest.y + color_example_dest.h / 4;
|
||||
dest.w = color_example_dest.w / 2;
|
||||
dest.h = color_example_dest.h / 2;
|
||||
|
||||
SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format, r, g, b));
|
||||
|
||||
SDL_UpdateRect(screen, dest.x, dest.y, dest.w, dest.h);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Revert to current color picker color */
|
||||
|
||||
SDL_GetRGB(getpixel_img_color_picker(img_color_picker, color_picker_x, color_picker_y),
|
||||
img_color_picker->format, &r, &g, &b);
|
||||
|
||||
SDL_FillRect(screen, &color_example_dest, SDL_MapRGB(screen->format, r, g, b));
|
||||
|
||||
SDL_UpdateRect(screen,
|
||||
color_example_dest.x,
|
||||
color_example_dest.y, color_example_dest.w, color_example_dest.h);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Revert to current color picker color, so we know what it was,
|
||||
and what we'll get if we go Back: */
|
||||
color_example_dest.x, color_example_dest.y,
|
||||
color_example_dest.w, color_example_dest.h);
|
||||
|
||||
SDL_FillRect(screen, &color_example_dest,
|
||||
SDL_MapRGB(screen->format,
|
||||
color_hexes[COLOR_PICKER][0],
|
||||
color_hexes[COLOR_PICKER][1],
|
||||
color_hexes[COLOR_PICKER][2]));
|
||||
|
||||
SDL_UpdateRect(screen,
|
||||
color_example_dest.x,
|
||||
color_example_dest.y, color_example_dest.w, color_example_dest.h);
|
||||
|
||||
|
||||
/* Change cursor to arrow (or hand, if over Back): */
|
||||
/* Change cursor to arrow (or hand, if over Back or Done): */
|
||||
|
||||
if (event.button.x >= back_left &&
|
||||
event.button.x < back_left + img_back->w &&
|
||||
event.button.y >= back_top && event.button.y < back_top + img_back->h)
|
||||
do_setcursor(cursor_hand);
|
||||
else if (event.button.x >= done_left &&
|
||||
event.button.x < done_left + img_yes->w &&
|
||||
event.button.y >= done_top && event.button.y < done_top + img_yes->h)
|
||||
do_setcursor(cursor_hand);
|
||||
else
|
||||
do_setcursor(cursor_arrow);
|
||||
}
|
||||
|
|
@ -22216,8 +22288,7 @@ static int do_color_picker(void)
|
|||
|
||||
if (chose)
|
||||
{
|
||||
getpixel_img_color_picker = getpixels[img_color_picker->format->BytesPerPixel];
|
||||
SDL_GetRGB(getpixel_img_color_picker(img_color_picker, x, y), img_color_picker->format, &r, &g, &b);
|
||||
SDL_GetRGB(getpixel_img_color_picker(img_color_picker, color_picker_x, color_picker_y), img_color_picker->format, &r, &g, &b);
|
||||
|
||||
color_hexes[COLOR_PICKER][0] = r;
|
||||
color_hexes[COLOR_PICKER][1] = g;
|
||||
|
|
@ -22238,6 +22309,112 @@ static int do_color_picker(void)
|
|||
}
|
||||
|
||||
|
||||
static void render_color_picker_palette(void)
|
||||
{
|
||||
int x, y;
|
||||
Uint8 r, g, b;
|
||||
void (*putpixel) (SDL_Surface *, int, int, Uint32);
|
||||
|
||||
putpixel = putpixels[img_color_picker->format->BytesPerPixel];
|
||||
for (y = 0; y < img_color_picker->h; y++)
|
||||
{
|
||||
for (x = 0; x < img_color_picker->w; x++)
|
||||
{
|
||||
hsvtorgb((((float) y * 360.0) / ((float) img_color_picker->h)),
|
||||
((float) x / ((float) img_color_picker->w)),
|
||||
1.0 - (((float) color_picker_v) / ((float) img_color_picker_val->h)),
|
||||
&r, &g, &b);
|
||||
putpixel(img_color_picker, x, y,
|
||||
SDL_MapRGBA(img_color_picker->format, r, g, b, 255));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void draw_color_picker_crosshairs(int color_picker_left, int color_picker_top, int color_picker_val_left, int color_picker_val_top)
|
||||
{
|
||||
SDL_Rect dest;
|
||||
int ctr_x;
|
||||
|
||||
/* Hue/Saturation (the big rectangle) */
|
||||
|
||||
dest.x = color_picker_x + color_picker_left - 3;
|
||||
dest.y = color_picker_y + color_picker_top - 1;
|
||||
dest.w = 7;
|
||||
dest.h = 3;
|
||||
|
||||
SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format, 0, 0, 0));
|
||||
|
||||
dest.x = color_picker_x + color_picker_left - 1;
|
||||
dest.y = color_picker_y + color_picker_top - 3;
|
||||
dest.w = 3;
|
||||
dest.h = 7;
|
||||
|
||||
SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format, 0, 0, 0));
|
||||
|
||||
dest.x = color_picker_x + color_picker_left - 2;
|
||||
dest.y = color_picker_y + color_picker_top;
|
||||
dest.w = 5;
|
||||
dest.h = 1;
|
||||
|
||||
SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format, 255, 255, 255));
|
||||
|
||||
dest.x = color_picker_x + color_picker_left;
|
||||
dest.y = color_picker_y + color_picker_top - 2;
|
||||
dest.w = 1;
|
||||
dest.h = 5;
|
||||
|
||||
SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format, 255, 255, 255));
|
||||
|
||||
|
||||
/* Value (the slider) */
|
||||
|
||||
ctr_x = color_picker_val_left + img_back->w / 2;
|
||||
|
||||
dest.x = ctr_x - 3;
|
||||
dest.y = color_picker_v + color_picker_val_top - 1;
|
||||
dest.w = 7;
|
||||
dest.h = 3;
|
||||
|
||||
SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format, 0, 0, 0));
|
||||
|
||||
dest.x = ctr_x - 1;
|
||||
dest.y = color_picker_v + color_picker_val_top - 3;
|
||||
dest.w = 3;
|
||||
dest.h = 7;
|
||||
|
||||
SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format, 0, 0, 0));
|
||||
|
||||
dest.x = ctr_x - 2;
|
||||
dest.y = color_picker_v + color_picker_val_top;
|
||||
dest.w = 5;
|
||||
dest.h = 1;
|
||||
|
||||
SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format, 255, 255, 255));
|
||||
|
||||
dest.x = ctr_x;
|
||||
dest.y = color_picker_v + color_picker_val_top - 2;
|
||||
dest.w = 1;
|
||||
dest.h = 5;
|
||||
|
||||
SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format, 255, 255, 255));
|
||||
}
|
||||
|
||||
|
||||
static void draw_color_picker_values(int l, int t)
|
||||
{
|
||||
SDL_Rect dest;
|
||||
|
||||
dest.x = l;
|
||||
dest.y = t;
|
||||
dest.w = img_color_picker_val->w;
|
||||
dest.h = img_color_picker_val->h;
|
||||
|
||||
SDL_BlitSurface(img_color_picker_val, NULL, screen, &dest);
|
||||
SDL_UpdateRect(screen, dest.x, dest.y, dest.w, dest.h);
|
||||
}
|
||||
|
||||
|
||||
enum {
|
||||
COLOR_MIXER_BTN_RED,
|
||||
COLOR_MIXER_BTN_YELLOW,
|
||||
|
|
@ -25954,13 +26131,14 @@ static void setup_colors(void)
|
|||
|
||||
/* Add "Color Picker" color: */
|
||||
|
||||
color_names[NUM_COLORS] = strdup(gettext("Pick a color."));
|
||||
color_names[NUM_COLORS] = strdup(gettext("Pick a color. The square shows all hues at varying levels of saturation. Use the slider to change the value."));
|
||||
color_hexes[NUM_COLORS] = (Uint8 *) malloc(sizeof(Uint8) * 3);
|
||||
color_hexes[NUM_COLORS][0] = 0;
|
||||
color_hexes[NUM_COLORS][1] = 0;
|
||||
color_hexes[NUM_COLORS][2] = 0;
|
||||
color_picker_x = 0;
|
||||
color_picker_y = 0;
|
||||
color_hexes[NUM_COLORS][0] = 255;
|
||||
color_hexes[NUM_COLORS][1] = 255;
|
||||
color_hexes[NUM_COLORS][2] = 255;
|
||||
color_picker_x = 0; /* Saturation */
|
||||
color_picker_y = 0; /* Hue */
|
||||
color_picker_v = 0; /* Value */
|
||||
NUM_COLORS++;
|
||||
|
||||
/* Add "Color Mixer" color: */
|
||||
|
|
@ -26926,6 +27104,7 @@ static void setup(void)
|
|||
show_progress_bar(screen);
|
||||
|
||||
img_color_picker = loadimagerb(DATA_PREFIX "images/ui/color_picker.png");
|
||||
img_color_picker_val = loadimagerb(DATA_PREFIX "images/ui/color_picker_val.png");
|
||||
|
||||
/* Create toolbox and selector labels: */
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue