Stamps can now be pre-flipped and/or pre-mirrored-and-flipped now (in addition to pre-mirrored).
Updated version # in some docs. Expanded comments in tp_magic_example.c Magic plugin example code.
This commit is contained in:
parent
51c6783846
commit
26c7051c07
13 changed files with 783 additions and 162 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
Tux Paint
|
Tux Paint
|
||||||
version 0.9.17
|
version 0.9.18
|
||||||
Advanced Stamps HOWTO
|
Advanced Stamps HOWTO
|
||||||
|
|
||||||
Copyright 2006 by Albert Cahalan for the Tux Paint project
|
Copyright 2006 by Albert Cahalan for the Tux Paint project
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
albert@users.sf.net
|
albert@users.sf.net
|
||||||
http://www.tuxpaint.org/
|
http://www.tuxpaint.org/
|
||||||
|
|
||||||
March 8, 2006 - October 26, 2006
|
March 8, 2006 - August 2, 2007
|
||||||
|
|
||||||
About this HOWTO
|
About this HOWTO
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ http://www.tuxpaint.org/
|
||||||
$Id$
|
$Id$
|
||||||
|
|
||||||
|
|
||||||
2007.July.19 (0.9.18)
|
2007.August.2 (0.9.18)
|
||||||
* Interface Improvements:
|
* Interface Improvements:
|
||||||
-----------------------
|
-----------------------
|
||||||
* Improved 'New' and 'Open' interface:
|
* Improved 'New' and 'Open' interface:
|
||||||
|
|
@ -27,6 +27,11 @@ $Id$
|
||||||
|
|
||||||
* Added an Octagon shape to the 'Shapes' tool.
|
* Added an Octagon shape to the 'Shapes' tool.
|
||||||
|
|
||||||
|
* Stamps can now be pre-flipped and/or pre-mirrored-and-flipped now
|
||||||
|
(in addition to pre-mirrored).
|
||||||
|
Use "_flip.png"/"_flip.svg" and "_mirror_flip.png"/"_mirror_flip.png",
|
||||||
|
respectively.
|
||||||
|
|
||||||
* Documentation Imrpovements:
|
* Documentation Imrpovements:
|
||||||
---------------------------
|
---------------------------
|
||||||
* Improved --usage output.
|
* Improved --usage output.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
Tux Paint
|
Tux Paint
|
||||||
version 0.9.17
|
version 0.9.18
|
||||||
Extending Tux Paint
|
Extending Tux Paint
|
||||||
|
|
||||||
Copyright 2002-2007 by Bill Kendrick and others
|
Copyright 2002-2007 by Bill Kendrick and others
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
bill@newbreedsoftware.com
|
bill@newbreedsoftware.com
|
||||||
http://www.tuxpaint.org/
|
http://www.tuxpaint.org/
|
||||||
|
|
||||||
June 14, 2002 - May 6, 2007
|
June 14, 2002 - August 2, 2007
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
@ -428,22 +428,31 @@ Stamps
|
||||||
it as Plain Text, and make sure the filename has ".dat" at the end,
|
it as Plain Text, and make sure the filename has ".dat" at the end,
|
||||||
and not ".txt"...
|
and not ".txt"...
|
||||||
|
|
||||||
Pre-Mirrored Images
|
Pre-Mirrored and Flipped Images
|
||||||
|
|
||||||
In some cases, you may wish to provide a pre-drawn version of a
|
In some cases, you may wish to provide a pre-drawn version of a
|
||||||
stamp's mirror-image. For example, imagine a picture of a fire truck
|
stamp's mirror-image, flipped image, or even both. For example,
|
||||||
with the words "Fire Department" written across the side. You probably
|
imagine a picture of a fire truck with the words "Fire Department"
|
||||||
do not want that text to appear backwards when the image is flipped!
|
written across the side. You probably do not want that text to appear
|
||||||
|
backwards when the image is flipped!
|
||||||
|
|
||||||
To create a mirrored version of a stamp that you want Tux Paint to
|
To create a mirrored version of a stamp that you want Tux Paint to
|
||||||
use, rather than mirroring one on its own, simply create a second
|
use, rather than mirroring one on its own, simply create a second
|
||||||
".png" graphics file with the same name, except with the string
|
".png" or ".svg" graphics file with the same name, except with
|
||||||
"_mirror" before the filename extension.
|
"_mirror" before the filename extension.
|
||||||
|
|
||||||
For example, for the stamp "truck.png" you would create another file
|
For example, for the stamp "truck.png" you would create another file
|
||||||
named "truck_mirror.png", which will be used when the stamp is
|
named "truck_mirror.png", which will be used when the stamp is
|
||||||
mirrored (rather than using a backwards version of 'truck.png').
|
mirrored (rather than using a backwards version of 'truck.png').
|
||||||
|
|
||||||
|
As of Tux Paint 0.9.18, you may similarly provide a pre-flipped image
|
||||||
|
with "_flip" in the name, and/or an image that is both mirrored and
|
||||||
|
flipped, by naming it "_mirror_flip".
|
||||||
|
|
||||||
|
Note: If the user flips and mirrors an image, and a pre-drawn
|
||||||
|
"_mirror_flip" doesn't exist, but either "_flip" or "_mirror" does, it
|
||||||
|
will be used, and mirrored or flipped, respectively.
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
|
|
||||||
Fonts
|
Fonts
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
Tux Paint
|
Tux Paint
|
||||||
version 0.9.17
|
version 0.9.18
|
||||||
Frequently Asked Questions
|
Frequently Asked Questions
|
||||||
|
|
||||||
Copyright 2002-2007 by Bill Kendrick and others
|
Copyright 2002-2007 by Bill Kendrick and others
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
bill@newbreedsoftware.com
|
bill@newbreedsoftware.com
|
||||||
http://www.tuxpaint.org/
|
http://www.tuxpaint.org/
|
||||||
|
|
||||||
September 14, 2002 - June 27, 2007
|
September 14, 2002 - August 2, 2007
|
||||||
|
|
||||||
Drawing-related
|
Drawing-related
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
Tux Paint
|
Tux Paint
|
||||||
version 0.9.17
|
version 0.9.18
|
||||||
|
|
||||||
Options Documentation
|
Options Documentation
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
Tux Paint
|
Tux Paint
|
||||||
version 0.9.17
|
version 0.9.18
|
||||||
|
|
||||||
A simple drawing program for children
|
A simple drawing program for children
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ alink="#FF00FF">
|
||||||
alt="Tux Paint"><br>
|
alt="Tux Paint"><br>
|
||||||
version
|
version
|
||||||
|
|
||||||
0.9.17
|
0.9.18
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
Advanced Stamps HOWTO</h1>
|
Advanced Stamps HOWTO</h1>
|
||||||
|
|
@ -21,7 +21,7 @@ New Breed Software</p>
|
||||||
<p><a href="mailto:albert@users.sf.net">albert@users.sf.net</a><br>
|
<p><a href="mailto:albert@users.sf.net">albert@users.sf.net</a><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>March 8, 2006 - October 26, 2006</p>
|
<p>March 8, 2006 - August 2, 2007</p>
|
||||||
</center>
|
</center>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ alt="Tux Paint"><br>
|
||||||
|
|
||||||
version
|
version
|
||||||
|
|
||||||
0.9.17
|
0.9.18
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
Extending Tux Paint</h1>
|
Extending Tux Paint</h1>
|
||||||
|
|
@ -23,7 +23,7 @@ New Breed Software</p>
|
||||||
<p><a href="mailto:bill@newbreedsoftware.com">bill@newbreedsoftware.com</a><br>
|
<p><a href="mailto:bill@newbreedsoftware.com">bill@newbreedsoftware.com</a><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>June 14, 2002 - May 6, 2007</p>
|
<p>June 14, 2002 - August 2, 2007</p>
|
||||||
</center>
|
</center>
|
||||||
|
|
||||||
<hr size=2 noshade>
|
<hr size=2 noshade>
|
||||||
|
|
@ -558,24 +558,34 @@ effect.</p>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
|
||||||
<h3>Pre-Mirrored Images</h3>
|
<h3>Pre-Mirrored and Flipped Images</h3>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<p>In some cases, you may wish to provide a pre-drawn version of
|
<p>In some cases, you may wish to provide a pre-drawn version of
|
||||||
a stamp's mirror-image. For example, imagine a picture of a fire
|
a stamp's mirror-image, flipped image, or even both. For example,
|
||||||
truck with the words "<i>Fire Department</i>" written across
|
imagine a picture of a fire truck with the words
|
||||||
the side. You probably do not want that text to appear backwards
|
"<i>Fire Department</i>" written across the side. You probably
|
||||||
when the image is flipped!</p>
|
do not want that text to appear backwards when the image is flipped!</p>
|
||||||
|
|
||||||
<p>To create a mirrored version of a stamp that you want Tux Paint
|
<p>To create a mirrored version of a stamp that you want Tux Paint
|
||||||
to use, rather than mirroring one on its own, simply create a second
|
to use, rather than mirroring one on its own, simply create a second
|
||||||
"<code>.png</code>" graphics file with the same name, except with
|
"<code>.png</code>" or "<code>.svg</code>" graphics file with the
|
||||||
the string "<code><b>_mirror</b></code>" before the filename
|
same name, except with "<code><b>_mirror</b></code>" before the filename
|
||||||
extension.</p>
|
extension.</p>
|
||||||
|
|
||||||
<p>For example, for the stamp "<code><b>truck.png</b></code>" you would
|
<p>For example, for the stamp "<code><b>truck.png</b></code>" you would
|
||||||
create another file named "<code><b>truck_mirror.png</b></code>", which
|
create another file named "<code><b>truck_mirror.png</b></code>", which
|
||||||
will be used when the stamp is mirrored (rather than using a
|
will be used when the stamp is mirrored (rather than using a
|
||||||
backwards version of '<code>truck.png</code>').</p>
|
backwards version of '<code>truck.png</code>').</p>
|
||||||
|
|
||||||
|
<p>As of Tux Paint 0.9.18, you may similarly provide a pre-flipped
|
||||||
|
image with "<code><b>_flip</b></code>" in the name, and/or an image that
|
||||||
|
is both mirrored and flipped, by naming it
|
||||||
|
"<code><b>_mirror_flip</b></code>".</p>
|
||||||
|
|
||||||
|
<p><b>Note:</b> If the user flips and mirrors an image, and a pre-drawn
|
||||||
|
"<code>_mirror_flip</code>" doesn't exist, but either "<code>_flip</code>"
|
||||||
|
or "<code>_mirror</code>" does, it will be used, and mirrored or flipped,
|
||||||
|
respectively.</p>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ alink="#FF00FF">
|
||||||
alt="Tux Paint"><br>
|
alt="Tux Paint"><br>
|
||||||
version
|
version
|
||||||
|
|
||||||
0.9.17
|
0.9.18
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
Frequently Asked Questions</h1>
|
Frequently Asked Questions</h1>
|
||||||
|
|
@ -22,7 +22,7 @@ New Breed Software</p>
|
||||||
<p><a href="mailto:bill@newbreedsoftware.com">bill@newbreedsoftware.com</a><br>
|
<p><a href="mailto:bill@newbreedsoftware.com">bill@newbreedsoftware.com</a><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>September 14, 2002 - June 27, 2007</p>
|
<p>September 14, 2002 - August 2, 2007</p>
|
||||||
</center>
|
</center>
|
||||||
|
|
||||||
<h2>Drawing-related</h2>
|
<h2>Drawing-related</h2>
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ alink="#FF00FF">
|
||||||
|
|
||||||
version
|
version
|
||||||
|
|
||||||
0.9.17
|
0.9.18
|
||||||
|
|
||||||
</h1>
|
</h1>
|
||||||
<h2>Options Documentation</h2>
|
<h2>Options Documentation</h2>
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ alt="Tux Paint"><br>
|
||||||
|
|
||||||
version
|
version
|
||||||
|
|
||||||
0.9.17
|
0.9.18
|
||||||
|
|
||||||
</h1>
|
</h1>
|
||||||
<h3>A simple drawing program for children</h3>
|
<h3>A simple drawing program for children</h3>
|
||||||
|
|
|
||||||
|
|
@ -1,176 +1,481 @@
|
||||||
|
/* tp_magic_example.c
|
||||||
|
|
||||||
|
An example of a "Magic" tool plugin for Tux Paint
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Inclusion of header files: */
|
||||||
|
/* -------------------------- */
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h> // For "strdup()"
|
||||||
#include <libintl.h>
|
#include <libintl.h> // For "gettext()"
|
||||||
#include "tp_magic_api.h"
|
|
||||||
#include "SDL_image.h"
|
#include "tp_magic_api.h" // Tux Paint "Magic" tool API header
|
||||||
#include "SDL_mixer.h"
|
#include "SDL_image.h" // For IMG_Load(), to load our PNG icon
|
||||||
|
#include "SDL_mixer.h" // For Mix_LoadWAV(), to load our sound effects
|
||||||
|
|
||||||
|
|
||||||
|
/* Tool Enumerations: */
|
||||||
|
/* ------------------ */
|
||||||
|
|
||||||
/* What tools we contain: */
|
/* What tools we contain: */
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
TOOL_ONE,
|
TOOL_ONE, // Becomes '0'
|
||||||
TOOL_TWO,
|
TOOL_TWO, // Becomes '1'
|
||||||
NUM_TOOLS
|
NUM_TOOLS // Becomes '2'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Our globals: */
|
/* A list of filenames for sounds and icons to load at startup: */
|
||||||
|
|
||||||
|
const char * snd_filenames[NUM_TOOLS] = {
|
||||||
|
"one.wav",
|
||||||
|
"two.wav"
|
||||||
|
};
|
||||||
|
|
||||||
|
const char * icon_filenames[NUM_TOOLS] = {
|
||||||
|
"one.png",
|
||||||
|
"two.png"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Below, we define a macro called "gettext_noop()" that does nothing in our
|
||||||
|
// code when compiled (it simply disappears; e.g., 'gettext_noop("foo")'
|
||||||
|
// becomes simply "foo"), but is useful because the gettext localization
|
||||||
|
// tools will look for it and create a catalog of strings that should be
|
||||||
|
// translated into other languages.
|
||||||
|
|
||||||
|
#ifndef gettext_noop
|
||||||
|
#define gettext_noop(String) String
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// We'll use this macro below, in some arrays of strings (char *'s) that
|
||||||
|
// hold the names and descriptions of our "Magic" tools.
|
||||||
|
|
||||||
|
|
||||||
|
/* A list of names for the tools */
|
||||||
|
|
||||||
|
const char * names[NUM_TOOLS] = {
|
||||||
|
gettext_noop("A tool"),
|
||||||
|
gettext_noop("Another tool")
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* A list of descriptions of the tools */
|
||||||
|
|
||||||
|
const char * descs[NUM_TOOLS] = {
|
||||||
|
gettext_noop("This is example tool number 1."),
|
||||||
|
gettext_noop("This is example tool number 2.")
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Our global variables: */
|
||||||
|
/* --------------------- */
|
||||||
|
|
||||||
|
/* Sound effects: */
|
||||||
Mix_Chunk * snd_effect[NUM_TOOLS];
|
Mix_Chunk * snd_effect[NUM_TOOLS];
|
||||||
|
|
||||||
|
/* The current color (an "RGB" value) the user has selected in Tux Paint: */
|
||||||
Uint8 example_r, example_g, example_b;
|
Uint8 example_r, example_g, example_b;
|
||||||
|
|
||||||
|
|
||||||
Uint32 example_api_version(void) { return(TP_MAGIC_API_VERSION); }
|
/* Our local function prototypes: */
|
||||||
|
/* ------------------------------ */
|
||||||
|
|
||||||
|
// These functions are called by other functions within our plugin,
|
||||||
|
// so we provide a 'prototype' of them, so the compiler knows what
|
||||||
|
// they accept and return. This lets us use them in other functions
|
||||||
|
// that are declared _before_ them.
|
||||||
|
|
||||||
|
void example_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 example_line_callback(void * ptr, int which,
|
||||||
|
SDL_Surface * canvas, SDL_Surface * snapshot,
|
||||||
|
int x, int y);
|
||||||
|
|
||||||
|
|
||||||
// No setup required:
|
/* Setup Functions: */
|
||||||
|
/* ---------------- */
|
||||||
|
|
||||||
|
// API Version check
|
||||||
|
//
|
||||||
|
// The running copy of Tux Paint that has loaded us first asks us what
|
||||||
|
// version of the Tux Paint "Magic" tool plugin API we were built against.
|
||||||
|
// If it deems us compatible, we'll be used!
|
||||||
|
//
|
||||||
|
// All we need to do here is return "TP_MAGIC_API_VERSION",
|
||||||
|
// which is #define'd in tp_magic_api.h.
|
||||||
|
|
||||||
|
Uint32 example_api_version(void)
|
||||||
|
{
|
||||||
|
return(TP_MAGIC_API_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Initialization
|
||||||
|
//
|
||||||
|
// This happens once, when Tux Paint starts up and is loading all of the
|
||||||
|
// "Magic" tool plugins. (Assuming what we returned from api_version() was
|
||||||
|
// acceptable!)
|
||||||
|
//
|
||||||
|
// All we're doing in this example is loading our sound effects,
|
||||||
|
// which we'll use later (in click(), drag() and release())
|
||||||
|
// when the user is using our Magic tools.
|
||||||
|
//
|
||||||
|
// The memory we allocate here to store the sounds will be
|
||||||
|
// freed (aka released, aka deallocated) when the user quits Tux Paint,
|
||||||
|
// when our shutdown() function is called.
|
||||||
|
|
||||||
int example_init(magic_api * api)
|
int example_init(magic_api * api)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
char fname[1024];
|
char fname[1024];
|
||||||
|
|
||||||
snprintf(fname, sizeof(fname), "%s/sounds/magic/one.wav",
|
for (i = 0; i < NUM_TOOLS; i++)
|
||||||
api->data_directory);
|
{
|
||||||
snd_effect[0] = Mix_LoadWAV(fname);
|
// Assemble the filename from the "snd_filenames[]" array into
|
||||||
|
// a full path to a real file.
|
||||||
|
//
|
||||||
|
// Use "api->data_directory" to figure out where our sounds should be.
|
||||||
|
// (The "tp-magic-config --dataprefix" command would have told us when
|
||||||
|
// we installed our plugin and its data.)
|
||||||
|
|
||||||
snprintf(fname, sizeof(fname), "%s/sounds/magic/two.wav",
|
snprintf(fname, sizeof(fname),
|
||||||
api->data_directory);
|
"%s/sounds/magic/%s.wav",
|
||||||
snd_effect[1] = Mix_LoadWAV(fname);
|
api->data_directory, snd_filenames[i]);
|
||||||
|
|
||||||
|
|
||||||
|
// Try to load the file!
|
||||||
|
|
||||||
|
snd_effect[i] = Mix_LoadWAV(fname);
|
||||||
|
}
|
||||||
|
|
||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have multiple tools:
|
|
||||||
|
// Report our tool count
|
||||||
|
//
|
||||||
|
// Tux Paint needs to know how many "Magic" tools we'll be providing.
|
||||||
|
// Return that number here. (We simply grab the value of "NUM_TOOLS"
|
||||||
|
// from our 'enum' above!)
|
||||||
|
//
|
||||||
|
// When Tux Paint is starting up and loading plugins, it will call
|
||||||
|
// some of the following setup functions once for each tool we report.
|
||||||
|
|
||||||
int example_get_tool_count(magic_api * api)
|
int example_get_tool_count(magic_api * api)
|
||||||
{
|
{
|
||||||
return(NUM_TOOLS);
|
return(NUM_TOOLS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load our icons:
|
|
||||||
|
// Load icons
|
||||||
|
//
|
||||||
|
// When Tux Paint is starting up and loading plugins, it asks us to
|
||||||
|
// provide icons for the "Magic" tool buttons.
|
||||||
|
|
||||||
SDL_Surface * example_get_icon(magic_api * api, int which)
|
SDL_Surface * example_get_icon(magic_api * api, int which)
|
||||||
{
|
{
|
||||||
char fname[1024];
|
char fname[1024];
|
||||||
|
|
||||||
if (which == TOOL_ONE)
|
// Assemble the filename from the "icon_filenames[]" array into
|
||||||
{
|
// a full path to a real file.
|
||||||
snprintf(fname, sizeof(fname), "%s/images/magic/one.png",
|
//
|
||||||
api->data_directory);
|
// Use "api->data_directory" to figure out where our sounds should be.
|
||||||
}
|
// (The "tp-magic-config --dataprefix" command would have told us when
|
||||||
else if (which == TOOL_TWO)
|
// we installed our plugin and its data.)
|
||||||
{
|
//
|
||||||
snprintf(fname, sizeof(fname), "%s/images/magic/two.png",
|
// We use 'which' (which of our tools Tux Paint is asking about)
|
||||||
api->data_directory);
|
// as an index into the array.
|
||||||
}
|
|
||||||
|
snprintf(fname, sizeof(fname), "%s/images/magic/%s.png",
|
||||||
|
api->data_directory, icon_filenames[which]);
|
||||||
|
|
||||||
|
|
||||||
|
// Try to load the image, and return the results to Tux Paint:
|
||||||
|
|
||||||
return(IMG_Load(fname));
|
return(IMG_Load(fname));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return our names, localized:
|
|
||||||
|
// Report our "Magic" tool names
|
||||||
|
//
|
||||||
|
// When Tux Paint is starting up and loading plugins, it asks us to
|
||||||
|
// provide names (labels) for the "Magic" tool buttons.
|
||||||
|
|
||||||
char * example_get_name(magic_api * api, int which)
|
char * example_get_name(magic_api * api, int which)
|
||||||
{
|
{
|
||||||
if (which == TOOL_ONE)
|
const char * our_name_english;
|
||||||
return(strdup(gettext("One")));
|
const char * our_name_localized;
|
||||||
else if (which == TOOL_TWO)
|
|
||||||
return(strdup(gettext("Two")));
|
|
||||||
|
|
||||||
return(NULL);
|
// Get our name from the "names[]" array.
|
||||||
|
//
|
||||||
|
// We use 'which' (which of our tools Tux Paint is asking about)
|
||||||
|
// as an index into the array.
|
||||||
|
|
||||||
|
our_name_english = names[which];
|
||||||
|
|
||||||
|
|
||||||
|
// Return a localized (aka translated) version of our name,
|
||||||
|
// if possible.
|
||||||
|
//
|
||||||
|
// We send "gettext()" the English version of the name from our array.
|
||||||
|
|
||||||
|
our_name_localized = gettext(our_name_english);
|
||||||
|
|
||||||
|
|
||||||
|
// Finally, duplicate the string into a new section of memory, and
|
||||||
|
// send it to Tux Paint. (Tux Paint keeps track of the string and
|
||||||
|
// will free it for us, so we have one less thing to keep track of.)
|
||||||
|
|
||||||
|
return(strdup(our_name_localized));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return our descriptions, localized:
|
|
||||||
|
// Report our "Magic" tool descriptions
|
||||||
|
//
|
||||||
|
// When Tux Paint is starting up and loading plugins, it asks us to
|
||||||
|
// provide names (labels) for the "Magic" tool buttons.
|
||||||
|
|
||||||
char * example_get_description(magic_api * api, int which)
|
char * example_get_description(magic_api * api, int which)
|
||||||
{
|
{
|
||||||
if (which == TOOL_ONE)
|
const char * our_desc_english;
|
||||||
return(strdup(gettext("Tool one.")));
|
const char * our_desc_localized;
|
||||||
else
|
|
||||||
return(strdup(gettext("Tool two.")));
|
|
||||||
|
|
||||||
return(NULL);
|
// Get our desc from the "descs[]" array.
|
||||||
|
//
|
||||||
|
// We use 'which' (which of our tools Tux Paint is asking about)
|
||||||
|
// as an index into the array.
|
||||||
|
|
||||||
|
our_desc_english = descs[which];
|
||||||
|
|
||||||
|
|
||||||
|
// Return a localized (aka translated) version of our description,
|
||||||
|
// if possible.
|
||||||
|
//
|
||||||
|
// We send "gettext()" the English version of the description from our array.
|
||||||
|
|
||||||
|
our_desc_localized = gettext(our_desc_english);
|
||||||
|
|
||||||
|
|
||||||
|
// Finally, duplicate the string into a new section of memory, and
|
||||||
|
// send it to Tux Paint. (Tux Paint keeps track of the string and
|
||||||
|
// will free it for us, so we have one less thing to keep track of.)
|
||||||
|
|
||||||
|
return(strdup(our_desc_localized));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do the effect:
|
// Report whether we accept colors
|
||||||
|
|
||||||
void do_example(void * ptr, int which, SDL_Surface * canvas, SDL_Surface * last,
|
int example_requires_colors(magic_api * api, int which)
|
||||||
int x, int y)
|
|
||||||
{
|
{
|
||||||
magic_api * api = (magic_api *) ptr;
|
// Both of our tools accept colors, so we're always returning '1' (for "true")
|
||||||
int xx, yy;
|
|
||||||
|
|
||||||
if (which == TOOL_ONE)
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Shut down
|
||||||
|
//
|
||||||
|
// Tux Paint is quitting. When it quits, it asks all of the plugins
|
||||||
|
// to 'clean up' after themselves. We, for example, loaded some sound
|
||||||
|
// effects at startup (in our init() function), so we should free the
|
||||||
|
// memory used by them now.
|
||||||
|
|
||||||
|
void example_shutdown(magic_api * api)
|
||||||
{
|
{
|
||||||
api->putpixel(canvas, x, y, SDL_MapRGB(canvas->format,
|
int i;
|
||||||
example_r,
|
|
||||||
example_g,
|
// Free (aka release, aka deallocate) the memory used to store the
|
||||||
example_b));
|
// sound effects that we loaded during init():
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_TOOLS; i++)
|
||||||
|
Mix_FreeChunk(snd_effect[i]);
|
||||||
}
|
}
|
||||||
else if (which == TOOL_TWO)
|
|
||||||
|
|
||||||
|
/* Functions that respond to events in Tux Paint: */
|
||||||
|
/* ---------------------------------------------- */
|
||||||
|
|
||||||
|
// Affect the canvas on click:
|
||||||
|
|
||||||
|
void example_click(magic_api * api, int which,
|
||||||
|
SDL_Surface * canvas, SDL_Surface * snapshot,
|
||||||
|
int x, int y, SDL_Rect * update_rect)
|
||||||
{
|
{
|
||||||
for (yy = -4; yy < 4; yy++)
|
// In our case, a single click (which is also the start of a drag!)
|
||||||
{
|
// is identical to what dragging does, but just at one point, rather
|
||||||
for (xx = -4; xx < 4; xx++)
|
// than across a line.
|
||||||
{
|
//
|
||||||
api->putpixel(canvas, x + xx, y + yy,
|
// So we 'cheat' here, by calling our draw() function with
|
||||||
api->getpixel(last,
|
// (x,y) for both the beginning and end points of a line.
|
||||||
canvas->w - x - xx,
|
|
||||||
canvas->h - y - yy));
|
example_drag(api, which, canvas, snapshot, x, y, x, y, update_rect);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Affect the canvas on drag:
|
// Affect the canvas on drag:
|
||||||
|
|
||||||
void example_drag(magic_api * api, int which, SDL_Surface * canvas,
|
void example_drag(magic_api * api, int which, SDL_Surface * canvas,
|
||||||
SDL_Surface * last, int ox, int oy, int x, int y,
|
SDL_Surface * snapshot, int ox, int oy, int x, int y,
|
||||||
SDL_Rect * update_rect)
|
SDL_Rect * update_rect)
|
||||||
{
|
{
|
||||||
api->line(which, canvas, last, ox, oy, x, y, 1, do_example);
|
// Call Tux Paint's "line()" function.
|
||||||
|
//
|
||||||
|
// It will calculate a straight line between (ox,ox) and (x,y).
|
||||||
|
// Every N steps along that line (in this case, N is '1'), it
|
||||||
|
// will call _our_ function, "example_line_callback()", and send
|
||||||
|
// the current X,Y coordinates along the line, as well as other
|
||||||
|
// useful things (which of our "Magic" tools is being used and
|
||||||
|
// the current and snapshot canvases).
|
||||||
|
|
||||||
|
api->line(which, canvas, snapshot, ox, oy, x, y, 1, example_line_callback);
|
||||||
|
|
||||||
|
|
||||||
|
// If we need to, swap the X and/or Y values, so that
|
||||||
|
// (ox,oy) is always the top left, and (x,y) is always the bottom right,
|
||||||
|
// so the values we put inside "update_rect" make sense:
|
||||||
|
|
||||||
if (ox > x) { int tmp = ox; ox = x; x = tmp; }
|
if (ox > x) { int tmp = ox; ox = x; x = tmp; }
|
||||||
if (oy > y) { int tmp = oy; oy = y; y = tmp; }
|
if (oy > y) { int tmp = oy; oy = y; y = tmp; }
|
||||||
|
|
||||||
|
|
||||||
|
// Fill in the elements of the "update_rect" SDL_Rect structure
|
||||||
|
// that Tux Paint is sharing with us.
|
||||||
|
|
||||||
update_rect->x = ox - 4;
|
update_rect->x = ox - 4;
|
||||||
update_rect->y = oy - 4;
|
update_rect->y = oy - 4;
|
||||||
update_rect->w = (x + 4) - update_rect->x;
|
update_rect->w = (x + 4) - update_rect->x;
|
||||||
update_rect->h = (y + 4) - update_rect->h;
|
update_rect->h = (y + 4) - update_rect->h;
|
||||||
|
|
||||||
|
|
||||||
|
// Play the appropriate sound effect
|
||||||
|
//
|
||||||
|
// We're calculating a value between 0-255 for where the mouse is
|
||||||
|
// across the canvas (0 is the left, ~128 is the center, 255 is the right).
|
||||||
|
//
|
||||||
|
// These are the exact values Tux Paint's "playsound()" wants,
|
||||||
|
// to determine what speaker to play the sound in.
|
||||||
|
// (So the sound will pan from speaker to speaker as you drag the
|
||||||
|
// mouse around the canvas!)
|
||||||
|
|
||||||
api->playsound(snd_effect[which],
|
api->playsound(snd_effect[which],
|
||||||
(x * 255) / canvas->w, (y * 255) / canvas->h);
|
(x * 255) / canvas->w, // pan
|
||||||
|
255); // distance
|
||||||
}
|
}
|
||||||
|
|
||||||
// Affect the canvas on click:
|
|
||||||
void example_click(magic_api * api, int which,
|
|
||||||
SDL_Surface * canvas, SDL_Surface * last,
|
|
||||||
int x, int y, SDL_Rect * update_rect)
|
|
||||||
{
|
|
||||||
example_drag(api, which, canvas, last, x, y, x, y, update_rect);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Affect the canvas on release:
|
// Affect the canvas on release:
|
||||||
|
|
||||||
void example_release(magic_api * api, int which,
|
void example_release(magic_api * api, int which,
|
||||||
SDL_Surface * canvas, SDL_Surface * last,
|
SDL_Surface * canvas, SDL_Surface * snapshot,
|
||||||
int x, int y, SDL_Rect * update_rect)
|
int x, int y, SDL_Rect * update_rect)
|
||||||
{
|
{
|
||||||
|
// Neither of our effects do anything special when the mouse is released
|
||||||
|
// from a click or click-and-drag, so there's no code here...
|
||||||
}
|
}
|
||||||
|
|
||||||
// No setup happened:
|
|
||||||
void example_shutdown(magic_api * api)
|
|
||||||
{
|
|
||||||
if (snd_effect[0] != NULL)
|
|
||||||
Mix_FreeChunk(snd_effect[0]);
|
|
||||||
|
|
||||||
if (snd_effect[1] != NULL)
|
// Accept colors
|
||||||
Mix_FreeChunk(snd_effect[1]);
|
//
|
||||||
}
|
// When any of our "Magic" tools are activated by the user,
|
||||||
|
// if that tool accepts colors, the current color selection is sent to us.
|
||||||
|
//
|
||||||
|
// Additionally, if one of our color-accepting tools is active when the
|
||||||
|
// user changes colors, we'll be informed of that, as well.
|
||||||
|
//
|
||||||
|
// The color comes in as RGB values.
|
||||||
|
|
||||||
// Record the color from Tux Paint:
|
|
||||||
void example_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b)
|
void example_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b)
|
||||||
{
|
{
|
||||||
|
// We simply store the RGB values in the global variables we
|
||||||
|
// declared at the top of this file.
|
||||||
|
|
||||||
example_r = r;
|
example_r = r;
|
||||||
example_g = g;
|
example_g = g;
|
||||||
example_b = b;
|
example_b = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use colors:
|
|
||||||
int example_requires_colors(magic_api * api, int which)
|
/* The Magic Effect Routines! */
|
||||||
|
/* -------------------------- */
|
||||||
|
|
||||||
|
// Our "callback" function
|
||||||
|
//
|
||||||
|
// We do the 'work' in this callback. Our plugin file has just one.
|
||||||
|
// Some "Magic" tool plugins may have more, depending on the tools they're
|
||||||
|
// providing. Some have none (since they're not click-and-drag
|
||||||
|
// painting-style tools).
|
||||||
|
//
|
||||||
|
// Our callback function gets called once for every point along a line between
|
||||||
|
// the mouse's previous and current position, as it's being dragged.
|
||||||
|
//
|
||||||
|
// It pays attention to 'which' to determine which of our plugin's tools
|
||||||
|
// is currently selected.
|
||||||
|
|
||||||
|
void example_line_callback(void * ptr, int which,
|
||||||
|
SDL_Surface * canvas, SDL_Surface * snapshot,
|
||||||
|
int x, int y)
|
||||||
{
|
{
|
||||||
return 1;
|
// For technical reasons, we can't accept a pointer to the "magic_api"
|
||||||
|
// struct, like the other functions do.
|
||||||
|
//
|
||||||
|
// Instead, we receive a 'generic' pointer (a "void *").
|
||||||
|
// The line below declares a local "magic_api" pointer variable called "api",
|
||||||
|
// and then assigns it to the value of the 'generic' pointer we received.
|
||||||
|
//
|
||||||
|
// (The "(magic_api *)" casts the generic pointer into the 'type' of
|
||||||
|
// pointer we want, a pointer to a "magic_api".)
|
||||||
|
magic_api * api = (magic_api *) ptr;
|
||||||
|
int xx, yy;
|
||||||
|
|
||||||
|
|
||||||
|
// This function handles both of our tools, so we need to check which
|
||||||
|
// is being used right now. We compare the 'which' argument that
|
||||||
|
// Tux Paint sends to us with the values we enumerated above.
|
||||||
|
|
||||||
|
if (which == TOOL_ONE)
|
||||||
|
{
|
||||||
|
// Tool number 1 simply draws a single pixel at the (x,y) location.
|
||||||
|
// It's a 1x1 pixel brush
|
||||||
|
|
||||||
|
api->putpixel(canvas, x, y, SDL_MapRGB(canvas->format,
|
||||||
|
example_r,
|
||||||
|
example_g,
|
||||||
|
example_b));
|
||||||
|
|
||||||
|
// We use "SDL_MapRGB()" to convert the RGB value we receive from Tux Paint
|
||||||
|
// for the user's current color selection to a 'Uint32' pixel value
|
||||||
|
// we can send to Tux Paint's "putpixel()" function.
|
||||||
|
}
|
||||||
|
else if (which == TOOL_TWO)
|
||||||
|
{
|
||||||
|
// Tool number 2 copies an 8x8 square of pixels from the opposite side
|
||||||
|
// of the canvas and puts it under the cursor
|
||||||
|
|
||||||
|
for (yy = -4; yy < 4; yy++)
|
||||||
|
{
|
||||||
|
for (xx = -4; xx < 4; xx++)
|
||||||
|
{
|
||||||
|
api->putpixel(canvas, x + xx, y + yy,
|
||||||
|
api->getpixel(snapshot,
|
||||||
|
canvas->w - x - xx,
|
||||||
|
canvas->h - y - yy));
|
||||||
|
|
||||||
|
// We simply use Tux Paint's "getpixel()" routine to pull pixel
|
||||||
|
// values from the 'snapshot', and then "putpixel()" to draw them
|
||||||
|
// right into the 'canvas'.
|
||||||
|
|
||||||
|
// Note: putpixel() and getpixel() are safe to use, even if your
|
||||||
|
// X,Y values are outside of the SDL surface (e.g., negative, or
|
||||||
|
// greater than the surface's width or height).
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
376
src/tuxpaint.c
376
src/tuxpaint.c
|
|
@ -1160,7 +1160,10 @@ typedef struct stamp_type
|
||||||
SDL_Surface *thumbnail;
|
SDL_Surface *thumbnail;
|
||||||
unsigned thumb_mirrored:1;
|
unsigned thumb_mirrored:1;
|
||||||
unsigned thumb_flipped:1;
|
unsigned thumb_flipped:1;
|
||||||
|
unsigned thumb_mirrored_flipped:1;
|
||||||
unsigned no_premirror:1;
|
unsigned no_premirror:1;
|
||||||
|
unsigned no_preflip:1;
|
||||||
|
unsigned no_premirrorflip:1;
|
||||||
|
|
||||||
unsigned processed:1; // got *.dat, computed size limits, etc.
|
unsigned processed:1; // got *.dat, computed size limits, etc.
|
||||||
|
|
||||||
|
|
@ -5206,9 +5209,8 @@ static void set_active_stamp(void)
|
||||||
{
|
{
|
||||||
stamp_type *sd = stamp_data[stamp_group][cur_stamp[stamp_group]];
|
stamp_type *sd = stamp_data[stamp_group][cur_stamp[stamp_group]];
|
||||||
unsigned len = strlen(sd->stampname);
|
unsigned len = strlen(sd->stampname);
|
||||||
char *buf = alloca(len + strlen("_mirror.EXT") + 1);
|
char *buf = alloca(len + strlen("_mirror_flip.EXT") + 1);
|
||||||
|
int needs_mirror, needs_flip;
|
||||||
/* FIXME: Add support for pre-flipped stamps! -bjk 2007.03.22 */
|
|
||||||
|
|
||||||
if (active_stamp)
|
if (active_stamp)
|
||||||
SDL_FreeSurface(active_stamp);
|
SDL_FreeSurface(active_stamp);
|
||||||
|
|
@ -5216,7 +5218,49 @@ static void set_active_stamp(void)
|
||||||
|
|
||||||
memcpy(buf, sd->stampname, len);
|
memcpy(buf, sd->stampname, len);
|
||||||
|
|
||||||
if (sd->mirrored && !sd->no_premirror)
|
printf("\nset_active_stamp()\n");
|
||||||
|
|
||||||
|
/* Look for pre-mirrored and pre-flipped version: */
|
||||||
|
|
||||||
|
needs_mirror = sd->mirrored;
|
||||||
|
needs_flip = sd->flipped;
|
||||||
|
|
||||||
|
if (sd->mirrored && sd->flipped)
|
||||||
|
{
|
||||||
|
/* Want mirrored and flipped, both */
|
||||||
|
|
||||||
|
printf("want both mirrored & flipped\n");
|
||||||
|
|
||||||
|
if (!sd->no_premirrorflip)
|
||||||
|
{
|
||||||
|
#ifndef NOSVG
|
||||||
|
memcpy(buf + len, "_mirror_flip.svg", 17);
|
||||||
|
active_stamp = do_loadimage(buf, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (active_stamp == NULL)
|
||||||
|
{
|
||||||
|
memcpy(buf + len, "_mirror_flip.png", 17);
|
||||||
|
active_stamp = do_loadimage(buf, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (active_stamp != NULL)
|
||||||
|
{
|
||||||
|
printf("found a _mirror_flip!\n");
|
||||||
|
|
||||||
|
needs_mirror = 0;
|
||||||
|
needs_flip = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Couldn't get one that was both, look for _mirror then _flip and
|
||||||
|
flip or mirror it: */
|
||||||
|
|
||||||
|
printf("didn't find a _mirror_flip\n");
|
||||||
|
|
||||||
|
if (!sd->no_premirror)
|
||||||
{
|
{
|
||||||
#ifndef NOSVG
|
#ifndef NOSVG
|
||||||
memcpy(buf + len, "_mirror.svg", 12);
|
memcpy(buf + len, "_mirror.svg", 12);
|
||||||
|
|
@ -5230,8 +5274,101 @@ static void set_active_stamp(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (active_stamp != NULL)
|
||||||
|
{
|
||||||
|
printf("found a _mirror!\n");
|
||||||
|
needs_mirror = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Couldn't get one that was just pre-mirrored, look for a
|
||||||
|
pre-flipped */
|
||||||
|
|
||||||
|
printf("didn't find a _mirror, either\n");
|
||||||
|
|
||||||
|
if (!sd->no_preflip)
|
||||||
|
{
|
||||||
|
#ifndef NOSVG
|
||||||
|
memcpy(buf + len, "_flip.svg", 10);
|
||||||
|
active_stamp = do_loadimage(buf, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (active_stamp == NULL)
|
||||||
|
{
|
||||||
|
memcpy(buf + len, "_flip.png", 10);
|
||||||
|
active_stamp = do_loadimage(buf, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (active_stamp != NULL)
|
||||||
|
{
|
||||||
|
printf("found a _flip!\n");
|
||||||
|
needs_flip = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
printf("didn't find a _flip, either\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (sd->flipped && !sd->no_preflip)
|
||||||
|
{
|
||||||
|
/* Want flipped only */
|
||||||
|
|
||||||
|
printf("want flipped only\n");
|
||||||
|
|
||||||
|
#ifndef NOSVG
|
||||||
|
memcpy(buf + len, "_flip.svg", 10);
|
||||||
|
active_stamp = do_loadimage(buf, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (active_stamp == NULL)
|
||||||
|
{
|
||||||
|
memcpy(buf + len, "_flip.png", 10);
|
||||||
|
active_stamp = do_loadimage(buf, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (active_stamp != NULL)
|
||||||
|
{
|
||||||
|
printf("found a _flip!\n");
|
||||||
|
needs_flip = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
printf("didn't find a _flip\n");
|
||||||
|
}
|
||||||
|
else if (sd->mirrored && !sd->no_premirror)
|
||||||
|
{
|
||||||
|
/* Want mirrored only */
|
||||||
|
|
||||||
|
printf("want mirrored only\n");
|
||||||
|
|
||||||
|
#ifndef NOSVG
|
||||||
|
memcpy(buf + len, "_mirror.svg", 12);
|
||||||
|
active_stamp = do_loadimage(buf, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (active_stamp == NULL)
|
||||||
|
{
|
||||||
|
memcpy(buf + len, "_mirror.png", 12);
|
||||||
|
active_stamp = do_loadimage(buf, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (active_stamp != NULL)
|
||||||
|
{
|
||||||
|
printf("found a _mirror!\n");
|
||||||
|
needs_mirror = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
printf("didn't find a _mirror\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Didn't want mirrored, or flipped, or couldn't load anything
|
||||||
|
that was pre-rendered: */
|
||||||
|
|
||||||
if (!active_stamp)
|
if (!active_stamp)
|
||||||
{
|
{
|
||||||
|
printf("loading normal\n");
|
||||||
|
|
||||||
#ifndef NOSVG
|
#ifndef NOSVG
|
||||||
memcpy(buf + len, ".svg", 5);
|
memcpy(buf + len, ".svg", 5);
|
||||||
active_stamp = do_loadimage(buf, 0);
|
active_stamp = do_loadimage(buf, 0);
|
||||||
|
|
@ -5243,27 +5380,44 @@ static void set_active_stamp(void)
|
||||||
active_stamp = do_loadimage(buf, 0);
|
active_stamp = do_loadimage(buf, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Never allow a NULL image! */
|
||||||
|
|
||||||
if (!active_stamp)
|
if (!active_stamp)
|
||||||
active_stamp = thumbnail(img_dead40x40, 40, 40, 1); // copy it
|
active_stamp = thumbnail(img_dead40x40, 40, 40, 1); // copy it
|
||||||
if (sd->mirrored)
|
|
||||||
|
|
||||||
|
/* If we wanted mirrored or flipped, and didn't get something pre-rendered,
|
||||||
|
do it to the image we did load: */
|
||||||
|
|
||||||
|
if (needs_mirror)
|
||||||
|
{
|
||||||
|
printf("mirroring\n");
|
||||||
active_stamp = mirror_surface(active_stamp);
|
active_stamp = mirror_surface(active_stamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sd->flipped)
|
if (needs_flip)
|
||||||
|
{
|
||||||
|
printf("flipping\n");
|
||||||
active_stamp = flip_surface(active_stamp);
|
active_stamp = flip_surface(active_stamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf("\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
static void get_stamp_thumb(stamp_type * sd)
|
static void get_stamp_thumb(stamp_type * sd)
|
||||||
{
|
{
|
||||||
SDL_Surface *bigimg = NULL;
|
SDL_Surface *bigimg = NULL;
|
||||||
unsigned len = strlen(sd->stampname);
|
unsigned len = strlen(sd->stampname);
|
||||||
char *buf = alloca(len + strlen("_mirror.EXT") + 1);
|
char *buf = alloca(len + strlen("_mirror_flip.EXT") + 1);
|
||||||
SDL_Surface *wrongmirror = NULL;
|
int need_mirror, need_flip;
|
||||||
int need_mirror = 0;
|
|
||||||
double ratio;
|
double ratio;
|
||||||
unsigned w;
|
unsigned w;
|
||||||
unsigned h;
|
unsigned h;
|
||||||
|
|
||||||
|
printf("\nget_stamp_thumb()\n");
|
||||||
|
|
||||||
memcpy(buf, sd->stampname, len);
|
memcpy(buf, sd->stampname, len);
|
||||||
|
|
||||||
if (!sd->processed)
|
if (!sd->processed)
|
||||||
|
|
@ -5302,25 +5456,111 @@ static void get_stamp_thumb(stamp_type * sd)
|
||||||
sd->no_txt = !sd->stxt;
|
sd->no_txt = !sd->stxt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// first see if we can re-use an existing thumbnail
|
// first see if we can re-use an existing thumbnail
|
||||||
if (sd->thumbnail)
|
if (sd->thumbnail)
|
||||||
{
|
{
|
||||||
if (sd->mirrored == sd->thumb_mirrored)
|
printf("have an sd->thumbnail\n");
|
||||||
|
|
||||||
|
if (sd->thumb_mirrored_flipped == sd->flipped &&
|
||||||
|
sd->thumb_mirrored_flipped == sd->mirrored &&
|
||||||
|
sd->mirrored == sd->thumb_mirrored &&
|
||||||
|
sd->flipped == sd->thumb_flipped)
|
||||||
{
|
{
|
||||||
if (sd->flipped == sd->thumb_flipped)
|
// It's already the way we want
|
||||||
return;
|
printf("mirrored == flipped == thumb_mirrored_flipped [bye]\n");
|
||||||
sd->thumbnail = flip_surface(sd->thumbnail);
|
|
||||||
sd->thumb_flipped = !sd->thumb_flipped;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
wrongmirror = sd->thumbnail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: Add support for pre-flipped stamps! -bjk 2007.03.22 */
|
|
||||||
|
|
||||||
// nope, unless perhaps it can be mirrored
|
// nope, see if there's a pre-rendered one we can use
|
||||||
if (sd->mirrored && !sd->no_premirror)
|
|
||||||
|
need_mirror = sd->mirrored;
|
||||||
|
need_flip = sd->flipped;
|
||||||
|
bigimg = NULL;
|
||||||
|
|
||||||
|
if (sd->mirrored && sd->flipped)
|
||||||
{
|
{
|
||||||
|
printf("want mirrored & flipped\n");
|
||||||
|
|
||||||
|
if (!sd->no_premirrorflip)
|
||||||
|
{
|
||||||
|
memcpy(buf + len, "_mirror_flip.png", 17);
|
||||||
|
bigimg = do_loadimage(buf, 0);
|
||||||
|
|
||||||
|
#ifndef NOSVG
|
||||||
|
if (bigimg == NULL)
|
||||||
|
{
|
||||||
|
memcpy(buf + len, "_mirror_flip.svg", 17);
|
||||||
|
bigimg = do_loadimage(buf, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bigimg)
|
||||||
|
{
|
||||||
|
printf("found a _mirror_flip!\n");
|
||||||
|
|
||||||
|
need_mirror = 0;
|
||||||
|
need_flip = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("didn't find a mirror_flip\n");
|
||||||
|
sd->no_premirrorflip = 1;
|
||||||
|
|
||||||
|
if (!sd->no_premirror)
|
||||||
|
{
|
||||||
|
memcpy(buf + len, "_mirror.png", 12);
|
||||||
|
bigimg = do_loadimage(buf, 0);
|
||||||
|
|
||||||
|
#ifndef NOSVG
|
||||||
|
if (bigimg == NULL)
|
||||||
|
{
|
||||||
|
memcpy(buf + len, "_mirror.svg", 12);
|
||||||
|
bigimg = do_loadimage(buf, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bigimg)
|
||||||
|
{
|
||||||
|
printf("found a _mirror\n");
|
||||||
|
|
||||||
|
need_mirror = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("didn't find a mirror\n");
|
||||||
|
|
||||||
|
if (!sd->no_preflip)
|
||||||
|
{
|
||||||
|
memcpy(buf + len, "_flip.png", 10);
|
||||||
|
bigimg = do_loadimage(buf, 0);
|
||||||
|
|
||||||
|
#ifndef NOSVG
|
||||||
|
if (bigimg == NULL)
|
||||||
|
{
|
||||||
|
memcpy(buf + len, "_flip.svg", 10);
|
||||||
|
bigimg = do_loadimage(buf, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bigimg)
|
||||||
|
{
|
||||||
|
printf("found a _flip\n");
|
||||||
|
|
||||||
|
need_flip = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (sd->mirrored && !sd->no_premirror)
|
||||||
|
{
|
||||||
|
printf("want mirrored only\n");
|
||||||
|
|
||||||
memcpy(buf + len, "_mirror.png", 12);
|
memcpy(buf + len, "_mirror.png", 12);
|
||||||
bigimg = do_loadimage(buf, 0);
|
bigimg = do_loadimage(buf, 0);
|
||||||
|
|
||||||
|
|
@ -5334,26 +5574,49 @@ static void get_stamp_thumb(stamp_type * sd)
|
||||||
|
|
||||||
if (bigimg)
|
if (bigimg)
|
||||||
{
|
{
|
||||||
if (wrongmirror)
|
printf("found a _mirror!\n");
|
||||||
SDL_FreeSurface(wrongmirror);
|
need_mirror = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
printf("didn't find a mirror\n");
|
||||||
sd->no_premirror = 1;
|
sd->no_premirror = 1;
|
||||||
}
|
}
|
||||||
if (wrongmirror && sd->no_premirror)
|
|
||||||
{
|
|
||||||
wrongmirror = mirror_surface(wrongmirror);
|
|
||||||
sd->thumbnail = wrongmirror;
|
|
||||||
sd->thumb_mirrored = !sd->thumb_mirrored;
|
|
||||||
|
|
||||||
if (sd->flipped == sd->thumb_flipped)
|
|
||||||
return;
|
|
||||||
sd->thumbnail = flip_surface(sd->thumbnail);
|
|
||||||
sd->thumb_flipped = !sd->thumb_flipped;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
else if (sd->flipped && !sd->no_preflip)
|
||||||
|
{
|
||||||
|
printf("want flipped only\n");
|
||||||
|
|
||||||
|
memcpy(buf + len, "_flip.png", 10);
|
||||||
|
bigimg = do_loadimage(buf, 0);
|
||||||
|
|
||||||
|
#ifndef NOSVG
|
||||||
|
if (bigimg == NULL)
|
||||||
|
{
|
||||||
|
memcpy(buf + len, "_flip.svg", 10);
|
||||||
|
bigimg = do_loadimage(buf, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (bigimg)
|
||||||
|
{
|
||||||
|
printf("found a _flip!\n");
|
||||||
|
need_flip = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("didn't find a flip\n");
|
||||||
|
sd->no_preflip = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* If we didn't load a pre-rendered, load the normal one: */
|
||||||
|
|
||||||
if (!bigimg)
|
if (!bigimg)
|
||||||
{
|
{
|
||||||
|
printf("loading normal...\n");
|
||||||
|
|
||||||
memcpy(buf + len, ".png", 5);
|
memcpy(buf + len, ".png", 5);
|
||||||
bigimg = do_loadimage(buf, 0);
|
bigimg = do_loadimage(buf, 0);
|
||||||
|
|
||||||
|
|
@ -5364,11 +5627,11 @@ static void get_stamp_thumb(stamp_type * sd)
|
||||||
bigimg = do_loadimage(buf, 0);
|
bigimg = do_loadimage(buf, 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (sd->mirrored)
|
|
||||||
need_mirror = 1; // want to mirror after scaling
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Scale the stamp down to its thumbnail size: */
|
||||||
|
|
||||||
w = 40;
|
w = 40;
|
||||||
h = 40;
|
h = 40;
|
||||||
if (bigimg)
|
if (bigimg)
|
||||||
|
|
@ -5387,16 +5650,41 @@ static void get_stamp_thumb(stamp_type * sd)
|
||||||
else
|
else
|
||||||
sd->thumbnail = bigimg;
|
sd->thumbnail = bigimg;
|
||||||
|
|
||||||
if (need_mirror)
|
|
||||||
sd->thumbnail = mirror_surface(sd->thumbnail);
|
|
||||||
sd->thumb_mirrored = sd->mirrored;
|
|
||||||
|
|
||||||
if (sd->flipped)
|
/* Mirror and/or flip the thumbnail, if we still need to do so: */
|
||||||
|
|
||||||
|
if (need_mirror)
|
||||||
|
{
|
||||||
|
printf("mirroring\n");
|
||||||
|
sd->thumbnail = mirror_surface(sd->thumbnail);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (need_flip)
|
||||||
|
{
|
||||||
|
printf("flipping\n");
|
||||||
sd->thumbnail = flip_surface(sd->thumbnail);
|
sd->thumbnail = flip_surface(sd->thumbnail);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Note the fact that the thumbnail's mirror/flip is the same as the main
|
||||||
|
stamp: */
|
||||||
|
|
||||||
|
if (sd->mirrored && sd->flipped)
|
||||||
|
sd->thumb_mirrored_flipped = 1;
|
||||||
|
else
|
||||||
|
sd->thumb_mirrored_flipped = 0;
|
||||||
|
|
||||||
|
sd->thumb_mirrored = sd->mirrored;
|
||||||
sd->thumb_flipped = sd->flipped;
|
sd->thumb_flipped = sd->flipped;
|
||||||
|
|
||||||
|
printf("\n\n");
|
||||||
|
|
||||||
|
|
||||||
|
/* Finish up, if we need to: */
|
||||||
|
|
||||||
if (sd->processed)
|
if (sd->processed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
sd->processed = 1; // not really, but on the next line...
|
sd->processed = 1; // not really, but on the next line...
|
||||||
loadstamp_finisher(sd, w, h, ratio);
|
loadstamp_finisher(sd, w, h, ratio);
|
||||||
}
|
}
|
||||||
|
|
@ -5451,12 +5739,12 @@ static void loadstamp_callback(SDL_Surface * screen,
|
||||||
while (i--)
|
while (i--)
|
||||||
{
|
{
|
||||||
char fname[512];
|
char fname[512];
|
||||||
const char *dotext, *ext, *mirror_ext;
|
const char *dotext, *ext, *mirror_ext, *flip_ext, *mirrorflip_ext;
|
||||||
|
|
||||||
/* FIXME: Support pre-flipped stamps -bjk 2007.03.22 */
|
|
||||||
|
|
||||||
ext = ".png";
|
ext = ".png";
|
||||||
mirror_ext = "_mirror.png";
|
mirror_ext = "_mirror.png";
|
||||||
|
flip_ext = "_flip.png";
|
||||||
|
mirrorflip_ext = "_mirror_flip.png";
|
||||||
dotext = (char *) strcasestr(files[i].str, ext);
|
dotext = (char *) strcasestr(files[i].str, ext);
|
||||||
|
|
||||||
#ifndef NOSVG
|
#ifndef NOSVG
|
||||||
|
|
@ -5464,6 +5752,8 @@ static void loadstamp_callback(SDL_Surface * screen,
|
||||||
{
|
{
|
||||||
ext = ".svg";
|
ext = ".svg";
|
||||||
mirror_ext = "_mirror.svg";
|
mirror_ext = "_mirror.svg";
|
||||||
|
flip_ext = "_flip.svg";
|
||||||
|
mirrorflip_ext = "_mirror_flip.svg";
|
||||||
dotext = (char *) strcasestr(files[i].str, ext);
|
dotext = (char *) strcasestr(files[i].str, ext);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -5494,7 +5784,9 @@ static void loadstamp_callback(SDL_Surface * screen,
|
||||||
|
|
||||||
if (dotext > files[i].str && !strcasecmp(dotext, ext)
|
if (dotext > files[i].str && !strcasecmp(dotext, ext)
|
||||||
&& (dotext - files[i].str + 1 + dirlen < sizeof fname)
|
&& (dotext - files[i].str + 1 + dirlen < sizeof fname)
|
||||||
&& !strcasestr(files[i].str, mirror_ext))
|
&& !strcasestr(files[i].str, mirror_ext)
|
||||||
|
&& !strcasestr(files[i].str, flip_ext)
|
||||||
|
&& !strcasestr(files[i].str, mirrorflip_ext))
|
||||||
{
|
{
|
||||||
snprintf(fname, sizeof fname, "%s/%s", dir, files[i].str);
|
snprintf(fname, sizeof fname, "%s/%s", dir, files[i].str);
|
||||||
if (num_stamps[stamp_group] == max_stamps[stamp_group])
|
if (num_stamps[stamp_group] == max_stamps[stamp_group])
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue