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