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 <[email protected]> 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 _______________________________________________ Pkg-games-commits mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-games-commits

