4 * Implementation of OLE IPicture and related interfaces
6 * Copyright 2000 Huw D M Davies for CodeWeavers.
11 * Only implements PICTYPE_BITMAP.
12 * Most methods are just stubs.
13 * Doesn't even expose IPersistStream, IConnectionPointContainer.
16 * NOTES (or things that msdn doesn't tell you)
18 * The width and height properties are returned in HIMETRIC units (0.01mm)
19 * IPicture::Render also uses these to select a region of the src picture.
20 * A bitmap's size is converted into these units by using the screen resolution
21 * thus an 8x8 bitmap on a 96dpi screen has a size of 212x212 (8/96 * 2540).
31 #include "wine/obj_picture.h"
32 #include "debugtools.h"
34 DEFAULT_DEBUG_CHANNEL(ole);
36 /*************************************************************************
37 * Declaration of implementation class
40 typedef struct OLEPictureImpl {
43 * IPicture handles IUnknown
46 ICOM_VTABLE(IPicture) *lpvtbl1;
47 ICOM_VTABLE(IDispatch) *lpvtbl2;
48 ICOM_VTABLE(IPersistStream) *lpvtbl3;
50 /* Object referenece count */
53 /* We own the object and must destroy it ourselves */
56 /* Picture description */
59 /* These are the pixel size of a bitmap */
63 /* And these are the size of the picture converted into HIMETRIC units */
64 OLE_XSIZE_HIMETRIC himetricWidth;
65 OLE_YSIZE_HIMETRIC himetricHeight;
70 * Macros to retrieve pointer to IUnknown (IPicture) from the other VTables.
72 #define ICOM_THIS_From_IDispatch(impl, name) \
73 impl *This = (impl*)(((char*)name)-sizeof(void*));
75 #define ICOM_THIS_From_IPersistStream(impl, name) \
76 impl *This = (impl*)(((char*)name)-2*sizeof(void*));
79 * Predeclare VTables. They get initialized at the end.
81 static ICOM_VTABLE(IPicture) OLEPictureImpl_VTable;
82 static ICOM_VTABLE(IDispatch) OLEPictureImpl_IDispatch_VTable;
83 static ICOM_VTABLE(IPersistStream) OLEPictureImpl_IPersistStream_VTable;
85 /***********************************************************************
86 * Implementation of the OLEPictureImpl class.
89 /************************************************************************
90 * OLEPictureImpl_Construct
92 * This method will construct a new instance of the OLEPictureImpl
95 * The caller of this method must release the object when it's
98 static OLEPictureImpl* OLEPictureImpl_Construct(LPPICTDESC pictDesc, BOOL fOwn)
100 OLEPictureImpl* newObject = 0;
101 TRACE("(%p) type = %d\n", pictDesc, pictDesc->picType);
104 * Allocate space for the object.
106 newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(OLEPictureImpl));
112 * Initialize the virtual function table.
114 newObject->lpvtbl1 = &OLEPictureImpl_VTable;
115 newObject->lpvtbl2 = &OLEPictureImpl_IDispatch_VTable;
116 newObject->lpvtbl3 = &OLEPictureImpl_IPersistStream_VTable;
119 * Start with one reference count. The caller of this function
120 * must release the interface pointer when it is done.
124 newObject->fOwn = fOwn;
126 if(pictDesc->cbSizeofstruct != sizeof(PICTDESC)) {
127 FIXME("struct size = %d\n", pictDesc->cbSizeofstruct);
129 memcpy(&newObject->desc, pictDesc, sizeof(PICTDESC));
131 switch(pictDesc->picType) {
137 TRACE("bitmap handle %08x\n", pictDesc->u.bmp.hbitmap);
138 if(GetObjectA(pictDesc->u.bmp.hbitmap, sizeof(bm), &bm) != sizeof(bm)) {
139 ERR("GetObject fails\n");
143 newObject->origWidth = bm.bmWidth;
144 newObject->origHeight = bm.bmHeight;
146 /* The width and height are stored in HIMETRIC units (0.01 mm),
147 so we take our pixel width divide by pixels per inch and
148 multiply by 25.4 * 100 */
150 /* Should we use GetBitmapDimension if available? */
152 hdcRef = CreateCompatibleDC(0);
154 newObject->himetricWidth = (bm.bmWidth * 2540) /
155 GetDeviceCaps(hdcRef, LOGPIXELSX);
156 newObject->himetricHeight = (bm.bmHeight * 2540) /
157 GetDeviceCaps(hdcRef, LOGPIXELSY);
162 case PICTYPE_METAFILE:
163 TRACE("metafile handle %08x\n", pictDesc->u.wmf.hmeta);
164 newObject->himetricWidth = pictDesc->u.wmf.xExt;
165 newObject->himetricHeight = pictDesc->u.wmf.yExt;
169 case PICTYPE_ENHMETAFILE:
171 FIXME("Unsupported type %d\n", pictDesc->picType);
172 newObject->himetricWidth = newObject->himetricHeight = 0;
176 TRACE("returning %p\n", newObject);
180 /************************************************************************
181 * OLEPictureImpl_Destroy
183 * This method is called by the Release method when the reference
184 * count goes down to 0. It will free all resources used by
186 static void OLEPictureImpl_Destroy(OLEPictureImpl* Obj)
188 TRACE("(%p)\n", Obj);
190 if(Obj->fOwn) { /* We need to destroy the picture */
191 switch(Obj->desc.picType) {
193 DeleteObject(Obj->desc.u.bmp.hbitmap);
195 case PICTYPE_METAFILE:
196 DeleteMetaFile(Obj->desc.u.wmf.hmeta);
199 DestroyIcon(Obj->desc.u.icon.hicon);
201 case PICTYPE_ENHMETAFILE:
202 DeleteEnhMetaFile(Obj->desc.u.emf.hemf);
205 FIXME("Unsupported type %d - unable to delete\n", Obj->desc.picType);
209 HeapFree(GetProcessHeap(), 0, Obj);
212 static ULONG WINAPI OLEPictureImpl_AddRef(IPicture* iface);
214 /************************************************************************
215 * OLEPictureImpl_QueryInterface (IUnknown)
217 * See Windows documentation for more details on IUnknown methods.
219 static HRESULT WINAPI OLEPictureImpl_QueryInterface(
224 ICOM_THIS(OLEPictureImpl, iface);
225 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
228 * Perform a sanity check on the parameters.
230 if ( (This==0) || (ppvObject==0) )
234 * Initialize the return parameter.
239 * Compare the riid with the interface IDs implemented by this object.
241 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
243 *ppvObject = (IPicture*)This;
245 else if (memcmp(&IID_IPicture, riid, sizeof(IID_IPicture)) == 0)
247 *ppvObject = (IPicture*)This;
249 else if (memcmp(&IID_IDispatch, riid, sizeof(IID_IDispatch)) == 0)
251 *ppvObject = (IDispatch*)&(This->lpvtbl2);
253 else if (memcmp(&IID_IPictureDisp, riid, sizeof(IID_IPictureDisp)) == 0)
255 *ppvObject = (IDispatch*)&(This->lpvtbl2);
257 /* else if (memcmp(&IID_IPersistStream, riid, sizeof(IID_IPersistStream)) == 0)
259 *ppvObject = (IPersistStream*)&(This->lpvtbl3);
263 * Check that we obtained an interface.
267 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
268 return E_NOINTERFACE;
272 * Query Interface always increases the reference count by one when it is
275 OLEPictureImpl_AddRef((IPicture*)This);
280 /************************************************************************
281 * OLEPictureImpl_AddRef (IUnknown)
283 * See Windows documentation for more details on IUnknown methods.
285 static ULONG WINAPI OLEPictureImpl_AddRef(
288 ICOM_THIS(OLEPictureImpl, iface);
289 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
295 /************************************************************************
296 * OLEPictureImpl_Release (IUnknown)
298 * See Windows documentation for more details on IUnknown methods.
300 static ULONG WINAPI OLEPictureImpl_Release(
303 ICOM_THIS(OLEPictureImpl, iface);
304 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
307 * Decrease the reference count on this object.
312 * If the reference count goes down to 0, perform suicide.
316 OLEPictureImpl_Destroy(This);
325 /************************************************************************
326 * OLEPictureImpl_get_Handle
328 static HRESULT WINAPI OLEPictureImpl_get_Handle(IPicture *iface,
331 ICOM_THIS(OLEPictureImpl, iface);
332 TRACE("(%p)->(%p)\n", This, phandle);
333 switch(This->desc.picType) {
335 *phandle = This->desc.u.bmp.hbitmap;
337 case PICTYPE_METAFILE:
338 *phandle = This->desc.u.wmf.hmeta;
341 *phandle = This->desc.u.icon.hicon;
343 case PICTYPE_ENHMETAFILE:
344 *phandle = This->desc.u.emf.hemf;
347 FIXME("Unimplemented type %d\n", This->desc.picType);
350 TRACE("returning handle %08x\n", *phandle);
354 /************************************************************************
355 * OLEPictureImpl_get_hPal
357 static HRESULT WINAPI OLEPictureImpl_get_hPal(IPicture *iface,
360 ICOM_THIS(OLEPictureImpl, iface);
361 FIXME("(%p)->(%p): stub\n", This, phandle);
365 /************************************************************************
366 * OLEPictureImpl_get_Type
368 static HRESULT WINAPI OLEPictureImpl_get_Type(IPicture *iface,
371 ICOM_THIS(OLEPictureImpl, iface);
372 TRACE("(%p)->(%p): type is %d\n", This, ptype, This->desc.picType);
373 *ptype = This->desc.picType;
377 /************************************************************************
378 * OLEPictureImpl_get_Width
380 static HRESULT WINAPI OLEPictureImpl_get_Width(IPicture *iface,
381 OLE_XSIZE_HIMETRIC *pwidth)
383 ICOM_THIS(OLEPictureImpl, iface);
384 TRACE("(%p)->(%p): width is %ld\n", This, pwidth, This->himetricWidth);
385 *pwidth = This->himetricWidth;
389 /************************************************************************
390 * OLEPictureImpl_get_Height
392 static HRESULT WINAPI OLEPictureImpl_get_Height(IPicture *iface,
393 OLE_YSIZE_HIMETRIC *pheight)
395 ICOM_THIS(OLEPictureImpl, iface);
396 TRACE("(%p)->(%p): height is %ld\n", This, pheight, This->himetricHeight);
397 *pheight = This->himetricHeight;
401 /************************************************************************
402 * OLEPictureImpl_Render
404 static HRESULT WINAPI OLEPictureImpl_Render(IPicture *iface, HDC hdc,
405 long x, long y, long cx, long cy,
406 OLE_XPOS_HIMETRIC xSrc,
407 OLE_YPOS_HIMETRIC ySrc,
408 OLE_XSIZE_HIMETRIC cxSrc,
409 OLE_YSIZE_HIMETRIC cySrc,
412 ICOM_THIS(OLEPictureImpl, iface);
413 TRACE("(%p)->(%08x, (%ld,%ld), (%ld,%ld) <- (%ld,%ld), (%ld,%ld), %p)\n",
414 This, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, prcWBounds);
416 TRACE("prcWBounds (%d,%d) - (%d,%d)\n", prcWBounds->left, prcWBounds->top,
417 prcWBounds->right, prcWBounds->bottom);
419 switch(This->desc.picType) {
425 /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
426 NB y-axis gets flipped */
428 hdcBmp = CreateCompatibleDC(0);
429 SetMapMode(hdcBmp, MM_ANISOTROPIC);
430 SetWindowOrgEx(hdcBmp, 0, 0, NULL);
431 SetWindowExtEx(hdcBmp, This->himetricWidth, This->himetricHeight, NULL);
432 SetViewportOrgEx(hdcBmp, 0, This->origHeight, NULL);
433 SetViewportExtEx(hdcBmp, This->origWidth, -This->origHeight, NULL);
435 hbmpOld = SelectObject(hdcBmp, This->desc.u.bmp.hbitmap);
437 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCCOPY);
439 SelectObject(hdcBmp, hbmpOld);
444 case PICTYPE_METAFILE:
446 case PICTYPE_ENHMETAFILE:
448 FIXME("type %d not implemented\n", This->desc.picType);
455 /************************************************************************
456 * OLEPictureImpl_set_hPal
458 static HRESULT WINAPI OLEPictureImpl_set_hPal(IPicture *iface,
461 ICOM_THIS(OLEPictureImpl, iface);
462 FIXME("(%p)->(%08x): stub\n", This, hpal);
466 /************************************************************************
467 * OLEPictureImpl_get_CurDC
469 static HRESULT WINAPI OLEPictureImpl_get_CurDC(IPicture *iface,
472 ICOM_THIS(OLEPictureImpl, iface);
473 FIXME("(%p)->(%p): stub\n", This, phdc);
477 /************************************************************************
478 * OLEPictureImpl_SelectPicture
480 static HRESULT WINAPI OLEPictureImpl_SelectPicture(IPicture *iface,
483 OLE_HANDLE *phbmpOut)
485 ICOM_THIS(OLEPictureImpl, iface);
486 FIXME("(%p)->(%08x, %p, %p): stub\n", This, hdcIn, phdcOut, phbmpOut);
490 /************************************************************************
491 * OLEPictureImpl_get_KeepOriginalFormat
493 static HRESULT WINAPI OLEPictureImpl_get_KeepOriginalFormat(IPicture *iface,
496 ICOM_THIS(OLEPictureImpl, iface);
497 FIXME("(%p)->(%p): stub\n", This, pfKeep);
501 /************************************************************************
502 * OLEPictureImpl_put_KeepOriginalFormat
504 static HRESULT WINAPI OLEPictureImpl_put_KeepOriginalFormat(IPicture *iface,
507 ICOM_THIS(OLEPictureImpl, iface);
508 FIXME("(%p)->(%d): stub\n", This, keep);
512 /************************************************************************
513 * OLEPictureImpl_PictureChanged
515 static HRESULT WINAPI OLEPictureImpl_PictureChanged(IPicture *iface)
517 ICOM_THIS(OLEPictureImpl, iface);
518 FIXME("(%p)->(): stub\n", This);
522 /************************************************************************
523 * OLEPictureImpl_SaveAsFile
525 static HRESULT WINAPI OLEPictureImpl_SaveAsFile(IPicture *iface,
530 ICOM_THIS(OLEPictureImpl, iface);
531 FIXME("(%p)->(%p, %d, %p): stub\n", This, pstream, SaveMemCopy, pcbSize);
535 /************************************************************************
536 * OLEPictureImpl_get_Attributes
538 static HRESULT WINAPI OLEPictureImpl_get_Attributes(IPicture *iface,
541 ICOM_THIS(OLEPictureImpl, iface);
542 FIXME("(%p)->(%p): stub\n", This, pdwAttr);
548 /************************************************************************
551 /************************************************************************
552 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
554 * See Windows documentation for more details on IUnknown methods.
556 static HRESULT WINAPI OLEPictureImpl_IDispatch_QueryInterface(
561 ICOM_THIS_From_IDispatch(IPicture, iface);
563 return IPicture_QueryInterface(This, riid, ppvoid);
566 /************************************************************************
567 * OLEPictureImpl_IDispatch_AddRef (IUnknown)
569 * See Windows documentation for more details on IUnknown methods.
571 static ULONG WINAPI OLEPictureImpl_IDispatch_AddRef(
574 ICOM_THIS_From_IDispatch(IPicture, iface);
576 return IPicture_AddRef(This);
579 /************************************************************************
580 * OLEPictureImpl_IDispatch_Release (IUnknown)
582 * See Windows documentation for more details on IUnknown methods.
584 static ULONG WINAPI OLEPictureImpl_IDispatch_Release(
587 ICOM_THIS_From_IDispatch(IPicture, iface);
589 return IPicture_Release(This);
592 /************************************************************************
593 * OLEPictureImpl_GetTypeInfoCount (IDispatch)
595 * See Windows documentation for more details on IDispatch methods.
597 static HRESULT WINAPI OLEPictureImpl_GetTypeInfoCount(
599 unsigned int* pctinfo)
606 /************************************************************************
607 * OLEPictureImpl_GetTypeInfo (IDispatch)
609 * See Windows documentation for more details on IDispatch methods.
611 static HRESULT WINAPI OLEPictureImpl_GetTypeInfo(
622 /************************************************************************
623 * OLEPictureImpl_GetIDsOfNames (IDispatch)
625 * See Windows documentation for more details on IDispatch methods.
627 static HRESULT WINAPI OLEPictureImpl_GetIDsOfNames(
640 /************************************************************************
641 * OLEPictureImpl_Invoke (IDispatch)
643 * See Windows documentation for more details on IDispatch methods.
645 static HRESULT WINAPI OLEPictureImpl_Invoke(
651 DISPPARAMS* pDispParams,
653 EXCEPINFO* pExepInfo,
662 static ICOM_VTABLE(IPicture) OLEPictureImpl_VTable =
664 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
665 OLEPictureImpl_QueryInterface,
666 OLEPictureImpl_AddRef,
667 OLEPictureImpl_Release,
668 OLEPictureImpl_get_Handle,
669 OLEPictureImpl_get_hPal,
670 OLEPictureImpl_get_Type,
671 OLEPictureImpl_get_Width,
672 OLEPictureImpl_get_Height,
673 OLEPictureImpl_Render,
674 OLEPictureImpl_set_hPal,
675 OLEPictureImpl_get_CurDC,
676 OLEPictureImpl_SelectPicture,
677 OLEPictureImpl_get_KeepOriginalFormat,
678 OLEPictureImpl_put_KeepOriginalFormat,
679 OLEPictureImpl_PictureChanged,
680 OLEPictureImpl_SaveAsFile,
681 OLEPictureImpl_get_Attributes
684 static ICOM_VTABLE(IDispatch) OLEPictureImpl_IDispatch_VTable =
686 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
687 OLEPictureImpl_IDispatch_QueryInterface,
688 OLEPictureImpl_IDispatch_AddRef,
689 OLEPictureImpl_IDispatch_Release,
690 OLEPictureImpl_GetTypeInfoCount,
691 OLEPictureImpl_GetTypeInfo,
692 OLEPictureImpl_GetIDsOfNames,
693 OLEPictureImpl_Invoke
696 /***********************************************************************
697 * OleCreatePictureIndirect
699 HRESULT WINAPI OleCreatePictureIndirect(LPPICTDESC lpPictDesc, REFIID riid,
700 BOOL fOwn, LPVOID *ppvObj )
702 OLEPictureImpl* newPict = NULL;
705 TRACE("(%p,%p,%d,%p)\n", lpPictDesc, riid, fOwn, ppvObj);
716 * Try to construct a new instance of the class.
718 newPict = OLEPictureImpl_Construct(lpPictDesc, fOwn);
721 return E_OUTOFMEMORY;
724 * Make sure it supports the interface required by the caller.
726 hr = IPicture_QueryInterface((IPicture*)newPict, riid, ppvObj);
729 * Release the reference obtained in the constructor. If
730 * the QueryInterface was unsuccessful, it will free the class.
732 IPicture_Release((IPicture*)newPict);
738 /***********************************************************************
741 HRESULT WINAPI OleLoadPicture( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
742 REFIID reed, LPVOID *ppvObj )
744 FIXME("(%p,%ld,%d,%p,%p), not implemented\n",
745 lpstream, lSize, fRunmode, reed, ppvObj);