diff --git a/mozilla/editor/libeditor/html/Makefile.in b/mozilla/editor/libeditor/html/Makefile.in
index 9cdeabbddc2..1c85176cc5b 100644
--- a/mozilla/editor/libeditor/html/Makefile.in
+++ b/mozilla/editor/libeditor/html/Makefile.in
@@ -59,9 +59,11 @@ REQUIRES = xpcom \
necko \
pref \
gfx \
+ imglib2 \
widget \
view \
webshell \
+ exthandler \
$(NULL)
# Building the full blown HTML Editor so add its source files and objects:
diff --git a/mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp b/mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp
index 9ab4e373b03..b2d34a33e14 100644
--- a/mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp
+++ b/mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp
@@ -130,6 +130,10 @@
#include "nsIPrefBranch.h"
#include "nsIPrefService.h"
#include "nsIContentFilter.h"
+#include "imgIEncoder.h"
+
+#include "nsIExternalHelperAppService.h"
+#include "nsCExternalHandlerService.h"
const PRUnichar nbsp = 160;
@@ -1143,7 +1147,11 @@ NS_IMETHODIMP nsHTMLEditor::PrepareHTMLTransferable(nsITransferable **aTransfera
}
(*aTransferable)->AddDataFlavor(kHTMLMime);
(*aTransferable)->AddDataFlavor(kFileMime);
- //(*aTransferable)->AddDataFlavor(kJPEGImageMime);
+#ifdef XP_WIN32
+ // we only support copy and paste of clipboard images on Windows
+ (*aTransferable)->AddDataFlavor(kJPEGImageMime);
+ (*aTransferable)->AddDataFlavor(kNativeImageMime);
+#endif
}
(*aTransferable)->AddDataFlavor(kUnicodeMime);
}
@@ -1407,14 +1415,58 @@ NS_IMETHODIMP nsHTMLEditor::InsertFromTransferable(nsITransferable *transferable
}
}
}
+ else if (flavor.Equals(NS_LITERAL_STRING(kNativeImageMime)))
+ {
+ nsXPIDLString htmlstr;
+ nsAutoEditBatch beginBatching(this);
+ rv = InsertHTMLWithContext(htmlstr, EmptyString(), EmptyString(), flavor, aSourceDoc, aDestinationNode, aDestOffset, aDoDeleteSelection);
+ }
else if (0 == nsCRT::strcmp(bestFlavor, kJPEGImageMime))
{
- // need to provide a hook from here
- // Insert Image code here
- printf("Don't know how to insert an image yet!\n");
- //nsIImage* image = (nsIImage *)data;
- //NS_RELEASE(image);
- rv = NS_ERROR_NOT_IMPLEMENTED; // for now give error code
+ // Insert Image code
+ nsCOMPtr clipboardImage (do_QueryInterface(genericDataObj));
+ if (clipboardImage)
+ {
+ // invoke image encoder
+ nsCOMPtr imgEncoder (do_CreateInstance("@mozilla.org/image/encoder;2?type=image/jpeg"));
+ if (imgEncoder)
+ {
+ nsCOMPtr clipboardImageFile;
+ rv = imgEncoder->EncodeClipboardImage(clipboardImage, getter_AddRefs(clipboardImageFile));
+
+ if (NS_FAILED(rv) || !clipboardImageFile)
+ return rv;
+
+ nsCOMPtr uri;
+ rv = NS_NewFileURI(getter_AddRefs(uri), clipboardImageFile);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr fileURL(do_QueryInterface(uri));
+ if (fileURL)
+ {
+ nsCAutoString urltext;
+ rv = fileURL->GetSpec(urltext);
+ if (NS_SUCCEEDED(rv) && !urltext.IsEmpty())
+ {
+ stuffToPaste.AssignLiteral("
");
+ nsAutoEditBatch beginBatching(this);
+ rv = InsertHTMLWithContext(stuffToPaste,
+ nsString(), nsString(), NS_LITERAL_STRING(kFileMime),
+ aSourceDoc,
+ aDestinationNode, aDestOffset,
+ aDoDeleteSelection);
+ }
+ }
+
+ nsCOMPtr tempFileManager (do_GetService(NS_EXTERNALHELPERAPPSERVICE_CONTRACTID));
+ if (tempFileManager)
+ tempFileManager->DeleteTemporaryFileOnExit(clipboardImageFile);
+ }
+ else
+ rv = NS_ERROR_NOT_IMPLEMENTED; // for now give error code, we don't know how to handle the image format from the clipboard
+ }
}
}
nsCRT::free(bestFlavor);
@@ -1927,7 +1979,7 @@ NS_IMETHODIMP nsHTMLEditor::CanPaste(PRInt32 aSelectionType, PRBool *aCanPaste)
// the flavors that we can deal with
const char* const textEditorFlavors[] = { kUnicodeMime, nsnull };
- const char* const htmlEditorFlavors[] = { kHTMLMime, kJPEGImageMime, nsnull };
+ const char* const htmlEditorFlavors[] = { kHTMLMime, kJPEGImageMime, kNativeImageMime, nsnull };
nsCOMPtr flavorsList =
do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID, &rv);
diff --git a/mozilla/modules/libpr0n/build/nsImageModule.cpp b/mozilla/modules/libpr0n/build/nsImageModule.cpp
index 122cf4c6c1d..14b7d42ed8f 100644
--- a/mozilla/modules/libpr0n/build/nsImageModule.cpp
+++ b/mozilla/modules/libpr0n/build/nsImageModule.cpp
@@ -74,6 +74,10 @@
#include "nsPNGDecoder.h"
#endif
+#if defined(XP_WIN32) && defined(IMG_BUILD_jpeg)
+#include "nsJPEGEncoder.h"
+#endif
+
#ifdef IMG_BUILD_jpeg
// jpeg
#include "nsJPEGDecoder.h"
@@ -102,6 +106,10 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsGIFDecoder2)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsJPEGDecoder)
#endif
+#if defined(XP_WIN32) && defined(IMG_BUILD_jpeg)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsJPEGEncoder)
+#endif
+
#ifdef IMG_BUILD_bmp
// bmp
NS_GENERIC_FACTORY_CONSTRUCTOR(nsICODecoder)
@@ -227,6 +235,13 @@ static const nsModuleComponentInfo components[] =
nsJPEGDecoderConstructor, },
#endif
+#if defined(XP_WIN32) && defined(IMG_BUILD_jpeg)
+ { "JPEG encoder",
+ NS_JPEGENCODER_CID,
+ "@mozilla.org/image/encoder;2?type=image/jpeg",
+ nsJPEGEncoderConstructor, },
+#endif
+
#ifdef IMG_BUILD_bmp
// bmp
{ "ICO Decoder",
diff --git a/mozilla/modules/libpr0n/decoders/jpeg/Makefile.in b/mozilla/modules/libpr0n/decoders/jpeg/Makefile.in
index 8dc8d2ea1b9..d9ea01a17db 100644
--- a/mozilla/modules/libpr0n/decoders/jpeg/Makefile.in
+++ b/mozilla/modules/libpr0n/decoders/jpeg/Makefile.in
@@ -35,11 +35,17 @@ LIBXUL_LIBRARY = 1
REQUIRES = xpcom \
string \
gfx \
+ widget \
imglib2 \
+ necko \
$(JPEG_REQUIRES) \
$(NULL)
-CPPSRCS = nsJPEGDecoder.cpp
+CPPSRCS = nsJPEGDecoder.cpp \
+ $(NULL)
+
+ifeq ($(OS_ARCH),WINNT)
+CPPSRCS += nsJPEGEncoder.cpp
+endif
include $(topsrcdir)/config/rules.mk
-
diff --git a/mozilla/modules/libpr0n/decoders/jpeg/nsJPEGEncoder.cpp b/mozilla/modules/libpr0n/decoders/jpeg/nsJPEGEncoder.cpp
new file mode 100755
index 00000000000..cf649099d77
--- /dev/null
+++ b/mozilla/modules/libpr0n/decoders/jpeg/nsJPEGEncoder.cpp
@@ -0,0 +1,567 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the JPEG image encoder.
+ *
+ * The Initial Developer of the Original Code is
+ * Scott MacGregor .
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifdef MOZ_LOGGING
+// sorry, this has to be before the pre-compiled header
+#define FORCE_PR_LOG /* Allow logging in the release build */
+#endif
+
+#include
+#include "nsJPEGEncoder.h"
+#include "nsIClipboard.h"
+#include "nsIComponentManager.h"
+#include "nspr.h"
+#include "nsCRT.h"
+#include "ImageLogging.h"
+#include "jerror.h"
+
+#include "nsILocalFile.h"
+#include "nsIOutputStream.h"
+#include "nsNetUtil.h"
+#include "nsDirectoryServiceDefs.h"
+
+PRLogModuleInfo *gJPEGEncoderLog = PR_NewLogModule("JPEGEncoder");
+
+#define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */
+
+NS_IMPL_ISUPPORTS1(nsJPEGEncoder, imgIEncoder)
+
+METHODDEF(boolean) empty_output_buffer (j_compress_ptr jd);
+METHODDEF(void) init_destination (j_compress_ptr jd);
+METHODDEF(void) term_destination (j_compress_ptr cinfo);
+METHODDEF(void) my_error_exit (j_common_ptr cinfo);
+
+// helper declarations for converting a bitmap to 4 byte RGB data
+
+nsresult ConvertColorBitMap(unsigned char * aBitmapBuffer, PBITMAPINFO pBitMapInfo, unsigned char * aOutputBuffer);nsJPEGEncoder * getEncoderForCompressionInfoStruct(jpeg_compress_struct * cInfo);
+
+struct bitFields {
+ PRUint32 red;
+ PRUint32 green;
+ PRUint32 blue;
+ PRUint8 redLeftShift;
+ PRUint8 redRightShift;
+ PRUint8 greenLeftShift;
+ PRUint8 greenRightShift;
+ PRUint8 blueLeftShift;
+ PRUint8 blueRightShift;
+};
+
+void CalcBitShift(bitFields * aColorMask);
+
+/*
+ * Implementation of a JPEG destination manager object
+ */
+typedef struct {
+ /* public fields; must be first in this struct! */
+ struct jpeg_destination_mgr pub;
+
+ nsJPEGEncoder *encoder; // weak reference
+
+} encoder_destination_mgr;
+
+nsJPEGEncoder::nsJPEGEncoder()
+{
+ mBuffer = nsnull;
+ mBufferLen = mBufferSize = 0;
+ memset(&mInfo, 0, sizeof(jpeg_compress_struct));
+}
+
+nsJPEGEncoder::~nsJPEGEncoder()
+{
+}
+
+nsresult nsJPEGEncoder::initCompressionInfo()
+{
+ /* We set up the normal JPEG error routines, then override error_exit. */
+ mInfo.err = jpeg_std_error(&mErr.pub);
+ mErr.pub.error_exit = my_error_exit;
+
+ /* Establish the setjmp return context for my_error_exit to use. */
+ if (setjmp(mErr.setjmp_buffer))
+ {
+ /* If we get here, the JPEG code has signaled an error.
+ * We need to clean up the JPEG object, close the input file, and return.
+ */
+ return NS_ERROR_FAILURE;
+ }
+
+ jpeg_create_compress(&mInfo);
+
+ encoder_destination_mgr * destinationManager;
+
+ // first, setup the destination manager
+ if (mInfo.dest == NULL)
+ {
+ destinationManager = PR_NEWZAP(encoder_destination_mgr);
+ if (!destinationManager)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ mInfo.dest = NS_REINTERPRET_CAST(struct jpeg_destination_mgr *, destinationManager);
+ }
+
+ /* Setup callback functions. */
+ destinationManager->pub.init_destination = init_destination ;
+ destinationManager->pub.empty_output_buffer = empty_output_buffer;
+ destinationManager->pub.term_destination = term_destination;
+
+ destinationManager->encoder = this; // note the lack of a reference here. We own the lifetime of the destinationManager object
+
+ return NS_OK;
+}
+
+nsJPEGEncoder * getEncoderForCompressionInfoStruct(jpeg_compress_struct * cInfo)
+{
+ if (cInfo && cInfo->dest)
+ {
+ encoder_destination_mgr *destinationManager = NS_REINTERPRET_CAST(encoder_destination_mgr *, cInfo->dest);
+ return destinationManager->encoder;
+ }
+
+ return NULL;
+}
+
+
+/** imgIEncoder methods **/
+
+NS_IMETHODIMP nsJPEGEncoder::EncodeClipboardImage(nsIClipboardImage * aClipboardImage, nsIFile ** aImageFile)
+{
+ // this is windows only....
+ STGMEDIUM stm;
+ nsresult rv = aClipboardImage->GetNativeImage( (void *) &stm);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // test...try writing the bitmap to a file
+ nsCOMPtr fileToUse;
+ NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(fileToUse));
+
+ fileToUse->Append(NS_LITERAL_STRING("moz-screenshot.jpg"));
+ nsCOMPtr path = do_QueryInterface(fileToUse);
+ path->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600);
+
+ rv = NS_NewLocalFileOutputStream(getter_AddRefs(mOutputStream), path);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // It is critical that we do not return early in this routine from here on out.
+ // We must release our lock and release stm before exiting
+ HGLOBAL hGlobal = stm.hGlobal;
+ BYTE * pGlobal = (BYTE *)::GlobalLock (hGlobal);
+ BITMAPINFO * bitMapInfo = (BITMAPINFO *) pGlobal;
+
+ rv = initCompressionInfo();
+ if (NS_SUCCEEDED(rv))
+ {
+ mInfo.in_color_space = JCS_RGB;
+ mInfo.input_components = 3;
+ mInfo.data_precision = 8;
+ mInfo.image_width = (JDIMENSION) bitMapInfo->bmiHeader.biWidth;
+ mInfo.image_height = (JDIMENSION) bitMapInfo->bmiHeader.biHeight;
+
+ unsigned char * rgbData = (unsigned char *) malloc (bitMapInfo->bmiHeader.biWidth * bitMapInfo->bmiHeader.biHeight * 3 /* RGB */);
+
+ if (rgbData)
+ {
+ rv = ConvertColorBitMap((unsigned char *) (pGlobal + bitMapInfo->bmiHeader.biSize), bitMapInfo, rgbData);
+ if (NS_SUCCEEDED(rv))
+ {
+ jpeg_set_defaults(&mInfo);
+
+ if ( bitMapInfo->bmiHeader.biXPelsPerMeter > 0 && bitMapInfo->bmiHeader.biYPelsPerMeter > 0)
+ {
+ /* Set JFIF density parameters from the BMP data */
+ mInfo.X_density = (UINT16) ( bitMapInfo->bmiHeader.biXPelsPerMeter/100); /* 100 cm per meter */
+ mInfo.Y_density = (UINT16) ( bitMapInfo->bmiHeader.biYPelsPerMeter/100);
+ mInfo.density_unit = 2; /* dots/cm */
+ }
+
+ jpeg_start_compress(&mInfo, TRUE);
+
+ PRInt32 row_stride = bitMapInfo->bmiHeader.biWidth * 3;
+ JSAMPROW row_pointer[1];
+
+ while (mInfo.next_scanline < mInfo.image_height)
+ {
+ row_pointer[0] = &rgbData[mInfo.next_scanline * row_stride];
+ jpeg_write_scanlines(&mInfo, row_pointer, 1);
+ }
+
+ jpeg_finish_compress(&mInfo);
+ }
+
+ free(rgbData);
+ } // if rgbdata
+
+ jpeg_destroy_compress(&mInfo);
+ }
+
+ // close the output file stream. we are done with it
+ mOutputStream->Close();
+
+ // return the file URL to the JPG
+ NS_IF_ADDREF(*aImageFile = fileToUse);
+
+ ::GlobalUnlock (hGlobal); // release our lock on the bitmap
+
+ aClipboardImage->ReleaseNativeImage( (void *) &stm);
+
+ return NS_OK;
+}
+
+void InvertRows(unsigned char * aInitialBuffer, PRUint32 sizeOfBuffer, PRUint32 numBytesPerRow)
+{
+ if (!numBytesPerRow)
+ return;
+
+ PRUint32 numRows = sizeOfBuffer / numBytesPerRow;
+ void * temporaryRowHolder = (void *) nsMemory::Alloc(numBytesPerRow);
+
+ PRUint32 currentRow = 0;
+ PRUint32 lastRow = (numRows - 1) * numBytesPerRow;
+ while (currentRow < lastRow)
+ {
+ // store the current row into a temporary buffer
+ memcpy(temporaryRowHolder, (void *) &aInitialBuffer[currentRow], numBytesPerRow);
+ memcpy((void *) &aInitialBuffer[currentRow], (void *)&aInitialBuffer[lastRow], numBytesPerRow);
+ memcpy((void *) &aInitialBuffer[lastRow], temporaryRowHolder, numBytesPerRow);
+ lastRow -= numBytesPerRow;
+ currentRow += numBytesPerRow;
+ }
+
+ nsMemory::Free(temporaryRowHolder);
+}
+
+nsresult ConvertColorBitMap(unsigned char * buffer, PBITMAPINFO pBitMapInfo, unsigned char * outBuffer)
+{
+ PR_LOG(gJPEGEncoderLog, PR_LOG_ALWAYS, ("nsJPEGEncoder::ConvertColorBitMap"));
+
+ PRUint8 bitCount = pBitMapInfo->bmiHeader.biBitCount;
+ PRUint32 imageSize = pBitMapInfo->bmiHeader.biSizeImage; // may be zero for BI_RGB bitmaps which means we need to calculate by hand
+ PRUint32 bytesPerPixel = bitCount / 8;
+
+ if (bitCount <= 4)
+ bytesPerPixel = 1;
+
+ // rows are DWORD aligned. Calculate how many real bytes are in each row in the bitmap. This number won't
+ // correspond to biWidth.
+ PRUint32 rowSize = (bitCount * pBitMapInfo->bmiHeader.biWidth + 7) / 8; // +7 to round up
+ if (rowSize % 4)
+ rowSize += (4 - (rowSize % 4)); // Pad to DWORD Boundary
+
+ // if our buffer includes a color map, skip over it
+ if (bitCount <= 8)
+ {
+ PRInt32 bytesToSkip = (pBitMapInfo->bmiHeader.biClrUsed ? pBitMapInfo->bmiHeader.biClrUsed : (1 << bitCount) ) * sizeof(RGBQUAD);
+ buffer += bytesToSkip;
+ }
+
+ bitFields colorMasks; // only used if biCompression == BI_BITFIELDS
+
+ if (pBitMapInfo->bmiHeader.biCompression == BI_BITFIELDS)
+ {
+ // color table consists of 3 DWORDS containing the color masks...
+ colorMasks.red = (*((PRUint32*)&(pBitMapInfo->bmiColors[0])));
+ colorMasks.green = (*((PRUint32*)&(pBitMapInfo->bmiColors[1])));
+ colorMasks.blue = (*((PRUint32*)&(pBitMapInfo->bmiColors[2])));
+ CalcBitShift(&colorMasks);
+ buffer += 3 * sizeof(DWORD);
+ }
+ else if (pBitMapInfo->bmiHeader.biCompression == BI_RGB && !imageSize) // BI_RGB can have a size of zero which means we figure it out
+ {
+ // XXX: note use rowSize here and not biWidth. rowSize accounts for the DWORD padding for each row
+ imageSize = rowSize * pBitMapInfo->bmiHeader.biHeight;
+ }
+
+ // dump out some log information about the bit map info struct
+ PR_LOG(gJPEGEncoderLog, PR_LOG_ALWAYS, ("nsJPEGEncoder::ConvertColorBitMap biBitCount: %u", bitCount));
+ PR_LOG(gJPEGEncoderLog, PR_LOG_ALWAYS, ("nsJPEGEncoder::ConvertColorBitMap rowSize: %u", rowSize));
+ PR_LOG(gJPEGEncoderLog, PR_LOG_ALWAYS, ("nsJPEGEncoder::ConvertColorBitMap biCompression: %u", pBitMapInfo->bmiHeader.biCompression));
+ PR_LOG(gJPEGEncoderLog, PR_LOG_ALWAYS, ("nsJPEGEncoder::ConvertColorBitMap biWidth: %u", pBitMapInfo->bmiHeader.biWidth));
+ PR_LOG(gJPEGEncoderLog, PR_LOG_ALWAYS, ("nsJPEGEncoder::ConvertColorBitMap biHeight: %u", pBitMapInfo->bmiHeader.biHeight));
+ PR_LOG(gJPEGEncoderLog, PR_LOG_ALWAYS, ("nsJPEGEncoder::ConvertColorBitMap biClrUsed: %u", pBitMapInfo->bmiHeader.biClrUsed));
+
+ InvertRows(buffer, imageSize, rowSize);
+
+ PR_LOG(gJPEGEncoderLog, PR_LOG_ALWAYS, ("nsJPEGEncoder::ConvertColorBitMap bytesPerPixel: %u", bytesPerPixel));
+ PR_LOG(gJPEGEncoderLog, PR_LOG_ALWAYS, ("nsJPEGEncoder::ConvertColorBitMap calculated imageSize: %u", imageSize));
+ PR_LOG(gJPEGEncoderLog, PR_LOG_ALWAYS, ("nsJPEGEncoder::ConvertColorBitMap biSizeImage: %u", pBitMapInfo->bmiHeader.biSizeImage));
+
+ if (!pBitMapInfo->bmiHeader.biCompression || pBitMapInfo->bmiHeader.biCompression == BI_BITFIELDS)
+ {
+ PRUint32 index = 0;
+ PRUint32 writeIndex = 0;
+
+ unsigned char redValue, greenValue, blueValue;
+ PRUint8 colorTableEntry = 0;
+ PRInt8 bit; // used for grayscale bitmaps where each bit is a pixel
+ PRUint32 numPixelsLeftInRow = pBitMapInfo->bmiHeader.biWidth; // how many more pixels do we still need to read for the current row
+ PRUint32 pos = 0;
+
+ while (index < imageSize)
+ {
+ switch (bitCount)
+ {
+ case 1:
+ for (bit = 7; bit >= 0 && numPixelsLeftInRow; bit--)
+ {
+ colorTableEntry = (buffer[index] >> bit) & 1;
+ outBuffer[writeIndex++] = pBitMapInfo->bmiColors[colorTableEntry].rgbRed;
+ outBuffer[writeIndex++] = pBitMapInfo->bmiColors[colorTableEntry].rgbGreen;
+ outBuffer[writeIndex++] = pBitMapInfo->bmiColors[colorTableEntry].rgbBlue;
+ numPixelsLeftInRow--;
+ }
+ pos += 1;
+ break;
+ case 4:
+ {
+ // each buffer[index] entry contains data for two pixels.
+ // read the first pixel
+ colorTableEntry = buffer[index] >> 4;
+ outBuffer[writeIndex++] = pBitMapInfo->bmiColors[colorTableEntry].rgbRed;
+ outBuffer[writeIndex++] = pBitMapInfo->bmiColors[colorTableEntry].rgbGreen;
+ outBuffer[writeIndex++] = pBitMapInfo->bmiColors[colorTableEntry].rgbBlue;
+ numPixelsLeftInRow--;
+
+ if (numPixelsLeftInRow) // now read the second pixel
+ {
+ colorTableEntry = buffer[index] & 0xF;
+ outBuffer[writeIndex++] = pBitMapInfo->bmiColors[colorTableEntry].rgbRed;
+ outBuffer[writeIndex++] = pBitMapInfo->bmiColors[colorTableEntry].rgbGreen;
+ outBuffer[writeIndex++] = pBitMapInfo->bmiColors[colorTableEntry].rgbBlue;
+ numPixelsLeftInRow--;
+ }
+ pos += 1;
+ }
+ break;
+ case 8:
+ outBuffer[writeIndex++] = pBitMapInfo->bmiColors[buffer[index]].rgbRed;
+ outBuffer[writeIndex++] = pBitMapInfo->bmiColors[buffer[index]].rgbGreen;
+ outBuffer[writeIndex++] = pBitMapInfo->bmiColors[buffer[index]].rgbBlue;
+ numPixelsLeftInRow--;
+ pos += 1;
+ break;
+ case 16:
+ {
+ PRUint16 num = 0;
+ num = (PRUint8) buffer[index+1];
+ num <<= 8;
+ num |= (PRUint8) buffer[index];
+
+ redValue = ((PRUint32) (((float)(num & 0xf800) / 0xf800) * 0xFF0000) & 0xFF0000)>> 16;
+ greenValue = ((PRUint32)(((float)(num & 0x07E0) / 0x07E0) * 0x00FF00) & 0x00FF00)>> 8;
+ blueValue = ((PRUint32)(((float)(num & 0x001F) / 0x001F) * 0x0000FF) & 0x0000FF);
+
+ // now we have the right RGB values...
+ outBuffer[writeIndex++] = redValue;
+ outBuffer[writeIndex++] = greenValue;
+ outBuffer[writeIndex++] = blueValue;
+ numPixelsLeftInRow--;
+ pos += 2;
+ }
+ break;
+ case 32:
+ case 24:
+ if (pBitMapInfo->bmiHeader.biCompression == BI_BITFIELDS)
+ {
+ PRUint32 val = *((PRUint32*) (buffer + index) );
+ outBuffer[writeIndex++] = (val & colorMasks.red) >> colorMasks.redRightShift << colorMasks.redLeftShift;
+ outBuffer[writeIndex++] = (val & colorMasks.green) >> colorMasks.greenRightShift << colorMasks.greenLeftShift;
+ outBuffer[writeIndex++] = (val & colorMasks.blue) >> colorMasks.blueRightShift << colorMasks.blueLeftShift;
+ numPixelsLeftInRow--;
+ pos += 4; // we read in 4 bytes of data in order to process this pixel
+ }
+ else
+ {
+ outBuffer[writeIndex++] = buffer[index+2];
+ outBuffer[writeIndex++] = buffer[index+1];
+ outBuffer[writeIndex++] = buffer[index];
+ numPixelsLeftInRow--;
+ pos += bytesPerPixel; // 3 bytes for 24 bit data, 4 bytes for 32 bit data (we skip over the 4th byte)...
+ }
+ break;
+ default:
+ // This is probably the wrong place to check this...
+ return NS_ERROR_FAILURE;
+ }
+
+ index += bytesPerPixel; // increment our loop counter
+
+ if (!numPixelsLeftInRow)
+ {
+ if (rowSize != pos)
+ {
+ // advance index to skip over remaining padding bytes
+ index += (rowSize - pos);
+ }
+ numPixelsLeftInRow = pBitMapInfo->bmiHeader.biWidth;
+ pos = 0;
+ }
+
+ } // while we still have bytes to process
+ }
+
+ PR_LOG(gJPEGEncoderLog, PR_LOG_ALWAYS, ("exiting nsJPEGEncoder::ConvertColorBitMap"));
+
+ return NS_OK;
+}
+
+static void calcBitmask(PRUint32 aMask, PRUint8& aBegin, PRUint8& aLength)
+{
+ // find the rightmost 1
+ PRUint8 pos;
+ PRBool started = PR_FALSE;
+ aBegin = aLength = 0;
+ for (pos = 0; pos <= 31; pos++)
+ {
+ if (!started && (aMask & (1 << pos)))
+ {
+ aBegin = pos;
+ started = PR_TRUE;
+ }
+ else if (started && !(aMask & (1 << pos)))
+ {
+ aLength = pos - aBegin;
+ break;
+ }
+ }
+}
+
+void CalcBitShift(bitFields * aColorMask)
+{
+ PRUint8 begin, length;
+ // red
+ calcBitmask(aColorMask->red, begin, length);
+ aColorMask->redRightShift = begin;
+ aColorMask->redLeftShift = 8 - length;
+ // green
+ calcBitmask(aColorMask->green, begin, length);
+ aColorMask->greenRightShift = begin;
+ aColorMask->greenLeftShift = 8 - length;
+ // blue
+ calcBitmask(aColorMask->blue, begin, length);
+ aColorMask->blueRightShift = begin;
+ aColorMask->blueLeftShift = 8 - length;
+}
+
+/******************************************************************************/
+/* data destination manager method
+ Initialize the destination buffer the JPEG library should write compressed bits into
+*/
+METHODDEF(void)
+init_destination (j_compress_ptr jd)
+{
+ nsJPEGEncoder * encoder = getEncoderForCompressionInfoStruct(jd);
+ if (!encoder)
+ return;
+
+ if (!encoder->mBuffer)
+ {
+ encoder->mBuffer = (JOCTET *)PR_Malloc(OUTPUT_BUF_SIZE);
+ encoder->mBufferSize = OUTPUT_BUF_SIZE;
+ }
+
+ jd->dest->next_output_byte = encoder->mBuffer;
+ jd->dest->free_in_buffer = OUTPUT_BUF_SIZE;
+
+}
+
+// called by the JPEG library when our working output buffer is full. We need to take the bits and write
+// them to our destination stream. return true if buffer was dumped successfully otherwise return
+METHODDEF(boolean) empty_output_buffer (j_compress_ptr cinfo)
+{
+ nsJPEGEncoder * encoder = getEncoderForCompressionInfoStruct(cinfo);
+ if (!encoder)
+ return PR_TRUE;
+
+ PRUint32 written;
+ encoder->mOutputStream->Write((const char*) encoder->mBuffer, encoder->mBufferSize, &written);
+
+ // XXX: what do we do if we did write the # of bytes we thought we should write?
+
+ // now reset the jpeg pointers to the start of the buffer
+ cinfo->dest->next_output_byte = encoder->mBuffer;
+ cinfo->dest->free_in_buffer = OUTPUT_BUF_SIZE;
+
+ return PR_TRUE;
+}
+
+
+/* Terminate destination --- called by jpeg_finish_compress()() after all
+ * data has been written to clean up JPEG destination manager. NOT called by
+ * jpeg_abort() or jpeg_destroy().
+*/
+METHODDEF(void) term_destination (j_compress_ptr cinfo)
+{
+ nsJPEGEncoder * encoder = getEncoderForCompressionInfoStruct(cinfo);
+ if (!encoder)
+ return;
+
+ // flush whatever is left in the buffer
+ PRUint32 written;
+ encoder->mOutputStream->Write((const char*) encoder->mBuffer, encoder->mBufferSize - cinfo->dest->free_in_buffer , &written);
+
+ // if we were an asynch process making calls back to an observer, we would
+ // make the notification saying we were all done in this method. Since we are blocking,
+ // do nothing.
+}
+
+/* Override the standard error method in the IJG JPEG decoder code.
+ */
+METHODDEF(void) my_error_exit (j_common_ptr cinfo)
+{
+ nsresult error_code;
+ encoder_error_mgr *err = (encoder_error_mgr *) cinfo->err;
+
+ /* Convert error to a browser error code */
+ switch (cinfo->err->msg_code) {
+ case JERR_OUT_OF_MEMORY:
+ error_code = NS_ERROR_OUT_OF_MEMORY;
+ default:
+ error_code = NS_ERROR_FAILURE;
+ }
+
+#ifdef DEBUG
+ char buffer[JMSG_LENGTH_MAX];
+
+ /* Create the message */
+ (*cinfo->err->format_message) (cinfo, buffer);
+
+ fprintf(stderr, "JPEG decoding error:\n%s\n", buffer);
+#endif
+
+ /* Return control to the setjmp point. */
+ longjmp(err->setjmp_buffer, error_code);
+}
diff --git a/mozilla/modules/libpr0n/decoders/jpeg/nsJPEGEncoder.h b/mozilla/modules/libpr0n/decoders/jpeg/nsJPEGEncoder.h
new file mode 100755
index 00000000000..866f52a1df6
--- /dev/null
+++ b/mozilla/modules/libpr0n/decoders/jpeg/nsJPEGEncoder.h
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the JPEG image encoder.
+ *
+ * The Initial Developer of the Original Code is
+ * Scott MacGregor .
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsJPEGEncoder_h_
+#define nsJPEGEncoder_h_
+
+#include "imgIEncoder.h"
+#include "nsIOutputStream.h"
+
+#include // stgmedium
+
+#include "nsCOMPtr.h"
+
+extern "C" {
+#include "jpeglib.h"
+}
+
+#include
+
+#define NS_JPEGENCODER_CID \
+{ /* 13784154-1C73-4635-B75F-F1F21755E1C1 */ \
+ 0x13784154, \
+ 0x1c73, \
+ 0x4635, \
+ {0xb7, 0x5f, 0xf1, 0xf2, 0x17, 0x55, 0xe1, 0xc1} \
+}
+
+// helper structs for interacting with the jpeg library
+typedef struct {
+ struct jpeg_error_mgr pub; /* "public" fields for IJG library*/
+ jmp_buf setjmp_buffer; /* For handling catastropic errors */
+} encoder_error_mgr;
+
+
+class nsJPEGEncoder : public imgIEncoder
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_IMGIENCODER
+
+ nsJPEGEncoder();
+ virtual ~nsJPEGEncoder();
+
+public:
+ encoder_error_mgr mErr;
+ struct jpeg_compress_struct mInfo;
+
+ JOCTET *mBuffer; // temporary buffer the jpeg library writes the compressed data to before we write it out to disk
+ PRUint32 mBufferLen; // amount of data currently in mBuffer
+ PRUint32 mBufferSize; // size in bytes what mBuffer was created with
+ nsCOMPtr mOutputStream;
+
+protected:
+ nsresult initCompressionInfo();
+};
+
+#endif // nsJPEGEncoder_h_
diff --git a/mozilla/modules/libpr0n/public/Makefile.in b/mozilla/modules/libpr0n/public/Makefile.in
index 9af5774fa1a..ab8f11cd87e 100644
--- a/mozilla/modules/libpr0n/public/Makefile.in
+++ b/mozilla/modules/libpr0n/public/Makefile.in
@@ -56,6 +56,7 @@ XPIDLSRCS = \
imgILoad.idl \
imgILoader.idl \
imgIRequest.idl \
+ imgIEncoder.idl \
$(NULL)
include $(topsrcdir)/config/rules.mk
diff --git a/mozilla/modules/libpr0n/public/imgIEncoder.idl b/mozilla/modules/libpr0n/public/imgIEncoder.idl
new file mode 100755
index 00000000000..b073885918e
--- /dev/null
+++ b/mozilla/modules/libpr0n/public/imgIEncoder.idl
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is image encoder interface.
+ *
+ * The Initial Developer of the Original Code is Scott MacGregor .
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+interface nsIClipboardImage;
+interface nsIFile;
+
+/**
+ * imgIEncoder interface
+ * Currently this is a very specific encoder designed to encode a native clipboard image as a JPEG out to disk.
+ * It is not intended to be a generic image encoder.
+ *
+ */
+
+[scriptable, uuid(CCC5B3AD-3E67-4e3d-97E1-B06B2E96FEF8)]
+interface imgIEncoder : nsISupports
+{
+ /**
+ Encode a native clipboard image
+ **/
+
+ void encodeClipboardImage(in nsIClipboardImage aClipboardImage, out nsIFile aImageFile);
+
+};
diff --git a/mozilla/widget/public/nsIClipboard.idl b/mozilla/widget/public/nsIClipboard.idl
index e505703c9e4..407ae780240 100644
--- a/mozilla/widget/public/nsIClipboard.idl
+++ b/mozilla/widget/public/nsIClipboard.idl
@@ -105,6 +105,22 @@ interface nsIClipboard : nsISupports
boolean supportsSelectionClipboard ( ) ;
};
+// Interface to a native image format such as the format stored on the clipboard
+[scriptable, uuid(DB21EB6C-AEBB-4d16-94EC-BCD8BBF513AE)]
+interface nsIClipboardImage : nsISupports
+{
+ // the idl compiler complains if these two methods are scriptable. need to figure out why
+ [noscript] void setNativeImage(in voidPtr aNativeImageData);
+
+ // caller must later call releaseNativeImage to release their reference to the image. nsIClipboardImage
+ // will keep its own reference until it is destroyed.
+ [noscript] void getNativeImage(in voidPtr aNativeImageData);
+
+ // releaseNativeImage should only be called if you used getNativeImageData. You should pass in the same
+ // object to both methods. (this routine exists so callers do not have to link in urlmon.lib just to release
+ // the stgmedium object on windows).
+ [noscript] void releaseNativeImage(in voidPtr aNativeImageData);
+};
%{ C++
diff --git a/mozilla/widget/public/nsWidgetsCID.h b/mozilla/widget/public/nsWidgetsCID.h
index 59821be5dd3..353d3e061b3 100644
--- a/mozilla/widget/public/nsWidgetsCID.h
+++ b/mozilla/widget/public/nsWidgetsCID.h
@@ -154,6 +154,10 @@
#define NS_CLIPBOARD_CID \
{ 0x8b5314ba, 0xdb01, 0x11d2, { 0x96, 0xce, 0x0, 0x60, 0xb0, 0xfb, 0x99, 0x56 } }
+// {B655157E-D264-4d24-B9C9-1E213276AB5A}
+#define NS_CLIPBOARDIMAGE_CID \
+{ 0xb655157e, 0xd264, 0x4d24, { 0xb9, 0xc9, 0x1e, 0x21, 0x32, 0x76, 0xab, 0x5a } }
+
// {77221D5A-1DD2-11B2-8C69-C710F15D2ED5}
#define NS_CLIPBOARDHELPER_CID \
{ 0x77221d5a, 0x1dd2, 0x11b2, { 0x8c, 0x69, 0xc7, 0x10, 0xf1, 0x5d, 0x2e, 0xd5 } }
diff --git a/mozilla/widget/src/build/Makefile.in b/mozilla/widget/src/build/Makefile.in
index 8c62be6a1a4..8c38bc44f26 100644
--- a/mozilla/widget/src/build/Makefile.in
+++ b/mozilla/widget/src/build/Makefile.in
@@ -78,6 +78,10 @@ ifneq ($(OS_ARCH), WINCE)
OS_LIBS += $(call EXPAND_LIBNAME, comctl32 comdlg32 shell32 gdi32 imm32 )
endif
+ifndef GNU_CC
+OS_LIBS += $(call EXPAND_LIBNAME, urlmon)
+endif
+
SHARED_LIBRARY_LIBS = \
$(DIST)/lib/$(LIB_PREFIX)widget_windows.$(LIB_SUFFIX) \
$(DIST)/lib/$(LIB_PREFIX)xpwidgets_s.$(LIB_SUFFIX) \
diff --git a/mozilla/widget/src/build/nsWinWidgetFactory.cpp b/mozilla/widget/src/build/nsWinWidgetFactory.cpp
index e99f0106554..26d7d2fa90a 100644
--- a/mozilla/widget/src/build/nsWinWidgetFactory.cpp
+++ b/mozilla/widget/src/build/nsWinWidgetFactory.cpp
@@ -70,6 +70,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboardHelper)
#ifndef WINCE
NS_GENERIC_FACTORY_CONSTRUCTOR(nsFilePicker)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSound)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboardImage)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDragService)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsBidiKeyboard)
#endif
@@ -109,6 +110,10 @@ static const nsModuleComponentInfo components[] =
// "@mozilla.org/widget/sound/win;1"
"@mozilla.org/sound;1",
nsSoundConstructor },
+ { "nsClipboardImage",
+ NS_CLIPBOARDIMAGE_CID,
+ "@mozilla.org/widget/clipboardimage;1",
+ nsClipboardImageConstructor },
{ "Drag Service",
NS_DRAGSERVICE_CID,
// "@mozilla.org/widget/dragservice/win;1",
diff --git a/mozilla/widget/src/windows/nsClipboard.cpp b/mozilla/widget/src/windows/nsClipboard.cpp
index 998649ef437..2a6e7bc77f2 100644
--- a/mozilla/widget/src/windows/nsClipboard.cpp
+++ b/mozilla/widget/src/windows/nsClipboard.cpp
@@ -60,8 +60,9 @@
#include "nsPrimitiveHelpers.h"
#include "nsImageClipboard.h"
#include "nsIWidget.h"
-#include "nsIComponentManager.h"
+#include "nsComponentManagerUtils.h"
#include "nsWidgetsCID.h"
+#include "nsGfxCIID.h"
#include "nsCRT.h"
#include "nsNetUtil.h"
@@ -112,7 +113,8 @@ UINT nsClipboard::GetFormat(const char* aMimeStr)
else if (strcmp(aMimeStr, kUnicodeMime) == 0)
format = CF_UNICODETEXT;
#ifndef WINCE
- else if (strcmp(aMimeStr, kJPEGImageMime) == 0)
+ else if (strcmp(aMimeStr, kJPEGImageMime) == 0 ||
+ strcmp(aMimeStr, kNativeImageMime) == 0)
format = CF_DIB;
else if (strcmp(aMimeStr, kFileMime) == 0 ||
strcmp(aMimeStr, kFilePromiseMime) == 0)
@@ -478,20 +480,16 @@ nsresult nsClipboard::GetNativeDataOffClipboard(IDataObject * aDataObject, UINT
#ifndef WINCE
case CF_DIB :
{
- HGLOBAL hGlobal = stm.hGlobal;
- BYTE * pGlobal = (BYTE *) GlobalLock (hGlobal) ;
- BITMAPV4HEADER * header = (BITMAPV4HEADER *)pGlobal;
+ nsIClipboardImage * nativeImageWrapper = nsnull; // don't use a nsCOMPtr here
+ result = CallCreateInstance("@mozilla.org/widget/clipboardimage;1", &nativeImageWrapper);
- nsImageFromClipboard converter ( header );
- nsIImage* image;
- converter.GetImage ( &image ); // addrefs for us, don't release
- if ( image ) {
- *aData = image;
- *aLen = sizeof(nsIImage*);
+ if (nativeImageWrapper)
+ {
+ nativeImageWrapper->SetNativeImage((void *) &stm);
+ *aData = nativeImageWrapper; // note that we never release our ref to nativeImageWrapper. We pass it on to the owner of *aData
+ *aLen = sizeof(nsIClipboardImage *);
result = NS_OK;
}
-
- GlobalUnlock (hGlobal) ;
} break;
case CF_HDROP :
@@ -651,6 +649,11 @@ nsresult nsClipboard::GetDataFromDataObject(IDataObject * aDataObject,
else
continue; // something wrong with this flavor, keep looking for other data
}
+ else if ( strcmp(flavorStr, kJPEGImageMime) == 0 || strcmp(flavorStr, kNativeImageMime) == 0) {
+ // we have image data. We don't want to attempt any conversions here
+ nsIClipboardImage * image = NS_REINTERPRET_CAST(nsIClipboardImage*, data);
+ genericDataWrapper = do_QueryInterface(image);
+ }
else {
// we probably have some form of text. The DOM only wants LF, so convert from Win32 line
// endings to DOM line endings.
@@ -664,6 +667,8 @@ nsresult nsClipboard::GetDataFromDataObject(IDataObject * aDataObject,
NS_ASSERTION ( genericDataWrapper, "About to put null data into the transferable" );
aTransferable->SetTransferData(flavorStr, genericDataWrapper, dataLen);
+ // don't free data if it is an image object
+ if (strcmp(flavorStr, kJPEGImageMime) && strcmp(flavorStr, kNativeImageMime))
nsMemory::Free ( NS_REINTERPRET_CAST(char*, data) );
res = NS_OK;
@@ -909,3 +914,75 @@ NS_IMETHODIMP nsClipboard::HasDataMatchingFlavors(nsISupportsArray *aFlavorList,
return NS_OK;
}
+
+
+nsClipboardImage::nsClipboardImage()
+{
+ memset(&mStgMedium, 0, sizeof(STGMEDIUM));
+}
+
+nsClipboardImage :: ~nsClipboardImage()
+{
+ if(mStgMedium.hGlobal)
+ ReleaseStgMedium(&mStgMedium);
+}
+
+NS_IMPL_ISUPPORTS1(nsClipboardImage, nsIClipboardImage)
+
+static HGLOBAL CopyGlobalMemory(HGLOBAL hSource)
+{
+ if (hSource == NULL)
+ return NULL;
+
+ DWORD nSize = (DWORD)::GlobalSize(hSource);
+ HGLOBAL hDest = ::GlobalAlloc(GMEM_SHARE | GMEM_MOVEABLE, nSize);
+ if (hDest == NULL)
+ return NULL;
+
+ // copy the bits
+ LPVOID lpSource = ::GlobalLock(hSource);
+ LPVOID lpDest = ::GlobalLock(hDest);
+ memcpy(lpDest, lpSource, nSize);
+ ::GlobalUnlock(hDest);
+ ::GlobalUnlock(hSource);
+
+ return hDest;
+}
+
+NS_IMETHODIMP nsClipboardImage::SetNativeImage(void * aNativeImageData)
+{
+ STGMEDIUM * stg = (STGMEDIUM *)aNativeImageData;
+
+ HGLOBAL hDest = CopyGlobalMemory(stg->hGlobal);
+ if (!hDest)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ if(mStgMedium.hGlobal)
+ ReleaseStgMedium(&mStgMedium);
+
+ mStgMedium = *stg;
+ mStgMedium.hGlobal = hDest;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsClipboardImage::GetNativeImage(void * aNativeImageData)
+{
+ // the caller should be passing in a STGMEDIUM object which we can copy into
+ HGLOBAL hDest = CopyGlobalMemory(mStgMedium.hGlobal);
+ if (!hDest)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ STGMEDIUM * stg = (STGMEDIUM *)aNativeImageData;
+
+ *stg = mStgMedium;
+ stg->hGlobal = hDest;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsClipboardImage::ReleaseNativeImage(void * aNativeImageData)
+{
+ STGMEDIUM * stg = (STGMEDIUM *) aNativeImageData;
+ if (stg)
+ ReleaseStgMedium(stg);
+ return NS_OK;
+}
diff --git a/mozilla/widget/src/windows/nsClipboard.h b/mozilla/widget/src/windows/nsClipboard.h
index 9b20046ffe4..3a26b8e7ffe 100644
--- a/mozilla/widget/src/windows/nsClipboard.h
+++ b/mozilla/widget/src/windows/nsClipboard.h
@@ -42,6 +42,7 @@
#include "nsIObserver.h"
#include "nsIURI.h"
#include
+#include
class nsITransferable;
class nsIClipboardOwner;
@@ -100,6 +101,19 @@ protected:
};
+class nsClipboardImage : public nsIClipboardImage {
+public:
+ nsClipboardImage();
+ ~nsClipboardImage();
+
+ NS_DECL_ISUPPORTS
+
+ NS_DECL_NSICLIPBOARDIMAGE
+
+protected:
+ STGMEDIUM mStgMedium;
+};
+
#define SET_FORMATETC(fe, cf, td, asp, li, med) \
{\
(fe).cfFormat=cf;\