]> git.saurik.com Git - wxWidgets.git/blob - src/msw/font.cpp
OS/2 fix in setdrive.
[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 int height = abs(info.lf.lfHeight);
222
223 // remember that 1pt = 1/72inch
224 const int ppInch = ::GetDeviceCaps(ScreenHDC(), LOGPIXELSY);
225 m_pointSize = (int) (((72.0*((double)height))/(double) ppInch) + 0.5);
226
227 m_encoding = wxGetFontEncFromCharSet(info.lf.lfCharSet);
228
229 m_fontId = 0;
230 m_temporary = FALSE;
231
232 m_hFont = 0;
233
234 m_nativeFontInfoOk = TRUE;
235 m_nativeFontInfo = info;
236 }
237
238 wxFontRefData::~wxFontRefData()
239 {
240 if ( m_hFont )
241 {
242 if ( !::DeleteObject((HFONT) m_hFont) )
243 {
244 wxLogLastError(wxT("DeleteObject(font)"));
245 }
246 }
247 }
248
249
250 // ----------------------------------------------------------------------------
251 // wxNativeFontInfo
252 // ----------------------------------------------------------------------------
253
254 bool wxNativeFontInfo::FromString(const wxString& s)
255 {
256 long l;
257
258 wxStringTokenizer tokenizer(s, _T(";"));
259
260 wxString token = tokenizer.GetNextToken();
261 //
262 // Ignore the version for now
263 //
264
265 token = tokenizer.GetNextToken();
266 if ( !token.ToLong(&l) )
267 return FALSE;
268 lf.lfHeight = l;
269
270 token = tokenizer.GetNextToken();
271 if ( !token.ToLong(&l) )
272 return FALSE;
273 lf.lfWidth = l;
274
275 token = tokenizer.GetNextToken();
276 if ( !token.ToLong(&l) )
277 return FALSE;
278 lf.lfEscapement = l;
279
280 token = tokenizer.GetNextToken();
281 if ( !token.ToLong(&l) )
282 return FALSE;
283 lf.lfOrientation = l;
284
285 token = tokenizer.GetNextToken();
286 if ( !token.ToLong(&l) )
287 return FALSE;
288 lf.lfWeight = l;
289
290 token = tokenizer.GetNextToken();
291 if ( !token.ToLong(&l) )
292 return FALSE;
293 lf.lfItalic = (BYTE)l;
294
295 token = tokenizer.GetNextToken();
296 if ( !token.ToLong(&l) )
297 return FALSE;
298 lf.lfUnderline = (BYTE)l;
299
300 token = tokenizer.GetNextToken();
301 if ( !token.ToLong(&l) )
302 return FALSE;
303 lf.lfStrikeOut = (BYTE)l;
304
305 token = tokenizer.GetNextToken();
306 if ( !token.ToLong(&l) )
307 return FALSE;
308 lf.lfCharSet = (BYTE)l;
309
310 token = tokenizer.GetNextToken();
311 if ( !token.ToLong(&l) )
312 return FALSE;
313 lf.lfOutPrecision = (BYTE)l;
314
315 token = tokenizer.GetNextToken();
316 if ( !token.ToLong(&l) )
317 return FALSE;
318 lf.lfClipPrecision = (BYTE)l;
319
320 token = tokenizer.GetNextToken();
321 if ( !token.ToLong(&l) )
322 return FALSE;
323 lf.lfQuality = (BYTE)l;
324
325 token = tokenizer.GetNextToken();
326 if ( !token.ToLong(&l) )
327 return FALSE;
328 lf.lfPitchAndFamily = (BYTE)l;
329
330 token = tokenizer.GetNextToken();
331 if(!token)
332 return FALSE;
333 wxStrcpy(lf.lfFaceName, token.c_str());
334
335 return TRUE;
336 }
337
338 wxString wxNativeFontInfo::ToString() const
339 {
340 wxString s;
341
342 s.Printf(_T("%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%s"),
343 0, // version, in case we want to change the format later
344 lf.lfHeight,
345 lf.lfWidth,
346 lf.lfEscapement,
347 lf.lfOrientation,
348 lf.lfWeight,
349 lf.lfItalic,
350 lf.lfUnderline,
351 lf.lfStrikeOut,
352 lf.lfCharSet,
353 lf.lfOutPrecision,
354 lf.lfClipPrecision,
355 lf.lfQuality,
356 lf.lfPitchAndFamily,
357 lf.lfFaceName);
358
359 return s;
360 }
361
362 // ----------------------------------------------------------------------------
363 // wxFont
364 // ----------------------------------------------------------------------------
365
366 void wxFont::Init()
367 {
368 if ( wxTheFontList )
369 wxTheFontList->Append(this);
370 }
371
372 bool wxFont::Create(const wxNativeFontInfo& info)
373 {
374 UnRef();
375
376 m_refData = new wxFontRefData(info);
377
378 RealizeResource();
379
380 return TRUE;
381 }
382
383 wxFont::wxFont(const wxString& fontdesc)
384 {
385 wxNativeFontInfo info;
386 if ( info.FromString(fontdesc) )
387 (void)Create(info);
388 }
389
390 /* Constructor for a font. Note that the real construction is done
391 * in wxDC::SetFont, when information is available about scaling etc.
392 */
393 bool wxFont::Create(int pointSize,
394 int family,
395 int style,
396 int weight,
397 bool underlined,
398 const wxString& faceName,
399 wxFontEncoding encoding)
400 {
401 UnRef();
402
403 // wxDEFAULT is a valid value for the font size too so we must treat it
404 // specially here (otherwise the size would be 70 == wxDEFAULT value)
405 if ( pointSize == wxDEFAULT )
406 pointSize = wxDEFAULT_FONT_SIZE;
407
408 m_refData = new wxFontRefData(pointSize, family, style, weight,
409 underlined, faceName, encoding);
410
411 RealizeResource();
412
413 return TRUE;
414 }
415
416 wxFont::~wxFont()
417 {
418 if ( wxTheFontList )
419 wxTheFontList->DeleteObject(this);
420 }
421
422 // ----------------------------------------------------------------------------
423 // real implementation
424 // ----------------------------------------------------------------------------
425
426 bool wxFont::RealizeResource()
427 {
428 if ( GetResourceHandle() )
429 {
430 // VZ: the old code returned FALSE in this case, but it doesn't seem
431 // to make sense because the font _was_ created
432 return TRUE;
433 }
434
435 if(!M_FONTDATA->m_nativeFontInfoOk)
436 {
437 wxFillLogFont(&M_FONTDATA->m_nativeFontInfo.lf, this);
438 M_FONTDATA->m_nativeFontInfoOk = TRUE;
439 }
440
441 M_FONTDATA->m_hFont = (WXHFONT)::CreateFontIndirect(&M_FONTDATA->m_nativeFontInfo.lf);
442 M_FONTDATA->m_faceName = M_FONTDATA->m_nativeFontInfo.lf.lfFaceName;
443 if ( !M_FONTDATA->m_hFont )
444 {
445 wxLogLastError(wxT("CreateFont"));
446
447 return FALSE;
448 }
449
450 return TRUE;
451 }
452
453 bool wxFont::FreeResource(bool WXUNUSED(force))
454 {
455 if ( GetResourceHandle() )
456 {
457 if ( !::DeleteObject((HFONT) M_FONTDATA->m_hFont) )
458 {
459 wxLogLastError(wxT("DeleteObject(font)"));
460 }
461
462 M_FONTDATA->m_hFont = 0;
463
464 return TRUE;
465 }
466 return FALSE;
467 }
468
469 WXHANDLE wxFont::GetResourceHandle()
470 {
471 return GetHFONT();
472 }
473
474 WXHFONT wxFont::GetHFONT() const
475 {
476 if ( !M_FONTDATA )
477 return 0;
478 else
479 return (WXHANDLE)M_FONTDATA->m_hFont;
480 }
481
482 bool wxFont::IsFree() const
483 {
484 return (M_FONTDATA && (M_FONTDATA->m_hFont == 0));
485 }
486
487 void wxFont::Unshare()
488 {
489 // Don't change shared data
490 if ( !m_refData )
491 {
492 m_refData = new wxFontRefData();
493 }
494 else
495 {
496 wxFontRefData* ref = new wxFontRefData(*M_FONTDATA);
497 UnRef();
498 m_refData = ref;
499 }
500 }
501
502 // ----------------------------------------------------------------------------
503 // change font attribute: we recreate font when doing it
504 // ----------------------------------------------------------------------------
505
506 void wxFont::SetPointSize(int pointSize)
507 {
508 Unshare();
509
510 M_FONTDATA->m_pointSize = pointSize;
511 M_FONTDATA->m_nativeFontInfoOk = FALSE;
512
513 RealizeResource();
514 }
515
516 void wxFont::SetFamily(int family)
517 {
518 Unshare();
519
520 M_FONTDATA->m_family = family;
521 M_FONTDATA->m_nativeFontInfoOk = FALSE;
522
523 RealizeResource();
524 }
525
526 void wxFont::SetStyle(int style)
527 {
528 Unshare();
529
530 M_FONTDATA->m_style = style;
531 M_FONTDATA->m_nativeFontInfoOk = FALSE;
532
533 RealizeResource();
534 }
535
536 void wxFont::SetWeight(int weight)
537 {
538 Unshare();
539
540 M_FONTDATA->m_weight = weight;
541 M_FONTDATA->m_nativeFontInfoOk = FALSE;
542
543 RealizeResource();
544 }
545
546 void wxFont::SetFaceName(const wxString& faceName)
547 {
548 Unshare();
549
550 M_FONTDATA->m_faceName = faceName;
551 M_FONTDATA->m_nativeFontInfoOk = FALSE;
552
553 RealizeResource();
554 }
555
556 void wxFont::SetUnderlined(bool underlined)
557 {
558 Unshare();
559
560 M_FONTDATA->m_underlined = underlined;
561 M_FONTDATA->m_nativeFontInfoOk = FALSE;
562
563 RealizeResource();
564 }
565
566 void wxFont::SetEncoding(wxFontEncoding encoding)
567 {
568 Unshare();
569
570 M_FONTDATA->m_encoding = encoding;
571 M_FONTDATA->m_nativeFontInfoOk = FALSE;
572
573 RealizeResource();
574 }
575
576 void wxFont::SetNativeFontInfo(const wxNativeFontInfo& info)
577 {
578 Unshare();
579
580 FreeResource();
581
582 M_FONTDATA->Init(info);
583
584 RealizeResource();
585 }
586
587 // ----------------------------------------------------------------------------
588 // accessors
589 // ----------------------------------------------------------------------------
590
591 int wxFont::GetPointSize() const
592 {
593 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
594
595 return M_FONTDATA->m_pointSize;
596 }
597
598 int wxFont::GetFamily() const
599 {
600 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
601
602 return M_FONTDATA->m_family;
603 }
604
605 int wxFont::GetFontId() const
606 {
607 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
608
609 return M_FONTDATA->m_fontId;
610 }
611
612 int wxFont::GetStyle() const
613 {
614 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
615
616 return M_FONTDATA->m_style;
617 }
618
619 int wxFont::GetWeight() const
620 {
621 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
622
623 return M_FONTDATA->m_weight;
624 }
625
626 bool wxFont::GetUnderlined() const
627 {
628 wxCHECK_MSG( Ok(), FALSE, wxT("invalid font") );
629
630 return M_FONTDATA->m_underlined;
631 }
632
633 wxString wxFont::GetFaceName() const
634 {
635 wxCHECK_MSG( Ok(), wxT(""), wxT("invalid font") );
636
637 return M_FONTDATA->m_faceName;
638 }
639
640 wxFontEncoding wxFont::GetEncoding() const
641 {
642 wxCHECK_MSG( Ok(), wxFONTENCODING_DEFAULT, wxT("invalid font") );
643
644 return M_FONTDATA->m_encoding;
645 }
646
647 wxNativeFontInfo *wxFont::GetNativeFontInfo() const
648 {
649 if( M_FONTDATA->m_nativeFontInfoOk )
650 return new wxNativeFontInfo(M_FONTDATA->m_nativeFontInfo);
651
652 return 0;
653 }
654