mirror of
https://github.com/aseprite/aseprite.git
synced 2025-02-06 12:39:57 +00:00
Convert Dirty to a class.
Remove all deprecated code of Dirty class that was not being used because the new ASE 0.8 tools implementation. Remove pointers to an Image/Mask from Dirty class.
This commit is contained in:
parent
9f58d0378a
commit
4c5a0177cc
@ -18,548 +18,141 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <algorithm>
|
||||||
|
|
||||||
#include "gui/jbase.h" // TODO remove this reference
|
|
||||||
|
|
||||||
#include "raster/algo.h"
|
|
||||||
#include "raster/pen.h"
|
|
||||||
#include "raster/dirty.h"
|
#include "raster/dirty.h"
|
||||||
#include "raster/image.h"
|
#include "raster/image.h"
|
||||||
#include "raster/mask.h"
|
|
||||||
|
|
||||||
#define ADD_COLUMN(row, col, u) \
|
Dirty::Dirty(int imgtype, int x1, int y1, int x2, int y2)
|
||||||
++row->cols; \
|
: m_imgtype(imgtype)
|
||||||
row->col = (DirtyCol*)jrealloc(row->col, \
|
, m_x1(x1), m_y1(y1)
|
||||||
sizeof(DirtyCol) * row->cols); \
|
, m_x2(x2), m_y2(y2)
|
||||||
col = row->col+u; \
|
|
||||||
if (u < row->cols-1) \
|
|
||||||
memmove(col+1, \
|
|
||||||
col, \
|
|
||||||
sizeof(DirtyCol) * (row->cols-1-u));
|
|
||||||
|
|
||||||
#define ADD_ROW(dirty, row, v) \
|
|
||||||
++dirty->rows; \
|
|
||||||
dirty->row = (DirtyRow*)jrealloc(dirty->row, \
|
|
||||||
sizeof(DirtyRow) * dirty->rows); \
|
|
||||||
row = dirty->row+v; \
|
|
||||||
if (v < dirty->rows-1) \
|
|
||||||
memmove(row+1, \
|
|
||||||
row, \
|
|
||||||
sizeof(DirtyRow) * (dirty->rows-1-v));
|
|
||||||
|
|
||||||
#define RESTORE_IMAGE(col) \
|
|
||||||
if ((col)->flags & DIRTY_VALID_COLUMN) { \
|
|
||||||
(col)->flags ^= DIRTY_VALID_COLUMN; \
|
|
||||||
\
|
|
||||||
memcpy((col)->ptr, \
|
|
||||||
(col)->data, \
|
|
||||||
dirty_line_size(dirty, (col)->w)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define JOIN_WITH_NEXT(row, col, u) \
|
|
||||||
{ \
|
|
||||||
RESTORE_IMAGE(col+1); \
|
|
||||||
\
|
|
||||||
col->w += (col+1)->w; \
|
|
||||||
\
|
|
||||||
if ((col+1)->data) \
|
|
||||||
jfree((col+1)->data); \
|
|
||||||
\
|
|
||||||
if (u+1 < row->cols-1) \
|
|
||||||
memmove(row->col+u+1, \
|
|
||||||
row->col+u+2, \
|
|
||||||
sizeof(DirtyCol) * (row->cols-2-u)); \
|
|
||||||
\
|
|
||||||
row->cols--; \
|
|
||||||
row->col = (DirtyCol*)jrealloc(row->col, \
|
|
||||||
sizeof(DirtyCol) * row->cols); \
|
|
||||||
col = row->col+u; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define EAT_COLUMNS() \
|
|
||||||
to_x2 = x2; \
|
|
||||||
\
|
|
||||||
/* "eat" columns in range */ \
|
|
||||||
for (u2=u+1; u2<row->cols; ++u2) { \
|
|
||||||
/* done (next column too far) */ \
|
|
||||||
if (x2 < row->col[u2].x-1) \
|
|
||||||
break; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
u2--; \
|
|
||||||
\
|
|
||||||
/* "eat" columns */ \
|
|
||||||
if (u2 > u) { \
|
|
||||||
for (u3=u+1; u3<=u2; ++u3) { \
|
|
||||||
RESTORE_IMAGE(row->col+u3); \
|
|
||||||
if (row->col[u3].data) \
|
|
||||||
jfree(row->col[u3].data); \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
to_x2 = MAX(to_x2, row->col[u2].x+row->col[u2].w-1); \
|
|
||||||
\
|
|
||||||
if (u2 < row->cols-1) \
|
|
||||||
memmove(row->col+u+1, \
|
|
||||||
row->col+u2+1, \
|
|
||||||
sizeof(DirtyCol) * (row->cols-u2-1)); \
|
|
||||||
\
|
|
||||||
row->cols -= u2 - u; \
|
|
||||||
row->col = (DirtyCol*)jrealloc(row->col, \
|
|
||||||
sizeof(DirtyCol) * row->cols); \
|
|
||||||
col = row->col+u; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
row->col[u].w = to_x2 - row->col[u].x + 1; \
|
|
||||||
row->col[u].data = jrealloc(row->col[u].data, \
|
|
||||||
dirty_line_size(dirty, row->col[u].w));
|
|
||||||
|
|
||||||
typedef void (*HLineSwapper)(void*,void*,int,int);
|
|
||||||
|
|
||||||
static HLineSwapper swap_hline(Image* image);
|
|
||||||
static void swap_hline32(void* image, void* data, int x1, int x2);
|
|
||||||
static void swap_hline16(void* image, void* data, int x1, int x2);
|
|
||||||
static void swap_hline8(void* image, void* data, int x1, int x2);
|
|
||||||
|
|
||||||
Dirty* dirty_new(Image* image, int x1, int y1, int x2, int y2, bool tiled)
|
|
||||||
{
|
{
|
||||||
Dirty* dirty = new Dirty;
|
|
||||||
|
|
||||||
dirty->image = image;
|
|
||||||
dirty->x1 = MID(0, x1, image->w-1);
|
|
||||||
dirty->y1 = MID(0, y1, image->h-1);
|
|
||||||
dirty->x2 = MID(x1, x2, image->w-1);
|
|
||||||
dirty->y2 = MID(y1, y2, image->h-1);
|
|
||||||
dirty->tiled = tiled;
|
|
||||||
dirty->rows = 0;
|
|
||||||
dirty->row = NULL;
|
|
||||||
dirty->mask = NULL;
|
|
||||||
|
|
||||||
return dirty;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Dirty* dirty_new_copy(Dirty* src)
|
Dirty::Dirty(const Dirty& src)
|
||||||
|
: m_imgtype(src.m_imgtype)
|
||||||
|
, m_x1(src.m_x1), m_y1(src.m_y1)
|
||||||
|
, m_x2(src.m_x2), m_y2(src.m_y2)
|
||||||
{
|
{
|
||||||
Dirty* dst = dirty_new(src->image, src->x1, src->y1, src->x2, src->y2, src->tiled);
|
m_rows.resize(src.m_rows.size());
|
||||||
int u, v, size;
|
|
||||||
|
|
||||||
dst->rows = src->rows;
|
for (size_t v=0; v<m_rows.size(); ++v) {
|
||||||
dst->row = (DirtyRow*)jmalloc(sizeof(DirtyRow) * src->rows);
|
const Row& srcRow = src.getRow(v);
|
||||||
|
Row* row = new Row(srcRow.y);
|
||||||
|
|
||||||
for (v=0; v<dst->rows; ++v) {
|
row->cols.resize(srcRow.cols.size());
|
||||||
dst->row[v].y = src->row[v].y;
|
|
||||||
dst->row[v].cols = src->row[v].cols;
|
|
||||||
dst->row[v].col = (DirtyCol*)jmalloc(sizeof(DirtyCol) * dst->row[v].cols);
|
|
||||||
|
|
||||||
for (u=0; u<dst->row[v].cols; ++u) {
|
for (size_t u=0; u<row->cols.size(); ++u) {
|
||||||
dst->row[v].col[u].x = src->row[v].col[u].x;
|
Col* col = new Col(*srcRow.cols[u]);
|
||||||
dst->row[v].col[u].w = src->row[v].col[u].w;
|
row->cols[u] = col;
|
||||||
dst->row[v].col[u].flags = src->row[v].col[u].flags;
|
}
|
||||||
dst->row[v].col[u].ptr = src->row[v].col[u].ptr;
|
|
||||||
|
|
||||||
size = dst->row[v].col[u].w << image_shift(dst->image);
|
m_rows[v] = row;
|
||||||
|
|
||||||
dst->row[v].col[u].data = jmalloc(size);
|
|
||||||
|
|
||||||
memcpy(dst->row[v].col[u].data, src->row[v].col[u].data, size);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return dst;
|
Dirty::Dirty(Image* image, Image* image_diff)
|
||||||
}
|
: m_imgtype(image->imgtype)
|
||||||
|
, m_x1(0), m_y1(0)
|
||||||
Dirty* dirty_new_from_differences(Image* image, Image* image_diff)
|
, m_x2(image->w-1), m_y2(image->h-1)
|
||||||
{
|
{
|
||||||
Dirty* dirty = dirty_new(image, 0, 0, image->w, image->h, false);
|
|
||||||
int x, y, x1, x2;
|
int x, y, x1, x2;
|
||||||
|
|
||||||
for (y=0; y<image->h; y++) {
|
for (y=0; y<image->h; y++) {
|
||||||
x1 = x2 = -1;
|
x1 = -1;
|
||||||
|
|
||||||
for (x=0; x<image->w; x++) {
|
for (x=0; x<image->w; x++) {
|
||||||
if (image_getpixel(image, x, y) != image_getpixel(image_diff, x, y)) {
|
if (image_getpixel(image, x, y) != image_getpixel(image_diff, x, y)) {
|
||||||
x1 = x;
|
x1 = x;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (x1 < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
for (x=image->w-1; x>=0; x--) {
|
for (x2=image->w-1; x2>x1; x2--) {
|
||||||
if (image_getpixel(image, x, y) != image_getpixel(image_diff, x, y)) {
|
if (image_getpixel(image, x2, y) != image_getpixel(image_diff, x2, y))
|
||||||
x2 = x;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Col* col = new Col(x1, x2-x1+1);
|
||||||
|
col->data.resize(getLineSize(col->w));
|
||||||
|
|
||||||
|
Row* row = new Row(y);
|
||||||
|
row->cols.push_back(col);
|
||||||
|
|
||||||
|
m_rows.push_back(row);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (x1 >= 0 && x2 >= 0)
|
Dirty::~Dirty()
|
||||||
dirty_hline(dirty, x1, y, x2);
|
|
||||||
}
|
|
||||||
|
|
||||||
return dirty;
|
|
||||||
}
|
|
||||||
|
|
||||||
void dirty_free(Dirty* dirty)
|
|
||||||
{
|
{
|
||||||
register DirtyRow* row;
|
RowsList::iterator row_it = m_rows.begin();
|
||||||
register DirtyCol* col;
|
RowsList::iterator row_end = m_rows.end();
|
||||||
DirtyRow* rowend;
|
|
||||||
DirtyCol* colend;
|
|
||||||
|
|
||||||
if (dirty->row) {
|
for (; row_it != row_end; ++row_it) {
|
||||||
row = dirty->row;
|
ColsList::iterator col_it = (*row_it)->cols.begin();
|
||||||
rowend = row+dirty->rows;
|
ColsList::iterator col_end = (*row_it)->cols.end();
|
||||||
for (; row<rowend; ++row) {
|
|
||||||
col = row->col;
|
|
||||||
colend = col+row->cols;
|
|
||||||
for (; col<colend; ++col)
|
|
||||||
jfree(col->data);
|
|
||||||
|
|
||||||
jfree(row->col);
|
for (; col_it != col_end; ++col_it)
|
||||||
|
delete *col_it;
|
||||||
|
|
||||||
|
delete *row_it;
|
||||||
}
|
}
|
||||||
|
|
||||||
jfree(dirty->row);
|
|
||||||
}
|
|
||||||
jfree(dirty);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Dirty::getMemSize() const
|
int Dirty::getMemSize() const
|
||||||
{
|
{
|
||||||
int u, v, size = 4+1+2*4+2; /* DWORD+BYTE+WORD[4]+WORD */
|
int size = 4+1+2*4+2; // DWORD+BYTE+WORD[4]+WORD
|
||||||
|
|
||||||
for (v=0; v<this->rows; v++) {
|
RowsList::const_iterator row_it = m_rows.begin();
|
||||||
size += 4; /* y, cols (WORD[2]) */
|
RowsList::const_iterator row_end = m_rows.end();
|
||||||
for (u=0; u<this->row[v].cols; u++) {
|
for (; row_it != row_end; ++row_it) {
|
||||||
size += 4; /* x, w (WORD[2]) */
|
size += 4; // y, cols (WORD[2])
|
||||||
size += image_line_size(this->image, this->row[v].col[u].w);
|
|
||||||
|
ColsList::const_iterator col_it = (*row_it)->cols.begin();
|
||||||
|
ColsList::const_iterator col_end = (*row_it)->cols.end();
|
||||||
|
for (; col_it != col_end; ++col_it) {
|
||||||
|
size += 4; // x, w (WORD[2])
|
||||||
|
size += getLineSize((*col_it)->w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dirty_hline(Dirty* dirty, int x1, int y, int x2)
|
void Dirty::saveImagePixels(Image* image)
|
||||||
{
|
{
|
||||||
DirtyRow* row; /* row=dirty->row+v */
|
RowsList::iterator row_it = m_rows.begin();
|
||||||
DirtyCol* col; /* col=row->col+u */
|
RowsList::iterator row_end = m_rows.end();
|
||||||
int x, u, v, w;
|
for (; row_it != row_end; ++row_it) {
|
||||||
int u2, u3, to_x2;
|
Row* row = *row_it;
|
||||||
|
|
||||||
if (dirty->tiled) {
|
ColsList::iterator col_it = (*row_it)->cols.begin();
|
||||||
if (x1 > x2)
|
ColsList::iterator col_end = (*row_it)->cols.end();
|
||||||
return;
|
for (; col_it != col_end; ++col_it) {
|
||||||
|
Col* col = *col_it;
|
||||||
|
|
||||||
dirty->tiled = false;
|
ase_uint8* address = (ase_uint8*)image_address(image, col->x, row->y);
|
||||||
|
std::copy(address, address+col->w, col->data.begin());
|
||||||
if (y < 0)
|
}
|
||||||
y = dirty->image->h - (-(y+1) % dirty->image->h) - 1;
|
|
||||||
else
|
|
||||||
y = y % dirty->image->h;
|
|
||||||
|
|
||||||
w = x2-x1+1;
|
|
||||||
if (w >= dirty->image->w)
|
|
||||||
dirty_hline(dirty, 0, y, dirty->image->w-1);
|
|
||||||
else {
|
|
||||||
x = x1;
|
|
||||||
if (x < 0)
|
|
||||||
x = dirty->image->w - (-(x+1) % dirty->image->w) - 1;
|
|
||||||
else
|
|
||||||
x = x % dirty->image->w;
|
|
||||||
|
|
||||||
if (x+w-1 <= dirty->image->w-1)
|
|
||||||
dirty_hline(dirty, x, y, x+w-1);
|
|
||||||
else {
|
|
||||||
dirty_hline(dirty, x, y, dirty->image->w-1);
|
|
||||||
dirty_hline(dirty, 0, y, w-(dirty->image->w-x)-1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dirty->tiled = true;
|
void Dirty::swapImagePixels(Image* image)
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* clip */
|
|
||||||
if ((y < dirty->y1) || (y > dirty->y2))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (x1 < dirty->x1)
|
|
||||||
x1 = dirty->x1;
|
|
||||||
|
|
||||||
if (x2 > dirty->x2)
|
|
||||||
x2 = dirty->x2;
|
|
||||||
|
|
||||||
if (x1 > x2)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* mask clip */
|
|
||||||
if (dirty->mask) {
|
|
||||||
if ((y < dirty->mask->y) || (y >= dirty->mask->y+dirty->mask->h))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (x1 < dirty->mask->x)
|
|
||||||
x1 = dirty->mask->x;
|
|
||||||
|
|
||||||
if (x2 > dirty->mask->x+dirty->mask->w-1)
|
|
||||||
x2 = dirty->mask->x+dirty->mask->w-1;
|
|
||||||
|
|
||||||
if (dirty->mask->bitmap) {
|
|
||||||
for (; x1<=x2; ++x1)
|
|
||||||
if (dirty->mask->bitmap->getpixel(x1-dirty->mask->x,
|
|
||||||
y-dirty->mask->y))
|
|
||||||
break;
|
|
||||||
|
|
||||||
for (; x2>=x1; x2--)
|
|
||||||
if (dirty->mask->bitmap->getpixel(x2-dirty->mask->x,
|
|
||||||
y-dirty->mask->y))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (x1 > x2)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check if the row exists */
|
|
||||||
row = NULL;
|
|
||||||
|
|
||||||
for (v=0; v<dirty->rows; ++v)
|
|
||||||
if (dirty->row[v].y == y) {
|
|
||||||
row = dirty->row+v;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (dirty->row[v].y > y)
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* we must add a new row? */
|
|
||||||
if (!row) {
|
|
||||||
ADD_ROW(dirty, row, v);
|
|
||||||
|
|
||||||
row->y = y;
|
|
||||||
row->cols = 0;
|
|
||||||
row->col = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**********************************************************************/
|
|
||||||
/* HLINE for Dirty with mask */
|
|
||||||
|
|
||||||
if (dirty->mask && dirty->mask->bitmap) {
|
|
||||||
for (x=x1; x<=x2; ++x) {
|
|
||||||
if (!dirty->mask->bitmap->getpixel(x-dirty->mask->x,
|
|
||||||
y-dirty->mask->y)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check if the pixel is inside some column */
|
|
||||||
col = row->col;
|
|
||||||
for (u=0; u<row->cols; ++u, ++col) {
|
|
||||||
/* inside a existent column */
|
|
||||||
if ((x >= col->x) && (x <= col->x+col->w-1))
|
|
||||||
goto done;
|
|
||||||
/* the pixel is in the right of the column */
|
|
||||||
else if (x == col->x+col->w) {
|
|
||||||
RESTORE_IMAGE(col);
|
|
||||||
|
|
||||||
++col->w;
|
|
||||||
|
|
||||||
/* there is a left column? */
|
|
||||||
if (u < row->cols-1 && x == (col+1)->x-1) {
|
|
||||||
if ((col+1)->flags & DIRTY_VALID_COLUMN) {
|
|
||||||
(col+1)->flags ^= DIRTY_VALID_COLUMN;
|
|
||||||
|
|
||||||
memcpy((col+1)->ptr,
|
|
||||||
(col+1)->data,
|
|
||||||
dirty_line_size(dirty, (col+1)->w));
|
|
||||||
}
|
|
||||||
|
|
||||||
col->w += (col+1)->w;
|
|
||||||
|
|
||||||
/* remove the col[u+1] */
|
|
||||||
if ((col+1)->data)
|
|
||||||
jfree((col+1)->data);
|
|
||||||
|
|
||||||
if (u+1 < row->cols-1)
|
|
||||||
memmove(col+1, col+2,
|
|
||||||
sizeof(DirtyCol) * (row->cols-2-u));
|
|
||||||
|
|
||||||
row->cols--;
|
|
||||||
row->col = (DirtyCol*)jrealloc(row->col, sizeof(DirtyCol) * row->cols);
|
|
||||||
col = row->col+u;
|
|
||||||
}
|
|
||||||
|
|
||||||
col->data = jrealloc(col->data, dirty_line_size(dirty, col->w));
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
/* the pixel is in the left of the column */
|
|
||||||
else if (x == col->x-1) {
|
|
||||||
if (col->flags & DIRTY_VALID_COLUMN) {
|
|
||||||
col->flags ^= DIRTY_VALID_COLUMN;
|
|
||||||
|
|
||||||
memcpy(col->ptr,
|
|
||||||
col->data,
|
|
||||||
dirty_line_size(dirty, col->w));
|
|
||||||
}
|
|
||||||
|
|
||||||
--col->x;
|
|
||||||
++col->w;
|
|
||||||
col->data = jrealloc(col->data, dirty_line_size(dirty, col->w));
|
|
||||||
col->ptr = image_address(dirty->image, x, y);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
else if (x < col->x)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* add a new column */
|
|
||||||
++row->cols;
|
|
||||||
row->col = (DirtyCol*)jrealloc(row->col, sizeof(DirtyCol) * row->cols);
|
|
||||||
col = row->col+u;
|
|
||||||
|
|
||||||
if (u < row->cols-1)
|
|
||||||
memmove(col+1, col, sizeof(DirtyCol) * (row->cols-1-u));
|
|
||||||
|
|
||||||
col->x = x;
|
|
||||||
col->w = 1;
|
|
||||||
col->flags = 0;
|
|
||||||
col->data = jmalloc(dirty_line_size(dirty, 1));
|
|
||||||
col->ptr = image_address(dirty->image, x, y);
|
|
||||||
|
|
||||||
done:;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**********************************************************************/
|
|
||||||
/* HLINE for Dirty without mask */
|
|
||||||
|
|
||||||
else {
|
|
||||||
/* go column by column */
|
|
||||||
col = row->col;
|
|
||||||
for (u=0; u<row->cols; ++u, ++col) {
|
|
||||||
/* the hline is to right of the column */
|
|
||||||
if ((x1 >= col->x) && (x1 <= col->x+col->w)) {
|
|
||||||
/* inside the column */
|
|
||||||
if (x2 <= col->x+col->w-1)
|
|
||||||
return;
|
|
||||||
/* extend this column to "x2" */
|
|
||||||
else {
|
|
||||||
RESTORE_IMAGE(col);
|
|
||||||
EAT_COLUMNS();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* the hline is to left of the column */
|
|
||||||
else if ((x1 < col->x) && (x2 >= col->x-1)) {
|
|
||||||
RESTORE_IMAGE(col);
|
|
||||||
|
|
||||||
/* extend to left */
|
|
||||||
col->w += col->x - x1;
|
|
||||||
col->x = x1;
|
|
||||||
col->ptr = image_address(dirty->image, x1, y);
|
|
||||||
|
|
||||||
/* inside the column */
|
|
||||||
if (x2 <= col->x+col->w-1) {
|
|
||||||
col->data = jrealloc(col->data, dirty_line_size(dirty, col->w));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* extend this column to "x2" */
|
|
||||||
else {
|
|
||||||
EAT_COLUMNS();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* the next column is more too far */
|
|
||||||
else if (x2 < col->x-1)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* add a new column */
|
|
||||||
ADD_COLUMN(row, col, u);
|
|
||||||
|
|
||||||
col->x = x1;
|
|
||||||
col->w = x2-x1+1;
|
|
||||||
col->flags = 0;
|
|
||||||
col->data = jmalloc(dirty_line_size(dirty, col->w));
|
|
||||||
col->ptr = image_address(dirty->image, x1, y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void dirty_save_image_data(Dirty* dirty)
|
|
||||||
{
|
{
|
||||||
register int v, u, shift = image_shift(dirty->image);
|
RowsList::iterator row_it = m_rows.begin();
|
||||||
|
RowsList::iterator row_end = m_rows.end();
|
||||||
|
for (; row_it != row_end; ++row_it) {
|
||||||
|
Row* row = *row_it;
|
||||||
|
|
||||||
for (v=0; v<dirty->rows; ++v)
|
ColsList::iterator col_it = (*row_it)->cols.begin();
|
||||||
for (u=0; u<dirty->row[v].cols; ++u) {
|
ColsList::iterator col_end = (*row_it)->cols.end();
|
||||||
if (!(dirty->row[v].col[u].flags & DIRTY_VALID_COLUMN)) {
|
for (; col_it != col_end; ++col_it) {
|
||||||
memcpy(dirty->row[v].col[u].data,
|
Col* col = *col_it;
|
||||||
dirty->row[v].col[u].ptr,
|
|
||||||
dirty->row[v].col[u].w<<shift);
|
|
||||||
|
|
||||||
dirty->row[v].col[u].flags |= DIRTY_VALID_COLUMN;
|
ase_uint8* address = (ase_uint8*)image_address(image, col->x, row->y);
|
||||||
dirty->row[v].col[u].flags |= DIRTY_MUSTBE_UPDATED;
|
std::swap_ranges(address, address+col->w, col->data.begin());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void dirty_swap(Dirty* dirty)
|
|
||||||
{
|
|
||||||
register DirtyRow* row;
|
|
||||||
register DirtyCol* col;
|
|
||||||
DirtyRow* rowend;
|
|
||||||
DirtyCol* colend;
|
|
||||||
HLineSwapper proc;
|
|
||||||
|
|
||||||
proc = swap_hline(dirty->image);
|
|
||||||
|
|
||||||
row = dirty->row;
|
|
||||||
rowend = row+dirty->rows;
|
|
||||||
for (; row<rowend; ++row) {
|
|
||||||
col = row->col;
|
|
||||||
colend = col+row->cols;
|
|
||||||
for (; col<colend; ++col) {
|
|
||||||
if (col->flags & DIRTY_VALID_COLUMN) {
|
|
||||||
(*proc)(col->ptr,
|
|
||||||
col->data,
|
|
||||||
col->x,
|
|
||||||
col->x+col->w-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static HLineSwapper swap_hline(Image* image)
|
|
||||||
{
|
|
||||||
register HLineSwapper proc;
|
|
||||||
switch (image->imgtype) {
|
|
||||||
case IMAGE_RGB: proc = swap_hline32; break;
|
|
||||||
case IMAGE_GRAYSCALE: proc = swap_hline16; break;
|
|
||||||
case IMAGE_INDEXED: proc = swap_hline8; break;
|
|
||||||
default:
|
|
||||||
proc = NULL;
|
|
||||||
}
|
|
||||||
return proc;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SWAP_HLINE(type) \
|
|
||||||
register type* address1 = (type*)image; \
|
|
||||||
register type* address2 = (type*)data; \
|
|
||||||
register int c; \
|
|
||||||
int x; \
|
|
||||||
\
|
|
||||||
for (x=x1; x<=x2; ++x) { \
|
|
||||||
c = *address1; \
|
|
||||||
*address1 = *address2; \
|
|
||||||
*address2 = c; \
|
|
||||||
++address1; \
|
|
||||||
++address2; \
|
|
||||||
}
|
|
||||||
|
|
||||||
static void swap_hline32(void* image, void* data, int x1, int x2)
|
|
||||||
{
|
|
||||||
SWAP_HLINE(ase_uint32);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void swap_hline16(void* image, void* data, int x1, int x2)
|
|
||||||
{
|
|
||||||
SWAP_HLINE(ase_uint16);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void swap_hline8(void* image, void* data, int x1, int x2)
|
|
||||||
{
|
|
||||||
SWAP_HLINE(ase_uint8);
|
|
||||||
}
|
|
||||||
|
@ -21,6 +21,8 @@
|
|||||||
|
|
||||||
#include "raster/image.h"
|
#include "raster/image.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class Pen;
|
class Pen;
|
||||||
class Image;
|
class Image;
|
||||||
class Mask;
|
class Mask;
|
||||||
@ -28,48 +30,68 @@ class Mask;
|
|||||||
#define DIRTY_VALID_COLUMN 1
|
#define DIRTY_VALID_COLUMN 1
|
||||||
#define DIRTY_MUSTBE_UPDATED 2
|
#define DIRTY_MUSTBE_UPDATED 2
|
||||||
|
|
||||||
struct DirtyCol
|
class Dirty {
|
||||||
{
|
public:
|
||||||
|
struct Col;
|
||||||
|
struct Row;
|
||||||
|
|
||||||
|
typedef std::vector<Col*> ColsList;
|
||||||
|
typedef std::vector<Row*> RowsList;
|
||||||
|
|
||||||
|
struct Col {
|
||||||
int x, w;
|
int x, w;
|
||||||
char flags;
|
std::vector<ase_uint8> data;
|
||||||
void* data;
|
|
||||||
void* ptr;
|
Col(int x, int w) : x(x), w(w) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DirtyRow
|
struct Row {
|
||||||
{
|
|
||||||
int y;
|
int y;
|
||||||
int cols;
|
ColsList cols;
|
||||||
DirtyCol* col;
|
|
||||||
|
Row(int y) : y(y) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Dirty
|
Dirty(int imgtype, int x1, int y1, int x2, int y2);
|
||||||
{
|
Dirty(const Dirty& src);
|
||||||
Image* image;
|
Dirty(Image* image1, Image* image2);
|
||||||
int x1, y1;
|
~Dirty();
|
||||||
int x2, y2;
|
|
||||||
bool tiled;
|
|
||||||
int rows;
|
|
||||||
DirtyRow* row;
|
|
||||||
Mask* mask;
|
|
||||||
|
|
||||||
int getMemSize() const;
|
int getMemSize() const;
|
||||||
};
|
|
||||||
|
|
||||||
Dirty* dirty_new(Image* image, int x1, int y1, int x2, int y2, bool tiled);
|
int getImgType() const { return m_imgtype; }
|
||||||
Dirty* dirty_new_copy(Dirty* src);
|
int x1() const { return m_x1; }
|
||||||
Dirty* dirty_new_from_differences(Image* image, Image* image_diff);
|
int y1() const { return m_y1; }
|
||||||
void dirty_free(Dirty* dirty);
|
int x2() const { return m_x2; }
|
||||||
|
int y2() const { return m_y2; }
|
||||||
|
|
||||||
void dirty_hline(Dirty* dirty, int x1, int y, int x2);
|
int getRowsCount() const { return m_rows.size(); }
|
||||||
|
const Row& getRow(int i) const { return *m_rows[i]; }
|
||||||
|
|
||||||
void dirty_save_image_data(Dirty* dirty);
|
inline int getLineSize(int width) const {
|
||||||
void dirty_swap(Dirty* dirty);
|
return imgtype_line_size(m_imgtype, width);
|
||||||
|
|
||||||
inline int dirty_line_size(Dirty* dirty, int width)
|
|
||||||
{
|
|
||||||
return image_line_size(dirty->image, width);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void saveImagePixels(Image* image);
|
||||||
|
void swapImagePixels(Image* image);
|
||||||
|
|
||||||
|
Dirty* clone() const { return new Dirty(*this); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Disable copying through operator=
|
||||||
|
Dirty& operator=(const Dirty&);
|
||||||
|
|
||||||
|
//private: // TODO these fields are public because Undo creates
|
||||||
|
public: // a Dirty instance from a deserialization process,
|
||||||
|
// remember to "privatize" these members when the
|
||||||
|
// new Undo implementation is finished.
|
||||||
|
|
||||||
|
int m_imgtype;
|
||||||
|
int m_x1, m_y1;
|
||||||
|
int m_x2, m_y2;
|
||||||
|
RowsList m_rows;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -149,7 +149,7 @@ static void chunk_image_invert(UndoStream* stream, UndoChunkImage* chunk);
|
|||||||
static void chunk_flip_new(UndoStream* stream, Image* image, int x1, int y1, int x2, int y2, bool horz);
|
static void chunk_flip_new(UndoStream* stream, Image* image, int x1, int y1, int x2, int y2, bool horz);
|
||||||
static void chunk_flip_invert(UndoStream* stream, UndoChunkFlip *chunk);
|
static void chunk_flip_invert(UndoStream* stream, UndoChunkFlip *chunk);
|
||||||
|
|
||||||
static void chunk_dirty_new(UndoStream* stream, Dirty *dirty);
|
static void chunk_dirty_new(UndoStream* stream, Image* image, Dirty *dirty);
|
||||||
static void chunk_dirty_invert(UndoStream* stream, UndoChunkDirty *chunk);
|
static void chunk_dirty_invert(UndoStream* stream, UndoChunkDirty *chunk);
|
||||||
|
|
||||||
static void chunk_add_image_new(UndoStream* stream, Stock *stock, int image_index);
|
static void chunk_add_image_new(UndoStream* stream, Stock *stock, int image_index);
|
||||||
@ -781,6 +781,7 @@ static void chunk_flip_invert(UndoStream* stream, UndoChunkFlip* chunk)
|
|||||||
|
|
||||||
"dirty"
|
"dirty"
|
||||||
|
|
||||||
|
DWORD image ID
|
||||||
DIRTY_DATA see read/write_raw_dirty
|
DIRTY_DATA see read/write_raw_dirty
|
||||||
|
|
||||||
***********************************************************************/
|
***********************************************************************/
|
||||||
@ -788,33 +789,40 @@ static void chunk_flip_invert(UndoStream* stream, UndoChunkFlip* chunk)
|
|||||||
struct UndoChunkDirty
|
struct UndoChunkDirty
|
||||||
{
|
{
|
||||||
UndoChunk head;
|
UndoChunk head;
|
||||||
|
ase_uint32 image_id;
|
||||||
ase_uint8 data[0];
|
ase_uint8 data[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
void Undo::undo_dirty(Dirty *dirty)
|
void Undo::undo_dirty(Image* image, Dirty* dirty)
|
||||||
{
|
{
|
||||||
chunk_dirty_new(m_undoStream, dirty);
|
chunk_dirty_new(m_undoStream, image, dirty);
|
||||||
updateUndo();
|
updateUndo();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void chunk_dirty_new(UndoStream* stream, Dirty *dirty)
|
static void chunk_dirty_new(UndoStream* stream, Image* image, Dirty *dirty)
|
||||||
{
|
{
|
||||||
UndoChunkDirty *chunk = (UndoChunkDirty *)
|
UndoChunkDirty *chunk = (UndoChunkDirty *)
|
||||||
undo_chunk_new(stream,
|
undo_chunk_new(stream,
|
||||||
UNDO_TYPE_DIRTY,
|
UNDO_TYPE_DIRTY,
|
||||||
sizeof(UndoChunkDirty)+get_raw_dirty_size(dirty));
|
sizeof(UndoChunkDirty)+get_raw_dirty_size(dirty));
|
||||||
|
|
||||||
|
chunk->image_id = image->getId();
|
||||||
write_raw_dirty(chunk->data, dirty);
|
write_raw_dirty(chunk->data, dirty);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void chunk_dirty_invert(UndoStream* stream, UndoChunkDirty *chunk)
|
static void chunk_dirty_invert(UndoStream* stream, UndoChunkDirty *chunk)
|
||||||
{
|
{
|
||||||
|
Image* image = (Image*)GfxObj::find(chunk->image_id);
|
||||||
|
|
||||||
|
if ((image) &&
|
||||||
|
(image->getType() == GFXOBJ_IMAGE)) {
|
||||||
Dirty* dirty = read_raw_dirty(chunk->data);
|
Dirty* dirty = read_raw_dirty(chunk->data);
|
||||||
|
|
||||||
if (dirty != NULL) {
|
if (dirty != NULL) {
|
||||||
dirty_swap(dirty);
|
dirty->swapImagePixels(image);
|
||||||
chunk_dirty_new(stream, dirty);
|
chunk_dirty_new(stream, image, dirty);
|
||||||
dirty_free(dirty);
|
delete dirty;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1863,7 +1871,6 @@ static void undo_chunk_free(UndoChunk* chunk)
|
|||||||
|
|
||||||
Raw dirty data
|
Raw dirty data
|
||||||
|
|
||||||
DWORD image ID
|
|
||||||
BYTE image type
|
BYTE image type
|
||||||
WORD[4] x1, y1, x2, y2
|
WORD[4] x1, y1, x2, y2
|
||||||
WORD rows
|
WORD rows
|
||||||
@ -1880,57 +1887,51 @@ static void undo_chunk_free(UndoChunk* chunk)
|
|||||||
|
|
||||||
static Dirty *read_raw_dirty(ase_uint8* raw_data)
|
static Dirty *read_raw_dirty(ase_uint8* raw_data)
|
||||||
{
|
{
|
||||||
ase_uint32 dword;
|
|
||||||
ase_uint16 word;
|
ase_uint16 word;
|
||||||
int x1, y1, x2, y2, size;
|
int x1, y1, x2, y2, size;
|
||||||
unsigned int image_id;
|
int u, v, x, y, w;
|
||||||
int u, v, x, y;
|
|
||||||
int imgtype;
|
int imgtype;
|
||||||
Image* image;
|
|
||||||
Dirty *dirty = NULL;
|
Dirty *dirty = NULL;
|
||||||
|
|
||||||
read_raw_uint32(image_id);
|
|
||||||
read_raw_uint8(imgtype);
|
read_raw_uint8(imgtype);
|
||||||
|
|
||||||
image = (Image*)GfxObj::find(image_id);
|
|
||||||
|
|
||||||
if ((image) &&
|
|
||||||
(image->getType() == GFXOBJ_IMAGE) &&
|
|
||||||
(image->imgtype == imgtype)) {
|
|
||||||
|
|
||||||
read_raw_uint16(x1);
|
read_raw_uint16(x1);
|
||||||
read_raw_uint16(y1);
|
read_raw_uint16(y1);
|
||||||
read_raw_uint16(x2);
|
read_raw_uint16(x2);
|
||||||
read_raw_uint16(y2);
|
read_raw_uint16(y2);
|
||||||
|
|
||||||
dirty = dirty_new(image, x1, y1, x2, y2, false);
|
dirty = new Dirty(imgtype, x1, y1, x2, y2);
|
||||||
read_raw_uint16(dirty->rows);
|
|
||||||
|
|
||||||
if (dirty->rows > 0) {
|
int noRows = 0;
|
||||||
dirty->row = (DirtyRow*)jmalloc(sizeof(DirtyRow) * dirty->rows);
|
read_raw_uint16(noRows);
|
||||||
|
if (noRows > 0) {
|
||||||
|
dirty->m_rows.resize(noRows);
|
||||||
|
|
||||||
for (v=0; v<dirty->rows; v++) {
|
for (v=0; v<dirty->getRowsCount(); v++) {
|
||||||
read_raw_uint16(dirty->row[v].y);
|
y = 0;
|
||||||
read_raw_uint16(dirty->row[v].cols);
|
read_raw_uint16(y);
|
||||||
|
|
||||||
y = dirty->row[v].y;
|
Dirty::Row* row = new Dirty::Row(y);
|
||||||
|
|
||||||
dirty->row[v].col = (DirtyCol*)jmalloc(sizeof(DirtyCol) * dirty->row[v].cols);
|
int noCols = 0;
|
||||||
for (u=0; u<dirty->row[v].cols; u++) {
|
read_raw_uint16(noCols);
|
||||||
read_raw_uint16(dirty->row[v].col[u].x);
|
row->cols.resize(noCols);
|
||||||
read_raw_uint16(dirty->row[v].col[u].w);
|
|
||||||
|
|
||||||
x = dirty->row[v].col[u].x;
|
for (u=0; u<noCols; u++) {
|
||||||
|
read_raw_uint16(x);
|
||||||
|
read_raw_uint16(w);
|
||||||
|
|
||||||
size = image_line_size(dirty->image, dirty->row[v].col[u].w);
|
Dirty::Col* col = new Dirty::Col(x, w);
|
||||||
|
|
||||||
dirty->row[v].col[u].flags = DIRTY_VALID_COLUMN;
|
size = dirty->getLineSize(col->w);
|
||||||
dirty->row[v].col[u].data = jmalloc(size);
|
ASSERT(size > 0);
|
||||||
dirty->row[v].col[u].ptr = image_address(dirty->image, x, y);
|
|
||||||
|
|
||||||
read_raw_data(dirty->row[v].col[u].data, size);
|
col->data.resize(size);
|
||||||
}
|
read_raw_data(&col->data[0], size);
|
||||||
|
|
||||||
|
row->cols[u] = col;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dirty->m_rows[v] = row;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1939,28 +1940,27 @@ static Dirty *read_raw_dirty(ase_uint8* raw_data)
|
|||||||
|
|
||||||
static ase_uint8* write_raw_dirty(ase_uint8* raw_data, Dirty* dirty)
|
static ase_uint8* write_raw_dirty(ase_uint8* raw_data, Dirty* dirty)
|
||||||
{
|
{
|
||||||
ase_uint32 dword;
|
|
||||||
ase_uint16 word;
|
ase_uint16 word;
|
||||||
int u, v, size;
|
|
||||||
|
|
||||||
write_raw_uint32(dirty->image->getId());
|
write_raw_uint8(dirty->getImgType());
|
||||||
write_raw_uint8(dirty->image->imgtype);
|
write_raw_uint16(dirty->x1());
|
||||||
write_raw_uint16(dirty->x1);
|
write_raw_uint16(dirty->y1());
|
||||||
write_raw_uint16(dirty->y1);
|
write_raw_uint16(dirty->x2());
|
||||||
write_raw_uint16(dirty->x2);
|
write_raw_uint16(dirty->y2());
|
||||||
write_raw_uint16(dirty->y2);
|
write_raw_uint16(dirty->getRowsCount());
|
||||||
write_raw_uint16(dirty->rows);
|
|
||||||
|
|
||||||
for (v=0; v<dirty->rows; v++) {
|
for (int v=0; v<dirty->getRowsCount(); v++) {
|
||||||
write_raw_uint16(dirty->row[v].y);
|
const Dirty::Row& row = dirty->getRow(v);
|
||||||
write_raw_uint16(dirty->row[v].cols);
|
|
||||||
|
|
||||||
for (u=0; u<dirty->row[v].cols; u++) {
|
write_raw_uint16(row.y);
|
||||||
write_raw_uint16(dirty->row[v].col[u].x);
|
write_raw_uint16(row.cols.size());
|
||||||
write_raw_uint16(dirty->row[v].col[u].w);
|
|
||||||
|
|
||||||
size = image_line_size(dirty->image, dirty->row[v].col[u].w);
|
for (size_t u=0; u<row.cols.size(); u++) {
|
||||||
write_raw_data(dirty->row[v].col[u].data, size);
|
write_raw_uint16(row.cols[u]->x);
|
||||||
|
write_raw_uint16(row.cols[u]->w);
|
||||||
|
|
||||||
|
size_t size = dirty->getLineSize(row.cols[u]->w);
|
||||||
|
write_raw_data(&row.cols[u]->data[0], size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1969,13 +1969,15 @@ static ase_uint8* write_raw_dirty(ase_uint8* raw_data, Dirty *dirty)
|
|||||||
|
|
||||||
static int get_raw_dirty_size(Dirty* dirty)
|
static int get_raw_dirty_size(Dirty* dirty)
|
||||||
{
|
{
|
||||||
int u, v, size = 4+1+2*4+2; /* DWORD+BYTE+WORD[4]+WORD */
|
int size = 1+2*4+2; // BYTE+WORD[4]+WORD
|
||||||
|
|
||||||
for (v=0; v<dirty->rows; v++) {
|
for (int v=0; v<dirty->getRowsCount(); v++) {
|
||||||
size += 4; /* y, cols (WORD[2]) */
|
const Dirty::Row& row = dirty->getRow(v);
|
||||||
for (u=0; u<dirty->row[v].cols; u++) {
|
|
||||||
size += 4; /* x, w (WORD[2]) */
|
size += 4; // y, cols (WORD[2])
|
||||||
size += image_line_size(dirty->image, dirty->row[v].col[u].w);
|
for (size_t u=0; u<row.cols.size(); u++) {
|
||||||
|
size += 4; // x, w (WORD[2])
|
||||||
|
size += dirty->getLineSize(row.cols[u]->w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,14 +25,13 @@
|
|||||||
#include "ase_exception.h"
|
#include "ase_exception.h"
|
||||||
|
|
||||||
class Cel;
|
class Cel;
|
||||||
|
class Dirty;
|
||||||
class Image;
|
class Image;
|
||||||
class Layer;
|
class Layer;
|
||||||
class Mask;
|
class Mask;
|
||||||
class Palette;
|
class Palette;
|
||||||
class Sprite;
|
class Sprite;
|
||||||
class Stock;
|
class Stock;
|
||||||
|
|
||||||
struct Dirty;
|
|
||||||
class UndoStream;
|
class UndoStream;
|
||||||
|
|
||||||
class UndoException : public ase_exception
|
class UndoException : public ase_exception
|
||||||
@ -72,7 +71,7 @@ public:
|
|||||||
void undo_data(GfxObj *gfxobj, void *data, int size);
|
void undo_data(GfxObj *gfxobj, void *data, int size);
|
||||||
void undo_image(Image *image, int x, int y, int w, int h);
|
void undo_image(Image *image, int x, int y, int w, int h);
|
||||||
void undo_flip(Image *image, int x1, int y1, int x2, int y2, bool horz);
|
void undo_flip(Image *image, int x1, int y1, int x2, int y2, bool horz);
|
||||||
void undo_dirty(Dirty *dirty);
|
void undo_dirty(Image* image, Dirty *dirty);
|
||||||
void undo_add_image(Stock *stock, int image_index);
|
void undo_add_image(Stock *stock, int image_index);
|
||||||
void undo_remove_image(Stock *stock, int image_index);
|
void undo_remove_image(Stock *stock, int image_index);
|
||||||
void undo_replace_image(Stock *stock, int image_index);
|
void undo_replace_image(Stock *stock, int image_index);
|
||||||
|
@ -540,9 +540,10 @@ void Undoable::flattenLayers(int bgcolor)
|
|||||||
|
|
||||||
/* we have to save the current state of `cel_image' in the undo */
|
/* we have to save the current state of `cel_image' in the undo */
|
||||||
if (isEnabled()) {
|
if (isEnabled()) {
|
||||||
Dirty* dirty = dirty_new_from_differences(cel_image, image);
|
Dirty* dirty = new Dirty(cel_image, image);
|
||||||
dirty_save_image_data(dirty);
|
dirty->saveImagePixels(cel_image);
|
||||||
m_sprite->getUndo()->undo_dirty(dirty);
|
m_sprite->getUndo()->undo_dirty(cel_image, dirty);
|
||||||
|
delete dirty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1959,15 +1959,14 @@ public:
|
|||||||
else {
|
else {
|
||||||
/* undo the dirty region */
|
/* undo the dirty region */
|
||||||
if (m_sprite->getUndo()->isEnabled()) {
|
if (m_sprite->getUndo()->isEnabled()) {
|
||||||
Dirty* dirty = dirty_new_from_differences(m_cel_image,
|
Dirty* dirty = new Dirty(m_cel_image, m_dst_image);
|
||||||
m_dst_image);
|
|
||||||
// TODO error handling
|
// TODO error handling
|
||||||
|
|
||||||
dirty_save_image_data(dirty);
|
dirty->saveImagePixels(m_cel_image);
|
||||||
if (dirty != NULL)
|
if (dirty != NULL)
|
||||||
m_sprite->getUndo()->undo_dirty(dirty);
|
m_sprite->getUndo()->undo_dirty(m_cel_image, dirty);
|
||||||
|
|
||||||
dirty_free(dirty);
|
delete dirty;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy the 'dst_image' to the cel_image */
|
/* copy the 'dst_image' to the cel_image */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user