Added Undoable::crop_sprite/layer/cel.

Added Undoable::replace_stock_image, autocrop.
Added image_shrink_rect function.
Removed autocrop_sprite, CropSprite, CropLayer, and CropCel functions.
This commit is contained in:
David Capello 2008-10-14 03:11:59 +00:00
parent 7a68a1d32b
commit e9c3d46693
21 changed files with 339 additions and 271 deletions

View File

@ -1,11 +1,23 @@
2008-10-13 David A. Capello <davidcapello@gmail.com>
* src/raster/gfxobj.cpp (_gfxobj_set_id): Fixed (the object is
removed from the map before its ID is changed).
* src/raster/stock.cpp (Stock::Stock): Fixed.
* src/raster/undoable.cpp (Undoable::crop_sprite)
(Undoable::crop_layer, Undoable::autocrop_sprite)
(Undoable::replace_stock_image): Added.
* src/raster/image.cpp (image_shrink_rect): Added.
* src/raster/gfxobj.cpp (objects_map): Replaced JList 'objects'
by a 'objects_map' (a std::map).
* src/raster/sprite.cpp (~Sprite),
src/modules/palettes.cpp (exit_module_palette): Fixed a serious
bug where palettes were not freed right (jfree instead of
* src/modules/palettes.cpp (exit_module_palette):
* src/commands/cmd_palette_editor.cpp (load_command): Fixed a
serious bug where palettes were not freed right (jfree instead of
palette_free). It leaves dead-pointers in the collection of
graphics objects in 'gfxobj.cpp'.

View File

@ -11,7 +11,8 @@ NEWS
+ Added support to lock lines in special angles with the Shift key,
useful to draw in isometric views (feature request #1961397).
+ Fixed bugs #1958760 and #1958932.
+ Fixed other bugs (Flatten Layers, File Selector, etc.).
+ Fixed other serious bugs (Dead-pointers to palettes, Flatten
Layers, File Selector, etc.).
0.6b2
-----

View File

@ -19,13 +19,15 @@
#include "config.h"
#include "commands/commands.h"
#include "core/app.h"
#include "modules/gui.h"
#include "modules/sprites.h"
#include "raster/image.h"
#include "raster/layer.h"
#include "raster/mask.h"
#include "raster/sprite.h"
#include "raster/undo.h"
#include "raster/undoable.h"
#include "widgets/colbar.h"
#include "util/autocrop.h"
#include "util/functions.h"
#include "util/misc.h"
@ -45,11 +47,16 @@ static bool cmd_crop_sprite_enabled(const char *argument)
static void cmd_crop_sprite_execute(const char *argument)
{
Sprite *sprite = current_sprite;
if (undo_is_enabled(sprite->undo))
undo_set_label(sprite->undo, "Sprite Crop");
CropSprite(sprite);
{
Undoable undoable(sprite, "Sprite Crop");
undoable.crop_sprite(current_sprite->mask->x,
current_sprite->mask->y,
current_sprite->mask->w,
current_sprite->mask->h,
colorbar_get_bg_color(app_get_colorbar()));
undoable.commit();
}
sprite_generate_mask_boundaries(sprite);
update_screen_for_sprite(sprite);
}
@ -65,11 +72,12 @@ static bool cmd_autocrop_sprite_enabled(const char *argument)
static void cmd_autocrop_sprite_execute(const char *argument)
{
Sprite *sprite = current_sprite;
if (undo_is_enabled(sprite->undo))
undo_set_label(sprite->undo, "Sprite Autocrop");
autocrop_sprite(sprite);
{
Undoable undoable(sprite, "Sprite Autocrop");
undoable.autocrop_sprite(colorbar_get_bg_color(app_get_colorbar()));
undoable.commit();
}
sprite_generate_mask_boundaries(sprite);
update_screen_for_sprite(sprite);
}

View File

@ -38,7 +38,6 @@ static void cmd_duplicate_sprite_execute(const char *argument)
{
JWidget window, src_name, dst_name, flatten;
Sprite *sprite = current_sprite;
Sprite *sprite_copy;
char buf[1024];
/* load the window widget */
@ -64,7 +63,9 @@ static void cmd_duplicate_sprite_execute(const char *argument)
if (jwindow_get_killer(window) == jwidget_find_name(window, "ok")) {
set_config_bool("DuplicateSprite", "Flatten",
jwidget_is_selected(flatten));
// make a copy of the current sprite
Sprite *sprite_copy;
if (jwidget_is_selected(flatten))
sprite_copy = sprite_new_flatten_copy(sprite);
else

View File

@ -292,7 +292,7 @@ static void load_command(JWidget widget)
}
else {
set_new_palette(palette);
jfree(palette);
palette_free(palette);
}
}
}

View File

@ -711,15 +711,15 @@ static Option *option_new(int type, const char *data)
return option;
}
static void option_free(Option *option)
static void option_free(Option* option)
{
jfree(option->data);
jfree(option);
}
static AppHook *apphook_new(void (*proc)(void *), void *data)
static AppHook *apphook_new(void (*proc)(void*), void* data)
{
AppHook *apphook = jnew(AppHook, 1);
AppHook* apphook = jnew(AppHook, 1);
if (!apphook)
return NULL;

View File

@ -243,7 +243,7 @@ static bool anieditor_msg_proc(JWidget widget, JMessage msg)
switch (msg->type) {
case JM_DESTROY:
if (anieditor->layers != NULL)
if (anieditor->layers)
jfree(anieditor->layers);
jfree(anieditor);
break;

View File

@ -248,16 +248,16 @@ void simple_dotted_mode(BITMAP *bmp, int fg, int bg)
/**********************************************************************/
/* Set/Restore sub-clip regions */
typedef struct CLIP_DATA
struct CLIP_DATA
{
BITMAP *bmp;
BITMAP* bmp;
int cl, ct, cr, cb;
} CLIP_DATA;
};
void *subclip(BITMAP *bmp, int x1, int y1, int x2, int y2)
void* subclip(BITMAP* bmp, int x1, int y1, int x2, int y2)
{
int cl, ct, cr, cb;
CLIP_DATA *data;
CLIP_DATA* data;
cl = bmp->cl;
ct = bmp->ct;
@ -274,7 +274,7 @@ void *subclip(BITMAP *bmp, int x1, int y1, int x2, int y2)
set_clip(bmp, x1, y1, x2, y2);
data = jnew(CLIP_DATA, 1);
data = new CLIP_DATA;
data->bmp = bmp;
data->cl = cl;
data->ct = ct;
@ -284,11 +284,11 @@ void *subclip(BITMAP *bmp, int x1, int y1, int x2, int y2)
return data;
}
void backclip(void *_data)
void backclip(void* _data)
{
CLIP_DATA* data = reinterpret_cast<CLIP_DATA*>(_data);
set_clip(data->bmp, data->cl, data->ct, data->cr, data->cb);
jfree(data);
delete data;
}
/**********************************************************************/
@ -302,8 +302,8 @@ struct RectTracker
int *pixel;
};
static void do_rect(BITMAP *bmp, int x1, int y1, int x2, int y2, int c,
void (*proc)(BITMAP *bmp, int x, int y, int c))
static void do_rect(BITMAP* bmp, int x1, int y1, int x2, int y2, int c,
void (*proc)(BITMAP* bmp, int x, int y, int c))
{
int x, y, u1, u2, v1, v2;
@ -338,25 +338,25 @@ static void do_rect(BITMAP *bmp, int x1, int y1, int x2, int y2, int c,
}
}
static void count_rect(BITMAP *bmp, int x, int y, int c)
static void count_rect(BITMAP* bmp, int x, int y, int c)
{
RectTracker *data = (RectTracker *)c;
RectTracker* data = (RectTracker*)c;
data->npixel++;
}
static void save_rect(BITMAP *bmp, int x, int y, int c)
static void save_rect(BITMAP* bmp, int x, int y, int c)
{
RectTracker *data = (RectTracker *)c;
RectTracker* data = (RectTracker*)c;
data->pixel[data->npixel++] = getpixel(bmp, x, y);
}
static void restore_rect(BITMAP *bmp, int x, int y, int c)
static void restore_rect(BITMAP* bmp, int x, int y, int c)
{
RectTracker *data = (RectTracker *)c;
RectTracker* data = (RectTracker*)c;
putpixel(bmp, x, y, data->pixel[data->npixel++]);
}
RectTracker *rect_tracker_new(BITMAP *bmp, int x1, int y1, int x2, int y2)
RectTracker* rect_tracker_new(BITMAP* bmp, int x1, int y1, int x2, int y2)
{
RectTracker *data;
int x, y;
@ -366,7 +366,7 @@ RectTracker *rect_tracker_new(BITMAP *bmp, int x1, int y1, int x2, int y2)
if (x1 > x2) { x = x1; x1 = x2; x2 = x; }
if (y1 > y2) { y = y1; y1 = y2; y2 = y; }
data = jnew(RectTracker, 1);
data = new RectTracker;
data->bmp = bmp;
data->x1 = x1;
@ -378,7 +378,7 @@ RectTracker *rect_tracker_new(BITMAP *bmp, int x1, int y1, int x2, int y2)
do_rect(bmp, x1, y1, x2, y2, (int)data, count_rect);
if (data->npixel > 0)
data->pixel = (int*)jmalloc(sizeof(int) * data->npixel);
data->pixel = new int[data->npixel];
else
data->pixel = NULL;
@ -390,7 +390,7 @@ RectTracker *rect_tracker_new(BITMAP *bmp, int x1, int y1, int x2, int y2)
return data;
}
void rect_tracker_free(RectTracker *data)
void rect_tracker_free(RectTracker* data)
{
jmouse_hide();
@ -398,9 +398,8 @@ void rect_tracker_free(RectTracker *data)
do_rect(data->bmp, data->x1, data->y1, data->x2, data->y2,
(int)data, restore_rect);
if (data->pixel != NULL)
jfree(data->pixel);
jfree(data);
delete[] data->pixel;
delete data;
jmouse_show();
}

View File

@ -225,7 +225,7 @@ ImageRef *images_ref_get_from_sprite(Sprite* sprite, int target, bool write)
return images_ref_get_from_layer(sprite, layer, target, write);
}
void images_ref_free(ImageRef *image_ref)
void images_ref_free(ImageRef* image_ref)
{
ImageRef *p, *next;

View File

@ -32,6 +32,9 @@ static JMutex objects_mutex;
static gfxobj_id object_id = 0; // last object ID created
static std::map<gfxobj_id, GfxObj*> objects_map; // graphics objects map
static void insert_gfxobj(GfxObj* gfxobj);
static void erase_gfxobj(GfxObj* gfxobj);
//////////////////////////////////////////////////////////////////////
bool gfxobj_init()
@ -46,7 +49,6 @@ bool gfxobj_init()
void gfxobj_exit()
{
assert(objects_map.empty());
jmutex_free(objects_mutex);
}
@ -69,14 +71,7 @@ GfxObj::~GfxObj()
{
// we have to remove this object from the map
jmutex_lock(objects_mutex);
{
std::map<gfxobj_id, GfxObj*>::iterator
it = objects_map.find(this->id);
assert(it != objects_map.end());
objects_map.erase(it);
}
erase_gfxobj(this);
jmutex_unlock(objects_mutex);
}
@ -88,7 +83,7 @@ void GfxObj::assign_id()
this->id = ++object_id;
// and here we add the object in the map of graphics-objects
objects_map.insert(std::make_pair(this->id, this));
insert_gfxobj(this);
}
jmutex_unlock(objects_mutex);
}
@ -115,7 +110,29 @@ GfxObj* gfxobj_find(gfxobj_id id)
void _gfxobj_set_id(GfxObj* gfxobj, gfxobj_id id)
{
assert(gfxobj_find(gfxobj->id) == gfxobj);
assert(gfxobj_find(id) == NULL);
gfxobj->id = id;
jmutex_lock(objects_mutex);
erase_gfxobj(gfxobj); // remove the object
gfxobj->id = id; // change the ID
insert_gfxobj(gfxobj); // insert the object again in the map
jmutex_unlock(objects_mutex);
}
//////////////////////////////////////////////////////////////////////
static void insert_gfxobj(GfxObj* gfxobj)
{
objects_map.insert(std::make_pair(gfxobj->id, gfxobj));
}
static void erase_gfxobj(GfxObj* gfxobj)
{
std::map<gfxobj_id, GfxObj*>::iterator
it = objects_map.find(gfxobj->id);
assert(it != objects_map.end());
objects_map.erase(it);
}

View File

@ -545,3 +545,47 @@ int image_count_diff(const Image* i1, const Image* i2)
return diff;
}
bool image_shrink_rect(Image *image, int *x1, int *y1, int *x2, int *y2, int refpixel)
{
#define SHRINK_SIDE(u_begin, u_op, u_final, u_add, \
v_begin, v_op, v_final, v_add, U, V, var) \
do { \
for (u = u_begin; u u_op u_final; u u_add) { \
for (v = v_begin; v v_op v_final; v v_add) { \
if (image->method->getpixel (image, U, V) != refpixel) \
break; \
} \
if (v == v_final) \
var; \
else \
break; \
} \
} while (0)
int u, v;
*x1 = 0;
*y1 = 0;
*x2 = image->w-1;
*y2 = image->h-1;
SHRINK_SIDE(0, <, image->w, ++,
0, <, image->h, ++, u, v, (*x1)++);
SHRINK_SIDE(0, <, image->h, ++,
0, <, image->w, ++, v, u, (*y1)++);
SHRINK_SIDE(image->w-1, >, 0, --,
0, <, image->h, ++, u, v, (*x2)--);
SHRINK_SIDE(image->h-1, >, 0, --,
0, <, image->w, ++, v, u, (*y2)--);
if ((*x1 > *x2) || (*y1 > *y2))
return false;
else
return true;
#undef SHRINK_SIDE
}

View File

@ -138,5 +138,6 @@ void image_to_allegro(Image* image, BITMAP* bmp, int x, int y);
void image_convert(Image* dst, const Image* src);
int image_count_diff(const Image* i1, const Image* i2);
bool image_shrink_rect(Image *image, int *x1, int *y1, int *x2, int *y2, int refpixel);
#endif /* RASTER_IMAGE_H */

View File

@ -446,6 +446,9 @@ void sprite_set_format_options(Sprite* sprite, struct FormatOptions *format_opti
void sprite_set_size(Sprite* sprite, int w, int h)
{
assert(w > 0);
assert(h > 0);
sprite->w = w;
sprite->h = h;
}

View File

@ -41,8 +41,10 @@ Stock::Stock(const Stock& stock)
: GfxObj(stock)
{
this->imgtype = stock.imgtype;
this->nimage = 0;
this->image = NULL;
for (int c=this->nimage; c<stock.nimage; ++c) {
for (int c=0; c<stock.nimage; ++c) {
if (!stock.image[c])
stock_add_image(this, NULL);
else {
@ -58,7 +60,7 @@ Stock::Stock(const Stock& stock)
Stock::~Stock()
{
for (int i=0; i<this->nimage; i++) {
if (this->image[i] != NULL)
if (this->image[i])
image_free(this->image[i]);
}
jfree(this->image);

View File

@ -627,7 +627,6 @@ static void chunk_image_new(UndoStream* stream, Image* image, int x, int y, int
chunk->y = y;
chunk->w = w;
chunk->h = h;
/* chunk->data = jmalloc(size*h); */
ptr = chunk->data;
for (v=0; v<h; ++v) {
@ -636,11 +635,6 @@ static void chunk_image_new(UndoStream* stream, Image* image, int x, int y, int
}
}
/* static void chunk_image_free(UndoChunkImage* chunk) */
/* { */
/* jfree(chunk->data); */
/* } */
static void chunk_image_invert(UndoStream* stream, UndoChunkImage* chunk, int state)
{
unsigned int id = chunk->image_id;
@ -914,7 +908,7 @@ void undo_replace_image(Undo* undo, Stock *stock, int image_index)
static void chunk_replace_image_new(UndoStream* stream, Stock *stock, int image_index)
{
Image* image = stock->image[image_index];
Image* image = stock_get_image(stock, image_index);
UndoChunkReplaceImage* chunk = (UndoChunkReplaceImage* )
undo_chunk_new(stream,
UNDO_TYPE_REPLACE_IMAGE,
@ -930,17 +924,21 @@ static void chunk_replace_image_invert(UndoStream* stream, UndoChunkReplaceImage
{
unsigned long stock_id = chunk->stock_id;
unsigned long image_index = chunk->image_index;
Stock *stock = (Stock *)gfxobj_find(stock_id);
Stock* stock = (Stock*)gfxobj_find(stock_id);
if (stock) {
// read the image to be restored from the chunk
Image* image = read_raw_image(chunk->data);
// save the current image in the (redo) stream
chunk_replace_image_new(stream, stock, image_index);
Image* old_image = stock_get_image(stock, image_index);
if (stock->image[image_index])
image_free(stock->image[image_index]);
// replace the image in the stock
stock_replace_image(stock, image_index, image);
// destroy the old image
image_free(old_image);
}
}

View File

@ -118,6 +118,69 @@ void Undoable::set_current_layer(Layer* layer)
sprite_set_layer(sprite, layer);
}
void Undoable::set_sprite_size(int w, int h)
{
assert(w > 0);
assert(h > 0);
if (is_enabled()) {
undo_int(sprite->undo, sprite, &sprite->w);
undo_int(sprite->undo, sprite, &sprite->h);
}
sprite_set_size(sprite, w, h);
}
void Undoable::crop_sprite(int x, int y, int w, int h, int bgcolor)
{
set_sprite_size(w, h);
displace_layers(sprite->set, -x, -y);
Layer *background_layer = sprite_get_background_layer(sprite);
if (background_layer)
crop_layer(background_layer, 0, 0, sprite->w, sprite->h, bgcolor);
if (!mask_is_empty(sprite->mask))
set_mask_position(sprite->mask->x-x, sprite->mask->y-y);
}
void Undoable::autocrop_sprite(int bgcolor)
{
int old_frame = sprite->frame;
int x1, y1, x2, y2;
int u1, v1, u2, v2;
x1 = y1 = INT_MAX;
x2 = y2 = INT_MIN;
Image* image = image_new(sprite->imgtype, sprite->w, sprite->h);
for (sprite->frame=0; sprite->frame<sprite->frames; sprite->frame++) {
image_clear(image, 0);
sprite_render(sprite, image, 0, 0);
// TODO configurable (what color pixel to use as "refpixel",
// here we are using the top-left pixel by default)
if (image_shrink_rect(image, &u1, &v1, &u2, &v2,
image_getpixel(image, 0, 0))) {
x1 = MIN(x1, u1);
y1 = MIN(y1, v1);
x2 = MAX(x2, u2);
y2 = MAX(y2, v2);
}
}
sprite->frame = old_frame;
image_free(image);
// do nothing
if (x1 > x2 || y1 > y2)
return;
crop_sprite(x1, y1, x2-x1+1, y2-y1+1, bgcolor);
}
/**
* Adds a new image in the stock.
*
@ -154,6 +217,22 @@ void Undoable::remove_image_from_stock(int image_index)
image_free(image);
}
void Undoable::replace_stock_image(int image_index, Image* new_image)
{
// get the current image in the 'image_index' position
Image* old_image = stock_get_image(sprite->stock, image_index);
assert(old_image);
// replace the image in the stock
if (is_enabled())
undo_replace_image(sprite->undo, sprite->stock, image_index);
stock_replace_image(sprite->stock, image_index, new_image);
// destroy the old image
image_free(old_image);
}
/**
* Creates a new transparent layer.
*/
@ -221,6 +300,47 @@ void Undoable::move_layer_after(Layer* layer, Layer* after_this)
layer_move_layer(layer->parent_layer, layer, after_this);
}
void Undoable::crop_layer(Layer* layer, int x, int y, int w, int h, int bgcolor)
{
JLink link;
if (!layer_is_background(layer))
bgcolor = 0;
JI_LIST_FOR_EACH(layer->cels, link) {
Cel* cel = reinterpret_cast<Cel*>(link->data);
crop_cel(cel, x, y, w, h, bgcolor);
}
}
/**
* Moves every frame in @a layer with the offset (@a dx, @a dy).
*/
void Undoable::displace_layers(Layer* layer, int dx, int dy)
{
switch (layer->type) {
case GFXOBJ_LAYER_IMAGE: {
Cel* cel;
JLink link;
JI_LIST_FOR_EACH(layer->cels, link) {
cel = reinterpret_cast<Cel*>(link->data);
set_cel_position(cel, cel->x+dx, cel->y+dy);
}
break;
}
case GFXOBJ_LAYER_SET: {
JLink link;
JI_LIST_FOR_EACH(layer->layers, link)
displace_layers(reinterpret_cast<Layer*>(link->data), dx, dy);
break;
}
}
}
void Undoable::new_frame()
{
// add a new cel to every layer
@ -399,6 +519,19 @@ void Undoable::set_cel_frame_position(Cel* cel, int frame)
cel->frame = frame;
}
void Undoable::set_cel_position(Cel* cel, int x, int y)
{
assert(cel);
if (is_enabled()) {
undo_int(sprite->undo, cel, &cel->x);
undo_int(sprite->undo, cel, &cel->y);
}
cel->x = x;
cel->y = y;
}
void Undoable::set_frame_duration(int frame, int msecs)
{
if (is_enabled())
@ -509,6 +642,21 @@ Cel* Undoable::get_current_cel()
return NULL;
}
void Undoable::crop_cel(Cel* cel, int x, int y, int w, int h, int bgcolor)
{
Image* cel_image = stock_get_image(sprite->stock, cel->image);
assert(cel_image);
// create the new image through a crop
Image* new_image = image_crop(cel_image, x-cel->x, y-cel->y, w, h, bgcolor);
// replace the image in the stock that is pointed by the cel
replace_stock_image(cel->image, new_image);
// update the cel's position
set_cel_position(cel, x, y);
}
Image* Undoable::get_cel_image(Cel* cel)
{
if (cel && cel->image >= 0 && cel->image < sprite->stock->nimage)
@ -577,3 +725,27 @@ void Undoable::clear_mask(int bgcolor)
}
}
void Undoable::copy_to_current_mask(Mask* mask)
{
assert(sprite->mask);
assert(mask);
if (is_enabled())
undo_set_mask(sprite->undo, sprite);
mask_copy(sprite->mask, mask);
}
void Undoable::set_mask_position(int x, int y)
{
assert(sprite->mask);
if (is_enabled()) {
undo_int(sprite->undo, sprite->mask, &sprite->mask->x);
undo_int(sprite->undo, sprite->mask, &sprite->mask->y);
}
sprite->mask->x = x;
sprite->mask->y = y;
}

View File

@ -47,15 +47,21 @@ public:
void set_number_of_frames(int frames);
void set_current_frame(int frame);
void set_current_layer(Layer* layer);
void set_sprite_size(int w, int h);
void crop_sprite(int x, int y, int w, int h, int bgcolor);
void autocrop_sprite(int bgcolor);
// for images in stock
int add_image_in_stock(Image* image);
void remove_image_from_stock(int image_index);
void replace_stock_image(int image_index, Image* new_image);
// for layers
Layer* new_layer();
void remove_layer(Layer* layer);
void move_layer_after(Layer *layer, Layer *after_this);
void crop_layer(Layer* layer, int x, int y, int w, int h, int bgcolor);
void displace_layers(Layer* layer, int dx, int dy);
// for frames
void new_frame();
@ -72,12 +78,18 @@ public:
void add_cel(Layer* layer, Cel* cel);
void remove_cel(Layer* layer, Cel* cel);
void set_cel_frame_position(Cel* cel, int frame);
void set_cel_position(Cel* cel, int x, int y);
Cel* get_current_cel();
void crop_cel(Cel* cel, int x, int y, int w, int h, int bgcolor);
// for image
Image* get_cel_image(Cel* cel);
void clear_mask(int bgcolor);
// for mask
void copy_to_current_mask(Mask* mask);
void set_mask_position(int x, int y);
};
#endif /* RASTER_UNDOABLE_H */

View File

@ -24,56 +24,6 @@
#include "util/autocrop.h"
#include "util/functions.h"
void autocrop_sprite(Sprite *sprite)
{
if (sprite != NULL) {
int old_frame = sprite->frame;
Mask *old_mask = sprite->mask;
Mask *mask;
Image *image;
int x1, y1, x2, y2;
int u1, v1, u2, v2;
x1 = y1 = INT_MAX;
x2 = y2 = INT_MIN;
image = image_new(sprite->imgtype, sprite->w, sprite->h);
if (!image)
return;
for (sprite->frame=0; sprite->frame<sprite->frames; sprite->frame++) {
image_clear(image, 0);
sprite_render(sprite, image, 0, 0);
/* TODO configurable (what color pixel to use as "refpixel",
here we are using the top-left pixel by default) */
if (get_shrink_rect(&u1, &v1, &u2, &v2,
image, image_getpixel (image, 0, 0))) {
x1 = MIN(x1, u1);
y1 = MIN(y1, v1);
x2 = MAX(x2, u2);
y2 = MAX(y2, v2);
}
}
sprite->frame = old_frame;
image_free(image);
/* do nothing */
if (x1 > x2 || y1 > y2)
return;
mask = mask_new();
mask_replace(mask, x1, y1, x2-x1+1, y2-y1+1);
sprite->mask = mask;
CropSprite(sprite);
sprite->mask = old_mask;
sprite_generate_mask_boundaries(sprite);
}
}
bool get_shrink_rect(int *x1, int *y1, int *x2, int *y2,
Image *image, int refpixel)
{

View File

@ -19,8 +19,6 @@
#ifndef UTIL_AUTOCROP_H
#define UTIL_AUTOCROP_H
void autocrop_sprite(Sprite *sprite);
bool get_shrink_rect(int *x1, int *y1, int *x2, int *y2,
Image *image, int refpixel);
bool get_shrink_rect2(int *x1, int *y1, int *x2, int *y2,

View File

@ -35,8 +35,6 @@
/* Sprite */
/*===================================================================*/
static void displace_layers(Undo *undo, Layer *layer, int x, int y);
/**
* Creates a new sprite with the given dimension with one transparent
* layer called "Layer 1".
@ -142,78 +140,6 @@ void SetSprite(Sprite *sprite)
set_current_sprite(sprite);
}
void CropSprite(Sprite *sprite)
{
if ((sprite != NULL) &&
(!mask_is_empty(sprite->mask))) {
if (undo_is_enabled(sprite->undo)) {
undo_open(sprite->undo);
undo_int(sprite->undo, (GfxObj *)sprite, &sprite->w);
undo_int(sprite->undo, (GfxObj *)sprite, &sprite->h);
}
sprite_set_size(sprite, sprite->mask->w, sprite->mask->h);
displace_layers(sprite->undo, sprite->set,
-sprite->mask->x, -sprite->mask->y);
{
Layer *background_layer = sprite_get_background_layer(sprite);
if (background_layer != NULL) {
CropLayer(background_layer, 0, 0, sprite->w, sprite->h);
}
}
if (undo_is_enabled(sprite->undo)) {
undo_int(sprite->undo, (GfxObj *)sprite->mask, &sprite->mask->x);
undo_int(sprite->undo, (GfxObj *)sprite->mask, &sprite->mask->y);
}
sprite->mask->x = 0;
sprite->mask->y = 0;
if (undo_is_enabled(sprite->undo))
undo_close(sprite->undo);
sprite_generate_mask_boundaries(sprite);
}
}
/**
* Moves every frame in "layer" with the offset "x"/"y".
*/
static void displace_layers(Undo *undo, Layer *layer, int x, int y)
{
switch (layer->type) {
case GFXOBJ_LAYER_IMAGE: {
Cel *cel;
JLink link;
JI_LIST_FOR_EACH(layer->cels, link) {
cel = reinterpret_cast<Cel*>(link->data);
if (undo_is_enabled(undo)) {
undo_int(undo, (GfxObj *)cel, &cel->x);
undo_int(undo, (GfxObj *)cel, &cel->y);
}
cel->x += x;
cel->y += y;
}
break;
}
case GFXOBJ_LAYER_SET: {
JLink link;
JI_LIST_FOR_EACH(layer->layers, link)
displace_layers(undo, reinterpret_cast<Layer*>(link->data), x, y);
break;
}
}
}
/*===================================================================*/
/* Layer */
/*===================================================================*/
@ -391,41 +317,6 @@ Layer *FlattenLayers(Sprite *sprite)
return background;
}
void CropLayer(Layer *layer, int x, int y, int w, int h)
{
Sprite *sprite = layer->sprite;
Cel *cel;
Image *image;
Image *new_image;
JLink link;
JI_LIST_FOR_EACH(layer->cels, link) {
cel = reinterpret_cast<Cel*>(link->data);
image = stock_get_image(sprite->stock, cel->image);
if (image == NULL)
continue;
new_image = image_crop(image, x-cel->x, y-cel->y, w, h,
app_get_color_to_clear_layer(layer));
if (new_image == NULL) {
console_printf(_("Not enough memory\n"));
return;
}
if (undo_is_enabled(sprite->undo)) {
undo_replace_image(sprite->undo, sprite->stock, cel->image);
undo_int(sprite->undo, (GfxObj *)cel, &cel->x);
undo_int(sprite->undo, (GfxObj *)cel, &cel->y);
}
cel->x = x;
cel->y = y;
stock_replace_image(sprite->stock, cel->image, new_image);
image_free(image);
}
}
/**
* Converts the selected layer in a `Background' layer.
*/
@ -667,38 +558,3 @@ void RemoveCel(Layer *layer, Cel *cel)
cel_free(cel);
}
}
void CropCel()
{
Sprite *sprite = current_sprite;
Image *image = GetImage(current_sprite);
if ((sprite) && (!mask_is_empty (sprite->mask)) && (image)) {
Cel *cel = layer_get_cel(sprite->layer, sprite->frame);
/* undo */
if (undo_is_enabled(sprite->undo)) {
undo_open(sprite->undo);
undo_int(sprite->undo, (GfxObj *)cel, &cel->x);
undo_int(sprite->undo, (GfxObj *)cel, &cel->y);
undo_replace_image(sprite->undo, sprite->stock, cel->image);
undo_close(sprite->undo);
}
/* replace the image */
sprite->stock->image[cel->image] =
image_crop(image,
sprite->mask->x-cel->x,
sprite->mask->y-cel->y,
sprite->mask->w,
sprite->mask->h, 0);
image_free(image); /* destroy the old image */
/* change the cel position */
cel->x = sprite->mask->x;
cel->y = sprite->mask->y;
update_screen_for_sprite(sprite);
}
}

View File

@ -33,8 +33,6 @@ void SaveSprite(const char* filename);
void SetSprite(Sprite* sprite);
void CropSprite(Sprite* sprite);
/*===================================================================*/
/* Layer */
/*===================================================================*/
@ -45,8 +43,6 @@ char *GetUniqueLayerName(Sprite* sprite);
Layer* FlattenLayers(Sprite* sprite);
void CropLayer(Layer* layer, int x, int y, int w, int h);
void BackgroundFromLayer(Sprite* sprite);
void LayerFromBackground(Sprite* sprite);
@ -56,6 +52,4 @@ void LayerFromBackground(Sprite* sprite);
void RemoveCel(Layer* layer, Cel* cel);
void CropCel();
#endif /* UTIL_FUNCTIONS_H */