Partial implementation for OLEPictureImpl_Save.

This commit is contained in:
Alex Villacís Lasso 2004-09-22 04:04:03 +00:00 committed by Alexandre Julliard
parent aadffd1f35
commit 2d02afbc09
1 changed files with 324 additions and 4 deletions

View File

@ -133,6 +133,9 @@ typedef struct OLEPictureImpl {
/* data */
void* data;
int datalen;
BOOL bIsDirty; /* Set to TRUE if picture has changed */
unsigned int loadtime_magic; /* If a length header was found, saves value */
unsigned int loadtime_format; /* for PICTYPE_BITMAP only, keeps track of image format (GIF/BMP/JPEG) */
} OLEPictureImpl;
/*
@ -225,6 +228,9 @@ static OLEPictureImpl* OLEPictureImpl_Construct(LPPICTDESC pictDesc, BOOL fOwn)
newObject->keepOrigFormat = TRUE;
newObject->hbmMask = NULL;
newObject->loadtime_magic = 0xdeadbeef;
newObject->loadtime_format = 0;
newObject->bIsDirty = FALSE;
if (pictDesc) {
if(pictDesc->cbSizeofstruct != sizeof(PICTDESC)) {
@ -671,6 +677,7 @@ static HRESULT WINAPI OLEPictureImpl_PictureChanged(IPicture *iface)
OLEPictureImpl *This = (OLEPictureImpl *)iface;
TRACE("(%p)->()\n", This);
OLEPicture_SendNotify(This,DISPID_PICT_HANDLE);
This->bIsDirty = TRUE;
return S_OK;
}
@ -813,7 +820,7 @@ static HRESULT WINAPI OLEPictureImpl_GetClassID(
{
ICOM_THIS_From_IPersistStream(IPicture, iface);
FIXME("(%p),stub!\n",This);
return E_NOTIMPL;
return E_FAIL;
}
/************************************************************************
@ -1365,6 +1372,7 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
break;
}
}
This->bIsDirty = FALSE;
/* FIXME: this notify is not really documented */
if (hr==S_OK)
@ -1372,12 +1380,324 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
return hr;
}
static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength);
static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLength);
static HRESULT WINAPI OLEPictureImpl_Save(
IPersistStream* iface,IStream*pStm,BOOL fClearDirty)
{
ICOM_THIS_From_IPersistStream(IPicture, iface);
FIXME("(%p,%p,%d),stub!\n",This,pStm,fClearDirty);
return E_NOTIMPL;
HRESULT hResult = E_NOTIMPL;
void * pIconData;
unsigned int iDataSize;
ULONG dummy;
int iSerializeResult = 0;
ICOM_THIS_From_IPersistStream(OLEPictureImpl, iface);
switch (This->desc.picType) {
case PICTYPE_ICON:
if (This->bIsDirty) {
if (serializeIcon(This->desc.u.icon.hicon, &pIconData, &iDataSize)) {
if (This->loadtime_magic != 0xdeadbeef) {
DWORD header[2];
header[0] = This->loadtime_magic;
header[1] = iDataSize;
IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
}
IStream_Write(pStm, pIconData, iDataSize, &dummy);
HeapFree(GetProcessHeap(), 0, This->data);
This->data = pIconData;
This->datalen = iDataSize;
hResult = S_OK;
} else {
FIXME("(%p,%p,%d), unable to serializeIcon()!\n",This,pStm,fClearDirty);
hResult = E_FAIL;
}
} else {
if (This->loadtime_magic != 0xdeadbeef) {
DWORD header[2];
header[0] = This->loadtime_magic;
header[1] = This->datalen;
IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
}
IStream_Write(pStm, This->data, This->datalen, &dummy);
hResult = S_OK;
}
break;
case PICTYPE_BITMAP:
if (This->bIsDirty) {
switch (This->keepOrigFormat ? This->loadtime_format : 0x4d42) {
case 0x4d42:
iSerializeResult = serializeBMP(This->desc.u.bmp.hbitmap, &pIconData, &iDataSize);
break;
case 0xd8ff:
FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This,pStm,fClearDirty);
break;
case 0x4947:
FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This,pStm,fClearDirty);
break;
default:
FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This,pStm,fClearDirty);
break;
}
if (iSerializeResult) {
/*
if (This->loadtime_magic != 0xdeadbeef) {
*/
if (1) {
DWORD header[2];
header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
header[1] = iDataSize;
IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
}
IStream_Write(pStm, pIconData, iDataSize, &dummy);
HeapFree(GetProcessHeap(), 0, This->data);
This->data = pIconData;
This->datalen = iDataSize;
hResult = S_OK;
}
} else {
/*
if (This->loadtime_magic != 0xdeadbeef) {
*/
if (1) {
DWORD header[2];
header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
header[1] = This->datalen;
IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
}
IStream_Write(pStm, This->data, This->datalen, &dummy);
hResult = S_OK;
}
break;
case PICTYPE_METAFILE:
FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This,pStm,fClearDirty);
break;
case PICTYPE_ENHMETAFILE:
FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This,pStm,fClearDirty);
break;
default:
FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This,pStm,fClearDirty);
break;
}
if (hResult == S_OK && fClearDirty) This->bIsDirty = FALSE;
return hResult;
}
static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLength)
{
int iSuccess = 0;
HDC hDC;
BITMAPINFO * pInfoBitmap;
int iNumPaletteEntries;
unsigned char * pPixelData;
BITMAPFILEHEADER * pFileHeader;
BITMAPINFO * pInfoHeader;
pInfoBitmap = (BITMAPINFO *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
/* Find out bitmap size and padded length */
hDC = GetDC(0);
pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
GetDIBits(hDC, hBitmap, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
/* Fetch bitmap palette & pixel data */
pPixelData = (unsigned char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
pInfoBitmap->bmiHeader.biSizeImage);
GetDIBits(hDC, hBitmap, 0, pInfoBitmap->bmiHeader.biHeight, pPixelData, pInfoBitmap, DIB_RGB_COLORS);
/* Calculate the total length required for the BMP data */
if (pInfoBitmap->bmiHeader.biClrUsed != 0) iNumPaletteEntries = pInfoBitmap->bmiHeader.biClrUsed;
else if (pInfoBitmap->bmiHeader.biBitCount <= 8) iNumPaletteEntries = 1 << pInfoBitmap->bmiHeader.biBitCount;
else iNumPaletteEntries = 0;
*pLength =
sizeof(BITMAPFILEHEADER) +
sizeof(BITMAPINFOHEADER) +
iNumPaletteEntries * sizeof(RGBQUAD) +
pInfoBitmap->bmiHeader.biSizeImage;
*ppBuffer = (void *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pLength);
/* Fill the BITMAPFILEHEADER */
pFileHeader = (BITMAPFILEHEADER *)(*ppBuffer);
pFileHeader->bfType = 0x4d42;
pFileHeader->bfSize = *pLength;
pFileHeader->bfOffBits =
sizeof(BITMAPFILEHEADER) +
sizeof(BITMAPINFOHEADER) +
iNumPaletteEntries * sizeof(RGBQUAD);
/* Fill the BITMAPINFOHEADER and the palette data */
pInfoHeader = (BITMAPINFO *)((unsigned char *)(*ppBuffer) + sizeof(BITMAPFILEHEADER));
memcpy(pInfoHeader, pInfoBitmap, sizeof(BITMAPINFOHEADER) + iNumPaletteEntries * sizeof(RGBQUAD));
memcpy(
(unsigned char *)(*ppBuffer) +
sizeof(BITMAPFILEHEADER) +
sizeof(BITMAPINFOHEADER) +
iNumPaletteEntries * sizeof(RGBQUAD),
pPixelData, pInfoBitmap->bmiHeader.biSizeImage);
iSuccess = 1;
HeapFree(GetProcessHeap(), 0, pPixelData);
HeapFree(GetProcessHeap(), 0, pInfoBitmap);
return iSuccess;
}
static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength)
{
ICONINFO infoIcon;
int iSuccess = 0;
*ppBuffer = NULL; *pLength = 0;
if (GetIconInfo(hIcon, &infoIcon)) {
HDC hDC;
BITMAPINFO * pInfoBitmap;
unsigned char * pIconData = NULL;
unsigned int iDataSize = 0;
pInfoBitmap = (BITMAPINFO *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
/* Find out icon size */
hDC = GetDC(0);
pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
GetDIBits(hDC, infoIcon.hbmColor, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
if (1) {
/* Auxiliary pointers */
CURSORICONFILEDIR * pIconDir;
CURSORICONFILEDIRENTRY * pIconEntry;
BITMAPINFOHEADER * pIconBitmapHeader;
unsigned int iOffsetPalette;
unsigned int iOffsetColorData;
unsigned int iOffsetMaskData;
unsigned int iLengthScanLineColor;
unsigned int iLengthScanLineMask;
unsigned int iNumEntriesPalette;
iLengthScanLineMask = ((pInfoBitmap->bmiHeader.biWidth + 31) >> 5) << 2;
iLengthScanLineColor = ((pInfoBitmap->bmiHeader.biWidth * pInfoBitmap->bmiHeader.biBitCount + 31) >> 5) << 2;
/*
FIXME("DEBUG: bitmap size is %d x %d\n",
pInfoBitmap->bmiHeader.biWidth,
pInfoBitmap->bmiHeader.biHeight);
FIXME("DEBUG: bitmap bpp is %d\n",
pInfoBitmap->bmiHeader.biBitCount);
FIXME("DEBUG: bitmap nplanes is %d\n",
pInfoBitmap->bmiHeader.biPlanes);
FIXME("DEBUG: bitmap biSizeImage is %lu\n",
pInfoBitmap->bmiHeader.biSizeImage);
*/
/* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */
iDataSize += 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY) + sizeof(BITMAPINFOHEADER);
pIconData = (unsigned char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, iDataSize);
/* Fill out the CURSORICONFILEDIR */
pIconDir = (CURSORICONFILEDIR *)pIconData;
pIconDir->idType = 1;
pIconDir->idCount = 1;
/* Fill out the CURSORICONFILEDIRENTRY */
pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
pIconEntry->bWidth = (unsigned char)pInfoBitmap->bmiHeader.biWidth;
pIconEntry->bHeight = (unsigned char)pInfoBitmap->bmiHeader.biHeight;
pIconEntry->bColorCount =
(pInfoBitmap->bmiHeader.biBitCount < 8)
? 1 << pInfoBitmap->bmiHeader.biBitCount
: 0;
pIconEntry->xHotspot = pInfoBitmap->bmiHeader.biPlanes;
pIconEntry->yHotspot = pInfoBitmap->bmiHeader.biBitCount;
pIconEntry->dwDIBSize = 0;
pIconEntry->dwDIBOffset = 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY);
/* Fill out the BITMAPINFOHEADER */
pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
memcpy(pIconBitmapHeader, &pInfoBitmap->bmiHeader, sizeof(BITMAPINFOHEADER));
/* Find out whether a palette exists for the bitmap */
if ( (pInfoBitmap->bmiHeader.biBitCount == 16 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)
|| (pInfoBitmap->bmiHeader.biBitCount == 24)
|| (pInfoBitmap->bmiHeader.biBitCount == 32 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)) {
iNumEntriesPalette = pInfoBitmap->bmiHeader.biClrUsed;
} else if ((pInfoBitmap->bmiHeader.biBitCount == 16 || pInfoBitmap->bmiHeader.biBitCount == 32)
&& pInfoBitmap->bmiHeader.biCompression == BI_BITFIELDS) {
iNumEntriesPalette = 3;
} else if (pInfoBitmap->bmiHeader.biBitCount <= 8) {
iNumEntriesPalette = 1 << pInfoBitmap->bmiHeader.biBitCount;
} else {
iNumEntriesPalette = 0;
}
/* Add bitmap size and header size to icon data size. */
iOffsetPalette = iDataSize;
iDataSize += iNumEntriesPalette * sizeof(DWORD);
iOffsetColorData = iDataSize;
iDataSize += pIconBitmapHeader->biSizeImage;
iOffsetMaskData = iDataSize;
iDataSize += pIconBitmapHeader->biHeight * iLengthScanLineMask;
pIconBitmapHeader->biSizeImage += pIconBitmapHeader->biHeight * iLengthScanLineMask;
pIconBitmapHeader->biHeight *= 2;
pIconData = (unsigned char *)HeapReAlloc(GetProcessHeap(), 0, pIconData, iDataSize);
pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
pIconEntry->dwDIBSize = iDataSize - (3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
/* Get the actual bitmap data from the icon bitmap */
GetDIBits(hDC, infoIcon.hbmColor, 0, pInfoBitmap->bmiHeader.biHeight,
pIconData + iOffsetColorData, pInfoBitmap, DIB_RGB_COLORS);
if (iNumEntriesPalette > 0) {
memcpy(pIconData + iOffsetPalette, pInfoBitmap->bmiColors,
iNumEntriesPalette * sizeof(RGBQUAD));
}
/* Reset all values so that GetDIBits call succeeds */
memset(pIconData + iOffsetMaskData, 0, iDataSize - iOffsetMaskData);
memset(pInfoBitmap, 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
/*
if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS)
&& GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight,
pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) {
printf("ERROR: unable to get bitmap mask (error %lu)\n",
GetLastError());
}
*/
GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight, pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS);
/* Write out everything produced so far to the stream */
*ppBuffer = pIconData; *pLength = iDataSize;
iSuccess = 1;
} else {
/*
printf("ERROR: unable to get bitmap information via GetDIBits() (error %lu)\n",
GetLastError());
*/
}
/*
Remarks (from MSDN entry on GetIconInfo):
GetIconInfo creates bitmaps for the hbmMask and hbmColor
members of ICONINFO. The calling application must manage
these bitmaps and delete them when they are no longer
necessary.
*/
if (hDC) ReleaseDC(0, hDC);
DeleteObject(infoIcon.hbmMask);
if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
HeapFree(GetProcessHeap(), 0, pInfoBitmap);
} else {
printf("ERROR: Unable to get icon information (error %lu)\n",
GetLastError());
}
return iSuccess;
}
static HRESULT WINAPI OLEPictureImpl_GetSizeMax(