diff --git a/docs/CHANGES.txt b/docs/CHANGES.txt index adb82c8cc..6e714fa4f 100644 --- a/docs/CHANGES.txt +++ b/docs/CHANGES.txt @@ -8,7 +8,7 @@ http://www.tuxpaint.org/ $Id$ -2008.July.09 (0.9.21) +2008.July.10 (0.9.21) * New Starters: ------------- * Silver Frame @@ -16,8 +16,19 @@ $Id$ * New Magic Tools: ---------------- - * BlurAll, Sharpen and BlackandWhite - Andrew Corcoran + * + BlurAll - Blurs entire image + + Sharpen - Sharpens entire image + + Trace Contour - Traces the edges of the image, over a white background. + + Silhouette - Creates an outline of the image, over a black background. + + Black & White - Removes all color from the image (turns it greyscale). + + Threshold - Turns image pure black & pure white (no grey or color). + By Andrew 'akanewbie' Corcoran + (Part of Tux4Kids' participation in Google Summer of Code 2008) + + * + Confetti - Paints random confetti bits on the canvas. + + Fold - Folds the corners of the image up, like a piece of paper. + By Adam 'foo-script' Rakowski + (Part of Tux4Kids' participation in Google Summer of Code 2008) * Magic Tool Improvememnts: -------------------------- diff --git a/magic/icons/confetti.png b/magic/icons/confetti.png new file mode 100644 index 000000000..fc82ff689 Binary files /dev/null and b/magic/icons/confetti.png differ diff --git a/magic/icons/fold.png b/magic/icons/fold.png new file mode 100644 index 000000000..a38c7032a Binary files /dev/null and b/magic/icons/fold.png differ diff --git a/magic/src/confetti.c b/magic/src/confetti.c new file mode 100644 index 000000000..981efed57 --- /dev/null +++ b/magic/src/confetti.c @@ -0,0 +1,188 @@ +#include //For time() + +#include "tp_magic_api.h" +#include "SDL_image.h" +#include "SDL_mixer.h" + +#define CONFETTI_BRUSH_SIZE 8 //radius of each confetti circle +#define CONFETTI_QUANTITY 3 //how many circles will be created every click? + +struct confetti_rgb +{ + Uint8 r, g, b; +}; + +struct confetti_rgb confetti_colors; //storage for colors, just for having everything in one place + +Mix_Chunk * confetti_snd; + + +// Housekeeping functions + +void confetti_drag(magic_api * api, int which, SDL_Surface * canvas, + SDL_Surface * snapshot, int ox, int oy, int x, int y, + SDL_Rect * update_rect); + +Uint32 confetti_api_version(void) +{ + return(TP_MAGIC_API_VERSION); +} + +void confetti_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b) //get the colors from API and store it in structure +{ + confetti_colors.r=r; + confetti_colors.g=g; + confetti_colors.b=b; +} + +int confetti_init(magic_api * api) +{ + char fname[1024]; + + snprintf(fname, sizeof(fname), "%s/sounds/magic/confetti.wav", api->data_directory); + confetti_snd = Mix_LoadWAV(fname); + + return(1); +} + +int confetti_get_tool_count(magic_api * api) +{ + return 1; +} + +SDL_Surface * confetti_get_icon(magic_api * api, int which) +{ + char fname[1024]; + + snprintf(fname, sizeof(fname), "%s/images/magic/confetti.png", + api->data_directory); + + return(IMG_Load(fname)); +} + +char * confetti_get_name(magic_api * api, int which) { return strdup(gettext_noop("Confetti")); } + +char * confetti_get_description(magic_api * api, int which, int mode) { return strdup(gettext_noop("Click to throw a confetti!")); } + +int confetti_requires_colors(magic_api * api, int which) { return 1; } + +void confetti_release(magic_api * api, int which, + SDL_Surface * canvas, SDL_Surface * snapshot, + int x, int y, SDL_Rect * update_rect) +{ + +} + +void confetti_shutdown(magic_api * api) + { Mix_FreeChunk(confetti_snd); } + + +//private functions + +inline char confetti_get_greater(const char what1, const char what2) { if (what1>what2) return what1; else return what2; } + +inline char confetti_get_lesser(const char what1, const char what2) { if (what1rgbtohsv(confetti_colors.r, confetti_colors.g, confetti_colors.b, &hsv_h, &hsv_s, &hsv_v); //color choosen by user is converted + //to HSV palette + + hsv_h+=((rand()%60)-30)%360; //Every circle has different, but + //smilar color + if (hsv_h<0) + hsv_h *= -1; + + api->hsvtorgb(hsv_h, hsv_s, hsv_v, &temp_r, &temp_g, &temp_b); //...and come back to RGB + + return SDL_MapRGB(canvas->format, temp_r, temp_g, temp_b); +} + + +static void confetti_circle(void * ptr, int which, + SDL_Surface * canvas, SDL_Surface * last, + int x, int y) +{ + magic_api * api = (magic_api *) ptr; + + int xx, yy; + Uint32 color=confetti_get_new_color(api, canvas); + + for (yy = y - CONFETTI_BRUSH_SIZE/2; yy < y + CONFETTI_BRUSH_SIZE/2; yy++) + + for (xx = x - CONFETTI_BRUSH_SIZE/2; xx < x + CONFETTI_BRUSH_SIZE/2; xx++) + + if (api->in_circle(xx - x , yy - y , CONFETTI_BRUSH_SIZE/2)) + api->putpixel(canvas, xx, yy, color); +} + +void confetti_click(magic_api * api, int which, int mode, + SDL_Surface * canvas, SDL_Surface * last, + int x, int y, SDL_Rect * update_rect) +{ + unsigned char i; + char min_x, max_x, min_y, max_y; + char dx,dy; + + for (i=0; i + dy=(rand()%100)-50; //to spread confetti around the cursor position + + if (!i) + { + min_x=max_x=dx; + min_y=max_y=dy; + } + else + { + min_x=confetti_get_lesser(min_x, dx); //any candidates to new min/max values? Hands up please... + max_x=confetti_get_greater(max_x, dx); + min_y=confetti_get_lesser(min_y, dy); + max_y=confetti_get_greater(max_y, dy); + } + confetti_circle((void *)api, which, canvas, last, x+dx, y+dy); + } + + update_rect->x = x+min_x - CONFETTI_BRUSH_SIZE/2; + update_rect->y = y+ min_y - CONFETTI_BRUSH_SIZE/2; + update_rect->w = CONFETTI_BRUSH_SIZE*1.5+max_x-min_x; + update_rect->h = CONFETTI_BRUSH_SIZE*1.5+max_y-min_y; + + api->playsound(confetti_snd, (x * 255) / canvas->w,255); +} + +void confetti_drag(magic_api * api, int which, SDL_Surface * canvas, + SDL_Surface * snapshot, int ox, int oy, int x, int y, + SDL_Rect * update_rect) +{ + int temp; + + if (ox>x) {temp=x; x=ox; ox=temp;} + if (oy>y) {temp=y; y=oy; oy=temp; } + + confetti_click(api, which, MODE_PAINT, canvas, snapshot, x, y, update_rect); +} + +void confetti_switchin(magic_api * api, int which, SDL_Surface * canvas) +{ + +} + +void confetti_switchout(magic_api * api, int which, SDL_Surface * canvas) +{ + +} + +int confetti_modes(magic_api * api, int which) +{ + return(MODE_PAINT); +} diff --git a/magic/src/fold.c b/magic/src/fold.c new file mode 100644 index 000000000..d8e84c76a --- /dev/null +++ b/magic/src/fold.c @@ -0,0 +1,268 @@ +//optimized version soon :) +//when "folding" same corner many times it gives strange results. Now it's allowed. Let me know +//if you think it shouldn't be. + +#include "tp_magic_api.h" +#include "SDL_image.h" +#include "SDL_mixer.h" + +#define FOLD_LEN 80 + +Mix_Chunk * fold_snd; +Uint8 fold_r, fold_g, fold_b; +Uint32 fold_color; +SDL_Surface * fold_surface_src, * fold_surface_dst; + +// Housekeeping functions + +void fold_drag(magic_api * api, int which, SDL_Surface * canvas, + SDL_Surface * snapshot, int ox, int oy, int x, int y, + SDL_Rect * update_rect); + +Uint32 fold_api_version(void) + +{ + return(TP_MAGIC_API_VERSION); +} + +void fold_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b) //get the colors from API and store it in structure +{ + fold_r=r; + fold_g=g; + fold_b=b; +} + +int fold_init(magic_api * api) +{ + char fname[1024]; + + snprintf(fname, sizeof(fname), "%s/sounds/magic/fold.wav", api->data_directory); + fold_snd = Mix_LoadWAV(fname); + + return(1); +} + +int fold_get_tool_count(magic_api * api) +{ + return 1; +} + +SDL_Surface * fold_get_icon(magic_api * api, int which) +{ + char fname[1024]; + + snprintf(fname, sizeof(fname), "%s/images/magic/fold.png", + api->data_directory); + + return(IMG_Load(fname)); +} + +char * fold_get_name(magic_api * api, int which) { return(strdup("Fold")); } + +char * fold_get_description(magic_api * api, int which, int mode) { return strdup(gettext_noop("Choose a background color and click to turn the corner of the page over")); } + +int fold_requires_colors(magic_api * api, int which) { return 1; } //selected color will be a "backpage" color + +void fold_release(magic_api * api, int which, + SDL_Surface * canvas, SDL_Surface * snapshot, + int x, int y, SDL_Rect * update_rect) +{ + +} + +void fold_shutdown(magic_api * api) + { + Mix_FreeChunk(fold_snd); + SDL_FreeSurface(fold_surface_dst); + SDL_FreeSurface(fold_surface_src); + } + +// Interactivity functions + +inline Uint8 fold_what_corner(int x, int y, SDL_Surface * canvas) +{ + if (x>=canvas->w/2) + { + if (y>=canvas->h/2) return 4; + else return 1; + } + else + { + if (y>=canvas->h/2) return 3; + else return 2; + } +} + +void static fold_rotate(void * ptr, SDL_Surface * canvas, SDL_Surface * snapshot, Uint8 corner) +{ + magic_api * api = (magic_api *) ptr; + + unsigned int x,y; + + if ((corner==2) || (corner==4)) //rotate +90 degs + { + for (x = 0; xputpixel(canvas, x, y, api->getpixel(snapshot, y, FOLD_LEN-x)); + } + else //rotate -90 degs + { + for (x=0; xputpixel(canvas,x,y,api->getpixel(snapshot,FOLD_LEN-y,x)); + } +} + +void static fold_flip(void * ptr, SDL_Surface * canvas, SDL_Surface * snapshot, Uint8 corner) //flip page +{ + magic_api * api = (magic_api *) ptr; + + unsigned int x, y; + + for (x=0; xw; x++) + for (y=0; yh; y++) + api->putpixel(canvas, x, y, api->getpixel(snapshot, snapshot->w-x, y)); //flip horizontal +} + +static void fold_print_line(void * ptr, int which, SDL_Surface * canvas, SDL_Surface * last, + int x, int y) +{ + magic_api * api = (magic_api *) ptr; + api->putpixel(canvas, x, y, SDL_MapRGB(last->format, 222, 222, 222)); //Middle gray. Color have been set arbitrary. +} + +static void fold_erase(void * ptr, int which, SDL_Surface * canvas, SDL_Surface * last, + int x, int y) +{ + magic_api * api = (magic_api *) ptr; + api->putpixel(canvas, x, y, fold_color); +} + +static void fold_draw_triangle (magic_api * ptr, int which, SDL_Surface * canvas, SDL_Surface * snapshot, Uint8 corner) +{ + magic_api * api = (magic_api *) ptr; + unsigned int i; + //this function could be optimized but it would make this code less readable + + switch(corner) //corners in mathematical order: 1: right upper, 2: left upper, ... + { + case 1: + for (i = 0; i < FOLD_LEN; i++) + api->line((void *)api, which, canvas, snapshot, canvas->w-FOLD_LEN+i, 0, canvas->w, FOLD_LEN-i, 1, fold_erase); + //clear the triangle by the corner + + api->line((void *)api, which, canvas, snapshot,canvas->w-FOLD_LEN, 0, canvas->w-FOLD_LEN, FOLD_LEN, 1, fold_print_line); + //draw vertical line + api->line((void *)api, which, canvas, snapshot,canvas->w-FOLD_LEN, FOLD_LEN, canvas->w, FOLD_LEN, 1, fold_print_line); + //draw horizontal line + api->line((void *)api, which, canvas, snapshot,canvas->w-FOLD_LEN, 0, canvas->w, FOLD_LEN, 1, fold_print_line); + //and another: oblique + break; + + case 2: + for (i = 0; i < FOLD_LEN; i++) + api->line((void *)api, which, canvas, snapshot, 0, FOLD_LEN-i, FOLD_LEN-i, 0, 1, fold_erase); + //sequence just like above + api->line((void *)api, which, canvas, snapshot,FOLD_LEN, 0, FOLD_LEN, FOLD_LEN, 1, fold_print_line); + api->line((void *)api, which, canvas, snapshot,0, FOLD_LEN, FOLD_LEN, FOLD_LEN, 1, fold_print_line); + api->line((void *)api, which, canvas, snapshot,0, FOLD_LEN, FOLD_LEN, 0, 1, fold_print_line); + break; + + case 3: + for (i = 0; i < FOLD_LEN; i++) + api->line((void *)api, which, canvas, snapshot, 0, canvas->h-FOLD_LEN+i, FOLD_LEN-i, canvas->h, 1, fold_erase); + + api->line((void *)api, which, canvas, snapshot,FOLD_LEN, canvas->h-FOLD_LEN, FOLD_LEN, canvas->h, 1, fold_print_line); + api->line((void *)api, which, canvas, snapshot,0, canvas->h-FOLD_LEN, FOLD_LEN, canvas->h-FOLD_LEN, 1, fold_print_line); + api->line((void *)api, which, canvas, snapshot,0, canvas->h-FOLD_LEN, FOLD_LEN, canvas->h, 1, fold_print_line); + break; + + case 4: + for (i = 0; i < FOLD_LEN; i++) + api->line((void *)api, which, canvas, snapshot, canvas->w-FOLD_LEN+i, canvas->h, canvas->w, + canvas->h-FOLD_LEN+i, 1, fold_erase); + + api->line((void *)api, which, canvas, snapshot,canvas->w-FOLD_LEN, canvas->h-FOLD_LEN, canvas->w-FOLD_LEN, + canvas->h, 1, fold_print_line); + api->line((void *)api, which, canvas, snapshot,canvas->w-FOLD_LEN, canvas->h-FOLD_LEN, canvas->w, + canvas->h-FOLD_LEN, 1, fold_print_line); + api->line((void *)api, which, canvas, snapshot,canvas->w-FOLD_LEN, canvas->h, canvas->w, canvas->h-FOLD_LEN, 1, fold_print_line); + break; + } +} + +void fold_click(magic_api * ptr, int which, int mode, + SDL_Surface * canvas, SDL_Surface * snapshot, + int x, int y, SDL_Rect * update_rect) +{ + Uint8 corner; + + magic_api * api = (magic_api *) ptr; + corner=fold_what_corner(x, y, snapshot); + + fold_color=SDL_MapRGB(snapshot->format, fold_r, fold_g, fold_b); + + fold_surface_src= SDL_CreateRGBSurface(SDL_ANYFORMAT, FOLD_LEN, FOLD_LEN, snapshot->format->BitsPerPixel, + snapshot->format->Rmask, snapshot->format->Gmask, snapshot->format->Bmask, snapshot->format->Amask); + + fold_surface_dst=SDL_CreateRGBSurface(SDL_ANYFORMAT, FOLD_LEN, FOLD_LEN, snapshot->format->BitsPerPixel, + snapshot->format->Rmask, snapshot->format->Gmask, snapshot->format->Bmask, snapshot->format->Amask); + + + switch(corner) + { + case 1: //Right Upper + update_rect->x=canvas->w-FOLD_LEN; + update_rect->y=0; + break; + + case 2: //LU + update_rect->x=update_rect->y=0; + break; + + case 3: //LL + update_rect->x=0; + update_rect->y=canvas->h-FOLD_LEN; + break; + + case 4: //RL + update_rect->x=canvas->w-FOLD_LEN; + update_rect->y=canvas->h-FOLD_LEN; + break; + } + + update_rect->w=FOLD_LEN; + update_rect->h=FOLD_LEN; + + SDL_BlitSurface(snapshot, update_rect, fold_surface_src, NULL); + fold_flip(api, fold_surface_dst, fold_surface_src, corner); + SDL_BlitSurface(fold_surface_dst, NULL, canvas, update_rect); + + SDL_BlitSurface(canvas, update_rect, fold_surface_src, NULL); + fold_rotate(api, fold_surface_dst, fold_surface_src, corner); + SDL_BlitSurface(fold_surface_dst, NULL, canvas, update_rect); + + fold_draw_triangle (api, which, canvas, snapshot, corner); +} + +void fold_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 fold_switchin(magic_api * api, int which, SDL_Surface * canvas) +{ + +} + +void fold_switchout(magic_api * api, int which, SDL_Surface * canvas) +{ + +} + +int fold_modes(magic_api * api, int which) +{ + return(MODE_PAINT); +}