RotateCanvasJob(const ContextReader& reader, int angle) : Job("Rotate Canvas") , m_writer(reader) , m_document(m_writer.document()) , m_sprite(m_writer.sprite()) { m_angle = angle; }
SpriteSizeJob(const ContextReader& reader, int new_width, int new_height, ResizeMethod resize_method) : Job("Sprite Size") , m_writer(reader) , m_document(m_writer.document()) , m_sprite(m_writer.sprite()) { m_new_width = new_width; m_new_height = new_height; m_resize_method = resize_method; }
RotateJob(const ContextReader& reader, int angle, const CelList& cels, bool rotateSprite) : Job("Rotate Canvas") , m_writer(reader) , m_document(m_writer.document()) , m_sprite(m_writer.sprite()) , m_cels(cels) , m_rotateSprite(rotateSprite) { m_angle = angle; }
void move_cel(ContextWriter& writer) { Document* document = writer.document(); Sprite* sprite = writer.sprite(); Cel *src_cel, *dst_cel; ASSERT(src_layer != NULL); ASSERT(dst_layer != NULL); ASSERT(src_frame >= 0 && src_frame < sprite->getTotalFrames()); ASSERT(dst_frame >= 0 && dst_frame < sprite->getTotalFrames()); if (src_layer->isBackground()) { copy_cel(writer); return; } src_cel = static_cast<LayerImage*>(src_layer)->getCel(src_frame); dst_cel = static_cast<LayerImage*>(dst_layer)->getCel(dst_frame); UndoTransaction undo(writer.context(), "Move Cel", undo::ModifyDocument); /* remove the 'dst_cel' (if it exists) because it must be replaced with 'src_cel' */ if ((dst_cel != NULL) && (!dst_layer->isBackground() || src_cel != NULL)) remove_cel(sprite, undo, static_cast<LayerImage*>(dst_layer), dst_cel); /* move the cel in the same layer */ if (src_cel != NULL) { if (src_layer == dst_layer) { if (undo.isEnabled()) undo.pushUndoer(new undoers::SetCelFrame(undo.getObjects(), src_cel)); src_cel->setFrame(dst_frame); } /* move the cel in different layers */ else { if (undo.isEnabled()) undo.pushUndoer(new undoers::RemoveCel(undo.getObjects(), src_layer, src_cel)); static_cast<LayerImage*>(src_layer)->removeCel(src_cel); src_cel->setFrame(dst_frame); /* if we are moving a cel from a transparent layer to the background layer, we have to clear the background of the image */ if (!src_layer->isBackground() && dst_layer->isBackground()) { Image *src_image = sprite->getStock()->getImage(src_cel->getImage()); Image *dst_image = image_crop(src_image, -src_cel->getX(), -src_cel->getY(), sprite->getWidth(), sprite->getHeight(), 0); if (undo.isEnabled()) { undo.pushUndoer(new undoers::ReplaceImage(undo.getObjects(), sprite->getStock(), src_cel->getImage())); undo.pushUndoer(new undoers::SetCelPosition(undo.getObjects(), src_cel)); undo.pushUndoer(new undoers::SetCelOpacity(undo.getObjects(), src_cel)); } image_clear(dst_image, app_get_color_to_clear_layer(dst_layer)); image_merge(dst_image, src_image, src_cel->getX(), src_cel->getY(), 255, BLEND_MODE_NORMAL); src_cel->setPosition(0, 0); src_cel->setOpacity(255); sprite->getStock()->replaceImage(src_cel->getImage(), dst_image); image_free(src_image); } if (undo.isEnabled()) undo.pushUndoer(new undoers::AddCel(undo.getObjects(), dst_layer, src_cel)); static_cast<LayerImage*>(dst_layer)->addCel(src_cel); } } undo.commit(); document->notifyCelMoved(src_layer, src_frame, dst_layer, dst_frame); set_frame_to_handle(NULL, FrameNumber(0), NULL, FrameNumber(0)); }
void copy_cel(ContextWriter& writer) { Document* document = writer.document(); Sprite* sprite = writer.sprite(); UndoTransaction undo(writer.context(), "Move Cel", undo::ModifyDocument); Cel *src_cel, *dst_cel; ASSERT(src_layer != NULL); ASSERT(dst_layer != NULL); ASSERT(src_frame >= 0 && src_frame < sprite->getTotalFrames()); ASSERT(dst_frame >= 0 && dst_frame < sprite->getTotalFrames()); src_cel = static_cast<LayerImage*>(src_layer)->getCel(src_frame); dst_cel = static_cast<LayerImage*>(dst_layer)->getCel(dst_frame); // Remove the 'dst_cel' (if it exists) because it must be replaced // with 'src_cel' if ((dst_cel != NULL) && (!dst_layer->isBackground() || src_cel != NULL)) remove_cel(sprite, undo, static_cast<LayerImage*>(dst_layer), dst_cel); // Move the cel in the same layer. if (src_cel != NULL) { Image *src_image = sprite->getStock()->getImage(src_cel->getImage()); Image *dst_image; int image_index; int dst_cel_x; int dst_cel_y; int dst_cel_opacity; // If we are moving a cel from a transparent layer to the // background layer, we have to clear the background of the image. if (!src_layer->isBackground() && dst_layer->isBackground()) { dst_image = image_crop(src_image, -src_cel->getX(), -src_cel->getY(), sprite->getWidth(), sprite->getHeight(), 0); image_clear(dst_image, app_get_color_to_clear_layer(dst_layer)); image_merge(dst_image, src_image, src_cel->getX(), src_cel->getY(), 255, BLEND_MODE_NORMAL); dst_cel_x = 0; dst_cel_y = 0; dst_cel_opacity = 255; } else { dst_image = Image::createCopy(src_image); dst_cel_x = src_cel->getX(); dst_cel_y = src_cel->getY(); dst_cel_opacity = src_cel->getOpacity(); } // Add the image in the stock image_index = sprite->getStock()->addImage(dst_image); if (undo.isEnabled()) undo.pushUndoer(new undoers::AddImage(undo.getObjects(), sprite->getStock(), image_index)); // Create the new cel dst_cel = new Cel(dst_frame, image_index); dst_cel->setPosition(dst_cel_x, dst_cel_y); dst_cel->setOpacity(dst_cel_opacity); if (undo.isEnabled()) undo.pushUndoer(new undoers::AddCel(undo.getObjects(), dst_layer, dst_cel)); static_cast<LayerImage*>(dst_layer)->addCel(dst_cel); } undo.commit(); document->notifyCelCopied(src_layer, src_frame, dst_layer, dst_frame); set_frame_to_handle(NULL, FrameNumber(0), NULL, FrameNumber(0)); }
void clipboard::cut(ContextWriter& writer) { ASSERT(writer.document() != NULL); ASSERT(writer.sprite() != NULL); ASSERT(writer.layer() != NULL); if (!copy_from_document(*writer.location())) { Console console; console.printf("Can't copying an image portion from the current layer\n"); } else { { UndoTransaction undoTransaction(writer.context(), "Cut"); DocumentApi api(writer.document()->getApi()); api.clearMask(writer.layer(), writer.cel(), app_get_color_to_clear_layer(writer.layer())); api.deselectMask(); undoTransaction.commit(); } writer.document()->generateMaskBoundaries(); update_screen_for_document(writer.document()); } }
/** * [working thread] */ virtual void onJob() { UndoTransaction undoTransaction(m_writer.context(), "Rotate Canvas"); DocumentApi api = m_document->getApi(); // get all sprite cels CelList cels; m_sprite->getCels(cels); // for each cel... for (CelIterator it = cels.begin(); it != cels.end(); ++it) { Cel* cel = *it; Image* image = m_sprite->getStock()->getImage(cel->getImage()); // change it location switch (m_angle) { case 180: api.setCelPosition(m_sprite, cel, m_sprite->getWidth() - cel->getX() - image->getWidth(), m_sprite->getHeight() - cel->getY() - image->getHeight()); break; case 90: api.setCelPosition(m_sprite, cel, m_sprite->getHeight() - cel->getY() - image->getHeight(), cel->getX()); break; case -90: api.setCelPosition(m_sprite, cel, cel->getY(), m_sprite->getWidth() - cel->getX() - image->getWidth()); break; } } // for each stock's image for (int i=0; i<m_sprite->getStock()->size(); ++i) { Image* image = m_sprite->getStock()->getImage(i); if (!image) continue; // rotate the image Image* new_image = Image::create(image->getPixelFormat(), m_angle == 180 ? image->getWidth(): image->getHeight(), m_angle == 180 ? image->getHeight(): image->getWidth()); raster::rotate_image(image, new_image, m_angle); api.replaceStockImage(m_sprite, i, new_image); jobProgress((float)i / m_sprite->getStock()->size()); // cancel all the operation? if (isCanceled()) return; // UndoTransaction destructor will undo all operations } // rotate mask if (m_document->isMaskVisible()) { Mask* origMask = m_document->getMask(); base::UniquePtr<Mask> new_mask(new Mask()); const gfx::Rect& origBounds = origMask->getBounds(); int x = 0, y = 0; switch (m_angle) { case 180: x = m_sprite->getWidth() - origBounds.x - origBounds.w; y = m_sprite->getHeight() - origBounds.y - origBounds.h; break; case 90: x = m_sprite->getHeight() - origBounds.y - origBounds.h; y = origBounds.x; break; case -90: x = origBounds.y; y = m_sprite->getWidth() - origBounds.x - origBounds.w; break; } // create the new rotated mask new_mask->replace(x, y, m_angle == 180 ? origBounds.w: origBounds.h, m_angle == 180 ? origBounds.h: origBounds.w); raster::rotate_image(origMask->getBitmap(), new_mask->getBitmap(), m_angle); // Copy new mask api.copyToCurrentMask(new_mask); // Regenerate mask m_document->resetTransformation(); m_document->generateMaskBoundaries(); } // change the sprite's size if (m_angle != 180) api.setSpriteSize(m_sprite, m_sprite->getHeight(), m_sprite->getWidth()); // commit changes undoTransaction.commit(); }
/** * [working thread] */ virtual void onJob() { UndoTransaction undoTransaction(m_writer.context(), "Sprite Size"); DocumentApi api = m_writer.document()->getApi(); // Get all sprite cels CelList cels; m_sprite->getCels(cels); // For each cel... int progress = 0; for (CelIterator it = cels.begin(); it != cels.end(); ++it, ++progress) { Cel* cel = *it; // Change its location api.setCelPosition(m_sprite, cel, scale_x(cel->x()), scale_y(cel->y())); // Get cel's image Image* image = cel->image(); if (!image) continue; // Resize the image int w = scale_x(image->width()); int h = scale_y(image->height()); Image* new_image = Image::create(image->pixelFormat(), MAX(1, w), MAX(1, h)); doc::algorithm::fixup_image_transparent_colors(image); doc::algorithm::resize_image(image, new_image, m_resize_method, m_sprite->getPalette(cel->frame()), m_sprite->getRgbMap(cel->frame())); api.replaceStockImage(m_sprite, cel->imageIndex(), new_image); jobProgress((float)progress / cels.size()); // cancel all the operation? if (isCanceled()) return; // UndoTransaction destructor will undo all operations } // Resize mask if (m_document->isMaskVisible()) { base::UniquePtr<Image> old_bitmap (crop_image(m_document->mask()->bitmap(), -1, -1, m_document->mask()->bitmap()->width()+2, m_document->mask()->bitmap()->height()+2, 0)); int w = scale_x(old_bitmap->width()); int h = scale_y(old_bitmap->height()); base::UniquePtr<Mask> new_mask(new Mask); new_mask->replace(scale_x(m_document->mask()->bounds().x-1), scale_y(m_document->mask()->bounds().y-1), MAX(1, w), MAX(1, h)); algorithm::resize_image(old_bitmap, new_mask->bitmap(), m_resize_method, m_sprite->getPalette(FrameNumber(0)), // Ignored m_sprite->getRgbMap(FrameNumber(0))); // Ignored // Reshrink new_mask->intersect(new_mask->bounds()); // Copy new mask api.copyToCurrentMask(new_mask); // Regenerate mask m_document->resetTransformation(); m_document->generateMaskBoundaries(); } // resize sprite api.setSpriteSize(m_sprite, m_new_width, m_new_height); // commit changes undoTransaction.commit(); }
// [working thread] virtual void onJob() { Transaction transaction(m_writer.context(), "Rotate Canvas"); DocumentApi api = m_document->getApi(transaction); // 1) Rotate cel positions for (Cel* cel : m_cels) { Image* image = cel->image(); if (!image) continue; switch (m_angle) { case 180: api.setCelPosition(m_sprite, cel, m_sprite->width() - cel->x() - image->width(), m_sprite->height() - cel->y() - image->height()); break; case 90: api.setCelPosition(m_sprite, cel, m_sprite->height() - cel->y() - image->height(), cel->x()); break; case -90: api.setCelPosition(m_sprite, cel, cel->y(), m_sprite->width() - cel->x() - image->width()); break; } } // 2) Rotate images int i = 0; for (Cel* cel : m_cels) { Image* image = cel->image(); if (image) { ImageRef new_image(Image::create(image->pixelFormat(), m_angle == 180 ? image->width(): image->height(), m_angle == 180 ? image->height(): image->width())); doc::rotate_image(image, new_image.get(), m_angle); api.replaceImage(m_sprite, cel->imageRef(), new_image); } jobProgress((float)i / m_cels.size()); ++i; // cancel all the operation? if (isCanceled()) return; // Transaction destructor will undo all operations } // rotate mask if (m_document->isMaskVisible()) { Mask* origMask = m_document->mask(); base::UniquePtr<Mask> new_mask(new Mask()); const gfx::Rect& origBounds = origMask->bounds(); int x = 0, y = 0; switch (m_angle) { case 180: x = m_sprite->width() - origBounds.x - origBounds.w; y = m_sprite->height() - origBounds.y - origBounds.h; break; case 90: x = m_sprite->height() - origBounds.y - origBounds.h; y = origBounds.x; break; case -90: x = origBounds.y; y = m_sprite->width() - origBounds.x - origBounds.w; break; } // create the new rotated mask new_mask->replace( gfx::Rect(x, y, m_angle == 180 ? origBounds.w: origBounds.h, m_angle == 180 ? origBounds.h: origBounds.w)); doc::rotate_image(origMask->bitmap(), new_mask->bitmap(), m_angle); // Copy new mask api.copyToCurrentMask(new_mask); // Regenerate mask m_document->resetTransformation(); m_document->generateMaskBoundaries(); } // change the sprite's size if (m_rotateSprite && m_angle != 180) api.setSpriteSize(m_sprite, m_sprite->height(), m_sprite->width()); // commit changes transaction.commit(); }