2 * OLE Font encapsulation implementation
4 * This file contains an implementation of the IFont
5 * interface and the OleCreateFontIndirect API call.
7 * Copyright 1999 Francis Beaudet
8 * Copyright 2006 (Google) Benjamin Arai
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 #define NONAMELESSUNION
30 #define NONAMELESSSTRUCT
37 #include "wine/list.h"
38 #include "wine/unicode.h"
40 #include "oleauto.h" /* for SysAllocString(....) */
43 #include "wine/debug.h"
44 #include "connpt.h" /* for CreateConnectionPoint */
47 WINE_DEFAULT_DEBUG_CHANNEL(ole);
49 /***********************************************************************
50 * Declaration of constants used when serializing the font object.
52 #define FONTPERSIST_ITALIC 0x02
53 #define FONTPERSIST_UNDERLINE 0x04
54 #define FONTPERSIST_STRIKETHROUGH 0x08
56 static HDC olefont_hdc;
58 /***********************************************************************
59 * List of the HFONTs it has given out, with each one having a separate
62 typedef struct _HFONTItem
66 /* Reference count of any IFont objects that own this hfont */
69 /* Total reference count of any refs held by the application obtained by AddRefHfont plus any internal refs */
72 /* The font associated with this object. */
75 } HFONTItem, *PHFONTItem;
77 static struct list OLEFontImpl_hFontList = LIST_INIT(OLEFontImpl_hFontList);
79 /* Counts how many fonts contain at least one lock */
80 static LONG ifont_cnt = 0;
82 /***********************************************************************
83 * Critical section for OLEFontImpl_hFontList
85 static CRITICAL_SECTION OLEFontImpl_csHFONTLIST;
86 static CRITICAL_SECTION_DEBUG OLEFontImpl_csHFONTLIST_debug =
88 0, 0, &OLEFontImpl_csHFONTLIST,
89 { &OLEFontImpl_csHFONTLIST_debug.ProcessLocksList,
90 &OLEFontImpl_csHFONTLIST_debug.ProcessLocksList },
91 0, 0, { (DWORD_PTR)(__FILE__ ": OLEFontImpl_csHFONTLIST") }
93 static CRITICAL_SECTION OLEFontImpl_csHFONTLIST = { &OLEFontImpl_csHFONTLIST_debug, -1, 0, 0, 0, 0 };
95 static HDC get_dc(void)
98 EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
100 olefont_hdc = CreateCompatibleDC(NULL);
102 LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
106 static void delete_dc(void)
108 EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
111 DeleteDC(olefont_hdc);
114 LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
117 static void HFONTItem_Delete(PHFONTItem item)
119 DeleteObject(item->gdiFont);
120 list_remove(&item->entry);
121 HeapFree(GetProcessHeap(), 0, item);
124 /* Find hfont item entry in the list. Should be called while holding the crit sect */
125 static HFONTItem *find_hfontitem(HFONT hfont)
129 LIST_FOR_EACH_ENTRY(item, &OLEFontImpl_hFontList, HFONTItem, entry)
131 if (item->gdiFont == hfont)
137 /* Add an item to the list with one internal reference */
138 static HRESULT add_hfontitem(HFONT hfont)
140 HFONTItem *new_item = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_item));
142 if(!new_item) return E_OUTOFMEMORY;
144 new_item->int_refs = 1;
145 new_item->total_refs = 1;
146 new_item->gdiFont = hfont;
147 EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
148 list_add_tail(&OLEFontImpl_hFontList,&new_item->entry);
149 LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
153 static HRESULT inc_int_ref(HFONT hfont)
156 HRESULT hr = S_FALSE;
158 EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
159 item = find_hfontitem(hfont);
167 LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
172 /* decrements the internal ref of a hfont item. If both refs are zero it'll
173 remove the item from the list and delete the hfont */
174 static HRESULT dec_int_ref(HFONT hfont)
177 HRESULT hr = S_FALSE;
179 EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
180 item = find_hfontitem(hfont);
186 if(item->int_refs == 0 && item->total_refs == 0)
187 HFONTItem_Delete(item);
190 LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
195 static HRESULT inc_ext_ref(HFONT hfont)
198 HRESULT hr = S_FALSE;
200 EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
202 item = find_hfontitem(hfont);
208 LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
213 static HRESULT dec_ext_ref(HFONT hfont)
216 HRESULT hr = S_FALSE;
218 EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
220 item = find_hfontitem(hfont);
223 if(--item->total_refs >= 0) hr = S_OK;
225 LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
230 static WCHAR *strdupW(const WCHAR* str)
233 DWORD size = (strlenW(str) + 1) * sizeof(WCHAR);
235 ret = HeapAlloc(GetProcessHeap(), 0, size);
237 memcpy(ret, str, size);
241 /***********************************************************************
242 * Declaration of the implementation class for the IFont interface
244 typedef struct OLEFontImpl OLEFontImpl;
249 * This class supports many interfaces. IUnknown, IFont,
250 * IDispatch, IDispFont IPersistStream and IConnectionPointContainer.
251 * The first two are supported by the first vtable, the next two are
252 * supported by the second table and the last two have their own.
254 const IFontVtbl* lpVtbl;
255 const IDispatchVtbl* lpvtblIDispatch;
256 const IPersistStreamVtbl* lpvtblIPersistStream;
257 const IConnectionPointContainerVtbl* lpvtblIConnectionPointContainer;
258 const IPersistPropertyBagVtbl* lpvtblIPersistPropertyBag;
259 const IPersistStreamInitVtbl* lpvtblIPersistStreamInit;
261 * Reference count for that instance of the class.
266 * This structure contains the description of the class.
268 FONTDESC description;
271 * Contain the font associated with this object.
281 IConnectionPoint *pPropertyNotifyCP;
282 IConnectionPoint *pFontEventsCP;
286 * Here, I define utility macros to help with the casting of the
288 * There is a version to accommodate all of the VTables implemented
292 static inline OLEFontImpl *impl_from_IDispatch( IDispatch *iface )
294 return (OLEFontImpl *)((char*)iface - FIELD_OFFSET(OLEFontImpl, lpvtblIDispatch));
297 static inline OLEFontImpl *impl_from_IPersistStream( IPersistStream *iface )
299 return (OLEFontImpl *)((char*)iface - FIELD_OFFSET(OLEFontImpl, lpvtblIPersistStream));
302 static inline OLEFontImpl *impl_from_IConnectionPointContainer( IConnectionPointContainer *iface )
304 return (OLEFontImpl *)((char*)iface - FIELD_OFFSET(OLEFontImpl, lpvtblIConnectionPointContainer));
307 static inline OLEFontImpl *impl_from_IPersistPropertyBag( IPersistPropertyBag *iface )
309 return (OLEFontImpl *)((char*)iface - FIELD_OFFSET(OLEFontImpl, lpvtblIPersistPropertyBag));
312 static inline OLEFontImpl *impl_from_IPersistStreamInit( IPersistStreamInit *iface )
314 return (OLEFontImpl *)((char*)iface - FIELD_OFFSET(OLEFontImpl, lpvtblIPersistStreamInit));
318 /***********************************************************************
319 * Prototypes for the implementation functions for the IFont
322 static OLEFontImpl* OLEFontImpl_Construct(const FONTDESC *fontDesc);
323 static void OLEFontImpl_Destroy(OLEFontImpl* fontDesc);
324 static ULONG WINAPI OLEFontImpl_AddRef(IFont* iface);
326 /******************************************************************************
327 * OleCreateFontIndirect [OLEAUT32.420]
329 HRESULT WINAPI OleCreateFontIndirect(
330 LPFONTDESC lpFontDesc,
334 OLEFontImpl* newFont = 0;
337 TRACE("(%p, %s, %p)\n", lpFontDesc, debugstr_guid(riid), ppvObj);
349 static WCHAR fname[] = { 'S','y','s','t','e','m',0 };
351 fd.cbSizeofstruct = sizeof(fd);
352 fd.lpstrName = fname;
353 fd.cySize.s.Lo = 80000;
359 fd.fStrikethrough = 0;
364 * Try to construct a new instance of the class.
366 newFont = OLEFontImpl_Construct(lpFontDesc);
369 return E_OUTOFMEMORY;
372 * Make sure it supports the interface required by the caller.
374 hr = IFont_QueryInterface((IFont*)newFont, riid, ppvObj);
377 * Release the reference obtained in the constructor. If
378 * the QueryInterface was unsuccessful, it will free the class.
380 IFont_Release((IFont*)newFont);
386 /***********************************************************************
387 * Implementation of the OLEFontImpl class.
390 /***********************************************************************
391 * OLEFont_SendNotify (internal)
393 * Sends notification messages of changed properties to any interested
396 static void OLEFont_SendNotify(OLEFontImpl* this, DISPID dispID)
398 static const WCHAR wszName[] = {'N','a','m','e',0};
399 static const WCHAR wszSize[] = {'S','i','z','e',0};
400 static const WCHAR wszBold[] = {'B','o','l','d',0};
401 static const WCHAR wszItalic[] = {'I','t','a','l','i','c',0};
402 static const WCHAR wszUnder[] = {'U','n','d','e','r','l','i','n','e',0};
403 static const WCHAR wszStrike[] = {'S','t','r','i','k','e','t','h','r','o','u','g','h',0};
404 static const WCHAR wszWeight[] = {'W','e','i','g','h','t',0};
405 static const WCHAR wszCharset[] = {'C','h','a','r','s','s','e','t',0};
406 static const LPCWSTR dispid_mapping[] =
419 IEnumConnections *pEnum;
425 hres = IConnectionPoint_EnumConnections(this->pPropertyNotifyCP, &pEnum);
428 while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) {
429 IPropertyNotifySink *sink;
431 IUnknown_QueryInterface(CD.pUnk, &IID_IPropertyNotifySink, (LPVOID)&sink);
432 IPropertyNotifySink_OnChanged(sink, dispID);
433 IPropertyNotifySink_Release(sink);
434 IUnknown_Release(CD.pUnk);
436 IEnumConnections_Release(pEnum);
439 hres = IConnectionPoint_EnumConnections(this->pFontEventsCP, &pEnum);
442 DISPPARAMS dispparams;
445 VariantInit(&vararg);
446 V_VT(&vararg) = VT_BSTR;
447 V_BSTR(&vararg) = SysAllocString(dispid_mapping[dispID]);
449 dispparams.cArgs = 1;
450 dispparams.cNamedArgs = 0;
451 dispparams.rgdispidNamedArgs = NULL;
452 dispparams.rgvarg = &vararg;
454 while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) {
455 IFontEventsDisp *disp;
457 IUnknown_QueryInterface(CD.pUnk, &IID_IFontEventsDisp, (LPVOID)&disp);
458 IDispatch_Invoke(disp, DISPID_FONT_CHANGED, &IID_NULL,
459 LOCALE_NEUTRAL, INVOKE_FUNC, &dispparams, NULL,
462 IDispatch_Release(disp);
463 IUnknown_Release(CD.pUnk);
465 VariantClear(&vararg);
466 IEnumConnections_Release(pEnum);
470 /************************************************************************
471 * OLEFontImpl_QueryInterface (IUnknown)
473 * See Windows documentation for more details on IUnknown methods.
475 static HRESULT WINAPI OLEFontImpl_QueryInterface(
480 OLEFontImpl *this = (OLEFontImpl *)iface;
481 TRACE("(%p)->(%s, %p)\n", this, debugstr_guid(riid), ppvObject);
484 * Perform a sanity check on the parameters.
486 if ( (this==0) || (ppvObject==0) )
490 * Initialize the return parameter.
495 * Compare the riid with the interface IDs implemented by this object.
497 if (IsEqualGUID(&IID_IUnknown, riid))
499 if (IsEqualGUID(&IID_IFont, riid))
501 if (IsEqualGUID(&IID_IDispatch, riid))
502 *ppvObject = &this->lpvtblIDispatch;
503 if (IsEqualGUID(&IID_IFontDisp, riid))
504 *ppvObject = &this->lpvtblIDispatch;
505 if (IsEqualIID(&IID_IPersist, riid) || IsEqualGUID(&IID_IPersistStream, riid))
506 *ppvObject = &this->lpvtblIPersistStream;
507 if (IsEqualGUID(&IID_IConnectionPointContainer, riid))
508 *ppvObject = &this->lpvtblIConnectionPointContainer;
509 if (IsEqualGUID(&IID_IPersistPropertyBag, riid))
510 *ppvObject = &this->lpvtblIPersistPropertyBag;
511 if (IsEqualGUID(&IID_IPersistStreamInit, riid))
512 *ppvObject = &this->lpvtblIPersistStreamInit;
515 * Check that we obtained an interface.
519 FIXME("() : asking for unsupported interface %s\n",debugstr_guid(riid));
520 return E_NOINTERFACE;
522 OLEFontImpl_AddRef((IFont*)this);
526 /************************************************************************
527 * OLEFontImpl_AddRef (IUnknown)
529 * See Windows documentation for more details on IUnknown methods.
531 static ULONG WINAPI OLEFontImpl_AddRef(
534 OLEFontImpl *this = (OLEFontImpl *)iface;
535 TRACE("(%p)->(ref=%d)\n", this, this->ref);
536 return InterlockedIncrement(&this->ref);
539 /************************************************************************
540 * OLEFontImpl_Release (IUnknown)
542 * See Windows documentation for more details on IUnknown methods.
544 static ULONG WINAPI OLEFontImpl_Release(
547 OLEFontImpl *this = (OLEFontImpl *)iface;
549 TRACE("(%p)->(ref=%d)\n", this, this->ref);
551 /* Decrease the reference count for current interface */
552 ret = InterlockedDecrement(&this->ref);
554 /* If the reference count goes down to 0, destroy. */
557 ULONG fontlist_refs = InterlockedDecrement(&ifont_cnt);
559 /* Final IFont object so destroy font cache */
560 if (fontlist_refs == 0)
562 HFONTItem *item, *cursor2;
564 EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
565 LIST_FOR_EACH_ENTRY_SAFE(item, cursor2, &OLEFontImpl_hFontList, HFONTItem, entry)
566 HFONTItem_Delete(item);
567 LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
572 dec_int_ref(this->gdiFont);
574 OLEFontImpl_Destroy(this);
586 static int CALLBACK font_enum_proc(const LOGFONTW *elf, const TEXTMETRICW *ntm, DWORD type, LPARAM lp)
588 enum_data *data = (enum_data*)lp;
590 if(elf->lfCharSet == data->orig_cs)
592 data->avail_cs = data->orig_cs;
595 if(data->avail_cs == -1) data->avail_cs = elf->lfCharSet;
599 static void realize_font(OLEFontImpl *This)
605 WCHAR text_face[LF_FACESIZE];
614 old_font = SelectObject(hdc, This->gdiFont);
615 GetTextFaceW(hdc, sizeof(text_face) / sizeof(text_face[0]), text_face);
616 SelectObject(hdc, old_font);
617 dec_int_ref(This->gdiFont);
621 memset(&logFont, 0, sizeof(LOGFONTW));
623 lstrcpynW(logFont.lfFaceName, This->description.lpstrName, LF_FACESIZE);
624 logFont.lfCharSet = This->description.sCharset;
626 /* If the font name has been changed then enumerate all charsets
627 and pick one that'll result in the font specified being selected */
628 if(text_face[0] && lstrcmpiW(text_face, This->description.lpstrName))
631 data.orig_cs = This->description.sCharset;
633 logFont.lfCharSet = DEFAULT_CHARSET;
634 EnumFontFamiliesExW(get_dc(), &logFont, font_enum_proc, (LPARAM)&data, 0);
635 if(data.avail_cs != -1) logFont.lfCharSet = data.avail_cs;
640 * The height of the font returned by the get_Size property is the
641 * height of the font in points multiplied by 10000... Using some
642 * simple conversions and the ratio given by the application, it can
643 * be converted to a height in pixels.
645 * Standard ratio is 72 / 2540, or 18 / 635 in lowest terms.
646 * Ratio is applied here relative to the standard.
649 fontHeight = MulDiv( This->description.cySize.s.Lo, This->cyLogical*635, This->cyHimetric*18 );
652 logFont.lfHeight = ((fontHeight%10000L)>5000L) ? (-fontHeight/10000L) - 1 :
653 (-fontHeight/10000L);
654 logFont.lfItalic = This->description.fItalic;
655 logFont.lfUnderline = This->description.fUnderline;
656 logFont.lfStrikeOut = This->description.fStrikethrough;
657 logFont.lfWeight = This->description.sWeight;
658 logFont.lfOutPrecision = OUT_CHARACTER_PRECIS;
659 logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
660 logFont.lfQuality = DEFAULT_QUALITY;
661 logFont.lfPitchAndFamily = DEFAULT_PITCH;
663 This->gdiFont = CreateFontIndirectW(&logFont);
666 add_hfontitem(This->gdiFont);
668 /* Fixup the name and charset properties so that they match the
670 old_font = SelectObject(get_dc(), This->gdiFont);
671 GetTextFaceW(hdc, sizeof(text_face) / sizeof(text_face[0]), text_face);
672 if(lstrcmpiW(text_face, This->description.lpstrName))
674 HeapFree(GetProcessHeap(), 0, This->description.lpstrName);
675 This->description.lpstrName = strdupW(text_face);
677 GetTextMetricsW(hdc, &tm);
678 This->description.sCharset = tm.tmCharSet;
679 SelectObject(hdc, old_font);
683 /************************************************************************
684 * OLEFontImpl_get_Name (IFont)
686 * See Windows documentation for more details on IFont methods.
688 static HRESULT WINAPI OLEFontImpl_get_Name(
692 OLEFontImpl *this = (OLEFontImpl *)iface;
693 TRACE("(%p)->(%p)\n", this, pname);
700 if(this->dirty) realize_font(this);
702 if (this->description.lpstrName!=0)
703 *pname = SysAllocString(this->description.lpstrName);
710 /************************************************************************
711 * OLEFontImpl_put_Name (IFont)
713 * See Windows documentation for more details on IFont methods.
715 static HRESULT WINAPI OLEFontImpl_put_Name(
719 OLEFontImpl *this = (OLEFontImpl *)iface;
720 TRACE("(%p)->(%p)\n", this, name);
723 return CTL_E_INVALIDPROPERTYVALUE;
725 if (this->description.lpstrName==0)
727 this->description.lpstrName = HeapAlloc(GetProcessHeap(),
729 (lstrlenW(name)+1) * sizeof(WCHAR));
733 this->description.lpstrName = HeapReAlloc(GetProcessHeap(),
735 this->description.lpstrName,
736 (lstrlenW(name)+1) * sizeof(WCHAR));
739 if (this->description.lpstrName==0)
740 return E_OUTOFMEMORY;
742 strcpyW(this->description.lpstrName, name);
743 TRACE("new name %s\n", debugstr_w(this->description.lpstrName));
744 OLEFont_SendNotify(this, DISPID_FONT_NAME);
748 /************************************************************************
749 * OLEFontImpl_get_Size (IFont)
751 * See Windows documentation for more details on IFont methods.
753 static HRESULT WINAPI OLEFontImpl_get_Size(
757 OLEFontImpl *this = (OLEFontImpl *)iface;
758 TRACE("(%p)->(%p)\n", this, psize);
766 if(this->dirty) realize_font(this);
769 psize->s.Lo = this->description.cySize.s.Lo;
774 /************************************************************************
775 * OLEFontImpl_put_Size (IFont)
777 * See Windows documentation for more details on IFont methods.
779 static HRESULT WINAPI OLEFontImpl_put_Size(
783 OLEFontImpl *this = (OLEFontImpl *)iface;
784 TRACE("(%p)->(%d)\n", this, size.s.Lo);
785 this->description.cySize.s.Hi = 0;
786 this->description.cySize.s.Lo = size.s.Lo;
787 OLEFont_SendNotify(this, DISPID_FONT_SIZE);
792 /************************************************************************
793 * OLEFontImpl_get_Bold (IFont)
795 * See Windows documentation for more details on IFont methods.
797 static HRESULT WINAPI OLEFontImpl_get_Bold(
801 OLEFontImpl *this = (OLEFontImpl *)iface;
802 TRACE("(%p)->(%p)\n", this, pbold);
809 if(this->dirty) realize_font(this);
811 *pbold = this->description.sWeight > 550;
816 /************************************************************************
817 * OLEFontImpl_put_Bold (IFont)
819 * See Windows documentation for more details on IFont methods.
821 static HRESULT WINAPI OLEFontImpl_put_Bold(
825 OLEFontImpl *this = (OLEFontImpl *)iface;
826 TRACE("(%p)->(%d)\n", this, bold);
827 this->description.sWeight = bold ? FW_BOLD : FW_NORMAL;
828 OLEFont_SendNotify(this, DISPID_FONT_BOLD);
833 /************************************************************************
834 * OLEFontImpl_get_Italic (IFont)
836 * See Windows documentation for more details on IFont methods.
838 static HRESULT WINAPI OLEFontImpl_get_Italic(
842 OLEFontImpl *this = (OLEFontImpl *)iface;
843 TRACE("(%p)->(%p)\n", this, pitalic);
850 if(this->dirty) realize_font(this);
852 *pitalic = this->description.fItalic;
857 /************************************************************************
858 * OLEFontImpl_put_Italic (IFont)
860 * See Windows documentation for more details on IFont methods.
862 static HRESULT WINAPI OLEFontImpl_put_Italic(
866 OLEFontImpl *this = (OLEFontImpl *)iface;
867 TRACE("(%p)->(%d)\n", this, italic);
869 this->description.fItalic = italic;
871 OLEFont_SendNotify(this, DISPID_FONT_ITALIC);
875 /************************************************************************
876 * OLEFontImpl_get_Underline (IFont)
878 * See Windows documentation for more details on IFont methods.
880 static HRESULT WINAPI OLEFontImpl_get_Underline(
884 OLEFontImpl *this = (OLEFontImpl *)iface;
885 TRACE("(%p)->(%p)\n", this, punderline);
893 if(this->dirty) realize_font(this);
895 *punderline = this->description.fUnderline;
900 /************************************************************************
901 * OLEFontImpl_put_Underline (IFont)
903 * See Windows documentation for more details on IFont methods.
905 static HRESULT WINAPI OLEFontImpl_put_Underline(
909 OLEFontImpl *this = (OLEFontImpl *)iface;
910 TRACE("(%p)->(%d)\n", this, underline);
912 this->description.fUnderline = underline;
914 OLEFont_SendNotify(this, DISPID_FONT_UNDER);
918 /************************************************************************
919 * OLEFontImpl_get_Strikethrough (IFont)
921 * See Windows documentation for more details on IFont methods.
923 static HRESULT WINAPI OLEFontImpl_get_Strikethrough(
925 BOOL* pstrikethrough)
927 OLEFontImpl *this = (OLEFontImpl *)iface;
928 TRACE("(%p)->(%p)\n", this, pstrikethrough);
933 if (pstrikethrough==0)
936 if(this->dirty) realize_font(this);
938 *pstrikethrough = this->description.fStrikethrough;
943 /************************************************************************
944 * OLEFontImpl_put_Strikethrough (IFont)
946 * See Windows documentation for more details on IFont methods.
948 static HRESULT WINAPI OLEFontImpl_put_Strikethrough(
952 OLEFontImpl *this = (OLEFontImpl *)iface;
953 TRACE("(%p)->(%d)\n", this, strikethrough);
955 this->description.fStrikethrough = strikethrough;
956 OLEFont_SendNotify(this, DISPID_FONT_STRIKE);
961 /************************************************************************
962 * OLEFontImpl_get_Weight (IFont)
964 * See Windows documentation for more details on IFont methods.
966 static HRESULT WINAPI OLEFontImpl_get_Weight(
970 OLEFontImpl *this = (OLEFontImpl *)iface;
971 TRACE("(%p)->(%p)\n", this, pweight);
979 if(this->dirty) realize_font(this);
981 *pweight = this->description.sWeight;
986 /************************************************************************
987 * OLEFontImpl_put_Weight (IFont)
989 * See Windows documentation for more details on IFont methods.
991 static HRESULT WINAPI OLEFontImpl_put_Weight(
995 OLEFontImpl *this = (OLEFontImpl *)iface;
996 TRACE("(%p)->(%d)\n", this, weight);
998 this->description.sWeight = weight;
1000 OLEFont_SendNotify(this, DISPID_FONT_WEIGHT);
1004 /************************************************************************
1005 * OLEFontImpl_get_Charset (IFont)
1007 * See Windows documentation for more details on IFont methods.
1009 static HRESULT WINAPI OLEFontImpl_get_Charset(
1013 OLEFontImpl *this = (OLEFontImpl *)iface;
1014 TRACE("(%p)->(%p)\n", this, pcharset);
1022 if(this->dirty) realize_font(this);
1024 *pcharset = this->description.sCharset;
1029 /************************************************************************
1030 * OLEFontImpl_put_Charset (IFont)
1032 * See Windows documentation for more details on IFont methods.
1034 static HRESULT WINAPI OLEFontImpl_put_Charset(
1038 OLEFontImpl *this = (OLEFontImpl *)iface;
1039 TRACE("(%p)->(%d)\n", this, charset);
1041 this->description.sCharset = charset;
1042 OLEFont_SendNotify(this, DISPID_FONT_CHARSET);
1047 /************************************************************************
1048 * OLEFontImpl_get_hFont (IFont)
1050 * See Windows documentation for more details on IFont methods.
1052 static HRESULT WINAPI OLEFontImpl_get_hFont(
1056 OLEFontImpl *this = (OLEFontImpl *)iface;
1057 TRACE("(%p)->(%p)\n", this, phfont);
1061 if(this->dirty) realize_font(this);
1063 *phfont = this->gdiFont;
1064 TRACE("Returning %p\n", *phfont);
1068 /************************************************************************
1069 * OLEFontImpl_Clone (IFont)
1071 * See Windows documentation for more details on IFont methods.
1073 static HRESULT WINAPI OLEFontImpl_Clone(
1077 OLEFontImpl* newObject = 0;
1078 OLEFontImpl *this = (OLEFontImpl *)iface;
1080 TRACE("(%p)->(%p)\n", this, ppfont);
1088 * Allocate space for the object.
1090 newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(OLEFontImpl));
1092 if (newObject==NULL)
1093 return E_OUTOFMEMORY;
1097 /* We need to alloc new memory for the string, otherwise
1098 * we free memory twice.
1100 newObject->description.lpstrName = HeapAlloc(
1102 (1+strlenW(this->description.lpstrName))*2
1104 strcpyW(newObject->description.lpstrName, this->description.lpstrName);
1107 /* Increment internal ref in hfont item list */
1108 if(newObject->gdiFont) inc_int_ref(newObject->gdiFont);
1110 InterlockedIncrement(&ifont_cnt);
1112 /* create new connection points */
1113 newObject->pPropertyNotifyCP = NULL;
1114 newObject->pFontEventsCP = NULL;
1115 CreateConnectionPoint((IUnknown*)newObject, &IID_IPropertyNotifySink, &newObject->pPropertyNotifyCP);
1116 CreateConnectionPoint((IUnknown*)newObject, &IID_IFontEventsDisp, &newObject->pFontEventsCP);
1118 if (!newObject->pPropertyNotifyCP || !newObject->pFontEventsCP)
1120 OLEFontImpl_Destroy(newObject);
1121 return E_OUTOFMEMORY;
1124 /* The cloned object starts with a reference count of 1 */
1127 *ppfont = (IFont*)newObject;
1132 /************************************************************************
1133 * OLEFontImpl_IsEqual (IFont)
1135 * See Windows documentation for more details on IFont methods.
1137 static HRESULT WINAPI OLEFontImpl_IsEqual(
1141 OLEFontImpl *left = (OLEFontImpl *)iface;
1142 OLEFontImpl *right = (OLEFontImpl *)pFontOther;
1144 INT left_len,right_len;
1146 if((iface == NULL) || (pFontOther == NULL))
1148 else if (left->description.cySize.s.Lo != right->description.cySize.s.Lo)
1150 else if (left->description.cySize.s.Hi != right->description.cySize.s.Hi)
1152 else if (left->description.sWeight != right->description.sWeight)
1154 else if (left->description.sCharset != right->description.sCharset)
1156 else if (left->description.fItalic != right->description.fItalic)
1158 else if (left->description.fUnderline != right->description.fUnderline)
1160 else if (left->description.fStrikethrough != right->description.fStrikethrough)
1163 /* Check from string */
1164 left_len = strlenW(left->description.lpstrName);
1165 right_len = strlenW(right->description.lpstrName);
1166 ret = CompareStringW(0,0,left->description.lpstrName, left_len,
1167 right->description.lpstrName, right_len);
1168 if (ret != CSTR_EQUAL)
1174 /************************************************************************
1175 * OLEFontImpl_SetRatio (IFont)
1177 * See Windows documentation for more details on IFont methods.
1179 static HRESULT WINAPI OLEFontImpl_SetRatio(
1184 OLEFontImpl *this = (OLEFontImpl *)iface;
1185 TRACE("(%p)->(%d, %d)\n", this, cyLogical, cyHimetric);
1187 this->cyLogical = cyLogical;
1188 this->cyHimetric = cyHimetric;
1193 /************************************************************************
1194 * OLEFontImpl_QueryTextMetrics (IFont)
1196 * See Windows documentation for more details on IFont methods.
1198 static HRESULT WINAPI OLEFontImpl_QueryTextMetrics(
1203 HFONT hOldFont, hNewFont;
1206 OLEFontImpl_get_hFont(iface, &hNewFont);
1207 hOldFont = SelectObject(hdcRef, hNewFont);
1208 GetTextMetricsW(hdcRef, ptm);
1209 SelectObject(hdcRef, hOldFont);
1210 ReleaseDC(0, hdcRef);
1214 /************************************************************************
1215 * OLEFontImpl_AddRefHfont (IFont)
1217 * See Windows documentation for more details on IFont methods.
1219 static HRESULT WINAPI OLEFontImpl_AddRefHfont(
1223 OLEFontImpl *this = (OLEFontImpl *)iface;
1225 TRACE("(%p)->(%p)\n", this, hfont);
1227 if (!hfont) return E_INVALIDARG;
1229 return inc_ext_ref(hfont);
1232 /************************************************************************
1233 * OLEFontImpl_ReleaseHfont (IFont)
1235 * See Windows documentation for more details on IFont methods.
1237 static HRESULT WINAPI OLEFontImpl_ReleaseHfont(
1241 OLEFontImpl *this = (OLEFontImpl *)iface;
1243 TRACE("(%p)->(%p)\n", this, hfont);
1245 if (!hfont) return E_INVALIDARG;
1247 return dec_ext_ref(hfont);
1250 /************************************************************************
1251 * OLEFontImpl_SetHdc (IFont)
1253 * See Windows documentation for more details on IFont methods.
1255 static HRESULT WINAPI OLEFontImpl_SetHdc(
1259 OLEFontImpl *this = (OLEFontImpl *)iface;
1260 FIXME("(%p)->(%p): Stub\n", this, hdc);
1265 * Virtual function tables for the OLEFontImpl class.
1267 static const IFontVtbl OLEFontImpl_VTable =
1269 OLEFontImpl_QueryInterface,
1271 OLEFontImpl_Release,
1272 OLEFontImpl_get_Name,
1273 OLEFontImpl_put_Name,
1274 OLEFontImpl_get_Size,
1275 OLEFontImpl_put_Size,
1276 OLEFontImpl_get_Bold,
1277 OLEFontImpl_put_Bold,
1278 OLEFontImpl_get_Italic,
1279 OLEFontImpl_put_Italic,
1280 OLEFontImpl_get_Underline,
1281 OLEFontImpl_put_Underline,
1282 OLEFontImpl_get_Strikethrough,
1283 OLEFontImpl_put_Strikethrough,
1284 OLEFontImpl_get_Weight,
1285 OLEFontImpl_put_Weight,
1286 OLEFontImpl_get_Charset,
1287 OLEFontImpl_put_Charset,
1288 OLEFontImpl_get_hFont,
1290 OLEFontImpl_IsEqual,
1291 OLEFontImpl_SetRatio,
1292 OLEFontImpl_QueryTextMetrics,
1293 OLEFontImpl_AddRefHfont,
1294 OLEFontImpl_ReleaseHfont,
1298 /************************************************************************
1299 * OLEFontImpl_IDispatch_QueryInterface (IUnknown)
1301 * See Windows documentation for more details on IUnknown methods.
1303 static HRESULT WINAPI OLEFontImpl_IDispatch_QueryInterface(
1308 OLEFontImpl *this = impl_from_IDispatch(iface);
1310 return IFont_QueryInterface((IFont *)this, riid, ppvoid);
1313 /************************************************************************
1314 * OLEFontImpl_IDispatch_Release (IUnknown)
1316 * See Windows documentation for more details on IUnknown methods.
1318 static ULONG WINAPI OLEFontImpl_IDispatch_Release(
1321 OLEFontImpl *this = impl_from_IDispatch(iface);
1323 return IFont_Release((IFont *)this);
1326 /************************************************************************
1327 * OLEFontImpl_IDispatch_AddRef (IUnknown)
1329 * See Windows documentation for more details on IUnknown methods.
1331 static ULONG WINAPI OLEFontImpl_IDispatch_AddRef(
1334 OLEFontImpl *this = impl_from_IDispatch(iface);
1336 return IFont_AddRef((IFont *)this);
1339 /************************************************************************
1340 * OLEFontImpl_GetTypeInfoCount (IDispatch)
1342 * See Windows documentation for more details on IDispatch methods.
1344 static HRESULT WINAPI OLEFontImpl_GetTypeInfoCount(
1346 unsigned int* pctinfo)
1348 OLEFontImpl *this = impl_from_IDispatch(iface);
1349 TRACE("(%p)->(%p)\n", this, pctinfo);
1355 /************************************************************************
1356 * OLEFontImpl_GetTypeInfo (IDispatch)
1358 * See Windows documentation for more details on IDispatch methods.
1360 static HRESULT WINAPI OLEFontImpl_GetTypeInfo(
1364 ITypeInfo** ppTInfo)
1366 static const WCHAR stdole2tlb[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
1370 OLEFontImpl *this = impl_from_IDispatch(iface);
1371 TRACE("(%p, iTInfo=%d, lcid=%04x, %p)\n", this, iTInfo, (int)lcid, ppTInfo);
1374 hres = LoadTypeLib(stdole2tlb, &tl);
1376 ERR("Could not load the stdole2.tlb?\n");
1379 hres = ITypeLib_GetTypeInfoOfGuid(tl, &IID_IFontDisp, ppTInfo);
1380 ITypeLib_Release(tl);
1382 FIXME("Did not IDispatch typeinfo from typelib, hres %x\n",hres);
1387 /************************************************************************
1388 * OLEFontImpl_GetIDsOfNames (IDispatch)
1390 * See Windows documentation for more details on IDispatch methods.
1392 static HRESULT WINAPI OLEFontImpl_GetIDsOfNames(
1395 LPOLESTR* rgszNames,
1403 OLEFontImpl *this = impl_from_IDispatch(iface);
1405 TRACE("(%p,%s,%p,cNames=%d,lcid=%04x,%p)\n", this, debugstr_guid(riid),
1406 rgszNames, cNames, (int)lcid, rgDispId);
1410 return E_INVALIDARG;
1414 /* retrieve type information */
1415 hres = OLEFontImpl_GetTypeInfo(iface, 0, lcid, &pTInfo);
1419 ERR("GetTypeInfo failed.\n");
1423 /* convert names to DISPIDs */
1424 hres = DispGetIDsOfNames (pTInfo, rgszNames, cNames, rgDispId);
1425 ITypeInfo_Release(pTInfo);
1431 /************************************************************************
1432 * OLEFontImpl_Invoke (IDispatch)
1434 * See Windows documentation for more details on IDispatch methods.
1436 * Note: Do not call _put_Xxx methods, since setting things here
1437 * should not call notify functions as I found out debugging the generic
1440 static HRESULT WINAPI OLEFontImpl_Invoke(
1442 DISPID dispIdMember,
1446 DISPPARAMS* pDispParams,
1447 VARIANT* pVarResult,
1448 EXCEPINFO* pExepInfo,
1451 OLEFontImpl *this = impl_from_IDispatch(iface);
1454 TRACE("%p->(%d,%s,0x%x,0x%x,%p,%p,%p,%p)\n", this, dispIdMember,
1455 debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, pExepInfo,
1458 /* validate parameters */
1460 if (!IsEqualIID(riid, &IID_NULL))
1462 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid));
1463 return DISP_E_UNKNOWNINTERFACE;
1466 if (wFlags & DISPATCH_PROPERTYGET)
1470 ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
1471 return DISP_E_PARAMNOTOPTIONAL;
1474 else if (wFlags & DISPATCH_PROPERTYPUT)
1478 ERR("null pDispParams not allowed when DISPATCH_PROPERTYPUT specified\n");
1479 return DISP_E_PARAMNOTOPTIONAL;
1481 if (pDispParams->cArgs != 1)
1483 ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams->cArgs);
1484 return DISP_E_BADPARAMCOUNT;
1489 ERR("one of DISPATCH_PROPERTYGET or DISPATCH_PROPERTYPUT must be specified\n");
1490 return DISP_E_MEMBERNOTFOUND;
1493 switch (dispIdMember) {
1494 case DISPID_FONT_NAME:
1495 if (wFlags & DISPATCH_PROPERTYGET) {
1496 V_VT(pVarResult) = VT_BSTR;
1497 return IFont_get_Name((IFont *)this, &V_BSTR(pVarResult));
1501 VariantInit(&vararg);
1502 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BSTR);
1506 hr = IFont_put_Name((IFont *)this, V_BSTR(&vararg));
1508 VariantClear(&vararg);
1512 case DISPID_FONT_BOLD:
1513 if (wFlags & DISPATCH_PROPERTYGET) {
1515 hr = IFont_get_Bold((IFont *)this, &value);
1516 V_VT(pVarResult) = VT_BOOL;
1517 V_BOOL(pVarResult) = value ? VARIANT_TRUE : VARIANT_FALSE;
1522 VariantInit(&vararg);
1523 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BOOL);
1527 hr = IFont_put_Bold((IFont *)this, V_BOOL(&vararg));
1529 VariantClear(&vararg);
1533 case DISPID_FONT_ITALIC:
1534 if (wFlags & DISPATCH_PROPERTYGET) {
1536 hr = IFont_get_Italic((IFont *)this, &value);
1537 V_VT(pVarResult) = VT_BOOL;
1538 V_BOOL(pVarResult) = value ? VARIANT_TRUE : VARIANT_FALSE;
1543 VariantInit(&vararg);
1544 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BOOL);
1548 hr = IFont_put_Italic((IFont *)this, V_BOOL(&vararg));
1550 VariantClear(&vararg);
1554 case DISPID_FONT_UNDER:
1555 if (wFlags & DISPATCH_PROPERTYGET) {
1557 hr = IFont_get_Underline((IFont *)this, &value);
1558 V_VT(pVarResult) = VT_BOOL;
1559 V_BOOL(pVarResult) = value ? VARIANT_TRUE : VARIANT_FALSE;
1564 VariantInit(&vararg);
1565 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BOOL);
1569 hr = IFont_put_Underline((IFont *)this, V_BOOL(&vararg));
1571 VariantClear(&vararg);
1575 case DISPID_FONT_STRIKE:
1576 if (wFlags & DISPATCH_PROPERTYGET) {
1578 hr = IFont_get_Strikethrough((IFont *)this, &value);
1579 V_VT(pVarResult) = VT_BOOL;
1580 V_BOOL(pVarResult) = value ? VARIANT_TRUE : VARIANT_FALSE;
1585 VariantInit(&vararg);
1586 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BOOL);
1590 hr = IFont_put_Strikethrough((IFont *)this, V_BOOL(&vararg));
1592 VariantClear(&vararg);
1596 case DISPID_FONT_SIZE:
1597 if (wFlags & DISPATCH_PROPERTYGET) {
1598 V_VT(pVarResult) = VT_CY;
1599 return OLEFontImpl_get_Size((IFont *)this, &V_CY(pVarResult));
1603 VariantInit(&vararg);
1604 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_CY);
1608 hr = IFont_put_Size((IFont *)this, V_CY(&vararg));
1610 VariantClear(&vararg);
1614 case DISPID_FONT_WEIGHT:
1615 if (wFlags & DISPATCH_PROPERTYGET) {
1616 V_VT(pVarResult) = VT_I2;
1617 return OLEFontImpl_get_Weight((IFont *)this, &V_I2(pVarResult));
1621 VariantInit(&vararg);
1622 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_I2);
1626 hr = IFont_put_Weight((IFont *)this, V_I2(&vararg));
1628 VariantClear(&vararg);
1632 case DISPID_FONT_CHARSET:
1633 if (wFlags & DISPATCH_PROPERTYGET) {
1634 V_VT(pVarResult) = VT_I2;
1635 return OLEFontImpl_get_Charset((IFont *)this, &V_I2(pVarResult));
1639 VariantInit(&vararg);
1640 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_I2);
1644 hr = IFont_put_Charset((IFont *)this, V_I2(&vararg));
1646 VariantClear(&vararg);
1651 ERR("member not found for dispid 0x%x\n", dispIdMember);
1652 return DISP_E_MEMBERNOTFOUND;
1656 static const IDispatchVtbl OLEFontImpl_IDispatch_VTable =
1658 OLEFontImpl_IDispatch_QueryInterface,
1659 OLEFontImpl_IDispatch_AddRef,
1660 OLEFontImpl_IDispatch_Release,
1661 OLEFontImpl_GetTypeInfoCount,
1662 OLEFontImpl_GetTypeInfo,
1663 OLEFontImpl_GetIDsOfNames,
1667 /************************************************************************
1668 * OLEFontImpl_IPersistStream_QueryInterface (IUnknown)
1670 * See Windows documentation for more details on IUnknown methods.
1672 static HRESULT WINAPI OLEFontImpl_IPersistStream_QueryInterface(
1673 IPersistStream* iface,
1677 OLEFontImpl *this = impl_from_IPersistStream(iface);
1679 return IFont_QueryInterface((IFont *)this, riid, ppvoid);
1682 /************************************************************************
1683 * OLEFontImpl_IPersistStream_Release (IUnknown)
1685 * See Windows documentation for more details on IUnknown methods.
1687 static ULONG WINAPI OLEFontImpl_IPersistStream_Release(
1688 IPersistStream* iface)
1690 OLEFontImpl *this = impl_from_IPersistStream(iface);
1692 return IFont_Release((IFont *)this);
1695 /************************************************************************
1696 * OLEFontImpl_IPersistStream_AddRef (IUnknown)
1698 * See Windows documentation for more details on IUnknown methods.
1700 static ULONG WINAPI OLEFontImpl_IPersistStream_AddRef(
1701 IPersistStream* iface)
1703 OLEFontImpl *this = impl_from_IPersistStream(iface);
1705 return IFont_AddRef((IFont *)this);
1708 /************************************************************************
1709 * OLEFontImpl_GetClassID (IPersistStream)
1711 * See Windows documentation for more details on IPersistStream methods.
1713 static HRESULT WINAPI OLEFontImpl_GetClassID(
1714 IPersistStream* iface,
1717 TRACE("(%p,%p)\n",iface,pClassID);
1721 *pClassID = CLSID_StdFont;
1726 /************************************************************************
1727 * OLEFontImpl_IsDirty (IPersistStream)
1729 * See Windows documentation for more details on IPersistStream methods.
1731 static HRESULT WINAPI OLEFontImpl_IsDirty(
1732 IPersistStream* iface)
1734 TRACE("(%p)\n",iface);
1738 /************************************************************************
1739 * OLEFontImpl_Load (IPersistStream)
1741 * See Windows documentation for more details on IPersistStream methods.
1743 * This is the format of the standard font serialization as far as I
1746 * Offset Type Value Comment
1747 * 0x0000 Byte Unknown Probably a version number, contains 0x01
1748 * 0x0001 Short Charset Charset value from the FONTDESC structure
1749 * 0x0003 Byte Attributes Flags defined as follows:
1751 * 00000100 - Underline
1752 * 00001000 - Strikethrough
1753 * 0x0004 Short Weight Weight value from FONTDESC structure
1754 * 0x0006 DWORD size "Low" portion of the cySize member of the FONTDESC
1756 * 0x000A Byte name length Length of the font name string (no null character)
1757 * 0x000B String name Name of the font (ASCII, no nul character)
1759 static HRESULT WINAPI OLEFontImpl_Load(
1760 IPersistStream* iface,
1761 IStream* pLoadStream)
1763 char readBuffer[0x100];
1770 OLEFontImpl *this = impl_from_IPersistStream(iface);
1773 * Read the version byte
1775 IStream_Read(pLoadStream, &bVersion, 1, &cbRead);
1784 IStream_Read(pLoadStream, &this->description.sCharset, 2, &cbRead);
1792 IStream_Read(pLoadStream, &bAttributes, 1, &cbRead);
1797 this->description.fItalic = (bAttributes & FONTPERSIST_ITALIC) != 0;
1798 this->description.fStrikethrough = (bAttributes & FONTPERSIST_STRIKETHROUGH) != 0;
1799 this->description.fUnderline = (bAttributes & FONTPERSIST_UNDERLINE) != 0;
1804 IStream_Read(pLoadStream, &this->description.sWeight, 2, &cbRead);
1812 IStream_Read(pLoadStream, &this->description.cySize.s.Lo, 4, &cbRead);
1817 this->description.cySize.s.Hi = 0;
1822 IStream_Read(pLoadStream, &bStringSize, 1, &cbRead);
1827 IStream_Read(pLoadStream, readBuffer, bStringSize, &cbRead);
1829 if (cbRead!=bStringSize)
1832 HeapFree(GetProcessHeap(), 0, this->description.lpstrName);
1834 len = MultiByteToWideChar( CP_ACP, 0, readBuffer, bStringSize, NULL, 0 );
1835 this->description.lpstrName = HeapAlloc( GetProcessHeap(), 0, (len+1) * sizeof(WCHAR) );
1836 MultiByteToWideChar( CP_ACP, 0, readBuffer, bStringSize, this->description.lpstrName, len );
1837 this->description.lpstrName[len] = 0;
1839 /* Ensure use of this font causes a new one to be created @@@@ */
1840 dec_int_ref(this->gdiFont);
1846 /************************************************************************
1847 * OLEFontImpl_Save (IPersistStream)
1849 * See Windows documentation for more details on IPersistStream methods.
1851 static HRESULT WINAPI OLEFontImpl_Save(
1852 IPersistStream* iface,
1853 IStream* pOutStream,
1856 char* writeBuffer = NULL;
1858 BYTE bVersion = 0x01;
1862 OLEFontImpl *this = impl_from_IPersistStream(iface);
1865 * Read the version byte
1867 IStream_Write(pOutStream, &bVersion, 1, &cbWritten);
1875 IStream_Write(pOutStream, &this->description.sCharset, 2, &cbWritten);
1885 if (this->description.fItalic)
1886 bAttributes |= FONTPERSIST_ITALIC;
1888 if (this->description.fStrikethrough)
1889 bAttributes |= FONTPERSIST_STRIKETHROUGH;
1891 if (this->description.fUnderline)
1892 bAttributes |= FONTPERSIST_UNDERLINE;
1894 IStream_Write(pOutStream, &bAttributes, 1, &cbWritten);
1902 IStream_Write(pOutStream, &this->description.sWeight, 2, &cbWritten);
1910 IStream_Write(pOutStream, &this->description.cySize.s.Lo, 4, &cbWritten);
1918 if (this->description.lpstrName!=0)
1919 bStringSize = WideCharToMultiByte( CP_ACP, 0, this->description.lpstrName,
1920 strlenW(this->description.lpstrName), NULL, 0, NULL, NULL );
1924 IStream_Write(pOutStream, &bStringSize, 1, &cbWritten);
1931 if (!(writeBuffer = HeapAlloc( GetProcessHeap(), 0, bStringSize ))) return E_OUTOFMEMORY;
1932 WideCharToMultiByte( CP_ACP, 0, this->description.lpstrName,
1933 strlenW(this->description.lpstrName),
1934 writeBuffer, bStringSize, NULL, NULL );
1936 IStream_Write(pOutStream, writeBuffer, bStringSize, &cbWritten);
1937 HeapFree(GetProcessHeap(), 0, writeBuffer);
1939 if (cbWritten!=bStringSize)
1946 /************************************************************************
1947 * OLEFontImpl_GetSizeMax (IPersistStream)
1949 * See Windows documentation for more details on IPersistStream methods.
1951 static HRESULT WINAPI OLEFontImpl_GetSizeMax(
1952 IPersistStream* iface,
1953 ULARGE_INTEGER* pcbSize)
1955 OLEFontImpl *this = impl_from_IPersistStream(iface);
1960 pcbSize->u.HighPart = 0;
1961 pcbSize->u.LowPart = 0;
1963 pcbSize->u.LowPart += sizeof(BYTE); /* Version */
1964 pcbSize->u.LowPart += sizeof(WORD); /* Lang code */
1965 pcbSize->u.LowPart += sizeof(BYTE); /* Flags */
1966 pcbSize->u.LowPart += sizeof(WORD); /* Weight */
1967 pcbSize->u.LowPart += sizeof(DWORD); /* Size */
1968 pcbSize->u.LowPart += sizeof(BYTE); /* StrLength */
1970 if (this->description.lpstrName!=0)
1971 pcbSize->u.LowPart += WideCharToMultiByte( CP_ACP, 0, this->description.lpstrName,
1972 strlenW(this->description.lpstrName),
1973 NULL, 0, NULL, NULL );
1978 static const IPersistStreamVtbl OLEFontImpl_IPersistStream_VTable =
1980 OLEFontImpl_IPersistStream_QueryInterface,
1981 OLEFontImpl_IPersistStream_AddRef,
1982 OLEFontImpl_IPersistStream_Release,
1983 OLEFontImpl_GetClassID,
1984 OLEFontImpl_IsDirty,
1987 OLEFontImpl_GetSizeMax
1990 /************************************************************************
1991 * OLEFontImpl_IConnectionPointContainer_QueryInterface (IUnknown)
1993 * See Windows documentation for more details on IUnknown methods.
1995 static HRESULT WINAPI OLEFontImpl_IConnectionPointContainer_QueryInterface(
1996 IConnectionPointContainer* iface,
2000 OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
2002 return IFont_QueryInterface((IFont*)this, riid, ppvoid);
2005 /************************************************************************
2006 * OLEFontImpl_IConnectionPointContainer_Release (IUnknown)
2008 * See Windows documentation for more details on IUnknown methods.
2010 static ULONG WINAPI OLEFontImpl_IConnectionPointContainer_Release(
2011 IConnectionPointContainer* iface)
2013 OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
2015 return IFont_Release((IFont*)this);
2018 /************************************************************************
2019 * OLEFontImpl_IConnectionPointContainer_AddRef (IUnknown)
2021 * See Windows documentation for more details on IUnknown methods.
2023 static ULONG WINAPI OLEFontImpl_IConnectionPointContainer_AddRef(
2024 IConnectionPointContainer* iface)
2026 OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
2028 return IFont_AddRef((IFont*)this);
2031 /************************************************************************
2032 * OLEFontImpl_EnumConnectionPoints (IConnectionPointContainer)
2034 * See Windows documentation for more details on IConnectionPointContainer
2037 static HRESULT WINAPI OLEFontImpl_EnumConnectionPoints(
2038 IConnectionPointContainer* iface,
2039 IEnumConnectionPoints **ppEnum)
2041 OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
2043 FIXME("(%p)->(%p): stub\n", this, ppEnum);
2047 /************************************************************************
2048 * OLEFontImpl_FindConnectionPoint (IConnectionPointContainer)
2050 * See Windows documentation for more details on IConnectionPointContainer
2053 static HRESULT WINAPI OLEFontImpl_FindConnectionPoint(
2054 IConnectionPointContainer* iface,
2056 IConnectionPoint **ppCp)
2058 OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
2059 TRACE("(%p)->(%s, %p)\n", this, debugstr_guid(riid), ppCp);
2061 if(IsEqualIID(riid, &IID_IPropertyNotifySink)) {
2062 return IConnectionPoint_QueryInterface(this->pPropertyNotifyCP,
2063 &IID_IConnectionPoint,
2065 } else if(IsEqualIID(riid, &IID_IFontEventsDisp)) {
2066 return IConnectionPoint_QueryInterface(this->pFontEventsCP,
2067 &IID_IConnectionPoint,
2070 FIXME("no connection point for %s\n", debugstr_guid(riid));
2071 return CONNECT_E_NOCONNECTION;
2075 static const IConnectionPointContainerVtbl
2076 OLEFontImpl_IConnectionPointContainer_VTable =
2078 OLEFontImpl_IConnectionPointContainer_QueryInterface,
2079 OLEFontImpl_IConnectionPointContainer_AddRef,
2080 OLEFontImpl_IConnectionPointContainer_Release,
2081 OLEFontImpl_EnumConnectionPoints,
2082 OLEFontImpl_FindConnectionPoint
2085 /************************************************************************
2086 * OLEFontImpl implementation of IPersistPropertyBag.
2088 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_QueryInterface(
2089 IPersistPropertyBag *iface, REFIID riid, LPVOID *ppvObj
2091 OLEFontImpl *this = impl_from_IPersistPropertyBag(iface);
2092 return IFont_QueryInterface((IFont *)this,riid,ppvObj);
2095 static ULONG WINAPI OLEFontImpl_IPersistPropertyBag_AddRef(
2096 IPersistPropertyBag *iface
2098 OLEFontImpl *this = impl_from_IPersistPropertyBag(iface);
2099 return IFont_AddRef((IFont *)this);
2102 static ULONG WINAPI OLEFontImpl_IPersistPropertyBag_Release(
2103 IPersistPropertyBag *iface
2105 OLEFontImpl *this = impl_from_IPersistPropertyBag(iface);
2106 return IFont_Release((IFont *)this);
2109 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_GetClassID(
2110 IPersistPropertyBag *iface, CLSID *classid
2112 FIXME("(%p,%p), stub!\n", iface, classid);
2116 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_InitNew(
2117 IPersistPropertyBag *iface
2119 FIXME("(%p), stub!\n", iface);
2123 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_Load(
2124 IPersistPropertyBag *iface, IPropertyBag* pPropBag, IErrorLog* pErrorLog
2126 /* (from Visual Basic 6 property bag)
2127 Name = "MS Sans Serif"
2131 Underline = 0 'False
2133 Strikethrough = 0 'False
2135 static const WCHAR sAttrName[] = {'N','a','m','e',0};
2136 static const WCHAR sAttrSize[] = {'S','i','z','e',0};
2137 static const WCHAR sAttrCharset[] = {'C','h','a','r','s','e','t',0};
2138 static const WCHAR sAttrWeight[] = {'W','e','i','g','h','t',0};
2139 static const WCHAR sAttrUnderline[] = {'U','n','d','e','r','l','i','n','e',0};
2140 static const WCHAR sAttrItalic[] = {'I','t','a','l','i','c',0};
2141 static const WCHAR sAttrStrikethrough[] = {'S','t','r','i','k','e','t','h','r','o','u','g','h',0};
2144 HRESULT iRes = S_OK;
2145 OLEFontImpl *this = impl_from_IPersistPropertyBag(iface);
2147 VariantInit(&rawAttr);
2148 VariantInit(&valueAttr);
2151 iRes = IPropertyBag_Read(pPropBag, sAttrName, &rawAttr, pErrorLog);
2154 iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_BSTR);
2156 iRes = IFont_put_Name((IFont *)this, V_BSTR(&valueAttr));
2158 else if (iRes == E_INVALIDARG)
2160 VariantClear(&rawAttr);
2161 VariantClear(&valueAttr);
2165 iRes = IPropertyBag_Read(pPropBag, sAttrSize, &rawAttr, pErrorLog);
2168 iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_CY);
2170 iRes = IFont_put_Size((IFont *)this, V_CY(&valueAttr));
2172 else if (iRes == E_INVALIDARG)
2174 VariantClear(&rawAttr);
2175 VariantClear(&valueAttr);
2179 iRes = IPropertyBag_Read(pPropBag, sAttrCharset, &rawAttr, pErrorLog);
2182 iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_I2);
2184 iRes = IFont_put_Charset((IFont *)this, V_I2(&valueAttr));
2186 else if (iRes == E_INVALIDARG)
2188 VariantClear(&rawAttr);
2189 VariantClear(&valueAttr);
2193 iRes = IPropertyBag_Read(pPropBag, sAttrWeight, &rawAttr, pErrorLog);
2196 iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_I2);
2198 iRes = IFont_put_Weight((IFont *)this, V_I2(&valueAttr));
2200 else if (iRes == E_INVALIDARG)
2202 VariantClear(&rawAttr);
2203 VariantClear(&valueAttr);
2208 iRes = IPropertyBag_Read(pPropBag, sAttrUnderline, &rawAttr, pErrorLog);
2211 iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_BOOL);
2213 iRes = IFont_put_Underline((IFont *)this, V_BOOL(&valueAttr));
2215 else if (iRes == E_INVALIDARG)
2217 VariantClear(&rawAttr);
2218 VariantClear(&valueAttr);
2222 iRes = IPropertyBag_Read(pPropBag, sAttrItalic, &rawAttr, pErrorLog);
2225 iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_BOOL);
2227 iRes = IFont_put_Italic((IFont *)this, V_BOOL(&valueAttr));
2229 else if (iRes == E_INVALIDARG)
2231 VariantClear(&rawAttr);
2232 VariantClear(&valueAttr);
2236 iRes = IPropertyBag_Read(pPropBag, sAttrStrikethrough, &rawAttr, pErrorLog);
2239 iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_BOOL);
2241 IFont_put_Strikethrough((IFont *)this, V_BOOL(&valueAttr));
2243 else if (iRes == E_INVALIDARG)
2245 VariantClear(&rawAttr);
2246 VariantClear(&valueAttr);
2250 WARN("-- 0x%08x\n", iRes);
2254 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_Save(
2255 IPersistPropertyBag *iface, IPropertyBag* pPropBag, BOOL fClearDirty,
2256 BOOL fSaveAllProperties
2258 FIXME("(%p,%p,%d,%d), stub!\n", iface, pPropBag, fClearDirty, fSaveAllProperties);
2262 static const IPersistPropertyBagVtbl OLEFontImpl_IPersistPropertyBag_VTable =
2264 OLEFontImpl_IPersistPropertyBag_QueryInterface,
2265 OLEFontImpl_IPersistPropertyBag_AddRef,
2266 OLEFontImpl_IPersistPropertyBag_Release,
2268 OLEFontImpl_IPersistPropertyBag_GetClassID,
2269 OLEFontImpl_IPersistPropertyBag_InitNew,
2270 OLEFontImpl_IPersistPropertyBag_Load,
2271 OLEFontImpl_IPersistPropertyBag_Save
2274 /************************************************************************
2275 * OLEFontImpl implementation of IPersistStreamInit.
2277 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_QueryInterface(
2278 IPersistStreamInit *iface, REFIID riid, LPVOID *ppvObj
2280 OLEFontImpl *this = impl_from_IPersistStreamInit(iface);
2281 return IFont_QueryInterface((IFont *)this,riid,ppvObj);
2284 static ULONG WINAPI OLEFontImpl_IPersistStreamInit_AddRef(
2285 IPersistStreamInit *iface
2287 OLEFontImpl *this = impl_from_IPersistStreamInit(iface);
2288 return IFont_AddRef((IFont *)this);
2291 static ULONG WINAPI OLEFontImpl_IPersistStreamInit_Release(
2292 IPersistStreamInit *iface
2294 OLEFontImpl *this = impl_from_IPersistStreamInit(iface);
2295 return IFont_Release((IFont *)this);
2298 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_GetClassID(
2299 IPersistStreamInit *iface, CLSID *classid
2301 FIXME("(%p,%p), stub!\n", iface, classid);
2305 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_IsDirty(
2306 IPersistStreamInit *iface
2308 FIXME("(%p), stub!\n", iface);
2312 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_Load(
2313 IPersistStreamInit *iface, LPSTREAM pStm
2315 FIXME("(%p,%p), stub!\n", iface, pStm);
2319 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_Save(
2320 IPersistStreamInit *iface, LPSTREAM pStm, BOOL fClearDirty
2322 FIXME("(%p,%p,%d), stub!\n", iface, pStm, fClearDirty);
2326 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_GetSizeMax(
2327 IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize
2329 FIXME("(%p,%p), stub!\n", iface, pcbSize);
2333 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_InitNew(
2334 IPersistStreamInit *iface
2336 FIXME("(%p), stub!\n", iface);
2340 static const IPersistStreamInitVtbl OLEFontImpl_IPersistStreamInit_VTable =
2342 OLEFontImpl_IPersistStreamInit_QueryInterface,
2343 OLEFontImpl_IPersistStreamInit_AddRef,
2344 OLEFontImpl_IPersistStreamInit_Release,
2346 OLEFontImpl_IPersistStreamInit_GetClassID,
2347 OLEFontImpl_IPersistStreamInit_IsDirty,
2348 OLEFontImpl_IPersistStreamInit_Load,
2349 OLEFontImpl_IPersistStreamInit_Save,
2350 OLEFontImpl_IPersistStreamInit_GetSizeMax,
2351 OLEFontImpl_IPersistStreamInit_InitNew
2354 /************************************************************************
2355 * OLEFontImpl_Construct
2357 * This method will construct a new instance of the OLEFontImpl
2360 * The caller of this method must release the object when it's
2363 static OLEFontImpl* OLEFontImpl_Construct(const FONTDESC *fontDesc)
2365 OLEFontImpl* newObject = 0;
2368 * Allocate space for the object.
2370 newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(OLEFontImpl));
2376 * Initialize the virtual function table.
2378 newObject->lpVtbl = &OLEFontImpl_VTable;
2379 newObject->lpvtblIDispatch = &OLEFontImpl_IDispatch_VTable;
2380 newObject->lpvtblIPersistStream = &OLEFontImpl_IPersistStream_VTable;
2381 newObject->lpvtblIConnectionPointContainer = &OLEFontImpl_IConnectionPointContainer_VTable;
2382 newObject->lpvtblIPersistPropertyBag = &OLEFontImpl_IPersistPropertyBag_VTable;
2383 newObject->lpvtblIPersistStreamInit = &OLEFontImpl_IPersistStreamInit_VTable;
2386 * Start with one reference count. The caller of this function
2387 * must release the interface pointer when it is done.
2392 * Copy the description of the font in the object.
2394 assert(fontDesc->cbSizeofstruct >= sizeof(FONTDESC));
2396 newObject->description.cbSizeofstruct = sizeof(FONTDESC);
2397 newObject->description.lpstrName = HeapAlloc(GetProcessHeap(),
2399 (lstrlenW(fontDesc->lpstrName)+1) * sizeof(WCHAR));
2400 strcpyW(newObject->description.lpstrName, fontDesc->lpstrName);
2401 newObject->description.cySize = fontDesc->cySize;
2402 newObject->description.sWeight = fontDesc->sWeight;
2403 newObject->description.sCharset = fontDesc->sCharset;
2404 newObject->description.fItalic = fontDesc->fItalic;
2405 newObject->description.fUnderline = fontDesc->fUnderline;
2406 newObject->description.fStrikethrough = fontDesc->fStrikethrough;
2409 * Initializing all the other members.
2411 newObject->gdiFont = 0;
2412 newObject->dirty = TRUE;
2413 newObject->cyLogical = 72L;
2414 newObject->cyHimetric = 2540L;
2415 newObject->pPropertyNotifyCP = NULL;
2416 newObject->pFontEventsCP = NULL;
2418 CreateConnectionPoint((IUnknown*)newObject, &IID_IPropertyNotifySink, &newObject->pPropertyNotifyCP);
2419 CreateConnectionPoint((IUnknown*)newObject, &IID_IFontEventsDisp, &newObject->pFontEventsCP);
2421 if (!newObject->pPropertyNotifyCP || !newObject->pFontEventsCP)
2423 OLEFontImpl_Destroy(newObject);
2427 InterlockedIncrement(&ifont_cnt);
2429 TRACE("returning %p\n", newObject);
2433 /************************************************************************
2434 * OLEFontImpl_Destroy
2436 * This method is called by the Release method when the reference
2437 * count goes down to 0. It will free all resources used by
2440 static void OLEFontImpl_Destroy(OLEFontImpl* fontDesc)
2442 TRACE("(%p)\n", fontDesc);
2444 HeapFree(GetProcessHeap(), 0, fontDesc->description.lpstrName);
2446 if (fontDesc->pPropertyNotifyCP)
2447 IConnectionPoint_Release(fontDesc->pPropertyNotifyCP);
2448 if (fontDesc->pFontEventsCP)
2449 IConnectionPoint_Release(fontDesc->pFontEventsCP);
2451 HeapFree(GetProcessHeap(), 0, fontDesc);
2454 /*******************************************************************************
2455 * StdFont ClassFactory
2459 /* IUnknown fields */
2460 const IClassFactoryVtbl *lpVtbl;
2462 } IClassFactoryImpl;
2464 static HRESULT WINAPI
2465 SFCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
2466 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2468 FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
2469 return E_NOINTERFACE;
2473 SFCF_AddRef(LPCLASSFACTORY iface) {
2474 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2475 return InterlockedIncrement(&This->ref);
2478 static ULONG WINAPI SFCF_Release(LPCLASSFACTORY iface) {
2479 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2480 /* static class, won't be freed */
2481 return InterlockedDecrement(&This->ref);
2484 static HRESULT WINAPI SFCF_CreateInstance(
2485 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
2487 return OleCreateFontIndirect(NULL,riid,ppobj);
2491 static HRESULT WINAPI SFCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
2492 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2493 FIXME("(%p)->(%d),stub!\n",This,dolock);
2497 static const IClassFactoryVtbl SFCF_Vtbl = {
2498 SFCF_QueryInterface,
2501 SFCF_CreateInstance,
2504 static IClassFactoryImpl STDFONT_CF = {&SFCF_Vtbl, 1 };
2506 void _get_STDFONT_CF(LPVOID *ppv) { *ppv = &STDFONT_CF; }