diff --git a/ChangeLog b/ChangeLog index 4d6d9ba32..e4c3d0f96 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2008-10-09 David A. Capello + + * src/raster/mask.cpp (shrink_mask): Fixed a bug where image_crop + where called with w<=0 and h<=0. + + * src/commands/cmd_clear.cpp (cmd_clear_execute): Changed to use + Undoable. + 2008-10-01 David A. Capello * src/raster/undo.cpp: Renamed undo_undo and undo_redo to diff --git a/src/commands/cmd_clear.cpp b/src/commands/cmd_clear.cpp index d8e9798f9..da19f4378 100644 --- a/src/commands/cmd_clear.cpp +++ b/src/commands/cmd_clear.cpp @@ -25,7 +25,7 @@ #include "raster/layer.h" #include "raster/sprite.h" #include "raster/undo.h" -#include "util/misc.h" +#include "raster/undoable.h" #include "widgets/colbar.h" static bool cmd_clear_enabled(const char *argument) @@ -40,15 +40,12 @@ static bool cmd_clear_enabled(const char *argument) static void cmd_clear_execute(const char *argument) { - Sprite *sprite = current_sprite; /* get current sprite */ - - if (undo_is_enabled(sprite->undo)) - undo_set_label(sprite->undo, "Clear"); - - /* clear the mask */ - ClearMask(); - - /* refresh the sprite */ + Sprite* sprite = current_sprite; + { + Undoable undoable(sprite, "Clear"); + undoable.clear_mask(app_get_color_to_clear_layer(sprite->layer)); + undoable.commit(); + } update_screen_for_sprite(sprite); } diff --git a/src/commands/cmd_remove_layer.cpp b/src/commands/cmd_remove_layer.cpp index d5377ae56..9eb14db23 100644 --- a/src/commands/cmd_remove_layer.cpp +++ b/src/commands/cmd_remove_layer.cpp @@ -23,7 +23,7 @@ #include "modules/sprites.h" #include "raster/sprite.h" #include "raster/undo.h" -#include "util/functions.h" +#include "raster/undoable.h" static bool cmd_remove_layer_enabled(const char *argument) { @@ -34,12 +34,12 @@ static bool cmd_remove_layer_enabled(const char *argument) static void cmd_remove_layer_execute(const char *argument) { - Sprite *sprite = current_sprite; - - if (undo_is_enabled(sprite->undo)) - undo_set_label(sprite->undo, "Remove Layer"); - - RemoveLayer(sprite); + Sprite* sprite = current_sprite; + { + Undoable undoable(sprite, "Remove Layer"); + undoable.remove_layer(sprite->layer); + undoable.commit(); + } update_screen_for_sprite(sprite); } diff --git a/src/raster/mask.cpp b/src/raster/mask.cpp index 2db3c9ccb..b4b77cf0c 100644 --- a/src/raster/mask.cpp +++ b/src/raster/mask.cpp @@ -459,7 +459,7 @@ static void shrink_mask(Mask* mask) SHRINK_SIDE(mask->h-1, >, 0, --, 0, <, mask->w, ++, v, u, y2--); - if ((x1 == x2) && (y1 == y2)) { + if ((x1 > x2) || (y1 > y2)) { mask_none(mask); } else if ((x1 != mask->x) || (x2 != mask->x+mask->w-1) || diff --git a/src/raster/undoable.cpp b/src/raster/undoable.cpp index 8eee4d05a..38d3036aa 100644 --- a/src/raster/undoable.cpp +++ b/src/raster/undoable.cpp @@ -26,6 +26,7 @@ #include "raster/cel.h" #include "raster/image.h" #include "raster/layer.h" +#include "raster/mask.h" #include "raster/sprite.h" #include "raster/stock.h" #include "raster/undo.h" @@ -103,10 +104,14 @@ void Undoable::set_current_frame(int frame) sprite_set_frame(sprite, frame); } +/** + * Sets the current selected layer in the sprite. + * + * @param layer + * The layer to select. Can be NULL. + */ void Undoable::set_current_layer(Layer* layer) { - assert(layer); - if (is_enabled()) undo_set_layer(sprite->undo, sprite); @@ -171,6 +176,43 @@ Layer* Undoable::new_layer() return layer; } +/** + * Removes and destroys the specified layer. + */ +void Undoable::remove_layer(Layer* layer) +{ + assert(layer); + + Layer* parent = layer->parent_layer; + + // if the layer to be removed is the selected layer + if (layer == sprite->layer) { + Layer* layer_select = NULL; + + // select: previous layer, or next layer, or parent(if it is not the + // main layer of sprite set) + if (layer_get_prev(layer)) + layer_select = layer_get_prev(layer); + else if (layer_get_next(layer)) + layer_select = layer_get_next(layer); + else if (parent != sprite->set) + layer_select = parent; + + // select other layer + set_current_layer(layer_select); + } + + // remove the layer + if (is_enabled()) + undo_remove_layer(sprite->undo, layer); + + layer_remove_layer(parent, layer); + + // destroy the layer + layer_free_images(layer); + layer_free(layer); +} + void Undoable::move_layer_after(Layer* layer, Layer* after_this) { if (is_enabled()) @@ -448,3 +490,80 @@ void Undoable::move_frame_before_layer(Layer* layer, int frame, int before_frame } } + +Cel* Undoable::get_current_cel() +{ + if (sprite->layer && layer_is_image(sprite->layer)) + return layer_get_cel(sprite->layer, sprite->frame); + else + return NULL; +} + +Image* Undoable::get_cel_image(Cel* cel) +{ + if (cel && cel->image >= 0 && cel->image < sprite->stock->nimage) + return sprite->stock->image[cel->image]; + else + return NULL; +} + +// clears the mask region in the current sprite with the BG color +void Undoable::clear_mask(int bgcolor) +{ + Cel* cel = get_current_cel(); + if (!cel) + return; + + Image* image = get_cel_image(cel); + if (!image) + return; + + // if the mask is empty then we have to clear the entire image + // in the cel + if (mask_is_empty(sprite->mask)) { + // if the layer is the background then we clear the image + if (layer_is_background(sprite->layer)) { + if (is_enabled()) + undo_image(sprite->undo, image, 0, 0, image->w, image->h); + + // clear all + image_clear(image, bgcolor); + } + // if the layer is transparent we can remove the cel (and it's + // associated image) + else { + remove_cel(sprite->layer, cel); + } + } + else { + int u, v, putx, puty; + int x1 = MAX(0, sprite->mask->x); + int y1 = MAX(0, sprite->mask->y); + int x2 = MIN(image->w-1, sprite->mask->x+sprite->mask->w-1); + int y2 = MIN(image->h-1, sprite->mask->y+sprite->mask->h-1); + + // do nothing + if (x1 > x2 || y1 > y2) + return; + + if (is_enabled()) + undo_image(sprite->undo, image, x1, y1, x2-x1+1, y2-y1+1); + + // clear the masked zones + for (v=0; vmask->h; v++) { + div_t d = div(0, 8); + ase_uint8* address = ((ase_uint8 **)sprite->mask->bitmap->line)[v]+d.quot; + + for (u=0; umask->w; u++) { + if ((*address & (1<mask->x - cel->x; + puty = v + sprite->mask->y - cel->y; + image_putpixel(image, putx, puty, bgcolor); + } + + _image_bitmap_next_bit(d, address); + } + } + } +} + diff --git a/src/raster/undoable.h b/src/raster/undoable.h index 4568825f2..36345b8a5 100644 --- a/src/raster/undoable.h +++ b/src/raster/undoable.h @@ -54,6 +54,7 @@ public: // for layers Layer* new_layer(); + void remove_layer(Layer* layer); void move_layer_after(Layer *layer, Layer *after_this); // for frames @@ -70,6 +71,11 @@ public: void add_cel(Layer* layer, Cel* cel); void remove_cel(Layer* layer, Cel* cel); void set_cel_frame_position(Cel* cel, int frame); + Cel* get_current_cel(); + + // for image + Image* get_cel_image(Cel* cel); + void clear_mask(int bgcolor); }; diff --git a/src/util/functions.cpp b/src/util/functions.cpp index 6866d4f48..fe40f6185 100644 --- a/src/util/functions.cpp +++ b/src/util/functions.cpp @@ -255,52 +255,6 @@ Layer *NewLayerSet(Sprite *sprite) return layer; } -/** - * Removes the current selected layer - */ -void RemoveLayer(Sprite *sprite) -{ - if (sprite != NULL && - sprite->layer != NULL) { - Layer *layer = sprite->layer; - Layer *parent = layer->parent_layer; - Layer *layer_select; - - /* select: previous layer, or next layer, or parent(if it is not - the main layer of sprite set) */ - if (layer_get_prev(layer)) - layer_select = layer_get_prev(layer); - else if (layer_get_next(layer)) - layer_select = layer_get_next(layer); - else if (parent != sprite->set) - layer_select = parent; - else - layer_select = NULL; - - /* undo stuff */ - if (undo_is_enabled(sprite->undo)) - undo_open(sprite->undo); - - /* select other layer */ - if (undo_is_enabled(sprite->undo)) - undo_set_layer(sprite->undo, sprite); - sprite_set_layer(sprite, layer_select); - - /* remove the layer */ - if (undo_is_enabled(sprite->undo)) - undo_remove_layer(sprite->undo, layer); - layer_remove_layer(parent, layer); - - /* destroy the layer */ - layer_free_images(layer); - layer_free(layer); - - /* close undo */ - if (undo_is_enabled(sprite->undo)) - undo_close(sprite->undo); - } -} - char *GetUniqueLayerName(Sprite *sprite) { if (sprite != NULL) { diff --git a/src/util/functions.h b/src/util/functions.h index 10aa06e03..e09897b6b 100644 --- a/src/util/functions.h +++ b/src/util/functions.h @@ -16,8 +16,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef SCRIPT_FUNCTIONS_H -#define SCRIPT_FUNCTIONS_H +#ifndef UTIL_FUNCTIONS_H +#define UTIL_FUNCTIONS_H class Sprite; class Layer; @@ -40,7 +40,6 @@ void CropSprite(Sprite* sprite); /*===================================================================*/ Layer* NewLayerSet(Sprite* sprite); -void RemoveLayer(Sprite* sprite); char *GetUniqueLayerName(Sprite* sprite); @@ -59,4 +58,4 @@ void RemoveCel(Layer* layer, Cel* cel); void CropCel(); -#endif /* SCRIPT_FUNCTIONS_H */ +#endif /* UTIL_FUNCTIONS_H */ diff --git a/src/util/misc.cpp b/src/util/misc.cpp index 9bbff3043..cc7842a87 100644 --- a/src/util/misc.cpp +++ b/src/util/misc.cpp @@ -58,9 +58,9 @@ Image *GetImage(Sprite *sprite) return image; } -Image *GetImage2(Sprite *sprite, int *x, int *y, int *opacity) +Image* GetImage2(Sprite* sprite, int* x, int* y, int* opacity) { - Image *image = NULL; + Image* image = NULL; if (sprite != NULL && sprite->layer != NULL &&