Fixes DeviceCapabilities for DC_PAPERSIZE.
[wine] / ole / olefont.c
1 /*
2  * OLE Font encapsulation implementation
3  *
4  * This file contains an implementation of the IFont
5  * interface and the OleCreateFontIndirect API call.
6  *
7  * Copyright 1999 Francis Beaudet
8  */
9 #include <assert.h>
10 #include <string.h>
11 #include "winerror.h"
12 #include "oleauto.h"    /* for SysAllocString(....) */
13 #include "wine/obj_olefont.h"
14 #include "wine/obj_storage.h"
15 #include "olectl.h"
16 #include "debugtools.h"
17 #include "heap.h"
18
19 DEFAULT_DEBUG_CHANNEL(ole)
20
21 /***********************************************************************
22  * Declaration of constants used when serializing the font object.
23  */
24 #define FONTPERSIST_ITALIC        0x02
25 #define FONTPERSIST_UNDERLINE     0x04
26 #define FONTPERSIST_STRIKETHROUGH 0x08
27
28 /***********************************************************************
29  * Declaration of the implementation class for the IFont interface
30  */
31 typedef struct OLEFontImpl OLEFontImpl;
32
33 struct OLEFontImpl
34 {
35   /*
36    * This class supports many interfaces. IUnknown, IFont, 
37    * IDispatch, IDispFont and IPersistStream. The first two are
38    * supported by the first vtablem the next two are supported by 
39    * the second table and the last one has it's own.
40    */
41   ICOM_VTABLE(IFont)*     lpvtbl1;
42   ICOM_VTABLE(IDispatch)* lpvtbl2;
43   ICOM_VTABLE(IPersistStream)*            lpvtbl3;
44
45   /*
46    * Reference count for that instance of the class.
47    */
48   ULONG ref;
49
50   /*
51    * This structure contains the description of the class.
52    */
53   FONTDESC description;
54
55   /*
56    * Contain the font associated with this object.
57    */
58   HFONT gdiFont;
59
60   /*
61    * Font lock count.
62    */
63   DWORD fontLock;
64
65   /*
66    * Size ratio
67    */
68   long cyLogical;
69   long cyHimetric;
70 };
71
72 /*
73  * Here, I define utility macros to help with the casting of the 
74  * "this" parameter.
75  * There is a version to accomodate all of the VTables implemented
76  * by this object.
77  */
78 #define _ICOM_THIS(class,name) class* this = (class*)name;
79 #define _ICOM_THIS_From_IDispatch(class, name) class* this = (class*)(((char*)name)-sizeof(void*)); 
80 #define _ICOM_THIS_From_IPersistStream(class, name) class* this = (class*)(((char*)name)-2*sizeof(void*)); 
81
82 /***********************************************************************
83  * Prototypes for the implementation functions for the IFont
84  * interface
85  */
86 static OLEFontImpl* OLEFontImpl_Construct(LPFONTDESC fontDesc);
87 static void         OLEFontImpl_Destroy(OLEFontImpl* fontDesc);
88 static HRESULT      WINAPI OLEFontImpl_QueryInterface(IFont* iface, REFIID riid, VOID** ppvoid);
89 static ULONG        WINAPI OLEFontImpl_AddRef(IFont* iface);
90 static ULONG        WINAPI OLEFontImpl_Release(IFont* iface);
91 static HRESULT      WINAPI OLEFontImpl_get_Name(IFont* iface, BSTR* pname);
92 static HRESULT      WINAPI OLEFontImpl_put_Name(IFont* iface, BSTR name);
93 static HRESULT      WINAPI OLEFontImpl_get_Size(IFont* iface, CY* psize);
94 static HRESULT      WINAPI OLEFontImpl_put_Size(IFont* iface, CY size);
95 static HRESULT      WINAPI OLEFontImpl_get_Bold(IFont* iface, BOOL* pbold);
96 static HRESULT      WINAPI OLEFontImpl_put_Bold(IFont* iface, BOOL bold);
97 static HRESULT      WINAPI OLEFontImpl_get_Italic(IFont* iface, BOOL* pitalic);
98 static HRESULT      WINAPI OLEFontImpl_put_Italic(IFont* iface, BOOL italic);
99 static HRESULT      WINAPI OLEFontImpl_get_Underline(IFont* iface, BOOL* punderline);
100 static HRESULT      WINAPI OLEFontImpl_put_Underline(IFont* iface, BOOL underline);
101 static HRESULT      WINAPI OLEFontImpl_get_Strikethrough(IFont* iface, BOOL* pstrikethrough);
102 static HRESULT      WINAPI OLEFontImpl_put_Strikethrough(IFont* iface, BOOL strikethrough);
103 static HRESULT      WINAPI OLEFontImpl_get_Weight(IFont* iface, short* pweight);
104 static HRESULT      WINAPI OLEFontImpl_put_Weight(IFont* iface, short weight);
105 static HRESULT      WINAPI OLEFontImpl_get_Charset(IFont* iface, short* pcharset);
106 static HRESULT      WINAPI OLEFontImpl_put_Charset(IFont* iface, short charset);
107 static HRESULT      WINAPI OLEFontImpl_get_hFont(IFont* iface, HFONT* phfont);
108 static HRESULT      WINAPI OLEFontImpl_Clone(IFont* iface, IFont** ppfont);
109 static HRESULT      WINAPI OLEFontImpl_IsEqual(IFont* iface, IFont* pFontOther);
110 static HRESULT      WINAPI OLEFontImpl_SetRatio(IFont* iface, long cyLogical, long cyHimetric);
111 static HRESULT      WINAPI OLEFontImpl_QueryTextMetrics(IFont* iface, TEXTMETRICOLE* ptm);
112 static HRESULT      WINAPI OLEFontImpl_AddRefHfont(IFont* iface, HFONT hfont);
113 static HRESULT      WINAPI OLEFontImpl_ReleaseHfont(IFont* iface, HFONT hfont);
114 static HRESULT      WINAPI OLEFontImpl_SetHdc(IFont* iface, HDC hdc);
115
116 /***********************************************************************
117  * Prototypes for the implementation functions for the IDispatch
118  * interface
119  */
120 static HRESULT WINAPI OLEFontImpl_IDispatch_QueryInterface(IDispatch* iface, 
121                                                     REFIID     riid, 
122                                                     VOID**     ppvoid);
123 static ULONG   WINAPI OLEFontImpl_IDispatch_AddRef(IDispatch* iface);
124 static ULONG   WINAPI OLEFontImpl_IDispatch_Release(IDispatch* iface);
125 static HRESULT WINAPI OLEFontImpl_GetTypeInfoCount(IDispatch*    iface, 
126                                                    unsigned int* pctinfo);
127 static HRESULT WINAPI OLEFontImpl_GetTypeInfo(IDispatch*  iface, 
128                                               UINT      iTInfo,
129                                               LCID        lcid, 
130                                               ITypeInfo** ppTInfo);
131 static HRESULT WINAPI OLEFontImpl_GetIDsOfNames(IDispatch*  iface,
132                                                 REFIID      riid, 
133                                                 LPOLESTR* rgszNames, 
134                                                 UINT      cNames, 
135                                                 LCID        lcid,
136                                                 DISPID*     rgDispId);
137 static HRESULT WINAPI OLEFontImpl_Invoke(IDispatch*  iface,
138                                          DISPID      dispIdMember, 
139                                          REFIID      riid, 
140                                          LCID        lcid, 
141                                          WORD        wFlags,
142                                          DISPPARAMS* pDispParams,
143                                          VARIANT*    pVarResult, 
144                                          EXCEPINFO*  pExepInfo,
145                                          UINT*     puArgErr); 
146
147 /***********************************************************************
148  * Prototypes for the implementation functions for the IPersistStream
149  * interface
150  */
151 static HRESULT WINAPI OLEFontImpl_IPersistStream_QueryInterface(IPersistStream* iface, 
152                                                     REFIID     riid, 
153                                                     VOID**     ppvoid);
154 static ULONG   WINAPI OLEFontImpl_IPersistStream_AddRef(IPersistStream* iface);
155 static ULONG   WINAPI OLEFontImpl_IPersistStream_Release(IPersistStream* iface);
156 static HRESULT WINAPI OLEFontImpl_GetClassID(IPersistStream* iface, 
157                                              CLSID*                pClassID);
158 static HRESULT WINAPI OLEFontImpl_IsDirty(IPersistStream*  iface);
159 static HRESULT WINAPI OLEFontImpl_Load(IPersistStream*  iface,
160                                        IStream*         pLoadStream);
161 static HRESULT WINAPI OLEFontImpl_Save(IPersistStream*  iface,
162                                        IStream*         pOutStream,
163                                        BOOL             fClearDirty); 
164 static HRESULT WINAPI OLEFontImpl_GetSizeMax(IPersistStream*  iface,
165                                              ULARGE_INTEGER*  pcbSize); 
166
167 /*
168  * Virtual function tables for the OLEFontImpl class.
169  */
170 static ICOM_VTABLE(IFont) OLEFontImpl_VTable =
171 {
172   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
173   OLEFontImpl_QueryInterface,
174   OLEFontImpl_AddRef,
175   OLEFontImpl_Release,
176   OLEFontImpl_get_Name,
177   OLEFontImpl_put_Name,
178   OLEFontImpl_get_Size,
179   OLEFontImpl_put_Size,
180   OLEFontImpl_get_Bold,
181   OLEFontImpl_put_Bold,
182   OLEFontImpl_get_Italic,
183   OLEFontImpl_put_Italic,
184   OLEFontImpl_get_Underline,
185   OLEFontImpl_put_Underline,
186   OLEFontImpl_get_Strikethrough,
187   OLEFontImpl_put_Strikethrough,
188   OLEFontImpl_get_Weight,
189   OLEFontImpl_put_Weight,
190   OLEFontImpl_get_Charset,
191   OLEFontImpl_put_Charset,
192   OLEFontImpl_get_hFont,
193   OLEFontImpl_Clone, 
194   OLEFontImpl_IsEqual,
195   OLEFontImpl_SetRatio,
196   OLEFontImpl_QueryTextMetrics,
197   OLEFontImpl_AddRefHfont,
198   OLEFontImpl_ReleaseHfont,
199   OLEFontImpl_SetHdc
200 };
201
202 static ICOM_VTABLE(IDispatch) OLEFontImpl_IDispatch_VTable =
203 {
204   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
205   OLEFontImpl_IDispatch_QueryInterface,
206   OLEFontImpl_IDispatch_AddRef,
207   OLEFontImpl_IDispatch_Release,
208   OLEFontImpl_GetTypeInfoCount,
209   OLEFontImpl_GetTypeInfo,
210   OLEFontImpl_GetIDsOfNames,
211   OLEFontImpl_Invoke
212 };
213
214 static ICOM_VTABLE(IPersistStream) OLEFontImpl_IPersistStream_VTable =
215 {
216   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
217   OLEFontImpl_IPersistStream_QueryInterface,
218   OLEFontImpl_IPersistStream_AddRef,
219   OLEFontImpl_IPersistStream_Release,
220   OLEFontImpl_GetClassID,
221   OLEFontImpl_IsDirty,
222   OLEFontImpl_Load,
223   OLEFontImpl_Save,
224   OLEFontImpl_GetSizeMax
225 };
226
227 /******************************************************************************
228  *              OleCreateFontIndirect   [OLEAUT32.420]
229  */
230 INT WINAPI OleCreateFontIndirect(
231   LPFONTDESC lpFontDesc,
232   REFIID     riid,
233   VOID**     ppvObj)
234 {
235   OLEFontImpl* newFont = 0;
236   HRESULT      hr      = S_OK;
237
238   /*
239    * Sanity check
240    */
241   if (ppvObj==0)
242     return E_POINTER;
243
244   *ppvObj = 0;
245
246   /*
247    * Try to construct a new instance of the class.
248    */
249   newFont = OLEFontImpl_Construct(lpFontDesc);
250
251   if (newFont == 0)
252     return E_OUTOFMEMORY;
253
254   /*
255    * Make sure it supports the interface required by the caller.
256    */
257   hr = IFont_QueryInterface((IFont*)newFont, riid, ppvObj);
258
259   /*
260    * Release the reference obtained in the constructor. If
261    * the QueryInterface was unsuccessful, it will free the class.
262    */
263   IFont_Release((IFont*)newFont);
264
265   return hr;
266 }
267
268
269 /***********************************************************************
270  * Implementation of the OLEFontImpl class.
271  */
272
273 /************************************************************************
274  * OLEFontImpl_Construct
275  *
276  * This method will construct a new instance of the OLEFontImpl
277  * class.
278  *
279  * The caller of this method must release the object when it's
280  * done with it.
281  */
282 static OLEFontImpl* OLEFontImpl_Construct(LPFONTDESC fontDesc)
283 {
284   OLEFontImpl* newObject = 0;
285
286   /*
287    * Allocate space for the object.
288    */
289   newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(OLEFontImpl));
290
291   if (newObject==0)
292     return newObject;
293   
294   /*
295    * Initialize the virtual function table.
296    */
297   newObject->lpvtbl1 = &OLEFontImpl_VTable;
298   newObject->lpvtbl2 = &OLEFontImpl_IDispatch_VTable;
299   newObject->lpvtbl3 = &OLEFontImpl_IPersistStream_VTable;
300   
301   /*
302    * Start with one reference count. The caller of this function 
303    * must release the interface pointer when it is done.
304    */
305   newObject->ref = 1;
306
307   /*
308    * Copy the description of the font in the object.
309    */
310   assert(fontDesc->cbSizeofstruct >= sizeof(FONTDESC));
311
312   newObject->description.cbSizeofstruct = sizeof(FONTDESC);
313   newObject->description.lpstrName = HeapAlloc(GetProcessHeap(),
314                                                0, 
315                                                (lstrlenW(fontDesc->lpstrName)+1) * sizeof(WCHAR));
316   lstrcpyW(newObject->description.lpstrName, fontDesc->lpstrName);
317   newObject->description.cySize         = fontDesc->cySize;
318   newObject->description.sWeight        = fontDesc->sWeight;
319   newObject->description.sCharset       = fontDesc->sCharset;
320   newObject->description.fItalic        = fontDesc->fItalic;
321   newObject->description.fUnderline     = fontDesc->fUnderline;
322   newObject->description.fStrikethrough = fontDesc->fStrikethrough;
323
324   /*
325    * Initializing all the other members.
326    */
327   newObject->gdiFont  = 0;
328   newObject->fontLock = 0;
329   newObject->cyHimetric = 1;
330   newObject->cyLogical  = 1;
331
332   return newObject;
333 }
334
335 /************************************************************************
336  * OLEFontImpl_Construct
337  *
338  * This method is called by the Release method when the reference
339  * count goes doen to 0. it will free all resources used by
340  * this object.
341  */
342 static void OLEFontImpl_Destroy(OLEFontImpl* fontDesc)
343 {
344   if (fontDesc->description.lpstrName!=0)
345     HeapFree(GetProcessHeap(), 0, fontDesc->description.lpstrName);
346
347   if (fontDesc->gdiFont!=0)
348     DeleteObject(fontDesc->gdiFont);
349
350   HeapFree(GetProcessHeap(), 0, fontDesc);
351 }
352
353 /************************************************************************
354  * OLEFontImpl_QueryInterface (IUnknown)
355  *
356  * See Windows documentation for more details on IUnknown methods.
357  */
358 HRESULT WINAPI OLEFontImpl_QueryInterface(
359   IFont*  iface,
360   REFIID  riid,
361   void**  ppvObject)
362 {
363   _ICOM_THIS(OLEFontImpl, iface);
364
365   /*
366    * Perform a sanity check on the parameters.
367    */
368   if ( (this==0) || (ppvObject==0) )
369     return E_INVALIDARG;
370   
371   /*
372    * Initialize the return parameter.
373    */
374   *ppvObject = 0;
375   
376   /*
377    * Compare the riid with the interface IDs implemented by this object.
378    */
379   if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0) 
380   {
381     *ppvObject = (IFont*)this;
382   }
383   else if (memcmp(&IID_IFont, riid, sizeof(IID_IFont)) == 0) 
384   {
385     *ppvObject = (IFont*)this;
386   }
387   else if (memcmp(&IID_IDispatch, riid, sizeof(IID_IDispatch)) == 0) 
388   {
389     *ppvObject = (IDispatch*)&(this->lpvtbl2);
390   }
391   else if (memcmp(&IID_IFontDisp, riid, sizeof(IID_IFontDisp)) == 0) 
392   {
393     *ppvObject = (IDispatch*)&(this->lpvtbl2);
394   }
395   else if (memcmp(&IID_IPersistStream, riid, sizeof(IID_IPersistStream)) == 0) 
396   {
397     *ppvObject = (IPersistStream*)&(this->lpvtbl3);
398   }
399   
400   /*
401    * Check that we obtained an interface.
402    */
403   if ((*ppvObject)==0)
404   {
405     char clsid[50];
406
407     WINE_StringFromCLSID((LPCLSID)riid,clsid);
408     
409     WARN(
410          "() : asking for un supported interface %s\n", 
411          clsid);
412
413     return E_NOINTERFACE;
414   }
415   
416   /*
417    * Query Interface always increases the reference count by one when it is
418    * successful
419    */
420   OLEFontImpl_AddRef((IFont*)this);
421
422   return S_OK;;
423 }
424         
425 /************************************************************************
426  * OLEFontImpl_AddRef (IUnknown)
427  *
428  * See Windows documentation for more details on IUnknown methods.
429  */
430 ULONG WINAPI OLEFontImpl_AddRef( 
431   IFont* iface)
432 {
433   _ICOM_THIS(OLEFontImpl, iface);
434
435   this->ref++;
436
437   return this->ref;
438 }
439         
440 /************************************************************************
441  * OLEFontImpl_Release (IUnknown)
442  *
443  * See Windows documentation for more details on IUnknown methods.
444  */
445 ULONG WINAPI OLEFontImpl_Release( 
446       IFont* iface)
447 {
448   _ICOM_THIS(OLEFontImpl, iface);
449
450   /*
451    * Decrease the reference count on this object.
452    */
453   this->ref--;
454
455   /*
456    * If the reference count goes down to 0, perform suicide.
457    */
458   if (this->ref==0)
459   {
460     OLEFontImpl_Destroy(this);
461
462     return 0;
463   }
464   
465   return this->ref;
466 }
467         
468 /************************************************************************
469  * OLEFontImpl_get_Name (IFont)
470  *
471  * See Windows documentation for more details on IFont methods.
472  */
473 static HRESULT WINAPI OLEFontImpl_get_Name(
474   IFont*  iface, 
475   BSTR* pname)
476 {
477   _ICOM_THIS(OLEFontImpl, iface);
478
479   /*
480    * Sanity check.
481    */
482   if (pname==0)
483     return E_POINTER;
484
485   if (this->description.lpstrName!=0)
486     *pname = SysAllocString(this->description.lpstrName);
487   else
488     *pname = 0;
489
490   return S_OK;
491 }
492
493 /************************************************************************
494  * OLEFontImpl_put_Name (IFont)
495  *
496  * See Windows documentation for more details on IFont methods.
497  */
498 static HRESULT WINAPI OLEFontImpl_put_Name(
499   IFont* iface, 
500   BSTR name)
501 {
502   _ICOM_THIS(OLEFontImpl, iface);
503
504   if (this->description.lpstrName==0)
505   {
506     this->description.lpstrName = HeapAlloc(GetProcessHeap(),
507                                             0, 
508                                             (lstrlenW(name)+1) * sizeof(WCHAR));
509   }
510   else
511   {
512     this->description.lpstrName = HeapReAlloc(GetProcessHeap(),
513                                               0, 
514                                               this->description.lpstrName,
515                                               (lstrlenW(name)+1) * sizeof(WCHAR));
516   }
517
518   if (this->description.lpstrName==0)
519     return E_OUTOFMEMORY;
520
521   lstrcpyW(this->description.lpstrName, name);
522
523   return S_OK;
524 }
525
526 /************************************************************************
527  * OLEFontImpl_get_Size (IFont)
528  *
529  * See Windows documentation for more details on IFont methods.
530  */
531 static HRESULT WINAPI OLEFontImpl_get_Size(
532   IFont* iface, 
533   CY*    psize)
534 {
535   _ICOM_THIS(OLEFontImpl, iface);
536
537   /*
538    * Sanity check
539    */
540   if (psize==0)
541     return E_POINTER;
542
543   psize->u.Hi = 0;
544   psize->u.Lo = this->description.cySize.u.Lo;
545
546   return S_OK;
547 }
548
549 /************************************************************************
550  * OLEFontImpl_put_Size (IFont)
551  *
552  * See Windows documentation for more details on IFont methods.
553  */
554 static HRESULT WINAPI OLEFontImpl_put_Size(
555   IFont* iface, 
556   CY     size)
557 {
558   _ICOM_THIS(OLEFontImpl, iface);
559
560   this->description.cySize.u.Hi = 0;
561   this->description.cySize.u.Lo = this->description.cySize.u.Lo;
562
563   return S_OK;
564 }
565
566 /************************************************************************
567  * OLEFontImpl_get_Bold (IFont)
568  *
569  * See Windows documentation for more details on IFont methods.
570  */
571 static HRESULT WINAPI OLEFontImpl_get_Bold(
572   IFont*  iface, 
573   BOOL* pbold)
574 {
575   FIXME("():Stub\n");
576   return E_NOTIMPL;
577 }
578
579 /************************************************************************
580  * OLEFontImpl_put_Bold (IFont)
581  *
582  * See Windows documentation for more details on IFont methods.
583  */
584 static HRESULT WINAPI OLEFontImpl_put_Bold(
585   IFont* iface,
586   BOOL bold)
587 {
588   FIXME("():Stub\n");
589   return E_NOTIMPL;
590 }
591
592 /************************************************************************
593  * OLEFontImpl_get_Italic (IFont)
594  *
595  * See Windows documentation for more details on IFont methods.
596  */
597 static HRESULT WINAPI OLEFontImpl_get_Italic(
598   IFont*  iface, 
599   BOOL* pitalic)
600 {
601   _ICOM_THIS(OLEFontImpl, iface);
602
603   /*
604    * Sanity check
605    */
606   if (pitalic==0)
607     return E_POINTER;
608
609   *pitalic = this->description.fItalic;
610
611   return S_OK;
612 }
613
614 /************************************************************************
615  * OLEFontImpl_put_Italic (IFont)
616  *
617  * See Windows documentation for more details on IFont methods.
618  */
619 static HRESULT WINAPI OLEFontImpl_put_Italic(
620   IFont* iface, 
621   BOOL italic)
622 {
623   _ICOM_THIS(OLEFontImpl, iface);
624
625   this->description.fItalic = italic;
626
627   return S_OK;
628 }
629
630 /************************************************************************
631  * OLEFontImpl_get_Underline (IFont)
632  *
633  * See Windows documentation for more details on IFont methods.
634  */
635 static HRESULT WINAPI OLEFontImpl_get_Underline(
636   IFont*  iface, 
637   BOOL* punderline)
638 {
639   _ICOM_THIS(OLEFontImpl, iface);
640
641   /*
642    * Sanity check
643    */
644   if (punderline==0)
645     return E_POINTER;
646
647   *punderline = this->description.fUnderline;
648
649   return S_OK;
650 }
651
652 /************************************************************************
653  * OLEFontImpl_put_Underline (IFont)
654  *
655  * See Windows documentation for more details on IFont methods.
656  */
657 static HRESULT WINAPI OLEFontImpl_put_Underline(
658   IFont* iface,
659   BOOL underline)
660 {
661   _ICOM_THIS(OLEFontImpl, iface);
662
663   this->description.fUnderline = underline;
664
665   return S_OK;
666 }
667
668 /************************************************************************
669  * OLEFontImpl_get_Strikethrough (IFont)
670  *
671  * See Windows documentation for more details on IFont methods.
672  */
673 static HRESULT WINAPI OLEFontImpl_get_Strikethrough(
674   IFont*  iface, 
675   BOOL* pstrikethrough)
676 {
677   _ICOM_THIS(OLEFontImpl, iface);
678
679   /*
680    * Sanity check
681    */
682   if (pstrikethrough==0)
683     return E_POINTER;
684
685   *pstrikethrough = this->description.fStrikethrough;
686
687   return S_OK;
688 }
689
690 /************************************************************************
691  * OLEFontImpl_put_Strikethrough (IFont)
692  *
693  * See Windows documentation for more details on IFont methods.
694  */
695 static HRESULT WINAPI OLEFontImpl_put_Strikethrough(
696  IFont* iface, 
697  BOOL strikethrough)
698 {
699   _ICOM_THIS(OLEFontImpl, iface);
700
701   this->description.fStrikethrough = strikethrough;
702
703   return S_OK;
704 }
705
706 /************************************************************************
707  * OLEFontImpl_get_Weight (IFont)
708  *
709  * See Windows documentation for more details on IFont methods.
710  */
711 static HRESULT WINAPI OLEFontImpl_get_Weight(
712   IFont* iface, 
713   short* pweight)
714 {
715   _ICOM_THIS(OLEFontImpl, iface);
716
717   /*
718    * Sanity check
719    */
720   if (pweight==0)
721     return E_POINTER;
722
723   *pweight = this->description.sWeight;
724
725   return S_OK;
726 }
727
728 /************************************************************************
729  * OLEFontImpl_put_Weight (IFont)
730  *
731  * See Windows documentation for more details on IFont methods.
732  */
733 static HRESULT WINAPI OLEFontImpl_put_Weight(
734   IFont* iface, 
735   short  weight)
736 {
737   _ICOM_THIS(OLEFontImpl, iface);
738
739   this->description.sWeight = weight;
740
741   return S_OK;
742 }
743
744 /************************************************************************
745  * OLEFontImpl_get_Charset (IFont)
746  *
747  * See Windows documentation for more details on IFont methods.
748  */
749 static HRESULT WINAPI OLEFontImpl_get_Charset(
750   IFont* iface, 
751   short* pcharset)
752 {
753   _ICOM_THIS(OLEFontImpl, iface);
754
755   /*
756    * Sanity check
757    */
758   if (pcharset==0)
759     return E_POINTER;
760
761   *pcharset = this->description.sCharset;
762
763   return S_OK;
764 }
765
766 /************************************************************************
767  * OLEFontImpl_put_Charset (IFont)
768  *
769  * See Windows documentation for more details on IFont methods.
770  */
771 static HRESULT WINAPI OLEFontImpl_put_Charset(
772   IFont* iface, 
773   short charset)
774 {
775   _ICOM_THIS(OLEFontImpl, iface);
776
777   this->description.sCharset = charset;
778
779   return S_OK;
780 }
781
782 /************************************************************************
783  * OLEFontImpl_get_hFont (IFont)
784  *
785  * See Windows documentation for more details on IFont methods.
786  */
787 static HRESULT WINAPI OLEFontImpl_get_hFont(
788   IFont*   iface,
789   HFONT* phfont)
790 {
791   _ICOM_THIS(OLEFontImpl, iface);
792
793   if (phfont==NULL)
794     return E_POINTER;
795
796   /*
797    * Realize the font if necessary
798  */
799   if (this->gdiFont==0)
800 {
801     LOGFONTW logFont;
802     INT      fontHeight;
803     CY       cySize;
804     
805     /*
806      * The height of the font returned by the get_Size property is the
807      * height of the font in points multiplied by 10000... Using some
808      * simple conversions and the ratio given by the application, it can
809      * be converted to a height in pixels.
810      */
811     IFont_get_Size(iface, &cySize);
812
813     fontHeight = MulDiv(cySize.u.Lo, 2540L, 72L);
814     fontHeight = MulDiv(fontHeight, this->cyLogical,this->cyHimetric);
815
816     memset(&logFont, 0, sizeof(LOGFONTW));
817
818     logFont.lfHeight          = ((fontHeight%10000L)>5000L) ? (-fontHeight/10000L)-1 :
819                                                               (-fontHeight/10000L);
820     logFont.lfItalic          = this->description.fItalic;
821     logFont.lfUnderline       = this->description.fUnderline;
822     logFont.lfStrikeOut       = this->description.fStrikethrough;
823     logFont.lfWeight          = this->description.sWeight;
824     logFont.lfCharSet         = this->description.sCharset;
825     logFont.lfOutPrecision    = OUT_CHARACTER_PRECIS;
826     logFont.lfClipPrecision   = CLIP_DEFAULT_PRECIS;
827     logFont.lfQuality         = DEFAULT_QUALITY;
828     logFont.lfPitchAndFamily  = DEFAULT_PITCH;
829     lstrcpyW(logFont.lfFaceName,this->description.lpstrName);
830
831     this->gdiFont = CreateFontIndirectW(&logFont);
832   }
833
834   *phfont = this->gdiFont;
835
836   return S_OK;
837 }
838
839 /************************************************************************
840  * OLEFontImpl_Clone (IFont)
841  *
842  * See Windows documentation for more details on IFont methods.
843  */
844 static HRESULT WINAPI OLEFontImpl_Clone(
845   IFont*  iface,
846   IFont** ppfont)
847 {
848   OLEFontImpl* newObject = 0;
849
850   _ICOM_THIS(OLEFontImpl, iface);
851
852   if (ppfont == NULL)
853     return E_POINTER;
854
855   *ppfont = NULL;
856
857   /*
858    * Allocate space for the object.
859    */
860   newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(OLEFontImpl));
861
862   if (newObject==NULL)
863     return E_OUTOFMEMORY;
864
865   *newObject = *this;
866
867   /*
868    * That new object starts with a reference count of 1
869    */
870   newObject->ref          = 1;
871
872   *ppfont = (IFont*)newObject;
873
874   return S_OK;
875 }
876
877 /************************************************************************
878  * OLEFontImpl_IsEqual (IFont)
879  *
880  * See Windows documentation for more details on IFont methods.
881  */
882 static HRESULT WINAPI OLEFontImpl_IsEqual(
883   IFont* iface, 
884   IFont* pFontOther)
885 {
886   FIXME("():Stub\n");
887   return E_NOTIMPL;
888 }
889
890 /************************************************************************
891  * OLEFontImpl_SetRatio (IFont)
892  *
893  * See Windows documentation for more details on IFont methods.
894  */
895 static HRESULT WINAPI OLEFontImpl_SetRatio(
896   IFont* iface,
897   long   cyLogical,
898   long   cyHimetric)
899 {
900   _ICOM_THIS(OLEFontImpl, iface);
901
902   this->cyLogical  = cyLogical;
903   this->cyHimetric = cyHimetric;
904
905   return S_OK;
906 }
907
908 /************************************************************************
909  * OLEFontImpl_QueryTextMetrics (IFont)
910  *
911  * See Windows documentation for more details on IFont methods.
912  */
913 static HRESULT      WINAPI OLEFontImpl_QueryTextMetrics(
914   IFont*         iface, 
915   TEXTMETRICOLE* ptm)
916 {
917   FIXME("():Stub\n");
918   return E_NOTIMPL;
919 }
920
921 /************************************************************************
922  * OLEFontImpl_AddRefHfont (IFont)
923  *
924  * See Windows documentation for more details on IFont methods.
925  */
926 static HRESULT WINAPI OLEFontImpl_AddRefHfont(
927   IFont*  iface, 
928   HFONT hfont)
929 {
930   _ICOM_THIS(OLEFontImpl, iface);
931
932   if ( (hfont == 0) ||
933        (hfont != this->gdiFont) )
934     return E_INVALIDARG;
935
936   this->fontLock++;
937
938   return S_OK;
939 }
940
941 /************************************************************************
942  * OLEFontImpl_ReleaseHfont (IFont)
943  *
944  * See Windows documentation for more details on IFont methods.
945  */
946 static HRESULT WINAPI OLEFontImpl_ReleaseHfont(
947   IFont*  iface,
948   HFONT hfont)
949 {
950   _ICOM_THIS(OLEFontImpl, iface);
951
952   if ( (hfont == 0) ||
953        (hfont != this->gdiFont) )
954     return E_INVALIDARG;
955
956   this->fontLock--;
957
958   /*
959    * If we just released our last font reference, destroy it.
960    */
961   if (this->fontLock==0)
962   {
963     DeleteObject(this->gdiFont);
964     this->gdiFont = 0; 
965 }
966
967   return S_OK;
968 }
969
970 /************************************************************************
971  * OLEFontImpl_SetHdc (IFont)
972  *
973  * See Windows documentation for more details on IFont methods.
974  */
975 static HRESULT WINAPI OLEFontImpl_SetHdc(
976   IFont* iface,
977   HDC  hdc)
978 {
979   FIXME("():Stub\n");
980   return E_NOTIMPL;
981 }
982
983 /************************************************************************
984  * OLEFontImpl_IDispatch_QueryInterface (IUnknown)
985  *
986  * See Windows documentation for more details on IUnknown methods.
987  */
988 static HRESULT WINAPI OLEFontImpl_IDispatch_QueryInterface(
989   IDispatch* iface,
990   REFIID     riid,
991   VOID**     ppvoid)
992 {
993   _ICOM_THIS_From_IDispatch(IFont, iface);
994
995   return IFont_QueryInterface(this, riid, ppvoid);
996 }
997
998 /************************************************************************
999  * OLEFontImpl_IDispatch_Release (IUnknown)
1000  *
1001  * See Windows documentation for more details on IUnknown methods.
1002  */
1003 static ULONG WINAPI OLEFontImpl_IDispatch_Release(
1004   IDispatch* iface)
1005 {
1006   _ICOM_THIS_From_IDispatch(IFont, iface);
1007
1008   return IFont_Release(this);
1009 }
1010
1011 /************************************************************************
1012  * OLEFontImpl_IDispatch_AddRef (IUnknown)
1013  *
1014  * See Windows documentation for more details on IUnknown methods.
1015  */
1016 static ULONG WINAPI OLEFontImpl_IDispatch_AddRef(
1017   IDispatch* iface)
1018 {
1019   _ICOM_THIS_From_IDispatch(IFont, iface);
1020
1021   return IFont_AddRef(this);
1022 }
1023
1024 /************************************************************************
1025  * OLEFontImpl_GetTypeInfoCount (IDispatch)
1026  *
1027  * See Windows documentation for more details on IDispatch methods.
1028  */
1029 static HRESULT WINAPI OLEFontImpl_GetTypeInfoCount(
1030   IDispatch*    iface, 
1031   unsigned int* pctinfo)
1032 {
1033   FIXME("():Stub\n");
1034
1035   return E_NOTIMPL;
1036 }
1037
1038 /************************************************************************
1039  * OLEFontImpl_GetTypeInfo (IDispatch)
1040  *
1041  * See Windows documentation for more details on IDispatch methods.
1042  */
1043 static HRESULT WINAPI OLEFontImpl_GetTypeInfo(
1044   IDispatch*  iface, 
1045   UINT      iTInfo,
1046   LCID        lcid, 
1047   ITypeInfo** ppTInfo)
1048 {
1049   FIXME("():Stub\n");
1050
1051   return E_NOTIMPL;
1052 }
1053
1054 /************************************************************************
1055  * OLEFontImpl_GetIDsOfNames (IDispatch)
1056  *
1057  * See Windows documentation for more details on IDispatch methods.
1058  */
1059 static HRESULT WINAPI OLEFontImpl_GetIDsOfNames(
1060   IDispatch*  iface,
1061   REFIID      riid, 
1062   LPOLESTR* rgszNames, 
1063   UINT      cNames, 
1064   LCID        lcid,
1065   DISPID*     rgDispId)
1066 {
1067   FIXME("():Stub\n");
1068
1069   return E_NOTIMPL;
1070 }
1071
1072 /************************************************************************
1073  * OLEFontImpl_Invoke (IDispatch)
1074  *
1075  * See Windows documentation for more details on IDispatch methods.
1076  */
1077 static HRESULT WINAPI OLEFontImpl_Invoke(
1078   IDispatch*  iface,
1079   DISPID      dispIdMember, 
1080   REFIID      riid, 
1081   LCID        lcid, 
1082   WORD        wFlags,
1083   DISPPARAMS* pDispParams,
1084   VARIANT*    pVarResult, 
1085   EXCEPINFO*  pExepInfo,
1086   UINT*     puArgErr)
1087 {
1088   FIXME("():Stub\n");
1089
1090   return E_NOTIMPL;
1091 }
1092
1093 /************************************************************************
1094  * OLEFontImpl_IPersistStream_QueryInterface (IUnknown)
1095  *
1096  * See Windows documentation for more details on IUnknown methods.
1097  */
1098 static HRESULT WINAPI OLEFontImpl_IPersistStream_QueryInterface(
1099   IPersistStream* iface,
1100   REFIID     riid,
1101   VOID**     ppvoid)
1102 {
1103   _ICOM_THIS_From_IPersistStream(IFont, iface);
1104
1105   return IFont_QueryInterface(this, riid, ppvoid);
1106 }
1107
1108 /************************************************************************
1109  * OLEFontImpl_IPersistStream_Release (IUnknown)
1110  *
1111  * See Windows documentation for more details on IUnknown methods.
1112  */
1113 static ULONG WINAPI OLEFontImpl_IPersistStream_Release(
1114   IPersistStream* iface)
1115 {
1116   _ICOM_THIS_From_IPersistStream(IFont, iface);
1117
1118   return IFont_Release(this);
1119 }
1120
1121 /************************************************************************
1122  * OLEFontImpl_IPersistStream_AddRef (IUnknown)
1123  *
1124  * See Windows documentation for more details on IUnknown methods.
1125  */
1126 static ULONG WINAPI OLEFontImpl_IPersistStream_AddRef(
1127   IPersistStream* iface)
1128 {
1129   _ICOM_THIS_From_IPersistStream(IFont, iface);
1130
1131   return IFont_AddRef(this);
1132 }
1133
1134 /************************************************************************
1135  * OLEFontImpl_GetClassID (IPersistStream)
1136  *
1137  * See Windows documentation for more details on IPersistStream methods.
1138  */
1139 static HRESULT WINAPI OLEFontImpl_GetClassID(
1140   IPersistStream* iface, 
1141   CLSID*                pClassID)
1142 {
1143   if (pClassID==0)
1144     return E_POINTER;
1145
1146   memcpy(pClassID, &CLSID_StdFont, sizeof(CLSID_StdFont));
1147
1148   return S_OK;
1149 }
1150
1151 /************************************************************************
1152  * OLEFontImpl_IsDirty (IPersistStream)
1153  *
1154  * See Windows documentation for more details on IPersistStream methods.
1155  */
1156 static HRESULT WINAPI OLEFontImpl_IsDirty(
1157   IPersistStream*  iface)
1158 {
1159   return S_OK;
1160 }
1161
1162 /************************************************************************
1163  * OLEFontImpl_Load (IPersistStream)
1164  *
1165  * See Windows documentation for more details on IPersistStream methods.
1166  *
1167  * This is the format of the standard font serialization as far as I
1168  * know
1169  *
1170  * Offset   Type   Value           Comment
1171  * 0x0000   Byte   Unknown         Probably a version number, contains 0x01
1172  * 0x0001   Short  Charset         Charset value from the FONTDESC structure
1173  * 0x0003   Byte   Attributes      Flags defined as follows:
1174  *                                     00000010 - Italic
1175  *                                     00000100 - Underline
1176  *                                     00001000 - Strikethrough
1177  * 0x0004   Short  Weight          Weight value from FONTDESC structure
1178  * 0x0006   DWORD  size            "Low" portion of the cySize member of the FONTDESC
1179  *                                 structure/
1180  * 0x000A   Byte   name length     Length of the font name string (no null character)
1181  * 0x000B   String name            Name of the font (ASCII, no nul character)
1182  */
1183 static HRESULT WINAPI OLEFontImpl_Load(
1184   IPersistStream*  iface,
1185   IStream*         pLoadStream)
1186 {
1187   char  readBuffer[0x100];
1188   ULONG cbRead;
1189   BYTE  bVersion;
1190   BYTE  bAttributes;
1191   BYTE  bStringSize;
1192
1193   _ICOM_THIS_From_IPersistStream(OLEFontImpl, iface);
1194   
1195   /*
1196    * Read the version byte
1197    */
1198   IStream_Read(pLoadStream, &bVersion, 1, &cbRead);
1199
1200   if ( (cbRead!=1) ||
1201        (bVersion!=0x01) )
1202     return E_FAIL;
1203
1204   /*
1205    * Charset
1206    */
1207   IStream_Read(pLoadStream, &this->description.sCharset, 2, &cbRead);
1208
1209   if (cbRead!=2)
1210     return E_FAIL;
1211
1212   /*
1213    * Attributes
1214    */
1215   IStream_Read(pLoadStream, &bAttributes, 1, &cbRead);
1216
1217   if (cbRead!=1)
1218     return E_FAIL;
1219
1220   this->description.fItalic        = (bAttributes & FONTPERSIST_ITALIC) != 0;
1221   this->description.fStrikethrough = (bAttributes & FONTPERSIST_STRIKETHROUGH) != 0;
1222   this->description.fUnderline     = (bAttributes & FONTPERSIST_UNDERLINE) != 0;
1223     
1224   /*
1225    * Weight
1226    */
1227   IStream_Read(pLoadStream, &this->description.sWeight, 2, &cbRead);
1228
1229   if (cbRead!=2)
1230     return E_FAIL;
1231
1232   /*
1233    * Size
1234    */
1235   IStream_Read(pLoadStream, &this->description.cySize.u.Lo, 4, &cbRead);
1236
1237   if (cbRead!=4)
1238     return E_FAIL;
1239
1240   this->description.cySize.u.Hi = 0;
1241
1242   /*
1243    * FontName
1244    */
1245   IStream_Read(pLoadStream, &bStringSize, 1, &cbRead);
1246
1247   if (cbRead!=1)
1248     return E_FAIL;
1249
1250   memset(readBuffer, 0, 0x100);
1251   IStream_Read(pLoadStream, readBuffer, bStringSize, &cbRead);
1252
1253   if (cbRead!=bStringSize)
1254     return E_FAIL;
1255
1256   if (this->description.lpstrName!=0)
1257     HeapFree(GetProcessHeap(), 0, this->description.lpstrName);
1258
1259   this->description.lpstrName = HEAP_strdupAtoW(GetProcessHeap(), 
1260                                                     HEAP_ZERO_MEMORY,
1261                                                     readBuffer);
1262
1263   return S_OK;
1264 }
1265
1266 /************************************************************************
1267  * OLEFontImpl_Save (IPersistStream)
1268  *
1269  * See Windows documentation for more details on IPersistStream methods.
1270  */
1271 static HRESULT WINAPI OLEFontImpl_Save(
1272   IPersistStream*  iface,
1273   IStream*         pOutStream,
1274   BOOL             fClearDirty)
1275 {
1276   char* writeBuffer = NULL;
1277   ULONG cbWritten;
1278   BYTE  bVersion = 0x01;
1279   BYTE  bAttributes;
1280   BYTE  bStringSize;
1281   
1282   _ICOM_THIS_From_IPersistStream(OLEFontImpl, iface);
1283
1284   /*
1285    * Read the version byte
1286    */
1287   IStream_Write(pOutStream, &bVersion, 1, &cbWritten);
1288
1289   if (cbWritten!=1)
1290     return E_FAIL;
1291
1292   /*
1293    * Charset
1294    */
1295   IStream_Write(pOutStream, &this->description.sCharset, 2, &cbWritten);
1296
1297   if (cbWritten!=2)
1298     return E_FAIL;
1299
1300   /*
1301    * Attributes
1302    */
1303   bAttributes = 0;
1304
1305   if (this->description.fItalic)
1306     bAttributes |= FONTPERSIST_ITALIC;
1307
1308   if (this->description.fStrikethrough)
1309     bAttributes |= FONTPERSIST_STRIKETHROUGH;
1310   
1311   if (this->description.fUnderline)
1312     bAttributes |= FONTPERSIST_UNDERLINE;
1313
1314   IStream_Write(pOutStream, &bAttributes, 1, &cbWritten);
1315
1316   if (cbWritten!=1)
1317     return E_FAIL;
1318   
1319   /*
1320    * Weight
1321    */
1322   IStream_Write(pOutStream, &this->description.sWeight, 2, &cbWritten);
1323
1324   if (cbWritten!=2)
1325     return E_FAIL;
1326
1327   /*
1328    * Size
1329    */
1330   IStream_Write(pOutStream, &this->description.cySize.u.Lo, 4, &cbWritten);
1331
1332   if (cbWritten!=4)
1333     return E_FAIL;
1334
1335   /*
1336    * FontName
1337    */
1338   if (this->description.lpstrName!=0)
1339     bStringSize = lstrlenW(this->description.lpstrName);
1340   else
1341     bStringSize = 0;
1342
1343   IStream_Write(pOutStream, &bStringSize, 1, &cbWritten);
1344
1345   if (cbWritten!=1)
1346     return E_FAIL;
1347
1348   if (bStringSize!=0)
1349   {
1350     writeBuffer = HEAP_strdupWtoA(GetProcessHeap(), 
1351                                   HEAP_ZERO_MEMORY,
1352                                   this->description.lpstrName);
1353
1354     if (writeBuffer==0)
1355       return E_OUTOFMEMORY;
1356
1357     IStream_Write(pOutStream, writeBuffer, bStringSize, &cbWritten);
1358     
1359     HeapFree(GetProcessHeap(), 0, writeBuffer);
1360
1361     if (cbWritten!=bStringSize)
1362       return E_FAIL;
1363   }
1364
1365   return S_OK;
1366 }
1367
1368 /************************************************************************
1369  * OLEFontImpl_GetSizeMax (IPersistStream)
1370  *
1371  * See Windows documentation for more details on IPersistStream methods.
1372  */
1373 static HRESULT WINAPI OLEFontImpl_GetSizeMax(
1374   IPersistStream*  iface,
1375   ULARGE_INTEGER*  pcbSize)
1376 {
1377   _ICOM_THIS_From_IPersistStream(OLEFontImpl, iface);
1378
1379   if (pcbSize==NULL)
1380     return E_POINTER;
1381
1382   pcbSize->HighPart = 0;
1383   pcbSize->LowPart = 0;
1384
1385   pcbSize->LowPart += sizeof(BYTE);  /* Version */
1386   pcbSize->LowPart += sizeof(WORD);  /* Lang code */
1387   pcbSize->LowPart += sizeof(BYTE);  /* Flags */
1388   pcbSize->LowPart += sizeof(WORD);  /* Weight */
1389   pcbSize->LowPart += sizeof(DWORD); /* Size */
1390   pcbSize->LowPart += sizeof(BYTE);  /* StrLength */
1391
1392   if (this->description.lpstrName!=0)
1393     pcbSize->LowPart += lstrlenW(this->description.lpstrName);
1394
1395   return S_OK;
1396 }