diff --git a/src/raster/dirty.cpp b/src/raster/dirty.cpp index 5ed499897..8701488a7 100644 --- a/src/raster/dirty.cpp +++ b/src/raster/dirty.cpp @@ -18,548 +18,141 @@ #include "config.h" -#include +#include -#include "gui/jbase.h" // TODO remove this reference - -#include "raster/algo.h" -#include "raster/pen.h" #include "raster/dirty.h" #include "raster/image.h" -#include "raster/mask.h" -#define ADD_COLUMN(row, col, u) \ - ++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)); - -#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; u2cols; ++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(int imgtype, int x1, int y1, int x2, int y2) + : m_imgtype(imgtype) + , m_x1(x1), m_y1(y1) + , m_x2(x2), m_y2(y2) { - 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); - int u, v, size; + m_rows.resize(src.m_rows.size()); - dst->rows = src->rows; - dst->row = (DirtyRow*)jmalloc(sizeof(DirtyRow) * src->rows); + for (size_t v=0; vrows; ++v) { - 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); + row->cols.resize(srcRow.cols.size()); - for (u=0; urow[v].cols; ++u) { - dst->row[v].col[u].x = src->row[v].col[u].x; - dst->row[v].col[u].w = src->row[v].col[u].w; - 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); - - dst->row[v].col[u].data = jmalloc(size); - - memcpy(dst->row[v].col[u].data, src->row[v].col[u].data, size); + for (size_t u=0; ucols.size(); ++u) { + Col* col = new Col(*srcRow.cols[u]); + row->cols[u] = col; } - } - return dst; + m_rows[v] = row; + } } -Dirty* dirty_new_from_differences(Image* image, Image* image_diff) +Dirty::Dirty(Image* image, Image* image_diff) + : m_imgtype(image->imgtype) + , m_x1(0), m_y1(0) + , 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; for (y=0; yh; y++) { - x1 = x2 = -1; - + x1 = -1; for (x=0; xw; x++) { if (image_getpixel(image, x, y) != image_getpixel(image_diff, x, y)) { x1 = x; break; } } + if (x1 < 0) + continue; - for (x=image->w-1; x>=0; x--) { - if (image_getpixel(image, x, y) != image_getpixel(image_diff, x, y)) { - x2 = x; + for (x2=image->w-1; x2>x1; x2--) { + if (image_getpixel(image, x2, y) != image_getpixel(image_diff, x2, y)) break; - } } - if (x1 >= 0 && x2 >= 0) - dirty_hline(dirty, x1, y, x2); - } + Col* col = new Col(x1, x2-x1+1); + col->data.resize(getLineSize(col->w)); - return dirty; + Row* row = new Row(y); + row->cols.push_back(col); + + m_rows.push_back(row); + } } -void dirty_free(Dirty* dirty) +Dirty::~Dirty() { - register DirtyRow* row; - register DirtyCol* col; - DirtyRow* rowend; - DirtyCol* colend; + RowsList::iterator row_it = m_rows.begin(); + RowsList::iterator row_end = m_rows.end(); - if (dirty->row) { - row = dirty->row; - rowend = row+dirty->rows; - for (; rowcol; - colend = col+row->cols; - for (; coldata); + for (; row_it != row_end; ++row_it) { + ColsList::iterator col_it = (*row_it)->cols.begin(); + ColsList::iterator col_end = (*row_it)->cols.end(); - jfree(row->col); - } + for (; col_it != col_end; ++col_it) + delete *col_it; - jfree(dirty->row); + delete *row_it; } - jfree(dirty); } 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; vrows; v++) { - size += 4; /* y, cols (WORD[2]) */ - for (u=0; urow[v].cols; u++) { - size += 4; /* x, w (WORD[2]) */ - size += image_line_size(this->image, this->row[v].col[u].w); + RowsList::const_iterator row_it = m_rows.begin(); + RowsList::const_iterator row_end = m_rows.end(); + for (; row_it != row_end; ++row_it) { + size += 4; // y, cols (WORD[2]) + + 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; } -void dirty_hline(Dirty* dirty, int x1, int y, int x2) +void Dirty::saveImagePixels(Image* image) { - DirtyRow* row; /* row=dirty->row+v */ - DirtyCol* col; /* col=row->col+u */ - int x, u, v, w; - int u2, u3, to_x2; + 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; - if (dirty->tiled) { - if (x1 > x2) - return; + ColsList::iterator col_it = (*row_it)->cols.begin(); + ColsList::iterator col_end = (*row_it)->cols.end(); + for (; col_it != col_end; ++col_it) { + Col* col = *col_it; - dirty->tiled = false; - - 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; - 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; vrows; ++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; ucols; ++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; ucols; ++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); - - for (v=0; vrows; ++v) - for (u=0; urow[v].cols; ++u) { - if (!(dirty->row[v].col[u].flags & DIRTY_VALID_COLUMN)) { - memcpy(dirty->row[v].col[u].data, - dirty->row[v].col[u].ptr, - dirty->row[v].col[u].w<row[v].col[u].flags |= DIRTY_VALID_COLUMN; - dirty->row[v].col[u].flags |= DIRTY_MUSTBE_UPDATED; - } - } -} - -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 (; rowcol; - colend = col+row->cols; - for (; colflags & DIRTY_VALID_COLUMN) { - (*proc)(col->ptr, - col->data, - col->x, - col->x+col->w-1); - } + ase_uint8* address = (ase_uint8*)image_address(image, col->x, row->y); + std::copy(address, address+col->w, col->data.begin()); } } } -static HLineSwapper swap_hline(Image* image) +void Dirty::swapImagePixels(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; + 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; + + ColsList::iterator col_it = (*row_it)->cols.begin(); + ColsList::iterator col_end = (*row_it)->cols.end(); + for (; col_it != col_end; ++col_it) { + Col* col = *col_it; + + ase_uint8* address = (ase_uint8*)image_address(image, col->x, row->y); + std::swap_ranges(address, address+col->w, col->data.begin()); + } } - 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); } diff --git a/src/raster/dirty.h b/src/raster/dirty.h index d1b2850fd..7465bf62d 100644 --- a/src/raster/dirty.h +++ b/src/raster/dirty.h @@ -21,6 +21,8 @@ #include "raster/image.h" +#include + class Pen; class Image; class Mask; @@ -28,48 +30,68 @@ class Mask; #define DIRTY_VALID_COLUMN 1 #define DIRTY_MUSTBE_UPDATED 2 -struct DirtyCol -{ - int x, w; - char flags; - void* data; - void* ptr; -}; +class Dirty { +public: + struct Col; + struct Row; -struct DirtyRow -{ - int y; - int cols; - DirtyCol* col; -}; + typedef std::vector ColsList; + typedef std::vector RowsList; -struct Dirty -{ - Image* image; - int x1, y1; - int x2, y2; - bool tiled; - int rows; - DirtyRow* row; - Mask* mask; + struct Col { + int x, w; + std::vector data; + + Col(int x, int w) : x(x), w(w) { } + }; + + struct Row { + int y; + ColsList cols; + + Row(int y) : y(y) { } + }; + + Dirty(int imgtype, int x1, int y1, int x2, int y2); + Dirty(const Dirty& src); + Dirty(Image* image1, Image* image2); + ~Dirty(); int getMemSize() const; + + int getImgType() const { return m_imgtype; } + int x1() const { return m_x1; } + int y1() const { return m_y1; } + int x2() const { return m_x2; } + int y2() const { return m_y2; } + + int getRowsCount() const { return m_rows.size(); } + const Row& getRow(int i) const { return *m_rows[i]; } + + inline int getLineSize(int width) const { + return imgtype_line_size(m_imgtype, 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; + }; -Dirty* dirty_new(Image* image, int x1, int y1, int x2, int y2, bool tiled); -Dirty* dirty_new_copy(Dirty* src); -Dirty* dirty_new_from_differences(Image* image, Image* image_diff); -void dirty_free(Dirty* dirty); - -void dirty_hline(Dirty* dirty, int x1, int y, int x2); - -void dirty_save_image_data(Dirty* dirty); -void dirty_swap(Dirty* dirty); - -inline int dirty_line_size(Dirty* dirty, int width) -{ - return image_line_size(dirty->image, width); -} - #endif diff --git a/src/raster/undo.cpp b/src/raster/undo.cpp index f5fd7681c..f214ebe93 100644 --- a/src/raster/undo.cpp +++ b/src/raster/undo.cpp @@ -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_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_add_image_new(UndoStream* stream, Stock *stock, int image_index); @@ -244,7 +244,7 @@ static UndoAction undo_actions[] = { /* Raw data */ 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); static int get_raw_dirty_size(Dirty *dirty); static Image* read_raw_image(ase_uint8* raw_data); @@ -781,6 +781,7 @@ static void chunk_flip_invert(UndoStream* stream, UndoChunkFlip* chunk) "dirty" + DWORD image ID DIRTY_DATA see read/write_raw_dirty ***********************************************************************/ @@ -788,33 +789,40 @@ static void chunk_flip_invert(UndoStream* stream, UndoChunkFlip* chunk) struct UndoChunkDirty { UndoChunk head; + ase_uint32 image_id; 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(); } -static void chunk_dirty_new(UndoStream* stream, Dirty *dirty) +static void chunk_dirty_new(UndoStream* stream, Image* image, Dirty *dirty) { UndoChunkDirty *chunk = (UndoChunkDirty *) undo_chunk_new(stream, UNDO_TYPE_DIRTY, sizeof(UndoChunkDirty)+get_raw_dirty_size(dirty)); + chunk->image_id = image->getId(); write_raw_dirty(chunk->data, dirty); } static void chunk_dirty_invert(UndoStream* stream, UndoChunkDirty *chunk) { - Dirty *dirty = read_raw_dirty(chunk->data); + Image* image = (Image*)GfxObj::find(chunk->image_id); - if (dirty != NULL) { - dirty_swap(dirty); - chunk_dirty_new(stream, dirty); - dirty_free(dirty); + if ((image) && + (image->getType() == GFXOBJ_IMAGE)) { + Dirty* dirty = read_raw_dirty(chunk->data); + + if (dirty != NULL) { + dirty->swapImagePixels(image); + chunk_dirty_new(stream, image, dirty); + delete dirty; + } } } @@ -1863,7 +1871,6 @@ static void undo_chunk_free(UndoChunk* chunk) Raw dirty data - DWORD image ID BYTE image type WORD[4] x1, y1, x2, y2 WORD rows @@ -1880,102 +1887,97 @@ static void undo_chunk_free(UndoChunk* chunk) static Dirty *read_raw_dirty(ase_uint8* raw_data) { - ase_uint32 dword; ase_uint16 word; int x1, y1, x2, y2, size; - unsigned int image_id; - int u, v, x, y; + int u, v, x, y, w; int imgtype; - Image* image; Dirty *dirty = NULL; - read_raw_uint32(image_id); read_raw_uint8(imgtype); + read_raw_uint16(x1); + read_raw_uint16(y1); + read_raw_uint16(x2); + read_raw_uint16(y2); - image = (Image*)GfxObj::find(image_id); + dirty = new Dirty(imgtype, x1, y1, x2, y2); - if ((image) && - (image->getType() == GFXOBJ_IMAGE) && - (image->imgtype == imgtype)) { + int noRows = 0; + read_raw_uint16(noRows); + if (noRows > 0) { + dirty->m_rows.resize(noRows); - read_raw_uint16(x1); - read_raw_uint16(y1); - read_raw_uint16(x2); - read_raw_uint16(y2); + for (v=0; vgetRowsCount(); v++) { + y = 0; + read_raw_uint16(y); - dirty = dirty_new(image, x1, y1, x2, y2, false); - read_raw_uint16(dirty->rows); + Dirty::Row* row = new Dirty::Row(y); - if (dirty->rows > 0) { - dirty->row = (DirtyRow*)jmalloc(sizeof(DirtyRow) * dirty->rows); + int noCols = 0; + read_raw_uint16(noCols); + row->cols.resize(noCols); - for (v=0; vrows; v++) { - read_raw_uint16(dirty->row[v].y); - read_raw_uint16(dirty->row[v].cols); + for (u=0; urow[v].y; - - dirty->row[v].col = (DirtyCol*)jmalloc(sizeof(DirtyCol) * dirty->row[v].cols); - for (u=0; urow[v].cols; u++) { - read_raw_uint16(dirty->row[v].col[u].x); - read_raw_uint16(dirty->row[v].col[u].w); + Dirty::Col* col = new Dirty::Col(x, w); - x = dirty->row[v].col[u].x; + size = dirty->getLineSize(col->w); + ASSERT(size > 0); - size = image_line_size(dirty->image, dirty->row[v].col[u].w); + col->data.resize(size); + read_raw_data(&col->data[0], size); - dirty->row[v].col[u].flags = DIRTY_VALID_COLUMN; - dirty->row[v].col[u].data = jmalloc(size); - dirty->row[v].col[u].ptr = image_address(dirty->image, x, y); - - read_raw_data(dirty->row[v].col[u].data, size); - } + row->cols[u] = col; } + + dirty->m_rows[v] = row; } } return dirty; } -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; - int u, v, size; - write_raw_uint32(dirty->image->getId()); - write_raw_uint8(dirty->image->imgtype); - write_raw_uint16(dirty->x1); - write_raw_uint16(dirty->y1); - write_raw_uint16(dirty->x2); - write_raw_uint16(dirty->y2); - write_raw_uint16(dirty->rows); + write_raw_uint8(dirty->getImgType()); + write_raw_uint16(dirty->x1()); + write_raw_uint16(dirty->y1()); + write_raw_uint16(dirty->x2()); + write_raw_uint16(dirty->y2()); + write_raw_uint16(dirty->getRowsCount()); - for (v=0; vrows; v++) { - write_raw_uint16(dirty->row[v].y); - write_raw_uint16(dirty->row[v].cols); + for (int v=0; vgetRowsCount(); v++) { + const Dirty::Row& row = dirty->getRow(v); - for (u=0; urow[v].cols; u++) { - write_raw_uint16(dirty->row[v].col[u].x); - write_raw_uint16(dirty->row[v].col[u].w); + write_raw_uint16(row.y); + write_raw_uint16(row.cols.size()); - size = image_line_size(dirty->image, dirty->row[v].col[u].w); - write_raw_data(dirty->row[v].col[u].data, size); + for (size_t u=0; ux); + 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); } } return raw_data; } -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; vrows; v++) { - size += 4; /* y, cols (WORD[2]) */ - for (u=0; urow[v].cols; u++) { - size += 4; /* x, w (WORD[2]) */ - size += image_line_size(dirty->image, dirty->row[v].col[u].w); + for (int v=0; vgetRowsCount(); v++) { + const Dirty::Row& row = dirty->getRow(v); + + size += 4; // y, cols (WORD[2]) + for (size_t u=0; ugetLineSize(row.cols[u]->w); } } diff --git a/src/raster/undo.h b/src/raster/undo.h index d52e141d7..f9777cdfe 100644 --- a/src/raster/undo.h +++ b/src/raster/undo.h @@ -25,14 +25,13 @@ #include "ase_exception.h" class Cel; +class Dirty; class Image; class Layer; class Mask; class Palette; class Sprite; class Stock; - -struct Dirty; class UndoStream; class UndoException : public ase_exception @@ -72,7 +71,7 @@ public: void undo_data(GfxObj *gfxobj, void *data, int size); 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_dirty(Dirty *dirty); + void undo_dirty(Image* image, Dirty *dirty); void undo_add_image(Stock *stock, int image_index); void undo_remove_image(Stock *stock, int image_index); void undo_replace_image(Stock *stock, int image_index); diff --git a/src/undoable.cpp b/src/undoable.cpp index 1854982c7..3b43d4828 100644 --- a/src/undoable.cpp +++ b/src/undoable.cpp @@ -540,9 +540,10 @@ void Undoable::flattenLayers(int bgcolor) /* we have to save the current state of `cel_image' in the undo */ if (isEnabled()) { - Dirty* dirty = dirty_new_from_differences(cel_image, image); - dirty_save_image_data(dirty); - m_sprite->getUndo()->undo_dirty(dirty); + Dirty* dirty = new Dirty(cel_image, image); + dirty->saveImagePixels(cel_image); + m_sprite->getUndo()->undo_dirty(cel_image, dirty); + delete dirty; } } else { diff --git a/src/widgets/editor/editor.cpp b/src/widgets/editor/editor.cpp index 5eae85c59..6dd06a61f 100644 --- a/src/widgets/editor/editor.cpp +++ b/src/widgets/editor/editor.cpp @@ -1959,15 +1959,14 @@ public: else { /* undo the dirty region */ if (m_sprite->getUndo()->isEnabled()) { - Dirty* dirty = dirty_new_from_differences(m_cel_image, - m_dst_image); + Dirty* dirty = new Dirty(m_cel_image, m_dst_image); // TODO error handling - dirty_save_image_data(dirty); + dirty->saveImagePixels(m_cel_image); 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 */