]> git.saurik.com Git - wxWidgets.git/blob - src/msw/font.cpp
bf831d467a11e83162eaf28521ce3d53bdf89d71
[wxWidgets.git] / src / msw / font.cpp
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$
8 // Copyright: (c) wxWindows team
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #ifdef __GNUG__
21 #pragma implementation "font.h"
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 #ifndef WX_PRECOMP
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"
37 #include "wx/log.h"
38 #endif // WX_PRECOMP
39
40 #include "wx/fontutil.h"
41 #include "wx/tokenzr.h"
42
43 #include "wx/msw/private.h"
44 #include "wx/tokenzr.h"
45
46 IMPLEMENT_DYNAMIC_CLASS(wxFont, wxGDIObject)
47
48 // ----------------------------------------------------------------------------
49 // constants
50 // ----------------------------------------------------------------------------
51
52 // ----------------------------------------------------------------------------
53 // wxFontRefData - the internal description of the font
54 // ----------------------------------------------------------------------------
55
56 class WXDLLEXPORT wxFontRefData: public wxGDIRefData
57 {
58 public:
59 // constructors
60 wxFontRefData()
61 {
62 Init(-1, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL,
63 FALSE, _T(""), wxFONTENCODING_DEFAULT);
64 }
65
66 wxFontRefData(int size,
67 int family,
68 int style,
69 int weight,
70 bool underlined,
71 const wxString& faceName,
72 wxFontEncoding encoding)
73 {
74 Init(size, family, style, weight, underlined, faceName, encoding);
75 }
76
77 wxFontRefData(const wxNativeFontInfo& info, WXHFONT hFont = 0)
78 {
79 Init(info, hFont);
80 }
81
82 wxFontRefData(const wxFontRefData& data)
83 {
84 if ( data.m_nativeFontInfoOk )
85 {
86 Init(data.m_nativeFontInfo);
87 }
88 else
89 {
90 Init(data.m_pointSize, data.m_family, data.m_style, data.m_weight,
91 data.m_underlined, data.m_faceName, data.m_encoding);
92 }
93 }
94
95 virtual ~wxFontRefData();
96
97 // operations
98 bool Alloc(wxFont *font);
99
100 void Free();
101
102 // all wxFont accessors
103 int GetPointSize() const
104 {
105 return m_nativeFontInfoOk ? m_nativeFontInfo.GetPointSize()
106 : m_pointSize;
107 }
108
109 int GetFamily() const
110 {
111 return m_family;
112 }
113
114 int GetStyle() const
115 {
116 return m_nativeFontInfoOk ? m_nativeFontInfo.GetStyle()
117 : m_style;
118 }
119
120 int GetWeight() const
121 {
122 return m_nativeFontInfoOk ? m_nativeFontInfo.GetWeight()
123 : m_weight;
124 }
125
126 bool GetUnderlined() const
127 {
128 return m_nativeFontInfoOk ? m_nativeFontInfo.GetUnderlined()
129 : m_underlined;
130 }
131
132 wxString GetFaceName() const
133 {
134 wxString s;
135 if ( m_nativeFontInfoOk )
136 s = m_nativeFontInfo.GetFaceName();
137 else
138 s = m_faceName;
139
140 return s;
141 }
142
143 wxFontEncoding GetEncoding() const
144 {
145 return m_nativeFontInfoOk ? m_nativeFontInfo.GetEncoding()
146 : m_encoding;
147 }
148
149 WXHFONT GetHFONT() const { return m_hFont; }
150
151 // ... and setters
152 void SetPointSize(int pointSize)
153 {
154 if ( m_nativeFontInfoOk )
155 m_nativeFontInfo.SetPointSize(pointSize);
156 else
157 m_pointSize = pointSize;
158 }
159
160 void SetFamily(int family)
161 {
162 m_family = family;
163 }
164
165 void SetStyle(int style)
166 {
167 if ( m_nativeFontInfoOk )
168 m_nativeFontInfo.SetStyle((wxFontStyle)style);
169 else
170 m_style = style;
171 }
172
173 void SetWeight(int weight)
174 {
175 if ( m_nativeFontInfoOk )
176 m_nativeFontInfo.SetWeight((wxFontWeight)weight);
177 else
178 m_weight = weight;
179 }
180
181 void SetFaceName(const wxString& faceName)
182 {
183 if ( m_nativeFontInfoOk )
184 m_nativeFontInfo.SetFaceName(faceName);
185 else
186 m_faceName = faceName;
187 }
188
189 void SetUnderlined(bool underlined)
190 {
191 if ( m_nativeFontInfoOk )
192 m_nativeFontInfo.SetUnderlined(underlined);
193 else
194 m_underlined = underlined;
195 }
196
197 void SetEncoding(wxFontEncoding encoding)
198 {
199 if ( m_nativeFontInfoOk )
200 m_nativeFontInfo.SetEncoding(encoding);
201 else
202 m_encoding = encoding;
203 }
204
205 // native font info tests
206 bool HasNativeFontInfo() const { return m_nativeFontInfoOk; }
207
208 const wxNativeFontInfo& GetNativeFontInfo() const
209 { return m_nativeFontInfo; }
210
211 protected:
212 // common part of all ctors
213 void Init(int size,
214 int family,
215 int style,
216 int weight,
217 bool underlined,
218 const wxString& faceName,
219 wxFontEncoding encoding);
220
221 void Init(const wxNativeFontInfo& info, WXHFONT hFont = 0);
222
223 // font characterstics
224 int m_pointSize;
225 int m_family;
226 int m_style;
227 int m_weight;
228 bool m_underlined;
229 wxString m_faceName;
230 wxFontEncoding m_encoding;
231
232 // Windows font handle
233 WXHFONT m_hFont;
234
235 // Native font info
236 wxNativeFontInfo m_nativeFontInfo;
237 bool m_nativeFontInfoOk;
238 };
239
240 // ============================================================================
241 // implementation
242 // ============================================================================
243
244 // ----------------------------------------------------------------------------
245 // wxFontRefData
246 // ----------------------------------------------------------------------------
247
248 void wxFontRefData::Init(int pointSize,
249 int family,
250 int style,
251 int weight,
252 bool underlined,
253 const wxString& faceName,
254 wxFontEncoding encoding)
255 {
256 m_style = style;
257 m_pointSize = pointSize == -1 ? wxNORMAL_FONT->GetPointSize() : pointSize;
258 m_family = family;
259 m_style = style;
260 m_weight = weight;
261 m_underlined = underlined;
262 m_faceName = faceName;
263 m_encoding = encoding;
264
265 m_hFont = 0;
266
267 m_nativeFontInfoOk = FALSE;
268 }
269
270 void wxFontRefData::Init(const wxNativeFontInfo& info, WXHFONT hFont)
271 {
272 // we don't really need the family, what for?
273 #if 0
274 // extract family from pitch-and-family
275 int lfFamily = info.lf.lfPitchAndFamily;
276 if ( lfFamily & FIXED_PITCH )
277 lfFamily -= FIXED_PITCH;
278 if ( lfFamily & VARIABLE_PITCH )
279 lfFamily -= VARIABLE_PITCH;
280
281 switch ( lfFamily )
282 {
283 case FF_ROMAN:
284 m_family = wxROMAN;
285 break;
286
287 case FF_SWISS:
288 m_family = wxSWISS;
289 break;
290
291 case FF_SCRIPT:
292 m_family = wxSCRIPT;
293 break;
294
295 case FF_MODERN:
296 m_family = wxMODERN;
297 break;
298
299 case FF_DECORATIVE:
300 m_family = wxDECORATIVE;
301 break;
302
303 default:
304 m_family = wxSWISS;
305 }
306 #endif // 0
307
308 // hFont may be zero, or it be passed in case we really want to
309 // use the exact font created in the underlying system
310 // (for example where we can't guarantee conversion from HFONT
311 // to LOGFONT back to HFONT)
312 m_hFont = hFont;
313
314 m_nativeFontInfoOk = TRUE;
315 m_nativeFontInfo = info;
316 }
317
318 wxFontRefData::~wxFontRefData()
319 {
320 Free();
321 }
322
323 bool wxFontRefData::Alloc(wxFont *font)
324 {
325 if ( !m_nativeFontInfoOk )
326 {
327 wxFillLogFont(&m_nativeFontInfo.lf, font);
328 m_nativeFontInfoOk = TRUE;
329 }
330
331 HFONT hfont = ::CreateFontIndirect(&m_nativeFontInfo.lf);
332 if ( !hfont )
333 {
334 wxLogLastError(wxT("CreateFont"));
335
336 return FALSE;
337 }
338
339 m_hFont = (WXHFONT)hfont;
340
341 return TRUE;
342 }
343
344 void wxFontRefData::Free()
345 {
346 if ( m_hFont )
347 {
348 if ( !::DeleteObject((HFONT) m_hFont) )
349 {
350 wxLogLastError(wxT("DeleteObject(font)"));
351 }
352
353 m_hFont = 0;
354 }
355 }
356
357 // ----------------------------------------------------------------------------
358 // wxNativeFontInfo
359 // ----------------------------------------------------------------------------
360
361 void wxNativeFontInfo::Init()
362 {
363 wxZeroMemory(lf);
364 }
365
366 int wxNativeFontInfo::GetPointSize() const
367 {
368 const int ppInch = ::GetDeviceCaps(ScreenHDC(), LOGPIXELSY);
369
370 return (int) (((72.0*(double)abs(lf.lfHeight)) / (double) ppInch) + 0.5);
371 }
372
373 wxFontStyle wxNativeFontInfo::GetStyle() const
374 {
375 return lf.lfItalic ? wxFONTSTYLE_ITALIC : wxFONTSTYLE_NORMAL;
376 }
377
378 wxFontWeight wxNativeFontInfo::GetWeight() const
379 {
380 if ( lf.lfWeight <= 300 )
381 return wxFONTWEIGHT_LIGHT;
382
383 if ( lf.lfWeight >= 600 )
384 return wxFONTWEIGHT_BOLD;
385
386 return wxFONTWEIGHT_NORMAL;
387 }
388
389 bool wxNativeFontInfo::GetUnderlined() const
390 {
391 return lf.lfUnderline != 0;
392 }
393
394 wxString wxNativeFontInfo::GetFaceName() const
395 {
396 return lf.lfFaceName;
397 }
398
399 wxFontEncoding wxNativeFontInfo::GetEncoding() const
400 {
401 return wxGetFontEncFromCharSet(lf.lfCharSet);
402 }
403
404 void wxNativeFontInfo::SetPointSize(int pointsize)
405 {
406 const int ppInch = ::GetDeviceCaps(ScreenHDC(), LOGPIXELSY);
407
408 lf.lfHeight = -(int)((pointsize*((double)ppInch)/72.0) + 0.5);
409 }
410
411 void wxNativeFontInfo::SetStyle(wxFontStyle style)
412 {
413 switch ( style )
414 {
415 default:
416 wxFAIL_MSG( _T("unknown font style") );
417 // fall through
418
419 case wxFONTSTYLE_NORMAL:
420 break;
421
422 case wxFONTSTYLE_ITALIC:
423 case wxFONTSTYLE_SLANT:
424 lf.lfItalic = TRUE;
425 break;
426 }
427 }
428
429 void wxNativeFontInfo::SetWeight(wxFontWeight weight)
430 {
431 switch ( weight )
432 {
433 default:
434 wxFAIL_MSG( _T("unknown font weight") );
435 // fall through
436
437 case wxFONTWEIGHT_NORMAL:
438 lf.lfWeight = FW_NORMAL;
439 break;
440
441 case wxFONTWEIGHT_LIGHT:
442 lf.lfWeight = FW_LIGHT;
443 break;
444
445 case wxFONTWEIGHT_BOLD:
446 lf.lfWeight = FW_BOLD;
447 break;
448 }
449 }
450
451 void wxNativeFontInfo::SetUnderlined(bool underlined)
452 {
453 lf.lfUnderline = underlined;
454 }
455
456 void wxNativeFontInfo::SetFaceName(wxString facename)
457 {
458 wxStrncpy(lf.lfFaceName, facename, sizeof(lf.lfFaceName));
459 }
460
461 void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding)
462 {
463 wxNativeEncodingInfo info;
464 if ( !wxGetNativeFontEncoding(encoding, &info) )
465 {
466 // unsupported encoding, replace with the default
467 info.charset = ANSI_CHARSET;
468 }
469
470 lf.lfCharSet = info.charset;
471 }
472
473 bool wxNativeFontInfo::FromString(const wxString& s)
474 {
475 long l;
476
477 wxStringTokenizer tokenizer(s, _T(";"));
478
479 // first the version
480 wxString token = tokenizer.GetNextToken();
481 if ( token != _T('0') )
482 return FALSE;
483
484 token = tokenizer.GetNextToken();
485 if ( !token.ToLong(&l) )
486 return FALSE;
487 lf.lfHeight = l;
488
489 token = tokenizer.GetNextToken();
490 if ( !token.ToLong(&l) )
491 return FALSE;
492 lf.lfWidth = l;
493
494 token = tokenizer.GetNextToken();
495 if ( !token.ToLong(&l) )
496 return FALSE;
497 lf.lfEscapement = l;
498
499 token = tokenizer.GetNextToken();
500 if ( !token.ToLong(&l) )
501 return FALSE;
502 lf.lfOrientation = l;
503
504 token = tokenizer.GetNextToken();
505 if ( !token.ToLong(&l) )
506 return FALSE;
507 lf.lfWeight = l;
508
509 token = tokenizer.GetNextToken();
510 if ( !token.ToLong(&l) )
511 return FALSE;
512 lf.lfItalic = (BYTE)l;
513
514 token = tokenizer.GetNextToken();
515 if ( !token.ToLong(&l) )
516 return FALSE;
517 lf.lfUnderline = (BYTE)l;
518
519 token = tokenizer.GetNextToken();
520 if ( !token.ToLong(&l) )
521 return FALSE;
522 lf.lfStrikeOut = (BYTE)l;
523
524 token = tokenizer.GetNextToken();
525 if ( !token.ToLong(&l) )
526 return FALSE;
527 lf.lfCharSet = (BYTE)l;
528
529 token = tokenizer.GetNextToken();
530 if ( !token.ToLong(&l) )
531 return FALSE;
532 lf.lfOutPrecision = (BYTE)l;
533
534 token = tokenizer.GetNextToken();
535 if ( !token.ToLong(&l) )
536 return FALSE;
537 lf.lfClipPrecision = (BYTE)l;
538
539 token = tokenizer.GetNextToken();
540 if ( !token.ToLong(&l) )
541 return FALSE;
542 lf.lfQuality = (BYTE)l;
543
544 token = tokenizer.GetNextToken();
545 if ( !token.ToLong(&l) )
546 return FALSE;
547 lf.lfPitchAndFamily = (BYTE)l;
548
549 token = tokenizer.GetNextToken();
550 if(!token)
551 return FALSE;
552 wxStrcpy(lf.lfFaceName, token.c_str());
553
554 return TRUE;
555 }
556
557 wxString wxNativeFontInfo::ToString() const
558 {
559 wxString s;
560
561 s.Printf(_T("%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%s"),
562 0, // version, in case we want to change the format later
563 lf.lfHeight,
564 lf.lfWidth,
565 lf.lfEscapement,
566 lf.lfOrientation,
567 lf.lfWeight,
568 lf.lfItalic,
569 lf.lfUnderline,
570 lf.lfStrikeOut,
571 lf.lfCharSet,
572 lf.lfOutPrecision,
573 lf.lfClipPrecision,
574 lf.lfQuality,
575 lf.lfPitchAndFamily,
576 lf.lfFaceName);
577
578 return s;
579 }
580
581 // ----------------------------------------------------------------------------
582 // wxFont
583 // ----------------------------------------------------------------------------
584
585 void wxFont::Init()
586 {
587 }
588
589 bool wxFont::Create(const wxNativeFontInfo& info, WXHFONT hFont)
590 {
591 UnRef();
592
593 m_refData = new wxFontRefData(info, hFont);
594
595 RealizeResource();
596
597 return TRUE;
598 }
599
600 wxFont::wxFont(const wxString& fontdesc)
601 {
602 wxNativeFontInfo info;
603 if ( info.FromString(fontdesc) )
604 (void)Create(info);
605 }
606
607 /* Constructor for a font. Note that the real construction is done
608 * in wxDC::SetFont, when information is available about scaling etc.
609 */
610 bool wxFont::Create(int pointSize,
611 int family,
612 int style,
613 int weight,
614 bool underlined,
615 const wxString& faceName,
616 wxFontEncoding encoding)
617 {
618 UnRef();
619
620 // wxDEFAULT is a valid value for the font size too so we must treat it
621 // specially here (otherwise the size would be 70 == wxDEFAULT value)
622 if ( pointSize == wxDEFAULT )
623 {
624 pointSize = wxNORMAL_FONT->GetPointSize();
625 }
626
627 m_refData = new wxFontRefData(pointSize, family, style, weight,
628 underlined, faceName, encoding);
629
630 RealizeResource();
631
632 return TRUE;
633 }
634
635 wxFont::~wxFont()
636 {
637 }
638
639 // ----------------------------------------------------------------------------
640 // real implementation
641 // ----------------------------------------------------------------------------
642
643 bool wxFont::RealizeResource()
644 {
645 if ( GetResourceHandle() )
646 {
647 // VZ: the old code returned FALSE in this case, but it doesn't seem
648 // to make sense because the font _was_ created
649 return TRUE;
650 }
651
652 return M_FONTDATA->Alloc(this);
653 }
654
655 bool wxFont::FreeResource(bool WXUNUSED(force))
656 {
657 if ( GetResourceHandle() )
658 {
659 M_FONTDATA->Free();
660
661 return TRUE;
662 }
663
664 return FALSE;
665 }
666
667 WXHANDLE wxFont::GetResourceHandle()
668 {
669 return GetHFONT();
670 }
671
672 WXHFONT wxFont::GetHFONT() const
673 {
674 return M_FONTDATA ? M_FONTDATA->GetHFONT() : 0;
675 }
676
677 bool wxFont::IsFree() const
678 {
679 return M_FONTDATA && (M_FONTDATA->GetHFONT() == 0);
680 }
681
682 void wxFont::Unshare()
683 {
684 // Don't change shared data
685 if ( !m_refData )
686 {
687 m_refData = new wxFontRefData();
688 }
689 else
690 {
691 wxFontRefData* ref = new wxFontRefData(*M_FONTDATA);
692 UnRef();
693 m_refData = ref;
694 }
695 }
696
697 // ----------------------------------------------------------------------------
698 // change font attribute: we recreate font when doing it
699 // ----------------------------------------------------------------------------
700
701 void wxFont::SetPointSize(int pointSize)
702 {
703 Unshare();
704
705 M_FONTDATA->SetPointSize(pointSize);
706
707 RealizeResource();
708 }
709
710 void wxFont::SetFamily(int family)
711 {
712 Unshare();
713
714 M_FONTDATA->SetFamily(family);
715
716 RealizeResource();
717 }
718
719 void wxFont::SetStyle(int style)
720 {
721 Unshare();
722
723 M_FONTDATA->SetStyle(style);
724
725 RealizeResource();
726 }
727
728 void wxFont::SetWeight(int weight)
729 {
730 Unshare();
731
732 M_FONTDATA->SetWeight(weight);
733
734 RealizeResource();
735 }
736
737 void wxFont::SetFaceName(const wxString& faceName)
738 {
739 Unshare();
740
741 M_FONTDATA->SetFaceName(faceName);
742
743 RealizeResource();
744 }
745
746 void wxFont::SetUnderlined(bool underlined)
747 {
748 Unshare();
749
750 M_FONTDATA->SetUnderlined(underlined);
751
752 RealizeResource();
753 }
754
755 void wxFont::SetEncoding(wxFontEncoding encoding)
756 {
757 Unshare();
758
759 M_FONTDATA->SetEncoding(encoding);
760
761 RealizeResource();
762 }
763
764 void wxFont::SetNativeFontInfo(const wxNativeFontInfo& info)
765 {
766 Unshare();
767
768 FreeResource();
769
770 *M_FONTDATA = wxFontRefData(info);
771
772 RealizeResource();
773 }
774
775 // ----------------------------------------------------------------------------
776 // accessors
777 // ----------------------------------------------------------------------------
778
779 int wxFont::GetPointSize() const
780 {
781 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
782
783 return M_FONTDATA->GetPointSize();
784 }
785
786 int wxFont::GetFamily() const
787 {
788 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
789
790 return M_FONTDATA->GetFamily();
791 }
792
793 int wxFont::GetStyle() const
794 {
795 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
796
797 return M_FONTDATA->GetStyle();
798 }
799
800 int wxFont::GetWeight() const
801 {
802 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
803
804 return M_FONTDATA->GetWeight();
805 }
806
807 bool wxFont::GetUnderlined() const
808 {
809 wxCHECK_MSG( Ok(), FALSE, wxT("invalid font") );
810
811 return M_FONTDATA->GetUnderlined();
812 }
813
814 wxString wxFont::GetFaceName() const
815 {
816 wxCHECK_MSG( Ok(), wxT(""), wxT("invalid font") );
817
818 return M_FONTDATA->GetFaceName();
819 }
820
821 wxFontEncoding wxFont::GetEncoding() const
822 {
823 wxCHECK_MSG( Ok(), wxFONTENCODING_DEFAULT, wxT("invalid font") );
824
825 return M_FONTDATA->GetEncoding();
826 }
827
828 wxNativeFontInfo *wxFont::GetNativeFontInfo() const
829 {
830 if ( M_FONTDATA->HasNativeFontInfo() )
831 return new wxNativeFontInfo(M_FONTDATA->GetNativeFontInfo());
832
833 return 0;
834 }
835