+#include "wx/scopeguard.h"
+#include "wx/tokenzr.h"
+
+// ----------------------------------------------------------------------------
+// constants
+// ----------------------------------------------------------------------------
+
+// the mask used to extract the pitch from LOGFONT::lfPitchAndFamily field
+static const int PITCH_MASK = FIXED_PITCH | VARIABLE_PITCH;
+
+// ----------------------------------------------------------------------------
+// wxFontRefData - the internal description of the font
+// ----------------------------------------------------------------------------
+
+class WXDLLEXPORT wxFontRefData: public wxGDIRefData
+{
+public:
+ // constructors
+ wxFontRefData()
+ {
+ Init(-1, wxSize(0,0), false, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL,
+ wxFONTWEIGHT_NORMAL, false, false, wxEmptyString,
+ wxFONTENCODING_DEFAULT);
+ }
+
+ wxFontRefData(int size,
+ const wxSize& pixelSize,
+ bool sizeUsingPixels,
+ wxFontFamily family,
+ wxFontStyle style,
+ wxFontWeight weight,
+ bool underlined,
+ bool strikethrough,
+ const wxString& faceName,
+ wxFontEncoding encoding)
+ {
+ Init(size, pixelSize, sizeUsingPixels, family, style, weight,
+ underlined, strikethrough, faceName, encoding);
+ }
+
+ wxFontRefData(const wxNativeFontInfo& info, WXHFONT hFont = 0)
+ {
+ Init(info, hFont);
+ }
+
+ wxFontRefData(const wxFontRefData& data) : wxGDIRefData()
+ {
+ Init(data.m_nativeFontInfo);
+ }
+
+ virtual ~wxFontRefData();
+
+ // operations
+ bool Alloc();
+
+ void Free();
+
+ // all wxFont accessors
+ int GetPointSize() const
+ {
+ return m_nativeFontInfo.GetPointSize();
+ }
+
+ wxSize GetPixelSize() const
+ {
+ return m_nativeFontInfo.GetPixelSize();
+ }
+
+ bool IsUsingSizeInPixels() const
+ {
+ return m_sizeUsingPixels;
+ }
+
+ wxFontFamily GetFamily() const
+ {
+ return m_nativeFontInfo.GetFamily();
+ }
+
+ wxFontStyle GetStyle() const
+ {
+ return m_nativeFontInfo.GetStyle();
+ }
+
+ wxFontWeight GetWeight() const
+ {
+ return m_nativeFontInfo.GetWeight();
+ }
+
+ bool GetUnderlined() const
+ {
+ return m_nativeFontInfo.GetUnderlined();
+ }
+
+ bool GetStrikethrough() const
+ {
+ return m_nativeFontInfo.GetStrikethrough();
+ }
+
+ wxString GetFaceName() const
+ {
+ wxString facename = m_nativeFontInfo.GetFaceName();
+ if ( facename.empty() )
+ {
+ facename = GetMSWFaceName();
+ if ( !facename.empty() )
+ {
+ // cache the face name, it shouldn't change unless the family
+ // does and wxNativeFontInfo::SetFamily() resets the face name
+ const_cast<wxFontRefData *>(this)->SetFaceName(facename);
+ }
+ }
+
+ return facename;
+ }
+
+ wxFontEncoding GetEncoding() const
+ {
+ return m_nativeFontInfo.GetEncoding();
+ }
+
+ WXHFONT GetHFONT() const
+ {
+ AllocIfNeeded();
+
+ return (WXHFONT)m_hFont;
+ }
+
+ bool HasHFONT() const
+ {
+ return m_hFont != 0;
+ }
+
+ // ... and setters: notice that all of them invalidate the currently
+ // allocated HFONT, if any, so that the next call to GetHFONT() recreates a
+ // new one
+ void SetPointSize(int pointSize)
+ {
+ Free();
+
+ m_nativeFontInfo.SetPointSize(pointSize);
+ m_sizeUsingPixels = false;
+ }
+
+ void SetPixelSize(const wxSize& pixelSize)
+ {
+ wxCHECK_RET( pixelSize.GetWidth() >= 0, "negative font width" );
+ wxCHECK_RET( pixelSize.GetHeight() != 0, "zero font height" );
+
+ Free();
+
+ m_nativeFontInfo.SetPixelSize(pixelSize);
+ m_sizeUsingPixels = true;
+ }
+
+ void SetFamily(wxFontFamily family)
+ {
+ Free();
+
+ m_nativeFontInfo.SetFamily(family);
+ }
+
+ void SetStyle(wxFontStyle style)
+ {
+ Free();
+
+ m_nativeFontInfo.SetStyle(style);
+ }
+
+ void SetWeight(wxFontWeight weight)
+ {
+ Free();
+
+ m_nativeFontInfo.SetWeight(weight);
+ }
+
+ bool SetFaceName(const wxString& faceName)
+ {
+ Free();
+
+ return m_nativeFontInfo.SetFaceName(faceName);
+ }
+
+ void SetUnderlined(bool underlined)
+ {
+ Free();
+
+ m_nativeFontInfo.SetUnderlined(underlined);
+ }
+
+ void SetStrikethrough(bool strikethrough)
+ {
+ Free();
+
+ m_nativeFontInfo.SetStrikethrough(strikethrough);
+ }
+
+ void SetEncoding(wxFontEncoding encoding)
+ {
+ Free();
+
+ m_nativeFontInfo.SetEncoding(encoding);
+ }
+
+ const wxNativeFontInfo& GetNativeFontInfo() const
+ {
+ // we need to create the font now to get the corresponding LOGFONT if
+ // it hadn't been done yet
+ AllocIfNeeded();
+
+ // ensure that we have a valid face name in our font information:
+ // GetFaceName() will try to retrieve it from our HFONT and save it if
+ // it was successful
+ (void)GetFaceName();
+
+ return m_nativeFontInfo;
+ }
+
+ void SetNativeFontInfo(const wxNativeFontInfo& nativeFontInfo)
+ {
+ Free();
+
+ m_nativeFontInfo = nativeFontInfo;
+ }
+
+protected:
+ // common part of all ctors
+ void Init(int size,
+ const wxSize& pixelSize,
+ bool sizeUsingPixels,
+ wxFontFamily family,
+ wxFontStyle style,
+ wxFontWeight weight,
+ bool underlined,
+ bool strikethrough,
+ const wxString& faceName,
+ wxFontEncoding encoding);
+
+ void Init(const wxNativeFontInfo& info, WXHFONT hFont = 0);
+
+ void AllocIfNeeded() const
+ {
+ if ( !m_hFont )
+ const_cast<wxFontRefData *>(this)->Alloc();
+ }
+
+ // retrieve the face name really being used by the font: this is used to
+ // get the face name selected by the system when we don't specify it (but
+ // use just the family for example)
+ wxString GetMSWFaceName() const
+ {
+ ScreenHDC hdc;
+ SelectInHDC selectFont(hdc, (HFONT)GetHFONT());
+
+ UINT otmSize = GetOutlineTextMetrics(hdc, 0, NULL);
+ if ( !otmSize )
+ {
+ wxLogLastError("GetOutlineTextMetrics(NULL)");
+ return wxString();
+ }
+
+ OUTLINETEXTMETRIC * const
+ otm = static_cast<OUTLINETEXTMETRIC *>(malloc(otmSize));
+ wxON_BLOCK_EXIT1( free, otm );
+
+ otm->otmSize = otmSize;
+ if ( !GetOutlineTextMetrics(hdc, otmSize, otm) )
+ {
+ wxLogLastError("GetOutlineTextMetrics()");
+ return wxString();
+ }
+
+ // in spite of its type, the otmpFamilyName field of OUTLINETEXTMETRIC
+ // gives an offset in _bytes_ of the face (not family!) name from the
+ // struct start while the name itself is an array of TCHARs
+ //
+ // FWIW otmpFaceName contains the same thing as otmpFamilyName followed
+ // by a possible " Italic" or " Bold" or something else suffix
+ return reinterpret_cast<wxChar *>(otm) +
+ wxPtrToUInt(otm->otmpFamilyName)/sizeof(wxChar);
+ }
+
+ // are we using m_nativeFontInfo.lf.lfHeight for point size or pixel size?
+ bool m_sizeUsingPixels;
+
+ // Windows font handle, created on demand in GetHFONT()
+ HFONT m_hFont;
+
+ // Native font info
+ wxNativeFontInfo m_nativeFontInfo;
+};
+
+#define M_FONTDATA ((wxFontRefData*)m_refData)
+
+// ============================================================================
+// implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// wxFontRefData
+// ----------------------------------------------------------------------------
+
+void wxFontRefData::Init(int pointSize,
+ const wxSize& pixelSize,
+ bool sizeUsingPixels,
+ wxFontFamily family,
+ wxFontStyle style,
+ wxFontWeight weight,
+ bool underlined,
+ bool strikethrough,
+ const wxString& faceName,
+ wxFontEncoding encoding)
+{
+ m_hFont = NULL;
+
+ m_sizeUsingPixels = sizeUsingPixels;
+ if ( m_sizeUsingPixels )
+ SetPixelSize(pixelSize);
+ else
+ SetPointSize(pointSize);
+
+ SetStyle(style);
+ SetWeight(weight);
+ SetUnderlined(underlined);
+ SetStrikethrough(strikethrough);
+
+ // set the family/facename
+ SetFamily(family);
+ if ( !faceName.empty() )
+ SetFaceName(faceName);
+
+ // deal with encoding now (it may override the font family and facename
+ // so do it after setting them)
+ SetEncoding(encoding);
+}
+
+void wxFontRefData::Init(const wxNativeFontInfo& info, WXHFONT hFont)
+{
+ // hFont may be zero, or it be passed in case we really want to
+ // use the exact font created in the underlying system
+ // (for example where we can't guarantee conversion from HFONT
+ // to LOGFONT back to HFONT)
+ m_hFont = (HFONT)hFont;
+ m_nativeFontInfo = info;
+
+ // TODO: m_sizeUsingPixels?
+}
+
+wxFontRefData::~wxFontRefData()
+{
+ Free();
+}
+
+bool wxFontRefData::Alloc()
+{
+ m_hFont = ::CreateFontIndirect(&m_nativeFontInfo.lf);
+ if ( !m_hFont )
+ {
+ wxLogLastError(wxT("CreateFont"));
+ return false;
+ }
+
+ return true;
+}
+
+void wxFontRefData::Free()
+{
+ if ( m_hFont )
+ {
+ if ( !::DeleteObject(m_hFont) )
+ {
+ wxLogLastError(wxT("DeleteObject(font)"));
+ }
+
+ m_hFont = 0;
+ }
+}
+
+// ----------------------------------------------------------------------------
+// wxNativeFontInfo
+// ----------------------------------------------------------------------------
+
+void wxNativeFontInfo::Init()
+{
+ wxZeroMemory(lf);
+
+ // we get better font quality if we use PROOF_QUALITY instead of
+ // DEFAULT_QUALITY but some fonts (e.g. "Terminal 6pt") are not available
+ // then so we allow to set a global option to choose between quality and
+ // wider font selection
+#ifdef __WXWINCE__
+ lf.lfQuality = CLEARTYPE_QUALITY;
+#else
+ lf.lfQuality = wxSystemOptions::GetOptionInt("msw.font.no-proof-quality")
+ ? DEFAULT_QUALITY
+ : PROOF_QUALITY;