"Clone" magic tool

This commit is contained in:
Bill Kendrick 2021-01-10 22:46:34 -08:00
parent 3b16897586
commit 1cb04f1e0a
11 changed files with 304 additions and 12 deletions

View file

@ -8,10 +8,14 @@ http://www.tuxpaint.org/
$Id$
2021.January.9 (0.9.26)
2021.January.10 (0.9.26)
* New Magic Tools:
----------------
* Pixels
Draws large squares, for classic computer 'pixel art' style drawings.
* Clone
Clones (copies, via painting) part of a drawing to another position.
* Documentation updates
---------------------

View file

@ -5,3 +5,5 @@
These two tools intelligently paint large and small brick patterns on the
canvas. The bricks can be tinted various redish hues by selecting
different colors in the color palette.
See also: Pixels

View file

@ -0,0 +1,7 @@
Tux Paint "Magic" Tool: Clone
By Bill Kendrick <bill@newbreedsoftware.com>
Clone (copy, via painting) part of the picture. Click ones to choose the
source, then click and drag to clone it elsewhere in the drawing. Once you
release, click to choose another source and start again.

View file

@ -6,4 +6,5 @@
<h1 align="center">Tux Paint "Magic" Tool: Bricks</h1>
<h2 align="center">By Albert Cahalan &lt;<a href="mailto:albert@users.sf.net">albert@users.sf.net</a>&gt;</h2>
<p>These two tools intelligently paint large and small brick patterns on the canvas. The bricks can be tinted various redish hues by selecting different colors in the color palette.</p>
<p>See also: <a href="pixels.html">Pixels</a></p>
</body></html>

View file

@ -0,0 +1,9 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<body><html><head><title>Tux Paint "Magic" Tool: Clone</title>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
</head>
<body bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink="#FF0000" alink="#FF00FF">
<h1 align="center">Tux Paint "Magic" Tool: Clone</h1>
<h2 align="center">By Bill Kendrick &lt;<a href="mailto:bill@newbreedsoftware.com">bill@newbreedsoftware.com</a>&gt;</h2>
<p>Clone (copy, via painting) part of the picture. Click ones to choose the source, then click and drag to clone it elsewhere in the drawing. Once you release, click to choose another source and start again.</p>
</body></html>

View file

@ -11,6 +11,7 @@
<li><a href="calligraphy.html">Calligraphy</a></li>
<li><a href="cartoon.html">Cartoon</a></li>
<li><a href="chalk.html">Chalk</a></li>
<li><a href="clone.html">Clone</a></li>
<li><a href="color_and_white.html">Color and White</a></li>
<li><a href="color_shift.html">Color Shift</a></li>
<li><a href="confetti.html">Confetti</a></li>
@ -19,7 +20,6 @@
<li><a href="drip.html">Drip</a></li>
<li><a href="edges.html">Edges</a></li>
<li><a href="emboss.html">Emboss</a></li>
<li><a href="fill.html">Fill</a></li>
<li><a href="fisheye.html">Fisheye</a></li>
<li><a href="flip.html">Flip</a></li>
<li><a href="flower.html">Flower</a></li>
@ -41,6 +41,7 @@
<li><a href="pattern.html">Pattern</a></li>
<li><a href="perspective.html">Perspective</a></li>
<li><a href="picasso.html">Picasso</a></li>
<li><a href="pixels.html">Pixels</a></li>
<li><a href="puzzle.html">Puzzle</a></li>
<li><a href="rails.html">Rails</a></li>
<li><a href="rain.html">Rain</a></li>

View file

@ -5,5 +5,6 @@
<body bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink="#FF0000" alink="#FF00FF">
<h1 align="center">Tux Paint "Magic" Tool: Pixels</h1>
<h2 align="center">By Bill Kendrick &lt;<a href="mailto:bill@newbreedsoftware.com">bill@newbreedsoftware.com</a>&gt;</h2>
<p>This tool draws squares on the canvas in a grid, simulating large pixels seen on older computer displays, and allowing simple "pixel art" to be created in Tux Paint.</p>
</body></html>
<p>Draw large square "pixels" on the canvas.</p>
<p>See also: <a href="bricks.html">Bricks</a></p>
</body></html>

View file

@ -7,6 +7,7 @@
* Calligraphy
* Cartoon
* Chalk
* Clone
* Color and White
* Color Shift
* Confetti
@ -15,7 +16,6 @@
* Drip
* Edges
* Emboss
* Fill
* Fisheye
* Flip
* Flower
@ -37,6 +37,7 @@
* Pattern
* Perspective
* Picasso
* Pixels
* Puzzle
* Rails
* Rain

View file

@ -2,6 +2,6 @@
By Bill Kendrick <bill@newbreedsoftware.com>
This tool draws squares on the canvas in a grid, simulating large pixels
seen on older computer displays, and allowing simple "pixel art" to be
created in Tux Paint.
Draw large square "pixels" on the canvas.
See also: Bricks

View file

@ -5,7 +5,7 @@ individual HTML files for each of them, and an index.html that links to
them all. */
/* Bill Kendrick <bill@newbreedsoftware.com> */
/* Oct. 8, 2009 - September 12, 2019 */
/* Oct. 8, 2009 - January 10, 2020 */
/* Authors of the Magic tools: */
@ -65,7 +65,8 @@ $tools = array(
array('name'=>'Bricks',
'desc'=>'These two tools intelligently paint large and small brick patterns on the canvas. The bricks can be tinted various redish hues by selecting different colors in the color palette.',
'author'=>$AUTHOR_ALBERT),
'author'=>$AUTHOR_ALBERT,
'see'=>'Pixels'),
array('name'=>'Calligraphy',
'desc'=>'This paints on the canvas with a calligraphy pen. The quicker you move, the thinner the lines.',
@ -79,6 +80,10 @@ $tools = array(
'desc'=>'This makes parts of the picture (where you move the mouse) look like a chalk drawing.',
'author'=>$AUTHOR_KENDRICK),
array('name'=>'Clone',
'desc'=>'Clone (copy, via painting) part of the picture. Click ones to choose the source, then click and drag to clone it elsewhere in the drawing. Once you release, click to choose another source and start again.',
'author'=>$AUTHOR_KENDRICK),
array('name'=>'Color and White',
'desc'=>'This makes parts of your picture two colors: white, and the color chosen in the palette. (i.e., if you choose black, you\'ll get a black and white picture).',
'author'=>$AUTHOR_ANDREWC),
@ -226,6 +231,11 @@ $tools = array(
'author'=>$AUTHOR_ADAMR,
'see'=>'Rosette', 'Kaleidoscope'),
array('name'=>'Pixels',
'desc'=>'Draw large square "pixels" on the canvas.',
'author'=>$AUTHOR_KENDRICK,
'see'=>'Bricks'),
array('name'=>'Puzzle',
'desc'=>'Slide parts of your picture around like a sliding puzzle.',
'author'=>$AUTHOR_ADAMR),
@ -372,11 +382,11 @@ foreach ($tools as $t) {
$out .= "<h2 align=\"center\">By ";
if (is_array($t['author'])) {
foreach ($t['author'] as $a) {
list($authname, $authemail) = split('\|', $a);
list($authname, $authemail) = explode('|', $a);
$out .= $authname." &lt;<a href=\"mailto:".$authemail."\">".$authemail."</a>&gt;<br>\n";
}
} else {
list($authname, $authemail) = split('\|', $t['author']);
list($authname, $authemail) = explode('|', $t['author']);
$out .= $authname." &lt;<a href=\"mailto:".$authemail."\">".$authemail."</a>&gt;";
}

256
magic/src/clone.c Normal file
View file

@ -0,0 +1,256 @@
/*
clone.c
Clone tool paintbrush Magic Tools Plugin
Tux Paint - A simple drawing program for children.
Copyright (c) 2021 by Bill Kendrick and others; see AUTHORS.txt
bill@newbreedsoftware.com
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)
Last updated: January 10, 2021
$Id$
*/
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "tp_magic_api.h"
#include "SDL_image.h"
#include "SDL_mixer.h"
/* What tools we contain: */
enum
{
TOOL_CLONE,
NUM_TOOLS
};
/* Tool states: */
enum
{
CLONE_READY_TO_START,
CLONE_STARTING,
CLONE_CLONING
};
/* Our globals: */
static Mix_Chunk *clone_snd;
int clone_state;
int clone_src_x, clone_src_y;
int clone_drag_start_x, clone_drag_start_y;
/* Local function prototype: */
int clone_init(magic_api * api);
Uint32 clone_api_version(void);
int clone_get_tool_count(magic_api * api);
SDL_Surface *clone_get_icon(magic_api * api, int which);
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_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);
void clone_shutdown(magic_api * api);
void clone_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b);
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);
// No setup required:
int clone_init(magic_api * api)
{
char fname[1024];
snprintf(fname, sizeof(fname), "%s/sounds/magic/clone.ogg", api->data_directory);
clone_snd = Mix_LoadWAV(fname);
clone_state = CLONE_READY_TO_START;
return (1);
}
Uint32 clone_api_version(void)
{
return (TP_MAGIC_API_VERSION);
}
// We have multiple tools:
int clone_get_tool_count(magic_api * api ATTRIBUTE_UNUSED)
{
return (NUM_TOOLS);
}
// Load our icons:
SDL_Surface *clone_get_icon(magic_api * api, int which ATTRIBUTE_UNUSED)
{
char fname[1024];
snprintf(fname, sizeof(fname), "%s/images/magic/clone.png", api->data_directory);
return (IMG_Load(fname));
}
// Return our names, localized:
char *clone_get_name(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED)
{
return (strdup(gettext_noop("Clone")));
}
// Return our descriptions, localized:
char *clone_get_description(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED)
{
return (strdup(gettext_noop("Click once to pick a spot to begin cloning. Click again and drag to clone that part of the picture.")));
return (NULL);
}
// Do the effect:
static void do_clone(void *ptr, int which ATTRIBUTE_UNUSED, SDL_Surface * canvas, SDL_Surface * last, int x, int y)
{
magic_api *api = (magic_api *) ptr;
Uint8 r, g, b;
int xx, yy;
int srcx, srcy;
Uint32 pixel;
srcx = clone_src_x + (x - clone_drag_start_x);
srcy = clone_src_y + (y - clone_drag_start_y);
for (yy = -16; yy < 16; yy++)
{
for (xx = -16; xx < 16; xx++)
{
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);
}
}
}
}
// 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)
{
if (clone_state != CLONE_CLONING)
return;
clone_drag_start_x = ox;
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);
clone_src_x += (x - ox);
clone_src_y += (y - oy);
if (ox > x)
{
int tmp = ox;
ox = x;
x = tmp;
}
if (oy > y)
{
int tmp = oy;
oy = y;
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;
api->playsound(clone_snd, (x * 255) / canvas->w, 255);
}
// Affect the canvas on click:
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) {
clone_src_x = x;
clone_src_y = y;
clone_state = CLONE_STARTING;
} else if (clone_state == CLONE_CLONING) {
clone_drag(api, which, canvas, last, x, y, x, y, update_rect);
}
}
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)
{
if (clone_state == CLONE_STARTING) {
clone_state = CLONE_CLONING;
} else {
clone_state = CLONE_READY_TO_START;
}
api->stopsound();
}
// No setup happened:
void clone_shutdown(magic_api * api ATTRIBUTE_UNUSED)
{
if (clone_snd != NULL)
Mix_FreeChunk(clone_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;
}
void clone_switchin(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED,
int mode ATTRIBUTE_UNUSED, SDL_Surface * canvas ATTRIBUTE_UNUSED)
{
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)
{
clone_state = CLONE_READY_TO_START;
}
int clone_modes(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED)
{
return (MODE_PAINT);
}