New Fill tool mode: Brush

Similar to solid fill (classic mode), but allows freehand
filling of an area.

Closes https://sourceforge.net/p/tuxpaint/feature-requests/207/
This commit is contained in:
Bill Kendrick 2021-10-19 00:26:26 -07:00
parent 910cd298e5
commit dcdebe9882
16 changed files with 152 additions and 6 deletions

BIN
data/images/fills/brush.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

View file

@ -8,7 +8,7 @@ http://www.tuxpaint.org/
$Id$
2021.October.17 (0.9.27)
2021.October.19 (0.9.27)
* New Magic Tools:
----------------
* "Lightning" - Draws a bolt of lightning striking between
@ -42,6 +42,10 @@ $Id$
* Other Improvements:
-------------------
* New "Fill" tool mode: "Brush". Similar to classic flood fill,
but only fills as you move the brush within the area to be
filled.
* Grouped similar Magic tools into sections.
(e.g., all of the distortions, versus painting tools, versus
full-image effects, etc.)

View file

@ -444,6 +444,8 @@ Available Tools
drawing with a color of your choice. Three fill options are
offered:
* Solid — click once to fill an area with a solid color.
* Brush — click and drag to fill an area with a solid
color using freehand painting.
* Linear — click and then drag to fill the area with
color that fades away (a gradient) towards where you
drag the mouse.

View file

@ -701,6 +701,7 @@
<p>
The 'Fill' tool 'flood-fills' a contiguous area of your drawing with a color of your choice. Three fill options are offered: <ul>
<li><strong>Solid</strong> &mdash; click once to fill an area with a solid color.</li>
<li><strong>Brush</strong> &mdash; click and drag to fill an area with a solid color using freehand painting.</li>
<li><strong>Linear</strong> &mdash; click and then drag to fill the area with color that fades away (a gradient) towards where you drag the mouse.</li>
<li><strong>Radial</strong> &mdash; click once to fill an area with a color that fades away (a gradient) radially, centered on where you clicked.</li>
</ul>

View file

@ -444,6 +444,8 @@ Available Tools
drawing with a color of your choice. Three fill options are
offered:
* Solid — click once to fill an area with a solid color.
* Brush — click and drag to fill an area with a solid
color using freehand painting.
* Linear — click and then drag to fill the area with
color that fades away (a gradient) towards where you
drag the mouse.

View file

@ -701,6 +701,7 @@
<p>
The 'Fill' tool 'flood-fills' a contiguous area of your drawing with a color of your choice. Three fill options are offered: <ul>
<li><strong>Solid</strong> &mdash; click once to fill an area with a solid color.</li>
<li><strong>Brush</strong> &mdash; click and drag to fill an area with a solid color using freehand painting.</li>
<li><strong>Linear</strong> &mdash; click and then drag to fill the area with color that fades away (a gradient) towards where you drag the mouse.</li>
<li><strong>Radial</strong> &mdash; click once to fill an area with a color that fades away (a gradient) radially, centered on where you clicked.</li>
</ul>

View file

@ -485,6 +485,8 @@ Outils disponibles
de remplissage sont offertes :
* Solide — cliquez une fois pour remplir une zone avec
une couleur unie.
* Brush — click and drag to fill an area with a solid
color using freehand painting.
* Linéaire—cliquez et faites glisser pour remplir une
zone avec une couleur qui s'atténue au fur et à mesure
dans la direction où vous déplacez la souris.

View file

@ -701,6 +701,7 @@
<p>
L'outil «Remplir» «remplit» une zone contiguë de votre dessin avec une couleur unie de votre choix. Trois options de remplissage sont offertes : <ul>
<li><strong>Solide</strong> &mdash; cliquez une fois pour remplir une zone avec une couleur unie.</li>
<li><strong>Brush</strong> &mdash; click and drag to fill an area with a solid color using freehand painting.</li>
<li><strong>Linéaire</strong>&mdash;cliquez et faites glisser pour remplir une zone avec une couleur qui s'atténue au fur et à mesure dans la direction où vous déplacez la souris.</li>
<li><strong>Radial</strong>&mdash;cliquez une fois pour remplir une zone avec une couleur qui s'atténue graduellement, à partir de l'endroit où vous avez cliqué.</li>
</ul>

View file

@ -461,6 +461,8 @@ Ferramentas dispoñíbeis
recheo:
* Sólida: prema unha vez para encher unha área cunha cor
sólida.
* Brush — click and drag to fill an area with a solid
color using freehand painting.
* Lineal: prema e arrastra para encher a área cunha cor
que se esvae (un gradiente) cara a onde arrastra o
rato.

View file

@ -701,6 +701,7 @@
<p>
A ferramenta «Encher» inunda unha área contigua do seu debuxo cunha cor da súa escolla. Ofrécense tres opcións de recheo: <ul>
<li><strong>Sólida</strong>: prema unha vez para encher unha área cunha cor sólida.</li>
<li><strong>Brush</strong> &mdash; click and drag to fill an area with a solid color using freehand painting.</li>
<li><strong>Lineal</strong>: prema e arrastra para encher a área cunha cor que se esvae (un gradiente) cara a onde arrastra o rato.</li>
<li><strong>Radial</strong>: prema unha vez para encher unha área cunha cor que se esvae (un gradiente) radialmente, centrado no lugar onde premeu.</li>
</ul>

View file

@ -316,6 +316,8 @@ Tux Paint の起動
「ぬる」ツールは、描画の連続した領域を好きな色で塗りつぶします。以下の3 つの塗りつぶしオプションが用意されています:
* たんしょく — 領域を一つの色で塗りつぶします。
* Brush — click and drag to fill an area with a solid
color using freehand painting.
* せんけい —
領域をクリックしてからドラッグすると、ドラッグした方向に向かって色が薄くなるようにグラデーションをつけて塗りつぶします。
* ほうしゃ —

View file

@ -701,6 +701,7 @@
<p>
「ぬる」ツールは、描画の連続した領域を好きな色で塗りつぶします。以下の3 つの塗りつぶしオプションが用意されています: <ul>
<li><strong>たんしょく</strong> &mdash; 領域を一つの色で塗りつぶします。</li>
<li><strong>Brush</strong> &mdash; click and drag to fill an area with a solid color using freehand painting.</li>
<li><strong>せんけい</strong> &mdash; 領域をクリックしてからドラッグすると、ドラッグした方向に向かって色が薄くなるようにグラデーションをつけて塗りつぶします。</li>
<li><strong>ほうしゃ</strong> &mdash; クリックした場所を中心に周りに向かって放射状に色が薄くなるようにグラデーションをつけて塗りつぶします。</li>
</ul>

View file

@ -27,7 +27,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
(See COPYING.txt)
Last updated: May 5, 2021
Last updated: October 18, 2021
$Id$
*/
@ -380,6 +380,102 @@ void draw_linear_gradient(SDL_Surface * canvas, SDL_Surface * last,
}
}
void draw_brush_fill_single(SDL_Surface * canvas, int x, int y, Uint32 draw_color, Uint8 * touched) {
int xx, yy;
for (yy = -16; yy < 16; yy++)
{
for (xx = -16; xx < 16; xx++)
{
if ((xx * xx) + (yy * yy) < (16 * 16) &&
touched[((y + yy) * canvas->w) + (x + xx)])
{
putpixels[canvas->format->BytesPerPixel] (canvas, x + xx, y + yy, draw_color);
}
}
}
}
void draw_brush_fill(SDL_Surface * canvas,
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,
int * up_x1, int * up_y1, int * up_x2, int * up_y2
) {
int xx, yy, x, y, dx, dy;
int orig_x1, orig_y1, orig_x2, orig_y2, tmp;
float m, b;
orig_x1 = x1;
orig_y1 = y1;
orig_x2 = x2;
orig_y2 = y2;
dx = x2 - x1;
dy = y2 - y1;
if (dx != 0)
{
m = ((float)dy) / ((float)dx);
b = y1 - m * x1;
if (x2 >= x1)
dx = 1;
else
dx = -1;
while (x1 != x2)
{
y1 = m * x1 + b;
y2 = m * (x1 + dx) + b;
if (y1 > y2)
{
for (y = y1; y >= y2; y--)
draw_brush_fill_single(canvas, x1, y, draw_color, touched);
}
else
{
for (y = y1; y <= y2; y++)
draw_brush_fill_single(canvas, x1, y, draw_color, touched);
}
x1 = x1 + dx;
}
}
else
{
if (y1 > y2)
{
y = y1;
y1 = y2;
y2 = y;
}
for (y = y1; y <= y2; y++)
draw_brush_fill_single(canvas, x1, y, draw_color, touched);
}
if (orig_x1 > orig_x2)
{
tmp = orig_x1;
orig_x1 = orig_x2;
orig_x2 = tmp;
}
if (orig_y1 > orig_y2)
{
tmp = orig_y1;
orig_y1 = orig_y2;
orig_y2 = tmp;
}
*up_x1 = orig_x1 - 16;
*up_y1 = orig_y1 - 16;
*up_x2 = orig_x2 + 16;
*up_y2 = orig_y2 + 16;
}
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
) {

View file

@ -27,7 +27,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
(See COPYING.txt)
Last updated: March 8, 2021
Last updated: October 18, 2021
$Id$
*/
@ -44,6 +44,10 @@ void draw_linear_gradient(SDL_Surface * canvas, SDL_Surface * last,
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);
void draw_brush_fill(SDL_Surface * canvas,
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,
int * up_x1, int * up_y1, int * up_x2, int * up_y2);
#endif

View file

@ -27,7 +27,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
(See COPYING.txt)
Last updated: September 6, 2021
Last updated: October 18, 2021
$Id$
*/
@ -40,6 +40,7 @@
enum {
FILL_FLOOD,
FILL_BRUSH,
FILL_GRADIENT_LINEAR,
FILL_GRADIENT_RADIAL,
NUM_FILLS
@ -47,18 +48,21 @@ enum {
const char *const fill_names[NUM_FILLS] = {
gettext_noop("Solid"),
gettext_noop("Brush"),
gettext_noop("Linear"),
gettext_noop("Radial")
};
const char *const fill_tips[NUM_FILLS] = {
gettext_noop("Click to fill an area with a solid color."),
gettext_noop("Click to fill an by hand, using a brush."),
gettext_noop("Click and drag to fill an area with a linear gradient (from the chosen color to transparent)."),
gettext_noop("Click to fill an area with a radial gradient (from the chosen color to transparent).")
};
const char *const fill_img_fnames[NUM_FILLS] = {
DATA_PREFIX "images/fills/solid.png",
DATA_PREFIX "images/fills/brush.png",
DATA_PREFIX "images/fills/gradient_linear.png",
DATA_PREFIX "images/fills/gradient_radial.png"
};

View file

@ -22,7 +22,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
(See COPYING.txt)
June 14, 2002 - September 25, 2021
June 14, 2002 - October 18, 2021
*/
#include "platform.h"
@ -4719,6 +4719,12 @@ static void mainloop(void)
fill_x, fill_y, old_x, old_y + 1, draw_color, sim_flood_touched);
fill_drag_started = 1;
}
else if (cur_fill == FILL_BRUSH)
{
/* Start painting within the fill area */
draw_brush_fill(canvas, sim_flood_x1, sim_flood_y1, sim_flood_x2, sim_flood_y2,
fill_x, fill_y, old_x, old_y, draw_color, sim_flood_touched, &x1, &x2, &y1, &y2);
}
update_canvas(x1, y1, x2, y2);
}
@ -5676,7 +5682,7 @@ static void mainloop(void)
}
else if (cur_tool == TOOL_FILL && cur_fill == FILL_GRADIENT_LINEAR && fill_drag_started)
{
Uint32 draw_color, canv_color;
Uint32 draw_color;
int undo_ctr;
SDL_Surface * last;
@ -5698,6 +5704,23 @@ static void mainloop(void)
update_canvas(sim_flood_x1, sim_flood_y1, sim_flood_x2, sim_flood_y2);
}
else if (cur_tool == TOOL_FILL && cur_fill == FILL_BRUSH)
{
Uint32 draw_color;
int x1, y1, x2, y2;
/* Pushing button and moving: Paint more within the fill area: */
draw_color = SDL_MapRGB(canvas->format,
color_hexes[cur_color][0],
color_hexes[cur_color][1],
color_hexes[cur_color][2]);
draw_brush_fill(canvas, sim_flood_x1, sim_flood_y1, sim_flood_x2, sim_flood_y2,
old_x, old_y, new_x, new_y, draw_color, sim_flood_touched, &x1, &y1, &x2, &y2);
update_canvas(x1, y1, x2, y2);
}
}