diff --git a/src/commands/cmd_rotate_canvas.cpp b/src/commands/cmd_rotate_canvas.cpp index 8635587c7..d15318430 100644 --- a/src/commands/cmd_rotate_canvas.cpp +++ b/src/commands/cmd_rotate_canvas.cpp @@ -95,25 +95,7 @@ protected: Image* new_image = image_new(image->imgtype, m_angle == 180 ? image->w: image->h, m_angle == 180 ? image->h: image->w); - - switch (m_angle) { - case 180: - for (int y=0; yh; ++y) - for (int x=0; xw; ++x) - new_image->putpixel(image->w - x - 1, - image->h - y - 1, image->getpixel(x, y)); - break; - case 90: - for (int y=0; yh; ++y) - for (int x=0; xw; ++x) - new_image->putpixel(image->h - y - 1, x, image->getpixel(x, y)); - break; - case -90: - for (int y=0; yh; ++y) - for (int x=0; xw; ++x) - new_image->putpixel(y, image->w - x - 1, image->getpixel(x, y)); - break; - } + image_rotate(image, new_image, m_angle); undoable.replace_stock_image(i, new_image); @@ -124,15 +106,44 @@ protected: return; // Undoable destructor will undo all operations } - // resize sprite + // rotate mask + if (m_sprite->mask->bitmap) { + Mask* new_mask = mask_new(); + int x, y; + + switch (m_angle) { + case 180: + x = m_sprite->w - m_sprite->mask->x - m_sprite->mask->w; + y = m_sprite->h - m_sprite->mask->y - m_sprite->mask->h; + break; + case 90: + x = m_sprite->h - m_sprite->mask->y - m_sprite->mask->h; + y = m_sprite->mask->x; + break; + case -90: + x = m_sprite->mask->y; + y = m_sprite->w - m_sprite->mask->x - m_sprite->mask->w; + break; + } + + // create the new rotated mask + mask_replace(new_mask, x, y, + m_angle == 180 ? m_sprite->mask->w: m_sprite->mask->h, + m_angle == 180 ? m_sprite->mask->h: m_sprite->mask->w); + image_rotate(m_sprite->mask->bitmap, new_mask->bitmap, m_angle); + + // copy new mask + undoable.copy_to_current_mask(new_mask); + mask_free(new_mask); + + // regenerate mask + sprite_generate_mask_boundaries(m_sprite); + } + + // change the sprite's size if (m_angle != 180) undoable.set_sprite_size(m_sprite->h, m_sprite->w); - // TODO rotate mask - - // regenerate mask - sprite_generate_mask_boundaries(m_sprite); - // commit changes undoable.commit(); } diff --git a/src/raster/image.cpp b/src/raster/image.cpp index a943a17c4..7d16191e9 100644 --- a/src/raster/image.cpp +++ b/src/raster/image.cpp @@ -126,6 +126,46 @@ Image* image_crop(const Image* image, int x, int y, int w, int h, int bgcolor) return trim; } +void image_rotate(const Image* src, Image* dst, int angle) +{ + int x, y; + + switch (angle) { + + case 180: + assert(dst->w == src->w); + assert(dst->h == src->h); + + for (y=0; yh; ++y) + for (x=0; xw; ++x) + dst->putpixel(src->w - x - 1, + src->h - y - 1, src->getpixel(x, y)); + break; + + case 90: + assert(dst->w == src->h); + assert(dst->h == src->w); + + for (y=0; yh; ++y) + for (x=0; xw; ++x) + dst->putpixel(src->h - y - 1, x, src->getpixel(x, y)); + break; + + case -90: + assert(dst->w == src->h); + assert(dst->h == src->w); + + for (y=0; yh; ++y) + for (x=0; xw; ++x) + dst->putpixel(y, src->w - x - 1, src->getpixel(x, y)); + break; + + // bad angle + default: + throw std::invalid_argument("Invalid angle specified to rotate the image"); + } +} + void image_hline(Image* image, int x1, int y, int x2, int color) { int t; diff --git a/src/raster/image.h b/src/raster/image.h index c701370a7..2217de378 100644 --- a/src/raster/image.h +++ b/src/raster/image.h @@ -77,6 +77,7 @@ void image_merge(Image* dst, const Image* src, int x, int y, int opacity, int blend_mode); Image* image_crop(const Image* image, int x, int y, int w, int h, int bgcolor); +void image_rotate(const Image* src, Image* dst, int angle); void image_hline(Image* image, int x1, int y, int x2, int color); void image_vline(Image* image, int x, int y1, int y2, int color);