]> git.saurik.com Git - wxWidgets.git/blame - src/msw/font.cpp
Added wxDynamicSashWindow to wxPython, plus other odds and ends.
[wxWidgets.git] / src / msw / font.cpp
CommitLineData
2bda0e17
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: font.cpp
3// Purpose: wxFont class
4// Author: Julian Smart
5// Modified by:
6// Created: 01/02/97
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart and Markus Holzem
b9b3ccd9 9// Licence: wxWindows licence
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
0c5d3e1c
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
2bda0e17 20#ifdef __GNUG__
0c5d3e1c 21 #pragma implementation "font.h"
2bda0e17
KB
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
0c5d3e1c 28 #pragma hdrstop
2bda0e17
KB
29#endif
30
31#ifndef WX_PRECOMP
0c5d3e1c
VZ
32 #include "wx/setup.h"
33 #include "wx/list.h"
34 #include "wx/utils.h"
35 #include "wx/app.h"
36 #include "wx/font.h"
f94dfb38 37 #include "wx/log.h"
0c5d3e1c 38#endif // WX_PRECOMP
2bda0e17 39
76e23cdb 40#include "wx/fontutil.h"
09fcd889 41#include "wx/tokenzr.h"
76e23cdb 42
2bda0e17 43#include "wx/msw/private.h"
1e6feb95 44#include "wx/tokenzr.h"
2bda0e17 45
7fee680b 46IMPLEMENT_DYNAMIC_CLASS(wxFont, wxGDIObject)
2bda0e17 47
3ca6a5f0
BP
48// ----------------------------------------------------------------------------
49// constants
50// ----------------------------------------------------------------------------
51
52// the default font size in points
53static const int wxDEFAULT_FONT_SIZE = 12;
54
0c5d3e1c
VZ
55// ----------------------------------------------------------------------------
56// wxFontRefData - the internal description of the font
57// ----------------------------------------------------------------------------
2bda0e17 58
0c5d3e1c 59class WXDLLEXPORT wxFontRefData: public wxGDIRefData
2bda0e17 60{
0c5d3e1c
VZ
61friend class WXDLLEXPORT wxFont;
62
63public:
64 wxFontRefData()
65 {
3ca6a5f0 66 Init(wxDEFAULT_FONT_SIZE, wxDEFAULT, wxNORMAL, wxNORMAL, FALSE,
74b31181 67 "", wxFONTENCODING_DEFAULT);
0c5d3e1c
VZ
68 }
69
70 wxFontRefData(const wxFontRefData& data)
71 {
72 Init(data.m_pointSize, data.m_family, data.m_style, data.m_weight,
73 data.m_underlined, data.m_faceName, data.m_encoding);
74
75 m_fontId = data.m_fontId;
76 }
77
78 wxFontRefData(int size,
79 int family,
80 int style,
81 int weight,
82 bool underlined,
83 const wxString& faceName,
84 wxFontEncoding encoding)
85 {
86 Init(size, family, style, weight, underlined, faceName, encoding);
87 }
2bda0e17 88
04ef50df 89 wxFontRefData(const wxNativeFontInfo& info, WXHFONT hFont = 0)
09fcd889 90 {
04ef50df 91 Init(info, hFont);
09fcd889
VZ
92 }
93
0c5d3e1c
VZ
94 virtual ~wxFontRefData();
95
96protected:
97 // common part of all ctors
98 void Init(int size,
99 int family,
100 int style,
101 int weight,
102 bool underlined,
103 const wxString& faceName,
104 wxFontEncoding encoding);
105
04ef50df 106 void Init(const wxNativeFontInfo& info, WXHFONT hFont = 0);
09fcd889 107
0c5d3e1c
VZ
108 // If TRUE, the pointer to the actual font is temporary and SHOULD NOT BE
109 // DELETED by destructor
110 bool m_temporary;
111
112 int m_fontId;
113
114 // font characterstics
115 int m_pointSize;
116 int m_family;
117 int m_style;
118 int m_weight;
119 bool m_underlined;
120 wxString m_faceName;
121 wxFontEncoding m_encoding;
122
123 // Windows font handle
124 WXHFONT m_hFont;
789034a0 125
09fcd889
VZ
126 // Native font info
127 wxNativeFontInfo m_nativeFontInfo;
128 bool m_nativeFontInfoOk;
0c5d3e1c
VZ
129};
130
131// ============================================================================
132// implementation
133// ============================================================================
134
135// ----------------------------------------------------------------------------
136// wxFontRefData
137// ----------------------------------------------------------------------------
138
139void wxFontRefData::Init(int pointSize,
140 int family,
141 int style,
142 int weight,
143 bool underlined,
144 const wxString& faceName,
145 wxFontEncoding encoding)
b823f5a1 146{
b9b3ccd9
VZ
147 m_style = style;
148 m_pointSize = pointSize;
149 m_family = family;
150 m_style = style;
151 m_weight = weight;
152 m_underlined = underlined;
153 m_faceName = faceName;
0c5d3e1c
VZ
154 m_encoding = encoding;
155
b9b3ccd9
VZ
156 m_fontId = 0;
157 m_temporary = FALSE;
0c5d3e1c 158
b9b3ccd9 159 m_hFont = 0;
789034a0 160
09fcd889
VZ
161 m_nativeFontInfoOk = FALSE;
162}
163
04ef50df 164void wxFontRefData::Init(const wxNativeFontInfo& info, WXHFONT hFont)
09fcd889
VZ
165{
166 // extract family from pitch-and-family
167 int lfFamily = info.lf.lfPitchAndFamily;
168 if ( lfFamily & FIXED_PITCH )
169 lfFamily -= FIXED_PITCH;
170 if ( lfFamily & VARIABLE_PITCH )
171 lfFamily -= VARIABLE_PITCH;
172
173 switch ( lfFamily )
174 {
175 case FF_ROMAN:
176 m_family = wxROMAN;
177 break;
178
179 case FF_SWISS:
180 m_family = wxSWISS;
181 break;
182
183 case FF_SCRIPT:
184 m_family = wxSCRIPT;
185 break;
186
187 case FF_MODERN:
188 m_family = wxMODERN;
189 break;
190
191 case FF_DECORATIVE:
192 m_family = wxDECORATIVE;
193 break;
194
195 default:
196 m_family = wxSWISS;
197 }
198
199 // weight and style
200 switch ( info.lf.lfWeight )
201 {
202 case FW_LIGHT:
203 m_weight = wxLIGHT;
204 break;
205
206 default:
207 case FW_NORMAL:
208 m_weight = wxNORMAL;
209 break;
210
211 case FW_BOLD:
212 m_weight = wxBOLD;
213 break;
214 }
215
216 m_style = info.lf.lfItalic ? wxITALIC : wxNORMAL;
217
218 m_underlined = info.lf.lfUnderline != 0;
219
220 m_faceName = info.lf.lfFaceName;
221
09fcd889
VZ
222 int height = abs(info.lf.lfHeight);
223
55bd3f34
VZ
224 // remember that 1pt = 1/72inch
225 const int ppInch = ::GetDeviceCaps(ScreenHDC(), LOGPIXELSY);
09fcd889 226 m_pointSize = (int) (((72.0*((double)height))/(double) ppInch) + 0.5);
789034a0 227
09fcd889 228 m_encoding = wxGetFontEncFromCharSet(info.lf.lfCharSet);
789034a0 229
09fcd889
VZ
230 m_fontId = 0;
231 m_temporary = FALSE;
232
04ef50df
JS
233 // hFont may be zero, or it be passed in case we really want to
234 // use the exact font created in the underlying system
235 // (for example where we can't guarantee conversion from HFONT
236 // to LOGFONT back to HFONT)
237 m_hFont = hFont;
789034a0 238
09fcd889
VZ
239 m_nativeFontInfoOk = TRUE;
240 m_nativeFontInfo = info;
b823f5a1
JS
241}
242
0c5d3e1c 243wxFontRefData::~wxFontRefData()
2bda0e17 244{
b9b3ccd9 245 if ( m_hFont )
0c5d3e1c 246 {
b9b3ccd9 247 if ( !::DeleteObject((HFONT) m_hFont) )
0c5d3e1c 248 {
f6bcfd97 249 wxLogLastError(wxT("DeleteObject(font)"));
0c5d3e1c
VZ
250 }
251 }
2bda0e17
KB
252}
253
09fcd889
VZ
254
255// ----------------------------------------------------------------------------
256// wxNativeFontInfo
257// ----------------------------------------------------------------------------
258
259bool wxNativeFontInfo::FromString(const wxString& s)
260{
261 long l;
262
263 wxStringTokenizer tokenizer(s, _T(";"));
264
265 wxString token = tokenizer.GetNextToken();
266 //
267 // Ignore the version for now
268 //
269
270 token = tokenizer.GetNextToken();
271 if ( !token.ToLong(&l) )
272 return FALSE;
273 lf.lfHeight = l;
274
275 token = tokenizer.GetNextToken();
276 if ( !token.ToLong(&l) )
277 return FALSE;
278 lf.lfWidth = l;
279
280 token = tokenizer.GetNextToken();
281 if ( !token.ToLong(&l) )
282 return FALSE;
283 lf.lfEscapement = l;
284
285 token = tokenizer.GetNextToken();
286 if ( !token.ToLong(&l) )
287 return FALSE;
288 lf.lfOrientation = l;
289
290 token = tokenizer.GetNextToken();
291 if ( !token.ToLong(&l) )
292 return FALSE;
293 lf.lfWeight = l;
294
295 token = tokenizer.GetNextToken();
296 if ( !token.ToLong(&l) )
297 return FALSE;
33ac7e6f 298 lf.lfItalic = (BYTE)l;
09fcd889
VZ
299
300 token = tokenizer.GetNextToken();
301 if ( !token.ToLong(&l) )
302 return FALSE;
33ac7e6f 303 lf.lfUnderline = (BYTE)l;
09fcd889
VZ
304
305 token = tokenizer.GetNextToken();
306 if ( !token.ToLong(&l) )
307 return FALSE;
33ac7e6f 308 lf.lfStrikeOut = (BYTE)l;
09fcd889
VZ
309
310 token = tokenizer.GetNextToken();
311 if ( !token.ToLong(&l) )
312 return FALSE;
33ac7e6f 313 lf.lfCharSet = (BYTE)l;
09fcd889
VZ
314
315 token = tokenizer.GetNextToken();
316 if ( !token.ToLong(&l) )
317 return FALSE;
33ac7e6f 318 lf.lfOutPrecision = (BYTE)l;
09fcd889
VZ
319
320 token = tokenizer.GetNextToken();
321 if ( !token.ToLong(&l) )
322 return FALSE;
33ac7e6f 323 lf.lfClipPrecision = (BYTE)l;
09fcd889
VZ
324
325 token = tokenizer.GetNextToken();
326 if ( !token.ToLong(&l) )
327 return FALSE;
33ac7e6f 328 lf.lfQuality = (BYTE)l;
09fcd889
VZ
329
330 token = tokenizer.GetNextToken();
331 if ( !token.ToLong(&l) )
332 return FALSE;
33ac7e6f 333 lf.lfPitchAndFamily = (BYTE)l;
09fcd889
VZ
334
335 token = tokenizer.GetNextToken();
336 if(!token)
337 return FALSE;
338 wxStrcpy(lf.lfFaceName, token.c_str());
339
340 return TRUE;
341}
342
343wxString wxNativeFontInfo::ToString() const
344{
345 wxString s;
346
347 s.Printf(_T("%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%s"),
348 0, // version, in case we want to change the format later
349 lf.lfHeight,
350 lf.lfWidth,
351 lf.lfEscapement,
352 lf.lfOrientation,
353 lf.lfWeight,
354 lf.lfItalic,
355 lf.lfUnderline,
356 lf.lfStrikeOut,
357 lf.lfCharSet,
358 lf.lfOutPrecision,
359 lf.lfClipPrecision,
360 lf.lfQuality,
361 lf.lfPitchAndFamily,
362 lf.lfFaceName);
363
364 return s;
365}
366
0c5d3e1c
VZ
367// ----------------------------------------------------------------------------
368// wxFont
369// ----------------------------------------------------------------------------
370
371void wxFont::Init()
2bda0e17 372{
2bda0e17
KB
373}
374
04ef50df 375bool wxFont::Create(const wxNativeFontInfo& info, WXHFONT hFont)
76e23cdb 376{
09fcd889
VZ
377 UnRef();
378
04ef50df 379 m_refData = new wxFontRefData(info, hFont);
09fcd889
VZ
380
381 RealizeResource();
382
383 return TRUE;
76e23cdb
VZ
384}
385
386wxFont::wxFont(const wxString& fontdesc)
387{
388 wxNativeFontInfo info;
389 if ( info.FromString(fontdesc) )
390 (void)Create(info);
391}
392
2bda0e17
KB
393/* Constructor for a font. Note that the real construction is done
394 * in wxDC::SetFont, when information is available about scaling etc.
395 */
0c5d3e1c
VZ
396bool wxFont::Create(int pointSize,
397 int family,
398 int style,
399 int weight,
400 bool underlined,
401 const wxString& faceName,
402 wxFontEncoding encoding)
2bda0e17 403{
0c5d3e1c 404 UnRef();
3ca6a5f0
BP
405
406 // wxDEFAULT is a valid value for the font size too so we must treat it
407 // specially here (otherwise the size would be 70 == wxDEFAULT value)
408 if ( pointSize == wxDEFAULT )
409 pointSize = wxDEFAULT_FONT_SIZE;
410
0c5d3e1c
VZ
411 m_refData = new wxFontRefData(pointSize, family, style, weight,
412 underlined, faceName, encoding);
2bda0e17 413
0c5d3e1c 414 RealizeResource();
2bda0e17 415
0c5d3e1c 416 return TRUE;
2bda0e17
KB
417}
418
419wxFont::~wxFont()
420{
2bda0e17
KB
421}
422
0c5d3e1c
VZ
423// ----------------------------------------------------------------------------
424// real implementation
425// ----------------------------------------------------------------------------
426
427bool wxFont::RealizeResource()
2bda0e17 428{
0c5d3e1c
VZ
429 if ( GetResourceHandle() )
430 {
431 // VZ: the old code returned FALSE in this case, but it doesn't seem
432 // to make sense because the font _was_ created
0c5d3e1c
VZ
433 return TRUE;
434 }
435
09fcd889
VZ
436 if(!M_FONTDATA->m_nativeFontInfoOk)
437 {
438 wxFillLogFont(&M_FONTDATA->m_nativeFontInfo.lf, this);
439 M_FONTDATA->m_nativeFontInfoOk = TRUE;
440 }
789034a0 441
09fcd889
VZ
442 M_FONTDATA->m_hFont = (WXHFONT)::CreateFontIndirect(&M_FONTDATA->m_nativeFontInfo.lf);
443 M_FONTDATA->m_faceName = M_FONTDATA->m_nativeFontInfo.lf.lfFaceName;
11c7d5b6 444 if ( !M_FONTDATA->m_hFont )
b9b3ccd9 445 {
f6bcfd97 446 wxLogLastError(wxT("CreateFont"));
11c7d5b6
VZ
447
448 return FALSE;
b9b3ccd9
VZ
449 }
450
11c7d5b6 451 return TRUE;
2bda0e17
KB
452}
453
33ac7e6f 454bool wxFont::FreeResource(bool WXUNUSED(force))
2bda0e17 455{
0c5d3e1c
VZ
456 if ( GetResourceHandle() )
457 {
458 if ( !::DeleteObject((HFONT) M_FONTDATA->m_hFont) )
459 {
f6bcfd97 460 wxLogLastError(wxT("DeleteObject(font)"));
0c5d3e1c
VZ
461 }
462
463 M_FONTDATA->m_hFont = 0;
464
465 return TRUE;
466 }
467 return FALSE;
2bda0e17
KB
468}
469
b823f5a1 470WXHANDLE wxFont::GetResourceHandle()
f6bcfd97
BP
471{
472 return GetHFONT();
473}
474
475WXHFONT wxFont::GetHFONT() const
2bda0e17 476{
0c5d3e1c
VZ
477 if ( !M_FONTDATA )
478 return 0;
479 else
11c7d5b6 480 return (WXHANDLE)M_FONTDATA->m_hFont;
2bda0e17
KB
481}
482
e90babdf 483bool wxFont::IsFree() const
2bda0e17 484{
0c5d3e1c 485 return (M_FONTDATA && (M_FONTDATA->m_hFont == 0));
2bda0e17
KB
486}
487
b823f5a1
JS
488void wxFont::Unshare()
489{
b9b3ccd9
VZ
490 // Don't change shared data
491 if ( !m_refData )
b823f5a1 492 {
b9b3ccd9
VZ
493 m_refData = new wxFontRefData();
494 }
b823f5a1
JS
495 else
496 {
b9b3ccd9
VZ
497 wxFontRefData* ref = new wxFontRefData(*M_FONTDATA);
498 UnRef();
499 m_refData = ref;
500 }
b823f5a1
JS
501}
502
0c5d3e1c
VZ
503// ----------------------------------------------------------------------------
504// change font attribute: we recreate font when doing it
505// ----------------------------------------------------------------------------
506
debe6624 507void wxFont::SetPointSize(int pointSize)
2bda0e17 508{
b823f5a1
JS
509 Unshare();
510
2bda0e17 511 M_FONTDATA->m_pointSize = pointSize;
09fcd889 512 M_FONTDATA->m_nativeFontInfoOk = FALSE;
b823f5a1
JS
513
514 RealizeResource();
2bda0e17
KB
515}
516
debe6624 517void wxFont::SetFamily(int family)
2bda0e17 518{
b823f5a1
JS
519 Unshare();
520
2bda0e17 521 M_FONTDATA->m_family = family;
09fcd889 522 M_FONTDATA->m_nativeFontInfoOk = FALSE;
b823f5a1
JS
523
524 RealizeResource();
2bda0e17
KB
525}
526
debe6624 527void wxFont::SetStyle(int style)
2bda0e17 528{
b823f5a1
JS
529 Unshare();
530
2bda0e17 531 M_FONTDATA->m_style = style;
09fcd889 532 M_FONTDATA->m_nativeFontInfoOk = FALSE;
b823f5a1
JS
533
534 RealizeResource();
2bda0e17
KB
535}
536
debe6624 537void wxFont::SetWeight(int weight)
2bda0e17 538{
b823f5a1
JS
539 Unshare();
540
2bda0e17 541 M_FONTDATA->m_weight = weight;
09fcd889 542 M_FONTDATA->m_nativeFontInfoOk = FALSE;
b823f5a1
JS
543
544 RealizeResource();
2bda0e17
KB
545}
546
547void wxFont::SetFaceName(const wxString& faceName)
548{
b823f5a1
JS
549 Unshare();
550
2bda0e17 551 M_FONTDATA->m_faceName = faceName;
09fcd889 552 M_FONTDATA->m_nativeFontInfoOk = FALSE;
b823f5a1
JS
553
554 RealizeResource();
2bda0e17
KB
555}
556
debe6624 557void wxFont::SetUnderlined(bool underlined)
2bda0e17 558{
b823f5a1
JS
559 Unshare();
560
2bda0e17 561 M_FONTDATA->m_underlined = underlined;
09fcd889 562 M_FONTDATA->m_nativeFontInfoOk = FALSE;
b823f5a1
JS
563
564 RealizeResource();
2bda0e17
KB
565}
566
0c5d3e1c 567void wxFont::SetEncoding(wxFontEncoding encoding)
2bda0e17 568{
0c5d3e1c
VZ
569 Unshare();
570
571 M_FONTDATA->m_encoding = encoding;
09fcd889
VZ
572 M_FONTDATA->m_nativeFontInfoOk = FALSE;
573
574 RealizeResource();
575}
576
577void wxFont::SetNativeFontInfo(const wxNativeFontInfo& info)
578{
579 Unshare();
789034a0
VZ
580
581 FreeResource();
09fcd889
VZ
582
583 M_FONTDATA->Init(info);
0c5d3e1c
VZ
584
585 RealizeResource();
586}
587
588// ----------------------------------------------------------------------------
589// accessors
590// ----------------------------------------------------------------------------
591
592int wxFont::GetPointSize() const
593{
789034a0
VZ
594 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
595
0c5d3e1c
VZ
596 return M_FONTDATA->m_pointSize;
597}
598
599int wxFont::GetFamily() const
600{
789034a0
VZ
601 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
602
0c5d3e1c 603 return M_FONTDATA->m_family;
2bda0e17
KB
604}
605
0c5d3e1c 606int wxFont::GetFontId() const
2bda0e17 607{
789034a0
VZ
608 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
609
0c5d3e1c 610 return M_FONTDATA->m_fontId;
2bda0e17
KB
611}
612
0c5d3e1c 613int wxFont::GetStyle() const
2bda0e17 614{
789034a0
VZ
615 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
616
0c5d3e1c 617 return M_FONTDATA->m_style;
2bda0e17
KB
618}
619
0c5d3e1c 620int wxFont::GetWeight() const
2bda0e17 621{
789034a0
VZ
622 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
623
0c5d3e1c 624 return M_FONTDATA->m_weight;
2bda0e17
KB
625}
626
0c5d3e1c
VZ
627bool wxFont::GetUnderlined() const
628{
789034a0
VZ
629 wxCHECK_MSG( Ok(), FALSE, wxT("invalid font") );
630
0c5d3e1c
VZ
631 return M_FONTDATA->m_underlined;
632}
633
634wxString wxFont::GetFaceName() const
635{
789034a0
VZ
636 wxCHECK_MSG( Ok(), wxT(""), wxT("invalid font") );
637
638 return M_FONTDATA->m_faceName;
0c5d3e1c
VZ
639}
640
641wxFontEncoding wxFont::GetEncoding() const
642{
789034a0
VZ
643 wxCHECK_MSG( Ok(), wxFONTENCODING_DEFAULT, wxT("invalid font") );
644
0c5d3e1c
VZ
645 return M_FONTDATA->m_encoding;
646}
a1d58ddc 647
e421922f 648wxNativeFontInfo *wxFont::GetNativeFontInfo() const
1e6feb95 649{
e421922f
VZ
650 if( M_FONTDATA->m_nativeFontInfoOk )
651 return new wxNativeFontInfo(M_FONTDATA->m_nativeFontInfo);
1e6feb95 652
e421922f 653 return 0;
09fcd889
VZ
654}
655