Fixed New Frame: now it copies the entire Cel of the previous frame.

Fixed bugs when undo cels with offset < 0,0 (because the sign wasn't being saved)
This commit is contained in:
David Capello 2008-04-14 03:05:19 +00:00
parent f4b4996540
commit 8908d25e07
20 changed files with 411 additions and 355 deletions

View File

@ -1,3 +1,21 @@
2008-04-13 David A. Capello <dacap@users.sourceforge.net>
* src/raster/undo.c (read_raw_cel, write_raw_cel): Fixed to
read/write the position of the Cel with sign (int16_t instead of
uint16_t).
* src/commands/cmd_advanced_mode.c (cmd_advanced_mode_execute):
Fixed another typo (reported by Manuel Quiñones).
* src/dialogs/tips.c (dialogs_tips): Fixed a typo (reported by
Manuel Quiñones).
* makefile.lnx: Applied Manuel Quiñones's patch to fix the
install/uninstall rules.
* src/commands/cmd_new_frame.c (copy_cel_in_next_frame): Fixed,
now it copies the entiry cel instead of the visible area.
2008-04-11 David A. Capello <dacap@users.sourceforge.net>
* src/modules/sprites.h (ImageRef): Added.
@ -533,7 +551,7 @@
2007-11-16 David A. Capello <dacap@users.sourceforge.net>
* src/raster/cel.c: Renamed "frame" to "cel" to avoid
confusion (Manuel Quiñones advice)
confusion (Manuel Quiñones advice).
* src/modules/render.[ch]: Moved to util/.

View File

@ -1,7 +1,6 @@
Next beta
---------
- search for "TODO next release"
- Check these routines:
+ move_cel
+ copy_cel

View File

@ -60,6 +60,7 @@
<!-- tools -->
<key command="configure_tools" shortcut="C" />
<key command="film_editor" shortcut="Tab" />
<key command="palette_editor" shortcut="F4" />
<key command="convolution_matrix" shortcut="F9" />
<key command="color_curve" shortcut="Ctrl+M" />
<key command="color_curve" shortcut="F10" />

View File

@ -1,5 +1,5 @@
# Allegro Sprite Editor tips
# Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2008 David A. Capello
# Copyright (C) 2001-2008 David A. Capello
**********************************************************************
\palette ase.pcx

View File

@ -14,13 +14,13 @@ endif
######################################################################
# Flags for GCC in GNU/Linux system
#ifdef DEBUGMODE
ifdef DEBUGMODE
CFLAGS = `allegro-config --cflags debug`
LFLAGS = `allegro-config --libs debug`
#else
else
CFLAGS = `allegro-config --cflags`
LFLAGS = `allegro-config --libs`
#endif
endif
######################################################################
# GCC stuff
@ -51,12 +51,12 @@ distclean: clean
-rm -f $(ASE)
install:
cp ase $(DEFAULT_PREFIX)/bin
cp aseprite $(DEFAULT_PREFIX)/bin
cp -r data $(DEFAULT_PREFIX)/share/ase
cp AUTHORS.txt $(DEFAULT_PREFIX)/share/ase
uninstall:
-rm -vf $(DEFAULT_PREFIX)/bin/ase
-rm -vf $(DEFAULT_PREFIX)/bin/aseprite
-rm -rvf $(DEFAULT_PREFIX)/share/ase
-include makefile.dep

View File

@ -64,7 +64,7 @@ static void cmd_advanced_mode_execute(const char *argument)
if (jalert("%s<<%s||%s||%s",
_("Warning - Important"),
buf,
_("&Don't show it again"), _("&Continue")) == 1) {
_("&Don't show this again"), _("&Continue")) == 1) {
set_config_bool("AdvancedMode", "Warning", FALSE);
}
}

View File

@ -73,20 +73,20 @@ static void cmd_merge_down_layer_execute(const char *argument)
dst_cel = layer_get_cel(dst_layer, frpos);
/* get images */
if (src_cel)
if (src_cel != NULL)
src_image = stock_get_image(sprite->stock, src_cel->image);
else
src_image = NULL;
if (dst_cel)
if (dst_cel != NULL)
dst_image = stock_get_image(sprite->stock, dst_cel->image);
else
dst_image = NULL;
/* with source image? */
if (src_image) {
if (src_image != NULL) {
/* no destination image */
if (!dst_image) {
if (dst_image == NULL) {
/* copy this cel to the destination layer... */
/* creating a copy of the image */
@ -95,7 +95,7 @@ static void cmd_merge_down_layer_execute(const char *argument)
/* adding it in the stock of images */
index = stock_add_image(sprite->stock, dst_image);
if (undo_is_enabled(sprite->undo))
undo_add_image(sprite->undo, sprite->stock, dst_image);
undo_add_image(sprite->undo, sprite->stock, index);
/* creating a copy of the cell */
dst_cel = cel_new(frpos, index);
@ -124,6 +124,11 @@ static void cmd_merge_down_layer_execute(const char *argument)
src_cel->opacity,
src_layer->blend_mode);
if (undo_is_enabled(sprite->undo)) {
undo_int(sprite->undo, (GfxObj *)dst_cel, &dst_cel->x);
undo_int(sprite->undo, (GfxObj *)dst_cel, &dst_cel->y);
}
cel_set_position(dst_cel, x1, y1);
if (undo_is_enabled(sprite->undo))

View File

@ -68,7 +68,7 @@ static void cmd_new_cel_execute(const char *argument)
undo_set_label(current_sprite->undo, "New Cel");
undo_open(current_sprite->undo);
undo_add_image(current_sprite->undo,
current_sprite->stock, image);
current_sprite->stock, image_index);
}
/* create the new cel */

View File

@ -117,32 +117,48 @@ static bool new_frame_for_layer(Sprite *sprite, Layer *layer, int frame)
return TRUE;
}
/* makes a copy of the cel in 'frame-1' to a new cel in 'frame' */
static bool copy_cel_in_next_frame(Sprite *sprite, Layer *layer, int frame)
{
int image_index;
Image *image;
Cel *cel;
Image *src_image;
Image *dst_image;
Cel *src_cel;
Cel *dst_cel;
/* create a new empty cel with a new clean image */
image = image_new(sprite->imgtype, sprite->w, sprite->h);
if (!image) {
/* create a copy of the previous cel */
src_cel = layer_get_cel(layer, frame-1);
src_image = src_cel ? stock_get_image(sprite->stock,
src_cel->image):
NULL;
if (src_image == NULL || frame == 0)
dst_image = image_new(sprite->imgtype, sprite->w, sprite->h);
else
dst_image = image_new_copy(src_image);
if (!dst_image) {
console_printf(_("Not enough memory.\n"));
return FALSE;
}
/* background color */
image_clear(image, 0);
if (frame > 0)
layer_render(layer, image, 0, 0, frame-1);
/* add the image in the stock */
image_index = stock_add_image(sprite->stock, image);
undo_add_image(sprite->undo, sprite->stock, image);
image_index = stock_add_image(sprite->stock, dst_image);
if (undo_is_enabled(sprite->undo))
undo_add_image(sprite->undo, sprite->stock, image_index);
/* create the new cel */
dst_cel = cel_new(frame, image_index);
if (src_cel != NULL) {
cel_set_position(dst_cel, src_cel->x, src_cel->y);
cel_set_opacity(dst_cel, src_cel->opacity);
}
/* add the cel in the layer */
cel = cel_new(frame, image_index);
undo_add_cel(sprite->undo, layer, cel);
layer_add_cel(layer, cel);
if (undo_is_enabled(sprite->undo))
undo_add_cel(sprite->undo, layer, dst_cel);
layer_add_cel(layer, dst_cel);
return TRUE;
}

View File

@ -92,7 +92,7 @@ void dialogs_tips(bool forced)
button_next = jbutton_new(_("&Next"));
view = jview_new();
tips = tips_new();
check = jcheck_new(_("Show me it in the start up"));
check = jcheck_new(_("Show this at startup"));
jwidget_set_min_size(button_close, 50, 0);
jwidget_set_min_size(button_prev, 50, 0);

View File

@ -311,11 +311,11 @@ void effect_flush(Effect *effect)
void effect_apply_to_target(Effect *effect)
{
ImageRef *p, *next, *images;
ImageRef *p, *images;
bool cancelled = FALSE;
int nimages;
images = sprite_get_images(effect->sprite, effect->target, TRUE);
images = images_ref_get_from_sprite(effect->sprite, effect->target, TRUE);
if (images == NULL)
return;
@ -351,10 +351,7 @@ void effect_apply_to_target(Effect *effect)
}
/* free all ImageRefs */
for (p=images; p; p=next) {
next = p->next;
jfree(p);
}
images_ref_free(images);
}
static EffectData *get_effect_data(const char *name)

View File

@ -49,7 +49,7 @@ Sprite *current_sprite = NULL;
static JList sprites_list;
static Sprite *clipboard_sprite;
static ImageRef *layer_get_images(Sprite *sprite, Layer *layer, int target, bool write);
static ImageRef *images_ref_get_from_layer(Sprite *sprite, Layer *layer, int target, bool write);
static void layer_get_pos(Sprite *sprite, Layer *layer, int target, bool write, int **x, int **y, int *count);
int init_module_sprites(void)
@ -218,15 +218,25 @@ Sprite *lock_current_sprite(void)
return NULL;
}
ImageRef *sprite_get_images(struct Sprite *sprite, int target, bool write)
ImageRef *images_ref_get_from_sprite(Sprite *sprite, int target, bool write)
{
Layer *layer = target & TARGET_ALL_LAYERS ? sprite->set:
sprite->layer;
return layer_get_images(sprite, layer, target, write);
return images_ref_get_from_layer(sprite, layer, target, write);
}
static ImageRef *layer_get_images(Sprite *sprite, Layer *layer, int target, bool write)
void images_ref_free(ImageRef *image_ref)
{
ImageRef *p, *next;
for (p=image_ref; p; p=next) {
next = p->next;
jfree(p);
}
}
static ImageRef *images_ref_get_from_layer(Sprite *sprite, Layer *layer, int target, bool write)
{
#define ADD_IMAGES(images) \
{ \
@ -288,7 +298,7 @@ static ImageRef *layer_get_images(Sprite *sprite, Layer *layer, int target, bool
JLink link;
JI_LIST_FOR_EACH(layer->layers, link) {
sub_images = layer_get_images(sprite, link->data, target, write);
sub_images = images_ref_get_from_layer(sprite, link->data, target, write);
if (sub_images != NULL)
ADD_IMAGES(sub_images);

View File

@ -58,7 +58,8 @@ bool is_current_sprite_writable(void);
struct Sprite *lock_current_sprite(void);
ImageRef *sprite_get_images(struct Sprite *sprite, int target, bool write);
ImageRef *images_ref_get_from_sprite(struct Sprite *sprite, int target, bool write);
void images_ref_free(ImageRef *image_ref);
#endif /* MODULES_SPRITES_H */

View File

@ -117,10 +117,9 @@ Layer *layer_new_copy(Sprite *dst_sprite, const Layer *src_layer)
image_copy = image_new_copy(image);
if (undo_is_enabled(dst_sprite->undo))
undo_add_image(dst_sprite->undo, dst_sprite->stock, image_copy);
cel_copy->image = stock_add_image(dst_sprite->stock, image_copy);
if (undo_is_enabled(dst_sprite->undo))
undo_add_image(dst_sprite->undo, dst_sprite->stock, cel_copy->image);
layer_add_cel(layer_copy, cel_copy);
}

View File

@ -135,13 +135,13 @@ static void chunk_flip_invert(UndoStream *stream, UndoChunkFlip *chunk, int stat
static void chunk_dirty_new(UndoStream *stream, Dirty *dirty);
static void chunk_dirty_invert(UndoStream *stream, UndoChunkDirty *chunk, int state);
static void chunk_add_image_new(UndoStream *stream, Stock *stock, Image *image);
static void chunk_add_image_new(UndoStream *stream, Stock *stock, int image_index);
static void chunk_add_image_invert(UndoStream *stream, UndoChunkAddImage *chunk, int state);
static void chunk_remove_image_new(UndoStream *stream, Stock *stock, Image *image);
static void chunk_remove_image_new(UndoStream *stream, Stock *stock, int image_index);
static void chunk_remove_image_invert(UndoStream *stream, UndoChunkRemoveImage *chunk, int state);
static void chunk_replace_image_new(UndoStream *stream, Stock *stock, int index);
static void chunk_replace_image_new(UndoStream *stream, Stock *stock, int image_index);
static void chunk_replace_image_invert(UndoStream *stream, UndoChunkReplaceImage *chunk, int state);
static void chunk_add_cel_new(UndoStream *stream, Layer *layer, Cel *cel);
@ -762,7 +762,7 @@ static void chunk_dirty_invert(UndoStream *stream, UndoChunkDirty *chunk, int st
"add_image"
DWORD stock ID
DWORD index
DWORD index of the image in the stock
***********************************************************************/
@ -770,45 +770,36 @@ struct UndoChunkAddImage
{
UndoChunk head;
ase_uint32 stock_id;
ase_uint32 index;
ase_uint32 image_index;
};
/* TODO fix this so it doesn't need to be called as:
image_index = stock_add_image(sprite->stock, image);
undo_add_image(sprite->undo, sprite->stock, image);
*/
void undo_add_image(Undo *undo, Stock *stock, Image *image)
void undo_add_image(Undo *undo, Stock *stock, int image_index)
{
chunk_add_image_new(undo->undo_stream, stock, image);
chunk_add_image_new(undo->undo_stream, stock, image_index);
update_undo(undo);
}
static void chunk_add_image_new(UndoStream *stream, Stock *stock, Image *image)
static void chunk_add_image_new(UndoStream *stream, Stock *stock, int image_index)
{
UndoChunkAddImage *chunk = (UndoChunkAddImage *)
undo_chunk_new(stream,
UNDO_TYPE_ADD_IMAGE,
sizeof(UndoChunkAddImage));
int index;
for (index=0; index<stock->nimage; index++)
if (stock->image[index] == image)
break;
chunk->stock_id = stock->gfxobj.id;
chunk->index = index;
chunk->image_index = image_index;
}
static void chunk_add_image_invert(UndoStream *stream, UndoChunkAddImage *chunk, int state)
{
unsigned int stock_id = chunk->stock_id;
unsigned int index = chunk->index;
unsigned int image_index = chunk->image_index;
Stock *stock = (Stock *)gfxobj_find(stock_id);
if (stock) {
Image *image = stock_get_image(stock, index);
if (image) {
chunk_remove_image_new(stream, stock, image);
Image *image = stock_get_image(stock, image_index);
if (image != NULL) {
chunk_remove_image_new(stream, stock, image_index);
stock_remove_image(stock, image);
image_free(image);
}
@ -820,7 +811,7 @@ static void chunk_add_image_invert(UndoStream *stream, UndoChunkAddImage *chunk,
"remove_image"
DWORD stock ID
DWORD index
DWORD index of the image in the stock
IMAGE_DATA see read/write_raw_image
***********************************************************************/
@ -829,30 +820,26 @@ struct UndoChunkRemoveImage
{
UndoChunk head;
ase_uint32 stock_id;
ase_uint32 index;
ase_uint32 image_index;
ase_uint8 data[0];
};
void undo_remove_image(Undo *undo, Stock *stock, Image *image)
void undo_remove_image(Undo *undo, Stock *stock, int image_index)
{
chunk_remove_image_new(undo->undo_stream, stock, image);
chunk_remove_image_new(undo->undo_stream, stock, image_index);
update_undo(undo);
}
static void chunk_remove_image_new(UndoStream *stream, Stock *stock, Image *image)
static void chunk_remove_image_new(UndoStream *stream, Stock *stock, int image_index)
{
Image *image = stock->image[image_index];
UndoChunkRemoveImage *chunk = (UndoChunkRemoveImage *)
undo_chunk_new(stream,
UNDO_TYPE_REMOVE_IMAGE,
sizeof(UndoChunkRemoveImage)+get_raw_image_size(image));
int index;
for (index=0; index<stock->nimage; index++)
if (stock->image[index] == image)
break;
chunk->stock_id = stock->gfxobj.id;
chunk->index = index;
chunk->image_index = image_index;
write_raw_image(chunk->data, image);
}
@ -860,7 +847,7 @@ static void chunk_remove_image_new(UndoStream *stream, Stock *stock, Image *imag
static void chunk_remove_image_invert(UndoStream *stream, UndoChunkRemoveImage *chunk, int state)
{
unsigned int stock_id = chunk->stock_id;
unsigned int index = chunk->index;
unsigned int image_index = chunk->image_index;
Stock *stock = (Stock *)gfxobj_find(stock_id);
if (stock) {
@ -868,8 +855,8 @@ static void chunk_remove_image_invert(UndoStream *stream, UndoChunkRemoveImage *
/* assert(image != NULL); */
stock_replace_image(stock, index, image);
chunk_add_image_new(stream, stock, image);
stock_replace_image(stock, image_index, image);
chunk_add_image_new(stream, stock, image_index);
}
}
@ -878,7 +865,7 @@ static void chunk_remove_image_invert(UndoStream *stream, UndoChunkRemoveImage *
"replace_image"
DWORD stock ID
DWORD index
DWORD index of the image in the stock
IMAGE_DATA see read/write_raw_image
***********************************************************************/
@ -887,26 +874,26 @@ struct UndoChunkReplaceImage
{
UndoChunk head;
ase_uint32 stock_id;
ase_uint32 index;
ase_uint32 image_index;
ase_uint8 data[0];
};
void undo_replace_image(Undo *undo, Stock *stock, int index)
void undo_replace_image(Undo *undo, Stock *stock, int image_index)
{
chunk_replace_image_new(undo->undo_stream, stock, index);
chunk_replace_image_new(undo->undo_stream, stock, image_index);
update_undo(undo);
}
static void chunk_replace_image_new(UndoStream *stream, Stock *stock, int index)
static void chunk_replace_image_new(UndoStream *stream, Stock *stock, int image_index)
{
Image *image = stock->image[index];
Image *image = stock->image[image_index];
UndoChunkReplaceImage *chunk = (UndoChunkReplaceImage *)
undo_chunk_new(stream,
UNDO_TYPE_REPLACE_IMAGE,
sizeof(UndoChunkReplaceImage)+get_raw_image_size(image));
chunk->stock_id = stock->gfxobj.id;
chunk->index = index;
chunk->image_index = image_index;
write_raw_image(chunk->data, image);
}
@ -914,18 +901,18 @@ static void chunk_replace_image_new(UndoStream *stream, Stock *stock, int index)
static void chunk_replace_image_invert(UndoStream *stream, UndoChunkReplaceImage *chunk, int state)
{
unsigned long stock_id = chunk->stock_id;
unsigned long index = chunk->index;
unsigned long image_index = chunk->image_index;
Stock *stock = (Stock *)gfxobj_find(stock_id);
if (stock) {
Image *image = read_raw_image(chunk->data);
chunk_replace_image_new(stream, stock, index);
chunk_replace_image_new(stream, stock, image_index);
if (stock->image[index])
image_free(stock->image[index]);
if (stock->image[image_index])
image_free(stock->image[image_index]);
stock_replace_image(stock, index, image);
stock_replace_image(stock, image_index, image);
}
}
@ -1104,7 +1091,8 @@ static void chunk_remove_layer_new(UndoStream *stream, Layer *layer)
Layer *after = layer_get_prev(layer);
chunk->set_id = set->gfxobj.id;
chunk->after_id = after ? after->gfxobj.id: 0;
chunk->after_id = after != NULL ? after->gfxobj.id: 0;
write_raw_layer(chunk->data, layer);
}
@ -1113,7 +1101,7 @@ static void chunk_remove_layer_invert(UndoStream *stream, UndoChunkRemoveLayer *
Layer *set = (Layer *)gfxobj_find(chunk->set_id);
Layer *after = (Layer *)gfxobj_find(chunk->after_id);
if (set) {
if (set != NULL) {
Layer *layer = read_raw_layer(chunk->data);
/* assert(layer != NULL); */
@ -1360,6 +1348,13 @@ static void undo_chunk_free(UndoChunk *chunk)
raw_data += 2; \
}
#define read_raw_int16(dst) \
{ \
memcpy(&word, raw_data, 2); \
dst = (int16_t)word; \
raw_data += 2; \
}
#define read_raw_uint8(dst) \
{ \
dst = *raw_data; \
@ -1386,6 +1381,13 @@ static void undo_chunk_free(UndoChunk *chunk)
raw_data += 2; \
}
#define write_raw_int16(src) \
{ \
word = (int16_t)src; \
memcpy(raw_data, &word, 2); \
raw_data += 2; \
}
#define write_raw_uint8(src) \
{ \
*raw_data = src; \
@ -1585,6 +1587,7 @@ static ase_uint8 *write_raw_image(ase_uint8 *raw_data, Image *image)
static int get_raw_image_size(Image *image)
{
assert(image != NULL);
return 4+1+2+2+IMAGE_LINE_SIZE(image, image->w) * image->h;
}
@ -1611,8 +1614,8 @@ static Cel *read_raw_cel(ase_uint8 *raw_data)
read_raw_uint32(cel_id);
read_raw_uint16(frame);
read_raw_uint16(image);
read_raw_uint16(x);
read_raw_uint16(y);
read_raw_int16(x);
read_raw_int16(y);
read_raw_uint16(opacity);
cel = cel_new(frame, image);
@ -1631,8 +1634,8 @@ static ase_uint8 *write_raw_cel(ase_uint8 *raw_data, Cel *cel)
write_raw_uint32(cel->gfxobj.id);
write_raw_uint16(cel->frame);
write_raw_uint16(cel->image);
write_raw_uint16(cel->x);
write_raw_uint16(cel->y);
write_raw_int16(cel->x);
write_raw_int16(cel->y);
write_raw_uint16(cel->opacity);
return raw_data;
@ -1684,7 +1687,7 @@ static Layer *read_raw_layer(ase_uint8 *raw_data)
/* read cels */
for (c=0; c<cels; c++) {
Cel *cel;
bool as_image;
bool has_image;
/* read the cel */
cel = read_raw_cel(raw_data);
@ -1694,8 +1697,8 @@ static Layer *read_raw_layer(ase_uint8 *raw_data)
layer_add_cel(layer, cel);
/* read the image */
read_raw_uint8(as_image);
if (as_image) {
read_raw_uint8(has_image);
if (has_image) {
Image *image = read_raw_image(raw_data);
raw_data += get_raw_image_size(image);

View File

@ -74,9 +74,9 @@ void undo_data(Undo *undo, GfxObj *gfxobj, void *data, int size);
void undo_image(Undo *undo, struct Image *image, int x, int y, int w, int h);
void undo_flip(Undo *undo, struct Image *image, int x1, int y1, int x2, int y2, int horz);
void undo_dirty(Undo *undo, struct Dirty *dirty);
void undo_add_image(Undo *undo, struct Stock *stock, struct Image *image);
void undo_remove_image(Undo *undo, struct Stock *stock, struct Image *image);
void undo_replace_image(Undo *undo, struct Stock *stock, int index);
void undo_add_image(Undo *undo, struct Stock *stock, int image_index);
void undo_remove_image(Undo *undo, struct Stock *stock, int image_index);
void undo_replace_image(Undo *undo, struct Stock *stock, int image_index);
void undo_add_cel(Undo *undo, struct Layer *layer, struct Cel *cel);
void undo_remove_cel(Undo *undo, struct Layer *layer, struct Cel *cel);
void undo_add_layer(Undo *undo, struct Layer *set, struct Layer *layer);

View File

@ -859,7 +859,7 @@ void RemoveCel(Layer *layer, Cel *cel)
image = stock_get_image(sprite->stock, cel->image);
if (undo_is_enabled(sprite->undo))
undo_remove_image(sprite->undo, sprite->stock, image);
undo_remove_image(sprite->undo, sprite->stock, cel->image);
stock_remove_image(sprite->stock, image);
image_free(image);

View File

@ -128,7 +128,7 @@ void copy_cel(void)
image_index = stock_add_image(sprite->stock, image);
if (undo_is_enabled(sprite->undo))
undo_add_image(sprite->undo, sprite->stock, image);
undo_add_image(sprite->undo, sprite->stock, image_index);
}
/* setup the cel */

View File

@ -309,30 +309,25 @@ int interactive_move_layer(int mode, bool use_undo, int (*callback)(void))
gui_feedback();
} while (editor_click(editor, &new_x, &new_y, &update, NULL));
new_x = cel->x;
new_y = cel->y;
cel_set_position(cel, begin_x, begin_y);
/* the position was changed */
if (!editor_click_cancel(editor)) {
if (use_undo && undo_is_enabled(sprite->undo)) {
new_x = cel->x;
new_y = cel->y;
undo_set_label(sprite->undo, "Cel Movement");
undo_open(sprite->undo);
cel->x = begin_x;
cel->y = begin_y;
undo_int(sprite->undo, (GfxObj *)cel, &cel->x);
undo_int(sprite->undo, (GfxObj *)cel, &cel->y);
cel->x = new_x;
cel->y = new_y;
undo_close(sprite->undo);
}
cel_set_position(cel, new_x, new_y);
ret = TRUE;
}
/* the position wasn't changed */
else {
cel->x = begin_x;
cel->y = begin_y;
ret = FALSE;
}

View File

@ -26,15 +26,12 @@
#include "raster/image.h"
#include "raster/palette.h"
#include "raster/sprite.h"
#include "raster/stock.h"
#include "util/quantize.h"
/* static int quantize_bitmaps1(struct Stock *stock, struct RGB *pal, int *bmp_i, int fill_other); */
/* static int quantize_bitmaps2(struct Stock *stock, struct Palette *pal); */
static int quantize_bitmaps(Image **image, int nimage, RGB *pal, int *bmp_i, int fill_other);
void sprite_quantize(struct Sprite *sprite)
void sprite_quantize(Sprite *sprite)
{
#if 0 /* TODO next release */
Palette *palette = palette_new(0, MAX_PALETTE_COLORS);
sprite_quantize_ex(sprite, palette);
@ -42,25 +39,39 @@ void sprite_quantize(struct Sprite *sprite)
/* just one palette */
sprite_reset_palettes(sprite);
sprite_set_palette(sprite, palette, FALSE);
#endif
palette_free(palette);
}
void sprite_quantize_ex(Sprite *sprite, Palette *palette)
{
#if 0 /* TODO */
Stock *stock;
Image *flat_image;
int c;
Image *flat_image, **image_array;
ImageRef *p, *images;
int c, nimage;
stock = sprite_get_images(sprite, TARGET_ALL_LAYERS |
TARGET_ALL_FRAMES, FALSE, NULL, NULL);
if (stock) {
images = images_ref_get_from_sprite(sprite, TARGET_ALL_LAYERS |
TARGET_ALL_FRAMES, FALSE);
if (images != NULL) {
/* add a flat image with the current sprite's frame rendered */
flat_image = image_new(sprite->imgtype, sprite->w, sprite->h);
image_clear(flat_image, 0);
sprite_render(sprite, flat_image, 0, 0);
stock_add_image(stock, flat_image);
/* count images in the 'images' list */
c = 0;
for (p=images; p; p=p->next)
c++;
c++; /* the 'flat_image' */
/* create an array of images */
nimage = c;
image_array = jmalloc(sizeof(Image**) * nimage);
c = 0;
for (p=images; p; p=p->next)
image_array[c++] = p->image;
image_array[c++] = flat_image; /* the 'flat_image' */
/* generate the optimized palette */
{
PALETTE rgbpal;
@ -69,25 +80,23 @@ void sprite_quantize_ex(Sprite *sprite, Palette *palette)
for (c=0; c<256; c++)
rgbpal[c].r = rgbpal[c].g = rgbpal[c].b = 255;
ibmp = jmalloc(sizeof (int) * stock->nimage);
for (c=0; c<stock->nimage; c++)
ibmp = jmalloc(sizeof(int) * nimage);
for (c=0; c<nimage; c++)
ibmp[c] = 128;
quantize_bitmaps1(stock, rgbpal, ibmp, TRUE);
quantize_bitmaps(image_array, nimage, rgbpal, ibmp, TRUE);
palette_from_allegro(palette, rgbpal);
jfree(ibmp);
}
stock_free(stock);
jfree(image_array);
image_free(flat_image);
images_ref_free(images);
}
#endif
}
#if 0 /* TODO next release */
/* quantize.c
* Copyright (C) 2000-2002 by Ben "entheh" Davis
*
@ -142,10 +151,10 @@ void sprite_quantize_ex(Sprite *sprite, Palette *palette)
typedef struct PALETTE_NODE
{
unsigned int rl,gl,bl,rh,gh,bh;
unsigned int n1,n2,Sr,Sg,Sb,E;
struct PALETTE_NODE *parent;
struct PALETTE_NODE *subnode[2][2][2];
unsigned int rl,gl,bl,rh,gh,bh;
unsigned int n1,n2,Sr,Sg,Sb,E;
struct PALETTE_NODE *parent;
struct PALETTE_NODE *subnode[2][2][2];
} PALETTE_NODE;
static PALETTE_NODE *rgb_node[64][64][64];
@ -155,228 +164,231 @@ static PALETTE_NODE *create_node(unsigned int rl,
unsigned int bl,
unsigned int rh,
unsigned int gh,
unsigned int bh,PALETTE_NODE *parent) {
PALETTE_NODE *node;
unsigned int rm,gm,bm;
node=jmalloc(sizeof(PALETTE_NODE));
if (!node)
return NULL;
node->rl=rl;
node->gl=gl;
node->bl=bl;
node->rh=rh;
node->gh=gh;
node->bh=bh;
node->E=node->Sb=node->Sg=node->Sr=node->n2=node->n1=0;
node->parent=parent;
if (rh-rl>TREE_DEPTH) {
rm=(rl+rh)>>1;
gm=(gl+gh)>>1;
bm=(bl+bh)>>1;
node->subnode[0][0][0]=create_node(rl,gl,bl,rm,gm,bm,node);
node->subnode[0][0][1]=create_node(rm,gl,bl,rh,gm,bm,node);
node->subnode[0][1][0]=create_node(rl,gm,bl,rm,gh,bm,node);
node->subnode[0][1][1]=create_node(rm,gm,bl,rh,gh,bm,node);
node->subnode[1][0][0]=create_node(rl,gl,bm,rm,gm,bh,node);
node->subnode[1][0][1]=create_node(rm,gl,bm,rh,gm,bh,node);
node->subnode[1][1][0]=create_node(rl,gm,bm,rm,gh,bh,node);
node->subnode[1][1][1]=create_node(rm,gm,bm,rh,gh,bh,node);
} else {
for (bm=bl;bm<bh;bm++) {
for (gm=gl;gm<gh;gm++) {
for (rm=rl;rm<rh;rm++) {
rgb_node[bm][gm][rm]=node;
unsigned int bh,PALETTE_NODE *parent)
{
PALETTE_NODE *node;
unsigned int rm,gm,bm;
node=jmalloc(sizeof(PALETTE_NODE));
if (!node)
return NULL;
node->rl=rl;
node->gl=gl;
node->bl=bl;
node->rh=rh;
node->gh=gh;
node->bh=bh;
node->E=node->Sb=node->Sg=node->Sr=node->n2=node->n1=0;
node->parent=parent;
if (rh-rl>TREE_DEPTH) {
rm=(rl+rh)>>1;
gm=(gl+gh)>>1;
bm=(bl+bh)>>1;
node->subnode[0][0][0]=create_node(rl,gl,bl,rm,gm,bm,node);
node->subnode[0][0][1]=create_node(rm,gl,bl,rh,gm,bm,node);
node->subnode[0][1][0]=create_node(rl,gm,bl,rm,gh,bm,node);
node->subnode[0][1][1]=create_node(rm,gm,bl,rh,gh,bm,node);
node->subnode[1][0][0]=create_node(rl,gl,bm,rm,gm,bh,node);
node->subnode[1][0][1]=create_node(rm,gl,bm,rh,gm,bh,node);
node->subnode[1][1][0]=create_node(rl,gm,bm,rm,gh,bh,node);
node->subnode[1][1][1]=create_node(rm,gm,bm,rh,gh,bh,node);
} else {
for (bm=bl;bm<bh;bm++) {
for (gm=gl;gm<gh;gm++) {
for (rm=rl;rm<rh;rm++) {
rgb_node[bm][gm][rm]=node;
}
}
}
}
node->subnode[1][1][1]=
node->subnode[1][1][0]=
node->subnode[1][0][1]=
node->subnode[1][0][0]=
node->subnode[0][1][1]=
node->subnode[0][1][0]=
node->subnode[0][0][1]=
node->subnode[0][0][0]=0;
}
node->subnode[1][1][1]=
node->subnode[1][1][0]=
node->subnode[1][0][1]=
node->subnode[1][0][0]=
node->subnode[0][1][1]=
node->subnode[0][1][0]=
node->subnode[0][0][1]=
node->subnode[0][0][0]=0;
}
return node;
return node;
}
static PALETTE_NODE *collapse_empty(PALETTE_NODE *node,unsigned int *n_colours) {
unsigned int b,g,r;
for (b=0;b<2;b++) {
for (g=0;g<2;g++) {
for (r=0;r<2;r++) {
if (node->subnode[b][g][r])
node->subnode[b][g][r]=collapse_empty(node->subnode[b][g][r],n_colours);
}
static PALETTE_NODE *collapse_empty(PALETTE_NODE *node,unsigned int *n_colours)
{
unsigned int b,g,r;
for (b=0;b<2;b++) {
for (g=0;g<2;g++) {
for (r=0;r<2;r++) {
if (node->subnode[b][g][r])
node->subnode[b][g][r]=collapse_empty(node->subnode[b][g][r],n_colours);
}
}
}
}
if (node->n1==0) {
jfree(node);
node=0;
} else if (node->n2) (*n_colours)++;
return node;
if (node->n1==0) {
jfree(node);
node=0;
} else if (node->n2) (*n_colours)++;
return node;
}
static PALETTE_NODE *collapse_nodes(PALETTE_NODE *node,unsigned int *n_colours,
unsigned int n_entries,unsigned int Ep) {
unsigned int b,g,r;
if (node->E<=Ep) {
for (b=0;b<2;b++) {
for (g=0;g<2;g++) {
for (r=0;r<2;r++) {
if (node->subnode[b][g][r]) {
node->subnode[b][g][r]=collapse_nodes(node->subnode[b][g][r],
n_colours,n_entries,0);
if (*n_colours<=n_entries) return node;
}
}
}
}
if (node->parent->n2) (*n_colours)--;
node->parent->n2+=node->n2;
node->parent->Sr+=node->Sr;
node->parent->Sg+=node->Sg;
node->parent->Sb+=node->Sb;
jfree(node);
node=0;
} else {
for (b=0;b<2;b++) {
for (g=0;g<2;g++) {
for (r=0;r<2;r++) {
if (node->subnode[b][g][r]) {
node->subnode[b][g][r]=collapse_nodes(node->subnode[b][g][r],
n_colours,n_entries,Ep);
if (*n_colours<=n_entries) return node;
}
}
}
}
}
return node;
}
static unsigned int distance_squared(int r,int g,int b) {
return r*r+g*g+b*b;
}
static void minimum_Ep(PALETTE_NODE *node,unsigned int *Ep) {
unsigned int r,g,b;
if (node->E<*Ep) *Ep=node->E;
for (b=0;b<2;b++) {
for (g=0;g<2;g++) {
for (r=0;r<2;r++) {
if (node->subnode[b][g][r]) minimum_Ep(node->subnode[b][g][r],Ep);
}
}
}
}
static void fill_palette(PALETTE_NODE *node,unsigned int *c,RGB *pal,int depth) {
unsigned int r,g,b;
if (node->n2) {
for (;pal[*c].r!=255;(*c)++);
pal[*c].r=node->Sr/node->n2;
pal[*c].g=node->Sg/node->n2;
pal[*c].b=node->Sb/node->n2;
(*c)++;
}
for (b=0;b<2;b++) {
for (g=0;g<2;g++) {
for (r=0;r<2;r++) {
if (node->subnode[b][g][r])
fill_palette(node->subnode[b][g][r],c,pal,depth+1);
}
}
}
}
static void destroy_tree(PALETTE_NODE *tree) {
unsigned int r,g,b;
for (b=0;b<2;b++) {
for (g=0;g<2;g++) {
for (r=0;r<2;r++) {
if (tree->subnode[b][g][r]) destroy_tree(tree->subnode[b][g][r]);
}
}
}
jfree(tree);
}
static int quantize_bitmaps1(Stock *stock, RGB *pal, int *bmp_i, int fill_other)
unsigned int n_entries,unsigned int Ep)
{
int c_bmp,x,y,c,r,g,b,n_colours=0,n_entries=0,Ep;
PALETTE_NODE *tree,*node;
/* only support RGB bitmaps */
if ((stock->nimage < 1) || (stock->imgtype != IMAGE_RGB))
return 0;
/*Create the tree structure*/
tree=create_node(0,0,0,64,64,64,0);
/*Scan the bitmaps*/
/* add_progress(stock->nimage+1); */
for (c_bmp=0;c_bmp<stock->nimage;c_bmp++) {
if (stock->image[c_bmp]) {
/* add_progress(stock->image[c_bmp]->h); */
for (y=0;y<stock->image[c_bmp]->h;y++) {
for (x=0;x<stock->image[c_bmp]->w;x++) {
c=stock->image[c_bmp]->method->getpixel(stock->image[c_bmp],x,y);
r=_rgba_getr(c)>>2;
g=_rgba_getg(c)>>2;
b=_rgba_getb(c)>>2;
node=rgb_node[b][g][r];
node->n2+=bmp_i[c_bmp];
node->Sr+=r*bmp_i[c_bmp];
node->Sg+=g*bmp_i[c_bmp];
node->Sb+=b*bmp_i[c_bmp];
do {
node->n1+=bmp_i[c_bmp];
node->E+=distance_squared((r<<1)-node->rl-node->rh,
(g<<1)-node->gl-node->gh,
(b<<1)-node->bl-node->bh)*bmp_i[c_bmp];
node=node->parent;
} while (node);
unsigned int b,g,r;
if (node->E<=Ep) {
for (b=0;b<2;b++) {
for (g=0;g<2;g++) {
for (r=0;r<2;r++) {
if (node->subnode[b][g][r]) {
node->subnode[b][g][r]=collapse_nodes(node->subnode[b][g][r],
n_colours,n_entries,0);
if (*n_colours<=n_entries) return node;
}
}
}
}
if (node->parent->n2) (*n_colours)--;
node->parent->n2+=node->n2;
node->parent->Sr+=node->Sr;
node->parent->Sg+=node->Sg;
node->parent->Sb+=node->Sb;
jfree(node);
node=0;
} else {
for (b=0;b<2;b++) {
for (g=0;g<2;g++) {
for (r=0;r<2;r++) {
if (node->subnode[b][g][r]) {
node->subnode[b][g][r]=collapse_nodes(node->subnode[b][g][r],
n_colours,n_entries,Ep);
if (*n_colours<=n_entries) return node;
}
}
}
}
/* do_progress(y); */
}
/* del_progress(); */
}
/* do_progress(c_bmp); */
}
/*Collapse empty nodes in the tree, and count leaves*/
tree=collapse_empty(tree,&n_colours);
/*Count free palette entries*/
for (c=0;c<256;c++) {
if (pal[c].r==255) n_entries++;
}
/*Collapse nodes until there are few enough to fit in the palette*/
if (n_colours > n_entries) {
/* int n_colours1 = n_colours; */
/* add_progress(n_colours1 - n_entries); */
while (n_colours>n_entries) {
Ep=0xFFFFFFFFul;
minimum_Ep(tree,&Ep);
tree=collapse_nodes(tree,&n_colours,n_entries,Ep);
/* if (n_colours > n_entries) */
/* do_progress(n_colours1 - n_colours); */
}
/* del_progress(); */
}
/* del_progress(); */
/*Fill palette*/
c=0;
fill_palette(tree,&c,pal,1);
if (fill_other) {
for (;c<256;c++) {
if (pal[c].r==255)
pal[c].b=pal[c].g=pal[c].r=0;
}
}
/*Free memory used by tree*/
destroy_tree(tree);
return n_colours;
return node;
}
#endif
static unsigned int distance_squared(int r,int g,int b)
{
return r*r+g*g+b*b;
}
static void minimum_Ep(PALETTE_NODE *node,unsigned int *Ep)
{
unsigned int r,g,b;
if (node->E<*Ep) *Ep=node->E;
for (b=0;b<2;b++) {
for (g=0;g<2;g++) {
for (r=0;r<2;r++) {
if (node->subnode[b][g][r]) minimum_Ep(node->subnode[b][g][r],Ep);
}
}
}
}
static void fill_palette(PALETTE_NODE *node,unsigned int *c,RGB *pal,int depth)
{
unsigned int r,g,b;
if (node->n2) {
for (;pal[*c].r!=255;(*c)++);
pal[*c].r=node->Sr/node->n2;
pal[*c].g=node->Sg/node->n2;
pal[*c].b=node->Sb/node->n2;
(*c)++;
}
for (b=0;b<2;b++) {
for (g=0;g<2;g++) {
for (r=0;r<2;r++) {
if (node->subnode[b][g][r])
fill_palette(node->subnode[b][g][r],c,pal,depth+1);
}
}
}
}
static void destroy_tree(PALETTE_NODE *tree)
{
unsigned int r,g,b;
for (b=0;b<2;b++) {
for (g=0;g<2;g++) {
for (r=0;r<2;r++) {
if (tree->subnode[b][g][r]) destroy_tree(tree->subnode[b][g][r]);
}
}
}
jfree(tree);
}
static int quantize_bitmaps(Image **image, int nimage, RGB *pal, int *bmp_i, int fill_other)
{
int c_bmp,x,y,c,r,g,b,n_colours=0,n_entries=0,Ep;
PALETTE_NODE *tree,*node;
/* only support RGB bitmaps */
if ((nimage < 1) || (image[0]->imgtype != IMAGE_RGB))
return 0;
/*Create the tree structure*/
tree=create_node(0,0,0,64,64,64,0);
/*Scan the bitmaps*/
/* add_progress(nimage+1); */
for (c_bmp=0;c_bmp<nimage;c_bmp++) {
/* add_progress(image[c_bmp]->h); */
for (y=0;y<image[c_bmp]->h;y++) {
for (x=0;x<image[c_bmp]->w;x++) {
c=image[c_bmp]->method->getpixel(image[c_bmp],x,y);
r=_rgba_getr(c)>>2;
g=_rgba_getg(c)>>2;
b=_rgba_getb(c)>>2;
node=rgb_node[b][g][r];
node->n2+=bmp_i[c_bmp];
node->Sr+=r*bmp_i[c_bmp];
node->Sg+=g*bmp_i[c_bmp];
node->Sb+=b*bmp_i[c_bmp];
do {
node->n1+=bmp_i[c_bmp];
node->E+=distance_squared((r<<1)-node->rl-node->rh,
(g<<1)-node->gl-node->gh,
(b<<1)-node->bl-node->bh)*bmp_i[c_bmp];
node=node->parent;
} while (node);
}
/* do_progress(y); */
}
/* del_progress(); */
/* do_progress(c_bmp); */
}
/*Collapse empty nodes in the tree, and count leaves*/
tree=collapse_empty(tree,&n_colours);
/*Count free palette entries*/
for (c=0;c<256;c++) {
if (pal[c].r==255) n_entries++;
}
/*Collapse nodes until there are few enough to fit in the palette*/
if (n_colours > n_entries) {
/* int n_colours1 = n_colours; */
/* add_progress(n_colours1 - n_entries); */
while (n_colours>n_entries) {
Ep=0xFFFFFFFFul;
minimum_Ep(tree,&Ep);
tree=collapse_nodes(tree,&n_colours,n_entries,Ep);
/* if (n_colours > n_entries) */
/* do_progress(n_colours1 - n_colours); */
}
/* del_progress(); */
}
/* del_progress(); */
/* fill palette */
c=0;
fill_palette(tree,&c,pal,1);
if (fill_other) {
for (;c<256;c++) {
if (pal[c].r==255)
pal[c].b=pal[c].g=pal[c].r=0;
}
}
/* free memory used by tree */
destroy_tree(tree);
return n_colours;
}