📄 olefont.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
/***********************************************************************
* List of the HFONTs it has given out, with each one having a separate
* ref count.
*/
typedef struct _HFONTItem
{
struct list entry;
/* Reference count for that instance of the class. */
LONG ref;
/* Contain 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 void HFONTItem_Delete(PHFONTItem item)
{
DeleteObject(item->gdiFont);
list_remove(&item->entry);
HeapFree(GetProcessHeap(), 0, item);
}
/***********************************************************************
* 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.
*/
const IFontVtbl* lpVtbl;
const IDispatchVtbl* lpvtblIDispatch;
const IPersistStreamVtbl* lpvtblIPersistStream;
const IConnectionPointContainerVtbl* lpvtblIConnectionPointContainer;
const IPersistPropertyBagVtbl* lpvtblIPersistPropertyBag;
const IPersistStreamInitVtbl* lpvtblIPersistStreamInit;
/*
* 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;
/*
* Size ratio
*/
long cyLogical;
long cyHimetric;
IConnectionPoint *pPropertyNotifyCP;
IConnectionPoint *pFontEventsCP;
};
/*
* Here, I define utility macros to help with the casting of the
* "this" parameter.
* There is a version to accommodate all of the VTables implemented
* by this object.
*/
static inline OLEFontImpl *impl_from_IDispatch( IDispatch *iface )
{
return (OLEFontImpl *)((char*)iface - FIELD_OFFSET(OLEFontImpl, lpvtblIDispatch));
}
static inline OLEFontImpl *impl_from_IPersistStream( IPersistStream *iface )
{
return (OLEFontImpl *)((char*)iface - FIELD_OFFSET(OLEFontImpl, lpvtblIPersistStream));
}
static inline OLEFontImpl *impl_from_IConnectionPointContainer( IConnectionPointContainer *iface )
{
return (OLEFontImpl *)((char*)iface - FIELD_OFFSET(OLEFontImpl, lpvtblIConnectionPointContainer));
}
static inline OLEFontImpl *impl_from_IPersistPropertyBag( IPersistPropertyBag *iface )
{
return (OLEFontImpl *)((char*)iface - FIELD_OFFSET(OLEFontImpl, lpvtblIPersistPropertyBag));
}
static inline OLEFontImpl *impl_from_IPersistStreamInit( IPersistStreamInit *iface )
{
return (OLEFontImpl *)((char*)iface - FIELD_OFFSET(OLEFontImpl, lpvtblIPersistStreamInit));
}
/***********************************************************************
* 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 = 0;
HRESULT hr = S_OK;
TRACE("(%p, %s, %p)\n", lpFontDesc, debugstr_guid(riid), ppvObj);
/*
* Sanity check
*/
if (ppvObj==0)
return E_POINTER;
*ppvObj = 0;
if (!lpFontDesc) {
FONTDESC fd;
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 = 0;
fd.fUnderline = 0;
fd.fStrikethrough = 0;
lpFontDesc = &fd;
}
/*
* Try to construct a new instance of the class.
*/
newFont = OLEFontImpl_Construct(lpFontDesc);
if (newFont == 0)
return E_OUTOFMEMORY;
/*
* Make sure it supports the interface required by the caller.
*/
hr = IFont_QueryInterface((IFont*)newFont, riid, ppvObj);
/*
* Release the reference obtained in the constructor. If
* the QueryInterface was unsuccessful, it will free the class.
*/
IFont_Release((IFont*)newFont);
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->gdiFont = 0;
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, (LPVOID)&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, (LPVOID)&disp);
IDispatch_Invoke(disp, DISPID_FONT_CHANGED, &IID_NULL,
LOCALE_NEUTRAL, INVOKE_FUNC, &dispparams, NULL,
NULL, NULL);
IDispatch_Release(disp);
IUnknown_Release(CD.pUnk);
}
VariantClear(&vararg);
IEnumConnections_Release(pEnum);
}
}
/************************************************************************
* OLEFontImpl_QueryInterface (IUnknown)
*
* See Windows documentation for more details on IUnknown methods.
*/
HRESULT WINAPI OLEFontImpl_QueryInterface(
IFont* iface,
REFIID riid,
void** ppvObject)
{
OLEFontImpl *this = (OLEFontImpl *)iface;
TRACE("(%p)->(%s, %p)\n", this, debugstr_guid(riid), ppvObject);
/*
* Perform a sanity check on the parameters.
*/
if ( (this==0) || (ppvObject==0) )
return E_INVALIDARG;
/*
* Initialize the return parameter.
*/
*ppvObject = 0;
/*
* Compare the riid with the interface IDs implemented by this object.
*/
if (IsEqualGUID(&IID_IUnknown, riid))
*ppvObject = (IFont*)this;
if (IsEqualGUID(&IID_IFont, riid))
*ppvObject = (IFont*)this;
if (IsEqualGUID(&IID_IDispatch, riid))
*ppvObject = (IDispatch*)&(this->lpvtblIDispatch);
if (IsEqualGUID(&IID_IFontDisp, riid))
*ppvObject = (IDispatch*)&(this->lpvtblIDispatch);
if (IsEqualIID(&IID_IPersist, riid) || IsEqualGUID(&IID_IPersistStream, riid))
*ppvObject = (IPersistStream*)&(this->lpvtblIPersistStream);
if (IsEqualGUID(&IID_IConnectionPointContainer, riid))
*ppvObject = (IConnectionPointContainer*)&(this->lpvtblIConnectionPointContainer);
if (IsEqualGUID(&IID_IPersistPropertyBag, riid))
*ppvObject = (IPersistPropertyBag*)&(this->lpvtblIPersistPropertyBag);
if (IsEqualGUID(&IID_IPersistStreamInit, riid))
*ppvObject = (IPersistStreamInit*)&(this->lpvtblIPersistStreamInit);
/*
* Check that we obtained an interface.
*/
if ((*ppvObject)==0)
{
FIXME("() : asking for unsupported interface %s\n",debugstr_guid(riid));
return E_NOINTERFACE;
}
OLEFontImpl_AddRef((IFont*)this);
return S_OK;
}
/************************************************************************
* OLEFontImpl_AddRef (IUnknown)
*
* See Windows documentation for more details on IUnknown methods.
*/
ULONG WINAPI OLEFontImpl_AddRef(
IFont* iface)
{
OLEFontImpl *this = (OLEFontImpl *)iface;
TRACE("(%p)->(ref=%d)\n", this, this->ref);
return InterlockedIncrement(&this->ref);
}
/************************************************************************
* OLEFontImpl_Release (IUnknown)
*
* See Windows documentation for more details on IUnknown methods.
*/
ULONG WINAPI OLEFontImpl_Release(
IFont* iface)
{
OLEFontImpl *this = (OLEFontImpl *)iface;
ULONG ret;
PHFONTItem ptr, next;
TRACE("(%p)->(ref=%d)\n", this, this->ref);
/* Decrease the reference count for current interface */
ret = InterlockedDecrement(&this->ref);
/* If the reference count goes down to 0, destroy. */
if (ret == 0)
{
ULONG fontlist_refs = InterlockedDecrement(&ifont_cnt);
/* Check if all HFONT list refs are zero */
if (fontlist_refs == 0)
{
EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
LIST_FOR_EACH_ENTRY_SAFE(ptr, next, &OLEFontImpl_hFontList, HFONTItem, entry)
HFONTItem_Delete(ptr);
LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
}
OLEFontImpl_Destroy(this);
}
return ret;
}
/************************************************************************
* 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 = (OLEFontImpl *)iface;
TRACE("(%p)->(%p)\n", this, pname);
/*
* Sanity check.
*/
if (pname==0)
return E_POINTER;
if (this->description.lpstrName!=0)
*pname = SysAllocString(this->description.lpstrName);
else
*pname = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -