Stamp performance improvements

+ Stamps are scaled before they are colorized or tinted,
   to increase performance.
 + The current stamp (in its current form: size, orientation,
   and color) is cached, so it may be applied to the canvas
   many times without having to re-render.
   (No longer scaling and tinting every time you click.)

Closes https://sourceforge.net/p/tuxpaint/bugs/147/
(h/t Andre Anckaert)
This commit is contained in:
Bill Kendrick 2022-01-25 22:21:55 -08:00 committed by Pere Pujal i Carabantes
parent c49d2a6f68
commit 20c0db88c3
2 changed files with 144 additions and 85 deletions

View file

@ -7,7 +7,7 @@ Various contributors (see below, and AUTHORS.txt)
http://www.tuxpaint.org/ http://www.tuxpaint.org/
2022.January.24 (0.9.28) 2022.January.25 (0.9.28)
* Improvements to "Paint" and "Lines" tools: * Improvements to "Paint" and "Lines" tools:
------------------------------------------ ------------------------------------------
* Brush spacing may now be altered within Tux Paint. * Brush spacing may now be altered within Tux Paint.
@ -23,6 +23,18 @@ http://www.tuxpaint.org/
(h/t Areti Tsolakidou for the suggestion) (h/t Areti Tsolakidou for the suggestion)
Bill Kendrick <bill@newbreedsoftware.com> Bill Kendrick <bill@newbreedsoftware.com>
* Improvements to "Stamp" tool:
-----------------------------
* Stamp performance improvements
+ Stamps are scaled before they are colorized or tinted,
to increase performance.
+ The current stamp (in its current form: size, orientation,
and color) is cached, so it may be applied to the canvas
many times without having to re-render.
(No longer scaling and tinting every time you click.)
Closes https://sourceforge.net/p/tuxpaint/bugs/147/
(h/t Andre Anckaert)
* Improvements to "Eraser" tool: * Improvements to "Eraser" tool:
------------------------------ ------------------------------
* Outline for circle-shaped erasers is now also circular. * Outline for circle-shaped erasers is now also circular.

View file

@ -1904,6 +1904,7 @@ static int max_stamps[MAX_STAMP_GROUPS];
static stamp_type **stamp_data[MAX_STAMP_GROUPS]; static stamp_type **stamp_data[MAX_STAMP_GROUPS];
static SDL_Surface *active_stamp; static SDL_Surface *active_stamp;
static SDL_Surface * current_stamp_cached = NULL;
/** /**
@ -2110,6 +2111,7 @@ static void update_stamp_xor(void);
#endif #endif
static void set_active_stamp(void); static void set_active_stamp(void);
static void clear_cached_stamp(void);
static int calc_eraser_size(int which_eraser); static int calc_eraser_size(int which_eraser);
static void do_eraser(int x, int y, int update); static void do_eraser(int x, int y, int update);
@ -4777,6 +4779,8 @@ static void mainloop(void)
color_hexes[cur_color][0], color_hexes[cur_color][0],
color_hexes[cur_color][1], color_hexes[cur_color][1],
color_hexes[cur_color][2]); color_hexes[cur_color][2]);
else if (cur_tool == TOOL_STAMP)
clear_cached_stamp();
} }
} }
} }
@ -7074,7 +7078,6 @@ static void tint_surface(SDL_Surface * tmp_surf, SDL_Surface * surf_ptr)
} }
/** /**
* Draw the current stamp onto the canvas. * Draw the current stamp onto the canvas.
* *
@ -7084,21 +7087,29 @@ static void tint_surface(SDL_Surface * tmp_surf, SDL_Surface * surf_ptr)
static void stamp_draw(int x, int y) static void stamp_draw(int x, int y)
{ {
SDL_Rect dest; SDL_Rect dest;
SDL_Surface *tmp_surf, *surf_ptr, *final_surf; SDL_Surface *scaled_surf, *tmp_surf, *surf_ptr;
Uint32 amask; Uint32 amask;
Uint8 r, g, b, a; Uint8 r, g, b, a;
int xx, yy, dont_free_tmp_surf, base_x, base_y; int xx, yy, base_x, base_y;
int dont_free_tmp_surf, dont_free_scaled_surf;
if (current_stamp_cached == NULL)
{
printf("Generating stamp image\n");
Uint32(*getpixel) (SDL_Surface *, int, int); Uint32(*getpixel) (SDL_Surface *, int, int);
void (*putpixel) (SDL_Surface *, int, int, Uint32); void (*putpixel) (SDL_Surface *, int, int, Uint32);
surf_ptr = active_stamp; /* Shrink or grow it! */
scaled_surf = thumbnail(active_stamp, CUR_STAMP_W, CUR_STAMP_H, 0);
dont_free_scaled_surf = 0;
surf_ptr = scaled_surf;
getpixel = getpixels[surf_ptr->format->BytesPerPixel]; getpixel = getpixels[surf_ptr->format->BytesPerPixel];
/* Create a temp surface to play with: */ /* Create a temp surface to play with: */
if (stamp_colorable(cur_stamp[stamp_group]) || stamp_tintable(cur_stamp[stamp_group])) if (stamp_colorable(cur_stamp[stamp_group]) || stamp_tintable(cur_stamp[stamp_group]))
{ {
amask = ~(surf_ptr->format->Rmask | surf_ptr->format->Gmask | surf_ptr->format->Bmask); amask = ~(surf_ptr->format->Rmask | surf_ptr->format->Gmask | surf_ptr->format->Bmask);
@ -7166,6 +7177,7 @@ static void stamp_draw(int x, int y)
} }
else if (stamp_tintable(cur_stamp[stamp_group])) else if (stamp_tintable(cur_stamp[stamp_group]))
{ {
/* Tintable */
if (stamp_data[stamp_group][cur_stamp[stamp_group]]->tinter == TINTER_VECTOR) if (stamp_data[stamp_group][cur_stamp[stamp_group]]->tinter == TINTER_VECTOR)
vector_tint_surface(tmp_surf, surf_ptr); vector_tint_surface(tmp_surf, surf_ptr);
else else
@ -7177,8 +7189,17 @@ static void stamp_draw(int x, int y)
tmp_surf = surf_ptr; tmp_surf = surf_ptr;
} }
/* Shrink or grow it! */ printf("Caching stamp\n");
final_surf = thumbnail(tmp_surf, CUR_STAMP_W, CUR_STAMP_H, 0); current_stamp_cached = SDL_DisplayFormatAlpha(tmp_surf);
}
else
{
printf("Using cached stamp!\n");
tmp_surf = current_stamp_cached;
dont_free_tmp_surf = 1;
dont_free_scaled_surf = 1;
}
/* Where it will go? */ /* Where it will go? */
base_x = x - (CUR_STAMP_W + 1) / 2; base_x = x - (CUR_STAMP_W + 1) / 2;
@ -7187,7 +7208,7 @@ static void stamp_draw(int x, int y)
/* And blit it! */ /* And blit it! */
dest.x = base_x; dest.x = base_x;
dest.y = base_y; dest.y = base_y;
SDL_BlitSurface(final_surf, NULL, canvas, &dest); /* FIXME: Conditional jump or move depends on uninitialised value(s) */ SDL_BlitSurface(tmp_surf, NULL, canvas, &dest); /* FIXME: Conditional jump or move depends on uninitialised value(s) */
update_canvas(x - (CUR_STAMP_W + 1) / 2, update_canvas(x - (CUR_STAMP_W + 1) / 2,
y - (CUR_STAMP_H + 1) / 2, x + (CUR_STAMP_W + 1) / 2, y + (CUR_STAMP_H + 1) / 2); y - (CUR_STAMP_H + 1) / 2, x + (CUR_STAMP_W + 1) / 2, y + (CUR_STAMP_H + 1) / 2);
@ -7197,7 +7218,8 @@ static void stamp_draw(int x, int y)
if (!dont_free_tmp_surf) if (!dont_free_tmp_surf)
SDL_FreeSurface(tmp_surf); SDL_FreeSurface(tmp_surf);
SDL_FreeSurface(final_surf); if (!dont_free_scaled_surf)
SDL_FreeSurface(scaled_surf);
} }
@ -7890,6 +7912,28 @@ static void loadstamp_finisher(stamp_type * sd, unsigned w, unsigned h, double r
} }
/**
* Clear the currently-cached stamp image
* (what we blit to the canvas, so the stamp in its
* current orientation, scale, and color), since we'll
* need to generate something new based on a change
* (a new size, color, orientation, or a completely
* different stamp)
*/
static void clear_cached_stamp(void)
{
if (current_stamp_cached != NULL)
{
printf("Clearing cached stamp\n");
SDL_FreeSurface(current_stamp_cached);
current_stamp_cached = NULL;
}
else
{
printf("No cached stamp to clear\n");
}
}
/** /**
* FIXME * FIXME
*/ */
@ -8135,6 +8179,8 @@ static void set_active_stamp(void)
#ifdef DEBUG #ifdef DEBUG
printf("\n\n"); printf("\n\n");
#endif #endif
clear_cached_stamp();
} }
/** /**
@ -13947,6 +13993,7 @@ static void cleanup(void)
free(stamp_data[j]); free(stamp_data[j]);
} }
free_surface(&active_stamp); free_surface(&active_stamp);
free_surface(&current_stamp_cached);
free_surface_array(img_brushes, num_brushes); free_surface_array(img_brushes, num_brushes);
free_surface_array(img_brushes_thumbs, num_brushes); free_surface_array(img_brushes_thumbs, num_brushes);