diff --git a/docs/AUTHORS.txt b/docs/AUTHORS.txt
index 656bc2722..226a74e2e 100644
--- a/docs/AUTHORS.txt
+++ b/docs/AUTHORS.txt
@@ -6,7 +6,7 @@ Copyright (c) 2002-2024
Various contributors (see below, and CHANGES.txt)
https://tuxpaint.org/
-June 17, 2002 - March 19, 2024
+June 17, 2002 - March 28, 2024
* Design and Coding:
@@ -148,6 +148,11 @@ June 17, 2002 - March 19, 2024
(https://freesound.org/people/KatHakaku/sounds/54112/)
Creative Commons 0 by KatHakaku
+ Filled Polygon
+ by Bill Kendrick
+ Scanline polygon fill routine based on public-domain code
+ by Darel Rex Finley, 2007
+
Bloom magic tool
by Bill Kendrick
Googly Eyes sound effect: "Torch Crackle.wav"
diff --git a/docs/CHANGES.txt b/docs/CHANGES.txt
index 5469ed948..14ec6a65f 100644
--- a/docs/CHANGES.txt
+++ b/docs/CHANGES.txt
@@ -6,7 +6,7 @@ Copyright (c) 2002-2024
Various contributors (see below, and AUTHORS.txt)
https://tuxpaint.org/
-2024.March.27 (0.9.33)
+2024.March.28 (0.9.33)
* New Magic Tools:
----------------
* WIP Specular Reflection: Draws a slightly blurred, wavy, and
@@ -27,6 +27,14 @@ https://tuxpaint.org/
* WIP Filled Polygon - Draw points to form a polygon which is filled
Bill Kendrick
+ Scanline polygon fill routine based on public-domain code
+ by Darel Rex Finley, 2007
- Last updated: March 27, 2024
+ Scanline polygon fill routine based on public-domain code
+ by Darel Rex Finley, 2007
+
+ Last updated: March 28, 2024
*/
@@ -60,6 +63,7 @@ void polyfill_line_callback(void *pointer, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int x, int y);
void polyfill_draw_preview(magic_api * api, SDL_Surface * canvas, int show_handles);
+void polyfill_draw_final(magic_api * api, SDL_Surface * canvas);
Uint32 polyfill_api_version(void)
@@ -234,6 +238,7 @@ void polyfill_draw_preview(magic_api * api, SDL_Surface * canvas, int show_handl
return;
SDL_BlitSurface(polyfill_snapshot, NULL, canvas, NULL);
+
for (i = 0; i < polyfill_num_pts - 1; i++) {
api->line((void *) api, 0 /* which */, canvas, NULL /* snapshot */,
polyfill_pt_x[i], polyfill_pt_y[i],
@@ -284,10 +289,9 @@ polyfill_release(magic_api * api, int which,
printf("Release while editing %d\n", polyfill_editing);
-// if (polyfill_editing == polyfill_num_pts) {
-// printf("Finalizing it...\n");
-// polyfill_num_pts++;
-// }
+ /* FIXME: If they simply clicked the first point (without
+ drawing to move it), and there are enough points, consider
+ it a final placement of a new point! */
/* Moved (or placed) the final spot at the beginning? */
if (polyfill_num_pts > 2 &&
@@ -311,8 +315,7 @@ polyfill_release(magic_api * api, int which,
polyfill_pt_y[polyfill_num_pts - 1] = polyfill_pt_y[0];
}
- // FIXME
- polyfill_draw_preview(api, canvas, 0);
+ polyfill_draw_final(api, canvas);
polyfill_num_pts = 0;
polyfill_editing = MAX_PTS;
@@ -358,6 +361,7 @@ polyfill_release(magic_api * api, int which,
void polyfill_set_color(magic_api * api, int which, SDL_Surface * canvas, SDL_Surface * snapshot, Uint8 r, Uint8 g, Uint8 b, SDL_Rect * update_rect)
{
polyfill_color = SDL_MapRGB(canvas->format, r, g, b);
+ polyfill_draw_preview(api, canvas, 1);
}
void polyfill_set_size(magic_api * api, int which, int mode, SDL_Surface * canvas, SDL_Surface * snapshot, Uint8 size, SDL_Rect * update_rect)
@@ -401,7 +405,82 @@ void polyfill_switchin(magic_api * api, int which, int mode,
void polyfill_switchout(magic_api * api, int which, int mode,
SDL_Surface * canvas)
{
- /* FIXME: Do we want to do this? */
- // polyfill_num_pts = 0;
- // polyfill_editing = MAX_PTS;
+ polyfill_num_pts = 0;
+ polyfill_editing = MAX_PTS;
+}
+
+/* Based on public-domain code by Darel Rex Finley, 2007
+ https://alienryderflex.com/polygon_fill/
+*/
+void polyfill_draw_final(magic_api * api, SDL_Surface * canvas) {
+ int i, j, ymin, ymax, y, nodes, swap;
+ int nodeX[256];
+ SDL_Rect rect;
+
+ SDL_BlitSurface(polyfill_snapshot, NULL, canvas, NULL);
+
+ ymin = canvas->w;
+ ymax = 0;
+ for (i = 0; i < polyfill_num_pts; i++) {
+ if (polyfill_pt_y[i] < ymin) {
+ ymin = polyfill_pt_y[i];
+ }
+ if (polyfill_pt_y[i] > ymax) {
+ ymax = polyfill_pt_y[i];
+ }
+ }
+ printf("ymin %d -> ymax %d\n", ymin, ymax);
+
+ for (y = ymin; y <= ymax; y++) {
+ nodes = 0;
+ j = polyfill_num_pts - 2;
+
+ for (i = 0; i < polyfill_num_pts - 1; i++) {
+ if ((polyfill_pt_y[i] < y && polyfill_pt_y[j] >= y) ||
+ (polyfill_pt_y[j] < y && polyfill_pt_y[i] >= y)) {
+ nodeX[nodes++] = (int)
+ (
+ (double) polyfill_pt_x[i] +
+ (double) (y - polyfill_pt_y[i]) /
+ (double) (polyfill_pt_y[j] - polyfill_pt_y[i]) *
+ (double) (polyfill_pt_x[j] - polyfill_pt_x[i])
+ );
+ }
+
+ j = i;
+ }
+
+ // Sort the nodes, via a simple “Bubble” sort.
+ i = 0;
+ while (i < nodes - 1) {
+ if (nodeX[i] > nodeX[i+1]) {
+ swap = nodeX[i];
+ nodeX[i] = nodeX[i + 1];
+ nodeX[i + 1] = swap;
+ if (i)
+ i--;
+ } else {
+ i++;
+ }
+ }
+
+ // Fill the pixels between node pairs.
+ for (i = 0; i < nodes; i += 2) {
+ if (nodeX[i] >= canvas->w)
+ break;
+
+ if (nodeX[i + 1] > 0) {
+ if (nodeX[i] < 0)
+ nodeX[i] = 0;
+ if (nodeX[i + 1] > canvas->w - 1)
+ nodeX[i + 1] = canvas->w - 1;
+
+ rect.x = nodeX[i];
+ rect.y = y;
+ rect.w = nodeX[i + 1] - nodeX[i] + 1;
+ rect.h = 1;
+ SDL_FillRect(canvas, &rect, polyfill_color);
+ }
+ }
+ }
}