]> git.saurik.com Git - wxWidgets.git/blob - src/msw/font.cpp
fixed serious bug in wxFont::operator== (ignored weight)
[wxWidgets.git] / src / msw / font.cpp
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
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 // the default font size in points
53 static const int wxDEFAULT_FONT_SIZE = 12;
54
55 // ----------------------------------------------------------------------------
56 // wxFontRefData - the internal description of the font
57 // ----------------------------------------------------------------------------
58
59 class WXDLLEXPORT wxFontRefData: public wxGDIRefData
60 {
61 friend class WXDLLEXPORT wxFont;
62
63 public:
64 wxFontRefData()
65 {
66 Init(wxDEFAULT_FONT_SIZE, wxDEFAULT, wxNORMAL, wxNORMAL, FALSE,
67 "", wxFONTENCODING_DEFAULT);
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 }
88
89 wxFontRefData(const wxNativeFontInfo& info, WXHFONT hFont = 0)
90 {
91 Init(info, hFont);
92 }
93
94 virtual ~wxFontRefData();
95
96 protected:
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
106 void Init(const wxNativeFontInfo& info, WXHFONT hFont = 0);
107
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;
125
126 // Native font info
127 wxNativeFontInfo m_nativeFontInfo;
128 bool m_nativeFontInfoOk;
129 };
130
131 // ============================================================================
132 // implementation
133 // ============================================================================
134
135 // ----------------------------------------------------------------------------
136 // wxFontRefData
137 // ----------------------------------------------------------------------------
138
139 void wxFontRefData::Init(int pointSize,
140 int family,
141 int style,
142 int weight,
143 bool underlined,
144 const wxString& faceName,
145 wxFontEncoding encoding)
146 {
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;
154 m_encoding = encoding;
155
156 m_fontId = 0;
157 m_temporary = FALSE;
158
159 m_hFont = 0;
160
161 m_nativeFontInfoOk = FALSE;
162 }
163
164 void wxFontRefData::Init(const wxNativeFontInfo& info, WXHFONT hFont)
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
222 int height = abs(info.lf.lfHeight);
223
224 // remember that 1pt = 1/72inch
225 const int ppInch = ::GetDeviceCaps(ScreenHDC(), LOGPIXELSY);
226 m_pointSize = (int) (((72.0*((double)height))/(double) ppInch) + 0.5);
227
228 m_encoding = wxGetFontEncFromCharSet(info.lf.lfCharSet);
229
230 m_fontId = 0;
231 m_temporary = FALSE;
232
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;
238
239 m_nativeFontInfoOk = TRUE;
240 m_nativeFontInfo = info;
241 }
242
243 wxFontRefData::~wxFontRefData()
244 {
245 if ( m_hFont )
246 {
247 if ( !::DeleteObject((HFONT) m_hFont) )
248 {
249 wxLogLastError(wxT("DeleteObject(font)"));
250 }
251 }
252 }
253
254
255 // ----------------------------------------------------------------------------
256 // wxNativeFontInfo
257 // ----------------------------------------------------------------------------
258
259 bool 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;
298 lf.lfItalic = (BYTE)l;
299
300 token = tokenizer.GetNextToken();
301 if ( !token.ToLong(&l) )
302 return FALSE;
303 lf.lfUnderline = (BYTE)l;
304
305 token = tokenizer.GetNextToken();
306 if ( !token.ToLong(&l) )
307 return FALSE;
308 lf.lfStrikeOut = (BYTE)l;
309
310 token = tokenizer.GetNextToken();
311 if ( !token.ToLong(&l) )
312 return FALSE;
313 lf.lfCharSet = (BYTE)l;
314
315 token = tokenizer.GetNextToken();
316 if ( !token.ToLong(&l) )
317 return FALSE;
318 lf.lfOutPrecision = (BYTE)l;
319
320 token = tokenizer.GetNextToken();
321 if ( !token.ToLong(&l) )
322 return FALSE;
323 lf.lfClipPrecision = (BYTE)l;
324
325 token = tokenizer.GetNextToken();
326 if ( !token.ToLong(&l) )
327 return FALSE;
328 lf.lfQuality = (BYTE)l;
329
330 token = tokenizer.GetNextToken();
331 if ( !token.ToLong(&l) )
332 return FALSE;
333 lf.lfPitchAndFamily = (BYTE)l;
334
335 token = tokenizer.GetNextToken();
336 if(!token)
337 return FALSE;
338 wxStrcpy(lf.lfFaceName, token.c_str());
339
340 return TRUE;
341 }
342
343 wxString 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
367 // ----------------------------------------------------------------------------
368 // wxFont
369 // ----------------------------------------------------------------------------
370
371 void wxFont::Init()
372 {
373 if ( wxTheFontList )
374 wxTheFontList->Append(this);
375 }
376
377 bool wxFont::Create(const wxNativeFontInfo& info, WXHFONT hFont)
378 {
379 UnRef();
380
381 m_refData = new wxFontRefData(info, hFont);
382
383 RealizeResource();
384
385 return TRUE;
386 }
387
388 wxFont::wxFont(const wxString& fontdesc)
389 {
390 wxNativeFontInfo info;
391 if ( info.FromString(fontdesc) )
392 (void)Create(info);
393 }
394
395 /* Constructor for a font. Note that the real construction is done
396 * in wxDC::SetFont, when information is available about scaling etc.
397 */
398 bool wxFont::Create(int pointSize,
399 int family,
400 int style,
401 int weight,
402 bool underlined,
403 const wxString& faceName,
404 wxFontEncoding encoding)
405 {
406 UnRef();
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
413 m_refData = new wxFontRefData(pointSize, family, style, weight,
414 underlined, faceName, encoding);
415
416 RealizeResource();
417
418 return TRUE;
419 }
420
421 wxFont::~wxFont()
422 {
423 if ( wxTheFontList )
424 wxTheFontList->DeleteObject(this);
425 }
426
427 // ----------------------------------------------------------------------------
428 // real implementation
429 // ----------------------------------------------------------------------------
430
431 bool wxFont::RealizeResource()
432 {
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
437 return TRUE;
438 }
439
440 if(!M_FONTDATA->m_nativeFontInfoOk)
441 {
442 wxFillLogFont(&M_FONTDATA->m_nativeFontInfo.lf, this);
443 M_FONTDATA->m_nativeFontInfoOk = TRUE;
444 }
445
446 M_FONTDATA->m_hFont = (WXHFONT)::CreateFontIndirect(&M_FONTDATA->m_nativeFontInfo.lf);
447 M_FONTDATA->m_faceName = M_FONTDATA->m_nativeFontInfo.lf.lfFaceName;
448 if ( !M_FONTDATA->m_hFont )
449 {
450 wxLogLastError(wxT("CreateFont"));
451
452 return FALSE;
453 }
454
455 return TRUE;
456 }
457
458 bool wxFont::FreeResource(bool WXUNUSED(force))
459 {
460 if ( GetResourceHandle() )
461 {
462 if ( !::DeleteObject((HFONT) M_FONTDATA->m_hFont) )
463 {
464 wxLogLastError(wxT("DeleteObject(font)"));
465 }
466
467 M_FONTDATA->m_hFont = 0;
468
469 return TRUE;
470 }
471 return FALSE;
472 }
473
474 WXHANDLE wxFont::GetResourceHandle()
475 {
476 return GetHFONT();
477 }
478
479 WXHFONT wxFont::GetHFONT() const
480 {
481 if ( !M_FONTDATA )
482 return 0;
483 else
484 return (WXHANDLE)M_FONTDATA->m_hFont;
485 }
486
487 bool wxFont::IsFree() const
488 {
489 return (M_FONTDATA && (M_FONTDATA->m_hFont == 0));
490 }
491
492 void wxFont::Unshare()
493 {
494 // Don't change shared data
495 if ( !m_refData )
496 {
497 m_refData = new wxFontRefData();
498 }
499 else
500 {
501 wxFontRefData* ref = new wxFontRefData(*M_FONTDATA);
502 UnRef();
503 m_refData = ref;
504 }
505 }
506
507 // ----------------------------------------------------------------------------
508 // change font attribute: we recreate font when doing it
509 // ----------------------------------------------------------------------------
510
511 void wxFont::SetPointSize(int pointSize)
512 {
513 Unshare();
514
515 M_FONTDATA->m_pointSize = pointSize;
516 M_FONTDATA->m_nativeFontInfoOk = FALSE;
517
518 RealizeResource();
519 }
520
521 void wxFont::SetFamily(int family)
522 {
523 Unshare();
524
525 M_FONTDATA->m_family = family;
526 M_FONTDATA->m_nativeFontInfoOk = FALSE;
527
528 RealizeResource();
529 }
530
531 void wxFont::SetStyle(int style)
532 {
533 Unshare();
534
535 M_FONTDATA->m_style = style;
536 M_FONTDATA->m_nativeFontInfoOk = FALSE;
537
538 RealizeResource();
539 }
540
541 void wxFont::SetWeight(int weight)
542 {
543 Unshare();
544
545 M_FONTDATA->m_weight = weight;
546 M_FONTDATA->m_nativeFontInfoOk = FALSE;
547
548 RealizeResource();
549 }
550
551 void wxFont::SetFaceName(const wxString& faceName)
552 {
553 Unshare();
554
555 M_FONTDATA->m_faceName = faceName;
556 M_FONTDATA->m_nativeFontInfoOk = FALSE;
557
558 RealizeResource();
559 }
560
561 void wxFont::SetUnderlined(bool underlined)
562 {
563 Unshare();
564
565 M_FONTDATA->m_underlined = underlined;
566 M_FONTDATA->m_nativeFontInfoOk = FALSE;
567
568 RealizeResource();
569 }
570
571 void wxFont::SetEncoding(wxFontEncoding encoding)
572 {
573 Unshare();
574
575 M_FONTDATA->m_encoding = encoding;
576 M_FONTDATA->m_nativeFontInfoOk = FALSE;
577
578 RealizeResource();
579 }
580
581 void wxFont::SetNativeFontInfo(const wxNativeFontInfo& info)
582 {
583 Unshare();
584
585 FreeResource();
586
587 M_FONTDATA->Init(info);
588
589 RealizeResource();
590 }
591
592 // ----------------------------------------------------------------------------
593 // accessors
594 // ----------------------------------------------------------------------------
595
596 int wxFont::GetPointSize() const
597 {
598 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
599
600 return M_FONTDATA->m_pointSize;
601 }
602
603 int wxFont::GetFamily() const
604 {
605 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
606
607 return M_FONTDATA->m_family;
608 }
609
610 int wxFont::GetFontId() const
611 {
612 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
613
614 return M_FONTDATA->m_fontId;
615 }
616
617 int wxFont::GetStyle() const
618 {
619 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
620
621 return M_FONTDATA->m_style;
622 }
623
624 int wxFont::GetWeight() const
625 {
626 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
627
628 return M_FONTDATA->m_weight;
629 }
630
631 bool wxFont::GetUnderlined() const
632 {
633 wxCHECK_MSG( Ok(), FALSE, wxT("invalid font") );
634
635 return M_FONTDATA->m_underlined;
636 }
637
638 wxString wxFont::GetFaceName() const
639 {
640 wxCHECK_MSG( Ok(), wxT(""), wxT("invalid font") );
641
642 return M_FONTDATA->m_faceName;
643 }
644
645 wxFontEncoding wxFont::GetEncoding() const
646 {
647 wxCHECK_MSG( Ok(), wxFONTENCODING_DEFAULT, wxT("invalid font") );
648
649 return M_FONTDATA->m_encoding;
650 }
651
652 wxNativeFontInfo *wxFont::GetNativeFontInfo() const
653 {
654 if( M_FONTDATA->m_nativeFontInfoOk )
655 return new wxNativeFontInfo(M_FONTDATA->m_nativeFontInfo);
656
657 return 0;
658 }
659