Ticket #33813: clip.diff

File clip.diff, 16.3 KB (added by MaddTheSane (C.W. Betts), 12 years ago)

Patch to strip out QuickDraw stuff

  • (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 = -fnext-runtime -framework Cocoa -framework Carbon
     1linkflags = -framework Cocoa
    22
    33all : macclipboard
    44
    55macclipboard : macclipboard.m clipboard_xfer.h
    6         gcc -I/sw/include `gimptool-2.0 --cflags` `gimptool-2.0 --libs` $(linkflags) macclipboard.m -o macclipboard
     6        gcc `gimptool-2.0 --cflags` `gimptool-2.0 --libs` $(linkflags) macclipboard.m -o macclipboard
    77
    88install : macclipboard
    99        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  
    3232/*
    3333The Mac clipboard ('pasteboard' or 'scrap') can contain data in multiple
    3434formats. The least common denominator for graphic data is 'PICT', a QuickDraw
    35 picture.
     35picture. However, QuickDraw, and by extension PICT, have been depricated and
     36aren't available under 64-bit code.
    3637
    3738Cocoa apps prefer TIFF, which also lets us transfer alpha channel data
    3839relatively reliably. When we post a TIFF, Cocoa does PICT translation for us.
     
    6970/* #include "config.h" */
    7071
    7172#import <Cocoa/Cocoa.h>
    72 #include <Carbon/Carbon.h>
    7373
    7474#include <sys/types.h>
    7575#include <sys/stat.h>
     
    117117static gboolean clipboard_paste_service    (gboolean         interactive,
    118118                                            NSString        *service);
    119119
    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 
    147120/* Other image types */
    148121static gboolean clipboard_paste_bitmap     (gboolean          interactive,
    149122                                            gint32            image_ID,
     
    173146                                            gint32           drawable_ID,
    174147                                            NSData          *data);
    175148
    176 static gint32   clipboard_load_pict        (gboolean         interactive,
    177                                             gchar            *filename);
    178 
    179149GimpPlugInInfo PLUG_IN_INFO =
    180150{
    181151  NULL,  /* init_proc  */
     
    290260                          GIMP_PLUGIN,
    291261                          1, 0,
    292262                          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                                     "");
    311263}
    312264
    313265static void
     
    348300    ok = clipboard_paste_service (interactive, @"Grab/Selection");
    349301  else if (strcmp (name, "plug_in_clipboard_grab_timed") == 0)
    350302    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   else
    363     {
    364       values[0].data.d_status = GIMP_PDB_CALLING_ERROR;
    365       [pool release];
    366       return;
    367     }
    368303 
    369304  values[0].data.d_status = ok ? GIMP_PDB_SUCCESS : GIMP_PDB_EXECUTION_ERROR;
    370   [pool release];
     305  [pool drain];
    371306}
    372307
    373308/*
     
    522457  else
    523458    {
    524459      [board setData: [bitmap TIFFRepresentation] forType: NSTIFFPboardType];
    525 
    526       /* Force conversion to PICT before we leave */
    527       [board types];
    528       [board dataForType: NSPICTPboardType];
    529460    }
     461        [bitmap release];
    530462
    531463  return TRUE;
    532464}
     
    561493  if (NSPerformService(service, board))
    562494    return clipboard_paste_board (interactive, IMAGE_NONE, IMAGE_NONE, board);
    563495
    564   g_message (_("Couldn't run system service %s"), [service cString]);
     496  g_message (_("Couldn't run system service %s"), [service UTF8String]);
    565497  return FALSE;
    566498}
    567499
    568 
    569 
    570 
    571500/*
    572501 * Find pasteable image(s) from a given pasteboard and um... paste them.
    573502 */
     
    577506                       gint32     drawable_ID,
    578507                       NSPasteboard *board)
    579508{
    580   gboolean retval = FALSE;
     509        gboolean retval = FALSE;
    581510
    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]];
    588516  if (type == nil)
    589517    {
    590518      g_message (_("Clipboard is empty or doesn't contain a picture."));
     
    599527    }
    600528
    601529  if ([type isEqualToString: NSTIFFPboardType])
    602     return clipboard_paste_bitmap (interactive, image_ID, drawable_ID,
     530          return clipboard_paste_bitmap (interactive, image_ID, drawable_ID,
    603531      [NSBitmapImageRep imageRepWithData: data], NULL);
    604   else if ([type isEqualToString: NSPICTPboardType])
    605     return clipboard_paste_pict (interactive, image_ID, drawable_ID, data, NULL);
    606532  else if ([type isEqualToString: NSRTFDPboardType])
    607     return clipboard_paste_rtfd (interactive, image_ID, drawable_ID, data);
    608 
     533          return clipboard_paste_rtfd (interactive, image_ID, drawable_ID, data);
     534       
    609535  g_message (_("Unsupported type. This shouldn't happen!"));
    610536  return FALSE;
    611537}
    612538
    613 
    614 /*
    615  * Render a given PICT into a newly created offscreen 32-bit graphics
    616  * 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 gboolean
    622 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 gboolean
    674 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 the
    689  * alpha channel values directly out of it.
    690  *
    691  * On input:
    692  *  bits contains aRGB image premultipled with black
    693  *  bits_white contains aRGB image premultipled with white
    694  *
    695  * On output, the alpha channel values in bits are filled in.
    696  */
    697 static gboolean
    698 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) * d
    712           where:
    713                         1 = d
    714                bits_white = d'
    715                      bits = a * s
    716 
    717              a = 1 - bits_white + bits
    718           */
    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 QuickDraw
    734  */
    735 static gboolean
    736 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 alpha
    767          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           else
    793             xfer_func = xfer_0rgb_graya;
    794         }
    795       else
    796         {
    797           layertype = GIMP_RGBA_IMAGE;
    798           if (hasalpha)
    799             xfer_func = xfer_argbP_rgba;
    800           else
    801             xfer_func = xfer_0rgb_rgba;
    802         }
    803     }
    804   else
    805     {
    806       if (hasalpha)
    807         {
    808           layertype = GIMP_RGBA_IMAGE;
    809           xfer_func = xfer_argbP_rgba;
    810         }
    811       else
    812         {
    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 
    829539static gboolean
    830540clipboard_paste_image (gboolean       interactive,
    831541                       gint32         image_ID,
     
    975685      if (channels != (3 + alpha))
    976686        {
    977687          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");
    979689          return FALSE;
    980690        }
    981691    }
     
    986696      if (channels != (1 + alpha))
    987697        {
    988698          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");
    990700          return FALSE;
    991701        }
    992702    }
     703        /* Apparently black color spaces are depricated in Snow Leopard and later*/
    993704  else if ([colorSpace isEqualToString: NSCalibratedBlackColorSpace] ||
    994705           [colorSpace isEqualToString: NSDeviceBlackColorSpace])
    995706    {
     
    997708      if (channels != (1 + alpha))
    998709        {
    999710          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");
    1001712          return FALSE;
    1002713        }
    1003714    }
    1004715  else
    1005716    {
    1006       g_message (_("Unknown colorspace! %s"), [colorSpace cString]);
     717      g_message (_("Unknown colorspace! %s"), [colorSpace UTF8String]);
    1007718      return FALSE;
    1008719    }
    1009720
     
    1153864  g_message (_("Rich text on clipboard is corrupt, can't read."));
    1154865  return FALSE;
    1155866}
    1156 
    1157 static gint32
    1158 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 }