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