Added support to copy & paste to/from the Windows Clipboard.

This commit is contained in:
David Capello 2009-03-07 19:14:40 +00:00
parent cb6b45bb3f
commit 73d1920e78
19 changed files with 488 additions and 196 deletions

View File

@ -2,9 +2,10 @@
NEWS
===================================
0.7
---
0.6.2
-----
+ Copy & Paste use Windows clipboard (feature #2577954).
+ Added "Save Copy As" command (feature #2636076).
+ Fixed compilation support for gcc 64 bits.
+ Fixed a bug with multiple editors and paste command.

View File

@ -24,7 +24,7 @@
/* general information */
#define PACKAGE "ASE"
#define VERSION "0.6.1"
#define VERSION "0.6.2"
#define WEBSITE "http://www.aseprite.org/"
#define COPYRIGHT "Copyright (C) 2001-2009 David Capello"

View File

@ -188,7 +188,7 @@ COMMON_SOURCES = \
src/util/autocrop.cpp \
src/util/boundary.cpp \
src/util/celmove.cpp \
src/util/clipbrd.cpp \
src/util/clipboard.cpp \
src/util/col_file.cpp \
src/util/filetoks.cpp \
src/util/functions.cpp \

View File

@ -1,7 +1,7 @@
#! /bin/sh
dir="`pwd`"
version=0.6.1
version=0.6.2
distdir=ase-$version
freetype_files="third_party/freetype/ChangeLog \

View File

@ -25,7 +25,7 @@
#include "raster/layer.h"
#include "raster/mask.h"
#include "raster/sprite.h"
#include "util/clipbrd.h"
#include "util/clipboard.h"
#include "util/misc.h"
static bool cmd_copy_enabled(const char *argument)
@ -43,7 +43,7 @@ static bool cmd_copy_enabled(const char *argument)
static void cmd_copy_execute(const char *argument)
{
copy_to_clipboard();
clipboard::copy(current_sprite);
}
Command cmd_copy = {

View File

@ -25,7 +25,7 @@
#include "raster/layer.h"
#include "raster/mask.h"
#include "raster/sprite.h"
#include "util/clipbrd.h"
#include "util/clipboard.h"
#include "util/misc.h"
static bool cmd_cut_enabled(const char *argument)
@ -43,7 +43,7 @@ static bool cmd_cut_enabled(const char *argument)
static void cmd_cut_execute(const char *argument)
{
cut_to_clipboard();
clipboard::cut(current_sprite);
}
Command cmd_cut = {

View File

@ -28,13 +28,10 @@
static void cmd_exit_execute(const char *argument)
{
Sprite *sprite = get_first_sprite();
Sprite *clipboard = get_clipboard_sprite();
while (sprite) {
/* check if this sprite is modified */
if (sprite_is_modified(sprite) &&
(!clipboard || sprite->id != clipboard->id)) {
// check if this sprite is modified
if (sprite_is_modified(sprite)) {
if (jalert(_("Warning<<There are sprites with changes.<<Do you want quit anyway?||&Yes||&No")) != 1) {
return;
}

View File

@ -22,14 +22,13 @@
#include "modules/sprites.h"
#include "raster/sprite.h"
#include "raster/undo.h"
#include "util/clipbrd.h"
#include "util/clipboard.h"
static bool cmd_paste_enabled(const char *argument)
{
Sprite *sprite = current_sprite;
Sprite *clipboard = get_clipboard_sprite();
return (sprite && clipboard && (clipboard != sprite));
return (sprite && clipboard::can_paste());
}
static void cmd_paste_execute(const char *argument)
@ -37,7 +36,7 @@ static void cmd_paste_execute(const char *argument)
if (undo_is_enabled(current_sprite->undo))
undo_set_label(current_sprite->undo, "Paste");
paste_from_clipboard();
clipboard::paste(current_sprite);
}
Command cmd_paste = {

View File

@ -35,7 +35,7 @@
#include "raster/blend.h"
#include "raster/image.h"
#include "raster/sprite.h"
#include "util/clipbrd.h"
#include "util/clipboard.h"
#include "util/misc.h"
#include "widgets/colbar.h"
#include "widgets/colbut.h"
@ -137,8 +137,9 @@ void dialogs_draw_text()
/* render text */
image = render_text(f, text, color);
if (image) {
copy_image_to_clipboard(image);
paste_from_clipboard();
clipboard::copy_image(image, sprite_get_palette(current_sprite,
current_sprite->frame));
clipboard::paste(current_sprite);
}
else
console_printf(_("Error rendering text.\n"));

View File

@ -420,14 +420,13 @@ static int is_sprite_in_some_editor(Sprite *sprite)
*/
static Sprite *get_more_reliable_sprite()
{
Sprite *clipboard = get_clipboard_sprite();
Sprite *sprite;
JLink link;
JI_LIST_FOR_EACH(get_sprite_list(), link) {
sprite = reinterpret_cast<Sprite*>(link->data);
if ((sprite != clipboard) && !(is_sprite_in_some_editor(sprite)))
if (!(is_sprite_in_some_editor(sprite)))
return sprite;
}

View File

@ -846,6 +846,7 @@ static bool manager_msg_proc(JWidget widget, JMessage msg)
/* ok, so we can execute the command represented by the
pressed-key in the message... */
if (command_is_enabled(command, NULL)) {
// if a menu is open, close everything
command_execute(command, NULL);
return TRUE;
}

View File

@ -46,7 +46,6 @@
Sprite* current_sprite = NULL;
static JList sprites_list;
static Sprite* clipboard_sprite;
static ImageRef *images_ref_get_from_layer(Sprite* sprite, Layer *layer, int target, bool write);
static void layer_get_pos(Sprite* sprite, Layer *layer, int target, bool write, int **x, int **y, int *count);
@ -54,7 +53,6 @@ static void layer_get_pos(Sprite* sprite, Layer *layer, int target, bool write,
int init_module_sprites()
{
sprites_list = jlist_new();
clipboard_sprite = NULL;
current_sprite = NULL;
return 0;
}
@ -63,11 +61,6 @@ void exit_module_sprites()
{
JLink link;
if (clipboard_sprite) {
sprite_free(clipboard_sprite);
clipboard_sprite = NULL;
}
JI_LIST_FOR_EACH(sprites_list, link) {
sprite_free(reinterpret_cast<Sprite*>(link->data));
}
@ -98,29 +91,6 @@ Sprite* get_next_sprite(Sprite* sprite)
return NULL;
}
Sprite* get_clipboard_sprite()
{
return clipboard_sprite;
}
void set_clipboard_sprite(Sprite* sprite)
{
if (clipboard_sprite) {
if (current_sprite == clipboard_sprite)
set_current_sprite(sprite);
if (is_interactive())
replace_sprite_in_editors(clipboard_sprite, sprite);
sprite_free(clipboard_sprite);
}
clipboard_sprite = sprite;
if (is_interactive())
app_realloc_sprite_list();
}
/* adds the "sprite" in the list of sprites */
void sprite_mount(Sprite* sprite)
{
@ -143,10 +113,6 @@ void sprite_unmount(Sprite* sprite)
/* remove from the sprite's list */
jlist_remove(sprites_list, sprite);
/* remove from the clipboard pointer */
if (sprite == get_clipboard_sprite())
clipboard_sprite = NULL;
if (is_interactive()) {
/* remove this sprite from tabs */
tabs_remove_tab(app_get_tabsbar(), sprite);

View File

@ -43,9 +43,6 @@ JList get_sprite_list();
Sprite* get_first_sprite();
Sprite* get_next_sprite(Sprite* sprite);
Sprite* get_clipboard_sprite();
void set_clipboard_sprite(Sprite* sprite);
void sprite_mount(Sprite* sprite);
void sprite_unmount(Sprite* sprite);

View File

@ -18,7 +18,7 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Adapted to ASE by David Capello (2003-2009)
* See "LICENSE.txt" for more information.
* See "LEGAL.txt" for more information.
*/
#include "config.h"

View File

@ -18,6 +18,7 @@
#include "config.h"
#include <cassert>
#include <allegro.h>
#include <allegro/internal/aintern.h>
@ -35,16 +36,22 @@
#include "raster/cel.h"
#include "raster/image.h"
#include "raster/layer.h"
#include "raster/palette.h"
#include "raster/rotate.h"
#include "raster/sprite.h"
#include "raster/stock.h"
#include "raster/undoable.h"
#include "raster/undo.h"
#include "util/clipbrd.h"
#include "util/clipboard.h"
#include "util/misc.h"
#include "widgets/colbar.h"
#include "widgets/statebar.h"
#if defined ALLEGRO_WINDOWS
#include <winalleg.h>
#include "util/clipboard_win32.h"
#endif
#define SCALE_MODE 0
#define ROTATE_MODE 1
@ -69,11 +76,13 @@ enum {
ACTION_ROTATE_BR,
};
static bool interactive_transform(JWidget widget,
Image *dest_image, Image *image,
int x, int y,
int xout[4], int yout[4]);
static int low_copy();
static void destroy_clipboard(void* data);
static void set_clipboard(Image* image, Palette* palette, bool set_system_clipboard);
static bool copy_from_sprite(Sprite* sprite);
static ase_uint32 get_shift_from_mask(ase_uint32 mask);
static bool interactive_transform(JWidget widget, Image *dest_image, Image *image,
int x, int y, int xout[4], int yout[4]);
static void apply_rotation(int x1, int y1, int x2, int y2,
fixed angle, int cx, int cy,
int xout[4], int yout[4]);
@ -90,56 +99,75 @@ static void fill_in_vars(int *in_box,
static void update_status_bar(JWidget editor, Image *image,
int x1, int y1, int x2, int y2, fixed angle);
bool has_clipboard_image(int *w, int *h)
static bool first_time = true;
static Palette* clipboard_palette = NULL;
static Image* clipboard_image = NULL;
static void destroy_clipboard(void* data)
{
Sprite *clipboard = get_clipboard_sprite();
Image *image = NULL;
Cel *cel;
if (clipboard) {
cel = layer_get_cel(clipboard->layer, clipboard->frame);
if (cel)
image = stock_get_image(clipboard->stock, cel->image);
delete clipboard_palette;
delete clipboard_image;
}
if (image) {
if (w) *w = image->w;
if (h) *h = image->h;
return TRUE;
}
else {
if (w) *w = 0;
if (h) *h = 0;
return FALSE;
}
}
void copy_image_to_clipboard(Image *image)
static void set_clipboard(Image* image, Palette* palette, bool set_system_clipboard)
{
Sprite *sprite;
Image *dest;
sprite = sprite_new_with_layer(image->imgtype, image->w, image->h);
if (sprite) {
dest = GetImage2(sprite, NULL, NULL, NULL);
image_copy(dest, image, 0, 0);
sprite_set_palette(sprite, get_current_palette(), FALSE);
set_clipboard_sprite(sprite);
}
if (first_time) {
first_time = false;
app_add_hook(APP_EXIT, destroy_clipboard, NULL);
}
void cut_to_clipboard()
delete clipboard_palette;
delete clipboard_image;
clipboard_palette = palette;
clipboard_image = image;
// copy to the Windows clipboard
#ifdef ALLEGRO_WINDOWS
if (set_system_clipboard)
set_win32_clipboard_bitmap(image, palette);
#endif
}
static bool copy_from_sprite(Sprite* sprite)
{
if (current_sprite == NULL ||
current_sprite->layer == NULL)
return;
assert(sprite);
Image* image = NewImageFromMask(sprite);
if (!image)
return false;
if (!low_copy())
Palette* pal = sprite_get_palette(sprite, sprite->frame);
set_clipboard(image, pal ? palette_new_copy(pal): NULL, true);
return true;
}
static ase_uint32 get_shift_from_mask(ase_uint32 mask)
{
ase_uint32 shift = 0;
for (shift=0; shift<32; ++shift)
if (mask & (1 << shift))
return shift;
return shift;
}
bool clipboard::can_paste()
{
#ifdef ALLEGRO_WINDOWS
if (win32_clipboard_contains_bitmap())
return true;
#endif
return clipboard_image != NULL;
}
void clipboard::cut(Sprite* sprite)
{
assert(sprite != NULL);
assert(sprite->layer != NULL);
if (!copy_from_sprite(sprite))
console_printf("Can't copying an image portion from the current layer\n");
else {
Sprite* sprite = current_sprite;
{
Undoable undoable(sprite, "Cut");
undoable.clear_mask(app_get_color_to_clear_layer(sprite->layer));
@ -149,55 +177,63 @@ void cut_to_clipboard()
}
}
void copy_to_clipboard()
void clipboard::copy(Sprite* sprite)
{
if (!current_sprite)
return;
assert(sprite != NULL);
if (!low_copy())
if (!copy_from_sprite(sprite))
console_printf(_("Can't copying an image portion from the current layer\n"));
}
void paste_from_clipboard()
void clipboard::copy_image(Image* image, Palette* pal)
{
set_clipboard(image_new_copy(image),
pal ? palette_new_copy(pal): NULL, true);
}
void clipboard::paste(Sprite* sprite)
{
Sprite *clipboard = get_clipboard_sprite();
Cel *cel;
Image *image;
Image *dest_image;
int xout[4], yout[4];
int dest_x, dest_y;
int dst_x, dst_y;
Image *src_image;
Image* dst_image;
bool paste;
if (!current_sprite ||
current_sprite == clipboard ||
!clipboard->layer ||
!is_interactive())
return;
if (clipboard->imgtype != current_sprite->imgtype) {
/* TODO now the user can't select the clipboard sprite */
console_printf(_("You can't copy sprites of different image types.\nYou should select the clipboard sprite, and change the image type of it.\n"));
return;
#ifdef ALLEGRO_WINDOWS
{
Image* win32_image = NULL;
Palette* win32_palette = NULL;
get_win32_clipboard_bitmap(win32_image, win32_palette);
if (win32_image != NULL)
set_clipboard(win32_image, win32_palette, false);
}
cel = layer_get_cel(clipboard->layer, clipboard->frame);
if (!cel) {
console_printf(_("Error: No cel in the clipboard\n"));
#endif
if (clipboard_image == NULL)
return;
}
image = stock_get_image(clipboard->stock, cel->image);
if (!image) {
console_printf(_("Error: No image in the clipboard\n"));
return;
}
assert(sprite != NULL);
dest_image = GetImage2(current_sprite, &dest_x, &dest_y, NULL);
if (!dest_image) {
// destination image (where to put this image)
dst_image = GetImage2(sprite, &dst_x, &dst_y, NULL);
if (!dst_image) {
console_printf(_("Error: no destination image\n"));
return;
}
// source image (clipboard or a converted copy to the destination 'imgtype')
if (clipboard_image->imgtype == sprite->imgtype)
src_image = clipboard_image;
else {
src_image = image_new(sprite->imgtype,
clipboard_image->w,
clipboard_image->h);
use_current_sprite_rgb_map();
image_convert(src_image, clipboard_image);
restore_rgb_map();
}
// do the interactive-transform loop (where the user can move the floating image)
{
JWidget view = jwidget_get_view(current_editor);
JRect vp = jview_get_viewport_position(view);
@ -205,11 +241,11 @@ void paste_from_clipboard()
screen_to_editor(current_editor, vp->x1, vp->y1, &x1, &y1);
screen_to_editor(current_editor, vp->x2-1, vp->y2-1, &x2, &y2);
x = (x1+x2)/2-image->w/2;
y = (y1+y2)/2-image->h/2;
x = (x1+x2)/2-src_image->w/2;
y = (y1+y2)/2-src_image->h/2;
paste = interactive_transform(current_editor,
dest_image, image, x, y, xout, yout);
dst_image, src_image, x, y, xout, yout);
jrect_free(vp);
}
@ -219,32 +255,34 @@ void paste_from_clipboard()
/* align to the destination cel-position */
for (c=0; c<4; ++c) {
xout[c] -= dest_x;
yout[c] -= dest_y;
xout[c] -= dst_x;
yout[c] -= dst_y;
}
/* clip the box for the undo */
u1 = MAX(0, MIN(xout[0], MIN(xout[1], MIN(xout[2], xout[3]))));
v1 = MAX(0, MIN(yout[0], MIN(yout[1], MIN(yout[2], yout[3]))));
u2 = MIN(dest_image->w-1, MAX(xout[0], MAX(xout[1], MAX(xout[2], xout[3]))));
v2 = MIN(dest_image->h-1, MAX(yout[0], MAX(yout[1], MAX(yout[2], yout[3]))));
u2 = MIN(dst_image->w-1, MAX(xout[0], MAX(xout[1], MAX(xout[2], xout[3]))));
v2 = MIN(dst_image->h-1, MAX(yout[0], MAX(yout[1], MAX(yout[2], yout[3]))));
w = u2-u1+1;
h = v2-v1+1;
if (w >= 1 && h >= 1) {
/* undo region */
if (undo_is_enabled(current_sprite->undo))
undo_image(current_sprite->undo, dest_image, u1, v1, w, h);
if (undo_is_enabled(sprite->undo))
undo_image(sprite->undo, dst_image, u1, v1, w, h);
/* draw the transformed image */
image_parallelogram(dest_image, image,
image_parallelogram(dst_image, src_image,
xout[0], yout[0], xout[1], yout[1],
xout[2], yout[2], xout[3], yout[3]);
}
}
update_screen_for_sprite(current_sprite);
if (src_image != clipboard_image)
image_free(src_image);
update_screen_for_sprite(sprite);
}
/**********************************************************************/
@ -286,6 +324,7 @@ static bool interactive_transform(JWidget widget,
int done = DONE_NONE;
fixed angle = 0;
int cx, cy;
int mask_color;
hide_drawing_cursor(widget);
@ -305,6 +344,7 @@ static bool interactive_transform(JWidget widget,
/* generate the preview bitmap (for fast-blitting) */
preview = create_bitmap(image->w, image->h);
mask_color = bitmap_mask_color(preview);
image_to_allegro(image, preview, 0, 0);
switch (image->imgtype) {
@ -313,8 +353,8 @@ static bool interactive_transform(JWidget widget,
int x, y;
for (y=0; y<image->h; y++)
for (x=0; x<image->w; x++)
if (_rgba_geta(image_getpixel(image, x, y)) < 128)
putpixel(preview, x, y, bitmap_mask_color(preview));
if (_rgba_geta(image->method->getpixel(image, x, y)) < 128)
putpixel(preview, x, y, mask_color);
break;
}
@ -322,8 +362,17 @@ static bool interactive_transform(JWidget widget,
int x, y;
for (y=0; y<image->h; y++)
for (x=0; x<image->w; x++)
if (_graya_geta(image_getpixel(image, x, y)) < 128)
putpixel(preview, x, y, bitmap_mask_color(preview));
if (_graya_geta(image->method->getpixel(image, x, y)) < 128)
putpixel(preview, x, y, mask_color);
break;
}
case IMAGE_INDEXED: {
int x, y;
for (y=0; y<image->h; y++)
for (x=0; x<image->w; x++)
if (image->method->getpixel(image, x, y) == 0)
putpixel(preview, x, y, mask_color);
break;
}
}
@ -648,40 +697,6 @@ static bool interactive_transform(JWidget widget,
return done == DONE_PASTE;
}
static int low_copy()
{
Sprite *sprite;
Layer *layer;
sprite = sprite_new(current_sprite->imgtype,
current_sprite->w,
current_sprite->h);
if (!sprite)
return FALSE;
/* set the current frame */
sprite_set_frame(sprite, current_sprite->frame);
/* create a new layer from the current mask (in the current
frame) */
layer = NewLayerFromMask(current_sprite, sprite);
if (!layer) {
sprite_free(sprite);
return FALSE;
}
layer_add_layer(sprite->set, layer);
sprite_set_layer(sprite, layer);
sprite_set_palette(sprite,
sprite_get_palette(current_sprite,
current_sprite->frame), 0);
set_clipboard_sprite(sprite);
return TRUE;
}
static void apply_rotation(int x1, int y1, int x2, int y2,
fixed angle, int cx, int cy,
int xout[4], int yout[4])

View File

@ -23,13 +23,16 @@
class Image;
bool has_clipboard_image(int *w, int *h);
namespace clipboard {
void copy_image_to_clipboard(Image* image);
bool can_paste();
void cut_to_clipboard();
void copy_to_clipboard();
void paste_from_clipboard();
void cut(Sprite* sprite);
void copy(Sprite* sprite);
void copy_image(Image* image, Palette* palette);
void paste(Sprite* sprite);
} // namespace clipboard
#endif /* UTIL_CLIPBRD_H */

268
src/util/clipboard_win32.h Normal file
View File

@ -0,0 +1,268 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2009 David Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
// included by clipboard.cpp
/**
* Returns true if the Windows clipboard contains a bitmap (CF_DIB
* format).
*/
static bool win32_clipboard_contains_bitmap()
{
return IsClipboardFormatAvailable(CF_DIB);
}
/**
* 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(Image* image, Palette* palette)
{
if (!OpenClipboard(win_get_window()))
return;
if (!EmptyClipboard()) {
CloseClipboard();
return;
}
// 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->imgtype) {
case IMAGE_RGB:
scanline = sizeof(ase_uint32) * image->w;
color_depth = 32;
break;
case IMAGE_GRAYSCALE:
// this is right! Grayscaled is copied as RGBA in Win32 Clipboard
scanline = sizeof(ase_uint32) * image->w;
color_depth = 32;
break;
case IMAGE_INDEXED:
padding = (4-(image->w&3))&3;
scanline = sizeof(ase_uint8) * image->w;
scanline += padding;
color_depth = 8;
palette_entries = palette->ncolors;
break;
}
assert(scanline > 0 && color_depth > 0);
// create the BITMAPV5HEADER structure
HGLOBAL hmem = GlobalAlloc(GHND,
sizeof(BITMAPV5HEADER)
+ palette_entries*sizeof(RGBQUAD)
+ scanline*image->h);
BITMAPV5HEADER* bi = (BITMAPV5HEADER*)GlobalLock(hmem);
bi->bV5Size = sizeof(BITMAPV5HEADER);
bi->bV5Width = image->w;
bi->bV5Height = image->h;
bi->bV5Planes = 1;
bi->bV5BitCount = color_depth;
bi->bV5Compression = BI_RGB;
bi->bV5SizeImage = scanline*image->h;
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->imgtype) {
case IMAGE_RGB: {
ase_uint32* dst = (ase_uint32*)(((ase_uint8*)bi)+bi->bV5Size);
ase_uint32 c;
for (int y=image->h-1; y>=0; --y)
for (int x=0; x<image->w; ++x) {
c = image->method->getpixel(image, x, y);
*(dst++) = ((_rgba_getb(c) << 0) |
(_rgba_getg(c) << 8) |
(_rgba_getr(c) << 16) |
(_rgba_geta(c) << 24));
}
break;
}
case IMAGE_GRAYSCALE: {
ase_uint32* dst = (ase_uint32*)(((ase_uint8*)bi)+bi->bV5Size);
ase_uint16 c;
for (int y=image->h-1; y>=0; --y)
for (int x=0; x<image->w; ++x) {
c = image->method->getpixel(image, x, y);
*(dst++) = ((_graya_getv(c) << 0) |
(_graya_getv(c) << 8) |
(_graya_getv(c) << 16) |
(_graya_geta(c) << 24));
}
break;
}
case IMAGE_INDEXED: {
Palette* palette = get_current_palette();
RGBQUAD* rgbquad = (RGBQUAD*)(((ase_uint8*)bi)+bi->bV5Size);
for (int i=0; i<palette->ncolors; ++i) {
rgbquad->rgbRed = _rgba_getr(palette->color[i]);
rgbquad->rgbGreen = _rgba_getg(palette->color[i]);
rgbquad->rgbBlue = _rgba_getb(palette->color[i]);
rgbquad++;
}
ase_uint8* dst = (ase_uint8*)(((ase_uint8*)bi)+bi->bV5Size
+ palette_entries*sizeof(RGBQUAD));
for (int y=image->h-1; y>=0; --y) {
for (int x=0; x<image->w; ++x) {
*(dst++) = image->method->getpixel(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, Palette*& palette)
{
image = NULL;
palette = NULL;
if (!win32_clipboard_contains_bitmap())
return;
if (!OpenClipboard(win_get_window()))
return;
BITMAPINFO* bi = (BITMAPINFO*)GetClipboardData(CF_DIB);
if (bi && bi->bmiHeader.biCompression == BI_RGB) {
try {
image = image_new(bi->bmiHeader.biBitCount == 8 ? IMAGE_INDEXED:
IMAGE_RGB,
bi->bmiHeader.biWidth,
ABS(bi->bmiHeader.biHeight));
bool valid_image = false;
switch (bi->bmiHeader.biBitCount) {
case 32: {
// BITMAPV5HEADER* bv5 = (BITMAPV5HEADER*)GetClipboardData(CF_DIBV5);
// ase_uint32* src = (ase_uint32*)(((ase_uint8*)bv5)+bv5->bV5Size);
ase_uint32* src = (ase_uint32*)(((ase_uint8*)bi)+bi->bmiHeader.biSize);
ase_uint32 c;
// int r_shift = get_shift_from_mask(bv5->bV5RedMask);
// int g_shift = get_shift_from_mask(bv5->bV5GreenMask);
// int b_shift = get_shift_from_mask(bv5->bV5BlueMask);
// int a_shift = get_shift_from_mask(bv5->bV5AlphaMask);
for (int y=image->h-1; y>=0; --y) {
for (int x=0; x<image->w; ++x) {
c = *(src++);
// image->method->putpixel(image, x, y,
// _rgba((c & bv5->bV5RedMask) >> r_shift,
// (c & bv5->bV5GreenMask) >> g_shift,
// (c & bv5->bV5BlueMask) >> b_shift,
// (c & bv5->bV5AlphaMask) >> a_shift));
image->method->putpixel(image, x, y,
_rgba((c & 0x00ff0000) >> 16,
(c & 0x0000ff00) >> 8,
(c & 0x000000ff) >> 0,
(c & 0xff000000) >> 24));
}
}
valid_image = true;
break;
}
case 24: {
ase_uint8* src = (((ase_uint8*)bi)+bi->bmiHeader.biSize);
ase_uint8 r, g, b;
int padding = (4-(image->w*3)&3)&3;
for (int y=image->h-1; y>=0; --y) {
for (int x=0; x<image->w; ++x) {
b = *(src++);
g = *(src++);
r = *(src++);
image->method->putpixel(image, x, y, _rgba(r, g, b, 255));
}
src += padding;
}
valid_image = true;
break;
}
case 16: {
// TODO
break;
}
case 8: {
int colors = bi->bmiHeader.biClrUsed > 0 ? bi->bmiHeader.biClrUsed: 256;
palette = palette_new(0, 256);
for (int c=0; c<256; ++c) {
int alpha = (c == 0) ? 0: 255;
if (c < colors) {
palette->color[c] = _rgba(bi->bmiColors[c].rgbRed,
bi->bmiColors[c].rgbGreen,
bi->bmiColors[c].rgbBlue, alpha);
}
else {
palette->color[c] = _rgba(0, 0, 0, alpha);
}
}
ase_uint8* src = (((ase_uint8*)bi)+bi->bmiHeader.biSize+sizeof(RGBQUAD)*colors);
int padding = (4-(image->w&3))&3;
for (int y=image->h-1; y>=0; --y) {
for (int x=0; x<image->w; ++x)
image->method->putpixel(image, x, y, *(src++) & 0xff);
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();
}

View File

@ -174,6 +174,50 @@ Layer *NewLayerFromMask(Sprite *src_sprite, Sprite *dst_sprite)
return layer;
}
Image* NewImageFromMask(Sprite* src_sprite)
{
ase_uint8 *address;
int x, y, u, v, getx, gety;
Image *dst, *src = GetImage2(src_sprite, &x, &y, NULL);
div_t d;
assert(src_sprite);
assert(src_sprite->mask);
assert(src_sprite->mask->bitmap);
assert(src);
dst = image_new(src_sprite->imgtype,
src_sprite->mask->w,
src_sprite->mask->h);
if (!dst)
return NULL;
/* clear the new image */
image_clear(dst, 0);
/* copy the masked zones */
for (v=0; v<src_sprite->mask->h; v++) {
d = div(0, 8);
address = ((ase_uint8 **)src_sprite->mask->bitmap->line)[v]+d.quot;
for (u=0; u<src_sprite->mask->w; u++) {
if ((*address & (1<<d.rem))) {
getx = u+src_sprite->mask->x-x;
gety = v+src_sprite->mask->y-y;
if ((getx >= 0) && (getx < src->w) &&
(gety >= 0) && (gety < src->h))
dst->method->putpixel(dst, u, v,
src->method->getpixel(src, getx, gety));
}
_image_bitmap_next_bit(d, address);
}
}
return dst;
}
Image *GetLayerImage(Layer *layer, int *x, int *y, int frame)
{
Image *image = NULL;

View File

@ -34,6 +34,7 @@ Image* GetImage2(Sprite* sprite, int *x, int *y, int *opacity);
void LoadPalette(const char* filename);
Layer* NewLayerFromMask(Sprite* src, Sprite* dst);
Image* NewImageFromMask(Sprite* src);
Image* GetLayerImage(Layer* layer, int *x, int *y, int frame);