Bug 393646 - Support reading image data off the clipboard on Mac r=josh,bienvenu sr=roc a=mconnor/drivers

This commit is contained in:
cbarrett@mozilla.com 2007-09-17 11:02:50 -07:00
parent bdb09ae04f
commit 39641d346a
3 changed files with 91 additions and 22 deletions

View File

@ -1118,10 +1118,8 @@ NS_IMETHODIMP nsHTMLEditor::PrepareHTMLTransferable(nsITransferable **aTransfera
}
(*aTransferable)->AddDataFlavor(kHTMLMime);
(*aTransferable)->AddDataFlavor(kFileMime);
#ifdef XP_WIN32
// image pasting from the clipboard is only implemented on Windows right now.
// image pasting from the clipboard is only implemented on Windows & Mac right now.
(*aTransferable)->AddDataFlavor(kJPEGImageMime);
#endif
}
(*aTransferable)->AddDataFlavor(kUnicodeMime);
}

View File

@ -45,6 +45,10 @@
#include "nsMemory.h"
#include "nsIImage.h"
#include "nsILocalFile.h"
#include "nsStringStream.h"
// Screenshots use the (undocumented) png pasteboard type.
#define IMAGE_PASTEBOARD_TYPES NSTIFFPboardType, @"Apple PNG pasteboard type", nil
#ifdef MOZ_LOGGING
#define FORCE_PR_LOG
@ -196,14 +200,72 @@ nsClipboard::GetNativeClipboardData(nsITransferable* aTransferable, PRInt32 aWhi
free(clipboardDataPtr);
break;
}
else if (flavorStr.EqualsLiteral(kJPEGImageMime) ||
flavorStr.EqualsLiteral(kPNGImageMime) ||
flavorStr.EqualsLiteral(kGIFImageMime)) {
// Figure out if there's data on the pasteboard we can grab (sanity check)
NSString *type = [cocoaPasteboard availableTypeFromArray:[NSArray arrayWithObjects:IMAGE_PASTEBOARD_TYPES]];
if (!type)
continue;
/*
if (flavorStr.EqualsLiteral(kPNGImageMime) || flavorStr.EqualsLiteral(kJPEGImageMime) ||
flavorStr.EqualsLiteral(kGIFImageMime)) {
// We have never supported this on Mac OS X, we could someday but nobody does this.
break;
// Read data off the clipboard, make sure to catch any exceptions (timeouts)
// XXX should convert to @try/@catch someday?
NSData *pasteboardData = nil;
NS_DURING
pasteboardData = [cocoaPasteboard dataForType:type];
NS_HANDLER
NS_ASSERTION(0, "Exception raised while getting data from the pasteboard.");
NS_ENDHANDLER
if (!pasteboardData)
continue;
// Figure out what type we're converting to
CFStringRef outputType = NULL;
if (flavorStr.EqualsLiteral(kJPEGImageMime))
outputType = CFSTR("public.jpeg");
else if (flavorStr.EqualsLiteral(kPNGImageMime))
outputType = CFSTR("public.png");
else if (flavorStr.EqualsLiteral(kGIFImageMime))
outputType = CFSTR("com.compuserve.gif");
else
continue;
// Use ImageIO to interpret the data on the clipboard and transcode.
// Note that ImageIO, like all CF APIs, allows NULLs to propagate freely
// and safely in most cases (like ObjC). A notable exception is CFRelease.
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
(NSNumber*)kCFBooleanTrue, kCGImageSourceShouldAllowFloat,
(type == NSTIFFPboardType ? @"public.tiff" : @"public.png"),
kCGImageSourceTypeIdentifierHint, nil];
CGImageSourceRef source = CGImageSourceCreateWithData((CFDataRef)pasteboardData,
(CFDictionaryRef)options);
NSMutableData *encodedData = [NSMutableData data];
CGImageDestinationRef dest = CGImageDestinationCreateWithData((CFMutableDataRef)encodedData,
outputType,
1, NULL);
CGImageDestinationAddImageFromSource(dest, source, 0, NULL);
PRBool successfullyConverted = CGImageDestinationFinalize(dest);
if (successfullyConverted) {
// Put the converted data in a form Gecko can understand
nsCOMPtr<nsIInputStream> byteStream;
NS_NewByteInputStream(getter_AddRefs(byteStream), (const char*)[encodedData bytes],
[encodedData length], NS_ASSIGNMENT_COPY);
aTransferable->SetTransferData(flavorStr, byteStream, sizeof(nsIInputStream*));
}
if (dest)
CFRelease(dest);
if (source)
CFRelease(source);
if (successfullyConverted)
break;
else
continue;
}
*/
}
return NS_OK;
@ -271,6 +333,15 @@ nsClipboard::HasDataMatchingFlavors(nsISupportsArray* aFlavorList, PRInt32 aWhic
*outResult = PR_TRUE;
break;
}
} else if (flavorStr.EqualsLiteral(kJPEGImageMime) ||
flavorStr.EqualsLiteral(kPNGImageMime) ||
flavorStr.EqualsLiteral(kGIFImageMime)) {
NSString* availableType = [generalPBoard availableTypeFromArray:
[NSArray arrayWithObjects:IMAGE_PASTEBOARD_TYPES]];
if (availableType) {
*outResult = PR_TRUE;
break;
}
}
}
}
@ -369,28 +440,31 @@ nsClipboard::PasteboardDictFromTransferable(nsITransferable* aTransferable)
NULL,
0,
kCGRenderingIntentDefault);
CGColorSpaceRelease(colorSpace);
CGDataProviderRelease(dataProvider);
// Convert the CGImageRef to TIFF data.
CFMutableDataRef tiffData = CFDataCreateMutable(kCFAllocatorDefault, 0);
CGImageDestinationRef destRef = CGImageDestinationCreateWithData(tiffData,
(CFStringRef)@"public.tiff",
CFSTR("public.tiff"),
1,
nil);
CGImageDestinationAddImage(destRef, imageRef, nil);
CGImageDestinationFinalize(destRef);
NULL);
CGImageDestinationAddImage(destRef, imageRef, NULL);
PRBool successfullyConverted = CGImageDestinationFinalize(destRef);
CGColorSpaceRelease(colorSpace);
CGImageRelease(imageRef);
CFRelease(destRef);
if (destRef)
CFRelease(destRef);
if (NS_FAILED(image->UnlockImagePixels(PR_FALSE))) {
CFRelease(tiffData);
if (NS_FAILED(image->UnlockImagePixels(PR_FALSE)) || !successfullyConverted) {
if (tiffData)
CFRelease(tiffData);
continue;
}
[pasteboardOutputDict setObject:(NSMutableData*)tiffData forKey:NSTIFFPboardType];
CFRelease(tiffData);
if (tiffData)
CFRelease(tiffData);
}
else if (flavorStr.EqualsLiteral(kFilePromiseMime)) {
[pasteboardOutputDict setObject:[NSArray arrayWithObject:@""] forKey:NSFilesPromisePboardType];

View File

@ -43,9 +43,6 @@
#include "nsMemory.h"
#include "prmem.h"
#include "imgIEncoder.h"
#ifdef MOZILLA_1_8_BRANCH
#define imgIEncoder imgIEncoder_MOZILLA_1_8_BRANCH
#endif
#include "nsLiteralString.h"
/* Things To Do 11/8/00
@ -233,7 +230,7 @@ nsImageFromClipboard ::GetEncodedImageStream (unsigned char * aClipboardData, ns
nsCOMPtr<imgIEncoder> encoder = do_CreateInstance("@mozilla.org/image/encoder;2?type=image/jpeg", &rv);
if (NS_SUCCEEDED(rv)){
rv = encoder->InitFromData(rgbData, 0, width, height, 3 * width /* RGB * # pixels in a row */,
imgIEncoder::INPUT_FORMAT_RGB, NS_LITERAL_STRING("transparency=none"));
imgIEncoder::INPUT_FORMAT_RGB, EmptyString());
if (NS_SUCCEEDED(rv))
encoder->QueryInterface(NS_GET_IID(nsIInputStream), (void **) aInputStream);
}