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