Ticket #33813: clip.diff
File clip.diff, 16.3 KB (added by MaddTheSane (C.W. Betts), 13 years ago) |
---|
-
(a) /Users/cwbetts/Downloads/macclipboard-gimp-0.7 vs. (b) macclipboard/Makefile
diff -u /Users/cwbetts/Downloads/macclipboard-gimp-0.7 2/Makefile macclipboard/Makefile
a b 1 linkflags = -f next-runtime -framework Cocoa -framework Carbon1 linkflags = -framework Cocoa 2 2 3 3 all : macclipboard 4 4 5 5 macclipboard : macclipboard.m clipboard_xfer.h 6 gcc -I/sw/include`gimptool-2.0 --cflags` `gimptool-2.0 --libs` $(linkflags) macclipboard.m -o macclipboard6 gcc `gimptool-2.0 --cflags` `gimptool-2.0 --libs` $(linkflags) macclipboard.m -o macclipboard 7 7 8 8 install : macclipboard 9 9 cp -p macclipboard $(HOME)/.gimp-2.0/plug-ins/ -
(a) /Users/cwbetts/Downloads/macclipboard-gimp-0.7 vs. (b) macclipboard/macclipboard.m
Binary files /Users/cwbetts/Downloads/macclipboard-gimp-0.7 2/macclipboard and macclipboard/macclipboard differ diff -u /Users/cwbetts/Downloads/macclipboard-gimp-0.7 2/macclipboard.m macclipboard/macclipboard.m
a b 32 32 /* 33 33 The Mac clipboard ('pasteboard' or 'scrap') can contain data in multiple 34 34 formats. The least common denominator for graphic data is 'PICT', a QuickDraw 35 picture. 35 picture. However, QuickDraw, and by extension PICT, have been depricated and 36 aren't available under 64-bit code. 36 37 37 38 Cocoa apps prefer TIFF, which also lets us transfer alpha channel data 38 39 relatively reliably. When we post a TIFF, Cocoa does PICT translation for us. … … 69 70 /* #include "config.h" */ 70 71 71 72 #import <Cocoa/Cocoa.h> 72 #include <Carbon/Carbon.h>73 73 74 74 #include <sys/types.h> 75 75 #include <sys/stat.h> … … 117 117 static gboolean clipboard_paste_service (gboolean interactive, 118 118 NSString *service); 119 119 120 121 /* PICT bits */122 static gboolean clipboard_offscreen_pict (PicHandle pic,123 guchar fill,124 guint32 *outWidth,125 guint32 *outHeight,126 guint32 *outRowstride,127 guchar **outBits,128 GWorldPtr *outGworld);129 130 static gboolean clipboard_buffer_has_alpha (guchar *bits,131 guint32 width,132 guint32 height,133 guint32 rowstride);134 135 static gboolean clipboard_extract_alpha (guchar *bits,136 guchar *bits_white,137 guint32 width,138 guint32 height,139 guint32 rowstride);140 141 static gboolean clipboard_paste_pict (gboolean interactive,142 gint32 image_ID,143 gint32 drawable_ID,144 NSData *data,145 gint32 *image_out);146 147 120 /* Other image types */ 148 121 static gboolean clipboard_paste_bitmap (gboolean interactive, 149 122 gint32 image_ID, … … 173 146 gint32 drawable_ID, 174 147 NSData *data); 175 148 176 static gint32 clipboard_load_pict (gboolean interactive,177 gchar *filename);178 179 149 GimpPlugInInfo PLUG_IN_INFO = 180 150 { 181 151 NULL, /* init_proc */ … … 290 260 GIMP_PLUGIN, 291 261 1, 0, 292 262 copy_args, NULL); 293 294 gimp_install_procedure ("file_pict_load",295 "Loads files of Macintosh PICT file format",296 "Loads files of Macintosh PICT file format",297 "Brion Vibber <brion@pobox.com>",298 "Brion Vibber <brion@pobox.com>",299 "2004",300 "<Load>/pict",301 NULL,302 GIMP_PLUGIN,303 G_N_ELEMENTS (load_args),304 G_N_ELEMENTS (load_return_vals),305 load_args, load_return_vals);306 307 gimp_register_magic_load_handler ("file_pict_load",308 "pict",309 "",310 "");311 263 } 312 264 313 265 static void … … 348 300 ok = clipboard_paste_service (interactive, @"Grab/Selection"); 349 301 else if (strcmp (name, "plug_in_clipboard_grab_timed") == 0) 350 302 ok = clipboard_paste_service (interactive, @"Grab/Timed Screen"); 351 else if (strcmp (name, "file_pict_load") == 0)352 {353 gint32 image = clipboard_load_pict (interactive, param[1].data.d_string);354 ok = (image != -1);355 if (ok)356 {357 *nreturn_vals = 2;358 values[1].type = GIMP_PDB_IMAGE;359 values[1].data.d_image = image;360 }361 }362 else363 {364 values[0].data.d_status = GIMP_PDB_CALLING_ERROR;365 [pool release];366 return;367 }368 303 369 304 values[0].data.d_status = ok ? GIMP_PDB_SUCCESS : GIMP_PDB_EXECUTION_ERROR; 370 [pool release];305 [pool drain]; 371 306 } 372 307 373 308 /* … … 522 457 else 523 458 { 524 459 [board setData: [bitmap TIFFRepresentation] forType: NSTIFFPboardType]; 525 526 /* Force conversion to PICT before we leave */527 [board types];528 [board dataForType: NSPICTPboardType];529 460 } 461 [bitmap release]; 530 462 531 463 return TRUE; 532 464 } … … 561 493 if (NSPerformService(service, board)) 562 494 return clipboard_paste_board (interactive, IMAGE_NONE, IMAGE_NONE, board); 563 495 564 g_message (_("Couldn't run system service %s"), [service cString]);496 g_message (_("Couldn't run system service %s"), [service UTF8String]); 565 497 return FALSE; 566 498 } 567 499 568 569 570 571 500 /* 572 501 * Find pasteable image(s) from a given pasteboard and um... paste them. 573 502 */ … … 577 506 gint32 drawable_ID, 578 507 NSPasteboard *board) 579 508 { 580 509 gboolean retval = FALSE; 581 510 582 NSString *type = [board availableTypeFromArray: 583 [NSArray arrayWithObjects: 584 NSTIFFPboardType, 585 NSPICTPboardType, 586 NSRTFDPboardType, 587 nil]]; 511 NSString *type = [board availableTypeFromArray: 512 [NSArray arrayWithObjects: 513 NSTIFFPboardType, 514 NSRTFDPboardType, 515 nil]]; 588 516 if (type == nil) 589 517 { 590 518 g_message (_("Clipboard is empty or doesn't contain a picture.")); … … 599 527 } 600 528 601 529 if ([type isEqualToString: NSTIFFPboardType]) 602 530 return clipboard_paste_bitmap (interactive, image_ID, drawable_ID, 603 531 [NSBitmapImageRep imageRepWithData: data], NULL); 604 else if ([type isEqualToString: NSPICTPboardType])605 return clipboard_paste_pict (interactive, image_ID, drawable_ID, data, NULL);606 532 else if ([type isEqualToString: NSRTFDPboardType]) 607 608 533 return clipboard_paste_rtfd (interactive, image_ID, drawable_ID, data); 534 609 535 g_message (_("Unsupported type. This shouldn't happen!")); 610 536 return FALSE; 611 537 } 612 538 613 614 /*615 * Render a given PICT into a newly created offscreen 32-bit graphics616 * world, returning some handy information about the bits.617 *618 * fill should be either 0x00 (transparent) or 0xff (solid white)619 * *outGworld must be released by caller with DisposeGWorld()620 */621 static gboolean622 clipboard_offscreen_pict (PicHandle pic,623 guchar fill,624 guint32 *outWidth,625 guint32 *outHeight,626 guint32 *outRowstride,627 guchar **outBits,628 GWorldPtr *outGworld)629 {630 OSStatus err;631 PictInfo info;632 err = GetPictInfo (pic, &info, 0, 0, 0, 0);633 if (err)634 {635 g_warning ("GetPictInfo returned %d", (int)err);636 return FALSE;637 }638 639 guint32 width = info.sourceRect.right - info.sourceRect.left;640 guint32 height = info.sourceRect.bottom - info.sourceRect.top;641 *outWidth = width;642 *outHeight = height;643 644 GWorldPtr gworld;645 QDErr qerr = NewGWorld (&gworld, 32, &info.sourceRect, NULL, NULL, 0);646 if (qerr)647 {648 g_warning ("NewGWorld returned %d", (int)qerr);649 return FALSE;650 }651 *outGworld = gworld;652 653 SetGWorld (gworld, NULL);654 PixMapHandle pixmap = GetGWorldPixMap (gworld);655 guchar *bits = (guchar *)GetPixBaseAddr (pixmap);656 *outBits = bits;657 658 guint32 rowstride = (*pixmap)->rowBytes & 0x3fff;659 *outRowstride = rowstride;660 661 /* Sometimes the picture won't fill the whole area;662 pre-fill the background as transparent or solid */663 memset (bits, fill, rowstride * height);664 665 DrawPicture (pic, &info.sourceRect);666 return TRUE;667 }668 669 /*670 * Returns TRUE if non-zero alpha values are detected.671 * Doesn't detect whether the image is actually transparent or not.672 */673 static gboolean674 clipboard_buffer_has_alpha (guchar *bits,675 guint32 width,676 guint32 height,677 guint32 rowstride)678 {679 int x, y;680 for (y = 0; y < height; y++)681 for (x = 0; x < width; x++)682 if (0 != bits[y * rowstride + x * 4])683 return TRUE;684 return FALSE;685 }686 687 /*688 * Awful hack for pasting alpha images from Photoshop; we can't get the689 * alpha channel values directly out of it.690 *691 * On input:692 * bits contains aRGB image premultipled with black693 * bits_white contains aRGB image premultipled with white694 *695 * On output, the alpha channel values in bits are filled in.696 */697 static gboolean698 clipboard_extract_alpha (guchar *bits,699 guchar *bits_white,700 guint32 width,701 guint32 height,702 guint32 rowstride)703 {704 guint32 x, y, n, rdiff, gdiff, bdiff;705 for (y = 0; y < height; y++)706 {707 n = y * rowstride;708 for (x = 0; x < width; x++)709 {710 /*711 d' = a * s + (1 - a) * d712 where:713 1 = d714 bits_white = d'715 bits = a * s716 717 a = 1 - bits_white + bits718 */719 720 /* Rounding may put the channels off by one */721 rdiff = 0xff - bits_white[n + 1] + bits[n + 1];722 /* gdiff = 0xff - bits_white[n + 2] + bits[n + 2]; */723 /* bdiff = 0xff - bits_white[n + 3] + bits[n + 3]; */724 bits[n] = rdiff;725 n += 4;726 /* g_print("reconstructed alpha %02x %02x %02x\n", rdiff, gdiff, bdiff); */727 }728 }729 return TRUE;730 }731 732 /*733 * Paste a PICT using QuickDraw734 */735 static gboolean736 clipboard_paste_pict (gboolean interactive,737 gint32 image_ID,738 gint32 drawable_ID,739 NSData *data,740 gint32 *image_out)741 {742 PicHandle pic;743 pic = (PicHandle)NewHandle ([data length]);744 if (pic == NULL)745 {746 g_warning ("clipboard_paste_pict: Couldn't allocate memory for picture (NewHandle returned FALSE)");747 return FALSE;748 }749 750 [data getBytes: *pic];751 752 guint32 width, height, rowstride;753 GWorldPtr gworld;754 guchar *bits;755 if (! clipboard_offscreen_pict (pic, 0x00,756 &width, &height, &rowstride,757 &bits, &gworld))758 {759 DisposeHandle ((Handle)pic);760 return FALSE;761 }762 763 gboolean hasalpha = clipboard_buffer_has_alpha (bits, width, height, rowstride);764 if (! hasalpha)765 {766 /* PICTs pasted from Photoshop don't touch the alpha767 channel but do store transparency. Ugly hack ahead!768 We render the image again on a white background,769 then extract alpha values from the difference. */770 GWorldPtr gworld_white;771 guchar *bits_white;772 if (clipboard_offscreen_pict (pic, 0xff,773 &width, &height, &rowstride,774 &bits_white, &gworld_white))775 {776 hasalpha = clipboard_extract_alpha (bits, bits_white,777 width, height, rowstride);778 DisposeGWorld (gworld_white);779 }780 }781 782 guint32 layertype;783 xfer_func_type xfer_func;784 if (image_ID != IMAGE_NONE)785 {786 GimpDrawable *drawable = gimp_drawable_get (drawable_ID);787 if (drawable->bpp < 3)788 {789 layertype = GIMP_GRAYA_IMAGE;790 if (hasalpha)791 xfer_func = xfer_argbP_graya;792 else793 xfer_func = xfer_0rgb_graya;794 }795 else796 {797 layertype = GIMP_RGBA_IMAGE;798 if (hasalpha)799 xfer_func = xfer_argbP_rgba;800 else801 xfer_func = xfer_0rgb_rgba;802 }803 }804 else805 {806 if (hasalpha)807 {808 layertype = GIMP_RGBA_IMAGE;809 xfer_func = xfer_argbP_rgba;810 }811 else812 {813 layertype = GIMP_RGB_IMAGE;814 xfer_func = xfer_0rgb_rgb;815 }816 }817 818 NSSize dpi = {72.0, 72.0};819 gboolean retval = clipboard_paste_image (interactive, image_ID, drawable_ID, dpi,820 bits, width, height, rowstride,821 4, 32, layertype, xfer_func, NULL, image_out);822 823 DisposeGWorld (gworld);824 DisposeHandle ((Handle)pic);825 826 return retval;827 }828 829 539 static gboolean 830 540 clipboard_paste_image (gboolean interactive, 831 541 gint32 image_ID, … … 975 685 if (channels != (3 + alpha)) 976 686 { 977 687 g_message (_("Don't understand %d-channel image in RGB image (%s; alpha: %s)"), 978 channels, [colorSpace cString], alpha ? "yes" : "no");688 channels, [colorSpace UTF8String], alpha ? "yes" : "no"); 979 689 return FALSE; 980 690 } 981 691 } … … 986 696 if (channels != (1 + alpha)) 987 697 { 988 698 g_message (_("Don't understand %d-channel image in grayscale image (%s; alpha: %s)"), 989 channels, [colorSpace cString], alpha ? "yes" : "no");699 channels, [colorSpace UTF8String], alpha ? "yes" : "no"); 990 700 return FALSE; 991 701 } 992 702 } 703 /* Apparently black color spaces are depricated in Snow Leopard and later*/ 993 704 else if ([colorSpace isEqualToString: NSCalibratedBlackColorSpace] || 994 705 [colorSpace isEqualToString: NSDeviceBlackColorSpace]) 995 706 { … … 997 708 if (channels != (1 + alpha)) 998 709 { 999 710 g_message (_("Don't understand %d-channel image in grayscale image (%s; alpha: %s)"), 1000 channels, [colorSpace cString], alpha ? "yes" : "no");711 channels, [colorSpace UTF8String], alpha ? "yes" : "no"); 1001 712 return FALSE; 1002 713 } 1003 714 } 1004 715 else 1005 716 { 1006 g_message (_("Unknown colorspace! %s"), [colorSpace cString]);717 g_message (_("Unknown colorspace! %s"), [colorSpace UTF8String]); 1007 718 return FALSE; 1008 719 } 1009 720 … … 1153 864 g_message (_("Rich text on clipboard is corrupt, can't read.")); 1154 865 return FALSE; 1155 866 } 1156 1157 static gint321158 clipboard_load_pict (gboolean interactive,1159 gchar *filename)1160 {1161 struct stat filestat;1162 if (0 == stat (filename, &filestat))1163 {1164 long fsize = filestat.st_size - 512;1165 guchar *buf = malloc (fsize);1166 FILE *file = fopen (filename, "rb");1167 fseek (file, 512, SEEK_SET);1168 fread (buf, 1, fsize, file);1169 fclose (file);1170 NSData *data = [NSData dataWithBytesNoCopy: buf length: fsize];1171 if (data != nil)1172 {1173 gint32 image_out;1174 if (clipboard_paste_pict (interactive, -1, -1, data, &image_out))1175 {1176 gimp_image_set_filename (image_out, filename);1177 return image_out;1178 }1179 }1180 }1181 g_message ("Could not open file %s", filename);1182 return -1;1183 }