]> git.saurik.com Git - wxWidgets.git/blame - src/msw/font.cpp
fixed bug in wxString::Matches() - backtrack now if \* mismatched
[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
KB
372{
373 if ( wxTheFontList )
374 wxTheFontList->Append(this);
375}
376
04ef50df 377bool wxFont::Create(const wxNativeFontInfo& info, WXHFONT hFont)
76e23cdb 378{
09fcd889
VZ
379 UnRef();
380
04ef50df 381 m_refData = new wxFontRefData(info, hFont);
09fcd889
VZ
382
383 RealizeResource();
384
385 return TRUE;
76e23cdb
VZ
386}
387
388wxFont::wxFont(const wxString& fontdesc)
389{
390 wxNativeFontInfo info;
391 if ( info.FromString(fontdesc) )
392 (void)Create(info);
393}
394
2bda0e17
KB
395/* Constructor for a font. Note that the real construction is done
396 * in wxDC::SetFont, when information is available about scaling etc.
397 */
0c5d3e1c
VZ
398bool wxFont::Create(int pointSize,
399 int family,
400 int style,
401 int weight,
402 bool underlined,
403 const wxString& faceName,
404 wxFontEncoding encoding)
2bda0e17 405{
0c5d3e1c 406 UnRef();
3ca6a5f0
BP
407
408 // wxDEFAULT is a valid value for the font size too so we must treat it
409 // specially here (otherwise the size would be 70 == wxDEFAULT value)
410 if ( pointSize == wxDEFAULT )
411 pointSize = wxDEFAULT_FONT_SIZE;
412
0c5d3e1c
VZ
413 m_refData = new wxFontRefData(pointSize, family, style, weight,
414 underlined, faceName, encoding);
2bda0e17 415
0c5d3e1c 416 RealizeResource();
2bda0e17 417
0c5d3e1c 418 return TRUE;
2bda0e17
KB
419}
420
421wxFont::~wxFont()
422{
0c5d3e1c
VZ
423 if ( wxTheFontList )
424 wxTheFontList->DeleteObject(this);
2bda0e17
KB
425}
426
0c5d3e1c
VZ
427// ----------------------------------------------------------------------------
428// real implementation
429// ----------------------------------------------------------------------------
430
431bool wxFont::RealizeResource()
2bda0e17 432{
0c5d3e1c
VZ
433 if ( GetResourceHandle() )
434 {
435 // VZ: the old code returned FALSE in this case, but it doesn't seem
436 // to make sense because the font _was_ created
0c5d3e1c
VZ
437 return TRUE;
438 }
439
09fcd889
VZ
440 if(!M_FONTDATA->m_nativeFontInfoOk)
441 {
442 wxFillLogFont(&M_FONTDATA->m_nativeFontInfo.lf, this);
443 M_FONTDATA->m_nativeFontInfoOk = TRUE;
444 }
789034a0 445
09fcd889
VZ
446 M_FONTDATA->m_hFont = (WXHFONT)::CreateFontIndirect(&M_FONTDATA->m_nativeFontInfo.lf);
447 M_FONTDATA->m_faceName = M_FONTDATA->m_nativeFontInfo.lf.lfFaceName;
11c7d5b6 448 if ( !M_FONTDATA->m_hFont )
b9b3ccd9 449 {
f6bcfd97 450 wxLogLastError(wxT("CreateFont"));
11c7d5b6
VZ
451
452 return FALSE;
b9b3ccd9
VZ
453 }
454
11c7d5b6 455 return TRUE;
2bda0e17
KB
456}
457
33ac7e6f 458bool wxFont::FreeResource(bool WXUNUSED(force))
2bda0e17 459{
0c5d3e1c
VZ
460 if ( GetResourceHandle() )
461 {
462 if ( !::DeleteObject((HFONT) M_FONTDATA->m_hFont) )
463 {
f6bcfd97 464 wxLogLastError(wxT("DeleteObject(font)"));
0c5d3e1c
VZ
465 }
466
467 M_FONTDATA->m_hFont = 0;
468
469 return TRUE;
470 }
471 return FALSE;
2bda0e17
KB
472}
473
b823f5a1 474WXHANDLE wxFont::GetResourceHandle()
f6bcfd97
BP
475{
476 return GetHFONT();
477}
478
479WXHFONT wxFont::GetHFONT() const
2bda0e17 480{
0c5d3e1c
VZ
481 if ( !M_FONTDATA )
482 return 0;
483 else
11c7d5b6 484 return (WXHANDLE)M_FONTDATA->m_hFont;
2bda0e17
KB
485}
486
e90babdf 487bool wxFont::IsFree() const
2bda0e17 488{
0c5d3e1c 489 return (M_FONTDATA && (M_FONTDATA->m_hFont == 0));
2bda0e17
KB
490}
491
b823f5a1
JS
492void wxFont::Unshare()
493{
b9b3ccd9
VZ
494 // Don't change shared data
495 if ( !m_refData )
b823f5a1 496 {
b9b3ccd9
VZ
497 m_refData = new wxFontRefData();
498 }
b823f5a1
JS
499 else
500 {
b9b3ccd9
VZ
501 wxFontRefData* ref = new wxFontRefData(*M_FONTDATA);
502 UnRef();
503 m_refData = ref;
504 }
b823f5a1
JS
505}
506
0c5d3e1c
VZ
507// ----------------------------------------------------------------------------
508// change font attribute: we recreate font when doing it
509// ----------------------------------------------------------------------------
510
debe6624 511void wxFont::SetPointSize(int pointSize)
2bda0e17 512{
b823f5a1
JS
513 Unshare();
514
2bda0e17 515 M_FONTDATA->m_pointSize = pointSize;
09fcd889 516 M_FONTDATA->m_nativeFontInfoOk = FALSE;
b823f5a1
JS
517
518 RealizeResource();
2bda0e17
KB
519}
520
debe6624 521void wxFont::SetFamily(int family)
2bda0e17 522{
b823f5a1
JS
523 Unshare();
524
2bda0e17 525 M_FONTDATA->m_family = family;
09fcd889 526 M_FONTDATA->m_nativeFontInfoOk = FALSE;
b823f5a1
JS
527
528 RealizeResource();
2bda0e17
KB
529}
530
debe6624 531void wxFont::SetStyle(int style)
2bda0e17 532{
b823f5a1
JS
533 Unshare();
534
2bda0e17 535 M_FONTDATA->m_style = style;
09fcd889 536 M_FONTDATA->m_nativeFontInfoOk = FALSE;
b823f5a1
JS
537
538 RealizeResource();
2bda0e17
KB
539}
540
debe6624 541void wxFont::SetWeight(int weight)
2bda0e17 542{
b823f5a1
JS
543 Unshare();
544
2bda0e17 545 M_FONTDATA->m_weight = weight;
09fcd889 546 M_FONTDATA->m_nativeFontInfoOk = FALSE;
b823f5a1
JS
547
548 RealizeResource();
2bda0e17
KB
549}
550
551void wxFont::SetFaceName(const wxString& faceName)
552{
b823f5a1
JS
553 Unshare();
554
2bda0e17 555 M_FONTDATA->m_faceName = faceName;
09fcd889 556 M_FONTDATA->m_nativeFontInfoOk = FALSE;
b823f5a1
JS
557
558 RealizeResource();
2bda0e17
KB
559}
560
debe6624 561void wxFont::SetUnderlined(bool underlined)
2bda0e17 562{
b823f5a1
JS
563 Unshare();
564
2bda0e17 565 M_FONTDATA->m_underlined = underlined;
09fcd889 566 M_FONTDATA->m_nativeFontInfoOk = FALSE;
b823f5a1
JS
567
568 RealizeResource();
2bda0e17
KB
569}
570
0c5d3e1c 571void wxFont::SetEncoding(wxFontEncoding encoding)
2bda0e17 572{
0c5d3e1c
VZ
573 Unshare();
574
575 M_FONTDATA->m_encoding = encoding;
09fcd889
VZ
576 M_FONTDATA->m_nativeFontInfoOk = FALSE;
577
578 RealizeResource();
579}
580
581void wxFont::SetNativeFontInfo(const wxNativeFontInfo& info)
582{
583 Unshare();
789034a0
VZ
584
585 FreeResource();
09fcd889
VZ
586
587 M_FONTDATA->Init(info);
0c5d3e1c
VZ
588
589 RealizeResource();
590}
591
592// ----------------------------------------------------------------------------
593// accessors
594// ----------------------------------------------------------------------------
595
596int wxFont::GetPointSize() const
597{
789034a0
VZ
598 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
599
0c5d3e1c
VZ
600 return M_FONTDATA->m_pointSize;
601}
602
603int wxFont::GetFamily() const
604{
789034a0
VZ
605 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
606
0c5d3e1c 607 return M_FONTDATA->m_family;
2bda0e17
KB
608}
609
0c5d3e1c 610int wxFont::GetFontId() const
2bda0e17 611{
789034a0
VZ
612 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
613
0c5d3e1c 614 return M_FONTDATA->m_fontId;
2bda0e17
KB
615}
616
0c5d3e1c 617int wxFont::GetStyle() const
2bda0e17 618{
789034a0
VZ
619 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
620
0c5d3e1c 621 return M_FONTDATA->m_style;
2bda0e17
KB
622}
623
0c5d3e1c 624int wxFont::GetWeight() const
2bda0e17 625{
789034a0
VZ
626 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
627
0c5d3e1c 628 return M_FONTDATA->m_weight;
2bda0e17
KB
629}
630
0c5d3e1c
VZ
631bool wxFont::GetUnderlined() const
632{
789034a0
VZ
633 wxCHECK_MSG( Ok(), FALSE, wxT("invalid font") );
634
0c5d3e1c
VZ
635 return M_FONTDATA->m_underlined;
636}
637
638wxString wxFont::GetFaceName() const
639{
789034a0
VZ
640 wxCHECK_MSG( Ok(), wxT(""), wxT("invalid font") );
641
642 return M_FONTDATA->m_faceName;
0c5d3e1c
VZ
643}
644
645wxFontEncoding wxFont::GetEncoding() const
646{
789034a0
VZ
647 wxCHECK_MSG( Ok(), wxFONTENCODING_DEFAULT, wxT("invalid font") );
648
0c5d3e1c
VZ
649 return M_FONTDATA->m_encoding;
650}
a1d58ddc 651
e421922f 652wxNativeFontInfo *wxFont::GetNativeFontInfo() const
1e6feb95 653{
e421922f
VZ
654 if( M_FONTDATA->m_nativeFontInfoOk )
655 return new wxNativeFontInfo(M_FONTDATA->m_nativeFontInfo);
1e6feb95 656
e421922f 657 return 0;
09fcd889
VZ
658}
659