2278 lines
63 KiB
C
2278 lines
63 KiB
C
/*
|
|
* OLE Font encapsulation implementation
|
|
*
|
|
* This file contains an implementation of the IFont
|
|
* interface and the OleCreateFontIndirect API call.
|
|
*
|
|
* Copyright 1999 Francis Beaudet
|
|
* Copyright 2006 (Google) Benjamin Arai
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
#include <assert.h>
|
|
#include <stdarg.h>
|
|
#include <string.h>
|
|
|
|
#define COBJMACROS
|
|
#define NONAMELESSUNION
|
|
#define NONAMELESSSTRUCT
|
|
|
|
#include "winerror.h"
|
|
#include "windef.h"
|
|
#include "winbase.h"
|
|
#include "wingdi.h"
|
|
#include "winuser.h"
|
|
#include "wine/list.h"
|
|
#include "wine/unicode.h"
|
|
#include "objbase.h"
|
|
#include "oleauto.h" /* for SysAllocString(....) */
|
|
#include "ole2.h"
|
|
#include "olectl.h"
|
|
#include "wine/debug.h"
|
|
#include "connpt.h" /* for CreateConnectionPoint */
|
|
#include "oaidl.h"
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(ole);
|
|
|
|
/***********************************************************************
|
|
* Declaration of constants used when serializing the font object.
|
|
*/
|
|
#define FONTPERSIST_ITALIC 0x02
|
|
#define FONTPERSIST_UNDERLINE 0x04
|
|
#define FONTPERSIST_STRIKETHROUGH 0x08
|
|
|
|
static HDC olefont_hdc;
|
|
|
|
/***********************************************************************
|
|
* List of the HFONTs it has given out, with each one having a separate
|
|
* ref count.
|
|
*/
|
|
typedef struct _HFONTItem
|
|
{
|
|
struct list entry;
|
|
|
|
/* Reference count of any IFont objects that own this hfont */
|
|
LONG int_refs;
|
|
|
|
/* Total reference count of any refs held by the application obtained by AddRefHfont plus any internal refs */
|
|
LONG total_refs;
|
|
|
|
/* The font associated with this object. */
|
|
HFONT gdiFont;
|
|
|
|
} HFONTItem, *PHFONTItem;
|
|
|
|
static struct list OLEFontImpl_hFontList = LIST_INIT(OLEFontImpl_hFontList);
|
|
|
|
/* Counts how many fonts contain at least one lock */
|
|
static LONG ifont_cnt = 0;
|
|
|
|
/***********************************************************************
|
|
* Critical section for OLEFontImpl_hFontList
|
|
*/
|
|
static CRITICAL_SECTION OLEFontImpl_csHFONTLIST;
|
|
static CRITICAL_SECTION_DEBUG OLEFontImpl_csHFONTLIST_debug =
|
|
{
|
|
0, 0, &OLEFontImpl_csHFONTLIST,
|
|
{ &OLEFontImpl_csHFONTLIST_debug.ProcessLocksList,
|
|
&OLEFontImpl_csHFONTLIST_debug.ProcessLocksList },
|
|
0, 0, { (DWORD_PTR)(__FILE__ ": OLEFontImpl_csHFONTLIST") }
|
|
};
|
|
static CRITICAL_SECTION OLEFontImpl_csHFONTLIST = { &OLEFontImpl_csHFONTLIST_debug, -1, 0, 0, 0, 0 };
|
|
|
|
static HDC get_dc(void)
|
|
{
|
|
HDC hdc;
|
|
EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
|
|
if(!olefont_hdc)
|
|
olefont_hdc = CreateCompatibleDC(NULL);
|
|
hdc = olefont_hdc;
|
|
LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
|
|
return hdc;
|
|
}
|
|
|
|
static void delete_dc(void)
|
|
{
|
|
EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
|
|
if(olefont_hdc)
|
|
{
|
|
DeleteDC(olefont_hdc);
|
|
olefont_hdc = NULL;
|
|
}
|
|
LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
|
|
}
|
|
|
|
static void HFONTItem_Delete(PHFONTItem item)
|
|
{
|
|
DeleteObject(item->gdiFont);
|
|
list_remove(&item->entry);
|
|
HeapFree(GetProcessHeap(), 0, item);
|
|
}
|
|
|
|
/* Find hfont item entry in the list. Should be called while holding the crit sect */
|
|
static HFONTItem *find_hfontitem(HFONT hfont)
|
|
{
|
|
HFONTItem *item;
|
|
|
|
LIST_FOR_EACH_ENTRY(item, &OLEFontImpl_hFontList, HFONTItem, entry)
|
|
{
|
|
if (item->gdiFont == hfont)
|
|
return item;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/* Add an item to the list with one internal reference */
|
|
static HRESULT add_hfontitem(HFONT hfont)
|
|
{
|
|
HFONTItem *new_item = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_item));
|
|
|
|
if(!new_item) return E_OUTOFMEMORY;
|
|
|
|
new_item->int_refs = 1;
|
|
new_item->total_refs = 1;
|
|
new_item->gdiFont = hfont;
|
|
EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
|
|
list_add_tail(&OLEFontImpl_hFontList,&new_item->entry);
|
|
LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT inc_int_ref(HFONT hfont)
|
|
{
|
|
HFONTItem *item;
|
|
HRESULT hr = S_FALSE;
|
|
|
|
EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
|
|
item = find_hfontitem(hfont);
|
|
|
|
if(item)
|
|
{
|
|
item->int_refs++;
|
|
item->total_refs++;
|
|
hr = S_OK;
|
|
}
|
|
LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
|
|
|
|
return hr;
|
|
}
|
|
|
|
/* decrements the internal ref of a hfont item. If both refs are zero it'll
|
|
remove the item from the list and delete the hfont */
|
|
static HRESULT dec_int_ref(HFONT hfont)
|
|
{
|
|
HFONTItem *item;
|
|
HRESULT hr = S_FALSE;
|
|
|
|
EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
|
|
item = find_hfontitem(hfont);
|
|
|
|
if(item)
|
|
{
|
|
item->int_refs--;
|
|
item->total_refs--;
|
|
if(item->int_refs == 0 && item->total_refs == 0)
|
|
HFONTItem_Delete(item);
|
|
hr = S_OK;
|
|
}
|
|
LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
|
|
|
|
return hr;
|
|
}
|
|
|
|
static HRESULT inc_ext_ref(HFONT hfont)
|
|
{
|
|
HFONTItem *item;
|
|
HRESULT hr = S_FALSE;
|
|
|
|
EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
|
|
|
|
item = find_hfontitem(hfont);
|
|
if(item)
|
|
{
|
|
item->total_refs++;
|
|
hr = S_OK;
|
|
}
|
|
LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
|
|
|
|
return hr;
|
|
}
|
|
|
|
static HRESULT dec_ext_ref(HFONT hfont)
|
|
{
|
|
HFONTItem *item;
|
|
HRESULT hr = S_FALSE;
|
|
|
|
EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
|
|
|
|
item = find_hfontitem(hfont);
|
|
if(item)
|
|
{
|
|
if(--item->total_refs >= 0) hr = S_OK;
|
|
}
|
|
LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
|
|
|
|
return hr;
|
|
}
|
|
|
|
static WCHAR *strdupW(const WCHAR* str)
|
|
{
|
|
WCHAR *ret;
|
|
DWORD size = (strlenW(str) + 1) * sizeof(WCHAR);
|
|
|
|
ret = HeapAlloc(GetProcessHeap(), 0, size);
|
|
if(ret)
|
|
memcpy(ret, str, size);
|
|
return ret;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* Declaration of the implementation class for the IFont interface
|
|
*/
|
|
typedef struct OLEFontImpl OLEFontImpl;
|
|
|
|
struct OLEFontImpl
|
|
{
|
|
/*
|
|
* This class supports many interfaces. IUnknown, IFont,
|
|
* IDispatch, IDispFont IPersistStream and IConnectionPointContainer.
|
|
* The first two are supported by the first vtable, the next two are
|
|
* supported by the second table and the last two have their own.
|
|
*/
|
|
IFont IFont_iface;
|
|
IDispatch IDispatch_iface;
|
|
IPersistStream IPersistStream_iface;
|
|
IConnectionPointContainer IConnectionPointContainer_iface;
|
|
IPersistPropertyBag IPersistPropertyBag_iface;
|
|
IPersistStreamInit IPersistStreamInit_iface;
|
|
/*
|
|
* Reference count for that instance of the class.
|
|
*/
|
|
LONG ref;
|
|
|
|
/*
|
|
* This structure contains the description of the class.
|
|
*/
|
|
FONTDESC description;
|
|
|
|
/*
|
|
* Contain the font associated with this object.
|
|
*/
|
|
HFONT gdiFont;
|
|
BOOL dirty;
|
|
/*
|
|
* Size ratio
|
|
*/
|
|
LONG cyLogical;
|
|
LONG cyHimetric;
|
|
|
|
/*
|
|
* Stash realized height (pixels) from TEXTMETRIC - used in get_Size()
|
|
*/
|
|
LONG nRealHeight;
|
|
|
|
IConnectionPoint *pPropertyNotifyCP;
|
|
IConnectionPoint *pFontEventsCP;
|
|
};
|
|
|
|
static inline OLEFontImpl *impl_from_IFont(IFont *iface)
|
|
{
|
|
return CONTAINING_RECORD(iface, OLEFontImpl, IFont_iface);
|
|
}
|
|
|
|
static inline OLEFontImpl *impl_from_IDispatch( IDispatch *iface )
|
|
{
|
|
return CONTAINING_RECORD(iface, OLEFontImpl, IDispatch_iface);
|
|
}
|
|
|
|
static inline OLEFontImpl *impl_from_IPersistStream( IPersistStream *iface )
|
|
{
|
|
return CONTAINING_RECORD(iface, OLEFontImpl, IPersistStream_iface);
|
|
}
|
|
|
|
static inline OLEFontImpl *impl_from_IConnectionPointContainer( IConnectionPointContainer *iface )
|
|
{
|
|
return CONTAINING_RECORD(iface, OLEFontImpl, IConnectionPointContainer_iface);
|
|
}
|
|
|
|
static inline OLEFontImpl *impl_from_IPersistPropertyBag( IPersistPropertyBag *iface )
|
|
{
|
|
return CONTAINING_RECORD(iface, OLEFontImpl, IPersistPropertyBag_iface);
|
|
}
|
|
|
|
static inline OLEFontImpl *impl_from_IPersistStreamInit( IPersistStreamInit *iface )
|
|
{
|
|
return CONTAINING_RECORD(iface, OLEFontImpl, IPersistStreamInit_iface);
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* Prototypes for the implementation functions for the IFont
|
|
* interface
|
|
*/
|
|
static OLEFontImpl* OLEFontImpl_Construct(const FONTDESC *fontDesc);
|
|
static void OLEFontImpl_Destroy(OLEFontImpl* fontDesc);
|
|
static ULONG WINAPI OLEFontImpl_AddRef(IFont* iface);
|
|
|
|
/******************************************************************************
|
|
* OleCreateFontIndirect [OLEAUT32.420]
|
|
*/
|
|
HRESULT WINAPI OleCreateFontIndirect(
|
|
LPFONTDESC lpFontDesc,
|
|
REFIID riid,
|
|
LPVOID* ppvObj)
|
|
{
|
|
OLEFontImpl* newFont;
|
|
HRESULT hr;
|
|
FONTDESC fd;
|
|
|
|
TRACE("(%p, %s, %p)\n", lpFontDesc, debugstr_guid(riid), ppvObj);
|
|
|
|
if (!ppvObj) return E_POINTER;
|
|
|
|
*ppvObj = 0;
|
|
|
|
if (!lpFontDesc) {
|
|
static WCHAR fname[] = { 'S','y','s','t','e','m',0 };
|
|
|
|
fd.cbSizeofstruct = sizeof(fd);
|
|
fd.lpstrName = fname;
|
|
fd.cySize.s.Lo = 80000;
|
|
fd.cySize.s.Hi = 0;
|
|
fd.sWeight = 0;
|
|
fd.sCharset = 0;
|
|
fd.fItalic = FALSE;
|
|
fd.fUnderline = FALSE;
|
|
fd.fStrikethrough = FALSE;
|
|
lpFontDesc = &fd;
|
|
}
|
|
|
|
newFont = OLEFontImpl_Construct(lpFontDesc);
|
|
if (!newFont) return E_OUTOFMEMORY;
|
|
|
|
hr = IFont_QueryInterface(&newFont->IFont_iface, riid, ppvObj);
|
|
IFont_Release(&newFont->IFont_iface);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* Implementation of the OLEFontImpl class.
|
|
*/
|
|
|
|
/***********************************************************************
|
|
* OLEFont_SendNotify (internal)
|
|
*
|
|
* Sends notification messages of changed properties to any interested
|
|
* connections.
|
|
*/
|
|
static void OLEFont_SendNotify(OLEFontImpl* this, DISPID dispID)
|
|
{
|
|
static const WCHAR wszName[] = {'N','a','m','e',0};
|
|
static const WCHAR wszSize[] = {'S','i','z','e',0};
|
|
static const WCHAR wszBold[] = {'B','o','l','d',0};
|
|
static const WCHAR wszItalic[] = {'I','t','a','l','i','c',0};
|
|
static const WCHAR wszUnder[] = {'U','n','d','e','r','l','i','n','e',0};
|
|
static const WCHAR wszStrike[] = {'S','t','r','i','k','e','t','h','r','o','u','g','h',0};
|
|
static const WCHAR wszWeight[] = {'W','e','i','g','h','t',0};
|
|
static const WCHAR wszCharset[] = {'C','h','a','r','s','s','e','t',0};
|
|
static const LPCWSTR dispid_mapping[] =
|
|
{
|
|
wszName,
|
|
NULL,
|
|
wszSize,
|
|
wszBold,
|
|
wszItalic,
|
|
wszUnder,
|
|
wszStrike,
|
|
wszWeight,
|
|
wszCharset
|
|
};
|
|
|
|
IEnumConnections *pEnum;
|
|
CONNECTDATA CD;
|
|
HRESULT hres;
|
|
|
|
this->dirty = TRUE;
|
|
|
|
hres = IConnectionPoint_EnumConnections(this->pPropertyNotifyCP, &pEnum);
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) {
|
|
IPropertyNotifySink *sink;
|
|
|
|
IUnknown_QueryInterface(CD.pUnk, &IID_IPropertyNotifySink, (void**)&sink);
|
|
IPropertyNotifySink_OnChanged(sink, dispID);
|
|
IPropertyNotifySink_Release(sink);
|
|
IUnknown_Release(CD.pUnk);
|
|
}
|
|
IEnumConnections_Release(pEnum);
|
|
}
|
|
|
|
hres = IConnectionPoint_EnumConnections(this->pFontEventsCP, &pEnum);
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
DISPPARAMS dispparams;
|
|
VARIANTARG vararg;
|
|
|
|
VariantInit(&vararg);
|
|
V_VT(&vararg) = VT_BSTR;
|
|
V_BSTR(&vararg) = SysAllocString(dispid_mapping[dispID]);
|
|
|
|
dispparams.cArgs = 1;
|
|
dispparams.cNamedArgs = 0;
|
|
dispparams.rgdispidNamedArgs = NULL;
|
|
dispparams.rgvarg = &vararg;
|
|
|
|
while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) {
|
|
IFontEventsDisp *disp;
|
|
|
|
IUnknown_QueryInterface(CD.pUnk, &IID_IFontEventsDisp, (void**)&disp);
|
|
IFontEventsDisp_Invoke(disp, DISPID_FONT_CHANGED, &IID_NULL,
|
|
LOCALE_NEUTRAL, INVOKE_FUNC, &dispparams, NULL,
|
|
NULL, NULL);
|
|
|
|
IFontEventsDisp_Release(disp);
|
|
IUnknown_Release(CD.pUnk);
|
|
}
|
|
VariantClear(&vararg);
|
|
IEnumConnections_Release(pEnum);
|
|
}
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_QueryInterface (IUnknown)
|
|
*
|
|
* See Windows documentation for more details on IUnknown methods.
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_QueryInterface(
|
|
IFont* iface,
|
|
REFIID riid,
|
|
void** ppvObject)
|
|
{
|
|
OLEFontImpl *this = impl_from_IFont(iface);
|
|
|
|
TRACE("(%p)->(%s, %p)\n", this, debugstr_guid(riid), ppvObject);
|
|
|
|
*ppvObject = 0;
|
|
|
|
if (IsEqualGUID(&IID_IUnknown, riid) ||
|
|
IsEqualGUID(&IID_IFont, riid))
|
|
{
|
|
*ppvObject = this;
|
|
}
|
|
else if (IsEqualGUID(&IID_IDispatch, riid) ||
|
|
IsEqualGUID(&IID_IFontDisp, riid))
|
|
{
|
|
*ppvObject = &this->IDispatch_iface;
|
|
}
|
|
else if (IsEqualGUID(&IID_IPersist, riid) ||
|
|
IsEqualGUID(&IID_IPersistStream, riid))
|
|
{
|
|
*ppvObject = &this->IPersistStream_iface;
|
|
}
|
|
else if (IsEqualGUID(&IID_IConnectionPointContainer, riid))
|
|
{
|
|
*ppvObject = &this->IConnectionPointContainer_iface;
|
|
}
|
|
else if (IsEqualGUID(&IID_IPersistPropertyBag, riid))
|
|
{
|
|
*ppvObject = &this->IPersistPropertyBag_iface;
|
|
}
|
|
else if (IsEqualGUID(&IID_IPersistStreamInit, riid))
|
|
{
|
|
*ppvObject = &this->IPersistStreamInit_iface;
|
|
}
|
|
|
|
if (!*ppvObject)
|
|
{
|
|
FIXME("() : asking for unsupported interface %s\n", debugstr_guid(riid));
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
IFont_AddRef(iface);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_AddRef (IUnknown)
|
|
*/
|
|
static ULONG WINAPI OLEFontImpl_AddRef(
|
|
IFont* iface)
|
|
{
|
|
OLEFontImpl *this = impl_from_IFont(iface);
|
|
TRACE("(%p)->(ref=%d)\n", this, this->ref);
|
|
return InterlockedIncrement(&this->ref);
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_Release (IUnknown)
|
|
*/
|
|
static ULONG WINAPI OLEFontImpl_Release(IFont* iface)
|
|
{
|
|
OLEFontImpl *this = impl_from_IFont(iface);
|
|
ULONG ref;
|
|
|
|
TRACE("(%p)->(ref=%d)\n", this, this->ref);
|
|
|
|
ref = InterlockedDecrement(&this->ref);
|
|
|
|
if (ref == 0)
|
|
{
|
|
ULONG fontlist_refs = InterlockedDecrement(&ifont_cnt);
|
|
|
|
/* Final IFont object so destroy font cache */
|
|
if (fontlist_refs == 0)
|
|
{
|
|
HFONTItem *item, *cursor2;
|
|
|
|
EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
|
|
LIST_FOR_EACH_ENTRY_SAFE(item, cursor2, &OLEFontImpl_hFontList, HFONTItem, entry)
|
|
HFONTItem_Delete(item);
|
|
LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
|
|
delete_dc();
|
|
}
|
|
else
|
|
{
|
|
dec_int_ref(this->gdiFont);
|
|
}
|
|
OLEFontImpl_Destroy(this);
|
|
}
|
|
|
|
return ref;
|
|
}
|
|
|
|
typedef struct
|
|
{
|
|
short orig_cs;
|
|
short avail_cs;
|
|
} enum_data;
|
|
|
|
static int CALLBACK font_enum_proc(const LOGFONTW *elf, const TEXTMETRICW *ntm, DWORD type, LPARAM lp)
|
|
{
|
|
enum_data *data = (enum_data*)lp;
|
|
|
|
if(elf->lfCharSet == data->orig_cs)
|
|
{
|
|
data->avail_cs = data->orig_cs;
|
|
return 0;
|
|
}
|
|
if(data->avail_cs == -1) data->avail_cs = elf->lfCharSet;
|
|
return 1;
|
|
}
|
|
|
|
static void realize_font(OLEFontImpl *This)
|
|
{
|
|
LOGFONTW logFont;
|
|
INT fontHeight;
|
|
WCHAR text_face[LF_FACESIZE];
|
|
HDC hdc = get_dc();
|
|
HFONT old_font;
|
|
TEXTMETRICW tm;
|
|
|
|
if (!This->dirty) return;
|
|
|
|
text_face[0] = 0;
|
|
|
|
if(This->gdiFont)
|
|
{
|
|
old_font = SelectObject(hdc, This->gdiFont);
|
|
GetTextFaceW(hdc, sizeof(text_face) / sizeof(text_face[0]), text_face);
|
|
SelectObject(hdc, old_font);
|
|
dec_int_ref(This->gdiFont);
|
|
This->gdiFont = 0;
|
|
}
|
|
|
|
memset(&logFont, 0, sizeof(LOGFONTW));
|
|
|
|
lstrcpynW(logFont.lfFaceName, This->description.lpstrName, LF_FACESIZE);
|
|
logFont.lfCharSet = This->description.sCharset;
|
|
|
|
/* If the font name has been changed then enumerate all charsets
|
|
and pick one that'll result in the font specified being selected */
|
|
if(text_face[0] && lstrcmpiW(text_face, This->description.lpstrName))
|
|
{
|
|
enum_data data;
|
|
data.orig_cs = This->description.sCharset;
|
|
data.avail_cs = -1;
|
|
logFont.lfCharSet = DEFAULT_CHARSET;
|
|
EnumFontFamiliesExW(get_dc(), &logFont, font_enum_proc, (LPARAM)&data, 0);
|
|
if(data.avail_cs != -1) logFont.lfCharSet = data.avail_cs;
|
|
}
|
|
|
|
/*
|
|
* The height of the font returned by the get_Size property is the
|
|
* height of the font in points multiplied by 10000... Using some
|
|
* simple conversions and the ratio given by the application, it can
|
|
* be converted to a height in pixels.
|
|
*
|
|
* Standard ratio is 72 / 2540, or 18 / 635 in lowest terms.
|
|
* Ratio is applied here relative to the standard.
|
|
*/
|
|
|
|
fontHeight = MulDiv( This->description.cySize.s.Lo, This->cyLogical*635, This->cyHimetric*18 );
|
|
|
|
logFont.lfHeight = ((fontHeight%10000L)>5000L) ? (-fontHeight/10000L) - 1 :
|
|
(-fontHeight/10000L);
|
|
logFont.lfItalic = This->description.fItalic;
|
|
logFont.lfUnderline = This->description.fUnderline;
|
|
logFont.lfStrikeOut = This->description.fStrikethrough;
|
|
logFont.lfWeight = This->description.sWeight;
|
|
logFont.lfOutPrecision = OUT_CHARACTER_PRECIS;
|
|
logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
|
|
logFont.lfQuality = DEFAULT_QUALITY;
|
|
logFont.lfPitchAndFamily = DEFAULT_PITCH;
|
|
|
|
This->gdiFont = CreateFontIndirectW(&logFont);
|
|
This->dirty = FALSE;
|
|
|
|
add_hfontitem(This->gdiFont);
|
|
|
|
/* Fixup the name and charset properties so that they match the
|
|
selected font */
|
|
old_font = SelectObject(get_dc(), This->gdiFont);
|
|
GetTextFaceW(hdc, sizeof(text_face) / sizeof(text_face[0]), text_face);
|
|
if(lstrcmpiW(text_face, This->description.lpstrName))
|
|
{
|
|
HeapFree(GetProcessHeap(), 0, This->description.lpstrName);
|
|
This->description.lpstrName = strdupW(text_face);
|
|
}
|
|
GetTextMetricsW(hdc, &tm);
|
|
This->description.sCharset = tm.tmCharSet;
|
|
/* While we have it handy, stash the realized font height for use by get_Size() */
|
|
This->nRealHeight = tm.tmHeight - tm.tmInternalLeading; /* corresponds to LOGFONT lfHeight */
|
|
SelectObject(hdc, old_font);
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_get_Name (IFont)
|
|
*
|
|
* See Windows documentation for more details on IFont methods.
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_get_Name(
|
|
IFont* iface,
|
|
BSTR* pname)
|
|
{
|
|
OLEFontImpl *this = impl_from_IFont(iface);
|
|
TRACE("(%p)->(%p)\n", this, pname);
|
|
|
|
if (pname==0)
|
|
return E_POINTER;
|
|
|
|
realize_font(this);
|
|
|
|
if (this->description.lpstrName!=0)
|
|
*pname = SysAllocString(this->description.lpstrName);
|
|
else
|
|
*pname = 0;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_put_Name (IFont)
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_put_Name(
|
|
IFont* iface,
|
|
BSTR name)
|
|
{
|
|
OLEFontImpl *This = impl_from_IFont(iface);
|
|
TRACE("(%p)->(%p)\n", This, name);
|
|
|
|
if (!name)
|
|
return CTL_E_INVALIDPROPERTYVALUE;
|
|
|
|
HeapFree(GetProcessHeap(), 0, This->description.lpstrName);
|
|
This->description.lpstrName = strdupW(name);
|
|
if (!This->description.lpstrName) return E_OUTOFMEMORY;
|
|
|
|
TRACE("new name %s\n", debugstr_w(This->description.lpstrName));
|
|
OLEFont_SendNotify(This, DISPID_FONT_NAME);
|
|
return S_OK;
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_get_Size (IFont)
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_get_Size(
|
|
IFont* iface,
|
|
CY* psize)
|
|
{
|
|
OLEFontImpl *this = impl_from_IFont(iface);
|
|
TRACE("(%p)->(%p)\n", this, psize);
|
|
|
|
if (!psize) return E_POINTER;
|
|
|
|
realize_font(this);
|
|
|
|
/*
|
|
* Convert realized font height in pixels to points descaled by current
|
|
* scaling ratio then scaled up by 10000.
|
|
*/
|
|
psize->s.Lo = MulDiv(this->nRealHeight,
|
|
this->cyHimetric * 72 * 10000,
|
|
this->cyLogical * 2540);
|
|
psize->s.Hi = 0;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_put_Size (IFont)
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_put_Size(
|
|
IFont* iface,
|
|
CY size)
|
|
{
|
|
OLEFontImpl *this = impl_from_IFont(iface);
|
|
TRACE("(%p)->(%d)\n", this, size.s.Lo);
|
|
this->description.cySize.s.Hi = 0;
|
|
this->description.cySize.s.Lo = size.s.Lo;
|
|
OLEFont_SendNotify(this, DISPID_FONT_SIZE);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_get_Bold (IFont)
|
|
*
|
|
* See Windows documentation for more details on IFont methods.
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_get_Bold(
|
|
IFont* iface,
|
|
BOOL* pbold)
|
|
{
|
|
OLEFontImpl *this = impl_from_IFont(iface);
|
|
TRACE("(%p)->(%p)\n", this, pbold);
|
|
|
|
if (!pbold) return E_POINTER;
|
|
|
|
realize_font(this);
|
|
|
|
*pbold = this->description.sWeight > 550;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_put_Bold (IFont)
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_put_Bold(
|
|
IFont* iface,
|
|
BOOL bold)
|
|
{
|
|
OLEFontImpl *this = impl_from_IFont(iface);
|
|
TRACE("(%p)->(%d)\n", this, bold);
|
|
this->description.sWeight = bold ? FW_BOLD : FW_NORMAL;
|
|
OLEFont_SendNotify(this, DISPID_FONT_BOLD);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_get_Italic (IFont)
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_get_Italic(
|
|
IFont* iface,
|
|
BOOL* pitalic)
|
|
{
|
|
OLEFontImpl *this = impl_from_IFont(iface);
|
|
TRACE("(%p)->(%p)\n", this, pitalic);
|
|
|
|
if (pitalic==0)
|
|
return E_POINTER;
|
|
|
|
realize_font(this);
|
|
|
|
*pitalic = this->description.fItalic;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_put_Italic (IFont)
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_put_Italic(
|
|
IFont* iface,
|
|
BOOL italic)
|
|
{
|
|
OLEFontImpl *this = impl_from_IFont(iface);
|
|
TRACE("(%p)->(%d)\n", this, italic);
|
|
|
|
this->description.fItalic = italic;
|
|
|
|
OLEFont_SendNotify(this, DISPID_FONT_ITALIC);
|
|
return S_OK;
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_get_Underline (IFont)
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_get_Underline(
|
|
IFont* iface,
|
|
BOOL* punderline)
|
|
{
|
|
OLEFontImpl *this = impl_from_IFont(iface);
|
|
TRACE("(%p)->(%p)\n", this, punderline);
|
|
|
|
if (punderline==0)
|
|
return E_POINTER;
|
|
|
|
realize_font(this);
|
|
|
|
*punderline = this->description.fUnderline;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_put_Underline (IFont)
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_put_Underline(
|
|
IFont* iface,
|
|
BOOL underline)
|
|
{
|
|
OLEFontImpl *this = impl_from_IFont(iface);
|
|
TRACE("(%p)->(%d)\n", this, underline);
|
|
|
|
this->description.fUnderline = underline;
|
|
|
|
OLEFont_SendNotify(this, DISPID_FONT_UNDER);
|
|
return S_OK;
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_get_Strikethrough (IFont)
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_get_Strikethrough(
|
|
IFont* iface,
|
|
BOOL* pstrikethrough)
|
|
{
|
|
OLEFontImpl *this = impl_from_IFont(iface);
|
|
TRACE("(%p)->(%p)\n", this, pstrikethrough);
|
|
|
|
if (pstrikethrough==0)
|
|
return E_POINTER;
|
|
|
|
realize_font(this);
|
|
|
|
*pstrikethrough = this->description.fStrikethrough;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_put_Strikethrough (IFont)
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_put_Strikethrough(
|
|
IFont* iface,
|
|
BOOL strikethrough)
|
|
{
|
|
OLEFontImpl *this = impl_from_IFont(iface);
|
|
TRACE("(%p)->(%d)\n", this, strikethrough);
|
|
|
|
this->description.fStrikethrough = strikethrough;
|
|
OLEFont_SendNotify(this, DISPID_FONT_STRIKE);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_get_Weight (IFont)
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_get_Weight(
|
|
IFont* iface,
|
|
short* pweight)
|
|
{
|
|
OLEFontImpl *this = impl_from_IFont(iface);
|
|
TRACE("(%p)->(%p)\n", this, pweight);
|
|
|
|
if (pweight==0)
|
|
return E_POINTER;
|
|
|
|
realize_font(this);
|
|
|
|
*pweight = this->description.sWeight;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_put_Weight (IFont)
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_put_Weight(
|
|
IFont* iface,
|
|
short weight)
|
|
{
|
|
OLEFontImpl *this = impl_from_IFont(iface);
|
|
TRACE("(%p)->(%d)\n", this, weight);
|
|
|
|
this->description.sWeight = weight;
|
|
|
|
OLEFont_SendNotify(this, DISPID_FONT_WEIGHT);
|
|
return S_OK;
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_get_Charset (IFont)
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_get_Charset(
|
|
IFont* iface,
|
|
short* pcharset)
|
|
{
|
|
OLEFontImpl *this = impl_from_IFont(iface);
|
|
TRACE("(%p)->(%p)\n", this, pcharset);
|
|
|
|
if (pcharset==0)
|
|
return E_POINTER;
|
|
|
|
realize_font(this);
|
|
|
|
*pcharset = this->description.sCharset;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_put_Charset (IFont)
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_put_Charset(
|
|
IFont* iface,
|
|
short charset)
|
|
{
|
|
OLEFontImpl *this = impl_from_IFont(iface);
|
|
TRACE("(%p)->(%d)\n", this, charset);
|
|
|
|
this->description.sCharset = charset;
|
|
OLEFont_SendNotify(this, DISPID_FONT_CHARSET);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_get_hFont (IFont)
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_get_hFont(
|
|
IFont* iface,
|
|
HFONT* phfont)
|
|
{
|
|
OLEFontImpl *this = impl_from_IFont(iface);
|
|
TRACE("(%p)->(%p)\n", this, phfont);
|
|
if (phfont==NULL)
|
|
return E_POINTER;
|
|
|
|
realize_font(this);
|
|
|
|
*phfont = this->gdiFont;
|
|
TRACE("Returning %p\n", *phfont);
|
|
return S_OK;
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_Clone (IFont)
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_Clone(
|
|
IFont* iface,
|
|
IFont** ppfont)
|
|
{
|
|
OLEFontImpl *this = impl_from_IFont(iface);
|
|
OLEFontImpl* newObject;
|
|
|
|
TRACE("(%p)->(%p)\n", this, ppfont);
|
|
|
|
if (ppfont == NULL)
|
|
return E_POINTER;
|
|
|
|
*ppfont = NULL;
|
|
|
|
newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(OLEFontImpl));
|
|
if (newObject==NULL)
|
|
return E_OUTOFMEMORY;
|
|
|
|
*newObject = *this;
|
|
/* allocate separate buffer */
|
|
newObject->description.lpstrName = strdupW(this->description.lpstrName);
|
|
|
|
/* Increment internal ref in hfont item list */
|
|
if(newObject->gdiFont) inc_int_ref(newObject->gdiFont);
|
|
|
|
InterlockedIncrement(&ifont_cnt);
|
|
|
|
newObject->pPropertyNotifyCP = NULL;
|
|
newObject->pFontEventsCP = NULL;
|
|
CreateConnectionPoint((IUnknown*)newObject, &IID_IPropertyNotifySink, &newObject->pPropertyNotifyCP);
|
|
CreateConnectionPoint((IUnknown*)newObject, &IID_IFontEventsDisp, &newObject->pFontEventsCP);
|
|
|
|
if (!newObject->pPropertyNotifyCP || !newObject->pFontEventsCP)
|
|
{
|
|
OLEFontImpl_Destroy(newObject);
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
/* The cloned object starts with a reference count of 1 */
|
|
newObject->ref = 1;
|
|
|
|
*ppfont = &newObject->IFont_iface;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_IsEqual (IFont)
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_IsEqual(
|
|
IFont* iface,
|
|
IFont* pFontOther)
|
|
{
|
|
OLEFontImpl *left = impl_from_IFont(iface);
|
|
OLEFontImpl *right = impl_from_IFont(pFontOther);
|
|
INT ret;
|
|
INT left_len,right_len;
|
|
|
|
if(pFontOther == NULL)
|
|
return E_POINTER;
|
|
else if (left->description.cySize.s.Lo != right->description.cySize.s.Lo)
|
|
return S_FALSE;
|
|
else if (left->description.cySize.s.Hi != right->description.cySize.s.Hi)
|
|
return S_FALSE;
|
|
else if (left->description.sWeight != right->description.sWeight)
|
|
return S_FALSE;
|
|
else if (left->description.sCharset != right->description.sCharset)
|
|
return S_FALSE;
|
|
else if (left->description.fItalic != right->description.fItalic)
|
|
return S_FALSE;
|
|
else if (left->description.fUnderline != right->description.fUnderline)
|
|
return S_FALSE;
|
|
else if (left->description.fStrikethrough != right->description.fStrikethrough)
|
|
return S_FALSE;
|
|
|
|
/* Check from string */
|
|
left_len = strlenW(left->description.lpstrName);
|
|
right_len = strlenW(right->description.lpstrName);
|
|
ret = CompareStringW(0,0,left->description.lpstrName, left_len,
|
|
right->description.lpstrName, right_len);
|
|
if (ret != CSTR_EQUAL)
|
|
return S_FALSE;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_SetRatio (IFont)
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_SetRatio(
|
|
IFont* iface,
|
|
LONG cyLogical,
|
|
LONG cyHimetric)
|
|
{
|
|
OLEFontImpl *this = impl_from_IFont(iface);
|
|
TRACE("(%p)->(%d, %d)\n", this, cyLogical, cyHimetric);
|
|
|
|
if(cyLogical == 0 || cyHimetric == 0)
|
|
return E_FAIL;
|
|
|
|
/* cyLogical and cyHimetric both set to 1 is a special case that
|
|
does not change the scaling but also does not fail */
|
|
if(cyLogical == 1 && cyHimetric == 1)
|
|
return S_OK;
|
|
|
|
this->cyLogical = cyLogical;
|
|
this->cyHimetric = cyHimetric;
|
|
this->dirty = TRUE;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_QueryTextMetrics (IFont)
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_QueryTextMetrics(
|
|
IFont* iface,
|
|
TEXTMETRICOLE* ptm)
|
|
{
|
|
HDC hdcRef;
|
|
HFONT hOldFont, hNewFont;
|
|
|
|
hdcRef = GetDC(0);
|
|
IFont_get_hFont(iface, &hNewFont);
|
|
hOldFont = SelectObject(hdcRef, hNewFont);
|
|
GetTextMetricsW(hdcRef, ptm);
|
|
SelectObject(hdcRef, hOldFont);
|
|
ReleaseDC(0, hdcRef);
|
|
return S_OK;
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_AddRefHfont (IFont)
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_AddRefHfont(
|
|
IFont* iface,
|
|
HFONT hfont)
|
|
{
|
|
OLEFontImpl *this = impl_from_IFont(iface);
|
|
|
|
TRACE("(%p)->(%p)\n", this, hfont);
|
|
|
|
if (!hfont) return E_INVALIDARG;
|
|
|
|
return inc_ext_ref(hfont);
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_ReleaseHfont (IFont)
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_ReleaseHfont(
|
|
IFont* iface,
|
|
HFONT hfont)
|
|
{
|
|
OLEFontImpl *this = impl_from_IFont(iface);
|
|
|
|
TRACE("(%p)->(%p)\n", this, hfont);
|
|
|
|
if (!hfont) return E_INVALIDARG;
|
|
|
|
return dec_ext_ref(hfont);
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_SetHdc (IFont)
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_SetHdc(
|
|
IFont* iface,
|
|
HDC hdc)
|
|
{
|
|
OLEFontImpl *this = impl_from_IFont(iface);
|
|
FIXME("(%p)->(%p): Stub\n", this, hdc);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static const IFontVtbl OLEFontImpl_VTable =
|
|
{
|
|
OLEFontImpl_QueryInterface,
|
|
OLEFontImpl_AddRef,
|
|
OLEFontImpl_Release,
|
|
OLEFontImpl_get_Name,
|
|
OLEFontImpl_put_Name,
|
|
OLEFontImpl_get_Size,
|
|
OLEFontImpl_put_Size,
|
|
OLEFontImpl_get_Bold,
|
|
OLEFontImpl_put_Bold,
|
|
OLEFontImpl_get_Italic,
|
|
OLEFontImpl_put_Italic,
|
|
OLEFontImpl_get_Underline,
|
|
OLEFontImpl_put_Underline,
|
|
OLEFontImpl_get_Strikethrough,
|
|
OLEFontImpl_put_Strikethrough,
|
|
OLEFontImpl_get_Weight,
|
|
OLEFontImpl_put_Weight,
|
|
OLEFontImpl_get_Charset,
|
|
OLEFontImpl_put_Charset,
|
|
OLEFontImpl_get_hFont,
|
|
OLEFontImpl_Clone,
|
|
OLEFontImpl_IsEqual,
|
|
OLEFontImpl_SetRatio,
|
|
OLEFontImpl_QueryTextMetrics,
|
|
OLEFontImpl_AddRefHfont,
|
|
OLEFontImpl_ReleaseHfont,
|
|
OLEFontImpl_SetHdc
|
|
};
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_IDispatch_QueryInterface (IUnknown)
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_IDispatch_QueryInterface(
|
|
IDispatch* iface,
|
|
REFIID riid,
|
|
VOID** ppvoid)
|
|
{
|
|
OLEFontImpl *this = impl_from_IDispatch(iface);
|
|
return IFont_QueryInterface(&this->IFont_iface, riid, ppvoid);
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_IDispatch_Release (IUnknown)
|
|
*/
|
|
static ULONG WINAPI OLEFontImpl_IDispatch_Release(
|
|
IDispatch* iface)
|
|
{
|
|
OLEFontImpl *this = impl_from_IDispatch(iface);
|
|
return IFont_Release(&this->IFont_iface);
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_IDispatch_AddRef (IUnknown)
|
|
*/
|
|
static ULONG WINAPI OLEFontImpl_IDispatch_AddRef(
|
|
IDispatch* iface)
|
|
{
|
|
OLEFontImpl *this = impl_from_IDispatch(iface);
|
|
return IFont_AddRef(&this->IFont_iface);
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_GetTypeInfoCount (IDispatch)
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_GetTypeInfoCount(
|
|
IDispatch* iface,
|
|
unsigned int* pctinfo)
|
|
{
|
|
OLEFontImpl *this = impl_from_IDispatch(iface);
|
|
TRACE("(%p)->(%p)\n", this, pctinfo);
|
|
*pctinfo = 1;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_GetTypeInfo (IDispatch)
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_GetTypeInfo(
|
|
IDispatch* iface,
|
|
UINT iTInfo,
|
|
LCID lcid,
|
|
ITypeInfo** ppTInfo)
|
|
{
|
|
static const WCHAR stdole2tlb[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
|
|
ITypeLib *tl;
|
|
HRESULT hres;
|
|
|
|
OLEFontImpl *this = impl_from_IDispatch(iface);
|
|
TRACE("(%p, iTInfo=%d, lcid=%04x, %p)\n", this, iTInfo, (int)lcid, ppTInfo);
|
|
if (iTInfo != 0)
|
|
return E_FAIL;
|
|
hres = LoadTypeLib(stdole2tlb, &tl);
|
|
if (FAILED(hres)) {
|
|
ERR("Could not load the stdole2.tlb?\n");
|
|
return hres;
|
|
}
|
|
hres = ITypeLib_GetTypeInfoOfGuid(tl, &IID_IFontDisp, ppTInfo);
|
|
ITypeLib_Release(tl);
|
|
if (FAILED(hres)) {
|
|
FIXME("Did not IDispatch typeinfo from typelib, hres %x\n",hres);
|
|
}
|
|
return hres;
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_GetIDsOfNames (IDispatch)
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_GetIDsOfNames(
|
|
IDispatch* iface,
|
|
REFIID riid,
|
|
LPOLESTR* rgszNames,
|
|
UINT cNames,
|
|
LCID lcid,
|
|
DISPID* rgDispId)
|
|
{
|
|
ITypeInfo * pTInfo;
|
|
HRESULT hres;
|
|
|
|
OLEFontImpl *this = impl_from_IDispatch(iface);
|
|
|
|
TRACE("(%p,%s,%p,cNames=%d,lcid=%04x,%p)\n", this, debugstr_guid(riid),
|
|
rgszNames, cNames, (int)lcid, rgDispId);
|
|
|
|
if (cNames == 0) return E_INVALIDARG;
|
|
|
|
hres = IDispatch_GetTypeInfo(iface, 0, lcid, &pTInfo);
|
|
if (FAILED(hres))
|
|
{
|
|
ERR("GetTypeInfo failed.\n");
|
|
return hres;
|
|
}
|
|
|
|
/* convert names to DISPIDs */
|
|
hres = DispGetIDsOfNames (pTInfo, rgszNames, cNames, rgDispId);
|
|
ITypeInfo_Release(pTInfo);
|
|
|
|
return hres;
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_Invoke (IDispatch)
|
|
*
|
|
* Note: Do not call _put_Xxx methods, since setting things here
|
|
* should not call notify functions as I found out debugging the generic
|
|
* MS VB5 installer.
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_Invoke(
|
|
IDispatch* iface,
|
|
DISPID dispIdMember,
|
|
REFIID riid,
|
|
LCID lcid,
|
|
WORD wFlags,
|
|
DISPPARAMS* pDispParams,
|
|
VARIANT* pVarResult,
|
|
EXCEPINFO* pExepInfo,
|
|
UINT* puArgErr)
|
|
{
|
|
OLEFontImpl *this = impl_from_IDispatch(iface);
|
|
HRESULT hr;
|
|
|
|
TRACE("%p->(%d,%s,0x%x,0x%x,%p,%p,%p,%p)\n", this, dispIdMember,
|
|
debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, pExepInfo,
|
|
puArgErr);
|
|
|
|
/* validate parameters */
|
|
|
|
if (!IsEqualIID(riid, &IID_NULL))
|
|
{
|
|
ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid));
|
|
return DISP_E_UNKNOWNINTERFACE;
|
|
}
|
|
|
|
if (wFlags & DISPATCH_PROPERTYGET)
|
|
{
|
|
if (!pVarResult)
|
|
{
|
|
ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
|
|
return DISP_E_PARAMNOTOPTIONAL;
|
|
}
|
|
}
|
|
else if (wFlags & DISPATCH_PROPERTYPUT)
|
|
{
|
|
if (!pDispParams)
|
|
{
|
|
ERR("null pDispParams not allowed when DISPATCH_PROPERTYPUT specified\n");
|
|
return DISP_E_PARAMNOTOPTIONAL;
|
|
}
|
|
if (pDispParams->cArgs != 1)
|
|
{
|
|
ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams->cArgs);
|
|
return DISP_E_BADPARAMCOUNT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ERR("one of DISPATCH_PROPERTYGET or DISPATCH_PROPERTYPUT must be specified\n");
|
|
return DISP_E_MEMBERNOTFOUND;
|
|
}
|
|
|
|
switch (dispIdMember) {
|
|
case DISPID_FONT_NAME:
|
|
if (wFlags & DISPATCH_PROPERTYGET) {
|
|
V_VT(pVarResult) = VT_BSTR;
|
|
return IFont_get_Name(&this->IFont_iface, &V_BSTR(pVarResult));
|
|
} else {
|
|
VARIANTARG vararg;
|
|
|
|
VariantInit(&vararg);
|
|
hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BSTR);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
hr = IFont_put_Name(&this->IFont_iface, V_BSTR(&vararg));
|
|
|
|
VariantClear(&vararg);
|
|
return hr;
|
|
}
|
|
break;
|
|
case DISPID_FONT_BOLD:
|
|
if (wFlags & DISPATCH_PROPERTYGET) {
|
|
BOOL value;
|
|
hr = IFont_get_Bold(&this->IFont_iface, &value);
|
|
V_VT(pVarResult) = VT_BOOL;
|
|
V_BOOL(pVarResult) = value ? VARIANT_TRUE : VARIANT_FALSE;
|
|
return hr;
|
|
} else {
|
|
VARIANTARG vararg;
|
|
|
|
VariantInit(&vararg);
|
|
hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BOOL);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
hr = IFont_put_Bold(&this->IFont_iface, V_BOOL(&vararg));
|
|
|
|
VariantClear(&vararg);
|
|
return hr;
|
|
}
|
|
break;
|
|
case DISPID_FONT_ITALIC:
|
|
if (wFlags & DISPATCH_PROPERTYGET) {
|
|
BOOL value;
|
|
hr = IFont_get_Italic(&this->IFont_iface, &value);
|
|
V_VT(pVarResult) = VT_BOOL;
|
|
V_BOOL(pVarResult) = value ? VARIANT_TRUE : VARIANT_FALSE;
|
|
return hr;
|
|
} else {
|
|
VARIANTARG vararg;
|
|
|
|
VariantInit(&vararg);
|
|
hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BOOL);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
hr = IFont_put_Italic(&this->IFont_iface, V_BOOL(&vararg));
|
|
|
|
VariantClear(&vararg);
|
|
return hr;
|
|
}
|
|
break;
|
|
case DISPID_FONT_UNDER:
|
|
if (wFlags & DISPATCH_PROPERTYGET) {
|
|
BOOL value;
|
|
hr = IFont_get_Underline(&this->IFont_iface, &value);
|
|
V_VT(pVarResult) = VT_BOOL;
|
|
V_BOOL(pVarResult) = value ? VARIANT_TRUE : VARIANT_FALSE;
|
|
return hr;
|
|
} else {
|
|
VARIANTARG vararg;
|
|
|
|
VariantInit(&vararg);
|
|
hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BOOL);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
hr = IFont_put_Underline(&this->IFont_iface, V_BOOL(&vararg));
|
|
|
|
VariantClear(&vararg);
|
|
return hr;
|
|
}
|
|
break;
|
|
case DISPID_FONT_STRIKE:
|
|
if (wFlags & DISPATCH_PROPERTYGET) {
|
|
BOOL value;
|
|
hr = IFont_get_Strikethrough(&this->IFont_iface, &value);
|
|
V_VT(pVarResult) = VT_BOOL;
|
|
V_BOOL(pVarResult) = value ? VARIANT_TRUE : VARIANT_FALSE;
|
|
return hr;
|
|
} else {
|
|
VARIANTARG vararg;
|
|
|
|
VariantInit(&vararg);
|
|
hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BOOL);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
hr = IFont_put_Strikethrough(&this->IFont_iface, V_BOOL(&vararg));
|
|
|
|
VariantClear(&vararg);
|
|
return hr;
|
|
}
|
|
break;
|
|
case DISPID_FONT_SIZE:
|
|
if (wFlags & DISPATCH_PROPERTYGET) {
|
|
V_VT(pVarResult) = VT_CY;
|
|
return IFont_get_Size(&this->IFont_iface, &V_CY(pVarResult));
|
|
} else {
|
|
VARIANTARG vararg;
|
|
|
|
VariantInit(&vararg);
|
|
hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_CY);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
hr = IFont_put_Size(&this->IFont_iface, V_CY(&vararg));
|
|
|
|
VariantClear(&vararg);
|
|
return hr;
|
|
}
|
|
break;
|
|
case DISPID_FONT_WEIGHT:
|
|
if (wFlags & DISPATCH_PROPERTYGET) {
|
|
V_VT(pVarResult) = VT_I2;
|
|
return IFont_get_Weight(&this->IFont_iface, &V_I2(pVarResult));
|
|
} else {
|
|
VARIANTARG vararg;
|
|
|
|
VariantInit(&vararg);
|
|
hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_I2);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
hr = IFont_put_Weight(&this->IFont_iface, V_I2(&vararg));
|
|
|
|
VariantClear(&vararg);
|
|
return hr;
|
|
}
|
|
break;
|
|
case DISPID_FONT_CHARSET:
|
|
if (wFlags & DISPATCH_PROPERTYGET) {
|
|
V_VT(pVarResult) = VT_I2;
|
|
return OLEFontImpl_get_Charset(&this->IFont_iface, &V_I2(pVarResult));
|
|
} else {
|
|
VARIANTARG vararg;
|
|
|
|
VariantInit(&vararg);
|
|
hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_I2);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
hr = IFont_put_Charset(&this->IFont_iface, V_I2(&vararg));
|
|
|
|
VariantClear(&vararg);
|
|
return hr;
|
|
}
|
|
break;
|
|
default:
|
|
ERR("member not found for dispid 0x%x\n", dispIdMember);
|
|
return DISP_E_MEMBERNOTFOUND;
|
|
}
|
|
}
|
|
|
|
static const IDispatchVtbl OLEFontImpl_IDispatch_VTable =
|
|
{
|
|
OLEFontImpl_IDispatch_QueryInterface,
|
|
OLEFontImpl_IDispatch_AddRef,
|
|
OLEFontImpl_IDispatch_Release,
|
|
OLEFontImpl_GetTypeInfoCount,
|
|
OLEFontImpl_GetTypeInfo,
|
|
OLEFontImpl_GetIDsOfNames,
|
|
OLEFontImpl_Invoke
|
|
};
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_IPersistStream_QueryInterface (IUnknown)
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_IPersistStream_QueryInterface(
|
|
IPersistStream* iface,
|
|
REFIID riid,
|
|
VOID** ppvoid)
|
|
{
|
|
OLEFontImpl *this = impl_from_IPersistStream(iface);
|
|
|
|
return IFont_QueryInterface(&this->IFont_iface, riid, ppvoid);
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_IPersistStream_Release (IUnknown)
|
|
*/
|
|
static ULONG WINAPI OLEFontImpl_IPersistStream_Release(
|
|
IPersistStream* iface)
|
|
{
|
|
OLEFontImpl *this = impl_from_IPersistStream(iface);
|
|
|
|
return IFont_Release(&this->IFont_iface);
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_IPersistStream_AddRef (IUnknown)
|
|
*/
|
|
static ULONG WINAPI OLEFontImpl_IPersistStream_AddRef(
|
|
IPersistStream* iface)
|
|
{
|
|
OLEFontImpl *this = impl_from_IPersistStream(iface);
|
|
|
|
return IFont_AddRef(&this->IFont_iface);
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_GetClassID (IPersistStream)
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_GetClassID(
|
|
IPersistStream* iface,
|
|
CLSID* pClassID)
|
|
{
|
|
TRACE("(%p,%p)\n",iface,pClassID);
|
|
if (pClassID==0)
|
|
return E_POINTER;
|
|
|
|
*pClassID = CLSID_StdFont;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_IsDirty (IPersistStream)
|
|
*
|
|
* See Windows documentation for more details on IPersistStream methods.
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_IsDirty(
|
|
IPersistStream* iface)
|
|
{
|
|
TRACE("(%p)\n",iface);
|
|
return S_OK;
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_Load (IPersistStream)
|
|
*
|
|
* See Windows documentation for more details on IPersistStream methods.
|
|
*
|
|
* This is the format of the standard font serialization as far as I
|
|
* know
|
|
*
|
|
* Offset Type Value Comment
|
|
* 0x0000 Byte Unknown Probably a version number, contains 0x01
|
|
* 0x0001 Short Charset Charset value from the FONTDESC structure
|
|
* 0x0003 Byte Attributes Flags defined as follows:
|
|
* 00000010 - Italic
|
|
* 00000100 - Underline
|
|
* 00001000 - Strikethrough
|
|
* 0x0004 Short Weight Weight value from FONTDESC structure
|
|
* 0x0006 DWORD size "Low" portion of the cySize member of the FONTDESC
|
|
* structure/
|
|
* 0x000A Byte name length Length of the font name string (no null character)
|
|
* 0x000B String name Name of the font (ASCII, no nul character)
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_Load(
|
|
IPersistStream* iface,
|
|
IStream* pLoadStream)
|
|
{
|
|
OLEFontImpl *this = impl_from_IPersistStream(iface);
|
|
BYTE version, attributes, string_size;
|
|
char readBuffer[0x100];
|
|
ULONG cbRead;
|
|
INT len;
|
|
|
|
/* Version */
|
|
IStream_Read(pLoadStream, &version, sizeof(BYTE), &cbRead);
|
|
if ((cbRead != sizeof(BYTE)) || (version != 0x01)) return E_FAIL;
|
|
|
|
/* Charset */
|
|
IStream_Read(pLoadStream, &this->description.sCharset, sizeof(WORD), &cbRead);
|
|
if (cbRead != sizeof(WORD)) return E_FAIL;
|
|
|
|
/* Attributes */
|
|
IStream_Read(pLoadStream, &attributes, sizeof(BYTE), &cbRead);
|
|
if (cbRead != sizeof(BYTE)) return E_FAIL;
|
|
|
|
this->description.fItalic = (attributes & FONTPERSIST_ITALIC) != 0;
|
|
this->description.fStrikethrough = (attributes & FONTPERSIST_STRIKETHROUGH) != 0;
|
|
this->description.fUnderline = (attributes & FONTPERSIST_UNDERLINE) != 0;
|
|
|
|
/* Weight */
|
|
IStream_Read(pLoadStream, &this->description.sWeight, sizeof(WORD), &cbRead);
|
|
if (cbRead != sizeof(WORD)) return E_FAIL;
|
|
|
|
/* Size */
|
|
IStream_Read(pLoadStream, &this->description.cySize.s.Lo, sizeof(DWORD), &cbRead);
|
|
if (cbRead != sizeof(DWORD)) return E_FAIL;
|
|
|
|
this->description.cySize.s.Hi = 0;
|
|
|
|
/* Name */
|
|
IStream_Read(pLoadStream, &string_size, sizeof(BYTE), &cbRead);
|
|
if (cbRead != sizeof(BYTE)) return E_FAIL;
|
|
|
|
IStream_Read(pLoadStream, readBuffer, string_size, &cbRead);
|
|
if (cbRead != string_size) return E_FAIL;
|
|
|
|
HeapFree(GetProcessHeap(), 0, this->description.lpstrName);
|
|
|
|
len = MultiByteToWideChar( CP_ACP, 0, readBuffer, string_size, NULL, 0 );
|
|
this->description.lpstrName = HeapAlloc( GetProcessHeap(), 0, (len+1) * sizeof(WCHAR) );
|
|
MultiByteToWideChar( CP_ACP, 0, readBuffer, string_size, this->description.lpstrName, len );
|
|
this->description.lpstrName[len] = 0;
|
|
|
|
/* Ensure use of this font causes a new one to be created */
|
|
dec_int_ref(this->gdiFont);
|
|
this->gdiFont = 0;
|
|
this->dirty = TRUE;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_Save (IPersistStream)
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_Save(
|
|
IPersistStream* iface,
|
|
IStream* pOutStream,
|
|
BOOL fClearDirty)
|
|
{
|
|
OLEFontImpl *this = impl_from_IPersistStream(iface);
|
|
BYTE attributes, string_size;
|
|
const BYTE version = 0x01;
|
|
char* writeBuffer = NULL;
|
|
ULONG written;
|
|
|
|
TRACE("(%p)->(%p %d)\n", this, pOutStream, fClearDirty);
|
|
|
|
/* Version */
|
|
IStream_Write(pOutStream, &version, sizeof(BYTE), &written);
|
|
if (written != sizeof(BYTE)) return E_FAIL;
|
|
|
|
/* Charset */
|
|
IStream_Write(pOutStream, &this->description.sCharset, sizeof(WORD), &written);
|
|
if (written != sizeof(WORD)) return E_FAIL;
|
|
|
|
/* Attributes */
|
|
attributes = 0;
|
|
|
|
if (this->description.fItalic)
|
|
attributes |= FONTPERSIST_ITALIC;
|
|
|
|
if (this->description.fStrikethrough)
|
|
attributes |= FONTPERSIST_STRIKETHROUGH;
|
|
|
|
if (this->description.fUnderline)
|
|
attributes |= FONTPERSIST_UNDERLINE;
|
|
|
|
IStream_Write(pOutStream, &attributes, sizeof(BYTE), &written);
|
|
if (written != sizeof(BYTE)) return E_FAIL;
|
|
|
|
/* Weight */
|
|
IStream_Write(pOutStream, &this->description.sWeight, sizeof(WORD), &written);
|
|
if (written != sizeof(WORD)) return E_FAIL;
|
|
|
|
/* Size */
|
|
IStream_Write(pOutStream, &this->description.cySize.s.Lo, sizeof(DWORD), &written);
|
|
if (written != sizeof(DWORD)) return E_FAIL;
|
|
|
|
/* FontName */
|
|
if (this->description.lpstrName)
|
|
string_size = WideCharToMultiByte( CP_ACP, 0, this->description.lpstrName,
|
|
strlenW(this->description.lpstrName), NULL, 0, NULL, NULL );
|
|
else
|
|
string_size = 0;
|
|
|
|
IStream_Write(pOutStream, &string_size, sizeof(BYTE), &written);
|
|
if (written != sizeof(BYTE)) return E_FAIL;
|
|
|
|
if (string_size)
|
|
{
|
|
if (!(writeBuffer = HeapAlloc( GetProcessHeap(), 0, string_size ))) return E_OUTOFMEMORY;
|
|
WideCharToMultiByte( CP_ACP, 0, this->description.lpstrName,
|
|
strlenW(this->description.lpstrName),
|
|
writeBuffer, string_size, NULL, NULL );
|
|
|
|
IStream_Write(pOutStream, writeBuffer, string_size, &written);
|
|
HeapFree(GetProcessHeap(), 0, writeBuffer);
|
|
|
|
if (written != string_size) return E_FAIL;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_GetSizeMax (IPersistStream)
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_GetSizeMax(
|
|
IPersistStream* iface,
|
|
ULARGE_INTEGER* pcbSize)
|
|
{
|
|
OLEFontImpl *this = impl_from_IPersistStream(iface);
|
|
|
|
if (pcbSize==NULL)
|
|
return E_POINTER;
|
|
|
|
pcbSize->u.HighPart = 0;
|
|
pcbSize->u.LowPart = 0;
|
|
|
|
pcbSize->u.LowPart += sizeof(BYTE); /* Version */
|
|
pcbSize->u.LowPart += sizeof(WORD); /* Lang code */
|
|
pcbSize->u.LowPart += sizeof(BYTE); /* Flags */
|
|
pcbSize->u.LowPart += sizeof(WORD); /* Weight */
|
|
pcbSize->u.LowPart += sizeof(DWORD); /* Size */
|
|
pcbSize->u.LowPart += sizeof(BYTE); /* StrLength */
|
|
|
|
if (this->description.lpstrName!=0)
|
|
pcbSize->u.LowPart += WideCharToMultiByte( CP_ACP, 0, this->description.lpstrName,
|
|
strlenW(this->description.lpstrName),
|
|
NULL, 0, NULL, NULL );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static const IPersistStreamVtbl OLEFontImpl_IPersistStream_VTable =
|
|
{
|
|
OLEFontImpl_IPersistStream_QueryInterface,
|
|
OLEFontImpl_IPersistStream_AddRef,
|
|
OLEFontImpl_IPersistStream_Release,
|
|
OLEFontImpl_GetClassID,
|
|
OLEFontImpl_IsDirty,
|
|
OLEFontImpl_Load,
|
|
OLEFontImpl_Save,
|
|
OLEFontImpl_GetSizeMax
|
|
};
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_IConnectionPointContainer_QueryInterface (IUnknown)
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_IConnectionPointContainer_QueryInterface(
|
|
IConnectionPointContainer* iface,
|
|
REFIID riid,
|
|
VOID** ppvoid)
|
|
{
|
|
OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
|
|
|
|
return IFont_QueryInterface(&this->IFont_iface, riid, ppvoid);
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_IConnectionPointContainer_Release (IUnknown)
|
|
*/
|
|
static ULONG WINAPI OLEFontImpl_IConnectionPointContainer_Release(
|
|
IConnectionPointContainer* iface)
|
|
{
|
|
OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
|
|
|
|
return IFont_Release(&this->IFont_iface);
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_IConnectionPointContainer_AddRef (IUnknown)
|
|
*/
|
|
static ULONG WINAPI OLEFontImpl_IConnectionPointContainer_AddRef(
|
|
IConnectionPointContainer* iface)
|
|
{
|
|
OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
|
|
|
|
return IFont_AddRef(&this->IFont_iface);
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_EnumConnectionPoints (IConnectionPointContainer)
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_EnumConnectionPoints(
|
|
IConnectionPointContainer* iface,
|
|
IEnumConnectionPoints **ppEnum)
|
|
{
|
|
OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
|
|
|
|
FIXME("(%p)->(%p): stub\n", this, ppEnum);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_FindConnectionPoint (IConnectionPointContainer)
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_FindConnectionPoint(
|
|
IConnectionPointContainer* iface,
|
|
REFIID riid,
|
|
IConnectionPoint **ppCp)
|
|
{
|
|
OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
|
|
TRACE("(%p)->(%s, %p)\n", this, debugstr_guid(riid), ppCp);
|
|
|
|
if(IsEqualIID(riid, &IID_IPropertyNotifySink)) {
|
|
return IConnectionPoint_QueryInterface(this->pPropertyNotifyCP, &IID_IConnectionPoint,
|
|
(void**)ppCp);
|
|
} else if(IsEqualIID(riid, &IID_IFontEventsDisp)) {
|
|
return IConnectionPoint_QueryInterface(this->pFontEventsCP, &IID_IConnectionPoint,
|
|
(void**)ppCp);
|
|
} else {
|
|
FIXME("no connection point for %s\n", debugstr_guid(riid));
|
|
return CONNECT_E_NOCONNECTION;
|
|
}
|
|
}
|
|
|
|
static const IConnectionPointContainerVtbl
|
|
OLEFontImpl_IConnectionPointContainer_VTable =
|
|
{
|
|
OLEFontImpl_IConnectionPointContainer_QueryInterface,
|
|
OLEFontImpl_IConnectionPointContainer_AddRef,
|
|
OLEFontImpl_IConnectionPointContainer_Release,
|
|
OLEFontImpl_EnumConnectionPoints,
|
|
OLEFontImpl_FindConnectionPoint
|
|
};
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl implementation of IPersistPropertyBag.
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_QueryInterface(
|
|
IPersistPropertyBag *iface, REFIID riid, LPVOID *ppvObj
|
|
) {
|
|
OLEFontImpl *this = impl_from_IPersistPropertyBag(iface);
|
|
return IFont_QueryInterface(&this->IFont_iface,riid,ppvObj);
|
|
}
|
|
|
|
static ULONG WINAPI OLEFontImpl_IPersistPropertyBag_AddRef(
|
|
IPersistPropertyBag *iface
|
|
) {
|
|
OLEFontImpl *this = impl_from_IPersistPropertyBag(iface);
|
|
return IFont_AddRef(&this->IFont_iface);
|
|
}
|
|
|
|
static ULONG WINAPI OLEFontImpl_IPersistPropertyBag_Release(
|
|
IPersistPropertyBag *iface
|
|
) {
|
|
OLEFontImpl *this = impl_from_IPersistPropertyBag(iface);
|
|
return IFont_Release(&this->IFont_iface);
|
|
}
|
|
|
|
static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_GetClassID(
|
|
IPersistPropertyBag *iface, CLSID *classid
|
|
) {
|
|
FIXME("(%p,%p), stub!\n", iface, classid);
|
|
return E_FAIL;
|
|
}
|
|
|
|
static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_InitNew(
|
|
IPersistPropertyBag *iface
|
|
) {
|
|
FIXME("(%p), stub!\n", iface);
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_Load(
|
|
IPersistPropertyBag *iface, IPropertyBag* pPropBag, IErrorLog* pErrorLog
|
|
) {
|
|
/* (from Visual Basic 6 property bag)
|
|
Name = "MS Sans Serif"
|
|
Size = 13.8
|
|
Charset = 0
|
|
Weight = 400
|
|
Underline = 0 'False
|
|
Italic = 0 'False
|
|
Strikethrough = 0 'False
|
|
*/
|
|
static const WCHAR sAttrName[] = {'N','a','m','e',0};
|
|
static const WCHAR sAttrSize[] = {'S','i','z','e',0};
|
|
static const WCHAR sAttrCharset[] = {'C','h','a','r','s','e','t',0};
|
|
static const WCHAR sAttrWeight[] = {'W','e','i','g','h','t',0};
|
|
static const WCHAR sAttrUnderline[] = {'U','n','d','e','r','l','i','n','e',0};
|
|
static const WCHAR sAttrItalic[] = {'I','t','a','l','i','c',0};
|
|
static const WCHAR sAttrStrikethrough[] = {'S','t','r','i','k','e','t','h','r','o','u','g','h',0};
|
|
OLEFontImpl *this = impl_from_IPersistPropertyBag(iface);
|
|
VARIANT value;
|
|
HRESULT iRes;
|
|
|
|
VariantInit(&value);
|
|
|
|
iRes = IPropertyBag_Read(pPropBag, sAttrName, &value, pErrorLog);
|
|
if (iRes == S_OK)
|
|
{
|
|
iRes = VariantChangeType(&value, &value, 0, VT_BSTR);
|
|
if (iRes == S_OK)
|
|
iRes = IFont_put_Name(&this->IFont_iface, V_BSTR(&value));
|
|
}
|
|
else if (iRes == E_INVALIDARG)
|
|
iRes = S_OK;
|
|
|
|
VariantClear(&value);
|
|
|
|
if (iRes == S_OK) {
|
|
iRes = IPropertyBag_Read(pPropBag, sAttrSize, &value, pErrorLog);
|
|
if (iRes == S_OK)
|
|
{
|
|
iRes = VariantChangeType(&value, &value, 0, VT_CY);
|
|
if (iRes == S_OK)
|
|
iRes = IFont_put_Size(&this->IFont_iface, V_CY(&value));
|
|
}
|
|
else if (iRes == E_INVALIDARG)
|
|
iRes = S_OK;
|
|
|
|
VariantClear(&value);
|
|
}
|
|
|
|
if (iRes == S_OK) {
|
|
iRes = IPropertyBag_Read(pPropBag, sAttrCharset, &value, pErrorLog);
|
|
if (iRes == S_OK)
|
|
{
|
|
iRes = VariantChangeType(&value, &value, 0, VT_I2);
|
|
if (iRes == S_OK)
|
|
iRes = IFont_put_Charset(&this->IFont_iface, V_I2(&value));
|
|
}
|
|
else if (iRes == E_INVALIDARG)
|
|
iRes = S_OK;
|
|
|
|
VariantClear(&value);
|
|
}
|
|
|
|
if (iRes == S_OK) {
|
|
iRes = IPropertyBag_Read(pPropBag, sAttrWeight, &value, pErrorLog);
|
|
if (iRes == S_OK)
|
|
{
|
|
iRes = VariantChangeType(&value, &value, 0, VT_I2);
|
|
if (iRes == S_OK)
|
|
iRes = IFont_put_Weight(&this->IFont_iface, V_I2(&value));
|
|
}
|
|
else if (iRes == E_INVALIDARG)
|
|
iRes = S_OK;
|
|
|
|
VariantClear(&value);
|
|
}
|
|
|
|
if (iRes == S_OK) {
|
|
iRes = IPropertyBag_Read(pPropBag, sAttrUnderline, &value, pErrorLog);
|
|
if (iRes == S_OK)
|
|
{
|
|
iRes = VariantChangeType(&value, &value, 0, VT_BOOL);
|
|
if (iRes == S_OK)
|
|
iRes = IFont_put_Underline(&this->IFont_iface, V_BOOL(&value));
|
|
}
|
|
else if (iRes == E_INVALIDARG)
|
|
iRes = S_OK;
|
|
|
|
VariantClear(&value);
|
|
}
|
|
|
|
if (iRes == S_OK) {
|
|
iRes = IPropertyBag_Read(pPropBag, sAttrItalic, &value, pErrorLog);
|
|
if (iRes == S_OK)
|
|
{
|
|
iRes = VariantChangeType(&value, &value, 0, VT_BOOL);
|
|
if (iRes == S_OK)
|
|
iRes = IFont_put_Italic(&this->IFont_iface, V_BOOL(&value));
|
|
}
|
|
else if (iRes == E_INVALIDARG)
|
|
iRes = S_OK;
|
|
|
|
VariantClear(&value);
|
|
}
|
|
|
|
if (iRes == S_OK) {
|
|
iRes = IPropertyBag_Read(pPropBag, sAttrStrikethrough, &value, pErrorLog);
|
|
if (iRes == S_OK)
|
|
{
|
|
iRes = VariantChangeType(&value, &value, 0, VT_BOOL);
|
|
if (iRes == S_OK)
|
|
IFont_put_Strikethrough(&this->IFont_iface, V_BOOL(&value));
|
|
}
|
|
else if (iRes == E_INVALIDARG)
|
|
iRes = S_OK;
|
|
|
|
VariantClear(&value);
|
|
}
|
|
|
|
if (FAILED(iRes))
|
|
WARN("-- 0x%08x\n", iRes);
|
|
return iRes;
|
|
}
|
|
|
|
static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_Save(
|
|
IPersistPropertyBag *iface, IPropertyBag* pPropBag, BOOL fClearDirty,
|
|
BOOL fSaveAllProperties
|
|
) {
|
|
FIXME("(%p,%p,%d,%d), stub!\n", iface, pPropBag, fClearDirty, fSaveAllProperties);
|
|
return E_FAIL;
|
|
}
|
|
|
|
static const IPersistPropertyBagVtbl OLEFontImpl_IPersistPropertyBag_VTable =
|
|
{
|
|
OLEFontImpl_IPersistPropertyBag_QueryInterface,
|
|
OLEFontImpl_IPersistPropertyBag_AddRef,
|
|
OLEFontImpl_IPersistPropertyBag_Release,
|
|
|
|
OLEFontImpl_IPersistPropertyBag_GetClassID,
|
|
OLEFontImpl_IPersistPropertyBag_InitNew,
|
|
OLEFontImpl_IPersistPropertyBag_Load,
|
|
OLEFontImpl_IPersistPropertyBag_Save
|
|
};
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl implementation of IPersistStreamInit.
|
|
*/
|
|
static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_QueryInterface(
|
|
IPersistStreamInit *iface, REFIID riid, LPVOID *ppvObj
|
|
) {
|
|
OLEFontImpl *this = impl_from_IPersistStreamInit(iface);
|
|
return IFont_QueryInterface(&this->IFont_iface,riid,ppvObj);
|
|
}
|
|
|
|
static ULONG WINAPI OLEFontImpl_IPersistStreamInit_AddRef(
|
|
IPersistStreamInit *iface
|
|
) {
|
|
OLEFontImpl *this = impl_from_IPersistStreamInit(iface);
|
|
return IFont_AddRef(&this->IFont_iface);
|
|
}
|
|
|
|
static ULONG WINAPI OLEFontImpl_IPersistStreamInit_Release(
|
|
IPersistStreamInit *iface
|
|
) {
|
|
OLEFontImpl *this = impl_from_IPersistStreamInit(iface);
|
|
return IFont_Release(&this->IFont_iface);
|
|
}
|
|
|
|
static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_GetClassID(
|
|
IPersistStreamInit *iface, CLSID *classid
|
|
) {
|
|
FIXME("(%p,%p), stub!\n", iface, classid);
|
|
return E_FAIL;
|
|
}
|
|
|
|
static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_IsDirty(
|
|
IPersistStreamInit *iface
|
|
) {
|
|
FIXME("(%p), stub!\n", iface);
|
|
return E_FAIL;
|
|
}
|
|
|
|
static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_Load(
|
|
IPersistStreamInit *iface, LPSTREAM pStm
|
|
) {
|
|
FIXME("(%p,%p), stub!\n", iface, pStm);
|
|
return E_FAIL;
|
|
}
|
|
|
|
static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_Save(
|
|
IPersistStreamInit *iface, LPSTREAM pStm, BOOL fClearDirty
|
|
) {
|
|
FIXME("(%p,%p,%d), stub!\n", iface, pStm, fClearDirty);
|
|
return E_FAIL;
|
|
}
|
|
|
|
static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_GetSizeMax(
|
|
IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize
|
|
) {
|
|
FIXME("(%p,%p), stub!\n", iface, pcbSize);
|
|
return E_FAIL;
|
|
}
|
|
|
|
static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_InitNew(
|
|
IPersistStreamInit *iface
|
|
) {
|
|
FIXME("(%p), stub!\n", iface);
|
|
return S_OK;
|
|
}
|
|
|
|
static const IPersistStreamInitVtbl OLEFontImpl_IPersistStreamInit_VTable =
|
|
{
|
|
OLEFontImpl_IPersistStreamInit_QueryInterface,
|
|
OLEFontImpl_IPersistStreamInit_AddRef,
|
|
OLEFontImpl_IPersistStreamInit_Release,
|
|
|
|
OLEFontImpl_IPersistStreamInit_GetClassID,
|
|
OLEFontImpl_IPersistStreamInit_IsDirty,
|
|
OLEFontImpl_IPersistStreamInit_Load,
|
|
OLEFontImpl_IPersistStreamInit_Save,
|
|
OLEFontImpl_IPersistStreamInit_GetSizeMax,
|
|
OLEFontImpl_IPersistStreamInit_InitNew
|
|
};
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_Construct
|
|
*
|
|
* This method will construct a new instance of the OLEFontImpl
|
|
* class.
|
|
*
|
|
* The caller of this method must release the object when it's
|
|
* done with it.
|
|
*/
|
|
static OLEFontImpl* OLEFontImpl_Construct(const FONTDESC *fontDesc)
|
|
{
|
|
OLEFontImpl* newObject;
|
|
|
|
newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(OLEFontImpl));
|
|
|
|
if (newObject==0)
|
|
return newObject;
|
|
|
|
newObject->IFont_iface.lpVtbl = &OLEFontImpl_VTable;
|
|
newObject->IDispatch_iface.lpVtbl = &OLEFontImpl_IDispatch_VTable;
|
|
newObject->IPersistStream_iface.lpVtbl = &OLEFontImpl_IPersistStream_VTable;
|
|
newObject->IConnectionPointContainer_iface.lpVtbl = &OLEFontImpl_IConnectionPointContainer_VTable;
|
|
newObject->IPersistPropertyBag_iface.lpVtbl = &OLEFontImpl_IPersistPropertyBag_VTable;
|
|
newObject->IPersistStreamInit_iface.lpVtbl = &OLEFontImpl_IPersistStreamInit_VTable;
|
|
|
|
newObject->ref = 1;
|
|
|
|
newObject->description.cbSizeofstruct = sizeof(FONTDESC);
|
|
newObject->description.lpstrName = strdupW(fontDesc->lpstrName);
|
|
newObject->description.cySize = fontDesc->cySize;
|
|
newObject->description.sWeight = fontDesc->sWeight;
|
|
newObject->description.sCharset = fontDesc->sCharset;
|
|
newObject->description.fItalic = fontDesc->fItalic;
|
|
newObject->description.fUnderline = fontDesc->fUnderline;
|
|
newObject->description.fStrikethrough = fontDesc->fStrikethrough;
|
|
|
|
newObject->gdiFont = 0;
|
|
newObject->dirty = TRUE;
|
|
newObject->cyLogical = GetDeviceCaps(get_dc(), LOGPIXELSY);
|
|
newObject->cyHimetric = 2540L;
|
|
newObject->pPropertyNotifyCP = NULL;
|
|
newObject->pFontEventsCP = NULL;
|
|
|
|
CreateConnectionPoint((IUnknown*)&newObject->IFont_iface, &IID_IPropertyNotifySink, &newObject->pPropertyNotifyCP);
|
|
CreateConnectionPoint((IUnknown*)&newObject->IFont_iface, &IID_IFontEventsDisp, &newObject->pFontEventsCP);
|
|
|
|
if (!newObject->pPropertyNotifyCP || !newObject->pFontEventsCP)
|
|
{
|
|
OLEFontImpl_Destroy(newObject);
|
|
return NULL;
|
|
}
|
|
|
|
InterlockedIncrement(&ifont_cnt);
|
|
|
|
TRACE("returning %p\n", newObject);
|
|
return newObject;
|
|
}
|
|
|
|
/************************************************************************
|
|
* OLEFontImpl_Destroy
|
|
*
|
|
* This method is called by the Release method when the reference
|
|
* count goes down to 0. It will free all resources used by
|
|
* this object.
|
|
*/
|
|
static void OLEFontImpl_Destroy(OLEFontImpl* fontDesc)
|
|
{
|
|
TRACE("(%p)\n", fontDesc);
|
|
|
|
HeapFree(GetProcessHeap(), 0, fontDesc->description.lpstrName);
|
|
|
|
if (fontDesc->pPropertyNotifyCP)
|
|
IConnectionPoint_Release(fontDesc->pPropertyNotifyCP);
|
|
if (fontDesc->pFontEventsCP)
|
|
IConnectionPoint_Release(fontDesc->pFontEventsCP);
|
|
|
|
HeapFree(GetProcessHeap(), 0, fontDesc);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* StdFont ClassFactory
|
|
*/
|
|
typedef struct
|
|
{
|
|
/* IUnknown fields */
|
|
IClassFactory IClassFactory_iface;
|
|
LONG ref;
|
|
} IClassFactoryImpl;
|
|
|
|
static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface)
|
|
{
|
|
return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface);
|
|
}
|
|
|
|
static HRESULT WINAPI
|
|
SFCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
|
|
IClassFactoryImpl *This = impl_from_IClassFactory(iface);
|
|
|
|
FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
static ULONG WINAPI
|
|
SFCF_AddRef(LPCLASSFACTORY iface) {
|
|
IClassFactoryImpl *This = impl_from_IClassFactory(iface);
|
|
return InterlockedIncrement(&This->ref);
|
|
}
|
|
|
|
static ULONG WINAPI SFCF_Release(LPCLASSFACTORY iface) {
|
|
IClassFactoryImpl *This = impl_from_IClassFactory(iface);
|
|
/* static class, won't be freed */
|
|
return InterlockedDecrement(&This->ref);
|
|
}
|
|
|
|
static HRESULT WINAPI SFCF_CreateInstance(
|
|
LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
|
|
) {
|
|
return OleCreateFontIndirect(NULL,riid,ppobj);
|
|
|
|
}
|
|
|
|
static HRESULT WINAPI SFCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
|
|
IClassFactoryImpl *This = impl_from_IClassFactory(iface);
|
|
FIXME("(%p)->(%d),stub!\n",This,dolock);
|
|
return S_OK;
|
|
}
|
|
|
|
static const IClassFactoryVtbl SFCF_Vtbl = {
|
|
SFCF_QueryInterface,
|
|
SFCF_AddRef,
|
|
SFCF_Release,
|
|
SFCF_CreateInstance,
|
|
SFCF_LockServer
|
|
};
|
|
static IClassFactoryImpl STDFONT_CF = {{&SFCF_Vtbl}, 1 };
|
|
|
|
void _get_STDFONT_CF(LPVOID *ppv) { *ppv = &STDFONT_CF; }
|