📄 olepicture.c
字号:
/*
* OLE Picture object
*
* Implementation of OLE IPicture and related interfaces
*
* Copyright 2000 Huw D M Davies for CodeWeavers.
* Copyright 2001 Marcus Meissner
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
* BUGS
*
* Support PICTYPE_BITMAP and PICTYPE_ICON, altough only bitmaps very well..
* Lots of methods are just stubs.
*
*
* NOTES (or things that msdn doesn't tell you)
*
* The width and height properties are returned in HIMETRIC units (0.01mm)
* IPicture::Render also uses these to select a region of the src picture.
* A bitmap's size is converted into these units by using the screen resolution
* thus an 8x8 bitmap on a 96dpi screen has a size of 212x212 (8/96 * 2540).
*
*/
#include "config.h"
#include "wine/port.h"
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
/* Must be before wine includes, the header has things conflicting with
* WINE headers.
*/
#define COBJMACROS
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "winerror.h"
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "ole2.h"
#include "olectl.h"
#include "oleauto.h"
#include "connpt.h"
#include "urlmon.h"
#include "wine/debug.h"
#include "wine/unicode.h"
#include "wine/wingdi16.h"
#ifdef SONAME_LIBJPEG
/* This is a hack, so jpeglib.h does not redefine INT32 and the like*/
#define XMD_H
#define UINT8 JPEG_UINT8
#define UINT16 JPEG_UINT16
#undef FAR
#define boolean jpeg_boolean
# include <jpeglib.h>
#undef jpeg_boolean
#undef UINT16
#endif
#ifdef HAVE_PNG_H
#undef FAR
#include <png.h>
#endif
#include "ungif.h"
WINE_DEFAULT_DEBUG_CHANNEL(ole);
#include "pshpack1.h"
typedef struct {
BYTE bWidth;
BYTE bHeight;
BYTE bColorCount;
BYTE bReserved;
WORD xHotspot;
WORD yHotspot;
DWORD dwDIBSize;
DWORD dwDIBOffset;
} CURSORICONFILEDIRENTRY;
typedef struct
{
WORD idReserved;
WORD idType;
WORD idCount;
CURSORICONFILEDIRENTRY idEntries[1];
} CURSORICONFILEDIR;
#include "poppack.h"
/*************************************************************************
* Declaration of implementation class
*/
typedef struct OLEPictureImpl {
/*
* IPicture handles IUnknown
*/
const IPictureVtbl *lpVtbl;
const IDispatchVtbl *lpvtblIDispatch;
const IPersistStreamVtbl *lpvtblIPersistStream;
const IConnectionPointContainerVtbl *lpvtblIConnectionPointContainer;
/* Object reference count */
LONG ref;
/* We own the object and must destroy it ourselves */
BOOL fOwn;
/* Picture description */
PICTDESC desc;
/* These are the pixel size of a bitmap */
DWORD origWidth;
DWORD origHeight;
/* And these are the size of the picture converted into HIMETRIC units */
OLE_XSIZE_HIMETRIC himetricWidth;
OLE_YSIZE_HIMETRIC himetricHeight;
IConnectionPoint *pCP;
BOOL keepOrigFormat;
HDC hDCCur;
/* Bitmap transparency mask */
HBITMAP hbmMask;
HBITMAP hbmXor;
COLORREF rgbTrans;
/* 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;
/*
* Macros to retrieve pointer to IUnknown (IPicture) from the other VTables.
*/
static inline OLEPictureImpl *impl_from_IDispatch( IDispatch *iface )
{
return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIDispatch));
}
static inline OLEPictureImpl *impl_from_IPersistStream( IPersistStream *iface )
{
return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIPersistStream));
}
static inline OLEPictureImpl *impl_from_IConnectionPointContainer( IConnectionPointContainer *iface )
{
return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIConnectionPointContainer));
}
/*
* Predeclare VTables. They get initialized at the end.
*/
static const IPictureVtbl OLEPictureImpl_VTable;
static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable;
static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable;
static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable;
/***********************************************************************
* Implementation of the OLEPictureImpl class.
*/
static void OLEPictureImpl_SetBitmap(OLEPictureImpl*This) {
BITMAP bm;
HDC hdcRef;
TRACE("bitmap handle %p\n", This->desc.u.bmp.hbitmap);
if(GetObjectA(This->desc.u.bmp.hbitmap, sizeof(bm), &bm) != sizeof(bm)) {
ERR("GetObject fails\n");
return;
}
This->origWidth = bm.bmWidth;
This->origHeight = bm.bmHeight;
/* The width and height are stored in HIMETRIC units (0.01 mm),
so we take our pixel width divide by pixels per inch and
multiply by 25.4 * 100 */
/* Should we use GetBitmapDimension if available? */
hdcRef = CreateCompatibleDC(0);
This->himetricWidth =(bm.bmWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
This->himetricHeight=(bm.bmHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
DeleteDC(hdcRef);
}
static void OLEPictureImpl_SetIcon(OLEPictureImpl * This)
{
ICONINFO infoIcon;
TRACE("icon handle %p\n", This->desc.u.icon.hicon);
if (GetIconInfo(This->desc.u.icon.hicon, &infoIcon)) {
HDC hdcRef;
BITMAP bm;
TRACE("bitmap handle for icon is %p\n", infoIcon.hbmColor);
if(GetObjectA(infoIcon.hbmColor ? infoIcon.hbmColor : infoIcon.hbmMask, sizeof(bm), &bm) != sizeof(bm)) {
ERR("GetObject fails on icon bitmap\n");
return;
}
This->origWidth = bm.bmWidth;
This->origHeight = infoIcon.hbmColor ? bm.bmHeight : bm.bmHeight / 2;
/* see comment on HIMETRIC on OLEPictureImpl_SetBitmap() */
hdcRef = GetDC(0);
This->himetricWidth = (This->origWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
This->himetricHeight= (This->origHeight *2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
ReleaseDC(0, hdcRef);
DeleteObject(infoIcon.hbmMask);
if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
} else {
ERR("GetIconInfo() fails on icon %p\n", This->desc.u.icon.hicon);
}
}
/************************************************************************
* OLEPictureImpl_Construct
*
* This method will construct a new instance of the OLEPictureImpl
* class.
*
* The caller of this method must release the object when it's
* done with it.
*/
static OLEPictureImpl* OLEPictureImpl_Construct(LPPICTDESC pictDesc, BOOL fOwn)
{
OLEPictureImpl* newObject = 0;
if (pictDesc)
TRACE("(%p) type = %d\n", pictDesc, pictDesc->picType);
/*
* Allocate space for the object.
*/
newObject = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(OLEPictureImpl));
if (newObject==0)
return newObject;
/*
* Initialize the virtual function table.
*/
newObject->lpVtbl = &OLEPictureImpl_VTable;
newObject->lpvtblIDispatch = &OLEPictureImpl_IDispatch_VTable;
newObject->lpvtblIPersistStream = &OLEPictureImpl_IPersistStream_VTable;
newObject->lpvtblIConnectionPointContainer = &OLEPictureImpl_IConnectionPointContainer_VTable;
newObject->pCP = NULL;
CreateConnectionPoint((IUnknown*)newObject,&IID_IPropertyNotifySink,&newObject->pCP);
if (!newObject->pCP)
{
HeapFree(GetProcessHeap(), 0, newObject);
return NULL;
}
/*
* Start with one reference count. The caller of this function
* must release the interface pointer when it is done.
*/
newObject->ref = 1;
newObject->hDCCur = 0;
newObject->fOwn = fOwn;
/* dunno about original value */
newObject->keepOrigFormat = TRUE;
newObject->hbmMask = NULL;
newObject->hbmXor = NULL;
newObject->loadtime_magic = 0xdeadbeef;
newObject->loadtime_format = 0;
newObject->bIsDirty = FALSE;
if (pictDesc) {
memcpy(&newObject->desc, pictDesc, sizeof(PICTDESC));
switch(pictDesc->picType) {
case PICTYPE_BITMAP:
OLEPictureImpl_SetBitmap(newObject);
break;
case PICTYPE_METAFILE:
TRACE("metafile handle %p\n", pictDesc->u.wmf.hmeta);
newObject->himetricWidth = pictDesc->u.wmf.xExt;
newObject->himetricHeight = pictDesc->u.wmf.yExt;
break;
case PICTYPE_NONE:
/* not sure what to do here */
newObject->himetricWidth = newObject->himetricHeight = 0;
break;
case PICTYPE_ICON:
OLEPictureImpl_SetIcon(newObject);
break;
case PICTYPE_ENHMETAFILE:
default:
FIXME("Unsupported type %d\n", pictDesc->picType);
newObject->himetricWidth = newObject->himetricHeight = 0;
break;
}
} else {
newObject->desc.picType = PICTYPE_UNINITIALIZED;
}
TRACE("returning %p\n", newObject);
return newObject;
}
/************************************************************************
* OLEPictureImpl_Destroy
*
* This method is called by the Release method when the reference
* count goes down to 0. It will free all resources used by
* this object. */
static void OLEPictureImpl_Destroy(OLEPictureImpl* Obj)
{
TRACE("(%p)\n", Obj);
if (Obj->pCP)
IConnectionPoint_Release(Obj->pCP);
if(Obj->fOwn) { /* We need to destroy the picture */
switch(Obj->desc.picType) {
case PICTYPE_BITMAP:
DeleteObject(Obj->desc.u.bmp.hbitmap);
if (Obj->hbmMask != NULL) DeleteObject(Obj->hbmMask);
if (Obj->hbmXor != NULL) DeleteObject(Obj->hbmXor);
break;
case PICTYPE_METAFILE:
DeleteMetaFile(Obj->desc.u.wmf.hmeta);
break;
case PICTYPE_ICON:
DestroyIcon(Obj->desc.u.icon.hicon);
break;
case PICTYPE_ENHMETAFILE:
DeleteEnhMetaFile(Obj->desc.u.emf.hemf);
break;
case PICTYPE_NONE:
case PICTYPE_UNINITIALIZED:
/* Nothing to do */
break;
default:
FIXME("Unsupported type %d - unable to delete\n", Obj->desc.picType);
break;
}
}
HeapFree(GetProcessHeap(), 0, Obj->data);
HeapFree(GetProcessHeap(), 0, Obj);
}
/************************************************************************
* OLEPictureImpl_AddRef (IUnknown)
*
* See Windows documentation for more details on IUnknown methods.
*/
static ULONG WINAPI OLEPictureImpl_AddRef(
IPicture* iface)
{
OLEPictureImpl *This = (OLEPictureImpl *)iface;
ULONG refCount = InterlockedIncrement(&This->ref);
TRACE("(%p)->(ref before=%d)\n", This, refCount - 1);
return refCount;
}
/************************************************************************
* OLEPictureImpl_Release (IUnknown)
*
* See Windows documentation for more details on IUnknown methods.
*/
static ULONG WINAPI OLEPictureImpl_Release(
IPicture* iface)
{
OLEPictureImpl *This = (OLEPictureImpl *)iface;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -