Linear gradient fill mode
This commit is contained in:
parent
0dfe96f291
commit
76cb1c5446
4 changed files with 81 additions and 16 deletions
|
|
@ -8,7 +8,7 @@ http://www.tuxpaint.org/
|
|||
|
||||
$Id$
|
||||
|
||||
2021.February.21 (0.9.26)
|
||||
2021.February.20 (0.9.26)
|
||||
* New Features
|
||||
------------
|
||||
* Larger UI buttons
|
||||
|
|
@ -20,10 +20,10 @@ $Id$
|
|||
Pere Pujal i Carabantes <pere@fornol.no-ip.org>
|
||||
|
||||
* Adding sub-tools to the Fill tool:
|
||||
+ Solid -- the classic fill tool, click to fill
|
||||
+ [WIP] Linear -- A linear gradient, click and drag to adjust,
|
||||
+ Solid -- The classic fill tool; click to fill
|
||||
+ Linear -- A linear gradient; click and drag to adjust,
|
||||
release mouse to finish
|
||||
+ Radial -- A radial gradient, click to fill
|
||||
+ Radial -- A radial gradient; click to fill
|
||||
(The gradients transition from the current color to the
|
||||
background that's being filled.)
|
||||
|
||||
|
|
|
|||
44
src/fill.c
44
src/fill.c
|
|
@ -188,16 +188,54 @@ void simulate_flood_fill(SDL_Surface * canvas, int x, int y, Uint32 cur_colr, Ui
|
|||
}
|
||||
|
||||
|
||||
void draw_linear_gradient(SDL_Surface * canvas, int x_left, int y_top, int x_right, int y_bottom,
|
||||
void draw_linear_gradient(SDL_Surface * canvas, SDL_Surface * last,
|
||||
int x_left, int y_top, int x_right, int y_bottom,
|
||||
int x1, int y1, int x2, int y2, Uint32 draw_color, Uint8 * touched
|
||||
) {
|
||||
Uint32 old_colr, new_colr;
|
||||
int xx, yy;
|
||||
float xd, yd;
|
||||
Uint8 draw_r, draw_g, draw_b, old_r, old_g, old_b, new_r, new_g, new_b;
|
||||
float A, B, C, C1, C2, ratio;
|
||||
|
||||
/* Get our target color */
|
||||
SDL_GetRGB(draw_color, canvas->format, &draw_r, &draw_g, &draw_b);
|
||||
|
||||
A = (x2 - x1);
|
||||
B = (y2 - y1);
|
||||
C1 = (A * x1) + (B * y1);
|
||||
C2 = (A * x2) + (B * y2);
|
||||
/* FIXME: C2 should be larger than C1? */
|
||||
|
||||
for (yy = y_top; yy <= y_bottom; yy++) {
|
||||
for (xx = x_left; xx <= x_right; xx++) {
|
||||
if (touched[(yy * canvas->w) + xx]) {
|
||||
/* FIXME */
|
||||
putpixels[canvas->format->BytesPerPixel] (canvas, xx, yy, draw_color);
|
||||
/* Get the old color, and blend it (with a distance-based ratio) with the target color */
|
||||
old_colr = getpixels[last->format->BytesPerPixel] (last, xx, yy);
|
||||
SDL_GetRGB(old_colr, last->format, &old_r, &old_g, &old_b);
|
||||
|
||||
/* (h/t David Z on StackOverflow for how to quickly compute this:
|
||||
https://stackoverflow.com/questions/521493/creating-a-linear-gradient-in-2d-array) */
|
||||
C = (A * xx) + (B * yy);
|
||||
|
||||
if (C < C1) {
|
||||
/* At/beyond the click spot (opposite direction of mouse); solid color */
|
||||
putpixels[canvas->format->BytesPerPixel] (canvas, xx, yy, draw_color);
|
||||
} else if (C >= C2) {
|
||||
/* At/beyond the mouse; completely faded out */
|
||||
putpixels[canvas->format->BytesPerPixel] (canvas, xx, yy, old_colr);
|
||||
} else {
|
||||
/* The actual gradient... */
|
||||
|
||||
ratio = (C - C1) / (C2 - C1);
|
||||
|
||||
new_r = (Uint8) (((float) old_r) * ratio + ((float) draw_r * (1.00 - ratio)));
|
||||
new_g = (Uint8) (((float) old_g) * ratio + ((float) draw_g * (1.00 - ratio)));
|
||||
new_b = (Uint8) (((float) old_b) * ratio + ((float) draw_b * (1.00 - ratio)));
|
||||
|
||||
new_colr = SDL_MapRGB(canvas->format, new_r, new_g, new_b);
|
||||
putpixels[canvas->format->BytesPerPixel] (canvas, xx, yy, new_colr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,8 @@
|
|||
int would_flood_fill(SDL_Surface * canvas, Uint32 cur_colr, Uint32 old_colr);
|
||||
void do_flood_fill(SDL_Surface * canvas, int x, int y, Uint32 cur_colr, Uint32 old_colr, int * x1, int * y1, int * x2, int * y2);
|
||||
void simulate_flood_fill(SDL_Surface * canvas, int x, int y, Uint32 cur_colr, Uint32 old_colr, int * x1, int * y1, int * x2, int * y2, Uint8 * touched);
|
||||
void draw_linear_gradient(SDL_Surface * canvas, int x_left, int y_top, int x_right, int y_bottom,
|
||||
void draw_linear_gradient(SDL_Surface * canvas, SDL_Surface * last,
|
||||
int x_left, int y_top, int x_right, int y_bottom,
|
||||
int x1, int y1, int x2, int y2, Uint32 draw_color, Uint8 * touched);
|
||||
void draw_radial_gradient(SDL_Surface * canvas, int x_left, int y_top, int x_right, int y_bottom,
|
||||
int x, int y, Uint32 draw_color, Uint8 * touched);
|
||||
|
|
|
|||
|
|
@ -1255,6 +1255,7 @@ static Uint8 canvas_color_r, canvas_color_g, canvas_color_b;
|
|||
static Uint8 *touched;
|
||||
static Uint8 *sim_flood_touched;
|
||||
int sim_flood_x1 = 0, sim_flood_y1 = 0, sim_flood_x2 = 0, sim_flood_y2 = 0;
|
||||
int fill_x, fill_y;
|
||||
static int last_print_time = 0;
|
||||
|
||||
static int shape_radius;
|
||||
|
|
@ -4536,6 +4537,9 @@ static void mainloop(void)
|
|||
color_hexes[cur_color][2]);
|
||||
canv_color = getpixels[canvas->format->BytesPerPixel] (canvas, old_x, old_y);
|
||||
|
||||
fill_x = old_x;
|
||||
fill_y = old_y;
|
||||
|
||||
if (would_flood_fill(canvas, draw_color, canv_color))
|
||||
{
|
||||
int x1, y1, x2, y2;
|
||||
|
|
@ -4583,13 +4587,12 @@ static void mainloop(void)
|
|||
draw_radial_gradient(canvas, sim_flood_x1, sim_flood_y1, sim_flood_x2, sim_flood_y2,
|
||||
old_x, old_y, draw_color, sim_flood_touched);
|
||||
}
|
||||
// else if (cur_fill == FILL_GRADIENT_LINEAR)
|
||||
// {
|
||||
// /* Start a linear gradient */
|
||||
//
|
||||
// draw_linear_gradient(canvas, sim_flood_x1, sim_flood_y1, sim_flood_x2, sim_flood_y2,
|
||||
// old_x, old_y, old_x, old_y + 1, draw_color, sim_flood_touched);
|
||||
// }
|
||||
else if (cur_fill == FILL_GRADIENT_LINEAR)
|
||||
{
|
||||
/* Start a linear gradient */
|
||||
draw_linear_gradient(canvas, canvas, sim_flood_x1, sim_flood_y1, sim_flood_x2, sim_flood_y2,
|
||||
fill_x, fill_y, old_x, old_y + 1, draw_color, sim_flood_touched);
|
||||
}
|
||||
|
||||
update_canvas(x1, y1, x2, y2);
|
||||
}
|
||||
|
|
@ -5427,7 +5430,6 @@ static void mainloop(void)
|
|||
do_setcursor(cursor_wand);
|
||||
else if (cur_tool == TOOL_ERASER)
|
||||
do_setcursor(cursor_tiny);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -5523,6 +5525,30 @@ static void mainloop(void)
|
|||
sz = calc_eraser_size(cur_eraser);
|
||||
rect_xor(new_x - sz / 2, new_y - sz / 2, new_x + sz / 2, new_y + sz / 2);
|
||||
}
|
||||
else if (cur_tool == TOOL_FILL && cur_fill == FILL_GRADIENT_LINEAR)
|
||||
{
|
||||
Uint32 draw_color, canv_color;
|
||||
int undo_ctr;
|
||||
SDL_Surface * last;
|
||||
|
||||
if (cur_undo > 0)
|
||||
undo_ctr = cur_undo - 1;
|
||||
else
|
||||
undo_ctr = NUM_UNDO_BUFS - 1;
|
||||
|
||||
last = undo_bufs[undo_ctr];
|
||||
|
||||
/* Pushing button and moving: Update the gradient: */
|
||||
|
||||
draw_color = SDL_MapRGB(canvas->format,
|
||||
color_hexes[cur_color][0],
|
||||
color_hexes[cur_color][1],
|
||||
color_hexes[cur_color][2]);
|
||||
draw_linear_gradient(canvas, last, sim_flood_x1, sim_flood_y1, sim_flood_x2, sim_flood_y2,
|
||||
fill_x, fill_y, new_x, new_y, draw_color, sim_flood_touched);
|
||||
|
||||
update_canvas(sim_flood_x1, sim_flood_y1, sim_flood_x2, sim_flood_y2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue