1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxFont class
4 // Author: David Webster
8 // Copyright: (c) David Webster
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
21 // For compilers that support precompilation, includes "wx.h".
22 #include "wx/wxprec.h"
33 #include "wx/os2/private.h"
35 #include "wx/fontutil.h"
36 #include "wx/fontmap.h"
38 #include "wx/tokenzr.h"
40 IMPLEMENT_DYNAMIC_CLASS(wxFont
, wxGDIObject
)
42 // ----------------------------------------------------------------------------
43 // wxFontRefData - the internal description of the font
44 // ----------------------------------------------------------------------------
46 class WXDLLEXPORT wxFontRefData
: public wxGDIRefData
51 Init(-1, wxFONTFAMILY_DEFAULT
, wxFONTSTYLE_NORMAL
, wxFONTWEIGHT_NORMAL
, FALSE
,
52 "", wxFONTENCODING_DEFAULT
);
55 wxFontRefData( int nSize
60 ,const wxString
& sFaceName
61 ,wxFontEncoding vEncoding
74 wxFontRefData( const wxNativeFontInfo
& rInfo
85 wxFontRefData(const wxFontRefData
& rData
)
87 Init( rData
.m_nPointSize
95 m_nFontId
= rData
.m_nFontId
;
98 virtual ~wxFontRefData();
103 bool Alloc(wxFont
* pFont
);
107 // All wxFont accessors
109 inline int GetPointSize(void) const
111 return m_bNativeFontInfoOk ? m_vNativeFontInfo
.GetPointSize()
115 inline int GetFamily(void) const
120 inline int GetStyle(void) const
122 return m_bNativeFontInfoOk ? m_vNativeFontInfo
.GetStyle()
126 inline int GetWeight(void) const
128 return m_bNativeFontInfoOk ? m_vNativeFontInfo
.GetWeight()
132 inline bool GetUnderlined(void) const
134 return m_bNativeFontInfoOk ? m_vNativeFontInfo
.GetUnderlined()
138 inline wxString
GetFaceName(void) const
142 if (m_bNativeFontInfoOk
)
143 sFaceName
= m_vNativeFontInfo
.GetFaceName();
145 sFaceName
= m_sFaceName
;
150 inline wxFontEncoding
GetEncoding(void) const
152 return m_bNativeFontInfoOk ? m_vNativeFontInfo
.GetEncoding()
156 inline WXHFONT
GetHFONT(void) const { return m_hFont
; }
157 inline HPS
GetPS(void) const { return m_hPS
; }
158 inline PFONTMETRICS
GetFM(void) const { return m_pFM
; }
159 inline int GetNumFonts(void) const { return m_nNumFonts
; }
162 inline void SetPointSize(int nPointSize
)
164 if (m_bNativeFontInfoOk
)
165 m_vNativeFontInfo
.SetPointSize(nPointSize
);
167 m_nPointSize
= nPointSize
;
170 inline void SetFamily(int nFamily
)
175 inline void SetStyle(int nStyle
)
177 if (m_bNativeFontInfoOk
)
178 m_vNativeFontInfo
.SetStyle((wxFontStyle
)nStyle
);
183 inline void SetWeight(int nWeight
)
185 if (m_bNativeFontInfoOk
)
186 m_vNativeFontInfo
.SetWeight((wxFontWeight
)nWeight
);
191 inline void SetFaceName(const wxString
& sFaceName
)
193 if (m_bNativeFontInfoOk
)
194 m_vNativeFontInfo
.SetFaceName(sFaceName
);
196 m_sFaceName
= sFaceName
;
199 inline void SetUnderlined(bool bUnderlined
)
201 if (m_bNativeFontInfoOk
)
202 m_vNativeFontInfo
.SetUnderlined(bUnderlined
);
204 m_bUnderlined
= bUnderlined
;
207 inline void SetEncoding(wxFontEncoding vEncoding
)
209 if (m_bNativeFontInfoOk
)
210 m_vNativeFontInfo
.SetEncoding(vEncoding
);
212 m_vEncoding
= vEncoding
;
215 inline void SetPS(HPS hPS
)
220 inline void SetFM(PFONTMETRICS pFM
)
225 inline void SetNumFonts(int nNumFonts
)
227 m_nNumFonts
= nNumFonts
;
231 // Native font info tests
233 bool HasNativeFontInfo() const { return m_bNativeFontInfoOk
; }
235 const wxNativeFontInfo
& GetNativeFontInfo() const
236 { return m_vNativeFontInfo
; }
240 // Common part of all ctors
247 ,const wxString
& rsFaceName
248 ,wxFontEncoding vEncoding
251 void Init( const wxNativeFontInfo
& rInfo
256 // If TRUE, the pointer to the actual font is temporary and SHOULD NOT BE
257 // DELETED by destructor
263 // Font characterstics
270 wxString m_sFaceName
;
271 wxFontEncoding m_vEncoding
;
277 wxNativeFontInfo m_vNativeFontInfo
;
278 bool m_bNativeFontInfoOk
;
281 // Some PM specific stuff
283 PFONTMETRICS m_pFM
; // array of FONTMETRICS structs
284 int m_nNumFonts
; // number of fonts in array
285 HPS m_hPS
; // PS handle this font belongs to
286 FATTRS m_vFattrs
; // Current fattrs struct
287 FACENAMEDESC m_vFname
; // Current facename struct
288 bool m_bInternalPS
; // Internally generated PS?
289 }; // end of CLASS wxFontRefData
291 // ============================================================================
293 // ============================================================================
295 // ----------------------------------------------------------------------------
297 // ----------------------------------------------------------------------------
299 void wxFontRefData
::Init(
305 , const wxString
& rsFaceName
306 , wxFontEncoding vEncoding
310 m_nPointSize
= nPointSize
;
314 m_bUnderlined
= bUnderlined
;
315 m_sFaceName
= rsFaceName
;
316 m_vEncoding
= vEncoding
;
319 m_bNativeFontInfoOk
= FALSE
;
322 m_bTemporary
= FALSE
;
323 m_pFM
= (PFONTMETRICS
)NULL
;
326 } // end of wxFontRefData::Init
328 void wxFontRefData
::Init(
329 const wxNativeFontInfo
& rInfo
330 , WXHFONT hFont
//this is the FontId -- functions as the hFont for OS/2
331 , WXHANDLE hPS
// Presentation Space we are using
335 // hFont may be zero, or it be passed in case we really want to
336 // use the exact font created in the underlying system
337 // (for example where we can't guarantee conversion from HFONT
338 // to LOGFONT back to HFONT)
341 m_nFontId
= (int)hFont
;
343 m_bNativeFontInfoOk
= TRUE
;
344 m_vNativeFontInfo
= rInfo
;
346 if (m_hPS
== NULLHANDLE
)
348 m_hPS
= ::WinGetPS(HWND_DESKTOP
);
355 wxFontRefData
::~wxFontRefData()
360 bool wxFontRefData
::Alloc(
368 PFONTMETRICS pFM
= NULL
;
370 if (!m_bNativeFontInfoOk
)
372 wxFillLogFont( &m_vNativeFontInfo
.fa
373 ,&m_vNativeFontInfo
.fn
380 m_bNativeFontInfoOk
= TRUE
;
383 if((lRc
= ::GpiCreateLogFont( m_hPS
386 ,&m_vNativeFontInfo
.fa
389 m_hFont
= (WXHFONT
)flId
;
394 wxLogLastError("CreateFont");
397 ::GpiSetCharSet(m_hPS
, flId
); // sets font for presentation space
398 ::GpiQueryFontMetrics(m_hPS
, sizeof(FONTMETRICS
), &m_vNativeFontInfo
.fm
);
401 // Set refData members with the results
403 memcpy(&m_vFattrs
, &m_vNativeFontInfo
.fa
, sizeof(m_vFattrs
));
404 memcpy(&m_vFname
, &m_vNativeFontInfo
.fn
, sizeof(m_vFname
));
405 m_nPointSize
= m_vNativeFontInfo
.fm
.lEmHeight
;
406 if (strcmp(m_vNativeFontInfo
.fa
.szFacename
, "Times New Roman") == 0)
408 else if (strcmp(m_vNativeFontInfo
.fa
.szFacename
, "Tms Rmn") == 0)
410 else if (strcmp(m_vNativeFontInfo
.fa
.szFacename
, "WarpSans") == 0)
412 else if (strcmp(m_vNativeFontInfo
.fa
.szFacename
, "Helvitica") == 0)
414 else if (strcmp(m_vNativeFontInfo
.fa
.szFacename
, "Helv") == 0)
416 else if (strcmp(m_vNativeFontInfo
.fa
.szFacename
, "Script") == 0)
417 m_nFamily
= wxSCRIPT
;
418 else if (strcmp(m_vNativeFontInfo
.fa
.szFacename
, "Courier New") == 0)
419 m_nFamily
= wxTELETYPE
;
420 else if (strcmp(m_vNativeFontInfo
.fa
.szFacename
, "Courier") == 0)
421 m_nFamily
= wxTELETYPE
;
422 else if (strcmp(m_vNativeFontInfo
.fa
.szFacename
, "System VIO") == 0)
423 m_nFamily
= wxMODERN
;
427 if (m_vNativeFontInfo
.fa
.fsSelection
& FATTR_SEL_ITALIC
)
428 m_nStyle
= wxFONTSTYLE_ITALIC
;
430 m_nStyle
= wxFONTSTYLE_NORMAL
;
431 switch(m_vNativeFontInfo
.fn
.usWeightClass
)
433 case FWEIGHT_DONT_CARE
:
434 m_nWeight
= wxFONTWEIGHT_NORMAL
;
438 m_nWeight
= wxFONTWEIGHT_NORMAL
;
442 m_nWeight
= wxFONTWEIGHT_LIGHT
;
446 m_nWeight
= wxFONTWEIGHT_BOLD
;
449 case FWEIGHT_ULTRA_BOLD
:
450 m_nWeight
= wxFONTWEIGHT_MAX
;
454 m_nWeight
= wxFONTWEIGHT_NORMAL
;
456 m_bUnderlined
= ((m_vNativeFontInfo
.fa
.fsSelection
& FATTR_SEL_UNDERSCORE
) != 0);
457 m_sFaceName
= m_vNativeFontInfo
.fa
.szFacename
;
458 m_vEncoding
= wxGetFontEncFromCharSet(m_vNativeFontInfo
.fa
.usCodePage
);
461 // We don't actuall keep the font around if using a temporary PS
466 ::GpiDeleteSetId( m_hPS
470 ::WinReleasePS(m_hPS
);
474 // Select the font into the Presentation space
476 ::GpiSetCharSet(m_hPS
, flId
); // sets font for presentation space
478 } // end of wxFontRefData::Alloc
480 void wxFontRefData
::Free()
484 m_pFM
= (PFONTMETRICS
)NULL
;
488 if (!::GpiSetCharSet(m_hPS
, LCID_DEFAULT
))
490 wxLogLastError(wxT("DeleteObject(font)"));
492 ::GpiDeleteSetId(m_hPS
, 1L); /* delete the logical font */
497 ::WinReleasePS(m_hPS
);
499 } // end of wxFontRefData::Free
501 // ----------------------------------------------------------------------------
503 // ----------------------------------------------------------------------------
505 void wxNativeFontInfo
::Init()
507 memset(&fa
, '\0', sizeof(FATTRS
));
508 } // end of wxNativeFontInfo::Init
510 int wxNativeFontInfo
::GetPointSize() const
513 } // end of wxNativeFontInfo::GetPointSize
515 wxFontStyle wxNativeFontInfo
::GetStyle() const
517 return fa
.fsSelection
& FATTR_SEL_ITALIC ? wxFONTSTYLE_ITALIC
: wxFONTSTYLE_NORMAL
;
518 } // end of wxNativeFontInfo::GetStyle
520 wxFontWeight wxNativeFontInfo
::GetWeight() const
522 switch(fn
.usWeightClass
)
524 case FWEIGHT_DONT_CARE
:
525 return wxFONTWEIGHT_NORMAL
;
528 return wxFONTWEIGHT_NORMAL
;
531 return wxFONTWEIGHT_LIGHT
;
534 return wxFONTWEIGHT_BOLD
;
536 case FWEIGHT_ULTRA_BOLD
:
537 return wxFONTWEIGHT_MAX
;
539 return wxFONTWEIGHT_NORMAL
;
540 } // end of wxNativeFontInfo::GetWeight
542 bool wxNativeFontInfo
::GetUnderlined() const
544 return ((fa
.fsSelection
& FATTR_SEL_UNDERSCORE
) != 0);
545 } // end of wxNativeFontInfo::GetUnderlined
547 wxString wxNativeFontInfo
::GetFaceName() const
549 return fm
.szFacename
;
550 } // end of wxNativeFontInfo::GetFaceName
552 wxFontFamily wxNativeFontInfo
::GetFamily() const
557 // Extract family from facename
559 if (strcmp(fa
.szFacename
, "Times New Roman") == 0)
561 else if (strcmp(fa
.szFacename
, "WarpSans") == 0)
563 else if (strcmp(fa
.szFacename
, "Script") == 0)
565 else if (strcmp(fa
.szFacename
, "Courier New") == 0)
569 return (wxFontFamily
)nFamily
;
570 } // end of wxNativeFontInfo::GetFamily
572 wxFontEncoding wxNativeFontInfo
::GetEncoding() const
574 return wxGetFontEncFromCharSet(fa
.usCodePage
);
575 } // end of wxNativeFontInfo::GetEncoding
577 void wxNativeFontInfo
::SetPointSize(
581 fm
.lEmHeight
= (LONG
)nPointsize
;
582 } // end of wxNativeFontInfo::SetPointSize
584 void wxNativeFontInfo
::SetStyle(
591 wxFAIL_MSG( _T("unknown font style") );
594 case wxFONTSTYLE_NORMAL
:
597 case wxFONTSTYLE_ITALIC
:
598 case wxFONTSTYLE_SLANT
:
599 fa
.fsSelection
|= FATTR_SEL_ITALIC
;
602 } // end of wxNativeFontInfo::SetStyle
604 void wxNativeFontInfo
::SetWeight(
611 wxFAIL_MSG( _T("unknown font weight") );
614 case wxFONTWEIGHT_NORMAL
:
615 fn
.usWeightClass
= FWEIGHT_NORMAL
;
618 case wxFONTWEIGHT_LIGHT
:
619 fn
.usWeightClass
= FWEIGHT_LIGHT
;
622 case wxFONTWEIGHT_BOLD
:
623 fn
.usWeightClass
= FWEIGHT_BOLD
;
626 } // end of wxNativeFontInfo::SetWeight
628 void wxNativeFontInfo
::SetUnderlined(
633 fa
.fsSelection
|= FATTR_SEL_UNDERSCORE
;
634 } // end of wxNativeFontInfo::SetUnderlined
636 void wxNativeFontInfo
::SetFaceName(
640 wxStrncpy(fa
.szFacename
, sFacename
, WXSIZEOF(fa
.szFacename
));
641 } // end of wxNativeFontInfo::SetFaceName
643 void wxNativeFontInfo
::SetFamily(
652 sFacename
= _T("Script");
656 sFacename
= _T("Times New Roman");
660 sFacename
= _T("Times New Roman");
665 sFacename
= _T("Courier New");
669 sFacename
= _T("WarpSans");
674 sFacename
= _T("Helv");
677 if (!wxStrlen(fa
.szFacename
) )
679 SetFaceName(sFacename
);
681 } // end of wxNativeFontInfo::SetFamily
683 void wxNativeFontInfo
::SetEncoding(
684 wxFontEncoding eEncoding
687 wxNativeEncodingInfo vInfo
;
689 if ( !wxGetNativeFontEncoding( eEncoding
694 if (wxTheFontMapper
->GetAltForEncoding( eEncoding
698 if (!vInfo
.facename
.empty())
701 // If we have this encoding only in some particular facename, use
702 // the facename - it is better to show the correct characters in a
703 // wrong facename than unreadable text in a correct one
705 SetFaceName(vInfo
.facename
);
709 #endif // wxUSE_FONTMAP
711 // unsupported encoding, replace with the default
715 fa
.usCodePage
= vInfo
.charset
;
716 } // end of wxNativeFontInfo::SetFaceName
718 bool wxNativeFontInfo
::FromString(
719 const wxString
& rsStr
724 wxStringTokenizer
vTokenizer(rsStr
, _T(";"));
729 wxString sToken
= vTokenizer
.GetNextToken();
731 if (sToken
!= _T('0'))
734 sToken
= vTokenizer
.GetNextToken();
735 if (!sToken
.ToLong(&lVal
))
739 sToken
= vTokenizer
.GetNextToken();
740 if (!sToken
.ToLong(&lVal
))
742 fa
.lAveCharWidth
= lVal
;
744 sToken
= vTokenizer
.GetNextToken();
745 if (!sToken
.ToLong(&lVal
))
747 fa
.fsSelection
= (USHORT
)lVal
;
749 sToken
= vTokenizer
.GetNextToken();
750 if (!sToken
.ToLong(&lVal
))
752 fa
.fsType
= (USHORT
)lVal
;
754 sToken
= vTokenizer
.GetNextToken();
755 if (!sToken
.ToLong(&lVal
))
757 fa
.fsFontUse
= (USHORT
)lVal
;
759 sToken
= vTokenizer
.GetNextToken();
760 if (!sToken
.ToLong(&lVal
))
762 fa
.idRegistry
= (USHORT
)lVal
;
764 sToken
= vTokenizer
.GetNextToken();
765 if (!sToken
.ToLong(&lVal
))
767 fa
.usCodePage
= (USHORT
)lVal
;
769 sToken
= vTokenizer
.GetNextToken();
770 if (!sToken
.ToLong(&lVal
))
774 sToken
= vTokenizer
.GetNextToken();
775 if (!sToken
.ToLong(&lVal
))
777 fn
.usWeightClass
= (USHORT
)lVal
;
779 sToken
= vTokenizer
.GetNextToken();
782 wxStrcpy(fa
.szFacename
, sToken
.c_str());
784 } // end of wxNativeFontInfo::FromString
786 wxString wxNativeFontInfo
::ToString() const
790 sStr
.Printf(_T("%d;%ld;%ld;%ld;%d;%d;%d;%d;%d;%ld;%d;%s"),
791 0, // version, in case we want to change the format later
804 } // end of wxNativeFontInfo::ToString
806 // ----------------------------------------------------------------------------
808 // ----------------------------------------------------------------------------
812 } // end of wxFont::Init
815 const wxNativeFontInfo
& rInfo
820 m_refData
= new wxFontRefData( rInfo
825 } // end of wxFont::Create
828 const wxString
& rsFontdesc
831 wxNativeFontInfo vInfo
;
833 if (vInfo
.FromString(rsFontdesc
))
835 } // end of wxFont::wxFont
837 // ----------------------------------------------------------------------------
838 // Constructor for a font. Note that the real construction is done
839 // in wxDC::SetFont, when information is available about scaling etc.
840 // ----------------------------------------------------------------------------
847 , const wxString
& rsFaceName
848 , wxFontEncoding vEncoding
854 // wxDEFAULT is a valid value for the font size too so we must treat it
855 // specially here (otherwise the size would be 70 == wxDEFAULT value)
857 if (nPointSize
== wxDEFAULT
)
859 nPointSize
= wxNORMAL_FONT
->GetPointSize();
861 m_refData
= new wxFontRefData( nPointSize
871 } // end of wxFont::Create
875 } // end of wxFont::~wxFont
877 // ----------------------------------------------------------------------------
878 // real implementation
879 // Boris' Kovalenko comments:
880 // Because OS/2 fonts are associated with PS we can not create the font
881 // here, but we may check that font definition is true
882 // ----------------------------------------------------------------------------
884 bool wxFont
::RealizeResource()
886 if ( GetResourceHandle() )
890 return M_FONTDATA
->Alloc(this);
891 } // end of wxFont::RealizeResource
893 bool wxFont
::FreeResource(
897 if (GetResourceHandle())
903 } // end of wxFont::FreeResource
905 WXHANDLE wxFont
::GetResourceHandle()
908 } // end of wxFont::GetResourceHandle
910 WXHFONT wxFont
::GetHFONT() const
912 return M_FONTDATA ? M_FONTDATA
->GetHFONT() : 0;
913 } // end of wxFont::GetHFONT
915 bool wxFont
::IsFree() const
917 return M_FONTDATA
&& (M_FONTDATA
->GetHFONT() == 0);
918 } // end of wxFont::IsFree
920 void wxFont
::Unshare()
922 // Don't change shared data
925 m_refData
= new wxFontRefData();
929 wxFontRefData
* ref
= new wxFontRefData(*M_FONTDATA
);
933 } // end of wxFont::Unshare
935 // ----------------------------------------------------------------------------
936 // change font attribute: we recreate font when doing it
937 // ----------------------------------------------------------------------------
939 void wxFont
::SetPointSize(
945 M_FONTDATA
->SetPointSize(nPointSize
);
948 } // end of wxFont::SetPointSize
950 void wxFont
::SetFamily(
956 M_FONTDATA
->SetFamily(nFamily
);
959 } // end of wxFont::SetFamily
961 void wxFont
::SetStyle(
967 M_FONTDATA
->SetStyle(nStyle
);
970 } // end of wxFont::SetStyle
972 void wxFont
::SetWeight(
978 M_FONTDATA
->SetWeight(nWeight
);
981 } // end of wxFont::SetWeight
983 void wxFont
::SetFaceName(
984 const wxString
& rsFaceName
989 M_FONTDATA
->SetFaceName(rsFaceName
);
992 } // end of wxFont::SetFaceName
994 void wxFont
::SetUnderlined(
1000 M_FONTDATA
->SetUnderlined(bUnderlined
);
1003 } // end of wxFont::SetUnderlined
1005 void wxFont
::SetEncoding(
1006 wxFontEncoding vEncoding
1011 M_FONTDATA
->SetEncoding(vEncoding
);
1014 } // end of wxFont::SetEncoding
1016 void wxFont
::SetNativeFontInfo(
1017 const wxNativeFontInfo
& rInfo
1024 *M_FONTDATA
= wxFontRefData(rInfo
);
1029 // ----------------------------------------------------------------------------
1031 // ----------------------------------------------------------------------------
1033 int wxFont
::GetPointSize() const
1035 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
1037 return M_FONTDATA
->GetPointSize();
1038 } // end of wxFont::GetPointSize
1040 int wxFont
::GetFamily() const
1042 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
1044 return M_FONTDATA
->GetFamily();
1045 } // end of wxFont::GetFamily
1047 int wxFont
::GetStyle() const
1049 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
1051 return M_FONTDATA
->GetStyle();
1052 } // end of wxFont::GetStyle
1054 int wxFont
::GetWeight() const
1056 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
1058 return M_FONTDATA
->GetWeight();
1061 bool wxFont
::GetUnderlined() const
1063 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid font") );
1065 return M_FONTDATA
->GetUnderlined();
1066 } // end of wxFont::GetUnderlined
1068 wxString wxFont
::GetFaceName() const
1070 wxCHECK_MSG( Ok(), wxT(""), wxT("invalid font") );
1072 return M_FONTDATA
->GetFaceName();
1073 } // end of wxFont::GetFaceName
1075 wxFontEncoding wxFont
::GetEncoding() const
1077 wxCHECK_MSG( Ok(), wxFONTENCODING_DEFAULT
, wxT("invalid font") );
1079 return M_FONTDATA
->GetEncoding();
1080 } // end of wxFont::GetEncoding
1082 wxNativeFontInfo
* wxFont
::GetNativeFontInfo() const
1084 if (M_FONTDATA
->HasNativeFontInfo())
1085 return new wxNativeFontInfo(M_FONTDATA
->GetNativeFontInfo());
1087 } // end of wxFont::GetNativeFontInfo
1090 // Internal use only method to set the FONTMETRICS array
1097 M_FONTDATA
->SetFM(pFM
);
1098 M_FONTDATA
->SetNumFonts(nNumFonts
);
1099 } // end of wxFont::SetFM
1108 M_FONTDATA
->SetPS(hPS
);
1111 } // end of wxFont::SetUnderlined