OLE picture object implementation.
[wine.git] / dlls / oleaut32 / olepicture.c
blob7f01dd74bc99b4f2bb78e58951e88a71d935243c
1 /*
2 * OLE Picture object
4 * Implementation of OLE IPicture and related interfaces
6 * Copyright 2000 Huw D M Davies for CodeWeavers.
9 * BUGS
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).
25 #include "winerror.h"
26 #include "olectl.h"
27 #include "wine/obj_picture.h"
28 #include "debugtools.h"
30 DEFAULT_DEBUG_CHANNEL(ole)
32 /*************************************************************************
33 * Declaration of implementation class
36 typedef struct OLEPictureImpl {
39 * IPicture handles IUnknown
42 ICOM_VTABLE(IPicture) *lpvtbl1;
43 ICOM_VTABLE(IDispatch) *lpvtbl2;
44 ICOM_VTABLE(IPersistStream) *lpvtbl3;
46 /* Object referenece count */
47 DWORD ref;
49 /* We own the object and must destroy it ourselves */
50 BOOL fOwn;
52 /* Picture description */
53 PICTDESC desc;
55 /* These are the pixel size of a bitmap */
56 DWORD origWidth;
57 DWORD origHeight;
59 /* And these are the size of the picture converted into HIMETRIC units */
60 OLE_XSIZE_HIMETRIC himetricWidth;
61 OLE_YSIZE_HIMETRIC himetricHeight;
63 } OLEPictureImpl;
66 * Macros to retrieve pointer to IUnknown (IPicture) from the other VTables.
68 #define ICOM_THIS_From_IDispatch(impl, name) \
69 impl *This = (impl*)(((char*)name)-sizeof(void*));
71 #define ICOM_THIS_From_IPersistStream(impl, name) \
72 impl *This = (impl*)(((char*)name)-2*sizeof(void*));
75 * Predeclare VTables. They get initialized at the end.
77 static ICOM_VTABLE(IPicture) OLEPictureImpl_VTable;
78 static ICOM_VTABLE(IDispatch) OLEPictureImpl_IDispatch_VTable;
79 static ICOM_VTABLE(IPersistStream) OLEPictureImpl_IPersistStream_VTable;
81 /***********************************************************************
82 * Implementation of the OLEPictureImpl class.
85 /************************************************************************
86 * OLEPictureImpl_Construct
88 * This method will construct a new instance of the OLEPictureImpl
89 * class.
91 * The caller of this method must release the object when it's
92 * done with it.
94 static OLEPictureImpl* OLEPictureImpl_Construct(LPPICTDESC pictDesc, BOOL fOwn)
96 OLEPictureImpl* newObject = 0;
97 TRACE("(%p) type = %d\n", pictDesc, pictDesc->picType);
100 * Allocate space for the object.
102 newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(OLEPictureImpl));
104 if (newObject==0)
105 return newObject;
108 * Initialize the virtual function table.
110 newObject->lpvtbl1 = &OLEPictureImpl_VTable;
111 newObject->lpvtbl2 = &OLEPictureImpl_IDispatch_VTable;
112 newObject->lpvtbl3 = &OLEPictureImpl_IPersistStream_VTable;
115 * Start with one reference count. The caller of this function
116 * must release the interface pointer when it is done.
118 newObject->ref = 1;
120 newObject->fOwn = fOwn;
122 if(pictDesc->cbSizeofstruct != sizeof(PICTDESC)) {
123 FIXME("struct size = %d\n", pictDesc->cbSizeofstruct);
125 memcpy(&newObject->desc, pictDesc, sizeof(PICTDESC));
127 switch(pictDesc->picType) {
128 case PICTYPE_BITMAP:
130 BITMAP bm;
131 HDC hdcRef;
133 TRACE("bitmap handle %08x\n", pictDesc->u.bmp.hbitmap);
134 if(GetObjectA(pictDesc->u.bmp.hbitmap, sizeof(bm), &bm) != sizeof(bm)) {
135 ERR("GetObject fails\n");
136 break;
139 newObject->origWidth = bm.bmWidth;
140 newObject->origHeight = bm.bmHeight;
142 /* The width and height are stored in HIMETRIC units (0.01 mm),
143 so we take our pixel width divide by pixels per inch and
144 multiply by 25.4 * 100 */
146 /* Should we use GetBitmapDimension if available? */
148 hdcRef = CreateCompatibleDC(0);
150 newObject->himetricWidth = (bm.bmWidth * 2540) /
151 GetDeviceCaps(hdcRef, LOGPIXELSX);
152 newObject->himetricHeight = (bm.bmHeight * 2540) /
153 GetDeviceCaps(hdcRef, LOGPIXELSY);
154 DeleteDC(hdcRef);
156 break;
158 case PICTYPE_METAFILE:
159 TRACE("metafile handle %08x\n", pictDesc->u.wmf.hmeta);
160 newObject->himetricWidth = pictDesc->u.wmf.xExt;
161 newObject->himetricHeight = pictDesc->u.wmf.yExt;
162 break;
164 case PICTYPE_ICON:
165 case PICTYPE_ENHMETAFILE:
166 default:
167 FIXME("Unsupported type %d\n", pictDesc->picType);
168 newObject->himetricWidth = newObject->himetricHeight = 0;
169 break;
172 TRACE("returning %p\n", newObject);
173 return newObject;
176 /************************************************************************
177 * OLEPictureImpl_Destroy
179 * This method is called by the Release method when the reference
180 * count goes doen to 0. it will free all resources used by
181 * this object. */
182 static void OLEPictureImpl_Destroy(OLEPictureImpl* Obj)
184 TRACE("(%p)\n", Obj);
186 if(Obj->fOwn) { /* We need to destroy the picture */
187 switch(Obj->desc.picType) {
188 case PICTYPE_BITMAP:
189 DeleteObject(Obj->desc.u.bmp.hbitmap);
190 break;
191 case PICTYPE_METAFILE:
192 DeleteMetaFile(Obj->desc.u.wmf.hmeta);
193 break;
194 case PICTYPE_ICON:
195 DestroyIcon(Obj->desc.u.icon.hicon);
196 break;
197 case PICTYPE_ENHMETAFILE:
198 DeleteEnhMetaFile(Obj->desc.u.emf.hemf);
199 break;
200 default:
201 FIXME("Unsupported type %d - unable to delete\n", Obj->desc.picType);
202 break;
205 HeapFree(GetProcessHeap(), 0, Obj);
208 static ULONG WINAPI OLEPictureImpl_AddRef(IPicture* iface);
210 /************************************************************************
211 * OLEPictureImpl_QueryInterface (IUnknown)
213 * See Windows documentation for more details on IUnknown methods.
215 static HRESULT WINAPI OLEPictureImpl_QueryInterface(
216 IPicture* iface,
217 REFIID riid,
218 void** ppvObject)
220 ICOM_THIS(OLEPictureImpl, iface);
221 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
224 * Perform a sanity check on the parameters.
226 if ( (This==0) || (ppvObject==0) )
227 return E_INVALIDARG;
230 * Initialize the return parameter.
232 *ppvObject = 0;
235 * Compare the riid with the interface IDs implemented by this object.
237 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
239 *ppvObject = (IPicture*)This;
241 else if (memcmp(&IID_IPicture, riid, sizeof(IID_IPicture)) == 0)
243 *ppvObject = (IPicture*)This;
245 else if (memcmp(&IID_IDispatch, riid, sizeof(IID_IDispatch)) == 0)
247 *ppvObject = (IDispatch*)&(This->lpvtbl2);
249 else if (memcmp(&IID_IPictureDisp, riid, sizeof(IID_IPictureDisp)) == 0)
251 *ppvObject = (IDispatch*)&(This->lpvtbl2);
253 /* else if (memcmp(&IID_IPersistStream, riid, sizeof(IID_IPersistStream)) == 0)
255 *ppvObject = (IPersistStream*)&(This->lpvtbl3);
259 * Check that we obtained an interface.
261 if ((*ppvObject)==0)
263 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
264 return E_NOINTERFACE;
268 * Query Interface always increases the reference count by one when it is
269 * successful
271 OLEPictureImpl_AddRef((IPicture*)This);
273 return S_OK;;
276 /************************************************************************
277 * OLEPictureImpl_AddRef (IUnknown)
279 * See Windows documentation for more details on IUnknown methods.
281 static ULONG WINAPI OLEPictureImpl_AddRef(
282 IPicture* iface)
284 ICOM_THIS(OLEPictureImpl, iface);
285 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
286 This->ref++;
288 return This->ref;
291 /************************************************************************
292 * OLEPictureImpl_Release (IUnknown)
294 * See Windows documentation for more details on IUnknown methods.
296 static ULONG WINAPI OLEPictureImpl_Release(
297 IPicture* iface)
299 ICOM_THIS(OLEPictureImpl, iface);
300 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
303 * Decrease the reference count on this object.
305 This->ref--;
308 * If the reference count goes down to 0, perform suicide.
310 if (This->ref==0)
312 OLEPictureImpl_Destroy(This);
314 return 0;
317 return This->ref;
321 /************************************************************************
322 * OLEPictureImpl_get_Handle
324 static HRESULT WINAPI OLEPictureImpl_get_Handle(IPicture *iface,
325 OLE_HANDLE *phandle)
327 ICOM_THIS(OLEPictureImpl, iface);
328 TRACE("(%p)->(%p)\n", This, phandle);
329 switch(This->desc.picType) {
330 case PICTYPE_BITMAP:
331 *phandle = This->desc.u.bmp.hbitmap;
332 break;
333 case PICTYPE_METAFILE:
334 *phandle = This->desc.u.wmf.hmeta;
335 break;
336 case PICTYPE_ICON:
337 *phandle = This->desc.u.icon.hicon;
338 break;
339 case PICTYPE_ENHMETAFILE:
340 *phandle = This->desc.u.emf.hemf;
341 break;
342 default:
343 FIXME("Unimplemented type %d\n", This->desc.picType);
344 return E_NOTIMPL;
346 TRACE("returning handle %08x\n", *phandle);
347 return S_OK;
350 /************************************************************************
351 * OLEPictureImpl_get_hPal
353 static HRESULT WINAPI OLEPictureImpl_get_hPal(IPicture *iface,
354 OLE_HANDLE *phandle)
356 ICOM_THIS(OLEPictureImpl, iface);
357 FIXME("(%p)->(%p): stub\n", This, phandle);
358 return E_NOTIMPL;
361 /************************************************************************
362 * OLEPictureImpl_get_Type
364 static HRESULT WINAPI OLEPictureImpl_get_Type(IPicture *iface,
365 short *ptype)
367 ICOM_THIS(OLEPictureImpl, iface);
368 TRACE("(%p)->(%p): type is %d\n", This, ptype, This->desc.picType);
369 *ptype = This->desc.picType;
370 return S_OK;
373 /************************************************************************
374 * OLEPictureImpl_get_Width
376 static HRESULT WINAPI OLEPictureImpl_get_Width(IPicture *iface,
377 OLE_XSIZE_HIMETRIC *pwidth)
379 ICOM_THIS(OLEPictureImpl, iface);
380 TRACE("(%p)->(%p): width is %ld\n", This, pwidth, This->himetricWidth);
381 *pwidth = This->himetricWidth;
382 return S_OK;
385 /************************************************************************
386 * OLEPictureImpl_get_Height
388 static HRESULT WINAPI OLEPictureImpl_get_Height(IPicture *iface,
389 OLE_YSIZE_HIMETRIC *pheight)
391 ICOM_THIS(OLEPictureImpl, iface);
392 TRACE("(%p)->(%p): height is %ld\n", This, pheight, This->himetricHeight);
393 *pheight = This->himetricHeight;
394 return S_OK;
397 /************************************************************************
398 * OLEPictureImpl_Render
400 static HRESULT WINAPI OLEPictureImpl_Render(IPicture *iface, HDC hdc,
401 long x, long y, long cx, long cy,
402 OLE_XPOS_HIMETRIC xSrc,
403 OLE_YPOS_HIMETRIC ySrc,
404 OLE_XSIZE_HIMETRIC cxSrc,
405 OLE_YSIZE_HIMETRIC cySrc,
406 LPCRECT prcWBounds)
408 ICOM_THIS(OLEPictureImpl, iface);
409 TRACE("(%p)->(%08x, (%ld,%ld), (%ld,%ld) <- (%ld,%ld), (%ld,%ld), %p)\n",
410 This, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, prcWBounds);
411 if(prcWBounds)
412 TRACE("prcWBounds (%d,%d) - (%d,%d)\n", prcWBounds->left, prcWBounds->top,
413 prcWBounds->right, prcWBounds->bottom);
415 switch(This->desc.picType) {
416 case PICTYPE_BITMAP:
418 HBITMAP hbmpOld;
419 HDC hdcBmp;
421 /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
422 NB y-axis gets flipped */
424 hdcBmp = CreateCompatibleDC(0);
425 SetMapMode(hdcBmp, MM_ANISOTROPIC);
426 SetWindowOrgEx(hdcBmp, 0, 0, NULL);
427 SetWindowExtEx(hdcBmp, This->himetricWidth, This->himetricHeight, NULL);
428 SetViewportOrgEx(hdcBmp, 0, This->origHeight, NULL);
429 SetViewportExtEx(hdcBmp, This->origWidth, -This->origHeight, NULL);
431 hbmpOld = SelectObject(hdcBmp, This->desc.u.bmp.hbitmap);
433 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCCOPY);
435 SelectObject(hdcBmp, hbmpOld);
436 DeleteDC(hdcBmp);
438 break;
440 case PICTYPE_METAFILE:
441 case PICTYPE_ICON:
442 case PICTYPE_ENHMETAFILE:
443 default:
444 FIXME("type %d not implemented\n", This->desc.picType);
445 return E_NOTIMPL;
448 return S_OK;
451 /************************************************************************
452 * OLEPictureImpl_set_hPal
454 static HRESULT WINAPI OLEPictureImpl_set_hPal(IPicture *iface,
455 OLE_HANDLE hpal)
457 ICOM_THIS(OLEPictureImpl, iface);
458 FIXME("(%p)->(%08x): stub\n", This, hpal);
459 return E_NOTIMPL;
462 /************************************************************************
463 * OLEPictureImpl_get_CurDC
465 static HRESULT WINAPI OLEPictureImpl_get_CurDC(IPicture *iface,
466 HDC *phdc)
468 ICOM_THIS(OLEPictureImpl, iface);
469 FIXME("(%p)->(%p): stub\n", This, phdc);
470 return E_NOTIMPL;
473 /************************************************************************
474 * OLEPictureImpl_SelectPicture
476 static HRESULT WINAPI OLEPictureImpl_SelectPicture(IPicture *iface,
477 HDC hdcIn,
478 HDC *phdcOut,
479 OLE_HANDLE *phbmpOut)
481 ICOM_THIS(OLEPictureImpl, iface);
482 FIXME("(%p)->(%08x, %p, %p): stub\n", This, hdcIn, phdcOut, phbmpOut);
483 return E_NOTIMPL;
486 /************************************************************************
487 * OLEPictureImpl_get_KeepOriginalFormat
489 static HRESULT WINAPI OLEPictureImpl_get_KeepOriginalFormat(IPicture *iface,
490 BOOL *pfKeep)
492 ICOM_THIS(OLEPictureImpl, iface);
493 FIXME("(%p)->(%p): stub\n", This, pfKeep);
494 return E_NOTIMPL;
497 /************************************************************************
498 * OLEPictureImpl_put_KeepOriginalFormat
500 static HRESULT WINAPI OLEPictureImpl_put_KeepOriginalFormat(IPicture *iface,
501 BOOL keep)
503 ICOM_THIS(OLEPictureImpl, iface);
504 FIXME("(%p)->(%d): stub\n", This, keep);
505 return E_NOTIMPL;
508 /************************************************************************
509 * OLEPictureImpl_PictureChanged
511 static HRESULT WINAPI OLEPictureImpl_PictureChanged(IPicture *iface)
513 ICOM_THIS(OLEPictureImpl, iface);
514 FIXME("(%p)->(): stub\n", This);
515 return E_NOTIMPL;
518 /************************************************************************
519 * OLEPictureImpl_SaveAsFile
521 static HRESULT WINAPI OLEPictureImpl_SaveAsFile(IPicture *iface,
522 IStream *pstream,
523 BOOL SaveMemCopy,
524 LONG *pcbSize)
526 ICOM_THIS(OLEPictureImpl, iface);
527 FIXME("(%p)->(%p, %d, %p): stub\n", This, pstream, SaveMemCopy, pcbSize);
528 return E_NOTIMPL;
531 /************************************************************************
532 * OLEPictureImpl_get_Attributes
534 static HRESULT WINAPI OLEPictureImpl_get_Attributes(IPicture *iface,
535 DWORD *pdwAttr)
537 ICOM_THIS(OLEPictureImpl, iface);
538 FIXME("(%p)->(%p): stub\n", This, pdwAttr);
539 return E_NOTIMPL;
544 /************************************************************************
545 * IDispatch
547 /************************************************************************
548 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
550 * See Windows documentation for more details on IUnknown methods.
552 static HRESULT WINAPI OLEPictureImpl_IDispatch_QueryInterface(
553 IDispatch* iface,
554 REFIID riid,
555 VOID** ppvoid)
557 ICOM_THIS_From_IDispatch(IPicture, iface);
559 return IPicture_QueryInterface(This, riid, ppvoid);
562 /************************************************************************
563 * OLEPictureImpl_IDispatch_AddRef (IUnknown)
565 * See Windows documentation for more details on IUnknown methods.
567 static ULONG WINAPI OLEPictureImpl_IDispatch_AddRef(
568 IDispatch* iface)
570 ICOM_THIS_From_IDispatch(IPicture, iface);
572 return IPicture_AddRef(This);
575 /************************************************************************
576 * OLEPictureImpl_IDispatch_Release (IUnknown)
578 * See Windows documentation for more details on IUnknown methods.
580 static ULONG WINAPI OLEPictureImpl_IDispatch_Release(
581 IDispatch* iface)
583 ICOM_THIS_From_IDispatch(IPicture, iface);
585 return IPicture_Release(This);
588 /************************************************************************
589 * OLEPictureImpl_GetTypeInfoCount (IDispatch)
591 * See Windows documentation for more details on IDispatch methods.
593 static HRESULT WINAPI OLEPictureImpl_GetTypeInfoCount(
594 IDispatch* iface,
595 unsigned int* pctinfo)
597 FIXME("():Stub\n");
599 return E_NOTIMPL;
602 /************************************************************************
603 * OLEPictureImpl_GetTypeInfo (IDispatch)
605 * See Windows documentation for more details on IDispatch methods.
607 static HRESULT WINAPI OLEPictureImpl_GetTypeInfo(
608 IDispatch* iface,
609 UINT iTInfo,
610 LCID lcid,
611 ITypeInfo** ppTInfo)
613 FIXME("():Stub\n");
615 return E_NOTIMPL;
618 /************************************************************************
619 * OLEPictureImpl_GetIDsOfNames (IDispatch)
621 * See Windows documentation for more details on IDispatch methods.
623 static HRESULT WINAPI OLEPictureImpl_GetIDsOfNames(
624 IDispatch* iface,
625 REFIID riid,
626 LPOLESTR* rgszNames,
627 UINT cNames,
628 LCID lcid,
629 DISPID* rgDispId)
631 FIXME("():Stub\n");
633 return E_NOTIMPL;
636 /************************************************************************
637 * OLEPictureImpl_Invoke (IDispatch)
639 * See Windows documentation for more details on IDispatch methods.
641 static HRESULT WINAPI OLEPictureImpl_Invoke(
642 IDispatch* iface,
643 DISPID dispIdMember,
644 REFIID riid,
645 LCID lcid,
646 WORD wFlags,
647 DISPPARAMS* pDispParams,
648 VARIANT* pVarResult,
649 EXCEPINFO* pExepInfo,
650 UINT* puArgErr)
652 FIXME("():Stub\n");
654 return E_NOTIMPL;
658 static ICOM_VTABLE(IPicture) OLEPictureImpl_VTable =
660 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
661 OLEPictureImpl_QueryInterface,
662 OLEPictureImpl_AddRef,
663 OLEPictureImpl_Release,
664 OLEPictureImpl_get_Handle,
665 OLEPictureImpl_get_hPal,
666 OLEPictureImpl_get_Type,
667 OLEPictureImpl_get_Width,
668 OLEPictureImpl_get_Height,
669 OLEPictureImpl_Render,
670 OLEPictureImpl_set_hPal,
671 OLEPictureImpl_get_CurDC,
672 OLEPictureImpl_SelectPicture,
673 OLEPictureImpl_get_KeepOriginalFormat,
674 OLEPictureImpl_put_KeepOriginalFormat,
675 OLEPictureImpl_PictureChanged,
676 OLEPictureImpl_SaveAsFile,
677 OLEPictureImpl_get_Attributes
680 static ICOM_VTABLE(IDispatch) OLEPictureImpl_IDispatch_VTable =
682 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
683 OLEPictureImpl_IDispatch_QueryInterface,
684 OLEPictureImpl_IDispatch_AddRef,
685 OLEPictureImpl_IDispatch_Release,
686 OLEPictureImpl_GetTypeInfoCount,
687 OLEPictureImpl_GetTypeInfo,
688 OLEPictureImpl_GetIDsOfNames,
689 OLEPictureImpl_Invoke
692 /***********************************************************************
693 * OleCreatePictureIndirect
695 HRESULT WINAPI OleCreatePictureIndirect(LPPICTDESC lpPictDesc, REFIID riid,
696 BOOL fOwn, LPVOID *ppvObj )
698 OLEPictureImpl* newPict = NULL;
699 HRESULT hr = S_OK;
701 TRACE("(%p,%p,%d,%p)\n", lpPictDesc, riid, fOwn, ppvObj);
704 * Sanity check
706 if (ppvObj==0)
707 return E_POINTER;
709 *ppvObj = NULL;
712 * Try to construct a new instance of the class.
714 newPict = OLEPictureImpl_Construct(lpPictDesc, fOwn);
716 if (newPict == NULL)
717 return E_OUTOFMEMORY;
720 * Make sure it supports the interface required by the caller.
722 hr = IPicture_QueryInterface((IPicture*)newPict, riid, ppvObj);
725 * Release the reference obtained in the constructor. If
726 * the QueryInterface was unsuccessful, it will free the class.
728 IPicture_Release((IPicture*)newPict);
730 return hr;
734 /***********************************************************************
735 * OleLoadPicture
737 HRESULT WINAPI OleLoadPicture( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
738 REFIID reed, LPVOID *ppvObj )
740 FIXME("(%p,%ld,%d,%p,%p), not implemented\n",
741 lpstream, lSize, fRunmode, reed, ppvObj);
742 return S_OK;