]> git.saurik.com Git - wxWidgets.git/blame - src/msw/font.cpp
fixes bug 414369
[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
221 // remember that 1pt = 1/72inch
222 int height = abs(info.lf.lfHeight);
223
224#if wxUSE_SCREEN_DPI
225 HDC dc = ::GetDC(NULL);
226 static const int ppInch = GetDeviceCaps(dc, LOGPIXELSY);
227 ::ReleaseDC(NULL, dc);
228#else
229 static const int ppInch = 96;
230#endif
231 m_pointSize = (int) (((72.0*((double)height))/(double) ppInch) + 0.5);
789034a0 232
09fcd889 233 m_encoding = wxGetFontEncFromCharSet(info.lf.lfCharSet);
789034a0 234
09fcd889
VZ
235 m_fontId = 0;
236 m_temporary = FALSE;
237
238 m_hFont = 0;
789034a0 239
09fcd889
VZ
240 m_nativeFontInfoOk = TRUE;
241 m_nativeFontInfo = info;
b823f5a1
JS
242}
243
0c5d3e1c 244wxFontRefData::~wxFontRefData()
2bda0e17 245{
b9b3ccd9 246 if ( m_hFont )
0c5d3e1c 247 {
b9b3ccd9 248 if ( !::DeleteObject((HFONT) m_hFont) )
0c5d3e1c 249 {
f6bcfd97 250 wxLogLastError(wxT("DeleteObject(font)"));
0c5d3e1c
VZ
251 }
252 }
2bda0e17
KB
253}
254
09fcd889
VZ
255
256// ----------------------------------------------------------------------------
257// wxNativeFontInfo
258// ----------------------------------------------------------------------------
259
260bool wxNativeFontInfo::FromString(const wxString& s)
261{
262 long l;
263
264 wxStringTokenizer tokenizer(s, _T(";"));
265
266 wxString token = tokenizer.GetNextToken();
267 //
268 // Ignore the version for now
269 //
270
271 token = tokenizer.GetNextToken();
272 if ( !token.ToLong(&l) )
273 return FALSE;
274 lf.lfHeight = l;
275
276 token = tokenizer.GetNextToken();
277 if ( !token.ToLong(&l) )
278 return FALSE;
279 lf.lfWidth = l;
280
281 token = tokenizer.GetNextToken();
282 if ( !token.ToLong(&l) )
283 return FALSE;
284 lf.lfEscapement = l;
285
286 token = tokenizer.GetNextToken();
287 if ( !token.ToLong(&l) )
288 return FALSE;
289 lf.lfOrientation = l;
290
291 token = tokenizer.GetNextToken();
292 if ( !token.ToLong(&l) )
293 return FALSE;
294 lf.lfWeight = l;
295
296 token = tokenizer.GetNextToken();
297 if ( !token.ToLong(&l) )
298 return FALSE;
299 lf.lfItalic = l;
300
301 token = tokenizer.GetNextToken();
302 if ( !token.ToLong(&l) )
303 return FALSE;
304 lf.lfUnderline = l;
305
306 token = tokenizer.GetNextToken();
307 if ( !token.ToLong(&l) )
308 return FALSE;
309 lf.lfStrikeOut = l;
310
311 token = tokenizer.GetNextToken();
312 if ( !token.ToLong(&l) )
313 return FALSE;
314 lf.lfCharSet = l;
315
316 token = tokenizer.GetNextToken();
317 if ( !token.ToLong(&l) )
318 return FALSE;
319 lf.lfOutPrecision = l;
320
321 token = tokenizer.GetNextToken();
322 if ( !token.ToLong(&l) )
323 return FALSE;
324 lf.lfClipPrecision = l;
325
326 token = tokenizer.GetNextToken();
327 if ( !token.ToLong(&l) )
328 return FALSE;
329 lf.lfQuality = l;
330
331 token = tokenizer.GetNextToken();
332 if ( !token.ToLong(&l) )
333 return FALSE;
334 lf.lfPitchAndFamily = l;
335
336 token = tokenizer.GetNextToken();
337 if(!token)
338 return FALSE;
339 wxStrcpy(lf.lfFaceName, token.c_str());
340
341 return TRUE;
342}
343
344wxString wxNativeFontInfo::ToString() const
345{
346 wxString s;
347
348 s.Printf(_T("%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%s"),
349 0, // version, in case we want to change the format later
350 lf.lfHeight,
351 lf.lfWidth,
352 lf.lfEscapement,
353 lf.lfOrientation,
354 lf.lfWeight,
355 lf.lfItalic,
356 lf.lfUnderline,
357 lf.lfStrikeOut,
358 lf.lfCharSet,
359 lf.lfOutPrecision,
360 lf.lfClipPrecision,
361 lf.lfQuality,
362 lf.lfPitchAndFamily,
363 lf.lfFaceName);
364
365 return s;
366}
367
0c5d3e1c
VZ
368// ----------------------------------------------------------------------------
369// wxFont
370// ----------------------------------------------------------------------------
371
372void wxFont::Init()
2bda0e17
KB
373{
374 if ( wxTheFontList )
375 wxTheFontList->Append(this);
376}
377
76e23cdb
VZ
378bool wxFont::Create(const wxNativeFontInfo& info)
379{
09fcd889
VZ
380 UnRef();
381
382 m_refData = new wxFontRefData(info);
383
384 RealizeResource();
385
386 return TRUE;
76e23cdb
VZ
387}
388
389wxFont::wxFont(const wxString& fontdesc)
390{
391 wxNativeFontInfo info;
392 if ( info.FromString(fontdesc) )
393 (void)Create(info);
394}
395
2bda0e17
KB
396/* Constructor for a font. Note that the real construction is done
397 * in wxDC::SetFont, when information is available about scaling etc.
398 */
0c5d3e1c
VZ
399bool wxFont::Create(int pointSize,
400 int family,
401 int style,
402 int weight,
403 bool underlined,
404 const wxString& faceName,
405 wxFontEncoding encoding)
2bda0e17 406{
0c5d3e1c 407 UnRef();
3ca6a5f0
BP
408
409 // wxDEFAULT is a valid value for the font size too so we must treat it
410 // specially here (otherwise the size would be 70 == wxDEFAULT value)
411 if ( pointSize == wxDEFAULT )
412 pointSize = wxDEFAULT_FONT_SIZE;
413
0c5d3e1c
VZ
414 m_refData = new wxFontRefData(pointSize, family, style, weight,
415 underlined, faceName, encoding);
2bda0e17 416
0c5d3e1c 417 RealizeResource();
2bda0e17 418
0c5d3e1c 419 return TRUE;
2bda0e17
KB
420}
421
422wxFont::~wxFont()
423{
0c5d3e1c
VZ
424 if ( wxTheFontList )
425 wxTheFontList->DeleteObject(this);
2bda0e17
KB
426}
427
0c5d3e1c
VZ
428// ----------------------------------------------------------------------------
429// real implementation
430// ----------------------------------------------------------------------------
431
432bool wxFont::RealizeResource()
2bda0e17 433{
0c5d3e1c
VZ
434 if ( GetResourceHandle() )
435 {
436 // VZ: the old code returned FALSE in this case, but it doesn't seem
437 // to make sense because the font _was_ created
0c5d3e1c
VZ
438 return TRUE;
439 }
440
09fcd889
VZ
441 if(!M_FONTDATA->m_nativeFontInfoOk)
442 {
443 wxFillLogFont(&M_FONTDATA->m_nativeFontInfo.lf, this);
444 M_FONTDATA->m_nativeFontInfoOk = TRUE;
445 }
789034a0 446
09fcd889
VZ
447 M_FONTDATA->m_hFont = (WXHFONT)::CreateFontIndirect(&M_FONTDATA->m_nativeFontInfo.lf);
448 M_FONTDATA->m_faceName = M_FONTDATA->m_nativeFontInfo.lf.lfFaceName;
11c7d5b6 449 if ( !M_FONTDATA->m_hFont )
b9b3ccd9 450 {
f6bcfd97 451 wxLogLastError(wxT("CreateFont"));
11c7d5b6
VZ
452
453 return FALSE;
b9b3ccd9
VZ
454 }
455
11c7d5b6 456 return TRUE;
2bda0e17
KB
457}
458
459bool wxFont::FreeResource(bool force)
460{
0c5d3e1c
VZ
461 if ( GetResourceHandle() )
462 {
463 if ( !::DeleteObject((HFONT) M_FONTDATA->m_hFont) )
464 {
f6bcfd97 465 wxLogLastError(wxT("DeleteObject(font)"));
0c5d3e1c
VZ
466 }
467
468 M_FONTDATA->m_hFont = 0;
469
470 return TRUE;
471 }
472 return FALSE;
2bda0e17
KB
473}
474
b823f5a1 475WXHANDLE wxFont::GetResourceHandle()
f6bcfd97
BP
476{
477 return GetHFONT();
478}
479
480WXHFONT wxFont::GetHFONT() const
2bda0e17 481{
0c5d3e1c
VZ
482 if ( !M_FONTDATA )
483 return 0;
484 else
11c7d5b6 485 return (WXHANDLE)M_FONTDATA->m_hFont;
2bda0e17
KB
486}
487
e90babdf 488bool wxFont::IsFree() const
2bda0e17 489{
0c5d3e1c 490 return (M_FONTDATA && (M_FONTDATA->m_hFont == 0));
2bda0e17
KB
491}
492
b823f5a1
JS
493void wxFont::Unshare()
494{
b9b3ccd9
VZ
495 // Don't change shared data
496 if ( !m_refData )
b823f5a1 497 {
b9b3ccd9
VZ
498 m_refData = new wxFontRefData();
499 }
b823f5a1
JS
500 else
501 {
b9b3ccd9
VZ
502 wxFontRefData* ref = new wxFontRefData(*M_FONTDATA);
503 UnRef();
504 m_refData = ref;
505 }
b823f5a1
JS
506}
507
0c5d3e1c
VZ
508// ----------------------------------------------------------------------------
509// change font attribute: we recreate font when doing it
510// ----------------------------------------------------------------------------
511
debe6624 512void wxFont::SetPointSize(int pointSize)
2bda0e17 513{
b823f5a1
JS
514 Unshare();
515
2bda0e17 516 M_FONTDATA->m_pointSize = pointSize;
09fcd889 517 M_FONTDATA->m_nativeFontInfoOk = FALSE;
b823f5a1
JS
518
519 RealizeResource();
2bda0e17
KB
520}
521
debe6624 522void wxFont::SetFamily(int family)
2bda0e17 523{
b823f5a1
JS
524 Unshare();
525
2bda0e17 526 M_FONTDATA->m_family = family;
09fcd889 527 M_FONTDATA->m_nativeFontInfoOk = FALSE;
b823f5a1
JS
528
529 RealizeResource();
2bda0e17
KB
530}
531
debe6624 532void wxFont::SetStyle(int style)
2bda0e17 533{
b823f5a1
JS
534 Unshare();
535
2bda0e17 536 M_FONTDATA->m_style = style;
09fcd889 537 M_FONTDATA->m_nativeFontInfoOk = FALSE;
b823f5a1
JS
538
539 RealizeResource();
2bda0e17
KB
540}
541
debe6624 542void wxFont::SetWeight(int weight)
2bda0e17 543{
b823f5a1
JS
544 Unshare();
545
2bda0e17 546 M_FONTDATA->m_weight = weight;
09fcd889 547 M_FONTDATA->m_nativeFontInfoOk = FALSE;
b823f5a1
JS
548
549 RealizeResource();
2bda0e17
KB
550}
551
552void wxFont::SetFaceName(const wxString& faceName)
553{
b823f5a1
JS
554 Unshare();
555
2bda0e17 556 M_FONTDATA->m_faceName = faceName;
09fcd889 557 M_FONTDATA->m_nativeFontInfoOk = FALSE;
b823f5a1
JS
558
559 RealizeResource();
2bda0e17
KB
560}
561
debe6624 562void wxFont::SetUnderlined(bool underlined)
2bda0e17 563{
b823f5a1
JS
564 Unshare();
565
2bda0e17 566 M_FONTDATA->m_underlined = underlined;
09fcd889 567 M_FONTDATA->m_nativeFontInfoOk = FALSE;
b823f5a1
JS
568
569 RealizeResource();
2bda0e17
KB
570}
571
0c5d3e1c 572void wxFont::SetEncoding(wxFontEncoding encoding)
2bda0e17 573{
0c5d3e1c
VZ
574 Unshare();
575
576 M_FONTDATA->m_encoding = encoding;
09fcd889
VZ
577 M_FONTDATA->m_nativeFontInfoOk = FALSE;
578
579 RealizeResource();
580}
581
582void wxFont::SetNativeFontInfo(const wxNativeFontInfo& info)
583{
584 Unshare();
789034a0
VZ
585
586 FreeResource();
09fcd889
VZ
587
588 M_FONTDATA->Init(info);
0c5d3e1c
VZ
589
590 RealizeResource();
591}
592
593// ----------------------------------------------------------------------------
594// accessors
595// ----------------------------------------------------------------------------
596
597int wxFont::GetPointSize() const
598{
789034a0
VZ
599 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
600
0c5d3e1c
VZ
601 return M_FONTDATA->m_pointSize;
602}
603
604int wxFont::GetFamily() const
605{
789034a0
VZ
606 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
607
0c5d3e1c 608 return M_FONTDATA->m_family;
2bda0e17
KB
609}
610
0c5d3e1c 611int wxFont::GetFontId() const
2bda0e17 612{
789034a0
VZ
613 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
614
0c5d3e1c 615 return M_FONTDATA->m_fontId;
2bda0e17
KB
616}
617
0c5d3e1c 618int wxFont::GetStyle() const
2bda0e17 619{
789034a0
VZ
620 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
621
0c5d3e1c 622 return M_FONTDATA->m_style;
2bda0e17
KB
623}
624
0c5d3e1c 625int wxFont::GetWeight() const
2bda0e17 626{
789034a0
VZ
627 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
628
0c5d3e1c 629 return M_FONTDATA->m_weight;
2bda0e17
KB
630}
631
0c5d3e1c
VZ
632bool wxFont::GetUnderlined() const
633{
789034a0
VZ
634 wxCHECK_MSG( Ok(), FALSE, wxT("invalid font") );
635
0c5d3e1c
VZ
636 return M_FONTDATA->m_underlined;
637}
638
639wxString wxFont::GetFaceName() const
640{
789034a0
VZ
641 wxCHECK_MSG( Ok(), wxT(""), wxT("invalid font") );
642
643 return M_FONTDATA->m_faceName;
0c5d3e1c
VZ
644}
645
646wxFontEncoding wxFont::GetEncoding() const
647{
789034a0
VZ
648 wxCHECK_MSG( Ok(), wxFONTENCODING_DEFAULT, wxT("invalid font") );
649
0c5d3e1c
VZ
650 return M_FONTDATA->m_encoding;
651}
a1d58ddc 652
09fcd889
VZ
653wxNativeFontInfo *wxFont::GetNativeFontInfo() const
654{
655 if( M_FONTDATA->m_nativeFontInfoOk )
656 return new wxNativeFontInfo(M_FONTDATA->m_nativeFontInfo);
789034a0 657
09fcd889
VZ
658 return 0;
659}
660