1/////////////////////////////////////////////////////////////////////////////
2// Name:        src/msw/font.cpp
3// Purpose:     wxFont class
4// Author:      Julian Smart
5// Modified by:
6// Created:     01/02/97
7// RCS-ID:      $Id: font.cpp 48064 2007-08-14 08:51:44Z JS $
8// Copyright:   (c) wxWidgets team
9// Licence:     wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24    #pragma hdrstop
25#endif
26
27#include "wx/font.h"
28
29#ifndef WX_PRECOMP
30    #include "wx/list.h"
31    #include "wx/utils.h"
32    #include "wx/app.h"
33    #include "wx/log.h"
34    #include "wx/encinfo.h"
35#endif // WX_PRECOMP
36
37#include "wx/msw/private.h"
38
39#include "wx/fontutil.h"
40#include "wx/fontmap.h"
41
42#ifndef __WXWINCE__
43    #include "wx/sysopt.h"
44#endif
45
46#include "wx/tokenzr.h"
47
48#if wxUSE_EXTENDED_RTTI
49
50wxBEGIN_ENUM( wxFontFamily )
51    wxENUM_MEMBER( wxDEFAULT )
52    wxENUM_MEMBER( wxDECORATIVE )
53    wxENUM_MEMBER( wxROMAN )
54    wxENUM_MEMBER( wxSCRIPT )
55    wxENUM_MEMBER( wxSWISS )
56    wxENUM_MEMBER( wxMODERN )
57    wxENUM_MEMBER( wxTELETYPE )
58wxEND_ENUM( wxFontFamily )
59
60wxBEGIN_ENUM( wxFontStyle )
61    wxENUM_MEMBER( wxNORMAL )
62    wxENUM_MEMBER( wxITALIC )
63    wxENUM_MEMBER( wxSLANT )
64wxEND_ENUM( wxFontStyle )
65
66wxBEGIN_ENUM( wxFontWeight )
67    wxENUM_MEMBER( wxNORMAL )
68    wxENUM_MEMBER( wxLIGHT )
69    wxENUM_MEMBER( wxBOLD )
70wxEND_ENUM( wxFontWeight )
71
72IMPLEMENT_DYNAMIC_CLASS_WITH_COPY_XTI(wxFont, wxGDIObject,"wx/font.h")
73
74wxBEGIN_PROPERTIES_TABLE(wxFont)
75    wxPROPERTY( Size,int, SetPointSize, GetPointSize, 12 , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
76    wxPROPERTY( Family, int  , SetFamily, GetFamily, (int)wxDEFAULT , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // wxFontFamily
77    wxPROPERTY( Style, int , SetStyle, GetStyle, (int)wxNORMAL , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // wxFontStyle
78    wxPROPERTY( Weight, int , SetWeight, GetWeight, (int)wxNORMAL , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // wxFontWeight
79    wxPROPERTY( Underlined, bool , SetUnderlined, GetUnderlined, false , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
80    wxPROPERTY( Face, wxString , SetFaceName, GetFaceName, EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
81    wxPROPERTY( Encoding, wxFontEncoding , SetEncoding, GetEncoding, wxFONTENCODING_DEFAULT , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
82wxEND_PROPERTIES_TABLE()
83
84wxCONSTRUCTOR_6( wxFont , int , Size , int , Family , int , Style , int , Weight , bool , Underlined , wxString , Face )
85
86wxBEGIN_HANDLERS_TABLE(wxFont)
87wxEND_HANDLERS_TABLE()
88
89#else
90    IMPLEMENT_DYNAMIC_CLASS(wxFont, wxGDIObject)
91#endif
92
93
94// ----------------------------------------------------------------------------
95// constants
96// ----------------------------------------------------------------------------
97
98// the mask used to extract the pitch from LOGFONT::lfPitchAndFamily field
99static const int PITCH_MASK = FIXED_PITCH | VARIABLE_PITCH;
100
101// ----------------------------------------------------------------------------
102// wxFontRefData - the internal description of the font
103// ----------------------------------------------------------------------------
104
105class WXDLLEXPORT wxFontRefData: public wxGDIRefData
106{
107public:
108    // constructors
109    wxFontRefData()
110    {
111        Init(-1, wxSize(0,0), false, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL,
112             wxFONTWEIGHT_NORMAL, false, wxEmptyString,
113             wxFONTENCODING_DEFAULT);
114    }
115
116    wxFontRefData(int size,
117                  const wxSize& pixelSize,
118                  bool sizeUsingPixels,
119                  int family,
120                  int style,
121                  int weight,
122                  bool underlined,
123                  const wxString& faceName,
124                  wxFontEncoding encoding)
125    {
126        Init(size, pixelSize, sizeUsingPixels, family, style, weight,
127             underlined, faceName, encoding);
128    }
129
130    wxFontRefData(const wxNativeFontInfo& info, WXHFONT hFont = 0)
131    {
132        Init(info, hFont);
133    }
134
135    wxFontRefData(const wxFontRefData& data) : wxGDIRefData()
136    {
137        if ( data.m_nativeFontInfoOk )
138        {
139            Init(data.m_nativeFontInfo);
140        }
141        else
142        {
143            Init(data.m_pointSize, data.m_pixelSize, data.m_sizeUsingPixels,
144                 data.m_family, data.m_style, data.m_weight,
145                 data.m_underlined, data.m_faceName, data.m_encoding);
146        }
147    }
148
149    virtual ~wxFontRefData();
150
151    // operations
152    bool Alloc(wxFont *font);
153
154    void Free();
155
156    // all wxFont accessors
157    int GetPointSize() const
158    {
159        return m_nativeFontInfoOk ? m_nativeFontInfo.GetPointSize()
160                                  : m_pointSize;
161    }
162
163    wxSize GetPixelSize() const
164    {
165        return m_nativeFontInfoOk ? m_nativeFontInfo.GetPixelSize()
166                                  : m_pixelSize;
167    }
168
169    bool IsUsingSizeInPixels() const
170    {
171        return m_nativeFontInfoOk ? true : m_sizeUsingPixels;
172    }
173
174    int GetFamily() const
175    {
176        return m_family;
177    }
178
179    int GetStyle() const
180    {
181        return m_nativeFontInfoOk ? m_nativeFontInfo.GetStyle()
182                                  : m_style;
183    }
184
185    int GetWeight() const
186    {
187        return m_nativeFontInfoOk ? m_nativeFontInfo.GetWeight()
188                                  : m_weight;
189    }
190
191    bool GetUnderlined() const
192    {
193        return m_nativeFontInfoOk ? m_nativeFontInfo.GetUnderlined()
194                                  : m_underlined;
195    }
196
197    wxString GetFaceName() const
198    {
199        wxString s;
200        if ( m_nativeFontInfoOk )
201            s = m_nativeFontInfo.GetFaceName();
202        else
203            s = m_faceName;
204
205        return s;
206    }
207
208    wxFontEncoding GetEncoding() const
209    {
210        return m_nativeFontInfoOk ? m_nativeFontInfo.GetEncoding()
211                                  : m_encoding;
212    }
213
214    WXHFONT GetHFONT() const { return m_hFont; }
215
216    // ... and setters
217    void SetPointSize(int pointSize)
218    {
219        if ( m_nativeFontInfoOk )
220        {
221            m_nativeFontInfo.SetPointSize(pointSize);
222        }
223        else
224        {
225            m_pointSize = pointSize;
226            m_sizeUsingPixels = false;
227        }
228    }
229
230    void SetPixelSize(const wxSize& pixelSize)
231    {
232        if ( m_nativeFontInfoOk )
233        {
234            m_nativeFontInfo.SetPixelSize(pixelSize);
235        }
236        else
237        {
238            m_pixelSize = pixelSize;
239            m_sizeUsingPixels = true;
240        }
241    }
242
243    void SetFamily(int family)
244    {
245        m_family = family;
246    }
247
248    void SetStyle(int style)
249    {
250        if ( m_nativeFontInfoOk )
251            m_nativeFontInfo.SetStyle((wxFontStyle)style);
252        else
253            m_style = style;
254    }
255
256    void SetWeight(int weight)
257    {
258        if ( m_nativeFontInfoOk )
259            m_nativeFontInfo.SetWeight((wxFontWeight)weight);
260        else
261            m_weight = weight;
262    }
263
264    bool SetFaceName(const wxString& faceName)
265    {
266        if ( m_nativeFontInfoOk )
267            return m_nativeFontInfo.SetFaceName(faceName);
268
269        m_faceName = faceName;
270        return true;
271    }
272
273    void SetUnderlined(bool underlined)
274    {
275        if ( m_nativeFontInfoOk )
276            m_nativeFontInfo.SetUnderlined(underlined);
277        else
278            m_underlined = underlined;
279    }
280
281    void SetEncoding(wxFontEncoding encoding)
282    {
283        if ( m_nativeFontInfoOk )
284            m_nativeFontInfo.SetEncoding(encoding);
285        else
286            m_encoding = encoding;
287    }
288
289    // native font info tests
290    bool HasNativeFontInfo() const { return m_nativeFontInfoOk; }
291
292    const wxNativeFontInfo& GetNativeFontInfo() const
293        { return m_nativeFontInfo; }
294
295protected:
296    // common part of all ctors
297    void Init(int size,
298              const wxSize& pixelSize,
299              bool sizeUsingPixels,
300              int family,
301              int style,
302              int weight,
303              bool underlined,
304              const wxString& faceName,
305              wxFontEncoding encoding);
306
307    void Init(const wxNativeFontInfo& info, WXHFONT hFont = 0);
308
309    // font characterstics
310    int           m_pointSize;
311    wxSize        m_pixelSize;
312    bool          m_sizeUsingPixels;
313    int           m_family;
314    int           m_style;
315    int           m_weight;
316    bool          m_underlined;
317    wxString      m_faceName;
318    wxFontEncoding m_encoding;
319
320    // Windows font handle
321    WXHFONT       m_hFont;
322
323    // Native font info
324    wxNativeFontInfo m_nativeFontInfo;
325    bool             m_nativeFontInfoOk;
326};
327
328#define M_FONTDATA ((wxFontRefData*)m_refData)
329
330// ============================================================================
331// implementation
332// ============================================================================
333
334// ----------------------------------------------------------------------------
335// wxFontRefData
336// ----------------------------------------------------------------------------
337
338void wxFontRefData::Init(int pointSize,
339                         const wxSize& pixelSize,
340                         bool sizeUsingPixels,
341                         int family,
342                         int style,
343                         int weight,
344                         bool underlined,
345                         const wxString& faceName,
346                         wxFontEncoding encoding)
347{
348    m_style = style;
349    m_pointSize = pointSize == -1 ? wxNORMAL_FONT->GetPointSize() : pointSize;
350    m_pixelSize = pixelSize;
351    m_sizeUsingPixels = sizeUsingPixels;
352    m_family = family;
353    m_style = style;
354    m_weight = weight;
355    m_underlined = underlined;
356    m_faceName = faceName;
357    m_encoding = encoding;
358
359    m_hFont = 0;
360
361    m_nativeFontInfoOk = false;
362}
363
364void wxFontRefData::Init(const wxNativeFontInfo& info, WXHFONT hFont)
365{
366    // hFont may be zero, or it be passed in case we really want to
367    // use the exact font created in the underlying system
368    // (for example where we can't guarantee conversion from HFONT
369    // to LOGFONT back to HFONT)
370    m_hFont = hFont;
371
372    m_nativeFontInfoOk = true;
373    m_nativeFontInfo = info;
374    // This is the best we can do since we don't have the
375    // correct information at this point.
376    m_family = wxSWISS;
377}
378
379wxFontRefData::~wxFontRefData()
380{
381    Free();
382}
383
384bool wxFontRefData::Alloc(wxFont *font)
385{
386    if ( !m_nativeFontInfoOk )
387    {
388        wxFillLogFont(&m_nativeFontInfo.lf, font);
389        m_nativeFontInfoOk = true;
390    }
391
392    HFONT hfont = ::CreateFontIndirect(&m_nativeFontInfo.lf);
393    if ( !hfont )
394    {
395        wxLogLastError(wxT("CreateFont"));
396        return false;
397    }
398
399    m_hFont = (WXHFONT)hfont;
400    return true;
401}
402
403void wxFontRefData::Free()
404{
405    if ( m_hFont )
406    {
407        if ( !::DeleteObject((HFONT) m_hFont) )
408        {
409            wxLogLastError(wxT("DeleteObject(font)"));
410        }
411
412        m_hFont = 0;
413    }
414}
415
416// ----------------------------------------------------------------------------
417// wxNativeFontInfo
418// ----------------------------------------------------------------------------
419
420void wxNativeFontInfo::Init()
421{
422    wxZeroMemory(lf);
423
424    // we get better font quality if we use PROOF_QUALITY instead of
425    // DEFAULT_QUALITY but some fonts (e.g. "Terminal 6pt") are not available
426    // then so we allow to set a global option to choose between quality and
427    // wider font selection
428#ifdef __WXWINCE__
429    lf.lfQuality = CLEARTYPE_QUALITY;
430#else
431    lf.lfQuality = wxSystemOptions::GetOptionInt(_T("msw.font.no-proof-quality"))
432                    ? DEFAULT_QUALITY
433                    : PROOF_QUALITY;
434#endif
435}
436
437int wxNativeFontInfo::GetPointSize() const
438{
439    // FIXME: using the screen here results in incorrect font size calculation
440    //        for printing!
441    const int ppInch = ::GetDeviceCaps(ScreenHDC(), LOGPIXELSY);
442
443    return (int) (((72.0*(double)abs((int) lf.lfHeight)) / (double) ppInch) + 0.5);
444}
445
446wxSize wxNativeFontInfo::GetPixelSize() const
447{
448    wxSize ret;
449    ret.SetHeight(lf.lfHeight);
450    ret.SetWidth(lf.lfWidth);
451    return ret;
452}
453
454wxFontStyle wxNativeFontInfo::GetStyle() const
455{
456    return lf.lfItalic ? wxFONTSTYLE_ITALIC : wxFONTSTYLE_NORMAL;
457}
458
459wxFontWeight wxNativeFontInfo::GetWeight() const
460{
461    if ( lf.lfWeight <= 300 )
462        return wxFONTWEIGHT_LIGHT;
463
464    if ( lf.lfWeight >= 600 )
465        return wxFONTWEIGHT_BOLD;
466
467    return wxFONTWEIGHT_NORMAL;
468}
469
470bool wxNativeFontInfo::GetUnderlined() const
471{
472    return lf.lfUnderline != 0;
473}
474
475wxString wxNativeFontInfo::GetFaceName() const
476{
477    return lf.lfFaceName;
478}
479
480wxFontFamily wxNativeFontInfo::GetFamily() const
481{
482    wxFontFamily family;
483
484    // extract family from pitch-and-family
485    switch ( lf.lfPitchAndFamily & ~PITCH_MASK )
486    {
487        case FF_ROMAN:
488            family = wxFONTFAMILY_ROMAN;
489            break;
490
491        default:
492            wxFAIL_MSG( _T("unknown LOGFONT::lfFamily value") );
493            // fall through
494
495        case FF_SWISS:
496            family = wxFONTFAMILY_SWISS;
497            break;
498
499        case FF_SCRIPT:
500            family = wxFONTFAMILY_SCRIPT;
501            break;
502
503        case FF_MODERN:
504            family = wxFONTFAMILY_MODERN;
505            break;
506
507        case FF_DECORATIVE:
508            family = wxFONTFAMILY_DECORATIVE;
509            break;
510    }
511
512    return family;
513}
514
515wxFontEncoding wxNativeFontInfo::GetEncoding() const
516{
517    return wxGetFontEncFromCharSet(lf.lfCharSet);
518}
519
520void wxNativeFontInfo::SetPointSize(int pointsize)
521{
522    // FIXME: using the screen here results in incorrect font size calculation
523    //        for printing!
524    const int ppInch = ::GetDeviceCaps(ScreenHDC(), LOGPIXELSY);
525
526    lf.lfHeight = -(int)((pointsize*((double)ppInch)/72.0) + 0.5);
527}
528
529void wxNativeFontInfo::SetPixelSize(const wxSize& pixelSize)
530{
531    lf.lfHeight = pixelSize.GetHeight();
532    lf.lfWidth = pixelSize.GetWidth();
533}
534
535
536void wxNativeFontInfo::SetStyle(wxFontStyle style)
537{
538    switch ( style )
539    {
540        default:
541            wxFAIL_MSG( _T("unknown font style") );
542            // fall through
543
544        case wxFONTSTYLE_NORMAL:
545            lf.lfItalic = FALSE;
546            break;
547
548        case wxFONTSTYLE_ITALIC:
549        case wxFONTSTYLE_SLANT:
550            lf.lfItalic = TRUE;
551            break;
552    }
553}
554
555void wxNativeFontInfo::SetWeight(wxFontWeight weight)
556{
557    switch ( weight )
558    {
559        default:
560            wxFAIL_MSG( _T("unknown font weight") );
561            // fall through
562
563        case wxFONTWEIGHT_NORMAL:
564            lf.lfWeight = FW_NORMAL;
565            break;
566
567        case wxFONTWEIGHT_LIGHT:
568            lf.lfWeight = FW_LIGHT;
569            break;
570
571        case wxFONTWEIGHT_BOLD:
572            lf.lfWeight = FW_BOLD;
573            break;
574    }
575}
576
577void wxNativeFontInfo::SetUnderlined(bool underlined)
578{
579    lf.lfUnderline = underlined;
580}
581
582bool wxNativeFontInfo::SetFaceName(const wxString& facename)
583{
584    size_t len = WXSIZEOF(lf.lfFaceName);
585    wxStrncpy(lf.lfFaceName, facename, len);
586    lf.lfFaceName[len - 1] = '\0';    // truncate the face name
587    return true;
588}
589
590void wxNativeFontInfo::SetFamily(wxFontFamily family)
591{
592    BYTE ff_family;
593    wxArrayString facename;
594
595    // the list of fonts associated with a family was partially
596    // taken from http://www.codestyle.org/css/font-family
597
598    switch ( family )
599    {
600        case wxSCRIPT:
601            ff_family = FF_SCRIPT;
602            facename.Add(_T("Script"));
603            facename.Add(_T("Brush Script MT"));
604            facename.Add(_T("Comic Sans MS"));
605            facename.Add(_T("Lucida Handwriting"));
606            break;
607
608        case wxDECORATIVE:
609            ff_family = FF_DECORATIVE;
610            facename.Add(_T("Old English Text MT"));
611            facename.Add(_T("Comic Sans MS"));
612            facename.Add(_T("Lucida Handwriting"));
613            break;
614
615        case wxROMAN:
616            ff_family = FF_ROMAN;
617            facename.Add(_T("Times New Roman"));
618            facename.Add(_T("Georgia"));
619            facename.Add(_T("Garamond"));
620            facename.Add(_T("Bookman Old Style"));
621            facename.Add(_T("Book Antiqua"));
622            break;
623
624        case wxTELETYPE:
625        case wxMODERN:
626            ff_family = FF_MODERN;
627            facename.Add(_T("Courier New"));
628            facename.Add(_T("Lucida Console"));
629            facename.Add(_T("Andale Mono"));
630            facename.Add(_T("OCR A Extended"));
631            facename.Add(_T("Terminal"));
632            break;
633
634        case wxSWISS:
635            ff_family = FF_SWISS;
636            facename.Add(_T("Arial"));
637            facename.Add(_T("Century Gothic"));
638            facename.Add(_T("Lucida Sans Unicode"));
639            facename.Add(_T("Tahoma"));
640            facename.Add(_T("Trebuchet MS"));
641            facename.Add(_T("Verdana"));
642            break;
643
644        case wxDEFAULT:
645        default:
646        {
647            // We want Windows 2000 or later to have new fonts even MS Shell Dlg
648            // is returned as default GUI font for compatibility
649            int verMaj;
650            ff_family = FF_SWISS;
651            if(wxGetOsVersion(&verMaj) == wxOS_WINDOWS_NT && verMaj >= 5)
652                facename.Add(_T("MS Shell Dlg 2"));
653            else
654                facename.Add(_T("MS Shell Dlg"));
655
656            // Quoting the MSDN:
657            //     "MS Shell Dlg is a mapping mechanism that enables
658            //     U.S. English Microsoft Windows NT, and Microsoft Windows 2000 to
659            //     support locales that have characters that are not contained in code
660            //     page 1252. It is not a font but a face name for a nonexistent font."
661        }
662    }
663
664    lf.lfPitchAndFamily = (BYTE)(DEFAULT_PITCH) | ff_family;
665
666    if ( !wxStrlen(lf.lfFaceName) )
667    {
668        SetFaceName(facename);
669    }
670}
671
672void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding)
673{
674    wxNativeEncodingInfo info;
675    if ( !wxGetNativeFontEncoding(encoding, &info) )
676    {
677#if wxUSE_FONTMAP
678        if ( wxFontMapper::Get()->GetAltForEncoding(encoding, &info) )
679        {
680            if ( !info.facename.empty() )
681            {
682                // if we have this encoding only in some particular facename, use
683                // the facename - it is better to show the correct characters in a
684                // wrong facename than unreadable text in a correct one
685                SetFaceName(info.facename);
686            }
687        }
688        else
689#endif // wxUSE_FONTMAP
690        {
691            // unsupported encoding, replace with the default
692            info.charset = DEFAULT_CHARSET;
693        }
694    }
695
696    lf.lfCharSet = (BYTE)info.charset;
697}
698
699bool wxNativeFontInfo::FromString(const wxString& s)
700{
701    long l;
702
703    wxStringTokenizer tokenizer(s, _T(";"));
704
705    // first the version
706    wxString token = tokenizer.GetNextToken();
707    if ( token != _T('0') )
708        return false;
709
710    token = tokenizer.GetNextToken();
711    if ( !token.ToLong(&l) )
712        return false;
713    lf.lfHeight = l;
714
715    token = tokenizer.GetNextToken();
716    if ( !token.ToLong(&l) )
717        return false;
718    lf.lfWidth = l;
719
720    token = tokenizer.GetNextToken();
721    if ( !token.ToLong(&l) )
722        return false;
723    lf.lfEscapement = l;
724
725    token = tokenizer.GetNextToken();
726    if ( !token.ToLong(&l) )
727        return false;
728    lf.lfOrientation = l;
729
730    token = tokenizer.GetNextToken();
731    if ( !token.ToLong(&l) )
732        return false;
733    lf.lfWeight = l;
734
735    token = tokenizer.GetNextToken();
736    if ( !token.ToLong(&l) )
737        return false;
738    lf.lfItalic = (BYTE)l;
739
740    token = tokenizer.GetNextToken();
741    if ( !token.ToLong(&l) )
742        return false;
743    lf.lfUnderline = (BYTE)l;
744
745    token = tokenizer.GetNextToken();
746    if ( !token.ToLong(&l) )
747        return false;
748    lf.lfStrikeOut = (BYTE)l;
749
750    token = tokenizer.GetNextToken();
751    if ( !token.ToLong(&l) )
752        return false;
753    lf.lfCharSet = (BYTE)l;
754
755    token = tokenizer.GetNextToken();
756    if ( !token.ToLong(&l) )
757        return false;
758    lf.lfOutPrecision = (BYTE)l;
759
760    token = tokenizer.GetNextToken();
761    if ( !token.ToLong(&l) )
762        return false;
763    lf.lfClipPrecision = (BYTE)l;
764
765    token = tokenizer.GetNextToken();
766    if ( !token.ToLong(&l) )
767        return false;
768    lf.lfQuality = (BYTE)l;
769
770    token = tokenizer.GetNextToken();
771    if ( !token.ToLong(&l) )
772        return false;
773    lf.lfPitchAndFamily = (BYTE)l;
774
775    token = tokenizer.GetNextToken();
776    if(!token)
777        return false;
778    wxStrcpy(lf.lfFaceName, token.c_str());
779
780    return true;
781}
782
783wxString wxNativeFontInfo::ToString() const
784{
785    wxString s;
786
787    s.Printf(_T("%d;%ld;%ld;%ld;%ld;%ld;%d;%d;%d;%d;%d;%d;%d;%d;%s"),
788             0, // version, in case we want to change the format later
789             lf.lfHeight,
790             lf.lfWidth,
791             lf.lfEscapement,
792             lf.lfOrientation,
793             lf.lfWeight,
794             lf.lfItalic,
795             lf.lfUnderline,
796             lf.lfStrikeOut,
797             lf.lfCharSet,
798             lf.lfOutPrecision,
799             lf.lfClipPrecision,
800             lf.lfQuality,
801             lf.lfPitchAndFamily,
802             lf.lfFaceName);
803
804    return s;
805}
806
807// ----------------------------------------------------------------------------
808// wxFont
809// ----------------------------------------------------------------------------
810
811bool wxFont::Create(const wxNativeFontInfo& info, WXHFONT hFont)
812{
813    UnRef();
814
815    m_refData = new wxFontRefData(info, hFont);
816
817    RealizeResource();
818
819    return true;
820}
821
822wxFont::wxFont(const wxString& fontdesc)
823{
824    wxNativeFontInfo info;
825    if ( info.FromString(fontdesc) )
826        (void)Create(info);
827}
828
829/* Constructor for a font. Note that the real construction is done
830 * in wxDC::SetFont, when information is available about scaling etc.
831 */
832bool wxFont::DoCreate(int pointSize,
833                      const wxSize& pixelSize,
834                      bool sizeUsingPixels,
835                      int family,
836                      int style,
837                      int weight,
838                      bool underlined,
839                      const wxString& faceName,
840                      wxFontEncoding encoding)
841{
842    UnRef();
843
844    // wxDEFAULT is a valid value for the font size too so we must treat it
845    // specially here (otherwise the size would be 70 == wxDEFAULT value)
846    if ( pointSize == wxDEFAULT )
847    {
848        pointSize = wxNORMAL_FONT->GetPointSize();
849    }
850
851    m_refData = new wxFontRefData(pointSize, pixelSize, sizeUsingPixels,
852                                  family, style, weight,
853                                  underlined, faceName, encoding);
854
855    RealizeResource();
856
857    return true;
858}
859
860wxFont::~wxFont()
861{
862}
863
864// ----------------------------------------------------------------------------
865// real implementation
866// ----------------------------------------------------------------------------
867
868bool wxFont::RealizeResource()
869{
870    if ( GetResourceHandle() )
871    {
872        // VZ: the old code returned false in this case, but it doesn't seem
873        //     to make sense because the font _was_ created
874        return true;
875    }
876
877    return M_FONTDATA->Alloc(this);
878}
879
880bool wxFont::FreeResource(bool WXUNUSED(force))
881{
882    if ( GetResourceHandle() )
883    {
884        M_FONTDATA->Free();
885
886        return true;
887    }
888
889    return false;
890}
891
892WXHANDLE wxFont::GetResourceHandle() const
893{
894    return (WXHANDLE)GetHFONT();
895}
896
897WXHFONT wxFont::GetHFONT() const
898{
899    return M_FONTDATA ? M_FONTDATA->GetHFONT() : 0;
900}
901
902bool wxFont::IsFree() const
903{
904    return M_FONTDATA && (M_FONTDATA->GetHFONT() == 0);
905}
906
907void wxFont::Unshare()
908{
909    // Don't change shared data
910    if ( !m_refData )
911    {
912        m_refData = new wxFontRefData();
913    }
914    else
915    {
916        wxFontRefData* ref = new wxFontRefData(*M_FONTDATA);
917        UnRef();
918        m_refData = ref;
919    }
920}
921
922// ----------------------------------------------------------------------------
923// change font attribute: we recreate font when doing it
924// ----------------------------------------------------------------------------
925
926void wxFont::SetPointSize(int pointSize)
927{
928    Unshare();
929
930    M_FONTDATA->SetPointSize(pointSize);
931
932    RealizeResource();
933}
934
935void wxFont::SetPixelSize(const wxSize& pixelSize)
936{
937    Unshare();
938
939    M_FONTDATA->SetPixelSize(pixelSize);
940
941    RealizeResource();
942}
943
944void wxFont::SetFamily(int family)
945{
946    Unshare();
947
948    M_FONTDATA->SetFamily(family);
949
950    RealizeResource();
951}
952
953void wxFont::SetStyle(int style)
954{
955    Unshare();
956
957    M_FONTDATA->SetStyle(style);
958
959    RealizeResource();
960}
961
962void wxFont::SetWeight(int weight)
963{
964    Unshare();
965
966    M_FONTDATA->SetWeight(weight);
967
968    RealizeResource();
969}
970
971bool wxFont::SetFaceName(const wxString& faceName)
972{
973    Unshare();
974
975    bool refdataok = M_FONTDATA->SetFaceName(faceName);
976
977    RealizeResource();
978
979    // NB: using win32's GetObject() API on M_FONTDATA->GetHFONT()
980    //     to retrieve a LOGFONT and then compare lf.lfFaceName
981    //     with given facename is not reliable at all:
982    //     Windows copies the facename given to ::CreateFontIndirect()
983    //     without any validity check.
984    //     Thus we use wxFontBase::SetFaceName to check if facename
985    //     is valid...
986    return refdataok && wxFontBase::SetFaceName(faceName);
987}
988
989void wxFont::SetUnderlined(bool underlined)
990{
991    Unshare();
992
993    M_FONTDATA->SetUnderlined(underlined);
994
995    RealizeResource();
996}
997
998void wxFont::SetEncoding(wxFontEncoding encoding)
999{
1000    Unshare();
1001
1002    M_FONTDATA->SetEncoding(encoding);
1003
1004    RealizeResource();
1005}
1006
1007void wxFont::DoSetNativeFontInfo(const wxNativeFontInfo& info)
1008{
1009    Unshare();
1010
1011    FreeResource();
1012
1013    *M_FONTDATA = wxFontRefData(info);
1014
1015    RealizeResource();
1016}
1017
1018// ----------------------------------------------------------------------------
1019// accessors
1020// ----------------------------------------------------------------------------
1021
1022int wxFont::GetPointSize() const
1023{
1024    wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
1025
1026    return M_FONTDATA->GetPointSize();
1027}
1028
1029wxSize wxFont::GetPixelSize() const
1030{
1031    wxCHECK_MSG( Ok(), wxDefaultSize, wxT("invalid font") );
1032
1033    return M_FONTDATA->GetPixelSize();
1034}
1035
1036bool wxFont::IsUsingSizeInPixels() const
1037{
1038    wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
1039
1040    return M_FONTDATA->IsUsingSizeInPixels();
1041}
1042
1043int wxFont::GetFamily() const
1044{
1045    wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
1046
1047    return M_FONTDATA->GetFamily();
1048}
1049
1050int wxFont::GetStyle() const
1051{
1052    wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
1053
1054    return M_FONTDATA->GetStyle();
1055}
1056
1057int wxFont::GetWeight() const
1058{
1059    wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
1060
1061    return M_FONTDATA->GetWeight();
1062}
1063
1064bool wxFont::GetUnderlined() const
1065{
1066    wxCHECK_MSG( Ok(), false, wxT("invalid font") );
1067
1068    return M_FONTDATA->GetUnderlined();
1069}
1070
1071wxString wxFont::GetFaceName() const
1072{
1073    wxCHECK_MSG( Ok(), wxEmptyString, wxT("invalid font") );
1074
1075    return M_FONTDATA->GetFaceName();
1076}
1077
1078wxFontEncoding wxFont::GetEncoding() const
1079{
1080    wxCHECK_MSG( Ok(), wxFONTENCODING_DEFAULT, wxT("invalid font") );
1081
1082    return M_FONTDATA->GetEncoding();
1083}
1084
1085const wxNativeFontInfo *wxFont::GetNativeFontInfo() const
1086{
1087    return Ok() && M_FONTDATA->HasNativeFontInfo() ? &(M_FONTDATA->GetNativeFontInfo())
1088                                           : NULL;
1089}
1090
1091wxString wxFont::GetNativeFontInfoDesc() const
1092{
1093    wxCHECK_MSG( Ok(), wxEmptyString, wxT("invalid font") );
1094
1095    // be sure we have an HFONT associated...
1096    wxConstCast(this, wxFont)->RealizeResource();
1097    return wxFontBase::GetNativeFontInfoDesc();
1098}
1099
1100wxString wxFont::GetNativeFontInfoUserDesc() const
1101{
1102    wxCHECK_MSG( Ok(), wxEmptyString, wxT("invalid font") );
1103
1104    // be sure we have an HFONT associated...
1105    wxConstCast(this, wxFont)->RealizeResource();
1106    return wxFontBase::GetNativeFontInfoUserDesc();
1107}
1108
1109bool wxFont::IsFixedWidth() const
1110{
1111    if ( M_FONTDATA->HasNativeFontInfo() )
1112    {
1113        // the two low-order bits specify the pitch of the font, the rest is
1114        // family
1115        BYTE pitch =
1116            (BYTE)(M_FONTDATA->GetNativeFontInfo().lf.lfPitchAndFamily & PITCH_MASK);
1117
1118        return pitch == FIXED_PITCH;
1119    }
1120
1121    return wxFontBase::IsFixedWidth();
1122}
1123