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$ $Id$
2021.October.17 (0.9.27) 2021.October.19 (0.9.27)
* New Magic Tools: * New Magic Tools:
---------------- ----------------
* "Lightning" - Draws a bolt of lightning striking between * "Lightning" - Draws a bolt of lightning striking between
@ -42,6 +42,10 @@ $Id$
* Other Improvements: * 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. * Grouped similar Magic tools into sections.
(e.g., all of the distortions, versus painting tools, versus (e.g., all of the distortions, versus painting tools, versus
full-image effects, etc.) full-image effects, etc.)

View file

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

View file

@ -701,6 +701,7 @@
<p> <p>
The 'Fill' tool 'flood-fills' a contiguous area of your drawing with a color of your choice. Three fill options are offered: <ul> 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>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>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> <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> </ul>

View file

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

View file

@ -701,6 +701,7 @@
<p> <p>
The 'Fill' tool 'flood-fills' a contiguous area of your drawing with a color of your choice. Three fill options are offered: <ul> 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>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>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> <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> </ul>

View file

@ -485,6 +485,8 @@ Outils disponibles
de remplissage sont offertes : de remplissage sont offertes :
* Solide — cliquez une fois pour remplir une zone avec * Solide — cliquez une fois pour remplir une zone avec
une couleur unie. 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 * Linéaire—cliquez et faites glisser pour remplir une
zone avec une couleur qui s'atténue au fur et à mesure zone avec une couleur qui s'atténue au fur et à mesure
dans la direction où vous déplacez la souris. dans la direction où vous déplacez la souris.

View file

@ -701,6 +701,7 @@
<p> <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> 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>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>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> <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> </ul>

View file

@ -461,6 +461,8 @@ Ferramentas dispoñíbeis
recheo: recheo:
* Sólida: prema unha vez para encher unha área cunha cor * Sólida: prema unha vez para encher unha área cunha cor
sólida. 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 * Lineal: prema e arrastra para encher a área cunha cor
que se esvae (un gradiente) cara a onde arrastra o que se esvae (un gradiente) cara a onde arrastra o
rato. rato.

View file

@ -701,6 +701,7 @@
<p> <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> 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>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>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> <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> </ul>

View file

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

View file

@ -701,6 +701,7 @@
<p> <p>
「ぬる」ツールは、描画の連続した領域を好きな色で塗りつぶします。以下の3 つの塗りつぶしオプションが用意されています: <ul> 「ぬる」ツールは、描画の連続した領域を好きな色で塗りつぶします。以下の3 つの塗りつぶしオプションが用意されています: <ul>
<li><strong>たんしょく</strong> &mdash; 領域を一つの色で塗りつぶします。</li> <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>
<li><strong>ほうしゃ</strong> &mdash; クリックした場所を中心に周りに向かって放射状に色が薄くなるようにグラデーションをつけて塗りつぶします。</li> <li><strong>ほうしゃ</strong> &mdash; クリックした場所を中心に周りに向かって放射状に色が薄くなるようにグラデーションをつけて塗りつぶします。</li>
</ul> </ul>

View file

@ -27,7 +27,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
(See COPYING.txt) (See COPYING.txt)
Last updated: May 5, 2021 Last updated: October 18, 2021
$Id$ $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, 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 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 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
(See COPYING.txt) (See COPYING.txt)
Last updated: March 8, 2021 Last updated: October 18, 2021
$Id$ $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); 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, 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); 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 #endif

View file

@ -27,7 +27,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
(See COPYING.txt) (See COPYING.txt)
Last updated: September 6, 2021 Last updated: October 18, 2021
$Id$ $Id$
*/ */
@ -40,6 +40,7 @@
enum { enum {
FILL_FLOOD, FILL_FLOOD,
FILL_BRUSH,
FILL_GRADIENT_LINEAR, FILL_GRADIENT_LINEAR,
FILL_GRADIENT_RADIAL, FILL_GRADIENT_RADIAL,
NUM_FILLS NUM_FILLS
@ -47,18 +48,21 @@ enum {
const char *const fill_names[NUM_FILLS] = { const char *const fill_names[NUM_FILLS] = {
gettext_noop("Solid"), gettext_noop("Solid"),
gettext_noop("Brush"),
gettext_noop("Linear"), gettext_noop("Linear"),
gettext_noop("Radial") gettext_noop("Radial")
}; };
const char *const fill_tips[NUM_FILLS] = { const char *const fill_tips[NUM_FILLS] = {
gettext_noop("Click to fill an area with a solid color."), 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 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).") 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] = { const char *const fill_img_fnames[NUM_FILLS] = {
DATA_PREFIX "images/fills/solid.png", DATA_PREFIX "images/fills/solid.png",
DATA_PREFIX "images/fills/brush.png",
DATA_PREFIX "images/fills/gradient_linear.png", DATA_PREFIX "images/fills/gradient_linear.png",
DATA_PREFIX "images/fills/gradient_radial.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 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
(See COPYING.txt) (See COPYING.txt)
June 14, 2002 - September 25, 2021 June 14, 2002 - October 18, 2021
*/ */
#include "platform.h" #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_x, fill_y, old_x, old_y + 1, draw_color, sim_flood_touched);
fill_drag_started = 1; 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); 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) 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; int undo_ctr;
SDL_Surface * last; 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); 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);
}
} }