Converted Blocks, Chalk, Drip, Blur, Bricks, Cartoon, Drip, Fill, Grass,

Rainbow, Smudge and Tint Magic tools to plugins.
This commit is contained in:
William Kendrick 2007-07-06 19:35:32 +00:00
parent 535220e921
commit 2d4eee798f
10 changed files with 1793 additions and 0 deletions

View file

@ -0,0 +1,246 @@
#include <stdio.h>
#include <string.h>
#include <libintl.h>
#include "tp_magic_api.h"
#include "SDL_image.h"
/* What tools we contain: */
enum {
TOOL_BLOCKS,
TOOL_CHALK,
TOOL_DRIP,
NUM_TOOLS
};
/* Our globals: */
Mix_Chunk * snd_effect[NUM_TOOLS];
// No setup required:
int blocks_chalk_drip_init(magic_api * api)
{
char fname[1024];
snprintf(fname, sizeof(fname), "%s/sounds/magic/blocks.wav",
api->data_directory);
snd_effect[0] = Mix_LoadWAV(fname);
snprintf(fname, sizeof(fname), "%s/sounds/magic/chalk.wav",
api->data_directory);
snd_effect[1] = Mix_LoadWAV(fname);
snprintf(fname, sizeof(fname), "%s/sounds/magic/drip.wav",
api->data_directory);
snd_effect[2] = Mix_LoadWAV(fname);
return(1);
}
// We have multiple tools:
int blocks_chalk_drip_get_tool_count(magic_api * api)
{
return(NUM_TOOLS);
}
// Load our icons:
SDL_Surface * blocks_chalk_drip_get_icon(magic_api * api, int which)
{
char fname[1024];
if (which == TOOL_BLOCKS)
{
snprintf(fname, sizeof(fname), "%s/images/magic/blocks.png",
api->data_directory);
}
else if (which == TOOL_CHALK)
{
snprintf(fname, sizeof(fname), "%s/images/magic/chalk.png",
api->data_directory);
}
else if (which == TOOL_DRIP)
{
snprintf(fname, sizeof(fname), "%s/images/magic/drip.png",
api->data_directory);
}
return(IMG_Load(fname));
}
// Return our names, localized:
char * blocks_chalk_drip_get_name(magic_api * api, int which)
{
if (which == TOOL_BLOCKS)
return(strdup(gettext("Blocks")));
else if (which == TOOL_CHALK)
return(strdup(gettext("Chalk")));
else if (which == TOOL_DRIP)
return(strdup(gettext("Drip")));
return(NULL);
}
// Return our descriptions, localized:
char * blocks_chalk_drip_get_description(magic_api * api, int which)
{
if (which == TOOL_BLOCKS)
return(strdup(gettext(
"Click and move the mouse around to turn the picture into a chalk drawing.")));
else if (which == TOOL_CHALK)
return(strdup(gettext(
"Click and move the mouse around to make the picture blocky.")));
else if (which == TOOL_DRIP)
return(strdup(gettext(
"Click and move the mouse around to make the picture drip.")));
return(NULL);
}
// Do the effect:
void do_example(void * ptr, int which, SDL_Surface * canvas, SDL_Surface * last,
int x, int y)
{
magic_api * api = (magic_api *) ptr;
int xx, yy;
int h;
SDL_Rect src, dest;
Uint8 r, g, b;
Uint32 colr;
if (which == TOOL_BLOCKS)
{
/* Put x/y on exact grid points: */
x = (x / 4) * 4;
y = (y / 4) * 4;
for (yy = y - 8; yy < y + 8; yy = yy + 4)
{
for (xx = x - 8; xx < x + 8; xx = xx + 4)
{
Uint32 pix[16];
Uint32 p_or = 0;
Uint32 p_and = ~0;
unsigned i = 16;
while (i--)
{
Uint32 p_tmp;
p_tmp = api->getpixel(last, xx + (i >> 2), yy + (i & 3));
p_or |= p_tmp;
p_and &= p_tmp;
pix[i] = p_tmp;
}
if (p_or == p_and) // if all pixels the same already
{
SDL_GetRGB(p_or, last->format, &r, &g, &b);
}
else // nope, must average them
{
double r_sum = 0.0;
double g_sum = 0.0;
double b_sum = 0.0;
i = 16;
while (i--)
{
SDL_GetRGB(pix[i], last->format, &r, &g, &b);
r_sum += api->sRGB_to_linear(r);
g_sum += api->sRGB_to_linear(g);
b_sum += api->sRGB_to_linear(b);
}
r = api->linear_to_sRGB(r_sum / 16.0);
g = api->linear_to_sRGB(g_sum / 16.0);
b = api->linear_to_sRGB(b_sum / 16.0);
}
/* Draw block: */
dest.x = xx;
dest.y = yy;
dest.w = 4;
dest.h = 4;
SDL_FillRect(canvas, &dest, SDL_MapRGB(canvas->format, r, g, b));
}
}
}
else if (which == TOOL_CHALK)
{
for (yy = y - 8; yy <= y + 8; yy = yy + 4)
{
for (xx = x - 8; xx <= x + 8; xx = xx + 4)
{
dest.x = xx + ((rand() % 5) - 2);
dest.y = yy + ((rand() % 5) - 2);
dest.w = (rand() % 4) + 2;
dest.h = (rand() % 4) + 2;
colr = api->getpixel(last, clamp(0, xx, canvas->w - 1),
clamp(0, yy, canvas->h - 1));
SDL_FillRect(canvas, &dest, colr);
}
}
}
else if (which == TOOL_DRIP)
{
for (xx = x - 8; xx <= x + 8; xx++)
{
h = (rand() % 8) + 8;
for (yy = y; yy <= y + h; yy++)
{
src.x = xx;
src.y = y;
src.w = 1;
src.h = 16;
dest.x = xx;
dest.y = yy;
SDL_BlitSurface(last, &src, canvas, &dest);
}
}
}
}
// Affect the canvas on drag:
void blocks_chalk_drip_drag(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * last, int ox, int oy, int x, int y)
{
api->line(which, canvas, last, ox, oy, x, y, 1, do_example);
api->playsound(snd_effect[which], (x * 255) / canvas->w, 255);
}
// Affect the canvas on click:
void blocks_chalk_drip_click(magic_api * api, int which,
SDL_Surface * canvas, SDL_Surface * last,
int x, int y)
{
blocks_chalk_drip_drag(api, which, canvas, last, x, y, x, y);
}
// No setup happened:
void blocks_chalk_drip_shutdown(magic_api * api)
{
if (snd_effect[0] != NULL)
Mix_FreeChunk(snd_effect[0]);
if (snd_effect[1] != NULL)
Mix_FreeChunk(snd_effect[1]);
}
// Record the color from Tux Paint:
void blocks_chalk_drip_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b)
{
}
// Use colors:
int blocks_chalk_drip_requires_colors(magic_api * api, int which)
{
return 0;
}

159
magic/src/blur.c Normal file
View file

@ -0,0 +1,159 @@
#include <stdio.h>
#include <string.h>
#include <libintl.h>
#include "tp_magic_api.h"
#include "SDL_image.h"
#include "SDL_mixer.h"
/* Our globals: */
Mix_Chunk * blur_snd;
int blur_init(magic_api * api)
{
char fname[1024];
snprintf(fname, sizeof(fname), "%s/sounds/magic/blur.wav",
api->data_directory);
blur_snd = Mix_LoadWAV(fname);
return(1);
}
int blur_get_tool_count(magic_api * api)
{
return(1);
}
// Load our icons:
SDL_Surface * blur_get_icon(magic_api * api, int which)
{
char fname[1024];
snprintf(fname, sizeof(fname), "%s/images/magic/blur.png",
api->data_directory);
return(IMG_Load(fname));
}
// Return our names, localized:
char * blur_get_name(magic_api * api, int which)
{
return(strdup(gettext("Blur")));
}
// Return our descriptions, localized:
char * blur_get_description(magic_api * api, int which)
{
return(strdup(gettext(
"Click and move the mouse around to blur the picture.")));
}
// Do the effect:
void do_blur(void * ptr, int which, SDL_Surface * canvas, SDL_Surface * last,
int x, int y)
{
magic_api * api = (magic_api *) ptr;
double state[32][32][3];
unsigned i;
Uint8 r, g, b;
i = 32 * 32;
while (i--)
{
int iy = i >> 5;
int ix = i & 0x1f;
// is it not on the circle of radius sqrt(220) at location 16,16?
if ((ix - 16) * (ix - 16) + (iy - 16) * (iy - 16) > 220)
continue;
// it is on the circle, so grab it
SDL_GetRGB(api->getpixel(canvas, x + ix - 16, y + iy - 16),
last->format, &r, &g, &b);
state[ix][iy][0] = api->sRGB_to_linear(r);
state[ix][iy][1] = api->sRGB_to_linear(g);
state[ix][iy][2] = api->sRGB_to_linear(b);
}
i = 32 * 32;
while (i--)
{
double lr, lg, lb; // linear red,green,blue
double weight;
int iy = i >> 5;
int ix = i & 0x1f;
int r2 = (ix - 16) * (ix - 16) + (iy - 16) * (iy - 16); // radius squared
// is it not on the circle of radius sqrt(140) at location 16,16?
if (r2 > 140)
continue;
// It is on the circle, but how strongly will it be affected?
// This is lame; we should use something like a gaussian or cosine
// via a lookup table. (inverted, because this is the center weight)
weight = r2 / 16.0 + 3.0;
// Sampling more points would be good too, though it'd be slower.
lr = state[ix][iy - 1][0]
+ state[ix - 1][iy][0] + state[ix][iy][0] * weight + state[ix +
1][iy][0]
+ state[ix][iy + 1][0];
lg = state[ix][iy - 1][1]
+ state[ix - 1][iy][1] + state[ix][iy][1] * weight + state[ix +
1][iy][1]
+ state[ix][iy + 1][1];
lb = state[ix][iy - 1][2]
+ state[ix - 1][iy][2] + state[ix][iy][2] * weight + state[ix +
1][iy][2]
+ state[ix][iy + 1][2];
lr /= weight + 4.0;
lg /= weight + 4.0;
lb /= weight + 4.0;
api->putpixel(canvas, x + ix - 16, y + iy - 16,
SDL_MapRGB(canvas->format, api->linear_to_sRGB(lr),
api->linear_to_sRGB(lg), api->linear_to_sRGB(lb)));
}
}
// Affect the canvas on drag:
void blur_drag(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * last, int ox, int oy, int x, int y)
{
api->line(which, canvas, last, ox, oy, x, y, 1, do_blur);
api->playsound(blur_snd, (x * 255) / canvas->w, 255);
}
// Affect the canvas on click:
void blur_click(magic_api * api, int which,
SDL_Surface * canvas, SDL_Surface * last,
int x, int y)
{
blur_drag(api, which, canvas, last, x, y, x, y);
}
void blur_shutdown(magic_api * api)
{
if (blur_snd != NULL)
Mix_FreeChunk(blur_snd);
}
// Record the color from Tux Paint:
void blur_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b)
{
}
// Use colors:
int blur_requires_colors(magic_api * api, int which)
{
return 0;
}

247
magic/src/bricks.c Normal file
View file

@ -0,0 +1,247 @@
#include <stdio.h>
#include <string.h>
#include <libintl.h>
#include "tp_magic_api.h"
#include "SDL_image.h"
#include "SDL_mixer.h"
/* What tools we contain: */
enum {
TOOL_LARGEBRICKS,
TOOL_SMALLBRICKS,
NUM_TOOLS
};
/* Our globals: */
Mix_Chunk * brick_snd;
Uint8 bricks_r, bricks_g, bricks_b;
/* Local function prototype: */
void do_brick(magic_api * api, SDL_Surface * canvas,
int x, int y, int w, int h);
// No setup required:
int bricks_init(magic_api * api)
{
char fname[1024];
snprintf(fname, sizeof(fname), "%s/sounds/magic/brick.wav",
api->data_directory);
brick_snd = Mix_LoadWAV(fname);
return(1);
}
// We have multiple tools:
int bricks_get_tool_count(magic_api * api)
{
return(NUM_TOOLS);
}
// Load our icons:
SDL_Surface * bricks_get_icon(magic_api * api, int which)
{
char fname[1024];
if (which == TOOL_LARGEBRICKS)
{
snprintf(fname, sizeof(fname), "%s/images/magic/largebrick.png",
api->data_directory);
}
else if (which == TOOL_SMALLBRICKS)
{
snprintf(fname, sizeof(fname), "%s/images/magic/smallbrick.png",
api->data_directory);
}
return(IMG_Load(fname));
}
// Return our names, localized:
char * bricks_get_name(magic_api * api, int which)
{
/* Both are named "Bricks", at the moment: */
return(strdup(gettext("Bricks")));
}
// Return our descriptions, localized:
char * bricks_get_description(magic_api * api, int which)
{
if (which == TOOL_LARGEBRICKS)
return(strdup(gettext("Click and move to draw large bricks.")));
else if (which == TOOL_SMALLBRICKS)
return(strdup(gettext("Click and move to draw small bricks.")));
return(NULL);
}
// Do the effect:
void do_bricks(void * ptr, int which, SDL_Surface * canvas, SDL_Surface * last,
int x, int y)
{
magic_api * api = (magic_api *) ptr;
// "specified" means the brick itself, w/o morter
// "nominal" means brick-to-brick (includes morter)
int specified_width, specified_height, specified_length;
int nominal_length;
int brick_x, brick_y;
int vertical_joint = 2; // between a brick and the one above/below
int horizontal_joint = 2; // between a brick and the one to the side
int nominal_width = 18;
int nominal_height = 12; // 11 to 14, for joints of 2
static unsigned char *map;
static int x_count;
static int y_count;
unsigned char *mybrick;
if (which == TOOL_LARGEBRICKS)
{
vertical_joint = 4; // between a brick and the one above/below
horizontal_joint = 4; // between a brick and the one to the side
nominal_width = 36;
nominal_height = 24; // 11 to 14, for joints of 2
}
nominal_length = 2 * nominal_width;
specified_width = nominal_width - horizontal_joint;
specified_height = nominal_height - vertical_joint;
specified_length = nominal_length - horizontal_joint;
if (!api->button_down())
{
if (map)
free(map);
// the "+ 3" allows for both ends and misalignment
x_count = (canvas->w + nominal_width - 1) / nominal_width + 3;
y_count = (canvas->h + nominal_height - 1) / nominal_height + 3;
map = calloc(x_count, y_count);
}
brick_x = x / nominal_width;
brick_y = y / nominal_height;
mybrick = map + brick_x + 1 + (brick_y + 1) * x_count;
if ((unsigned) x < (unsigned) canvas->w
&& (unsigned) y < (unsigned) canvas->h && !*mybrick)
{
int my_x = brick_x * nominal_width;
int my_w = specified_width;
*mybrick = 1;
// FIXME:
//SDL_LockSurface(canvas);
if ((brick_y ^ brick_x) & 1)
{
if (mybrick[1])
my_w = specified_length;
}
else if (mybrick[-1])
{
my_x -= nominal_width;
my_w = specified_length;
}
do_brick(api, canvas, my_x, brick_y * nominal_height,
my_w, specified_height);
// FIXME:
// SDL_UnlockSurface(canvas);
// upper left corner and lower right corner
// FIXME
/*
update_canvas(brick_x * nominal_width - nominal_width,
brick_y * nominal_height - vertical_joint,
brick_x * nominal_width + specified_length,
(brick_y + 1) * nominal_height);
*/
}
}
// Affect the canvas on drag:
void bricks_drag(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * last, int ox, int oy, int x, int y)
{
api->line(which, canvas, last, ox, oy, x, y, 1, do_bricks);
api->playsound(brick_snd, (x * 255) / canvas->w, 255);
}
// Affect the canvas on click:
void bricks_click(magic_api * api, int which,
SDL_Surface * canvas, SDL_Surface * last,
int x, int y)
{
bricks_drag(api, which, canvas, last, x, y, x, y);
}
// No setup happened:
void bricks_shutdown(magic_api * api)
{
if (brick_snd != NULL)
Mix_FreeChunk(brick_snd);
}
// Record the color from Tux Paint:
void bricks_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b)
{
bricks_r = r;
bricks_g = g;
bricks_b = b;
}
// Use colors:
int bricks_requires_colors(magic_api * api, int which)
{
return 1;
}
void do_brick(magic_api * api, SDL_Surface * canvas,
int x, int y, int w, int h)
{
SDL_Rect dest;
// brick color: 127,76,73
double ran_r = rand() / (double) RAND_MAX;
double ran_g = rand() / (double) RAND_MAX;
double base_r =
api->sRGB_to_linear(bricks_r) * 1.5 +
api->sRGB_to_linear(127) * 5.0 + ran_r;
double base_g =
api->sRGB_to_linear(bricks_g) * 1.5 +
api->sRGB_to_linear(76) * 5.0 + ran_g;
double base_b =
api->sRGB_to_linear(bricks_b) * 1.5 +
api->sRGB_to_linear(73) * 5.0 + (ran_r + ran_g * 2.0) / 3.0;
Uint8 r = api->linear_to_sRGB(base_r / 7.5);
Uint8 g = api->linear_to_sRGB(base_g / 7.5);
Uint8 b = api->linear_to_sRGB(base_b / 7.5);
dest.x = x;
dest.y = y;
dest.w = w;
dest.h = h;
SDL_FillRect(canvas, &dest, SDL_MapRGB(canvas->format, r, g, b));
/* Note: We only play the brick sound when we actually DRAW a brick: */
api->playsound(brick_snd, (x * 255) / canvas->w, 255);
}

178
magic/src/cartoon.c Normal file
View file

@ -0,0 +1,178 @@
#include <stdio.h>
#include <string.h>
#include <libintl.h>
#include <math.h>
#include "tp_magic_api.h"
#include "SDL_image.h"
#include "SDL_mixer.h"
/* Our globals: */
Mix_Chunk * cartoon_snd;
#define OUTLINE_THRESH 48
// No setup required:
int cartoon_init(magic_api * api)
{
char fname[1024];
snprintf(fname, sizeof(fname), "%s/sounds/magic/cartoon.wav",
api->data_directory);
cartoon_snd = Mix_LoadWAV(fname);
return(1);
}
// We have multiple tools:
int cartoon_get_tool_count(magic_api * api)
{
return(1);
}
// Load our icons:
SDL_Surface * cartoon_get_icon(magic_api * api, int which)
{
char fname[1024];
snprintf(fname, sizeof(fname), "%s/images/magic/cartoon.png",
api->data_directory);
return(IMG_Load(fname));
}
// Return our names, localized:
char * cartoon_get_name(magic_api * api, int which)
{
return(strdup(gettext("Cartoon")));
}
// Return our descriptions, localized:
char * cartoon_get_description(magic_api * api, int which)
{
return(strdup(gettext(
"Click and move the mouse around to turn the picture into a cartoon.")));
}
// Do the effect:
void do_cartoon(void * ptr, int which, SDL_Surface * canvas, SDL_Surface * last,
int x, int y)
{
magic_api * api = (magic_api *) ptr;
int xx, yy;
Uint8 r1, g1, b1, r2, g2, b2;
Uint8 r, g, b;
float hue, sat, val;
/* First, convert colors to more cartoony ones: */
for (yy = y - 16; yy < y + 16; yy = yy + 1)
{
for (xx = x - 16; xx < x + 16; xx = xx + 1)
{
if (api->in_circle(xx - x, yy - y, 16))
{
/* Get original color: */
SDL_GetRGB(api->getpixel(last, xx, yy), last->format, &r, &g, &b);
api->rgbtohsv(r, g, b, &hue, &sat, &val);
val = val - 0.5;
val = val * 4;
val = val + 0.5;
if (val < 0)
val = 0;
else if (val > 1.0)
val = 1.0;
val = floor(val * 4) / 4;
hue = floor(hue * 4) / 4;
sat = floor(sat * 4) / 4;
api->hsvtorgb(hue, sat, val, &r, &g, &b);
api->putpixel(canvas, xx, yy, SDL_MapRGB(canvas->format, r, g, b));
}
}
}
/* Then, draw dark outlines where there's a large contrast change */
for (yy = y - 16; yy < y + 16; yy++)
{
for (xx = x - 16; xx < x + 16; xx++)
{
if (api->in_circle(xx - x, yy - y, 16))
{
/* Get original color: */
SDL_GetRGB(api->getpixel(last, xx, yy), last->format, &r, &g, &b);
SDL_GetRGB(api->getpixel(last, xx + 1, yy),
last->format, &r1, &g1, &b1);
SDL_GetRGB(api->getpixel(last, xx + 1, yy + 1),
last->format, &r2, &g2, &b2);
if (abs(((r + g + b) / 3) - (r1 + g1 + b1) / 3) > OUTLINE_THRESH
|| abs(((r + g + b) / 3) - (r2 + g2 + b2) / 3) >
OUTLINE_THRESH || abs(r - r1) > OUTLINE_THRESH
|| abs(g - g1) > OUTLINE_THRESH
|| abs(b - b1) > OUTLINE_THRESH
|| abs(r - r2) > OUTLINE_THRESH
|| abs(g - g2) > OUTLINE_THRESH
|| abs(b - b2) > OUTLINE_THRESH)
{
api->putpixel(canvas, xx - 1, yy,
SDL_MapRGB(canvas->format, 0, 0, 0));
api->putpixel(canvas, xx, yy - 1,
SDL_MapRGB(canvas->format, 0, 0, 0));
api->putpixel(canvas, xx - 1, yy - 1,
SDL_MapRGB(canvas->format, 0, 0, 0));
}
}
}
}
}
// Affect the canvas on drag:
void cartoon_drag(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * last, int ox, int oy, int x, int y)
{
api->line(which, canvas, last, ox, oy, x, y, 1, do_cartoon);
api->playsound(cartoon_snd, (x * 255) / canvas->w, 255);
}
// Affect the canvas on click:
void cartoon_click(magic_api * api, int which,
SDL_Surface * canvas, SDL_Surface * last,
int x, int y)
{
cartoon_drag(api, which, canvas, last, x, y, x, y);
}
// No setup happened:
void cartoon_shutdown(magic_api * api)
{
if (cartoon_snd != NULL)
Mix_FreeChunk(cartoon_snd);
}
// Record the color from Tux Paint:
void cartoon_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b)
{
}
// Use colors:
int cartoon_requires_colors(magic_api * api, int which)
{
return 0;
}

156
magic/src/drip.c Normal file
View file

@ -0,0 +1,156 @@
#include <stdio.h>
#include <string.h>
#include <libintl.h>
#include "tp_magic_api.h"
#include "SDL_image.h"
#include "SDL_mixer.h"
/* What tools we contain: */
enum {
TOOL_ONE,
TOOL_TWO,
NUM_TOOLS
};
/* Our globals: */
Mix_Chunk * snd_effect[NUM_TOOLS];
Uint8 example_r, example_g, example_b;
// No setup required:
int example_init(magic_api * api)
{
char fname[1024];
snprintf(fname, sizeof(fname), "%s/sounds/magic/one.wav",
api->data_directory);
snd_effect[0] = Mix_LoadWAV(fname);
snprintf(fname, sizeof(fname), "%s/sounds/magic/two.wav",
api->data_directory);
snd_effect[1] = Mix_LoadWAV(fname);
return(1);
}
// We have multiple tools:
int example_get_tool_count(magic_api * api)
{
return(NUM_TOOLS);
}
// Load our icons:
SDL_Surface * example_get_icon(magic_api * api, int which)
{
char fname[1024];
if (which == TOOL_ONE)
{
snprintf(fname, sizeof(fname), "%s/images/magic/one.png",
api->data_directory);
}
else if (which == TOOL_TWO)
{
snprintf(fname, sizeof(fname), "%s/images/magic/two.png",
api->data_directory);
}
return(IMG_Load(fname));
}
// Return our names, localized:
char * example_get_name(magic_api * api, int which)
{
if (which == TOOL_ONE)
return(strdup(gettext("One")));
else if (which == TOOL_TWO)
return(strdup(gettext("Two")));
return(NULL);
}
// Return our descriptions, localized:
char * example_get_description(magic_api * api, int which)
{
if (which == TOOL_ONE)
return(strdup(gettext("Tool one.")));
else
return(strdup(gettext("Tool two.")));
return(NULL);
}
// Do the effect:
void do_example(void * ptr, int which, SDL_Surface * canvas, SDL_Surface * last,
int x, int y)
{
magic_api * api = (magic_api *) ptr;
int xx, yy;
if (which == TOOL_ONE)
{
api->putpixel(canvas, x, y, SDL_MapRGB(canvas->format,
example_r,
example_g,
example_b));
}
else if (which == TOOL_TWO)
{
for (yy = -4; yy < 4; yy++)
{
for (xx = -4; xx < 4; xx++)
{
api->putpixel(canvas, x + xx, y + yy,
api->getpixel(last,
canvas->w - x - xx,
canvas->h - y - yy));
}
}
}
}
// Affect the canvas on drag:
void example_drag(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * last, int ox, int oy, int x, int y)
{
api->line(which, canvas, last, ox, oy, x, y, 1, do_example);
api->playsound(snd_effect[which], (x * 255) / canvas->w, 255);
}
// Affect the canvas on click:
void example_click(magic_api * api, int which,
SDL_Surface * canvas, SDL_Surface * last,
int x, int y)
{
example_drag(api, which, canvas, last, x, y, x, y);
}
// No setup happened:
void example_shutdown(magic_api * api)
{
if (snd_effect[0] != NULL)
Mix_FreeChunk(snd_effect[0]);
if (snd_effect[1] != NULL)
Mix_FreeChunk(snd_effect[1]);
}
// Record the color from Tux Paint:
void example_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b)
{
example_r = r;
example_g = g;
example_b = b;
}
// Use colors:
int example_requires_colors(magic_api * api, int which)
{
return 1;
}

203
magic/src/fill.c Normal file
View file

@ -0,0 +1,203 @@
#include <stdio.h>
#include <string.h>
#include <libintl.h>
#include "tp_magic_api.h"
#include "SDL_image.h"
/* Our globals: */
Mix_Chunk * fill_snd;
Uint8 fill_r, fill_g, fill_b;
/* Local function prototypes: */
static int colors_close(magic_api * api, SDL_Surface * canvas,
Uint32 c1, Uint32 c2);
void do_flood_fill(magic_api * api, SDL_Surface * canvas, int x, int y,
Uint32 cur_colr, Uint32 old_colr);
// No setup required:
int fill_init(magic_api * api)
{
char fname[1024];
snprintf(fname, sizeof(fname), "%s/sounds/magic/fill.wav",
api->data_directory);
fill_snd = Mix_LoadWAV(fname);
return(1);
}
// We have multiple tools:
int fill_get_tool_count(magic_api * api)
{
return(1);
}
// Load our icons:
SDL_Surface * fill_get_icon(magic_api * api, int which)
{
char fname[1024];
snprintf(fname, sizeof(fname), "%s/images/magic/fill.png",
api->data_directory);
return(IMG_Load(fname));
}
// Return our names, localized:
char * fill_get_name(magic_api * api, int which)
{
return(strdup(gettext("Fill")));
}
// Return our descriptions, localized:
char * fill_get_description(magic_api * api, int which)
{
return(strdup(gettext(
"Click in the picture to fill that area with color.")));
}
// Affect the canvas on drag:
void fill_drag(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * last, int ox, int oy, int x, int y)
{
}
// Affect the canvas on click:
void fill_click(magic_api * api, int which,
SDL_Surface * canvas, SDL_Surface * last,
int x, int y)
{
do_flood_fill(api, canvas, x, y, SDL_MapRGB(canvas->format,
fill_r, fill_g, fill_b),
api->getpixel(canvas, x, y));
}
// No setup happened:
void fill_shutdown(magic_api * api)
{
Mix_FreeChunk(fill_snd);
}
// Record the color from Tux Paint:
void fill_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b)
{
fill_r = r;
fill_g = g;
fill_b = b;
}
// Use colors:
int fill_requires_colors(magic_api * api, int which)
{
return 1;
}
static int colors_close(magic_api * api, SDL_Surface * canvas,
Uint32 c1, Uint32 c2)
{
Uint8 r1, g1, b1, r2, g2, b2;
if (c1 == c2)
{
/* Get it over with quick, if possible! */
return 1;
}
else
{
double r, g, b;
SDL_GetRGB(c1, canvas->format, &r1, &g1, &b1);
SDL_GetRGB(c2, canvas->format, &r2, &g2, &b2);
// use distance in linear RGB space
r = api->sRGB_to_linear(r1) - api->sRGB_to_linear(r2);
r *= r;
g = api->sRGB_to_linear(g1) - api->sRGB_to_linear(g2);
g *= g;
b = api->sRGB_to_linear(b1) - api->sRGB_to_linear(b2);
b *= b;
// easy to confuse:
// dark grey, brown, purple
// light grey, tan
// red, orange
return r + g + b < 0.04;
}
}
void do_flood_fill(magic_api * api, SDL_Surface * canvas, int x, int y,
Uint32 cur_colr, Uint32 old_colr)
{
int fillL, fillR, i, in_line;
static unsigned char prog_anim;
if (cur_colr == old_colr || colors_close(api, canvas, cur_colr, old_colr))
return;
fillL = x;
fillR = x;
prog_anim++;
if ((prog_anim % 4) == 0)
{
api->update_progress_bar();
api->playsound(fill_snd, (x * 255) / canvas->w, 255);
}
/* Find left side, filling along the way */
in_line = 1;
while (in_line)
{
api->putpixel(canvas, fillL, y, cur_colr);
fillL--;
in_line =
(fillL < 0) ? 0 : colors_close(api, canvas,
api->getpixel(canvas, fillL, y),
old_colr);
}
fillL++;
/* Find right side, filling along the way */
in_line = 1;
while (in_line)
{
api->putpixel(canvas, fillR, y, cur_colr);
fillR++;
in_line = (fillR >= canvas->w) ? 0 : colors_close(api, canvas,
api->getpixel(canvas, fillR, y),
old_colr);
}
fillR--;
/* Search top and bottom */
for (i = fillL; i <= fillR; i++)
{
if (y > 0 && colors_close(api, canvas, api->getpixel(canvas, i, y - 1),
old_colr))
do_flood_fill(api, canvas, i, y - 1, cur_colr, old_colr);
if (y < canvas->h
&& colors_close(api, canvas, api->getpixel(canvas, i, y + 1), old_colr))
do_flood_fill(api, canvas, i, y + 1, cur_colr, old_colr);
}
}

199
magic/src/grass.c Normal file
View file

@ -0,0 +1,199 @@
#include <stdio.h>
#include <string.h>
#include <libintl.h>
#include "tp_magic_api.h"
#include "SDL_image.h"
#include "SDL_mixer.h"
/* Our globals: */
Mix_Chunk * grass_snd;
Uint8 grass_r, grass_g, grass_b;
SDL_Surface * img_grass;
/* Local prototypes: */
void do_grass(void * ptr, int which,
SDL_Surface * canvas, SDL_Surface * last,
int x, int y);
static int log2int(int x);
// No setup required:
int grass_init(magic_api * api)
{
char fname[1024];
snprintf(fname, sizeof(fname), "%s/sounds/magic/grass.wav",
api->data_directory);
grass_snd = Mix_LoadWAV(fname);
snprintf(fname, sizeof(fname), "%s/images/magic/grass_data.png",
api->data_directory);
img_grass = IMG_Load(fname);
return(1);
}
// We have multiple tools:
int grass_get_tool_count(magic_api * api)
{
return(1);
}
// Load our icons:
SDL_Surface * grass_get_icon(magic_api * api, int which)
{
char fname[1024];
snprintf(fname, sizeof(fname), "%s/images/magic/grass.png",
api->data_directory);
return(IMG_Load(fname));
}
// Return our names, localized:
char * grass_get_name(magic_api * api, int which)
{
return(strdup(gettext("Grass")));
}
// Return our descriptions, localized:
char * grass_get_description(magic_api * api, int which)
{
return(strdup(gettext("Click and move to draw grass. Dont forget the dirt!")));
}
// Affect the canvas on drag:
void grass_drag(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * last, int ox, int oy, int x, int y)
{
api->line(which, canvas, last, ox, oy, x, y, 4, do_grass);
api->playsound(grass_snd,
(x * 255) / canvas->w, (y * 255) / canvas->h);
}
// Affect the canvas on click:
void grass_click(magic_api * api, int which,
SDL_Surface * canvas, SDL_Surface * last,
int x, int y)
{
grass_drag(api, which, canvas, last, x, y, x, y);
}
// No setup happened:
void grass_shutdown(magic_api * api)
{
if (grass_snd != NULL)
Mix_FreeChunk(grass_snd);
}
// Record the color from Tux Paint:
void grass_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b)
{
grass_r = r;
grass_g = g;
grass_b = b;
}
// Use colors:
int grass_requires_colors(magic_api * api, int which)
{
return 1;
}
void do_grass(void * ptr, int which,
SDL_Surface * canvas, SDL_Surface * last,
int x, int y)
{
magic_api * api = (magic_api *) ptr;
int xx, yy;
// grass color: 82,180,17
static int bucket;
double tmp_red, tmp_green, tmp_blue;
Uint8 r, g, b, a;
SDL_Rect src, dest;
if (!api->button_down())
bucket = 0;
bucket += (3.5 + (rand() / (double) RAND_MAX)) * 7.0;
while (bucket >= 0)
{
int rank =
log2int(((double) y / canvas->h) *
(0.99 + (rand() / (double) RAND_MAX)) * 64);
int ah = 1 << rank;
bucket -= ah;
src.x = (rand() % 4) * 64;
src.y = ah;
src.w = 64;
src.h = ah;
dest.x = x - 32;
dest.y = y - 30 + (int) ((rand() / (double) RAND_MAX) * 30);
tmp_red =
api->sRGB_to_linear(grass_r) * 2.0 +
(rand() / (double) RAND_MAX);
tmp_green =
api->sRGB_to_linear(grass_g) * 2.0 +
(rand() / (double) RAND_MAX);
tmp_blue =
api->sRGB_to_linear(grass_b) * 2.0 +
api->sRGB_to_linear(17);
for (yy = 0; yy < ah; yy++)
{
for (xx = 0; xx < 64; xx++)
{
double rd, gd, bd;
SDL_GetRGBA(api->getpixel(img_grass, xx + src.x, yy + src.y),
img_grass->format, &r, &g, &b, &a);
rd = api->sRGB_to_linear(r) * 8.0 + tmp_red;
rd = rd * (a / 255.0) / 11.0;
gd = api->sRGB_to_linear(g) * 8.0 + tmp_green;
gd = gd * (a / 255.0) / 11.0;
bd = api->sRGB_to_linear(b) * 8.0 + tmp_blue;
bd = bd * (a / 255.0) / 11.0;
SDL_GetRGB(api->getpixel(canvas, xx + dest.x, yy + dest.y),
canvas->format, &r, &g, &b);
r =
api->linear_to_sRGB(api->sRGB_to_linear(r) * (1.0 - a / 255.0) +
rd);
g =
api->linear_to_sRGB(api->sRGB_to_linear(g) * (1.0 - a / 255.0) +
gd);
b =
api->linear_to_sRGB(api->sRGB_to_linear(b) * (1.0 - a / 255.0) +
bd);
api->putpixel(canvas, xx + dest.x, yy + dest.y,
SDL_MapRGB(canvas->format, r, g, b));
}
}
}
}
// this one rounds down
static int log2int(int x)
{
int y = 0;
if (x <= 1)
return 0;
x >>= 1;
while (x)
{
x >>= 1;
y++;
}
return y;
}

147
magic/src/rainbow.c Normal file
View file

@ -0,0 +1,147 @@
#include <stdio.h>
#include <string.h>
#include <libintl.h>
#include "tp_magic_api.h"
#include "SDL_image.h"
#include "SDL_mixer.h"
/* Our globals: */
#define NUM_RAINBOW_COLORS 23
const int rainbow_hexes[NUM_RAINBOW_COLORS][3] = {
{255, 0, 0},
{255, 64, 0},
{255, 128, 0},
{255, 192, 0},
{255, 255, 0},
{192, 255, 0},
{128, 255, 0},
{64, 255, 0},
{0, 255, 0},
{0, 255, 64},
{0, 255, 128},
{0, 255, 192},
{0, 255, 255},
{0, 192, 255},
{0, 128, 255},
{0, 64, 255},
{64, 0, 255},
{128, 0, 255},
{192, 0, 255},
{255, 0, 255},
{255, 0, 192},
{255, 0, 128},
{255, 0, 64}
};
int rainbow_color;
Uint32 rainbow_rgb;
Mix_Chunk * rainbow_snd;
// Load our sfx:
int rainbow_init(magic_api * api)
{
char fname[1024];
rainbow_color = 0;
snprintf(fname, sizeof(fname), "%s/sounds/magic/rainbow.wav",
api->data_directory);
rainbow_snd = Mix_LoadWAV(fname);
return(1);
}
// We have multiple tools:
int rainbow_get_tool_count(magic_api * api)
{
return(1);
}
// Load our icons:
SDL_Surface * rainbow_get_icon(magic_api * api, int which)
{
char fname[1024];
snprintf(fname, sizeof(fname), "%s/images/magic/rainbow.png",
api->data_directory);
return(IMG_Load(fname));
}
// Return our names, localized:
char * rainbow_get_name(magic_api * api, int which)
{
return(strdup(gettext("Rainbow")));
}
// Return our descriptions, localized:
char * rainbow_get_description(magic_api * api, int which)
{
return(strdup(
gettext("You can draw in rainbow colors!")));
}
// Do the effect:
void do_example(void * ptr, int which, SDL_Surface * canvas, SDL_Surface * last,
int x, int y)
{
magic_api * api = (magic_api *) ptr;
int xx, yy;
for (yy = y - 16; yy < y + 16; yy++)
{
for (xx = x - 16; xx < x + 16; xx++)
{
if (api->in_circle(xx - x, yy - y, 16))
{
api->putpixel(canvas, xx, yy, rainbow_rgb);
}
}
}
}
// Affect the canvas on drag:
void rainbow_drag(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * last, int ox, int oy, int x, int y)
{
rainbow_color = (rainbow_color + 1) % NUM_RAINBOW_COLORS;
rainbow_rgb = SDL_MapRGB(canvas->format,
rainbow_hexes[rainbow_color][0],
rainbow_hexes[rainbow_color][1],
rainbow_hexes[rainbow_color][2]);
api->line(which, canvas, last, ox, oy, x, y, 1, do_example);
api->playsound(rainbow_snd, (x * 255) / canvas->w, 255);
}
// Affect the canvas on click:
void rainbow_click(magic_api * api, int which,
SDL_Surface * canvas, SDL_Surface * last,
int x, int y)
{
rainbow_drag(api, which, canvas, last, x, y, x, y);
}
// Clean up
void rainbow_shutdown(magic_api * api)
{
if (rainbow_snd != NULL)
Mix_FreeChunk(rainbow_snd);
}
// Record the color from Tux Paint:
void rainbow_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b)
{
}
// Use colors:
int rainbow_requires_colors(magic_api * api, int which)
{
return 0;
}

127
magic/src/smudge.c Normal file
View file

@ -0,0 +1,127 @@
#include <stdio.h>
#include <string.h>
#include <libintl.h>
#include "tp_magic_api.h"
#include "SDL_image.h"
#include "SDL_mixer.h"
/* Our globals: */
Mix_Chunk * smudge_snd;
// No setup required:
int smudge_init(magic_api * api)
{
char fname[1024];
snprintf(fname, sizeof(fname), "%s/sounds/magic/smudge.wav",
api->data_directory);
smudge_snd = Mix_LoadWAV(fname);
return(1);
}
// We have multiple tools:
int smudge_get_tool_count(magic_api * api)
{
return(1);
}
// Load our icons:
SDL_Surface * smudge_get_icon(magic_api * api, int which)
{
char fname[1024];
snprintf(fname, sizeof(fname), "%s/images/magic/smudge.png",
api->data_directory);
return(IMG_Load(fname));
}
// Return our names, localized:
char * smudge_get_name(magic_api * api, int which)
{
return(strdup(gettext("Smudge")));
}
// Return our descriptions, localized:
char * smudge_get_description(magic_api * api, int which)
{
return(strdup(gettext(
"Click and move the mouse around to smudge the picture.")));
}
// Do the effect:
void do_smudge(void * ptr, int which, SDL_Surface * canvas, SDL_Surface * last,
int x, int y)
{
magic_api * api = (magic_api *) ptr;
static double state[32][32][3];
unsigned i = 32 * 32;
double rate = api->button_down() ? 0.5 : 0.0;
Uint8 r, g, b;
while (i--)
{
int iy = i >> 5;
int ix = i & 0x1f;
// is it not on the circle of radius sqrt(120) at location 16,16?
if ((ix - 16) * (ix - 16) + (iy - 16) * (iy - 16) > 120)
continue;
// it is on the circle, so grab it
SDL_GetRGB(api->getpixel(canvas, x + ix - 16, y + iy - 16),
last->format, &r, &g, &b);
state[ix][iy][0] =
rate * state[ix][iy][0] + (1.0 - rate) * api->sRGB_to_linear(r);
state[ix][iy][1] =
rate * state[ix][iy][1] + (1.0 - rate) * api->sRGB_to_linear(g);
state[ix][iy][2] =
rate * state[ix][iy][2] + (1.0 - rate) * api->sRGB_to_linear(b);
// opacity 100% --> new data not blended w/ existing data
api->putpixel(canvas, x + ix - 16, y + iy - 16,
SDL_MapRGB(canvas->format, api->linear_to_sRGB(state[ix][iy][0]),
api->linear_to_sRGB(state[ix][iy][1]),
api->linear_to_sRGB(state[ix][iy][2])));
}
}
// Affect the canvas on drag:
void smudge_drag(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * last, int ox, int oy, int x, int y)
{
api->line(which, canvas, last, ox, oy, x, y, 1, do_smudge);
api->playsound(smudge_snd, (x * 255) / canvas->w, 255);
}
// Affect the canvas on click:
void smudge_click(magic_api * api, int which,
SDL_Surface * canvas, SDL_Surface * last,
int x, int y)
{
smudge_drag(api, which, canvas, last, x, y, x, y);
}
// No setup happened:
void smudge_shutdown(magic_api * api)
{
if (smudge_snd != NULL)
Mix_FreeChunk(smudge_snd);
}
// Record the color from Tux Paint:
void smudge_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b)
{
}
// Use colors:
int smudge_requires_colors(magic_api * api, int which)
{
return 0;
}

131
magic/src/tint.c Normal file
View file

@ -0,0 +1,131 @@
#include <stdio.h>
#include <string.h>
#include <libintl.h>
#include "tp_magic_api.h"
#include "SDL_image.h"
#include "SDL_mixer.h"
/* Our globals: */
Mix_Chunk * tint_snd;
Uint8 tint_r, tint_g, tint_b;
// No setup required:
int tint_init(magic_api * api)
{
char fname[1024];
snprintf(fname, sizeof(fname), "%s/sounds/magic/tint.wav",
api->data_directory);
tint_snd = Mix_LoadWAV(fname);
return(1);
}
// We have multiple tools:
int tint_get_tool_count(magic_api * api)
{
return(1);
}
// Load our icons:
SDL_Surface * tint_get_icon(magic_api * api, int which)
{
char fname[1024];
snprintf(fname, sizeof(fname), "%s/images/magic/tint.png",
api->data_directory);
return(IMG_Load(fname));
}
// Return our names, localized:
char * tint_get_name(magic_api * api, int which)
{
return(strdup(gettext("Tint")));
}
// Return our descriptions, localized:
char * tint_get_description(magic_api * api, int which)
{
return(strdup(gettext(
"Click and move the mouse around to change the pictures color.")));
}
// Do the effect:
void do_tint(void * ptr, int which, SDL_Surface * canvas, SDL_Surface * last,
int x, int y)
{
magic_api * api = (magic_api *) ptr;
double rd = api->sRGB_to_linear(tint_r);
double gd = api->sRGB_to_linear(tint_g);
double bd = api->sRGB_to_linear(tint_b);
double old;
int xx, yy;
Uint8 r, g, b;
for (yy = y - 16; yy < y + 16; yy++)
{
for (xx = x - 16; xx < x + 16; xx++)
{
if (api->in_circle(xx - x, yy - y, 16))
{
/* Get original pixel: */
SDL_GetRGB(api->getpixel(last, xx, yy), last->format, &r, &g, &b);
old = api->sRGB_to_linear(r) * 0.2126 +
api->sRGB_to_linear(g) * 0.7152 +
api->sRGB_to_linear(b) * 0.0722;
api->putpixel(canvas, xx, yy,
SDL_MapRGB(canvas->format,
api->linear_to_sRGB(rd * old),
api->linear_to_sRGB(gd * old),
api->linear_to_sRGB(bd * old)));
}
}
}
}
// Affect the canvas on drag:
void tint_drag(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * last, int ox, int oy, int x, int y)
{
api->line(which, canvas, last, ox, oy, x, y, 1, do_tint);
api->playsound(tint_snd, (x * 255) / canvas->w, 255);
}
// Affect the canvas on click:
void tint_click(magic_api * api, int which,
SDL_Surface * canvas, SDL_Surface * last,
int x, int y)
{
tint_drag(api, which, canvas, last, x, y, x, y);
}
// No setup happened:
void tint_shutdown(magic_api * api)
{
if (tint_snd != NULL)
Mix_FreeChunk(tint_snd);
}
// Record the color from Tux Paint:
void tint_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b)
{
tint_r = r;
tint_g = g;
tint_b = b;
}
// Use colors:
int tint_requires_colors(magic_api * api, int which)
{
return 1;
}