[aseprite] 86/128: Use clip library to copy & paste images/custom data
Tobias Hansen
thansen at moszumanska.debian.org
Mon May 9 21:24:26 UTC 2016
This is an automated email from the git hooks/post-receive script.
thansen pushed a commit to branch master
in repository aseprite.
commit c99a1872569fb272d1e8158d7582a76ac413ed49
Author: David Capello <davidcapello at gmail.com>
Date: Fri Apr 29 20:42:05 2016 -0300
Use clip library to copy & paste images/custom data
With this change we finally support copy & paste images into the OS X
pasteboard. (Fix #925, fix #533, fix #172.)
---
src/app/CMakeLists.txt | 1 +
src/app/util/clipboard.cpp | 89 ++++----
src/app/util/clipboard_native.cpp | 296 +++++++++++++++++++++++++
src/app/util/clipboard_native.h | 36 ++++
src/app/util/clipboard_win32.h | 442 --------------------------------------
src/clip | 2 +-
6 files changed, 383 insertions(+), 483 deletions(-)
diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt
index 04eea0a..6aecda9 100644
--- a/src/app/CMakeLists.txt
+++ b/src/app/CMakeLists.txt
@@ -421,6 +421,7 @@ add_library(app-lib
ui_context.cpp
util/autocrop.cpp
util/clipboard.cpp
+ util/clipboard_native.cpp
util/create_cel_copy.cpp
util/expand_cel_canvas.cpp
util/filetoks.cpp
diff --git a/src/app/util/clipboard.cpp b/src/app/util/clipboard.cpp
index 993cd35..c9e9746 100644
--- a/src/app/util/clipboard.cpp
+++ b/src/app/util/clipboard.cpp
@@ -28,21 +28,12 @@
#include "app/ui/timeline.h"
#include "app/ui_context.h"
#include "app/util/clipboard.h"
+#include "app/util/clipboard_native.h"
#include "app/util/new_image_from_mask.h"
#include "base/shared_ptr.h"
#include "doc/doc.h"
#include "render/quantization.h"
-#ifdef _WIN32
- #define USE_NATIVE_WIN32_CLIPBOARD
-#endif
-
-#ifdef USE_NATIVE_WIN32_CLIPBOARD
- #include <windows.h>
-
- #include "app/util/clipboard_win32.h"
-#endif
-
#include <stdexcept>
namespace app {
@@ -112,6 +103,8 @@ ClipboardManager::ClipboardManager()
ASSERT(!g_instance);
g_instance = this;
+ register_native_clipboard_formats();
+
clipboard_range.observeUIContext();
}
@@ -134,18 +127,31 @@ ClipboardManager* ClipboardManager::instance()
return g_instance;
}
-static void set_clipboard_image(Image* image, Mask* mask, Palette* palette, bool set_system_clipboard)
+static void set_clipboard_image(Image* image,
+ Mask* mask,
+ Palette* palette,
+ bool set_system_clipboard,
+ bool image_source_is_transparent)
{
clipboard_palette.reset(palette);
clipboard_picks.clear();
clipboard_image.reset(image);
clipboard_mask.reset(mask);
- // copy to the Windows clipboard
-#ifdef USE_NATIVE_WIN32_CLIPBOARD
- if (set_system_clipboard)
- set_win32_clipboard_bitmap(image, mask, palette);
-#endif
+ // Copy image to the native clipboard
+ if (set_system_clipboard) {
+ color_t oldMask;
+ if (image) {
+ oldMask = image->maskColor();
+ if (!image_source_is_transparent)
+ image->setMaskColor(-1);
+ }
+
+ set_native_clipboard_bitmap(image, mask, palette);
+
+ if (image && !image_source_is_transparent)
+ image->setMaskColor(oldMask);
+ }
clipboard_range.invalidate();
}
@@ -164,20 +170,22 @@ static bool copy_from_document(const Site& site)
const Mask* mask = document->mask();
const Palette* pal = document->sprite()->palette(site.frame());
- set_clipboard_image(image,
- (mask ? new Mask(*mask): nullptr),
- (pal ? new Palette(*pal): nullptr), true);
+ set_clipboard_image(
+ image,
+ (mask ? new Mask(*mask): nullptr),
+ (pal ? new Palette(*pal): nullptr),
+ true,
+ site.layer() && !site.layer()->isBackground());
+
return true;
}
ClipboardFormat get_current_format()
{
-#ifdef USE_NATIVE_WIN32_CLIPBOARD
- if (win32_clipboard_contains_bitmap())
+ // Check if the native clipboard has an image
+ if (has_native_clipboard_bitmap())
return ClipboardImage;
-#endif
-
- if (clipboard_image)
+ else if (clipboard_image)
return ClipboardImage;
else if (clipboard_range.valid())
return ClipboardDocumentRange;
@@ -200,7 +208,7 @@ void get_document_range_info(Document** document, DocumentRange* range)
void clear_content()
{
- set_clipboard_image(nullptr, nullptr, nullptr, true);
+ set_clipboard_image(nullptr, nullptr, nullptr, true, false);
}
void cut(ContextWriter& writer)
@@ -255,7 +263,8 @@ void copy_image(const Image* image, const Mask* mask, const Palette* pal)
set_clipboard_image(
Image::createCopy(image),
(mask ? new Mask(*mask): nullptr),
- (pal ? new Palette(*pal): nullptr), true);
+ (pal ? new Palette(*pal): nullptr),
+ true, false);
}
void copy_palette(const Palette* palette, const doc::PalettePicks& picks)
@@ -265,7 +274,8 @@ void copy_palette(const Palette* palette, const doc::PalettePicks& picks)
set_clipboard_image(nullptr,
nullptr,
- new Palette(*palette), true);
+ new Palette(*palette),
+ true, false);
clipboard_picks = picks;
}
@@ -281,17 +291,16 @@ void paste()
switch (get_current_format()) {
case clipboard::ClipboardImage: {
-#ifdef USE_NATIVE_WIN32_CLIPBOARD
// 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_mask, win32_palette);
- if (win32_image)
- set_clipboard_image(win32_image, win32_mask, win32_palette, false);
+ Image* native_image = nullptr;
+ Mask* native_mask = nullptr;
+ Palette* native_palette = nullptr;
+ get_native_clipboard_bitmap(&native_image, &native_mask, &native_palette);
+ if (native_image)
+ set_clipboard_image(native_image, native_mask, native_palette,
+ false, false);
}
-#endif
if (!clipboard_image)
return;
@@ -509,18 +518,18 @@ void paste()
bool get_image_size(gfx::Size& size)
{
-#ifdef USE_NATIVE_WIN32_CLIPBOARD
- // Get the image from the clipboard.
- return get_win32_clipboard_bitmap_size(size);
+#if defined(_WIN32) || defined(__APPLE__)
+ if (get_native_clipboard_bitmap_size(&size))
+ return true;
#else
if (clipboard_image) {
size.w = clipboard_image->width();
size.h = clipboard_image->height();
return true;
}
- else
- return false;
#endif
+
+ return false;
}
Palette* get_palette()
diff --git a/src/app/util/clipboard_native.cpp b/src/app/util/clipboard_native.cpp
new file mode 100644
index 0000000..dcdf6f5
--- /dev/null
+++ b/src/app/util/clipboard_native.cpp
@@ -0,0 +1,296 @@
+// 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/util/clipboard_native.h"
+
+#include "base/serialization.h"
+#include "base/unique_ptr.h"
+#include "clip/clip.h"
+#include "doc/color_scales.h"
+#include "doc/image.h"
+#include "doc/image_impl.h"
+#include "doc/image_io.h"
+#include "doc/mask_io.h"
+#include "doc/palette_io.h"
+#include "gfx/size.h"
+#include "she/display.h"
+#include "she/system.h"
+#include "ui/alert.h"
+
+#include <sstream>
+#include <vector>
+
+namespace app {
+namespace clipboard {
+
+using namespace base::serialization;
+using namespace base::serialization::little_endian;
+
+namespace {
+ clip::format custom_image_format = 0;
+
+ void* native_display_handle() {
+ return she::instance()->defaultDisplay()->nativeHandle();
+ }
+
+ void custom_error_handler(clip::ErrorCode code) {
+ switch (code) {
+ case clip::ErrorCode::CannotLock:
+ ui::Alert::show("Error<<Cannot access to the clipboard.\nMaybe other application is using it.||&OK");
+ break;
+ case clip::ErrorCode::ImageNotSupported:
+ ui::Alert::show("Error<<The current clipboard image format is not supported.||&OK");
+ break;
+ }
+ }
+
+}
+
+void register_native_clipboard_formats()
+{
+ clip::set_error_handler(custom_error_handler);
+ custom_image_format = clip::register_format("org.aseprite.Image");
+}
+
+bool has_native_clipboard_bitmap()
+{
+ return clip::has(clip::image_format());
+}
+
+bool set_native_clipboard_bitmap(const doc::Image* image,
+ const doc::Mask* mask,
+ const doc::Palette* palette)
+{
+ clip::lock l(native_display_handle());
+ if (!l.locked())
+ return false;
+
+ l.clear();
+
+ if (!image)
+ return false;
+
+ // Set custom clipboard formats
+ if (custom_image_format) {
+ 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);
+
+ if (os.good()) {
+ size_t size = (size_t)os.tellp();
+ if (size > 0) {
+ std::vector<char> data(size);
+ os.seekp(0);
+ os.read(&data[0], size);
+
+ l.set_data(custom_image_format, &data[0], size);
+ }
+ }
+ }
+
+ clip::image_spec spec;
+ spec.width = image->width();
+ spec.height = image->height();
+ spec.bits_per_pixel = 32;
+ spec.bytes_per_row = (image->pixelFormat() == doc::IMAGE_RGB ?
+ image->getRowStrideSize(): 4*spec.width);
+ spec.red_mask = doc::rgba_r_mask;
+ spec.green_mask = doc::rgba_g_mask;
+ spec.blue_mask = doc::rgba_b_mask;
+ spec.alpha_mask = doc::rgba_a_mask;
+ spec.red_shift = doc::rgba_r_shift;
+ spec.green_shift = doc::rgba_g_shift;
+ spec.blue_shift = doc::rgba_b_shift;
+ spec.alpha_shift = doc::rgba_a_shift;
+
+ switch (image->pixelFormat()) {
+ case doc::IMAGE_RGB: {
+ // We use the RGB image data directly
+ clip::image img(image->getPixelAddress(0, 0), spec);
+ l.set_image(img);
+ break;
+ }
+ case doc::IMAGE_GRAYSCALE: {
+ clip::image img(spec);
+ const doc::LockImageBits<doc::GrayscaleTraits> bits(image);
+ auto it = bits.begin();
+ uint32_t* dst = (uint32_t*)img.data();
+ for (int y=0; y<image->height(); ++y) {
+ for (int x=0; x<image->width(); ++x, ++it) {
+ doc::color_t c = *it;
+ *(dst++) = doc::rgba(doc::graya_getv(c),
+ doc::graya_getv(c),
+ doc::graya_getv(c),
+ doc::graya_geta(c));
+ }
+ }
+ l.set_image(img);
+ break;
+ }
+ case doc::IMAGE_INDEXED: {
+ clip::image img(spec);
+ const doc::LockImageBits<doc::IndexedTraits> bits(image);
+ auto it = bits.begin();
+ uint32_t* dst = (uint32_t*)img.data();
+ for (int y=0; y<image->height(); ++y) {
+ for (int x=0; x<image->width(); ++x, ++it) {
+ doc::color_t c = palette->getEntry(*it);
+
+ // Use alpha=0 for mask color
+ if (*it == image->maskColor())
+ c &= doc::rgba_rgb_mask;
+
+ *(dst++) = c;
+ }
+ }
+ l.set_image(img);
+ break;
+ }
+ }
+
+ return true;
+}
+
+bool get_native_clipboard_bitmap(doc::Image** image,
+ doc::Mask** mask,
+ doc::Palette** palette)
+{
+ *image = nullptr;
+ *mask = nullptr;
+ *palette = nullptr;
+
+ clip::lock l(native_display_handle());
+ if (!l.locked())
+ return false;
+
+ // Prefer the custom format (to avoid losing mask and palette)
+ if (l.is_convertible(custom_image_format)) {
+ size_t size = l.get_data_length(custom_image_format);
+ if (size > 0) {
+ std::vector<char> buf(size);
+ if (l.get_data(custom_image_format, &buf[0], size)) {
+ std::stringstream is;
+ is.write(&buf[0], size);
+ is.seekp(0);
+
+ 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);
+ if (image)
+ return true;
+ }
+ }
+ }
+
+ if (!l.is_convertible(clip::image_format()))
+ return false;
+
+ clip::image img;
+ if (!l.get_image(img))
+ return false;
+
+ const clip::image_spec& spec = img.spec();
+
+ base::UniquePtr<doc::Image> dst(
+ doc::Image::create(doc::IMAGE_RGB,
+ spec.width, spec.height));
+
+ switch (spec.bits_per_pixel) {
+ case 64: {
+ doc::LockImageBits<doc::RgbTraits> bits(dst.get(), doc::Image::WriteLock);
+ auto it = bits.begin();
+ for (unsigned long y=0; y<spec.height; ++y) {
+ const uint64_t* src = (const uint64_t*)(img.data()+spec.bytes_per_row*y);
+ for (unsigned long x=0; x<spec.width; ++x, ++it, ++src) {
+ uint64_t c = *((const uint64_t*)src);
+ *it = doc::rgba(
+ uint8_t((c & spec.red_mask) >> spec.red_shift >> 8),
+ uint8_t((c & spec.green_mask) >> spec.green_shift >> 8),
+ uint8_t((c & spec.blue_mask) >> spec.blue_shift >> 8),
+ uint8_t((c & spec.alpha_mask) >> spec.alpha_shift >> 8));
+ }
+ }
+ break;
+ }
+ case 32: {
+ doc::LockImageBits<doc::RgbTraits> bits(dst.get(), doc::Image::WriteLock);
+ auto it = bits.begin();
+ for (unsigned long y=0; y<spec.height; ++y) {
+ const uint32_t* src = (const uint32_t*)(img.data()+spec.bytes_per_row*y);
+ for (unsigned long x=0; x<spec.width; ++x, ++it, ++src) {
+ const uint32_t c = *((const uint32_t*)src);
+ *it = doc::rgba(
+ uint8_t((c & spec.red_mask ) >> spec.red_shift ),
+ uint8_t((c & spec.green_mask) >> spec.green_shift),
+ uint8_t((c & spec.blue_mask ) >> spec.blue_shift ),
+ uint8_t((c & spec.alpha_mask) >> spec.alpha_shift));
+ }
+ }
+ break;
+ }
+ case 24: {
+ doc::LockImageBits<doc::RgbTraits> bits(dst.get(), doc::Image::WriteLock);
+ auto it = bits.begin();
+ for (unsigned long y=0; y<spec.height; ++y) {
+ const char* src = (const char*)(img.data()+spec.bytes_per_row*y);
+ for (unsigned long x=0; x<spec.width; ++x, ++it, src+=3) {
+ unsigned long c = *((const unsigned long*)src);
+ *it = doc::rgba(
+ uint8_t((c & spec.red_mask) >> spec.red_shift),
+ uint8_t((c & spec.green_mask) >> spec.green_shift),
+ uint8_t((c & spec.blue_mask) >> spec.blue_shift),
+ 255);
+ }
+ }
+ break;
+ }
+ case 16: {
+ doc::LockImageBits<doc::RgbTraits> bits(dst.get(), doc::Image::WriteLock);
+ auto it = bits.begin();
+ for (unsigned long y=0; y<spec.height; ++y) {
+ const uint16_t* src = (const uint16_t*)(img.data()+spec.bytes_per_row*y);
+ for (unsigned long x=0; x<spec.width; ++x, ++it, ++src) {
+ const uint16_t c = *((const uint16_t*)src);
+ *it = doc::rgba(
+ doc::scale_5bits_to_8bits((c & spec.red_mask ) >> spec.red_shift ),
+ doc::scale_6bits_to_8bits((c & spec.green_mask) >> spec.green_shift),
+ doc::scale_5bits_to_8bits((c & spec.blue_mask ) >> spec.blue_shift ),
+ 255);
+ }
+ }
+ break;
+ }
+ }
+
+ *image = dst.release();
+ return true;
+}
+
+bool get_native_clipboard_bitmap_size(gfx::Size* size)
+{
+ clip::image_spec spec;
+ if (clip::get_image_spec(spec)) {
+ size->w = spec.width;
+ size->h = spec.height;
+ return true;
+ }
+ else
+ return false;
+}
+
+} // namespace clipboard
+} // namespace app
diff --git a/src/app/util/clipboard_native.h b/src/app/util/clipboard_native.h
new file mode 100644
index 0000000..f4eabef
--- /dev/null
+++ b/src/app/util/clipboard_native.h
@@ -0,0 +1,36 @@
+// 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.
+
+#ifndef APP_UTIL_CLIPBOARD_NATIVE_H_INCLUDED
+#define APP_UTIL_CLIPBOARD_NATIVE_H_INCLUDED
+#pragma once
+
+#include "gfx/fwd.h"
+
+namespace doc {
+ class Image;
+ class Mask;
+ class Palette;
+}
+
+namespace app {
+namespace clipboard {
+
+void register_native_clipboard_formats();
+bool has_native_clipboard_bitmap();
+bool set_native_clipboard_bitmap(const doc::Image* image,
+ const doc::Mask* mask,
+ const doc::Palette* palette);
+bool get_native_clipboard_bitmap(doc::Image** image,
+ doc::Mask** mask,
+ doc::Palette** palette);
+bool get_native_clipboard_bitmap_size(gfx::Size* size);
+
+} // namespace clipboard
+} // namespace app
+
+#endif
diff --git a/src/app/util/clipboard_win32.h b/src/app/util/clipboard_win32.h
deleted file mode 100644
index 5d007c5..0000000
--- a/src/app/util/clipboard_win32.h
+++ /dev/null
@@ -1,442 +0,0 @@
-// Aseprite
-// 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
-// published by the Free Software Foundation.
-
-// 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"
-
-#ifndef LCS_WINDOWS_COLOR_SPACE
-#define LCS_WINDOWS_COLOR_SPACE 'Win '
-#endif
-
-#ifndef CF_DIBV5
-#define CF_DIBV5 17
-#endif
-
-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)
-{
- uint32_t shift = 0;
- for (shift=0; shift<32; ++shift)
- if (mask & (1 << shift))
- return shift;
- return shift;
-}
-
-bool win32_open_clipboard(HWND hwnd)
-{
- if (!custom_clipboard_format) {
- custom_clipboard_format = RegisterClipboardFormat(L"Aseprite.Image.1");
- if (!custom_clipboard_format)
- LOG("Error registering custom clipboard format: %d\n", GetLastError());
- }
-
- for (int i=0; i<5; ++i) {
- if (OpenClipboard(hwnd))
- return true;
-
- Sleep(100);
- }
- return false;
-}
-
-/**
- * Returns true if the Windows clipboard contains a bitmap (CF_DIB
- * format).
- */
-static bool win32_clipboard_contains_bitmap()
-{
- return IsClipboardFormatAvailable(CF_DIB) ? true: false;
-}
-
-/**
- * Changes the Windows clipboard content to the specified image. The
- * palette is optional and only used if the image is IMAGE_INDEXED type.
- */
-static void set_win32_clipboard_bitmap(const Image* image, const Mask* mask, Palette* palette)
-{
- HWND hwnd = static_cast<HWND>(she::instance()->defaultDisplay()->nativeHandle());
- if (!win32_open_clipboard(hwnd))
- return;
-
- if (!EmptyClipboard()) {
- CloseClipboard();
- return;
- }
-
- if (!image) {
- CloseClipboard();
- return;
- }
-
- // Set custom clipboard formats
- if (custom_clipboard_format) {
- 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);
-
- if (os.good()) {
- size_t size = (size_t)os.tellp();
- HGLOBAL hmem = GlobalAlloc(GHND, size+4);
- if (hmem) {
- char* p = (char*)GlobalLock(hmem);
- if (p) {
- *((uint32_t*)p) = size;
- os.seekp(0);
- os.read(p+4, size);
- }
- GlobalUnlock(hmem);
- if (p)
- SetClipboardData(custom_clipboard_format, hmem);
- GlobalFree(hmem);
- }
- }
- }
-
- // information to create the memory necessary for the bitmap
- int padding = 0;
- int scanline = 0;
- int color_depth = 0;
- int palette_entries = 0;
-
- switch (image->pixelFormat()) {
- case IMAGE_RGB:
- scanline = sizeof(uint32_t) * image->width();
- color_depth = 32;
- break;
- case IMAGE_GRAYSCALE:
- // this is right! Grayscaled is copied as RGBA in Win32 Clipboard
- scanline = sizeof(uint32_t) * image->width();
- color_depth = 32;
- break;
- case IMAGE_INDEXED:
- ASSERT(palette);
- padding = (4-(image->width()&3))&3;
- scanline = sizeof(uint8_t) * image->width();
- scanline += padding;
- color_depth = 8;
- palette_entries = palette->size();
- break;
- }
- ASSERT(scanline > 0 && color_depth > 0);
-
- // create the BITMAPV5HEADER structure
- HGLOBAL hmem = GlobalAlloc(GHND,
- sizeof(BITMAPV5HEADER)
- + palette_entries*sizeof(RGBQUAD)
- + scanline*image->height());
- if (!hmem) {
- // TODO cannot copy exception
- CloseClipboard();
- return;
- }
-
- BITMAPV5HEADER* bi = (BITMAPV5HEADER*)GlobalLock(hmem);
-
- bi->bV5Size = sizeof(BITMAPV5HEADER);
- bi->bV5Width = image->width();
- bi->bV5Height = image->height();
- bi->bV5Planes = 1;
- bi->bV5BitCount = color_depth;
- bi->bV5Compression = BI_RGB;
- bi->bV5SizeImage = scanline*image->height();
- bi->bV5RedMask = 0x00ff0000;
- bi->bV5GreenMask = 0x0000ff00;
- bi->bV5BlueMask = 0x000000ff;
- bi->bV5AlphaMask = 0xff000000;
- bi->bV5CSType = LCS_WINDOWS_COLOR_SPACE;
- bi->bV5Intent = LCS_GM_GRAPHICS;
- bi->bV5ClrUsed = palette_entries == 256 ? 0: palette_entries;
-
- // write pixels
- switch (image->pixelFormat()) {
- case IMAGE_RGB: {
- uint32_t* dst = (uint32_t*)(((uint8_t*)bi)+bi->bV5Size);
- uint32_t c;
- for (int y=image->height()-1; y>=0; --y)
- for (int x=0; x<image->width(); ++x) {
- c = get_pixel_fast<RgbTraits>(image, x, y);
- *(dst++) = ((rgba_getb(c) << 0) |
- (rgba_getg(c) << 8) |
- (rgba_getr(c) << 16) |
- (rgba_geta(c) << 24));
- }
- break;
- }
- case IMAGE_GRAYSCALE: {
- uint32_t* dst = (uint32_t*)(((uint8_t*)bi)+bi->bV5Size);
- uint16_t c;
- for (int y=image->height()-1; y>=0; --y)
- for (int x=0; x<image->width(); ++x) {
- c = get_pixel_fast<GrayscaleTraits>(image, x, y);
- *(dst++) = ((graya_getv(c) << 0) |
- (graya_getv(c) << 8) |
- (graya_getv(c) << 16) |
- (graya_geta(c) << 24));
- }
- break;
- }
- case IMAGE_INDEXED: {
- ASSERT(palette);
- RGBQUAD* rgbquad = (RGBQUAD*)(((uint8_t*)bi)+bi->bV5Size);
- for (int i=0; i<palette->size(); ++i) {
- rgbquad->rgbRed = rgba_getr(palette->getEntry(i));
- rgbquad->rgbGreen = rgba_getg(palette->getEntry(i));
- rgbquad->rgbBlue = rgba_getb(palette->getEntry(i));
- rgbquad++;
- }
-
- uint8_t* dst = (uint8_t*)(((uint8_t*)bi)+bi->bV5Size
- + palette_entries*sizeof(RGBQUAD));
- for (int y=image->height()-1; y>=0; --y) {
- for (int x=0; x<image->width(); ++x) {
- *(dst++) = get_pixel_fast<IndexedTraits>(image, x, y);
- }
- dst += padding;
- }
- break;
- }
- }
-
- GlobalUnlock(hmem);
- SetClipboardData(CF_DIBV5, hmem);
- CloseClipboard();
-
- GlobalFree(hmem);
-}
-
-/**
- * Creates an Image from the current Windows Clipboard content.
- */
-static void get_win32_clipboard_bitmap(Image*& image, Mask*& mask, Palette*& palette)
-{
- image = nullptr;
- mask = nullptr;
- palette = nullptr;
-
- if (!win32_clipboard_contains_bitmap())
- return;
-
- HWND hwnd = static_cast<HWND>(she::instance()->defaultDisplay()->nativeHandle());
- if (!win32_open_clipboard(hwnd))
- return;
-
- // Prefer the custom format (to avoid losing data)
- if (custom_clipboard_format &&
- 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 &&
- bi->bmiHeader.biCompression != BI_BITFIELDS) {
- ui::Alert::show("Error<<The current Windows clipboard format is not a bitmap.||&OK");
- return;
- }
-
- try {
- image = Image::create(bi->bmiHeader.biBitCount == 8 ? IMAGE_INDEXED:
- IMAGE_RGB,
- bi->bmiHeader.biWidth,
- ABS(bi->bmiHeader.biHeight));
-
- bool valid_image = false;
- switch (bi->bmiHeader.biBitCount) {
-
- // 32 BPP
- case 32:
- if (bi->bmiHeader.biCompression == BI_BITFIELDS) {
- uint32_t* src = (uint32_t*)(((uint8_t*)bi)+bi->bmiHeader.biSize+sizeof(RGBQUAD)*3);
- uint32_t c;
-
- uint32_t r_mask = (uint32_t)*((uint32_t*)&bi->bmiColors[0]);
- uint32_t g_mask = (uint32_t)*((uint32_t*)&bi->bmiColors[1]);
- uint32_t b_mask = (uint32_t)*((uint32_t*)&bi->bmiColors[2]);
- uint32_t r_shift = get_shift_from_mask(r_mask);
- uint32_t g_shift = get_shift_from_mask(g_mask);
- uint32_t b_shift = get_shift_from_mask(b_mask);
-
- for (int y=image->height()-1; y>=0; --y) {
- uint32_t* dst = (uint32_t*)image->getPixelAddress(0, y);
-
- 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);
- }
- }
- }
- else if (bi->bmiHeader.biCompression == BI_RGB) {
- uint32_t* src = (uint32_t*)(((uint8_t*)bi)+bi->bmiHeader.biSize);
- uint32_t c;
-
- for (int y=image->height()-1; y>=0; --y) {
- uint32_t* dst = (uint32_t*)image->getPixelAddress(0, y);
-
- for (int x=0; x<image->width(); ++x) {
- c = *(src++);
- *(dst++) = rgba((c & 0x00ff0000) >> 16,
- (c & 0x0000ff00) >> 8,
- (c & 0x000000ff) >> 0,
- (c & 0xff000000) >> 24);
- }
- }
- }
- valid_image = true;
- break;
-
- // 24 BPP
- case 24: {
- uint8_t* src = (((uint8_t*)bi)+bi->bmiHeader.biSize);
- uint8_t r, g, b;
- int padding = (4-((image->width()*3)&3))&3;
-
- for (int y=image->height()-1; y>=0; --y) {
- uint32_t* dst = (uint32_t*)image->getPixelAddress(0, y);
-
- for (int x=0; x<image->width(); ++x) {
- b = *(src++);
- g = *(src++);
- r = *(src++);
- *(dst++) = rgba(r, g, b, 255);
- }
- src += padding;
- }
- valid_image = true;
- break;
- }
-
- // 16 BPP
- case 16: {
- uint16_t* src = (uint16_t*)(((uint8_t*)bi)+bi->bmiHeader.biSize+sizeof(RGBQUAD)*3);
- uint16_t word;
- uint8_t r, g, b;
- int padding = ((4-((image->width()*2)&3))&3)/2;
-
- uint32_t r_mask = (uint32_t)*((uint32_t*)&bi->bmiColors[0]);
- uint32_t g_mask = (uint32_t)*((uint32_t*)&bi->bmiColors[1]);
- uint32_t b_mask = (uint32_t)*((uint32_t*)&bi->bmiColors[2]);
- uint32_t r_shift = get_shift_from_mask(r_mask);
- uint32_t g_shift = get_shift_from_mask(g_mask);
- uint32_t b_shift = get_shift_from_mask(b_mask);
-
- for (int y=image->height()-1; y>=0; --y) {
- for (int x=0; x<image->width(); ++x) {
- word = *(src++);
- r = scale_5bits_to_8bits((word & r_mask) >> r_shift);
- g = scale_6bits_to_8bits((word & g_mask) >> g_shift);
- b = scale_5bits_to_8bits((word & b_mask) >> b_shift);
- put_pixel_fast<RgbTraits>(image, x, y, rgba(r, g, b, 255));
- }
- src += padding;
- }
- valid_image = true;
- break;
- }
-
- // 8 BPP
- case 8: {
- int colors = bi->bmiHeader.biClrUsed > 0 ? bi->bmiHeader.biClrUsed: 256;
- palette = new Palette(frame_t(0), colors);
- for (int c=0; c<colors; ++c) {
- palette->setEntry(c, rgba(bi->bmiColors[c].rgbRed,
- bi->bmiColors[c].rgbGreen,
- bi->bmiColors[c].rgbBlue, 255));
- }
-
- uint8_t* src = (((uint8_t*)bi)+bi->bmiHeader.biSize+sizeof(RGBQUAD)*colors);
- int padding = (4-(image->width()&3))&3;
-
- for (int y=image->height()-1; y>=0; --y) {
- for (int x=0; x<image->width(); ++x) {
- int c = *(src++);
- put_pixel_fast<IndexedTraits>(image, x, y, MID(0, c, colors-1));
- }
-
- src += padding;
- }
-
- valid_image = true;
- break;
- }
-
- }
-
- if (!valid_image) {
- delete image;
- delete palette;
- image = NULL;
- palette = NULL;
- }
- }
- catch (...) {
- delete image;
- delete palette;
- image = NULL;
- palette = NULL;
- }
- }
-
- CloseClipboard();
-}
-
-static bool get_win32_clipboard_bitmap_size(gfx::Size& size)
-{
- bool result = false;
-
- HWND hwnd = static_cast<HWND>(she::instance()->defaultDisplay()->nativeHandle());
-
- if (win32_clipboard_contains_bitmap() && win32_open_clipboard(hwnd)) {
- BITMAPINFO* bi = (BITMAPINFO*)GetClipboardData(CF_DIB);
- if (bi) {
- size.w = bi->bmiHeader.biWidth;
- size.h = ABS(bi->bmiHeader.biHeight);
- result = true;
- }
- CloseClipboard();
- }
- return result;
-}
-
-}
diff --git a/src/clip b/src/clip
index e57130a..5ef7852 160000
--- a/src/clip
+++ b/src/clip
@@ -1 +1 @@
-Subproject commit e57130a56659d001d7bc33081c7cb3abe0621be2
+Subproject commit 5ef7852ae4d297aa5ab14ad5e5728e1f0c2e50bd
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/aseprite.git
More information about the Pkg-games-commits
mailing list