"xorpixel()" function added to Magic Tools API

This commit is contained in:
Bill Kendrick 2021-02-20 15:19:40 -08:00
parent d588e5d214
commit 7cd547e746
6 changed files with 103 additions and 62 deletions

View file

@ -1,10 +1,10 @@
# Tux Paint - A simple drawing program for children. # Tux Paint - A simple drawing program for children.
# Copyright (c) 2002-2020 # Copyright (c) 2002-2021
# Various contributors (see AUTHORS.txt) # Various contributors (see AUTHORS.txt)
# http://www.tuxpaint.org/ # http://www.tuxpaint.org/
# June 14, 2002 - December 27, 2020 # June 14, 2002 - January 2, 2020
# The version number, for release: # The version number, for release:
@ -15,7 +15,7 @@ ifdef SOURCE_DATE_EPOCH
else else
VER_DATE=$(shell date "+%Y-%m-%d") VER_DATE=$(shell date "+%Y-%m-%d")
endif endif
MAGIC_API_VERSION:=0x00000003 MAGIC_API_VERSION:=0x00000004
# Need to know the OS # Need to know the OS

View file

@ -18,6 +18,8 @@ $Id$
for the color palette at the bottom of the screen. for the color palette at the bottom of the screen.
(Use the "colorsrows" option.) (Use the "colorsrows" option.)
Pere Pujal i Carabantes <pere@fornol.no-ip.org> Pere Pujal i Carabantes <pere@fornol.no-ip.org>
* A new "xorpixel()" function has been added to the Magic Tools API.
* New Magic Tools: * New Magic Tools:
---------------- ----------------

View file

@ -3,7 +3,7 @@
Copyright 2007-2018 by various contributors; see AUTHORS.txt Copyright 2007-2018 by various contributors; see AUTHORS.txt
http://www.tuxpaint.org/ http://www.tuxpaint.org/
July 5, 2007 - August 30, 2018 July 5, 2007 - February 20, 2021
---------------------------------------------------------------------- ----------------------------------------------------------------------
@ -392,6 +392,13 @@ Interfaces
RGB values to a Uint32 'pixel' value appropriate to the RGB values to a Uint32 'pixel' value appropriate to the
destination surface.) destination surface.)
* Uint32 xorpixel(SDL_Surface * surf, int x, int y)
Applies an XOR (exclusive-or) operation to the pixel at
coordinates (x,y) of the SDL_Surface. Applying an XOR again at
the same position will return the pixel to the original value.
Useful for displaying temporary 'rubberband' lines, outlines,
and crosshairs, while utilizing a Magic Tool.
* SDL_Surface * scale(SDL_Surface * surf, int w, int h, * SDL_Surface * scale(SDL_Surface * surf, int w, int h,
int keep_aspect) int keep_aspect)
This accepts an existing SDL surface and creates a new one This accepts an existing SDL surface and creates a new one
@ -648,12 +655,12 @@ Compiling
A snippet from a Makefile to compile a Tux Paint "Magic" tool plugin A snippet from a Makefile to compile a Tux Paint "Magic" tool plugin
might look like this: might look like this:
+----------------------------------------------------------------+ +------------------------------------------------------+
| CFLAGS=-Wall -O2 $(shell tp-magic-config --cflags) | | CFLAGS=-Wall -O2 $(shell tp-magic-config --cflags) |
| | | |
| my_plugin.so: my_plugin.c | | my_plugin.so: my_plugin.c |
| gcc -shared $(CFLAGS) -o my_plugin.so my_plugin.c | | gcc -shared $(CFLAGS) -o my_plugin.so my_plugin.c |
+----------------------------------------------------------------+ +------------------------------------------------------+
The first line sets up Makefile variable ("CFLAGS") that contains The first line sets up Makefile variable ("CFLAGS") that contains
flags for the compiler. "-Wall" asks for all compiler warnings to be flags for the compiler. "-Wall" asks for all compiler warnings to be
@ -683,15 +690,15 @@ Compiling
An even more generalized Makefile might look like this: An even more generalized Makefile might look like this:
+----------------------------------------------------------------+ +----------------------------------------------------+
| CFLAGS=-Wall -O2 $(shell tp-magic-config --cflags) | | CFLAGS=-Wall -O2 $(shell tp-magic-config --cflags) |
| | | |
| my_plugin_1.so: my_plugin_1.c | | my_plugin_1.so: my_plugin_1.c |
| $(CC) -shared $(CFLAGS) -o $@ $< | | $(CC) -shared $(CFLAGS) -o $@ $< |
| | | |
| my_plugin_2.so: my_plugin_2.c | | my_plugin_2.so: my_plugin_2.c |
| $(CC) -shared $(CFLAGS) -o $@ $< | | $(CC) -shared $(CFLAGS) -o $@ $< |
+----------------------------------------------------------------+ +----------------------------------------------------+
As before, there are lines that define the command "make" should run As before, there are lines that define the command "make" should run
when it determines that it needs to (re)compile the ".so" file(s). when it determines that it needs to (re)compile the ".so" file(s).
@ -799,35 +806,35 @@ Installing
A snippet from a more generalized Makefile might look like this: A snippet from a more generalized Makefile might look like this:
+----------------------------------------------------------------+ +------------------------------------------------------------+
| PLUGINPREFIX=$(shell tp-magic-config --pluginprefix) | | PLUGINPREFIX=$(shell tp-magic-config --pluginprefix) |
| PLUGINDOCPREFIX=$(shell tp-magic-config --plugindocprefix) | | PLUGINDOCPREFIX=$(shell tp-magic-config --plugindocprefix) |
| DATAPREFIX=$(shell tp-magic-config --dataprefix) | | DATAPREFIX=$(shell tp-magic-config --dataprefix) |
| | | |
| install: | | install: |
| # | | # |
| # Install plugin | | # Install plugin |
| mkdir -p $(PLUGINPREFIX) | | mkdir -p $(PLUGINPREFIX) |
| cp *.so $(PLUGINPREFIX)/ | | cp *.so $(PLUGINPREFIX)/ |
| chmod 644 $(PLUGINPREFIX)/*.so | | chmod 644 $(PLUGINPREFIX)/*.so |
| # | | # |
| # Install icons | | # Install icons |
| mkdir -p $(DATAPREFIX)/images/magic | | mkdir -p $(DATAPREFIX)/images/magic |
| cp icons/*.png $(DATAPREFIX)/images/magic/ | | cp icons/*.png $(DATAPREFIX)/images/magic/ |
| chmod 644 $(DATAPREFIX)/images/magic/*.png | | chmod 644 $(DATAPREFIX)/images/magic/*.png |
| # | | # |
| # Install sound effects | | # Install sound effects |
| mkdir -p $(DATAPREFIX)/sounds/magic | | mkdir -p $(DATAPREFIX)/sounds/magic |
| cp sounds/*.ogg $(DATAPREFIX)/sounds/magic/ | | cp sounds/*.ogg $(DATAPREFIX)/sounds/magic/ |
| chmod 644 $(DATAPREFIX)/sounds/magic/*.ogg | | chmod 644 $(DATAPREFIX)/sounds/magic/*.ogg |
| # | | # |
| # Install docs | | # Install docs |
| mkdir -p $(PLUGINDOCPREFIX)/html | | mkdir -p $(PLUGINDOCPREFIX)/html |
| cp docs/*.html $(PLUGINDOCPREFIX)/html/ | | cp docs/*.html $(PLUGINDOCPREFIX)/html/ |
| cp docs/*.txt $(PLUGINDOCPREFIX)/ | | cp docs/*.txt $(PLUGINDOCPREFIX)/ |
| chmod 644 $(PLUGINDOCPREFIX)/html/*.html | | chmod 644 $(PLUGINDOCPREFIX)/html/*.html |
| chmod 644 $(PLUGINDOCPREFIX)/*.txt | | chmod 644 $(PLUGINDOCPREFIX)/*.txt |
+----------------------------------------------------------------+ +------------------------------------------------------------+
The first three lines set up Makefile variables that contain the The first three lines set up Makefile variables that contain the
paths returned by the "tp-magic-config" command-line tool. (The paths returned by the "tp-magic-config" command-line tool. (The

View file

@ -12,7 +12,7 @@ alink="#FF00FF">
<p>Copyright 2007-2018 by various contributors; see AUTHORS.txt<br/> <p>Copyright 2007-2018 by various contributors; see AUTHORS.txt<br/>
<a href="http://www.tuxpaint.org/">http://www.tuxpaint.org/</a></p> <a href="http://www.tuxpaint.org/">http://www.tuxpaint.org/</a></p>
<p>July 5, 2007 - August 30, 2018</p> <p>July 5, 2007 - February 20, 2021</p>
</center> </center>
<hr size=2 noshade> <hr size=2 noshade>
@ -497,6 +497,15 @@ plugin's functions.
surface.)<br> surface.)<br>
<br> <br>
<li><code><b>Uint32 xorpixel(SDL_Surface&nbsp;*&nbsp;surf,
int&nbsp;x, int&nbsp;y)</b></code><br>
Applies an XOR (exclusive-or) operation to the pixel at coordinates
(x,y) of the SDL_Surface. Applying an XOR again at the same position
will return the pixel to the original value. Useful for displaying
temporary 'rubberband' lines, outlines, and crosshairs, while
utilizing a Magic Tool.<br>
<br>
<li><code><b>SDL_Surface * scale(SDL_Surface&nbsp;*&nbsp;surf, <li><code><b>SDL_Surface * scale(SDL_Surface&nbsp;*&nbsp;surf,
int&nbsp;w, int&nbsp;h, int&nbsp;keep_aspect)</b></code><br> int&nbsp;w, int&nbsp;h, int&nbsp;keep_aspect)</b></code><br>
This accepts an existing SDL surface and creates a new one scaled to an This accepts an existing SDL surface and creates a new one scaled to an

View file

@ -110,6 +110,9 @@ typedef struct magic_api_t {
SDL_MustLockSurface() can tell you whether a surface needs to be locked. */ SDL_MustLockSurface() can tell you whether a surface needs to be locked. */
void (*putpixel)(SDL_Surface *, int, int, Uint32); void (*putpixel)(SDL_Surface *, int, int, Uint32);
/* XOR's the pixel at (x,y) location of the surface. */
Uint32 (*xorpixel)(SDL_Surface *, int, int);
/* Asks Tux Paint to play a sound (one loaded via SDL_mixer library); /* Asks Tux Paint to play a sound (one loaded via SDL_mixer library);
the first value is for left/right panning (0 is left, 128 is center, the first value is for left/right panning (0 is left, 128 is center,
255 is right); the second value is for total volume (0 is off, 255 is 255 is right); the second value is for total volume (0 is off, 255 is

View file

@ -22,7 +22,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
(See COPYING.txt) (See COPYING.txt)
June 14, 2002 - January 26, 2021 June 14, 2002 - February 20, 2021
*/ */
@ -751,6 +751,7 @@ static int WINDOW_HEIGHT = 600;
static void magic_putpixel(SDL_Surface * surface, int x, int y, Uint32 pixel); static void magic_putpixel(SDL_Surface * surface, int x, int y, Uint32 pixel);
static Uint32 magic_getpixel(SDL_Surface * surface, int x, int y); static Uint32 magic_getpixel(SDL_Surface * surface, int x, int y);
static void magic_xorpixel(SDL_Surface * surface, int x, int y);
/** /**
* Sets a variety of screen layout globals, based on the * Sets a variety of screen layout globals, based on the
@ -1915,6 +1916,7 @@ static void draw_none(void);
static void do_undo(void); static void do_undo(void);
static void do_redo(void); static void do_redo(void);
static void render_brush(void); static void render_brush(void);
static void _xorpixel(SDL_Surface * surf, int x, int y);
static void line_xor(int x1, int y1, int x2, int y2); static void line_xor(int x1, int y1, int x2, int y2);
static void rect_xor(int x1, int y1, int x2, int y2); static void rect_xor(int x1, int y1, int x2, int y2);
static void draw_blinking_cursor(void); static void draw_blinking_cursor(void);
@ -9920,32 +9922,26 @@ static SDL_Surface *zoom(SDL_Surface * src, int new_w, int new_h)
#endif #endif
/**
* FIXME
*/
/* XOR must show up on black, white, 0x7f grey, and 0x80 grey. /* XOR must show up on black, white, 0x7f grey, and 0x80 grey.
XOR must be exactly 100% perfectly reversable. */ XOR must be exactly 100% perfectly reversable. */
static void xorpixel(int x, int y) static void _xorpixel(SDL_Surface * surf, int x, int y)
{ {
Uint8 *p; Uint8 *p;
int BytesPerPixel; int BytesPerPixel;
/* if outside the canvas, return */ /* if outside the canvas, return */
if ((unsigned)x >= (unsigned)canvas->w || (unsigned)y >= (unsigned)canvas->h) if (x < 0 || x >= surf->w || y < 0 || y >= surf->h)
return; return;
/* now switch to screen coordinates */
x += r_canvas.x;
y += r_canvas.y;
/* Always 4, except 3 when loading a saved image. */ /* Always 4, except 3 when loading a saved image. */
BytesPerPixel = screen->format->BytesPerPixel; BytesPerPixel = surf->format->BytesPerPixel;
/* Set a pointer to the exact location in memory of the pixel */ /* Set a pointer to the exact location in memory of the pixel */
p = (Uint8 *) (((Uint8 *) screen->pixels) + /* Start: beginning of RAM */ p = (Uint8 *) (((Uint8 *) surf->pixels) + /* Start: beginning of RAM */
(y * screen->pitch) + /* Go down Y lines */ (y * surf->pitch) + /* Go down Y lines */
(x * BytesPerPixel)); /* Go in X pixels */ (x * BytesPerPixel)); /* Go in X pixels */
/* XOR the (correctly-sized) piece of data in the screen's RAM */ /* XOR the (correctly-sized) piece of data in the surface's RAM */
if (likely(BytesPerPixel == 4)) if (likely(BytesPerPixel == 4))
*(Uint32 *) p ^= 0x80808080u; /* 32-bit display */ *(Uint32 *) p ^= 0x80808080u; /* 32-bit display */
else if (BytesPerPixel == 1) else if (BytesPerPixel == 1)
@ -9960,6 +9956,21 @@ static void xorpixel(int x, int y)
} }
} }
/**
* FIXME
*/
static void xorpixel(int x, int y) {
/* if outside the canvas, return */
if ((unsigned)x >= (unsigned)canvas->w || (unsigned)y >= (unsigned)canvas->h)
return;
/* now switch to screen coordinates */
x += r_canvas.x;
y += r_canvas.y;
_xorpixel(screen, x, y);
}
/** /**
* FIXME * FIXME
@ -18655,6 +18666,7 @@ static void load_magic_plugins(void)
magic_api_struct->in_circle = in_circle_rad; magic_api_struct->in_circle = in_circle_rad;
magic_api_struct->getpixel = magic_getpixel; magic_api_struct->getpixel = magic_getpixel;
magic_api_struct->putpixel = magic_putpixel; magic_api_struct->putpixel = magic_putpixel;
magic_api_struct->xorpixel = magic_xorpixel;
magic_api_struct->line = magic_line_func; magic_api_struct->line = magic_line_func;
magic_api_struct->playsound = magic_playsound; magic_api_struct->playsound = magic_playsound;
magic_api_struct->stopsound = magic_stopsound; magic_api_struct->stopsound = magic_stopsound;
@ -21301,6 +21313,14 @@ static Uint32 magic_getpixel(SDL_Surface * surface, int x, int y)
return (getpixels[surface->format->BytesPerPixel] (surface, x, y)); return (getpixels[surface->format->BytesPerPixel] (surface, x, y));
} }
/**
* FIXME
*/
static void magic_xorpixel(SDL_Surface * surface, int x, int y)
{
_xorpixel(surface, x, y);
}
/** /**
* FIXME * FIXME