From dcdebe98826410ae435d31477c0b952d07cb940c Mon Sep 17 00:00:00 2001 From: Bill Kendrick Date: Tue, 19 Oct 2021 00:26:26 -0700 Subject: [PATCH] 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/ --- data/images/fills/brush.png | Bin 0 -> 5409 bytes docs/CHANGES.txt | 6 +- docs/en/README.txt | 2 + docs/en/html/README.html | 1 + docs/es_ES.UTF-8/README.txt | 2 + docs/es_ES.UTF-8/html/README.html | 1 + docs/fr_FR.UTF-8/README.txt | 2 + docs/fr_FR.UTF-8/html/README.html | 1 + docs/gl_ES.UTF-8/README.txt | 2 + docs/gl_ES.UTF-8/html/README.html | 1 + docs/ja_JP.UTF-8/README.txt | 2 + docs/ja_JP.UTF-8/html/README.html | 1 + src/fill.c | 98 +++++++++++++++++++++++++++++- src/fill.h | 6 +- src/fill_tools.h | 6 +- src/tuxpaint.c | 27 +++++++- 16 files changed, 152 insertions(+), 6 deletions(-) create mode 100644 data/images/fills/brush.png diff --git a/data/images/fills/brush.png b/data/images/fills/brush.png new file mode 100644 index 0000000000000000000000000000000000000000..6803497b4683374796f0ca3a53566e0a2cd62614 GIT binary patch literal 5409 zcmeHLYg7~G77aoTL=jLBDuQV!D##?0_d_CthY~S}0ST{GCdq^Z$vcpUsGwGhF9Zcd zQK4!pwXvW@rB($2MT8a=uqr6^(OXdv(H0evP68^f+dtlQ`_IfuGIPFj_Bm&Nd(O%v zD?DtTEoKS^g+keKLxT9o_e|vNZao(H{JbN+1BDvXmlheV<3oC^N~4s>l3}cFnF_|j z2AKqfGFYv5Cs z`yE}RXju5@+SXGgy&jG0wKR5m1HSoBRnSPim zasr(9{}{jVM?k%~_;^k5iNDr1H%JVQ)00~_bal3sJB`gP+n4%nZ86E~O7YxnTUzy9 z*2E_{zk&%pSeF3jI}L6Rt9-n9v{F(n=ZNJ=|Azi(X{9l4;l*7wPp}6`)h@tGW!uvp zw05lOt9sZ^`^AYJ9@nfr>VwBo?Ms$eYprYv(&y?(()R(?mU-c5w^4C6aO|X;H-0Z;c@rfUz7Kr>M@E2p0-yMC_0vR z%X_zG4v4lxHS^rMi!I~s*ROZKS5}jq_CuDD=Go+%k}tcGxVt;7`|JzjY0hSR(oZ2@ zeAQ9PNlGPi)VrmiB^Xxd-#*5IMnNBK@=BbbsZKt$DWYT(mb$|hBgF2o6YkcD3Z8vB z(Uj zd)vN*6=UzDZt-?32{`B!n*vro9kzK<<)vA54k+yPy$eNY>*>sa-&z0nD9jOUyg?$rCMYqR48zANvt}l10fV#VH4KsW3&v8W+Nt-KrE-Y~Y{qwAYjUOw;F`NC7GW0{kdOpiwEk| zbJk_{;+wyl{d0f$9m>LtX0qzQ@j+MHgcsYMrp0ZXX0hT%Rb5J4#9tW~-HL}UY~@|c z3!tp2!}YG5duuydc-&vy`oLI`eFcpT{p^4;V@+Vf{-A41=RE4U|FHWO+4yQDD)bXg zfq(QtB{HSDWXLp%<}F}}lyW>IRtjOfL9Rlk6$<6+XHY?+rLYbwgcD^7Htx~MGdQeF z%*F|*Jdmdfgr%~OGz}b)78WT=TPk9Taei|!z6KToAcu7j)*w$-Xjuj}&Wy`K&P`?l z4r_MNEoI}PdEwYVr3S`Q@Dw}<1RG?jB-|Vf)>k8zu=qi9M<9?ZHcqP3saOPpUa!aN z$#|tEkw9cJnFNqTAdvvX1JEv0=pX~2(0Z64hB1O*tw10X;)`STOl_@$l4u`B` zU)LvB@py0G71|LN5IzV7NJSvxL4sUP7#*S21*ak)BL)3qgfI6QlRiO{7wp%*L4tz?ve>^2YiOZ%T+vi+C(EDSkxr5wLprYWNmNmYJ8Z zShH+dkZ3rG7D|Q1=0r%`@RCRhDH37i{vHw3YrE_pHVdXvLAnTJ02C$#0w`1>9S~AM zDnO)BArPWbh+_J1dvDOSN{LPnX<$ww(kapnA|P`&*qLT3z22=wFNF~%0Fc1~K^)=V z??((#i4u^Gs8&J}B9aq<00R_>0U}cflc_=miAWQ@TjBrG4+$g@0V0T?MuH%VL}C#s z07xIzqA$TTrC#r#FX6xTc-UdoSVO28wjtvZnZATK<9CEJlPvzl*NC?M#S94aha~UC z?+3a*(DhynyqEI_b$y`gy%=~e=MU=oztM$x`v3{f znU3O9-)uuHHmZ;qEebWx!SuFRC0>$)7|}W|FBp9fGYLI;LOMRo5&8GZn;XQ5jIQY} zI2C$><8t0FE34JMjN!Pu9TR}Au4`(p-Xa{B!8jqgu-Ad5Q;*w@Kg{}aW8s(yN%_YD z*JCoDZhmojdYkm-kG`3A41Fg(&RpU2RXrZ)=%``eT7J{+9OY|bFdtX-aYPjvD>HtR z$$h@Zf`_%-FFs@U@}so=Wz|6OCui4f7A3gXTgXMHrtib}v^$?TY#IMqhEv9t@|#Xg zw!i-pIA%Ezd!JF&f%!hwVN!d#)HtX`xk_geUK*`W=lQEqRj1Kq7AN%n*VgE-dg{(j zYWL}lNl$969+(`B&YzloCPSvq+tys_WtluaD|#Am>*FE8qO*MWjNCCZZdwAd|D+TfL&gj$Q}#cNj_y&TkXLi13tqR~0nZ`06N z6?R!@sO^fSuiSR1i}r4DwP$jj;bO<%dfBsVRy}U+8Q00Jw=&vPhNnN-cJ}HKd=92C z3bR2=&-7Sov`mkz8Z56mh2FDnOrao2!6WMJ7>lb0Q+GUvi}?MVtTs$|q}7VW3kI*$ z*lG8zzOkrLu-&q|NH1?99N?s6-f(v+`s}W9zdV2_7Z7Ew`sC9{Q0V6w3zd|-S z+Uh21`H^Fi)(5EvrM9h#8T+3X<;>tj%} The 'Fill' tool 'flood-fills' a contiguous area of your 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.
  • Radial — click once to fill an area with a color that fades away (a gradient) radially, centered on where you clicked.
diff --git a/docs/es_ES.UTF-8/README.txt b/docs/es_ES.UTF-8/README.txt index 82b501260..a96c025fb 100644 --- a/docs/es_ES.UTF-8/README.txt +++ b/docs/es_ES.UTF-8/README.txt @@ -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. diff --git a/docs/es_ES.UTF-8/html/README.html b/docs/es_ES.UTF-8/html/README.html index d5c1ae7e3..567342d5c 100644 --- a/docs/es_ES.UTF-8/html/README.html +++ b/docs/es_ES.UTF-8/html/README.html @@ -701,6 +701,7 @@

The 'Fill' tool 'flood-fills' a contiguous area of your 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.
  • Radial — click once to fill an area with a color that fades away (a gradient) radially, centered on where you clicked.
diff --git a/docs/fr_FR.UTF-8/README.txt b/docs/fr_FR.UTF-8/README.txt index f89e1df8a..c013d7f7d 100644 --- a/docs/fr_FR.UTF-8/README.txt +++ b/docs/fr_FR.UTF-8/README.txt @@ -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. diff --git a/docs/fr_FR.UTF-8/html/README.html b/docs/fr_FR.UTF-8/html/README.html index 65ad9d512..15b11a60a 100644 --- a/docs/fr_FR.UTF-8/html/README.html +++ b/docs/fr_FR.UTF-8/html/README.html @@ -701,6 +701,7 @@

L'outil «Remplir» «remplit» une zone contiguë de votre dessin avec une couleur unie de votre choix. Trois options 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.
  • Radial—cliquez une fois pour remplir une zone avec une couleur qui s'atténue graduellement, à partir de l'endroit où vous avez cliqué.
diff --git a/docs/gl_ES.UTF-8/README.txt b/docs/gl_ES.UTF-8/README.txt index b467be0fb..8c06f5f6a 100644 --- a/docs/gl_ES.UTF-8/README.txt +++ b/docs/gl_ES.UTF-8/README.txt @@ -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. diff --git a/docs/gl_ES.UTF-8/html/README.html b/docs/gl_ES.UTF-8/html/README.html index 09ecf8e80..03abbd1a2 100644 --- a/docs/gl_ES.UTF-8/html/README.html +++ b/docs/gl_ES.UTF-8/html/README.html @@ -701,6 +701,7 @@

A ferramenta «Encher» inunda unha área contigua do seu debuxo cunha cor da súa escolla. Ofrécense tres opcións de 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.
  • Radial: prema unha vez para encher unha área cunha cor que se esvae (un gradiente) radialmente, centrado no lugar onde premeu.
diff --git a/docs/ja_JP.UTF-8/README.txt b/docs/ja_JP.UTF-8/README.txt index 1607c7581..789628f0e 100644 --- a/docs/ja_JP.UTF-8/README.txt +++ b/docs/ja_JP.UTF-8/README.txt @@ -316,6 +316,8 @@ Tux Paint の起動 「ぬる」ツールは、描画の連続した領域を好きな色で塗りつぶします。以下の3 つの塗りつぶしオプションが用意されています: * たんしょく — 領域を一つの色で塗りつぶします。 + * Brush — click and drag to fill an area with a solid + color using freehand painting. * せんけい — 領域をクリックしてからドラッグすると、ドラッグした方向に向かって色が薄くなるようにグラデーションをつけて塗りつぶします。 * ほうしゃ — diff --git a/docs/ja_JP.UTF-8/html/README.html b/docs/ja_JP.UTF-8/html/README.html index 56d55f166..228f14d7e 100644 --- a/docs/ja_JP.UTF-8/html/README.html +++ b/docs/ja_JP.UTF-8/html/README.html @@ -701,6 +701,7 @@

「ぬる」ツールは、描画の連続した領域を好きな色で塗りつぶします。以下の3 つの塗りつぶしオプションが用意されています:

  • たんしょく — 領域を一つの色で塗りつぶします。
  • +
  • Brush — click and drag to fill an area with a solid color using freehand painting.
  • せんけい — 領域をクリックしてからドラッグすると、ドラッグした方向に向かって色が薄くなるようにグラデーションをつけて塗りつぶします。
  • ほうしゃ — クリックした場所を中心に周りに向かって放射状に色が薄くなるようにグラデーションをつけて塗りつぶします。
diff --git a/src/fill.c b/src/fill.c index bf931c5b9..39b53a34b 100644 --- a/src/fill.c +++ b/src/fill.c @@ -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 ) { diff --git a/src/fill.h b/src/fill.h index 4681c8a8b..f7f8e162c 100644 --- a/src/fill.h +++ b/src/fill.h @@ -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 diff --git a/src/fill_tools.h b/src/fill_tools.h index 6ac7cf94d..17c75ce83 100644 --- a/src/fill_tools.h +++ b/src/fill_tools.h @@ -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" }; diff --git a/src/tuxpaint.c b/src/tuxpaint.c index 982193acc..51c9251ea 100644 --- a/src/tuxpaint.c +++ b/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 - 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); + } }