diff --git a/src/commands/cmd_paste.cpp b/src/commands/cmd_paste.cpp index 6aeeac02a..631a21a5b 100644 --- a/src/commands/cmd_paste.cpp +++ b/src/commands/cmd_paste.cpp @@ -57,8 +57,7 @@ bool PasteCommand::onEnabled(Context* context) void PasteCommand::onExecute(Context* context) { - ActiveDocumentWriter document(context); - clipboard::paste(document); + clipboard::paste(); } ////////////////////////////////////////////////////////////////////// diff --git a/src/util/clipboard.cpp b/src/util/clipboard.cpp index a9a92d1fe..ce8946a4f 100644 --- a/src/util/clipboard.cpp +++ b/src/util/clipboard.cpp @@ -30,6 +30,7 @@ #include "raster/cel.h" #include "raster/image.h" #include "raster/layer.h" +#include "raster/mask.h" #include "raster/palette.h" #include "raster/quantization.h" #include "raster/rotate.h" @@ -58,55 +59,15 @@ #include "util/clipboard_win32.h" #endif -#define SCALE_MODE 0 -#define ROTATE_MODE 1 - -enum { - ACTION_SETMODE, - ACTION_MOVE, - ACTION_SCALE_TL, - ACTION_SCALE_T, - ACTION_SCALE_TR, - ACTION_SCALE_L, - ACTION_SCALE_R, - ACTION_SCALE_BL, - ACTION_SCALE_B, - ACTION_SCALE_BR, - ACTION_ROTATE_TL, - ACTION_ROTATE_T, - ACTION_ROTATE_TR, - ACTION_ROTATE_L, - ACTION_ROTATE_R, - ACTION_ROTATE_BL, - ACTION_ROTATE_B, - ACTION_ROTATE_BR, -}; - static void set_clipboard(Image* image, Palette* palette, bool set_system_clipboard); static bool copy_from_document(const Document* document); -static bool interactive_transform(Editor* widget, Image *dest_image, Image *image, - int x, int y, int xout[4], int yout[4]); -static void apply_rotation(int x1, int y1, int x2, int y2, - fixed angle, int cx, int cy, - int xout[4], int yout[4]); -static void draw_box(BITMAP *bmp, - int cx1, int cy1, int cx2, int cy2, - int x1, int y1, int x2, int y2, BITMAP *preview, - int mode, fixed angle, int cx, int cy); -static void draw_icon(BITMAP *bmp, int x, int y, int mode, fixed angle); -static void fill_in_vars(int *in_box, - int *in_left, int *in_center, int *in_right, - int *in_top, int *in_middle, int *in_bottom, - int x1, int y1, int x2, int y2, fixed angle, - int cx, int cy); -static void update_status_bar(Editor* editor, Image *image, - int x1, int y1, int x2, int y2, fixed angle); - static bool first_time = true; static Palette* clipboard_palette = NULL; static Image* clipboard_image = NULL; +static int clipboard_x = 0; +static int clipboard_y = 0; static void on_exit_delete_clipboard() { @@ -143,6 +104,9 @@ static bool copy_from_document(const Document* document) if (!image) return false; + clipboard_x = document->getMask()->x; + clipboard_y = document->getMask()->y; + const Palette* pal = document->getSprite()->getPalette(document->getSprite()->getCurrentFrame()); set_clipboard(image, pal ? new Palette(*pal): NULL, true); return true; @@ -197,17 +161,12 @@ void clipboard::copy_image(Image* image, Palette* pal) pal ? new Palette(*pal): NULL, true); } -void clipboard::paste(DocumentWriter& document) +void clipboard::paste() { - UndoTransaction undoTransaction(document, "Paste"); - undo::UndoHistory* undo = document->getUndoHistory(); - int xout[4], yout[4]; - int dst_x, dst_y; - Image *src_image; - Image* dst_image; - bool paste; + Editor* editor = current_editor; #ifdef ALLEGRO_WINDOWS + // Get the image from the clipboard. { Image* win32_image = NULL; Palette* win32_palette = NULL; @@ -216,45 +175,14 @@ void clipboard::paste(DocumentWriter& document) set_clipboard(win32_image, win32_palette, false); } #endif + + Sprite* sprite = editor->getDocument()->getSprite(); + if (clipboard_image == NULL) return; - ASSERT(document != NULL); - ASSERT(document->getSprite() != NULL); - - Sprite* sprite = document->getSprite(); - - // Destination image (where to put this image) - dst_image = sprite->getCurrentImage(&dst_x, &dst_y); - if (!dst_image) { - // We don't have an image to paste the clipboard content, - // here we create the cel/image to draw on it - - LayerImage* layer = dynamic_cast(sprite->getCurrentLayer()); - ASSERT(layer != NULL); - - // Create the image for the cel (of a size equal to the entire sprite size) - dst_image = image_new(sprite->getImgType(), sprite->getWidth(), sprite->getHeight()); - image_clear(dst_image, 0); - - // Add the new image in the stock - int dst_image_index = sprite->getStock()->addImage(dst_image); - if (undo->isEnabled()) - undo->pushUndoer(new undoers::AddImage(undo->getObjects(), - sprite->getStock(), dst_image_index)); - - // Create the new cel in the current frame with the recently - // created image - Cel* cel = new Cel(sprite->getCurrentFrame(), dst_image_index); - - // Add the cel to the layer - undoTransaction.addCel(layer, cel); - - // Default destination position - dst_x = dst_y = 0; - } - // Source image (clipboard or a converted copy to the destination 'imgtype') + Image* src_image; if (clipboard_image->imgtype == sprite->getImgType()) src_image = clipboard_image; else { @@ -264,630 +192,9 @@ void clipboard::paste(DocumentWriter& document) false); } - // Do the interactive-transform loop (where the user can move the floating image) - { - View* view = View::getView(current_editor); - gfx::Rect vp = view->getViewportBounds(); - int x, y, x1, y1, x2, y2; - - current_editor->screenToEditor(vp.x, vp.y, &x1, &y1); - current_editor->screenToEditor(vp.x+vp.w-1, vp.y+vp.h-1, &x2, &y2); - x = (x1+x2)/2-src_image->w/2; - y = (y1+y2)/2-src_image->h/2; - - paste = interactive_transform(current_editor, - dst_image, src_image, x, y, xout, yout); - } - - if (paste) { - int c, w, h, u1, v1, u2, v2; - - /* align to the destination cel-position */ - for (c=0; c<4; ++c) { - xout[c] -= dst_x; - yout[c] -= dst_y; - } - - /* clip the box for the undo */ - u1 = MAX(0, MIN(xout[0], MIN(xout[1], MIN(xout[2], xout[3])))); - v1 = MAX(0, MIN(yout[0], MIN(yout[1], MIN(yout[2], yout[3])))); - u2 = MIN(dst_image->w-1, MAX(xout[0], MAX(xout[1], MAX(xout[2], xout[3])))); - v2 = MIN(dst_image->h-1, MAX(yout[0], MAX(yout[1], MAX(yout[2], yout[3])))); - - w = u2-u1+1; - h = v2-v1+1; - - if (w >= 1 && h >= 1) { - // Add information to hold the modified region in the image. - if (undo->isEnabled()) - undo->pushUndoer(new undoers::ImageArea(undo->getObjects(), - dst_image, u1, v1, w, h)); - - // Draw the transformed image. - image_parallelogram(dst_image, src_image, - xout[0], yout[0], xout[1], yout[1], - xout[2], yout[2], xout[3], yout[3]); - } - - // Commit the "paste" operation - undoTransaction.commit(); - } + // Change to MovingPixelsState + editor->pasteImage(src_image, clipboard_x, clipboard_y); if (src_image != clipboard_image) image_free(src_image); - - update_screen_for_document(document); -} - -/**********************************************************************/ -/* interactive transform */ - -enum { DONE_NONE, DONE_CANCEL, DONE_PASTE }; - -static bool interactive_transform(Editor* editor, - Image *dest_image, Image *image, - int x, int y, - int xout[4], int yout[4]) -{ -#define UPDATE() \ - jmouse_hide(); \ - old_screen = ji_screen; \ - ji_screen = bmp1; \ - jmanager_dispatch_messages(ji_get_default_manager()); \ - ji_screen = old_screen; \ - REDRAW(); \ - jmouse_show(); - -#define REDRAW() \ - jmouse_hide(); \ - blit(bmp1, bmp2, vp.x, vp.y, 0, 0, vp.w, vp.h); \ - draw_box(bmp2, \ - 0, 0, vp.w-1, vp.h-1, \ - x1-vp.x, y1-vp.y, x2-vp.x, y2-vp.y, \ - preview, mode, angle, cx-vp.x, cy-vp.y); \ - blit(bmp2, ji_screen, 0, 0, vp.x, vp.y, vp.w, vp.h); \ - update_status_bar(editor, image, x1, y1, x2, y2, angle); \ - jmouse_show(); - - int x1, y1, x2, y2; - int u1, v1, u2, v2; - int action = ACTION_SETMODE; - int mode = SCALE_MODE; - BITMAP *bmp1, *bmp2, *preview, *old_screen; - gfx::Rect vp = View::getView(editor)->getViewportBounds(); - int done = DONE_NONE; - fixed angle = 0; - int cx, cy; - int mask_color; - - editor->hideDrawingCursor(); - - editor->editorToScreen(x, y, &x1, &y1); - editor->editorToScreen(x+image->w, y+image->h, &x2, &y2); - cx = (x1+x2)/2; - cy = (y1+y2)/2; - - /* generate a bitmap to save the viewport content and other to make - double-buffered */ - bmp1 = create_bitmap(JI_SCREEN_W, JI_SCREEN_H); - bmp2 = create_bitmap(vp.w, vp.h); - - jmouse_hide(); - blit(ji_screen, bmp1, 0, 0, 0, 0, JI_SCREEN_W, JI_SCREEN_H); - jmouse_show(); - - /* generate the preview bitmap (for fast-blitting) */ - preview = create_bitmap(image->w, image->h); - mask_color = bitmap_mask_color(preview); - image_to_allegro(image, preview, 0, 0, get_current_palette()); - - switch (image->imgtype) { - - case IMAGE_RGB: { - int x, y; - for (y=0; yh; y++) - for (x=0; xw; x++) - if (_rgba_geta(image_getpixel_fast(image, x, y)) < 128) - putpixel(preview, x, y, mask_color); - break; - } - - case IMAGE_GRAYSCALE: { - int x, y; - for (y=0; yh; y++) - for (x=0; xw; x++) - if (_graya_geta(image_getpixel_fast(image, x, y)) < 128) - putpixel(preview, x, y, mask_color); - break; - } - - case IMAGE_INDEXED: { - int x, y; - for (y=0; yh; y++) - for (x=0; xw; x++) - if (image_getpixel_fast(image, x, y) == 0) - putpixel(preview, x, y, mask_color); - break; - } - } - - /* update the bitmaps */ - UPDATE(); - - while (done == DONE_NONE) { - poll_keyboard(); - - if (keypressed()) { - int c = readkey(); - fixed old_angle = angle; - - switch (c>>8) { - case KEY_ESC: done = DONE_CANCEL; break; /* cancel */ - case KEY_ENTER: done = DONE_PASTE; break; /* paste */ - case KEY_LEFT: angle = fixadd(angle, itofix(1)); break; - case KEY_RIGHT: angle = fixsub(angle, itofix(1)); break; - case KEY_UP: angle = fixadd(angle, itofix(32)); break; - case KEY_DOWN: angle = fixsub(angle, itofix(32)); break; - } - - if (old_angle != angle) { - angle &= 255<<16; - REDRAW(); - } - } - - /* mouse moved */ - if (jmouse_poll()) { - int in_left, in_center, in_right; - int in_top, in_middle, in_bottom; - int in_box; - - fill_in_vars(&in_box, - &in_left, &in_center, &in_right, - &in_top, &in_middle, &in_bottom, - x1, y1, x2, y2, angle, cx, cy); - - if (in_box) { - jmouse_set_cursor(JI_CURSOR_SCROLL); - action = ACTION_MOVE; - } - else { - /* top */ - if (in_top && in_left) { - jmouse_set_cursor(JI_CURSOR_SIZE_TL); - action = mode == SCALE_MODE ? ACTION_SCALE_TL: ACTION_ROTATE_TL; - } - else if (in_top && in_center) { - jmouse_set_cursor(JI_CURSOR_SIZE_T); - action = mode == SCALE_MODE ? ACTION_SCALE_T: ACTION_ROTATE_T; - } - else if (in_top && in_right) { - jmouse_set_cursor(JI_CURSOR_SIZE_TR); - action = mode == SCALE_MODE ? ACTION_SCALE_TR: ACTION_ROTATE_TR; - } - /* middle */ - else if (in_middle && in_left) { - jmouse_set_cursor(JI_CURSOR_SIZE_L); - action = mode == SCALE_MODE ? ACTION_SCALE_L: ACTION_ROTATE_L; - } - else if (in_middle && in_right) { - jmouse_set_cursor(JI_CURSOR_SIZE_R); - action = mode == SCALE_MODE ? ACTION_SCALE_R: ACTION_ROTATE_R; - } - /* bottom */ - else if (in_bottom && in_left) { - jmouse_set_cursor(JI_CURSOR_SIZE_BL); - action = mode == SCALE_MODE ? ACTION_SCALE_BL: ACTION_ROTATE_BL; - } - else if (in_bottom && in_center) { - jmouse_set_cursor(JI_CURSOR_SIZE_B); - action = mode == SCALE_MODE ? ACTION_SCALE_B: ACTION_ROTATE_B; - } - else if (in_bottom && in_right) { - jmouse_set_cursor(JI_CURSOR_SIZE_BR); - action = mode == SCALE_MODE ? ACTION_SCALE_BR: ACTION_ROTATE_BR; - } - /* normal */ - else { - jmouse_set_cursor(JI_CURSOR_NORMAL); - action = ACTION_SETMODE; - } - } - } - - /* button pressed */ - if (jmouse_b(0)) { - /* left button+shift || middle button = scroll movement */ - if ((jmouse_b(0) == 1 && (key[KEY_LSHIFT] || key[KEY_RSHIFT])) || - (jmouse_b(0) == 4)) { - View* view = View::getView(editor); - - x = jmouse_x(0) - jmouse_x(1); - y = jmouse_y(0) - jmouse_y(1); - -/* screenToEditor (widget, x1, y1, &x1, &y1); */ -/* screenToEditor (widget, x2, y2, &x2, &y2); */ - - /* TODO */ - - gfx::Point scroll = view->getViewScroll(); - editor->setEditorScroll(scroll.x-x, scroll.y-y, true); - -/* editorToScreen(widget, x1, y1, &x1, &y1); */ -/* editorToScreen(widget, x2, y2, &x2, &y2); */ - - jmouse_control_infinite_scroll(vp); - - view->invalidate(); - jwidget_flush_redraw(view); - UPDATE(); - - /* recenter the pivot (cx, cy) */ -/* { */ -/* MATRIX m; */ -/* fixed fx, fy, fz; */ -/* /\* new pivot position with transformation *\/ */ -/* int ncx = (x1+x2)/2; */ -/* int ncy = (y1+y2)/2; */ - -/* get_rotation_matrix (&m, 0, 0, angle); */ - -/* /\* new pivot position in the screen *\/ */ -/* apply_matrix (&m, itofix(ncx-cx), itofix(ncy-cy), 0, &fx, &fy, &fz); */ -/* cx = cx+fixtoi(fx); */ -/* cy = cy+fixtoi(fy); */ - -/* /\* move all vertices to leave the pivot as the center *\/ */ -/* x1 += cx - ncx; */ -/* y1 += cy - ncy; */ -/* x2 += cx - ncx; */ -/* y2 += cy - ncy; */ - -/* jmouse_hide(); */ -/* blit (bmp1, bmp2, 0, 0, 0, 0, vp->w, vp->h); */ -/* draw_box (bmp2, */ -/* 0, 0, vp->w-1, vp->h-1, */ -/* x1-vp->x, y1-vp->y, x2-vp->x, y2-vp->y, */ -/* preview, mode, angle, cx-vp->x, cy-vp->y); */ -/* blit (bmp2, ji_screen, 0, 0, vp->x, vp->y, vp->w, vp->h); */ -/* update_status_bar (widget, image, x1, y1, x2, y2, angle); */ -/* jmouse_show(); */ -/* } */ - } - /* right button = paste */ - else if (jmouse_b(0) == 2) { - done = DONE_PASTE; /* paste */ - } - /* change mode */ - else if (action == ACTION_SETMODE) { - mode = (mode == SCALE_MODE) ? ROTATE_MODE: SCALE_MODE; - REDRAW(); - - do { - poll_keyboard(); - jmouse_poll(); - gui_feedback(); - } while (jmouse_b(0)); - } - /* modify selection */ - else { - int mx = jmouse_x(0); - int my = jmouse_y(0); - fixed angle1 = angle; - fixed angle2 = fixatan2(itofix(jmouse_y(0)-cy), - itofix(jmouse_x(0)-cx)); - angle2 = fixsub(0, angle2); - - u1 = x1; - v1 = y1; - u2 = x2; - v2 = y2; - - do { - poll_keyboard(); - if (jmouse_poll()) { - - if (action == ACTION_MOVE) { - x = jmouse_x(0) - mx; - y = jmouse_y(0) - my; - } - else if (action >= ACTION_SCALE_TL && - action <= ACTION_SCALE_BR) { - x = fixtoi(fixmul(itofix(jmouse_x(0) - mx), fixcos(angle))) - + fixtoi(fixmul(itofix(jmouse_y(0) - my),-fixsin(angle))); - y = fixtoi(fixmul(itofix(jmouse_x(0) - mx), fixsin(angle))) - + fixtoi(fixmul(itofix(jmouse_y(0) - my), fixcos(angle))); - } - else - x = y = 0; - - x1 = u1; - y1 = v1; - x2 = u2; - y2 = v2; - - switch (action) { - case ACTION_MOVE: - x1 += x; - y1 += y; - x2 += x; - y2 += y; - cx = (x1+x2)/2; - cy = (y1+y2)/2; - break; - case ACTION_SCALE_L: - x1 = MIN(x1+x, x2); - break; - case ACTION_SCALE_T: - y1 = MIN(y1+y, y2); - break; - case ACTION_SCALE_R: - x2 = MAX(x2+x, x1); - break; - case ACTION_SCALE_B: - y2 = MAX(y2+y, y1); - break; - case ACTION_SCALE_TL: - x1 = MIN(x1+x, x2); - y1 = MIN(y1+y, y2); - break; - case ACTION_SCALE_TR: - x2 = MAX(x2+x, x1); - y1 = MIN(y1+y, y2); - break; - case ACTION_SCALE_BL: - x1 = MIN(x1+x, x2); - y2 = MAX(y2+y, y1); - break; - case ACTION_SCALE_BR: - x2 = MAX(x2+x, x1); - y2 = MAX(y2+y, y1); - break; - case ACTION_ROTATE_TL: - case ACTION_ROTATE_T: - case ACTION_ROTATE_TR: - case ACTION_ROTATE_L: - case ACTION_ROTATE_R: - case ACTION_ROTATE_BL: - case ACTION_ROTATE_B: - case ACTION_ROTATE_BR: - angle = fixatan2(itofix(jmouse_y(0)-cy), - itofix(jmouse_x(0)-cx)); - angle &= 255<<16; - angle = fixsub(0, angle); - - angle = fixadd(angle1, fixsub (angle, angle2)); - break; - } - - editor->screenToEditor(x1, y1, &x1, &y1); - editor->screenToEditor(x2, y2, &x2, &y2); - - // if (UIContext::instance()->getSettings()->get_snap_to_grid() && angle == 0) { - // int ox = x1; - // int oy = y1; - // apply_grid(&x1, &y1, false); - // x2 += x1 - ox; - // y2 += y1 - oy; - // } - - editor->editorToScreen(x1, y1, &x1, &y1); - editor->editorToScreen(x2, y2, &x2, &y2); - - /* redraw the screen */ - REDRAW(); - } - - gui_feedback(); - } while (jmouse_b(0)); - - /* recenter the pivot (cx, cy) */ - { - MATRIX m; - fixed fx, fy, fz; - /* new pivot position with transformation */ - int ncx = (x1+x2)/2; - int ncy = (y1+y2)/2; - - get_rotation_matrix(&m, 0, 0, angle); - - /* new pivot position in the screen */ - apply_matrix(&m, itofix(ncx-cx), itofix(ncy-cy), 0, &fx, &fy, &fz); - cx = cx+fixtoi(fx); - cy = cy+fixtoi(fy); - - /* move all vertices to leave the pivot as the center */ - x1 += cx - ncx; - y1 += cy - ncy; - x2 += cx - ncx; - y2 += cy - ncy; - - REDRAW(); - } - } - } - - gui_feedback(); - } - - if (done == DONE_PASTE) { - int c; - apply_rotation(x1, y1, x2, y2, angle, cx, cy, xout, yout); - for (c=0; c<4; c++) - editor->screenToEditor(xout[c], yout[c], xout+c, yout+c); - } - - destroy_bitmap(bmp1); - destroy_bitmap(bmp2); - destroy_bitmap(preview); - - clear_keybuf(); - - /* restore the cursor */ - editor->showDrawingCursor(); - - return done == DONE_PASTE; -} - -static void apply_rotation(int x1, int y1, int x2, int y2, - fixed angle, int cx, int cy, - int xout[4], int yout[4]) -{ -#define APPLYMATRIX(_x,_y,n) \ - apply_matrix (&m, itofix (_x-cx), itofix (_y-cy), 0, &fx, &fy, &fz); \ - xout[n] = cx+fixtoi(fx); \ - yout[n] = cy+fixtoi(fy); - - MATRIX m; - fixed fx, fy, fz; - - get_rotation_matrix (&m, 0, 0, angle); - APPLYMATRIX(x1,y1,0); - APPLYMATRIX(x2,y1,1); - APPLYMATRIX(x2,y2,2); - APPLYMATRIX(x1,y2,3); -} - -static void draw_box(BITMAP *bmp, - int cx1, int cy1, int cx2, int cy2, - int x1, int y1, int x2, int y2, - BITMAP *preview, int mode, fixed angle, - int cx, int cy) -{ - fixed xs[4], ys[4]; - int x[4], y[4]; - int c; - - set_clip_rect(bmp, cx1, cy1, cx2, cy2); - - /* calculate corner positions */ - apply_rotation(x1, y1, x2, y2, angle, cx, cy, x, y); - - /* draw the preview */ - for (c=0; c<4; c++) { - xs[c] = itofix(x[c]); - ys[c] = itofix(y[c]); - } - _parallelogram_map_standard(bmp, preview, xs, ys); - - /* draw bounds */ -#if 1 - simple_dotted_mode(bmp, makecol(0, 0, 0), makecol(255, 255, 255)); - line(bmp, x[0], y[0], x[1], y[1], 0xffffff); - line(bmp, x[0], y[0], x[3], y[3], 0xffffff); - line(bmp, x[2], y[2], x[1], y[1], 0xffffff); - line(bmp, x[2], y[2], x[3], y[3], 0xffffff); - solid_mode(); -#endif - - /* draw icons */ -#define DRAWICON(n1,n2,_angle) \ - draw_icon(bmp, (x[n1]+x[n2])/2, (y[n1]+y[n2])/2, mode, _angle) - - DRAWICON(1, 2, angle); - DRAWICON(1, 1, fixadd(angle, itofix(32))); - DRAWICON(0, 1, fixadd(angle, itofix(64))); - DRAWICON(0, 0, fixadd(angle, itofix(96))); - DRAWICON(0, 3, fixadd(angle, itofix(128))); - DRAWICON(3, 3, fixadd(angle, itofix(160))); - DRAWICON(3, 2, fixadd(angle, itofix(192))); - DRAWICON(2, 2, fixadd(angle, itofix(224))); - - set_clip_rect(bmp, 0, 0, bmp->w-1, bmp->h-1); -} - -static void draw_icon(BITMAP *bmp, int x, int y, int mode, fixed angle) -{ - SkinTheme* theme = static_cast(CurrentTheme::get()); - BITMAP* gfx; - - angle &= (255<<16); - - // 0 degree - if ((angle > ((256-16)<<16)) || (angle <= ((0+16)<<16))) { - gfx = theme->get_part(mode == SCALE_MODE ? PART_SCALE_ARROW_3: PART_ROTATE_ARROW_3); - draw_sprite_ex(bmp, gfx, x, y-gfx->h/2, DRAW_SPRITE_TRANS, DRAW_SPRITE_H_FLIP); - } - // 45 degree - else if ((angle >= ((32-16)<<16)) && (angle <= ((32+16)<<16))) { - gfx = theme->get_part(mode == SCALE_MODE ? PART_SCALE_ARROW_1: PART_ROTATE_ARROW_1); - draw_sprite_ex(bmp, gfx, x, y-gfx->h, DRAW_SPRITE_TRANS, DRAW_SPRITE_H_FLIP); - } - // 90 degree - else if ((angle >= ((64-16)<<16)) && (angle <= ((64+16)<<16))) { - gfx = theme->get_part(mode == SCALE_MODE ? PART_SCALE_ARROW_2: PART_ROTATE_ARROW_2); - draw_sprite_ex(bmp, gfx, x-gfx->w/2, y-gfx->h, DRAW_SPRITE_TRANS, DRAW_SPRITE_NO_FLIP); - } - // 135 degree - else if ((angle >= ((96-16)<<16)) && (angle <= ((96+16)<<16))) { - gfx = theme->get_part(mode == SCALE_MODE ? PART_SCALE_ARROW_1: PART_ROTATE_ARROW_1); - draw_sprite_ex(bmp, gfx, x-gfx->w, y-gfx->h, DRAW_SPRITE_TRANS, DRAW_SPRITE_NO_FLIP); - } - // 180 degree - else if ((angle >= ((128-16)<<16)) && (angle <= ((128+16)<<16))) { - gfx = theme->get_part(mode == SCALE_MODE ? PART_SCALE_ARROW_3: PART_ROTATE_ARROW_3); - draw_sprite_ex(bmp, gfx, x-gfx->w, y-gfx->h/2, DRAW_SPRITE_TRANS, DRAW_SPRITE_NO_FLIP); - } - // 225 degree - else if ((angle >= ((160-16)<<16)) && (angle <= ((160+16)<<16))) { - gfx = theme->get_part(mode == SCALE_MODE ? PART_SCALE_ARROW_1: PART_ROTATE_ARROW_1); - draw_sprite_ex(bmp, gfx, x-gfx->w, y, DRAW_SPRITE_TRANS, DRAW_SPRITE_V_FLIP); - } - // 270 degree - else if ((angle >= ((192-16)<<16)) && (angle <= ((192+16)<<16))) { - gfx = theme->get_part(mode == SCALE_MODE ? PART_SCALE_ARROW_2: PART_ROTATE_ARROW_2); - draw_sprite_ex(bmp, gfx, x-gfx->w/2, y, DRAW_SPRITE_TRANS, DRAW_SPRITE_V_FLIP); - } - // 315 degree - else if ((angle >= ((224-16)<<16)) && (angle <= ((224+16)<<16))) { - gfx = theme->get_part(mode == SCALE_MODE ? PART_SCALE_ARROW_1: PART_ROTATE_ARROW_1); - draw_sprite_ex(bmp, gfx, x, y, DRAW_SPRITE_TRANS, DRAW_SPRITE_VH_FLIP); - } -} - -static void fill_in_vars(int *in_box, - int *in_left, int *in_center, int *in_right, - int *in_top, int *in_middle, int *in_bottom, - int x1, int y1, int x2, int y2, fixed angle, - int cx, int cy) -{ - MATRIX m; - int mx = jmouse_x(0); - int my = jmouse_y(0); - fixed fx, fy, fz; - - get_rotation_matrix (&m, 0, 0, fixsub (0, angle)); - apply_matrix (&m, itofix (mx-cx), itofix (my-cy), 0, &fx, &fy, &fz); - mx = cx+fixtoi (fx); - my = cy+fixtoi (fy); - - *in_box = (mx >= x1 && my >= y1 && mx <= x2 && my <= y2); - *in_left = (mx >= x1-12 && mx < x1); - *in_top = (my >= y1-12 && my < y1); - *in_right = (mx > x2 && mx <= x2+12); - *in_bottom = (my > y2 && my <= y2+12); - *in_center = (mx > (x1+x2)/2-6 && mx < (x1+x2)/2+6); - *in_middle = (my > (y1+y2)/2-6 && my < (y1+y2)/2+6); -} - -static void update_status_bar(Editor* editor, Image *image, - int x1, int y1, int x2, int y2, fixed angle) -{ - int u1, v1, u2, v2; - int iangle = 360*(fixtoi (angle & (255<<16)))/256; - - editor->screenToEditor(x1, y1, &u1, &v1); - editor->screenToEditor(x2, y2, &u2, &v2); - - app_get_statusbar()->setStatusText - (0, - "Pos: %3d %3d Size: %3d %3d Orig: %3d %3d (%.02f%% %.02f%%) Angle: %3d", - u1, v1, u2-u1, v2-v1, - image->w, image->h, - (double)(u2-u1)*100/image->w, - (double)(v2-v1)*100/image->h, - iangle); - - jwidget_flush_redraw(app_get_statusbar()); - jmanager_dispatch_messages(ji_get_default_manager()); } diff --git a/src/util/clipboard.h b/src/util/clipboard.h index db8a9ccf4..4640dfafb 100644 --- a/src/util/clipboard.h +++ b/src/util/clipboard.h @@ -32,7 +32,7 @@ namespace clipboard { void cut(DocumentWriter& document); void copy(const DocumentReader& document); void copy_image(Image* image, Palette* palette); - void paste(DocumentWriter& document); + void paste(); } // namespace clipboard diff --git a/src/widgets/editor/editor.cpp b/src/widgets/editor/editor.cpp index 309bf6208..9bde2c3c9 100644 --- a/src/widgets/editor/editor.cpp +++ b/src/widgets/editor/editor.cpp @@ -45,6 +45,8 @@ #include "widgets/color_bar.h" #include "widgets/editor/editor_customization_delegate.h" #include "widgets/editor/editor_decorator.h" +#include "widgets/editor/moving_pixels_state.h" +#include "widgets/editor/pixels_movement.h" #include "widgets/editor/standby_state.h" #include "widgets/statebar.h" @@ -1152,3 +1154,17 @@ void Editor::setZoomAndCenterInMouse(int zoom, int mouse_x, int mouse_y) } showDrawingCursor(); } + +void Editor::pasteImage(const Image* image, int x, int y) +{ + Document* document = getDocument(); + int opacity = 255; + Sprite* sprite = getSprite(); + PixelsMovement* pixelsMovement = new PixelsMovement(document, sprite, image, x, y, opacity, + "Paste"); + + // Select the pasted image so the user can move it and transform it. + pixelsMovement->maskImage(image, x, y); + + setState(EditorStatePtr(new MovingPixelsState(this, NULL, pixelsMovement, NoHandle))); +} diff --git a/src/widgets/editor/editor.h b/src/widgets/editor/editor.h index e88be8169..4e2e18b5a 100644 --- a/src/widgets/editor/editor.h +++ b/src/widgets/editor/editor.h @@ -136,6 +136,8 @@ public: bool processKeysToSetZoom(int scancode); + void pasteImage(const Image* image, int x, int y); + // in cursor.c static int get_raw_cursor_color(); diff --git a/src/widgets/editor/handle_type.h b/src/widgets/editor/handle_type.h index 3bab15aa7..f54e2b7e9 100644 --- a/src/widgets/editor/handle_type.h +++ b/src/widgets/editor/handle_type.h @@ -25,7 +25,7 @@ enum HandleType { NoHandle, // This is the handle to move the pixels region, generally, the // whole region activates this handle. - //MoveHandle, + MoveHandle, // One of the region's corders to scale. ScaleNWHandle, ScaleNHandle, ScaleNEHandle, ScaleWHandle, ScaleEHandle, diff --git a/src/widgets/editor/moving_pixels_state.cpp b/src/widgets/editor/moving_pixels_state.cpp index 3c1206843..67bb0843a 100644 --- a/src/widgets/editor/moving_pixels_state.cpp +++ b/src/widgets/editor/moving_pixels_state.cpp @@ -32,7 +32,6 @@ #include "raster/sprite.h" #include "tools/ink.h" #include "tools/tool.h" -#include "util/misc.h" #include "widgets/editor/editor.h" #include "widgets/editor/editor_customization_delegate.h" #include "widgets/editor/pixels_movement.h" @@ -42,36 +41,24 @@ #include -MovingPixelsState::MovingPixelsState(Editor* editor, Message* msg, Image* imge, int x, int y, int opacity, HandleType handle) +MovingPixelsState::MovingPixelsState(Editor* editor, Message* msg, PixelsMovement* pixelsMovement, HandleType handle) { EditorCustomizationDelegate* customization = editor->getCustomizationDelegate(); + m_pixelsMovement = pixelsMovement; - // Copy the mask to the extra cel image - Document* document = editor->getDocument(); - Sprite* sprite = editor->getSprite(); - { - UniquePtr tmpImage(NewImageFromMask(document)); - x = document->getMask()->x; - y = document->getMask()->y; - m_pixelsMovement = new PixelsMovement(document, sprite, tmpImage, x, y, opacity); + if (handle != NoHandle) { + int u, v; + editor->screenToEditor(msg->mouse.x, msg->mouse.y, &u, &v); + m_pixelsMovement->catchImage(u, v, handle); + + editor->captureMouse(); } - // If the Ctrl key is pressed start dragging a copy of the selection - if (customization && customization->isCopySelectionKeyPressed()) - m_pixelsMovement->copyMask(); - else - m_pixelsMovement->cutMask(); - - editor->screenToEditor(msg->mouse.x, msg->mouse.y, &x, &y); - m_pixelsMovement->catchImage(x, y, handle); - // Setup mask color setTransparentColor(app_get_statusbar()->getTransparentColor()); app_get_statusbar()->addListener(this); app_get_statusbar()->showMovePixelsOptions(); - - editor->captureMouse(); } MovingPixelsState::~MovingPixelsState() @@ -153,7 +140,7 @@ bool MovingPixelsState::onMouseDown(Editor* editor, Message* msg) // Re-catch the image int x, y; editor->screenToEditor(msg->mouse.x, msg->mouse.y, &x, &y); - m_pixelsMovement->catchImageAgain(x, y, NoHandle); + m_pixelsMovement->catchImageAgain(x, y, MoveHandle); editor->captureMouse(); return true; diff --git a/src/widgets/editor/moving_pixels_state.h b/src/widgets/editor/moving_pixels_state.h index 6766a0b40..be25fbb1c 100644 --- a/src/widgets/editor/moving_pixels_state.h +++ b/src/widgets/editor/moving_pixels_state.h @@ -31,8 +31,7 @@ class PixelsMovement; class MovingPixelsState : public StandbyState, StatusBarListener { public: - MovingPixelsState(Editor* editor, Message* msg, Image* imge, int x, int y, int opacity, - HandleType handle); + MovingPixelsState(Editor* editor, Message* msg, PixelsMovement* pixelsMovement, HandleType handle); virtual ~MovingPixelsState(); virtual bool onBeforeChangeState(Editor* editor) OVERRIDE; diff --git a/src/widgets/editor/pixels_movement.cpp b/src/widgets/editor/pixels_movement.cpp index 41f4c91da..8e7a94818 100644 --- a/src/widgets/editor/pixels_movement.cpp +++ b/src/widgets/editor/pixels_movement.cpp @@ -36,10 +36,11 @@ static inline const la::Vector2d point2Vector(const gfx::PointT& pt) return la::Vector2d(pt.x, pt.y); } -PixelsMovement::PixelsMovement(Document* document, Sprite* sprite, const Image* moveThis, int initialX, int initialY, int opacity) +PixelsMovement::PixelsMovement(Document* document, Sprite* sprite, const Image* moveThis, int initialX, int initialY, int opacity, + const char* operationName) : m_documentReader(document) , m_sprite(sprite) - , m_undoTransaction(document, "Pixels Movement") + , m_undoTransaction(document, operationName) , m_firstDrop(true) , m_isDragging(false) , m_adjustPivot(false) @@ -91,6 +92,8 @@ void PixelsMovement::copyMask() void PixelsMovement::catchImage(int x, int y, HandleType handle) { + ASSERT(handle != NoHandle); + m_catchX = x; m_catchY = y; m_isDragging = true; @@ -119,6 +122,32 @@ void PixelsMovement::catchImageAgain(int x, int y, HandleType handle) update_screen_for_document(m_documentReader); } +void PixelsMovement::maskImage(const Image* image, int x, int y) +{ + mask_replace(m_currentMask, x, y, image->w, image->h); + + m_currentMask->freeze(); + image_clear(m_currentMask->bitmap, 0); + for (int v=0; vh; ++v) { + for (int u=0; uw; ++u) { + int bit = (image->getpixel(u, v) != image->mask_color ? 1: 0); + m_currentMask->bitmap->putpixel(u, v, bit); + } + } + m_currentMask->unfreeze(); + + mask_copy(m_initialMask, m_currentMask); + + DocumentWriter documentWriter(m_documentReader); + + m_undoTransaction.copyToCurrentMask(m_currentMask); + + documentWriter->setMask(m_currentMask); + documentWriter->generateMaskBoundaries(m_currentMask); + + update_screen_for_document(m_documentReader); +} + gfx::Rect PixelsMovement::moveImage(int x, int y) { DocumentWriter documentWriter(m_documentReader); @@ -141,7 +170,7 @@ gfx::Rect PixelsMovement::moveImage(int x, int y) switch (m_handle) { - case NoHandle: + case MoveHandle: x1 += dx; y1 += dy; x2 += dx; diff --git a/src/widgets/editor/pixels_movement.h b/src/widgets/editor/pixels_movement.h index c8838d0f1..9cc8984c4 100644 --- a/src/widgets/editor/pixels_movement.h +++ b/src/widgets/editor/pixels_movement.h @@ -37,7 +37,8 @@ class PixelsMovement public: // The "moveThis" image specifies the chunk of pixels to be moved. // The "x" and "y" parameters specify the initial position of the image. - PixelsMovement(Document* document, Sprite* sprite, const Image* moveThis, int x, int y, int opacity); + PixelsMovement(Document* document, Sprite* sprite, const Image* moveThis, int x, int y, int opacity, + const char* operationName); ~PixelsMovement(); void cutMask(); @@ -45,6 +46,10 @@ public: void catchImage(int x, int y, HandleType handle); void catchImageAgain(int x, int y, HandleType handle); + // Creates a mask for the given image. Useful when the user paste a + // image from the clipboard. + void maskImage(const Image* image, int x, int y); + // Moves the image to the new position (relative to the start // position given in the ctor). Returns the rectangle that should be // redrawn. diff --git a/src/widgets/editor/standby_state.cpp b/src/widgets/editor/standby_state.cpp index 1196f98cf..ab1f7ecb7 100644 --- a/src/widgets/editor/standby_state.cpp +++ b/src/widgets/editor/standby_state.cpp @@ -36,6 +36,7 @@ #include "tools/ink.h" #include "tools/tool.h" #include "ui_context.h" +#include "util/misc.h" #include "widgets/color_bar.h" #include "widgets/editor/drawing_state.h" #include "widgets/editor/editor.h" @@ -43,6 +44,7 @@ #include "widgets/editor/handle_type.h" #include "widgets/editor/moving_cel_state.h" #include "widgets/editor/moving_pixels_state.h" +#include "widgets/editor/pixels_movement.h" #include "widgets/editor/scrolling_state.h" #include "widgets/editor/tool_loop_impl.h" #include "widgets/editor/transform_handles.h" @@ -176,7 +178,7 @@ bool StandbyState::onMouseDown(Editor* editor, Message* msg) } // Change to MovingPixelsState - editor->setState(EditorStatePtr(new MovingPixelsState(editor, msg, image, x, y, opacity, handle))); + transformSelection(editor, msg, handle); } return true; } @@ -195,7 +197,7 @@ bool StandbyState::onMouseDown(Editor* editor, Message* msg) } // Change to MovingPixelsState - editor->setState(EditorStatePtr(new MovingPixelsState(editor, msg, image, x, y, opacity, NoHandle))); + transformSelection(editor, msg, MoveHandle); } return true; } @@ -467,6 +469,27 @@ gfx::Transformation StandbyState::getTransformation(Editor* editor) return editor->getDocument()->getTransformation(); } +void StandbyState::transformSelection(Editor* editor, Message* msg, HandleType handle) +{ + EditorCustomizationDelegate* customization = editor->getCustomizationDelegate(); + Document* document = editor->getDocument(); + UniquePtr tmpImage(NewImageFromMask(document)); + int x = document->getMask()->x; + int y = document->getMask()->y; + int opacity = 255; + Sprite* sprite = editor->getSprite(); + PixelsMovement* pixelsMovement = new PixelsMovement(document, sprite, tmpImage, x, y, opacity, + "Transformation"); + + // If the Ctrl key is pressed start dragging a copy of the selection + if (customization && customization->isCopySelectionKeyPressed()) + pixelsMovement->copyMask(); + else + pixelsMovement->cutMask(); + + editor->setState(EditorStatePtr(new MovingPixelsState(editor, msg, pixelsMovement, handle))); +} + ////////////////////////////////////////////////////////////////////// // Decorator diff --git a/src/widgets/editor/standby_state.h b/src/widgets/editor/standby_state.h index a4bb834e5..fefa41517 100644 --- a/src/widgets/editor/standby_state.h +++ b/src/widgets/editor/standby_state.h @@ -23,6 +23,7 @@ #include "gfx/transformation.h" #include "widgets/editor/editor_decorator.h" #include "widgets/editor/editor_state.h" +#include "widgets/editor/handle_type.h" class TransformHandles; @@ -68,6 +69,8 @@ protected: }; private: + void transformSelection(Editor* editor, Message* msg, HandleType handle); + Decorator* m_decorator; };