mirror of
https://github.com/aseprite/aseprite.git
synced 2025-01-05 21:57:20 +00:00
Add custom clipboard format on Win32 to copy/paste image+mask+palette
This commit is contained in:
parent
c5f898e6a7
commit
ea09ada11b
@ -35,8 +35,7 @@
|
||||
#include "render/quantization.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
// TODO Re-enable native clipboard with custom format to save image+mask when possible
|
||||
//#define USE_NATIVE_WIN32_CLIPBOARD
|
||||
#define USE_NATIVE_WIN32_CLIPBOARD
|
||||
#endif
|
||||
|
||||
#ifdef USE_NATIVE_WIN32_CLIPBOARD
|
||||
@ -252,17 +251,28 @@ void clipboard::paste()
|
||||
// Get the image from the clipboard.
|
||||
{
|
||||
Image* win32_image = NULL;
|
||||
Mask* win32_mask = NULL;
|
||||
Palette* win32_palette = NULL;
|
||||
get_win32_clipboard_bitmap(win32_image, win32_palette);
|
||||
if (win32_image != NULL)
|
||||
set_clipboard_image(win32_image, win32_palette, false);
|
||||
get_win32_clipboard_bitmap(win32_image, win32_mask, win32_palette);
|
||||
if (win32_image)
|
||||
set_clipboard_image(win32_image, win32_mask, win32_palette, false);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!clipboard_image ||
|
||||
!clipboard_mask)
|
||||
if (!clipboard_image)
|
||||
return;
|
||||
|
||||
if (!clipboard_mask) {
|
||||
gfx::Rect visibleBounds = editor->getVisibleSpriteBounds();
|
||||
gfx::Rect imageBounds = clipboard_image->bounds();
|
||||
|
||||
clipboard_mask.reset(new Mask);
|
||||
clipboard_mask->replace(
|
||||
gfx::Rect(visibleBounds.x + visibleBounds.w/2 - imageBounds.w/2,
|
||||
visibleBounds.y + visibleBounds.h/2 - imageBounds.h/2,
|
||||
imageBounds.w, imageBounds.h));
|
||||
}
|
||||
|
||||
Palette* dst_palette = dstSpr->palette(editor->frame());
|
||||
|
||||
// Source image (clipboard or a converted copy to the destination 'imgtype')
|
||||
|
@ -7,7 +7,11 @@
|
||||
|
||||
// included by clipboard.cpp
|
||||
|
||||
#include "base/serialization.h"
|
||||
#include "doc/color_scales.h"
|
||||
#include "doc/image_io.h"
|
||||
#include "doc/mask_io.h"
|
||||
#include "doc/palette_io.h"
|
||||
#include "she/display.h"
|
||||
#include "she/system.h"
|
||||
#include "ui/alert.h"
|
||||
@ -23,6 +27,10 @@
|
||||
namespace {
|
||||
|
||||
using namespace doc;
|
||||
using namespace base::serialization;
|
||||
using namespace base::serialization::little_endian;
|
||||
|
||||
static UINT custom_clipboard_format = 0;
|
||||
|
||||
static uint32_t get_shift_from_mask(uint32_t mask)
|
||||
{
|
||||
@ -35,6 +43,9 @@ static uint32_t get_shift_from_mask(uint32_t mask)
|
||||
|
||||
bool win32_open_clipboard(HWND hwnd)
|
||||
{
|
||||
if (!custom_clipboard_format)
|
||||
custom_clipboard_format = RegisterClipboardFormat(L"Aseprite.Image.1");
|
||||
|
||||
for (int i=0; i<5; ++i) {
|
||||
if (OpenClipboard(hwnd))
|
||||
return true;
|
||||
@ -73,6 +84,31 @@ static void set_win32_clipboard_bitmap(const Image* image, const Mask* mask, Pal
|
||||
return;
|
||||
}
|
||||
|
||||
// Set custom clipboard formats
|
||||
{
|
||||
std::stringstream os;
|
||||
write32(os,
|
||||
(image ? 1: 0) |
|
||||
(mask ? 2: 0) |
|
||||
(palette ? 4: 0));
|
||||
if (image) doc::write_image(os, image);
|
||||
if (mask) doc::write_mask(os, mask);
|
||||
if (palette) doc::write_palette(os, palette);
|
||||
|
||||
size_t size = (size_t)os.tellp();
|
||||
|
||||
HGLOBAL hmem = GlobalAlloc(GHND, size+4);
|
||||
char* p = (char*)GlobalLock(hmem);
|
||||
|
||||
*((uint32_t*)p) = size;
|
||||
os.seekp(0);
|
||||
os.read(p+4, size);
|
||||
|
||||
GlobalUnlock(hmem);
|
||||
SetClipboardData(custom_clipboard_format, hmem);
|
||||
GlobalFree(hmem);
|
||||
}
|
||||
|
||||
// information to create the memory necessary for the bitmap
|
||||
int padding = 0;
|
||||
int scanline = 0;
|
||||
@ -182,10 +218,11 @@ static void set_win32_clipboard_bitmap(const Image* image, const Mask* mask, Pal
|
||||
/**
|
||||
* Creates an Image from the current Windows Clipboard content.
|
||||
*/
|
||||
static void get_win32_clipboard_bitmap(Image*& image, Palette*& palette)
|
||||
static void get_win32_clipboard_bitmap(Image*& image, Mask*& mask, Palette*& palette)
|
||||
{
|
||||
image = NULL;
|
||||
palette = NULL;
|
||||
image = nullptr;
|
||||
mask = nullptr;
|
||||
palette = nullptr;
|
||||
|
||||
if (!win32_clipboard_contains_bitmap())
|
||||
return;
|
||||
@ -194,6 +231,27 @@ static void get_win32_clipboard_bitmap(Image*& image, Palette*& palette)
|
||||
if (!win32_open_clipboard(hwnd))
|
||||
return;
|
||||
|
||||
// Prefer the custom format (to avoid losing data)
|
||||
if (IsClipboardFormatAvailable(custom_clipboard_format)) {
|
||||
const char* ptr = (const char*)GetClipboardData(custom_clipboard_format);
|
||||
if (ptr) {
|
||||
size_t size = *((uint32_t*)ptr);
|
||||
if (size > 0) {
|
||||
std::stringstream is;
|
||||
is.write(ptr+4, size);
|
||||
|
||||
int bits = read32(is);
|
||||
if (bits & 1) image = doc::read_image(is, false);
|
||||
if (bits & 2) mask = doc::read_mask(is);
|
||||
if (bits & 4) palette = doc::read_palette(is);
|
||||
}
|
||||
|
||||
CloseClipboard();
|
||||
if (image)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
BITMAPINFO* bi = (BITMAPINFO*)GetClipboardData(CF_DIB);
|
||||
if (bi) {
|
||||
if (bi->bmiHeader.biCompression != BI_RGB &&
|
||||
@ -230,8 +288,8 @@ static void get_win32_clipboard_bitmap(Image*& image, Palette*& palette)
|
||||
for (int x=0; x<image->width(); ++x) {
|
||||
c = *(src++);
|
||||
*(dst++) = rgba((c & r_mask) >> r_shift,
|
||||
(c & g_mask) >> g_shift,
|
||||
(c & b_mask) >> b_shift, 255);
|
||||
(c & g_mask) >> g_shift,
|
||||
(c & b_mask) >> b_shift, 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -245,9 +303,9 @@ static void get_win32_clipboard_bitmap(Image*& image, Palette*& palette)
|
||||
for (int x=0; x<image->width(); ++x) {
|
||||
c = *(src++);
|
||||
*(dst++) = rgba((c & 0x00ff0000) >> 16,
|
||||
(c & 0x0000ff00) >> 8,
|
||||
(c & 0x000000ff) >> 0,
|
||||
(c & 0xff000000) >> 24);
|
||||
(c & 0x0000ff00) >> 8,
|
||||
(c & 0x000000ff) >> 0,
|
||||
(c & 0xff000000) >> 24);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user