1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/qt/font.cpp
3 // Author: Peter Most, Mariano Reingart, Javier Torres
4 // Copyright: (c) 2009 wxWidgets dev team
5 // Licence: wxWindows licence
6 /////////////////////////////////////////////////////////////////////////////
7
8 // For compilers that support precompilation, includes "wx.h".
9 #include "wx/wxprec.h"
10
11
12 #include <QtGui/QFont>
13 #include <QtGui/QFontInfo>
14
15 #include "wx/font.h"
16 #include "wx/fontutil.h"
17 #include "wx/qt/private/utils.h"
18 #include "wx/qt/private/converter.h"
19
20 // Older versions of QT don't define all the QFont::Weight enum values, so just
21 // do it ourselves here for all case instead.
22 #if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0))
23 #define wxQFontEnumOrInt(a, b) a
24 #else
25 #define wxQFontEnumOrInt(a, b) b
26 #endif
27
28 enum
29 {
30 wxQFont_Thin = wxQFontEnumOrInt( QFont::Thin, 0 ),
31 wxQFont_ExtraLight = wxQFontEnumOrInt( QFont::ExtraLight, 12 ),
32 wxQFont_Light = QFont::Light,
33 wxQFont_Normal = QFont::Normal,
34 wxQFont_Medium = wxQFontEnumOrInt( QFont::Medium, 57 ),
35 wxQFont_DemiBold = QFont::DemiBold,
36 wxQFont_Bold = QFont::Bold,
37 wxQFont_ExtraBold = wxQFontEnumOrInt( QFont::ExtraBold, 81 ),
38 wxQFont_Black = QFont::Black
39 };
40
ConvertFontFamily(wxFontFamily family)41 static QFont::StyleHint ConvertFontFamily(wxFontFamily family)
42 {
43 switch (family)
44 {
45 case wxFONTFAMILY_DEFAULT:
46 return QFont::AnyStyle;
47
48 case wxFONTFAMILY_DECORATIVE:
49 return QFont::Decorative;
50
51 case wxFONTFAMILY_ROMAN:
52 return QFont::Serif;
53
54 case wxFONTFAMILY_SCRIPT:
55 return QFont::Decorative;
56
57 case wxFONTFAMILY_SWISS:
58 return QFont::SansSerif;
59
60 case wxFONTFAMILY_MODERN:
61 return QFont::TypeWriter;
62
63 case wxFONTFAMILY_TELETYPE:
64 return QFont::TypeWriter;
65
66 case wxFONTFAMILY_MAX:
67 wxFAIL_MSG( "Invalid font family value" );
68 break;
69 }
70 return QFont::AnyStyle;
71 }
72
73 // Helper of ConvertFontWeight() and GetNumericWeight(): if a value lies in
74 // ]fromMin, fromMax] interval, then map it to [toMin, toMax] interval linearly
75 // and return true, otherwise return false and don't modify it.
TryToMap(int & x,int fromMin,int fromMax,int toMin,int toMax)76 static bool TryToMap(int& x, int fromMin, int fromMax, int toMin, int toMax)
77 {
78 if ( x > fromMin && x <= fromMax )
79 {
80 x = (toMin*(fromMax - x) + toMax*(x - fromMin))/(fromMax - fromMin);
81
82 return true;
83 }
84
85 return false;
86 }
87
ConvertFontWeight(int w)88 static int ConvertFontWeight(int w)
89 {
90 // Note that wxQFont_Thin is 0, so we can't have anything lighter than it.
91 if ( TryToMap(w, wxFONTWEIGHT_INVALID, wxFONTWEIGHT_THIN,
92 wxQFont_Thin, wxQFont_Thin) ||
93 TryToMap(w, wxFONTWEIGHT_THIN, wxFONTWEIGHT_EXTRALIGHT,
94 wxQFont_Thin, wxQFont_ExtraLight) ||
95 TryToMap(w, wxFONTWEIGHT_EXTRALIGHT, wxFONTWEIGHT_LIGHT,
96 wxQFont_ExtraLight, wxQFont_Light) ||
97 TryToMap(w, wxFONTWEIGHT_LIGHT, wxFONTWEIGHT_NORMAL,
98 wxQFont_Light, wxQFont_Normal) ||
99 TryToMap(w, wxFONTWEIGHT_NORMAL, wxFONTWEIGHT_MEDIUM,
100 wxQFont_Normal, wxQFont_Medium) ||
101 TryToMap(w, wxFONTWEIGHT_MEDIUM, wxFONTWEIGHT_SEMIBOLD,
102 wxQFont_Medium, wxQFont_DemiBold) ||
103 TryToMap(w, wxFONTWEIGHT_SEMIBOLD, wxFONTWEIGHT_BOLD,
104 wxQFont_DemiBold, wxQFont_Bold) ||
105 TryToMap(w, wxFONTWEIGHT_BOLD, wxFONTWEIGHT_EXTRABOLD,
106 wxQFont_Bold, wxQFont_ExtraBold) ||
107 TryToMap(w, wxFONTWEIGHT_EXTRABOLD, wxFONTWEIGHT_HEAVY,
108 wxQFont_ExtraBold, wxQFont_Black) ||
109 TryToMap(w, wxFONTWEIGHT_HEAVY, wxFONTWEIGHT_EXTRAHEAVY,
110 wxQFont_Black, 99) )
111 {
112 return w;
113 }
114
115 wxFAIL_MSG("invalid wxFont weight");
116
117 return wxQFont_Normal;
118 }
119
120 class wxFontRefData: public wxGDIRefData
121 {
122 public:
wxFontRefData()123 wxFontRefData() {}
124
wxFontRefData(const wxFontInfo & info)125 wxFontRefData(const wxFontInfo& info)
126 {
127 if ( info.HasFaceName() )
128 m_nativeFontInfo.SetFaceName(info.GetFaceName());
129 else
130 m_nativeFontInfo.SetFamily(info.GetFamily());
131
132 if ( info.IsUsingSizeInPixels() )
133 m_nativeFontInfo.SetPixelSize(info.GetPixelSize());
134 else
135 m_nativeFontInfo.SetSizeOrDefault(info.GetFractionalPointSize());
136
137 m_nativeFontInfo.SetStyle(info.GetStyle());
138 m_nativeFontInfo.SetWeight(info.GetWeight());
139 m_nativeFontInfo.SetUnderlined(info.IsUnderlined());
140 m_nativeFontInfo.SetStrikethrough(info.IsStrikethrough());
141
142 }
143
wxFontRefData(const wxFontRefData & data)144 wxFontRefData( const wxFontRefData& data )
145 : wxGDIRefData()
146 {
147 m_nativeFontInfo.m_qtFont = data.m_nativeFontInfo.m_qtFont;
148 }
149
150 wxNativeFontInfo m_nativeFontInfo;
151 };
152
153 #define M_FONTDATA ((wxFontRefData *)m_refData)->m_nativeFontInfo
154
wxFont()155 wxFont::wxFont()
156 {
157 m_refData = new wxFontRefData();
158 }
159
wxFont(const wxFontInfo & info)160 wxFont::wxFont(const wxFontInfo& info)
161 {
162 m_refData = new wxFontRefData(info);
163 }
164
wxFont(const wxString & nativeFontInfoString)165 wxFont::wxFont(const wxString& nativeFontInfoString)
166 {
167 m_refData = new wxFontRefData();
168
169 QFont font;
170 font.fromString(wxQtConvertString( nativeFontInfoString ));
171 M_FONTDATA.m_qtFont = font;
172 }
173
wxFont(const wxNativeFontInfo & info)174 wxFont::wxFont(const wxNativeFontInfo& info)
175 {
176 m_refData = new wxFontRefData();
177
178 M_FONTDATA.m_qtFont = info.m_qtFont;
179 }
180
wxFont(const QFont & font)181 wxFont::wxFont(const QFont& font)
182 {
183 m_refData = new wxFontRefData();
184
185 M_FONTDATA.m_qtFont = font;
186 }
187
wxFont(int size,wxFontFamily family,wxFontStyle style,wxFontWeight weight,bool underlined,const wxString & face,wxFontEncoding encoding)188 wxFont::wxFont(int size,
189 wxFontFamily family,
190 wxFontStyle style,
191 wxFontWeight weight,
192 bool underlined,
193 const wxString& face,
194 wxFontEncoding encoding)
195 {
196 m_refData = new wxFontRefData();
197 Create(wxSize(0, size), family, style, weight, underlined, face, encoding);
198 }
199
wxFont(const wxSize & pixelSize,wxFontFamily family,wxFontStyle style,wxFontWeight weight,bool underlined,const wxString & face,wxFontEncoding encoding)200 wxFont::wxFont(const wxSize& pixelSize,
201 wxFontFamily family,
202 wxFontStyle style,
203 wxFontWeight weight,
204 bool underlined,
205 const wxString& face,
206 wxFontEncoding encoding)
207 {
208 Create(pixelSize, family, style, weight, underlined, face, encoding);
209 }
210
wxFont(int size,int family,int style,int weight,bool underlined,const wxString & face,wxFontEncoding encoding)211 wxFont::wxFont(int size,
212 int family,
213 int style,
214 int weight,
215 bool underlined,
216 const wxString& face,
217 wxFontEncoding encoding)
218 {
219 Create(wxSize(0, size), (wxFontFamily)family, (wxFontStyle)style, (wxFontWeight)weight, underlined, face, encoding);
220 }
221
222
Create(wxSize size,wxFontFamily family,wxFontStyle style,wxFontWeight weight,bool underlined,const wxString & face,wxFontEncoding encoding)223 bool wxFont::Create(wxSize size, wxFontFamily family, wxFontStyle style,
224 wxFontWeight weight, bool underlined, const wxString& face,
225 wxFontEncoding encoding )
226 {
227 UnRef();
228
229 m_refData = new wxFontRefData(InfoFromLegacyParams(size.GetHeight(), family,
230 style, weight, underlined,
231 face, encoding));
232
233 return true;
234 }
235
GetPointSize() const236 int wxFont::GetPointSize() const
237 {
238 return M_FONTDATA.wxNativeFontInfo::GetPointSize();
239 }
240
GetFractionalPointSize() const241 double wxFont::GetFractionalPointSize() const
242 {
243 return M_FONTDATA.GetFractionalPointSize();
244 }
245
GetPixelSize() const246 wxSize wxFont::GetPixelSize() const
247 {
248 return M_FONTDATA.GetPixelSize();
249 }
250
GetStyle() const251 wxFontStyle wxFont::GetStyle() const
252 {
253 return M_FONTDATA.GetStyle();
254 }
255
GetNumericWeight() const256 int wxFont::GetNumericWeight() const
257 {
258 return M_FONTDATA.GetNumericWeight();
259 }
260
GetUnderlined() const261 bool wxFont::GetUnderlined() const
262 {
263 return M_FONTDATA.GetUnderlined();
264 }
265
GetFaceName() const266 wxString wxFont::GetFaceName() const
267 {
268 return M_FONTDATA.GetFaceName();
269 }
270
GetEncoding() const271 wxFontEncoding wxFont::GetEncoding() const
272 {
273 return M_FONTDATA.GetEncoding();
274 }
275
GetNativeFontInfo() const276 const wxNativeFontInfo *wxFont::GetNativeFontInfo() const
277 {
278 return &M_FONTDATA;
279 }
280
GetStrikethrough() const281 bool wxFont::GetStrikethrough() const
282 {
283 return M_FONTDATA.GetStrikethrough();
284 }
285
286
SetFractionalPointSize(double pointSize)287 void wxFont::SetFractionalPointSize(double pointSize)
288 {
289 AllocExclusive();
290
291 M_FONTDATA.SetFractionalPointSize(pointSize);
292 }
293
SetPixelSize(const wxSize & pixelSize)294 void wxFont::SetPixelSize(const wxSize& pixelSize)
295 {
296 AllocExclusive();
297
298 M_FONTDATA.SetPixelSize(pixelSize);
299 }
300
SetFaceName(const wxString & facename)301 bool wxFont::SetFaceName(const wxString& facename)
302 {
303 AllocExclusive();
304
305 return M_FONTDATA.SetFaceName(facename);
306 }
307
SetFamily(wxFontFamily family)308 void wxFont::SetFamily( wxFontFamily family )
309 {
310 AllocExclusive();
311
312 M_FONTDATA.SetFamily(family);
313 }
314
SetStyle(wxFontStyle style)315 void wxFont::SetStyle( wxFontStyle style )
316 {
317 AllocExclusive();
318
319 M_FONTDATA.SetStyle(style);
320 }
321
SetNumericWeight(int weight)322 void wxFont::SetNumericWeight(int weight)
323 {
324 AllocExclusive();
325
326 M_FONTDATA.SetNumericWeight(weight);
327 }
328
SetUnderlined(bool underlined)329 void wxFont::SetUnderlined( bool underlined )
330 {
331 AllocExclusive();
332
333 M_FONTDATA.SetUnderlined(underlined);
334 }
335
SetStrikethrough(bool strikethrough)336 void wxFont::SetStrikethrough(bool strikethrough)
337 {
338 AllocExclusive();
339
340 M_FONTDATA.SetStrikethrough(strikethrough);
341 }
342
SetEncoding(wxFontEncoding encoding)343 void wxFont::SetEncoding(wxFontEncoding encoding)
344 {
345 AllocExclusive();
346
347 M_FONTDATA.SetEncoding(encoding);
348 }
349
DoSetNativeFontInfo(const wxNativeFontInfo & info)350 void wxFont::DoSetNativeFontInfo(const wxNativeFontInfo& info)
351 {
352 SetFractionalPointSize(info.GetPointSize());
353 SetFamily(info.GetFamily());
354 SetStyle(info.GetStyle());
355 SetNumericWeight(info.GetWeight());
356 SetUnderlined(info.GetUnderlined());
357 SetStrikethrough(info.GetStrikethrough());
358 SetFaceName(info.GetFaceName());
359 SetEncoding(info.GetEncoding());
360 }
361
CreateGDIRefData() const362 wxGDIRefData *wxFont::CreateGDIRefData() const
363 {
364 return new wxFontRefData;
365 }
366
CloneGDIRefData(const wxGDIRefData * data) const367 wxGDIRefData *wxFont::CloneGDIRefData(const wxGDIRefData *data) const
368 {
369 return new wxFontRefData(*(wxFontRefData *)data);
370 }
371
GetHandle() const372 QFont wxFont::GetHandle() const
373 {
374 return M_FONTDATA.m_qtFont;
375 }
376
DoGetFamily() const377 wxFontFamily wxFont::DoGetFamily() const
378 {
379 return M_FONTDATA.GetFamily();
380 }
381
382 // ----------------------------------------------------------------------------
383 // wxNativeFontInfo
384 // ----------------------------------------------------------------------------
385
Init()386 void wxNativeFontInfo::Init()
387 {
388 }
389
GetFractionalPointSize() const390 double wxNativeFontInfo::GetFractionalPointSize() const
391 {
392 return m_qtFont.pointSizeF();
393 }
394
GetPixelSize() const395 wxSize wxNativeFontInfo::GetPixelSize() const
396 {
397 return wxSize(0, m_qtFont.pixelSize());
398 }
399
GetStyle() const400 wxFontStyle wxNativeFontInfo::GetStyle() const
401 {
402 switch (m_qtFont.style())
403 {
404 case QFont::StyleNormal:
405 return wxFONTSTYLE_NORMAL;
406
407 case QFont::StyleItalic:
408 return wxFONTSTYLE_ITALIC;
409
410 case QFont::StyleOblique:
411 return wxFONTSTYLE_SLANT;
412 }
413 wxFAIL_MSG( "Invalid font style value" );
414 return wxFontStyle();
415 }
416
GetNumericWeight() const417 int wxNativeFontInfo::GetNumericWeight() const
418 {
419 int w = m_qtFont.weight();
420
421 // Special case of wxQFont_Thin == 0.
422 if ( w == wxQFont_Thin )
423 return wxFONTWEIGHT_THIN;
424
425 if ( TryToMap(w, wxQFont_Thin, wxQFont_ExtraLight,
426 wxFONTWEIGHT_THIN, wxFONTWEIGHT_EXTRALIGHT) ||
427 TryToMap(w, wxQFont_ExtraLight, wxQFont_Light,
428 wxFONTWEIGHT_EXTRALIGHT, wxFONTWEIGHT_LIGHT) ||
429 TryToMap(w, wxQFont_Light, wxQFont_Normal,
430 wxFONTWEIGHT_LIGHT, wxFONTWEIGHT_NORMAL) ||
431 TryToMap(w, wxQFont_Normal, wxQFont_Medium,
432 wxFONTWEIGHT_NORMAL, wxFONTWEIGHT_MEDIUM) ||
433 TryToMap(w, wxQFont_Medium, wxQFont_DemiBold,
434 wxFONTWEIGHT_MEDIUM, wxFONTWEIGHT_SEMIBOLD) ||
435 TryToMap(w, wxQFont_DemiBold, wxQFont_Bold,
436 wxFONTWEIGHT_SEMIBOLD, wxFONTWEIGHT_BOLD) ||
437 TryToMap(w, wxQFont_Bold, wxQFont_ExtraBold,
438 wxFONTWEIGHT_BOLD, wxFONTWEIGHT_EXTRABOLD) ||
439 TryToMap(w, wxQFont_ExtraBold, wxQFont_Black,
440 wxFONTWEIGHT_EXTRABOLD, wxFONTWEIGHT_HEAVY) ||
441 TryToMap(w, wxQFont_Black, 99,
442 wxFONTWEIGHT_HEAVY, wxFONTWEIGHT_EXTRAHEAVY) )
443 {
444 return w;
445 }
446
447 wxFAIL_MSG( "Invalid QFont weight" );
448
449 return wxFONTWEIGHT_NORMAL;
450 }
451
GetUnderlined() const452 bool wxNativeFontInfo::GetUnderlined() const
453 {
454 return m_qtFont.underline();
455 }
456
GetStrikethrough() const457 bool wxNativeFontInfo::GetStrikethrough() const
458 {
459 return m_qtFont.strikeOut();
460 }
461
GetFaceName() const462 wxString wxNativeFontInfo::GetFaceName() const
463 {
464 // use font info to get the matched face name (not the family given)
465 QFontInfo info = QFontInfo(m_qtFont);
466 return wxQtConvertString(info.family());
467 }
468
GetFamily() const469 wxFontFamily wxNativeFontInfo::GetFamily() const
470 {
471 switch (m_qtFont.styleHint())
472 {
473 case QFont::System:
474 case QFont::AnyStyle:
475 return wxFONTFAMILY_DEFAULT;
476
477 case QFont::Fantasy:
478 case QFont::Cursive:
479 case QFont::Decorative:
480 return wxFONTFAMILY_DECORATIVE;
481
482 case QFont::Serif:
483 return wxFONTFAMILY_ROMAN;
484
485 case QFont::SansSerif:
486 return wxFONTFAMILY_SWISS;
487
488 case QFont::Monospace:
489 case QFont::TypeWriter:
490 return wxFONTFAMILY_TELETYPE;
491
492 }
493 return wxFONTFAMILY_UNKNOWN;
494 }
495
GetEncoding() const496 wxFontEncoding wxNativeFontInfo::GetEncoding() const
497 {
498 return wxFONTENCODING_UTF8;
499 }
500
SetFractionalPointSize(double pointsize)501 void wxNativeFontInfo::SetFractionalPointSize(double pointsize)
502 {
503 m_qtFont.setPointSizeF(pointsize);
504 }
505
SetPixelSize(const wxSize & size)506 void wxNativeFontInfo::SetPixelSize(const wxSize& size)
507 {
508 m_qtFont.setPixelSize(size.GetHeight());
509 }
510
SetStyle(wxFontStyle style)511 void wxNativeFontInfo::SetStyle(wxFontStyle style)
512 {
513 QFont::Style qtStyle;
514
515 switch ( style )
516 {
517 case wxFONTSTYLE_ITALIC:
518 qtStyle = QFont::StyleItalic;
519 break;
520
521 case wxFONTSTYLE_NORMAL:
522 qtStyle = QFont::StyleNormal;
523 break;
524
525 case wxFONTSTYLE_SLANT:
526 qtStyle = QFont::StyleOblique;
527 break;
528
529 case wxFONTSTYLE_MAX:
530 wxFAIL_MSG("unknown font style");
531 return;
532 }
533
534 m_qtFont.setStyle(qtStyle);
535 }
536
SetNumericWeight(int weight)537 void wxNativeFontInfo::SetNumericWeight(int weight)
538 {
539 m_qtFont.setWeight(ConvertFontWeight(weight));
540 }
541
SetUnderlined(bool underlined)542 void wxNativeFontInfo::SetUnderlined(bool underlined)
543 {
544 m_qtFont.setUnderline(underlined);
545 }
546
SetStrikethrough(bool strikethrough)547 void wxNativeFontInfo::SetStrikethrough(bool strikethrough)
548 {
549 m_qtFont.setStrikeOut(strikethrough);
550 }
551
SetFaceName(const wxString & facename)552 bool wxNativeFontInfo::SetFaceName(const wxString& facename)
553 {
554 m_qtFont.setFamily(wxQtConvertString(facename));
555 // Qt uses a "font matching algorithm" so the font will be always valid
556 return true;
557 }
558
SetFamily(wxFontFamily family)559 void wxNativeFontInfo::SetFamily(wxFontFamily family)
560 {
561 m_qtFont.setStyleHint(ConvertFontFamily(family));
562 // reset the face name to force qt to choose a new font
563 m_qtFont.setFamily(m_qtFont.defaultFamily());
564 }
565
SetEncoding(wxFontEncoding WXUNUSED (encoding))566 void wxNativeFontInfo::SetEncoding(wxFontEncoding WXUNUSED(encoding))
567 {
568 wxMISSING_IMPLEMENTATION( __FUNCTION__ );
569 }
570
FromString(const wxString & s)571 bool wxNativeFontInfo::FromString(const wxString& s)
572 {
573 return m_qtFont.fromString( wxQtConvertString( s ) );
574 }
575
ToString() const576 wxString wxNativeFontInfo::ToString() const
577 {
578 return wxQtConvertString( m_qtFont.toString() );
579 }
580
FromUserString(const wxString & s)581 bool wxNativeFontInfo::FromUserString(const wxString& s)
582 {
583 return FromString(s);
584 }
585
ToUserString() const586 wxString wxNativeFontInfo::ToUserString() const
587 {
588 return ToString();
589 }
590