Merge branch 'master' into sdl2.0. Updating with latest changes and improvements, clone, fill,...

This commit is contained in:
Pere Pujal i Carabantes 2021-02-25 00:48:38 +01:00
commit 00b4aa126f
180 changed files with 15268 additions and 8028 deletions

View file

@ -1,13 +1,12 @@
/*
blind.c
//
BLIND Magic Tools Plugin
Tux Paint - A simple drawing program for children.
By Pere Pujal Carabantes
Copyright (c) 2002-2009 by Bill Kendrick and others; see AUTHORS.txt
bill@newbreedsoftware.com
Copyright (c) 2009-2021
http://www.tuxpaint.org/
This program is free software; you can redistribute it and/or modify
@ -275,20 +274,20 @@ void blind_click(magic_api * api, int which, int mode ATTRIBUTE_UNUSED,
{
if (x < y)
blind_side = 1; /* left */
blind_side = BLIND_SIDE_LEFT;
else if (canvas->w - x < y)
blind_side = 3; /* right */
blind_side = BLIND_SIDE_RIGHT;
else
blind_side = 0; /* top */
blind_side = BLIND_SIDE_TOP;
}
else
{
if (x < canvas->h - y)
blind_side = 1; /* left */
blind_side = BLIND_SIDE_LEFT;
else if (canvas->w - x < canvas->h - y)
blind_side = 3; /* right */
blind_side = BLIND_SIDE_RIGHT;
else
blind_side = 2; /* bottom */
blind_side = BLIND_SIDE_BOTTOM;
}
blind_drag(api, which, canvas, last, x, y, x, y, update_rect);

245
magic/src/checkerboard.c Normal file
View file

@ -0,0 +1,245 @@
/*
checkeroard.c
"Checkerboard" Magic Tools Plugin
Tux Paint - A simple drawing program for children.
By Bill Kendrick
Based on `blind.c` by Pere Pujal Carabantes
Copyright (c) 2021
http://www.tuxpaint.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
(See COPYING.txt)
*/
#include "tp_magic_api.h"
#include "SDL_image.h"
#include "SDL_mixer.h"
static Uint8 checkerboard_r, checkerboard_g, checkerboard_b;
int checkerboard_start_x, checkerboard_start_y;
Mix_Chunk *checkerboard_snd;
// Prototypes
Uint32 checkerboard_api_version(void);
void checkerboard_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b);
int checkerboard_init(magic_api * api);
int checkerboard_get_tool_count(magic_api * api);
SDL_Surface *checkerboard_get_icon(magic_api * api, int which);
char *checkerboard_get_name(magic_api * api, int which);
char *checkerboard_get_description(magic_api * api, int which, int mode);
int checkerboard_requires_colors(magic_api * api, int which);
void checkerboard_release(magic_api * api, int which,
SDL_Surface * canvas, SDL_Surface * snapshot, int x, int y, SDL_Rect * update_rect);
void checkerboard_shutdown(magic_api * api);
void checkerboard_paint_checkerboard(void *ptr_to_api, int which_tool, SDL_Surface * canvas, SDL_Surface * snapshot, int x, int y);
void checkerboard_drag(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int ox, int oy, int x, int y, SDL_Rect * update_rect);
void checkerboard_click(magic_api * api, int which, int mode,
SDL_Surface * canvas, SDL_Surface * last, int x, int y, SDL_Rect * update_rect);
void checkerboard_switchin(magic_api * api, int which, int mode, SDL_Surface * canvas);
void checkerboard_switchout(magic_api * api, int which, int mode, SDL_Surface * canvas);
int checkerboard_modes(magic_api * api, int which);
// Housekeeping functions
Uint32 checkerboard_api_version(void)
{
return (TP_MAGIC_API_VERSION);
}
void checkerboard_set_color(magic_api * api ATTRIBUTE_UNUSED, Uint8 r, Uint8 g, Uint8 b) //get the colors from API and store it in structure
{
checkerboard_r = r;
checkerboard_g = g;
checkerboard_b = b;
}
int checkerboard_init(magic_api * api)
{
char fname[1024];
snprintf(fname, sizeof(fname), "%s/sounds/magic/checkerboard.ogg", api->data_directory);
checkerboard_snd = Mix_LoadWAV(fname);
return (1);
}
int checkerboard_get_tool_count(magic_api * api ATTRIBUTE_UNUSED)
{
return 1;
}
SDL_Surface *checkerboard_get_icon(magic_api * api, int which ATTRIBUTE_UNUSED)
{
char fname[1024];
snprintf(fname, sizeof(fname), "%s/images/magic/checkerboard.png", api->data_directory);
return (IMG_Load(fname));
}
char *checkerboard_get_name(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED)
{
return strdup(gettext_noop("Checkerboard"));
}
char *checkerboard_get_description(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED)
{
return
strdup(gettext_noop
("Click and drag to fill the canvas with a checkerboard pattern."));
}
int checkerboard_requires_colors(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED)
{
return 1;
}
void checkerboard_release(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED,
SDL_Surface * canvas ATTRIBUTE_UNUSED, SDL_Surface * snapshot ATTRIBUTE_UNUSED,
int x ATTRIBUTE_UNUSED, int y ATTRIBUTE_UNUSED, SDL_Rect * update_rect ATTRIBUTE_UNUSED)
{
}
void checkerboard_shutdown(magic_api * api ATTRIBUTE_UNUSED)
{
Mix_FreeChunk(checkerboard_snd);
}
// Interactivity functions
void checkerboard_drag(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * snapshot,
int ox ATTRIBUTE_UNUSED, int oy ATTRIBUTE_UNUSED,
int x, int y, SDL_Rect * update_rect)
{
int sz, xx, yy;
Uint8 draw_start, draw_row, draw_cell;
Uint32 colr;
SDL_Rect dest;
SDL_BlitSurface(snapshot, NULL, canvas, NULL);
sz = max(10, max(abs(x - checkerboard_start_x), abs(y - checkerboard_start_y)));
colr = SDL_MapRGB(canvas->format, checkerboard_r, checkerboard_g, checkerboard_b);
draw_start = 1;
if (x < checkerboard_start_x)
draw_start = !draw_start;
if (y < checkerboard_start_y)
draw_start = !draw_start;
/* From the mouse Y position down... */
draw_row = draw_start;
for (yy = checkerboard_start_y; yy <= canvas->h; yy += sz) {
/* From the mouse X position right... */
draw_cell = draw_row;
for (xx = checkerboard_start_x; xx <= canvas->w; xx += sz) {
if (draw_cell) {
dest.x = xx;
dest.y = yy;
dest.w = sz;
dest.h = sz;
SDL_FillRect(canvas, &dest, colr);
}
draw_cell = !draw_cell;
}
/* From the mouse X position left... */
draw_cell = !draw_row;
for (xx = checkerboard_start_x - sz; xx > -sz; xx -= sz) {
if (draw_cell) {
dest.x = xx;
dest.y = yy;
dest.w = sz;
dest.h = sz;
SDL_FillRect(canvas, &dest, colr);
}
draw_cell = !draw_cell;
}
draw_row = !draw_row;
}
/* From the mouse Y position up... */
draw_row = !draw_start;
for (yy = checkerboard_start_y - sz; yy > -sz; yy -= sz) {
/* From the mouse X position right... */
draw_cell = draw_row;
for (xx = checkerboard_start_x; xx <= canvas->w; xx += sz) {
if (draw_cell) {
dest.x = xx;
dest.y = yy;
dest.w = sz;
dest.h = sz;
SDL_FillRect(canvas, &dest, colr);
}
draw_cell = !draw_cell;
}
/* From the mouse X position left... */
draw_cell = !draw_row;
for (xx = checkerboard_start_x - sz; xx > -sz; xx -= sz) {
if (draw_cell) {
dest.x = xx;
dest.y = yy;
dest.w = sz;
dest.h = sz;
SDL_FillRect(canvas, &dest, colr);
}
draw_cell = !draw_cell;
}
draw_row = !draw_row;
}
/* Always applies to the whole screen! */
update_rect->x = 0;
update_rect->y = 0;
update_rect->w = canvas->w;
update_rect->h = canvas->h;
api->playsound(checkerboard_snd, 128, 255);
}
void checkerboard_click(magic_api * api, int which, int mode,
SDL_Surface * canvas, SDL_Surface * last,
int x, int y,
SDL_Rect * update_rect)
{
checkerboard_start_x = x;
checkerboard_start_y = y;
checkerboard_drag(api, which, canvas, last, x, y, x, y, update_rect);
}
void checkerboard_switchin(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED,
SDL_Surface * canvas ATTRIBUTE_UNUSED)
{
}
void checkerboard_switchout(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED,
SDL_Surface * canvas ATTRIBUTE_UNUSED)
{
}
int checkerboard_modes(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED)
{
return (MODE_PAINT);
}

View file

@ -23,7 +23,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
(See COPYING.txt)
Last updated: February 10, 2021
Last updated: February 20, 2021
$Id$
*/
@ -59,6 +59,8 @@ static Mix_Chunk *clone_start_snd, *clone_snd;
int clone_state;
int clone_src_x, clone_src_y;
int clone_drag_start_x, clone_drag_start_y;
SDL_Surface * clone_last;
int clone_crosshair_visible;
/* Local function prototype: */
@ -71,6 +73,9 @@ char *clone_get_name(magic_api * api, int which);
char *clone_get_description(magic_api * api, int which, int mode);
void clone_drag(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * last, int ox, int oy, int x, int y, SDL_Rect * update_rect);
void clone_doit(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * last, int ox, int oy, int x, int y, SDL_Rect * update_rect,
int crosshairs);
void clone_click(magic_api * api, int which, int mode,
SDL_Surface * canvas, SDL_Surface * last, int x, int y, SDL_Rect * update_rect);
void clone_release(magic_api * api, int which, SDL_Surface * canvas, SDL_Surface * last, int x, int y, SDL_Rect * update_rect);
@ -80,6 +85,8 @@ int clone_requires_colors(magic_api * api, int which);
void clone_switchin(magic_api * api, int which, int mode, SDL_Surface * canvas);
void clone_switchout(magic_api * api, int which, int mode, SDL_Surface * canvas);
int clone_modes(magic_api * api, int which);
void clone_crosshairs(magic_api * api, SDL_Surface * canvas, int x, int y);
void done_cloning(magic_api * api, SDL_Surface * canvas, SDL_Rect * update_rect);
// No setup required:
int clone_init(magic_api * api)
@ -93,6 +100,7 @@ int clone_init(magic_api * api)
clone_snd = Mix_LoadWAV(fname);
clone_state = CLONE_READY_TO_START;
clone_crosshair_visible = 0;
return (1);
}
@ -145,15 +153,18 @@ static void do_clone(void *ptr, int which ATTRIBUTE_UNUSED, SDL_Surface * canvas
srcx = clone_src_x + (x - clone_drag_start_x);
srcy = clone_src_y + (y - clone_drag_start_y);
for (yy = -16; yy < 16; yy++)
if (!api->touched(x, y))
{
for (xx = -16; xx < 16; xx++)
for (yy = -16; yy < 16; yy++)
{
if (api->in_circle(xx, yy, 16))
for (xx = -16; xx < 16; xx++)
{
SDL_GetRGB(api->getpixel(last, srcx + xx, srcy + yy), last->format, &r, &g, &b);
pixel = SDL_MapRGB(canvas->format, r, g, b);
api->putpixel(canvas, x + xx, y + yy, pixel);
if (api->in_circle(xx, yy, 16))
{
SDL_GetRGB(api->getpixel(last, srcx + xx, srcy + yy), last->format, &r, &g, &b);
pixel = SDL_MapRGB(canvas->format, r, g, b);
api->putpixel(canvas, x + xx, y + yy, pixel);
}
}
}
}
@ -161,7 +172,21 @@ static void do_clone(void *ptr, int which ATTRIBUTE_UNUSED, SDL_Surface * canvas
// Affect the canvas on drag:
void clone_drag(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * last, int ox, int oy, int x, int y, SDL_Rect * update_rect)
SDL_Surface * last ATTRIBUTE_UNUSED, int ox, int oy, int x, int y, SDL_Rect * update_rect)
{
/* Step 3 - Actively cloning (moving the mouse) */
/* Erase crosshairs at old source position */
clone_crosshairs(api, canvas, clone_src_x, clone_src_y);
clone_crosshair_visible = 0;
/* Do the cloning (and draw crosshairs at new source position) */
clone_doit(api, which, canvas, clone_last, ox, oy, x, y, update_rect, 1);
}
void clone_doit(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * last, int ox, int oy, int x, int y, SDL_Rect * update_rect,
int crosshairs)
{
if (clone_state != CLONE_CLONING)
return;
@ -170,8 +195,8 @@ void clone_drag(magic_api * api, int which, SDL_Surface * canvas,
clone_drag_start_y = oy;
api->line((void *)api, which, canvas, last, ox, oy, x, y, 1, do_clone);
// do_clone((void *)api, which, canvas, last, x, y);
/* Move source position relative to mouse motion */
clone_src_x += (x - ox);
clone_src_y += (y - oy);
@ -190,10 +215,20 @@ void clone_drag(magic_api * api, int which, SDL_Surface * canvas,
y = tmp;
}
update_rect->x = x - 64;
update_rect->y = y - 64;
update_rect->w = (ox + 128) - update_rect->x;
update_rect->h = (oy + 128) - update_rect->h;
if (crosshairs) {
clone_crosshairs(api, canvas, clone_src_x, clone_src_y);
/* FIXME be more clever */
update_rect->x = 0;
update_rect->y = 0;
update_rect->w = canvas->w;
update_rect->h = canvas->h;
clone_crosshair_visible = 1;
} else {
update_rect->x = x - 64;
update_rect->y = y - 64;
update_rect->w = (ox + 128) - update_rect->x;
update_rect->h = (oy + 128) - update_rect->h;
}
api->playsound(clone_snd, (x * 255) / canvas->w, 255);
}
@ -203,28 +238,67 @@ void clone_click(magic_api * api, int which, int mode ATTRIBUTE_UNUSED,
SDL_Surface * canvas, SDL_Surface * last, int x, int y, SDL_Rect * update_rect)
{
if (clone_state == CLONE_READY_TO_START) {
/* Step 1 - Picking a source for the clone */
clone_src_x = x;
clone_src_y = y;
clone_state = CLONE_STARTING;
api->playsound(clone_start_snd, (x * 255) / canvas->w, 255);
SDL_BlitSurface(last, NULL, clone_last, NULL);
/* Draw crosshairs at starting source position */
clone_crosshairs(api, canvas, clone_src_x, clone_src_y);
clone_crosshair_visible = 1;
update_rect->x = x - 15;
update_rect->y = y - 15;
update_rect->w = 32;
update_rect->h = 32;
} else if (clone_state == CLONE_CLONING) {
clone_drag(api, which, canvas, last, x, y, x, y, update_rect);
/* Step 2 - Starting a clone (hopefully holding mouse down here) */
clone_doit(api, which, canvas, clone_last, x, y, x, y, update_rect, 0);
}
}
void clone_release(magic_api * api, int which ATTRIBUTE_UNUSED,
SDL_Surface * canvas ATTRIBUTE_UNUSED, SDL_Surface * last ATTRIBUTE_UNUSED,
int x ATTRIBUTE_UNUSED, int y ATTRIBUTE_UNUSED, SDL_Rect * update_rect ATTRIBUTE_UNUSED)
SDL_Surface * canvas, SDL_Surface * last ATTRIBUTE_UNUSED,
int x ATTRIBUTE_UNUSED, int y ATTRIBUTE_UNUSED, SDL_Rect * update_rect)
{
if (clone_state == CLONE_STARTING) {
/* Release of the initial click (to pick initial source position);
now ready for second click (to begin cloning) */
clone_state = CLONE_CLONING;
} else {
clone_state = CLONE_READY_TO_START;
api->stopsound();
done_cloning(api, canvas, update_rect);
}
}
void done_cloning(magic_api * api, SDL_Surface * canvas, SDL_Rect * update_rect) {
/* Done cloning! */
/* Erase crosshairs from source position, now that we're all done */
if (clone_crosshair_visible)
{
clone_crosshairs(api, canvas, clone_src_x, clone_src_y);
update_rect->x = clone_src_x - 15;
update_rect->y = clone_src_y - 15;
update_rect->w = 32;
update_rect->h = 32;
clone_crosshair_visible = 0;
}
clone_state = CLONE_READY_TO_START;
api->stopsound();
}
void clone_crosshairs(magic_api * api, SDL_Surface * canvas, int x, int y) {
int i;
for (i = -15; i < 16; i++) {
api->xorpixel(canvas, x + i, y);
api->xorpixel(canvas, x, y + i);
}
}
// No setup happened:
void clone_shutdown(magic_api * api ATTRIBUTE_UNUSED)
{
if (clone_snd != NULL)
@ -233,12 +307,10 @@ void clone_shutdown(magic_api * api ATTRIBUTE_UNUSED)
Mix_FreeChunk(clone_start_snd);
}
// Record the color from Tux Paint:
void clone_set_color(magic_api * api ATTRIBUTE_UNUSED, Uint8 ATTRIBUTE_UNUSED r, Uint8 ATTRIBUTE_UNUSED g, Uint8 ATTRIBUTE_UNUSED b)
{
}
// Use colors:
int clone_requires_colors(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED)
{
return 0;
@ -247,13 +319,22 @@ int clone_requires_colors(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_
void clone_switchin(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED,
int mode ATTRIBUTE_UNUSED, SDL_Surface * canvas ATTRIBUTE_UNUSED)
{
clone_last = SDL_CreateRGBSurface(SDL_ANYFORMAT, canvas->w, canvas->h, canvas->format->BitsPerPixel,
canvas->format->Rmask, canvas->format->Gmask, canvas->format->Bmask,
canvas->format->Amask);
clone_state = CLONE_READY_TO_START;
}
void clone_switchout(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED,
int mode ATTRIBUTE_UNUSED, SDL_Surface * canvas ATTRIBUTE_UNUSED)
void clone_switchout(magic_api * api, int which ATTRIBUTE_UNUSED,
int mode ATTRIBUTE_UNUSED, SDL_Surface * canvas)
{
clone_state = CLONE_READY_TO_START;
SDL_Rect update_rect; /* Needed to satisfy done_cloning() :-( */
done_cloning(api, canvas, &update_rect);
if (clone_last != NULL)
SDL_FreeSurface(clone_last);
}
int clone_modes(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED)

View file

@ -1,6 +1,6 @@
/* halftone.c
Last modified: 2011.07.17
Last modified: 2021.02.20
*/
@ -24,7 +24,7 @@ enum
const char *snd_filenames[NUM_TOOLS] = {
"halftone.wav",
"halftone.ogg",
};
const char *icon_filenames[NUM_TOOLS] = {
@ -84,12 +84,14 @@ int halftone_init(magic_api * api)
snprintf(fname, sizeof(fname), "%ssounds/magic/%s", api->data_directory, snd_filenames[i]);
snd_effect[i] = Mix_LoadWAV(fname);
/*
if (snd_effect[i] == NULL)
{
SDL_FreeSurface(canvas_backup);
SDL_FreeSurface(square);
return (0);
}
*/
}
@ -146,8 +148,11 @@ void halftone_shutdown(magic_api * api ATTRIBUTE_UNUSED)
{
int i;
for (i = 0; i < NUM_TOOLS; i++)
Mix_FreeChunk(snd_effect[i]);
for (i = 0; i < NUM_TOOLS; i++) {
if (snd_effect[i] != NULL) {
Mix_FreeChunk(snd_effect[i]);
}
}
SDL_FreeSurface(canvas_backup);
SDL_FreeSurface(square);