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