#endif
#ifndef WX_PRECOMP
- #include <stdio.h>
#include "wx/setup.h"
#include "wx/list.h"
#include "wx/utils.h"
#include "wx/app.h"
#include "wx/font.h"
+ #include "wx/log.h"
#endif // WX_PRECOMP
+#include "wx/fontutil.h"
+#include "wx/tokenzr.h"
+
#include "wx/msw/private.h"
+#include "wx/tokenzr.h"
-#if !USE_SHARED_LIBRARIES
- IMPLEMENT_DYNAMIC_CLASS(wxFont, wxGDIObject)
+IMPLEMENT_DYNAMIC_CLASS(wxFont, wxGDIObject)
- #if wxUSE_PORTABLE_FONTS_IN_MSW
- IMPLEMENT_DYNAMIC_CLASS(wxFontNameDirectory, wxObject)
- #endif
-#endif
+// ----------------------------------------------------------------------------
+// constants
+// ----------------------------------------------------------------------------
+
+// the default font size in points
+static const int wxDEFAULT_FONT_SIZE = 12;
// ----------------------------------------------------------------------------
// wxFontRefData - the internal description of the font
public:
wxFontRefData()
{
- Init(12, wxDEFAULT, wxNORMAL, wxNORMAL, FALSE,
+ Init(wxDEFAULT_FONT_SIZE, wxDEFAULT, wxNORMAL, wxNORMAL, FALSE,
"", wxFONTENCODING_DEFAULT);
}
Init(size, family, style, weight, underlined, faceName, encoding);
}
+ wxFontRefData(const wxNativeFontInfo& info, WXHFONT hFont = 0)
+ {
+ Init(info, hFont);
+ }
+
virtual ~wxFontRefData();
protected:
const wxString& faceName,
wxFontEncoding encoding);
+ void Init(const wxNativeFontInfo& info, WXHFONT hFont = 0);
+
// If TRUE, the pointer to the actual font is temporary and SHOULD NOT BE
// DELETED by destructor
bool m_temporary;
// Windows font handle
WXHFONT m_hFont;
+
+ // Native font info
+ wxNativeFontInfo m_nativeFontInfo;
+ bool m_nativeFontInfoOk;
};
// ============================================================================
m_temporary = FALSE;
m_hFont = 0;
+
+ m_nativeFontInfoOk = FALSE;
+}
+
+void wxFontRefData::Init(const wxNativeFontInfo& info, WXHFONT hFont)
+{
+ // extract family from pitch-and-family
+ int lfFamily = info.lf.lfPitchAndFamily;
+ if ( lfFamily & FIXED_PITCH )
+ lfFamily -= FIXED_PITCH;
+ if ( lfFamily & VARIABLE_PITCH )
+ lfFamily -= VARIABLE_PITCH;
+
+ switch ( lfFamily )
+ {
+ case FF_ROMAN:
+ m_family = wxROMAN;
+ break;
+
+ case FF_SWISS:
+ m_family = wxSWISS;
+ break;
+
+ case FF_SCRIPT:
+ m_family = wxSCRIPT;
+ break;
+
+ case FF_MODERN:
+ m_family = wxMODERN;
+ break;
+
+ case FF_DECORATIVE:
+ m_family = wxDECORATIVE;
+ break;
+
+ default:
+ m_family = wxSWISS;
+ }
+
+ // weight and style
+ switch ( info.lf.lfWeight )
+ {
+ case FW_LIGHT:
+ m_weight = wxLIGHT;
+ break;
+
+ default:
+ case FW_NORMAL:
+ m_weight = wxNORMAL;
+ break;
+
+ case FW_BOLD:
+ m_weight = wxBOLD;
+ break;
+ }
+
+ m_style = info.lf.lfItalic ? wxITALIC : wxNORMAL;
+
+ m_underlined = info.lf.lfUnderline != 0;
+
+ m_faceName = info.lf.lfFaceName;
+
+ int height = abs(info.lf.lfHeight);
+
+ // remember that 1pt = 1/72inch
+ const int ppInch = ::GetDeviceCaps(ScreenHDC(), LOGPIXELSY);
+ m_pointSize = (int) (((72.0*((double)height))/(double) ppInch) + 0.5);
+
+ m_encoding = wxGetFontEncFromCharSet(info.lf.lfCharSet);
+
+ m_fontId = 0;
+ m_temporary = FALSE;
+
+ // 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;
+
+ m_nativeFontInfoOk = TRUE;
+ m_nativeFontInfo = info;
}
wxFontRefData::~wxFontRefData()
{
if ( !::DeleteObject((HFONT) m_hFont) )
{
- wxLogLastError("DeleteObject(font)");
+ wxLogLastError(wxT("DeleteObject(font)"));
}
}
}
+
+// ----------------------------------------------------------------------------
+// wxNativeFontInfo
+// ----------------------------------------------------------------------------
+
+bool wxNativeFontInfo::FromString(const wxString& s)
+{
+ long l;
+
+ wxStringTokenizer tokenizer(s, _T(";"));
+
+ wxString token = tokenizer.GetNextToken();
+ //
+ // Ignore the version for now
+ //
+
+ token = tokenizer.GetNextToken();
+ if ( !token.ToLong(&l) )
+ return FALSE;
+ lf.lfHeight = l;
+
+ token = tokenizer.GetNextToken();
+ if ( !token.ToLong(&l) )
+ return FALSE;
+ lf.lfWidth = l;
+
+ token = tokenizer.GetNextToken();
+ if ( !token.ToLong(&l) )
+ return FALSE;
+ lf.lfEscapement = l;
+
+ token = tokenizer.GetNextToken();
+ if ( !token.ToLong(&l) )
+ return FALSE;
+ lf.lfOrientation = l;
+
+ token = tokenizer.GetNextToken();
+ if ( !token.ToLong(&l) )
+ return FALSE;
+ lf.lfWeight = l;
+
+ token = tokenizer.GetNextToken();
+ if ( !token.ToLong(&l) )
+ return FALSE;
+ lf.lfItalic = (BYTE)l;
+
+ token = tokenizer.GetNextToken();
+ if ( !token.ToLong(&l) )
+ return FALSE;
+ lf.lfUnderline = (BYTE)l;
+
+ token = tokenizer.GetNextToken();
+ if ( !token.ToLong(&l) )
+ return FALSE;
+ lf.lfStrikeOut = (BYTE)l;
+
+ token = tokenizer.GetNextToken();
+ if ( !token.ToLong(&l) )
+ return FALSE;
+ lf.lfCharSet = (BYTE)l;
+
+ token = tokenizer.GetNextToken();
+ if ( !token.ToLong(&l) )
+ return FALSE;
+ lf.lfOutPrecision = (BYTE)l;
+
+ token = tokenizer.GetNextToken();
+ if ( !token.ToLong(&l) )
+ return FALSE;
+ lf.lfClipPrecision = (BYTE)l;
+
+ token = tokenizer.GetNextToken();
+ if ( !token.ToLong(&l) )
+ return FALSE;
+ lf.lfQuality = (BYTE)l;
+
+ token = tokenizer.GetNextToken();
+ if ( !token.ToLong(&l) )
+ return FALSE;
+ lf.lfPitchAndFamily = (BYTE)l;
+
+ token = tokenizer.GetNextToken();
+ if(!token)
+ return FALSE;
+ wxStrcpy(lf.lfFaceName, token.c_str());
+
+ return TRUE;
+}
+
+wxString wxNativeFontInfo::ToString() const
+{
+ wxString s;
+
+ s.Printf(_T("%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%s"),
+ 0, // version, in case we want to change the format later
+ lf.lfHeight,
+ lf.lfWidth,
+ lf.lfEscapement,
+ lf.lfOrientation,
+ lf.lfWeight,
+ lf.lfItalic,
+ lf.lfUnderline,
+ lf.lfStrikeOut,
+ lf.lfCharSet,
+ lf.lfOutPrecision,
+ lf.lfClipPrecision,
+ lf.lfQuality,
+ lf.lfPitchAndFamily,
+ lf.lfFaceName);
+
+ return s;
+}
+
// ----------------------------------------------------------------------------
// wxFont
// ----------------------------------------------------------------------------
void wxFont::Init()
{
- if ( wxTheFontList )
- wxTheFontList->Append(this);
+}
+
+bool wxFont::Create(const wxNativeFontInfo& info, WXHFONT hFont)
+{
+ UnRef();
+
+ m_refData = new wxFontRefData(info, hFont);
+
+ RealizeResource();
+
+ return TRUE;
+}
+
+wxFont::wxFont(const wxString& fontdesc)
+{
+ wxNativeFontInfo info;
+ if ( info.FromString(fontdesc) )
+ (void)Create(info);
}
/* Constructor for a font. Note that the real construction is done
wxFontEncoding encoding)
{
UnRef();
+
+ // wxDEFAULT is a valid value for the font size too so we must treat it
+ // specially here (otherwise the size would be 70 == wxDEFAULT value)
+ if ( pointSize == wxDEFAULT )
+ pointSize = wxDEFAULT_FONT_SIZE;
+
m_refData = new wxFontRefData(pointSize, family, style, weight,
underlined, faceName, encoding);
wxFont::~wxFont()
{
- if ( wxTheFontList )
- wxTheFontList->DeleteObject(this);
}
// ----------------------------------------------------------------------------
{
// VZ: the old code returned FALSE in this case, but it doesn't seem
// to make sense because the font _was_ created
- wxLogDebug(wxT("Calling wxFont::RealizeResource() twice"));
-
return TRUE;
}
- int ff_family = 0;
- wxString ff_face;
-
- switch ( M_FONTDATA->m_family )
+ if(!M_FONTDATA->m_nativeFontInfoOk)
{
- case wxSCRIPT:
- ff_family = FF_SCRIPT ;
- ff_face = wxT("Script") ;
- break ;
-
- case wxDECORATIVE:
- ff_family = FF_DECORATIVE;
- break;
-
- case wxROMAN:
- ff_family = FF_ROMAN;
- ff_face = wxT("Times New Roman") ;
- break;
-
- case wxTELETYPE:
- case wxMODERN:
- ff_family = FF_MODERN;
- ff_face = wxT("Courier New") ;
- break;
-
- case wxSWISS:
- ff_family = FF_SWISS;
- ff_face = wxT("Arial") ;
- break;
-
- case wxDEFAULT:
- default:
- ff_family = FF_SWISS;
- ff_face = wxT("Arial") ;
+ wxFillLogFont(&M_FONTDATA->m_nativeFontInfo.lf, this);
+ M_FONTDATA->m_nativeFontInfoOk = TRUE;
}
- BYTE ff_italic;
- switch ( M_FONTDATA->m_style )
+ M_FONTDATA->m_hFont = (WXHFONT)::CreateFontIndirect(&M_FONTDATA->m_nativeFontInfo.lf);
+ M_FONTDATA->m_faceName = M_FONTDATA->m_nativeFontInfo.lf.lfFaceName;
+ if ( !M_FONTDATA->m_hFont )
{
- case wxITALIC:
- case wxSLANT:
- ff_italic = 1;
- break;
-
- default:
- wxFAIL_MSG(wxT("unknown font slant"));
- // fall through
-
- case wxNORMAL:
- ff_italic = 0;
- }
-
- int ff_weight = 0;
- switch ( M_FONTDATA->m_weight )
- {
- default:
- wxFAIL_MSG(wxT("unknown font weight"));
- // fall through
-
- case wxNORMAL:
- ff_weight = FW_NORMAL;
- break;
-
- case wxLIGHT:
- ff_weight = FW_LIGHT;
- break;
-
- case wxBOLD:
- ff_weight = FW_BOLD;
- break;
- }
-
- const wxChar* pzFace;
- if ( M_FONTDATA->m_faceName.IsEmpty() )
- pzFace = ff_face;
- else
- pzFace = M_FONTDATA->m_faceName ;
-
-#if 0
- /* Always calculate fonts using the screen DC (is this the best strategy?)
- * There may be confusion if a font is selected into a printer
- * DC (say), because the height will be calculated very differently.
- */
- // What sort of display is it?
- int technology = ::GetDeviceCaps(dc, TECHNOLOGY);
-
- int nHeight;
-
- if (technology != DT_RASDISPLAY && technology != DT_RASPRINTER)
- {
- // Have to get screen DC Caps, because a metafile will return 0.
- HDC dc2 = ::GetDC(NULL);
- nHeight = M_FONTDATA->m_pointSize*GetDeviceCaps(dc2, LOGPIXELSY)/72;
- ::ReleaseDC(NULL, dc2);
- }
- else
- {
- nHeight = M_FONTDATA->m_pointSize*GetDeviceCaps(dc, LOGPIXELSY)/72;
- }
-#endif // 0
-
-#if 0
- // Have to get screen DC Caps, because a metafile will return 0.
- HDC dc2 = ::GetDC(NULL);
- ppInch = ::GetDeviceCaps(dc2, LOGPIXELSY);
- ::ReleaseDC(NULL, dc2);
-#endif // 0
-
- // New behaviour: apparently ppInch varies according to Large/Small Fonts
- // setting in Windows. This messes up fonts. So, set ppInch to a constant
- // 96 dpi.
- static const int ppInch = 96;
-
-#if wxFONT_SIZE_COMPATIBILITY
- // Incorrect, but compatible with old wxWindows behaviour
- int nHeight = (M_FONTDATA->m_pointSize*ppInch/72);
-#else
- // Correct for Windows compatibility
- int nHeight = - (M_FONTDATA->m_pointSize*ppInch/72);
-#endif
-
- BYTE ff_underline = M_FONTDATA->m_underlined;
-
- wxFontEncoding encoding = M_FONTDATA->m_encoding;
- if ( encoding == wxFONTENCODING_DEFAULT )
- {
- encoding = wxFont::GetDefaultEncoding();
- }
-
- DWORD charset;
- switch ( encoding )
- {
- case wxFONTENCODING_ISO8859_1:
- case wxFONTENCODING_ISO8859_15:
- case wxFONTENCODING_CP1250:
- charset = ANSI_CHARSET;
- break;
-#if !defined(__WIN16__)
- case wxFONTENCODING_ISO8859_2:
- case wxFONTENCODING_CP1252:
- charset = EASTEUROPE_CHARSET;
- break;
-
- case wxFONTENCODING_ISO8859_4:
- case wxFONTENCODING_ISO8859_10:
- charset = BALTIC_CHARSET;
- break;
-
- case wxFONTENCODING_ISO8859_5:
- case wxFONTENCODING_CP1251:
- charset = RUSSIAN_CHARSET;
- break;
-
- case wxFONTENCODING_ISO8859_6:
- charset = ARABIC_CHARSET;
- break;
-
- case wxFONTENCODING_ISO8859_7:
- charset = GREEK_CHARSET;
- break;
-
- case wxFONTENCODING_ISO8859_8:
- charset = HEBREW_CHARSET;
- break;
-
- case wxFONTENCODING_ISO8859_9:
- charset = TURKISH_CHARSET;
- break;
-
- case wxFONTENCODING_ISO8859_11:
- charset = THAI_CHARSET;
- break;
-#endif // BC++ 16-bit
-
- case wxFONTENCODING_CP437:
- charset = OEM_CHARSET;
- break;
+ wxLogLastError(wxT("CreateFont"));
- default:
- wxFAIL_MSG(wxT("unsupported encoding"));
- // fall through
-
- case wxFONTENCODING_SYSTEM:
- charset = ANSI_CHARSET;
- }
-
- HFONT hFont = ::CreateFont
- (
- nHeight, // height
- 0, // width (choose best)
- 0, // escapement
- 0, // orientation
- ff_weight, // weight
- ff_italic, // italic?
- ff_underline, // underlined?
- 0, // strikeout?
- charset, // charset
- OUT_DEFAULT_PRECIS, // precision
- CLIP_DEFAULT_PRECIS, // clip precision
- PROOF_QUALITY, // quality of match
- DEFAULT_PITCH | // fixed or variable
- ff_family, // family id
- pzFace // face name
- );
-
- M_FONTDATA->m_hFont = (WXHFONT)hFont;
- if ( !hFont )
- {
- wxLogLastError("CreateFont");
+ return FALSE;
}
- return hFont != 0;
+ return TRUE;
}
-bool wxFont::FreeResource(bool force)
+bool wxFont::FreeResource(bool WXUNUSED(force))
{
if ( GetResourceHandle() )
{
if ( !::DeleteObject((HFONT) M_FONTDATA->m_hFont) )
{
- wxLogLastError("DeleteObject(font)");
+ wxLogLastError(wxT("DeleteObject(font)"));
}
M_FONTDATA->m_hFont = 0;
}
WXHANDLE wxFont::GetResourceHandle()
+{
+ return GetHFONT();
+}
+
+WXHFONT wxFont::GetHFONT() const
{
if ( !M_FONTDATA )
return 0;
else
- return (WXHANDLE)M_FONTDATA->m_hFont ;
+ return (WXHANDLE)M_FONTDATA->m_hFont;
}
bool wxFont::IsFree() const
Unshare();
M_FONTDATA->m_pointSize = pointSize;
+ M_FONTDATA->m_nativeFontInfoOk = FALSE;
RealizeResource();
}
Unshare();
M_FONTDATA->m_family = family;
+ M_FONTDATA->m_nativeFontInfoOk = FALSE;
RealizeResource();
}
Unshare();
M_FONTDATA->m_style = style;
+ M_FONTDATA->m_nativeFontInfoOk = FALSE;
RealizeResource();
}
Unshare();
M_FONTDATA->m_weight = weight;
+ M_FONTDATA->m_nativeFontInfoOk = FALSE;
RealizeResource();
}
Unshare();
M_FONTDATA->m_faceName = faceName;
+ M_FONTDATA->m_nativeFontInfoOk = FALSE;
RealizeResource();
}
Unshare();
M_FONTDATA->m_underlined = underlined;
+ M_FONTDATA->m_nativeFontInfoOk = FALSE;
RealizeResource();
}
Unshare();
M_FONTDATA->m_encoding = encoding;
+ M_FONTDATA->m_nativeFontInfoOk = FALSE;
+
+ RealizeResource();
+}
+
+void wxFont::SetNativeFontInfo(const wxNativeFontInfo& info)
+{
+ Unshare();
+
+ FreeResource();
+
+ M_FONTDATA->Init(info);
RealizeResource();
}
int wxFont::GetPointSize() const
{
+ wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
+
return M_FONTDATA->m_pointSize;
}
int wxFont::GetFamily() const
{
+ wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
+
return M_FONTDATA->m_family;
}
int wxFont::GetFontId() const
{
+ wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
+
return M_FONTDATA->m_fontId;
}
int wxFont::GetStyle() const
{
+ wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
+
return M_FONTDATA->m_style;
}
int wxFont::GetWeight() const
{
+ wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
+
return M_FONTDATA->m_weight;
}
bool wxFont::GetUnderlined() const
{
+ wxCHECK_MSG( Ok(), FALSE, wxT("invalid font") );
+
return M_FONTDATA->m_underlined;
}
wxString wxFont::GetFaceName() const
{
- wxString str;
- if ( M_FONTDATA )
- str = M_FONTDATA->m_faceName ;
- return str;
+ wxCHECK_MSG( Ok(), wxT(""), wxT("invalid font") );
+
+ return M_FONTDATA->m_faceName;
}
wxFontEncoding wxFont::GetEncoding() const
{
+ wxCHECK_MSG( Ok(), wxFONTENCODING_DEFAULT, wxT("invalid font") );
+
return M_FONTDATA->m_encoding;
}
+
+wxNativeFontInfo *wxFont::GetNativeFontInfo() const
+{
+ if( M_FONTDATA->m_nativeFontInfoOk )
+ return new wxNativeFontInfo(M_FONTDATA->m_nativeFontInfo);
+
+ return 0;
+}
+