mirror of
https://github.com/aseprite/aseprite.git
synced 2025-02-05 18:40:37 +00:00
Added support to copy & paste to/from the Windows Clipboard.
This commit is contained in:
parent
cb6b45bb3f
commit
73d1920e78
5
NEWS.txt
5
NEWS.txt
@ -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.
|
||||
|
2
config.h
2
config.h
@ -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"
|
||||
|
||||
|
@ -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 \
|
||||
|
@ -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 \
|
||||
|
@ -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 = {
|
||||
|
@ -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 = {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 = {
|
||||
|
@ -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"));
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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]);
|
||||
@ -87,59 +96,78 @@ static void fill_in_vars(int *in_box,
|
||||
int *in_top, int *in_middle, int *in_bottom,
|
||||
int x1, int y1, int x2, int y2, fixed angle,
|
||||
int cx, int cy);
|
||||
static void update_status_bar(JWidget editor, Image *image,
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
delete clipboard_palette;
|
||||
delete clipboard_image;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
void cut_to_clipboard()
|
||||
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,39 +255,41 @@ 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);
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
/* interactive transform */
|
||||
|
||||
enum { DONE_NONE, DONE_CANCEL, DONE_PASTE };
|
||||
|
||||
|
||||
static bool interactive_transform(JWidget widget,
|
||||
Image *dest_image, Image *image,
|
||||
int x, int y,
|
||||
@ -282,10 +320,11 @@ static bool interactive_transform(JWidget widget,
|
||||
int action = ACTION_SETMODE;
|
||||
int mode = SCALE_MODE;
|
||||
BITMAP *bmp1, *bmp2, *preview, *old_screen;
|
||||
JRect vp = jview_get_viewport_position (jwidget_get_view (widget));
|
||||
JRect vp = jview_get_viewport_position(jwidget_get_view(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;
|
||||
}
|
||||
}
|
||||
@ -588,7 +637,7 @@ static bool interactive_transform(JWidget widget,
|
||||
x2 += x1 - ox;
|
||||
y2 += y1 - oy;
|
||||
}
|
||||
|
||||
|
||||
editor_to_screen(widget, x1, y1, &x1, &y1);
|
||||
editor_to_screen(widget, x2, y2, &x2, &y2);
|
||||
|
||||
@ -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])
|
@ -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
268
src/util/clipboard_win32.h
Normal 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();
|
||||
}
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user