Handle the %f case in wsprintf.
[wine.git] / dlls / oleaut32 / olepicture.c
blob1b931b372f0e19137e94c3d504c128a8d7d5b1ba
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 <string.h>
26 #include "winerror.h"
27 #include "winbase.h"
28 #include "wingdi.h"
29 #include "winuser.h"
30 #include "ole2.h"
31 #include "olectl.h"
32 #include "wine/obj_picture.h"
33 #include "debugtools.h"
35 DEFAULT_DEBUG_CHANNEL(ole);
37 /*************************************************************************
38 * Declaration of implementation class
41 typedef struct OLEPictureImpl {
44 * IPicture handles IUnknown
47 ICOM_VTABLE(IPicture) *lpvtbl1;
48 ICOM_VTABLE(IDispatch) *lpvtbl2;
49 ICOM_VTABLE(IPersistStream) *lpvtbl3;
51 /* Object referenece count */
52 DWORD ref;
54 /* We own the object and must destroy it ourselves */
55 BOOL fOwn;
57 /* Picture description */
58 PICTDESC desc;
60 /* These are the pixel size of a bitmap */
61 DWORD origWidth;
62 DWORD origHeight;
64 /* And these are the size of the picture converted into HIMETRIC units */
65 OLE_XSIZE_HIMETRIC himetricWidth;
66 OLE_YSIZE_HIMETRIC himetricHeight;
68 } OLEPictureImpl;
71 * Macros to retrieve pointer to IUnknown (IPicture) from the other VTables.
73 #define ICOM_THIS_From_IDispatch(impl, name) \
74 impl *This = (impl*)(((char*)name)-sizeof(void*));
76 #define ICOM_THIS_From_IPersistStream(impl, name) \
77 impl *This = (impl*)(((char*)name)-2*sizeof(void*));
80 * Predeclare VTables. They get initialized at the end.
82 static ICOM_VTABLE(IPicture) OLEPictureImpl_VTable;
83 static ICOM_VTABLE(IDispatch) OLEPictureImpl_IDispatch_VTable;
84 static ICOM_VTABLE(IPersistStream) OLEPictureImpl_IPersistStream_VTable;
86 /***********************************************************************
87 * Implementation of the OLEPictureImpl class.
90 /************************************************************************
91 * OLEPictureImpl_Construct
93 * This method will construct a new instance of the OLEPictureImpl
94 * class.
96 * The caller of this method must release the object when it's
97 * done with it.
99 static OLEPictureImpl* OLEPictureImpl_Construct(LPPICTDESC pictDesc, BOOL fOwn)
101 OLEPictureImpl* newObject = 0;
102 TRACE("(%p) type = %d\n", pictDesc, pictDesc->picType);
105 * Allocate space for the object.
107 newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(OLEPictureImpl));
109 if (newObject==0)
110 return newObject;
113 * Initialize the virtual function table.
115 newObject->lpvtbl1 = &OLEPictureImpl_VTable;
116 newObject->lpvtbl2 = &OLEPictureImpl_IDispatch_VTable;
117 newObject->lpvtbl3 = &OLEPictureImpl_IPersistStream_VTable;
120 * Start with one reference count. The caller of this function
121 * must release the interface pointer when it is done.
123 newObject->ref = 1;
125 newObject->fOwn = fOwn;
127 if(pictDesc->cbSizeofstruct != sizeof(PICTDESC)) {
128 FIXME("struct size = %d\n", pictDesc->cbSizeofstruct);
130 memcpy(&newObject->desc, pictDesc, sizeof(PICTDESC));
132 switch(pictDesc->picType) {
133 case PICTYPE_BITMAP:
135 BITMAP bm;
136 HDC hdcRef;
138 TRACE("bitmap handle %08x\n", pictDesc->u.bmp.hbitmap);
139 if(GetObjectA(pictDesc->u.bmp.hbitmap, sizeof(bm), &bm) != sizeof(bm)) {
140 ERR("GetObject fails\n");
141 break;
144 newObject->origWidth = bm.bmWidth;
145 newObject->origHeight = bm.bmHeight;
147 /* The width and height are stored in HIMETRIC units (0.01 mm),
148 so we take our pixel width divide by pixels per inch and
149 multiply by 25.4 * 100 */
151 /* Should we use GetBitmapDimension if available? */
153 hdcRef = CreateCompatibleDC(0);
155 newObject->himetricWidth = (bm.bmWidth * 2540) /
156 GetDeviceCaps(hdcRef, LOGPIXELSX);
157 newObject->himetricHeight = (bm.bmHeight * 2540) /
158 GetDeviceCaps(hdcRef, LOGPIXELSY);
159 DeleteDC(hdcRef);
161 break;
163 case PICTYPE_METAFILE:
164 TRACE("metafile handle %08x\n", pictDesc->u.wmf.hmeta);
165 newObject->himetricWidth = pictDesc->u.wmf.xExt;
166 newObject->himetricHeight = pictDesc->u.wmf.yExt;
167 break;
169 case PICTYPE_ICON:
170 case PICTYPE_ENHMETAFILE:
171 default:
172 FIXME("Unsupported type %d\n", pictDesc->picType);
173 newObject->himetricWidth = newObject->himetricHeight = 0;
174 break;
177 TRACE("returning %p\n", newObject);
178 return newObject;
181 /************************************************************************
182 * OLEPictureImpl_Destroy
184 * This method is called by the Release method when the reference
185 * count goes down to 0. It will free all resources used by
186 * this object. */
187 static void OLEPictureImpl_Destroy(OLEPictureImpl* Obj)
189 TRACE("(%p)\n", Obj);
191 if(Obj->fOwn) { /* We need to destroy the picture */
192 switch(Obj->desc.picType) {
193 case PICTYPE_BITMAP:
194 DeleteObject(Obj->desc.u.bmp.hbitmap);
195 break;
196 case PICTYPE_METAFILE:
197 DeleteMetaFile(Obj->desc.u.wmf.hmeta);
198 break;
199 case PICTYPE_ICON:
200 DestroyIcon(Obj->desc.u.icon.hicon);
201 break;
202 case PICTYPE_ENHMETAFILE:
203 DeleteEnhMetaFile(Obj->desc.u.emf.hemf);
204 break;
205 default:
206 FIXME("Unsupported type %d - unable to delete\n", Obj->desc.picType);
207 break;
210 HeapFree(GetProcessHeap(), 0, Obj);
213 static ULONG WINAPI OLEPictureImpl_AddRef(IPicture* iface);
215 /************************************************************************
216 * OLEPictureImpl_QueryInterface (IUnknown)
218 * See Windows documentation for more details on IUnknown methods.
220 static HRESULT WINAPI OLEPictureImpl_QueryInterface(
221 IPicture* iface,
222 REFIID riid,
223 void** ppvObject)
225 ICOM_THIS(OLEPictureImpl, iface);
226 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
229 * Perform a sanity check on the parameters.
231 if ( (This==0) || (ppvObject==0) )
232 return E_INVALIDARG;
235 * Initialize the return parameter.
237 *ppvObject = 0;
240 * Compare the riid with the interface IDs implemented by this object.
242 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
244 *ppvObject = (IPicture*)This;
246 else if (memcmp(&IID_IPicture, riid, sizeof(IID_IPicture)) == 0)
248 *ppvObject = (IPicture*)This;
250 else if (memcmp(&IID_IDispatch, riid, sizeof(IID_IDispatch)) == 0)
252 *ppvObject = (IDispatch*)&(This->lpvtbl2);
254 else if (memcmp(&IID_IPictureDisp, riid, sizeof(IID_IPictureDisp)) == 0)
256 *ppvObject = (IDispatch*)&(This->lpvtbl2);
258 /* else if (memcmp(&IID_IPersistStream, riid, sizeof(IID_IPersistStream)) == 0)
260 *ppvObject = (IPersistStream*)&(This->lpvtbl3);
264 * Check that we obtained an interface.
266 if ((*ppvObject)==0)
268 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
269 return E_NOINTERFACE;
273 * Query Interface always increases the reference count by one when it is
274 * successful
276 OLEPictureImpl_AddRef((IPicture*)This);
278 return S_OK;;
281 /************************************************************************
282 * OLEPictureImpl_AddRef (IUnknown)
284 * See Windows documentation for more details on IUnknown methods.
286 static ULONG WINAPI OLEPictureImpl_AddRef(
287 IPicture* iface)
289 ICOM_THIS(OLEPictureImpl, iface);
290 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
291 This->ref++;
293 return This->ref;
296 /************************************************************************
297 * OLEPictureImpl_Release (IUnknown)
299 * See Windows documentation for more details on IUnknown methods.
301 static ULONG WINAPI OLEPictureImpl_Release(
302 IPicture* iface)
304 ICOM_THIS(OLEPictureImpl, iface);
305 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
308 * Decrease the reference count on this object.
310 This->ref--;
313 * If the reference count goes down to 0, perform suicide.
315 if (This->ref==0)
317 OLEPictureImpl_Destroy(This);
319 return 0;
322 return This->ref;
326 /************************************************************************
327 * OLEPictureImpl_get_Handle
329 static HRESULT WINAPI OLEPictureImpl_get_Handle(IPicture *iface,
330 OLE_HANDLE *phandle)
332 ICOM_THIS(OLEPictureImpl, iface);
333 TRACE("(%p)->(%p)\n", This, phandle);
334 switch(This->desc.picType) {
335 case PICTYPE_BITMAP:
336 *phandle = This->desc.u.bmp.hbitmap;
337 break;
338 case PICTYPE_METAFILE:
339 *phandle = This->desc.u.wmf.hmeta;
340 break;
341 case PICTYPE_ICON:
342 *phandle = This->desc.u.icon.hicon;
343 break;
344 case PICTYPE_ENHMETAFILE:
345 *phandle = This->desc.u.emf.hemf;
346 break;
347 default:
348 FIXME("Unimplemented type %d\n", This->desc.picType);
349 return E_NOTIMPL;
351 TRACE("returning handle %08x\n", *phandle);
352 return S_OK;
355 /************************************************************************
356 * OLEPictureImpl_get_hPal
358 static HRESULT WINAPI OLEPictureImpl_get_hPal(IPicture *iface,
359 OLE_HANDLE *phandle)
361 ICOM_THIS(OLEPictureImpl, iface);
362 FIXME("(%p)->(%p): stub\n", This, phandle);
363 return E_NOTIMPL;
366 /************************************************************************
367 * OLEPictureImpl_get_Type
369 static HRESULT WINAPI OLEPictureImpl_get_Type(IPicture *iface,
370 short *ptype)
372 ICOM_THIS(OLEPictureImpl, iface);
373 TRACE("(%p)->(%p): type is %d\n", This, ptype, This->desc.picType);
374 *ptype = This->desc.picType;
375 return S_OK;
378 /************************************************************************
379 * OLEPictureImpl_get_Width
381 static HRESULT WINAPI OLEPictureImpl_get_Width(IPicture *iface,
382 OLE_XSIZE_HIMETRIC *pwidth)
384 ICOM_THIS(OLEPictureImpl, iface);
385 TRACE("(%p)->(%p): width is %ld\n", This, pwidth, This->himetricWidth);
386 *pwidth = This->himetricWidth;
387 return S_OK;
390 /************************************************************************
391 * OLEPictureImpl_get_Height
393 static HRESULT WINAPI OLEPictureImpl_get_Height(IPicture *iface,
394 OLE_YSIZE_HIMETRIC *pheight)
396 ICOM_THIS(OLEPictureImpl, iface);
397 TRACE("(%p)->(%p): height is %ld\n", This, pheight, This->himetricHeight);
398 *pheight = This->himetricHeight;
399 return S_OK;
402 /************************************************************************
403 * OLEPictureImpl_Render
405 static HRESULT WINAPI OLEPictureImpl_Render(IPicture *iface, HDC hdc,
406 long x, long y, long cx, long cy,
407 OLE_XPOS_HIMETRIC xSrc,
408 OLE_YPOS_HIMETRIC ySrc,
409 OLE_XSIZE_HIMETRIC cxSrc,
410 OLE_YSIZE_HIMETRIC cySrc,
411 LPCRECT prcWBounds)
413 ICOM_THIS(OLEPictureImpl, iface);
414 TRACE("(%p)->(%08x, (%ld,%ld), (%ld,%ld) <- (%ld,%ld), (%ld,%ld), %p)\n",
415 This, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, prcWBounds);
416 if(prcWBounds)
417 TRACE("prcWBounds (%d,%d) - (%d,%d)\n", prcWBounds->left, prcWBounds->top,
418 prcWBounds->right, prcWBounds->bottom);
420 switch(This->desc.picType) {
421 case PICTYPE_BITMAP:
423 HBITMAP hbmpOld;
424 HDC hdcBmp;
426 /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
427 NB y-axis gets flipped */
429 hdcBmp = CreateCompatibleDC(0);
430 SetMapMode(hdcBmp, MM_ANISOTROPIC);
431 SetWindowOrgEx(hdcBmp, 0, 0, NULL);
432 SetWindowExtEx(hdcBmp, This->himetricWidth, This->himetricHeight, NULL);
433 SetViewportOrgEx(hdcBmp, 0, This->origHeight, NULL);
434 SetViewportExtEx(hdcBmp, This->origWidth, -This->origHeight, NULL);
436 hbmpOld = SelectObject(hdcBmp, This->desc.u.bmp.hbitmap);
438 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCCOPY);
440 SelectObject(hdcBmp, hbmpOld);
441 DeleteDC(hdcBmp);
443 break;
445 case PICTYPE_METAFILE:
446 case PICTYPE_ICON:
447 case PICTYPE_ENHMETAFILE:
448 default:
449 FIXME("type %d not implemented\n", This->desc.picType);
450 return E_NOTIMPL;
453 return S_OK;
456 /************************************************************************
457 * OLEPictureImpl_set_hPal
459 static HRESULT WINAPI OLEPictureImpl_set_hPal(IPicture *iface,
460 OLE_HANDLE hpal)
462 ICOM_THIS(OLEPictureImpl, iface);
463 FIXME("(%p)->(%08x): stub\n", This, hpal);
464 return E_NOTIMPL;
467 /************************************************************************
468 * OLEPictureImpl_get_CurDC
470 static HRESULT WINAPI OLEPictureImpl_get_CurDC(IPicture *iface,
471 HDC *phdc)
473 ICOM_THIS(OLEPictureImpl, iface);
474 FIXME("(%p)->(%p): stub\n", This, phdc);
475 return E_NOTIMPL;
478 /************************************************************************
479 * OLEPictureImpl_SelectPicture
481 static HRESULT WINAPI OLEPictureImpl_SelectPicture(IPicture *iface,
482 HDC hdcIn,
483 HDC *phdcOut,
484 OLE_HANDLE *phbmpOut)
486 ICOM_THIS(OLEPictureImpl, iface);
487 FIXME("(%p)->(%08x, %p, %p): stub\n", This, hdcIn, phdcOut, phbmpOut);
488 return E_NOTIMPL;
491 /************************************************************************
492 * OLEPictureImpl_get_KeepOriginalFormat
494 static HRESULT WINAPI OLEPictureImpl_get_KeepOriginalFormat(IPicture *iface,
495 BOOL *pfKeep)
497 ICOM_THIS(OLEPictureImpl, iface);
498 FIXME("(%p)->(%p): stub\n", This, pfKeep);
499 return E_NOTIMPL;
502 /************************************************************************
503 * OLEPictureImpl_put_KeepOriginalFormat
505 static HRESULT WINAPI OLEPictureImpl_put_KeepOriginalFormat(IPicture *iface,
506 BOOL keep)
508 ICOM_THIS(OLEPictureImpl, iface);
509 FIXME("(%p)->(%d): stub\n", This, keep);
510 return E_NOTIMPL;
513 /************************************************************************
514 * OLEPictureImpl_PictureChanged
516 static HRESULT WINAPI OLEPictureImpl_PictureChanged(IPicture *iface)
518 ICOM_THIS(OLEPictureImpl, iface);
519 FIXME("(%p)->(): stub\n", This);
520 return E_NOTIMPL;
523 /************************************************************************
524 * OLEPictureImpl_SaveAsFile
526 static HRESULT WINAPI OLEPictureImpl_SaveAsFile(IPicture *iface,
527 IStream *pstream,
528 BOOL SaveMemCopy,
529 LONG *pcbSize)
531 ICOM_THIS(OLEPictureImpl, iface);
532 FIXME("(%p)->(%p, %d, %p): stub\n", This, pstream, SaveMemCopy, pcbSize);
533 return E_NOTIMPL;
536 /************************************************************************
537 * OLEPictureImpl_get_Attributes
539 static HRESULT WINAPI OLEPictureImpl_get_Attributes(IPicture *iface,
540 DWORD *pdwAttr)
542 ICOM_THIS(OLEPictureImpl, iface);
543 FIXME("(%p)->(%p): stub\n", This, pdwAttr);
544 return E_NOTIMPL;
549 /************************************************************************
550 * IDispatch
552 /************************************************************************
553 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
555 * See Windows documentation for more details on IUnknown methods.
557 static HRESULT WINAPI OLEPictureImpl_IDispatch_QueryInterface(
558 IDispatch* iface,
559 REFIID riid,
560 VOID** ppvoid)
562 ICOM_THIS_From_IDispatch(IPicture, iface);
564 return IPicture_QueryInterface(This, riid, ppvoid);
567 /************************************************************************
568 * OLEPictureImpl_IDispatch_AddRef (IUnknown)
570 * See Windows documentation for more details on IUnknown methods.
572 static ULONG WINAPI OLEPictureImpl_IDispatch_AddRef(
573 IDispatch* iface)
575 ICOM_THIS_From_IDispatch(IPicture, iface);
577 return IPicture_AddRef(This);
580 /************************************************************************
581 * OLEPictureImpl_IDispatch_Release (IUnknown)
583 * See Windows documentation for more details on IUnknown methods.
585 static ULONG WINAPI OLEPictureImpl_IDispatch_Release(
586 IDispatch* iface)
588 ICOM_THIS_From_IDispatch(IPicture, iface);
590 return IPicture_Release(This);
593 /************************************************************************
594 * OLEPictureImpl_GetTypeInfoCount (IDispatch)
596 * See Windows documentation for more details on IDispatch methods.
598 static HRESULT WINAPI OLEPictureImpl_GetTypeInfoCount(
599 IDispatch* iface,
600 unsigned int* pctinfo)
602 FIXME("():Stub\n");
604 return E_NOTIMPL;
607 /************************************************************************
608 * OLEPictureImpl_GetTypeInfo (IDispatch)
610 * See Windows documentation for more details on IDispatch methods.
612 static HRESULT WINAPI OLEPictureImpl_GetTypeInfo(
613 IDispatch* iface,
614 UINT iTInfo,
615 LCID lcid,
616 ITypeInfo** ppTInfo)
618 FIXME("():Stub\n");
620 return E_NOTIMPL;
623 /************************************************************************
624 * OLEPictureImpl_GetIDsOfNames (IDispatch)
626 * See Windows documentation for more details on IDispatch methods.
628 static HRESULT WINAPI OLEPictureImpl_GetIDsOfNames(
629 IDispatch* iface,
630 REFIID riid,
631 LPOLESTR* rgszNames,
632 UINT cNames,
633 LCID lcid,
634 DISPID* rgDispId)
636 FIXME("():Stub\n");
638 return E_NOTIMPL;
641 /************************************************************************
642 * OLEPictureImpl_Invoke (IDispatch)
644 * See Windows documentation for more details on IDispatch methods.
646 static HRESULT WINAPI OLEPictureImpl_Invoke(
647 IDispatch* iface,
648 DISPID dispIdMember,
649 REFIID riid,
650 LCID lcid,
651 WORD wFlags,
652 DISPPARAMS* pDispParams,
653 VARIANT* pVarResult,
654 EXCEPINFO* pExepInfo,
655 UINT* puArgErr)
657 FIXME("():Stub\n");
659 return E_NOTIMPL;
663 static ICOM_VTABLE(IPicture) OLEPictureImpl_VTable =
665 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
666 OLEPictureImpl_QueryInterface,
667 OLEPictureImpl_AddRef,
668 OLEPictureImpl_Release,
669 OLEPictureImpl_get_Handle,
670 OLEPictureImpl_get_hPal,
671 OLEPictureImpl_get_Type,
672 OLEPictureImpl_get_Width,
673 OLEPictureImpl_get_Height,
674 OLEPictureImpl_Render,
675 OLEPictureImpl_set_hPal,
676 OLEPictureImpl_get_CurDC,
677 OLEPictureImpl_SelectPicture,
678 OLEPictureImpl_get_KeepOriginalFormat,
679 OLEPictureImpl_put_KeepOriginalFormat,
680 OLEPictureImpl_PictureChanged,
681 OLEPictureImpl_SaveAsFile,
682 OLEPictureImpl_get_Attributes
685 static ICOM_VTABLE(IDispatch) OLEPictureImpl_IDispatch_VTable =
687 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
688 OLEPictureImpl_IDispatch_QueryInterface,
689 OLEPictureImpl_IDispatch_AddRef,
690 OLEPictureImpl_IDispatch_Release,
691 OLEPictureImpl_GetTypeInfoCount,
692 OLEPictureImpl_GetTypeInfo,
693 OLEPictureImpl_GetIDsOfNames,
694 OLEPictureImpl_Invoke
697 /***********************************************************************
698 * OleCreatePictureIndirect
700 HRESULT WINAPI OleCreatePictureIndirect(LPPICTDESC lpPictDesc, REFIID riid,
701 BOOL fOwn, LPVOID *ppvObj )
703 OLEPictureImpl* newPict = NULL;
704 HRESULT hr = S_OK;
706 TRACE("(%p,%p,%d,%p)\n", lpPictDesc, riid, fOwn, ppvObj);
709 * Sanity check
711 if (ppvObj==0)
712 return E_POINTER;
714 *ppvObj = NULL;
717 * Try to construct a new instance of the class.
719 newPict = OLEPictureImpl_Construct(lpPictDesc, fOwn);
721 if (newPict == NULL)
722 return E_OUTOFMEMORY;
725 * Make sure it supports the interface required by the caller.
727 hr = IPicture_QueryInterface((IPicture*)newPict, riid, ppvObj);
730 * Release the reference obtained in the constructor. If
731 * the QueryInterface was unsuccessful, it will free the class.
733 IPicture_Release((IPicture*)newPict);
735 return hr;
739 /***********************************************************************
740 * OleLoadPicture
742 HRESULT WINAPI OleLoadPicture( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
743 REFIID reed, LPVOID *ppvObj )
745 FIXME("(%p,%ld,%d,%p,%p), not implemented\n",
746 lpstream, lSize, fRunmode, reed, ppvObj);
747 return S_OK;
750 /***********************************************************************
751 * OleLoadPictureEx
753 HRESULT WINAPI OleLoadPictureEx( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
754 REFIID reed, DWORD xsiz, DWORD ysiz, DWORD flags, LPVOID *ppvObj )
756 FIXME("(%p,%ld,%d,%p,%lx,%lx,%lx,%p), not implemented\n",
757 lpstream, lSize, fRunmode, reed, xsiz, ysiz, flags, ppvObj);
758 return S_OK;