source: trunk/src/oleaut32/olepicture.c@ 8889

Last change on this file since 8889 was 8450, checked in by sandervl, 23 years ago

Wine resync

File size: 35.7 KB
Line 
1/*
2 * OLE Picture object
3 *
4 * Implementation of OLE IPicture and related interfaces
5 *
6 * Copyright 2000 Huw D M Davies for CodeWeavers.
7 * Copyright 2001 Marcus Meissner
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 *
23 * BUGS
24 *
25 * Support PICTYPE_BITMAP and PICTYPE_ICON, altough only bitmaps very well..
26 * Lots of methods are just stubs.
27 *
28 *
29 * NOTES (or things that msdn doesn't tell you)
30 *
31 * The width and height properties are returned in HIMETRIC units (0.01mm)
32 * IPicture::Render also uses these to select a region of the src picture.
33 * A bitmap's size is converted into these units by using the screen resolution
34 * thus an 8x8 bitmap on a 96dpi screen has a size of 212x212 (8/96 * 2540).
35 *
36 */
37
38#include "config.h"
39
40#include <unistd.h>
41#include <stdio.h>
42#include <string.h>
43#include "winerror.h"
44#include "winbase.h"
45#include "wingdi.h"
46#include "winuser.h"
47#include "ole2.h"
48#include "olectl.h"
49#include "oleauto.h"
50#include "wine/obj_picture.h"
51#include "wine/obj_connection.h"
52#include "connpt.h"
53#include "wine/debug.h"
54
55#include "wine/wingdi16.h"
56#include "cursoricon.h"
57
58#ifdef HAVE_LIBJPEG
59/* This is a hack, so jpeglib.h does not redefine INT32 and the like*/
60#define XMD_H
61#define UINT16 JPEG_UINT16
62#ifdef HAVE_JPEGLIB_H
63# include <jpeglib.h>
64#endif
65#undef UINT16
66#endif
67
68WINE_DEFAULT_DEBUG_CHANNEL(ole);
69
70/*************************************************************************
71 * Declaration of implementation class
72 */
73
74typedef struct OLEPictureImpl {
75
76 /*
77 * IPicture handles IUnknown
78 */
79
80 ICOM_VTABLE(IPicture) *lpvtbl1;
81 ICOM_VTABLE(IDispatch) *lpvtbl2;
82 ICOM_VTABLE(IPersistStream) *lpvtbl3;
83 ICOM_VTABLE(IConnectionPointContainer) *lpvtbl4;
84
85 /* Object referenece count */
86 DWORD ref;
87
88 /* We own the object and must destroy it ourselves */
89 BOOL fOwn;
90
91 /* Picture description */
92 PICTDESC desc;
93
94 /* These are the pixel size of a bitmap */
95 DWORD origWidth;
96 DWORD origHeight;
97
98 /* And these are the size of the picture converted into HIMETRIC units */
99 OLE_XSIZE_HIMETRIC himetricWidth;
100 OLE_YSIZE_HIMETRIC himetricHeight;
101
102 IConnectionPoint *pCP;
103
104 BOOL keepOrigFormat;
105 HDC hDCCur;
106} OLEPictureImpl;
107
108/*
109 * Macros to retrieve pointer to IUnknown (IPicture) from the other VTables.
110 */
111#define ICOM_THIS_From_IDispatch(impl, name) \
112 impl *This = (impl*)(((char*)name)-sizeof(void*));
113#define ICOM_THIS_From_IPersistStream(impl, name) \
114 impl *This = (impl*)(((char*)name)-2*sizeof(void*));
115#define ICOM_THIS_From_IConnectionPointContainer(impl, name) \
116 impl *This = (impl*)(((char*)name)-3*sizeof(void*));
117
118/*
119 * Predeclare VTables. They get initialized at the end.
120 */
121static ICOM_VTABLE(IPicture) OLEPictureImpl_VTable;
122static ICOM_VTABLE(IDispatch) OLEPictureImpl_IDispatch_VTable;
123static ICOM_VTABLE(IPersistStream) OLEPictureImpl_IPersistStream_VTable;
124static ICOM_VTABLE(IConnectionPointContainer) OLEPictureImpl_IConnectionPointContainer_VTable;
125
126/***********************************************************************
127 * Implementation of the OLEPictureImpl class.
128 */
129
130static void OLEPictureImpl_SetBitmap(OLEPictureImpl*This) {
131 BITMAP bm;
132 HDC hdcRef;
133
134 TRACE("bitmap handle %08x\n", This->desc.u.bmp.hbitmap);
135 if(GetObjectA(This->desc.u.bmp.hbitmap, sizeof(bm), &bm) != sizeof(bm)) {
136 ERR("GetObject fails\n");
137 return;
138 }
139 This->origWidth = bm.bmWidth;
140 This->origHeight = bm.bmHeight;
141 /* The width and height are stored in HIMETRIC units (0.01 mm),
142 so we take our pixel width divide by pixels per inch and
143 multiply by 25.4 * 100 */
144 /* Should we use GetBitmapDimension if available? */
145 hdcRef = CreateCompatibleDC(0);
146 This->himetricWidth =(bm.bmWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
147 This->himetricHeight=(bm.bmHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
148 DeleteDC(hdcRef);
149}
150
151/************************************************************************
152 * OLEPictureImpl_Construct
153 *
154 * This method will construct a new instance of the OLEPictureImpl
155 * class.
156 *
157 * The caller of this method must release the object when it's
158 * done with it.
159 */
160static OLEPictureImpl* OLEPictureImpl_Construct(LPPICTDESC pictDesc, BOOL fOwn)
161{
162 OLEPictureImpl* newObject = 0;
163
164 if (pictDesc)
165 TRACE("(%p) type = %d\n", pictDesc, pictDesc->picType);
166
167 /*
168 * Allocate space for the object.
169 */
170 newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(OLEPictureImpl));
171
172 if (newObject==0)
173 return newObject;
174
175 /*
176 * Initialize the virtual function table.
177 */
178 newObject->lpvtbl1 = &OLEPictureImpl_VTable;
179 newObject->lpvtbl2 = &OLEPictureImpl_IDispatch_VTable;
180 newObject->lpvtbl3 = &OLEPictureImpl_IPersistStream_VTable;
181 newObject->lpvtbl4 = &OLEPictureImpl_IConnectionPointContainer_VTable;
182
183 CreateConnectionPoint((IUnknown*)newObject,&IID_IPropertyNotifySink,&newObject->pCP);
184
185 /*
186 * Start with one reference count. The caller of this function
187 * must release the interface pointer when it is done.
188 */
189 newObject->ref = 1;
190 newObject->hDCCur = 0;
191
192 newObject->fOwn = fOwn;
193
194 /* dunno about original value */
195 newObject->keepOrigFormat = TRUE;
196
197 if (pictDesc) {
198 if(pictDesc->cbSizeofstruct != sizeof(PICTDESC)) {
199 FIXME("struct size = %d\n", pictDesc->cbSizeofstruct);
200 }
201 memcpy(&newObject->desc, pictDesc, sizeof(PICTDESC));
202
203
204 switch(pictDesc->picType) {
205 case PICTYPE_BITMAP:
206 OLEPictureImpl_SetBitmap(newObject);
207 break;
208
209 case PICTYPE_METAFILE:
210 TRACE("metafile handle %08x\n", pictDesc->u.wmf.hmeta);
211 newObject->himetricWidth = pictDesc->u.wmf.xExt;
212 newObject->himetricHeight = pictDesc->u.wmf.yExt;
213 break;
214
215 case PICTYPE_ICON:
216 case PICTYPE_ENHMETAFILE:
217 default:
218 FIXME("Unsupported type %d\n", pictDesc->picType);
219 newObject->himetricWidth = newObject->himetricHeight = 0;
220 break;
221 }
222 } else {
223 newObject->desc.picType = PICTYPE_UNINITIALIZED;
224 }
225
226 TRACE("returning %p\n", newObject);
227 return newObject;
228}
229
230/************************************************************************
231 * OLEPictureImpl_Destroy
232 *
233 * This method is called by the Release method when the reference
234 * count goes down to 0. It will free all resources used by
235 * this object. */
236static void OLEPictureImpl_Destroy(OLEPictureImpl* Obj)
237{
238 TRACE("(%p)\n", Obj);
239
240 if(Obj->fOwn) { /* We need to destroy the picture */
241 switch(Obj->desc.picType) {
242 case PICTYPE_BITMAP:
243 DeleteObject(Obj->desc.u.bmp.hbitmap);
244 break;
245 case PICTYPE_METAFILE:
246 DeleteMetaFile(Obj->desc.u.wmf.hmeta);
247 break;
248 case PICTYPE_ICON:
249 DestroyIcon(Obj->desc.u.icon.hicon);
250 break;
251 case PICTYPE_ENHMETAFILE:
252 DeleteEnhMetaFile(Obj->desc.u.emf.hemf);
253 break;
254 default:
255 FIXME("Unsupported type %d - unable to delete\n", Obj->desc.picType);
256 break;
257 }
258 }
259 HeapFree(GetProcessHeap(), 0, Obj);
260}
261
262static ULONG WINAPI OLEPictureImpl_AddRef(IPicture* iface);
263
264/************************************************************************
265 * OLEPictureImpl_QueryInterface (IUnknown)
266 *
267 * See Windows documentation for more details on IUnknown methods.
268 */
269static HRESULT WINAPI OLEPictureImpl_QueryInterface(
270 IPicture* iface,
271 REFIID riid,
272 void** ppvObject)
273{
274 ICOM_THIS(OLEPictureImpl, iface);
275 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
276
277 /*
278 * Perform a sanity check on the parameters.
279 */
280 if ( (This==0) || (ppvObject==0) )
281 return E_INVALIDARG;
282
283 /*
284 * Initialize the return parameter.
285 */
286 *ppvObject = 0;
287
288 /*
289 * Compare the riid with the interface IDs implemented by this object.
290 */
291 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
292 {
293 *ppvObject = (IPicture*)This;
294 }
295 else if (memcmp(&IID_IPicture, riid, sizeof(IID_IPicture)) == 0)
296 {
297 *ppvObject = (IPicture*)This;
298 }
299 else if (memcmp(&IID_IDispatch, riid, sizeof(IID_IDispatch)) == 0)
300 {
301 *ppvObject = (IDispatch*)&(This->lpvtbl2);
302 }
303 else if (memcmp(&IID_IPictureDisp, riid, sizeof(IID_IPictureDisp)) == 0)
304 {
305 *ppvObject = (IDispatch*)&(This->lpvtbl2);
306 }
307 else if (memcmp(&IID_IPersistStream, riid, sizeof(IID_IPersistStream)) == 0)
308 {
309 *ppvObject = (IPersistStream*)&(This->lpvtbl3);
310 }
311 else if (memcmp(&IID_IConnectionPointContainer, riid, sizeof(IID_IConnectionPointContainer)) == 0)
312 {
313 *ppvObject = (IConnectionPointContainer*)&(This->lpvtbl4);
314 }
315 /*
316 * Check that we obtained an interface.
317 */
318 if ((*ppvObject)==0)
319 {
320 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
321 return E_NOINTERFACE;
322 }
323
324 /*
325 * Query Interface always increases the reference count by one when it is
326 * successful
327 */
328 OLEPictureImpl_AddRef((IPicture*)This);
329
330 return S_OK;;
331}
332/***********************************************************************
333 * OLEPicture_SendNotify (internal)
334 *
335 * Sends notification messages of changed properties to any interested
336 * connections.
337 */
338static void OLEPicture_SendNotify(OLEPictureImpl* this, DISPID dispID)
339{
340 IEnumConnections *pEnum;
341 CONNECTDATA CD;
342
343 if (IConnectionPoint_EnumConnections(this->pCP, &pEnum))
344 return;
345 while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) {
346 IPropertyNotifySink *sink;
347
348 IUnknown_QueryInterface(CD.pUnk, &IID_IPropertyNotifySink, (LPVOID)&sink);
349 IPropertyNotifySink_OnChanged(sink, dispID);
350 IPropertyNotifySink_Release(sink);
351 IUnknown_Release(CD.pUnk);
352 }
353 IEnumConnections_Release(pEnum);
354 return;
355}
356
357/************************************************************************
358 * OLEPictureImpl_AddRef (IUnknown)
359 *
360 * See Windows documentation for more details on IUnknown methods.
361 */
362static ULONG WINAPI OLEPictureImpl_AddRef(
363 IPicture* iface)
364{
365 ICOM_THIS(OLEPictureImpl, iface);
366 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
367 This->ref++;
368
369 return This->ref;
370}
371
372/************************************************************************
373 * OLEPictureImpl_Release (IUnknown)
374 *
375 * See Windows documentation for more details on IUnknown methods.
376 */
377static ULONG WINAPI OLEPictureImpl_Release(
378 IPicture* iface)
379{
380 ICOM_THIS(OLEPictureImpl, iface);
381 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
382
383 /*
384 * Decrease the reference count on this object.
385 */
386 This->ref--;
387
388 /*
389 * If the reference count goes down to 0, perform suicide.
390 */
391 if (This->ref==0)
392 {
393 OLEPictureImpl_Destroy(This);
394
395 return 0;
396 }
397
398 return This->ref;
399}
400
401
402/************************************************************************
403 * OLEPictureImpl_get_Handle
404 */
405static HRESULT WINAPI OLEPictureImpl_get_Handle(IPicture *iface,
406 OLE_HANDLE *phandle)
407{
408 ICOM_THIS(OLEPictureImpl, iface);
409 TRACE("(%p)->(%p)\n", This, phandle);
410 switch(This->desc.picType) {
411 case PICTYPE_BITMAP:
412 *phandle = This->desc.u.bmp.hbitmap;
413 break;
414 case PICTYPE_METAFILE:
415 *phandle = This->desc.u.wmf.hmeta;
416 break;
417 case PICTYPE_ICON:
418 *phandle = This->desc.u.icon.hicon;
419 break;
420 case PICTYPE_ENHMETAFILE:
421 *phandle = This->desc.u.emf.hemf;
422 break;
423 default:
424 FIXME("Unimplemented type %d\n", This->desc.picType);
425 return E_NOTIMPL;
426 }
427 TRACE("returning handle %08x\n", *phandle);
428 return S_OK;
429}
430
431/************************************************************************
432 * OLEPictureImpl_get_hPal
433 */
434static HRESULT WINAPI OLEPictureImpl_get_hPal(IPicture *iface,
435 OLE_HANDLE *phandle)
436{
437 ICOM_THIS(OLEPictureImpl, iface);
438 FIXME("(%p)->(%p): stub\n", This, phandle);
439 return E_NOTIMPL;
440}
441
442/************************************************************************
443 * OLEPictureImpl_get_Type
444 */
445static HRESULT WINAPI OLEPictureImpl_get_Type(IPicture *iface,
446 short *ptype)
447{
448 ICOM_THIS(OLEPictureImpl, iface);
449 TRACE("(%p)->(%p): type is %d\n", This, ptype, This->desc.picType);
450 *ptype = This->desc.picType;
451 return S_OK;
452}
453
454/************************************************************************
455 * OLEPictureImpl_get_Width
456 */
457static HRESULT WINAPI OLEPictureImpl_get_Width(IPicture *iface,
458 OLE_XSIZE_HIMETRIC *pwidth)
459{
460 ICOM_THIS(OLEPictureImpl, iface);
461 TRACE("(%p)->(%p): width is %ld\n", This, pwidth, This->himetricWidth);
462 *pwidth = This->himetricWidth;
463 return S_OK;
464}
465
466/************************************************************************
467 * OLEPictureImpl_get_Height
468 */
469static HRESULT WINAPI OLEPictureImpl_get_Height(IPicture *iface,
470 OLE_YSIZE_HIMETRIC *pheight)
471{
472 ICOM_THIS(OLEPictureImpl, iface);
473 TRACE("(%p)->(%p): height is %ld\n", This, pheight, This->himetricHeight);
474 *pheight = This->himetricHeight;
475 return S_OK;
476}
477
478/************************************************************************
479 * OLEPictureImpl_Render
480 */
481static HRESULT WINAPI OLEPictureImpl_Render(IPicture *iface, HDC hdc,
482 long x, long y, long cx, long cy,
483 OLE_XPOS_HIMETRIC xSrc,
484 OLE_YPOS_HIMETRIC ySrc,
485 OLE_XSIZE_HIMETRIC cxSrc,
486 OLE_YSIZE_HIMETRIC cySrc,
487 LPCRECT prcWBounds)
488{
489 ICOM_THIS(OLEPictureImpl, iface);
490 TRACE("(%p)->(%08x, (%ld,%ld), (%ld,%ld) <- (%ld,%ld), (%ld,%ld), %p)\n",
491 This, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, prcWBounds);
492 if(prcWBounds)
493 TRACE("prcWBounds (%d,%d) - (%d,%d)\n", prcWBounds->left, prcWBounds->top,
494 prcWBounds->right, prcWBounds->bottom);
495
496 /*
497 * While the documentation suggests this to be here (or after rendering?)
498 * it does cause an endless recursion in my sample app. -MM 20010804
499 OLEPicture_SendNotify(This,DISPID_PICT_RENDER);
500 */
501
502 switch(This->desc.picType) {
503 case PICTYPE_BITMAP:
504 {
505 HBITMAP hbmpOld;
506 HDC hdcBmp;
507
508 /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
509 NB y-axis gets flipped */
510
511 hdcBmp = CreateCompatibleDC(0);
512 SetMapMode(hdcBmp, MM_ANISOTROPIC);
513 SetWindowOrgEx(hdcBmp, 0, 0, NULL);
514 SetWindowExtEx(hdcBmp, This->himetricWidth, This->himetricHeight, NULL);
515 SetViewportOrgEx(hdcBmp, 0, This->origHeight, NULL);
516 SetViewportExtEx(hdcBmp, This->origWidth, -This->origHeight, NULL);
517
518 hbmpOld = SelectObject(hdcBmp, This->desc.u.bmp.hbitmap);
519
520 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCCOPY);
521
522 SelectObject(hdcBmp, hbmpOld);
523 DeleteDC(hdcBmp);
524 }
525 break;
526 case PICTYPE_ICON:
527 FIXME("Not quite correct implementation of rendering icons...\n");
528 DrawIcon(hdc,x,y,This->desc.u.icon.hicon);
529 break;
530
531 case PICTYPE_METAFILE:
532 case PICTYPE_ENHMETAFILE:
533 default:
534 FIXME("type %d not implemented\n", This->desc.picType);
535 return E_NOTIMPL;
536 }
537 return S_OK;
538}
539
540/************************************************************************
541 * OLEPictureImpl_set_hPal
542 */
543static HRESULT WINAPI OLEPictureImpl_set_hPal(IPicture *iface,
544 OLE_HANDLE hpal)
545{
546 ICOM_THIS(OLEPictureImpl, iface);
547 FIXME("(%p)->(%08x): stub\n", This, hpal);
548 OLEPicture_SendNotify(This,DISPID_PICT_HPAL);
549 return E_NOTIMPL;
550}
551
552/************************************************************************
553 * OLEPictureImpl_get_CurDC
554 */
555static HRESULT WINAPI OLEPictureImpl_get_CurDC(IPicture *iface,
556 HDC *phdc)
557{
558 ICOM_THIS(OLEPictureImpl, iface);
559 TRACE("(%p), returning %x\n", This, This->hDCCur);
560 if (phdc) *phdc = This->hDCCur;
561 return S_OK;
562}
563
564/************************************************************************
565 * OLEPictureImpl_SelectPicture
566 */
567static HRESULT WINAPI OLEPictureImpl_SelectPicture(IPicture *iface,
568 HDC hdcIn,
569 HDC *phdcOut,
570 OLE_HANDLE *phbmpOut)
571{
572 ICOM_THIS(OLEPictureImpl, iface);
573 TRACE("(%p)->(%08x, %p, %p)\n", This, hdcIn, phdcOut, phbmpOut);
574 if (This->desc.picType == PICTYPE_BITMAP) {
575 SelectObject(hdcIn,This->desc.u.bmp.hbitmap);
576
577 if (phdcOut)
578 *phdcOut = This->hDCCur;
579 This->hDCCur = hdcIn;
580 if (phbmpOut)
581 *phbmpOut = This->desc.u.bmp.hbitmap;
582 return S_OK;
583 } else {
584 FIXME("Don't know how to select picture type %d\n",This->desc.picType);
585 return E_FAIL;
586 }
587}
588
589/************************************************************************
590 * OLEPictureImpl_get_KeepOriginalFormat
591 */
592static HRESULT WINAPI OLEPictureImpl_get_KeepOriginalFormat(IPicture *iface,
593 BOOL *pfKeep)
594{
595 ICOM_THIS(OLEPictureImpl, iface);
596 TRACE("(%p)->(%p)\n", This, pfKeep);
597 if (!pfKeep)
598 return E_POINTER;
599 *pfKeep = This->keepOrigFormat;
600 return S_OK;
601}
602
603/************************************************************************
604 * OLEPictureImpl_put_KeepOriginalFormat
605 */
606static HRESULT WINAPI OLEPictureImpl_put_KeepOriginalFormat(IPicture *iface,
607 BOOL keep)
608{
609 ICOM_THIS(OLEPictureImpl, iface);
610 TRACE("(%p)->(%d)\n", This, keep);
611 This->keepOrigFormat = keep;
612 /* FIXME: what DISPID notification here? */
613 return S_OK;
614}
615
616/************************************************************************
617 * OLEPictureImpl_PictureChanged
618 */
619static HRESULT WINAPI OLEPictureImpl_PictureChanged(IPicture *iface)
620{
621 ICOM_THIS(OLEPictureImpl, iface);
622 TRACE("(%p)->()\n", This);
623 OLEPicture_SendNotify(This,DISPID_PICT_HANDLE);
624 return S_OK;
625}
626
627/************************************************************************
628 * OLEPictureImpl_SaveAsFile
629 */
630static HRESULT WINAPI OLEPictureImpl_SaveAsFile(IPicture *iface,
631 IStream *pstream,
632 BOOL SaveMemCopy,
633 LONG *pcbSize)
634{
635 ICOM_THIS(OLEPictureImpl, iface);
636 FIXME("(%p)->(%p, %d, %p): stub\n", This, pstream, SaveMemCopy, pcbSize);
637 return E_NOTIMPL;
638}
639
640/************************************************************************
641 * OLEPictureImpl_get_Attributes
642 */
643static HRESULT WINAPI OLEPictureImpl_get_Attributes(IPicture *iface,
644 DWORD *pdwAttr)
645{
646 ICOM_THIS(OLEPictureImpl, iface);
647 TRACE("(%p)->(%p).\n", This, pdwAttr);
648 *pdwAttr = 0;
649 switch (This->desc.picType) {
650 case PICTYPE_BITMAP: break; /* not 'truely' scalable, see MSDN. */
651 case PICTYPE_ICON: *pdwAttr = PICTURE_TRANSPARENT;break;
652 case PICTYPE_METAFILE: *pdwAttr = PICTURE_TRANSPARENT|PICTURE_SCALABLE;break;
653 default:FIXME("Unknown pictype %d\n",This->desc.picType);break;
654 }
655 return S_OK;
656}
657
658
659/************************************************************************
660 * IConnectionPointContainer
661 */
662
663static HRESULT WINAPI OLEPictureImpl_IConnectionPointContainer_QueryInterface(
664 IConnectionPointContainer* iface,
665 REFIID riid,
666 VOID** ppvoid
667) {
668 ICOM_THIS_From_IConnectionPointContainer(IPicture,iface);
669
670 return IPicture_QueryInterface(This,riid,ppvoid);
671}
672
673static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_AddRef(
674 IConnectionPointContainer* iface)
675{
676 ICOM_THIS_From_IConnectionPointContainer(IPicture, iface);
677
678 return IPicture_AddRef(This);
679}
680
681static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_Release(
682 IConnectionPointContainer* iface)
683{
684 ICOM_THIS_From_IConnectionPointContainer(IPicture, iface);
685
686 return IPicture_Release(This);
687}
688
689static HRESULT WINAPI OLEPictureImpl_EnumConnectionPoints(
690 IConnectionPointContainer* iface,
691 IEnumConnectionPoints** ppEnum
692) {
693 ICOM_THIS_From_IConnectionPointContainer(IPicture, iface);
694
695 FIXME("(%p,%p), stub!\n",This,ppEnum);
696 return E_NOTIMPL;
697}
698
699static HRESULT WINAPI OLEPictureImpl_FindConnectionPoint(
700 IConnectionPointContainer* iface,
701 REFIID riid,
702 IConnectionPoint **ppCP
703) {
704 ICOM_THIS_From_IConnectionPointContainer(OLEPictureImpl, iface);
705 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppCP);
706 if (!ppCP)
707 return E_POINTER;
708 *ppCP = NULL;
709 if (IsEqualGUID(riid,&IID_IPropertyNotifySink))
710 return IConnectionPoint_QueryInterface(This->pCP,&IID_IConnectionPoint,(LPVOID)ppCP);
711 FIXME("tried to find connection point on %s?\n",debugstr_guid(riid));
712 return 0x80040200;
713}
714/************************************************************************
715 * IPersistStream
716 */
717/************************************************************************
718 * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown)
719 *
720 * See Windows documentation for more details on IUnknown methods.
721 */
722static HRESULT WINAPI OLEPictureImpl_IPersistStream_QueryInterface(
723 IPersistStream* iface,
724 REFIID riid,
725 VOID** ppvoid)
726{
727 ICOM_THIS_From_IPersistStream(IPicture, iface);
728
729 return IPicture_QueryInterface(This, riid, ppvoid);
730}
731
732/************************************************************************
733 * OLEPictureImpl_IPersistStream_AddRef (IUnknown)
734 *
735 * See Windows documentation for more details on IUnknown methods.
736 */
737static ULONG WINAPI OLEPictureImpl_IPersistStream_AddRef(
738 IPersistStream* iface)
739{
740 ICOM_THIS_From_IPersistStream(IPicture, iface);
741
742 return IPicture_AddRef(This);
743}
744
745/************************************************************************
746 * OLEPictureImpl_IPersistStream_Release (IUnknown)
747 *
748 * See Windows documentation for more details on IUnknown methods.
749 */
750static ULONG WINAPI OLEPictureImpl_IPersistStream_Release(
751 IPersistStream* iface)
752{
753 ICOM_THIS_From_IPersistStream(IPicture, iface);
754
755 return IPicture_Release(This);
756}
757
758/************************************************************************
759 * OLEPictureImpl_IPersistStream_GetClassID
760 */
761static HRESULT WINAPI OLEPictureImpl_GetClassID(
762 IPersistStream* iface,CLSID* pClassID)
763{
764 ICOM_THIS_From_IPersistStream(IPicture, iface);
765 FIXME("(%p),stub!\n",This);
766 return E_NOTIMPL;
767}
768
769/************************************************************************
770 * OLEPictureImpl_IPersistStream_IsDirty
771 */
772static HRESULT WINAPI OLEPictureImpl_IsDirty(
773 IPersistStream* iface)
774{
775 ICOM_THIS_From_IPersistStream(IPicture, iface);
776 FIXME("(%p),stub!\n",This);
777 return E_NOTIMPL;
778}
779
780#ifdef HAVE_LIBJPEG
781/* for the jpeg decompressor source manager. */
782static void _jpeg_init_source(j_decompress_ptr cinfo) { }
783
784static boolean _jpeg_fill_input_buffer(j_decompress_ptr cinfo) {
785 ERR("(), should not get here.\n");
786 return FALSE;
787}
788
789static void _jpeg_skip_input_data(j_decompress_ptr cinfo,long num_bytes) {
790 ERR("(%ld), should not get here.\n",num_bytes);
791}
792
793static boolean _jpeg_resync_to_restart(j_decompress_ptr cinfo, int desired) {
794 ERR("(desired=%d), should not get here.\n",desired);
795 return FALSE;
796}
797static void _jpeg_term_source(j_decompress_ptr cinfo) { }
798#endif /* HAVE_LIBJPEG */
799
800/************************************************************************
801 * OLEPictureImpl_IPersistStream_Load (IUnknown)
802 *
803 * Loads the binary data from the IStream. Starts at current position.
804 * There appears to be an 2 DWORD header:
805 * DWORD magic;
806 * DWORD len;
807 *
808 * Currently implemented: BITMAP, ICON, JPEG.
809 */
810static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
811 HRESULT hr = E_FAIL;
812 ULONG xread;
813 BYTE *xbuf;
814 DWORD header[2];
815 WORD magic;
816 ICOM_THIS_From_IPersistStream(OLEPictureImpl, iface);
817
818 TRACE("(%p,%p)\n",This,pStm);
819
820 hr=IStream_Read(pStm,header,8,&xread);
821 if (hr || xread!=8) {
822 FIXME("Failure while reading picture header (hr is %lx, nread is %ld).\n",hr,xread);
823 return hr;
824 }
825 xread = 0;
826 xbuf = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,header[1]);
827 while (xread < header[1]) {
828 ULONG nread;
829 hr = IStream_Read(pStm,xbuf+xread,header[1]-xread,&nread);
830 xread+=nread;
831 if (hr || !nread)
832 break;
833 }
834 if (xread != header[1])
835 FIXME("Could only read %ld of %ld bytes?\n",xread,header[1]);
836
837 magic = xbuf[0] + (xbuf[1]<<8);
838 switch (magic) {
839 case 0xd8ff: { /* JPEG */
840#ifdef HAVE_LIBJPEG
841 struct jpeg_decompress_struct jd;
842 struct jpeg_error_mgr jerr;
843 int ret;
844 JDIMENSION x;
845 JSAMPROW samprow;
846 BITMAPINFOHEADER bmi;
847 LPBYTE bits;
848 HDC hdcref;
849 struct jpeg_source_mgr xjsm;
850
851 /* This is basically so we can use in-memory data for jpeg decompression.
852 * We need to have all the functions.
853 */
854 xjsm.next_input_byte = xbuf;
855 xjsm.bytes_in_buffer = xread;
856 xjsm.init_source = _jpeg_init_source;
857 xjsm.fill_input_buffer = _jpeg_fill_input_buffer;
858 xjsm.skip_input_data = _jpeg_skip_input_data;
859 xjsm.resync_to_restart = _jpeg_resync_to_restart;
860 xjsm.term_source = _jpeg_term_source;
861
862 jd.err = jpeg_std_error(&jerr);
863 jpeg_create_decompress(&jd);
864 jd.src = &xjsm;
865 ret=jpeg_read_header(&jd,TRUE);
866 jpeg_start_decompress(&jd);
867 if (ret != JPEG_HEADER_OK) {
868 ERR("Jpeg image in stream has bad format, read header returned %d.\n",ret);
869 HeapFree(GetProcessHeap(),0,xbuf);
870 return E_FAIL;
871 }
872 bits = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(jd.output_height+1)*jd.output_width*jd.output_components);
873 samprow=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,jd.output_width*jd.output_components);
874 while ( jd.output_scanline<jd.output_height ) {
875 x = jpeg_read_scanlines(&jd,&samprow,1);
876 if (x != 1) {
877 FIXME("failed to read current scanline?\n");
878 break;
879 }
880 memcpy( bits+jd.output_scanline*jd.output_width*jd.output_components,
881 samprow,
882 jd.output_width*jd.output_components
883 );
884 }
885 bmi.biSize = sizeof(bmi);
886 bmi.biWidth = jd.output_width;
887 bmi.biHeight = -jd.output_height;
888 bmi.biPlanes = 1;
889 bmi.biBitCount = jd.output_components<<3;
890 bmi.biCompression = BI_RGB;
891 bmi.biSizeImage = jd.output_height*jd.output_width*jd.output_components;
892 bmi.biXPelsPerMeter = 0;
893 bmi.biYPelsPerMeter = 0;
894 bmi.biClrUsed = 0;
895 bmi.biClrImportant = 0;
896
897 HeapFree(GetProcessHeap(),0,samprow);
898 jpeg_finish_decompress(&jd);
899 jpeg_destroy_decompress(&jd);
900 hdcref = GetDC(0);
901 This->desc.u.bmp.hbitmap=CreateDIBitmap(
902 hdcref,
903 &bmi,
904 CBM_INIT,
905 bits,
906 (BITMAPINFO*)&bmi,
907 DIB_RGB_COLORS
908 );
909 DeleteDC(hdcref);
910 This->desc.picType = PICTYPE_BITMAP;
911 OLEPictureImpl_SetBitmap(This);
912 hr = S_OK;
913 HeapFree(GetProcessHeap(),0,bits);
914#else
915 ERR("Trying to load JPEG picture, but JPEG supported not compiled in.\n");
916 hr = E_FAIL;
917#endif
918 break;
919 }
920 case 0x4d42: { /* Bitmap */
921 BITMAPFILEHEADER *bfh = (BITMAPFILEHEADER*)xbuf;
922 BITMAPINFO *bi = (BITMAPINFO*)(bfh+1);
923 HDC hdcref;
924
925 /* Does not matter whether this is a coreheader or not, we only use
926 * components which are in both
927 */
928 hdcref = GetDC(0);
929 This->desc.u.bmp.hbitmap = CreateDIBitmap(
930 hdcref,
931 &(bi->bmiHeader),
932 CBM_INIT,
933 xbuf+bfh->bfOffBits,
934 bi,
935 (bi->bmiHeader.biBitCount<=8)?DIB_PAL_COLORS:DIB_RGB_COLORS
936 );
937 DeleteDC(hdcref);
938 This->desc.picType = PICTYPE_BITMAP;
939 OLEPictureImpl_SetBitmap(This);
940 hr = S_OK;
941 break;
942 }
943 case 0x0000: { /* ICON , first word is dwReserved */
944 HICON hicon;
945 CURSORICONFILEDIR *cifd = (CURSORICONFILEDIR*)xbuf;
946 int i;
947
948 /*
949 FIXME("icon.idReserved=%d\n",cifd->idReserved);
950 FIXME("icon.idType=%d\n",cifd->idType);
951 FIXME("icon.idCount=%d\n",cifd->idCount);
952
953 for (i=0;i<cifd->idCount;i++) {
954 FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
955 FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
956 FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
957 FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
958 FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
959 FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
960 FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
961 FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
962 }
963 */
964 i=0;
965 /* If we have more than one icon, try to find the best.
966 * this currently means '32 pixel wide'.
967 */
968 if (cifd->idCount!=1) {
969 for (i=0;i<cifd->idCount;i++) {
970 if (cifd->idEntries[i].bWidth == 32)
971 break;
972 }
973 if (i==cifd->idCount) i=0;
974 }
975
976 hicon = CreateIconFromResourceEx(
977 xbuf+cifd->idEntries[i].dwDIBOffset,
978 cifd->idEntries[i].dwDIBSize,
979 TRUE, /* is icon */
980 0x00030000,
981 cifd->idEntries[i].bWidth,
982 cifd->idEntries[i].bHeight,
983 0
984 );
985 if (!hicon) {
986 FIXME("CreateIcon failed.\n");
987 hr = E_FAIL;
988 } else {
989 This->desc.picType = PICTYPE_ICON;
990 This->desc.u.icon.hicon = hicon;
991 hr = S_OK;
992 }
993 break;
994 }
995 default:
996 FIXME("Unknown magic %04x\n",magic);
997 hr=E_FAIL;
998 break;
999 }
1000 HeapFree(GetProcessHeap(),0,xbuf);
1001
1002 /* FIXME: this notify is not really documented */
1003 if (hr==S_OK)
1004 OLEPicture_SendNotify(This,DISPID_PICT_TYPE);
1005 return hr;
1006}
1007
1008static HRESULT WINAPI OLEPictureImpl_Save(
1009 IPersistStream* iface,IStream*pStm,BOOL fClearDirty)
1010{
1011 ICOM_THIS_From_IPersistStream(IPicture, iface);
1012 FIXME("(%p,%p,%d),stub!\n",This,pStm,fClearDirty);
1013 return E_NOTIMPL;
1014}
1015
1016static HRESULT WINAPI OLEPictureImpl_GetSizeMax(
1017 IPersistStream* iface,ULARGE_INTEGER*pcbSize)
1018{
1019 ICOM_THIS_From_IPersistStream(IPicture, iface);
1020 FIXME("(%p,%p),stub!\n",This,pcbSize);
1021 return E_NOTIMPL;
1022}
1023
1024/************************************************************************
1025 * IDispatch
1026 */
1027/************************************************************************
1028 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
1029 *
1030 * See Windows documentation for more details on IUnknown methods.
1031 */
1032static HRESULT WINAPI OLEPictureImpl_IDispatch_QueryInterface(
1033 IDispatch* iface,
1034 REFIID riid,
1035 VOID** ppvoid)
1036{
1037 ICOM_THIS_From_IDispatch(IPicture, iface);
1038
1039 return IPicture_QueryInterface(This, riid, ppvoid);
1040}
1041
1042/************************************************************************
1043 * OLEPictureImpl_IDispatch_AddRef (IUnknown)
1044 *
1045 * See Windows documentation for more details on IUnknown methods.
1046 */
1047static ULONG WINAPI OLEPictureImpl_IDispatch_AddRef(
1048 IDispatch* iface)
1049{
1050 ICOM_THIS_From_IDispatch(IPicture, iface);
1051
1052 return IPicture_AddRef(This);
1053}
1054
1055/************************************************************************
1056 * OLEPictureImpl_IDispatch_Release (IUnknown)
1057 *
1058 * See Windows documentation for more details on IUnknown methods.
1059 */
1060static ULONG WINAPI OLEPictureImpl_IDispatch_Release(
1061 IDispatch* iface)
1062{
1063 ICOM_THIS_From_IDispatch(IPicture, iface);
1064
1065 return IPicture_Release(This);
1066}
1067
1068/************************************************************************
1069 * OLEPictureImpl_GetTypeInfoCount (IDispatch)
1070 *
1071 * See Windows documentation for more details on IDispatch methods.
1072 */
1073static HRESULT WINAPI OLEPictureImpl_GetTypeInfoCount(
1074 IDispatch* iface,
1075 unsigned int* pctinfo)
1076{
1077 FIXME("():Stub\n");
1078
1079 return E_NOTIMPL;
1080}
1081
1082/************************************************************************
1083 * OLEPictureImpl_GetTypeInfo (IDispatch)
1084 *
1085 * See Windows documentation for more details on IDispatch methods.
1086 */
1087static HRESULT WINAPI OLEPictureImpl_GetTypeInfo(
1088 IDispatch* iface,
1089 UINT iTInfo,
1090 LCID lcid,
1091 ITypeInfo** ppTInfo)
1092{
1093 FIXME("():Stub\n");
1094
1095 return E_NOTIMPL;
1096}
1097
1098/************************************************************************
1099 * OLEPictureImpl_GetIDsOfNames (IDispatch)
1100 *
1101 * See Windows documentation for more details on IDispatch methods.
1102 */
1103static HRESULT WINAPI OLEPictureImpl_GetIDsOfNames(
1104 IDispatch* iface,
1105 REFIID riid,
1106 LPOLESTR* rgszNames,
1107 UINT cNames,
1108 LCID lcid,
1109 DISPID* rgDispId)
1110{
1111 FIXME("():Stub\n");
1112
1113 return E_NOTIMPL;
1114}
1115
1116/************************************************************************
1117 * OLEPictureImpl_Invoke (IDispatch)
1118 *
1119 * See Windows documentation for more details on IDispatch methods.
1120 */
1121static HRESULT WINAPI OLEPictureImpl_Invoke(
1122 IDispatch* iface,
1123 DISPID dispIdMember,
1124 REFIID riid,
1125 LCID lcid,
1126 WORD wFlags,
1127 DISPPARAMS* pDispParams,
1128 VARIANT* pVarResult,
1129 EXCEPINFO* pExepInfo,
1130 UINT* puArgErr)
1131{
1132 FIXME("(dispid: %ld):Stub\n",dispIdMember);
1133
1134 VariantInit(pVarResult);
1135 V_VT(pVarResult) = VT_BOOL;
1136 V_UNION(pVarResult,boolVal) = FALSE;
1137 return S_OK;
1138}
1139
1140
1141static ICOM_VTABLE(IPicture) OLEPictureImpl_VTable =
1142{
1143 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1144 OLEPictureImpl_QueryInterface,
1145 OLEPictureImpl_AddRef,
1146 OLEPictureImpl_Release,
1147 OLEPictureImpl_get_Handle,
1148 OLEPictureImpl_get_hPal,
1149 OLEPictureImpl_get_Type,
1150 OLEPictureImpl_get_Width,
1151 OLEPictureImpl_get_Height,
1152 OLEPictureImpl_Render,
1153 OLEPictureImpl_set_hPal,
1154 OLEPictureImpl_get_CurDC,
1155 OLEPictureImpl_SelectPicture,
1156 OLEPictureImpl_get_KeepOriginalFormat,
1157 OLEPictureImpl_put_KeepOriginalFormat,
1158 OLEPictureImpl_PictureChanged,
1159 OLEPictureImpl_SaveAsFile,
1160 OLEPictureImpl_get_Attributes
1161};
1162
1163static ICOM_VTABLE(IDispatch) OLEPictureImpl_IDispatch_VTable =
1164{
1165 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1166 OLEPictureImpl_IDispatch_QueryInterface,
1167 OLEPictureImpl_IDispatch_AddRef,
1168 OLEPictureImpl_IDispatch_Release,
1169 OLEPictureImpl_GetTypeInfoCount,
1170 OLEPictureImpl_GetTypeInfo,
1171 OLEPictureImpl_GetIDsOfNames,
1172 OLEPictureImpl_Invoke
1173};
1174
1175static ICOM_VTABLE(IPersistStream) OLEPictureImpl_IPersistStream_VTable =
1176{
1177 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1178 OLEPictureImpl_IPersistStream_QueryInterface,
1179 OLEPictureImpl_IPersistStream_AddRef,
1180 OLEPictureImpl_IPersistStream_Release,
1181 OLEPictureImpl_GetClassID,
1182 OLEPictureImpl_IsDirty,
1183 OLEPictureImpl_Load,
1184 OLEPictureImpl_Save,
1185 OLEPictureImpl_GetSizeMax
1186};
1187
1188static ICOM_VTABLE(IConnectionPointContainer) OLEPictureImpl_IConnectionPointContainer_VTable =
1189{
1190 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1191 OLEPictureImpl_IConnectionPointContainer_QueryInterface,
1192 OLEPictureImpl_IConnectionPointContainer_AddRef,
1193 OLEPictureImpl_IConnectionPointContainer_Release,
1194 OLEPictureImpl_EnumConnectionPoints,
1195 OLEPictureImpl_FindConnectionPoint
1196};
1197
1198/***********************************************************************
1199 * OleCreatePictureIndirect (OLEAUT32.419)
1200 */
1201HRESULT WINAPI OleCreatePictureIndirect(LPPICTDESC lpPictDesc, REFIID riid,
1202 BOOL fOwn, LPVOID *ppvObj )
1203{
1204 OLEPictureImpl* newPict = NULL;
1205 HRESULT hr = S_OK;
1206
1207 TRACE("(%p,%p,%d,%p)\n", lpPictDesc, riid, fOwn, ppvObj);
1208
1209 /*
1210 * Sanity check
1211 */
1212 if (ppvObj==0)
1213 return E_POINTER;
1214
1215 *ppvObj = NULL;
1216
1217 /*
1218 * Try to construct a new instance of the class.
1219 */
1220 newPict = OLEPictureImpl_Construct(lpPictDesc, fOwn);
1221
1222 if (newPict == NULL)
1223 return E_OUTOFMEMORY;
1224
1225 /*
1226 * Make sure it supports the interface required by the caller.
1227 */
1228 hr = IPicture_QueryInterface((IPicture*)newPict, riid, ppvObj);
1229
1230 /*
1231 * Release the reference obtained in the constructor. If
1232 * the QueryInterface was unsuccessful, it will free the class.
1233 */
1234 IPicture_Release((IPicture*)newPict);
1235
1236 return hr;
1237}
1238
1239
1240/***********************************************************************
1241 * OleLoadPicture (OLEAUT32.418)
1242 */
1243HRESULT WINAPI OleLoadPicture( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
1244 REFIID riid, LPVOID *ppvObj )
1245{
1246 LPPERSISTSTREAM ps;
1247 IPicture *newpic;
1248 HRESULT hr;
1249
1250 TRACE("(%p,%ld,%d,%s,%p), partially implemented.\n",
1251 lpstream, lSize, fRunmode, debugstr_guid(riid), ppvObj);
1252
1253 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
1254 if (hr)
1255 return hr;
1256 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
1257 if (hr) {
1258 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
1259 IPicture_Release(newpic);
1260 *ppvObj = NULL;
1261 return hr;
1262 }
1263 IPersistStream_Load(ps,lpstream);
1264 IPersistStream_Release(ps);
1265 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
1266 if (hr)
1267 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
1268 IPicture_Release(newpic);
1269 return hr;
1270}
1271
1272/***********************************************************************
1273 * OleLoadPictureEx (OLEAUT32.425)
1274 */
1275HRESULT WINAPI OleLoadPictureEx( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
1276 REFIID reed, DWORD xsiz, DWORD ysiz, DWORD flags, LPVOID *ppvObj )
1277{
1278 FIXME("(%p,%ld,%d,%p,%lx,%lx,%lx,%p), not implemented\n",
1279 lpstream, lSize, fRunmode, reed, xsiz, ysiz, flags, ppvObj);
1280 return S_OK;
1281}
1282
Note: See TracBrowser for help on using the repository browser.