Add CopyMerged command (Ctrl+Shift+C) (fix #824)

This commit is contained in:
David Capello 2016-05-17 12:59:48 -03:00
parent fda9abce33
commit 0f3252a80b
8 changed files with 118 additions and 29 deletions

View File

@ -12,7 +12,7 @@
<key command="OpenFile" shortcut="Ctrl+O" mac="Cmd+O" />
<key command="SaveFile" shortcut="Ctrl+S" mac="Cmd+S" />
<key command="SaveFileAs" shortcut="Ctrl+Shift+S" mac="Cmd+Shift+S" />
<key command="SaveFileCopyAs" shortcut="Ctrl+Shift+C" mac="Cmd+Shift+C" />
<key command="SaveFileCopyAs" shortcut="Ctrl+Alt+Shift+S" mac="Cmd+Alt+Shift+S" />
<key command="CloseFile" shortcut="Ctrl+W" mac="Cmd+W" />
<key command="CloseAllFiles" shortcut="Ctrl+Shift+W" mac="Cmd+Shift+W" />
<key command="ImportSpriteSheet" shortcut="Ctrl+I" mac="Cmd+I" />
@ -35,6 +35,7 @@
<key command="Cut" shortcut="Shift+Del" />
<key command="Copy" shortcut="Ctrl+C" mac="Cmd+C" />
<key command="Copy" shortcut="Ctrl+Ins" mac="Cmd+Ins" />
<key command="CopyMerged" shortcut="Ctrl+Shift+C" mac="Cmd+Shift+C" />
<key command="Paste" shortcut="Ctrl+V" mac="Cmd+V" />
<key command="Paste" shortcut="Shift+Ins" />
<key command="Clear" shortcut="Del" />
@ -530,6 +531,7 @@
<separator />
<item command="Cut" text="Cu&amp;t" />
<item command="Copy" text="&amp;Copy" />
<item command="CopyMerged" text="Copy Mer&amp;ged" />
<item command="Paste" text="&amp;Paste" />
<item command="Clear" text="C&amp;lear" />
<separator />

View File

@ -180,6 +180,7 @@ add_library(app-lib
commands/cmd_color_quantization.cpp
commands/cmd_copy.cpp
commands/cmd_copy_cel.cpp
commands/cmd_copy_merged.cpp
commands/cmd_crop.cpp
commands/cmd_cut.cpp
commands/cmd_deselect_mask.cpp

View File

@ -0,0 +1,51 @@
// Aseprite
// Copyright (C) 2016 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "app/commands/command.h"
#include "app/context_access.h"
#include "app/util/clipboard.h"
namespace app {
class CopyMergedCommand : public Command {
public:
CopyMergedCommand();
Command* clone() const override { return new CopyMergedCommand(*this); }
protected:
bool onEnabled(Context* ctx) override;
void onExecute(Context* ctx) override;
};
CopyMergedCommand::CopyMergedCommand()
: Command("CopyMerged",
"Copy Merged",
CmdUIOnlyFlag)
{
}
bool CopyMergedCommand::onEnabled(Context* ctx)
{
return ctx->checkFlags(ContextFlags::ActiveDocumentIsReadable);
}
void CopyMergedCommand::onExecute(Context* ctx)
{
ContextReader reader(ctx);
clipboard::copy_merged(reader);
}
Command* CommandFactory::createCopyMergedCommand()
{
return new CopyMergedCommand;
}
} // namespace app

View File

@ -25,6 +25,7 @@ FOR_EACH_COMMAND(ColorQuantization)
FOR_EACH_COMMAND(ConvolutionMatrix)
FOR_EACH_COMMAND(Copy)
FOR_EACH_COMMAND(CopyCel)
FOR_EACH_COMMAND(CopyMerged)
FOR_EACH_COMMAND(CropSprite)
FOR_EACH_COMMAND(Cut)
FOR_EACH_COMMAND(DeselectMask)

View File

@ -157,20 +157,17 @@ static void set_clipboard_image(Image* image,
clipboard_range.invalidate();
}
static bool copy_from_document(const Site& site)
static bool copy_from_document(const Site& site, bool merged = false)
{
const app::Document* document = static_cast<const app::Document*>(site.document());
ASSERT(document);
ASSERT(document != NULL);
ASSERT(document->isMaskVisible());
Image* image = new_image_from_mask(site);
const Mask* mask = document->mask();
Image* image = new_image_from_mask(site, mask, merged);
if (!image)
return false;
const Mask* mask = document->mask();
const Palette* pal = document->sprite()->palette(site.frame());
set_clipboard_image(
image,
(mask ? new Mask(*mask): nullptr),
@ -250,6 +247,13 @@ void copy(const ContextReader& reader)
}
}
void copy_merged(const ContextReader& reader)
{
ASSERT(reader.document() != NULL);
copy_from_document(*reader.site(), true);
}
void copy_range(const ContextReader& reader, const DocumentRange& range)
{
ASSERT(reader.document() != NULL);

View File

@ -21,6 +21,7 @@ namespace doc {
}
namespace app {
class Document;
class ContextReader;
class ContextWriter;
class DocumentRange;
@ -51,6 +52,7 @@ namespace app {
void clear_content();
void cut(ContextWriter& context);
void copy(const ContextReader& context);
void copy_merged(const ContextReader& context);
void copy_range(const ContextReader& context, const DocumentRange& range);
void copy_image(const Image* image, const Mask* mask, const Palette* palette);
void copy_palette(const Palette* palette, const PalettePicks& picks);

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2015 David Capello
// Copyright (C) 2001-2016 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
@ -15,7 +15,9 @@
#include "base/unique_ptr.h"
#include "doc/image_impl.h"
#include "doc/mask.h"
#include "doc/primitives.h"
#include "doc/site.h"
#include "render/render.h"
namespace app {
@ -27,45 +29,69 @@ Image* new_image_from_mask(const Site& site)
return new_image_from_mask(site, srcMask);
}
doc::Image* new_image_from_mask(const doc::Site& site, const doc::Mask* srcMask)
doc::Image* new_image_from_mask(const doc::Site& site,
const doc::Mask* srcMask,
bool merged)
{
const Sprite* srcSprite = site.sprite();
const Image* srcMaskBitmap = srcMask->bitmap();
const gfx::Rect& srcBounds = srcMask->bounds();
const Image* srcMaskBitmap = (srcMask ? srcMask->bitmap(): nullptr);
gfx::Rect srcBounds = (srcMask ? srcMask->bounds(): srcSprite->bounds());
int x, y, u, v, getx, gety;
const Image *src = site.image(&x, &y);
ASSERT(srcSprite);
ASSERT(srcMask);
ASSERT(srcMaskBitmap);
base::UniquePtr<Image> dst(Image::create(srcSprite->pixelFormat(), srcBounds.w, srcBounds.h));
if (!dst)
return nullptr;
// Clear the new image
dst->setMaskColor(src ? src->maskColor(): srcSprite->transparentColor());
dst->setMaskColor(srcSprite->transparentColor());
clear_image(dst, dst->maskColor());
const Image* src = nullptr;
if (merged) {
render::Render render;
render.renderSprite(dst, srcSprite, site.frame(),
gfx::Clip(0, 0, srcBounds));
src = dst;
}
else {
src = site.image(&x, &y);
}
// Copy the masked zones
if (src) {
const LockImageBits<BitmapTraits> maskBits(srcMaskBitmap, gfx::Rect(0, 0, srcBounds.w, srcBounds.h));
LockImageBits<BitmapTraits>::const_iterator mask_it = maskBits.begin();
if (srcMaskBitmap) {
// Copy active layer with mask
const LockImageBits<BitmapTraits> maskBits(srcMaskBitmap, gfx::Rect(0, 0, srcBounds.w, srcBounds.h));
LockImageBits<BitmapTraits>::const_iterator mask_it = maskBits.begin();
for (v=0; v<srcBounds.h; ++v) {
for (u=0; u<srcBounds.w; ++u, ++mask_it) {
ASSERT(mask_it != maskBits.end());
for (v=0; v<srcBounds.h; ++v) {
for (u=0; u<srcBounds.w; ++u, ++mask_it) {
ASSERT(mask_it != maskBits.end());
if (*mask_it) {
getx = u+srcBounds.x-x;
gety = v+srcBounds.y-y;
if (src != dst) {
if (*mask_it) {
getx = u+srcBounds.x-x;
gety = v+srcBounds.y-y;
if ((getx >= 0) && (getx < src->width()) &&
(gety >= 0) && (gety < src->height()))
dst->putPixel(u, v, src->getPixel(getx, gety));
if ((getx >= 0) && (getx < src->width()) &&
(gety >= 0) && (gety < src->height()))
dst->putPixel(u, v, src->getPixel(getx, gety));
}
}
else {
if (!*mask_it) {
dst->putPixel(u, v, dst->maskColor());
}
}
}
}
}
else if (src != dst) {
copy_image(dst, src, -srcBounds.x, -srcBounds.y);
}
}
return dst.release();

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2015 David Capello
// Copyright (C) 2001-2016 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
@ -18,7 +18,9 @@ namespace doc {
namespace app {
doc::Image* new_image_from_mask(const doc::Site& site);
doc::Image* new_image_from_mask(const doc::Site& site, const doc::Mask* mask);
doc::Image* new_image_from_mask(const doc::Site& site,
const doc::Mask* mask,
bool merged = false);
} // namespace app