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